diff --git a/.gitignore b/.gitignore index b0db77a36..e3479758d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +.*.swp /env /dl /.config diff --git a/Config.in b/Config.in index 2ec025579..1f689c066 100644 --- a/Config.in +++ b/Config.in @@ -25,8 +25,6 @@ menu "Target Images" depends TARGET_ROOTFS_INITRAMFS depends !LINUX_2_6_21 depends !LINUX_2_6_25 - depends !LINUX_2_6_27 - depends !LINUX_2_6_28 default TARGET_INITRAMFS_COMPRESSION_LZMA if TARGET_ar71xx default TARGET_INITRAMFS_COMPRESSION_NONE help @@ -93,7 +91,7 @@ menu "Target Images" config TARGET_ROOTFS_UBIFS bool "ubifs" default y if USES_UBIFS - depends !TARGET_ROOTFS_INITRAMFS + depends !TARGET_ROOTFS_INITRAMFS && USES_UBIFS help Build a ubifs root filesystem @@ -167,6 +165,7 @@ choice config USE_SSTRIP bool "sstrip" + depends !DEBUG depends !USE_GLIBC depends !USE_EGLIBC help @@ -197,7 +196,7 @@ config DEBUG prompt "Compile packages with debugging info" default n help - Disables stripping and adds -g3 to the CFLAGS + Adds -g3 to the CFLAGS config DEBUG_DIR bool "Install debugging binaries into a staging directory" diff --git a/feeds.conf.default b/feeds.conf.default index 305ad149f..d7afeeb48 100644 --- a/feeds.conf.default +++ b/feeds.conf.default @@ -6,3 +6,4 @@ src-svn efl svn://svn.openwrt.org/openwrt/feeds/efl src-svn desktop svn://svn.openwrt.org/openwrt/feeds/desktop src-svn xfce svn://svn.openwrt.org/openwrt/feeds/xfce src-git qipackages git://projects.qi-hardware.com/openwrt-packages.git +#src-link custom /usr/src/openwrt/custom-feed diff --git a/include/host-build.mk b/include/host-build.mk index 8eb49c8f4..6324276a7 100644 --- a/include/host-build.mk +++ b/include/host-build.mk @@ -130,17 +130,8 @@ ifndef DUMP touch $$@ $(call Host/Exports,$(HOST_STAMP_BUILT)) - $(HOST_STAMP_BUILT): $(HOST_STAMP_CONFIGURED) - $(call Host/Compile) - touch $$@ - - $(HOST_STAMP_INSTALLED): $(HOST_STAMP_BUILT) - $(call Host/Install) - mkdir -p $$(shell dirname $$@) - touch $$@ - ifdef Host/Install - host-install: $(HOST_STAMP_INSTALLED) + host-install: $(if $(STAMP_BUILT),$(HOST_STAMP_BUILT),$(HOST_STAMP_INSTALLED)) endif ifndef STAMP_BUILT @@ -149,8 +140,20 @@ ifndef DUMP install: host-install clean: host-clean update: host-update + + $(HOST_STAMP_BUILT): $(HOST_STAMP_CONFIGURED) + $(call Host/Compile) + touch $$@ + + $(HOST_STAMP_INSTALLED): $(HOST_STAMP_BUILT) + $(call Host/Install) + mkdir -p $$(shell dirname $$@) + touch $$@ else - host-compile: $(HOST_STAMP_INSTALLED) + $(HOST_STAMP_BUILT): $(HOST_STAMP_CONFIGURED) + $(call Host/Compile) + $(call Host/Install) + touch $$@ endif host-prepare: $(HOST_STAMP_PREPARED) host-configure: $(HOST_STAMP_CONFIGURED) diff --git a/include/image.mk b/include/image.mk index 5949dc538..ac8093704 100644 --- a/include/image.mk +++ b/include/image.mk @@ -23,7 +23,7 @@ JFFS2OPTS := --pad --big-endian --squash SQUASHFS_OPTS := -be endif -ifneq ($(CONFIG_LINUX_2_4)$(CONFIG_LINUX_2_6_21)$(CONFIG_LINUX_2_6_25)$(CONFIG_LINUX_2_6_28),) +ifneq ($(CONFIG_LINUX_2_4)$(CONFIG_LINUX_2_6_21)$(CONFIG_LINUX_2_6_25),) USE_SQUASHFS3 := y endif @@ -89,9 +89,9 @@ ifneq ($(CONFIG_TARGET_ROOTFS_INITRAMFS),y) ifeq ($(CONFIG_TARGET_ROOTFS_UBIFS),y) define Image/mkfs/ubifs $(CP) ./ubinize.cfg $(KDIR) - mkfs.ubifs $(UBIFS_OPTS) -o $(KDIR)/root.ubifs -d $(TARGET_DIR) + $(STAGING_DIR_HOST)/bin/mkfs.ubifs $(UBIFS_OPTS) -o $(KDIR)/root.ubifs -d $(TARGET_DIR) (cd $(KDIR); \ - ubinize $(UBINIZE_OPTS) -o $(BIN_DIR)/openwrt-$(BOARD)-rootfs.ubi ubinize.cfg) + $(STAGING_DIR_HOST)/bin/ubinize $(UBINIZE_OPTS) -o $(BIN_DIR)/openwrt-$(BOARD)-rootfs.ubi ubinize.cfg) endef endif else diff --git a/include/kernel-version.mk b/include/kernel-version.mk index 4562d5a38..4ab4bbe68 100644 --- a/include/kernel-version.mk +++ b/include/kernel-version.mk @@ -16,14 +16,14 @@ endif ifeq ($(LINUX_VERSION),2.6.25.20) LINUX_KERNEL_MD5SUM:=0da698edccf03e2235abc2830a495114 endif -ifeq ($(LINUX_VERSION),2.6.28.10) - LINUX_KERNEL_MD5SUM:=c4efb2c494d749cb5de274f8ae41c3fa +ifeq ($(LINUX_VERSION),2.6.30.10) + LINUX_KERNEL_MD5SUM:=eb6be465f914275967a5602cb33662f5 endif -ifeq ($(LINUX_VERSION),2.6.30.9) - LINUX_KERNEL_MD5SUM:=5a4cd5543a9d7c1a819700b21be31ef1 +ifeq ($(LINUX_VERSION),2.6.31.11) + LINUX_KERNEL_MD5SUM:=39e34c9a6439bcd4c088abe631302a99 endif -ifeq ($(LINUX_VERSION),2.6.31.6) - LINUX_KERNEL_MD5SUM:=485472df88af84becdcf47f45de3ba46 +ifeq ($(LINUX_VERSION),2.6.32.3) + LINUX_KERNEL_MD5SUM:=730045c2c7f7e6618db3c4d4d7094853 endif # disable the md5sum check for unknown kernel versions diff --git a/include/kernel.mk b/include/kernel.mk index ee4d4b8dc..480b9682c 100644 --- a/include/kernel.mk +++ b/include/kernel.mk @@ -42,7 +42,9 @@ else LINUX_SOURCE:=linux-$(LINUX_VERSION).tar.bz2 TESTING:=$(if $(findstring -rc,$(LINUX_VERSION)),/testing,) - LINUX_SITE:=@KERNEL/linux/kernel/v$(KERNEL)$(TESTING) \ + ifeq ($(call qstrip,$(CONFIG_EXTERNAL_KERNEL_TREE)),) + LINUX_SITE:=@KERNEL/linux/kernel/v$(KERNEL)$(TESTING) + endif ifneq ($(TARGET_BUILD),1) PKG_BUILD_DIR ?= $(KERNEL_BUILD_DIR)/$(PKG_NAME)$(if $(PKG_VERSION),-$(PKG_VERSION)) diff --git a/include/netfilter.mk b/include/netfilter.mk index b08d521f6..9eeee4f6e 100644 --- a/include/netfilter.mk +++ b/include/netfilter.mk @@ -65,7 +65,7 @@ $(eval $(call nf_add,EBTABLES_WATCHERS,CONFIG_BRIDGE_EBT_ULOG, $(P_EBT)ebt_ulog) $(eval $(call nf_add,EBTABLES_WATCHERS,CONFIG_BRIDGE_EBT_NFLOG, $(P_EBT)ebt_nflog)) # userland only -$(eval $(if $(NF_KMOD),,$(call nf_add,IPT_CORE,CONFIG_IP_NF_IPTABLES, xt_standard ipt_icmp xt_tcp xt_udp))) +$(eval $(if $(NF_KMOD),,$(call nf_add,IPT_CORE,CONFIG_IP_NF_IPTABLES, xt_standard ipt_icmp xt_tcp xt_udp xt_comment))) $(eval $(call nf_add,IPT_CORE,CONFIG_IP_NF_MATCH_LIMIT, $(P_V4)ipt_limit)) $(eval $(call nf_add,IPT_CORE,CONFIG_NETFILTER_XT_MATCH_LIMIT, $(P_XT)xt_limit)) diff --git a/include/site/linux b/include/site/linux new file mode 100644 index 000000000..ca4fd29c9 --- /dev/null +++ b/include/site/linux @@ -0,0 +1,72 @@ +ac_atomic_add=yes +ac_atomic_sub=yes +ac_cv_c_gettext_without_libintl=yes +ac_cv_c_long_double=no +ac_cv_conv_longlong_to_float=yes +ac_cv_file__dev_zero=yes +ac_cv_func___va_copy=no +ac_cv_func__exit=yes +ac_cv_func_bcopy=yes +ac_cv_func_bzero=yes +ac_cv_func_bcmp=yes +ac_cv_func_fchmod=yes +ac_cv_func_getaddrinfo=yes +ac_cv_func_getcwd=yes +ac_cv_func_getdomainname=yes +ac_cv_func_getpgrp_void=yes +ac_cv_func_getpwuid_r=yes +ac_cv_func_index=yes +ac_cv_func_lstat_dereferences_slashed_symlink=yes +ac_cv_func_lstat_empty_string_bug=no +ac_cv_func_lstat=yes +ac_cv_func_malloc_0_nonnull=yes +ac_cv_func_malloc_works=yes +ac_cv_func_memcmp_clean=yes +ac_cv_func_memcmp_working=yes +ac_cv_func_posix_getgrgid_r=yes +ac_cv_func_posix_getpwuid_r=yes +ac_cv_func_pthread_key_delete=yes +ac_cv_func_realloc_0_nonnull=yes +ac_cv_func_realloc_works=yes +ac_cv_func_rename=yes +ac_cv_func_rindex=yes +ac_cv_func_setlocale=yes +ac_cv_func_setgrent_void=yes +ac_cv_func_setpgrp_void=yes +ac_cv_func_setresuid=no +ac_cv_func_setvbuf_reversed=no +ac_cv_func_stat_empty_string_bug=no +ac_cv_func_stat_ignores_trailing_slash=no +ac_cv_func_strerror=yes +ac_cv_func_strftime=yes +ac_cv_func_utimes=yes +ac_cv_func___adjtimex=yes +ac_cv_func_va_copy=no +ac_cv_func_vsnprintf=yes +ac_cv_have_accrights_in_msghdr=no +ac_cv_have_broken_snprintf=no +ac_cv_have_control_in_msghdr=yes +ac_cv_have_decl_sys_siglist=no +ac_cv_have_openpty_ctty_bug=yes +ac_cv_have_space_d_name_in_struct_dirent=yes +ac_cv_header_netinet_sctp_h=no +ac_cv_header_netinet_sctp_uio_h=no +ac_cv_int64_t=yes +ac_cv_lbl_unaligned_fail=no +ac_cv_linux_kernel_pppoe=yes +ac_cv_linux_vers=2 +ac_cv_pack_bitfields_reversed=yes +ac_cv_path_LDCONFIG= +ac_cv_regexec_segfault_emptystr=no +ac_cv_sctp=no +ac_cv_sys_restartable_syscalls=yes +ac_cv_time_r_type=POSIX +ac_cv_type_suseconds_t=yes +ac_cv_uchar=no +ac_cv_uint=yes +ac_cv_uint64_t=yes +ac_cv_ulong=yes +ac_cv_ushort=yes +ac_cv_va_copy=C99 +ac_cv_va_val_copy=yes +as_cv_unaligned_access=yes diff --git a/include/site/linux-gnu b/include/site/linux-gnu index ca4fd29c9..be4a8d001 100644 --- a/include/site/linux-gnu +++ b/include/site/linux-gnu @@ -1,72 +1 @@ -ac_atomic_add=yes -ac_atomic_sub=yes -ac_cv_c_gettext_without_libintl=yes -ac_cv_c_long_double=no -ac_cv_conv_longlong_to_float=yes -ac_cv_file__dev_zero=yes -ac_cv_func___va_copy=no -ac_cv_func__exit=yes -ac_cv_func_bcopy=yes -ac_cv_func_bzero=yes -ac_cv_func_bcmp=yes -ac_cv_func_fchmod=yes -ac_cv_func_getaddrinfo=yes -ac_cv_func_getcwd=yes -ac_cv_func_getdomainname=yes -ac_cv_func_getpgrp_void=yes -ac_cv_func_getpwuid_r=yes -ac_cv_func_index=yes -ac_cv_func_lstat_dereferences_slashed_symlink=yes -ac_cv_func_lstat_empty_string_bug=no -ac_cv_func_lstat=yes -ac_cv_func_malloc_0_nonnull=yes -ac_cv_func_malloc_works=yes -ac_cv_func_memcmp_clean=yes -ac_cv_func_memcmp_working=yes -ac_cv_func_posix_getgrgid_r=yes -ac_cv_func_posix_getpwuid_r=yes -ac_cv_func_pthread_key_delete=yes -ac_cv_func_realloc_0_nonnull=yes -ac_cv_func_realloc_works=yes -ac_cv_func_rename=yes -ac_cv_func_rindex=yes -ac_cv_func_setlocale=yes -ac_cv_func_setgrent_void=yes -ac_cv_func_setpgrp_void=yes -ac_cv_func_setresuid=no -ac_cv_func_setvbuf_reversed=no -ac_cv_func_stat_empty_string_bug=no -ac_cv_func_stat_ignores_trailing_slash=no -ac_cv_func_strerror=yes -ac_cv_func_strftime=yes -ac_cv_func_utimes=yes -ac_cv_func___adjtimex=yes -ac_cv_func_va_copy=no -ac_cv_func_vsnprintf=yes -ac_cv_have_accrights_in_msghdr=no -ac_cv_have_broken_snprintf=no -ac_cv_have_control_in_msghdr=yes -ac_cv_have_decl_sys_siglist=no -ac_cv_have_openpty_ctty_bug=yes -ac_cv_have_space_d_name_in_struct_dirent=yes -ac_cv_header_netinet_sctp_h=no -ac_cv_header_netinet_sctp_uio_h=no -ac_cv_int64_t=yes -ac_cv_lbl_unaligned_fail=no -ac_cv_linux_kernel_pppoe=yes -ac_cv_linux_vers=2 -ac_cv_pack_bitfields_reversed=yes -ac_cv_path_LDCONFIG= -ac_cv_regexec_segfault_emptystr=no -ac_cv_sctp=no -ac_cv_sys_restartable_syscalls=yes -ac_cv_time_r_type=POSIX -ac_cv_type_suseconds_t=yes -ac_cv_uchar=no -ac_cv_uint=yes -ac_cv_uint64_t=yes -ac_cv_ulong=yes -ac_cv_ushort=yes -ac_cv_va_copy=C99 -ac_cv_va_val_copy=yes -as_cv_unaligned_access=yes +. $TOPDIR/include/site/linux diff --git a/include/site/linux-uclibc b/include/site/linux-uclibc index ca4fd29c9..be4a8d001 100644 --- a/include/site/linux-uclibc +++ b/include/site/linux-uclibc @@ -1,72 +1 @@ -ac_atomic_add=yes -ac_atomic_sub=yes -ac_cv_c_gettext_without_libintl=yes -ac_cv_c_long_double=no -ac_cv_conv_longlong_to_float=yes -ac_cv_file__dev_zero=yes -ac_cv_func___va_copy=no -ac_cv_func__exit=yes -ac_cv_func_bcopy=yes -ac_cv_func_bzero=yes -ac_cv_func_bcmp=yes -ac_cv_func_fchmod=yes -ac_cv_func_getaddrinfo=yes -ac_cv_func_getcwd=yes -ac_cv_func_getdomainname=yes -ac_cv_func_getpgrp_void=yes -ac_cv_func_getpwuid_r=yes -ac_cv_func_index=yes -ac_cv_func_lstat_dereferences_slashed_symlink=yes -ac_cv_func_lstat_empty_string_bug=no -ac_cv_func_lstat=yes -ac_cv_func_malloc_0_nonnull=yes -ac_cv_func_malloc_works=yes -ac_cv_func_memcmp_clean=yes -ac_cv_func_memcmp_working=yes -ac_cv_func_posix_getgrgid_r=yes -ac_cv_func_posix_getpwuid_r=yes -ac_cv_func_pthread_key_delete=yes -ac_cv_func_realloc_0_nonnull=yes -ac_cv_func_realloc_works=yes -ac_cv_func_rename=yes -ac_cv_func_rindex=yes -ac_cv_func_setlocale=yes -ac_cv_func_setgrent_void=yes -ac_cv_func_setpgrp_void=yes -ac_cv_func_setresuid=no -ac_cv_func_setvbuf_reversed=no -ac_cv_func_stat_empty_string_bug=no -ac_cv_func_stat_ignores_trailing_slash=no -ac_cv_func_strerror=yes -ac_cv_func_strftime=yes -ac_cv_func_utimes=yes -ac_cv_func___adjtimex=yes -ac_cv_func_va_copy=no -ac_cv_func_vsnprintf=yes -ac_cv_have_accrights_in_msghdr=no -ac_cv_have_broken_snprintf=no -ac_cv_have_control_in_msghdr=yes -ac_cv_have_decl_sys_siglist=no -ac_cv_have_openpty_ctty_bug=yes -ac_cv_have_space_d_name_in_struct_dirent=yes -ac_cv_header_netinet_sctp_h=no -ac_cv_header_netinet_sctp_uio_h=no -ac_cv_int64_t=yes -ac_cv_lbl_unaligned_fail=no -ac_cv_linux_kernel_pppoe=yes -ac_cv_linux_vers=2 -ac_cv_pack_bitfields_reversed=yes -ac_cv_path_LDCONFIG= -ac_cv_regexec_segfault_emptystr=no -ac_cv_sctp=no -ac_cv_sys_restartable_syscalls=yes -ac_cv_time_r_type=POSIX -ac_cv_type_suseconds_t=yes -ac_cv_uchar=no -ac_cv_uint=yes -ac_cv_uint64_t=yes -ac_cv_ulong=yes -ac_cv_ushort=yes -ac_cv_va_copy=C99 -ac_cv_va_val_copy=yes -as_cv_unaligned_access=yes +. $TOPDIR/include/site/linux diff --git a/package/ar7-atm/Config.in b/package/ar7-atm/Config.in new file mode 100644 index 000000000..c828d5c9a --- /dev/null +++ b/package/ar7-atm/Config.in @@ -0,0 +1,15 @@ +choice + prompt "Firmware version" + depends on (PACKAGE_kmod-sangam-atm-annex-a || PACKAGE_kmod-sangam-atm-annex-b) + default AR7_ATM_FW_VERSION_704 + help + This option allows you to switch between firmware/driver versions which + might improve the DSL line speed. + +config AR7_ATM_FW_VERSION_704 + bool "D7.04.03.00" + +config AR7_ATM_FW_VERSION_703 + bool "D7.03.01.00" + +endchoice diff --git a/package/ar7-atm/Makefile b/package/ar7-atm/Makefile index e03704ab3..88036c693 100644 --- a/package/ar7-atm/Makefile +++ b/package/ar7-atm/Makefile @@ -9,23 +9,36 @@ include $(TOPDIR)/rules.mk include $(INCLUDE_DIR)/kernel.mk PKG_NAME:=sangam_atm + +ifeq ($(CONFIG_AR7_ATM_FW_VERSION_704),y) PKG_VERSION:=D7.04.03.00 +PKG_MD5SUM:=3d76004e46f09e88931f91670cb420ad PKG_RELEASE:=R1 +endif + +ifeq ($(CONFIG_AR7_ATM_FW_VERSION_703),y) +PKG_VERSION:=D7.03.01.00 +PKG_MD5SUM:=bc6e9c6adb1be25820c7ee661de8ca7d +PKG_RELEASE:=R2 +endif PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION)-$(PKG_RELEASE).tar.bz2 PKG_SOURCE_URL:=http://mirror2.openwrt.org/sources -PKG_MD5SUM:=3d76004e46f09e88931f91670cb420ad include $(INCLUDE_DIR)/package.mk define KernelPackage/sangam-atm/Default SUBMENU:=Network Devices - DEPENDS:=@TARGET_ar7 +kmod-atm + DEPENDS:=@TARGET_ar7 +kmod-atm TITLE:=AR7 ADSL driver FILES:=$(PKG_BUILD_DIR)/tiatm.$(LINUX_KMOD_SUFFIX) AUTOLOAD:=$(call AutoLoad,50,tiatm) endef +define KernelPackage/sangam-atm/config + source "$(SOURCE)/Config.in" +endef + define KernelPackage/sangam-atm-annex-a $(call KernelPackage/sangam-atm/Default) TITLE+= (Annex A, ADSL over POTS) @@ -35,6 +48,10 @@ define KernelPackage/sangam-atm-annex-a/description The AR7 ADSL driver for Annex A (ADSL over POTS). endef +define KernelPackage/sangam-atm-annex-a/config +$(call KernelPackage/sangam-atm/config) +endef + define KernelPackage/sangam-atm-annex-b $(call KernelPackage/sangam-atm/Default) TITLE+= (Annex B, ADSL over ISDN) @@ -44,6 +61,10 @@ define KernelPackage/sangam-atm-annex-b/description The AR7 ADSL driver for Annex B (ADSL over ISDN). endef +define KernelPackage/sangam-atm-annex-a/config +$(call KernelPackage/sangam-atm/config) +endef + define Build/Compile $(MAKE) -C "$(LINUX_DIR)" \ CROSS_COMPILE="$(TARGET_CROSS)" \ diff --git a/package/base-files/Makefile b/package/base-files/Makefile index cad128c2f..673ba3eb2 100644 --- a/package/base-files/Makefile +++ b/package/base-files/Makefile @@ -439,7 +439,7 @@ ifeq ($(CONFIG_EXTERNAL_TOOLCHAIN),) endef define Package/libpthread/install_lib - $(if $(wildcard $(TOOLCHAIN_DIR)/usr/lib/libc_so.a),$(CP) $(TOOLCHAIN_DIR)/usr/lib/libpthread_so.a $(1)/lib/libpthread_pic.a) + $(if $(wildcard $(TOOLCHAIN_DIR)/usr/lib/libpthread_so.a),$(CP) $(TOOLCHAIN_DIR)/usr/lib/libpthread_so.a $(1)/lib/libpthread_pic.a) endef define Package/librt/install diff --git a/package/base-files/files/etc/functions.sh b/package/base-files/files/etc/functions.sh index eb7faac1f..fa0ba0427 100755 --- a/package/base-files/files/etc/functions.sh +++ b/package/base-files/files/etc/functions.sh @@ -2,8 +2,13 @@ # Copyright (C) 2006 OpenWrt.org # Copyright (C) 2006 Fokus Fraunhofer -alias debug=${DEBUG:-:} -alias mount='busybox mount' + +debug () { + ${DEBUG:-:} "$@" +} +mount() { + busybox mount "$@" +} # newline N=" @@ -258,7 +263,7 @@ jffs2_mark_erase() { echo -e "\xde\xad\xc0\xde" | mtd -qq write - "$1" } -uci_apply_defaults() {( +uci_apply_defaults() { cd /etc/uci-defaults || return 0 files="$(ls)" [ -z "$files" ] && return 0 @@ -267,6 +272,6 @@ uci_apply_defaults() {( ( . "./$(basename $file)" ) && rm -f "$file" done uci commit -)} +} [ -z "$IPKG_INSTROOT" -a -f /lib/config/uci.sh ] && . /lib/config/uci.sh diff --git a/package/base-files/files/etc/init.d/boot b/package/base-files/files/etc/init.d/boot index aa9e96778..2ed4c5061 100755 --- a/package/base-files/files/etc/init.d/boot +++ b/package/base-files/files/etc/init.d/boot @@ -35,10 +35,9 @@ system_config() { [ -x /sbin/klogd ] && klogd ${klogconloglevel:+-c $klogconloglevel} } -apply_uci_config() {( - include /lib/config - uci_apply_defaults -)} +apply_uci_config() { + sh -c '. /etc/functions.sh; include /lib/config; uci_apply_defaults' +} start() { [ -f /proc/mounts ] || /sbin/mount_root diff --git a/package/base-files/files/etc/init.d/led b/package/base-files/files/etc/init.d/led index 046134fc5..d9e3db6ae 100755 --- a/package/base-files/files/etc/init.d/led +++ b/package/base-files/files/etc/init.d/led @@ -1,7 +1,7 @@ #!/bin/sh /etc/rc.common # (C) 2008 openwrt.org -START=60 +START=96 load_led() { local name diff --git a/package/base-files/files/lib/network/config.sh b/package/base-files/files/lib/network/config.sh index fbbf0e119..ccdfc38b3 100755 --- a/package/base-files/files/lib/network/config.sh +++ b/package/base-files/files/lib/network/config.sh @@ -289,7 +289,7 @@ setup_interface() { # don't stay running in background if dhcp is not the main proto on the interface (e.g. when using pptp) local dhcpopts [ ."$proto1" != ."$proto" ] && dhcpopts="-n -q" - $DEBUG eval udhcpc -t 0 -i "$iface" ${ipaddr:+-r $ipaddr} ${hostname:+-H $hostname} ${clientid:+-c $clientid} -b -p "$pidfile" ${dhcpopts:- -R &} + $DEBUG eval udhcpc -t 0 -i "$iface" ${ipaddr:+-r $ipaddr} ${hostname:+-H $hostname} ${clientid:+-c $clientid} -b -p "$pidfile" ${dhcpopts:- -O rootpath -R &} lock -u "/var/lock/dhcp-$iface" fi ;; diff --git a/package/base-files/files/sbin/hotplug-call b/package/base-files/files/sbin/hotplug-call index e2f7e3617..c5a76a76c 100755 --- a/package/base-files/files/sbin/hotplug-call +++ b/package/base-files/files/sbin/hotplug-call @@ -8,7 +8,7 @@ export HOTPLUG_TYPE="$1" [ -d /sys/firmware -a "firmware" = "$HOTPLUG_TYPE" -a "add" = "$ACTION" ] && { [ -f "/lib/firmware/$FIRMWARE" ] && { echo 1 > "/sys$DEVPATH/loading" - cp "/lib/firmware/$FIRMWARE" "/sys$DEVPATH/data" + dd if="/lib/firmware/$FIRMWARE" of="/sys$DEVPATH/data" bs=64k echo 0 > "/sys$DEVPATH/loading" } exit 0 diff --git a/package/broadcom-diag/src/diag.c b/package/broadcom-diag/src/diag.c index 89af0f7fc..fefd036c7 100644 --- a/package/broadcom-diag/src/diag.c +++ b/package/broadcom-diag/src/diag.c @@ -61,6 +61,7 @@ enum { WRTSL54GS, WRT54G3G, WRT160N, + WRT300NV11, WRT350N, WRT600N, WRT600NV11, @@ -131,6 +132,12 @@ enum { /* Sitecom */ WL105B, + + /* Western Digital */ + WDNetCenter, + + /* Askey */ + RT210W, }; static void __init bcm4780_init(void) { @@ -147,6 +154,21 @@ static void __init bcm4780_init(void) { schedule_timeout(HZ * 5); } +static void __init NetCenter_init(void) { + /* unset pin 6 (+12V) */ + int pin = 1 << 6; + gpio_outen(pin, pin); + gpio_control(pin, 0); + gpio_out(pin, pin); + /* unset pin 1 (turn off red led, blue will light alone if +5V comes up) */ + pin = 1 << 1; + gpio_outen(pin, pin); + gpio_control(pin, 0); + gpio_out(pin, pin); + /* unset pin 3 (+5V) and wait 5 seconds (harddisk spin up) */ + bcm4780_init(); +} + static void __init bcm57xx_init(void) { int pin = 1 << 2; @@ -255,6 +277,19 @@ static struct platform_t __initdata platforms[] = { { .name = "ses_orange", .gpio = 1 << 3, .polarity = REVERSE }, }, }, + [WRT300NV11] = { + .name = "Linksys WRT300N V1.1", + .buttons = { + { .name = "reset", .gpio = 1 << 6 }, // "Reset" on back panel + { .name = "ses", .gpio = 1 << 4 }, // "Reserved" on top panel + }, + .leds = { + { .name = "power", .gpio = 1 << 1, .polarity = NORMAL }, // "Power" + { .name = "ses_amber", .gpio = 1 << 3, .polarity = REVERSE }, // "Security" Amber + { .name = "ses_green", .gpio = 1 << 5, .polarity = REVERSE }, // "Security" Green + }, + .platform_init = bcm57xx_init, + }, [WRT350N] = { .name = "Linksys WRT350N", .buttons = { @@ -793,6 +828,30 @@ static struct platform_t __initdata platforms[] = { { .name = "power", .gpio = 1 << 3}, }, }, + /* Western Digital Net Center */ + [WDNetCenter] = { + .name = "Western Digital NetCenter", + .buttons = { + { .name = "power", .gpio = 1 << 0}, + { .name = "reset", .gpio = 1 << 7}, + }, + .platform_init = NetCenter_init, + }, + /* Askey (and clones) */ + [RT210W] = { + .name = "Askey RT210W", + .buttons = { + /* Power button is hard-wired to hardware reset */ + /* but is also connected to GPIO 7 (probably for bootloader recovery) */ + { .name = "power", .gpio = 1 << 7}, + }, + .leds = { + /* These were verified and named based on Belkin F5D4230-4 v1112 */ + { .name = "connected", .gpio = 1 << 0, .polarity = REVERSE }, + { .name = "wlan", .gpio = 1 << 3, .polarity = REVERSE }, + { .name = "power", .gpio = 1 << 5, .polarity = REVERSE }, + }, + }, }; static struct platform_t __init *platform_detect(void) @@ -886,6 +945,9 @@ static struct platform_t __init *platform_detect(void) if (startswith(getvar("pmon_ver"), "CFE")) { /* CFE based - newer hardware */ if (!strcmp(boardnum, "42")) { /* Linksys */ + if (!strcmp(boardtype, "0x478") && !strcmp(getvar("boot_hw_model"), "WRT300N") && !strcmp(getvar("boot_hw_ver"), "1.1")) + return &platforms[WRT300NV11]; + if (!strcmp(boardtype, "0x478") && !strcmp(getvar("cardbus"), "1")) return &platforms[WRT350N]; @@ -930,6 +992,10 @@ static struct platform_t __init *platform_detect(void) !strcmp(getvar("boardflags"), "0x750")) /* D-Link DIR-320 */ return &platforms[DIR320]; + if (!strncmp(boardnum, "TH",2) && !strcmp(boardtype,"0x042f")) { + return &platforms[WDNetCenter]; + } + } else { /* PMON based - old stuff */ if ((simple_strtoul(getvar("GemtekPmonVer"), NULL, 0) == 9) && (simple_strtoul(getvar("et0phyaddr"), NULL, 0) == 30)) { @@ -959,6 +1025,18 @@ static struct platform_t __init *platform_detect(void) /* unknown asus stuff, probably bcm4702 */ if (startswith(boardnum, "asusX")) return &platforms[ASUS_4702]; + + /* bcm4702 based Askey RT210W clones, Including: + * Askey RT210W (duh?) + * Siemens SE505v1 + * Belkin F5D7230-4 before version v1444 (MiniPCI slot, not integrated) + */ + if (!strcmp(boardtype,"bcm94710r4") + && !strcmp(boardnum ,"100") + && !strcmp(getvar("pmon_ver"),"v1.03.12.bk") + ){ + return &platforms[RT210W]; + } } if (buf || !strcmp(boardnum, "00")) {/* probably buffalo */ diff --git a/package/broadcom-wl/files/lib/wifi/broadcom.sh b/package/broadcom-wl/files/lib/wifi/broadcom.sh index 985100f6f..f5d15f841 100644 --- a/package/broadcom-wl/files/lib/wifi/broadcom.sh +++ b/package/broadcom-wl/files/lib/wifi/broadcom.sh @@ -124,6 +124,8 @@ enable_broadcom() { config_get maclist "$device" maclist config_get macaddr "$device" macaddr config_get txpower "$device" txpower + config_get frag "$device" frag + config_get rts "$device" rts local vif_pre_up vif_post_up vif_do_up vif_txpower local doth=0 local wmm=0 @@ -291,6 +293,8 @@ ${wet:+wet 1} wme ${wmm:-0} rxant ${rxantenna:-3} txant ${txantenna:-3} +fragthresh ${frag:-2346} +rtsthresh ${rts:-2347} monitor ${monitor:-0} passive ${passive:-0} diff --git a/package/busybox/Makefile b/package/busybox/Makefile index 508c3e99a..43da0a48d 100644 --- a/package/busybox/Makefile +++ b/package/busybox/Makefile @@ -8,13 +8,13 @@ include $(TOPDIR)/rules.mk PKG_NAME:=busybox -PKG_VERSION:=1.14.4 -PKG_RELEASE:=2 +PKG_VERSION:=1.15.3 +PKG_RELEASE:=1 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2 PKG_SOURCE_URL:=http://www.busybox.net/downloads \ http://distfiles.gentoo.org/distfiles/ -PKG_MD5SUM:=ad6d0b271e60783a3c767c4ccbc7f98e +PKG_MD5SUM:=6059ac9456de6fb18dc8ee4cd0ec9240 include $(INCLUDE_DIR)/package.mk diff --git a/package/busybox/config/Config.in b/package/busybox/config/Config.in index cf656998c..3beb0d12a 100644 --- a/package/busybox/config/Config.in +++ b/package/busybox/config/Config.in @@ -29,18 +29,6 @@ config BUSYBOX_CONFIG_EXTRA_COMPAT some GNU extensions in libc. You probably only need this option if you plan to run busybox on desktop. -config BUSYBOX_CONFIG_FEATURE_ASSUME_UNICODE - bool "Assume that 1:1 char/glyph correspondence is not true" - default n - help - This makes various applets aware that one byte is not - one character on screen. - - Busybox aims to eventually work correctly with Unicode displays. - Any older encodings are not guaranteed to work. - Probably by the time when busybox will be fully Unicode-clean, - other encodings will be mainly of historic interest. - choice prompt "Buffer allocation policy" default BUSYBOX_CONFIG_FEATURE_BUFFERS_GO_ON_STACK @@ -113,7 +101,29 @@ config BUSYBOX_CONFIG_LOCALE_SUPPORT Enable this if your system has locale support and you would like busybox to support locale settings. -config BUSYBOX_CONFIG_GETOPT_LONG +config BUSYBOX_CONFIG_FEATURE_ASSUME_UNICODE + bool "Support Unicode" + default n + help + This makes various applets aware that one byte is not + one character on screen. + + Busybox aims to eventually work correctly with Unicode displays. + Any older encodings are not guaranteed to work. + Probably by the time when busybox will be fully Unicode-clean, + other encodings will be mainly of historic interest. + +config BUSYBOX_CONFIG_FEATURE_CHECK_UNICODE_IN_ENV + bool "Check $LANG environment variable" + default n + depends on BUSYBOX_CONFIG_FEATURE_ASSUME_UNICODE && !BUSYBOX_CONFIG_LOCALE_SUPPORT + help + With this option on, Unicode support is activated + only if LANG variable has the value of the form "xxxx.utf8" + + Otherwise, Unicode support will be always enabled and active. + +config BUSYBOX_CONFIG_LONG_OPTS bool "Support for --long-options" default y help diff --git a/package/busybox/config/archival/Config.in b/package/busybox/config/archival/Config.in index 81534e840..5103be484 100644 --- a/package/busybox/config/archival/Config.in +++ b/package/busybox/config/archival/Config.in @@ -53,12 +53,12 @@ config BUSYBOX_CONFIG_AR probably say N here. config BUSYBOX_CONFIG_FEATURE_AR_LONG_FILENAMES - bool "Support for long filenames (not need for debs)" + bool "Support for long filenames (not needed for debs)" default n depends on BUSYBOX_CONFIG_AR help - By default the ar format can only store the first 15 characters of - the filename, this option removes that limitation. + By default the ar format can only store the first 15 characters + of the filename, this option removes that limitation. It supports the GNU ar long filename method which moves multiple long filenames into a the data section of a new ar entry. @@ -165,6 +165,21 @@ config BUSYBOX_CONFIG_GZIP gzip is used to compress files. It's probably the most widely used UNIX compression program. +config BUSYBOX_CONFIG_LZOP + bool "lzop" + default n + help + Lzop compression/decompresion. + +config BUSYBOX_CONFIG_LZOP_COMPR_HIGH + bool "lzop complession levels 7,8,9 (not very useful)" + default n + depends on BUSYBOX_CONFIG_LZOP + help + High levels (7,8,9) of lzop compression. These levels + are actually slower than gzip at equivalent compression ratios + and take up 3.2K of code. + config BUSYBOX_CONFIG_RPM2CPIO bool "rpm2cpio" default n @@ -196,11 +211,11 @@ config BUSYBOX_CONFIG_FEATURE_TAR_CREATE tar archives using the `-c' option. config BUSYBOX_CONFIG_FEATURE_TAR_AUTODETECT - bool "Autodetect gz/bz2 compressed tarballs" + bool "Autodetect compressed tarballs" default n depends on BUSYBOX_CONFIG_FEATURE_SEAMLESS_Z || BUSYBOX_CONFIG_FEATURE_SEAMLESS_GZ || BUSYBOX_CONFIG_FEATURE_SEAMLESS_BZ2 || BUSYBOX_CONFIG_FEATURE_SEAMLESS_LZMA help - With this option tar can automatically detect gzip/bzip2 compressed + With this option tar can automatically detect compressed tarballs. Currently it works only on files (not pipes etc). config BUSYBOX_CONFIG_FEATURE_TAR_FROM @@ -241,7 +256,7 @@ config BUSYBOX_CONFIG_FEATURE_TAR_GNU_EXTENSIONS config BUSYBOX_CONFIG_FEATURE_TAR_LONG_OPTIONS bool "Enable long options" default n - depends on BUSYBOX_CONFIG_TAR && BUSYBOX_CONFIG_GETOPT_LONG + depends on BUSYBOX_CONFIG_TAR && BUSYBOX_CONFIG_LONG_OPTS help Enable use of long options, increases size by about 400 Bytes @@ -283,8 +298,8 @@ config BUSYBOX_CONFIG_FEATURE_LZMA_FAST default n depends on BUSYBOX_CONFIG_UNLZMA help - This option reduces decompression time by about 33% at the cost of - a 2K bigger binary. + This option reduces decompression time by about 25% at the cost of + a 1K bigger binary. config BUSYBOX_CONFIG_UNZIP bool "unzip" diff --git a/package/busybox/config/console-tools/Config.in b/package/busybox/config/console-tools/Config.in index ffc96d1b6..229cf45c5 100644 --- a/package/busybox/config/console-tools/Config.in +++ b/package/busybox/config/console-tools/Config.in @@ -91,7 +91,7 @@ config BUSYBOX_CONFIG_SETCONSOLE config BUSYBOX_CONFIG_FEATURE_SETCONSOLE_LONG_OPTIONS bool "Enable long options" default n - depends on BUSYBOX_CONFIG_SETCONSOLE && BUSYBOX_CONFIG_GETOPT_LONG + depends on BUSYBOX_CONFIG_SETCONSOLE && BUSYBOX_CONFIG_LONG_OPTS help Support long options for the setconsole applet. diff --git a/package/busybox/config/coreutils/Config.in b/package/busybox/config/coreutils/Config.in index 4b106cf42..06e7874e2 100644 --- a/package/busybox/config/coreutils/Config.in +++ b/package/busybox/config/coreutils/Config.in @@ -204,7 +204,7 @@ config BUSYBOX_CONFIG_ENV config BUSYBOX_CONFIG_FEATURE_ENV_LONG_OPTIONS bool "Enable long options" default n - depends on BUSYBOX_CONFIG_ENV && BUSYBOX_CONFIG_GETOPT_LONG + depends on BUSYBOX_CONFIG_ENV && BUSYBOX_CONFIG_LONG_OPTS help Support long options for the env applet. @@ -217,7 +217,7 @@ config BUSYBOX_CONFIG_EXPAND config BUSYBOX_CONFIG_FEATURE_EXPAND_LONG_OPTIONS bool "Enable long options" default n - depends on BUSYBOX_CONFIG_EXPAND && BUSYBOX_CONFIG_GETOPT_LONG + depends on BUSYBOX_CONFIG_EXPAND && BUSYBOX_CONFIG_LONG_OPTS help Support long options for the expand applet. @@ -249,6 +249,12 @@ config BUSYBOX_CONFIG_FOLD help Wrap text to fit a specific width. +config BUSYBOX_CONFIG_FSYNC + bool "fsync" + default n + help + fsync is used to flush file-related cached blocks to disk. + config BUSYBOX_CONFIG_HEAD bool "head" default y @@ -285,7 +291,7 @@ config BUSYBOX_CONFIG_INSTALL config BUSYBOX_CONFIG_FEATURE_INSTALL_LONG_OPTIONS bool "Enable long options" default n - depends on BUSYBOX_CONFIG_INSTALL && BUSYBOX_CONFIG_GETOPT_LONG + depends on BUSYBOX_CONFIG_INSTALL && BUSYBOX_CONFIG_LONG_OPTS help Support long options for the install applet. @@ -358,7 +364,7 @@ config BUSYBOX_CONFIG_FEATURE_LS_USERNAME config BUSYBOX_CONFIG_FEATURE_LS_COLOR bool "Allow use of color to identify file types" default y - depends on BUSYBOX_CONFIG_LS && BUSYBOX_CONFIG_GETOPT_LONG + depends on BUSYBOX_CONFIG_LS && BUSYBOX_CONFIG_LONG_OPTS help This enables the --color option to ls. @@ -388,7 +394,7 @@ config BUSYBOX_CONFIG_MKDIR config BUSYBOX_CONFIG_FEATURE_MKDIR_LONG_OPTIONS bool "Enable long options" default n - depends on BUSYBOX_CONFIG_MKDIR && BUSYBOX_CONFIG_GETOPT_LONG + depends on BUSYBOX_CONFIG_MKDIR && BUSYBOX_CONFIG_LONG_OPTS help Support long options for the mkdir applet. @@ -415,7 +421,7 @@ config BUSYBOX_CONFIG_MV config BUSYBOX_CONFIG_FEATURE_MV_LONG_OPTIONS bool "Enable long options" default n - depends on BUSYBOX_CONFIG_MV && BUSYBOX_CONFIG_GETOPT_LONG + depends on BUSYBOX_CONFIG_MV && BUSYBOX_CONFIG_LONG_OPTS help Support long options for the mv applet. @@ -492,7 +498,7 @@ config BUSYBOX_CONFIG_RMDIR config BUSYBOX_CONFIG_FEATURE_RMDIR_LONG_OPTIONS bool "Enable long options" default n - depends on BUSYBOX_CONFIG_RMDIR && BUSYBOX_CONFIG_GETOPT_LONG + depends on BUSYBOX_CONFIG_RMDIR && BUSYBOX_CONFIG_LONG_OPTS help Support long options for the rmdir applet, including --ignore-fail-on-non-empty for compatibility with GNU rmdir. @@ -629,7 +635,7 @@ config BUSYBOX_CONFIG_TAIL from files. config BUSYBOX_CONFIG_FEATURE_FANCY_TAIL - bool "Enable extra tail options (-q, -s, and -v)" + bool "Enable extra tail options (-q, -s, -v, and -F)" default y depends on BUSYBOX_CONFIG_TAIL help @@ -661,7 +667,7 @@ config BUSYBOX_CONFIG_TEST config BUSYBOX_CONFIG_FEATURE_TEST_64 bool "Extend test to 64 bit" default y - depends on BUSYBOX_CONFIG_TEST || BUSYBOX_CONFIG_ASH_BUILTIN_TEST + depends on BUSYBOX_CONFIG_TEST || BUSYBOX_CONFIG_ASH_BUILTIN_TEST || BUSYBOX_CONFIG_HUSH help Enable 64-bit support in test. @@ -726,7 +732,7 @@ config BUSYBOX_CONFIG_UNEXPAND config BUSYBOX_CONFIG_FEATURE_UNEXPAND_LONG_OPTIONS bool "Enable long options" default n - depends on BUSYBOX_CONFIG_UNEXPAND && BUSYBOX_CONFIG_GETOPT_LONG + depends on BUSYBOX_CONFIG_UNEXPAND && BUSYBOX_CONFIG_LONG_OPTS help Support long options for the unexpand applet. diff --git a/package/busybox/config/debianutils/Config.in b/package/busybox/config/debianutils/Config.in index e5f0c2616..e61c661fc 100644 --- a/package/busybox/config/debianutils/Config.in +++ b/package/busybox/config/debianutils/Config.in @@ -35,7 +35,7 @@ config BUSYBOX_CONFIG_RUN_PARTS config BUSYBOX_CONFIG_FEATURE_RUN_PARTS_LONG_OPTIONS bool "Enable long options" default n - depends on BUSYBOX_CONFIG_RUN_PARTS && BUSYBOX_CONFIG_GETOPT_LONG + depends on BUSYBOX_CONFIG_RUN_PARTS && BUSYBOX_CONFIG_LONG_OPTS help Support long options for the run-parts applet. @@ -69,7 +69,7 @@ config BUSYBOX_CONFIG_FEATURE_START_STOP_DAEMON_FANCY config BUSYBOX_CONFIG_FEATURE_START_STOP_DAEMON_LONG_OPTIONS bool "Enable long options" default n - depends on BUSYBOX_CONFIG_START_STOP_DAEMON && BUSYBOX_CONFIG_GETOPT_LONG + depends on BUSYBOX_CONFIG_START_STOP_DAEMON && BUSYBOX_CONFIG_LONG_OPTS help Support long options for the start-stop-daemon applet. diff --git a/package/busybox/config/findutils/Config.in b/package/busybox/config/findutils/Config.in index 991b97fac..32a213b46 100644 --- a/package/busybox/config/findutils/Config.in +++ b/package/busybox/config/findutils/Config.in @@ -12,17 +12,17 @@ config BUSYBOX_CONFIG_FIND find is used to search your system to find specified files. config BUSYBOX_CONFIG_FEATURE_FIND_PRINT0 - bool "Enable -print0 option" + bool "Enable -print0: NUL-terminated output" default y depends on BUSYBOX_CONFIG_FIND help - Causes output names to be separated by a null character + Causes output names to be separated by a NUL character rather than a newline. This allows names that contain newlines and other whitespace to be more easily interpreted by other programs. config BUSYBOX_CONFIG_FEATURE_FIND_MTIME - bool "Enable modified time matching (-mtime option)" + bool "Enable -mtime: modified time matching" default n depends on BUSYBOX_CONFIG_FIND help @@ -30,7 +30,7 @@ config BUSYBOX_CONFIG_FEATURE_FIND_MTIME files, in days. config BUSYBOX_CONFIG_FEATURE_FIND_MMIN - bool "Enable modified time matching (-mmin option)" + bool "Enable -mmin: modified time matching by minutes" default n depends on BUSYBOX_CONFIG_FIND help @@ -38,14 +38,14 @@ config BUSYBOX_CONFIG_FEATURE_FIND_MMIN files, in minutes. config BUSYBOX_CONFIG_FEATURE_FIND_PERM - bool "Enable permissions matching (-perm option)" + bool "Enable -perm: permissions matching" default y depends on BUSYBOX_CONFIG_FIND help Enable searching based on file permissions. config BUSYBOX_CONFIG_FEATURE_FIND_TYPE - bool "Enable filetype matching (-type option)" + bool "Enable -type: file type matching (file/dir/link/...)" default y depends on BUSYBOX_CONFIG_FIND help @@ -53,21 +53,21 @@ config BUSYBOX_CONFIG_FEATURE_FIND_TYPE directory, socket, device, etc.). config BUSYBOX_CONFIG_FEATURE_FIND_XDEV - bool "Enable 'stay in filesystem' option (-xdev)" + bool "Enable -xdev: 'stay in filesystem'" default y depends on BUSYBOX_CONFIG_FIND help This option allows find to restrict searches to a single filesystem. config BUSYBOX_CONFIG_FEATURE_FIND_MAXDEPTH - bool "Enable -maxdepth N option" + bool "Enable -maxdepth N" default y depends on BUSYBOX_CONFIG_FIND help This option enables -maxdepth N option. config BUSYBOX_CONFIG_FEATURE_FIND_NEWER - bool "Enable -newer option for comparing file mtimes" + bool "Enable -newer: compare file modification times" default n depends on BUSYBOX_CONFIG_FIND help @@ -75,14 +75,14 @@ config BUSYBOX_CONFIG_FEATURE_FIND_NEWER a modified time that is more recent than the specified FILE. config BUSYBOX_CONFIG_FEATURE_FIND_INUM - bool "Enable inode number matching (-inum option)" + bool "Enable -inum: inode number matching" default n depends on BUSYBOX_CONFIG_FIND help Support the 'find -inum' option for searching by inode number. config BUSYBOX_CONFIG_FEATURE_FIND_EXEC - bool "Enable -exec option allowing execution of commands" + bool "Enable -exec: execute commands" default y depends on BUSYBOX_CONFIG_FIND help @@ -90,14 +90,14 @@ config BUSYBOX_CONFIG_FEATURE_FIND_EXEC the files matched. config BUSYBOX_CONFIG_FEATURE_FIND_USER - bool "Enable username/uid matching (-user option)" + bool "Enable -user: username/uid matching" default y depends on BUSYBOX_CONFIG_FIND help Support the 'find -user' option for searching by username or uid. config BUSYBOX_CONFIG_FEATURE_FIND_GROUP - bool "Enable group/gid matching (-group option)" + bool "Enable -group: group/gid matching" default y depends on BUSYBOX_CONFIG_FIND help @@ -113,7 +113,7 @@ config BUSYBOX_CONFIG_FEATURE_FIND_NOT the non-POSIX notation '-not'. config BUSYBOX_CONFIG_FEATURE_FIND_DEPTH - bool "Enable the -depth option" + bool "Enable -depth" default y depends on BUSYBOX_CONFIG_FIND help @@ -127,14 +127,14 @@ config BUSYBOX_CONFIG_FEATURE_FIND_PAREN Enable usage of parens '(' to specify logical order of arguments. config BUSYBOX_CONFIG_FEATURE_FIND_SIZE - bool "Enable -size option allowing matching for file size" + bool "Enable -size: file size matching" default y depends on BUSYBOX_CONFIG_FIND help Support the 'find -size' option for searching by file size. config BUSYBOX_CONFIG_FEATURE_FIND_PRUNE - bool "Enable -prune option allowing to exclude subdirectories" + bool "Enable -prune: exclude subdirectories" default y depends on BUSYBOX_CONFIG_FIND help @@ -142,7 +142,7 @@ config BUSYBOX_CONFIG_FEATURE_FIND_PRUNE exclusion .svn and CVS directories. config BUSYBOX_CONFIG_FEATURE_FIND_DELETE - bool "Enable -delete option allowing to delete files" + bool "Enable -delete: delete files/dirs" default n depends on BUSYBOX_CONFIG_FIND && BUSYBOX_CONFIG_FEATURE_FIND_DEPTH help @@ -151,21 +151,21 @@ config BUSYBOX_CONFIG_FEATURE_FIND_DELETE try to protect the user from doing stupid things. Use with care. config BUSYBOX_CONFIG_FEATURE_FIND_PATH - bool "Enable -path option allowing to match pathname patterns" + bool "Enable -path: match pathname with shell pattern" default y depends on BUSYBOX_CONFIG_FIND help The -path option matches whole pathname instead of just filename. config BUSYBOX_CONFIG_FEATURE_FIND_REGEX - bool "Enable -regex: match pathname to regex" + bool "Enable -regex: match pathname with regex" default y depends on BUSYBOX_CONFIG_FIND help The -regex option matches whole pathname against regular expression. config BUSYBOX_CONFIG_FEATURE_FIND_CONTEXT - bool "Enable -context option for matching security context" + bool "Enable -context: security context matching" default n depends on BUSYBOX_CONFIG_FIND && BUSYBOX_CONFIG_SELINUX help @@ -178,7 +178,7 @@ config BUSYBOX_CONFIG_GREP grep is used to search files for a specified pattern. config BUSYBOX_CONFIG_FEATURE_GREP_EGREP_ALIAS - bool "Support extended regular expressions (egrep & grep -E)" + bool "Enable extended regular expressions (egrep & grep -E)" default y depends on BUSYBOX_CONFIG_GREP help @@ -193,7 +193,7 @@ config BUSYBOX_CONFIG_FEATURE_GREP_FGREP_ALIAS help fgrep sees the search pattern as a normal string rather than regular expressions. - grep -F is always builtin, this just creates the fgrep alias. + grep -F always works, this just creates the fgrep alias. config BUSYBOX_CONFIG_FEATURE_GREP_CONTEXT bool "Enable before and after context flags (-A, -B and -C)" @@ -208,40 +208,39 @@ config BUSYBOX_CONFIG_XARGS bool "xargs" default y help - xargs is used to execute a specified command on + xargs is used to execute a specified command for every item from standard input. config BUSYBOX_CONFIG_FEATURE_XARGS_SUPPORT_CONFIRMATION - bool "Enable prompt and confirmation option -p" + bool "Enable -p: prompt and confirmation" default y depends on BUSYBOX_CONFIG_XARGS help - Support prompt the user about whether to run each command + Support -p: prompt the user whether to run each command line and read a line from the terminal. config BUSYBOX_CONFIG_FEATURE_XARGS_SUPPORT_QUOTES - bool "Enable support single and double quotes and backslash" + bool "Enable single and double quotes and backslash" default y depends on BUSYBOX_CONFIG_XARGS help - Default xargs unsupport single and double quotes - and backslash for can use aruments with spaces. + Support quoting in the input. config BUSYBOX_CONFIG_FEATURE_XARGS_SUPPORT_TERMOPT - bool "Enable support options -x" + bool "Enable -x: exit if -s or -n is exceeded" default y depends on BUSYBOX_CONFIG_XARGS help - Enable support exit if the size (see the -s or -n option) + Support -x: exit if the command size (see the -s or -n option) is exceeded. config BUSYBOX_CONFIG_FEATURE_XARGS_SUPPORT_ZERO_TERM - bool "Enable null terminated option -0" + bool "Enable -0: NUL-terminated input" default y depends on BUSYBOX_CONFIG_XARGS help - Enable input filenames are terminated by a null character - instead of by whitespace, and the quotes and backslash + Support -0: input items are terminated by a NUL character + instead of whitespace, and the quotes and backslash are not special. endmenu diff --git a/package/busybox/config/init/Config.in b/package/busybox/config/init/Config.in index 75f329817..949889563 100644 --- a/package/busybox/config/init/Config.in +++ b/package/busybox/config/init/Config.in @@ -93,6 +93,26 @@ config BUSYBOX_CONFIG_HALT help Stop all processes and either halt, reboot, or power off the system. +config BUSYBOX_CONFIG_FEATURE_CALL_TELINIT + bool "Call telinit on shutdown and reboot" + default n + depends on BUSYBOX_CONFIG_HALT && !BUSYBOX_CONFIG_INIT + help + Call an external program (normally telinit) to facilitate + a switch to a proper runlevel. + + This option is only available if you selected halt and friends, + but did not select init. + +config BUSYBOX_CONFIG_TELINIT_PATH + string "Path to telinit executable" + default "/sbin/telinit" + depends on BUSYBOX_CONFIG_FEATURE_CALL_TELINIT + help + When busybox halt and friends have to call external telinit + to facilitate proper shutdown, this path is to be used when + locating telinit executable. + config BUSYBOX_CONFIG_MESG bool "mesg" default y diff --git a/package/busybox/config/libbb/Config.in b/package/busybox/config/libbb/Config.in index e456dd8e7..8016ef080 100644 --- a/package/busybox/config/libbb/Config.in +++ b/package/busybox/config/libbb/Config.in @@ -13,7 +13,7 @@ config BUSYBOX_CONFIG_PASSWORD_MINLEN Minimum allowable password length. config BUSYBOX_CONFIG_MD5_SIZE_VS_SPEED - int "MD5: Trade Bytes for Speed" + int "MD5: Trade bytes for speed (0:fast, 3:slow)" default 2 range 0 3 help @@ -102,6 +102,28 @@ config BUSYBOX_CONFIG_FEATURE_EDITING_FANCY_PROMPT Setting this option allows for prompts to use things like \w and \$ and escape codes. +config BUSYBOX_CONFIG_FEATURE_EDITING_ASK_TERMINAL + bool "Query cursor position from terminal" + default n + depends on BUSYBOX_CONFIG_FEATURE_EDITING + help + Allow usage of "ESC [ 6 n" sequence. Terminal answers back with + current cursor position. This information is used to make line + editing more robust in some cases. + If you are not sure whether your terminals respond to this code + correctly, or want to save on code size (about 300 bytes), + then do not turn this option on. + +config BUSYBOX_CONFIG_FEATURE_NON_POSIX_CP + bool "Non-POSIX, but safer, copying to special nodes" + default y + help + With this option, "cp file symlink" will delete symlink + and create a regular file. This does not conform to POSIX, + but prevents a symlink attack. + Similarly, "cp file device" will not send file's data + to the device. + config BUSYBOX_CONFIG_FEATURE_VERBOSE_CP_MESSAGE bool "Give more precise messages when copy fails (cp, mv etc)" default n @@ -151,4 +173,5 @@ config BUSYBOX_CONFIG_FEATURE_HWIB help Support for printing infiniband addresses in network applets. + endmenu diff --git a/package/busybox/config/loginutils/Config.in b/package/busybox/config/loginutils/Config.in index d88876cf9..4498e4e2d 100644 --- a/package/busybox/config/loginutils/Config.in +++ b/package/busybox/config/loginutils/Config.in @@ -97,6 +97,13 @@ config BUSYBOX_CONFIG_ADDGROUP help Utility for creating a new group account. +config BUSYBOX_CONFIG_FEATURE_ADDGROUP_LONG_OPTIONS + bool "Enable long options" + default n + depends on BUSYBOX_CONFIG_ADDGROUP && BUSYBOX_CONFIG_LONG_OPTS + help + Support long options for the addgroup applet. + config BUSYBOX_CONFIG_FEATURE_ADDUSER_TO_GROUP bool "Support for adding users to groups" default n @@ -141,10 +148,26 @@ config BUSYBOX_CONFIG_ADDUSER config BUSYBOX_CONFIG_FEATURE_ADDUSER_LONG_OPTIONS bool "Enable long options" default n - depends on BUSYBOX_CONFIG_ADDUSER && BUSYBOX_CONFIG_GETOPT_LONG + depends on BUSYBOX_CONFIG_ADDUSER && BUSYBOX_CONFIG_LONG_OPTS help Support long options for the adduser applet. +config BUSYBOX_CONFIG_FIRST_SYSTEM_ID + int "First valid system uid or gid for adduser and addgroup" + depends on BUSYBOX_CONFIG_ADDUSER || BUSYBOX_CONFIG_ADDGROUP + range 0 64900 + default 100 + help + First valid system uid or gid for adduser and addgroup + +config BUSYBOX_CONFIG_LAST_SYSTEM_ID + int "Last valid system uid or gid for adduser and addgroup" + depends on BUSYBOX_CONFIG_ADDUSER || BUSYBOX_CONFIG_ADDGROUP + range 0 64900 + default 999 + help + Last valid system uid or gid for adduser and addgroup + config BUSYBOX_CONFIG_DELUSER bool "deluser" default n diff --git a/package/busybox/config/miscutils/Config.in b/package/busybox/config/miscutils/Config.in index 1ddfb940a..9dce72ebd 100644 --- a/package/busybox/config/miscutils/Config.in +++ b/package/busybox/config/miscutils/Config.in @@ -19,6 +19,28 @@ config BUSYBOX_CONFIG_BBCONFIG The bbconfig applet will print the config file with which busybox was built. +config BUSYBOX_CONFIG_BEEP + bool "beep" + default n + help + The beep applets beeps in a given freq/Hz. + +config BUSYBOX_CONFIG_FEATURE_BEEP_FREQ + int "default frequency" + range 0 2147483647 + default 4000 + depends on BUSYBOX_CONFIG_BEEP + help + Frequency for default beep. + +config BUSYBOX_CONFIG_FEATURE_BEEP_LENGTH_MS + int "default length" + range 0 2147483647 + default 30 + depends on BUSYBOX_CONFIG_BEEP + help + Length in ms for default beep. + config BUSYBOX_CONFIG_CHAT bool "chat" default n @@ -250,6 +272,20 @@ config BUSYBOX_CONFIG_FBSPLASH "NN" (ASCII decimal number) - percentage to show on progress bar "exit" - well you guessed it +config BUSYBOX_CONFIG_FLASH_LOCK + bool "flash_lock" + default n + help + The flash_lock binary from mtd-utils as of git head 5ec0c10d0. This + utility locks part or all of the flash device. + +config BUSYBOX_CONFIG_FLASH_UNLOCK + bool "flash_unlock" + default n + help + The flash_unlock binary from mtd-utils as of git head 5ec0c10d0. This + utility unlocks part or all of the flash device. + config BUSYBOX_CONFIG_FLASH_ERASEALL bool "flash_eraseall" default n @@ -576,6 +612,12 @@ config BUSYBOX_CONFIG_TTYSIZE error, but returns default 80x24. Usage in shell scripts: width=`ttysize w`. +config BUSYBOX_CONFIG_VOLNAME + bool "volname" + default n + help + Prints a CD-ROM volume name. + config BUSYBOX_CONFIG_WATCHDOG bool "watchdog" default y diff --git a/package/busybox/config/modutils/Config.in b/package/busybox/config/modutils/Config.in index e2f880faf..9ec54b1e9 100644 --- a/package/busybox/config/modutils/Config.in +++ b/package/busybox/config/modutils/Config.in @@ -90,12 +90,8 @@ config BUSYBOX_CONFIG_MODPROBE Handle the loading of modules, and their dependencies on a high level. - Note that in the state, modprobe does not understand multiple - module options from the configuration file. See option below. - config BUSYBOX_CONFIG_FEATURE_MODPROBE_BLACKLIST - bool - prompt "Blacklist support" + bool "Blacklist support" default n depends on BUSYBOX_CONFIG_MODPROBE help diff --git a/package/busybox/config/networking/Config.in b/package/busybox/config/networking/Config.in index 0bde42b14..35dae5f59 100644 --- a/package/busybox/config/networking/Config.in +++ b/package/busybox/config/networking/Config.in @@ -12,6 +12,17 @@ config BUSYBOX_CONFIG_FEATURE_IPV6 Enable IPv6 support in busybox. This adds IPv6 support in the networking applets. +config BUSYBOX_CONFIG_FEATURE_UNIX_LOCAL + bool "Enable Unix domain socket support (usually not needed)" + default n + help + Enable Unix domain socket support in all busybox networking + applets. Address of the form local:/path/to/unix/socket + will be recognized. + + This extension is almost never used in real world usage. + You most likely want to say N. + config BUSYBOX_CONFIG_FEATURE_PREFER_IPV4_ADDRESS bool "Prefer IPv4 addresses from DNS queries" default y @@ -121,7 +132,7 @@ config BUSYBOX_CONFIG_FTPPUT config BUSYBOX_CONFIG_FEATURE_FTPGETPUT_LONG_OPTIONS bool "Enable long options in ftpget/ftpput" default n - depends on BUSYBOX_CONFIG_GETOPT_LONG && (BUSYBOX_CONFIG_FTPGET || BUSYBOX_CONFIG_FTPPUT) + depends on BUSYBOX_CONFIG_LONG_OPTS && (BUSYBOX_CONFIG_FTPGET || BUSYBOX_CONFIG_FTPPUT) help Support long options for the ftpget/ftpput applet. @@ -154,14 +165,6 @@ config BUSYBOX_CONFIG_FEATURE_HTTPD_USE_SENDFILE When enabled, httpd will use the kernel sendfile() function instead of read/write loop. -config BUSYBOX_CONFIG_FEATURE_HTTPD_RELOAD_CONFIG_SIGHUP - bool "Support reloading of global config file on HUP signal" - default y - depends on BUSYBOX_CONFIG_HTTPD - help - This option enables processing of SIGHUP to reload cached - configuration settings. - config BUSYBOX_CONFIG_FEATURE_HTTPD_SETUID bool "Enable -u option" default n @@ -188,14 +191,6 @@ config BUSYBOX_CONFIG_FEATURE_HTTPD_AUTH_MD5 Enables basic per URL authentication from /etc/httpd.conf using md5 passwords. -config BUSYBOX_CONFIG_FEATURE_HTTPD_CONFIG_WITH_MIME_TYPES - bool "Support loading additional MIME types at run-time" - default y - depends on BUSYBOX_CONFIG_HTTPD - help - This option enables support for additional MIME types at - run-time to be specified in the configuration file. - config BUSYBOX_CONFIG_FEATURE_HTTPD_CGI bool "Support Common Gateway Interface (CGI)" default y @@ -312,6 +307,12 @@ config BUSYBOX_CONFIG_IFENSLAVE Userspace application to bind several interfaces to a logical interface (use with kernel bonding driver). +config BUSYBOX_CONFIG_IFPLUGD + bool "ifplugd" + default n + help + Network interface plug detection daemon. + config BUSYBOX_CONFIG_IFUPDOWN bool "ifupdown" default n @@ -577,7 +578,7 @@ config BUSYBOX_CONFIG_FEATURE_IPCALC_FANCY config BUSYBOX_CONFIG_FEATURE_IPCALC_LONG_OPTIONS bool "Enable long options" default n - depends on BUSYBOX_CONFIG_IPCALC && BUSYBOX_CONFIG_GETOPT_LONG + depends on BUSYBOX_CONFIG_IPCALC && BUSYBOX_CONFIG_LONG_OPTS help Support long options for the ipcalc applet. @@ -842,15 +843,14 @@ config BUSYBOX_CONFIG_TFTP_DEBUG default n depends on BUSYBOX_CONFIG_TFTP || BUSYBOX_CONFIG_TFTPD help - Enable debug settings for tftp. This is useful if you're running - into problems with tftp as the protocol doesn't help you much when - you run into problems. + Make tftp[d] print debugging messages on stderr. + This is useful if you are diagnosing a bug in tftp[d]. config BUSYBOX_CONFIG_TRACEROUTE bool "traceroute" default y help - Utility to trace the route of IP packets + Utility to trace the route of IP packets. config BUSYBOX_CONFIG_FEATURE_TRACEROUTE_VERBOSE bool "Enable verbose output" @@ -916,7 +916,7 @@ config BUSYBOX_CONFIG_FEATURE_WGET_AUTHENTICATION config BUSYBOX_CONFIG_FEATURE_WGET_LONG_OPTIONS bool "Enable long options" default y - depends on BUSYBOX_CONFIG_WGET && BUSYBOX_CONFIG_GETOPT_LONG + depends on BUSYBOX_CONFIG_WGET && BUSYBOX_CONFIG_LONG_OPTS help Support long options for the wget applet. diff --git a/package/busybox/config/networking/udhcp/Config.in b/package/busybox/config/networking/udhcp/Config.in index 10e06d5e3..22156232f 100644 --- a/package/busybox/config/networking/udhcp/Config.in +++ b/package/busybox/config/networking/udhcp/Config.in @@ -75,11 +75,16 @@ config BUSYBOX_CONFIG_FEATURE_UDHCP_PORT This feature is typically not needed. config BUSYBOX_CONFIG_UDHCP_DEBUG - bool "Compile udhcp with noisy debugging messages" - default n - depends on BUSYBOX_CONFIG_APP_UDHCPD || BUSYBOX_CONFIG_APP_UDHCPC + int "Maximum verbosity level for udhcp applets (0..9)" + default 0 + range 0 9 + depends on BUSYBOX_CONFIG_APP_UDHCPD || BUSYBOX_CONFIG_APP_UDHCPC || BUSYBOX_CONFIG_APP_DHCPRELAY help - If selected, udhcpd will output extra debugging output. + Verbosity can be increased with multiple -v options. + This options controls how high it can be cranked up. + + Bigger values result in bigger code. Levels above 1 + are very verbose and useful for debugging only. config BUSYBOX_CONFIG_FEATURE_UDHCP_RFC3397 bool "Support for RFC3397 domain search (experimental)" diff --git a/package/busybox/config/procps/Config.in b/package/busybox/config/procps/Config.in index 734359260..bd21cb377 100644 --- a/package/busybox/config/procps/Config.in +++ b/package/busybox/config/procps/Config.in @@ -91,13 +91,13 @@ config BUSYBOX_CONFIG_PS ps gives a snapshot of the current processes. config BUSYBOX_CONFIG_FEATURE_PS_WIDE - bool "Enable argument for wide output (-w)" + bool "Enable wide output option (-w)" default n depends on BUSYBOX_CONFIG_PS help Support argument 'w' for wide output. - If given once, 132 chars are printed and given more than - one, the length is unlimited. + If given once, 132 chars are printed, and if given more + than once, the length is unlimited. config BUSYBOX_CONFIG_FEATURE_PS_TIME bool "Enable time and elapsed time output" @@ -106,6 +106,13 @@ config BUSYBOX_CONFIG_FEATURE_PS_TIME help Support -o time and -o etime output specifiers. +config BUSYBOX_CONFIG_FEATURE_PS_ADDITIONAL_COLUMNS + bool "Enable additional ps columns" + default n + depends on BUSYBOX_CONFIG_PS && BUSYBOX_CONFIG_DESKTOP + help + Support -o rgroup, -o ruser, -o nice output specifiers. + config BUSYBOX_CONFIG_FEATURE_PS_UNUSUAL_SYSTEMS bool "Support Linux prior to 2.4.0 and non-ELF systems" default n diff --git a/package/busybox/config/selinux/Config.in b/package/busybox/config/selinux/Config.in index b5b2d663e..dbd960630 100644 --- a/package/busybox/config/selinux/Config.in +++ b/package/busybox/config/selinux/Config.in @@ -16,7 +16,7 @@ config BUSYBOX_CONFIG_CHCON config BUSYBOX_CONFIG_FEATURE_CHCON_LONG_OPTIONS bool "Enable long options" default n - depends on BUSYBOX_CONFIG_CHCON && BUSYBOX_CONFIG_GETOPT_LONG + depends on BUSYBOX_CONFIG_CHCON && BUSYBOX_CONFIG_LONG_OPTS help Support long options for the chcon applet. @@ -67,7 +67,7 @@ config BUSYBOX_CONFIG_RUNCON config BUSYBOX_CONFIG_FEATURE_RUNCON_LONG_OPTIONS bool "Enable long options" default n - depends on BUSYBOX_CONFIG_RUNCON && BUSYBOX_CONFIG_GETOPT_LONG + depends on BUSYBOX_CONFIG_RUNCON && BUSYBOX_CONFIG_LONG_OPTS help Support long options for the runcon applet. diff --git a/package/busybox/config/shell/Config.in b/package/busybox/config/shell/Config.in index 233c3a8f4..6ff3e3df4 100644 --- a/package/busybox/config/shell/Config.in +++ b/package/busybox/config/shell/Config.in @@ -24,9 +24,9 @@ config BUSYBOX_CONFIG_FEATURE_SH_IS_HUSH #### select LASH #### bool "lash" -config BUSYBOX_CONFIG_FEATURE_SH_IS_MSH - select BUSYBOX_CONFIG_MSH - bool "msh" +####config FEATURE_SH_IS_MSH +#### select MSH +#### bool "msh" config BUSYBOX_CONFIG_FEATURE_SH_IS_NONE bool "none" @@ -43,9 +43,6 @@ config BUSYBOX_CONFIG_ASH shell (by Herbert Xu), which was created by porting the 'ash' shell (written by Kenneth Almquist) from NetBSD. -comment "Ash Shell Options" - depends on BUSYBOX_CONFIG_ASH - config BUSYBOX_CONFIG_ASH_BASH_COMPAT bool "bash-compatible extensions" default y @@ -169,16 +166,23 @@ config BUSYBOX_CONFIG_HUSH It does not handle select, aliases, brace expansion, tilde expansion, &>file and >&file redirection of stdout+stderr. +config BUSYBOX_CONFIG_HUSH_BASH_COMPAT + bool "bash-compatible extensions" + default y + depends on BUSYBOX_CONFIG_HUSH + help + Enable bash-compatible extensions. + config BUSYBOX_CONFIG_HUSH_HELP bool "help builtin" - default n + default y depends on BUSYBOX_CONFIG_HUSH help Enable help builtin in hush. Code size + ~1 kbyte. config BUSYBOX_CONFIG_HUSH_INTERACTIVE bool "Interactive mode" - default n + default y depends on BUSYBOX_CONFIG_HUSH help Enable interactive mode (prompt and command editing). @@ -188,7 +192,7 @@ config BUSYBOX_CONFIG_HUSH_INTERACTIVE config BUSYBOX_CONFIG_HUSH_JOB bool "Job control" - default n + default y depends on BUSYBOX_CONFIG_HUSH_INTERACTIVE help Enable job control: Ctrl-Z backgrounds, Ctrl-C interrupts current @@ -199,39 +203,53 @@ config BUSYBOX_CONFIG_HUSH_JOB config BUSYBOX_CONFIG_HUSH_TICK bool "Process substitution" - default n + default y depends on BUSYBOX_CONFIG_HUSH help Enable process substitution `command` and $(command) in hush. config BUSYBOX_CONFIG_HUSH_IF bool "Support if/then/elif/else/fi" - default n + default y depends on BUSYBOX_CONFIG_HUSH help Enable if/then/elif/else/fi in hush. config BUSYBOX_CONFIG_HUSH_LOOPS bool "Support for, while and until loops" - default n + default y depends on BUSYBOX_CONFIG_HUSH help Enable for, while and until loops in hush. config BUSYBOX_CONFIG_HUSH_CASE bool "Support case ... esac statement" - default n + default y depends on BUSYBOX_CONFIG_HUSH help Enable case ... esac statement in hush. +400 bytes. config BUSYBOX_CONFIG_HUSH_FUNCTIONS bool "Support funcname() { commands; } syntax" - default n + default y depends on BUSYBOX_CONFIG_HUSH help Enable support for shell functions in hush. +800 bytes. +config BUSYBOX_CONFIG_HUSH_LOCAL + bool "Support local builtin" + default y + depends on BUSYBOX_CONFIG_HUSH_FUNCTIONS + help + Enable support for local variables in functions. + +config BUSYBOX_CONFIG_HUSH_EXPORT_N + bool "Support export '-n' option" + default y + depends on BUSYBOX_CONFIG_HUSH + help + Enable support for export '-n' option in hush. It is a bash extension. + config BUSYBOX_CONFIG_LASH bool "lash (deprecated: aliased to hush)" default n @@ -242,6 +260,7 @@ config BUSYBOX_CONFIG_LASH config BUSYBOX_CONFIG_MSH bool "msh (deprecated: please use hush)" default n + select BUSYBOX_CONFIG_HUSH help msh is deprecated and will be removed, please migrate to hush. If there is a feature msh has but hush does not, please let us know. @@ -254,9 +273,6 @@ config BUSYBOX_CONFIG_MSH # It uses only vfork, so it can be used on uClinux systems. -comment "Bourne Shell Options" - depends on BUSYBOX_CONFIG_MSH || BUSYBOX_CONFIG_LASH || BUSYBOX_CONFIG_HUSH || BUSYBOX_CONFIG_ASH - config BUSYBOX_CONFIG_SH_MATH_SUPPORT bool "POSIX math support" default y diff --git a/package/busybox/config/util-linux/Config.in b/package/busybox/config/util-linux/Config.in index 526ea00cc..9d5462b26 100644 --- a/package/busybox/config/util-linux/Config.in +++ b/package/busybox/config/util-linux/Config.in @@ -250,6 +250,13 @@ config BUSYBOX_CONFIG_GETOPT written by others, this utility may be for you. Most people will wisely leave this disabled. +config BUSYBOX_CONFIG_FEATURE_GETOPT_LONG + bool "Support option -l" + default n if BUSYBOX_CONFIG_LONG_OPTS + depends on BUSYBOX_CONFIG_GETOPT + help + Enable support for long options (option -l). + config BUSYBOX_CONFIG_HEXDUMP bool "hexdump" default y @@ -286,7 +293,7 @@ config BUSYBOX_CONFIG_HWCLOCK config BUSYBOX_CONFIG_FEATURE_HWCLOCK_LONG_OPTIONS bool "Support long options (--hctosys,...)" default n - depends on BUSYBOX_CONFIG_HWCLOCK && BUSYBOX_CONFIG_GETOPT_LONG + depends on BUSYBOX_CONFIG_HWCLOCK && BUSYBOX_CONFIG_LONG_OPTS help By default, the hwclock utility only uses short options. If you are overly fond of its long options, such as --hctosys, --utc, etc) @@ -399,15 +406,12 @@ config BUSYBOX_CONFIG_MKSWAP Once you have created swap space using 'mkswap' you need to enable the swap space using the 'swapon' utility. -config BUSYBOX_CONFIG_FEATURE_MKSWAP_V0 - bool "Version 0 support" +config BUSYBOX_CONFIG_FEATURE_MKSWAP_UUID + bool "UUID support" default n depends on BUSYBOX_CONFIG_MKSWAP -# depends on MKSWAP && BUSYBOX_CONFIG_DEPRECATED help - Enable support for the old v0 style. - If your kernel is older than 2.1.117, then v0 support is the - only option. + Generate swap spaces with universally unique identifiers. config BUSYBOX_CONFIG_MORE bool "more" @@ -764,6 +768,13 @@ config BUSYBOX_CONFIG_SCRIPT help The script makes typescript of terminal session. +config BUSYBOX_CONFIG_SCRIPTREPLAY + bool "scriptreplay" + default n + help + This program replays a typescript, using timing information + given by script -t. + config BUSYBOX_CONFIG_SETARCH bool "setarch" default n diff --git a/package/busybox/patches/000-autoconf.patch b/package/busybox/patches/000-autoconf.patch index 8cb7a4cc7..d0a6f6127 100644 --- a/package/busybox/patches/000-autoconf.patch +++ b/package/busybox/patches/000-autoconf.patch @@ -1,18 +1,18 @@ --- a/applets/Kbuild +++ b/applets/Kbuild -@@ -18,13 +18,13 @@ HOSTCFLAGS_usage.o = -I$(srctree)/includ +@@ -27,13 +27,13 @@ HOSTCFLAGS_usage.o = -I$(srctree_slash)i applets/applets.o: include/usage_compressed.h include/applet_tables.h --applets/usage: .config $(srctree)/applets/usage_compressed -+applets/usage: .config $(srctree)/applets/usage_compressed include/autoconf.h +-applets/usage: .config $(srctree_slash)applets/usage_compressed ++applets/usage: .config $(srctree_slash)applets/usage_compressed include/autoconf.h applets/applet_tables: .config quiet_cmd_gen_usage_compressed = GEN include/usage_compressed.h - cmd_gen_usage_compressed = $(srctree)/applets/usage_compressed include/usage_compressed.h applets + cmd_gen_usage_compressed = $(srctree_slash)applets/usage_compressed include/usage_compressed.h applets --include/usage_compressed.h: applets/usage $(srctree)/applets/usage_compressed -+include/usage_compressed.h: applets/usage $(srctree)/applets/usage_compressed include/autoconf.h +-include/usage_compressed.h: applets/usage $(srctree_slash)applets/usage_compressed ++include/usage_compressed.h: applets/usage $(srctree_slash)applets/usage_compressed include/autoconf.h $(call cmd,gen_usage_compressed) quiet_cmd_gen_applet_tables = GEN include/applet_tables.h diff --git a/package/busybox/patches/003-brctl_show_fix.patch b/package/busybox/patches/003-brctl_show_fix.patch index f3fc40288..b921c7890 100644 --- a/package/busybox/patches/003-brctl_show_fix.patch +++ b/package/busybox/patches/003-brctl_show_fix.patch @@ -4,23 +4,23 @@ "setageing\0" "setfd\0" "sethello\0" "setmaxage\0" "setpathcost\0" "setportprio\0" "setbridgeprio\0" ) -- USE_FEATURE_BRCTL_SHOW("showmacs\0" "show\0"); -+ USE_FEATURE_BRCTL_SHOW("show\0"); +- IF_FEATURE_BRCTL_SHOW("showmacs\0" "show\0"); ++ IF_FEATURE_BRCTL_SHOW("show\0"); enum { ARG_addbr = 0, ARG_delbr, ARG_addif, ARG_delif - USE_FEATURE_BRCTL_FANCY(, + IF_FEATURE_BRCTL_FANCY(, @@ -112,7 +112,7 @@ int brctl_main(int argc UNUSED_PARAM, ch ARG_setageing, ARG_setfd, ARG_sethello, ARG_setmaxage, ARG_setpathcost, ARG_setportprio, ARG_setbridgeprio ) -- USE_FEATURE_BRCTL_SHOW(, ARG_showmacs, ARG_show) -+ USE_FEATURE_BRCTL_SHOW(, ARG_show) +- IF_FEATURE_BRCTL_SHOW(, ARG_showmacs, ARG_show) ++ IF_FEATURE_BRCTL_SHOW(, ARG_show) }; int fd; --- a/networking/Config.in +++ b/networking/Config.in -@@ -66,12 +66,12 @@ config FEATURE_BRCTL_FANCY +@@ -77,12 +77,12 @@ config FEATURE_BRCTL_FANCY This adds about 600 bytes. config FEATURE_BRCTL_SHOW diff --git a/package/busybox/patches/110-wget_getopt_fix.patch b/package/busybox/patches/110-wget_getopt_fix.patch index abb03d49f..617679eab 100644 --- a/package/busybox/patches/110-wget_getopt_fix.patch +++ b/package/busybox/patches/110-wget_getopt_fix.patch @@ -1,6 +1,6 @@ --- a/networking/wget.c +++ b/networking/wget.c -@@ -485,7 +485,7 @@ int wget_main(int argc UNUSED_PARAM, cha +@@ -653,7 +653,7 @@ int wget_main(int argc UNUSED_PARAM, cha // "tries\0" Required_argument "t" // "timeout\0" Required_argument "T" /* Ignored (we always use PASV): */ diff --git a/package/busybox/patches/240-udhcpc_retries.patch b/package/busybox/patches/240-udhcpc_retries.patch index 81f120d8e..bfcc02b7f 100644 --- a/package/busybox/patches/240-udhcpc_retries.patch +++ b/package/busybox/patches/240-udhcpc_retries.patch @@ -1,6 +1,6 @@ --- a/networking/udhcp/dhcpc.c +++ b/networking/udhcp/dhcpc.c -@@ -363,7 +363,7 @@ int udhcpc_main(int argc UNUSED_PARAM, c +@@ -380,7 +380,7 @@ int udhcpc_main(int argc UNUSED_PARAM, c switch (state) { case INIT_SELECTING: @@ -8,13 +8,13 @@ + if (!discover_retries || packet_num < discover_retries) { if (packet_num == 0) xid = random_xid(); - -@@ -394,7 +394,7 @@ int udhcpc_main(int argc UNUSED_PARAM, c + /* broadcast */ +@@ -409,7 +409,7 @@ int udhcpc_main(int argc UNUSED_PARAM, c + packet_num = 0; continue; - case RENEW_REQUESTED: case REQUESTING: - if (packet_num < discover_retries) { + if (!discover_retries || packet_num < discover_retries) { - /* send request packet */ - if (state == RENEW_REQUESTED) /* unicast */ - send_renew(xid, server_addr, requested_ip); + /* send broadcast select packet */ + send_select(xid, server_addr, requested_ip); + timeout = discover_timeout; diff --git a/package/busybox/patches/241-udhcpc-oversized_packets.patch b/package/busybox/patches/241-udhcpc-oversized_packets.patch index 405a7a52e..0ee4c542e 100644 --- a/package/busybox/patches/241-udhcpc-oversized_packets.patch +++ b/package/busybox/patches/241-udhcpc-oversized_packets.patch @@ -1,39 +1,40 @@ --- a/networking/udhcp/packet.c +++ b/networking/udhcp/packet.c -@@ -120,6 +120,10 @@ uint16_t FAST_FUNC udhcp_checksum(void * +@@ -164,6 +164,11 @@ uint16_t FAST_FUNC udhcp_checksum(void * return ~sum; } -+int udhcp_get_payload_len(struct dhcpMessage *payload) ++int udhcp_get_payload_len(struct dhcp_packet *dhcp_pkt) +{ -+ return sizeof(struct dhcpMessage) - DHCP_OPTIONS_BUFSIZE + end_option(payload->options) + sizeof(payload->options[0]); ++ return sizeof(struct dhcp_packet) - DHCP_OPTIONS_BUFSIZE + end_option(dhcp_pkt->options) + sizeof(dhcp_pkt->options[0]); +} - ++ /* Construct a ip/udp header for a packet, send packet */ - int FAST_FUNC udhcp_send_raw_packet(struct dhcpMessage *payload, -@@ -132,11 +136,7 @@ int FAST_FUNC udhcp_send_raw_packet(stru + int FAST_FUNC udhcp_send_raw_packet(struct dhcp_packet *dhcp_pkt, + uint32_t source_ip, int source_port, +@@ -175,11 +180,7 @@ int FAST_FUNC udhcp_send_raw_packet(stru int fd; int result = -1; const char *msg; - - enum { -- IP_UPD_DHCP_SIZE = sizeof(struct udp_dhcp_packet) - CONFIG_UDHCPC_SLACK_FOR_BUGGY_SERVERS, -- UPD_DHCP_SIZE = IP_UPD_DHCP_SIZE - offsetof(struct udp_dhcp_packet, udp), +- IP_UPD_DHCP_SIZE = sizeof(struct ip_udp_dhcp_packet) - CONFIG_UDHCPC_SLACK_FOR_BUGGY_SERVERS, +- UPD_DHCP_SIZE = IP_UPD_DHCP_SIZE - offsetof(struct ip_udp_dhcp_packet, udp), - }; -+ int p_len = udhcp_get_payload_len(payload); ++ int p_len = udhcp_get_payload_len(dhcp_pkt); fd = socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_IP)); if (fd < 0) { -@@ -146,7 +146,7 @@ int FAST_FUNC udhcp_send_raw_packet(stru +@@ -189,7 +190,7 @@ int FAST_FUNC udhcp_send_raw_packet(stru memset(&dest, 0, sizeof(dest)); memset(&packet, 0, sizeof(packet)); -- packet.data = *payload; /* struct copy */ -+ memcpy(&(packet.data), payload, p_len); +- packet.data = *dhcp_pkt; /* struct copy */ ++ memcpy(&(packet.data), dhcp_pkt, p_len); dest.sll_family = AF_PACKET; dest.sll_protocol = htons(ETH_P_IP); -@@ -163,23 +163,18 @@ int FAST_FUNC udhcp_send_raw_packet(stru +@@ -206,24 +207,19 @@ int FAST_FUNC udhcp_send_raw_packet(stru packet.ip.daddr = dest_ip; packet.udp.source = htons(source_port); packet.udp.dest = htons(dest_port); @@ -58,18 +59,31 @@ - * If you need to change this: last byte of the packet is - * packet.data.options[end_option(packet.data.options)] - */ + udhcp_dump_packet(dhcp_pkt); - result = sendto(fd, &packet, IP_UPD_DHCP_SIZE, 0, + result = sendto(fd, &packet, p_len, 0, (struct sockaddr *) &dest, sizeof(dest)); msg = "sendto"; ret_close: -@@ -231,8 +226,7 @@ int FAST_FUNC udhcp_send_kernel_packet(s +@@ -245,10 +241,6 @@ int FAST_FUNC udhcp_send_kernel_packet(s + int result = -1; + const char *msg; + +- enum { +- DHCP_SIZE = sizeof(struct dhcp_packet) - CONFIG_UDHCPC_SLACK_FOR_BUGGY_SERVERS, +- }; +- + fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP); + if (fd < 0) { + msg = "socket(%s)"; +@@ -274,9 +266,8 @@ int FAST_FUNC udhcp_send_kernel_packet(s goto ret_close; } - /* Currently we send full-sized DHCP packets (see above) */ -- result = safe_write(fd, payload, DHCP_SIZE); -+ result = safe_write(fd, payload, udhcp_get_payload_len(payload)); + udhcp_dump_packet(dhcp_pkt); +- result = safe_write(fd, dhcp_pkt, DHCP_SIZE); ++ result = safe_write(fd, dhcp_pkt, udhcp_get_payload_len(dhcp_pkt)); msg = "write"; ret_close: close(fd); diff --git a/package/busybox/patches/242-udhcpc_msgs.patch b/package/busybox/patches/242-udhcpc_msgs.patch index 0140c7854..1200c34c7 100644 --- a/package/busybox/patches/242-udhcpc_msgs.patch +++ b/package/busybox/patches/242-udhcpc_msgs.patch @@ -3,7 +3,7 @@ @@ -126,6 +126,7 @@ int FAST_FUNC send_decline(uint32_t xid, int FAST_FUNC send_discover(uint32_t xid, uint32_t requested) { - struct dhcpMessage packet; + struct dhcp_packet packet; + static int msgs = 0; init_packet(&packet, DHCPDISCOVER); diff --git a/package/busybox/patches/243-udhcpc_changed_ifindex.patch b/package/busybox/patches/243-udhcpc_changed_ifindex.patch index f0ab34d26..c5bf9123d 100644 --- a/package/busybox/patches/243-udhcpc_changed_ifindex.patch +++ b/package/busybox/patches/243-udhcpc_changed_ifindex.patch @@ -1,6 +1,6 @@ --- a/networking/udhcp/dhcpc.c +++ b/networking/udhcp/dhcpc.c -@@ -327,6 +327,12 @@ int udhcpc_main(int argc UNUSED_PARAM, c +@@ -342,6 +342,12 @@ int udhcpc_main(int argc UNUSED_PARAM, c /* silence "uninitialized!" warning */ unsigned timestamp_before_wait = timestamp_before_wait; @@ -8,7 +8,7 @@ + * member interfaces were added/removed or if the status of the + * bridge changed). + * Workaround: refresh it here before processing the next packet */ -+ udhcp_read_interface(client_config.interface, &client_config.ifindex, NULL, client_config.arp); ++ udhcp_read_interface(client_config.interface, &client_config.ifindex, NULL, client_config.client_mac); + //bb_error_msg("sockfd:%d, listen_mode:%d", sockfd, listen_mode); diff --git a/package/busybox/patches/244-udhcpc_cidrroute.patch b/package/busybox/patches/244-udhcpc_cidrroute.patch deleted file mode 100644 index 29313ae79..000000000 --- a/package/busybox/patches/244-udhcpc_cidrroute.patch +++ /dev/null @@ -1,18 +0,0 @@ ---- a/networking/udhcp/options.c -+++ b/networking/udhcp/options.c -@@ -48,6 +48,7 @@ const struct dhcp_option dhcp_options[] - #if ENABLE_FEATURE_UDHCP_RFC3397 - { OPTION_STR1035 | OPTION_LIST , 0x77 }, /* search */ - #endif -+ { OPTION_U8 | OPTION_LIST | OPTION_REQ, 0x79 }, /* cidr_static_routes */ - /* MSIE's "Web Proxy Autodiscovery Protocol" support */ - { OPTION_STRING , 0xfc }, /* wpad */ - -@@ -97,6 +98,7 @@ const char dhcp_option_strings[] ALIGN1 - #if ENABLE_FEATURE_UDHCP_RFC3397 - "search" "\0" - #endif -+ "cidrroute" "\0" /* cidr_static_routes */ - /* MSIE's "Web Proxy Autodiscovery Protocol" support */ - "wpad" "\0" - ; diff --git a/package/busybox/patches/250-ash_export-n.patch b/package/busybox/patches/250-ash_export-n.patch index f11cb8f79..6a420e221 100644 --- a/package/busybox/patches/250-ash_export-n.patch +++ b/package/busybox/patches/250-ash_export-n.patch @@ -1,6 +1,6 @@ --- a/shell/ash.c +++ b/shell/ash.c -@@ -12273,8 +12273,17 @@ exportcmd(int argc UNUSED_PARAM, char ** +@@ -12360,8 +12360,17 @@ exportcmd(int argc UNUSED_PARAM, char ** const char *p; char **aptr; int flag = argv[0][0] == 'r' ? VREADONLY : VEXPORT; @@ -19,7 +19,7 @@ aptr = argptr; name = *aptr; if (name) { -@@ -12286,10 +12295,12 @@ exportcmd(int argc UNUSED_PARAM, char ** +@@ -12373,10 +12382,12 @@ exportcmd(int argc UNUSED_PARAM, char ** vp = *findvar(hashvar(name), name); if (vp) { vp->flags |= flag; diff --git a/package/busybox/patches/300-netmsg.patch b/package/busybox/patches/300-netmsg.patch index 641449eca..aba146872 100644 --- a/package/busybox/patches/300-netmsg.patch +++ b/package/busybox/patches/300-netmsg.patch @@ -1,16 +1,16 @@ --- a/include/applets.h +++ b/include/applets.h -@@ -271,6 +271,7 @@ USE_MT(APPLET(mt, _BB_DIR_BIN, _BB_SUID_ - USE_MV(APPLET(mv, _BB_DIR_BIN, _BB_SUID_NEVER)) - USE_NAMEIF(APPLET(nameif, _BB_DIR_SBIN, _BB_SUID_NEVER)) - USE_NC(APPLET(nc, _BB_DIR_USR_BIN, _BB_SUID_NEVER)) -+USE_NETMSG(APPLET(netmsg, _BB_DIR_BIN, _BB_SUID_ALWAYS)) - USE_NETSTAT(APPLET(netstat, _BB_DIR_BIN, _BB_SUID_NEVER)) - USE_NICE(APPLET(nice, _BB_DIR_BIN, _BB_SUID_NEVER)) - USE_NMETER(APPLET(nmeter, _BB_DIR_USR_BIN, _BB_SUID_NEVER)) +@@ -278,6 +278,7 @@ IF_MT(APPLET(mt, _BB_DIR_BIN, _BB_SUID_D + IF_MV(APPLET(mv, _BB_DIR_BIN, _BB_SUID_DROP)) + IF_NAMEIF(APPLET(nameif, _BB_DIR_SBIN, _BB_SUID_DROP)) + IF_NC(APPLET(nc, _BB_DIR_USR_BIN, _BB_SUID_DROP)) ++IF_NETMSG(APPLET(netmsg, _BB_DIR_BIN, _BB_SUID_REQUIRE)) + IF_NETSTAT(APPLET(netstat, _BB_DIR_BIN, _BB_SUID_DROP)) + IF_NICE(APPLET(nice, _BB_DIR_BIN, _BB_SUID_DROP)) + IF_NMETER(APPLET(nmeter, _BB_DIR_USR_BIN, _BB_SUID_DROP)) --- a/include/usage.h +++ b/include/usage.h -@@ -3010,6 +3010,9 @@ +@@ -3101,6 +3101,9 @@ #endif @@ -18,11 +18,11 @@ +#define netmsg_full_usage "" + #define netstat_trivial_usage \ - "[-laentuwxr"USE_FEATURE_NETSTAT_WIDE("W")USE_FEATURE_NETSTAT_PRG("p")"]" + "[-laentuwxr"IF_FEATURE_NETSTAT_WIDE("W")IF_FEATURE_NETSTAT_PRG("p")"]" #define netstat_full_usage "\n\n" \ --- a/networking/Config.in +++ b/networking/Config.in -@@ -600,6 +600,12 @@ config NC +@@ -617,6 +617,12 @@ config NC A simple Unix utility which reads and writes data across network connections. @@ -37,7 +37,7 @@ default n --- a/networking/Kbuild +++ b/networking/Kbuild -@@ -24,6 +24,7 @@ lib-$(CONFIG_IP) += ip.o +@@ -25,6 +25,7 @@ lib-$(CONFIG_IP) += ip.o lib-$(CONFIG_IPCALC) += ipcalc.o lib-$(CONFIG_NAMEIF) += nameif.o lib-$(CONFIG_NC) += nc.o diff --git a/package/busybox/patches/340-lock_util.patch b/package/busybox/patches/340-lock_util.patch index 8cffe45fd..3e9055862 100644 --- a/package/busybox/patches/340-lock_util.patch +++ b/package/busybox/patches/340-lock_util.patch @@ -1,16 +1,16 @@ --- a/include/applets.h +++ b/include/applets.h -@@ -228,6 +228,7 @@ USE_LN(APPLET_NOEXEC(ln, ln, _BB_DIR_BIN - USE_LOAD_POLICY(APPLET(load_policy, _BB_DIR_USR_SBIN, _BB_SUID_NEVER)) - USE_LOADFONT(APPLET(loadfont, _BB_DIR_USR_SBIN, _BB_SUID_NEVER)) - USE_LOADKMAP(APPLET(loadkmap, _BB_DIR_SBIN, _BB_SUID_NEVER)) -+USE_LOCK(APPLET(lock, _BB_DIR_BIN, _BB_SUID_NEVER)) - USE_LOGGER(APPLET(logger, _BB_DIR_USR_BIN, _BB_SUID_NEVER)) - USE_LOGIN(APPLET(login, _BB_DIR_BIN, _BB_SUID_ALWAYS)) - USE_LOGNAME(APPLET_NOFORK(logname, logname, _BB_DIR_USR_BIN, _BB_SUID_NEVER, logname)) +@@ -233,6 +233,7 @@ IF_LN(APPLET_NOEXEC(ln, ln, _BB_DIR_BIN, + IF_LOAD_POLICY(APPLET(load_policy, _BB_DIR_USR_SBIN, _BB_SUID_DROP)) + IF_LOADFONT(APPLET(loadfont, _BB_DIR_USR_SBIN, _BB_SUID_DROP)) + IF_LOADKMAP(APPLET(loadkmap, _BB_DIR_SBIN, _BB_SUID_DROP)) ++IF_LOCK(APPLET(lock, _BB_DIR_BIN, _BB_SUID_DROP)) + IF_LOGGER(APPLET(logger, _BB_DIR_USR_BIN, _BB_SUID_DROP)) + IF_LOGIN(APPLET(login, _BB_DIR_BIN, _BB_SUID_REQUIRE)) + IF_LOGNAME(APPLET_NOFORK(logname, logname, _BB_DIR_USR_BIN, _BB_SUID_DROP, logname)) --- a/include/usage.h +++ b/include/usage.h -@@ -2246,6 +2246,9 @@ +@@ -2325,6 +2325,9 @@ #define loadkmap_example_usage \ "$ loadkmap < /etc/i18n/lang-keymap\n" @@ -18,11 +18,11 @@ +#define lock_full_usage "" + #define logger_trivial_usage \ - "[OPTION]... [MESSAGE]" + "[OPTIONS] [MESSAGE]" #define logger_full_usage "\n\n" \ --- a/miscutils/Config.in +++ b/miscutils/Config.in -@@ -420,6 +420,11 @@ config FEATURE_HDPARM_HDIO_GETSET_DMA +@@ -456,6 +456,11 @@ config FEATURE_HDPARM_HDIO_GETSET_DMA help Enables the 'hdparm -d' option to get/set using_dma flag. @@ -36,7 +36,7 @@ default n --- a/miscutils/Kbuild +++ b/miscutils/Kbuild -@@ -23,6 +23,7 @@ lib-$(CONFIG_INOTIFYD) += inotifyd.o +@@ -26,6 +26,7 @@ lib-$(CONFIG_INOTIFYD) += inotifyd.o lib-$(CONFIG_FEATURE_LAST_SMALL)+= last.o lib-$(CONFIG_FEATURE_LAST_FANCY)+= last_fancy.o lib-$(CONFIG_LESS) += less.o diff --git a/package/busybox/patches/350-httpd_redir.patch b/package/busybox/patches/350-httpd_redir.patch index 912cb6d49..3d3e041ce 100644 --- a/package/busybox/patches/350-httpd_redir.patch +++ b/package/busybox/patches/350-httpd_redir.patch @@ -1,24 +1,22 @@ --- a/include/usage.h +++ b/include/usage.h -@@ -1638,7 +1638,8 @@ - USE_FEATURE_HTTPD_BASIC_AUTH(" [-r realm]") \ - USE_FEATURE_HTTPD_AUTH_MD5(" [-m pass]") \ - " [-h home]" \ -- " [-d/-e string]" -+ " [-d/-e string]" \ +@@ -1693,6 +1693,7 @@ + IF_FEATURE_HTTPD_BASIC_AUTH(" [-r REALM]") \ + " [-h HOME]\n" \ + "or httpd -d/-e" IF_FEATURE_HTTPD_AUTH_MD5("/-m") " STRING" + " [-R [-H ]]" #define httpd_full_usage "\n\n" \ "Listen for incoming HTTP requests\n" \ "\nOptions:" \ -@@ -1656,6 +1657,8 @@ - "\n -h HOME Home directory (default .)" \ +@@ -1710,6 +1711,8 @@ + "\n -m STRING MD5 crypt STRING") \ "\n -e STRING HTML encode STRING" \ "\n -d STRING URL decode STRING" \ + "\n -R PATH Redirect target path" \ + "\n -H HOST Redirect target host" \ #define hwclock_trivial_usage \ - USE_FEATURE_HWCLOCK_LONG_OPTIONS( \ + IF_FEATURE_HWCLOCK_LONG_OPTIONS( \ --- a/networking/httpd.c +++ b/networking/httpd.c @@ -248,6 +248,8 @@ struct globals { @@ -29,7 +27,7 @@ + const char *redirect_host; Htaccess_IP *ip_a_d; /* config allow/deny lines */ - USE_FEATURE_HTTPD_BASIC_AUTH(const char *g_realm;) + IF_FEATURE_HTTPD_BASIC_AUTH(const char *g_realm;) @@ -294,6 +296,8 @@ struct globals { #define index_page (G.index_page ) #define found_mime_type (G.found_mime_type ) @@ -76,19 +74,19 @@ + c_opt_config_file, d_opt_decode_url, h_opt_home_httpd, - USE_FEATURE_HTTPD_ENCODE_URL_STR(e_opt_encode_url,) + IF_FEATURE_HTTPD_ENCODE_URL_STR(e_opt_encode_url,) @@ -2315,12 +2328,13 @@ int httpd_main(int argc UNUSED_PARAM, ch /* We do not "absolutize" path given by -h (home) opt. * If user gives relative path in -h, * $SCRIPT_FILENAME will not be set. */ - opt = getopt32(argv, "c:d:h:" + opt = getopt32(argv, "R:H:c:d:h:" - USE_FEATURE_HTTPD_ENCODE_URL_STR("e:") - USE_FEATURE_HTTPD_BASIC_AUTH("r:") - USE_FEATURE_HTTPD_AUTH_MD5("m:") - USE_FEATURE_HTTPD_SETUID("u:") + IF_FEATURE_HTTPD_ENCODE_URL_STR("e:") + IF_FEATURE_HTTPD_BASIC_AUTH("r:") + IF_FEATURE_HTTPD_AUTH_MD5("m:") + IF_FEATURE_HTTPD_SETUID("u:") "p:ifv", + &redirect_path, &redirect_host, &opt_c_configFile, &url_for_decode, &home_httpd - USE_FEATURE_HTTPD_ENCODE_URL_STR(, &url_for_encode) - USE_FEATURE_HTTPD_BASIC_AUTH(, &g_realm) + IF_FEATURE_HTTPD_ENCODE_URL_STR(, &url_for_encode) + IF_FEATURE_HTTPD_BASIC_AUTH(, &g_realm) diff --git a/package/busybox/patches/430-uniq_memleak.patch b/package/busybox/patches/430-uniq_memleak.patch deleted file mode 100644 index 48127a57c..000000000 --- a/package/busybox/patches/430-uniq_memleak.patch +++ /dev/null @@ -1,11 +0,0 @@ ---- a/coreutils/uniq.c -+++ b/coreutils/uniq.c -@@ -82,6 +82,8 @@ int uniq_main(int argc UNUSED_PARAM, cha - - if (!s0 || strncmp(e0, e1, max_chars)) { - break; -+ } else { -+ free(s1); - } - - ++dups; /* note: testing for overflow seems excessive. */ diff --git a/package/busybox/patches/470-insmod_search.patch b/package/busybox/patches/470-insmod_search.patch index cc7ca79ce..022ca24e6 100644 --- a/package/busybox/patches/470-insmod_search.patch +++ b/package/busybox/patches/470-insmod_search.patch @@ -119,7 +119,7 @@ } --- a/modutils/Config.in +++ b/modutils/Config.in -@@ -211,7 +211,7 @@ config FEATURE_MODUTILS_SYMBOLS +@@ -210,7 +210,7 @@ config FEATURE_MODUTILS_SYMBOLS config DEFAULT_MODULES_DIR string "Default directory containing modules" default "/lib/modules" diff --git a/package/busybox/patches/480-mount_union.patch b/package/busybox/patches/480-mount_union.patch index 2a22322ae..e520d781b 100644 --- a/package/busybox/patches/480-mount_union.patch +++ b/package/busybox/patches/480-mount_union.patch @@ -1,6 +1,6 @@ --- a/util-linux/mount.c +++ b/util-linux/mount.c -@@ -42,6 +42,10 @@ +@@ -69,6 +69,10 @@ #define MS_DIRSYNC 128 // Directory modifications are synchronous #endif @@ -11,7 +11,7 @@ #if defined(__dietlibc__) // 16.12.2006, Sampo Kellomaki (sampo@iki.fi) -@@ -152,6 +156,7 @@ static const int32_t mount_options[] = { +@@ -185,6 +189,7 @@ static const int32_t mount_options[] = { /* "rslave" */ MS_SLAVE|MS_RECURSIVE, /* "rprivate" */ MS_SLAVE|MS_RECURSIVE, /* "runbindable" */ MS_UNBINDABLE|MS_RECURSIVE, @@ -19,7 +19,7 @@ ) // Always understood. -@@ -206,6 +211,7 @@ static const char mount_option_str[] = +@@ -239,6 +244,7 @@ static const char mount_option_str[] = "rslave\0" "rprivate\0" "runbindable\0" diff --git a/package/busybox/patches/500-ping6_crash.patch b/package/busybox/patches/500-ping6_crash.patch deleted file mode 100644 index 8412a18ac..000000000 --- a/package/busybox/patches/500-ping6_crash.patch +++ /dev/null @@ -1,12 +0,0 @@ -Index: busybox-1.15.2/networking/ping.c -=================================================================== ---- busybox-1.15.2.orig/networking/ping.c 2009-11-24 22:57:29.000000000 +0100 -+++ busybox-1.15.2/networking/ping.c 2009-11-24 22:58:58.000000000 +0100 -@@ -769,6 +769,7 @@ - int ping6_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; - int ping6_main(int argc UNUSED_PARAM, char **argv) - { -+ argv[-1] = argv[0]; - argv[0] = (char*)"-6"; - return ping_main(0 /* argc+1 - but it's unused anyway */, - argv - 1); diff --git a/package/busybox/patches/524-udhcpc_renew.patch b/package/busybox/patches/524-udhcpc_renew.patch index 0a43b8fe3..8ba4835ae 100644 --- a/package/busybox/patches/524-udhcpc_renew.patch +++ b/package/busybox/patches/524-udhcpc_renew.patch @@ -1,6 +1,6 @@ --- a/networking/udhcp/dhcpc.c +++ b/networking/udhcp/dhcpc.c -@@ -69,7 +69,6 @@ static void perform_renew(void) +@@ -76,7 +76,6 @@ static void perform_renew(void) state = RENEW_REQUESTED; break; case RENEW_REQUESTED: /* impatient are we? fine, square 1 */ diff --git a/package/busybox/patches/902-telnetd_intr.patch b/package/busybox/patches/902-telnetd_intr.patch index 3b84fc4d3..92a2d4725 100644 --- a/package/busybox/patches/902-telnetd_intr.patch +++ b/package/busybox/patches/902-telnetd_intr.patch @@ -1,8 +1,6 @@ -diff --git a/networking/telnetd.c b/networking/telnetd.c -index 2a0ace5..c281feb 100644 --- a/networking/telnetd.c +++ b/networking/telnetd.c -@@ -308,6 +308,7 @@ make_new_session( +@@ -306,6 +306,7 @@ make_new_session( /* Restore default signal handling ASAP */ bb_signals((1 << SIGCHLD) + (1 << SIGPIPE), SIG_DFL); diff --git a/package/carl9170/Makefile b/package/carl9170/Makefile new file mode 100644 index 000000000..10c83a476 --- /dev/null +++ b/package/carl9170/Makefile @@ -0,0 +1,66 @@ +# +# Copyright (C) 2006 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +include $(TOPDIR)/rules.mk +include $(INCLUDE_DIR)/kernel.mk + +PKG_NAME:=carl9170 +PKG_VERSION:=0.9.2.1 +PKG_RELEASE:=1 + +PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2 +PKG_SOURCE_URL:=http://www.kernel.org/pub/linux/kernel/people/chr/carl9170/$(PKG_VERSION) +PKG_MD5SUM:=5f0057ea651343460ea4f1fb093a4bdf + +include $(INCLUDE_DIR)/package.mk + +DRV_PATH:=$(PKG_BUILD_DIR)/drivers/net/wireless/ath/carl9170 + +define KernelPackage/carl9170 + SUBMENU:=Wireless Drivers + TITLE:=Driver for Atheros AR9170 USB sticks + DEPENDS:=+kmod-mac80211 +kmod-ath + URL:=http://www.kernel.org/pub/linux/kernel/people/chr/carl9170 + FILES:=$(DRV_PATH)/carl9170usb.$(LINUX_KMOD_SUFFIX) + AUTOLOAD:=$(call AutoLoad,60,carl9170usb) +endef + +define KernelPackage/carl9170/description + This package contains a driver for Atheros AR9170 USB sticks using the free firmware +endef + +define Build/Prepare + rm -rf $(PKG_BUILD_DIR) + mkdir -p $(PKG_BUILD_DIR) + $(HOST_TAR) -C $(PKG_BUILD_DIR) -xjf $(DL_DIR)/$(PKG_SOURCE) + $(HOST_TAR) -C $(PKG_BUILD_DIR) -xf $(PKG_BUILD_DIR)/$(PKG_VERSION)/driver/carl9170-driver-$(PKG_VERSION).tar + ln -s Makefile.standalone $(DRV_PATH)/Makefile + ln -s $(STAGING_DIR)/usr/include/mac80211/ath/*.h $(PKG_BUILD_DIR)/drivers/net/wireless/ath/ + $(Build/Patch) +endef + +BUILDFLAGS = \ + CONFIG_MAC80211_DEBUGFS=$(CONFIG_PACKAGE_MAC80211_DEBUGFS) + +EXTRA_CFLAGS = \ + $(if $(CONFIG_ATH_USER_REGD),-DATH_USER_REGD) + +define Build/Compile + $(MAKE) -C $(LINUX_DIR) \ + SUBDIRS="$(DRV_PATH)" \ + ARCH="$(LINUX_KARCH)" \ + CROSS_COMPILE="$(KERNEL_CROSS)" \ + CC="$(TARGET_CC) -I$(STAGING_DIR)/usr/include/mac80211 $(EXTRA_CFLAGS)" \ + $(BUILDFLAGS) +endef + +define KernelPackage/carl9170/install + $(INSTALL_DIR) $(1)/lib/firmware + $(INSTALL_DATA) $(PKG_BUILD_DIR)/$(PKG_VERSION)/firmware_build/carl9170.fw $(1)/lib/firmware/ +endef + +$(eval $(call KernelPackage,carl9170)) diff --git a/package/carl9170/patches/100-request_firmware_compat.patch b/package/carl9170/patches/100-request_firmware_compat.patch new file mode 100644 index 000000000..93fdc6f08 --- /dev/null +++ b/package/carl9170/patches/100-request_firmware_compat.patch @@ -0,0 +1,31 @@ +--- a/drivers/net/wireless/ath/carl9170/usb.c ++++ b/drivers/net/wireless/ath/carl9170/usb.c +@@ -983,11 +983,28 @@ err_failed: + ar9170_usb_firmware_failed(aru); + } + ++ ++ + static int ar9170_usb_request_firmware(struct ar9170_usb *aru) + { ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33)) ++ const struct firmware *fw; ++ int ret; ++ ++ ret = request_firmware(&fw, ++ ar9170_fws[aru->fw_load].files[aru->fw_files].name, ++ &aru->udev->dev); ++ ++ if (ret < 0) ++ return ret; ++ ++ ar9170_usb_firmware_step2(fw, aru); ++ return 0; ++#else + return request_firmware_nowait(THIS_MODULE, 1, + ar9170_fws[aru->fw_load].files[aru->fw_files].name, + &aru->udev->dev, GFP_KERNEL, aru, ar9170_usb_firmware_step2); ++#endif + } + + static void ar9170_usb_disconnect(struct usb_interface *intf) diff --git a/package/carl9170/patches/110-endian_fixes.patch b/package/carl9170/patches/110-endian_fixes.patch new file mode 100644 index 000000000..fa2eb1a55 --- /dev/null +++ b/package/carl9170/patches/110-endian_fixes.patch @@ -0,0 +1,93 @@ +--- a/drivers/net/wireless/ath/carl9170/fw.c ++++ b/drivers/net/wireless/ath/carl9170/fw.c +@@ -39,7 +39,7 @@ const void *ar9170_fw_find_desc(struct a + for_each_hdr(iter, ar->fw_desc) { + if (!memcmp(iter->magic, descid, sizeof(*descid)) && + !CHECK_HDR_VERSION(iter, compatible_revision) && +- (iter->length >= len)) { ++ (le16_to_cpu(iter->length) >= len)) { + ret = (void *)iter; + break; + } +@@ -63,20 +63,22 @@ static int ar9170_fw_verify_descs(struct + end = (void *) head + max_len; + + while (pos < end) { +- if (((unsigned long)pos + pos->length) > (unsigned long)end) ++ int pos_length = le16_to_cpu(pos->length); ++ ++ if (((unsigned long)pos + pos_length) > (unsigned long)end) + return -EMSGSIZE; + +- if (pos->length > max_len) ++ if (pos_length > max_len) + return -EMSGSIZE; + +- if (pos->length < sizeof(struct carl9170_fw_desc_head)) ++ if (pos_length < sizeof(struct carl9170_fw_desc_head)) + return -EINVAL; + + if (!memcmp(pos->magic, last_magic, sizeof(last_magic))) + return 0; + +- pos = (void *)((unsigned long)pos + pos->length); +- max_len -= pos->length; ++ pos = (void *)((unsigned long)pos + pos_length); ++ max_len -= le16_to_cpu(pos->length); + } + + return -EINVAL; +@@ -139,7 +141,7 @@ static int ar9170_fw_check(struct ar9170 + if (SUPP(CARL9170_FW_CRC32_CHECKSUM_TAIL)) { + __le32 crc32; + +- crc32 = crc32_le(~0, data, len - 4); ++ crc32 = cpu_to_le32(crc32_le(~0, data, len - 4)); + if (!memcmp(&crc32, &data[len - 4], 4) == 0) { + dev_err(ar->pdev, "CRC32 checksum mismatch!\n"); + return -EINVAL; +--- a/drivers/net/wireless/ath/carl9170/fwhdr.h ++++ b/drivers/net/wireless/ath/carl9170/fwhdr.h +@@ -196,7 +196,7 @@ struct carl9170_fw_last_desc_v1 { + #define for_each_hdr(desc, fw_desc) \ + for (desc = fw_desc; \ + (memcmp(desc->magic, LAST_MAGIC, 4) && desc->length); \ +- desc = (void *)((unsigned long)desc + desc->length)) ++ desc = (void *)((unsigned long)desc + le16_to_cpu(desc->length))) + + #define CHECK_HDR_VERSION(head, _min_ver) \ + (((head)->cur_ver < _min_ver) || ((head)->min_ver > _min_ver)) \ +--- a/drivers/net/wireless/ath/carl9170/usb.c ++++ b/drivers/net/wireless/ath/carl9170/usb.c +@@ -640,9 +640,10 @@ static int ar9170_usb_check_firmware(str + } + + if ((usb_desc->tx_descs < 16) || +- (usb_desc->tx_frag_len < 64) || (usb_desc->tx_frag_len > 512) || +- (usb_desc->rx_max_frame_len < 1024) || +- (usb_desc->rx_max_frame_len > AR9170_MAX_RX_BUFFER_SIZE)) { ++ (le16_to_cpu(usb_desc->tx_frag_len) < 64) || ++ (le16_to_cpu(usb_desc->tx_frag_len) > 512) || ++ (le16_to_cpu(usb_desc->rx_max_frame_len) < 1024) || ++ (le16_to_cpu(usb_desc->rx_max_frame_len) > AR9170_MAX_RX_BUFFER_SIZE)) { + dev_err(&aru->udev->dev, "usb firmware has obvious signs of " + "malicious tampering.\n"); + err = -EINVAL; +@@ -650,14 +651,14 @@ static int ar9170_usb_check_firmware(str + } + + if (SUPP(CARL9170_FW_USB_MINIBOOT)) +- aru->fw_offset = usb_desc->miniboot_size; ++ aru->fw_offset = le16_to_cpu(usb_desc->miniboot_size); + else + aru->fw_offset = 0; + +- aru->rx_size = usb_desc->rx_max_frame_len; ++ aru->rx_size = le16_to_cpu(usb_desc->rx_max_frame_len); + aru->common.mem_blocks = usb_desc->tx_descs; + atomic_set(&aru->common.mem_free_blocks, usb_desc->tx_descs); +- aru->common.mem_block_size = usb_desc->tx_frag_len; ++ aru->common.mem_block_size = le16_to_cpu(usb_desc->tx_frag_len); + return 0; + + fail: diff --git a/package/carl9170/patches/120-fix_missing_include.patch b/package/carl9170/patches/120-fix_missing_include.patch new file mode 100644 index 000000000..02a7a87cc --- /dev/null +++ b/package/carl9170/patches/120-fix_missing_include.patch @@ -0,0 +1,10 @@ +--- a/drivers/net/wireless/ath/carl9170/debug.c ++++ b/drivers/net/wireless/ath/carl9170/debug.c +@@ -38,6 +38,7 @@ + */ + + #include ++#include + #include "carl9170.h" + #include "usb.h" + #include "cmd.h" diff --git a/package/carl9170/patches/130-ht_default.patch b/package/carl9170/patches/130-ht_default.patch new file mode 100644 index 000000000..aa629497c --- /dev/null +++ b/package/carl9170/patches/130-ht_default.patch @@ -0,0 +1,11 @@ +--- a/drivers/net/wireless/ath/carl9170/main.c ++++ b/drivers/net/wireless/ath/carl9170/main.c +@@ -50,7 +50,7 @@ static int modparam_nohwcrypt; + module_param_named(nohwcrypt, modparam_nohwcrypt, bool, S_IRUGO); + MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption."); + +-int modparam_ht; ++int modparam_ht = 1; + module_param_named(ht, modparam_ht, bool, S_IRUGO); + MODULE_PARM_DESC(ht, "enable MPDU aggregation."); + diff --git a/package/dnsmasq/Makefile b/package/dnsmasq/Makefile index 27f438c73..a3223431f 100644 --- a/package/dnsmasq/Makefile +++ b/package/dnsmasq/Makefile @@ -9,7 +9,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=dnsmasq PKG_VERSION:=2.51 -PKG_RELEASE:=1 +PKG_RELEASE:=3 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz PKG_SOURCE_URL:=http://thekelleys.org.uk/dnsmasq diff --git a/package/dnsmasq/files/dnsmasq.init b/package/dnsmasq/files/dnsmasq.init index bc14aa6c4..7955fdb0e 100644 --- a/package/dnsmasq/files/dnsmasq.init +++ b/package/dnsmasq/files/dnsmasq.init @@ -101,78 +101,80 @@ dnsmasq() { dhcp_subscrid_add() { local cfg="$1" - config_get name "$cfg" name - [ -n "$name" ] || return 0 + config_get networkid "$cfg" networkid + [ -n "$networkid" ] || return 0 config_get subscriberid "$cfg" subscriberid [ -n "$subscriberid" ] || return 0 - append args "--dhcp-subscrid=$name,$subscriberid" + append args "--dhcp-subscrid=$networkid,$subscriberid" - dhcp_option_add "$cfg" "$name" + dhcp_option_add "$cfg" "$networkid" } dhcp_remoteid_add() { local cfg="$1" - config_get name "$cfg" name - [ -n "$name" ] || return 0 + config_get networkid "$cfg" networkid + [ -n "$networkid" ] || return 0 config_get remoteid "$cfg" remoteid [ -n "$remoteid" ] || return 0 - append args "--dhcp-remoteid=$name,$remoteid" + append args "--dhcp-remoteid=$networkid,$remoteid" - dhcp_option_add "$cfg" "$name" + dhcp_option_add "$cfg" "$networkid" } dhcp_circuitid_add() { local cfg="$1" - config_get name "$cfg" name - [ -n "$name" ] || return 0 + config_get networkid "$cfg" networkid + [ -n "$networkid" ] || return 0 config_get circuitid "$cfg" circuitid [ -n "$circuitid" ] || return 0 - append args "--dhcp-circuitid=$name,$circuitid" + append args "--dhcp-circuitid=$networkid,$circuitid" - dhcp_option_add "$cfg" "$name" + dhcp_option_add "$cfg" "$networkid" } dhcp_userclass_add() { local cfg="$1" - config_get name "$cfg" name - [ -n "$name" ] || return 0 + config_get networkid "$cfg" networkid + [ -n "$networkid" ] || return 0 config_get userclass "$cfg" userclass [ -n "$userclass" ] || return 0 - append args "--dhcp-userclass=$name,$userclass" + append args "--dhcp-userclass=$networkid,$userclass" - dhcp_option_add "$cfg" "$name" + dhcp_option_add "$cfg" "$networkid" } dhcp_vendorclass_add() { local cfg="$1" - config_get name "$cfg" name - [ -n "$name" ] || return 0 + config_get networkid "$cfg" networkid + [ -n "$networkid" ] || return 0 config_get vendorclass "$cfg" vendorclass [ -n "$vendorclass" ] || return 0 - append args "--dhcp-vendorclass=$name,$vendorclass" + append args "--dhcp-vendorclass=$networkid,$vendorclass" - dhcp_option_add "$cfg" "$name" + dhcp_option_add "$cfg" "$networkid" } dhcp_host_add() { local cfg="$1" config_get name "$cfg" name - [ -n "$name" ] && dhcp_option_add "$cfg" "$name" + + config_get networkid "$cfg" networkid + [ -n "$networkid" ] && dhcp_option_add "$cfg" "$networkid" config_get mac "$cfg" mac [ -n "$mac" ] || return 0 @@ -180,27 +182,27 @@ dhcp_host_add() { config_get ip "$cfg" ip [ -n "$ip" ] || return 0 - append args "--dhcp-host=$mac,$ip${name:+,$name}" + append args "--dhcp-host=$mac,${networkid:+net:$networkid,}$ip${name:+,$name}" } dhcp_mac_add() { local cfg="$1" - config_get name "$cfg" name - [ -n "$name" ] || return 0 + config_get networkid "$cfg" networkid + [ -n "$networkid" ] || return 0 config_get mac "$cfg" mac [ -n "$mac" ] || return 0 - append args "--dhcp-mac=$name,$mac" + append args "--dhcp-mac=$networkid,$mac" - dhcp_option_add "$cfg" "$name" + dhcp_option_add "$cfg" "$networkid" } dhcp_boot_add() { local cfg="$1" - config_get name "$cfg" name + config_get networkid "$cfg" networkid config_get filename "$cfg" filename [ -n "$filename" ] || return 0 @@ -211,9 +213,9 @@ dhcp_boot_add() { config_get serveraddress "$cfg" serveraddress [ -n "$serveraddress" ] || return 0 - append args "--dhcp-boot=${name:+net:$name,}$filename,$servername,$serveraddress" + append args "--dhcp-boot=${networkid:+net:$networkid,}$filename,$servername,$serveraddress" - dhcp_option_add "$cfg" "$name" + dhcp_option_add "$cfg" "$networkid" } @@ -222,8 +224,8 @@ dhcp_add() { config_get net "$cfg" interface [ -n "$net" ] || return 0 - config_get name "$cfg" name - [ -n "$name" ] || name="$net" + config_get networkid "$cfg" networkid + [ -n "$networkid" ] || networkid="$net" config_get ifname "$net" ifname [ -n "$ifname" ] || return 0 @@ -259,18 +261,18 @@ dhcp_add() { limit="$((${limit:-150} + 1))" eval "$(ipcalc.sh $ipaddr $netmask $start $limit)" if [ "$dynamicdhcp" = "0" ]; then END="static"; fi - append args "--dhcp-range=$name,$START,$END,$NETMASK,$leasetime${options:+ $options}" + append args "--dhcp-range=$networkid,$START,$END,$NETMASK,$leasetime${options:+ $options}" - dhcp_option_add "$cfg" "$name" + dhcp_option_add "$cfg" "$networkid" } dhcp_option_add() { local cfg="$1" - local name="$2" + local networkid="$2" config_get dhcp_option "$cfg" dhcp_option for o in $dhcp_option; do - append args "-O $name","$o" + append args "-O $networkid","$o" done } @@ -309,6 +311,7 @@ start() { /usr/sbin/dnsmasq $args && { rm -f /tmp/resolv.conf + [ -n "$DOMAIN" ] && echo "search $DOMAIN" >> /tmp/resolv.conf DNS_SERVERS="$DNS_SERVERS 127.0.0.1" for DNS_SERVER in $DNS_SERVERS ; do echo "nameserver $DNS_SERVER" >> /tmp/resolv.conf diff --git a/package/e2fsprogs/Makefile b/package/e2fsprogs/Makefile index c05105aab..bf744147b 100644 --- a/package/e2fsprogs/Makefile +++ b/package/e2fsprogs/Makefile @@ -49,7 +49,7 @@ endef define Package/uuidgen $(call Package/e2fsprogs) - DEPENDS:=libuuid + DEPENDS:=+libuuid TITLE:=Command line utility to create a new UUID value endef @@ -86,25 +86,25 @@ endef define Package/tune2fs $(call Package/e2fsprogs) TITLE:=Ext2 Filesystem tune utility - DEPENDS:=e2fsprogs + DEPENDS:= +e2fsprogs endef define Package/resize2fs $(call Package/e2fsprogs) TITLE:=Ext2 Filesystem resize utility - DEPENDS:=e2fsprogs + DEPENDS:= +e2fsprogs endef define Package/badblocks $(call Package/e2fsprogs) TITLE:=Ext2 Filesystem badblocks utility - DEPENDS:=e2fsprogs + DEPENDS:= +e2fsprogs endef define Package/blkid $(call Package/e2fsprogs) TITLE:=Command-line utility to locate/print block device attributes - DEPENDS:=libuuid libblkid + DEPENDS:=+libuuid +libblkid endef TARGET_CFLAGS += $(FPIC) @@ -177,7 +177,7 @@ endef define Package/libext2fs/install $(INSTALL_DIR) $(1)/usr/lib - $(CP) $(PKG_INSTALL_DIR)/usr/lib/libext2fs.so* $(1)/usr/lib/ + $(CP) $(PKG_INSTALL_DIR)/usr/lib/libext2fs.so.* $(1)/usr/lib/ endef define Package/tune2fs/install diff --git a/package/e2fsprogs/patches/001-fix_abs_shlibs_symlinks.patch b/package/e2fsprogs/patches/001-fix_abs_shlibs_symlinks.patch new file mode 100644 index 000000000..e6dd084ac --- /dev/null +++ b/package/e2fsprogs/patches/001-fix_abs_shlibs_symlinks.patch @@ -0,0 +1,11 @@ +--- a/lib/Makefile.elf-lib ++++ b/lib/Makefile.elf-lib +@@ -45,7 +45,7 @@ install-shlibs install:: $(ELF_LIB) inst + @echo " SYMLINK $(ELF_INSTALL_DIR)/$(ELF_SONAME)" + @$(LN_S) -f $(ELF_LIB) $(DESTDIR)$(ELF_INSTALL_DIR)/$(ELF_SONAME) + @echo " SYMLINK $(libdir)/$(ELF_IMAGE).so" +- @$(LN_S) -f $(ELF_INSTALL_DIR)/$(ELF_SONAME) \ ++ @$(LN_S) -f $(ELF_SONAME) \ + $(DESTDIR)$(libdir)/$(ELF_IMAGE).so + @echo " LDCONFIG" + @-$(LDCONFIG) diff --git a/package/firewall/Makefile b/package/firewall/Makefile index fbbe056c0..8d0452602 100644 --- a/package/firewall/Makefile +++ b/package/firewall/Makefile @@ -9,7 +9,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=firewall PKG_VERSION:=1 -PKG_RELEASE:=8 +PKG_RELEASE:=9 include $(INCLUDE_DIR)/package.mk @@ -18,7 +18,7 @@ define Package/firewall CATEGORY:=Base system URL:=http://openwrt.org/ TITLE:=OpenWrt firewall - DEPENDS:=+iptables-mod-conntrack +iptables-mod-nat + DEPENDS:=+iptables +iptables-mod-conntrack +iptables-mod-nat PKGARCH:=all endef diff --git a/package/firewall/files/20-firewall b/package/firewall/files/20-firewall index 1cfc1b9c0..4b89326b5 100644 --- a/package/firewall/files/20-firewall +++ b/package/firewall/files/20-firewall @@ -2,35 +2,4 @@ unset ZONE config_get ifname $INTERFACE ifname [ "$ifname" == "lo" ] && exit 0 - -load_zones() { - local name - local network - config_get name $1 name - config_get network $1 network - [ -z "$network" ] && network=$name - for n in $network; do - [ "$n" = "$INTERFACE" ] && ZONE="$ZONE $name" - done -} - -config_foreach load_zones zone - -[ -z "$ZONE" ] && exit 0 - -[ ifup = "$ACTION" ] && { - for z in $ZONE; do - local loaded - config_get loaded core loaded - [ -n "$loaded" ] && addif "$INTERFACE" "$ifname" "$z" - done -} - -[ ifdown = "$ACTION" ] && { - local up - config_get up "$INTERFACE" up - - for z in $ZONE; do - [ "$up" == "1" ] && delif "$INTERFACE" "$ifname" "$z" - done -} +fw_event "$ACTION" "$INTERFACE" diff --git a/package/firewall/files/uci_firewall.sh b/package/firewall/files/uci_firewall.sh index 67662c1ac..05fe39beb 100755 --- a/package/firewall/files/uci_firewall.sh +++ b/package/firewall/files/uci_firewall.sh @@ -1,4 +1,4 @@ -#!/bin/sh +#!/bin/sh # Copyright (C) 2008 John Crispin . /etc/functions.sh @@ -43,12 +43,12 @@ load_policy() { create_zone() { local exists - + [ "$1" == "loopback" ] && return config_get exists $ZONE_LIST $1 [ -n "$exists" ] && return - config_set $ZONE_LIST $1 1 + config_set $ZONE_LIST $1 1 $IPTABLES -N zone_$1 $IPTABLES -N zone_$1_MSSFIX @@ -90,8 +90,8 @@ addif() { $IPTABLES -I zone_${zone}_ACCEPT 1 -i "$ifname" -j ACCEPT $IPTABLES -I zone_${zone}_DROP 1 -i "$ifname" -j DROP $IPTABLES -I zone_${zone}_REJECT 1 -i "$ifname" -j reject - $IPTABLES -I zone_${zone}_nat 1 -t nat -o "$ifname" -j MASQUERADE - $IPTABLES -I PREROUTING 1 -t nat -i "$ifname" -j zone_${zone}_prerouting + $IPTABLES -I zone_${zone}_nat 1 -t nat -o "$ifname" -j MASQUERADE + $IPTABLES -I PREROUTING 1 -t nat -i "$ifname" -j zone_${zone}_prerouting $IPTABLES -A forward -i "$ifname" -j zone_${zone}_forward $IPTABLES -t raw -I PREROUTING 1 -i "$ifname" -j zone_${zone}_notrack uci_set_state firewall core "${network}_ifname" "$ifname" @@ -113,8 +113,8 @@ delif() { $IPTABLES -D zone_${zone}_ACCEPT -i "$ifname" -j ACCEPT $IPTABLES -D zone_${zone}_DROP -i "$ifname" -j DROP $IPTABLES -D zone_${zone}_REJECT -i "$ifname" -j reject - $IPTABLES -D zone_${zone}_nat -t nat -o "$ifname" -j MASQUERADE - $IPTABLES -D PREROUTING -t nat -i "$ifname" -j zone_${zone}_prerouting + $IPTABLES -D zone_${zone}_nat -t nat -o "$ifname" -j MASQUERADE + $IPTABLES -D PREROUTING -t nat -i "$ifname" -j zone_${zone}_prerouting $IPTABLES -D forward -i "$ifname" -j zone_${zone}_forward uci_revert_state firewall core "${network}_ifname" uci_revert_state firewall core "${network}_zone" @@ -160,17 +160,17 @@ fw_defaults() { load_policy "$1" echo 1 > /proc/sys/net/ipv4/tcp_syncookies - for f in /proc/sys/net/ipv4/conf/*/accept_redirects + for f in /proc/sys/net/ipv4/conf/*/accept_redirects do echo 0 > $f done - for f in /proc/sys/net/ipv4/conf/*/accept_source_route + for f in /proc/sys/net/ipv4/conf/*/accept_source_route do echo 0 > $f - done - + done + uci_revert_state firewall core - uci_set_state firewall core "" firewall_state + uci_set_state firewall core "" firewall_state $IPTABLES -P INPUT DROP $IPTABLES -P OUTPUT DROP @@ -197,7 +197,7 @@ fw_defaults() { config_get syn_rate $1 syn_rate config_get syn_burst $1 syn_burst [ "$syn_flood" == "1" ] && load_synflood $syn_rate $syn_burst - + echo "Adding custom chains" fw_custom_chains @@ -253,7 +253,7 @@ fw_zone() { } fw_rule() { - local src + local src local src_ip local src_mac local src_port @@ -287,7 +287,7 @@ fw_rule() { dest_port_last=${dest_port#*-} [ "$dest_port_first" -ne "$dest_port_last" ] && { \ dest_port="$dest_port_first:$dest_port_last"; } - + ZONE=input TARGET=$target [ -z "$target" ] && target=DROP @@ -303,7 +303,7 @@ fw_rule() { ${src_mac:+-m mac --mac-source $src_mac} \ ${dest_ip:+-d $dest_ip} \ ${dest_port:+--dport $dest_port} \ - -j $TARGET + -j $TARGET } [ "$proto" == "tcpudp" -o -z "$proto" ] && { proto=tcp @@ -340,7 +340,7 @@ fw_redirect() { local dest_ip local dest_port dest_port2 local proto - + config_get src $1 src config_get src_ip $1 src_ip config_get src_port $1 src_port @@ -351,7 +351,7 @@ fw_redirect() { config_get proto $1 proto [ -z "$src" -o -z "$dest_ip" ] && { \ echo "redirect needs src and dest_ip"; return ; } - + src_port_first=${src_port%-*} src_port_last=${src_port#*-} [ "$src_port_first" -ne "$src_port_last" ] && { \ @@ -362,7 +362,7 @@ fw_redirect() { [ "$src_dport_first" -ne "$src_dport_last" ] && { \ src_dport="$src_dport_first:$src_dport_last"; } - dest_port2=$dest_port + dest_port2=${dest_port:-$src_dport} dest_port_first=${dest_port2%-*} dest_port_last=${dest_port2#*-} [ "$dest_port_first" -ne "$dest_port_last" ] && { \ @@ -384,7 +384,7 @@ fw_redirect() { ${src_port:+--sport $src_port} \ ${dest_port2:+--dport $dest_port2} \ ${src_mac:+-m mac --mac-source $src_mac} \ - -j ACCEPT + -j ACCEPT } [ "$proto" == "tcpudp" -o -z "$proto" ] && { proto=tcp @@ -402,13 +402,53 @@ fw_include() { [ -e $path ] && . $path } +get_interface_zones() { + local interface="$2" + local name + local network + config_get name $1 name + config_get network $1 network + [ -z "$network" ] && network=$name + for n in $network; do + [ "$n" = "$interface" ] && append add_zone "$name" + done +} + +fw_event() { + local action="$1" + local interface="$2" + local ifname="$(sh -c ". /etc/functions.sh; include /lib/network; scan_interfaces; config_get "$interface" ifname")" + add_zone= + local up + + [ -z "$ifname" ] && return 0 + config_foreach get_interface_zones zone "$interface" + [ -z "$add_zone" ] && return 0 + + case "$action" in + ifup) + for z in $add_zone; do + local loaded + config_get loaded core loaded + [ -n "$loaded" ] && addif "$interface" "$ifname" "$z" + done + ;; + ifdown) + config_get up "$interface" up + + for z in $ZONE; do + [ "$up" == "1" ] && delif "$interface" "$ifname" "$z" + done + ;; + esac +} + fw_addif() { local up local ifname config_get up $1 up - config_get ifname $1 ifname [ -n "$up" ] || return 0 - (ACTION="ifup" INTERFACE="$1" . /etc/hotplug.d/iface/20-firewall) + fw_event ifup "$1" } fw_custom_chains() { @@ -418,7 +458,7 @@ fw_custom_chains() { $IPTABLES -N forwarding_rule $IPTABLES -N prerouting_rule -t nat $IPTABLES -N postrouting_rule -t nat - + $IPTABLES -A INPUT -j input_rule $IPTABLES -A OUTPUT -j output_rule $IPTABLES -A FORWARD -j forwarding_rule @@ -464,10 +504,12 @@ fw_init() { echo "Loading zone defaults" config_foreach fw_zone_defaults zone uci_set_state firewall core loaded 1 + config_set core loaded 1 config_foreach fw_check_notrack zone - unset CONFIG_APPEND - config_load network - config_foreach fw_addif interface + INTERFACES="$(sh -c '. /etc/functions.sh; config_load network; config_foreach echo interface')" + for interface in $INTERFACES; do + fw_addif "$interface" + done } fw_stop() { diff --git a/package/gdb/Makefile b/package/gdb/Makefile index d2bb43be9..6a166d0eb 100644 --- a/package/gdb/Makefile +++ b/package/gdb/Makefile @@ -19,7 +19,7 @@ include $(INCLUDE_DIR)/package.mk define Package/gdb/Default SECTION:=utils CATEGORY:=Utilities - DEPENDS:= @!avr32 + DEPENDS:= @!(avr32||cris) endef define Package/gdb @@ -42,8 +42,10 @@ define Package/gdbserver/description than the one which is running the program being debugged. endef +# XXX: add --disable-werror to prevent build failure with arm CONFIGURE_ARGS+= \ - --with-system-readline + --with-system-readline \ + --disable-werror \ CONFIGURE_VARS+= \ ac_cv_search_tgetent="$(TARGET_LDFLAGS) -lncurses -lreadline" diff --git a/package/hostap-driver/Makefile b/package/hostap-driver/Makefile index cd1ca79ca..6841fcdc0 100644 --- a/package/hostap-driver/Makefile +++ b/package/hostap-driver/Makefile @@ -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_30||LINUX_2_6_31):kmod-ieee80211 +LINUX_2_6_30||LINUX_2_6_31:kmod-lib80211 +wireless-tools + DEPENDS:=@PCI_SUPPORT||PCMCIA_SUPPORT +!(LINUX_2_6_30||LINUX_2_6_31||LINUX_2_6_32):kmod-ieee80211 +LINUX_2_6_30||LINUX_2_6_31||LINUX_2_6_32:kmod-lib80211 +wireless-tools KCONFIG:=CONFIG_HOSTAP CONFIG_HOSTAP_FIRMWARE=y CONFIG_HOSTAP_FIRMWARE_NVRAM=y PROVIDES:=kmod-hostap endef diff --git a/package/hostapd/Makefile b/package/hostapd/Makefile index d1ca7ea88..6b4679616 100644 --- a/package/hostapd/Makefile +++ b/package/hostapd/Makefile @@ -8,9 +8,9 @@ include $(TOPDIR)/rules.mk PKG_NAME:=hostapd -PKG_VERSION:=20091129 +PKG_VERSION:=20100108 PKG_RELEASE:=1 -PKG_REV:=be8eb8ab3ee42aa66930aea827bdcb05a2172276 +PKG_REV:=d97572a40fd7ec77094e2e4ef83424a4c0f7e24d PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2 PKG_SOURCE_URL:=git://w1.fi/srv/git/hostap.git diff --git a/package/hostapd/files/hostapd.sh b/package/hostapd/files/hostapd.sh index e12c39276..740155725 100644 --- a/package/hostapd/files/hostapd.sh +++ b/package/hostapd/files/hostapd.sh @@ -78,6 +78,7 @@ hostapd_setup_vif() { config_get hwmode "$device" hwmode config_get wpa_group_rekey "$vif" wpa_group_rekey config_get ieee80211d "$vif" ieee80211d + config_get_bool hidden "$vif" hidden 0 config_get_bool wds "$vif" wds 0 [ "$wds" -gt 0 -a "$driver" = "nl80211" ] && wds="wds_sta=1" || wds="" case "$hwmode" in @@ -119,6 +120,7 @@ EOF ;; *) cat >> /var/run/hostapd-$ifname.conf <ioctl_sock, drv->iface, 0); + madwifi_set_privacy(drv->iface, drv, 0); /* default to no privacy */ - if (ioctl(drv->ioctl_sock, SIOCSIFFLAGS, &ifr) != 0) { - perror("ioctl[SIOCSIFFLAGS]"); + madwifi_receive_probe_req(drv); +@@ -1261,8 +1259,7 @@ madwifi_set_countermeasures(void *priv, + static int + madwifi_commit(void *priv) + { +- struct madwifi_driver_data *drv = priv; +- return linux_set_iface_flags(drv->ioctl_sock, drv->iface, 1); ++ return 0; + } + + #else /* HOSTAPD */ diff --git a/package/hostapd/patches/110-countrycode.patch b/package/hostapd/patches/110-countrycode.patch index 73738f15e..dec26ee02 100644 --- a/package/hostapd/patches/110-countrycode.patch +++ b/package/hostapd/patches/110-countrycode.patch @@ -1,14 +1,10 @@ ---- a/hostapd/hostapd.c -+++ b/hostapd/hostapd.c -@@ -1339,10 +1339,8 @@ static int setup_interface(struct hostap - if (hapd->iconf->country[0] && hapd->iconf->country[1]) { - os_memcpy(country, hapd->iconf->country, 3); +--- a/src/ap/hostapd.c ++++ b/src/ap/hostapd.c +@@ -649,7 +649,6 @@ static int setup_interface(struct hostap country[3] = '\0'; -- if (hostapd_set_country(hapd, country) < 0) { -+ if (hostapd_set_country(hapd, country) < 0) + if (hostapd_set_country(hapd, country) < 0) { wpa_printf(MSG_ERROR, "Failed to set country code"); - return -1; -- } + } } - if (hapd->iconf->bridge_packets != INTERNAL_BRIDGE_DO_NOT_CONTROL && diff --git a/package/hostapd/patches/120-compile_fix.patch b/package/hostapd/patches/120-compile_fix.patch new file mode 100644 index 000000000..43a15787d --- /dev/null +++ b/package/hostapd/patches/120-compile_fix.patch @@ -0,0 +1,28 @@ +--- a/src/drivers/driver_nl80211.c ++++ b/src/drivers/driver_nl80211.c +@@ -22,6 +22,7 @@ + #include + #include + #include ++#include + #include + #include + #include "nl80211_copy.h" +--- a/src/drivers/driver_madwifi.c ++++ b/src/drivers/driver_madwifi.c +@@ -69,6 +69,7 @@ + #define MADWIFI_NG + #endif /* IEEE80211_IOCTL_SETWMMPARAMS */ + ++#define WPA_KEY_RSC_LEN 8 + + #ifdef HOSTAPD + +@@ -1499,7 +1500,6 @@ wpa_driver_madwifi_set_key(const char *i + wk.ik_keyix = key_idx; + wk.ik_keylen = key_len; + #ifdef WORDS_BIGENDIAN +-#define WPA_KEY_RSC_LEN 8 + { + size_t i; + u8 tmp[WPA_KEY_RSC_LEN]; diff --git a/package/hostapd/patches/120-wds_ap.patch b/package/hostapd/patches/120-wds_ap.patch deleted file mode 100644 index a6f7669f6..000000000 --- a/package/hostapd/patches/120-wds_ap.patch +++ /dev/null @@ -1,248 +0,0 @@ ---- a/hostapd/config.c -+++ b/hostapd/config.c -@@ -1526,6 +1526,8 @@ struct hostapd_config * hostapd_config_r - line, pos); - errors++; - } -+ } else if (os_strcmp(buf, "wds_sta") == 0) { -+ bss->wds_sta = atoi(pos); - } else if (os_strcmp(buf, "ap_max_inactivity") == 0) { - bss->ap_max_inactivity = atoi(pos); - } else if (os_strcmp(buf, "country_code") == 0) { ---- a/hostapd/config.h -+++ b/hostapd/config.h -@@ -195,6 +195,7 @@ struct hostapd_bss_config { - int num_accept_mac; - struct mac_acl_entry *deny_mac; - int num_deny_mac; -+ int wds_sta; - - int auth_algs; /* bitfield of allowed IEEE 802.11 authentication - * algorithms, WPA_AUTH_ALG_{OPEN,SHARED,LEAP} */ ---- a/src/drivers/driver.h -+++ b/src/drivers/driver.h -@@ -1127,6 +1127,7 @@ struct wpa_driver_ops { - const char *ifname, const u8 *addr); - int (*set_sta_vlan)(void *priv, const u8 *addr, const char *ifname, - int vlan_id); -+ int (*set_wds_sta)(void *priv, const u8 *addr, int aid, int val); - /** - * commit - Optional commit changes handler - * @priv: driver private data ---- a/src/drivers/driver_nl80211.c -+++ b/src/drivers/driver_nl80211.c -@@ -2675,7 +2675,7 @@ static void nl80211_remove_iface(struct - static int nl80211_create_iface_once(struct wpa_driver_nl80211_data *drv, - const char *ifname, - enum nl80211_iftype iftype, -- const u8 *addr) -+ const u8 *addr, int wds) - { - struct nl_msg *msg, *flags = NULL; - int ifidx; -@@ -2706,6 +2706,8 @@ static int nl80211_create_iface_once(str - - if (err) - goto nla_put_failure; -+ } else if (wds) { -+ NLA_PUT_U8(msg, NL80211_ATTR_4ADDR, wds); - } - - ret = send_and_recv_msgs(drv, msg, NULL, NULL); -@@ -2736,11 +2738,11 @@ static int nl80211_create_iface_once(str - } - static int nl80211_create_iface(struct wpa_driver_nl80211_data *drv, - const char *ifname, enum nl80211_iftype iftype, -- const u8 *addr) -+ const u8 *addr, int wds) - { - int ret; - -- ret = nl80211_create_iface_once(drv, ifname, iftype, addr); -+ ret = nl80211_create_iface_once(drv, ifname, iftype, addr, wds); - - /* if error occured and interface exists already */ - if (ret == -ENFILE && if_nametoindex(ifname)) { -@@ -2750,7 +2752,7 @@ static int nl80211_create_iface(struct w - nl80211_remove_iface(drv, if_nametoindex(ifname)); - - /* Try to create the interface again */ -- ret = nl80211_create_iface_once(drv, ifname, iftype, addr); -+ ret = nl80211_create_iface_once(drv, ifname, iftype, addr, wds); - } - - return ret; -@@ -2975,7 +2977,7 @@ static struct sock_filter msock_filter_i - - #if 0 - /* -- * drop non-data frames, WDS frames -+ * drop non-data frames - */ - /* load the lower byte of the frame control field */ - BPF_STMT(BPF_LD | BPF_B | BPF_IND, 0), -@@ -2983,13 +2985,13 @@ static struct sock_filter msock_filter_i - BPF_STMT(BPF_ALU | BPF_AND | BPF_K, 0x0c), - /* drop non-data frames */ - BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 8, 0, FAIL), -+#endif - /* load the upper byte of the frame control field */ -- BPF_STMT(BPF_LD | BPF_B | BPF_IND, 0), -+ BPF_STMT(BPF_LD | BPF_B | BPF_IND, 1), - /* mask off toDS/fromDS */ - BPF_STMT(BPF_ALU | BPF_AND | BPF_K, 0x03), -- /* drop WDS frames */ -- BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 3, FAIL, 0), --#endif -+ /* accept WDS frames */ -+ BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 3, PASS, 0), - - /* - * add header length to index -@@ -3095,7 +3097,7 @@ nl80211_create_monitor_interface(struct - buf[IFNAMSIZ - 1] = '\0'; - - drv->monitor_ifidx = -- nl80211_create_iface(drv, buf, NL80211_IFTYPE_MONITOR, NULL); -+ nl80211_create_iface(drv, buf, NL80211_IFTYPE_MONITOR, NULL, 0); - - if (drv->monitor_ifidx < 0) - return -1; -@@ -4064,7 +4066,7 @@ static int i802_bss_add(void *priv, cons - if (bss == NULL) - return -1; - -- ifidx = nl80211_create_iface(priv, ifname, NL80211_IFTYPE_AP, bssid); -+ ifidx = nl80211_create_iface(priv, ifname, NL80211_IFTYPE_AP, bssid, 0); - if (ifidx < 0) { - os_free(bss); - return -1; -@@ -4162,7 +4164,7 @@ static int i802_if_add(const char *iface - enum hostapd_driver_if_type type, char *ifname, - const u8 *addr) - { -- if (nl80211_create_iface(priv, ifname, i802_if_type(type), addr) < 0) -+ if (nl80211_create_iface(priv, ifname, i802_if_type(type), addr, 0) < 0) - return -1; - return 0; - } -@@ -4208,6 +4210,22 @@ static int i802_set_sta_vlan(void *priv, - return -ENOBUFS; - } - -+static int i802_set_wds_sta(void *priv, const u8 *addr, int aid, int val) -+{ -+ struct wpa_driver_nl80211_data *drv = priv; -+ char name[16]; -+ -+ sprintf(name, "%s.sta%d", drv->ifname, aid); -+ if (val) { -+ if (nl80211_create_iface(priv, name, NL80211_IFTYPE_AP_VLAN, NULL, 1) < 0) -+ return -1; -+ hostapd_set_iface_flags(drv, name, 1); -+ return i802_set_sta_vlan(priv, addr, name, 0); -+ } else { -+ i802_set_sta_vlan(priv, addr, drv->ifname, 0); -+ return i802_if_remove(priv, HOSTAPD_IF_VLAN, name, NULL); -+ } -+} - - static void handle_eapol(int sock, void *eloop_ctx, void *sock_ctx) - { -@@ -4424,5 +4442,6 @@ const struct wpa_driver_ops wpa_driver_n - .if_update = i802_if_update, - .if_remove = i802_if_remove, - .set_sta_vlan = i802_set_sta_vlan, -+ .set_wds_sta = i802_set_wds_sta, - #endif /* HOSTAPD */ - }; ---- a/hostapd/driver_i.h -+++ b/hostapd/driver_i.h -@@ -446,6 +446,14 @@ hostapd_set_sta_vlan(const char *ifname, - } - - static inline int -+hostapd_set_wds_sta(struct hostapd_data *hapd, const u8 *addr, int aid, int val) -+{ -+ if (hapd->driver == NULL || hapd->driver->set_wds_sta == NULL) -+ return 0; -+ return hapd->driver->set_wds_sta(hapd->drv_priv, addr, aid, val); -+} -+ -+static inline int - hostapd_driver_commit(struct hostapd_data *hapd) - { - if (hapd->driver == NULL || hapd->driver->commit == NULL) ---- a/hostapd/drv_callbacks.c -+++ b/hostapd/drv_callbacks.c -@@ -167,6 +167,7 @@ static const u8 * get_hdr_bssid(const st - if (len < 24) - return NULL; - switch (fc & (WLAN_FC_FROMDS | WLAN_FC_TODS)) { -+ case WLAN_FC_FROMDS|WLAN_FC_TODS: - case WLAN_FC_TODS: - return hdr->addr1; - case WLAN_FC_FROMDS: -@@ -213,6 +214,7 @@ void hostapd_rx_from_unknown_sta(struct - { - struct sta_info *sta; - const u8 *addr; -+ u16 fc = le_to_host16(hdr->frame_control); - - hapd = get_hapd_bssid(hapd->iface, get_hdr_bssid(hdr, len)); - if (hapd == NULL || hapd == HAPD_BROADCAST) -@@ -231,6 +233,14 @@ void hostapd_rx_from_unknown_sta(struct - hostapd_sta_deauth( - hapd, addr, - WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA); -+ } else { -+ if (!sta->wds_sta) { -+ if ((fc & (WLAN_FC_TODS | WLAN_FC_FROMDS)) == -+ (WLAN_FC_TODS | WLAN_FC_FROMDS)) { -+ sta->wds_sta = 1; -+ hostapd_set_wds_sta(hapd, addr, sta->aid, 1); -+ } -+ } - } - } - ---- a/hostapd/sta_info.c -+++ b/hostapd/sta_info.c -@@ -120,6 +120,7 @@ void ap_free_sta(struct hostapd_data *ha - - accounting_sta_stop(hapd, sta); - -+ hostapd_set_wds_sta(hapd, sta->addr, sta->aid, 0); - if (!ap_sta_in_other_bss(hapd, sta, WLAN_STA_ASSOC) && - !(sta->flags & WLAN_STA_PREAUTH)) - hostapd_sta_remove(hapd, sta->addr); ---- a/hostapd/sta_info.h -+++ b/hostapd/sta_info.h -@@ -78,6 +78,7 @@ struct sta_info { - struct hostapd_ssid *ssid_probe; /* SSID selection based on ProbeReq */ - - int vlan_id; -+ int wds_sta; - - #ifdef CONFIG_IEEE80211N - struct ht_cap_ie ht_capabilities; /* IEEE 802.11n capabilities */ ---- a/src/common/nl80211_copy.h -+++ b/src/common/nl80211_copy.h -@@ -584,6 +584,8 @@ enum nl80211_commands { - * changed then the list changed and the dump should be repeated - * completely from scratch. - * -+ * @NL80211_ATTR_4ADDR: Use 4-address frames on a virtual interface -+ * - * @NL80211_ATTR_MAX: highest attribute number currently defined - * @__NL80211_ATTR_AFTER_LAST: internal use - */ -@@ -714,6 +716,8 @@ enum nl80211_attrs { - - NL80211_ATTR_PID, - -+ NL80211_ATTR_4ADDR, -+ - /* add attributes here, update the policy in nl80211.c */ - - __NL80211_ATTR_AFTER_LAST, diff --git a/package/hostapd/patches/130-compile_fix.patch b/package/hostapd/patches/130-compile_fix.patch deleted file mode 100644 index 5a04f9a80..000000000 --- a/package/hostapd/patches/130-compile_fix.patch +++ /dev/null @@ -1,10 +0,0 @@ ---- a/src/drivers/driver_nl80211.c -+++ b/src/drivers/driver_nl80211.c -@@ -23,6 +23,7 @@ - #include - #include - #include -+#include - #include "nl80211_copy.h" - - #include "common.h" diff --git a/package/hotplug2/Makefile b/package/hotplug2/Makefile index b51e5a97f..2f8fc1477 100644 --- a/package/hotplug2/Makefile +++ b/package/hotplug2/Makefile @@ -8,7 +8,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=hotplug2 -PKG_REV:=199 +PKG_REV:=201 PKG_VERSION:=$(PKG_REV) PKG_RELEASE:=1 diff --git a/package/hotplug2/patches/100-env_memleak.patch b/package/hotplug2/patches/100-env_memleak.patch new file mode 100644 index 000000000..31f404029 --- /dev/null +++ b/package/hotplug2/patches/100-env_memleak.patch @@ -0,0 +1,64 @@ +diff -Naur a/action.c b/action.c +--- a/action.c 2009-11-18 13:15:21.000000000 +0000 ++++ b/action.c 2009-11-18 13:11:19.000000000 +0000 +@@ -31,6 +31,30 @@ + } + + /** ++ * Creates a "key=value" string from the given key and value ++ * ++ * @1 Key ++ * @2 Value ++ * ++ * Returns: Newly allocated string in "key=value" form ++ * ++ */ ++static char* alloc_env(const char *key, const char *value) { ++ size_t keylen, vallen; ++ char *combined; ++ ++ keylen = strlen(key); ++ vallen = strlen(value) + 1; ++ ++ combined = xmalloc(keylen + vallen + 1); ++ memcpy(combined, key, keylen); ++ combined[keylen] = '='; ++ memcpy(&combined[keylen + 1], value, vallen); ++ ++ return combined; ++} ++ ++/** + * Choose what action should be taken according to passed settings. + * + * @1 Hotplug settings +@@ -41,16 +65,25 @@ + */ + void action_perform(struct settings_t *settings, struct uevent_t *event) { + int i; ++ char **env; ++ ++ env = xmalloc(sizeof(char *) * event->env_vars_c); ++ ++ for (i = 0; i < event->env_vars_c; i++) { ++ env[i] = alloc_env(event->env_vars[i].key, event->env_vars[i].value); ++ putenv(env[i]); ++ } + +- for (i = 0; i < event->env_vars_c; i++) +- setenv(event->env_vars[i].key, event->env_vars[i].value, 1); +- + if (settings->dumb == 0) { + ruleset_execute(&settings->rules, event, settings); + } else { + action_dumb(settings, event); + } + +- for (i = 0; i < event->env_vars_c; i++) ++ for (i = 0; i < event->env_vars_c; i++) { + unsetenv(event->env_vars[i].key); ++ free(env[i]); ++ } ++ ++ free(env); + } diff --git a/package/hotplug2/patches/100-recv_check.patch b/package/hotplug2/patches/100-recv_check.patch deleted file mode 100644 index 168df47bb..000000000 --- a/package/hotplug2/patches/100-recv_check.patch +++ /dev/null @@ -1,12 +0,0 @@ ---- a/hotplug2.c -+++ b/hotplug2.c -@@ -300,6 +300,9 @@ int main(int argc, char *argv[]) { - worker_ctx = settings->worker->module->init(settings); - while (process) { - size = recv(settings->netlink_socket, &buffer, sizeof(buffer), 0); -+ if (size < 0) -+ continue; -+ - uevent = uevent_deserialize(buffer, size); - - if (uevent == NULL) diff --git a/package/hotplug2/patches/110-static_worker.patch b/package/hotplug2/patches/110-static_worker.patch index 453a52d54..bca4aace7 100644 --- a/package/hotplug2/patches/110-static_worker.patch +++ b/package/hotplug2/patches/110-static_worker.patch @@ -1,164 +1,22 @@ ---- a/Makefile -+++ b/Makefile -@@ -4,7 +4,24 @@ SOFTWARE=hotplug2 - VERSION=1.0-alpha - - BINS=hotplug2 hotplug2-modwrap --SUBDIRS=parser rules workers -+SUBDIRS=parser rules -+ -+hotplug2-objs := \ -+ hotplug2.o netlink.o seqnum.o settings.o uevent.o xmemutils.o \ -+ workers/loader.o parser/parser.o parser/buffer.o parser/token.o \ -+ parser/token_queue.o parser/lexer.o rules/ruleset.o rules/rule.o \ -+ rules/condition.o rules/expression.o rules/execution.o \ -+ rules/command.o -+ -+ifdef STATIC_WORKER -+ ifeq ($(wildcard workers/worker_$(STATIC_WORKER).c),) -+ $(error Worker source worker/worker_$(STATIC_WORKER).c not found) -+ endif -+ hotplug2-objs += action.o workers/worker_$(STATIC_WORKER).o -+else -+ SUBDIRS += workers -+endif -+ - DESTDIR= - - -@@ -13,13 +30,16 @@ all: $(BINS) - install: - $(INSTALL_BIN) $(BINS) $(DESTDIR)/sbin/ - -- --hotplug2: hotplug2.o netlink.o seqnum.o settings.o uevent.o xmemutils.o \ -- workers/loader.o parser/parser.o parser/buffer.o parser/token.o \ -- parser/token_queue.o parser/lexer.o rules/ruleset.o rules/rule.o \ -- rules/condition.o rules/expression.o rules/execution.o \ -- rules/command.o -+hotplug2: $(hotplug2-objs) - - coldplug2: coldplug2.o - - include common.mak -+ -+ifdef STATIC_WORKER -+ CFLAGS += -DSTATIC_WORKER=1 -+else -+ CFLAGS += $(FPIC) -+ LDFLAGS += -ldl -+endif -+ ---- a/common.mak -+++ b/common.mak -@@ -1,7 +1,10 @@ +diff -Naur a/common.mak b/common.mak +--- a/common.mak 2009-11-18 13:15:21.000000000 +0000 ++++ b/common.mak 2009-11-18 13:25:18.000000000 +0000 +@@ -1,7 +1,7 @@ # vim:set sw=8 nosta: --CFLAGS=-Os -Wall -g -fPIC + COPTS=-Os -Wall -g -LDFLAGS=-g -ldl -+COPTS=-Os -Wall -g +LDFLAGS=-g -+ -+CFLAGS=$(COPTS) -+FPIC=-fPIC - INSTALL=install -c -m 644 - INSTALL_BIN=install -c -m 755 ---- a/workers/loader.c -+++ b/workers/loader.c -@@ -1,5 +1,23 @@ - #include "loader.h" + CFLAGS=$(COPTS) + FPIC=-fPIC +diff -Naur a/Makefile b/Makefile +--- a/Makefile 2009-11-18 13:15:21.000000000 +0000 ++++ b/Makefile 2009-11-18 13:25:18.000000000 +0000 +@@ -40,5 +40,6 @@ + CFLAGS += -DSTATIC_WORKER=1 + else + CFLAGS += $(FPIC) ++ LDFLAGS += -ldl + endif -+#ifdef STATIC_WORKER -+ -+extern struct worker_module_t worker_module; -+static struct loader_ctx_t static_ctx = { -+ .module = &worker_module -+}; -+ -+struct loader_ctx_t *worker_load(const char *name) -+{ -+ return &static_ctx; -+} -+ -+void worker_free(struct loader_ctx_t *ctx) -+{ -+} -+ -+#else -+ - struct loader_ctx_t *worker_load(const char *name) { - struct loader_ctx_t *ctx; - -@@ -12,7 +30,7 @@ struct loader_ctx_t *worker_load(const c - return NULL; - } - -- ctx->module = dlsym(ctx->dl_handle, "module"); -+ ctx->module = dlsym(ctx->dl_handle, "worker_module"); - if (ctx->module == NULL) { - fprintf(stderr, "Loader error: %s\n", dlerror()); - worker_free(ctx); -@@ -31,3 +49,5 @@ void worker_free(struct loader_ctx_t *ct - - free(ctx); - } -+ -+#endif ---- a/hotplug2.c -+++ b/hotplug2.c -@@ -261,17 +261,21 @@ int main(int argc, char *argv[]) { - } - - /* Load the worker. */ -+#ifndef STATIC_WORKER - if (settings->worker_name == NULL) { - fprintf(stderr, "Missing worker name.\n"); - settings_clear(settings); - exit(1); - } -+#endif - settings->worker = worker_load(settings->worker_name); -+#ifndef STATIC_WORKER - if (settings->worker == NULL) { - fprintf(stderr, "Unable to load worker: %s\n", settings->worker_name); - settings_clear(settings); - exit(1); - } -+#endif - - /* Prepare a netlink connection to the kernel. */ - settings->netlink_socket = netlink_init(); ---- a/workers/worker_example.c -+++ b/workers/worker_example.c -@@ -62,7 +62,7 @@ static int worker_example_process(void * - return 0; - } - --struct worker_module_t module = { -+struct worker_module_t worker_module = { - "Hotplug2 example module", - worker_example_init, - worker_example_deinit, ---- a/workers/worker_fork.c -+++ b/workers/worker_fork.c -@@ -443,7 +443,7 @@ static int worker_fork_process(void *in_ - return 0; - } - --struct worker_module_t module = { -+struct worker_module_t worker_module = { - "Hotplug2 forking module", - worker_fork_init, - worker_fork_deinit, ---- a/workers/worker_single.c -+++ b/workers/worker_single.c -@@ -18,7 +18,7 @@ static int worker_single_process(void *s - return 0; - } - --struct worker_module_t module = { -+struct worker_module_t worker_module = { - "Hotplug2 single process module", - worker_single_init, - worker_single_deinit, diff --git a/package/ipset/Makefile b/package/ipset/Makefile new file mode 100644 index 000000000..7a2e8a1e8 --- /dev/null +++ b/package/ipset/Makefile @@ -0,0 +1,84 @@ +# +# Copyright (C) 2009 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# +# +include $(TOPDIR)/rules.mk +include $(INCLUDE_DIR)/kernel.mk + +PKG_NAME:=ipset +PKG_VERSION:=4.1 +PKG_RELEASE:=1 + +PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2 +PKG_SOURCE_URL:=http://ipset.netfilter.org +PKG_MD5SUM:=d104007fdf5ea64fef774c22b1c0a97b + +include $(INCLUDE_DIR)/package.mk + +define Package/ipset/Default + DEPENDS:= @LINUX_2_6 @(!(TARGET_ps3||TARGET_pxcab)||BROKEN) +endef + +define Package/ipset +$(call Package/ipset/Default) + SECTION:=net + CATEGORY:=Network + DEPENDS+= +iptables-mod-ipset +kmod-ipt-ipset + TITLE:=IPset administration utility + URL:=http://ipset.netfilter.org/ +endef + +include $(INCLUDE_DIR)/kernel-defaults.mk + +IPSET_MAKEOPTS:= -C $(PKG_BUILD_DIR) \ + $(TARGET_CONFIGURE_OPTS) \ + COPT_FLAGS="$(TARGET_CFLAGS)" \ + LDFLAGS="-rdynamic -static-libgcc" \ + NO_EXTRA_WARN_FLAGS=yes \ + KERNEL_DIR="$(LINUX_DIR)" \ + PREFIX=/usr \ + +IPSET_MODULES:= \ + ip_set \ + ip_set_iphash \ + ip_set_ipmap \ + ip_set_ipporthash \ + ip_set_ipportiphash \ + ip_set_ipportnethash \ + ip_set_iptree \ + ip_set_iptreemap \ + ip_set_macipmap \ + ip_set_nethash \ + ip_set_portmap \ + ip_set_setlist \ + ipt_set \ + ipt_SET \ + +define Build/Compile + mkdir -p $(PKG_INSTALL_DIR) + $(MAKE) $(IPSET_MAKEOPTS) binaries + $(MAKE) $(KERNEL_MAKEOPTS) M="$(PKG_BUILD_DIR)/kernel" IP_NF_SET_MAX="256" IP_NF_SET_HASHSIZE="1024" modules + $(MAKE) $(IPSET_MAKEOPTS) DESTDIR="$(PKG_INSTALL_DIR)" binaries_install +endef + +define Package/ipset/install + $(INSTALL_DIR) $(1)/usr/sbin + $(CP) $(PKG_INSTALL_DIR)/usr/sbin/ipset $(1)/usr/sbin/ + $(INSTALL_DIR) $(1)/usr/lib/ipset + $(CP) $(PKG_INSTALL_DIR)/usr/lib/ipset/libipset*.so $(1)/usr/lib/ipset/ +endef + +define KernelPackage/ipt-ipset +$(call Package/ipset/Default) + SUBMENU:=Netfilter Extensions + TITLE:=IPset netfilter modules + DEPENDS+= kmod-ipt-core + FILES:=$(foreach mod,$(IPSET_MODULES),$(PKG_BUILD_DIR)/kernel/$(mod).ko) + AUTOLOAD:=$(call AutoLoad,46,$(IPSET_MODULES)) +endef + +$(eval $(call BuildPackage,ipset)) +$(eval $(call KernelPackage,ipt-ipset)) diff --git a/package/iptables/Makefile b/package/iptables/Makefile index f4d59abd9..60f4754ca 100644 --- a/package/iptables/Makefile +++ b/package/iptables/Makefile @@ -10,7 +10,7 @@ include $(INCLUDE_DIR)/kernel.mk PKG_NAME:=iptables PKG_VERSION:=1.4.4 -PKG_RELEASE:=2 +PKG_RELEASE:=3 PKG_MD5SUM:=08cd9196881657ea0615d926334cb7e9 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2 @@ -33,7 +33,7 @@ endif define Package/iptables/Default SECTION:=net - CATEGORY:=Base system + CATEGORY:=Network URL:=http://netfilter.org/ endef @@ -52,6 +52,7 @@ endef define Package/iptables/description IPv4 firewall administration tool. Includes support for: + - comment - limit - LOG - mac @@ -141,6 +142,18 @@ define Package/iptables-mod-ipsec/description - libipt_policy endef +define Package/iptables-mod-ipset +$(call Package/iptables/Module, @LINUX_2_6) + TITLE:=IPset iptables extensions +endef + +define Package/iptables-mod-ipset/description + IPset iptables extensions. + Includes: + - libipt_set + - libipt_SET +endef + define Package/iptables-mod-nat $(call Package/iptables/Module, +kmod-ipt-nat) TITLE:=Basic NAT extensions @@ -359,6 +372,7 @@ $(eval $(call BuildPlugin,iptables-mod-filter,$(IPT_FILTER-m),$(L7_INSTALL))) $(eval $(call BuildPlugin,iptables-mod-imq,$(IPT_IMQ-m))) $(eval $(call BuildPlugin,iptables-mod-ipopt,$(IPT_IPOPT-m))) $(eval $(call BuildPlugin,iptables-mod-ipsec,$(IPT_IPSEC-m))) +$(eval $(call BuildPlugin,iptables-mod-ipset,ipt_set ipt_SET)) $(eval $(call BuildPlugin,iptables-mod-nat,$(IPT_NAT-m))) $(eval $(call BuildPlugin,iptables-mod-nat-extra,$(IPT_NAT_EXTRA-m))) $(eval $(call BuildPlugin,iptables-mod-iprange,$(IPT_IPRANGE-m))) diff --git a/package/kernel/modules/block.mk b/package/kernel/modules/block.mk index cbdf2b3a0..d6ad6a6a9 100644 --- a/package/kernel/modules/block.mk +++ b/package/kernel/modules/block.mk @@ -192,22 +192,23 @@ define KernelPackage/ide-core CONFIG_IDE_GD_ATAPI=n \ CONFIG_BLK_DEV_IDEDMA_PCI=y \ CONFIG_BLK_DEV_IDEPCI=y -ifeq ($(strip $(call CompareKernelPatchVer,$(KERNEL_PATCHVER),ge,2.6.28)),1) - FILES:= \ + FILES:= \ $(LINUX_DIR)/drivers/ide/ide-core.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/ide/ide-gd_mod.$(LINUX_KMOD_SUFFIX) - AUTOLOAD:=$(call AutoLoad,20,ide-core) $(call AutoLoad,40,ide-gd_mod) -else - FILES:= \ - $(LINUX_DIR)/drivers/ide/ide-core.$(LINUX_KMOD_SUFFIX) \ - $(LINUX_DIR)/drivers/ide/ide-disk.$(LINUX_KMOD_SUFFIX) - AUTOLOAD:=$(call AutoLoad,20,ide-core) $(call AutoLoad,40,ide-disk) -endif + AUTOLOAD:= \ + $(call AutoLoad,20,ide-core) \ + $(call AutoLoad,40,ide-gd_mod) endef define KernelPackage/ide-core/2.4 - FILES+=$(LINUX_DIR)/drivers/ide/ide-detect.$(LINUX_KMOD_SUFFIX) - AUTOLOAD+=$(call AutoLoad,35,ide-detect) + FILES:= \ + $(LINUX_DIR)/drivers/ide/ide-core.$(LINUX_KMOD_SUFFIX) \ + $(LINUX_DIR)/drivers/ide/ide-detect.$(LINUX_KMOD_SUFFIX) \ + $(LINUX_DIR)/drivers/ide/ide-disk.$(LINUX_KMOD_SUFFIX) + AUTOLOAD:= \ + $(call AutoLoad,20,ide-core) \ + $(call AutoLoad,35,ide-detect) \ + $(call AutoLoad,40,ide-disk) endef ifneq ($(CONFIG_arm)$(CONFIG_powerpc),y) @@ -233,14 +234,14 @@ define KernelPackage/ide-aec62xx TITLE:=Acard AEC62xx IDE driver DEPENDS:=@PCI_SUPPORT +kmod-ide-core KCONFIG:=CONFIG_BLK_DEV_AEC62XX -ifeq ($(strip $(call CompareKernelPatchVer,$(KERNEL_PATCHVER),ge,2.6.28)),1) FILES:=$(LINUX_DIR)/drivers/ide/aec62xx.$(LINUX_KMOD_SUFFIX) -else - FILES:=$(LINUX_DIR)/drivers/ide/pci/aec62xx.$(LINUX_KMOD_SUFFIX) -endif AUTOLOAD:=$(call AutoLoad,30,aec62xx) endef +define KernelPackage/ide-aec62xx/2.4 + FILES:=$(LINUX_DIR)/drivers/ide/pci/aec62xx.$(LINUX_KMOD_SUFFIX) +endef + define KernelPackage/ide-aec62xx/description Support for Acard AEC62xx (Artop ATP8xx) IDE controllers. endef @@ -269,11 +270,7 @@ define KernelPackage/ide-pdc202xx TITLE:=Promise PDC202xx IDE driver DEPENDS:=+kmod-ide-core KCONFIG:=CONFIG_BLK_DEV_PDC202XX_OLD - ifeq ($(strip $(call CompareKernelPatchVer,$(KERNEL_PATCHVER),ge,2.6.28)),1) FILES:=$(LINUX_DIR)/drivers/ide/pdc202xx_old.$(LINUX_KMOD_SUFFIX) - else - FILES:=$(LINUX_DIR)/drivers/ide/pci/pdc202xx_old.$(LINUX_KMOD_SUFFIX) - endif AUTOLOAD:=$(call AutoLoad,30,pdc202xx_old) endef @@ -294,11 +291,7 @@ define KernelPackage/ide-it821x TITLE:=ITE IT821x IDE driver DEPENDS:=+kmod-ide-core KCONFIG:=CONFIG_BLK_DEV_IT821X -ifeq ($(strip $(call CompareKernelPatchVer,$(KERNEL_PATCHVER),ge,2.6.28)),1) FILES=$(LINUX_DIR)/drivers/ide/it821x.$(LINUX_KMOD_SUFFIX) -else - FILES=$(LINUX_DIR)/drivers/ide/pci/it821x.$(LINUX_KMOD_SUFFIX) -endif AUTOLOAD:=$(call AutoLoad,30,it821x) endef diff --git a/package/kernel/modules/crypto.mk b/package/kernel/modules/crypto.mk index 012b68bef..1d0985b02 100644 --- a/package/kernel/modules/crypto.mk +++ b/package/kernel/modules/crypto.mk @@ -14,39 +14,22 @@ CRYPTO_MENU:=Cryptographic API modules # - sha1 > sha1_generic (2.6.24) # - sha256 > sha256_generic (2.6.24) # - sha512 > sha512_generic (2.6.26) -ifeq ($(strip $(call CompareKernelPatchVer,$(KERNEL_PATCHVER),ge,2.6.24)),1) +ifneq ($(CONFIG_LINUX_2_6),) CRYPTO_GENERIC:=_generic AES_SUFFIX:=$(CRYPTO_GENERIC) DES_SUFFIX:=$(CRYPTO_GENERIC) SHA1_SUFFIX:=$(CRYPTO_GENERIC) SHA256_SUFFIX:=$(CRYPTO_GENERIC) -endif -ifeq ($(strip $(call CompareKernelPatchVer,$(KERNEL_PATCHVER),ge,2.6.25)),1) - CRYPTO_PREFIX:=crypto_ - BLKCIPHER_PREFIX:=$(CRYPTO_PREFIX) -endif -ifeq ($(strip $(call CompareKernelPatchVer,$(KERNEL_PATCHVER),ge,2.6.26)),1) SHA512_SUFFIX:=$(CRYPTO_GENERIC) endif -AEAD_CONF:=AEAD -MANAGER_CONF:=MANAGER -BLKCIPHER_CONF:=BLKCIPHER -HASH_CONF:=HASH -ifeq ($(strip $(call CompareKernelPatchVer,$(KERNEL_PATCHVER),ge,2.6.30)),1) - CRYPTO_MODULE_PCOMPRESS:=PCOMP=pcompress - AEAD_CONF:=AEAD2 - MANAGER_CONF:=MANAGER2 - BLKCIPHER_CONF:=BLKCIPHER2 - HASH_CONF:=HASH2 -endif CRYPTO_MODULES = \ ALGAPI=crypto_algapi \ - $(AEAD_CONF)=aead \ - $(CRYPTO_MODULE_PCOMPRESS) \ - $(BLKCIPHER_CONF)=$(BLKCIPHER_PREFIX)blkcipher \ - $(HASH_CONF)=crypto_hash \ - $(MANAGER_CONF)=cryptomgr \ + AEAD2=aead \ + PCOMP=pcompress \ + BLKCIPHER2=crypto_blkcipher \ + HASH2=crypto_hash \ + MANAGER2=cryptomgr \ CBC=cbc \ ECB=ecb \ DEFLATE=deflate diff --git a/package/kernel/modules/fs.mk b/package/kernel/modules/fs.mk index 3755f0f66..84d482657 100644 --- a/package/kernel/modules/fs.mk +++ b/package/kernel/modules/fs.mk @@ -111,12 +111,6 @@ endef $(eval $(call KernelPackage,fs-ext3)) -ifeq ($(strip $(call CompareKernelPatchVer,$(KERNEL_PATCHVER),lt,2.6.28)),1) - EXT4_NAME:=ext4dev -else - EXT4_NAME:=ext4 -endif - define KernelPackage/fs-ext4 SUBMENU:=$(FS_MENU) TITLE:=EXT4 filesystem support @@ -129,7 +123,7 @@ define KernelPackage/fs-ext4 CONFIG_JBD2 DEPENDS:= @LINUX_2_6 +kmod-crc16 $(if $(DUMP)$(CONFIG_FS_MBCACHE),+kmod-fs-mbcache) FILES:= \ - $(LINUX_DIR)/fs/ext4/$(EXT4_NAME).$(LINUX_KMOD_SUFFIX) \ + $(LINUX_DIR)/fs/ext4/ext4.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/fs/jbd2/jbd2.$(LINUX_KMOD_SUFFIX) AUTOLOAD:=$(call AutoLoad,30,jbd2 $(EXT4_NAME)) endef @@ -277,21 +271,18 @@ endef $(eval $(call KernelPackage,fs-nfsd)) - -ifeq ($(strip $(call CompareKernelPatchVer,$(KERNEL_PATCHVER),ge,2.6.28)),1) - MSDOS_DIR:=fat -endif -MSDOS_DIR?=msdos - define KernelPackage/fs-msdos SUBMENU:=$(FS_MENU) TITLE:=MSDOS filesystem support KCONFIG:=CONFIG_MSDOS_FS - FILES:=$(LINUX_DIR)/fs/$(MSDOS_DIR)/msdos.$(LINUX_KMOD_SUFFIX) + FILES:=$(LINUX_DIR)/fs/fat/msdos.$(LINUX_KMOD_SUFFIX) AUTOLOAD:=$(call AutoLoad,40,msdos) $(call KernelPackage/nls/Depends) endef +define KernelPackage/fs-msdos/2.4 + FILES:=$(LINUX_DIR)/fs/msdos/msdos.$(LINUX_KMOD_SUFFIX) +endef define KernelPackage/fs-msdos/description Kernel module for MSDOS filesystem support @@ -314,11 +305,6 @@ endef $(eval $(call KernelPackage,fs-reiserfs)) -ifeq ($(strip $(call CompareKernelPatchVer,$(KERNEL_PATCHVER),ge,2.6.28)),1) - VFAT_DIR:=fat -endif -VFAT_DIR?=vfat - define KernelPackage/fs-vfat SUBMENU:=$(FS_MENU) TITLE:=VFAT filesystem support @@ -327,11 +313,16 @@ define KernelPackage/fs-vfat CONFIG_VFAT_FS FILES:= \ $(LINUX_DIR)/fs/fat/fat.$(LINUX_KMOD_SUFFIX) \ - $(LINUX_DIR)/fs/$(VFAT_DIR)/vfat.$(LINUX_KMOD_SUFFIX) + $(LINUX_DIR)/fs/fat/vfat.$(LINUX_KMOD_SUFFIX) AUTOLOAD:=$(call AutoLoad,30,fat vfat) $(call KernelPackage/nls/Depends) endef +define KernelPackage/fs-vfat/2.4 + FILES:= \ + $(LINUX_DIR)/fs/fat/fat.$(LINUX_KMOD_SUFFIX) \ + $(LINUX_DIR)/fs/vfat/vfat.$(LINUX_KMOD_SUFFIX) +endef define KernelPackage/fs-vfat/description Kernel module for VFAT filesystem support @@ -364,7 +355,7 @@ define KernelPackage/fs-btrfs CONFIG_BTRFS_FS \ CONFIG_BTRFS_FS_POSIX_ACL=n # for crc32c - DEPENDS:=+kmod-crypto-core @!LINUX_2_6_21&&!LINUX_2_6_25&&!LINUX_2_6_28 + DEPENDS:=+kmod-crypto-core @!LINUX_2_6_21&&!LINUX_2_6_25 FILES:=\ $(LINUX_DIR)/crypto/crc32c.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/lib/libcrc32c.$(LINUX_KMOD_SUFFIX) \ @@ -459,6 +450,23 @@ endef $(eval $(call KernelPackage,nls-cp852)) +define KernelPackage/nls-cp866 + SUBMENU:=$(FS_MENU) + TITLE:=Codepage 866 (Cyrillic) + KCONFIG:=CONFIG_NLS_CODEPAGE_866 + FILES:=$(LINUX_DIR)/fs/nls/nls_cp866.$(LINUX_KMOD_SUFFIX) + AUTOLOAD:=$(call AutoLoad,25,nls_cp866) +$(call KernelPackage/nls/Depends) +endef + + +define KernelPackage/nls-cp866/description + Kernel module for NLS Codepage 866 (Cyrillic) +endef + +$(eval $(call KernelPackage,nls-cp866)) + + define KernelPackage/nls-cp1250 SUBMENU:=$(FS_MENU) TITLE:=Codepage 1250 (Eastern Europe) diff --git a/package/kernel/modules/netdevices.mk b/package/kernel/modules/netdevices.mk index f270c7f8e..b283855b0 100644 --- a/package/kernel/modules/netdevices.mk +++ b/package/kernel/modules/netdevices.mk @@ -290,7 +290,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_28||LINUX_2_6_30||LINUX_2_6_31:kmod-libphy @!TARGET_ubicom32 + DEPENDS:=@LINUX_2_6 +LINUX_2_6_30||LINUX_2_6_31:kmod-libphy @!TARGET_ubicom32 SUBMENU:=$(NETWORK_DEVICES_MENU) AUTOLOAD:=$(call AutoLoad,50,tg3) endef @@ -359,3 +359,19 @@ endef $(eval $(call KernelPackage,gigaset)) + +define KernelPackage/macvlan + SUBMENU:=$(NETWORK_DEVICES_MENU) + TITLE:=MAC-VLAN support + DEPENDS:=@LINUX_2_6 @!LINUX_2_6_21 + KCONFIG:=CONFIG_MACVLAN + FILES:=$(LINUX_DIR)/drivers/net/macvlan.$(LINUX_KMOD_SUFFIX) + AUTOLOAD:=$(call AutoLoad,50,macvlan) +endef + +define KernelPackage/macvlan/description + A kernel module which allows one to create virtual interfaces that + map packets to or from specific MAC addresses to a particular interface. +endef + +$(eval $(call KernelPackage,macvlan)) diff --git a/package/kernel/modules/netfilter.mk b/package/kernel/modules/netfilter.mk index 9c97379ab..1b4c6922a 100644 --- a/package/kernel/modules/netfilter.mk +++ b/package/kernel/modules/netfilter.mk @@ -286,6 +286,7 @@ $(eval $(call KernelPackage,ipt-ulog)) define KernelPackage/ipt-iprange SUBMENU:=$(NF_MENU) TITLE:=Module for matching ip ranges + KCONFIG:=$(KCONFIG_IPT_IPRANGE) FILES:=$(foreach mod,$(IPT_IPRANGE-m),$(LINUX_DIR)/net/$(mod).$(LINUX_KMOD_SUFFIX)) AUTOLOAD:=$(call AutoLoad,45,$(notdir $(IPT_IPRANGE-m))) DEPENDS:= kmod-ipt-core diff --git a/package/kernel/modules/netsupport.mk b/package/kernel/modules/netsupport.mk index c58dfcb3a..5b58aae03 100644 --- a/package/kernel/modules/netsupport.mk +++ b/package/kernel/modules/netsupport.mk @@ -577,7 +577,7 @@ $(eval $(call KernelPackage,sched)) define KernelPackage/ax25 SUBMENU:=$(NETWORK_SUPPORT_MENU) TITLE:=AX25 support - DEPENDS:=kmod-crc16 + DEPENDS:= +kmod-crc16 KCONFIG:= \ CONFIG_AX25 \ CONFIG_MKISS diff --git a/package/kernel/modules/other.mk b/package/kernel/modules/other.mk index 2116dd0cb..73466bb2f 100644 --- a/package/kernel/modules/other.mk +++ b/package/kernel/modules/other.mk @@ -71,11 +71,7 @@ define KernelPackage/eeprom-93cx6 TITLE:=EEPROM 93CX6 support DEPENDS:=@LINUX_2_6 KCONFIG:=CONFIG_EEPROM_93CX6 -ifeq ($(strip $(call CompareKernelPatchVer,$(KERNEL_PATCHVER),ge,2.6.29)),1) FILES:=$(LINUX_DIR)/drivers/misc/eeprom/eeprom_93cx6.$(LINUX_KMOD_SUFFIX) -else - FILES:=$(LINUX_DIR)/drivers/misc/eeprom_93cx6.$(LINUX_KMOD_SUFFIX) -endif AUTOLOAD:=$(call AutoLoad,20,eeprom_93cx6) endef @@ -305,7 +301,6 @@ define KernelPackage/bluetooth/2.6 # CONFIG_BT_BNEP \ # CONFIG_BT_HCIUSB \ # CONFIG_BT_HCIUART -ifeq ($(strip $(call CompareKernelPatchVer,$(KERNEL_PATCHVER),ge,2.6.27)),1) FILES:= \ $(LINUX_DIR)/net/bluetooth/bluetooth.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/net/bluetooth/l2cap.$(LINUX_KMOD_SUFFIX) \ @@ -316,18 +311,6 @@ ifeq ($(strip $(call CompareKernelPatchVer,$(KERNEL_PATCHVER),ge,2.6.27)),1) $(LINUX_DIR)/drivers/bluetooth/hci_uart.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/drivers/bluetooth/btusb.$(LINUX_KMOD_SUFFIX) AUTOLOAD:=$(call AutoLoad,90,bluetooth l2cap sco rfcomm bnep hidp hci_uart btusb) -else - FILES:= \ - $(LINUX_DIR)/net/bluetooth/bluetooth.$(LINUX_KMOD_SUFFIX) \ - $(LINUX_DIR)/net/bluetooth/l2cap.$(LINUX_KMOD_SUFFIX) \ - $(LINUX_DIR)/net/bluetooth/sco.$(LINUX_KMOD_SUFFIX) \ - $(LINUX_DIR)/net/bluetooth/rfcomm/rfcomm.$(LINUX_KMOD_SUFFIX) \ - $(LINUX_DIR)/net/bluetooth/bnep/bnep.$(LINUX_KMOD_SUFFIX) \ - $(LINUX_DIR)/net/bluetooth/hidp/hidp.$(LINUX_KMOD_SUFFIX) \ - $(LINUX_DIR)/drivers/bluetooth/hci_uart.$(LINUX_KMOD_SUFFIX) \ - $(LINUX_DIR)/drivers/bluetooth/hci_usb.$(LINUX_KMOD_SUFFIX) - AUTOLOAD:=$(call AutoLoad,90,bluetooth l2cap sco rfcomm bnep hidp hci_uart hci_usb) -endif endef define KernelPackage/bluetooth/description @@ -384,10 +367,7 @@ $(eval $(call KernelPackage,mmc-at91)) ifeq ($(KERNEL),2.4) WATCHDOG_DIR=char endif -ifeq ($(strip $(call CompareKernelPatchVer,$(KERNEL_PATCHVER),ge,2.6.24)),1) - WATCHDOG_DIR=watchdog -endif -WATCHDOG_DIR?=char/watchdog +WATCHDOG_DIR?=watchdog define KernelPackage/atmel-wdt SUBMENU:=$(OTHER_MENU) @@ -425,7 +405,7 @@ define KernelPackage/rdc321x-wdt DEPENDS:=@TARGET_rdc KCONFIG:=CONFIG_RDC321X_WDT FILES:=$(LINUX_DIR)/drivers/$(WATCHDOG_DIR)/rdc321x_wdt.$(LINUX_KMOD_SUFFIX) - AUTOLOAD:=$(call AutoLoad,50,rdc321_wdt) + AUTOLOAD:=$(call AutoLoad,50,rdc321x_wdt) endef define KernelPackage/rdc321x-wdt/description @@ -516,6 +496,22 @@ endef $(eval $(call KernelPackage,leds-alix)) +define KernelPackage/leds-wndr3700-usb + SUBMENU:=$(OTHER_MENU) + TITLE:=WNDR3700 USB LED support + DEPENDS:= @TARGET_ar71xx + KCONFIG:=CONFIG_LEDS_WNDR3700_USB + FILES:=$(LINUX_DIR)/drivers/leds/leds-wndr3700-usb.$(LINUX_KMOD_SUFFIX) + AUTOLOAD:=$(call AutoLoad,60,leds-wndr3700-usb) +endef + +define KernelPackage/leds-wndr3700-usb/description + Kernel module for the USB LED on the NETGWR WNDR3700 board. +endef + +$(eval $(call KernelPackage,leds-wndr3700-usb)) + + define KernelPackage/ledtrig-netdev SUBMENU:=$(OTHER_MENU) TITLE:=LED NETDEV Trigger @@ -811,10 +807,10 @@ $(eval $(call KernelPackage,textsearch)) define KernelPackage/rfkill SUBMENU:=$(OTHER_MENU) TITLE:=RF switch subsystem support - DEPENDS:=@TARGET_x86||TARGET_olpc||TARGET_s3c24xx||TARGET_brcm47xx + DEPENDS:=@TARGET_x86||TARGET_olpc||TARGET_s3c24xx||TARGET_brcm47xx||TARGET_ar71xx KCONFIG:= \ CONFIG_RFKILL \ - CONFIG_RFKILL_INPUT \ + CONFIG_RFKILL_INPUT=y \ CONFIG_RFKILL_LEDS=y ifeq ($(strip $(call CompareKernelPatchVer,$(KERNEL_PATCHVER),ge,2.6.31)),1) FILES:= \ diff --git a/package/kernel/modules/sound.mk b/package/kernel/modules/sound.mk index 1d3a5bee6..0e7cefe56 100644 --- a/package/kernel/modules/sound.mk +++ b/package/kernel/modules/sound.mk @@ -10,7 +10,7 @@ SOUND_MENU:=Sound Support define KernelPackage/sound-core SUBMENU:=$(SOUND_MENU) TITLE:=Sound support - DEPENDS:=@PCI_SUPPORT||USB_SUPPORT + DEPENDS:=@PCI_SUPPORT||USB_SUPPORT||TARGET_uml KCONFIG:= \ CONFIG_SOUND \ CONFIG_SND \ @@ -63,7 +63,7 @@ define KernelPackage/sound-core/2.6 AUTOLOAD:=$(call AutoLoad,30,$(SOUNDCORE_LOAD)) endef -define KernelPackage/sound-core/uml-2.6 +define KernelPackage/sound-core/uml FILES:= \ $(LINUX_DIR)/sound/soundcore.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/arch/um/drivers/hostaudio.$(LINUX_KMOD_SUFFIX) @@ -79,7 +79,7 @@ $(eval $(call KernelPackage,sound-core)) define KernelPackage/sound-i8x0 SUBMENU:=$(SOUND_MENU) TITLE:=Intel/SiS/nVidia/AMD/ALi AC97 Controller - DEPENDS:=kmod-sound-core + DEPENDS:=kmod-sound-core @!TARGET_uml KCONFIG:=CONFIG_SND_INTEL8X0 FILES:=$(LINUX_DIR)/sound/pci/snd-intel8x0.$(LINUX_KMOD_SUFFIX) AUTOLOAD:=$(call AutoLoad,35,snd-i8x0) @@ -96,7 +96,7 @@ $(eval $(call KernelPackage,sound-i8x0)) define KernelPackage/sound-ps3 SUBMENU:=$(SOUND_MENU) TITLE:=PS3 Audio - DEPENDS:=kmod-sound-core @TARGET_ps3 + DEPENDS:=kmod-sound-core @TARGET_ps3||@TARGET_ps3chk KCONFIG:=CONFIG_SND_PS3 \ CONFIG_SND_PPC=y \ CONFIG_SND_PS3_DEFAULT_START_DELAY=2000 @@ -113,7 +113,7 @@ $(eval $(call KernelPackage,sound-ps3)) define KernelPackage/sound-cs5535audio SUBMENU:=$(SOUND_MENU) TITLE:=CS5535 PCI Controller - DEPENDS:=kmod-sound-core + DEPENDS:=kmod-sound-core @!TARGET_uml KCONFIG:=CONFIG_SND_CS5535AUDIO FILES:=$(LINUX_DIR)/sound/pci/cs5535audio/snd-cs5535audio.$(LINUX_KMOD_SUFFIX) \ $(LINUX_DIR)/sound/ac97_bus.$(LINUX_KMOD_SUFFIX) \ diff --git a/package/kernel/modules/spi.mk b/package/kernel/modules/spi.mk index 48e105f2c..ed1ab010d 100644 --- a/package/kernel/modules/spi.mk +++ b/package/kernel/modules/spi.mk @@ -81,7 +81,7 @@ define KernelPackage/spi-dev CONFIG_SPI=y \ CONFIG_SPI_MASTER=y FILES:=$(LINUX_DIR)/drivers/spi/spidev.$(LINUX_KMOD_SUFFIX) - AUTOLOAD:=$(call AutoLoad,91,spidev) + AUTOLOAD:=$(call AutoLoad,93,spidev) endef define KernelPackage/spi-dev/description diff --git a/package/kernel/modules/usb.mk b/package/kernel/modules/usb.mk index 831716172..2aaed3ca5 100644 --- a/package/kernel/modules/usb.mk +++ b/package/kernel/modules/usb.mk @@ -301,7 +301,7 @@ $(eval $(call KernelPackage,usb-serial-belkin)) define KernelPackage/usb-serial-ch341 - $(call usbdep,kmod-usb-serial @LINUX_2_6&&@!LINUX_2_6_23) + $(call usbdep,kmod-usb-serial @LINUX_2_6) TITLE:=Support for CH341 devices KCONFIG:=CONFIG_USB_SERIAL_CH341 FILES:=$(LINUX_DIR)/drivers/usb/serial/ch341.$(LINUX_KMOD_SUFFIX) @@ -514,7 +514,7 @@ define KernelPackage/usb-video TITLE:=Support for USB video devices KCONFIG:=CONFIG_VIDEO_USBVIDEO FILES:=$(LINUX_DIR)/drivers/media/video/usbvideo/usbvideo.$(LINUX_KMOD_SUFFIX) - AUTOLOAD:=$(call AutoLoad,60,usbvideo) + AUTOLOAD:=$(call AutoLoad,61,usbvideo) endef define KernelPackage/usb-video/description @@ -621,7 +621,7 @@ $(eval $(call KernelPackage,usb-net-asix)) define KernelPackage/usb-net-hso - $(call usbdep,kmod-usb-net @LINUX_2_6 @!LINUX_2_6_21 @!LINUX_2_6_23 @!LINUX_2_6_24 @!LINUX_2_6_25 +!TARGET_rb532||!TARGET_avr32||!TARGET_brcm47xx||!TARGET_s3c24xx||!TARGET_ifxmips||!TARGET_atheros||!TARGET_adm5120||!TARGET_ar7||!TARGET_ppc40x||!TARGET_ixp4xx||!TARGET_rdc:kmod-rfkill) + $(call usbdep,kmod-usb-net @LINUX_2_6 @!LINUX_2_6_21 @!LINUX_2_6_25 +!TARGET_rb532||!TARGET_avr32||!TARGET_brcm47xx||!TARGET_s3c24xx||!TARGET_ifxmips||!TARGET_atheros||!TARGET_adm5120||!TARGET_ar7||!TARGET_ppc40x||!TARGET_ixp4xx||!TARGET_rdc:kmod-rfkill) TITLE:=Kernel module for Option USB High Speed Mobile Devices KCONFIG:=CONFIG_USB_HSO FILES:= \ diff --git a/package/kernel/modules/video.mk b/package/kernel/modules/video.mk index f1ee75a85..17aab2705 100644 --- a/package/kernel/modules/video.mk +++ b/package/kernel/modules/video.mk @@ -16,6 +16,7 @@ define KernelPackage/video-core CONFIG_MEDIA_SUPPORT=m \ CONFIG_VIDEO_DEV \ CONFIG_VIDEO_V4L1=y \ + CONFIG_VIDEO_ALLOW_V4L1=y \ CONFIG_VIDEO_CAPTURE_DRIVERS=y \ CONFIG_V4L_USB_DRIVERS=y endef @@ -25,7 +26,6 @@ define KernelPackage/video-core/2.4 AUTOLOAD:=$(call AutoLoad,60,videodev) endef -ifeq ($(strip $(call CompareKernelPatchVer,$(KERNEL_PATCHVER),ge,2.6.29)),1) define KernelPackage/video-core/2.6 FILES:= \ $(LINUX_DIR)/drivers/media/video/v4l2-common.$(LINUX_KMOD_SUFFIX) \ @@ -37,21 +37,6 @@ define KernelPackage/video-core/2.6 v4l2-common \ ) endef -else -define KernelPackage/video-core/2.6 - FILES:= \ - $(LINUX_DIR)/drivers/media/video/v4l2-common.$(LINUX_KMOD_SUFFIX) \ - $(LINUX_DIR)/drivers/media/video/v4l1-compat.$(LINUX_KMOD_SUFFIX) \ - $(LINUX_DIR)/drivers/media/video/compat_ioctl32.$(LINUX_KMOD_SUFFIX) \ - $(LINUX_DIR)/drivers/media/video/videodev.$(LINUX_KMOD_SUFFIX) - AUTOLOAD:=$(call AutoLoad,60, \ - v4l1-compat \ - videodev \ - v4l2-common \ - compat_ioctl32 \ - ) -endef -endif define KernelPackage/video-core/description Kernel modules for Video4Linux support @@ -167,7 +152,7 @@ $(eval $(call KernelPackage,video-pwc)) define KernelPackage/video-uvc SUBMENU:=$(VIDEO_MENU) TITLE:=USB Video Class (UVC) support - DEPENDS:=@LINUX_2_6 @!LINUX_2_6_25 @!LINUX_2_6_24 @!LINUX_2_6_23 @USB_SUPPORT +kmod-usb-core +kmod-video-core + DEPENDS:=@LINUX_2_6 @!LINUX_2_6_25 @USB_SUPPORT +kmod-usb-core +kmod-video-core KCONFIG:= CONFIG_USB_VIDEO_CLASS FILES:=$(LINUX_DIR)/drivers/media/video/uvc/uvcvideo.$(LINUX_KMOD_SUFFIX) AUTOLOAD:=$(call AutoLoad,90,uvcvideo) @@ -266,7 +251,7 @@ $(eval $(call KernelPackage,video-gspca-mars)) define KernelPackage/video-gspca-mr97310a SUBMENU:=$(VIDEO_MENU) TITLE:=mr97310a webcam support - DEPENDS:=kmod-video-gspca-core @!LINUX_2_6_28 + DEPENDS:=kmod-video-gspca-core KCONFIG:=CONFIG_USB_GSPCA_MR97310A FILES:=$(LINUX_DIR)/drivers/media/video/gspca/gspca_mr97310a.$(LINUX_KMOD_SUFFIX) AUTOLOAD:=$(call AutoLoad,75,gspca_mr97310a) @@ -298,7 +283,7 @@ $(eval $(call KernelPackage,video-gspca-ov519)) define KernelPackage/video-gspca-ov534 SUBMENU:=$(VIDEO_MENU) TITLE:=ov534 webcam support - DEPENDS:=kmod-video-gspca-core @!LINUX_2_6_28 + DEPENDS:=kmod-video-gspca-core KCONFIG:=CONFIG_USB_GSPCA_OV534 FILES:=$(LINUX_DIR)/drivers/media/video/gspca/gspca_ov534.$(LINUX_KMOD_SUFFIX) AUTOLOAD:=$(call AutoLoad,75,gspca_ov534) @@ -474,7 +459,7 @@ $(eval $(call KernelPackage,video-gspca-spca561)) define KernelPackage/video-gspca-sq905 SUBMENU:=$(VIDEO_MENU) TITLE:=sq905 webcam support - DEPENDS:=kmod-video-gspca-core @!LINUX_2_6_28 + DEPENDS:=kmod-video-gspca-core KCONFIG:=CONFIG_USB_GSPCA_SQ905 FILES:=$(LINUX_DIR)/drivers/media/video/gspca/gspca_sq905.$(LINUX_KMOD_SUFFIX) AUTOLOAD:=$(call AutoLoad,75,gspca_sq905) @@ -490,7 +475,7 @@ $(eval $(call KernelPackage,video-gspca-sq905)) define KernelPackage/video-gspca-sq905c SUBMENU:=$(VIDEO_MENU) TITLE:=sq905c webcam support - DEPENDS:=kmod-video-gspca-core @!LINUX_2_6_28 + DEPENDS:=kmod-video-gspca-core KCONFIG:=CONFIG_USB_GSPCA_SQ905C FILES:=$(LINUX_DIR)/drivers/media/video/gspca/gspca_sq905c.$(LINUX_KMOD_SUFFIX) AUTOLOAD:=$(call AutoLoad,75,gspca_sq905c) @@ -618,7 +603,7 @@ $(eval $(call KernelPackage,video-gspca-m5602)) define KernelPackage/video-gspca-stv06xx SUBMENU:=$(VIDEO_MENU) TITLE:=stv06xx webcam support - DEPENDS:=kmod-video-gspca-core @!LINUX_2_6_28 + DEPENDS:=kmod-video-gspca-core KCONFIG:=CONFIG_USB_STV06XX FILES:=$(LINUX_DIR)/drivers/media/video/gspca/stv06xx/gspca_stv06xx.$(LINUX_KMOD_SUFFIX) AUTOLOAD:=$(call AutoLoad,75,gspca_stv06xx) diff --git a/package/kernel/modules/wireless.mk b/package/kernel/modules/wireless.mk index 609e04bf8..19f07408c 100644 --- a/package/kernel/modules/wireless.mk +++ b/package/kernel/modules/wireless.mk @@ -12,7 +12,7 @@ WIRELESS_MENU:=Wireless Drivers define KernelPackage/ieee80211 SUBMENU:=$(WIRELESS_MENU) TITLE:=802.11 Networking stack - DEPENDS:=+kmod-crypto-arc4 +kmod-crypto-aes +kmod-crypto-michael-mic @LINUX_2_4||@LINUX_2_6_21||LINUX_2_6_23||LINUX_2_6_24||LINUX_2_6_25||LINUX_2_6_26||LINUX_2_6_28 + DEPENDS:=+kmod-crypto-arc4 +kmod-crypto-aes +kmod-crypto-michael-mic @LINUX_2_4||@LINUX_2_6_21||LINUX_2_6_25 KCONFIG:= \ CONFIG_IEEE80211 \ CONFIG_IEEE80211_CRYPT_WEP \ @@ -49,7 +49,7 @@ $(eval $(call KernelPackage,ieee80211)) define KernelPackage/lib80211 SUBMENU:=$(WIRELESS_MENU) TITLE:=802.11 Networking stack - DEPENDS:=@LINUX_2_6_30||LINUX_2_6_31 + DEPENDS:=@LINUX_2_6_30||LINUX_2_6_31||LINUX_2_6_32 KCONFIG:= \ CONFIG_LIB80211 \ CONFIG_LIB80211_CRYPT_WEP \ @@ -80,16 +80,12 @@ endef $(eval $(call KernelPackage,lib80211)) -ifeq ($(strip $(call CompareKernelPatchVer,$(KERNEL_PATCHVER),ge,2.6.29)),1) - IPW_DIR:=ipw2x00/ -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_30||LINUX_2_6_31 + DEPENDS:=@PCI_SUPPORT +kmod-crypto-arc4 +kmod-crypto-aes +kmod-crypto-michael-mic +kmod-lib80211 @LINUX_2_6_30||LINUX_2_6_31||LINUX_2_6_32 KCONFIG:=CONFIG_LIBIPW - FILES:=$(LINUX_DIR)/drivers/net/wireless/$(IPW_DIR)libipw.$(LINUX_KMOD_SUFFIX) + FILES:=$(LINUX_DIR)/drivers/net/wireless/ipw2x00/libipw.$(LINUX_KMOD_SUFFIX) AUTOLOAD:=$(call AutoLoad,49,libipw) endef @@ -105,7 +101,7 @@ define KernelPackage/net-ipw2100 TITLE:=Intel IPW2100 driver DEPENDS:=@PCI_SUPPORT +!(LINUX_2_6_30||LINUX_2_6_31):kmod-ieee80211 +LINUX_2_6_30||LINUX_2_6_31:kmod-net-libipw KCONFIG:=CONFIG_IPW2100 - FILES:=$(LINUX_DIR)/drivers/net/wireless/$(IPW_DIR)ipw2100.$(LINUX_KMOD_SUFFIX) + FILES:=$(LINUX_DIR)/drivers/net/wireless/ipw2x00/ipw2100.$(LINUX_KMOD_SUFFIX) AUTOLOAD:=$(call AutoLoad,50,ipw2100) endef @@ -123,7 +119,7 @@ define KernelPackage/net-ipw2200 TITLE:=Intel IPW2200 driver DEPENDS:=@PCI_SUPPORT +!(LINUX_2_6_30||LINUX_2_6_31):kmod-ieee80211 +LINUX_2_6_30||LINUX_2_6_31:kmod-net-libipw KCONFIG:=CONFIG_IPW2200 - FILES:=$(LINUX_DIR)/drivers/net/wireless/$(IPW_DIR)ipw2200.$(LINUX_KMOD_SUFFIX) + FILES:=$(LINUX_DIR)/drivers/net/wireless/ipw2x00/ipw2200.$(LINUX_KMOD_SUFFIX) AUTOLOAD:=$(call AutoLoad,50,ipw2200) endef @@ -152,34 +148,15 @@ endef $(eval $(call KernelPackage,net-airo)) -ifeq ($(strip $(call CompareKernelPatchVer,$(KERNEL_PATCHVER),ge,2.6.29)),1) - ORINOCO_DIR:=orinoco/ -endif - define KernelPackage/net-hermes SUBMENU:=$(WIRELESS_MENU) TITLE:=Hermes 802.11b chipset support DEPENDS:=@LINUX_2_6 @PCI_SUPPORT||PCMCIA_SUPPORT KCONFIG:=CONFIG_HERMES \ CONFIG_HERMES_CACHE_FW_ON_INIT=n -ifeq ($(strip $(call CompareKernelPatchVer,$(KERNEL_PATCHVER),ge,2.6.30)),1) FILES:= \ - $(LINUX_DIR)/drivers/net/wireless/$(ORINOCO_DIR)orinoco.$(LINUX_KMOD_SUFFIX) + $(LINUX_DIR)/drivers/net/wireless/orinoco/orinoco.$(LINUX_KMOD_SUFFIX) AUTOLOAD:=$(call AutoLoad,50,orinoco) -else -ifeq ($(strip $(call CompareKernelPatchVer,$(KERNEL_PATCHVER),ge,2.6.28)),1) - FILES:= \ - $(LINUX_DIR)/drivers/net/wireless/$(ORINOCO_DIR)hermes.$(LINUX_KMOD_SUFFIX) \ - $(LINUX_DIR)/drivers/net/wireless/$(ORINOCO_DIR)orinoco.$(LINUX_KMOD_SUFFIX) \ - $(LINUX_DIR)/drivers/net/wireless/$(ORINOCO_DIR)hermes_dld.$(LINUX_KMOD_SUFFIX) - AUTOLOAD:=$(call AutoLoad,50,hermes hermes_dld orinoco) -else - FILES:= \ - $(LINUX_DIR)/drivers/net/wireless/hermes.$(LINUX_KMOD_SUFFIX) \ - $(LINUX_DIR)/drivers/net/wireless/orinoco.$(LINUX_KMOD_SUFFIX) - AUTOLOAD:=$(call AutoLoad,50,hermes orinoco) -endif -endif endef define KernelPackage/net-hermes/description @@ -194,7 +171,7 @@ define KernelPackage/net-hermes-pci TITLE:=Intersil Prism 2.5 PCI support DEPENDS:=@PCI_SUPPORT +kmod-net-hermes KCONFIG:=CONFIG_PCI_HERMES - FILES:=$(LINUX_DIR)/drivers/net/wireless/$(ORINOCO_DIR)orinoco_pci.$(LINUX_KMOD_SUFFIX) + FILES:=$(LINUX_DIR)/drivers/net/wireless/orinoco/orinoco_pci.$(LINUX_KMOD_SUFFIX) AUTOLOAD:=$(call AutoLoad,55,orinoco_pci) endef @@ -210,7 +187,7 @@ define KernelPackage/net-hermes-plx TITLE:=PLX9052 based PCI adaptor DEPENDS:=@PCI_SUPPORT +kmod-net-hermes KCONFIG:=CONFIG_PLX_HERMES - FILES:=$(LINUX_DIR)/drivers/net/wireless/$(ORINOCO_DIR)orinoco_plx.$(LINUX_KMOD_SUFFIX) + FILES:=$(LINUX_DIR)/drivers/net/wireless/orinoco/orinoco_plx.$(LINUX_KMOD_SUFFIX) AUTOLOAD:=$(call AutoLoad,55,orinoco_plx) endef diff --git a/package/libipfix/extra/append-wprobe-ie.pl b/package/libipfix/extra/append-wprobe-ie.pl index 3a8db3fe1..8bb658bbb 100644 --- a/package/libipfix/extra/append-wprobe-ie.pl +++ b/package/libipfix/extra/append-wprobe-ie.pl @@ -1,21 +1,17 @@ use strict; my @fields = ( - [ "_avg", "FLOAT", " - Average" ], - [ "_stdev", "FLOAT", " - Standard deviation" ], - [ "_n", "UINT", " - Number of samples" ] + [ "_n", "UINT", " - Number of samples", 4 ], + [ "_s", "UINT", " - Sum of samples", 8 ], + [ "_ss", "UINT", " - Sum of squared samples", 8 ], ); -my $file = $ARGV[0] or die "Syntax: $0 \n"; +my $file = $ARGV[0] or die "Syntax: $0 \n"; -f $file or die "File not found\n"; -my $last_ie = 0; -my $line; -open IES, "<$file" or die "Can't open file"; -while ($line = ) { - $line =~ /^(\d+)\s*,/ and $last_ie = $1; -} -close IES; -while () { +my $start = $ARGV[1]; +$start =~ /^\d+$/ or die "Invalid start number"; +open FILE, "<$file" or die "Can't open file"; +while () { /^(%?)(\w+),\s*(\w+),\s*(.+)$/ and do { my $counter = $1; my $rfield = $2; @@ -23,18 +19,20 @@ while () { my $descr = $4; my @f; if ($counter) { - @f = [ "", "UINT", "" ]; + @f = [ "", "UINT", "", 4]; } else { @f = @fields; } foreach my $f (@f) { - my $nr = ++$last_ie; + my $nr = $start++; my $n = $f->[0]; my $N = uc $n; my $ftype = $f->[1]; my $fdesc = $f->[2]; - print "$nr, IPFIX_FT_WPROBE_$rfield$N, 4, IPFIX_CODING_$ftype, \"$nfield$n\", \"$descr$fdesc\"\n"; + my $size = $f->[3]; + print "$nr, IPFIX_FT_WPROBE_$rfield$N, $size, IPFIX_CODING_$ftype, \"$nfield$n\", \"$descr$fdesc\"\n"; } }; } +close FILE; diff --git a/package/libipfix/patches/100-openimp_sync.patch b/package/libipfix/patches/100-openimp_sync.patch index 135379529..5b6e2e379 100644 --- a/package/libipfix/patches/100-openimp_sync.patch +++ b/package/libipfix/patches/100-openimp_sync.patch @@ -329,7 +329,16 @@ /** exporter funcs --- a/lib/ipfix_col.c +++ b/lib/ipfix_col.c -@@ -907,7 +907,7 @@ int ipfix_decode_datarecord( ipfixt_node +@@ -897,6 +897,8 @@ int ipfix_decode_datarecord( ipfixt_node + return -1; + } + ++ n->ipfixt->fields[i].elem->decode(p,p,len); ++ + data->lens[i] = len; + data->addrs[i] = p; + +@@ -907,7 +909,7 @@ int ipfix_decode_datarecord( ipfixt_node return 0; } @@ -338,7 +347,7 @@ { if ( data ) { if ( data->addrs ) -@@ -925,6 +925,7 @@ int ipfix_parse_msg( ipfix_input_t *inpu +@@ -925,6 +927,7 @@ int ipfix_parse_msg( ipfix_input_t *inpu ipfix_hdr_t hdr; /* ipfix packet header */ ipfixs_node_t *s; ipfix_datarecord_t data = { NULL, NULL, 0 }; @@ -346,7 +355,7 @@ uint8_t *buf; /* ipfix payload */ uint16_t setid, setlen; /* set id, set lenght */ int i, nread, offset; /* counter */ -@@ -1042,6 +1043,12 @@ int ipfix_parse_msg( ipfix_input_t *inpu +@@ -1042,6 +1045,12 @@ int ipfix_parse_msg( ipfix_input_t *inpu err_flag = 1; } else { @@ -359,7 +368,7 @@ /** read data records */ for ( offset=nread, bytesleft=setlen; bytesleft>4; ) { -@@ -1076,11 +1083,11 @@ int ipfix_parse_msg( ipfix_input_t *inpu +@@ -1076,11 +1085,11 @@ int ipfix_parse_msg( ipfix_input_t *inpu goto errend; end: @@ -373,7 +382,7 @@ return -1; } -@@ -1093,7 +1100,7 @@ void process_client_tcp( int fd, int mas +@@ -1093,7 +1102,7 @@ void process_client_tcp( int fd, int mas tcp_conn_t *tcon = (tcp_conn_t*)data; char *func = "process_client_tcp"; @@ -403,3 +412,63 @@ if ( (access( s->fname, R_OK ) <0 ) && (mkdir( s->fname, S_IRWXU ) <0) ) { mlogf( 0, "[%s] cannot access dir '%s': %s\n", +--- a/lib/ipfix_FOKUS_IEs.txt ++++ b/lib/ipfix_FOKUS_IEs.txt +@@ -24,6 +24,8 @@ + 196, IPFIX_FT_PKTID, 4, IPFIX_CODING_UINT, "pktId", "FOKUS packet id" + 197, IPFIX_FT_STARTTIME, 4, IPFIX_CODING_INT, "startTime", "FOKUS interval start" + 198, IPFIX_FT_ENDTIME, 4, IPFIX_CODING_INT, "endTime", "FOKUS interval end" ++199, IPFIX_FT_RTT_USEC, 8, IPFIX_CODING_UINT, "rtt_usec", "FOKUS rtt in us" ++ + 300, IPFIX_FT_FLOWCREATIONTIMEUSEC, 4, IPFIX_CODING_INT, "flowCreationTimeUsec", "FOKUS flow start usec fraction" + 301, IPFIX_FT_FLOWENDTIMEUSEC, 4, IPFIX_CODING_INT, "flowEndTimeUsec", "FOKUS flow end usec fraction" + 303, IPFIX_FT_TC_PACKETS, 4, IPFIX_CODING_UINT, "tcPackets", "DAIDALOS Packets seen" +@@ -39,3 +41,48 @@ + 313, IPFIX_FT_OWDVARMIN_NSEC, 4, IPFIX_CODING_INT, "owdvarmin_nsec", "FOKUS minimum owd variance in ns" + 314, IPFIX_FT_OWDVARMAX_NSEC, 4, IPFIX_CODING_INT, "owdvarmax_nsec", "FOKUS maximum ow variance in ns" + ++# Project INTERSECTION ++315, IPFIX_FT_SOURCEIPV4FANOUT, 4, IPFIX_CODING_UINT,"sourceIPv4FanOut", "FOKUS IPv4 fanout" ++316, IPFIX_FT_DESTINATIONIPV4FANIN, 4, IPFIX_CODING_UINT,"destinationIPv4FanIn", "FOKUS IPv4 fanin" ++ ++# Project PRISM ++ ++330, IPFIX_FT_PR_SESSIONID, 4, IPFIX_CODING_UINT, "sessionId", "PRISM Session ID" ++331, IPFIX_FT_PR_TRANSACTIONID, 4, IPFIX_CODING_UINT, "transactionId", "PRISM Transaction ID" ++332, IPFIX_FT_PR_ENCRYPTEDDATA, 65535, IPFIX_CODING_STRING, "encryptedData", "PRISM encrypted data" ++333, IPFIX_FT_PR_DECRYPTIONKEY, 65535, IPFIX_CODING_STRING, "decryptionKey", "PRISM decryption key" ++334, IPFIX_FT_PR_KEYSHARE, 65535, IPFIX_CODING_STRING, "keyShare", "PRISM key share" ++335, IPFIX_FT_PR_KEYSHAREADP, 65535, IPFIX_CODING_STRING, "keyShareAdp", "PRISM key share ADP" ++336, IPFIX_FT_PR_INITVECTOR, 65535, IPFIX_CODING_STRING, "cryptoInitVector", "PRISM crypto init vector" ++ ++ ++# these information elements have been defined by FOKUS for the Oracle project ++ ++402, IPFIX_FT_ORsignalBandwidth, 4, IPFIX_CODING_UINT, "ORsignalBandwidth", "signal bandwidth" ++403, IPFIX_FT_ORsignalPower, 2, IPFIX_CODING_UINT, "ORsignalPower", "ERIP" ++404, IPFIX_FT_ORmodulationType, 2, IPFIX_CODING_UINT, "ORmodulationType", "AM/FM,.." ++405, IPFIX_FT_ORsymbolRate, 2, IPFIX_CODING_UINT, "ORsymbolRate", "symbol rate" ++406, IPFIX_FT_ORmodulationOrder, 1, IPFIX_CODING_UINT, "ORmodulationOrder", "number of levels" ++407, IPFIX_FT_ORrolloffFactor, 2, IPFIX_CODING_UINT, "ORrolloffFactor", "roll of factor" ++408, IPFIX_FT_ORgeopositionLon, 4, IPFIX_CODING_UINT, "ORgeopositionLon", "GPS coordinate, resolution 1 cm" ++409, IPFIX_FT_ORgeopositionLat, 4, IPFIX_CODING_UINT, "ORgeopositionLat", "GPS coordinate, resolution 1 cm" ++410, IPFIX_FT_ORgeopositionElev, 4, IPFIX_CODING_UINT, "ORgeopositionElev", "GPS coordinate, resolution 1 cm" ++411, IPFIX_FT_ORpolicyRecord, 65535, IPFIX_CODING_STRING, "ORpolicyRecord", "policy record has variable length, First 8 bits in data describe the length (in bytes) of the field" ++420, IPFIX_FT_channel_status, 1, IPFIX_CODING_UINT, "channel_status", vacancy of the scanned channel (1: channel busy, 0: channel idle)" ++421, IPFIX_FT_sensing_value, 2, IPFIX_CODING_UINT, "sensing_value", "Cost function output" ++422, IPFIX_FT_sensing_threshold, 2, IPFIX_CODING_UINT, "sensing_threshold", "Decision threshold" ++423, IPFIX_FT_OR_terminal_id, 1, IPFIX_CODING_UINT, "OR_terminal_id", "terminal identifier" ++424, IPFIX_FT_OR_terminal_id_list, 65535, IPFIX_CODING_STRING, "OR_terminal_id_list", "terminal identifier list" ++425, IPFIX_FT_Infrastructure_network_id, 1, IPFIX_CODING_UINT, "Infrastructure_network_id", "network identifier" ++426, IPFIX_FT_Infrastructure_network_type, 1, IPFIX_CODING_UINT, "Infrastructure_network_type", "network type (GSM - 1, UMTS - 2, WiMAX - 3, WiFi - 4)" ++427, IPFIX_FT_Battery_lifetime_min, 1, IPFIX_CODING_UINT, "Battery_lifetime_min", "expected battery lifetime to provide requested services or functionalities, in minutes" ++428, IPFIX_FT_Battery_lifetime_h, 1, IPFIX_CODING_UINT, "Battery_lifetime_h", "expected battery lifetime to provide requested services or functionalities, in hours" ++429, IPFIX_FT_Battery_status, 1, IPFIX_CODING_UINT, "Battery_status", "expected battery lifetime to provide requested services or functionalities, 1 bit status flag, values 1 or 0" ++430, IPFIX_FT_Cell_id_number, 4, IPFIX_CODING_UINT, "Cell_id_number", "16-32 bit cell id number, identifier" ++431, IPFIX_FT_Spectral_allocation_vector, 1, IPFIX_CODING_UINT, "Spectral_allocation_vector", "binary vector to indicate whether a band is free 1 bit 0 or not 1 bit 1" ++432, IPFIX_FT_Spectral_allocation_profile, 2, IPFIX_CODING_UINT, "Spectral_allocation_profile", "received power spectral density vs. frequency to indicate spectral activity in the band of interest (8-16 bits per discrete frequency value)" ++433, IPFIX_FT_Center_frequency, 2, IPFIX_CODING_UINT, "Center_frequency", "Center frequency of the sensed band" ++434, IPFIX_FT_Bandwidth_of_CAP, 2, IPFIX_CODING_UINT, "Bandwidth_of_CAP", "Bandwidth of the spectral allocation profile" ++435, IPFIX_FT_ORmodulation, 1, IPFIX_CODING_UINT, "ORmodulation", "CREST factor" ++436, IPFIX_FT_ORprofileRecord, 65535, IPFIX_CODING_STRING, "ORprofileRecord", "profile record has variable length, First 8 bits in data describe the length (in bytes) of the field" ++ diff --git a/package/libipfix/patches/110-wprobe_ie.patch b/package/libipfix/patches/110-wprobe_ie.patch index bbfa33120..5e3728081 100644 --- a/package/libipfix/patches/110-wprobe_ie.patch +++ b/package/libipfix/patches/110-wprobe_ie.patch @@ -1,44 +1,44 @@ --- a/lib/ipfix_FOKUS_IEs.txt +++ b/lib/ipfix_FOKUS_IEs.txt -@@ -39,3 +39,41 @@ - 313, IPFIX_FT_OWDVARMIN_NSEC, 4, IPFIX_CODING_INT, "owdvarmin_nsec", "FOKUS minimum owd variance in ns" - 314, IPFIX_FT_OWDVARMAX_NSEC, 4, IPFIX_CODING_INT, "owdvarmax_nsec", "FOKUS maximum ow variance in ns" +@@ -86,3 +86,41 @@ + 435, IPFIX_FT_ORmodulation, 1, IPFIX_CODING_UINT, "ORmodulation", "CREST factor" + 436, IPFIX_FT_ORprofileRecord, 65535, IPFIX_CODING_STRING, "ORprofileRecord", "profile record has variable length, First 8 bits in data describe the length (in bytes) of the field" -+315, IPFIX_FT_WPROBE_NOISE_AVG, 4, IPFIX_CODING_FLOAT, "global_noise_avg", "wprobe global noice floor - Average" -+316, IPFIX_FT_WPROBE_NOISE_STDEV, 4, IPFIX_CODING_FLOAT, "global_noise_stdev", "wprobe global noice floor - Standard deviation" -+317, IPFIX_FT_WPROBE_NOISE_N, 4, IPFIX_CODING_UINT, "global_noise_n", "wprobe global noice floor - Number of samples" -+318, IPFIX_FT_WPROBE_PHY_BUSY_AVG, 4, IPFIX_CODING_FLOAT, "global_phy_busy_avg", "wprobe global airtime total - Average" -+319, IPFIX_FT_WPROBE_PHY_BUSY_STDEV, 4, IPFIX_CODING_FLOAT, "global_phy_busy_stdev", "wprobe global airtime total - Standard deviation" -+320, IPFIX_FT_WPROBE_PHY_BUSY_N, 4, IPFIX_CODING_UINT, "global_phy_busy_n", "wprobe global airtime total - Number of samples" -+321, IPFIX_FT_WPROBE_PHY_RX_AVG, 4, IPFIX_CODING_FLOAT, "global_phy_rx_avg", "wprobe global airtime total from rx-frame - Average" -+322, IPFIX_FT_WPROBE_PHY_RX_STDEV, 4, IPFIX_CODING_FLOAT, "global_phy_rx_stdev", "wprobe global airtime total from rx-frame - Standard deviation" -+323, IPFIX_FT_WPROBE_PHY_RX_N, 4, IPFIX_CODING_UINT, "global_phy_rx_n", "wprobe global airtime total from rx-frame - Number of samples" -+324, IPFIX_FT_WPROBE_PHY_TX_AVG, 4, IPFIX_CODING_FLOAT, "global_phy_tx_avg", "wprobe global airtime total from tx-frame - Average" -+325, IPFIX_FT_WPROBE_PHY_TX_STDEV, 4, IPFIX_CODING_FLOAT, "global_phy_tx_stdev", "wprobe global airtime total from tx-frame - Standard deviation" -+326, IPFIX_FT_WPROBE_PHY_TX_N, 4, IPFIX_CODING_UINT, "global_phy_tx_n", "wprobe global airtime total from tx-frame - Number of samples" -+327, IPFIX_FT_WPROBE_RSSI_AVG, 4, IPFIX_CODING_FLOAT, "link_rssi_avg", "wprobe link received signal strength indication - Average" -+328, IPFIX_FT_WPROBE_RSSI_STDEV, 4, IPFIX_CODING_FLOAT, "link_rssi_stdev", "wprobe link received signal strength indication - Standard deviation" -+329, IPFIX_FT_WPROBE_RSSI_N, 4, IPFIX_CODING_UINT, "link_rssi_n", "wprobe link received signal strength indication - Number of samples" -+330, IPFIX_FT_WPROBE_SIGNAL_AVG, 4, IPFIX_CODING_FLOAT, "link_signal_avg", "wprobe link signal strength in dB - Average" -+331, IPFIX_FT_WPROBE_SIGNAL_STDEV, 4, IPFIX_CODING_FLOAT, "link_signal_stdev", "wprobe link signal strength in dB - Standard deviation" -+332, IPFIX_FT_WPROBE_SIGNAL_N, 4, IPFIX_CODING_UINT, "link_signal_n", "wprobe link signal strength in dB - Number of samples" -+333, IPFIX_FT_WPROBE_IEEE_RX_RATE_AVG, 4, IPFIX_CODING_FLOAT, "link_ieee_rx_rate_avg", "wprobe link IEEE 802.11 RX data rate - Average" -+334, IPFIX_FT_WPROBE_IEEE_RX_RATE_STDEV, 4, IPFIX_CODING_FLOAT, "link_ieee_rx_rate_stdev", "wprobe link IEEE 802.11 RX data rate - Standard deviation" -+335, IPFIX_FT_WPROBE_IEEE_RX_RATE_N, 4, IPFIX_CODING_UINT, "link_ieee_rx_rate_n", "wprobe link IEEE 802.11 RX data rate - Number of samples" -+336, IPFIX_FT_WPROBE_IEEE_TX_RATE_AVG, 4, IPFIX_CODING_FLOAT, "link_ieee_tx_rate_avg", "wprobe link IEEE 802.11 TX data rate - Average" -+337, IPFIX_FT_WPROBE_IEEE_TX_RATE_STDEV, 4, IPFIX_CODING_FLOAT, "link_ieee_tx_rate_stdev", "wprobe link IEEE 802.11 TX data rate - Standard deviation" -+338, IPFIX_FT_WPROBE_IEEE_TX_RATE_N, 4, IPFIX_CODING_UINT, "link_ieee_tx_rate_n", "wprobe link IEEE 802.11 TX data rate - Number of samples" -+339, IPFIX_FT_WPROBE_RETRANSMIT_200_AVG, 4, IPFIX_CODING_FLOAT, "link_retransmit_200_avg", "wprobe link total retransmissions per packet - <200 bytes - Average" -+340, IPFIX_FT_WPROBE_RETRANSMIT_200_STDEV, 4, IPFIX_CODING_FLOAT, "link_retransmit_200_stdev", "wprobe link total retransmissions per packet - <200 bytes - Standard deviation" -+341, IPFIX_FT_WPROBE_RETRANSMIT_200_N, 4, IPFIX_CODING_UINT, "link_retransmit_200_n", "wprobe link total retransmissions per packet - <200 bytes - Number of samples" -+342, IPFIX_FT_WPROBE_RETRANSMIT_400_AVG, 4, IPFIX_CODING_FLOAT, "link_retransmit_400_avg", "wprobe link total retransmissions per packet - <400 bytes - Average" -+343, IPFIX_FT_WPROBE_RETRANSMIT_400_STDEV, 4, IPFIX_CODING_FLOAT, "link_retransmit_400_stdev", "wprobe link total retransmissions per packet - <400 bytes - Standard deviation" -+344, IPFIX_FT_WPROBE_RETRANSMIT_400_N, 4, IPFIX_CODING_UINT, "link_retransmit_400_n", "wprobe link total retransmissions per packet - <400 bytes - Number of samples" -+345, IPFIX_FT_WPROBE_RETRANSMIT_800_AVG, 4, IPFIX_CODING_FLOAT, "link_retransmit_800_avg", "wprobe link total retransmissions per packet - <800 bytes - Average" -+346, IPFIX_FT_WPROBE_RETRANSMIT_800_STDEV, 4, IPFIX_CODING_FLOAT, "link_retransmit_800_stdev", "wprobe link total retransmissions per packet - <800 bytes - Standard deviation" -+347, IPFIX_FT_WPROBE_RETRANSMIT_800_N, 4, IPFIX_CODING_UINT, "link_retransmit_800_n", "wprobe link total retransmissions per packet - <800 bytes - Number of samples" -+348, IPFIX_FT_WPROBE_RETRANSMIT_1600_AVG, 4, IPFIX_CODING_FLOAT, "link_retransmit_1600_avg", "wprobe link total retransmissions per packet - >800 bytes - Average" -+349, IPFIX_FT_WPROBE_RETRANSMIT_1600_STDEV, 4, IPFIX_CODING_FLOAT, "link_retransmit_1600_stdev", "wprobe link total retransmissions per packet - >800 bytes - Standard deviation" -+350, IPFIX_FT_WPROBE_RETRANSMIT_1600_N, 4, IPFIX_CODING_UINT, "link_retransmit_1600_n", "wprobe link total retransmissions per packet - >800 bytes - Number of samples" -+351, IPFIX_FT_WPROBE_FRAMES, 4, IPFIX_CODING_UINT, "global_frames", "wprobe global number of 802.11 frames seen" -+352, IPFIX_FT_WPROBE_PROBEREQ, 4, IPFIX_CODING_UINT, "global_probereq", "wprobe global number of 802.11 probe requests seen" ++500, IPFIX_FT_WPROBE_NOISE_N, 4, IPFIX_CODING_UINT, "global_noise_n", "wprobe global noice floor - Number of samples" ++501, IPFIX_FT_WPROBE_NOISE_S, 8, IPFIX_CODING_UINT, "global_noise_s", "wprobe global noice floor - Sum of samples" ++502, IPFIX_FT_WPROBE_NOISE_SS, 8, IPFIX_CODING_UINT, "global_noise_ss", "wprobe global noice floor - Sum of squared samples" ++503, IPFIX_FT_WPROBE_PHY_BUSY_N, 4, IPFIX_CODING_UINT, "global_phy_busy_n", "wprobe global airtime total - Number of samples" ++504, IPFIX_FT_WPROBE_PHY_BUSY_S, 8, IPFIX_CODING_UINT, "global_phy_busy_s", "wprobe global airtime total - Sum of samples" ++505, IPFIX_FT_WPROBE_PHY_BUSY_SS, 8, IPFIX_CODING_UINT, "global_phy_busy_ss", "wprobe global airtime total - Sum of squared samples" ++506, IPFIX_FT_WPROBE_PHY_RX_N, 4, IPFIX_CODING_UINT, "global_phy_rx_n", "wprobe global airtime total from rx-frame - Number of samples" ++507, IPFIX_FT_WPROBE_PHY_RX_S, 8, IPFIX_CODING_UINT, "global_phy_rx_s", "wprobe global airtime total from rx-frame - Sum of samples" ++508, IPFIX_FT_WPROBE_PHY_RX_SS, 8, IPFIX_CODING_UINT, "global_phy_rx_ss", "wprobe global airtime total from rx-frame - Sum of squared samples" ++509, IPFIX_FT_WPROBE_PHY_TX_N, 4, IPFIX_CODING_UINT, "global_phy_tx_n", "wprobe global airtime total from tx-frame - Number of samples" ++510, IPFIX_FT_WPROBE_PHY_TX_S, 8, IPFIX_CODING_UINT, "global_phy_tx_s", "wprobe global airtime total from tx-frame - Sum of samples" ++511, IPFIX_FT_WPROBE_PHY_TX_SS, 8, IPFIX_CODING_UINT, "global_phy_tx_ss", "wprobe global airtime total from tx-frame - Sum of squared samples" ++512, IPFIX_FT_WPROBE_RSSI_N, 4, IPFIX_CODING_UINT, "link_rssi_n", "wprobe link received signal strength indication - Number of samples" ++513, IPFIX_FT_WPROBE_RSSI_S, 8, IPFIX_CODING_UINT, "link_rssi_s", "wprobe link received signal strength indication - Sum of samples" ++514, IPFIX_FT_WPROBE_RSSI_SS, 8, IPFIX_CODING_UINT, "link_rssi_ss", "wprobe link received signal strength indication - Sum of squared samples" ++515, IPFIX_FT_WPROBE_SIGNAL_N, 4, IPFIX_CODING_UINT, "link_signal_n", "wprobe link signal strength in dB - Number of samples" ++516, IPFIX_FT_WPROBE_SIGNAL_S, 8, IPFIX_CODING_UINT, "link_signal_s", "wprobe link signal strength in dB - Sum of samples" ++517, IPFIX_FT_WPROBE_SIGNAL_SS, 8, IPFIX_CODING_UINT, "link_signal_ss", "wprobe link signal strength in dB - Sum of squared samples" ++518, IPFIX_FT_WPROBE_IEEE_RX_RATE_N, 4, IPFIX_CODING_UINT, "link_ieee_rx_rate_n", "wprobe link IEEE 802.11 RX data rate - Number of samples" ++519, IPFIX_FT_WPROBE_IEEE_RX_RATE_S, 8, IPFIX_CODING_UINT, "link_ieee_rx_rate_s", "wprobe link IEEE 802.11 RX data rate - Sum of samples" ++520, IPFIX_FT_WPROBE_IEEE_RX_RATE_SS, 8, IPFIX_CODING_UINT, "link_ieee_rx_rate_ss", "wprobe link IEEE 802.11 RX data rate - Sum of squared samples" ++521, IPFIX_FT_WPROBE_IEEE_TX_RATE_N, 4, IPFIX_CODING_UINT, "link_ieee_tx_rate_n", "wprobe link IEEE 802.11 TX data rate - Number of samples" ++522, IPFIX_FT_WPROBE_IEEE_TX_RATE_S, 8, IPFIX_CODING_UINT, "link_ieee_tx_rate_s", "wprobe link IEEE 802.11 TX data rate - Sum of samples" ++523, IPFIX_FT_WPROBE_IEEE_TX_RATE_SS, 8, IPFIX_CODING_UINT, "link_ieee_tx_rate_ss", "wprobe link IEEE 802.11 TX data rate - Sum of squared samples" ++524, IPFIX_FT_WPROBE_RETRANSMIT_200_N, 4, IPFIX_CODING_UINT, "link_retransmit_200_n", "wprobe link total retransmissions per packet - <200 bytes - Number of samples" ++525, IPFIX_FT_WPROBE_RETRANSMIT_200_S, 8, IPFIX_CODING_UINT, "link_retransmit_200_s", "wprobe link total retransmissions per packet - <200 bytes - Sum of samples" ++526, IPFIX_FT_WPROBE_RETRANSMIT_200_SS, 8, IPFIX_CODING_UINT, "link_retransmit_200_ss", "wprobe link total retransmissions per packet - <200 bytes - Sum of squared samples" ++527, IPFIX_FT_WPROBE_RETRANSMIT_400_N, 4, IPFIX_CODING_UINT, "link_retransmit_400_n", "wprobe link total retransmissions per packet - <400 bytes - Number of samples" ++528, IPFIX_FT_WPROBE_RETRANSMIT_400_S, 8, IPFIX_CODING_UINT, "link_retransmit_400_s", "wprobe link total retransmissions per packet - <400 bytes - Sum of samples" ++529, IPFIX_FT_WPROBE_RETRANSMIT_400_SS, 8, IPFIX_CODING_UINT, "link_retransmit_400_ss", "wprobe link total retransmissions per packet - <400 bytes - Sum of squared samples" ++530, IPFIX_FT_WPROBE_RETRANSMIT_800_N, 4, IPFIX_CODING_UINT, "link_retransmit_800_n", "wprobe link total retransmissions per packet - <800 bytes - Number of samples" ++531, IPFIX_FT_WPROBE_RETRANSMIT_800_S, 8, IPFIX_CODING_UINT, "link_retransmit_800_s", "wprobe link total retransmissions per packet - <800 bytes - Sum of samples" ++532, IPFIX_FT_WPROBE_RETRANSMIT_800_SS, 8, IPFIX_CODING_UINT, "link_retransmit_800_ss", "wprobe link total retransmissions per packet - <800 bytes - Sum of squared samples" ++533, IPFIX_FT_WPROBE_RETRANSMIT_1600_N, 4, IPFIX_CODING_UINT, "link_retransmit_1600_n", "wprobe link total retransmissions per packet - >800 bytes - Number of samples" ++534, IPFIX_FT_WPROBE_RETRANSMIT_1600_S, 8, IPFIX_CODING_UINT, "link_retransmit_1600_s", "wprobe link total retransmissions per packet - >800 bytes - Sum of samples" ++535, IPFIX_FT_WPROBE_RETRANSMIT_1600_SS, 8, IPFIX_CODING_UINT, "link_retransmit_1600_ss", "wprobe link total retransmissions per packet - >800 bytes - Sum of squared samples" ++536, IPFIX_FT_WPROBE_FRAMES, 4, IPFIX_CODING_UINT, "global_frames", "wprobe global number of 802.11 frames seen" ++537, IPFIX_FT_WPROBE_PROBEREQ, 4, IPFIX_CODING_UINT, "global_probereq", "wprobe global number of 802.11 probe requests seen" diff --git a/package/mac80211/Config.in.b43 b/package/mac80211/Config.in.b43 index f5399312c..e1f4d37d7 100644 --- a/package/mac80211/Config.in.b43 +++ b/package/mac80211/Config.in.b43 @@ -3,7 +3,7 @@ choice prompt "b43 firmware version" depends on PACKAGE_kmod-b43 - default B43_STABLE + default B43_EXPERIMENTAL help This option allows you to select the version of the b43 firmware. @@ -41,20 +41,18 @@ endchoice config B43_FW_SQUASH bool "Remove unnecessary firmware files" depends on PACKAGE_kmod-b43 && !B43_OPENFIRMWARE + default y help This options allows you to remove unnecessary b43 firmware files from the final rootfs image. This can reduce the rootfs size by up to 200k. - Do _NOT_ use this option, if you don't know the core revision - and/or PHY type of your wireless chip. - - If unsure, say N. + If unsure, say Y. config B43_FW_SQUASH_COREREVS string "Core revisions to include" depends on PACKAGE_kmod-b43 && B43_FW_SQUASH - default "5,6,7,8,9,10" + default "5,6,7,8,9,10,13,14,15" help This is a comma seperated list of core revision numbers. Example (keep files for rev5 only): @@ -65,7 +63,7 @@ config B43_FW_SQUASH_COREREVS config B43_FW_SQUASH_PHYTYPES string "PHY types to include" depends on PACKAGE_kmod-b43 && B43_FW_SQUASH - default "G,LP,N" + default "G,LP" help This is a comma seperated list of PHY types: A => A-PHY diff --git a/package/mac80211/Config.in.b43legacy b/package/mac80211/Config.in.b43legacy new file mode 100644 index 000000000..2e2f06e5a --- /dev/null +++ b/package/mac80211/Config.in.b43legacy @@ -0,0 +1,24 @@ +# B43 configuration + +config B43LEGACY_FW_SQUASH + bool "Remove unnecessary firmware files" + depends on PACKAGE_kmod-b43legacy + default y + help + This options allows you to remove unnecessary b43legacy firmware files + from the final rootfs image. This can reduce the rootfs size by + up to 50k. + + If unsure, say Y. + +config B43LEGACY_FW_SQUASH_COREREVS + string "Core revisions to include" + depends on PACKAGE_kmod-b43legacy && B43LEGACY_FW_SQUASH + default "1,2,3,4" + help + This is a comma seperated list of core revision numbers. + Example (keep files for rev4 only): + 4 + Example (keep files for rev2 and rev4): + 2,4 + diff --git a/package/mac80211/Makefile b/package/mac80211/Makefile index 4ee955574..652603af6 100644 --- a/package/mac80211/Makefile +++ b/package/mac80211/Makefile @@ -10,12 +10,12 @@ include $(INCLUDE_DIR)/kernel.mk PKG_NAME:=mac80211 -PKG_VERSION:=2009-11-21 -PKG_RELEASE:=7 +PKG_VERSION:=2010-01-07 +PKG_RELEASE:=8 PKG_SOURCE_URL:= \ - http://www.orbit-lab.org/kernel/compat-wireless-2.6/2009/11 \ + http://www.orbit-lab.org/kernel/compat-wireless-2.6/2009/12 \ http://wireless.kernel.org/download/compat-wireless-2.6 -PKG_MD5SUM:=00e80559cddaa160605098572f5c58b8 +PKG_MD5SUM:=f783d3d4a140a76855916b54fa18be47 PKG_SOURCE:=compat-wireless-$(PKG_VERSION).tar.bz2 PKG_BUILD_DIR:=$(KERNEL_BUILD_DIR)/compat-wireless-$(PKG_VERSION) @@ -33,17 +33,18 @@ WMENU:=Wireless Drivers define KernelPackage/mac80211/Default SUBMENU:=$(WMENU) URL:=http://linuxwireless.org/ - DEPENDS:=@LINUX_2_6 @!TARGET_avr32 + DEPENDS:=@LINUX_2_6 @!TARGET_avr32 @(!(TARGET_ep93xx||TARGET_ps3||TARGET_pxcab)||BROKEN) endef define KernelPackage/mac80211 $(call KernelPackage/mac80211/Default) TITLE:=Linux 802.11 Wireless Networking Stack - DEPENDS+= +kmod-crypto-arc4 +kmod-crypto-aes +wireless-tools +@PACKAGE_iw @!LINUX_2_6_21 @!LINUX_2_6_25 + DEPENDS+= +kmod-crypto-arc4 +kmod-crypto-aes +wireless-tools +iw @!LINUX_2_6_21 @!LINUX_2_6_25 FILES:= \ + $(PKG_BUILD_DIR)/compat/compat.$(LINUX_KMOD_SUFFIX) \ $(PKG_BUILD_DIR)/net/mac80211/mac80211.$(LINUX_KMOD_SUFFIX) \ $(PKG_BUILD_DIR)/net/wireless/cfg80211.$(LINUX_KMOD_SUFFIX) - AUTOLOAD:=$(call AutoLoad,20,cfg80211 mac80211) + AUTOLOAD:=$(call AutoLoad,20,compat cfg80211 mac80211) endef define KernelPackage/mac80211/config @@ -155,7 +156,7 @@ endef define KernelPackage/rt2x00-lib $(call KernelPackage/rt2x00/Default) - DEPENDS+= @PCI_SUPPORT||@USB_SUPPORT +kmod-mac80211 +kmod-crc-itu-t + DEPENDS+= @(PCI_SUPPORT||USB_SUPPORT) +kmod-mac80211 +kmod-crc-itu-t TITLE+= (LIB) FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/rt2x00/rt2x00lib.$(LINUX_KMOD_SUFFIX) AUTOLOAD:=$(call AutoLoad,25,blkcipher ecb arc4 rt2x00lib) @@ -489,6 +490,10 @@ $(call KernelPackage/b43-common) AUTOLOAD:=$(call AutoLoad,30,b43legacy) endef +define KernelPackage/b43legacy/config + source "$(SOURCE)/Config.in.b43legacy" +endef + define KernelPackage/b43legacy/description Kernel module for Broadcom 43xx-legacy wireless support (mac80211 stack) new endef @@ -615,9 +620,13 @@ define Build/Compile endef define Build/InstallDev - mkdir -p $(1)/usr/include/mac80211 $(1)/usr/include/net/mac80211 + mkdir -p \ + $(1)/usr/include/mac80211 \ + $(1)/usr/include/mac80211/ath \ + $(1)/usr/include/net/mac80211 $(CP) $(PKG_BUILD_DIR)/net/mac80211/*.h $(PKG_BUILD_DIR)/include/* $(1)/usr/include/mac80211/ $(CP) $(PKG_BUILD_DIR)/net/mac80211/rate.h $(1)/usr/include/net/mac80211/ + $(CP) $(PKG_BUILD_DIR)/drivers/net/wireless/ath/*.h $(1)/usr/include/mac80211/ath/ endef define KernelPackage/libertas/install @@ -637,7 +646,7 @@ endef define KernelPackage/p54-usb/install $(INSTALL_DIR) $(1)/lib/firmware - $(INSTALL_DATA) $(DL_DIR)/$(P54USBFW) $(1)/lib/firmware/isl3886usb + $(INSTALL_DATA) $(DL_DIR)/$(P54USBFW) $(1)/lib/firmware/isl3887usb endef define KernelPackage/rt61-pci/install @@ -712,6 +721,9 @@ define KernelPackage/b43legacy/install $(INSTALL_DIR) $(1)/lib/firmware/ b43-fwcutter --unsupported -w $(1)/lib/firmware/ $(DL_DIR)/$(PKG_B43_FWV3_SOURCE) +ifneq ($(CONFIG_B43LEGACY_FW_SQUASH),) + b43-fwsquash.py "G" "$(CONFIG_B43LEGACY_FW_SQUASH_COREREVS)" "$(1)/lib/firmware/b43legacy" +endif endef $(eval $(call KernelPackage,ath5k)) diff --git a/package/mac80211/files/host_bin/b43-fwsquash.py b/package/mac80211/files/host_bin/b43-fwsquash.py index 52484d1b1..8c5859c42 100755 --- a/package/mac80211/files/host_bin/b43-fwsquash.py +++ b/package/mac80211/files/host_bin/b43-fwsquash.py @@ -62,9 +62,13 @@ def phytypes_match(types_a, types_b): return False revmapping = { + "ucode2.fw" : (2,3,), + "ucode4.fw" : (4,), "ucode5.fw" : (5,6,7,8,9,10,), "ucode11.fw" : (11,12,), "ucode13.fw" : (13,), + "ucode14.fw" : (14,), + "ucode15.fw" : (15,), "pcm4.fw" : (1,2,3,4,), "pcm5.fw" : (5,6,7,8,9,10,), } @@ -72,13 +76,20 @@ revmapping = { initvalmapping = { "a0g1initvals5.fw" : ( (5,6,7,8,9,10,), ("AG",), ), "a0g0initvals5.fw" : ( (5,6,7,8,9,10,), ("A", "AG",), ), + "b0g0initvals2.fw" : ( (2,4,), ("G",), ), "b0g0initvals5.fw" : ( (5,6,7,8,9,10,), ("G",), ), "b0g0initvals13.fw" : ( (13,), ("G",), ), "n0initvals11.fw" : ( (11,12,), ("N",), ), + "lp0initvals13.fw" : ( (13,), ("LP",), ), + "lp0initvals14.fw" : ( (14,), ("LP",), ), + "lp0initvals15.fw" : ( (15,), ("LP",), ), "a0g1bsinitvals5.fw" : ( (5,6,7,8,9,10,), ("AG",), ), "a0g0bsinitvals5.fw" : ( (5,6,7,8,9,10,), ("A", "AG"), ), "b0g0bsinitvals5.fw" : ( (5,6,7,8,9,10,), ("G",), ), "n0bsinitvals11.fw" : ( (11,12,), ("N",), ), + "lp0bsinitvals13.fw" : ( (13,), ("LP",), ), + "lp0bsinitvals14.fw" : ( (14,), ("LP",), ), + "lp0bsinitvals15.fw" : ( (15,), ("LP",), ), } for f in fwfiles: diff --git a/package/mac80211/files/lib/wifi/mac80211.sh b/package/mac80211/files/lib/wifi/mac80211.sh index bc6cc1449..742c1bb44 100644 --- a/package/mac80211/files/lib/wifi/mac80211.sh +++ b/package/mac80211/files/lib/wifi/mac80211.sh @@ -76,11 +76,13 @@ enable_mac80211() { config_get channel "$device" channel config_get vifs "$device" vifs config_get txpower "$device" txpower + config_get country "$device" country find_mac80211_phy "$device" || return 0 config_get phy "$device" phy local i=0 fixed="" + [ -n "$country" ] && iw reg set "$country" [ "$channel" = "auto" -o "$channel" = "0" ] || { fixed=1 } @@ -147,7 +149,7 @@ enable_mac80211() { else offset="0" fi - vif_mac="$( printf %02x $(($mac_1 + $offset)) ):$mac_2" + vif_mac="$( printf %02x $((0x$mac_1 + $offset)) ):$mac_2" } ifconfig "$ifname" hw ether "$vif_mac" @@ -176,10 +178,10 @@ enable_mac80211() { case "$enc" in wep) config_get keymgmt "$vif" keymgmt - if [ -e "$keymgmt" ]; then + if [ -n "$keymgmt" ]; then for idx in 1 2 3 4; do local zidx - zidx = idx - 1 + zidx=$(($idx - 1)) config_get key "$vif" "key${idx}" if [ -n "$key" ]; then append keystring "${zidx}:${key} " @@ -187,7 +189,7 @@ enable_mac80211() { done fi ;; - wpa) + *wpa*|*psk*) config_get key "$vif" key ;; esac @@ -207,7 +209,7 @@ enable_mac80211() { config_get rts "$vif" rts if [ -n "$rts" ]; then - iw phy "$phy" set rts "${frag%%.*}" + iw phy "$phy" set rts "${rts%%.*}" fi ifconfig "$ifname" up @@ -240,7 +242,7 @@ enable_mac80211() { config_get bssid "$vif" bssid case "$enc" in wep) - if [ -e "$keymgmt" ]; then + if [ -n "$keymgmt" ]; then [ -n "$keystring" ] && iw dev "$ifname" connect "$ssid" ${fixed:+$freq} $bssid key "$keystring" else @@ -254,7 +256,7 @@ enable_mac80211() { fi fi ;; - wpa*|psk*) + *wpa*|*psk*) config_get key "$vif" key if eval "type wpa_supplicant_setup_vif" 2>/dev/null >/dev/null; then wpa_supplicant_setup_vif "$vif" wext || { @@ -279,7 +281,7 @@ enable_mac80211() { check_device() { config_get phy "$1" phy [ -z "$phy" ] && { - find_mac80211_phy "$1" || return 0 + find_mac80211_phy "$1" >/dev/null || return 0 config_get phy "$1" phy } [ "$phy" = "$dev" ] && found=1 @@ -289,7 +291,7 @@ detect_mac80211() { devidx=0 config_load wireless while :; do - config_get type "wifi$devidx" type + config_get type "radio$devidx" type [ -n "$type" ] || break devidx=$(($devidx + 1)) done @@ -318,7 +320,7 @@ detect_mac80211() { iw phy "$dev" info | grep -q '2412 MHz' || { mode_band="a"; channel="36"; } cat <lock, flags); -+ list_for_each_entry(lazarus, &anchor->urb_list, anchor_list) { -+ usb_unpoison_urb(lazarus); -+ } -+ //anchor->poisoned = 0; /* XXX: cannot backport */ -+ spin_unlock_irqrestore(&anchor->lock, flags); -+} -+EXPORT_SYMBOL_GPL(usb_unpoison_anchored_urbs); -+#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29) */ -+ -+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)) -+ -+/* -+ * Compat-wireless notes for USB backport stuff: -+ * -+ * urb->reject exists on 2.6.27, the poison/unpoison helpers -+ * did not though. The anchor poison does not exist so we cannot use them. -+ * -+ * USB anchor poising seems to exist to prevent future driver sumbissions -+ * of usb_anchor_urb() to an anchor marked as poisoned. For older kernels -+ * we cannot use that, so new usb_anchor_urb()s will be anchored. The down -+ * side to this should be submission of URBs will continue being anchored -+ * on an anchor instead of having them being rejected immediately when the -+ * driver realized we needed to stop. For ar9170 we poison URBs upon the -+ * ar9170 mac80211 stop callback(), don't think this should be so bad. -+ * It mean there is period of time in older kernels for which we continue -+ * to anchor new URBs to a known stopped anchor. We have two anchors -+ * (TX, and RX) -+ */ -+ -+#if 0 -+/** -+ * usb_poison_urb - reliably kill a transfer and prevent further use of an URB -+ * @urb: pointer to URB describing a previously submitted request, -+ * may be NULL -+ * -+ * This routine cancels an in-progress request. It is guaranteed that -+ * upon return all completion handlers will have finished and the URB -+ * will be totally idle and cannot be reused. These features make -+ * this an ideal way to stop I/O in a disconnect() callback. -+ * If the request has not already finished or been unlinked -+ * the completion handler will see urb->status == -ENOENT. -+ * -+ * After and while the routine runs, attempts to resubmit the URB will fail -+ * with error -EPERM. Thus even if the URB's completion handler always -+ * tries to resubmit, it will not succeed and the URB will become idle. -+ * -+ * This routine may not be used in an interrupt context (such as a bottom -+ * half or a completion handler), or when holding a spinlock, or in other -+ * situations where the caller can't schedule(). -+ * -+ * This routine should not be called by a driver after its disconnect -+ * method has returned. -+ */ -+void usb_poison_urb(struct urb *urb) -+{ -+ might_sleep(); -+ if (!(urb && urb->dev && urb->ep)) -+ return; -+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28)) -+ spin_lock_irq(&usb_reject_lock); -+#endif -+ ++urb->reject; -+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28)) -+ spin_unlock_irq(&usb_reject_lock); -+#endif -+ /* -+ * XXX: usb_hcd_unlink_urb() needs backporting... this is defined -+ * on usb hcd.c but urb.c gets access to it. That is, older kernels -+ * have usb_hcd_unlink_urb() but its not exported, nor can we -+ * re-implement it exactly. This essentially dequeues the urb from -+ * hw, we need to figure out a way to backport this. -+ */ -+ //usb_hcd_unlink_urb(urb, -ENOENT); -+ -+ wait_event(usb_kill_urb_queue, atomic_read(&urb->use_count) == 0); -+} -+EXPORT_SYMBOL_GPL(usb_poison_urb); -+#endif -+ -+void usb_unpoison_urb(struct urb *urb) -+{ -+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28)) -+ unsigned long flags; -+#endif -+ -+ if (!urb) -+ return; -+ -+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28)) -+ spin_lock_irqsave(&usb_reject_lock, flags); -+#endif -+ --urb->reject; -+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28)) -+ spin_unlock_irqrestore(&usb_reject_lock, flags); -+#endif -+} -+EXPORT_SYMBOL_GPL(usb_unpoison_urb); -+ -+ -+#if 0 -+/** -+ * usb_poison_anchored_urbs - cease all traffic from an anchor -+ * @anchor: anchor the requests are bound to -+ * -+ * this allows all outstanding URBs to be poisoned starting -+ * from the back of the queue. Newly added URBs will also be -+ * poisoned -+ * -+ * This routine should not be called by a driver after its disconnect -+ * method has returned. -+ */ -+void usb_poison_anchored_urbs(struct usb_anchor *anchor) -+{ -+ struct urb *victim; -+ -+ spin_lock_irq(&anchor->lock); -+ // anchor->poisoned = 1; /* XXX: Cannot backport */ -+ while (!list_empty(&anchor->urb_list)) { -+ victim = list_entry(anchor->urb_list.prev, struct urb, -+ anchor_list); -+ /* we must make sure the URB isn't freed before we kill it*/ -+ usb_get_urb(victim); -+ spin_unlock_irq(&anchor->lock); -+ /* this will unanchor the URB */ -+ usb_poison_urb(victim); -+ usb_put_urb(victim); -+ spin_lock_irq(&anchor->lock); -+ } -+ spin_unlock_irq(&anchor->lock); -+} -+EXPORT_SYMBOL_GPL(usb_poison_anchored_urbs); -+#endif -+ -+/** -+ * usb_get_from_anchor - get an anchor's oldest urb -+ * @anchor: the anchor whose urb you want -+ * -+ * this will take the oldest urb from an anchor, -+ * unanchor and return it -+ */ -+struct urb *usb_get_from_anchor(struct usb_anchor *anchor) -+{ -+ struct urb *victim; -+ unsigned long flags; -+ -+ spin_lock_irqsave(&anchor->lock, flags); -+ if (!list_empty(&anchor->urb_list)) { -+ victim = list_entry(anchor->urb_list.next, struct urb, -+ anchor_list); -+ usb_get_urb(victim); -+ spin_unlock_irqrestore(&anchor->lock, flags); -+ usb_unanchor_urb(victim); -+ } else { -+ spin_unlock_irqrestore(&anchor->lock, flags); -+ victim = NULL; -+ } -+ -+ return victim; -+} -+ -+EXPORT_SYMBOL_GPL(usb_get_from_anchor); -+ -+/** -+ * usb_scuttle_anchored_urbs - unanchor all an anchor's urbs -+ * @anchor: the anchor whose urbs you want to unanchor -+ * -+ * use this to get rid of all an anchor's urbs -+ */ -+void usb_scuttle_anchored_urbs(struct usb_anchor *anchor) -+{ -+ struct urb *victim; -+ unsigned long flags; -+ -+ spin_lock_irqsave(&anchor->lock, flags); -+ while (!list_empty(&anchor->urb_list)) { -+ victim = list_entry(anchor->urb_list.prev, struct urb, -+ anchor_list); -+ usb_get_urb(victim); -+ spin_unlock_irqrestore(&anchor->lock, flags); -+ /* this may free the URB */ -+ usb_unanchor_urb(victim); -+ usb_put_urb(victim); -+ spin_lock_irqsave(&anchor->lock, flags); -+ } -+ spin_unlock_irqrestore(&anchor->lock, flags); -+} -+ -+EXPORT_SYMBOL_GPL(usb_scuttle_anchored_urbs); -+ -+/** -+ * usb_anchor_empty - is an anchor empty -+ * @anchor: the anchor you want to query -+ * -+ * returns 1 if the anchor has no urbs associated with it -+ */ -+int usb_anchor_empty(struct usb_anchor *anchor) -+{ -+ return list_empty(&anchor->urb_list); -+} -+ -+EXPORT_SYMBOL_GPL(usb_anchor_empty); -+ -+#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28) */ -+ - static void ar9170_usb_submit_urb(struct ar9170_usb *aru) - { - struct urb *urb; ---- a/net/wireless/compat-2.6.28.c -+++ b/net/wireless/compat-2.6.28.c -@@ -12,202 +12,8 @@ - - #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)) - --#include -- - /* 2.6.28 compat code goes here */ - --/* -- * Compat-wireless notes for USB backport stuff: -- * -- * urb->reject exists on 2.6.27, the poison/unpoison helpers -- * did not though. The anchor poison does not exist so we cannot use them. -- * -- * USB anchor poising seems to exist to prevent future driver sumbissions -- * of usb_anchor_urb() to an anchor marked as poisoned. For older kernels -- * we cannot use that, so new usb_anchor_urb()s will be anchored. The down -- * side to this should be submission of URBs will continue being anchored -- * on an anchor instead of having them being rejected immediately when the -- * driver realized we needed to stop. For ar9170 we poison URBs upon the -- * ar9170 mac80211 stop callback(), don't think this should be so bad. -- * It mean there is period of time in older kernels for which we continue -- * to anchor new URBs to a known stopped anchor. We have two anchors -- * (TX, and RX) -- */ -- --#if 0 --/** -- * usb_poison_urb - reliably kill a transfer and prevent further use of an URB -- * @urb: pointer to URB describing a previously submitted request, -- * may be NULL -- * -- * This routine cancels an in-progress request. It is guaranteed that -- * upon return all completion handlers will have finished and the URB -- * will be totally idle and cannot be reused. These features make -- * this an ideal way to stop I/O in a disconnect() callback. -- * If the request has not already finished or been unlinked -- * the completion handler will see urb->status == -ENOENT. -- * -- * After and while the routine runs, attempts to resubmit the URB will fail -- * with error -EPERM. Thus even if the URB's completion handler always -- * tries to resubmit, it will not succeed and the URB will become idle. -- * -- * This routine may not be used in an interrupt context (such as a bottom -- * half or a completion handler), or when holding a spinlock, or in other -- * situations where the caller can't schedule(). -- * -- * This routine should not be called by a driver after its disconnect -- * method has returned. -- */ --void usb_poison_urb(struct urb *urb) --{ -- might_sleep(); -- if (!(urb && urb->dev && urb->ep)) -- return; --#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28)) -- spin_lock_irq(&usb_reject_lock); --#endif -- ++urb->reject; --#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28)) -- spin_unlock_irq(&usb_reject_lock); --#endif -- /* -- * XXX: usb_hcd_unlink_urb() needs backporting... this is defined -- * on usb hcd.c but urb.c gets access to it. That is, older kernels -- * have usb_hcd_unlink_urb() but its not exported, nor can we -- * re-implement it exactly. This essentially dequeues the urb from -- * hw, we need to figure out a way to backport this. -- */ -- //usb_hcd_unlink_urb(urb, -ENOENT); -- -- wait_event(usb_kill_urb_queue, atomic_read(&urb->use_count) == 0); --} --EXPORT_SYMBOL_GPL(usb_poison_urb); --#endif -- --void usb_unpoison_urb(struct urb *urb) --{ --#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28)) -- unsigned long flags; --#endif -- -- if (!urb) -- return; -- --#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28)) -- spin_lock_irqsave(&usb_reject_lock, flags); --#endif -- --urb->reject; --#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28)) -- spin_unlock_irqrestore(&usb_reject_lock, flags); --#endif --} --EXPORT_SYMBOL_GPL(usb_unpoison_urb); -- -- --#if 0 --/** -- * usb_poison_anchored_urbs - cease all traffic from an anchor -- * @anchor: anchor the requests are bound to -- * -- * this allows all outstanding URBs to be poisoned starting -- * from the back of the queue. Newly added URBs will also be -- * poisoned -- * -- * This routine should not be called by a driver after its disconnect -- * method has returned. -- */ --void usb_poison_anchored_urbs(struct usb_anchor *anchor) --{ -- struct urb *victim; -- -- spin_lock_irq(&anchor->lock); -- // anchor->poisoned = 1; /* XXX: Cannot backport */ -- while (!list_empty(&anchor->urb_list)) { -- victim = list_entry(anchor->urb_list.prev, struct urb, -- anchor_list); -- /* we must make sure the URB isn't freed before we kill it*/ -- usb_get_urb(victim); -- spin_unlock_irq(&anchor->lock); -- /* this will unanchor the URB */ -- usb_poison_urb(victim); -- usb_put_urb(victim); -- spin_lock_irq(&anchor->lock); -- } -- spin_unlock_irq(&anchor->lock); --} --EXPORT_SYMBOL_GPL(usb_poison_anchored_urbs); --#endif -- --/** -- * usb_get_from_anchor - get an anchor's oldest urb -- * @anchor: the anchor whose urb you want -- * -- * this will take the oldest urb from an anchor, -- * unanchor and return it -- */ --struct urb *usb_get_from_anchor(struct usb_anchor *anchor) --{ -- struct urb *victim; -- unsigned long flags; -- -- spin_lock_irqsave(&anchor->lock, flags); -- if (!list_empty(&anchor->urb_list)) { -- victim = list_entry(anchor->urb_list.next, struct urb, -- anchor_list); -- usb_get_urb(victim); -- spin_unlock_irqrestore(&anchor->lock, flags); -- usb_unanchor_urb(victim); -- } else { -- spin_unlock_irqrestore(&anchor->lock, flags); -- victim = NULL; -- } -- -- return victim; --} -- --EXPORT_SYMBOL_GPL(usb_get_from_anchor); -- --/** -- * usb_scuttle_anchored_urbs - unanchor all an anchor's urbs -- * @anchor: the anchor whose urbs you want to unanchor -- * -- * use this to get rid of all an anchor's urbs -- */ --void usb_scuttle_anchored_urbs(struct usb_anchor *anchor) --{ -- struct urb *victim; -- unsigned long flags; -- -- spin_lock_irqsave(&anchor->lock, flags); -- while (!list_empty(&anchor->urb_list)) { -- victim = list_entry(anchor->urb_list.prev, struct urb, -- anchor_list); -- usb_get_urb(victim); -- spin_unlock_irqrestore(&anchor->lock, flags); -- /* this may free the URB */ -- usb_unanchor_urb(victim); -- usb_put_urb(victim); -- spin_lock_irqsave(&anchor->lock, flags); -- } -- spin_unlock_irqrestore(&anchor->lock, flags); --} -- --EXPORT_SYMBOL_GPL(usb_scuttle_anchored_urbs); -- --/** -- * usb_anchor_empty - is an anchor empty -- * @anchor: the anchor you want to query -- * -- * returns 1 if the anchor has no urbs associated with it -- */ --int usb_anchor_empty(struct usb_anchor *anchor) --{ -- return list_empty(&anchor->urb_list); --} -- --EXPORT_SYMBOL_GPL(usb_anchor_empty); -- -- - void __iomem *pci_ioremap_bar(struct pci_dev *pdev, int bar) - { - /* ---- a/net/wireless/compat-2.6.29.c -+++ b/net/wireless/compat-2.6.29.c -@@ -12,29 +12,7 @@ - - #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29)) - --#include -- --/** -- * usb_unpoison_anchored_urbs - let an anchor be used successfully again -- * @anchor: anchor the requests are bound to -- * -- * Reverses the effect of usb_poison_anchored_urbs -- * the anchor can be used normally after it returns -- */ --void usb_unpoison_anchored_urbs(struct usb_anchor *anchor) --{ -- unsigned long flags; -- struct urb *lazarus; -- -- spin_lock_irqsave(&anchor->lock, flags); -- list_for_each_entry(lazarus, &anchor->urb_list, anchor_list) { -- usb_unpoison_urb(lazarus); -- } -- //anchor->poisoned = 0; /* XXX: cannot backport */ -- spin_unlock_irqrestore(&anchor->lock, flags); --} --EXPORT_SYMBOL_GPL(usb_unpoison_anchored_urbs); -- -+/* 2.6.29 compat code goes here */ - - #endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29) */ - ---- a/include/net/compat-2.6.28.h -+++ b/include/net/compat-2.6.28.h -@@ -9,7 +9,6 @@ - - #include - #include --#include - - #ifndef ETH_P_PAE - #define ETH_P_PAE 0x888E /* Port Access Entity (IEEE 802.1X) */ -@@ -37,19 +36,6 @@ - #define pcmcia_parse_tuple(tuple, parse) pccard_parse_tuple(tuple, parse) - #endif - --#if 0 --extern void usb_poison_urb(struct urb *urb); --#endif --extern void usb_unpoison_urb(struct urb *urb); -- --#if 0 --extern void usb_poison_anchored_urbs(struct usb_anchor *anchor); --#endif -- --extern struct urb *usb_get_from_anchor(struct usb_anchor *anchor); --extern void usb_scuttle_anchored_urbs(struct usb_anchor *anchor); --extern int usb_anchor_empty(struct usb_anchor *anchor); -- - - void __iomem *pci_ioremap_bar(struct pci_dev *pdev, int bar); - ---- a/include/net/compat-2.6.29.h -+++ b/include/net/compat-2.6.29.h -@@ -8,7 +8,6 @@ - #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29)) - - #include --#include - - /** - * skb_queue_is_first - check if skb is the first entry in the queue -@@ -41,8 +40,6 @@ static inline struct sk_buff *skb_queue_ - return skb->prev; - } - --extern void usb_unpoison_anchored_urbs(struct usb_anchor *anchor); -- - #define DIV_ROUND_CLOSEST(x, divisor)( \ - { \ - typeof(divisor) __divisor = divisor; \ diff --git a/package/mac80211/patches/020-fix_compat_h.patch b/package/mac80211/patches/020-fix_compat_h.patch new file mode 100644 index 000000000..7f90cf4dc --- /dev/null +++ b/package/mac80211/patches/020-fix_compat_h.patch @@ -0,0 +1,11 @@ +--- a/include/linux/compat-2.6.32.h ++++ b/include/linux/compat-2.6.32.h +@@ -7,7 +7,7 @@ + #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,32)) + + #include +-#include ++#include + #include + #include + diff --git a/package/mac80211/patches/021-fix_missing_ifdefs.patch b/package/mac80211/patches/021-fix_missing_ifdefs.patch new file mode 100644 index 000000000..2c838ebac --- /dev/null +++ b/package/mac80211/patches/021-fix_missing_ifdefs.patch @@ -0,0 +1,18 @@ +--- a/compat/compat-2.6.33.c ++++ b/compat/compat-2.6.33.c +@@ -12,6 +12,7 @@ + + #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33)) + ++#ifdef CONFIG_PCCARD + + /** + * pccard_loop_tuple() - loop over tuples in the CIS +@@ -125,6 +126,7 @@ int pcmcia_loop_tuple(struct pcmcia_devi + EXPORT_SYMBOL(pcmcia_loop_tuple); + /* Source: drivers/pcmcia/pcmcia_resource.c */ + ++#endif + + #endif /* (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33)) */ + diff --git a/package/mac80211/patches/401-ath9k-dont-register-leds-on-ar9100.patch b/package/mac80211/patches/401-ath9k-dont-register-leds-on-ar9100.patch index 2a9bdc8b2..a4af5c98d 100644 --- a/package/mac80211/patches/401-ath9k-dont-register-leds-on-ar9100.patch +++ b/package/mac80211/patches/401-ath9k-dont-register-leds-on-ar9100.patch @@ -1,6 +1,6 @@ --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c -@@ -1139,6 +1139,9 @@ static void ath_unregister_led(struct at +@@ -1103,6 +1103,9 @@ static void ath_unregister_led(struct at static void ath_deinit_leds(struct ath_softc *sc) { @@ -10,7 +10,7 @@ ath_unregister_led(&sc->assoc_led); sc->sc_flags &= ~SC_OP_LED_ASSOCIATED; ath_unregister_led(&sc->tx_led); -@@ -1157,6 +1160,9 @@ static void ath_init_leds(struct ath_sof +@@ -1121,6 +1124,9 @@ static void ath_init_leds(struct ath_sof else sc->sc_ah->led_pin = ATH_LED_PIN_DEF; diff --git a/package/mac80211/patches/403-ath9k-fix-invalid-mac-address-handling.patch b/package/mac80211/patches/403-ath9k-fix-invalid-mac-address-handling.patch index 687d9e477..63cb3d979 100644 --- a/package/mac80211/patches/403-ath9k-fix-invalid-mac-address-handling.patch +++ b/package/mac80211/patches/403-ath9k-fix-invalid-mac-address-handling.patch @@ -8,7 +8,7 @@ #include #include "hw.h" -@@ -489,8 +490,18 @@ static int ath9k_hw_init_macaddr(struct +@@ -461,8 +462,18 @@ static int ath9k_hw_init_macaddr(struct common->macaddr[2 * i] = eeval >> 8; common->macaddr[2 * i + 1] = eeval & 0xff; } diff --git a/package/mac80211/patches/406-ath9k-set-AH_USE_EEPROM-only-if-no-platform-data-present.patch b/package/mac80211/patches/406-ath9k-set-AH_USE_EEPROM-only-if-no-platform-data-present.patch index 734dea030..6be788814 100644 --- a/package/mac80211/patches/406-ath9k-set-AH_USE_EEPROM-only-if-no-platform-data-present.patch +++ b/package/mac80211/patches/406-ath9k-set-AH_USE_EEPROM-only-if-no-platform-data-present.patch @@ -1,6 +1,6 @@ --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c -@@ -431,11 +431,8 @@ static void ath9k_hw_init_defaults(struc +@@ -403,11 +403,8 @@ static void ath9k_hw_init_defaults(struc ah->hw_version.magic = AR5416_MAGIC; ah->hw_version.subvendorid = 0; @@ -22,7 +22,7 @@ #include "ath9k.h" #include "btcoex.h" -@@ -1633,6 +1634,7 @@ static int ath_init_softc(u16 devid, str +@@ -1597,6 +1598,7 @@ static int ath_init_softc(u16 devid, str { struct ath_hw *ah = NULL; struct ath_common *common; @@ -30,7 +30,7 @@ int r = 0, i; int csz = 0; int qnum; -@@ -1656,6 +1658,10 @@ static int ath_init_softc(u16 devid, str +@@ -1619,6 +1621,10 @@ static int ath_init_softc(u16 devid, str ah->hw_version.devid = devid; ah->hw_version.subsysid = subsysid; diff --git a/package/mac80211/patches/407-ath9k-override-mac-address-from-platform-data.patch b/package/mac80211/patches/407-ath9k-override-mac-address-from-platform-data.patch index e4aeab5ce..615de77a5 100644 --- a/package/mac80211/patches/407-ath9k-override-mac-address-from-platform-data.patch +++ b/package/mac80211/patches/407-ath9k-override-mac-address-from-platform-data.patch @@ -11,7 +11,7 @@ #include "hw.h" #include "rc.h" #include "initvals.h" -@@ -472,17 +474,23 @@ static int ath9k_hw_rf_claim(struct ath_ +@@ -448,17 +450,23 @@ static int ath9k_hw_rf_claim(struct ath_ static int ath9k_hw_init_macaddr(struct ath_hw *ah) { struct ath_common *common = ath9k_hw_common(ah); diff --git a/package/mac80211/patches/500-ath9k_rate_control_api.patch b/package/mac80211/patches/500-ath9k_rate_control_api.patch deleted file mode 100644 index fe476cb25..000000000 --- a/package/mac80211/patches/500-ath9k_rate_control_api.patch +++ /dev/null @@ -1,1244 +0,0 @@ ---- a/drivers/net/wireless/ath/ath9k/rc.c -+++ b/drivers/net/wireless/ath/ath9k/rc.c -@@ -19,132 +19,133 @@ - - static const struct ath_rate_table ar5416_11na_ratetable = { - 42, -+ 8, /* MCS start */ - { - { VALID, VALID, WLAN_RC_PHY_OFDM, 6000, /* 6 Mb */ -- 5400, 0x0b, 0x00, 12, -+ 5400, 0, 0x00, 12, - 0, 0, 0, 0, 0, 0 }, - { VALID, VALID, WLAN_RC_PHY_OFDM, 9000, /* 9 Mb */ -- 7800, 0x0f, 0x00, 18, -+ 7800, 1, 0x00, 18, - 0, 1, 1, 1, 1, 0 }, - { VALID, VALID, WLAN_RC_PHY_OFDM, 12000, /* 12 Mb */ -- 10000, 0x0a, 0x00, 24, -+ 10000, 2, 0x00, 24, - 2, 2, 2, 2, 2, 0 }, - { VALID, VALID, WLAN_RC_PHY_OFDM, 18000, /* 18 Mb */ -- 13900, 0x0e, 0x00, 36, -+ 13900, 3, 0x00, 36, - 2, 3, 3, 3, 3, 0 }, - { VALID, VALID, WLAN_RC_PHY_OFDM, 24000, /* 24 Mb */ -- 17300, 0x09, 0x00, 48, -+ 17300, 4, 0x00, 48, - 4, 4, 4, 4, 4, 0 }, - { VALID, VALID, WLAN_RC_PHY_OFDM, 36000, /* 36 Mb */ -- 23000, 0x0d, 0x00, 72, -+ 23000, 5, 0x00, 72, - 4, 5, 5, 5, 5, 0 }, - { VALID, VALID, WLAN_RC_PHY_OFDM, 48000, /* 48 Mb */ -- 27400, 0x08, 0x00, 96, -+ 27400, 6, 0x00, 96, - 4, 6, 6, 6, 6, 0 }, - { VALID, VALID, WLAN_RC_PHY_OFDM, 54000, /* 54 Mb */ -- 29300, 0x0c, 0x00, 108, -+ 29300, 7, 0x00, 108, - 4, 7, 7, 7, 7, 0 }, - { VALID_2040, VALID_2040, WLAN_RC_PHY_HT_20_SS, 6500, /* 6.5 Mb */ -- 6400, 0x80, 0x00, 0, -+ 6400, 0, 0x00, 0, - 0, 8, 24, 8, 24, 3216 }, - { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 13000, /* 13 Mb */ -- 12700, 0x81, 0x00, 1, -+ 12700, 1, 0x00, 1, - 2, 9, 25, 9, 25, 6434 }, - { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 19500, /* 19.5 Mb */ -- 18800, 0x82, 0x00, 2, -+ 18800, 2, 0x00, 2, - 2, 10, 26, 10, 26, 9650 }, - { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 26000, /* 26 Mb */ -- 25000, 0x83, 0x00, 3, -+ 25000, 3, 0x00, 3, - 4, 11, 27, 11, 27, 12868 }, - { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 39000, /* 39 Mb */ -- 36700, 0x84, 0x00, 4, -+ 36700, 4, 0x00, 4, - 4, 12, 28, 12, 28, 19304 }, - { INVALID, VALID_20, WLAN_RC_PHY_HT_20_SS, 52000, /* 52 Mb */ -- 48100, 0x85, 0x00, 5, -+ 48100, 5, 0x00, 5, - 4, 13, 29, 13, 29, 25740 }, - { INVALID, VALID_20, WLAN_RC_PHY_HT_20_SS, 58500, /* 58.5 Mb */ -- 53500, 0x86, 0x00, 6, -+ 53500, 6, 0x00, 6, - 4, 14, 30, 14, 30, 28956 }, - { INVALID, VALID_20, WLAN_RC_PHY_HT_20_SS, 65000, /* 65 Mb */ -- 59000, 0x87, 0x00, 7, -+ 59000, 7, 0x00, 7, - 4, 15, 31, 15, 32, 32180 }, - { INVALID, INVALID, WLAN_RC_PHY_HT_20_DS, 13000, /* 13 Mb */ -- 12700, 0x88, 0x00, -+ 12700, 8, 0x00, - 8, 3, 16, 33, 16, 33, 6430 }, - { INVALID, INVALID, WLAN_RC_PHY_HT_20_DS, 26000, /* 26 Mb */ -- 24800, 0x89, 0x00, 9, -+ 24800, 9, 0x00, 9, - 2, 17, 34, 17, 34, 12860 }, - { INVALID, INVALID, WLAN_RC_PHY_HT_20_DS, 39000, /* 39 Mb */ -- 36600, 0x8a, 0x00, 10, -+ 36600, 10, 0x00, 10, - 2, 18, 35, 18, 35, 19300 }, - { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 52000, /* 52 Mb */ -- 48100, 0x8b, 0x00, 11, -+ 48100, 11, 0x00, 11, - 4, 19, 36, 19, 36, 25736 }, - { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 78000, /* 78 Mb */ -- 69500, 0x8c, 0x00, 12, -+ 69500, 12, 0x00, 12, - 4, 20, 37, 20, 37, 38600 }, - { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 104000, /* 104 Mb */ -- 89500, 0x8d, 0x00, 13, -+ 89500, 13, 0x00, 13, - 4, 21, 38, 21, 38, 51472 }, - { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 117000, /* 117 Mb */ -- 98900, 0x8e, 0x00, 14, -+ 98900, 14, 0x00, 14, - 4, 22, 39, 22, 39, 57890 }, - { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 130000, /* 130 Mb */ -- 108300, 0x8f, 0x00, 15, -+ 108300, 15, 0x00, 15, - 4, 23, 40, 23, 41, 64320 }, - { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 13500, /* 13.5 Mb */ -- 13200, 0x80, 0x00, 0, -+ 13200, 0, 0x00, 0, - 0, 8, 24, 24, 24, 6684 }, - { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 27500, /* 27.0 Mb */ -- 25900, 0x81, 0x00, 1, -+ 25900, 1, 0x00, 1, - 2, 9, 25, 25, 25, 13368 }, - { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 40500, /* 40.5 Mb */ -- 38600, 0x82, 0x00, 2, -+ 38600, 2, 0x00, 2, - 2, 10, 26, 26, 26, 20052 }, - { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 54000, /* 54 Mb */ -- 49800, 0x83, 0x00, 3, -+ 49800, 3, 0x00, 3, - 4, 11, 27, 27, 27, 26738 }, - { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 81500, /* 81 Mb */ -- 72200, 0x84, 0x00, 4, -+ 72200, 4, 0x00, 4, - 4, 12, 28, 28, 28, 40104 }, - { INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS, 108000, /* 108 Mb */ -- 92900, 0x85, 0x00, 5, -+ 92900, 5, 0x00, 5, - 4, 13, 29, 29, 29, 53476 }, - { INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS, 121500, /* 121.5 Mb */ -- 102700, 0x86, 0x00, 6, -+ 102700, 6, 0x00, 6, - 4, 14, 30, 30, 30, 60156 }, - { INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS, 135000, /* 135 Mb */ -- 112000, 0x87, 0x00, 7, -+ 112000, 7, 0x00, 7, - 4, 15, 31, 32, 32, 66840 }, - { INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS_HGI, 150000, /* 150 Mb */ -- 122000, 0x87, 0x00, 7, -+ 122000, 7, 0x00, 7, - 4, 15, 31, 32, 32, 74200 }, - { INVALID, INVALID, WLAN_RC_PHY_HT_40_DS, 27000, /* 27 Mb */ -- 25800, 0x88, 0x00, 8, -+ 25800, 8, 0x00, 8, - 0, 16, 33, 33, 33, 13360 }, - { INVALID, INVALID, WLAN_RC_PHY_HT_40_DS, 54000, /* 54 Mb */ -- 49800, 0x89, 0x00, 9, -+ 49800, 9, 0x00, 9, - 2, 17, 34, 34, 34, 26720 }, - { INVALID, INVALID, WLAN_RC_PHY_HT_40_DS, 81000, /* 81 Mb */ -- 71900, 0x8a, 0x00, 10, -+ 71900, 10, 0x00, 10, - 2, 18, 35, 35, 35, 40080 }, - { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 108000, /* 108 Mb */ -- 92500, 0x8b, 0x00, 11, -+ 92500, 11, 0x00, 11, - 4, 19, 36, 36, 36, 53440 }, - { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 162000, /* 162 Mb */ -- 130300, 0x8c, 0x00, 12, -+ 130300, 12, 0x00, 12, - 4, 20, 37, 37, 37, 80160 }, - { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 216000, /* 216 Mb */ -- 162800, 0x8d, 0x00, 13, -+ 162800, 13, 0x00, 13, - 4, 21, 38, 38, 38, 106880 }, - { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 243000, /* 243 Mb */ -- 178200, 0x8e, 0x00, 14, -+ 178200, 14, 0x00, 14, - 4, 22, 39, 39, 39, 120240 }, - { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 270000, /* 270 Mb */ -- 192100, 0x8f, 0x00, 15, -+ 192100, 15, 0x00, 15, - 4, 23, 40, 41, 41, 133600 }, - { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS_HGI, 300000, /* 300 Mb */ -- 207000, 0x8f, 0x00, 15, -+ 207000, 15, 0x00, 15, - 4, 23, 40, 41, 41, 148400 }, - }, - 50, /* probe interval */ -@@ -156,144 +157,145 @@ static const struct ath_rate_table ar541 - - static const struct ath_rate_table ar5416_11ng_ratetable = { - 46, -+ 12, /* MCS start */ - { - { VALID_ALL, VALID_ALL, WLAN_RC_PHY_CCK, 1000, /* 1 Mb */ -- 900, 0x1b, 0x00, 2, -+ 900, 0, 0x00, 2, - 0, 0, 0, 0, 0, 0 }, - { VALID_ALL, VALID_ALL, WLAN_RC_PHY_CCK, 2000, /* 2 Mb */ -- 1900, 0x1a, 0x04, 4, -+ 1900, 1, 0x04, 4, - 1, 1, 1, 1, 1, 0 }, - { VALID_ALL, VALID_ALL, WLAN_RC_PHY_CCK, 5500, /* 5.5 Mb */ -- 4900, 0x19, 0x04, 11, -+ 4900, 2, 0x04, 11, - 2, 2, 2, 2, 2, 0 }, - { VALID_ALL, VALID_ALL, WLAN_RC_PHY_CCK, 11000, /* 11 Mb */ -- 8100, 0x18, 0x04, 22, -+ 8100, 3, 0x04, 22, - 3, 3, 3, 3, 3, 0 }, - { INVALID, INVALID, WLAN_RC_PHY_OFDM, 6000, /* 6 Mb */ -- 5400, 0x0b, 0x00, 12, -+ 5400, 4, 0x00, 12, - 4, 4, 4, 4, 4, 0 }, - { INVALID, INVALID, WLAN_RC_PHY_OFDM, 9000, /* 9 Mb */ -- 7800, 0x0f, 0x00, 18, -+ 7800, 5, 0x00, 18, - 4, 5, 5, 5, 5, 0 }, - { VALID, VALID, WLAN_RC_PHY_OFDM, 12000, /* 12 Mb */ -- 10100, 0x0a, 0x00, 24, -+ 10100, 6, 0x00, 24, - 6, 6, 6, 6, 6, 0 }, - { VALID, VALID, WLAN_RC_PHY_OFDM, 18000, /* 18 Mb */ -- 14100, 0x0e, 0x00, 36, -+ 14100, 7, 0x00, 36, - 6, 7, 7, 7, 7, 0 }, - { VALID, VALID, WLAN_RC_PHY_OFDM, 24000, /* 24 Mb */ -- 17700, 0x09, 0x00, 48, -+ 17700, 8, 0x00, 48, - 8, 8, 8, 8, 8, 0 }, - { VALID, VALID, WLAN_RC_PHY_OFDM, 36000, /* 36 Mb */ -- 23700, 0x0d, 0x00, 72, -+ 23700, 9, 0x00, 72, - 8, 9, 9, 9, 9, 0 }, - { VALID, VALID, WLAN_RC_PHY_OFDM, 48000, /* 48 Mb */ -- 27400, 0x08, 0x00, 96, -+ 27400, 10, 0x00, 96, - 8, 10, 10, 10, 10, 0 }, - { VALID, VALID, WLAN_RC_PHY_OFDM, 54000, /* 54 Mb */ -- 30900, 0x0c, 0x00, 108, -+ 30900, 11, 0x00, 108, - 8, 11, 11, 11, 11, 0 }, - { INVALID, INVALID, WLAN_RC_PHY_HT_20_SS, 6500, /* 6.5 Mb */ -- 6400, 0x80, 0x00, 0, -+ 6400, 0, 0x00, 0, - 4, 12, 28, 12, 28, 3216 }, - { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 13000, /* 13 Mb */ -- 12700, 0x81, 0x00, 1, -+ 12700, 1, 0x00, 1, - 6, 13, 29, 13, 29, 6434 }, - { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 19500, /* 19.5 Mb */ -- 18800, 0x82, 0x00, 2, -+ 18800, 2, 0x00, 2, - 6, 14, 30, 14, 30, 9650 }, - { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 26000, /* 26 Mb */ -- 25000, 0x83, 0x00, 3, -+ 25000, 3, 0x00, 3, - 8, 15, 31, 15, 31, 12868 }, - { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 39000, /* 39 Mb */ -- 36700, 0x84, 0x00, 4, -+ 36700, 4, 0x00, 4, - 8, 16, 32, 16, 32, 19304 }, - { INVALID, VALID_20, WLAN_RC_PHY_HT_20_SS, 52000, /* 52 Mb */ -- 48100, 0x85, 0x00, 5, -+ 48100, 5, 0x00, 5, - 8, 17, 33, 17, 33, 25740 }, - { INVALID, VALID_20, WLAN_RC_PHY_HT_20_SS, 58500, /* 58.5 Mb */ -- 53500, 0x86, 0x00, 6, -+ 53500, 6, 0x00, 6, - 8, 18, 34, 18, 34, 28956 }, - { INVALID, VALID_20, WLAN_RC_PHY_HT_20_SS, 65000, /* 65 Mb */ -- 59000, 0x87, 0x00, 7, -+ 59000, 7, 0x00, 7, - 8, 19, 35, 19, 36, 32180 }, - { INVALID, INVALID, WLAN_RC_PHY_HT_20_DS, 13000, /* 13 Mb */ -- 12700, 0x88, 0x00, 8, -+ 12700, 8, 0x00, 8, - 4, 20, 37, 20, 37, 6430 }, - { INVALID, INVALID, WLAN_RC_PHY_HT_20_DS, 26000, /* 26 Mb */ -- 24800, 0x89, 0x00, 9, -+ 24800, 9, 0x00, 9, - 6, 21, 38, 21, 38, 12860 }, - { INVALID, INVALID, WLAN_RC_PHY_HT_20_DS, 39000, /* 39 Mb */ -- 36600, 0x8a, 0x00, 10, -+ 36600, 10, 0x00, 10, - 6, 22, 39, 22, 39, 19300 }, - { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 52000, /* 52 Mb */ -- 48100, 0x8b, 0x00, 11, -+ 48100, 11, 0x00, 11, - 8, 23, 40, 23, 40, 25736 }, - { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 78000, /* 78 Mb */ -- 69500, 0x8c, 0x00, 12, -+ 69500, 12, 0x00, 12, - 8, 24, 41, 24, 41, 38600 }, - { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 104000, /* 104 Mb */ -- 89500, 0x8d, 0x00, 13, -+ 89500, 13, 0x00, 13, - 8, 25, 42, 25, 42, 51472 }, - { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 117000, /* 117 Mb */ -- 98900, 0x8e, 0x00, 14, -+ 98900, 14, 0x00, 14, - 8, 26, 43, 26, 44, 57890 }, - { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 130000, /* 130 Mb */ -- 108300, 0x8f, 0x00, 15, -+ 108300, 15, 0x00, 15, - 8, 27, 44, 27, 45, 64320 }, - { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 13500, /* 13.5 Mb */ -- 13200, 0x80, 0x00, 0, -+ 13200, 0, 0x00, 0, - 8, 12, 28, 28, 28, 6684 }, - { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 27500, /* 27.0 Mb */ -- 25900, 0x81, 0x00, 1, -+ 25900, 1, 0x00, 1, - 8, 13, 29, 29, 29, 13368 }, - { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 40500, /* 40.5 Mb */ -- 38600, 0x82, 0x00, 2, -+ 38600, 2, 0x00, 2, - 8, 14, 30, 30, 30, 20052 }, - { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 54000, /* 54 Mb */ -- 49800, 0x83, 0x00, 3, -+ 49800, 3, 0x00, 3, - 8, 15, 31, 31, 31, 26738 }, - { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 81500, /* 81 Mb */ -- 72200, 0x84, 0x00, 4, -+ 72200, 4, 0x00, 4, - 8, 16, 32, 32, 32, 40104 }, - { INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS, 108000, /* 108 Mb */ -- 92900, 0x85, 0x00, 5, -+ 92900, 5, 0x00, 5, - 8, 17, 33, 33, 33, 53476 }, - { INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS, 121500, /* 121.5 Mb */ -- 102700, 0x86, 0x00, 6, -+ 102700, 6, 0x00, 6, - 8, 18, 34, 34, 34, 60156 }, - { INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS, 135000, /* 135 Mb */ -- 112000, 0x87, 0x00, 7, -+ 112000, 7, 0x00, 7, - 8, 19, 35, 36, 36, 66840 }, - { INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS_HGI, 150000, /* 150 Mb */ -- 122000, 0x87, 0x00, 7, -+ 122000, 7, 0x00, 7, - 8, 19, 35, 36, 36, 74200 }, - { INVALID, INVALID, WLAN_RC_PHY_HT_40_DS, 27000, /* 27 Mb */ -- 25800, 0x88, 0x00, 8, -+ 25800, 8, 0x00, 8, - 8, 20, 37, 37, 37, 13360 }, - { INVALID, INVALID, WLAN_RC_PHY_HT_40_DS, 54000, /* 54 Mb */ -- 49800, 0x89, 0x00, 9, -+ 49800, 9, 0x00, 9, - 8, 21, 38, 38, 38, 26720 }, - { INVALID, INVALID, WLAN_RC_PHY_HT_40_DS, 81000, /* 81 Mb */ -- 71900, 0x8a, 0x00, 10, -+ 71900, 10, 0x00, 10, - 8, 22, 39, 39, 39, 40080 }, - { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 108000, /* 108 Mb */ -- 92500, 0x8b, 0x00, 11, -+ 92500, 11, 0x00, 11, - 8, 23, 40, 40, 40, 53440 }, - { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 162000, /* 162 Mb */ -- 130300, 0x8c, 0x00, 12, -+ 130300, 12, 0x00, 12, - 8, 24, 41, 41, 41, 80160 }, - { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 216000, /* 216 Mb */ -- 162800, 0x8d, 0x00, 13, -+ 162800, 13, 0x00, 13, - 8, 25, 42, 42, 42, 106880 }, - { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 243000, /* 243 Mb */ -- 178200, 0x8e, 0x00, 14, -+ 178200, 14, 0x00, 14, - 8, 26, 43, 43, 43, 120240 }, - { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 270000, /* 270 Mb */ -- 192100, 0x8f, 0x00, 15, -+ 192100, 15, 0x00, 15, - 8, 27, 44, 45, 45, 133600 }, - { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS_HGI, 300000, /* 300 Mb */ -- 207000, 0x8f, 0x00, 15, -+ 207000, 15, 0x00, 15, - 8, 27, 44, 45, 45, 148400 }, - }, - 50, /* probe interval */ -@@ -302,30 +304,31 @@ static const struct ath_rate_table ar541 - - static const struct ath_rate_table ar5416_11a_ratetable = { - 8, -+ 0, - { - { VALID, VALID, WLAN_RC_PHY_OFDM, 6000, /* 6 Mb */ -- 5400, 0x0b, 0x00, (0x80|12), -+ 5400, 0, 0x00, 12, - 0, 0, 0 }, - { VALID, VALID, WLAN_RC_PHY_OFDM, 9000, /* 9 Mb */ -- 7800, 0x0f, 0x00, 18, -+ 7800, 1, 0x00, 18, - 0, 1, 0 }, - { VALID, VALID, WLAN_RC_PHY_OFDM, 12000, /* 12 Mb */ -- 10000, 0x0a, 0x00, (0x80|24), -+ 10000, 2, 0x00, 24, - 2, 2, 0 }, - { VALID, VALID, WLAN_RC_PHY_OFDM, 18000, /* 18 Mb */ -- 13900, 0x0e, 0x00, 36, -+ 13900, 3, 0x00, 36, - 2, 3, 0 }, - { VALID, VALID, WLAN_RC_PHY_OFDM, 24000, /* 24 Mb */ -- 17300, 0x09, 0x00, (0x80|48), -+ 17300, 4, 0x00, 48, - 4, 4, 0 }, - { VALID, VALID, WLAN_RC_PHY_OFDM, 36000, /* 36 Mb */ -- 23000, 0x0d, 0x00, 72, -+ 23000, 5, 0x00, 72, - 4, 5, 0 }, - { VALID, VALID, WLAN_RC_PHY_OFDM, 48000, /* 48 Mb */ -- 27400, 0x08, 0x00, 96, -+ 27400, 6, 0x00, 96, - 4, 6, 0 }, - { VALID, VALID, WLAN_RC_PHY_OFDM, 54000, /* 54 Mb */ -- 29300, 0x0c, 0x00, 108, -+ 29300, 7, 0x00, 108, - 4, 7, 0 }, - }, - 50, /* probe interval */ -@@ -334,48 +337,63 @@ static const struct ath_rate_table ar541 - - static const struct ath_rate_table ar5416_11g_ratetable = { - 12, -+ 0, - { - { VALID, VALID, WLAN_RC_PHY_CCK, 1000, /* 1 Mb */ -- 900, 0x1b, 0x00, 2, -+ 900, 0, 0x00, 2, - 0, 0, 0 }, - { VALID, VALID, WLAN_RC_PHY_CCK, 2000, /* 2 Mb */ -- 1900, 0x1a, 0x04, 4, -+ 1900, 1, 0x04, 4, - 1, 1, 0 }, - { VALID, VALID, WLAN_RC_PHY_CCK, 5500, /* 5.5 Mb */ -- 4900, 0x19, 0x04, 11, -+ 4900, 2, 0x04, 11, - 2, 2, 0 }, - { VALID, VALID, WLAN_RC_PHY_CCK, 11000, /* 11 Mb */ -- 8100, 0x18, 0x04, 22, -+ 8100, 3, 0x04, 22, - 3, 3, 0 }, - { INVALID, INVALID, WLAN_RC_PHY_OFDM, 6000, /* 6 Mb */ -- 5400, 0x0b, 0x00, 12, -+ 5400, 4, 0x00, 12, - 4, 4, 0 }, - { INVALID, INVALID, WLAN_RC_PHY_OFDM, 9000, /* 9 Mb */ -- 7800, 0x0f, 0x00, 18, -+ 7800, 5, 0x00, 18, - 4, 5, 0 }, - { VALID, VALID, WLAN_RC_PHY_OFDM, 12000, /* 12 Mb */ -- 10000, 0x0a, 0x00, 24, -+ 10000, 6, 0x00, 24, - 6, 6, 0 }, - { VALID, VALID, WLAN_RC_PHY_OFDM, 18000, /* 18 Mb */ -- 13900, 0x0e, 0x00, 36, -+ 13900, 7, 0x00, 36, - 6, 7, 0 }, - { VALID, VALID, WLAN_RC_PHY_OFDM, 24000, /* 24 Mb */ -- 17300, 0x09, 0x00, 48, -+ 17300, 8, 0x00, 48, - 8, 8, 0 }, - { VALID, VALID, WLAN_RC_PHY_OFDM, 36000, /* 36 Mb */ -- 23000, 0x0d, 0x00, 72, -+ 23000, 9, 0x00, 72, - 8, 9, 0 }, - { VALID, VALID, WLAN_RC_PHY_OFDM, 48000, /* 48 Mb */ -- 27400, 0x08, 0x00, 96, -+ 27400, 10, 0x00, 96, - 8, 10, 0 }, - { VALID, VALID, WLAN_RC_PHY_OFDM, 54000, /* 54 Mb */ -- 29300, 0x0c, 0x00, 108, -+ 29300, 11, 0x00, 108, - 8, 11, 0 }, - }, - 50, /* probe interval */ - 0, /* Phy rates allowed initially */ - }; - -+static const struct ath_rate_table *hw_rate_table[ATH9K_MODE_MAX] = { -+ [ATH9K_MODE_11A] = &ar5416_11a_ratetable, -+ [ATH9K_MODE_11G] = &ar5416_11g_ratetable, -+ [ATH9K_MODE_11NA_HT20] = &ar5416_11na_ratetable, -+ [ATH9K_MODE_11NG_HT20] = &ar5416_11ng_ratetable, -+ [ATH9K_MODE_11NA_HT40PLUS] = &ar5416_11na_ratetable, -+ [ATH9K_MODE_11NA_HT40MINUS] = &ar5416_11na_ratetable, -+ [ATH9K_MODE_11NG_HT40PLUS] = &ar5416_11ng_ratetable, -+ [ATH9K_MODE_11NG_HT40MINUS] = &ar5416_11ng_ratetable, -+}; -+ -+static int ath_rc_get_rateindex(const struct ath_rate_table *rate_table, -+ struct ieee80211_tx_rate *rate); -+ - static inline int8_t median(int8_t a, int8_t b, int8_t c) - { - if (a >= b) { -@@ -534,7 +552,7 @@ static u8 ath_rc_setvalid_rates(struct a - * capflag matches one of the validity - * (VALID/VALID_20/VALID_40) flags */ - -- if (((rate & 0x7F) == (dot11rate & 0x7F)) && -+ if ((rate == dot11rate) && - ((valid & WLAN_RC_CAP_MODE(capflag)) == - WLAN_RC_CAP_MODE(capflag)) && - !WLAN_RC_PHY_HT(phy)) { -@@ -576,8 +594,7 @@ static u8 ath_rc_setvalid_htrates(struct - u8 rate = rateset->rs_rates[i]; - u8 dot11rate = rate_table->info[j].dot11rate; - -- if (((rate & 0x7F) != (dot11rate & 0x7F)) || -- !WLAN_RC_PHY_HT(phy) || -+ if ((rate != dot11rate) || !WLAN_RC_PHY_HT(phy) || - !WLAN_RC_PHY_HT_VALID(valid, capflag)) - continue; - -@@ -696,18 +713,20 @@ static void ath_rc_rate_set_series(const - u8 tries, u8 rix, int rtsctsenable) - { - rate->count = tries; -- rate->idx = rix; -+ rate->idx = rate_table->info[rix].ratecode; - - if (txrc->short_preamble) - rate->flags |= IEEE80211_TX_RC_USE_SHORT_PREAMBLE; - if (txrc->rts || rtsctsenable) - rate->flags |= IEEE80211_TX_RC_USE_RTS_CTS; -- if (WLAN_RC_PHY_40(rate_table->info[rix].phy)) -- rate->flags |= IEEE80211_TX_RC_40_MHZ_WIDTH; -- if (WLAN_RC_PHY_SGI(rate_table->info[rix].phy)) -- rate->flags |= IEEE80211_TX_RC_SHORT_GI; -- if (WLAN_RC_PHY_HT(rate_table->info[rix].phy)) -+ -+ if (WLAN_RC_PHY_HT(rate_table->info[rix].phy)) { - rate->flags |= IEEE80211_TX_RC_MCS; -+ if (WLAN_RC_PHY_40(rate_table->info[rix].phy)) -+ rate->flags |= IEEE80211_TX_RC_40_MHZ_WIDTH; -+ if (WLAN_RC_PHY_SGI(rate_table->info[rix].phy)) -+ rate->flags |= IEEE80211_TX_RC_SHORT_GI; -+ } - } - - static void ath_rc_rate_set_rtscts(struct ath_softc *sc, -@@ -720,7 +739,7 @@ static void ath_rc_rate_set_rtscts(struc - /* get the cix for the lowest valid rix */ - for (i = 3; i >= 0; i--) { - if (rates[i].count && (rates[i].idx >= 0)) { -- rix = rates[i].idx; -+ rix = ath_rc_get_rateindex(rate_table, &rates[i]); - break; - } - } -@@ -1080,15 +1099,19 @@ static int ath_rc_get_rateindex(const st - { - int rix; - -+ if (!(rate->flags & IEEE80211_TX_RC_MCS)) -+ return rate->idx; -+ -+ rix = rate->idx + rate_table->mcs_start; - if ((rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH) && - (rate->flags & IEEE80211_TX_RC_SHORT_GI)) -- rix = rate_table->info[rate->idx].ht_index; -+ rix = rate_table->info[rix].ht_index; - else if (rate->flags & IEEE80211_TX_RC_SHORT_GI) -- rix = rate_table->info[rate->idx].sgi_index; -+ rix = rate_table->info[rix].sgi_index; - else if (rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH) -- rix = rate_table->info[rate->idx].cw40index; -+ rix = rate_table->info[rix].cw40index; - else -- rix = rate_table->info[rate->idx].base_index; -+ rix = rate_table->info[rix].base_index; - - return rix; - } -@@ -1183,7 +1206,9 @@ struct ath_rate_table *ath_choose_rate_t - - ath_print(common, ATH_DBG_CONFIG, - "Choosing rate table for mode: %d\n", mode); -- return sc->hw_rate_table[mode]; -+ -+ sc->cur_rate_mode = mode; -+ return hw_rate_table[mode]; - } - - static void ath_rc_init(struct ath_softc *sc, -@@ -1197,12 +1222,6 @@ static void ath_rc_init(struct ath_softc - u8 *ht_mcs = (u8 *)&ath_rc_priv->neg_ht_rates; - u8 i, j, k, hi = 0, hthi = 0; - -- if (!rate_table) { -- ath_print(common, ATH_DBG_FATAL, -- "Rate table not initialized\n"); -- return; -- } -- - /* Initial rate table size. Will change depending - * on the working rate set */ - ath_rc_priv->rate_table_size = RATE_TABLE_SIZE; -@@ -1357,7 +1376,8 @@ static void ath_tx_status(void *priv, st - } - } - -- ath_debug_stat_rc(sc, skb); -+ ath_debug_stat_rc(sc, ath_rc_get_rateindex(sc->cur_rate_table, -+ &tx_info->status.rates[final_ts_idx])); - } - - static void ath_rate_init(void *priv, struct ieee80211_supported_band *sband, -@@ -1365,7 +1385,7 @@ static void ath_rate_init(void *priv, st - { - struct ath_softc *sc = priv; - struct ath_rate_priv *ath_rc_priv = priv_sta; -- const struct ath_rate_table *rate_table = NULL; -+ const struct ath_rate_table *rate_table; - bool is_cw40, is_sgi40; - int i, j = 0; - -@@ -1397,11 +1417,9 @@ static void ath_rate_init(void *priv, st - (sc->sc_ah->opmode == NL80211_IFTYPE_MESH_POINT) || - (sc->sc_ah->opmode == NL80211_IFTYPE_ADHOC)) { - rate_table = ath_choose_rate_table(sc, sband->band, -- sta->ht_cap.ht_supported, -- is_cw40); -- } else if (sc->sc_ah->opmode == NL80211_IFTYPE_AP) { -- /* cur_rate_table would be set on init through config() */ -- rate_table = sc->cur_rate_table; -+ sta->ht_cap.ht_supported, is_cw40); -+ } else { -+ rate_table = hw_rate_table[sc->cur_rate_mode]; - } - - ath_rc_priv->ht_cap = ath_rc_build_ht_caps(sc, sta, is_cw40, is_sgi40); -@@ -1445,6 +1463,7 @@ static void ath_rate_update(void *priv, - ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_CONFIG, - "Operating HT Bandwidth changed to: %d\n", - sc->hw->conf.channel_type); -+ sc->cur_rate_table = hw_rate_table[sc->cur_rate_mode]; - } - } - } -@@ -1497,26 +1516,6 @@ static struct rate_control_ops ath_rate_ - .free_sta = ath_rate_free_sta, - }; - --void ath_rate_attach(struct ath_softc *sc) --{ -- sc->hw_rate_table[ATH9K_MODE_11A] = -- &ar5416_11a_ratetable; -- sc->hw_rate_table[ATH9K_MODE_11G] = -- &ar5416_11g_ratetable; -- sc->hw_rate_table[ATH9K_MODE_11NA_HT20] = -- &ar5416_11na_ratetable; -- sc->hw_rate_table[ATH9K_MODE_11NG_HT20] = -- &ar5416_11ng_ratetable; -- sc->hw_rate_table[ATH9K_MODE_11NA_HT40PLUS] = -- &ar5416_11na_ratetable; -- sc->hw_rate_table[ATH9K_MODE_11NA_HT40MINUS] = -- &ar5416_11na_ratetable; -- sc->hw_rate_table[ATH9K_MODE_11NG_HT40PLUS] = -- &ar5416_11ng_ratetable; -- sc->hw_rate_table[ATH9K_MODE_11NG_HT40MINUS] = -- &ar5416_11ng_ratetable; --} -- - int ath_rate_control_register(void) - { - return ieee80211_rate_control_register(&ath_rate_ops); ---- a/drivers/net/wireless/ath/ath9k/xmit.c -+++ b/drivers/net/wireless/ath/ath9k/xmit.c -@@ -70,6 +70,29 @@ static int ath_tx_num_badfrms(struct ath - static void ath_tx_rc_status(struct ath_buf *bf, struct ath_desc *ds, - int nbad, int txok, bool update_rc); - -+enum { -+ MCS_DEFAULT, -+ MCS_HT40, -+ MCS_HT40_SGI, -+}; -+ -+static int ath_max_4ms_framelen[3][16] = { -+ [MCS_DEFAULT] = { -+ 3216, 6434, 9650, 12868, 19304, 25740, 28956, 32180, -+ 6430, 12860, 19300, 25736, 38600, 51472, 57890, 64320, -+ }, -+ [MCS_HT40] = { -+ 6684, 13368, 20052, 26738, 40104, 53476, 60156, 66840, -+ 13360, 26720, 40080, 53440, 80160, 106880, 120240, 133600, -+ }, -+ [MCS_HT40_SGI] = { -+ /* TODO: Only MCS 7 and 15 updated, recalculate the rest */ -+ 6684, 13368, 20052, 26738, 40104, 53476, 60156, 74200, -+ 13360, 26720, 40080, 53440, 80160, 106880, 120240, 148400, -+ } -+}; -+ -+ - /*********************/ - /* Aggregation logic */ - /*********************/ -@@ -459,7 +482,6 @@ static void ath_tx_complete_aggr(struct - static u32 ath_lookup_rate(struct ath_softc *sc, struct ath_buf *bf, - struct ath_atx_tid *tid) - { -- const struct ath_rate_table *rate_table = sc->cur_rate_table; - struct sk_buff *skb; - struct ieee80211_tx_info *tx_info; - struct ieee80211_tx_rate *rates; -@@ -480,12 +502,20 @@ static u32 ath_lookup_rate(struct ath_so - - for (i = 0; i < 4; i++) { - if (rates[i].count) { -- if (!WLAN_RC_PHY_HT(rate_table->info[rates[i].idx].phy)) { -+ int modeidx; -+ if (!(rates[i].flags & IEEE80211_TX_RC_MCS)) { - legacy = 1; - break; - } - -- frmlen = rate_table->info[rates[i].idx].max_4ms_framelen; -+ if (rates[i].flags & IEEE80211_TX_RC_SHORT_GI) -+ modeidx = MCS_HT40_SGI; -+ else if (rates[i].flags & IEEE80211_TX_RC_40_MHZ_WIDTH) -+ modeidx = MCS_HT40; -+ else -+ modeidx = MCS_DEFAULT; -+ -+ frmlen = ath_max_4ms_framelen[modeidx][rates[i].idx]; - max_4ms_framelen = min(max_4ms_framelen, frmlen); - } - } -@@ -523,12 +553,11 @@ static u32 ath_lookup_rate(struct ath_so - static int ath_compute_num_delims(struct ath_softc *sc, struct ath_atx_tid *tid, - struct ath_buf *bf, u16 frmlen) - { -- const struct ath_rate_table *rt = sc->cur_rate_table; - struct sk_buff *skb = bf->bf_mpdu; - struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); - u32 nsymbits, nsymbols; - u16 minlen; -- u8 rc, flags, rix; -+ u8 flags, rix; - int width, half_gi, ndelim, mindelim; - - /* Select standard number of delimiters based on frame length alone */ -@@ -558,7 +587,6 @@ static int ath_compute_num_delims(struct - - rix = tx_info->control.rates[0].idx; - flags = tx_info->control.rates[0].flags; -- rc = rt->info[rix].ratecode; - width = (flags & IEEE80211_TX_RC_40_MHZ_WIDTH) ? 1 : 0; - half_gi = (flags & IEEE80211_TX_RC_SHORT_GI) ? 1 : 0; - -@@ -570,7 +598,7 @@ static int ath_compute_num_delims(struct - if (nsymbols == 0) - nsymbols = 1; - -- nsymbits = bits_per_symbol[HT_RC_2_MCS(rc)][width]; -+ nsymbits = bits_per_symbol[rix][width]; - minlen = (nsymbols * nsymbits) / BITS_PER_BYTE; - - if (frmlen < minlen) { -@@ -1425,22 +1453,14 @@ static int setup_tx_flags(struct ath_sof - static u32 ath_pkt_duration(struct ath_softc *sc, u8 rix, struct ath_buf *bf, - int width, int half_gi, bool shortPreamble) - { -- const struct ath_rate_table *rate_table = sc->cur_rate_table; - u32 nbits, nsymbits, duration, nsymbols; -- u8 rc; - int streams, pktlen; - - pktlen = bf_isaggr(bf) ? bf->bf_al : bf->bf_frmlen; -- rc = rate_table->info[rix].ratecode; -- -- /* for legacy rates, use old function to compute packet duration */ -- if (!IS_HT_RATE(rc)) -- return ath9k_hw_computetxtime(sc->sc_ah, rate_table, pktlen, -- rix, shortPreamble); - - /* find number of symbols: PLCP + data */ - nbits = (pktlen << 3) + OFDM_PLCP_BITS; -- nsymbits = bits_per_symbol[HT_RC_2_MCS(rc)][width]; -+ nsymbits = bits_per_symbol[rix][width]; - nsymbols = (nbits + nsymbits - 1) / nsymbits; - - if (!half_gi) -@@ -1449,7 +1469,7 @@ static u32 ath_pkt_duration(struct ath_s - duration = SYMBOL_TIME_HALFGI(nsymbols); - - /* addup duration for legacy/ht training and signal fields */ -- streams = HT_RC_2_STREAMS(rc); -+ streams = HT_RC_2_STREAMS(rix); - duration += L_STF + L_LTF + L_SIG + HT_SIG + HT_STF + HT_LTF(streams); - - return duration; -@@ -1458,11 +1478,11 @@ static u32 ath_pkt_duration(struct ath_s - static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf) - { - struct ath_common *common = ath9k_hw_common(sc->sc_ah); -- const struct ath_rate_table *rt = sc->cur_rate_table; - struct ath9k_11n_rate_series series[4]; - struct sk_buff *skb; - struct ieee80211_tx_info *tx_info; - struct ieee80211_tx_rate *rates; -+ const struct ieee80211_rate *rate; - struct ieee80211_hdr *hdr; - int i, flags = 0; - u8 rix = 0, ctsrate = 0; -@@ -1481,11 +1501,10 @@ static void ath_buf_set_rate(struct ath_ - * checking the BSS's global flag. - * But for the rate series, IEEE80211_TX_RC_USE_SHORT_PREAMBLE is used. - */ -+ rate = ieee80211_get_rts_cts_rate(sc->hw, tx_info); -+ ctsrate = rate->hw_value; - if (sc->sc_flags & SC_OP_PREAMBLE_SHORT) -- ctsrate = rt->info[tx_info->control.rts_cts_rate_idx].ratecode | -- rt->info[tx_info->control.rts_cts_rate_idx].short_preamble; -- else -- ctsrate = rt->info[tx_info->control.rts_cts_rate_idx].ratecode; -+ ctsrate |= rate->hw_value_short; - - /* - * ATH9K_TXDESC_RTSENA and ATH9K_TXDESC_CTSENA are mutually exclusive. -@@ -1508,6 +1527,9 @@ static void ath_buf_set_rate(struct ath_ - flags &= ~(ATH9K_TXDESC_RTSENA); - - for (i = 0; i < 4; i++) { -+ bool is_40, is_sgi, is_sp; -+ int phy; -+ - if (!rates[i].count || (rates[i].idx < 0)) - continue; - -@@ -1515,12 +1537,6 @@ static void ath_buf_set_rate(struct ath_ - series[i].Tries = rates[i].count; - series[i].ChSel = common->tx_chainmask; - -- if (rates[i].flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE) -- series[i].Rate = rt->info[rix].ratecode | -- rt->info[rix].short_preamble; -- else -- series[i].Rate = rt->info[rix].ratecode; -- - if (rates[i].flags & IEEE80211_TX_RC_USE_RTS_CTS) - series[i].RateFlags |= ATH9K_RATESERIES_RTS_CTS; - if (rates[i].flags & IEEE80211_TX_RC_40_MHZ_WIDTH) -@@ -1528,10 +1544,36 @@ static void ath_buf_set_rate(struct ath_ - if (rates[i].flags & IEEE80211_TX_RC_SHORT_GI) - series[i].RateFlags |= ATH9K_RATESERIES_HALFGI; - -- series[i].PktDuration = ath_pkt_duration(sc, rix, bf, -- (rates[i].flags & IEEE80211_TX_RC_40_MHZ_WIDTH) != 0, -- (rates[i].flags & IEEE80211_TX_RC_SHORT_GI), -- (rates[i].flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE)); -+ is_sgi = !!(rates[i].flags & IEEE80211_TX_RC_SHORT_GI); -+ is_40 = !!(rates[i].flags & IEEE80211_TX_RC_40_MHZ_WIDTH); -+ is_sp = !!(rates[i].flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE); -+ -+ if (rates[i].flags & IEEE80211_TX_RC_MCS) { -+ /* MCS rates */ -+ series[i].Rate = rix | 0x80; -+ series[i].PktDuration = ath_pkt_duration(sc, rix, bf, -+ is_40, is_sgi, is_sp); -+ continue; -+ } -+ -+ /* legcay rates */ -+ if ((tx_info->band == IEEE80211_BAND_2GHZ) && -+ !(rate->flags & IEEE80211_RATE_ERP_G)) -+ phy = WLAN_RC_PHY_CCK; -+ else -+ phy = WLAN_RC_PHY_OFDM; -+ -+ rate = &sc->sbands[tx_info->band].bitrates[rates[i].idx]; -+ series[i].Rate = rate->hw_value; -+ if (rate->hw_value_short) { -+ if (rates[i].flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE) -+ series[i].Rate |= rate->hw_value_short; -+ } else { -+ is_sp = false; -+ } -+ -+ series[i].PktDuration = ath9k_hw_computetxtime(sc->sc_ah, -+ phy, rate->bitrate * 100, bf->bf_frmlen, rix, is_sp); - } - - /* set dur_update_en for l-sig computation except for PS-Poll frames */ -@@ -1920,8 +1962,10 @@ static void ath_tx_rc_status(struct ath_ - } - } - -- for (i = tx_rateindex + 1; i < hw->max_rates; i++) -+ for (i = tx_rateindex + 1; i < hw->max_rates; i++) { - tx_info->status.rates[i].count = 0; -+ tx_info->status.rates[i].idx = -1; -+ } - - tx_info->status.rates[tx_rateindex].count = bf->bf_retries + 1; - } ---- a/drivers/net/wireless/ath/ath9k/ath9k.h -+++ b/drivers/net/wireless/ath/ath9k/ath9k.h -@@ -21,7 +21,6 @@ - #include - #include - --#include "rc.h" - #include "debug.h" - #include "common.h" - -@@ -423,6 +422,7 @@ struct ath_led { - #define SC_OP_BT_PRIORITY_DETECTED BIT(21) - - struct ath_wiphy; -+struct ath_rate_table; - - struct ath_softc { - struct ieee80211_hw *hw; -@@ -467,9 +467,8 @@ struct ath_softc { - struct ath_rx rx; - struct ath_tx tx; - struct ath_beacon beacon; -- struct ieee80211_rate rates[IEEE80211_NUM_BANDS][ATH_RATE_MAX]; -- const struct ath_rate_table *hw_rate_table[ATH9K_MODE_MAX]; - const struct ath_rate_table *cur_rate_table; -+ enum wireless_mode cur_rate_mode; - struct ieee80211_supported_band sbands[IEEE80211_NUM_BANDS]; - - struct ath_led radio_led; ---- a/drivers/net/wireless/ath/ath9k/main.c -+++ b/drivers/net/wireless/ath/ath9k/main.c -@@ -105,37 +105,55 @@ static struct ieee80211_channel ath9k_5g - CHAN5G(5825, 37), /* Channel 165 */ - }; - -+/* Atheros hardware rate code addition for short premble */ -+#define SHPCHECK(__hw_rate, __flags) \ -+ ((__flags & IEEE80211_RATE_SHORT_PREAMBLE) ? (__hw_rate | 0x04 ) : 0) -+ -+#define RATE(_bitrate, _hw_rate, _flags) { \ -+ .bitrate = (_bitrate), \ -+ .flags = (_flags), \ -+ .hw_value = (_hw_rate), \ -+ .hw_value_short = (SHPCHECK(_hw_rate, _flags)) \ -+} -+ -+static struct ieee80211_rate ath9k_legacy_rates[] = { -+ RATE(10, 0x1b, 0), -+ RATE(20, 0x1a, IEEE80211_RATE_SHORT_PREAMBLE), -+ RATE(55, 0x19, IEEE80211_RATE_SHORT_PREAMBLE), -+ RATE(110, 0x18, IEEE80211_RATE_SHORT_PREAMBLE), -+ RATE(60, 0x0b, 0), -+ RATE(90, 0x0f, 0), -+ RATE(120, 0x0a, 0), -+ RATE(180, 0x0e, 0), -+ RATE(240, 0x09, 0), -+ RATE(360, 0x0d, 0), -+ RATE(480, 0x08, 0), -+ RATE(540, 0x0c, 0), -+}; -+ - static void ath_cache_conf_rate(struct ath_softc *sc, - struct ieee80211_conf *conf) - { - switch (conf->channel->band) { - case IEEE80211_BAND_2GHZ: - if (conf_is_ht20(conf)) -- sc->cur_rate_table = -- sc->hw_rate_table[ATH9K_MODE_11NG_HT20]; -+ sc->cur_rate_mode = ATH9K_MODE_11NG_HT20; - else if (conf_is_ht40_minus(conf)) -- sc->cur_rate_table = -- sc->hw_rate_table[ATH9K_MODE_11NG_HT40MINUS]; -+ sc->cur_rate_mode = ATH9K_MODE_11NG_HT40MINUS; - else if (conf_is_ht40_plus(conf)) -- sc->cur_rate_table = -- sc->hw_rate_table[ATH9K_MODE_11NG_HT40PLUS]; -+ sc->cur_rate_mode = ATH9K_MODE_11NG_HT40PLUS; - else -- sc->cur_rate_table = -- sc->hw_rate_table[ATH9K_MODE_11G]; -+ sc->cur_rate_mode = ATH9K_MODE_11G; - break; - case IEEE80211_BAND_5GHZ: - if (conf_is_ht20(conf)) -- sc->cur_rate_table = -- sc->hw_rate_table[ATH9K_MODE_11NA_HT20]; -+ sc->cur_rate_mode = ATH9K_MODE_11NA_HT20; - else if (conf_is_ht40_minus(conf)) -- sc->cur_rate_table = -- sc->hw_rate_table[ATH9K_MODE_11NA_HT40MINUS]; -+ sc->cur_rate_mode = ATH9K_MODE_11NA_HT40MINUS; - else if (conf_is_ht40_plus(conf)) -- sc->cur_rate_table = -- sc->hw_rate_table[ATH9K_MODE_11NA_HT40PLUS]; -+ sc->cur_rate_mode = ATH9K_MODE_11NA_HT40PLUS; - else -- sc->cur_rate_table = -- sc->hw_rate_table[ATH9K_MODE_11A]; -+ sc->cur_rate_mode = ATH9K_MODE_11A; - break; - default: - BUG_ON(1); -@@ -191,51 +209,6 @@ static u8 parse_mpdudensity(u8 mpdudensi - } - } - --static void ath_setup_rates(struct ath_softc *sc, enum ieee80211_band band) --{ -- const struct ath_rate_table *rate_table = NULL; -- struct ieee80211_supported_band *sband; -- struct ieee80211_rate *rate; -- int i, maxrates; -- -- switch (band) { -- case IEEE80211_BAND_2GHZ: -- rate_table = sc->hw_rate_table[ATH9K_MODE_11G]; -- break; -- case IEEE80211_BAND_5GHZ: -- rate_table = sc->hw_rate_table[ATH9K_MODE_11A]; -- break; -- default: -- break; -- } -- -- if (rate_table == NULL) -- return; -- -- sband = &sc->sbands[band]; -- rate = sc->rates[band]; -- -- if (rate_table->rate_cnt > ATH_RATE_MAX) -- maxrates = ATH_RATE_MAX; -- else -- maxrates = rate_table->rate_cnt; -- -- for (i = 0; i < maxrates; i++) { -- rate[i].bitrate = rate_table->info[i].ratekbps / 100; -- rate[i].hw_value = rate_table->info[i].ratecode; -- if (rate_table->info[i].short_preamble) { -- rate[i].hw_value_short = rate_table->info[i].ratecode | -- rate_table->info[i].short_preamble; -- rate[i].flags = IEEE80211_RATE_SHORT_PREAMBLE; -- } -- sband->n_bitrates++; -- -- ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_CONFIG, -- "Rate: %2dMbps, ratecode: %2d\n", -- rate[i].bitrate / 10, rate[i].hw_value); -- } --} -- - static struct ath9k_channel *ath_get_curchannel(struct ath_softc *sc, - struct ieee80211_hw *hw) - { -@@ -1713,12 +1686,6 @@ static int ath_init_softc(u16 devid, str - /* default to MONITOR mode */ - sc->sc_ah->opmode = NL80211_IFTYPE_MONITOR; - -- /* Setup rate tables */ -- -- ath_rate_attach(sc); -- ath_setup_rates(sc, IEEE80211_BAND_2GHZ); -- ath_setup_rates(sc, IEEE80211_BAND_5GHZ); -- - /* - * Allocate hardware transmit queues: one queue for - * beacon frames and one data queue for each QoS -@@ -1839,19 +1806,22 @@ static int ath_init_softc(u16 devid, str - /* setup channels and rates */ - - sc->sbands[IEEE80211_BAND_2GHZ].channels = ath9k_2ghz_chantable; -- sc->sbands[IEEE80211_BAND_2GHZ].bitrates = -- sc->rates[IEEE80211_BAND_2GHZ]; - sc->sbands[IEEE80211_BAND_2GHZ].band = IEEE80211_BAND_2GHZ; - sc->sbands[IEEE80211_BAND_2GHZ].n_channels = - ARRAY_SIZE(ath9k_2ghz_chantable); -+ sc->sbands[IEEE80211_BAND_2GHZ].bitrates = ath9k_legacy_rates; -+ sc->sbands[IEEE80211_BAND_2GHZ].n_bitrates = -+ ARRAY_SIZE(ath9k_legacy_rates); - - if (test_bit(ATH9K_MODE_11A, sc->sc_ah->caps.wireless_modes)) { - sc->sbands[IEEE80211_BAND_5GHZ].channels = ath9k_5ghz_chantable; -- sc->sbands[IEEE80211_BAND_5GHZ].bitrates = -- sc->rates[IEEE80211_BAND_5GHZ]; - sc->sbands[IEEE80211_BAND_5GHZ].band = IEEE80211_BAND_5GHZ; - sc->sbands[IEEE80211_BAND_5GHZ].n_channels = - ARRAY_SIZE(ath9k_5ghz_chantable); -+ sc->sbands[IEEE80211_BAND_5GHZ].bitrates = -+ ath9k_legacy_rates + 4; -+ sc->sbands[IEEE80211_BAND_5GHZ].n_bitrates = -+ ARRAY_SIZE(ath9k_legacy_rates) - 4; - } - - switch (ah->btcoex_hw.scheme) { ---- a/drivers/net/wireless/ath/ath9k/rc.h -+++ b/drivers/net/wireless/ath/ath9k/rc.h -@@ -104,6 +104,7 @@ enum { - */ - struct ath_rate_table { - int rate_cnt; -+ int mcs_start; - struct { - int valid; - int valid_single_stream; -@@ -179,8 +180,6 @@ enum ath9k_internal_frame_type { - ATH9K_INT_UNPAUSE - }; - --void ath_rate_attach(struct ath_softc *sc); --u8 ath_rate_findrateix(struct ath_softc *sc, u8 dot11_rate); - int ath_rate_control_register(void); - void ath_rate_control_unregister(void); - ---- a/drivers/net/wireless/ath/ath9k/beacon.c -+++ b/drivers/net/wireless/ath/ath9k/beacon.c -@@ -65,9 +65,9 @@ static void ath_beacon_setup(struct ath_ - struct ath_common *common = ath9k_hw_common(ah); - struct ath_desc *ds; - struct ath9k_11n_rate_series series[4]; -- const struct ath_rate_table *rt; - int flags, antenna, ctsrate = 0, ctsduration = 0; -- u8 rate; -+ struct ieee80211_supported_band *sband; -+ u8 rate = 0; - - ds = bf->bf_desc; - flags = ATH9K_TXDESC_NOACK; -@@ -91,10 +91,10 @@ static void ath_beacon_setup(struct ath_ - - ds->ds_data = bf->bf_buf_addr; - -- rt = sc->cur_rate_table; -- rate = rt->info[0].ratecode; -+ sband = &sc->sbands[common->hw->conf.channel->band]; -+ rate = sband->bitrates[0].hw_value; - if (sc->sc_flags & SC_OP_PREAMBLE_SHORT) -- rate |= rt->info[0].short_preamble; -+ rate |= sband->bitrates[0].hw_value_short; - - ath9k_hw_set11n_txdesc(ah, ds, skb->len + FCS_LEN, - ATH9K_PKT_TYPE_BEACON, ---- a/drivers/net/wireless/ath/ath9k/debug.h -+++ b/drivers/net/wireless/ath/ath9k/debug.h -@@ -18,6 +18,7 @@ - #define DEBUG_H - - #include "hw.h" -+#include "rc.h" - - struct ath_txq; - struct ath_buf; -@@ -138,7 +139,7 @@ void ath9k_exit_debug(struct ath_hw *ah) - int ath9k_debug_create_root(void); - void ath9k_debug_remove_root(void); - void ath_debug_stat_interrupt(struct ath_softc *sc, enum ath9k_int status); --void ath_debug_stat_rc(struct ath_softc *sc, struct sk_buff *skb); -+void ath_debug_stat_rc(struct ath_softc *sc, int final_rate); - void ath_debug_stat_tx(struct ath_softc *sc, struct ath_txq *txq, - struct ath_buf *bf); - void ath_debug_stat_retries(struct ath_softc *sc, int rix, -@@ -170,7 +171,7 @@ static inline void ath_debug_stat_interr - } - - static inline void ath_debug_stat_rc(struct ath_softc *sc, -- struct sk_buff *skb) -+ int final_rate) - { - } - ---- a/drivers/net/wireless/ath/ath9k/debug.c -+++ b/drivers/net/wireless/ath/ath9k/debug.c -@@ -255,21 +255,11 @@ static const struct file_operations fops - .owner = THIS_MODULE - }; - --void ath_debug_stat_rc(struct ath_softc *sc, struct sk_buff *skb) -+void ath_debug_stat_rc(struct ath_softc *sc, int final_rate) - { -- struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); -- struct ieee80211_tx_rate *rates = tx_info->status.rates; -- int final_ts_idx = 0, idx, i; - struct ath_rc_stats *stats; - -- for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) { -- if (!rates[i].count) -- break; -- -- final_ts_idx = i; -- } -- idx = rates[final_ts_idx].idx; -- stats = &sc->debug.stats.rcstats[idx]; -+ stats = &sc->debug.stats.rcstats[final_rate]; - stats->success++; - } - ---- a/drivers/net/wireless/ath/ath9k/hw.c -+++ b/drivers/net/wireless/ath/ath9k/hw.c -@@ -149,22 +149,19 @@ bool ath9k_get_channel_edges(struct ath_ - } - - u16 ath9k_hw_computetxtime(struct ath_hw *ah, -- const struct ath_rate_table *rates, -+ u8 phy, int kbps, - u32 frameLen, u16 rateix, - bool shortPreamble) - { - u32 bitsPerSymbol, numBits, numSymbols, phyTime, txTime; -- u32 kbps; -- -- kbps = rates->info[rateix].ratekbps; - - if (kbps == 0) - return 0; - -- switch (rates->info[rateix].phy) { -+ switch (phy) { - case WLAN_RC_PHY_CCK: - phyTime = CCK_PREAMBLE_BITS + CCK_PLCP_BITS; -- if (shortPreamble && rates->info[rateix].short_preamble) -+ if (shortPreamble) - phyTime >>= 1; - numBits = frameLen << 3; - txTime = CCK_SIFS_TIME + phyTime + ((numBits * 1000) / kbps); -@@ -195,8 +192,7 @@ u16 ath9k_hw_computetxtime(struct ath_hw - break; - default: - ath_print(ath9k_hw_common(ah), ATH_DBG_FATAL, -- "Unknown phy %u (rate ix %u)\n", -- rates->info[rateix].phy, rateix); -+ "Unknown phy %u (rate ix %u)\n", phy, rateix); - txTime = 0; - break; - } ---- a/drivers/net/wireless/ath/ath9k/hw.h -+++ b/drivers/net/wireless/ath/ath9k/hw.h -@@ -647,7 +647,7 @@ bool ath9k_hw_wait(struct ath_hw *ah, u3 - u32 ath9k_hw_reverse_bits(u32 val, u32 n); - bool ath9k_get_channel_edges(struct ath_hw *ah, u16 flags, u16 *low, u16 *high); - u16 ath9k_hw_computetxtime(struct ath_hw *ah, -- const struct ath_rate_table *rates, -+ u8 phy, int kbps, - u32 frameLen, u16 rateix, bool shortPreamble); - void ath9k_hw_get_channel_centers(struct ath_hw *ah, - struct ath9k_channel *chan, ---- a/drivers/net/wireless/ath/ath9k/mac.h -+++ b/drivers/net/wireless/ath/ath9k/mac.h -@@ -616,7 +616,6 @@ enum ath9k_cipher { - - struct ath_hw; - struct ath9k_channel; --struct ath_rate_table; - - u32 ath9k_hw_gettxbuf(struct ath_hw *ah, u32 q); - void ath9k_hw_puttxbuf(struct ath_hw *ah, u32 q, u32 txdp); diff --git a/package/mac80211/patches/501-ath9k_rc_table_cleanup.patch b/package/mac80211/patches/501-ath9k_rc_table_cleanup.patch deleted file mode 100644 index 30e0f9f0e..000000000 --- a/package/mac80211/patches/501-ath9k_rc_table_cleanup.patch +++ /dev/null @@ -1,477 +0,0 @@ ---- a/drivers/net/wireless/ath/ath9k/rc.h -+++ b/drivers/net/wireless/ath/ath9k/rc.h -@@ -112,14 +112,12 @@ struct ath_rate_table { - u32 ratekbps; - u32 user_ratekbps; - u8 ratecode; -- u8 short_preamble; - u8 dot11rate; - u8 ctrl_rate; - u8 base_index; - u8 cw40index; - u8 sgi_index; - u8 ht_index; -- u32 max_4ms_framelen; - } info[RATE_TABLE_SIZE]; - u32 probe_interval; - u8 initial_ratemax; ---- a/drivers/net/wireless/ath/ath9k/rc.c -+++ b/drivers/net/wireless/ath/ath9k/rc.c -@@ -22,131 +22,89 @@ static const struct ath_rate_table ar541 - 8, /* MCS start */ - { - { VALID, VALID, WLAN_RC_PHY_OFDM, 6000, /* 6 Mb */ -- 5400, 0, 0x00, 12, -- 0, 0, 0, 0, 0, 0 }, -+ 5400, 0, 12, 0, 0, 0, 0, 0 }, - { VALID, VALID, WLAN_RC_PHY_OFDM, 9000, /* 9 Mb */ -- 7800, 1, 0x00, 18, -- 0, 1, 1, 1, 1, 0 }, -+ 7800, 1, 18, 0, 1, 1, 1, 1 }, - { VALID, VALID, WLAN_RC_PHY_OFDM, 12000, /* 12 Mb */ -- 10000, 2, 0x00, 24, -- 2, 2, 2, 2, 2, 0 }, -+ 10000, 2, 24, 2, 2, 2, 2, 2 }, - { VALID, VALID, WLAN_RC_PHY_OFDM, 18000, /* 18 Mb */ -- 13900, 3, 0x00, 36, -- 2, 3, 3, 3, 3, 0 }, -+ 13900, 3, 36, 2, 3, 3, 3, 3 }, - { VALID, VALID, WLAN_RC_PHY_OFDM, 24000, /* 24 Mb */ -- 17300, 4, 0x00, 48, -- 4, 4, 4, 4, 4, 0 }, -+ 17300, 4, 48, 4, 4, 4, 4, 4 }, - { VALID, VALID, WLAN_RC_PHY_OFDM, 36000, /* 36 Mb */ -- 23000, 5, 0x00, 72, -- 4, 5, 5, 5, 5, 0 }, -+ 23000, 5, 72, 4, 5, 5, 5, 5 }, - { VALID, VALID, WLAN_RC_PHY_OFDM, 48000, /* 48 Mb */ -- 27400, 6, 0x00, 96, -- 4, 6, 6, 6, 6, 0 }, -+ 27400, 6, 96, 4, 6, 6, 6, 6 }, - { VALID, VALID, WLAN_RC_PHY_OFDM, 54000, /* 54 Mb */ -- 29300, 7, 0x00, 108, -- 4, 7, 7, 7, 7, 0 }, -+ 29300, 7, 108, 4, 7, 7, 7, 7 }, - { VALID_2040, VALID_2040, WLAN_RC_PHY_HT_20_SS, 6500, /* 6.5 Mb */ -- 6400, 0, 0x00, 0, -- 0, 8, 24, 8, 24, 3216 }, -+ 6400, 0, 0, 0, 8, 24, 8, 24 }, - { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 13000, /* 13 Mb */ -- 12700, 1, 0x00, 1, -- 2, 9, 25, 9, 25, 6434 }, -+ 12700, 1, 1, 2, 9, 25, 9, 25 }, - { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 19500, /* 19.5 Mb */ -- 18800, 2, 0x00, 2, -- 2, 10, 26, 10, 26, 9650 }, -+ 18800, 2, 2, 2, 10, 26, 10, 26 }, - { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 26000, /* 26 Mb */ -- 25000, 3, 0x00, 3, -- 4, 11, 27, 11, 27, 12868 }, -+ 25000, 3, 3, 4, 11, 27, 11, 27 }, - { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 39000, /* 39 Mb */ -- 36700, 4, 0x00, 4, -- 4, 12, 28, 12, 28, 19304 }, -+ 36700, 4, 4, 4, 12, 28, 12, 28 }, - { INVALID, VALID_20, WLAN_RC_PHY_HT_20_SS, 52000, /* 52 Mb */ -- 48100, 5, 0x00, 5, -- 4, 13, 29, 13, 29, 25740 }, -+ 48100, 5, 5, 4, 13, 29, 13, 29 }, - { INVALID, VALID_20, WLAN_RC_PHY_HT_20_SS, 58500, /* 58.5 Mb */ -- 53500, 6, 0x00, 6, -- 4, 14, 30, 14, 30, 28956 }, -+ 53500, 6, 6, 4, 14, 30, 14, 30 }, - { INVALID, VALID_20, WLAN_RC_PHY_HT_20_SS, 65000, /* 65 Mb */ -- 59000, 7, 0x00, 7, -- 4, 15, 31, 15, 32, 32180 }, -+ 59000, 7, 7, 4, 15, 31, 15, 32 }, - { INVALID, INVALID, WLAN_RC_PHY_HT_20_DS, 13000, /* 13 Mb */ -- 12700, 8, 0x00, -- 8, 3, 16, 33, 16, 33, 6430 }, -+ 12700, 8, 8, 3, 16, 33, 16, 33 }, - { INVALID, INVALID, WLAN_RC_PHY_HT_20_DS, 26000, /* 26 Mb */ -- 24800, 9, 0x00, 9, -- 2, 17, 34, 17, 34, 12860 }, -+ 24800, 9, 9, 2, 17, 34, 17, 34 }, - { INVALID, INVALID, WLAN_RC_PHY_HT_20_DS, 39000, /* 39 Mb */ -- 36600, 10, 0x00, 10, -- 2, 18, 35, 18, 35, 19300 }, -+ 36600, 10, 10, 2, 18, 35, 18, 35 }, - { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 52000, /* 52 Mb */ -- 48100, 11, 0x00, 11, -- 4, 19, 36, 19, 36, 25736 }, -+ 48100, 11, 11, 4, 19, 36, 19, 36 }, - { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 78000, /* 78 Mb */ -- 69500, 12, 0x00, 12, -- 4, 20, 37, 20, 37, 38600 }, -+ 69500, 12, 12, 4, 20, 37, 20, 37 }, - { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 104000, /* 104 Mb */ -- 89500, 13, 0x00, 13, -- 4, 21, 38, 21, 38, 51472 }, -+ 89500, 13, 13, 4, 21, 38, 21, 38 }, - { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 117000, /* 117 Mb */ -- 98900, 14, 0x00, 14, -- 4, 22, 39, 22, 39, 57890 }, -+ 98900, 14, 14, 4, 22, 39, 22, 39 }, - { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 130000, /* 130 Mb */ -- 108300, 15, 0x00, 15, -- 4, 23, 40, 23, 41, 64320 }, -+ 108300, 15, 15, 4, 23, 40, 23, 41 }, - { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 13500, /* 13.5 Mb */ -- 13200, 0, 0x00, 0, -- 0, 8, 24, 24, 24, 6684 }, -+ 13200, 0, 0, 0, 8, 24, 24, 24 }, - { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 27500, /* 27.0 Mb */ -- 25900, 1, 0x00, 1, -- 2, 9, 25, 25, 25, 13368 }, -+ 25900, 1, 1, 2, 9, 25, 25, 25 }, - { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 40500, /* 40.5 Mb */ -- 38600, 2, 0x00, 2, -- 2, 10, 26, 26, 26, 20052 }, -+ 38600, 2, 2, 2, 10, 26, 26, 26 }, - { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 54000, /* 54 Mb */ -- 49800, 3, 0x00, 3, -- 4, 11, 27, 27, 27, 26738 }, -+ 49800, 3, 3, 4, 11, 27, 27, 27 }, - { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 81500, /* 81 Mb */ -- 72200, 4, 0x00, 4, -- 4, 12, 28, 28, 28, 40104 }, -+ 72200, 4, 4, 4, 12, 28, 28, 28 }, - { INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS, 108000, /* 108 Mb */ -- 92900, 5, 0x00, 5, -- 4, 13, 29, 29, 29, 53476 }, -+ 92900, 5, 5, 4, 13, 29, 29, 29 }, - { INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS, 121500, /* 121.5 Mb */ -- 102700, 6, 0x00, 6, -- 4, 14, 30, 30, 30, 60156 }, -+ 102700, 6, 6, 4, 14, 30, 30, 30 }, - { INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS, 135000, /* 135 Mb */ -- 112000, 7, 0x00, 7, -- 4, 15, 31, 32, 32, 66840 }, -+ 112000, 7, 7, 4, 15, 31, 32, 32 }, - { INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS_HGI, 150000, /* 150 Mb */ -- 122000, 7, 0x00, 7, -- 4, 15, 31, 32, 32, 74200 }, -+ 122000, 7, 7, 4, 15, 31, 32, 32 }, - { INVALID, INVALID, WLAN_RC_PHY_HT_40_DS, 27000, /* 27 Mb */ -- 25800, 8, 0x00, 8, -- 0, 16, 33, 33, 33, 13360 }, -+ 25800, 8, 8, 0, 16, 33, 33, 33 }, - { INVALID, INVALID, WLAN_RC_PHY_HT_40_DS, 54000, /* 54 Mb */ -- 49800, 9, 0x00, 9, -- 2, 17, 34, 34, 34, 26720 }, -+ 49800, 9, 9, 2, 17, 34, 34, 34 }, - { INVALID, INVALID, WLAN_RC_PHY_HT_40_DS, 81000, /* 81 Mb */ -- 71900, 10, 0x00, 10, -- 2, 18, 35, 35, 35, 40080 }, -+ 71900, 10, 10, 2, 18, 35, 35, 35 }, - { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 108000, /* 108 Mb */ -- 92500, 11, 0x00, 11, -- 4, 19, 36, 36, 36, 53440 }, -+ 92500, 11, 11, 4, 19, 36, 36, 36 }, - { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 162000, /* 162 Mb */ -- 130300, 12, 0x00, 12, -- 4, 20, 37, 37, 37, 80160 }, -+ 130300, 12, 12, 4, 20, 37, 37, 37 }, - { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 216000, /* 216 Mb */ -- 162800, 13, 0x00, 13, -- 4, 21, 38, 38, 38, 106880 }, -+ 162800, 13, 13, 4, 21, 38, 38, 38 }, - { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 243000, /* 243 Mb */ -- 178200, 14, 0x00, 14, -- 4, 22, 39, 39, 39, 120240 }, -+ 178200, 14, 14, 4, 22, 39, 39, 39 }, - { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 270000, /* 270 Mb */ -- 192100, 15, 0x00, 15, -- 4, 23, 40, 41, 41, 133600 }, -+ 192100, 15, 15, 4, 23, 40, 41, 41 }, - { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS_HGI, 300000, /* 300 Mb */ -- 207000, 15, 0x00, 15, -- 4, 23, 40, 41, 41, 148400 }, -+ 207000, 15, 15, 4, 23, 40, 41, 41 }, - }, - 50, /* probe interval */ - WLAN_RC_HT_FLAG, /* Phy rates allowed initially */ -@@ -160,144 +118,98 @@ static const struct ath_rate_table ar541 - 12, /* MCS start */ - { - { VALID_ALL, VALID_ALL, WLAN_RC_PHY_CCK, 1000, /* 1 Mb */ -- 900, 0, 0x00, 2, -- 0, 0, 0, 0, 0, 0 }, -+ 900, 0, 2, 0, 0, 0, 0, 0 }, - { VALID_ALL, VALID_ALL, WLAN_RC_PHY_CCK, 2000, /* 2 Mb */ -- 1900, 1, 0x04, 4, -- 1, 1, 1, 1, 1, 0 }, -+ 1900, 1, 4, 1, 1, 1, 1, 1 }, - { VALID_ALL, VALID_ALL, WLAN_RC_PHY_CCK, 5500, /* 5.5 Mb */ -- 4900, 2, 0x04, 11, -- 2, 2, 2, 2, 2, 0 }, -+ 4900, 2, 11, 2, 2, 2, 2, 2 }, - { VALID_ALL, VALID_ALL, WLAN_RC_PHY_CCK, 11000, /* 11 Mb */ -- 8100, 3, 0x04, 22, -- 3, 3, 3, 3, 3, 0 }, -+ 8100, 3, 22, 3, 3, 3, 3, 3 }, - { INVALID, INVALID, WLAN_RC_PHY_OFDM, 6000, /* 6 Mb */ -- 5400, 4, 0x00, 12, -- 4, 4, 4, 4, 4, 0 }, -+ 5400, 4, 12, 4, 4, 4, 4, 4 }, - { INVALID, INVALID, WLAN_RC_PHY_OFDM, 9000, /* 9 Mb */ -- 7800, 5, 0x00, 18, -- 4, 5, 5, 5, 5, 0 }, -+ 7800, 5, 18, 4, 5, 5, 5, 5 }, - { VALID, VALID, WLAN_RC_PHY_OFDM, 12000, /* 12 Mb */ -- 10100, 6, 0x00, 24, -- 6, 6, 6, 6, 6, 0 }, -+ 10100, 6, 24, 6, 6, 6, 6, 6 }, - { VALID, VALID, WLAN_RC_PHY_OFDM, 18000, /* 18 Mb */ -- 14100, 7, 0x00, 36, -- 6, 7, 7, 7, 7, 0 }, -+ 14100, 7, 36, 6, 7, 7, 7, 7 }, - { VALID, VALID, WLAN_RC_PHY_OFDM, 24000, /* 24 Mb */ -- 17700, 8, 0x00, 48, -- 8, 8, 8, 8, 8, 0 }, -+ 17700, 8, 48, 8, 8, 8, 8, 8 }, - { VALID, VALID, WLAN_RC_PHY_OFDM, 36000, /* 36 Mb */ -- 23700, 9, 0x00, 72, -- 8, 9, 9, 9, 9, 0 }, -+ 23700, 9, 72, 8, 9, 9, 9, 9 }, - { VALID, VALID, WLAN_RC_PHY_OFDM, 48000, /* 48 Mb */ -- 27400, 10, 0x00, 96, -- 8, 10, 10, 10, 10, 0 }, -+ 27400, 10, 96, 8, 10, 10, 10, 10 }, - { VALID, VALID, WLAN_RC_PHY_OFDM, 54000, /* 54 Mb */ -- 30900, 11, 0x00, 108, -- 8, 11, 11, 11, 11, 0 }, -+ 30900, 11, 108, 8, 11, 11, 11, 11 }, - { INVALID, INVALID, WLAN_RC_PHY_HT_20_SS, 6500, /* 6.5 Mb */ -- 6400, 0, 0x00, 0, -- 4, 12, 28, 12, 28, 3216 }, -+ 6400, 0, 0, 4, 12, 28, 12, 28 }, - { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 13000, /* 13 Mb */ -- 12700, 1, 0x00, 1, -- 6, 13, 29, 13, 29, 6434 }, -+ 12700, 1, 1, 6, 13, 29, 13, 29 }, - { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 19500, /* 19.5 Mb */ -- 18800, 2, 0x00, 2, -- 6, 14, 30, 14, 30, 9650 }, -+ 18800, 2, 2, 6, 14, 30, 14, 30 }, - { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 26000, /* 26 Mb */ -- 25000, 3, 0x00, 3, -- 8, 15, 31, 15, 31, 12868 }, -+ 25000, 3, 3, 8, 15, 31, 15, 31 }, - { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 39000, /* 39 Mb */ -- 36700, 4, 0x00, 4, -- 8, 16, 32, 16, 32, 19304 }, -+ 36700, 4, 4, 8, 16, 32, 16, 32 }, - { INVALID, VALID_20, WLAN_RC_PHY_HT_20_SS, 52000, /* 52 Mb */ -- 48100, 5, 0x00, 5, -- 8, 17, 33, 17, 33, 25740 }, -+ 48100, 5, 5, 8, 17, 33, 17, 33 }, - { INVALID, VALID_20, WLAN_RC_PHY_HT_20_SS, 58500, /* 58.5 Mb */ -- 53500, 6, 0x00, 6, -- 8, 18, 34, 18, 34, 28956 }, -+ 53500, 6, 6, 8, 18, 34, 18, 34 }, - { INVALID, VALID_20, WLAN_RC_PHY_HT_20_SS, 65000, /* 65 Mb */ -- 59000, 7, 0x00, 7, -- 8, 19, 35, 19, 36, 32180 }, -+ 59000, 7, 7, 8, 19, 35, 19, 36 }, - { INVALID, INVALID, WLAN_RC_PHY_HT_20_DS, 13000, /* 13 Mb */ -- 12700, 8, 0x00, 8, -- 4, 20, 37, 20, 37, 6430 }, -+ 12700, 8, 8, 4, 20, 37, 20, 37 }, - { INVALID, INVALID, WLAN_RC_PHY_HT_20_DS, 26000, /* 26 Mb */ -- 24800, 9, 0x00, 9, -- 6, 21, 38, 21, 38, 12860 }, -+ 24800, 9, 9, 6, 21, 38, 21, 38 }, - { INVALID, INVALID, WLAN_RC_PHY_HT_20_DS, 39000, /* 39 Mb */ -- 36600, 10, 0x00, 10, -- 6, 22, 39, 22, 39, 19300 }, -+ 36600, 10, 10, 6, 22, 39, 22, 39 }, - { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 52000, /* 52 Mb */ -- 48100, 11, 0x00, 11, -- 8, 23, 40, 23, 40, 25736 }, -+ 48100, 11, 11, 8, 23, 40, 23, 40 }, - { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 78000, /* 78 Mb */ -- 69500, 12, 0x00, 12, -- 8, 24, 41, 24, 41, 38600 }, -+ 69500, 12, 12, 8, 24, 41, 24, 41 }, - { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 104000, /* 104 Mb */ -- 89500, 13, 0x00, 13, -- 8, 25, 42, 25, 42, 51472 }, -+ 89500, 13, 13, 8, 25, 42, 25, 42 }, - { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 117000, /* 117 Mb */ -- 98900, 14, 0x00, 14, -- 8, 26, 43, 26, 44, 57890 }, -+ 98900, 14, 14, 8, 26, 43, 26, 44 }, - { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 130000, /* 130 Mb */ -- 108300, 15, 0x00, 15, -- 8, 27, 44, 27, 45, 64320 }, -+ 108300, 15, 15, 8, 27, 44, 27, 45 }, - { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 13500, /* 13.5 Mb */ -- 13200, 0, 0x00, 0, -- 8, 12, 28, 28, 28, 6684 }, -+ 13200, 0, 0, 8, 12, 28, 28, 28 }, - { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 27500, /* 27.0 Mb */ -- 25900, 1, 0x00, 1, -- 8, 13, 29, 29, 29, 13368 }, -+ 25900, 1, 1, 8, 13, 29, 29, 29 }, - { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 40500, /* 40.5 Mb */ -- 38600, 2, 0x00, 2, -- 8, 14, 30, 30, 30, 20052 }, -+ 38600, 2, 2, 8, 14, 30, 30, 30 }, - { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 54000, /* 54 Mb */ -- 49800, 3, 0x00, 3, -- 8, 15, 31, 31, 31, 26738 }, -+ 49800, 3, 3, 8, 15, 31, 31, 31 }, - { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 81500, /* 81 Mb */ -- 72200, 4, 0x00, 4, -- 8, 16, 32, 32, 32, 40104 }, -+ 72200, 4, 4, 8, 16, 32, 32, 32 }, - { INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS, 108000, /* 108 Mb */ -- 92900, 5, 0x00, 5, -- 8, 17, 33, 33, 33, 53476 }, -+ 92900, 5, 5, 8, 17, 33, 33, 33 }, - { INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS, 121500, /* 121.5 Mb */ -- 102700, 6, 0x00, 6, -- 8, 18, 34, 34, 34, 60156 }, -+ 102700, 6, 6, 8, 18, 34, 34, 34 }, - { INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS, 135000, /* 135 Mb */ -- 112000, 7, 0x00, 7, -- 8, 19, 35, 36, 36, 66840 }, -+ 112000, 7, 7, 8, 19, 35, 36, 36 }, - { INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS_HGI, 150000, /* 150 Mb */ -- 122000, 7, 0x00, 7, -- 8, 19, 35, 36, 36, 74200 }, -+ 122000, 7, 7, 8, 19, 35, 36, 36 }, - { INVALID, INVALID, WLAN_RC_PHY_HT_40_DS, 27000, /* 27 Mb */ -- 25800, 8, 0x00, 8, -- 8, 20, 37, 37, 37, 13360 }, -+ 25800, 8, 8, 8, 20, 37, 37, 37 }, - { INVALID, INVALID, WLAN_RC_PHY_HT_40_DS, 54000, /* 54 Mb */ -- 49800, 9, 0x00, 9, -- 8, 21, 38, 38, 38, 26720 }, -+ 49800, 9, 9, 8, 21, 38, 38, 38 }, - { INVALID, INVALID, WLAN_RC_PHY_HT_40_DS, 81000, /* 81 Mb */ -- 71900, 10, 0x00, 10, -- 8, 22, 39, 39, 39, 40080 }, -+ 71900, 10, 10, 8, 22, 39, 39, 39 }, - { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 108000, /* 108 Mb */ -- 92500, 11, 0x00, 11, -- 8, 23, 40, 40, 40, 53440 }, -+ 92500, 11, 11, 8, 23, 40, 40, 40 }, - { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 162000, /* 162 Mb */ -- 130300, 12, 0x00, 12, -- 8, 24, 41, 41, 41, 80160 }, -+ 130300, 12, 12, 8, 24, 41, 41, 41 }, - { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 216000, /* 216 Mb */ -- 162800, 13, 0x00, 13, -- 8, 25, 42, 42, 42, 106880 }, -+ 162800, 13, 13, 8, 25, 42, 42, 42 }, - { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 243000, /* 243 Mb */ -- 178200, 14, 0x00, 14, -- 8, 26, 43, 43, 43, 120240 }, -+ 178200, 14, 14, 8, 26, 43, 43, 43 }, - { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 270000, /* 270 Mb */ -- 192100, 15, 0x00, 15, -- 8, 27, 44, 45, 45, 133600 }, -+ 192100, 15, 15, 8, 27, 44, 45, 45 }, - { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS_HGI, 300000, /* 300 Mb */ -- 207000, 15, 0x00, 15, -- 8, 27, 44, 45, 45, 148400 }, -- }, -+ 207000, 15, 15, 8, 27, 44, 45, 45 }, -+ }, - 50, /* probe interval */ - WLAN_RC_HT_FLAG, /* Phy rates allowed initially */ - }; -@@ -307,29 +219,21 @@ static const struct ath_rate_table ar541 - 0, - { - { VALID, VALID, WLAN_RC_PHY_OFDM, 6000, /* 6 Mb */ -- 5400, 0, 0x00, 12, -- 0, 0, 0 }, -+ 5400, 0, 12, 0, 0, 0 }, - { VALID, VALID, WLAN_RC_PHY_OFDM, 9000, /* 9 Mb */ -- 7800, 1, 0x00, 18, -- 0, 1, 0 }, -+ 7800, 1, 18, 0, 1, 0 }, - { VALID, VALID, WLAN_RC_PHY_OFDM, 12000, /* 12 Mb */ -- 10000, 2, 0x00, 24, -- 2, 2, 0 }, -+ 10000, 2, 24, 2, 2, 0 }, - { VALID, VALID, WLAN_RC_PHY_OFDM, 18000, /* 18 Mb */ -- 13900, 3, 0x00, 36, -- 2, 3, 0 }, -+ 13900, 3, 36, 2, 3, 0 }, - { VALID, VALID, WLAN_RC_PHY_OFDM, 24000, /* 24 Mb */ -- 17300, 4, 0x00, 48, -- 4, 4, 0 }, -+ 17300, 4, 48, 4, 4, 0 }, - { VALID, VALID, WLAN_RC_PHY_OFDM, 36000, /* 36 Mb */ -- 23000, 5, 0x00, 72, -- 4, 5, 0 }, -+ 23000, 5, 72, 4, 5, 0 }, - { VALID, VALID, WLAN_RC_PHY_OFDM, 48000, /* 48 Mb */ -- 27400, 6, 0x00, 96, -- 4, 6, 0 }, -+ 27400, 6, 96, 4, 6, 0 }, - { VALID, VALID, WLAN_RC_PHY_OFDM, 54000, /* 54 Mb */ -- 29300, 7, 0x00, 108, -- 4, 7, 0 }, -+ 29300, 7, 108, 4, 7, 0 }, - }, - 50, /* probe interval */ - 0, /* Phy rates allowed initially */ -@@ -340,41 +244,29 @@ static const struct ath_rate_table ar541 - 0, - { - { VALID, VALID, WLAN_RC_PHY_CCK, 1000, /* 1 Mb */ -- 900, 0, 0x00, 2, -- 0, 0, 0 }, -+ 900, 0, 2, 0, 0, 0 }, - { VALID, VALID, WLAN_RC_PHY_CCK, 2000, /* 2 Mb */ -- 1900, 1, 0x04, 4, -- 1, 1, 0 }, -+ 1900, 1, 4, 1, 1, 0 }, - { VALID, VALID, WLAN_RC_PHY_CCK, 5500, /* 5.5 Mb */ -- 4900, 2, 0x04, 11, -- 2, 2, 0 }, -+ 4900, 2, 11, 2, 2, 0 }, - { VALID, VALID, WLAN_RC_PHY_CCK, 11000, /* 11 Mb */ -- 8100, 3, 0x04, 22, -- 3, 3, 0 }, -+ 8100, 3, 22, 3, 3, 0 }, - { INVALID, INVALID, WLAN_RC_PHY_OFDM, 6000, /* 6 Mb */ -- 5400, 4, 0x00, 12, -- 4, 4, 0 }, -+ 5400, 4, 12, 4, 4, 0 }, - { INVALID, INVALID, WLAN_RC_PHY_OFDM, 9000, /* 9 Mb */ -- 7800, 5, 0x00, 18, -- 4, 5, 0 }, -+ 7800, 5, 18, 4, 5, 0 }, - { VALID, VALID, WLAN_RC_PHY_OFDM, 12000, /* 12 Mb */ -- 10000, 6, 0x00, 24, -- 6, 6, 0 }, -+ 10000, 6, 24, 6, 6, 0 }, - { VALID, VALID, WLAN_RC_PHY_OFDM, 18000, /* 18 Mb */ -- 13900, 7, 0x00, 36, -- 6, 7, 0 }, -+ 13900, 7, 36, 6, 7, 0 }, - { VALID, VALID, WLAN_RC_PHY_OFDM, 24000, /* 24 Mb */ -- 17300, 8, 0x00, 48, -- 8, 8, 0 }, -+ 17300, 8, 48, 8, 8, 0 }, - { VALID, VALID, WLAN_RC_PHY_OFDM, 36000, /* 36 Mb */ -- 23000, 9, 0x00, 72, -- 8, 9, 0 }, -+ 23000, 9, 72, 8, 9, 0 }, - { VALID, VALID, WLAN_RC_PHY_OFDM, 48000, /* 48 Mb */ -- 27400, 10, 0x00, 96, -- 8, 10, 0 }, -+ 27400, 10, 96, 8, 10, 0 }, - { VALID, VALID, WLAN_RC_PHY_OFDM, 54000, /* 54 Mb */ -- 29300, 11, 0x00, 108, -- 8, 11, 0 }, -+ 29300, 11, 108, 8, 11, 0 }, - }, - 50, /* probe interval */ - 0, /* Phy rates allowed initially */ diff --git a/package/mac80211/patches/530-ath9k_debugfs_chainmask.patch b/package/mac80211/patches/510-ath9k_debugfs_chainmask.patch similarity index 96% rename from package/mac80211/patches/530-ath9k_debugfs_chainmask.patch rename to package/mac80211/patches/510-ath9k_debugfs_chainmask.patch index a26b4dc8a..157098a69 100644 --- a/package/mac80211/patches/530-ath9k_debugfs_chainmask.patch +++ b/package/mac80211/patches/510-ath9k_debugfs_chainmask.patch @@ -91,7 +91,7 @@ static ssize_t read_file_dma(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { -@@ -574,6 +658,16 @@ int ath9k_init_debug(struct ath_hw *ah) +@@ -600,6 +684,16 @@ int ath9k_init_debug(struct ath_hw *ah) goto err; #endif @@ -108,7 +108,7 @@ sc->debug.debugfs_dma = debugfs_create_file("dma", S_IRUSR, sc->debug.debugfs_phy, sc, &fops_dma); if (!sc->debug.debugfs_dma) -@@ -617,6 +711,8 @@ void ath9k_exit_debug(struct ath_hw *ah) +@@ -643,6 +737,8 @@ void ath9k_exit_debug(struct ath_hw *ah) struct ath_common *common = ath9k_hw_common(ah); struct ath_softc *sc = (struct ath_softc *) common->priv; diff --git a/package/mac80211/patches/510-ath_use_gfp_dma.patch b/package/mac80211/patches/510-ath_use_gfp_dma.patch deleted file mode 100644 index 9390a2faa..000000000 --- a/package/mac80211/patches/510-ath_use_gfp_dma.patch +++ /dev/null @@ -1,17 +0,0 @@ ---- a/drivers/net/wireless/ath/main.c -+++ b/drivers/net/wireless/ath/main.c -@@ -31,6 +31,14 @@ struct sk_buff *ath_rxbuf_alloc(struct a - u32 off; - - /* -+ * Enable GFP_DMA in order to avoid using DMA bounce buffers -+ * on IXP4xx devices with more than 64M RAM -+ */ -+#ifdef CONFIG_ARCH_IXP4XX -+ gfp_mask |= GFP_DMA; -+#endif -+ -+ /* - * Cache-line-align. This is important (for the - * 5210 at least) as not doing so causes bogus data - * in rx'd frames. diff --git a/package/mac80211/patches/520-ath9k_debugfs_config.patch b/package/mac80211/patches/520-ath9k_debugfs_config.patch deleted file mode 100644 index 021338307..000000000 --- a/package/mac80211/patches/520-ath9k_debugfs_config.patch +++ /dev/null @@ -1,81 +0,0 @@ ---- a/drivers/net/wireless/ath/ath9k/Makefile -+++ b/drivers/net/wireless/ath/ath9k/Makefile -@@ -7,7 +7,7 @@ ath9k-y += beacon.o \ - - ath9k-$(CONFIG_PCI) += pci.o - ath9k-$(CONFIG_ATHEROS_AR71XX) += ahb.o --ath9k-$(CONFIG_ATH9K_DEBUG) += debug.o -+ath9k-$(CONFIG_ATH9K_DEBUGFS) += debug.o - - obj-$(CONFIG_ATH9K) += ath9k.o - ---- a/drivers/net/wireless/ath/ath9k/ath9k.h -+++ b/drivers/net/wireless/ath/ath9k/ath9k.h -@@ -483,7 +483,7 @@ struct ath_softc { - - int beacon_interval; - --#ifdef CONFIG_ATH9K_DEBUG -+#ifdef CONFIG_ATH9K_DEBUGFS - struct ath9k_debug debug; - #endif - struct ath_beacon_config cur_beacon_conf; ---- a/drivers/net/wireless/ath/ath9k/debug.c -+++ b/drivers/net/wireless/ath/ath9k/debug.c -@@ -31,6 +31,8 @@ static int ath9k_debugfs_open(struct ino - return 0; - } - -+#ifdef CONFIG_ATH_DEBUG -+ - static ssize_t read_file_debug(struct file *file, char __user *user_buf, - size_t count, loff_t *ppos) - { -@@ -71,6 +73,8 @@ static const struct file_operations fops - .owner = THIS_MODULE - }; - -+#endif -+ - static ssize_t read_file_dma(struct file *file, char __user *user_buf, - size_t count, loff_t *ppos) - { -@@ -563,10 +567,12 @@ int ath9k_init_debug(struct ath_hw *ah) - if (!sc->debug.debugfs_phy) - goto err; - -+#ifdef CONFIG_ATH_DEBUG - sc->debug.debugfs_debug = debugfs_create_file("debug", - S_IRUSR | S_IWUSR, sc->debug.debugfs_phy, sc, &fops_debug); - if (!sc->debug.debugfs_debug) - goto err; -+#endif - - sc->debug.debugfs_dma = debugfs_create_file("dma", S_IRUSR, - sc->debug.debugfs_phy, sc, &fops_dma); ---- a/drivers/net/wireless/ath/ath9k/debug.h -+++ b/drivers/net/wireless/ath/ath9k/debug.h -@@ -23,13 +23,13 @@ - struct ath_txq; - struct ath_buf; - --#ifdef CONFIG_ATH9K_DEBUG -+#ifdef CONFIG_ATH9K_DEBUGFS - #define TX_STAT_INC(q, c) sc->debug.stats.txstats[q].c++ - #else - #define TX_STAT_INC(q, c) do { } while (0) - #endif - --#ifdef CONFIG_ATH9K_DEBUG -+#ifdef CONFIG_ATH9K_DEBUGFS - - /** - * struct ath_interrupt_stats - Contains statistics about interrupts -@@ -186,6 +186,6 @@ static inline void ath_debug_stat_retrie - { - } - --#endif /* CONFIG_ATH9K_DEBUG */ -+#endif /* CONFIG_ATH9K_DEBUGFS */ - - #endif /* DEBUG_H */ diff --git a/package/mac80211/patches/540-ath9k_debugfs_regaccess.patch b/package/mac80211/patches/520-ath9k_debugfs_regaccess.patch similarity index 94% rename from package/mac80211/patches/540-ath9k_debugfs_regaccess.patch rename to package/mac80211/patches/520-ath9k_debugfs_regaccess.patch index b927b5513..b9fa0221d 100644 --- a/package/mac80211/patches/540-ath9k_debugfs_regaccess.patch +++ b/package/mac80211/patches/520-ath9k_debugfs_regaccess.patch @@ -1,6 +1,6 @@ --- a/drivers/net/wireless/ath/ath9k/debug.c +++ b/drivers/net/wireless/ath/ath9k/debug.c -@@ -638,6 +638,86 @@ static const struct file_operations fops +@@ -664,6 +664,86 @@ static const struct file_operations fops .owner = THIS_MODULE }; @@ -87,7 +87,7 @@ int ath9k_init_debug(struct ath_hw *ah) { struct ath_common *common = ath9k_hw_common(ah); -@@ -700,6 +780,17 @@ int ath9k_init_debug(struct ath_hw *ah) +@@ -726,6 +806,17 @@ int ath9k_init_debug(struct ath_hw *ah) if (!sc->debug.debugfs_xmit) goto err; @@ -105,7 +105,7 @@ return 0; err: ath9k_exit_debug(ah); -@@ -713,6 +804,8 @@ void ath9k_exit_debug(struct ath_hw *ah) +@@ -739,6 +830,8 @@ void ath9k_exit_debug(struct ath_hw *ah) debugfs_remove(sc->debug.debugfs_tx_chainmask); debugfs_remove(sc->debug.debugfs_rx_chainmask); diff --git a/package/mac80211/patches/530-mac80211_queue_fix.patch b/package/mac80211/patches/530-mac80211_queue_fix.patch new file mode 100644 index 000000000..d84167392 --- /dev/null +++ b/package/mac80211/patches/530-mac80211_queue_fix.patch @@ -0,0 +1,69 @@ +--- a/net/mac80211/iface.c ++++ b/net/mac80211/iface.c +@@ -329,7 +329,7 @@ static int ieee80211_open(struct net_dev + if (sdata->vif.type == NL80211_IFTYPE_STATION) + ieee80211_queue_work(&local->hw, &sdata->u.mgd.work); + +- netif_start_queue(dev); ++ netif_tx_start_all_queues(dev); + + return 0; + err_del_interface: +@@ -357,7 +357,7 @@ static int ieee80211_stop(struct net_dev + /* + * Stop TX on this interface first. + */ +- netif_stop_queue(dev); ++ netif_tx_stop_all_queues(dev); + + /* + * Purge work for this interface. +--- a/net/mac80211/mlme.c ++++ b/net/mac80211/mlme.c +@@ -723,7 +723,7 @@ static void ieee80211_set_associated(str + ieee80211_recalc_smps(local, sdata); + mutex_unlock(&local->iflist_mtx); + +- netif_start_queue(sdata->dev); ++ netif_tx_start_all_queues(sdata->dev); + netif_carrier_on(sdata->dev); + } + +@@ -759,7 +759,7 @@ static void ieee80211_set_disassoc(struc + * time -- we don't want the scan code to enable queues. + */ + +- netif_stop_queue(sdata->dev); ++ netif_tx_stop_all_queues(sdata->dev); + netif_carrier_off(sdata->dev); + + rcu_read_lock(); +--- a/net/mac80211/offchannel.c ++++ b/net/mac80211/offchannel.c +@@ -113,7 +113,7 @@ void ieee80211_offchannel_stop_beaconing + */ + if (sdata->vif.type != NL80211_IFTYPE_STATION && + sdata->vif.type != NL80211_IFTYPE_MONITOR) +- netif_stop_queue(sdata->dev); ++ netif_tx_stop_all_queues(sdata->dev); + } + mutex_unlock(&local->iflist_mtx); + } +@@ -131,7 +131,7 @@ void ieee80211_offchannel_stop_station(s + continue; + + if (sdata->vif.type == NL80211_IFTYPE_STATION) { +- netif_stop_queue(sdata->dev); ++ netif_tx_stop_all_queues(sdata->dev); + if (sdata->u.mgd.associated) + ieee80211_offchannel_ps_enable(sdata); + } +@@ -153,7 +153,7 @@ void ieee80211_offchannel_return(struct + if (sdata->vif.type == NL80211_IFTYPE_STATION) { + if (sdata->u.mgd.associated) + ieee80211_offchannel_ps_disable(sdata); +- netif_wake_queue(sdata->dev); ++ netif_tx_wake_all_queues(sdata->dev); + } + + /* re-enable beaconing */ diff --git a/package/mac80211/patches/540-mac80211_work_fix.patch b/package/mac80211/patches/540-mac80211_work_fix.patch new file mode 100644 index 000000000..339a52d51 --- /dev/null +++ b/package/mac80211/patches/540-mac80211_work_fix.patch @@ -0,0 +1,30 @@ +--- a/net/mac80211/scan.c ++++ b/net/mac80211/scan.c +@@ -284,6 +284,7 @@ void ieee80211_scan_completed(struct iee + ieee80211_mlme_notify_scan_completed(local); + ieee80211_ibss_notify_scan_completed(local); + ieee80211_mesh_notify_scan_completed(local); ++ ieee80211_queue_work(&local->hw, &local->work_work); + } + EXPORT_SYMBOL(ieee80211_scan_completed); + +--- a/net/mac80211/work.c ++++ b/net/mac80211/work.c +@@ -818,6 +818,7 @@ static void ieee80211_work_work(struct w + wk->chan == local->tmp_channel && + wk->chan_type == local->tmp_channel_type) { + wk->started = true; ++ wk->timeout = jiffies; + } + + if (!wk->started && !local->tmp_channel) { +@@ -935,6 +936,9 @@ void ieee80211_add_work(struct ieee80211 + if (WARN_ON(!wk->done)) + return; + ++ if (WARN_ON(!ieee80211_sdata_running(wk->sdata))) ++ return; ++ + wk->started = false; + + local = wk->sdata->local; diff --git a/package/mac80211/patches/550-ath9k-enable-2GHz-band-only-if-the-device-supports.patch b/package/mac80211/patches/550-ath9k-enable-2GHz-band-only-if-the-device-supports.patch deleted file mode 100644 index ed07822e7..000000000 --- a/package/mac80211/patches/550-ath9k-enable-2GHz-band-only-if-the-device-supports.patch +++ /dev/null @@ -1,108 +0,0 @@ ---- a/drivers/net/wireless/ath/ath9k/hw.c -+++ b/drivers/net/wireless/ath/ath9k/hw.c -@@ -979,7 +979,10 @@ int ath9k_hw_init(struct ath_hw *ah) - return r; - - ath9k_hw_init_mode_gain_regs(ah); -- ath9k_hw_fill_cap_info(ah); -+ r = ath9k_hw_fill_cap_info(ah); -+ if (r) -+ return r; -+ - ath9k_hw_init_11a_eeprom_fix(ah); - - r = ath9k_hw_init_macaddr(ah); -@@ -3115,7 +3118,7 @@ EXPORT_SYMBOL(ath9k_hw_set_sta_beacon_ti - /* HW Capabilities */ - /*******************/ - --void ath9k_hw_fill_cap_info(struct ath_hw *ah) -+int ath9k_hw_fill_cap_info(struct ath_hw *ah) - { - struct ath9k_hw_capabilities *pCap = &ah->caps; - struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah); -@@ -3146,6 +3149,12 @@ void ath9k_hw_fill_cap_info(struct ath_h - } - - eeval = ah->eep_ops->get_eeprom(ah, EEP_OP_MODE); -+ if ((eeval & (AR5416_OPFLAGS_11G | AR5416_OPFLAGS_11A)) == 0) { -+ ath_print(common, ATH_DBG_FATAL, -+ "no band has been marked as supported in EEPROM.\n"); -+ return -EINVAL; -+ } -+ - bitmap_zero(pCap->wireless_modes, ATH9K_MODE_MAX); - - if (eeval & AR5416_OPFLAGS_11A) { -@@ -3305,6 +3314,8 @@ void ath9k_hw_fill_cap_info(struct ath_h - } else { - btcoex_hw->scheme = ATH_BTCOEX_CFG_NONE; - } -+ -+ return 0; - } - - bool ath9k_hw_getcapability(struct ath_hw *ah, enum ath9k_capability_type type, ---- a/drivers/net/wireless/ath/ath9k/hw.h -+++ b/drivers/net/wireless/ath/ath9k/hw.h -@@ -619,7 +619,7 @@ void ath9k_hw_detach(struct ath_hw *ah); - int ath9k_hw_init(struct ath_hw *ah); - int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, - bool bChannelChange); --void ath9k_hw_fill_cap_info(struct ath_hw *ah); -+int ath9k_hw_fill_cap_info(struct ath_hw *ah); - bool ath9k_hw_getcapability(struct ath_hw *ah, enum ath9k_capability_type type, - u32 capability, u32 *result); - bool ath9k_hw_setcapability(struct ath_hw *ah, enum ath9k_capability_type type, ---- a/drivers/net/wireless/ath/ath9k/main.c -+++ b/drivers/net/wireless/ath/ath9k/main.c -@@ -1805,13 +1805,15 @@ static int ath_init_softc(u16 devid, str - - /* setup channels and rates */ - -- sc->sbands[IEEE80211_BAND_2GHZ].channels = ath9k_2ghz_chantable; -- sc->sbands[IEEE80211_BAND_2GHZ].band = IEEE80211_BAND_2GHZ; -- sc->sbands[IEEE80211_BAND_2GHZ].n_channels = -- ARRAY_SIZE(ath9k_2ghz_chantable); -- sc->sbands[IEEE80211_BAND_2GHZ].bitrates = ath9k_legacy_rates; -- sc->sbands[IEEE80211_BAND_2GHZ].n_bitrates = -- ARRAY_SIZE(ath9k_legacy_rates); -+ if (test_bit(ATH9K_MODE_11G, sc->sc_ah->caps.wireless_modes)) { -+ sc->sbands[IEEE80211_BAND_2GHZ].channels = ath9k_2ghz_chantable; -+ sc->sbands[IEEE80211_BAND_2GHZ].band = IEEE80211_BAND_2GHZ; -+ sc->sbands[IEEE80211_BAND_2GHZ].n_channels = -+ ARRAY_SIZE(ath9k_2ghz_chantable); -+ sc->sbands[IEEE80211_BAND_2GHZ].bitrates = ath9k_legacy_rates; -+ sc->sbands[IEEE80211_BAND_2GHZ].n_bitrates = -+ ARRAY_SIZE(ath9k_legacy_rates); -+ } - - if (test_bit(ATH9K_MODE_11A, sc->sc_ah->caps.wireless_modes)) { - sc->sbands[IEEE80211_BAND_5GHZ].channels = ath9k_5ghz_chantable; -@@ -1886,8 +1888,9 @@ void ath_set_hw_capab(struct ath_softc * - - hw->rate_control_algorithm = "ath9k_rate_control"; - -- hw->wiphy->bands[IEEE80211_BAND_2GHZ] = -- &sc->sbands[IEEE80211_BAND_2GHZ]; -+ if (test_bit(ATH9K_MODE_11G, sc->sc_ah->caps.wireless_modes)) -+ hw->wiphy->bands[IEEE80211_BAND_2GHZ] = -+ &sc->sbands[IEEE80211_BAND_2GHZ]; - if (test_bit(ATH9K_MODE_11A, sc->sc_ah->caps.wireless_modes)) - hw->wiphy->bands[IEEE80211_BAND_5GHZ] = - &sc->sbands[IEEE80211_BAND_5GHZ]; -@@ -1926,9 +1929,12 @@ int ath_init_device(u16 devid, struct at - reg = &common->regulatory; - - if (ah->caps.hw_caps & ATH9K_HW_CAP_HT) { -- setup_ht_cap(sc, &sc->sbands[IEEE80211_BAND_2GHZ].ht_cap); -+ if (test_bit(ATH9K_MODE_11G, ah->caps.wireless_modes)) -+ setup_ht_cap(sc, -+ &sc->sbands[IEEE80211_BAND_2GHZ].ht_cap); - if (test_bit(ATH9K_MODE_11A, ah->caps.wireless_modes)) -- setup_ht_cap(sc, &sc->sbands[IEEE80211_BAND_5GHZ].ht_cap); -+ setup_ht_cap(sc, -+ &sc->sbands[IEEE80211_BAND_5GHZ].ht_cap); - } - - /* initialize tx/rx engine */ diff --git a/package/mac80211/patches/550-mac80211_action_frame_fix.patch b/package/mac80211/patches/550-mac80211_action_frame_fix.patch new file mode 100644 index 000000000..9283af64a --- /dev/null +++ b/package/mac80211/patches/550-mac80211_action_frame_fix.patch @@ -0,0 +1,26 @@ +--- a/net/mac80211/mlme.c ++++ b/net/mac80211/mlme.c +@@ -1451,7 +1451,9 @@ static void ieee80211_sta_rx_queued_mgmt + rma = ieee80211_rx_mgmt_disassoc(sdata, mgmt, skb->len); + break; + case IEEE80211_STYPE_ACTION: +- /* XXX: differentiate, can only happen for CSA now! */ ++ if (mgmt->u.action.category != WLAN_CATEGORY_SPECTRUM_MGMT) ++ break; ++ + ieee80211_sta_process_chanswitch(sdata, + &mgmt->u.action.u.chan_switch.sw_elem, + (void *)ifmgd->associated->priv); +--- a/net/mac80211/rx.c ++++ b/net/mac80211/rx.c +@@ -1934,6 +1934,10 @@ ieee80211_rx_h_action(struct ieee80211_r + } + break; + default: ++ /* do not process rejected action frames */ ++ if (mgmt->u.action.category & 0x80) ++ return RX_DROP_MONITOR; ++ + return RX_CONTINUE; + } + diff --git a/package/mac80211/patches/560-wds_assoc_dummyframe.patch b/package/mac80211/patches/560-wds_assoc_dummyframe.patch new file mode 100644 index 000000000..9efb3ac6d --- /dev/null +++ b/package/mac80211/patches/560-wds_assoc_dummyframe.patch @@ -0,0 +1,76 @@ +--- a/net/mac80211/mlme.c ++++ b/net/mac80211/mlme.c +@@ -312,6 +312,38 @@ void ieee80211_send_nullfunc(struct ieee + ieee80211_tx_skb(sdata, skb); + } + ++static void ieee80211_send_4addr_nullfunc(struct ieee80211_local *local, ++ struct ieee80211_sub_if_data *sdata) ++{ ++ struct sk_buff *skb; ++ struct ieee80211_hdr *nullfunc; ++ __le16 fc; ++ ++ if (WARN_ON(sdata->vif.type != NL80211_IFTYPE_STATION)) ++ return; ++ ++ skb = dev_alloc_skb(local->hw.extra_tx_headroom + 30); ++ if (!skb) { ++ printk(KERN_DEBUG "%s: failed to allocate buffer for 4addr " ++ "nullfunc frame\n", sdata->name); ++ return; ++ } ++ skb_reserve(skb, local->hw.extra_tx_headroom); ++ ++ nullfunc = (struct ieee80211_hdr *) skb_put(skb, 30); ++ memset(nullfunc, 0, 30); ++ fc = cpu_to_le16(IEEE80211_FTYPE_DATA | IEEE80211_STYPE_NULLFUNC | ++ IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS); ++ nullfunc->frame_control = fc; ++ memcpy(nullfunc->addr1, sdata->u.mgd.bssid, ETH_ALEN); ++ memcpy(nullfunc->addr2, sdata->vif.addr, ETH_ALEN); ++ memcpy(nullfunc->addr3, sdata->u.mgd.bssid, ETH_ALEN); ++ memcpy(nullfunc->addr4, sdata->vif.addr, ETH_ALEN); ++ ++ IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; ++ ieee80211_tx_skb(sdata, skb); ++} ++ + /* spectrum management related things */ + static void ieee80211_chswitch_work(struct work_struct *work) + { +@@ -1120,6 +1152,13 @@ static bool ieee80211_assoc_success(stru + ieee80211_set_associated(sdata, cbss, changed); + + /* ++ * If we're using 4-addr mode, let the AP know that we're ++ * doing so, so that it can create the STA VLAN on its side ++ */ ++ if (ifmgd->use_4addr) ++ ieee80211_send_4addr_nullfunc(local, sdata); ++ ++ /* + * Start timer to probe the connection to the AP now. + * Also start the timer that will detect beacon loss. + */ +--- a/net/mac80211/rx.c ++++ b/net/mac80211/rx.c +@@ -1111,6 +1111,18 @@ ieee80211_rx_h_sta_process(struct ieee80 + if (ieee80211_is_nullfunc(hdr->frame_control) || + ieee80211_is_qos_nullfunc(hdr->frame_control)) { + I802_DEBUG_INC(rx->local->rx_handlers_drop_nullfunc); ++ ++ /* ++ * If we receive a 4-addr nullfunc frame from a STA ++ * that was not moved to a 4-addr STA vlan yet, drop ++ * the frame to the monitor interface, to make sure ++ * that hostapd sees it ++ */ ++ if (ieee80211_has_a4(hdr->frame_control) && ++ (rx->sdata->vif.type == NL80211_IFTYPE_AP || ++ (rx->sdata->vif.type == NL80211_IFTYPE_AP_VLAN && ++ !rx->sdata->u.vlan.sta))) ++ return RX_DROP_MONITOR; + /* + * Update counter and free packet here to avoid + * counting this as a dropped packed. diff --git a/package/mac80211/patches/570-vlan_sta_lookup.patch b/package/mac80211/patches/570-vlan_sta_lookup.patch new file mode 100644 index 000000000..ad15ca974 --- /dev/null +++ b/package/mac80211/patches/570-vlan_sta_lookup.patch @@ -0,0 +1,98 @@ +--- a/net/mac80211/sta_info.c ++++ b/net/mac80211/sta_info.c +@@ -119,6 +119,27 @@ struct sta_info *sta_info_get(struct iee + return sta; + } + ++/* ++ * Get sta info either from the specified interface ++ * or from one of its vlans ++ */ ++struct sta_info *sta_info_get_bss(struct ieee80211_sub_if_data *sdata, ++ const u8 *addr) ++{ ++ struct ieee80211_local *local = sdata->local; ++ struct sta_info *sta; ++ ++ sta = rcu_dereference(local->sta_hash[STA_HASH(addr)]); ++ while (sta) { ++ if ((sta->sdata == sdata || ++ sta->sdata->bss == sdata->bss) && ++ memcmp(sta->sta.addr, addr, ETH_ALEN) == 0) ++ break; ++ sta = rcu_dereference(sta->hnext); ++ } ++ return sta; ++} ++ + struct sta_info *sta_info_get_by_idx(struct ieee80211_sub_if_data *sdata, + int idx) + { +--- a/net/mac80211/sta_info.h ++++ b/net/mac80211/sta_info.h +@@ -408,6 +408,9 @@ static inline u32 get_sta_flags(struct s + struct sta_info *sta_info_get(struct ieee80211_sub_if_data *sdata, + const u8 *addr); + ++struct sta_info *sta_info_get_bss(struct ieee80211_sub_if_data *sdata, ++ const u8 *addr); ++ + static inline + void for_each_sta_info_type_check(struct ieee80211_local *local, + const u8 *addr, +--- a/net/mac80211/cfg.c ++++ b/net/mac80211/cfg.c +@@ -148,7 +148,7 @@ static int ieee80211_add_key(struct wiph + rcu_read_lock(); + + if (mac_addr) { +- sta = sta_info_get(sdata, mac_addr); ++ sta = sta_info_get_bss(sdata, mac_addr); + if (!sta) { + ieee80211_key_free(key); + err = -ENOENT; +@@ -179,7 +179,7 @@ static int ieee80211_del_key(struct wiph + if (mac_addr) { + ret = -ENOENT; + +- sta = sta_info_get(sdata, mac_addr); ++ sta = sta_info_get_bss(sdata, mac_addr); + if (!sta) + goto out_unlock; + +@@ -226,7 +226,7 @@ static int ieee80211_get_key(struct wiph + rcu_read_lock(); + + if (mac_addr) { +- sta = sta_info_get(sdata, mac_addr); ++ sta = sta_info_get_bss(sdata, mac_addr); + if (!sta) + goto out; + +@@ -419,7 +419,7 @@ static int ieee80211_get_station(struct + + rcu_read_lock(); + +- sta = sta_info_get(sdata, mac); ++ sta = sta_info_get_bss(sdata, mac); + if (sta) { + ret = 0; + sta_set_sinfo(sta, sinfo); +@@ -775,7 +775,7 @@ static int ieee80211_del_station(struct + if (mac) { + rcu_read_lock(); + +- sta = sta_info_get(sdata, mac); ++ sta = sta_info_get_bss(sdata, mac); + if (!sta) { + rcu_read_unlock(); + return -ENOENT; +@@ -803,7 +803,7 @@ static int ieee80211_change_station(stru + + rcu_read_lock(); + +- sta = sta_info_get(sdata, mac); ++ sta = sta_info_get_bss(sdata, mac); + if (!sta) { + rcu_read_unlock(); + return -ENOENT; diff --git a/package/mac80211/patches/580-4addr_vlan_check.patch b/package/mac80211/patches/580-4addr_vlan_check.patch new file mode 100644 index 000000000..7079957ee --- /dev/null +++ b/package/mac80211/patches/580-4addr_vlan_check.patch @@ -0,0 +1,15 @@ +--- a/net/mac80211/tx.c ++++ b/net/mac80211/tx.c +@@ -1051,8 +1051,11 @@ ieee80211_tx_prepare(struct ieee80211_su + + hdr = (struct ieee80211_hdr *) skb->data; + +- if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) ++ if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) { + tx->sta = rcu_dereference(sdata->u.vlan.sta); ++ if (!tx->sta && sdata->dev->ieee80211_ptr->use_4addr) ++ return TX_DROP; ++ } + if (!tx->sta) + tx->sta = sta_info_get(sdata, hdr->addr1); + diff --git a/package/mac80211/patches/590-endian_fix.patch b/package/mac80211/patches/590-endian_fix.patch new file mode 100644 index 000000000..9381a6f43 --- /dev/null +++ b/package/mac80211/patches/590-endian_fix.patch @@ -0,0 +1,15 @@ +--- a/net/mac80211/iface.c ++++ b/net/mac80211/iface.c +@@ -690,10 +690,10 @@ static u16 ieee80211_monitor_select_queu + return 0; + + if (skb->len < 4 || +- skb->len < rtap->it_len + 2 /* frame control */) ++ skb->len < le16_to_cpu(rtap->it_len) + 2 /* frame control */) + return 0; /* doesn't matter, frame will be dropped */ + +- hdr = (void *)((u8 *)skb->data + rtap->it_len); ++ hdr = (void *)((u8 *)skb->data + le16_to_cpu(rtap->it_len)); + + if (!ieee80211_is_data(hdr->frame_control)) { + skb->priority = 7; diff --git a/package/mac80211/patches/600-monitor_select_queue_fix.patch b/package/mac80211/patches/600-monitor_select_queue_fix.patch new file mode 100644 index 000000000..9a3b1d47f --- /dev/null +++ b/package/mac80211/patches/600-monitor_select_queue_fix.patch @@ -0,0 +1,26 @@ +--- a/net/mac80211/iface.c ++++ b/net/mac80211/iface.c +@@ -685,6 +685,7 @@ static u16 ieee80211_monitor_select_queu + struct ieee80211_local *local = sdata->local; + struct ieee80211_hdr *hdr; + struct ieee80211_radiotap_header *rtap = (void *)skb->data; ++ u8 *p; + + if (local->hw.queues < 4) + return 0; +@@ -695,11 +696,14 @@ static u16 ieee80211_monitor_select_queu + + hdr = (void *)((u8 *)skb->data + le16_to_cpu(rtap->it_len)); + +- if (!ieee80211_is_data(hdr->frame_control)) { ++ if (!ieee80211_is_data_qos(hdr->frame_control)) { + skb->priority = 7; + return ieee802_1d_to_ac[skb->priority]; + } + ++ p = ieee80211_get_qos_ctl(hdr); ++ skb->priority = *p & IEEE80211_QOS_CTL_TAG1D_MASK; ++ + return ieee80211_downgrade_queue(local, skb); + } + diff --git a/package/madwifi/Makefile b/package/madwifi/Makefile index 8e6d6dab2..79a3b3f87 100644 --- a/package/madwifi/Makefile +++ b/package/madwifi/Makefile @@ -161,7 +161,7 @@ define KernelPackage/madwifi SUBMENU:=Wireless Drivers TITLE:=Driver for Atheros wireless chipsets URL:=http://madwifi-project.org/ - DEPENDS:=+wireless-tools @PCI_SUPPORT||TARGET_atheros @!TARGET_avr32 @!TARGET_etrax @!TARGET_cobalt @!TARGET_octeon @LINUX_2_6 + DEPENDS:=+wireless-tools @PCI_SUPPORT||TARGET_atheros @!TARGET_avr32 @!TARGET_etrax @!TARGET_sibyte @!TARGET_cobalt @!TARGET_octeon @LINUX_2_6 @(!(TARGET_ep93xx||TARGET_pxcab)||BROKEN) FILES:=$(MADWIFI_FILES) AUTOLOAD:=$(call AutoLoad,50,$(MADWIFI_AUTOLOAD)) endef diff --git a/package/madwifi/files/lib/wifi/madwifi.sh b/package/madwifi/files/lib/wifi/madwifi.sh index b2bec7d25..29e9f3791 100755 --- a/package/madwifi/files/lib/wifi/madwifi.sh +++ b/package/madwifi/files/lib/wifi/madwifi.sh @@ -88,6 +88,7 @@ enable_atheros() { config_get antrx "$device" rxantenna config_get anttx "$device" txantenna config_get_bool softled "$device" softled 1 + config_get antenna "$device" antenna devname="$(cat /proc/sys/dev/$device/dev_name)" local antgpio= @@ -96,6 +97,13 @@ enable_atheros() { NanoStation2) antgpio=7; invert=1;; NanoStation5) antgpio=1; invert=1;; "NanoStation Loco2") antgpio=2;; + "NanoStation Loco5") + case "$antenna" in + horizontal) antdiv=0; anttx=1; antrx=1;; + vertical) antdiv=0; anttx=2; antrx=2;; + *) antdiv=1; anttx=0; antrx=0;; + esac + ;; esac if [ -n "$invert" ]; then _set="clear" @@ -106,21 +114,33 @@ enable_atheros() { fi if [ -n "$antgpio" ]; then softled=0 - config_get antenna "$device" antenna - case "$antenna" in - external) antdiv=0; antrx=1; anttx=1 ;; - horizontal) antdiv=0; antrx=1; anttx=1 ;; - vertical) antdiv=0; antrx=2; anttx=2 ;; - auto) antdiv=1; antrx=0; anttx=0 ;; + case "$devname" in + "NanoStation Loco2") + antdiv=0 + antrx=1 + anttx=1 + case "$antenna" in + horizontal) gpioval=0;; + *) gpioval=1;; + esac + ;; + *) + case "$antenna" in + external) antdiv=0; antrx=1; anttx=1; gpioval=1;; + horizontal) antdiv=0; antrx=1; anttx=1; gpioval=0;; + vertical) antdiv=0; antrx=2; anttx=2; gpioval=0;; + auto) antdiv=1; antrx=0; anttx=0; gpioval=0;; + esac + ;; esac [ -x "$(which gpioctl 2>/dev/null)" ] || antenna= gpioctl "dirout" "$antgpio" >/dev/null 2>&1 - case "$antenna" in - horizontal|vertical|auto) + case "$gpioval" in + 0) gpioctl "$_clear" "$antgpio" >/dev/null 2>&1 ;; - external) + 1) gpioctl "$_set" "$antgpio" >/dev/null 2>&1 ;; esac @@ -358,6 +378,18 @@ detect_atheros() { config_get type "$dev" type devname="$(cat /proc/sys/dev/$dev/dev_name)" case "$devname" in + "NanoStation Loco2") + EXTRA_DEV=" +# Ubiquiti NanoStation Loco2 features + option antenna vertical # (horizontal|vertical) +" + ;; + "NanoStation Loco5") + EXTRA_DEV=" +# Ubiquiti NanoStation Loco5 features + option antenna auto # (auto|horizontal|vertical) +" + ;; NanoStation*) EXTRA_DEV=" # Ubiquiti NanoStation features diff --git a/package/madwifi/patches/453-procps.patch b/package/madwifi/patches/453-procps.patch index 253764055..5a5633b1c 100644 --- a/package/madwifi/patches/453-procps.patch +++ b/package/madwifi/patches/453-procps.patch @@ -1,6 +1,6 @@ ---- a/net80211/ieee80211_linux.h 2009-10-04 22:27:05.528151949 +0300 -+++ b/net80211/ieee80211_linux.h 2009-10-04 22:28:06.255777139 +0300 -@@ -640,12 +640,24 @@ +--- a/net80211/ieee80211_linux.h ++++ b/net80211/ieee80211_linux.h +@@ -640,12 +640,24 @@ static __inline unsigned long msecs_to_j void __user *buffer, size_t *lenp) #define IEEE80211_SYSCTL_PROC_DOINTVEC(ctl, write, filp, buffer, lenp, ppos) \ proc_dointvec(ctl, write, filp, buffer, lenp) @@ -26,9 +26,9 @@ #endif void ieee80211_virtfs_latevattach(struct ieee80211vap *); ---- a/ath/if_athvar.h 2009-10-04 22:27:05.543151943 +0300 -+++ b/ath/if_athvar.h 2009-10-04 22:27:40.115902053 +0300 -@@ -173,14 +173,22 @@ +--- a/ath/if_athvar.h ++++ b/ath/if_athvar.h +@@ -173,14 +173,22 @@ static inline struct net_device *_alloc_ proc_dointvec(ctl, write, filp, buffer, lenp) #define ATH_SYSCTL_PROC_DOSTRING(ctl, write, filp, buffer, lenp, ppos) \ proc_dostring(ctl, write, filp, buffer, lenp) diff --git a/package/madwifi/patches/454-cca.patch b/package/madwifi/patches/454-cca.patch new file mode 100644 index 000000000..53792cc8f --- /dev/null +++ b/package/madwifi/patches/454-cca.patch @@ -0,0 +1,186 @@ +--- a/ath/if_ath.c ++++ b/ath/if_ath.c +@@ -383,6 +383,8 @@ static void ath_poll_disable(struct net_ + static void ath_poll_enable(struct net_device *dev); + static void ath_fetch_idle_time(struct ath_softc *sc); + static void ath_set_timing(struct ath_softc *sc); ++static void ath_update_cca_thresh(struct ath_softc *sc); ++static int ath_hw_read_nf(struct ath_softc *sc); + + /* calibrate every 30 secs in steady state but check every second at first. */ + static int ath_calinterval = ATH_SHORT_CALINTERVAL; +@@ -2623,6 +2625,10 @@ ath_init(struct net_device *dev) + goto done; + } + ++ ath_hal_process_noisefloor(ah); ++ ic->ic_channoise = ath_hal_get_channel_noise(ah, &(sc->sc_curchan)); ++ ath_update_cca_thresh(sc); ++ + if (sc->sc_softled) + ath_hal_gpioCfgOutput(ah, sc->sc_ledpin); + +@@ -3024,6 +3030,10 @@ ath_reset(struct net_device *dev) + EPRINTF(sc, "Unable to reset hardware: '%s' (HAL status %u)\n", + ath_get_hal_status_desc(status), status); + ++ ath_hal_process_noisefloor(ah); ++ ic->ic_channoise = ath_hal_get_channel_noise(ah, &(sc->sc_curchan)); ++ ath_update_cca_thresh(sc); ++ + ath_setintmit(sc); + ath_update_txpow(sc); /* update tx power state */ + ath_radar_update(sc); +@@ -9374,9 +9384,11 @@ ath_calibrate(unsigned long arg) + sc->sc_curchan.channel); + sc->sc_stats.ast_per_calfail++; + } +- ic->ic_channoise = ath_hal_get_channel_noise(ah, &(sc->sc_curchan)); + + ath_hal_process_noisefloor(ah); ++ ic->ic_channoise = ath_hal_get_channel_noise(ah, &(sc->sc_curchan)); ++ ath_update_cca_thresh(sc); ++ + if (isIQdone == AH_TRUE) { + /* Unless user has overridden calibration interval, + * upgrade to less frequent calibration */ +@@ -9711,8 +9723,6 @@ ath_newstate(struct ieee80211vap *vap, e + break; + } + +- ath_hal_process_noisefloor(ah); +- ic->ic_channoise = ath_hal_get_channel_noise(ah, &(sc->sc_curchan)); + /* + * Reset rssi stats; maybe not the best place... + */ +@@ -10968,6 +10978,7 @@ enum { + ATH_INTMIT, + ATH_NOISE_IMMUNITY, + ATH_OFDM_WEAK_DET, ++ ATH_CCA_THRESH, + ATH_CHANBW, + ATH_OUTDOOR, + ATH_DISTANCE, +@@ -11110,6 +11121,66 @@ ath_sysctl_get_intmit(struct ath_softc * + return 0; + } + ++#define AR_PHY_CCA 0x9864 ++#define AR_PHY_MINCCA_PWR 0x0FF80000 ++#define AR_PHY_MINCCA_PWR_S 19 ++#define AR_PHY_CCA_THRESH62 0x0007F000 ++#define AR_PHY_CCA_THRESH62_S 12 ++ ++static int ++ath_nf_from_cca(u32 phy_cca) ++{ ++ int nf = (phy_cca >> 19) & 0x1ff; ++ nf = -((nf ^ 0x1ff) + 1); ++ return nf; ++} ++ ++static int ++ath_hw_read_nf(struct ath_softc *sc) ++{ ++ return ath_nf_from_cca(OS_REG_READ(sc->sc_ah, AR_PHY_CCA)); ++} ++ ++static void ++ath_update_cca_thresh(struct ath_softc *sc) ++{ ++ struct ath_hal *ah = sc->sc_ah; ++ int newthr = 0; ++ u32 phy_cca; ++ int nf; ++ ++ phy_cca = OS_REG_READ(ah, AR_PHY_CCA); ++ if (sc->sc_cca_thresh < 0) { ++ newthr = sc->sc_cca_thresh - ath_nf_from_cca(phy_cca); ++ ++ /* 0xf is a typical eeprom value for thresh62, ++ * use it as minimum for signal based thresholds ++ * to prevent complete connection drops */ ++ if (newthr < 0xf) ++ newthr = 0xf; ++ } else { ++ newthr = sc->sc_cca_thresh; ++ } ++ ++ if ((newthr < 4) || (newthr >= 127)) ++ return; ++ ++ phy_cca &= ~AR_PHY_CCA_THRESH62; ++ phy_cca |= newthr << AR_PHY_CCA_THRESH62_S; ++ OS_REG_WRITE(ah, AR_PHY_CCA, phy_cca); ++} ++ ++static int ++ath_get_cca_thresh(struct ath_softc *sc) ++{ ++ struct ath_hal *ah = sc->sc_ah; ++ u32 phy_cca; ++ ++ phy_cca = OS_REG_READ(ah, AR_PHY_CCA); ++ return ath_nf_from_cca(phy_cca) + ++ ((phy_cca & AR_PHY_CCA_THRESH62) >> AR_PHY_CCA_THRESH62_S); ++} ++ + static int + ATH_SYSCTL_DECL(ath_sysctl_hwinfo, ctl, write, filp, buffer, lenp, ppos) + { +@@ -11356,6 +11427,10 @@ ATH_SYSCTL_DECL(ath_sysctl_halparam, ctl + case ATH_OFDM_WEAK_DET: + ret = ath_sysctl_set_intmit(sc, (long)ctl->extra2, val); + break; ++ case ATH_CCA_THRESH: ++ sc->sc_cca_thresh = val; ++ ath_update_cca_thresh(sc); ++ break; + default: + ret = -EINVAL; + break; +@@ -11436,6 +11511,9 @@ ATH_SYSCTL_DECL(ath_sysctl_halparam, ctl + case ATH_OFDM_WEAK_DET: + ret = ath_sysctl_get_intmit(sc, (long)ctl->extra2, &val); + break; ++ case ATH_CCA_THRESH: ++ val = ath_get_cca_thresh(sc); ++ break; + default: + ret = -EINVAL; + break; +@@ -11667,6 +11745,12 @@ static const ctl_table ath_sysctl_templa + .proc_handler = ath_sysctl_halparam, + .extra2 = (void *)ATH_OFDM_WEAK_DET, + }, ++ { .ctl_name = CTL_AUTO, ++ .procname = "cca_thresh", ++ .mode = 0644, ++ .proc_handler = ath_sysctl_halparam, ++ .extra2 = (void *)ATH_CCA_THRESH, ++ }, + { 0 } + }; + +--- a/ath/if_athvar.h ++++ b/ath/if_athvar.h +@@ -844,6 +844,7 @@ struct ath_softc { + int sc_cal_interval; /* current calibration interval */ + struct timer_list sc_cal_ch; /* calibration timer */ + HAL_NODE_STATS sc_halstats; /* station-mode rssi stats */ ++ int sc_cca_thresh; /* configured CCA threshold */ + + struct ctl_table_header *sc_sysctl_header; + struct ctl_table *sc_sysctls; +--- a/ath/ath_wprobe.c ++++ b/ath/ath_wprobe.c +@@ -133,8 +133,7 @@ ath_wprobe_sync(struct wprobe_iface *dev + rx = READ_CLR(ah, AR5K_RXFC); + tx = READ_CLR(ah, AR5K_TXFC); + OS_REG_WRITE(ah, AR5K_MIBC, 0); +- noise = ath_hal_get_channel_noise(sc->sc_ah, &(sc->sc_curchan)); +- ic->ic_channoise = noise; ++ noise = ath_hw_read_nf(sc); + + WPROBE_FILL_BEGIN(val, ath_wprobe_globals); + if (cc & 0xf0000000) { diff --git a/package/madwifi/patches/455-beacon_watchdog.patch b/package/madwifi/patches/455-beacon_watchdog.patch new file mode 100644 index 000000000..e399564df --- /dev/null +++ b/package/madwifi/patches/455-beacon_watchdog.patch @@ -0,0 +1,95 @@ +--- a/ath/if_ath.c ++++ b/ath/if_ath.c +@@ -379,6 +379,7 @@ static u_int32_t ath_get_clamped_maxtxpo + static u_int32_t ath_set_clamped_maxtxpower(struct ath_softc *sc, + u_int32_t new_clamped_maxtxpower); + ++static void ath_bcn_timer(unsigned long arg); + static void ath_poll_disable(struct net_device *dev); + static void ath_poll_enable(struct net_device *dev); + static void ath_fetch_idle_time(struct ath_softc *sc); +@@ -829,6 +830,10 @@ ath_attach(u_int16_t devid, struct net_d + sc->sc_cal_ch.function = ath_calibrate; + sc->sc_cal_ch.data = (unsigned long) dev; + ++ init_timer(&sc->sc_bcntimer); ++ sc->sc_bcntimer.function = ath_bcn_timer; ++ sc->sc_bcntimer.data = (unsigned long) dev; ++ + /* initialize DFS related variables */ + sc->sc_dfswait = 0; + sc->sc_dfs_cac = 0; +@@ -2704,6 +2709,7 @@ ath_stop_locked(struct net_device *dev) + DPRINTF(sc, ATH_DEBUG_RESET, "invalid=%u flags=0x%x\n", + sc->sc_invalid, dev->flags); + ++ del_timer_sync(&sc->sc_bcntimer); + if (dev->flags & IFF_RUNNING) { + /* + * Shutdown the hardware and driver: +@@ -3006,6 +3012,7 @@ ath_reset(struct net_device *dev) + struct ieee80211_channel *c; + HAL_STATUS status; + ++ del_timer_sync(&sc->sc_bcntimer); + /* + * XXX: starting the calibration too early seems to lead to + * problems with the beacons. +@@ -5305,6 +5312,7 @@ ath_beacon_send(struct ath_softc *sc, in + if (ath_chan_unavail_dbgmsg(sc)) + return; + ++ mod_timer(&sc->sc_bcntimer, jiffies + sc->sc_bcntimer_reload); + /* + * Check if the previous beacon has gone out. If + * not don't try to post another, skip this period +@@ -5487,6 +5495,18 @@ ath_beacon_free(struct ath_softc *sc) + cleanup_ath_buf(sc, bf, BUS_DMA_TODEVICE); + } + ++static void ath_bcn_timer(unsigned long arg) ++{ ++ struct net_device *dev = (struct net_device *)arg; ++ struct ath_softc *sc = netdev_priv(dev); ++ struct ath_hal *ah = sc->sc_ah; ++ ++ if (!sc->sc_beacons) ++ return; ++ ++ ath_reset(dev); ++} ++ + /* + * Configure the beacon and sleep timers. + * +@@ -5523,6 +5543,7 @@ ath_beacon_config(struct ath_softc *sc, + if (vap == NULL) + vap = TAILQ_FIRST(&ic->ic_vaps); /* XXX */ + ++ del_timer_sync(&sc->sc_bcntimer); + ni = vap->iv_bss; + + /* TSF calculation is timing critical - we don't want to be interrupted here */ +@@ -5699,6 +5720,9 @@ ath_beacon_config(struct ath_softc *sc, + sc->sc_imask |= HAL_INT_SWBA; + ath_set_beacon_cal(sc, 1); + ath_beaconq_config(sc); ++ ++ sc->sc_bcntimer_reload = msecs_to_jiffies(10 * (intval & HAL_BEACON_PERIOD)); ++ mod_timer(&sc->sc_bcntimer, jiffies + sc->sc_bcntimer_reload); + } else + ath_set_beacon_cal(sc, 0); + +--- a/ath/if_athvar.h ++++ b/ath/if_athvar.h +@@ -789,6 +789,10 @@ struct ath_softc { + u_int16_t sc_ledoff; /* off time for current blink */ + struct timer_list sc_ledtimer; /* led off timer */ + ++ /* beacon watchdog timer */ ++ u_int32_t sc_bcntimer_reload; ++ struct timer_list sc_bcntimer; ++ + struct ATH_TQ_STRUCT sc_fataltq; /* fatal error intr tasklet */ + + int sc_rxbufsize; /* rx size based on mtu */ diff --git a/package/openssl/Makefile b/package/openssl/Makefile index 23695fcc2..ac565218d 100644 --- a/package/openssl/Makefile +++ b/package/openssl/Makefile @@ -71,12 +71,16 @@ OPENSSL_NO_CIPHERS:= no-idea no-md2 no-mdc2 no-rc5 no-sha0 no-smime \ no-rmd160 no-aes192 no-ripemd no-camellia no-ans1 no-krb5 ifeq ($(BOARD),ixp4xx) OPENSSL_OPTIONS:= shared no-ec no-err no-hw no-threads zlib-dynamic \ - no-sse2 no-perlasm --with-cryptodev + no-sse2 --with-cryptodev else OPENSSL_OPTIONS:= shared no-ec no-err no-hw no-threads zlib-dynamic \ - no-engines no-sse2 no-perlasm + no-engines no-sse2 +endif +ifdef CONFIG_arm +OPENSSL_MAKEFLAGS := AES_ASM_OBJ="aes-armv4.o aes_cbc.o" +else +OPENSSL_OPTIONS += no-perlasm endif - define Build/Configure (cd $(PKG_BUILD_DIR); \ @@ -100,21 +104,25 @@ define Build/Compile $(MAKE) -C $(PKG_BUILD_DIR) \ MAKEDEPPROG="$(TARGET_CROSS)gcc" \ OPENWRT_OPTIMIZATION_FLAGS="$(TARGET_CFLAGS)" \ + $(OPENSSL_MAKEFLAGS) \ depend $(MAKE) -C $(PKG_BUILD_DIR) \ CC="$(TARGET_CC)" \ AR="$(TARGET_CROSS)ar r" \ RANLIB="$(TARGET_CROSS)ranlib" \ OPENWRT_OPTIMIZATION_FLAGS="$(TARGET_CFLAGS)" \ + $(OPENSSL_MAKEFLAGS) \ all build-shared # Work around openssl build bug to link libssl.so with libcrypto.so. -rm $(PKG_BUILD_DIR)/libssl.so.*.*.* $(MAKE) -C $(PKG_BUILD_DIR) \ CC="$(TARGET_CC)" \ OPENWRT_OPTIMIZATION_FLAGS="$(TARGET_CFLAGS)" \ + $(OPENSSL_MAKEFLAGS) \ do_linux-shared $(MAKE) -C $(PKG_BUILD_DIR) \ INSTALL_PREFIX="$(PKG_INSTALL_DIR)" \ + $(OPENSSL_MAKEFLAGS) \ install endef diff --git a/package/openssl/patches/310-arm_asm.patch b/package/openssl/patches/310-arm_asm.patch new file mode 100644 index 000000000..2d940f0ef --- /dev/null +++ b/package/openssl/patches/310-arm_asm.patch @@ -0,0 +1,13 @@ +--- a/crypto/aes/Makefile ++++ b/crypto/aes/Makefile +@@ -47,6 +47,9 @@ lib: $(LIBOBJ) + + $(LIBOBJ): $(LIBSRC) + ++aes-armv4.s: asm/aes-armv4.pl ++ $(PERL) $^ > $@ ++ + aes-ia64.s: asm/aes-ia64.S + $(CC) $(CFLAGS) -E asm/aes-ia64.S > $@ + + diff --git a/package/opkg/Makefile b/package/opkg/Makefile index 9c87e482c..6894ae7cb 100644 --- a/package/opkg/Makefile +++ b/package/opkg/Makefile @@ -1,5 +1,5 @@ # -# Copyright (C) 2006-2009 OpenWrt.org +# Copyright (C) 2006-2010 OpenWrt.org # # This is free software, licensed under the GNU General Public License v2. # See /LICENSE for more information. @@ -8,7 +8,7 @@ include $(TOPDIR)/rules.mk include $(INCLUDE_DIR)/kernel.mk PKG_NAME:=opkg -PKG_REV:=284 +PKG_REV:=513 PKG_VERSION:=$(PKG_REV) PKG_RELEASE:=1 @@ -47,7 +47,8 @@ EXTRA_CFLAGS += $(TARGET_CPPFLAGS) CONFIGURE_ARGS += \ --disable-curl \ --disable-gpg \ - --with-ipkgetcdir=/etc + --with-opkgetcdir=/etc \ + --with-opkglockfile=/var/lock/opkg.lock define Build/Configure (cd $(PKG_BUILD_DIR); \ diff --git a/package/opkg/patches/003-fs_overlay_support.patch b/package/opkg/patches/003-fs_overlay_support.patch index f84060ab1..0716ae481 100644 --- a/package/opkg/patches/003-fs_overlay_support.patch +++ b/package/opkg/patches/003-fs_overlay_support.patch @@ -6,56 +6,46 @@ Signed-off-by: Nicolas Thill --- a/libopkg/opkg_conf.c +++ b/libopkg/opkg_conf.c -@@ -72,6 +72,7 @@ - { "offline_root_path", OPKG_OPT_TYPE_STRING, &conf->offline_root_path }, - { "offline_root_post_script_cmd", OPKG_OPT_TYPE_STRING, &conf->offline_root_post_script_cmd }, - { "offline_root_pre_script_cmd", OPKG_OPT_TYPE_STRING, &conf->offline_root_pre_script_cmd }, -+ { "overlay_root", OPKG_OPT_TYPE_STRING, &conf->overlay_root }, - { "proxy_passwd", OPKG_OPT_TYPE_STRING, &conf->proxy_passwd }, - { "proxy_user", OPKG_OPT_TYPE_STRING, &conf->proxy_user }, - { "query-all", OPKG_OPT_TYPE_BOOL, &conf->query_all }, +@@ -62,6 +62,7 @@ + { "download_only", OPKG_OPT_TYPE_BOOL, &_conf.download_only }, + { "nodeps", OPKG_OPT_TYPE_BOOL, &_conf.nodeps }, + { "offline_root", OPKG_OPT_TYPE_STRING, &_conf.offline_root }, ++ { "overlay_root", OPKG_OPT_TYPE_STRING, &_conf.overlay_root }, + { "proxy_passwd", OPKG_OPT_TYPE_STRING, &_conf.proxy_passwd }, + { "proxy_user", OPKG_OPT_TYPE_STRING, &_conf.proxy_user }, + { "query-all", OPKG_OPT_TYPE_BOOL, &_conf.query_all }, --- a/libopkg/opkg_conf.h +++ b/libopkg/opkg_conf.h -@@ -70,6 +70,7 @@ - char *offline_root_path; - char *offline_root_pre_script_cmd; - char *offline_root_post_script_cmd; +@@ -76,6 +76,7 @@ + int check_signature; + int nodeps; /* do not follow dependences */ + char *offline_root; + char *overlay_root; int query_all; int verbosity; int noaction; --- a/libopkg/opkg_install.c +++ b/libopkg/opkg_install.c -@@ -470,12 +470,15 @@ - * my diddling with the .opk file size below isn't going to cut it. - * 3) return a proper error code instead of 1 - */ -- int comp_size, blocks_available; -+ int comp_size, blocks_available = -1; - char *root_dir; - - if (!conf->force_space && pkg->installed_size != NULL) { - root_dir = pkg->dest ? pkg->dest->root_dir : conf->default_dest->root_dir; -- blocks_available = get_available_blocks(root_dir); -+ if (conf->overlay_root != NULL) -+ blocks_available = get_available_blocks(conf->overlay_root); -+ if (blocks_available < 0) -+ blocks_available = get_available_blocks(root_dir); - - comp_size = strtoul(pkg->installed_size, NULL, 0); - /* round up a blocks count without doing fancy-but-slow casting jazz */ ---- a/libopkg/opkg_utils.c -+++ b/libopkg/opkg_utils.c -@@ -31,10 +31,8 @@ +@@ -189,13 +189,19 @@ + verify_pkg_installable(pkg_t *pkg) { - struct statfs sfs; + unsigned long kbs_available, pkg_size_kbs; +- char *root_dir; ++ char *root_dir = NULL; -- if(statfs(filesystem, &sfs)){ -- fprintf(stderr, "bad statfs\n"); -- return 0; -- } -+ if(statfs(filesystem, &sfs)) -+ return -1; - /* fprintf(stderr, "reported fs type %x\n", sfs.f_type); */ + if (conf->force_space || pkg->installed_size == 0) + return 0; - // Actually ((sfs.f_bavail * sfs.f_bsize) / 1024) +- root_dir = pkg->dest ? pkg->dest->root_dir : +- conf->default_dest->root_dir; ++ if( !pkg->dest || !strcmp(pkg->dest->name, "root") ) ++ root_dir = conf->overlay_root; ++ else ++ root_dir = pkg->dest->root_dir; ++ ++ if( !root_dir ) ++ root_dir = conf->default_dest->root_dir; ++ + kbs_available = get_available_kbytes(root_dir); + + pkg_size_kbs = (pkg->installed_size + 1023)/1024; diff --git a/package/opkg/patches/004-host_cpu.patch b/package/opkg/patches/004-host_cpu.patch index ad1c74c58..d500d603d 100644 --- a/package/opkg/patches/004-host_cpu.patch +++ b/package/opkg/patches/004-host_cpu.patch @@ -12,9 +12,9 @@ +++ b/libopkg/Makefile.am @@ -1,5 +1,5 @@ - --AM_CFLAGS=-Wall -Werror -DHOST_CPU_STR=\"@host_cpu@\" -DBUILD_CPU=@build_cpu@ -DLIBDIR=\"@libdir@\" -DOPKGLIBDIR=\"@opkglibdir@\" -DOPKGETCDIR=\"@opkgetcdir@\" -DDATADIR=\"@datadir@\" -I$(top_srcdir) $(BIGENDIAN_CFLAGS) $(CURL_CFLAGS) $(GPGME_CFLAGS) $(PATHFINDER_CFLAGS) +-AM_CFLAGS=-Wall -DHOST_CPU_STR=\"@host_cpu@\" -DBUILD_CPU=@build_cpu@ -DLIBDIR=\"@libdir@\" -DOPKGLIBDIR=\"@opkglibdir@\" -DOPKGETCDIR=\"@opkgetcdir@\" -DOPKGLOCKFILE=\"@opkglockfile@\" -DDATADIR=\"@datadir@\" -I$(top_srcdir) $(BIGENDIAN_CFLAGS) $(CURL_CFLAGS) $(GPGME_CFLAGS) $(PATHFINDER_CFLAGS) +HOST_CPU=@host_cpu@ -+AM_CFLAGS=-Wall -Werror -DHOST_CPU_STR=\"$(HOST_CPU)\" -DBUILD_CPU=@build_cpu@ -DLIBDIR=\"@libdir@\" -DOPKGLIBDIR=\"@opkglibdir@\" -DOPKGETCDIR=\"@opkgetcdir@\" -DDATADIR=\"@datadir@\" -I$(top_srcdir) $(BIGENDIAN_CFLAGS) $(CURL_CFLAGS) $(GPGME_CFLAGS) $(PATHFINDER_CFLAGS) ++AM_CFLAGS=-Wall -DHOST_CPU_STR=\"$(HOST_CPU)\" -DBUILD_CPU=@build_cpu@ -DLIBDIR=\"@libdir@\" -DOPKGLIBDIR=\"@opkglibdir@\" -DOPKGETCDIR=\"@opkgetcdir@\" -DOPKGLOCKFILE=\"@opkglockfile@\" -DDATADIR=\"@datadir@\" -I$(top_srcdir) $(BIGENDIAN_CFLAGS) $(CURL_CFLAGS) $(GPGME_CFLAGS) $(PATHFINDER_CFLAGS) libopkg_includedir=$(includedir)/libopkg - libopkg_include_HEADERS= opkg.h + libopkg_include_HEADERS= *.h diff --git a/package/opkg/patches/005-uninitialized_err.patch b/package/opkg/patches/005-uninitialized_err.patch deleted file mode 100644 index 0d3b6cf24..000000000 --- a/package/opkg/patches/005-uninitialized_err.patch +++ /dev/null @@ -1,16 +0,0 @@ ---- a/libopkg/pkg_hash.c -+++ b/libopkg/pkg_hash.c -@@ -384,8 +384,11 @@ - abstract_pkg_t *apkg = NULL; - pkg_t *ret; - -- if (!(apkg = abstract_pkg_fetch_by_name(hash, name))) -- return NULL; -+ if (!(apkg = abstract_pkg_fetch_by_name(hash, name))) { -+ if (err) -+ *err = 0; -+ return NULL; -+ } - - ret = pkg_hash_fetch_best_installation_candidate(conf, apkg, pkg_name_constraint_fcn, apkg->name, 0, err); - diff --git a/package/opkg/patches/007-force_static.patch b/package/opkg/patches/007-force_static.patch index 632250863..4ae8bfea4 100644 --- a/package/opkg/patches/007-force_static.patch +++ b/package/opkg/patches/007-force_static.patch @@ -1,6 +1,6 @@ --- a/libopkg/Makefile.am +++ b/libopkg/Makefile.am -@@ -36,16 +36,10 @@ +@@ -35,16 +35,10 @@ opkg_util_sources += sha256.c sha256.h endif @@ -15,7 +15,7 @@ -libopkg_la_LIBADD = $(top_builddir)/libbb/libbb.la $(CURL_LIBS) $(GPGME_LIBS) $(OPENSSL_LIBS) $(PATHFINDER_LIBS) - -# make sure we only export symbols that are for public use --libopkg_la_LDFLAGS = -export-symbols-regex "^opkg_.*" +-#libopkg_la_LDFLAGS = -export-symbols-regex "^opkg_.*" - - - @@ -34,18 +34,22 @@ libbb.h \ unzip.c \ wfopen.c \ ---- a/src/Makefile.am -+++ b/src/Makefile.am -@@ -2,5 +2,5 @@ - bin_PROGRAMS = opkg-cl - - opkg_cl_SOURCES = opkg-frontend.c --opkg_cl_LDADD = $(top_builddir)/libopkg/libopkg.la \ -- $(top_builddir)/libbb/libbb.la -+opkg_cl_LDADD = $(top_builddir)/libopkg/libopkg.a \ -+ $(top_builddir)/libbb/libbb.a --- a/tests/Makefile.am +++ b/tests/Makefile.am +@@ -4,11 +4,11 @@ + #noinst_PROGRAMS = libopkg_test opkg_active_list_test + noinst_PROGRAMS = libopkg_test + +-#opkg_hash_test_LDADD = $(top_builddir)/libbb/libbb.la $(top_builddir)/libopkg/libopkg.la ++#opkg_hash_test_LDADD = $(top_builddir)/libbb/libbb.a $(top_builddir)/libopkg/libopkg.a + #opkg_hash_test_SOURCES = opkg_hash_test.c + #opkg_hash_test_CFLAGS = $(ALL_CFLAGS) -I$(top_srcdir) + +-#opkg_extract_test_LDADD = $(top_builddir)/libbb/libbb.la $(top_builddir)/libopkg/libopkg.la ++#opkg_extract_test_LDADD = $(top_builddir)/libbb/libbb.a $(top_builddir)/libopkg/libopkg.a + #opkg_extract_test_SOURCES = opkg_extract_test.c + #opkg_extract_test_CFLAGS = $(ALL_CFLAGS) -I$(top_srcdir) + @@ -16,7 +16,7 @@ #opkg_active_list_test_SOURCES = opkg_active_list_test.c #opkg_active_list_test_CFLAGS = $(ALL_CFLAGS) -I$(top_srcdir) @@ -53,5 +57,15 @@ -libopkg_test_LDADD = $(top_builddir)/libopkg/libopkg.la +libopkg_test_LDADD = $(top_builddir)/libopkg/libopkg.a $(top_builddir)/libbb/libbb.a libopkg_test_SOURCE = libopkg_test.c + libopkg_test_LDFLAGS = -static +--- a/src/Makefile.am ++++ b/src/Makefile.am +@@ -2,5 +2,5 @@ + bin_PROGRAMS = opkg-cl + opkg_cl_SOURCES = opkg-cl.c +-opkg_cl_LDADD = $(top_builddir)/libopkg/libopkg.la \ +- $(top_builddir)/libbb/libbb.la ++opkg_cl_LDADD = $(top_builddir)/libopkg/libopkg.a \ ++ $(top_builddir)/libbb/libbb.a diff --git a/package/opkg/patches/009-remove-upgrade-all.patch b/package/opkg/patches/009-remove-upgrade-all.patch index d2440e031..d73ef466e 100644 --- a/package/opkg/patches/009-remove-upgrade-all.patch +++ b/package/opkg/patches/009-remove-upgrade-all.patch @@ -1,40 +1,29 @@ ---- a/libopkg/args.c -+++ b/libopkg/args.c -@@ -259,7 +259,7 @@ - - printf("\nPackage Manipulation:\n"); - printf("\tupdate Update list of available packages\n"); -- printf("\tupgrade Upgrade all installed packages to latest version\n"); -+ printf("\tupgrade Upgrade package to latest version\n"); - printf("\tinstall Download and install (and dependencies)\n"); - printf("\tinstall Install package \n"); - printf("\tconfigure [] Configure unpacked packages\n"); --- a/libopkg/opkg_cmd.c +++ b/libopkg/opkg_cmd.c -@@ -75,7 +75,7 @@ - array for easier maintenance */ - static opkg_cmd_t cmds[] = { - {"update", 0, (opkg_cmd_fun_t)opkg_update_cmd}, -- {"upgrade", 0, (opkg_cmd_fun_t)opkg_upgrade_cmd}, -+ {"upgrade", 1, (opkg_cmd_fun_t)opkg_upgrade_cmd}, - {"list", 0, (opkg_cmd_fun_t)opkg_list_cmd}, - {"list_installed", 0, (opkg_cmd_fun_t)opkg_list_installed_cmd}, - {"list_upgradable", 0, (opkg_cmd_fun_t)opkg_list_upgradable_cmd}, -@@ -607,17 +607,6 @@ - opkg_install_by_name(conf, arg); +@@ -498,17 +498,6 @@ + opkg_install_by_name(arg); } } - } else { - pkg_vec_t *installed = pkg_vec_alloc(); - -- pkg_info_preinstall_check(conf); +- pkg_info_preinstall_check(); - -- pkg_hash_fetch_all_installed(&conf->pkg_hash, installed); +- pkg_hash_fetch_all_installed(installed); - for (i = 0; i < installed->len; i++) { - pkg = installed->pkgs[i]; -- opkg_upgrade_pkg(conf, pkg); +- opkg_upgrade_pkg(pkg); - } - pkg_vec_free(installed); } - opkg_configure_packages(conf, NULL); + opkg_configure_packages(NULL); +@@ -1166,7 +1155,7 @@ + array for easier maintenance */ + static opkg_cmd_t cmds[] = { + {"update", 0, (opkg_cmd_fun_t)opkg_update_cmd, PFM_DESCRIPTION|PFM_SOURCE}, +- {"upgrade", 0, (opkg_cmd_fun_t)opkg_upgrade_cmd, PFM_DESCRIPTION|PFM_SOURCE}, ++ {"upgrade", 1, (opkg_cmd_fun_t)opkg_upgrade_cmd, PFM_DESCRIPTION|PFM_SOURCE}, + {"list", 0, (opkg_cmd_fun_t)opkg_list_cmd, PFM_SOURCE}, + {"list_installed", 0, (opkg_cmd_fun_t)opkg_list_installed_cmd, PFM_SOURCE}, + {"list-installed", 0, (opkg_cmd_fun_t)opkg_list_installed_cmd, PFM_SOURCE}, diff --git a/package/opkg/patches/010-remove-flag.patch b/package/opkg/patches/010-remove-flag.patch index 9b988b89e..277546fed 100644 --- a/package/opkg/patches/010-remove-flag.patch +++ b/package/opkg/patches/010-remove-flag.patch @@ -1,78 +1,60 @@ ---- a/libopkg/args.c -+++ b/libopkg/args.c -@@ -264,8 +264,6 @@ - printf("\tinstall Install package \n"); - printf("\tconfigure [] Configure unpacked packages\n"); - printf("\tremove Remove package \n"); -- printf("\tflag ... Flag package(s) \n"); -- printf("\t =hold|noprune|user|ok|installed|unpacked (one per invocation) \n"); - - printf("\nInformational Commands:\n"); - printf("\tlist List available packages and descriptions\n"); --- a/libopkg/opkg_cmd.c +++ b/libopkg/opkg_cmd.c -@@ -54,7 +54,6 @@ - static int opkg_list_upgradable_cmd(opkg_conf_t *conf, int argc, char **argv); - static int opkg_remove_cmd(opkg_conf_t *conf, int argc, char **argv); - static int opkg_purge_cmd(opkg_conf_t *conf, int argc, char **argv); --static int opkg_flag_cmd(opkg_conf_t *conf, int argc, char **argv); - static int opkg_files_cmd(opkg_conf_t *conf, int argc, char **argv); - static int opkg_search_cmd(opkg_conf_t *conf, int argc, char **argv); - static int opkg_download_cmd(opkg_conf_t *conf, int argc, char **argv); -@@ -80,7 +79,6 @@ - {"list_installed", 0, (opkg_cmd_fun_t)opkg_list_installed_cmd}, - {"list_upgradable", 0, (opkg_cmd_fun_t)opkg_list_upgradable_cmd}, - {"info", 0, (opkg_cmd_fun_t)opkg_info_cmd}, -- {"flag", 1, (opkg_cmd_fun_t)opkg_flag_cmd}, - {"status", 0, (opkg_cmd_fun_t)opkg_status_cmd}, - {"install_pending", 0, (opkg_cmd_fun_t)opkg_install_pending_cmd}, - {"install", 1, (opkg_cmd_fun_t)opkg_install_cmd}, -@@ -960,48 +958,6 @@ - return 0; +@@ -738,49 +738,6 @@ } --static int opkg_flag_cmd(opkg_conf_t *conf, int argc, char **argv) + static int +-opkg_flag_cmd(int argc, char **argv) -{ - int i; - pkg_t *pkg; - const char *flags = argv[0]; - -- global_conf = conf; - signal(SIGINT, sigint_handler); - - for (i=1; i < argc; i++) { - if (conf->restrict_to_default_dest) { -- pkg = pkg_hash_fetch_installed_by_name_dest(&conf->pkg_hash, -- argv[i], +- pkg = pkg_hash_fetch_installed_by_name_dest(argv[i], - conf->default_dest); - } else { -- pkg = pkg_hash_fetch_installed_by_name(&conf->pkg_hash, argv[i]); +- pkg = pkg_hash_fetch_installed_by_name(argv[i]); - } - - if (pkg == NULL) { -- opkg_message(conf, OPKG_ERROR, -- "Package %s is not installed.\n", argv[i]); +- opkg_msg(ERROR, "Package %s is not installed.\n", argv[i]); - continue; - } - if (( strcmp(flags,"hold")==0)||( strcmp(flags,"noprune")==0)|| - ( strcmp(flags,"user")==0)||( strcmp(flags,"ok")==0)) { - pkg->state_flag = pkg_state_flag_from_str(flags); - } --/* pb_ asked this feature 03292004 */ --/* Actually I will use only this two, but this is an open for various status */ +- +- /* +- * Useful if a package is installed in an offline_root, and +- * should be configured by opkg-cl configure at a later date. +- */ - if (( strcmp(flags,"installed")==0)||( strcmp(flags,"unpacked")==0)){ - pkg->state_status = pkg_state_status_from_str(flags); - } +- - opkg_state_changed++; -- opkg_message(conf, OPKG_NOTICE, -- "Setting flags for package %s to %s\n", +- opkg_msg(NOTICE, "Setting flags for package %s to %s.\n", - pkg->name, flags); - } - -- write_status_files_if_changed(conf); +- write_status_files_if_changed(); - return 0; -} - - static int opkg_files_cmd(opkg_conf_t *conf, int argc, char **argv) +-static int + opkg_files_cmd(int argc, char **argv) { pkg_t *pkg; +@@ -1162,7 +1119,6 @@ + {"list_upgradable", 0, (opkg_cmd_fun_t)opkg_list_upgradable_cmd, PFM_SOURCE}, + {"list-upgradable", 0, (opkg_cmd_fun_t)opkg_list_upgradable_cmd, PFM_SOURCE}, + {"info", 0, (opkg_cmd_fun_t)opkg_info_cmd, 0}, +- {"flag", 1, (opkg_cmd_fun_t)opkg_flag_cmd, PFM_DESCRIPTION|PFM_SOURCE}, + {"status", 0, (opkg_cmd_fun_t)opkg_status_cmd, PFM_DESCRIPTION|PFM_SOURCE}, + {"install", 1, (opkg_cmd_fun_t)opkg_install_cmd, PFM_DESCRIPTION|PFM_SOURCE}, + {"remove", 1, (opkg_cmd_fun_t)opkg_remove_cmd, PFM_DESCRIPTION|PFM_SOURCE}, diff --git a/package/opkg/patches/011-old-config-location.patch b/package/opkg/patches/011-old-config-location.patch new file mode 100644 index 000000000..74a98ef4a --- /dev/null +++ b/package/opkg/patches/011-old-config-location.patch @@ -0,0 +1,14 @@ +--- a/src/opkg-cl.c ++++ b/src/opkg-cl.c +@@ -172,7 +172,10 @@ + printf("Confusion: getopt_long returned %d\n", c); + } + } +- ++ ++ if(!conf->conf_file) ++ conf->conf_file = xstrdup("/etc/opkg.conf"); ++ + if (parse_err) + return parse_err; + else diff --git a/package/opkg/patches/012-cleanup-tmpdir.patch b/package/opkg/patches/012-cleanup-tmpdir.patch new file mode 100644 index 000000000..e69de29bb diff --git a/package/ppp/files/ppp.sh b/package/ppp/files/ppp.sh index 8dfdab7a0..23fcb89ff 100644 --- a/package/ppp/files/ppp.sh +++ b/package/ppp/files/ppp.sh @@ -51,9 +51,16 @@ start_pppd() { interval="${keepalive##*[, ]}" [ "$interval" != "$keepalive" ] || interval=5 - config_get_bool peerdns "$cfg" peerdns 1 - [ "$peerdns" -eq 1 ] && peerdns="usepeerdns" || peerdns="" - + config_get_bool peerdns "$cfg" peerdns 1 + [ "$peerdns" -eq 1 ] && peerdns="usepeerdns" || { + peerdns="" + config_get dns "$config" dns + for dns in $dns; do + grep -q "$dns" /tmp/resolv.conf.auto 2>/dev/null || \ + echo "nameserver $dns" >> /tmp/resolv.conf.auto + done + } + config_get demand "$cfg" demand [ -n "$demand" ] && echo "nameserver 1.1.1.1" > /tmp/resolv.conf.auto diff --git a/package/qos-scripts/Makefile b/package/qos-scripts/Makefile index 65a759088..253e65dc4 100644 --- a/package/qos-scripts/Makefile +++ b/package/qos-scripts/Makefile @@ -18,7 +18,7 @@ include $(INCLUDE_DIR)/package.mk define Package/qos-scripts SECTION:=utils CATEGORY:=Base system - DEPENDS:=+tc +kmod-sched +iptables-mod-filter +iptables-mod-ipopt +iptables-mod-conntrack-extra +iptables-mod-imq + DEPENDS:=+tc +kmod-sched +iptables +iptables-mod-filter +iptables-mod-ipopt +iptables-mod-conntrack-extra +iptables-mod-imq TITLE:=QoS scripts PKGARCH:=all endef diff --git a/package/siit/Makefile b/package/siit/Makefile index f73e9584e..b94840c81 100644 --- a/package/siit/Makefile +++ b/package/siit/Makefile @@ -16,7 +16,7 @@ include $(INCLUDE_DIR)/package.mk define KernelPackage/siit SUBMENU:=Network Devices TITLE:=Stateless IP ICMP Translation Algorithm - DEPENDS:=@!LINUX_2_6_31 + DEPENDS:=@!LINUX_2_6_31 @(!(TARGET_ps3||TARGET_pxcab)||BROKEN) FILES:=$(PKG_BUILD_DIR)/siit.$(LINUX_KMOD_SUFFIX) AUTOLOAD:=$(call AutoLoad,50,siit) endef diff --git a/package/spidev_test/Makefile b/package/spidev_test/Makefile index eead4c14e..4750ba01b 100644 --- a/package/spidev_test/Makefile +++ b/package/spidev_test/Makefile @@ -16,7 +16,7 @@ include $(INCLUDE_DIR)/package.mk define Package/spidev-test SECTION:=utils CATEGORY:=Utilities - DEPENDS:=@LINUX_2_6 + DEPENDS:=@LINUX_2_6 +kmod-spi-dev TITLE:=SPI testing utility VERSION:=$(LINUX_VERSION)-$(PKG_RELEASE) URL:=http://www.kernel.org diff --git a/package/uboot-ifxmips/files/board/ifx/danube/flash.c b/package/uboot-ifxmips/files/board/ifx/danube/flash.c index f8a543dbe..bc919c1c1 100644 --- a/package/uboot-ifxmips/files/board/ifx/danube/flash.c +++ b/package/uboot-ifxmips/files/board/ifx/danube/flash.c @@ -83,21 +83,25 @@ unsigned long flash_init (void) unsigned long size = 0; int i; + printf("%s:%s[%d]\n", __FILE__, __func__, __LINE__); /* Init: no FLASHes known */ for (i=0; i < CFG_MAX_FLASH_BANKS; ++i) { // 1 bank ulong flashbase = (i == 0) ? PHYS_FLASH_1 : PHYS_FLASH_2; // 0xb0000000, 0xb4000000 - volatile ulong * buscon = (ulong *) + printf("%s:%s[%d]\n", __FILE__, __func__, __LINE__); + volatile ulong * buscon = (ulong *) ((i == 0) ? DANUBE_EBU_BUSCON0 : DANUBE_EBU_BUSCON1); /* Disable write protection */ // *buscon &= ~AMAZON_EBU_BUSCON0_WRDIS; /* Enable write protection */ *buscon |= DANUBE_EBU_BUSCON0_WRDIS; +printf("%s:%s[%d]\n", __FILE__, __func__, __LINE__); #if 1 memset(&flash_info[i], 0, sizeof(flash_info_t)); #endif +printf("%s:%s[%d]\n", __FILE__, __func__, __LINE__); flash_info[i].size = flash_get_size((FPW *)flashbase, &flash_info[i]); @@ -227,6 +231,22 @@ static void flash_get_offsets (ulong base, flash_info_t *info) bootsect_size = 0x00002000 * (sizeof(FPW)/2); sect_size = 0x00010000 * (sizeof(FPW)/2); + /* set sector offsets for bottom boot block type */ + for (i = 0; i < 8; ++i) { + info->start[i] = base + (i * bootsect_size); + } + for (i = 8; i < info->sector_count; i++) { + info->start[i] = base + ((i - 7) * sect_size); + } + } + else if(((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_AMD) + && ((info->flash_id & FLASH_TYPEMASK)==FLASH_29LV320B)){ + int bootsect_size; /* number of bytes/boot sector */ + int sect_size; /* number of bytes/regular sector */ + + bootsect_size = 0x00002000 * (sizeof(FPW)/2); + sect_size = 0x00010000 * (sizeof(FPW)/2); + /* set sector offsets for bottom boot block type */ for (i = 0; i < 8; ++i) { info->start[i] = base + (i * bootsect_size); @@ -378,6 +398,7 @@ void flash_print_info (flash_info_t *info) case FLASH_29LV640BB: //liupeng for MXIC FLASH_29LV640BB fmt = "29LV640BB (64 Mbit, boot sector SA0~SA126 size 64k bytes,other sectors SA127~SA135 size 8k bytes)\n"; break; + case FLASH_29LV320B: //joelin for MXIC FLASH_29LV320AB case FLASH_29LV320AB: //joelin for MXIC FLASH_29LV320AB fmt = "29LV320AB (32 Mbit, boot sector SA0~SA7 size 8K bytes,other sectors SA8~SA70 size 64K bytes)\n"; break; @@ -437,24 +458,28 @@ ulong flash_get_size (FPWV *addr, flash_info_t *info) * This works for any bus width and any FLASH device width. */ -// printf("\n type is %08lx", addr[1] & 0xff); //joelin 10/06/2004 flash type -// printf("\n type is %08lx", addr[0] & 0xff); //joelin 10/06/2004 flash type + printf("\n type is %08lx", addr[1] & 0xff); //joelin 10/06/2004 flash type + printf("\n type is %08lx", addr[0] & 0xff); //joelin 10/06/2004 flash type // asm("SYNC"); switch (addr[1] & 0xff) { case (uchar)AMD_MANUFACT: + printf("%s:%s[%d]\n", __FILE__, __func__, __LINE__); info->flash_id = FLASH_MAN_AMD; break; case (uchar)INTEL_MANUFACT: // 0x0089 + printf("%s:%s[%d]\n", __FILE__, __func__, __LINE__); info->flash_id = FLASH_MAN_INTEL; //0x00300000 break; //joelin for MXIC case (uchar)MX_MANUFACT: // 0x00c2 + printf("%s:%s[%d]\n", __FILE__, __func__, __LINE__); info->flash_id = FLASH_MAN_MX ;//0x00030000 break; default: + printf("%s:%s[%d]\n", __FILE__, __func__, __LINE__); info->flash_id = FLASH_UNKNOWN; info->sector_count = 0; info->size = 0; @@ -464,8 +489,15 @@ ulong flash_get_size (FPWV *addr, flash_info_t *info) break;*/ } + printf("%s:%s[%d] %08lx\n", __FILE__, __func__, __LINE__, addr[0]); /* Check 16 bits or 32 bits of ID so work on 32 or 16 bit bus. */ if (info->flash_id != FLASH_UNKNOWN) switch (addr[0]) { + case (FPW)EON_ID_EN29LV320B: + printf("%s:%s[%d]\n", __FILE__, __func__, __LINE__); + info->flash_id += FLASH_29LV320B; + info->sector_count = 71; + info->size = 0x00400000 * (sizeof(FPW)/2); + break; case (FPW)AMD_ID_LV640U: /* 29LV640 and 29LV641 have same ID */ info->flash_id += FLASH_AM640U; info->sector_count = 128; @@ -606,6 +638,7 @@ int flash_erase (flash_info_t *info, int s_first, int s_last) case FLASH_28F320J3A: case FLASH_AM640U: case FLASH_29LV640BB: //liupeng for MXIC MX29LV640BB + case FLASH_29LV320B: case FLASH_29LV320AB: //joelin for MXIC MX29LV320AB case FLASH_29LV160BB: //joelin for MXIC MX29LV160BB break; diff --git a/package/uboot-ifxmips/files/include/configs/danube.h b/package/uboot-ifxmips/files/include/configs/danube.h index ed95f3361..cd2d247fe 100644 --- a/package/uboot-ifxmips/files/include/configs/danube.h +++ b/package/uboot-ifxmips/files/include/configs/danube.h @@ -36,10 +36,10 @@ #ifdef DANUBE_USE_DDR_RAM //#define DANUBE_DDR_RAM_111M -#define DANUBE_DDR_RAM_166M +//#define DANUBE_DDR_RAM_166M //#define PROMOSDDR400 //#define DDR_SAMSUNG_166M -//#define DDR_PSC_166M +#define DDR_PSC_166M //#define DANUBE_DDR_RAM_133M #define DANUBE_DDR_RAM_SIZE 32 /* 32M DDR-DRAM for reference board */ #endif diff --git a/package/uboot-ifxmips/patches/100-ifx.patch b/package/uboot-ifxmips/patches/100-ifx.patch index 01a5884db..5b0859c3b 100644 --- a/package/uboot-ifxmips/patches/100-ifx.patch +++ b/package/uboot-ifxmips/patches/100-ifx.patch @@ -1,7 +1,7 @@ Index: u-boot-1.1.5/Makefile =================================================================== --- u-boot-1.1.5.orig/Makefile 2006-10-20 17:54:33.000000000 +0200 -+++ u-boot-1.1.5/Makefile 2009-10-04 23:06:03.000000000 +0200 ++++ u-boot-1.1.5/Makefile 2009-11-09 16:35:03.000000000 +0100 @@ -24,7 +24,7 @@ VERSION = 1 PATCHLEVEL = 1 @@ -249,7 +249,7 @@ Index: u-boot-1.1.5/Makefile Index: u-boot-1.1.5/common/cmd_bootm.c =================================================================== --- u-boot-1.1.5.orig/common/cmd_bootm.c 2006-10-20 17:54:33.000000000 +0200 -+++ u-boot-1.1.5/common/cmd_bootm.c 2009-10-04 23:06:03.000000000 +0200 ++++ u-boot-1.1.5/common/cmd_bootm.c 2009-11-09 16:35:03.000000000 +0100 @@ -31,6 +31,7 @@ #include #include @@ -336,7 +336,7 @@ Index: u-boot-1.1.5/common/cmd_bootm.c Index: u-boot-1.1.5/common/cmd_flash.c =================================================================== --- u-boot-1.1.5.orig/common/cmd_flash.c 2006-10-20 17:54:33.000000000 +0200 -+++ u-boot-1.1.5/common/cmd_flash.c 2009-10-04 23:06:03.000000000 +0200 ++++ u-boot-1.1.5/common/cmd_flash.c 2009-11-09 16:35:03.000000000 +0100 @@ -196,9 +196,17 @@ } @@ -657,7 +657,7 @@ Index: u-boot-1.1.5/common/cmd_flash.c Index: u-boot-1.1.5/common/cmd_nvedit.c =================================================================== --- u-boot-1.1.5.orig/common/cmd_nvedit.c 2006-10-20 17:54:33.000000000 +0200 -+++ u-boot-1.1.5/common/cmd_nvedit.c 2009-10-04 23:06:03.000000000 +0200 ++++ u-boot-1.1.5/common/cmd_nvedit.c 2009-11-09 16:35:03.000000000 +0100 @@ -540,8 +540,19 @@ extern char * env_name_spec; @@ -682,7 +682,7 @@ Index: u-boot-1.1.5/common/cmd_nvedit.c Index: u-boot-1.1.5/common/console.c =================================================================== --- u-boot-1.1.5.orig/common/console.c 2006-10-20 17:54:33.000000000 +0200 -+++ u-boot-1.1.5/common/console.c 2009-10-04 23:06:03.000000000 +0200 ++++ u-boot-1.1.5/common/console.c 2009-11-09 16:35:03.000000000 +0100 @@ -324,7 +324,7 @@ #endif @@ -717,7 +717,7 @@ Index: u-boot-1.1.5/common/console.c Index: u-boot-1.1.5/common/devices.c =================================================================== --- u-boot-1.1.5.orig/common/devices.c 2006-10-20 17:54:33.000000000 +0200 -+++ u-boot-1.1.5/common/devices.c 2009-10-04 23:06:03.000000000 +0200 ++++ u-boot-1.1.5/common/devices.c 2009-11-09 16:35:03.000000000 +0100 @@ -39,6 +39,7 @@ list_t devlist = 0; device_t *stdio_devices[] = { NULL, NULL, NULL }; @@ -735,7 +735,7 @@ Index: u-boot-1.1.5/common/devices.c Index: u-boot-1.1.5/common/env_common.c =================================================================== --- u-boot-1.1.5.orig/common/env_common.c 2006-10-20 17:54:33.000000000 +0200 -+++ u-boot-1.1.5/common/env_common.c 2009-10-04 23:06:03.000000000 +0200 ++++ u-boot-1.1.5/common/env_common.c 2009-11-09 16:35:03.000000000 +0100 @@ -219,7 +219,9 @@ * We must allocate a buffer for the environment */ @@ -784,7 +784,7 @@ Index: u-boot-1.1.5/common/env_common.c Index: u-boot-1.1.5/common/env_flash.c =================================================================== --- u-boot-1.1.5.orig/common/env_flash.c 2006-10-20 17:54:33.000000000 +0200 -+++ u-boot-1.1.5/common/env_flash.c 2009-10-04 23:06:03.000000000 +0200 ++++ u-boot-1.1.5/common/env_flash.c 2009-11-09 16:35:03.000000000 +0100 @@ -66,7 +66,6 @@ #endif @@ -874,7 +874,7 @@ Index: u-boot-1.1.5/common/env_flash.c Index: u-boot-1.1.5/config.mk =================================================================== --- u-boot-1.1.5.orig/config.mk 2006-10-20 17:54:33.000000000 +0200 -+++ u-boot-1.1.5/config.mk 2009-10-04 23:32:51.000000000 +0200 ++++ u-boot-1.1.5/config.mk 2009-11-09 16:35:03.000000000 +0100 @@ -127,10 +127,15 @@ OBJDUMP = $(CROSS_COMPILE)objdump RANLIB = $(CROSS_COMPILE)RANLIB @@ -964,7 +964,7 @@ Index: u-boot-1.1.5/config.mk Index: u-boot-1.1.5/drivers/Makefile =================================================================== --- u-boot-1.1.5.orig/drivers/Makefile 2006-10-20 17:54:33.000000000 +0200 -+++ u-boot-1.1.5/drivers/Makefile 2009-10-04 23:06:03.000000000 +0200 ++++ u-boot-1.1.5/drivers/Makefile 2009-11-09 16:35:03.000000000 +0100 @@ -50,7 +50,7 @@ videomodes.o w83c553f.o \ ks8695eth.o \ @@ -977,7 +977,7 @@ Index: u-boot-1.1.5/drivers/Makefile Index: u-boot-1.1.5/include/asm-mips/mipsregs.h =================================================================== --- u-boot-1.1.5.orig/include/asm-mips/mipsregs.h 2006-10-20 17:54:33.000000000 +0200 -+++ u-boot-1.1.5/include/asm-mips/mipsregs.h 2009-10-04 23:06:03.000000000 +0200 ++++ u-boot-1.1.5/include/asm-mips/mipsregs.h 2009-11-09 16:35:03.000000000 +0100 @@ -48,6 +48,7 @@ #define CP0_CAUSE $13 #define CP0_EPC $14 @@ -1048,7 +1048,7 @@ Index: u-boot-1.1.5/include/asm-mips/mipsregs.h Index: u-boot-1.1.5/include/cmd_confdefs.h =================================================================== --- u-boot-1.1.5.orig/include/cmd_confdefs.h 2006-10-20 17:54:33.000000000 +0200 -+++ u-boot-1.1.5/include/cmd_confdefs.h 2009-10-04 23:06:03.000000000 +0200 ++++ u-boot-1.1.5/include/cmd_confdefs.h 2009-11-09 16:35:03.000000000 +0100 @@ -94,6 +94,7 @@ #define CFG_CMD_EXT2 0x1000000000000000ULL /* EXT2 Support */ #define CFG_CMD_SNTP 0x2000000000000000ULL /* SNTP support */ @@ -1068,14 +1068,14 @@ Index: u-boot-1.1.5/include/cmd_confdefs.h Index: u-boot-1.1.5/include/config.h =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ u-boot-1.1.5/include/config.h 2009-10-04 23:06:04.000000000 +0200 ++++ u-boot-1.1.5/include/config.h 2009-11-09 16:35:03.000000000 +0100 @@ -0,0 +1,2 @@ +/* Automatically generated - do not edit */ +#include Index: u-boot-1.1.5/include/config.mk =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ u-boot-1.1.5/include/config.mk 2009-10-04 23:06:04.000000000 +0200 ++++ u-boot-1.1.5/include/config.mk 2009-11-09 16:35:03.000000000 +0100 @@ -0,0 +1,5 @@ +ARCH = mips +CPU = mips @@ -1085,7 +1085,7 @@ Index: u-boot-1.1.5/include/config.mk Index: u-boot-1.1.5/include/flash.h =================================================================== --- u-boot-1.1.5.orig/include/flash.h 2006-10-20 17:54:33.000000000 +0200 -+++ u-boot-1.1.5/include/flash.h 2009-10-04 23:06:03.000000000 +0200 ++++ u-boot-1.1.5/include/flash.h 2009-11-09 16:36:11.000000000 +0100 @@ -79,7 +79,7 @@ extern unsigned long flash_init (void); extern void flash_print_info (flash_info_t *); @@ -1095,7 +1095,18 @@ Index: u-boot-1.1.5/include/flash.h extern int flash_sect_protect (int flag, ulong addr_first, ulong addr_last); /* common/flash.c */ -@@ -299,6 +299,10 @@ +@@ -131,7 +131,9 @@ + #define MT2_MANUFACT 0x002C002C /* alternate MICRON manufacturer ID*/ + #define EXCEL_MANUFACT 0x004A004A /* Excel Semiconductor */ + +- /* Micron Technologies (INTEL compat.) */ ++#define EON_ID_EN29LV320B 0x22f9 ++#define FLASH_29LV320B 0xE0 ++/* Micron Technologies (INTEL compat.) */ + #define MT_ID_28F400_T 0x44704470 /* 28F400B3 ID ( 4 M, top boot sector) */ + #define MT_ID_28F400_B 0x44714471 /* 28F400B3 ID ( 4 M, bottom boot sect) */ + +@@ -299,6 +301,10 @@ #define TOSH_ID_FVT160 0xC2 /* TC58FVT160 ID (16 M, top ) */ #define TOSH_ID_FVB160 0x43 /* TC58FVT160 ID (16 M, bottom ) */ @@ -1106,7 +1117,7 @@ Index: u-boot-1.1.5/include/flash.h /*----------------------------------------------------------------------- * Internal FLASH identification codes * -@@ -422,6 +426,10 @@ +@@ -422,6 +428,10 @@ #define FLASH_S29GL064M 0x00F0 /* Spansion S29GL064M-R6 */ #define FLASH_S29GL128N 0x00F1 /* Spansion S29GL128N */ @@ -1120,7 +1131,7 @@ Index: u-boot-1.1.5/include/flash.h Index: u-boot-1.1.5/include/image.h =================================================================== --- u-boot-1.1.5.orig/include/image.h 2006-10-20 17:54:33.000000000 +0200 -+++ u-boot-1.1.5/include/image.h 2009-10-04 23:06:03.000000000 +0200 ++++ u-boot-1.1.5/include/image.h 2009-11-09 16:35:03.000000000 +0100 @@ -132,6 +132,7 @@ #define IH_COMP_NONE 0 /* No Compression Used */ #define IH_COMP_GZIP 1 /* gzip Compression Used */ @@ -1132,7 +1143,7 @@ Index: u-boot-1.1.5/include/image.h Index: u-boot-1.1.5/include/syscall.h =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ u-boot-1.1.5/include/syscall.h 2009-10-04 23:06:03.000000000 +0200 ++++ u-boot-1.1.5/include/syscall.h 2009-11-09 16:35:03.000000000 +0100 @@ -0,0 +1,42 @@ +#ifndef __MON_SYS_CALL_H__ +#define __MON_SYS_CALL_H__ @@ -1179,7 +1190,7 @@ Index: u-boot-1.1.5/include/syscall.h Index: u-boot-1.1.5/ld_uboot.conf =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ u-boot-1.1.5/ld_uboot.conf 2009-10-04 23:06:03.000000000 +0200 ++++ u-boot-1.1.5/ld_uboot.conf 2009-11-09 16:35:03.000000000 +0100 @@ -0,0 +1,8 @@ +TAG_DWNLD() +{ @@ -1192,7 +1203,7 @@ Index: u-boot-1.1.5/ld_uboot.conf Index: u-boot-1.1.5/lib_generic/Makefile =================================================================== --- u-boot-1.1.5.orig/lib_generic/Makefile 2006-10-20 17:54:33.000000000 +0200 -+++ u-boot-1.1.5/lib_generic/Makefile 2009-10-04 23:06:03.000000000 +0200 ++++ u-boot-1.1.5/lib_generic/Makefile 2009-11-09 16:35:03.000000000 +0100 @@ -28,7 +28,7 @@ COBJS = bzlib.o bzlib_crctable.o bzlib_decompress.o \ bzlib_randtable.o bzlib_huffman.o \ @@ -1205,7 +1216,7 @@ Index: u-boot-1.1.5/lib_generic/Makefile Index: u-boot-1.1.5/lib_mips/board.c =================================================================== --- u-boot-1.1.5.orig/lib_mips/board.c 2006-10-20 17:54:33.000000000 +0200 -+++ u-boot-1.1.5/lib_mips/board.c 2009-10-04 23:06:03.000000000 +0200 ++++ u-boot-1.1.5/lib_mips/board.c 2009-11-09 16:35:03.000000000 +0100 @@ -29,9 +29,30 @@ #include #include @@ -1657,7 +1668,7 @@ Index: u-boot-1.1.5/lib_mips/board.c Index: u-boot-1.1.5/lib_mips/time.c =================================================================== --- u-boot-1.1.5.orig/lib_mips/time.c 2006-10-20 17:54:33.000000000 +0200 -+++ u-boot-1.1.5/lib_mips/time.c 2009-10-04 23:06:03.000000000 +0200 ++++ u-boot-1.1.5/lib_mips/time.c 2009-11-09 16:35:03.000000000 +0100 @@ -80,6 +80,19 @@ /*NOP*/; } @@ -1681,7 +1692,7 @@ Index: u-boot-1.1.5/lib_mips/time.c Index: u-boot-1.1.5/net/eth.c =================================================================== --- u-boot-1.1.5.orig/net/eth.c 2006-10-20 17:54:33.000000000 +0200 -+++ u-boot-1.1.5/net/eth.c 2009-10-04 23:06:03.000000000 +0200 ++++ u-boot-1.1.5/net/eth.c 2009-11-09 16:35:03.000000000 +0100 @@ -25,6 +25,9 @@ #include #include @@ -1716,7 +1727,7 @@ Index: u-boot-1.1.5/net/eth.c Index: u-boot-1.1.5/tools/mkimage.c =================================================================== --- u-boot-1.1.5.orig/tools/mkimage.c 2006-10-20 17:54:33.000000000 +0200 -+++ u-boot-1.1.5/tools/mkimage.c 2009-10-04 23:06:03.000000000 +0200 ++++ u-boot-1.1.5/tools/mkimage.c 2009-11-09 16:35:03.000000000 +0100 @@ -28,6 +28,7 @@ #ifndef __WIN32__ #include /* for host / network byte order conversions */ @@ -1754,7 +1765,7 @@ Index: u-boot-1.1.5/tools/mkimage.c Index: u-boot-1.1.5/cpu/mips/cache.S =================================================================== --- u-boot-1.1.5.orig/cpu/mips/cache.S 2006-10-20 17:54:33.000000000 +0200 -+++ u-boot-1.1.5/cpu/mips/cache.S 2009-10-04 23:06:03.000000000 +0200 ++++ u-boot-1.1.5/cpu/mips/cache.S 2009-11-09 16:35:03.000000000 +0100 @@ -29,7 +29,9 @@ #include #include @@ -1797,7 +1808,7 @@ Index: u-boot-1.1.5/cpu/mips/cache.S Index: u-boot-1.1.5/cpu/mips/config.mk =================================================================== --- u-boot-1.1.5.orig/cpu/mips/config.mk 2006-10-20 17:54:33.000000000 +0200 -+++ u-boot-1.1.5/cpu/mips/config.mk 2009-10-04 23:06:03.000000000 +0200 ++++ u-boot-1.1.5/cpu/mips/config.mk 2009-11-09 16:35:03.000000000 +0100 @@ -20,20 +20,26 @@ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, # MA 02111-1307 USA @@ -1836,7 +1847,7 @@ Index: u-boot-1.1.5/cpu/mips/config.mk Index: u-boot-1.1.5/cpu/mips/cpu.c =================================================================== --- u-boot-1.1.5.orig/cpu/mips/cpu.c 2006-10-20 17:54:33.000000000 +0200 -+++ u-boot-1.1.5/cpu/mips/cpu.c 2009-10-04 23:06:03.000000000 +0200 ++++ u-boot-1.1.5/cpu/mips/cpu.c 2009-11-09 16:35:03.000000000 +0100 @@ -23,7 +23,12 @@ #include @@ -1863,7 +1874,7 @@ Index: u-boot-1.1.5/cpu/mips/cpu.c Index: u-boot-1.1.5/cpu/mips/incaip_clock.c =================================================================== --- u-boot-1.1.5.orig/cpu/mips/incaip_clock.c 2006-10-20 17:54:33.000000000 +0200 -+++ u-boot-1.1.5/cpu/mips/incaip_clock.c 2009-10-04 23:06:03.000000000 +0200 ++++ u-boot-1.1.5/cpu/mips/incaip_clock.c 2009-11-09 16:35:03.000000000 +0100 @@ -22,8 +22,9 @@ */ @@ -1884,7 +1895,7 @@ Index: u-boot-1.1.5/cpu/mips/incaip_clock.c Index: u-boot-1.1.5/cpu/mips/start.S =================================================================== --- u-boot-1.1.5.orig/cpu/mips/start.S 2006-10-20 17:54:33.000000000 +0200 -+++ u-boot-1.1.5/cpu/mips/start.S 2009-10-04 23:06:03.000000000 +0200 ++++ u-boot-1.1.5/cpu/mips/start.S 2009-11-09 16:35:03.000000000 +0100 @@ -27,7 +27,9 @@ #include #include @@ -2137,7 +2148,7 @@ Index: u-boot-1.1.5/cpu/mips/start.S Index: u-boot-1.1.5/tools/Makefile =================================================================== --- u-boot-1.1.5.orig/tools/Makefile 2006-10-20 17:54:33.000000000 +0200 -+++ u-boot-1.1.5/tools/Makefile 2009-10-04 23:06:03.000000000 +0200 ++++ u-boot-1.1.5/tools/Makefile 2009-11-09 16:35:03.000000000 +0100 @@ -21,7 +21,7 @@ # MA 02111-1307 USA # diff --git a/package/wpa_supplicant/files/wpa_supplicant.sh b/package/wpa_supplicant/files/wpa_supplicant.sh index 5053d1e28..1d1367a17 100644 --- a/package/wpa_supplicant/files/wpa_supplicant.sh +++ b/package/wpa_supplicant/files/wpa_supplicant.sh @@ -1,25 +1,31 @@ wpa_supplicant_setup_vif() { local vif="$1" local driver="$2" - + local key="$key" + # wpa_supplicant should use wext for mac80211 cards [ "$driver" = "mac80211" ] && driver='wext' + # make sure we have the psk + [ -n "$key" ] || { + config_get key "$vif" key + } + case "$enc" in - PSK|psk|psk2|PSK2) + *psk*) key_mgmt='WPA-PSK' config_get_bool usepassphrase "$vif" passphrase 1 case "$enc" in - psk|PSK) - proto='WPA' + *psk2*) + proto='RSN' if [ "$usepassphrase" = "1" ]; then passphrase="psk=\"${key}\"" else passphrase="psk=${key}" fi ;; - psk2|PSK2) - proto='RSN' + *psk*) + proto='WPA' if [ "$usepassphrase" = "1" ]; then passphrase="psk=\"${key}\"" else @@ -28,13 +34,13 @@ wpa_supplicant_setup_vif() { ;; esac ;; - WPA|wpa|WPA2|wpa2|8021x|8021X) + *wpa*|*8021x*) proto='WPA2' key_mgmt='WPA-EAP' config_get ca_cert "$vif" ca_cert ca_cert=${ca_cert:+"ca_cert=\"$ca_cert\""} case "$eap_type" in - tls|TLS) + tls) pairwise='pairwise=CCMP' group='group=CCMP' config_get priv_key "$vif" priv_key @@ -42,7 +48,7 @@ wpa_supplicant_setup_vif() { priv_key="private_key=\"$priv_key\"" priv_key_pwd="private_key_passwd=\"$priv_key_pwd\"" ;; - peap|PEAP|ttls|TTLS) + peap|ttls) config_get auth "$vif" auth config_get identity "$vif" identity config_get password "$vif" password diff --git a/package/wpa_supplicant/patches/150-Remove-PS3-gelic-legacy-wpa-support.patch b/package/wpa_supplicant/patches/150-Remove-PS3-gelic-legacy-wpa-support.patch new file mode 100644 index 000000000..94559f1b3 --- /dev/null +++ b/package/wpa_supplicant/patches/150-Remove-PS3-gelic-legacy-wpa-support.patch @@ -0,0 +1,251 @@ +From 67441c596f016f69c230eaa31ecb2272c6cbf4bf Mon Sep 17 00:00:00 2001 +From: Hamish Guthrie +Date: Wed, 6 Jan 2010 10:00:22 +0100 +Subject: [PATCH] Remove PS3 gelic legacy wpa support + +The ps3 wireless driver now supports wireless extensions. There is dedicated support code in wpa_supplicant for the old gelic wireless driver. The current gelic driver retains the old API with CONFIG_GELIC_WIRELESS_OLD_PSK_INTERFACE, which is being removed from the driver. + +Signed-off-by: Hamish Guthrie +--- + src/drivers/driver_ps3.c | 186 ---------------------------------------------- + src/drivers/drivers.c | 6 -- + wpa_supplicant/Makefile | 6 -- + 3 files changed, 0 insertions(+), 198 deletions(-) + delete mode 100644 src/drivers/driver_ps3.c + +diff --git a/src/drivers/driver_ps3.c b/src/drivers/driver_ps3.c +deleted file mode 100644 +index fde3425..0000000 +--- a/src/drivers/driver_ps3.c ++++ /dev/null +@@ -1,186 +0,0 @@ +-/* +- * WPA Supplicant - PS3 Linux wireless extension driver interface +- * Copyright 2007, 2008 Sony Corporation +- * +- * 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. +- * +- * Alternatively, this software may be distributed under the terms of BSD +- * license. +- * +- * See README and COPYING for more details. +- */ +- +-#include "includes.h" +-#include +-#include "wireless_copy.h" +-#include "common.h" +-#include "wpa_common.h" +-#include "driver.h" +-#include "eloop.h" +-#include "driver_wext.h" +-#include "ieee802_11_defs.h" +- +-static int wpa_driver_ps3_set_wpa_key(struct wpa_driver_wext_data *drv, +- struct wpa_driver_associate_params *params) +-{ +- int ret, i; +- struct iwreq iwr; +- char *buf, *str; +- +- if (!params->psk && !params->passphrase) { +- wpa_printf(MSG_INFO, "%s:no PSK error", __func__); +- return -EINVAL; +- } +- +- os_memset(&iwr, 0, sizeof(iwr)); +- if (params->psk) { +- /* includes null */ +- iwr.u.data.length = PMK_LEN * 2 + 1; +- buf = os_malloc(iwr.u.data.length); +- if (!buf) +- return -ENOMEM; +- str = buf; +- for (i = 0; i < PMK_LEN; i++) { +- str += snprintf(str, iwr.u.data.length - (str - buf), +- "%02x", params->psk[i]); +- } +- } else if (params->passphrase) { +- /* including quotations and null */ +- iwr.u.data.length = strlen(params->passphrase) + 3; +- buf = os_malloc(iwr.u.data.length); +- if (!buf) +- return -ENOMEM; +- buf[0] = '"'; +- os_memcpy(buf + 1, params->passphrase, iwr.u.data.length - 3); +- buf[iwr.u.data.length - 2] = '"'; +- buf[iwr.u.data.length - 1] = '\0'; +- } else +- return -EINVAL; +- iwr.u.data.pointer = (caddr_t) buf; +- os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); +- ret = ioctl(drv->ioctl_sock, SIOCIWFIRSTPRIV, &iwr); +- os_free(buf); +- +- return ret; +-} +- +-static int wpa_driver_ps3_set_wep_keys(struct wpa_driver_wext_data *drv, +- struct wpa_driver_associate_params *params) +-{ +- int ret, i; +- struct iwreq iwr; +- +- for (i = 0; i < 4; i++) { +- os_memset(&iwr, 0, sizeof(iwr)); +- os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); +- iwr.u.encoding.flags = i + 1; +- if (params->wep_key_len[i]) { +- iwr.u.encoding.pointer = (caddr_t) params->wep_key[i]; +- iwr.u.encoding.length = params->wep_key_len[i]; +- } else +- iwr.u.encoding.flags = IW_ENCODE_NOKEY | +- IW_ENCODE_DISABLED; +- +- if (ioctl(drv->ioctl_sock, SIOCSIWENCODE, &iwr) < 0) { +- perror("ioctl[SIOCSIWENCODE]"); +- ret = -1; +- } +- } +- return ret; +-} +- +-static int wpa_driver_ps3_associate(void *priv, +- struct wpa_driver_associate_params *params) +-{ +- struct wpa_driver_wext_data *drv = priv; +- int ret, value; +- +- wpa_printf(MSG_DEBUG, "%s: <-", __func__); +- +- /* clear BSSID */ +- if (!params->bssid && +- wpa_driver_wext_set_bssid(drv, NULL) < 0) +- ret = -1; +- +- if (wpa_driver_wext_set_mode(drv, params->mode) < 0) +- ret = -1; +- +- if (params->wpa_ie == NULL || params->wpa_ie_len == 0) +- value = IW_AUTH_WPA_VERSION_DISABLED; +- else if (params->wpa_ie[0] == WLAN_EID_RSN) +- value = IW_AUTH_WPA_VERSION_WPA2; +- else +- value = IW_AUTH_WPA_VERSION_WPA; +- if (wpa_driver_wext_set_auth_param(drv, +- IW_AUTH_WPA_VERSION, value) < 0) +- ret = -1; +- value = wpa_driver_wext_cipher2wext(params->pairwise_suite); +- if (wpa_driver_wext_set_auth_param(drv, +- IW_AUTH_CIPHER_PAIRWISE, value) < 0) +- ret = -1; +- value = wpa_driver_wext_cipher2wext(params->group_suite); +- if (wpa_driver_wext_set_auth_param(drv, +- IW_AUTH_CIPHER_GROUP, value) < 0) +- ret = -1; +- value = wpa_driver_wext_keymgmt2wext(params->key_mgmt_suite); +- if (wpa_driver_wext_set_auth_param(drv, IW_AUTH_KEY_MGMT, value) < 0) +- ret = -1; +- +- /* set selected BSSID */ +- if (params->bssid && +- wpa_driver_wext_set_bssid(drv, params->bssid) < 0) +- ret = -1; +- +- switch (params->group_suite) { +- case CIPHER_NONE: +- ret = 0; +- break; +- case CIPHER_WEP40: +- case CIPHER_WEP104: +- ret = wpa_driver_ps3_set_wep_keys(drv, params); +- break; +- case CIPHER_TKIP: +- case CIPHER_CCMP: +- ret = wpa_driver_ps3_set_wpa_key(drv, params); +- break; +- } +- +- /* start to associate */ +- ret = wpa_driver_wext_set_ssid(drv, params->ssid, params->ssid_len); +- +- wpa_printf(MSG_DEBUG, "%s: ->", __func__); +- +- return ret; +-} +- +-static int wpa_driver_ps3_get_capa(void *priv, struct wpa_driver_capa *capa) +-{ +- int ret; +- wpa_printf(MSG_DEBUG, "%s:<-", __func__); +- +- ret = wpa_driver_wext_get_capa(priv, capa); +- if (ret) { +- wpa_printf(MSG_INFO, "%s: base wext returns error %d", +- __func__, ret); +- return ret; +- } +- /* PS3 hypervisor does association and 4way handshake by itself */ +- capa->flags |= WPA_DRIVER_FLAGS_4WAY_HANDSHAKE; +- wpa_printf(MSG_DEBUG, "%s:->", __func__); +- return 0; +-} +- +-const struct wpa_driver_ops wpa_driver_ps3_ops = { +- .name = "ps3", +- .desc = "PLAYSTATION3 Linux wireless extension driver", +- .get_bssid = wpa_driver_wext_get_bssid, +- .get_ssid = wpa_driver_wext_get_ssid, +- .scan = wpa_driver_wext_scan, +- .get_scan_results2 = wpa_driver_wext_get_scan_results, +- .associate = wpa_driver_ps3_associate, /* PS3 */ +- .init = wpa_driver_wext_init, +- .deinit = wpa_driver_wext_deinit, +- .get_capa = wpa_driver_ps3_get_capa, /* PS3 */ +-}; +diff --git a/src/drivers/drivers.c b/src/drivers/drivers.c +index d278797..7e7d720 100644 +--- a/src/drivers/drivers.c ++++ b/src/drivers/drivers.c +@@ -64,9 +64,6 @@ extern struct wpa_driver_ops wpa_driver_ralink_ops; /* driver_ralink.c */ + #ifdef CONFIG_DRIVER_OSX + extern struct wpa_driver_ops wpa_driver_osx_ops; /* driver_osx.m */ + #endif /* CONFIG_DRIVER_OSX */ +-#ifdef CONFIG_DRIVER_PS3 +-extern struct wpa_driver_ops wpa_driver_ps3_ops; /* driver_ps3.c */ +-#endif /* CONFIG_DRIVER_PS3 */ + #ifdef CONFIG_DRIVER_IPHONE + extern struct wpa_driver_ops wpa_driver_iphone_ops; /* driver_iphone.m */ + #endif /* CONFIG_DRIVER_IPHONE */ +@@ -126,9 +123,6 @@ struct wpa_driver_ops *wpa_supplicant_drivers[] = + #ifdef CONFIG_DRIVER_OSX + &wpa_driver_osx_ops, + #endif /* CONFIG_DRIVER_OSX */ +-#ifdef CONFIG_DRIVER_PS3 +- &wpa_driver_ps3_ops, +-#endif /* CONFIG_DRIVER_PS3 */ + #ifdef CONFIG_DRIVER_IPHONE + &wpa_driver_iphone_ops, + #endif /* CONFIG_DRIVER_IPHONE */ +diff --git a/wpa_supplicant/Makefile b/wpa_supplicant/Makefile +index 45d6ada..f131e92 100644 +--- a/wpa_supplicant/Makefile ++++ b/wpa_supplicant/Makefile +@@ -226,12 +226,6 @@ LDFLAGS += -framework CoreFoundation + LDFLAGS += -F/System/Library/PrivateFrameworks -framework Apple80211 + endif + +-ifdef CONFIG_DRIVER_PS3 +-CFLAGS += -DCONFIG_DRIVER_PS3 -m64 +-OBJS_d += ../src/drivers/driver_ps3.o +-LDFLAGS += -m64 +-endif +- + ifdef CONFIG_DRIVER_IPHONE + CFLAGS += -DCONFIG_DRIVER_IPHONE + OBJS_d += ../src/drivers/driver_iphone.o +-- +1.6.2.4 + diff --git a/package/wprobe/Makefile b/package/wprobe/Makefile index 536a85eb2..85667b771 100644 --- a/package/wprobe/Makefile +++ b/package/wprobe/Makefile @@ -18,9 +18,17 @@ PKG_CONFIG_DEPENDS = \ include $(INCLUDE_DIR)/package.mk +# XXX: build failure on cris +# wprobe-lib.c:145: error: 'packed' attribute ignored for field of type 'struct ' +# wprobe-lib.c:149: error: 'packed' attribute ignored for field of type 'struct ' + +define Package/wprobe/Default + DEPENDS:=@LINUX_2_6 @(!(TARGET_ps3||TARGET_pxcab||cris)||BROKEN) +endef + define KernelPackage/wprobe +$(call Package/wprobe/Default) SUBMENU:=Network Support - DEPENDS:=@LINUX_2_6 TITLE:=Wireless driver probe infrastructure FILES:= \ $(PKG_BUILD_DIR)/kernel/wprobe.$(LINUX_KMOD_SUFFIX) @@ -32,9 +40,10 @@ define KernelPackage/wprobe/description endef define Package/wprobe-util +$(call Package/wprobe/Default) SECTION:=net CATEGORY:=Network - DEPENDS:=+kmod-wprobe +libnl-tiny + DEPENDS+=+kmod-wprobe +libnl-tiny TITLE:=Wireless measurement utility endef @@ -44,9 +53,10 @@ define Package/wprobe-util/description endef define Package/wprobe-export +$(call Package/wprobe/Default) SECTION:=net CATEGORY:=Network - DEPENDS:=+wprobe-util + DEPENDS+=+wprobe-util TITLE:=Wireless measurement data exporter endef diff --git a/package/wprobe/files/wprobe.init b/package/wprobe/files/wprobe.init index 26d5c3d31..b35246d42 100755 --- a/package/wprobe/files/wprobe.init +++ b/package/wprobe/files/wprobe.init @@ -1,6 +1,6 @@ #!/bin/sh /etc/rc.common START=90 -EXPORTER=/usr/sbin/wprobe-ipfix +EXPORTER=/sbin/wprobe-export UTIL=/sbin/wprobe-util wprobe_ssd() { @@ -30,7 +30,7 @@ start_proxy() { start_ipfix() { local cfg="$1" - config_get ifname "$cfg" interface + config_get ifname "$cfg" ifname config_get host "$cfg" host config_get port "$cfg" port config_get proto "$cfg" proto diff --git a/package/wprobe/src/exporter/wprobe-export.c b/package/wprobe/src/exporter/wprobe-export.c index 48be5f36b..a0e52e2f4 100644 --- a/package/wprobe/src/exporter/wprobe-export.c +++ b/package/wprobe/src/exporter/wprobe-export.c @@ -25,7 +25,6 @@ static int do_close = 0; struct wprobe_mapping { int id; bool counter; - float scale; const char *wprobe_id; struct wprobe_value *val; }; @@ -36,16 +35,14 @@ struct wprobe_mapping { #define WMAP(_id, _name, ...) \ { \ - .scale = 1.0f, \ .counter = false, \ - .id = IPFIX_FT_WPROBE_##_id##_AVG, \ + .id = IPFIX_FT_WPROBE_##_id##_N, \ .wprobe_id = _name \ , ## __VA_ARGS__ \ } #define WMAP_COUNTER(_id, _name, ...) \ { \ - .scale = 1.0f, \ .counter = true, \ .id = IPFIX_FT_WPROBE_##_id, \ .wprobe_id = _name \ @@ -144,7 +141,7 @@ add_template_fields(ipfix_t *handle, ipfix_template_t *t, struct wprobe_mapping if (map[i].counter) g_data.addrs[f++] = &map[i].val->U32; else - g_data.addrs[f++] = &map[i].val->avg; + g_data.addrs[f++] = &map[i].val->n; if (ipfix_add_field( handle, t, FOKUS_USERID, map[i].id + 0, 4) < 0) exit(1); @@ -152,11 +149,14 @@ add_template_fields(ipfix_t *handle, ipfix_template_t *t, struct wprobe_mapping if (map[i].counter) continue; - g_data.addrs[f++] = &map[i].val->stdev; - g_data.addrs[f++] = &map[i].val->n; - if (ipfix_add_field( handle, t, FOKUS_USERID, map[i].id + 1, 4) < 0) + g_data.lens[f] = 8; + g_data.addrs[f++] = &map[i].val->s; + + g_data.lens[f] = 8; + g_data.addrs[f++] = &map[i].val->ss; + if (ipfix_add_field( handle, t, FOKUS_USERID, map[i].id + 1, 8) < 0) exit(1); - if (ipfix_add_field( handle, t, FOKUS_USERID, map[i].id + 2, 4) < 0) + if (ipfix_add_field( handle, t, FOKUS_USERID, map[i].id + 2, 8) < 0) exit(1); } g_data.maxfields = f; diff --git a/package/wprobe/src/user/wprobe-util.c b/package/wprobe/src/user/wprobe-util.c index 72feece02..6a9868ed0 100644 --- a/package/wprobe/src/user/wprobe-util.c +++ b/package/wprobe/src/user/wprobe-util.c @@ -82,7 +82,7 @@ wprobe_dump_data(struct wprobe_iface *dev) bool first = true; if (!simple_mode) - fprintf(stderr, "\n"); + fprintf(stdout, "\n"); wprobe_request_data(dev, NULL); list_for_each_entry(attr, &dev->global_attr, list) { if (simple_mode) { @@ -90,7 +90,7 @@ wprobe_dump_data(struct wprobe_iface *dev) fprintf(stdout, "[global]\n"); fprintf(stdout, "%s=%s\n", attr->name, wprobe_dump_value(attr)); } else { - fprintf(stderr, (first ? + fprintf(stdout, (first ? "Global: %s=%s\n" : " %s=%s\n"), attr->name, @@ -105,7 +105,7 @@ wprobe_dump_data(struct wprobe_iface *dev) wprobe_request_data(dev, link->addr); list_for_each_entry(attr, &dev->link_attr, list) { if (first) { - fprintf((simple_mode ? stdout : stderr), + fprintf(stdout, (simple_mode ? "[%02x:%02x:%02x:%02x:%02x:%02x]\n%s=%s\n" : "%02x:%02x:%02x:%02x:%02x:%02x: %s=%s\n"), @@ -115,7 +115,7 @@ wprobe_dump_data(struct wprobe_iface *dev) wprobe_dump_value(attr)); first = false; } else { - fprintf((simple_mode ? stdout : stderr), + fprintf(stdout, (simple_mode ? "%s=%s\n" : " %s=%s\n"), attr->name, @@ -171,11 +171,11 @@ static void show_attributes(struct wprobe_iface *dev) if (simple_mode) return; list_for_each_entry(attr, &dev->global_attr, list) { - fprintf(stderr, "Global attribute: '%s' (%s)\n", + fprintf(stdout, "Global attribute: '%s' (%s)\n", attr->name, attr_typestr[attr->type]); } list_for_each_entry(attr, &dev->link_attr, list) { - fprintf(stderr, "Link attribute: '%s' (%s)\n", + fprintf(stdout, "Link attribute: '%s' (%s)\n", attr->name, attr_typestr[attr->type]); } } @@ -196,9 +196,9 @@ static void show_filter_simple(void *arg, const char *group, struct wprobe_filte static void show_filter(void *arg, const char *group, struct wprobe_filter_item *items, int n_items) { int i; - fprintf(stderr, "Filter group: '%s' (tx/rx)\n", group); + fprintf(stdout, "Filter group: '%s' (tx/rx)\n", group); for (i = 0; i < n_items; i++) { - fprintf(stderr, " - %s (%lld/%lld)\n", + fprintf(stdout, " - %s (%lld/%lld)\n", items[i].name, items[i].tx, items[i].rx); } } @@ -415,7 +415,7 @@ int main(int argc, char **argv) if (!dev || (list_empty(&dev->global_attr) && list_empty(&dev->link_attr))) { if (err) - fprintf(stderr, "%s\n", err); + fprintf(stdout, "%s\n", err); else fprintf(stderr, "Interface '%s' not found\n", ifname); return 1; diff --git a/package/zlib/Makefile b/package/zlib/Makefile index 19457c1ac..d8213b972 100644 --- a/package/zlib/Makefile +++ b/package/zlib/Makefile @@ -39,6 +39,7 @@ endef define Build/Compile $(MAKE) -C $(PKG_BUILD_DIR) \ $(TARGET_CONFIGURE_OPTS) \ + LDSHARED="$(TARGET_CROSS)ld -shared" \ CFLAGS="$(TARGET_CFLAGS) $(FPIC)" \ libz.a libz.so mkdir -p $(PKG_INSTALL_DIR) diff --git a/rules.mk b/rules.mk index 0ee8d568a..31c8854e9 100644 --- a/rules.mk +++ b/rules.mk @@ -45,7 +45,7 @@ else endif DL_DIR:=$(if $(call qstrip,$(CONFIG_DOWNLOAD_FOLDER)),$(call qstrip,$(CONFIG_DOWNLOAD_FOLDER)),$(TOPDIR)/dl) -BIN_DIR:=$(TOPDIR)/bin +BIN_DIR:=$(TOPDIR)/bin/$(BOARD) INCLUDE_DIR:=$(TOPDIR)/include SCRIPT_DIR:=$(TOPDIR)/scripts BUILD_DIR_BASE:=$(TOPDIR)/build_dir @@ -61,7 +61,7 @@ ifeq ($(CONFIG_EXTERNAL_TOOLCHAIN),) STAGING_DIR:=$(TOPDIR)/staging_dir/target-$(ARCH)_$(LIBC)-$(LIBCV) BUILD_DIR_TOOLCHAIN:=$(BUILD_DIR_BASE)/toolchain-$(ARCH)_gcc-$(GCCV)_$(LIBC)-$(LIBCV) TOOLCHAIN_DIR:=$(TOPDIR)/staging_dir/toolchain-$(ARCH)_gcc-$(GCCV)_$(LIBC)-$(LIBCV) - PACKAGE_DIR:=$(BIN_DIR)/packages/$(BOARD)_$(LIBC)-$(LIBCV) + PACKAGE_DIR:=$(BIN_DIR)/packages else ifeq ($(CONFIG_NATIVE_TOOLCHAIN),) GNU_TARGET_NAME=$(call qstrip,$(CONFIG_TARGET_NAME)) @@ -73,7 +73,7 @@ else STAGING_DIR:=$(TOPDIR)/staging_dir/target-$(GNU_TARGET_NAME) BUILD_DIR_TOOLCHAIN:=$(BUILD_DIR_BASE)/toolchain-$(GNU_TARGET_NAME) TOOLCHAIN_DIR:=$(TOPDIR)/staging_dir/toolchain-$(GNU_TARGET_NAME) - PACKAGE_DIR:=$(BIN_DIR)/packages/$(BOARD)_$(GNU_TARGET_NAME) + PACKAGE_DIR:=$(BIN_DIR)/packages endif STAMP_DIR:=$(BUILD_DIR)/stamp STAMP_DIR_HOST=$(BUILD_DIR_HOST)/stamp diff --git a/scripts/combined-image.sh b/scripts/combined-image.sh index 30373e756..5472b2cfd 100644 --- a/scripts/combined-image.sh +++ b/scripts/combined-image.sh @@ -7,9 +7,11 @@ BLKSZ=65536 exit 1 } +IMAGE=${3:-openwrt-combined.img} + # Make sure provided images are 64k aligned. -kern=$(mktemp) -root=$(mktemp) +kern="${IMAGE}.kernel" +root="${IMAGE}.rootfs" dd if="$1" of="$kern" bs=$BLKSZ conv=sync 2>/dev/null dd if="$2" of="$root" bs=$BLKSZ conv=sync 2>/dev/null @@ -26,7 +28,7 @@ md5=$(cat "$kern" "$root" | md5sum -) $(stat -c "%s" "$kern") $(stat -c "%s" "$root") "${md5%% *}" | \ dd bs=$BLKSZ conv=sync; cat "$kern" "$root" -) > ${3:-openwrt-combined.img} 2>/dev/null +) > ${IMAGE} 2>/dev/null # Clean up. rm -f "$kern" "$root" diff --git a/scripts/config/.gitignore b/scripts/config/.gitignore index 903b0de28..72812668d 100644 --- a/scripts/config/.gitignore +++ b/scripts/config/.gitignore @@ -1,6 +1,6 @@ *.o lxdialog -conf -mconf +conf* +mconf* mconf_check *.*.c diff --git a/scripts/config/lex.zconf.c_shipped b/scripts/config/lex.zconf.c_shipped index 42bcdd456..31637377a 100644 --- a/scripts/config/lex.zconf.c_shipped +++ b/scripts/config/lex.zconf.c_shipped @@ -2268,7 +2268,10 @@ void zconf_nextfile(const char *name) struct buffer *buf; retval = glob(name, GLOB_ERR | GLOB_MARK, NULL, &files); - if (retval == GLOB_NOSPACE || retval == GLOB_ABORTED || retval == GLOB_NOMATCH) { + if (retval == GLOB_NOMATCH) + return; + + if (retval == GLOB_NOSPACE || retval == GLOB_ABORTED) { printf("%s:%d: glob failed: %s \"%s\"\n", zconf_curname(), zconf_lineno(), retval == GLOB_NOSPACE ? "failed to allocate memory" : retval == GLOB_ABORTED ? "read error" : "no match", diff --git a/scripts/config/zconf.l b/scripts/config/zconf.l index 7acb60f8e..71107a56e 100644 --- a/scripts/config/zconf.l +++ b/scripts/config/zconf.l @@ -302,7 +302,10 @@ void zconf_nextfile(const char *name) struct buffer *buf; retval = glob(name, GLOB_ERR | GLOB_MARK, NULL, &files); - if (retval == GLOB_NOSPACE || retval == GLOB_ABORTED || retval == GLOB_NOMATCH) { + if (retval == GLOB_NOMATCH) + return; + + if (retval == GLOB_NOSPACE || retval == GLOB_ABORTED) { printf("%s:%d: glob failed: %s \"%s\"\n", zconf_curname(), zconf_lineno(), retval == GLOB_NOSPACE ? "failed to allocate memory" : retval == GLOB_ABORTED ? "read error" : "no match", diff --git a/scripts/dl_cleanup.py b/scripts/dl_cleanup.py new file mode 100755 index 000000000..48f587de5 --- /dev/null +++ b/scripts/dl_cleanup.py @@ -0,0 +1,216 @@ +#!/usr/bin/env python +""" +# OpenWRT download directory cleanup utility. +# Delete all but the very last version of the program tarballs. +# +# Copyright (c) 2010 Michael Buesch +""" + +import sys +import os +import re +import getopt + +# Commandline options +opt_dryrun = False + + +def parseVer_1234(match): + progname = match.group(1) + progversion = (int(match.group(2)) << 64) |\ + (int(match.group(3)) << 48) |\ + (int(match.group(4)) << 32) |\ + (int(match.group(5)) << 16) + return (progname, progversion) + +def parseVer_123(match): + progname = match.group(1) + try: + patchlevel = match.group(5) + except (IndexError), e: + patchlevel = None + if patchlevel: + patchlevel = ord(patchlevel[0]) + else: + patchlevel = 0 + progversion = (int(match.group(2)) << 64) |\ + (int(match.group(3)) << 48) |\ + (int(match.group(4)) << 32) |\ + patchlevel + return (progname, progversion) + +def parseVer_12(match): + progname = match.group(1) + try: + patchlevel = match.group(4) + except (IndexError), e: + patchlevel = None + if patchlevel: + patchlevel = ord(patchlevel[0]) + else: + patchlevel = 0 + progversion = (int(match.group(2)) << 64) |\ + (int(match.group(3)) << 48) |\ + patchlevel + return (progname, progversion) + +def parseVer_r(match): + progname = match.group(1) + progversion = (int(match.group(2)) << 64) + return (progname, progversion) + +def parseVer_ymd(match): + progname = match.group(1) + progversion = (int(match.group(2)) << 64) |\ + (int(match.group(3)) << 48) |\ + (int(match.group(4)) << 32) + return (progname, progversion) + +extensions = ( + ".tar.gz", + ".tar.bz2", + ".orig.tar.gz", + ".orig.tar.bz2", + ".zip", + ".tgz", + ".tbz", +) + +versionRegex = ( + (re.compile(r"(.+)[-_](\d+)\.(\d+)\.(\d+)\.(\d+)"), parseVer_1234), # xxx-1.2.3.4 + (re.compile(r"(.+)[-_](\d\d\d\d)-?(\d\d)-?(\d\d)"), parseVer_ymd), # xxx-YYYY-MM-DD + (re.compile(r"(.+)[-_](\d+)\.(\d+)\.(\d+)(\w?)"), parseVer_123), # xxx-1.2.3a + (re.compile(r"(.+)[-_](\d+)_(\d+)_(\d+)"), parseVer_123), # xxx-1_2_3 + (re.compile(r"(.+)[-_](\d+)\.(\d+)(\w?)"), parseVer_12), # xxx-1.2a + (re.compile(r"(.+)[-_]r?(\d+)"), parseVer_r), # xxx-r1111 +) + +blacklist = [ + ("linux", re.compile(r"linux-.*")), + ("gcc", re.compile(r"gcc-.*")), + ("wl_apsta", re.compile(r"wl_apsta.*")), + (".fw", re.compile(r".*\.fw")), + (".arm", re.compile(r".*\.arm")), + (".bin", re.compile(r".*\.bin")), + ("rt-firmware", re.compile(r"RT[\d\w]+_Firmware.*")), +] + +class EntryParseError(Exception): pass + +class Entry: + def __init__(self, directory, filename): + self.directory = directory + self.filename = filename + self.progname = "" + + for ext in extensions: + if filename.endswith(ext): + filename = filename[0:0-len(ext)] + break + else: + print self.filename, "has an unknown file-extension" + raise EntryParseError("ext") + for (regex, parseVersion) in versionRegex: + match = regex.match(filename) + if match: + (self.progname, self.version) = parseVersion(match) + break + else: + print self.filename, "has an unknown version pattern" + raise EntryParseError("ver") + + def deleteFile(self): + path = (self.directory + "/" + self.filename).replace("//", "/") + print "Deleting", path + if not opt_dryrun: + os.unlink(path) + + def __eq__(self, y): + return self.filename == y.filename + + def __ge__(self, y): + return self.version >= y.version + +def usage(): + print "OpenWRT download directory cleanup utility" + print "Usage: " + sys.argv[0] + " [OPTIONS] " + print "" + print " -d|--dry-run Do a dry-run. Don't delete any files" + print " -B|--show-blacklist Show the blacklist and exit" + print " -w|--whitelist ITEM Remove ITEM from blacklist" + +def main(argv): + global opt_dryrun + + try: + (opts, args) = getopt.getopt(argv[1:], + "hdBw:", + [ "help", "dry-run", "show-blacklist", "whitelist=", ]) + if len(args) != 1: + raise getopt.GetoptError() + except getopt.GetoptError: + usage() + return 1 + directory = args[0] + for (o, v) in opts: + if o in ("-h", "--help"): + usage() + return 0 + if o in ("-d", "--dry-run"): + opt_dryrun = True + if o in ("-w", "--whitelist"): + for i in range(0, len(blacklist)): + (name, regex) = blacklist[i] + if name == v: + del blacklist[i] + break + else: + print "Whitelist error: Item", v,\ + "is not in blacklist" + return 1 + if o in ("-B", "--show-blacklist"): + for (name, regex) in blacklist: + print name + return 0 + + # Create a directory listing and parse the file names. + entries = [] + for filename in os.listdir(directory): + if filename == "." or filename == "..": + continue + for (name, regex) in blacklist: + if regex.match(filename): + if opt_dryrun: + print filename, "is blacklisted" + break + else: + try: + entries.append(Entry(directory, filename)) + except (EntryParseError), e: pass + + # Create a map of programs + progmap = {} + for entry in entries: + if entry.progname in progmap.keys(): + progmap[entry.progname].append(entry) + else: + progmap[entry.progname] = [entry,] + + # Traverse the program map and delete everything but the last version + for prog in progmap: + lastVersion = None + versions = progmap[prog] + for version in versions: + if lastVersion is None or version >= lastVersion: + lastVersion = version + if lastVersion: + for version in versions: + if version != lastVersion: + version.deleteFile() + if opt_dryrun: + print "Keeping", lastVersion.filename + + return 0 + +if __name__ == "__main__": + sys.exit(main(sys.argv)) diff --git a/scripts/symlink-tree.sh b/scripts/symlink-tree.sh new file mode 100755 index 000000000..8be5f6c96 --- /dev/null +++ b/scripts/symlink-tree.sh @@ -0,0 +1,45 @@ +#!/usr/bin/env bash +# Create a new openwrt tree with symlinks pointing at the current tree +# Usage: ./scripts/symlink-tree.sh + +FILES=" + BSDmakefile + Config.in + LICENSE + Makefile + README + dl + docs + feeds.conf.default + include + package + rules.mk + scripts + target + toolchain + tools" + +if [ -f feeds.conf ] ; then + FILES="$FILES feeds.conf" +fi + +if [ -z "$1" ]; then + echo "Syntax: $0 " + exit 1 +fi + +if [ -e "$1" ]; then + echo "Error: $1 already exists" + exit 1 +fi + +set -e # fail if any commands fails +mkdir -p dl "$1" +for file in $FILES; do + [ -e "$PWD/$file" ] || { + echo "ERROR: $file does not exist in the current tree" + exit 1 + } + ln -s "$PWD/$file" "$1/" +done +exit 0 diff --git a/scripts/update-package-md5sum b/scripts/update-package-md5sum new file mode 100755 index 000000000..1cf17163e --- /dev/null +++ b/scripts/update-package-md5sum @@ -0,0 +1,38 @@ +#!/usr/bin/env sh +# +# update-package-md5sum - Updates md5sum of OpenWrt packages +# +# update-package-md5sum will update the md5sum for all recusivly found OpenWrt packages +# in a given directory. +# +# Usage: scripts/update-package-md5sum +# +# Example: `scripts/update-package-md5sum feeds/packages/python` + +DL_FOLDER=`grep -Eo '^CONFIG_DOWNLOAD_FOLDER=".*"$' .config | \ + sed 's,^CONFIG_DOWNLOAD_FOLDER="\(.*\)"$,\1,'` +if test -z ${DL_FOLDER}; then + DL_FOLDER=./dl +fi + +if test -z "$1"; then + echo "Usage: $0 " + exit +fi + +for file in `find $1 -name Makefile`; do + if grep BuildPackage ${file} > /dev/null; then + source=`DUMP=1 TOPDIR=\`pwd\` make -f ${file} | grep -m 1 Source | cut -f 2 -d ' '` + if test -n "${source}"; then + if test ! -f "${DL_FOLDER}/${source}"; then + make package/`basename \`dirname ${file}\``/download + fi + sum=`md5sum ${DL_FOLDER}/${source} 2> /dev/null` || continue + echo Updating ${file}... + sum=`echo ${sum} | cut -d ' ' -f 1` + sed -i "s,^PKG_MD5SUM:=.*,PKG_MD5SUM:=${sum}," ${file} + else + echo No source for ${file} + fi + fi +done diff --git a/target/Config.in b/target/Config.in index 643885a32..1b2c303db 100644 --- a/target/Config.in +++ b/target/Config.in @@ -53,7 +53,10 @@ config USES_UBIFS config USES_CPIOGZ bool -config PROFILE_KCONFIG +config USES_UBIFS + bool + +config PROFILE_KCONFIG bool config NOMMU @@ -61,6 +64,20 @@ config NOMMU # Architecture selection +config arm + bool + +config armeb + select BIG_ENDIAN + bool + +config avr32 + select BIG_ENDIAN + bool + +config cris + bool + config i386 bool @@ -68,7 +85,6 @@ config i686 bool config m68k - select BIG_ENDIAN bool config mips @@ -85,28 +101,12 @@ config mips64 config mips64el bool -config arm - bool - -config armeb - select BIG_ENDIAN - bool - -config avr32 - select BIG_ENDIAN - bool - -config cris - bool - -config m68k - bool - config powerpc select BIG_ENDIAN bool config powerpc64 + select BIG_ENDIAN bool config sh3 @@ -127,32 +127,32 @@ config sparc select BIG_ENDIAN bool -config x86_64 - bool - config ubicom32 select BIG_ENDIAN bool +config x86_64 + bool + config ARCH string - default "arm" if arm - default "armeb" if armeb - default "avr32" if avr32 - default "cris" if cris - default "i386" if i386 - default "i686" if i686 - default "m68k" if m68k - default "mips" if mips - default "mipsel" if mipsel - default "mips64" if mips64 - default "mips64el" if mips64el - default "powerpc" if powerpc - default "sh3" if sh3 - default "sh3eb" if sh3eb - default "sh4" if sh4 - default "sh4eb" if sh4eb - default "sparc" if sparc - default "x86_64" if x86_64 + default "arm" if arm + default "armeb" if armeb + default "avr32" if avr32 + default "cris" if cris + default "i386" if i386 + default "i686" if i686 + default "m68k" if m68k + default "mips" if mips + default "mipsel" if mipsel + default "mips64" if mips64 + default "mips64el" if mips64el + default "powerpc" if powerpc + default "sh3" if sh3 + default "sh3eb" if sh3eb + default "sh4" if sh4 + default "sh4eb" if sh4eb + default "sparc" if sparc default "ubicom32" if ubicom32 + default "x86_64" if x86_64 diff --git a/target/imagebuilder/Config.in b/target/imagebuilder/Config.in index 64fc4051c..0d19bed1c 100644 --- a/target/imagebuilder/Config.in +++ b/target/imagebuilder/Config.in @@ -3,6 +3,7 @@ config IB depends !TARGET_ROOTFS_INITRAMFS depends !TARGET_uml depends !PROFILE_KCONFIG + depends !EXTERNAL_TOOLCHAIN select ALL help This is essentially a stripped-down version of the buildroot diff --git a/target/linux/adm5120/Makefile b/target/linux/adm5120/Makefile index d27141618..8bd1eb11a 100644 --- a/target/linux/adm5120/Makefile +++ b/target/linux/adm5120/Makefile @@ -9,13 +9,14 @@ include $(TOPDIR)/rules.mk BOARD:=adm5120 BOARDNAME:=Infineon/ADMtek ADM5120 -LINUX_VERSION:=2.6.30.9 +LINUX_VERSION:=2.6.30.10 SUBTARGETS:=router_le router_be INITRAMFS_EXTRA_FILES:= include $(INCLUDE_DIR)/target.mk DEFAULT_PACKAGES += admswconfig hostapd-mini kmod-input-core \ - kmod-input-polldev kmod-input-gpio-buttons kmod-button-hotplug + kmod-input-polldev kmod-input-gpio-buttons kmod-button-hotplug \ + kmod-leds-gpio kmod-ledtrig-adm5120-switch $(eval $(call BuildTarget)) diff --git a/target/linux/adm5120/base-files/etc/diag.sh b/target/linux/adm5120/base-files/etc/diag.sh index e03175523..3a66dfc87 100755 --- a/target/linux/adm5120/base-files/etc/diag.sh +++ b/target/linux/adm5120/base-files/etc/diag.sh @@ -35,6 +35,7 @@ status_led_off() { set_state() { case "$1" in preinit) + insmod leds-gpio status_led_set_timer 200 200 ;; failsafe) diff --git a/target/linux/adm5120/base-files/lib/adm5120.sh b/target/linux/adm5120/base-files/lib/adm5120.sh index fb0526e40..06e2aac2d 100755 --- a/target/linux/adm5120/base-files/lib/adm5120.sh +++ b/target/linux/adm5120/base-files/lib/adm5120.sh @@ -9,7 +9,7 @@ status_led="" sys_mtd_part="" adm5120_detect() { - board_name=$(awk 'BEGIN{FS="[ \t]+:[ \t]"} /system type/ {print $2}' /proc/cpuinfo) + board_name=$(awk 'BEGIN{FS="[ \t]+:[ \t]"} /machine/ {print $2}' /proc/cpuinfo) case "$board_name" in "Cellvision"*) diff --git a/target/linux/adm5120/base-files/lib/upgrade/platform.sh b/target/linux/adm5120/base-files/lib/upgrade/platform.sh index 3a9cec6e5..a0678b858 100644 --- a/target/linux/adm5120/base-files/lib/upgrade/platform.sh +++ b/target/linux/adm5120/base-files/lib/upgrade/platform.sh @@ -1,19 +1,38 @@ -PART_NAME=partition1 +# +# Copyright (C) 2009-2010 OpenWrt.org +# + +. /lib/adm5120.sh + +PART_NAME="firmware" +RAMFS_COPY_DATA=/lib/adm5120.sh platform_check_image() { + local magic="$(get_magic_word "$1")" + [ "$ARGC" -gt 1 ] && return 1 - case "$(get_magic_word "$1")" in + case "$board_name" in + "ZyXEL"*) # .trx files - 4844) return 0;; - *) - echo "Invalid image type. Please use only .trx files" + [ "$magic" != "4844" ] && { + echo "Invalid image type." return 1 + } + return 0 + ;; + *) ;; esac + + echo "Sysupgrade is not yet supported on $board_name." + return 1 } -# use default for platform_do_upgrade() +platform_do_upgrade() { + PART_NAME="$sys_mtd_part" + default_do_upgrade "$ARGV" +} disable_watchdog() { killall watchdog diff --git a/target/linux/adm5120/files/arch/mips/adm5120/common/Makefile b/target/linux/adm5120/files/arch/mips/adm5120/common/Makefile index d24aa0788..8d302c593 100644 --- a/target/linux/adm5120/files/arch/mips/adm5120/common/Makefile +++ b/target/linux/adm5120/files/arch/mips/adm5120/common/Makefile @@ -4,3 +4,5 @@ obj-y := adm5120.o setup.o prom.o irq.o memory.o clock.o \ gpio.o platform.o + +obj-$(CONFIG_EARLY_PRINTK) += early-printk.o diff --git a/target/linux/adm5120/files/arch/mips/adm5120/common/adm5120.c b/target/linux/adm5120/files/arch/mips/adm5120/common/adm5120.c index 3b969ce6e..28388342c 100644 --- a/target/linux/adm5120/files/arch/mips/adm5120/common/adm5120.c +++ b/target/linux/adm5120/files/arch/mips/adm5120/common/adm5120.c @@ -12,7 +12,6 @@ #include #include -//#include #include #include @@ -24,7 +23,6 @@ unsigned int adm5120_revision; unsigned int adm5120_package; unsigned int adm5120_nand_boot; unsigned long adm5120_speed; -unsigned long adm5120_mach_type; /* * CPU settings detection diff --git a/target/linux/adm5120/files/arch/mips/adm5120/common/clock.c b/target/linux/adm5120/files/arch/mips/adm5120/common/clock.c index d00430995..1ada60fed 100644 --- a/target/linux/adm5120/files/arch/mips/adm5120/common/clock.c +++ b/target/linux/adm5120/files/arch/mips/adm5120/common/clock.c @@ -19,6 +19,7 @@ #include #include #include +#include #include @@ -32,7 +33,9 @@ static struct clk uart_clk = { struct clk *clk_get(struct device *dev, const char *id) { - if (!strcmp(id, "UARTCLK")) + char *name = dev_name(dev); + + if (!strcmp(name, "apb:uart0") || !strcmp(name, "apb:uart1")) return &uart_clk; return ERR_PTR(-ENOENT); diff --git a/target/linux/adm5120/files/arch/mips/adm5120/common/early-printk.c b/target/linux/adm5120/files/arch/mips/adm5120/common/early-printk.c new file mode 100644 index 000000000..6aff1475a --- /dev/null +++ b/target/linux/adm5120/files/arch/mips/adm5120/common/early-printk.c @@ -0,0 +1,29 @@ +/* + * ADM5120 specific early printk support + * + * Copyright (C) 2007-2008 Gabor Juhos + * + * 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 +#include + +#include +#include +#include + +#define UART_READ(r) \ + __raw_readl((void __iomem *)(KSEG1ADDR(ADM5120_UART0_BASE)+(r))) +#define UART_WRITE(r, v) \ + __raw_writel((v), (void __iomem *)(KSEG1ADDR(ADM5120_UART0_BASE)+(r))) + +void __init prom_putchar(char ch) +{ + while ((UART_READ(UART_REG_FLAG) & UART_FLAG_TXFE) == 0); + UART_WRITE(UART_REG_DATA, ch); + while ((UART_READ(UART_REG_FLAG) & UART_FLAG_TXFE) == 0); +} diff --git a/target/linux/adm5120/files/arch/mips/adm5120/common/platform.c b/target/linux/adm5120/files/arch/mips/adm5120/common/platform.c index 9526fe977..7fe86a13e 100644 --- a/target/linux/adm5120/files/arch/mips/adm5120/common/platform.c +++ b/target/linux/adm5120/files/arch/mips/adm5120/common/platform.c @@ -190,7 +190,7 @@ struct amba_pl010_data adm5120_uart0_data = { struct amba_device adm5120_uart0_device = { .dev = { - .bus_id = "APB:UART0", + .init_name = "apb:uart0", .platform_data = &adm5120_uart0_data, }, .res = { @@ -208,7 +208,7 @@ struct amba_pl010_data adm5120_uart1_data = { struct amba_device adm5120_uart1_device = { .dev = { - .bus_id = "APB:UART1", + .init_name = "apb:uart1", .platform_data = &adm5120_uart1_data, }, .res = { diff --git a/target/linux/adm5120/files/arch/mips/adm5120/common/prom.c b/target/linux/adm5120/files/arch/mips/adm5120/common/prom.c index 5b2e45def..81ba365a0 100644 --- a/target/linux/adm5120/files/arch/mips/adm5120/common/prom.c +++ b/target/linux/adm5120/files/arch/mips/adm5120/common/prom.c @@ -13,15 +13,11 @@ #include #include #include -#include -#include #include #include #include -#include -#include #include #include @@ -206,35 +202,35 @@ static void __init prom_detect_machtype(void) { if (bootbase_present()) { adm5120_prom_type = ADM5120_PROM_BOOTBASE; - adm5120_mach_type = detect_machtype_bootbase(); + mips_machtype = detect_machtype_bootbase(); return; } if (cfe_present()) { adm5120_prom_type = ADM5120_PROM_CFE; - adm5120_mach_type = detect_machtype_cfe(); + mips_machtype = detect_machtype_cfe(); return; } if (myloader_present()) { adm5120_prom_type = ADM5120_PROM_MYLOADER; - adm5120_mach_type = detect_machtype_myloader(); + mips_machtype = detect_machtype_myloader(); return; } if (routerboot_present()) { adm5120_prom_type = ADM5120_PROM_ROUTERBOOT; - adm5120_mach_type = detect_machtype_routerboot(); + mips_machtype = detect_machtype_routerboot(); return; } if (generic_prom_present()) { adm5120_prom_type = ADM5120_PROM_GENERIC; - adm5120_mach_type = detect_machtype_generic(); + mips_machtype = detect_machtype_generic(); return; } - adm5120_mach_type = MACH_ADM5120_GENERIC; + mips_machtype = MACH_ADM5120_GENERIC; } #ifdef CONFIG_IMAGE_CMDLINE_HACK @@ -254,18 +250,6 @@ static void __init prom_init_cmdline(void) static void inline prom_init_cmdline(void) {} #endif /* CONFIG_IMAGE_CMDLINE_HACK */ -#define UART_READ(r) \ - __raw_readl((void __iomem *)(KSEG1ADDR(ADM5120_UART0_BASE)+(r))) -#define UART_WRITE(r, v) \ - __raw_writel((v), (void __iomem *)(KSEG1ADDR(ADM5120_UART0_BASE)+(r))) - -void __init prom_putchar(char ch) -{ - while ((UART_READ(UART_REG_FLAG) & UART_FLAG_TXFE) == 0); - UART_WRITE(UART_REG_DATA, ch); - while ((UART_READ(UART_REG_FLAG) & UART_FLAG_TXFE) == 0); -} - void __init prom_init(void) { prom_detect_machtype(); diff --git a/target/linux/adm5120/files/arch/mips/adm5120/common/setup.c b/target/linux/adm5120/files/arch/mips/adm5120/common/setup.c index 271dfaa6b..843a616bb 100644 --- a/target/linux/adm5120/files/arch/mips/adm5120/common/setup.c +++ b/target/linux/adm5120/files/arch/mips/adm5120/common/setup.c @@ -21,6 +21,7 @@ #include #include +#include #include #include #include @@ -106,7 +107,7 @@ static int __init adm5120_board_setup(void) { adm5120_gpio_init(); - mips_machine_setup(adm5120_mach_type); + mips_machine_setup(mips_machtype); return 0; } diff --git a/target/linux/adm5120/files/arch/mips/adm5120/zyxel/p-33x.c b/target/linux/adm5120/files/arch/mips/adm5120/zyxel/p-33x.c index 6d4d4ddee..24dce3255 100644 --- a/target/linux/adm5120/files/arch/mips/adm5120/zyxel/p-33x.c +++ b/target/linux/adm5120/files/arch/mips/adm5120/zyxel/p-33x.c @@ -27,11 +27,15 @@ static struct mtd_partition p33x_partitions[] = { .name = "rom", .offset = MTDPART_OFS_APPEND, .size = 16*1024, - } , { - .name = "bootext", - .offset = MTDPART_OFS_APPEND, - .size = 96*1024, .mask_flags = MTD_WRITEABLE, + } , { + .name = "bootext1", + .offset = MTDPART_OFS_APPEND, + .size = 32*1024, + } , { + .name = "bootext2", + .offset = MTDPART_OFS_APPEND, + .size = 64*1024, } , { .name = "trx", .offset = MTDPART_OFS_APPEND, @@ -83,7 +87,7 @@ void __init p33x_generic_setup(void) adm5120_add_device_gpio(P33X_GPIO_DEV_MASK); adm5120_setup_eth_macs(bootbase_info.mac); - adm5120_add_device_switch(5, p33x_vlans); + adm5120_add_device_switch(6, p33x_vlans); adm5120_pci_set_irq_map(ARRAY_SIZE(p33x_pci_irqs), p33x_pci_irqs); } diff --git a/target/linux/adm5120/files/arch/mips/include/asm/mach-adm5120/adm5120_info.h b/target/linux/adm5120/files/arch/mips/include/asm/mach-adm5120/adm5120_info.h index 7cc18ebd4..a72a9927f 100644 --- a/target/linux/adm5120/files/arch/mips/include/asm/mach-adm5120/adm5120_info.h +++ b/target/linux/adm5120/files/arch/mips/include/asm/mach-adm5120/adm5120_info.h @@ -37,54 +37,54 @@ extern unsigned int adm5120_package; extern unsigned long adm5120_memsize; -extern unsigned long adm5120_mach_type; - -#define MACH_ADM5120_GENERIC 0 /* Generic board */ -#define MACH_ADM5120_WP54G_WRT 1 /* Compex WP54G-WRT */ -#define MACH_ADM5120_WP54 2 /* Compex WP54G/WP54AG/WPP54G/WPP54AG */ -#define MACH_ADM5120_NP28G 3 /* Compex NP28G */ -#define MACH_ADM5120_NP28GHS 4 /* Compex NP28G HotSpot */ -#define MACH_ADM5120_NP27G 5 /* Compex NP27G */ -#define MACH_ADM5120_WP54Gv1C 6 /* Compex WP54G version 1C */ -#define MACH_ADM5120_RB_11X 7 /* Mikrotik RouterBOARD 111/112 */ -#define MACH_ADM5120_RB_133 8 /* Mikrotik RouterBOARD 133 */ -#define MACH_ADM5120_RB_133C 9 /* Mikrotik RouterBOARD 133c */ -#define MACH_ADM5120_RB_150 10 /* Mikrotik RouterBOARD 150 */ -#define MACH_ADM5120_RB_153 11 /* Mikrotik RouterBOARD 153 */ -#define MACH_ADM5120_RB_192 12 /* Mikrotik RouterBOARD 192 */ -#define MACH_ADM5120_HS100 13 /* ZyXEL HomeSafe 100/100W */ -#define MACH_ADM5120_P334U 14 /* ZyXEL Prestige 334U */ -#define MACH_ADM5120_P334W 15 /* ZyXEL Prestige 334W */ -#define MACH_ADM5120_P334WH 16 /* ZyXEL Prestige 334WH */ -#define MACH_ADM5120_P334WHD 17 /* ZyXEL Prestige 334WHD */ -#define MACH_ADM5120_P334WT 18 /* ZyXEL Prestige 334WT */ -#define MACH_ADM5120_P335 19 /* ZyXEL Prestige 335/335WT */ -#define MACH_ADM5120_P335PLUS 20 /* ZyXEL Prestige 335Plus */ -#define MACH_ADM5120_P335U 21 /* ZyXEL Prestige 335U */ -#define MACH_ADM5120_ES2108 22 /* ZyXEL Ethernet Switch 2108 */ -#define MACH_ADM5120_ES2108F 23 /* ZyXEL Ethernet Switch 2108-F */ -#define MACH_ADM5120_ES2108G 24 /* ZyXEL Ethernet Switch 2108-G */ -#define MACH_ADM5120_ES2108LC 25 /* ZyXEL Ethernet Switch 2108-LC */ -#define MACH_ADM5120_ES2108PWR 26 /* ZyXEL Ethernet Switch 2108-PWR */ -#define MACH_ADM5120_ES2024A 27 /* ZyXEL Ethernet Switch 2024A */ -#define MACH_ADM5120_ES2024PWR 28 /* ZyXEL Ethernet Switch 2024PWR */ -#define MACH_ADM5120_CAS630 29 /* Cellvision CAS-630/630W */ -#define MACH_ADM5120_CAS670 30 /* Cellvision CAS-670/670W */ -#define MACH_ADM5120_CAS700 31 /* Cellvision CAS-700/700W */ -#define MACH_ADM5120_CAS771 32 /* Cellvision CAS-771/771W */ -#define MACH_ADM5120_CAS790 33 /* Cellvision CAS-790 */ -#define MACH_ADM5120_CAS861 34 /* Cellvision CAS-861/861W */ -#define MACH_ADM5120_NFS101U 35 /* Cellvision NFS-101U/101WU */ -#define MACH_ADM5120_NFS202U 36 /* Cellvision NFS-202U/202WU */ -#define MACH_ADM5120_EASY5120PATA 37 /* Infineon EASY 5120P-ATA */ -#define MACH_ADM5120_EASY5120RT 38 /* Infineon EASY 5120-RT */ -#define MACH_ADM5120_EASY5120WVOIP 39 /* Infineon EASY 5120-WVoIP */ -#define MACH_ADM5120_EASY83000 40 /* Infineon EASY-83000 */ -#define MACH_ADM5120_BR6104K 41 /* Edimax BR-6104K */ -#define MACH_ADM5120_BR6104KP 42 /* Edimax BR-6104KP */ -#define MACH_ADM5120_BR61X4WG 43 /* Edimax BR-6104Wg/BR-6114WG */ -#define MACH_ADM5120_PMUGW 44 /* Motorola Powerline MU Gateway */ -#define MACH_ADM5120_5GXI 45 /* OSBRiDGE 5GXi/5XLi */ +enum { + MACH_ADM5120_GENERIC = 0, /* Generic board */ + MACH_ADM5120_5GXI, /* OSBRiDGE 5GXi/5XLi */ + MACH_ADM5120_BR6104K, /* Edimax BR-6104K */ + MACH_ADM5120_BR6104KP, /* Edimax BR-6104KP */ + MACH_ADM5120_BR61X4WG, /* Edimax BR-6104Wg/BR-6114WG */ + MACH_ADM5120_CAS630, /* Cellvision CAS-630/630W */ + MACH_ADM5120_CAS670, /* Cellvision CAS-670/670W */ + MACH_ADM5120_CAS700, /* Cellvision CAS-700/700W */ + MACH_ADM5120_CAS771, /* Cellvision CAS-771/771W */ + MACH_ADM5120_CAS790, /* Cellvision CAS-790 */ + MACH_ADM5120_CAS861, /* Cellvision CAS-861/861W */ + MACH_ADM5120_EASY5120PATA, /* Infineon EASY 5120P-ATA */ + MACH_ADM5120_EASY5120RT, /* Infineon EASY 5120-RT */ + MACH_ADM5120_EASY5120WVOIP, /* Infineon EASY 5120-WVoIP */ + MACH_ADM5120_EASY83000, /* Infineon EASY-83000 */ + MACH_ADM5120_ES2108, /* ZyXEL Ethernet Switch 2108 */ + MACH_ADM5120_ES2108F, /* ZyXEL Ethernet Switch 2108-F */ + MACH_ADM5120_ES2108G, /* ZyXEL Ethernet Switch 2108-G */ + MACH_ADM5120_ES2108LC, /* ZyXEL Ethernet Switch 2108-LC */ + MACH_ADM5120_ES2108PWR, /* ZyXEL Ethernet Switch 2108-PWR */ + MACH_ADM5120_ES2024A, /* ZyXEL Ethernet Switch 2024A */ + MACH_ADM5120_ES2024PWR, /* ZyXEL Ethernet Switch 2024PWR */ + MACH_ADM5120_HS100, /* ZyXEL HomeSafe 100/100W */ + MACH_ADM5120_NFS101U, /* Cellvision NFS-101U/101WU */ + MACH_ADM5120_NFS202U, /* Cellvision NFS-202U/202WU */ + MACH_ADM5120_NP28G, /* Compex NP28G */ + MACH_ADM5120_NP28GHS, /* Compex NP28G HotSpot */ + MACH_ADM5120_NP27G, /* Compex NP27G */ + MACH_ADM5120_RB_11X, /* Mikrotik RouterBOARD 111/112 */ + MACH_ADM5120_RB_133, /* Mikrotik RouterBOARD 133 */ + MACH_ADM5120_RB_133C, /* Mikrotik RouterBOARD 133c */ + MACH_ADM5120_RB_150, /* Mikrotik RouterBOARD 150 */ + MACH_ADM5120_RB_153, /* Mikrotik RouterBOARD 153 */ + MACH_ADM5120_RB_192, /* Mikrotik RouterBOARD 192 */ + MACH_ADM5120_P334U, /* ZyXEL Prestige 334U */ + MACH_ADM5120_P334W, /* ZyXEL Prestige 334W */ + MACH_ADM5120_P334WH, /* ZyXEL Prestige 334WH */ + MACH_ADM5120_P334WHD, /* ZyXEL Prestige 334WHD */ + MACH_ADM5120_P334WT, /* ZyXEL Prestige 334WT */ + MACH_ADM5120_P335, /* ZyXEL Prestige 335/335WT */ + MACH_ADM5120_P335PLUS, /* ZyXEL Prestige 335Plus */ + MACH_ADM5120_P335U, /* ZyXEL Prestige 335U */ + MACH_ADM5120_PMUGW, /* Motorola Powerline MU Gateway */ + MACH_ADM5120_WP54, /* Compex WP54G/WP54AG/WPP54G/WPP54AG */ + MACH_ADM5120_WP54G_WRT, /* Compex WP54G-WRT */ + MACH_ADM5120_WP54Gv1C, /* Compex WP54G version 1C */ +}; /* * TODO:remove adm5120_eth* variables when the switch driver will be diff --git a/target/linux/adm5120/files/drivers/mtd/maps/adm5120-flash.c b/target/linux/adm5120/files/drivers/mtd/maps/adm5120-flash.c index 8bd7ae1c0..ed407ebde 100644 --- a/target/linux/adm5120/files/drivers/mtd/maps/adm5120-flash.c +++ b/target/linux/adm5120/files/drivers/mtd/maps/adm5120-flash.c @@ -233,7 +233,7 @@ static int adm5120_flash_initinfo(struct adm5120_flash_info *info, struct flash_desc *fdesc; u32 t = 0; - map->name = dev->dev.bus_id; + map->name = dev_name(&dev->dev); if (dev->id > 1) { MAP_ERR(map, "invalid flash id\n"); diff --git a/target/linux/adm5120/files/drivers/net/adm5120sw.c b/target/linux/adm5120/files/drivers/net/adm5120sw.c index 7acc84d24..09cb9097e 100644 --- a/target/linux/adm5120/files/drivers/net/adm5120sw.c +++ b/target/linux/adm5120/files/drivers/net/adm5120sw.c @@ -517,7 +517,7 @@ static int adm5120_if_poll(struct napi_struct *napi, int limit) status = sw_int_status() & SWITCH_INTS_POLL; if ((done < limit) && (!status)) { SW_DBG("disable polling mode for %s\n", dev->name); - netif_rx_complete(dev, napi); + napi_complete(napi); sw_int_unmask(SWITCH_INTS_POLL); return 0; } @@ -548,7 +548,7 @@ static irqreturn_t adm5120_switch_irq(int irq, void *dev_id) sw_dump_intr_mask("poll ints", status); SW_DBG("enable polling mode for %s\n", dev->name); sw_int_mask(SWITCH_INTS_POLL); - netif_rx_schedule(dev, &priv->napi); + napi_schedule(&priv->napi); } #else sw_int_ack(status); @@ -808,8 +808,8 @@ static int adm5120_if_open(struct net_device *dev) adm5120_if_napi_enable(dev); - err = request_irq(dev->irq, adm5120_switch_irq, - (IRQF_SHARED | IRQF_DISABLED), dev->name, dev); + err = request_irq(dev->irq, adm5120_switch_irq, IRQF_SHARED, + dev->name, dev); if (err) { SW_ERR("unable to get irq for %s\n", dev->name); goto err; @@ -973,9 +973,12 @@ static void adm5120_if_set_multicast_list(struct net_device *dev) static int adm5120_if_set_mac_address(struct net_device *dev, void *p) { - struct sockaddr *addr = p; + int ret; + + ret = eth_mac_addr(dev, p); + if (ret) + return ret; - memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); adm5120_write_mac(dev); return 0; } @@ -1017,6 +1020,18 @@ static int adm5120_if_do_ioctl(struct net_device *dev, struct ifreq *rq, return 0; } +static const struct net_device_ops adm5120sw_netdev_ops = { + .ndo_open = adm5120_if_open, + .ndo_stop = adm5120_if_stop, + .ndo_start_xmit = adm5120_if_hard_start_xmit, + .ndo_set_multicast_list = adm5120_if_set_multicast_list, + .ndo_do_ioctl = adm5120_if_do_ioctl, + .ndo_tx_timeout = adm5120_if_tx_timeout, + .ndo_validate_addr = eth_validate_addr, + .ndo_change_mtu = eth_change_mtu, + .ndo_set_mac_address = adm5120_if_set_mac_address, +}; + static struct net_device *adm5120_if_alloc(void) { struct net_device *dev; @@ -1030,14 +1045,8 @@ static struct net_device *adm5120_if_alloc(void) priv->dev = dev; dev->irq = ADM5120_IRQ_SWITCH; - dev->open = adm5120_if_open; - dev->hard_start_xmit = adm5120_if_hard_start_xmit; - dev->stop = adm5120_if_stop; - dev->set_multicast_list = adm5120_if_set_multicast_list; - dev->do_ioctl = adm5120_if_do_ioctl; - dev->tx_timeout = adm5120_if_tx_timeout; + dev->netdev_ops = &adm5120sw_netdev_ops; dev->watchdog_timeo = TX_TIMEOUT; - dev->set_mac_address = adm5120_if_set_mac_address; #ifdef CONFIG_ADM5120_SWITCH_NAPI netif_napi_add(dev, &priv->napi, adm5120_if_poll, 64); diff --git a/target/linux/adm5120/patches-2.6.28/801-mtd_trxsplit_2.6.28_fix.patch b/target/linux/adm5120/patches-2.6.28/801-mtd_trxsplit_2.6.28_fix.patch deleted file mode 100644 index 6a31cd5d1..000000000 --- a/target/linux/adm5120/patches-2.6.28/801-mtd_trxsplit_2.6.28_fix.patch +++ /dev/null @@ -1,11 +0,0 @@ ---- a/drivers/mtd/trxsplit.c -+++ b/drivers/mtd/trxsplit.c -@@ -18,7 +18,7 @@ - #include - #include - --#include -+//#include - - #define PFX "trxsplit: " - diff --git a/target/linux/adm5120/patches-2.6.30/800-adm5120-remove-amba-bus-id.patch b/target/linux/adm5120/patches-2.6.30/800-adm5120-remove-amba-bus-id.patch deleted file mode 100644 index 6be70ca09..000000000 --- a/target/linux/adm5120/patches-2.6.30/800-adm5120-remove-amba-bus-id.patch +++ /dev/null @@ -1,20 +0,0 @@ ---- a/arch/mips/adm5120/common/platform.c -+++ b/arch/mips/adm5120/common/platform.c -@@ -190,7 +190,7 @@ struct amba_pl010_data adm5120_uart0_dat - - struct amba_device adm5120_uart0_device = { - .dev = { -- .bus_id = "APB:UART0", -+ .init_name = "apb:uart0", - .platform_data = &adm5120_uart0_data, - }, - .res = { -@@ -208,7 +208,7 @@ struct amba_pl010_data adm5120_uart1_dat - - struct amba_device adm5120_uart1_device = { - .dev = { -- .bus_id = "APB:UART1", -+ .init_name = "apb:uart1", - .platform_data = &adm5120_uart1_data, - }, - .res = { diff --git a/target/linux/adm5120/patches-2.6.30/801-adm5120-flash-remove-bus-id.patch b/target/linux/adm5120/patches-2.6.30/801-adm5120-flash-remove-bus-id.patch deleted file mode 100644 index d9e72e064..000000000 --- a/target/linux/adm5120/patches-2.6.30/801-adm5120-flash-remove-bus-id.patch +++ /dev/null @@ -1,11 +0,0 @@ ---- a/drivers/mtd/maps/adm5120-flash.c -+++ b/drivers/mtd/maps/adm5120-flash.c -@@ -233,7 +233,7 @@ static int adm5120_flash_initinfo(struct - struct flash_desc *fdesc; - u32 t = 0; - -- map->name = dev->dev.bus_id; -+ map->name = dev_name(&dev->dev); - - if (dev->id > 1) { - MAP_ERR(map, "invalid flash id\n"); diff --git a/target/linux/adm5120/patches-2.6.30/802-adm5120-switch-remove-redundant-napi-functions.patch b/target/linux/adm5120/patches-2.6.30/802-adm5120-switch-remove-redundant-napi-functions.patch deleted file mode 100644 index 5c5873b73..000000000 --- a/target/linux/adm5120/patches-2.6.30/802-adm5120-switch-remove-redundant-napi-functions.patch +++ /dev/null @@ -1,20 +0,0 @@ ---- a/drivers/net/adm5120sw.c -+++ b/drivers/net/adm5120sw.c -@@ -517,7 +517,7 @@ static int adm5120_if_poll(struct napi_s - status = sw_int_status() & SWITCH_INTS_POLL; - if ((done < limit) && (!status)) { - SW_DBG("disable polling mode for %s\n", dev->name); -- netif_rx_complete(dev, napi); -+ napi_complete(napi); - sw_int_unmask(SWITCH_INTS_POLL); - return 0; - } -@@ -548,7 +548,7 @@ static irqreturn_t adm5120_switch_irq(in - sw_dump_intr_mask("poll ints", status); - SW_DBG("enable polling mode for %s\n", dev->name); - sw_int_mask(SWITCH_INTS_POLL); -- netif_rx_schedule(dev, &priv->napi); -+ napi_schedule(&priv->napi); - } - #else - sw_int_ack(status); diff --git a/target/linux/adm5120/patches-2.6.30/803-adm5120-fix-clock-for-amba-uart.patch b/target/linux/adm5120/patches-2.6.30/803-adm5120-fix-clock-for-amba-uart.patch deleted file mode 100644 index 795c28578..000000000 --- a/target/linux/adm5120/patches-2.6.30/803-adm5120-fix-clock-for-amba-uart.patch +++ /dev/null @@ -1,21 +0,0 @@ ---- a/arch/mips/adm5120/common/clock.c -+++ b/arch/mips/adm5120/common/clock.c -@@ -19,6 +19,7 @@ - #include - #include - #include -+#include - - #include - -@@ -32,7 +33,9 @@ static struct clk uart_clk = { - - struct clk *clk_get(struct device *dev, const char *id) - { -- if (!strcmp(id, "UARTCLK")) -+ char *name = dev_name(dev); -+ -+ if (!strcmp(name, "apb:uart0") || !strcmp(name, "apb:uart1")) - return &uart_clk; - - return ERR_PTR(-ENOENT); diff --git a/target/linux/adm5120/patches-2.6.30/810-adm5120sw-netdev_ops.patch b/target/linux/adm5120/patches-2.6.30/810-adm5120sw-netdev_ops.patch deleted file mode 100644 index ae116509c..000000000 --- a/target/linux/adm5120/patches-2.6.30/810-adm5120sw-netdev_ops.patch +++ /dev/null @@ -1,52 +0,0 @@ ---- a/drivers/net/adm5120sw.c -+++ b/drivers/net/adm5120sw.c -@@ -973,9 +973,12 @@ static void adm5120_if_set_multicast_lis - - static int adm5120_if_set_mac_address(struct net_device *dev, void *p) - { -- struct sockaddr *addr = p; -+ int ret; -+ -+ ret = eth_mac_addr(dev, p); -+ if (ret) -+ return ret; - -- memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); - adm5120_write_mac(dev); - return 0; - } -@@ -1017,6 +1020,18 @@ static int adm5120_if_do_ioctl(struct ne - return 0; - } - -+static const struct net_device_ops adm5120sw_netdev_ops = { -+ .ndo_open = adm5120_if_open, -+ .ndo_stop = adm5120_if_stop, -+ .ndo_start_xmit = adm5120_if_hard_start_xmit, -+ .ndo_set_multicast_list = adm5120_if_set_multicast_list, -+ .ndo_do_ioctl = adm5120_if_do_ioctl, -+ .ndo_tx_timeout = adm5120_if_tx_timeout, -+ .ndo_validate_addr = eth_validate_addr, -+ .ndo_change_mtu = eth_change_mtu, -+ .ndo_set_mac_address = adm5120_if_set_mac_address, -+}; -+ - static struct net_device *adm5120_if_alloc(void) - { - struct net_device *dev; -@@ -1030,14 +1045,8 @@ static struct net_device *adm5120_if_all - priv->dev = dev; - - dev->irq = ADM5120_IRQ_SWITCH; -- dev->open = adm5120_if_open; -- dev->hard_start_xmit = adm5120_if_hard_start_xmit; -- dev->stop = adm5120_if_stop; -- dev->set_multicast_list = adm5120_if_set_multicast_list; -- dev->do_ioctl = adm5120_if_do_ioctl; -- dev->tx_timeout = adm5120_if_tx_timeout; -+ dev->netdev_ops = &adm5120sw_netdev_ops; - dev->watchdog_timeo = TX_TIMEOUT; -- dev->set_mac_address = adm5120_if_set_mac_address; - - #ifdef CONFIG_ADM5120_SWITCH_NAPI - netif_napi_add(dev, &priv->napi, adm5120_if_poll, 64); diff --git a/target/linux/adm5120/patches-2.6.31/800-adm5120-remove-amba-bus-id.patch b/target/linux/adm5120/patches-2.6.31/800-adm5120-remove-amba-bus-id.patch deleted file mode 100644 index 6be70ca09..000000000 --- a/target/linux/adm5120/patches-2.6.31/800-adm5120-remove-amba-bus-id.patch +++ /dev/null @@ -1,20 +0,0 @@ ---- a/arch/mips/adm5120/common/platform.c -+++ b/arch/mips/adm5120/common/platform.c -@@ -190,7 +190,7 @@ struct amba_pl010_data adm5120_uart0_dat - - struct amba_device adm5120_uart0_device = { - .dev = { -- .bus_id = "APB:UART0", -+ .init_name = "apb:uart0", - .platform_data = &adm5120_uart0_data, - }, - .res = { -@@ -208,7 +208,7 @@ struct amba_pl010_data adm5120_uart1_dat - - struct amba_device adm5120_uart1_device = { - .dev = { -- .bus_id = "APB:UART1", -+ .init_name = "apb:uart1", - .platform_data = &adm5120_uart1_data, - }, - .res = { diff --git a/target/linux/adm5120/patches-2.6.31/801-adm5120-flash-remove-bus-id.patch b/target/linux/adm5120/patches-2.6.31/801-adm5120-flash-remove-bus-id.patch deleted file mode 100644 index d9e72e064..000000000 --- a/target/linux/adm5120/patches-2.6.31/801-adm5120-flash-remove-bus-id.patch +++ /dev/null @@ -1,11 +0,0 @@ ---- a/drivers/mtd/maps/adm5120-flash.c -+++ b/drivers/mtd/maps/adm5120-flash.c -@@ -233,7 +233,7 @@ static int adm5120_flash_initinfo(struct - struct flash_desc *fdesc; - u32 t = 0; - -- map->name = dev->dev.bus_id; -+ map->name = dev_name(&dev->dev); - - if (dev->id > 1) { - MAP_ERR(map, "invalid flash id\n"); diff --git a/target/linux/adm5120/patches-2.6.31/802-adm5120-switch-remove-redundant-napi-functions.patch b/target/linux/adm5120/patches-2.6.31/802-adm5120-switch-remove-redundant-napi-functions.patch deleted file mode 100644 index 5c5873b73..000000000 --- a/target/linux/adm5120/patches-2.6.31/802-adm5120-switch-remove-redundant-napi-functions.patch +++ /dev/null @@ -1,20 +0,0 @@ ---- a/drivers/net/adm5120sw.c -+++ b/drivers/net/adm5120sw.c -@@ -517,7 +517,7 @@ static int adm5120_if_poll(struct napi_s - status = sw_int_status() & SWITCH_INTS_POLL; - if ((done < limit) && (!status)) { - SW_DBG("disable polling mode for %s\n", dev->name); -- netif_rx_complete(dev, napi); -+ napi_complete(napi); - sw_int_unmask(SWITCH_INTS_POLL); - return 0; - } -@@ -548,7 +548,7 @@ static irqreturn_t adm5120_switch_irq(in - sw_dump_intr_mask("poll ints", status); - SW_DBG("enable polling mode for %s\n", dev->name); - sw_int_mask(SWITCH_INTS_POLL); -- netif_rx_schedule(dev, &priv->napi); -+ napi_schedule(&priv->napi); - } - #else - sw_int_ack(status); diff --git a/target/linux/adm5120/patches-2.6.31/803-adm5120-fix-clock-for-amba-uart.patch b/target/linux/adm5120/patches-2.6.31/803-adm5120-fix-clock-for-amba-uart.patch deleted file mode 100644 index 795c28578..000000000 --- a/target/linux/adm5120/patches-2.6.31/803-adm5120-fix-clock-for-amba-uart.patch +++ /dev/null @@ -1,21 +0,0 @@ ---- a/arch/mips/adm5120/common/clock.c -+++ b/arch/mips/adm5120/common/clock.c -@@ -19,6 +19,7 @@ - #include - #include - #include -+#include - - #include - -@@ -32,7 +33,9 @@ static struct clk uart_clk = { - - struct clk *clk_get(struct device *dev, const char *id) - { -- if (!strcmp(id, "UARTCLK")) -+ char *name = dev_name(dev); -+ -+ if (!strcmp(name, "apb:uart0") || !strcmp(name, "apb:uart1")) - return &uart_clk; - - return ERR_PTR(-ENOENT); diff --git a/target/linux/adm5120/patches-2.6.31/810-adm5120sw-netdev_ops.patch b/target/linux/adm5120/patches-2.6.31/810-adm5120sw-netdev_ops.patch deleted file mode 100644 index ae116509c..000000000 --- a/target/linux/adm5120/patches-2.6.31/810-adm5120sw-netdev_ops.patch +++ /dev/null @@ -1,52 +0,0 @@ ---- a/drivers/net/adm5120sw.c -+++ b/drivers/net/adm5120sw.c -@@ -973,9 +973,12 @@ static void adm5120_if_set_multicast_lis - - static int adm5120_if_set_mac_address(struct net_device *dev, void *p) - { -- struct sockaddr *addr = p; -+ int ret; -+ -+ ret = eth_mac_addr(dev, p); -+ if (ret) -+ return ret; - -- memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); - adm5120_write_mac(dev); - return 0; - } -@@ -1017,6 +1020,18 @@ static int adm5120_if_do_ioctl(struct ne - return 0; - } - -+static const struct net_device_ops adm5120sw_netdev_ops = { -+ .ndo_open = adm5120_if_open, -+ .ndo_stop = adm5120_if_stop, -+ .ndo_start_xmit = adm5120_if_hard_start_xmit, -+ .ndo_set_multicast_list = adm5120_if_set_multicast_list, -+ .ndo_do_ioctl = adm5120_if_do_ioctl, -+ .ndo_tx_timeout = adm5120_if_tx_timeout, -+ .ndo_validate_addr = eth_validate_addr, -+ .ndo_change_mtu = eth_change_mtu, -+ .ndo_set_mac_address = adm5120_if_set_mac_address, -+}; -+ - static struct net_device *adm5120_if_alloc(void) - { - struct net_device *dev; -@@ -1030,14 +1045,8 @@ static struct net_device *adm5120_if_all - priv->dev = dev; - - dev->irq = ADM5120_IRQ_SWITCH; -- dev->open = adm5120_if_open; -- dev->hard_start_xmit = adm5120_if_hard_start_xmit; -- dev->stop = adm5120_if_stop; -- dev->set_multicast_list = adm5120_if_set_multicast_list; -- dev->do_ioctl = adm5120_if_do_ioctl; -- dev->tx_timeout = adm5120_if_tx_timeout; -+ dev->netdev_ops = &adm5120sw_netdev_ops; - dev->watchdog_timeo = TX_TIMEOUT; -- dev->set_mac_address = adm5120_if_set_mac_address; - - #ifdef CONFIG_ADM5120_SWITCH_NAPI - netif_napi_add(dev, &priv->napi, adm5120_if_poll, 64); diff --git a/target/linux/adm5120/patches-2.6.28/001-adm5120.patch b/target/linux/adm5120/patches-2.6.32/001-adm5120.patch similarity index 90% rename from target/linux/adm5120/patches-2.6.28/001-adm5120.patch rename to target/linux/adm5120/patches-2.6.32/001-adm5120.patch index b67e1081b..5a5750bac 100644 --- a/target/linux/adm5120/patches-2.6.28/001-adm5120.patch +++ b/target/linux/adm5120/patches-2.6.32/001-adm5120.patch @@ -1,6 +1,6 @@ --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig -@@ -19,6 +19,21 @@ choice +@@ -20,6 +20,21 @@ choice prompt "System type" default SGI_IP22 @@ -22,17 +22,17 @@ config MACH_ALCHEMY bool "Alchemy processor based machines" -@@ -597,6 +612,7 @@ config WR_PPMC +@@ -673,6 +688,7 @@ config CAVIUM_OCTEON_REFERENCE_BOARD endchoice +source "arch/mips/adm5120/Kconfig" source "arch/mips/alchemy/Kconfig" source "arch/mips/basler/excite/Kconfig" - source "arch/mips/emma/Kconfig" + source "arch/mips/bcm63xx/Kconfig" --- a/arch/mips/Makefile +++ b/arch/mips/Makefile -@@ -183,6 +183,22 @@ cflags-$(CONFIG_MACH_JAZZ) += -I$(srctre +@@ -191,6 +191,22 @@ cflags-$(CONFIG_MACH_JAZZ) += -I$(srctre load-$(CONFIG_MACH_JAZZ) += 0xffffffff80080000 # diff --git a/target/linux/adm5120/patches-2.6.28/002-adm5120_flash.patch b/target/linux/adm5120/patches-2.6.32/002-adm5120_flash.patch similarity index 75% rename from target/linux/adm5120/patches-2.6.28/002-adm5120_flash.patch rename to target/linux/adm5120/patches-2.6.32/002-adm5120_flash.patch index 16470704a..e3d63ab05 100644 --- a/target/linux/adm5120/patches-2.6.28/002-adm5120_flash.patch +++ b/target/linux/adm5120/patches-2.6.32/002-adm5120_flash.patch @@ -1,18 +1,17 @@ --- a/drivers/mtd/maps/Kconfig +++ b/drivers/mtd/maps/Kconfig -@@ -540,5 +540,9 @@ config MTD_PLATRAM - - This selection automatically selects the map_ram driver. +@@ -557,4 +557,8 @@ config MTD_VMU + To build this as a module select M here, the module will be called + vmu-flash. +config MTD_ADM5120 + tristate "Map driver for ADM5120 based boards" + depends on ADM5120 + endmenu - --- a/drivers/mtd/maps/Makefile +++ b/drivers/mtd/maps/Makefile -@@ -42,6 +42,7 @@ obj-$(CONFIG_MTD_DBOX2) += dbox2-flash. +@@ -41,6 +41,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 diff --git a/target/linux/adm5120/patches-2.6.28/003-adm5120_switch.patch b/target/linux/adm5120/patches-2.6.32/003-adm5120_switch.patch similarity index 85% rename from target/linux/adm5120/patches-2.6.28/003-adm5120_switch.patch rename to target/linux/adm5120/patches-2.6.32/003-adm5120_switch.patch index 1359078aa..cf6350c8c 100644 --- a/target/linux/adm5120/patches-2.6.28/003-adm5120_switch.patch +++ b/target/linux/adm5120/patches-2.6.32/003-adm5120_switch.patch @@ -13,11 +13,11 @@ depends on PCI && SGI_IP27 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile -@@ -191,6 +191,7 @@ obj-$(CONFIG_SC92031) += sc92031.o +@@ -208,6 +208,7 @@ obj-$(CONFIG_SC92031) += sc92031.o # This is also a 82596 and should probably be merged obj-$(CONFIG_LP486E) += lp486e.o +obj-$(CONFIG_ADM5120_ENET) += adm5120sw.o obj-$(CONFIG_ETH16I) += eth16i.o - obj-$(CONFIG_ZORRO8390) += zorro8390.o + obj-$(CONFIG_ZORRO8390) += zorro8390.o 8390.o obj-$(CONFIG_HPLANCE) += hplance.o 7990.o diff --git a/target/linux/adm5120/patches-2.6.28/005-adm5120_usb.patch b/target/linux/adm5120/patches-2.6.32/005-adm5120_usb.patch similarity index 67% rename from target/linux/adm5120/patches-2.6.28/005-adm5120_usb.patch rename to target/linux/adm5120/patches-2.6.32/005-adm5120_usb.patch index 75cd81b79..8b5a55347 100644 --- a/target/linux/adm5120/patches-2.6.28/005-adm5120_usb.patch +++ b/target/linux/adm5120/patches-2.6.32/005-adm5120_usb.patch @@ -1,13 +1,13 @@ --- a/drivers/usb/Makefile +++ b/drivers/usb/Makefile -@@ -17,6 +17,7 @@ obj-$(CONFIG_USB_SL811_HCD) += host/ - obj-$(CONFIG_USB_U132_HCD) += host/ - obj-$(CONFIG_USB_R8A66597_HCD) += host/ - obj-$(CONFIG_USB_HWA_HCD) += host/ +@@ -9,6 +9,7 @@ obj-$(CONFIG_USB) += core/ + obj-$(CONFIG_USB_MON) += mon/ + + obj-$(CONFIG_PCI) += host/ +obj-$(CONFIG_USB_ADM5120_HCD) += host/ - - obj-$(CONFIG_USB_C67X00_HCD) += c67x00/ - + obj-$(CONFIG_USB_EHCI_HCD) += host/ + obj-$(CONFIG_USB_ISP116X_HCD) += host/ + obj-$(CONFIG_USB_OHCI_HCD) += host/ --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -4,6 +4,10 @@ @@ -23,11 +23,11 @@ depends on USB --- a/drivers/usb/host/Makefile +++ b/drivers/usb/host/Makefile -@@ -12,6 +12,7 @@ obj-$(CONFIG_USB_WHCI_HCD) += whci/ +@@ -18,6 +18,7 @@ obj-$(CONFIG_USB_WHCI_HCD) += whci/ obj-$(CONFIG_PCI) += pci-quirks.o +obj-$(CONFIG_USB_ADM5120_HCD) += adm5120-hcd.o obj-$(CONFIG_USB_EHCI_HCD) += ehci-hcd.o + obj-$(CONFIG_USB_OXU210HP_HCD) += oxu210hp-hcd.o obj-$(CONFIG_USB_ISP116X_HCD) += isp116x-hcd.o - obj-$(CONFIG_USB_OHCI_HCD) += ohci-hcd.o diff --git a/target/linux/adm5120/patches-2.6.28/007-adm5120_pci.patch b/target/linux/adm5120/patches-2.6.32/007-adm5120_pci.patch similarity index 72% rename from target/linux/adm5120/patches-2.6.28/007-adm5120_pci.patch rename to target/linux/adm5120/patches-2.6.32/007-adm5120_pci.patch index 3393cfe04..91bd79d76 100644 --- a/target/linux/adm5120/patches-2.6.28/007-adm5120_pci.patch +++ b/target/linux/adm5120/patches-2.6.32/007-adm5120_pci.patch @@ -1,13 +1,16 @@ --- a/arch/mips/pci/Makefile +++ b/arch/mips/pci/Makefile -@@ -52,3 +52,4 @@ obj-$(CONFIG_VICTOR_MPC30X) += fixup-mpc - obj-$(CONFIG_ZAO_CAPCELLA) += fixup-capcella.o +@@ -55,6 +55,7 @@ obj-$(CONFIG_ZAO_CAPCELLA) += fixup-capc obj-$(CONFIG_WR_PPMC) += fixup-wrppmc.o obj-$(CONFIG_MIKROTIK_RB532) += pci-rc32434.o ops-rc32434.o fixup-rc32434.o + obj-$(CONFIG_CPU_CAVIUM_OCTEON) += pci-octeon.o pcie-octeon.o +obj-$(CONFIG_ADM5120) += pci-adm5120.o + + ifdef CONFIG_PCI_MSI + obj-$(CONFIG_CPU_CAVIUM_OCTEON) += msi-octeon.o --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h -@@ -1729,6 +1729,9 @@ +@@ -1748,6 +1748,9 @@ #define PCI_VENDOR_ID_ESDGMBH 0x12fe #define PCI_DEVICE_ID_ESDGMBH_CPCIASIO4 0x0111 diff --git a/target/linux/adm5120/patches-2.6.28/009-adm5120_leds_switch_trigger.patch b/target/linux/adm5120/patches-2.6.32/009-adm5120_leds_switch_trigger.patch similarity index 87% rename from target/linux/adm5120/patches-2.6.28/009-adm5120_leds_switch_trigger.patch rename to target/linux/adm5120/patches-2.6.32/009-adm5120_leds_switch_trigger.patch index 1881892ea..272fb8f19 100644 --- a/target/linux/adm5120/patches-2.6.28/009-adm5120_leds_switch_trigger.patch +++ b/target/linux/adm5120/patches-2.6.32/009-adm5120_leds_switch_trigger.patch @@ -1,6 +1,6 @@ --- a/drivers/leds/Kconfig +++ b/drivers/leds/Kconfig -@@ -234,4 +234,12 @@ config LEDS_TRIGGER_NETDEV +@@ -315,4 +315,12 @@ config LEDS_TRIGGER_NETDEV This allows LEDs to be controlled by network device activity. If unsure, say Y. @@ -15,7 +15,7 @@ endif # NEW_LEDS --- a/drivers/leds/Makefile +++ b/drivers/leds/Makefile -@@ -33,3 +33,4 @@ obj-$(CONFIG_LEDS_TRIGGER_BACKLIGHT) += +@@ -42,3 +42,4 @@ obj-$(CONFIG_LEDS_TRIGGER_GPIO) += ledt 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 diff --git a/target/linux/adm5120/patches-2.6.28/101-cfi_fixup_macronix_bootloc.patch b/target/linux/adm5120/patches-2.6.32/101-cfi_fixup_macronix_bootloc.patch similarity index 100% rename from target/linux/adm5120/patches-2.6.28/101-cfi_fixup_macronix_bootloc.patch rename to target/linux/adm5120/patches-2.6.32/101-cfi_fixup_macronix_bootloc.patch diff --git a/target/linux/adm5120/patches-2.6.28/102-jedec_pmc_39lvxxx_chips.patch b/target/linux/adm5120/patches-2.6.32/102-jedec_pmc_39lvxxx_chips.patch similarity index 94% rename from target/linux/adm5120/patches-2.6.28/102-jedec_pmc_39lvxxx_chips.patch rename to target/linux/adm5120/patches-2.6.32/102-jedec_pmc_39lvxxx_chips.patch index 6c827c851..1847656b4 100644 --- a/target/linux/adm5120/patches-2.6.28/102-jedec_pmc_39lvxxx_chips.patch +++ b/target/linux/adm5120/patches-2.6.32/102-jedec_pmc_39lvxxx_chips.patch @@ -1,6 +1,6 @@ --- a/drivers/mtd/chips/jedec_probe.c +++ b/drivers/mtd/chips/jedec_probe.c -@@ -128,6 +128,10 @@ +@@ -133,6 +133,10 @@ #define UPD29F064115 0x221C /* PMC */ @@ -11,7 +11,7 @@ #define PM49FL002 0x006D #define PM49FL004 0x006E #define PM49FL008 0x006A -@@ -1248,6 +1252,54 @@ static const struct amd_flash_info jedec +@@ -1275,6 +1279,54 @@ static const struct amd_flash_info jedec ERASEINFO(0x02000,2), ERASEINFO(0x04000,1), } diff --git a/target/linux/adm5120/patches-2.6.28/103-mtd_trxsplit.patch b/target/linux/adm5120/patches-2.6.32/103-mtd_trxsplit.patch similarity index 86% rename from target/linux/adm5120/patches-2.6.28/103-mtd_trxsplit.patch rename to target/linux/adm5120/patches-2.6.32/103-mtd_trxsplit.patch index d3b085804..69f103550 100644 --- a/target/linux/adm5120/patches-2.6.28/103-mtd_trxsplit.patch +++ b/target/linux/adm5120/patches-2.6.32/103-mtd_trxsplit.patch @@ -1,6 +1,6 @@ --- a/drivers/mtd/Kconfig +++ b/drivers/mtd/Kconfig -@@ -55,6 +55,11 @@ config MTD_ROOTFS_SPLIT +@@ -63,6 +63,11 @@ config MTD_ROOTFS_SPLIT depends on MTD_PARTITIONS default y @@ -14,7 +14,7 @@ depends on MTD_PARTITIONS --- a/drivers/mtd/Makefile +++ b/drivers/mtd/Makefile -@@ -8,6 +8,7 @@ mtd-y := mtdcore.o mtdsuper.o +@@ -8,6 +8,7 @@ mtd-y := mtdcore.o mtdsuper.o mtdbdi. mtd-$(CONFIG_MTD_PARTITIONS) += mtdpart.o obj-$(CONFIG_MTD_CONCAT) += mtdconcat.o diff --git a/target/linux/adm5120/patches-2.6.28/120-rb153_cf_driver.patch b/target/linux/adm5120/patches-2.6.32/120-rb153_cf_driver.patch similarity index 83% rename from target/linux/adm5120/patches-2.6.28/120-rb153_cf_driver.patch rename to target/linux/adm5120/patches-2.6.32/120-rb153_cf_driver.patch index 32e85907b..c8e2be4f4 100644 --- a/target/linux/adm5120/patches-2.6.28/120-rb153_cf_driver.patch +++ b/target/linux/adm5120/patches-2.6.32/120-rb153_cf_driver.patch @@ -1,7 +1,7 @@ --- a/drivers/ata/Makefile +++ b/drivers/ata/Makefile -@@ -72,6 +72,7 @@ obj-$(CONFIG_PATA_BF54X) += pata_bf54x.o - obj-$(CONFIG_PATA_PLATFORM) += pata_platform.o +@@ -77,6 +77,7 @@ obj-$(CONFIG_PATA_PLATFORM) += pata_plat + obj-$(CONFIG_PATA_AT91) += pata_at91.o obj-$(CONFIG_PATA_OF_PLATFORM) += pata_of_platform.o obj-$(CONFIG_PATA_ICSIDE) += pata_icside.o +obj-$(CONFIG_PATA_RB153_CF) += pata_rb153_cf.o @@ -10,7 +10,7 @@ # Should be last but one libata driver --- a/drivers/ata/Kconfig +++ b/drivers/ata/Kconfig -@@ -567,6 +567,15 @@ config PATA_RADISYS +@@ -597,6 +597,15 @@ config PATA_RADISYS If unsure, say N. diff --git a/target/linux/adm5120/patches-2.6.28/200-amba_pl010_hacks.patch b/target/linux/adm5120/patches-2.6.32/200-amba_pl010_hacks.patch similarity index 99% rename from target/linux/adm5120/patches-2.6.28/200-amba_pl010_hacks.patch rename to target/linux/adm5120/patches-2.6.32/200-amba_pl010_hacks.patch index 285764411..41c88a948 100644 --- a/target/linux/adm5120/patches-2.6.28/200-amba_pl010_hacks.patch +++ b/target/linux/adm5120/patches-2.6.32/200-amba_pl010_hacks.patch @@ -63,7 +63,7 @@ static void pl010_rx_chars(struct uart_amba_port *uap) @@ -120,9 +119,9 @@ static void pl010_rx_chars(struct uart_a - struct tty_struct *tty = uap->port.info->port.tty; + struct tty_struct *tty = uap->port.state->port.tty; unsigned int status, ch, flag, rsr, max_count = 256; - status = readb(uap->port.membase + UART01x_FR); diff --git a/target/linux/adm5120/patches-2.6.28/201-amba_bus_hacks.patch b/target/linux/adm5120/patches-2.6.32/201-amba_bus_hacks.patch similarity index 86% rename from target/linux/adm5120/patches-2.6.28/201-amba_bus_hacks.patch rename to target/linux/adm5120/patches-2.6.32/201-amba_bus_hacks.patch index 299f21652..9db3e55ad 100644 --- a/target/linux/adm5120/patches-2.6.28/201-amba_bus_hacks.patch +++ b/target/linux/adm5120/patches-2.6.32/201-amba_bus_hacks.patch @@ -1,7 +1,7 @@ --- a/drivers/amba/bus.c +++ b/drivers/amba/bus.c -@@ -17,6 +17,10 @@ - #include +@@ -18,6 +18,10 @@ + #include #include +#ifndef NO_IRQ diff --git a/target/linux/adm5120/patches-2.6.28/203-gpio_leds_brightness.patch b/target/linux/adm5120/patches-2.6.32/203-gpio_leds_brightness.patch similarity index 90% rename from target/linux/adm5120/patches-2.6.28/203-gpio_leds_brightness.patch rename to target/linux/adm5120/patches-2.6.32/203-gpio_leds_brightness.patch index bb94fd05e..8bccf395c 100644 --- a/target/linux/adm5120/patches-2.6.28/203-gpio_leds_brightness.patch +++ b/target/linux/adm5120/patches-2.6.32/203-gpio_leds_brightness.patch @@ -1,6 +1,6 @@ --- a/drivers/leds/leds-gpio.c +++ b/drivers/leds/leds-gpio.c -@@ -43,13 +43,17 @@ static void gpio_led_set(struct led_clas +@@ -44,13 +44,17 @@ static void gpio_led_set(struct led_clas container_of(led_cdev, struct gpio_led_data, cdev); int level; diff --git a/target/linux/adm5120/patches-2.6.28/310-adm5120_wdt.patch b/target/linux/adm5120/patches-2.6.32/310-adm5120_wdt.patch similarity index 90% rename from target/linux/adm5120/patches-2.6.28/310-adm5120_wdt.patch rename to target/linux/adm5120/patches-2.6.32/310-adm5120_wdt.patch index 2346009f8..b7833c72a 100644 --- a/target/linux/adm5120/patches-2.6.28/310-adm5120_wdt.patch +++ b/target/linux/adm5120/patches-2.6.32/310-adm5120_wdt.patch @@ -1,6 +1,6 @@ --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig -@@ -696,6 +696,18 @@ config RC32434_WDT +@@ -790,6 +790,18 @@ config RC32434_WDT To compile this driver as a module, choose M here: the module will be called rc32434_wdt. @@ -21,7 +21,7 @@ depends on SGI_HAS_INDYDOG --- a/drivers/watchdog/Makefile +++ b/drivers/watchdog/Makefile -@@ -106,6 +106,7 @@ obj-$(CONFIG_WDT_RM9K_GPI) += rm9k_wdt.o +@@ -113,6 +113,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 diff --git a/target/linux/adm5120/router_be/config-2.6.28 b/target/linux/adm5120/router_be/config-2.6.32 similarity index 87% rename from target/linux/adm5120/router_be/config-2.6.28 rename to target/linux/adm5120/router_be/config-2.6.32 index 0ae8fac27..7bba47a6e 100644 --- a/target/linux/adm5120/router_be/config-2.6.28 +++ b/target/linux/adm5120/router_be/config-2.6.32 @@ -1,7 +1,8 @@ CONFIG_32BIT=y # CONFIG_64BIT is not set +CONFIG_ADM5120=y CONFIG_ADM5120_ENET=y -# CONFIG_ADM5120_MACH_5GXI is not set +CONFIG_ADM5120_MACH_5GXI=y CONFIG_ADM5120_MACH_P_334WT=y CONFIG_ADM5120_MACH_P_335=y # CONFIG_ADM5120_OEM_CELLVISION is not set @@ -10,13 +11,15 @@ CONFIG_ADM5120_MACH_P_335=y # CONFIG_ADM5120_OEM_INFINEON is not set # CONFIG_ADM5120_OEM_MIKROTIK is not set # CONFIG_ADM5120_OEM_MOTOROLA is not set -# CONFIG_ADM5120_OEM_OSBRIDGE is not set +CONFIG_ADM5120_OEM_OSBRIDGE=y CONFIG_ADM5120_OEM_ZYXEL=y CONFIG_ADM5120_SOC_BGA=y CONFIG_ADM5120_WDT=y -CONFIG_ADM5120=y +# CONFIG_ALCHEMY_GPIO_INDIRECT is not set +# CONFIG_AR7 is not set # CONFIG_ARCH_HAS_ILOG2_U32 is not set # CONFIG_ARCH_HAS_ILOG2_U64 is not set +CONFIG_ARCH_HIBERNATION_POSSIBLE=y CONFIG_ARCH_POPULATES_NODE_MAP=y CONFIG_ARCH_REQUIRE_GPIOLIB=y # CONFIG_ARCH_SUPPORTS_MSI is not set @@ -24,21 +27,25 @@ CONFIG_ARCH_SUPPORTS_OPROFILE=y CONFIG_ARCH_SUSPEND_POSSIBLE=y CONFIG_ARM_AMBA=y # CONFIG_BCM47XX is not set +# CONFIG_BCM63XX is not set CONFIG_BINFMT_MISC=m CONFIG_BITREVERSE=y +# CONFIG_CAVIUM_OCTEON_REFERENCE_BOARD is not set +# CONFIG_CAVIUM_OCTEON_SIMULATOR is not set CONFIG_CC_OPTIMIZE_FOR_SIZE=y CONFIG_CEVT_R4K=y -CONFIG_CLASSIC_RCU=y +CONFIG_CEVT_R4K_LIB=y +CONFIG_CFG80211_DEFAULT_PS_VALUE=0 CONFIG_CMDLINE="console=ttyS0,115200 rootfstype=squashfs,jffs2" CONFIG_CPU_BIG_ENDIAN=y -CONFIG_CPU_HAS_LLSC=y +# CONFIG_CPU_CAVIUM_OCTEON is not set 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_LOONGSON2E is not set +CONFIG_CPU_MIPS32=y CONFIG_CPU_MIPS32_R1=y # CONFIG_CPU_MIPS32_R2 is not set -CONFIG_CPU_MIPS32=y # CONFIG_CPU_MIPS64_R1 is not set # CONFIG_CPU_MIPS64_R2 is not set CONFIG_CPU_MIPSR1=y @@ -61,6 +68,8 @@ CONFIG_CPU_SUPPORTS_HIGHMEM=y # CONFIG_CPU_TX49XX is not set # CONFIG_CPU_VR41XX is not set CONFIG_CSRC_R4K=y +CONFIG_CSRC_R4K_LIB=y +CONFIG_DECOMPRESS_LZMA=y CONFIG_DEVPORT=y # CONFIG_DM9000 is not set CONFIG_DMA_NEED_PCI_MAP_STATE=y @@ -70,55 +79,54 @@ CONFIG_ELF_CORE=y CONFIG_FIRMWARE_IN_KERNEL=y CONFIG_FS_POSIX_ACL=y CONFIG_GENERIC_ACL=y -CONFIG_GENERIC_CLOCKEVENTS_BUILD=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_GENERIC_HARDIRQS_NO__DO_IRQ=y CONFIG_GPIOLIB=y +# CONFIG_GPIO_PL061 is not set 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_GENERIC_DMA_COHERENT=y CONFIG_HAVE_IDE=y CONFIG_HAVE_OPROFILE=y -CONFIG_HID_COMPAT=y CONFIG_HID=m CONFIG_HID_SUPPORT=y CONFIG_HW_HAS_PCI=y CONFIG_HW_RANDOM=y -# CONFIG_HZ_100 is not set CONFIG_HZ=250 +# CONFIG_HZ_100 is not set CONFIG_HZ_250=y -# CONFIG_IDE is not set CONFIG_INITRAMFS_SOURCE="" -CONFIG_INOTIFY_USER=y CONFIG_INOTIFY=y -# CONFIG_INPUT_GPIO_BUTTONS is not set +CONFIG_INOTIFY_USER=y CONFIG_INPUT=m +# CONFIG_INPUT_GPIO_BUTTONS is not set # CONFIG_INPUT_YEALINK is not set CONFIG_IRQ_CPU=y # CONFIG_ISDN is not set CONFIG_LEDS_GPIO=m CONFIG_LEDS_TRIGGER_ADM5120_SWITCH=m -CONFIG_LEGACY_PTY_COUNT=256 CONFIG_LEGACY_PTYS=y -# CONFIG_LEMOTE_FULONG is not set +CONFIG_LEGACY_PTY_COUNT=256 # CONFIG_MACH_ALCHEMY is not set # CONFIG_MACH_DECSTATION is not set -# CONFIG_MACH_EMMA is not set # CONFIG_MACH_JAZZ is not set +# CONFIG_MACH_LOONGSON is not set # CONFIG_MACH_TX39XX is not set # CONFIG_MACH_TX49XX is not set # CONFIG_MACH_VR41XX is not set CONFIG_MII=m # 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 @@ -126,7 +134,6 @@ 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_MIPS=y CONFIG_MODULE_FORCE_UNLOAD=y CONFIG_MTD_ADM5120=y CONFIG_MTD_BLOCK2MTD=y @@ -135,6 +142,7 @@ CONFIG_MTD_CFI_FIXUP_MACRONIX_BOOTLOC=y CONFIG_MTD_CMDLINE_PARTS=y CONFIG_MTD_TRXSPLIT=y # CONFIG_NET_PCI is not set +CONFIG_NLS=m # CONFIG_NO_IOPORT is not set # CONFIG_NXP_STB220 is not set # CONFIG_NXP_STB225 is not set @@ -147,21 +155,21 @@ CONFIG_PCI_DOMAINS=y # CONFIG_PNX8550_JBS is not set # CONFIG_PNX8550_STB810 is not set # CONFIG_PROBE_INITRD_HEADER is not set -CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y +CONFIG_SCHED_OMIT_FRAME_POINTER=y # CONFIG_SCSI_DMA is not set # CONFIG_SERIAL_8250 is not set +CONFIG_SERIAL_AMBA_PL010=y CONFIG_SERIAL_AMBA_PL010_CONSOLE=y CONFIG_SERIAL_AMBA_PL010_NUMPORTS=2 CONFIG_SERIAL_AMBA_PL010_PORTNAME="ttyS" -CONFIG_SERIAL_AMBA_PL010=y # CONFIG_SERIAL_AMBA_PL011 is not set +CONFIG_SERIO=y # CONFIG_SERIO_AMBAKMI is not set # CONFIG_SERIO_I8042 is not set # CONFIG_SERIO_LIBPS2 is not set # CONFIG_SERIO_PCIPS2 is not set # CONFIG_SERIO_RAW is not set CONFIG_SERIO_SERPORT=y -CONFIG_SERIO=y # CONFIG_SGI_IP22 is not set # CONFIG_SGI_IP27 is not set # CONFIG_SGI_IP28 is not set @@ -186,15 +194,16 @@ CONFIG_SYS_SUPPORTS_BIG_ENDIAN=y CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y CONFIG_TMPFS_POSIX_ACL=y CONFIG_TRAD_SIGNALS=y +# CONFIG_TREE_PREEMPT_RCU is not set +CONFIG_TREE_RCU=y +CONFIG_USB=m CONFIG_USB_ADM5120_HCD=m CONFIG_USB_DEBUG=y CONFIG_USB_EHCI_HCD=m -CONFIG_USB=m # CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set # CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set CONFIG_USB_OHCI_HCD=m CONFIG_USB_SUPPORT=y # CONFIG_USB_UHCI_HCD is not set -# CONFIG_VGASTATE is not set CONFIG_VM_EVENT_COUNTERS=y CONFIG_ZONE_DMA_FLAG=0 diff --git a/target/linux/adm5120/router_le/config-2.6.28 b/target/linux/adm5120/router_le/config-2.6.32 similarity index 86% rename from target/linux/adm5120/router_le/config-2.6.28 rename to target/linux/adm5120/router_le/config-2.6.32 index 22ced5eaf..fb363b205 100644 --- a/target/linux/adm5120/router_le/config-2.6.28 +++ b/target/linux/adm5120/router_le/config-2.6.32 @@ -1,10 +1,10 @@ CONFIG_32BIT=y # CONFIG_64BIT is not set -# CONFIG_8139TOO is not set +CONFIG_ADM5120=y CONFIG_ADM5120_ENET=y CONFIG_ADM5120_MACH_5GXI=y -CONFIG_ADM5120_MACH_BR_6104KP=y CONFIG_ADM5120_MACH_BR_6104K=y +CONFIG_ADM5120_MACH_BR_6104KP=y CONFIG_ADM5120_MACH_BR_61X4WG=y CONFIG_ADM5120_MACH_CAS_771=y CONFIG_ADM5120_MACH_EASY5120P_ATA=y @@ -16,8 +16,8 @@ CONFIG_ADM5120_MACH_NP27G=y CONFIG_ADM5120_MACH_NP28G=y CONFIG_ADM5120_MACH_PMUGW=y CONFIG_ADM5120_MACH_RB_11X=y -CONFIG_ADM5120_MACH_RB_133C=y CONFIG_ADM5120_MACH_RB_133=y +CONFIG_ADM5120_MACH_RB_133C=y CONFIG_ADM5120_MACH_RB_150=y CONFIG_ADM5120_MACH_RB_153=y CONFIG_ADM5120_MACH_RB_192=y @@ -32,9 +32,11 @@ CONFIG_ADM5120_OEM_OSBRIDGE=y # CONFIG_ADM5120_OEM_ZYXEL is not set CONFIG_ADM5120_SOC_BGA=y CONFIG_ADM5120_WDT=y -CONFIG_ADM5120=y +# CONFIG_ALCHEMY_GPIO_INDIRECT is not set +# CONFIG_AR7 is not set # CONFIG_ARCH_HAS_ILOG2_U32 is not set # CONFIG_ARCH_HAS_ILOG2_U64 is not set +CONFIG_ARCH_HIBERNATION_POSSIBLE=y CONFIG_ARCH_POPULATES_NODE_MAP=y CONFIG_ARCH_REQUIRE_GPIOLIB=y # CONFIG_ARCH_SUPPORTS_MSI is not set @@ -42,21 +44,26 @@ CONFIG_ARCH_SUPPORTS_OPROFILE=y CONFIG_ARCH_SUSPEND_POSSIBLE=y CONFIG_ARM_AMBA=y CONFIG_ATA=m +# CONFIG_ATA_PIIX is not set # CONFIG_BCM47XX is not set +# CONFIG_BCM63XX is not set CONFIG_BITREVERSE=y +# CONFIG_CAVIUM_OCTEON_REFERENCE_BOARD is not set +# CONFIG_CAVIUM_OCTEON_SIMULATOR is not set CONFIG_CC_OPTIMIZE_FOR_SIZE=y CONFIG_CEVT_R4K=y -CONFIG_CLASSIC_RCU=y +CONFIG_CEVT_R4K_LIB=y +CONFIG_CFG80211_DEFAULT_PS_VALUE=0 CONFIG_CMDLINE="console=ttyS0,115200 rootfstype=squashfs,yaffs2,jffs2" # CONFIG_CPU_BIG_ENDIAN is not set -CONFIG_CPU_HAS_LLSC=y +# CONFIG_CPU_CAVIUM_OCTEON is not set CONFIG_CPU_HAS_PREFETCH=y CONFIG_CPU_HAS_SYNC=y CONFIG_CPU_LITTLE_ENDIAN=y -# CONFIG_CPU_LOONGSON2 is not set +# CONFIG_CPU_LOONGSON2E is not set +CONFIG_CPU_MIPS32=y CONFIG_CPU_MIPS32_R1=y # CONFIG_CPU_MIPS32_R2 is not set -CONFIG_CPU_MIPS32=y # CONFIG_CPU_MIPS64_R1 is not set # CONFIG_CPU_MIPS64_R2 is not set CONFIG_CPU_MIPSR1=y @@ -78,18 +85,22 @@ CONFIG_CPU_SUPPORTS_HIGHMEM=y # CONFIG_CPU_TX39XX is not set # CONFIG_CPU_TX49XX is not set # CONFIG_CPU_VR41XX is not set -CONFIG_CRYPTO_AEAD2=m -CONFIG_CRYPTO_ALGAPI2=m -CONFIG_CRYPTO_ALGAPI=m +CONFIG_CRYPTO_AEAD2=y +CONFIG_CRYPTO_AES=m CONFIG_CRYPTO_ARC4=m -CONFIG_CRYPTO_BLKCIPHER2=m CONFIG_CRYPTO_BLKCIPHER=m +CONFIG_CRYPTO_BLKCIPHER2=y CONFIG_CRYPTO_ECB=m -CONFIG_CRYPTO_HASH2=m -CONFIG_CRYPTO_MANAGER2=m +CONFIG_CRYPTO_HASH=m +CONFIG_CRYPTO_HASH2=y CONFIG_CRYPTO_MANAGER=m -CONFIG_CRYPTO_RNG2=m +CONFIG_CRYPTO_MANAGER2=y +CONFIG_CRYPTO_MICHAEL_MIC=m +CONFIG_CRYPTO_RNG2=y +CONFIG_CRYPTO_WORKQUEUE=y CONFIG_CSRC_R4K=y +CONFIG_CSRC_R4K_LIB=y +CONFIG_DECOMPRESS_LZMA=y CONFIG_DEVPORT=y # CONFIG_DM9000 is not set CONFIG_DMA_NEED_PCI_MAP_STATE=y @@ -99,13 +110,15 @@ CONFIG_ELF_CORE=y CONFIG_FIRMWARE_IN_KERNEL=y CONFIG_FS_POSIX_ACL=y CONFIG_GENERIC_ACL=y -CONFIG_GENERIC_CLOCKEVENTS_BUILD=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_GENERIC_HARDIRQS_NO__DO_IRQ=y CONFIG_GPIOLIB=y +# CONFIG_GPIO_PL061 is not set CONFIG_GPIO_SYSFS=y # CONFIG_HAMRADIO is not set CONFIG_HARDWARE_WATCHPOINTS=y @@ -113,50 +126,49 @@ 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_GENERIC_DMA_COHERENT=y CONFIG_HAVE_IDE=y CONFIG_HAVE_OPROFILE=y -CONFIG_HID_COMPAT=y CONFIG_HID=m CONFIG_HID_SUPPORT=y -# CONFIG_HOSTAP_FIRMWARE_NVRAM is not set -CONFIG_HOSTAP_FIRMWARE=y CONFIG_HOSTAP=m +CONFIG_HOSTAP_FIRMWARE=y +# CONFIG_HOSTAP_FIRMWARE_NVRAM is not set CONFIG_HOSTAP_PCI=m CONFIG_HW_HAS_PCI=y CONFIG_HW_RANDOM=y -# CONFIG_HZ_100 is not set CONFIG_HZ=250 +# CONFIG_HZ_100 is not set CONFIG_HZ_250=y -# CONFIG_IDE is not set -CONFIG_IEEE80211_CRYPT_WEP=m -CONFIG_IEEE80211=m CONFIG_IMAGE_CMDLINE_HACK=y CONFIG_INITRAMFS_SOURCE="" -CONFIG_INOTIFY_USER=y CONFIG_INOTIFY=y -# CONFIG_INPUT_GPIO_BUTTONS is not set +CONFIG_INOTIFY_USER=y CONFIG_INPUT=m +# CONFIG_INPUT_GPIO_BUTTONS is not set # CONFIG_INPUT_YEALINK is not set CONFIG_IRQ_CPU=y # CONFIG_ISDN is not set CONFIG_KEXEC=y CONFIG_LEDS_GPIO=m CONFIG_LEDS_TRIGGER_ADM5120_SWITCH=m -CONFIG_LEGACY_PTY_COUNT=256 CONFIG_LEGACY_PTYS=y -# CONFIG_LEMOTE_FULONG is not set +CONFIG_LEGACY_PTY_COUNT=256 +CONFIG_LIB80211=m +CONFIG_LIB80211_CRYPT_CCMP=m +CONFIG_LIB80211_CRYPT_TKIP=m +CONFIG_LIB80211_CRYPT_WEP=m # CONFIG_MACH_ALCHEMY is not set # CONFIG_MACH_DECSTATION is not set -# CONFIG_MACH_EMMA is not set # CONFIG_MACH_JAZZ is not set +# CONFIG_MACH_LOONGSON is not set # CONFIG_MACH_TX39XX is not set # CONFIG_MACH_TX49XX is not set # CONFIG_MACH_VR41XX is not set CONFIG_MII=m # 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 @@ -164,7 +176,6 @@ 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_MIPS=y CONFIG_MODULE_FORCE_UNLOAD=y CONFIG_MTD_ADM5120=y CONFIG_MTD_CFI_FIXUP_MACRONIX_BOOTLOC=y @@ -172,9 +183,10 @@ CONFIG_MTD_CFI_FIXUP_MACRONIX_BOOTLOC=y CONFIG_MTD_CMDLINE_PARTS=y CONFIG_MTD_JEDECPROBE=y CONFIG_MTD_MYLOADER_PARTS=y -CONFIG_MTD_NAND_PLATFORM=y CONFIG_MTD_NAND=y +CONFIG_MTD_NAND_PLATFORM=y CONFIG_MTD_TRXSPLIT=y +CONFIG_NLS=m CONFIG_NO_HZ=y # CONFIG_NO_IOPORT is not set # CONFIG_NXP_STB220 is not set @@ -189,22 +201,21 @@ CONFIG_PCI_DOMAINS=y # CONFIG_PNX8550_JBS is not set # CONFIG_PNX8550_STB810 is not set # CONFIG_PROBE_INITRD_HEADER is not set -# CONFIG_R6040 is not set -CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y +CONFIG_SCHED_OMIT_FRAME_POINTER=y CONFIG_SCSI=m # CONFIG_SERIAL_8250 is not set +CONFIG_SERIAL_AMBA_PL010=y CONFIG_SERIAL_AMBA_PL010_CONSOLE=y CONFIG_SERIAL_AMBA_PL010_NUMPORTS=2 CONFIG_SERIAL_AMBA_PL010_PORTNAME="ttyS" -CONFIG_SERIAL_AMBA_PL010=y # CONFIG_SERIAL_AMBA_PL011 is not set +CONFIG_SERIO=y # CONFIG_SERIO_AMBAKMI is not set # CONFIG_SERIO_I8042 is not set # CONFIG_SERIO_LIBPS2 is not set # CONFIG_SERIO_PCIPS2 is not set # CONFIG_SERIO_RAW is not set CONFIG_SERIO_SERPORT=y -CONFIG_SERIO=y # CONFIG_SGI_IP22 is not set # CONFIG_SGI_IP27 is not set # CONFIG_SGI_IP28 is not set @@ -230,16 +241,16 @@ CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y # CONFIG_TC35815 is not set CONFIG_TMPFS_POSIX_ACL=y CONFIG_TRAD_SIGNALS=y +# CONFIG_TREE_PREEMPT_RCU is not set +CONFIG_TREE_RCU=y +CONFIG_USB=m CONFIG_USB_ADM5120_HCD=m CONFIG_USB_EHCI_HCD=m -CONFIG_USB=m # CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set # CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set CONFIG_USB_OHCI_HCD=m CONFIG_USB_SUPPORT=y # CONFIG_USB_UHCI_HCD is not set -# CONFIG_VGASTATE is not set -# CONFIG_VIA_RHINE is not set CONFIG_VLAN_8021Q=m CONFIG_VM_EVENT_COUNTERS=y CONFIG_YAFFS_9BYTE_TAGS=y diff --git a/target/linux/amazon/Makefile b/target/linux/amazon/Makefile index d0787ca25..826937a5f 100644 --- a/target/linux/amazon/Makefile +++ b/target/linux/amazon/Makefile @@ -10,7 +10,7 @@ ARCH:=mips BOARD:=amazon BOARDNAME:=Infineon Amazon FEATURES:=squashfs jffs2 broken -LINUX_VERSION:=2.6.30.9 +LINUX_VERSION:=2.6.30.10 include $(INCLUDE_DIR)/target.mk diff --git a/target/linux/amazon/config-2.6.30 b/target/linux/amazon/config-2.6.30 index bb6bca05c..fa062cee9 100644 --- a/target/linux/amazon/config-2.6.30 +++ b/target/linux/amazon/config-2.6.30 @@ -138,6 +138,7 @@ CONFIG_SCHED_OMIT_FRAME_POINTER=y # CONFIG_SIBYTE_SENTOSA is not set # CONFIG_SIBYTE_SWARM is not set # CONFIG_SLOW_WORK is not set +CONFIG_SWAP_IO_SPACE=y CONFIG_SYS_HAS_CPU_MIPS32_R1=y CONFIG_SYS_HAS_CPU_MIPS32_R2=y CONFIG_SYS_HAS_EARLY_PRINTK=y @@ -146,4 +147,5 @@ CONFIG_SYS_SUPPORTS_ARBIT_HZ=y CONFIG_SYS_SUPPORTS_BIG_ENDIAN=y CONFIG_TRACING_SUPPORT=y CONFIG_TRAD_SIGNALS=y +CONFIG_USB_SUPPORT=y CONFIG_ZONE_DMA_FLAG=0 diff --git a/target/linux/amazon/files/arch/mips/amazon/Makefile b/target/linux/amazon/files/arch/mips/amazon/Makefile index 9cdc100b8..47761a277 100644 --- a/target/linux/amazon/files/arch/mips/amazon/Makefile +++ b/target/linux/amazon/files/arch/mips/amazon/Makefile @@ -4,6 +4,6 @@ # # Makefile for Infineon Amazon # -obj-y := dma-core.o interrupt.o prom.o setup.o +obj-y := dma-core.o interrupt.o prom.o setup.o board.o obj-$(CONFIG_PCI) += pci.o diff --git a/target/linux/amazon/files/arch/mips/amazon/board.c b/target/linux/amazon/files/arch/mips/amazon/board.c new file mode 100644 index 000000000..330cec608 --- /dev/null +++ b/target/linux/amazon/files/arch/mips/amazon/board.c @@ -0,0 +1,69 @@ +/* + * 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, MA 02111-1307, USA. + * + * Copyright (C) 2009 Hauke Mehrtens + */ + + +#include +#include + +#define AMAZON_FLASH_START 0x13000000 +#define AMAZON_FLASH_MAX 0x1000000 + +static struct platform_device amazon_mii = { + .id = 0, + .name = "amazon_mii0", +// .dev = { +// .platform_data = amazon_ethaddr, +// } +}; + +static struct platform_device amazon_wdt = { + .id = 0, + .name = "amazon_wdt", +}; + +static struct platform_device amazon_asc = { + .id = 0, + .name = "amazon_asc", +}; + +static struct resource amazon_mtd_resource = { + .start = AMAZON_FLASH_START, + .end = AMAZON_FLASH_START + AMAZON_FLASH_MAX - 1, + .flags = IORESOURCE_MEM, +}; + +static struct platform_device amazon_mtd = { + .id = 0, + .name = "amazon_mtd", + .num_resources = 1, + .resource = &amazon_mtd_resource, +}; + + +struct platform_device *amazon_devs[] = { + &amazon_mii, &amazon_mtd, &amazon_wdt, &amazon_asc +}; + + +int __init amazon_init_devices(void) +{ + printk(KERN_INFO ""); + return platform_add_devices(amazon_devs, 4); +} + +arch_initcall(amazon_init_devices); diff --git a/target/linux/amazon/files/arch/mips/amazon/pci.c b/target/linux/amazon/files/arch/mips/amazon/pci.c index ab305a983..1b2afb9d4 100644 --- a/target/linux/amazon/files/arch/mips/amazon/pci.c +++ b/target/linux/amazon/files/arch/mips/amazon/pci.c @@ -36,7 +36,7 @@ #endif #define AMAZON_PCI_MEM_SIZE 0x00400000 #define AMAZON_PCI_IO_BASE 0xb2400000 -#define AMAZON_PCI_IO_SIZE 0x00002000 +#define AMAZON_PCI_IO_SIZE 0x00200000 #define AMAZON_PCI_CFG_BUSNUM_SHF 16 #define AMAZON_PCI_CFG_DEVNUM_SHF 11 @@ -45,27 +45,15 @@ #define PCI_ACCESS_READ 0 #define PCI_ACCESS_WRITE 1 -static inline u32 amazon_r32(u32 addr) -{ - u32 *ptr = (u32 *) addr; - return __raw_readl(ptr); -} - -static inline void amazon_w32(u32 addr, u32 val) -{ - u32 *ptr = (u32 *) addr; - __raw_writel(val, ptr); -} - - static struct resource pci_io_resource = { .name = "io pci IO space", -#if 0 +#if 1 .start = AMAZON_PCI_IO_BASE, .end = AMAZON_PCI_IO_BASE + AMAZON_PCI_IO_SIZE - 1, -#endif +#else .start = 0, - .end = AMAZON_PCI_IO_SIZE - 1, + .end = 0x00002000 - 1, +#endif .flags = IORESOURCE_IO }; @@ -76,15 +64,6 @@ static struct resource pci_mem_resource = { .flags = IORESOURCE_MEM }; -static inline u32 amazon_pci_swap(u32 val) -{ -#ifdef CONFIG_AMAZON_PCI_HW_SWAP - return swab32(val); -#else - return val; -#endif -} - static int amazon_pci_config_access(unsigned char access_type, struct pci_bus *bus, unsigned int devfn, unsigned int where, u32 *data) { @@ -92,31 +71,43 @@ static int amazon_pci_config_access(unsigned char access_type, u32 pci_addr; u32 val; int ret; - + /* Amazon support slot from 0 to 15 */ /* devfn 0 & 0x20 is itself */ - if ((bus != 0) || (devfn == 0) || (devfn == 0x20)) + if ((bus->number != 0) || (devfn > 0x7f) || (devfn == 0) || (devfn == 0x20)) return 1; - pci_addr=AMAZON_PCI_CFG_BASE | + local_irq_save(flags); + + pci_addr = AMAZON_PCI_CFG_BASE | bus->number << AMAZON_PCI_CFG_BUSNUM_SHF | devfn << AMAZON_PCI_CFG_FUNNUM_SHF | (where & ~0x3); - - local_irq_save(flags); - if (access_type == PCI_ACCESS_WRITE) { - val = amazon_pci_swap(*data); + + if (access_type == PCI_ACCESS_WRITE) + { +#ifdef CONFIG_SWAP_IO_SPACE + val = swab32(*data); +#endif ret = put_dbe(val, (u32 *)pci_addr); } else { ret = get_dbe(val, (u32 *)pci_addr); - *data = amazon_pci_swap(val); +#ifdef CONFIG_SWAP_IO_SPACE + *data = swab32(val); +#else + *data = val; +#endif } - amazon_w32(PCI_MODE, amazon_r32(PCI_MODE) & (~(1<> ((where & 3) << 3)) & 0xff; - break; - case 2: - *((u16 *) val) = (data >> ((where & 3) << 3)) & 0xffff; - break; - case 4: - *val = data; - break; - default: - return -1; - } + if (size == 1) + *val = (data >> ((where & 3) << 3)) & 0xff; + else if (size == 2) + *val = (data >> ((where & 3) << 3)) & 0xffff; + else + *val = data; - return ret; + return PCIBIOS_SUCCESSFUL; } static int amazon_pci_write(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 val) { - if (size != 4) { - u32 data; + u32 data = 0; + if (size == 4) + { + data = val; + } else { if (amazon_pci_config_access(PCI_ACCESS_READ, bus, devfn, where, &data)) - return -1; + return PCIBIOS_DEVICE_NOT_FOUND; if (size == 1) - val = (data & ~(0xff << ((where & 3) << 3))) | (val << ((where & 3) << 3)); + data = (data & ~(0xff << ((where & 3) << 3))) | + (val << ((where & 3) << 3)); else if (size == 2) - val = (data & ~(0xffff << ((where & 3) << 3))) | (val << ((where & 3) << 3)); - else - return -1; + data = (data & ~(0xffff << ((where & 3) << 3))) | + (val << ((where & 3) << 3)); } - if (amazon_pci_config_access(PCI_ACCESS_WRITE, bus, devfn, where, &val)) - return -1; + if (amazon_pci_config_access(PCI_ACCESS_WRITE, bus, devfn, where, &data)) + return PCIBIOS_DEVICE_NOT_FOUND; return PCIBIOS_SUCCESSFUL; } @@ -179,10 +163,12 @@ static struct pci_ops amazon_pci_ops = { static struct pci_controller amazon_pci_controller = { .pci_ops = &amazon_pci_ops, .mem_resource = &pci_mem_resource, - .io_resource = &pci_io_resource + .mem_offset = 0x00000000UL, + .io_resource = &pci_io_resource, + .io_offset = 0x00000000UL, }; -int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin) +int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) { switch (slot) { case 13: @@ -240,17 +226,17 @@ int pcibios_plat_dev_init(struct pci_dev *dev) return 0; } -int amazon_pci_init(void) +int __init amazon_pci_init(void) { u32 temp_buffer; -#ifdef CONFIG_AMAZON_PCI_HW_SWAP +#ifdef CONFIG_SWAP_IO_SPACE AMAZON_PCI_REG32(IRM) = AMAZON_PCI_REG32(IRM) | (1<<27) | (1<<28); wmb(); #endif AMAZON_PCI_REG32(CLOCK_CONTROL) = AMAZON_PCI_REG32(CLOCK_CONTROL) | (1< #include #include +#include #include #include @@ -206,7 +207,7 @@ static struct file_operations wdt_fops = { release: wdt_release, }; -int __init amazon_wdt_init_module(void) +static int __init amazon_wdt_probe(struct platform_device *dev) { int result = result = register_chrdev(0, "watchdog", &wdt_fops); @@ -226,7 +227,7 @@ int __init amazon_wdt_init_module(void) return 0; } -void amazon_wdt_cleanup_module(void) +static int amazon_wdt_remove(struct platform_device *dev) { unregister_chrdev(0, "watchdog"); #ifdef AMAZON_WDT_DEBUG @@ -234,13 +235,35 @@ void amazon_wdt_cleanup_module(void) remove_proc_entry("amazon_wdt", NULL); #endif printk(KERN_INFO DRV_NAME "unregistered\n"); - return; + return 0; } +static struct platform_driver amazon_wdt_driver = { + .probe = amazon_wdt_probe, + .remove = amazon_wdt_remove, + .driver = { + .name = "amazon_wdt", + .owner = THIS_MODULE, + }, +}; + +static int __init amazon_wdt_init(void) +{ + int ret = platform_driver_register(&amazon_wdt_driver); + if (ret) + printk(KERN_WARNING "amazon_wdt: error registering platfom driver!\n"); + return ret; +} + +static void __exit amazon_wdt_exit(void) +{ + platform_driver_unregister(&amazon_wdt_driver); +} + +module_init(amazon_wdt_init); +module_exit(amazon_wdt_exit); + MODULE_LICENSE ("GPL"); MODULE_AUTHOR("Infineon / John Crispin "); MODULE_DESCRIPTION("AMAZON WDT driver"); -module_init(amazon_wdt_init_module); -module_exit(amazon_wdt_cleanup_module); - diff --git a/target/linux/amazon/files/drivers/mtd/maps/amazon.c b/target/linux/amazon/files/drivers/mtd/maps/amazon.c index 8c3114189..55bfe3237 100644 --- a/target/linux/amazon/files/drivers/mtd/maps/amazon.c +++ b/target/linux/amazon/files/drivers/mtd/maps/amazon.c @@ -20,6 +20,7 @@ // copyright 2007 john crispin // copyright 2007 felix fietkau +// copyright 2009 hauke mehrtens #include #include @@ -32,6 +33,7 @@ #include #include #include +#include #include #define AMAZON_PCI_ARB_CTL_ALT 0xb100205c @@ -41,7 +43,6 @@ static struct map_info amazon_map = { .name = "AMAZON_FLASH", .bankwidth = 2, - .size = 0x1000000, }; static map_word amazon_read16(struct map_info * map, unsigned long ofs) @@ -62,7 +63,6 @@ void amazon_copy_from(struct map_info *map, void *to, unsigned long from, ssize_ { u8 *p; u8 *to_8; - ssize_t l = len; from = (unsigned long) (from + map->virt); p = (u8 *) from; to_8 = (u8 *) to; @@ -102,9 +102,6 @@ static struct mtd_partition amazon_partitions[3] = { }, }; - -unsigned long flash_start = 0x13000000; -unsigned long flash_size = 0x800000; unsigned long uImage_size = 0x10000d; int find_uImage_size(unsigned long start_offset) @@ -121,9 +118,8 @@ int find_uImage_size(unsigned long start_offset) return temp + 0x40; } -int __init init_amazon_mtd(void) +static int __init amazon_mtd_probe(struct platform_device *dev) { - int ret = 0; unsigned long uimage_size; struct mtd_info *mymtd = NULL; struct mtd_partition *parts = NULL; @@ -135,18 +131,19 @@ int __init init_amazon_mtd(void) amazon_map.copy_from = amazon_copy_from; amazon_map.copy_to = amazon_copy_to; - amazon_map.phys = flash_start; - amazon_map.virt = ioremap_nocache(flash_start, flash_size); + amazon_map.phys = dev->resource->start; + amazon_map.size = dev->resource->end - amazon_map.phys + 1; + amazon_map.virt = ioremap_nocache(amazon_map.phys, amazon_map.size); if (!amazon_map.virt) { - printk(KERN_WARNING "Failed to ioremap!\n"); + printk(KERN_WARNING "amazon_mtd: Failed to ioremap!\n"); return -EIO; } mymtd = (struct mtd_info *) do_map_probe("cfi_probe", &amazon_map); if (!mymtd) { iounmap(amazon_map.virt); - printk("probing failed\n"); + printk(KERN_WARNING "amazon_mtd: probing failed\n"); return -ENXIO; } @@ -173,18 +170,35 @@ int __init init_amazon_mtd(void) add_mtd_partitions(mymtd, parts, 3); printk(KERN_INFO "amazon_mtd: added %s flash with %dMB\n", - amazon_map.name, mymtd->size >> 20); + amazon_map.name, ((int)mymtd->size) >> 20); return 0; } -static void __exit cleanup_amazon_mtd(void) +static struct platform_driver amazon_mtd_driver = { + .probe = amazon_mtd_probe, + .driver = { + .name = "amazon_mtd", + .owner = THIS_MODULE, + }, +}; + +static int __init amazon_mtd_init(void) { - /* FIXME! */ + int ret = platform_driver_register(&amazon_mtd_driver); + if (ret) + printk(KERN_WARNING "amazon_mtd: error registering platfom driver!\n"); + return ret; } -module_init(init_amazon_mtd); -module_exit(cleanup_amazon_mtd); +static void __exit amazon_mtd_cleanup(void) +{ + platform_driver_unregister(&amazon_mtd_driver); +} + +module_init(amazon_mtd_init); +module_exit(amazon_mtd_cleanup); MODULE_LICENSE("GPL"); MODULE_AUTHOR("john crispin blogic@openwrt.org"); MODULE_DESCRIPTION("MTD map driver for AMAZON boards"); + diff --git a/target/linux/amazon/files/drivers/net/amazon_sw.c b/target/linux/amazon/files/drivers/net/amazon_sw.c index 14d3a8507..1101d840d 100644 --- a/target/linux/amazon/files/drivers/net/amazon_sw.c +++ b/target/linux/amazon/files/drivers/net/amazon_sw.c @@ -38,6 +38,7 @@ // copyright 2007 john crispin // copyright 2007 felix fietkau +// copyright 2009 hauke mehrtens // TODO @@ -85,6 +86,7 @@ #include #include #include +#include #include #include @@ -263,7 +265,7 @@ static int __init ethaddr_setup(char *line) if (line) line = (*ep) ? ep + 1 : ep; } - printk("mac address %2x-%2x-%2x-%2x-%2x-%2x \n", my_ethaddr[0], my_ethaddr[1], my_ethaddr[2], my_ethaddr[3], my_ethaddr[4], my_ethaddr[5]); + printk(KERN_INFO "amazon_mii0: mac address %2x-%2x-%2x-%2x-%2x-%2x \n", my_ethaddr[0], my_ethaddr[1], my_ethaddr[2], my_ethaddr[3], my_ethaddr[4], my_ethaddr[5]); return 0; } @@ -311,7 +313,7 @@ int switch_open(struct net_device *dev) #ifdef CONFIG_NET_HW_FLOWCONTROL if ((priv->fc_bit = netdev_register_fc(dev, amazon_xon)) == 0) { - printk("Hardware Flow Control register fails\n"); + printk(KERN_WARNING "amazon_mii0: Hardware Flow Control register fails\n"); } #endif @@ -660,18 +662,18 @@ int switch_hw_receive(struct net_device *dev, struct dma_device_info *dma_dev) len = dma_device_read(dma_dev, &buf, (void **) &skb); if (len >= 0x600) { - printk("packet too large %d\n", len); + printk(KERN_WARNING "amazon_mii0: packet too large %d\n", len); goto switch_hw_receive_err_exit; } /* remove CRC */ len -= 4; if (skb == NULL) { - printk("cannot restore pointer\n"); + printk(KERN_WARNING "amazon_mii0: cannot restore pointer\n"); goto switch_hw_receive_err_exit; } if (len > (skb->end - skb->tail)) { - printk("BUG, len:%d end:%p tail:%p\n", (len + 4), skb->end, skb->tail); + printk(KERN_WARNING "amazon_mii0: BUG, len:%d end:%p tail:%p\n", (len + 4), skb->end, skb->tail); goto switch_hw_receive_err_exit; } skb_put(skb, len); @@ -784,7 +786,7 @@ int switch_init(struct net_device *dev) int result; struct switch_priv *priv; ether_setup(dev); /* assign some of the fields */ - printk("%s up using ", dev->name); + printk(KERN_INFO "amazon_mii0: %s up using ", dev->name); dev->open = switch_open; dev->stop = switch_release; dev->hard_start_xmit = switch_tx; @@ -827,7 +829,7 @@ int switch_init(struct net_device *dev) return OK; } -int switch_init_module(void) +static int amazon_mii_probe(struct platform_device *dev) { int i = 0, result, device_present = 0; struct switch_priv *priv; @@ -839,7 +841,7 @@ int switch_init_module(void) priv = (struct switch_priv *) netdev_priv(switch_devs[i]); priv->num = i; if ((result = register_netdev(switch_devs[i]))) - printk("error %i registering device \"%s\"\n", result, switch_devs[i]->name); + printk(KERN_WARNING "amazon_mii0: error %i registering device \"%s\"\n", result, switch_devs[i]->name); else device_present++; } @@ -847,7 +849,7 @@ int switch_init_module(void) return device_present ? 0 : -ENODEV; } -void switch_cleanup(void) +static int amazon_mii_remove(struct platform_device *dev) { int i; struct switch_priv *priv; @@ -860,11 +862,35 @@ void switch_cleanup(void) kfree(netdev_priv(switch_devs[i])); unregister_netdev(switch_devs[i]); } - return; + return 0; } -module_init(switch_init_module); -module_exit(switch_cleanup); +static struct platform_driver amazon_mii_driver = { + .probe = amazon_mii_probe, + .remove = amazon_mii_remove, + .driver = { + .name = "amazon_mii0", + .owner = THIS_MODULE, + }, +}; + +static int __init amazon_mii_init(void) +{ + int ret = platform_driver_register(&amazon_mii_driver); + if (ret) + printk(KERN_WARNING "amazon_mii0: Error registering platfom driver!\n"); + return ret; +} + +static void __exit amazon_mii_cleanup(void) +{ + platform_driver_unregister(&amazon_mii_driver); +} + +module_init(amazon_mii_init); +module_exit(amazon_mii_cleanup); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Wu Qi Ming"); +MODULE_DESCRIPTION("ethernet driver for AMAZON boards"); + diff --git a/target/linux/amazon/files/drivers/serial/amazon_asc.c b/target/linux/amazon/files/drivers/serial/amazon_asc.c index 629754945..f7fa907b0 100644 --- a/target/linux/amazon/files/drivers/serial/amazon_asc.c +++ b/target/linux/amazon/files/drivers/serial/amazon_asc.c @@ -44,6 +44,7 @@ #include #include #include +#include #include #include @@ -670,7 +671,7 @@ static struct uart_driver amazonasc_reg = { .cons = &amazonasc_console, }; -static int __init amazonasc_init(void) +static int __init amazon_asc_probe(struct platform_device *dev) { unsigned char res; uart_register_driver(&amazonasc_reg); @@ -678,14 +679,38 @@ static int __init amazonasc_init(void) return res; } -static void __exit amazonasc_exit(void) +static int __exit amazon_asc_remove(struct platform_device *dev) { uart_unregister_driver(&amazonasc_reg); + return 0; } -module_init(amazonasc_init); -module_exit(amazonasc_exit); +static struct platform_driver amazon_asc_driver = { + .probe = amazon_asc_probe, + .remove = amazon_asc_remove, + .driver = { + .name = "amazon_asc", + .owner = THIS_MODULE, + }, +}; + +static int __init amazon_asc_init(void) +{ + int ret = platform_driver_register(&amazon_asc_driver); + if (ret) + printk(KERN_WARNING "amazon_asc: error registering platfom driver!\n"); + return ret; +} + +static void __exit amazon_asc_cleanup(void) +{ + platform_driver_unregister(&amazon_asc_driver); +} + +module_init(amazon_asc_init); +module_exit(amazon_asc_cleanup); MODULE_AUTHOR("Gary Jennejohn, Felix Fietkau, John Crispin"); MODULE_DESCRIPTION("MIPS AMAZONASC serial port driver"); MODULE_LICENSE("GPL"); + diff --git a/target/linux/amazon/files/include/asm-mips/amazon/amazon.h b/target/linux/amazon/files/include/asm-mips/amazon/amazon.h index 56e6943f6..1ec3c3b99 100644 --- a/target/linux/amazon/files/include/asm-mips/amazon/amazon.h +++ b/target/linux/amazon/files/include/asm-mips/amazon/amazon.h @@ -25,9 +25,14 @@ other party has been advised of the possibility of such damages. ******************************************************************************/ -#define amazon_readl(a) readl(((u32*)(a))) -#define amazon_writel(a,b) writel(a, ((u32*)(b))) -#define amazon_writel_masked(a,b,c) writel((readl(((u32*)(a))) & ~b) | (c & b), ((u32*)(a))) +#define amazon_readl(a) __raw_readl(((u32*)(a))) +#define amazon_writel(a,b) __raw_writel(a, ((u32*)(b))) +#define amazon_writel_masked(a,b,c) __raw_writel((__raw_readl(((u32*)(a))) & ~b) | (c & b), ((u32*)(a))) + +#define IOPORT_RESOURCE_START 0x10000000 +#define IOPORT_RESOURCE_END 0xffffffff +#define IOMEM_RESOURCE_START 0x10000000 +#define IOMEM_RESOURCE_END 0xffffffff /* check ADSL link status */ #define AMAZON_CHECK_LINK diff --git a/target/linux/amazon/files/include/asm-mips/mach-amazon/mangle-port.h b/target/linux/amazon/files/include/asm-mips/mach-amazon/mangle-port.h index 9aefebbe6..af8c3e939 100644 --- a/target/linux/amazon/files/include/asm-mips/mach-amazon/mangle-port.h +++ b/target/linux/amazon/files/include/asm-mips/mach-amazon/mangle-port.h @@ -5,8 +5,8 @@ * * Copyright (C) 2003, 2004 Ralf Baechle */ -#ifndef __ASM_MACH_GENERIC_MANGLE_PORT_H -#define __ASM_MACH_GENERIC_MANGLE_PORT_H +#ifndef __ASM_MACH_AMAZON_MANGLE_PORT_H +#define __ASM_MACH_AMAZON_MANGLE_PORT_H #define __swizzle_addr_b(port) (port) #define __swizzle_addr_w(port) ((port) ^ 2) @@ -27,26 +27,26 @@ */ #if defined(CONFIG_SWAP_IO_SPACE) -# define ioswabb(a,x) (x) -# define __mem_ioswabb(a,x) (x) -# define ioswabw(a,x) le16_to_cpu(x) -# define __mem_ioswabw(a,x) (x) -# define ioswabl(a,x) le32_to_cpu(x) -# define __mem_ioswabl(a,x) (x) -# define ioswabq(a,x) le64_to_cpu(x) -# define __mem_ioswabq(a,x) (x) +# define ioswabb(a, x) (x) +# define __mem_ioswabb(a, x) (x) +# define ioswabw(a, x) le16_to_cpu(x) +# define __mem_ioswabw(a, x) (x) +# define ioswabl(a, x) le32_to_cpu(x) +# define __mem_ioswabl(a, x) (x) +# define ioswabq(a, x) le64_to_cpu(x) +# define __mem_ioswabq(a, x) (x) #else -# define ioswabb(a,x) (x) -# define __mem_ioswabb(a,x) (x) -# define ioswabw(a,x) (x) -# define __mem_ioswabw(a,x) cpu_to_le16(x) -# define ioswabl(a,x) (x) -# define __mem_ioswabl(a,x) cpu_to_le32(x) -# define ioswabq(a,x) (x) -# define __mem_ioswabq(a,x) cpu_to_le32(x) +# define ioswabb(a, x) (x) +# define __mem_ioswabb(a, x) (x) +# define ioswabw(a, x) (x) +# define __mem_ioswabw(a, x) cpu_to_le16(x) +# define ioswabl(a, x) (x) +# define __mem_ioswabl(a, x) cpu_to_le32(x) +# define ioswabq(a, x) (x) +# define __mem_ioswabq(a, x) cpu_to_le32(x) #endif -#endif /* __ASM_MACH_GENERIC_MANGLE_PORT_H */ +#endif /* __ASM_MACH_AMAZON_MANGLE_PORT_H */ diff --git a/target/linux/amazon/patches-2.6.30/100-board.patch b/target/linux/amazon/patches-2.6.30/100-board.patch index df813e74d..66d5fd62d 100644 --- a/target/linux/amazon/patches-2.6.30/100-board.patch +++ b/target/linux/amazon/patches-2.6.30/100-board.patch @@ -1,6 +1,6 @@ --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig -@@ -60,6 +60,21 @@ config BCM47XX +@@ -60,6 +60,22 @@ config BCM47XX help Support for BCM47XX based boards @@ -18,11 +18,12 @@ + select SYS_SUPPORTS_32BIT_KERNEL + select SYS_HAS_EARLY_PRINTK + select HW_HAS_PCI ++ select SWAP_IO_SPACE + config MIPS_COBALT bool "Cobalt Server" select CEVT_R4K -@@ -633,6 +648,7 @@ config CAVIUM_OCTEON_REFERENCE_BOARD +@@ -633,6 +649,7 @@ config CAVIUM_OCTEON_REFERENCE_BOARD endchoice diff --git a/target/linux/amazon/patches-2.6.30/230-fix_pci.patch b/target/linux/amazon/patches-2.6.30/230-fix_pci.patch deleted file mode 100644 index 84d88dd92..000000000 --- a/target/linux/amazon/patches-2.6.30/230-fix_pci.patch +++ /dev/null @@ -1,20 +0,0 @@ ---- a/arch/mips/amazon/pci.c -+++ b/arch/mips/amazon/pci.c -@@ -182,7 +182,7 @@ static struct pci_controller amazon_pci_ - .io_resource = &pci_io_resource - }; - --int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin) -+int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) - { - switch (slot) { - case 13: -@@ -240,7 +240,7 @@ int pcibios_plat_dev_init(struct pci_dev - return 0; - } - --int amazon_pci_init(void) -+int __init amazon_pci_init(void) - { - u32 temp_buffer; - diff --git a/target/linux/ar7/Makefile b/target/linux/ar7/Makefile index 9704515a3..e553bb2ab 100644 --- a/target/linux/ar7/Makefile +++ b/target/linux/ar7/Makefile @@ -11,7 +11,7 @@ BOARD:=ar7 BOARDNAME:=TI AR7 FEATURES:=squashfs jffs2 atm -LINUX_VERSION:=2.6.30.9 +LINUX_VERSION:=2.6.30.10 include $(INCLUDE_DIR)/target.mk diff --git a/target/linux/ar7/files/arch/mips/ar7/gpio.c b/target/linux/ar7/files/arch/mips/ar7/gpio.c index 207d27093..56860f46d 100644 --- a/target/linux/ar7/files/arch/mips/ar7/gpio.c +++ b/target/linux/ar7/files/arch/mips/ar7/gpio.c @@ -21,11 +21,11 @@ #include -static const char *ar7_gpio_list[AR7_GPIO_MAX]; +static const char *ar7_gpio_list[TITAN_GPIO_MAX]; int gpio_request(unsigned gpio, const char *label) { - if (gpio >= AR7_GPIO_MAX) + if (gpio >= (ar7_is_titan() ? TITAN_GPIO_MAX : AR7_GPIO_MAX)) return -EINVAL; if (ar7_gpio_list[gpio]) diff --git a/target/linux/ar7/files/arch/mips/ar7/setup.c b/target/linux/ar7/files/arch/mips/ar7/setup.c index 58e152857..35b7b8d77 100644 --- a/target/linux/ar7/files/arch/mips/ar7/setup.c +++ b/target/linux/ar7/files/arch/mips/ar7/setup.c @@ -23,8 +23,10 @@ #include #include #include +#include #include +static int titan_variant; /*hold the results of the gpio_init_titan_variant() so that it is only called once*/ static void ar7_machine_restart(char *command); static void ar7_machine_halt(void); static void ar7_machine_power_off(void); @@ -59,6 +61,18 @@ const char *get_system_type(void) return "TI AR7 (TNETD7100)"; case AR7_CHIP_7200: return "TI AR7 (TNETD7200)"; + case AR7_CHIP_TITAN: + titan_variant = ar7_init_titan_variant(); + switch (titan_variant /*(gpio_get_value_titan(1) >> 12) & 0xf*/) { + case TITAN_CHIP_1050: + return "TI AR7 (TNETV1050)"; + case TITAN_CHIP_1055: + return "TI AR7 (TNETV1055)"; + case TITAN_CHIP_1056: + return "TI AR7 (TNETV1056)"; + case TITAN_CHIP_1060: + return "TI AR7 (TNETV1060)"; + } default: return "TI AR7 (Unknown)"; } diff --git a/target/linux/ar7/files/drivers/char/ar7_gpio.c b/target/linux/ar7/files/drivers/char/ar7_gpio.c index 16460cdd5..6b38bbd89 100644 --- a/target/linux/ar7/files/drivers/char/ar7_gpio.c +++ b/target/linux/ar7/files/drivers/char/ar7_gpio.c @@ -98,7 +98,7 @@ static int ar7_gpio_open(struct inode *inode, struct file *file) { int m = iminor(inode); - if (m >= AR7_GPIO_MAX) + if (m >= (ar7_is_titan() ? TITAN_GPIO_MAX : AR7_GPIO_MAX)) return -EINVAL; return nonseekable_open(inode, file); diff --git a/target/linux/ar7/files/include/asm-mips/ar7/ar7.h b/target/linux/ar7/files/include/asm-mips/ar7/ar7.h index d972e09ef..19b5289fd 100644 --- a/target/linux/ar7/files/include/asm-mips/ar7/ar7.h +++ b/target/linux/ar7/files/include/asm-mips/ar7/ar7.h @@ -44,6 +44,11 @@ #define UR8_REGS_WDT (AR7_REGS_BASE + 0x0b00) #define UR8_REGS_UART1 (AR7_REGS_BASE + 0x0f00) +#define TITAN_REGS_MAC0 (0x08640000) +#define TITAN_REGS_MAC1 (TITAN_REGS_MAC0 + 0x0800) +#define TITAN_REGS_VLYNQ0 (AR7_REGS_BASE + 0x1c00) +#define TITAN_REGS_VLYNQ1 (AR7_REGS_BASE + 0x1300) + #define AR7_RESET_PEREPHERIAL 0x0 #define AR7_RESET_SOFTWARE 0x4 #define AR7_RESET_STATUS 0x8 @@ -53,15 +58,30 @@ #define AR7_RESET_BIT_MDIO 22 #define AR7_RESET_BIT_EPHY 26 +#define TITAN_RESET_BIT_EPHY1 28 + /* GPIO control registers */ #define AR7_GPIO_INPUT 0x0 #define AR7_GPIO_OUTPUT 0x4 #define AR7_GPIO_DIR 0x8 #define AR7_GPIO_ENABLE 0xc +#define TITAN_GPIO_INPUT_0 0x0 +#define TITAN_GPIO_INPUT_1 0x4 +#define TITAN_GPIO_OUTPUT_0 0x8 +#define TITAN_GPIO_OUTPUT_1 0xc +#define TITAN_GPIO_DIR_0 0x10 +#define TITAN_GPIO_DIR_1 0x14 +#define TITAN_GPIO_ENBL_0 0x18 +#define TITAN_GPIO_ENBL_1 0x1c #define AR7_CHIP_7100 0x18 #define AR7_CHIP_7200 0x2b #define AR7_CHIP_7300 0x05 +#define AR7_CHIP_TITAN 0x07 +#define TITAN_CHIP_1050 0x0f +#define TITAN_CHIP_1055 0x0e +#define TITAN_CHIP_1056 0x0d +#define TITAN_CHIP_1060 0x07 /* Interrupts */ #define AR7_IRQ_UART0 15 @@ -86,14 +106,22 @@ struct plat_dsl_data { extern int ar7_cpu_clock, ar7_bus_clock, ar7_dsp_clock; +static inline int ar7_is_titan(void) +{ + return (readl((void *)KSEG1ADDR(AR7_REGS_GPIO + 0x24)) & 0xffff) == + AR7_CHIP_TITAN; +} + static inline u16 ar7_chip_id(void) { - return readl((void *)KSEG1ADDR(AR7_REGS_GPIO + 0x14)) & 0xffff; + return ar7_is_titan() ? AR7_CHIP_TITAN : (readl((void *) + KSEG1ADDR(AR7_REGS_GPIO + 0x14)) & 0xffff); } static inline u8 ar7_chip_rev(void) { - return (readl((void *)KSEG1ADDR(AR7_REGS_GPIO + 0x14)) >> 16) & 0xff; + return (readl((void *)KSEG1ADDR(AR7_REGS_GPIO + (ar7_is_titan() ? 0x24 : + 0x14))) >> 16) & 0xff; } static inline int ar7_cpu_freq(void) diff --git a/target/linux/ar7/files/include/asm-mips/ar7/gpio.h b/target/linux/ar7/files/include/asm-mips/ar7/gpio.h index 36cc68896..fde93bc7c 100644 --- a/target/linux/ar7/files/include/asm-mips/ar7/gpio.h +++ b/target/linux/ar7/files/include/asm-mips/ar7/gpio.h @@ -19,14 +19,18 @@ #ifndef __AR7_GPIO_H__ #define __AR7_GPIO_H__ #include +#ifndef __AR7_TITAN_H__ +#include +#endif #define AR7_GPIO_MAX 32 +#define TITAN_GPIO_MAX 51 extern int gpio_request(unsigned gpio, const char *label); extern void gpio_free(unsigned gpio); /* Common GPIO layer */ -static inline int gpio_get_value(unsigned gpio) +static inline int gpio_get_value_ar7(unsigned gpio) { void __iomem *gpio_in = (void __iomem *)KSEG1ADDR(AR7_REGS_GPIO + AR7_GPIO_INPUT); @@ -34,7 +38,23 @@ static inline int gpio_get_value(unsigned gpio) return readl(gpio_in) & (1 << gpio); } -static inline void gpio_set_value(unsigned gpio, int value) +static inline int gpio_get_value_titan(unsigned gpio) +{ + void __iomem *gpio_in0 = + (void __iomem *)KSEG1ADDR(AR7_REGS_GPIO + TITAN_GPIO_INPUT_0); + void __iomem *gpio_in1 = + (void __iomem *)KSEG1ADDR(AR7_REGS_GPIO + TITAN_GPIO_INPUT_1); + + return readl(gpio >> 5 ? gpio_in1 : gpio_in0) & (1 << (gpio & 0x1f)); +} + +static inline int gpio_get_value(unsigned gpio) +{ + return ar7_is_titan() ? gpio_get_value_titan(gpio) : + gpio_get_value_ar7(gpio); +} + +static inline void gpio_set_value_ar7(unsigned gpio, int value) { void __iomem *gpio_out = (void __iomem *)KSEG1ADDR(AR7_REGS_GPIO + AR7_GPIO_OUTPUT); @@ -46,7 +66,29 @@ static inline void gpio_set_value(unsigned gpio, int value) writel(tmp, gpio_out); } -static inline int gpio_direction_input(unsigned gpio) +static inline void gpio_set_value_titan(unsigned gpio, int value) +{ + void __iomem *gpio_out0 = + (void __iomem *)KSEG1ADDR(AR7_REGS_GPIO + TITAN_GPIO_OUTPUT_0); + void __iomem *gpio_out1 = + (void __iomem *)KSEG1ADDR(AR7_REGS_GPIO + TITAN_GPIO_OUTPUT_1); + unsigned tmp; + + tmp = readl(gpio >> 5 ? gpio_out1 : gpio_out0) & ~(1 << (gpio & 0x1f)); + if (value) + tmp |= 1 << (gpio & 0x1f); + writel(tmp, gpio >> 5 ? gpio_out1 : gpio_out0); +} + +static inline void gpio_set_value(unsigned gpio, int value) +{ + if (ar7_is_titan()) + gpio_set_value_titan(gpio, value); + else + gpio_set_value_ar7(gpio, value); +} + +static inline int gpio_direction_input_ar7(unsigned gpio) { void __iomem *gpio_dir = (void __iomem *)KSEG1ADDR(AR7_REGS_GPIO + AR7_GPIO_DIR); @@ -59,7 +101,29 @@ static inline int gpio_direction_input(unsigned gpio) return 0; } -static inline int gpio_direction_output(unsigned gpio, int value) +static inline int gpio_direction_input_titan(unsigned gpio) +{ + void __iomem *gpio_dir0 = + (void __iomem *)KSEG1ADDR(AR7_REGS_GPIO + TITAN_GPIO_DIR_0); + void __iomem *gpio_dir1 = + (void __iomem *)KSEG1ADDR(AR7_REGS_GPIO + TITAN_GPIO_DIR_1); + + if (gpio >= TITAN_GPIO_MAX) + return -EINVAL; + + writel(readl(gpio >> 5 ? gpio_dir1 : gpio_dir0) | (1 << (gpio & 0x1f)), + gpio >> 5 ? gpio_dir1 : gpio_dir0); + + return 0; +} + +static inline int gpio_direction_input(unsigned gpio) +{ + return ar7_is_titan() ? gpio_direction_input_titan(gpio) : + gpio_direction_input_ar7(gpio); +} + +static inline int gpio_direction_output_ar7(unsigned gpio, int value) { void __iomem *gpio_dir = (void __iomem *)KSEG1ADDR(AR7_REGS_GPIO + AR7_GPIO_DIR); @@ -73,6 +137,29 @@ static inline int gpio_direction_output(unsigned gpio, int value) return 0; } +static inline int gpio_direction_output_titan(unsigned gpio, int value) +{ + void __iomem *gpio_dir0 = + (void __iomem *)KSEG1ADDR(AR7_REGS_GPIO + TITAN_GPIO_DIR_0); + void __iomem *gpio_dir1 = + (void __iomem *)KSEG1ADDR(AR7_REGS_GPIO + TITAN_GPIO_DIR_1); + + if (gpio >= TITAN_GPIO_MAX) + return -EINVAL; + + gpio_set_value_titan(gpio, value); + writel(readl(gpio >> 5 ? gpio_dir1 : gpio_dir0) & ~(1 << + (gpio & 0x1f)), gpio >> 5 ? gpio_dir1 : gpio_dir0); + + return 0; +} + +static inline int gpio_direction_output(unsigned gpio, int value) +{ + return ar7_is_titan() ? gpio_direction_output_titan(gpio, value) : + gpio_direction_output_ar7(gpio, value); +} + static inline int gpio_to_irq(unsigned gpio) { return -EINVAL; @@ -84,7 +171,7 @@ static inline int irq_to_gpio(unsigned irq) } /* Board specific GPIO functions */ -static inline int ar7_gpio_enable(unsigned gpio) +static inline int ar7_gpio_enable_ar7(unsigned gpio) { void __iomem *gpio_en = (void __iomem *)KSEG1ADDR(AR7_REGS_GPIO + AR7_GPIO_ENABLE); @@ -94,7 +181,26 @@ static inline int ar7_gpio_enable(unsigned gpio) return 0; } -static inline int ar7_gpio_disable(unsigned gpio) +static inline int ar7_gpio_enable_titan(unsigned gpio) +{ + void __iomem *gpio_en0 = + (void __iomem *)KSEG1ADDR(AR7_REGS_GPIO + TITAN_GPIO_ENBL_0); + void __iomem *gpio_en1 = + (void __iomem *)KSEG1ADDR(AR7_REGS_GPIO + TITAN_GPIO_ENBL_1); + + writel(readl(gpio >> 5 ? gpio_en1 : gpio_en0) | (1 << (gpio & 0x1f)), + gpio >> 5 ? gpio_en1 : gpio_en0); + + return 0; +} + +static inline int ar7_gpio_enable(unsigned gpio) +{ + return ar7_is_titan() ? ar7_gpio_enable_titan(gpio) : + ar7_gpio_enable_ar7(gpio); +} + +static inline int ar7_gpio_disable_ar7(unsigned gpio) { void __iomem *gpio_en = (void __iomem *)KSEG1ADDR(AR7_REGS_GPIO + AR7_GPIO_ENABLE); @@ -104,6 +210,60 @@ static inline int ar7_gpio_disable(unsigned gpio) return 0; } +static inline int ar7_gpio_disable_titan(unsigned gpio) +{ + void __iomem *gpio_en0 = + (void __iomem *)KSEG1ADDR(AR7_REGS_GPIO + TITAN_GPIO_ENBL_0); + void __iomem *gpio_en1 = + (void __iomem *)KSEG1ADDR(AR7_REGS_GPIO + TITAN_GPIO_ENBL_1); + + writel(readl(gpio >> 5 ? gpio_en1 : gpio_en0) & ~(1 << (gpio & 0x1f)), + gpio >> 5 ? gpio_en1 : gpio_en0); + + return 0; +} + +static inline int ar7_gpio_disable(unsigned gpio) +{ + return ar7_is_titan() ? ar7_gpio_disable_titan(gpio) : + ar7_gpio_disable_ar7(gpio); +} + +static inline int ar7_init_titan_variant( void ) +{ + /*UINT32 new_val;*/ + unsigned new_val; + + /* set GPIO 44 - 47 as input */ + /*PAL_sysGpioCtrl(const int, GPIO_PIN, GPIO_INPUT_PIN); */ + /*define titan_gpio_ctrl in titan.h*/ + titan_gpio_ctrl(44, GPIO_PIN, GPIO_INPUT_PIN); + titan_gpio_ctrl(45, GPIO_PIN, GPIO_INPUT_PIN); + titan_gpio_ctrl(46, GPIO_PIN, GPIO_INPUT_PIN); + titan_gpio_ctrl(47, GPIO_PIN, GPIO_INPUT_PIN); + + /* read GPIO to get Titan variant type */ + /*fix this*/ + titan_sysGpioInValue( &new_val, 1 ); + + new_val >>= 12; + new_val &= 0x0f; + + switch ( new_val ) + { + case TITAN_CHIP_1050: + case TITAN_CHIP_1055: + case TITAN_CHIP_1056: + case TITAN_CHIP_1060: + return new_val; + + default: + break; + } + /* In case we get an invalid value, return the default Titan chip */ + return TITAN_CHIP_1050; +} + #include #endif diff --git a/target/linux/ar7/files/include/asm-mips/ar7/titan.h b/target/linux/ar7/files/include/asm-mips/ar7/titan.h new file mode 100644 index 000000000..0c2a51fde --- /dev/null +++ b/target/linux/ar7/files/include/asm-mips/ar7/titan.h @@ -0,0 +1,178 @@ +/* + * Copyright (C) 2008 Stanley Pinchak + * + * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +#ifndef __AR7_TITAN_H__ +#define __AR7_TITAN_H__ + +#ifndef __AR7_GPIO_H__ +#include +#endif + +typedef enum TITAN_GPIO_PIN_MODE_tag +{ + FUNCTIONAL_PIN = 0, + GPIO_PIN = 1 +} TITAN_GPIO_PIN_MODE_T; + +typedef enum TITAN_GPIO_PIN_DIRECTION_tag +{ + GPIO_OUTPUT_PIN = 0, + GPIO_INPUT_PIN = 1 +} TITAN_GPIO_PIN_DIRECTION_T; + +/********************************************************************** + * GPIO Control + **********************************************************************/ + +typedef struct +{ + int pinSelReg; + int shift; + int func; + +} GPIO_CFG; + +static GPIO_CFG gptable[]= { + /* PIN_SEL_REG, START_BIT, GPIO_CFG_MUX_VALUE */ + {4,24,1}, + {4,26,1}, + {4,28,1}, + {4,30,1}, + {5,6,1}, + {5,8,1}, + {5,10,1}, + {5,12,1}, + {7,14,3}, + {7,16,3}, + {7,18,3}, + {7,20,3}, + {7,22,3}, + {7,26,3}, + {7,28,3}, + {7,30,3}, + {8,0,3}, + {8,2,3}, + {8,4,3}, + {8,10,3}, + {8,14,3}, + {8,16,3}, + {8,18,3}, + {8,20,3}, + {9,8,3}, + {9,10,3}, + {9,12,3}, + {9,14,3}, + {9,18,3}, + {9,20,3}, + {9,24,3}, + {9,26,3}, + {9,28,3}, + {9,30,3}, + {10,0,3}, + {10,2,3}, + {10,8,3}, + {10,10,3}, + {10,12,3}, + {10,14,3}, + {13,12,3}, + {13,14,3}, + {13,16,3}, + {13,18,3}, + {13,24,3}, + {13,26,3}, + {13,28,3}, + {13,30,3}, + {14,2,3}, + {14,6,3}, + {14,8,3}, + {14,12,3} +}; + +typedef struct +{ + volatile unsigned int reg[21]; +} +PIN_SEL_REG_ARRAY_T; + +typedef struct +{ + unsigned int data_in [2]; + unsigned int data_out[2]; + unsigned int dir[2]; + unsigned int enable[2]; + +} TITAN_GPIO_CONTROL_T; + +#define AVALANCHE_PIN_SEL_BASE 0xA861160C /*replace with KSEG1ADDR()*/ + +static inline int titan_gpio_ctrl(unsigned int gpio_pin, TITAN_GPIO_PIN_MODE_T pin_mode, + TITAN_GPIO_PIN_DIRECTION_T pin_direction) +{ + int reg_index = 0; + int mux_status; + GPIO_CFG gpio_cfg; + volatile PIN_SEL_REG_ARRAY_T *pin_sel_array = (PIN_SEL_REG_ARRAY_T*) AVALANCHE_PIN_SEL_BASE; + volatile TITAN_GPIO_CONTROL_T *gpio_cntl = (TITAN_GPIO_CONTROL_T*) KSEG1ADDR(AR7_REGS_GPIO + TITAN_GPIO_INPUT_0); + + if (gpio_pin > 51 ) + return(-1); + + gpio_cfg = gptable[gpio_pin]; + mux_status = (pin_sel_array->reg[gpio_cfg.pinSelReg - 1] >> gpio_cfg.shift) & 0x3; + if(!((mux_status == 0 /* tri-stated */ ) || (mux_status == gpio_cfg.func /*GPIO functionality*/))) + { + return(-1); /* Pin have been configured for non GPIO funcs. */ + } + + /* Set the pin to be used as GPIO. */ + pin_sel_array->reg[gpio_cfg.pinSelReg - 1] |= ((gpio_cfg.func & 0x3) << gpio_cfg.shift); + + /* Check whether gpio refers to the first GPIO reg or second. */ + if(gpio_pin > 31) + { + reg_index = 1; + gpio_pin -= 32; + } + + if(pin_mode) + gpio_cntl->enable[reg_index] |= (1 << gpio_pin); /* Enable */ + else + gpio_cntl->enable[reg_index] &= ~(1 << gpio_pin); + + if(pin_direction) + gpio_cntl->dir[reg_index] |= (1 << gpio_pin); /* Input */ + else + gpio_cntl->dir[reg_index] &= ~(1 << gpio_pin); + + return(0); + +}/* end of function titan_gpio_ctrl */ + +static inline int titan_sysGpioInValue(unsigned int *in_val, unsigned int reg_index) +{ + volatile TITAN_GPIO_CONTROL_T *gpio_cntl = (TITAN_GPIO_CONTROL_T*) KSEG1ADDR(AR7_REGS_GPIO + TITAN_GPIO_INPUT_0); + + if(reg_index > 1) + return (-1); + + *in_val = gpio_cntl->data_in[reg_index]; + + return (0); +} + + +#endif diff --git a/target/linux/ar7/patches-2.6.30/930-titan-platform.patch b/target/linux/ar7/patches-2.6.30/930-titan-platform.patch new file mode 100644 index 000000000..80f7eb8ad --- /dev/null +++ b/target/linux/ar7/patches-2.6.30/930-titan-platform.patch @@ -0,0 +1,248 @@ +--- a/arch/mips/ar7/platform.c 2009-11-18 14:57:44.000000000 +0800 ++++ b/arch/mips/ar7/platform.c 2009-11-18 15:43:04.000000000 +0800 +@@ -128,6 +128,36 @@ + }, + }; + ++static struct resource cpmac_low_res_titan[] = { ++ { ++ .name = "regs", ++ .flags = IORESOURCE_MEM, ++ .start = TITAN_REGS_MAC0, ++ .end = TITAN_REGS_MAC0 + 0x7ff, ++ }, ++ { ++ .name = "irq", ++ .flags = IORESOURCE_IRQ, ++ .start = 27, ++ .end = 27, ++ }, ++}; ++ ++static struct resource cpmac_high_res_titan[] = { ++ { ++ .name = "regs", ++ .flags = IORESOURCE_MEM, ++ .start = TITAN_REGS_MAC1, ++ .end = TITAN_REGS_MAC1 + 0x7ff, ++ }, ++ { ++ .name = "irq", ++ .flags = IORESOURCE_IRQ, ++ .start = 41, ++ .end = 41, ++ }, ++}; ++ + static struct resource vlynq_low_res[] = { + { + .name = "regs", +@@ -182,6 +212,60 @@ + }, + }; + ++static struct resource vlynq_low_res_titan[] = { ++ { ++ .name = "regs", ++ .flags = IORESOURCE_MEM, ++ .start = TITAN_REGS_VLYNQ0, ++ .end = TITAN_REGS_VLYNQ0 + 0xff, ++ }, ++ { ++ .name = "irq", ++ .flags = IORESOURCE_IRQ, ++ .start = 33, ++ .end = 33, ++ }, ++ { ++ .name = "mem", ++ .flags = IORESOURCE_MEM, ++ .start = 0x0c000000, ++ .end = 0x0fffffff, ++ }, ++ { ++ .name = "devirq", ++ .flags = IORESOURCE_IRQ, ++ .start = 80, ++ .end = 111, ++ }, ++}; ++ ++static struct resource vlynq_high_res_titan[] = { ++ { ++ .name = "regs", ++ .flags = IORESOURCE_MEM, ++ .start = TITAN_REGS_VLYNQ1, ++ .end = TITAN_REGS_VLYNQ1 + 0xff, ++ }, ++ { ++ .name = "irq", ++ .flags = IORESOURCE_IRQ, ++ .start = 34, ++ .end = 34, ++ }, ++ { ++ .name = "mem", ++ .flags = IORESOURCE_MEM, ++ .start = 0x40000000, ++ .end = 0x43ffffff, ++ }, ++ { ++ .name = "devirq", ++ .flags = IORESOURCE_IRQ, ++ .start = 112, ++ .end = 143, ++ }, ++}; ++ + static struct resource usb_res[] = { + { + .name = "regs", +@@ -226,6 +310,18 @@ + .phy_mask = 0x7fffffff, + }; + ++static struct plat_cpmac_data cpmac_low_data_titan = { ++ .reset_bit = 17, ++ .power_bit = 20, ++ .phy_mask = 0x40000000, ++}; ++ ++static struct plat_cpmac_data cpmac_high_data_titan = { ++ .reset_bit = 21, ++ .power_bit = 22, ++ .phy_mask = 0x80000000, ++}; ++ + static struct plat_vlynq_data vlynq_low_data = { + .ops.on = vlynq_on, + .ops.off = vlynq_off, +@@ -240,6 +336,20 @@ + .gpio_bit = 19, + }; + ++static struct plat_vlynq_data vlynq_low_data_titan = { ++ .ops.on = vlynq_on, ++ .ops.off = vlynq_off, ++ .reset_bit = 15, ++ .gpio_bit = 14, ++}; ++ ++static struct plat_vlynq_data vlynq_high_data_titan = { ++ .ops.on = vlynq_on, ++ .ops.off = vlynq_off, ++ .reset_bit = 16, ++ .gpio_bit = 7, ++}; ++ + static struct platform_device physmap_flash = { + .id = 0, + .name = "physmap-flash", +@@ -273,6 +383,30 @@ + .num_resources = ARRAY_SIZE(cpmac_high_res), + }; + ++static struct platform_device cpmac_low_titan = { ++ .id = 0, ++ .name = "cpmac", ++ .dev = { ++ .dma_mask = &cpmac_dma_mask, ++ .coherent_dma_mask = DMA_32BIT_MASK, ++ .platform_data = &cpmac_low_data_titan, ++ }, ++ .resource = cpmac_low_res_titan, ++ .num_resources = ARRAY_SIZE(cpmac_low_res_titan), ++}; ++ ++static struct platform_device cpmac_high_titan = { ++ .id = 1, ++ .name = "cpmac", ++ .dev = { ++ .dma_mask = &cpmac_dma_mask, ++ .coherent_dma_mask = DMA_32BIT_MASK, ++ .platform_data = &cpmac_high_data_titan, ++ }, ++ .resource = cpmac_high_res_titan, ++ .num_resources = ARRAY_SIZE(cpmac_high_res_titan), ++}; ++ + static struct platform_device vlynq_low = { + .id = 0, + .name = "vlynq", +@@ -289,6 +423,22 @@ + .num_resources = ARRAY_SIZE(vlynq_high_res), + }; + ++static struct platform_device vlynq_low_titan = { ++ .id = 0, ++ .name = "vlynq", ++ .dev.platform_data = &vlynq_low_data_titan, ++ .resource = vlynq_low_res_titan, ++ .num_resources = ARRAY_SIZE(vlynq_low_res_titan), ++}; ++ ++static struct platform_device vlynq_high_titan = { ++ .id = 1, ++ .name = "vlynq", ++ .dev.platform_data = &vlynq_high_data_titan, ++ .resource = vlynq_high_res_titan, ++ .num_resources = ARRAY_SIZE(vlynq_high_res_titan), ++}; ++ + + /* This is proper way to define uart ports, but they are then detected + * as xscale and, obviously, don't work... +@@ -333,6 +483,11 @@ + { .name = "status", .gpio = 8, .active_low = 1, }, + }; + ++static struct gpio_led titan_leds[] = { ++ { .name = "status", .gpio = 8, .active_low = 1, }, ++ { .name = "wifi", .gpio = 13, .active_low = 1, }, ++}; ++ + static struct gpio_led dsl502t_leds[] = { + { .name = "status", .gpio = 9, .active_low = 1, }, + { .name = "ethernet", .gpio = 7, .active_low = 1, }, +@@ -425,7 +580,7 @@ + /* FIXME: the whole thing is unreliable */ + prId = prom_getenv("ProductID"); + usb_prod = prom_getenv("usb_prod"); +- ++ + /* If we can't get the product id from PROM, use the default LEDs */ + if (!prId) + return; +@@ -442,6 +597,9 @@ + } else if (strstr(prId, "DG834")) { + ar7_led_data.num_leds = ARRAY_SIZE(dg834g_leds); + ar7_led_data.leds = dg834g_leds; ++ } else if (strstr(prId, "CYWM")) { ++ ar7_led_data.num_leds = ARRAY_SIZE(titan_leds); ++ ar7_led_data.leds = titan_leds; + } + } + +@@ -502,14 +660,18 @@ + if (res) + return res; + +- ar7_device_disable(vlynq_low_data.reset_bit); +- res = platform_device_register(&vlynq_low); ++ ar7_device_disable(ar7_is_titan() ? vlynq_low_data_titan.reset_bit : ++ vlynq_low_data.reset_bit); ++ res = platform_device_register(ar7_is_titan() ? &vlynq_low_titan : ++ &vlynq_low); + if (res) + return res; + + if (ar7_has_high_vlynq()) { +- ar7_device_disable(vlynq_high_data.reset_bit); +- res = platform_device_register(&vlynq_high); ++ ar7_device_disable(ar7_is_titan() ? vlynq_high_data_titan.reset_bit : ++ vlynq_high_data.reset_bit); ++ res = platform_device_register(ar7_is_titan() ? &vlynq_high_titan : ++ &vlynq_high); + if (res) + return res; + } diff --git a/target/linux/ar7/patches-2.6.30/940-cpmac-titan.patch b/target/linux/ar7/patches-2.6.30/940-cpmac-titan.patch new file mode 100644 index 000000000..0e3a8b9ce --- /dev/null +++ b/target/linux/ar7/patches-2.6.30/940-cpmac-titan.patch @@ -0,0 +1,66 @@ +--- a/arch/mips/ar7/platform.c 2009-11-18 15:47:42.000000000 +0800 ++++ b/arch/mips/ar7/platform.c 2009-11-19 00:56:05.000000000 +0800 +@@ -677,24 +677,32 @@ + } + + if (ar7_has_high_cpmac()) { +- res = fixed_phy_add(PHY_POLL, cpmac_high.id, &fixed_phy_status); ++ res = fixed_phy_add(PHY_POLL, ar7_is_titan()?cpmac_high_titan.id: cpmac_high.id, &fixed_phy_status); + if (res && res != -ENODEV) + return res; + +- cpmac_get_mac(1, cpmac_high_data.dev_addr); +- res = platform_device_register(&cpmac_high); ++ cpmac_get_mac(1, ar7_is_titan() ? cpmac_high_data_titan.dev_addr: ++ cpmac_high_data.dev_addr); ++ res = platform_device_register(ar7_is_titan() ? &cpmac_high_titan : ++ &cpmac_high); + if (res) + return res; + } else { +- cpmac_low_data.phy_mask = 0xffffffff; +- } ++ if (ar7_is_titan()) ++ cpmac_low_data_titan.phy_mask = 0xffffffff; ++ else ++ cpmac_low_data.phy_mask = 0xffffffff; ++ } + +- res = fixed_phy_add(PHY_POLL, cpmac_low.id, &fixed_phy_status); ++ res = fixed_phy_add(PHY_POLL, ar7_is_titan()?cpmac_low_titan.id: ++ cpmac_low.id, &fixed_phy_status); + if (res && res != -ENODEV) + return res; + +- cpmac_get_mac(0, cpmac_low_data.dev_addr); +- res = platform_device_register(&cpmac_low); ++ cpmac_get_mac(0, ar7_is_titan() ? cpmac_low_data_titan.dev_addr : ++ cpmac_low_data.dev_addr); ++ res = platform_device_register(ar7_is_titan() ? &cpmac_low_titan : ++ &cpmac_low); + if (res) + return res; + +--- a/drivers/net/cpmac.c 2009-11-18 15:47:42.000000000 +0800 ++++ b/drivers/net/cpmac.c 2009-11-19 00:58:25.000000000 +0800 +@@ -1236,6 +1236,10 @@ + ar7_device_reset(AR7_RESET_BIT_CPMAC_HI); + ar7_device_reset(AR7_RESET_BIT_EPHY); + ++ if (ar7_is_titan()) { ++ ar7_device_reset(TITAN_RESET_BIT_EPHY1); ++ } ++ + cpmac_mii->reset(cpmac_mii); + + for (i = 0; i < 300; i++) +@@ -1250,7 +1254,8 @@ + mask = 0; + } + +- cpmac_mii->phy_mask = ~(mask | 0x80000000); ++ cpmac_mii->phy_mask = ar7_is_titan()? ~(mask | 0x80000000 | 0x40000000): ++ ~(mask | 0x80000000); + snprintf(cpmac_mii->id, MII_BUS_ID_SIZE, "1"); + + res = mdiobus_register(cpmac_mii); diff --git a/target/linux/ar71xx/Makefile b/target/linux/ar71xx/Makefile index c604acfab..b16b42863 100644 --- a/target/linux/ar71xx/Makefile +++ b/target/linux/ar71xx/Makefile @@ -12,7 +12,7 @@ BOARDNAME:=Atheros AR71xx/AR7240/AR913x FEATURES:=squashfs jffs2 tgz CFLAGS:=-Os -pipe -mips32r2 -mtune=mips32r2 -funit-at-a-time -LINUX_VERSION:=2.6.30.9 +LINUX_VERSION:=2.6.30.10 include $(INCLUDE_DIR)/target.mk diff --git a/target/linux/ar71xx/base-files/etc/defconfig/dir-825-b1/network b/target/linux/ar71xx/base-files/etc/defconfig/dir-825-b1/network new file mode 100644 index 000000000..2d4d8e012 --- /dev/null +++ b/target/linux/ar71xx/base-files/etc/defconfig/dir-825-b1/network @@ -0,0 +1,16 @@ +config interface loopback + option ifname lo + option proto static + option ipaddr 127.0.0.1 + option netmask 255.0.0.0 + +config interface lan + option ifname eth0 + option type bridge + option proto static + option ipaddr 192.168.1.1 + option netmask 255.255.255.0 + +config interface wan + option ifname eth1 + option proto dhcp diff --git a/target/linux/ar71xx/base-files/etc/defconfig/tl-wr841n-v1/network b/target/linux/ar71xx/base-files/etc/defconfig/tl-wr841n-v1/network new file mode 100644 index 000000000..80fea51d3 --- /dev/null +++ b/target/linux/ar71xx/base-files/etc/defconfig/tl-wr841n-v1/network @@ -0,0 +1,19 @@ +config interface loopback + option ifname lo + option proto static + option ipaddr 127.0.0.1 + option netmask 255.0.0.0 + +config interface mac0 + option ifname eth0 + +config interface lan + option ifname "lan1 lan2 lan3 lan4" + option type bridge + option proto static + option ipaddr 192.168.1.1 + option netmask 255.255.255.0 + +config interface wan + option ifname wan + option proto dhcp diff --git a/target/linux/ar71xx/base-files/etc/defconfig/wrt160nl/network b/target/linux/ar71xx/base-files/etc/defconfig/wrt160nl/network index 24fca7208..f670d149c 100644 --- a/target/linux/ar71xx/base-files/etc/defconfig/wrt160nl/network +++ b/target/linux/ar71xx/base-files/etc/defconfig/wrt160nl/network @@ -15,11 +15,11 @@ config interface wan option ifname eth1 option proto dhcp -config switch eth1 +config switch eth0 option reset 1 option enable_vlan 1 config switch_vlan - option device eth1 + option device eth0 option vlan 1 option ports "0 1 2 3 4 5" diff --git a/target/linux/ar71xx/base-files/etc/diag.sh b/target/linux/ar71xx/base-files/etc/diag.sh index 1d88f431f..1fc2c34fe 100755 --- a/target/linux/ar71xx/base-files/etc/diag.sh +++ b/target/linux/ar71xx/base-files/etc/diag.sh @@ -42,6 +42,15 @@ get_status_led() { bullet-m | rocket-m | nano-m) status_led="ubnt:green:link4" ;; + dir-600-a1) + status_led="dir-600-a1:green:power" + ;; + dir-615-c1) + status_led="dir-615c1:green:status" + ;; + dir-825-b1) + status_led="dir825b1:orange:power" + ;; ls-sr71) status_led="ubnt:green:d22" ;; @@ -54,15 +63,21 @@ get_status_led() { pb44) status_led="pb44:amber:jump1" ;; - routerstation) + routerstation | routerstation-pro) status_led="ubnt:green:rf" ;; tew-632brp) status_led="tew-632brp:green:status" ;; + tl-wr1043nd) + status_led="tl-wr1043nd:green:system" + ;; tl-wr741nd) status_led="tl-wr741nd:green:system" ;; + tl-wr841n-v1) + status_led="tl-wr841n:green:system" + ;; tl-wr941nd) status_led="tl-wr941nd:green:system" ;; diff --git a/target/linux/ar71xx/base-files/etc/preinit.arch b/target/linux/ar71xx/base-files/etc/preinit.arch index a6af7e117..637aa5fc5 100644 --- a/target/linux/ar71xx/base-files/etc/preinit.arch +++ b/target/linux/ar71xx/base-files/etc/preinit.arch @@ -32,6 +32,10 @@ preinit_set_mac_address() { tew-632brp) fetch_mac_from_mtd config lan_mac wan_mac ;; + dir-615-c1) + fetch_mac_from_mtd config lan_mac wan_mac + echo 1 > /sys/class/leds/dir-615-c1:green:wancpu/brightness + ;; wrt160nl) fetch_mac_from_mtd nvram lan_hwaddr wan_hwaddr ;; diff --git a/target/linux/ar71xx/base-files/lib/ar71xx.sh b/target/linux/ar71xx/base-files/lib/ar71xx.sh index c24a8b3e8..327107b0d 100755 --- a/target/linux/ar71xx/base-files/lib/ar71xx.sh +++ b/target/linux/ar71xx/base-files/lib/ar71xx.sh @@ -19,6 +19,12 @@ ar71xx_board_name() { *AW-NR580) name="aw-nr580" ;; + *"DIR-600 rev. A1") + name="dir-600-a1" + ;; + *"DIR-825 rev. B1") + name="dir-825-b1" + ;; *"Bullet M") name="bullet-m" ;; @@ -64,9 +70,18 @@ ar71xx_board_name() { *TEW-632BRP) name="tew-632brp" ;; + *TL-WR1043ND) + name="tl-wr1043nd" + ;; + *"DIR-615 rev. C1") + name="dir-615-c1" + ;; *TL-WR741ND) name="tl-wr741nd" ;; + *"TL-WR841N v1") + name="tl-wr841n-v1" + ;; *TL-WR941ND) name="tl-wr941nd" ;; diff --git a/target/linux/ar71xx/base-files/lib/upgrade/platform.sh b/target/linux/ar71xx/base-files/lib/upgrade/platform.sh index 97c3a41da..13a154441 100755 --- a/target/linux/ar71xx/base-files/lib/upgrade/platform.sh +++ b/target/linux/ar71xx/base-files/lib/upgrade/platform.sh @@ -68,14 +68,14 @@ platform_check_image() { [ "$ARGC" -gt 1 ] && return 1 case "$board" in - ap83 | mzk-w04nu | mzk-w300nh | tew-632brp | wrt-400n | bullet-m | nano-m | rocket-m) + ap81 | ap83 | dir-600-a1 | dir-615-c1 | dir-825-b1 | mzk-w04nu | mzk-w300nh | tew-632brp | wrt-400n | bullet-m | nano-m | rocket-m) [ "$magic" != "2705" ] && { echo "Invalid image type." return 1 } return 0 ;; - tl-wr741nd | tl-wr941nd) + tl-wr741nd | tl-wr841n-v1 | tl-wr941nd | tl-wr1043nd) [ "$magic" != "0100" ] && { echo "Invalid image type." return 1 @@ -96,7 +96,7 @@ platform_check_image() { } return 0 ;; - routerstation | routerstation-pro | ls-sr71) + routerstation | routerstation-pro | ls-sr71 | pb42 | pb44) [ "$magic" != "4349" ] && { echo "Invalid image. Use *-sysupgrade.bin files on this board" return 1 diff --git a/target/linux/ar71xx/config-2.6.30 b/target/linux/ar71xx/config-2.6.30 index 4a2f129f1..357913468 100644 --- a/target/linux/ar71xx/config-2.6.30 +++ b/target/linux/ar71xx/config-2.6.30 @@ -1,11 +1,24 @@ CONFIG_32BIT=y # CONFIG_64BIT is not set +CONFIG_AG71XX=y CONFIG_AG71XX_AR8216_SUPPORT=y # CONFIG_AG71XX_DEBUG is not set -CONFIG_AG71XX=y +# CONFIG_AG71XX_DEBUG_FS is not set +CONFIG_AR71XX_DEV_AP91_PCI=y +CONFIG_AR71XX_DEV_AP94_PCI=y +CONFIG_AR71XX_DEV_AR913X_WMAC=y +CONFIG_AR71XX_DEV_DSA=y +CONFIG_AR71XX_DEV_GPIO_BUTTONS=y +CONFIG_AR71XX_DEV_LEDS_GPIO=y +CONFIG_AR71XX_DEV_M25P80=y +CONFIG_AR71XX_DEV_PB42_PCI=y +CONFIG_AR71XX_DEV_USB=y CONFIG_AR71XX_MACH_AP81=y CONFIG_AR71XX_MACH_AP83=y CONFIG_AR71XX_MACH_AW_NR580=y +CONFIG_AR71XX_MACH_DIR_600_A1=y +CONFIG_AR71XX_MACH_DIR_615_C1=y +CONFIG_AR71XX_MACH_DIR_825_B1=y CONFIG_AR71XX_MACH_GENERIC=y CONFIG_AR71XX_MACH_MZK_W04NU=y CONFIG_AR71XX_MACH_MZK_W300NH=y @@ -13,7 +26,9 @@ 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_WR1043ND=y CONFIG_AR71XX_MACH_TL_WR741ND=y +CONFIG_AR71XX_MACH_TL_WR841N_V1=y CONFIG_AR71XX_MACH_TL_WR941ND=y CONFIG_AR71XX_MACH_UBNT=y CONFIG_AR71XX_MACH_WNDR3700=y @@ -21,6 +36,7 @@ CONFIG_AR71XX_MACH_WNR2000=y CONFIG_AR71XX_MACH_WP543=y CONFIG_AR71XX_MACH_WRT160NL=y CONFIG_AR71XX_MACH_WRT400N=y +CONFIG_AR71XX_NVRAM=y CONFIG_AR71XX_WDT=y # CONFIG_ARCH_HAS_ILOG2_U32 is not set # CONFIG_ARCH_HAS_ILOG2_U64 is not set @@ -36,8 +52,8 @@ CONFIG_BITREVERSE=y # CONFIG_CAVIUM_OCTEON_REFERENCE_BOARD is not set # CONFIG_CAVIUM_OCTEON_SIMULATOR is not set CONFIG_CC_OPTIMIZE_FOR_SIZE=y -CONFIG_CEVT_R4K_LIB=y 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 @@ -46,9 +62,9 @@ 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_MIPS32=y # CONFIG_CPU_MIPS64_R1 is not set # CONFIG_CPU_MIPS64_R2 is not set CONFIG_CPU_MIPSR2=y @@ -70,16 +86,16 @@ 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_LIB=y CONFIG_CSRC_R4K=y +CONFIG_CSRC_R4K_LIB=y CONFIG_DECOMPRESS_LZMA=y CONFIG_DEVPORT=y # CONFIG_DM9000 is not set CONFIG_DMA_NEED_PCI_MAP_STATE=y CONFIG_DMA_NONCOHERENT=y CONFIG_EARLY_PRINTK=y -CONFIG_GENERIC_CLOCKEVENTS_BUILD=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 @@ -99,10 +115,10 @@ CONFIG_HAVE_MLOCK=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_I2C=y CONFIG_ICPLUS_PHY=y CONFIG_IMAGE_CMDLINE_HACK=y CONFIG_INITRAMFS_ROOT_GID=0 @@ -111,6 +127,7 @@ CONFIG_INITRAMFS_SOURCE="../../root" CONFIG_IRQ_CPU=y # CONFIG_ISDN is not set # CONFIG_LEDS_GPIO is not set +# CONFIG_LEDS_WNDR3700_USB is not set # CONFIG_LEMOTE_FULONG is not set # CONFIG_M25PXX_USE_FAST_READ is not set # CONFIG_MACH_ALCHEMY is not set @@ -121,6 +138,7 @@ CONFIG_IRQ_CPU=y # 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_L1_CACHE_SHIFT=5 CONFIG_MIPS_MACHINE=y @@ -129,21 +147,22 @@ 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_MIPS=y CONFIG_MTD_AR91XX_FLASH=y -# CONFIG_MTD_CFI_INTELEXT is not set # CONFIG_MTD_CFI is not set +# CONFIG_MTD_CFI_INTELEXT is not set CONFIG_MTD_CMDLINE_PARTS=y CONFIG_MTD_JEDECPROBE=y CONFIG_MTD_M25P80=y CONFIG_MTD_MYLOADER_PARTS=y -CONFIG_MTD_NAND_RB4XX=y CONFIG_MTD_NAND=y +CONFIG_MTD_NAND_RB4XX=y CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-2 CONFIG_MTD_REDBOOT_PARTS=y CONFIG_MTD_WRT160NL_PARTS=y CONFIG_MYLOADER=y +CONFIG_NET_DSA=y CONFIG_NET_DSA_MV88E6060=y +CONFIG_NET_DSA_MV88E6063=y # CONFIG_NET_DSA_MV88E6123_61_65 is not set # CONFIG_NET_DSA_MV88E6131 is not set # CONFIG_NET_DSA_MV88E6XXX is not set @@ -151,7 +170,6 @@ CONFIG_NET_DSA_MV88E6060=y # CONFIG_NET_DSA_TAG_DSA is not set # CONFIG_NET_DSA_TAG_EDSA is not set CONFIG_NET_DSA_TAG_TRAILER=y -CONFIG_NET_DSA=y # CONFIG_NO_IOPORT is not set # CONFIG_NXP_STB220 is not set # CONFIG_NXP_STB225 is not set @@ -165,6 +183,7 @@ CONFIG_PHYLIB=y # CONFIG_PNX8550_STB810 is not set # CONFIG_PROBE_INITRD_HEADER is not set CONFIG_RTL8306_PHY=y +CONFIG_RTL8366_SMI=y CONFIG_SCHED_OMIT_FRAME_POINTER=y # CONFIG_SCSI_DMA is not set # CONFIG_SERIAL_8250_EXTENDED is not set @@ -185,6 +204,7 @@ CONFIG_SERIAL_8250_RUNTIME_UARTS=1 # CONFIG_SLAB is not set # CONFIG_SLOW_WORK is not set CONFIG_SLUB=y +CONFIG_SPI=y CONFIG_SPI_AP83=y CONFIG_SPI_AR71XX=y CONFIG_SPI_BITBANG=y @@ -193,7 +213,6 @@ CONFIG_SPI_MASTER=y CONFIG_SPI_PB44=y # CONFIG_SPI_SPIDEV is not set # CONFIG_SPI_VSC7385 is not set -CONFIG_SPI=y CONFIG_SWCONFIG=y CONFIG_SYS_HAS_CPU_MIPS32_R1=y CONFIG_SYS_HAS_CPU_MIPS32_R2=y diff --git a/target/linux/ar71xx/config-2.6.31 b/target/linux/ar71xx/config-2.6.31 index b92b0f639..5c9affa74 100644 --- a/target/linux/ar71xx/config-2.6.31 +++ b/target/linux/ar71xx/config-2.6.31 @@ -1,12 +1,26 @@ CONFIG_32BIT=y # CONFIG_64BIT is not set +CONFIG_AG71XX=y CONFIG_AG71XX_AR8216_SUPPORT=y # CONFIG_AG71XX_DEBUG is not set -CONFIG_AG71XX=y +# CONFIG_AG71XX_DEBUG_FS is not set # CONFIG_ALCHEMY_GPIO_INDIRECT is not set +# CONFIG_AR7 is not set +CONFIG_AR71XX_DEV_AP91_PCI=y +CONFIG_AR71XX_DEV_AP94_PCI=y +CONFIG_AR71XX_DEV_AR913X_WMAC=y +CONFIG_AR71XX_DEV_DSA=y +CONFIG_AR71XX_DEV_GPIO_BUTTONS=y +CONFIG_AR71XX_DEV_LEDS_GPIO=y +CONFIG_AR71XX_DEV_M25P80=y +CONFIG_AR71XX_DEV_PB42_PCI=y +CONFIG_AR71XX_DEV_USB=y CONFIG_AR71XX_MACH_AP81=y CONFIG_AR71XX_MACH_AP83=y CONFIG_AR71XX_MACH_AW_NR580=y +CONFIG_AR71XX_MACH_DIR_600_A1=y +CONFIG_AR71XX_MACH_DIR_615_C1=y +CONFIG_AR71XX_MACH_DIR_825_B1=y CONFIG_AR71XX_MACH_GENERIC=y CONFIG_AR71XX_MACH_MZK_W04NU=y CONFIG_AR71XX_MACH_MZK_W300NH=y @@ -14,7 +28,9 @@ 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_WR1043ND=y CONFIG_AR71XX_MACH_TL_WR741ND=y +CONFIG_AR71XX_MACH_TL_WR841N_V1=y CONFIG_AR71XX_MACH_TL_WR941ND=y CONFIG_AR71XX_MACH_UBNT=y CONFIG_AR71XX_MACH_WNDR3700=y @@ -22,8 +38,8 @@ CONFIG_AR71XX_MACH_WNR2000=y CONFIG_AR71XX_MACH_WP543=y CONFIG_AR71XX_MACH_WRT160NL=y CONFIG_AR71XX_MACH_WRT400N=y +CONFIG_AR71XX_NVRAM=y CONFIG_AR71XX_WDT=y -# CONFIG_AR7 is not set # CONFIG_ARCH_HAS_ILOG2_U32 is not set # CONFIG_ARCH_HAS_ILOG2_U64 is not set CONFIG_ARCH_HIBERNATION_POSSIBLE=y @@ -38,8 +54,8 @@ CONFIG_BITREVERSE=y # CONFIG_CAVIUM_OCTEON_REFERENCE_BOARD is not set # CONFIG_CAVIUM_OCTEON_SIMULATOR is not set CONFIG_CC_OPTIMIZE_FOR_SIZE=y -CONFIG_CEVT_R4K_LIB=y 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 @@ -48,9 +64,9 @@ 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_MIPS32=y # CONFIG_CPU_MIPS64_R1 is not set # CONFIG_CPU_MIPS64_R2 is not set CONFIG_CPU_MIPSR2=y @@ -72,8 +88,8 @@ 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_LIB=y CONFIG_CSRC_R4K=y +CONFIG_CSRC_R4K_LIB=y CONFIG_DECOMPRESS_LZMA=y CONFIG_DEVPORT=y # CONFIG_DM9000 is not set @@ -81,8 +97,8 @@ CONFIG_DMA_NEED_PCI_MAP_STATE=y CONFIG_DMA_NONCOHERENT=y CONFIG_EARLY_PRINTK=y # CONFIG_FSNOTIFY is not set -CONFIG_GENERIC_CLOCKEVENTS_BUILD=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 @@ -101,18 +117,20 @@ 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_I2C=y CONFIG_ICPLUS_PHY=y CONFIG_IMAGE_CMDLINE_HACK=y +# CONFIG_INITRAMFS_COMPRESSION_LZO is not set 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_LEDS_WNDR3700_USB is not set # CONFIG_LEMOTE_FULONG is not set # CONFIG_M25PXX_USE_FAST_READ is not set CONFIG_MAC80211_DEFAULT_PS_VALUE=0 @@ -124,6 +142,7 @@ CONFIG_MAC80211_DEFAULT_PS_VALUE=0 # 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_L1_CACHE_SHIFT=5 CONFIG_MIPS_MACHINE=y @@ -132,21 +151,22 @@ 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_MIPS=y CONFIG_MTD_AR91XX_FLASH=y -# CONFIG_MTD_CFI_INTELEXT is not set # CONFIG_MTD_CFI is not set +# CONFIG_MTD_CFI_INTELEXT is not set CONFIG_MTD_CMDLINE_PARTS=y CONFIG_MTD_JEDECPROBE=y CONFIG_MTD_M25P80=y CONFIG_MTD_MYLOADER_PARTS=y -CONFIG_MTD_NAND_RB4XX=y CONFIG_MTD_NAND=y +CONFIG_MTD_NAND_RB4XX=y CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-2 CONFIG_MTD_REDBOOT_PARTS=y CONFIG_MTD_WRT160NL_PARTS=y CONFIG_MYLOADER=y +CONFIG_NET_DSA=y CONFIG_NET_DSA_MV88E6060=y +CONFIG_NET_DSA_MV88E6063=y # CONFIG_NET_DSA_MV88E6123_61_65 is not set # CONFIG_NET_DSA_MV88E6131 is not set # CONFIG_NET_DSA_MV88E6XXX is not set @@ -154,7 +174,6 @@ CONFIG_NET_DSA_MV88E6060=y # CONFIG_NET_DSA_TAG_DSA is not set # CONFIG_NET_DSA_TAG_EDSA is not set CONFIG_NET_DSA_TAG_TRAILER=y -CONFIG_NET_DSA=y # CONFIG_NO_IOPORT is not set # CONFIG_NXP_STB220 is not set # CONFIG_NXP_STB225 is not set @@ -168,6 +187,7 @@ CONFIG_PHYLIB=y # CONFIG_PNX8550_STB810 is not set # CONFIG_PROBE_INITRD_HEADER is not set CONFIG_RTL8306_PHY=y +CONFIG_RTL8366_SMI=y CONFIG_SCHED_OMIT_FRAME_POINTER=y # CONFIG_SCSI_DMA is not set # CONFIG_SERIAL_8250_EXTENDED is not set @@ -187,6 +207,7 @@ CONFIG_SERIAL_8250_RUNTIME_UARTS=1 # 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 @@ -195,7 +216,6 @@ CONFIG_SPI_MASTER=y CONFIG_SPI_PB44=y # CONFIG_SPI_SPIDEV is not set # CONFIG_SPI_VSC7385 is not set -CONFIG_SPI=y CONFIG_SWCONFIG=y CONFIG_SYS_HAS_CPU_MIPS32_R1=y CONFIG_SYS_HAS_CPU_MIPS32_R2=y diff --git a/target/linux/ar71xx/config-2.6.28 b/target/linux/ar71xx/config-2.6.32 similarity index 80% rename from target/linux/ar71xx/config-2.6.28 rename to target/linux/ar71xx/config-2.6.32 index 340379068..a4ac682ef 100644 --- a/target/linux/ar71xx/config-2.6.28 +++ b/target/linux/ar71xx/config-2.6.32 @@ -1,12 +1,26 @@ CONFIG_32BIT=y # CONFIG_64BIT is not set -# CONFIG_8139TOO is not set +CONFIG_AG71XX=y CONFIG_AG71XX_AR8216_SUPPORT=y # CONFIG_AG71XX_DEBUG is not set -CONFIG_AG71XX=y +# CONFIG_AG71XX_DEBUG_FS is not set +# CONFIG_ALCHEMY_GPIO_INDIRECT is not set +# CONFIG_AR7 is not set +CONFIG_AR71XX_DEV_AP91_PCI=y +CONFIG_AR71XX_DEV_AP94_PCI=y +CONFIG_AR71XX_DEV_AR913X_WMAC=y +CONFIG_AR71XX_DEV_DSA=y +CONFIG_AR71XX_DEV_GPIO_BUTTONS=y +CONFIG_AR71XX_DEV_LEDS_GPIO=y +CONFIG_AR71XX_DEV_M25P80=y +CONFIG_AR71XX_DEV_PB42_PCI=y +CONFIG_AR71XX_DEV_USB=y CONFIG_AR71XX_MACH_AP81=y CONFIG_AR71XX_MACH_AP83=y CONFIG_AR71XX_MACH_AW_NR580=y +CONFIG_AR71XX_MACH_DIR_600_A1=y +CONFIG_AR71XX_MACH_DIR_615_C1=y +CONFIG_AR71XX_MACH_DIR_825_B1=y CONFIG_AR71XX_MACH_GENERIC=y CONFIG_AR71XX_MACH_MZK_W04NU=y CONFIG_AR71XX_MACH_MZK_W300NH=y @@ -14,7 +28,9 @@ 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_WR1043ND=y CONFIG_AR71XX_MACH_TL_WR741ND=y +CONFIG_AR71XX_MACH_TL_WR841N_V1=y CONFIG_AR71XX_MACH_TL_WR941ND=y CONFIG_AR71XX_MACH_UBNT=y CONFIG_AR71XX_MACH_WNDR3700=y @@ -22,9 +38,11 @@ CONFIG_AR71XX_MACH_WNR2000=y CONFIG_AR71XX_MACH_WP543=y CONFIG_AR71XX_MACH_WRT160NL=y CONFIG_AR71XX_MACH_WRT400N=y +CONFIG_AR71XX_NVRAM=y CONFIG_AR71XX_WDT=y # CONFIG_ARCH_HAS_ILOG2_U32 is not set # CONFIG_ARCH_HAS_ILOG2_U64 is not set +CONFIG_ARCH_HIBERNATION_POSSIBLE=y CONFIG_ARCH_POPULATES_NODE_MAP=y CONFIG_ARCH_REQUIRE_GPIOLIB=y # CONFIG_ARCH_SUPPORTS_MSI is not set @@ -32,20 +50,24 @@ CONFIG_ARCH_SUPPORTS_OPROFILE=y CONFIG_ARCH_SUSPEND_POSSIBLE=y CONFIG_ATHEROS_AR71XX=y # CONFIG_BCM47XX is not set +# CONFIG_BCM63XX is not set CONFIG_BITREVERSE=y +# CONFIG_CAVIUM_OCTEON_REFERENCE_BOARD is not set +# CONFIG_CAVIUM_OCTEON_SIMULATOR is not set CONFIG_CC_OPTIMIZE_FOR_SIZE=y CONFIG_CEVT_R4K=y -CONFIG_CLASSIC_RCU=y +CONFIG_CEVT_R4K_LIB=y +CONFIG_CFG80211_DEFAULT_PS_VALUE=0 CONFIG_CMDLINE="rootfstype=squashfs,yaffs,jffs2 noinitrd console=ttyS0,115200" CONFIG_CPU_BIG_ENDIAN=y -CONFIG_CPU_HAS_LLSC=y +# CONFIG_CPU_CAVIUM_OCTEON is not set 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_LOONGSON2E is not set +CONFIG_CPU_MIPS32=y # CONFIG_CPU_MIPS32_R1 is not set CONFIG_CPU_MIPS32_R2=y -CONFIG_CPU_MIPS32=y # CONFIG_CPU_MIPS64_R1 is not set # CONFIG_CPU_MIPS64_R2 is not set CONFIG_CPU_MIPSR2=y @@ -68,18 +90,23 @@ CONFIG_CPU_SUPPORTS_HIGHMEM=y # CONFIG_CPU_TX49XX is not set # CONFIG_CPU_VR41XX is not set CONFIG_CSRC_R4K=y +CONFIG_CSRC_R4K_LIB=y +CONFIG_DECOMPRESS_LZMA=y CONFIG_DEVPORT=y # CONFIG_DM9000 is not set CONFIG_DMA_NEED_PCI_MAP_STATE=y CONFIG_DMA_NONCOHERENT=y CONFIG_EARLY_PRINTK=y -CONFIG_GENERIC_CLOCKEVENTS_BUILD=y +# CONFIG_FSNOTIFY is not set 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_GENERIC_HARDIRQS_NO__DO_IRQ=y CONFIG_GPIOLIB=y +# CONFIG_GPIO_MC33880 is not set CONFIG_GPIO_PCF857X=y CONFIG_GPIO_SYSFS=y CONFIG_HARDWARE_WATCHPOINTS=y @@ -87,35 +114,37 @@ 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_GENERIC_DMA_COHERENT=y 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_I2C=y CONFIG_ICPLUS_PHY=y -# CONFIG_IDE is not set CONFIG_IMAGE_CMDLINE_HACK=y +# CONFIG_INITRAMFS_COMPRESSION_LZO is not set 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_LEDS_WNDR3700_USB 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_EMMA is not set # CONFIG_MACH_JAZZ is not set +# CONFIG_MACH_LOONGSON is not set # CONFIG_MACH_TX39XX is not set # CONFIG_MACH_TX49XX is not set # CONFIG_MACH_VR41XX is not set +# CONFIG_MFD_MC13783 is not set CONFIG_MICREL_PHY=y # CONFIG_MIKROTIK_RB532 is not set +CONFIG_MIPS=y # CONFIG_MIPS_COBALT is not set CONFIG_MIPS_L1_CACHE_SHIFT=5 CONFIG_MIPS_MACHINE=y @@ -124,21 +153,23 @@ 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_MIPS=y CONFIG_MTD_AR91XX_FLASH=y -# CONFIG_MTD_CFI_INTELEXT is not set # CONFIG_MTD_CFI is not set +# CONFIG_MTD_CFI_INTELEXT is not set CONFIG_MTD_CMDLINE_PARTS=y CONFIG_MTD_JEDECPROBE=y CONFIG_MTD_M25P80=y CONFIG_MTD_MYLOADER_PARTS=y -CONFIG_MTD_NAND_RB4XX=y CONFIG_MTD_NAND=y +CONFIG_MTD_NAND_RB4XX=y CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-2 CONFIG_MTD_REDBOOT_PARTS=y +# CONFIG_MTD_SST25L is not set CONFIG_MTD_WRT160NL_PARTS=y CONFIG_MYLOADER=y +CONFIG_NET_DSA=y CONFIG_NET_DSA_MV88E6060=y +CONFIG_NET_DSA_MV88E6063=y # CONFIG_NET_DSA_MV88E6123_61_65 is not set # CONFIG_NET_DSA_MV88E6131 is not set # CONFIG_NET_DSA_MV88E6XXX is not set @@ -146,7 +177,6 @@ CONFIG_NET_DSA_MV88E6060=y # CONFIG_NET_DSA_TAG_DSA is not set # CONFIG_NET_DSA_TAG_EDSA is not set CONFIG_NET_DSA_TAG_TRAILER=y -CONFIG_NET_DSA=y # CONFIG_NO_IOPORT is not set # CONFIG_NXP_STB220 is not set # CONFIG_NXP_STB225 is not set @@ -159,9 +189,9 @@ CONFIG_PHYLIB=y # CONFIG_PNX8550_JBS is not set # CONFIG_PNX8550_STB810 is not set # CONFIG_PROBE_INITRD_HEADER is not set -# CONFIG_R6040 is not set CONFIG_RTL8306_PHY=y -CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y +CONFIG_RTL8366_SMI=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 @@ -180,6 +210,7 @@ CONFIG_SERIAL_8250_RUNTIME_UARTS=1 # 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 @@ -188,7 +219,6 @@ CONFIG_SPI_MASTER=y CONFIG_SPI_PB44=y # CONFIG_SPI_SPIDEV is not set # CONFIG_SPI_VSC7385 is not set -CONFIG_SPI=y CONFIG_SWCONFIG=y CONFIG_SYS_HAS_CPU_MIPS32_R1=y CONFIG_SYS_HAS_CPU_MIPS32_R2=y @@ -198,9 +228,9 @@ CONFIG_SYS_SUPPORTS_ARBIT_HZ=y CONFIG_SYS_SUPPORTS_BIG_ENDIAN=y # CONFIG_TC35815 is not set CONFIG_TRAD_SIGNALS=y +# CONFIG_TREE_PREEMPT_RCU is not set +CONFIG_TREE_RCU=y CONFIG_USB_SUPPORT=y -# CONFIG_VGASTATE is not set -# CONFIG_VIA_RHINE is not set CONFIG_YAFFS_9BYTE_TAGS=y CONFIG_YAFFS_ALWAYS_CHECK_CHUNK_ERASED=y CONFIG_YAFFS_AUTO_YAFFS2=y diff --git a/target/linux/ar71xx/files/arch/mips/ar71xx/Kconfig b/target/linux/ar71xx/files/arch/mips/ar71xx/Kconfig index 72c28b460..a9ffcc311 100644 --- a/target/linux/ar71xx/files/arch/mips/ar71xx/Kconfig +++ b/target/linux/ar71xx/files/arch/mips/ar71xx/Kconfig @@ -4,23 +4,69 @@ menu "Atheros AR71xx machine selection" config AR71XX_MACH_AP81 bool "Atheros AP81 board support" - default y + select AR71XX_DEV_M25P80 + select AR71XX_DEV_AR913X_WMAC + select AR71XX_DEV_GPIO_BUTTONS + select AR71XX_DEV_LEDS_GPIO + select AR71XX_DEV_USB + default n config AR71XX_MACH_AP83 bool "Atheros AP83 board support" - default y + select AR71XX_DEV_AR913X_WMAC + select AR71XX_DEV_GPIO_BUTTONS + select AR71XX_DEV_LEDS_GPIO + select AR71XX_DEV_USB + default n + +config AR71XX_MACH_DIR_600_A1 + bool "D-Link DIR-600 rev. A1 support" + select AR71XX_DEV_AP91_PCI if PCI + select AR71XX_DEV_M25P80 + select AR71XX_DEV_GPIO_BUTTONS + select AR71XX_DEV_LEDS_GPIO + default n + +config AR71XX_MACH_DIR_615_C1 + bool "D-Link DIR-615 rev. C1 support" + select AR71XX_DEV_M25P80 + select AR71XX_DEV_AR913X_WMAC + select AR71XX_DEV_GPIO_BUTTONS + select AR71XX_DEV_LEDS_GPIO + select AR71XX_NVRAM + default n + +config AR71XX_MACH_DIR_825_B1 + bool "D-Link DIR-825 rev. B1 board support" + select AR71XX_DEV_M25P80 + select AR71XX_DEV_AP94_PCI if PCI + select AR71XX_DEV_GPIO_BUTTONS + select AR71XX_DEV_LEDS_GPIO + select AR71XX_DEV_USB + default n config AR71XX_MACH_PB42 bool "Atheros PB42 board support" - default y + select AR71XX_DEV_M25P80 + select AR71XX_DEV_GPIO_BUTTONS + select AR71XX_DEV_PB42_PCI if PCI + default n config AR71XX_MACH_PB44 bool "Atheros PB44 board support" - default y + select AR71XX_DEV_GPIO_BUTTONS + select AR71XX_DEV_PB42_PCI if PCI + select AR71XX_DEV_LEDS_GPIO + select AR71XX_DEV_USB + default n config AR71XX_MACH_AW_NR580 bool "AzureWave AW-NR580 board support" - default y + select AR71XX_DEV_M25P80 + select AR71XX_DEV_GPIO_BUTTONS + select AR71XX_DEV_PB42_PCI if PCI + select AR71XX_DEV_LEDS_GPIO + default n config AR71XX_MACH_GENERIC bool "Generic AR71xx based machine support" @@ -29,52 +75,156 @@ config AR71XX_MACH_GENERIC config AR71XX_MACH_WP543 bool "Compex WP543/WPJ543 board support" select MYLOADER - default y + select AR71XX_DEV_M25P80 + select AR71XX_DEV_GPIO_BUTTONS + select AR71XX_DEV_PB42_PCI if PCI + select AR71XX_DEV_LEDS_GPIO + select AR71XX_DEV_USB + default n config AR71XX_MACH_WRT160NL bool "Linksys WRT160NL board support" - default y + select AR71XX_DEV_M25P80 + select AR71XX_DEV_AR913X_WMAC + select AR71XX_DEV_GPIO_BUTTONS + select AR71XX_DEV_LEDS_GPIO + select AR71XX_DEV_USB + select AR71XX_NVRAM + default n config AR71XX_MACH_WRT400N bool "Linksys WRT400N board support" - default y + select AR71XX_DEV_AP94_PCI if PCI + select AR71XX_DEV_M25P80 + select AR71XX_DEV_GPIO_BUTTONS + select AR71XX_DEV_LEDS_GPIO + default n config AR71XX_MACH_RB_4XX bool "MikroTik RouterBOARD 4xx series support" - default y + select AR71XX_DEV_GPIO_BUTTONS + select AR71XX_DEV_LEDS_GPIO + select AR71XX_DEV_USB + default n config AR71XX_MACH_WNDR3700 bool "NETGEAR WNDR3700 board support" - default y + select AR71XX_DEV_M25P80 + select AR71XX_DEV_AP94_PCI if PCI + select AR71XX_DEV_GPIO_BUTTONS + select AR71XX_DEV_LEDS_GPIO + select AR71XX_DEV_USB + default n config AR71XX_MACH_WNR2000 bool "NETGEAR WNR2000 board support" - default y + select AR71XX_DEV_M25P80 + select AR71XX_DEV_AR913X_WMAC + select AR71XX_DEV_GPIO_BUTTONS + select AR71XX_DEV_LEDS_GPIO + default n config AR71XX_MACH_MZK_W04NU bool "Planex MZK-W04NU board support" - default y + select AR71XX_DEV_M25P80 + select AR71XX_DEV_AR913X_WMAC + select AR71XX_DEV_GPIO_BUTTONS + select AR71XX_DEV_LEDS_GPIO + select AR71XX_DEV_USB + default n config AR71XX_MACH_MZK_W300NH bool "Planex MZK-W300NH board support" - default y + select AR71XX_DEV_M25P80 + select AR71XX_DEV_AR913X_WMAC + select AR71XX_DEV_GPIO_BUTTONS + select AR71XX_DEV_LEDS_GPIO + default n config AR71XX_MACH_TL_WR741ND bool "TP-LINK TL-WR741ND support" - default y + select AR71XX_DEV_M25P80 + select AR71XX_DEV_AP91_PCI if PCI + select AR71XX_DEV_GPIO_BUTTONS + select AR71XX_DEV_LEDS_GPIO + default n + +config AR71XX_MACH_TL_WR841N_V1 + bool "TP-LINK TL-WR841N v1 support" + select AR71XX_DEV_M25P80 + select AR71XX_DEV_PB42_PCI if PCI + select AR71XX_DEV_DSA + select AR71XX_DEV_GPIO_BUTTONS + select AR71XX_DEV_LEDS_GPIO + default n config AR71XX_MACH_TL_WR941ND bool "TP-LINK TL-WR941ND support" - default y + select AR71XX_DEV_M25P80 + select AR71XX_DEV_AR913X_WMAC + select AR71XX_DEV_DSA + select AR71XX_DEV_GPIO_BUTTONS + select AR71XX_DEV_LEDS_GPIO + default n + +config AR71XX_MACH_TL_WR1043ND + bool "TP-LINK TL-WR1043ND support" + select AR71XX_DEV_M25P80 + select AR71XX_DEV_AR913X_WMAC + select AR71XX_DEV_GPIO_BUTTONS + select AR71XX_DEV_LEDS_GPIO + select AR71XX_DEV_USB + default n config AR71XX_MACH_TEW_632BRP bool "TRENDnet TEW-632BRP support" - default y + select AR71XX_DEV_M25P80 + select AR71XX_DEV_AR913X_WMAC + select AR71XX_DEV_GPIO_BUTTONS + select AR71XX_DEV_LEDS_GPIO + select AR71XX_NVRAM + default n config AR71XX_MACH_UBNT bool "Ubiquiti AR71xx based boards support" - default y + select AR71XX_DEV_M25P80 + select AR71XX_DEV_AP91_PCI if PCI + select AR71XX_DEV_GPIO_BUTTONS + select AR71XX_DEV_LEDS_GPIO + select AR71XX_DEV_PB42_PCI if PCI + select AR71XX_DEV_USB + default n endmenu +config AR71XX_DEV_M25P80 + def_bool n + +config AR71XX_DEV_AP91_PCI + def_bool n + +config AR71XX_DEV_AP94_PCI + def_bool n + +config AR71XX_DEV_AR913X_WMAC + def_bool n + +config AR71XX_DEV_DSA + def_bool n + +config AR71XX_DEV_GPIO_BUTTONS + def_bool n + +config AR71XX_DEV_LEDS_GPIO + def_bool n + +config AR71XX_DEV_PB42_PCI + def_bool n + +config AR71XX_DEV_USB + def_bool n + +config AR71XX_NVRAM + def_bool n + endif diff --git a/target/linux/ar71xx/files/arch/mips/ar71xx/Makefile b/target/linux/ar71xx/files/arch/mips/ar71xx/Makefile index 71ba835dc..a441dc701 100644 --- a/target/linux/ar71xx/files/arch/mips/ar71xx/Makefile +++ b/target/linux/ar71xx/files/arch/mips/ar71xx/Makefile @@ -13,9 +13,24 @@ obj-y := prom.o irq.o setup.o devices.o gpio.o ar71xx.o obj-$(CONFIG_EARLY_PRINTK) += early_printk.o obj-$(CONFIG_PCI) += pci.o +obj-$(CONFIG_AR71XX_DEV_AP91_PCI) += dev-ap91-pci.o +obj-$(CONFIG_AR71XX_DEV_AP94_PCI) += dev-ap94-pci.o +obj-$(CONFIG_AR71XX_DEV_AR913X_WMAC) += dev-ar913x-wmac.o +obj-$(CONFIG_AR71XX_DEV_DSA) += dev-dsa.o +obj-$(CONFIG_AR71XX_DEV_GPIO_BUTTONS) += dev-gpio-buttons.o +obj-$(CONFIG_AR71XX_DEV_LEDS_GPIO) += dev-leds-gpio.o +obj-$(CONFIG_AR71XX_DEV_M25P80) += dev-m25p80.o +obj-$(CONFIG_AR71XX_DEV_PB42_PCI) += dev-pb42-pci.o +obj-$(CONFIG_AR71XX_DEV_USB) += dev-usb.o + +obj-$(CONFIG_AR71XX_NVRAM) += nvram.o + obj-$(CONFIG_AR71XX_MACH_AP81) += mach-ap81.o obj-$(CONFIG_AR71XX_MACH_AP83) += mach-ap83.o obj-$(CONFIG_AR71XX_MACH_AW_NR580) += mach-aw-nr580.o +obj-$(CONFIG_AR71XX_MACH_DIR_600_A1) += mach-dir-600-a1.o +obj-$(CONFIG_AR71XX_MACH_DIR_615_C1) += mach-dir-615-c1.o +obj-$(CONFIG_AR71XX_MACH_DIR_825_B1) += mach-dir-825-b1.o obj-$(CONFIG_AR71XX_MACH_GENERIC) += mach-generic.o obj-$(CONFIG_AR71XX_MACH_MZK_W04NU) += mach-mzk-w04nu.o obj-$(CONFIG_AR71XX_MACH_MZK_W300NH) += mach-mzk-w300nh.o @@ -24,7 +39,9 @@ obj-$(CONFIG_AR71XX_MACH_PB44) += mach-pb44.o obj-$(CONFIG_AR71XX_MACH_RB_4XX) += mach-rb-4xx.o obj-$(CONFIG_AR71XX_MACH_TEW_632BRP) += mach-tew-632brp.o obj-$(CONFIG_AR71XX_MACH_TL_WR741ND) += mach-tl-wr741nd.o +obj-$(CONFIG_AR71XX_MACH_TL_WR841N_V1) += mach-tl-wr841n.o obj-$(CONFIG_AR71XX_MACH_TL_WR941ND) += mach-tl-wr941nd.o +obj-$(CONFIG_AR71XX_MACH_TL_WR1043ND) += mach-tl-wr1043nd.o obj-$(CONFIG_AR71XX_MACH_UBNT) += mach-ubnt.o obj-$(CONFIG_AR71XX_MACH_WNDR3700) += mach-wndr3700.o obj-$(CONFIG_AR71XX_MACH_WNR2000) += mach-wnr2000.o diff --git a/target/linux/ar71xx/files/arch/mips/ar71xx/ar71xx.c b/target/linux/ar71xx/files/arch/mips/ar71xx/ar71xx.c index 2a9dff311..0eddf26fb 100644 --- a/target/linux/ar71xx/files/arch/mips/ar71xx/ar71xx.c +++ b/target/linux/ar71xx/files/arch/mips/ar71xx/ar71xx.c @@ -113,6 +113,41 @@ void ar71xx_device_start(u32 mask) } EXPORT_SYMBOL_GPL(ar71xx_device_start); +int ar71xx_device_stopped(u32 mask) +{ + unsigned long flags; + u32 t; + + switch (ar71xx_soc) { + case AR71XX_SOC_AR7130: + case AR71XX_SOC_AR7141: + case AR71XX_SOC_AR7161: + local_irq_save(flags); + t = ar71xx_reset_rr(AR71XX_RESET_REG_RESET_MODULE); + local_irq_restore(flags); + break; + + case AR71XX_SOC_AR7240: + local_irq_save(flags); + t = ar71xx_reset_rr(AR724X_RESET_REG_RESET_MODULE); + local_irq_restore(flags); + break; + + case AR71XX_SOC_AR9130: + case AR71XX_SOC_AR9132: + local_irq_save(flags); + t = ar71xx_reset_rr(AR91XX_RESET_REG_RESET_MODULE); + local_irq_restore(flags); + break; + + default: + BUG(); + } + + return ((t & mask) == mask); +} +EXPORT_SYMBOL_GPL(ar71xx_device_stopped); + void ar71xx_ddr_flush(u32 reg) { ar71xx_ddr_wr(reg, 1); diff --git a/target/linux/ar71xx/files/arch/mips/ar71xx/dev-ap91-pci.c b/target/linux/ar71xx/files/arch/mips/ar71xx/dev-ap91-pci.c new file mode 100644 index 000000000..e81a01aba --- /dev/null +++ b/target/linux/ar71xx/files/arch/mips/ar71xx/dev-ap91-pci.c @@ -0,0 +1,114 @@ +/* + * Atheros AP91 reference board PCI initialization + * + * Copyright (C) 2009 Gabor Juhos + * + * 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 +#include +#include + +#include +#include + +#include "dev-ap91-pci.h" + +static struct ath9k_platform_data ap91_wmac_data; +static char ap91_wmac_mac[6]; +static int ap91_pci_fixup_enabled; + +static struct ar71xx_pci_irq ap91_pci_irqs[] __initdata = { + { + .slot = 0, + .pin = 1, + .irq = AR71XX_PCI_IRQ_DEV0, + } +}; + +static int ap91_pci_plat_dev_init(struct pci_dev *dev) +{ + switch(PCI_SLOT(dev->devfn)) { + case 0: + dev->dev.platform_data = &ap91_wmac_data; + break; + } + + return 0; +} + +static void ap91_pci_fixup(struct pci_dev *dev) +{ + void __iomem *mem; + u16 *cal_data; + u16 cmd; + u32 val; + + if (!ap91_pci_fixup_enabled) + return; + + printk(KERN_INFO "PCI: fixup device %s\n", pci_name(dev)); + + cal_data = ap91_wmac_data.eeprom_data; + if (*cal_data != 0xa55a) { + printk(KERN_ERR "PCI: no calibration data found for %s\n", + pci_name(dev)); + return; + } + + mem = ioremap(AR71XX_PCI_MEM_BASE, 0x10000); + if (!mem) { + printk(KERN_ERR "PCI: ioremap error for device %s\n", + pci_name(dev)); + return; + } + + /* Setup the PCI device to allow access to the internal registers */ + pci_write_config_dword(dev, PCI_BASE_ADDRESS_0, 0xffff); + pci_read_config_word(dev, PCI_COMMAND, &cmd); + cmd |= PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY; + pci_write_config_word(dev, PCI_COMMAND, cmd); + + /* set pointer to first reg address */ + cal_data += 3; + while (*cal_data != 0xffff) { + u32 reg; + reg = *cal_data++; + val = *cal_data++; + val |= (*cal_data++) << 16; + + __raw_writel(val, mem + reg); + udelay(100); + } + + pci_read_config_dword(dev, PCI_VENDOR_ID, &val); + dev->vendor = val & 0xffff; + dev->device = (val >> 16) & 0xffff; + + pci_read_config_dword(dev, PCI_CLASS_REVISION, &val); + dev->revision = val & 0xff; + dev->class = val >> 8; /* upper 3 bytes */ + + iounmap(mem); +} +DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_ATHEROS, PCI_ANY_ID, ap91_pci_fixup); + +void __init ap91_pci_init(u8 *cal_data, u8 *mac_addr) +{ + if (cal_data) + memcpy(ap91_wmac_data.eeprom_data, cal_data, + sizeof(ap91_wmac_data.eeprom_data)); + + if (mac_addr) { + memcpy(ap91_wmac_mac, mac_addr, sizeof(ap91_wmac_mac)); + ap91_wmac_data.macaddr = ap91_wmac_mac; + } + + ar71xx_pci_plat_dev_init = ap91_pci_plat_dev_init; + ar71xx_pci_init(ARRAY_SIZE(ap91_pci_irqs), ap91_pci_irqs); + + ap91_pci_fixup_enabled = 1; +} diff --git a/target/linux/ar71xx/files/arch/mips/ar71xx/dev-ap91-pci.h b/target/linux/ar71xx/files/arch/mips/ar71xx/dev-ap91-pci.h new file mode 100644 index 000000000..d6f2e522d --- /dev/null +++ b/target/linux/ar71xx/files/arch/mips/ar71xx/dev-ap91-pci.h @@ -0,0 +1,21 @@ +/* + * Atheros AP91 reference board PCI initialization + * + * Copyright (C) 2009 Gabor Juhos + * + * 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 _AR71XX_DEV_AP91_PCI_H +#define _AR71XX_DEV_AP91_PCI_H + +#if defined(CONFIG_AR71XX_DEV_AP91_PCI) +void ap91_pci_init(u8 *cal_data, u8 *mac_addr) __init; +#else +static inline void ap91_pci_init(u8 *cal_data, u8 *mac_addr) { } +#endif + +#endif /* _AR71XX_DEV_AP91_PCI_H */ + diff --git a/target/linux/ar71xx/files/arch/mips/ar71xx/dev-ap94-pci.c b/target/linux/ar71xx/files/arch/mips/ar71xx/dev-ap94-pci.c new file mode 100644 index 000000000..920ab6c72 --- /dev/null +++ b/target/linux/ar71xx/files/arch/mips/ar71xx/dev-ap94-pci.c @@ -0,0 +1,153 @@ +/* + * Atheros AP94 reference board PCI initialization + * + * Copyright (C) 2009 Gabor Juhos + * + * 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 +#include +#include + +#include +#include + +#include "dev-ap94-pci.h" + +static struct ath9k_platform_data ap94_wmac0_data; +static struct ath9k_platform_data ap94_wmac1_data; +static char ap94_wmac0_mac[6]; +static char ap94_wmac1_mac[6]; +static int ap94_pci_fixup_enabled; + +static struct ar71xx_pci_irq ap94_pci_irqs[] __initdata = { + { + .slot = 0, + .pin = 1, + .irq = AR71XX_PCI_IRQ_DEV0, + }, { + .slot = 1, + .pin = 1, + .irq = AR71XX_PCI_IRQ_DEV1, + } +}; + +static int ap94_pci_plat_dev_init(struct pci_dev *dev) +{ + switch(PCI_SLOT(dev->devfn)) { + case 17: + dev->dev.platform_data = &ap94_wmac0_data; + break; + + case 18: + dev->dev.platform_data = &ap94_wmac1_data; + break; + } + + return 0; +} + +static void ap94_pci_fixup(struct pci_dev *dev) +{ + void __iomem *mem; + u16 *cal_data; + u16 cmd; + u32 bar0; + u32 val; + + if (!ap94_pci_fixup_enabled) + return; + + switch (PCI_SLOT(dev->devfn)) { + case 17: + cal_data = ap94_wmac0_data.eeprom_data; + break; + case 18: + cal_data = ap94_wmac1_data.eeprom_data; + break; + default: + return; + } + + if (*cal_data != 0xa55a) { + printk(KERN_ERR "PCI: no calibration data found for %s\n", + pci_name(dev)); + return; + } + + mem = ioremap(AR71XX_PCI_MEM_BASE, 0x10000); + if (!mem) { + printk(KERN_ERR "PCI: ioremap error for device %s\n", + pci_name(dev)); + return; + } + + printk(KERN_INFO "PCI: fixup device %s\n", pci_name(dev)); + + pci_read_config_dword(dev, PCI_BASE_ADDRESS_0, &bar0); + + /* Setup the PCI device to allow access to the internal registers */ + pci_write_config_dword(dev, PCI_BASE_ADDRESS_0, AR71XX_PCI_MEM_BASE); + pci_read_config_word(dev, PCI_COMMAND, &cmd); + cmd |= PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY; + pci_write_config_word(dev, PCI_COMMAND, cmd); + + /* set pointer to first reg address */ + cal_data += 3; + while (*cal_data != 0xffff) { + u32 reg; + reg = *cal_data++; + val = *cal_data++; + val |= (*cal_data++) << 16; + + __raw_writel(val, mem + reg); + udelay(100); + } + + pci_read_config_dword(dev, PCI_VENDOR_ID, &val); + dev->vendor = val & 0xffff; + dev->device = (val >> 16) & 0xffff; + + pci_read_config_dword(dev, PCI_CLASS_REVISION, &val); + dev->revision = val & 0xff; + dev->class = val >> 8; /* upper 3 bytes */ + + pci_read_config_word(dev, PCI_COMMAND, &cmd); + cmd &= ~(PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY); + pci_write_config_word(dev, PCI_COMMAND, cmd); + + pci_write_config_dword(dev, PCI_BASE_ADDRESS_0, bar0); + + iounmap(mem); +} +DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_ATHEROS, PCI_ANY_ID, ap94_pci_fixup); + +void __init ap94_pci_init(u8 *cal_data0, u8 *mac_addr0, + u8 *cal_data1, u8 *mac_addr1) +{ + if (cal_data0) + memcpy(ap94_wmac0_data.eeprom_data, cal_data0, + sizeof(ap94_wmac0_data.eeprom_data)); + + if (cal_data1) + memcpy(ap94_wmac1_data.eeprom_data, cal_data1, + sizeof(ap94_wmac1_data.eeprom_data)); + + if (mac_addr0) { + memcpy(ap94_wmac0_mac, mac_addr0, sizeof(ap94_wmac0_mac)); + ap94_wmac0_data.macaddr = ap94_wmac0_mac; + } + + if (mac_addr1) { + memcpy(ap94_wmac1_mac, mac_addr1, sizeof(ap94_wmac1_mac)); + ap94_wmac1_data.macaddr = ap94_wmac1_mac; + } + + ar71xx_pci_plat_dev_init = ap94_pci_plat_dev_init; + ar71xx_pci_init(ARRAY_SIZE(ap94_pci_irqs), ap94_pci_irqs); + + ap94_pci_fixup_enabled = 1; +} diff --git a/target/linux/ar71xx/files/arch/mips/ar71xx/dev-ap94-pci.h b/target/linux/ar71xx/files/arch/mips/ar71xx/dev-ap94-pci.h new file mode 100644 index 000000000..7969ed427 --- /dev/null +++ b/target/linux/ar71xx/files/arch/mips/ar71xx/dev-ap94-pci.h @@ -0,0 +1,25 @@ +/* + * Atheros AP94 reference board PCI initialization + * + * Copyright (C) 2009 Gabor Juhos + * + * 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 _AR71XX_DEV_AP94_PCI_H +#define _AR71XX_DEV_AP94_PCI_H + +#if defined(CONFIG_AR71XX_DEV_AP94_PCI) +void ap94_pci_init(u8 *cal_data0, u8 *mac_addr0, + u8 *cal_data1, u8 *mac_addr1) __init; +#else +static inline void ap94_pci_init(u8 *cal_data0, u8 *mac_addr0, + u8 *cal_data1, u8 *mac_addr1) +{ +} +#endif + +#endif /* _AR71XX_DEV_AP94_PCI_H */ + diff --git a/target/linux/ar71xx/files/arch/mips/ar71xx/dev-ar913x-wmac.c b/target/linux/ar71xx/files/arch/mips/ar71xx/dev-ar913x-wmac.c new file mode 100644 index 000000000..67eaa833b --- /dev/null +++ b/target/linux/ar71xx/files/arch/mips/ar71xx/dev-ar913x-wmac.c @@ -0,0 +1,68 @@ +/* + * Atheros AR913x SoC built-in WMAC device support + * + * Copyright (C) 2008-2009 Gabor Juhos + * Copyright (C) 2008 Imre Kaloz + * + * Parts of this file are based on Atheros' 2.6.15 BSP + * + * 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 +#include +#include +#include +#include +#include + +#include + +#include "dev-ar913x-wmac.h" + +static struct ath9k_platform_data ar913x_wmac_data; +static char ar913x_wmac_mac[6]; + +static struct resource ar913x_wmac_resources[] = { + { + .start = AR91XX_WMAC_BASE, + .end = AR91XX_WMAC_BASE + AR91XX_WMAC_SIZE - 1, + .flags = IORESOURCE_MEM, + }, { + .start = AR71XX_CPU_IRQ_WMAC, + .end = AR71XX_CPU_IRQ_WMAC, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device ar913x_wmac_device = { + .name = "ath9k", + .id = -1, + .resource = ar913x_wmac_resources, + .num_resources = ARRAY_SIZE(ar913x_wmac_resources), + .dev = { + .platform_data = &ar913x_wmac_data, + }, +}; + +void __init ar913x_add_device_wmac(u8 *cal_data, u8 *mac_addr) +{ + if (cal_data) + memcpy(ar913x_wmac_data.eeprom_data, cal_data, + sizeof(ar913x_wmac_data.eeprom_data)); + + if (mac_addr) { + memcpy(ar913x_wmac_mac, mac_addr, sizeof(ar913x_wmac_mac)); + ar913x_wmac_data.macaddr = ar913x_wmac_mac; + } + + ar71xx_device_stop(RESET_MODULE_AMBA2WMAC); + mdelay(10); + + ar71xx_device_start(RESET_MODULE_AMBA2WMAC); + mdelay(10); + + platform_device_register(&ar913x_wmac_device); +} diff --git a/target/linux/ar71xx/files/arch/mips/ar71xx/dev-ar913x-wmac.h b/target/linux/ar71xx/files/arch/mips/ar71xx/dev-ar913x-wmac.h new file mode 100644 index 000000000..72d8d7288 --- /dev/null +++ b/target/linux/ar71xx/files/arch/mips/ar71xx/dev-ar913x-wmac.h @@ -0,0 +1,19 @@ +/* + * Atheros AR913x SoC built-in WMAC device support + * + * Copyright (C) 2008-2009 Gabor Juhos + * Copyright (C) 2008 Imre Kaloz + * + * Parts of this file are based on Atheros' 2.6.15 BSP + * + * 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 _AR71XX_DEV_AR913X_WMAC_H +#define _AR71XX_DEV_AR913X_WMAC_H + +void ar913x_add_device_wmac(u8 *cal_data, u8 *mac_addr) __init; + +#endif /* _AR71XX_DEV_AR913X_WMAC_H */ diff --git a/target/linux/ar71xx/files/arch/mips/ar71xx/dev-dsa.c b/target/linux/ar71xx/files/arch/mips/ar71xx/dev-dsa.c new file mode 100644 index 000000000..c2877f272 --- /dev/null +++ b/target/linux/ar71xx/files/arch/mips/ar71xx/dev-dsa.c @@ -0,0 +1,50 @@ +/* + * Atheros AR71xx DSA switch device support + * + * Copyright (C) 2008-2009 Gabor Juhos + * Copyright (C) 2008 Imre Kaloz + * + * 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 +#include + +#include + +#include "devices.h" +#include "dev-dsa.h" + +static struct platform_device ar71xx_dsa_switch_device = { + .name = "dsa", + .id = 0, +}; + +void __init ar71xx_add_device_dsa(unsigned int id, + struct dsa_platform_data *d) +{ + int i; + + switch (id) { + case 0: + d->netdev = &ar71xx_eth0_device.dev; + break; + case 1: + d->netdev = &ar71xx_eth1_device.dev; + break; + default: + printk(KERN_ERR + "ar71xx: invalid ethernet id %d for DSA switch\n", + id); + return; + } + + for (i = 0; i < d->nr_chips; i++) + d->chip[i].mii_bus = &ar71xx_mdio_device.dev; + + ar71xx_dsa_switch_device.dev.platform_data = d; + + platform_device_register(&ar71xx_dsa_switch_device); +} diff --git a/target/linux/ar71xx/files/arch/mips/ar71xx/dev-dsa.h b/target/linux/ar71xx/files/arch/mips/ar71xx/dev-dsa.h new file mode 100644 index 000000000..2b11882e3 --- /dev/null +++ b/target/linux/ar71xx/files/arch/mips/ar71xx/dev-dsa.h @@ -0,0 +1,20 @@ +/* + * Atheros AR71xx DSA switch device support + * + * Copyright (C) 2008-2009 Gabor Juhos + * Copyright (C) 2008 Imre Kaloz + * + * 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 _AR71XX_DEV_DSA_H +#define _AR71XX_DEV_DSA_H + +#include + +void ar71xx_add_device_dsa(unsigned int id, + struct dsa_platform_data *d) __init; + +#endif /* _AR71XX_DEV_DSA_H */ diff --git a/target/linux/ar71xx/files/arch/mips/ar71xx/dev-gpio-buttons.c b/target/linux/ar71xx/files/arch/mips/ar71xx/dev-gpio-buttons.c new file mode 100644 index 000000000..df7416de1 --- /dev/null +++ b/target/linux/ar71xx/files/arch/mips/ar71xx/dev-gpio-buttons.c @@ -0,0 +1,58 @@ +/* + * Atheros AR71xx GPIO button support + * + * Copyright (C) 2008-2009 Gabor Juhos + * Copyright (C) 2008 Imre Kaloz + * + * 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/init.h" +#include + +#include "dev-gpio-buttons.h" + +void __init ar71xx_add_device_gpio_buttons(int id, + unsigned poll_interval, + unsigned nbuttons, + struct gpio_button *buttons) +{ + struct platform_device *pdev; + struct gpio_buttons_platform_data pdata; + struct gpio_button *p; + int err; + + p = kmalloc(nbuttons * sizeof(*p), GFP_KERNEL); + if (!p) + return; + + memcpy(p, buttons, nbuttons * sizeof(*p)); + + pdev = platform_device_alloc("gpio-buttons", id); + if (!pdev) + goto err_free_buttons; + + memset(&pdata, 0, sizeof(pdata)); + pdata.poll_interval = poll_interval; + pdata.nbuttons = nbuttons; + pdata.buttons = p; + + err = platform_device_add_data(pdev, &pdata, sizeof(pdata)); + if (err) + goto err_put_pdev; + + + err = platform_device_add(pdev); + if (err) + goto err_put_pdev; + + return; + +err_put_pdev: + platform_device_put(pdev); + +err_free_buttons: + kfree(p); +} diff --git a/target/linux/ar71xx/files/arch/mips/ar71xx/dev-gpio-buttons.h b/target/linux/ar71xx/files/arch/mips/ar71xx/dev-gpio-buttons.h new file mode 100644 index 000000000..97e9fe599 --- /dev/null +++ b/target/linux/ar71xx/files/arch/mips/ar71xx/dev-gpio-buttons.h @@ -0,0 +1,25 @@ +/* + * Atheros AR71xx GPIO button support + * + * Copyright (C) 2008-2009 Gabor Juhos + * Copyright (C) 2008 Imre Kaloz + * + * 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 _AR71XX_DEV_GPIO_BUTTONS_H +#define _AR71XX_DEV_GPIO_BUTTONS_H + +#include +#include + +#include + +void ar71xx_add_device_gpio_buttons(int id, + unsigned poll_interval, + unsigned nbuttons, + struct gpio_button *buttons) __init; + +#endif /* _AR71XX_DEV_GPIO_BUTTONS_H */ diff --git a/target/linux/ar71xx/files/arch/mips/ar71xx/dev-leds-gpio.c b/target/linux/ar71xx/files/arch/mips/ar71xx/dev-leds-gpio.c new file mode 100644 index 000000000..7066ddc01 --- /dev/null +++ b/target/linux/ar71xx/files/arch/mips/ar71xx/dev-leds-gpio.c @@ -0,0 +1,56 @@ +/* + * Atheros AR71xx GPIO LED device support + * + * Copyright (C) 2008-2009 Gabor Juhos + * Copyright (C) 2008 Imre Kaloz + * + * Parts of this file are based on Atheros' 2.6.15 BSP + * + * 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 +#include + +#include "dev-leds-gpio.h" + +void __init ar71xx_add_device_leds_gpio(int id, unsigned num_leds, + struct gpio_led *leds) +{ + struct platform_device *pdev; + struct gpio_led_platform_data pdata; + struct gpio_led *p; + int err; + + p = kmalloc(num_leds * sizeof(*p), GFP_KERNEL); + if (!p) + return; + + memcpy(p, leds, num_leds * sizeof(*p)); + + pdev = platform_device_alloc("leds-gpio", id); + if (!pdev) + goto err_free_leds; + + memset(&pdata, 0, sizeof(pdata)); + pdata.num_leds = num_leds; + pdata.leds = p; + + err = platform_device_add_data(pdev, &pdata, sizeof(pdata)); + if (err) + goto err_put_pdev; + + err = platform_device_add(pdev); + if (err) + goto err_put_pdev; + + return; + +err_put_pdev: + platform_device_put(pdev); + +err_free_leds: + kfree(p); +} diff --git a/target/linux/ar71xx/files/arch/mips/ar71xx/dev-leds-gpio.h b/target/linux/ar71xx/files/arch/mips/ar71xx/dev-leds-gpio.h new file mode 100644 index 000000000..ab4a89d83 --- /dev/null +++ b/target/linux/ar71xx/files/arch/mips/ar71xx/dev-leds-gpio.h @@ -0,0 +1,21 @@ +/* + * Atheros AR71xx GPIO LED device support + * + * Copyright (C) 2008-2009 Gabor Juhos + * Copyright (C) 2008 Imre Kaloz + * + * 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 _AR71XX_DEV_LEDS_GPIO_H +#define _AR71XX_DEV_LEDS_GPIO_H + +#include + +void ar71xx_add_device_leds_gpio(int id, + unsigned num_leds, + struct gpio_led *leds) __init; + +#endif /* _AR71XX_DEV_LEDS_GPIO_H */ diff --git a/target/linux/ar71xx/files/arch/mips/ar71xx/dev-m25p80.c b/target/linux/ar71xx/files/arch/mips/ar71xx/dev-m25p80.c new file mode 100644 index 000000000..666b508fc --- /dev/null +++ b/target/linux/ar71xx/files/arch/mips/ar71xx/dev-m25p80.c @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2009 Gabor Juhos + * + * 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 +#include +#include + +#include "devices.h" +#include "dev-m25p80.h" + +static struct spi_board_info ar71xx_spi_info[] = { + { + .bus_num = 0, + .chip_select = 0, + .max_speed_hz = 25000000, + .modalias = "m25p80", + } +}; + +void __init ar71xx_add_device_m25p80(struct flash_platform_data *pdata) +{ + ar71xx_spi_info[0].platform_data = pdata; + ar71xx_add_device_spi(NULL, ar71xx_spi_info, + ARRAY_SIZE(ar71xx_spi_info)); +} diff --git a/target/linux/ar71xx/files/arch/mips/ar71xx/dev-m25p80.h b/target/linux/ar71xx/files/arch/mips/ar71xx/dev-m25p80.h new file mode 100644 index 000000000..0b8e56d03 --- /dev/null +++ b/target/linux/ar71xx/files/arch/mips/ar71xx/dev-m25p80.h @@ -0,0 +1,16 @@ +/* + * Copyright (C) 2009 Gabor Juhos + * + * 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 _AR71XX_DEV_M25P80_H +#define _AR71XX_DEV_M25P80_H + +#include + +void ar71xx_add_device_m25p80(struct flash_platform_data *pdata) __init; + +#endif /* _AR71XX_DEV_M25P80_H */ diff --git a/target/linux/ar71xx/files/arch/mips/ar71xx/dev-pb42-pci.c b/target/linux/ar71xx/files/arch/mips/ar71xx/dev-pb42-pci.c new file mode 100644 index 000000000..0678567a2 --- /dev/null +++ b/target/linux/ar71xx/files/arch/mips/ar71xx/dev-pb42-pci.c @@ -0,0 +1,40 @@ +/* + * Atheros PB42 reference board PCI initialization + * + * Copyright (C) 2008-2009 Gabor Juhos + * Copyright (C) 2008 Imre Kaloz + * + * Parts of this file are based on Atheros' 2.6.15 BSP + * + * 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 + +#include +#include + +#include "dev-pb42-pci.h" + +static struct ar71xx_pci_irq pb42_pci_irqs[] __initdata = { + { + .slot = 0, + .pin = 1, + .irq = AR71XX_PCI_IRQ_DEV0, + }, { + .slot = 1, + .pin = 1, + .irq = AR71XX_PCI_IRQ_DEV1, + }, { + .slot = 2, + .pin = 1, + .irq = AR71XX_PCI_IRQ_DEV2, + } +}; + +void __init pb42_pci_init(void) +{ + ar71xx_pci_init(ARRAY_SIZE(pb42_pci_irqs), pb42_pci_irqs); +} diff --git a/target/linux/ar71xx/files/arch/mips/ar71xx/dev-pb42-pci.h b/target/linux/ar71xx/files/arch/mips/ar71xx/dev-pb42-pci.h new file mode 100644 index 000000000..f9ef95123 --- /dev/null +++ b/target/linux/ar71xx/files/arch/mips/ar71xx/dev-pb42-pci.h @@ -0,0 +1,21 @@ +/* + * Atheros PB42 reference board PCI initialization + * + * Copyright (C) 2008-2009 Gabor Juhos + * Copyright (C) 2008 Imre Kaloz + * + * 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 _AR71XX_DEV_PB42_PCI_H +#define _AR71XX_DEV_PB42_PCI_H + +#if defined(CONFIG_AR71XX_DEV_PB42_PCI) +void pb42_pci_init(void) __init; +#else +static inline void pb42_pci_init(void) { } +#endif + +#endif /* _AR71XX_DEV_PB42_PCI_H */ diff --git a/target/linux/ar71xx/files/arch/mips/ar71xx/dev-usb.c b/target/linux/ar71xx/files/arch/mips/ar71xx/dev-usb.c new file mode 100644 index 000000000..514ab3d7b --- /dev/null +++ b/target/linux/ar71xx/files/arch/mips/ar71xx/dev-usb.c @@ -0,0 +1,173 @@ +/* + * Atheros AR71xx USB host device support + * + * Copyright (C) 2008-2009 Gabor Juhos + * Copyright (C) 2008 Imre Kaloz + * + * Parts of this file are based on Atheros' 2.6.15 BSP + * + * 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 +#include +#include +#include +#include + +#include +#include + +#include "dev-usb.h" + +/* + * OHCI (USB full speed host controller) + */ +static struct resource ar71xx_ohci_resources[] = { + [0] = { + .start = AR71XX_OHCI_BASE, + .end = AR71XX_OHCI_BASE + AR71XX_OHCI_SIZE - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AR71XX_MISC_IRQ_OHCI, + .end = AR71XX_MISC_IRQ_OHCI, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct resource ar7240_ohci_resources[] = { + [0] = { + .start = AR7240_OHCI_BASE, + .end = AR7240_OHCI_BASE + AR7240_OHCI_SIZE - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AR71XX_CPU_IRQ_USB, + .end = AR71XX_CPU_IRQ_USB, + .flags = IORESOURCE_IRQ, + }, +}; + +static u64 ar71xx_ohci_dmamask = DMA_BIT_MASK(32); +static struct platform_device ar71xx_ohci_device = { + .name = "ar71xx-ohci", + .id = -1, + .resource = ar71xx_ohci_resources, + .num_resources = ARRAY_SIZE(ar71xx_ohci_resources), + .dev = { + .dma_mask = &ar71xx_ohci_dmamask, + .coherent_dma_mask = DMA_BIT_MASK(32), + }, +}; + +/* + * EHCI (USB full speed host controller) + */ +static struct resource ar71xx_ehci_resources[] = { + [0] = { + .start = AR71XX_EHCI_BASE, + .end = AR71XX_EHCI_BASE + AR71XX_EHCI_SIZE - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AR71XX_CPU_IRQ_USB, + .end = AR71XX_CPU_IRQ_USB, + .flags = IORESOURCE_IRQ, + }, +}; + +static u64 ar71xx_ehci_dmamask = DMA_BIT_MASK(32); +static struct ar71xx_ehci_platform_data ar71xx_ehci_data; + +static struct platform_device ar71xx_ehci_device = { + .name = "ar71xx-ehci", + .id = -1, + .resource = ar71xx_ehci_resources, + .num_resources = ARRAY_SIZE(ar71xx_ehci_resources), + .dev = { + .dma_mask = &ar71xx_ehci_dmamask, + .coherent_dma_mask = DMA_BIT_MASK(32), + .platform_data = &ar71xx_ehci_data, + }, +}; + +#define AR71XX_USB_RESET_MASK \ + (RESET_MODULE_USB_HOST | RESET_MODULE_USB_PHY \ + | RESET_MODULE_USB_OHCI_DLL) + +#define AR7240_USB_RESET_MASK \ + (RESET_MODULE_USB_HOST | RESET_MODULE_USB_OHCI_DLL_7240) + +static void __init ar71xx_usb_setup(void) +{ + ar71xx_device_stop(AR71XX_USB_RESET_MASK); + mdelay(1000); + ar71xx_device_start(AR71XX_USB_RESET_MASK); + + /* Turning on the Buff and Desc swap bits */ + ar71xx_usb_ctrl_wr(USB_CTRL_REG_CONFIG, 0xf0000); + + /* WAR for HW bug. Here it adjusts the duration between two SOFS */ + ar71xx_usb_ctrl_wr(USB_CTRL_REG_FLADJ, 0x20c00); + + mdelay(900); + + platform_device_register(&ar71xx_ohci_device); + platform_device_register(&ar71xx_ehci_device); +} + +static void __init ar7240_usb_setup(void) +{ + ar71xx_device_stop(AR7240_USB_RESET_MASK); + mdelay(1000); + ar71xx_device_start(AR7240_USB_RESET_MASK); + + /* WAR for HW bug. Here it adjusts the duration between two SOFS */ + ar71xx_usb_ctrl_wr(USB_CTRL_REG_FLADJ, 0x3); + + ar71xx_ohci_device.resource = ar7240_ohci_resources; + ar71xx_ohci_device.num_resources = ARRAY_SIZE(ar7240_ohci_resources); + + platform_device_register(&ar71xx_ohci_device); +} + +static void __init ar91xx_usb_setup(void) +{ + ar71xx_device_stop(RESET_MODULE_USBSUS_OVERRIDE); + mdelay(10); + + ar71xx_device_start(RESET_MODULE_USB_HOST); + mdelay(10); + + ar71xx_device_start(RESET_MODULE_USB_PHY); + mdelay(10); + + ar71xx_ehci_data.is_ar91xx = 1; + platform_device_register(&ar71xx_ehci_device); +} + +void __init ar71xx_add_device_usb(void) +{ + switch (ar71xx_soc) { + case AR71XX_SOC_AR7240: + ar7240_usb_setup(); + break; + + case AR71XX_SOC_AR7130: + case AR71XX_SOC_AR7141: + case AR71XX_SOC_AR7161: + ar71xx_usb_setup(); + break; + + case AR71XX_SOC_AR9130: + case AR71XX_SOC_AR9132: + ar91xx_usb_setup(); + break; + + default: + BUG(); + } +} diff --git a/target/linux/ar71xx/files/arch/mips/ar71xx/dev-usb.h b/target/linux/ar71xx/files/arch/mips/ar71xx/dev-usb.h new file mode 100644 index 000000000..aa49f539c --- /dev/null +++ b/target/linux/ar71xx/files/arch/mips/ar71xx/dev-usb.h @@ -0,0 +1,17 @@ +/* + * Atheros AR71xx USB host device support + * + * Copyright (C) 2008-2009 Gabor Juhos + * Copyright (C) 2008 Imre Kaloz + * + * 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 _AR71XX_DEV_USB_H +#define _AR71XX_DEV_USB_H + +void ar71xx_add_device_usb(void) __init; + +#endif /* _AR71XX_DEV_USB_H */ diff --git a/target/linux/ar71xx/files/arch/mips/ar71xx/devices.c b/target/linux/ar71xx/files/arch/mips/ar71xx/devices.c index bed23938e..6aee4dc5c 100644 --- a/target/linux/ar71xx/files/arch/mips/ar71xx/devices.c +++ b/target/linux/ar71xx/files/arch/mips/ar71xx/devices.c @@ -14,11 +14,9 @@ #include #include #include -#include #include #include #include -#include #include @@ -26,153 +24,6 @@ static u8 ar71xx_mac_base[ETH_ALEN] __initdata; -/* - * OHCI (USB full speed host controller) - */ -static struct resource ar71xx_ohci_resources[] = { - [0] = { - .start = AR71XX_OHCI_BASE, - .end = AR71XX_OHCI_BASE + AR71XX_OHCI_SIZE - 1, - .flags = IORESOURCE_MEM, - }, - [1] = { - .start = AR71XX_MISC_IRQ_OHCI, - .end = AR71XX_MISC_IRQ_OHCI, - .flags = IORESOURCE_IRQ, - }, -}; - -static struct resource ar7240_ohci_resources[] = { - [0] = { - .start = AR7240_OHCI_BASE, - .end = AR7240_OHCI_BASE + AR7240_OHCI_SIZE - 1, - .flags = IORESOURCE_MEM, - }, - [1] = { - .start = AR71XX_CPU_IRQ_USB, - .end = AR71XX_CPU_IRQ_USB, - .flags = IORESOURCE_IRQ, - }, -}; - -static u64 ar71xx_ohci_dmamask = DMA_BIT_MASK(32); -static struct platform_device ar71xx_ohci_device = { - .name = "ar71xx-ohci", - .id = -1, - .resource = ar71xx_ohci_resources, - .num_resources = ARRAY_SIZE(ar71xx_ohci_resources), - .dev = { - .dma_mask = &ar71xx_ohci_dmamask, - .coherent_dma_mask = DMA_BIT_MASK(32), - }, -}; - -/* - * EHCI (USB full speed host controller) - */ -static struct resource ar71xx_ehci_resources[] = { - [0] = { - .start = AR71XX_EHCI_BASE, - .end = AR71XX_EHCI_BASE + AR71XX_EHCI_SIZE - 1, - .flags = IORESOURCE_MEM, - }, - [1] = { - .start = AR71XX_CPU_IRQ_USB, - .end = AR71XX_CPU_IRQ_USB, - .flags = IORESOURCE_IRQ, - }, -}; - - -static u64 ar71xx_ehci_dmamask = DMA_BIT_MASK(32); -static struct ar71xx_ehci_platform_data ar71xx_ehci_data; - -static struct platform_device ar71xx_ehci_device = { - .name = "ar71xx-ehci", - .id = -1, - .resource = ar71xx_ehci_resources, - .num_resources = ARRAY_SIZE(ar71xx_ehci_resources), - .dev = { - .dma_mask = &ar71xx_ehci_dmamask, - .coherent_dma_mask = DMA_BIT_MASK(32), - .platform_data = &ar71xx_ehci_data, - }, -}; - -#define AR71XX_USB_RESET_MASK \ - (RESET_MODULE_USB_HOST | RESET_MODULE_USB_PHY \ - | RESET_MODULE_USB_OHCI_DLL) - -#define AR7240_USB_RESET_MASK \ - (RESET_MODULE_USB_HOST | RESET_MODULE_USB_OHCI_DLL_7240) - -static void __init ar71xx_usb_setup(void) -{ - ar71xx_device_stop(AR71XX_USB_RESET_MASK); - mdelay(1000); - ar71xx_device_start(AR71XX_USB_RESET_MASK); - - /* Turning on the Buff and Desc swap bits */ - ar71xx_usb_ctrl_wr(USB_CTRL_REG_CONFIG, 0xf0000); - - /* WAR for HW bug. Here it adjusts the duration between two SOFS */ - ar71xx_usb_ctrl_wr(USB_CTRL_REG_FLADJ, 0x20c00); - - mdelay(900); -} - -static void __init ar7240_usb_setup(void) -{ - ar71xx_ohci_device.resource = ar7240_ohci_resources; - - ar71xx_device_stop(AR7240_USB_RESET_MASK); - mdelay(1000); - ar71xx_device_start(AR7240_USB_RESET_MASK); - - /* WAR for HW bug. Here it adjusts the duration between two SOFS */ - ar71xx_usb_ctrl_wr(USB_CTRL_REG_FLADJ, 0x3); -} - -static void __init ar91xx_usb_setup(void) -{ - ar71xx_device_stop(RESET_MODULE_USBSUS_OVERRIDE); - mdelay(10); - - ar71xx_device_start(RESET_MODULE_USB_HOST); - mdelay(10); - - ar71xx_device_start(RESET_MODULE_USB_PHY); - mdelay(10); -} - -void __init ar71xx_add_device_usb(void) -{ - switch (ar71xx_soc) { - case AR71XX_SOC_AR7240: - ar7240_usb_setup(); - platform_device_register(&ar71xx_ohci_device); - break; - - case AR71XX_SOC_AR7130: - case AR71XX_SOC_AR7141: - case AR71XX_SOC_AR7161: - ar71xx_usb_setup(); - platform_device_register(&ar71xx_ohci_device); - platform_device_register(&ar71xx_ehci_device); - break; - - case AR71XX_SOC_AR9130: - case AR71XX_SOC_AR9132: - ar91xx_usb_setup(); - ar71xx_ehci_data.is_ar91xx = 1; - platform_device_register(&ar71xx_ehci_device); - break; - - default: - BUG(); - } -} - static struct resource ar71xx_uart_resources[] = { { .start = AR71XX_UART_BASE, @@ -221,7 +72,7 @@ static struct resource ar71xx_mdio_resources[] = { static struct ag71xx_mdio_platform_data ar71xx_mdio_data; -static struct platform_device ar71xx_mdio_device = { +struct platform_device ar71xx_mdio_device = { .name = "ag71xx-mdio", .id = -1, .resource = ar71xx_mdio_resources, @@ -401,7 +252,7 @@ struct ag71xx_platform_data ar71xx_eth0_data = { .reset_bit = RESET_MODULE_GE0_MAC, }; -static struct platform_device ar71xx_eth0_device = { +struct platform_device ar71xx_eth0_device = { .name = "ag71xx", .id = 0, .resource = ar71xx_eth0_resources, @@ -434,7 +285,7 @@ struct ag71xx_platform_data ar71xx_eth1_data = { .reset_bit = RESET_MODULE_GE1_MAC, }; -static struct platform_device ar71xx_eth1_device = { +struct platform_device ar71xx_eth1_device = { .name = "ag71xx", .id = 1, .resource = ar71xx_eth1_resources, @@ -628,6 +479,9 @@ void __init ar71xx_add_device_eth(unsigned int id) ar71xx_eth_instance); } + if (pdata->mii_bus_dev == NULL) + pdata->mii_bus_dev = &ar71xx_mdio_device.dev; + /* Reset the device */ ar71xx_device_stop(pdata->reset_bit); mdelay(100); @@ -663,88 +517,6 @@ void __init ar71xx_add_device_spi(struct ar71xx_spi_platform_data *pdata, platform_device_register(&ar71xx_spi_device); } -void __init ar71xx_add_device_leds_gpio(int id, unsigned num_leds, - struct gpio_led *leds) -{ - struct platform_device *pdev; - struct gpio_led_platform_data pdata; - struct gpio_led *p; - int err; - - p = kmalloc(num_leds * sizeof(*p), GFP_KERNEL); - if (!p) - return; - - memcpy(p, leds, num_leds * sizeof(*p)); - - pdev = platform_device_alloc("leds-gpio", id); - if (!pdev) - goto err_free_leds; - - memset(&pdata, 0, sizeof(pdata)); - pdata.num_leds = num_leds; - pdata.leds = p; - - err = platform_device_add_data(pdev, &pdata, sizeof(pdata)); - if (err) - goto err_put_pdev; - - err = platform_device_add(pdev); - if (err) - goto err_put_pdev; - - return; - -err_put_pdev: - platform_device_put(pdev); - -err_free_leds: - kfree(p); -} - -void __init ar71xx_add_device_gpio_buttons(int id, - unsigned poll_interval, - unsigned nbuttons, - struct gpio_button *buttons) -{ - struct platform_device *pdev; - struct gpio_buttons_platform_data pdata; - struct gpio_button *p; - int err; - - p = kmalloc(nbuttons * sizeof(*p), GFP_KERNEL); - if (!p) - return; - - memcpy(p, buttons, nbuttons * sizeof(*p)); - - pdev = platform_device_alloc("gpio-buttons", id); - if (!pdev) - goto err_free_buttons; - - memset(&pdata, 0, sizeof(pdata)); - pdata.poll_interval = poll_interval; - pdata.nbuttons = nbuttons; - pdata.buttons = p; - - err = platform_device_add_data(pdev, &pdata, sizeof(pdata)); - if (err) - goto err_put_pdev; - - - err = platform_device_add(pdev); - if (err) - goto err_put_pdev; - - return; - -err_put_pdev: - platform_device_put(pdev); - -err_free_buttons: - kfree(p); -} - void __init ar71xx_add_device_wdt(void) { platform_device_register_simple("ar71xx-wdt", -1, NULL, 0); @@ -774,69 +546,16 @@ void __init ar71xx_parse_mac_addr(char *mac_str) "\"%s\"\n", mac_str); } -static struct resource ar91xx_wmac_resources[] = { - { - .start = AR91XX_WMAC_BASE, - .end = AR91XX_WMAC_BASE + AR91XX_WMAC_SIZE - 1, - .flags = IORESOURCE_MEM, - }, { - .start = AR71XX_CPU_IRQ_WMAC, - .end = AR71XX_CPU_IRQ_WMAC, - .flags = IORESOURCE_IRQ, - }, -}; - -static struct ath9k_platform_data ar91xx_wmac_data; - -static struct platform_device ar91xx_wmac_device = { - .name = "ath9k", - .id = -1, - .resource = ar91xx_wmac_resources, - .num_resources = ARRAY_SIZE(ar91xx_wmac_resources), - .dev = { - .platform_data = &ar91xx_wmac_data, - }, -}; - -void __init ar91xx_add_device_wmac(void) +static int __init ar71xx_ethaddr_setup(char *str) { - u8 *ee = (u8 *) KSEG1ADDR(0x1fff1000); - - memcpy(ar91xx_wmac_data.eeprom_data, ee, - sizeof(ar91xx_wmac_data.eeprom_data)); - - ar71xx_device_stop(RESET_MODULE_AMBA2WMAC); - mdelay(10); - - ar71xx_device_start(RESET_MODULE_AMBA2WMAC); - mdelay(10); - - platform_device_register(&ar91xx_wmac_device); + ar71xx_parse_mac_addr(str); + return 1; } +__setup("ethaddr=", ar71xx_ethaddr_setup); -static struct platform_device ar71xx_dsa_switch_device = { - .name = "dsa", - .id = 0, -}; - -void __init ar71xx_add_device_dsa(unsigned int id, - struct dsa_platform_data *d) +static int __init ar71xx_kmac_setup(char *str) { - switch (id) { - case 0: - d->netdev = &ar71xx_eth0_device.dev; - break; - case 1: - d->netdev = &ar71xx_eth1_device.dev; - break; - default: - printk(KERN_ERR - "ar71xx: invalid ethernet id %d for DSA switch\n", - id); - return; - } - d->mii_bus = &ar71xx_mdio_device.dev; - ar71xx_dsa_switch_device.dev.platform_data = d; - - platform_device_register(&ar71xx_dsa_switch_device); + ar71xx_parse_mac_addr(str); + return 1; } +__setup("kmac=", ar71xx_kmac_setup); diff --git a/target/linux/ar71xx/files/arch/mips/ar71xx/devices.h b/target/linux/ar71xx/files/arch/mips/ar71xx/devices.h index 6c721269d..957675b0e 100644 --- a/target/linux/ar71xx/files/arch/mips/ar71xx/devices.h +++ b/target/linux/ar71xx/files/arch/mips/ar71xx/devices.h @@ -14,9 +14,7 @@ #include -#include -#include -#include +struct platform_device; void ar71xx_add_device_spi(struct ar71xx_spi_platform_data *pdata, struct spi_board_info const *info, @@ -36,27 +34,15 @@ extern struct ar71xx_eth_pll_data ar71xx_eth1_pll_data; extern struct ag71xx_platform_data ar71xx_eth0_data; extern struct ag71xx_platform_data ar71xx_eth1_data; +extern struct platform_device ar71xx_eth0_device; +extern struct platform_device ar71xx_eth1_device; void ar71xx_add_device_eth(unsigned int id) __init; +extern struct platform_device ar71xx_mdio_device; void ar71xx_add_device_mdio(u32 phy_mask) __init; -void ar71xx_add_device_leds_gpio(int id, - unsigned num_leds, - struct gpio_led *leds) __init; - -void ar71xx_add_device_gpio_buttons(int id, - unsigned poll_interval, - unsigned nbuttons, - struct gpio_button *buttons) __init; - -void ar71xx_add_device_usb(void) __init; void ar71xx_add_device_uart(void) __init; void ar71xx_add_device_wdt(void) __init; -void ar91xx_add_device_wmac(void) __init; - -void ar71xx_add_device_dsa(unsigned int id, - struct dsa_platform_data *d) __init; - #endif /* __AR71XX_DEVICES_H */ diff --git a/target/linux/ar71xx/files/arch/mips/ar71xx/mach-ap81.c b/target/linux/ar71xx/files/arch/mips/ar71xx/mach-ap81.c index 418631a3b..daf7dcf9f 100644 --- a/target/linux/ar71xx/files/arch/mips/ar71xx/mach-ap81.c +++ b/target/linux/ar71xx/files/arch/mips/ar71xx/mach-ap81.c @@ -9,17 +9,18 @@ * by the Free Software Foundation. */ -#include #include #include -#include -#include -#include -#include #include +#include "machtype.h" #include "devices.h" +#include "dev-m25p80.h" +#include "dev-ar913x-wmac.h" +#include "dev-gpio-buttons.h" +#include "dev-leds-gpio.h" +#include "dev-usb.h" #define AP81_GPIO_LED_STATUS 1 #define AP81_GPIO_LED_AOSS 3 @@ -66,16 +67,6 @@ static struct flash_platform_data ap81_flash_data = { #endif }; -static struct spi_board_info ap81_spi_info[] = { - { - .bus_num = 0, - .chip_select = 0, - .max_speed_hz = 25000000, - .modalias = "m25p80", - .platform_data = &ap81_flash_data, - } -}; - static struct gpio_led ap81_leds_gpio[] __initdata = { { .name = "ap81:green:status", @@ -116,9 +107,9 @@ static struct gpio_button ap81_gpio_buttons[] __initdata = { static void __init ap81_setup(void) { - u8 *mac = (u8 *) KSEG1ADDR(0x1fff1000); + u8 *eeprom = (u8 *) KSEG1ADDR(0x1fff1000); - ar71xx_set_mac_base(mac); + ar71xx_set_mac_base(eeprom); ar71xx_add_device_mdio(0x0); ar71xx_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_RMII; @@ -135,8 +126,7 @@ static void __init ap81_setup(void) ar71xx_add_device_usb(); - ar71xx_add_device_spi(NULL, ap81_spi_info, - ARRAY_SIZE(ap81_spi_info)); + ar71xx_add_device_m25p80(&ap81_flash_data); ar71xx_add_device_leds_gpio(-1, ARRAY_SIZE(ap81_leds_gpio), ap81_leds_gpio); @@ -145,7 +135,7 @@ static void __init ap81_setup(void) ARRAY_SIZE(ap81_gpio_buttons), ap81_gpio_buttons); - ar91xx_add_device_wmac(); + ar913x_add_device_wmac(eeprom, NULL); } -MIPS_MACHINE(AR71XX_MACH_AP81, "Atheros AP81", ap81_setup); +MIPS_MACHINE(AR71XX_MACH_AP81, "AP81", "Atheros AP81", ap81_setup); diff --git a/target/linux/ar71xx/files/arch/mips/ar71xx/mach-ap83.c b/target/linux/ar71xx/files/arch/mips/ar71xx/mach-ap83.c index 80dd3c64a..cd4746ba7 100644 --- a/target/linux/ar71xx/files/arch/mips/ar71xx/mach-ap83.c +++ b/target/linux/ar71xx/files/arch/mips/ar71xx/mach-ap83.c @@ -11,18 +11,21 @@ #include #include -#include #include #include #include #include #include -#include #include #include +#include "machtype.h" #include "devices.h" +#include "dev-ar913x-wmac.h" +#include "dev-gpio-buttons.h" +#include "dev-leds-gpio.h" +#include "dev-usb.h" #define AP83_GPIO_LED_WLAN 6 #define AP83_GPIO_LED_POWER 14 @@ -35,6 +38,8 @@ #define AP83_050_GPIO_VSC7385_MOSI 16 #define AP83_050_GPIO_VSC7385_SCK 17 +#define AP83_BUTTONS_POLL_INTERVAL 20 + #ifdef CONFIG_MTD_PARTITIONS static struct mtd_partition ap83_flash_partitions[] = { { @@ -189,9 +194,9 @@ static struct spi_board_info ap83_spi_info[] = { static void __init ap83_generic_setup(void) { - u8 *mac = (u8 *) KSEG1ADDR(0x1fff1000); + u8 *eeprom = (u8 *) KSEG1ADDR(0x1fff1000); - ar71xx_set_mac_base(mac); + ar71xx_set_mac_base(eeprom); ar71xx_add_device_mdio(0xfffffffe); @@ -212,12 +217,13 @@ static void __init ap83_generic_setup(void) ar71xx_add_device_leds_gpio(-1, ARRAY_SIZE(ap83_leds_gpio), ap83_leds_gpio); - ar71xx_add_device_gpio_buttons(-1, 20, ARRAY_SIZE(ap83_gpio_buttons), + ar71xx_add_device_gpio_buttons(-1, AP83_BUTTONS_POLL_INTERVAL, + ARRAY_SIZE(ap83_gpio_buttons), ap83_gpio_buttons); ar71xx_add_device_usb(); - ar91xx_add_device_wmac(); + ar913x_add_device_wmac(eeprom, NULL); platform_device_register(&ap83_flash_device); @@ -258,4 +264,4 @@ static void __init ap83_setup(void) } } -MIPS_MACHINE(AR71XX_MACH_AP83, "Atheros AP83", ap83_setup); +MIPS_MACHINE(AR71XX_MACH_AP83, "AP83", "Atheros AP83", ap83_setup); diff --git a/target/linux/ar71xx/files/arch/mips/ar71xx/mach-aw-nr580.c b/target/linux/ar71xx/files/arch/mips/ar71xx/mach-aw-nr580.c index 1e8c2baec..5cee4c6ea 100644 --- a/target/linux/ar71xx/files/arch/mips/ar71xx/mach-aw-nr580.c +++ b/target/linux/ar71xx/files/arch/mips/ar71xx/mach-aw-nr580.c @@ -9,18 +9,18 @@ * by the Free Software Foundation. */ -#include #include #include -#include -#include -#include #include #include -#include +#include "machtype.h" #include "devices.h" +#include "dev-m25p80.h" +#include "dev-gpio-buttons.h" +#include "dev-pb42-pci.h" +#include "dev-leds-gpio.h" #define AW_NR580_GPIO_LED_READY_RED 0 #define AW_NR580_GPIO_LED_WLAN 1 @@ -33,15 +33,6 @@ #define AW_NR580_BUTTONS_POLL_INTERVAL 20 -static struct spi_board_info aw_nr580_spi_info[] = { - { - .bus_num = 0, - .chip_select = 0, - .max_speed_hz = 25000000, - .modalias = "m25p80", - } -}; - static struct gpio_led aw_nr580_leds_gpio[] __initdata = { { .name = "aw-nr580:red:ready", @@ -84,14 +75,6 @@ static struct gpio_button aw_nr580_gpio_buttons[] __initdata = { } }; -static struct ar71xx_pci_irq aw_nr580_pci_irqs[] __initdata = { - { - .slot = 1, - .pin = 1, - .irq = AR71XX_PCI_IRQ_DEV1, - } -}; - static void __init aw_nr580_setup(void) { ar71xx_add_device_mdio(0x0); @@ -103,10 +86,9 @@ static void __init aw_nr580_setup(void) ar71xx_add_device_eth(0); - ar71xx_pci_init(ARRAY_SIZE(aw_nr580_pci_irqs), aw_nr580_pci_irqs); + pb42_pci_init(); - ar71xx_add_device_spi(NULL, aw_nr580_spi_info, - ARRAY_SIZE(aw_nr580_spi_info)); + ar71xx_add_device_m25p80(NULL); ar71xx_add_device_leds_gpio(-1, ARRAY_SIZE(aw_nr580_leds_gpio), aw_nr580_leds_gpio); @@ -116,4 +98,5 @@ static void __init aw_nr580_setup(void) aw_nr580_gpio_buttons); } -MIPS_MACHINE(AR71XX_MACH_AW_NR580, "AzureWave AW-NR580", aw_nr580_setup); +MIPS_MACHINE(AR71XX_MACH_AW_NR580, "AW-NR580", "AzureWave AW-NR580", + aw_nr580_setup); diff --git a/target/linux/ar71xx/files/arch/mips/ar71xx/mach-dir-600-a1.c b/target/linux/ar71xx/files/arch/mips/ar71xx/mach-dir-600-a1.c new file mode 100644 index 000000000..d76e9b649 --- /dev/null +++ b/target/linux/ar71xx/files/arch/mips/ar71xx/mach-dir-600-a1.c @@ -0,0 +1,150 @@ +/* + * D-Link DIR-600 rev. A1 board support + * + * Copyright (C) 2010 Gabor Juhos + * + * 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 +#include + +#include + +#include "machtype.h" +#include "devices.h" +#include "dev-m25p80.h" +#include "dev-ap91-pci.h" +#include "dev-gpio-buttons.h" +#include "dev-leds-gpio.h" + +#define DIR_600_A1_GPIO_LED_WPS 0 +#define DIR_600_A1_GPIO_LED_POWER_AMBER 1 +#define DIR_600_A1_GPIO_LED_POWER_GREEN 6 + +#define DIR_600_A1_GPIO_BTN_RESET 8 +#define DIR_600_A1_GPIO_BTN_WPS 12 + +#define DIR_600_A1_BUTTONS_POLL_INTERVAL 20 + +#ifdef CONFIG_MTD_PARTITIONS +static struct mtd_partition dir_600_a1_partitions[] = { + { + .name = "u-boot", + .offset = 0, + .size = 0x030000, + .mask_flags = MTD_WRITEABLE, + }, { + .name = "nvram", + .offset = 0x030000, + .size = 0x010000, + }, { + .name = "kernel", + .offset = 0x040000, + .size = 0x0e0000, + }, { + .name = "rootfs", + .offset = 0x120000, + .size = 0x2c0000, + }, { + .name = "mac", + .offset = 0x3e0000, + .size = 0x010000, + .mask_flags = MTD_WRITEABLE, + }, { + .name = "art", + .offset = 0x3f0000, + .size = 0x010000, + .mask_flags = MTD_WRITEABLE, + }, { + .name = "firmware", + .offset = 0x040000, + .size = 0x3a0000, + } +}; +#endif /* CONFIG_MTD_PARTITIONS */ + +static struct flash_platform_data dir_600_a1_flash_data = { +#ifdef CONFIG_MTD_PARTITIONS + .parts = dir_600_a1_partitions, + .nr_parts = ARRAY_SIZE(dir_600_a1_partitions), +#endif +}; + +static struct gpio_led dir_600_a1_leds_gpio[] __initdata = { + { + .name = "dir-600-a1:green:power", + .gpio = DIR_600_A1_GPIO_LED_POWER_GREEN, + }, { + .name = "dir-600-a1:amber:power", + .gpio = DIR_600_A1_GPIO_LED_POWER_AMBER, + }, { + .name = "dir-600-a1:blue:wps", + .gpio = DIR_600_A1_GPIO_LED_WPS, + .active_low = 1, + } +}; + +static struct gpio_button dir_600_a1_gpio_buttons[] __initdata = { + { + .desc = "reset", + .type = EV_KEY, + .code = BTN_0, + .threshold = 5, + .gpio = DIR_600_A1_GPIO_BTN_RESET, + .active_low = 1, + }, { + .desc = "wps", + .type = EV_KEY, + .code = BTN_1, + .threshold = 5, + .gpio = DIR_600_A1_GPIO_BTN_WPS, + .active_low = 1, + } +}; + +static void __init dir_600_a1_setup(void) +{ + u8 *mac = (u8 *) KSEG1ADDR(0x1fff0000); + u8 *ee = (u8 *) KSEG1ADDR(0x1fff1000); + + ar71xx_set_mac_base(mac); + ar71xx_add_device_mdio(0x0); + + /* WAN port */ + ar71xx_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_RMII; + ar71xx_eth0_data.phy_mask = 0x0; + ar71xx_eth0_data.speed = SPEED_100; + ar71xx_eth0_data.duplex = DUPLEX_FULL; + ar71xx_eth0_data.fifo_cfg1 = 0x0fff0000; + ar71xx_eth0_data.fifo_cfg2 = 0x00001fff; + ar71xx_eth0_data.fifo_cfg3 = 0x008001ff; + + /* LAN ports */ + ar71xx_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_RMII; + ar71xx_eth1_data.phy_mask = 0x0; + ar71xx_eth1_data.speed = SPEED_1000; + ar71xx_eth1_data.duplex = DUPLEX_FULL; + ar71xx_eth1_data.fifo_cfg1 = 0x0fff0000; + ar71xx_eth1_data.fifo_cfg2 = 0x00001fff; + ar71xx_eth1_data.fifo_cfg3 = 0x008001ff; + + ar71xx_add_device_eth(1); + ar71xx_add_device_eth(0); + + ar71xx_add_device_m25p80(&dir_600_a1_flash_data); + + ar71xx_add_device_leds_gpio(-1, ARRAY_SIZE(dir_600_a1_leds_gpio), + dir_600_a1_leds_gpio); + + ar71xx_add_device_gpio_buttons(-1, DIR_600_A1_BUTTONS_POLL_INTERVAL, + ARRAY_SIZE(dir_600_a1_gpio_buttons), + dir_600_a1_gpio_buttons); + + ap91_pci_init(ee, NULL); +} + +MIPS_MACHINE(AR71XX_MACH_DIR_600_A1, "DIR-600-A1", "D-Link DIR-600 rev. A1", + dir_600_a1_setup); diff --git a/target/linux/ar71xx/files/arch/mips/ar71xx/mach-dir-615-c1.c b/target/linux/ar71xx/files/arch/mips/ar71xx/mach-dir-615-c1.c new file mode 100644 index 000000000..d6f1fa75d --- /dev/null +++ b/target/linux/ar71xx/files/arch/mips/ar71xx/mach-dir-615-c1.c @@ -0,0 +1,170 @@ +/* + * D-Link DIR-615 rev C1 board support + * + * Copyright (C) 2008-2009 Gabor Juhos + * Copyright (C) 2008 Imre Kaloz + * + * 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 +#include + +#include + +#include "machtype.h" +#include "devices.h" +#include "dev-m25p80.h" +#include "dev-ar913x-wmac.h" +#include "dev-gpio-buttons.h" +#include "dev-leds-gpio.h" +#include "nvram.h" + +#define DIR_615C1_GPIO_LED_ORANGE_STATUS 1 /* ORANGE:STATUS:TRICOLOR */ +#define DIR_615C1_GPIO_LED_BLUE_WPS 3 /* BLUE:WPS */ +#define DIR_615C1_GPIO_LED_GREEN_WAN 4 /* GREEN:WAN:TRICOLOR */ +#define DIR_615C1_GPIO_LED_GREEN_WANCPU 5 /* GREEN:WAN:CPU:TRICOLOR */ +#define DIR_615C1_GPIO_LED_GREEN_WLAN 6 /* GREEN:WLAN */ +#define DIR_615C1_GPIO_LED_GREEN_STATUS 14 /* GREEN:STATUS:TRICOLOR */ +#define DIR_615C1_GPIO_LED_ORANGE_WAN 15 /* ORANGE:WAN:TRICOLOR */ + +/* buttons may need refinement */ + +#define DIR_615C1_GPIO_BTN_WPS 12 +#define DIR_615C1_GPIO_BTN_RESET 21 + +#define DIR_615C1_BUTTONS_POLL_INTERVAL 20 + +#define DIR_615C1_CONFIG_ADDR 0x1f020000 +#define DIR_615C1_CONFIG_SIZE 0x10000 + +#ifdef CONFIG_MTD_PARTITIONS +static struct mtd_partition dir_615c1_partitions[] = { + { + .name = "u-boot", + .offset = 0, + .size = 0x020000, + .mask_flags = MTD_WRITEABLE, + } , { + .name = "config", + .offset = 0x020000, + .size = 0x010000, + } , { + .name = "kernel", + .offset = 0x030000, + .size = 0x0d0000, + } , { + .name = "rootfs", + .offset = 0x100000, + .size = 0x2f0000, + } , { + .name = "art", + .offset = 0x3f0000, + .size = 0x010000, + .mask_flags = MTD_WRITEABLE, + } , { + .name = "firmware", + .offset = 0x030000, + .size = 0x3c0000, + } +}; +#endif /* CONFIG_MTD_PARTITIONS */ + +static struct flash_platform_data dir_615c1_flash_data = { +#ifdef CONFIG_MTD_PARTITIONS + .parts = dir_615c1_partitions, + .nr_parts = ARRAY_SIZE(dir_615c1_partitions), +#endif +}; + +static struct gpio_led dir_615c1_leds_gpio[] __initdata = { + { + .name = "dir-615c1:orange:status", + .gpio = DIR_615C1_GPIO_LED_ORANGE_STATUS, + .active_low = 1, + }, { + .name = "dir-615c1:blue:wps", + .gpio = DIR_615C1_GPIO_LED_BLUE_WPS, + .active_low = 1, + }, { + .name = "dir-615c1:green:wan", + .gpio = DIR_615C1_GPIO_LED_GREEN_WAN, + .active_low = 1, + }, { + .name = "dir-615c1:green:wancpu", + .gpio = DIR_615C1_GPIO_LED_GREEN_WANCPU, + .active_low = 1, + }, { + .name = "dir-615c1:green:wlan", + .gpio = DIR_615C1_GPIO_LED_GREEN_WLAN, + .active_low = 1, + }, { + .name = "dir-615c1:green:status", + .gpio = DIR_615C1_GPIO_LED_GREEN_STATUS, + .active_low = 1, + }, { + .name = "dir-615c1:orange:wan", + .gpio = DIR_615C1_GPIO_LED_ORANGE_WAN, + .active_low = 1, + } + +}; + +static struct gpio_button dir_615c1_gpio_buttons[] __initdata = { + { + .desc = "reset", + .type = EV_KEY, + .code = BTN_0, + .threshold = 5, + .gpio = DIR_615C1_GPIO_BTN_RESET, + }, { + .desc = "wps", + .type = EV_KEY, + .code = BTN_1, + .threshold = 5, + .gpio = DIR_615C1_GPIO_BTN_WPS, + } +}; + +static void __init dir_615c1_setup(void) +{ + const char *config = (char *) KSEG1ADDR(DIR_615C1_CONFIG_ADDR); + u8 *eeprom = (u8 *) KSEG1ADDR(0x1fff1000); + u8 mac[6]; + u8 *wlan_mac = NULL; + + if (nvram_parse_mac_addr(config, DIR_615C1_CONFIG_SIZE, + "lan_mac=", mac) == 0) { + ar71xx_set_mac_base(mac); + wlan_mac = mac; + } + + ar71xx_add_device_mdio(0x0); + + ar71xx_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_RMII; + ar71xx_eth0_data.phy_mask = 0xf; + ar71xx_eth0_data.speed = SPEED_100; + ar71xx_eth0_data.duplex = DUPLEX_FULL; + + ar71xx_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_RMII; + ar71xx_eth1_data.phy_mask = 0x10; + + ar71xx_add_device_eth(0); + ar71xx_add_device_eth(1); + + ar71xx_add_device_m25p80(&dir_615c1_flash_data); + + ar71xx_add_device_leds_gpio(-1, ARRAY_SIZE(dir_615c1_leds_gpio), + dir_615c1_leds_gpio); + + ar71xx_add_device_gpio_buttons(-1, DIR_615C1_BUTTONS_POLL_INTERVAL, + ARRAY_SIZE(dir_615c1_gpio_buttons), + dir_615c1_gpio_buttons); + + ar913x_add_device_wmac(eeprom, wlan_mac); +} + +MIPS_MACHINE(AR71XX_MACH_DIR_615_C1, "DIR-615-C1", "D-Link DIR-615 rev. C1", + dir_615c1_setup); diff --git a/target/linux/ar71xx/files/arch/mips/ar71xx/mach-dir-825-b1.c b/target/linux/ar71xx/files/arch/mips/ar71xx/mach-dir-825-b1.c new file mode 100644 index 000000000..80ab33084 --- /dev/null +++ b/target/linux/ar71xx/files/arch/mips/ar71xx/mach-dir-825-b1.c @@ -0,0 +1,192 @@ +/* + * D-Link DIR-825 rev. B1 board support + * + * Copyright (C) 2009 Lukas Kuna, Evkanet, s.r.o. + * + * based on mach-wndr3700.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 +#include +#include +#include +#include + +#include + +#include "machtype.h" +#include "devices.h" +#include "dev-m25p80.h" +#include "dev-ap94-pci.h" +#include "dev-gpio-buttons.h" +#include "dev-leds-gpio.h" +#include "dev-usb.h" + +#define DIR825B1_GPIO_LED_BLUE_USB 0 +#define DIR825B1_GPIO_LED_ORANGE_POWER 1 +#define DIR825B1_GPIO_LED_BLUE_POWER 2 +#define DIR825B1_GPIO_LED_BLUE_POWERSAVE 4 +#define DIR825B1_GPIO_LED_ORANGE_PLANET 6 +#define DIR825B1_GPIO_LED_BLUE_PLANET 11 + +#define DIR825B1_GPIO_BTN_RESET 3 +#define DIR825B1_GPIO_BTN_POWERSAVE 8 + +#define DIR825B1_GPIO_RTL8366_SDA 5 +#define DIR825B1_GPIO_RTL8366_SCK 7 + +#define DIR825B1_BUTTONS_POLL_INTERVAL 20 + +#define DIR825B1_CAL_LOCATION_0 0x1f661000 +#define DIR825B1_CAL_LOCATION_1 0x1f665000 + +#define DIR825B1_MAC_LOCATION_0 0x2ffa81b8 +#define DIR825B1_MAC_LOCATION_1 0x2ffa8370 + +#ifdef CONFIG_MTD_PARTITIONS +static struct mtd_partition dir825b1_partitions[] = { + { + .name = "uboot", + .offset = 0, + .size = 0x040000, + .mask_flags = MTD_WRITEABLE, + } , { + .name = "config", + .offset = 0x040000, + .size = 0x010000, + .mask_flags = MTD_WRITEABLE, + } , { + .name = "firmware", + .offset = 0x050000, + .size = 0x610000, + } , { + .name = "caldata", + .offset = 0x660000, + .size = 0x010000, + .mask_flags = MTD_WRITEABLE, + } , { + .name = "unknown", + .offset = 0x670000, + .size = 0x190000, + .mask_flags = MTD_WRITEABLE, + } +}; +#endif /* CONFIG_MTD_PARTITIONS */ + +static struct flash_platform_data dir825b1_flash_data = { +#ifdef CONFIG_MTD_PARTITIONS + .parts = dir825b1_partitions, + .nr_parts = ARRAY_SIZE(dir825b1_partitions), +#endif +}; + +static struct gpio_led dir825b1_leds_gpio[] __initdata = { + { + .name = "dir825b1:blue:usb", + .gpio = DIR825B1_GPIO_LED_BLUE_USB, + .active_low = 1, + }, { + .name = "dir825b1:orange:power", + .gpio = DIR825B1_GPIO_LED_ORANGE_POWER, + .active_low = 1, + }, { + .name = "dir825b1:blue:power", + .gpio = DIR825B1_GPIO_LED_BLUE_POWER, + .active_low = 1, + }, { + .name = "dir825b1:blue:powersave", + .gpio = DIR825B1_GPIO_LED_BLUE_POWERSAVE, + .active_low = 1, + }, { + .name = "dir825b1:orange:planet", + .gpio = DIR825B1_GPIO_LED_ORANGE_PLANET, + .active_low = 1, + }, { + .name = "dir825b1:blue:planet", + .gpio = DIR825B1_GPIO_LED_BLUE_PLANET, + .active_low = 1, + } +}; + +static struct gpio_button dir825b1_gpio_buttons[] __initdata = { + { + .desc = "reset", + .type = EV_KEY, + .code = BTN_0, + .threshold = 5, + .gpio = DIR825B1_GPIO_BTN_RESET, + .active_low = 1, + } , { + .desc = "powersave", + .type = EV_KEY, + .code = BTN_1, + .threshold = 5, + .gpio = DIR825B1_GPIO_BTN_POWERSAVE, + .active_low = 1, + } +}; + +static struct rtl8366_smi_platform_data dir825b1_rtl8366_smi_data = { + .gpio_sda = DIR825B1_GPIO_RTL8366_SDA, + .gpio_sck = DIR825B1_GPIO_RTL8366_SCK, +}; + +static struct platform_device dir825b1_rtl8366_smi_device = { + .name = "rtl8366-smi", + .id = -1, + .dev = { + .platform_data = &dir825b1_rtl8366_smi_data, + } +}; + +static void __init dir825b1_setup(void) +{ + u8 mac[6], i; + + memcpy(mac, (u8*)KSEG1ADDR(DIR825B1_MAC_LOCATION_1), 6); + for(i = 5; i >= 3; i--) + if(++mac[i] != 0x00) break; + + ar71xx_set_mac_base(mac); + + ar71xx_add_device_mdio(0x0); + + ar71xx_eth0_data.mii_bus_dev = &dir825b1_rtl8366_smi_device.dev; + ar71xx_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_RGMII; + ar71xx_eth0_data.speed = SPEED_1000; + ar71xx_eth0_data.duplex = DUPLEX_FULL; + ar71xx_eth0_pll_data.pll_1000 = 0x11110000; + + ar71xx_eth1_data.mii_bus_dev = &dir825b1_rtl8366_smi_device.dev; + ar71xx_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_RGMII; + ar71xx_eth1_data.phy_mask = 0x10; + ar71xx_eth1_pll_data.pll_1000 = 0x11110000; + + ar71xx_add_device_eth(0); + ar71xx_add_device_eth(1); + + ar71xx_add_device_m25p80(&dir825b1_flash_data); + + ar71xx_add_device_leds_gpio(-1, ARRAY_SIZE(dir825b1_leds_gpio), + dir825b1_leds_gpio); + + ar71xx_add_device_gpio_buttons(-1, DIR825B1_BUTTONS_POLL_INTERVAL, + ARRAY_SIZE(dir825b1_gpio_buttons), + dir825b1_gpio_buttons); + + ar71xx_add_device_usb(); + + platform_device_register(&dir825b1_rtl8366_smi_device); + + ap94_pci_init((u8 *) KSEG1ADDR(DIR825B1_CAL_LOCATION_0), + (u8 *) KSEG1ADDR(DIR825B1_MAC_LOCATION_0), + (u8 *) KSEG1ADDR(DIR825B1_CAL_LOCATION_1), + (u8 *) KSEG1ADDR(DIR825B1_MAC_LOCATION_1)); +} + +MIPS_MACHINE(AR71XX_MACH_DIR_825_B1, "DIR-825-B1", "D-Link DIR-825 rev. B1", + dir825b1_setup); diff --git a/target/linux/ar71xx/files/arch/mips/ar71xx/mach-generic.c b/target/linux/ar71xx/files/arch/mips/ar71xx/mach-generic.c index c183ba937..8dfa6405e 100644 --- a/target/linux/ar71xx/files/arch/mips/ar71xx/mach-generic.c +++ b/target/linux/ar71xx/files/arch/mips/ar71xx/mach-generic.c @@ -11,12 +11,13 @@ #include -#include #include +#include "machtype.h" static void __init ar71xx_generic_init(void) { /* Nothing to do */ } -MIPS_MACHINE(AR71XX_MACH_GENERIC, "Generic AR71xx board", ar71xx_generic_init); +MIPS_MACHINE(AR71XX_MACH_GENERIC, "Generic", "Generic AR71xx board", + ar71xx_generic_init); diff --git a/target/linux/ar71xx/files/arch/mips/ar71xx/mach-mzk-w04nu.c b/target/linux/ar71xx/files/arch/mips/ar71xx/mach-mzk-w04nu.c index 3a1490202..6af5dd4cd 100644 --- a/target/linux/ar71xx/files/arch/mips/ar71xx/mach-mzk-w04nu.c +++ b/target/linux/ar71xx/files/arch/mips/ar71xx/mach-mzk-w04nu.c @@ -8,18 +8,18 @@ * by the Free Software Foundation. */ -#include #include #include -#include -#include -#include - -#include #include +#include "machtype.h" #include "devices.h" +#include "dev-ar913x-wmac.h" +#include "dev-gpio-buttons.h" +#include "dev-leds-gpio.h" +#include "dev-m25p80.h" +#include "dev-usb.h" #define MZK_W04NU_GPIO_LED_USB 0 #define MZK_W04NU_GPIO_LED_STATUS 1 @@ -73,16 +73,6 @@ static struct flash_platform_data mzk_w04nu_flash_data = { #endif }; -static struct spi_board_info mzk_w04nu_spi_info[] = { - { - .bus_num = 0, - .chip_select = 0, - .max_speed_hz = 25000000, - .modalias = "m25p80", - .platform_data = &mzk_w04nu_flash_data, - } -}; - static struct gpio_led mzk_w04nu_leds_gpio[] __initdata = { { .name = "mzk-w04nu:green:status", @@ -138,9 +128,9 @@ static struct gpio_button mzk_w04nu_gpio_buttons[] __initdata = { static void __init mzk_w04nu_setup(void) { - u8 *mac = (u8 *) KSEG1ADDR(0x1fff1000); + u8 *eeprom = (u8 *) KSEG1ADDR(0x1fff1000); - ar71xx_set_mac_base(mac); + ar71xx_set_mac_base(eeprom); ar71xx_add_device_mdio(0x0); @@ -156,8 +146,7 @@ static void __init mzk_w04nu_setup(void) ar71xx_add_device_eth(0); ar71xx_add_device_eth(1); - ar71xx_add_device_spi(NULL, mzk_w04nu_spi_info, - ARRAY_SIZE(mzk_w04nu_spi_info)); + ar71xx_add_device_m25p80(&mzk_w04nu_flash_data); ar71xx_add_device_leds_gpio(-1, ARRAY_SIZE(mzk_w04nu_leds_gpio), mzk_w04nu_leds_gpio); @@ -167,7 +156,8 @@ static void __init mzk_w04nu_setup(void) mzk_w04nu_gpio_buttons); ar71xx_add_device_usb(); - ar91xx_add_device_wmac(); + ar913x_add_device_wmac(eeprom, NULL); } -MIPS_MACHINE(AR71XX_MACH_MZK_W04NU, "Planex MZK-W04NU", mzk_w04nu_setup); +MIPS_MACHINE(AR71XX_MACH_MZK_W04NU, "MZK-W04NU", "Planex MZK-W04NU", + mzk_w04nu_setup); diff --git a/target/linux/ar71xx/files/arch/mips/ar71xx/mach-mzk-w300nh.c b/target/linux/ar71xx/files/arch/mips/ar71xx/mach-mzk-w300nh.c index 49cc2ac3f..88a3bd17b 100644 --- a/target/linux/ar71xx/files/arch/mips/ar71xx/mach-mzk-w300nh.c +++ b/target/linux/ar71xx/files/arch/mips/ar71xx/mach-mzk-w300nh.c @@ -9,18 +9,17 @@ * by the Free Software Foundation. */ -#include #include #include -#include -#include -#include - -#include #include +#include "machtype.h" #include "devices.h" +#include "dev-m25p80.h" +#include "dev-ar913x-wmac.h" +#include "dev-gpio-buttons.h" +#include "dev-leds-gpio.h" #define MZK_W300NH_GPIO_LED_STATUS 1 #define MZK_W300NH_GPIO_LED_WPS 3 @@ -77,16 +76,6 @@ static struct flash_platform_data mzk_w300nh_flash_data = { #endif }; -static struct spi_board_info mzk_w300nh_spi_info[] = { - { - .bus_num = 0, - .chip_select = 0, - .max_speed_hz = 25000000, - .modalias = "m25p80", - .platform_data = &mzk_w300nh_flash_data, - } -}; - static struct gpio_led mzk_w300nh_leds_gpio[] __initdata = { { .name = "mzk-w300nh:green:status", @@ -138,9 +127,9 @@ static struct gpio_button mzk_w300nh_gpio_buttons[] __initdata = { static void __init mzk_w300nh_setup(void) { - u8 *mac = (u8 *) KSEG1ADDR(0x1fff1000); + u8 *eeprom = (u8 *) KSEG1ADDR(0x1fff1000); - ar71xx_set_mac_base(mac); + ar71xx_set_mac_base(eeprom); ar71xx_add_device_mdio(0x0); @@ -156,8 +145,7 @@ static void __init mzk_w300nh_setup(void) ar71xx_add_device_eth(0); ar71xx_add_device_eth(1); - ar71xx_add_device_spi(NULL, mzk_w300nh_spi_info, - ARRAY_SIZE(mzk_w300nh_spi_info)); + ar71xx_add_device_m25p80(&mzk_w300nh_flash_data); ar71xx_add_device_leds_gpio(-1, ARRAY_SIZE(mzk_w300nh_leds_gpio), mzk_w300nh_leds_gpio); @@ -165,7 +153,8 @@ static void __init mzk_w300nh_setup(void) ar71xx_add_device_gpio_buttons(-1, MZK_W04NU_BUTTONS_POLL_INTERVAL, ARRAY_SIZE(mzk_w300nh_gpio_buttons), mzk_w300nh_gpio_buttons); - ar91xx_add_device_wmac(); + ar913x_add_device_wmac(eeprom, NULL); } -MIPS_MACHINE(AR71XX_MACH_MZK_W300NH, "Planex MZK-W300NH", mzk_w300nh_setup); +MIPS_MACHINE(AR71XX_MACH_MZK_W300NH, "MZK-W300NH", "Planex MZK-W300NH", + mzk_w300nh_setup); diff --git a/target/linux/ar71xx/files/arch/mips/ar71xx/mach-pb42.c b/target/linux/ar71xx/files/arch/mips/ar71xx/mach-pb42.c index 154a1e43d..44bf38991 100644 --- a/target/linux/ar71xx/files/arch/mips/ar71xx/mach-pb42.c +++ b/target/linux/ar71xx/files/arch/mips/ar71xx/mach-pb42.c @@ -9,49 +9,20 @@ * by the Free Software Foundation. */ -#include -#include -#include -#include -#include -#include - -#include #include -#include +#include "machtype.h" #include "devices.h" +#include "dev-m25p80.h" +#include "dev-gpio-buttons.h" +#include "dev-pb42-pci.h" +#include "dev-usb.h" #define PB42_BUTTONS_POLL_INTERVAL 20 #define PB42_GPIO_BTN_SW4 8 #define PB42_GPIO_BTN_SW5 3 -static struct spi_board_info pb42_spi_info[] = { - { - .bus_num = 0, - .chip_select = 0, - .max_speed_hz = 25000000, - .modalias = "m25p80", - } -}; - -static struct ar71xx_pci_irq pb42_pci_irqs[] __initdata = { - { - .slot = 0, - .pin = 1, - .irq = AR71XX_PCI_IRQ_DEV0, - }, { - .slot = 1, - .pin = 1, - .irq = AR71XX_PCI_IRQ_DEV1, - }, { - .slot = 2, - .pin = 1, - .irq = AR71XX_PCI_IRQ_DEV2, - } -}; - static struct gpio_button pb42_gpio_buttons[] __initdata = { { .desc = "sw4", @@ -76,8 +47,7 @@ static struct gpio_button pb42_gpio_buttons[] __initdata = { static void __init pb42_init(void) { - ar71xx_add_device_spi(NULL, pb42_spi_info, - ARRAY_SIZE(pb42_spi_info)); + ar71xx_add_device_m25p80(NULL); ar71xx_add_device_mdio(~PB42_MDIO_PHYMASK); @@ -96,7 +66,7 @@ static void __init pb42_init(void) ARRAY_SIZE(pb42_gpio_buttons), pb42_gpio_buttons); - ar71xx_pci_init(ARRAY_SIZE(pb42_pci_irqs), pb42_pci_irqs); + pb42_pci_init(); } -MIPS_MACHINE(AR71XX_MACH_PB42, "Atheros PB42", pb42_init); +MIPS_MACHINE(AR71XX_MACH_PB42, "PB42", "Atheros PB42", pb42_init); diff --git a/target/linux/ar71xx/files/arch/mips/ar71xx/mach-pb44.c b/target/linux/ar71xx/files/arch/mips/ar71xx/mach-pb44.c index 04f995c09..7cace674b 100644 --- a/target/linux/ar71xx/files/arch/mips/ar71xx/mach-pb44.c +++ b/target/linux/ar71xx/files/arch/mips/ar71xx/mach-pb44.c @@ -10,7 +10,6 @@ #include #include -#include #include #include #include @@ -20,11 +19,14 @@ #include #include -#include #include -#include +#include "machtype.h" #include "devices.h" +#include "dev-pb42-pci.h" +#include "dev-gpio-buttons.h" +#include "dev-leds-gpio.h" +#include "dev-usb.h" #define PB44_PCF8757_VSC7395_CS 0 #define PB44_PCF8757_STEREO_CS 1 @@ -52,22 +54,6 @@ #define PB44_GPIO_LED_JUMP1 (PB44_GPIO_EXP_BASE + PB44_PCF8757_LED_JUMP1) #define PB44_GPIO_LED_JUMP2 (PB44_GPIO_EXP_BASE + PB44_PCF8757_LED_JUMP2) -static struct ar71xx_pci_irq pb44_pci_irqs[] __initdata = { - { - .slot = 0, - .pin = 1, - .irq = AR71XX_PCI_IRQ_DEV0, - }, { - .slot = 1, - .pin = 1, - .irq = AR71XX_PCI_IRQ_DEV1, - }, { - .slot = 2, - .pin = 1, - .irq = AR71XX_PCI_IRQ_DEV2, - } -}; - static struct i2c_gpio_platform_data pb44_i2c_gpio_data = { .sda_pin = PB44_GPIO_I2C_SDA, .scl_pin = PB44_GPIO_I2C_SCL, @@ -202,7 +188,7 @@ static void __init pb44_init(void) ar71xx_add_device_usb(); - ar71xx_pci_init(ARRAY_SIZE(pb44_pci_irqs), pb44_pci_irqs); + pb42_pci_init(); i2c_register_board_info(0, pb44_i2c_board_info, ARRAY_SIZE(pb44_i2c_board_info)); @@ -219,4 +205,4 @@ static void __init pb44_init(void) pb44_gpio_buttons); } -MIPS_MACHINE(AR71XX_MACH_PB44, "Atheros PB44", pb44_init); +MIPS_MACHINE(AR71XX_MACH_PB44, "PB44", "Atheros PB44", pb44_init); diff --git a/target/linux/ar71xx/files/arch/mips/ar71xx/mach-rb-4xx.c b/target/linux/ar71xx/files/arch/mips/ar71xx/mach-rb-4xx.c index a8e97c385..ab3d65be9 100644 --- a/target/linux/ar71xx/files/arch/mips/ar71xx/mach-rb-4xx.c +++ b/target/linux/ar71xx/files/arch/mips/ar71xx/mach-rb-4xx.c @@ -15,13 +15,15 @@ #include #include #include -#include -#include #include #include +#include "machtype.h" #include "devices.h" +#include "dev-gpio-buttons.h" +#include "dev-leds-gpio.h" +#include "dev-usb.h" #define RB4XX_GPIO_USER_LED 4 #define RB4XX_GPIO_RESET_SWITCH 7 @@ -181,7 +183,8 @@ static void __init rb411_setup(void) ar71xx_pci_init(ARRAY_SIZE(rb4xx_pci_irqs), rb4xx_pci_irqs); } -MIPS_MACHINE(AR71XX_MACH_RB_411, "MikroTik RouterBOARD 411/A/AH", rb411_setup); +MIPS_MACHINE(AR71XX_MACH_RB_411, "411", "MikroTik RouterBOARD 411/A/AH", + rb411_setup); static void __init rb411u_setup(void) { @@ -198,7 +201,8 @@ static void __init rb411u_setup(void) ar71xx_add_device_usb(); } -MIPS_MACHINE(AR71XX_MACH_RB_411U, "MikroTik RouterBOARD 411U", rb411u_setup); +MIPS_MACHINE(AR71XX_MACH_RB_411U, "411U", "MikroTik RouterBOARD 411U", + rb411u_setup); static void __init rb433_setup(void) { @@ -221,7 +225,8 @@ static void __init rb433_setup(void) ar71xx_pci_init(ARRAY_SIZE(rb4xx_pci_irqs), rb4xx_pci_irqs); } -MIPS_MACHINE(AR71XX_MACH_RB_433, "MikroTik RouterBOARD 433/AH", rb433_setup); +MIPS_MACHINE(AR71XX_MACH_RB_433, "433", "MikroTik RouterBOARD 433/AH", + rb433_setup); static void __init rb433u_setup(void) { @@ -229,7 +234,8 @@ static void __init rb433u_setup(void) ar71xx_add_device_usb(); } -MIPS_MACHINE(AR71XX_MACH_RB_433U, "MikroTik RouterBOARD 433UAH", rb433u_setup); +MIPS_MACHINE(AR71XX_MACH_RB_433U, "433U", "MikroTik RouterBOARD 433UAH", + rb433u_setup); static void __init rb450_generic_setup(int gige) { @@ -255,14 +261,16 @@ static void __init rb450_setup(void) rb450_generic_setup(0); } -MIPS_MACHINE(AR71XX_MACH_RB_450, "MikroTik RouterBOARD 450", rb450_setup); +MIPS_MACHINE(AR71XX_MACH_RB_450, "450", "MikroTik RouterBOARD 450", + rb450_setup); static void __init rb450g_setup(void) { rb450_generic_setup(1); } -MIPS_MACHINE(AR71XX_MACH_RB_450G, "MikroTik RouterBOARD 450G", rb450g_setup); +MIPS_MACHINE(AR71XX_MACH_RB_450G, "450G", "MikroTik RouterBOARD 450G", + rb450g_setup); static void __init rb493_setup(void) { @@ -285,4 +293,5 @@ static void __init rb493_setup(void) ar71xx_pci_init(ARRAY_SIZE(rb4xx_pci_irqs), rb4xx_pci_irqs); } -MIPS_MACHINE(AR71XX_MACH_RB_493, "MikroTik RouterBOARD 493/AH", rb493_setup); +MIPS_MACHINE(AR71XX_MACH_RB_493, "493", "MikroTik RouterBOARD 493/AH", + rb493_setup); diff --git a/target/linux/ar71xx/files/arch/mips/ar71xx/mach-tew-632brp.c b/target/linux/ar71xx/files/arch/mips/ar71xx/mach-tew-632brp.c index afb8ceebd..c92cb00eb 100644 --- a/target/linux/ar71xx/files/arch/mips/ar71xx/mach-tew-632brp.c +++ b/target/linux/ar71xx/files/arch/mips/ar71xx/mach-tew-632brp.c @@ -9,18 +9,18 @@ * by the Free Software Foundation. */ -#include #include #include -#include -#include -#include - -#include #include +#include "machtype.h" #include "devices.h" +#include "dev-m25p80.h" +#include "dev-ar913x-wmac.h" +#include "dev-gpio-buttons.h" +#include "dev-leds-gpio.h" +#include "nvram.h" #define TEW_632BRP_GPIO_LED_STATUS 1 #define TEW_632BRP_GPIO_LED_WPS 3 @@ -30,6 +30,9 @@ #define TEW_632BRP_BUTTONS_POLL_INTERVAL 20 +#define TEW_632BRP_CONFIG_ADDR 0x1f020000 +#define TEW_632BRP_CONFIG_SIZE 0x10000 + #ifdef CONFIG_MTD_PARTITIONS static struct mtd_partition tew_632brp_partitions[] = { { @@ -69,16 +72,6 @@ static struct flash_platform_data tew_632brp_flash_data = { #endif }; -static struct spi_board_info tew_632brp_spi_info[] = { - { - .bus_num = 0, - .chip_select = 0, - .max_speed_hz = 25000000, - .modalias = "m25p80", - .platform_data = &tew_632brp_flash_data, - } -}; - static struct gpio_led tew_632brp_leds_gpio[] __initdata = { { .name = "tew-632brp:green:status", @@ -113,6 +106,17 @@ static struct gpio_button tew_632brp_gpio_buttons[] __initdata = { static void __init tew_632brp_setup(void) { + const char *config = (char *) KSEG1ADDR(TEW_632BRP_CONFIG_ADDR); + u8 *eeprom = (u8 *) KSEG1ADDR(0x1fff1000); + u8 mac[6]; + u8 *wlan_mac = NULL; + + if (nvram_parse_mac_addr(config, TEW_632BRP_CONFIG_SIZE, + "lan_mac=", mac) == 0) { + ar71xx_set_mac_base(mac); + wlan_mac = mac; + } + ar71xx_add_device_mdio(0x0); ar71xx_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_RMII; @@ -126,8 +130,7 @@ static void __init tew_632brp_setup(void) ar71xx_add_device_eth(0); ar71xx_add_device_eth(1); - ar71xx_add_device_spi(NULL, tew_632brp_spi_info, - ARRAY_SIZE(tew_632brp_spi_info)); + ar71xx_add_device_m25p80(&tew_632brp_flash_data); ar71xx_add_device_leds_gpio(-1, ARRAY_SIZE(tew_632brp_leds_gpio), tew_632brp_leds_gpio); @@ -136,7 +139,8 @@ static void __init tew_632brp_setup(void) ARRAY_SIZE(tew_632brp_gpio_buttons), tew_632brp_gpio_buttons); - ar91xx_add_device_wmac(); + ar913x_add_device_wmac(eeprom, wlan_mac); } -MIPS_MACHINE(AR71XX_MACH_TEW_632BRP, "TRENDnet TEW-632BRP", tew_632brp_setup); +MIPS_MACHINE(AR71XX_MACH_TEW_632BRP, "TEW-632BRP", "TRENDnet TEW-632BRP", + tew_632brp_setup); diff --git a/target/linux/ar71xx/files/arch/mips/ar71xx/mach-tl-wr1043nd.c b/target/linux/ar71xx/files/arch/mips/ar71xx/mach-tl-wr1043nd.c new file mode 100644 index 000000000..79bb22713 --- /dev/null +++ b/target/linux/ar71xx/files/arch/mips/ar71xx/mach-tl-wr1043nd.c @@ -0,0 +1,137 @@ +/* + * TP-LINK TL-WR1043ND board support + * + * Copyright (C) 2009 Gabor Juhos + * + * 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 +#include + +#include + +#include "machtype.h" +#include "devices.h" +#include "dev-m25p80.h" +#include "dev-ar913x-wmac.h" +#include "dev-gpio-buttons.h" +#include "dev-leds-gpio.h" +#include "dev-usb.h" + +#define TL_WR1043ND_GPIO_LED_USB 1 +#define TL_WR1043ND_GPIO_LED_SYSTEM 2 +#define TL_WR1043ND_GPIO_LED_QSS 5 +#define TL_WR1043ND_GPIO_LED_WLAN 9 + +#define TL_WR1043ND_GPIO_BTN_RESET 3 +#define TL_WR1043ND_GPIO_BTN_QSS 7 + +#define TL_WR1043ND_BUTTONS_POLL_INTERVAL 20 + +#ifdef CONFIG_MTD_PARTITIONS +static struct mtd_partition tl_wr1043nd_partitions[] = { + { + .name = "u-boot", + .offset = 0, + .size = 0x020000, + .mask_flags = MTD_WRITEABLE, + } , { + .name = "kernel", + .offset = 0x020000, + .size = 0x140000, + } , { + .name = "rootfs", + .offset = 0x160000, + .size = 0x690000, + } , { + .name = "art", + .offset = 0x7f0000, + .size = 0x010000, + .mask_flags = MTD_WRITEABLE, + } , { + .name = "firmware", + .offset = 0x020000, + .size = 0x7d0000, + } +}; +#endif /* CONFIG_MTD_PARTITIONS */ + +static struct flash_platform_data tl_wr1043nd_flash_data = { +#ifdef CONFIG_MTD_PARTITIONS + .parts = tl_wr1043nd_partitions, + .nr_parts = ARRAY_SIZE(tl_wr1043nd_partitions), +#endif +}; + +static struct gpio_led tl_wr1043nd_leds_gpio[] __initdata = { + { + .name = "tl-wr1043nd:green:usb", + .gpio = TL_WR1043ND_GPIO_LED_USB, + .active_low = 1, + }, { + .name = "tl-wr1043nd:green:system", + .gpio = TL_WR1043ND_GPIO_LED_SYSTEM, + .active_low = 1, + }, { + .name = "tl-wr1043nd:green:qss", + .gpio = TL_WR1043ND_GPIO_LED_QSS, + .active_low = 0, + }, { + .name = "tl-wr1043nd:green:wlan", + .gpio = TL_WR1043ND_GPIO_LED_WLAN, + .active_low = 1, + } +}; + +static struct gpio_button tl_wr1043nd_gpio_buttons[] __initdata = { + { + .desc = "reset", + .type = EV_KEY, + .code = BTN_0, + .threshold = 5, + .gpio = TL_WR1043ND_GPIO_BTN_RESET, + .active_low = 1, + }, { + .desc = "qss", + .type = EV_KEY, + .code = BTN_1, + .threshold = 5, + .gpio = TL_WR1043ND_GPIO_BTN_QSS, + .active_low = 1, + } +}; + +static void __init tl_wr1043nd_setup(void) +{ + u8 *mac = (u8 *) KSEG1ADDR(0x1f01fc00); + u8 *eeprom = (u8 *) KSEG1ADDR(0x1fff1000); + + ar71xx_set_mac_base(mac); + + ar71xx_add_device_mdio(0x0); + + ar71xx_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_RGMII; + ar71xx_eth0_data.phy_mask = 0x0; + ar71xx_eth0_data.speed = SPEED_1000; + ar71xx_eth0_data.duplex = DUPLEX_FULL; + + ar71xx_add_device_eth(0); + + ar71xx_add_device_usb(); + + ar71xx_add_device_m25p80(&tl_wr1043nd_flash_data); + + ar71xx_add_device_leds_gpio(-1, ARRAY_SIZE(tl_wr1043nd_leds_gpio), + tl_wr1043nd_leds_gpio); + + ar71xx_add_device_gpio_buttons(-1, TL_WR1043ND_BUTTONS_POLL_INTERVAL, + ARRAY_SIZE(tl_wr1043nd_gpio_buttons), + tl_wr1043nd_gpio_buttons); + ar913x_add_device_wmac(eeprom, NULL); +} + +MIPS_MACHINE(AR71XX_MACH_TL_WR1043ND, "TL-WR1043ND", "TP-LINK TL-WR1043ND", + tl_wr1043nd_setup); diff --git a/target/linux/ar71xx/files/arch/mips/ar71xx/mach-tl-wr741nd.c b/target/linux/ar71xx/files/arch/mips/ar71xx/mach-tl-wr741nd.c index 1d13ce94d..b2d33c0d7 100644 --- a/target/linux/ar71xx/files/arch/mips/ar71xx/mach-tl-wr741nd.c +++ b/target/linux/ar71xx/files/arch/mips/ar71xx/mach-tl-wr741nd.c @@ -8,21 +8,17 @@ * by the Free Software Foundation. */ -#include -#include #include #include -#include -#include -#include -#include - -#include #include -#include +#include "machtype.h" #include "devices.h" +#include "dev-m25p80.h" +#include "dev-ap91-pci.h" +#include "dev-gpio-buttons.h" +#include "dev-leds-gpio.h" #define TL_WR741ND_GPIO_LED_QSS 0 #define TL_WR741ND_GPIO_LED_SYSTEM 1 @@ -67,16 +63,6 @@ static struct flash_platform_data tl_wr741nd_flash_data = { #endif }; -static struct spi_board_info tl_wr741nd_spi_info[] = { - { - .bus_num = 0, - .chip_select = 0, - .max_speed_hz = 25000000, - .modalias = "m25p80", - .platform_data = &tl_wr741nd_flash_data, - } -}; - static struct gpio_led tl_wr741nd_leds_gpio[] __initdata = { { .name = "tl-wr741nd:green:system", @@ -107,41 +93,10 @@ static struct gpio_button tl_wr741nd_gpio_buttons[] __initdata = { } }; -#ifdef CONFIG_PCI -static struct ar71xx_pci_irq tl_wr741nd_pci_irqs[] __initdata = { - { - .slot = 0, - .pin = 1, - .irq = AR71XX_PCI_IRQ_DEV0, - } -}; - -static struct ath9k_platform_data tl_wr741nd_wmac_data; - -static int tl_wr741nd_pci_plat_dev_init(struct pci_dev *dev) -{ - dev->dev.platform_data = &tl_wr741nd_wmac_data; - return 0; -} - -static void tl_wr741nd_pci_init(void) -{ - u8 *ee = (u8 *) KSEG1ADDR(0x1fff1000); - - memcpy(tl_wr741nd_wmac_data.eeprom_data, ee, - sizeof(tl_wr741nd_wmac_data.eeprom_data)); - - ar71xx_pci_plat_dev_init = tl_wr741nd_pci_plat_dev_init; - - ar71xx_pci_init(ARRAY_SIZE(tl_wr741nd_pci_irqs), tl_wr741nd_pci_irqs); -} -#else -static inline void tl_wr741nd_pci_init(void) { }; -#endif /* CONFIG_PCI */ - static void __init tl_wr741nd_setup(void) { u8 *mac = (u8 *) KSEG1ADDR(0x1f01fc00); + u8 *ee = (u8 *) KSEG1ADDR(0x1fff1000); ar71xx_set_mac_base(mac); ar71xx_add_device_mdio(0x0); @@ -167,8 +122,7 @@ static void __init tl_wr741nd_setup(void) ar71xx_add_device_eth(1); ar71xx_add_device_eth(0); - ar71xx_add_device_spi(NULL, tl_wr741nd_spi_info, - ARRAY_SIZE(tl_wr741nd_spi_info)); + ar71xx_add_device_m25p80(&tl_wr741nd_flash_data); ar71xx_add_device_leds_gpio(-1, ARRAY_SIZE(tl_wr741nd_leds_gpio), tl_wr741nd_leds_gpio); @@ -177,6 +131,7 @@ static void __init tl_wr741nd_setup(void) ARRAY_SIZE(tl_wr741nd_gpio_buttons), tl_wr741nd_gpio_buttons); - tl_wr741nd_pci_init(); + ap91_pci_init(ee, NULL); } -MIPS_MACHINE(AR71XX_MACH_TL_WR741ND, "TP-LINK TL-WR741ND", tl_wr741nd_setup); +MIPS_MACHINE(AR71XX_MACH_TL_WR741ND, "TL-WR741ND", "TP-LINK TL-WR741ND", + tl_wr741nd_setup); diff --git a/target/linux/ar71xx/files/arch/mips/ar71xx/mach-tl-wr841n.c b/target/linux/ar71xx/files/arch/mips/ar71xx/mach-tl-wr841n.c new file mode 100644 index 000000000..3bc063ae5 --- /dev/null +++ b/target/linux/ar71xx/files/arch/mips/ar71xx/mach-tl-wr841n.c @@ -0,0 +1,144 @@ +/* + * TP-LINK TL-WR841N board support + * + * Copyright (C) 2009 Gabor Juhos + * + * 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 +#include + +#include + +#include "machtype.h" +#include "devices.h" +#include "dev-dsa.h" +#include "dev-m25p80.h" +#include "dev-gpio-buttons.h" +#include "dev-pb42-pci.h" +#include "dev-leds-gpio.h" + +#define TL_WR841ND_V1_GPIO_LED_SYSTEM 2 +#define TL_WR841ND_V1_GPIO_LED_QSS_GREEN 4 +#define TL_WR841ND_V1_GPIO_LED_QSS_RED 5 + +#define TL_WR841ND_V1_GPIO_BTN_RESET 3 +#define TL_WR841ND_V1_GPIO_BTN_QSS 7 + +#define TL_WR841ND_V1_BUTTONS_POLL_INTERVAL 20 + +#ifdef CONFIG_MTD_PARTITIONS +static struct mtd_partition tl_wr841n_v1_partitions[] = { + { + .name = "redboot", + .offset = 0, + .size = 0x020000, + .mask_flags = MTD_WRITEABLE, + } , { + .name = "kernel", + .offset = 0x020000, + .size = 0x140000, + } , { + .name = "rootfs", + .offset = 0x160000, + .size = 0x280000, + } , { + .name = "config", + .offset = 0x3e0000, + .size = 0x020000, + .mask_flags = MTD_WRITEABLE, + } , { + .name = "firmware", + .offset = 0x020000, + .size = 0x3c0000, + } +}; +#endif /* CONFIG_MTD_PARTITIONS */ + +static struct flash_platform_data tl_wr841n_v1_flash_data = { +#ifdef CONFIG_MTD_PARTITIONS + .parts = tl_wr841n_v1_partitions, + .nr_parts = ARRAY_SIZE(tl_wr841n_v1_partitions), +#endif +}; + +static struct gpio_led tl_wr841n_v1_leds_gpio[] __initdata = { + { + .name = "tl-wr841n:green:system", + .gpio = TL_WR841ND_V1_GPIO_LED_SYSTEM, + .active_low = 1, + }, { + .name = "tl-wr841n:red:qss", + .gpio = TL_WR841ND_V1_GPIO_LED_QSS_RED, + }, { + .name = "tl-wr841n:green:qss", + .gpio = TL_WR841ND_V1_GPIO_LED_QSS_GREEN, + } +}; + +static struct gpio_button tl_wr841n_v1_gpio_buttons[] __initdata = { + { + .desc = "reset", + .type = EV_KEY, + .code = BTN_0, + .threshold = 5, + .gpio = TL_WR841ND_V1_GPIO_BTN_RESET, + .active_low = 1, + }, { + .desc = "qss", + .type = EV_KEY, + .code = BTN_1, + .threshold = 5, + .gpio = TL_WR841ND_V1_GPIO_BTN_QSS, + .active_low = 1, + } +}; + +static struct dsa_chip_data tl_wr841n_v1_dsa_chip = { + .port_names[0] = "wan", + .port_names[1] = "lan1", + .port_names[2] = "lan2", + .port_names[3] = "lan3", + .port_names[4] = "lan4", + .port_names[5] = "cpu", +}; + +static struct dsa_platform_data tl_wr841n_v1_dsa_data = { + .nr_chips = 1, + .chip = &tl_wr841n_v1_dsa_chip, +}; + +static void __init tl_wr841n_v1_setup(void) +{ + u8 *mac = (u8 *) KSEG1ADDR(0x1f01fc00); + + ar71xx_set_mac_base(mac); + + ar71xx_add_device_mdio(0x0); + + ar71xx_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_RMII; + ar71xx_eth0_data.phy_mask = 0x0; + ar71xx_eth0_data.speed = SPEED_100; + ar71xx_eth0_data.duplex = DUPLEX_FULL; + + ar71xx_add_device_eth(0); + + ar71xx_add_device_dsa(0, &tl_wr841n_v1_dsa_data); + + ar71xx_add_device_m25p80(&tl_wr841n_v1_flash_data); + + ar71xx_add_device_leds_gpio(-1, ARRAY_SIZE(tl_wr841n_v1_leds_gpio), + tl_wr841n_v1_leds_gpio); + + ar71xx_add_device_gpio_buttons(-1, TL_WR841ND_V1_BUTTONS_POLL_INTERVAL, + ARRAY_SIZE(tl_wr841n_v1_gpio_buttons), + tl_wr841n_v1_gpio_buttons); + + pb42_pci_init(); +} + +MIPS_MACHINE(AR71XX_MACH_TL_WR841N_V1, "TL-WR841N-v1.5", "TP-LINK TL-WR841N v1", + tl_wr841n_v1_setup); diff --git a/target/linux/ar71xx/files/arch/mips/ar71xx/mach-tl-wr941nd.c b/target/linux/ar71xx/files/arch/mips/ar71xx/mach-tl-wr941nd.c index eb1a1b0da..0f4277ea0 100644 --- a/target/linux/ar71xx/files/arch/mips/ar71xx/mach-tl-wr941nd.c +++ b/target/linux/ar71xx/files/arch/mips/ar71xx/mach-tl-wr941nd.c @@ -1,28 +1,29 @@ /* * TP-LINK TL-WR941ND board support * - * Copyright (C) 2009 Gabor Juhos + * Copyright (C) 2009-2010 Gabor Juhos * * 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 #include #include -#include -#include -#include - -#include #include +#include "machtype.h" #include "devices.h" +#include "dev-dsa.h" +#include "dev-m25p80.h" +#include "dev-ar913x-wmac.h" +#include "dev-gpio-buttons.h" +#include "dev-leds-gpio.h" #define TL_WR941ND_GPIO_LED_SYSTEM 2 -#define TL_WR941ND_GPIO_LED_QSS 5 +#define TL_WR941ND_GPIO_LED_QSS_RED 4 +#define TL_WR941ND_GPIO_LED_QSS_GREEN 5 #define TL_WR941ND_GPIO_BTN_RESET 3 #define TL_WR941ND_GPIO_BTN_QSS 7 @@ -64,16 +65,6 @@ static struct flash_platform_data tl_wr941nd_flash_data = { #endif }; -static struct spi_board_info tl_wr941nd_spi_info[] = { - { - .bus_num = 0, - .chip_select = 0, - .max_speed_hz = 25000000, - .modalias = "m25p80", - .platform_data = &tl_wr941nd_flash_data, - } -}; - static struct gpio_led tl_wr941nd_leds_gpio[] __initdata = { { .name = "tl-wr941nd:green:system", @@ -81,8 +72,10 @@ static struct gpio_led tl_wr941nd_leds_gpio[] __initdata = { .active_low = 1, }, { .name = "tl-wr941nd:red:qss", - .gpio = TL_WR941ND_GPIO_LED_QSS, - .active_low = 1, + .gpio = TL_WR941ND_GPIO_LED_QSS_RED, + }, { + .name = "tl-wr941nd:green:qss", + .gpio = TL_WR941ND_GPIO_LED_QSS_GREEN, } }; @@ -104,7 +97,7 @@ static struct gpio_button tl_wr941nd_gpio_buttons[] __initdata = { } }; -static struct dsa_platform_data tl_wr941nd_dsa_data = { +static struct dsa_chip_data tl_wr941nd_dsa_chip = { .port_names[0] = "wan", .port_names[1] = "lan1", .port_names[2] = "lan2", @@ -113,9 +106,15 @@ static struct dsa_platform_data tl_wr941nd_dsa_data = { .port_names[5] = "cpu", }; +static struct dsa_platform_data tl_wr941nd_dsa_data = { + .nr_chips = 1, + .chip = &tl_wr941nd_dsa_chip, +}; + static void __init tl_wr941nd_setup(void) { u8 *mac = (u8 *) KSEG1ADDR(0x1f01fc00); + u8 *eeprom = (u8 *) KSEG1ADDR(0x1fff1000); ar71xx_set_mac_base(mac); @@ -129,8 +128,7 @@ static void __init tl_wr941nd_setup(void) ar71xx_add_device_eth(0); ar71xx_add_device_dsa(0, &tl_wr941nd_dsa_data); - ar71xx_add_device_spi(NULL, tl_wr941nd_spi_info, - ARRAY_SIZE(tl_wr941nd_spi_info)); + ar71xx_add_device_m25p80(&tl_wr941nd_flash_data); ar71xx_add_device_leds_gpio(-1, ARRAY_SIZE(tl_wr941nd_leds_gpio), tl_wr941nd_leds_gpio); @@ -138,7 +136,8 @@ static void __init tl_wr941nd_setup(void) ar71xx_add_device_gpio_buttons(-1, TL_WR941ND_BUTTONS_POLL_INTERVAL, ARRAY_SIZE(tl_wr941nd_gpio_buttons), tl_wr941nd_gpio_buttons); - ar91xx_add_device_wmac(); + ar913x_add_device_wmac(eeprom, mac); } -MIPS_MACHINE(AR71XX_MACH_TL_WR941ND, "TP-LINK TL-WR941ND", tl_wr941nd_setup); +MIPS_MACHINE(AR71XX_MACH_TL_WR941ND, "TL-WR941ND", "TP-LINK TL-WR941ND", + tl_wr941nd_setup); diff --git a/target/linux/ar71xx/files/arch/mips/ar71xx/mach-ubnt.c b/target/linux/ar71xx/files/arch/mips/ar71xx/mach-ubnt.c index 371ac0fc3..37151ab02 100644 --- a/target/linux/ar71xx/files/arch/mips/ar71xx/mach-ubnt.c +++ b/target/linux/ar71xx/files/arch/mips/ar71xx/mach-ubnt.c @@ -10,18 +10,16 @@ * by the Free Software Foundation. */ -#include -#include -#include -#include -#include -#include - -#include #include -#include +#include "machtype.h" #include "devices.h" +#include "dev-m25p80.h" +#include "dev-ap91-pci.h" +#include "dev-gpio-buttons.h" +#include "dev-pb42-pci.h" +#include "dev-leds-gpio.h" +#include "dev-usb.h" #define UBNT_RS_GPIO_LED_RF 2 #define UBNT_RS_GPIO_SW4 8 @@ -42,31 +40,6 @@ #define UBNT_BUTTONS_POLL_INTERVAL 20 -static struct spi_board_info ubnt_spi_info[] = { - { - .bus_num = 0, - .chip_select = 0, - .max_speed_hz = 25000000, - .modalias = "m25p80", - } -}; - -static struct ar71xx_pci_irq ubnt_pci_irqs[] __initdata = { - { - .slot = 0, - .pin = 1, - .irq = AR71XX_PCI_IRQ_DEV0, - }, { - .slot = 1, - .pin = 1, - .irq = AR71XX_PCI_IRQ_DEV1, - }, { - .slot = 2, - .pin = 1, - .irq = AR71XX_PCI_IRQ_DEV2, - } -}; - static struct gpio_led ubnt_rs_leds_gpio[] __initdata = { { .name = "ubnt:green:rf", @@ -151,14 +124,13 @@ static struct gpio_button ubnt_m_gpio_buttons[] __initdata = { static void __init ubnt_generic_setup(void) { - ar71xx_add_device_spi(NULL, ubnt_spi_info, - ARRAY_SIZE(ubnt_spi_info)); + ar71xx_add_device_m25p80(NULL); ar71xx_add_device_gpio_buttons(-1, UBNT_BUTTONS_POLL_INTERVAL, ARRAY_SIZE(ubnt_gpio_buttons), ubnt_gpio_buttons); - ar71xx_pci_init(ARRAY_SIZE(ubnt_pci_irqs), ubnt_pci_irqs); + pb42_pci_init(); } #define UBNT_RS_WAN_PHYMASK (1 << 20) @@ -191,7 +163,11 @@ static void __init ubnt_rs_setup(void) ubnt_rs_leds_gpio); } -MIPS_MACHINE(AR71XX_MACH_UBNT_RS, "Ubiquiti RouterStation", ubnt_rs_setup); +MIPS_MACHINE(AR71XX_MACH_UBNT_RS, "UBNT-RS", "Ubiquiti RouterStation", + ubnt_rs_setup); + +MIPS_MACHINE(AR71XX_MACH_UBNT_AR71XX, "Ubiquiti AR71xx-based board", + "Ubiquiti RouterStation", ubnt_rs_setup); static void __init ubnt_rspro_setup(void) { @@ -217,7 +193,7 @@ static void __init ubnt_rspro_setup(void) ubnt_rs_leds_gpio); } -MIPS_MACHINE(AR71XX_MACH_UBNT_RSPRO, "Ubiquiti RouterStation Pro", +MIPS_MACHINE(AR71XX_MACH_UBNT_RSPRO, "UBNT-RSPRO", "Ubiquiti RouterStation Pro", ubnt_rspro_setup); static void __init ubnt_lsx_setup(void) @@ -225,7 +201,7 @@ static void __init ubnt_lsx_setup(void) ubnt_generic_setup(); } -MIPS_MACHINE(AR71XX_MACH_UBNT_LSX, "Ubiquiti LSX", ubnt_lsx_setup); +MIPS_MACHINE(AR71XX_MACH_UBNT_LSX, "UBNT-LSX", "Ubiquiti LSX", ubnt_lsx_setup); #define UBNT_LSSR71_PHY_MASK (1 << 1) @@ -244,49 +220,17 @@ static void __init ubnt_lssr71_setup(void) ubnt_ls_sr71_leds_gpio); } -MIPS_MACHINE(AR71XX_MACH_UBNT_LSSR71, "Ubiquiti LS-SR71", ubnt_lssr71_setup); - -#ifdef CONFIG_PCI -static struct ar71xx_pci_irq ubnt_m_pci_irqs[] __initdata = { - { - .slot = 0, - .pin = 1, - .irq = AR71XX_PCI_IRQ_DEV0, - } -}; - -static struct ath9k_platform_data ubnt_m_wmac_data; - -static int ubmnt_m_pci_plat_dev_init(struct pci_dev *dev) -{ - dev->dev.platform_data = &ubnt_m_wmac_data; - return 0; -} - -static void __init ubnt_m_pci_init(void) -{ - u8 *ee = (u8 *) KSEG1ADDR(0x1fff1000); - - memcpy(ubnt_m_wmac_data.eeprom_data, ee, - sizeof(ubnt_m_wmac_data.eeprom_data)); - - ar71xx_pci_plat_dev_init = ubmnt_m_pci_plat_dev_init; - - ar71xx_pci_init(ARRAY_SIZE(ubnt_m_pci_irqs), - ubnt_m_pci_irqs); -} -#else -static inline void ubnt_m_pci_init(void) { }; -#endif /* CONFIG_PCI */ +MIPS_MACHINE(AR71XX_MACH_UBNT_LSSR71, "UBNT-LS-SR71", "Ubiquiti LS-SR71", + ubnt_lssr71_setup); static void __init ubnt_m_setup(void) { u8 *mac = (u8 *) KSEG1ADDR(0x1fff0000); + u8 *ee = (u8 *) KSEG1ADDR(0x1fff1000); ar71xx_set_mac_base(mac); - ar71xx_add_device_spi(NULL, ubnt_spi_info, - ARRAY_SIZE(ubnt_spi_info)); + ar71xx_add_device_m25p80(NULL); ar71xx_add_device_mdio(~0); @@ -300,7 +244,7 @@ static void __init ubnt_m_setup(void) ar71xx_add_device_eth(0); - ubnt_m_pci_init(); + ap91_pci_init(ee, NULL); ar71xx_add_device_leds_gpio(-1, ARRAY_SIZE(ubnt_m_leds_gpio), ubnt_m_leds_gpio); @@ -316,8 +260,10 @@ static void __init ubnt_rocket_m_setup(void) ar71xx_add_device_usb(); } -MIPS_MACHINE(AR71XX_MACH_UBNT_BULLET_M, "Ubiquiti Bullet M", ubnt_m_setup); -MIPS_MACHINE(AR71XX_MACH_UBNT_ROCKET_M, "Ubiquiti Rocket M", ubnt_rocket_m_setup); +MIPS_MACHINE(AR71XX_MACH_UBNT_BULLET_M, "UBNT-BM", "Ubiquiti Bullet M", + ubnt_m_setup); +MIPS_MACHINE(AR71XX_MACH_UBNT_ROCKET_M, "UBNT-RM", "Ubiquiti Rocket M", + ubnt_rocket_m_setup); /* TODO detect the second ethernet port and use one init function for all Ubiquiti MIMO series products */ @@ -336,4 +282,5 @@ static void __init ubnt_nano_m_setup(void) ar71xx_add_device_eth(1); } -MIPS_MACHINE(AR71XX_MACH_UBNT_NANO_M, "Ubiquiti Nanostation M", ubnt_nano_m_setup); +MIPS_MACHINE(AR71XX_MACH_UBNT_NANO_M, "UBNT-NM", "Ubiquiti Nanostation M", + ubnt_nano_m_setup); diff --git a/target/linux/ar71xx/files/arch/mips/ar71xx/mach-wndr3700.c b/target/linux/ar71xx/files/arch/mips/ar71xx/mach-wndr3700.c index 5f95270ad..14cde55d2 100644 --- a/target/linux/ar71xx/files/arch/mips/ar71xx/mach-wndr3700.c +++ b/target/linux/ar71xx/files/arch/mips/ar71xx/mach-wndr3700.c @@ -12,18 +12,18 @@ #include #include #include -#include -#include -#include -#include -#include #include +#include -#include #include -#include +#include "machtype.h" #include "devices.h" +#include "dev-m25p80.h" +#include "dev-ap94-pci.h" +#include "dev-gpio-buttons.h" +#include "dev-leds-gpio.h" +#include "dev-usb.h" #define WNDR3700_GPIO_LED_WPS_ORANGE 0 #define WNDR3700_GPIO_LED_POWER_ORANGE 1 @@ -34,8 +34,16 @@ #define WNDR3700_GPIO_BTN_RESET 8 #define WNDR3700_GPIO_BTN_WIFI 11 +#define WNDR3700_GPIO_RTL8366_SDA 5 +#define WNDR3700_GPIO_RTL8366_SCK 7 + #define WNDR3700_BUTTONS_POLL_INTERVAL 20 +#define WNDR3700_WMAC0_MAC_OFFSET 0 +#define WNDR3700_WMAC1_MAC_OFFSET 0xc +#define WNDR3700_CALDATA0_OFFSET 0x1000 +#define WNDR3700_CALDATA1_OFFSET 0x5000 + #ifdef CONFIG_MTD_PARTITIONS static struct mtd_partition wndr3700_partitions[] = { { @@ -93,145 +101,6 @@ static struct flash_platform_data wndr3700_flash_data = { #endif }; -#ifdef CONFIG_PCI -static struct ar71xx_pci_irq wndr3700_pci_irqs[] __initdata = { - { - .slot = 0, - .pin = 1, - .irq = AR71XX_PCI_IRQ_DEV0, - }, { - .slot = 1, - .pin = 1, - .irq = AR71XX_PCI_IRQ_DEV1, - } -}; - -static struct ath9k_platform_data wndr3700_wmac0_data; -static u8 wndr3700_wmac0_macaddr[6]; -static struct ath9k_platform_data wndr3700_wmac1_data; -static u8 wndr3700_wmac1_macaddr[6]; - -static void wndr3700_pci_fixup(struct pci_dev *dev) -{ - void __iomem *mem; - u16 *cal_data; - u16 cmd; - u32 bar0; - u32 val; - - if (ar71xx_mach != AR71XX_MACH_WNDR3700) - return; - - switch (PCI_SLOT(dev->devfn)) { - case 17: - cal_data = wndr3700_wmac0_data.eeprom_data; - break; - case 18: - cal_data = wndr3700_wmac1_data.eeprom_data; - break; - default: - return; - } - - if (*cal_data != 0xa55a) { - printk(KERN_ERR "PCI: no calibration data found for %s\n", - pci_name(dev)); - return; - } - - mem = ioremap(AR71XX_PCI_MEM_BASE, 0x10000); - if (!mem) { - printk(KERN_ERR "PCI: ioremap error for device %s\n", - pci_name(dev)); - return; - } - - printk(KERN_INFO "PCI: fixup device %s\n", pci_name(dev)); - - pci_read_config_dword(dev, PCI_BASE_ADDRESS_0, &bar0); - - /* Setup the PCI device to allow access to the internal registers */ - pci_write_config_dword(dev, PCI_BASE_ADDRESS_0, AR71XX_PCI_MEM_BASE); - pci_read_config_word(dev, PCI_COMMAND, &cmd); - cmd |= PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY; - pci_write_config_word(dev, PCI_COMMAND, cmd); - - /* set pointer to first reg address */ - cal_data += 3; - while (*cal_data != 0xffff) { - u32 reg; - reg = *cal_data++; - val = *cal_data++; - val |= (*cal_data++) << 16; - - __raw_writel(val, mem + reg); - udelay(100); - } - - pci_read_config_dword(dev, PCI_VENDOR_ID, &val); - dev->vendor = val & 0xffff; - dev->device = (val >> 16) & 0xffff; - - pci_read_config_dword(dev, PCI_CLASS_REVISION, &val); - dev->revision = val & 0xff; - dev->class = val >> 8; /* upper 3 bytes */ - - pci_read_config_word(dev, PCI_COMMAND, &cmd); - cmd &= ~(PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY); - pci_write_config_word(dev, PCI_COMMAND, cmd); - - pci_write_config_dword(dev, PCI_BASE_ADDRESS_0, bar0); - - iounmap(mem); -} -DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_ATHEROS, PCI_ANY_ID, - wndr3700_pci_fixup); - -static int wndr3700_pci_plat_dev_init(struct pci_dev *dev) -{ - switch (PCI_SLOT(dev->devfn)) { - case 17: - dev->dev.platform_data = &wndr3700_wmac0_data; - break; - case 18: - dev->dev.platform_data = &wndr3700_wmac1_data; - break; - } - - return 0; -} - -static void __init wndr3700_pci_init(void) -{ - u8 *ee = (u8 *) KSEG1ADDR(0x1fff0000); - - memcpy(wndr3700_wmac0_data.eeprom_data, ee + 0x1000, - sizeof(wndr3700_wmac0_data.eeprom_data)); - memcpy(wndr3700_wmac0_macaddr, ee, sizeof(wndr3700_wmac0_macaddr)); - wndr3700_wmac0_data.macaddr = wndr3700_wmac0_macaddr; - - memcpy(wndr3700_wmac1_data.eeprom_data, ee + 0x5000, - sizeof(wndr3700_wmac1_data.eeprom_data)); - memcpy(wndr3700_wmac1_macaddr, ee + 12, sizeof(wndr3700_wmac1_macaddr)); - wndr3700_wmac1_data.macaddr = wndr3700_wmac1_macaddr; - - ar71xx_pci_plat_dev_init = wndr3700_pci_plat_dev_init; - ar71xx_pci_init(ARRAY_SIZE(wndr3700_pci_irqs), wndr3700_pci_irqs); -} -#else -static inline void wndr3700_pci_init(void) { }; -#endif /* CONFIG_PCI */ - -static struct spi_board_info wndr3700_spi_info[] = { - { - .bus_num = 0, - .chip_select = 0, - .max_speed_hz = 25000000, - .modalias = "m25p80", - .platform_data = &wndr3700_flash_data, - } -}; - static struct gpio_led wndr3700_leds_gpio[] __initdata = { { .name = "wndr3700:green:power", @@ -274,20 +143,34 @@ static struct gpio_button wndr3700_gpio_buttons[] __initdata = { } }; +static struct rtl8366_smi_platform_data wndr3700_rtl8366_smi_data = { + .gpio_sda = WNDR3700_GPIO_RTL8366_SDA, + .gpio_sck = WNDR3700_GPIO_RTL8366_SCK, +}; + +static struct platform_device wndr3700_rtl8366_smi_device = { + .name = "rtl8366-smi", + .id = -1, + .dev = { + .platform_data = &wndr3700_rtl8366_smi_data, + } +}; + static void __init wndr3700_setup(void) { - u8 *mac = (u8 *) KSEG1ADDR(0x1fff0000); + u8 *art = (u8 *) KSEG1ADDR(0x1fff0000); - ar71xx_set_mac_base(mac); - ar71xx_add_device_mdio(0x0); + ar71xx_set_mac_base(art); ar71xx_eth0_pll_data.pll_1000 = 0x11110000; + ar71xx_eth0_data.mii_bus_dev = &wndr3700_rtl8366_smi_device.dev; ar71xx_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_RGMII; ar71xx_eth0_data.phy_mask = 0xf; ar71xx_eth0_data.speed = SPEED_1000; ar71xx_eth0_data.duplex = DUPLEX_FULL; ar71xx_eth1_pll_data.pll_1000 = 0x11110000; + ar71xx_eth1_data.mii_bus_dev = &wndr3700_rtl8366_smi_device.dev; ar71xx_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_RGMII; ar71xx_eth1_data.phy_mask = 0x10; @@ -296,8 +179,7 @@ static void __init wndr3700_setup(void) ar71xx_add_device_usb(); - ar71xx_add_device_spi(NULL, wndr3700_spi_info, - ARRAY_SIZE(wndr3700_spi_info)); + ar71xx_add_device_m25p80(&wndr3700_flash_data); ar71xx_add_device_leds_gpio(-1, ARRAY_SIZE(wndr3700_leds_gpio), wndr3700_leds_gpio); @@ -306,7 +188,14 @@ static void __init wndr3700_setup(void) ARRAY_SIZE(wndr3700_gpio_buttons), wndr3700_gpio_buttons); - wndr3700_pci_init(); + platform_device_register(&wndr3700_rtl8366_smi_device); + platform_device_register_simple("wndr3700-led-usb", -1, NULL, 0); + + ap94_pci_init(art + WNDR3700_CALDATA0_OFFSET, + art + WNDR3700_WMAC0_MAC_OFFSET, + art + WNDR3700_CALDATA1_OFFSET, + art + WNDR3700_WMAC1_MAC_OFFSET); } -MIPS_MACHINE(AR71XX_MACH_WNDR3700, "NETGEAR WNDR3700", wndr3700_setup); +MIPS_MACHINE(AR71XX_MACH_WNDR3700, "WNDR3700", "NETGEAR WNDR3700", + wndr3700_setup); diff --git a/target/linux/ar71xx/files/arch/mips/ar71xx/mach-wnr2000.c b/target/linux/ar71xx/files/arch/mips/ar71xx/mach-wnr2000.c index d766fef71..778e99d71 100644 --- a/target/linux/ar71xx/files/arch/mips/ar71xx/mach-wnr2000.c +++ b/target/linux/ar71xx/files/arch/mips/ar71xx/mach-wnr2000.c @@ -10,18 +10,17 @@ * by the Free Software Foundation. */ -#include #include #include -#include -#include -#include - -#include #include +#include "machtype.h" #include "devices.h" +#include "dev-m25p80.h" +#include "dev-ar913x-wmac.h" +#include "dev-gpio-buttons.h" +#include "dev-leds-gpio.h" #define WNR2000_GPIO_LED_PWR_GREEN 14 #define WNR2000_GPIO_LED_PWR_AMBER 7 @@ -79,16 +78,6 @@ static struct flash_platform_data wnr2000_flash_data = { #endif }; -static struct spi_board_info wnr2000_spi_info[] = { - { - .bus_num = 0, - .chip_select = 0, - .max_speed_hz = 25000000, - .modalias = "m25p80", - .platform_data = &wnr2000_flash_data, - } -}; - static struct gpio_led wnr2000_leds_gpio[] __initdata = { { .name = "wnr2000:green:power", @@ -127,9 +116,9 @@ static struct gpio_button wnr2000_gpio_buttons[] __initdata = { static void __init wnr2000_setup(void) { - u8 *mac = (u8 *) KSEG1ADDR(0x1fff1000); + u8 *eeprom = (u8 *) KSEG1ADDR(0x1fff1000); - ar71xx_set_mac_base(mac); + ar71xx_set_mac_base(eeprom); ar71xx_add_device_mdio(0x0); ar71xx_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_RMII; @@ -144,8 +133,7 @@ static void __init wnr2000_setup(void) ar71xx_add_device_eth(0); ar71xx_add_device_eth(1); - ar71xx_add_device_spi(NULL, wnr2000_spi_info, - ARRAY_SIZE(wnr2000_spi_info)); + ar71xx_add_device_m25p80(&wnr2000_flash_data); ar71xx_add_device_leds_gpio(-1, ARRAY_SIZE(wnr2000_leds_gpio), wnr2000_leds_gpio); @@ -155,7 +143,7 @@ static void __init wnr2000_setup(void) wnr2000_gpio_buttons); - ar91xx_add_device_wmac(); + ar913x_add_device_wmac(eeprom, NULL); } -MIPS_MACHINE(AR71XX_MACH_WNR2000, "NETGEAR WNR2000", wnr2000_setup); +MIPS_MACHINE(AR71XX_MACH_WNR2000, "WNR2000", "NETGEAR WNR2000", wnr2000_setup); diff --git a/target/linux/ar71xx/files/arch/mips/ar71xx/mach-wp543.c b/target/linux/ar71xx/files/arch/mips/ar71xx/mach-wp543.c index 9f1111dae..a2669f17a 100644 --- a/target/linux/ar71xx/files/arch/mips/ar71xx/mach-wp543.c +++ b/target/linux/ar71xx/files/arch/mips/ar71xx/mach-wp543.c @@ -9,18 +9,18 @@ * by the Free Software Foundation. */ -#include #include #include -#include -#include -#include -#include #include -#include +#include "machtype.h" #include "devices.h" +#include "dev-m25p80.h" +#include "dev-pb42-pci.h" +#include "dev-gpio-buttons.h" +#include "dev-leds-gpio.h" +#include "dev-usb.h" #define WP543_GPIO_SW6 2 #define WP543_GPIO_LED_1 3 @@ -32,31 +32,6 @@ #define WP543_BUTTONS_POLL_INTERVAL 20 -static struct spi_board_info wp543_spi_info[] = { - { - .bus_num = 0, - .chip_select = 0, - .max_speed_hz = 25000000, - .modalias = "m25p80", - } -}; - -static struct ar71xx_pci_irq wp543_pci_irqs[] __initdata = { - { - .slot = 0, - .pin = 1, - .irq = AR71XX_PCI_IRQ_DEV0, - }, { - .slot = 1, - .pin = 1, - .irq = AR71XX_PCI_IRQ_DEV1, - }, { - .slot = 2, - .pin = 1, - .irq = AR71XX_PCI_IRQ_DEV2, - } -}; - static struct gpio_led wp543_leds_gpio[] __initdata = { { .name = "wp543:green:led1", @@ -99,7 +74,7 @@ static struct gpio_button wp543_gpio_buttons[] __initdata = { static void __init wp543_setup(void) { - ar71xx_add_device_spi(NULL, wp543_spi_info, ARRAY_SIZE(wp543_spi_info)); + ar71xx_add_device_m25p80(NULL); ar71xx_add_device_mdio(0xfffffff7); @@ -111,7 +86,7 @@ static void __init wp543_setup(void) ar71xx_add_device_usb(); - ar71xx_pci_init(ARRAY_SIZE(wp543_pci_irqs), wp543_pci_irqs); + pb42_pci_init(); ar71xx_add_device_leds_gpio(-1, ARRAY_SIZE(wp543_leds_gpio), wp543_leds_gpio); @@ -121,4 +96,4 @@ static void __init wp543_setup(void) wp543_gpio_buttons); } -MIPS_MACHINE(AR71XX_MACH_WP543, "Compex WP543", wp543_setup); +MIPS_MACHINE(AR71XX_MACH_WP543, "WP543", "Compex WP543", wp543_setup); diff --git a/target/linux/ar71xx/files/arch/mips/ar71xx/mach-wrt160nl.c b/target/linux/ar71xx/files/arch/mips/ar71xx/mach-wrt160nl.c index 0a73be112..9c85235ea 100644 --- a/target/linux/ar71xx/files/arch/mips/ar71xx/mach-wrt160nl.c +++ b/target/linux/ar71xx/files/arch/mips/ar71xx/mach-wrt160nl.c @@ -8,17 +8,19 @@ * by the Free Software Foundation. */ -#include #include #include -#include -#include -#include -#include #include +#include "machtype.h" #include "devices.h" +#include "dev-m25p80.h" +#include "dev-ar913x-wmac.h" +#include "dev-gpio-buttons.h" +#include "dev-leds-gpio.h" +#include "dev-usb.h" +#include "nvram.h" #define WRT160NL_GPIO_LED_POWER 14 #define WRT160NL_GPIO_LED_WPS_AMBER 9 @@ -30,6 +32,9 @@ #define WRT160NL_BUTTONS_POLL_INTERVAL 20 +#define WRT160NL_NVRAM_ADDR 0x1f7e0000 +#define WRT160NL_NVRAM_SIZE 0x10000 + #ifdef CONFIG_MTD_PARTITIONS static struct mtd_partition wrt160nl_partitions[] = { { @@ -70,16 +75,6 @@ static struct flash_platform_data wrt160nl_flash_data = { #endif }; -static struct spi_board_info wrt160nl_spi_info[] = { - { - .bus_num = 0, - .chip_select = 0, - .max_speed_hz = 25000000, - .modalias = "m25p80", - .platform_data = &wrt160nl_flash_data, - } -}; - static struct gpio_led wrt160nl_leds_gpio[] __initdata = { { .name = "wrt160nl:blue:power", @@ -121,12 +116,18 @@ static struct gpio_button wrt160nl_gpio_buttons[] __initdata = { static void __init wrt160nl_setup(void) { + const char *nvram = (char *) KSEG1ADDR(WRT160NL_NVRAM_ADDR); + u8 *eeprom = (u8 *) KSEG1ADDR(0x1fff1000); + u8 mac[6]; + + if (nvram_parse_mac_addr(nvram, WRT160NL_NVRAM_SIZE, + "lan_hwaddr=", mac) == 0) + ar71xx_set_mac_base(mac); + ar71xx_add_device_mdio(0x0); ar71xx_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_RMII; - ar71xx_eth0_data.phy_mask = 0xf; - ar71xx_eth0_data.speed = SPEED_100; - ar71xx_eth0_data.duplex = DUPLEX_FULL; + ar71xx_eth0_data.phy_mask = 0x01; ar71xx_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_RMII; ar71xx_eth1_data.phy_mask = 0x10; @@ -134,11 +135,15 @@ static void __init wrt160nl_setup(void) ar71xx_add_device_eth(0); ar71xx_add_device_eth(1); - ar71xx_add_device_spi(NULL, wrt160nl_spi_info, - ARRAY_SIZE(wrt160nl_spi_info)); + ar71xx_add_device_m25p80(&wrt160nl_flash_data); ar71xx_add_device_usb(); - ar91xx_add_device_wmac(); + + if (nvram_parse_mac_addr(nvram, WRT160NL_NVRAM_SIZE, + "wl0_hwaddr=", mac) == 0) + ar913x_add_device_wmac(eeprom, mac); + else + ar913x_add_device_wmac(eeprom, NULL); ar71xx_add_device_leds_gpio(-1, ARRAY_SIZE(wrt160nl_leds_gpio), wrt160nl_leds_gpio); @@ -146,6 +151,8 @@ static void __init wrt160nl_setup(void) ar71xx_add_device_gpio_buttons(-1, WRT160NL_BUTTONS_POLL_INTERVAL, ARRAY_SIZE(wrt160nl_gpio_buttons), wrt160nl_gpio_buttons); + } -MIPS_MACHINE(AR71XX_MACH_WRT160NL, "Linksys WRT160NL", wrt160nl_setup); +MIPS_MACHINE(AR71XX_MACH_WRT160NL, "WRT160NL", "Linksys WRT160NL", + wrt160nl_setup); diff --git a/target/linux/ar71xx/files/arch/mips/ar71xx/mach-wrt400n.c b/target/linux/ar71xx/files/arch/mips/ar71xx/mach-wrt400n.c index 0298b1a6b..465b6c612 100644 --- a/target/linux/ar71xx/files/arch/mips/ar71xx/mach-wrt400n.c +++ b/target/linux/ar71xx/files/arch/mips/ar71xx/mach-wrt400n.c @@ -1,7 +1,7 @@ /* * Linksys WRT400N board support * - * Copyright (C) 2009 Gabor Juhos + * Copyright (C) 2009-2010 Gabor Juhos * Copyright (C) 2009 Imre Kaloz * * This program is free software; you can redistribute it and/or modify it @@ -9,17 +9,17 @@ * by the Free Software Foundation. */ -#include #include #include -#include -#include -#include -#include #include +#include "machtype.h" #include "devices.h" +#include "dev-ap94-pci.h" +#include "dev-m25p80.h" +#include "dev-gpio-buttons.h" +#include "dev-leds-gpio.h" #define WRT400N_GPIO_LED_ORANGE 5 #define WRT400N_GPIO_LED_GREEN 4 @@ -31,6 +31,10 @@ #define WRT400N_BUTTONS_POLL_INTERVAL 20 +#define WRT400N_MAC_ADDR_OFFSET 0x120c +#define WRT400N_CALDATA0_OFFSET 0x1000 +#define WRT400N_CALDATA1_OFFSET 0x5000 + #ifdef CONFIG_MTD_PARTITIONS static struct mtd_partition wrt400n_partitions[] = { { @@ -86,16 +90,6 @@ static struct flash_platform_data wrt400n_flash_data = { #endif }; -static struct spi_board_info wrt400n_spi_info[] = { - { - .bus_num = 0, - .chip_select = 0, - .max_speed_hz = 25000000, - .modalias = "m25p80", - .platform_data = &wrt400n_flash_data, - } -}; - static struct gpio_led wrt400n_leds_gpio[] __initdata = { { .name = "wrt400n:green:status", @@ -136,6 +130,16 @@ static struct gpio_button wrt400n_gpio_buttons[] __initdata = { static void __init wrt400n_setup(void) { + u8 *art = (u8 *) KSEG1ADDR(0x1fff0000); + u8 mac[6]; + int i; + + memcpy(mac, art + WRT400N_MAC_ADDR_OFFSET, 6); + for (i = 5; i >= 3; i--) + if (++mac[i] != 0x00) break; + + ar71xx_set_mac_base(mac); + ar71xx_add_device_mdio(0x0); ar71xx_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_RMII; @@ -150,8 +154,7 @@ static void __init wrt400n_setup(void) ar71xx_add_device_eth(0); ar71xx_add_device_eth(1); - ar71xx_add_device_spi(NULL, wrt400n_spi_info, - ARRAY_SIZE(wrt400n_spi_info)); + ar71xx_add_device_m25p80(&wrt400n_flash_data); ar71xx_add_device_leds_gpio(-1, ARRAY_SIZE(wrt400n_leds_gpio), wrt400n_leds_gpio); @@ -160,7 +163,8 @@ static void __init wrt400n_setup(void) ARRAY_SIZE(wrt400n_gpio_buttons), wrt400n_gpio_buttons); - /* TODO: PCI support */ + ap94_pci_init(art + WRT400N_CALDATA0_OFFSET, NULL, + art + WRT400N_CALDATA1_OFFSET, NULL); } -MIPS_MACHINE(AR71XX_MACH_WRT400N, "Linksys WRT400N", wrt400n_setup); +MIPS_MACHINE(AR71XX_MACH_WRT400N, "WRT400N", "Linksys WRT400N", wrt400n_setup); diff --git a/target/linux/ar71xx/files/arch/mips/ar71xx/machtype.h b/target/linux/ar71xx/files/arch/mips/ar71xx/machtype.h new file mode 100644 index 000000000..98681c6c9 --- /dev/null +++ b/target/linux/ar71xx/files/arch/mips/ar71xx/machtype.h @@ -0,0 +1,56 @@ +/* + * Atheros AR71xx machine type definitions + * + * Copyright (C) 2008-2010 Gabor Juhos + * Copyright (C) 2008 Imre Kaloz + * + * 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 _AR71XX_MACHTYPE_H +#define _AR71XX_MACHTYPE_H + +#include + +enum ar71xx_mach_type { + AR71XX_MACH_GENERIC = 0, + AR71XX_MACH_AP81, /* Atheros AP81 */ + AR71XX_MACH_AP83, /* Atheros AP83 */ + AR71XX_MACH_AW_NR580, /* AzureWave AW-NR580 */ + AR71XX_MACH_DIR_600_A1, /* D-Link DIR-600 rev. A1 */ + AR71XX_MACH_DIR_615_C1, /* D-Link DIR-615 rev. C1 */ + AR71XX_MACH_DIR_825_B1, /* D-Link DIR-825 rev. B1 */ + AR71XX_MACH_RB_411, /* MikroTik RouterBOARD 411/411A/411AH */ + AR71XX_MACH_RB_411U, /* MikroTik RouterBOARD 411U */ + AR71XX_MACH_RB_433, /* MikroTik RouterBOARD 433/433AH */ + AR71XX_MACH_RB_433U, /* MikroTik RouterBOARD 433UAH */ + AR71XX_MACH_RB_450, /* MikroTik RouterBOARD 450 */ + AR71XX_MACH_RB_450G, /* MikroTik RouterBOARD 450G */ + AR71XX_MACH_RB_493, /* Mikrotik RouterBOARD 493/493AH */ + AR71XX_MACH_PB42, /* Atheros PB42 */ + AR71XX_MACH_PB44, /* Atheros PB44 */ + AR71XX_MACH_MZK_W04NU, /* Planex MZK-W04NU */ + AR71XX_MACH_MZK_W300NH, /* Planex MZK-W300NH */ + AR71XX_MACH_TEW_632BRP, /* TRENDnet TEW-632BRP */ + AR71XX_MACH_TL_WR741ND, /* TP-LINK TL-WR741ND */ + AR71XX_MACH_TL_WR841N_V1, /* TP-LINK TL-WR841N v1 */ + AR71XX_MACH_TL_WR941ND, /* TP-LINK TL-WR941ND */ + AR71XX_MACH_TL_WR1043ND, /* TP-LINK TL-WR1041ND */ + AR71XX_MACH_UBNT_LSSR71, /* Ubiquiti LS-SR71 */ + AR71XX_MACH_UBNT_LSX, /* Ubiquiti LSX */ + AR71XX_MACH_UBNT_RS, /* Ubiquiti RouterStation */ + AR71XX_MACH_UBNT_AR71XX, /* Ubiquiti AR71xx-based board */ + AR71XX_MACH_UBNT_RSPRO, /* Ubiquiti RouterStation Pro */ + AR71XX_MACH_UBNT_BULLET_M, /* Ubiquiti Bullet M */ + AR71XX_MACH_UBNT_ROCKET_M, /* Ubiquiti Rocket M */ + AR71XX_MACH_UBNT_NANO_M, /* Ubiquiti NanoStation M */ + AR71XX_MACH_WNDR3700, /* NETGEAR WNDR3700 */ + AR71XX_MACH_WNR2000, /* NETGEAR WNR2000 */ + AR71XX_MACH_WP543, /* Compex WP543 */ + AR71XX_MACH_WRT160NL, /* Linksys WRT160NL */ + AR71XX_MACH_WRT400N, /* Linksys WRT400N */ +}; + +#endif /* _AR71XX_MACHTYPE_H */ diff --git a/target/linux/ar71xx/files/arch/mips/ar71xx/nvram.c b/target/linux/ar71xx/files/arch/mips/ar71xx/nvram.c new file mode 100644 index 000000000..e6d1f8047 --- /dev/null +++ b/target/linux/ar71xx/files/arch/mips/ar71xx/nvram.c @@ -0,0 +1,75 @@ +/* + * Atheros AR71xx minimal nvram support + * + * Copyright (C) 2009 Gabor Juhos + * + * 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 +#include +#include +#include +#include + +#include "nvram.h" + +char *nvram_find_var(const char *name, const char *buf, unsigned buf_len) +{ + unsigned len = strlen(name); + char *cur, *last; + + if (buf_len == 0 || len == 0) + return NULL; + + if (buf_len < len) + return NULL; + + if (len == 1) + return memchr(buf, (int) *name, buf_len); + + last = (char *) buf + buf_len - len; + for (cur = (char *) buf; cur <= last; cur++) + if (cur[0] == name[0] && memcmp(cur, name, len) == 0) + return cur + len; + + return NULL; +} + +int nvram_parse_mac_addr(const char *nvram, unsigned nvram_len, + const char *name, char *mac) +{ + char *buf; + char *mac_str; + int ret; + int t; + + buf = vmalloc(nvram_len); + if (!buf) + return -ENOMEM; + + memcpy(buf, nvram, nvram_len); + buf[nvram_len - 1] = '\0'; + + mac_str = nvram_find_var(name, buf, nvram_len); + if (!mac_str) { + ret = -EINVAL; + goto free; + } + + t = sscanf(mac_str, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx", + &mac[0], &mac[1], &mac[2], &mac[3], &mac[4], &mac[5]); + + if (t != 6) { + ret = -EINVAL; + goto free; + } + + ret = 0; + + free: + vfree(buf); + return ret; +} diff --git a/target/linux/ar71xx/files/arch/mips/ar71xx/nvram.h b/target/linux/ar71xx/files/arch/mips/ar71xx/nvram.h new file mode 100644 index 000000000..b025d3fc9 --- /dev/null +++ b/target/linux/ar71xx/files/arch/mips/ar71xx/nvram.h @@ -0,0 +1,19 @@ +/* + * Atheros AR71xx minimal nvram support + * + * Copyright (C) 2009 Gabor Juhos + * + * 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 _AR71XX_NVRAM_H +#define _AR71XX_NVRAM_H + +char *nvram_find_var(const char *name, const char *buf, + unsigned buf_len) __init; +int nvram_parse_mac_addr(const char *nvram, unsigned nvram_len, + const char *name, char *mac) __init; + +#endif /* _AR71XX_NVRAM_H */ diff --git a/target/linux/ar71xx/files/arch/mips/ar71xx/prom.c b/target/linux/ar71xx/files/arch/mips/ar71xx/prom.c index 4cc97632a..5b47d6bfe 100644 --- a/target/linux/ar71xx/files/arch/mips/ar71xx/prom.c +++ b/target/linux/ar71xx/files/arch/mips/ar71xx/prom.c @@ -20,135 +20,6 @@ #include -#include "devices.h" - -struct board_rec { - char *name; - enum ar71xx_mach_type mach_type; -}; - -static struct board_rec boards[] __initdata = { - { - .name = "411", - .mach_type = AR71XX_MACH_RB_411, - }, { - .name = "411U", - .mach_type = AR71XX_MACH_RB_411U, - }, { - .name = "433", - .mach_type = AR71XX_MACH_RB_433, - }, { - .name = "433U", - .mach_type = AR71XX_MACH_RB_433U, - }, { - .name = "450", - .mach_type = AR71XX_MACH_RB_450, - }, { - .name = "450G", - .mach_type = AR71XX_MACH_RB_450G, - }, { - .name = "493", - .mach_type = AR71XX_MACH_RB_493, - }, { - .name = "AP81", - .mach_type = AR71XX_MACH_AP81, - }, { - .name = "AP83", - .mach_type = AR71XX_MACH_AP83, - }, { - .name = "AW-NR580", - .mach_type = AR71XX_MACH_AW_NR580, - }, { - .name = "TEW-632BRP", - .mach_type = AR71XX_MACH_TEW_632BRP, - }, { - .name = "TL-WR741ND", - .mach_type = AR71XX_MACH_TL_WR741ND, - }, { - .name = "TL-WR941ND", - .mach_type = AR71XX_MACH_TL_WR941ND, - }, { - .name = "UBNT-RS", - .mach_type = AR71XX_MACH_UBNT_RS, - }, { - .name = "UBNT-RSPRO", - .mach_type = AR71XX_MACH_UBNT_RSPRO, - }, { - .name = "Ubiquiti AR71xx-based board", - .mach_type = AR71XX_MACH_UBNT_RS, - }, { - .name = "UBNT-LS-SR71", - .mach_type = AR71XX_MACH_UBNT_LSSR71, - }, { - .name = "UBNT-LSX", - .mach_type = AR71XX_MACH_UBNT_LSX, - }, { - .name = "UBNT-BM", - .mach_type = AR71XX_MACH_UBNT_BULLET_M, - }, { - .name = "UBNT-RM", - .mach_type = AR71XX_MACH_UBNT_ROCKET_M, - }, { - .name = "UBNT-NM", - .mach_type = AR71XX_MACH_UBNT_NANO_M, - }, { - .name = "WNDR3700", - .mach_type = AR71XX_MACH_WNDR3700, - }, { - .name = "WNR2000", - .mach_type = AR71XX_MACH_WNR2000, - }, { - .name = "WRT160NL", - .mach_type = AR71XX_MACH_WRT160NL, - }, { - .name = "WP543", - .mach_type = AR71XX_MACH_WP543, - }, { - .name = "WRT400N", - .mach_type = AR71XX_MACH_WRT400N, - }, { - .name = "PB42", - .mach_type = AR71XX_MACH_PB42, - }, { - .name = "PB44", - .mach_type = AR71XX_MACH_PB44, - }, { - .name = "MZK-W300NH", - .mach_type = AR71XX_MACH_MZK_W300NH, - }, { - .name = "MZK-W04NU", - .mach_type = AR71XX_MACH_MZK_W04NU, - } -}; - -static int __init ar71xx_board_setup(char *name) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(boards); i++) - if (strcmp(name, boards[i].name) == 0) { - ar71xx_mach = boards[i].mach_type; - break; - } - - return 1; -} -__setup("board=", ar71xx_board_setup); - -static int __init ar71xx_ethaddr_setup(char *str) -{ - ar71xx_parse_mac_addr(str); - return 1; -} -__setup("ethaddr=", ar71xx_ethaddr_setup); - -static int __init ar71xx_kmac_setup(char *str) -{ - ar71xx_parse_mac_addr(str); - return 1; -} -__setup("kmac=", ar71xx_kmac_setup); - static inline int is_valid_ram_addr(void *addr) { if (((u32) addr > KSEG0) && @@ -279,8 +150,6 @@ void __init prom_init(void) (unsigned int)fw_arg2, (unsigned int)fw_arg3); - ar71xx_mach = AR71XX_MACH_GENERIC; - if (ar71xx_prom_init_myloader()) return; diff --git a/target/linux/ar71xx/files/arch/mips/ar71xx/setup.c b/target/linux/ar71xx/files/arch/mips/ar71xx/setup.c index 4a2295af4..f23592223 100644 --- a/target/linux/ar71xx/files/arch/mips/ar71xx/setup.c +++ b/target/linux/ar71xx/files/arch/mips/ar71xx/setup.c @@ -24,6 +24,7 @@ #include #include +#include "machtype.h" #include "devices.h" #define AR71XX_SYS_TYPE_LEN 64 @@ -31,8 +32,6 @@ #define AR91XX_BASE_FREQ 5000000 #define AR724X_BASE_FREQ 5000000 -enum ar71xx_mach_type ar71xx_mach; - u32 ar71xx_cpu_freq; EXPORT_SYMBOL_GPL(ar71xx_cpu_freq); @@ -275,6 +274,8 @@ void __init plat_time_init(void) mips_hpt_frequency = ar71xx_cpu_freq / 2; } +__setup("board=", mips_machtype_setup); + static int __init ar71xx_machine_setup(void) { ar71xx_gpio_init(); @@ -282,7 +283,7 @@ static int __init ar71xx_machine_setup(void) ar71xx_add_device_uart(); ar71xx_add_device_wdt(); - mips_machine_setup(ar71xx_mach); + mips_machine_setup(); return 0; } diff --git a/target/linux/ar71xx/files/arch/mips/include/asm/mach-ar71xx/ar71xx.h b/target/linux/ar71xx/files/arch/mips/include/asm/mach-ar71xx/ar71xx.h index 46629327c..00e7cbc4b 100644 --- a/target/linux/ar71xx/files/arch/mips/include/asm/mach-ar71xx/ar71xx.h +++ b/target/linux/ar71xx/files/arch/mips/include/asm/mach-ar71xx/ar71xx.h @@ -119,41 +119,6 @@ enum ar71xx_soc_type { extern enum ar71xx_soc_type ar71xx_soc; -enum ar71xx_mach_type { - AR71XX_MACH_GENERIC = 0, - AR71XX_MACH_AP81, /* Atheros AP81 */ - AR71XX_MACH_AP83, /* Atheros AP83 */ - AR71XX_MACH_AW_NR580, /* AzureWave AW-NR580 */ - AR71XX_MACH_RB_411, /* MikroTik RouterBOARD 411/411A/411AH */ - AR71XX_MACH_RB_411U, /* MikroTik RouterBOARD 411U */ - AR71XX_MACH_RB_433, /* MikroTik RouterBOARD 433/433AH */ - AR71XX_MACH_RB_433U, /* MikroTik RouterBOARD 433UAH */ - AR71XX_MACH_RB_450, /* MikroTik RouterBOARD 450 */ - AR71XX_MACH_RB_450G, /* MikroTik RouterBOARD 450G */ - AR71XX_MACH_RB_493, /* Mikrotik RouterBOARD 493/493AH */ - AR71XX_MACH_PB42, /* Atheros PB42 */ - AR71XX_MACH_PB44, /* Atheros PB44 */ - AR71XX_MACH_MZK_W04NU, /* Planex MZK-W04NU */ - AR71XX_MACH_MZK_W300NH, /* Planex MZK-W300NH */ - AR71XX_MACH_TEW_632BRP, /* TRENDnet TEW-632BRP */ - AR71XX_MACH_TL_WR741ND, /* TP-LINK TL-WR741ND */ - AR71XX_MACH_TL_WR941ND, /* TP-LINK TL-WR941ND */ - AR71XX_MACH_UBNT_LSSR71, /* Ubiquiti LS-SR71 */ - AR71XX_MACH_UBNT_LSX, /* Ubiquiti LSX */ - AR71XX_MACH_UBNT_RS, /* Ubiquiti RouterStation */ - AR71XX_MACH_UBNT_RSPRO, /* Ubiquiti RouterStation Pro */ - AR71XX_MACH_UBNT_BULLET_M, /* Ubiquiti Bullet M */ - AR71XX_MACH_UBNT_ROCKET_M, /* Ubiquiti Rocket M */ - AR71XX_MACH_UBNT_NANO_M, /* Ubiquiti NanoStation M */ - AR71XX_MACH_WNR2000, /* NETGEAR WNR2000 */ - AR71XX_MACH_WNDR3700, /* NETGEAR WNDR3700 */ - AR71XX_MACH_WP543, /* Compex WP543 */ - AR71XX_MACH_WRT160NL, /* Linksys WRT160NL */ - AR71XX_MACH_WRT400N, /* Linksys WRT400N */ -}; - -extern enum ar71xx_mach_type ar71xx_mach; - /* * PLL block */ @@ -175,6 +140,7 @@ extern enum ar71xx_mach_type ar71xx_mach; #define AR71XX_ETH1_PLL_SHIFT 19 #define AR724X_PLL_REG_CPU_CONFIG 0x00 +#define AR724X_PLL_REG_PCIE_CONFIG 0x18 #define AR724X_PLL_DIV_SHIFT 0 #define AR724X_PLL_DIV_MASK 0x3ff @@ -381,9 +347,13 @@ void ar71xx_ddr_flush(u32 reg); #define AR724X_PCI_CFG_BASE (AR71XX_PCI_MEM_BASE + 0x4000000) #define AR724X_PCI_CFG_SIZE 0x1000 +#define AR724X_PCI_REG_APP 0x00 +#define AR724X_PCI_REG_RESET 0x18 #define AR724X_PCI_REG_INT_STATUS 0x4c #define AR724X_PCI_REG_INT_MASK 0x50 +#define AR724X_PCI_APP_LTSSM_ENABLE BIT(0) + #define AR724X_PCI_INT_DEV0 BIT(14) static inline void ar724x_pci_wr(unsigned reg, u32 val) @@ -395,6 +365,14 @@ static inline void ar724x_pci_wr(unsigned reg, u32 val) iounmap(base); } +static inline void ar724x_pci_wr_nf(unsigned reg, u32 val) +{ + void __iomem *base; + + base = ioremap_nocache(AR724X_PCI_CTRL_BASE, AR724X_PCI_CTRL_SIZE); + iounmap(base); +} + static inline u32 ar724x_pci_rr(unsigned reg) { void __iomem *base; @@ -474,6 +452,10 @@ static inline u32 ar724x_pci_rr(unsigned reg) #define RESET_MODULE_PCI_BUS BIT(1) #define RESET_MODULE_PCI_CORE BIT(0) +#define AR724X_RESET_PCIE_PHY_SERIAL BIT(10) +#define AR724X_RESET_PCIE_PHY BIT(7) +#define AR724X_RESET_PCIE BIT(6) + #define REV_ID_MAJOR_MASK 0xf0 #define REV_ID_MAJOR_AR71XX 0xa0 #define REV_ID_MAJOR_AR913X 0xb0 @@ -508,6 +490,7 @@ static inline u32 ar71xx_reset_rr(unsigned reg) void ar71xx_device_stop(u32 mask); void ar71xx_device_start(u32 mask); +int ar71xx_device_stopped(u32 mask); /* * SPI block diff --git a/target/linux/ar71xx/files/arch/mips/include/asm/mach-ar71xx/platform.h b/target/linux/ar71xx/files/arch/mips/include/asm/mach-ar71xx/platform.h index baded8b8b..145e79fce 100644 --- a/target/linux/ar71xx/files/arch/mips/include/asm/mach-ar71xx/platform.h +++ b/target/linux/ar71xx/files/arch/mips/include/asm/mach-ar71xx/platform.h @@ -25,6 +25,7 @@ struct ag71xx_platform_data { u32 reset_bit; u32 mii_if; u8 mac_addr[ETH_ALEN]; + struct device *mii_bus_dev; u8 has_gbit:1; u8 is_ar91xx:1; diff --git a/target/linux/ar71xx/files/arch/mips/pci/pci-ar724x.c b/target/linux/ar71xx/files/arch/mips/pci/pci-ar724x.c index 139af940a..5fcfc8738 100644 --- a/target/linux/ar71xx/files/arch/mips/pci/pci-ar724x.c +++ b/target/linux/ar71xx/files/arch/mips/pci/pci-ar724x.c @@ -131,7 +131,7 @@ static int ar724x_pci_write_config(struct pci_bus *bus, unsigned int devfn, static void ar724x_pci_fixup(struct pci_dev *dev) { - u32 t; + u16 cmd; if (!ar724x_pci_fixup_enable) return; @@ -139,14 +139,13 @@ static void ar724x_pci_fixup(struct pci_dev *dev) if (dev->bus->number != 0 || dev->devfn != 0) return; - DBG("PCI: fixup host controller %s (%04x:%04x)\n", pci_name(dev), - dev->vendor, dev->device); - /* setup COMMAND register */ - t = PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER | PCI_COMMAND_INVALIDATE - | PCI_COMMAND_PARITY | PCI_COMMAND_SERR | PCI_COMMAND_FAST_BACK; + pci_read_config_word(dev, PCI_COMMAND, &cmd); + cmd |= PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER | + PCI_COMMAND_INVALIDATE | PCI_COMMAND_PARITY | PCI_COMMAND_SERR | + PCI_COMMAND_FAST_BACK; - pci_write_config_word(dev, PCI_COMMAND, t); + pci_write_config_word(dev, PCI_COMMAND, cmd); } DECLARE_PCI_FIXUP_EARLY(PCI_ANY_ID, PCI_ANY_ID, ar724x_pci_fixup); @@ -201,21 +200,66 @@ static struct pci_controller ar724x_pci_controller = { .io_resource = &ar724x_pci_io_resource, }; -int __init ar724x_pcibios_init(void) +static void __init ar724x_pci_reset(void) +{ + ar71xx_device_stop(AR724X_RESET_PCIE); + ar71xx_device_stop(AR724X_RESET_PCIE_PHY); + ar71xx_device_stop(AR724X_RESET_PCIE_PHY_SERIAL); + udelay(100); + + ar71xx_device_start(AR724X_RESET_PCIE_PHY_SERIAL); + udelay(100); + ar71xx_device_start(AR724X_RESET_PCIE_PHY); + ar71xx_device_start(AR724X_RESET_PCIE); +} + +static int __init ar724x_pci_setup(void) { u32 t; + /* setup COMMAND register */ + t = PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER | PCI_COMMAND_INVALIDATE | + PCI_COMMAND_PARITY|PCI_COMMAND_SERR|PCI_COMMAND_FAST_BACK; + + ar724x_pci_write(ar724x_pci_localcfg_base, PCI_COMMAND, 4, t); + ar724x_pci_write(ar724x_pci_localcfg_base, 0x20, 4, 0x1ff01000); + ar724x_pci_write(ar724x_pci_localcfg_base, 0x24, 4, 0x1ff01000); + + t = ar724x_pci_rr(AR724X_PCI_REG_RESET); + if (t != 0x7) { + udelay(100000); + ar724x_pci_wr_nf(AR724X_PCI_REG_RESET, 0); + udelay(100); + ar724x_pci_wr_nf(AR724X_PCI_REG_RESET, 4); + udelay(100000); + } + + ar724x_pci_wr(AR724X_PCI_REG_APP, AR724X_PCI_APP_LTSSM_ENABLE); + udelay(1000); + + t = ar724x_pci_rr(AR724X_PCI_REG_APP); + if ((t & AR724X_PCI_APP_LTSSM_ENABLE) == 0x0) { + printk(KERN_WARNING "PCI: no PCIe module found\n"); + return -ENODEV; + } + + return 0; +} + +int __init ar724x_pcibios_init(void) +{ + int ret; + ar724x_pci_localcfg_base = ioremap_nocache(AR724X_PCI_CRP_BASE, AR724X_PCI_CRP_SIZE); ar724x_pci_devcfg_base = ioremap_nocache(AR724X_PCI_CFG_BASE, AR724X_PCI_CFG_SIZE); - /* setup COMMAND register */ - t = PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER | PCI_COMMAND_INVALIDATE | - PCI_COMMAND_PARITY | PCI_COMMAND_SERR | PCI_COMMAND_FAST_BACK; - - ar724x_pci_write(ar724x_pci_localcfg_base, PCI_COMMAND, 4, t); + ar724x_pci_reset(); + ret = ar724x_pci_setup(); + if (ret) + return ret; ar724x_pci_fixup_enable = 1; register_pci_controller(&ar724x_pci_controller); diff --git a/target/linux/ar71xx/files/drivers/leds/leds-wndr3700-usb.c b/target/linux/ar71xx/files/drivers/leds/leds-wndr3700-usb.c new file mode 100644 index 000000000..9f178611d --- /dev/null +++ b/target/linux/ar71xx/files/drivers/leds/leds-wndr3700-usb.c @@ -0,0 +1,75 @@ +/* + * USB LED driver for the NETGEAR WNDR3700 + * + * Copyright (C) 2009 Gabor Juhos + * + * 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 +#include +#include + +#include + +#define DRIVER_NAME "wndr3700-led-usb" + +static void wndr3700_usb_led_set(struct led_classdev *cdev, + enum led_brightness brightness) +{ + if (brightness) + ar71xx_device_start(RESET_MODULE_GE1_PHY); + else + ar71xx_device_stop(RESET_MODULE_GE1_PHY); +} + +static enum led_brightness wndr3700_usb_led_get(struct led_classdev *cdev) +{ + return ar71xx_device_stopped(RESET_MODULE_GE1_PHY) ? LED_OFF : LED_FULL; +} + +static struct led_classdev wndr3700_usb_led = { + .name = "wndr3700:green:usb", + .brightness_set = wndr3700_usb_led_set, + .brightness_get = wndr3700_usb_led_get, +}; + +static int __devinit wndr3700_usb_led_probe(struct platform_device *pdev) +{ + return led_classdev_register(&pdev->dev, &wndr3700_usb_led); +} + +static int __devexit wndr3700_usb_led_remove(struct platform_device *pdev) +{ + led_classdev_unregister(&wndr3700_usb_led); + return 0; +} + +static struct platform_driver wndr3700_usb_led_driver = { + .probe = wndr3700_usb_led_probe, + .remove = __devexit_p(wndr3700_usb_led_remove), + .driver = { + .name = DRIVER_NAME, + .owner = THIS_MODULE, + }, +}; + +static int __init wndr3700_usb_led_init(void) +{ + return platform_driver_register(&wndr3700_usb_led_driver); +} + +static void __exit wndr3700_usb_led_exit(void) +{ + platform_driver_unregister(&wndr3700_usb_led_driver); +} + +module_init(wndr3700_usb_led_init); +module_exit(wndr3700_usb_led_exit); + +MODULE_DESCRIPTION("USB LED driver for the NETGEAR WNDR3700"); +MODULE_AUTHOR("Gabor Juhos "); +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:" DRIVER_NAME); diff --git a/target/linux/ar71xx/files/drivers/net/ag71xx/Kconfig b/target/linux/ar71xx/files/drivers/net/ag71xx/Kconfig index 801fcaf9d..59bc6fffd 100644 --- a/target/linux/ar71xx/files/drivers/net/ag71xx/Kconfig +++ b/target/linux/ar71xx/files/drivers/net/ag71xx/Kconfig @@ -6,18 +6,28 @@ config AG71XX If you wish to compile a kernel for AR71xx/91xx and enable ethernet support, then you should always answer Y to this. +if AG71XX + config AG71XX_DEBUG bool "Atheros AR71xx built-in ethernet driver debugging" - depends on AG71XX default n help Atheros AR71xx built-in ethernet driver debugging messages. +config AG71XX_DEBUG_FS + bool "Atheros AR71xx built-in ethernet driver debugfs support" + depends on DEBUG_FS + default n + help + Say Y, if you need access to various statistics provided by + the ag71xx driver. + config AG71XX_AR8216_SUPPORT bool "special support for the Atheros AR8216 switch" - depends on AG71XX default n default y if AR71XX_MACH_WNR2000 || AR71XX_MACH_MZK_W04NU || AR71XX_MACH_WRT400N help Say 'y' here if you want to enable special support for the Atheros AR8216 switch found on some boards. + +endif diff --git a/target/linux/ar71xx/files/drivers/net/ag71xx/Makefile b/target/linux/ar71xx/files/drivers/net/ag71xx/Makefile index aa1798d19..3485ab385 100644 --- a/target/linux/ar71xx/files/drivers/net/ag71xx/Makefile +++ b/target/linux/ar71xx/files/drivers/net/ag71xx/Makefile @@ -2,12 +2,13 @@ # Makefile for the Atheros AR71xx built-in ethernet macs # -ag71xx-y += ag71xx_main.o -ag71xx-y += ag71xx_ethtool.o -ag71xx-y += ag71xx_phy.o +ag71xx-y += ag71xx_main.o +ag71xx-y += ag71xx_ethtool.o +ag71xx-y += ag71xx_phy.o ag71xx-y += ag71xx_mdio.o -ag71xx-$(CONFIG_AG71XX_AR8216_SUPPORT) += ag71xx_ar8216.o +ag71xx-$(CONFIG_AG71XX_DEBUG_FS) += ag71xx_debugfs.o +ag71xx-$(CONFIG_AG71XX_AR8216_SUPPORT) += ag71xx_ar8216.o obj-$(CONFIG_AG71XX) += ag71xx.o diff --git a/target/linux/ar71xx/files/drivers/net/ag71xx/ag71xx.h b/target/linux/ar71xx/files/drivers/net/ag71xx/ag71xx.h index 77962fec8..139fc9455 100644 --- a/target/linux/ar71xx/files/drivers/net/ag71xx/ag71xx.h +++ b/target/linux/ar71xx/files/drivers/net/ag71xx/ag71xx.h @@ -1,7 +1,7 @@ /* * Atheros AR71xx built-in ethernet mac driver * - * Copyright (C) 2008-2009 Gabor Juhos + * Copyright (C) 2008-2010 Gabor Juhos * Copyright (C) 2008 Imre Kaloz * * Based on Atheros' AG7100 driver @@ -109,6 +109,38 @@ struct ag71xx_mdio { struct ag71xx_mdio_platform_data *pdata; }; +struct ag71xx_int_stats { + unsigned long rx_pr; + unsigned long rx_be; + unsigned long rx_of; + unsigned long tx_ps; + unsigned long tx_be; + unsigned long tx_ur; + unsigned long total; +}; + +struct ag71xx_napi_stats { + unsigned long napi_calls; + unsigned long rx_count; + unsigned long rx_packets; + unsigned long rx_packets_max; + unsigned long tx_count; + unsigned long tx_packets; + unsigned long tx_packets_max; + + unsigned long rx[AG71XX_NAPI_WEIGHT + 1]; + unsigned long tx[AG71XX_NAPI_WEIGHT + 1]; +}; + +struct ag71xx_debug { + struct dentry *debugfs_dir; + struct dentry *debugfs_int_stats; + struct dentry *debugfs_napi_stats; + + struct ag71xx_int_stats int_stats; + struct ag71xx_napi_stats napi_stats; +}; + struct ag71xx { void __iomem *mac_base; void __iomem *mii_ctrl; @@ -131,11 +163,14 @@ struct ag71xx { struct work_struct restart_work; struct timer_list oom_timer; + +#ifdef CONFIG_AG71XX_DEBUG_FS + struct ag71xx_debug debug; +#endif }; extern struct ethtool_ops ag71xx_ethtool_ops; -extern struct ag71xx_mdio *ag71xx_mdio_bus; int ag71xx_mdio_driver_init(void) __init; void ag71xx_mdio_driver_exit(void); @@ -451,4 +486,22 @@ static inline int ag71xx_remove_ar8216_header(struct ag71xx *ag, } #endif +#ifdef CONFIG_AG71XX_DEBUG_FS +int ag71xx_debugfs_root_init(void); +void ag71xx_debugfs_root_exit(void); +int ag71xx_debugfs_init(struct ag71xx *ag); +void ag71xx_debugfs_exit(struct ag71xx *ag); +void ag71xx_debugfs_update_int_stats(struct ag71xx *ag, u32 status); +void ag71xx_debugfs_update_napi_stats(struct ag71xx *ag, int rx, int tx); +#else +static inline int ag71xx_debugfs_root_init(void) { return 0; } +static inline void ag71xx_debugfs_root_exit(void) {} +static inline int ag71xx_debugfs_init(struct ag71xx *ag) { return 0; } +static inline void ag71xx_debugfs_exit(struct ag71xx *ag) {} +static inline void ag71xx_debugfs_update_int_stats(struct ag71xx *ag, + u32 status) {} +static inline void ag71xx_debugfs_update_napi_stats(struct ag71xx *ag, + int rx, int tx) {} +#endif /* CONFIG_AG71XX_DEBUG_FS */ + #endif /* _AG71XX_H */ diff --git a/target/linux/ar71xx/files/drivers/net/ag71xx/ag71xx_ar8216.c b/target/linux/ar71xx/files/drivers/net/ag71xx/ag71xx_ar8216.c index 39221ad62..5b3722651 100644 --- a/target/linux/ar71xx/files/drivers/net/ag71xx/ag71xx_ar8216.c +++ b/target/linux/ar71xx/files/drivers/net/ag71xx/ag71xx_ar8216.c @@ -2,7 +2,7 @@ * Atheros AR71xx built-in ethernet mac driver * Special support for the Atheros ar8216 switch chip * - * Copyright (C) 2009 Gabor Juhos + * Copyright (C) 2009-2010 Gabor Juhos * * Based on Atheros' AG7100 driver * diff --git a/target/linux/ar71xx/files/drivers/net/ag71xx/ag71xx_debugfs.c b/target/linux/ar71xx/files/drivers/net/ag71xx/ag71xx_debugfs.c new file mode 100644 index 000000000..c37265e7b --- /dev/null +++ b/target/linux/ar71xx/files/drivers/net/ag71xx/ag71xx_debugfs.c @@ -0,0 +1,197 @@ +/* + * Atheros AR71xx built-in ethernet mac driver + * + * Copyright (C) 2008-2010 Gabor Juhos + * Copyright (C) 2008 Imre Kaloz + * + * Based on Atheros' AG7100 driver + * + * 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 + +#include "ag71xx.h" + +static struct dentry *ag71xx_debugfs_root; + +static int ag71xx_debugfs_generic_open(struct inode *inode, struct file *file) +{ + file->private_data = inode->i_private; + return 0; +} + +void ag71xx_debugfs_update_int_stats(struct ag71xx *ag, u32 status) +{ + if (status) + ag->debug.int_stats.total++; + if (status & AG71XX_INT_TX_PS) + ag->debug.int_stats.tx_ps++; + if (status & AG71XX_INT_TX_UR) + ag->debug.int_stats.tx_ur++; + if (status & AG71XX_INT_TX_BE) + ag->debug.int_stats.tx_be++; + if (status & AG71XX_INT_RX_PR) + ag->debug.int_stats.rx_pr++; + if (status & AG71XX_INT_RX_OF) + ag->debug.int_stats.rx_of++; + if (status & AG71XX_INT_RX_BE) + ag->debug.int_stats.rx_be++; +} + +static ssize_t read_file_int_stats(struct file *file, char __user *user_buf, + size_t count, loff_t *ppos) +{ +#define PR_INT_STAT(_label, _field) \ + len += snprintf(buf + len, sizeof(buf) - len, \ + "%20s: %10lu\n", _label, ag->debug.int_stats._field); + + struct ag71xx *ag = file->private_data; + char buf[256]; + unsigned int len = 0; + + PR_INT_STAT("TX Packet Sent", tx_ps); + PR_INT_STAT("TX Underrun", tx_ur); + PR_INT_STAT("TX Bus Error", tx_be); + PR_INT_STAT("RX Packet Received", rx_pr); + PR_INT_STAT("RX Overflow", rx_of); + PR_INT_STAT("RX Bus Error", rx_be); + len += snprintf(buf + len, sizeof(buf) - len, "\n"); + PR_INT_STAT("Total", total); + + return simple_read_from_buffer(user_buf, count, ppos, buf, len); +#undef PR_INT_STAT +} + +static const struct file_operations ag71xx_fops_int_stats = { + .open = ag71xx_debugfs_generic_open, + .read = read_file_int_stats, + .owner = THIS_MODULE +}; + +void ag71xx_debugfs_update_napi_stats(struct ag71xx *ag, int rx, int tx) +{ + struct ag71xx_napi_stats *stats = &ag->debug.napi_stats; + + if (rx) { + stats->rx_count++; + stats->rx_packets += rx; + if (rx <= AG71XX_NAPI_WEIGHT) + stats->rx[rx]++; + if (rx > stats->rx_packets_max) + stats->rx_packets_max = rx; + } + + if (tx) { + stats->tx_count++; + stats->tx_packets += tx; + if (tx <= AG71XX_NAPI_WEIGHT) + stats->tx[tx]++; + if (tx > stats->tx_packets_max) + stats->tx_packets_max = tx; + } +} + +static ssize_t read_file_napi_stats(struct file *file, char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct ag71xx *ag = file->private_data; + struct ag71xx_napi_stats *stats = &ag->debug.napi_stats; + char buf[2048]; + unsigned int len = 0; + unsigned long rx_avg = 0; + unsigned long tx_avg = 0; + int i; + + if (stats->rx_count) + rx_avg = stats->rx_packets / stats->rx_count; + + if (stats->tx_count) + tx_avg = stats->tx_packets / stats->tx_count; + + len += snprintf(buf + len, sizeof(buf) - len, "%3s %10s %10s\n", + "len", "rx", "tx"); + + for (i = 1; i <= AG71XX_NAPI_WEIGHT; i++) + len += snprintf(buf + len, sizeof(buf) - len, + "%3d: %10lu %10lu\n", + i, stats->rx[i], stats->tx[i]); + + len += snprintf(buf + len, sizeof(buf) - len, "\n"); + + len += snprintf(buf + len, sizeof(buf) - len, "%3s: %10lu %10lu\n", + "sum", stats->rx_count, stats->tx_count); + len += snprintf(buf + len, sizeof(buf) - len, "%3s: %10lu %10lu\n", + "avg", rx_avg, tx_avg); + len += snprintf(buf + len, sizeof(buf) - len, "%3s: %10lu %10lu\n", + "max", stats->rx_packets_max, stats->tx_packets_max); + len += snprintf(buf + len, sizeof(buf) - len, "%3s: %10lu %10lu\n", + "pkt", stats->rx_packets, stats->tx_packets); + + return simple_read_from_buffer(user_buf, count, ppos, buf, len); +} + +static const struct file_operations ag71xx_fops_napi_stats = { + .open = ag71xx_debugfs_generic_open, + .read = read_file_napi_stats, + .owner = THIS_MODULE +}; + +void ag71xx_debugfs_exit(struct ag71xx *ag) +{ + debugfs_remove(ag->debug.debugfs_napi_stats); + debugfs_remove(ag->debug.debugfs_int_stats); + debugfs_remove(ag->debug.debugfs_dir); +} + +int ag71xx_debugfs_init(struct ag71xx *ag) +{ + ag->debug.debugfs_dir = debugfs_create_dir(ag->dev->name, + ag71xx_debugfs_root); + if (!ag->debug.debugfs_dir) + goto err; + + ag->debug.debugfs_int_stats = + debugfs_create_file("int_stats", + S_IRUGO, + ag->debug.debugfs_dir, + ag, + &ag71xx_fops_int_stats); + if (!ag->debug.debugfs_int_stats) + goto err; + + ag->debug.debugfs_napi_stats = + debugfs_create_file("napi_stats", + S_IRUGO, + ag->debug.debugfs_dir, + ag, + &ag71xx_fops_napi_stats); + if (!ag->debug.debugfs_napi_stats) + goto err; + + return 0; + + err: + ag71xx_debugfs_exit(ag); + return -ENOMEM; +} + +int ag71xx_debugfs_root_init(void) +{ + if (ag71xx_debugfs_root) + return -EBUSY; + + ag71xx_debugfs_root = debugfs_create_dir(KBUILD_MODNAME, NULL); + if (!ag71xx_debugfs_root) + return -ENOENT; + + return 0; +} + +void ag71xx_debugfs_root_exit(void) +{ + debugfs_remove(ag71xx_debugfs_root); + ag71xx_debugfs_root = NULL; +} diff --git a/target/linux/ar71xx/files/drivers/net/ag71xx/ag71xx_ethtool.c b/target/linux/ar71xx/files/drivers/net/ag71xx/ag71xx_ethtool.c index 3ac347f6b..1f1c6aa77 100644 --- a/target/linux/ar71xx/files/drivers/net/ag71xx/ag71xx_ethtool.c +++ b/target/linux/ar71xx/files/drivers/net/ag71xx/ag71xx_ethtool.c @@ -1,7 +1,7 @@ /* * Atheros AR71xx built-in ethernet mac driver * - * Copyright (C) 2008-2009 Gabor Juhos + * Copyright (C) 2008-2010 Gabor Juhos * Copyright (C) 2008 Imre Kaloz * * Based on Atheros' AG7100 driver diff --git a/target/linux/ar71xx/files/drivers/net/ag71xx/ag71xx_main.c b/target/linux/ar71xx/files/drivers/net/ag71xx/ag71xx_main.c index 72d2acced..884366fd3 100644 --- a/target/linux/ar71xx/files/drivers/net/ag71xx/ag71xx_main.c +++ b/target/linux/ar71xx/files/drivers/net/ag71xx/ag71xx_main.c @@ -1,7 +1,7 @@ /* * Atheros AR71xx built-in ethernet mac driver * - * Copyright (C) 2008-2009 Gabor Juhos + * Copyright (C) 2008-2010 Gabor Juhos * Copyright (C) 2008 Imre Kaloz * * Based on Atheros' AG7100 driver @@ -587,7 +587,7 @@ static void ag71xx_oom_timer_handler(unsigned long data) struct net_device *dev = (struct net_device *) data; struct ag71xx *ag = netdev_priv(dev); - netif_rx_schedule(dev, &ag->napi); + napi_schedule(&ag->napi); } static void ag71xx_tx_timeout(struct net_device *dev) @@ -608,10 +608,10 @@ static void ag71xx_restart_work_func(struct work_struct *work) ag71xx_open(ag->dev); } -static void ag71xx_tx_packets(struct ag71xx *ag) +static int ag71xx_tx_packets(struct ag71xx *ag) { struct ag71xx_ring *ring = &ag->tx_ring; - unsigned int sent; + int sent; DBG("%s: processing TX ring\n", ag->dev->name); @@ -641,6 +641,7 @@ static void ag71xx_tx_packets(struct ag71xx *ag) if ((ring->curr - ring->dirty) < AG71XX_TX_THRES_WAKEUP) netif_wake_queue(ag->dev); + return sent; } static int ag71xx_rx_packets(struct ag71xx *ag, int limit) @@ -711,13 +712,16 @@ static int ag71xx_poll(struct napi_struct *napi, int limit) struct ag71xx_ring *rx_ring; unsigned long flags; u32 status; - int done; + int tx_done; + int rx_done; pdata->ddr_flush(); - ag71xx_tx_packets(ag); + tx_done = ag71xx_tx_packets(ag); DBG("%s: processing RX ring\n", dev->name); - done = ag71xx_rx_packets(ag, limit); + rx_done = ag71xx_rx_packets(ag, limit); + + ag71xx_debugfs_update_napi_stats(ag, rx_done, tx_done); rx_ring = &ag->rx_ring; if (rx_ring->buf[rx_ring->dirty % AG71XX_RX_RING_SIZE].skb == NULL) @@ -732,7 +736,7 @@ static int ag71xx_poll(struct napi_struct *napi, int limit) ag71xx_wr(ag, AG71XX_REG_RX_CTRL, RX_CTRL_RXE); } - if (done < limit) { + if (rx_done < limit) { if (status & RX_STATUS_PR) goto more; @@ -740,29 +744,29 @@ static int ag71xx_poll(struct napi_struct *napi, int limit) if (status & TX_STATUS_PS) goto more; - DBG("%s: disable polling mode, done=%d, limit=%d\n", - dev->name, done, limit); + DBG("%s: disable polling mode, rx=%d, tx=%d,limit=%d\n", + dev->name, rx_done, tx_done, limit); - netif_rx_complete(dev, napi); + napi_complete(napi); /* enable interrupts */ spin_lock_irqsave(&ag->lock, flags); ag71xx_int_enable(ag, AG71XX_INT_POLL); spin_unlock_irqrestore(&ag->lock, flags); - return done; + return rx_done; } more: - DBG("%s: stay in polling mode, done=%d, limit=%d\n", - dev->name, done, limit); - return done; + DBG("%s: stay in polling mode, rx=%d, tx=%d, limit=%d\n", + dev->name, rx_done, tx_done, limit); + return rx_done; oom: if (netif_msg_rx_err(ag)) printk(KERN_DEBUG "%s: out of memory\n", dev->name); mod_timer(&ag->oom_timer, jiffies + AG71XX_OOM_REFILL); - netif_rx_complete(dev, napi); + napi_complete(napi); return 0; } @@ -792,9 +796,11 @@ static irqreturn_t ag71xx_interrupt(int irq, void *dev_id) 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); + napi_schedule(&ag->napi); } + ag71xx_debugfs_update_int_stats(ag, status); + return IRQ_HANDLED; } @@ -803,6 +809,18 @@ static void ag71xx_set_multicast_list(struct net_device *dev) /* TODO */ } +static const struct net_device_ops ag71xx_netdev_ops = { + .ndo_open = ag71xx_open, + .ndo_stop = ag71xx_stop, + .ndo_start_xmit = ag71xx_hard_start_xmit, + .ndo_set_multicast_list = ag71xx_set_multicast_list, + .ndo_do_ioctl = ag71xx_do_ioctl, + .ndo_tx_timeout = ag71xx_tx_timeout, + .ndo_change_mtu = eth_change_mtu, + .ndo_set_mac_address = eth_mac_addr, + .ndo_validate_addr = eth_validate_addr, +}; + static int __init ag71xx_probe(struct platform_device *pdev) { struct net_device *dev; @@ -818,6 +836,12 @@ static int __init ag71xx_probe(struct platform_device *pdev) goto err_out; } + if (pdata->mii_bus_dev == NULL) { + dev_err(&pdev->dev, "no MII bus device specified\n"); + err = -EINVAL; + goto err_out; + } + dev = alloc_etherdev(sizeof(*ag)); if (!dev) { dev_err(&pdev->dev, "alloc_etherdev failed\n"); @@ -830,7 +854,6 @@ static int __init ag71xx_probe(struct platform_device *pdev) ag = netdev_priv(dev); ag->pdev = pdev; ag->dev = dev; - ag->mii_bus = ag71xx_mdio_bus->mii_bus; ag->msg_enable = netif_msg_init(ag71xx_msg_level, AG71XX_DEFAULT_MSG_ENABLE); spin_lock_init(&ag->lock); @@ -873,14 +896,9 @@ static int __init ag71xx_probe(struct platform_device *pdev) } dev->base_addr = (unsigned long)ag->mac_base; - dev->open = ag71xx_open; - dev->stop = ag71xx_stop; - dev->hard_start_xmit = ag71xx_hard_start_xmit; - dev->set_multicast_list = ag71xx_set_multicast_list; - dev->do_ioctl = ag71xx_do_ioctl; + dev->netdev_ops = &ag71xx_netdev_ops; dev->ethtool_ops = &ag71xx_ethtool_ops; - dev->tx_timeout = ag71xx_tx_timeout; INIT_WORK(&ag->restart_work, ag71xx_restart_work_func); init_timer(&ag->oom_timer); @@ -906,21 +924,20 @@ static int __init ag71xx_probe(struct platform_device *pdev) ag71xx_dump_regs(ag); - /* Reset the mdio bus explicitly */ - if (ag->mii_bus) { - mutex_lock(&ag->mii_bus->mdio_lock); - ag->mii_bus->reset(ag->mii_bus); - mutex_unlock(&ag->mii_bus->mdio_lock); - } - err = ag71xx_phy_connect(ag); if (err) goto err_unregister_netdev; + err = ag71xx_debugfs_init(ag); + if (err) + goto err_phy_disconnect; + platform_set_drvdata(pdev, dev); return 0; + err_phy_disconnect: + ag71xx_phy_disconnect(ag); err_unregister_netdev: unregister_netdev(dev); err_free_irq: @@ -943,6 +960,7 @@ static int __exit ag71xx_remove(struct platform_device *pdev) if (dev) { struct ag71xx *ag = netdev_priv(dev); + ag71xx_debugfs_exit(ag); ag71xx_phy_disconnect(ag); unregister_netdev(dev); free_irq(dev->irq, dev); @@ -967,10 +985,14 @@ static int __init ag71xx_module_init(void) { int ret; - ret = ag71xx_mdio_driver_init(); + ret = ag71xx_debugfs_root_init(); if (ret) goto err_out; + ret = ag71xx_mdio_driver_init(); + if (ret) + goto err_debugfs_exit; + ret = platform_driver_register(&ag71xx_driver); if (ret) goto err_mdio_exit; @@ -979,6 +1001,8 @@ static int __init ag71xx_module_init(void) err_mdio_exit: ag71xx_mdio_driver_exit(); + err_debugfs_exit: + ag71xx_debugfs_root_exit(); err_out: return ret; } @@ -987,6 +1011,7 @@ static void __exit ag71xx_module_exit(void) { platform_driver_unregister(&ag71xx_driver); ag71xx_mdio_driver_exit(); + ag71xx_debugfs_root_exit(); } module_init(ag71xx_module_init); diff --git a/target/linux/ar71xx/files/drivers/net/ag71xx/ag71xx_mdio.c b/target/linux/ar71xx/files/drivers/net/ag71xx/ag71xx_mdio.c index b6fccbbcd..3984840e0 100644 --- a/target/linux/ar71xx/files/drivers/net/ag71xx/ag71xx_mdio.c +++ b/target/linux/ar71xx/files/drivers/net/ag71xx/ag71xx_mdio.c @@ -1,7 +1,7 @@ /* * Atheros AR71xx built-in ethernet mac driver * - * Copyright (C) 2008-2009 Gabor Juhos + * Copyright (C) 2008-2010 Gabor Juhos * Copyright (C) 2008 Imre Kaloz * * Based on Atheros' AG7100 driver @@ -16,8 +16,6 @@ #define AG71XX_MDIO_RETRY 1000 #define AG71XX_MDIO_DELAY 5 -struct ag71xx_mdio *ag71xx_mdio_bus; - static inline void ag71xx_mdio_wr(struct ag71xx_mdio *am, unsigned reg, u32 value) { @@ -143,9 +141,6 @@ static int __init ag71xx_mdio_probe(struct platform_device *pdev) int i; int err; - if (ag71xx_mdio_bus) - return -EBUSY; - pdata = pdev->dev.platform_data; if (!pdata) { dev_err(&pdev->dev, "no platform data specified\n"); @@ -187,7 +182,7 @@ static int __init ag71xx_mdio_probe(struct platform_device *pdev) am->mii_bus->irq = am->mii_irq; am->mii_bus->priv = am; am->mii_bus->parent = &pdev->dev; - snprintf(am->mii_bus->id, MII_BUS_ID_SIZE, "%x", 0); + snprintf(am->mii_bus->id, MII_BUS_ID_SIZE, "%s", dev_name(&pdev->dev)); am->mii_bus->phy_mask = pdata->phy_mask; for (i = 0; i < PHY_MAX_ADDR; i++) @@ -202,7 +197,6 @@ static int __init ag71xx_mdio_probe(struct platform_device *pdev) ag71xx_mdio_dump_regs(am); platform_set_drvdata(pdev, am); - ag71xx_mdio_bus = am; return 0; err_free_bus: @@ -220,7 +214,6 @@ static int __exit ag71xx_mdio_remove(struct platform_device *pdev) struct ag71xx_mdio *am = platform_get_drvdata(pdev); if (am) { - ag71xx_mdio_bus = NULL; mdiobus_unregister(am->mii_bus); mdiobus_free(am->mii_bus); iounmap(am->mdio_base); diff --git a/target/linux/ar71xx/files/drivers/net/ag71xx/ag71xx_phy.c b/target/linux/ar71xx/files/drivers/net/ag71xx/ag71xx_phy.c index 176eddaaf..3e3d38326 100644 --- a/target/linux/ar71xx/files/drivers/net/ag71xx/ag71xx_phy.c +++ b/target/linux/ar71xx/files/drivers/net/ag71xx/ag71xx_phy.c @@ -1,7 +1,7 @@ /* * Atheros AR71xx built-in ethernet mac driver * - * Copyright (C) 2008-2009 Gabor Juhos + * Copyright (C) 2008-2010 Gabor Juhos * Copyright (C) 2008 Imre Kaloz * * Based on Atheros' AG7100 driver @@ -262,10 +262,59 @@ static int ag71xx_phy_connect_multi(struct ag71xx *ag) return ret; } +static int dev_is_class(struct device *dev, void *class) +{ + if (dev->class != NULL && !strcmp(dev->class->name, class)) + return 1; + + return 0; +} + +static struct device *dev_find_class(struct device *parent, char *class) +{ + if (dev_is_class(parent, class)) { + get_device(parent); + return parent; + } + + return device_find_child(parent, class, dev_is_class); +} + +static struct mii_bus *dev_to_mii_bus(struct device *dev) +{ + struct device *d; + + d = dev_find_class(dev, "mdio_bus"); + if (d != NULL) { + struct mii_bus *bus; + + bus = to_mii_bus(d); + put_device(d); + + return bus; + } + + return NULL; +} + int ag71xx_phy_connect(struct ag71xx *ag) { struct ag71xx_platform_data *pdata = ag71xx_get_pdata(ag); + ag->mii_bus = dev_to_mii_bus(pdata->mii_bus_dev); + if (ag->mii_bus == NULL) { + printk(KERN_ERR "%s: unable to find MII bus on device '%s'\n", + ag->dev->name, dev_name(pdata->mii_bus_dev)); + return -ENODEV; + } + + /* Reset the mdio bus explicitly */ + if (ag->mii_bus->reset) { + mutex_lock(&ag->mii_bus->mdio_lock); + ag->mii_bus->reset(ag->mii_bus); + mutex_unlock(&ag->mii_bus->mdio_lock); + } + if (pdata->phy_mask) return ag71xx_phy_connect_multi(ag); diff --git a/target/linux/ar71xx/files/drivers/net/phy/rtl8366_smi.c b/target/linux/ar71xx/files/drivers/net/phy/rtl8366_smi.c new file mode 100644 index 000000000..e43f8a2d0 --- /dev/null +++ b/target/linux/ar71xx/files/drivers/net/phy/rtl8366_smi.c @@ -0,0 +1,661 @@ +/* + * Platform driver for the Realtek RTL8366 ethernet switch + * + * Copyright (C) 2009 Gabor Juhos + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//#define DEBUG 1 + +#define RTL8366_SMI_DRIVER_NAME "rtl8366-smi" +#define RTL8366_SMI_DRIVER_DESC "Realtek RTL8366 switch driver" +#define RTL8366_SMI_DRIVER_VER "0.1.0" + +#define RTL8366S_PHY_NO_MAX 4 +#define RTL8366S_PHY_PAGE_MAX 7 +#define RTL8366S_PHY_ADDR_MAX 31 + +#define RTL8366S_CHIP_VERSION_CTRL_REG 0x0104 +#define RTL8366S_CHIP_VERSION_MASK 0xf +#define RTL8366S_CHIP_ID_REG 0x0105 +#define RTL8366S_CHIP_ID_8366 0x8366 + +/* PHY registers control */ +#define RTL8366S_PHY_ACCESS_CTRL_REG 0x8028 +#define RTL8366S_PHY_ACCESS_DATA_REG 0x8029 + +#define RTL8366S_PHY_CTRL_READ 1 +#define RTL8366S_PHY_CTRL_WRITE 0 + +#define RTL8366S_PHY_REG_MASK 0x1f +#define RTL8366S_PHY_PAGE_OFFSET 5 +#define RTL8366S_PHY_PAGE_MASK (0x7 << 5) +#define RTL8366S_PHY_NO_OFFSET 9 +#define RTL8366S_PHY_NO_MASK (0x1f << 9) + +#define RTL8366_SMI_ACK_RETRY_COUNT 5 +#define RTL8366_SMI_CLK_DELAY 10 /* nsec */ + +struct rtl8366_smi { + struct platform_device *pdev; + struct rtl8366_smi_platform_data *pdata; + spinlock_t lock; + struct mii_bus *mii_bus; + int mii_irq[PHY_MAX_ADDR]; +}; + +static inline void rtl8366_smi_clk_delay(struct rtl8366_smi *smi) +{ + ndelay(RTL8366_SMI_CLK_DELAY); +} + +static void rtl8366_smi_start(struct rtl8366_smi *smi) +{ + unsigned int sda = smi->pdata->gpio_sda; + unsigned int sck = smi->pdata->gpio_sck; + + /* + * Set GPIO pins to output mode, with initial state: + * SCK = 0, SDA = 1 + */ + gpio_direction_output(sck, 0); + gpio_direction_output(sda, 1); + rtl8366_smi_clk_delay(smi); + + /* CLK 1: 0 -> 1, 1 -> 0 */ + gpio_set_value(sck, 1); + rtl8366_smi_clk_delay(smi); + gpio_set_value(sck, 0); + rtl8366_smi_clk_delay(smi); + + /* CLK 2: */ + gpio_set_value(sck, 1); + rtl8366_smi_clk_delay(smi); + gpio_set_value(sda, 0); + rtl8366_smi_clk_delay(smi); + gpio_set_value(sck, 0); + rtl8366_smi_clk_delay(smi); + gpio_set_value(sda, 1); +} + +static void rtl8366_smi_stop(struct rtl8366_smi *smi) +{ + unsigned int sda = smi->pdata->gpio_sda; + unsigned int sck = smi->pdata->gpio_sck; + + rtl8366_smi_clk_delay(smi); + gpio_set_value(sda, 0); + gpio_set_value(sck, 1); + rtl8366_smi_clk_delay(smi); + gpio_set_value(sda, 1); + rtl8366_smi_clk_delay(smi); + gpio_set_value(sck, 1); + rtl8366_smi_clk_delay(smi); + gpio_set_value(sck, 0); + rtl8366_smi_clk_delay(smi); + gpio_set_value(sck, 1); + + /* add a click */ + rtl8366_smi_clk_delay(smi); + gpio_set_value(sck, 0); + rtl8366_smi_clk_delay(smi); + gpio_set_value(sck, 1); + + /* set GPIO pins to input mode */ + gpio_direction_input(sda); + gpio_direction_input(sck); +} + +static void rtl8366_smi_write_bits(struct rtl8366_smi *smi, u32 data, u32 len) +{ + unsigned int sda = smi->pdata->gpio_sda; + unsigned int sck = smi->pdata->gpio_sck; + + for (; len > 0; len--) { + rtl8366_smi_clk_delay(smi); + + /* prepare data */ + if ( data & ( 1 << (len - 1)) ) + gpio_set_value(sda, 1); + else + gpio_set_value(sda, 0); + rtl8366_smi_clk_delay(smi); + + /* clocking */ + gpio_set_value(sck, 1); + rtl8366_smi_clk_delay(smi); + gpio_set_value(sck, 0); + } +} + +static void rtl8366_smi_read_bits(struct rtl8366_smi *smi, u32 len, u32 *data) +{ + unsigned int sda = smi->pdata->gpio_sda; + unsigned int sck = smi->pdata->gpio_sck; + + gpio_direction_input(sda); + + for (*data = 0; len > 0; len--) { + u32 u; + + rtl8366_smi_clk_delay(smi); + + /* clocking */ + gpio_set_value(sck, 1); + rtl8366_smi_clk_delay(smi); + u = gpio_get_value(sda); + gpio_set_value(sck, 0); + + *data |= (u << (len - 1)); + } + + gpio_direction_output(sda, 0); +} + +static int rtl8366_smi_wait_for_ack(struct rtl8366_smi *smi) +{ + int retry_cnt; + + retry_cnt = 0; + do { + u32 ack; + + rtl8366_smi_read_bits(smi, 1, &ack); + if (ack == 0) + break; + + if (++retry_cnt > RTL8366_SMI_ACK_RETRY_COUNT) + return -EIO; + } while (1); + + return 0; +} + +static int rtl8366_smi_write_byte(struct rtl8366_smi *smi, u8 data) +{ + rtl8366_smi_write_bits(smi, data, 8); + return rtl8366_smi_wait_for_ack(smi); +} + +static int rtl8366_smi_read_byte0(struct rtl8366_smi *smi, u8 *data) +{ + u32 t; + + /* read data */ + rtl8366_smi_read_bits(smi, 8, &t); + *data = (t & 0xff); + + /* send an ACK */ + rtl8366_smi_write_bits(smi, 0x00, 1); + + return 0; +} + +static int rtl8366_smi_read_byte1(struct rtl8366_smi *smi, u8 *data) +{ + u32 t; + + /* read data */ + rtl8366_smi_read_bits(smi, 8, &t); + *data = (t & 0xff); + + /* send an ACK */ + rtl8366_smi_write_bits(smi, 0x01, 1); + + return 0; +} + +static int rtl8366_smi_read_reg(struct rtl8366_smi *smi, u32 addr, u32 *data) +{ + unsigned long flags; + u8 lo = 0; + u8 hi = 0; + int ret; + + spin_lock_irqsave(&smi->lock, flags); + + rtl8366_smi_start(smi); + + /* send READ command */ + ret = rtl8366_smi_write_byte(smi, 0x0a << 4 | 0x04 << 1 | 0x01); + if (ret) + goto out; + + /* set ADDR[7:0] */ + ret = rtl8366_smi_write_byte(smi, addr & 0xff); + if (ret) + goto out; + + /* set ADDR[15:8] */ + ret = rtl8366_smi_write_byte(smi, addr >> 8); + if (ret) + goto out; + + /* read DATA[7:0] */ + rtl8366_smi_read_byte0(smi, &lo); + /* read DATA[15:8] */ + rtl8366_smi_read_byte1(smi, &hi); + + *data = ((u32) lo) | (((u32) hi) << 8); + + ret = 0; + + out: + rtl8366_smi_stop(smi); + spin_unlock_irqrestore(&smi->lock, flags); + + return ret; +} + +static int rtl8366_smi_write_reg(struct rtl8366_smi *smi, u32 addr, u32 data) +{ + unsigned long flags; + int ret; + + spin_lock_irqsave(&smi->lock, flags); + + rtl8366_smi_start(smi); + + /* send WRITE command */ + ret = rtl8366_smi_write_byte(smi, 0x0a << 4 | 0x04 << 1 | 0x00); + if (ret) + goto out; + + /* set ADDR[7:0] */ + ret = rtl8366_smi_write_byte(smi, addr & 0xff); + if (ret) + goto out; + + /* set ADDR[15:8] */ + ret = rtl8366_smi_write_byte(smi, addr >> 8); + if (ret) + goto out; + + /* write DATA[7:0] */ + ret = rtl8366_smi_write_byte(smi, data & 0xff); + if (ret) + goto out; + + /* write DATA[15:8] */ + ret = rtl8366_smi_write_byte(smi, data >> 8); + if (ret) + goto out; + + ret = 0; + + out: + rtl8366_smi_stop(smi); + spin_unlock_irqrestore(&smi->lock, flags); + + return ret; +} + +static int rtl8366_smi_read_phy_reg(struct rtl8366_smi *smi, + u32 phy_no, u32 page, u32 addr, u32 *data) +{ + u32 reg; + int ret; + + if (phy_no > RTL8366S_PHY_NO_MAX) + return -EINVAL; + + if (page > RTL8366S_PHY_PAGE_MAX) + return -EINVAL; + + if (addr > RTL8366S_PHY_ADDR_MAX) + return -EINVAL; + + ret = rtl8366_smi_write_reg(smi, RTL8366S_PHY_ACCESS_CTRL_REG, + RTL8366S_PHY_CTRL_READ); + if (ret) + return ret; + + reg = 0x8000 | (1 << (phy_no + RTL8366S_PHY_NO_OFFSET)) | + ((page << RTL8366S_PHY_PAGE_OFFSET) & RTL8366S_PHY_PAGE_MASK) | + (addr & RTL8366S_PHY_REG_MASK); + + ret = rtl8366_smi_write_reg(smi, reg, 0); + if (ret) + return ret; + + ret = rtl8366_smi_read_reg(smi, RTL8366S_PHY_ACCESS_DATA_REG, data); + if (ret) + return ret; + + return 0; +} + +static int rtl8366_smi_write_phy_reg(struct rtl8366_smi *smi, + u32 phy_no, u32 page, u32 addr, u32 data) +{ + u32 reg; + int ret; + + if (phy_no > RTL8366S_PHY_NO_MAX) + return -EINVAL; + + if (page > RTL8366S_PHY_PAGE_MAX) + return -EINVAL; + + if (addr > RTL8366S_PHY_ADDR_MAX) + return -EINVAL; + + ret = rtl8366_smi_write_reg(smi, RTL8366S_PHY_ACCESS_CTRL_REG, + RTL8366S_PHY_CTRL_WRITE); + if (ret) + return ret; + + reg = 0x8000 | (1 << (phy_no + RTL8366S_PHY_NO_OFFSET)) | + ((page << RTL8366S_PHY_PAGE_OFFSET) & RTL8366S_PHY_PAGE_MASK) | + (addr & RTL8366S_PHY_REG_MASK); + + ret = rtl8366_smi_write_reg(smi, reg, data); + if (ret) + return ret; + + return 0; +} + +#ifdef DEBUG +static void rtl8366_smi_dump_regs(struct rtl8366_smi *smi) +{ + u32 t; + int err; + int i; + + for (i = 0; i < 0x200; i++) { + err = rtl8366_smi_read_reg(smi, i, &t); + if (err) { + dev_err(&smi->pdev->dev, + "unable to read register %04x\n", i); + return; + } + dev_info(&smi->pdev->dev, "reg %04x: %04x\n", i, t); + } + + for (i = 0; i <= RTL8366S_PHY_NO_MAX; i++) { + int j; + + for (j = 0; j <= RTL8366S_PHY_ADDR_MAX; j++) { + err = rtl8366_smi_read_phy_reg(smi, i, 0, j, &t); + if (err) { + dev_err(&smi->pdev->dev, + "unable to read PHY%u:%02x register\n", + i, j); + return; + } + dev_info(&smi->pdev->dev, + "PHY%u:%02x: %04x\n", i, j, t); + } + } +} +#else +static inline void rtl8366_smi_dump_regs(struct rtl8366_smi *smi) {} +#endif + +static int rtl8366_smi_mii_read(struct mii_bus *bus, int addr, int reg) +{ + struct rtl8366_smi *smi = bus->priv; + u32 val = 0; + int err; + + err = rtl8366_smi_read_phy_reg(smi, addr, 0, reg, &val); + if (err) + return 0xffff; + + return val; +} + +static int rtl8366_smi_mii_write(struct mii_bus *bus, int addr, int reg, + u16 val) +{ + struct rtl8366_smi *smi = bus->priv; + u32 t; + int err; + + err = rtl8366_smi_write_phy_reg(smi, addr, 0, reg, val); + /* flush write */ + (void) rtl8366_smi_read_phy_reg(smi, addr, 0, reg, &t); + + return err; +} + +static int rtl8366_smi_mii_init(struct rtl8366_smi *smi) +{ + int ret; + int i; + + smi->mii_bus = mdiobus_alloc(); + if (smi->mii_bus == NULL) { + ret = -ENOMEM; + goto err; + } + + spin_lock_init(&smi->lock); + smi->mii_bus->priv = (void *) smi; + smi->mii_bus->name = "rtl8366-smi"; + smi->mii_bus->read = rtl8366_smi_mii_read; + smi->mii_bus->write = rtl8366_smi_mii_write; + snprintf(smi->mii_bus->id, MII_BUS_ID_SIZE, "%s", + dev_name(&smi->pdev->dev)); + smi->mii_bus->parent = &smi->pdev->dev; + smi->mii_bus->phy_mask = ~(0x1f); + smi->mii_bus->irq = smi->mii_irq; + for (i = 0; i < PHY_MAX_ADDR; i++) + smi->mii_irq[i] = PHY_POLL; + + rtl8366_smi_dump_regs(smi); + + ret = mdiobus_register(smi->mii_bus); + if (ret) + goto err_free; + + rtl8366_smi_dump_regs(smi); + + return 0; + + err_free: + mdiobus_free(smi->mii_bus); + err: + return ret; +} + +static void rtl8366_smi_mii_cleanup(struct rtl8366_smi *smi) +{ + mdiobus_unregister(smi->mii_bus); + mdiobus_free(smi->mii_bus); +} + +static int rtl8366_smi_setup(struct rtl8366_smi *smi) +{ + u32 chip_id = 0; + u32 chip_ver = 0; + int ret; + + ret = rtl8366_smi_read_reg(smi, RTL8366S_CHIP_ID_REG, &chip_id); + if (ret) { + dev_err(&smi->pdev->dev, "unable to read chip id\n"); + return ret; + } + + switch (chip_id) { + case RTL8366S_CHIP_ID_8366: + break; + default: + dev_err(&smi->pdev->dev, "unknown chip id (%04x)\n", chip_id); + return -ENODEV; + } + + ret = rtl8366_smi_read_reg(smi, RTL8366S_CHIP_VERSION_CTRL_REG, + &chip_ver); + if (ret) { + dev_err(&smi->pdev->dev, "unable to read chip version\n"); + return ret; + } + + dev_info(&smi->pdev->dev, "RTL%04x ver. %u chip found\n", + chip_id, chip_ver & RTL8366S_CHIP_VERSION_MASK); + + return 0; +} + +static int __init rtl8366_smi_probe(struct platform_device *pdev) +{ + static int rtl8366_smi_version_printed; + struct rtl8366_smi_platform_data *pdata; + struct rtl8366_smi *smi; + int err; + + if (!rtl8366_smi_version_printed++) + printk(KERN_NOTICE RTL8366_SMI_DRIVER_DESC + " version " RTL8366_SMI_DRIVER_VER"\n"); + + pdata = pdev->dev.platform_data; + if (!pdata) { + dev_err(&pdev->dev, "no platform data specified\n"); + err = -EINVAL; + goto err_out; + } + + smi = kzalloc(sizeof(struct rtl8366_smi), GFP_KERNEL); + if (!smi) { + dev_err(&pdev->dev, "no memory for private data\n"); + err = -ENOMEM; + goto err_out; + } + + err = gpio_request(pdata->gpio_sda, dev_name(&pdev->dev)); + if (err) { + dev_err(&pdev->dev, "gpio_request failed for %u, err=%d\n", + pdata->gpio_sda, err); + goto err_free_smi; + } + + err = gpio_request(pdata->gpio_sck, dev_name(&pdev->dev)); + if (err) { + dev_err(&pdev->dev, "gpio_request failed for %u, err=%d\n", + pdata->gpio_sck, err); + goto err_free_sda; + } + + smi->pdev = pdev; + smi->pdata = pdata; + spin_lock_init(&smi->lock); + + platform_set_drvdata(pdev, smi); + + dev_info(&pdev->dev, "using GPIO pins %u (SDA) and %u (SCK)\n", + pdata->gpio_sda, pdata->gpio_sck); + + err = rtl8366_smi_setup(smi); + if (err) + goto err_clear_drvdata; + + err = rtl8366_smi_mii_init(smi); + if (err) + goto err_clear_drvdata; + + return 0; + + err_clear_drvdata: + platform_set_drvdata(pdev, NULL); + gpio_free(pdata->gpio_sck); + err_free_sda: + gpio_free(pdata->gpio_sda); + err_free_smi: + kfree(smi); + err_out: + return err; +} + +static int __devexit rtl8366_smi_remove(struct platform_device *pdev) +{ + struct rtl8366_smi *smi = platform_get_drvdata(pdev); + + if (smi) { + struct rtl8366_smi_platform_data *pdata; + + pdata = pdev->dev.platform_data; + + rtl8366_smi_mii_cleanup(smi); + platform_set_drvdata(pdev, NULL); + gpio_free(pdata->gpio_sck); + gpio_free(pdata->gpio_sda); + kfree(smi); + } + + return 0; +} + +int rtl8366_phy_config_aneg(struct phy_device *phydev) +{ + return 0; +} + +static struct platform_driver rtl8366_smi_driver = { + .driver = { + .name = RTL8366_SMI_DRIVER_NAME, + .owner = THIS_MODULE, + }, + .probe = rtl8366_smi_probe, + .remove = __devexit_p(rtl8366_smi_remove), +}; + +static struct phy_driver rtl8366_smi_phy_driver = { + .phy_id = 0x001cc960, + .name = "Realtek RTL8366", + .phy_id_mask = 0x1ffffff0, + .features = PHY_GBIT_FEATURES, + .config_aneg = rtl8366_phy_config_aneg, + .read_status = genphy_read_status, + .driver = { + .owner = THIS_MODULE, + }, +}; + +static int __init rtl8366_smi_init(void) +{ + int ret; + + ret = phy_driver_register(&rtl8366_smi_phy_driver); + if (ret) + return ret; + + ret = platform_driver_register(&rtl8366_smi_driver); + if (ret) + goto err_phy_unregister; + + return 0; + + err_phy_unregister: + phy_driver_unregister(&rtl8366_smi_phy_driver); + return ret; +} +module_init(rtl8366_smi_init); + +static void __exit rtl8366_smi_exit(void) +{ + platform_driver_unregister(&rtl8366_smi_driver); + phy_driver_unregister(&rtl8366_smi_phy_driver); +} +module_exit(rtl8366_smi_exit); + +MODULE_DESCRIPTION(RTL8366_SMI_DRIVER_DESC); +MODULE_VERSION(RTL8366_SMI_DRIVER_VER); +MODULE_AUTHOR("Gabor Juhos "); +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:" RTL8366_SMI_DRIVER_NAME); diff --git a/target/linux/ar71xx/files/include/linux/rtl8366_smi.h b/target/linux/ar71xx/files/include/linux/rtl8366_smi.h new file mode 100644 index 000000000..cd0fcbc45 --- /dev/null +++ b/target/linux/ar71xx/files/include/linux/rtl8366_smi.h @@ -0,0 +1,19 @@ +/* + * Platform data definition for the Realtek RTL8366 ethernet switch driver + * + * Copyright (C) 2009 Gabor Juhos + * + * 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 _RTL8366_SMI_H +#define _RTL8366_SMI_H + +struct rtl8366_smi_platform_data { + unsigned gpio_sda; + unsigned gpio_sck; +}; + +#endif /* _RTL8366_SMI_H */ diff --git a/target/linux/ar71xx/files/net/dsa/mv88e6063.c b/target/linux/ar71xx/files/net/dsa/mv88e6063.c new file mode 100644 index 000000000..5638a9fe9 --- /dev/null +++ b/target/linux/ar71xx/files/net/dsa/mv88e6063.c @@ -0,0 +1,294 @@ +/* + * net/dsa/mv88e6063.c - Driver for Marvell 88e6063 switch chips + * Copyright (c) 2009 Gabor Juhos + * + * This driver was base on: net/dsa/mv88e6060.c + * net/dsa/mv88e6063.c - Driver for Marvell 88e6060 switch chips + * Copyright (c) 2008-2009 Marvell Semiconductor + * + * 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. + */ + +#include +#include +#include +#include "dsa_priv.h" + +#define REG_BASE 0x10 +#define REG_PHY(p) (REG_BASE + (p)) +#define REG_PORT(p) (REG_BASE + 8 + (p)) +#define REG_GLOBAL (REG_BASE + 0x0f) +#define NUM_PORTS 7 + +static int reg_read(struct dsa_switch *ds, int addr, int reg) +{ + return mdiobus_read(ds->master_mii_bus, addr, reg); +} + +#define REG_READ(addr, reg) \ + ({ \ + int __ret; \ + \ + __ret = reg_read(ds, addr, reg); \ + if (__ret < 0) \ + return __ret; \ + __ret; \ + }) + + +static int reg_write(struct dsa_switch *ds, int addr, int reg, u16 val) +{ + return mdiobus_write(ds->master_mii_bus, addr, reg, val); +} + +#define REG_WRITE(addr, reg, val) \ + ({ \ + int __ret; \ + \ + __ret = reg_write(ds, addr, reg, val); \ + if (__ret < 0) \ + return __ret; \ + }) + +static char *mv88e6063_probe(struct mii_bus *bus, int sw_addr) +{ + int ret; + + ret = mdiobus_read(bus, REG_PORT(0), 0x03); + if (ret >= 0) { + ret &= 0xfff0; + if (ret == 0x1530) + return "Marvell 88E6063"; + } + + return NULL; +} + +static int mv88e6063_switch_reset(struct dsa_switch *ds) +{ + int i; + int ret; + + /* + * Set all ports to the disabled state. + */ + for (i = 0; i < NUM_PORTS; i++) { + ret = REG_READ(REG_PORT(i), 0x04); + REG_WRITE(REG_PORT(i), 0x04, ret & 0xfffc); + } + + /* + * Wait for transmit queues to drain. + */ + msleep(2); + + /* + * Reset the switch. + */ + REG_WRITE(REG_GLOBAL, 0x0a, 0xa130); + + /* + * Wait up to one second for reset to complete. + */ + for (i = 0; i < 1000; i++) { + ret = REG_READ(REG_GLOBAL, 0x00); + if ((ret & 0x8000) == 0x0000) + break; + + msleep(1); + } + if (i == 1000) + return -ETIMEDOUT; + + return 0; +} + +static int mv88e6063_setup_global(struct dsa_switch *ds) +{ + /* + * Disable discarding of frames with excessive collisions, + * set the maximum frame size to 1536 bytes, and mask all + * interrupt sources. + */ + REG_WRITE(REG_GLOBAL, 0x04, 0x0800); + + /* + * Enable automatic address learning, set the address + * database size to 1024 entries, and set the default aging + * time to 5 minutes. + */ + REG_WRITE(REG_GLOBAL, 0x0a, 0x2130); + + return 0; +} + +static int mv88e6063_setup_port(struct dsa_switch *ds, int p) +{ + int addr = REG_PORT(p); + + /* + * Do not force flow control, disable Ingress and Egress + * Header tagging, disable VLAN tunneling, and set the port + * state to Forwarding. Additionally, if this is the CPU + * port, enable Ingress and Egress Trailer tagging mode. + */ + REG_WRITE(addr, 0x04, dsa_is_cpu_port(ds, p) ? 0x4103 : 0x0003); + + /* + * Port based VLAN map: give each port its own address + * database, allow the CPU port to talk to each of the 'real' + * ports, and allow each of the 'real' ports to only talk to + * the CPU port. + */ + REG_WRITE(addr, 0x06, + ((p & 0xf) << 12) | + (dsa_is_cpu_port(ds, p) ? + ds->phys_port_mask : + (1 << ds->dst->cpu_port))); + + /* + * Port Association Vector: when learning source addresses + * of packets, add the address to the address database using + * a port bitmap that has only the bit for this port set and + * the other bits clear. + */ + REG_WRITE(addr, 0x0b, 1 << p); + + return 0; +} + +static int mv88e6063_setup(struct dsa_switch *ds) +{ + int i; + int ret; + + ret = mv88e6063_switch_reset(ds); + if (ret < 0) + return ret; + + /* @@@ initialise atu */ + + ret = mv88e6063_setup_global(ds); + if (ret < 0) + return ret; + + for (i = 0; i < NUM_PORTS; i++) { + ret = mv88e6063_setup_port(ds, i); + if (ret < 0) + return ret; + } + + return 0; +} + +static int mv88e6063_set_addr(struct dsa_switch *ds, u8 *addr) +{ + REG_WRITE(REG_GLOBAL, 0x01, (addr[0] << 8) | addr[1]); + REG_WRITE(REG_GLOBAL, 0x02, (addr[2] << 8) | addr[3]); + REG_WRITE(REG_GLOBAL, 0x03, (addr[4] << 8) | addr[5]); + + return 0; +} + +static int mv88e6063_port_to_phy_addr(int port) +{ + if (port >= 0 && port <= NUM_PORTS) + return REG_PHY(port); + return -1; +} + +static int mv88e6063_phy_read(struct dsa_switch *ds, int port, int regnum) +{ + int addr; + + addr = mv88e6063_port_to_phy_addr(port); + if (addr == -1) + return 0xffff; + + return reg_read(ds, addr, regnum); +} + +static int +mv88e6063_phy_write(struct dsa_switch *ds, int port, int regnum, u16 val) +{ + int addr; + + addr = mv88e6063_port_to_phy_addr(port); + if (addr == -1) + return 0xffff; + + return reg_write(ds, addr, regnum, val); +} + +static void mv88e6063_poll_link(struct dsa_switch *ds) +{ + int i; + + for (i = 0; i < DSA_MAX_PORTS; i++) { + struct net_device *dev; + int uninitialized_var(port_status); + int link; + int speed; + int duplex; + int fc; + + dev = ds->ports[i]; + if (dev == NULL) + continue; + + link = 0; + if (dev->flags & IFF_UP) { + port_status = reg_read(ds, REG_PORT(i), 0x00); + if (port_status < 0) + continue; + + link = !!(port_status & 0x1000); + } + + if (!link) { + if (netif_carrier_ok(dev)) { + printk(KERN_INFO "%s: link down\n", dev->name); + netif_carrier_off(dev); + } + continue; + } + + speed = (port_status & 0x0100) ? 100 : 10; + duplex = (port_status & 0x0200) ? 1 : 0; + fc = ((port_status & 0xc000) == 0xc000) ? 1 : 0; + + if (!netif_carrier_ok(dev)) { + printk(KERN_INFO "%s: link up, %d Mb/s, %s duplex, " + "flow control %sabled\n", dev->name, + speed, duplex ? "full" : "half", + fc ? "en" : "dis"); + netif_carrier_on(dev); + } + } +} + +static struct dsa_switch_driver mv88e6063_switch_driver = { + .tag_protocol = htons(ETH_P_TRAILER), + .probe = mv88e6063_probe, + .setup = mv88e6063_setup, + .set_addr = mv88e6063_set_addr, + .phy_read = mv88e6063_phy_read, + .phy_write = mv88e6063_phy_write, + .poll_link = mv88e6063_poll_link, +}; + +static int __init mv88e6063_init(void) +{ + register_switch_driver(&mv88e6063_switch_driver); + return 0; +} +module_init(mv88e6063_init); + +static void __exit mv88e6063_cleanup(void) +{ + unregister_switch_driver(&mv88e6063_switch_driver); +} +module_exit(mv88e6063_cleanup); diff --git a/target/linux/ar71xx/image/Makefile b/target/linux/ar71xx/image/Makefile index 653a8af69..4cc88d477 100644 --- a/target/linux/ar71xx/image/Makefile +++ b/target/linux/ar71xx/image/Makefile @@ -77,6 +77,43 @@ define Image/Build/WRT400N fi; fi endef +dir600a1_mtdlayout=mtdparts=spi0.0:192k(u-boot)ro,64k(nvram)ro,896k(kernel),2816k(rootfs),64k(mac)ro,64k(art)ro,3712k@0x40000(firmware) +define Image/Build/DIR600A1 + $(call PatchKernelLzma,$(2),$(3) $(dir600a1_mtdlayout)) + if [ `stat -c%s "$(KDIR)/vmlinux-$(2).bin.lzma"` -gt 917504 ]; then \ + echo "Warning: $(KDIR)/vmlinux-$(2).bin.lzma is too big"; \ + else if [ `stat -c%s $(KDIR)/root.$(1)` -gt 2818048 ]; then \ + echo "Warning: $(KDIR)/root.$(1) is too big"; \ + else \ + mkimage -A mips -O linux -T kernel -a 0x80060000 -C lzma -e \ + 0x80060000 \ + -n 'MIPS OpenWrt Linux-$(LINUX_VERSION)' \ + -d $(KDIR)/vmlinux-$(2).bin.lzma $(KDIR)/vmlinux-$(2).uImage; \ + ( \ + dd if=$(KDIR)/vmlinux-$(2).uImage bs=896k conv=sync; \ + dd if=$(KDIR)/root.$(1) bs=2752k conv=sync; \ + echo -n "AP91-AR7240-RT-090223-00"; \ + ) > $(call imgname,$(1),$(2))-universal.bin; \ + fi; fi +endef + +dir825b1_mtdlayout=mtdparts=spi0.0:256k(uboot)ro,64k(config)ro,1024k(kernel),5184k(rootfs),64k(caldata)ro,1600k(unknown)ro,6208k@0x50000(firmware) +define Image/Build/DIR825B1 + $(call PatchKernelLzma,$(2),$(3) $(dir825b1_mtdlayout)) + $(call MkImageLzma,$(KDIR)/vmlinux-$(2).bin.lzma,$(call imgname,$(1),$(2)).bin) + if [ `stat -c%s "$(call imgname,$(1),$(2)).bin"` -gt 1048576 ]; then \ + echo "Warning: $(KDIR)/vmlinux-$(2).bin.lzma is too big"; \ + rm -f $(call imgname,$(1),$(2)).bin; \ + else if [ `stat -c%s $(KDIR)/root.$(1)` -gt 5308416 ]; then \ + echo "Warning: $(KDIR)/root.$(1) is too big"; \ + rm -f $(call imgname,$(1),$(2)).bin; \ + else \ + dd if=$(KDIR)/root.$(1) of=$(call imgname,$(1),$(2)).bin bs=1k seek=1024; \ + cp $(call imgname,$(1),$(2)).bin $(call imgname,$(1),$(2))-backup-loader.bin; \ + echo -n "01AP94-AR7161-RT-080619-00" >> $(call imgname,$(1),$(2))-backup-loader.bin; \ + fi; fi +endef + cameo_mtdlayout=mtdparts=spi0.0:128k(u-boot)ro,64k(config)ro,896k(kernel),2880k(rootfs),64k(art)ro,3776k@0x30000(firmware) define Image/Build/Cameo $(call PatchKernelLzma,$(2),$(3) $(cameo_mtdlayout)) @@ -116,10 +153,22 @@ define Image/Build/AP83 ( \ dd if=$(KDIR)/vmlinux-$(2).uImage bs=1280k conv=sync; \ dd if=$(KDIR)/root.$(1); \ - ) > $(call imgname,$(1),$(2)-firmware).bin; \ + ) > $(call imgname,$(1),$(2))-sysupgrade.bin; \ fi; fi endef +define Image/Build/PB4X + $(call PatchKernelLzma,$(2),$(3)) + dd if=$(KDIR)/vmlinux-$(2).bin.lzma \ + of=$(call imgname,kernel,$(2)).bin bs=64k conv=sync + dd if=$(KDIR)/root.$(1) \ + of=$(call imgname,$(1),$(2)-rootfs).bin bs=128k conv=sync + -sh $(TOPDIR)/scripts/combined-image.sh \ + "$(call imgname,kernel,$(2)).bin" \ + "$(call imgname,$(1),$(2)-rootfs).bin" \ + $(call imgname,$(1),$(2))-sysupgrade.bin +endef + define Image/Build/MyLoader -$(STAGING_DIR_HOST)/bin/mkmylofw -B $(2) \ -p0x030000:0xd0000:al:0x80060000:kernel:$(KDIR)/vmlinux.bin.lzma \ @@ -220,8 +269,7 @@ wndr3700_mtdlayout=mtdparts=spi0.0:320k(u-boot)ro,128k(u-boot-env)ro,1024k(kerne define Image/Build/WNDR3700 $(call PatchKernelLzma,$(2),$(3) $(wndr3700_mtdlayout)) $(call MkImageLzma,$(KDIR)/vmlinux-$(2).bin.lzma,$(KDIR)/vmlinux-$(2).uImage) - mkdir $(KDIR)/wndr3700 - mkdir $(KDIR)/wndr3700/image + mkdir -p $(KDIR)/wndr3700/image $(STAGING_DIR_HOST)/bin/wndr3700 \ $(KDIR)/vmlinux-$(2).uImage \ $(KDIR)/wndr3700/image/uImage @@ -248,168 +296,100 @@ define Image/Build/WNDR3700 -o $(call imgname,$(1),$(2))-factory.img endef -define Image/Build/Template/Compex - $(call Image/Build/MyLoader,$(1),$(2)) +define Image/Build/Template/all/squashfs + $(call Image/Build/$(1),squashfs,$(2),$(3),$(4),$(5),$(6),$(7)) endef -define Image/Build/Template/Compex/squashfs - $(call Image/Build/Template/Compex,squashfs,$(1)) +define Image/Build/Template/all/jffs2-64k + $(call Image/Build/$(1),jffs2-64k,$(2),$(3),$(4),$(5),$(6),$(7)) endef -define Image/Build/Template/WRT400N - $(call Image/Build/WRT400N,$(1),$(2),$(3),$(4)) +define Image/Build/Template/all/jffs2-128k + $(call Image/Build/$(1),jffs2-128k,$(2),$(3),$(4),$(5),$(6),$(7)) endef -define Image/Build/Template/WRT400N/squashfs - $(call Image/Build/Template/WRT400N,squashfs,$(1),$(2),$(3)) +define Image/Build/Template/squashfs-only/squashfs + $(call Image/Build/$(1),squashfs,$(2),$(3),$(4),$(5),$(6),$(7)) endef -define Image/Build/Template/WRT400N/jffs2-64k - $(call Image/Build/Template/WRT400N,jffs2-64k,$(1),$(2),$(3)) +define Image/Build/Template/64k/squashfs + $(call Image/Build/$(1),squashfs,$(2),$(3),$(4),$(5),$(6),$(7)) endef -define Image/Build/Template/CyberTAN - $(call Image/Build/CyberTAN,$(1),$(2),$(3),$(4)) +define Image/Build/Template/64k/jffs2-64k + $(call Image/Build/$(1),jffs2-64k,$(2),$(3),$(4),$(5),$(6),$(7)) endef -define Image/Build/Template/CyberTAN/squashfs - $(call Image/Build/Template/CyberTAN,squashfs,$(1),$(2),$(3)) +define Image/Build/Template/128k/squashfs + $(call Image/Build/$(1),squashfs,$(2),$(3),$(4),$(5),$(6),$(7)) endef -define Image/Build/Template/CyberTAN/jffs2-64k - $(call Image/Build/Template/CyberTAN,jffs2-64k,$(1),$(2),$(3)) +define Image/Build/Template/128k/jffs2-128k + $(call Image/Build/$(1),jffs2-128k,$(2),$(3),$(4),$(5),$(6),$(7)) endef -define Image/Build/Template/Cameo - $(call Image/Build/Cameo,$(1),$(2),$(3),$(4)) -endef - -define Image/Build/Template/Cameo/squashfs - $(call Image/Build/Template/Cameo,squashfs,$(1),$(2),$(3)) -endef - -define Image/Build/Template/AP83 - $(call Image/Build/AP83,$(1),$(2),$(3)) -endef - -define Image/Build/Template/AP83/squashfs - $(call Image/Build/Template/AP83,squashfs,$(1),$(2)) -endef - -define Image/Build/Template/AP83/jffs2-64k - $(call Image/Build/Template/AP83,jffs2-64k,$(1),$(2)) -endef - -define Image/Build/Template/TPLINK - $(call Image/Build/TPLINK,$(1),$(2),$(3),$(4)) -endef - -define Image/Build/Template/TPLINK/squashfs - $(call Image/Build/Template/TPLINK,squashfs,$(1),$(2),$(3)) -endef - -define Image/Build/Template/TPLINK4K - $(call Image/Build/TPLINK,$(1),$(2),$(3),$(4)) -endef - -define Image/Build/Template/TPLINK4K/squashfs - $(call Image/Build/Template/TPLINK,squashfs,$(1),$(2),$(3)) -endef - -define Image/Build/Template/UBNT - $(call Image/Build/UBNT,$(1),$(2),$(3),$(4),$(5),$(6)) -endef - -define Image/Build/Template/UBNT/squashfs - $(call Image/Build/Template/UBNT,squashfs,$(1),$(2),$(3),$(4),$(5)) -endef - -define Image/Build/Template/UBNT/jffs2-64k - $(call Image/Build/Template/UBNT,jffs2-64k,$(1),$(2),$(3),$(4),$(5)) -endef - -define Image/Build/Template/UBNTXM - $(call Image/Build/UBNTXM,$(1),$(2),$(3),$(4),$(5),$(6)) -endef - -define Image/Build/Template/UBNTXM/squashfs - $(call Image/Build/Template/UBNTXM,squashfs,$(1),$(2),$(3),$(4),$(5)) -endef - -define Image/Build/Template/UBNTXM/jffs2-64k - $(call Image/Build/Template/UBNTXM,jffs2-64k,$(1),$(2),$(3),$(4),$(5)) -endef - -define Image/Build/Template/Planex - $(call Image/Build/Planex,$(1),$(2),$(3)) -endef - -define Image/Build/Template/Planex/squashfs - $(call Image/Build/Template/Planex,squashfs,$(1),$(2)) -endef - -define Image/Build/Template/Planex/jffs2-64k - $(call Image/Build/Template/Planex,jffs2-64k,$(1),$(2)) -endef - -define Image/Build/Template/WNDR3700 - $(call Image/Build/WNDR3700,$(1),$(2),$(3)) -endef - -define Image/Build/Template/WNDR3700/squashfs - $(call Image/Build/Template/WNDR3700,squashfs,$(1),$(2)) -endef - -define Image/Build/Template/WNDR3700/jffs2-64k - $(call Image/Build/Template/WNDR3700,jffs2-64k,$(1),$(2)) +define Image/Build/Profile/AP81 + $(call Image/Build/Template/64k/$(1),AP83,ap81,board=AP81) endef define Image/Build/Profile/AP83 - $(call Image/Build/Template/AP83/$(1),ap83,board=AP83) + $(call Image/Build/Template/64k/$(1),AP83,ap83,board=AP83) +endef + +define Image/Build/Profile/PB42 + $(call Image/Build/Template/64k/$(1),PB4X,pb42,board=PB42) +endef + +define Image/Build/Profile/PB44 + $(call Image/Build/Template/64k/$(1),PB4X,pb44,board=PB44) endef define Image/Build/Profile/WP543 - $(call Image/Build/Template/Compex/$(1),wp543) + $(call Image/Build/Template/64k/$(1),MyLoader,wp543) +endef + +define Image/Build/Profile/DIR600A1 + $(call Image/Build/Template/64k/$(1),DIR600A1,dir-600-a1,board=DIR-600-A1) endef define Image/Build/Profile/DIR615C1 - $(call Image/Build/Template/Cameo/$(1),dir-615c1,board=TEW-632BRP,"AP81-AR9130-RT-070614-02") + $(call Image/Build/Template/squashfs-only/$(1),Cameo,dir-615-c1,board=DIR-615-C1,"AP81-AR9130-RT-070614-02") endef define Image/Build/Profile/TEW632BRP - $(call Image/Build/Template/Cameo/$(1),tew-632brp,board=TEW-632BRP,"AP81-AR9130-RT-070614-00") + $(call Image/Build/Template/squashfs-only/$(1),Cameo,tew-632brp,board=TEW-632BRP,"AP81-AR9130-RT-070614-00") endef define Image/Build/Profile/TEW652BRP - $(call Image/Build/Template/Cameo/$(1),tew-652brp,board=TEW-632BRP,"AP81-AR9130-RT-080609-05") + $(call Image/Build/Template/squashfs-only/$(1),Cameo,tew-652brp,board=TEW-632BRP,"AP81-AR9130-RT-080609-05") endef define Image/Build/Profile/A02RBW300N - $(call Image/Build/Template/Cameo/$(1),a02-rb-w300n,board=TEW-632BRP,"AP81-AR9130-RT-070614-03") + $(call Image/Build/Template/squashfs-only/$(1),Cameo,a02-rb-w300n,board=TEW-632BRP,"AP81-AR9130-RT-070614-03") endef define Image/Build/Profile/UBNTRS - $(call Image/Build/Template/UBNT/$(1),ubnt-rs,board=UBNT-RS,RS,RSx,ar7100) + $(call Image/Build/Template/64k/$(1),UBNT,ubnt-rs,board=UBNT-RS,RS,RSx,ar7100) endef define Image/Build/Profile/UBNTRSPRO - $(call Image/Build/Template/UBNT/$(1),ubnt-rspro,board=UBNT-RSPRO,RSPRO,RSPRO,ar7100pro) + $(call Image/Build/Template/64k/$(1),UBNT,ubnt-rspro,board=UBNT-RSPRO,RSPRO,RSPRO,ar7100pro) endef define Image/Build/Profile/UBNTLSSR71 - $(call Image/Build/Template/UBNT/$(1),ubnt-ls-sr71,board=UBNT-LS-SR71,LS-SR71,LS-SR71,ar7100) + $(call Image/Build/Template/64k/$(1),UBNT,ubnt-ls-sr71,board=UBNT-LS-SR71,LS-SR71,LS-SR71,ar7100) endef define Image/Build/Profile/UBNTBULLETM - $(call Image/Build/Template/UBNTXM/$(1),ubnt-bullet-m,board=UBNT-BM,XM,UBNTXM,ar7240) + $(call Image/Build/Template/64k/$(1),UBNTXM,ubnt-bullet-m,board=UBNT-BM,XM,UBNTXM,ar7240) endef define Image/Build/Profile/UBNTROCKETM - $(call Image/Build/Template/UBNTXM/$(1),ubnt-rocket-m,board=UBNT-RM,XM,UBNTXM,ar7240) + $(call Image/Build/Template/64k/$(1),UBNTXM,ubnt-rocket-m,board=UBNT-RM,XM,UBNTXM,ar7240) endef define Image/Build/Profile/UBNTNANOM - $(call Image/Build/Template/UBNTXM/$(1),ubnt-nano-m,board=UBNT-NM,XM,UBNTXM,ar7240) + $(call Image/Build/Template/64k/$(1),UBNTXM,ubnt-nano-m,board=UBNT-NM,XM,UBNTXM,ar7240) endef define Image/Build/Profile/UBNT @@ -422,53 +402,72 @@ define Image/Build/Profile/UBNT endef define Image/Build/Profile/MZKW04NU - $(call Image/Build/Template/Planex/$(1),mzk-w04nu,board=MZK-W04NU) + $(call Image/Build/Template/64k/$(1),Planex,mzk-w04nu,board=MZK-W04NU) endef define Image/Build/Profile/MZKW300NH - $(call Image/Build/Template/Planex/$(1),mzk-w300nh,board=MZK-W300NH) + $(call Image/Build/Template/64k/$(1),Planex,mzk-w300nh,board=MZK-W300NH) endef define Image/Build/Profile/TLWR741NDV1 - $(call Image/Build/Template/TPLINK4K/$(1),tl-wr741ndv1,board=TL-WR741ND,TL-WR741NDv1) + $(call Image/Build/Template/squashfs-only/$(1),TPLINK4K,tl-wr741nd-v1,board=TL-WR741ND,TL-WR741NDv1) +endef + +define Image/Build/Profile/TLWR841NV15 + $(call Image/Build/Template/squashfs-only/$(1),TPLINK,tl-wr841n-v1.5,board=TL-WR841N-v1.5,TL-WR841Nv1.5) endef define Image/Build/Profile/TLWR841NDV3 - $(call Image/Build/Template/TPLINK/$(1),tl-wr841ndv3,board=TL-WR941ND,TL-WR841NDv3) + $(call Image/Build/Template/squashfs-only/$(1),TPLINK,tl-wr841nd-v3,board=TL-WR941ND,TL-WR841NDv3) endef define Image/Build/Profile/TLWR841NDV5 - $(call Image/Build/Template/TPLINK4K/$(1),tl-wr841ndv5,board=TL-WR741ND,TL-WR841NDv5) + $(call Image/Build/Template/squashfs-only/$(1),TPLINK4K,tl-wr841nd-v5,board=TL-WR741ND,TL-WR841NDv5) endef define Image/Build/Profile/TLWR941NDV2 - $(call Image/Build/Template/TPLINK/$(1),tl-wr941ndv2,board=TL-WR941ND,TL-WR941NDv2) + $(call Image/Build/Template/squashfs-only/$(1),TPLINK,tl-wr941nd-v2,board=TL-WR941ND,TL-WR941NDv2) +endef + +define Image/Build/Profile/TLWR1043NDV1 + $(call Image/Build/Template/squashfs-only/$(1),TPLINK,tl-wr1043nd-v1,board=TL-WR1043ND,TL-WR1043NDv1) endef define Image/Build/Profile/WNDR3700 - $(call Image/Build/Template/WNDR3700/$(1),wndr3700,board=WNDR3700) + $(call Image/Build/Template/64k/$(1),WNDR3700,wndr3700,board=WNDR3700) endef define Image/Build/Profile/WRT400N - $(call Image/Build/Template/WRT400N/$(1),wrt400n,board=WRT400N) + $(call Image/Build/Template/64k/$(1),WRT400N,wrt400n,board=WRT400N) +endef + +define Image/Build/Profile/DIR825B1 + $(call Image/Build/Template/64k/$(1),DIR825B1,dir-825-b1,board=DIR-825-B1) endef define Image/Build/Profile/WRT160NL - $(call Image/Build/Template/CyberTAN/$(1),wrt160nl,board=WRT160NL,1.00.01) + $(call Image/Build/Template/64k/$(1),CyberTAN,wrt160nl,board=WRT160NL,1.00.01) endef define Image/Build/Profile/Default + $(call Image/Build/Profile/AP81,$(1)) $(call Image/Build/Profile/AP83,$(1)) $(call Image/Build/Profile/A02RBW300N,$(1)) + $(call Image/Build/Profile/DIR600A1,$(1)) $(call Image/Build/Profile/DIR615C1,$(1)) + $(call Image/Build/Profile/DIR825B1,$(1)) $(call Image/Build/Profile/MZKW04NU,$(1)) $(call Image/Build/Profile/MZKW300NH,$(1)) + $(call Image/Build/Profile/PB42,$(1)) + $(call Image/Build/Profile/PB44,$(1)) $(call Image/Build/Profile/TEW632BRP,$(1)) $(call Image/Build/Profile/TEW652BRP,$(1)) $(call Image/Build/Profile/TLWR741NDV1,$(1)) + $(call Image/Build/Profile/TLWR841NV15,$(1)) $(call Image/Build/Profile/TLWR841NDV3,$(1)) $(call Image/Build/Profile/TLWR841NDV5,$(1)) $(call Image/Build/Profile/TLWR941NDV2,$(1)) + $(call Image/Build/Profile/TLWR1043NDV1,$(1)) $(call Image/Build/Profile/UBNT,$(1)) $(call Image/Build/Profile/WP543,$(1)) $(call Image/Build/Profile/WNDR3700,$(1)) diff --git a/target/linux/ar71xx/patches-2.6.28/102-mtd_m25p80_add_myloader_parser.patch b/target/linux/ar71xx/patches-2.6.28/102-mtd_m25p80_add_myloader_parser.patch deleted file mode 100644 index 65e9154d2..000000000 --- a/target/linux/ar71xx/patches-2.6.28/102-mtd_m25p80_add_myloader_parser.patch +++ /dev/null @@ -1,22 +0,0 @@ ---- a/drivers/mtd/devices/m25p80.c -+++ b/drivers/mtd/devices/m25p80.c -@@ -711,12 +711,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; diff --git a/target/linux/ar71xx/patches-2.6.28/104-mtd_m25p80_add_redboot_parser.patch b/target/linux/ar71xx/patches-2.6.28/104-mtd_m25p80_add_redboot_parser.patch deleted file mode 100644 index 462ae6879..000000000 --- a/target/linux/ar71xx/patches-2.6.28/104-mtd_m25p80_add_redboot_parser.patch +++ /dev/null @@ -1,12 +0,0 @@ ---- a/drivers/mtd/devices/m25p80.c -+++ b/drivers/mtd/devices/m25p80.c -@@ -722,6 +722,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, diff --git a/target/linux/ar71xx/patches-2.6.30/120-dsa-trailer-tag-validation-fix.patch b/target/linux/ar71xx/patches-2.6.30/120-dsa-trailer-tag-validation-fix.patch new file mode 100644 index 000000000..b58aeedc3 --- /dev/null +++ b/target/linux/ar71xx/patches-2.6.30/120-dsa-trailer-tag-validation-fix.patch @@ -0,0 +1,11 @@ +--- a/net/dsa/tag_trailer.c ++++ b/net/dsa/tag_trailer.c +@@ -86,7 +86,7 @@ static int trailer_rcv(struct sk_buff *s + + trailer = skb_tail_pointer(skb) - 4; + if (trailer[0] != 0x80 || (trailer[1] & 0xf8) != 0x00 || +- (trailer[3] & 0xef) != 0x00 || trailer[3] != 0x00) ++ (trailer[2] & 0xef) != 0x00 || (trailer[3] & 0xfe) != 0x00) + goto out_drop; + + source_port = trailer[1] & 7; diff --git a/target/linux/ar71xx/patches-2.6.30/121-dsa-add-88e6063-driver.patch b/target/linux/ar71xx/patches-2.6.30/121-dsa-add-88e6063-driver.patch new file mode 100644 index 000000000..1a11a69c6 --- /dev/null +++ b/target/linux/ar71xx/patches-2.6.30/121-dsa-add-88e6063-driver.patch @@ -0,0 +1,26 @@ +--- a/net/dsa/Kconfig ++++ b/net/dsa/Kconfig +@@ -36,6 +36,13 @@ config NET_DSA_MV88E6060 + This enables support for the Marvell 88E6060 ethernet switch + chip. + ++config NET_DSA_MV88E6063 ++ bool "Marvell 88E6063 ethernet switch chip support" ++ select NET_DSA_TAG_TRAILER ++ ---help--- ++ This enables support for the Marvell 88E6063 ethernet switch ++ chip ++ + config NET_DSA_MV88E6XXX_NEED_PPU + bool + default n +--- a/net/dsa/Makefile ++++ b/net/dsa/Makefile +@@ -6,6 +6,7 @@ obj-$(CONFIG_NET_DSA_TAG_TRAILER) += tag + # switch drivers + obj-$(CONFIG_NET_DSA_MV88E6XXX) += mv88e6xxx.o + obj-$(CONFIG_NET_DSA_MV88E6060) += mv88e6060.o ++obj-$(CONFIG_NET_DSA_MV88E6063) += mv88e6063.o + obj-$(CONFIG_NET_DSA_MV88E6123_61_65) += mv88e6123_61_65.o + obj-$(CONFIG_NET_DSA_MV88E6131) += mv88e6131.o + diff --git a/target/linux/ar71xx/patches-2.6.30/204-rtl8366-smi-driver.patch b/target/linux/ar71xx/patches-2.6.30/204-rtl8366-smi-driver.patch new file mode 100644 index 000000000..77874b49f --- /dev/null +++ b/target/linux/ar71xx/patches-2.6.30/204-rtl8366-smi-driver.patch @@ -0,0 +1,21 @@ +--- a/drivers/net/phy/Kconfig ++++ b/drivers/net/phy/Kconfig +@@ -140,4 +140,8 @@ config MDIO_GPIO + To compile this driver as a module, choose M here: the module + will be called mdio-gpio. + ++config RTL8366_SMI ++ tristate "Support for RTL8366 switch via SMI interface" ++ depends on GENERIC_GPIO ++ + endif # PHYLIB +--- a/drivers/net/phy/Makefile ++++ b/drivers/net/phy/Makefile +@@ -19,6 +19,7 @@ obj-$(CONFIG_IP175C_PHY) += ip175c.o + obj-$(CONFIG_REALTEK_PHY) += realtek.o + obj-$(CONFIG_AR8216_PHY) += ar8216.o + obj-$(CONFIG_RTL8306_PHY) += rtl8306.o ++obj-$(CONFIG_RTL8366_SMI) += rtl8366_smi.o + obj-$(CONFIG_LSI_ET1011C_PHY) += et1011c.o + obj-$(CONFIG_MICREL) += micrel.o + obj-$(CONFIG_FIXED_PHY) += fixed.o diff --git a/target/linux/ar71xx/patches-2.6.30/205-wndr3700-usb-led-driver.patch b/target/linux/ar71xx/patches-2.6.30/205-wndr3700-usb-led-driver.patch new file mode 100644 index 000000000..8284f9a03 --- /dev/null +++ b/target/linux/ar71xx/patches-2.6.30/205-wndr3700-usb-led-driver.patch @@ -0,0 +1,26 @@ +--- a/drivers/leds/Kconfig ++++ b/drivers/leds/Kconfig +@@ -227,6 +227,13 @@ config LEDS_BD2802 + This option enables support for BD2802GU RGB LED driver chips + accessed via the I2C bus. + ++config LEDS_WNDR3700_USB ++ tristate "NETGEAR WNDR3700 USB LED driver" ++ depends on LEDS_CLASS && AR71XX_MACH_WNDR3700 ++ help ++ This option enables support for the USB LED found on the ++ NETGEAR WNDR3700 board. ++ + comment "LED Triggers" + + config LEDS_TRIGGERS +--- a/drivers/leds/Makefile ++++ b/drivers/leds/Makefile +@@ -27,6 +27,7 @@ obj-$(CONFIG_LEDS_PCA955X) += leds-pca9 + obj-$(CONFIG_LEDS_DA903X) += leds-da903x.o + obj-$(CONFIG_LEDS_WM8350) += leds-wm8350.o + obj-$(CONFIG_LEDS_PWM) += leds-pwm.o ++obj-${CONFIG_LEDS_WNDR3700_USB} += leds-wndr3700-usb.o + + # LED SPI Drivers + obj-$(CONFIG_LEDS_DAC124S085) += leds-dac124s085.o diff --git a/target/linux/ar71xx/patches-2.6.30/400-mips-multi-machine-update.patch b/target/linux/ar71xx/patches-2.6.30/400-mips-multi-machine-update.patch new file mode 100644 index 000000000..78646210e --- /dev/null +++ b/target/linux/ar71xx/patches-2.6.30/400-mips-multi-machine-update.patch @@ -0,0 +1,128 @@ +--- a/arch/mips/kernel/mips_machine.c ++++ b/arch/mips/kernel/mips_machine.c +@@ -7,12 +7,13 @@ + * + */ + #include ++#include + + #include +-#include + + static struct list_head mips_machines __initdata = + LIST_HEAD_INIT(mips_machines); ++static char *mips_machid __initdata; + + char *mips_machine_name = "Unknown"; + +@@ -55,20 +56,65 @@ void __init mips_machine_set_name(char * + } + } + +-void __init mips_machine_setup(unsigned long machtype) ++void __init mips_machine_setup(void) + { + struct mips_machine *mach; + +- mach = mips_machine_find(machtype); ++ mach = mips_machine_find(mips_machtype); + if (!mach) { +- printk(KERN_ALERT "MIPS: no machine registered for " +- "machtype %lu\n", machtype); ++ printk(KERN_WARNING "MIPS: no machine registered for " ++ "machtype %lu\n", mips_machtype); + return; + } + + mips_machine_set_name(mach->mach_name); +- printk(KERN_INFO "MIPS: machine is %s\n", mips_machine_name); ++ printk(KERN_NOTICE "MIPS: machine is %s\n", mips_machine_name); + + if (mach->mach_setup) + mach->mach_setup(); + } ++ ++int __init mips_machtype_setup(char *id) ++{ ++ if (mips_machid == NULL) ++ mips_machid = id; ++ ++ return 1; ++} ++ ++__setup("machtype=", mips_machtype_setup); ++ ++static int __init mips_machtype_init(void) ++{ ++ struct list_head *this; ++ struct mips_machine *mach; ++ ++ if (mips_machid == NULL) ++ return 0; ++ ++ list_for_each(this, &mips_machines) { ++ mach = list_entry(this, struct mips_machine, list); ++ if (mach->mach_id == NULL) ++ continue; ++ ++ if (strcmp(mach->mach_id, mips_machid) == 0) { ++ mips_machtype = mach->mach_type; ++ return 0; ++ } ++ } ++ ++ printk(KERN_WARNING ++ "MIPS: no machine found for id: '%s', registered machines:\n", ++ mips_machid); ++ printk(KERN_WARNING "%32s %s\n", "id", "name"); ++ ++ list_for_each(this, &mips_machines) { ++ mach = list_entry(this, struct mips_machine, list); ++ printk(KERN_WARNING "%32s %s\n", ++ mach->mach_id ? mach->mach_id : "", mach->mach_name); ++ } ++ ++ return 0; ++} ++ ++core_initcall(mips_machtype_init); +--- a/include/asm-mips/mips_machine.h ++++ b/include/asm-mips/mips_machine.h +@@ -13,24 +13,32 @@ + #include + #include + ++#include ++ + struct mips_machine { + unsigned long mach_type; +- void (*mach_setup)(void); ++ char *mach_id; + char *mach_name; ++ void (*mach_setup)(void); + struct list_head list; + }; + + void mips_machine_register(struct mips_machine *) __init; +-void mips_machine_setup(unsigned long machtype) __init; ++void mips_machine_setup(void) __init; ++int mips_machtype_setup(char *id) __init; + void mips_machine_set_name(char *name) __init; + + extern char *mips_machine_name; + +-#define MIPS_MACHINE(_type, _name, _setup) \ +-static char machine_name_##_type[] __initdata = _name; \ +-static struct mips_machine machine_##_type __initdata = \ ++#define MIPS_MACHINE(_type, _id, _name, _setup) \ ++static char machine_name_##_type[] __initconst \ ++ __aligned(1) = _name; \ ++static char machine_id_##_type[] __initconst \ ++ __aligned(1) = _id; \ ++static struct mips_machine machine_##_type __initconst = \ + { \ + .mach_type = _type, \ ++ .mach_id = machine_id_##_type, \ + .mach_name = machine_name_##_type, \ + .mach_setup = _setup, \ + }; \ diff --git a/target/linux/ar71xx/patches-2.6.30/800-ag71xx-remove-netdev-arg-from-napi-calls.patch b/target/linux/ar71xx/patches-2.6.30/800-ag71xx-remove-netdev-arg-from-napi-calls.patch deleted file mode 100644 index aca39a431..000000000 --- a/target/linux/ar71xx/patches-2.6.30/800-ag71xx-remove-netdev-arg-from-napi-calls.patch +++ /dev/null @@ -1,38 +0,0 @@ ---- a/drivers/net/ag71xx/ag71xx_main.c -+++ b/drivers/net/ag71xx/ag71xx_main.c -@@ -575,7 +575,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) -@@ -731,7 +731,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); -@@ -750,7 +750,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; - } - -@@ -780,7 +780,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; diff --git a/target/linux/ar71xx/patches-2.6.30/801-ag71xx-remove-redundant-napi-functions.patch b/target/linux/ar71xx/patches-2.6.30/801-ag71xx-remove-redundant-napi-functions.patch deleted file mode 100644 index 65a02bc12..000000000 --- a/target/linux/ar71xx/patches-2.6.30/801-ag71xx-remove-redundant-napi-functions.patch +++ /dev/null @@ -1,38 +0,0 @@ ---- a/drivers/net/ag71xx/ag71xx_main.c -+++ b/drivers/net/ag71xx/ag71xx_main.c -@@ -575,7 +575,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(&ag->napi); -+ napi_schedule(&ag->napi); - } - - static void ag71xx_tx_timeout(struct net_device *dev) -@@ -731,7 +731,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(napi); -+ napi_complete(napi); - - /* enable interrupts */ - spin_lock_irqsave(&ag->lock, flags); -@@ -750,7 +750,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(napi); -+ napi_complete(napi); - return 0; - } - -@@ -780,7 +780,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(&ag->napi); -+ napi_schedule(&ag->napi); - } - - return IRQ_HANDLED; diff --git a/target/linux/ar71xx/patches-2.6.30/802-ag71xx-use-netdev-ops.patch b/target/linux/ar71xx/patches-2.6.30/802-ag71xx-use-netdev-ops.patch deleted file mode 100644 index 6f291711e..000000000 --- a/target/linux/ar71xx/patches-2.6.30/802-ag71xx-use-netdev-ops.patch +++ /dev/null @@ -1,37 +0,0 @@ ---- a/drivers/net/ag71xx/ag71xx_main.c -+++ b/drivers/net/ag71xx/ag71xx_main.c -@@ -791,6 +791,18 @@ static void ag71xx_set_multicast_list(st - /* TODO */ - } - -+static const struct net_device_ops ag71xx_netdev_ops = { -+ .ndo_open = ag71xx_open, -+ .ndo_stop = ag71xx_stop, -+ .ndo_start_xmit = ag71xx_hard_start_xmit, -+ .ndo_set_multicast_list = ag71xx_set_multicast_list, -+ .ndo_do_ioctl = ag71xx_do_ioctl, -+ .ndo_tx_timeout = ag71xx_tx_timeout, -+ .ndo_change_mtu = eth_change_mtu, -+ .ndo_set_mac_address = eth_mac_addr, -+ .ndo_validate_addr = eth_validate_addr, -+}; -+ - static int __init ag71xx_probe(struct platform_device *pdev) - { - struct net_device *dev; -@@ -861,14 +873,9 @@ static int __init ag71xx_probe(struct pl - } - - dev->base_addr = (unsigned long)ag->mac_base; -- dev->open = ag71xx_open; -- dev->stop = ag71xx_stop; -- dev->hard_start_xmit = ag71xx_hard_start_xmit; -- dev->set_multicast_list = ag71xx_set_multicast_list; -- dev->do_ioctl = ag71xx_do_ioctl; -+ dev->netdev_ops = &ag71xx_netdev_ops; - dev->ethtool_ops = &ag71xx_ethtool_ops; - -- dev->tx_timeout = ag71xx_tx_timeout; - INIT_WORK(&ag->restart_work, ag71xx_restart_work_func); - - init_timer(&ag->oom_timer); diff --git a/target/linux/ar71xx/patches-2.6.30/803-ar71xx-update-dsa-switch-support.patch b/target/linux/ar71xx/patches-2.6.30/803-ar71xx-update-dsa-switch-support.patch deleted file mode 100644 index 245c9f35c..000000000 --- a/target/linux/ar71xx/patches-2.6.30/803-ar71xx-update-dsa-switch-support.patch +++ /dev/null @@ -1,46 +0,0 @@ ---- a/arch/mips/ar71xx/devices.c -+++ b/arch/mips/ar71xx/devices.c -@@ -780,6 +780,8 @@ static struct platform_device ar71xx_dsa - void __init ar71xx_add_device_dsa(unsigned int id, - struct dsa_platform_data *d) - { -+ int i; -+ - switch (id) { - case 0: - d->netdev = &ar71xx_eth0_device.dev; -@@ -793,7 +795,10 @@ void __init ar71xx_add_device_dsa(unsign - id); - return; - } -- d->mii_bus = &ar71xx_mdio_device.dev; -+ -+ for (i = 0; i < d->nr_chips; i++) -+ d->chip[i].mii_bus = &ar71xx_mdio_device.dev; -+ - ar71xx_dsa_switch_device.dev.platform_data = d; - - platform_device_register(&ar71xx_dsa_switch_device); ---- a/arch/mips/ar71xx/mach-tl-wr941nd.c -+++ b/arch/mips/ar71xx/mach-tl-wr941nd.c -@@ -104,7 +104,7 @@ static struct gpio_button tl_wr941nd_gpi - } - }; - --static struct dsa_platform_data tl_wr941nd_dsa_data = { -+static struct dsa_chip_data tl_wr941nd_dsa_chip = { - .port_names[0] = "wan", - .port_names[1] = "lan1", - .port_names[2] = "lan2", -@@ -113,6 +113,11 @@ static struct dsa_platform_data tl_wr941 - .port_names[5] = "cpu", - }; - -+static struct dsa_platform_data tl_wr941nd_dsa_data = { -+ .nr_chips = 1, -+ .chip = &tl_wr941nd_dsa_chip, -+}; -+ - static void __init tl_wr941nd_setup(void) - { - u8 *mac = (u8 *) KSEG1ADDR(0x1f01fc00); diff --git a/target/linux/ar71xx/patches-2.6.31/003-ar71xx_usb_host.patch b/target/linux/ar71xx/patches-2.6.31/003-ar71xx_usb_host.patch index c2f14b2af..0294faf99 100644 --- a/target/linux/ar71xx/patches-2.6.31/003-ar71xx_usb_host.patch +++ b/target/linux/ar71xx/patches-2.6.31/003-ar71xx_usb_host.patch @@ -30,7 +30,7 @@ depends on USB_OHCI_HCD && (STB03xxx || PPC_MPC52xx) --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c -@@ -1117,6 +1117,11 @@ MODULE_LICENSE ("GPL"); +@@ -1119,6 +1119,11 @@ MODULE_LICENSE ("GPL"); #define PLATFORM_DRIVER ixp4xx_ehci_driver #endif @@ -44,7 +44,7 @@ #error "missing bus glue for ehci-hcd" --- a/drivers/usb/host/ohci-hcd.c +++ b/drivers/usb/host/ohci-hcd.c -@@ -1081,6 +1081,11 @@ MODULE_LICENSE ("GPL"); +@@ -1086,6 +1086,11 @@ MODULE_LICENSE ("GPL"); #define TMIO_OHCI_DRIVER ohci_hcd_tmio_driver #endif diff --git a/target/linux/ar71xx/patches-2.6.31/108-mtd_fix_cfi_cmdset_0002_erase_status_check.patch b/target/linux/ar71xx/patches-2.6.31/108-mtd_fix_cfi_cmdset_0002_erase_status_check.patch index 3f25b61dd..22aefe0d4 100644 --- a/target/linux/ar71xx/patches-2.6.31/108-mtd_fix_cfi_cmdset_0002_erase_status_check.patch +++ b/target/linux/ar71xx/patches-2.6.31/108-mtd_fix_cfi_cmdset_0002_erase_status_check.patch @@ -1,6 +1,6 @@ --- a/drivers/mtd/chips/cfi_cmdset_0002.c +++ b/drivers/mtd/chips/cfi_cmdset_0002.c -@@ -1579,7 +1579,7 @@ static int __xipram do_erase_chip(struct +@@ -1568,7 +1568,7 @@ static int __xipram do_erase_chip(struct chip->erase_suspended = 0; } @@ -9,7 +9,7 @@ break; if (time_after(jiffies, timeo)) { -@@ -1667,7 +1667,7 @@ static int __xipram do_erase_oneblock(st +@@ -1656,7 +1656,7 @@ static int __xipram do_erase_oneblock(st chip->erase_suspended = 0; } diff --git a/target/linux/ar71xx/patches-2.6.31/110-usb-ehci-add-war-for-synopsys-hc-bug.patch b/target/linux/ar71xx/patches-2.6.31/110-usb-ehci-add-war-for-synopsys-hc-bug.patch index a61499965..2e607ab23 100644 --- a/target/linux/ar71xx/patches-2.6.31/110-usb-ehci-add-war-for-synopsys-hc-bug.patch +++ b/target/linux/ar71xx/patches-2.6.31/110-usb-ehci-add-war-for-synopsys-hc-bug.patch @@ -1,6 +1,6 @@ --- a/drivers/usb/host/ehci-q.c +++ b/drivers/usb/host/ehci-q.c -@@ -1128,6 +1128,9 @@ static void end_unlink_async (struct ehc +@@ -1140,6 +1140,9 @@ static void end_unlink_async (struct ehc ehci->reclaim = NULL; start_unlink_async (ehci, next); } @@ -12,10 +12,10 @@ /* makes sure the async qh will become idle */ --- a/drivers/usb/host/ehci.h +++ b/drivers/usb/host/ehci.h -@@ -126,6 +126,7 @@ struct ehci_hcd { /* one per controlle - unsigned big_endian_mmio:1; +@@ -128,6 +128,7 @@ struct ehci_hcd { /* one per controlle unsigned big_endian_desc:1; unsigned has_amcc_usb23:1; + unsigned broken_periodic:1; + unsigned has_synopsys_hc_bug:1; /* Synopsys HC */ /* required for usb32 quirk */ diff --git a/target/linux/ar71xx/patches-2.6.31/120-dsa-trailer-tag-validation-fix.patch b/target/linux/ar71xx/patches-2.6.31/120-dsa-trailer-tag-validation-fix.patch new file mode 100644 index 000000000..b58aeedc3 --- /dev/null +++ b/target/linux/ar71xx/patches-2.6.31/120-dsa-trailer-tag-validation-fix.patch @@ -0,0 +1,11 @@ +--- a/net/dsa/tag_trailer.c ++++ b/net/dsa/tag_trailer.c +@@ -86,7 +86,7 @@ static int trailer_rcv(struct sk_buff *s + + trailer = skb_tail_pointer(skb) - 4; + if (trailer[0] != 0x80 || (trailer[1] & 0xf8) != 0x00 || +- (trailer[3] & 0xef) != 0x00 || trailer[3] != 0x00) ++ (trailer[2] & 0xef) != 0x00 || (trailer[3] & 0xfe) != 0x00) + goto out_drop; + + source_port = trailer[1] & 7; diff --git a/target/linux/ar71xx/patches-2.6.31/121-dsa-add-88e6063-driver.patch b/target/linux/ar71xx/patches-2.6.31/121-dsa-add-88e6063-driver.patch new file mode 100644 index 000000000..1a11a69c6 --- /dev/null +++ b/target/linux/ar71xx/patches-2.6.31/121-dsa-add-88e6063-driver.patch @@ -0,0 +1,26 @@ +--- a/net/dsa/Kconfig ++++ b/net/dsa/Kconfig +@@ -36,6 +36,13 @@ config NET_DSA_MV88E6060 + This enables support for the Marvell 88E6060 ethernet switch + chip. + ++config NET_DSA_MV88E6063 ++ bool "Marvell 88E6063 ethernet switch chip support" ++ select NET_DSA_TAG_TRAILER ++ ---help--- ++ This enables support for the Marvell 88E6063 ethernet switch ++ chip ++ + config NET_DSA_MV88E6XXX_NEED_PPU + bool + default n +--- a/net/dsa/Makefile ++++ b/net/dsa/Makefile +@@ -6,6 +6,7 @@ obj-$(CONFIG_NET_DSA_TAG_TRAILER) += tag + # switch drivers + obj-$(CONFIG_NET_DSA_MV88E6XXX) += mv88e6xxx.o + obj-$(CONFIG_NET_DSA_MV88E6060) += mv88e6060.o ++obj-$(CONFIG_NET_DSA_MV88E6063) += mv88e6063.o + obj-$(CONFIG_NET_DSA_MV88E6123_61_65) += mv88e6123_61_65.o + obj-$(CONFIG_NET_DSA_MV88E6131) += mv88e6131.o + diff --git a/target/linux/ar71xx/patches-2.6.31/204-rtl8366-smi-driver.patch b/target/linux/ar71xx/patches-2.6.31/204-rtl8366-smi-driver.patch new file mode 100644 index 000000000..77874b49f --- /dev/null +++ b/target/linux/ar71xx/patches-2.6.31/204-rtl8366-smi-driver.patch @@ -0,0 +1,21 @@ +--- a/drivers/net/phy/Kconfig ++++ b/drivers/net/phy/Kconfig +@@ -140,4 +140,8 @@ config MDIO_GPIO + To compile this driver as a module, choose M here: the module + will be called mdio-gpio. + ++config RTL8366_SMI ++ tristate "Support for RTL8366 switch via SMI interface" ++ depends on GENERIC_GPIO ++ + endif # PHYLIB +--- a/drivers/net/phy/Makefile ++++ b/drivers/net/phy/Makefile +@@ -19,6 +19,7 @@ obj-$(CONFIG_IP175C_PHY) += ip175c.o + obj-$(CONFIG_REALTEK_PHY) += realtek.o + obj-$(CONFIG_AR8216_PHY) += ar8216.o + obj-$(CONFIG_RTL8306_PHY) += rtl8306.o ++obj-$(CONFIG_RTL8366_SMI) += rtl8366_smi.o + obj-$(CONFIG_LSI_ET1011C_PHY) += et1011c.o + obj-$(CONFIG_MICREL) += micrel.o + obj-$(CONFIG_FIXED_PHY) += fixed.o diff --git a/target/linux/ar71xx/patches-2.6.31/205-wndr3700-usb-led-driver.patch b/target/linux/ar71xx/patches-2.6.31/205-wndr3700-usb-led-driver.patch new file mode 100644 index 000000000..d9fba35b3 --- /dev/null +++ b/target/linux/ar71xx/patches-2.6.31/205-wndr3700-usb-led-driver.patch @@ -0,0 +1,26 @@ +--- a/drivers/leds/Kconfig ++++ b/drivers/leds/Kconfig +@@ -229,6 +229,13 @@ config LEDS_BD2802 + This option enables support for BD2802GU RGB LED driver chips + accessed via the I2C bus. + ++config LEDS_WNDR3700_USB ++ tristate "NETGEAR WNDR3700 USB LED driver" ++ depends on LEDS_CLASS && AR71XX_MACH_WNDR3700 ++ help ++ This option enables support for the USB LED found on the ++ NETGEAR WNDR3700 board. ++ + comment "LED Triggers" + + config LEDS_TRIGGERS +--- a/drivers/leds/Makefile ++++ b/drivers/leds/Makefile +@@ -28,6 +28,7 @@ obj-$(CONFIG_LEDS_PCA955X) += leds-pca9 + obj-$(CONFIG_LEDS_DA903X) += leds-da903x.o + obj-$(CONFIG_LEDS_WM8350) += leds-wm8350.o + obj-$(CONFIG_LEDS_PWM) += leds-pwm.o ++obj-${CONFIG_LEDS_WNDR3700_USB} += leds-wndr3700-usb.o + + # LED SPI Drivers + obj-$(CONFIG_LEDS_DAC124S085) += leds-dac124s085.o diff --git a/target/linux/ar71xx/patches-2.6.31/400-mips-multi-machine-update.patch b/target/linux/ar71xx/patches-2.6.31/400-mips-multi-machine-update.patch new file mode 100644 index 000000000..78646210e --- /dev/null +++ b/target/linux/ar71xx/patches-2.6.31/400-mips-multi-machine-update.patch @@ -0,0 +1,128 @@ +--- a/arch/mips/kernel/mips_machine.c ++++ b/arch/mips/kernel/mips_machine.c +@@ -7,12 +7,13 @@ + * + */ + #include ++#include + + #include +-#include + + static struct list_head mips_machines __initdata = + LIST_HEAD_INIT(mips_machines); ++static char *mips_machid __initdata; + + char *mips_machine_name = "Unknown"; + +@@ -55,20 +56,65 @@ void __init mips_machine_set_name(char * + } + } + +-void __init mips_machine_setup(unsigned long machtype) ++void __init mips_machine_setup(void) + { + struct mips_machine *mach; + +- mach = mips_machine_find(machtype); ++ mach = mips_machine_find(mips_machtype); + if (!mach) { +- printk(KERN_ALERT "MIPS: no machine registered for " +- "machtype %lu\n", machtype); ++ printk(KERN_WARNING "MIPS: no machine registered for " ++ "machtype %lu\n", mips_machtype); + return; + } + + mips_machine_set_name(mach->mach_name); +- printk(KERN_INFO "MIPS: machine is %s\n", mips_machine_name); ++ printk(KERN_NOTICE "MIPS: machine is %s\n", mips_machine_name); + + if (mach->mach_setup) + mach->mach_setup(); + } ++ ++int __init mips_machtype_setup(char *id) ++{ ++ if (mips_machid == NULL) ++ mips_machid = id; ++ ++ return 1; ++} ++ ++__setup("machtype=", mips_machtype_setup); ++ ++static int __init mips_machtype_init(void) ++{ ++ struct list_head *this; ++ struct mips_machine *mach; ++ ++ if (mips_machid == NULL) ++ return 0; ++ ++ list_for_each(this, &mips_machines) { ++ mach = list_entry(this, struct mips_machine, list); ++ if (mach->mach_id == NULL) ++ continue; ++ ++ if (strcmp(mach->mach_id, mips_machid) == 0) { ++ mips_machtype = mach->mach_type; ++ return 0; ++ } ++ } ++ ++ printk(KERN_WARNING ++ "MIPS: no machine found for id: '%s', registered machines:\n", ++ mips_machid); ++ printk(KERN_WARNING "%32s %s\n", "id", "name"); ++ ++ list_for_each(this, &mips_machines) { ++ mach = list_entry(this, struct mips_machine, list); ++ printk(KERN_WARNING "%32s %s\n", ++ mach->mach_id ? mach->mach_id : "", mach->mach_name); ++ } ++ ++ return 0; ++} ++ ++core_initcall(mips_machtype_init); +--- a/include/asm-mips/mips_machine.h ++++ b/include/asm-mips/mips_machine.h +@@ -13,24 +13,32 @@ + #include + #include + ++#include ++ + struct mips_machine { + unsigned long mach_type; +- void (*mach_setup)(void); ++ char *mach_id; + char *mach_name; ++ void (*mach_setup)(void); + struct list_head list; + }; + + void mips_machine_register(struct mips_machine *) __init; +-void mips_machine_setup(unsigned long machtype) __init; ++void mips_machine_setup(void) __init; ++int mips_machtype_setup(char *id) __init; + void mips_machine_set_name(char *name) __init; + + extern char *mips_machine_name; + +-#define MIPS_MACHINE(_type, _name, _setup) \ +-static char machine_name_##_type[] __initdata = _name; \ +-static struct mips_machine machine_##_type __initdata = \ ++#define MIPS_MACHINE(_type, _id, _name, _setup) \ ++static char machine_name_##_type[] __initconst \ ++ __aligned(1) = _name; \ ++static char machine_id_##_type[] __initconst \ ++ __aligned(1) = _id; \ ++static struct mips_machine machine_##_type __initconst = \ + { \ + .mach_type = _type, \ ++ .mach_id = machine_id_##_type, \ + .mach_name = machine_name_##_type, \ + .mach_setup = _setup, \ + }; \ diff --git a/target/linux/ar71xx/patches-2.6.31/800-ag71xx-remove-netdev-arg-from-napi-calls.patch b/target/linux/ar71xx/patches-2.6.31/800-ag71xx-remove-netdev-arg-from-napi-calls.patch deleted file mode 100644 index aca39a431..000000000 --- a/target/linux/ar71xx/patches-2.6.31/800-ag71xx-remove-netdev-arg-from-napi-calls.patch +++ /dev/null @@ -1,38 +0,0 @@ ---- a/drivers/net/ag71xx/ag71xx_main.c -+++ b/drivers/net/ag71xx/ag71xx_main.c -@@ -575,7 +575,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) -@@ -731,7 +731,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); -@@ -750,7 +750,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; - } - -@@ -780,7 +780,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; diff --git a/target/linux/ar71xx/patches-2.6.31/801-ag71xx-remove-redundant-napi-functions.patch b/target/linux/ar71xx/patches-2.6.31/801-ag71xx-remove-redundant-napi-functions.patch deleted file mode 100644 index 65a02bc12..000000000 --- a/target/linux/ar71xx/patches-2.6.31/801-ag71xx-remove-redundant-napi-functions.patch +++ /dev/null @@ -1,38 +0,0 @@ ---- a/drivers/net/ag71xx/ag71xx_main.c -+++ b/drivers/net/ag71xx/ag71xx_main.c -@@ -575,7 +575,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(&ag->napi); -+ napi_schedule(&ag->napi); - } - - static void ag71xx_tx_timeout(struct net_device *dev) -@@ -731,7 +731,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(napi); -+ napi_complete(napi); - - /* enable interrupts */ - spin_lock_irqsave(&ag->lock, flags); -@@ -750,7 +750,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(napi); -+ napi_complete(napi); - return 0; - } - -@@ -780,7 +780,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(&ag->napi); -+ napi_schedule(&ag->napi); - } - - return IRQ_HANDLED; diff --git a/target/linux/ar71xx/patches-2.6.31/802-ag71xx-use-netdev-ops.patch b/target/linux/ar71xx/patches-2.6.31/802-ag71xx-use-netdev-ops.patch deleted file mode 100644 index a692b734a..000000000 --- a/target/linux/ar71xx/patches-2.6.31/802-ag71xx-use-netdev-ops.patch +++ /dev/null @@ -1,37 +0,0 @@ ---- a/drivers/net/ag71xx/ag71xx_main.c -+++ b/drivers/net/ag71xx/ag71xx_main.c -@@ -791,6 +791,18 @@ static void ag71xx_set_multicast_list(st - /* TODO */ - } - -+static const struct net_device_ops ag71xx_netdev_ops = { -+ .ndo_open = ag71xx_open, -+ .ndo_stop = ag71xx_stop, -+ .ndo_start_xmit = ag71xx_hard_start_xmit, -+ .ndo_set_multicast_list = ag71xx_set_multicast_list, -+ .ndo_do_ioctl = ag71xx_do_ioctl, -+ .ndo_tx_timeout = ag71xx_tx_timeout, -+ .ndo_change_mtu = eth_change_mtu, -+ .ndo_set_mac_address = eth_mac_addr, -+ .ndo_validate_addr = eth_validate_addr, -+}; -+ - static int __init ag71xx_probe(struct platform_device *pdev) - { - struct net_device *dev; -@@ -875,14 +887,9 @@ static int __init ag71xx_probe(struct pl - } - - dev->base_addr = (unsigned long)ag->mac_base; -- dev->open = ag71xx_open; -- dev->stop = ag71xx_stop; -- dev->hard_start_xmit = ag71xx_hard_start_xmit; -- dev->set_multicast_list = ag71xx_set_multicast_list; -- dev->do_ioctl = ag71xx_do_ioctl; -+ dev->netdev_ops = &ag71xx_netdev_ops; - dev->ethtool_ops = &ag71xx_ethtool_ops; - -- dev->tx_timeout = ag71xx_tx_timeout; - INIT_WORK(&ag->restart_work, ag71xx_restart_work_func); - - init_timer(&ag->oom_timer); diff --git a/target/linux/ar71xx/patches-2.6.31/803-ar71xx-update-dsa-switch-support.patch b/target/linux/ar71xx/patches-2.6.31/803-ar71xx-update-dsa-switch-support.patch deleted file mode 100644 index 03f9dd27f..000000000 --- a/target/linux/ar71xx/patches-2.6.31/803-ar71xx-update-dsa-switch-support.patch +++ /dev/null @@ -1,46 +0,0 @@ ---- a/arch/mips/ar71xx/devices.c -+++ b/arch/mips/ar71xx/devices.c -@@ -790,6 +790,8 @@ static struct platform_device ar71xx_dsa - void __init ar71xx_add_device_dsa(unsigned int id, - struct dsa_platform_data *d) - { -+ int i; -+ - switch (id) { - case 0: - d->netdev = &ar71xx_eth0_device.dev; -@@ -803,7 +805,10 @@ void __init ar71xx_add_device_dsa(unsign - id); - return; - } -- d->mii_bus = &ar71xx_mdio_device.dev; -+ -+ for (i = 0; i < d->nr_chips; i++) -+ d->chip[i].mii_bus = &ar71xx_mdio_device.dev; -+ - ar71xx_dsa_switch_device.dev.platform_data = d; - - platform_device_register(&ar71xx_dsa_switch_device); ---- a/arch/mips/ar71xx/mach-tl-wr941nd.c -+++ b/arch/mips/ar71xx/mach-tl-wr941nd.c -@@ -104,7 +104,7 @@ static struct gpio_button tl_wr941nd_gpi - } - }; - --static struct dsa_platform_data tl_wr941nd_dsa_data = { -+static struct dsa_chip_data tl_wr941nd_dsa_chip = { - .port_names[0] = "wan", - .port_names[1] = "lan1", - .port_names[2] = "lan2", -@@ -113,6 +113,11 @@ static struct dsa_platform_data tl_wr941 - .port_names[5] = "cpu", - }; - -+static struct dsa_platform_data tl_wr941nd_dsa_data = { -+ .nr_chips = 1, -+ .chip = &tl_wr941nd_dsa_chip, -+}; -+ - static void __init tl_wr941nd_setup(void) - { - u8 *mac = (u8 *) KSEG1ADDR(0x1f01fc00); diff --git a/target/linux/ar71xx/patches-2.6.28/001-ar71xx_core.patch b/target/linux/ar71xx/patches-2.6.32/001-ar71xx_core.patch similarity index 75% rename from target/linux/ar71xx/patches-2.6.28/001-ar71xx_core.patch rename to target/linux/ar71xx/patches-2.6.32/001-ar71xx_core.patch index 30004aaf6..c33e902e9 100644 --- a/target/linux/ar71xx/patches-2.6.28/001-ar71xx_core.patch +++ b/target/linux/ar71xx/patches-2.6.32/001-ar71xx_core.patch @@ -1,8 +1,8 @@ --- a/arch/mips/Makefile +++ b/arch/mips/Makefile -@@ -593,6 +593,13 @@ core-$(CONFIG_TOSHIBA_RBTX4927) += arch/ - core-$(CONFIG_TOSHIBA_RBTX4938) += arch/mips/txx9/rbtx4938/ - core-$(CONFIG_TOSHIBA_RBTX4939) += arch/mips/txx9/rbtx4939/ +@@ -624,6 +624,13 @@ else + load-$(CONFIG_CPU_CAVIUM_OCTEON) += 0xffffffff81100000 + endif +# +# Atheros AR71xx @@ -16,9 +16,9 @@ --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig -@@ -22,6 +22,23 @@ choice - config MACH_ALCHEMY - bool "Alchemy processor based machines" +@@ -43,6 +43,23 @@ config AR7 + Support for the Texas Instruments AR7 System-on-a-Chip + family: TNETD7100, 7200 and 7300. +config ATHEROS_AR71XX + bool "Atheros AR71xx based boards" @@ -40,11 +40,11 @@ config BASLER_EXCITE bool "Basler eXcite smart camera" select CEVT_R4K -@@ -598,6 +615,7 @@ config WR_PPMC +@@ -674,6 +691,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/emma/Kconfig" + source "arch/mips/bcm63xx/Kconfig" source "arch/mips/jazz/Kconfig" diff --git a/target/linux/ar71xx/patches-2.6.28/002-ar71xx_pci.patch b/target/linux/ar71xx/patches-2.6.32/002-ar71xx_pci.patch similarity index 56% rename from target/linux/ar71xx/patches-2.6.28/002-ar71xx_pci.patch rename to target/linux/ar71xx/patches-2.6.32/002-ar71xx_pci.patch index 737c21f10..3facce9d7 100644 --- a/target/linux/ar71xx/patches-2.6.28/002-ar71xx_pci.patch +++ b/target/linux/ar71xx/patches-2.6.32/002-ar71xx_pci.patch @@ -1,9 +1,9 @@ --- 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 +@@ -18,6 +18,7 @@ obj-$(CONFIG_PCI_TX4927) += ops-tx4927.o obj-$(CONFIG_BCM47XX) += pci-bcm47xx.o + obj-$(CONFIG_BCM63XX) += pci-bcm63xx.o fixup-bcm63xx.o \ + ops-bcm63xx.o +obj-$(CONFIG_ATHEROS_AR71XX) += pci-ar71xx.o pci-ar724x.o # diff --git a/target/linux/ar71xx/patches-2.6.28/003-ar71xx_usb_host.patch b/target/linux/ar71xx/patches-2.6.32/003-ar71xx_usb_host.patch similarity index 87% rename from target/linux/ar71xx/patches-2.6.28/003-ar71xx_usb_host.patch rename to target/linux/ar71xx/patches-2.6.32/003-ar71xx_usb_host.patch index 53f811bc9..08559bccb 100644 --- a/target/linux/ar71xx/patches-2.6.28/003-ar71xx_usb_host.patch +++ b/target/linux/ar71xx/patches-2.6.32/003-ar71xx_usb_host.patch @@ -1,6 +1,6 @@ --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig -@@ -81,6 +81,13 @@ config USB_EHCI_BIG_ENDIAN_DESC +@@ -98,6 +98,13 @@ config USB_EHCI_BIG_ENDIAN_DESC depends on USB_EHCI_HCD && (440EPX || ARCH_IXP4XX) default y @@ -14,7 +14,7 @@ config USB_EHCI_FSL bool "Support for Freescale on-chip EHCI USB controller" depends on USB_EHCI_HCD && FSL_SOC -@@ -140,6 +147,13 @@ config USB_OHCI_HCD +@@ -189,6 +196,13 @@ config USB_OHCI_HCD To compile this driver as a module, choose M here: the module will be called ohci-hcd. @@ -30,8 +30,8 @@ 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 +@@ -1140,6 +1140,11 @@ MODULE_LICENSE ("GPL"); + #define PLATFORM_DRIVER ehci_atmel_driver #endif +#ifdef CONFIG_USB_EHCI_AR71XX @@ -44,7 +44,7 @@ #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"); +@@ -1085,6 +1085,11 @@ MODULE_LICENSE ("GPL"); #define TMIO_OHCI_DRIVER ohci_hcd_tmio_driver #endif diff --git a/target/linux/ar71xx/patches-2.6.28/004-ar71xx_spi_controller.patch b/target/linux/ar71xx/patches-2.6.32/004-ar71xx_spi_controller.patch similarity index 100% rename from target/linux/ar71xx/patches-2.6.28/004-ar71xx_spi_controller.patch rename to target/linux/ar71xx/patches-2.6.32/004-ar71xx_spi_controller.patch diff --git a/target/linux/ar71xx/patches-2.6.28/005-ar71xx_mac_driver.patch b/target/linux/ar71xx/patches-2.6.32/005-ar71xx_mac_driver.patch similarity index 73% rename from target/linux/ar71xx/patches-2.6.28/005-ar71xx_mac_driver.patch rename to target/linux/ar71xx/patches-2.6.32/005-ar71xx_mac_driver.patch index ed7c67ca5..72fc978e8 100644 --- a/target/linux/ar71xx/patches-2.6.28/005-ar71xx_mac_driver.patch +++ b/target/linux/ar71xx/patches-2.6.32/005-ar71xx_mac_driver.patch @@ -1,6 +1,6 @@ --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig -@@ -2039,6 +2039,8 @@ config ACENIC_OMIT_TIGON_I +@@ -2126,6 +2126,8 @@ config ACENIC_OMIT_TIGON_I The safe and default value for this is N. @@ -11,9 +11,9 @@ depends on PCI --- a/drivers/net/Makefile +++ b/drivers/net/Makefile -@@ -93,6 +93,7 @@ obj-$(CONFIG_SH_ETH) += sh_eth.o - obj-$(CONFIG_MII) += mii.o - obj-$(CONFIG_PHYLIB) += phy/ +@@ -106,6 +106,7 @@ obj-$(CONFIG_STMMAC_ETH) += stmmac/ + # end link order section + # +obj-$(CONFIG_AG71XX) += ag71xx/ obj-$(CONFIG_SUNDANCE) += sundance.o diff --git a/target/linux/ar71xx/patches-2.6.28/006-ar71xx_wdt_driver.patch b/target/linux/ar71xx/patches-2.6.32/006-ar71xx_wdt_driver.patch similarity index 86% rename from target/linux/ar71xx/patches-2.6.28/006-ar71xx_wdt_driver.patch rename to target/linux/ar71xx/patches-2.6.32/006-ar71xx_wdt_driver.patch index bf0ffcd60..bd6364ddb 100644 --- a/target/linux/ar71xx/patches-2.6.28/006-ar71xx_wdt_driver.patch +++ b/target/linux/ar71xx/patches-2.6.32/006-ar71xx_wdt_driver.patch @@ -1,6 +1,6 @@ --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig -@@ -747,6 +747,13 @@ config TXX9_WDT +@@ -850,6 +850,13 @@ config TXX9_WDT help Hardware driver for the built-in watchdog timer on TXx9 MIPS SoCs. @@ -16,7 +16,7 @@ # POWERPC Architecture --- a/drivers/watchdog/Makefile +++ b/drivers/watchdog/Makefile -@@ -106,6 +106,7 @@ obj-$(CONFIG_WDT_RM9K_GPI) += rm9k_wdt.o +@@ -113,6 +113,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 diff --git a/target/linux/ar71xx/patches-2.6.28/007-ar91xx_flash_driver.patch b/target/linux/ar71xx/patches-2.6.32/007-ar91xx_flash_driver.patch similarity index 88% rename from target/linux/ar71xx/patches-2.6.28/007-ar91xx_flash_driver.patch rename to target/linux/ar71xx/patches-2.6.32/007-ar91xx_flash_driver.patch index 3219ff382..244d820da 100644 --- a/target/linux/ar71xx/patches-2.6.28/007-ar91xx_flash_driver.patch +++ b/target/linux/ar71xx/patches-2.6.32/007-ar91xx_flash_driver.patch @@ -1,6 +1,6 @@ --- a/drivers/mtd/maps/Kconfig +++ b/drivers/mtd/maps/Kconfig -@@ -257,6 +257,13 @@ config MTD_ALCHEMY +@@ -259,6 +259,13 @@ config MTD_ALCHEMY help Flash memory access on AMD Alchemy Pb/Db/RDK Reference Boards @@ -13,10 +13,10 @@ + config MTD_DILNETPC tristate "CFI Flash device mapped on DIL/Net PC" - depends on X86 && MTD_CONCAT && MTD_PARTITIONS && MTD_CFI_INTELEXT + depends on X86 && MTD_CONCAT && MTD_PARTITIONS && MTD_CFI_INTELEXT && BROKEN --- a/drivers/mtd/maps/Makefile +++ b/drivers/mtd/maps/Makefile -@@ -42,6 +42,7 @@ obj-$(CONFIG_MTD_DBOX2) += dbox2-flash. +@@ -41,6 +41,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 diff --git a/target/linux/ar71xx/patches-2.6.28/100-mtd_m25p80_add_pm25lv_flash_support.patch b/target/linux/ar71xx/patches-2.6.32/100-mtd_m25p80_add_pm25lv_flash_support.patch similarity index 66% rename from target/linux/ar71xx/patches-2.6.28/100-mtd_m25p80_add_pm25lv_flash_support.patch rename to target/linux/ar71xx/patches-2.6.32/100-mtd_m25p80_add_pm25lv_flash_support.patch index f7975f2ff..30c5cc952 100644 --- a/target/linux/ar71xx/patches-2.6.28/100-mtd_m25p80_add_pm25lv_flash_support.patch +++ b/target/linux/ar71xx/patches-2.6.32/100-mtd_m25p80_add_pm25lv_flash_support.patch @@ -1,8 +1,8 @@ --- a/drivers/mtd/devices/m25p80.c +++ b/drivers/mtd/devices/m25p80.c -@@ -503,6 +503,10 @@ static struct flash_info __devinitdata m - { "at26df161a", 0x1f4601, 0, 64 * 1024, 32, SECT_4K, }, - { "at26df321", 0x1f4701, 0, 64 * 1024, 64, SECT_4K, }, +@@ -626,6 +626,10 @@ static struct flash_info __devinitdata m + { "mx25l12805d", 0xc22018, 0, 64 * 1024, 256, }, + { "mx25l12855e", 0xc22618, 0, 64 * 1024, 256, }, + /* PMC -- pm25x "blocks" are 32K, sectors are 4K */ + { "pm25lv512", 0, 32 * 1024, 2, SECT_4K }, diff --git a/target/linux/ar71xx/patches-2.6.28/101-ksz8041_phy_driver.patch b/target/linux/ar71xx/patches-2.6.32/101-ksz8041_phy_driver.patch similarity index 68% rename from target/linux/ar71xx/patches-2.6.28/101-ksz8041_phy_driver.patch rename to target/linux/ar71xx/patches-2.6.32/101-ksz8041_phy_driver.patch index 239875edd..866b50386 100644 --- a/target/linux/ar71xx/patches-2.6.28/101-ksz8041_phy_driver.patch +++ b/target/linux/ar71xx/patches-2.6.32/101-ksz8041_phy_driver.patch @@ -1,6 +1,6 @@ --- a/drivers/net/phy/Kconfig +++ b/drivers/net/phy/Kconfig -@@ -85,6 +85,11 @@ config RTL8306_PHY +@@ -114,6 +114,11 @@ config RTL8306_PHY tristate "Driver for Realtek RTL8306S switches" select SWCONFIG @@ -14,11 +14,11 @@ depends on PHYLIB=y --- a/drivers/net/phy/Makefile +++ b/drivers/net/phy/Makefile -@@ -17,6 +17,7 @@ obj-$(CONFIG_ADM6996_PHY) += adm6996.o - obj-$(CONFIG_IP175C_PHY) += ip175c.o +@@ -21,6 +21,7 @@ obj-$(CONFIG_REALTEK_PHY) += realtek.o + obj-$(CONFIG_AR8216_PHY) += ar8216.o obj-$(CONFIG_RTL8306_PHY) += rtl8306.o - obj-$(CONFIG_REALTEK_PHY) += realtek.o -+obj-$(CONFIG_MICREL_PHY) += micrel.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_OF_GPIO) += mdio-ofgpio.o + obj-$(CONFIG_MDIO_GPIO) += mdio-gpio.o diff --git a/target/linux/ar71xx/patches-2.6.32/102-mtd_m25p80_add_myloader_parser.patch b/target/linux/ar71xx/patches-2.6.32/102-mtd_m25p80_add_myloader_parser.patch new file mode 100644 index 000000000..7b28fe418 --- /dev/null +++ b/target/linux/ar71xx/patches-2.6.32/102-mtd_m25p80_add_myloader_parser.patch @@ -0,0 +1,19 @@ +--- a/drivers/mtd/devices/m25p80.c ++++ b/drivers/mtd/devices/m25p80.c +@@ -856,6 +856,16 @@ static int __devinit m25p_probe(struct s + part_probes, &parts, 0); + } + ++#ifdef CONFIG_MTD_MYLOADER_PARTS ++ if (nr_parts <= 0) { ++ static const char *part_probes[] ++ = { "MyLoader", NULL, }; ++ ++ nr_parts = parse_mtd_partitions(&flash->mtd, ++ part_probes, &parts, 0); ++ } ++#endif ++ + if (nr_parts <= 0 && data && data->parts) { + parts = data->parts; + nr_parts = data->nr_parts; diff --git a/target/linux/ar71xx/patches-2.6.28/103-mtd_m25p80_add_en25pxx_support.patch b/target/linux/ar71xx/patches-2.6.32/103-mtd_m25p80_add_en25pxx_support.patch similarity index 66% rename from target/linux/ar71xx/patches-2.6.28/103-mtd_m25p80_add_en25pxx_support.patch rename to target/linux/ar71xx/patches-2.6.32/103-mtd_m25p80_add_en25pxx_support.patch index 673ab041c..d3bd1dd5e 100644 --- a/target/linux/ar71xx/patches-2.6.28/103-mtd_m25p80_add_en25pxx_support.patch +++ b/target/linux/ar71xx/patches-2.6.32/103-mtd_m25p80_add_en25pxx_support.patch @@ -1,8 +1,8 @@ --- a/drivers/mtd/devices/m25p80.c +++ b/drivers/mtd/devices/m25p80.c -@@ -503,6 +503,10 @@ static struct flash_info __devinitdata m - { "at26df161a", 0x1f4601, 0, 64 * 1024, 32, SECT_4K, }, - { "at26df321", 0x1f4701, 0, 64 * 1024, 64, SECT_4K, }, +@@ -626,6 +626,10 @@ static struct flash_info __devinitdata m + { "mx25l12805d", 0xc22018, 0, 64 * 1024, 256, }, + { "mx25l12855e", 0xc22618, 0, 64 * 1024, 256, }, + /* EON -- en25pxx */ + { "en25p32", 0x1c2016, 0, 64 * 1024, 64, }, diff --git a/target/linux/ar71xx/patches-2.6.32/104-mtd_m25p80_add_redboot_parser.patch b/target/linux/ar71xx/patches-2.6.32/104-mtd_m25p80_add_redboot_parser.patch new file mode 100644 index 000000000..d4a8ce9a4 --- /dev/null +++ b/target/linux/ar71xx/patches-2.6.32/104-mtd_m25p80_add_redboot_parser.patch @@ -0,0 +1,18 @@ +--- a/drivers/mtd/devices/m25p80.c ++++ b/drivers/mtd/devices/m25p80.c +@@ -870,6 +870,15 @@ static int __devinit m25p_probe(struct s + } + #endif + ++#ifdef CONFIG_MTD_REDBOOT_PARTS ++ if (nr_parts <= 0) { ++ static const char *part_probes[] ++ = { "RedBoot", NULL, }; ++ ++ nr_parts = parse_mtd_partitions(&flash->mtd, ++ part_probes, &parts, 0); ++ } ++#endif + if (nr_parts <= 0 && data && data->parts) { + parts = data->parts; + nr_parts = data->nr_parts; diff --git a/target/linux/ar71xx/patches-2.6.28/105-mtd_m25p80_add_mx25lxxx_support.patch b/target/linux/ar71xx/patches-2.6.32/105-mtd_m25p80_add_mx25lxxx_support.patch similarity index 88% rename from target/linux/ar71xx/patches-2.6.28/105-mtd_m25p80_add_mx25lxxx_support.patch rename to target/linux/ar71xx/patches-2.6.32/105-mtd_m25p80_add_mx25lxxx_support.patch index d4b8ee93e..201c20546 100644 --- a/target/linux/ar71xx/patches-2.6.28/105-mtd_m25p80_add_mx25lxxx_support.patch +++ b/target/linux/ar71xx/patches-2.6.32/105-mtd_m25p80_add_mx25lxxx_support.patch @@ -1,6 +1,6 @@ --- a/drivers/mtd/devices/m25p80.c +++ b/drivers/mtd/devices/m25p80.c -@@ -507,6 +507,11 @@ static struct flash_info __devinitdata m +@@ -630,6 +630,11 @@ static struct flash_info __devinitdata m { "en25p32", 0x1c2016, 0, 64 * 1024, 64, }, { "en25p64", 0x1c2017, 0, 64 * 1024, 128, }, diff --git a/target/linux/ar71xx/patches-2.6.28/106-mtd_m25p80_add_xxxs33b_support.patch b/target/linux/ar71xx/patches-2.6.32/106-mtd_m25p80_add_xxxs33b_support.patch similarity index 88% rename from target/linux/ar71xx/patches-2.6.28/106-mtd_m25p80_add_xxxs33b_support.patch rename to target/linux/ar71xx/patches-2.6.32/106-mtd_m25p80_add_xxxs33b_support.patch index e4e01637d..01be5dbb4 100644 --- a/target/linux/ar71xx/patches-2.6.28/106-mtd_m25p80_add_xxxs33b_support.patch +++ b/target/linux/ar71xx/patches-2.6.32/106-mtd_m25p80_add_xxxs33b_support.patch @@ -1,6 +1,6 @@ --- a/drivers/mtd/devices/m25p80.c +++ b/drivers/mtd/devices/m25p80.c -@@ -512,6 +512,11 @@ static struct flash_info __devinitdata m +@@ -635,6 +635,11 @@ static struct flash_info __devinitdata m { "mx25l64", 0xc22017, 0, 64 * 1024, 128, }, { "mx25l128", 0xc22018, 0, 64 * 1024, 256, }, diff --git a/target/linux/ar71xx/patches-2.6.28/107-mtd-SST39VF6401B-support.patch b/target/linux/ar71xx/patches-2.6.32/107-mtd-SST39VF6401B-support.patch similarity index 86% rename from target/linux/ar71xx/patches-2.6.28/107-mtd-SST39VF6401B-support.patch rename to target/linux/ar71xx/patches-2.6.32/107-mtd-SST39VF6401B-support.patch index a89e8e77d..2fdfcb7cd 100644 --- a/target/linux/ar71xx/patches-2.6.28/107-mtd-SST39VF6401B-support.patch +++ b/target/linux/ar71xx/patches-2.6.32/107-mtd-SST39VF6401B-support.patch @@ -1,14 +1,14 @@ --- a/drivers/mtd/chips/jedec_probe.c +++ b/drivers/mtd/chips/jedec_probe.c -@@ -159,6 +159,7 @@ - #define SST39LF800 0x2781 +@@ -166,6 +166,7 @@ #define SST39LF160 0x2782 #define SST39VF1601 0x234b + #define SST39VF3201 0x235b +#define SST39VF6401B 0x236d #define SST39LF512 0x00D4 #define SST39LF010 0x00D5 #define SST39LF020 0x00D6 -@@ -1502,6 +1503,18 @@ static const struct amd_flash_info jedec +@@ -1556,6 +1557,18 @@ static const struct amd_flash_info jedec ERASEINFO(0x10000,64), } }, { diff --git a/target/linux/ar71xx/patches-2.6.28/108-mtd_fix_cfi_cmdset_0002_erase_status_check.patch b/target/linux/ar71xx/patches-2.6.32/108-mtd_fix_cfi_cmdset_0002_erase_status_check.patch similarity index 76% rename from target/linux/ar71xx/patches-2.6.28/108-mtd_fix_cfi_cmdset_0002_erase_status_check.patch rename to target/linux/ar71xx/patches-2.6.32/108-mtd_fix_cfi_cmdset_0002_erase_status_check.patch index c17f27459..22aefe0d4 100644 --- a/target/linux/ar71xx/patches-2.6.28/108-mtd_fix_cfi_cmdset_0002_erase_status_check.patch +++ b/target/linux/ar71xx/patches-2.6.32/108-mtd_fix_cfi_cmdset_0002_erase_status_check.patch @@ -1,6 +1,6 @@ --- a/drivers/mtd/chips/cfi_cmdset_0002.c +++ b/drivers/mtd/chips/cfi_cmdset_0002.c -@@ -1558,7 +1558,7 @@ static int __xipram do_erase_chip(struct +@@ -1568,7 +1568,7 @@ static int __xipram do_erase_chip(struct chip->erase_suspended = 0; } @@ -9,7 +9,7 @@ break; if (time_after(jiffies, timeo)) { -@@ -1646,7 +1646,7 @@ static int __xipram do_erase_oneblock(st +@@ -1656,7 +1656,7 @@ static int __xipram do_erase_oneblock(st chip->erase_suspended = 0; } diff --git a/target/linux/ar71xx/patches-2.6.28/109-mtd-wrt160nl-trx-parser.patch b/target/linux/ar71xx/patches-2.6.32/109-mtd-wrt160nl-trx-parser.patch similarity index 63% rename from target/linux/ar71xx/patches-2.6.28/109-mtd-wrt160nl-trx-parser.patch rename to target/linux/ar71xx/patches-2.6.32/109-mtd-wrt160nl-trx-parser.patch index f67ce20f3..4136db8e9 100644 --- a/target/linux/ar71xx/patches-2.6.28/109-mtd-wrt160nl-trx-parser.patch +++ b/target/linux/ar71xx/patches-2.6.32/109-mtd-wrt160nl-trx-parser.patch @@ -1,18 +1,25 @@ --- a/drivers/mtd/devices/m25p80.c +++ b/drivers/mtd/devices/m25p80.c -@@ -735,6 +735,9 @@ static int __devinit m25p_probe(struct s - #ifdef CONFIG_MTD_REDBOOT_PARTS - "RedBoot", +@@ -889,6 +889,16 @@ static int __devinit m25p_probe(struct s + part_probes, &parts, 0); + } #endif ++ +#ifdef CONFIG_MTD_WRT160NL_PARTS -+ "wrt160nl", ++ if (nr_parts <= 0) { ++ static const char *part_probes[] ++ = { "wrt160nl", NULL, }; ++ ++ nr_parts = parse_mtd_partitions(&flash->mtd, ++ part_probes, &parts, 0); ++ } +#endif - NULL, }; - - nr_parts = parse_mtd_partitions(&flash->mtd, + if (nr_parts <= 0 && data && data->parts) { + parts = data->parts; + nr_parts = data->nr_parts; --- a/drivers/mtd/Kconfig +++ b/drivers/mtd/Kconfig -@@ -172,6 +172,12 @@ config MTD_AR7_PARTS +@@ -181,6 +181,12 @@ config MTD_AR7_PARTS ---help--- TI AR7 partitioning support @@ -24,7 +31,7 @@ + config MTD_MYLOADER_PARTS tristate "MyLoader partition parsing" - depends on MTD_PARTITIONS && (ADM5120 || ATHEROS || ATHEROS_AR71XX) + depends on MTD_PARTITIONS && (ADM5120 || ATHEROS_AR231X || ATHEROS_AR71XX) --- a/drivers/mtd/Makefile +++ b/drivers/mtd/Makefile @@ -12,6 +12,7 @@ obj-$(CONFIG_MTD_REDBOOT_PARTS) += redbo diff --git a/target/linux/ar71xx/patches-2.6.28/110-usb-ehci-add-war-for-synopsys-hc-bug.patch b/target/linux/ar71xx/patches-2.6.32/110-usb-ehci-add-war-for-synopsys-hc-bug.patch similarity index 57% rename from target/linux/ar71xx/patches-2.6.28/110-usb-ehci-add-war-for-synopsys-hc-bug.patch rename to target/linux/ar71xx/patches-2.6.32/110-usb-ehci-add-war-for-synopsys-hc-bug.patch index 8d203e8a4..91af1ac60 100644 --- a/target/linux/ar71xx/patches-2.6.28/110-usb-ehci-add-war-for-synopsys-hc-bug.patch +++ b/target/linux/ar71xx/patches-2.6.32/110-usb-ehci-add-war-for-synopsys-hc-bug.patch @@ -1,6 +1,6 @@ --- 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 +@@ -1167,6 +1167,9 @@ static void end_unlink_async (struct ehc ehci->reclaim = NULL; start_unlink_async (ehci, next); } @@ -12,11 +12,11 @@ /* makes sure the async qh will become idle */ --- a/drivers/usb/host/ehci.h +++ b/drivers/usb/host/ehci.h -@@ -124,6 +124,7 @@ struct ehci_hcd { /* one per controlle - unsigned has_fsl_port_bug:1; /* FreeScale */ - unsigned big_endian_mmio:1; - unsigned big_endian_desc:1; +@@ -129,6 +129,7 @@ struct ehci_hcd { /* one per controlle + unsigned has_amcc_usb23:1; + unsigned need_io_watchdog:1; + unsigned broken_periodic:1; + unsigned has_synopsys_hc_bug:1; /* Synopsys HC */ - u8 sbrn; /* packed release number */ - + /* required for usb32 quirk */ + #define OHCI_CTRL_HCFS (3 << 6) diff --git a/target/linux/ar71xx/patches-2.6.32/120-dsa-trailer-tag-validation-fix.patch b/target/linux/ar71xx/patches-2.6.32/120-dsa-trailer-tag-validation-fix.patch new file mode 100644 index 000000000..b58aeedc3 --- /dev/null +++ b/target/linux/ar71xx/patches-2.6.32/120-dsa-trailer-tag-validation-fix.patch @@ -0,0 +1,11 @@ +--- a/net/dsa/tag_trailer.c ++++ b/net/dsa/tag_trailer.c +@@ -86,7 +86,7 @@ static int trailer_rcv(struct sk_buff *s + + trailer = skb_tail_pointer(skb) - 4; + if (trailer[0] != 0x80 || (trailer[1] & 0xf8) != 0x00 || +- (trailer[3] & 0xef) != 0x00 || trailer[3] != 0x00) ++ (trailer[2] & 0xef) != 0x00 || (trailer[3] & 0xfe) != 0x00) + goto out_drop; + + source_port = trailer[1] & 7; diff --git a/target/linux/ar71xx/patches-2.6.32/121-dsa-add-88e6063-driver.patch b/target/linux/ar71xx/patches-2.6.32/121-dsa-add-88e6063-driver.patch new file mode 100644 index 000000000..1a11a69c6 --- /dev/null +++ b/target/linux/ar71xx/patches-2.6.32/121-dsa-add-88e6063-driver.patch @@ -0,0 +1,26 @@ +--- a/net/dsa/Kconfig ++++ b/net/dsa/Kconfig +@@ -36,6 +36,13 @@ config NET_DSA_MV88E6060 + This enables support for the Marvell 88E6060 ethernet switch + chip. + ++config NET_DSA_MV88E6063 ++ bool "Marvell 88E6063 ethernet switch chip support" ++ select NET_DSA_TAG_TRAILER ++ ---help--- ++ This enables support for the Marvell 88E6063 ethernet switch ++ chip ++ + config NET_DSA_MV88E6XXX_NEED_PPU + bool + default n +--- a/net/dsa/Makefile ++++ b/net/dsa/Makefile +@@ -6,6 +6,7 @@ obj-$(CONFIG_NET_DSA_TAG_TRAILER) += tag + # switch drivers + obj-$(CONFIG_NET_DSA_MV88E6XXX) += mv88e6xxx.o + obj-$(CONFIG_NET_DSA_MV88E6060) += mv88e6060.o ++obj-$(CONFIG_NET_DSA_MV88E6063) += mv88e6063.o + obj-$(CONFIG_NET_DSA_MV88E6123_61_65) += mv88e6123_61_65.o + obj-$(CONFIG_NET_DSA_MV88E6131) += mv88e6131.o + diff --git a/target/linux/ar71xx/patches-2.6.28/140-redboot_partition_scan.patch b/target/linux/ar71xx/patches-2.6.32/140-redboot_partition_scan.patch similarity index 100% rename from target/linux/ar71xx/patches-2.6.28/140-redboot_partition_scan.patch rename to target/linux/ar71xx/patches-2.6.32/140-redboot_partition_scan.patch diff --git a/target/linux/ar71xx/patches-2.6.28/200-rb4xx_nand_driver.patch b/target/linux/ar71xx/patches-2.6.32/200-rb4xx_nand_driver.patch similarity index 71% rename from target/linux/ar71xx/patches-2.6.28/200-rb4xx_nand_driver.patch rename to target/linux/ar71xx/patches-2.6.32/200-rb4xx_nand_driver.patch index 9e4477d88..bce835f86 100644 --- a/target/linux/ar71xx/patches-2.6.28/200-rb4xx_nand_driver.patch +++ b/target/linux/ar71xx/patches-2.6.32/200-rb4xx_nand_driver.patch @@ -1,8 +1,8 @@ --- a/drivers/mtd/nand/Kconfig +++ b/drivers/mtd/nand/Kconfig -@@ -420,4 +420,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. +@@ -482,4 +482,8 @@ config MTD_NAND_W90P910 + This enables the driver for the NAND Flash on evaluation board based + on w90p910. +config MTD_NAND_RB4XX + tristate "NAND flash driver for RouterBoard 4xx series" @@ -11,7 +11,7 @@ endif # MTD_NAND --- a/drivers/mtd/nand/Makefile +++ b/drivers/mtd/nand/Makefile -@@ -29,6 +29,7 @@ obj-$(CONFIG_MTD_NAND_BASLER_EXCITE) += +@@ -31,6 +31,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 diff --git a/target/linux/ar71xx/patches-2.6.28/201-ap83_spi_controller.patch b/target/linux/ar71xx/patches-2.6.32/201-ap83_spi_controller.patch similarity index 100% rename from target/linux/ar71xx/patches-2.6.28/201-ap83_spi_controller.patch rename to target/linux/ar71xx/patches-2.6.32/201-ap83_spi_controller.patch diff --git a/target/linux/ar71xx/patches-2.6.28/202-spi_vsc7385_driver.patch b/target/linux/ar71xx/patches-2.6.32/202-spi_vsc7385_driver.patch similarity index 82% rename from target/linux/ar71xx/patches-2.6.28/202-spi_vsc7385_driver.patch rename to target/linux/ar71xx/patches-2.6.32/202-spi_vsc7385_driver.patch index 26f6156da..a4b4595b0 100644 --- a/target/linux/ar71xx/patches-2.6.28/202-spi_vsc7385_driver.patch +++ b/target/linux/ar71xx/patches-2.6.32/202-spi_vsc7385_driver.patch @@ -1,6 +1,6 @@ --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig -@@ -283,6 +283,11 @@ config SPI_TLE62X0 +@@ -296,6 +296,11 @@ config SPI_TLE62X0 sysfs interface, with each line presented as a kind of GPIO exposing both switch control and diagnostic feedback. @@ -14,9 +14,9 @@ # --- a/drivers/spi/Makefile +++ b/drivers/spi/Makefile -@@ -38,6 +38,7 @@ obj-$(CONFIG_SPI_SH_SCI) += spi_sh_sci. +@@ -40,6 +40,7 @@ obj-$(CONFIG_SPI_STMP3XXX) += spi_stmp. + # SPI protocol drivers (device/link on bus) - obj-$(CONFIG_SPI_AT25) += at25.o obj-$(CONFIG_SPI_SPIDEV) += spidev.o +obj-$(CONFIG_SPI_VSC7385) += spi_vsc7385.o obj-$(CONFIG_SPI_TLE62X0) += tle62x0.o diff --git a/target/linux/ar71xx/patches-2.6.28/203-pb44_spi_controller.patch b/target/linux/ar71xx/patches-2.6.32/203-pb44_spi_controller.patch similarity index 100% rename from target/linux/ar71xx/patches-2.6.28/203-pb44_spi_controller.patch rename to target/linux/ar71xx/patches-2.6.32/203-pb44_spi_controller.patch diff --git a/target/linux/ar71xx/patches-2.6.32/204-rtl8366-smi-driver.patch b/target/linux/ar71xx/patches-2.6.32/204-rtl8366-smi-driver.patch new file mode 100644 index 000000000..78ec2e44c --- /dev/null +++ b/target/linux/ar71xx/patches-2.6.32/204-rtl8366-smi-driver.patch @@ -0,0 +1,21 @@ +--- a/drivers/net/phy/Kconfig ++++ b/drivers/net/phy/Kconfig +@@ -146,4 +146,8 @@ config MDIO_GPIO + To compile this driver as a module, choose M here: the module + will be called mdio-gpio. + ++config RTL8366_SMI ++ tristate "Support for RTL8366 switch via SMI interface" ++ depends on GENERIC_GPIO ++ + endif # PHYLIB +--- a/drivers/net/phy/Makefile ++++ b/drivers/net/phy/Makefile +@@ -20,6 +20,7 @@ obj-$(CONFIG_IP175C_PHY) += ip175c.o + obj-$(CONFIG_REALTEK_PHY) += realtek.o + obj-$(CONFIG_AR8216_PHY) += ar8216.o + obj-$(CONFIG_RTL8306_PHY) += rtl8306.o ++obj-$(CONFIG_RTL8366_SMI) += rtl8366_smi.o + obj-$(CONFIG_LSI_ET1011C_PHY) += et1011c.o + obj-$(CONFIG_MICREL) += micrel.o + obj-$(CONFIG_FIXED_PHY) += fixed.o diff --git a/target/linux/ar71xx/patches-2.6.32/205-wndr3700-usb-led-driver.patch b/target/linux/ar71xx/patches-2.6.32/205-wndr3700-usb-led-driver.patch new file mode 100644 index 000000000..3f7c84899 --- /dev/null +++ b/target/linux/ar71xx/patches-2.6.32/205-wndr3700-usb-led-driver.patch @@ -0,0 +1,26 @@ +--- a/drivers/leds/Kconfig ++++ b/drivers/leds/Kconfig +@@ -236,6 +236,13 @@ config LEDS_BD2802 + This option enables support for BD2802GU RGB LED driver chips + accessed via the I2C bus. + ++config LEDS_WNDR3700_USB ++ tristate "NETGEAR WNDR3700 USB LED driver" ++ depends on LEDS_CLASS && AR71XX_MACH_WNDR3700 ++ help ++ This option enables support for the USB LED found on the ++ NETGEAR WNDR3700 board. ++ + comment "LED Triggers" + + config LEDS_TRIGGERS +--- a/drivers/leds/Makefile ++++ b/drivers/leds/Makefile +@@ -29,6 +29,7 @@ obj-$(CONFIG_LEDS_DA903X) += leds-da903 + obj-$(CONFIG_LEDS_WM831X_STATUS) += leds-wm831x-status.o + obj-$(CONFIG_LEDS_WM8350) += leds-wm8350.o + obj-$(CONFIG_LEDS_PWM) += leds-pwm.o ++obj-${CONFIG_LEDS_WNDR3700_USB} += leds-wndr3700-usb.o + + # LED SPI Drivers + obj-$(CONFIG_LEDS_DAC124S085) += leds-dac124s085.o diff --git a/target/linux/ar71xx/patches-2.6.28/300-mips_fw_myloader.patch b/target/linux/ar71xx/patches-2.6.32/300-mips_fw_myloader.patch similarity index 77% rename from target/linux/ar71xx/patches-2.6.28/300-mips_fw_myloader.patch rename to target/linux/ar71xx/patches-2.6.32/300-mips_fw_myloader.patch index 3bca34c8d..8a834607d 100644 --- a/target/linux/ar71xx/patches-2.6.28/300-mips_fw_myloader.patch +++ b/target/linux/ar71xx/patches-2.6.32/300-mips_fw_myloader.patch @@ -1,16 +1,16 @@ --- a/arch/mips/Makefile +++ b/arch/mips/Makefile -@@ -167,6 +167,7 @@ endif +@@ -169,6 +169,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 -@@ -789,6 +789,9 @@ config MIPS_NILE4 +@@ -880,6 +880,9 @@ config MIPS_NILE4 config MIPS_DISABLE_OBSOLETE_IDE bool diff --git a/target/linux/ar71xx/patches-2.6.32/400-mips-multi-machine-update.patch b/target/linux/ar71xx/patches-2.6.32/400-mips-multi-machine-update.patch new file mode 100644 index 000000000..78646210e --- /dev/null +++ b/target/linux/ar71xx/patches-2.6.32/400-mips-multi-machine-update.patch @@ -0,0 +1,128 @@ +--- a/arch/mips/kernel/mips_machine.c ++++ b/arch/mips/kernel/mips_machine.c +@@ -7,12 +7,13 @@ + * + */ + #include ++#include + + #include +-#include + + static struct list_head mips_machines __initdata = + LIST_HEAD_INIT(mips_machines); ++static char *mips_machid __initdata; + + char *mips_machine_name = "Unknown"; + +@@ -55,20 +56,65 @@ void __init mips_machine_set_name(char * + } + } + +-void __init mips_machine_setup(unsigned long machtype) ++void __init mips_machine_setup(void) + { + struct mips_machine *mach; + +- mach = mips_machine_find(machtype); ++ mach = mips_machine_find(mips_machtype); + if (!mach) { +- printk(KERN_ALERT "MIPS: no machine registered for " +- "machtype %lu\n", machtype); ++ printk(KERN_WARNING "MIPS: no machine registered for " ++ "machtype %lu\n", mips_machtype); + return; + } + + mips_machine_set_name(mach->mach_name); +- printk(KERN_INFO "MIPS: machine is %s\n", mips_machine_name); ++ printk(KERN_NOTICE "MIPS: machine is %s\n", mips_machine_name); + + if (mach->mach_setup) + mach->mach_setup(); + } ++ ++int __init mips_machtype_setup(char *id) ++{ ++ if (mips_machid == NULL) ++ mips_machid = id; ++ ++ return 1; ++} ++ ++__setup("machtype=", mips_machtype_setup); ++ ++static int __init mips_machtype_init(void) ++{ ++ struct list_head *this; ++ struct mips_machine *mach; ++ ++ if (mips_machid == NULL) ++ return 0; ++ ++ list_for_each(this, &mips_machines) { ++ mach = list_entry(this, struct mips_machine, list); ++ if (mach->mach_id == NULL) ++ continue; ++ ++ if (strcmp(mach->mach_id, mips_machid) == 0) { ++ mips_machtype = mach->mach_type; ++ return 0; ++ } ++ } ++ ++ printk(KERN_WARNING ++ "MIPS: no machine found for id: '%s', registered machines:\n", ++ mips_machid); ++ printk(KERN_WARNING "%32s %s\n", "id", "name"); ++ ++ list_for_each(this, &mips_machines) { ++ mach = list_entry(this, struct mips_machine, list); ++ printk(KERN_WARNING "%32s %s\n", ++ mach->mach_id ? mach->mach_id : "", mach->mach_name); ++ } ++ ++ return 0; ++} ++ ++core_initcall(mips_machtype_init); +--- a/include/asm-mips/mips_machine.h ++++ b/include/asm-mips/mips_machine.h +@@ -13,24 +13,32 @@ + #include + #include + ++#include ++ + struct mips_machine { + unsigned long mach_type; +- void (*mach_setup)(void); ++ char *mach_id; + char *mach_name; ++ void (*mach_setup)(void); + struct list_head list; + }; + + void mips_machine_register(struct mips_machine *) __init; +-void mips_machine_setup(unsigned long machtype) __init; ++void mips_machine_setup(void) __init; ++int mips_machtype_setup(char *id) __init; + void mips_machine_set_name(char *name) __init; + + extern char *mips_machine_name; + +-#define MIPS_MACHINE(_type, _name, _setup) \ +-static char machine_name_##_type[] __initdata = _name; \ +-static struct mips_machine machine_##_type __initdata = \ ++#define MIPS_MACHINE(_type, _id, _name, _setup) \ ++static char machine_name_##_type[] __initconst \ ++ __aligned(1) = _name; \ ++static char machine_id_##_type[] __initconst \ ++ __aligned(1) = _id; \ ++static struct mips_machine machine_##_type __initconst = \ + { \ + .mach_type = _type, \ ++ .mach_id = machine_id_##_type, \ + .mach_name = machine_name_##_type, \ + .mach_setup = _setup, \ + }; \ diff --git a/target/linux/ar71xx/patches-2.6.28/901-get_c0_compare_irq_function.patch b/target/linux/ar71xx/patches-2.6.32/901-get_c0_compare_irq_function.patch similarity index 70% rename from target/linux/ar71xx/patches-2.6.28/901-get_c0_compare_irq_function.patch rename to target/linux/ar71xx/patches-2.6.32/901-get_c0_compare_irq_function.patch index ec3924f7c..babe906eb 100644 --- a/target/linux/ar71xx/patches-2.6.28/901-get_c0_compare_irq_function.patch +++ b/target/linux/ar71xx/patches-2.6.32/901-get_c0_compare_irq_function.patch @@ -1,14 +1,14 @@ --- a/arch/mips/kernel/traps.c +++ b/arch/mips/kernel/traps.c -@@ -47,6 +47,7 @@ - #include +@@ -48,6 +48,7 @@ #include #include + #include +#include extern void check_wait(void); extern asmlinkage void r4k_wait(void); -@@ -1514,6 +1515,8 @@ void __cpuinit per_cpu_trap_init(void) +@@ -1537,6 +1538,8 @@ void __cpuinit per_cpu_trap_init(void) */ if (cpu_has_mips_r2) { cp0_compare_irq = (read_c0_intctl() >> 29) & 7; @@ -19,11 +19,11 @@ cp0_perfcount_irq = -1; --- a/arch/mips/include/asm/time.h +++ b/arch/mips/include/asm/time.h -@@ -53,6 +53,7 @@ extern int (*perf_irq)(void); - #ifdef CONFIG_CEVT_R4K - extern int mips_clockevent_init(void); +@@ -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); - #else - static inline int mips_clockevent_init(void) - { + extern int r4k_clockevent_init(void); + #endif + diff --git a/target/linux/ar71xx/patches-2.6.28/902-mips_clocksource_init_war.patch b/target/linux/ar71xx/patches-2.6.32/902-mips_clocksource_init_war.patch similarity index 91% rename from target/linux/ar71xx/patches-2.6.28/902-mips_clocksource_init_war.patch rename to target/linux/ar71xx/patches-2.6.32/902-mips_clocksource_init_war.patch index 03a66ff13..894eed1e5 100644 --- a/target/linux/ar71xx/patches-2.6.28/902-mips_clocksource_init_war.patch +++ b/target/linux/ar71xx/patches-2.6.32/902-mips_clocksource_init_war.patch @@ -1,6 +1,6 @@ --- a/arch/mips/kernel/cevt-r4k.c +++ b/arch/mips/kernel/cevt-r4k.c -@@ -15,6 +15,22 @@ +@@ -16,6 +16,22 @@ #include /* @@ -23,7 +23,7 @@ * 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 +@@ -31,6 +47,7 @@ static int mips_next_event(unsigned long cnt = read_c0_count(); cnt += delta; write_c0_compare(cnt); @@ -31,7 +31,7 @@ res = ((int)(read_c0_count() - cnt) > 0) ? -ETIME : 0; return res; } -@@ -99,22 +116,6 @@ static int c0_compare_int_pending(void) +@@ -100,22 +117,6 @@ static int c0_compare_int_pending(void) return (read_c0_cause() >> cp0_compare_irq) & 0x100; } diff --git a/target/linux/ar71xx/patches-2.6.32/960-ar8216-add-register-debug.patch b/target/linux/ar71xx/patches-2.6.32/960-ar8216-add-register-debug.patch new file mode 100644 index 000000000..f4d1e586e --- /dev/null +++ b/target/linux/ar71xx/patches-2.6.32/960-ar8216-add-register-debug.patch @@ -0,0 +1,257 @@ +--- a/drivers/net/phy/ar8216.c ++++ b/drivers/net/phy/ar8216.c +@@ -563,10 +563,227 @@ ar8216_config_aneg(struct phy_device *ph + return 0; + } + ++#define ar8216_dbg(fmt, args...) printk(KERN_DEBUG "ar8216: " fmt, ## args) ++ ++static inline const char *ctrl_state_str(u32 ctrl) ++{ ++ switch (ctrl & AR8216_PORT_CTRL_STATE) { ++ case AR8216_PORT_STATE_DISABLED: ++ return "disabled"; ++ case AR8216_PORT_STATE_BLOCK: ++ return "block"; ++ case AR8216_PORT_STATE_LISTEN: ++ return "listen"; ++ case AR8216_PORT_STATE_LEARN: ++ return "learn"; ++ case AR8216_PORT_STATE_FORWARD: ++ return "forward"; ++ default: ++ break; ++ } ++ ++ return "????"; ++} ++ ++static inline const char *ctrl_vlanmode_str(u32 ctrl) ++{ ++ u32 vlan_mode; ++ ++ vlan_mode = (ctrl & AR8216_PORT_CTRL_VLAN_MODE) >> ++ AR8216_PORT_CTRL_VLAN_MODE_S; ++ switch (vlan_mode) { ++ case AR8216_OUT_KEEP: ++ return "keep"; ++ case AR8216_OUT_STRIP_VLAN: ++ return "strip vlan"; ++ case AR8216_OUT_ADD_VLAN: ++ return "add_vlan"; ++ default: ++ break; ++ } ++ ++ return "????"; ++} ++ ++static inline const char *vlan_vlanmode_str(u32 vlan) ++{ ++ u32 vlan_mode; ++ ++ vlan_mode = (vlan & AR8216_PORT_VLAN_MODE) >> ++ AR8216_PORT_VLAN_MODE_S; ++ switch (vlan_mode) { ++ case AR8216_IN_PORT_ONLY: ++ return "port only"; ++ case AR8216_IN_PORT_FALLBACK: ++ return "port fallback"; ++ case AR8216_IN_VLAN_ONLY: ++ return "VLAN only"; ++ case AR8216_IN_SECURE: ++ return "secure"; ++ default: ++ break; ++ } ++ ++ return "????"; ++} ++ ++static void ++ar8216_dump_regs(struct ar8216_priv *ap) ++{ ++ unsigned int i; ++ u32 t; ++ ++ t = ar8216_mii_read(ap, AR8216_REG_CTRL); ++ ar8216_dbg("CTRL\t\t: %08x\n", t); ++ ar8216_dbg(" version\t: %u\n", (t & 0xff00) >> 8); ++ ar8216_dbg(" revision\t: %u\n", (t & 0xff)); ++ ++ ar8216_dbg("POWER_ON\t: %08x\n", ++ ar8216_mii_read(ap, 0x04)); ++ ar8216_dbg("INT\t\t: %08x\n", ++ ar8216_mii_read(ap, 0x10)); ++ ar8216_dbg("INT_MASK\t: %08x\n", ++ ar8216_mii_read(ap, 0x14)); ++ ar8216_dbg("MAC_ADDR0\t: %08x\n", ++ ar8216_mii_read(ap, 0x20)); ++ ar8216_dbg("MAC_ADDR1\t: %08x\n", ++ ar8216_mii_read(ap, 0x24)); ++ ar8216_dbg("FLOOD_MASK\t: %08x\n", ++ ar8216_mii_read(ap, 0x2c)); ++ ++ t = ar8216_mii_read(ap, AR8216_REG_GLOBAL_CTRL); ++ ar8216_dbg("GLOBAL_CTRL\t: %08x\n", t); ++ ar8216_dbg(" mtu\t\t: %lu\n", t & AR8216_GCTRL_MTU); ++ ++ ar8216_dbg("FLOW_CONTROL0\t: %08x\n", ++ ar8216_mii_read(ap, 0x34)); ++ ar8216_dbg("FLOW_CONTROL1\t: %08x\n", ++ ar8216_mii_read(ap, 0x38)); ++ ar8216_dbg("QM_CONTROL\t: %08x\n", ++ ar8216_mii_read(ap, 0x3c)); ++ ar8216_dbg("VLAN_TABLE0\t: %08x\n", ++ ar8216_mii_read(ap, AR8216_REG_VTU)); ++ ar8216_dbg("VLAN_TABLE1\t: %08x\n", ++ ar8216_mii_read(ap, AR8216_REG_VTU_DATA)); ++ ar8216_dbg("ADDR_TABLE0\t: %08x\n", ++ ar8216_mii_read(ap, AR8216_REG_ATU)); ++ ar8216_dbg("ADDR_TABLE1\t: %08x\n", ++ ar8216_mii_read(ap, AR8216_REG_ATU_DATA)); ++ ar8216_dbg("ADDR_TABLE2\t: %08x\n", ++ ar8216_mii_read(ap, 0x58)); ++ ar8216_dbg("ADDR_CTRL\t: %08x\n", ++ ar8216_mii_read(ap, 0x5c)); ++ ar8216_dbg("IP_PRIO0\t: %08x\n", ++ ar8216_mii_read(ap, 0x60)); ++ ar8216_dbg("IP_PRIO1\t: %08x\n", ++ ar8216_mii_read(ap, 0x64)); ++ ar8216_dbg("IP_PRIO2\t: %08x\n", ++ ar8216_mii_read(ap, 0x68)); ++ ar8216_dbg("IP_PRIO3\t: %08x\n", ++ ar8216_mii_read(ap, 0x6c)); ++ ar8216_dbg("TAG_PRIO\t: %08x\n", ++ ar8216_mii_read(ap, 0x70)); ++ ar8216_dbg("SERVICE_TAG\t: %08x\n", ++ ar8216_mii_read(ap, 0x74)); ++ ar8216_dbg("CPU_PORT\t: %08x\n", ++ ar8216_mii_read(ap, 0x78)); ++ ar8216_dbg("MIB_FUNC\t: %08x\n", ++ ar8216_mii_read(ap, 0x80)); ++ ar8216_dbg("MDIO\t\t: %08x\n", ++ ar8216_mii_read(ap, 0x98)); ++ ar8216_dbg("LED0\t\t: %08x\n", ++ ar8216_mii_read(ap, 0xb0)); ++ ar8216_dbg("LED1\t\t: %08x\n", ++ ar8216_mii_read(ap, 0xb4)); ++ ar8216_dbg("LED2\t\t: %08x\n", ++ ar8216_mii_read(ap, 0xb8)); ++ ++ for (i = 0; i < 6; i++) { ++ u32 reg = 0x100 * (i + 1); ++ ++ t = ar8216_mii_read(ap, AR8216_REG_PORT_STATUS(i)); ++ ar8216_dbg("PORT%d_STATUS\t: %08x\n", i, t); ++ ar8216_dbg(" speed\t\t: %s\n", ++ (t & AR8216_PORT_STATUS_SPEED) ? "100" : "10"); ++ ar8216_dbg(" speed error\t: %s\n", ++ (t & AR8216_PORT_STATUS_SPEED_ERR) ? "yes" : "no"); ++ ar8216_dbg(" txmac\t\t: %d\n", ++ (t & AR8216_PORT_STATUS_TXMAC) ? 1 : 0); ++ ar8216_dbg(" rxmac\t\t: %d\n", ++ (t & AR8216_PORT_STATUS_RXMAC) ? 1 : 0); ++ ar8216_dbg(" tx_flow\t: %s\n", ++ (t & AR8216_PORT_STATUS_TXFLOW) ? "on" : "off"); ++ ar8216_dbg(" rx_flow\t: %s\n", ++ (t & AR8216_PORT_STATUS_RXFLOW) ? "on" : "off"); ++ ar8216_dbg(" duplex\t: %s\n", ++ (t & AR8216_PORT_STATUS_DUPLEX) ? "full" : "half"); ++ ar8216_dbg(" link\t\t: %s\n", ++ (t & AR8216_PORT_STATUS_LINK_UP) ? "up" : "down"); ++ ar8216_dbg(" auto\t\t: %s\n", ++ (t & AR8216_PORT_STATUS_LINK_AUTO) ? "on" : "off"); ++ ar8216_dbg(" pause\t\t: %s\n", ++ (t & AR8216_PORT_STATUS_LINK_PAUSE) ? "on" : "off"); ++ ++ t = ar8216_mii_read(ap, AR8216_REG_PORT_CTRL(i)); ++ ar8216_dbg("PORT%d_CTRL\t: %08x\n", i, t); ++ ar8216_dbg(" state\t\t: %s\n", ctrl_state_str(t)); ++ ar8216_dbg(" learn lock\t: %s\n", ++ (t & AR8216_PORT_CTRL_LEARN_LOCK) ? "on" : "off"); ++ ar8216_dbg(" vlan_mode\t: %s\n", ctrl_vlanmode_str(t)); ++ ar8216_dbg(" igmp_snoop\t: %s\n", ++ (t & AR8216_PORT_CTRL_IGMP_SNOOP) ? "on" : "off"); ++ ar8216_dbg(" header\t: %s\n", ++ (t & AR8216_PORT_CTRL_HEADER) ? "on" : "off"); ++ ar8216_dbg(" mac_loop\t: %s\n", ++ (t & AR8216_PORT_CTRL_MAC_LOOP) ? "on" : "off"); ++ ar8216_dbg(" single_vlan\t: %s\n", ++ (t & AR8216_PORT_CTRL_SINGLE_VLAN) ? "on" : "off"); ++ ar8216_dbg(" mirror tx\t: %s\n", ++ (t & AR8216_PORT_CTRL_MIRROR_TX) ? "on" : "off"); ++ ar8216_dbg(" mirror rx\t: %s\n", ++ (t & AR8216_PORT_CTRL_MIRROR_RX) ? "on" : "off"); ++ ++ t = ar8216_mii_read(ap, AR8216_REG_PORT_VLAN(i)); ++ ar8216_dbg("PORT%d_VLAN\t: %08x\n", i, t); ++ ar8216_dbg(" default id\t: %lu\n", ++ (t & AR8216_PORT_VLAN_DEFAULT_ID)); ++ ar8216_dbg(" dest ports\t: %s%s%s%s%s%s\n", ++ (t & 0x010000) ? "0 " : "", ++ (t & 0x020000) ? "1 " : "", ++ (t & 0x040000) ? "2 " : "", ++ (t & 0x080000) ? "3 " : "", ++ (t & 0x100000) ? "4 " : "", ++ (t & 0x200000) ? "5 " : ""); ++ ar8216_dbg(" tx priority\t: %s\n", ++ (t & AR8216_PORT_VLAN_TX_PRIO) ? "on" : "off"); ++ ar8216_dbg(" port priority\t: %lu\n", ++ (t & AR8216_PORT_VLAN_PRIORITY) >> ++ AR8216_PORT_VLAN_PRIORITY_S); ++ ar8216_dbg(" ingress mode\t: %s\n", vlan_vlanmode_str(t)); ++ ++ t = ar8216_mii_read(ap, AR8216_REG_PORT_RATE(i)); ++ ar8216_dbg("PORT%d_RATE0\t: %08x\n", i, t); ++ ++ ar8216_dbg("PORT%d_PRIO\t: %08x\n", i, ++ ar8216_mii_read(ap, AR8216_REG_PORT_PRIO(i))); ++ ar8216_dbg("PORT%d_STORM\t: %08x\n", i, ++ ar8216_mii_read(ap, reg + 0x14)); ++ ar8216_dbg("PORT%d_QUEUE\t: %08x\n", i, ++ ar8216_mii_read(ap, reg + 0x18)); ++ ar8216_dbg("PORT%d_RATE1\t: %08x\n", i, ++ ar8216_mii_read(ap, reg + 0x1c)); ++ ar8216_dbg("PORT%d_RATE2\t: %08x\n", i, ++ ar8216_mii_read(ap, reg + 0x20)); ++ ar8216_dbg("PORT%d_RATE3\t: %08x\n", i, ++ ar8216_mii_read(ap, reg + 0x24)); ++ } ++} ++ + static int + ar8216_probe(struct phy_device *pdev) + { + struct ar8216_priv priv; ++ static int regs_dumped; + + u8 id, rev; + u32 val; +@@ -575,9 +792,14 @@ ar8216_probe(struct phy_device *pdev) + val = ar8216_mii_read(&priv, AR8216_REG_CTRL); + rev = val & 0xff; + id = (val >> 8) & 0xff; +- if ((id != 1) || (rev != 1)) ++ if ((id != 1) || (rev != 1 && rev != 2)) + return -ENODEV; + ++ if (!regs_dumped) { ++ ar8216_dump_regs(&priv); ++ regs_dumped++; ++ } ++ + return 0; + } + +--- a/drivers/net/phy/ar8216.h ++++ b/drivers/net/phy/ar8216.h +@@ -27,7 +27,7 @@ + #define AR8216_CTRL_RESET BIT(31) + + #define AR8216_REG_GLOBAL_CTRL 0x0030 +-#define AR8216_GCTRL_MTU BITS(0, 10) ++#define AR8216_GCTRL_MTU BITS(0, 12) + + #define AR8216_REG_VTU 0x0040 + #define AR8216_VTU_OP BITS(0, 3) diff --git a/target/linux/ar71xx/profiles/atheros.mk b/target/linux/ar71xx/profiles/atheros.mk new file mode 100644 index 000000000..91494a873 --- /dev/null +++ b/target/linux/ar71xx/profiles/atheros.mk @@ -0,0 +1,50 @@ +# +# Copyright (C) 2009-2010 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +define Profile/AP81 + NAME:=Atheros AP81 reference board + PACKAGES:=hostapd-mini kmod-ath9k kmod-usb-core kmod-usb2 +endef + +define Profile/AP81/Description + Package set optimized for the Atheros AP81 reference board. +endef + +$(eval $(call Profile,AP81)) + +define Profile/AP83 + NAME:=Atheros AP83 reference board + PACKAGES:=hostapd-mini kmod-ath9k kmod-usb-core kmod-usb2 +endef + +define Profile/AP83/Description + Package set optimized for the Atheros AP83 reference board. +endef + +$(eval $(call Profile,AP83)) + +define Profile/PB42 + NAME:=Atheros PB42 reference board + PACKAGES:=hostapd-mini kmod-ath9k kmod-usb-core kmod-usb-ohci kmod-usb2 +endef + +define Profile/PB42/Description + Package set optimized for the Atheros PB42 reference board. +endef + +$(eval $(call Profile,PB42)) + +define Profile/PB44 + NAME:=Atheros PB44 reference board + PACKAGES:=hostapd-mini kmod-ath9k kmod-usb-core kmod-usb-ohci kmod-usb2 +endef + +define Profile/PB44/Description + Package set optimized for the Atheros PB44 reference board. +endef + +$(eval $(call Profile,PB44)) diff --git a/target/linux/ar71xx/profiles/d-link.mk b/target/linux/ar71xx/profiles/d-link.mk index 460900ddf..d28a74ca9 100644 --- a/target/linux/ar71xx/profiles/d-link.mk +++ b/target/linux/ar71xx/profiles/d-link.mk @@ -5,6 +5,18 @@ # See /LICENSE for more information. # +define Profile/DIR600A1 + NAME:=D-Link DIR-600 rev. A1 + PACKAGES:=kmod-ath9k hostapd-mini +endef + +define Profile/DIR600A1/Description + Package set optimized for the D-Link DIR-600 rev. A1. +endef + +$(eval $(call Profile,DIR600A1)) + + define Profile/DIR615C1 NAME:=D-Link DIR-615 rev. C1 PACKAGES:=kmod-ath9k hostapd-mini @@ -15,3 +27,15 @@ define Profile/DIR615C1/Description endef $(eval $(call Profile,DIR615C1)) + + +define Profile/DIR825B1 + NAME:=D-Link DIR-825 rev. B1 + PACKAGES:=kmod-ath9k hostapd-mini +endef + +define Profile/DIR825B1/Description + Package set optimized for the D-Link DIR-825 rev. B1. +endef + +$(eval $(call Profile,DIR825B1)) diff --git a/target/linux/ar71xx/profiles/tp-link.mk b/target/linux/ar71xx/profiles/tp-link.mk index ab5ed54ca..1b9cace93 100644 --- a/target/linux/ar71xx/profiles/tp-link.mk +++ b/target/linux/ar71xx/profiles/tp-link.mk @@ -7,6 +7,7 @@ define Profile/TLWR741NDV1 NAME:=TP-LINK TL-WR741ND v1 + PACKAGES:=kmod-ath9k hostapd-mini endef define Profile/TLWR741NDV1/Description @@ -15,6 +16,17 @@ endef $(eval $(call Profile,TLWR741NDV1)) +define Profile/TLWR841NV15 + NAME:=TP-LINK TL-WR841N v1.5 + PACKAGES:=kmod-ath9k hostapd-mini +endef + +define Profile/TLWR841NV15/Description + Package set optimized for the TP-LINK TL-WR841N v1.5. +endef + +$(eval $(call Profile,TLWR841NV15)) + define Profile/TLWR841NDV3 NAME:=TP-LINK TL-WR841ND v3 PACKAGES:=kmod-ath9k hostapd-mini @@ -47,3 +59,14 @@ define Profile/TLWR941NDV2/Description endef $(eval $(call Profile,TLWR941NDV2)) + +define Profile/TLWR1043NDV1 + NAME:=TP-LINK TL-WR1043ND v1 + PACKAGES:=kmod-ath9k hostapd-mini kmod-usb-core kmod-usb2 +endef + +define Profile/TLWR1043NDV1/Description + Package set optimized for the TP-LINK TL-WR1043ND v1. +endef + +$(eval $(call Profile,TLWR1043NDV1)) diff --git a/target/linux/atheros/Makefile b/target/linux/atheros/Makefile index edee9e671..885a93aa4 100644 --- a/target/linux/atheros/Makefile +++ b/target/linux/atheros/Makefile @@ -11,7 +11,7 @@ BOARD:=atheros BOARDNAME:=Atheros AR231x/AR5312 FEATURES:=squashfs jffs2 -LINUX_VERSION:=2.6.30.9 +LINUX_VERSION:=2.6.30.10 include $(INCLUDE_DIR)/target.mk diff --git a/target/linux/au1000/Makefile b/target/linux/au1000/Makefile index e752ed853..d0bd1425a 100644 --- a/target/linux/au1000/Makefile +++ b/target/linux/au1000/Makefile @@ -12,7 +12,7 @@ BOARDNAME:=RMI/AMD AU1x00 FEATURES:=jffs2 usb pci SUBTARGETS=au1500 au1550 -LINUX_VERSION:=2.6.30.9 +LINUX_VERSION:=2.6.30.10 include $(INCLUDE_DIR)/target.mk DEFAULT_PACKAGES += hostapd-mini yamonenv diff --git a/target/linux/au1000/patches-2.6.28/001-mtx1_cmdline.patch b/target/linux/au1000/patches-2.6.28/001-mtx1_cmdline.patch deleted file mode 100644 index a45832765..000000000 --- a/target/linux/au1000/patches-2.6.28/001-mtx1_cmdline.patch +++ /dev/null @@ -1,11 +0,0 @@ ---- a/arch/mips/alchemy/mtx-1/init.c -+++ b/arch/mips/alchemy/mtx-1/init.c -@@ -49,7 +49,7 @@ void __init prom_init(void) - prom_argv = (char **)fw_arg1; - prom_envp = (char **)fw_arg2; - -- prom_init_cmdline(); -+ strcpy(arcs_cmdline, CONFIG_CMDLINE); - - memsize_str = prom_getenv("memsize"); - if (!memsize_str) diff --git a/target/linux/au1000/patches-2.6.28/002-openwrt_rootfs.patch b/target/linux/au1000/patches-2.6.28/002-openwrt_rootfs.patch deleted file mode 100644 index e1056e93d..000000000 --- a/target/linux/au1000/patches-2.6.28/002-openwrt_rootfs.patch +++ /dev/null @@ -1,11 +0,0 @@ ---- a/arch/mips/alchemy/mtx-1/platform.c -+++ b/arch/mips/alchemy/mtx-1/platform.c -@@ -90,7 +90,7 @@ static struct platform_device mtx1_gpio_ - - static struct mtd_partition mtx1_mtd_partitions[] = { - { -- .name = "filesystem", -+ .name = "rootfs", - .size = 0x01C00000, - .offset = 0, - }, diff --git a/target/linux/au1000/patches-2.6.28/003-au1000_eth_ioctl.patch b/target/linux/au1000/patches-2.6.28/003-au1000_eth_ioctl.patch deleted file mode 100644 index 4b152f3aa..000000000 --- a/target/linux/au1000/patches-2.6.28/003-au1000_eth_ioctl.patch +++ /dev/null @@ -1,15 +0,0 @@ ---- a/drivers/net/au1000_eth.c -+++ b/drivers/net/au1000_eth.c -@@ -1293,9 +1293,12 @@ static void set_rx_mode(struct net_devic - } - } - -+#define AU1000_KNOWN_PHY_IOCTLS (SIOCGMIIPHY & 0xfff0) - static int au1000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) - { - struct au1000_private *aup = (struct au1000_private *)dev->priv; -+ if((cmd & AU1000_KNOWN_PHY_IOCTLS) != AU1000_KNOWN_PHY_IOCTLS) -+ return -EINVAL; - - if (!netif_running(dev)) return -EINVAL; - diff --git a/target/linux/au1000/patches-2.6.28/004-state_led_phy_fix.patch b/target/linux/au1000/patches-2.6.28/004-state_led_phy_fix.patch deleted file mode 100644 index e681970c5..000000000 --- a/target/linux/au1000/patches-2.6.28/004-state_led_phy_fix.patch +++ /dev/null @@ -1,31 +0,0 @@ ---- a/drivers/net/au1000_eth.c -+++ b/drivers/net/au1000_eth.c -@@ -184,6 +184,15 @@ struct au1000_private *au_macs[NUM_ETH_I - # undef AU1XXX_PHY1_IRQ - #endif - -+#if defined(CONFIG_MIPS_MTX1) -+/* -+ * 4G MeshCube (MTX-1) board -+ * PHY is at address 31 on MAC0 -+ * autodetect fails if not searched for highest address ! -+ */ -+# define AU1XXX_PHY_SEARCH_HIGHEST_ADDR -+#endif -+ - #if defined(AU1XXX_PHY0_BUSID) && (AU1XXX_PHY0_BUSID > 0) - # error MAC0-associated PHY attached 2nd MACs MII bus not supported yet - #endif -@@ -380,6 +389,12 @@ static int mii_probe (struct net_device - aup->old_duplex = -1; - aup->phy_dev = phydev; - -+#ifdef CONFIG_MIPS_MTX1 -+ /* set up ethernet jack LEDs on the 4G MeshCube (MTX-1 board) */ -+ printk(KERN_INFO "MTX-1 PHY: updating LED settings\n"); -+ phy_write(phydev, 0x11, 0xff80); -+#endif -+ - printk(KERN_INFO "%s: attached PHY driver [%s] " - "(mii_bus:phy_addr=%s, irq=%d)\n", - dev->name, phydev->drv->name, phydev->dev.bus_id, phydev->irq); diff --git a/target/linux/au1000/patches-2.6.28/006-missing_string_header.patch b/target/linux/au1000/patches-2.6.28/006-missing_string_header.patch deleted file mode 100644 index 8aba20252..000000000 --- a/target/linux/au1000/patches-2.6.28/006-missing_string_header.patch +++ /dev/null @@ -1,10 +0,0 @@ ---- a/arch/mips/alchemy/mtx-1/init.c -+++ b/arch/mips/alchemy/mtx-1/init.c -@@ -32,6 +32,7 @@ - #include - - #include -+#include - - #include - diff --git a/target/linux/au1000/patches-2.6.28/007-gpiolib.patch b/target/linux/au1000/patches-2.6.28/007-gpiolib.patch deleted file mode 100644 index bd4b5635a..000000000 --- a/target/linux/au1000/patches-2.6.28/007-gpiolib.patch +++ /dev/null @@ -1,396 +0,0 @@ ---- a/arch/mips/alchemy/Kconfig -+++ b/arch/mips/alchemy/Kconfig -@@ -134,3 +134,4 @@ config SOC_AU1X00 - select SYS_HAS_CPU_MIPS32_R1 - select SYS_SUPPORTS_32BIT_KERNEL - select SYS_SUPPORTS_APM_EMULATION -+ select ARCH_REQUIRE_GPIOLIB ---- a/arch/mips/alchemy/common/gpio.c -+++ b/arch/mips/alchemy/common/gpio.c -@@ -1,5 +1,5 @@ - /* -- * Copyright (C) 2007, OpenWrt.org, Florian Fainelli -+ * Copyright (C) 2007-2008, OpenWrt.org, Florian Fainelli - * Architecture specific GPIO support - * - * This program is free software; you can redistribute it and/or modify it -@@ -27,122 +27,222 @@ - * others have a second one : GPIO2 - */ - -+#include - #include -+#include -+#include -+#include - - #include --#include -+#include - --#define gpio1 sys --#if !defined(CONFIG_SOC_AU1000) -+struct au1000_gpio_chip { -+ struct gpio_chip chip; -+ void __iomem *regbase; -+}; - --static struct au1x00_gpio2 *const gpio2 = (struct au1x00_gpio2 *) GPIO2_BASE; -+#if !defined(CONFIG_SOC_AU1000) - #define GPIO2_OUTPUT_ENABLE_MASK 0x00010000 - --static int au1xxx_gpio2_read(unsigned gpio) -+/* -+ * Return GPIO bank 2 level -+ */ -+static int au1000_gpio2_get(struct gpio_chip *chip, unsigned offset) - { -- gpio -= AU1XXX_GPIO_BASE; -- return ((gpio2->pinstate >> gpio) & 0x01); -+ u32 mask = 1 << offset; -+ struct au1000_gpio_chip *gpch; -+ -+ gpch = container_of(chip, struct au1000_gpio_chip, chip); -+ return readl(gpch->regbase + AU1000_GPIO2_ST) & mask; - } - --static void au1xxx_gpio2_write(unsigned gpio, int value) -+/* -+ * Set output GPIO bank 2 level -+ */ -+static void au1000_gpio2_set(struct gpio_chip *chip, -+ unsigned offset, int value) - { -- gpio -= AU1XXX_GPIO_BASE; -- -- gpio2->output = (GPIO2_OUTPUT_ENABLE_MASK << gpio) | ((!!value) << gpio); -+ u32 mask = (!!value) << offset; -+ struct au1000_gpio_chip *gpch; -+ unsigned long flags; -+ -+ gpch = container_of(chip, struct au1000_gpio_chip, chip); -+ -+ local_irq_save(flags); -+ writel((GPIO2_OUTPUT_ENABLE_MASK << offset) | mask, -+ gpch->regbase + AU1000_GPIO2_OUT); -+ local_irq_restore(flags); - } - --static int au1xxx_gpio2_direction_input(unsigned gpio) -+/* -+ * Set GPIO bank 2 direction to input -+ */ -+static int au1000_gpio2_direction_input(struct gpio_chip *chip, unsigned offset) - { -- gpio -= AU1XXX_GPIO_BASE; -- gpio2->dir &= ~(0x01 << gpio); -+ unsigned long flags; -+ u32 mask = 1 << offset; -+ u32 value; -+ struct au1000_gpio_chip *gpch; -+ void __iomem *gpdr; -+ -+ gpch = container_of(chip, struct au1000_gpio_chip, chip); -+ gpdr = gpch->regbase + AU1000_GPIO2_DIR; -+ -+ local_irq_save(flags); -+ value = readl(gpdr); -+ value &= ~mask; -+ writel(value, gpdr); -+ local_irq_restore(flags); -+ - return 0; - } - --static int au1xxx_gpio2_direction_output(unsigned gpio, int value) -+/* -+ * Set GPIO bank2 direction to output -+ */ -+static int au1000_gpio2_direction_output(struct gpio_chip *chip, -+ unsigned offset, int value) - { -- gpio -= AU1XXX_GPIO_BASE; -- gpio2->dir |= 0x01 << gpio; -- gpio2->output = (GPIO2_OUTPUT_ENABLE_MASK << gpio) | ((!!value) << gpio); -+ unsigned long flags; -+ u32 mask = 1 << offset; -+ u32 tmp; -+ struct au1000_gpio_chip *gpch; -+ void __iomem *gpdr; -+ -+ gpch = container_of(chip, struct au1000_gpio_chip, chip); -+ gpdr = gpch->regbase + AU1000_GPIO2_DIR; -+ -+ local_irq_save(flags); -+ tmp = readl(gpdr); -+ tmp |= mask; -+ writel(tmp, gpdr); -+ mask = (!!value) << offset; -+ writel((GPIO2_OUTPUT_ENABLE_MASK << offset) | mask, -+ gpch->regbase + AU1000_GPIO2_OUT); -+ local_irq_restore(flags); -+ - return 0; - } -- - #endif /* !defined(CONFIG_SOC_AU1000) */ - --static int au1xxx_gpio1_read(unsigned gpio) -+/* -+ * Return GPIO bank 2 level -+ */ -+static int au1000_gpio1_get(struct gpio_chip *chip, unsigned offset) - { -- return (gpio1->pinstaterd >> gpio) & 0x01; -+ u32 mask = 1 << offset; -+ struct au1000_gpio_chip *gpch; -+ -+ gpch = container_of(chip, struct au1000_gpio_chip, chip); -+ return readl(gpch->regbase + 0x0110) & mask; - } - --static void au1xxx_gpio1_write(unsigned gpio, int value) -+/* -+ * Set GPIO bank 1 level -+ */ -+static void au1000_gpio1_set(struct gpio_chip *chip, -+ unsigned offset, int value) - { -+ unsigned long flags; -+ u32 mask = 1 << offset; -+ struct au1000_gpio_chip *gpch; -+ -+ gpch = container_of(chip, struct au1000_gpio_chip, chip); -+ -+ local_irq_save(flags); - if (value) -- gpio1->outputset = (0x01 << gpio); -+ writel(mask, gpch->regbase + 0x0108); - else -- /* Output a zero */ -- gpio1->outputclr = (0x01 << gpio); -+ writel(mask, gpch->regbase + 0x010C); -+ local_irq_restore(flags); - } - --static int au1xxx_gpio1_direction_input(unsigned gpio) -+/* -+ * Set GPIO bank 1 direction to input -+ */ -+static int au1000_gpio1_direction_input(struct gpio_chip *chip, unsigned offset) - { -- gpio1->pininputen = (0x01 << gpio); -- return 0; --} -+ unsigned long flags; -+ u32 mask = 1 << offset; -+ u32 value; -+ struct au1000_gpio_chip *gpch; -+ void __iomem *gpdr; -+ -+ gpch = container_of(chip, struct au1000_gpio_chip, chip); -+ gpdr = gpch->regbase + 0x0110; -+ -+ local_irq_save(flags); -+ value = readl(gpdr); -+ value |= mask; -+ writel(mask, gpdr); -+ local_irq_restore(flags); - --static int au1xxx_gpio1_direction_output(unsigned gpio, int value) --{ -- gpio1->trioutclr = (0x01 & gpio); -- au1xxx_gpio1_write(gpio, value); - return 0; - } - --int au1xxx_gpio_get_value(unsigned gpio) -+/* -+ * Set GPIO bank 1 direction to output -+ */ -+static int au1000_gpio1_direction_output(struct gpio_chip *chip, -+ unsigned offset, int value) - { -- if (gpio >= AU1XXX_GPIO_BASE) --#if defined(CONFIG_SOC_AU1000) -- return 0; --#else -- return au1xxx_gpio2_read(gpio); --#endif -+ unsigned long flags; -+ u32 mask = 1 << offset; -+ u32 tmp; -+ struct au1000_gpio_chip *gpch; -+ void __iomem *gpdr; -+ -+ gpch = container_of(chip, struct au1000_gpio_chip, chip); -+ gpdr = gpch->regbase + 0x0100; -+ -+ local_irq_save(flags); -+ tmp = readl(gpdr); -+ writel(tmp, gpdr); -+ if (value) -+ writel(mask, gpch->regbase + 0x0108); - else -- return au1xxx_gpio1_read(gpio); --} --EXPORT_SYMBOL(au1xxx_gpio_get_value); -+ writel(mask, gpch->regbase + 0x0108); -+ local_irq_restore(flags); - --void au1xxx_gpio_set_value(unsigned gpio, int value) --{ -- if (gpio >= AU1XXX_GPIO_BASE) --#if defined(CONFIG_SOC_AU1000) -- ; --#else -- au1xxx_gpio2_write(gpio, value); --#endif -- else -- au1xxx_gpio1_write(gpio, value); -+ return 0; - } --EXPORT_SYMBOL(au1xxx_gpio_set_value); - --int au1xxx_gpio_direction_input(unsigned gpio) --{ -- if (gpio >= AU1XXX_GPIO_BASE) --#if defined(CONFIG_SOC_AU1000) -- return -ENODEV; --#else -- return au1xxx_gpio2_direction_input(gpio); -+struct au1000_gpio_chip au1000_gpio_chip[] = { -+ [0] = { -+ .regbase = (void __iomem *)SYS_BASE, -+ .chip = { -+ .label = "au1000-gpio1", -+ .direction_input = au1000_gpio1_direction_input, -+ .direction_output = au1000_gpio1_direction_output, -+ .get = au1000_gpio1_get, -+ .set = au1000_gpio1_set, -+ .base = 0, -+ .ngpio = 32, -+ }, -+ }, -+#if !defined(CONFIG_SOC_AU1000) -+ [1] = { -+ .regbase = (void __iomem *)GPIO2_BASE, -+ .chip = { -+ .label = "au1000-gpio2", -+ .direction_input = au1000_gpio2_direction_input, -+ .direction_output = au1000_gpio2_direction_output, -+ .get = au1000_gpio2_get, -+ .set = au1000_gpio2_set, -+ .base = AU1XXX_GPIO_BASE, -+ .ngpio = 32, -+ }, -+ }, - #endif -+}; - -- return au1xxx_gpio1_direction_input(gpio); --} --EXPORT_SYMBOL(au1xxx_gpio_direction_input); -- --int au1xxx_gpio_direction_output(unsigned gpio, int value) -+int __init au1000_gpio_init(void) - { -- if (gpio >= AU1XXX_GPIO_BASE) --#if defined(CONFIG_SOC_AU1000) -- return -ENODEV; --#else -- return au1xxx_gpio2_direction_output(gpio, value); -+ gpiochip_add(&au1000_gpio_chip[0].chip); -+#if !defined(CONFIG_SOC_AU1000) -+ gpiochip_add(&au1000_gpio_chip[1].chip); - #endif - -- return au1xxx_gpio1_direction_output(gpio, value); -+ return 0; - } --EXPORT_SYMBOL(au1xxx_gpio_direction_output); -+arch_initcall(au1000_gpio_init); ---- a/arch/mips/include/asm/mach-au1x00/gpio.h -+++ b/arch/mips/include/asm/mach-au1x00/gpio.h -@@ -1,69 +1,21 @@ - #ifndef _AU1XXX_GPIO_H_ - #define _AU1XXX_GPIO_H_ - --#include -- - #define AU1XXX_GPIO_BASE 200 - --struct au1x00_gpio2 { -- u32 dir; -- u32 reserved; -- u32 output; -- u32 pinstate; -- u32 inten; -- u32 enable; --}; -- --extern int au1xxx_gpio_get_value(unsigned gpio); --extern void au1xxx_gpio_set_value(unsigned gpio, int value); --extern int au1xxx_gpio_direction_input(unsigned gpio); --extern int au1xxx_gpio_direction_output(unsigned gpio, int value); -- -- --/* Wrappers for the arch-neutral GPIO API */ -- --static inline int gpio_request(unsigned gpio, const char *label) --{ -- /* Not yet implemented */ -- return 0; --} -- --static inline void gpio_free(unsigned gpio) --{ -- /* Not yet implemented */ --} -- --static inline int gpio_direction_input(unsigned gpio) --{ -- return au1xxx_gpio_direction_input(gpio); --} -- --static inline int gpio_direction_output(unsigned gpio, int value) --{ -- return au1xxx_gpio_direction_output(gpio, value); --} -- --static inline int gpio_get_value(unsigned gpio) --{ -- return au1xxx_gpio_get_value(gpio); --} -- --static inline void gpio_set_value(unsigned gpio, int value) --{ -- au1xxx_gpio_set_value(gpio, value); --} -- --static inline int gpio_to_irq(unsigned gpio) --{ -- return gpio; --} -- --static inline int irq_to_gpio(unsigned irq) --{ -- return irq; --} -+#define AU1000_GPIO2_DIR 0x00 -+#define AU1000_GPIO2_RSVD 0x04 -+#define AU1000_GPIO2_OUT 0x08 -+#define AU1000_GPIO2_ST 0x0C -+#define AU1000_GPIO2_INT 0x10 -+#define AU1000_GPIO2_EN 0x14 -+ -+#define gpio_get_value __gpio_get_value -+#define gpio_set_value __gpio_set_value -+ -+#define gpio_to_irq(gpio) NULL -+#define irq_to_gpio(irq) NULL - --/* For cansleep */ - #include - - #endif /* _AU1XXX_GPIO_H_ */ diff --git a/target/linux/avr32/Makefile b/target/linux/avr32/Makefile index 02dca1cc9..0cffccb8e 100644 --- a/target/linux/avr32/Makefile +++ b/target/linux/avr32/Makefile @@ -10,7 +10,7 @@ ARCH:=avr32 BOARD:=avr32 BOARDNAME:=Atmel AVR32 FEATURES:=squashfs -LINUX_VERSION:=2.6.30.9 +LINUX_VERSION:=2.6.30.10 include $(INCLUDE_DIR)/target.mk diff --git a/target/linux/brcm-2.4/base-files/etc/init.d/netconfig b/target/linux/brcm-2.4/base-files/etc/init.d/netconfig index b5d900a73..d63f17b12 100755 --- a/target/linux/brcm-2.4/base-files/etc/init.d/netconfig +++ b/target/linux/brcm-2.4/base-files/etc/init.d/netconfig @@ -15,10 +15,10 @@ start() { vlan[0-9]|vlan1[0-5]) local id="${1#vlan}" append batch "delete network.eth0.${1}${N}" - append batch "set network.eth0_${n}=switch_vlan${N}" - append batch "set network.eth0_${n}.device=eth0${N}" - append batch "set network.eth0_${n}.vlan=${id}${N}" - append batch "set network.eth0_${n}.ports='${2}'${N}" + append batch "set network.eth0_${id}=switch_vlan${N}" + append batch "set network.eth0_${id}.device=eth0${N}" + append batch "set network.eth0_${id}.vlan=${id}${N}" + append batch "set network.eth0_${id}.ports='${2}'${N}" ;; esac } @@ -164,8 +164,10 @@ start() { c["lan_ifname"] = "eth0" c["wan_ifname"] = "eth1" } - if (nvram["boardtype"] == "0x478") { - # generic broadcom 4785 processor with 5397 switch? + # generic broadcom 4705/4785 processor with 5397 switch? + # EXCEPT Linksys WRT300N V1.1 + if ((nvram["boardtype"] == "0x478") && \ + (model != "Linksys WRT300N V1.1")) { c["vlan0ports"] = "1 2 3 4 8*" c["vlan1ports"] = "0 8" } diff --git a/target/linux/brcm-2.4/image/Makefile b/target/linux/brcm-2.4/image/Makefile index 39570200a..3dad1cee7 100644 --- a/target/linux/brcm-2.4/image/Makefile +++ b/target/linux/brcm-2.4/image/Makefile @@ -68,7 +68,8 @@ define Image/Build/jffs2-64k $(call Image/Build/CyberTAN,$(1),wrt54g,W54G,4.71.1,$(patsubst jffs2-%,jffs2,$(1))) $(call Image/Build/CyberTAN,$(1),wrt54gs_v4,W54s,1.09.1,$(patsubst jffs2-%,jffs2,$(1))) $(call Image/Build/CyberTAN,$(1),wrt150n,N150,1.51.3,$(patsubst jffs2-%,jffs2,$(1))) - $(call Image/Build/CyberTAN,$(1),wrt300n_v1,EWCB,1.51.2,$(patsubst jffs2-%,jffs2,$(1))) + $(call Image/Build/CyberTAN,$(1),wrt300n_v1,EWCB,1.03.6,$(patsubst jffs2-%,jffs2,$(1))) + $(call Image/Build/CyberTAN,$(1),wrt300n_v11,EWC2,1.51.2,$(patsubst jffs2-%,jffs2,$(1))) $(call Image/Build/CyberTAN,$(1),wrt350n_v1,EWCG,1.04.1,$(patsubst jffs2-%,jffs2,$(1))) $(call Image/Build/Motorola,$(1),wa840g,2,$(patsubst jffs2-%,jffs2,$(1))) $(call Image/Build/Motorola,$(1),we800g,3,$(patsubst jffs2-%,jffs2,$(1))) diff --git a/target/linux/brcm-2.4/profiles/WRT300Nv11.mk b/target/linux/brcm-2.4/profiles/WRT300Nv11.mk new file mode 100644 index 000000000..dddcd1424 --- /dev/null +++ b/target/linux/brcm-2.4/profiles/WRT300Nv11.mk @@ -0,0 +1,17 @@ +# +# Copyright (C) 2006-2008 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +define Profile/WRT300Nv11 + NAME:=Linksys WRT300N v1.1 + PACKAGES:=kmod-brcm-wl-mimo wlc nas kmod-wlcompat kmod-brcm-57xx +endef + +define Profile/WRT300Nv11/Description + Package set optimized for the WRT300N v1.1 +endef +$(eval $(call Profile,WRT300Nv11)) + diff --git a/target/linux/brcm47xx/Makefile b/target/linux/brcm47xx/Makefile index 421bddf24..f1344956a 100644 --- a/target/linux/brcm47xx/Makefile +++ b/target/linux/brcm47xx/Makefile @@ -11,7 +11,7 @@ BOARD:=brcm47xx BOARDNAME:=Broadcom BCM947xx/953xx FEATURES:=squashfs usb -LINUX_VERSION:=2.6.30.9 +LINUX_VERSION:=2.6.30.10 include $(INCLUDE_DIR)/target.mk DEFAULT_PACKAGES += hostapd-mini kmod-switch kmod-diag nvram diff --git a/target/linux/brcm47xx/config-2.6.28 b/target/linux/brcm47xx/config-2.6.32 similarity index 82% rename from target/linux/brcm47xx/config-2.6.28 rename to target/linux/brcm47xx/config-2.6.32 index 509384ef8..ca7914753 100644 --- a/target/linux/brcm47xx/config-2.6.28 +++ b/target/linux/brcm47xx/config-2.6.32 @@ -1,6 +1,5 @@ CONFIG_32BIT=y # CONFIG_64BIT is not set -# CONFIG_8139TOO is not set # CONFIG_ARCH_HAS_ILOG2_U32 is not set # CONFIG_ARCH_HAS_ILOG2_U64 is not set CONFIG_ARCH_POPULATES_NODE_MAP=y @@ -14,14 +13,20 @@ CONFIG_B44_PCI=y CONFIG_B44=y CONFIG_BCM47XX_WDT=y CONFIG_BCM47XX=y +# CONFIG_ALCHEMY_GPIO_INDIRECT is not set +# CONFIG_AR7 is not set +# CONFIG_BCM63XX is not set +# CONFIG_BINARY_PRINTF is not set CONFIG_BITREVERSE=y -# CONFIG_BSD_DISKLABEL is not set # CONFIG_BSD_PROCESS_ACCT is not set +# CONFIG_CAVIUM_OCTEON_REFERENCE_BOARD is not set +# CONFIG_CAVIUM_OCTEON_SIMULATOR is not set +CONFIG_CEVT_R4K_LIB=y CONFIG_CEVT_R4K=y CONFIG_CFE=y -CONFIG_CLASSIC_RCU=y CONFIG_CMDLINE="root=/dev/mtdblock2 rootfstype=squashfs,jffs2 noinitrd console=ttyS0,115200" # CONFIG_CPU_BIG_ENDIAN is not set +# CONFIG_CPU_CAVIUM_OCTEON is not set CONFIG_CPU_HAS_LLSC=y CONFIG_CPU_HAS_PREFETCH=y CONFIG_CPU_HAS_SYNC=y @@ -51,7 +56,15 @@ CONFIG_CPU_SUPPORTS_HIGHMEM=y # CONFIG_CPU_TX39XX is not set # CONFIG_CPU_TX49XX is not set # CONFIG_CPU_VR41XX is not set +CONFIG_CRYPTO_AEAD2=y +CONFIG_CRYPTO_BLKCIPHER2=y +CONFIG_CRYPTO_HASH2=y +CONFIG_CRYPTO_MANAGER2=y +CONFIG_CRYPTO_RNG2=y +CONFIG_CRYPTO_WORKQUEUE=y +CONFIG_CSRC_R4K_LIB=y CONFIG_CSRC_R4K=y +CONFIG_DECOMPRESS_LZMA=y CONFIG_DEVPORT=y # CONFIG_DM9000 is not set CONFIG_DMA_NEED_PCI_MAP_STATE=y @@ -59,9 +72,10 @@ CONFIG_DMA_NONCOHERENT=y CONFIG_GENERIC_CLOCKEVENTS_BUILD=y CONFIG_GENERIC_CLOCKEVENTS=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_GENERIC_HARDIRQS_NO__DO_IRQ=y # CONFIG_HAMRADIO is not set CONFIG_HARDWARE_WATCHPOINTS=y CONFIG_HAS_DMA=y @@ -70,13 +84,13 @@ CONFIG_HAS_IOPORT=y CONFIG_HAVE_ARCH_KGDB=y # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set CONFIG_HAVE_IDE=y +CONFIG_HAVE_MLOCK=y CONFIG_HAVE_OPROFILE=y CONFIG_HW_HAS_PCI=y CONFIG_HW_RANDOM=y # CONFIG_HZ_100 is not set CONFIG_HZ=250 CONFIG_HZ_250=y -# CONFIG_IDE is not set CONFIG_INITRAMFS_SOURCE="" # CONFIG_IP_ROUTE_VERBOSE is not set CONFIG_IRQ_CPU=y @@ -86,7 +100,6 @@ CONFIG_LEDS_GPIO=y # CONFIG_LEMOTE_FULONG is not set # CONFIG_MACH_ALCHEMY is not set # CONFIG_MACH_DECSTATION is not set -# CONFIG_MACH_EMMA is not set # CONFIG_MACH_JAZZ is not set # CONFIG_MACH_TX39XX is not set # CONFIG_MACH_TX49XX is not set @@ -114,8 +127,7 @@ CONFIG_PHYLIB=y # CONFIG_PNX8550_STB810 is not set # CONFIG_PROBE_INITRD_HEADER is not set # CONFIG_PROC_KCORE is not set -# CONFIG_R6040 is not set -CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y +CONFIG_SCHED_OMIT_FRAME_POINTER=y # CONFIG_SCSI_DMA is not set # CONFIG_SERIAL_8250_DETECT_IRQ is not set CONFIG_SERIAL_8250_EXTENDED=y @@ -134,6 +146,7 @@ CONFIG_SERIAL_8250_SHARE_IRQ=y # CONFIG_SIBYTE_RHONE is not set # CONFIG_SIBYTE_SENTOSA is not set # CONFIG_SIBYTE_SWARM is not set +# CONFIG_SLOW_WORK is not set CONFIG_SSB_B43_PCI_BRIDGE=y CONFIG_SSB_DEBUG=y CONFIG_SSB_DRIVER_EXTIF=y @@ -153,11 +166,18 @@ CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y CONFIG_SYS_SUPPORTS_ARBIT_HZ=y CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y # CONFIG_TC35815 is not set +CONFIG_TRACING_SUPPORT=y CONFIG_TRAD_SIGNALS=y CONFIG_USB_EHCI_HCD_SSB=y CONFIG_USB_OHCI_HCD_SSB=y CONFIG_USB_SUPPORT=y -# CONFIG_VGASTATE is not set -# CONFIG_VIA_RHINE is not set CONFIG_WATCHDOG_NOWAYOUT=y CONFIG_ZONE_DMA_FLAG=0 +CONFIG_TREE_RCU=y +CONFIG_HAVE_GENERIC_DMA_COHERENT=y +CONFIG_ARCH_HIBERNATION_POSSIBLE=y +# CONFIG_MACH_LOONGSON is not set +# CONFIG_CPU_LOONGSON2E is not set +# CONFIG_TREE_PREEMPT_RCU is not set +# CONFIG_FSNOTIFY is not set + diff --git a/target/linux/brcm47xx/patches-2.6.28/212-b44_alignment_fix.patch b/target/linux/brcm47xx/patches-2.6.28/212-b44_alignment_fix.patch deleted file mode 100644 index b5840f296..000000000 --- a/target/linux/brcm47xx/patches-2.6.28/212-b44_alignment_fix.patch +++ /dev/null @@ -1,48 +0,0 @@ ---- a/drivers/net/b44.c -+++ b/drivers/net/b44.c -@@ -73,8 +73,8 @@ - (BP)->tx_cons - (BP)->tx_prod - TX_RING_GAP(BP)) - #define NEXT_TX(N) (((N) + 1) & (B44_TX_RING_SIZE - 1)) - --#define RX_PKT_OFFSET 30 --#define RX_PKT_BUF_SZ (1536 + RX_PKT_OFFSET + 64) -+#define RX_PKT_OFFSET (RX_HEADER_LEN + 2) -+#define RX_PKT_BUF_SZ (1536 + RX_PKT_OFFSET) - - /* minimum number of free TX descriptors required to wake up TX process */ - #define B44_TX_WAKEUP_THRESH (B44_TX_RING_SIZE / 4) -@@ -682,7 +682,6 @@ static int b44_alloc_rx_skb(struct b44 * - } - - rh = (struct rx_header *) skb->data; -- skb_reserve(skb, RX_PKT_OFFSET); - - rh->len = 0; - rh->flags = 0; -@@ -693,13 +692,13 @@ static int b44_alloc_rx_skb(struct b44 * - if (src_map != NULL) - src_map->skb = NULL; - -- ctrl = (DESC_CTRL_LEN & (RX_PKT_BUF_SZ - RX_PKT_OFFSET)); -+ ctrl = (DESC_CTRL_LEN & RX_PKT_BUF_SZ); - if (dest_idx == (B44_RX_RING_SIZE - 1)) - ctrl |= DESC_CTRL_EOT; - - dp = &bp->rx_ring[dest_idx]; - dp->ctrl = cpu_to_le32(ctrl); -- dp->addr = cpu_to_le32((u32) mapping + RX_PKT_OFFSET + bp->dma_offset); -+ dp->addr = cpu_to_le32((u32) mapping + bp->dma_offset); - - if (bp->flags & B44_FLAG_RX_RING_HACK) - b44_sync_dma_desc_for_device(bp->sdev, bp->rx_ring_dma, -@@ -809,8 +808,8 @@ static int b44_rx(struct b44 *bp, int bu - ssb_dma_unmap_single(bp->sdev, map, - skb_size, DMA_FROM_DEVICE); - /* Leave out rx_header */ -- skb_put(skb, len + RX_PKT_OFFSET); -- skb_pull(skb, RX_PKT_OFFSET); -+ skb_put(skb, len + RX_PKT_OFFSET); -+ skb_pull(skb, RX_PKT_OFFSET); - } else { - struct sk_buff *copy_skb; - diff --git a/target/linux/brcm47xx/patches-2.6.28/500-lzma_initramfs.patch b/target/linux/brcm47xx/patches-2.6.28/500-lzma_initramfs.patch deleted file mode 100644 index 6a4a666c3..000000000 --- a/target/linux/brcm47xx/patches-2.6.28/500-lzma_initramfs.patch +++ /dev/null @@ -1,125 +0,0 @@ ---- a/init/initramfs.c -+++ b/init/initramfs.c -@@ -7,6 +7,7 @@ - #include - #include - #include -+#include - - static __initdata char *message; - static void __init error(char *x) -@@ -475,6 +476,69 @@ static void __init flush_window(void) - outcnt = 0; - } - -+#include -+static int __init lzma_unzip(void) -+{ -+ unsigned int i; /* temp value */ -+ unsigned int lc; /* literal context bits */ -+ unsigned int lp; /* literal pos state bits */ -+ unsigned int pb; /* pos state bits */ -+ unsigned int osize; /* uncompressed size */ -+ unsigned char *workspace; -+ unsigned char* outputbuffer; -+ unsigned int outsizeProcessed = 0; -+ int workspace_size; -+ int res; -+ -+ // lzma args -+ i = get_byte(); -+ lc = i % 9, i = i / 9; -+ lp = i % 5, pb = i / 5; -+ -+ // skip dictionary size -+ for (i = 0; i < 4; i++) -+ get_byte(); -+ -+ /* read the lower half of uncompressed size in the header */ -+ osize = ((unsigned int)get_byte()) + -+ ((unsigned int)get_byte() << 8) + -+ ((unsigned int)get_byte() << 16) + -+ ((unsigned int)get_byte() << 24); -+ -+ /* skip rest of the header (upper half of uncompressed size) */ -+ for (i = 0; i < 4; i++) -+ get_byte(); -+ -+ workspace_size = ((LZMA_BASE_SIZE + (LZMA_LIT_SIZE << (lc + lp))) * sizeof(CProb)) + 100; -+ printk( KERN_NOTICE "initramfs: LZMA lc=%d,lp=%d,pb=%d,origSize=%d\n", -+ lc,lp,pb,osize); -+ outputbuffer = vmalloc(osize); -+ if (outputbuffer == 0) { -+ printk(KERN_ERR "initramfs: Couldn't allocate lzma output buffer\n"); -+ return -1; -+ } -+ -+ workspace = vmalloc(workspace_size); -+ if (workspace == NULL) { -+ printk(KERN_ERR "initramfs: Couldn't allocate lzma workspace\n"); -+ return -1; -+ } -+ -+ res = LzmaDecode(workspace, workspace_size, lc, lp, pb, inbuf + inptr, insize - inptr, outputbuffer, osize, &outsizeProcessed); -+ if( res != 0 ) { -+ panic( KERN_ERR "initramfs: Lzma decode failure\n"); -+ return -1; -+ } -+ -+ flush_buffer(outputbuffer, outsizeProcessed); -+ inptr = insize; -+ -+ vfree(outputbuffer); -+ vfree(workspace); -+ state = Reset; -+ return 0; -+} -+ - static char * __init unpack_to_rootfs(char *buf, unsigned len, int check_only) - { - int written; -@@ -509,12 +573,28 @@ static char * __init unpack_to_rootfs(ch - inptr = 0; - outcnt = 0; /* bytes in output buffer */ - bytes_out = 0; -- crc = (ulg)0xffffffffL; /* shift register contents */ -- makecrc(); -- gunzip(); -- if (state != Reset) -+ if( inbuf[0] == 037 && ((inbuf[1] == 0213) || (inbuf[1] == 0236))) -+ { -+ printk( KERN_NOTICE "detected gzip initramfs\n"); -+ crc = (ulg)0xffffffffL; /* shift register contents */ -+ makecrc(); -+ gunzip(); -+ if (state != Reset) - error("junk in gzipped archive"); -- this_header = saved_offset + inptr; -+ } -+ else if(!memcmp(inbuf+1, "\x00\x00\x80\x00", 4)) /* FIXME: hardcoded dictionary size */ -+ { -+ printk( KERN_NOTICE "detected lzma initramfs\n"); -+ lzma_unzip(); -+ } -+ else -+ { -+ // skip forward ? -+ crc = (ulg)0xffffffffL; /* shift register contents */ -+ makecrc(); -+ gunzip(); -+ } -+ this_header = saved_offset + inptr; - buf += inptr; - len -= inptr; - } ---- a/scripts/gen_initramfs_list.sh -+++ b/scripts/gen_initramfs_list.sh -@@ -287,7 +287,7 @@ if [ ! -z ${output_file} ]; then - if [ "${is_cpio_compressed}" = "compressed" ]; then - cat ${cpio_tfile} > ${output_file} - else -- cat ${cpio_tfile} | gzip -f -9 - > ${output_file} -+ lzma e -lc1 -lp2 -pb2 ${cpio_tfile} ${output_file} - fi - [ -z ${cpio_file} ] && rm ${cpio_tfile} - fi diff --git a/target/linux/brcm47xx/patches-2.6.28/811-bcm47xx-fix-gpio-direction-retval.patch b/target/linux/brcm47xx/patches-2.6.28/811-bcm47xx-fix-gpio-direction-retval.patch deleted file mode 100644 index fc9613bd2..000000000 --- a/target/linux/brcm47xx/patches-2.6.28/811-bcm47xx-fix-gpio-direction-retval.patch +++ /dev/null @@ -1,47 +0,0 @@ -The GPIO API is supposed to return 0 or a negative error code, -but the SSB GPIO functions return the bitmask of the GPIO register. -Fix this by ignoring the bitmask and always returning 0. The SSB GPIO functions can't fail. - ---mb - - - ---- a/arch/mips/include/asm/mach-bcm47xx/gpio.h -+++ b/arch/mips/include/asm/mach-bcm47xx/gpio.h -@@ -31,24 +31,28 @@ static inline void gpio_set_value(unsign - - static inline int gpio_direction_input(unsigned gpio) - { -- return ssb_gpio_outen(&ssb_bcm47xx, 1 << gpio, 0); -+ ssb_gpio_outen(&ssb_bcm47xx, 1 << gpio, 0); -+ return 0; - } - - static inline int gpio_direction_output(unsigned gpio, int value) - { -- return ssb_gpio_outen(&ssb_bcm47xx, 1 << gpio, 1 << gpio); -+ ssb_gpio_outen(&ssb_bcm47xx, 1 << gpio, 1 << gpio); -+ return 0; - } - --static int gpio_intmask(unsigned gpio, int value) -+static inline int gpio_intmask(unsigned gpio, int value) - { -- return ssb_gpio_intmask(&ssb_bcm47xx, 1 << gpio, -- value ? 1 << gpio : 0); -+ ssb_gpio_intmask(&ssb_bcm47xx, 1 << gpio, -+ value ? 1 << gpio : 0); -+ return 0; - } - --static int gpio_polarity(unsigned gpio, int value) -+static inline int gpio_polarity(unsigned gpio, int value) - { -- return ssb_gpio_polarity(&ssb_bcm47xx, 1 << gpio, -- value ? 1 << gpio : 0); -+ ssb_gpio_polarity(&ssb_bcm47xx, 1 << gpio, -+ value ? 1 << gpio : 0); -+ return 0; - } - - diff --git a/target/linux/brcm47xx/patches-2.6.28/814-export_ssb_watchdog.patch b/target/linux/brcm47xx/patches-2.6.28/814-export_ssb_watchdog.patch deleted file mode 100644 index 40639947b..000000000 --- a/target/linux/brcm47xx/patches-2.6.28/814-export_ssb_watchdog.patch +++ /dev/null @@ -1,16 +0,0 @@ -this patch export ssb_watchdog_timer_set to allow to use it in a Linux -watchdog driver. - - -Signed-off-by: Matthieu CASTET -Acked-by : Michael Buesch ---- a/drivers/ssb/embedded.c -+++ b/drivers/ssb/embedded.c -@@ -29,6 +29,7 @@ int ssb_watchdog_timer_set(struct ssb_bu - } - return -ENODEV; - } -+EXPORT_SYMBOL(ssb_watchdog_timer_set); - - u32 ssb_gpio_in(struct ssb_bus *bus, u32 mask) - { diff --git a/target/linux/brcm47xx/patches-2.6.28/815-watchdog.patch b/target/linux/brcm47xx/patches-2.6.28/815-watchdog.patch deleted file mode 100644 index f524d8c14..000000000 --- a/target/linux/brcm47xx/patches-2.6.28/815-watchdog.patch +++ /dev/null @@ -1,326 +0,0 @@ -This add watchdog driver for broadcom 47xx device. -It uses the ssb subsytem to access embeded watchdog device. - -Because the watchdog timeout is very short (about 2s), a soft timer is used -to increase the watchdog period. - -Note : A patch for exporting the ssb_watchdog_timer_set will -be submitted on next linux-mips merge. Without this patch it can't -be build as a module. - -Signed-off-by: Aleksandar Radovanovic -Signed-off-by: Matthieu CASTET ---- a/drivers/watchdog/Kconfig -+++ b/drivers/watchdog/Kconfig -@@ -747,6 +747,12 @@ config TXX9_WDT - help - Hardware driver for the built-in watchdog timer on TXx9 MIPS SoCs. - -+config BCM47XX_WDT -+ tristate "Broadcom BCM47xx Watchdog Timer" -+ depends on BCM47XX -+ help -+ Hardware driver for the Broadcom BCM47xx Watchog Timer. -+ - # PARISC Architecture - - # POWERPC Architecture ---- a/drivers/watchdog/Makefile -+++ b/drivers/watchdog/Makefile -@@ -106,6 +106,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_BCM47XX_WDT) += bcm47xx_wdt.o - - # PARISC Architecture - ---- /dev/null -+++ b/drivers/watchdog/bcm47xx_wdt.c -@@ -0,0 +1,286 @@ -+/* -+ * Watchdog driver for Broadcom BCM47XX -+ * -+ * Copyright (C) 2008 Aleksandar Radovanovic -+ * Copyright (C) 2009 Matthieu CASTET -+ * -+ * 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. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#define DRV_NAME "bcm47xx_wdt" -+ -+#define WDT_DEFAULT_TIME 30 /* seconds */ -+#define WDT_MAX_TIME 256 /* seconds */ -+ -+static int wdt_time = WDT_DEFAULT_TIME; -+static int nowayout = WATCHDOG_NOWAYOUT; -+ -+module_param(wdt_time, int, 0); -+MODULE_PARM_DESC(wdt_time, "Watchdog time in seconds. (default=" -+ __MODULE_STRING(WDT_DEFAULT_TIME) ")"); -+ -+#ifdef CONFIG_WATCHDOG_NOWAYOUT -+module_param(nowayout, int, 0); -+MODULE_PARM_DESC(nowayout, -+ "Watchdog cannot be stopped once started (default=" -+ __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); -+#endif -+ -+static unsigned long bcm47xx_wdt_busy; -+static char expect_release; -+static struct timer_list wdt_timer; -+static atomic_t ticks; -+ -+static inline void bcm47xx_wdt_hw_start(void) -+{ -+ /* this is 2,5s on 100Mhz clock and 2s on 133 Mhz */ -+ ssb_watchdog_timer_set(&ssb_bcm47xx, 0xfffffff); -+} -+ -+static inline int bcm47xx_wdt_hw_stop(void) -+{ -+ return ssb_watchdog_timer_set(&ssb_bcm47xx, 0); -+} -+ -+static void bcm47xx_timer_tick(unsigned long unused) -+{ -+ if (!atomic_dec_and_test(&ticks)) { -+ bcm47xx_wdt_hw_start(); -+ mod_timer(&wdt_timer, jiffies + HZ); -+ } else { -+ printk(KERN_CRIT DRV_NAME "Watchdog will fire soon!!!\n"); -+ } -+} -+ -+static inline void bcm47xx_wdt_pet(void) -+{ -+ atomic_set(&ticks, wdt_time); -+} -+ -+static void bcm47xx_wdt_start(void) -+{ -+ bcm47xx_wdt_pet(); -+ bcm47xx_timer_tick(0); -+} -+ -+static void bcm47xx_wdt_pause(void) -+{ -+ del_timer_sync(&wdt_timer); -+ bcm47xx_wdt_hw_stop(); -+} -+ -+static void bcm47xx_wdt_stop(void) -+{ -+ bcm47xx_wdt_pause(); -+} -+ -+static int bcm47xx_wdt_settimeout(int new_time) -+{ -+ if ((new_time <= 0) || (new_time > WDT_MAX_TIME)) -+ return -EINVAL; -+ -+ wdt_time = new_time; -+ return 0; -+} -+ -+static int bcm47xx_wdt_open(struct inode *inode, struct file *file) -+{ -+ if (test_and_set_bit(0, &bcm47xx_wdt_busy)) -+ return -EBUSY; -+ -+ bcm47xx_wdt_start(); -+ return nonseekable_open(inode, file); -+} -+ -+static int bcm47xx_wdt_release(struct inode *inode, struct file *file) -+{ -+ if (expect_release == 42) { -+ bcm47xx_wdt_stop(); -+ } else { -+ printk(KERN_CRIT DRV_NAME -+ ": Unexpected close, not stopping watchdog!\n"); -+ bcm47xx_wdt_start(); -+ } -+ -+ clear_bit(0, &bcm47xx_wdt_busy); -+ expect_release = 0; -+ return 0; -+} -+ -+static ssize_t bcm47xx_wdt_write(struct file *file, const char __user *data, -+ size_t len, loff_t *ppos) -+{ -+ if (len) { -+ if (!nowayout) { -+ size_t i; -+ -+ expect_release = 0; -+ -+ for (i = 0; i != len; i++) { -+ char c; -+ if (get_user(c, data + i)) -+ return -EFAULT; -+ if (c == 'V') -+ expect_release = 42; -+ } -+ } -+ bcm47xx_wdt_pet(); -+ } -+ return len; -+} -+ -+static struct watchdog_info bcm47xx_wdt_info = { -+ .identity = DRV_NAME, -+ .options = WDIOF_SETTIMEOUT | -+ WDIOF_KEEPALIVEPING | -+ WDIOF_MAGICCLOSE, -+}; -+ -+static long bcm47xx_wdt_ioctl(struct file *file, -+ unsigned int cmd, unsigned long arg) -+{ -+ void __user *argp = (void __user *)arg; -+ int __user *p = argp; -+ int new_value, retval = -EINVAL;; -+ -+ switch (cmd) { -+ case WDIOC_GETSUPPORT: -+ return copy_to_user(argp, &bcm47xx_wdt_info, -+ sizeof(bcm47xx_wdt_info)) ? -EFAULT : 0; -+ -+ case WDIOC_GETSTATUS: -+ case WDIOC_GETBOOTSTATUS: -+ return put_user(0, p); -+ -+ case WDIOC_SETOPTIONS: -+ if (get_user(new_value, p)) -+ return -EFAULT; -+ -+ if (new_value & WDIOS_DISABLECARD) { -+ bcm47xx_wdt_stop(); -+ retval = 0; -+ } -+ -+ if (new_value & WDIOS_ENABLECARD) { -+ bcm47xx_wdt_start(); -+ retval = 0; -+ } -+ -+ return retval; -+ -+ case WDIOC_KEEPALIVE: -+ bcm47xx_wdt_pet(); -+ return 0; -+ -+ case WDIOC_SETTIMEOUT: -+ if (get_user(new_value, p)) -+ return -EFAULT; -+ -+ if (bcm47xx_wdt_settimeout(new_value)) -+ return -EINVAL; -+ -+ bcm47xx_wdt_pet(); -+ -+ case WDIOC_GETTIMEOUT: -+ return put_user(wdt_time, p); -+ -+ default: -+ return -ENOTTY; -+ } -+} -+ -+static int bcm47xx_wdt_notify_sys(struct notifier_block *this, -+ unsigned long code, void *unused) -+{ -+ if (code == SYS_DOWN || code == SYS_HALT) -+ bcm47xx_wdt_stop(); -+ return NOTIFY_DONE; -+} -+ -+static const struct file_operations bcm47xx_wdt_fops = { -+ .owner = THIS_MODULE, -+ .llseek = no_llseek, -+ .unlocked_ioctl = bcm47xx_wdt_ioctl, -+ .open = bcm47xx_wdt_open, -+ .release = bcm47xx_wdt_release, -+ .write = bcm47xx_wdt_write, -+}; -+ -+static struct miscdevice bcm47xx_wdt_miscdev = { -+ .minor = WATCHDOG_MINOR, -+ .name = "watchdog", -+ .fops = &bcm47xx_wdt_fops, -+}; -+ -+static struct notifier_block bcm47xx_wdt_notifier = { -+ .notifier_call = bcm47xx_wdt_notify_sys, -+}; -+ -+static int __init bcm47xx_wdt_init(void) -+{ -+ int ret; -+ -+ if (bcm47xx_wdt_hw_stop() < 0) -+ return -ENODEV; -+ -+ setup_timer(&wdt_timer, bcm47xx_timer_tick, 0L); -+ -+ if (bcm47xx_wdt_settimeout(wdt_time)) { -+ bcm47xx_wdt_settimeout(WDT_DEFAULT_TIME); -+ printk(KERN_INFO DRV_NAME -+ ": wdt_time value must be 1 <= wdt_time <= 256, using %d\n", -+ wdt_time); -+ } -+ -+ ret = register_reboot_notifier(&bcm47xx_wdt_notifier); -+ if (ret) -+ return ret; -+ -+ ret = misc_register(&bcm47xx_wdt_miscdev); -+ if (ret) { -+ unregister_reboot_notifier(&bcm47xx_wdt_notifier); -+ return ret; -+ } -+ -+ printk(KERN_INFO "BCM47xx Watchdog Timer enabled (%d seconds%s)\n", -+ wdt_time, nowayout ? ", nowayout" : ""); -+ return 0; -+} -+ -+static void __exit bcm47xx_wdt_exit(void) -+{ -+ if (!nowayout) -+ bcm47xx_wdt_stop(); -+ -+ misc_deregister(&bcm47xx_wdt_miscdev); -+ -+ unregister_reboot_notifier(&bcm47xx_wdt_notifier); -+} -+ -+module_init(bcm47xx_wdt_init); -+module_exit(bcm47xx_wdt_exit); -+ -+MODULE_AUTHOR("Aleksandar Radovanovic"); -+MODULE_DESCRIPTION("Watchdog driver for Broadcom BCM47xx"); -+MODULE_LICENSE("GPL"); -+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); diff --git a/target/linux/brcm47xx/patches-2.6.28/816-ssb_fix_irq_setup.patch b/target/linux/brcm47xx/patches-2.6.28/816-ssb_fix_irq_setup.patch deleted file mode 100644 index 05c36517d..000000000 --- a/target/linux/brcm47xx/patches-2.6.28/816-ssb_fix_irq_setup.patch +++ /dev/null @@ -1,183 +0,0 @@ -the current ssb irq setup (in ssb_mipscore_init) have some problem : -it configure some device on some irq without checking that the irq is not taken by an other device. - -For example in my case PCI host is on irq 0 and IPSEC on irq 3. -The current code : -- store in dev->irq that IPSEC irq is 3+2 -- do a set_irq 0->3 on PCI host - -But now IPSEC irq is not routed anymore to the mips code and dev->irq is wrong. This cause problem described in [1]. - -This patch try to solve the problem by making set_irq configure the device we want to take the irq on the shared irq0. -The previous example become : -- store in dev->irq that IPSEC irq is 3+2 -- do a set_irq 0->3 on PCI host : - - irq 3 is already taken by IPSEC. do a set_irq 3->0 on IPSEC - - -I also added some code to print the irq configuration before and after irq setup to allow easier debugging. And I add extra checking in ssb_mips_irq to report device without irq or device with not routed irq. - - -[1] http://www.danm.de/files/src/bcm5365p/REPORTED_DEVICES - -Signed-off-by: Matthieu CASTET ---- a/drivers/ssb/driver_mipscore.c -+++ b/drivers/ssb/driver_mipscore.c -@@ -49,29 +49,54 @@ static const u32 ipsflag_irq_shift[] = { - - static inline u32 ssb_irqflag(struct ssb_device *dev) - { -- return ssb_read32(dev, SSB_TPSFLAG) & SSB_TPSFLAG_BPFLAG; -+ u32 tpsflag = ssb_read32(dev, SSB_TPSFLAG); -+ if (tpsflag) -+ return ssb_read32(dev, SSB_TPSFLAG) & SSB_TPSFLAG_BPFLAG; -+ else -+ /* not irq supported */ -+ return 0x3f; -+} -+ -+static struct ssb_device *find_device(struct ssb_device *rdev, int irqflag) -+{ -+ struct ssb_bus *bus = rdev->bus; -+ int i; -+ for (i = 0; i < bus->nr_devices; i++) { -+ struct ssb_device *dev; -+ dev = &(bus->devices[i]); -+ if (ssb_irqflag(dev) == irqflag) -+ return dev; -+ } -+ return NULL; - } - - /* Get the MIPS IRQ assignment for a specified device. - * If unassigned, 0 is returned. -+ * If disabled, 5 is returned. -+ * If not supported, 6 is returned. - */ - unsigned int ssb_mips_irq(struct ssb_device *dev) - { - struct ssb_bus *bus = dev->bus; -+ struct ssb_device *mdev = bus->mipscore.dev; - u32 irqflag; - u32 ipsflag; - u32 tmp; - unsigned int irq; - - irqflag = ssb_irqflag(dev); -+ if (irqflag == 0x3f) -+ return 6; - ipsflag = ssb_read32(bus->mipscore.dev, SSB_IPSFLAG); - for (irq = 1; irq <= 4; irq++) { - tmp = ((ipsflag & ipsflag_irq_mask[irq]) >> ipsflag_irq_shift[irq]); - if (tmp == irqflag) - break; - } -- if (irq == 5) -- irq = 0; -+ if (irq == 5) { -+ if ((1 << irqflag) & ssb_read32(mdev, SSB_INTVEC)) -+ irq = 0; -+ } - - return irq; - } -@@ -97,25 +122,56 @@ static void set_irq(struct ssb_device *d - struct ssb_device *mdev = bus->mipscore.dev; - u32 irqflag = ssb_irqflag(dev); - -+ BUG_ON(oldirq == 6); -+ - dev->irq = irq + 2; - -- ssb_dprintk(KERN_INFO PFX -- "set_irq: core 0x%04x, irq %d => %d\n", -- dev->id.coreid, oldirq, irq); - /* clear the old irq */ - if (oldirq == 0) - ssb_write32(mdev, SSB_INTVEC, (~(1 << irqflag) & ssb_read32(mdev, SSB_INTVEC))); -- else -+ else if (oldirq != 5) - clear_irq(bus, oldirq); - - /* assign the new one */ - if (irq == 0) { - ssb_write32(mdev, SSB_INTVEC, ((1 << irqflag) | ssb_read32(mdev, SSB_INTVEC))); - } else { -+ u32 ipsflag = ssb_read32(mdev, SSB_IPSFLAG); -+ if ((ipsflag & ipsflag_irq_mask[irq]) != ipsflag_irq_mask[irq]) { -+ u32 oldipsflag = (ipsflag & ipsflag_irq_mask[irq]) >> ipsflag_irq_shift[irq]; -+ struct ssb_device *olddev = find_device(dev, oldipsflag); -+ if (olddev) -+ set_irq(olddev, 0); -+ } - irqflag <<= ipsflag_irq_shift[irq]; -- irqflag |= (ssb_read32(mdev, SSB_IPSFLAG) & ~ipsflag_irq_mask[irq]); -+ irqflag |= (ipsflag & ~ipsflag_irq_mask[irq]); - ssb_write32(mdev, SSB_IPSFLAG, irqflag); - } -+ ssb_dprintk(KERN_INFO PFX -+ "set_irq: core 0x%04x, irq %d => %d\n", -+ dev->id.coreid, oldirq+2, irq+2); -+} -+ -+static void print_irq(struct ssb_device *dev, unsigned int irq) -+{ -+ int i; -+ static const char *irq_name[] = {"2(S)", "3", "4", "5", "6", "D", "I"}; -+ ssb_dprintk(KERN_INFO PFX -+ "core 0x%04x, irq :", dev->id.coreid); -+ for (i = 0; i <= 6; i++) { -+ ssb_dprintk(" %s%s", irq_name[i], i==irq?"*":" "); -+ } -+ ssb_dprintk("\n"); -+} -+ -+static void dump_irq(struct ssb_bus *bus) -+{ -+ int i; -+ for (i = 0; i < bus->nr_devices; i++) { -+ struct ssb_device *dev; -+ dev = &(bus->devices[i]); -+ print_irq(dev, ssb_mips_irq(dev)); -+ } - } - - static void ssb_mips_serial_init(struct ssb_mipscore *mcore) -@@ -197,18 +253,26 @@ void ssb_mipscore_init(struct ssb_mipsco - else if (bus->chipco.dev) - ssb_chipco_timing_init(&bus->chipco, ns); - -+ dump_irq(bus); - /* Assign IRQs to all cores on the bus, start with irq line 2, because serial usually takes 1 */ - for (irq = 2, i = 0; i < bus->nr_devices; i++) { -+ int mips_irq; - dev = &(bus->devices[i]); -- dev->irq = ssb_mips_irq(dev) + 2; -+ mips_irq = ssb_mips_irq(dev); -+ if (mips_irq > 4) -+ dev->irq = 0; -+ else -+ dev->irq = mips_irq + 2; -+ if (dev->irq > 5) -+ continue; - switch (dev->id.coreid) { - case SSB_DEV_USB11_HOST: - /* shouldn't need a separate irq line for non-4710, most of them have a proper - * external usb controller on the pci */ - if ((bus->chip_id == 0x4710) && (irq <= 4)) { - set_irq(dev, irq++); -- break; - } -+ break; - /* fallthrough */ - case SSB_DEV_PCI: - case SSB_DEV_ETHERNET: -@@ -222,6 +286,8 @@ void ssb_mipscore_init(struct ssb_mipsco - } - } - } -+ ssb_dprintk(KERN_INFO PFX "after irq reconfiguration\n"); -+ dump_irq(bus); - - ssb_mips_serial_init(mcore); - ssb_mips_flash_detect(mcore); diff --git a/target/linux/brcm47xx/patches-2.6.28/100-board_support.patch b/target/linux/brcm47xx/patches-2.6.32/100-board_support.patch similarity index 97% rename from target/linux/brcm47xx/patches-2.6.28/100-board_support.patch rename to target/linux/brcm47xx/patches-2.6.32/100-board_support.patch index ac5d9124e..ce5160eb9 100644 --- a/target/linux/brcm47xx/patches-2.6.28/100-board_support.patch +++ b/target/linux/brcm47xx/patches-2.6.32/100-board_support.patch @@ -15,7 +15,7 @@ extern char *system_type; --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h -@@ -2069,6 +2069,7 @@ +@@ -2106,6 +2106,7 @@ #define PCI_DEVICE_ID_TIGON3_5906M 0x1713 #define PCI_DEVICE_ID_BCM4401 0x4401 #define PCI_DEVICE_ID_BCM4401B0 0x4402 diff --git a/target/linux/brcm47xx/patches-2.6.28/110-flash_map.patch b/target/linux/brcm47xx/patches-2.6.32/110-flash_map.patch similarity index 95% rename from target/linux/brcm47xx/patches-2.6.28/110-flash_map.patch rename to target/linux/brcm47xx/patches-2.6.32/110-flash_map.patch index 5d2fd1e5e..59e89e575 100644 --- a/target/linux/brcm47xx/patches-2.6.28/110-flash_map.patch +++ b/target/linux/brcm47xx/patches-2.6.32/110-flash_map.patch @@ -1,6 +1,6 @@ --- a/drivers/mtd/maps/Kconfig +++ b/drivers/mtd/maps/Kconfig -@@ -332,6 +332,12 @@ config MTD_CFI_FLAGADM +@@ -343,6 +343,12 @@ config MTD_CFI_FLAGADM Mapping for the Flaga digital module. If you don't have one, ignore this setting. diff --git a/target/linux/brcm47xx/patches-2.6.28/130-remove_scache.patch b/target/linux/brcm47xx/patches-2.6.32/130-remove_scache.patch similarity index 86% rename from target/linux/brcm47xx/patches-2.6.28/130-remove_scache.patch rename to target/linux/brcm47xx/patches-2.6.32/130-remove_scache.patch index e4ea20d6b..4ed30486d 100644 --- a/target/linux/brcm47xx/patches-2.6.28/130-remove_scache.patch +++ b/target/linux/brcm47xx/patches-2.6.32/130-remove_scache.patch @@ -1,6 +1,6 @@ --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig -@@ -198,7 +198,6 @@ config MIPS_MALTA +@@ -195,7 +195,6 @@ config MIPS_MALTA select I8259 select MIPS_BOARDS_GEN select MIPS_BONITO64 @@ -8,7 +8,7 @@ select PCI_GT64XXX_PCI0 select MIPS_MSC select SWAP_IO_SPACE -@@ -1395,13 +1394,6 @@ config IP22_CPU_SCACHE +@@ -1473,13 +1472,6 @@ config IP22_CPU_SCACHE bool select BOARD_SCACHE @@ -24,7 +24,7 @@ select BOARD_SCACHE --- a/arch/mips/kernel/cpu-probe.c +++ b/arch/mips/kernel/cpu-probe.c -@@ -755,6 +755,8 @@ static inline void cpu_probe_mips(struct +@@ -753,6 +753,8 @@ static inline void cpu_probe_mips(struct case PRID_IMP_25KF: c->cputype = CPU_25KF; __cpu_name[cpu] = "MIPS 25Kc"; @@ -35,7 +35,7 @@ c->cputype = CPU_34K; --- a/arch/mips/mm/Makefile +++ b/arch/mips/mm/Makefile -@@ -31,6 +31,5 @@ obj-$(CONFIG_CPU_VR41XX) += c-r4k.o cex- +@@ -32,6 +32,5 @@ obj-$(CONFIG_CPU_CAVIUM_OCTEON) += c-oct obj-$(CONFIG_IP22_CPU_SCACHE) += sc-ip22.o obj-$(CONFIG_R5000_CPU_SCACHE) += sc-r5k.o obj-$(CONFIG_RM7000_CPU_SCACHE) += sc-rm7k.o @@ -44,7 +44,7 @@ EXTRA_CFLAGS += -Werror --- a/arch/mips/mm/c-r4k.c +++ b/arch/mips/mm/c-r4k.c -@@ -1121,7 +1121,6 @@ static void __init loongson2_sc_init(voi +@@ -1135,7 +1135,6 @@ static void __init loongson2_sc_init(voi extern int r5k_sc_init(void); extern int rm7k_sc_init(void); @@ -52,7 +52,7 @@ static void __cpuinit setup_scache(void) { -@@ -1175,29 +1174,17 @@ static void __cpuinit setup_scache(void) +@@ -1189,29 +1188,17 @@ static void __cpuinit setup_scache(void) #endif default: diff --git a/target/linux/brcm47xx/patches-2.6.28/150-cpu_fixes.patch b/target/linux/brcm47xx/patches-2.6.32/150-cpu_fixes.patch similarity index 93% rename from target/linux/brcm47xx/patches-2.6.28/150-cpu_fixes.patch rename to target/linux/brcm47xx/patches-2.6.32/150-cpu_fixes.patch index 7abfbb2b6..f5209d4fe 100644 --- a/target/linux/brcm47xx/patches-2.6.28/150-cpu_fixes.patch +++ b/target/linux/brcm47xx/patches-2.6.32/150-cpu_fixes.patch @@ -140,7 +140,7 @@ __##pfx##flush_prologue \ \ for (ws = 0; ws < ws_end; ws += ws_inc) \ -@@ -393,35 +460,37 @@ static inline void blast_##pfx##cache##l +@@ -393,36 +460,38 @@ static inline void blast_##pfx##cache##l __##pfx##flush_epilogue \ } @@ -150,6 +150,7 @@ -__BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 32) -__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 32) -__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 32) +-__BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 64) -__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 64) -__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 64) -__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 128) @@ -166,6 +167,7 @@ +__BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 32, ) +__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 32, BCM4710_FILL_TLB(start);) +__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 32, ) ++__BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 64, ) +__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 64, BCM4710_FILL_TLB(start);) +__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 64, ) +__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 128, ) @@ -195,7 +197,7 @@ prot##cache_op(hitop, addr); \ if (addr == aend) \ break; \ -@@ -431,13 +500,13 @@ static inline void prot##blast_##pfx##ca +@@ -432,13 +501,13 @@ static inline void prot##blast_##pfx##ca __##pfx##flush_epilogue \ } @@ -218,7 +220,7 @@ #endif /* _ASM_R4KCACHE_H */ --- a/arch/mips/include/asm/stackframe.h +++ b/arch/mips/include/asm/stackframe.h -@@ -409,6 +409,10 @@ +@@ -426,6 +426,10 @@ .macro RESTORE_SP_AND_RET LONG_L sp, PT_R29(sp) .set mips3 @@ -244,7 +246,7 @@ #endif --- a/arch/mips/mm/c-r4k.c +++ b/arch/mips/mm/c-r4k.c -@@ -34,6 +34,9 @@ +@@ -35,6 +35,9 @@ #include /* for run_uncached() */ @@ -254,7 +256,7 @@ /* * Special Variant of smp_call_function for use by cache functions: * -@@ -104,6 +107,9 @@ static void __cpuinit r4k_blast_dcache_p +@@ -111,6 +114,9 @@ static void __cpuinit r4k_blast_dcache_p { unsigned long dc_lsize = cpu_dcache_line_size(); @@ -264,7 +266,7 @@ if (dc_lsize == 0) r4k_blast_dcache_page = (void *)cache_noop; else if (dc_lsize == 16) -@@ -118,6 +124,9 @@ static void __cpuinit r4k_blast_dcache_p +@@ -127,6 +133,9 @@ static void __cpuinit r4k_blast_dcache_p { unsigned long dc_lsize = cpu_dcache_line_size(); @@ -274,7 +276,7 @@ if (dc_lsize == 0) r4k_blast_dcache_page_indexed = (void *)cache_noop; else if (dc_lsize == 16) -@@ -132,6 +141,9 @@ static void __cpuinit r4k_blast_dcache_s +@@ -143,6 +152,9 @@ static void __cpuinit r4k_blast_dcache_s { unsigned long dc_lsize = cpu_dcache_line_size(); @@ -284,7 +286,7 @@ if (dc_lsize == 0) r4k_blast_dcache = (void *)cache_noop; else if (dc_lsize == 16) -@@ -647,6 +659,8 @@ static void local_r4k_flush_cache_sigtra +@@ -680,6 +692,8 @@ static void local_r4k_flush_cache_sigtra unsigned long addr = (unsigned long) arg; R4600_HIT_CACHEOP_WAR_IMPL; @@ -293,7 +295,7 @@ if (dc_lsize) protected_writeback_dcache_line(addr & ~(dc_lsize - 1)); if (!cpu_icache_snoops_remote_store && scache_size) -@@ -1271,6 +1285,17 @@ static void __cpuinit coherency_setup(vo +@@ -1298,6 +1312,17 @@ static void __cpuinit coherency_setup(vo * silly idea of putting something else there ... */ switch (current_cpu_type()) { @@ -311,7 +313,7 @@ case CPU_R4000PC: case CPU_R4000SC: case CPU_R4000MC: -@@ -1328,6 +1353,15 @@ void __cpuinit r4k_cache_init(void) +@@ -1354,6 +1379,15 @@ void __cpuinit r4k_cache_init(void) break; } @@ -327,7 +329,7 @@ probe_pcache(); setup_scache(); -@@ -1386,5 +1420,13 @@ void __cpuinit r4k_cache_init(void) +@@ -1412,5 +1446,13 @@ void __cpuinit r4k_cache_init(void) #if !defined(CONFIG_MIPS_CMP) local_r4k___flush_cache_all(NULL); #endif @@ -343,7 +345,7 @@ } --- a/arch/mips/mm/tlbex.c +++ b/arch/mips/mm/tlbex.c -@@ -678,6 +678,9 @@ static void __cpuinit build_r4000_tlb_re +@@ -784,6 +784,9 @@ static void __cpuinit build_r4000_tlb_re /* No need for uasm_i_nop */ } @@ -353,7 +355,7 @@ #ifdef CONFIG_64BIT build_get_pmde64(&p, &l, &r, K0, K1); /* get pmd in K1 */ #else -@@ -1085,6 +1088,9 @@ build_r4000_tlbchange_handler_head(u32 * +@@ -1238,6 +1241,9 @@ build_r4000_tlbchange_handler_head(u32 * struct uasm_reloc **r, unsigned int pte, unsigned int ptr) { diff --git a/target/linux/brcm47xx/patches-2.6.28/160-kmap_coherent.patch b/target/linux/brcm47xx/patches-2.6.32/160-kmap_coherent.patch similarity index 92% rename from target/linux/brcm47xx/patches-2.6.28/160-kmap_coherent.patch rename to target/linux/brcm47xx/patches-2.6.32/160-kmap_coherent.patch index 0219adfd5..ef1cacdba 100644 --- a/target/linux/brcm47xx/patches-2.6.28/160-kmap_coherent.patch +++ b/target/linux/brcm47xx/patches-2.6.32/160-kmap_coherent.patch @@ -1,6 +1,6 @@ --- a/arch/mips/include/asm/cpu-features.h +++ b/arch/mips/include/asm/cpu-features.h -@@ -101,6 +101,9 @@ +@@ -104,6 +104,9 @@ #ifndef cpu_has_pindexed_dcache #define cpu_has_pindexed_dcache (cpu_data[0].dcache.flags & MIPS_CACHE_PINDEX) #endif @@ -48,7 +48,7 @@ kunmap_atomic(vaddr, KM_USER0); --- a/arch/mips/mm/init.c +++ b/arch/mips/mm/init.c -@@ -212,7 +212,7 @@ void copy_user_highpage(struct page *to, +@@ -204,7 +204,7 @@ void copy_user_highpage(struct page *to, void *vfrom, *vto; vto = kmap_atomic(to, KM_USER1); @@ -57,7 +57,7 @@ page_mapped(from) && !Page_dcache_dirty(from)) { vfrom = kmap_coherent(from, vaddr); copy_page(vto, vfrom); -@@ -234,7 +234,7 @@ void copy_to_user_page(struct vm_area_st +@@ -226,7 +226,7 @@ void copy_to_user_page(struct vm_area_st struct page *page, unsigned long vaddr, void *dst, const void *src, unsigned long len) { @@ -66,7 +66,7 @@ page_mapped(page) && !Page_dcache_dirty(page)) { void *vto = kmap_coherent(page, vaddr) + (vaddr & ~PAGE_MASK); memcpy(vto, src, len); -@@ -252,7 +252,7 @@ void copy_from_user_page(struct vm_area_ +@@ -244,7 +244,7 @@ void copy_from_user_page(struct vm_area_ struct page *page, unsigned long vaddr, void *dst, const void *src, unsigned long len) { diff --git a/target/linux/brcm47xx/patches-2.6.28/170-128MB_ram_bugfix.patch b/target/linux/brcm47xx/patches-2.6.32/170-128MB_ram_bugfix.patch similarity index 100% rename from target/linux/brcm47xx/patches-2.6.28/170-128MB_ram_bugfix.patch rename to target/linux/brcm47xx/patches-2.6.32/170-128MB_ram_bugfix.patch diff --git a/target/linux/brcm47xx/patches-2.6.28/210-b44_phy_fix.patch b/target/linux/brcm47xx/patches-2.6.32/210-b44_phy_fix.patch similarity index 55% rename from target/linux/brcm47xx/patches-2.6.28/210-b44_phy_fix.patch rename to target/linux/brcm47xx/patches-2.6.32/210-b44_phy_fix.patch index e38332eb6..51b65afa6 100644 --- a/target/linux/brcm47xx/patches-2.6.28/210-b44_phy_fix.patch +++ b/target/linux/brcm47xx/patches-2.6.32/210-b44_phy_fix.patch @@ -9,16 +9,7 @@ } static void __b44_set_flow_ctrl(struct b44 *bp, u32 pause_flags) -@@ -384,7 +384,7 @@ static void b44_set_flow_ctrl(struct b44 - __b44_set_flow_ctrl(bp, pause_enab); - } - --#ifdef SSB_DRIVER_MIPS -+#ifdef CONFIG_SSB_DRIVER_MIPS - extern char *nvram_get(char *name); - static void b44_wap54g10_workaround(struct b44 *bp) - { -@@ -2213,6 +2213,10 @@ static int __devinit b44_init_one(struct +@@ -2220,6 +2220,10 @@ static int __devinit b44_init_one(struct */ b44_chip_reset(bp, B44_CHIP_RESET_FULL); @@ -26,6 +17,6 @@ + if (b44_phy_reset(bp) < 0) + bp->phy_addr = B44_PHY_ADDR_NO_PHY; + - printk(KERN_INFO "%s: Broadcom 44xx/47xx 10/100BaseT Ethernet %s\n", - dev->name, print_mac(mac, dev->dev_addr)); + printk(KERN_INFO "%s: Broadcom 44xx/47xx 10/100BaseT Ethernet %pM\n", + dev->name, dev->dev_addr); diff --git a/target/linux/brcm47xx/patches-2.6.28/220-bcm5354.patch b/target/linux/brcm47xx/patches-2.6.32/220-bcm5354.patch similarity index 95% rename from target/linux/brcm47xx/patches-2.6.28/220-bcm5354.patch rename to target/linux/brcm47xx/patches-2.6.32/220-bcm5354.patch index 837bd43e7..6aedfb2e5 100644 --- a/target/linux/brcm47xx/patches-2.6.28/220-bcm5354.patch +++ b/target/linux/brcm47xx/patches-2.6.32/220-bcm5354.patch @@ -31,7 +31,7 @@ } --- a/drivers/ssb/main.c +++ b/drivers/ssb/main.c -@@ -1013,6 +1013,8 @@ u32 ssb_clockspeed(struct ssb_bus *bus) +@@ -1010,6 +1010,8 @@ u32 ssb_clockspeed(struct ssb_bus *bus) if (bus->chip_id == 0x5365) { rate = 100000000; diff --git a/target/linux/brcm47xx/patches-2.6.28/250-ohci-ssb-usb2.patch b/target/linux/brcm47xx/patches-2.6.32/250-ohci-ssb-usb2.patch similarity index 100% rename from target/linux/brcm47xx/patches-2.6.28/250-ohci-ssb-usb2.patch rename to target/linux/brcm47xx/patches-2.6.32/250-ohci-ssb-usb2.patch diff --git a/target/linux/brcm47xx/patches-2.6.28/260-ohci-set-dma-mask.patch b/target/linux/brcm47xx/patches-2.6.32/260-ohci-set-dma-mask.patch similarity index 100% rename from target/linux/brcm47xx/patches-2.6.28/260-ohci-set-dma-mask.patch rename to target/linux/brcm47xx/patches-2.6.32/260-ohci-set-dma-mask.patch diff --git a/target/linux/brcm47xx/patches-2.6.28/270-ehci-ssb.patch b/target/linux/brcm47xx/patches-2.6.32/270-ehci-ssb.patch similarity index 97% rename from target/linux/brcm47xx/patches-2.6.28/270-ehci-ssb.patch rename to target/linux/brcm47xx/patches-2.6.32/270-ehci-ssb.patch index 2af7b4945..d1421332b 100644 --- a/target/linux/brcm47xx/patches-2.6.28/270-ehci-ssb.patch +++ b/target/linux/brcm47xx/patches-2.6.32/270-ehci-ssb.patch @@ -7,9 +7,9 @@ --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig -@@ -96,6 +96,19 @@ config USB_EHCI_HCD_PPC_OF - Enables support for the USB controller present on the PowerPC - OpenFirmware platform bus. +@@ -106,6 +106,19 @@ config USB_OXU210HP_HCD + To compile this driver as a module, choose M here: the + module will be called oxu210hp-hcd. +config USB_EHCI_HCD_SSB + bool "EHCI support for Broadcom SSB EHCI core" @@ -29,7 +29,7 @@ depends on USB --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c -@@ -1036,8 +1036,16 @@ MODULE_LICENSE ("GPL"); +@@ -1075,8 +1075,16 @@ MODULE_LICENSE ("GPL"); #define PLATFORM_DRIVER ixp4xx_ehci_driver #endif @@ -214,7 +214,7 @@ + u32 tmp, flags = 0; + + hcd = usb_create_hcd(&ssb_ehci_hc_driver, dev->dev, -+ dev->dev->bus_id); ++ dev_name(dev->dev)); + if (!hcd) + goto err_dev_disable; + diff --git a/target/linux/brcm47xx/patches-2.6.28/275-usb2-bcm5354-init.patch b/target/linux/brcm47xx/patches-2.6.32/275-usb2-bcm5354-init.patch similarity index 100% rename from target/linux/brcm47xx/patches-2.6.28/275-usb2-bcm5354-init.patch rename to target/linux/brcm47xx/patches-2.6.32/275-usb2-bcm5354-init.patch diff --git a/target/linux/brcm47xx/patches-2.6.32/280-activate_ssb_support_in_usb.patch b/target/linux/brcm47xx/patches-2.6.32/280-activate_ssb_support_in_usb.patch new file mode 100644 index 000000000..aeb9d334c --- /dev/null +++ b/target/linux/brcm47xx/patches-2.6.32/280-activate_ssb_support_in_usb.patch @@ -0,0 +1,16 @@ +This prevents the options from being delete with make kernel_oldconfig. +--- + drivers/ssb/Kconfig | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/drivers/ssb/Kconfig ++++ b/drivers/ssb/Kconfig +@@ -126,6 +126,8 @@ config SSB_DRIVER_MIPS + config SSB_EMBEDDED + bool + depends on SSB_DRIVER_MIPS ++ select USB_EHCI_HCD_SSB if USB_EHCI_HCD ++ select USB_OHCI_HCD_SSB if USB_OHCI_HCD + default y + + config SSB_DRIVER_EXTIF diff --git a/target/linux/brcm47xx/patches-2.6.28/300-fork_cacheflush.patch b/target/linux/brcm47xx/patches-2.6.32/300-fork_cacheflush.patch similarity index 100% rename from target/linux/brcm47xx/patches-2.6.28/300-fork_cacheflush.patch rename to target/linux/brcm47xx/patches-2.6.32/300-fork_cacheflush.patch diff --git a/target/linux/brcm47xx/patches-2.6.28/301-kmod-fuse-dcache-bug-r4k.patch b/target/linux/brcm47xx/patches-2.6.32/301-kmod-fuse-dcache-bug-r4k.patch similarity index 93% rename from target/linux/brcm47xx/patches-2.6.28/301-kmod-fuse-dcache-bug-r4k.patch rename to target/linux/brcm47xx/patches-2.6.32/301-kmod-fuse-dcache-bug-r4k.patch index efe3891cd..6e1b130e9 100644 --- a/target/linux/brcm47xx/patches-2.6.28/301-kmod-fuse-dcache-bug-r4k.patch +++ b/target/linux/brcm47xx/patches-2.6.32/301-kmod-fuse-dcache-bug-r4k.patch @@ -18,7 +18,7 @@ unsigned long addr, unsigned long pfn) { struct flush_cache_page_args args; -@@ -1430,3 +1430,10 @@ void __cpuinit r4k_cache_init(void) +@@ -1443,3 +1443,10 @@ void __cpuinit r4k_cache_init(void) coherency_setup(); #endif } diff --git a/target/linux/brcm47xx/patches-2.6.28/302-kmod-fuse-dcache-bug-fuse.patch b/target/linux/brcm47xx/patches-2.6.32/302-kmod-fuse-dcache-bug-fuse.patch similarity index 82% rename from target/linux/brcm47xx/patches-2.6.28/302-kmod-fuse-dcache-bug-fuse.patch rename to target/linux/brcm47xx/patches-2.6.32/302-kmod-fuse-dcache-bug-fuse.patch index a81e76719..79515d444 100644 --- a/target/linux/brcm47xx/patches-2.6.28/302-kmod-fuse-dcache-bug-fuse.patch +++ b/target/linux/brcm47xx/patches-2.6.32/302-kmod-fuse-dcache-bug-fuse.patch @@ -1,6 +1,6 @@ --- a/fs/fuse/dev.c +++ b/fs/fuse/dev.c -@@ -525,6 +525,11 @@ static void fuse_copy_finish(struct fuse +@@ -527,6 +527,11 @@ static void fuse_copy_finish(struct fuse } } @@ -12,7 +12,7 @@ /* * Get another pagefull of userspace buffer, and map it to kernel * address space, and lock request -@@ -533,6 +538,9 @@ static int fuse_copy_fill(struct fuse_co +@@ -535,6 +540,9 @@ static int fuse_copy_fill(struct fuse_co { unsigned long offset; int err; @@ -22,8 +22,8 @@ unlock_request(cs->fc, cs->req); fuse_copy_finish(cs); -@@ -544,14 +552,22 @@ static int fuse_copy_fill(struct fuse_co - cs->nr_segs --; +@@ -546,14 +554,22 @@ static int fuse_copy_fill(struct fuse_co + cs->nr_segs--; } down_read(¤t->mm->mmap_sem); +#ifndef DCACHE_BUG @@ -45,7 +45,7 @@ cs->buf = cs->mapaddr + offset; cs->len = min(PAGE_SIZE - offset, cs->seglen); cs->seglen -= cs->len; -@@ -565,6 +581,11 @@ static int fuse_copy_do(struct fuse_copy +@@ -567,6 +583,11 @@ static int fuse_copy_do(struct fuse_copy { unsigned ncpy = min(*size, cs->len); if (val) { @@ -69,8 +69,8 @@ #include --- a/fs/fuse/inode.c +++ b/fs/fuse/inode.c -@@ -1038,6 +1038,10 @@ static int __init fuse_init(void) - printk("fuse init (API version %i.%i)\n", +@@ -1055,6 +1055,10 @@ static int __init fuse_init(void) + printk(KERN_INFO "fuse init (API version %i.%i)\n", FUSE_KERNEL_VERSION, FUSE_KERNEL_MINOR_VERSION); +#ifdef DCACHE_BUG diff --git a/target/linux/brcm47xx/patches-2.6.28/310-no_highpage.patch b/target/linux/brcm47xx/patches-2.6.32/310-no_highpage.patch similarity index 93% rename from target/linux/brcm47xx/patches-2.6.28/310-no_highpage.patch rename to target/linux/brcm47xx/patches-2.6.32/310-no_highpage.patch index 23efb59a1..45ce36a11 100644 --- a/target/linux/brcm47xx/patches-2.6.28/310-no_highpage.patch +++ b/target/linux/brcm47xx/patches-2.6.32/310-no_highpage.patch @@ -1,6 +1,6 @@ --- a/arch/mips/include/asm/page.h +++ b/arch/mips/include/asm/page.h -@@ -32,6 +32,7 @@ +@@ -35,6 +35,7 @@ #ifndef __ASSEMBLY__ #include @@ -8,7 +8,7 @@ #include extern void build_clear_page(void); -@@ -67,13 +68,16 @@ static inline void clear_user_page(void +@@ -70,13 +71,16 @@ static inline void clear_user_page(void flush_data_cache_page((unsigned long)addr); } @@ -33,7 +33,7 @@ * These are used to make use of C type-checking.. --- a/arch/mips/mm/init.c +++ b/arch/mips/mm/init.c -@@ -206,30 +206,6 @@ void kunmap_coherent(void) +@@ -198,30 +198,6 @@ void kunmap_coherent(void) preempt_check_resched(); } diff --git a/target/linux/brcm47xx/patches-2.6.28/400-arch-bcm47xx.patch b/target/linux/brcm47xx/patches-2.6.32/400-arch-bcm47xx.patch similarity index 100% rename from target/linux/brcm47xx/patches-2.6.28/400-arch-bcm47xx.patch rename to target/linux/brcm47xx/patches-2.6.32/400-arch-bcm47xx.patch diff --git a/target/linux/brcm47xx/patches-2.6.28/601-mips-remove-pci-collision-check.patch b/target/linux/brcm47xx/patches-2.6.32/601-mips-remove-pci-collision-check.patch similarity index 89% rename from target/linux/brcm47xx/patches-2.6.28/601-mips-remove-pci-collision-check.patch rename to target/linux/brcm47xx/patches-2.6.32/601-mips-remove-pci-collision-check.patch index 8bc009085..7860ca0dd 100644 --- a/target/linux/brcm47xx/patches-2.6.28/601-mips-remove-pci-collision-check.patch +++ b/target/linux/brcm47xx/patches-2.6.32/601-mips-remove-pci-collision-check.patch @@ -1,6 +1,6 @@ --- a/arch/mips/pci/pci.c +++ b/arch/mips/pci/pci.c -@@ -207,12 +207,10 @@ static int pcibios_enable_resources(stru +@@ -185,12 +185,10 @@ static int pcibios_enable_resources(stru if ((idx == PCI_ROM_RESOURCE) && (!(r->flags & IORESOURCE_ROM_ENABLE))) continue; diff --git a/target/linux/brcm47xx/patches-2.6.28/700-ssb-gigabit-ethernet-driver.patch b/target/linux/brcm47xx/patches-2.6.32/700-ssb-gigabit-ethernet-driver.patch similarity index 73% rename from target/linux/brcm47xx/patches-2.6.28/700-ssb-gigabit-ethernet-driver.patch rename to target/linux/brcm47xx/patches-2.6.32/700-ssb-gigabit-ethernet-driver.patch index 27da5fc44..8cf9f8e38 100644 --- a/target/linux/brcm47xx/patches-2.6.28/700-ssb-gigabit-ethernet-driver.patch +++ b/target/linux/brcm47xx/patches-2.6.32/700-ssb-gigabit-ethernet-driver.patch @@ -1,14 +1,14 @@ --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c -@@ -40,6 +40,7 @@ - #include +@@ -41,6 +41,7 @@ #include #include + #include +#include #include #include -@@ -428,8 +429,9 @@ static void _tw32_flush(struct tg3 *tp, +@@ -446,8 +447,9 @@ static void _tw32_flush(struct tg3 *tp, static inline void tw32_mailbox_flush(struct tg3 *tp, u32 off, u32 val) { tp->write32_mbox(tp, off, val); @@ -20,7 +20,7 @@ tp->read32_mbox(tp, off); } -@@ -439,7 +441,7 @@ static void tg3_write32_tx_mbox(struct t +@@ -457,7 +459,7 @@ static void tg3_write32_tx_mbox(struct t writel(val, mbox); if (tp->tg3_flags & TG3_FLAG_TXD_MBOX_HWBUG) writel(val, mbox); @@ -29,7 +29,7 @@ readl(mbox); } -@@ -711,7 +713,7 @@ static void tg3_switch_clocks(struct tg3 +@@ -729,7 +731,7 @@ static void tg3_switch_clocks(struct tg3 #define PHY_BUSY_LOOPS 5000 @@ -38,16 +38,7 @@ { u32 frame_val; unsigned int loops; -@@ -725,7 +727,7 @@ static int tg3_readphy(struct tg3 *tp, i - - *val = 0x0; - -- frame_val = ((PHY_ADDR << MI_COM_PHY_ADDR_SHIFT) & -+ frame_val = ((phy_addr << MI_COM_PHY_ADDR_SHIFT) & - MI_COM_PHY_ADDR_MASK); - frame_val |= ((reg << MI_COM_REG_ADDR_SHIFT) & - MI_COM_REG_ADDR_MASK); -@@ -760,7 +762,12 @@ static int tg3_readphy(struct tg3 *tp, i +@@ -778,7 +780,12 @@ static int tg3_readphy(struct tg3 *tp, i return ret; } @@ -61,16 +52,7 @@ { u32 frame_val; unsigned int loops; -@@ -776,7 +783,7 @@ static int tg3_writephy(struct tg3 *tp, - udelay(80); - } - -- frame_val = ((PHY_ADDR << MI_COM_PHY_ADDR_SHIFT) & -+ frame_val = ((phy_addr << MI_COM_PHY_ADDR_SHIFT) & - MI_COM_PHY_ADDR_MASK); - frame_val |= ((reg << MI_COM_REG_ADDR_SHIFT) & - MI_COM_REG_ADDR_MASK); -@@ -809,6 +816,11 @@ static int tg3_writephy(struct tg3 *tp, +@@ -827,6 +834,11 @@ static int tg3_writephy(struct tg3 *tp, return ret; } @@ -82,7 +64,17 @@ static int tg3_bmcr_reset(struct tg3 *tp) { u32 phy_control; -@@ -2232,8 +2244,10 @@ static int tg3_set_power_state(struct tg +@@ -2263,6 +2275,9 @@ static int tg3_nvram_read(struct tg3 *tp + { + int ret; + ++ if (tp->tg3_flags3 & TG3_FLG3_IS_SSB_CORE) ++ return -ENODEV; ++ + if (!(tp->tg3_flags & TG3_FLAG_NVRAM)) + return tg3_nvram_read_using_eeprom(tp, offset, val); + +@@ -2594,8 +2609,10 @@ static int tg3_set_power_state(struct tg tg3_frob_aux_power(tp); /* Workaround for unstable PLL clock */ @@ -95,7 +87,7 @@ u32 val = tr32(0x7d00); val &= ~((1 << 16) | (1 << 4) | (1 << 2) | (1 << 1) | 1); -@@ -2725,6 +2739,14 @@ relink: +@@ -3087,6 +3104,14 @@ relink: tg3_phy_copper_begin(tp); @@ -110,7 +102,7 @@ tg3_readphy(tp, MII_BMSR, &tmp); if (!tg3_readphy(tp, MII_BMSR, &tmp) && (tmp & BMSR_LSTATUS)) -@@ -5659,6 +5681,11 @@ static int tg3_poll_fw(struct tg3 *tp) +@@ -6000,6 +6025,11 @@ static int tg3_poll_fw(struct tg3 *tp) int i; u32 val; @@ -122,7 +114,7 @@ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) { /* Wait up to 20ms for init done. */ for (i = 0; i < 200; i++) { -@@ -5902,6 +5929,14 @@ static int tg3_chip_reset(struct tg3 *tp +@@ -6257,6 +6287,14 @@ static int tg3_chip_reset(struct tg3 *tp tw32(0x5000, 0x400); } @@ -137,7 +129,7 @@ tw32(GRC_MODE, tp->grc_mode); if (tp->pci_chip_rev_id == CHIPREV_ID_5705_A0) { -@@ -6176,9 +6211,12 @@ static int tg3_halt_cpu(struct tg3 *tp, +@@ -6409,9 +6447,12 @@ static int tg3_halt_cpu(struct tg3 *tp, return -ENODEV; } @@ -153,8 +145,8 @@ return 0; } -@@ -6259,6 +6297,11 @@ static int tg3_load_5701_a0_firmware_fix - struct fw_info info; +@@ -6474,6 +6515,11 @@ static int tg3_load_5701_a0_firmware_fix + const __be32 *fw_data; int err, i; + if (tp->tg3_flags3 & TG3_FLG3_IS_SSB_CORE) { @@ -162,10 +154,10 @@ + return 0; + } + - info.text_base = TG3_FW_TEXT_ADDR; - info.text_len = TG3_FW_TEXT_LEN; - info.text_data = &tg3FwText[0]; -@@ -6817,6 +6860,11 @@ static int tg3_load_tso_firmware(struct + fw_data = (void *)tp->fw->data; + + /* Firmware blob starts with version numbers, followed by +@@ -6533,6 +6579,11 @@ static int tg3_load_tso_firmware(struct unsigned long cpu_base, cpu_scratch_base, cpu_scratch_size; int err, i; @@ -177,7 +169,7 @@ if (tp->tg3_flags2 & TG3_FLG2_HW_TSO) return 0; -@@ -7776,6 +7824,11 @@ static void tg3_timer(unsigned long __op +@@ -7444,6 +7495,11 @@ static void tg3_timer(unsigned long __op spin_lock(&tp->lock); @@ -189,19 +181,19 @@ if (!(tp->tg3_flags & TG3_FLAG_TAGGED_STATUS)) { /* All of this garbage is because when using non-tagged * IRQ status the mailbox/status_block protocol the chip -@@ -9469,6 +9522,11 @@ static int tg3_test_nvram(struct tg3 *tp - __le32 *buf; - int i, j, k, err = 0, size; +@@ -9217,6 +9273,11 @@ static int tg3_test_nvram(struct tg3 *tp + if (tp->tg3_flags3 & TG3_FLG3_NO_NVRAM) + return 0; + if (tp->tg3_flags3 & TG3_FLG3_IS_SSB_CORE) { + /* We don't have NVRAM. */ + return 0; + } + - if (tg3_nvram_read_swab(tp, 0, &magic) != 0) + if (tg3_nvram_read(tp, 0, &magic) != 0) return -EIO; -@@ -10262,7 +10320,7 @@ static int tg3_ioctl(struct net_device * +@@ -10010,7 +10071,7 @@ static int tg3_ioctl(struct net_device * return -EAGAIN; spin_lock_bh(&tp->lock); @@ -210,7 +202,7 @@ spin_unlock_bh(&tp->lock); data->val_out = mii_regval; -@@ -10281,7 +10339,7 @@ static int tg3_ioctl(struct net_device * +@@ -10029,7 +10090,7 @@ static int tg3_ioctl(struct net_device * return -EAGAIN; spin_lock_bh(&tp->lock); @@ -219,7 +211,7 @@ spin_unlock_bh(&tp->lock); return err; -@@ -10759,6 +10817,12 @@ static void __devinit tg3_get_5906_nvram +@@ -10619,6 +10680,12 @@ static void __devinit tg3_get_57780_nvra /* Chips other than 5700/5701 use the NVRAM for fetching info. */ static void __devinit tg3_nvram_init(struct tg3 *tp) { @@ -232,17 +224,7 @@ tw32_f(GRC_EEPROM_ADDR, (EEPROM_ADDR_FSM_RESET | (EEPROM_DEFAULT_CLOCK_PERIOD << -@@ -10900,6 +10964,9 @@ static int tg3_nvram_read(struct tg3 *tp - { - int ret; - -+ if (tp->tg3_flags3 & TG3_FLG3_IS_SSB_CORE) -+ return -ENODEV; -+ - if (!(tp->tg3_flags & TG3_FLAG_NVRAM)) - return tg3_nvram_read_using_eeprom(tp, offset, val); - -@@ -11147,6 +11214,9 @@ static int tg3_nvram_write_block(struct +@@ -10877,6 +10944,9 @@ static int tg3_nvram_write_block(struct { int ret; @@ -252,15 +234,7 @@ if (tp->tg3_flags & TG3_FLAG_EEPROM_WRITE_PROT) { tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl & ~GRC_LCLCTRL_GPIO_OUTPUT1); -@@ -12205,7 +12275,6 @@ static int __devinit tg3_get_invariants( - tp->write32 = tg3_write_flush_reg32; - } - -- - if ((tp->tg3_flags & TG3_FLAG_TXD_MBOX_HWBUG) || - (tp->tg3_flags & TG3_FLAG_MBOX_WRITE_REORDER)) { - tp->write32_tx_mbox = tg3_write32_tx_mbox; -@@ -12241,6 +12310,11 @@ static int __devinit tg3_get_invariants( +@@ -12136,6 +12205,11 @@ static int __devinit tg3_get_invariants( GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701))) tp->tg3_flags |= TG3_FLAG_SRAM_USE_CONFIG; @@ -272,7 +246,7 @@ /* Get eeprom hw config before calling tg3_set_power_state(). * In particular, the TG3_FLG2_IS_NIC flag must be * determined before calling tg3_set_power_state() so that -@@ -12640,6 +12714,10 @@ static int __devinit tg3_get_device_addr +@@ -12513,6 +12587,10 @@ static int __devinit tg3_get_device_addr } if (!is_valid_ether_addr(&dev->dev_addr[0])) { @@ -283,7 +257,7 @@ #ifdef CONFIG_SPARC if (!tg3_get_default_macaddr_sparc(tp)) return 0; -@@ -13131,6 +13209,7 @@ static char * __devinit tg3_phy_string(s +@@ -13004,6 +13082,7 @@ static char * __devinit tg3_phy_string(s case PHY_ID_BCM5704: return "5704"; case PHY_ID_BCM5705: return "5705"; case PHY_ID_BCM5750: return "5750"; @@ -291,7 +265,7 @@ case PHY_ID_BCM5752: return "5752"; case PHY_ID_BCM5714: return "5714"; case PHY_ID_BCM5780: return "5780"; -@@ -13317,6 +13396,13 @@ static int __devinit tg3_init_one(struct +@@ -13214,6 +13293,13 @@ static int __devinit tg3_init_one(struct tp->msg_enable = tg3_debug; else tp->msg_enable = TG3_DEF_MSG_ENABLE; @@ -307,17 +281,17 @@ * swapping. DMA data byte swapping is controlled in the GRC_MODE --- a/drivers/net/tg3.h +++ b/drivers/net/tg3.h -@@ -2516,6 +2516,9 @@ struct tg3 { - #define TG3_FLG3_RGMII_STD_IBND_DISABLE 0x00000100 - #define TG3_FLG3_RGMII_EXT_IBND_RX_EN 0x00000200 - #define TG3_FLG3_RGMII_EXT_IBND_TX_EN 0x00000400 +@@ -1853,6 +1853,9 @@ + #define NIC_SRAM_RGMII_STD_IBND_DISABLE 0x00000004 + #define NIC_SRAM_RGMII_EXT_IBND_RX_EN 0x00000008 + #define NIC_SRAM_RGMII_EXT_IBND_TX_EN 0x00000010 +#define TG3_FLG3_IS_SSB_CORE 0x00000800 +#define TG3_FLG3_FLUSH_POSTED_WRITES 0x00001000 +#define TG3_FLG3_ROBOSWITCH 0x00002000 - struct timer_list timer; - u16 timer_counter; -@@ -2574,6 +2577,7 @@ struct tg3 { + #define NIC_SRAM_RX_MINI_BUFFER_DESC 0x00001000 + +@@ -2701,6 +2704,7 @@ struct tg3 { #define PHY_ID_BCM5714 0x60008340 #define PHY_ID_BCM5780 0x60008350 #define PHY_ID_BCM5755 0xbc050cc0 @@ -325,7 +299,7 @@ #define PHY_ID_BCM5787 0xbc050ce0 #define PHY_ID_BCM5756 0xbc050ed0 #define PHY_ID_BCM5784 0xbc050fa0 -@@ -2613,7 +2617,7 @@ struct tg3 { +@@ -2745,7 +2749,7 @@ struct tg3 { (X) == PHY_ID_BCM5780 || (X) == PHY_ID_BCM5787 || \ (X) == PHY_ID_BCM5755 || (X) == PHY_ID_BCM5756 || \ (X) == PHY_ID_BCM5906 || (X) == PHY_ID_BCM5761 || \ diff --git a/target/linux/brcm47xx/patches-2.6.28/800-fix_cfe_detection.patch b/target/linux/brcm47xx/patches-2.6.32/800-fix_cfe_detection.patch similarity index 97% rename from target/linux/brcm47xx/patches-2.6.28/800-fix_cfe_detection.patch rename to target/linux/brcm47xx/patches-2.6.32/800-fix_cfe_detection.patch index c3a8a5738..6cba54053 100644 --- a/target/linux/brcm47xx/patches-2.6.28/800-fix_cfe_detection.patch +++ b/target/linux/brcm47xx/patches-2.6.32/800-fix_cfe_detection.patch @@ -90,7 +90,7 @@ { char buf[CL_SIZE]; -@@ -154,9 +130,12 @@ static __init void prom_init_mem(void) +@@ -146,9 +122,12 @@ static __init void prom_init_mem(void) void __init prom_init(void) { diff --git a/target/linux/brcm47xx/patches-2.6.28/812-disable_wgt634u_crap.patch b/target/linux/brcm47xx/patches-2.6.32/812-disable_wgt634u_crap.patch similarity index 100% rename from target/linux/brcm47xx/patches-2.6.28/812-disable_wgt634u_crap.patch rename to target/linux/brcm47xx/patches-2.6.32/812-disable_wgt634u_crap.patch diff --git a/target/linux/brcm47xx/patches-2.6.28/813-use_netdev_alloc_skb.patch b/target/linux/brcm47xx/patches-2.6.32/813-use_netdev_alloc_skb.patch similarity index 81% rename from target/linux/brcm47xx/patches-2.6.28/813-use_netdev_alloc_skb.patch rename to target/linux/brcm47xx/patches-2.6.32/813-use_netdev_alloc_skb.patch index 6641e40e2..c431e4096 100644 --- a/target/linux/brcm47xx/patches-2.6.28/813-use_netdev_alloc_skb.patch +++ b/target/linux/brcm47xx/patches-2.6.32/813-use_netdev_alloc_skb.patch @@ -1,6 +1,6 @@ --- a/drivers/net/b44.c +++ b/drivers/net/b44.c -@@ -814,7 +814,7 @@ static int b44_rx(struct b44 *bp, int bu +@@ -815,7 +815,7 @@ static int b44_rx(struct b44 *bp, int bu struct sk_buff *copy_skb; b44_recycle_rx(bp, cons, bp->rx_prod); diff --git a/target/linux/brcm47xx/patches-2.6.28/900-disable_early_printk.patch b/target/linux/brcm47xx/patches-2.6.32/900-disable_early_printk.patch similarity index 100% rename from target/linux/brcm47xx/patches-2.6.28/900-disable_early_printk.patch rename to target/linux/brcm47xx/patches-2.6.32/900-disable_early_printk.patch diff --git a/target/linux/brcm47xx/patches-2.6.28/920-cache-wround.patch b/target/linux/brcm47xx/patches-2.6.32/920-cache-wround.patch similarity index 90% rename from target/linux/brcm47xx/patches-2.6.28/920-cache-wround.patch rename to target/linux/brcm47xx/patches-2.6.32/920-cache-wround.patch index 9986f5ac1..e9b37e7b5 100644 --- a/target/linux/brcm47xx/patches-2.6.28/920-cache-wround.patch +++ b/target/linux/brcm47xx/patches-2.6.32/920-cache-wround.patch @@ -31,7 +31,7 @@ --- a/arch/mips/mm/tlbex.c +++ b/arch/mips/mm/tlbex.c -@@ -548,6 +548,9 @@ build_get_pgde32(u32 **p, unsigned int t +@@ -544,6 +544,9 @@ build_get_pgde32(u32 **p, unsigned int t #endif uasm_i_addu(p, ptr, tmp, ptr); #else @@ -41,7 +41,7 @@ UASM_i_LA_mostly(p, ptr, pgdc); #endif uasm_i_mfc0(p, tmp, C0_BADVADDR); /* get faulting address */ -@@ -678,12 +681,12 @@ static void __cpuinit build_r4000_tlb_re +@@ -674,12 +677,12 @@ static void __cpuinit build_r4000_tlb_re /* No need for uasm_i_nop */ } @@ -57,7 +57,7 @@ build_get_pgde32(&p, K0, K1); /* get pgd in K1 */ #endif -@@ -691,6 +694,9 @@ static void __cpuinit build_r4000_tlb_re +@@ -687,6 +690,9 @@ static void __cpuinit build_r4000_tlb_re build_update_entries(&p, K0, K1); build_tlb_write_entry(&p, &l, &r, tlb_random); uasm_l_leave(&l, p); @@ -67,7 +67,7 @@ uasm_i_eret(&p); /* return from trap */ #ifdef CONFIG_64BIT -@@ -1088,12 +1094,12 @@ build_r4000_tlbchange_handler_head(u32 * +@@ -1084,12 +1090,12 @@ build_r4000_tlbchange_handler_head(u32 * struct uasm_reloc **r, unsigned int pte, unsigned int ptr) { @@ -83,7 +83,7 @@ build_get_pgde32(p, pte, ptr); /* get pgd in ptr */ #endif -@@ -1121,6 +1127,9 @@ build_r4000_tlbchange_handler_tail(u32 * +@@ -1117,6 +1123,9 @@ build_r4000_tlbchange_handler_tail(u32 * build_update_entries(p, tmp, ptr); build_tlb_write_entry(p, l, r, tlb_indexed); uasm_l_leave(l, *p); diff --git a/target/linux/brcm63xx/Makefile b/target/linux/brcm63xx/Makefile index 4a3b43a4e..dec4806d4 100644 --- a/target/linux/brcm63xx/Makefile +++ b/target/linux/brcm63xx/Makefile @@ -10,7 +10,7 @@ ARCH:=mips BOARD:=brcm63xx BOARDNAME:=Broadcom BCM63xx FEATURES:=squashfs jffs2 usb atm pci pcmcia -LINUX_VERSION:=2.6.30.9 +LINUX_VERSION:=2.6.30.10 include $(INCLUDE_DIR)/target.mk diff --git a/target/linux/cobalt/Makefile b/target/linux/cobalt/Makefile index 103da193a..266e4dfdb 100644 --- a/target/linux/cobalt/Makefile +++ b/target/linux/cobalt/Makefile @@ -12,7 +12,7 @@ BOARDNAME:=Cobalt Microservers FEATURES:=tgz pci ext2 CFLAGS:=-O2 -pipe -mtune=r5000 -funit-at-a-time -LINUX_VERSION:=2.6.30.9 +LINUX_VERSION:=2.6.30.10 include $(INCLUDE_DIR)/target.mk diff --git a/target/linux/cobalt/patches/001-no_module_reloc.patch b/target/linux/cobalt/patches/001-no_module_reloc.patch index 833dea791..b6604ea07 100644 --- a/target/linux/cobalt/patches/001-no_module_reloc.patch +++ b/target/linux/cobalt/patches/001-no_module_reloc.patch @@ -1,7 +1,6 @@ -diff -urN linux-2.6.30.7/arch/mips/Makefile linux-2.6.30.7.new/arch/mips/Makefile ---- linux-2.6.30.7/arch/mips/Makefile 2009-09-27 13:17:16.000000000 +0200 -+++ linux-2.6.30.7.new/arch/mips/Makefile 2009-09-15 19:46:05.000000000 +0200 -@@ -83,7 +83,7 @@ +--- a/arch/mips/Makefile ++++ b/arch/mips/Makefile +@@ -83,7 +83,7 @@ all-$(CONFIG_BOOT_ELF64) := $(vmlinux-64 cflags-y += -G 0 -mno-abicalls -fno-pic -pipe cflags-y += -msoft-float LDFLAGS_vmlinux += -G 0 -static -n -nostdlib @@ -10,10 +9,9 @@ diff -urN linux-2.6.30.7/arch/mips/Makefile linux-2.6.30.7.new/arch/mips/Makefil cflags-y += -ffreestanding -diff -urN linux-2.6.30.7/arch/mips/include/asm/module.h linux-2.6.30.7.new/arch/mips/include/asm/module.h ---- linux-2.6.30.7/arch/mips/include/asm/module.h 2009-09-27 13:17:16.000000000 +0200 -+++ linux-2.6.30.7.new/arch/mips/include/asm/module.h 2009-09-15 19:46:05.000000000 +0200 -@@ -9,11 +9,6 @@ +--- a/arch/mips/include/asm/module.h ++++ b/arch/mips/include/asm/module.h +@@ -9,11 +9,6 @@ struct mod_arch_specific { struct list_head dbe_list; const struct exception_table_entry *dbe_start; const struct exception_table_entry *dbe_end; @@ -25,10 +23,9 @@ diff -urN linux-2.6.30.7/arch/mips/include/asm/module.h linux-2.6.30.7.new/arch/ }; typedef uint8_t Elf64_Byte; /* Type for a 8-bit quantity. */ -diff -urN linux-2.6.30.7/arch/mips/kernel/module.c linux-2.6.30.7.new/arch/mips/kernel/module.c ---- linux-2.6.30.7/arch/mips/kernel/module.c 2009-09-27 13:17:16.000000000 +0200 -+++ linux-2.6.30.7.new/arch/mips/kernel/module.c 2009-09-15 19:46:05.000000000 +0200 -@@ -43,116 +43,6 @@ +--- a/arch/mips/kernel/module.c ++++ b/arch/mips/kernel/module.c +@@ -43,116 +43,6 @@ static struct mips_hi16 *mips_hi16_list; static LIST_HEAD(dbe_list); static DEFINE_SPINLOCK(dbe_lock); @@ -145,7 +142,7 @@ diff -urN linux-2.6.30.7/arch/mips/kernel/module.c linux-2.6.30.7.new/arch/mips/ void *module_alloc(unsigned long size) { #ifdef MODULE_START -@@ -168,45 +58,16 @@ +@@ -168,45 +58,16 @@ void *module_alloc(unsigned long size) return __vmalloc_area(area, GFP_KERNEL, PAGE_KERNEL); #else @@ -193,7 +190,7 @@ diff -urN linux-2.6.30.7/arch/mips/kernel/module.c linux-2.6.30.7.new/arch/mips/ /* FIXME: If module_region == mod->init_region, trim exception table entries. */ } -@@ -214,24 +75,6 @@ +@@ -214,24 +75,6 @@ void module_free(struct module *mod, voi int module_frob_arch_sections(Elf_Ehdr *hdr, Elf_Shdr *sechdrs, char *secstrings, struct module *mod) { @@ -218,7 +215,7 @@ diff -urN linux-2.6.30.7/arch/mips/kernel/module.c linux-2.6.30.7.new/arch/mips/ return 0; } -@@ -254,41 +97,27 @@ +@@ -254,41 +97,27 @@ static int apply_r_mips_32_rela(struct m return 0; } @@ -274,7 +271,7 @@ diff -urN linux-2.6.30.7/arch/mips/kernel/module.c linux-2.6.30.7.new/arch/mips/ { if (v % 4) { printk(KERN_ERR "module %s: dangerous relocation\n", me->name); -@@ -296,31 +125,17 @@ +@@ -296,31 +125,17 @@ static int set_r_mips_26(struct module * } if ((v & 0xf0000000) != (((unsigned long)location + 4) & 0xf0000000)) { @@ -309,7 +306,7 @@ diff -urN linux-2.6.30.7/arch/mips/kernel/module.c linux-2.6.30.7.new/arch/mips/ static int apply_r_mips_hi16_rel(struct module *me, u32 *location, Elf_Addr v) { struct mips_hi16 *n; -@@ -585,23 +400,11 @@ +@@ -585,23 +400,11 @@ int module_finalize(const Elf_Ehdr *hdr, list_add(&me->arch.dbe_list, &dbe_list); spin_unlock_irq(&dbe_lock); } diff --git a/target/linux/coldfire/Makefile b/target/linux/coldfire/Makefile index 0d2963400..b9f96422a 100644 --- a/target/linux/coldfire/Makefile +++ b/target/linux/coldfire/Makefile @@ -12,7 +12,6 @@ BOARDNAME:=Freescale Coldfire v4e FEATURES:=squashfs broken LINUX_VERSION:=2.6.25.20 -LINUX_KARCH:=m68k include $(INCLUDE_DIR)/target.mk diff --git a/target/linux/ep93xx/Makefile b/target/linux/ep93xx/Makefile index 52cabaaaa..dae98ad7c 100644 --- a/target/linux/ep93xx/Makefile +++ b/target/linux/ep93xx/Makefile @@ -12,7 +12,7 @@ BOARDNAME:=Cirrus Logic EP93xx SoC FEATURES:=squashfs jffs2 ext2 tgz usb CFLAGS:=-Os -pipe -march=armv4t -funit-at-a-time -LINUX_VERSION:=2.6.30.9 +LINUX_VERSION:=2.6.30.10 include $(INCLUDE_DIR)/target.mk diff --git a/target/linux/etrax/Makefile b/target/linux/etrax/Makefile index 3dcfb2279..df0d69043 100644 --- a/target/linux/etrax/Makefile +++ b/target/linux/etrax/Makefile @@ -10,7 +10,7 @@ ARCH:=cris BOARD:=etrax BOARDNAME:=Foxboard (ETRAX 100LX) FEATURES:=squashfs jffs2 -LINUX_VERSION:=2.6.30.9 +LINUX_VERSION:=2.6.30.10 DEVICE_TYPE= include $(INCLUDE_DIR)/target.mk diff --git a/target/linux/gemini/Makefile b/target/linux/gemini/Makefile index 52a7c078b..d0e7bb9cc 100644 --- a/target/linux/gemini/Makefile +++ b/target/linux/gemini/Makefile @@ -12,7 +12,7 @@ BOARDNAME:=Cortina Systems CS351x FEATURES:=squashfs CFLAGS:=-Os -pipe -march=armv4 -mtune=arm9tdmi -funit-at-a-time -LINUX_VERSION:=2.6.30.9 +LINUX_VERSION:=2.6.30.10 include $(INCLUDE_DIR)/target.mk diff --git a/target/linux/generic-2.6/config-2.6.28 b/target/linux/generic-2.6/config-2.6.28 deleted file mode 100644 index 82b79bd8a..000000000 --- a/target/linux/generic-2.6/config-2.6.28 +++ /dev/null @@ -1,2327 +0,0 @@ -# CONFIG_6PACK is not set -# CONFIG_8139CP is not set -# CONFIG_9P_FS is not set -# CONFIG_ACCESSIBILITY is not set -# CONFIG_ACENIC is not set -# CONFIG_ACORN_PARTITION is not set -# CONFIG_ADAPTEC_STARFIRE is not set -# CONFIG_ADFS_FS is not set -# CONFIG_ADM6996_PHY is not set -# CONFIG_ADM8211 is not set -# CONFIG_AFFS_FS is not set -# CONFIG_AF_RXRPC is not set -# CONFIG_AFS_FS is not set -CONFIG_AIO=y -# CONFIG_AIRO_CS is not set -# CONFIG_AIRO is not set -# CONFIG_ALIM7101_WDT is not set -# CONFIG_AMD8111_ETH is not set -# CONFIG_AMIGA_PARTITION is not set -CONFIG_ANON_INODES=y -# CONFIG_APPLICOM is not set -# CONFIG_AR8216_PHY is not set -# CONFIG_ARCH_AAEC2000 is not set -# CONFIG_ARCH_AT91 is not set -# CONFIG_ARCH_CLPS711X is not set -# CONFIG_ARCH_CLPS7500 is not set -# CONFIG_ARCH_DAVINCI is not set -# CONFIG_ARCH_EBSA110 is not set -# CONFIG_ARCH_EP93XX is not set -CONFIG_ARCH_FLATMEM_ENABLE=y -# CONFIG_ARCH_FOOTBRIDGE is not set -# CONFIG_ARCH_GEMINI is not set -# CONFIG_ARCH_H720X is not set -# CONFIG_ARCH_IMX is not set -# CONFIG_ARCH_INTEGRATOR is not set -# CONFIG_ARCH_IOP13XX is not set -# CONFIG_ARCH_IOP32X is not set -# CONFIG_ARCH_IOP33X is not set -# CONFIG_ARCH_IXP2000 is not set -# CONFIG_ARCH_IXP23XX is not set -# CONFIG_ARCH_IXP4XX is not set -# CONFIG_ARCH_KIRKWOOD is not set -# CONFIG_ARCH_KS8695 is not set -# CONFIG_ARCH_L7200 is not set -# CONFIG_ARCH_LH7A40X is not set -# CONFIG_ARCH_LOKI is not set -# CONFIG_ARCH_MMP is not set -# CONFIG_ARCH_MSM is not set -# CONFIG_ARCH_MV78XX0 is not set -# CONFIG_ARCH_MXC is not set -# CONFIG_ARCH_NETX is not set -# CONFIG_ARCH_NS9XXX is not set -# CONFIG_ARCH_OMAP is not set -# CONFIG_ARCH_ORION5X is not set -# CONFIG_ARCH_PNX4008 is not set -# CONFIG_ARCH_PXA is not set -# CONFIG_ARCH_REALVIEW is not set -# CONFIG_ARCH_RPC is not set -# CONFIG_ARCH_S3C2410 is not set -# CONFIG_ARCH_S3C64XX is not set -# CONFIG_ARCH_SA1100 is not set -# CONFIG_ARCH_SHARK is not set -# CONFIG_ARCH_VERSATILE is not set -# CONFIG_ARCNET is not set -CONFIG_ARPD=y -CONFIG_ASK_IP_FIB_HASH=y -# CONFIG_AT24 is not set -# CONFIG_ATA_ACPI is not set -# CONFIG_ATA_GENERIC is not set -# CONFIG_ATA is not set -# CONFIG_ATALK is not set -# CONFIG_ATA_NONSTANDARD is not set -# CONFIG_ATA_OVER_ETH is not set -# CONFIG_ATARI_PARTITION is not set -CONFIG_ATA_SFF=y -# CONFIG_ATH5K is not set -# CONFIG_ATH9K is not set -# CONFIG_ATL1E is not set -# CONFIG_ATL1 is not set -# CONFIG_ATL2 is not set -# CONFIG_ATM_AMBASSADOR is not set -CONFIG_ATM_BR2684_IPFILTER=y -# CONFIG_ATM_BR2684 is not set -# CONFIG_ATM_CLIP is not set -CONFIG_ATM_CLIP_NO_ICMP=y -# CONFIG_ATM_DRIVERS is not set -# CONFIG_ATM_DUMMY is not set -# CONFIG_ATMEL is not set -# CONFIG_ATM_ENI is not set -# CONFIG_ATM_FIRESTREAM is not set -# CONFIG_ATM_FORE200E is not set -# CONFIG_ATM_FORE200E_MAYBE is not set -# CONFIG_ATM_HE is not set -# CONFIG_ATM_HORIZON is not set -# CONFIG_ATM_IA is not set -# CONFIG_ATM_IDT77252 is not set -# CONFIG_ATM is not set -# CONFIG_ATM_LANAI is not set -# CONFIG_ATM_LANE is not set -# CONFIG_ATM_MPOA is not set -# CONFIG_ATM_NICSTAR is not set -# CONFIG_ATM_TCP is not set -# CONFIG_ATM_ZATM is not set -# CONFIG_AUDIT is not set -# CONFIG_AUTOFS4_FS is not set -# CONFIG_AUTOFS_FS is not set -# CONFIG_AX25_DAMA_SLAVE is not set -# CONFIG_AX25 is not set -# CONFIG_AX88796 is not set -# CONFIG_B43 is not set -# CONFIG_B43LEGACY is not set -# CONFIG_B44 is not set -# CONFIG_BACKLIGHT_LCD_SUPPORT is not set -CONFIG_BASE_FULL=y -CONFIG_BASE_SMALL=0 -# CONFIG_BASLER_EXCITE is not set -# CONFIG_BAYCOM_EPP is not set -# CONFIG_BAYCOM_PAR is not set -# CONFIG_BAYCOM_SER_FDX is not set -# CONFIG_BAYCOM_SER_HDX is not set -CONFIG_BCM43XX_DEBUG=y -CONFIG_BCM43XX_DMA_AND_PIO_MODE=y -# CONFIG_BCM43XX_DMA_MODE is not set -CONFIG_BCM43XX_DMA=y -# CONFIG_BCM43XX is not set -# CONFIG_BCM43XX_PIO_MODE is not set -CONFIG_BCM43XX_PIO=y -# CONFIG_BEFS_FS is not set -# CONFIG_BFS_FS is not set -CONFIG_BINFMT_ELF=y -# CONFIG_BINFMT_MISC is not set -# CONFIG_BLINK is not set -# CONFIG_BLK_CPQ_CISS_DA is not set -# CONFIG_BLK_CPQ_DA is not set -# CONFIG_BLK_DEV_3W_XXXX_RAID is not set -# CONFIG_BLK_DEV_AEC62XX is not set -# CONFIG_BLK_DEV_ALI15X3 is not set -# CONFIG_BLK_DEV_AMD74XX is not set -# CONFIG_BLK_DEV_ATIIXP is not set -# CONFIG_BLK_DEV_BSG is not set -# CONFIG_BLK_DEV_CMD640 is not set -# CONFIG_BLK_DEV_CMD64X is not set -# CONFIG_BLK_DEV_COW_COMMON is not set -# CONFIG_BLK_DEV_CRYPTOLOOP is not set -# CONFIG_BLK_DEV_CS5520 is not set -# CONFIG_BLK_DEV_CS5530 is not set -# CONFIG_BLK_DEV_CS5535 is not set -# CONFIG_BLK_DEV_CY82C693 is not set -# CONFIG_BLK_DEV_DAC960 is not set -# CONFIG_BLK_DEV_DELKIN is not set -# CONFIG_BLK_DEV_FD is not set -# CONFIG_BLK_DEV_GENERIC is not set -# CONFIG_BLK_DEV_HD_IDE is not set -# CONFIG_BLK_DEV_HD is not set -# CONFIG_BLK_DEV_HD_ONLY is not set -# CONFIG_BLK_DEV_HPT34X is not set -# CONFIG_BLK_DEV_HPT366 is not set -# CONFIG_BLK_DEV_IDEACPI is not set -# CONFIG_BLK_DEV_IDECD is not set -# CONFIG_BLK_DEV_IDECS is not set -# CONFIG_BLK_DEV_IDEDMA_FORCED is not set -# CONFIG_BLK_DEV_IDEFLOPPY is not set -# CONFIG_BLK_DEV_IDEPCI is not set -# CONFIG_BLK_DEV_IDEPNP is not set -# CONFIG_BLK_DEV_IDE_SATA is not set -# CONFIG_BLK_DEV_IDESCSI is not set -# CONFIG_BLK_DEV_IDETAPE is not set -CONFIG_BLK_DEV_INITRD=y -# CONFIG_BLK_DEV_INTEGRITY is not set -# CONFIG_BLK_DEV_IO_TRACE is not set -# CONFIG_BLK_DEV_IT8213 is not set -# CONFIG_BLK_DEV_IT821X is not set -# CONFIG_BLK_DEV_JMICRON is not set -# CONFIG_BLK_DEV_LOOP is not set -# CONFIG_BLK_DEV_NBD is not set -# CONFIG_BLK_DEV_NS87415 is not set -# CONFIG_BLK_DEV_OFFBOARD is not set -# CONFIG_BLK_DEV_OPTI621 is not set -# CONFIG_BLK_DEV_PDC202XX_NEW is not set -# CONFIG_BLK_DEV_PDC202XX_OLD is not set -# CONFIG_BLK_DEV_PIIX is not set -# CONFIG_BLK_DEV_PLATFORM is not set -# CONFIG_BLK_DEV_RAM is not set -# CONFIG_BLK_DEV_RZ1000 is not set -# CONFIG_BLK_DEV_SC1200 is not set -# CONFIG_BLK_DEV_SD is not set -# CONFIG_BLK_DEV_SIIMAGE is not set -# CONFIG_BLK_DEV_SIS5513 is not set -# CONFIG_BLK_DEV_SL82C105 is not set -# CONFIG_BLK_DEV_SLC90E66 is not set -# CONFIG_BLK_DEV_SR is not set -# CONFIG_BLK_DEV_SVWKS is not set -# CONFIG_BLK_DEV_SX8 is not set -# CONFIG_BLK_DEV_TC86C001 is not set -# CONFIG_BLK_DEV_TRIFLEX is not set -# CONFIG_BLK_DEV_TRM290 is not set -# CONFIG_BLK_DEV_UB is not set -# CONFIG_BLK_DEV_UMEM is not set -# CONFIG_BLK_DEV_VIA82CXXX is not set -# CONFIG_BLK_DEV_XIP is not set -CONFIG_BLK_DEV=y -CONFIG_BLOCK=y -# CONFIG_BNX2 is not set -# CONFIG_BONDING is not set -# CONFIG_BPQETHER is not set -# CONFIG_BRIDGE_EBT_802_3 is not set -# CONFIG_BRIDGE_EBT_AMONG is not set -# CONFIG_BRIDGE_EBT_ARP is not set -# CONFIG_BRIDGE_EBT_ARPREPLY is not set -# CONFIG_BRIDGE_EBT_BROUTE is not set -# CONFIG_BRIDGE_EBT_DNAT is not set -# CONFIG_BRIDGE_EBT_IP6 is not set -# CONFIG_BRIDGE_EBT_IP is not set -# CONFIG_BRIDGE_EBT_LIMIT is not set -# CONFIG_BRIDGE_EBT_LOG is not set -# CONFIG_BRIDGE_EBT_MARK is not set -# CONFIG_BRIDGE_EBT_MARK_T is not set -# CONFIG_BRIDGE_EBT_NFLOG is not set -# CONFIG_BRIDGE_EBT_PKTTYPE is not set -# CONFIG_BRIDGE_EBT_REDIRECT is not set -# CONFIG_BRIDGE_EBT_SNAT is not set -# CONFIG_BRIDGE_EBT_STP is not set -# CONFIG_BRIDGE_EBT_T_FILTER is not set -# CONFIG_BRIDGE_EBT_T_NAT is not set -# CONFIG_BRIDGE_EBT_ULOG is not set -# CONFIG_BRIDGE_EBT_VLAN is not set -# CONFIG_BRIDGE_NETFILTER is not set -# CONFIG_BRIDGE_NF_EBTABLES is not set -CONFIG_BRIDGE=y -# CONFIG_BROADCOM_PHY is not set -CONFIG_BROKEN_ON_SMP=y -CONFIG_BSD_DISKLABEL=y -# CONFIG_BSD_PROCESS_ACCT_V3 is not set -CONFIG_BSD_PROCESS_ACCT=y -# CONFIG_BT_BNEP is not set -CONFIG_BT_BNEP_MC_FILTER=y -CONFIG_BT_BNEP_PROTO_FILTER=y -# CONFIG_BT_CMTP is not set -# CONFIG_BT_HCIBCM203X is not set -# CONFIG_BT_HCIBFUSB is not set -# CONFIG_BT_HCIBLUECARD is not set -# CONFIG_BT_HCIBPA10X is not set -# CONFIG_BT_HCIBT3C is not set -# CONFIG_BT_HCIBTSDIO is not set -# CONFIG_BT_HCIBTUART is not set -# CONFIG_BT_HCIBTUSB is not set -# CONFIG_BT_HCIDTL1 is not set -CONFIG_BT_HCIUART_BCSP=y -CONFIG_BT_HCIUART_H4=y -# CONFIG_BT_HCIUART is not set -# CONFIG_BT_HCIUART_LL is not set -# CONFIG_BT_HCIUSB is not set -CONFIG_BT_HCIUSB_SCO=y -# CONFIG_BT_HCIVHCI is not set -# CONFIG_BT_HIDP is not set -# CONFIG_BT is not set -# CONFIG_BT_L2CAP is not set -# CONFIG_BT_RFCOMM is not set -CONFIG_BT_RFCOMM_TTY=y -# CONFIG_BT_SCO is not set -CONFIG_BUG=y -# CONFIG_C2PORT is not set -# CONFIG_CAN is not set -# CONFIG_CAPI_AVM is not set -# CONFIG_CAPI_EICON is not set -# CONFIG_CAPI_TRACE is not set -CONFIG_CARDBUS=y -# CONFIG_CARDMAN_4000 is not set -# CONFIG_CARDMAN_4040 is not set -# CONFIG_CASSINI is not set -# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set -# CONFIG_CDROM_PKTCDVD is not set -# CONFIG_CFG80211 is not set -# CONFIG_CGROUPS is not set -# CONFIG_CHELSIO_T1 is not set -# CONFIG_CHELSIO_T3 is not set -# CONFIG_CHR_DEV_OSST is not set -# CONFIG_CHR_DEV_SCH is not set -# CONFIG_CHR_DEV_SG is not set -# CONFIG_CHR_DEV_ST is not set -# CONFIG_CICADA_PHY is not set -# CONFIG_CIFS_DEBUG2 is not set -# CONFIG_CIFS_EXPERIMENTAL is not set -# CONFIG_CIFS is not set -CONFIG_CIFS_POSIX=y -# CONFIG_CIFS_STATS2 is not set -CONFIG_CIFS_STATS=y -# CONFIG_CIFS_WEAK_PW_HASH is not set -# CONFIG_CIFS_XATTR is not set -CONFIG_CLS_U32_MARK=y -CONFIG_CLS_U32_PERF=y -CONFIG_CMDLINE="" -# CONFIG_CODA_FS is not set -# CONFIG_COMPAT_BRK is not set -# CONFIG_CONFIGFS_FS is not set -# CONFIG_CONNECTOR is not set -# CONFIG_CONTEXT_SWITCH_TRACER is not set -# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set -# CONFIG_CPU_DCACHE_DISABLE is not set -# CONFIG_CPU_FREQ is not set -# CONFIG_CPU_IDLE is not set -# CONFIG_CRAMFS is not set -# CONFIG_CRC16 is not set -CONFIG_CRC32=y -# CONFIG_CRC7 is not set -# CONFIG_CRC_CCITT is not set -# CONFIG_CRC_ITU_T is not set -# CONFIG_CRC_T10DIF is not set -CONFIG_CROSSCOMPILE=y -# CONFIG_CRYPTO_AEAD is not set -# CONFIG_CRYPTO_AES_586 is not set -# CONFIG_CRYPTO_AES is not set -# CONFIG_CRYPTO_ALGAPI is not set -# CONFIG_CRYPTO_ANSI_CPRNG is not set -# CONFIG_CRYPTO_ANUBIS is not set -# CONFIG_CRYPTO_ARC4 is not set -# CONFIG_CRYPTO_AUTHENC is not set -# CONFIG_CRYPTO_BLKCIPHER is not set -# CONFIG_CRYPTO_BLOWFISH is not set -# CONFIG_CRYPTO_CAMELLIA is not set -# CONFIG_CRYPTO_CAST5 is not set -# CONFIG_CRYPTO_CAST6 is not set -# CONFIG_CRYPTO_CBC is not set -# CONFIG_CRYPTO_CCM is not set -# CONFIG_CRYPTO_CRC32C_INTEL is not set -# CONFIG_CRYPTO_CRC32C is not set -# CONFIG_CRYPTO_CRYPTD is not set -# CONFIG_CRYPTO_CTR is not set -# CONFIG_CRYPTO_CTS is not set -# CONFIG_CRYPTO_DEFLATE is not set -# CONFIG_CRYPTO_DES is not set -# CONFIG_CRYPTO_DEV_HIFN_795X is not set -# CONFIG_CRYPTO_ECB is not set -# CONFIG_CRYPTO_FCRYPT is not set -# CONFIG_CRYPTO_FIPS is not set -# CONFIG_CRYPTO_GCM is not set -# CONFIG_CRYPTO_GF128MUL is not set -# CONFIG_CRYPTO_HASH is not set -# CONFIG_CRYPTO_HMAC is not set -# CONFIG_CRYPTO_HW is not set -# CONFIG_CRYPTO_KHAZAD is not set -# CONFIG_CRYPTO_LRW is not set -# CONFIG_CRYPTO_LZO is not set -# CONFIG_CRYPTO_MANAGER2 is not set -# CONFIG_CRYPTO_MANAGER is not set -# CONFIG_CRYPTO_MD4 is not set -# CONFIG_CRYPTO_MD5 is not set -# CONFIG_CRYPTO_MICHAEL_MIC is not set -# CONFIG_CRYPTO_NULL is not set -# CONFIG_CRYPTO_PCBC is not set -# CONFIG_CRYPTO_PRNG is not set -# CONFIG_CRYPTO_RMD128 is not set -# CONFIG_CRYPTO_RMD160 is not set -# CONFIG_CRYPTO_RMD256 is not set -# CONFIG_CRYPTO_RMD320 is not set -# CONFIG_CRYPTO_RNG is not set -# CONFIG_CRYPTO_SALSA20_586 is not set -# CONFIG_CRYPTO_SALSA20 is not set -# CONFIG_CRYPTO_SEED is not set -# CONFIG_CRYPTO_SEQIV is not set -# CONFIG_CRYPTO_SERPENT is not set -# CONFIG_CRYPTO_SHA1 is not set -# CONFIG_CRYPTO_SHA256 is not set -# CONFIG_CRYPTO_SHA512 is not set -# CONFIG_CRYPTO_TEA is not set -# CONFIG_CRYPTO_TEST is not set -# CONFIG_CRYPTO_TGR192 is not set -# CONFIG_CRYPTO_TWOFISH_586 is not set -# CONFIG_CRYPTO_TWOFISH_COMMON is not set -# CONFIG_CRYPTO_TWOFISH is not set -# CONFIG_CRYPTO_WP512 is not set -# CONFIG_CRYPTO_XCBC is not set -# CONFIG_CRYPTO_XTS is not set -CONFIG_CRYPTO=y -# CONFIG_DAB is not set -# CONFIG_DAVICOM_PHY is not set -# CONFIG_DEBUG_BUGVERBOSE is not set -CONFIG_DEBUG_FS=y -# CONFIG_DEBUG_KERNEL is not set -# CONFIG_DEBUG_MEMORY_INIT is not set -# CONFIG_DECNET is not set -# CONFIG_DEFAULT_AS is not set -# CONFIG_DEFAULT_BIC is not set -# CONFIG_DEFAULT_CFQ is not set -# CONFIG_DEFAULT_CUBIC is not set -CONFIG_DEFAULT_DEADLINE=y -# CONFIG_DEFAULT_HTCP is not set -CONFIG_DEFAULT_IOSCHED="deadline" -# CONFIG_DEFAULT_NOOP is not set -# CONFIG_DEFAULT_RENO is not set -CONFIG_DEFAULT_TCP_CONG="westwood" -# CONFIG_DEFAULT_VEGAS is not set -CONFIG_DEFAULT_WESTWOOD=y -CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" -# CONFIG_DEVKMEM is not set -# CONFIG_DGRS is not set -# CONFIG_DISCONTIGMEM_MANUAL is not set -# CONFIG_DISPLAY_SUPPORT is not set -# CONFIG_DL2K is not set -# CONFIG_DLM is not set -# CONFIG_DMADEVICES is not set -# CONFIG_DMA_ENGINE is not set -# CONFIG_DMASCC is not set -# CONFIG_DMATEST is not set -# CONFIG_DNOTIFY is not set -# CONFIG_DRM is not set -# CONFIG_DS1682 is not set -# CONFIG_DTLK is not set -# CONFIG_DUMMY is not set -# CONFIG_DVB_CORE is not set -# CONFIG_DVB is not set -# CONFIG_DYNAMIC_PRINTK_DEBUG is not set -# CONFIG_E1000E is not set -# CONFIG_E1000 is not set -# CONFIG_E100 is not set -# CONFIG_ECONET is not set -# CONFIG_EEPRO100 is not set -# CONFIG_EEPROM_93CX6 is not set -# CONFIG_EFI_PARTITION is not set -# CONFIG_EFS_FS is not set -# CONFIG_ELF_CORE is not set -CONFIG_EMBEDDED=y -# CONFIG_ENABLE_MUST_CHECK is not set -CONFIG_ENABLE_WARN_DEPRECATED=y -# CONFIG_ENC28J60 is not set -# CONFIG_ENCLOSURE_SERVICES is not set -# CONFIG_EPIC100 is not set -CONFIG_EPOLL=y -# CONFIG_EQUALIZER is not set -CONFIG_EVENTFD=y -CONFIG_EXPERIMENTAL=y -# CONFIG_EXPORTFS is not set -# CONFIG_EXT2_FS is not set -# CONFIG_EXT2_FS_XATTR is not set -# CONFIG_EXT2_FS_XIP is not set -# CONFIG_EXT3_FS is not set -# CONFIG_EXT3_FS_XATTR is not set -# CONFIG_EXT4DEV_FS is not set -# CONFIG_EXT4_FS is not set -CONFIG_EXTRA_FIRMWARE="" -CONFIG_EXTRA_TARGETS="" -# CONFIG_FAIR_GROUP_SCHED is not set -CONFIG_FAT_DEFAULT_CODEPAGE=437 -CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" -# CONFIG_FAT_FS is not set -# CONFIG_FB_GEODE is not set -# CONFIG_FB_IBM_GXT4500 is not set -# CONFIG_FB is not set -# CONFIG_FB_PXA is not set -# CONFIG_FDDI is not set -# CONFIG_FEALNX is not set -CONFIG_FIB_RULES=y -CONFIG_FILE_LOCKING=y -# CONFIG_FIREWIRE is not set -# CONFIG_FIRMWARE_IN_KERNEL is not set -# CONFIG_FIXED_PHY is not set -CONFIG_FLATMEM_MANUAL=y -CONFIG_FLATMEM=y -CONFIG_FLAT_NODE_MEM_MAP=y -# CONFIG_FORCEDETH is not set -CONFIG_FRAME_WARN=1024 -# CONFIG_FREEZER is not set -# CONFIG_FS_POSIX_ACL is not set -# CONFIG_FTL is not set -# CONFIG_FTRACE is not set -# CONFIG_FUSE_FS is not set -# CONFIG_FUSION_FC is not set -# CONFIG_FUSION is not set -# CONFIG_FUSION_SAS is not set -# CONFIG_FUSION_SPI is not set -CONFIG_FUTEX=y -CONFIG_FW_LOADER=y -CONFIG_GACT_PROB=y -# CONFIG_GAMEPORT is not set -CONFIG_GENERIC_CALIBRATE_DELAY=y -CONFIG_GENERIC_HARDIRQS=y -CONFIG_GENERIC_HWEIGHT=y -CONFIG_GENERIC_IRQ_PROBE=y -CONFIG_GENERIC_TIME=y -# CONFIG_GFS2_FS is not set -# CONFIG_GPIO_BT8XX is not set -# CONFIG_GPIO_DEVICE is not set -# CONFIG_GPIOLIB is not set -# CONFIG_GPIO_MAX7301 is not set -# CONFIG_GPIO_MAX732X is not set -# CONFIG_GPIO_MCP23S08 is not set -# CONFIG_GPIO_PCA953X is not set -# CONFIG_GPIO_PCF857X is not set -# CONFIG_GPIO_SYSFS is not set -# CONFIG_GPIO_XILINX is not set -# CONFIG_GROUP_SCHED is not set -# CONFIG_HAMACHI is not set -CONFIG_HAMRADIO=y -# CONFIG_HAPPYMEAL is not set -# CONFIG_HAVE_AOUT is not set -# CONFIG_HDLC_CISCO is not set -# CONFIG_HDLC_FR is not set -# CONFIG_HDLC is not set -# CONFIG_HDLC_PPP is not set -# CONFIG_HDLC_RAW_ETH is not set -# CONFIG_HDLC_RAW is not set -# CONFIG_HEADERS_CHECK is not set -# CONFIG_HERMES is not set -# CONFIG_HFS_FS is not set -# CONFIG_HFSPLUS_FS is not set -# CONFIG_HID_A4TECH is not set -# CONFIG_HID_APPLE is not set -# CONFIG_HID_BELKIN is not set -# CONFIG_HID_BRIGHT is not set -# CONFIG_HID_CHERRY is not set -# CONFIG_HID_CHICONY is not set -# CONFIG_HID_COMPAT is not set -# CONFIG_HID_CYPRESS is not set -# CONFIG_HID_DEBUG is not set -# CONFIG_HID_DELL is not set -# CONFIG_HID_EZKEY is not set -# CONFIG_HID_FF is not set -# CONFIG_HID_GYRATION is not set -# CONFIG_HID is not set -# CONFIG_HID_LOGITECH is not set -# CONFIG_HID_MICROSOFT is not set -# CONFIG_HID_MONTEREY is not set -# CONFIG_HID_PANTHERLORD is not set -# CONFIG_HID_PETALYNX is not set -# CONFIG_HID_PID is not set -# CONFIG_HIDRAW is not set -# CONFIG_HID_SAMSUNG is not set -# CONFIG_HID_SONY is not set -# CONFIG_HID_SUNPLUS is not set -# CONFIG_HID_SUPPORT is not set -CONFIG_HIGH_RES_TIMERS=y -# CONFIG_HIPPI is not set -# CONFIG_HOSTAP_CS is not set -# CONFIG_HOSTAP is not set -# CONFIG_HOSTAP_PCI is not set -# CONFIG_HOSTAP_PLX is not set -# CONFIG_HOTPLUG_CPU is not set -# CONFIG_HOTPLUG_PCI is not set -CONFIG_HOTPLUG=y -# CONFIG_HP100 is not set -# CONFIG_HPFS_FS is not set -# CONFIG_HP_ILO is not set -# CONFIG_HTC_EGPIO is not set -# CONFIG_HTC_PASIC3 is not set -# CONFIG_HUGETLB_PAGE is not set -# CONFIG_HWMON is not set -# CONFIG_HWMON_VID is not set -CONFIG_HZ=100 -# CONFIG_HZ_1000 is not set -CONFIG_HZ_100=y -# CONFIG_HZ_1024 is not set -# CONFIG_HZ_128 is not set -# CONFIG_HZ_250 is not set -# CONFIG_HZ_256 is not set -# CONFIG_HZ_300 is not set -# CONFIG_HZ_48 is not set -# CONFIG_I2C_ALGOBIT is not set -# CONFIG_I2C_ALGOPCA is not set -# CONFIG_I2C_ALGOPCF is not set -# CONFIG_I2C_ALI1535 is not set -# CONFIG_I2C_ALI1563 is not set -# CONFIG_I2C_ALI15X3 is not set -# CONFIG_I2C_AMD756 is not set -# CONFIG_I2C_AMD8111 is not set -# CONFIG_I2C_CHARDEV is not set -# CONFIG_I2C_DEBUG_ALGO is not set -# CONFIG_I2C_DEBUG_BUS is not set -# CONFIG_I2C_DEBUG_CHIP is not set -# CONFIG_I2C_DEBUG_CORE is not set -# CONFIG_I2C_ELEKTOR is not set -# CONFIG_I2C_GPIO is not set -# CONFIG_I2C_HELPER_AUTO is not set -# CONFIG_I2C_I801 is not set -# CONFIG_I2C_I810 is not set -# CONFIG_I2C_IBM_IIC is not set -# CONFIG_I2C_ISCH is not set -# CONFIG_I2C is not set -# CONFIG_I2C_MPC is not set -# CONFIG_I2C_NFORCE2 is not set -# CONFIG_I2C_OCORES is not set -# CONFIG_I2C_PARPORT_LIGHT is not set -# CONFIG_I2C_PCA_ISA is not set -# CONFIG_I2C_PCA_PLATFORM is not set -# CONFIG_I2C_PIIX4 is not set -# CONFIG_I2C_PROSAVAGE is not set -# CONFIG_I2C_SAVAGE4 is not set -# CONFIG_I2C_SIMTEC is not set -# CONFIG_I2C_SIS5595 is not set -# CONFIG_I2C_SIS630 is not set -# CONFIG_I2C_SIS96X is not set -# CONFIG_I2C_STUB is not set -# CONFIG_I2C_TAOS_EVM is not set -# CONFIG_I2C_TINY_USB is not set -# CONFIG_I2C_VIA is not set -# CONFIG_I2C_VIAPRO is not set -# CONFIG_I2C_VOODOO3 is not set -# CONFIG_I2O is not set -# CONFIG_I82092 is not set -# CONFIG_I82365 is not set -# CONFIG_IBM_NEW_EMAC_EMAC4 is not set -# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set -# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set -# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set -# CONFIG_IBM_NEW_EMAC_RGMII is not set -# CONFIG_IBM_NEW_EMAC_TAH is not set -# CONFIG_IBM_NEW_EMAC_ZMII is not set -# CONFIG_ICPLUS_PHY is not set -# CONFIG_ICS932S401 is not set -# CONFIG_IDEDISK_MULTI_MODE is not set -# CONFIG_IDEDMA_IVB is not set -# CONFIG_IDEDMA_ONLYDISK is not set -# CONFIG_IDE_GD is not set -CONFIG_IDE_MAX_HWIFS=4 -# CONFIG_IDEPCI_SHARE_IRQ is not set -CONFIG_IDE_PROC_FS=y -# CONFIG_IDE_TASK_IOCTL is not set -# CONFIG_IEEE1394_DV1394 is not set -# CONFIG_IEEE1394_ETH1394 is not set -# CONFIG_IEEE1394 is not set -# CONFIG_IEEE1394_OHCI1394 is not set -# CONFIG_IEEE1394_PCILYNX is not set -# CONFIG_IEEE1394_RAWIO is not set -# CONFIG_IEEE1394_VERBOSEDEBUG is not set -# CONFIG_IEEE1394_VIDEO1394 is not set -# CONFIG_IEEE80211_CRYPT_CCMP is not set -# CONFIG_IEEE80211_CRYPT_TKIP is not set -# CONFIG_IEEE80211_CRYPT_WEP is not set -# CONFIG_IEEE80211_DEBUG is not set -# CONFIG_IEEE80211 is not set -# CONFIG_IEEE80211_SOFTMAC_DEBUG is not set -# CONFIG_IEEE80211_SOFTMAC is not set -# CONFIG_IFB is not set -# CONFIG_IGB is not set -# CONFIG_IKCONFIG is not set -# CONFIG_IKCONFIG_PROC is not set -# CONFIG_IMAGE_CMDLINE_HACK is not set -# CONFIG_IMQ_BEHAVIOR_AA is not set -# CONFIG_IMQ_BEHAVIOR_AB is not set -# CONFIG_IMQ_BEHAVIOR_BA is not set -# CONFIG_IMQ_BEHAVIOR_BB is not set -# CONFIG_IMQ is not set -CONFIG_IMQ_NUM_DEVS=2 -# CONFIG_INET6_AH is not set -# CONFIG_INET6_ESP is not set -# CONFIG_INET6_IPCOMP is not set -# CONFIG_INET6_TUNNEL is not set -# CONFIG_INET6_XFRM_MODE_BEET is not set -# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set -# CONFIG_INET6_XFRM_MODE_TRANSPORT is not set -# CONFIG_INET6_XFRM_MODE_TUNNEL is not set -# CONFIG_INET6_XFRM_TUNNEL is not set -# CONFIG_INET_AH is not set -# CONFIG_INET_DIAG is not set -# CONFIG_INET_ESP is not set -# CONFIG_INET_IPCOMP is not set -# CONFIG_INET_LRO is not set -# CONFIG_INET_TCP_DIAG is not set -# CONFIG_INET_TUNNEL is not set -# CONFIG_INET_XFRM_MODE_BEET is not set -# CONFIG_INET_XFRM_MODE_TRANSPORT is not set -# CONFIG_INET_XFRM_MODE_TUNNEL is not set -# CONFIG_INET_XFRM_TUNNEL is not set -CONFIG_INET=y -# CONFIG_INFINIBAND is not set -# CONFIG_INFTL is not set -CONFIG_INIT_ENV_ARG_LIMIT=32 -# CONFIG_INOTIFY is not set -# CONFIG_INOTIFY_USER is not set -# CONFIG_INPUT_APANEL is not set -# CONFIG_INPUT_ATI_REMOTE2 is not set -# CONFIG_INPUT_ATI_REMOTE is not set -# CONFIG_INPUT_ATLAS_BTNS is not set -# CONFIG_INPUT_CM109 is not set -# CONFIG_INPUT_EVBUG is not set -# CONFIG_INPUT_EVDEV is not set -# CONFIG_INPUT_FF_MEMLESS is not set -# CONFIG_INPUT is not set -# CONFIG_INPUT_JOYDEV is not set -# CONFIG_INPUT_JOYSTICK is not set -# CONFIG_INPUT_KEYBOARD is not set -# CONFIG_INPUT_KEYSPAN_REMOTE is not set -CONFIG_INPUT_MISC=y -# CONFIG_INPUT_MOUSEDEV is not set -# CONFIG_INPUT_MOUSE is not set -# CONFIG_INPUT_PCSPKR is not set -# CONFIG_INPUT_POLLDEV is not set -# CONFIG_INPUT_POWERMATE is not set -# CONFIG_INPUT_TABLET is not set -# CONFIG_INPUT_TOUCHSCREEN is not set -# CONFIG_INPUT_TSDEV is not set -# CONFIG_INPUT_UINPUT is not set -# CONFIG_INPUT_WISTRON_BTNS is not set -# CONFIG_INSTRUMENTATION is not set -# CONFIG_IOSCHED_AS is not set -# CONFIG_IOSCHED_CFQ is not set -CONFIG_IOSCHED_DEADLINE=y -CONFIG_IOSCHED_NOOP=y -# CONFIG_IP1000 is not set -# CONFIG_IP175C_PHY is not set -# CONFIG_IP6_NF_FILTER is not set -# CONFIG_IP6_NF_IPTABLES is not set -# CONFIG_IP6_NF_MANGLE is not set -# CONFIG_IP6_NF_MATCH_AH is not set -# CONFIG_IP6_NF_MATCH_EUI64 is not set -# CONFIG_IP6_NF_MATCH_FRAG is not set -# CONFIG_IP6_NF_MATCH_HL is not set -# CONFIG_IP6_NF_MATCH_IPV6HEADER is not set -# CONFIG_IP6_NF_MATCH_LIMIT is not set -# CONFIG_IP6_NF_MATCH_MH is not set -# CONFIG_IP6_NF_MATCH_OPTS is not set -# CONFIG_IP6_NF_MATCH_OWNER is not set -# CONFIG_IP6_NF_MATCH_RT is not set -# CONFIG_IP6_NF_QUEUE is not set -# CONFIG_IP6_NF_RAW is not set -# CONFIG_IP6_NF_TARGET_HL is not set -# CONFIG_IP6_NF_TARGET_IMQ is not set -# CONFIG_IP6_NF_TARGET_LOG is not set -# CONFIG_IP6_NF_TARGET_REJECT is not set -# CONFIG_IP6_NF_TARGET_ROUTE is not set -CONFIG_IP_ADVANCED_ROUTER=y -# CONFIG_IPC_NS is not set -# CONFIG_IP_DCCP is not set -CONFIG_IP_FIB_HASH=y -# CONFIG_IP_FIB_TRIE is not set -# CONFIG_IPMI_HANDLER is not set -CONFIG_IP_MROUTE=y -CONFIG_IP_MULTICAST=y -CONFIG_IP_MULTIPLE_TABLES=y -# CONFIG_IP_NF_AMANDA is not set -# CONFIG_IP_NF_ARPFILTER is not set -# CONFIG_IP_NF_ARP_MANGLE is not set -# CONFIG_IP_NF_ARPTABLES is not set -# CONFIG_IP_NF_CONNTRACK_EVENTS is not set -CONFIG_IP_NF_CONNTRACK_MARK=y -CONFIG_IP_NF_CONNTRACK=y -CONFIG_IP_NF_CT_ACCT=y -# CONFIG_IP_NF_CT_PROTO_SCTP is not set -# CONFIG_IP_NF_FILTER is not set -# CONFIG_IP_NF_FTP is not set -# CONFIG_IP_NF_H323 is not set -# CONFIG_IP_NF_IPTABLES is not set -# CONFIG_IP_NF_IRC is not set -# CONFIG_IP_NF_MANGLE is not set -# CONFIG_IP_NF_MATCH_ADDRTYPE is not set -# CONFIG_IP_NF_MATCH_AH is not set -# CONFIG_IP_NF_MATCH_ECN is not set -# CONFIG_IP_NF_MATCH_HASHLIMIT is not set -# CONFIG_IP_NF_MATCH_IPP2P is not set -# CONFIG_IP_NF_MATCH_OWNER is not set -# CONFIG_IP_NF_MATCH_RECENT is not set -# CONFIG_IP_NF_MATCH_SET is not set -# CONFIG_IP_NF_MATCH_TIME is not set -# CONFIG_IP_NF_MATCH_TOS is not set -# CONFIG_IP_NF_MATCH_TTL is not set -# CONFIG_IP_NF_NAT_AMANDA is not set -# CONFIG_IP_NF_NAT_FTP is not set -# CONFIG_IP_NF_NAT_H323 is not set -# CONFIG_IP_NF_NAT_IRC is not set -CONFIG_IP_NF_NAT_NEEDED=y -# CONFIG_IP_NF_NAT_PPTP is not set -# CONFIG_IP_NF_NAT_SIP is not set -# CONFIG_IP_NF_NAT_SNMP_BASIC is not set -# CONFIG_IP_NF_NAT_TFTP is not set -CONFIG_IP_NF_NAT=y -# CONFIG_IP_NF_NETBIOS_NS is not set -# CONFIG_IP_NF_PPTP is not set -# CONFIG_IP_NF_QUEUE is not set -# CONFIG_IP_NF_RAW is not set -CONFIG_IP_NF_SET_HASHSIZE=1024 -# CONFIG_IP_NF_SET_IPHASH is not set -# CONFIG_IP_NF_SET_IPMAP is not set -# CONFIG_IP_NF_SET_IPPORTHASH is not set -# CONFIG_IP_NF_SET_IPTREE is not set -# CONFIG_IP_NF_SET_IPTREEMAP is not set -# CONFIG_IP_NF_SET is not set -# CONFIG_IP_NF_SET_MACIPMAP is not set -CONFIG_IP_NF_SET_MAX=256 -# CONFIG_IP_NF_SET_NETHASH is not set -# CONFIG_IP_NF_SET_PORTMAP is not set -# CONFIG_IP_NF_SIP is not set -# CONFIG_IP_NF_TARGET_CLUSTERIP is not set -# CONFIG_IP_NF_TARGET_ECN is not set -# CONFIG_IP_NF_TARGET_IMQ is not set -# CONFIG_IP_NF_TARGET_LOG is not set -# CONFIG_IP_NF_TARGET_MASQUERADE is not set -# CONFIG_IP_NF_TARGET_NETMAP is not set -# CONFIG_IP_NF_TARGET_REDIRECT is not set -# CONFIG_IP_NF_TARGET_REJECT is not set -# CONFIG_IP_NF_TARGET_ROUTE is not set -# CONFIG_IP_NF_TARGET_SAME is not set -# CONFIG_IP_NF_TARGET_SET is not set -# CONFIG_IP_NF_TARGET_TOS is not set -# CONFIG_IP_NF_TARGET_TTL is not set -# CONFIG_IP_NF_TARGET_ULOG is not set -# CONFIG_IP_NF_TFTP is not set -# CONFIG_IP_PIMSM_V1 is not set -# CONFIG_IP_PIMSM_V2 is not set -# CONFIG_IP_PNP is not set -CONFIG_IP_ROUTE_FWMARK=y -CONFIG_IP_ROUTE_MULTIPATH_CACHED=y -# CONFIG_IP_ROUTE_MULTIPATH_DRR is not set -# CONFIG_IP_ROUTE_MULTIPATH_RANDOM is not set -# CONFIG_IP_ROUTE_MULTIPATH_RR is not set -# CONFIG_IP_ROUTE_MULTIPATH_WRANDOM is not set -CONFIG_IP_ROUTE_MULTIPATH=y -CONFIG_IP_ROUTE_VERBOSE=y -# CONFIG_IP_SCTP is not set -CONFIG_IPSEC_NAT_TRAVERSAL=y -# CONFIG_IPV6 is not set -# CONFIG_IPV6_MIP6 is not set -# CONFIG_IPV6_MROUTE is not set -# CONFIG_IPV6_MULTIPLE_TABLES is not set -CONFIG_IPV6_NDISC_NODETYPE=y -# CONFIG_IPV6_OPTIMISTIC_DAD is not set -# CONFIG_IPV6_PRIVACY is not set -# CONFIG_IPV6_ROUTE_INFO is not set -# CONFIG_IPV6_ROUTER_PREF is not set -# CONFIG_IPV6_SIT is not set -# CONFIG_IPV6_TUNNEL is not set -# CONFIG_IP_VS is not set -# CONFIG_IPW2100_DEBUG is not set -# CONFIG_IPW2100 is not set -CONFIG_IPW2100_MONITOR=y -# CONFIG_IPW2200_DEBUG is not set -# CONFIG_IPW2200 is not set -CONFIG_IPW2200_MONITOR=y -# CONFIG_IPW2200_PROMISCUOUS is not set -# CONFIG_IPW2200_QOS is not set -# CONFIG_IPW2200_RADIOTAP is not set -# CONFIG_IPWIRELESS is not set -# CONFIG_IPX is not set -# CONFIG_IRDA is not set -# CONFIG_IRQSOFF_TRACER is not set -# CONFIG_ISCSI_TCP is not set -# CONFIG_ISDN_CAPI_CAPI20 is not set -CONFIG_ISDN_CAPI_CAPIFS_BOOL=y -# CONFIG_ISDN_CAPI_CAPIFS is not set -# CONFIG_ISDN_CAPI is not set -CONFIG_ISDN_CAPI_MIDDLEWARE=y -# CONFIG_ISDN_DRV_AVMB1_VERBOSE_REASON is not set -# CONFIG_ISDN_I4L is not set -CONFIG_ISDN=y -# CONFIG_ISO9660_FS is not set -# CONFIG_IWL3945 is not set -# CONFIG_IWLAGN is not set -# CONFIG_IWLCORE is not set -# CONFIG_IWLWIFI_LEDS is not set -# CONFIG_IXGB is not set -# CONFIG_JBD2_DEBUG is not set -# CONFIG_JBD_DEBUG is not set -# CONFIG_JBD is not set -# CONFIG_JFFS2_CMODE_FAVOURLZO is not set -# CONFIG_JFFS2_CMODE_NONE is not set -CONFIG_JFFS2_CMODE_PRIORITY=y -# CONFIG_JFFS2_CMODE_SIZE is not set -CONFIG_JFFS2_COMPRESSION_OPTIONS=y -CONFIG_JFFS2_FS_DEBUG=0 -# CONFIG_JFFS2_FS_WBUF_VERIFY is not set -CONFIG_JFFS2_FS_WRITEBUFFER=y -# CONFIG_JFFS2_FS_XATTR is not set -CONFIG_JFFS2_FS=y -# CONFIG_JFFS2_LZO is not set -CONFIG_JFFS2_RTIME=y -# CONFIG_JFFS2_RUBIN is not set -CONFIG_JFFS2_SUMMARY=y -CONFIG_JFFS2_ZLIB=y -# CONFIG_JFFS_FS is not set -# CONFIG_JFS_DEBUG is not set -# CONFIG_JFS_FS is not set -# CONFIG_JFS_POSIX_ACL is not set -# CONFIG_JFS_SECURITY is not set -# CONFIG_JFS_STATISTICS is not set -# CONFIG_JME is not set -CONFIG_JOLIET=y -# CONFIG_KALLSYMS_EXTRA_PASS is not set -# CONFIG_KALLSYMS is not set -# CONFIG_KARMA_PARTITION is not set -# CONFIG_KEXEC is not set -# CONFIG_KEYS is not set -CONFIG_KMOD=y -# CONFIG_KPROBES is not set -# CONFIG_LANMEDIA is not set -# CONFIG_LAPB is not set -# CONFIG_LASAT is not set -# CONFIG_LATENCYTOP is not set -# CONFIG_LBD is not set -# CONFIG_LDM_PARTITION is not set -# CONFIG_LEDS_ALIX is not set -CONFIG_LEDS_CLASS=y -# CONFIG_LEDS_PCA9532 is not set -# CONFIG_LEDS_PCA955X is not set -# CONFIG_LEDS_TRIGGER_BACKLIGHT is not set -CONFIG_LEDS_TRIGGER_DEFAULT_ON=y -CONFIG_LEDS_TRIGGER_HEARTBEAT=y -# CONFIG_LEDS_TRIGGER_IDE_DISK is not set -# CONFIG_LEDS_TRIGGER_MORSE is not set -CONFIG_LEDS_TRIGGER_NETDEV=y -CONFIG_LEDS_TRIGGERS=y -CONFIG_LEDS_TRIGGER_TIMER=y -# CONFIG_LEGACY_PTYS is not set -# CONFIG_LIBCRC32C is not set -# CONFIG_LIBERTAS is not set -# CONFIG_LIBERTAS_THINFIRM is not set -# CONFIG_LIBERTAS_USB is not set -# CONFIG_LLC2 is not set -CONFIG_LLC=y -CONFIG_LOCALVERSION="" -# CONFIG_LOCALVERSION_AUTO is not set -CONFIG_LOCKDEP_SUPPORT=y -# CONFIG_LOCKD is not set -CONFIG_LOCKD_V4=y -CONFIG_LOG_BUF_SHIFT=14 -# CONFIG_LOGIRUMBLEPAD2_FF is not set -# CONFIG_LOGITECH_FF is not set -# CONFIG_LSF is not set -# CONFIG_LXT_PHY is not set -# CONFIG_MAC80211 is not set -# CONFIG_MAC_EMUMOUSEBTN is not set -# CONFIG_MAC_PARTITION is not set -# CONFIG_MACVLAN is not set -# CONFIG_MAGIC_SYSRQ is not set -# CONFIG_MARKEINS is not set -# CONFIG_MARKERS is not set -# CONFIG_MARVELL_PHY is not set -# CONFIG_MDIO_BITBANG is not set -# CONFIG_MD is not set -# CONFIG_MEDIA_ATTACH is not set -# CONFIG_MEDIA_TUNER_CUSTOMIZE is not set -# CONFIG_MEGARAID_LEGACY is not set -# CONFIG_MEGARAID_NEWGEN is not set -# CONFIG_MEGARAID_SAS is not set -# CONFIG_MEMSTICK is not set -# CONFIG_MFD_ASIC3 is not set -# CONFIG_MFD_CORE is not set -# CONFIG_MFD_PCF50606 is not set -# CONFIG_MFD_SM501 is not set -# CONFIG_MFD_T7L66XB is not set -# CONFIG_MFD_TC6387XB is not set -# CONFIG_MFD_TC6393XB is not set -# CONFIG_MFD_TMIO is not set -# CONFIG_MFD_WM8350_I2C is not set -# CONFIG_MFD_WM8400 is not set -# CONFIG_MIGRATION is not set -CONFIG_MII=y -CONFIG_MINI_FO=y -# CONFIG_MINIX_FS is not set -# CONFIG_MINIX_SUBPARTITION is not set -# CONFIG_MIPS_FPU_EMU is not set -CONFIG_MISC_DEVICES=y -# CONFIG_MISDN_HFCPCI is not set -# CONFIG_MISDN is not set -# CONFIG_MKISS is not set -# CONFIG_MMC_ARMMMCI is not set -CONFIG_MMC_BLOCK_BOUNCE=y -# CONFIG_MMC_BLOCK is not set -# CONFIG_MMC is not set -# CONFIG_MMC_SDRICOH_CS is not set -# CONFIG_MMC_TEST is not set -CONFIG_MMU=y -# CONFIG_MODULE_FORCE_LOAD is not set -# CONFIG_MODULE_FORCE_UNLOAD is not set -# CONFIG_MODULE_SRCVERSION_ALL is not set -CONFIG_MODULES=y -CONFIG_MODULE_UNLOAD=y -# CONFIG_MODVERSIONS is not set -# CONFIG_MOUSE_APPLETOUCH is not set -# CONFIG_MOUSE_INPORT is not set -# CONFIG_MOUSE_LOGIBM is not set -# CONFIG_MOUSE_PC110PAD is not set -# CONFIG_MSDOS_FS is not set -CONFIG_MSDOS_PARTITION=y -# CONFIG_MTD_ABSENT is not set -# CONFIG_MTD_AFS_PARTS is not set -# CONFIG_MTD_ALAUDA is not set -# CONFIG_MTD_AR7_PARTS is not set -# CONFIG_MTD_ARM_INTEGRATOR is not set -CONFIG_MTD_BLKDEVS=y -# CONFIG_MTD_BLOCK2MTD is not set -CONFIG_MTD_BLOCK=y -# CONFIG_MTD_CFI_ADV_OPTIONS is not set -CONFIG_MTD_CFI_AMDSTD=y -# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set -CONFIG_MTD_CFI_I1=y -CONFIG_MTD_CFI_I2=y -# CONFIG_MTD_CFI_I4 is not set -# CONFIG_MTD_CFI_I8 is not set -CONFIG_MTD_CFI_INTELEXT=y -# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set -CONFIG_MTD_CFI_NOSWAP=y -# CONFIG_MTD_CFI_STAA is not set -CONFIG_MTD_CFI_UTIL=y -CONFIG_MTD_CFI=y -CONFIG_MTD_CHAR=y -# CONFIG_MTD_CMDLINE_PARTS is not set -CONFIG_MTD_COMPLEX_MAPPINGS=y -# CONFIG_MTD_CONCAT is not set -# CONFIG_MTD_DATAFLASH is not set -# CONFIG_MTD_DEBUG is not set -# CONFIG_MTD_DOC2000 is not set -# CONFIG_MTD_DOC2001 is not set -# CONFIG_MTD_DOC2001PLUS is not set -CONFIG_MTD_GEN_PROBE=y -# CONFIG_MTD_INTEL_VR_NOR is not set -# CONFIG_MTD_JEDECPROBE is not set -# CONFIG_MTD_LPDDR is not set -# CONFIG_MTD_M25P80 is not set -# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set -CONFIG_MTD_MAP_BANK_WIDTH_1=y -CONFIG_MTD_MAP_BANK_WIDTH_2=y -# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set -CONFIG_MTD_MAP_BANK_WIDTH_4=y -# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set -# CONFIG_MTD_MTDRAM is not set -# CONFIG_MTD_MYLOADER_PARTS is not set -# CONFIG_MTD_NAND_CAFE is not set -# CONFIG_MTD_NAND_DISKONCHIP is not set -# CONFIG_MTD_NAND_ECC_SMC is not set -CONFIG_MTD_NAND_IDS=y -# CONFIG_MTD_NAND is not set -# CONFIG_MTD_NAND_MUSEUM_IDS is not set -# CONFIG_MTD_NAND_NANDSIM is not set -# CONFIG_MTD_NAND_PLATFORM is not set -# CONFIG_MTD_NAND_VERIFY_WRITE is not set -# CONFIG_MTD_ONENAND is not set -# CONFIG_MTD_OOPS is not set -# CONFIG_MTD_OTP is not set -CONFIG_MTD_PARTITIONS=y -# CONFIG_MTD_PCI is not set -# CONFIG_MTD_PHRAM is not set -# CONFIG_MTD_PHYSMAP is not set -# CONFIG_MTD_PLATRAM is not set -# CONFIG_MTD_PMC551 is not set -# CONFIG_MTD_RAM is not set -CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1 -# CONFIG_MTD_REDBOOT_PARTS is not set -CONFIG_MTD_REDBOOT_PARTS_READONLY=y -# CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED is not set -# CONFIG_MTD_ROM is not set -CONFIG_MTD_ROOTFS_ROOT_DEV=y -CONFIG_MTD_ROOTFS_SPLIT=y -# CONFIG_MTD_SLRAM is not set -# CONFIG_MTD_UBI is not set -CONFIG_MTD=y -# CONFIG_MVSWITCH_PHY is not set -# CONFIG_MWAVE is not set -# CONFIG_MYRI10GE is not set -# CONFIG_NAMESPACES is not set -# CONFIG_NATSEMI is not set -# CONFIG_NCP_FS is not set -# CONFIG_NE2K_PCI is not set -# CONFIG_NET_9P is not set -# CONFIG_NET_ACT_GACT is not set -# CONFIG_NET_ACT_IPT is not set -# CONFIG_NET_ACT_MIRRED is not set -# CONFIG_NET_ACT_NAT is not set -# CONFIG_NET_ACT_PEDIT is not set -# CONFIG_NET_ACT_POLICE is not set -# CONFIG_NET_ACT_SIMP is not set -CONFIG_NET_ACT_SKBEDIT=y -CONFIG_NET_CLS_ACT=y -CONFIG_NET_CLS_BASIC=y -# CONFIG_NET_CLS_FLOW is not set -# CONFIG_NET_CLS_FW is not set -CONFIG_NET_CLS_IND=y -# CONFIG_NET_CLS_ROUTE4 is not set -# CONFIG_NET_CLS_RSVP6 is not set -# CONFIG_NET_CLS_RSVP is not set -# CONFIG_NET_CLS_TCINDEX is not set -# CONFIG_NET_CLS_U32 is not set -CONFIG_NET_CLS=y -# CONFIG_NETCONSOLE is not set -# CONFIG_NETDEBUG is not set -# CONFIG_NETDEV_10000 is not set -CONFIG_NETDEV_1000=y -CONFIG_NETDEVICES_MULTIQUEUE=y -CONFIG_NETDEVICES=y -# CONFIG_NET_DSA is not set -# CONFIG_NET_EMATCH_CMP is not set -# CONFIG_NET_EMATCH is not set -# CONFIG_NET_EMATCH_META is not set -# CONFIG_NET_EMATCH_NBYTE is not set -CONFIG_NET_EMATCH_STACK=32 -# CONFIG_NET_EMATCH_TEXT is not set -# CONFIG_NET_EMATCH_U32 is not set -CONFIG_NET_ESTIMATOR=y -CONFIG_NET_ETHERNET=y -# CONFIG_NET_FC is not set -CONFIG_NETFILTER_ADVANCED=y -# CONFIG_NETFILTER_DEBUG is not set -# CONFIG_NETFILTER_NETLINK is not set -# CONFIG_NETFILTER_NETLINK_LOG is not set -# CONFIG_NETFILTER_NETLINK_QUEUE is not set -# CONFIG_NETFILTER_TPROXY is not set -# CONFIG_NETFILTER_XTABLES is not set -# CONFIG_NETFILTER_XT_MATCH_COMMENT is not set -# CONFIG_NETFILTER_XT_MATCH_CONNBYTES is not set -# CONFIG_NETFILTER_XT_MATCH_CONNLIMIT is not set -# CONFIG_NETFILTER_XT_MATCH_CONNMARK is not set -# CONFIG_NETFILTER_XT_MATCH_CONNTRACK is not set -# CONFIG_NETFILTER_XT_MATCH_DCCP is not set -# CONFIG_NETFILTER_XT_MATCH_DSCP is not set -# CONFIG_NETFILTER_XT_MATCH_ESP is not set -# CONFIG_NETFILTER_XT_MATCH_HASHLIMIT is not set -# CONFIG_NETFILTER_XT_MATCH_HELPER is not set -# CONFIG_NETFILTER_XT_MATCH_IPRANGE is not set -# CONFIG_NETFILTER_XT_MATCH_LAYER7_DEBUG is not set -# CONFIG_NETFILTER_XT_MATCH_LAYER7 is not set -# CONFIG_NETFILTER_XT_MATCH_LENGTH is not set -# CONFIG_NETFILTER_XT_MATCH_LIMIT is not set -# CONFIG_NETFILTER_XT_MATCH_MAC is not set -# CONFIG_NETFILTER_XT_MATCH_MARK is not set -# CONFIG_NETFILTER_XT_MATCH_MULTIPORT is not set -# CONFIG_NETFILTER_XT_MATCH_OWNER is not set -# CONFIG_NETFILTER_XT_MATCH_PHYSDEV is not set -# CONFIG_NETFILTER_XT_MATCH_PKTTYPE is not set -# CONFIG_NETFILTER_XT_MATCH_POLICY is not set -# CONFIG_NETFILTER_XT_MATCH_QUOTA is not set -# CONFIG_NETFILTER_XT_MATCH_RATEEST is not set -# CONFIG_NETFILTER_XT_MATCH_REALM is not set -# CONFIG_NETFILTER_XT_MATCH_RECENT is not set -# CONFIG_NETFILTER_XT_MATCH_RECENT_PROC_COMPAT is not set -# CONFIG_NETFILTER_XT_MATCH_SCTP is not set -# CONFIG_NETFILTER_XT_MATCH_STATE is not set -# CONFIG_NETFILTER_XT_MATCH_STATISTIC is not set -# CONFIG_NETFILTER_XT_MATCH_STRING is not set -# CONFIG_NETFILTER_XT_MATCH_TCPMSS is not set -# CONFIG_NETFILTER_XT_MATCH_TIME is not set -# CONFIG_NETFILTER_XT_MATCH_U32 is not set -# CONFIG_NETFILTER_XT_TARGET_CLASSIFY is not set -# CONFIG_NETFILTER_XT_TARGET_CONNMARK is not set -# CONFIG_NETFILTER_XT_TARGET_DSCP is not set -# CONFIG_NETFILTER_XT_TARGET_IMQ is not set -# CONFIG_NETFILTER_XT_TARGET_MARK is not set -# CONFIG_NETFILTER_XT_TARGET_NFLOG is not set -# CONFIG_NETFILTER_XT_TARGET_NFQUEUE is not set -# CONFIG_NETFILTER_XT_TARGET_NOTRACK is not set -# CONFIG_NETFILTER_XT_TARGET_RATEEST is not set -# CONFIG_NETFILTER_XT_TARGET_TCPMSS is not set -# CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP is not set -# CONFIG_NETFILTER_XT_TARGET_TRACE is not set -CONFIG_NETFILTER=y -CONFIG_NET_IPGRE_BROADCAST=y -# CONFIG_NET_IPGRE is not set -# CONFIG_NET_IPIP is not set -# CONFIG_NET_ISA is not set -# CONFIG_NET_KEY is not set -# CONFIG_NET_KEY_MIGRATE is not set -CONFIG_NET_PCI=y -# CONFIG_NET_PCMCIA is not set -# CONFIG_NET_PKTGEN is not set -# CONFIG_NET_POLL_CONTROLLER is not set -# CONFIG_NETPOLL is not set -CONFIG_NET_RADIO=y -# CONFIG_NETROM is not set -# CONFIG_NET_SB1000 is not set -# CONFIG_NET_SCH_ATM is not set -# CONFIG_NET_SCH_CBQ is not set -# CONFIG_NET_SCH_CLK_CPU is not set -# CONFIG_NET_SCH_CLK_GETTIMEOFDAY is not set -CONFIG_NET_SCH_CLK_JIFFIES=y -# CONFIG_NET_SCH_DSMARK is not set -CONFIG_NET_SCHED=y -# CONFIG_NET_SCH_ESFQ is not set -CONFIG_NET_SCH_ESFQ_NFCT=y -CONFIG_NET_SCH_FIFO=y -# CONFIG_NET_SCH_GRED is not set -# CONFIG_NET_SCH_HFSC is not set -# CONFIG_NET_SCH_HTB is not set -# CONFIG_NET_SCH_INGRESS is not set -# CONFIG_NET_SCH_MULTIQ is not set -# CONFIG_NET_SCH_NETEM is not set -# CONFIG_NET_SCH_PRIO is not set -# CONFIG_NET_SCH_RED is not set -# CONFIG_NET_SCH_RR is not set -# CONFIG_NET_SCH_SFQ is not set -# CONFIG_NET_SCH_TBF is not set -# CONFIG_NET_SCH_TEQL is not set -# CONFIG_NET_TULIP is not set -# CONFIG_NET_VENDOR_3COM is not set -CONFIG_NET_WIRELESS_RTNETLINK=y -CONFIG_NET_WIRELESS=y -CONFIG_NETWORK_FILESYSTEMS=y -# CONFIG_NETWORK_SECMARK is not set -# CONFIG_NETXEN_NIC is not set -CONFIG_NET=y -# CONFIG_NEW_GPIO is not set -CONFIG_NEW_LEDS=y -# CONFIG_NF_CONNTRACK_AMANDA is not set -CONFIG_NF_CONNTRACK_ENABLED=y -# CONFIG_NF_CONNTRACK_EVENTS is not set -# CONFIG_NF_CONNTRACK_FTP is not set -# CONFIG_NF_CONNTRACK_H323 is not set -# CONFIG_NF_CONNTRACK_IPV4 is not set -# CONFIG_NF_CONNTRACK_IPV6 is not set -# CONFIG_NF_CONNTRACK_IRC is not set -# CONFIG_NF_CONNTRACK is not set -CONFIG_NF_CONNTRACK_MARK=y -# CONFIG_NF_CONNTRACK_NETBIOS_NS is not set -# CONFIG_NF_CONNTRACK_PPTP is not set -CONFIG_NF_CONNTRACK_PROC_COMPAT=y -# CONFIG_NF_CONNTRACK_RTSP is not set -# CONFIG_NF_CONNTRACK_SANE is not set -# CONFIG_NF_CONNTRACK_SIP is not set -CONFIG_NF_CONNTRACK_SUPPORT=y -# CONFIG_NF_CONNTRACK_TFTP is not set -# CONFIG_NF_CT_ACCT is not set -# CONFIG_NF_CT_NETLINK is not set -# CONFIG_NF_CT_PROTO_DCCP is not set -# CONFIG_NF_CT_PROTO_GRE is not set -# CONFIG_NF_CT_PROTO_SCTP is not set -# CONFIG_NF_CT_PROTO_UDPLITE is not set -# CONFIG_NF_DEFRAG_IPV4 is not set -# CONFIG_NF_NAT_AMANDA is not set -# CONFIG_NF_NAT_FTP is not set -# CONFIG_NF_NAT_H323 is not set -# CONFIG_NF_NAT_IRC is not set -# CONFIG_NF_NAT is not set -CONFIG_NF_NAT_NEEDED=y -# CONFIG_NF_NAT_PPTP is not set -# CONFIG_NF_NAT_PROTO_GRE is not set -# CONFIG_NF_NAT_RTSP is not set -# CONFIG_NF_NAT_SIP is not set -# CONFIG_NF_NAT_SNMP_BASIC is not set -# CONFIG_NF_NAT_TFTP is not set -# CONFIG_NFS_ACL_SUPPORT is not set -CONFIG_NFS_COMMON=y -# CONFIG_NFS_DIRECTIO is not set -# CONFIG_NFSD is not set -CONFIG_NFSD_TCP=y -# CONFIG_NFSD_V2_ACL is not set -# CONFIG_NFSD_V3_ACL is not set -CONFIG_NFSD_V3=y -CONFIG_NFSD_V4=y -# CONFIG_NFS_FS is not set -# CONFIG_NFS_V3_ACL is not set -CONFIG_NFS_V3=y -CONFIG_NFS_V4=y -# CONFIG_NFTL is not set -CONFIG_NL80211=y -# CONFIG_NLS_ASCII is not set -# CONFIG_NLS_CODEPAGE_1250 is not set -# CONFIG_NLS_CODEPAGE_1251 is not set -# CONFIG_NLS_CODEPAGE_437 is not set -# CONFIG_NLS_CODEPAGE_737 is not set -# CONFIG_NLS_CODEPAGE_775 is not set -# CONFIG_NLS_CODEPAGE_850 is not set -# CONFIG_NLS_CODEPAGE_852 is not set -# CONFIG_NLS_CODEPAGE_855 is not set -# CONFIG_NLS_CODEPAGE_857 is not set -# CONFIG_NLS_CODEPAGE_860 is not set -# CONFIG_NLS_CODEPAGE_861 is not set -# CONFIG_NLS_CODEPAGE_862 is not set -# CONFIG_NLS_CODEPAGE_863 is not set -# CONFIG_NLS_CODEPAGE_864 is not set -# CONFIG_NLS_CODEPAGE_865 is not set -# CONFIG_NLS_CODEPAGE_866 is not set -# CONFIG_NLS_CODEPAGE_869 is not set -# CONFIG_NLS_CODEPAGE_874 is not set -# CONFIG_NLS_CODEPAGE_932 is not set -# CONFIG_NLS_CODEPAGE_936 is not set -# CONFIG_NLS_CODEPAGE_949 is not set -# CONFIG_NLS_CODEPAGE_950 is not set -CONFIG_NLS_DEFAULT="iso8859-1" -# CONFIG_NLS is not set -# CONFIG_NLS_ISO8859_13 is not set -# CONFIG_NLS_ISO8859_14 is not set -# CONFIG_NLS_ISO8859_15 is not set -# CONFIG_NLS_ISO8859_1 is not set -# CONFIG_NLS_ISO8859_2 is not set -# CONFIG_NLS_ISO8859_3 is not set -# CONFIG_NLS_ISO8859_4 is not set -# CONFIG_NLS_ISO8859_5 is not set -# CONFIG_NLS_ISO8859_6 is not set -# CONFIG_NLS_ISO8859_7 is not set -# CONFIG_NLS_ISO8859_8 is not set -# CONFIG_NLS_ISO8859_9 is not set -# CONFIG_NLS_KOI8_R is not set -# CONFIG_NLS_KOI8_U is not set -# CONFIG_NLS_UTF8 is not set -# CONFIG_NO_HZ is not set -# CONFIG_NORTEL_HERMES is not set -# CONFIG_NOZOMI is not set -# CONFIG_NS83820 is not set -# CONFIG_NTFS_DEBUG is not set -# CONFIG_NTFS_FS is not set -# CONFIG_NTFS_RW is not set -# CONFIG_NVRAM is not set -# CONFIG_OCF_BENCH is not set -# CONFIG_OCF_EP80579 is not set -# CONFIG_OCF_HIFNHIPP is not set -# CONFIG_OCF_HIFN is not set -# CONFIG_OCF_IXP4XX is not set -# CONFIG_OCF_OCF is not set -# CONFIG_OCF_OCFNULL is not set -# CONFIG_OCFS2_FS is not set -# CONFIG_OCF_SAFE is not set -# CONFIG_OCF_TALITOS is not set -# CONFIG_OMFS_FS is not set -# CONFIG_OSF_PARTITION is not set -# CONFIG_P54_COMMON is not set -CONFIG_PACKET_MMAP=y -CONFIG_PACKET=y -# CONFIG_PAGE_SIZE_16KB is not set -CONFIG_PAGE_SIZE_4KB=y -# CONFIG_PAGE_SIZE_64KB is not set -# CONFIG_PAGE_SIZE_8KB is not set -# CONFIG_PANTHERLORD_FF is not set -# CONFIG_PARPORT is not set -# CONFIG_PARPORT_PC is not set -CONFIG_PARTITION_ADVANCED=y -# CONFIG_PATA_ALI is not set -# CONFIG_PATA_AMD is not set -# CONFIG_PATA_ARTOP is not set -# CONFIG_PATA_ATIIXP is not set -# CONFIG_PATA_CMD640_PCI is not set -# CONFIG_PATA_CMD64X is not set -# CONFIG_PATA_CS5520 is not set -# CONFIG_PATA_CS5530 is not set -# CONFIG_PATA_CS5535 is not set -# CONFIG_PATA_CYPRESS is not set -# CONFIG_PATA_EFAR is not set -# CONFIG_PATA_HPT366 is not set -# CONFIG_PATA_HPT37X is not set -# CONFIG_PATA_HPT3X2N is not set -# CONFIG_PATA_HPT3X3 is not set -# CONFIG_PATA_ISAPNP is not set -# CONFIG_PATA_IT8213 is not set -# CONFIG_PATA_IT821X is not set -# CONFIG_PATA_JMICRON is not set -# CONFIG_PATA_LEGACY is not set -# CONFIG_PATA_MARVELL is not set -# CONFIG_PATA_MPIIX is not set -# CONFIG_PATA_NETCELL is not set -# CONFIG_PATA_NINJA32 is not set -# CONFIG_PATA_NS87410 is not set -# CONFIG_PATA_NS87415 is not set -# CONFIG_PATA_OLDPIIX is not set -# CONFIG_PATA_OPTIDMA is not set -# CONFIG_PATA_OPTI is not set -# CONFIG_PATA_PCMCIA is not set -# CONFIG_PATA_PDC2027X is not set -# CONFIG_PATA_PDC_OLD is not set -# CONFIG_PATA_PLATFORM is not set -# CONFIG_PATA_QDI is not set -# CONFIG_PATA_RADISYS is not set -# CONFIG_PATA_RZ1000 is not set -# CONFIG_PATA_SC1200 is not set -# CONFIG_PATA_SCH is not set -# CONFIG_PATA_SERVERWORKS is not set -# CONFIG_PATA_SIL680 is not set -# CONFIG_PATA_SIS is not set -# CONFIG_PATA_TRIFLEX is not set -# CONFIG_PATA_VIA is not set -# CONFIG_PATA_WINBOND is not set -# CONFIG_PATA_WINBOND_VLB is not set -# CONFIG_PC300TOO is not set -# CONFIG_PCCARD is not set -# CONFIG_PCF8575 is not set -# CONFIG_PCI200SYN is not set -# CONFIG_PCI_ATMEL is not set -# CONFIG_PCI_DISABLE_COMMON_QUIRKS is not set -# CONFIG_PCI_HERMES is not set -# CONFIG_PCI_LEGACY is not set -# CONFIG_PCI_MSI is not set -# CONFIG_PCIPCWATCHDOG is not set -CONFIG_PCI_QUIRKS=y -CONFIG_PCI_SYSCALL=y -CONFIG_PCI=y -# CONFIG_PCMCIA_AHA152X is not set -# CONFIG_PCMCIA_ATMEL is not set -# CONFIG_PCMCIA_DEBUG is not set -# CONFIG_PCMCIA_FDOMAIN is not set -# CONFIG_PCMCIA_HERMES is not set -# CONFIG_PCMCIA_IOCTL is not set -# CONFIG_PCMCIA is not set -# CONFIG_PCMCIA_LOAD_CIS is not set -# CONFIG_PCMCIA_NETWAVE is not set -# CONFIG_PCMCIA_NINJA_SCSI is not set -# CONFIG_PCMCIA_QLOGIC is not set -# CONFIG_PCMCIA_RAYCS is not set -# CONFIG_PCMCIA_SPECTRUM is not set -# CONFIG_PCMCIA_SYM53C500 is not set -# CONFIG_PCMCIA_WAVELAN is not set -# CONFIG_PCMCIA_WL3501 is not set -# CONFIG_PCNET32 is not set -# CONFIG_PCSPKR_PLATFORM is not set -# CONFIG_PD6729 is not set -# CONFIG_PDC_ADMA is not set -# CONFIG_PHANTOM is not set -# CONFIG_PHONE is not set -# CONFIG_PHONET is not set -# CONFIG_PHYLIB is not set -# CONFIG_PHYS_ADDR_T_64BIT is not set -# CONFIG_PID_NS is not set -CONFIG_PLIST=y -# CONFIG_PLX_HERMES is not set -# CONFIG_PMIC_DA903X is not set -# CONFIG_PM is not set -# CONFIG_POSIX_MQUEUE is not set -# CONFIG_POWER_SUPPLY is not set -CONFIG_PPC4xx_GPIO=y -# CONFIG_PPP_ASYNC is not set -# CONFIG_PPP_BSDCOMP is not set -# CONFIG_PPP_DEFLATE is not set -CONFIG_PPP_FILTER=y -# CONFIG_PPP is not set -# CONFIG_PPP_MPPE is not set -CONFIG_PPP_MULTILINK=y -# CONFIG_PPPOATM is not set -# CONFIG_PPPOE is not set -# CONFIG_PPPOL2TP is not set -# CONFIG_PPP_SYNC_TTY is not set -# CONFIG_PREEMPT is not set -CONFIG_PREEMPT_NONE=y -# CONFIG_PREEMPT_VOLUNTARY is not set -CONFIG_PREVENT_FIRMWARE_BUILD=y -# CONFIG_PRINTK_TIME is not set -CONFIG_PRINTK=y -# CONFIG_PRISM54 is not set -CONFIG_PROC_FS=y -CONFIG_PROC_KCORE=y -# CONFIG_PROC_PAGE_MONITOR is not set -CONFIG_PROC_SYSCTL=y -# CONFIG_PROFILING is not set -# CONFIG_QEMU is not set -# CONFIG_QLA3XXX is not set -# CONFIG_QNX4FS_FS is not set -# CONFIG_QSEMI_PHY is not set -# CONFIG_QUOTA is not set -# CONFIG_R3964 is not set -# CONFIG_R8169 is not set -# CONFIG_RADIO_ADAPTERS is not set -# CONFIG_RADIO_AZTECH is not set -# CONFIG_RADIO_CADET is not set -# CONFIG_RADIO_GEMTEK is not set -# CONFIG_RADIO_GEMTEK_PCI is not set -# CONFIG_RADIO_MAESTRO is not set -# CONFIG_RADIO_MAXIRADIO is not set -# CONFIG_RADIO_RTRACK2 is not set -# CONFIG_RADIO_RTRACK is not set -# CONFIG_RADIO_SF16FMI is not set -# CONFIG_RADIO_SF16FMR2 is not set -# CONFIG_RADIO_TERRATEC is not set -# CONFIG_RADIO_TRUST is not set -# CONFIG_RADIO_TYPHOON is not set -# CONFIG_RADIO_ZOLTRIX is not set -# CONFIG_RAID_ATTRS is not set -CONFIG_RAMFS=y -# CONFIG_RAW_DRIVER is not set -# CONFIG_RCU_CPU_STALL_DETECTOR is not set -# CONFIG_REALTEK_PHY is not set -# CONFIG_REGULATOR_BQ24022 is not set -# CONFIG_REGULATOR_FIXED_VOLTAGE is not set -# CONFIG_REGULATOR is not set -# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set -# CONFIG_REISERFS_CHECK is not set -# CONFIG_REISERFS_FS is not set -# CONFIG_REISERFS_FS_XATTR is not set -# CONFIG_REISERFS_PROC_INFO is not set -# CONFIG_RELAY is not set -# CONFIG_RESOURCES_64BIT is not set -# CONFIG_RFD_FTL is not set -# CONFIG_RFKILL_INPUT is not set -# CONFIG_RFKILL is not set -# CONFIG_ROMFS_FS is not set -# CONFIG_ROSE is not set -# CONFIG_RPCSEC_GSS_KRB5 is not set -# CONFIG_RPCSEC_GSS_SPKM3 is not set -# CONFIG_RT2X00 is not set -# CONFIG_RTC_CLASS is not set -# CONFIG_RTC_DEBUG is not set -# CONFIG_RTC_DRV_BQ4802 is not set -CONFIG_RTC_DRV_CMOS=y -# CONFIG_RTC_DRV_DS1286 is not set -# CONFIG_RTC_DRV_DS1305 is not set -# CONFIG_RTC_DRV_DS1307 is not set -# CONFIG_RTC_DRV_DS1374 is not set -# CONFIG_RTC_DRV_DS1390 is not set -# CONFIG_RTC_DRV_DS1511 is not set -# CONFIG_RTC_DRV_DS1553 is not set -# CONFIG_RTC_DRV_DS1672 is not set -# CONFIG_RTC_DRV_DS1742 is not set -# CONFIG_RTC_DRV_DS3234 is not set -# CONFIG_RTC_DRV_FM3130 is not set -# CONFIG_RTC_DRV_ISL1208 is not set -# CONFIG_RTC_DRV_M41T80 is not set -# CONFIG_RTC_DRV_M41T94 is not set -# CONFIG_RTC_DRV_M48T35 is not set -# CONFIG_RTC_DRV_M48T59 is not set -# CONFIG_RTC_DRV_M48T86 is not set -# CONFIG_RTC_DRV_MAX6900 is not set -# CONFIG_RTC_DRV_MAX6902 is not set -# CONFIG_RTC_DRV_PCF50606 is not set -# CONFIG_RTC_DRV_PCF8563 is not set -# CONFIG_RTC_DRV_PCF8583 is not set -# CONFIG_RTC_DRV_R9701 is not set -# CONFIG_RTC_DRV_RS5C348 is not set -# CONFIG_RTC_DRV_RS5C372 is not set -# CONFIG_RTC_DRV_RTC7301 is not set -# CONFIG_RTC_DRV_RX8581 is not set -# CONFIG_RTC_DRV_S35390A is not set -# CONFIG_RTC_DRV_STK17TA8 is not set -# CONFIG_RTC_DRV_TEST is not set -# CONFIG_RTC_DRV_V3020 is not set -# CONFIG_RTC_DRV_X1205 is not set -CONFIG_RTC_HCTOSYS_DEVICE="rtc0" -CONFIG_RTC_HCTOSYS=y -# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set -CONFIG_RTC_INTF_DEV=y -CONFIG_RTC_INTF_PROC=y -CONFIG_RTC_INTF_SYSFS=y -CONFIG_RTC_LIB=y -# CONFIG_RTL8180 is not set -# CONFIG_RTL8187 is not set -# CONFIG_RTL8306_PHY is not set -CONFIG_RT_MUTEXES=y -CONFIG_RWSEM_GENERIC_SPINLOCK=y -# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set -# CONFIG_S2IO is not set -# CONFIG_SAMPLES is not set -# CONFIG_SATA_AHCI is not set -# CONFIG_SATA_INIC162X is not set -# CONFIG_SATA_MV is not set -# CONFIG_SATA_NV is not set -# CONFIG_SATA_PMP is not set -# CONFIG_SATA_PROMISE is not set -# CONFIG_SATA_QSTOR is not set -# CONFIG_SATA_SIL24 is not set -# CONFIG_SATA_SIL is not set -# CONFIG_SATA_SIS is not set -# CONFIG_SATA_SVW is not set -# CONFIG_SATA_SX4 is not set -# CONFIG_SATA_ULI is not set -# CONFIG_SATA_VIA is not set -# CONFIG_SATA_VITESSE is not set -# CONFIG_SC92031 is not set -# CONFIG_SCC is not set -# CONFIG_SCHED_TRACER is not set -# CONFIG_SCSI_3W_9XXX is not set -# CONFIG_SCSI_7000FASST is not set -# CONFIG_SCSI_AACRAID is not set -# CONFIG_SCSI_ACARD is not set -# CONFIG_SCSI_ADVANSYS is not set -# CONFIG_SCSI_AHA152X is not set -# CONFIG_SCSI_AHA1542 is not set -# CONFIG_SCSI_AIC79XX is not set -# CONFIG_SCSI_AIC7XXX is not set -# CONFIG_SCSI_AIC7XXX_OLD is not set -# CONFIG_SCSI_AIC94XX is not set -# CONFIG_SCSI_ARCMSR is not set -# CONFIG_SCSI_BUSLOGIC is not set -# CONFIG_SCSI_CONSTANTS is not set -# CONFIG_SCSI_DC390T is not set -# CONFIG_SCSI_DC395x is not set -# CONFIG_SCSI_DEBUG is not set -# CONFIG_SCSI_DH is not set -CONFIG_SCSI_DMA=y -# CONFIG_SCSI_DMX3191D is not set -# CONFIG_SCSI_DPT_I2O is not set -# CONFIG_SCSI_DTC3280 is not set -# CONFIG_SCSI_EATA is not set -# CONFIG_SCSI_ESP_CORE is not set -# CONFIG_SCSI_FC_ATTRS is not set -# CONFIG_SCSI_FUTURE_DOMAIN is not set -# CONFIG_SCSI_GDTH is not set -# CONFIG_SCSI_GENERIC_NCR5380 is not set -# CONFIG_SCSI_GENERIC_NCR5380_MMIO is not set -# CONFIG_SCSI_HPTIOP is not set -# CONFIG_SCSI_IN2000 is not set -# CONFIG_SCSI_INIA100 is not set -# CONFIG_SCSI_INITIO is not set -# CONFIG_SCSI_IPR is not set -# CONFIG_SCSI_IPS is not set -# CONFIG_SCSI_ISCSI_ATTRS is not set -# CONFIG_SCSI is not set -# CONFIG_SCSI_LOGGING is not set -# CONFIG_SCSI_LOWLEVEL_PCMCIA is not set -CONFIG_SCSI_LOWLEVEL=y -# CONFIG_SCSI_LPFC is not set -CONFIG_SCSI_MULTI_LUN=y -# CONFIG_SCSI_MVSAS is not set -# CONFIG_SCSI_NCR53C406A is not set -# CONFIG_SCSI_NETLINK is not set -# CONFIG_SCSI_NSP32 is not set -# CONFIG_SCSI_PAS16 is not set -CONFIG_SCSI_PROC_FS=y -# CONFIG_SCSI_PSI240I is not set -# CONFIG_SCSI_QLA_FC is not set -# CONFIG_SCSI_QLA_ISCSI is not set -# CONFIG_SCSI_QLOGIC_1280 is not set -# CONFIG_SCSI_QLOGIC_FAS is not set -# CONFIG_SCSI_SAS_ATTRS is not set -# CONFIG_SCSI_SAS_LIBSAS is not set -# CONFIG_SCSI_SCAN_ASYNC is not set -# CONFIG_SCSI_SEAGATE is not set -# CONFIG_SCSI_SPI_ATTRS is not set -# CONFIG_SCSI_SRP_ATTRS is not set -# CONFIG_SCSI_SRP is not set -# CONFIG_SCSI_STEX is not set -# CONFIG_SCSI_SYM53C416 is not set -# CONFIG_SCSI_SYM53C8XX_2 is not set -# CONFIG_SCSI_T128 is not set -# CONFIG_SCSI_TGT is not set -# CONFIG_SCSI_U14_34F is not set -# CONFIG_SCSI_ULTRASTOR is not set -CONFIG_SCSI_WAIT_SCAN=m -# CONFIG_SECCOMP is not set -# CONFIG_SECURITY_FILE_CAPABILITIES is not set -# CONFIG_SECURITYFS is not set -# CONFIG_SECURITY is not set -CONFIG_SELECT_MEMORY_MODEL=y -# CONFIG_SENSORS_ABITUGURU3 is not set -# CONFIG_SENSORS_ABITUGURU is not set -# CONFIG_SENSORS_AD7414 is not set -# CONFIG_SENSORS_AD7418 is not set -# CONFIG_SENSORS_ADCXX is not set -# CONFIG_SENSORS_ADM1021 is not set -# CONFIG_SENSORS_ADM1025 is not set -# CONFIG_SENSORS_ADM1026 is not set -# CONFIG_SENSORS_ADM1029 is not set -# CONFIG_SENSORS_ADM1031 is not set -# CONFIG_SENSORS_ADM9240 is not set -# CONFIG_SENSORS_ADS7828 is not set -# CONFIG_SENSORS_ADT7462 is not set -# CONFIG_SENSORS_ADT7470 is not set -# CONFIG_SENSORS_ADT7473 is not set -# CONFIG_SENSORS_APPLESMC is not set -# CONFIG_SENSORS_ASB100 is not set -# CONFIG_SENSORS_ATXP1 is not set -# CONFIG_SENSORS_CORETEMP is not set -# CONFIG_SENSORS_DME1737 is not set -# CONFIG_SENSORS_DS1337 is not set -# CONFIG_SENSORS_DS1374 is not set -# CONFIG_SENSORS_DS1621 is not set -# CONFIG_SENSORS_EEPROM is not set -# CONFIG_SENSORS_F71805F is not set -# CONFIG_SENSORS_F71882FG is not set -# CONFIG_SENSORS_F75375S is not set -# CONFIG_SENSORS_FSCHER is not set -# CONFIG_SENSORS_FSCHMD is not set -# CONFIG_SENSORS_FSCPOS is not set -# CONFIG_SENSORS_GL518SM is not set -# CONFIG_SENSORS_GL520SM is not set -# CONFIG_SENSORS_HDAPS is not set -# CONFIG_SENSORS_I5K_AMB is not set -# CONFIG_SENSORS_IT87 is not set -# CONFIG_SENSORS_K8TEMP is not set -# CONFIG_SENSORS_LM63 is not set -# CONFIG_SENSORS_LM70 is not set -# CONFIG_SENSORS_LM75 is not set -# CONFIG_SENSORS_LM77 is not set -# CONFIG_SENSORS_LM78 is not set -# CONFIG_SENSORS_LM80 is not set -# CONFIG_SENSORS_LM83 is not set -# CONFIG_SENSORS_LM85 is not set -# CONFIG_SENSORS_LM87 is not set -# CONFIG_SENSORS_LM90 is not set -# CONFIG_SENSORS_LM92 is not set -# CONFIG_SENSORS_LM93 is not set -# CONFIG_SENSORS_M41T00 is not set -# CONFIG_SENSORS_MAX1111 is not set -# CONFIG_SENSORS_MAX1619 is not set -# CONFIG_SENSORS_MAX6650 is not set -# CONFIG_SENSORS_MAX6875 is not set -# CONFIG_SENSORS_PC87427 is not set -# CONFIG_SENSORS_PCA9539 is not set -# CONFIG_SENSORS_PCF8574 is not set -# CONFIG_SENSORS_PCF8591 is not set -# CONFIG_SENSORS_SIS5595 is not set -# CONFIG_SENSORS_SMSC47B397 is not set -# CONFIG_SENSORS_SMSC47M192 is not set -# CONFIG_SENSORS_SMSC47M1 is not set -# CONFIG_SENSORS_THMC50 is not set -# CONFIG_SENSORS_TSL2550 is not set -# CONFIG_SENSORS_VIA686A is not set -# CONFIG_SENSORS_VT1211 is not set -# CONFIG_SENSORS_VT8231 is not set -# CONFIG_SENSORS_W83627EHF is not set -# CONFIG_SENSORS_W83627HF is not set -# CONFIG_SENSORS_W83781D is not set -# CONFIG_SENSORS_W83791D is not set -# CONFIG_SENSORS_W83792D is not set -# CONFIG_SENSORS_W83793 is not set -# CONFIG_SENSORS_W83L785TS is not set -# CONFIG_SENSORS_W83L786NG is not set -CONFIG_SERIAL_8250_CONSOLE=y -# CONFIG_SERIAL_8250_CS is not set -CONFIG_SERIAL_8250_NR_UARTS=2 -# CONFIG_SERIAL_8250_PCI is not set -CONFIG_SERIAL_8250_RUNTIME_UARTS=2 -CONFIG_SERIAL_8250=y -CONFIG_SERIAL_CORE_CONSOLE=y -CONFIG_SERIAL_CORE=y -# CONFIG_SERIAL_JSM is not set -# CONFIG_SERIAL_NONSTANDARD is not set -# CONFIG_SERIAL_UARTLITE is not set -# CONFIG_SERIO is not set -# CONFIG_SGI_IOC4 is not set -# CONFIG_SGI_PARTITION is not set -# CONFIG_SHAPER is not set -CONFIG_SHMEM=y -CONFIG_SIGNALFD=y -# CONFIG_SIS190 is not set -# CONFIG_SIS900 is not set -# CONFIG_SK98LIN is not set -# CONFIG_SKGE is not set -# CONFIG_SKY2_DEBUG is not set -# CONFIG_SKY2 is not set -CONFIG_SLABINFO=y -CONFIG_SLAB=y -# CONFIG_SLHC is not set -# CONFIG_SLIP is not set -# CONFIG_SLOB is not set -# CONFIG_SLUB_DEBUG is not set -# CONFIG_SLUB is not set -# CONFIG_SMB_FS is not set -# CONFIG_SMB_NLS_DEFAULT is not set -# CONFIG_SMC911X is not set -# CONFIG_SMC91X is not set -# CONFIG_SMP is not set -# CONFIG_SMSC_PHY is not set -# CONFIG_SND_AC97_POWER_SAVE is not set -# CONFIG_SND_AD1816A is not set -# CONFIG_SND_AD1848 is not set -# CONFIG_SND_AD1889 is not set -# CONFIG_SND_ADLIB is not set -# CONFIG_SND_ALI5451 is not set -# CONFIG_SND_ALS100 is not set -# CONFIG_SND_ALS300 is not set -# CONFIG_SND_ALS4000 is not set -# CONFIG_SND_ARM is not set -# CONFIG_SND_ATIIXP is not set -# CONFIG_SND_ATIIXP_MODEM is not set -# CONFIG_SND_AU8810 is not set -# CONFIG_SND_AU8820 is not set -# CONFIG_SND_AU8830 is not set -# CONFIG_SND_AW2 is not set -# CONFIG_SND_AZT2320 is not set -# CONFIG_SND_AZT3328 is not set -# CONFIG_SND_BT87X is not set -# CONFIG_SND_CA0106 is not set -# CONFIG_SND_CMI8330 is not set -# CONFIG_SND_CMIPCI is not set -# CONFIG_SND_CS4231 is not set -# CONFIG_SND_CS4232 is not set -# CONFIG_SND_CS4236 is not set -# CONFIG_SND_CS4281 is not set -# CONFIG_SND_CS46XX is not set -# CONFIG_SND_CS5530 is not set -# CONFIG_SND_CS5535AUDIO is not set -# CONFIG_SND_DARLA20 is not set -# CONFIG_SND_DARLA24 is not set -# CONFIG_SND_DEBUG is not set -CONFIG_SND_DRIVERS=y -# CONFIG_SND_DT019X is not set -# CONFIG_SND_DUMMY is not set -# CONFIG_SND_DYNAMIC_MINORS is not set -# CONFIG_SND_ECHO3G is not set -# CONFIG_SND_EMU10K1 is not set -# CONFIG_SND_EMU10K1X is not set -# CONFIG_SND_ENS1370 is not set -# CONFIG_SND_ENS1371 is not set -# CONFIG_SND_ES1688 is not set -# CONFIG_SND_ES18XX is not set -# CONFIG_SND_ES1938 is not set -# CONFIG_SND_ES1968 is not set -# CONFIG_SND_ES968 is not set -# CONFIG_SND_FM801 is not set -# CONFIG_SND_GINA20 is not set -# CONFIG_SND_GINA24 is not set -# CONFIG_SND_GUSCLASSIC is not set -# CONFIG_SND_GUSEXTREME is not set -# CONFIG_SND_GUSMAX is not set -# CONFIG_SND_HDA_INTEL is not set -# CONFIG_SND_HDSP is not set -# CONFIG_SND_HDSPM is not set -# CONFIG_SND_HIFIER is not set -# CONFIG_SND_HWDEP is not set -# CONFIG_SND_ICE1712 is not set -# CONFIG_SND_ICE1724 is not set -# CONFIG_SND_INDIGODJ is not set -# CONFIG_SND_INDIGOIO is not set -# CONFIG_SND_INDIGO is not set -# CONFIG_SND_INTEL8X0 is not set -# CONFIG_SND_INTEL8X0M is not set -# CONFIG_SND_INTERWAVE is not set -# CONFIG_SND_INTERWAVE_STB is not set -# CONFIG_SND_ISA is not set -# CONFIG_SND is not set -# CONFIG_SND_KORG1212 is not set -# CONFIG_SND_LAYLA20 is not set -# CONFIG_SND_LAYLA24 is not set -# CONFIG_SND_MAESTRO3 is not set -# CONFIG_SND_MIA is not set -# CONFIG_SND_MIPS is not set -# CONFIG_SND_MIRO is not set -# CONFIG_SND_MIXART is not set -# CONFIG_SND_MIXER_OSS is not set -# CONFIG_SND_MONA is not set -# CONFIG_SND_MPU401 is not set -# CONFIG_SND_MTPAV is not set -# CONFIG_SND_NM256 is not set -# CONFIG_SND_OPL3SA2 is not set -# CONFIG_SND_OPTI92X_AD1848 is not set -# CONFIG_SND_OPTI92X_CS4231 is not set -# CONFIG_SND_OPTI93X is not set -CONFIG_SND_OSSEMUL=y -# CONFIG_SND_OXYGEN is not set -# CONFIG_SND_PCI is not set -# CONFIG_SND_PCMCIA is not set -# CONFIG_SND_PCM is not set -# CONFIG_SND_PCM_OSS is not set -CONFIG_SND_PCM_OSS_PLUGINS=y -# CONFIG_SND_PCXHR is not set -# CONFIG_SND_PDAUDIOCF is not set -# CONFIG_SND_RAWMIDI is not set -# CONFIG_SND_RIPTIDE is not set -# CONFIG_SND_RME32 is not set -# CONFIG_SND_RME9652 is not set -# CONFIG_SND_RME96 is not set -# CONFIG_SND_RTCTIMER is not set -# CONFIG_SND_SB16 is not set -# CONFIG_SND_SB8 is not set -# CONFIG_SND_SBAWE is not set -# CONFIG_SND_SEQUENCER is not set -# CONFIG_SND_SERIAL_U16550 is not set -# CONFIG_SND_SGALAXY is not set -# CONFIG_SND_SOC is not set -# CONFIG_SND_SONICVIBES is not set -# CONFIG_SND_SPI is not set -# CONFIG_SND_SSCAPE is not set -# CONFIG_SND_SUPPORT_OLD_API is not set -# CONFIG_SND_TIMER is not set -# CONFIG_SND_TRIDENT is not set -# CONFIG_SND_USB_AUDIO is not set -# CONFIG_SND_USB_CAIAQ is not set -# CONFIG_SND_USB_US122L is not set -# CONFIG_SND_USB_USX2Y is not set -CONFIG_SND_USB=y -# CONFIG_SND_VERBOSE_PRINTK is not set -CONFIG_SND_VERBOSE_PROCFS=y -# CONFIG_SND_VIA82XX is not set -# CONFIG_SND_VIA82XX_MODEM is not set -# CONFIG_SND_VIRTUOSO is not set -# CONFIG_SND_VX222 is not set -# CONFIG_SND_VXPOCKET is not set -# CONFIG_SND_WAVEFRONT is not set -# CONFIG_SND_YMFPCI is not set -# CONFIG_SNI_RM is not set -# CONFIG_SOC_CAMERA is not set -# CONFIG_SOFT_WATCHDOG is not set -# CONFIG_SOLARIS_X86_PARTITION is not set -# CONFIG_SONYPI is not set -# CONFIG_SOUND is not set -# CONFIG_SOUND_PRIME is not set -# CONFIG_SPARSEMEM_MANUAL is not set -# CONFIG_SPARSEMEM_STATIC is not set -# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set -# CONFIG_SPI_AT25 is not set -# CONFIG_SPI_DEBUG is not set -# CONFIG_SPI_GPIO_OLD is not set -# CONFIG_SPI is not set -# CONFIG_SPI_MASTER is not set -# CONFIG_SPI_TLE62X0 is not set -CONFIG_SPLIT_PTLOCK_CPUS=4 -# CONFIG_SQUASHFS_EMBEDDED is not set -CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3 -# CONFIG_SQUASHFS_VMALLOC is not set -CONFIG_SQUASHFS=y -# CONFIG_SSB_BLOCKIO is not set -# CONFIG_SSB_DEBUG is not set -# CONFIG_SSB is not set -# CONFIG_SSB_PCMCIAHOST is not set -CONFIG_SSB_POSSIBLE=y -# CONFIG_SSB_SILENT is not set -# CONFIG_SSFDC is not set -CONFIG_STACKTRACE_SUPPORT=y -# CONFIG_STAGING is not set -CONFIG_STANDALONE=y -CONFIG_STP=y -# CONFIG_STRIP is not set -# CONFIG_SUNDANCE is not set -# CONFIG_SUNGEM is not set -# CONFIG_SUN_PARTITION is not set -# CONFIG_SUNRPC_BIND34 is not set -# CONFIG_SUNRPC_GSS is not set -# CONFIG_SUNRPC is not set -# CONFIG_SUNRPC_REGISTER_V4 is not set -CONFIG_SUSPEND_UP_POSSIBLE=y -CONFIG_SWAP=y -# CONFIG_SWCONFIG is not set -# CONFIG_SYNCLINK_CS is not set -CONFIG_SYN_COOKIES=y -CONFIG_SYSCTL_SYSCALL_CHECK=y -CONFIG_SYSCTL_SYSCALL=y -CONFIG_SYSCTL=y -# CONFIG_SYSFS_DEPRECATED is not set -# CONFIG_SYSFS_DEPRECATED_V2 is not set -CONFIG_SYSFS=y -# CONFIG_SYS_HYPERVISOR is not set -# CONFIG_SYSV68_PARTITION is not set -# CONFIG_SYSV_FS is not set -CONFIG_SYSVIPC_SYSCTL=y -CONFIG_SYSVIPC=y -# CONFIG_TASKSTATS is not set -# CONFIG_TCG_TPM is not set -# CONFIG_TCIC is not set -CONFIG_TCP_CONG_ADVANCED=y -# CONFIG_TCP_CONG_BIC is not set -# CONFIG_TCP_CONG_CUBIC is not set -# CONFIG_TCP_CONG_HSTCP is not set -# CONFIG_TCP_CONG_HTCP is not set -# CONFIG_TCP_CONG_HYBLA is not set -# CONFIG_TCP_CONG_ILLINOIS is not set -# CONFIG_TCP_CONG_LP is not set -# CONFIG_TCP_CONG_SCALABLE is not set -# CONFIG_TCP_CONG_VEGAS is not set -# CONFIG_TCP_CONG_VENO is not set -CONFIG_TCP_CONG_WESTWOOD=y -# CONFIG_TCP_CONG_YEAH is not set -# CONFIG_TCP_MD5SIG is not set -# CONFIG_TEXTSEARCH_BM is not set -# CONFIG_TEXTSEARCH_FSM is not set -# CONFIG_TEXTSEARCH_KMP is not set -CONFIG_TEXTSEARCH=y -# CONFIG_THERMAL_HWMON is not set -# CONFIG_THERMAL is not set -# CONFIG_THRUSTMASTER_FF is not set -CONFIG_TICK_ONESHOT=y -# CONFIG_TIFM_CORE is not set -# CONFIG_TIGON3 is not set -CONFIG_TIMERFD=y -# CONFIG_TINY_SHMEM is not set -# CONFIG_TIPC is not set -# CONFIG_TLAN is not set -# CONFIG_TMD_HERMES is not set -# CONFIG_TMPFS_POSIX_ACL is not set -CONFIG_TMPFS=y -# CONFIG_TPS65010 is not set -CONFIG_TRACE_IRQFLAGS_SUPPORT=y -# CONFIG_TR is not set -# CONFIG_TUNER_3036 is not set -# CONFIG_TUNER_TEA5761 is not set -# CONFIG_TUN is not set -# CONFIG_UDF_FS is not set -CONFIG_UDF_NLS=y -CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" -# CONFIG_UFS_FS is not set -# CONFIG_UIO is not set -# CONFIG_ULTRIX_PARTITION is not set -# CONFIG_UNEVICTABLE_LRU is not set -CONFIG_UNIX98_PTYS=y -# CONFIG_UNIXWARE_DISKLABEL is not set -CONFIG_UNIX=y -# CONFIG_UNUSED_SYMBOLS is not set -# CONFIG_USB_ACECAD is not set -# CONFIG_USB_ACM is not set -# CONFIG_USB_ADUTUX is not set -# CONFIG_USB_AIPTEK is not set -CONFIG_USB_ALI_M5632=y -CONFIG_USB_AN2720=y -# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set -# CONFIG_USB_APPLEDISPLAY is not set -# CONFIG_USB_APPLETOUCH is not set -CONFIG_USB_ARCH_HAS_EHCI=y -CONFIG_USB_ARCH_HAS_HCD=y -CONFIG_USB_ARCH_HAS_OHCI=y -CONFIG_USB_ARMLINUX=y -# CONFIG_USB_ATI_REMOTE2 is not set -# CONFIG_USB_ATI_REMOTE is not set -# CONFIG_USB_ATM is not set -# CONFIG_USB_AUERSWALD is not set -# CONFIG_USB_BANDWIDTH is not set -CONFIG_USB_BELKIN=y -# CONFIG_USB_BERRY_CHARGE is not set -# CONFIG_USB_C67X00_HCD is not set -# CONFIG_USB_CATC is not set -# CONFIG_USB_CXACRU is not set -# CONFIG_USB_CYPRESS_CY7C63 is not set -# CONFIG_USB_CYTHERM is not set -# CONFIG_USB_DABUSB is not set -# CONFIG_USB_DEBUG is not set -# CONFIG_USB_DEVICE_CLASS is not set -CONFIG_USB_DEVICEFS=y -# CONFIG_USB_DSBR is not set -# CONFIG_USB_DYNAMIC_MINORS is not set -CONFIG_USB_EHCI_ROOT_HUB_TT=y -# CONFIG_USB_EHCI_SPLIT_ISO is not set -# CONFIG_USB_EHCI_TT_NEWSCHED is not set -# CONFIG_USB_EMI26 is not set -# CONFIG_USB_EMI62 is not set -# CONFIG_USB_EPSON2888 is not set -# CONFIG_USB_ET61X251 is not set -CONFIG_USB_EZUSB=y -# CONFIG_USB_FTDI_ELAN is not set -# CONFIG_USB_GADGET is not set -# CONFIG_USB_GSPCA_CONEX is not set -# CONFIG_USB_GSPCA_ETOMS is not set -# CONFIG_USB_GSPCA_FINEPIX is not set -# CONFIG_USB_GSPCA is not set -# CONFIG_USB_GSPCA_MARS is not set -# CONFIG_USB_GSPCA_OV519 is not set -# CONFIG_USB_GSPCA_PAC207 is not set -# CONFIG_USB_GSPCA_PAC7311 is not set -# CONFIG_USB_GSPCA_SONIXB is not set -# CONFIG_USB_GSPCA_SONIXJ is not set -# CONFIG_USB_GSPCA_SPCA500 is not set -# CONFIG_USB_GSPCA_SPCA501 is not set -# CONFIG_USB_GSPCA_SPCA505 is not set -# CONFIG_USB_GSPCA_SPCA506 is not set -# CONFIG_USB_GSPCA_SPCA508 is not set -# CONFIG_USB_GSPCA_SPCA561 is not set -# CONFIG_USB_GSPCA_STK014 is not set -# CONFIG_USB_GSPCA_SUNPLUS is not set -# CONFIG_USB_GSPCA_T613 is not set -# CONFIG_USB_GSPCA_TV8532 is not set -# CONFIG_USB_GSPCA_VC032X is not set -# CONFIG_USB_GSPCA_ZC3XX is not set -# CONFIG_USB_HIDDEV is not set -# CONFIG_USB_HIDINPUT_POWERBOOK is not set -CONFIG_USB_HIDINPUT=y -# CONFIG_USB_HID is not set -# CONFIG_USB_HSO is not set -# CONFIG_USB_HWA_HCD is not set -# CONFIG_USB_IBMCAM is not set -# CONFIG_USB_IDMOUSE is not set -# CONFIG_USB_IOWARRIOR is not set -# CONFIG_USB_ISIGHTFW is not set -# CONFIG_USB is not set -# CONFIG_USB_ISP116X_HCD is not set -# CONFIG_USB_ISP1760_HCD is not set -# CONFIG_USB_KAWETH is not set -# CONFIG_USB_KBD is not set -# CONFIG_USB_KBTAB is not set -# CONFIG_USB_KC2190 is not set -# CONFIG_USB_KEYSPAN_REMOTE is not set -# CONFIG_USB_KONICAWC is not set -# CONFIG_USB_LCD is not set -# CONFIG_USB_LD is not set -# CONFIG_USB_LED is not set -# CONFIG_USB_LEGOTOWER is not set -# CONFIG_USB_LIBUSUAL is not set -# CONFIG_USB_M5602 is not set -# CONFIG_USB_MDC800 is not set -# CONFIG_USB_MICROTEK is not set -# CONFIG_USB_MON is not set -# CONFIG_USB_MOUSE is not set -# CONFIG_USB_NET_AX8817X is not set -# CONFIG_USB_NET_CDCETHER is not set -# CONFIG_USB_NET_CDC_SUBSET is not set -# CONFIG_USB_NET_DM9601 is not set -# CONFIG_USB_NET_GL620A is not set -# CONFIG_USB_NET_MCS7830 is not set -# CONFIG_USB_NET_NET1080 is not set -# CONFIG_USB_NET_PLUSB is not set -# CONFIG_USB_NET_RNDIS_HOST is not set -# CONFIG_USB_NET_RNDIS_WLAN is not set -# CONFIG_USB_NET_SMSC95XX is not set -# CONFIG_USB_NET_ZAURUS is not set -# CONFIG_USB_OHCI_BIG_ENDIAN is not set -# CONFIG_USB_OHCI_HCD is not set -# CONFIG_USB_OHCI_HCD_SSB is not set -CONFIG_USB_OHCI_LITTLE_ENDIAN=y -# CONFIG_USB_OTG_BLACKLIST_HUB is not set -# CONFIG_USB_OTG is not set -# CONFIG_USB_OTG_WHITELIST is not set -# CONFIG_USB_OV511 is not set -# CONFIG_USBPCWATCHDOG is not set -# CONFIG_USB_PEGASUS is not set -# CONFIG_USB_PHIDGET is not set -# CONFIG_USB_POWERMATE is not set -# CONFIG_USB_PRINTER is not set -# CONFIG_USB_QUICKCAM_MESSENGER is not set -# CONFIG_USB_R8A66597_HCD is not set -# CONFIG_USB_RIO500 is not set -# CONFIG_USB_RTL8150 is not set -# CONFIG_USB_S2255 is not set -# CONFIG_USB_SE401 is not set -# CONFIG_USB_SERIAL_AIRCABLE is not set -# CONFIG_USB_SERIAL_AIRPRIME is not set -# CONFIG_USB_SERIAL_ARK3116 is not set -# CONFIG_USB_SERIAL_BELKIN is not set -# CONFIG_USB_SERIAL_CH341 is not set -# CONFIG_USB_SERIAL_CP2101 is not set -# CONFIG_USB_SERIAL_CYBERJACK is not set -# CONFIG_USB_SERIAL_CYPRESS_M8 is not set -# CONFIG_USB_SERIAL_DEBUG is not set -# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set -# CONFIG_USB_SERIAL_EDGEPORT is not set -# CONFIG_USB_SERIAL_EDGEPORT_TI is not set -# CONFIG_USB_SERIAL_EMPEG is not set -# CONFIG_USB_SERIAL_FTDI_SIO is not set -# CONFIG_USB_SERIAL_FUNSOFT is not set -# CONFIG_USB_SERIAL_GARMIN is not set -CONFIG_USB_SERIAL_GENERIC=y -# CONFIG_USB_SERIAL_HP4X is not set -# CONFIG_USB_SERIAL_IPAQ is not set -# CONFIG_USB_SERIAL_IPW is not set -# CONFIG_USB_SERIAL_IR is not set -# CONFIG_USB_SERIAL is not set -# CONFIG_USB_SERIAL_IUU is not set -# CONFIG_USB_SERIAL_KEYSPAN is not set -CONFIG_USB_SERIAL_KEYSPAN_MPR=y -# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set -CONFIG_USB_SERIAL_KEYSPAN_USA18X=y -CONFIG_USB_SERIAL_KEYSPAN_USA19QI=y -CONFIG_USB_SERIAL_KEYSPAN_USA19QW=y -CONFIG_USB_SERIAL_KEYSPAN_USA19W=y -CONFIG_USB_SERIAL_KEYSPAN_USA19=y -CONFIG_USB_SERIAL_KEYSPAN_USA28XA=y -CONFIG_USB_SERIAL_KEYSPAN_USA28XB=y -CONFIG_USB_SERIAL_KEYSPAN_USA28X=y -CONFIG_USB_SERIAL_KEYSPAN_USA28=y -CONFIG_USB_SERIAL_KEYSPAN_USA49WLC=y -CONFIG_USB_SERIAL_KEYSPAN_USA49W=y -# CONFIG_USB_SERIAL_KLSI is not set -# CONFIG_USB_SERIAL_KOBIL_SCT is not set -# CONFIG_USB_SERIAL_MCT_U232 is not set -# CONFIG_USB_SERIAL_MOS7720 is not set -# CONFIG_USB_SERIAL_MOS7840 is not set -# CONFIG_USB_SERIAL_MOTOROLA is not set -# CONFIG_USB_SERIAL_NAVMAN is not set -# CONFIG_USB_SERIAL_OMNINET is not set -# CONFIG_USB_SERIAL_OPTION is not set -# CONFIG_USB_SERIAL_OTI6858 is not set -# CONFIG_USB_SERIAL_PL2303 is not set -# CONFIG_USB_SERIAL_SAFE is not set -CONFIG_USB_SERIAL_SAFE_PADDED=y -# CONFIG_USB_SERIAL_SIERRAWIRELESS is not set -# CONFIG_USB_SERIAL_SPCP8X5 is not set -# CONFIG_USB_SERIAL_TI is not set -# CONFIG_USB_SERIAL_VISOR is not set -# CONFIG_USB_SERIAL_WHITEHEAT is not set -# CONFIG_USB_SERIAL_XIRCOM is not set -# CONFIG_USB_SEVSEG is not set -# CONFIG_USB_SISUSBVGA is not set -# CONFIG_USB_SL811_HCD is not set -# CONFIG_USB_SN9C102 is not set -# CONFIG_USB_SPEEDTOUCH is not set -# CONFIG_USB_STKWEBCAM is not set -CONFIG_USB_STORAGE_ALAUDA=y -# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set -CONFIG_USB_STORAGE_DATAFAB=y -# CONFIG_USB_STORAGE_DEBUG is not set -CONFIG_USB_STORAGE_DPCM=y -CONFIG_USB_STORAGE_FREECOM=y -# CONFIG_USB_STORAGE_ISD200 is not set -# CONFIG_USB_STORAGE is not set -CONFIG_USB_STORAGE_JUMPSHOT=y -CONFIG_USB_STORAGE_KARMA=y -# CONFIG_USB_STORAGE_ONETOUCH is not set -CONFIG_USB_STORAGE_SDDR09=y -CONFIG_USB_STORAGE_SDDR55=y -# CONFIG_USB_STORAGE_SIERRA is not set -CONFIG_USB_STORAGE_USBAT=y -# CONFIG_USB_STV680 is not set -# CONFIG_USB_SUPPORT is not set -# CONFIG_USB_SUSPEND is not set -# CONFIG_USB_TEST is not set -# CONFIG_USB_TMC is not set -# CONFIG_USB_TOUCHSCREEN is not set -# CONFIG_USB_TRANCEVIBRATOR is not set -# CONFIG_USB_UEAGLEATM is not set -# CONFIG_USB_USBNET is not set -# CONFIG_USB_USBNET_MII is not set -# CONFIG_USB_VICAM is not set -CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV=y -# CONFIG_USB_VIDEO_CLASS is not set -# CONFIG_USB_VST is not set -# CONFIG_USB_W9968CF is not set -# CONFIG_USB_WACOM is not set -# CONFIG_USB_WDM is not set -# CONFIG_USB_WHCI_HCD is not set -# CONFIG_USB_WUSB_CBAF is not set -# CONFIG_USB_WUSB is not set -# CONFIG_USB_XPAD is not set -# CONFIG_USB_XUSBATM is not set -# CONFIG_USB_YEALINK is not set -# CONFIG_USB_ZC0301 is not set -# CONFIG_USB_ZD1201 is not set -# CONFIG_USB_ZR364XX is not set -# CONFIG_USE_GENERIC_SMP_HELPERS is not set -# CONFIG_UTS_NS is not set -# CONFIG_UWB is not set -# CONFIG_VETH is not set -# CONFIG_VFAT_FS is not set -# CONFIG_VIA_VELOCITY is not set -# CONFIG_VIDEO_ADV7170 is not set -# CONFIG_VIDEO_ADV7175 is not set -# CONFIG_VIDEO_ADV_DEBUG is not set -# CONFIG_VIDEO_ALLOW_V4L1 is not set -# CONFIG_VIDEO_BT819 is not set -# CONFIG_VIDEO_BT848 is not set -# CONFIG_VIDEO_BT856 is not set -# CONFIG_VIDEO_BT866 is not set -# CONFIG_VIDEO_CAFE_CCIC is not set -# CONFIG_VIDEO_CAPTURE_DRIVERS is not set -# CONFIG_VIDEO_CPIA is not set -# CONFIG_VIDEO_CS5345 is not set -# CONFIG_VIDEO_CS53L32A is not set -# CONFIG_VIDEO_CX2341X is not set -# CONFIG_VIDEO_CX25840 is not set -# CONFIG_VIDEO_CX88 is not set -# CONFIG_VIDEO_DEV is not set -# CONFIG_VIDEO_DPC is not set -# CONFIG_VIDEO_EM28XX is not set -# CONFIG_VIDEO_FIXED_MINOR_RANGES is not set -# CONFIG_VIDEO_HELPER_CHIPS_AUTO is not set -# CONFIG_VIDEO_HEXIUM_GEMINI is not set -# CONFIG_VIDEO_HEXIUM_ORION is not set -# CONFIG_VIDEO_IVTV is not set -# CONFIG_VIDEO_KS0127 is not set -# CONFIG_VIDEO_M52790 is not set -# CONFIG_VIDEO_MEDIA is not set -# CONFIG_VIDEO_MSP3400 is not set -# CONFIG_VIDEO_MXB is not set -# CONFIG_VIDEO_OUTPUT_CONTROL is not set -# CONFIG_VIDEO_OV7670 is not set -# CONFIG_VIDEO_OVCAMCHIP is not set -# CONFIG_VIDEO_PMS is not set -# CONFIG_VIDEO_PVRUSB2 is not set -# CONFIG_VIDEO_SAA5246A is not set -# CONFIG_VIDEO_SAA5249 is not set -# CONFIG_VIDEO_SAA7110 is not set -# CONFIG_VIDEO_SAA7111 is not set -# CONFIG_VIDEO_SAA7114 is not set -# CONFIG_VIDEO_SAA711X is not set -# CONFIG_VIDEO_SAA7127 is not set -# CONFIG_VIDEO_SAA7134 is not set -# CONFIG_VIDEO_SAA717X is not set -# CONFIG_VIDEO_SAA7185 is not set -# CONFIG_VIDEO_SAA7191 is not set -# CONFIG_VIDEO_SH_MOBILE_CEU is not set -# CONFIG_VIDEO_STRADIS is not set -# CONFIG_VIDEO_TCM825X is not set -# CONFIG_VIDEO_TDA7432 is not set -# CONFIG_VIDEO_TDA9840 is not set -# CONFIG_VIDEO_TDA9875 is not set -# CONFIG_VIDEO_TEA6415C is not set -# CONFIG_VIDEO_TEA6420 is not set -# CONFIG_VIDEO_TLV320AIC23B is not set -# CONFIG_VIDEO_TVAUDIO is not set -# CONFIG_VIDEO_TVP5150 is not set -# CONFIG_VIDEO_UPD64031A is not set -# CONFIG_VIDEO_UPD64083 is not set -# CONFIG_VIDEO_USBVISION is not set -CONFIG_VIDEO_V4L1_COMPAT=y -# CONFIG_VIDEO_V4L1 is not set -# CONFIG_VIDEO_V4L2_COMMON is not set -# CONFIG_VIDEO_V4L2 is not set -# CONFIG_VIDEO_VIVI is not set -# CONFIG_VIDEO_VP27SMPX is not set -# CONFIG_VIDEO_VPX3220 is not set -# CONFIG_VIDEO_WM8739 is not set -# CONFIG_VIDEO_WM8775 is not set -# CONFIG_VIDEO_ZORAN is not set -# CONFIG_VIRQ_DEBUG is not set -CONFIG_VIRT_TO_BUS=y -# CONFIG_VIRTUALIZATION is not set -# CONFIG_VITESSE_PHY is not set -# CONFIG_VLAN_8021Q_GVRP is not set -CONFIG_VLAN_8021Q=y -# CONFIG_VM_EVENT_COUNTERS is not set -# CONFIG_VMSPLIT_1G is not set -# CONFIG_VMSPLIT_2G is not set -CONFIG_VMSPLIT_3G=y -# CONFIG_VT is not set -# CONFIG_VXFS_FS is not set -# CONFIG_W1 is not set -# CONFIG_W1_MASTER_DS1WM is not set -# CONFIG_W1_MASTER_DS2482 is not set -# CONFIG_W1_MASTER_DS2490 is not set -# CONFIG_W1_MASTER_GPIO is not set -# CONFIG_W1_MASTER_MATROX is not set -# CONFIG_W1_SLAVE_BQ27000 is not set -# CONFIG_W1_SLAVE_DS2433 is not set -# CONFIG_W1_SLAVE_DS2760 is not set -# CONFIG_W1_SLAVE_SMEM is not set -# CONFIG_W1_SLAVE_THERM is not set -# CONFIG_W83627HF_WDT is not set -# CONFIG_W83697HF_WDT is not set -# CONFIG_W83877F_WDT is not set -# CONFIG_W83977F_WDT is not set -# CONFIG_WAN is not set -# CONFIG_WAN_ROUTER is not set -# CONFIG_WANXL is not set -# CONFIG_WATCHDOG_NOWAYOUT is not set -CONFIG_WATCHDOG=y -# CONFIG_WDTPCI is not set -CONFIG_WIRELESS_EXT_SYSFS=y -CONFIG_WIRELESS_EXT=y -CONFIG_WIRELESS_OLD_REGULATORY=y -CONFIG_WIRELESS=y -CONFIG_WLAN_80211=y -# CONFIG_WLAN_PRE80211 is not set -# CONFIG_WR_PPMC is not set -# CONFIG_X25 is not set -# CONFIG_XFRM_IPCOMP is not set -# CONFIG_XFRM_MIGRATE is not set -# CONFIG_XFRM_STATISTICS is not set -# CONFIG_XFRM_SUB_POLICY is not set -# CONFIG_XFRM_USER is not set -CONFIG_XFRM=y -# CONFIG_XFS_DEBUG is not set -# CONFIG_XFS_FS is not set -# CONFIG_XFS_POSIX_ACL is not set -# CONFIG_XFS_QUOTA is not set -# CONFIG_XFS_RT is not set -# CONFIG_XFS_SECURITY is not set -# CONFIG_XIP_KERNEL is not set -# CONFIG_YAFFS_FS is not set -# CONFIG_YAM is not set -# CONFIG_YELLOWFIN is not set -# CONFIG_YENTA is not set -# CONFIG_YENTA_O2 is not set -# CONFIG_YENTA_RICOH is not set -# CONFIG_YENTA_TI is not set -# CONFIG_YENTA_TOSHIBA is not set -# CONFIG_ZD1211RW_DEBUG is not set -# CONFIG_ZD1211RW is not set -# CONFIG_ZEROPLUS_FF is not set -# CONFIG_ZISOFS_FS is not set -CONFIG_ZISOFS=y -CONFIG_ZLIB_DEFLATE=y -CONFIG_ZLIB_INFLATE=y -CONFIG_ZONE_DMA_FLAG=1 -CONFIG_ZONE_DMA=y diff --git a/target/linux/generic-2.6/config-2.6.30 b/target/linux/generic-2.6/config-2.6.30 index 62f05d621..d5e82a2a2 100644 --- a/target/linux/generic-2.6/config-2.6.30 +++ b/target/linux/generic-2.6/config-2.6.30 @@ -597,6 +597,7 @@ CONFIG_GENERIC_TIME=y CONFIG_HAMRADIO=y # CONFIG_HAPPYMEAL is not set # CONFIG_HAVE_AOUT is not set +# CONFIG_HCALL_STATS is not set # CONFIG_HDLC_CISCO is not set # CONFIG_HDLC_FR is not set # CONFIG_HDLC is not set @@ -2542,6 +2543,7 @@ CONFIG_VMSPLIT_3G=y # CONFIG_VT is not set # CONFIG_VXFS_FS is not set # CONFIG_W1 is not set +# CONFIG_W1_CON is not set # CONFIG_W1_MASTER_DS1WM is not set # CONFIG_W1_MASTER_DS2482 is not set # CONFIG_W1_MASTER_DS2490 is not set diff --git a/target/linux/generic-2.6/config-2.6.31 b/target/linux/generic-2.6/config-2.6.31 index 221a13f42..9e56c5d3d 100644 --- a/target/linux/generic-2.6/config-2.6.31 +++ b/target/linux/generic-2.6/config-2.6.31 @@ -618,6 +618,7 @@ CONFIG_HAMRADIO=y # CONFIG_HAVE_AOUT is not set CONFIG_HAVE_MLOCKED_PAGE_BIT=y CONFIG_HAVE_MLOCK=y +# CONFIG_HCALL_STATS is not set # CONFIG_HDLC_CISCO is not set # CONFIG_HDLC_FR is not set # CONFIG_HDLC is not set @@ -662,6 +663,7 @@ CONFIG_HAVE_MLOCK=y # CONFIG_HID_SUPPORT is not set # CONFIG_HID_THRUSTMASTER is not set # CONFIG_HID_TOPSEED is not set +# CONFIG_HID_WACOM is not set # CONFIG_HID_ZEROPLUS is not set # CONFIG_HIGHMEM is not set CONFIG_HIGH_RES_TIMERS=y @@ -2523,6 +2525,7 @@ CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV=y # CONFIG_VIA_VELOCITY is not set # CONFIG_VIDEO_ADV7170 is not set # CONFIG_VIDEO_ADV7175 is not set +# CONFIG_VIDEO_ADV7343 is not set # CONFIG_VIDEO_ADV_DEBUG is not set # CONFIG_VIDEO_ALLOW_V4L1 is not set # CONFIG_VIDEO_BT819 is not set @@ -2552,6 +2555,7 @@ CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV=y # CONFIG_VIDEO_M52790 is not set # CONFIG_VIDEO_MEDIA is not set # CONFIG_VIDEO_MSP3400 is not set +# CONFIG_VIDEO_MT9V011 is not set # CONFIG_VIDEO_MXB is not set # CONFIG_VIDEO_OUTPUT_CONTROL is not set # CONFIG_VIDEO_OV7670 is not set @@ -2578,6 +2582,7 @@ CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV=y # CONFIG_VIDEO_TDA9875 is not set # CONFIG_VIDEO_TEA6415C is not set # CONFIG_VIDEO_TEA6420 is not set +# CONFIG_VIDEO_THS7303 is not set # CONFIG_VIDEO_TLV320AIC23B is not set # CONFIG_VIDEO_TVAUDIO is not set # CONFIG_VIDEO_TVP514X is not set @@ -2611,6 +2616,7 @@ CONFIG_VMSPLIT_3G=y # CONFIG_VT is not set # CONFIG_VXFS_FS is not set # CONFIG_W1 is not set +# CONFIG_W1_CON is not set # CONFIG_W1_MASTER_DS1WM is not set # CONFIG_W1_MASTER_DS2482 is not set # CONFIG_W1_MASTER_DS2490 is not set diff --git a/target/linux/generic-2.6/config-2.6.32 b/target/linux/generic-2.6/config-2.6.32 index 146c853f8..3b0e75438 100644 --- a/target/linux/generic-2.6/config-2.6.32 +++ b/target/linux/generic-2.6/config-2.6.32 @@ -627,6 +627,7 @@ CONFIG_HAMRADIO=y # CONFIG_HAVE_AOUT is not set CONFIG_HAVE_MLOCKED_PAGE_BIT=y CONFIG_HAVE_MLOCK=y +# CONFIG_HCALL_STATS is not set # CONFIG_HDLC_CISCO is not set # CONFIG_HDLC_FR is not set # CONFIG_HDLC is not set @@ -672,6 +673,7 @@ CONFIG_HAVE_MLOCK=y # CONFIG_HID_THRUSTMASTER is not set # CONFIG_HID_TOPSEED is not set # CONFIG_HID_TWINHAN is not set +# CONFIG_HID_WACOM is not set # CONFIG_HID_ZEROPLUS is not set # CONFIG_HIGHMEM is not set CONFIG_HIGH_RES_TIMERS=y @@ -2646,6 +2648,7 @@ CONFIG_VMSPLIT_3G=y # CONFIG_VT is not set # CONFIG_VXFS_FS is not set # CONFIG_W1 is not set +# CONFIG_W1_CON is not set # CONFIG_W1_MASTER_DS1WM is not set # CONFIG_W1_MASTER_DS2482 is not set # CONFIG_W1_MASTER_DS2490 is not set diff --git a/target/linux/generic-2.6/files-2.6.28/include/linux/gpio_buttons.h b/target/linux/generic-2.6/files-2.6.28/include/linux/gpio_buttons.h deleted file mode 100644 index f5e629725..000000000 --- a/target/linux/generic-2.6/files-2.6.28/include/linux/gpio_buttons.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Definitions for the GPIO buttons interface driver - * - * Copyright (C) 2007,2008 Gabor Juhos - * - * 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_ */ - diff --git a/target/linux/generic-2.6/files-2.6.28/include/linux/gpio_dev.h b/target/linux/generic-2.6/files-2.6.28/include/linux/gpio_dev.h deleted file mode 100644 index 3f3c9c772..000000000 --- a/target/linux/generic-2.6/files-2.6.28/include/linux/gpio_dev.h +++ /dev/null @@ -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 diff --git a/target/linux/generic-2.6/files-2.6.30/drivers/char/gpio_dev.c b/target/linux/generic-2.6/files-2.6.30/drivers/char/gpio_dev.c deleted file mode 100644 index 8392fcf2d..000000000 --- a/target/linux/generic-2.6/files-2.6.30/drivers/char/gpio_dev.c +++ /dev/null @@ -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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#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"); diff --git a/target/linux/generic-2.6/files-2.6.30/drivers/input/misc/gpio_buttons.c b/target/linux/generic-2.6/files-2.6.30/drivers/input/misc/gpio_buttons.c deleted file mode 100644 index 83a817834..000000000 --- a/target/linux/generic-2.6/files-2.6.30/drivers/input/misc/gpio_buttons.c +++ /dev/null @@ -1,209 +0,0 @@ -/* - * Driver for buttons on GPIO lines not capable of generating interrupts - * - * Copyright (C) 2007,2008 Gabor Juhos - * - * This file was based on: /drivers/input/misc/cobalt_btns.c - * Copyright (C) 2007 Yoichi Yuasa - * - * 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 -#include -#include - -#include -#include -#include -#include - -#include - -#include - -#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 "); -MODULE_VERSION(DRV_VERSION); -MODULE_DESCRIPTION("Polled buttons driver for CPU GPIOs"); - diff --git a/target/linux/generic-2.6/files-2.6.30/drivers/leds/ledtrig-morse.c b/target/linux/generic-2.6/files-2.6.30/drivers/leds/ledtrig-morse.c deleted file mode 100644 index cb47480a3..000000000 --- a/target/linux/generic-2.6/files-2.6.30/drivers/leds/ledtrig-morse.c +++ /dev/null @@ -1,365 +0,0 @@ -/* - * LED Morse Trigger - * - * Copyright (C) 2007 Gabor Juhos - * - * This file was based on: drivers/led/ledtrig-timer.c - * Copyright 2005-2006 Openedhand Ltd. - * Author: Richard Purdie - * - * 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 - * Copyright (C) 2003 Tomas Szepe - * - * 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#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, "\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 "); -MODULE_DESCRIPTION("Morse LED trigger"); -MODULE_LICENSE("GPL"); diff --git a/target/linux/generic-2.6/files-2.6.30/drivers/leds/ledtrig-netdev.c b/target/linux/generic-2.6/files-2.6.30/drivers/leds/ledtrig-netdev.c deleted file mode 100644 index 4193e4eda..000000000 --- a/target/linux/generic-2.6/files-2.6.30/drivers/leds/ledtrig-netdev.c +++ /dev/null @@ -1,454 +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 - * - * Derived from ledtrig-timer.c which is: - * Copyright 2005-2006 Openedhand Ltd. - * Author: Richard Purdie - * - * 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26) -#include -#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; - } -#ifdef CONFIG_COMPAT_NET_DEV_OPS - dev_stats = trigger_data->net_dev->get_stats(trigger_data->net_dev); -#else - dev_stats = trigger_data->net_dev->netdev_ops->ndo_get_stats(trigger_data->net_dev); -#endif - 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 "); -MODULE_DESCRIPTION("Netdev LED trigger"); -MODULE_LICENSE("GPL"); diff --git a/target/linux/generic-2.6/files-2.6.30/include/linux/gpio_buttons.h b/target/linux/generic-2.6/files-2.6.30/include/linux/gpio_buttons.h deleted file mode 100644 index f5e629725..000000000 --- a/target/linux/generic-2.6/files-2.6.30/include/linux/gpio_buttons.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Definitions for the GPIO buttons interface driver - * - * Copyright (C) 2007,2008 Gabor Juhos - * - * 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_ */ - diff --git a/target/linux/generic-2.6/files-2.6.30/include/linux/gpio_dev.h b/target/linux/generic-2.6/files-2.6.30/include/linux/gpio_dev.h deleted file mode 100644 index 3f3c9c772..000000000 --- a/target/linux/generic-2.6/files-2.6.30/include/linux/gpio_dev.h +++ /dev/null @@ -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 diff --git a/target/linux/generic-2.6/files-2.6.31/drivers/char/gpio_dev.c b/target/linux/generic-2.6/files-2.6.31/drivers/char/gpio_dev.c deleted file mode 100644 index 8392fcf2d..000000000 --- a/target/linux/generic-2.6/files-2.6.31/drivers/char/gpio_dev.c +++ /dev/null @@ -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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#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"); diff --git a/target/linux/generic-2.6/files-2.6.31/drivers/input/misc/gpio_buttons.c b/target/linux/generic-2.6/files-2.6.31/drivers/input/misc/gpio_buttons.c deleted file mode 100644 index 83a817834..000000000 --- a/target/linux/generic-2.6/files-2.6.31/drivers/input/misc/gpio_buttons.c +++ /dev/null @@ -1,209 +0,0 @@ -/* - * Driver for buttons on GPIO lines not capable of generating interrupts - * - * Copyright (C) 2007,2008 Gabor Juhos - * - * This file was based on: /drivers/input/misc/cobalt_btns.c - * Copyright (C) 2007 Yoichi Yuasa - * - * 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 -#include -#include - -#include -#include -#include -#include - -#include - -#include - -#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 "); -MODULE_VERSION(DRV_VERSION); -MODULE_DESCRIPTION("Polled buttons driver for CPU GPIOs"); - diff --git a/target/linux/generic-2.6/files-2.6.31/drivers/leds/ledtrig-morse.c b/target/linux/generic-2.6/files-2.6.31/drivers/leds/ledtrig-morse.c deleted file mode 100644 index cb47480a3..000000000 --- a/target/linux/generic-2.6/files-2.6.31/drivers/leds/ledtrig-morse.c +++ /dev/null @@ -1,365 +0,0 @@ -/* - * LED Morse Trigger - * - * Copyright (C) 2007 Gabor Juhos - * - * This file was based on: drivers/led/ledtrig-timer.c - * Copyright 2005-2006 Openedhand Ltd. - * Author: Richard Purdie - * - * 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 - * Copyright (C) 2003 Tomas Szepe - * - * 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#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, "\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 "); -MODULE_DESCRIPTION("Morse LED trigger"); -MODULE_LICENSE("GPL"); diff --git a/target/linux/generic-2.6/files-2.6.31/drivers/leds/ledtrig-netdev.c b/target/linux/generic-2.6/files-2.6.31/drivers/leds/ledtrig-netdev.c deleted file mode 100644 index 4193e4eda..000000000 --- a/target/linux/generic-2.6/files-2.6.31/drivers/leds/ledtrig-netdev.c +++ /dev/null @@ -1,454 +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 - * - * Derived from ledtrig-timer.c which is: - * Copyright 2005-2006 Openedhand Ltd. - * Author: Richard Purdie - * - * 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26) -#include -#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; - } -#ifdef CONFIG_COMPAT_NET_DEV_OPS - dev_stats = trigger_data->net_dev->get_stats(trigger_data->net_dev); -#else - dev_stats = trigger_data->net_dev->netdev_ops->ndo_get_stats(trigger_data->net_dev); -#endif - 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 "); -MODULE_DESCRIPTION("Netdev LED trigger"); -MODULE_LICENSE("GPL"); diff --git a/target/linux/generic-2.6/files-2.6.31/include/linux/glamo-engine.h b/target/linux/generic-2.6/files-2.6.31/include/linux/glamo-engine.h deleted file mode 100644 index 516d45fa6..000000000 --- a/target/linux/generic-2.6/files-2.6.31/include/linux/glamo-engine.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef __GLAMO_ENGINE_H -#define __GLAMO_ENGINE_H - -enum glamo_engine { - GLAMO_ENGINE_CAPTURE = 0, - GLAMO_ENGINE_ISP = 1, - GLAMO_ENGINE_JPEG = 2, - GLAMO_ENGINE_MPEG_ENC = 3, - GLAMO_ENGINE_MPEG_DEC = 4, - GLAMO_ENGINE_LCD = 5, - GLAMO_ENGINE_CMDQ = 6, - GLAMO_ENGINE_2D = 7, - GLAMO_ENGINE_3D = 8, - GLAMO_ENGINE_MMC = 9, - GLAMO_ENGINE_MICROP0 = 10, - GLAMO_ENGINE_RISC = 11, - GLAMO_ENGINE_MICROP1_MPEG_ENC = 12, - GLAMO_ENGINE_MICROP1_MPEG_DEC = 13, -#if 0 - GLAMO_ENGINE_H264_DEC = 14, - GLAMO_ENGINE_RISC1 = 15, - GLAMO_ENGINE_SPI = 16, -#endif - __NUM_GLAMO_ENGINES -}; - -#endif diff --git a/target/linux/generic-2.6/files-2.6.31/include/linux/glamofb.h b/target/linux/generic-2.6/files-2.6.31/include/linux/glamofb.h deleted file mode 100644 index 5f9fab5a4..000000000 --- a/target/linux/generic-2.6/files-2.6.31/include/linux/glamofb.h +++ /dev/null @@ -1,35 +0,0 @@ -#ifndef _LINUX_GLAMOFB_H -#define _LINUX_GLAMOFB_H - -#include - -#ifdef __KERNEL__ - -struct glamo_core; -struct glamofb_handle; - -struct glamo_fb_platform_data { - int width, height; - - int num_modes; - struct fb_videomode *modes; - - struct glamo_core *core; -}; - -int glamofb_cmd_mode(struct glamofb_handle *gfb, int on); -int glamofb_cmd_write(struct glamofb_handle *gfb, u_int16_t val); - -#ifdef CONFIG_MFD_GLAMO -void glamo_lcm_reset(struct platform_device *pdev, int level); -#else -#define glamo_lcm_reset(...) do {} while (0) -#endif - -#endif - -#define GLAMOFB_ENGINE_ENABLE _IOW('F', 0x1, __u32) -#define GLAMOFB_ENGINE_DISABLE _IOW('F', 0x2, __u32) -#define GLAMOFB_ENGINE_RESET _IOW('F', 0x3, __u32) - -#endif diff --git a/target/linux/generic-2.6/files-2.6.31/include/linux/gpio_buttons.h b/target/linux/generic-2.6/files-2.6.31/include/linux/gpio_buttons.h deleted file mode 100644 index f5e629725..000000000 --- a/target/linux/generic-2.6/files-2.6.31/include/linux/gpio_buttons.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Definitions for the GPIO buttons interface driver - * - * Copyright (C) 2007,2008 Gabor Juhos - * - * 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_ */ - diff --git a/target/linux/generic-2.6/files-2.6.31/include/linux/gpio_dev.h b/target/linux/generic-2.6/files-2.6.31/include/linux/gpio_dev.h deleted file mode 100644 index 3f3c9c772..000000000 --- a/target/linux/generic-2.6/files-2.6.31/include/linux/gpio_dev.h +++ /dev/null @@ -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 diff --git a/target/linux/generic-2.6/files-2.6.32/drivers/char/gpio_dev.c b/target/linux/generic-2.6/files-2.6.32/drivers/char/gpio_dev.c deleted file mode 100644 index 8392fcf2d..000000000 --- a/target/linux/generic-2.6/files-2.6.32/drivers/char/gpio_dev.c +++ /dev/null @@ -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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#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"); diff --git a/target/linux/generic-2.6/files-2.6.32/drivers/input/misc/gpio_buttons.c b/target/linux/generic-2.6/files-2.6.32/drivers/input/misc/gpio_buttons.c deleted file mode 100644 index 83a817834..000000000 --- a/target/linux/generic-2.6/files-2.6.32/drivers/input/misc/gpio_buttons.c +++ /dev/null @@ -1,209 +0,0 @@ -/* - * Driver for buttons on GPIO lines not capable of generating interrupts - * - * Copyright (C) 2007,2008 Gabor Juhos - * - * This file was based on: /drivers/input/misc/cobalt_btns.c - * Copyright (C) 2007 Yoichi Yuasa - * - * 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 -#include -#include - -#include -#include -#include -#include - -#include - -#include - -#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 "); -MODULE_VERSION(DRV_VERSION); -MODULE_DESCRIPTION("Polled buttons driver for CPU GPIOs"); - diff --git a/target/linux/generic-2.6/files-2.6.32/drivers/leds/ledtrig-morse.c b/target/linux/generic-2.6/files-2.6.32/drivers/leds/ledtrig-morse.c deleted file mode 100644 index cb47480a3..000000000 --- a/target/linux/generic-2.6/files-2.6.32/drivers/leds/ledtrig-morse.c +++ /dev/null @@ -1,365 +0,0 @@ -/* - * LED Morse Trigger - * - * Copyright (C) 2007 Gabor Juhos - * - * This file was based on: drivers/led/ledtrig-timer.c - * Copyright 2005-2006 Openedhand Ltd. - * Author: Richard Purdie - * - * 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 - * Copyright (C) 2003 Tomas Szepe - * - * 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#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, "\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 "); -MODULE_DESCRIPTION("Morse LED trigger"); -MODULE_LICENSE("GPL"); diff --git a/target/linux/generic-2.6/files-2.6.32/drivers/leds/ledtrig-netdev.c b/target/linux/generic-2.6/files-2.6.32/drivers/leds/ledtrig-netdev.c deleted file mode 100644 index 4193e4eda..000000000 --- a/target/linux/generic-2.6/files-2.6.32/drivers/leds/ledtrig-netdev.c +++ /dev/null @@ -1,454 +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 - * - * Derived from ledtrig-timer.c which is: - * Copyright 2005-2006 Openedhand Ltd. - * Author: Richard Purdie - * - * 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26) -#include -#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; - } -#ifdef CONFIG_COMPAT_NET_DEV_OPS - dev_stats = trigger_data->net_dev->get_stats(trigger_data->net_dev); -#else - dev_stats = trigger_data->net_dev->netdev_ops->ndo_get_stats(trigger_data->net_dev); -#endif - 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 "); -MODULE_DESCRIPTION("Netdev LED trigger"); -MODULE_LICENSE("GPL"); diff --git a/target/linux/generic-2.6/files-2.6.32/include/linux/glamo-engine.h b/target/linux/generic-2.6/files-2.6.32/include/linux/glamo-engine.h deleted file mode 100644 index 516d45fa6..000000000 --- a/target/linux/generic-2.6/files-2.6.32/include/linux/glamo-engine.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef __GLAMO_ENGINE_H -#define __GLAMO_ENGINE_H - -enum glamo_engine { - GLAMO_ENGINE_CAPTURE = 0, - GLAMO_ENGINE_ISP = 1, - GLAMO_ENGINE_JPEG = 2, - GLAMO_ENGINE_MPEG_ENC = 3, - GLAMO_ENGINE_MPEG_DEC = 4, - GLAMO_ENGINE_LCD = 5, - GLAMO_ENGINE_CMDQ = 6, - GLAMO_ENGINE_2D = 7, - GLAMO_ENGINE_3D = 8, - GLAMO_ENGINE_MMC = 9, - GLAMO_ENGINE_MICROP0 = 10, - GLAMO_ENGINE_RISC = 11, - GLAMO_ENGINE_MICROP1_MPEG_ENC = 12, - GLAMO_ENGINE_MICROP1_MPEG_DEC = 13, -#if 0 - GLAMO_ENGINE_H264_DEC = 14, - GLAMO_ENGINE_RISC1 = 15, - GLAMO_ENGINE_SPI = 16, -#endif - __NUM_GLAMO_ENGINES -}; - -#endif diff --git a/target/linux/generic-2.6/files-2.6.32/include/linux/glamofb.h b/target/linux/generic-2.6/files-2.6.32/include/linux/glamofb.h deleted file mode 100644 index 5f9fab5a4..000000000 --- a/target/linux/generic-2.6/files-2.6.32/include/linux/glamofb.h +++ /dev/null @@ -1,35 +0,0 @@ -#ifndef _LINUX_GLAMOFB_H -#define _LINUX_GLAMOFB_H - -#include - -#ifdef __KERNEL__ - -struct glamo_core; -struct glamofb_handle; - -struct glamo_fb_platform_data { - int width, height; - - int num_modes; - struct fb_videomode *modes; - - struct glamo_core *core; -}; - -int glamofb_cmd_mode(struct glamofb_handle *gfb, int on); -int glamofb_cmd_write(struct glamofb_handle *gfb, u_int16_t val); - -#ifdef CONFIG_MFD_GLAMO -void glamo_lcm_reset(struct platform_device *pdev, int level); -#else -#define glamo_lcm_reset(...) do {} while (0) -#endif - -#endif - -#define GLAMOFB_ENGINE_ENABLE _IOW('F', 0x1, __u32) -#define GLAMOFB_ENGINE_DISABLE _IOW('F', 0x2, __u32) -#define GLAMOFB_ENGINE_RESET _IOW('F', 0x3, __u32) - -#endif diff --git a/target/linux/generic-2.6/files-2.6.32/include/linux/gpio_buttons.h b/target/linux/generic-2.6/files-2.6.32/include/linux/gpio_buttons.h deleted file mode 100644 index f5e629725..000000000 --- a/target/linux/generic-2.6/files-2.6.32/include/linux/gpio_buttons.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Definitions for the GPIO buttons interface driver - * - * Copyright (C) 2007,2008 Gabor Juhos - * - * 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_ */ - diff --git a/target/linux/generic-2.6/files-2.6.32/include/linux/gpio_dev.h b/target/linux/generic-2.6/files-2.6.32/include/linux/gpio_dev.h deleted file mode 100644 index 3f3c9c772..000000000 --- a/target/linux/generic-2.6/files-2.6.32/include/linux/gpio_dev.h +++ /dev/null @@ -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 diff --git a/target/linux/generic-2.6/files-2.6.28/drivers/char/gpio_dev.c b/target/linux/generic-2.6/files/drivers/char/gpio_dev.c similarity index 100% rename from target/linux/generic-2.6/files-2.6.28/drivers/char/gpio_dev.c rename to target/linux/generic-2.6/files/drivers/char/gpio_dev.c diff --git a/target/linux/generic-2.6/files-2.6.28/drivers/input/misc/gpio_buttons.c b/target/linux/generic-2.6/files/drivers/input/misc/gpio_buttons.c similarity index 100% rename from target/linux/generic-2.6/files-2.6.28/drivers/input/misc/gpio_buttons.c rename to target/linux/generic-2.6/files/drivers/input/misc/gpio_buttons.c diff --git a/target/linux/generic-2.6/files-2.6.28/drivers/leds/ledtrig-morse.c b/target/linux/generic-2.6/files/drivers/leds/ledtrig-morse.c similarity index 100% rename from target/linux/generic-2.6/files-2.6.28/drivers/leds/ledtrig-morse.c rename to target/linux/generic-2.6/files/drivers/leds/ledtrig-morse.c diff --git a/target/linux/generic-2.6/files-2.6.28/drivers/leds/ledtrig-netdev.c b/target/linux/generic-2.6/files/drivers/leds/ledtrig-netdev.c similarity index 99% rename from target/linux/generic-2.6/files-2.6.28/drivers/leds/ledtrig-netdev.c rename to target/linux/generic-2.6/files/drivers/leds/ledtrig-netdev.c index fac3571bd..8dba8e654 100644 --- a/target/linux/generic-2.6/files-2.6.28/drivers/leds/ledtrig-netdev.c +++ b/target/linux/generic-2.6/files/drivers/leds/ledtrig-netdev.c @@ -46,7 +46,7 @@ * 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: @@ -307,7 +307,7 @@ done: 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; + const struct net_device_stats *dev_stats; unsigned new_activity; write_lock(&trigger_data->lock); @@ -318,7 +318,7 @@ static void netdev_trig_timer(unsigned long arg) goto no_restart; } - dev_stats = trigger_data->net_dev->get_stats(trigger_data->net_dev); + dev_stats = 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); diff --git a/target/linux/generic-2.6/files/drivers/net/phy/adm6996.c b/target/linux/generic-2.6/files/drivers/net/phy/adm6996.c index 972d20c6d..bc40be067 100644 --- a/target/linux/generic-2.6/files/drivers/net/phy/adm6996.c +++ b/target/linux/generic-2.6/files/drivers/net/phy/adm6996.c @@ -96,7 +96,7 @@ static int adm6996_read_status(struct phy_device *phydev) { phydev->speed = SPEED_100; phydev->duplex = DUPLEX_FULL; - phydev->state = PHY_UP; + phydev->link = 1; return 0; } diff --git a/target/linux/generic-2.6/files/drivers/net/phy/ar8216.c b/target/linux/generic-2.6/files/drivers/net/phy/ar8216.c index 93e4b33d9..92cc9f384 100644 --- a/target/linux/generic-2.6/files/drivers/net/phy/ar8216.c +++ b/target/linux/generic-2.6/files/drivers/net/phy/ar8216.c @@ -546,7 +546,7 @@ ar8216_read_status(struct phy_device *phydev) phydev->speed = SPEED_100; phydev->duplex = DUPLEX_FULL; - phydev->state = PHY_UP; + phydev->link = 1; /* flush the address translation unit */ if (ar8216_wait_bit(priv, AR8216_REG_ATU, AR8216_ATU_ACTIVE, 0)) diff --git a/target/linux/generic-2.6/files/drivers/net/phy/mvswitch.c b/target/linux/generic-2.6/files/drivers/net/phy/mvswitch.c index 3ae8899c2..c2f324572 100644 --- a/target/linux/generic-2.6/files/drivers/net/phy/mvswitch.c +++ b/target/linux/generic-2.6/files/drivers/net/phy/mvswitch.c @@ -366,7 +366,7 @@ mvswitch_read_status(struct phy_device *pdev) { pdev->speed = SPEED_100; pdev->duplex = DUPLEX_FULL; - pdev->state = PHY_UP; + pdev->link = 1; /* XXX ugly workaround: we can't force the switch * to gracefully handle hosts moving from one port to another, diff --git a/target/linux/generic-2.6/files/drivers/net/phy/rtl8306.c b/target/linux/generic-2.6/files/drivers/net/phy/rtl8306.c index eba0babe2..901b5b2f8 100644 --- a/target/linux/generic-2.6/files/drivers/net/phy/rtl8306.c +++ b/target/linux/generic-2.6/files/drivers/net/phy/rtl8306.c @@ -46,18 +46,22 @@ #define RTL8306_MAGIC 0x8306 +static LIST_HEAD(phydevs); + struct rtl_priv { + struct list_head list; struct switch_dev dev; int page; int type; int do_cpu; struct mii_bus *bus; char hwname[sizeof(RTL_NAME_UNKNOWN)]; +}; - /* temporary register saves for port operations */ - int tmp_speed; - int tmp_nway; - int tmp_duplex; +struct rtl_phyregs { + int nway; + int speed; + int duplex; }; #define to_rtl(_dev) container_of(_dev, struct rtl_priv, dev) @@ -157,6 +161,7 @@ enum rtl_regidx { RTL_REG_PORT##id##_LINK, \ RTL_REG_PORT##id##_SPEED, \ RTL_REG_PORT##id##_NWAY, \ + RTL_REG_PORT##id##_NRESTART, \ RTL_REG_PORT##id##_DUPLEX, \ RTL_REG_PORT##id##_RXEN, \ RTL_REG_PORT##id##_TXEN @@ -217,6 +222,7 @@ static const struct rtl_reg rtl_regs[] = { #define REG_PORT_SETTING(port, phy) \ [RTL_REG_PORT##port##_SPEED] = { 0, phy, 0, 1, 13, 0 }, \ [RTL_REG_PORT##port##_NWAY] = { 0, phy, 0, 1, 12, 0 }, \ + [RTL_REG_PORT##port##_NRESTART] = { 0, phy, 0, 1, 9, 0 }, \ [RTL_REG_PORT##port##_DUPLEX] = { 0, phy, 0, 1, 8, 0 }, \ [RTL_REG_PORT##port##_TXEN] = { 0, phy, 24, 1, 11, 0 }, \ [RTL_REG_PORT##port##_RXEN] = { 0, phy, 24, 1, 10, 0 }, \ @@ -355,23 +361,19 @@ rtl_set(struct switch_dev *dev, enum rtl_regidx s, unsigned int val) } static void -rtl_phy_save(struct switch_dev *dev, int port) +rtl_phy_save(struct switch_dev *dev, int port, struct rtl_phyregs *regs) { - struct rtl_priv *priv = to_rtl(dev); - - priv->tmp_nway = rtl_get(dev, RTL_PORT_REG(port, NWAY)); - priv->tmp_speed = rtl_get(dev, RTL_PORT_REG(port, SPEED)); - priv->tmp_duplex = rtl_get(dev, RTL_PORT_REG(port, DUPLEX)); + regs->nway = rtl_get(dev, RTL_PORT_REG(port, NWAY)); + regs->speed = rtl_get(dev, RTL_PORT_REG(port, SPEED)); + regs->duplex = rtl_get(dev, RTL_PORT_REG(port, DUPLEX)); } static void -rtl_phy_restore(struct switch_dev *dev, int port) +rtl_phy_restore(struct switch_dev *dev, int port, struct rtl_phyregs *regs) { - struct rtl_priv *priv = to_rtl(dev); - - rtl_set(dev, RTL_PORT_REG(port, NWAY), priv->tmp_nway); - rtl_set(dev, RTL_PORT_REG(port, SPEED), priv->tmp_speed); - rtl_set(dev, RTL_PORT_REG(port, DUPLEX), priv->tmp_duplex); + rtl_set(dev, RTL_PORT_REG(port, NWAY), regs->nway); + rtl_set(dev, RTL_PORT_REG(port, SPEED), regs->speed); + rtl_set(dev, RTL_PORT_REG(port, DUPLEX), regs->duplex); } static void @@ -379,6 +381,12 @@ rtl_port_set_enable(struct switch_dev *dev, int port, int enabled) { rtl_set(dev, RTL_PORT_REG(port, RXEN), enabled); rtl_set(dev, RTL_PORT_REG(port, TXEN), enabled); + + if ((port >= 5) || !enabled) + return; + + /* restart autonegotiation if enabled */ + rtl_set(dev, RTL_PORT_REG(port, NRESTART), 1); } static int @@ -386,8 +394,9 @@ rtl_hw_apply(struct switch_dev *dev) { int i; int trunk_en, trunk_psel; + struct rtl_phyregs port5; - rtl_phy_save(dev, 5); + rtl_phy_save(dev, 5, &port5); /* disable rx/tx from PHYs */ for (i = 0; i < RTL8306_NUM_PORTS - 1; i++) { @@ -423,8 +432,7 @@ rtl_hw_apply(struct switch_dev *dev) /* restore trunking settings */ rtl_set(dev, RTL_REG_EN_TRUNK, trunk_en); rtl_set(dev, RTL_REG_TRUNK_PORTSEL, trunk_psel); - - rtl_phy_restore(dev, 5); + rtl_phy_restore(dev, 5, &port5); return 0; } @@ -522,6 +530,7 @@ static int rtl_attr_set_int(struct switch_dev *dev, const struct switch_attr *attr, struct switch_val *val) { int idx = attr->id + (val->port_vlan * attr->ofs); + struct rtl_phyregs port; if (attr->id >= ARRAY_SIZE(rtl_regs)) return -EINVAL; @@ -535,9 +544,9 @@ rtl_attr_set_int(struct switch_dev *dev, const struct switch_attr *attr, struct (rtl_regs[idx].reg == 22) && (rtl_regs[idx].page == 0)) { - rtl_phy_save(dev, val->port_vlan); + rtl_phy_save(dev, val->port_vlan, &port); rtl_set(dev, idx, val->value.i); - rtl_phy_restore(dev, val->port_vlan); + rtl_phy_restore(dev, val->port_vlan, &port); } else { rtl_set(dev, idx, val->value.i); } @@ -617,6 +626,7 @@ static int rtl_set_vlan(struct switch_dev *dev, const struct switch_attr *attr, struct switch_val *val) { struct rtl_priv *priv = to_rtl(dev); + struct rtl_phyregs port; int en = val->value.i; int i; @@ -629,12 +639,12 @@ rtl_set_vlan(struct switch_dev *dev, const struct switch_attr *attr, struct swit for (i = 0; i < RTL8306_NUM_PORTS; i++) { if (i > 3) - rtl_phy_save(dev, val->port_vlan); + rtl_phy_save(dev, val->port_vlan, &port); rtl_set(dev, RTL_PORT_REG(i, NULL_VID_REPLACE), 1); rtl_set(dev, RTL_PORT_REG(i, VID_INSERT), (en ? (i == dev->cpu_port ? 0 : 1) : 1)); rtl_set(dev, RTL_PORT_REG(i, TAG_INSERT), (en ? (i == dev->cpu_port ? 2 : 1) : 3)); if (i > 3) - rtl_phy_restore(dev, val->port_vlan); + rtl_phy_restore(dev, val->port_vlan, &port); } rtl_set(dev, RTL_REG_VLAN_ENABLE, en); @@ -706,6 +716,10 @@ rtl8306_config_init(struct phy_device *pdev) unsigned int chipid, chipver, chiptype; int err; + /* Only init the switch for the primary PHY */ + if (pdev->addr != 0) + return 0; + val.value.i = 1; memcpy(&priv->dev, &rtldev, sizeof(struct switch_dev)); priv->do_cpu = 0; @@ -913,6 +927,10 @@ rtl8306_fixup(struct phy_device *pdev) struct rtl_priv priv; u16 chipid; + /* Attach to primary LAN port and WAN port */ + if (pdev->addr != 0 && pdev->addr != 4) + return 0; + priv.page = -1; priv.bus = pdev->bus; chipid = rtl_get(&priv.dev, RTL_REG_CHIPID); @@ -927,10 +945,21 @@ rtl8306_probe(struct phy_device *pdev) { struct rtl_priv *priv; + list_for_each_entry(priv, &phydevs, list) { + /* + * share one rtl_priv instance between virtual phy + * devices on the same bus + */ + if (priv->bus == pdev->bus) + goto found; + } priv = kzalloc(sizeof(struct rtl_priv), GFP_KERNEL); if (!priv) return -ENOMEM; + priv->bus = pdev->bus; + +found: pdev->priv = priv; return 0; } @@ -946,15 +975,50 @@ rtl8306_remove(struct phy_device *pdev) static int rtl8306_config_aneg(struct phy_device *pdev) { + struct rtl_priv *priv = pdev->priv; + + /* Only for WAN */ + if (pdev->addr == 0) + return 0; + + /* Restart autonegotiation */ + rtl_set(&priv->dev, RTL_PORT_REG(4, NWAY), 1); + rtl_set(&priv->dev, RTL_PORT_REG(4, NRESTART), 1); + return 0; } static int rtl8306_read_status(struct phy_device *pdev) { - pdev->speed = SPEED_100; - pdev->duplex = DUPLEX_FULL; - pdev->state = PHY_UP; + struct rtl_priv *priv = pdev->priv; + struct switch_dev *dev = &priv->dev; + + if (pdev->addr == 4) { + /* WAN */ + pdev->speed = rtl_get(dev, RTL_PORT_REG(4, SPEED)) ? SPEED_100 : SPEED_10; + pdev->duplex = rtl_get(dev, RTL_PORT_REG(4, DUPLEX)) ? DUPLEX_FULL : DUPLEX_HALF; + pdev->link = !!rtl_get(dev, RTL_PORT_REG(4, LINK)); + } else { + /* LAN */ + pdev->speed = SPEED_100; + pdev->duplex = DUPLEX_FULL; + pdev->link = 1; + } + + /* + * Bypass generic PHY status read, + * it doesn't work with this switch + */ + if (pdev->link) { + pdev->state = PHY_RUNNING; + netif_carrier_on(pdev->attached_dev); + pdev->adjust_link(pdev->attached_dev); + } else { + pdev->state = PHY_NOLINK; + netif_carrier_off(pdev->attached_dev); + pdev->adjust_link(pdev->attached_dev); + } return 0; } @@ -962,6 +1026,7 @@ rtl8306_read_status(struct phy_device *pdev) static struct phy_driver rtl8306_driver = { .name = "Realtek RTL8306S", + .flags = PHY_HAS_MAGICANEG, .phy_id = RTL8306_MAGIC, .phy_id_mask = 0xffffffff, .features = PHY_BASIC_FEATURES, diff --git a/target/linux/generic-2.6/files-2.6.30/include/linux/glamo-engine.h b/target/linux/generic-2.6/files/include/linux/glamo-engine.h similarity index 100% rename from target/linux/generic-2.6/files-2.6.30/include/linux/glamo-engine.h rename to target/linux/generic-2.6/files/include/linux/glamo-engine.h diff --git a/target/linux/generic-2.6/files-2.6.30/include/linux/glamofb.h b/target/linux/generic-2.6/files/include/linux/glamofb.h similarity index 100% rename from target/linux/generic-2.6/files-2.6.30/include/linux/glamofb.h rename to target/linux/generic-2.6/files/include/linux/glamofb.h diff --git a/target/linux/generic-2.6/files-2.6.25/include/linux/gpio_buttons.h b/target/linux/generic-2.6/files/include/linux/gpio_buttons.h similarity index 100% rename from target/linux/generic-2.6/files-2.6.25/include/linux/gpio_buttons.h rename to target/linux/generic-2.6/files/include/linux/gpio_buttons.h diff --git a/target/linux/generic-2.6/files-2.6.25/include/linux/gpio_dev.h b/target/linux/generic-2.6/files/include/linux/gpio_dev.h similarity index 100% rename from target/linux/generic-2.6/files-2.6.25/include/linux/gpio_dev.h rename to target/linux/generic-2.6/files/include/linux/gpio_dev.h diff --git a/target/linux/generic-2.6/patches-2.6.25/200-sched_esfq.patch b/target/linux/generic-2.6/patches-2.6.25/200-sched_esfq.patch index a3c02625d..3f66e2c67 100644 --- a/target/linux/generic-2.6/patches-2.6.25/200-sched_esfq.patch +++ b/target/linux/generic-2.6/patches-2.6.25/200-sched_esfq.patch @@ -90,7 +90,7 @@ obj-$(CONFIG_NET_SCH_PRIO) += sch_prio.o --- /dev/null +++ b/net/sched/sch_esfq.c -@@ -0,0 +1,702 @@ +@@ -0,0 +1,704 @@ +/* + * net/sched/sch_esfq.c Extended Stochastic Fairness Queueing discipline. + * @@ -143,7 +143,9 @@ +#include +#include +#include ++#ifdef CONFIG_NET_SCH_ESFQ_NFCT +#include ++#endif + +/* Stochastic Fairness Queuing algorithm. + For more comments look at sch_sfq.c. diff --git a/target/linux/generic-2.6/patches-2.6.28/001-squashfs.patch b/target/linux/generic-2.6/patches-2.6.28/001-squashfs.patch deleted file mode 100644 index 606f150e1..000000000 --- a/target/linux/generic-2.6/patches-2.6.28/001-squashfs.patch +++ /dev/null @@ -1,4170 +0,0 @@ ---- a/fs/Kconfig -+++ b/fs/Kconfig -@@ -931,6 +931,71 @@ config CRAMFS - - If unsure, say N. - -+config SQUASHFS -+ tristate "SquashFS 3.0 - Squashed file system support" -+ select ZLIB_INFLATE -+ help -+ Saying Y here includes support for SquashFS 3.0 (a Compressed Read-Only File -+ System). Squashfs is a highly compressed read-only filesystem for Linux. -+ It uses zlib compression to compress both files, inodes and directories. -+ Inodes in the system are very small and all blocks are packed to minimise -+ data overhead. Block sizes greater than 4K are supported up to a maximum of 64K. -+ SquashFS 3.0 supports 64 bit filesystems and files (larger than 4GB), full -+ uid/gid information, hard links and timestamps. -+ -+ Squashfs is intended for general read-only filesystem use, for archival -+ use (i.e. in cases where a .tar.gz file may be used), and in embedded -+ systems where low overhead is needed. Further information and filesystem tools -+ are available from http://squashfs.sourceforge.net. -+ -+ If you want to compile this as a module ( = code which can be -+ inserted in and removed from the running kernel whenever you want), -+ say M here and read . The module -+ will be called squashfs. Note that the root file system (the one -+ containing the directory /) cannot be compiled as a module. -+ -+ If unsure, say N. -+ -+config SQUASHFS_EMBEDDED -+ -+ bool "Additional options for memory-constrained systems" -+ depends on SQUASHFS -+ default n -+ help -+ Saying Y here allows you to specify cache sizes and how Squashfs -+ allocates memory. This is only intended for memory constrained -+ systems. -+ -+ If unsure, say N. -+ -+config SQUASHFS_FRAGMENT_CACHE_SIZE -+ int "Number of fragments cached" if SQUASHFS_EMBEDDED -+ depends on SQUASHFS -+ default "3" -+ help -+ By default SquashFS caches the last 3 fragments read from -+ the filesystem. Increasing this amount may mean SquashFS -+ has to re-read fragments less often from disk, at the expense -+ of extra system memory. Decreasing this amount will mean -+ SquashFS uses less memory at the expense of extra reads from disk. -+ -+ Note there must be at least one cached fragment. Anything -+ much more than three will probably not make much difference. -+ -+config SQUASHFS_VMALLOC -+ bool "Use Vmalloc rather than Kmalloc" if SQUASHFS_EMBEDDED -+ depends on SQUASHFS -+ default n -+ help -+ By default SquashFS uses kmalloc to obtain fragment cache memory. -+ Kmalloc memory is the standard kernel allocator, but it can fail -+ on memory constrained systems. Because of the way Vmalloc works, -+ Vmalloc can succeed when kmalloc fails. Specifying this option -+ will make SquashFS always use Vmalloc to allocate the -+ fragment cache memory. -+ -+ If unsure, say N. -+ - config VXFS_FS - tristate "FreeVxFS file system support (VERITAS VxFS(TM) compatible)" - depends on BLOCK ---- a/fs/Makefile -+++ b/fs/Makefile -@@ -76,6 +76,7 @@ obj-$(CONFIG_JBD) += jbd/ - obj-$(CONFIG_JBD2) += jbd2/ - obj-$(CONFIG_EXT2_FS) += ext2/ - obj-$(CONFIG_CRAMFS) += cramfs/ -+obj-$(CONFIG_SQUASHFS) += squashfs/ - obj-y += ramfs/ - obj-$(CONFIG_HUGETLBFS) += hugetlbfs/ - obj-$(CONFIG_CODA_FS) += coda/ ---- /dev/null -+++ b/fs/squashfs/inode.c -@@ -0,0 +1,2122 @@ -+/* -+ * Squashfs - a compressed read only filesystem for Linux -+ * -+ * Copyright (c) 2002, 2003, 2004, 2005, 2006 -+ * Phillip Lougher -+ * -+ * 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, -+ * 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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -+ * -+ * inode.c -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "squashfs.h" -+ -+static void squashfs_put_super(struct super_block *); -+static int squashfs_statfs(struct dentry *, struct kstatfs *); -+static int squashfs_symlink_readpage(struct file *file, struct page *page); -+static int squashfs_readpage(struct file *file, struct page *page); -+static int squashfs_readpage4K(struct file *file, struct page *page); -+static int squashfs_readdir(struct file *, void *, filldir_t); -+static struct inode *squashfs_alloc_inode(struct super_block *sb); -+static void squashfs_destroy_inode(struct inode *inode); -+static int init_inodecache(void); -+static void destroy_inodecache(void); -+static struct dentry *squashfs_lookup(struct inode *, struct dentry *, -+ struct nameidata *); -+static struct inode *squashfs_iget(struct super_block *s, squashfs_inode_t inode); -+static long long read_blocklist(struct inode *inode, int index, -+ int readahead_blks, char *block_list, -+ unsigned short **block_p, unsigned int *bsize); -+static int squashfs_get_sb(struct file_system_type *, int, -+ const char *, void *, struct vfsmount *); -+ -+ -+static z_stream stream; -+ -+static struct file_system_type squashfs_fs_type = { -+ .owner = THIS_MODULE, -+ .name = "squashfs", -+ .get_sb = squashfs_get_sb, -+ .kill_sb = kill_block_super, -+ .fs_flags = FS_REQUIRES_DEV -+}; -+ -+static unsigned char squashfs_filetype_table[] = { -+ DT_UNKNOWN, DT_DIR, DT_REG, DT_LNK, DT_BLK, DT_CHR, DT_FIFO, DT_SOCK -+}; -+ -+static struct super_operations squashfs_ops = { -+ .alloc_inode = squashfs_alloc_inode, -+ .destroy_inode = squashfs_destroy_inode, -+ .statfs = squashfs_statfs, -+ .put_super = squashfs_put_super, -+}; -+ -+SQSH_EXTERN struct address_space_operations squashfs_symlink_aops = { -+ .readpage = squashfs_symlink_readpage -+}; -+ -+SQSH_EXTERN struct address_space_operations squashfs_aops = { -+ .readpage = squashfs_readpage -+}; -+ -+SQSH_EXTERN struct address_space_operations squashfs_aops_4K = { -+ .readpage = squashfs_readpage4K -+}; -+ -+static struct file_operations squashfs_dir_ops = { -+ .read = generic_read_dir, -+ .readdir = squashfs_readdir -+}; -+ -+SQSH_EXTERN struct inode_operations squashfs_dir_inode_ops = { -+ .lookup = squashfs_lookup -+}; -+ -+ -+static struct buffer_head *get_block_length(struct super_block *s, -+ int *cur_index, int *offset, int *c_byte) -+{ -+ struct squashfs_sb_info *msblk = s->s_fs_info; -+ unsigned short temp; -+ struct buffer_head *bh; -+ -+ if (!(bh = sb_bread(s, *cur_index))) -+ goto out; -+ -+ if (msblk->devblksize - *offset == 1) { -+ if (msblk->swap) -+ ((unsigned char *) &temp)[1] = *((unsigned char *) -+ (bh->b_data + *offset)); -+ else -+ ((unsigned char *) &temp)[0] = *((unsigned char *) -+ (bh->b_data + *offset)); -+ brelse(bh); -+ if (!(bh = sb_bread(s, ++(*cur_index)))) -+ goto out; -+ if (msblk->swap) -+ ((unsigned char *) &temp)[0] = *((unsigned char *) -+ bh->b_data); -+ else -+ ((unsigned char *) &temp)[1] = *((unsigned char *) -+ bh->b_data); -+ *c_byte = temp; -+ *offset = 1; -+ } else { -+ if (msblk->swap) { -+ ((unsigned char *) &temp)[1] = *((unsigned char *) -+ (bh->b_data + *offset)); -+ ((unsigned char *) &temp)[0] = *((unsigned char *) -+ (bh->b_data + *offset + 1)); -+ } else { -+ ((unsigned char *) &temp)[0] = *((unsigned char *) -+ (bh->b_data + *offset)); -+ ((unsigned char *) &temp)[1] = *((unsigned char *) -+ (bh->b_data + *offset + 1)); -+ } -+ *c_byte = temp; -+ *offset += 2; -+ } -+ -+ if (SQUASHFS_CHECK_DATA(msblk->sblk.flags)) { -+ if (*offset == msblk->devblksize) { -+ brelse(bh); -+ if (!(bh = sb_bread(s, ++(*cur_index)))) -+ goto out; -+ *offset = 0; -+ } -+ if (*((unsigned char *) (bh->b_data + *offset)) != -+ SQUASHFS_MARKER_BYTE) { -+ ERROR("Metadata block marker corrupt @ %x\n", -+ *cur_index); -+ brelse(bh); -+ goto out; -+ } -+ (*offset)++; -+ } -+ return bh; -+ -+out: -+ return NULL; -+} -+ -+ -+SQSH_EXTERN unsigned int squashfs_read_data(struct super_block *s, char *buffer, -+ long long index, unsigned int length, -+ long long *next_index) -+{ -+ struct squashfs_sb_info *msblk = s->s_fs_info; -+ struct buffer_head *bh[((SQUASHFS_FILE_MAX_SIZE - 1) >> -+ msblk->devblksize_log2) + 2]; -+ unsigned int offset = index & ((1 << msblk->devblksize_log2) - 1); -+ unsigned int cur_index = index >> msblk->devblksize_log2; -+ int bytes, avail_bytes, b = 0, k; -+ char *c_buffer; -+ unsigned int compressed; -+ unsigned int c_byte = length; -+ -+ if (c_byte) { -+ bytes = msblk->devblksize - offset; -+ compressed = SQUASHFS_COMPRESSED_BLOCK(c_byte); -+ c_buffer = compressed ? msblk->read_data : buffer; -+ c_byte = SQUASHFS_COMPRESSED_SIZE_BLOCK(c_byte); -+ -+ TRACE("Block @ 0x%llx, %scompressed size %d\n", index, compressed -+ ? "" : "un", (unsigned int) c_byte); -+ -+ if (!(bh[0] = sb_getblk(s, cur_index))) -+ goto block_release; -+ -+ for (b = 1; bytes < c_byte; b++) { -+ if (!(bh[b] = sb_getblk(s, ++cur_index))) -+ goto block_release; -+ bytes += msblk->devblksize; -+ } -+ ll_rw_block(READ, b, bh); -+ } else { -+ if (!(bh[0] = get_block_length(s, &cur_index, &offset, -+ &c_byte))) -+ goto read_failure; -+ -+ bytes = msblk->devblksize - offset; -+ compressed = SQUASHFS_COMPRESSED(c_byte); -+ c_buffer = compressed ? msblk->read_data : buffer; -+ c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte); -+ -+ TRACE("Block @ 0x%llx, %scompressed size %d\n", index, compressed -+ ? "" : "un", (unsigned int) c_byte); -+ -+ for (b = 1; bytes < c_byte; b++) { -+ if (!(bh[b] = sb_getblk(s, ++cur_index))) -+ goto block_release; -+ bytes += msblk->devblksize; -+ } -+ ll_rw_block(READ, b - 1, bh + 1); -+ } -+ -+ if (compressed) -+ down(&msblk->read_data_mutex); -+ -+ for (bytes = 0, k = 0; k < b; k++) { -+ avail_bytes = (c_byte - bytes) > (msblk->devblksize - offset) ? -+ msblk->devblksize - offset : -+ c_byte - bytes; -+ wait_on_buffer(bh[k]); -+ if (!buffer_uptodate(bh[k])) -+ goto block_release; -+ memcpy(c_buffer + bytes, bh[k]->b_data + offset, avail_bytes); -+ bytes += avail_bytes; -+ offset = 0; -+ brelse(bh[k]); -+ } -+ -+ /* -+ * uncompress block -+ */ -+ if (compressed) { -+ int zlib_err; -+ -+ stream.next_in = c_buffer; -+ stream.avail_in = c_byte; -+ stream.next_out = buffer; -+ stream.avail_out = msblk->read_size; -+ -+ if (((zlib_err = zlib_inflateInit(&stream)) != Z_OK) || -+ ((zlib_err = zlib_inflate(&stream, Z_FINISH)) -+ != Z_STREAM_END) || ((zlib_err = -+ zlib_inflateEnd(&stream)) != Z_OK)) { -+ ERROR("zlib_fs returned unexpected result 0x%x\n", -+ zlib_err); -+ bytes = 0; -+ } else -+ bytes = stream.total_out; -+ -+ up(&msblk->read_data_mutex); -+ } -+ -+ if (next_index) -+ *next_index = index + c_byte + (length ? 0 : -+ (SQUASHFS_CHECK_DATA(msblk->sblk.flags) -+ ? 3 : 2)); -+ return bytes; -+ -+block_release: -+ while (--b >= 0) -+ brelse(bh[b]); -+ -+read_failure: -+ ERROR("sb_bread failed reading block 0x%x\n", cur_index); -+ return 0; -+} -+ -+ -+SQSH_EXTERN int squashfs_get_cached_block(struct super_block *s, char *buffer, -+ long long block, unsigned int offset, -+ int length, long long *next_block, -+ unsigned int *next_offset) -+{ -+ struct squashfs_sb_info *msblk = s->s_fs_info; -+ int n, i, bytes, return_length = length; -+ long long next_index; -+ -+ TRACE("Entered squashfs_get_cached_block [%llx:%x]\n", block, offset); -+ -+ while ( 1 ) { -+ for (i = 0; i < SQUASHFS_CACHED_BLKS; i++) -+ if (msblk->block_cache[i].block == block) -+ break; -+ -+ down(&msblk->block_cache_mutex); -+ -+ if (i == SQUASHFS_CACHED_BLKS) { -+ /* read inode header block */ -+ for (i = msblk->next_cache, n = SQUASHFS_CACHED_BLKS; -+ n ; n --, i = (i + 1) % -+ SQUASHFS_CACHED_BLKS) -+ if (msblk->block_cache[i].block != -+ SQUASHFS_USED_BLK) -+ break; -+ -+ if (n == 0) { -+ wait_queue_t wait; -+ -+ init_waitqueue_entry(&wait, current); -+ add_wait_queue(&msblk->waitq, &wait); -+ set_current_state(TASK_UNINTERRUPTIBLE); -+ up(&msblk->block_cache_mutex); -+ schedule(); -+ set_current_state(TASK_RUNNING); -+ remove_wait_queue(&msblk->waitq, &wait); -+ continue; -+ } -+ msblk->next_cache = (i + 1) % SQUASHFS_CACHED_BLKS; -+ -+ if (msblk->block_cache[i].block == -+ SQUASHFS_INVALID_BLK) { -+ if (!(msblk->block_cache[i].data = -+ kmalloc(SQUASHFS_METADATA_SIZE, -+ GFP_KERNEL))) { -+ ERROR("Failed to allocate cache" -+ "block\n"); -+ up(&msblk->block_cache_mutex); -+ goto out; -+ } -+ } -+ -+ msblk->block_cache[i].block = SQUASHFS_USED_BLK; -+ up(&msblk->block_cache_mutex); -+ -+ if (!(msblk->block_cache[i].length = -+ squashfs_read_data(s, -+ msblk->block_cache[i].data, -+ block, 0, &next_index))) { -+ ERROR("Unable to read cache block [%llx:%x]\n", -+ block, offset); -+ goto out; -+ } -+ -+ down(&msblk->block_cache_mutex); -+ wake_up(&msblk->waitq); -+ msblk->block_cache[i].block = block; -+ msblk->block_cache[i].next_index = next_index; -+ TRACE("Read cache block [%llx:%x]\n", block, offset); -+ } -+ -+ if (msblk->block_cache[i].block != block) { -+ up(&msblk->block_cache_mutex); -+ continue; -+ } -+ -+ if ((bytes = msblk->block_cache[i].length - offset) >= length) { -+ if (buffer) -+ memcpy(buffer, msblk->block_cache[i].data + -+ offset, length); -+ if (msblk->block_cache[i].length - offset == length) { -+ *next_block = msblk->block_cache[i].next_index; -+ *next_offset = 0; -+ } else { -+ *next_block = block; -+ *next_offset = offset + length; -+ } -+ up(&msblk->block_cache_mutex); -+ goto finish; -+ } else { -+ if (buffer) { -+ memcpy(buffer, msblk->block_cache[i].data + -+ offset, bytes); -+ buffer += bytes; -+ } -+ block = msblk->block_cache[i].next_index; -+ up(&msblk->block_cache_mutex); -+ length -= bytes; -+ offset = 0; -+ } -+ } -+ -+finish: -+ return return_length; -+out: -+ return 0; -+} -+ -+ -+static int get_fragment_location(struct super_block *s, unsigned int fragment, -+ long long *fragment_start_block, -+ unsigned int *fragment_size) -+{ -+ struct squashfs_sb_info *msblk = s->s_fs_info; -+ long long start_block = -+ msblk->fragment_index[SQUASHFS_FRAGMENT_INDEX(fragment)]; -+ int offset = SQUASHFS_FRAGMENT_INDEX_OFFSET(fragment); -+ struct squashfs_fragment_entry fragment_entry; -+ -+ if (msblk->swap) { -+ struct squashfs_fragment_entry sfragment_entry; -+ -+ if (!squashfs_get_cached_block(s, (char *) &sfragment_entry, -+ start_block, offset, -+ sizeof(sfragment_entry), &start_block, -+ &offset)) -+ goto out; -+ SQUASHFS_SWAP_FRAGMENT_ENTRY(&fragment_entry, &sfragment_entry); -+ } else -+ if (!squashfs_get_cached_block(s, (char *) &fragment_entry, -+ start_block, offset, -+ sizeof(fragment_entry), &start_block, -+ &offset)) -+ goto out; -+ -+ *fragment_start_block = fragment_entry.start_block; -+ *fragment_size = fragment_entry.size; -+ -+ return 1; -+ -+out: -+ return 0; -+} -+ -+ -+SQSH_EXTERN void release_cached_fragment(struct squashfs_sb_info *msblk, struct -+ squashfs_fragment_cache *fragment) -+{ -+ down(&msblk->fragment_mutex); -+ fragment->locked --; -+ wake_up(&msblk->fragment_wait_queue); -+ up(&msblk->fragment_mutex); -+} -+ -+ -+SQSH_EXTERN struct squashfs_fragment_cache *get_cached_fragment(struct super_block -+ *s, long long start_block, -+ int length) -+{ -+ int i, n; -+ struct squashfs_sb_info *msblk = s->s_fs_info; -+ -+ while ( 1 ) { -+ down(&msblk->fragment_mutex); -+ -+ for (i = 0; i < SQUASHFS_CACHED_FRAGMENTS && -+ msblk->fragment[i].block != start_block; i++); -+ -+ if (i == SQUASHFS_CACHED_FRAGMENTS) { -+ for (i = msblk->next_fragment, n = -+ SQUASHFS_CACHED_FRAGMENTS; n && -+ msblk->fragment[i].locked; n--, i = (i + 1) % -+ SQUASHFS_CACHED_FRAGMENTS); -+ -+ if (n == 0) { -+ wait_queue_t wait; -+ -+ init_waitqueue_entry(&wait, current); -+ add_wait_queue(&msblk->fragment_wait_queue, -+ &wait); -+ set_current_state(TASK_UNINTERRUPTIBLE); -+ up(&msblk->fragment_mutex); -+ schedule(); -+ set_current_state(TASK_RUNNING); -+ remove_wait_queue(&msblk->fragment_wait_queue, -+ &wait); -+ continue; -+ } -+ msblk->next_fragment = (msblk->next_fragment + 1) % -+ SQUASHFS_CACHED_FRAGMENTS; -+ -+ if (msblk->fragment[i].data == NULL) -+ if (!(msblk->fragment[i].data = SQUASHFS_ALLOC -+ (SQUASHFS_FILE_MAX_SIZE))) { -+ ERROR("Failed to allocate fragment " -+ "cache block\n"); -+ up(&msblk->fragment_mutex); -+ goto out; -+ } -+ -+ msblk->fragment[i].block = SQUASHFS_INVALID_BLK; -+ msblk->fragment[i].locked = 1; -+ up(&msblk->fragment_mutex); -+ -+ if (!(msblk->fragment[i].length = squashfs_read_data(s, -+ msblk->fragment[i].data, -+ start_block, length, NULL))) { -+ ERROR("Unable to read fragment cache block " -+ "[%llx]\n", start_block); -+ msblk->fragment[i].locked = 0; -+ goto out; -+ } -+ -+ msblk->fragment[i].block = start_block; -+ TRACE("New fragment %d, start block %lld, locked %d\n", -+ i, msblk->fragment[i].block, -+ msblk->fragment[i].locked); -+ break; -+ } -+ -+ msblk->fragment[i].locked++; -+ up(&msblk->fragment_mutex); -+ TRACE("Got fragment %d, start block %lld, locked %d\n", i, -+ msblk->fragment[i].block, -+ msblk->fragment[i].locked); -+ break; -+ } -+ -+ return &msblk->fragment[i]; -+ -+out: -+ return NULL; -+} -+ -+ -+static struct inode *squashfs_new_inode(struct super_block *s, -+ struct squashfs_base_inode_header *inodeb) -+{ -+ struct squashfs_sb_info *msblk = s->s_fs_info; -+ struct inode *i = new_inode(s); -+ -+ if (i) { -+ i->i_ino = inodeb->inode_number; -+ i->i_mtime.tv_sec = inodeb->mtime; -+ i->i_atime.tv_sec = inodeb->mtime; -+ i->i_ctime.tv_sec = inodeb->mtime; -+ i->i_uid = msblk->uid[inodeb->uid]; -+ i->i_mode = inodeb->mode; -+ i->i_size = 0; -+ if (inodeb->guid == SQUASHFS_GUIDS) -+ i->i_gid = i->i_uid; -+ else -+ i->i_gid = msblk->guid[inodeb->guid]; -+ } -+ -+ return i; -+} -+ -+ -+static struct inode *squashfs_iget(struct super_block *s, squashfs_inode_t inode) -+{ -+ struct inode *i; -+ struct squashfs_sb_info *msblk = s->s_fs_info; -+ struct squashfs_super_block *sblk = &msblk->sblk; -+ long long block = SQUASHFS_INODE_BLK(inode) + -+ sblk->inode_table_start; -+ unsigned int offset = SQUASHFS_INODE_OFFSET(inode); -+ long long next_block; -+ unsigned int next_offset; -+ union squashfs_inode_header id, sid; -+ struct squashfs_base_inode_header *inodeb = &id.base, -+ *sinodeb = &sid.base; -+ -+ TRACE("Entered squashfs_iget\n"); -+ -+ if (msblk->swap) { -+ if (!squashfs_get_cached_block(s, (char *) sinodeb, block, -+ offset, sizeof(*sinodeb), &next_block, -+ &next_offset)) -+ goto failed_read; -+ SQUASHFS_SWAP_BASE_INODE_HEADER(inodeb, sinodeb, -+ sizeof(*sinodeb)); -+ } else -+ if (!squashfs_get_cached_block(s, (char *) inodeb, block, -+ offset, sizeof(*inodeb), &next_block, -+ &next_offset)) -+ goto failed_read; -+ -+ switch(inodeb->inode_type) { -+ case SQUASHFS_FILE_TYPE: { -+ unsigned int frag_size; -+ long long frag_blk; -+ struct squashfs_reg_inode_header *inodep = &id.reg; -+ struct squashfs_reg_inode_header *sinodep = &sid.reg; -+ -+ if (msblk->swap) { -+ if (!squashfs_get_cached_block(s, (char *) -+ sinodep, block, offset, -+ sizeof(*sinodep), &next_block, -+ &next_offset)) -+ goto failed_read; -+ SQUASHFS_SWAP_REG_INODE_HEADER(inodep, sinodep); -+ } else -+ if (!squashfs_get_cached_block(s, (char *) -+ inodep, block, offset, -+ sizeof(*inodep), &next_block, -+ &next_offset)) -+ goto failed_read; -+ -+ frag_blk = SQUASHFS_INVALID_BLK; -+ if (inodep->fragment != SQUASHFS_INVALID_FRAG && -+ !get_fragment_location(s, -+ inodep->fragment, &frag_blk, &frag_size)) -+ goto failed_read; -+ -+ if((i = squashfs_new_inode(s, inodeb)) == NULL) -+ goto failed_read1; -+ -+ i->i_nlink = 1; -+ i->i_size = inodep->file_size; -+ i->i_fop = &generic_ro_fops; -+ i->i_mode |= S_IFREG; -+ i->i_blocks = ((i->i_size - 1) >> 9) + 1; -+ SQUASHFS_I(i)->u.s1.fragment_start_block = frag_blk; -+ SQUASHFS_I(i)->u.s1.fragment_size = frag_size; -+ SQUASHFS_I(i)->u.s1.fragment_offset = inodep->offset; -+ SQUASHFS_I(i)->start_block = inodep->start_block; -+ SQUASHFS_I(i)->u.s1.block_list_start = next_block; -+ SQUASHFS_I(i)->offset = next_offset; -+ if (sblk->block_size > 4096) -+ i->i_data.a_ops = &squashfs_aops; -+ else -+ i->i_data.a_ops = &squashfs_aops_4K; -+ -+ TRACE("File inode %x:%x, start_block %llx, " -+ "block_list_start %llx, offset %x\n", -+ SQUASHFS_INODE_BLK(inode), offset, -+ inodep->start_block, next_block, -+ next_offset); -+ break; -+ } -+ case SQUASHFS_LREG_TYPE: { -+ unsigned int frag_size; -+ long long frag_blk; -+ struct squashfs_lreg_inode_header *inodep = &id.lreg; -+ struct squashfs_lreg_inode_header *sinodep = &sid.lreg; -+ -+ if (msblk->swap) { -+ if (!squashfs_get_cached_block(s, (char *) -+ sinodep, block, offset, -+ sizeof(*sinodep), &next_block, -+ &next_offset)) -+ goto failed_read; -+ SQUASHFS_SWAP_LREG_INODE_HEADER(inodep, sinodep); -+ } else -+ if (!squashfs_get_cached_block(s, (char *) -+ inodep, block, offset, -+ sizeof(*inodep), &next_block, -+ &next_offset)) -+ goto failed_read; -+ -+ frag_blk = SQUASHFS_INVALID_BLK; -+ if (inodep->fragment != SQUASHFS_INVALID_FRAG && -+ !get_fragment_location(s, -+ inodep->fragment, &frag_blk, &frag_size)) -+ goto failed_read; -+ -+ if((i = squashfs_new_inode(s, inodeb)) == NULL) -+ goto failed_read1; -+ -+ i->i_nlink = inodep->nlink; -+ i->i_size = inodep->file_size; -+ i->i_fop = &generic_ro_fops; -+ i->i_mode |= S_IFREG; -+ i->i_blocks = ((i->i_size - 1) >> 9) + 1; -+ SQUASHFS_I(i)->u.s1.fragment_start_block = frag_blk; -+ SQUASHFS_I(i)->u.s1.fragment_size = frag_size; -+ SQUASHFS_I(i)->u.s1.fragment_offset = inodep->offset; -+ SQUASHFS_I(i)->start_block = inodep->start_block; -+ SQUASHFS_I(i)->u.s1.block_list_start = next_block; -+ SQUASHFS_I(i)->offset = next_offset; -+ if (sblk->block_size > 4096) -+ i->i_data.a_ops = &squashfs_aops; -+ else -+ i->i_data.a_ops = &squashfs_aops_4K; -+ -+ TRACE("File inode %x:%x, start_block %llx, " -+ "block_list_start %llx, offset %x\n", -+ SQUASHFS_INODE_BLK(inode), offset, -+ inodep->start_block, next_block, -+ next_offset); -+ break; -+ } -+ case SQUASHFS_DIR_TYPE: { -+ struct squashfs_dir_inode_header *inodep = &id.dir; -+ struct squashfs_dir_inode_header *sinodep = &sid.dir; -+ -+ if (msblk->swap) { -+ if (!squashfs_get_cached_block(s, (char *) -+ sinodep, block, offset, -+ sizeof(*sinodep), &next_block, -+ &next_offset)) -+ goto failed_read; -+ SQUASHFS_SWAP_DIR_INODE_HEADER(inodep, sinodep); -+ } else -+ if (!squashfs_get_cached_block(s, (char *) -+ inodep, block, offset, -+ sizeof(*inodep), &next_block, -+ &next_offset)) -+ goto failed_read; -+ -+ if((i = squashfs_new_inode(s, inodeb)) == NULL) -+ goto failed_read1; -+ -+ i->i_nlink = inodep->nlink; -+ i->i_size = inodep->file_size; -+ i->i_op = &squashfs_dir_inode_ops; -+ i->i_fop = &squashfs_dir_ops; -+ i->i_mode |= S_IFDIR; -+ SQUASHFS_I(i)->start_block = inodep->start_block; -+ SQUASHFS_I(i)->offset = inodep->offset; -+ SQUASHFS_I(i)->u.s2.directory_index_count = 0; -+ SQUASHFS_I(i)->u.s2.parent_inode = inodep->parent_inode; -+ -+ TRACE("Directory inode %x:%x, start_block %x, offset " -+ "%x\n", SQUASHFS_INODE_BLK(inode), -+ offset, inodep->start_block, -+ inodep->offset); -+ break; -+ } -+ case SQUASHFS_LDIR_TYPE: { -+ struct squashfs_ldir_inode_header *inodep = &id.ldir; -+ struct squashfs_ldir_inode_header *sinodep = &sid.ldir; -+ -+ if (msblk->swap) { -+ if (!squashfs_get_cached_block(s, (char *) -+ sinodep, block, offset, -+ sizeof(*sinodep), &next_block, -+ &next_offset)) -+ goto failed_read; -+ SQUASHFS_SWAP_LDIR_INODE_HEADER(inodep, -+ sinodep); -+ } else -+ if (!squashfs_get_cached_block(s, (char *) -+ inodep, block, offset, -+ sizeof(*inodep), &next_block, -+ &next_offset)) -+ goto failed_read; -+ -+ if((i = squashfs_new_inode(s, inodeb)) == NULL) -+ goto failed_read1; -+ -+ i->i_nlink = inodep->nlink; -+ i->i_size = inodep->file_size; -+ i->i_op = &squashfs_dir_inode_ops; -+ i->i_fop = &squashfs_dir_ops; -+ i->i_mode |= S_IFDIR; -+ SQUASHFS_I(i)->start_block = inodep->start_block; -+ SQUASHFS_I(i)->offset = inodep->offset; -+ SQUASHFS_I(i)->u.s2.directory_index_start = next_block; -+ SQUASHFS_I(i)->u.s2.directory_index_offset = -+ next_offset; -+ SQUASHFS_I(i)->u.s2.directory_index_count = -+ inodep->i_count; -+ SQUASHFS_I(i)->u.s2.parent_inode = inodep->parent_inode; -+ -+ TRACE("Long directory inode %x:%x, start_block %x, " -+ "offset %x\n", -+ SQUASHFS_INODE_BLK(inode), offset, -+ inodep->start_block, inodep->offset); -+ break; -+ } -+ case SQUASHFS_SYMLINK_TYPE: { -+ struct squashfs_symlink_inode_header *inodep = -+ &id.symlink; -+ struct squashfs_symlink_inode_header *sinodep = -+ &sid.symlink; -+ -+ if (msblk->swap) { -+ if (!squashfs_get_cached_block(s, (char *) -+ sinodep, block, offset, -+ sizeof(*sinodep), &next_block, -+ &next_offset)) -+ goto failed_read; -+ SQUASHFS_SWAP_SYMLINK_INODE_HEADER(inodep, -+ sinodep); -+ } else -+ if (!squashfs_get_cached_block(s, (char *) -+ inodep, block, offset, -+ sizeof(*inodep), &next_block, -+ &next_offset)) -+ goto failed_read; -+ -+ if((i = squashfs_new_inode(s, inodeb)) == NULL) -+ goto failed_read1; -+ -+ i->i_nlink = inodep->nlink; -+ i->i_size = inodep->symlink_size; -+ i->i_op = &page_symlink_inode_operations; -+ i->i_data.a_ops = &squashfs_symlink_aops; -+ i->i_mode |= S_IFLNK; -+ SQUASHFS_I(i)->start_block = next_block; -+ SQUASHFS_I(i)->offset = next_offset; -+ -+ TRACE("Symbolic link inode %x:%x, start_block %llx, " -+ "offset %x\n", -+ SQUASHFS_INODE_BLK(inode), offset, -+ next_block, next_offset); -+ break; -+ } -+ case SQUASHFS_BLKDEV_TYPE: -+ case SQUASHFS_CHRDEV_TYPE: { -+ struct squashfs_dev_inode_header *inodep = &id.dev; -+ struct squashfs_dev_inode_header *sinodep = &sid.dev; -+ -+ if (msblk->swap) { -+ if (!squashfs_get_cached_block(s, (char *) -+ sinodep, block, offset, -+ sizeof(*sinodep), &next_block, -+ &next_offset)) -+ goto failed_read; -+ SQUASHFS_SWAP_DEV_INODE_HEADER(inodep, sinodep); -+ } else -+ if (!squashfs_get_cached_block(s, (char *) -+ inodep, block, offset, -+ sizeof(*inodep), &next_block, -+ &next_offset)) -+ goto failed_read; -+ -+ if ((i = squashfs_new_inode(s, inodeb)) == NULL) -+ goto failed_read1; -+ -+ i->i_nlink = inodep->nlink; -+ i->i_mode |= (inodeb->inode_type == -+ SQUASHFS_CHRDEV_TYPE) ? S_IFCHR : -+ S_IFBLK; -+ init_special_inode(i, i->i_mode, -+ old_decode_dev(inodep->rdev)); -+ -+ TRACE("Device inode %x:%x, rdev %x\n", -+ SQUASHFS_INODE_BLK(inode), offset, -+ inodep->rdev); -+ break; -+ } -+ case SQUASHFS_FIFO_TYPE: -+ case SQUASHFS_SOCKET_TYPE: { -+ struct squashfs_ipc_inode_header *inodep = &id.ipc; -+ struct squashfs_ipc_inode_header *sinodep = &sid.ipc; -+ -+ if (msblk->swap) { -+ if (!squashfs_get_cached_block(s, (char *) -+ sinodep, block, offset, -+ sizeof(*sinodep), &next_block, -+ &next_offset)) -+ goto failed_read; -+ SQUASHFS_SWAP_IPC_INODE_HEADER(inodep, sinodep); -+ } else -+ if (!squashfs_get_cached_block(s, (char *) -+ inodep, block, offset, -+ sizeof(*inodep), &next_block, -+ &next_offset)) -+ goto failed_read; -+ -+ if ((i = squashfs_new_inode(s, inodeb)) == NULL) -+ goto failed_read1; -+ -+ i->i_nlink = inodep->nlink; -+ i->i_mode |= (inodeb->inode_type == SQUASHFS_FIFO_TYPE) -+ ? S_IFIFO : S_IFSOCK; -+ init_special_inode(i, i->i_mode, 0); -+ break; -+ } -+ default: -+ ERROR("Unknown inode type %d in squashfs_iget!\n", -+ inodeb->inode_type); -+ goto failed_read1; -+ } -+ -+ insert_inode_hash(i); -+ return i; -+ -+failed_read: -+ ERROR("Unable to read inode [%llx:%x]\n", block, offset); -+ -+failed_read1: -+ return NULL; -+} -+ -+ -+static int read_fragment_index_table(struct super_block *s) -+{ -+ struct squashfs_sb_info *msblk = s->s_fs_info; -+ struct squashfs_super_block *sblk = &msblk->sblk; -+ -+ /* Allocate fragment index table */ -+ if (!(msblk->fragment_index = kmalloc(SQUASHFS_FRAGMENT_INDEX_BYTES -+ (sblk->fragments), GFP_KERNEL))) { -+ ERROR("Failed to allocate uid/gid table\n"); -+ return 0; -+ } -+ -+ if (SQUASHFS_FRAGMENT_INDEX_BYTES(sblk->fragments) && -+ !squashfs_read_data(s, (char *) -+ msblk->fragment_index, -+ sblk->fragment_table_start, -+ SQUASHFS_FRAGMENT_INDEX_BYTES -+ (sblk->fragments) | -+ SQUASHFS_COMPRESSED_BIT_BLOCK, NULL)) { -+ ERROR("unable to read fragment index table\n"); -+ return 0; -+ } -+ -+ if (msblk->swap) { -+ int i; -+ long long fragment; -+ -+ for (i = 0; i < SQUASHFS_FRAGMENT_INDEXES(sblk->fragments); -+ i++) { -+ SQUASHFS_SWAP_FRAGMENT_INDEXES((&fragment), -+ &msblk->fragment_index[i], 1); -+ msblk->fragment_index[i] = fragment; -+ } -+ } -+ -+ return 1; -+} -+ -+ -+static int supported_squashfs_filesystem(struct squashfs_sb_info *msblk, int silent) -+{ -+ struct squashfs_super_block *sblk = &msblk->sblk; -+ -+ msblk->iget = squashfs_iget; -+ msblk->read_blocklist = read_blocklist; -+ msblk->read_fragment_index_table = read_fragment_index_table; -+ -+ if (sblk->s_major == 1) { -+ if (!squashfs_1_0_supported(msblk)) { -+ SERROR("Major/Minor mismatch, Squashfs 1.0 filesystems " -+ "are unsupported\n"); -+ SERROR("Please recompile with " -+ "Squashfs 1.0 support enabled\n"); -+ return 0; -+ } -+ } else if (sblk->s_major == 2) { -+ if (!squashfs_2_0_supported(msblk)) { -+ SERROR("Major/Minor mismatch, Squashfs 2.0 filesystems " -+ "are unsupported\n"); -+ SERROR("Please recompile with " -+ "Squashfs 2.0 support enabled\n"); -+ return 0; -+ } -+ } else if(sblk->s_major != SQUASHFS_MAJOR || sblk->s_minor > -+ SQUASHFS_MINOR) { -+ SERROR("Major/Minor mismatch, trying to mount newer %d.%d " -+ "filesystem\n", sblk->s_major, sblk->s_minor); -+ SERROR("Please update your kernel\n"); -+ return 0; -+ } -+ -+ return 1; -+} -+ -+ -+static int squashfs_fill_super(struct super_block *s, void *data, int silent) -+{ -+ struct squashfs_sb_info *msblk; -+ struct squashfs_super_block *sblk; -+ int i; -+ char b[BDEVNAME_SIZE]; -+ struct inode *root; -+ -+ TRACE("Entered squashfs_read_superblock\n"); -+ -+ if (!(s->s_fs_info = kmalloc(sizeof(struct squashfs_sb_info), -+ GFP_KERNEL))) { -+ ERROR("Failed to allocate superblock\n"); -+ goto failure; -+ } -+ memset(s->s_fs_info, 0, sizeof(struct squashfs_sb_info)); -+ msblk = s->s_fs_info; -+ sblk = &msblk->sblk; -+ -+ msblk->devblksize = sb_min_blocksize(s, BLOCK_SIZE); -+ msblk->devblksize_log2 = ffz(~msblk->devblksize); -+ -+ init_MUTEX(&msblk->read_data_mutex); -+ init_MUTEX(&msblk->read_page_mutex); -+ init_MUTEX(&msblk->block_cache_mutex); -+ init_MUTEX(&msblk->fragment_mutex); -+ init_MUTEX(&msblk->meta_index_mutex); -+ -+ init_waitqueue_head(&msblk->waitq); -+ init_waitqueue_head(&msblk->fragment_wait_queue); -+ -+ if (!squashfs_read_data(s, (char *) sblk, SQUASHFS_START, -+ sizeof(struct squashfs_super_block) | -+ SQUASHFS_COMPRESSED_BIT_BLOCK, NULL)) { -+ SERROR("unable to read superblock\n"); -+ goto failed_mount; -+ } -+ -+ /* Check it is a SQUASHFS superblock */ -+ msblk->swap = 0; -+ if ((s->s_magic = sblk->s_magic) != SQUASHFS_MAGIC) { -+ if (sblk->s_magic == SQUASHFS_MAGIC_SWAP) { -+ struct squashfs_super_block ssblk; -+ -+ WARNING("Mounting a different endian SQUASHFS " -+ "filesystem on %s\n", bdevname(s->s_bdev, b)); -+ -+ SQUASHFS_SWAP_SUPER_BLOCK(&ssblk, sblk); -+ memcpy(sblk, &ssblk, sizeof(struct squashfs_super_block)); -+ msblk->swap = 1; -+ } else { -+ SERROR("Can't find a SQUASHFS superblock on %s\n", -+ bdevname(s->s_bdev, b)); -+ goto failed_mount; -+ } -+ } -+ -+ /* Check the MAJOR & MINOR versions */ -+ if(!supported_squashfs_filesystem(msblk, silent)) -+ goto failed_mount; -+ -+ TRACE("Found valid superblock on %s\n", bdevname(s->s_bdev, b)); -+ TRACE("Inodes are %scompressed\n", -+ SQUASHFS_UNCOMPRESSED_INODES -+ (sblk->flags) ? "un" : ""); -+ TRACE("Data is %scompressed\n", -+ SQUASHFS_UNCOMPRESSED_DATA(sblk->flags) -+ ? "un" : ""); -+ TRACE("Check data is %s present in the filesystem\n", -+ SQUASHFS_CHECK_DATA(sblk->flags) ? -+ "" : "not"); -+ TRACE("Filesystem size %lld bytes\n", sblk->bytes_used); -+ TRACE("Block size %d\n", sblk->block_size); -+ TRACE("Number of inodes %d\n", sblk->inodes); -+ if (sblk->s_major > 1) -+ TRACE("Number of fragments %d\n", sblk->fragments); -+ TRACE("Number of uids %d\n", sblk->no_uids); -+ TRACE("Number of gids %d\n", sblk->no_guids); -+ TRACE("sblk->inode_table_start %llx\n", sblk->inode_table_start); -+ TRACE("sblk->directory_table_start %llx\n", sblk->directory_table_start); -+ if (sblk->s_major > 1) -+ TRACE("sblk->fragment_table_start %llx\n", -+ sblk->fragment_table_start); -+ TRACE("sblk->uid_start %llx\n", sblk->uid_start); -+ -+ s->s_flags |= MS_RDONLY; -+ s->s_op = &squashfs_ops; -+ -+ /* Init inode_table block pointer array */ -+ if (!(msblk->block_cache = kmalloc(sizeof(struct squashfs_cache) * -+ SQUASHFS_CACHED_BLKS, GFP_KERNEL))) { -+ ERROR("Failed to allocate block cache\n"); -+ goto failed_mount; -+ } -+ -+ for (i = 0; i < SQUASHFS_CACHED_BLKS; i++) -+ msblk->block_cache[i].block = SQUASHFS_INVALID_BLK; -+ -+ msblk->next_cache = 0; -+ -+ /* Allocate read_data block */ -+ msblk->read_size = (sblk->block_size < SQUASHFS_METADATA_SIZE) ? -+ SQUASHFS_METADATA_SIZE : -+ sblk->block_size; -+ -+ if (!(msblk->read_data = kmalloc(msblk->read_size, GFP_KERNEL))) { -+ ERROR("Failed to allocate read_data block\n"); -+ goto failed_mount; -+ } -+ -+ /* Allocate read_page block */ -+ if (!(msblk->read_page = kmalloc(sblk->block_size, GFP_KERNEL))) { -+ ERROR("Failed to allocate read_page block\n"); -+ goto failed_mount; -+ } -+ -+ /* Allocate uid and gid tables */ -+ if (!(msblk->uid = kmalloc((sblk->no_uids + sblk->no_guids) * -+ sizeof(unsigned int), GFP_KERNEL))) { -+ ERROR("Failed to allocate uid/gid table\n"); -+ goto failed_mount; -+ } -+ msblk->guid = msblk->uid + sblk->no_uids; -+ -+ if (msblk->swap) { -+ unsigned int suid[sblk->no_uids + sblk->no_guids]; -+ -+ if (!squashfs_read_data(s, (char *) &suid, sblk->uid_start, -+ ((sblk->no_uids + sblk->no_guids) * -+ sizeof(unsigned int)) | -+ SQUASHFS_COMPRESSED_BIT_BLOCK, NULL)) { -+ ERROR("unable to read uid/gid table\n"); -+ goto failed_mount; -+ } -+ -+ SQUASHFS_SWAP_DATA(msblk->uid, suid, (sblk->no_uids + -+ sblk->no_guids), (sizeof(unsigned int) * 8)); -+ } else -+ if (!squashfs_read_data(s, (char *) msblk->uid, sblk->uid_start, -+ ((sblk->no_uids + sblk->no_guids) * -+ sizeof(unsigned int)) | -+ SQUASHFS_COMPRESSED_BIT_BLOCK, NULL)) { -+ ERROR("unable to read uid/gid table\n"); -+ goto failed_mount; -+ } -+ -+ -+ if (sblk->s_major == 1 && squashfs_1_0_supported(msblk)) -+ goto allocate_root; -+ -+ if (!(msblk->fragment = kmalloc(sizeof(struct squashfs_fragment_cache) * -+ SQUASHFS_CACHED_FRAGMENTS, GFP_KERNEL))) { -+ ERROR("Failed to allocate fragment block cache\n"); -+ goto failed_mount; -+ } -+ -+ for (i = 0; i < SQUASHFS_CACHED_FRAGMENTS; i++) { -+ msblk->fragment[i].locked = 0; -+ msblk->fragment[i].block = SQUASHFS_INVALID_BLK; -+ msblk->fragment[i].data = NULL; -+ } -+ -+ msblk->next_fragment = 0; -+ -+ /* Allocate fragment index table */ -+ if (msblk->read_fragment_index_table(s) == 0) -+ goto failed_mount; -+ -+allocate_root: -+ if ((root = (msblk->iget)(s, sblk->root_inode)) == NULL) -+ goto failed_mount; -+ -+ if ((s->s_root = d_alloc_root(root)) == NULL) { -+ ERROR("Root inode create failed\n"); -+ iput(root); -+ goto failed_mount; -+ } -+ -+ TRACE("Leaving squashfs_read_super\n"); -+ return 0; -+ -+failed_mount: -+ kfree(msblk->fragment_index); -+ kfree(msblk->fragment); -+ kfree(msblk->uid); -+ kfree(msblk->read_page); -+ kfree(msblk->read_data); -+ kfree(msblk->block_cache); -+ kfree(msblk->fragment_index_2); -+ kfree(s->s_fs_info); -+ s->s_fs_info = NULL; -+ return -EINVAL; -+ -+failure: -+ return -ENOMEM; -+} -+ -+ -+static int squashfs_statfs(struct dentry *dentry, struct kstatfs *buf) -+{ -+ struct squashfs_sb_info *msblk = dentry->d_inode->i_sb->s_fs_info; -+ struct squashfs_super_block *sblk = &msblk->sblk; -+ -+ TRACE("Entered squashfs_statfs\n"); -+ -+ buf->f_type = SQUASHFS_MAGIC; -+ buf->f_bsize = sblk->block_size; -+ buf->f_blocks = ((sblk->bytes_used - 1) >> sblk->block_log) + 1; -+ buf->f_bfree = buf->f_bavail = 0; -+ buf->f_files = sblk->inodes; -+ buf->f_ffree = 0; -+ buf->f_namelen = SQUASHFS_NAME_LEN; -+ -+ return 0; -+} -+ -+ -+static int squashfs_symlink_readpage(struct file *file, struct page *page) -+{ -+ struct inode *inode = page->mapping->host; -+ int index = page->index << PAGE_CACHE_SHIFT, length, bytes; -+ long long block = SQUASHFS_I(inode)->start_block; -+ int offset = SQUASHFS_I(inode)->offset; -+ void *pageaddr = kmap(page); -+ -+ TRACE("Entered squashfs_symlink_readpage, page index %ld, start block " -+ "%llx, offset %x\n", page->index, -+ SQUASHFS_I(inode)->start_block, -+ SQUASHFS_I(inode)->offset); -+ -+ for (length = 0; length < index; length += bytes) { -+ if (!(bytes = squashfs_get_cached_block(inode->i_sb, NULL, -+ block, offset, PAGE_CACHE_SIZE, &block, -+ &offset))) { -+ ERROR("Unable to read symbolic link [%llx:%x]\n", block, -+ offset); -+ goto skip_read; -+ } -+ } -+ -+ if (length != index) { -+ ERROR("(squashfs_symlink_readpage) length != index\n"); -+ bytes = 0; -+ goto skip_read; -+ } -+ -+ bytes = (i_size_read(inode) - length) > PAGE_CACHE_SIZE ? PAGE_CACHE_SIZE : -+ i_size_read(inode) - length; -+ -+ if (!(bytes = squashfs_get_cached_block(inode->i_sb, pageaddr, block, -+ offset, bytes, &block, &offset))) -+ ERROR("Unable to read symbolic link [%llx:%x]\n", block, offset); -+ -+skip_read: -+ memset(pageaddr + bytes, 0, PAGE_CACHE_SIZE - bytes); -+ kunmap(page); -+ SetPageUptodate(page); -+ unlock_page(page); -+ -+ return 0; -+} -+ -+ -+struct meta_index *locate_meta_index(struct inode *inode, int index, int offset) -+{ -+ struct meta_index *meta = NULL; -+ struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info; -+ int i; -+ -+ down(&msblk->meta_index_mutex); -+ -+ TRACE("locate_meta_index: index %d, offset %d\n", index, offset); -+ -+ if(msblk->meta_index == NULL) -+ goto not_allocated; -+ -+ for (i = 0; i < SQUASHFS_META_NUMBER; i ++) -+ if (msblk->meta_index[i].inode_number == inode->i_ino && -+ msblk->meta_index[i].offset >= offset && -+ msblk->meta_index[i].offset <= index && -+ msblk->meta_index[i].locked == 0) { -+ TRACE("locate_meta_index: entry %d, offset %d\n", i, -+ msblk->meta_index[i].offset); -+ meta = &msblk->meta_index[i]; -+ offset = meta->offset; -+ } -+ -+ if (meta) -+ meta->locked = 1; -+ -+not_allocated: -+ up(&msblk->meta_index_mutex); -+ -+ return meta; -+} -+ -+ -+struct meta_index *empty_meta_index(struct inode *inode, int offset, int skip) -+{ -+ struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info; -+ struct meta_index *meta = NULL; -+ int i; -+ -+ down(&msblk->meta_index_mutex); -+ -+ TRACE("empty_meta_index: offset %d, skip %d\n", offset, skip); -+ -+ if(msblk->meta_index == NULL) { -+ if (!(msblk->meta_index = kmalloc(sizeof(struct meta_index) * -+ SQUASHFS_META_NUMBER, GFP_KERNEL))) { -+ ERROR("Failed to allocate meta_index\n"); -+ goto failed; -+ } -+ for(i = 0; i < SQUASHFS_META_NUMBER; i++) { -+ msblk->meta_index[i].inode_number = 0; -+ msblk->meta_index[i].locked = 0; -+ } -+ msblk->next_meta_index = 0; -+ } -+ -+ for(i = SQUASHFS_META_NUMBER; i && -+ msblk->meta_index[msblk->next_meta_index].locked; i --) -+ msblk->next_meta_index = (msblk->next_meta_index + 1) % -+ SQUASHFS_META_NUMBER; -+ -+ if(i == 0) { -+ TRACE("empty_meta_index: failed!\n"); -+ goto failed; -+ } -+ -+ TRACE("empty_meta_index: returned meta entry %d, %p\n", -+ msblk->next_meta_index, -+ &msblk->meta_index[msblk->next_meta_index]); -+ -+ meta = &msblk->meta_index[msblk->next_meta_index]; -+ msblk->next_meta_index = (msblk->next_meta_index + 1) % -+ SQUASHFS_META_NUMBER; -+ -+ meta->inode_number = inode->i_ino; -+ meta->offset = offset; -+ meta->skip = skip; -+ meta->entries = 0; -+ meta->locked = 1; -+ -+failed: -+ up(&msblk->meta_index_mutex); -+ return meta; -+} -+ -+ -+void release_meta_index(struct inode *inode, struct meta_index *meta) -+{ -+ meta->locked = 0; -+} -+ -+ -+static int read_block_index(struct super_block *s, int blocks, char *block_list, -+ long long *start_block, int *offset) -+{ -+ struct squashfs_sb_info *msblk = s->s_fs_info; -+ unsigned int *block_listp; -+ int block = 0; -+ -+ if (msblk->swap) { -+ char sblock_list[blocks << 2]; -+ -+ if (!squashfs_get_cached_block(s, sblock_list, *start_block, -+ *offset, blocks << 2, start_block, offset)) { -+ ERROR("Unable to read block list [%llx:%x]\n", -+ *start_block, *offset); -+ goto failure; -+ } -+ SQUASHFS_SWAP_INTS(((unsigned int *)block_list), -+ ((unsigned int *)sblock_list), blocks); -+ } else -+ if (!squashfs_get_cached_block(s, block_list, *start_block, -+ *offset, blocks << 2, start_block, offset)) { -+ ERROR("Unable to read block list [%llx:%x]\n", -+ *start_block, *offset); -+ goto failure; -+ } -+ -+ for (block_listp = (unsigned int *) block_list; blocks; -+ block_listp++, blocks --) -+ block += SQUASHFS_COMPRESSED_SIZE_BLOCK(*block_listp); -+ -+ return block; -+ -+failure: -+ return -1; -+} -+ -+ -+#define SIZE 256 -+ -+static inline int calculate_skip(int blocks) { -+ int skip = (blocks - 1) / ((SQUASHFS_SLOTS * SQUASHFS_META_ENTRIES + 1) * SQUASHFS_META_INDEXES); -+ return skip >= 7 ? 7 : skip + 1; -+} -+ -+ -+static int get_meta_index(struct inode *inode, int index, -+ long long *index_block, int *index_offset, -+ long long *data_block, char *block_list) -+{ -+ struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info; -+ struct squashfs_super_block *sblk = &msblk->sblk; -+ int skip = calculate_skip(i_size_read(inode) >> sblk->block_log); -+ int offset = 0; -+ struct meta_index *meta; -+ struct meta_entry *meta_entry; -+ long long cur_index_block = SQUASHFS_I(inode)->u.s1.block_list_start; -+ int cur_offset = SQUASHFS_I(inode)->offset; -+ long long cur_data_block = SQUASHFS_I(inode)->start_block; -+ int i; -+ -+ index /= SQUASHFS_META_INDEXES * skip; -+ -+ while ( offset < index ) { -+ meta = locate_meta_index(inode, index, offset + 1); -+ -+ if (meta == NULL) { -+ if ((meta = empty_meta_index(inode, offset + 1, -+ skip)) == NULL) -+ goto all_done; -+ } else { -+ offset = index < meta->offset + meta->entries ? index : -+ meta->offset + meta->entries - 1; -+ meta_entry = &meta->meta_entry[offset - meta->offset]; -+ cur_index_block = meta_entry->index_block + sblk->inode_table_start; -+ cur_offset = meta_entry->offset; -+ cur_data_block = meta_entry->data_block; -+ TRACE("get_meta_index: offset %d, meta->offset %d, " -+ "meta->entries %d\n", offset, meta->offset, -+ meta->entries); -+ TRACE("get_meta_index: index_block 0x%llx, offset 0x%x" -+ " data_block 0x%llx\n", cur_index_block, -+ cur_offset, cur_data_block); -+ } -+ -+ for (i = meta->offset + meta->entries; i <= index && -+ i < meta->offset + SQUASHFS_META_ENTRIES; i++) { -+ int blocks = skip * SQUASHFS_META_INDEXES; -+ -+ while (blocks) { -+ int block = blocks > (SIZE >> 2) ? (SIZE >> 2) : -+ blocks; -+ int res = read_block_index(inode->i_sb, block, -+ block_list, &cur_index_block, -+ &cur_offset); -+ -+ if (res == -1) -+ goto failed; -+ -+ cur_data_block += res; -+ blocks -= block; -+ } -+ -+ meta_entry = &meta->meta_entry[i - meta->offset]; -+ meta_entry->index_block = cur_index_block - sblk->inode_table_start; -+ meta_entry->offset = cur_offset; -+ meta_entry->data_block = cur_data_block; -+ meta->entries ++; -+ offset ++; -+ } -+ -+ TRACE("get_meta_index: meta->offset %d, meta->entries %d\n", -+ meta->offset, meta->entries); -+ -+ release_meta_index(inode, meta); -+ } -+ -+all_done: -+ *index_block = cur_index_block; -+ *index_offset = cur_offset; -+ *data_block = cur_data_block; -+ -+ return offset * SQUASHFS_META_INDEXES * skip; -+ -+failed: -+ release_meta_index(inode, meta); -+ return -1; -+} -+ -+ -+static long long read_blocklist(struct inode *inode, int index, -+ int readahead_blks, char *block_list, -+ unsigned short **block_p, unsigned int *bsize) -+{ -+ long long block_ptr; -+ int offset; -+ long long block; -+ int res = get_meta_index(inode, index, &block_ptr, &offset, &block, -+ block_list); -+ -+ TRACE("read_blocklist: res %d, index %d, block_ptr 0x%llx, offset" -+ " 0x%x, block 0x%llx\n", res, index, block_ptr, offset, -+ block); -+ -+ if(res == -1) -+ goto failure; -+ -+ index -= res; -+ -+ while ( index ) { -+ int blocks = index > (SIZE >> 2) ? (SIZE >> 2) : index; -+ int res = read_block_index(inode->i_sb, blocks, block_list, -+ &block_ptr, &offset); -+ if (res == -1) -+ goto failure; -+ block += res; -+ index -= blocks; -+ } -+ -+ if (read_block_index(inode->i_sb, 1, block_list, -+ &block_ptr, &offset) == -1) -+ goto failure; -+ *bsize = *((unsigned int *) block_list); -+ -+ return block; -+ -+failure: -+ return 0; -+} -+ -+ -+static int squashfs_readpage(struct file *file, struct page *page) -+{ -+ struct inode *inode = page->mapping->host; -+ struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info; -+ struct squashfs_super_block *sblk = &msblk->sblk; -+ unsigned char block_list[SIZE]; -+ long long block; -+ unsigned int bsize, i = 0, bytes = 0, byte_offset = 0; -+ int index = page->index >> (sblk->block_log - PAGE_CACHE_SHIFT); -+ void *pageaddr; -+ struct squashfs_fragment_cache *fragment = NULL; -+ char *data_ptr = msblk->read_page; -+ -+ int mask = (1 << (sblk->block_log - PAGE_CACHE_SHIFT)) - 1; -+ int start_index = page->index & ~mask; -+ int end_index = start_index | mask; -+ -+ TRACE("Entered squashfs_readpage, page index %lx, start block %llx\n", -+ page->index, -+ SQUASHFS_I(inode)->start_block); -+ -+ if (page->index >= ((i_size_read(inode) + PAGE_CACHE_SIZE - 1) >> -+ PAGE_CACHE_SHIFT)) -+ goto skip_read; -+ -+ if (SQUASHFS_I(inode)->u.s1.fragment_start_block == SQUASHFS_INVALID_BLK -+ || index < (i_size_read(inode) >> -+ sblk->block_log)) { -+ if ((block = (msblk->read_blocklist)(inode, index, 1, -+ block_list, NULL, &bsize)) == 0) -+ goto skip_read; -+ -+ down(&msblk->read_page_mutex); -+ -+ if (!(bytes = squashfs_read_data(inode->i_sb, msblk->read_page, -+ block, bsize, NULL))) { -+ ERROR("Unable to read page, block %llx, size %x\n", block, -+ bsize); -+ up(&msblk->read_page_mutex); -+ goto skip_read; -+ } -+ } else { -+ if ((fragment = get_cached_fragment(inode->i_sb, -+ SQUASHFS_I(inode)-> -+ u.s1.fragment_start_block, -+ SQUASHFS_I(inode)->u.s1.fragment_size)) -+ == NULL) { -+ ERROR("Unable to read page, block %llx, size %x\n", -+ SQUASHFS_I(inode)-> -+ u.s1.fragment_start_block, -+ (int) SQUASHFS_I(inode)-> -+ u.s1.fragment_size); -+ goto skip_read; -+ } -+ bytes = SQUASHFS_I(inode)->u.s1.fragment_offset + -+ (i_size_read(inode) & (sblk->block_size -+ - 1)); -+ byte_offset = SQUASHFS_I(inode)->u.s1.fragment_offset; -+ data_ptr = fragment->data; -+ } -+ -+ for (i = start_index; i <= end_index && byte_offset < bytes; -+ i++, byte_offset += PAGE_CACHE_SIZE) { -+ struct page *push_page; -+ int available_bytes = (bytes - byte_offset) > PAGE_CACHE_SIZE ? -+ PAGE_CACHE_SIZE : bytes - byte_offset; -+ -+ TRACE("bytes %d, i %d, byte_offset %d, available_bytes %d\n", -+ bytes, i, byte_offset, available_bytes); -+ -+ if (i == page->index) { -+ pageaddr = kmap_atomic(page, KM_USER0); -+ memcpy(pageaddr, data_ptr + byte_offset, -+ available_bytes); -+ memset(pageaddr + available_bytes, 0, -+ PAGE_CACHE_SIZE - available_bytes); -+ kunmap_atomic(pageaddr, KM_USER0); -+ flush_dcache_page(page); -+ SetPageUptodate(page); -+ unlock_page(page); -+ } else if ((push_page = -+ grab_cache_page_nowait(page->mapping, i))) { -+ pageaddr = kmap_atomic(push_page, KM_USER0); -+ -+ memcpy(pageaddr, data_ptr + byte_offset, -+ available_bytes); -+ memset(pageaddr + available_bytes, 0, -+ PAGE_CACHE_SIZE - available_bytes); -+ kunmap_atomic(pageaddr, KM_USER0); -+ flush_dcache_page(push_page); -+ SetPageUptodate(push_page); -+ unlock_page(push_page); -+ page_cache_release(push_page); -+ } -+ } -+ -+ if (SQUASHFS_I(inode)->u.s1.fragment_start_block == SQUASHFS_INVALID_BLK -+ || index < (i_size_read(inode) >> -+ sblk->block_log)) -+ up(&msblk->read_page_mutex); -+ else -+ release_cached_fragment(msblk, fragment); -+ -+ return 0; -+ -+skip_read: -+ pageaddr = kmap_atomic(page, KM_USER0); -+ memset(pageaddr + bytes, 0, PAGE_CACHE_SIZE - bytes); -+ kunmap_atomic(pageaddr, KM_USER0); -+ flush_dcache_page(page); -+ SetPageUptodate(page); -+ unlock_page(page); -+ -+ return 0; -+} -+ -+ -+static int squashfs_readpage4K(struct file *file, struct page *page) -+{ -+ struct inode *inode = page->mapping->host; -+ struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info; -+ struct squashfs_super_block *sblk = &msblk->sblk; -+ unsigned char block_list[SIZE]; -+ long long block; -+ unsigned int bsize, bytes = 0; -+ void *pageaddr; -+ -+ TRACE("Entered squashfs_readpage4K, page index %lx, start block %llx\n", -+ page->index, -+ SQUASHFS_I(inode)->start_block); -+ -+ if (page->index >= ((i_size_read(inode) + PAGE_CACHE_SIZE - 1) >> -+ PAGE_CACHE_SHIFT)) { -+ pageaddr = kmap_atomic(page, KM_USER0); -+ goto skip_read; -+ } -+ -+ if (SQUASHFS_I(inode)->u.s1.fragment_start_block == SQUASHFS_INVALID_BLK -+ || page->index < (i_size_read(inode) >> -+ sblk->block_log)) { -+ block = (msblk->read_blocklist)(inode, page->index, 1, -+ block_list, NULL, &bsize); -+ -+ down(&msblk->read_page_mutex); -+ bytes = squashfs_read_data(inode->i_sb, msblk->read_page, block, -+ bsize, NULL); -+ pageaddr = kmap_atomic(page, KM_USER0); -+ if (bytes) -+ memcpy(pageaddr, msblk->read_page, bytes); -+ else -+ ERROR("Unable to read page, block %llx, size %x\n", -+ block, bsize); -+ up(&msblk->read_page_mutex); -+ } else { -+ struct squashfs_fragment_cache *fragment = -+ get_cached_fragment(inode->i_sb, -+ SQUASHFS_I(inode)-> -+ u.s1.fragment_start_block, -+ SQUASHFS_I(inode)-> u.s1.fragment_size); -+ pageaddr = kmap_atomic(page, KM_USER0); -+ if (fragment) { -+ bytes = i_size_read(inode) & (sblk->block_size - 1); -+ memcpy(pageaddr, fragment->data + SQUASHFS_I(inode)-> -+ u.s1.fragment_offset, bytes); -+ release_cached_fragment(msblk, fragment); -+ } else -+ ERROR("Unable to read page, block %llx, size %x\n", -+ SQUASHFS_I(inode)-> -+ u.s1.fragment_start_block, (int) -+ SQUASHFS_I(inode)-> u.s1.fragment_size); -+ } -+ -+skip_read: -+ memset(pageaddr + bytes, 0, PAGE_CACHE_SIZE - bytes); -+ kunmap_atomic(pageaddr, KM_USER0); -+ flush_dcache_page(page); -+ SetPageUptodate(page); -+ unlock_page(page); -+ -+ return 0; -+} -+ -+ -+static int get_dir_index_using_offset(struct super_block *s, long long -+ *next_block, unsigned int *next_offset, -+ long long index_start, -+ unsigned int index_offset, int i_count, -+ long long f_pos) -+{ -+ struct squashfs_sb_info *msblk = s->s_fs_info; -+ struct squashfs_super_block *sblk = &msblk->sblk; -+ int i, length = 0; -+ struct squashfs_dir_index index; -+ -+ TRACE("Entered get_dir_index_using_offset, i_count %d, f_pos %d\n", -+ i_count, (unsigned int) f_pos); -+ -+ f_pos =- 3; -+ if (f_pos == 0) -+ goto finish; -+ -+ for (i = 0; i < i_count; i++) { -+ if (msblk->swap) { -+ struct squashfs_dir_index sindex; -+ squashfs_get_cached_block(s, (char *) &sindex, -+ index_start, index_offset, -+ sizeof(sindex), &index_start, -+ &index_offset); -+ SQUASHFS_SWAP_DIR_INDEX(&index, &sindex); -+ } else -+ squashfs_get_cached_block(s, (char *) &index, -+ index_start, index_offset, -+ sizeof(index), &index_start, -+ &index_offset); -+ -+ if (index.index > f_pos) -+ break; -+ -+ squashfs_get_cached_block(s, NULL, index_start, index_offset, -+ index.size + 1, &index_start, -+ &index_offset); -+ -+ length = index.index; -+ *next_block = index.start_block + sblk->directory_table_start; -+ } -+ -+ *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE; -+ -+finish: -+ return length + 3; -+} -+ -+ -+static int get_dir_index_using_name(struct super_block *s, long long -+ *next_block, unsigned int *next_offset, -+ long long index_start, -+ unsigned int index_offset, int i_count, -+ const char *name, int size) -+{ -+ struct squashfs_sb_info *msblk = s->s_fs_info; -+ struct squashfs_super_block *sblk = &msblk->sblk; -+ int i, length = 0; -+ char buffer[sizeof(struct squashfs_dir_index) + SQUASHFS_NAME_LEN + 1]; -+ struct squashfs_dir_index *index = (struct squashfs_dir_index *) buffer; -+ char str[SQUASHFS_NAME_LEN + 1]; -+ -+ TRACE("Entered get_dir_index_using_name, i_count %d\n", i_count); -+ -+ strncpy(str, name, size); -+ str[size] = '\0'; -+ -+ for (i = 0; i < i_count; i++) { -+ if (msblk->swap) { -+ struct squashfs_dir_index sindex; -+ squashfs_get_cached_block(s, (char *) &sindex, -+ index_start, index_offset, -+ sizeof(sindex), &index_start, -+ &index_offset); -+ SQUASHFS_SWAP_DIR_INDEX(index, &sindex); -+ } else -+ squashfs_get_cached_block(s, (char *) index, -+ index_start, index_offset, -+ sizeof(struct squashfs_dir_index), -+ &index_start, &index_offset); -+ -+ squashfs_get_cached_block(s, index->name, index_start, -+ index_offset, index->size + 1, -+ &index_start, &index_offset); -+ -+ index->name[index->size + 1] = '\0'; -+ -+ if (strcmp(index->name, str) > 0) -+ break; -+ -+ length = index->index; -+ *next_block = index->start_block + sblk->directory_table_start; -+ } -+ -+ *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE; -+ return length + 3; -+} -+ -+ -+static int squashfs_readdir(struct file *file, void *dirent, filldir_t filldir) -+{ -+ struct inode *i = file->f_dentry->d_inode; -+ struct squashfs_sb_info *msblk = i->i_sb->s_fs_info; -+ struct squashfs_super_block *sblk = &msblk->sblk; -+ long long next_block = SQUASHFS_I(i)->start_block + -+ sblk->directory_table_start; -+ int next_offset = SQUASHFS_I(i)->offset, length = 0, dirs_read = 0, -+ dir_count; -+ struct squashfs_dir_header dirh; -+ char buffer[sizeof(struct squashfs_dir_entry) + SQUASHFS_NAME_LEN + 1]; -+ struct squashfs_dir_entry *dire = (struct squashfs_dir_entry *) buffer; -+ -+ TRACE("Entered squashfs_readdir [%llx:%x]\n", next_block, next_offset); -+ -+ while(file->f_pos < 3) { -+ char *name; -+ int size, i_ino; -+ -+ if(file->f_pos == 0) { -+ name = "."; -+ size = 1; -+ i_ino = i->i_ino; -+ } else { -+ name = ".."; -+ size = 2; -+ i_ino = SQUASHFS_I(i)->u.s2.parent_inode; -+ } -+ TRACE("Calling filldir(%x, %s, %d, %d, %d, %d)\n", -+ (unsigned int) dirent, name, size, (int) -+ file->f_pos, i_ino, -+ squashfs_filetype_table[1]); -+ -+ if (filldir(dirent, name, size, -+ file->f_pos, i_ino, -+ squashfs_filetype_table[1]) < 0) { -+ TRACE("Filldir returned less than 0\n"); -+ goto finish; -+ } -+ file->f_pos += size; -+ dirs_read++; -+ } -+ -+ length = get_dir_index_using_offset(i->i_sb, &next_block, &next_offset, -+ SQUASHFS_I(i)->u.s2.directory_index_start, -+ SQUASHFS_I(i)->u.s2.directory_index_offset, -+ SQUASHFS_I(i)->u.s2.directory_index_count, -+ file->f_pos); -+ -+ while (length < i_size_read(i)) { -+ /* read directory header */ -+ if (msblk->swap) { -+ struct squashfs_dir_header sdirh; -+ -+ if (!squashfs_get_cached_block(i->i_sb, (char *) &sdirh, -+ next_block, next_offset, sizeof(sdirh), -+ &next_block, &next_offset)) -+ goto failed_read; -+ -+ length += sizeof(sdirh); -+ SQUASHFS_SWAP_DIR_HEADER(&dirh, &sdirh); -+ } else { -+ if (!squashfs_get_cached_block(i->i_sb, (char *) &dirh, -+ next_block, next_offset, sizeof(dirh), -+ &next_block, &next_offset)) -+ goto failed_read; -+ -+ length += sizeof(dirh); -+ } -+ -+ dir_count = dirh.count + 1; -+ while (dir_count--) { -+ if (msblk->swap) { -+ struct squashfs_dir_entry sdire; -+ if (!squashfs_get_cached_block(i->i_sb, (char *) -+ &sdire, next_block, next_offset, -+ sizeof(sdire), &next_block, -+ &next_offset)) -+ goto failed_read; -+ -+ length += sizeof(sdire); -+ SQUASHFS_SWAP_DIR_ENTRY(dire, &sdire); -+ } else { -+ if (!squashfs_get_cached_block(i->i_sb, (char *) -+ dire, next_block, next_offset, -+ sizeof(*dire), &next_block, -+ &next_offset)) -+ goto failed_read; -+ -+ length += sizeof(*dire); -+ } -+ -+ if (!squashfs_get_cached_block(i->i_sb, dire->name, -+ next_block, next_offset, -+ dire->size + 1, &next_block, -+ &next_offset)) -+ goto failed_read; -+ -+ length += dire->size + 1; -+ -+ if (file->f_pos >= length) -+ continue; -+ -+ dire->name[dire->size + 1] = '\0'; -+ -+ TRACE("Calling filldir(%x, %s, %d, %d, %x:%x, %d, %d)\n", -+ (unsigned int) dirent, dire->name, -+ dire->size + 1, (int) file->f_pos, -+ dirh.start_block, dire->offset, -+ dirh.inode_number + dire->inode_number, -+ squashfs_filetype_table[dire->type]); -+ -+ if (filldir(dirent, dire->name, dire->size + 1, -+ file->f_pos, -+ dirh.inode_number + dire->inode_number, -+ squashfs_filetype_table[dire->type]) -+ < 0) { -+ TRACE("Filldir returned less than 0\n"); -+ goto finish; -+ } -+ file->f_pos = length; -+ dirs_read++; -+ } -+ } -+ -+finish: -+ return dirs_read; -+ -+failed_read: -+ ERROR("Unable to read directory block [%llx:%x]\n", next_block, -+ next_offset); -+ return 0; -+} -+ -+ -+static struct dentry *squashfs_lookup(struct inode *i, struct dentry *dentry, -+ struct nameidata *nd) -+{ -+ const unsigned char *name = dentry->d_name.name; -+ int len = dentry->d_name.len; -+ struct inode *inode = NULL; -+ struct squashfs_sb_info *msblk = i->i_sb->s_fs_info; -+ struct squashfs_super_block *sblk = &msblk->sblk; -+ long long next_block = SQUASHFS_I(i)->start_block + -+ sblk->directory_table_start; -+ int next_offset = SQUASHFS_I(i)->offset, length = 0, -+ dir_count; -+ struct squashfs_dir_header dirh; -+ char buffer[sizeof(struct squashfs_dir_entry) + SQUASHFS_NAME_LEN]; -+ struct squashfs_dir_entry *dire = (struct squashfs_dir_entry *) buffer; -+ -+ TRACE("Entered squashfs_lookup [%llx:%x]\n", next_block, next_offset); -+ -+ if (len > SQUASHFS_NAME_LEN) -+ goto exit_loop; -+ -+ length = get_dir_index_using_name(i->i_sb, &next_block, &next_offset, -+ SQUASHFS_I(i)->u.s2.directory_index_start, -+ SQUASHFS_I(i)->u.s2.directory_index_offset, -+ SQUASHFS_I(i)->u.s2.directory_index_count, name, -+ len); -+ -+ while (length < i_size_read(i)) { -+ /* read directory header */ -+ if (msblk->swap) { -+ struct squashfs_dir_header sdirh; -+ if (!squashfs_get_cached_block(i->i_sb, (char *) &sdirh, -+ next_block, next_offset, sizeof(sdirh), -+ &next_block, &next_offset)) -+ goto failed_read; -+ -+ length += sizeof(sdirh); -+ SQUASHFS_SWAP_DIR_HEADER(&dirh, &sdirh); -+ } else { -+ if (!squashfs_get_cached_block(i->i_sb, (char *) &dirh, -+ next_block, next_offset, sizeof(dirh), -+ &next_block, &next_offset)) -+ goto failed_read; -+ -+ length += sizeof(dirh); -+ } -+ -+ dir_count = dirh.count + 1; -+ while (dir_count--) { -+ if (msblk->swap) { -+ struct squashfs_dir_entry sdire; -+ if (!squashfs_get_cached_block(i->i_sb, (char *) -+ &sdire, next_block,next_offset, -+ sizeof(sdire), &next_block, -+ &next_offset)) -+ goto failed_read; -+ -+ length += sizeof(sdire); -+ SQUASHFS_SWAP_DIR_ENTRY(dire, &sdire); -+ } else { -+ if (!squashfs_get_cached_block(i->i_sb, (char *) -+ dire, next_block,next_offset, -+ sizeof(*dire), &next_block, -+ &next_offset)) -+ goto failed_read; -+ -+ length += sizeof(*dire); -+ } -+ -+ if (!squashfs_get_cached_block(i->i_sb, dire->name, -+ next_block, next_offset, dire->size + 1, -+ &next_block, &next_offset)) -+ goto failed_read; -+ -+ length += dire->size + 1; -+ -+ if (name[0] < dire->name[0]) -+ goto exit_loop; -+ -+ if ((len == dire->size + 1) && !strncmp(name, -+ dire->name, len)) { -+ squashfs_inode_t ino = -+ SQUASHFS_MKINODE(dirh.start_block, -+ dire->offset); -+ -+ TRACE("calling squashfs_iget for directory " -+ "entry %s, inode %x:%x, %d\n", name, -+ dirh.start_block, dire->offset, -+ dirh.inode_number + dire->inode_number); -+ -+ inode = (msblk->iget)(i->i_sb, ino); -+ -+ goto exit_loop; -+ } -+ } -+ } -+ -+exit_loop: -+ d_add(dentry, inode); -+ return ERR_PTR(0); -+ -+failed_read: -+ ERROR("Unable to read directory block [%llx:%x]\n", next_block, -+ next_offset); -+ goto exit_loop; -+} -+ -+ -+static void squashfs_put_super(struct super_block *s) -+{ -+ int i; -+ -+ if (s->s_fs_info) { -+ struct squashfs_sb_info *sbi = s->s_fs_info; -+ if (sbi->block_cache) -+ for (i = 0; i < SQUASHFS_CACHED_BLKS; i++) -+ if (sbi->block_cache[i].block != -+ SQUASHFS_INVALID_BLK) -+ kfree(sbi->block_cache[i].data); -+ if (sbi->fragment) -+ for (i = 0; i < SQUASHFS_CACHED_FRAGMENTS; i++) -+ SQUASHFS_FREE(sbi->fragment[i].data); -+ kfree(sbi->fragment); -+ kfree(sbi->block_cache); -+ kfree(sbi->read_data); -+ kfree(sbi->read_page); -+ kfree(sbi->uid); -+ kfree(sbi->fragment_index); -+ kfree(sbi->fragment_index_2); -+ kfree(sbi->meta_index); -+ kfree(s->s_fs_info); -+ s->s_fs_info = NULL; -+ } -+} -+ -+ -+static int squashfs_get_sb(struct file_system_type *fs_type, -+ int flags, const char *dev_name, void *data, -+ struct vfsmount *mnt) -+{ -+ return get_sb_bdev(fs_type, flags, dev_name, data, squashfs_fill_super, mnt); -+} -+ -+ -+static int __init init_squashfs_fs(void) -+{ -+ int err = init_inodecache(); -+ if (err) -+ goto out; -+ -+ printk(KERN_INFO "squashfs: version 3.0 (2006/03/15) " -+ "Phillip Lougher\n"); -+ -+ if (!(stream.workspace = vmalloc(zlib_inflate_workspacesize()))) { -+ ERROR("Failed to allocate zlib workspace\n"); -+ destroy_inodecache(); -+ err = -ENOMEM; -+ goto out; -+ } -+ -+ if ((err = register_filesystem(&squashfs_fs_type))) { -+ vfree(stream.workspace); -+ destroy_inodecache(); -+ } -+ -+out: -+ return err; -+} -+ -+ -+static void __exit exit_squashfs_fs(void) -+{ -+ vfree(stream.workspace); -+ unregister_filesystem(&squashfs_fs_type); -+ destroy_inodecache(); -+} -+ -+ -+static struct kmem_cache * squashfs_inode_cachep; -+ -+ -+static struct inode *squashfs_alloc_inode(struct super_block *sb) -+{ -+ struct squashfs_inode_info *ei; -+ ei = kmem_cache_alloc(squashfs_inode_cachep, GFP_KERNEL); -+ if (!ei) -+ return NULL; -+ return &ei->vfs_inode; -+} -+ -+ -+static void squashfs_destroy_inode(struct inode *inode) -+{ -+ kmem_cache_free(squashfs_inode_cachep, SQUASHFS_I(inode)); -+} -+ -+ -+static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flags) -+{ -+ struct squashfs_inode_info *ei = foo; -+ -+ inode_init_once(&ei->vfs_inode); -+} -+ -+ -+static int __init init_inodecache(void) -+{ -+ squashfs_inode_cachep = kmem_cache_create("squashfs_inode_cache", -+ sizeof(struct squashfs_inode_info), -+ 0, SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT, -+ init_once); -+ if (squashfs_inode_cachep == NULL) -+ return -ENOMEM; -+ return 0; -+} -+ -+ -+static void destroy_inodecache(void) -+{ -+ kmem_cache_destroy(squashfs_inode_cachep); -+} -+ -+ -+module_init(init_squashfs_fs); -+module_exit(exit_squashfs_fs); -+MODULE_DESCRIPTION("squashfs, a compressed read-only filesystem"); -+MODULE_AUTHOR("Phillip Lougher "); -+MODULE_LICENSE("GPL"); ---- /dev/null -+++ b/fs/squashfs/Makefile -@@ -0,0 +1,7 @@ -+# -+# Makefile for the linux squashfs routines. -+# -+ -+obj-$(CONFIG_SQUASHFS) += squashfs.o -+squashfs-y += inode.o -+squashfs-y += squashfs2_0.o ---- /dev/null -+++ b/fs/squashfs/squashfs2_0.c -@@ -0,0 +1,758 @@ -+/* -+ * Squashfs - a compressed read only filesystem for Linux -+ * -+ * Copyright (c) 2002, 2003, 2004, 2005, 2006 -+ * Phillip Lougher -+ * -+ * 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, -+ * 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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -+ * -+ * squashfs2_0.c -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "squashfs.h" -+static int squashfs_readdir_2(struct file *file, void *dirent, filldir_t filldir); -+static struct dentry *squashfs_lookup_2(struct inode *, struct dentry *, -+ struct nameidata *); -+ -+static struct file_operations squashfs_dir_ops_2 = { -+ .read = generic_read_dir, -+ .readdir = squashfs_readdir_2 -+}; -+ -+static struct inode_operations squashfs_dir_inode_ops_2 = { -+ .lookup = squashfs_lookup_2 -+}; -+ -+static unsigned char squashfs_filetype_table[] = { -+ DT_UNKNOWN, DT_DIR, DT_REG, DT_LNK, DT_BLK, DT_CHR, DT_FIFO, DT_SOCK -+}; -+ -+static int read_fragment_index_table_2(struct super_block *s) -+{ -+ struct squashfs_sb_info *msblk = s->s_fs_info; -+ struct squashfs_super_block *sblk = &msblk->sblk; -+ -+ if (!(msblk->fragment_index_2 = kmalloc(SQUASHFS_FRAGMENT_INDEX_BYTES_2 -+ (sblk->fragments), GFP_KERNEL))) { -+ ERROR("Failed to allocate uid/gid table\n"); -+ return 0; -+ } -+ -+ if (SQUASHFS_FRAGMENT_INDEX_BYTES_2(sblk->fragments) && -+ !squashfs_read_data(s, (char *) -+ msblk->fragment_index_2, -+ sblk->fragment_table_start, -+ SQUASHFS_FRAGMENT_INDEX_BYTES_2 -+ (sblk->fragments) | -+ SQUASHFS_COMPRESSED_BIT_BLOCK, NULL)) { -+ ERROR("unable to read fragment index table\n"); -+ return 0; -+ } -+ -+ if (msblk->swap) { -+ int i; -+ unsigned int fragment; -+ -+ for (i = 0; i < SQUASHFS_FRAGMENT_INDEXES_2(sblk->fragments); -+ i++) { -+ SQUASHFS_SWAP_FRAGMENT_INDEXES_2((&fragment), -+ &msblk->fragment_index_2[i], 1); -+ msblk->fragment_index_2[i] = fragment; -+ } -+ } -+ -+ return 1; -+} -+ -+ -+static int get_fragment_location_2(struct super_block *s, unsigned int fragment, -+ long long *fragment_start_block, -+ unsigned int *fragment_size) -+{ -+ struct squashfs_sb_info *msblk = s->s_fs_info; -+ long long start_block = -+ msblk->fragment_index_2[SQUASHFS_FRAGMENT_INDEX_2(fragment)]; -+ int offset = SQUASHFS_FRAGMENT_INDEX_OFFSET_2(fragment); -+ struct squashfs_fragment_entry_2 fragment_entry; -+ -+ if (msblk->swap) { -+ struct squashfs_fragment_entry_2 sfragment_entry; -+ -+ if (!squashfs_get_cached_block(s, (char *) &sfragment_entry, -+ start_block, offset, -+ sizeof(sfragment_entry), &start_block, -+ &offset)) -+ goto out; -+ SQUASHFS_SWAP_FRAGMENT_ENTRY_2(&fragment_entry, &sfragment_entry); -+ } else -+ if (!squashfs_get_cached_block(s, (char *) &fragment_entry, -+ start_block, offset, -+ sizeof(fragment_entry), &start_block, -+ &offset)) -+ goto out; -+ -+ *fragment_start_block = fragment_entry.start_block; -+ *fragment_size = fragment_entry.size; -+ -+ return 1; -+ -+out: -+ return 0; -+} -+ -+ -+static struct inode *squashfs_new_inode(struct super_block *s, -+ struct squashfs_base_inode_header_2 *inodeb, unsigned int ino) -+{ -+ struct squashfs_sb_info *msblk = s->s_fs_info; -+ struct squashfs_super_block *sblk = &msblk->sblk; -+ struct inode *i = new_inode(s); -+ -+ if (i) { -+ i->i_ino = ino; -+ i->i_mtime.tv_sec = sblk->mkfs_time; -+ i->i_atime.tv_sec = sblk->mkfs_time; -+ i->i_ctime.tv_sec = sblk->mkfs_time; -+ i->i_uid = msblk->uid[inodeb->uid]; -+ i->i_mode = inodeb->mode; -+ i->i_nlink = 1; -+ i->i_size = 0; -+ if (inodeb->guid == SQUASHFS_GUIDS) -+ i->i_gid = i->i_uid; -+ else -+ i->i_gid = msblk->guid[inodeb->guid]; -+ } -+ -+ return i; -+} -+ -+ -+static struct inode *squashfs_iget_2(struct super_block *s, squashfs_inode_t inode) -+{ -+ struct inode *i; -+ struct squashfs_sb_info *msblk = s->s_fs_info; -+ struct squashfs_super_block *sblk = &msblk->sblk; -+ unsigned int block = SQUASHFS_INODE_BLK(inode) + -+ sblk->inode_table_start; -+ unsigned int offset = SQUASHFS_INODE_OFFSET(inode); -+ unsigned int ino = SQUASHFS_MK_VFS_INODE(block -+ - sblk->inode_table_start, offset); -+ long long next_block; -+ unsigned int next_offset; -+ union squashfs_inode_header_2 id, sid; -+ struct squashfs_base_inode_header_2 *inodeb = &id.base, -+ *sinodeb = &sid.base; -+ -+ TRACE("Entered squashfs_iget\n"); -+ -+ if (msblk->swap) { -+ if (!squashfs_get_cached_block(s, (char *) sinodeb, block, -+ offset, sizeof(*sinodeb), &next_block, -+ &next_offset)) -+ goto failed_read; -+ SQUASHFS_SWAP_BASE_INODE_HEADER_2(inodeb, sinodeb, -+ sizeof(*sinodeb)); -+ } else -+ if (!squashfs_get_cached_block(s, (char *) inodeb, block, -+ offset, sizeof(*inodeb), &next_block, -+ &next_offset)) -+ goto failed_read; -+ -+ switch(inodeb->inode_type) { -+ case SQUASHFS_FILE_TYPE: { -+ struct squashfs_reg_inode_header_2 *inodep = &id.reg; -+ struct squashfs_reg_inode_header_2 *sinodep = &sid.reg; -+ long long frag_blk; -+ unsigned int frag_size; -+ -+ if (msblk->swap) { -+ if (!squashfs_get_cached_block(s, (char *) -+ sinodep, block, offset, -+ sizeof(*sinodep), &next_block, -+ &next_offset)) -+ goto failed_read; -+ SQUASHFS_SWAP_REG_INODE_HEADER_2(inodep, sinodep); -+ } else -+ if (!squashfs_get_cached_block(s, (char *) -+ inodep, block, offset, -+ sizeof(*inodep), &next_block, -+ &next_offset)) -+ goto failed_read; -+ -+ frag_blk = SQUASHFS_INVALID_BLK; -+ if (inodep->fragment != SQUASHFS_INVALID_FRAG && -+ !get_fragment_location_2(s, -+ inodep->fragment, &frag_blk, &frag_size)) -+ goto failed_read; -+ -+ if((i = squashfs_new_inode(s, inodeb, ino)) == NULL) -+ goto failed_read1; -+ -+ i->i_size = inodep->file_size; -+ i->i_fop = &generic_ro_fops; -+ i->i_mode |= S_IFREG; -+ i->i_mtime.tv_sec = inodep->mtime; -+ i->i_atime.tv_sec = inodep->mtime; -+ i->i_ctime.tv_sec = inodep->mtime; -+ i->i_blocks = ((i->i_size - 1) >> 9) + 1; -+ i->i_blksize = PAGE_CACHE_SIZE; -+ SQUASHFS_I(i)->u.s1.fragment_start_block = frag_blk; -+ SQUASHFS_I(i)->u.s1.fragment_size = frag_size; -+ SQUASHFS_I(i)->u.s1.fragment_offset = inodep->offset; -+ SQUASHFS_I(i)->start_block = inodep->start_block; -+ SQUASHFS_I(i)->u.s1.block_list_start = next_block; -+ SQUASHFS_I(i)->offset = next_offset; -+ if (sblk->block_size > 4096) -+ i->i_data.a_ops = &squashfs_aops; -+ else -+ i->i_data.a_ops = &squashfs_aops_4K; -+ -+ TRACE("File inode %x:%x, start_block %x, " -+ "block_list_start %llx, offset %x\n", -+ SQUASHFS_INODE_BLK(inode), offset, -+ inodep->start_block, next_block, -+ next_offset); -+ break; -+ } -+ case SQUASHFS_DIR_TYPE: { -+ struct squashfs_dir_inode_header_2 *inodep = &id.dir; -+ struct squashfs_dir_inode_header_2 *sinodep = &sid.dir; -+ -+ if (msblk->swap) { -+ if (!squashfs_get_cached_block(s, (char *) -+ sinodep, block, offset, -+ sizeof(*sinodep), &next_block, -+ &next_offset)) -+ goto failed_read; -+ SQUASHFS_SWAP_DIR_INODE_HEADER_2(inodep, sinodep); -+ } else -+ if (!squashfs_get_cached_block(s, (char *) -+ inodep, block, offset, -+ sizeof(*inodep), &next_block, -+ &next_offset)) -+ goto failed_read; -+ -+ if((i = squashfs_new_inode(s, inodeb, ino)) == NULL) -+ goto failed_read1; -+ -+ i->i_size = inodep->file_size; -+ i->i_op = &squashfs_dir_inode_ops_2; -+ i->i_fop = &squashfs_dir_ops_2; -+ i->i_mode |= S_IFDIR; -+ i->i_mtime.tv_sec = inodep->mtime; -+ i->i_atime.tv_sec = inodep->mtime; -+ i->i_ctime.tv_sec = inodep->mtime; -+ SQUASHFS_I(i)->start_block = inodep->start_block; -+ SQUASHFS_I(i)->offset = inodep->offset; -+ SQUASHFS_I(i)->u.s2.directory_index_count = 0; -+ SQUASHFS_I(i)->u.s2.parent_inode = 0; -+ -+ TRACE("Directory inode %x:%x, start_block %x, offset " -+ "%x\n", SQUASHFS_INODE_BLK(inode), -+ offset, inodep->start_block, -+ inodep->offset); -+ break; -+ } -+ case SQUASHFS_LDIR_TYPE: { -+ struct squashfs_ldir_inode_header_2 *inodep = &id.ldir; -+ struct squashfs_ldir_inode_header_2 *sinodep = &sid.ldir; -+ -+ if (msblk->swap) { -+ if (!squashfs_get_cached_block(s, (char *) -+ sinodep, block, offset, -+ sizeof(*sinodep), &next_block, -+ &next_offset)) -+ goto failed_read; -+ SQUASHFS_SWAP_LDIR_INODE_HEADER_2(inodep, -+ sinodep); -+ } else -+ if (!squashfs_get_cached_block(s, (char *) -+ inodep, block, offset, -+ sizeof(*inodep), &next_block, -+ &next_offset)) -+ goto failed_read; -+ -+ if((i = squashfs_new_inode(s, inodeb, ino)) == NULL) -+ goto failed_read1; -+ -+ i->i_size = inodep->file_size; -+ i->i_op = &squashfs_dir_inode_ops_2; -+ i->i_fop = &squashfs_dir_ops_2; -+ i->i_mode |= S_IFDIR; -+ i->i_mtime.tv_sec = inodep->mtime; -+ i->i_atime.tv_sec = inodep->mtime; -+ i->i_ctime.tv_sec = inodep->mtime; -+ SQUASHFS_I(i)->start_block = inodep->start_block; -+ SQUASHFS_I(i)->offset = inodep->offset; -+ SQUASHFS_I(i)->u.s2.directory_index_start = next_block; -+ SQUASHFS_I(i)->u.s2.directory_index_offset = -+ next_offset; -+ SQUASHFS_I(i)->u.s2.directory_index_count = -+ inodep->i_count; -+ SQUASHFS_I(i)->u.s2.parent_inode = 0; -+ -+ TRACE("Long directory inode %x:%x, start_block %x, " -+ "offset %x\n", -+ SQUASHFS_INODE_BLK(inode), offset, -+ inodep->start_block, inodep->offset); -+ break; -+ } -+ case SQUASHFS_SYMLINK_TYPE: { -+ struct squashfs_symlink_inode_header_2 *inodep = -+ &id.symlink; -+ struct squashfs_symlink_inode_header_2 *sinodep = -+ &sid.symlink; -+ -+ if (msblk->swap) { -+ if (!squashfs_get_cached_block(s, (char *) -+ sinodep, block, offset, -+ sizeof(*sinodep), &next_block, -+ &next_offset)) -+ goto failed_read; -+ SQUASHFS_SWAP_SYMLINK_INODE_HEADER_2(inodep, -+ sinodep); -+ } else -+ if (!squashfs_get_cached_block(s, (char *) -+ inodep, block, offset, -+ sizeof(*inodep), &next_block, -+ &next_offset)) -+ goto failed_read; -+ -+ if((i = squashfs_new_inode(s, inodeb, ino)) == NULL) -+ goto failed_read1; -+ -+ i->i_size = inodep->symlink_size; -+ i->i_op = &page_symlink_inode_operations; -+ i->i_data.a_ops = &squashfs_symlink_aops; -+ i->i_mode |= S_IFLNK; -+ SQUASHFS_I(i)->start_block = next_block; -+ SQUASHFS_I(i)->offset = next_offset; -+ -+ TRACE("Symbolic link inode %x:%x, start_block %llx, " -+ "offset %x\n", -+ SQUASHFS_INODE_BLK(inode), offset, -+ next_block, next_offset); -+ break; -+ } -+ case SQUASHFS_BLKDEV_TYPE: -+ case SQUASHFS_CHRDEV_TYPE: { -+ struct squashfs_dev_inode_header_2 *inodep = &id.dev; -+ struct squashfs_dev_inode_header_2 *sinodep = &sid.dev; -+ -+ if (msblk->swap) { -+ if (!squashfs_get_cached_block(s, (char *) -+ sinodep, block, offset, -+ sizeof(*sinodep), &next_block, -+ &next_offset)) -+ goto failed_read; -+ SQUASHFS_SWAP_DEV_INODE_HEADER_2(inodep, sinodep); -+ } else -+ if (!squashfs_get_cached_block(s, (char *) -+ inodep, block, offset, -+ sizeof(*inodep), &next_block, -+ &next_offset)) -+ goto failed_read; -+ -+ if ((i = squashfs_new_inode(s, inodeb, ino)) == NULL) -+ goto failed_read1; -+ -+ i->i_mode |= (inodeb->inode_type == -+ SQUASHFS_CHRDEV_TYPE) ? S_IFCHR : -+ S_IFBLK; -+ init_special_inode(i, i->i_mode, -+ old_decode_dev(inodep->rdev)); -+ -+ TRACE("Device inode %x:%x, rdev %x\n", -+ SQUASHFS_INODE_BLK(inode), offset, -+ inodep->rdev); -+ break; -+ } -+ case SQUASHFS_FIFO_TYPE: -+ case SQUASHFS_SOCKET_TYPE: { -+ if ((i = squashfs_new_inode(s, inodeb, ino)) == NULL) -+ goto failed_read1; -+ -+ i->i_mode |= (inodeb->inode_type == SQUASHFS_FIFO_TYPE) -+ ? S_IFIFO : S_IFSOCK; -+ init_special_inode(i, i->i_mode, 0); -+ break; -+ } -+ default: -+ ERROR("Unknown inode type %d in squashfs_iget!\n", -+ inodeb->inode_type); -+ goto failed_read1; -+ } -+ -+ insert_inode_hash(i); -+ return i; -+ -+failed_read: -+ ERROR("Unable to read inode [%x:%x]\n", block, offset); -+ -+failed_read1: -+ return NULL; -+} -+ -+ -+static int get_dir_index_using_offset(struct super_block *s, long long -+ *next_block, unsigned int *next_offset, -+ long long index_start, -+ unsigned int index_offset, int i_count, -+ long long f_pos) -+{ -+ struct squashfs_sb_info *msblk = s->s_fs_info; -+ struct squashfs_super_block *sblk = &msblk->sblk; -+ int i, length = 0; -+ struct squashfs_dir_index_2 index; -+ -+ TRACE("Entered get_dir_index_using_offset, i_count %d, f_pos %d\n", -+ i_count, (unsigned int) f_pos); -+ -+ if (f_pos == 0) -+ goto finish; -+ -+ for (i = 0; i < i_count; i++) { -+ if (msblk->swap) { -+ struct squashfs_dir_index_2 sindex; -+ squashfs_get_cached_block(s, (char *) &sindex, -+ index_start, index_offset, -+ sizeof(sindex), &index_start, -+ &index_offset); -+ SQUASHFS_SWAP_DIR_INDEX_2(&index, &sindex); -+ } else -+ squashfs_get_cached_block(s, (char *) &index, -+ index_start, index_offset, -+ sizeof(index), &index_start, -+ &index_offset); -+ -+ if (index.index > f_pos) -+ break; -+ -+ squashfs_get_cached_block(s, NULL, index_start, index_offset, -+ index.size + 1, &index_start, -+ &index_offset); -+ -+ length = index.index; -+ *next_block = index.start_block + sblk->directory_table_start; -+ } -+ -+ *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE; -+ -+finish: -+ return length; -+} -+ -+ -+static int get_dir_index_using_name(struct super_block *s, long long -+ *next_block, unsigned int *next_offset, -+ long long index_start, -+ unsigned int index_offset, int i_count, -+ const char *name, int size) -+{ -+ struct squashfs_sb_info *msblk = s->s_fs_info; -+ struct squashfs_super_block *sblk = &msblk->sblk; -+ int i, length = 0; -+ char buffer[sizeof(struct squashfs_dir_index_2) + SQUASHFS_NAME_LEN + 1]; -+ struct squashfs_dir_index_2 *index = (struct squashfs_dir_index_2 *) buffer; -+ char str[SQUASHFS_NAME_LEN + 1]; -+ -+ TRACE("Entered get_dir_index_using_name, i_count %d\n", i_count); -+ -+ strncpy(str, name, size); -+ str[size] = '\0'; -+ -+ for (i = 0; i < i_count; i++) { -+ if (msblk->swap) { -+ struct squashfs_dir_index_2 sindex; -+ squashfs_get_cached_block(s, (char *) &sindex, -+ index_start, index_offset, -+ sizeof(sindex), &index_start, -+ &index_offset); -+ SQUASHFS_SWAP_DIR_INDEX_2(index, &sindex); -+ } else -+ squashfs_get_cached_block(s, (char *) index, -+ index_start, index_offset, -+ sizeof(struct squashfs_dir_index_2), -+ &index_start, &index_offset); -+ -+ squashfs_get_cached_block(s, index->name, index_start, -+ index_offset, index->size + 1, -+ &index_start, &index_offset); -+ -+ index->name[index->size + 1] = '\0'; -+ -+ if (strcmp(index->name, str) > 0) -+ break; -+ -+ length = index->index; -+ *next_block = index->start_block + sblk->directory_table_start; -+ } -+ -+ *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE; -+ return length; -+} -+ -+ -+static int squashfs_readdir_2(struct file *file, void *dirent, filldir_t filldir) -+{ -+ struct inode *i = file->f_dentry->d_inode; -+ struct squashfs_sb_info *msblk = i->i_sb->s_fs_info; -+ struct squashfs_super_block *sblk = &msblk->sblk; -+ long long next_block = SQUASHFS_I(i)->start_block + -+ sblk->directory_table_start; -+ int next_offset = SQUASHFS_I(i)->offset, length = 0, dirs_read = 0, -+ dir_count; -+ struct squashfs_dir_header_2 dirh; -+ char buffer[sizeof(struct squashfs_dir_entry_2) + SQUASHFS_NAME_LEN + 1]; -+ struct squashfs_dir_entry_2 *dire = (struct squashfs_dir_entry_2 *) buffer; -+ -+ TRACE("Entered squashfs_readdir_2 [%llx:%x]\n", next_block, next_offset); -+ -+ length = get_dir_index_using_offset(i->i_sb, &next_block, &next_offset, -+ SQUASHFS_I(i)->u.s2.directory_index_start, -+ SQUASHFS_I(i)->u.s2.directory_index_offset, -+ SQUASHFS_I(i)->u.s2.directory_index_count, -+ file->f_pos); -+ -+ while (length < i_size_read(i)) { -+ /* read directory header */ -+ if (msblk->swap) { -+ struct squashfs_dir_header_2 sdirh; -+ -+ if (!squashfs_get_cached_block(i->i_sb, (char *) &sdirh, -+ next_block, next_offset, sizeof(sdirh), -+ &next_block, &next_offset)) -+ goto failed_read; -+ -+ length += sizeof(sdirh); -+ SQUASHFS_SWAP_DIR_HEADER_2(&dirh, &sdirh); -+ } else { -+ if (!squashfs_get_cached_block(i->i_sb, (char *) &dirh, -+ next_block, next_offset, sizeof(dirh), -+ &next_block, &next_offset)) -+ goto failed_read; -+ -+ length += sizeof(dirh); -+ } -+ -+ dir_count = dirh.count + 1; -+ while (dir_count--) { -+ if (msblk->swap) { -+ struct squashfs_dir_entry_2 sdire; -+ if (!squashfs_get_cached_block(i->i_sb, (char *) -+ &sdire, next_block, next_offset, -+ sizeof(sdire), &next_block, -+ &next_offset)) -+ goto failed_read; -+ -+ length += sizeof(sdire); -+ SQUASHFS_SWAP_DIR_ENTRY_2(dire, &sdire); -+ } else { -+ if (!squashfs_get_cached_block(i->i_sb, (char *) -+ dire, next_block, next_offset, -+ sizeof(*dire), &next_block, -+ &next_offset)) -+ goto failed_read; -+ -+ length += sizeof(*dire); -+ } -+ -+ if (!squashfs_get_cached_block(i->i_sb, dire->name, -+ next_block, next_offset, -+ dire->size + 1, &next_block, -+ &next_offset)) -+ goto failed_read; -+ -+ length += dire->size + 1; -+ -+ if (file->f_pos >= length) -+ continue; -+ -+ dire->name[dire->size + 1] = '\0'; -+ -+ TRACE("Calling filldir(%x, %s, %d, %d, %x:%x, %d)\n", -+ (unsigned int) dirent, dire->name, -+ dire->size + 1, (int) file->f_pos, -+ dirh.start_block, dire->offset, -+ squashfs_filetype_table[dire->type]); -+ -+ if (filldir(dirent, dire->name, dire->size + 1, -+ file->f_pos, SQUASHFS_MK_VFS_INODE( -+ dirh.start_block, dire->offset), -+ squashfs_filetype_table[dire->type]) -+ < 0) { -+ TRACE("Filldir returned less than 0\n"); -+ goto finish; -+ } -+ file->f_pos = length; -+ dirs_read++; -+ } -+ } -+ -+finish: -+ return dirs_read; -+ -+failed_read: -+ ERROR("Unable to read directory block [%llx:%x]\n", next_block, -+ next_offset); -+ return 0; -+} -+ -+ -+static struct dentry *squashfs_lookup_2(struct inode *i, struct dentry *dentry, -+ struct nameidata *nd) -+{ -+ const unsigned char *name = dentry->d_name.name; -+ int len = dentry->d_name.len; -+ struct inode *inode = NULL; -+ struct squashfs_sb_info *msblk = i->i_sb->s_fs_info; -+ struct squashfs_super_block *sblk = &msblk->sblk; -+ long long next_block = SQUASHFS_I(i)->start_block + -+ sblk->directory_table_start; -+ int next_offset = SQUASHFS_I(i)->offset, length = 0, -+ dir_count; -+ struct squashfs_dir_header_2 dirh; -+ char buffer[sizeof(struct squashfs_dir_entry_2) + SQUASHFS_NAME_LEN]; -+ struct squashfs_dir_entry_2 *dire = (struct squashfs_dir_entry_2 *) buffer; -+ int sorted = sblk->s_major == 2 && sblk->s_minor >= 1; -+ -+ TRACE("Entered squashfs_lookup [%llx:%x]\n", next_block, next_offset); -+ -+ if (len > SQUASHFS_NAME_LEN) -+ goto exit_loop; -+ -+ length = get_dir_index_using_name(i->i_sb, &next_block, &next_offset, -+ SQUASHFS_I(i)->u.s2.directory_index_start, -+ SQUASHFS_I(i)->u.s2.directory_index_offset, -+ SQUASHFS_I(i)->u.s2.directory_index_count, name, -+ len); -+ -+ while (length < i_size_read(i)) { -+ /* read directory header */ -+ if (msblk->swap) { -+ struct squashfs_dir_header_2 sdirh; -+ if (!squashfs_get_cached_block(i->i_sb, (char *) &sdirh, -+ next_block, next_offset, sizeof(sdirh), -+ &next_block, &next_offset)) -+ goto failed_read; -+ -+ length += sizeof(sdirh); -+ SQUASHFS_SWAP_DIR_HEADER_2(&dirh, &sdirh); -+ } else { -+ if (!squashfs_get_cached_block(i->i_sb, (char *) &dirh, -+ next_block, next_offset, sizeof(dirh), -+ &next_block, &next_offset)) -+ goto failed_read; -+ -+ length += sizeof(dirh); -+ } -+ -+ dir_count = dirh.count + 1; -+ while (dir_count--) { -+ if (msblk->swap) { -+ struct squashfs_dir_entry_2 sdire; -+ if (!squashfs_get_cached_block(i->i_sb, (char *) -+ &sdire, next_block,next_offset, -+ sizeof(sdire), &next_block, -+ &next_offset)) -+ goto failed_read; -+ -+ length += sizeof(sdire); -+ SQUASHFS_SWAP_DIR_ENTRY_2(dire, &sdire); -+ } else { -+ if (!squashfs_get_cached_block(i->i_sb, (char *) -+ dire, next_block,next_offset, -+ sizeof(*dire), &next_block, -+ &next_offset)) -+ goto failed_read; -+ -+ length += sizeof(*dire); -+ } -+ -+ if (!squashfs_get_cached_block(i->i_sb, dire->name, -+ next_block, next_offset, dire->size + 1, -+ &next_block, &next_offset)) -+ goto failed_read; -+ -+ length += dire->size + 1; -+ -+ if (sorted && name[0] < dire->name[0]) -+ goto exit_loop; -+ -+ if ((len == dire->size + 1) && !strncmp(name, -+ dire->name, len)) { -+ squashfs_inode_t ino = -+ SQUASHFS_MKINODE(dirh.start_block, -+ dire->offset); -+ -+ TRACE("calling squashfs_iget for directory " -+ "entry %s, inode %x:%x, %lld\n", name, -+ dirh.start_block, dire->offset, ino); -+ -+ inode = (msblk->iget)(i->i_sb, ino); -+ -+ goto exit_loop; -+ } -+ } -+ } -+ -+exit_loop: -+ d_add(dentry, inode); -+ return ERR_PTR(0); -+ -+failed_read: -+ ERROR("Unable to read directory block [%llx:%x]\n", next_block, -+ next_offset); -+ goto exit_loop; -+} -+ -+ -+int squashfs_2_0_supported(struct squashfs_sb_info *msblk) -+{ -+ struct squashfs_super_block *sblk = &msblk->sblk; -+ -+ msblk->iget = squashfs_iget_2; -+ msblk->read_fragment_index_table = read_fragment_index_table_2; -+ -+ sblk->bytes_used = sblk->bytes_used_2; -+ sblk->uid_start = sblk->uid_start_2; -+ sblk->guid_start = sblk->guid_start_2; -+ sblk->inode_table_start = sblk->inode_table_start_2; -+ sblk->directory_table_start = sblk->directory_table_start_2; -+ sblk->fragment_table_start = sblk->fragment_table_start_2; -+ -+ return 1; -+} ---- /dev/null -+++ b/fs/squashfs/squashfs.h -@@ -0,0 +1,86 @@ -+/* -+ * Squashfs - a compressed read only filesystem for Linux -+ * -+ * Copyright (c) 2002, 2003, 2004, 2005, 2006 -+ * Phillip Lougher -+ * -+ * 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, -+ * 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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -+ * -+ * squashfs.h -+ */ -+ -+#ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY -+#undef CONFIG_SQUASHFS_1_0_COMPATIBILITY -+#endif -+ -+#ifdef SQUASHFS_TRACE -+#define TRACE(s, args...) printk(KERN_NOTICE "SQUASHFS: "s, ## args) -+#else -+#define TRACE(s, args...) {} -+#endif -+ -+#define ERROR(s, args...) printk(KERN_ERR "SQUASHFS error: "s, ## args) -+ -+#define SERROR(s, args...) do { \ -+ if (!silent) \ -+ printk(KERN_ERR "SQUASHFS error: "s, ## args);\ -+ } while(0) -+ -+#define WARNING(s, args...) printk(KERN_WARNING "SQUASHFS: "s, ## args) -+ -+static inline struct squashfs_inode_info *SQUASHFS_I(struct inode *inode) -+{ -+ return list_entry(inode, struct squashfs_inode_info, vfs_inode); -+} -+ -+#if defined(CONFIG_SQUASHFS_1_0_COMPATIBILITY ) || defined(CONFIG_SQUASHFS_2_0_COMPATIBILITY) -+#define SQSH_EXTERN -+extern unsigned int squashfs_read_data(struct super_block *s, char *buffer, -+ long long index, unsigned int length, -+ long long *next_index); -+extern int squashfs_get_cached_block(struct super_block *s, char *buffer, -+ long long block, unsigned int offset, -+ int length, long long *next_block, -+ unsigned int *next_offset); -+extern void release_cached_fragment(struct squashfs_sb_info *msblk, struct -+ squashfs_fragment_cache *fragment); -+extern struct squashfs_fragment_cache *get_cached_fragment(struct super_block -+ *s, long long start_block, -+ int length); -+extern struct address_space_operations squashfs_symlink_aops; -+extern struct address_space_operations squashfs_aops; -+extern struct address_space_operations squashfs_aops_4K; -+extern struct inode_operations squashfs_dir_inode_ops; -+#else -+#define SQSH_EXTERN static -+#endif -+ -+#ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY -+extern int squashfs_1_0_supported(struct squashfs_sb_info *msblk); -+#else -+static inline int squashfs_1_0_supported(struct squashfs_sb_info *msblk) -+{ -+ return 0; -+} -+#endif -+ -+#ifdef CONFIG_SQUASHFS_2_0_COMPATIBILITY -+extern int squashfs_2_0_supported(struct squashfs_sb_info *msblk); -+#else -+static inline int squashfs_2_0_supported(struct squashfs_sb_info *msblk) -+{ -+ return 0; -+} -+#endif ---- a/include/linux/magic.h -+++ b/include/linux/magic.h -@@ -39,6 +39,9 @@ - #define REISER2FS_SUPER_MAGIC_STRING "ReIsEr2Fs" - #define REISER2FS_JR_SUPER_MAGIC_STRING "ReIsEr3Fs" - -+#define SQUASHFS_MAGIC 0x73717368 -+#define SQUASHFS_MAGIC_SWAP 0x68737173 -+ - #define SMB_SUPER_MAGIC 0x517B - #define USBDEVICE_SUPER_MAGIC 0x9fa2 - #define CGROUP_SUPER_MAGIC 0x27e0eb ---- /dev/null -+++ b/include/linux/squashfs_fs.h -@@ -0,0 +1,911 @@ -+#ifndef SQUASHFS_FS -+#define SQUASHFS_FS -+ -+/* -+ * Squashfs -+ * -+ * Copyright (c) 2002, 2003, 2004, 2005, 2006 -+ * Phillip Lougher -+ * -+ * 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, -+ * 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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -+ * -+ * squashfs_fs.h -+ */ -+ -+#ifndef CONFIG_SQUASHFS_2_0_COMPATIBILITY -+#define CONFIG_SQUASHFS_2_0_COMPATIBILITY -+#endif -+ -+#ifdef CONFIG_SQUASHFS_VMALLOC -+#define SQUASHFS_ALLOC(a) vmalloc(a) -+#define SQUASHFS_FREE(a) vfree(a) -+#else -+#define SQUASHFS_ALLOC(a) kmalloc(a, GFP_KERNEL) -+#define SQUASHFS_FREE(a) kfree(a) -+#endif -+#define SQUASHFS_CACHED_FRAGMENTS CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE -+#define SQUASHFS_MAJOR 3 -+#define SQUASHFS_MINOR 0 -+#define SQUASHFS_START 0 -+ -+/* size of metadata (inode and directory) blocks */ -+#define SQUASHFS_METADATA_SIZE 8192 -+#define SQUASHFS_METADATA_LOG 13 -+ -+/* default size of data blocks */ -+#define SQUASHFS_FILE_SIZE 65536 -+#define SQUASHFS_FILE_LOG 16 -+ -+#define SQUASHFS_FILE_MAX_SIZE 65536 -+ -+/* Max number of uids and gids */ -+#define SQUASHFS_UIDS 256 -+#define SQUASHFS_GUIDS 255 -+ -+/* Max length of filename (not 255) */ -+#define SQUASHFS_NAME_LEN 256 -+ -+#define SQUASHFS_INVALID ((long long) 0xffffffffffff) -+#define SQUASHFS_INVALID_FRAG ((unsigned int) 0xffffffff) -+#define SQUASHFS_INVALID_BLK ((long long) -1) -+#define SQUASHFS_USED_BLK ((long long) -2) -+ -+/* Filesystem flags */ -+#define SQUASHFS_NOI 0 -+#define SQUASHFS_NOD 1 -+#define SQUASHFS_CHECK 2 -+#define SQUASHFS_NOF 3 -+#define SQUASHFS_NO_FRAG 4 -+#define SQUASHFS_ALWAYS_FRAG 5 -+#define SQUASHFS_DUPLICATE 6 -+ -+#define SQUASHFS_BIT(flag, bit) ((flag >> bit) & 1) -+ -+#define SQUASHFS_UNCOMPRESSED_INODES(flags) SQUASHFS_BIT(flags, \ -+ SQUASHFS_NOI) -+ -+#define SQUASHFS_UNCOMPRESSED_DATA(flags) SQUASHFS_BIT(flags, \ -+ SQUASHFS_NOD) -+ -+#define SQUASHFS_UNCOMPRESSED_FRAGMENTS(flags) SQUASHFS_BIT(flags, \ -+ SQUASHFS_NOF) -+ -+#define SQUASHFS_NO_FRAGMENTS(flags) SQUASHFS_BIT(flags, \ -+ SQUASHFS_NO_FRAG) -+ -+#define SQUASHFS_ALWAYS_FRAGMENTS(flags) SQUASHFS_BIT(flags, \ -+ SQUASHFS_ALWAYS_FRAG) -+ -+#define SQUASHFS_DUPLICATES(flags) SQUASHFS_BIT(flags, \ -+ SQUASHFS_DUPLICATE) -+ -+#define SQUASHFS_CHECK_DATA(flags) SQUASHFS_BIT(flags, \ -+ SQUASHFS_CHECK) -+ -+#define SQUASHFS_MKFLAGS(noi, nod, check_data, nof, no_frag, always_frag, \ -+ duplicate_checking) (noi | (nod << 1) | (check_data << 2) \ -+ | (nof << 3) | (no_frag << 4) | (always_frag << 5) | \ -+ (duplicate_checking << 6)) -+ -+/* Max number of types and file types */ -+#define SQUASHFS_DIR_TYPE 1 -+#define SQUASHFS_FILE_TYPE 2 -+#define SQUASHFS_SYMLINK_TYPE 3 -+#define SQUASHFS_BLKDEV_TYPE 4 -+#define SQUASHFS_CHRDEV_TYPE 5 -+#define SQUASHFS_FIFO_TYPE 6 -+#define SQUASHFS_SOCKET_TYPE 7 -+#define SQUASHFS_LDIR_TYPE 8 -+#define SQUASHFS_LREG_TYPE 9 -+ -+/* 1.0 filesystem type definitions */ -+#define SQUASHFS_TYPES 5 -+#define SQUASHFS_IPC_TYPE 0 -+ -+/* Flag whether block is compressed or uncompressed, bit is set if block is -+ * uncompressed */ -+#define SQUASHFS_COMPRESSED_BIT (1 << 15) -+ -+#define SQUASHFS_COMPRESSED_SIZE(B) (((B) & ~SQUASHFS_COMPRESSED_BIT) ? \ -+ (B) & ~SQUASHFS_COMPRESSED_BIT : SQUASHFS_COMPRESSED_BIT) -+ -+#define SQUASHFS_COMPRESSED(B) (!((B) & SQUASHFS_COMPRESSED_BIT)) -+ -+#define SQUASHFS_COMPRESSED_BIT_BLOCK (1 << 24) -+ -+#define SQUASHFS_COMPRESSED_SIZE_BLOCK(B) (((B) & \ -+ ~SQUASHFS_COMPRESSED_BIT_BLOCK) ? (B) & \ -+ ~SQUASHFS_COMPRESSED_BIT_BLOCK : SQUASHFS_COMPRESSED_BIT_BLOCK) -+ -+#define SQUASHFS_COMPRESSED_BLOCK(B) (!((B) & SQUASHFS_COMPRESSED_BIT_BLOCK)) -+ -+/* -+ * Inode number ops. Inodes consist of a compressed block number, and an -+ * uncompressed offset within that block -+ */ -+#define SQUASHFS_INODE_BLK(a) ((unsigned int) ((a) >> 16)) -+ -+#define SQUASHFS_INODE_OFFSET(a) ((unsigned int) ((a) & 0xffff)) -+ -+#define SQUASHFS_MKINODE(A, B) ((squashfs_inode_t)(((squashfs_inode_t) (A)\ -+ << 16) + (B))) -+ -+/* Compute 32 bit VFS inode number from squashfs inode number */ -+#define SQUASHFS_MK_VFS_INODE(a, b) ((unsigned int) (((a) << 8) + \ -+ ((b) >> 2) + 1)) -+/* XXX */ -+ -+/* Translate between VFS mode and squashfs mode */ -+#define SQUASHFS_MODE(a) ((a) & 0xfff) -+ -+/* fragment and fragment table defines */ -+#define SQUASHFS_FRAGMENT_BYTES(A) (A * sizeof(struct squashfs_fragment_entry)) -+ -+#define SQUASHFS_FRAGMENT_INDEX(A) (SQUASHFS_FRAGMENT_BYTES(A) / \ -+ SQUASHFS_METADATA_SIZE) -+ -+#define SQUASHFS_FRAGMENT_INDEX_OFFSET(A) (SQUASHFS_FRAGMENT_BYTES(A) % \ -+ SQUASHFS_METADATA_SIZE) -+ -+#define SQUASHFS_FRAGMENT_INDEXES(A) ((SQUASHFS_FRAGMENT_BYTES(A) + \ -+ SQUASHFS_METADATA_SIZE - 1) / \ -+ SQUASHFS_METADATA_SIZE) -+ -+#define SQUASHFS_FRAGMENT_INDEX_BYTES(A) (SQUASHFS_FRAGMENT_INDEXES(A) *\ -+ sizeof(long long)) -+ -+/* cached data constants for filesystem */ -+#define SQUASHFS_CACHED_BLKS 8 -+ -+#define SQUASHFS_MAX_FILE_SIZE_LOG 64 -+ -+#define SQUASHFS_MAX_FILE_SIZE ((long long) 1 << \ -+ (SQUASHFS_MAX_FILE_SIZE_LOG - 2)) -+ -+#define SQUASHFS_MARKER_BYTE 0xff -+ -+/* meta index cache */ -+#define SQUASHFS_META_INDEXES (SQUASHFS_METADATA_SIZE / sizeof(unsigned int)) -+#define SQUASHFS_META_ENTRIES 31 -+#define SQUASHFS_META_NUMBER 8 -+#define SQUASHFS_SLOTS 4 -+ -+#include -+ -+struct meta_entry { -+ long long data_block; -+ unsigned int index_block; -+ unsigned short offset; -+ unsigned short pad; -+}; -+ -+struct meta_index { -+ unsigned int inode_number; -+ unsigned int offset; -+ unsigned short entries; -+ unsigned short skip; -+ unsigned short locked; -+ unsigned short pad; -+ struct meta_entry meta_entry[SQUASHFS_META_ENTRIES]; -+}; -+ -+ -+/* -+ * definitions for structures on disk -+ */ -+ -+typedef long long squashfs_block_t; -+typedef long long squashfs_inode_t; -+ -+struct squashfs_super_block { -+ unsigned int s_magic; -+ unsigned int inodes; -+ unsigned int bytes_used_2; -+ unsigned int uid_start_2; -+ unsigned int guid_start_2; -+ unsigned int inode_table_start_2; -+ unsigned int directory_table_start_2; -+ unsigned int s_major:16; -+ unsigned int s_minor:16; -+ unsigned int block_size_1:16; -+ unsigned int block_log:16; -+ unsigned int flags:8; -+ unsigned int no_uids:8; -+ unsigned int no_guids:8; -+ unsigned int mkfs_time /* time of filesystem creation */; -+ squashfs_inode_t root_inode; -+ unsigned int block_size; -+ unsigned int fragments; -+ unsigned int fragment_table_start_2; -+ long long bytes_used; -+ long long uid_start; -+ long long guid_start; -+ long long inode_table_start; -+ long long directory_table_start; -+ long long fragment_table_start; -+ long long unused; -+} __attribute__ ((packed)); -+ -+struct squashfs_dir_index { -+ unsigned int index; -+ unsigned int start_block; -+ unsigned char size; -+ unsigned char name[0]; -+} __attribute__ ((packed)); -+ -+#define SQUASHFS_BASE_INODE_HEADER \ -+ unsigned int inode_type:4; \ -+ unsigned int mode:12; \ -+ unsigned int uid:8; \ -+ unsigned int guid:8; \ -+ unsigned int mtime; \ -+ unsigned int inode_number; -+ -+struct squashfs_base_inode_header { -+ SQUASHFS_BASE_INODE_HEADER; -+} __attribute__ ((packed)); -+ -+struct squashfs_ipc_inode_header { -+ SQUASHFS_BASE_INODE_HEADER; -+ unsigned int nlink; -+} __attribute__ ((packed)); -+ -+struct squashfs_dev_inode_header { -+ SQUASHFS_BASE_INODE_HEADER; -+ unsigned int nlink; -+ unsigned short rdev; -+} __attribute__ ((packed)); -+ -+struct squashfs_symlink_inode_header { -+ SQUASHFS_BASE_INODE_HEADER; -+ unsigned int nlink; -+ unsigned short symlink_size; -+ char symlink[0]; -+} __attribute__ ((packed)); -+ -+struct squashfs_reg_inode_header { -+ SQUASHFS_BASE_INODE_HEADER; -+ squashfs_block_t start_block; -+ unsigned int fragment; -+ unsigned int offset; -+ unsigned int file_size; -+ unsigned short block_list[0]; -+} __attribute__ ((packed)); -+ -+struct squashfs_lreg_inode_header { -+ SQUASHFS_BASE_INODE_HEADER; -+ unsigned int nlink; -+ squashfs_block_t start_block; -+ unsigned int fragment; -+ unsigned int offset; -+ long long file_size; -+ unsigned short block_list[0]; -+} __attribute__ ((packed)); -+ -+struct squashfs_dir_inode_header { -+ SQUASHFS_BASE_INODE_HEADER; -+ unsigned int nlink; -+ unsigned int file_size:19; -+ unsigned int offset:13; -+ unsigned int start_block; -+ unsigned int parent_inode; -+} __attribute__ ((packed)); -+ -+struct squashfs_ldir_inode_header { -+ SQUASHFS_BASE_INODE_HEADER; -+ unsigned int nlink; -+ unsigned int file_size:27; -+ unsigned int offset:13; -+ unsigned int start_block; -+ unsigned int i_count:16; -+ unsigned int parent_inode; -+ struct squashfs_dir_index index[0]; -+} __attribute__ ((packed)); -+ -+union squashfs_inode_header { -+ struct squashfs_base_inode_header base; -+ struct squashfs_dev_inode_header dev; -+ struct squashfs_symlink_inode_header symlink; -+ struct squashfs_reg_inode_header reg; -+ struct squashfs_lreg_inode_header lreg; -+ struct squashfs_dir_inode_header dir; -+ struct squashfs_ldir_inode_header ldir; -+ struct squashfs_ipc_inode_header ipc; -+}; -+ -+struct squashfs_dir_entry { -+ unsigned int offset:13; -+ unsigned int type:3; -+ unsigned int size:8; -+ int inode_number:16; -+ char name[0]; -+} __attribute__ ((packed)); -+ -+struct squashfs_dir_header { -+ unsigned int count:8; -+ unsigned int start_block; -+ unsigned int inode_number; -+} __attribute__ ((packed)); -+ -+struct squashfs_fragment_entry { -+ long long start_block; -+ unsigned int size; -+ unsigned int unused; -+} __attribute__ ((packed)); -+ -+extern int squashfs_uncompress_block(void *d, int dstlen, void *s, int srclen); -+extern int squashfs_uncompress_init(void); -+extern int squashfs_uncompress_exit(void); -+ -+/* -+ * macros to convert each packed bitfield structure from little endian to big -+ * endian and vice versa. These are needed when creating or using a filesystem -+ * on a machine with different byte ordering to the target architecture. -+ * -+ */ -+ -+#define SQUASHFS_SWAP_START \ -+ int bits;\ -+ int b_pos;\ -+ unsigned long long val;\ -+ unsigned char *s;\ -+ unsigned char *d; -+ -+#define SQUASHFS_SWAP_SUPER_BLOCK(s, d) {\ -+ SQUASHFS_SWAP_START\ -+ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_super_block));\ -+ SQUASHFS_SWAP((s)->s_magic, d, 0, 32);\ -+ SQUASHFS_SWAP((s)->inodes, d, 32, 32);\ -+ SQUASHFS_SWAP((s)->bytes_used_2, d, 64, 32);\ -+ SQUASHFS_SWAP((s)->uid_start_2, d, 96, 32);\ -+ SQUASHFS_SWAP((s)->guid_start_2, d, 128, 32);\ -+ SQUASHFS_SWAP((s)->inode_table_start_2, d, 160, 32);\ -+ SQUASHFS_SWAP((s)->directory_table_start_2, d, 192, 32);\ -+ SQUASHFS_SWAP((s)->s_major, d, 224, 16);\ -+ SQUASHFS_SWAP((s)->s_minor, d, 240, 16);\ -+ SQUASHFS_SWAP((s)->block_size_1, d, 256, 16);\ -+ SQUASHFS_SWAP((s)->block_log, d, 272, 16);\ -+ SQUASHFS_SWAP((s)->flags, d, 288, 8);\ -+ SQUASHFS_SWAP((s)->no_uids, d, 296, 8);\ -+ SQUASHFS_SWAP((s)->no_guids, d, 304, 8);\ -+ SQUASHFS_SWAP((s)->mkfs_time, d, 312, 32);\ -+ SQUASHFS_SWAP((s)->root_inode, d, 344, 64);\ -+ SQUASHFS_SWAP((s)->block_size, d, 408, 32);\ -+ SQUASHFS_SWAP((s)->fragments, d, 440, 32);\ -+ SQUASHFS_SWAP((s)->fragment_table_start_2, d, 472, 32);\ -+ SQUASHFS_SWAP((s)->bytes_used, d, 504, 64);\ -+ SQUASHFS_SWAP((s)->uid_start, d, 568, 64);\ -+ SQUASHFS_SWAP((s)->guid_start, d, 632, 64);\ -+ SQUASHFS_SWAP((s)->inode_table_start, d, 696, 64);\ -+ SQUASHFS_SWAP((s)->directory_table_start, d, 760, 64);\ -+ SQUASHFS_SWAP((s)->fragment_table_start, d, 824, 64);\ -+ SQUASHFS_SWAP((s)->unused, d, 888, 64);\ -+} -+ -+#define SQUASHFS_SWAP_BASE_INODE_CORE(s, d, n)\ -+ SQUASHFS_MEMSET(s, d, n);\ -+ SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\ -+ SQUASHFS_SWAP((s)->mode, d, 4, 12);\ -+ SQUASHFS_SWAP((s)->uid, d, 16, 8);\ -+ SQUASHFS_SWAP((s)->guid, d, 24, 8);\ -+ SQUASHFS_SWAP((s)->mtime, d, 32, 32);\ -+ SQUASHFS_SWAP((s)->inode_number, d, 64, 32); -+ -+#define SQUASHFS_SWAP_BASE_INODE_HEADER(s, d, n) {\ -+ SQUASHFS_SWAP_START\ -+ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, n)\ -+} -+ -+#define SQUASHFS_SWAP_IPC_INODE_HEADER(s, d) {\ -+ SQUASHFS_SWAP_START\ -+ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ -+ sizeof(struct squashfs_ipc_inode_header))\ -+ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ -+} -+ -+#define SQUASHFS_SWAP_DEV_INODE_HEADER(s, d) {\ -+ SQUASHFS_SWAP_START\ -+ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ -+ sizeof(struct squashfs_dev_inode_header)); \ -+ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ -+ SQUASHFS_SWAP((s)->rdev, d, 128, 16);\ -+} -+ -+#define SQUASHFS_SWAP_SYMLINK_INODE_HEADER(s, d) {\ -+ SQUASHFS_SWAP_START\ -+ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ -+ sizeof(struct squashfs_symlink_inode_header));\ -+ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ -+ SQUASHFS_SWAP((s)->symlink_size, d, 128, 16);\ -+} -+ -+#define SQUASHFS_SWAP_REG_INODE_HEADER(s, d) {\ -+ SQUASHFS_SWAP_START\ -+ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ -+ sizeof(struct squashfs_reg_inode_header));\ -+ SQUASHFS_SWAP((s)->start_block, d, 96, 64);\ -+ SQUASHFS_SWAP((s)->fragment, d, 160, 32);\ -+ SQUASHFS_SWAP((s)->offset, d, 192, 32);\ -+ SQUASHFS_SWAP((s)->file_size, d, 224, 32);\ -+} -+ -+#define SQUASHFS_SWAP_LREG_INODE_HEADER(s, d) {\ -+ SQUASHFS_SWAP_START\ -+ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ -+ sizeof(struct squashfs_lreg_inode_header));\ -+ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ -+ SQUASHFS_SWAP((s)->start_block, d, 128, 64);\ -+ SQUASHFS_SWAP((s)->fragment, d, 192, 32);\ -+ SQUASHFS_SWAP((s)->offset, d, 224, 32);\ -+ SQUASHFS_SWAP((s)->file_size, d, 256, 64);\ -+} -+ -+#define SQUASHFS_SWAP_DIR_INODE_HEADER(s, d) {\ -+ SQUASHFS_SWAP_START\ -+ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ -+ sizeof(struct squashfs_dir_inode_header));\ -+ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ -+ SQUASHFS_SWAP((s)->file_size, d, 128, 19);\ -+ SQUASHFS_SWAP((s)->offset, d, 147, 13);\ -+ SQUASHFS_SWAP((s)->start_block, d, 160, 32);\ -+ SQUASHFS_SWAP((s)->parent_inode, d, 192, 32);\ -+} -+ -+#define SQUASHFS_SWAP_LDIR_INODE_HEADER(s, d) {\ -+ SQUASHFS_SWAP_START\ -+ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ -+ sizeof(struct squashfs_ldir_inode_header));\ -+ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ -+ SQUASHFS_SWAP((s)->file_size, d, 128, 27);\ -+ SQUASHFS_SWAP((s)->offset, d, 155, 13);\ -+ SQUASHFS_SWAP((s)->start_block, d, 168, 32);\ -+ SQUASHFS_SWAP((s)->i_count, d, 200, 16);\ -+ SQUASHFS_SWAP((s)->parent_inode, d, 216, 32);\ -+} -+ -+#define SQUASHFS_SWAP_DIR_INDEX(s, d) {\ -+ SQUASHFS_SWAP_START\ -+ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_index));\ -+ SQUASHFS_SWAP((s)->index, d, 0, 32);\ -+ SQUASHFS_SWAP((s)->start_block, d, 32, 32);\ -+ SQUASHFS_SWAP((s)->size, d, 64, 8);\ -+} -+ -+#define SQUASHFS_SWAP_DIR_HEADER(s, d) {\ -+ SQUASHFS_SWAP_START\ -+ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_header));\ -+ SQUASHFS_SWAP((s)->count, d, 0, 8);\ -+ SQUASHFS_SWAP((s)->start_block, d, 8, 32);\ -+ SQUASHFS_SWAP((s)->inode_number, d, 40, 32);\ -+} -+ -+#define SQUASHFS_SWAP_DIR_ENTRY(s, d) {\ -+ SQUASHFS_SWAP_START\ -+ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_entry));\ -+ SQUASHFS_SWAP((s)->offset, d, 0, 13);\ -+ SQUASHFS_SWAP((s)->type, d, 13, 3);\ -+ SQUASHFS_SWAP((s)->size, d, 16, 8);\ -+ SQUASHFS_SWAP((s)->inode_number, d, 24, 16);\ -+} -+ -+#define SQUASHFS_SWAP_FRAGMENT_ENTRY(s, d) {\ -+ SQUASHFS_SWAP_START\ -+ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_fragment_entry));\ -+ SQUASHFS_SWAP((s)->start_block, d, 0, 64);\ -+ SQUASHFS_SWAP((s)->size, d, 64, 32);\ -+} -+ -+#define SQUASHFS_SWAP_SHORTS(s, d, n) {\ -+ int entry;\ -+ int bit_position;\ -+ SQUASHFS_SWAP_START\ -+ SQUASHFS_MEMSET(s, d, n * 2);\ -+ for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ -+ 16)\ -+ SQUASHFS_SWAP(s[entry], d, bit_position, 16);\ -+} -+ -+#define SQUASHFS_SWAP_INTS(s, d, n) {\ -+ int entry;\ -+ int bit_position;\ -+ SQUASHFS_SWAP_START\ -+ SQUASHFS_MEMSET(s, d, n * 4);\ -+ for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ -+ 32)\ -+ SQUASHFS_SWAP(s[entry], d, bit_position, 32);\ -+} -+ -+#define SQUASHFS_SWAP_LONG_LONGS(s, d, n) {\ -+ int entry;\ -+ int bit_position;\ -+ SQUASHFS_SWAP_START\ -+ SQUASHFS_MEMSET(s, d, n * 8);\ -+ for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ -+ 64)\ -+ SQUASHFS_SWAP(s[entry], d, bit_position, 64);\ -+} -+ -+#define SQUASHFS_SWAP_DATA(s, d, n, bits) {\ -+ int entry;\ -+ int bit_position;\ -+ SQUASHFS_SWAP_START\ -+ SQUASHFS_MEMSET(s, d, n * bits / 8);\ -+ for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ -+ bits)\ -+ SQUASHFS_SWAP(s[entry], d, bit_position, bits);\ -+} -+ -+#define SQUASHFS_SWAP_FRAGMENT_INDEXES(s, d, n) SQUASHFS_SWAP_LONG_LONGS(s, d, n) -+ -+#ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY -+ -+struct squashfs_base_inode_header_1 { -+ unsigned int inode_type:4; -+ unsigned int mode:12; /* protection */ -+ unsigned int uid:4; /* index into uid table */ -+ unsigned int guid:4; /* index into guid table */ -+} __attribute__ ((packed)); -+ -+struct squashfs_ipc_inode_header_1 { -+ unsigned int inode_type:4; -+ unsigned int mode:12; /* protection */ -+ unsigned int uid:4; /* index into uid table */ -+ unsigned int guid:4; /* index into guid table */ -+ unsigned int type:4; -+ unsigned int offset:4; -+} __attribute__ ((packed)); -+ -+struct squashfs_dev_inode_header_1 { -+ unsigned int inode_type:4; -+ unsigned int mode:12; /* protection */ -+ unsigned int uid:4; /* index into uid table */ -+ unsigned int guid:4; /* index into guid table */ -+ unsigned short rdev; -+} __attribute__ ((packed)); -+ -+struct squashfs_symlink_inode_header_1 { -+ unsigned int inode_type:4; -+ unsigned int mode:12; /* protection */ -+ unsigned int uid:4; /* index into uid table */ -+ unsigned int guid:4; /* index into guid table */ -+ unsigned short symlink_size; -+ char symlink[0]; -+} __attribute__ ((packed)); -+ -+struct squashfs_reg_inode_header_1 { -+ unsigned int inode_type:4; -+ unsigned int mode:12; /* protection */ -+ unsigned int uid:4; /* index into uid table */ -+ unsigned int guid:4; /* index into guid table */ -+ unsigned int mtime; -+ unsigned int start_block; -+ unsigned int file_size:32; -+ unsigned short block_list[0]; -+} __attribute__ ((packed)); -+ -+struct squashfs_dir_inode_header_1 { -+ unsigned int inode_type:4; -+ unsigned int mode:12; /* protection */ -+ unsigned int uid:4; /* index into uid table */ -+ unsigned int guid:4; /* index into guid table */ -+ unsigned int file_size:19; -+ unsigned int offset:13; -+ unsigned int mtime; -+ unsigned int start_block:24; -+} __attribute__ ((packed)); -+ -+#define SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, n) \ -+ SQUASHFS_MEMSET(s, d, n);\ -+ SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\ -+ SQUASHFS_SWAP((s)->mode, d, 4, 12);\ -+ SQUASHFS_SWAP((s)->uid, d, 16, 4);\ -+ SQUASHFS_SWAP((s)->guid, d, 20, 4); -+ -+#define SQUASHFS_SWAP_BASE_INODE_HEADER_1(s, d, n) {\ -+ SQUASHFS_SWAP_START\ -+ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, n)\ -+} -+ -+#define SQUASHFS_SWAP_IPC_INODE_HEADER_1(s, d) {\ -+ SQUASHFS_SWAP_START\ -+ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ -+ sizeof(struct squashfs_ipc_inode_header_1));\ -+ SQUASHFS_SWAP((s)->type, d, 24, 4);\ -+ SQUASHFS_SWAP((s)->offset, d, 28, 4);\ -+} -+ -+#define SQUASHFS_SWAP_DEV_INODE_HEADER_1(s, d) {\ -+ SQUASHFS_SWAP_START\ -+ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ -+ sizeof(struct squashfs_dev_inode_header_1));\ -+ SQUASHFS_SWAP((s)->rdev, d, 24, 16);\ -+} -+ -+#define SQUASHFS_SWAP_SYMLINK_INODE_HEADER_1(s, d) {\ -+ SQUASHFS_SWAP_START\ -+ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ -+ sizeof(struct squashfs_symlink_inode_header_1));\ -+ SQUASHFS_SWAP((s)->symlink_size, d, 24, 16);\ -+} -+ -+#define SQUASHFS_SWAP_REG_INODE_HEADER_1(s, d) {\ -+ SQUASHFS_SWAP_START\ -+ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ -+ sizeof(struct squashfs_reg_inode_header_1));\ -+ SQUASHFS_SWAP((s)->mtime, d, 24, 32);\ -+ SQUASHFS_SWAP((s)->start_block, d, 56, 32);\ -+ SQUASHFS_SWAP((s)->file_size, d, 88, 32);\ -+} -+ -+#define SQUASHFS_SWAP_DIR_INODE_HEADER_1(s, d) {\ -+ SQUASHFS_SWAP_START\ -+ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ -+ sizeof(struct squashfs_dir_inode_header_1));\ -+ SQUASHFS_SWAP((s)->file_size, d, 24, 19);\ -+ SQUASHFS_SWAP((s)->offset, d, 43, 13);\ -+ SQUASHFS_SWAP((s)->mtime, d, 56, 32);\ -+ SQUASHFS_SWAP((s)->start_block, d, 88, 24);\ -+} -+ -+#endif -+ -+#ifdef CONFIG_SQUASHFS_2_0_COMPATIBILITY -+ -+struct squashfs_dir_index_2 { -+ unsigned int index:27; -+ unsigned int start_block:29; -+ unsigned char size; -+ unsigned char name[0]; -+} __attribute__ ((packed)); -+ -+struct squashfs_base_inode_header_2 { -+ unsigned int inode_type:4; -+ unsigned int mode:12; /* protection */ -+ unsigned int uid:8; /* index into uid table */ -+ unsigned int guid:8; /* index into guid table */ -+} __attribute__ ((packed)); -+ -+struct squashfs_ipc_inode_header_2 { -+ unsigned int inode_type:4; -+ unsigned int mode:12; /* protection */ -+ unsigned int uid:8; /* index into uid table */ -+ unsigned int guid:8; /* index into guid table */ -+} __attribute__ ((packed)); -+ -+struct squashfs_dev_inode_header_2 { -+ unsigned int inode_type:4; -+ unsigned int mode:12; /* protection */ -+ unsigned int uid:8; /* index into uid table */ -+ unsigned int guid:8; /* index into guid table */ -+ unsigned short rdev; -+} __attribute__ ((packed)); -+ -+struct squashfs_symlink_inode_header_2 { -+ unsigned int inode_type:4; -+ unsigned int mode:12; /* protection */ -+ unsigned int uid:8; /* index into uid table */ -+ unsigned int guid:8; /* index into guid table */ -+ unsigned short symlink_size; -+ char symlink[0]; -+} __attribute__ ((packed)); -+ -+struct squashfs_reg_inode_header_2 { -+ unsigned int inode_type:4; -+ unsigned int mode:12; /* protection */ -+ unsigned int uid:8; /* index into uid table */ -+ unsigned int guid:8; /* index into guid table */ -+ unsigned int mtime; -+ unsigned int start_block; -+ unsigned int fragment; -+ unsigned int offset; -+ unsigned int file_size:32; -+ unsigned short block_list[0]; -+} __attribute__ ((packed)); -+ -+struct squashfs_dir_inode_header_2 { -+ unsigned int inode_type:4; -+ unsigned int mode:12; /* protection */ -+ unsigned int uid:8; /* index into uid table */ -+ unsigned int guid:8; /* index into guid table */ -+ unsigned int file_size:19; -+ unsigned int offset:13; -+ unsigned int mtime; -+ unsigned int start_block:24; -+} __attribute__ ((packed)); -+ -+struct squashfs_ldir_inode_header_2 { -+ unsigned int inode_type:4; -+ unsigned int mode:12; /* protection */ -+ unsigned int uid:8; /* index into uid table */ -+ unsigned int guid:8; /* index into guid table */ -+ unsigned int file_size:27; -+ unsigned int offset:13; -+ unsigned int mtime; -+ unsigned int start_block:24; -+ unsigned int i_count:16; -+ struct squashfs_dir_index_2 index[0]; -+} __attribute__ ((packed)); -+ -+union squashfs_inode_header_2 { -+ struct squashfs_base_inode_header_2 base; -+ struct squashfs_dev_inode_header_2 dev; -+ struct squashfs_symlink_inode_header_2 symlink; -+ struct squashfs_reg_inode_header_2 reg; -+ struct squashfs_dir_inode_header_2 dir; -+ struct squashfs_ldir_inode_header_2 ldir; -+ struct squashfs_ipc_inode_header_2 ipc; -+}; -+ -+struct squashfs_dir_header_2 { -+ unsigned int count:8; -+ unsigned int start_block:24; -+} __attribute__ ((packed)); -+ -+struct squashfs_dir_entry_2 { -+ unsigned int offset:13; -+ unsigned int type:3; -+ unsigned int size:8; -+ char name[0]; -+} __attribute__ ((packed)); -+ -+struct squashfs_fragment_entry_2 { -+ unsigned int start_block; -+ unsigned int size; -+} __attribute__ ((packed)); -+ -+#define SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, n)\ -+ SQUASHFS_MEMSET(s, d, n);\ -+ SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\ -+ SQUASHFS_SWAP((s)->mode, d, 4, 12);\ -+ SQUASHFS_SWAP((s)->uid, d, 16, 8);\ -+ SQUASHFS_SWAP((s)->guid, d, 24, 8);\ -+ -+#define SQUASHFS_SWAP_BASE_INODE_HEADER_2(s, d, n) {\ -+ SQUASHFS_SWAP_START\ -+ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, n)\ -+} -+ -+#define SQUASHFS_SWAP_IPC_INODE_HEADER_2(s, d) \ -+ SQUASHFS_SWAP_BASE_INODE_HEADER_2(s, d, sizeof(struct squashfs_ipc_inode_header_2)) -+ -+#define SQUASHFS_SWAP_DEV_INODE_HEADER_2(s, d) {\ -+ SQUASHFS_SWAP_START\ -+ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ -+ sizeof(struct squashfs_dev_inode_header_2)); \ -+ SQUASHFS_SWAP((s)->rdev, d, 32, 16);\ -+} -+ -+#define SQUASHFS_SWAP_SYMLINK_INODE_HEADER_2(s, d) {\ -+ SQUASHFS_SWAP_START\ -+ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ -+ sizeof(struct squashfs_symlink_inode_header_2));\ -+ SQUASHFS_SWAP((s)->symlink_size, d, 32, 16);\ -+} -+ -+#define SQUASHFS_SWAP_REG_INODE_HEADER_2(s, d) {\ -+ SQUASHFS_SWAP_START\ -+ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ -+ sizeof(struct squashfs_reg_inode_header_2));\ -+ SQUASHFS_SWAP((s)->mtime, d, 32, 32);\ -+ SQUASHFS_SWAP((s)->start_block, d, 64, 32);\ -+ SQUASHFS_SWAP((s)->fragment, d, 96, 32);\ -+ SQUASHFS_SWAP((s)->offset, d, 128, 32);\ -+ SQUASHFS_SWAP((s)->file_size, d, 160, 32);\ -+} -+ -+#define SQUASHFS_SWAP_DIR_INODE_HEADER_2(s, d) {\ -+ SQUASHFS_SWAP_START\ -+ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ -+ sizeof(struct squashfs_dir_inode_header_2));\ -+ SQUASHFS_SWAP((s)->file_size, d, 32, 19);\ -+ SQUASHFS_SWAP((s)->offset, d, 51, 13);\ -+ SQUASHFS_SWAP((s)->mtime, d, 64, 32);\ -+ SQUASHFS_SWAP((s)->start_block, d, 96, 24);\ -+} -+ -+#define SQUASHFS_SWAP_LDIR_INODE_HEADER_2(s, d) {\ -+ SQUASHFS_SWAP_START\ -+ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ -+ sizeof(struct squashfs_ldir_inode_header_2));\ -+ SQUASHFS_SWAP((s)->file_size, d, 32, 27);\ -+ SQUASHFS_SWAP((s)->offset, d, 59, 13);\ -+ SQUASHFS_SWAP((s)->mtime, d, 72, 32);\ -+ SQUASHFS_SWAP((s)->start_block, d, 104, 24);\ -+ SQUASHFS_SWAP((s)->i_count, d, 128, 16);\ -+} -+ -+#define SQUASHFS_SWAP_DIR_INDEX_2(s, d) {\ -+ SQUASHFS_SWAP_START\ -+ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_index_2));\ -+ SQUASHFS_SWAP((s)->index, d, 0, 27);\ -+ SQUASHFS_SWAP((s)->start_block, d, 27, 29);\ -+ SQUASHFS_SWAP((s)->size, d, 56, 8);\ -+} -+#define SQUASHFS_SWAP_DIR_HEADER_2(s, d) {\ -+ SQUASHFS_SWAP_START\ -+ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_header_2));\ -+ SQUASHFS_SWAP((s)->count, d, 0, 8);\ -+ SQUASHFS_SWAP((s)->start_block, d, 8, 24);\ -+} -+ -+#define SQUASHFS_SWAP_DIR_ENTRY_2(s, d) {\ -+ SQUASHFS_SWAP_START\ -+ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_entry_2));\ -+ SQUASHFS_SWAP((s)->offset, d, 0, 13);\ -+ SQUASHFS_SWAP((s)->type, d, 13, 3);\ -+ SQUASHFS_SWAP((s)->size, d, 16, 8);\ -+} -+ -+#define SQUASHFS_SWAP_FRAGMENT_ENTRY_2(s, d) {\ -+ SQUASHFS_SWAP_START\ -+ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_fragment_entry_2));\ -+ SQUASHFS_SWAP((s)->start_block, d, 0, 32);\ -+ SQUASHFS_SWAP((s)->size, d, 32, 32);\ -+} -+ -+#define SQUASHFS_SWAP_FRAGMENT_INDEXES_2(s, d, n) SQUASHFS_SWAP_INTS(s, d, n) -+ -+/* fragment and fragment table defines */ -+#define SQUASHFS_FRAGMENT_BYTES_2(A) (A * sizeof(struct squashfs_fragment_entry_2)) -+ -+#define SQUASHFS_FRAGMENT_INDEX_2(A) (SQUASHFS_FRAGMENT_BYTES_2(A) / \ -+ SQUASHFS_METADATA_SIZE) -+ -+#define SQUASHFS_FRAGMENT_INDEX_OFFSET_2(A) (SQUASHFS_FRAGMENT_BYTES_2(A) % \ -+ SQUASHFS_METADATA_SIZE) -+ -+#define SQUASHFS_FRAGMENT_INDEXES_2(A) ((SQUASHFS_FRAGMENT_BYTES_2(A) + \ -+ SQUASHFS_METADATA_SIZE - 1) / \ -+ SQUASHFS_METADATA_SIZE) -+ -+#define SQUASHFS_FRAGMENT_INDEX_BYTES_2(A) (SQUASHFS_FRAGMENT_INDEXES_2(A) *\ -+ sizeof(int)) -+ -+#endif -+ -+#ifdef __KERNEL__ -+ -+/* -+ * macros used to swap each structure entry, taking into account -+ * bitfields and different bitfield placing conventions on differing -+ * architectures -+ */ -+ -+#include -+ -+#ifdef __BIG_ENDIAN -+ /* convert from little endian to big endian */ -+#define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, \ -+ tbits, b_pos) -+#else -+ /* convert from big endian to little endian */ -+#define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, \ -+ tbits, 64 - tbits - b_pos) -+#endif -+ -+#define _SQUASHFS_SWAP(value, p, pos, tbits, SHIFT) {\ -+ b_pos = pos % 8;\ -+ val = 0;\ -+ s = (unsigned char *)p + (pos / 8);\ -+ d = ((unsigned char *) &val) + 7;\ -+ for(bits = 0; bits < (tbits + b_pos); bits += 8) \ -+ *d-- = *s++;\ -+ value = (val >> (SHIFT))/* & ((1 << tbits) - 1)*/;\ -+} -+ -+#define SQUASHFS_MEMSET(s, d, n) memset(s, 0, n); -+ -+#endif -+#endif ---- /dev/null -+++ b/include/linux/squashfs_fs_i.h -@@ -0,0 +1,45 @@ -+#ifndef SQUASHFS_FS_I -+#define SQUASHFS_FS_I -+/* -+ * Squashfs -+ * -+ * Copyright (c) 2002, 2003, 2004, 2005, 2006 -+ * Phillip Lougher -+ * -+ * 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, -+ * 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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -+ * -+ * squashfs_fs_i.h -+ */ -+ -+struct squashfs_inode_info { -+ long long start_block; -+ unsigned int offset; -+ union { -+ struct { -+ long long fragment_start_block; -+ unsigned int fragment_size; -+ unsigned int fragment_offset; -+ long long block_list_start; -+ } s1; -+ struct { -+ long long directory_index_start; -+ unsigned int directory_index_offset; -+ unsigned int directory_index_count; -+ unsigned int parent_inode; -+ } s2; -+ } u; -+ struct inode vfs_inode; -+}; -+#endif ---- /dev/null -+++ b/include/linux/squashfs_fs_sb.h -@@ -0,0 +1,74 @@ -+#ifndef SQUASHFS_FS_SB -+#define SQUASHFS_FS_SB -+/* -+ * Squashfs -+ * -+ * Copyright (c) 2002, 2003, 2004, 2005, 2006 -+ * Phillip Lougher -+ * -+ * 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, -+ * 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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -+ * -+ * squashfs_fs_sb.h -+ */ -+ -+#include -+ -+struct squashfs_cache { -+ long long block; -+ int length; -+ long long next_index; -+ char *data; -+}; -+ -+struct squashfs_fragment_cache { -+ long long block; -+ int length; -+ unsigned int locked; -+ char *data; -+}; -+ -+struct squashfs_sb_info { -+ struct squashfs_super_block sblk; -+ int devblksize; -+ int devblksize_log2; -+ int swap; -+ struct squashfs_cache *block_cache; -+ struct squashfs_fragment_cache *fragment; -+ int next_cache; -+ int next_fragment; -+ int next_meta_index; -+ unsigned int *uid; -+ unsigned int *guid; -+ long long *fragment_index; -+ unsigned int *fragment_index_2; -+ unsigned int read_size; -+ char *read_data; -+ char *read_page; -+ struct semaphore read_data_mutex; -+ struct semaphore read_page_mutex; -+ struct semaphore block_cache_mutex; -+ struct semaphore fragment_mutex; -+ struct semaphore meta_index_mutex; -+ wait_queue_head_t waitq; -+ wait_queue_head_t fragment_wait_queue; -+ struct meta_index *meta_index; -+ struct inode *(*iget)(struct super_block *s, squashfs_inode_t \ -+ inode); -+ long long (*read_blocklist)(struct inode *inode, int \ -+ index, int readahead_blks, char *block_list, \ -+ unsigned short **block_p, unsigned int *bsize); -+ int (*read_fragment_index_table)(struct super_block *s); -+}; -+#endif ---- a/init/do_mounts_rd.c -+++ b/init/do_mounts_rd.c -@@ -5,6 +5,7 @@ - #include - #include - #include -+#include - #include - #include - -@@ -37,6 +38,7 @@ static int __init crd_load(int in_fd, in - * numbers could not be found. - * - * We currently check for the following magic numbers: -+ * squashfs - * minix - * ext2 - * romfs -@@ -51,6 +53,7 @@ identify_ramdisk_image(int fd, int start - struct ext2_super_block *ext2sb; - struct romfs_super_block *romfsb; - struct cramfs_super *cramfsb; -+ struct squashfs_super_block *squashfsb; - int nblocks = -1; - unsigned char *buf; - -@@ -62,6 +65,7 @@ identify_ramdisk_image(int fd, int start - ext2sb = (struct ext2_super_block *) buf; - romfsb = (struct romfs_super_block *) buf; - cramfsb = (struct cramfs_super *) buf; -+ squashfsb = (struct squashfs_super_block *) buf; - memset(buf, 0xe5, size); - - /* -@@ -99,6 +103,15 @@ identify_ramdisk_image(int fd, int start - goto done; - } - -+ /* squashfs is at block zero too */ -+ if (squashfsb->s_magic == SQUASHFS_MAGIC) { -+ printk(KERN_NOTICE -+ "RAMDISK: squashfs filesystem found at block %d\n", -+ start_block); -+ nblocks = (squashfsb->bytes_used+BLOCK_SIZE-1)>>BLOCK_SIZE_BITS; -+ goto done; -+ } -+ - /* - * Read block 1 to test for minix and ext2 superblock - */ diff --git a/target/linux/generic-2.6/patches-2.6.28/002-lzma_decompress.patch b/target/linux/generic-2.6/patches-2.6.28/002-lzma_decompress.patch deleted file mode 100644 index 4c1578e26..000000000 --- a/target/linux/generic-2.6/patches-2.6.28/002-lzma_decompress.patch +++ /dev/null @@ -1,780 +0,0 @@ ---- /dev/null -+++ b/include/linux/LzmaDecode.h -@@ -0,0 +1,100 @@ -+/* -+ LzmaDecode.h -+ LZMA Decoder interface -+ -+ LZMA SDK 4.05 Copyright (c) 1999-2004 Igor Pavlov (2004-08-25) -+ http://www.7-zip.org/ -+ -+ LZMA SDK is licensed under two licenses: -+ 1) GNU Lesser General Public License (GNU LGPL) -+ 2) Common Public License (CPL) -+ It means that you can select one of these two licenses and -+ follow rules of that license. -+ -+ SPECIAL EXCEPTION: -+ Igor Pavlov, as the author of this code, expressly permits you to -+ statically or dynamically link your code (or bind by name) to the -+ interfaces of this file without subjecting your linked code to the -+ terms of the CPL or GNU LGPL. Any modifications or additions -+ to this file, however, are subject to the LGPL or CPL terms. -+*/ -+ -+#ifndef __LZMADECODE_H -+#define __LZMADECODE_H -+ -+/* #define _LZMA_IN_CB */ -+/* Use callback for input data */ -+ -+/* #define _LZMA_OUT_READ */ -+/* Use read function for output data */ -+ -+/* #define _LZMA_PROB32 */ -+/* It can increase speed on some 32-bit CPUs, -+ but memory usage will be doubled in that case */ -+ -+/* #define _LZMA_LOC_OPT */ -+/* Enable local speed optimizations inside code */ -+ -+#ifndef UInt32 -+#ifdef _LZMA_UINT32_IS_ULONG -+#define UInt32 unsigned long -+#else -+#define UInt32 unsigned int -+#endif -+#endif -+ -+#ifdef _LZMA_PROB32 -+#define CProb UInt32 -+#else -+#define CProb unsigned short -+#endif -+ -+#define LZMA_RESULT_OK 0 -+#define LZMA_RESULT_DATA_ERROR 1 -+#define LZMA_RESULT_NOT_ENOUGH_MEM 2 -+ -+#ifdef _LZMA_IN_CB -+typedef struct _ILzmaInCallback -+{ -+ int (*Read)(void *object, unsigned char **buffer, UInt32 *bufferSize); -+} ILzmaInCallback; -+#endif -+ -+#define LZMA_BASE_SIZE 1846 -+#define LZMA_LIT_SIZE 768 -+ -+/* -+bufferSize = (LZMA_BASE_SIZE + (LZMA_LIT_SIZE << (lc + lp)))* sizeof(CProb) -+bufferSize += 100 in case of _LZMA_OUT_READ -+by default CProb is unsigned short, -+but if specify _LZMA_PROB_32, CProb will be UInt32(unsigned int) -+*/ -+ -+#ifdef _LZMA_OUT_READ -+int LzmaDecoderInit( -+ unsigned char *buffer, UInt32 bufferSize, -+ int lc, int lp, int pb, -+ unsigned char *dictionary, UInt32 dictionarySize, -+ #ifdef _LZMA_IN_CB -+ ILzmaInCallback *inCallback -+ #else -+ unsigned char *inStream, UInt32 inSize -+ #endif -+); -+#endif -+ -+int LzmaDecode( -+ unsigned char *buffer, -+ #ifndef _LZMA_OUT_READ -+ UInt32 bufferSize, -+ int lc, int lp, int pb, -+ #ifdef _LZMA_IN_CB -+ ILzmaInCallback *inCallback, -+ #else -+ unsigned char *inStream, UInt32 inSize, -+ #endif -+ #endif -+ unsigned char *outStream, UInt32 outSize, -+ UInt32 *outSizeProcessed); -+ -+#endif ---- /dev/null -+++ b/lib/LzmaDecode.c -@@ -0,0 +1,663 @@ -+/* -+ LzmaDecode.c -+ LZMA Decoder -+ -+ LZMA SDK 4.05 Copyright (c) 1999-2004 Igor Pavlov (2004-08-25) -+ http://www.7-zip.org/ -+ -+ LZMA SDK is licensed under two licenses: -+ 1) GNU Lesser General Public License (GNU LGPL) -+ 2) Common Public License (CPL) -+ It means that you can select one of these two licenses and -+ follow rules of that license. -+ -+ SPECIAL EXCEPTION: -+ Igor Pavlov, as the author of this code, expressly permits you to -+ statically or dynamically link your code (or bind by name) to the -+ interfaces of this file without subjecting your linked code to the -+ terms of the CPL or GNU LGPL. Any modifications or additions -+ to this file, however, are subject to the LGPL or CPL terms. -+*/ -+ -+#include -+ -+#ifndef Byte -+#define Byte unsigned char -+#endif -+ -+#define kNumTopBits 24 -+#define kTopValue ((UInt32)1 << kNumTopBits) -+ -+#define kNumBitModelTotalBits 11 -+#define kBitModelTotal (1 << kNumBitModelTotalBits) -+#define kNumMoveBits 5 -+ -+typedef struct _CRangeDecoder -+{ -+ Byte *Buffer; -+ Byte *BufferLim; -+ UInt32 Range; -+ UInt32 Code; -+ #ifdef _LZMA_IN_CB -+ ILzmaInCallback *InCallback; -+ int Result; -+ #endif -+ int ExtraBytes; -+} CRangeDecoder; -+ -+Byte RangeDecoderReadByte(CRangeDecoder *rd) -+{ -+ if (rd->Buffer == rd->BufferLim) -+ { -+ #ifdef _LZMA_IN_CB -+ UInt32 size; -+ rd->Result = rd->InCallback->Read(rd->InCallback, &rd->Buffer, &size); -+ rd->BufferLim = rd->Buffer + size; -+ if (size == 0) -+ #endif -+ { -+ rd->ExtraBytes = 1; -+ return 0xFF; -+ } -+ } -+ return (*rd->Buffer++); -+} -+ -+/* #define ReadByte (*rd->Buffer++) */ -+#define ReadByte (RangeDecoderReadByte(rd)) -+ -+void RangeDecoderInit(CRangeDecoder *rd, -+ #ifdef _LZMA_IN_CB -+ ILzmaInCallback *inCallback -+ #else -+ Byte *stream, UInt32 bufferSize -+ #endif -+ ) -+{ -+ int i; -+ #ifdef _LZMA_IN_CB -+ rd->InCallback = inCallback; -+ rd->Buffer = rd->BufferLim = 0; -+ #else -+ rd->Buffer = stream; -+ rd->BufferLim = stream + bufferSize; -+ #endif -+ rd->ExtraBytes = 0; -+ rd->Code = 0; -+ rd->Range = (0xFFFFFFFF); -+ for(i = 0; i < 5; i++) -+ rd->Code = (rd->Code << 8) | ReadByte; -+} -+ -+#define RC_INIT_VAR UInt32 range = rd->Range; UInt32 code = rd->Code; -+#define RC_FLUSH_VAR rd->Range = range; rd->Code = code; -+#define RC_NORMALIZE if (range < kTopValue) { range <<= 8; code = (code << 8) | ReadByte; } -+ -+UInt32 RangeDecoderDecodeDirectBits(CRangeDecoder *rd, int numTotalBits) -+{ -+ RC_INIT_VAR -+ UInt32 result = 0; -+ int i; -+ for (i = numTotalBits; i > 0; i--) -+ { -+ /* UInt32 t; */ -+ range >>= 1; -+ -+ result <<= 1; -+ if (code >= range) -+ { -+ code -= range; -+ result |= 1; -+ } -+ /* -+ t = (code - range) >> 31; -+ t &= 1; -+ code -= range & (t - 1); -+ result = (result + result) | (1 - t); -+ */ -+ RC_NORMALIZE -+ } -+ RC_FLUSH_VAR -+ return result; -+} -+ -+int RangeDecoderBitDecode(CProb *prob, CRangeDecoder *rd) -+{ -+ UInt32 bound = (rd->Range >> kNumBitModelTotalBits) * *prob; -+ if (rd->Code < bound) -+ { -+ rd->Range = bound; -+ *prob += (kBitModelTotal - *prob) >> kNumMoveBits; -+ if (rd->Range < kTopValue) -+ { -+ rd->Code = (rd->Code << 8) | ReadByte; -+ rd->Range <<= 8; -+ } -+ return 0; -+ } -+ else -+ { -+ rd->Range -= bound; -+ rd->Code -= bound; -+ *prob -= (*prob) >> kNumMoveBits; -+ if (rd->Range < kTopValue) -+ { -+ rd->Code = (rd->Code << 8) | ReadByte; -+ rd->Range <<= 8; -+ } -+ return 1; -+ } -+} -+ -+#define RC_GET_BIT2(prob, mi, A0, A1) \ -+ UInt32 bound = (range >> kNumBitModelTotalBits) * *prob; \ -+ if (code < bound) \ -+ { A0; range = bound; *prob += (kBitModelTotal - *prob) >> kNumMoveBits; mi <<= 1; } \ -+ else \ -+ { A1; range -= bound; code -= bound; *prob -= (*prob) >> kNumMoveBits; mi = (mi + mi) + 1; } \ -+ RC_NORMALIZE -+ -+#define RC_GET_BIT(prob, mi) RC_GET_BIT2(prob, mi, ; , ;) -+ -+int RangeDecoderBitTreeDecode(CProb *probs, int numLevels, CRangeDecoder *rd) -+{ -+ int mi = 1; -+ int i; -+ #ifdef _LZMA_LOC_OPT -+ RC_INIT_VAR -+ #endif -+ for(i = numLevels; i > 0; i--) -+ { -+ #ifdef _LZMA_LOC_OPT -+ CProb *prob = probs + mi; -+ RC_GET_BIT(prob, mi) -+ #else -+ mi = (mi + mi) + RangeDecoderBitDecode(probs + mi, rd); -+ #endif -+ } -+ #ifdef _LZMA_LOC_OPT -+ RC_FLUSH_VAR -+ #endif -+ return mi - (1 << numLevels); -+} -+ -+int RangeDecoderReverseBitTreeDecode(CProb *probs, int numLevels, CRangeDecoder *rd) -+{ -+ int mi = 1; -+ int i; -+ int symbol = 0; -+ #ifdef _LZMA_LOC_OPT -+ RC_INIT_VAR -+ #endif -+ for(i = 0; i < numLevels; i++) -+ { -+ #ifdef _LZMA_LOC_OPT -+ CProb *prob = probs + mi; -+ RC_GET_BIT2(prob, mi, ; , symbol |= (1 << i)) -+ #else -+ int bit = RangeDecoderBitDecode(probs + mi, rd); -+ mi = mi + mi + bit; -+ symbol |= (bit << i); -+ #endif -+ } -+ #ifdef _LZMA_LOC_OPT -+ RC_FLUSH_VAR -+ #endif -+ return symbol; -+} -+ -+Byte LzmaLiteralDecode(CProb *probs, CRangeDecoder *rd) -+{ -+ int symbol = 1; -+ #ifdef _LZMA_LOC_OPT -+ RC_INIT_VAR -+ #endif -+ do -+ { -+ #ifdef _LZMA_LOC_OPT -+ CProb *prob = probs + symbol; -+ RC_GET_BIT(prob, symbol) -+ #else -+ symbol = (symbol + symbol) | RangeDecoderBitDecode(probs + symbol, rd); -+ #endif -+ } -+ while (symbol < 0x100); -+ #ifdef _LZMA_LOC_OPT -+ RC_FLUSH_VAR -+ #endif -+ return symbol; -+} -+ -+Byte LzmaLiteralDecodeMatch(CProb *probs, CRangeDecoder *rd, Byte matchByte) -+{ -+ int symbol = 1; -+ #ifdef _LZMA_LOC_OPT -+ RC_INIT_VAR -+ #endif -+ do -+ { -+ int bit; -+ int matchBit = (matchByte >> 7) & 1; -+ matchByte <<= 1; -+ #ifdef _LZMA_LOC_OPT -+ { -+ CProb *prob = probs + ((1 + matchBit) << 8) + symbol; -+ RC_GET_BIT2(prob, symbol, bit = 0, bit = 1) -+ } -+ #else -+ bit = RangeDecoderBitDecode(probs + ((1 + matchBit) << 8) + symbol, rd); -+ symbol = (symbol << 1) | bit; -+ #endif -+ if (matchBit != bit) -+ { -+ while (symbol < 0x100) -+ { -+ #ifdef _LZMA_LOC_OPT -+ CProb *prob = probs + symbol; -+ RC_GET_BIT(prob, symbol) -+ #else -+ symbol = (symbol + symbol) | RangeDecoderBitDecode(probs + symbol, rd); -+ #endif -+ } -+ break; -+ } -+ } -+ while (symbol < 0x100); -+ #ifdef _LZMA_LOC_OPT -+ RC_FLUSH_VAR -+ #endif -+ return symbol; -+} -+ -+#define kNumPosBitsMax 4 -+#define kNumPosStatesMax (1 << kNumPosBitsMax) -+ -+#define kLenNumLowBits 3 -+#define kLenNumLowSymbols (1 << kLenNumLowBits) -+#define kLenNumMidBits 3 -+#define kLenNumMidSymbols (1 << kLenNumMidBits) -+#define kLenNumHighBits 8 -+#define kLenNumHighSymbols (1 << kLenNumHighBits) -+ -+#define LenChoice 0 -+#define LenChoice2 (LenChoice + 1) -+#define LenLow (LenChoice2 + 1) -+#define LenMid (LenLow + (kNumPosStatesMax << kLenNumLowBits)) -+#define LenHigh (LenMid + (kNumPosStatesMax << kLenNumMidBits)) -+#define kNumLenProbs (LenHigh + kLenNumHighSymbols) -+ -+int LzmaLenDecode(CProb *p, CRangeDecoder *rd, int posState) -+{ -+ if(RangeDecoderBitDecode(p + LenChoice, rd) == 0) -+ return RangeDecoderBitTreeDecode(p + LenLow + -+ (posState << kLenNumLowBits), kLenNumLowBits, rd); -+ if(RangeDecoderBitDecode(p + LenChoice2, rd) == 0) -+ return kLenNumLowSymbols + RangeDecoderBitTreeDecode(p + LenMid + -+ (posState << kLenNumMidBits), kLenNumMidBits, rd); -+ return kLenNumLowSymbols + kLenNumMidSymbols + -+ RangeDecoderBitTreeDecode(p + LenHigh, kLenNumHighBits, rd); -+} -+ -+#define kNumStates 12 -+ -+#define kStartPosModelIndex 4 -+#define kEndPosModelIndex 14 -+#define kNumFullDistances (1 << (kEndPosModelIndex >> 1)) -+ -+#define kNumPosSlotBits 6 -+#define kNumLenToPosStates 4 -+ -+#define kNumAlignBits 4 -+#define kAlignTableSize (1 << kNumAlignBits) -+ -+#define kMatchMinLen 2 -+ -+#define IsMatch 0 -+#define IsRep (IsMatch + (kNumStates << kNumPosBitsMax)) -+#define IsRepG0 (IsRep + kNumStates) -+#define IsRepG1 (IsRepG0 + kNumStates) -+#define IsRepG2 (IsRepG1 + kNumStates) -+#define IsRep0Long (IsRepG2 + kNumStates) -+#define PosSlot (IsRep0Long + (kNumStates << kNumPosBitsMax)) -+#define SpecPos (PosSlot + (kNumLenToPosStates << kNumPosSlotBits)) -+#define Align (SpecPos + kNumFullDistances - kEndPosModelIndex) -+#define LenCoder (Align + kAlignTableSize) -+#define RepLenCoder (LenCoder + kNumLenProbs) -+#define Literal (RepLenCoder + kNumLenProbs) -+ -+#if Literal != LZMA_BASE_SIZE -+StopCompilingDueBUG -+#endif -+ -+#ifdef _LZMA_OUT_READ -+ -+typedef struct _LzmaVarState -+{ -+ CRangeDecoder RangeDecoder; -+ Byte *Dictionary; -+ UInt32 DictionarySize; -+ UInt32 DictionaryPos; -+ UInt32 GlobalPos; -+ UInt32 Reps[4]; -+ int lc; -+ int lp; -+ int pb; -+ int State; -+ int PreviousIsMatch; -+ int RemainLen; -+} LzmaVarState; -+ -+int LzmaDecoderInit( -+ unsigned char *buffer, UInt32 bufferSize, -+ int lc, int lp, int pb, -+ unsigned char *dictionary, UInt32 dictionarySize, -+ #ifdef _LZMA_IN_CB -+ ILzmaInCallback *inCallback -+ #else -+ unsigned char *inStream, UInt32 inSize -+ #endif -+ ) -+{ -+ LzmaVarState *vs = (LzmaVarState *)buffer; -+ CProb *p = (CProb *)(buffer + sizeof(LzmaVarState)); -+ UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (lc + lp)); -+ UInt32 i; -+ if (bufferSize < numProbs * sizeof(CProb) + sizeof(LzmaVarState)) -+ return LZMA_RESULT_NOT_ENOUGH_MEM; -+ vs->Dictionary = dictionary; -+ vs->DictionarySize = dictionarySize; -+ vs->DictionaryPos = 0; -+ vs->GlobalPos = 0; -+ vs->Reps[0] = vs->Reps[1] = vs->Reps[2] = vs->Reps[3] = 1; -+ vs->lc = lc; -+ vs->lp = lp; -+ vs->pb = pb; -+ vs->State = 0; -+ vs->PreviousIsMatch = 0; -+ vs->RemainLen = 0; -+ dictionary[dictionarySize - 1] = 0; -+ for (i = 0; i < numProbs; i++) -+ p[i] = kBitModelTotal >> 1; -+ RangeDecoderInit(&vs->RangeDecoder, -+ #ifdef _LZMA_IN_CB -+ inCallback -+ #else -+ inStream, inSize -+ #endif -+ ); -+ return LZMA_RESULT_OK; -+} -+ -+int LzmaDecode(unsigned char *buffer, -+ unsigned char *outStream, UInt32 outSize, -+ UInt32 *outSizeProcessed) -+{ -+ LzmaVarState *vs = (LzmaVarState *)buffer; -+ CProb *p = (CProb *)(buffer + sizeof(LzmaVarState)); -+ CRangeDecoder rd = vs->RangeDecoder; -+ int state = vs->State; -+ int previousIsMatch = vs->PreviousIsMatch; -+ Byte previousByte; -+ UInt32 rep0 = vs->Reps[0], rep1 = vs->Reps[1], rep2 = vs->Reps[2], rep3 = vs->Reps[3]; -+ UInt32 nowPos = 0; -+ UInt32 posStateMask = (1 << (vs->pb)) - 1; -+ UInt32 literalPosMask = (1 << (vs->lp)) - 1; -+ int lc = vs->lc; -+ int len = vs->RemainLen; -+ UInt32 globalPos = vs->GlobalPos; -+ -+ Byte *dictionary = vs->Dictionary; -+ UInt32 dictionarySize = vs->DictionarySize; -+ UInt32 dictionaryPos = vs->DictionaryPos; -+ -+ if (len == -1) -+ { -+ *outSizeProcessed = 0; -+ return LZMA_RESULT_OK; -+ } -+ -+ while(len > 0 && nowPos < outSize) -+ { -+ UInt32 pos = dictionaryPos - rep0; -+ if (pos >= dictionarySize) -+ pos += dictionarySize; -+ outStream[nowPos++] = dictionary[dictionaryPos] = dictionary[pos]; -+ if (++dictionaryPos == dictionarySize) -+ dictionaryPos = 0; -+ len--; -+ } -+ if (dictionaryPos == 0) -+ previousByte = dictionary[dictionarySize - 1]; -+ else -+ previousByte = dictionary[dictionaryPos - 1]; -+#else -+ -+int LzmaDecode( -+ Byte *buffer, UInt32 bufferSize, -+ int lc, int lp, int pb, -+ #ifdef _LZMA_IN_CB -+ ILzmaInCallback *inCallback, -+ #else -+ unsigned char *inStream, UInt32 inSize, -+ #endif -+ unsigned char *outStream, UInt32 outSize, -+ UInt32 *outSizeProcessed) -+{ -+ UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (lc + lp)); -+ CProb *p = (CProb *)buffer; -+ CRangeDecoder rd; -+ UInt32 i; -+ int state = 0; -+ int previousIsMatch = 0; -+ Byte previousByte = 0; -+ UInt32 rep0 = 1, rep1 = 1, rep2 = 1, rep3 = 1; -+ UInt32 nowPos = 0; -+ UInt32 posStateMask = (1 << pb) - 1; -+ UInt32 literalPosMask = (1 << lp) - 1; -+ int len = 0; -+ if (bufferSize < numProbs * sizeof(CProb)) -+ return LZMA_RESULT_NOT_ENOUGH_MEM; -+ for (i = 0; i < numProbs; i++) -+ p[i] = kBitModelTotal >> 1; -+ RangeDecoderInit(&rd, -+ #ifdef _LZMA_IN_CB -+ inCallback -+ #else -+ inStream, inSize -+ #endif -+ ); -+#endif -+ -+ *outSizeProcessed = 0; -+ while(nowPos < outSize) -+ { -+ int posState = (int)( -+ (nowPos -+ #ifdef _LZMA_OUT_READ -+ + globalPos -+ #endif -+ ) -+ & posStateMask); -+ #ifdef _LZMA_IN_CB -+ if (rd.Result != LZMA_RESULT_OK) -+ return rd.Result; -+ #endif -+ if (rd.ExtraBytes != 0) -+ return LZMA_RESULT_DATA_ERROR; -+ if (RangeDecoderBitDecode(p + IsMatch + (state << kNumPosBitsMax) + posState, &rd) == 0) -+ { -+ CProb *probs = p + Literal + (LZMA_LIT_SIZE * -+ ((( -+ (nowPos -+ #ifdef _LZMA_OUT_READ -+ + globalPos -+ #endif -+ ) -+ & literalPosMask) << lc) + (previousByte >> (8 - lc)))); -+ -+ if (state < 4) state = 0; -+ else if (state < 10) state -= 3; -+ else state -= 6; -+ if (previousIsMatch) -+ { -+ Byte matchByte; -+ #ifdef _LZMA_OUT_READ -+ UInt32 pos = dictionaryPos - rep0; -+ if (pos >= dictionarySize) -+ pos += dictionarySize; -+ matchByte = dictionary[pos]; -+ #else -+ matchByte = outStream[nowPos - rep0]; -+ #endif -+ previousByte = LzmaLiteralDecodeMatch(probs, &rd, matchByte); -+ previousIsMatch = 0; -+ } -+ else -+ previousByte = LzmaLiteralDecode(probs, &rd); -+ outStream[nowPos++] = previousByte; -+ #ifdef _LZMA_OUT_READ -+ dictionary[dictionaryPos] = previousByte; -+ if (++dictionaryPos == dictionarySize) -+ dictionaryPos = 0; -+ #endif -+ } -+ else -+ { -+ previousIsMatch = 1; -+ if (RangeDecoderBitDecode(p + IsRep + state, &rd) == 1) -+ { -+ if (RangeDecoderBitDecode(p + IsRepG0 + state, &rd) == 0) -+ { -+ if (RangeDecoderBitDecode(p + IsRep0Long + (state << kNumPosBitsMax) + posState, &rd) == 0) -+ { -+ #ifdef _LZMA_OUT_READ -+ UInt32 pos; -+ #endif -+ if ( -+ (nowPos -+ #ifdef _LZMA_OUT_READ -+ + globalPos -+ #endif -+ ) -+ == 0) -+ return LZMA_RESULT_DATA_ERROR; -+ state = state < 7 ? 9 : 11; -+ #ifdef _LZMA_OUT_READ -+ pos = dictionaryPos - rep0; -+ if (pos >= dictionarySize) -+ pos += dictionarySize; -+ previousByte = dictionary[pos]; -+ dictionary[dictionaryPos] = previousByte; -+ if (++dictionaryPos == dictionarySize) -+ dictionaryPos = 0; -+ #else -+ previousByte = outStream[nowPos - rep0]; -+ #endif -+ outStream[nowPos++] = previousByte; -+ continue; -+ } -+ } -+ else -+ { -+ UInt32 distance; -+ if(RangeDecoderBitDecode(p + IsRepG1 + state, &rd) == 0) -+ distance = rep1; -+ else -+ { -+ if(RangeDecoderBitDecode(p + IsRepG2 + state, &rd) == 0) -+ distance = rep2; -+ else -+ { -+ distance = rep3; -+ rep3 = rep2; -+ } -+ rep2 = rep1; -+ } -+ rep1 = rep0; -+ rep0 = distance; -+ } -+ len = LzmaLenDecode(p + RepLenCoder, &rd, posState); -+ state = state < 7 ? 8 : 11; -+ } -+ else -+ { -+ int posSlot; -+ rep3 = rep2; -+ rep2 = rep1; -+ rep1 = rep0; -+ state = state < 7 ? 7 : 10; -+ len = LzmaLenDecode(p + LenCoder, &rd, posState); -+ posSlot = RangeDecoderBitTreeDecode(p + PosSlot + -+ ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) << -+ kNumPosSlotBits), kNumPosSlotBits, &rd); -+ if (posSlot >= kStartPosModelIndex) -+ { -+ int numDirectBits = ((posSlot >> 1) - 1); -+ rep0 = ((2 | ((UInt32)posSlot & 1)) << numDirectBits); -+ if (posSlot < kEndPosModelIndex) -+ { -+ rep0 += RangeDecoderReverseBitTreeDecode( -+ p + SpecPos + rep0 - posSlot - 1, numDirectBits, &rd); -+ } -+ else -+ { -+ rep0 += RangeDecoderDecodeDirectBits(&rd, -+ numDirectBits - kNumAlignBits) << kNumAlignBits; -+ rep0 += RangeDecoderReverseBitTreeDecode(p + Align, kNumAlignBits, &rd); -+ } -+ } -+ else -+ rep0 = posSlot; -+ rep0++; -+ } -+ if (rep0 == (UInt32)(0)) -+ { -+ /* it's for stream version */ -+ len = -1; -+ break; -+ } -+ if (rep0 > nowPos -+ #ifdef _LZMA_OUT_READ -+ + globalPos -+ #endif -+ ) -+ { -+ return LZMA_RESULT_DATA_ERROR; -+ } -+ len += kMatchMinLen; -+ do -+ { -+ #ifdef _LZMA_OUT_READ -+ UInt32 pos = dictionaryPos - rep0; -+ if (pos >= dictionarySize) -+ pos += dictionarySize; -+ previousByte = dictionary[pos]; -+ dictionary[dictionaryPos] = previousByte; -+ if (++dictionaryPos == dictionarySize) -+ dictionaryPos = 0; -+ #else -+ previousByte = outStream[nowPos - rep0]; -+ #endif -+ outStream[nowPos++] = previousByte; -+ len--; -+ } -+ while(len > 0 && nowPos < outSize); -+ } -+ } -+ -+ #ifdef _LZMA_OUT_READ -+ vs->RangeDecoder = rd; -+ vs->DictionaryPos = dictionaryPos; -+ vs->GlobalPos = globalPos + nowPos; -+ vs->Reps[0] = rep0; -+ vs->Reps[1] = rep1; -+ vs->Reps[2] = rep2; -+ vs->Reps[3] = rep3; -+ vs->State = state; -+ vs->PreviousIsMatch = previousIsMatch; -+ vs->RemainLen = len; -+ #endif -+ -+ *outSizeProcessed = nowPos; -+ return LZMA_RESULT_OK; -+} ---- a/lib/Makefile -+++ b/lib/Makefile -@@ -20,7 +20,7 @@ lib-y += kobject.o kref.o klist.o - - obj-y += bcd.o div64.o sort.o parser.o halfmd4.o debug_locks.o random32.o \ - bust_spinlocks.o hexdump.o kasprintf.o bitmap.o scatterlist.o \ -- string_helpers.o -+ string_helpers.o LzmaDecode.o - - ifeq ($(CONFIG_DEBUG_KOBJECT),y) - CFLAGS_kobject.o += -DDEBUG diff --git a/target/linux/generic-2.6/patches-2.6.28/003-squashfs_lzma.patch b/target/linux/generic-2.6/patches-2.6.28/003-squashfs_lzma.patch deleted file mode 100644 index 9050e370c..000000000 --- a/target/linux/generic-2.6/patches-2.6.28/003-squashfs_lzma.patch +++ /dev/null @@ -1,107 +0,0 @@ ---- a/fs/squashfs/inode.c -+++ b/fs/squashfs/inode.c -@@ -4,6 +4,9 @@ - * Copyright (c) 2002, 2003, 2004, 2005, 2006 - * Phillip Lougher - * -+ * LZMA decompressor support added by Oleg I. Vdovikin -+ * Copyright (c) 2005 Oleg I.Vdovikin -+ * - * 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, -@@ -21,6 +24,7 @@ - * inode.c - */ - -+#define SQUASHFS_LZMA - #include - #include - #include -@@ -44,6 +48,19 @@ - - #include "squashfs.h" - -+#ifdef SQUASHFS_LZMA -+#include -+ -+/* default LZMA settings, should be in sync with mksquashfs */ -+#define LZMA_LC 3 -+#define LZMA_LP 0 -+#define LZMA_PB 2 -+ -+#define LZMA_WORKSPACE_SIZE ((LZMA_BASE_SIZE + \ -+ (LZMA_LIT_SIZE << (LZMA_LC + LZMA_LP))) * sizeof(CProb)) -+ -+#endif -+ - static void squashfs_put_super(struct super_block *); - static int squashfs_statfs(struct dentry *, struct kstatfs *); - static int squashfs_symlink_readpage(struct file *file, struct page *page); -@@ -64,7 +81,11 @@ static int squashfs_get_sb(struct file_s - const char *, void *, struct vfsmount *); - - -+#ifdef SQUASHFS_LZMA -+static unsigned char lzma_workspace[LZMA_WORKSPACE_SIZE]; -+#else - static z_stream stream; -+#endif - - static struct file_system_type squashfs_fs_type = { - .owner = THIS_MODULE, -@@ -249,6 +270,15 @@ SQSH_EXTERN unsigned int squashfs_read_d - if (compressed) { - int zlib_err; - -+#ifdef SQUASHFS_LZMA -+ if ((zlib_err = LzmaDecode(lzma_workspace, -+ LZMA_WORKSPACE_SIZE, LZMA_LC, LZMA_LP, LZMA_PB, -+ c_buffer, c_byte, buffer, msblk->read_size, &bytes)) != LZMA_RESULT_OK) -+ { -+ ERROR("lzma returned unexpected result 0x%x\n", zlib_err); -+ bytes = 0; -+ } -+#else - stream.next_in = c_buffer; - stream.avail_in = c_byte; - stream.next_out = buffer; -@@ -263,7 +293,7 @@ SQSH_EXTERN unsigned int squashfs_read_d - bytes = 0; - } else - bytes = stream.total_out; -- -+#endif - up(&msblk->read_data_mutex); - } - -@@ -2045,15 +2075,19 @@ static int __init init_squashfs_fs(void) - printk(KERN_INFO "squashfs: version 3.0 (2006/03/15) " - "Phillip Lougher\n"); - -+#ifndef SQUASHFS_LZMA - if (!(stream.workspace = vmalloc(zlib_inflate_workspacesize()))) { - ERROR("Failed to allocate zlib workspace\n"); - destroy_inodecache(); - err = -ENOMEM; - goto out; - } -+#endif - - if ((err = register_filesystem(&squashfs_fs_type))) { -+#ifndef SQUASHFS_LZMA - vfree(stream.workspace); -+#endif - destroy_inodecache(); - } - -@@ -2064,7 +2098,9 @@ out: - - static void __exit exit_squashfs_fs(void) - { -+#ifndef SQUASHFS_LZMA - vfree(stream.workspace); -+#endif - unregister_filesystem(&squashfs_fs_type); - destroy_inodecache(); - } diff --git a/target/linux/generic-2.6/patches-2.6.28/004-extra_optimization.patch b/target/linux/generic-2.6/patches-2.6.28/004-extra_optimization.patch deleted file mode 100644 index 8827ed0c3..000000000 --- a/target/linux/generic-2.6/patches-2.6.28/004-extra_optimization.patch +++ /dev/null @@ -1,21 +0,0 @@ ---- a/Makefile -+++ b/Makefile -@@ -512,7 +512,7 @@ all: vmlinux - ifdef CONFIG_CC_OPTIMIZE_FOR_SIZE - KBUILD_CFLAGS += -Os - else --KBUILD_CFLAGS += -O2 -+KBUILD_CFLAGS += -O2 -fno-reorder-blocks -fno-tree-ch - endif - - include $(srctree)/arch/$(SRCARCH)/Makefile -@@ -549,6 +549,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,) - diff --git a/target/linux/generic-2.6/patches-2.6.28/005-squashfs_fix.patch b/target/linux/generic-2.6/patches-2.6.28/005-squashfs_fix.patch deleted file mode 100644 index 51474864e..000000000 --- a/target/linux/generic-2.6/patches-2.6.28/005-squashfs_fix.patch +++ /dev/null @@ -1,29 +0,0 @@ ---- a/fs/squashfs/inode.c -+++ b/fs/squashfs/inode.c -@@ -33,6 +33,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -43,8 +44,8 @@ - #include - #include - #include -+#include - #include --#include - - #include "squashfs.h" - -@@ -2125,7 +2126,7 @@ static void squashfs_destroy_inode(struc - } - - --static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flags) -+static void init_once(void *foo) - { - struct squashfs_inode_info *ei = foo; - diff --git a/target/linux/generic-2.6/patches-2.6.28/006-gcc4_inline_fix.patch b/target/linux/generic-2.6/patches-2.6.28/006-gcc4_inline_fix.patch deleted file mode 100644 index 642f11b21..000000000 --- a/target/linux/generic-2.6/patches-2.6.28/006-gcc4_inline_fix.patch +++ /dev/null @@ -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: diff --git a/target/linux/generic-2.6/patches-2.6.28/007-samsung_flash.patch b/target/linux/generic-2.6/patches-2.6.28/007-samsung_flash.patch deleted file mode 100644 index abb753c40..000000000 --- a/target/linux/generic-2.6/patches-2.6.28/007-samsung_flash.patch +++ /dev/null @@ -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 *); -@@ -365,12 +366,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 */ diff --git a/target/linux/generic-2.6/patches-2.6.28/008-squashfs_vfs_super.patch b/target/linux/generic-2.6/patches-2.6.28/008-squashfs_vfs_super.patch deleted file mode 100644 index f1dc2d751..000000000 --- a/target/linux/generic-2.6/patches-2.6.28/008-squashfs_vfs_super.patch +++ /dev/null @@ -1,11 +0,0 @@ ---- a/fs/squashfs/inode.c -+++ b/fs/squashfs/inode.c -@@ -1179,7 +1179,7 @@ failure: - - static int squashfs_statfs(struct dentry *dentry, struct kstatfs *buf) - { -- struct squashfs_sb_info *msblk = dentry->d_inode->i_sb->s_fs_info; -+ struct squashfs_sb_info *msblk = dentry->d_sb->s_fs_info; - struct squashfs_super_block *sblk = &msblk->sblk; - - TRACE("Entered squashfs_statfs\n"); diff --git a/target/linux/generic-2.6/patches-2.6.28/010-disable_old_squashfs_compatibility.patch b/target/linux/generic-2.6/patches-2.6.28/010-disable_old_squashfs_compatibility.patch deleted file mode 100644 index 01e27573b..000000000 --- a/target/linux/generic-2.6/patches-2.6.28/010-disable_old_squashfs_compatibility.patch +++ /dev/null @@ -1,19 +0,0 @@ ---- a/fs/squashfs/Makefile -+++ b/fs/squashfs/Makefile -@@ -4,4 +4,3 @@ - - obj-$(CONFIG_SQUASHFS) += squashfs.o - squashfs-y += inode.o --squashfs-y += squashfs2_0.o ---- a/fs/squashfs/squashfs.h -+++ b/fs/squashfs/squashfs.h -@@ -24,6 +24,9 @@ - #ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY - #undef CONFIG_SQUASHFS_1_0_COMPATIBILITY - #endif -+#ifdef CONFIG_SQUASHFS_2_0_COMPATIBILITY -+#undef CONFIG_SQUASHFS_2_0_COMPATIBILITY -+#endif - - #ifdef SQUASHFS_TRACE - #define TRACE(s, args...) printk(KERN_NOTICE "SQUASHFS: "s, ## args) diff --git a/target/linux/generic-2.6/patches-2.6.28/011-mips_boot.patch b/target/linux/generic-2.6/patches-2.6.28/011-mips_boot.patch deleted file mode 100644 index c2a043acd..000000000 --- a/target/linux/generic-2.6/patches-2.6.28/011-mips_boot.patch +++ /dev/null @@ -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. diff --git a/target/linux/generic-2.6/patches-2.6.28/020-mips_multi_machine_support.patch b/target/linux/generic-2.6/patches-2.6.28/020-mips_multi_machine_support.patch deleted file mode 100644 index af5511061..000000000 --- a/target/linux/generic-2.6/patches-2.6.28/020-mips_multi_machine_support.patch +++ /dev/null @@ -1,157 +0,0 @@ ---- /dev/null -+++ b/include/asm-mips/mips_machine.h -@@ -0,0 +1,47 @@ -+/* -+ * Copyright (C) 2008 Gabor Juhos -+ * -+ * 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 -+#include -+ -+#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 -+ * -+ * 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 -+#include -+ -+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 -@@ -84,6 +84,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 -@@ -763,6 +763,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 - #include - #include -+#include - - 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", diff --git a/target/linux/generic-2.6/patches-2.6.28/021-mips_image_cmdline_hack.patch b/target/linux/generic-2.6/patches-2.6.28/021-mips_image_cmdline_hack.patch deleted file mode 100644 index ec2dfce56..000000000 --- a/target/linux/generic-2.6/patches-2.6.28/021-mips_image_cmdline_hack.patch +++ /dev/null @@ -1,28 +0,0 @@ ---- a/arch/mips/Kconfig -+++ b/arch/mips/Kconfig -@@ -766,6 +766,10 @@ config SYNC_R4K - config MIPS_MACHINE - def_bool n - -+config IMAGE_CMDLINE_HACK -+ bool "OpenWrt specific image command line hack" -+ default n -+ - config NO_IOPORT - def_bool n - ---- a/arch/mips/kernel/head.S -+++ b/arch/mips/kernel/head.S -@@ -143,6 +143,12 @@ FEXPORT(__kernel_entry) - j kernel_entry - #endif - -+#ifdef CONFIG_IMAGE_CMDLINE_HACK -+ .ascii "CMDLINE:" -+EXPORT(__image_cmdline) -+ .fill 0x400 -+#endif /* CONFIG_IMAGE_CMDLINE_HACK */ -+ - __REF - - NESTED(kernel_entry, 16, sp) # kernel entry point diff --git a/target/linux/generic-2.6/patches-2.6.28/022-mips_div64_gcc4.4.0.patch b/target/linux/generic-2.6/patches-2.6.28/022-mips_div64_gcc4.4.0.patch deleted file mode 100644 index a549d616c..000000000 --- a/target/linux/generic-2.6/patches-2.6.28/022-mips_div64_gcc4.4.0.patch +++ /dev/null @@ -1,171 +0,0 @@ -From: Ralf Baechle -Date: Thu, 30 Apr 2009 16:14:56 +0000 (+0200) -Subject: MIPS: Rewrite 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 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 ---- - ---- 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 -+#include - --#if (_MIPS_SZLONG == 32) -+#if BITS_PER_LONG == 64 - --#include -+#include - - /* - * 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 */ diff --git a/target/linux/generic-2.6/patches-2.6.28/023-mips_delay_gcc4.4.0.patch b/target/linux/generic-2.6/patches-2.6.28/023-mips_delay_gcc4.4.0.patch deleted file mode 100644 index fcfa79280..000000000 --- a/target/linux/generic-2.6/patches-2.6.28/023-mips_delay_gcc4.4.0.patch +++ /dev/null @@ -1,152 +0,0 @@ -From: Wu Zhangjin - -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 ---- - 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 diff --git a/target/linux/generic-2.6/patches-2.6.28/024-mips_disable_fpu.patch b/target/linux/generic-2.6/patches-2.6.28/024-mips_disable_fpu.patch deleted file mode 100644 index 718d08dc3..000000000 --- a/target/linux/generic-2.6/patches-2.6.28/024-mips_disable_fpu.patch +++ /dev/null @@ -1,155 +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 --- ---- a/arch/mips/Kconfig -+++ b/arch/mips/Kconfig -@@ -751,6 +751,17 @@ config I8259 - config MIPS_BONITO64 - bool - -+config MIPS_FPU_EMU -+ bool "Enable FPU emulation" -+ default y -+ 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,36 @@ int fpu_emulator_restore_context32(struc - - return err; - } --#endif -+#endif /* CONFIG_64BIT */ -+#else -+ -+void fpu_emulator_init_fpu(void) -+{ -+ printk(KERN_INFO "FPU emulator disabled, make sure your toolchain" -+ "was compiled with software floating point support (soft-float)\n"); -+ 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 */ diff --git a/target/linux/generic-2.6/patches-2.6.28/025-mips_fix_loading_of_modules_with_unresolved_weak_sy.patch b/target/linux/generic-2.6/patches-2.6.28/025-mips_fix_loading_of_modules_with_unresolved_weak_sy.patch deleted file mode 100644 index 20c6132e4..000000000 --- a/target/linux/generic-2.6/patches-2.6.28/025-mips_fix_loading_of_modules_with_unresolved_weak_sy.patch +++ /dev/null @@ -1,42 +0,0 @@ -From 819b4bda18d62b52d04789c4a8d4fc3fbf9ce242 Mon Sep 17 00:00:00 2001 -From: Gabor Juhos -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 ---- - 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; diff --git a/target/linux/generic-2.6/patches-2.6.28/026-mips_module_reloc.patch b/target/linux/generic-2.6/patches-2.6.28/026-mips_module_reloc.patch deleted file mode 100644 index dd035b945..000000000 --- a/target/linux/generic-2.6/patches-2.6.28/026-mips_module_reloc.patch +++ /dev/null @@ -1,326 +0,0 @@ ---- a/arch/mips/Makefile -+++ b/arch/mips/Makefile -@@ -82,7 +82,7 @@ all-$(CONFIG_BOOT_ELF64) := $(vmlinux-64 - cflags-y += -G 0 -mno-abicalls -fno-pic -pipe - cflags-y += -msoft-float - LDFLAGS_vmlinux += -G 0 -static -n -nostdlib --MODFLAGS += -mlong-calls -+MODFLAGS += -mno-long-calls - - cflags-y += -ffreestanding - ---- a/arch/mips/include/asm/module.h -+++ b/arch/mips/include/asm/module.h -@@ -9,6 +9,11 @@ struct mod_arch_specific { - struct list_head dbe_list; - const struct exception_table_entry *dbe_start; - const struct exception_table_entry *dbe_end; -+ -+ void *plt_tbl; -+ unsigned int core_plt_offset; -+ unsigned int core_plt_size; -+ unsigned int init_plt_offset; - }; - - typedef uint8_t Elf64_Byte; /* Type for a 8-bit quantity. */ ---- a/arch/mips/kernel/module.c -+++ b/arch/mips/kernel/module.c -@@ -43,6 +43,114 @@ static struct mips_hi16 *mips_hi16_list; - static LIST_HEAD(dbe_list); - static DEFINE_SPINLOCK(dbe_lock); - -+/* -+ * Get the potential max trampolines size required of the init and -+ * non-init sections. Only used if we cannot find enough contiguous -+ * physically mapped memory to put the module into. -+ */ -+static unsigned int -+get_plt_size(const Elf32_Ehdr *hdr, const Elf32_Shdr *sechdrs, -+ const char *secstrings, unsigned int symindex, bool is_init) -+{ -+ unsigned long ret = 0; -+ unsigned int i, j; -+ Elf_Sym *syms; -+ -+ /* Everything marked ALLOC (this includes the exported symbols) */ -+ for (i = 1; i < hdr->e_shnum; ++i) { -+ unsigned int info = sechdrs[i].sh_info; -+ -+ if (sechdrs[i].sh_type != SHT_REL -+ && sechdrs[i].sh_type != SHT_RELA) -+ continue; -+ -+ /* Not a valid relocation section? */ -+ if (info >= hdr->e_shnum) -+ continue; -+ -+ /* Don't bother with non-allocated sections */ -+ if (!(sechdrs[info].sh_flags & SHF_ALLOC)) -+ continue; -+ -+ /* If it's called *.init*, and we're not init, we're -+ not interested */ -+ if ((strstr(secstrings + sechdrs[i].sh_name, ".init") != 0) -+ != is_init) -+ continue; -+ -+ syms = (Elf_Sym *) sechdrs[symindex].sh_addr; -+ if (sechdrs[i].sh_type == SHT_REL) { -+ Elf_Mips_Rel *rel = (void *) sechdrs[i].sh_addr; -+ unsigned int size = sechdrs[i].sh_size / sizeof(*rel); -+ -+ for (j = 0; j < size; ++j) { -+ Elf_Sym *sym; -+ -+ if (ELF_MIPS_R_TYPE(rel[j]) != R_MIPS_26) -+ continue; -+ -+ sym = syms + ELF_MIPS_R_SYM(rel[j]); -+ if (!is_init && sym->st_shndx != SHN_UNDEF) -+ continue; -+ -+ ret += 4 * sizeof(int); -+ } -+ } else { -+ Elf_Mips_Rela *rela = (void *) sechdrs[i].sh_addr; -+ unsigned int size = sechdrs[i].sh_size / sizeof(*rela); -+ -+ for (j = 0; j < size; ++j) { -+ Elf_Sym *sym; -+ -+ if (ELF_MIPS_R_TYPE(rela[j]) != R_MIPS_26) -+ continue; -+ -+ sym = syms + ELF_MIPS_R_SYM(rela[j]); -+ if (!is_init && sym->st_shndx != SHN_UNDEF) -+ continue; -+ -+ ret += 4 * sizeof(int); -+ } -+ } -+ } -+ -+ return ret; -+} -+ -+static void *alloc_phys(unsigned long size) -+{ -+ unsigned order; -+ struct page *page; -+ struct page *p; -+ -+ size = PAGE_ALIGN(size); -+ order = get_order(size); -+ -+ page = alloc_pages(GFP_KERNEL | __GFP_NORETRY | __GFP_NOWARN | -+ __GFP_THISNODE, order); -+ if (!page) -+ return NULL; -+ -+ split_page(page, order); -+ -+ for (p = page + (size >> PAGE_SHIFT); p < page + (1 << order); ++p) -+ __free_page(p); -+ -+ return page_address(page); -+} -+ -+static void free_phys(void *ptr, unsigned long size) -+{ -+ struct page *page; -+ struct page *end; -+ -+ page = virt_to_page(ptr); -+ end = page + (PAGE_ALIGN(size) >> PAGE_SHIFT); -+ -+ for (; page < end; ++page) -+ __free_page(page); -+} -+ - void *module_alloc(unsigned long size) - { - #ifdef MODULE_START -@@ -58,16 +166,41 @@ void *module_alloc(unsigned long size) - - return __vmalloc_area(area, GFP_KERNEL, PAGE_KERNEL); - #else -+ void *ptr; -+ - if (size == 0) - return NULL; -- return vmalloc(size); -+ -+ ptr = alloc_phys(size); -+ -+ /* If we failed to allocate physically contiguous memory, -+ * fall back to regular vmalloc. The module loader code will -+ * create jump tables to handle long jumps */ -+ if (!ptr) -+ return vmalloc(size); -+ -+ return ptr; - #endif - } - -+static inline bool is_phys_addr(void *ptr) -+{ -+ return (KSEGX(ptr) == KSEG0); -+} -+ - /* Free memory returned from module_alloc */ - void module_free(struct module *mod, void *module_region) - { -- vfree(module_region); -+ if (is_phys_addr(module_region)) { -+ if (mod->module_init == module_region) -+ free_phys(module_region, mod->init_size); -+ else if (mod->module_core == module_region) -+ free_phys(module_region, mod->core_size); -+ else -+ BUG(); -+ } else { -+ vfree(module_region); -+ } - /* FIXME: If module_region == mod->init_region, trim exception - table entries. */ - } -@@ -75,6 +208,24 @@ void module_free(struct module *mod, voi - int module_frob_arch_sections(Elf_Ehdr *hdr, Elf_Shdr *sechdrs, - char *secstrings, struct module *mod) - { -+ unsigned int symindex = 0; -+ unsigned int core_size, init_size; -+ int i; -+ -+ for (i = 1; i < hdr->e_shnum; i++) -+ if (sechdrs[i].sh_type == SHT_SYMTAB) -+ symindex = i; -+ -+ core_size = get_plt_size(hdr, sechdrs, secstrings, symindex, false); -+ init_size = get_plt_size(hdr, sechdrs, secstrings, symindex, true); -+ -+ mod->arch.core_plt_offset = 0; -+ mod->arch.core_plt_size = core_size; -+ mod->arch.init_plt_offset = core_size; -+ mod->arch.plt_tbl = kmalloc(core_size + init_size, GFP_KERNEL); -+ if (!mod->arch.plt_tbl) -+ return -ENOMEM; -+ - return 0; - } - -@@ -97,27 +248,41 @@ static int apply_r_mips_32_rela(struct m - return 0; - } - --static int apply_r_mips_26_rel(struct module *me, u32 *location, Elf_Addr v) -+static Elf_Addr add_plt_entry_to(unsigned *plt_offset, -+ void *start, Elf_Addr v) - { -- if (v % 4) { -- printk(KERN_ERR "module %s: dangerous relocation\n", me->name); -- return -ENOEXEC; -- } -+ unsigned *tramp = start + *plt_offset; - -- if ((v & 0xf0000000) != (((unsigned long)location + 4) & 0xf0000000)) { -- printk(KERN_ERR -- "module %s: relocation overflow\n", -- me->name); -- return -ENOEXEC; -- } -+ *plt_offset += 4 * sizeof(int); -+ -+ /* adjust carry for addiu */ -+ if (v & 0x00008000) -+ v += 0x10000; - -- *location = (*location & ~0x03ffffff) | -- ((*location + (v >> 2)) & 0x03ffffff); -+ tramp[0] = 0x3c190000 | (v >> 16); /* lui t9, hi16 */ -+ tramp[1] = 0x27390000 | (v & 0xffff); /* addiu t9, t9, lo16 */ -+ tramp[2] = 0x03200008; /* jr t9 */ -+ tramp[3] = 0x00000000; /* nop */ -+ -+ return (Elf_Addr) tramp; -+} -+ -+static Elf_Addr add_plt_entry(struct module *me, void *location, Elf_Addr v) -+{ -+ if (location >= me->module_core && -+ location < me->module_core + me->core_size) -+ return add_plt_entry_to(&me->arch.core_plt_offset, -+ me->arch.plt_tbl, v); -+ -+ if (location >= me->module_init && -+ location < me->module_init + me->init_size) -+ return add_plt_entry_to(&me->arch.init_plt_offset, -+ me->arch.plt_tbl, v); - - return 0; - } - --static int apply_r_mips_26_rela(struct module *me, u32 *location, Elf_Addr v) -+static int set_r_mips_26(struct module *me, u32 *location, u32 ofs, Elf_Addr v) - { - if (v % 4) { - printk(KERN_ERR "module %s: dangerous relocation\n", me->name); -@@ -125,17 +290,31 @@ static int apply_r_mips_26_rela(struct m - } - - if ((v & 0xf0000000) != (((unsigned long)location + 4) & 0xf0000000)) { -- printk(KERN_ERR -+ v = add_plt_entry(me, location, v + (ofs << 2)); -+ if (!v) { -+ printk(KERN_ERR - "module %s: relocation overflow\n", - me->name); -- return -ENOEXEC; -+ return -ENOEXEC; -+ } -+ ofs = 0; - } - -- *location = (*location & ~0x03ffffff) | ((v >> 2) & 0x03ffffff); -+ *location = (*location & ~0x03ffffff) | ((ofs + (v >> 2)) & 0x03ffffff); - - return 0; - } - -+static int apply_r_mips_26_rel(struct module *me, u32 *location, Elf_Addr v) -+{ -+ return set_r_mips_26(me, location, *location & 0x03ffffff, v); -+} -+ -+static int apply_r_mips_26_rela(struct module *me, u32 *location, Elf_Addr v) -+{ -+ return set_r_mips_26(me, location, 0, v); -+} -+ - static int apply_r_mips_hi16_rel(struct module *me, u32 *location, Elf_Addr v) - { - struct mips_hi16 *n; -@@ -400,11 +579,23 @@ int module_finalize(const Elf_Ehdr *hdr, - list_add(&me->arch.dbe_list, &dbe_list); - spin_unlock_irq(&dbe_lock); - } -+ -+ /* Get rid of the fixup trampoline if we're running the module -+ * from physically mapped address space */ -+ if (me->arch.core_plt_offset == 0 && -+ me->arch.init_plt_offset == me->arch.core_plt_size && -+ is_phys_addr(me->module_core)) { -+ kfree(me->arch.plt_tbl); -+ me->arch.plt_tbl = NULL; -+ } -+ - return 0; - } - - void module_arch_cleanup(struct module *mod) - { -+ if (mod->arch.plt_tbl) -+ kfree(mod->arch.plt_tbl); - spin_lock_irq(&dbe_lock); - list_del(&mod->arch.dbe_list); - spin_unlock_irq(&dbe_lock); diff --git a/target/linux/generic-2.6/patches-2.6.28/027-module_exports.patch b/target/linux/generic-2.6/patches-2.6.28/027-module_exports.patch deleted file mode 100644 index e931ec9d9..000000000 --- a/target/linux/generic-2.6/patches-2.6.28/027-module_exports.patch +++ /dev/null @@ -1,191 +0,0 @@ ---- a/include/asm-generic/vmlinux.lds.h -+++ b/include/asm-generic/vmlinux.lds.h -@@ -2,6 +2,27 @@ - #define LOAD_OFFSET 0 - #endif - -+#ifndef SYMTAB_KEEP_STR -+#define SYMTAB_KEEP_STR *(__ksymtab_strings.*) -+#define SYMTAB_DISCARD_STR -+#else -+#define SYMTAB_DISCARD_STR *(__ksymtab_strings.*) -+#endif -+ -+#ifndef SYMTAB_KEEP -+#define SYMTAB_KEEP *(__ksymtab.*) -+#define SYMTAB_DISCARD -+#else -+#define SYMTAB_DISCARD *(__ksymtab.*) -+#endif -+ -+#ifndef SYMTAB_KEEP_GPL -+#define SYMTAB_KEEP_GPL *(__ksymtab_gpl.*) -+#define SYMTAB_DISCARD_GPL -+#else -+#define SYMTAB_DISCARD_GPL *(__ksymtab_gpl.*) -+#endif -+ - #ifndef VMLINUX_SYMBOL - #define VMLINUX_SYMBOL(_sym_) _sym_ - #endif -@@ -124,35 +145,35 @@ - /* Kernel symbol table: Normal symbols */ \ - __ksymtab : AT(ADDR(__ksymtab) - LOAD_OFFSET) { \ - VMLINUX_SYMBOL(__start___ksymtab) = .; \ -- *(__ksymtab) \ -+ SYMTAB_KEEP \ - VMLINUX_SYMBOL(__stop___ksymtab) = .; \ - } \ - \ - /* Kernel symbol table: GPL-only symbols */ \ - __ksymtab_gpl : AT(ADDR(__ksymtab_gpl) - LOAD_OFFSET) { \ - VMLINUX_SYMBOL(__start___ksymtab_gpl) = .; \ -- *(__ksymtab_gpl) \ -+ SYMTAB_KEEP_GPL \ - VMLINUX_SYMBOL(__stop___ksymtab_gpl) = .; \ - } \ - \ - /* Kernel symbol table: Normal unused symbols */ \ - __ksymtab_unused : AT(ADDR(__ksymtab_unused) - LOAD_OFFSET) { \ - VMLINUX_SYMBOL(__start___ksymtab_unused) = .; \ -- *(__ksymtab_unused) \ -+ *(__ksymtab_unused.*) \ - VMLINUX_SYMBOL(__stop___ksymtab_unused) = .; \ - } \ - \ - /* Kernel symbol table: GPL-only unused symbols */ \ - __ksymtab_unused_gpl : AT(ADDR(__ksymtab_unused_gpl) - LOAD_OFFSET) { \ - VMLINUX_SYMBOL(__start___ksymtab_unused_gpl) = .; \ -- *(__ksymtab_unused_gpl) \ -+ *(__ksymtab_unused_gpl.*) \ - VMLINUX_SYMBOL(__stop___ksymtab_unused_gpl) = .; \ - } \ - \ - /* Kernel symbol table: GPL-future-only symbols */ \ - __ksymtab_gpl_future : AT(ADDR(__ksymtab_gpl_future) - LOAD_OFFSET) { \ - VMLINUX_SYMBOL(__start___ksymtab_gpl_future) = .; \ -- *(__ksymtab_gpl_future) \ -+ *(__ksymtab_gpl_future.*) \ - VMLINUX_SYMBOL(__stop___ksymtab_gpl_future) = .; \ - } \ - \ -@@ -193,7 +214,13 @@ - \ - /* Kernel symbol table: strings */ \ - __ksymtab_strings : AT(ADDR(__ksymtab_strings) - LOAD_OFFSET) { \ -- *(__ksymtab_strings) \ -+ SYMTAB_KEEP_STR \ -+ } \ -+ \ -+ /DISCARD/ : { \ -+ SYMTAB_DISCARD \ -+ SYMTAB_DISCARD_GPL \ -+ SYMTAB_DISCARD_STR \ - } \ - \ - /* __*init sections */ \ ---- a/include/linux/module.h -+++ b/include/linux/module.h -@@ -187,16 +187,24 @@ void *__symbol_get_gpl(const char *symbo - #define __CRC_SYMBOL(sym, sec) - #endif - -+#ifdef MODULE -+#define __EXPORT_SUFFIX(sym) -+#else -+#define __EXPORT_SUFFIX(sym) "." #sym -+#endif -+ - /* For every exported symbol, place a struct in the __ksymtab section */ - #define __EXPORT_SYMBOL(sym, sec) \ - extern typeof(sym) sym; \ - __CRC_SYMBOL(sym, sec) \ - static const char __kstrtab_##sym[] \ -- __attribute__((section("__ksymtab_strings"), aligned(1))) \ -+ __attribute__((section("__ksymtab_strings" \ -+ __EXPORT_SUFFIX(sym)), aligned(1))) \ - = MODULE_SYMBOL_PREFIX #sym; \ - static const struct kernel_symbol __ksymtab_##sym \ - __used \ -- __attribute__((section("__ksymtab" sec), unused)) \ -+ __attribute__((section("__ksymtab" sec \ -+ __EXPORT_SUFFIX(sym)), unused)) \ - = { (unsigned long)&sym, __kstrtab_##sym } - - #define EXPORT_SYMBOL(sym) \ ---- a/Makefile -+++ b/Makefile -@@ -963,7 +963,7 @@ prepare: prepare0 - # Leave this as default for preprocessing vmlinux.lds.S, which is now - # done in arch/$(ARCH)/kernel/Makefile - --export CPPFLAGS_vmlinux.lds += -P -C -U$(ARCH) -+export CPPFLAGS_vmlinux.lds += -P -C -U$(ARCH) $(EXTRA_LDSFLAGS) - - # The asm symlink changes when $(ARCH) changes. - # Detect this and ask user to run make mrproper ---- a/arch/powerpc/kernel/vmlinux.lds.S -+++ b/arch/powerpc/kernel/vmlinux.lds.S -@@ -37,12 +37,6 @@ jiffies = jiffies_64 + 4; - #endif - SECTIONS - { -- /* Sections to be discarded. */ -- /DISCARD/ : { -- *(.exitcall.exit) -- EXIT_DATA -- } -- - . = KERNELBASE; - - /* -@@ -290,6 +284,12 @@ SECTIONS - __bss_stop = .; - } - -+ /* Sections to be discarded. */ -+ /DISCARD/ : { -+ *(.exitcall.exit) -+ EXIT_DATA -+ } -+ - . = ALIGN(PAGE_SIZE); - _end = . ; - PROVIDE32 (end = .); ---- a/arch/arm/kernel/vmlinux.lds.S -+++ b/arch/arm/kernel/vmlinux.lds.S -@@ -76,16 +76,6 @@ SECTIONS - #endif - } - -- /DISCARD/ : { /* Exit code and data */ -- EXIT_TEXT -- EXIT_DATA -- *(.exitcall.exit) --#ifndef CONFIG_MMU -- *(.fixup) -- *(__ex_table) --#endif -- } -- - .text : { /* Real text segment */ - _text = .; /* Text and read-only data */ - __exception_text_start = .; -@@ -173,6 +163,17 @@ SECTIONS - *(COMMON) - _end = .; - } -+ -+ /DISCARD/ : { /* Exit code and data */ -+ EXIT_TEXT -+ EXIT_DATA -+ *(.exitcall.exit) -+#ifndef CONFIG_MMU -+ *(.fixup) -+ *(__ex_table) -+#endif -+ } -+ - /* Stabs debugging sections. */ - .stab 0 : { *(.stab) } - .stabstr 0 : { *(.stabstr) } diff --git a/target/linux/generic-2.6/patches-2.6.28/028-arm_module_unresolved_weak_sym.patch b/target/linux/generic-2.6/patches-2.6.28/028-arm_module_unresolved_weak_sym.patch deleted file mode 100644 index 57554b387..000000000 --- a/target/linux/generic-2.6/patches-2.6.28/028-arm_module_unresolved_weak_sym.patch +++ /dev/null @@ -1,13 +0,0 @@ ---- a/arch/arm/kernel/module.c -+++ b/arch/arm/kernel/module.c -@@ -101,6 +101,10 @@ apply_relocate(Elf32_Shdr *sechdrs, cons - return -ENOEXEC; - } - -+ if ((IS_ERR_VALUE(sym->st_value) || !sym->st_value) && -+ ELF_ST_BIND(sym->st_info) == STB_WEAK) -+ continue; -+ - loc = dstsec->sh_addr + rel->r_offset; - - switch (ELF32_R_TYPE(rel->r_info)) { diff --git a/target/linux/generic-2.6/patches-2.6.28/030-pci_disable_common_quirks.patch b/target/linux/generic-2.6/patches-2.6.28/030-pci_disable_common_quirks.patch deleted file mode 100644 index a8aa561d0..000000000 --- a/target/linux/generic-2.6/patches-2.6.28/030-pci_disable_common_quirks.patch +++ /dev/null @@ -1,43 +0,0 @@ ---- a/drivers/pci/Kconfig -+++ b/drivers/pci/Kconfig -@@ -42,6 +42,12 @@ config PCI_DEBUG - - When in doubt, say N. - -+config PCI_DISABLE_COMMON_QUIRKS -+ bool "PCI disable common quirks" -+ depends on PCI -+ help -+ If you don't know what to do here, say N. -+ - config HT_IRQ - bool "Interrupts on hypertransport devices" - default y ---- a/drivers/pci/quirks.c -+++ b/drivers/pci/quirks.c -@@ -34,6 +34,7 @@ int pcie_mch_quirk; - EXPORT_SYMBOL(pcie_mch_quirk); - - #ifdef CONFIG_PCI_QUIRKS -+#ifndef CONFIG_PCI_DISABLE_COMMON_QUIRKS - /* The Mellanox Tavor device gives false positive parity errors - * Mark this device with a broken_parity_status, to allow - * PCI scanning code to "skip" this now blacklisted device. -@@ -1580,7 +1581,9 @@ static void __devinit fixup_rev1_53c810( - } - } - DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NCR, PCI_DEVICE_ID_NCR_53C810, fixup_rev1_53c810); -+#endif /* !CONFIG_PCI_DISABLE_COMMON_QUIRKS */ - -+#ifndef CONFIG_PCI_DISABLE_COMMON_QUIRKS - /* Enable 1k I/O space granularity on the Intel P64H2 */ - static void __devinit quirk_p64h2_1k_io(struct pci_dev *dev) - { -@@ -1972,6 +1975,7 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AT - quirk_msi_intx_disable_bug); - - #endif /* CONFIG_PCI_MSI */ -+#endif /* !CONFIG_PCI_DISABLE_COMMON_QUIRKS */ - - static void pci_do_fixups(struct pci_dev *dev, struct pci_fixup *f, struct pci_fixup *end) - { diff --git a/target/linux/generic-2.6/patches-2.6.28/060-block2mtd_init.patch b/target/linux/generic-2.6/patches-2.6.28/060-block2mtd_init.patch deleted file mode 100644 index 50df4aae0..000000000 --- a/target/linux/generic-2.6/patches-2.6.28/060-block2mtd_init.patch +++ /dev/null @@ -1,110 +0,0 @@ ---- a/drivers/mtd/devices/block2mtd.c -+++ b/drivers/mtd/devices/block2mtd.c -@@ -14,6 +14,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -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=[,]\""); -+MODULE_PARM_DESC(block2mtd, "Device to use. \"block2mtd=[,[,]]\""); - - static int __init block2mtd_init(void) - { diff --git a/target/linux/generic-2.6/patches-2.6.28/065-rootfs_split.patch b/target/linux/generic-2.6/patches-2.6.28/065-rootfs_split.patch deleted file mode 100644 index 2ba39834b..000000000 --- a/target/linux/generic-2.6/patches-2.6.28/065-rootfs_split.patch +++ /dev/null @@ -1,624 +0,0 @@ ---- a/drivers/mtd/Kconfig -+++ b/drivers/mtd/Kconfig -@@ -45,6 +45,16 @@ config MTD_PARTITIONS - devices. Partitioning on NFTL 'devices' is a different - that's the - 'normal' form of partitioning used on a block device. - -+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 - #include - #include -+#include -+#include - - /* 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,147 @@ out_register: - return slave; - } - -+#ifdef CONFIG_MTD_ROOTFS_SPLIT -+#define ROOTFS_SPLIT_NAME "rootfs_data" -+#define ROOTFS_REMOVED_NAME "" -+static int split_squashfs(struct mtd_info *master, int offset, int *split_offset) -+{ -+ struct squashfs_super_block sb; -+ int len, ret; -+ -+ ret = master->read(master, offset, sizeof(sb), &len, (void *) &sb); -+ if (ret || (len != sizeof(sb))) { -+ printk(KERN_ALERT "split_squashfs: error occured while reading " -+ "from \"%s\"\n", master->name); -+ return -EINVAL; -+ } -+ -+ if (sb.s_magic != 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=%X, len=%X \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"), -+ part->offset, 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 +645,29 @@ int add_mtd_partitions(struct mtd_info * - { - struct mtd_part *slave; - u_int32_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 +675,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 - #include -+#include - - #include - -@@ -769,6 +770,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 -@@ -98,6 +98,7 @@ struct mtd_oob_ops { - uint8_t *oobbuf; - }; - -+struct mtd_info; - struct mtd_info { - u_char type; - u_int32_t flags; -@@ -213,6 +214,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 */ - u_int32_t size; /* partition size */ -@@ -41,6 +42,7 @@ struct mtd_partition { - u_int32_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 diff --git a/target/linux/generic-2.6/patches-2.6.28/070-redboot_space.patch b/target/linux/generic-2.6/patches-2.6.28/070-redboot_space.patch deleted file mode 100644 index 6ace83c01..000000000 --- a/target/linux/generic-2.6/patches-2.6.28/070-redboot_space.patch +++ /dev/null @@ -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); diff --git a/target/linux/generic-2.6/patches-2.6.28/071-redboot_boardconfig.patch b/target/linux/generic-2.6/patches-2.6.28/071-redboot_boardconfig.patch deleted file mode 100644 index f9bc4fe36..000000000 --- a/target/linux/generic-2.6/patches-2.6.28/071-redboot_boardconfig.patch +++ /dev/null @@ -1,60 +0,0 @@ ---- a/drivers/mtd/redboot.c -+++ b/drivers/mtd/redboot.c -@@ -11,6 +11,8 @@ - #include - #include - -+#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 ( ; iimg->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: diff --git a/target/linux/generic-2.6/patches-2.6.28/080-mtd_plat_nand_chip_fixup.patch b/target/linux/generic-2.6/patches-2.6.28/080-mtd_plat_nand_chip_fixup.patch deleted file mode 100644 index 9e4a3c56f..000000000 --- a/target/linux/generic-2.6/patches-2.6.28/080-mtd_plat_nand_chip_fixup.patch +++ /dev/null @@ -1,32 +0,0 @@ ---- a/include/linux/mtd/nand.h -+++ b/include/linux/mtd/nand.h -@@ -579,6 +579,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; - } diff --git a/target/linux/generic-2.6/patches-2.6.28/081-mtd_myloader_partition_parser.patch b/target/linux/generic-2.6/patches-2.6.28/081-mtd_myloader_partition_parser.patch deleted file mode 100644 index 7a5addd63..000000000 --- a/target/linux/generic-2.6/patches-2.6.28/081-mtd_myloader_partition_parser.patch +++ /dev/null @@ -1,35 +0,0 @@ ---- a/drivers/mtd/Kconfig -+++ b/drivers/mtd/Kconfig -@@ -172,6 +172,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 diff --git a/target/linux/generic-2.6/patches-2.6.28/082-mtd_myloader_use_linux_byteorder_h.patch b/target/linux/generic-2.6/patches-2.6.28/082-mtd_myloader_use_linux_byteorder_h.patch deleted file mode 100644 index 2461fa36e..000000000 --- a/target/linux/generic-2.6/patches-2.6.28/082-mtd_myloader_use_linux_byteorder_h.patch +++ /dev/null @@ -1,11 +0,0 @@ ---- a/drivers/mtd/myloader.c -+++ b/drivers/mtd/myloader.c -@@ -19,7 +19,7 @@ - #include - #include - #include --#include -+#include - #include - - #define BLOCK_LEN_MIN 0x10000 diff --git a/target/linux/generic-2.6/patches-2.6.28/090-mtd_fix_nand_correct_data_return_code.patch b/target/linux/generic-2.6/patches-2.6.28/090-mtd_fix_nand_correct_data_return_code.patch deleted file mode 100644 index be2c7d732..000000000 --- a/target/linux/generic-2.6/patches-2.6.28/090-mtd_fix_nand_correct_data_return_code.patch +++ /dev/null @@ -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); - diff --git a/target/linux/generic-2.6/patches-2.6.28/100-netfilter_layer7_2.21.patch b/target/linux/generic-2.6/patches-2.6.28/100-netfilter_layer7_2.21.patch deleted file mode 100644 index 57f1b0274..000000000 --- a/target/linux/generic-2.6/patches-2.6.28/100-netfilter_layer7_2.21.patch +++ /dev/null @@ -1,2132 +0,0 @@ ---- /dev/null -+++ b/include/linux/netfilter/xt_layer7.h -@@ -0,0 +1,13 @@ -+#ifndef _XT_LAYER7_H -+#define _XT_LAYER7_H -+ -+#define MAX_PATTERN_LEN 8192 -+#define MAX_PROTOCOL_LEN 256 -+ -+struct xt_layer7_info { -+ char protocol[MAX_PROTOCOL_LEN]; -+ char pattern[MAX_PATTERN_LEN]; -+ u_int8_t invert; -+}; -+ -+#endif /* _XT_LAYER7_H */ ---- a/include/net/netfilter/nf_conntrack.h -+++ b/include/net/netfilter/nf_conntrack.h -@@ -118,6 +118,22 @@ struct nf_conn - u_int32_t secmark; - #endif - -+#if defined(CONFIG_NETFILTER_XT_MATCH_LAYER7) || \ -+ defined(CONFIG_NETFILTER_XT_MATCH_LAYER7_MODULE) -+ struct { -+ /* -+ * e.g. "http". NULL before decision. "unknown" after decision -+ * if no match. -+ */ -+ char *app_proto; -+ /* -+ * application layer data so far. NULL after match decision. -+ */ -+ char *app_data; -+ unsigned int app_data_len; -+ } layer7; -+#endif -+ - /* Storage reserved for other modules: */ - union nf_conntrack_proto proto; - ---- a/net/netfilter/Kconfig -+++ b/net/netfilter/Kconfig -@@ -795,6 +795,27 @@ config NETFILTER_XT_MATCH_STATE - - To compile it as a module, choose M here. If unsure, say N. - -+config NETFILTER_XT_MATCH_LAYER7 -+ tristate '"layer7" match support' -+ depends on NETFILTER_XTABLES -+ depends on EXPERIMENTAL && (IP_NF_CONNTRACK || NF_CONNTRACK) -+ depends on NF_CT_ACCT -+ help -+ Say Y if you want to be able to classify connections (and their -+ packets) based on regular expression matching of their application -+ layer data. This is one way to classify applications such as -+ peer-to-peer filesharing systems that do not always use the same -+ port. -+ -+ To compile it as a module, choose M here. If unsure, say N. -+ -+config NETFILTER_XT_MATCH_LAYER7_DEBUG -+ bool 'Layer 7 debugging output' -+ depends on NETFILTER_XT_MATCH_LAYER7 -+ help -+ Say Y to get lots of debugging output. -+ -+ - config NETFILTER_XT_MATCH_STATISTIC - tristate '"statistic" match support' - depends on NETFILTER_ADVANCED ---- a/net/netfilter/Makefile -+++ b/net/netfilter/Makefile -@@ -84,6 +84,7 @@ obj-$(CONFIG_NETFILTER_XT_MATCH_RECENT) - obj-$(CONFIG_NETFILTER_XT_MATCH_SCTP) += xt_sctp.o - obj-$(CONFIG_NETFILTER_XT_MATCH_SOCKET) += xt_socket.o - obj-$(CONFIG_NETFILTER_XT_MATCH_STATE) += xt_state.o -+obj-$(CONFIG_NETFILTER_XT_MATCH_LAYER7) += xt_layer7.o - obj-$(CONFIG_NETFILTER_XT_MATCH_STATISTIC) += xt_statistic.o - obj-$(CONFIG_NETFILTER_XT_MATCH_STRING) += xt_string.o - obj-$(CONFIG_NETFILTER_XT_MATCH_TCPMSS) += xt_tcpmss.o ---- a/net/netfilter/nf_conntrack_core.c -+++ b/net/netfilter/nf_conntrack_core.c -@@ -201,6 +201,14 @@ destroy_conntrack(struct nf_conntrack *n - * too. */ - nf_ct_remove_expectations(ct); - -+ #if defined(CONFIG_NETFILTER_XT_MATCH_LAYER7) || defined(CONFIG_NETFILTER_XT_MATCH_LAYER7_MODULE) -+ if(ct->layer7.app_proto) -+ kfree(ct->layer7.app_proto); -+ if(ct->layer7.app_data) -+ kfree(ct->layer7.app_data); -+ #endif -+ -+ - /* We overload first tuple to link into unconfirmed list. */ - if (!nf_ct_is_confirmed(ct)) { - BUG_ON(hlist_unhashed(&ct->tuplehash[IP_CT_DIR_ORIGINAL].hnode)); ---- a/net/netfilter/nf_conntrack_standalone.c -+++ b/net/netfilter/nf_conntrack_standalone.c -@@ -165,6 +165,12 @@ static int ct_seq_show(struct seq_file * - return -ENOSPC; - #endif - -+#if defined(CONFIG_NETFILTER_XT_MATCH_LAYER7) || defined(CONFIG_NETFILTER_XT_MATCH_LAYER7_MODULE) -+ if(ct->layer7.app_proto && -+ seq_printf(s, "l7proto=%s ", ct->layer7.app_proto)) -+ return -ENOSPC; -+#endif -+ - if (seq_printf(s, "use=%u\n", atomic_read(&ct->ct_general.use))) - return -ENOSPC; - ---- /dev/null -+++ b/net/netfilter/regexp/regexp.c -@@ -0,0 +1,1197 @@ -+/* -+ * regcomp and regexec -- regsub and regerror are elsewhere -+ * @(#)regexp.c 1.3 of 18 April 87 -+ * -+ * Copyright (c) 1986 by University of Toronto. -+ * Written by Henry Spencer. Not derived from licensed software. -+ * -+ * Permission is granted to anyone to use this software for any -+ * purpose on any computer system, and to redistribute it freely, -+ * subject to the following restrictions: -+ * -+ * 1. The author is not responsible for the consequences of use of -+ * this software, no matter how awful, even if they arise -+ * from defects in it. -+ * -+ * 2. The origin of this software must not be misrepresented, either -+ * by explicit claim or by omission. -+ * -+ * 3. Altered versions must be plainly marked as such, and must not -+ * be misrepresented as being the original software. -+ * -+ * Beware that some of this code is subtly aware of the way operator -+ * precedence is structured in regular expressions. Serious changes in -+ * regular-expression syntax might require a total rethink. -+ * -+ * This code was modified by Ethan Sommer to work within the kernel -+ * (it now uses kmalloc etc..) -+ * -+ * Modified slightly by Matthew Strait to use more modern C. -+ */ -+ -+#include "regexp.h" -+#include "regmagic.h" -+ -+/* added by ethan and matt. Lets it work in both kernel and user space. -+(So iptables can use it, for instance.) Yea, it goes both ways... */ -+#if __KERNEL__ -+ #define malloc(foo) kmalloc(foo,GFP_ATOMIC) -+#else -+ #define printk(format,args...) printf(format,##args) -+#endif -+ -+void regerror(char * s) -+{ -+ printk("<3>Regexp: %s\n", s); -+ /* NOTREACHED */ -+} -+ -+/* -+ * The "internal use only" fields in regexp.h are present to pass info from -+ * compile to execute that permits the execute phase to run lots faster on -+ * simple cases. They are: -+ * -+ * regstart char that must begin a match; '\0' if none obvious -+ * reganch is the match anchored (at beginning-of-line only)? -+ * regmust string (pointer into program) that match must include, or NULL -+ * regmlen length of regmust string -+ * -+ * Regstart and reganch permit very fast decisions on suitable starting points -+ * for a match, cutting down the work a lot. Regmust permits fast rejection -+ * of lines that cannot possibly match. The regmust tests are costly enough -+ * that regcomp() supplies a regmust only if the r.e. contains something -+ * potentially expensive (at present, the only such thing detected is * or + -+ * at the start of the r.e., which can involve a lot of backup). Regmlen is -+ * supplied because the test in regexec() needs it and regcomp() is computing -+ * it anyway. -+ */ -+ -+/* -+ * Structure for regexp "program". This is essentially a linear encoding -+ * of a nondeterministic finite-state machine (aka syntax charts or -+ * "railroad normal form" in parsing technology). Each node is an opcode -+ * plus a "next" pointer, possibly plus an operand. "Next" pointers of -+ * all nodes except BRANCH implement concatenation; a "next" pointer with -+ * a BRANCH on both ends of it is connecting two alternatives. (Here we -+ * have one of the subtle syntax dependencies: an individual BRANCH (as -+ * opposed to a collection of them) is never concatenated with anything -+ * because of operator precedence.) The operand of some types of node is -+ * a literal string; for others, it is a node leading into a sub-FSM. In -+ * particular, the operand of a BRANCH node is the first node of the branch. -+ * (NB this is *not* a tree structure: the tail of the branch connects -+ * to the thing following the set of BRANCHes.) The opcodes are: -+ */ -+ -+/* definition number opnd? meaning */ -+#define END 0 /* no End of program. */ -+#define BOL 1 /* no Match "" at beginning of line. */ -+#define EOL 2 /* no Match "" at end of line. */ -+#define ANY 3 /* no Match any one character. */ -+#define ANYOF 4 /* str Match any character in this string. */ -+#define ANYBUT 5 /* str Match any character not in this string. */ -+#define BRANCH 6 /* node Match this alternative, or the next... */ -+#define BACK 7 /* no Match "", "next" ptr points backward. */ -+#define EXACTLY 8 /* str Match this string. */ -+#define NOTHING 9 /* no Match empty string. */ -+#define STAR 10 /* node Match this (simple) thing 0 or more times. */ -+#define PLUS 11 /* node Match this (simple) thing 1 or more times. */ -+#define OPEN 20 /* no Mark this point in input as start of #n. */ -+ /* OPEN+1 is number 1, etc. */ -+#define CLOSE 30 /* no Analogous to OPEN. */ -+ -+/* -+ * Opcode notes: -+ * -+ * BRANCH The set of branches constituting a single choice are hooked -+ * together with their "next" pointers, since precedence prevents -+ * anything being concatenated to any individual branch. The -+ * "next" pointer of the last BRANCH in a choice points to the -+ * thing following the whole choice. This is also where the -+ * final "next" pointer of each individual branch points; each -+ * branch starts with the operand node of a BRANCH node. -+ * -+ * BACK Normal "next" pointers all implicitly point forward; BACK -+ * exists to make loop structures possible. -+ * -+ * STAR,PLUS '?', and complex '*' and '+', are implemented as circular -+ * BRANCH structures using BACK. Simple cases (one character -+ * per match) are implemented with STAR and PLUS for speed -+ * and to minimize recursive plunges. -+ * -+ * OPEN,CLOSE ...are numbered at compile time. -+ */ -+ -+/* -+ * A node is one char of opcode followed by two chars of "next" pointer. -+ * "Next" pointers are stored as two 8-bit pieces, high order first. The -+ * value is a positive offset from the opcode of the node containing it. -+ * An operand, if any, simply follows the node. (Note that much of the -+ * code generation knows about this implicit relationship.) -+ * -+ * Using two bytes for the "next" pointer is vast overkill for most things, -+ * but allows patterns to get big without disasters. -+ */ -+#define OP(p) (*(p)) -+#define NEXT(p) (((*((p)+1)&0377)<<8) + (*((p)+2)&0377)) -+#define OPERAND(p) ((p) + 3) -+ -+/* -+ * See regmagic.h for one further detail of program structure. -+ */ -+ -+ -+/* -+ * Utility definitions. -+ */ -+#ifndef CHARBITS -+#define UCHARAT(p) ((int)*(unsigned char *)(p)) -+#else -+#define UCHARAT(p) ((int)*(p)&CHARBITS) -+#endif -+ -+#define FAIL(m) { regerror(m); return(NULL); } -+#define ISMULT(c) ((c) == '*' || (c) == '+' || (c) == '?') -+#define META "^$.[()|?+*\\" -+ -+/* -+ * Flags to be passed up and down. -+ */ -+#define HASWIDTH 01 /* Known never to match null string. */ -+#define SIMPLE 02 /* Simple enough to be STAR/PLUS operand. */ -+#define SPSTART 04 /* Starts with * or +. */ -+#define WORST 0 /* Worst case. */ -+ -+/* -+ * Global work variables for regcomp(). -+ */ -+struct match_globals { -+char *reginput; /* String-input pointer. */ -+char *regbol; /* Beginning of input, for ^ check. */ -+char **regstartp; /* Pointer to startp array. */ -+char **regendp; /* Ditto for endp. */ -+char *regparse; /* Input-scan pointer. */ -+int regnpar; /* () count. */ -+char regdummy; -+char *regcode; /* Code-emit pointer; ®dummy = don't. */ -+long regsize; /* Code size. */ -+}; -+ -+/* -+ * Forward declarations for regcomp()'s friends. -+ */ -+#ifndef STATIC -+#define STATIC static -+#endif -+STATIC char *reg(struct match_globals *g, int paren,int *flagp); -+STATIC char *regbranch(struct match_globals *g, int *flagp); -+STATIC char *regpiece(struct match_globals *g, int *flagp); -+STATIC char *regatom(struct match_globals *g, int *flagp); -+STATIC char *regnode(struct match_globals *g, char op); -+STATIC char *regnext(struct match_globals *g, char *p); -+STATIC void regc(struct match_globals *g, char b); -+STATIC void reginsert(struct match_globals *g, char op, char *opnd); -+STATIC void regtail(struct match_globals *g, char *p, char *val); -+STATIC void regoptail(struct match_globals *g, char *p, char *val); -+ -+ -+__kernel_size_t my_strcspn(const char *s1,const char *s2) -+{ -+ char *scan1; -+ char *scan2; -+ int count; -+ -+ count = 0; -+ for (scan1 = (char *)s1; *scan1 != '\0'; scan1++) { -+ for (scan2 = (char *)s2; *scan2 != '\0';) /* ++ moved down. */ -+ if (*scan1 == *scan2++) -+ return(count); -+ count++; -+ } -+ return(count); -+} -+ -+/* -+ - regcomp - compile a regular expression into internal code -+ * -+ * We can't allocate space until we know how big the compiled form will be, -+ * but we can't compile it (and thus know how big it is) until we've got a -+ * place to put the code. So we cheat: we compile it twice, once with code -+ * generation turned off and size counting turned on, and once "for real". -+ * This also means that we don't allocate space until we are sure that the -+ * thing really will compile successfully, and we never have to move the -+ * code and thus invalidate pointers into it. (Note that it has to be in -+ * one piece because free() must be able to free it all.) -+ * -+ * Beware that the optimization-preparation code in here knows about some -+ * of the structure of the compiled regexp. -+ */ -+regexp * -+regcomp(char *exp,int *patternsize) -+{ -+ register regexp *r; -+ register char *scan; -+ register char *longest; -+ register int len; -+ int flags; -+ struct match_globals g; -+ -+ /* commented out by ethan -+ extern char *malloc(); -+ */ -+ -+ if (exp == NULL) -+ FAIL("NULL argument"); -+ -+ /* First pass: determine size, legality. */ -+ g.regparse = exp; -+ g.regnpar = 1; -+ g.regsize = 0L; -+ g.regcode = &g.regdummy; -+ regc(&g, MAGIC); -+ if (reg(&g, 0, &flags) == NULL) -+ return(NULL); -+ -+ /* Small enough for pointer-storage convention? */ -+ if (g.regsize >= 32767L) /* Probably could be 65535L. */ -+ FAIL("regexp too big"); -+ -+ /* Allocate space. */ -+ *patternsize=sizeof(regexp) + (unsigned)g.regsize; -+ r = (regexp *)malloc(sizeof(regexp) + (unsigned)g.regsize); -+ if (r == NULL) -+ FAIL("out of space"); -+ -+ /* Second pass: emit code. */ -+ g.regparse = exp; -+ g.regnpar = 1; -+ g.regcode = r->program; -+ regc(&g, MAGIC); -+ if (reg(&g, 0, &flags) == NULL) -+ return(NULL); -+ -+ /* Dig out information for optimizations. */ -+ r->regstart = '\0'; /* Worst-case defaults. */ -+ r->reganch = 0; -+ r->regmust = NULL; -+ r->regmlen = 0; -+ scan = r->program+1; /* First BRANCH. */ -+ if (OP(regnext(&g, scan)) == END) { /* Only one top-level choice. */ -+ scan = OPERAND(scan); -+ -+ /* Starting-point info. */ -+ if (OP(scan) == EXACTLY) -+ r->regstart = *OPERAND(scan); -+ else if (OP(scan) == BOL) -+ r->reganch++; -+ -+ /* -+ * If there's something expensive in the r.e., find the -+ * longest literal string that must appear and make it the -+ * regmust. Resolve ties in favor of later strings, since -+ * the regstart check works with the beginning of the r.e. -+ * and avoiding duplication strengthens checking. Not a -+ * strong reason, but sufficient in the absence of others. -+ */ -+ if (flags&SPSTART) { -+ longest = NULL; -+ len = 0; -+ for (; scan != NULL; scan = regnext(&g, scan)) -+ if (OP(scan) == EXACTLY && strlen(OPERAND(scan)) >= len) { -+ longest = OPERAND(scan); -+ len = strlen(OPERAND(scan)); -+ } -+ r->regmust = longest; -+ r->regmlen = len; -+ } -+ } -+ -+ return(r); -+} -+ -+/* -+ - reg - regular expression, i.e. main body or parenthesized thing -+ * -+ * Caller must absorb opening parenthesis. -+ * -+ * Combining parenthesis handling with the base level of regular expression -+ * is a trifle forced, but the need to tie the tails of the branches to what -+ * follows makes it hard to avoid. -+ */ -+static char * -+reg(struct match_globals *g, int paren, int *flagp /* Parenthesized? */ ) -+{ -+ register char *ret; -+ register char *br; -+ register char *ender; -+ register int parno = 0; /* 0 makes gcc happy */ -+ int flags; -+ -+ *flagp = HASWIDTH; /* Tentatively. */ -+ -+ /* Make an OPEN node, if parenthesized. */ -+ if (paren) { -+ if (g->regnpar >= NSUBEXP) -+ FAIL("too many ()"); -+ parno = g->regnpar; -+ g->regnpar++; -+ ret = regnode(g, OPEN+parno); -+ } else -+ ret = NULL; -+ -+ /* Pick up the branches, linking them together. */ -+ br = regbranch(g, &flags); -+ if (br == NULL) -+ return(NULL); -+ if (ret != NULL) -+ regtail(g, ret, br); /* OPEN -> first. */ -+ else -+ ret = br; -+ if (!(flags&HASWIDTH)) -+ *flagp &= ~HASWIDTH; -+ *flagp |= flags&SPSTART; -+ while (*g->regparse == '|') { -+ g->regparse++; -+ br = regbranch(g, &flags); -+ if (br == NULL) -+ return(NULL); -+ regtail(g, ret, br); /* BRANCH -> BRANCH. */ -+ if (!(flags&HASWIDTH)) -+ *flagp &= ~HASWIDTH; -+ *flagp |= flags&SPSTART; -+ } -+ -+ /* Make a closing node, and hook it on the end. */ -+ ender = regnode(g, (paren) ? CLOSE+parno : END); -+ regtail(g, ret, ender); -+ -+ /* Hook the tails of the branches to the closing node. */ -+ for (br = ret; br != NULL; br = regnext(g, br)) -+ regoptail(g, br, ender); -+ -+ /* Check for proper termination. */ -+ if (paren && *g->regparse++ != ')') { -+ FAIL("unmatched ()"); -+ } else if (!paren && *g->regparse != '\0') { -+ if (*g->regparse == ')') { -+ FAIL("unmatched ()"); -+ } else -+ FAIL("junk on end"); /* "Can't happen". */ -+ /* NOTREACHED */ -+ } -+ -+ return(ret); -+} -+ -+/* -+ - regbranch - one alternative of an | operator -+ * -+ * Implements the concatenation operator. -+ */ -+static char * -+regbranch(struct match_globals *g, int *flagp) -+{ -+ register char *ret; -+ register char *chain; -+ register char *latest; -+ int flags; -+ -+ *flagp = WORST; /* Tentatively. */ -+ -+ ret = regnode(g, BRANCH); -+ chain = NULL; -+ while (*g->regparse != '\0' && *g->regparse != '|' && *g->regparse != ')') { -+ latest = regpiece(g, &flags); -+ if (latest == NULL) -+ return(NULL); -+ *flagp |= flags&HASWIDTH; -+ if (chain == NULL) /* First piece. */ -+ *flagp |= flags&SPSTART; -+ else -+ regtail(g, chain, latest); -+ chain = latest; -+ } -+ if (chain == NULL) /* Loop ran zero times. */ -+ (void) regnode(g, NOTHING); -+ -+ return(ret); -+} -+ -+/* -+ - regpiece - something followed by possible [*+?] -+ * -+ * Note that the branching code sequences used for ? and the general cases -+ * of * and + are somewhat optimized: they use the same NOTHING node as -+ * both the endmarker for their branch list and the body of the last branch. -+ * It might seem that this node could be dispensed with entirely, but the -+ * endmarker role is not redundant. -+ */ -+static char * -+regpiece(struct match_globals *g, int *flagp) -+{ -+ register char *ret; -+ register char op; -+ register char *next; -+ int flags; -+ -+ ret = regatom(g, &flags); -+ if (ret == NULL) -+ return(NULL); -+ -+ op = *g->regparse; -+ if (!ISMULT(op)) { -+ *flagp = flags; -+ return(ret); -+ } -+ -+ if (!(flags&HASWIDTH) && op != '?') -+ FAIL("*+ operand could be empty"); -+ *flagp = (op != '+') ? (WORST|SPSTART) : (WORST|HASWIDTH); -+ -+ if (op == '*' && (flags&SIMPLE)) -+ reginsert(g, STAR, ret); -+ else if (op == '*') { -+ /* Emit x* as (x&|), where & means "self". */ -+ reginsert(g, BRANCH, ret); /* Either x */ -+ regoptail(g, ret, regnode(g, BACK)); /* and loop */ -+ regoptail(g, ret, ret); /* back */ -+ regtail(g, ret, regnode(g, BRANCH)); /* or */ -+ regtail(g, ret, regnode(g, NOTHING)); /* null. */ -+ } else if (op == '+' && (flags&SIMPLE)) -+ reginsert(g, PLUS, ret); -+ else if (op == '+') { -+ /* Emit x+ as x(&|), where & means "self". */ -+ next = regnode(g, BRANCH); /* Either */ -+ regtail(g, ret, next); -+ regtail(g, regnode(g, BACK), ret); /* loop back */ -+ regtail(g, next, regnode(g, BRANCH)); /* or */ -+ regtail(g, ret, regnode(g, NOTHING)); /* null. */ -+ } else if (op == '?') { -+ /* Emit x? as (x|) */ -+ reginsert(g, BRANCH, ret); /* Either x */ -+ regtail(g, ret, regnode(g, BRANCH)); /* or */ -+ next = regnode(g, NOTHING); /* null. */ -+ regtail(g, ret, next); -+ regoptail(g, ret, next); -+ } -+ g->regparse++; -+ if (ISMULT(*g->regparse)) -+ FAIL("nested *?+"); -+ -+ return(ret); -+} -+ -+/* -+ - regatom - the lowest level -+ * -+ * Optimization: gobbles an entire sequence of ordinary characters so that -+ * it can turn them into a single node, which is smaller to store and -+ * faster to run. Backslashed characters are exceptions, each becoming a -+ * separate node; the code is simpler that way and it's not worth fixing. -+ */ -+static char * -+regatom(struct match_globals *g, int *flagp) -+{ -+ register char *ret; -+ int flags; -+ -+ *flagp = WORST; /* Tentatively. */ -+ -+ switch (*g->regparse++) { -+ case '^': -+ ret = regnode(g, BOL); -+ break; -+ case '$': -+ ret = regnode(g, EOL); -+ break; -+ case '.': -+ ret = regnode(g, ANY); -+ *flagp |= HASWIDTH|SIMPLE; -+ break; -+ case '[': { -+ register int class; -+ register int classend; -+ -+ if (*g->regparse == '^') { /* Complement of range. */ -+ ret = regnode(g, ANYBUT); -+ g->regparse++; -+ } else -+ ret = regnode(g, ANYOF); -+ if (*g->regparse == ']' || *g->regparse == '-') -+ regc(g, *g->regparse++); -+ while (*g->regparse != '\0' && *g->regparse != ']') { -+ if (*g->regparse == '-') { -+ g->regparse++; -+ if (*g->regparse == ']' || *g->regparse == '\0') -+ regc(g, '-'); -+ else { -+ class = UCHARAT(g->regparse-2)+1; -+ classend = UCHARAT(g->regparse); -+ if (class > classend+1) -+ FAIL("invalid [] range"); -+ for (; class <= classend; class++) -+ regc(g, class); -+ g->regparse++; -+ } -+ } else -+ regc(g, *g->regparse++); -+ } -+ regc(g, '\0'); -+ if (*g->regparse != ']') -+ FAIL("unmatched []"); -+ g->regparse++; -+ *flagp |= HASWIDTH|SIMPLE; -+ } -+ break; -+ case '(': -+ ret = reg(g, 1, &flags); -+ if (ret == NULL) -+ return(NULL); -+ *flagp |= flags&(HASWIDTH|SPSTART); -+ break; -+ case '\0': -+ case '|': -+ case ')': -+ FAIL("internal urp"); /* Supposed to be caught earlier. */ -+ break; -+ case '?': -+ case '+': -+ case '*': -+ FAIL("?+* follows nothing"); -+ break; -+ case '\\': -+ if (*g->regparse == '\0') -+ FAIL("trailing \\"); -+ ret = regnode(g, EXACTLY); -+ regc(g, *g->regparse++); -+ regc(g, '\0'); -+ *flagp |= HASWIDTH|SIMPLE; -+ break; -+ default: { -+ register int len; -+ register char ender; -+ -+ g->regparse--; -+ len = my_strcspn((const char *)g->regparse, (const char *)META); -+ if (len <= 0) -+ FAIL("internal disaster"); -+ ender = *(g->regparse+len); -+ if (len > 1 && ISMULT(ender)) -+ len--; /* Back off clear of ?+* operand. */ -+ *flagp |= HASWIDTH; -+ if (len == 1) -+ *flagp |= SIMPLE; -+ ret = regnode(g, EXACTLY); -+ while (len > 0) { -+ regc(g, *g->regparse++); -+ len--; -+ } -+ regc(g, '\0'); -+ } -+ break; -+ } -+ -+ return(ret); -+} -+ -+/* -+ - regnode - emit a node -+ */ -+static char * /* Location. */ -+regnode(struct match_globals *g, char op) -+{ -+ register char *ret; -+ register char *ptr; -+ -+ ret = g->regcode; -+ if (ret == &g->regdummy) { -+ g->regsize += 3; -+ return(ret); -+ } -+ -+ ptr = ret; -+ *ptr++ = op; -+ *ptr++ = '\0'; /* Null "next" pointer. */ -+ *ptr++ = '\0'; -+ g->regcode = ptr; -+ -+ return(ret); -+} -+ -+/* -+ - regc - emit (if appropriate) a byte of code -+ */ -+static void -+regc(struct match_globals *g, char b) -+{ -+ if (g->regcode != &g->regdummy) -+ *g->regcode++ = b; -+ else -+ g->regsize++; -+} -+ -+/* -+ - reginsert - insert an operator in front of already-emitted operand -+ * -+ * Means relocating the operand. -+ */ -+static void -+reginsert(struct match_globals *g, char op, char* opnd) -+{ -+ register char *src; -+ register char *dst; -+ register char *place; -+ -+ if (g->regcode == &g->regdummy) { -+ g->regsize += 3; -+ return; -+ } -+ -+ src = g->regcode; -+ g->regcode += 3; -+ dst = g->regcode; -+ while (src > opnd) -+ *--dst = *--src; -+ -+ place = opnd; /* Op node, where operand used to be. */ -+ *place++ = op; -+ *place++ = '\0'; -+ *place++ = '\0'; -+} -+ -+/* -+ - regtail - set the next-pointer at the end of a node chain -+ */ -+static void -+regtail(struct match_globals *g, char *p, char *val) -+{ -+ register char *scan; -+ register char *temp; -+ register int offset; -+ -+ if (p == &g->regdummy) -+ return; -+ -+ /* Find last node. */ -+ scan = p; -+ for (;;) { -+ temp = regnext(g, scan); -+ if (temp == NULL) -+ break; -+ scan = temp; -+ } -+ -+ if (OP(scan) == BACK) -+ offset = scan - val; -+ else -+ offset = val - scan; -+ *(scan+1) = (offset>>8)&0377; -+ *(scan+2) = offset&0377; -+} -+ -+/* -+ - regoptail - regtail on operand of first argument; nop if operandless -+ */ -+static void -+regoptail(struct match_globals *g, char *p, char *val) -+{ -+ /* "Operandless" and "op != BRANCH" are synonymous in practice. */ -+ if (p == NULL || p == &g->regdummy || OP(p) != BRANCH) -+ return; -+ regtail(g, OPERAND(p), val); -+} -+ -+/* -+ * regexec and friends -+ */ -+ -+ -+/* -+ * Forwards. -+ */ -+STATIC int regtry(struct match_globals *g, regexp *prog, char *string); -+STATIC int regmatch(struct match_globals *g, char *prog); -+STATIC int regrepeat(struct match_globals *g, char *p); -+ -+#ifdef DEBUG -+int regnarrate = 0; -+void regdump(); -+STATIC char *regprop(char *op); -+#endif -+ -+/* -+ - regexec - match a regexp against a string -+ */ -+int -+regexec(regexp *prog, char *string) -+{ -+ register char *s; -+ struct match_globals g; -+ -+ /* Be paranoid... */ -+ if (prog == NULL || string == NULL) { -+ printk("<3>Regexp: NULL parameter\n"); -+ return(0); -+ } -+ -+ /* Check validity of program. */ -+ if (UCHARAT(prog->program) != MAGIC) { -+ printk("<3>Regexp: corrupted program\n"); -+ return(0); -+ } -+ -+ /* If there is a "must appear" string, look for it. */ -+ if (prog->regmust != NULL) { -+ s = string; -+ while ((s = strchr(s, prog->regmust[0])) != NULL) { -+ if (strncmp(s, prog->regmust, prog->regmlen) == 0) -+ break; /* Found it. */ -+ s++; -+ } -+ if (s == NULL) /* Not present. */ -+ return(0); -+ } -+ -+ /* Mark beginning of line for ^ . */ -+ g.regbol = string; -+ -+ /* Simplest case: anchored match need be tried only once. */ -+ if (prog->reganch) -+ return(regtry(&g, prog, string)); -+ -+ /* Messy cases: unanchored match. */ -+ s = string; -+ if (prog->regstart != '\0') -+ /* We know what char it must start with. */ -+ while ((s = strchr(s, prog->regstart)) != NULL) { -+ if (regtry(&g, prog, s)) -+ return(1); -+ s++; -+ } -+ else -+ /* We don't -- general case. */ -+ do { -+ if (regtry(&g, prog, s)) -+ return(1); -+ } while (*s++ != '\0'); -+ -+ /* Failure. */ -+ return(0); -+} -+ -+/* -+ - regtry - try match at specific point -+ */ -+static int /* 0 failure, 1 success */ -+regtry(struct match_globals *g, regexp *prog, char *string) -+{ -+ register int i; -+ register char **sp; -+ register char **ep; -+ -+ g->reginput = string; -+ g->regstartp = prog->startp; -+ g->regendp = prog->endp; -+ -+ sp = prog->startp; -+ ep = prog->endp; -+ for (i = NSUBEXP; i > 0; i--) { -+ *sp++ = NULL; -+ *ep++ = NULL; -+ } -+ if (regmatch(g, prog->program + 1)) { -+ prog->startp[0] = string; -+ prog->endp[0] = g->reginput; -+ return(1); -+ } else -+ return(0); -+} -+ -+/* -+ - regmatch - main matching routine -+ * -+ * Conceptually the strategy is simple: check to see whether the current -+ * node matches, call self recursively to see whether the rest matches, -+ * and then act accordingly. In practice we make some effort to avoid -+ * recursion, in particular by going through "ordinary" nodes (that don't -+ * need to know whether the rest of the match failed) by a loop instead of -+ * by recursion. -+ */ -+static int /* 0 failure, 1 success */ -+regmatch(struct match_globals *g, char *prog) -+{ -+ register char *scan = prog; /* Current node. */ -+ char *next; /* Next node. */ -+ -+#ifdef DEBUG -+ if (scan != NULL && regnarrate) -+ fprintf(stderr, "%s(\n", regprop(scan)); -+#endif -+ while (scan != NULL) { -+#ifdef DEBUG -+ if (regnarrate) -+ fprintf(stderr, "%s...\n", regprop(scan)); -+#endif -+ next = regnext(g, scan); -+ -+ switch (OP(scan)) { -+ case BOL: -+ if (g->reginput != g->regbol) -+ return(0); -+ break; -+ case EOL: -+ if (*g->reginput != '\0') -+ return(0); -+ break; -+ case ANY: -+ if (*g->reginput == '\0') -+ return(0); -+ g->reginput++; -+ break; -+ case EXACTLY: { -+ register int len; -+ register char *opnd; -+ -+ opnd = OPERAND(scan); -+ /* Inline the first character, for speed. */ -+ if (*opnd != *g->reginput) -+ return(0); -+ len = strlen(opnd); -+ if (len > 1 && strncmp(opnd, g->reginput, len) != 0) -+ return(0); -+ g->reginput += len; -+ } -+ break; -+ case ANYOF: -+ if (*g->reginput == '\0' || strchr(OPERAND(scan), *g->reginput) == NULL) -+ return(0); -+ g->reginput++; -+ break; -+ case ANYBUT: -+ if (*g->reginput == '\0' || strchr(OPERAND(scan), *g->reginput) != NULL) -+ return(0); -+ g->reginput++; -+ break; -+ case NOTHING: -+ case BACK: -+ break; -+ case OPEN+1: -+ case OPEN+2: -+ case OPEN+3: -+ case OPEN+4: -+ case OPEN+5: -+ case OPEN+6: -+ case OPEN+7: -+ case OPEN+8: -+ case OPEN+9: { -+ register int no; -+ register char *save; -+ -+ no = OP(scan) - OPEN; -+ save = g->reginput; -+ -+ if (regmatch(g, next)) { -+ /* -+ * Don't set startp if some later -+ * invocation of the same parentheses -+ * already has. -+ */ -+ if (g->regstartp[no] == NULL) -+ g->regstartp[no] = save; -+ return(1); -+ } else -+ return(0); -+ } -+ break; -+ case CLOSE+1: -+ case CLOSE+2: -+ case CLOSE+3: -+ case CLOSE+4: -+ case CLOSE+5: -+ case CLOSE+6: -+ case CLOSE+7: -+ case CLOSE+8: -+ case CLOSE+9: -+ { -+ register int no; -+ register char *save; -+ -+ no = OP(scan) - CLOSE; -+ save = g->reginput; -+ -+ if (regmatch(g, next)) { -+ /* -+ * Don't set endp if some later -+ * invocation of the same parentheses -+ * already has. -+ */ -+ if (g->regendp[no] == NULL) -+ g->regendp[no] = save; -+ return(1); -+ } else -+ return(0); -+ } -+ break; -+ case BRANCH: { -+ register char *save; -+ -+ if (OP(next) != BRANCH) /* No choice. */ -+ next = OPERAND(scan); /* Avoid recursion. */ -+ else { -+ do { -+ save = g->reginput; -+ if (regmatch(g, OPERAND(scan))) -+ return(1); -+ g->reginput = save; -+ scan = regnext(g, scan); -+ } while (scan != NULL && OP(scan) == BRANCH); -+ return(0); -+ /* NOTREACHED */ -+ } -+ } -+ break; -+ case STAR: -+ case PLUS: { -+ register char nextch; -+ register int no; -+ register char *save; -+ register int min; -+ -+ /* -+ * Lookahead to avoid useless match attempts -+ * when we know what character comes next. -+ */ -+ nextch = '\0'; -+ if (OP(next) == EXACTLY) -+ nextch = *OPERAND(next); -+ min = (OP(scan) == STAR) ? 0 : 1; -+ save = g->reginput; -+ no = regrepeat(g, OPERAND(scan)); -+ while (no >= min) { -+ /* If it could work, try it. */ -+ if (nextch == '\0' || *g->reginput == nextch) -+ if (regmatch(g, next)) -+ return(1); -+ /* Couldn't or didn't -- back up. */ -+ no--; -+ g->reginput = save + no; -+ } -+ return(0); -+ } -+ break; -+ case END: -+ return(1); /* Success! */ -+ break; -+ default: -+ printk("<3>Regexp: memory corruption\n"); -+ return(0); -+ break; -+ } -+ -+ scan = next; -+ } -+ -+ /* -+ * We get here only if there's trouble -- normally "case END" is -+ * the terminating point. -+ */ -+ printk("<3>Regexp: corrupted pointers\n"); -+ return(0); -+} -+ -+/* -+ - regrepeat - repeatedly match something simple, report how many -+ */ -+static int -+regrepeat(struct match_globals *g, char *p) -+{ -+ register int count = 0; -+ register char *scan; -+ register char *opnd; -+ -+ scan = g->reginput; -+ opnd = OPERAND(p); -+ switch (OP(p)) { -+ case ANY: -+ count = strlen(scan); -+ scan += count; -+ break; -+ case EXACTLY: -+ while (*opnd == *scan) { -+ count++; -+ scan++; -+ } -+ break; -+ case ANYOF: -+ while (*scan != '\0' && strchr(opnd, *scan) != NULL) { -+ count++; -+ scan++; -+ } -+ break; -+ case ANYBUT: -+ while (*scan != '\0' && strchr(opnd, *scan) == NULL) { -+ count++; -+ scan++; -+ } -+ break; -+ default: /* Oh dear. Called inappropriately. */ -+ printk("<3>Regexp: internal foulup\n"); -+ count = 0; /* Best compromise. */ -+ break; -+ } -+ g->reginput = scan; -+ -+ return(count); -+} -+ -+/* -+ - regnext - dig the "next" pointer out of a node -+ */ -+static char* -+regnext(struct match_globals *g, char *p) -+{ -+ register int offset; -+ -+ if (p == &g->regdummy) -+ return(NULL); -+ -+ offset = NEXT(p); -+ if (offset == 0) -+ return(NULL); -+ -+ if (OP(p) == BACK) -+ return(p-offset); -+ else -+ return(p+offset); -+} -+ -+#ifdef DEBUG -+ -+STATIC char *regprop(); -+ -+/* -+ - regdump - dump a regexp onto stdout in vaguely comprehensible form -+ */ -+void -+regdump(regexp *r) -+{ -+ register char *s; -+ register char op = EXACTLY; /* Arbitrary non-END op. */ -+ register char *next; -+ /* extern char *strchr(); */ -+ -+ -+ s = r->program + 1; -+ while (op != END) { /* While that wasn't END last time... */ -+ op = OP(s); -+ printf("%2d%s", s-r->program, regprop(s)); /* Where, what. */ -+ next = regnext(s); -+ if (next == NULL) /* Next ptr. */ -+ printf("(0)"); -+ else -+ printf("(%d)", (s-r->program)+(next-s)); -+ s += 3; -+ if (op == ANYOF || op == ANYBUT || op == EXACTLY) { -+ /* Literal string, where present. */ -+ while (*s != '\0') { -+ putchar(*s); -+ s++; -+ } -+ s++; -+ } -+ putchar('\n'); -+ } -+ -+ /* Header fields of interest. */ -+ if (r->regstart != '\0') -+ printf("start `%c' ", r->regstart); -+ if (r->reganch) -+ printf("anchored "); -+ if (r->regmust != NULL) -+ printf("must have \"%s\"", r->regmust); -+ printf("\n"); -+} -+ -+/* -+ - regprop - printable representation of opcode -+ */ -+static char * -+regprop(char *op) -+{ -+#define BUFLEN 50 -+ register char *p; -+ static char buf[BUFLEN]; -+ -+ strcpy(buf, ":"); -+ -+ switch (OP(op)) { -+ case BOL: -+ p = "BOL"; -+ break; -+ case EOL: -+ p = "EOL"; -+ break; -+ case ANY: -+ p = "ANY"; -+ break; -+ case ANYOF: -+ p = "ANYOF"; -+ break; -+ case ANYBUT: -+ p = "ANYBUT"; -+ break; -+ case BRANCH: -+ p = "BRANCH"; -+ break; -+ case EXACTLY: -+ p = "EXACTLY"; -+ break; -+ case NOTHING: -+ p = "NOTHING"; -+ break; -+ case BACK: -+ p = "BACK"; -+ break; -+ case END: -+ p = "END"; -+ break; -+ case OPEN+1: -+ case OPEN+2: -+ case OPEN+3: -+ case OPEN+4: -+ case OPEN+5: -+ case OPEN+6: -+ case OPEN+7: -+ case OPEN+8: -+ case OPEN+9: -+ snprintf(buf+strlen(buf),BUFLEN-strlen(buf), "OPEN%d", OP(op)-OPEN); -+ p = NULL; -+ break; -+ case CLOSE+1: -+ case CLOSE+2: -+ case CLOSE+3: -+ case CLOSE+4: -+ case CLOSE+5: -+ case CLOSE+6: -+ case CLOSE+7: -+ case CLOSE+8: -+ case CLOSE+9: -+ snprintf(buf+strlen(buf),BUFLEN-strlen(buf), "CLOSE%d", OP(op)-CLOSE); -+ p = NULL; -+ break; -+ case STAR: -+ p = "STAR"; -+ break; -+ case PLUS: -+ p = "PLUS"; -+ break; -+ default: -+ printk("<3>Regexp: corrupted opcode\n"); -+ break; -+ } -+ if (p != NULL) -+ strncat(buf, p, BUFLEN-strlen(buf)); -+ return(buf); -+} -+#endif -+ -+ ---- /dev/null -+++ b/net/netfilter/regexp/regexp.h -@@ -0,0 +1,41 @@ -+/* -+ * Definitions etc. for regexp(3) routines. -+ * -+ * Caveat: this is V8 regexp(3) [actually, a reimplementation thereof], -+ * not the System V one. -+ */ -+ -+#ifndef REGEXP_H -+#define REGEXP_H -+ -+ -+/* -+http://www.opensource.apple.com/darwinsource/10.3/expect-1/expect/expect.h , -+which contains a version of this library, says: -+ -+ * -+ * NSUBEXP must be at least 10, and no greater than 117 or the parser -+ * will not work properly. -+ * -+ -+However, it looks rather like this library is limited to 10. If you think -+otherwise, let us know. -+*/ -+ -+#define NSUBEXP 10 -+typedef struct regexp { -+ char *startp[NSUBEXP]; -+ char *endp[NSUBEXP]; -+ char regstart; /* Internal use only. */ -+ char reganch; /* Internal use only. */ -+ char *regmust; /* Internal use only. */ -+ int regmlen; /* Internal use only. */ -+ char program[1]; /* Unwarranted chumminess with compiler. */ -+} regexp; -+ -+regexp * regcomp(char *exp, int *patternsize); -+int regexec(regexp *prog, char *string); -+void regsub(regexp *prog, char *source, char *dest); -+void regerror(char *s); -+ -+#endif ---- /dev/null -+++ b/net/netfilter/regexp/regmagic.h -@@ -0,0 +1,5 @@ -+/* -+ * The first byte of the regexp internal "program" is actually this magic -+ * number; the start node begins in the second byte. -+ */ -+#define MAGIC 0234 ---- /dev/null -+++ b/net/netfilter/regexp/regsub.c -@@ -0,0 +1,95 @@ -+/* -+ * regsub -+ * @(#)regsub.c 1.3 of 2 April 86 -+ * -+ * Copyright (c) 1986 by University of Toronto. -+ * Written by Henry Spencer. Not derived from licensed software. -+ * -+ * Permission is granted to anyone to use this software for any -+ * purpose on any computer system, and to redistribute it freely, -+ * subject to the following restrictions: -+ * -+ * 1. The author is not responsible for the consequences of use of -+ * this software, no matter how awful, even if they arise -+ * from defects in it. -+ * -+ * 2. The origin of this software must not be misrepresented, either -+ * by explicit claim or by omission. -+ * -+ * 3. Altered versions must be plainly marked as such, and must not -+ * be misrepresented as being the original software. -+ * -+ * -+ * This code was modified by Ethan Sommer to work within the kernel -+ * (it now uses kmalloc etc..) -+ * -+ */ -+#include "regexp.h" -+#include "regmagic.h" -+#include -+ -+ -+#ifndef CHARBITS -+#define UCHARAT(p) ((int)*(unsigned char *)(p)) -+#else -+#define UCHARAT(p) ((int)*(p)&CHARBITS) -+#endif -+ -+#if 0 -+//void regerror(char * s) -+//{ -+// printk("regexp(3): %s", s); -+// /* NOTREACHED */ -+//} -+#endif -+ -+/* -+ - regsub - perform substitutions after a regexp match -+ */ -+void -+regsub(regexp * prog, char * source, char * dest) -+{ -+ register char *src; -+ register char *dst; -+ register char c; -+ register int no; -+ register int len; -+ -+ /* Not necessary and gcc doesn't like it -MLS */ -+ /*extern char *strncpy();*/ -+ -+ if (prog == NULL || source == NULL || dest == NULL) { -+ regerror("NULL parm to regsub"); -+ return; -+ } -+ if (UCHARAT(prog->program) != MAGIC) { -+ regerror("damaged regexp fed to regsub"); -+ return; -+ } -+ -+ src = source; -+ dst = dest; -+ while ((c = *src++) != '\0') { -+ if (c == '&') -+ no = 0; -+ else if (c == '\\' && '0' <= *src && *src <= '9') -+ no = *src++ - '0'; -+ else -+ no = -1; -+ -+ if (no < 0) { /* Ordinary character. */ -+ if (c == '\\' && (*src == '\\' || *src == '&')) -+ c = *src++; -+ *dst++ = c; -+ } else if (prog->startp[no] != NULL && prog->endp[no] != NULL) { -+ len = prog->endp[no] - prog->startp[no]; -+ (void) strncpy(dst, prog->startp[no], len); -+ dst += len; -+ if (len != 0 && *(dst-1) == '\0') { /* strncpy hit NUL. */ -+ regerror("damaged match string"); -+ return; -+ } -+ } -+ } -+ *dst++ = '\0'; -+} ---- /dev/null -+++ b/net/netfilter/xt_layer7.c -@@ -0,0 +1,666 @@ -+/* -+ Kernel module to match application layer (OSI layer 7) data in connections. -+ -+ http://l7-filter.sf.net -+ -+ (C) 2003-2009 Matthew Strait and Ethan Sommer. -+ -+ 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. -+ http://www.gnu.org/licenses/gpl.txt -+ -+ Based on ipt_string.c (C) 2000 Emmanuel Roger , -+ xt_helper.c (C) 2002 Harald Welte and cls_layer7.c (C) 2003 Matthew Strait, -+ Ethan Sommer, Justin Levandoski. -+*/ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27) -+#include -+#include -+#endif -+#include -+#include -+#include -+#include -+ -+#include "regexp/regexp.c" -+ -+MODULE_LICENSE("GPL"); -+MODULE_AUTHOR("Matthew Strait , Ethan Sommer "); -+MODULE_DESCRIPTION("iptables application layer match module"); -+MODULE_ALIAS("ipt_layer7"); -+MODULE_VERSION("2.21"); -+ -+static int maxdatalen = 2048; // this is the default -+module_param(maxdatalen, int, 0444); -+MODULE_PARM_DESC(maxdatalen, "maximum bytes of data looked at by l7-filter"); -+#ifdef CONFIG_NETFILTER_XT_MATCH_LAYER7_DEBUG -+ #define DPRINTK(format,args...) printk(format,##args) -+#else -+ #define DPRINTK(format,args...) -+#endif -+ -+/* Number of packets whose data we look at. -+This can be modified through /proc/net/layer7_numpackets */ -+static int num_packets = 10; -+ -+static struct pattern_cache { -+ char * regex_string; -+ regexp * pattern; -+ struct pattern_cache * next; -+} * first_pattern_cache = NULL; -+ -+DEFINE_SPINLOCK(l7_lock); -+ -+static int total_acct_packets(struct nf_conn *ct) -+{ -+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 26) -+ BUG_ON(ct == NULL); -+ return (ct->counters[IP_CT_DIR_ORIGINAL].packets + ct->counters[IP_CT_DIR_REPLY].packets); -+#else -+ struct nf_conn_counter *acct; -+ -+ BUG_ON(ct == NULL); -+ acct = nf_conn_acct_find(ct); -+ if (!acct) -+ return 0; -+ return (acct[IP_CT_DIR_ORIGINAL].packets + acct[IP_CT_DIR_REPLY].packets); -+#endif -+} -+ -+#ifdef CONFIG_IP_NF_MATCH_LAYER7_DEBUG -+/* Converts an unfriendly string into a friendly one by -+replacing unprintables with periods and all whitespace with " ". */ -+static char * friendly_print(unsigned char * s) -+{ -+ char * f = kmalloc(strlen(s) + 1, GFP_ATOMIC); -+ int i; -+ -+ if(!f) { -+ if (net_ratelimit()) -+ printk(KERN_ERR "layer7: out of memory in " -+ "friendly_print, bailing.\n"); -+ return NULL; -+ } -+ -+ for(i = 0; i < strlen(s); i++){ -+ if(isprint(s[i]) && s[i] < 128) f[i] = s[i]; -+ else if(isspace(s[i])) f[i] = ' '; -+ else f[i] = '.'; -+ } -+ f[i] = '\0'; -+ return f; -+} -+ -+static char dec2hex(int i) -+{ -+ switch (i) { -+ case 0 ... 9: -+ return (i + '0'); -+ break; -+ case 10 ... 15: -+ return (i - 10 + 'a'); -+ break; -+ default: -+ if (net_ratelimit()) -+ printk("layer7: Problem in dec2hex\n"); -+ return '\0'; -+ } -+} -+ -+static char * hex_print(unsigned char * s) -+{ -+ char * g = kmalloc(strlen(s)*3 + 1, GFP_ATOMIC); -+ int i; -+ -+ if(!g) { -+ if (net_ratelimit()) -+ printk(KERN_ERR "layer7: out of memory in hex_print, " -+ "bailing.\n"); -+ return NULL; -+ } -+ -+ for(i = 0; i < strlen(s); i++) { -+ g[i*3 ] = dec2hex(s[i]/16); -+ g[i*3 + 1] = dec2hex(s[i]%16); -+ g[i*3 + 2] = ' '; -+ } -+ g[i*3] = '\0'; -+ -+ return g; -+} -+#endif // DEBUG -+ -+/* Use instead of regcomp. As we expect to be seeing the same regexps over and -+over again, it make sense to cache the results. */ -+static regexp * compile_and_cache(const char * regex_string, -+ const char * protocol) -+{ -+ struct pattern_cache * node = first_pattern_cache; -+ struct pattern_cache * last_pattern_cache = first_pattern_cache; -+ struct pattern_cache * tmp; -+ unsigned int len; -+ -+ while (node != NULL) { -+ if (!strcmp(node->regex_string, regex_string)) -+ return node->pattern; -+ -+ last_pattern_cache = node;/* points at the last non-NULL node */ -+ node = node->next; -+ } -+ -+ /* If we reach the end of the list, then we have not yet cached -+ the pattern for this regex. Let's do that now. -+ Be paranoid about running out of memory to avoid list corruption. */ -+ tmp = kmalloc(sizeof(struct pattern_cache), GFP_ATOMIC); -+ -+ if(!tmp) { -+ if (net_ratelimit()) -+ printk(KERN_ERR "layer7: out of memory in " -+ "compile_and_cache, bailing.\n"); -+ return NULL; -+ } -+ -+ tmp->regex_string = kmalloc(strlen(regex_string) + 1, GFP_ATOMIC); -+ tmp->pattern = kmalloc(sizeof(struct regexp), GFP_ATOMIC); -+ tmp->next = NULL; -+ -+ if(!tmp->regex_string || !tmp->pattern) { -+ if (net_ratelimit()) -+ printk(KERN_ERR "layer7: out of memory in " -+ "compile_and_cache, bailing.\n"); -+ kfree(tmp->regex_string); -+ kfree(tmp->pattern); -+ kfree(tmp); -+ return NULL; -+ } -+ -+ /* Ok. The new node is all ready now. */ -+ node = tmp; -+ -+ if(first_pattern_cache == NULL) /* list is empty */ -+ first_pattern_cache = node; /* make node the beginning */ -+ else -+ last_pattern_cache->next = node; /* attach node to the end */ -+ -+ /* copy the string and compile the regex */ -+ len = strlen(regex_string); -+ DPRINTK("About to compile this: \"%s\"\n", regex_string); -+ node->pattern = regcomp((char *)regex_string, &len); -+ if ( !node->pattern ) { -+ if (net_ratelimit()) -+ printk(KERN_ERR "layer7: Error compiling regexp " -+ "\"%s\" (%s)\n", -+ regex_string, protocol); -+ /* pattern is now cached as NULL, so we won't try again. */ -+ } -+ -+ strcpy(node->regex_string, regex_string); -+ return node->pattern; -+} -+ -+static int can_handle(const struct sk_buff *skb) -+{ -+ if(!ip_hdr(skb)) /* not IP */ -+ return 0; -+ if(ip_hdr(skb)->protocol != IPPROTO_TCP && -+ ip_hdr(skb)->protocol != IPPROTO_UDP && -+ ip_hdr(skb)->protocol != IPPROTO_ICMP) -+ return 0; -+ return 1; -+} -+ -+/* Returns offset the into the skb->data that the application data starts */ -+static int app_data_offset(const struct sk_buff *skb) -+{ -+ /* In case we are ported somewhere (ebtables?) where ip_hdr(skb) -+ isn't set, this can be gotten from 4*(skb->data[0] & 0x0f) as well. */ -+ int ip_hl = 4*ip_hdr(skb)->ihl; -+ -+ if( ip_hdr(skb)->protocol == IPPROTO_TCP ) { -+ /* 12 == offset into TCP header for the header length field. -+ Can't get this with skb->h.th->doff because the tcphdr -+ struct doesn't get set when routing (this is confirmed to be -+ true in Netfilter as well as QoS.) */ -+ int tcp_hl = 4*(skb->data[ip_hl + 12] >> 4); -+ -+ return ip_hl + tcp_hl; -+ } else if( ip_hdr(skb)->protocol == IPPROTO_UDP ) { -+ return ip_hl + 8; /* UDP header is always 8 bytes */ -+ } else if( ip_hdr(skb)->protocol == IPPROTO_ICMP ) { -+ return ip_hl + 8; /* ICMP header is 8 bytes */ -+ } else { -+ if (net_ratelimit()) -+ printk(KERN_ERR "layer7: tried to handle unknown " -+ "protocol!\n"); -+ return ip_hl + 8; /* something reasonable */ -+ } -+} -+ -+/* handles whether there's a match when we aren't appending data anymore */ -+static int match_no_append(struct nf_conn * conntrack, -+ struct nf_conn * master_conntrack, -+ enum ip_conntrack_info ctinfo, -+ enum ip_conntrack_info master_ctinfo, -+ const struct xt_layer7_info * info) -+{ -+ /* If we're in here, throw the app data away */ -+ if(master_conntrack->layer7.app_data != NULL) { -+ -+ #ifdef CONFIG_IP_NF_MATCH_LAYER7_DEBUG -+ if(!master_conntrack->layer7.app_proto) { -+ char * f = -+ friendly_print(master_conntrack->layer7.app_data); -+ char * g = -+ hex_print(master_conntrack->layer7.app_data); -+ DPRINTK("\nl7-filter gave up after %d bytes " -+ "(%d packets):\n%s\n", -+ strlen(f), total_acct_packets(master_conntrack), f); -+ kfree(f); -+ DPRINTK("In hex: %s\n", g); -+ kfree(g); -+ } -+ #endif -+ -+ kfree(master_conntrack->layer7.app_data); -+ master_conntrack->layer7.app_data = NULL; /* don't free again */ -+ } -+ -+ if(master_conntrack->layer7.app_proto){ -+ /* Here child connections set their .app_proto (for /proc) */ -+ if(!conntrack->layer7.app_proto) { -+ conntrack->layer7.app_proto = -+ kmalloc(strlen(master_conntrack->layer7.app_proto)+1, -+ GFP_ATOMIC); -+ if(!conntrack->layer7.app_proto){ -+ if (net_ratelimit()) -+ printk(KERN_ERR "layer7: out of memory " -+ "in match_no_append, " -+ "bailing.\n"); -+ return 1; -+ } -+ strcpy(conntrack->layer7.app_proto, -+ master_conntrack->layer7.app_proto); -+ } -+ -+ return (!strcmp(master_conntrack->layer7.app_proto, -+ info->protocol)); -+ } -+ else { -+ /* If not classified, set to "unknown" to distinguish from -+ connections that are still being tested. */ -+ master_conntrack->layer7.app_proto = -+ kmalloc(strlen("unknown")+1, GFP_ATOMIC); -+ if(!master_conntrack->layer7.app_proto){ -+ if (net_ratelimit()) -+ printk(KERN_ERR "layer7: out of memory in " -+ "match_no_append, bailing.\n"); -+ return 1; -+ } -+ strcpy(master_conntrack->layer7.app_proto, "unknown"); -+ return 0; -+ } -+} -+ -+/* 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 = 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; -+ -+ /* 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++) { -+ if(app_data[i] != '\0') { -+ /* the kernel version of tolower mungs 'upper ascii' */ -+ master_conntrack->layer7.app_data[length+oldlength] = -+ isascii(app_data[i])? -+ tolower(app_data[i]) : app_data[i]; -+ length++; -+ } -+ } -+ -+ master_conntrack->layer7.app_data[length+oldlength] = '\0'; -+ master_conntrack->layer7.app_data_len = length + oldlength; -+ -+ return length; -+} -+ -+/* taken from drivers/video/modedb.c */ -+static int my_atoi(const char *s) -+{ -+ int val = 0; -+ -+ for (;; s++) { -+ switch (*s) { -+ case '0'...'9': -+ val = 10*val+(*s-'0'); -+ break; -+ default: -+ return val; -+ } -+ } -+} -+ -+/* write out num_packets to userland. */ -+static int layer7_read_proc(char* page, char ** start, off_t off, int count, -+ int* eof, void * data) -+{ -+ if(num_packets > 99 && net_ratelimit()) -+ printk(KERN_ERR "layer7: NOT REACHED. num_packets too big\n"); -+ -+ page[0] = num_packets/10 + '0'; -+ page[1] = num_packets%10 + '0'; -+ page[2] = '\n'; -+ page[3] = '\0'; -+ -+ *eof=1; -+ -+ return 3; -+} -+ -+/* Read in num_packets from userland */ -+static int layer7_write_proc(struct file* file, const char* buffer, -+ unsigned long count, void *data) -+{ -+ char * foo = kmalloc(count, GFP_ATOMIC); -+ -+ if(!foo){ -+ if (net_ratelimit()) -+ printk(KERN_ERR "layer7: out of memory, bailing. " -+ "num_packets unchanged.\n"); -+ return count; -+ } -+ -+ if(copy_from_user(foo, buffer, count)) { -+ return -EFAULT; -+ } -+ -+ -+ num_packets = my_atoi(foo); -+ kfree (foo); -+ -+ /* This has an arbitrary limit to make the math easier. I'm lazy. -+ But anyway, 99 is a LOT! If you want more, you're doing it wrong! */ -+ if(num_packets > 99) { -+ printk(KERN_WARNING "layer7: num_packets can't be > 99.\n"); -+ num_packets = 99; -+ } else if(num_packets < 1) { -+ printk(KERN_WARNING "layer7: num_packets can't be < 1.\n"); -+ num_packets = 1; -+ } -+ -+ return count; -+} -+ -+static bool -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28) -+match(const struct sk_buff *skbin, const struct xt_match_param *par) -+#else -+match(const struct sk_buff *skbin, -+ const struct net_device *in, -+ const struct net_device *out, -+ const struct xt_match *match, -+ const void *matchinfo, -+ int offset, -+ unsigned int protoff, -+ bool *hotdrop) -+#endif -+{ -+ /* sidestep const without getting a compiler warning... */ -+ struct sk_buff * skb = (struct sk_buff *)skbin; -+ -+ const struct xt_layer7_info * info = -+ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28) -+ par->matchinfo; -+ #else -+ matchinfo; -+ #endif -+ -+ enum ip_conntrack_info master_ctinfo, ctinfo; -+ struct nf_conn *master_conntrack, *conntrack; -+ unsigned char * app_data; -+ unsigned int pattern_result, appdatalen; -+ regexp * comppattern; -+ -+ /* Be paranoid/incompetent - lock the entire match function. */ -+ spin_lock_bh(&l7_lock); -+ -+ if(!can_handle(skb)){ -+ DPRINTK("layer7: This is some protocol I can't handle.\n"); -+ spin_unlock_bh(&l7_lock); -+ return info->invert; -+ } -+ -+ /* Treat parent & all its children together as one connection, except -+ for the purpose of setting conntrack->layer7.app_proto in the actual -+ connection. This makes /proc/net/ip_conntrack more satisfying. */ -+ if(!(conntrack = nf_ct_get(skb, &ctinfo)) || -+ !(master_conntrack=nf_ct_get(skb,&master_ctinfo))){ -+ DPRINTK("layer7: couldn't get conntrack.\n"); -+ spin_unlock_bh(&l7_lock); -+ return info->invert; -+ } -+ -+ /* Try to get a master conntrack (and its master etc) for FTP, etc. */ -+ while (master_ct(master_conntrack) != NULL) -+ 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) { -+ -+ pattern_result = match_no_append(conntrack, master_conntrack, -+ ctinfo, master_ctinfo, info); -+ -+ /* skb->cb[0] == seen. Don't do things twice if there are -+ multiple l7 rules. I'm not sure that using cb for this purpose -+ is correct, even though it says "put your private variables -+ there". But it doesn't look like it is being used for anything -+ else in the skbs that make it here. */ -+ skb->cb[0] = 1; /* marking it seen here's probably irrelevant */ -+ -+ spin_unlock_bh(&l7_lock); -+ return (pattern_result ^ info->invert); -+ } -+ -+ if(skb_is_nonlinear(skb)){ -+ if(skb_linearize(skb) != 0){ -+ if (net_ratelimit()) -+ printk(KERN_ERR "layer7: failed to linearize " -+ "packet, bailing.\n"); -+ spin_unlock_bh(&l7_lock); -+ return info->invert; -+ } -+ } -+ -+ /* now that the skb is linearized, it's safe to set these. */ -+ app_data = skb->data + app_data_offset(skb); -+ appdatalen = skb_tail_pointer(skb) - app_data; -+ -+ /* the return value gets checked later, when we're ready to use it */ -+ comppattern = compile_and_cache(info->pattern, info->protocol); -+ -+ /* 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){ -+ master_conntrack->layer7.app_data = -+ kmalloc(maxdatalen, GFP_ATOMIC); -+ if(!master_conntrack->layer7.app_data){ -+ if (net_ratelimit()) -+ printk(KERN_ERR "layer7: out of memory in " -+ "match, bailing.\n"); -+ spin_unlock_bh(&l7_lock); -+ return info->invert; -+ } -+ -+ master_conntrack->layer7.app_data[0] = '\0'; -+ } -+ -+ /* Can be here, but unallocated, if numpackets is increased near -+ the beginning of a connection */ -+ if(master_conntrack->layer7.app_data == NULL){ -+ spin_unlock_bh(&l7_lock); -+ return info->invert; /* unmatched */ -+ } -+ -+ if(!skb->cb[0]){ -+ int newbytes; -+ newbytes = add_data(master_conntrack, app_data, appdatalen); -+ -+ if(newbytes == 0) { /* didn't add any data */ -+ skb->cb[0] = 1; -+ /* Didn't match before, not going to match now */ -+ spin_unlock_bh(&l7_lock); -+ return info->invert; -+ } -+ } -+ -+ /* If looking for "unknown", then never match. "Unknown" means that -+ we've given up; we're still trying with these packets. */ -+ if(!strcmp(info->protocol, "unknown")) { -+ pattern_result = 0; -+ /* If looking for "unset", then always match. "Unset" means that we -+ haven't yet classified the connection. */ -+ } else if(!strcmp(info->protocol, "unset")) { -+ pattern_result = 2; -+ DPRINTK("layer7: matched unset: not yet classified " -+ "(%d/%d packets)\n", -+ total_acct_packets(master_conntrack), num_packets); -+ /* If the regexp failed to compile, don't bother running it */ -+ } else if(comppattern && -+ regexec(comppattern, master_conntrack->layer7.app_data)){ -+ DPRINTK("layer7: matched %s\n", info->protocol); -+ pattern_result = 1; -+ } else pattern_result = 0; -+ -+ if(pattern_result == 1) { -+ master_conntrack->layer7.app_proto = -+ kmalloc(strlen(info->protocol)+1, GFP_ATOMIC); -+ if(!master_conntrack->layer7.app_proto){ -+ if (net_ratelimit()) -+ printk(KERN_ERR "layer7: out of memory in " -+ "match, bailing.\n"); -+ spin_unlock_bh(&l7_lock); -+ return (pattern_result ^ info->invert); -+ } -+ strcpy(master_conntrack->layer7.app_proto, info->protocol); -+ } else if(pattern_result > 1) { /* cleanup from "unset" */ -+ pattern_result = 1; -+ } -+ -+ /* mark the packet seen */ -+ skb->cb[0] = 1; -+ -+ spin_unlock_bh(&l7_lock); -+ return (pattern_result ^ info->invert); -+} -+ -+// load nf_conntrack_ipv4 -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28) -+static bool check(const struct xt_mtchk_param *par) -+{ -+ if (nf_ct_l3proto_try_module_get(par->match->family) < 0) { -+ printk(KERN_WARNING "can't load conntrack support for " -+ "proto=%d\n", par->match->family); -+#else -+static bool check(const char *tablename, const void *inf, -+ const struct xt_match *match, void *matchinfo, -+ unsigned int hook_mask) -+{ -+ if (nf_ct_l3proto_try_module_get(match->family) < 0) { -+ printk(KERN_WARNING "can't load conntrack support for " -+ "proto=%d\n", match->family); -+#endif -+ return 0; -+ } -+ return 1; -+} -+ -+ -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28) -+ static void destroy(const struct xt_mtdtor_param *par) -+ { -+ nf_ct_l3proto_module_put(par->match->family); -+ } -+#else -+ static void destroy(const struct xt_match *match, void *matchinfo) -+ { -+ nf_ct_l3proto_module_put(match->family); -+ } -+#endif -+ -+static struct xt_match xt_layer7_match[] __read_mostly = { -+{ -+ .name = "layer7", -+ .family = AF_INET, -+ .checkentry = check, -+ .match = match, -+ .destroy = destroy, -+ .matchsize = sizeof(struct xt_layer7_info), -+ .me = THIS_MODULE -+} -+}; -+ -+static void layer7_cleanup_proc(void) -+{ -+ remove_proc_entry("layer7_numpackets", init_net.proc_net); -+} -+ -+/* register the proc file */ -+static void layer7_init_proc(void) -+{ -+ struct proc_dir_entry* entry; -+ entry = create_proc_entry("layer7_numpackets", 0644, init_net.proc_net); -+ entry->read_proc = layer7_read_proc; -+ entry->write_proc = layer7_write_proc; -+} -+ -+static int __init xt_layer7_init(void) -+{ -+ need_conntrack(); -+ -+ layer7_init_proc(); -+ if(maxdatalen < 1) { -+ printk(KERN_WARNING "layer7: maxdatalen can't be < 1, " -+ "using 1\n"); -+ maxdatalen = 1; -+ } -+ /* This is not a hard limit. It's just here to prevent people from -+ bringing their slow machines to a grinding halt. */ -+ else if(maxdatalen > 65536) { -+ printk(KERN_WARNING "layer7: maxdatalen can't be > 65536, " -+ "using 65536\n"); -+ maxdatalen = 65536; -+ } -+ return xt_register_matches(xt_layer7_match, -+ ARRAY_SIZE(xt_layer7_match)); -+} -+ -+static void __exit xt_layer7_fini(void) -+{ -+ layer7_cleanup_proc(); -+ xt_unregister_matches(xt_layer7_match, ARRAY_SIZE(xt_layer7_match)); -+} -+ -+module_init(xt_layer7_init); -+module_exit(xt_layer7_fini); diff --git a/target/linux/generic-2.6/patches-2.6.28/101-netfilter_layer7_pktmatch.patch b/target/linux/generic-2.6/patches-2.6.28/101-netfilter_layer7_pktmatch.patch deleted file mode 100644 index f65e301fd..000000000 --- a/target/linux/generic-2.6/patches-2.6.28/101-netfilter_layer7_pktmatch.patch +++ /dev/null @@ -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){ diff --git a/target/linux/generic-2.6/patches-2.6.28/110-netfilter_match_speedup.patch b/target/linux/generic-2.6/patches-2.6.28/110-netfilter_match_speedup.patch deleted file mode 100644 index 8aa1f08cd..000000000 --- a/target/linux/generic-2.6/patches-2.6.28/110-netfilter_match_speedup.patch +++ /dev/null @@ -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, -@@ -151,13 +154,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; -@@ -167,6 +192,8 @@ ip_checkentry(const struct ipt_ip *ip) - ip->invflags & ~IPT_INV_MASK); - return false; - } -+ -+#undef FWINV - return true; - } - -@@ -214,7 +241,6 @@ unconditional(const struct ipt_ip *ip) - return 0; - - return 1; --#undef FWINV - } - - #if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \ -@@ -332,8 +358,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; -@@ -351,12 +396,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]); - diff --git a/target/linux/generic-2.6/patches-2.6.28/130-netfilter_ipset.patch b/target/linux/generic-2.6/patches-2.6.28/130-netfilter_ipset.patch deleted file mode 100644 index f127533d2..000000000 --- a/target/linux/generic-2.6/patches-2.6.28/130-netfilter_ipset.patch +++ /dev/null @@ -1,7749 +0,0 @@ ---- a/include/linux/netfilter_ipv4/Kbuild -+++ b/include/linux/netfilter_ipv4/Kbuild -@@ -45,3 +45,20 @@ header-y += ipt_ttl.h - - unifdef-y += ip_queue.h - unifdef-y += ip_tables.h -+ -+unifdef-y += ip_set.h -+header-y += ip_set_iphash.h -+unifdef-y += ip_set_bitmaps.h -+unifdef-y += ip_set_getport.h -+unifdef-y += ip_set_hashes.h -+header-y += ip_set_ipmap.h -+header-y += ip_set_ipporthash.h -+header-y += ip_set_ipportiphash.h -+header-y += ip_set_ipportnethash.h -+unifdef-y += ip_set_iptree.h -+unifdef-y += ip_set_iptreemap.h -+header-y += ip_set_jhash.h -+header-y += ip_set_macipmap.h -+header-y += ip_set_nethash.h -+header-y += ip_set_portmap.h -+header-y += ip_set_setlist.h ---- /dev/null -+++ b/include/linux/netfilter_ipv4/ip_set.h -@@ -0,0 +1,574 @@ -+#ifndef _IP_SET_H -+#define _IP_SET_H -+ -+/* Copyright (C) 2000-2002 Joakim Axelsson -+ * Patrick Schaaf -+ * Martin Josefsson -+ * Copyright (C) 2003-2004 Jozsef Kadlecsik -+ * -+ * 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. -+ */ -+ -+#if 0 -+#define IP_SET_DEBUG -+#endif -+ -+/* -+ * A sockopt of such quality has hardly ever been seen before on the open -+ * market! This little beauty, hardly ever used: above 64, so it's -+ * traditionally used for firewalling, not touched (even once!) by the -+ * 2.0, 2.2 and 2.4 kernels! -+ * -+ * Comes with its own certificate of authenticity, valid anywhere in the -+ * Free world! -+ * -+ * Rusty, 19.4.2000 -+ */ -+#define SO_IP_SET 83 -+ -+/* -+ * Heavily modify by Joakim Axelsson 08.03.2002 -+ * - Made it more modulebased -+ * -+ * Additional heavy modifications by Jozsef Kadlecsik 22.02.2004 -+ * - bindings added -+ * - in order to "deal with" backward compatibility, renamed to ipset -+ */ -+ -+/* -+ * Used so that the kernel module and ipset-binary can match their versions -+ */ -+#define IP_SET_PROTOCOL_VERSION 3 -+ -+#define IP_SET_MAXNAMELEN 32 /* set names and set typenames */ -+ -+/* Lets work with our own typedef for representing an IP address. -+ * We hope to make the code more portable, possibly to IPv6... -+ * -+ * The representation works in HOST byte order, because most set types -+ * will perform arithmetic operations and compare operations. -+ * -+ * For now the type is an uint32_t. -+ * -+ * Make sure to ONLY use the functions when translating and parsing -+ * in order to keep the host byte order and make it more portable: -+ * parse_ip() -+ * parse_mask() -+ * parse_ipandmask() -+ * ip_tostring() -+ * (Joakim: where are they???) -+ */ -+ -+typedef uint32_t ip_set_ip_t; -+ -+/* Sets are identified by an id in kernel space. Tweak with ip_set_id_t -+ * and IP_SET_INVALID_ID if you want to increase the max number of sets. -+ */ -+typedef uint16_t ip_set_id_t; -+ -+#define IP_SET_INVALID_ID 65535 -+ -+/* How deep we follow bindings */ -+#define IP_SET_MAX_BINDINGS 6 -+ -+/* -+ * Option flags for kernel operations (ipt_set_info) -+ */ -+#define IPSET_SRC 0x01 /* Source match/add */ -+#define IPSET_DST 0x02 /* Destination match/add */ -+#define IPSET_MATCH_INV 0x04 /* Inverse matching */ -+ -+/* -+ * Set features -+ */ -+#define IPSET_TYPE_IP 0x01 /* IP address type of set */ -+#define IPSET_TYPE_PORT 0x02 /* Port type of set */ -+#define IPSET_DATA_SINGLE 0x04 /* Single data storage */ -+#define IPSET_DATA_DOUBLE 0x08 /* Double data storage */ -+#define IPSET_DATA_TRIPLE 0x10 /* Triple data storage */ -+#define IPSET_TYPE_IP1 0x20 /* IP address type of set */ -+#define IPSET_TYPE_SETNAME 0x40 /* setname type of set */ -+ -+/* Reserved keywords */ -+#define IPSET_TOKEN_DEFAULT ":default:" -+#define IPSET_TOKEN_ALL ":all:" -+ -+/* SO_IP_SET operation constants, and their request struct types. -+ * -+ * Operation ids: -+ * 0-99: commands with version checking -+ * 100-199: add/del/test/bind/unbind -+ * 200-299: list, save, restore -+ */ -+ -+/* Single shot operations: -+ * version, create, destroy, flush, rename and swap -+ * -+ * Sets are identified by name. -+ */ -+ -+#define IP_SET_REQ_STD \ -+ unsigned op; \ -+ unsigned version; \ -+ char name[IP_SET_MAXNAMELEN] -+ -+#define IP_SET_OP_CREATE 0x00000001 /* Create a new (empty) set */ -+struct ip_set_req_create { -+ IP_SET_REQ_STD; -+ char typename[IP_SET_MAXNAMELEN]; -+}; -+ -+#define IP_SET_OP_DESTROY 0x00000002 /* Remove a (empty) set */ -+struct ip_set_req_std { -+ IP_SET_REQ_STD; -+}; -+ -+#define IP_SET_OP_FLUSH 0x00000003 /* Remove all IPs in a set */ -+/* Uses ip_set_req_std */ -+ -+#define IP_SET_OP_RENAME 0x00000004 /* Rename a set */ -+/* Uses ip_set_req_create */ -+ -+#define IP_SET_OP_SWAP 0x00000005 /* Swap two sets */ -+/* Uses ip_set_req_create */ -+ -+union ip_set_name_index { -+ char name[IP_SET_MAXNAMELEN]; -+ ip_set_id_t index; -+}; -+ -+#define IP_SET_OP_GET_BYNAME 0x00000006 /* Get set index by name */ -+struct ip_set_req_get_set { -+ unsigned op; -+ unsigned version; -+ union ip_set_name_index set; -+}; -+ -+#define IP_SET_OP_GET_BYINDEX 0x00000007 /* Get set name by index */ -+/* Uses ip_set_req_get_set */ -+ -+#define IP_SET_OP_VERSION 0x00000100 /* Ask kernel version */ -+struct ip_set_req_version { -+ unsigned op; -+ unsigned version; -+}; -+ -+/* Double shots operations: -+ * add, del, test, bind and unbind. -+ * -+ * First we query the kernel to get the index and type of the target set, -+ * then issue the command. Validity of IP is checked in kernel in order -+ * to minimalize sockopt operations. -+ */ -+ -+/* Get minimal set data for add/del/test/bind/unbind IP */ -+#define IP_SET_OP_ADT_GET 0x00000010 /* Get set and type */ -+struct ip_set_req_adt_get { -+ unsigned op; -+ unsigned version; -+ union ip_set_name_index set; -+ char typename[IP_SET_MAXNAMELEN]; -+}; -+ -+#define IP_SET_REQ_BYINDEX \ -+ unsigned op; \ -+ ip_set_id_t index; -+ -+struct ip_set_req_adt { -+ IP_SET_REQ_BYINDEX; -+}; -+ -+#define IP_SET_OP_ADD_IP 0x00000101 /* Add an IP to a set */ -+/* Uses ip_set_req_adt, with type specific addage */ -+ -+#define IP_SET_OP_DEL_IP 0x00000102 /* Remove an IP from a set */ -+/* Uses ip_set_req_adt, with type specific addage */ -+ -+#define IP_SET_OP_TEST_IP 0x00000103 /* Test an IP in a set */ -+/* Uses ip_set_req_adt, with type specific addage */ -+ -+#define IP_SET_OP_BIND_SET 0x00000104 /* Bind an IP to a set */ -+/* Uses ip_set_req_bind, with type specific addage */ -+struct ip_set_req_bind { -+ IP_SET_REQ_BYINDEX; -+ char binding[IP_SET_MAXNAMELEN]; -+}; -+ -+#define IP_SET_OP_UNBIND_SET 0x00000105 /* Unbind an IP from a set */ -+/* Uses ip_set_req_bind, with type speficic addage -+ * index = 0 means unbinding for all sets */ -+ -+#define IP_SET_OP_TEST_BIND_SET 0x00000106 /* Test binding an IP to a set */ -+/* Uses ip_set_req_bind, with type specific addage */ -+ -+/* Multiple shots operations: list, save, restore. -+ * -+ * - check kernel version and query the max number of sets -+ * - get the basic information on all sets -+ * and size required for the next step -+ * - get actual set data: header, data, bindings -+ */ -+ -+/* Get max_sets and the index of a queried set -+ */ -+#define IP_SET_OP_MAX_SETS 0x00000020 -+struct ip_set_req_max_sets { -+ unsigned op; -+ unsigned version; -+ ip_set_id_t max_sets; /* max_sets */ -+ ip_set_id_t sets; /* real number of sets */ -+ union ip_set_name_index set; /* index of set if name used */ -+}; -+ -+/* Get the id and name of the sets plus size for next step */ -+#define IP_SET_OP_LIST_SIZE 0x00000201 -+#define IP_SET_OP_SAVE_SIZE 0x00000202 -+struct ip_set_req_setnames { -+ unsigned op; -+ ip_set_id_t index; /* set to list/save */ -+ u_int32_t size; /* size to get setdata/bindings */ -+ /* followed by sets number of struct ip_set_name_list */ -+}; -+ -+struct ip_set_name_list { -+ char name[IP_SET_MAXNAMELEN]; -+ char typename[IP_SET_MAXNAMELEN]; -+ ip_set_id_t index; -+ ip_set_id_t id; -+}; -+ -+/* The actual list operation */ -+#define IP_SET_OP_LIST 0x00000203 -+struct ip_set_req_list { -+ IP_SET_REQ_BYINDEX; -+ /* sets number of struct ip_set_list in reply */ -+}; -+ -+struct ip_set_list { -+ ip_set_id_t index; -+ ip_set_id_t binding; -+ u_int32_t ref; -+ u_int32_t header_size; /* Set header data of header_size */ -+ u_int32_t members_size; /* Set members data of members_size */ -+ u_int32_t bindings_size;/* Set bindings data of bindings_size */ -+}; -+ -+struct ip_set_hash_list { -+ ip_set_ip_t ip; -+ ip_set_id_t binding; -+}; -+ -+/* The save operation */ -+#define IP_SET_OP_SAVE 0x00000204 -+/* Uses ip_set_req_list, in the reply replaced by -+ * sets number of struct ip_set_save plus a marker -+ * ip_set_save followed by ip_set_hash_save structures. -+ */ -+struct ip_set_save { -+ ip_set_id_t index; -+ ip_set_id_t binding; -+ u_int32_t header_size; /* Set header data of header_size */ -+ u_int32_t members_size; /* Set members data of members_size */ -+}; -+ -+/* At restoring, ip == 0 means default binding for the given set: */ -+struct ip_set_hash_save { -+ ip_set_ip_t ip; -+ ip_set_id_t id; -+ ip_set_id_t binding; -+}; -+ -+/* The restore operation */ -+#define IP_SET_OP_RESTORE 0x00000205 -+/* Uses ip_set_req_setnames followed by ip_set_restore structures -+ * plus a marker ip_set_restore, followed by ip_set_hash_save -+ * structures. -+ */ -+struct ip_set_restore { -+ char name[IP_SET_MAXNAMELEN]; -+ char typename[IP_SET_MAXNAMELEN]; -+ ip_set_id_t index; -+ u_int32_t header_size; /* Create data of header_size */ -+ u_int32_t members_size; /* Set members data of members_size */ -+}; -+ -+static inline int bitmap_bytes(ip_set_ip_t a, ip_set_ip_t b) -+{ -+ return 4 * ((((b - a + 8) / 8) + 3) / 4); -+} -+ -+/* General limit for the elements in a set */ -+#define MAX_RANGE 0x0000FFFF -+ -+#ifdef __KERNEL__ -+#include -+#include -+ -+#define ip_set_printk(format, args...) \ -+ do { \ -+ printk("%s: %s: ", __FILE__, __FUNCTION__); \ -+ printk(format "\n" , ## args); \ -+ } while (0) -+ -+#if defined(IP_SET_DEBUG) -+#define DP(format, args...) \ -+ do { \ -+ printk("%s: %s (DBG): ", __FILE__, __FUNCTION__);\ -+ printk(format "\n" , ## args); \ -+ } while (0) -+#define IP_SET_ASSERT(x) \ -+ do { \ -+ if (!(x)) \ -+ printk("IP_SET_ASSERT: %s:%i(%s)\n", \ -+ __FILE__, __LINE__, __FUNCTION__); \ -+ } while (0) -+#else -+#define DP(format, args...) -+#define IP_SET_ASSERT(x) -+#endif -+ -+struct ip_set; -+ -+/* -+ * The ip_set_type definition - one per set type, e.g. "ipmap". -+ * -+ * Each individual set has a pointer, set->type, going to one -+ * of these structures. Function pointers inside the structure implement -+ * the real behaviour of the sets. -+ * -+ * If not mentioned differently, the implementation behind the function -+ * pointers of a set_type, is expected to return 0 if ok, and a negative -+ * errno (e.g. -EINVAL) on error. -+ */ -+struct ip_set_type { -+ struct list_head list; /* next in list of set types */ -+ -+ /* test for IP in set (kernel: iptables -m set src|dst) -+ * return 0 if not in set, 1 if in set. -+ */ -+ int (*testip_kernel) (struct ip_set *set, -+ const struct sk_buff * skb, -+ ip_set_ip_t *ip, -+ const u_int32_t *flags, -+ unsigned char index); -+ -+ /* test for IP in set (userspace: ipset -T set IP) -+ * return 0 if not in set, 1 if in set. -+ */ -+ int (*testip) (struct ip_set *set, -+ const void *data, u_int32_t size, -+ ip_set_ip_t *ip); -+ -+ /* -+ * Size of the data structure passed by when -+ * adding/deletin/testing an entry. -+ */ -+ u_int32_t reqsize; -+ -+ /* Add IP into set (userspace: ipset -A set IP) -+ * Return -EEXIST if the address is already in the set, -+ * and -ERANGE if the address lies outside the set bounds. -+ * If the address was not already in the set, 0 is returned. -+ */ -+ int (*addip) (struct ip_set *set, -+ const void *data, u_int32_t size, -+ ip_set_ip_t *ip); -+ -+ /* Add IP into set (kernel: iptables ... -j SET set src|dst) -+ * Return -EEXIST if the address is already in the set, -+ * and -ERANGE if the address lies outside the set bounds. -+ * If the address was not already in the set, 0 is returned. -+ */ -+ int (*addip_kernel) (struct ip_set *set, -+ const struct sk_buff * skb, -+ ip_set_ip_t *ip, -+ const u_int32_t *flags, -+ unsigned char index); -+ -+ /* remove IP from set (userspace: ipset -D set --entry x) -+ * Return -EEXIST if the address is NOT in the set, -+ * and -ERANGE if the address lies outside the set bounds. -+ * If the address really was in the set, 0 is returned. -+ */ -+ int (*delip) (struct ip_set *set, -+ const void *data, u_int32_t size, -+ ip_set_ip_t *ip); -+ -+ /* remove IP from set (kernel: iptables ... -j SET --entry x) -+ * Return -EEXIST if the address is NOT in the set, -+ * and -ERANGE if the address lies outside the set bounds. -+ * If the address really was in the set, 0 is returned. -+ */ -+ int (*delip_kernel) (struct ip_set *set, -+ const struct sk_buff * skb, -+ ip_set_ip_t *ip, -+ const u_int32_t *flags, -+ unsigned char index); -+ -+ /* new set creation - allocated type specific items -+ */ -+ int (*create) (struct ip_set *set, -+ const void *data, u_int32_t size); -+ -+ /* retry the operation after successfully tweaking the set -+ */ -+ int (*retry) (struct ip_set *set); -+ -+ /* set destruction - free type specific items -+ * There is no return value. -+ * Can be called only when child sets are destroyed. -+ */ -+ void (*destroy) (struct ip_set *set); -+ -+ /* set flushing - reset all bits in the set, or something similar. -+ * There is no return value. -+ */ -+ void (*flush) (struct ip_set *set); -+ -+ /* Listing: size needed for header -+ */ -+ u_int32_t header_size; -+ -+ /* Listing: Get the header -+ * -+ * Fill in the information in "data". -+ * This function is always run after list_header_size() under a -+ * writelock on the set. Therefor is the length of "data" always -+ * correct. -+ */ -+ void (*list_header) (const struct ip_set *set, -+ void *data); -+ -+ /* Listing: Get the size for the set members -+ */ -+ int (*list_members_size) (const struct ip_set *set); -+ -+ /* Listing: Get the set members -+ * -+ * Fill in the information in "data". -+ * This function is always run after list_member_size() under a -+ * writelock on the set. Therefor is the length of "data" always -+ * correct. -+ */ -+ void (*list_members) (const struct ip_set *set, -+ void *data); -+ -+ char typename[IP_SET_MAXNAMELEN]; -+ unsigned char features; -+ int protocol_version; -+ -+ /* Set this to THIS_MODULE if you are a module, otherwise NULL */ -+ struct module *me; -+}; -+ -+extern int ip_set_register_set_type(struct ip_set_type *set_type); -+extern void ip_set_unregister_set_type(struct ip_set_type *set_type); -+ -+/* A generic ipset */ -+struct ip_set { -+ char name[IP_SET_MAXNAMELEN]; /* the name of the set */ -+ rwlock_t lock; /* lock for concurrency control */ -+ ip_set_id_t id; /* set id for swapping */ -+ ip_set_id_t binding; /* default binding for the set */ -+ atomic_t ref; /* in kernel and in hash references */ -+ struct ip_set_type *type; /* the set types */ -+ void *data; /* pooltype specific data */ -+}; -+ -+/* Structure to bind set elements to sets */ -+struct ip_set_hash { -+ struct list_head list; /* list of clashing entries in hash */ -+ ip_set_ip_t ip; /* ip from set */ -+ ip_set_id_t id; /* set id */ -+ ip_set_id_t binding; /* set we bind the element to */ -+}; -+ -+/* register and unregister set references */ -+extern ip_set_id_t ip_set_get_byname(const char name[IP_SET_MAXNAMELEN]); -+extern ip_set_id_t ip_set_get_byindex(ip_set_id_t index); -+extern void ip_set_put_byindex(ip_set_id_t index); -+extern ip_set_id_t ip_set_id(ip_set_id_t index); -+extern ip_set_id_t __ip_set_get_byname(const char name[IP_SET_MAXNAMELEN], -+ struct ip_set **set); -+extern void __ip_set_put_byindex(ip_set_id_t index); -+ -+/* API for iptables set match, and SET target */ -+extern int ip_set_addip_kernel(ip_set_id_t id, -+ const struct sk_buff *skb, -+ const u_int32_t *flags); -+extern int ip_set_delip_kernel(ip_set_id_t id, -+ const struct sk_buff *skb, -+ const u_int32_t *flags); -+extern int ip_set_testip_kernel(ip_set_id_t id, -+ const struct sk_buff *skb, -+ const u_int32_t *flags); -+ -+/* Macros to generate functions */ -+ -+#define STRUCT(pre, type) CONCAT2(pre, type) -+#define CONCAT2(pre, type) struct pre##type -+ -+#define FNAME(pre, mid, post) CONCAT3(pre, mid, post) -+#define CONCAT3(pre, mid, post) pre##mid##post -+ -+#define UADT0(type, adt, args...) \ -+static int \ -+FNAME(type,_u,adt)(struct ip_set *set, const void *data, u_int32_t size,\ -+ ip_set_ip_t *hash_ip) \ -+{ \ -+ const STRUCT(ip_set_req_,type) *req = data; \ -+ \ -+ return FNAME(type,_,adt)(set, hash_ip , ## args); \ -+} -+ -+#define UADT(type, adt, args...) \ -+ UADT0(type, adt, req->ip , ## args) -+ -+#define KADT(type, adt, getfn, args...) \ -+static int \ -+FNAME(type,_k,adt)(struct ip_set *set, \ -+ const struct sk_buff *skb, \ -+ ip_set_ip_t *hash_ip, \ -+ const u_int32_t *flags, \ -+ unsigned char index) \ -+{ \ -+ ip_set_ip_t ip = getfn(skb, flags[index]); \ -+ \ -+ KADT_CONDITION \ -+ return FNAME(type,_,adt)(set, hash_ip, ip , ##args); \ -+} -+ -+#define REGISTER_MODULE(type) \ -+static int __init ip_set_##type##_init(void) \ -+{ \ -+ init_max_page_size(); \ -+ return ip_set_register_set_type(&ip_set_##type); \ -+} \ -+ \ -+static void __exit ip_set_##type##_fini(void) \ -+{ \ -+ /* FIXME: possible race with ip_set_create() */ \ -+ ip_set_unregister_set_type(&ip_set_##type); \ -+} \ -+ \ -+module_init(ip_set_##type##_init); \ -+module_exit(ip_set_##type##_fini); -+ -+/* Common functions */ -+ -+static inline ip_set_ip_t -+ipaddr(const struct sk_buff *skb, u_int32_t flag) -+{ -+ return ntohl(flag & IPSET_SRC ? ip_hdr(skb)->saddr : ip_hdr(skb)->daddr); -+} -+ -+#define jhash_ip(map, i, ip) jhash_1word(ip, *(map->initval + i)) -+ -+#define pack_ip_port(map, ip, port) \ -+ (port + ((ip - ((map)->first_ip)) << 16)) -+ -+#endif /* __KERNEL__ */ -+ -+#endif /*_IP_SET_H*/ ---- /dev/null -+++ b/include/linux/netfilter_ipv4/ip_set_bitmaps.h -@@ -0,0 +1,121 @@ -+#ifndef __IP_SET_BITMAPS_H -+#define __IP_SET_BITMAPS_H -+ -+/* Macros to generate functions */ -+ -+#ifdef __KERNEL__ -+#define BITMAP_CREATE(type) \ -+static int \ -+type##_create(struct ip_set *set, const void *data, u_int32_t size) \ -+{ \ -+ int newbytes; \ -+ const struct ip_set_req_##type##_create *req = data; \ -+ struct ip_set_##type *map; \ -+ \ -+ if (req->from > req->to) { \ -+ DP("bad range"); \ -+ return -ENOEXEC; \ -+ } \ -+ \ -+ map = kmalloc(sizeof(struct ip_set_##type), GFP_KERNEL); \ -+ if (!map) { \ -+ DP("out of memory for %zu bytes", \ -+ sizeof(struct ip_set_##type)); \ -+ return -ENOMEM; \ -+ } \ -+ map->first_ip = req->from; \ -+ map->last_ip = req->to; \ -+ \ -+ newbytes = __##type##_create(req, map); \ -+ if (newbytes < 0) { \ -+ kfree(map); \ -+ return newbytes; \ -+ } \ -+ \ -+ map->size = newbytes; \ -+ map->members = ip_set_malloc(newbytes); \ -+ if (!map->members) { \ -+ DP("out of memory for %i bytes", newbytes); \ -+ kfree(map); \ -+ return -ENOMEM; \ -+ } \ -+ memset(map->members, 0, newbytes); \ -+ \ -+ set->data = map; \ -+ return 0; \ -+} -+ -+#define BITMAP_DESTROY(type) \ -+static void \ -+type##_destroy(struct ip_set *set) \ -+{ \ -+ struct ip_set_##type *map = set->data; \ -+ \ -+ ip_set_free(map->members, map->size); \ -+ kfree(map); \ -+ \ -+ set->data = NULL; \ -+} -+ -+#define BITMAP_FLUSH(type) \ -+static void \ -+type##_flush(struct ip_set *set) \ -+{ \ -+ struct ip_set_##type *map = set->data; \ -+ memset(map->members, 0, map->size); \ -+} -+ -+#define BITMAP_LIST_HEADER(type) \ -+static void \ -+type##_list_header(const struct ip_set *set, void *data) \ -+{ \ -+ const struct ip_set_##type *map = set->data; \ -+ struct ip_set_req_##type##_create *header = data; \ -+ \ -+ header->from = map->first_ip; \ -+ header->to = map->last_ip; \ -+ __##type##_list_header(map, header); \ -+} -+ -+#define BITMAP_LIST_MEMBERS_SIZE(type) \ -+static int \ -+type##_list_members_size(const struct ip_set *set) \ -+{ \ -+ const struct ip_set_##type *map = set->data; \ -+ \ -+ return map->size; \ -+} -+ -+#define BITMAP_LIST_MEMBERS(type) \ -+static void \ -+type##_list_members(const struct ip_set *set, void *data) \ -+{ \ -+ const struct ip_set_##type *map = set->data; \ -+ \ -+ memcpy(data, map->members, map->size); \ -+} -+ -+#define IP_SET_TYPE(type, __features) \ -+struct ip_set_type ip_set_##type = { \ -+ .typename = #type, \ -+ .features = __features, \ -+ .protocol_version = IP_SET_PROTOCOL_VERSION, \ -+ .create = &type##_create, \ -+ .destroy = &type##_destroy, \ -+ .flush = &type##_flush, \ -+ .reqsize = sizeof(struct ip_set_req_##type), \ -+ .addip = &type##_uadd, \ -+ .addip_kernel = &type##_kadd, \ -+ .delip = &type##_udel, \ -+ .delip_kernel = &type##_kdel, \ -+ .testip = &type##_utest, \ -+ .testip_kernel = &type##_ktest, \ -+ .header_size = sizeof(struct ip_set_req_##type##_create),\ -+ .list_header = &type##_list_header, \ -+ .list_members_size = &type##_list_members_size, \ -+ .list_members = &type##_list_members, \ -+ .me = THIS_MODULE, \ -+}; -+#endif /* __KERNEL */ -+ -+#endif /* __IP_SET_BITMAPS_H */ ---- /dev/null -+++ b/include/linux/netfilter_ipv4/ip_set_compat.h -@@ -0,0 +1,71 @@ -+#ifndef _IP_SET_COMPAT_H -+#define _IP_SET_COMPAT_H -+ -+#ifdef __KERNEL__ -+#include -+ -+/* Arrgh */ -+#ifdef MODULE -+#define __MOD_INC(foo) __MOD_INC_USE_COUNT(foo) -+#define __MOD_DEC(foo) __MOD_DEC_USE_COUNT(foo) -+#else -+#define __MOD_INC(foo) 1 -+#define __MOD_DEC(foo) -+#endif -+ -+/* Backward compatibility */ -+#ifndef __nocast -+#define __nocast -+#endif -+#ifndef __bitwise__ -+#define __bitwise__ -+#endif -+ -+/* Compatibility glue code */ -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) -+#include -+#define DEFINE_RWLOCK(x) rwlock_t x = RW_LOCK_UNLOCKED -+#define try_module_get(x) __MOD_INC(x) -+#define module_put(x) __MOD_DEC(x) -+#define __clear_bit(nr, addr) clear_bit(nr, addr) -+#define __set_bit(nr, addr) set_bit(nr, addr) -+#define __test_and_set_bit(nr, addr) test_and_set_bit(nr, addr) -+#define __test_and_clear_bit(nr, addr) test_and_clear_bit(nr, addr) -+ -+typedef unsigned __bitwise__ gfp_t; -+ -+static inline void *kzalloc(size_t size, gfp_t flags) -+{ -+ void *data = kmalloc(size, flags); -+ -+ if (data) -+ memset(data, 0, size); -+ -+ return data; -+} -+#endif -+ -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) -+#define __KMEM_CACHE_T__ kmem_cache_t -+#else -+#define __KMEM_CACHE_T__ struct kmem_cache -+#endif -+ -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22) -+#define ip_hdr(skb) ((skb)->nh.iph) -+#define skb_mac_header(skb) ((skb)->mac.raw) -+#define eth_hdr(skb) ((struct ethhdr *)skb_mac_header(skb)) -+#endif -+ -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23) -+#include -+#define KMEM_CACHE_CREATE(name, size) \ -+ kmem_cache_create(name, size, 0, 0, NULL, NULL) -+#else -+#define KMEM_CACHE_CREATE(name, size) \ -+ kmem_cache_create(name, size, 0, 0, NULL) -+#endif -+ -+ -+#endif /* __KERNEL__ */ -+#endif /* _IP_SET_COMPAT_H */ ---- /dev/null -+++ b/include/linux/netfilter_ipv4/ip_set_getport.h -@@ -0,0 +1,48 @@ -+#ifndef _IP_SET_GETPORT_H -+#define _IP_SET_GETPORT_H -+ -+#ifdef __KERNEL__ -+ -+#define INVALID_PORT (MAX_RANGE + 1) -+ -+/* We must handle non-linear skbs */ -+static inline ip_set_ip_t -+get_port(const struct sk_buff *skb, u_int32_t flags) -+{ -+ struct iphdr *iph = ip_hdr(skb); -+ u_int16_t offset = ntohs(iph->frag_off) & IP_OFFSET; -+ switch (iph->protocol) { -+ case IPPROTO_TCP: { -+ struct tcphdr tcph; -+ -+ /* See comments at tcp_match in ip_tables.c */ -+ if (offset) -+ return INVALID_PORT; -+ -+ if (skb_copy_bits(skb, ip_hdr(skb)->ihl*4, &tcph, sizeof(tcph)) < 0) -+ /* No choice either */ -+ return INVALID_PORT; -+ -+ return ntohs(flags & IPSET_SRC ? -+ tcph.source : tcph.dest); -+ } -+ case IPPROTO_UDP: { -+ struct udphdr udph; -+ -+ if (offset) -+ return INVALID_PORT; -+ -+ if (skb_copy_bits(skb, ip_hdr(skb)->ihl*4, &udph, sizeof(udph)) < 0) -+ /* No choice either */ -+ return INVALID_PORT; -+ -+ return ntohs(flags & IPSET_SRC ? -+ udph.source : udph.dest); -+ } -+ default: -+ return INVALID_PORT; -+ } -+} -+#endif /* __KERNEL__ */ -+ -+#endif /*_IP_SET_GETPORT_H*/ ---- /dev/null -+++ b/include/linux/netfilter_ipv4/ip_set_hashes.h -@@ -0,0 +1,306 @@ -+#ifndef __IP_SET_HASHES_H -+#define __IP_SET_HASHES_H -+ -+#define initval_t uint32_t -+ -+/* Macros to generate functions */ -+ -+#ifdef __KERNEL__ -+#define HASH_RETRY0(type, dtype, cond) \ -+static int \ -+type##_retry(struct ip_set *set) \ -+{ \ -+ struct ip_set_##type *map = set->data, *tmp; \ -+ dtype *elem; \ -+ void *members; \ -+ u_int32_t i, hashsize = map->hashsize; \ -+ int res; \ -+ \ -+ if (map->resize == 0) \ -+ return -ERANGE; \ -+ \ -+ again: \ -+ res = 0; \ -+ \ -+ /* Calculate new hash size */ \ -+ hashsize += (hashsize * map->resize)/100; \ -+ if (hashsize == map->hashsize) \ -+ hashsize++; \ -+ \ -+ ip_set_printk("rehashing of set %s triggered: " \ -+ "hashsize grows from %lu to %lu", \ -+ set->name, \ -+ (long unsigned)map->hashsize, \ -+ (long unsigned)hashsize); \ -+ \ -+ tmp = kmalloc(sizeof(struct ip_set_##type) \ -+ + map->probes * sizeof(initval_t), GFP_ATOMIC); \ -+ if (!tmp) { \ -+ DP("out of memory for %zu bytes", \ -+ sizeof(struct ip_set_##type) \ -+ + map->probes * sizeof(initval_t)); \ -+ return -ENOMEM; \ -+ } \ -+ tmp->members = harray_malloc(hashsize, sizeof(dtype), GFP_ATOMIC);\ -+ if (!tmp->members) { \ -+ DP("out of memory for %zu bytes", hashsize * sizeof(dtype));\ -+ kfree(tmp); \ -+ return -ENOMEM; \ -+ } \ -+ tmp->hashsize = hashsize; \ -+ tmp->elements = 0; \ -+ tmp->probes = map->probes; \ -+ tmp->resize = map->resize; \ -+ memcpy(tmp->initval, map->initval, map->probes * sizeof(initval_t));\ -+ __##type##_retry(tmp, map); \ -+ \ -+ write_lock_bh(&set->lock); \ -+ map = set->data; /* Play safe */ \ -+ for (i = 0; i < map->hashsize && res == 0; i++) { \ -+ elem = HARRAY_ELEM(map->members, dtype *, i); \ -+ if (cond) \ -+ res = __##type##_add(tmp, elem); \ -+ } \ -+ if (res) { \ -+ /* Failure, try again */ \ -+ write_unlock_bh(&set->lock); \ -+ harray_free(tmp->members); \ -+ kfree(tmp); \ -+ goto again; \ -+ } \ -+ \ -+ /* Success at resizing! */ \ -+ members = map->members; \ -+ \ -+ map->hashsize = tmp->hashsize; \ -+ map->members = tmp->members; \ -+ write_unlock_bh(&set->lock); \ -+ \ -+ harray_free(members); \ -+ kfree(tmp); \ -+ \ -+ return 0; \ -+} -+ -+#define HASH_RETRY(type, dtype) \ -+ HASH_RETRY0(type, dtype, *elem) -+ -+#define HASH_RETRY2(type, dtype) \ -+ HASH_RETRY0(type, dtype, elem->ip || elem->ip1) -+ -+#define HASH_CREATE(type, dtype) \ -+static int \ -+type##_create(struct ip_set *set, const void *data, u_int32_t size) \ -+{ \ -+ const struct ip_set_req_##type##_create *req = data; \ -+ struct ip_set_##type *map; \ -+ uint16_t i; \ -+ \ -+ if (req->hashsize < 1) { \ -+ ip_set_printk("hashsize too small"); \ -+ return -ENOEXEC; \ -+ } \ -+ \ -+ if (req->probes < 1) { \ -+ ip_set_printk("probes too small"); \ -+ return -ENOEXEC; \ -+ } \ -+ \ -+ map = kmalloc(sizeof(struct ip_set_##type) \ -+ + req->probes * sizeof(initval_t), GFP_KERNEL); \ -+ if (!map) { \ -+ DP("out of memory for %zu bytes", \ -+ sizeof(struct ip_set_##type) \ -+ + req->probes * sizeof(initval_t)); \ -+ return -ENOMEM; \ -+ } \ -+ for (i = 0; i < req->probes; i++) \ -+ get_random_bytes(((initval_t *) map->initval)+i, 4); \ -+ map->elements = 0; \ -+ map->hashsize = req->hashsize; \ -+ map->probes = req->probes; \ -+ map->resize = req->resize; \ -+ if (__##type##_create(req, map)) { \ -+ kfree(map); \ -+ return -ENOEXEC; \ -+ } \ -+ map->members = harray_malloc(map->hashsize, sizeof(dtype), GFP_KERNEL);\ -+ if (!map->members) { \ -+ DP("out of memory for %zu bytes", map->hashsize * sizeof(dtype));\ -+ kfree(map); \ -+ return -ENOMEM; \ -+ } \ -+ \ -+ set->data = map; \ -+ return 0; \ -+} -+ -+#define HASH_DESTROY(type) \ -+static void \ -+type##_destroy(struct ip_set *set) \ -+{ \ -+ struct ip_set_##type *map = set->data; \ -+ \ -+ harray_free(map->members); \ -+ kfree(map); \ -+ \ -+ set->data = NULL; \ -+} -+ -+#define HASH_FLUSH(type, dtype) \ -+static void \ -+type##_flush(struct ip_set *set) \ -+{ \ -+ struct ip_set_##type *map = set->data; \ -+ harray_flush(map->members, map->hashsize, sizeof(dtype)); \ -+ map->elements = 0; \ -+} -+ -+#define HASH_FLUSH_CIDR(type, dtype) \ -+static void \ -+type##_flush(struct ip_set *set) \ -+{ \ -+ struct ip_set_##type *map = set->data; \ -+ harray_flush(map->members, map->hashsize, sizeof(dtype)); \ -+ memset(map->cidr, 0, sizeof(map->cidr)); \ -+ memset(map->nets, 0, sizeof(map->nets)); \ -+ map->elements = 0; \ -+} -+ -+#define HASH_LIST_HEADER(type) \ -+static void \ -+type##_list_header(const struct ip_set *set, void *data) \ -+{ \ -+ const struct ip_set_##type *map = set->data; \ -+ struct ip_set_req_##type##_create *header = data; \ -+ \ -+ header->hashsize = map->hashsize; \ -+ header->probes = map->probes; \ -+ header->resize = map->resize; \ -+ __##type##_list_header(map, header); \ -+} -+ -+#define HASH_LIST_MEMBERS_SIZE(type, dtype) \ -+static int \ -+type##_list_members_size(const struct ip_set *set) \ -+{ \ -+ const struct ip_set_##type *map = set->data; \ -+ \ -+ return (map->hashsize * sizeof(dtype)); \ -+} -+ -+#define HASH_LIST_MEMBERS(type, dtype) \ -+static void \ -+type##_list_members(const struct ip_set *set, void *data) \ -+{ \ -+ const struct ip_set_##type *map = set->data; \ -+ dtype *elem; \ -+ uint32_t i; \ -+ \ -+ for (i = 0; i < map->hashsize; i++) { \ -+ elem = HARRAY_ELEM(map->members, dtype *, i); \ -+ ((dtype *)data)[i] = *elem; \ -+ } \ -+} -+ -+#define HASH_LIST_MEMBERS_MEMCPY(type, dtype) \ -+static void \ -+type##_list_members(const struct ip_set *set, void *data) \ -+{ \ -+ const struct ip_set_##type *map = set->data; \ -+ dtype *elem; \ -+ uint32_t i; \ -+ \ -+ for (i = 0; i < map->hashsize; i++) { \ -+ elem = HARRAY_ELEM(map->members, dtype *, i); \ -+ memcpy((((dtype *)data)+i), elem, sizeof(dtype)); \ -+ } \ -+} -+ -+#define IP_SET_RTYPE(type, __features) \ -+struct ip_set_type ip_set_##type = { \ -+ .typename = #type, \ -+ .features = __features, \ -+ .protocol_version = IP_SET_PROTOCOL_VERSION, \ -+ .create = &type##_create, \ -+ .retry = &type##_retry, \ -+ .destroy = &type##_destroy, \ -+ .flush = &type##_flush, \ -+ .reqsize = sizeof(struct ip_set_req_##type), \ -+ .addip = &type##_uadd, \ -+ .addip_kernel = &type##_kadd, \ -+ .delip = &type##_udel, \ -+ .delip_kernel = &type##_kdel, \ -+ .testip = &type##_utest, \ -+ .testip_kernel = &type##_ktest, \ -+ .header_size = sizeof(struct ip_set_req_##type##_create),\ -+ .list_header = &type##_list_header, \ -+ .list_members_size = &type##_list_members_size, \ -+ .list_members = &type##_list_members, \ -+ .me = THIS_MODULE, \ -+}; -+ -+/* Helper functions */ -+static inline void -+add_cidr_size(uint8_t *cidr, uint8_t size) -+{ -+ uint8_t next; -+ int i; -+ -+ for (i = 0; i < 30 && cidr[i]; i++) { -+ if (cidr[i] < size) { -+ next = cidr[i]; -+ cidr[i] = size; -+ size = next; -+ } -+ } -+ if (i < 30) -+ cidr[i] = size; -+} -+ -+static inline void -+del_cidr_size(uint8_t *cidr, uint8_t size) -+{ -+ int i; -+ -+ for (i = 0; i < 29 && cidr[i]; i++) { -+ if (cidr[i] == size) -+ cidr[i] = size = cidr[i+1]; -+ } -+ cidr[29] = 0; -+} -+#else -+#include -+#endif /* __KERNEL */ -+ -+#ifndef UINT16_MAX -+#define UINT16_MAX 65535 -+#endif -+ -+static unsigned char shifts[] = {255, 253, 249, 241, 225, 193, 129, 1}; -+ -+static inline ip_set_ip_t -+pack_ip_cidr(ip_set_ip_t ip, unsigned char cidr) -+{ -+ ip_set_ip_t addr, *paddr = &addr; -+ unsigned char n, t, *a; -+ -+ addr = htonl(ip & (0xFFFFFFFF << (32 - (cidr)))); -+#ifdef __KERNEL__ -+ DP("ip:%u.%u.%u.%u/%u", NIPQUAD(addr), cidr); -+#endif -+ n = cidr / 8; -+ t = cidr % 8; -+ a = &((unsigned char *)paddr)[n]; -+ *a = *a /(1 << (8 - t)) + shifts[t]; -+#ifdef __KERNEL__ -+ DP("n: %u, t: %u, a: %u", n, t, *a); -+ DP("ip:%u.%u.%u.%u/%u, %u.%u.%u.%u", -+ HIPQUAD(ip), cidr, NIPQUAD(addr)); -+#endif -+ -+ return ntohl(addr); -+} -+ -+ -+#endif /* __IP_SET_HASHES_H */ ---- /dev/null -+++ b/include/linux/netfilter_ipv4/ip_set_iphash.h -@@ -0,0 +1,30 @@ -+#ifndef __IP_SET_IPHASH_H -+#define __IP_SET_IPHASH_H -+ -+#include -+#include -+ -+#define SETTYPE_NAME "iphash" -+ -+struct ip_set_iphash { -+ ip_set_ip_t *members; /* the iphash proper */ -+ uint32_t elements; /* number of elements */ -+ uint32_t hashsize; /* hash size */ -+ uint16_t probes; /* max number of probes */ -+ uint16_t resize; /* resize factor in percent */ -+ ip_set_ip_t netmask; /* netmask */ -+ initval_t initval[0]; /* initvals for jhash_1word */ -+}; -+ -+struct ip_set_req_iphash_create { -+ uint32_t hashsize; -+ uint16_t probes; -+ uint16_t resize; -+ ip_set_ip_t netmask; -+}; -+ -+struct ip_set_req_iphash { -+ ip_set_ip_t ip; -+}; -+ -+#endif /* __IP_SET_IPHASH_H */ ---- /dev/null -+++ b/include/linux/netfilter_ipv4/ip_set_ipmap.h -@@ -0,0 +1,57 @@ -+#ifndef __IP_SET_IPMAP_H -+#define __IP_SET_IPMAP_H -+ -+#include -+#include -+ -+#define SETTYPE_NAME "ipmap" -+ -+struct ip_set_ipmap { -+ void *members; /* the ipmap proper */ -+ ip_set_ip_t first_ip; /* host byte order, included in range */ -+ ip_set_ip_t last_ip; /* host byte order, included in range */ -+ ip_set_ip_t netmask; /* subnet netmask */ -+ ip_set_ip_t sizeid; /* size of set in IPs */ -+ ip_set_ip_t hosts; /* number of hosts in a subnet */ -+ u_int32_t size; /* size of the ipmap proper */ -+}; -+ -+struct ip_set_req_ipmap_create { -+ ip_set_ip_t from; -+ ip_set_ip_t to; -+ ip_set_ip_t netmask; -+}; -+ -+struct ip_set_req_ipmap { -+ ip_set_ip_t ip; -+}; -+ -+static inline unsigned int -+mask_to_bits(ip_set_ip_t mask) -+{ -+ unsigned int bits = 32; -+ ip_set_ip_t maskaddr; -+ -+ if (mask == 0xFFFFFFFF) -+ return bits; -+ -+ maskaddr = 0xFFFFFFFE; -+ while (--bits > 0 && maskaddr != mask) -+ maskaddr <<= 1; -+ -+ return bits; -+} -+ -+static inline ip_set_ip_t -+range_to_mask(ip_set_ip_t from, ip_set_ip_t to, unsigned int *bits) -+{ -+ ip_set_ip_t mask = 0xFFFFFFFE; -+ -+ *bits = 32; -+ while (--(*bits) > 0 && mask && (to & mask) != from) -+ mask <<= 1; -+ -+ return mask; -+} -+ -+#endif /* __IP_SET_IPMAP_H */ ---- /dev/null -+++ b/include/linux/netfilter_ipv4/ip_set_ipporthash.h -@@ -0,0 +1,33 @@ -+#ifndef __IP_SET_IPPORTHASH_H -+#define __IP_SET_IPPORTHASH_H -+ -+#include -+#include -+ -+#define SETTYPE_NAME "ipporthash" -+ -+struct ip_set_ipporthash { -+ ip_set_ip_t *members; /* the ipporthash proper */ -+ uint32_t elements; /* number of elements */ -+ uint32_t hashsize; /* hash size */ -+ uint16_t probes; /* max number of probes */ -+ uint16_t resize; /* resize factor in percent */ -+ ip_set_ip_t first_ip; /* host byte order, included in range */ -+ ip_set_ip_t last_ip; /* host byte order, included in range */ -+ initval_t initval[0]; /* initvals for jhash_1word */ -+}; -+ -+struct ip_set_req_ipporthash_create { -+ uint32_t hashsize; -+ uint16_t probes; -+ uint16_t resize; -+ ip_set_ip_t from; -+ ip_set_ip_t to; -+}; -+ -+struct ip_set_req_ipporthash { -+ ip_set_ip_t ip; -+ ip_set_ip_t port; -+}; -+ -+#endif /* __IP_SET_IPPORTHASH_H */ ---- /dev/null -+++ b/include/linux/netfilter_ipv4/ip_set_ipportiphash.h -@@ -0,0 +1,39 @@ -+#ifndef __IP_SET_IPPORTIPHASH_H -+#define __IP_SET_IPPORTIPHASH_H -+ -+#include -+#include -+ -+#define SETTYPE_NAME "ipportiphash" -+ -+struct ipportip { -+ ip_set_ip_t ip; -+ ip_set_ip_t ip1; -+}; -+ -+struct ip_set_ipportiphash { -+ struct ipportip *members; /* the ipportip proper */ -+ uint32_t elements; /* number of elements */ -+ uint32_t hashsize; /* hash size */ -+ uint16_t probes; /* max number of probes */ -+ uint16_t resize; /* resize factor in percent */ -+ ip_set_ip_t first_ip; /* host byte order, included in range */ -+ ip_set_ip_t last_ip; /* host byte order, included in range */ -+ initval_t initval[0]; /* initvals for jhash_1word */ -+}; -+ -+struct ip_set_req_ipportiphash_create { -+ uint32_t hashsize; -+ uint16_t probes; -+ uint16_t resize; -+ ip_set_ip_t from; -+ ip_set_ip_t to; -+}; -+ -+struct ip_set_req_ipportiphash { -+ ip_set_ip_t ip; -+ ip_set_ip_t port; -+ ip_set_ip_t ip1; -+}; -+ -+#endif /* __IP_SET_IPPORTIPHASH_H */ ---- /dev/null -+++ b/include/linux/netfilter_ipv4/ip_set_ipportnethash.h -@@ -0,0 +1,42 @@ -+#ifndef __IP_SET_IPPORTNETHASH_H -+#define __IP_SET_IPPORTNETHASH_H -+ -+#include -+#include -+ -+#define SETTYPE_NAME "ipportnethash" -+ -+struct ipportip { -+ ip_set_ip_t ip; -+ ip_set_ip_t ip1; -+}; -+ -+struct ip_set_ipportnethash { -+ struct ipportip *members; /* the ipportip proper */ -+ uint32_t elements; /* number of elements */ -+ uint32_t hashsize; /* hash size */ -+ uint16_t probes; /* max number of probes */ -+ uint16_t resize; /* resize factor in percent */ -+ ip_set_ip_t first_ip; /* host byte order, included in range */ -+ ip_set_ip_t last_ip; /* host byte order, included in range */ -+ uint8_t cidr[30]; /* CIDR sizes */ -+ uint16_t nets[30]; /* nr of nets by CIDR sizes */ -+ initval_t initval[0]; /* initvals for jhash_1word */ -+}; -+ -+struct ip_set_req_ipportnethash_create { -+ uint32_t hashsize; -+ uint16_t probes; -+ uint16_t resize; -+ ip_set_ip_t from; -+ ip_set_ip_t to; -+}; -+ -+struct ip_set_req_ipportnethash { -+ ip_set_ip_t ip; -+ ip_set_ip_t port; -+ ip_set_ip_t ip1; -+ uint8_t cidr; -+}; -+ -+#endif /* __IP_SET_IPPORTNETHASH_H */ ---- /dev/null -+++ b/include/linux/netfilter_ipv4/ip_set_iptree.h -@@ -0,0 +1,39 @@ -+#ifndef __IP_SET_IPTREE_H -+#define __IP_SET_IPTREE_H -+ -+#include -+ -+#define SETTYPE_NAME "iptree" -+ -+struct ip_set_iptreed { -+ unsigned long expires[256]; /* x.x.x.ADDR */ -+}; -+ -+struct ip_set_iptreec { -+ struct ip_set_iptreed *tree[256]; /* x.x.ADDR.* */ -+}; -+ -+struct ip_set_iptreeb { -+ struct ip_set_iptreec *tree[256]; /* x.ADDR.*.* */ -+}; -+ -+struct ip_set_iptree { -+ unsigned int timeout; -+ unsigned int gc_interval; -+#ifdef __KERNEL__ -+ uint32_t elements; /* number of elements */ -+ struct timer_list gc; -+ struct ip_set_iptreeb *tree[256]; /* ADDR.*.*.* */ -+#endif -+}; -+ -+struct ip_set_req_iptree_create { -+ unsigned int timeout; -+}; -+ -+struct ip_set_req_iptree { -+ ip_set_ip_t ip; -+ unsigned int timeout; -+}; -+ -+#endif /* __IP_SET_IPTREE_H */ ---- /dev/null -+++ b/include/linux/netfilter_ipv4/ip_set_iptreemap.h -@@ -0,0 +1,40 @@ -+#ifndef __IP_SET_IPTREEMAP_H -+#define __IP_SET_IPTREEMAP_H -+ -+#include -+ -+#define SETTYPE_NAME "iptreemap" -+ -+#ifdef __KERNEL__ -+struct ip_set_iptreemap_d { -+ unsigned char bitmap[32]; /* x.x.x.y */ -+}; -+ -+struct ip_set_iptreemap_c { -+ struct ip_set_iptreemap_d *tree[256]; /* x.x.y.x */ -+}; -+ -+struct ip_set_iptreemap_b { -+ struct ip_set_iptreemap_c *tree[256]; /* x.y.x.x */ -+ unsigned char dirty[32]; -+}; -+#endif -+ -+struct ip_set_iptreemap { -+ unsigned int gc_interval; -+#ifdef __KERNEL__ -+ struct timer_list gc; -+ struct ip_set_iptreemap_b *tree[256]; /* y.x.x.x */ -+#endif -+}; -+ -+struct ip_set_req_iptreemap_create { -+ unsigned int gc_interval; -+}; -+ -+struct ip_set_req_iptreemap { -+ ip_set_ip_t ip; -+ ip_set_ip_t end; -+}; -+ -+#endif /* __IP_SET_IPTREEMAP_H */ ---- /dev/null -+++ b/include/linux/netfilter_ipv4/ip_set_jhash.h -@@ -0,0 +1,157 @@ -+#ifndef _LINUX_JHASH_H -+#define _LINUX_JHASH_H -+ -+/* jhash.h: Jenkins hash support. -+ * -+ * Copyright (C) 2006. Bob Jenkins (bob_jenkins@burtleburtle.net) -+ * -+ * http://burtleburtle.net/bob/hash/ -+ * -+ * These are the credits from Bob's sources: -+ * -+ * lookup3.c, by Bob Jenkins, May 2006, Public Domain. -+ * -+ * 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 my fault. Jozsef -+ */ -+ -+#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) \ -+{ \ -+ 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 0xdeadbeef -+ -+/* The most generic version, hashes an arbitrary sequence -+ * of bytes. No alignment or length assumptions are made about -+ * the input key. The result depends on endianness. -+ */ -+static inline u32 jhash(const void *key, u32 length, u32 initval) -+{ -+ u32 a,b,c; -+ const u8 *k = key; -+ -+ /* 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; -+ } -+ -+ /* 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 1 : a += k[0]; -+ __jhash_final(a, b, c); -+ case 0 : -+ break; -+ } -+ -+ return c; -+} -+ -+/* A special optimized version that handles 1 or more of u32s. -+ * The length parameter here is the number of u32s in the key. -+ */ -+static inline u32 jhash2(const u32 *k, u32 length, u32 initval) -+{ -+ u32 a, b, c; -+ -+ /* Set up the internal state */ -+ a = b = c = JHASH_GOLDEN_RATIO + (length<<2) + initval; -+ -+ /* handle most of the key */ -+ while (length > 3) { -+ a += k[0]; -+ b += k[1]; -+ c += k[2]; -+ __jhash_mix(a, b, c); -+ length -= 3; -+ k += 3; -+ } -+ -+ /* 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). -+ */ -+static inline u32 jhash_3words(u32 a, u32 b, u32 c, u32 initval) -+{ -+ a += JHASH_GOLDEN_RATIO + initval; -+ b += JHASH_GOLDEN_RATIO + initval; -+ c += JHASH_GOLDEN_RATIO + initval; -+ -+ __jhash_final(a, b, c); -+ -+ return c; -+} -+ -+static inline u32 jhash_2words(u32 a, u32 b, u32 initval) -+{ -+ return jhash_3words(0, a, b, initval); -+} -+ -+static inline u32 jhash_1word(u32 a, u32 initval) -+{ -+ return jhash_3words(0, 0, a, initval); -+} -+ -+#endif /* _LINUX_JHASH_H */ ---- /dev/null -+++ b/include/linux/netfilter_ipv4/ip_set_macipmap.h -@@ -0,0 +1,39 @@ -+#ifndef __IP_SET_MACIPMAP_H -+#define __IP_SET_MACIPMAP_H -+ -+#include -+#include -+ -+#define SETTYPE_NAME "macipmap" -+ -+/* general flags */ -+#define IPSET_MACIP_MATCHUNSET 1 -+ -+/* per ip flags */ -+#define IPSET_MACIP_ISSET 1 -+ -+struct ip_set_macipmap { -+ void *members; /* the macipmap proper */ -+ ip_set_ip_t first_ip; /* host byte order, included in range */ -+ ip_set_ip_t last_ip; /* host byte order, included in range */ -+ u_int32_t flags; -+ u_int32_t size; /* size of the ipmap proper */ -+}; -+ -+struct ip_set_req_macipmap_create { -+ ip_set_ip_t from; -+ ip_set_ip_t to; -+ u_int32_t flags; -+}; -+ -+struct ip_set_req_macipmap { -+ ip_set_ip_t ip; -+ unsigned char ethernet[ETH_ALEN]; -+}; -+ -+struct ip_set_macip { -+ unsigned short match; -+ unsigned char ethernet[ETH_ALEN]; -+}; -+ -+#endif /* __IP_SET_MACIPMAP_H */ ---- /dev/null -+++ b/include/linux/netfilter_ipv4/ip_set_malloc.h -@@ -0,0 +1,153 @@ -+#ifndef _IP_SET_MALLOC_H -+#define _IP_SET_MALLOC_H -+ -+#ifdef __KERNEL__ -+#include -+ -+static size_t max_malloc_size = 0, max_page_size = 0; -+static size_t default_max_malloc_size = 131072; /* Guaranteed: slab.c */ -+ -+static inline int init_max_page_size(void) -+{ -+/* Compatibility glues to support 2.4.36 */ -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) -+#define __GFP_NOWARN 0 -+ -+ /* Guaranteed: slab.c */ -+ max_malloc_size = max_page_size = default_max_malloc_size; -+#else -+ size_t page_size = 0; -+ -+#define CACHE(x) if (max_page_size == 0 || x < max_page_size) \ -+ page_size = x; -+#include -+#undef CACHE -+ if (page_size) { -+ if (max_malloc_size == 0) -+ max_malloc_size = page_size; -+ -+ max_page_size = page_size; -+ -+ return 1; -+ } -+#endif -+ return 0; -+} -+ -+struct harray { -+ size_t max_elements; -+ void *arrays[0]; -+}; -+ -+static inline void * -+__harray_malloc(size_t hashsize, size_t typesize, gfp_t flags) -+{ -+ struct harray *harray; -+ size_t max_elements, size, i, j; -+ -+ BUG_ON(max_page_size == 0); -+ -+ if (typesize > max_page_size) -+ return NULL; -+ -+ max_elements = max_page_size/typesize; -+ size = hashsize/max_elements; -+ if (hashsize % max_elements) -+ size++; -+ -+ /* Last pointer signals end of arrays */ -+ harray = kmalloc(sizeof(struct harray) + (size + 1) * sizeof(void *), -+ flags); -+ -+ if (!harray) -+ return NULL; -+ -+ for (i = 0; i < size - 1; i++) { -+ harray->arrays[i] = kmalloc(max_elements * typesize, flags); -+ if (!harray->arrays[i]) -+ goto undo; -+ memset(harray->arrays[i], 0, max_elements * typesize); -+ } -+ harray->arrays[i] = kmalloc((hashsize - i * max_elements) * typesize, -+ flags); -+ if (!harray->arrays[i]) -+ goto undo; -+ memset(harray->arrays[i], 0, (hashsize - i * max_elements) * typesize); -+ -+ harray->max_elements = max_elements; -+ harray->arrays[size] = NULL; -+ -+ return (void *)harray; -+ -+ undo: -+ for (j = 0; j < i; j++) { -+ kfree(harray->arrays[j]); -+ } -+ kfree(harray); -+ return NULL; -+} -+ -+static inline void * -+harray_malloc(size_t hashsize, size_t typesize, gfp_t flags) -+{ -+ void *harray; -+ -+ do { -+ harray = __harray_malloc(hashsize, typesize, flags|__GFP_NOWARN); -+ } while (harray == NULL && init_max_page_size()); -+ -+ return harray; -+} -+ -+static inline void harray_free(void *h) -+{ -+ struct harray *harray = (struct harray *) h; -+ size_t i; -+ -+ for (i = 0; harray->arrays[i] != NULL; i++) -+ kfree(harray->arrays[i]); -+ kfree(harray); -+} -+ -+static inline void harray_flush(void *h, size_t hashsize, size_t typesize) -+{ -+ struct harray *harray = (struct harray *) h; -+ size_t i; -+ -+ for (i = 0; harray->arrays[i+1] != NULL; i++) -+ memset(harray->arrays[i], 0, harray->max_elements * typesize); -+ memset(harray->arrays[i], 0, -+ (hashsize - i * harray->max_elements) * typesize); -+} -+ -+#define HARRAY_ELEM(h, type, which) \ -+({ \ -+ struct harray *__h = (struct harray *)(h); \ -+ ((type)((__h)->arrays[(which)/(__h)->max_elements]) \ -+ + (which)%(__h)->max_elements); \ -+}) -+ -+/* General memory allocation and deallocation */ -+static inline void * ip_set_malloc(size_t bytes) -+{ -+ BUG_ON(max_malloc_size == 0); -+ -+ if (bytes > default_max_malloc_size) -+ return vmalloc(bytes); -+ else -+ return kmalloc(bytes, GFP_KERNEL | __GFP_NOWARN); -+} -+ -+static inline void ip_set_free(void * data, size_t bytes) -+{ -+ BUG_ON(max_malloc_size == 0); -+ -+ if (bytes > default_max_malloc_size) -+ vfree(data); -+ else -+ kfree(data); -+} -+ -+#endif /* __KERNEL__ */ -+ -+#endif /*_IP_SET_MALLOC_H*/ ---- /dev/null -+++ b/include/linux/netfilter_ipv4/ip_set_nethash.h -@@ -0,0 +1,31 @@ -+#ifndef __IP_SET_NETHASH_H -+#define __IP_SET_NETHASH_H -+ -+#include -+#include -+ -+#define SETTYPE_NAME "nethash" -+ -+struct ip_set_nethash { -+ ip_set_ip_t *members; /* the nethash proper */ -+ uint32_t elements; /* number of elements */ -+ uint32_t hashsize; /* hash size */ -+ uint16_t probes; /* max number of probes */ -+ uint16_t resize; /* resize factor in percent */ -+ uint8_t cidr[30]; /* CIDR sizes */ -+ uint16_t nets[30]; /* nr of nets by CIDR sizes */ -+ initval_t initval[0]; /* initvals for jhash_1word */ -+}; -+ -+struct ip_set_req_nethash_create { -+ uint32_t hashsize; -+ uint16_t probes; -+ uint16_t resize; -+}; -+ -+struct ip_set_req_nethash { -+ ip_set_ip_t ip; -+ uint8_t cidr; -+}; -+ -+#endif /* __IP_SET_NETHASH_H */ ---- /dev/null -+++ b/include/linux/netfilter_ipv4/ip_set_portmap.h -@@ -0,0 +1,25 @@ -+#ifndef __IP_SET_PORTMAP_H -+#define __IP_SET_PORTMAP_H -+ -+#include -+#include -+ -+#define SETTYPE_NAME "portmap" -+ -+struct ip_set_portmap { -+ void *members; /* the portmap proper */ -+ ip_set_ip_t first_ip; /* host byte order, included in range */ -+ ip_set_ip_t last_ip; /* host byte order, included in range */ -+ u_int32_t size; /* size of the ipmap proper */ -+}; -+ -+struct ip_set_req_portmap_create { -+ ip_set_ip_t from; -+ ip_set_ip_t to; -+}; -+ -+struct ip_set_req_portmap { -+ ip_set_ip_t ip; -+}; -+ -+#endif /* __IP_SET_PORTMAP_H */ ---- /dev/null -+++ b/include/linux/netfilter_ipv4/ip_set_setlist.h -@@ -0,0 +1,26 @@ -+#ifndef __IP_SET_SETLIST_H -+#define __IP_SET_SETLIST_H -+ -+#include -+ -+#define SETTYPE_NAME "setlist" -+ -+#define IP_SET_SETLIST_ADD_AFTER 0 -+#define IP_SET_SETLIST_ADD_BEFORE 1 -+ -+struct ip_set_setlist { -+ uint8_t size; -+ ip_set_id_t index[0]; -+}; -+ -+struct ip_set_req_setlist_create { -+ uint8_t size; -+}; -+ -+struct ip_set_req_setlist { -+ char name[IP_SET_MAXNAMELEN]; -+ char ref[IP_SET_MAXNAMELEN]; -+ uint8_t before; -+}; -+ -+#endif /* __IP_SET_SETLIST_H */ ---- /dev/null -+++ b/include/linux/netfilter_ipv4/ipt_set.h -@@ -0,0 +1,21 @@ -+#ifndef _IPT_SET_H -+#define _IPT_SET_H -+ -+#include -+ -+struct ipt_set_info { -+ ip_set_id_t index; -+ u_int32_t flags[IP_SET_MAX_BINDINGS + 1]; -+}; -+ -+/* match info */ -+struct ipt_set_info_match { -+ struct ipt_set_info match_set; -+}; -+ -+struct ipt_set_info_target { -+ struct ipt_set_info add_set; -+ struct ipt_set_info del_set; -+}; -+ -+#endif /*_IPT_SET_H*/ ---- /dev/null -+++ b/net/ipv4/netfilter/ip_set.c -@@ -0,0 +1,2076 @@ -+/* Copyright (C) 2000-2002 Joakim Axelsson -+ * Patrick Schaaf -+ * Copyright (C) 2003-2004 Jozsef Kadlecsik -+ * -+ * 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. -+ */ -+ -+/* Kernel module for IP set management */ -+ -+#include -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19) -+#include -+#endif -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27) -+#include -+#else -+#include -+#endif -+#include -+ -+#define ASSERT_READ_LOCK(x) -+#define ASSERT_WRITE_LOCK(x) -+#include -+#include -+ -+static struct list_head set_type_list; /* all registered sets */ -+static struct ip_set **ip_set_list; /* all individual sets */ -+static DEFINE_RWLOCK(ip_set_lock); /* protects the lists and the hash */ -+static DECLARE_MUTEX(ip_set_app_mutex); /* serializes user access */ -+static ip_set_id_t ip_set_max = CONFIG_IP_NF_SET_MAX; -+static ip_set_id_t ip_set_bindings_hash_size = CONFIG_IP_NF_SET_HASHSIZE; -+static struct list_head *ip_set_hash; /* hash of bindings */ -+static unsigned int ip_set_hash_random; /* random seed */ -+ -+#define SETNAME_EQ(a,b) (strncmp(a,b,IP_SET_MAXNAMELEN) == 0) -+ -+/* -+ * Sets are identified either by the index in ip_set_list or by id. -+ * The id never changes and is used to find a key in the hash. -+ * The index may change by swapping and used at all other places -+ * (set/SET netfilter modules, binding value, etc.) -+ * -+ * Userspace requests are serialized by ip_set_mutex and sets can -+ * be deleted only from userspace. Therefore ip_set_list locking -+ * must obey the following rules: -+ * -+ * - kernel requests: read and write locking mandatory -+ * - user requests: read locking optional, write locking mandatory -+ */ -+ -+static inline void -+__ip_set_get(ip_set_id_t index) -+{ -+ atomic_inc(&ip_set_list[index]->ref); -+} -+ -+static inline void -+__ip_set_put(ip_set_id_t index) -+{ -+ atomic_dec(&ip_set_list[index]->ref); -+} -+ -+/* -+ * Binding routines -+ */ -+ -+static inline struct ip_set_hash * -+__ip_set_find(u_int32_t key, ip_set_id_t id, ip_set_ip_t ip) -+{ -+ struct ip_set_hash *set_hash; -+ -+ list_for_each_entry(set_hash, &ip_set_hash[key], list) -+ if (set_hash->id == id && set_hash->ip == ip) -+ return set_hash; -+ -+ return NULL; -+} -+ -+static ip_set_id_t -+ip_set_find_in_hash(ip_set_id_t id, ip_set_ip_t ip) -+{ -+ u_int32_t key = jhash_2words(id, ip, ip_set_hash_random) -+ % ip_set_bindings_hash_size; -+ struct ip_set_hash *set_hash; -+ -+ ASSERT_READ_LOCK(&ip_set_lock); -+ IP_SET_ASSERT(ip_set_list[id]); -+ DP("set: %s, ip: %u.%u.%u.%u", ip_set_list[id]->name, HIPQUAD(ip)); -+ -+ set_hash = __ip_set_find(key, id, ip); -+ -+ DP("set: %s, ip: %u.%u.%u.%u, binding: %s", ip_set_list[id]->name, -+ HIPQUAD(ip), -+ set_hash != NULL ? ip_set_list[set_hash->binding]->name : ""); -+ -+ return (set_hash != NULL ? set_hash->binding : IP_SET_INVALID_ID); -+} -+ -+static inline void -+__set_hash_del(struct ip_set_hash *set_hash) -+{ -+ ASSERT_WRITE_LOCK(&ip_set_lock); -+ IP_SET_ASSERT(ip_set_list[set_hash->binding]); -+ -+ __ip_set_put(set_hash->binding); -+ list_del(&set_hash->list); -+ kfree(set_hash); -+} -+ -+static int -+ip_set_hash_del(ip_set_id_t id, ip_set_ip_t ip) -+{ -+ u_int32_t key = jhash_2words(id, ip, ip_set_hash_random) -+ % ip_set_bindings_hash_size; -+ struct ip_set_hash *set_hash; -+ -+ IP_SET_ASSERT(ip_set_list[id]); -+ DP("set: %s, ip: %u.%u.%u.%u", ip_set_list[id]->name, HIPQUAD(ip)); -+ write_lock_bh(&ip_set_lock); -+ set_hash = __ip_set_find(key, id, ip); -+ DP("set: %s, ip: %u.%u.%u.%u, binding: %s", ip_set_list[id]->name, -+ HIPQUAD(ip), -+ set_hash != NULL ? ip_set_list[set_hash->binding]->name : ""); -+ -+ if (set_hash != NULL) -+ __set_hash_del(set_hash); -+ write_unlock_bh(&ip_set_lock); -+ return 0; -+} -+ -+static int -+ip_set_hash_add(ip_set_id_t id, ip_set_ip_t ip, ip_set_id_t binding) -+{ -+ u_int32_t key = jhash_2words(id, ip, ip_set_hash_random) -+ % ip_set_bindings_hash_size; -+ struct ip_set_hash *set_hash; -+ int ret = 0; -+ -+ IP_SET_ASSERT(ip_set_list[id]); -+ IP_SET_ASSERT(ip_set_list[binding]); -+ DP("set: %s, ip: %u.%u.%u.%u, binding: %s", ip_set_list[id]->name, -+ HIPQUAD(ip), ip_set_list[binding]->name); -+ write_lock_bh(&ip_set_lock); -+ set_hash = __ip_set_find(key, id, ip); -+ if (!set_hash) { -+ set_hash = kmalloc(sizeof(struct ip_set_hash), GFP_ATOMIC); -+ if (!set_hash) { -+ ret = -ENOMEM; -+ goto unlock; -+ } -+ INIT_LIST_HEAD(&set_hash->list); -+ set_hash->id = id; -+ set_hash->ip = ip; -+ list_add(&set_hash->list, &ip_set_hash[key]); -+ } else { -+ IP_SET_ASSERT(ip_set_list[set_hash->binding]); -+ DP("overwrite binding: %s", -+ ip_set_list[set_hash->binding]->name); -+ __ip_set_put(set_hash->binding); -+ } -+ set_hash->binding = binding; -+ __ip_set_get(set_hash->binding); -+ DP("stored: key %u, id %u (%s), ip %u.%u.%u.%u, binding %u (%s)", -+ key, id, ip_set_list[id]->name, -+ HIPQUAD(ip), binding, ip_set_list[binding]->name); -+ unlock: -+ write_unlock_bh(&ip_set_lock); -+ return ret; -+} -+ -+#define FOREACH_HASH_DO(fn, args...) \ -+({ \ -+ ip_set_id_t __key; \ -+ struct ip_set_hash *__set_hash; \ -+ \ -+ for (__key = 0; __key < ip_set_bindings_hash_size; __key++) { \ -+ list_for_each_entry(__set_hash, &ip_set_hash[__key], list) \ -+ fn(__set_hash , ## args); \ -+ } \ -+}) -+ -+#define FOREACH_HASH_RW_DO(fn, args...) \ -+({ \ -+ ip_set_id_t __key; \ -+ struct ip_set_hash *__set_hash, *__n; \ -+ \ -+ ASSERT_WRITE_LOCK(&ip_set_lock); \ -+ for (__key = 0; __key < ip_set_bindings_hash_size; __key++) { \ -+ list_for_each_entry_safe(__set_hash, __n, &ip_set_hash[__key], list)\ -+ fn(__set_hash , ## args); \ -+ } \ -+}) -+ -+/* Add, del and test set entries from kernel */ -+ -+#define follow_bindings(index, set, ip) \ -+((index = ip_set_find_in_hash((set)->id, ip)) != IP_SET_INVALID_ID \ -+ || (index = (set)->binding) != IP_SET_INVALID_ID) -+ -+int -+ip_set_testip_kernel(ip_set_id_t index, -+ const struct sk_buff *skb, -+ const u_int32_t *flags) -+{ -+ struct ip_set *set; -+ ip_set_ip_t ip; -+ int res; -+ unsigned char i = 0; -+ -+ IP_SET_ASSERT(flags[i]); -+ read_lock_bh(&ip_set_lock); -+ do { -+ set = ip_set_list[index]; -+ IP_SET_ASSERT(set); -+ DP("set %s, index %u", set->name, index); -+ read_lock_bh(&set->lock); -+ res = set->type->testip_kernel(set, skb, &ip, flags, i++); -+ read_unlock_bh(&set->lock); -+ i += !!(set->type->features & IPSET_DATA_DOUBLE); -+ } while (res > 0 -+ && flags[i] -+ && follow_bindings(index, set, ip)); -+ read_unlock_bh(&ip_set_lock); -+ -+ return (res < 0 ? 0 : res); -+} -+ -+int -+ip_set_addip_kernel(ip_set_id_t index, -+ const struct sk_buff *skb, -+ const u_int32_t *flags) -+{ -+ struct ip_set *set; -+ ip_set_ip_t ip; -+ int res; -+ unsigned char i = 0; -+ -+ IP_SET_ASSERT(flags[i]); -+ retry: -+ read_lock_bh(&ip_set_lock); -+ do { -+ set = ip_set_list[index]; -+ IP_SET_ASSERT(set); -+ DP("set %s, index %u", set->name, index); -+ write_lock_bh(&set->lock); -+ res = set->type->addip_kernel(set, skb, &ip, flags, i++); -+ write_unlock_bh(&set->lock); -+ i += !!(set->type->features & IPSET_DATA_DOUBLE); -+ } while ((res == 0 || res == -EEXIST) -+ && flags[i] -+ && follow_bindings(index, set, ip)); -+ read_unlock_bh(&ip_set_lock); -+ -+ if (res == -EAGAIN -+ && set->type->retry -+ && (res = set->type->retry(set)) == 0) -+ goto retry; -+ -+ return res; -+} -+ -+int -+ip_set_delip_kernel(ip_set_id_t index, -+ const struct sk_buff *skb, -+ const u_int32_t *flags) -+{ -+ struct ip_set *set; -+ ip_set_ip_t ip; -+ int res; -+ unsigned char i = 0; -+ -+ IP_SET_ASSERT(flags[i]); -+ read_lock_bh(&ip_set_lock); -+ do { -+ set = ip_set_list[index]; -+ IP_SET_ASSERT(set); -+ DP("set %s, index %u", set->name, index); -+ write_lock_bh(&set->lock); -+ res = set->type->delip_kernel(set, skb, &ip, flags, i++); -+ write_unlock_bh(&set->lock); -+ i += !!(set->type->features & IPSET_DATA_DOUBLE); -+ } while ((res == 0 || res == -EEXIST) -+ && flags[i] -+ && follow_bindings(index, set, ip)); -+ read_unlock_bh(&ip_set_lock); -+ -+ return res; -+} -+ -+/* Register and deregister settype */ -+ -+static inline struct ip_set_type * -+find_set_type(const char *name) -+{ -+ struct ip_set_type *set_type; -+ -+ list_for_each_entry(set_type, &set_type_list, list) -+ if (!strncmp(set_type->typename, name, IP_SET_MAXNAMELEN - 1)) -+ return set_type; -+ return NULL; -+} -+ -+int -+ip_set_register_set_type(struct ip_set_type *set_type) -+{ -+ int ret = 0; -+ -+ if (set_type->protocol_version != IP_SET_PROTOCOL_VERSION) { -+ ip_set_printk("'%s' uses wrong protocol version %u (want %u)", -+ set_type->typename, -+ set_type->protocol_version, -+ IP_SET_PROTOCOL_VERSION); -+ return -EINVAL; -+ } -+ -+ write_lock_bh(&ip_set_lock); -+ if (find_set_type(set_type->typename)) { -+ /* Duplicate! */ -+ ip_set_printk("'%s' already registered!", -+ set_type->typename); -+ ret = -EINVAL; -+ goto unlock; -+ } -+ if (!try_module_get(THIS_MODULE)) { -+ ret = -EFAULT; -+ goto unlock; -+ } -+ list_add(&set_type->list, &set_type_list); -+ DP("'%s' registered.", set_type->typename); -+ unlock: -+ write_unlock_bh(&ip_set_lock); -+ return ret; -+} -+ -+void -+ip_set_unregister_set_type(struct ip_set_type *set_type) -+{ -+ write_lock_bh(&ip_set_lock); -+ if (!find_set_type(set_type->typename)) { -+ ip_set_printk("'%s' not registered?", -+ set_type->typename); -+ goto unlock; -+ } -+ list_del(&set_type->list); -+ module_put(THIS_MODULE); -+ DP("'%s' unregistered.", set_type->typename); -+ unlock: -+ write_unlock_bh(&ip_set_lock); -+ -+} -+ -+ip_set_id_t -+__ip_set_get_byname(const char *name, struct ip_set **set) -+{ -+ ip_set_id_t i, index = IP_SET_INVALID_ID; -+ -+ for (i = 0; i < ip_set_max; i++) { -+ if (ip_set_list[i] != NULL -+ && SETNAME_EQ(ip_set_list[i]->name, name)) { -+ __ip_set_get(i); -+ index = i; -+ *set = ip_set_list[i]; -+ break; -+ } -+ } -+ return index; -+} -+ -+void __ip_set_put_byindex(ip_set_id_t index) -+{ -+ if (ip_set_list[index]) -+ __ip_set_put(index); -+} -+ -+/* -+ * Userspace routines -+ */ -+ -+/* -+ * Find set by name, reference it once. The reference makes sure the -+ * thing pointed to, does not go away under our feet. Drop the reference -+ * later, using ip_set_put(). -+ */ -+ip_set_id_t -+ip_set_get_byname(const char *name) -+{ -+ ip_set_id_t i, index = IP_SET_INVALID_ID; -+ -+ down(&ip_set_app_mutex); -+ for (i = 0; i < ip_set_max; i++) { -+ if (ip_set_list[i] != NULL -+ && SETNAME_EQ(ip_set_list[i]->name, name)) { -+ __ip_set_get(i); -+ index = i; -+ break; -+ } -+ } -+ up(&ip_set_app_mutex); -+ return index; -+} -+ -+/* -+ * Find set by index, reference it once. The reference makes sure the -+ * thing pointed to, does not go away under our feet. Drop the reference -+ * later, using ip_set_put(). -+ */ -+ip_set_id_t -+ip_set_get_byindex(ip_set_id_t index) -+{ -+ down(&ip_set_app_mutex); -+ -+ if (index >= ip_set_max) -+ return IP_SET_INVALID_ID; -+ -+ if (ip_set_list[index]) -+ __ip_set_get(index); -+ else -+ index = IP_SET_INVALID_ID; -+ -+ up(&ip_set_app_mutex); -+ return index; -+} -+ -+/* -+ * Find the set id belonging to the index. -+ * We are protected by the mutex, so we do not need to use -+ * ip_set_lock. There is no need to reference the sets either. -+ */ -+ip_set_id_t -+ip_set_id(ip_set_id_t index) -+{ -+ if (index >= ip_set_max || !ip_set_list[index]) -+ return IP_SET_INVALID_ID; -+ -+ return ip_set_list[index]->id; -+} -+ -+/* -+ * If the given set pointer points to a valid set, decrement -+ * reference count by 1. The caller shall not assume the index -+ * to be valid, after calling this function. -+ */ -+void ip_set_put_byindex(ip_set_id_t index) -+{ -+ down(&ip_set_app_mutex); -+ if (ip_set_list[index]) -+ __ip_set_put(index); -+ up(&ip_set_app_mutex); -+} -+ -+/* Find a set by name or index */ -+static ip_set_id_t -+ip_set_find_byname(const char *name) -+{ -+ ip_set_id_t i, index = IP_SET_INVALID_ID; -+ -+ for (i = 0; i < ip_set_max; i++) { -+ if (ip_set_list[i] != NULL -+ && SETNAME_EQ(ip_set_list[i]->name, name)) { -+ index = i; -+ break; -+ } -+ } -+ return index; -+} -+ -+static ip_set_id_t -+ip_set_find_byindex(ip_set_id_t index) -+{ -+ if (index >= ip_set_max || ip_set_list[index] == NULL) -+ index = IP_SET_INVALID_ID; -+ -+ return index; -+} -+ -+/* -+ * Add, del, test, bind and unbind -+ */ -+ -+static inline int -+__ip_set_testip(struct ip_set *set, -+ const void *data, -+ u_int32_t size, -+ ip_set_ip_t *ip) -+{ -+ int res; -+ -+ read_lock_bh(&set->lock); -+ res = set->type->testip(set, data, size, ip); -+ read_unlock_bh(&set->lock); -+ -+ return res; -+} -+ -+static int -+__ip_set_addip(ip_set_id_t index, -+ const void *data, -+ u_int32_t size) -+{ -+ struct ip_set *set = ip_set_list[index]; -+ ip_set_ip_t ip; -+ int res; -+ -+ IP_SET_ASSERT(set); -+ do { -+ write_lock_bh(&set->lock); -+ res = set->type->addip(set, data, size, &ip); -+ write_unlock_bh(&set->lock); -+ } while (res == -EAGAIN -+ && set->type->retry -+ && (res = set->type->retry(set)) == 0); -+ -+ return res; -+} -+ -+static int -+ip_set_addip(ip_set_id_t index, -+ const void *data, -+ u_int32_t size) -+{ -+ struct ip_set *set = ip_set_list[index]; -+ -+ IP_SET_ASSERT(set); -+ -+ if (size - sizeof(struct ip_set_req_adt) != set->type->reqsize) { -+ ip_set_printk("data length wrong (want %lu, have %zu)", -+ (long unsigned)set->type->reqsize, -+ size - sizeof(struct ip_set_req_adt)); -+ return -EINVAL; -+ } -+ return __ip_set_addip(index, -+ data + sizeof(struct ip_set_req_adt), -+ size - sizeof(struct ip_set_req_adt)); -+} -+ -+static int -+ip_set_delip(ip_set_id_t index, -+ const void *data, -+ u_int32_t size) -+{ -+ struct ip_set *set = ip_set_list[index]; -+ ip_set_ip_t ip; -+ int res; -+ -+ IP_SET_ASSERT(set); -+ -+ if (size - sizeof(struct ip_set_req_adt) != set->type->reqsize) { -+ ip_set_printk("data length wrong (want %lu, have %zu)", -+ (long unsigned)set->type->reqsize, -+ size - sizeof(struct ip_set_req_adt)); -+ return -EINVAL; -+ } -+ write_lock_bh(&set->lock); -+ res = set->type->delip(set, -+ data + sizeof(struct ip_set_req_adt), -+ size - sizeof(struct ip_set_req_adt), -+ &ip); -+ write_unlock_bh(&set->lock); -+ -+ return res; -+} -+ -+static int -+ip_set_testip(ip_set_id_t index, -+ const void *data, -+ u_int32_t size) -+{ -+ struct ip_set *set = ip_set_list[index]; -+ ip_set_ip_t ip; -+ int res; -+ -+ IP_SET_ASSERT(set); -+ -+ if (size - sizeof(struct ip_set_req_adt) != set->type->reqsize) { -+ ip_set_printk("data length wrong (want %lu, have %zu)", -+ (long unsigned)set->type->reqsize, -+ size - sizeof(struct ip_set_req_adt)); -+ return -EINVAL; -+ } -+ res = __ip_set_testip(set, -+ data + sizeof(struct ip_set_req_adt), -+ size - sizeof(struct ip_set_req_adt), -+ &ip); -+ -+ return (res > 0 ? -EEXIST : res); -+} -+ -+static int -+ip_set_bindip(ip_set_id_t index, -+ const void *data, -+ u_int32_t size) -+{ -+ struct ip_set *set = ip_set_list[index]; -+ const struct ip_set_req_bind *req_bind; -+ ip_set_id_t binding; -+ ip_set_ip_t ip; -+ int res; -+ -+ IP_SET_ASSERT(set); -+ if (size < sizeof(struct ip_set_req_bind)) -+ return -EINVAL; -+ -+ req_bind = data; -+ -+ if (SETNAME_EQ(req_bind->binding, IPSET_TOKEN_DEFAULT)) { -+ /* Default binding of a set */ -+ const char *binding_name; -+ -+ if (size != sizeof(struct ip_set_req_bind) + IP_SET_MAXNAMELEN) -+ return -EINVAL; -+ -+ binding_name = data + sizeof(struct ip_set_req_bind); -+ -+ binding = ip_set_find_byname(binding_name); -+ if (binding == IP_SET_INVALID_ID) -+ return -ENOENT; -+ -+ write_lock_bh(&ip_set_lock); -+ /* Sets as binding values are referenced */ -+ if (set->binding != IP_SET_INVALID_ID) -+ __ip_set_put(set->binding); -+ set->binding = binding; -+ __ip_set_get(set->binding); -+ write_unlock_bh(&ip_set_lock); -+ -+ return 0; -+ } -+ binding = ip_set_find_byname(req_bind->binding); -+ if (binding == IP_SET_INVALID_ID) -+ return -ENOENT; -+ -+ res = __ip_set_testip(set, -+ data + sizeof(struct ip_set_req_bind), -+ size - sizeof(struct ip_set_req_bind), -+ &ip); -+ DP("set %s, ip: %u.%u.%u.%u, binding %s", -+ set->name, HIPQUAD(ip), ip_set_list[binding]->name); -+ -+ if (res >= 0) -+ res = ip_set_hash_add(set->id, ip, binding); -+ -+ return res; -+} -+ -+#define FOREACH_SET_DO(fn, args...) \ -+({ \ -+ ip_set_id_t __i; \ -+ struct ip_set *__set; \ -+ \ -+ for (__i = 0; __i < ip_set_max; __i++) { \ -+ __set = ip_set_list[__i]; \ -+ if (__set != NULL) \ -+ fn(__set , ##args); \ -+ } \ -+}) -+ -+static inline void -+__set_hash_del_byid(struct ip_set_hash *set_hash, ip_set_id_t id) -+{ -+ if (set_hash->id == id) -+ __set_hash_del(set_hash); -+} -+ -+static inline void -+__unbind_default(struct ip_set *set) -+{ -+ if (set->binding != IP_SET_INVALID_ID) { -+ /* Sets as binding values are referenced */ -+ __ip_set_put(set->binding); -+ set->binding = IP_SET_INVALID_ID; -+ } -+} -+ -+static int -+ip_set_unbindip(ip_set_id_t index, -+ const void *data, -+ u_int32_t size) -+{ -+ struct ip_set *set; -+ const struct ip_set_req_bind *req_bind; -+ ip_set_ip_t ip; -+ int res; -+ -+ DP(""); -+ if (size < sizeof(struct ip_set_req_bind)) -+ return -EINVAL; -+ -+ req_bind = data; -+ -+ DP("%u %s", index, req_bind->binding); -+ if (index == IP_SET_INVALID_ID) { -+ /* unbind :all: */ -+ if (SETNAME_EQ(req_bind->binding, IPSET_TOKEN_DEFAULT)) { -+ /* Default binding of sets */ -+ write_lock_bh(&ip_set_lock); -+ FOREACH_SET_DO(__unbind_default); -+ write_unlock_bh(&ip_set_lock); -+ return 0; -+ } else if (SETNAME_EQ(req_bind->binding, IPSET_TOKEN_ALL)) { -+ /* Flush all bindings of all sets*/ -+ write_lock_bh(&ip_set_lock); -+ FOREACH_HASH_RW_DO(__set_hash_del); -+ write_unlock_bh(&ip_set_lock); -+ return 0; -+ } -+ DP("unreachable reached!"); -+ return -EINVAL; -+ } -+ -+ set = ip_set_list[index]; -+ IP_SET_ASSERT(set); -+ if (SETNAME_EQ(req_bind->binding, IPSET_TOKEN_DEFAULT)) { -+ /* Default binding of set */ -+ ip_set_id_t binding = ip_set_find_byindex(set->binding); -+ -+ if (binding == IP_SET_INVALID_ID) -+ return -ENOENT; -+ -+ write_lock_bh(&ip_set_lock); -+ /* Sets in hash values are referenced */ -+ __ip_set_put(set->binding); -+ set->binding = IP_SET_INVALID_ID; -+ write_unlock_bh(&ip_set_lock); -+ -+ return 0; -+ } else if (SETNAME_EQ(req_bind->binding, IPSET_TOKEN_ALL)) { -+ /* Flush all bindings */ -+ -+ write_lock_bh(&ip_set_lock); -+ FOREACH_HASH_RW_DO(__set_hash_del_byid, set->id); -+ write_unlock_bh(&ip_set_lock); -+ return 0; -+ } -+ -+ res = __ip_set_testip(set, -+ data + sizeof(struct ip_set_req_bind), -+ size - sizeof(struct ip_set_req_bind), -+ &ip); -+ -+ DP("set %s, ip: %u.%u.%u.%u", set->name, HIPQUAD(ip)); -+ if (res >= 0) -+ res = ip_set_hash_del(set->id, ip); -+ -+ return res; -+} -+ -+static int -+ip_set_testbind(ip_set_id_t index, -+ const void *data, -+ u_int32_t size) -+{ -+ struct ip_set *set = ip_set_list[index]; -+ const struct ip_set_req_bind *req_bind; -+ ip_set_id_t binding; -+ ip_set_ip_t ip; -+ int res; -+ -+ IP_SET_ASSERT(set); -+ if (size < sizeof(struct ip_set_req_bind)) -+ return -EINVAL; -+ -+ req_bind = data; -+ -+ if (SETNAME_EQ(req_bind->binding, IPSET_TOKEN_DEFAULT)) { -+ /* Default binding of set */ -+ const char *binding_name; -+ -+ if (size != sizeof(struct ip_set_req_bind) + IP_SET_MAXNAMELEN) -+ return -EINVAL; -+ -+ binding_name = data + sizeof(struct ip_set_req_bind); -+ -+ binding = ip_set_find_byname(binding_name); -+ if (binding == IP_SET_INVALID_ID) -+ return -ENOENT; -+ -+ res = (set->binding == binding) ? -EEXIST : 0; -+ -+ return res; -+ } -+ binding = ip_set_find_byname(req_bind->binding); -+ if (binding == IP_SET_INVALID_ID) -+ return -ENOENT; -+ -+ -+ res = __ip_set_testip(set, -+ data + sizeof(struct ip_set_req_bind), -+ size - sizeof(struct ip_set_req_bind), -+ &ip); -+ DP("set %s, ip: %u.%u.%u.%u, binding %s", -+ set->name, HIPQUAD(ip), ip_set_list[binding]->name); -+ -+ if (res >= 0) -+ res = (ip_set_find_in_hash(set->id, ip) == binding) -+ ? -EEXIST : 0; -+ -+ return res; -+} -+ -+static struct ip_set_type * -+find_set_type_rlock(const char *typename) -+{ -+ struct ip_set_type *type; -+ -+ read_lock_bh(&ip_set_lock); -+ type = find_set_type(typename); -+ if (type == NULL) -+ read_unlock_bh(&ip_set_lock); -+ -+ return type; -+} -+ -+static int -+find_free_id(const char *name, -+ ip_set_id_t *index, -+ ip_set_id_t *id) -+{ -+ ip_set_id_t i; -+ -+ *id = IP_SET_INVALID_ID; -+ for (i = 0; i < ip_set_max; i++) { -+ if (ip_set_list[i] == NULL) { -+ if (*id == IP_SET_INVALID_ID) -+ *id = *index = i; -+ } else if (SETNAME_EQ(name, ip_set_list[i]->name)) -+ /* Name clash */ -+ return -EEXIST; -+ } -+ if (*id == IP_SET_INVALID_ID) -+ /* No free slot remained */ -+ return -ERANGE; -+ /* Check that index is usable as id (swapping) */ -+ check: -+ for (i = 0; i < ip_set_max; i++) { -+ if (ip_set_list[i] != NULL -+ && ip_set_list[i]->id == *id) { -+ *id = i; -+ goto check; -+ } -+ } -+ return 0; -+} -+ -+/* -+ * Create a set -+ */ -+static int -+ip_set_create(const char *name, -+ const char *typename, -+ ip_set_id_t restore, -+ const void *data, -+ u_int32_t size) -+{ -+ struct ip_set *set; -+ ip_set_id_t index = 0, id; -+ int res = 0; -+ -+ DP("setname: %s, typename: %s, id: %u", name, typename, restore); -+ -+ /* -+ * First, and without any locks, allocate and initialize -+ * a normal base set structure. -+ */ -+ set = kmalloc(sizeof(struct ip_set), GFP_KERNEL); -+ if (!set) -+ return -ENOMEM; -+ rwlock_init(&set->lock); -+ strncpy(set->name, name, IP_SET_MAXNAMELEN); -+ set->binding = IP_SET_INVALID_ID; -+ atomic_set(&set->ref, 0); -+ -+ /* -+ * Next, take the &ip_set_lock, check that we know the type, -+ * and take a reference on the type, to make sure it -+ * stays available while constructing our new set. -+ * -+ * After referencing the type, we drop the &ip_set_lock, -+ * and let the new set construction run without locks. -+ */ -+ set->type = find_set_type_rlock(typename); -+ if (set->type == NULL) { -+ /* Try loading the module */ -+ char modulename[IP_SET_MAXNAMELEN + strlen("ip_set_") + 1]; -+ strcpy(modulename, "ip_set_"); -+ strcat(modulename, typename); -+ DP("try to load %s", modulename); -+ request_module(modulename); -+ set->type = find_set_type_rlock(typename); -+ } -+ if (set->type == NULL) { -+ ip_set_printk("no set type '%s', set '%s' not created", -+ typename, name); -+ res = -ENOENT; -+ goto out; -+ } -+ if (!try_module_get(set->type->me)) { -+ read_unlock_bh(&ip_set_lock); -+ res = -EFAULT; -+ goto out; -+ } -+ read_unlock_bh(&ip_set_lock); -+ -+ /* Check request size */ -+ if (size != set->type->header_size) { -+ ip_set_printk("data length wrong (want %lu, have %lu)", -+ (long unsigned)set->type->header_size, -+ (long unsigned)size); -+ goto put_out; -+ } -+ -+ /* -+ * Without holding any locks, create private part. -+ */ -+ res = set->type->create(set, data, size); -+ if (res != 0) -+ goto put_out; -+ -+ /* BTW, res==0 here. */ -+ -+ /* -+ * Here, we have a valid, constructed set. &ip_set_lock again, -+ * find free id/index and check that it is not already in -+ * ip_set_list. -+ */ -+ write_lock_bh(&ip_set_lock); -+ if ((res = find_free_id(set->name, &index, &id)) != 0) { -+ DP("no free id!"); -+ goto cleanup; -+ } -+ -+ /* Make sure restore gets the same index */ -+ if (restore != IP_SET_INVALID_ID && index != restore) { -+ DP("Can't restore, sets are screwed up"); -+ res = -ERANGE; -+ goto cleanup; -+ } -+ -+ /* -+ * Finally! Add our shiny new set to the list, and be done. -+ */ -+ DP("create: '%s' created with index %u, id %u!", set->name, index, id); -+ set->id = id; -+ ip_set_list[index] = set; -+ write_unlock_bh(&ip_set_lock); -+ return res; -+ -+ cleanup: -+ write_unlock_bh(&ip_set_lock); -+ set->type->destroy(set); -+ put_out: -+ module_put(set->type->me); -+ out: -+ kfree(set); -+ return res; -+} -+ -+/* -+ * Destroy a given existing set -+ */ -+static void -+ip_set_destroy_set(ip_set_id_t index) -+{ -+ struct ip_set *set = ip_set_list[index]; -+ -+ IP_SET_ASSERT(set); -+ DP("set: %s", set->name); -+ write_lock_bh(&ip_set_lock); -+ FOREACH_HASH_RW_DO(__set_hash_del_byid, set->id); -+ if (set->binding != IP_SET_INVALID_ID) -+ __ip_set_put(set->binding); -+ ip_set_list[index] = NULL; -+ write_unlock_bh(&ip_set_lock); -+ -+ /* Must call it without holding any lock */ -+ set->type->destroy(set); -+ module_put(set->type->me); -+ kfree(set); -+} -+ -+/* -+ * Destroy a set - or all sets -+ * Sets must not be referenced/used. -+ */ -+static int -+ip_set_destroy(ip_set_id_t index) -+{ -+ ip_set_id_t i; -+ -+ /* ref modification always protected by the mutex */ -+ if (index != IP_SET_INVALID_ID) { -+ if (atomic_read(&ip_set_list[index]->ref)) -+ return -EBUSY; -+ ip_set_destroy_set(index); -+ } else { -+ for (i = 0; i < ip_set_max; i++) { -+ if (ip_set_list[i] != NULL -+ && (atomic_read(&ip_set_list[i]->ref))) -+ return -EBUSY; -+ } -+ -+ for (i = 0; i < ip_set_max; i++) { -+ if (ip_set_list[i] != NULL) -+ ip_set_destroy_set(i); -+ } -+ } -+ return 0; -+} -+ -+static void -+ip_set_flush_set(struct ip_set *set) -+{ -+ DP("set: %s %u", set->name, set->id); -+ -+ write_lock_bh(&set->lock); -+ set->type->flush(set); -+ write_unlock_bh(&set->lock); -+} -+ -+/* -+ * Flush data in a set - or in all sets -+ */ -+static int -+ip_set_flush(ip_set_id_t index) -+{ -+ if (index != IP_SET_INVALID_ID) { -+ IP_SET_ASSERT(ip_set_list[index]); -+ ip_set_flush_set(ip_set_list[index]); -+ } else -+ FOREACH_SET_DO(ip_set_flush_set); -+ -+ return 0; -+} -+ -+/* Rename a set */ -+static int -+ip_set_rename(ip_set_id_t index, const char *name) -+{ -+ struct ip_set *set = ip_set_list[index]; -+ ip_set_id_t i; -+ int res = 0; -+ -+ DP("set: %s to %s", set->name, name); -+ write_lock_bh(&ip_set_lock); -+ for (i = 0; i < ip_set_max; i++) { -+ if (ip_set_list[i] != NULL -+ && SETNAME_EQ(ip_set_list[i]->name, name)) { -+ res = -EEXIST; -+ goto unlock; -+ } -+ } -+ strncpy(set->name, name, IP_SET_MAXNAMELEN); -+ unlock: -+ write_unlock_bh(&ip_set_lock); -+ return res; -+} -+ -+/* -+ * Swap two sets so that name/index points to the other. -+ * References are also swapped. -+ */ -+static int -+ip_set_swap(ip_set_id_t from_index, ip_set_id_t to_index) -+{ -+ struct ip_set *from = ip_set_list[from_index]; -+ struct ip_set *to = ip_set_list[to_index]; -+ char from_name[IP_SET_MAXNAMELEN]; -+ u_int32_t from_ref; -+ -+ DP("set: %s to %s", from->name, to->name); -+ /* Features must not change. -+ * Not an artifical restriction anymore, as we must prevent -+ * possible loops created by swapping in setlist type of sets. */ -+ if (from->type->features != to->type->features) -+ return -ENOEXEC; -+ -+ /* No magic here: ref munging protected by the mutex */ -+ write_lock_bh(&ip_set_lock); -+ strncpy(from_name, from->name, IP_SET_MAXNAMELEN); -+ from_ref = atomic_read(&from->ref); -+ -+ strncpy(from->name, to->name, IP_SET_MAXNAMELEN); -+ atomic_set(&from->ref, atomic_read(&to->ref)); -+ strncpy(to->name, from_name, IP_SET_MAXNAMELEN); -+ atomic_set(&to->ref, from_ref); -+ -+ ip_set_list[from_index] = to; -+ ip_set_list[to_index] = from; -+ -+ write_unlock_bh(&ip_set_lock); -+ return 0; -+} -+ -+/* -+ * List set data -+ */ -+ -+static inline void -+__set_hash_bindings_size_list(struct ip_set_hash *set_hash, -+ ip_set_id_t id, u_int32_t *size) -+{ -+ if (set_hash->id == id) -+ *size += sizeof(struct ip_set_hash_list); -+} -+ -+static inline void -+__set_hash_bindings_size_save(struct ip_set_hash *set_hash, -+ ip_set_id_t id, u_int32_t *size) -+{ -+ if (set_hash->id == id) -+ *size += sizeof(struct ip_set_hash_save); -+} -+ -+static inline void -+__set_hash_bindings(struct ip_set_hash *set_hash, -+ ip_set_id_t id, void *data, int *used) -+{ -+ if (set_hash->id == id) { -+ struct ip_set_hash_list *hash_list = data + *used; -+ -+ hash_list->ip = set_hash->ip; -+ hash_list->binding = set_hash->binding; -+ *used += sizeof(struct ip_set_hash_list); -+ } -+} -+ -+static int ip_set_list_set(ip_set_id_t index, -+ void *data, -+ int *used, -+ int len) -+{ -+ struct ip_set *set = ip_set_list[index]; -+ struct ip_set_list *set_list; -+ -+ /* Pointer to our header */ -+ set_list = data + *used; -+ -+ DP("set: %s, used: %d %p %p", set->name, *used, data, data + *used); -+ -+ /* Get and ensure header size */ -+ if (*used + sizeof(struct ip_set_list) > len) -+ goto not_enough_mem; -+ *used += sizeof(struct ip_set_list); -+ -+ read_lock_bh(&set->lock); -+ /* Get and ensure set specific header size */ -+ set_list->header_size = set->type->header_size; -+ if (*used + set_list->header_size > len) -+ goto unlock_set; -+ -+ /* Fill in the header */ -+ set_list->index = index; -+ set_list->binding = set->binding; -+ set_list->ref = atomic_read(&set->ref); -+ -+ /* Fill in set spefific header data */ -+ set->type->list_header(set, data + *used); -+ *used += set_list->header_size; -+ -+ /* Get and ensure set specific members size */ -+ set_list->members_size = set->type->list_members_size(set); -+ if (*used + set_list->members_size > len) -+ goto unlock_set; -+ -+ /* Fill in set spefific members data */ -+ set->type->list_members(set, data + *used); -+ *used += set_list->members_size; -+ read_unlock_bh(&set->lock); -+ -+ /* Bindings */ -+ -+ /* Get and ensure set specific bindings size */ -+ set_list->bindings_size = 0; -+ FOREACH_HASH_DO(__set_hash_bindings_size_list, -+ set->id, &set_list->bindings_size); -+ if (*used + set_list->bindings_size > len) -+ goto not_enough_mem; -+ -+ /* Fill in set spefific bindings data */ -+ FOREACH_HASH_DO(__set_hash_bindings, set->id, data, used); -+ -+ return 0; -+ -+ unlock_set: -+ read_unlock_bh(&set->lock); -+ not_enough_mem: -+ DP("not enough mem, try again"); -+ return -EAGAIN; -+} -+ -+/* -+ * Save sets -+ */ -+static int ip_set_save_set(ip_set_id_t index, -+ void *data, -+ int *used, -+ int len) -+{ -+ struct ip_set *set; -+ struct ip_set_save *set_save; -+ -+ /* Pointer to our header */ -+ set_save = data + *used; -+ -+ /* Get and ensure header size */ -+ if (*used + sizeof(struct ip_set_save) > len) -+ goto not_enough_mem; -+ *used += sizeof(struct ip_set_save); -+ -+ set = ip_set_list[index]; -+ DP("set: %s, used: %d(%d) %p %p", set->name, *used, len, -+ data, data + *used); -+ -+ read_lock_bh(&set->lock); -+ /* Get and ensure set specific header size */ -+ set_save->header_size = set->type->header_size; -+ if (*used + set_save->header_size > len) -+ goto unlock_set; -+ -+ /* Fill in the header */ -+ set_save->index = index; -+ set_save->binding = set->binding; -+ -+ /* Fill in set spefific header data */ -+ set->type->list_header(set, data + *used); -+ *used += set_save->header_size; -+ -+ DP("set header filled: %s, used: %d(%lu) %p %p", set->name, *used, -+ (unsigned long)set_save->header_size, data, data + *used); -+ /* Get and ensure set specific members size */ -+ set_save->members_size = set->type->list_members_size(set); -+ if (*used + set_save->members_size > len) -+ goto unlock_set; -+ -+ /* Fill in set spefific members data */ -+ set->type->list_members(set, data + *used); -+ *used += set_save->members_size; -+ read_unlock_bh(&set->lock); -+ DP("set members filled: %s, used: %d(%lu) %p %p", set->name, *used, -+ (unsigned long)set_save->members_size, data, data + *used); -+ return 0; -+ -+ unlock_set: -+ read_unlock_bh(&set->lock); -+ not_enough_mem: -+ DP("not enough mem, try again"); -+ return -EAGAIN; -+} -+ -+static inline void -+__set_hash_save_bindings(struct ip_set_hash *set_hash, -+ ip_set_id_t id, -+ void *data, -+ int *used, -+ int len, -+ int *res) -+{ -+ if (*res == 0 -+ && (id == IP_SET_INVALID_ID || set_hash->id == id)) { -+ struct ip_set_hash_save *hash_save = data + *used; -+ /* Ensure bindings size */ -+ if (*used + sizeof(struct ip_set_hash_save) > len) { -+ *res = -ENOMEM; -+ return; -+ } -+ hash_save->id = set_hash->id; -+ hash_save->ip = set_hash->ip; -+ hash_save->binding = set_hash->binding; -+ *used += sizeof(struct ip_set_hash_save); -+ } -+} -+ -+static int ip_set_save_bindings(ip_set_id_t index, -+ void *data, -+ int *used, -+ int len) -+{ -+ int res = 0; -+ struct ip_set_save *set_save; -+ -+ DP("used %u, len %u", *used, len); -+ /* Get and ensure header size */ -+ if (*used + sizeof(struct ip_set_save) > len) -+ return -ENOMEM; -+ -+ /* Marker */ -+ set_save = data + *used; -+ set_save->index = IP_SET_INVALID_ID; -+ set_save->header_size = 0; -+ set_save->members_size = 0; -+ *used += sizeof(struct ip_set_save); -+ -+ DP("marker added used %u, len %u", *used, len); -+ /* Fill in bindings data */ -+ if (index != IP_SET_INVALID_ID) -+ /* Sets are identified by id in hash */ -+ index = ip_set_list[index]->id; -+ FOREACH_HASH_DO(__set_hash_save_bindings, index, data, used, len, &res); -+ -+ return res; -+} -+ -+/* -+ * Restore sets -+ */ -+static int ip_set_restore(void *data, -+ int len) -+{ -+ int res = 0; -+ int line = 0, used = 0, members_size; -+ struct ip_set *set; -+ struct ip_set_hash_save *hash_save; -+ struct ip_set_restore *set_restore; -+ ip_set_id_t index; -+ -+ /* Loop to restore sets */ -+ while (1) { -+ line++; -+ -+ DP("%d %zu %d", used, sizeof(struct ip_set_restore), len); -+ /* Get and ensure header size */ -+ if (used + sizeof(struct ip_set_restore) > len) -+ return line; -+ set_restore = data + used; -+ used += sizeof(struct ip_set_restore); -+ -+ /* Ensure data size */ -+ if (used -+ + set_restore->header_size -+ + set_restore->members_size > len) -+ return line; -+ -+ /* Check marker */ -+ if (set_restore->index == IP_SET_INVALID_ID) { -+ line--; -+ goto bindings; -+ } -+ -+ /* Try to create the set */ -+ DP("restore %s %s", set_restore->name, set_restore->typename); -+ res = ip_set_create(set_restore->name, -+ set_restore->typename, -+ set_restore->index, -+ data + used, -+ set_restore->header_size); -+ -+ if (res != 0) -+ return line; -+ used += set_restore->header_size; -+ -+ index = ip_set_find_byindex(set_restore->index); -+ DP("index %u, restore_index %u", index, set_restore->index); -+ if (index != set_restore->index) -+ return line; -+ /* Try to restore members data */ -+ set = ip_set_list[index]; -+ members_size = 0; -+ DP("members_size %lu reqsize %lu", -+ (unsigned long)set_restore->members_size, -+ (unsigned long)set->type->reqsize); -+ while (members_size + set->type->reqsize <= -+ set_restore->members_size) { -+ line++; -+ DP("members: %d, line %d", members_size, line); -+ res = __ip_set_addip(index, -+ data + used + members_size, -+ set->type->reqsize); -+ if (!(res == 0 || res == -EEXIST)) -+ return line; -+ members_size += set->type->reqsize; -+ } -+ -+ DP("members_size %lu %d", -+ (unsigned long)set_restore->members_size, members_size); -+ if (members_size != set_restore->members_size) -+ return line++; -+ used += set_restore->members_size; -+ } -+ -+ bindings: -+ /* Loop to restore bindings */ -+ while (used < len) { -+ line++; -+ -+ DP("restore binding, line %u", line); -+ /* Get and ensure size */ -+ if (used + sizeof(struct ip_set_hash_save) > len) -+ return line; -+ hash_save = data + used; -+ used += sizeof(struct ip_set_hash_save); -+ -+ /* hash_save->id is used to store the index */ -+ index = ip_set_find_byindex(hash_save->id); -+ DP("restore binding index %u, id %u, %u -> %u", -+ index, hash_save->id, hash_save->ip, hash_save->binding); -+ if (index != hash_save->id) -+ return line; -+ if (ip_set_find_byindex(hash_save->binding) == IP_SET_INVALID_ID) { -+ DP("corrupt binding set index %u", hash_save->binding); -+ return line; -+ } -+ set = ip_set_list[hash_save->id]; -+ /* Null valued IP means default binding */ -+ if (hash_save->ip) -+ res = ip_set_hash_add(set->id, -+ hash_save->ip, -+ hash_save->binding); -+ else { -+ IP_SET_ASSERT(set->binding == IP_SET_INVALID_ID); -+ write_lock_bh(&ip_set_lock); -+ set->binding = hash_save->binding; -+ __ip_set_get(set->binding); -+ write_unlock_bh(&ip_set_lock); -+ DP("default binding: %u", set->binding); -+ } -+ if (res != 0) -+ return line; -+ } -+ if (used != len) -+ return line; -+ -+ return 0; -+} -+ -+static int -+ip_set_sockfn_set(struct sock *sk, int optval, void *user, unsigned int len) -+{ -+ void *data; -+ int res = 0; /* Assume OK */ -+ unsigned *op; -+ struct ip_set_req_adt *req_adt; -+ ip_set_id_t index = IP_SET_INVALID_ID; -+ int (*adtfn)(ip_set_id_t index, -+ const void *data, u_int32_t size); -+ struct fn_table { -+ int (*fn)(ip_set_id_t index, -+ const void *data, u_int32_t size); -+ } adtfn_table[] = -+ { { ip_set_addip }, { ip_set_delip }, { ip_set_testip}, -+ { ip_set_bindip}, { ip_set_unbindip }, { ip_set_testbind }, -+ }; -+ -+ DP("optval=%d, user=%p, len=%d", optval, user, len); -+ if (!capable(CAP_NET_ADMIN)) -+ return -EPERM; -+ if (optval != SO_IP_SET) -+ return -EBADF; -+ if (len <= sizeof(unsigned)) { -+ ip_set_printk("short userdata (want >%zu, got %u)", -+ sizeof(unsigned), len); -+ return -EINVAL; -+ } -+ data = vmalloc(len); -+ if (!data) { -+ DP("out of mem for %u bytes", len); -+ return -ENOMEM; -+ } -+ if (copy_from_user(data, user, len) != 0) { -+ res = -EFAULT; -+ goto done; -+ } -+ if (down_interruptible(&ip_set_app_mutex)) { -+ res = -EINTR; -+ goto done; -+ } -+ -+ op = (unsigned *)data; -+ DP("op=%x", *op); -+ -+ if (*op < IP_SET_OP_VERSION) { -+ /* Check the version at the beginning of operations */ -+ struct ip_set_req_version *req_version = data; -+ if (req_version->version != IP_SET_PROTOCOL_VERSION) { -+ res = -EPROTO; -+ goto done; -+ } -+ } -+ -+ switch (*op) { -+ case IP_SET_OP_CREATE:{ -+ struct ip_set_req_create *req_create = data; -+ -+ if (len < sizeof(struct ip_set_req_create)) { -+ ip_set_printk("short CREATE data (want >=%zu, got %u)", -+ sizeof(struct ip_set_req_create), len); -+ res = -EINVAL; -+ goto done; -+ } -+ req_create->name[IP_SET_MAXNAMELEN - 1] = '\0'; -+ req_create->typename[IP_SET_MAXNAMELEN - 1] = '\0'; -+ res = ip_set_create(req_create->name, -+ req_create->typename, -+ IP_SET_INVALID_ID, -+ data + sizeof(struct ip_set_req_create), -+ len - sizeof(struct ip_set_req_create)); -+ goto done; -+ } -+ case IP_SET_OP_DESTROY:{ -+ struct ip_set_req_std *req_destroy = data; -+ -+ if (len != sizeof(struct ip_set_req_std)) { -+ ip_set_printk("invalid DESTROY data (want %zu, got %u)", -+ sizeof(struct ip_set_req_std), len); -+ res = -EINVAL; -+ goto done; -+ } -+ if (SETNAME_EQ(req_destroy->name, IPSET_TOKEN_ALL)) { -+ /* Destroy all sets */ -+ index = IP_SET_INVALID_ID; -+ } else { -+ req_destroy->name[IP_SET_MAXNAMELEN - 1] = '\0'; -+ index = ip_set_find_byname(req_destroy->name); -+ -+ if (index == IP_SET_INVALID_ID) { -+ res = -ENOENT; -+ goto done; -+ } -+ } -+ -+ res = ip_set_destroy(index); -+ goto done; -+ } -+ case IP_SET_OP_FLUSH:{ -+ struct ip_set_req_std *req_flush = data; -+ -+ if (len != sizeof(struct ip_set_req_std)) { -+ ip_set_printk("invalid FLUSH data (want %zu, got %u)", -+ sizeof(struct ip_set_req_std), len); -+ res = -EINVAL; -+ goto done; -+ } -+ if (SETNAME_EQ(req_flush->name, IPSET_TOKEN_ALL)) { -+ /* Flush all sets */ -+ index = IP_SET_INVALID_ID; -+ } else { -+ req_flush->name[IP_SET_MAXNAMELEN - 1] = '\0'; -+ index = ip_set_find_byname(req_flush->name); -+ -+ if (index == IP_SET_INVALID_ID) { -+ res = -ENOENT; -+ goto done; -+ } -+ } -+ res = ip_set_flush(index); -+ goto done; -+ } -+ case IP_SET_OP_RENAME:{ -+ struct ip_set_req_create *req_rename = data; -+ -+ if (len != sizeof(struct ip_set_req_create)) { -+ ip_set_printk("invalid RENAME data (want %zu, got %u)", -+ sizeof(struct ip_set_req_create), len); -+ res = -EINVAL; -+ goto done; -+ } -+ -+ req_rename->name[IP_SET_MAXNAMELEN - 1] = '\0'; -+ req_rename->typename[IP_SET_MAXNAMELEN - 1] = '\0'; -+ -+ index = ip_set_find_byname(req_rename->name); -+ if (index == IP_SET_INVALID_ID) { -+ res = -ENOENT; -+ goto done; -+ } -+ res = ip_set_rename(index, req_rename->typename); -+ goto done; -+ } -+ case IP_SET_OP_SWAP:{ -+ struct ip_set_req_create *req_swap = data; -+ ip_set_id_t to_index; -+ -+ if (len != sizeof(struct ip_set_req_create)) { -+ ip_set_printk("invalid SWAP data (want %zu, got %u)", -+ sizeof(struct ip_set_req_create), len); -+ res = -EINVAL; -+ goto done; -+ } -+ -+ req_swap->name[IP_SET_MAXNAMELEN - 1] = '\0'; -+ req_swap->typename[IP_SET_MAXNAMELEN - 1] = '\0'; -+ -+ index = ip_set_find_byname(req_swap->name); -+ if (index == IP_SET_INVALID_ID) { -+ res = -ENOENT; -+ goto done; -+ } -+ to_index = ip_set_find_byname(req_swap->typename); -+ if (to_index == IP_SET_INVALID_ID) { -+ res = -ENOENT; -+ goto done; -+ } -+ res = ip_set_swap(index, to_index); -+ goto done; -+ } -+ default: -+ break; /* Set identified by id */ -+ } -+ -+ /* There we may have add/del/test/bind/unbind/test_bind operations */ -+ if (*op < IP_SET_OP_ADD_IP || *op > IP_SET_OP_TEST_BIND_SET) { -+ res = -EBADMSG; -+ goto done; -+ } -+ adtfn = adtfn_table[*op - IP_SET_OP_ADD_IP].fn; -+ -+ if (len < sizeof(struct ip_set_req_adt)) { -+ ip_set_printk("short data in adt request (want >=%zu, got %u)", -+ sizeof(struct ip_set_req_adt), len); -+ res = -EINVAL; -+ goto done; -+ } -+ req_adt = data; -+ -+ /* -U :all: :all:|:default: uses IP_SET_INVALID_ID */ -+ if (!(*op == IP_SET_OP_UNBIND_SET -+ && req_adt->index == IP_SET_INVALID_ID)) { -+ index = ip_set_find_byindex(req_adt->index); -+ if (index == IP_SET_INVALID_ID) { -+ res = -ENOENT; -+ goto done; -+ } -+ } -+ res = adtfn(index, data, len); -+ -+ done: -+ up(&ip_set_app_mutex); -+ vfree(data); -+ if (res > 0) -+ res = 0; -+ DP("final result %d", res); -+ return res; -+} -+ -+static int -+ip_set_sockfn_get(struct sock *sk, int optval, void *user, int *len) -+{ -+ int res = 0; -+ unsigned *op; -+ ip_set_id_t index = IP_SET_INVALID_ID; -+ void *data; -+ int copylen = *len; -+ -+ DP("optval=%d, user=%p, len=%d", optval, user, *len); -+ if (!capable(CAP_NET_ADMIN)) -+ return -EPERM; -+ if (optval != SO_IP_SET) -+ return -EBADF; -+ if (*len < sizeof(unsigned)) { -+ ip_set_printk("short userdata (want >=%zu, got %d)", -+ sizeof(unsigned), *len); -+ return -EINVAL; -+ } -+ data = vmalloc(*len); -+ if (!data) { -+ DP("out of mem for %d bytes", *len); -+ return -ENOMEM; -+ } -+ if (copy_from_user(data, user, *len) != 0) { -+ res = -EFAULT; -+ goto done; -+ } -+ if (down_interruptible(&ip_set_app_mutex)) { -+ res = -EINTR; -+ goto done; -+ } -+ -+ op = (unsigned *) data; -+ DP("op=%x", *op); -+ -+ if (*op < IP_SET_OP_VERSION) { -+ /* Check the version at the beginning of operations */ -+ struct ip_set_req_version *req_version = data; -+ if (req_version->version != IP_SET_PROTOCOL_VERSION) { -+ res = -EPROTO; -+ goto done; -+ } -+ } -+ -+ switch (*op) { -+ case IP_SET_OP_VERSION: { -+ struct ip_set_req_version *req_version = data; -+ -+ if (*len != sizeof(struct ip_set_req_version)) { -+ ip_set_printk("invalid VERSION (want %zu, got %d)", -+ sizeof(struct ip_set_req_version), -+ *len); -+ res = -EINVAL; -+ goto done; -+ } -+ -+ req_version->version = IP_SET_PROTOCOL_VERSION; -+ res = copy_to_user(user, req_version, -+ sizeof(struct ip_set_req_version)); -+ goto done; -+ } -+ case IP_SET_OP_GET_BYNAME: { -+ struct ip_set_req_get_set *req_get = data; -+ -+ if (*len != sizeof(struct ip_set_req_get_set)) { -+ ip_set_printk("invalid GET_BYNAME (want %zu, got %d)", -+ sizeof(struct ip_set_req_get_set), *len); -+ res = -EINVAL; -+ goto done; -+ } -+ req_get->set.name[IP_SET_MAXNAMELEN - 1] = '\0'; -+ index = ip_set_find_byname(req_get->set.name); -+ req_get->set.index = index; -+ goto copy; -+ } -+ case IP_SET_OP_GET_BYINDEX: { -+ struct ip_set_req_get_set *req_get = data; -+ -+ if (*len != sizeof(struct ip_set_req_get_set)) { -+ ip_set_printk("invalid GET_BYINDEX (want %zu, got %d)", -+ sizeof(struct ip_set_req_get_set), *len); -+ res = -EINVAL; -+ goto done; -+ } -+ req_get->set.name[IP_SET_MAXNAMELEN - 1] = '\0'; -+ index = ip_set_find_byindex(req_get->set.index); -+ strncpy(req_get->set.name, -+ index == IP_SET_INVALID_ID ? "" -+ : ip_set_list[index]->name, IP_SET_MAXNAMELEN); -+ goto copy; -+ } -+ case IP_SET_OP_ADT_GET: { -+ struct ip_set_req_adt_get *req_get = data; -+ -+ if (*len != sizeof(struct ip_set_req_adt_get)) { -+ ip_set_printk("invalid ADT_GET (want %zu, got %d)", -+ sizeof(struct ip_set_req_adt_get), *len); -+ res = -EINVAL; -+ goto done; -+ } -+ req_get->set.name[IP_SET_MAXNAMELEN - 1] = '\0'; -+ index = ip_set_find_byname(req_get->set.name); -+ if (index != IP_SET_INVALID_ID) { -+ req_get->set.index = index; -+ strncpy(req_get->typename, -+ ip_set_list[index]->type->typename, -+ IP_SET_MAXNAMELEN - 1); -+ } else { -+ res = -ENOENT; -+ goto done; -+ } -+ goto copy; -+ } -+ case IP_SET_OP_MAX_SETS: { -+ struct ip_set_req_max_sets *req_max_sets = data; -+ ip_set_id_t i; -+ -+ if (*len != sizeof(struct ip_set_req_max_sets)) { -+ ip_set_printk("invalid MAX_SETS (want %zu, got %d)", -+ sizeof(struct ip_set_req_max_sets), *len); -+ res = -EINVAL; -+ goto done; -+ } -+ -+ if (SETNAME_EQ(req_max_sets->set.name, IPSET_TOKEN_ALL)) { -+ req_max_sets->set.index = IP_SET_INVALID_ID; -+ } else { -+ req_max_sets->set.name[IP_SET_MAXNAMELEN - 1] = '\0'; -+ req_max_sets->set.index = -+ ip_set_find_byname(req_max_sets->set.name); -+ if (req_max_sets->set.index == IP_SET_INVALID_ID) { -+ res = -ENOENT; -+ goto done; -+ } -+ } -+ req_max_sets->max_sets = ip_set_max; -+ req_max_sets->sets = 0; -+ for (i = 0; i < ip_set_max; i++) { -+ if (ip_set_list[i] != NULL) -+ req_max_sets->sets++; -+ } -+ goto copy; -+ } -+ case IP_SET_OP_LIST_SIZE: -+ case IP_SET_OP_SAVE_SIZE: { -+ struct ip_set_req_setnames *req_setnames = data; -+ struct ip_set_name_list *name_list; -+ struct ip_set *set; -+ ip_set_id_t i; -+ int used; -+ -+ if (*len < sizeof(struct ip_set_req_setnames)) { -+ ip_set_printk("short LIST_SIZE (want >=%zu, got %d)", -+ sizeof(struct ip_set_req_setnames), *len); -+ res = -EINVAL; -+ goto done; -+ } -+ -+ req_setnames->size = 0; -+ used = sizeof(struct ip_set_req_setnames); -+ for (i = 0; i < ip_set_max; i++) { -+ if (ip_set_list[i] == NULL) -+ continue; -+ name_list = data + used; -+ used += sizeof(struct ip_set_name_list); -+ if (used > copylen) { -+ res = -EAGAIN; -+ goto done; -+ } -+ set = ip_set_list[i]; -+ /* Fill in index, name, etc. */ -+ name_list->index = i; -+ name_list->id = set->id; -+ strncpy(name_list->name, -+ set->name, -+ IP_SET_MAXNAMELEN - 1); -+ strncpy(name_list->typename, -+ set->type->typename, -+ IP_SET_MAXNAMELEN - 1); -+ DP("filled %s of type %s, index %u\n", -+ name_list->name, name_list->typename, -+ name_list->index); -+ if (!(req_setnames->index == IP_SET_INVALID_ID -+ || req_setnames->index == i)) -+ continue; -+ /* Update size */ -+ switch (*op) { -+ case IP_SET_OP_LIST_SIZE: { -+ req_setnames->size += sizeof(struct ip_set_list) -+ + set->type->header_size -+ + set->type->list_members_size(set); -+ /* Sets are identified by id in the hash */ -+ FOREACH_HASH_DO(__set_hash_bindings_size_list, -+ set->id, &req_setnames->size); -+ break; -+ } -+ case IP_SET_OP_SAVE_SIZE: { -+ req_setnames->size += sizeof(struct ip_set_save) -+ + set->type->header_size -+ + set->type->list_members_size(set); -+ FOREACH_HASH_DO(__set_hash_bindings_size_save, -+ set->id, &req_setnames->size); -+ break; -+ } -+ default: -+ break; -+ } -+ } -+ if (copylen != used) { -+ res = -EAGAIN; -+ goto done; -+ } -+ goto copy; -+ } -+ case IP_SET_OP_LIST: { -+ struct ip_set_req_list *req_list = data; -+ ip_set_id_t i; -+ int used; -+ -+ if (*len < sizeof(struct ip_set_req_list)) { -+ ip_set_printk("short LIST (want >=%zu, got %d)", -+ sizeof(struct ip_set_req_list), *len); -+ res = -EINVAL; -+ goto done; -+ } -+ index = req_list->index; -+ if (index != IP_SET_INVALID_ID -+ && ip_set_find_byindex(index) != index) { -+ res = -ENOENT; -+ goto done; -+ } -+ used = 0; -+ if (index == IP_SET_INVALID_ID) { -+ /* List all sets */ -+ for (i = 0; i < ip_set_max && res == 0; i++) { -+ if (ip_set_list[i] != NULL) -+ res = ip_set_list_set(i, data, &used, *len); -+ } -+ } else { -+ /* List an individual set */ -+ res = ip_set_list_set(index, data, &used, *len); -+ } -+ if (res != 0) -+ goto done; -+ else if (copylen != used) { -+ res = -EAGAIN; -+ goto done; -+ } -+ goto copy; -+ } -+ case IP_SET_OP_SAVE: { -+ struct ip_set_req_list *req_save = data; -+ ip_set_id_t i; -+ int used; -+ -+ if (*len < sizeof(struct ip_set_req_list)) { -+ ip_set_printk("short SAVE (want >=%zu, got %d)", -+ sizeof(struct ip_set_req_list), *len); -+ res = -EINVAL; -+ goto done; -+ } -+ index = req_save->index; -+ if (index != IP_SET_INVALID_ID -+ && ip_set_find_byindex(index) != index) { -+ res = -ENOENT; -+ goto done; -+ } -+ -+#define SETLIST(set) (strcmp(set->type->typename, "setlist") == 0) -+ -+ used = 0; -+ if (index == IP_SET_INVALID_ID) { -+ /* Save all sets: ugly setlist type dependency */ -+ int setlist = 0; -+ setlists: -+ for (i = 0; i < ip_set_max && res == 0; i++) { -+ if (ip_set_list[i] != NULL -+ && !(setlist ^ SETLIST(ip_set_list[i]))) -+ res = ip_set_save_set(i, data, &used, *len); -+ } -+ if (!setlist) { -+ setlist = 1; -+ goto setlists; -+ } -+ } else { -+ /* Save an individual set */ -+ res = ip_set_save_set(index, data, &used, *len); -+ } -+ if (res == 0) -+ res = ip_set_save_bindings(index, data, &used, *len); -+ -+ if (res != 0) -+ goto done; -+ else if (copylen != used) { -+ res = -EAGAIN; -+ goto done; -+ } -+ goto copy; -+ } -+ case IP_SET_OP_RESTORE: { -+ struct ip_set_req_setnames *req_restore = data; -+ int line; -+ -+ if (*len < sizeof(struct ip_set_req_setnames) -+ || *len != req_restore->size) { -+ ip_set_printk("invalid RESTORE (want =%lu, got %d)", -+ (long unsigned)req_restore->size, *len); -+ res = -EINVAL; -+ goto done; -+ } -+ line = ip_set_restore(data + sizeof(struct ip_set_req_setnames), -+ req_restore->size - sizeof(struct ip_set_req_setnames)); -+ DP("ip_set_restore: %d", line); -+ if (line != 0) { -+ res = -EAGAIN; -+ req_restore->size = line; -+ copylen = sizeof(struct ip_set_req_setnames); -+ goto copy; -+ } -+ goto done; -+ } -+ default: -+ res = -EBADMSG; -+ goto done; -+ } /* end of switch(op) */ -+ -+ copy: -+ DP("set %s, copylen %d", index != IP_SET_INVALID_ID -+ && ip_set_list[index] -+ ? ip_set_list[index]->name -+ : ":all:", copylen); -+ res = copy_to_user(user, data, copylen); -+ -+ done: -+ up(&ip_set_app_mutex); -+ vfree(data); -+ if (res > 0) -+ res = 0; -+ DP("final result %d", res); -+ return res; -+} -+ -+static struct nf_sockopt_ops so_set = { -+ .pf = PF_INET, -+ .set_optmin = SO_IP_SET, -+ .set_optmax = SO_IP_SET + 1, -+ .set = &ip_set_sockfn_set, -+ .get_optmin = SO_IP_SET, -+ .get_optmax = SO_IP_SET + 1, -+ .get = &ip_set_sockfn_get, -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23) -+ .use = 0, -+#else -+ .owner = THIS_MODULE, -+#endif -+}; -+ -+static int max_sets, hash_size; -+ -+module_param(max_sets, int, 0600); -+MODULE_PARM_DESC(max_sets, "maximal number of sets"); -+module_param(hash_size, int, 0600); -+MODULE_PARM_DESC(hash_size, "hash size for bindings"); -+MODULE_LICENSE("GPL"); -+MODULE_AUTHOR("Jozsef Kadlecsik "); -+MODULE_DESCRIPTION("module implementing core IP set support"); -+ -+static int __init ip_set_init(void) -+{ -+ int res; -+ ip_set_id_t i; -+ -+ get_random_bytes(&ip_set_hash_random, 4); -+ if (max_sets) -+ ip_set_max = max_sets; -+ ip_set_list = vmalloc(sizeof(struct ip_set *) * ip_set_max); -+ if (!ip_set_list) { -+ printk(KERN_ERR "Unable to create ip_set_list\n"); -+ return -ENOMEM; -+ } -+ memset(ip_set_list, 0, sizeof(struct ip_set *) * ip_set_max); -+ if (hash_size) -+ ip_set_bindings_hash_size = hash_size; -+ ip_set_hash = vmalloc(sizeof(struct list_head) * ip_set_bindings_hash_size); -+ if (!ip_set_hash) { -+ printk(KERN_ERR "Unable to create ip_set_hash\n"); -+ vfree(ip_set_list); -+ return -ENOMEM; -+ } -+ for (i = 0; i < ip_set_bindings_hash_size; i++) -+ INIT_LIST_HEAD(&ip_set_hash[i]); -+ -+ INIT_LIST_HEAD(&set_type_list); -+ -+ res = nf_register_sockopt(&so_set); -+ if (res != 0) { -+ ip_set_printk("SO_SET registry failed: %d", res); -+ vfree(ip_set_list); -+ vfree(ip_set_hash); -+ return res; -+ } -+ -+ return 0; -+} -+ -+static void __exit ip_set_fini(void) -+{ -+ /* There can't be any existing set or binding */ -+ nf_unregister_sockopt(&so_set); -+ vfree(ip_set_list); -+ vfree(ip_set_hash); -+ DP("these are the famous last words"); -+} -+ -+EXPORT_SYMBOL(ip_set_register_set_type); -+EXPORT_SYMBOL(ip_set_unregister_set_type); -+ -+EXPORT_SYMBOL(ip_set_get_byname); -+EXPORT_SYMBOL(ip_set_get_byindex); -+EXPORT_SYMBOL(ip_set_put_byindex); -+EXPORT_SYMBOL(ip_set_id); -+EXPORT_SYMBOL(__ip_set_get_byname); -+EXPORT_SYMBOL(__ip_set_put_byindex); -+ -+EXPORT_SYMBOL(ip_set_addip_kernel); -+EXPORT_SYMBOL(ip_set_delip_kernel); -+EXPORT_SYMBOL(ip_set_testip_kernel); -+ -+module_init(ip_set_init); -+module_exit(ip_set_fini); ---- /dev/null -+++ b/net/ipv4/netfilter/ip_set_iphash.c -@@ -0,0 +1,166 @@ -+/* Copyright (C) 2003-2008 Jozsef Kadlecsik -+ * -+ * 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. -+ */ -+ -+/* Kernel module implementing an ip hash set */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+ -+#include -+ -+static int limit = MAX_RANGE; -+ -+static inline __u32 -+iphash_id(struct ip_set *set, ip_set_ip_t *hash_ip, ip_set_ip_t ip) -+{ -+ struct ip_set_iphash *map = set->data; -+ __u32 id; -+ u_int16_t i; -+ ip_set_ip_t *elem; -+ -+ *hash_ip = ip & map->netmask; -+ DP("set: %s, ip:%u.%u.%u.%u, %u.%u.%u.%u, %u.%u.%u.%u", -+ set->name, HIPQUAD(ip), HIPQUAD(*hash_ip), HIPQUAD(map->netmask)); -+ -+ for (i = 0; i < map->probes; i++) { -+ id = jhash_ip(map, i, *hash_ip) % map->hashsize; -+ DP("hash key: %u", id); -+ elem = HARRAY_ELEM(map->members, ip_set_ip_t *, id); -+ if (*elem == *hash_ip) -+ return id; -+ /* No shortcut - there can be deleted entries. */ -+ } -+ return UINT_MAX; -+} -+ -+static inline int -+iphash_test(struct ip_set *set, ip_set_ip_t *hash_ip, ip_set_ip_t ip) -+{ -+ return (ip && iphash_id(set, hash_ip, ip) != UINT_MAX); -+} -+ -+#define KADT_CONDITION -+ -+UADT(iphash, test) -+KADT(iphash, test, ipaddr) -+ -+static inline int -+__iphash_add(struct ip_set_iphash *map, ip_set_ip_t *ip) -+{ -+ __u32 probe; -+ u_int16_t i; -+ ip_set_ip_t *elem, *slot = NULL; -+ -+ for (i = 0; i < map->probes; i++) { -+ probe = jhash_ip(map, i, *ip) % map->hashsize; -+ elem = HARRAY_ELEM(map->members, ip_set_ip_t *, probe); -+ if (*elem == *ip) -+ return -EEXIST; -+ if (!(slot || *elem)) -+ slot = elem; -+ /* There can be deleted entries, must check all slots */ -+ } -+ if (slot) { -+ *slot = *ip; -+ map->elements++; -+ return 0; -+ } -+ /* Trigger rehashing */ -+ return -EAGAIN; -+} -+ -+static inline int -+iphash_add(struct ip_set *set, ip_set_ip_t *hash_ip, ip_set_ip_t ip) -+{ -+ struct ip_set_iphash *map = set->data; -+ -+ if (!ip || map->elements >= limit) -+ return -ERANGE; -+ -+ *hash_ip = ip & map->netmask; -+ -+ return __iphash_add(map, hash_ip); -+} -+ -+UADT(iphash, add) -+KADT(iphash, add, ipaddr) -+ -+static inline void -+__iphash_retry(struct ip_set_iphash *tmp, struct ip_set_iphash *map) -+{ -+ tmp->netmask = map->netmask; -+} -+ -+HASH_RETRY(iphash, ip_set_ip_t) -+ -+static inline int -+iphash_del(struct ip_set *set, ip_set_ip_t *hash_ip, ip_set_ip_t ip) -+{ -+ struct ip_set_iphash *map = set->data; -+ ip_set_ip_t id, *elem; -+ -+ if (!ip) -+ return -ERANGE; -+ -+ id = iphash_id(set, hash_ip, ip); -+ if (id == UINT_MAX) -+ return -EEXIST; -+ -+ elem = HARRAY_ELEM(map->members, ip_set_ip_t *, id); -+ *elem = 0; -+ map->elements--; -+ -+ return 0; -+} -+ -+UADT(iphash, del) -+KADT(iphash, del, ipaddr) -+ -+static inline int -+__iphash_create(const struct ip_set_req_iphash_create *req, -+ struct ip_set_iphash *map) -+{ -+ map->netmask = req->netmask; -+ -+ return 0; -+} -+ -+HASH_CREATE(iphash, ip_set_ip_t) -+HASH_DESTROY(iphash) -+ -+HASH_FLUSH(iphash, ip_set_ip_t) -+ -+static inline void -+__iphash_list_header(const struct ip_set_iphash *map, -+ struct ip_set_req_iphash_create *header) -+{ -+ header->netmask = map->netmask; -+} -+ -+HASH_LIST_HEADER(iphash) -+HASH_LIST_MEMBERS_SIZE(iphash, ip_set_ip_t) -+HASH_LIST_MEMBERS(iphash, ip_set_ip_t) -+ -+IP_SET_RTYPE(iphash, IPSET_TYPE_IP | IPSET_DATA_SINGLE) -+ -+MODULE_LICENSE("GPL"); -+MODULE_AUTHOR("Jozsef Kadlecsik "); -+MODULE_DESCRIPTION("iphash type of IP sets"); -+module_param(limit, int, 0600); -+MODULE_PARM_DESC(limit, "maximal number of elements stored in the sets"); -+ -+REGISTER_MODULE(iphash) ---- /dev/null -+++ b/net/ipv4/netfilter/ip_set_ipmap.c -@@ -0,0 +1,142 @@ -+/* Copyright (C) 2000-2002 Joakim Axelsson -+ * Patrick Schaaf -+ * Copyright (C) 2003-2008 Jozsef Kadlecsik -+ * -+ * 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. -+ */ -+ -+/* Kernel module implementing an IP set type: the single bitmap type */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+ -+static inline ip_set_ip_t -+ip_to_id(const struct ip_set_ipmap *map, ip_set_ip_t ip) -+{ -+ return (ip - map->first_ip)/map->hosts; -+} -+ -+static inline int -+ipmap_test(const struct ip_set *set, ip_set_ip_t *hash_ip, ip_set_ip_t ip) -+{ -+ const struct ip_set_ipmap *map = set->data; -+ -+ if (ip < map->first_ip || ip > map->last_ip) -+ return -ERANGE; -+ -+ *hash_ip = ip & map->netmask; -+ DP("set: %s, ip:%u.%u.%u.%u, %u.%u.%u.%u", -+ set->name, HIPQUAD(ip), HIPQUAD(*hash_ip)); -+ return !!test_bit(ip_to_id(map, *hash_ip), map->members); -+} -+ -+#define KADT_CONDITION -+ -+UADT(ipmap, test) -+KADT(ipmap, test, ipaddr) -+ -+static inline int -+ipmap_add(struct ip_set *set, ip_set_ip_t *hash_ip, ip_set_ip_t ip) -+{ -+ struct ip_set_ipmap *map = set->data; -+ -+ if (ip < map->first_ip || ip > map->last_ip) -+ return -ERANGE; -+ -+ *hash_ip = ip & map->netmask; -+ DP("%u.%u.%u.%u, %u.%u.%u.%u", HIPQUAD(ip), HIPQUAD(*hash_ip)); -+ if (test_and_set_bit(ip_to_id(map, *hash_ip), map->members)) -+ return -EEXIST; -+ -+ return 0; -+} -+ -+UADT(ipmap, add) -+KADT(ipmap, add, ipaddr) -+ -+static inline int -+ipmap_del(struct ip_set *set, ip_set_ip_t *hash_ip, ip_set_ip_t ip) -+{ -+ struct ip_set_ipmap *map = set->data; -+ -+ if (ip < map->first_ip || ip > map->last_ip) -+ return -ERANGE; -+ -+ *hash_ip = ip & map->netmask; -+ DP("%u.%u.%u.%u, %u.%u.%u.%u", HIPQUAD(ip), HIPQUAD(*hash_ip)); -+ if (!test_and_clear_bit(ip_to_id(map, *hash_ip), map->members)) -+ return -EEXIST; -+ -+ return 0; -+} -+ -+UADT(ipmap, del) -+KADT(ipmap, del, ipaddr) -+ -+static inline int -+__ipmap_create(const struct ip_set_req_ipmap_create *req, -+ struct ip_set_ipmap *map) -+{ -+ map->netmask = req->netmask; -+ -+ if (req->netmask == 0xFFFFFFFF) { -+ map->hosts = 1; -+ map->sizeid = map->last_ip - map->first_ip + 1; -+ } else { -+ unsigned int mask_bits, netmask_bits; -+ ip_set_ip_t mask; -+ -+ map->first_ip &= map->netmask; /* Should we better bark? */ -+ -+ mask = range_to_mask(map->first_ip, map->last_ip, &mask_bits); -+ netmask_bits = mask_to_bits(map->netmask); -+ -+ if ((!mask && (map->first_ip || map->last_ip != 0xFFFFFFFF)) -+ || netmask_bits <= mask_bits) -+ return -ENOEXEC; -+ -+ DP("mask_bits %u, netmask_bits %u", -+ mask_bits, netmask_bits); -+ map->hosts = 2 << (32 - netmask_bits - 1); -+ map->sizeid = 2 << (netmask_bits - mask_bits - 1); -+ } -+ if (map->sizeid > MAX_RANGE + 1) { -+ ip_set_printk("range too big, %d elements (max %d)", -+ map->sizeid, MAX_RANGE+1); -+ return -ENOEXEC; -+ } -+ DP("hosts %u, sizeid %u", map->hosts, map->sizeid); -+ return bitmap_bytes(0, map->sizeid - 1); -+} -+ -+BITMAP_CREATE(ipmap) -+BITMAP_DESTROY(ipmap) -+BITMAP_FLUSH(ipmap) -+ -+static inline void -+__ipmap_list_header(const struct ip_set_ipmap *map, -+ struct ip_set_req_ipmap_create *header) -+{ -+ header->netmask = map->netmask; -+} -+ -+BITMAP_LIST_HEADER(ipmap) -+BITMAP_LIST_MEMBERS_SIZE(ipmap) -+BITMAP_LIST_MEMBERS(ipmap) -+ -+IP_SET_TYPE(ipmap, IPSET_TYPE_IP | IPSET_DATA_SINGLE) -+ -+MODULE_LICENSE("GPL"); -+MODULE_AUTHOR("Jozsef Kadlecsik "); -+MODULE_DESCRIPTION("ipmap type of IP sets"); -+ -+REGISTER_MODULE(ipmap) ---- /dev/null -+++ b/net/ipv4/netfilter/ip_set_ipporthash.c -@@ -0,0 +1,203 @@ -+/* Copyright (C) 2003-2008 Jozsef Kadlecsik -+ * -+ * 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. -+ */ -+ -+/* Kernel module implementing an ip+port hash set */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+ -+#include -+#include -+ -+static int limit = MAX_RANGE; -+ -+static inline __u32 -+ipporthash_id(struct ip_set *set, ip_set_ip_t *hash_ip, -+ ip_set_ip_t ip, ip_set_ip_t port) -+{ -+ struct ip_set_ipporthash *map = set->data; -+ __u32 id; -+ u_int16_t i; -+ ip_set_ip_t *elem; -+ -+ *hash_ip = pack_ip_port(map, ip, port); -+ -+ DP("set: %s, ipport:%u.%u.%u.%u:%u, %u.%u.%u.%u", -+ set->name, HIPQUAD(ip), port, HIPQUAD(*hash_ip)); -+ if (!*hash_ip) -+ return UINT_MAX; -+ -+ for (i = 0; i < map->probes; i++) { -+ id = jhash_ip(map, i, *hash_ip) % map->hashsize; -+ DP("hash key: %u", id); -+ elem = HARRAY_ELEM(map->members, ip_set_ip_t *, id); -+ if (*elem == *hash_ip) -+ return id; -+ /* No shortcut - there can be deleted entries. */ -+ } -+ return UINT_MAX; -+} -+ -+static inline int -+ipporthash_test(struct ip_set *set, ip_set_ip_t *hash_ip, -+ ip_set_ip_t ip, ip_set_ip_t port) -+{ -+ struct ip_set_ipporthash *map = set->data; -+ -+ if (ip < map->first_ip || ip > map->last_ip) -+ return -ERANGE; -+ -+ return (ipporthash_id(set, hash_ip, ip, port) != UINT_MAX); -+} -+ -+#define KADT_CONDITION \ -+ ip_set_ip_t port; \ -+ \ -+ if (flags[index+1] == 0) \ -+ return 0; \ -+ \ -+ port = get_port(skb, flags[index+1]); \ -+ \ -+ if (port == INVALID_PORT) \ -+ return 0; -+ -+UADT(ipporthash, test, req->port) -+KADT(ipporthash, test, ipaddr, port) -+ -+static inline int -+__ipporthash_add(struct ip_set_ipporthash *map, ip_set_ip_t *ip) -+{ -+ __u32 probe; -+ u_int16_t i; -+ ip_set_ip_t *elem, *slot = NULL; -+ -+ for (i = 0; i < map->probes; i++) { -+ probe = jhash_ip(map, i, *ip) % map->hashsize; -+ elem = HARRAY_ELEM(map->members, ip_set_ip_t *, probe); -+ if (*elem == *ip) -+ return -EEXIST; -+ if (!(slot || *elem)) -+ slot = elem; -+ /* There can be deleted entries, must check all slots */ -+ } -+ if (slot) { -+ *slot = *ip; -+ map->elements++; -+ return 0; -+ } -+ /* Trigger rehashing */ -+ return -EAGAIN; -+} -+ -+static inline int -+ipporthash_add(struct ip_set *set, ip_set_ip_t *hash_ip, -+ ip_set_ip_t ip, ip_set_ip_t port) -+{ -+ struct ip_set_ipporthash *map = set->data; -+ if (map->elements > limit) -+ return -ERANGE; -+ if (ip < map->first_ip || ip > map->last_ip) -+ return -ERANGE; -+ -+ *hash_ip = pack_ip_port(map, ip, port); -+ -+ if (!*hash_ip) -+ return -ERANGE; -+ -+ return __ipporthash_add(map, hash_ip); -+} -+ -+UADT(ipporthash, add, req->port) -+KADT(ipporthash, add, ipaddr, port) -+ -+static inline void -+__ipporthash_retry(struct ip_set_ipporthash *tmp, -+ struct ip_set_ipporthash *map) -+{ -+ tmp->first_ip = map->first_ip; -+ tmp->last_ip = map->last_ip; -+} -+ -+HASH_RETRY(ipporthash, ip_set_ip_t) -+ -+static inline int -+ipporthash_del(struct ip_set *set, ip_set_ip_t *hash_ip, -+ ip_set_ip_t ip, ip_set_ip_t port) -+{ -+ struct ip_set_ipporthash *map = set->data; -+ ip_set_ip_t id; -+ ip_set_ip_t *elem; -+ -+ if (ip < map->first_ip || ip > map->last_ip) -+ return -ERANGE; -+ -+ id = ipporthash_id(set, hash_ip, ip, port); -+ -+ if (id == UINT_MAX) -+ return -EEXIST; -+ -+ elem = HARRAY_ELEM(map->members, ip_set_ip_t *, id); -+ *elem = 0; -+ map->elements--; -+ -+ return 0; -+} -+ -+UADT(ipporthash, del, req->port) -+KADT(ipporthash, del, ipaddr, port) -+ -+static inline int -+__ipporthash_create(const struct ip_set_req_ipporthash_create *req, -+ struct ip_set_ipporthash *map) -+{ -+ if (req->to - req->from > MAX_RANGE) { -+ ip_set_printk("range too big, %d elements (max %d)", -+ req->to - req->from + 1, MAX_RANGE+1); -+ return -ENOEXEC; -+ } -+ map->first_ip = req->from; -+ map->last_ip = req->to; -+ return 0; -+} -+ -+HASH_CREATE(ipporthash, ip_set_ip_t) -+HASH_DESTROY(ipporthash) -+HASH_FLUSH(ipporthash, ip_set_ip_t) -+ -+static inline void -+__ipporthash_list_header(const struct ip_set_ipporthash *map, -+ struct ip_set_req_ipporthash_create *header) -+{ -+ header->from = map->first_ip; -+ header->to = map->last_ip; -+} -+ -+HASH_LIST_HEADER(ipporthash) -+HASH_LIST_MEMBERS_SIZE(ipporthash, ip_set_ip_t) -+HASH_LIST_MEMBERS(ipporthash, ip_set_ip_t) -+ -+IP_SET_RTYPE(ipporthash, IPSET_TYPE_IP | IPSET_TYPE_PORT | IPSET_DATA_DOUBLE) -+ -+MODULE_LICENSE("GPL"); -+MODULE_AUTHOR("Jozsef Kadlecsik "); -+MODULE_DESCRIPTION("ipporthash type of IP sets"); -+module_param(limit, int, 0600); -+MODULE_PARM_DESC(limit, "maximal number of elements stored in the sets"); -+ -+REGISTER_MODULE(ipporthash) ---- /dev/null -+++ b/net/ipv4/netfilter/ip_set_ipportiphash.c -@@ -0,0 +1,216 @@ -+/* Copyright (C) 2008 Jozsef Kadlecsik -+ * -+ * 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. -+ */ -+ -+/* Kernel module implementing an ip+port+ip hash set */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+ -+#include -+#include -+ -+static int limit = MAX_RANGE; -+ -+#define jhash_ip2(map, i, ipport, ip1) \ -+ jhash_2words(ipport, ip1, *(map->initval + i)) -+ -+static inline __u32 -+ipportiphash_id(struct ip_set *set, ip_set_ip_t *hash_ip, -+ ip_set_ip_t ip, ip_set_ip_t port, ip_set_ip_t ip1) -+{ -+ struct ip_set_ipportiphash *map = set->data; -+ __u32 id; -+ u_int16_t i; -+ struct ipportip *elem; -+ -+ *hash_ip = pack_ip_port(map, ip, port); -+ DP("set: %s, ipport:%u.%u.%u.%u:%u, %u.%u.%u.%u", -+ set->name, HIPQUAD(ip), port, HIPQUAD(*hash_ip)); -+ if (!(*hash_ip || ip1)) -+ return UINT_MAX; -+ -+ for (i = 0; i < map->probes; i++) { -+ id = jhash_ip2(map, i, *hash_ip, ip1) % map->hashsize; -+ DP("hash key: %u", id); -+ elem = HARRAY_ELEM(map->members, struct ipportip *, id); -+ if (elem->ip == *hash_ip && elem->ip1 == ip1) -+ return id; -+ /* No shortcut - there can be deleted entries. */ -+ } -+ return UINT_MAX; -+} -+ -+static inline int -+ipportiphash_test(struct ip_set *set, ip_set_ip_t *hash_ip, -+ ip_set_ip_t ip, ip_set_ip_t port, ip_set_ip_t ip1) -+{ -+ struct ip_set_ipportiphash *map = set->data; -+ -+ if (ip < map->first_ip || ip > map->last_ip) -+ return -ERANGE; -+ -+ return (ipportiphash_id(set, hash_ip, ip, port, ip1) != UINT_MAX); -+} -+ -+#define KADT_CONDITION \ -+ ip_set_ip_t port, ip1; \ -+ \ -+ if (flags[index+2] == 0) \ -+ return 0; \ -+ \ -+ port = get_port(skb, flags[index+1]); \ -+ ip1 = ipaddr(skb, flags[index+2]); \ -+ \ -+ if (port == INVALID_PORT) \ -+ return 0; -+ -+UADT(ipportiphash, test, req->port, req->ip1) -+KADT(ipportiphash, test, ipaddr, port, ip1) -+ -+static inline int -+__ipportip_add(struct ip_set_ipportiphash *map, -+ ip_set_ip_t hash_ip, ip_set_ip_t ip1) -+{ -+ __u32 probe; -+ u_int16_t i; -+ struct ipportip *elem, *slot = NULL; -+ -+ for (i = 0; i < map->probes; i++) { -+ probe = jhash_ip2(map, i, hash_ip, ip1) % map->hashsize; -+ elem = HARRAY_ELEM(map->members, struct ipportip *, probe); -+ if (elem->ip == hash_ip && elem->ip1 == ip1) -+ return -EEXIST; -+ if (!(slot || elem->ip || elem->ip1)) -+ slot = elem; -+ /* There can be deleted entries, must check all slots */ -+ } -+ if (slot) { -+ slot->ip = hash_ip; -+ slot->ip1 = ip1; -+ map->elements++; -+ return 0; -+ } -+ /* Trigger rehashing */ -+ return -EAGAIN; -+} -+ -+static inline int -+__ipportiphash_add(struct ip_set_ipportiphash *map, -+ struct ipportip *elem) -+{ -+ return __ipportip_add(map, elem->ip, elem->ip1); -+} -+ -+static inline int -+ipportiphash_add(struct ip_set *set, ip_set_ip_t *hash_ip, -+ ip_set_ip_t ip, ip_set_ip_t port, ip_set_ip_t ip1) -+{ -+ struct ip_set_ipportiphash *map = set->data; -+ -+ if (map->elements > limit) -+ return -ERANGE; -+ if (ip < map->first_ip || ip > map->last_ip) -+ return -ERANGE; -+ -+ *hash_ip = pack_ip_port(map, ip, port); -+ if (!(*hash_ip || ip1)) -+ return -ERANGE; -+ -+ return __ipportip_add(map, *hash_ip, ip1); -+} -+ -+UADT(ipportiphash, add, req->port, req->ip1) -+KADT(ipportiphash, add, ipaddr, port, ip1) -+ -+static inline void -+__ipportiphash_retry(struct ip_set_ipportiphash *tmp, -+ struct ip_set_ipportiphash *map) -+{ -+ tmp->first_ip = map->first_ip; -+ tmp->last_ip = map->last_ip; -+} -+ -+HASH_RETRY2(ipportiphash, struct ipportip) -+ -+static inline int -+ipportiphash_del(struct ip_set *set, ip_set_ip_t *hash_ip, -+ ip_set_ip_t ip, ip_set_ip_t port, ip_set_ip_t ip1) -+{ -+ struct ip_set_ipportiphash *map = set->data; -+ ip_set_ip_t id; -+ struct ipportip *elem; -+ -+ if (ip < map->first_ip || ip > map->last_ip) -+ return -ERANGE; -+ -+ id = ipportiphash_id(set, hash_ip, ip, port, ip1); -+ -+ if (id == UINT_MAX) -+ return -EEXIST; -+ -+ elem = HARRAY_ELEM(map->members, struct ipportip *, id); -+ elem->ip = elem->ip1 = 0; -+ map->elements--; -+ -+ return 0; -+} -+ -+UADT(ipportiphash, del, req->port, req->ip1) -+KADT(ipportiphash, del, ipaddr, port, ip1) -+ -+static inline int -+__ipportiphash_create(const struct ip_set_req_ipportiphash_create *req, -+ struct ip_set_ipportiphash *map) -+{ -+ if (req->to - req->from > MAX_RANGE) { -+ ip_set_printk("range too big, %d elements (max %d)", -+ req->to - req->from + 1, MAX_RANGE+1); -+ return -ENOEXEC; -+ } -+ map->first_ip = req->from; -+ map->last_ip = req->to; -+ return 0; -+} -+ -+HASH_CREATE(ipportiphash, struct ipportip) -+HASH_DESTROY(ipportiphash) -+HASH_FLUSH(ipportiphash, struct ipportip) -+ -+static inline void -+__ipportiphash_list_header(const struct ip_set_ipportiphash *map, -+ struct ip_set_req_ipportiphash_create *header) -+{ -+ header->from = map->first_ip; -+ header->to = map->last_ip; -+} -+ -+HASH_LIST_HEADER(ipportiphash) -+HASH_LIST_MEMBERS_SIZE(ipportiphash, struct ipportip) -+HASH_LIST_MEMBERS_MEMCPY(ipportiphash, struct ipportip) -+ -+IP_SET_RTYPE(ipportiphash, IPSET_TYPE_IP | IPSET_TYPE_PORT -+ | IPSET_TYPE_IP1 | IPSET_DATA_TRIPLE) -+ -+MODULE_LICENSE("GPL"); -+MODULE_AUTHOR("Jozsef Kadlecsik "); -+MODULE_DESCRIPTION("ipportiphash type of IP sets"); -+module_param(limit, int, 0600); -+MODULE_PARM_DESC(limit, "maximal number of elements stored in the sets"); -+ -+REGISTER_MODULE(ipportiphash) ---- /dev/null -+++ b/net/ipv4/netfilter/ip_set_ipportnethash.c -@@ -0,0 +1,304 @@ -+/* Copyright (C) 2008 Jozsef Kadlecsik -+ * -+ * 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. -+ */ -+ -+/* Kernel module implementing an ip+port+net hash set */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+ -+#include -+#include -+ -+static int limit = MAX_RANGE; -+ -+#define jhash_ip2(map, i, ipport, ip1) \ -+ jhash_2words(ipport, ip1, *(map->initval + i)) -+ -+static inline __u32 -+ipportnethash_id_cidr(struct ip_set *set, ip_set_ip_t *hash_ip, -+ ip_set_ip_t ip, ip_set_ip_t port, -+ ip_set_ip_t ip1, uint8_t cidr) -+{ -+ struct ip_set_ipportnethash *map = set->data; -+ __u32 id; -+ u_int16_t i; -+ struct ipportip *elem; -+ -+ *hash_ip = pack_ip_port(map, ip, port); -+ DP("set: %s, ipport:%u.%u.%u.%u:%u, %u.%u.%u.%u", -+ set->name, HIPQUAD(ip), port, HIPQUAD(*hash_ip)); -+ ip1 = pack_ip_cidr(ip1, cidr); -+ if (!(*hash_ip || ip1)) -+ return UINT_MAX; -+ -+ for (i = 0; i < map->probes; i++) { -+ id = jhash_ip2(map, i, *hash_ip, ip1) % map->hashsize; -+ DP("hash key: %u", id); -+ elem = HARRAY_ELEM(map->members, struct ipportip *, id); -+ if (elem->ip == *hash_ip && elem->ip1 == ip1) -+ return id; -+ /* No shortcut - there can be deleted entries. */ -+ } -+ return UINT_MAX; -+} -+ -+static inline __u32 -+ipportnethash_id(struct ip_set *set, ip_set_ip_t *hash_ip, -+ ip_set_ip_t ip, ip_set_ip_t port, ip_set_ip_t ip1) -+{ -+ struct ip_set_ipportnethash *map = set->data; -+ __u32 id = UINT_MAX; -+ int i; -+ -+ for (i = 0; i < 30 && map->cidr[i]; i++) { -+ id = ipportnethash_id_cidr(set, hash_ip, ip, port, ip1, -+ map->cidr[i]); -+ if (id != UINT_MAX) -+ break; -+ } -+ return id; -+} -+ -+static inline int -+ipportnethash_test_cidr(struct ip_set *set, ip_set_ip_t *hash_ip, -+ ip_set_ip_t ip, ip_set_ip_t port, -+ ip_set_ip_t ip1, uint8_t cidr) -+{ -+ struct ip_set_ipportnethash *map = set->data; -+ -+ if (ip < map->first_ip || ip > map->last_ip) -+ return -ERANGE; -+ -+ return (ipportnethash_id_cidr(set, hash_ip, ip, port, ip1, -+ cidr) != UINT_MAX); -+} -+ -+static inline int -+ipportnethash_test(struct ip_set *set, ip_set_ip_t *hash_ip, -+ ip_set_ip_t ip, ip_set_ip_t port, ip_set_ip_t ip1) -+{ -+ struct ip_set_ipportnethash *map = set->data; -+ -+ if (ip < map->first_ip || ip > map->last_ip) -+ return -ERANGE; -+ -+ return (ipportnethash_id(set, hash_ip, ip, port, ip1) != UINT_MAX); -+} -+ -+static int -+ipportnethash_utest(struct ip_set *set, const void *data, u_int32_t size, -+ ip_set_ip_t *hash_ip) -+{ -+ const struct ip_set_req_ipportnethash *req = data; -+ -+ if (req->cidr <= 0 || req->cidr > 32) -+ return -EINVAL; -+ return (req->cidr == 32 -+ ? ipportnethash_test(set, hash_ip, req->ip, req->port, -+ req->ip1) -+ : ipportnethash_test_cidr(set, hash_ip, req->ip, req->port, -+ req->ip1, req->cidr)); -+} -+ -+#define KADT_CONDITION \ -+ ip_set_ip_t port, ip1; \ -+ \ -+ if (flags[index+2] == 0) \ -+ return 0; \ -+ \ -+ port = get_port(skb, flags[index+1]); \ -+ ip1 = ipaddr(skb, flags[index+2]); \ -+ \ -+ if (port == INVALID_PORT) \ -+ return 0; -+ -+KADT(ipportnethash, test, ipaddr, port, ip1) -+ -+static inline int -+__ipportnet_add(struct ip_set_ipportnethash *map, -+ ip_set_ip_t hash_ip, ip_set_ip_t ip1) -+{ -+ __u32 probe; -+ u_int16_t i; -+ struct ipportip *elem, *slot = NULL; -+ -+ for (i = 0; i < map->probes; i++) { -+ probe = jhash_ip2(map, i, hash_ip, ip1) % map->hashsize; -+ elem = HARRAY_ELEM(map->members, struct ipportip *, probe); -+ if (elem->ip == hash_ip && elem->ip1 == ip1) -+ return -EEXIST; -+ if (!(slot || elem->ip || elem->ip1)) -+ slot = elem; -+ /* There can be deleted entries, must check all slots */ -+ } -+ if (slot) { -+ slot->ip = hash_ip; -+ slot->ip1 = ip1; -+ map->elements++; -+ return 0; -+ } -+ /* Trigger rehashing */ -+ return -EAGAIN; -+} -+ -+static inline int -+__ipportnethash_add(struct ip_set_ipportnethash *map, -+ struct ipportip *elem) -+{ -+ return __ipportnet_add(map, elem->ip, elem->ip1); -+} -+ -+static inline int -+ipportnethash_add(struct ip_set *set, ip_set_ip_t *hash_ip, -+ ip_set_ip_t ip, ip_set_ip_t port, -+ ip_set_ip_t ip1, uint8_t cidr) -+{ -+ struct ip_set_ipportnethash *map = set->data; -+ struct ipportip; -+ int ret; -+ -+ if (map->elements > limit) -+ return -ERANGE; -+ if (ip < map->first_ip || ip > map->last_ip) -+ return -ERANGE; -+ if (cidr <= 0 || cidr >= 32) -+ return -EINVAL; -+ if (map->nets[cidr-1] == UINT16_MAX) -+ return -ERANGE; -+ -+ *hash_ip = pack_ip_port(map, ip, port); -+ ip1 = pack_ip_cidr(ip1, cidr); -+ if (!(*hash_ip || ip1)) -+ return -ERANGE; -+ -+ ret =__ipportnet_add(map, *hash_ip, ip1); -+ if (ret == 0) { -+ if (!map->nets[cidr-1]++) -+ add_cidr_size(map->cidr, cidr); -+ map->elements++; -+ } -+ return ret; -+} -+ -+#undef KADT_CONDITION -+#define KADT_CONDITION \ -+ struct ip_set_ipportnethash *map = set->data; \ -+ uint8_t cidr = map->cidr[0] ? map->cidr[0] : 31; \ -+ ip_set_ip_t port, ip1; \ -+ \ -+ if (flags[index+2] == 0) \ -+ return 0; \ -+ \ -+ port = get_port(skb, flags[index+1]); \ -+ ip1 = ipaddr(skb, flags[index+2]); \ -+ \ -+ if (port == INVALID_PORT) \ -+ return 0; -+ -+UADT(ipportnethash, add, req->port, req->ip1, req->cidr) -+KADT(ipportnethash, add, ipaddr, port, ip1, cidr) -+ -+static inline void -+__ipportnethash_retry(struct ip_set_ipportnethash *tmp, -+ struct ip_set_ipportnethash *map) -+{ -+ tmp->first_ip = map->first_ip; -+ tmp->last_ip = map->last_ip; -+ memcpy(tmp->cidr, map->cidr, sizeof(tmp->cidr)); -+ memcpy(tmp->nets, map->nets, sizeof(tmp->nets)); -+} -+ -+HASH_RETRY2(ipportnethash, struct ipportip) -+ -+static inline int -+ipportnethash_del(struct ip_set *set, ip_set_ip_t *hash_ip, -+ ip_set_ip_t ip, ip_set_ip_t port, -+ ip_set_ip_t ip1, uint8_t cidr) -+{ -+ struct ip_set_ipportnethash *map = set->data; -+ ip_set_ip_t id; -+ struct ipportip *elem; -+ -+ if (ip < map->first_ip || ip > map->last_ip) -+ return -ERANGE; -+ if (!ip) -+ return -ERANGE; -+ if (cidr <= 0 || cidr >= 32) -+ return -EINVAL; -+ -+ id = ipportnethash_id_cidr(set, hash_ip, ip, port, ip1, cidr); -+ -+ if (id == UINT_MAX) -+ return -EEXIST; -+ -+ elem = HARRAY_ELEM(map->members, struct ipportip *, id); -+ elem->ip = elem->ip1 = 0; -+ map->elements--; -+ if (!map->nets[cidr-1]--) -+ del_cidr_size(map->cidr, cidr); -+ -+ return 0; -+} -+ -+UADT(ipportnethash, del, req->port, req->ip1, req->cidr) -+KADT(ipportnethash, del, ipaddr, port, ip1, cidr) -+ -+static inline int -+__ipportnethash_create(const struct ip_set_req_ipportnethash_create *req, -+ struct ip_set_ipportnethash *map) -+{ -+ if (req->to - req->from > MAX_RANGE) { -+ ip_set_printk("range too big, %d elements (max %d)", -+ req->to - req->from + 1, MAX_RANGE+1); -+ return -ENOEXEC; -+ } -+ map->first_ip = req->from; -+ map->last_ip = req->to; -+ memset(map->cidr, 0, sizeof(map->cidr)); -+ memset(map->nets, 0, sizeof(map->nets)); -+ return 0; -+} -+ -+HASH_CREATE(ipportnethash, struct ipportip) -+HASH_DESTROY(ipportnethash) -+HASH_FLUSH_CIDR(ipportnethash, struct ipportip); -+ -+static inline void -+__ipportnethash_list_header(const struct ip_set_ipportnethash *map, -+ struct ip_set_req_ipportnethash_create *header) -+{ -+ header->from = map->first_ip; -+ header->to = map->last_ip; -+} -+ -+HASH_LIST_HEADER(ipportnethash) -+ -+HASH_LIST_MEMBERS_SIZE(ipportnethash, struct ipportip) -+HASH_LIST_MEMBERS_MEMCPY(ipportnethash, struct ipportip) -+ -+IP_SET_RTYPE(ipportnethash, IPSET_TYPE_IP | IPSET_TYPE_PORT -+ | IPSET_TYPE_IP1 | IPSET_DATA_TRIPLE) -+ -+MODULE_LICENSE("GPL"); -+MODULE_AUTHOR("Jozsef Kadlecsik "); -+MODULE_DESCRIPTION("ipportnethash type of IP sets"); -+module_param(limit, int, 0600); -+MODULE_PARM_DESC(limit, "maximal number of elements stored in the sets"); -+ -+REGISTER_MODULE(ipportnethash) ---- /dev/null -+++ b/net/ipv4/netfilter/ip_set_iptree.c -@@ -0,0 +1,466 @@ -+/* Copyright (C) 2005-2008 Jozsef Kadlecsik -+ * -+ * 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. -+ */ -+ -+/* Kernel module implementing an IP set type: the iptree type */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+ -+static int limit = MAX_RANGE; -+ -+/* Garbage collection interval in seconds: */ -+#define IPTREE_GC_TIME 5*60 -+/* Sleep so many milliseconds before trying again -+ * to delete the gc timer at destroying/flushing a set */ -+#define IPTREE_DESTROY_SLEEP 100 -+ -+static __KMEM_CACHE_T__ *branch_cachep; -+static __KMEM_CACHE_T__ *leaf_cachep; -+ -+ -+#if defined(__LITTLE_ENDIAN) -+#define ABCD(a,b,c,d,addrp) do { \ -+ a = ((unsigned char *)addrp)[3]; \ -+ b = ((unsigned char *)addrp)[2]; \ -+ c = ((unsigned char *)addrp)[1]; \ -+ d = ((unsigned char *)addrp)[0]; \ -+} while (0) -+#elif defined(__BIG_ENDIAN) -+#define ABCD(a,b,c,d,addrp) do { \ -+ a = ((unsigned char *)addrp)[0]; \ -+ b = ((unsigned char *)addrp)[1]; \ -+ c = ((unsigned char *)addrp)[2]; \ -+ d = ((unsigned char *)addrp)[3]; \ -+} while (0) -+#else -+#error "Please fix asm/byteorder.h" -+#endif /* __LITTLE_ENDIAN */ -+ -+#define TESTIP_WALK(map, elem, branch) do { \ -+ if ((map)->tree[elem]) { \ -+ branch = (map)->tree[elem]; \ -+ } else \ -+ return 0; \ -+} while (0) -+ -+static inline int -+iptree_test(struct ip_set *set, ip_set_ip_t *hash_ip, ip_set_ip_t ip) -+{ -+ struct ip_set_iptree *map = set->data; -+ struct ip_set_iptreeb *btree; -+ struct ip_set_iptreec *ctree; -+ struct ip_set_iptreed *dtree; -+ unsigned char a,b,c,d; -+ -+ if (!ip) -+ return -ERANGE; -+ -+ *hash_ip = ip; -+ ABCD(a, b, c, d, hash_ip); -+ DP("%u %u %u %u timeout %u", a, b, c, d, map->timeout); -+ TESTIP_WALK(map, a, btree); -+ TESTIP_WALK(btree, b, ctree); -+ TESTIP_WALK(ctree, c, dtree); -+ DP("%lu %lu", dtree->expires[d], jiffies); -+ return dtree->expires[d] -+ && (!map->timeout -+ || time_after(dtree->expires[d], jiffies)); -+} -+ -+#define KADT_CONDITION -+ -+UADT(iptree, test) -+KADT(iptree, test, ipaddr) -+ -+#define ADDIP_WALK(map, elem, branch, type, cachep) do { \ -+ if ((map)->tree[elem]) { \ -+ DP("found %u", elem); \ -+ branch = (map)->tree[elem]; \ -+ } else { \ -+ branch = (type *) \ -+ kmem_cache_alloc(cachep, GFP_ATOMIC); \ -+ if (branch == NULL) \ -+ return -ENOMEM; \ -+ memset(branch, 0, sizeof(*branch)); \ -+ (map)->tree[elem] = branch; \ -+ DP("alloc %u", elem); \ -+ } \ -+} while (0) -+ -+static inline int -+iptree_add(struct ip_set *set, ip_set_ip_t *hash_ip, -+ ip_set_ip_t ip, unsigned int timeout) -+{ -+ struct ip_set_iptree *map = set->data; -+ struct ip_set_iptreeb *btree; -+ struct ip_set_iptreec *ctree; -+ struct ip_set_iptreed *dtree; -+ unsigned char a,b,c,d; -+ int ret = 0; -+ -+ if (!ip || map->elements >= limit) -+ /* We could call the garbage collector -+ * but it's probably overkill */ -+ return -ERANGE; -+ -+ *hash_ip = ip; -+ ABCD(a, b, c, d, hash_ip); -+ DP("%u %u %u %u timeout %u", a, b, c, d, timeout); -+ ADDIP_WALK(map, a, btree, struct ip_set_iptreeb, branch_cachep); -+ ADDIP_WALK(btree, b, ctree, struct ip_set_iptreec, branch_cachep); -+ ADDIP_WALK(ctree, c, dtree, struct ip_set_iptreed, leaf_cachep); -+ if (dtree->expires[d] -+ && (!map->timeout || time_after(dtree->expires[d], jiffies))) -+ ret = -EEXIST; -+ if (map->timeout && timeout == 0) -+ timeout = map->timeout; -+ dtree->expires[d] = map->timeout ? (timeout * HZ + jiffies) : 1; -+ /* Lottery: I won! */ -+ if (dtree->expires[d] == 0) -+ dtree->expires[d] = 1; -+ DP("%u %lu", d, dtree->expires[d]); -+ if (ret == 0) -+ map->elements++; -+ return ret; -+} -+ -+UADT(iptree, add, req->timeout) -+KADT(iptree, add, ipaddr, 0) -+ -+#define DELIP_WALK(map, elem, branch) do { \ -+ if ((map)->tree[elem]) { \ -+ branch = (map)->tree[elem]; \ -+ } else \ -+ return -EEXIST; \ -+} while (0) -+ -+static inline int -+iptree_del(struct ip_set *set, ip_set_ip_t *hash_ip, ip_set_ip_t ip) -+{ -+ struct ip_set_iptree *map = set->data; -+ struct ip_set_iptreeb *btree; -+ struct ip_set_iptreec *ctree; -+ struct ip_set_iptreed *dtree; -+ unsigned char a,b,c,d; -+ -+ if (!ip) -+ return -ERANGE; -+ -+ *hash_ip = ip; -+ ABCD(a, b, c, d, hash_ip); -+ DELIP_WALK(map, a, btree); -+ DELIP_WALK(btree, b, ctree); -+ DELIP_WALK(ctree, c, dtree); -+ -+ if (dtree->expires[d]) { -+ dtree->expires[d] = 0; -+ map->elements--; -+ return 0; -+ } -+ return -EEXIST; -+} -+ -+UADT(iptree, del) -+KADT(iptree, del, ipaddr) -+ -+#define LOOP_WALK_BEGIN(map, i, branch) \ -+ for (i = 0; i < 256; i++) { \ -+ if (!(map)->tree[i]) \ -+ continue; \ -+ branch = (map)->tree[i] -+ -+#define LOOP_WALK_END } -+ -+static void -+ip_tree_gc(unsigned long ul_set) -+{ -+ struct ip_set *set = (struct ip_set *) ul_set; -+ struct ip_set_iptree *map = set->data; -+ struct ip_set_iptreeb *btree; -+ struct ip_set_iptreec *ctree; -+ struct ip_set_iptreed *dtree; -+ unsigned int a,b,c,d; -+ unsigned char i,j,k; -+ -+ i = j = k = 0; -+ DP("gc: %s", set->name); -+ write_lock_bh(&set->lock); -+ LOOP_WALK_BEGIN(map, a, btree); -+ LOOP_WALK_BEGIN(btree, b, ctree); -+ LOOP_WALK_BEGIN(ctree, c, dtree); -+ for (d = 0; d < 256; d++) { -+ if (dtree->expires[d]) { -+ DP("gc: %u %u %u %u: expires %lu jiffies %lu", -+ a, b, c, d, -+ dtree->expires[d], jiffies); -+ if (map->timeout -+ && time_before(dtree->expires[d], jiffies)) { -+ dtree->expires[d] = 0; -+ map->elements--; -+ } else -+ k = 1; -+ } -+ } -+ if (k == 0) { -+ DP("gc: %s: leaf %u %u %u empty", -+ set->name, a, b, c); -+ kmem_cache_free(leaf_cachep, dtree); -+ ctree->tree[c] = NULL; -+ } else { -+ DP("gc: %s: leaf %u %u %u not empty", -+ set->name, a, b, c); -+ j = 1; -+ k = 0; -+ } -+ LOOP_WALK_END; -+ if (j == 0) { -+ DP("gc: %s: branch %u %u empty", -+ set->name, a, b); -+ kmem_cache_free(branch_cachep, ctree); -+ btree->tree[b] = NULL; -+ } else { -+ DP("gc: %s: branch %u %u not empty", -+ set->name, a, b); -+ i = 1; -+ j = k = 0; -+ } -+ LOOP_WALK_END; -+ if (i == 0) { -+ DP("gc: %s: branch %u empty", -+ set->name, a); -+ kmem_cache_free(branch_cachep, btree); -+ map->tree[a] = NULL; -+ } else { -+ DP("gc: %s: branch %u not empty", -+ set->name, a); -+ i = j = k = 0; -+ } -+ LOOP_WALK_END; -+ write_unlock_bh(&set->lock); -+ -+ map->gc.expires = jiffies + map->gc_interval * HZ; -+ add_timer(&map->gc); -+} -+ -+static inline void -+init_gc_timer(struct ip_set *set) -+{ -+ struct ip_set_iptree *map = set->data; -+ -+ /* Even if there is no timeout for the entries, -+ * we still have to call gc because delete -+ * do not clean up empty branches */ -+ map->gc_interval = IPTREE_GC_TIME; -+ init_timer(&map->gc); -+ map->gc.data = (unsigned long) set; -+ map->gc.function = ip_tree_gc; -+ map->gc.expires = jiffies + map->gc_interval * HZ; -+ add_timer(&map->gc); -+} -+ -+static int -+iptree_create(struct ip_set *set, const void *data, u_int32_t size) -+{ -+ const struct ip_set_req_iptree_create *req = data; -+ struct ip_set_iptree *map; -+ -+ if (size != sizeof(struct ip_set_req_iptree_create)) { -+ ip_set_printk("data length wrong (want %zu, have %lu)", -+ sizeof(struct ip_set_req_iptree_create), -+ (unsigned long)size); -+ return -EINVAL; -+ } -+ -+ map = kmalloc(sizeof(struct ip_set_iptree), GFP_KERNEL); -+ if (!map) { -+ DP("out of memory for %zu bytes", -+ sizeof(struct ip_set_iptree)); -+ return -ENOMEM; -+ } -+ memset(map, 0, sizeof(*map)); -+ map->timeout = req->timeout; -+ map->elements = 0; -+ set->data = map; -+ -+ init_gc_timer(set); -+ -+ return 0; -+} -+ -+static inline void -+__flush(struct ip_set_iptree *map) -+{ -+ struct ip_set_iptreeb *btree; -+ struct ip_set_iptreec *ctree; -+ struct ip_set_iptreed *dtree; -+ unsigned int a,b,c; -+ -+ LOOP_WALK_BEGIN(map, a, btree); -+ LOOP_WALK_BEGIN(btree, b, ctree); -+ LOOP_WALK_BEGIN(ctree, c, dtree); -+ kmem_cache_free(leaf_cachep, dtree); -+ LOOP_WALK_END; -+ kmem_cache_free(branch_cachep, ctree); -+ LOOP_WALK_END; -+ kmem_cache_free(branch_cachep, btree); -+ LOOP_WALK_END; -+ map->elements = 0; -+} -+ -+static void -+iptree_destroy(struct ip_set *set) -+{ -+ struct ip_set_iptree *map = set->data; -+ -+ /* gc might be running */ -+ while (!del_timer(&map->gc)) -+ msleep(IPTREE_DESTROY_SLEEP); -+ __flush(map); -+ kfree(map); -+ set->data = NULL; -+} -+ -+static void -+iptree_flush(struct ip_set *set) -+{ -+ struct ip_set_iptree *map = set->data; -+ unsigned int timeout = map->timeout; -+ -+ /* gc might be running */ -+ while (!del_timer(&map->gc)) -+ msleep(IPTREE_DESTROY_SLEEP); -+ __flush(map); -+ memset(map, 0, sizeof(*map)); -+ map->timeout = timeout; -+ -+ init_gc_timer(set); -+} -+ -+static void -+iptree_list_header(const struct ip_set *set, void *data) -+{ -+ const struct ip_set_iptree *map = set->data; -+ struct ip_set_req_iptree_create *header = data; -+ -+ header->timeout = map->timeout; -+} -+ -+static int -+iptree_list_members_size(const struct ip_set *set) -+{ -+ const struct ip_set_iptree *map = set->data; -+ struct ip_set_iptreeb *btree; -+ struct ip_set_iptreec *ctree; -+ struct ip_set_iptreed *dtree; -+ unsigned int a,b,c,d; -+ unsigned int count = 0; -+ -+ LOOP_WALK_BEGIN(map, a, btree); -+ LOOP_WALK_BEGIN(btree, b, ctree); -+ LOOP_WALK_BEGIN(ctree, c, dtree); -+ for (d = 0; d < 256; d++) { -+ if (dtree->expires[d] -+ && (!map->timeout || time_after(dtree->expires[d], jiffies))) -+ count++; -+ } -+ LOOP_WALK_END; -+ LOOP_WALK_END; -+ LOOP_WALK_END; -+ -+ DP("members %u", count); -+ return (count * sizeof(struct ip_set_req_iptree)); -+} -+ -+static void -+iptree_list_members(const struct ip_set *set, void *data) -+{ -+ const struct ip_set_iptree *map = set->data; -+ struct ip_set_iptreeb *btree; -+ struct ip_set_iptreec *ctree; -+ struct ip_set_iptreed *dtree; -+ unsigned int a,b,c,d; -+ size_t offset = 0; -+ struct ip_set_req_iptree *entry; -+ -+ LOOP_WALK_BEGIN(map, a, btree); -+ LOOP_WALK_BEGIN(btree, b, ctree); -+ LOOP_WALK_BEGIN(ctree, c, dtree); -+ for (d = 0; d < 256; d++) { -+ if (dtree->expires[d] -+ && (!map->timeout || time_after(dtree->expires[d], jiffies))) { -+ entry = data + offset; -+ entry->ip = ((a << 24) | (b << 16) | (c << 8) | d); -+ entry->timeout = !map->timeout ? 0 -+ : (dtree->expires[d] - jiffies)/HZ; -+ offset += sizeof(struct ip_set_req_iptree); -+ } -+ } -+ LOOP_WALK_END; -+ LOOP_WALK_END; -+ LOOP_WALK_END; -+} -+ -+IP_SET_TYPE(iptree, IPSET_TYPE_IP | IPSET_DATA_SINGLE) -+ -+MODULE_LICENSE("GPL"); -+MODULE_AUTHOR("Jozsef Kadlecsik "); -+MODULE_DESCRIPTION("iptree type of IP sets"); -+module_param(limit, int, 0600); -+MODULE_PARM_DESC(limit, "maximal number of elements stored in the sets"); -+ -+static int __init ip_set_iptree_init(void) -+{ -+ int ret; -+ -+ branch_cachep = KMEM_CACHE_CREATE("ip_set_iptreeb", -+ sizeof(struct ip_set_iptreeb)); -+ if (!branch_cachep) { -+ printk(KERN_ERR "Unable to create ip_set_iptreeb slab cache\n"); -+ ret = -ENOMEM; -+ goto out; -+ } -+ leaf_cachep = KMEM_CACHE_CREATE("ip_set_iptreed", -+ sizeof(struct ip_set_iptreed)); -+ if (!leaf_cachep) { -+ printk(KERN_ERR "Unable to create ip_set_iptreed slab cache\n"); -+ ret = -ENOMEM; -+ goto free_branch; -+ } -+ ret = ip_set_register_set_type(&ip_set_iptree); -+ if (ret == 0) -+ goto out; -+ -+ kmem_cache_destroy(leaf_cachep); -+ free_branch: -+ kmem_cache_destroy(branch_cachep); -+ out: -+ return ret; -+} -+ -+static void __exit ip_set_iptree_fini(void) -+{ -+ /* FIXME: possible race with ip_set_create() */ -+ ip_set_unregister_set_type(&ip_set_iptree); -+ kmem_cache_destroy(leaf_cachep); -+ kmem_cache_destroy(branch_cachep); -+} -+ -+module_init(ip_set_iptree_init); -+module_exit(ip_set_iptree_fini); ---- /dev/null -+++ b/net/ipv4/netfilter/ip_set_iptreemap.c -@@ -0,0 +1,708 @@ -+/* Copyright (C) 2007 Sven Wegener -+ * -+ * 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. -+ */ -+ -+/* This modules implements the iptreemap ipset type. It uses bitmaps to -+ * represent every single IPv4 address as a bit. The bitmaps are managed in a -+ * tree structure, where the first three octets of an address are used as an -+ * index to find the bitmap and the last octet is used as the bit number. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+ -+#define IPTREEMAP_DEFAULT_GC_TIME (5 * 60) -+#define IPTREEMAP_DESTROY_SLEEP (100) -+ -+static __KMEM_CACHE_T__ *cachep_b; -+static __KMEM_CACHE_T__ *cachep_c; -+static __KMEM_CACHE_T__ *cachep_d; -+ -+static struct ip_set_iptreemap_d *fullbitmap_d; -+static struct ip_set_iptreemap_c *fullbitmap_c; -+static struct ip_set_iptreemap_b *fullbitmap_b; -+ -+#if defined(__LITTLE_ENDIAN) -+#define ABCD(a, b, c, d, addr) \ -+ do { \ -+ a = ((unsigned char *)addr)[3]; \ -+ b = ((unsigned char *)addr)[2]; \ -+ c = ((unsigned char *)addr)[1]; \ -+ d = ((unsigned char *)addr)[0]; \ -+ } while (0) -+#elif defined(__BIG_ENDIAN) -+#define ABCD(a,b,c,d,addrp) do { \ -+ a = ((unsigned char *)addrp)[0]; \ -+ b = ((unsigned char *)addrp)[1]; \ -+ c = ((unsigned char *)addrp)[2]; \ -+ d = ((unsigned char *)addrp)[3]; \ -+} while (0) -+#else -+#error "Please fix asm/byteorder.h" -+#endif /* __LITTLE_ENDIAN */ -+ -+#define TESTIP_WALK(map, elem, branch, full) \ -+ do { \ -+ branch = (map)->tree[elem]; \ -+ if (!branch) \ -+ return 0; \ -+ else if (branch == full) \ -+ return 1; \ -+ } while (0) -+ -+#define ADDIP_WALK(map, elem, branch, type, cachep, full) \ -+ do { \ -+ branch = (map)->tree[elem]; \ -+ if (!branch) { \ -+ branch = (type *) kmem_cache_alloc(cachep, GFP_ATOMIC); \ -+ if (!branch) \ -+ return -ENOMEM; \ -+ memset(branch, 0, sizeof(*branch)); \ -+ (map)->tree[elem] = branch; \ -+ } else if (branch == full) { \ -+ return -EEXIST; \ -+ } \ -+ } while (0) -+ -+#define ADDIP_RANGE_LOOP(map, a, a1, a2, hint, branch, full, cachep, free) \ -+ for (a = a1; a <= a2; a++) { \ -+ branch = (map)->tree[a]; \ -+ if (branch != full) { \ -+ if ((a > a1 && a < a2) || (hint)) { \ -+ if (branch) \ -+ free(branch); \ -+ (map)->tree[a] = full; \ -+ continue; \ -+ } else if (!branch) { \ -+ branch = kmem_cache_alloc(cachep, GFP_ATOMIC); \ -+ if (!branch) \ -+ return -ENOMEM; \ -+ memset(branch, 0, sizeof(*branch)); \ -+ (map)->tree[a] = branch; \ -+ } -+ -+#define ADDIP_RANGE_LOOP_END() \ -+ } \ -+ } -+ -+#define DELIP_WALK(map, elem, branch, cachep, full, flags) \ -+ do { \ -+ branch = (map)->tree[elem]; \ -+ if (!branch) { \ -+ return -EEXIST; \ -+ } else if (branch == full) { \ -+ branch = kmem_cache_alloc(cachep, flags); \ -+ if (!branch) \ -+ return -ENOMEM; \ -+ memcpy(branch, full, sizeof(*full)); \ -+ (map)->tree[elem] = branch; \ -+ } \ -+ } while (0) -+ -+#define DELIP_RANGE_LOOP(map, a, a1, a2, hint, branch, full, cachep, free, flags) \ -+ for (a = a1; a <= a2; a++) { \ -+ branch = (map)->tree[a]; \ -+ if (branch) { \ -+ if ((a > a1 && a < a2) || (hint)) { \ -+ if (branch != full) \ -+ free(branch); \ -+ (map)->tree[a] = NULL; \ -+ continue; \ -+ } else if (branch == full) { \ -+ branch = kmem_cache_alloc(cachep, flags); \ -+ if (!branch) \ -+ return -ENOMEM; \ -+ memcpy(branch, full, sizeof(*branch)); \ -+ (map)->tree[a] = branch; \ -+ } -+ -+#define DELIP_RANGE_LOOP_END() \ -+ } \ -+ } -+ -+#define LOOP_WALK_BEGIN(map, i, branch) \ -+ for (i = 0; i < 256; i++) { \ -+ branch = (map)->tree[i]; \ -+ if (likely(!branch)) \ -+ continue; -+ -+#define LOOP_WALK_END() \ -+ } -+ -+#define LOOP_WALK_BEGIN_GC(map, i, branch, full, cachep, count) \ -+ count = -256; \ -+ for (i = 0; i < 256; i++) { \ -+ branch = (map)->tree[i]; \ -+ if (likely(!branch)) \ -+ continue; \ -+ count++; \ -+ if (branch == full) { \ -+ count++; \ -+ continue; \ -+ } -+ -+#define LOOP_WALK_END_GC(map, i, branch, full, cachep, count) \ -+ if (-256 == count) { \ -+ kmem_cache_free(cachep, branch); \ -+ (map)->tree[i] = NULL; \ -+ } else if (256 == count) { \ -+ kmem_cache_free(cachep, branch); \ -+ (map)->tree[i] = full; \ -+ } \ -+ } -+ -+#define LOOP_WALK_BEGIN_COUNT(map, i, branch, inrange, count) \ -+ for (i = 0; i < 256; i++) { \ -+ if (!(map)->tree[i]) { \ -+ if (inrange) { \ -+ count++; \ -+ inrange = 0; \ -+ } \ -+ continue; \ -+ } \ -+ branch = (map)->tree[i]; -+ -+#define LOOP_WALK_END_COUNT() \ -+ } -+ -+#define GETVALUE1(a, a1, b1, r) \ -+ (a == a1 ? b1 : r) -+ -+#define GETVALUE2(a, b, a1, b1, c1, r) \ -+ (a == a1 && b == b1 ? c1 : r) -+ -+#define GETVALUE3(a, b, c, a1, b1, c1, d1, r) \ -+ (a == a1 && b == b1 && c == c1 ? d1 : r) -+ -+#define CHECK1(a, a1, a2, b1, b2, c1, c2, d1, d2) \ -+ ( \ -+ GETVALUE1(a, a1, b1, 0) == 0 \ -+ && GETVALUE1(a, a2, b2, 255) == 255 \ -+ && c1 == 0 \ -+ && c2 == 255 \ -+ && d1 == 0 \ -+ && d2 == 255 \ -+ ) -+ -+#define CHECK2(a, b, a1, a2, b1, b2, c1, c2, d1, d2) \ -+ ( \ -+ GETVALUE2(a, b, a1, b1, c1, 0) == 0 \ -+ && GETVALUE2(a, b, a2, b2, c2, 255) == 255 \ -+ && d1 == 0 \ -+ && d2 == 255 \ -+ ) -+ -+#define CHECK3(a, b, c, a1, a2, b1, b2, c1, c2, d1, d2) \ -+ ( \ -+ GETVALUE3(a, b, c, a1, b1, c1, d1, 0) == 0 \ -+ && GETVALUE3(a, b, c, a2, b2, c2, d2, 255) == 255 \ -+ ) -+ -+ -+static inline void -+free_d(struct ip_set_iptreemap_d *map) -+{ -+ kmem_cache_free(cachep_d, map); -+} -+ -+static inline void -+free_c(struct ip_set_iptreemap_c *map) -+{ -+ struct ip_set_iptreemap_d *dtree; -+ unsigned int i; -+ -+ LOOP_WALK_BEGIN(map, i, dtree) { -+ if (dtree != fullbitmap_d) -+ free_d(dtree); -+ } LOOP_WALK_END(); -+ -+ kmem_cache_free(cachep_c, map); -+} -+ -+static inline void -+free_b(struct ip_set_iptreemap_b *map) -+{ -+ struct ip_set_iptreemap_c *ctree; -+ unsigned int i; -+ -+ LOOP_WALK_BEGIN(map, i, ctree) { -+ if (ctree != fullbitmap_c) -+ free_c(ctree); -+ } LOOP_WALK_END(); -+ -+ kmem_cache_free(cachep_b, map); -+} -+ -+static inline int -+iptreemap_test(struct ip_set *set, ip_set_ip_t *hash_ip, ip_set_ip_t ip) -+{ -+ struct ip_set_iptreemap *map = set->data; -+ struct ip_set_iptreemap_b *btree; -+ struct ip_set_iptreemap_c *ctree; -+ struct ip_set_iptreemap_d *dtree; -+ unsigned char a, b, c, d; -+ -+ *hash_ip = ip; -+ -+ ABCD(a, b, c, d, hash_ip); -+ -+ TESTIP_WALK(map, a, btree, fullbitmap_b); -+ TESTIP_WALK(btree, b, ctree, fullbitmap_c); -+ TESTIP_WALK(ctree, c, dtree, fullbitmap_d); -+ -+ return !!test_bit(d, (void *) dtree->bitmap); -+} -+ -+#define KADT_CONDITION -+ -+UADT(iptreemap, test) -+KADT(iptreemap, test, ipaddr) -+ -+static inline int -+__addip_single(struct ip_set *set, ip_set_ip_t *hash_ip, ip_set_ip_t ip) -+{ -+ struct ip_set_iptreemap *map = (struct ip_set_iptreemap *) set->data; -+ struct ip_set_iptreemap_b *btree; -+ struct ip_set_iptreemap_c *ctree; -+ struct ip_set_iptreemap_d *dtree; -+ unsigned char a, b, c, d; -+ -+ *hash_ip = ip; -+ -+ ABCD(a, b, c, d, hash_ip); -+ -+ ADDIP_WALK(map, a, btree, struct ip_set_iptreemap_b, cachep_b, fullbitmap_b); -+ ADDIP_WALK(btree, b, ctree, struct ip_set_iptreemap_c, cachep_c, fullbitmap_c); -+ ADDIP_WALK(ctree, c, dtree, struct ip_set_iptreemap_d, cachep_d, fullbitmap_d); -+ -+ if (__test_and_set_bit(d, (void *) dtree->bitmap)) -+ return -EEXIST; -+ -+ __set_bit(b, (void *) btree->dirty); -+ -+ return 0; -+} -+ -+static inline int -+iptreemap_add(struct ip_set *set, ip_set_ip_t *hash_ip, -+ ip_set_ip_t start, ip_set_ip_t end) -+{ -+ struct ip_set_iptreemap *map = set->data; -+ struct ip_set_iptreemap_b *btree; -+ struct ip_set_iptreemap_c *ctree; -+ struct ip_set_iptreemap_d *dtree; -+ unsigned int a, b, c, d; -+ unsigned char a1, b1, c1, d1; -+ unsigned char a2, b2, c2, d2; -+ -+ if (start == end) -+ return __addip_single(set, hash_ip, start); -+ -+ *hash_ip = start; -+ -+ ABCD(a1, b1, c1, d1, &start); -+ ABCD(a2, b2, c2, d2, &end); -+ -+ /* This is sooo ugly... */ -+ ADDIP_RANGE_LOOP(map, a, a1, a2, CHECK1(a, a1, a2, b1, b2, c1, c2, d1, d2), btree, fullbitmap_b, cachep_b, free_b) { -+ ADDIP_RANGE_LOOP(btree, b, GETVALUE1(a, a1, b1, 0), GETVALUE1(a, a2, b2, 255), CHECK2(a, b, a1, a2, b1, b2, c1, c2, d1, d2), ctree, fullbitmap_c, cachep_c, free_c) { -+ ADDIP_RANGE_LOOP(ctree, c, GETVALUE2(a, b, a1, b1, c1, 0), GETVALUE2(a, b, a2, b2, c2, 255), CHECK3(a, b, c, a1, a2, b1, b2, c1, c2, d1, d2), dtree, fullbitmap_d, cachep_d, free_d) { -+ for (d = GETVALUE3(a, b, c, a1, b1, c1, d1, 0); d <= GETVALUE3(a, b, c, a2, b2, c2, d2, 255); d++) -+ __set_bit(d, (void *) dtree->bitmap); -+ __set_bit(b, (void *) btree->dirty); -+ } ADDIP_RANGE_LOOP_END(); -+ } ADDIP_RANGE_LOOP_END(); -+ } ADDIP_RANGE_LOOP_END(); -+ -+ return 0; -+} -+ -+UADT0(iptreemap, add, min(req->ip, req->end), max(req->ip, req->end)) -+KADT(iptreemap, add, ipaddr, ip) -+ -+static inline int -+__delip_single(struct ip_set *set, ip_set_ip_t *hash_ip, -+ ip_set_ip_t ip, gfp_t flags) -+{ -+ struct ip_set_iptreemap *map = set->data; -+ struct ip_set_iptreemap_b *btree; -+ struct ip_set_iptreemap_c *ctree; -+ struct ip_set_iptreemap_d *dtree; -+ unsigned char a,b,c,d; -+ -+ *hash_ip = ip; -+ -+ ABCD(a, b, c, d, hash_ip); -+ -+ DELIP_WALK(map, a, btree, cachep_b, fullbitmap_b, flags); -+ DELIP_WALK(btree, b, ctree, cachep_c, fullbitmap_c, flags); -+ DELIP_WALK(ctree, c, dtree, cachep_d, fullbitmap_d, flags); -+ -+ if (!__test_and_clear_bit(d, (void *) dtree->bitmap)) -+ return -EEXIST; -+ -+ __set_bit(b, (void *) btree->dirty); -+ -+ return 0; -+} -+ -+static inline int -+iptreemap_del(struct ip_set *set, ip_set_ip_t *hash_ip, -+ ip_set_ip_t start, ip_set_ip_t end, gfp_t flags) -+{ -+ struct ip_set_iptreemap *map = set->data; -+ struct ip_set_iptreemap_b *btree; -+ struct ip_set_iptreemap_c *ctree; -+ struct ip_set_iptreemap_d *dtree; -+ unsigned int a, b, c, d; -+ unsigned char a1, b1, c1, d1; -+ unsigned char a2, b2, c2, d2; -+ -+ if (start == end) -+ return __delip_single(set, hash_ip, start, flags); -+ -+ *hash_ip = start; -+ -+ ABCD(a1, b1, c1, d1, &start); -+ ABCD(a2, b2, c2, d2, &end); -+ -+ /* This is sooo ugly... */ -+ DELIP_RANGE_LOOP(map, a, a1, a2, CHECK1(a, a1, a2, b1, b2, c1, c2, d1, d2), btree, fullbitmap_b, cachep_b, free_b, flags) { -+ DELIP_RANGE_LOOP(btree, b, GETVALUE1(a, a1, b1, 0), GETVALUE1(a, a2, b2, 255), CHECK2(a, b, a1, a2, b1, b2, c1, c2, d1, d2), ctree, fullbitmap_c, cachep_c, free_c, flags) { -+ DELIP_RANGE_LOOP(ctree, c, GETVALUE2(a, b, a1, b1, c1, 0), GETVALUE2(a, b, a2, b2, c2, 255), CHECK3(a, b, c, a1, a2, b1, b2, c1, c2, d1, d2), dtree, fullbitmap_d, cachep_d, free_d, flags) { -+ for (d = GETVALUE3(a, b, c, a1, b1, c1, d1, 0); d <= GETVALUE3(a, b, c, a2, b2, c2, d2, 255); d++) -+ __clear_bit(d, (void *) dtree->bitmap); -+ __set_bit(b, (void *) btree->dirty); -+ } DELIP_RANGE_LOOP_END(); -+ } DELIP_RANGE_LOOP_END(); -+ } DELIP_RANGE_LOOP_END(); -+ -+ return 0; -+} -+ -+UADT0(iptreemap, del, min(req->ip, req->end), max(req->ip, req->end), GFP_KERNEL) -+KADT(iptreemap, del, ipaddr, ip, GFP_ATOMIC) -+ -+/* Check the status of the bitmap -+ * -1 == all bits cleared -+ * 1 == all bits set -+ * 0 == anything else -+ */ -+static inline int -+bitmap_status(struct ip_set_iptreemap_d *dtree) -+{ -+ unsigned char first = dtree->bitmap[0]; -+ int a; -+ -+ for (a = 1; a < 32; a++) -+ if (dtree->bitmap[a] != first) -+ return 0; -+ -+ return (first == 0 ? -1 : (first == 255 ? 1 : 0)); -+} -+ -+static void -+gc(unsigned long addr) -+{ -+ struct ip_set *set = (struct ip_set *) addr; -+ struct ip_set_iptreemap *map = set->data; -+ struct ip_set_iptreemap_b *btree; -+ struct ip_set_iptreemap_c *ctree; -+ struct ip_set_iptreemap_d *dtree; -+ unsigned int a, b, c; -+ int i, j, k; -+ -+ write_lock_bh(&set->lock); -+ -+ LOOP_WALK_BEGIN_GC(map, a, btree, fullbitmap_b, cachep_b, i) { -+ LOOP_WALK_BEGIN_GC(btree, b, ctree, fullbitmap_c, cachep_c, j) { -+ if (!__test_and_clear_bit(b, (void *) btree->dirty)) -+ continue; -+ LOOP_WALK_BEGIN_GC(ctree, c, dtree, fullbitmap_d, cachep_d, k) { -+ switch (bitmap_status(dtree)) { -+ case -1: -+ kmem_cache_free(cachep_d, dtree); -+ ctree->tree[c] = NULL; -+ k--; -+ break; -+ case 1: -+ kmem_cache_free(cachep_d, dtree); -+ ctree->tree[c] = fullbitmap_d; -+ k++; -+ break; -+ } -+ } LOOP_WALK_END(); -+ } LOOP_WALK_END_GC(btree, b, ctree, fullbitmap_c, cachep_c, k); -+ } LOOP_WALK_END_GC(map, a, btree, fullbitmap_b, cachep_b, j); -+ -+ write_unlock_bh(&set->lock); -+ -+ map->gc.expires = jiffies + map->gc_interval * HZ; -+ add_timer(&map->gc); -+} -+ -+static inline void -+init_gc_timer(struct ip_set *set) -+{ -+ struct ip_set_iptreemap *map = set->data; -+ -+ init_timer(&map->gc); -+ map->gc.data = (unsigned long) set; -+ map->gc.function = gc; -+ map->gc.expires = jiffies + map->gc_interval * HZ; -+ add_timer(&map->gc); -+} -+ -+static int -+iptreemap_create(struct ip_set *set, const void *data, u_int32_t size) -+{ -+ const struct ip_set_req_iptreemap_create *req = data; -+ struct ip_set_iptreemap *map; -+ -+ map = kzalloc(sizeof(*map), GFP_KERNEL); -+ if (!map) -+ return -ENOMEM; -+ -+ map->gc_interval = req->gc_interval ? req->gc_interval : IPTREEMAP_DEFAULT_GC_TIME; -+ set->data = map; -+ -+ init_gc_timer(set); -+ -+ return 0; -+} -+ -+static inline void -+__flush(struct ip_set_iptreemap *map) -+{ -+ struct ip_set_iptreemap_b *btree; -+ unsigned int a; -+ -+ LOOP_WALK_BEGIN(map, a, btree); -+ if (btree != fullbitmap_b) -+ free_b(btree); -+ LOOP_WALK_END(); -+} -+ -+static void -+iptreemap_destroy(struct ip_set *set) -+{ -+ struct ip_set_iptreemap *map = set->data; -+ -+ while (!del_timer(&map->gc)) -+ msleep(IPTREEMAP_DESTROY_SLEEP); -+ -+ __flush(map); -+ kfree(map); -+ -+ set->data = NULL; -+} -+ -+static void -+iptreemap_flush(struct ip_set *set) -+{ -+ struct ip_set_iptreemap *map = set->data; -+ -+ while (!del_timer(&map->gc)) -+ msleep(IPTREEMAP_DESTROY_SLEEP); -+ -+ __flush(map); -+ -+ memset(map, 0, sizeof(*map)); -+ -+ init_gc_timer(set); -+} -+ -+static void -+iptreemap_list_header(const struct ip_set *set, void *data) -+{ -+ struct ip_set_iptreemap *map = set->data; -+ struct ip_set_req_iptreemap_create *header = data; -+ -+ header->gc_interval = map->gc_interval; -+} -+ -+static int -+iptreemap_list_members_size(const struct ip_set *set) -+{ -+ struct ip_set_iptreemap *map = set->data; -+ struct ip_set_iptreemap_b *btree; -+ struct ip_set_iptreemap_c *ctree; -+ struct ip_set_iptreemap_d *dtree; -+ unsigned int a, b, c, d, inrange = 0, count = 0; -+ -+ LOOP_WALK_BEGIN_COUNT(map, a, btree, inrange, count) { -+ LOOP_WALK_BEGIN_COUNT(btree, b, ctree, inrange, count) { -+ LOOP_WALK_BEGIN_COUNT(ctree, c, dtree, inrange, count) { -+ for (d = 0; d < 256; d++) { -+ if (test_bit(d, (void *) dtree->bitmap)) { -+ inrange = 1; -+ } else if (inrange) { -+ count++; -+ inrange = 0; -+ } -+ } -+ } LOOP_WALK_END_COUNT(); -+ } LOOP_WALK_END_COUNT(); -+ } LOOP_WALK_END_COUNT(); -+ -+ if (inrange) -+ count++; -+ -+ return (count * sizeof(struct ip_set_req_iptreemap)); -+} -+ -+static inline u_int32_t -+add_member(void *data, size_t offset, ip_set_ip_t start, ip_set_ip_t end) -+{ -+ struct ip_set_req_iptreemap *entry = data + offset; -+ -+ entry->ip = start; -+ entry->end = end; -+ -+ return sizeof(*entry); -+} -+ -+static void -+iptreemap_list_members(const struct ip_set *set, void *data) -+{ -+ struct ip_set_iptreemap *map = set->data; -+ struct ip_set_iptreemap_b *btree; -+ struct ip_set_iptreemap_c *ctree; -+ struct ip_set_iptreemap_d *dtree; -+ unsigned int a, b, c, d, inrange = 0; -+ size_t offset = 0; -+ ip_set_ip_t start = 0, end = 0, ip; -+ -+ LOOP_WALK_BEGIN(map, a, btree) { -+ LOOP_WALK_BEGIN(btree, b, ctree) { -+ LOOP_WALK_BEGIN(ctree, c, dtree) { -+ for (d = 0; d < 256; d++) { -+ if (test_bit(d, (void *) dtree->bitmap)) { -+ ip = ((a << 24) | (b << 16) | (c << 8) | d); -+ if (!inrange) { -+ inrange = 1; -+ start = ip; -+ } else if (end < ip - 1) { -+ offset += add_member(data, offset, start, end); -+ start = ip; -+ } -+ end = ip; -+ } else if (inrange) { -+ offset += add_member(data, offset, start, end); -+ inrange = 0; -+ } -+ } -+ } LOOP_WALK_END(); -+ } LOOP_WALK_END(); -+ } LOOP_WALK_END(); -+ -+ if (inrange) -+ add_member(data, offset, start, end); -+} -+ -+IP_SET_TYPE(iptreemap, IPSET_TYPE_IP | IPSET_DATA_SINGLE) -+ -+MODULE_LICENSE("GPL"); -+MODULE_AUTHOR("Sven Wegener "); -+MODULE_DESCRIPTION("iptreemap type of IP sets"); -+ -+static int __init ip_set_iptreemap_init(void) -+{ -+ int ret = -ENOMEM; -+ int a; -+ -+ cachep_b = KMEM_CACHE_CREATE("ip_set_iptreemap_b", -+ sizeof(struct ip_set_iptreemap_b)); -+ if (!cachep_b) { -+ ip_set_printk("Unable to create ip_set_iptreemap_b slab cache"); -+ goto out; -+ } -+ -+ cachep_c = KMEM_CACHE_CREATE("ip_set_iptreemap_c", -+ sizeof(struct ip_set_iptreemap_c)); -+ if (!cachep_c) { -+ ip_set_printk("Unable to create ip_set_iptreemap_c slab cache"); -+ goto outb; -+ } -+ -+ cachep_d = KMEM_CACHE_CREATE("ip_set_iptreemap_d", -+ sizeof(struct ip_set_iptreemap_d)); -+ if (!cachep_d) { -+ ip_set_printk("Unable to create ip_set_iptreemap_d slab cache"); -+ goto outc; -+ } -+ -+ fullbitmap_d = kmem_cache_alloc(cachep_d, GFP_KERNEL); -+ if (!fullbitmap_d) -+ goto outd; -+ -+ fullbitmap_c = kmem_cache_alloc(cachep_c, GFP_KERNEL); -+ if (!fullbitmap_c) -+ goto outbitmapd; -+ -+ fullbitmap_b = kmem_cache_alloc(cachep_b, GFP_KERNEL); -+ if (!fullbitmap_b) -+ goto outbitmapc; -+ -+ ret = ip_set_register_set_type(&ip_set_iptreemap); -+ if (0 > ret) -+ goto outbitmapb; -+ -+ /* Now init our global bitmaps */ -+ memset(fullbitmap_d->bitmap, 0xff, sizeof(fullbitmap_d->bitmap)); -+ -+ for (a = 0; a < 256; a++) -+ fullbitmap_c->tree[a] = fullbitmap_d; -+ -+ for (a = 0; a < 256; a++) -+ fullbitmap_b->tree[a] = fullbitmap_c; -+ memset(fullbitmap_b->dirty, 0, sizeof(fullbitmap_b->dirty)); -+ -+ return 0; -+ -+outbitmapb: -+ kmem_cache_free(cachep_b, fullbitmap_b); -+outbitmapc: -+ kmem_cache_free(cachep_c, fullbitmap_c); -+outbitmapd: -+ kmem_cache_free(cachep_d, fullbitmap_d); -+outd: -+ kmem_cache_destroy(cachep_d); -+outc: -+ kmem_cache_destroy(cachep_c); -+outb: -+ kmem_cache_destroy(cachep_b); -+out: -+ -+ return ret; -+} -+ -+static void __exit ip_set_iptreemap_fini(void) -+{ -+ ip_set_unregister_set_type(&ip_set_iptreemap); -+ kmem_cache_free(cachep_d, fullbitmap_d); -+ kmem_cache_free(cachep_c, fullbitmap_c); -+ kmem_cache_free(cachep_b, fullbitmap_b); -+ kmem_cache_destroy(cachep_d); -+ kmem_cache_destroy(cachep_c); -+ kmem_cache_destroy(cachep_b); -+} -+ -+module_init(ip_set_iptreemap_init); -+module_exit(ip_set_iptreemap_fini); ---- /dev/null -+++ b/net/ipv4/netfilter/ip_set_macipmap.c -@@ -0,0 +1,164 @@ -+/* Copyright (C) 2000-2002 Joakim Axelsson -+ * Patrick Schaaf -+ * Martin Josefsson -+ * Copyright (C) 2003-2008 Jozsef Kadlecsik -+ * -+ * 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. -+ */ -+ -+/* Kernel module implementing an IP set type: the macipmap type */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+ -+static int -+macipmap_utest(struct ip_set *set, const void *data, u_int32_t size, -+ ip_set_ip_t *hash_ip) -+{ -+ const struct ip_set_macipmap *map = set->data; -+ const struct ip_set_macip *table = map->members; -+ const struct ip_set_req_macipmap *req = data; -+ -+ if (req->ip < map->first_ip || req->ip > map->last_ip) -+ return -ERANGE; -+ -+ *hash_ip = req->ip; -+ DP("set: %s, ip:%u.%u.%u.%u, %u.%u.%u.%u", -+ set->name, HIPQUAD(req->ip), HIPQUAD(*hash_ip)); -+ if (table[req->ip - map->first_ip].match) { -+ return (memcmp(req->ethernet, -+ &table[req->ip - map->first_ip].ethernet, -+ ETH_ALEN) == 0); -+ } else { -+ return (map->flags & IPSET_MACIP_MATCHUNSET ? 1 : 0); -+ } -+} -+ -+static int -+macipmap_ktest(struct ip_set *set, -+ const struct sk_buff *skb, -+ ip_set_ip_t *hash_ip, -+ const u_int32_t *flags, -+ unsigned char index) -+{ -+ const struct ip_set_macipmap *map = set->data; -+ const struct ip_set_macip *table = map->members; -+ ip_set_ip_t ip; -+ -+ ip = ipaddr(skb, flags[index]); -+ -+ if (ip < map->first_ip || ip > map->last_ip) -+ return 0; -+ -+ *hash_ip = ip; -+ DP("set: %s, ip:%u.%u.%u.%u, %u.%u.%u.%u", -+ set->name, HIPQUAD(ip), HIPQUAD(*hash_ip)); -+ if (table[ip - map->first_ip].match) { -+ /* Is mac pointer valid? -+ * If so, compare... */ -+ return (skb_mac_header(skb) >= skb->head -+ && (skb_mac_header(skb) + ETH_HLEN) <= skb->data -+ && (memcmp(eth_hdr(skb)->h_source, -+ &table[ip - map->first_ip].ethernet, -+ ETH_ALEN) == 0)); -+ } else { -+ return (map->flags & IPSET_MACIP_MATCHUNSET ? 1 : 0); -+ } -+} -+ -+/* returns 0 on success */ -+static inline int -+macipmap_add(struct ip_set *set, ip_set_ip_t *hash_ip, -+ ip_set_ip_t ip, const unsigned char *ethernet) -+{ -+ struct ip_set_macipmap *map = set->data; -+ struct ip_set_macip *table = map->members; -+ -+ if (ip < map->first_ip || ip > map->last_ip) -+ return -ERANGE; -+ if (table[ip - map->first_ip].match) -+ return -EEXIST; -+ -+ *hash_ip = ip; -+ DP("%u.%u.%u.%u, %u.%u.%u.%u", HIPQUAD(ip), HIPQUAD(*hash_ip)); -+ memcpy(&table[ip - map->first_ip].ethernet, ethernet, ETH_ALEN); -+ table[ip - map->first_ip].match = IPSET_MACIP_ISSET; -+ return 0; -+} -+ -+#define KADT_CONDITION \ -+ if (!(skb_mac_header(skb) >= skb->head \ -+ && (skb_mac_header(skb) + ETH_HLEN) <= skb->data))\ -+ return -EINVAL; -+ -+UADT(macipmap, add, req->ethernet) -+KADT(macipmap, add, ipaddr, eth_hdr(skb)->h_source) -+ -+static inline int -+macipmap_del(struct ip_set *set, ip_set_ip_t *hash_ip, ip_set_ip_t ip) -+{ -+ struct ip_set_macipmap *map = set->data; -+ struct ip_set_macip *table = map->members; -+ -+ if (ip < map->first_ip || ip > map->last_ip) -+ return -ERANGE; -+ if (!table[ip - map->first_ip].match) -+ return -EEXIST; -+ -+ *hash_ip = ip; -+ table[ip - map->first_ip].match = 0; -+ DP("%u.%u.%u.%u, %u.%u.%u.%u", HIPQUAD(ip), HIPQUAD(*hash_ip)); -+ return 0; -+} -+ -+#undef KADT_CONDITION -+#define KADT_CONDITION -+ -+UADT(macipmap, del) -+KADT(macipmap, del, ipaddr) -+ -+static inline int -+__macipmap_create(const struct ip_set_req_macipmap_create *req, -+ struct ip_set_macipmap *map) -+{ -+ if (req->to - req->from > MAX_RANGE) { -+ ip_set_printk("range too big, %d elements (max %d)", -+ req->to - req->from + 1, MAX_RANGE+1); -+ return -ENOEXEC; -+ } -+ map->flags = req->flags; -+ return (req->to - req->from + 1) * sizeof(struct ip_set_macip); -+} -+ -+BITMAP_CREATE(macipmap) -+BITMAP_DESTROY(macipmap) -+BITMAP_FLUSH(macipmap) -+ -+static inline void -+__macipmap_list_header(const struct ip_set_macipmap *map, -+ struct ip_set_req_macipmap_create *header) -+{ -+ header->flags = map->flags; -+} -+ -+BITMAP_LIST_HEADER(macipmap) -+BITMAP_LIST_MEMBERS_SIZE(macipmap) -+BITMAP_LIST_MEMBERS(macipmap) -+ -+IP_SET_TYPE(macipmap, IPSET_TYPE_IP | IPSET_DATA_SINGLE) -+ -+MODULE_LICENSE("GPL"); -+MODULE_AUTHOR("Jozsef Kadlecsik "); -+MODULE_DESCRIPTION("macipmap type of IP sets"); -+ -+REGISTER_MODULE(macipmap) ---- /dev/null -+++ b/net/ipv4/netfilter/ip_set_nethash.c -@@ -0,0 +1,225 @@ -+/* Copyright (C) 2003-2008 Jozsef Kadlecsik -+ * -+ * 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. -+ */ -+ -+/* Kernel module implementing a cidr nethash set */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+ -+#include -+ -+static int limit = MAX_RANGE; -+ -+static inline __u32 -+nethash_id_cidr(const struct ip_set_nethash *map, -+ ip_set_ip_t *hash_ip, -+ ip_set_ip_t ip, -+ uint8_t cidr) -+{ -+ __u32 id; -+ u_int16_t i; -+ ip_set_ip_t *elem; -+ -+ *hash_ip = pack_ip_cidr(ip, cidr); -+ if (!*hash_ip) -+ return MAX_RANGE; -+ -+ for (i = 0; i < map->probes; i++) { -+ id = jhash_ip(map, i, *hash_ip) % map->hashsize; -+ DP("hash key: %u", id); -+ elem = HARRAY_ELEM(map->members, ip_set_ip_t *, id); -+ if (*elem == *hash_ip) -+ return id; -+ /* No shortcut - there can be deleted entries. */ -+ } -+ return UINT_MAX; -+} -+ -+static inline __u32 -+nethash_id(struct ip_set *set, ip_set_ip_t *hash_ip, ip_set_ip_t ip) -+{ -+ const struct ip_set_nethash *map = set->data; -+ __u32 id = UINT_MAX; -+ int i; -+ -+ for (i = 0; i < 30 && map->cidr[i]; i++) { -+ id = nethash_id_cidr(map, hash_ip, ip, map->cidr[i]); -+ if (id != UINT_MAX) -+ break; -+ } -+ return id; -+} -+ -+static inline int -+nethash_test_cidr(struct ip_set *set, ip_set_ip_t *hash_ip, -+ ip_set_ip_t ip, uint8_t cidr) -+{ -+ const struct ip_set_nethash *map = set->data; -+ -+ return (nethash_id_cidr(map, hash_ip, ip, cidr) != UINT_MAX); -+} -+ -+static inline int -+nethash_test(struct ip_set *set, ip_set_ip_t *hash_ip, ip_set_ip_t ip) -+{ -+ return (nethash_id(set, hash_ip, ip) != UINT_MAX); -+} -+ -+static int -+nethash_utest(struct ip_set *set, const void *data, u_int32_t size, -+ ip_set_ip_t *hash_ip) -+{ -+ const struct ip_set_req_nethash *req = data; -+ -+ if (req->cidr <= 0 || req->cidr > 32) -+ return -EINVAL; -+ return (req->cidr == 32 ? nethash_test(set, hash_ip, req->ip) -+ : nethash_test_cidr(set, hash_ip, req->ip, req->cidr)); -+} -+ -+#define KADT_CONDITION -+ -+KADT(nethash, test, ipaddr) -+ -+static inline int -+__nethash_add(struct ip_set_nethash *map, ip_set_ip_t *ip) -+{ -+ __u32 probe; -+ u_int16_t i; -+ ip_set_ip_t *elem, *slot = NULL; -+ -+ for (i = 0; i < map->probes; i++) { -+ probe = jhash_ip(map, i, *ip) % map->hashsize; -+ elem = HARRAY_ELEM(map->members, ip_set_ip_t *, probe); -+ if (*elem == *ip) -+ return -EEXIST; -+ if (!(slot || *elem)) -+ slot = elem; -+ /* There can be deleted entries, must check all slots */ -+ } -+ if (slot) { -+ *slot = *ip; -+ map->elements++; -+ return 0; -+ } -+ /* Trigger rehashing */ -+ return -EAGAIN; -+} -+ -+static inline int -+nethash_add(struct ip_set *set, ip_set_ip_t *hash_ip, -+ ip_set_ip_t ip, uint8_t cidr) -+{ -+ struct ip_set_nethash *map = set->data; -+ int ret; -+ -+ if (map->elements >= limit || map->nets[cidr-1] == UINT16_MAX) -+ return -ERANGE; -+ if (cidr <= 0 || cidr >= 32) -+ return -EINVAL; -+ -+ *hash_ip = pack_ip_cidr(ip, cidr); -+ DP("%u.%u.%u.%u/%u, %u.%u.%u.%u", HIPQUAD(ip), cidr, HIPQUAD(*hash_ip)); -+ if (!*hash_ip) -+ return -ERANGE; -+ -+ ret = __nethash_add(map, hash_ip); -+ if (ret == 0) { -+ if (!map->nets[cidr-1]++) -+ add_cidr_size(map->cidr, cidr); -+ map->elements++; -+ } -+ -+ return ret; -+} -+ -+#undef KADT_CONDITION -+#define KADT_CONDITION \ -+ struct ip_set_nethash *map = set->data; \ -+ uint8_t cidr = map->cidr[0] ? map->cidr[0] : 31; -+ -+UADT(nethash, add, req->cidr) -+KADT(nethash, add, ipaddr, cidr) -+ -+static inline void -+__nethash_retry(struct ip_set_nethash *tmp, struct ip_set_nethash *map) -+{ -+ memcpy(tmp->cidr, map->cidr, sizeof(tmp->cidr)); -+ memcpy(tmp->nets, map->nets, sizeof(tmp->nets)); -+} -+ -+HASH_RETRY(nethash, ip_set_ip_t) -+ -+static inline int -+nethash_del(struct ip_set *set, ip_set_ip_t *hash_ip, -+ ip_set_ip_t ip, uint8_t cidr) -+{ -+ struct ip_set_nethash *map = set->data; -+ ip_set_ip_t id, *elem; -+ -+ if (cidr <= 0 || cidr >= 32) -+ return -EINVAL; -+ -+ id = nethash_id_cidr(map, hash_ip, ip, cidr); -+ if (id == UINT_MAX) -+ return -EEXIST; -+ -+ elem = HARRAY_ELEM(map->members, ip_set_ip_t *, id); -+ *elem = 0; -+ map->elements--; -+ if (!map->nets[cidr-1]--) -+ del_cidr_size(map->cidr, cidr); -+ return 0; -+} -+ -+UADT(nethash, del, req->cidr) -+KADT(nethash, del, ipaddr, cidr) -+ -+static inline int -+__nethash_create(const struct ip_set_req_nethash_create *req, -+ struct ip_set_nethash *map) -+{ -+ memset(map->cidr, 0, sizeof(map->cidr)); -+ memset(map->nets, 0, sizeof(map->nets)); -+ -+ return 0; -+} -+ -+HASH_CREATE(nethash, ip_set_ip_t) -+HASH_DESTROY(nethash) -+ -+HASH_FLUSH_CIDR(nethash, ip_set_ip_t) -+ -+static inline void -+__nethash_list_header(const struct ip_set_nethash *map, -+ struct ip_set_req_nethash_create *header) -+{ -+} -+ -+HASH_LIST_HEADER(nethash) -+HASH_LIST_MEMBERS_SIZE(nethash, ip_set_ip_t) -+HASH_LIST_MEMBERS(nethash, ip_set_ip_t) -+ -+IP_SET_RTYPE(nethash, IPSET_TYPE_IP | IPSET_DATA_SINGLE) -+ -+MODULE_LICENSE("GPL"); -+MODULE_AUTHOR("Jozsef Kadlecsik "); -+MODULE_DESCRIPTION("nethash type of IP sets"); -+module_param(limit, int, 0600); -+MODULE_PARM_DESC(limit, "maximal number of elements stored in the sets"); -+ -+REGISTER_MODULE(nethash) ---- /dev/null -+++ b/net/ipv4/netfilter/ip_set_portmap.c -@@ -0,0 +1,114 @@ -+/* Copyright (C) 2003-2008 Jozsef Kadlecsik -+ * -+ * 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. -+ */ -+ -+/* Kernel module implementing a port set type as a bitmap */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+ -+#include -+#include -+ -+static inline int -+portmap_test(const struct ip_set *set, ip_set_ip_t *hash_port, -+ ip_set_ip_t port) -+{ -+ const struct ip_set_portmap *map = set->data; -+ -+ if (port < map->first_ip || port > map->last_ip) -+ return -ERANGE; -+ -+ *hash_port = port; -+ DP("set: %s, port:%u, %u", set->name, port, *hash_port); -+ return !!test_bit(port - map->first_ip, map->members); -+} -+ -+#define KADT_CONDITION \ -+ if (ip == INVALID_PORT) \ -+ return 0; -+ -+UADT(portmap, test) -+KADT(portmap, test, get_port) -+ -+static inline int -+portmap_add(struct ip_set *set, ip_set_ip_t *hash_port, ip_set_ip_t port) -+{ -+ struct ip_set_portmap *map = set->data; -+ -+ if (port < map->first_ip || port > map->last_ip) -+ return -ERANGE; -+ if (test_and_set_bit(port - map->first_ip, map->members)) -+ return -EEXIST; -+ -+ *hash_port = port; -+ DP("port %u", port); -+ return 0; -+} -+ -+UADT(portmap, add) -+KADT(portmap, add, get_port) -+ -+static inline int -+portmap_del(struct ip_set *set, ip_set_ip_t *hash_port, ip_set_ip_t port) -+{ -+ struct ip_set_portmap *map = set->data; -+ -+ if (port < map->first_ip || port > map->last_ip) -+ return -ERANGE; -+ if (!test_and_clear_bit(port - map->first_ip, map->members)) -+ return -EEXIST; -+ -+ *hash_port = port; -+ DP("port %u", port); -+ return 0; -+} -+ -+UADT(portmap, del) -+KADT(portmap, del, get_port) -+ -+static inline int -+__portmap_create(const struct ip_set_req_portmap_create *req, -+ struct ip_set_portmap *map) -+{ -+ if (req->to - req->from > MAX_RANGE) { -+ ip_set_printk("range too big, %d elements (max %d)", -+ req->to - req->from + 1, MAX_RANGE+1); -+ return -ENOEXEC; -+ } -+ return bitmap_bytes(req->from, req->to); -+} -+ -+BITMAP_CREATE(portmap) -+BITMAP_DESTROY(portmap) -+BITMAP_FLUSH(portmap) -+ -+static inline void -+__portmap_list_header(const struct ip_set_portmap *map, -+ struct ip_set_req_portmap_create *header) -+{ -+} -+ -+BITMAP_LIST_HEADER(portmap) -+BITMAP_LIST_MEMBERS_SIZE(portmap) -+BITMAP_LIST_MEMBERS(portmap) -+ -+IP_SET_TYPE(portmap, IPSET_TYPE_PORT | IPSET_DATA_SINGLE) -+ -+MODULE_LICENSE("GPL"); -+MODULE_AUTHOR("Jozsef Kadlecsik "); -+MODULE_DESCRIPTION("portmap type of IP sets"); -+ -+REGISTER_MODULE(portmap) ---- /dev/null -+++ b/net/ipv4/netfilter/ip_set_setlist.c -@@ -0,0 +1,330 @@ -+/* Copyright (C) 2008 Jozsef Kadlecsik -+ * -+ * 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. -+ */ -+ -+/* Kernel module implementing an IP set type: the setlist type */ -+ -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+ -+/* -+ * before ==> index, ref -+ * after ==> ref, index -+ */ -+ -+static inline int -+next_index_eq(const struct ip_set_setlist *map, int i, ip_set_id_t index) -+{ -+ return i < map->size && map->index[i] == index; -+} -+ -+static int -+setlist_utest(struct ip_set *set, const void *data, u_int32_t size, -+ ip_set_ip_t *hash_ip) -+{ -+ const struct ip_set_setlist *map = set->data; -+ const struct ip_set_req_setlist *req = data; -+ ip_set_id_t index, ref = IP_SET_INVALID_ID; -+ int i, res = 0; -+ struct ip_set *s; -+ -+ if (req->before && req->ref[0] == '\0') -+ return 0; -+ -+ index = __ip_set_get_byname(req->name, &s); -+ if (index == IP_SET_INVALID_ID) -+ return 0; -+ if (req->ref[0] != '\0') { -+ ref = __ip_set_get_byname(req->ref, &s); -+ if (ref == IP_SET_INVALID_ID) -+ goto finish; -+ } -+ for (i = 0; i < map->size -+ && map->index[i] != IP_SET_INVALID_ID; i++) { -+ if (req->before && map->index[i] == index) { -+ res = next_index_eq(map, i + 1, ref); -+ break; -+ } else if (!req->before) { -+ if ((ref == IP_SET_INVALID_ID -+ && map->index[i] == index) -+ || (map->index[i] == ref -+ && next_index_eq(map, i + 1, index))) { -+ res = 1; -+ break; -+ } -+ } -+ } -+ if (ref != IP_SET_INVALID_ID) -+ __ip_set_put_byindex(ref); -+finish: -+ __ip_set_put_byindex(index); -+ return res; -+} -+ -+static int -+setlist_ktest(struct ip_set *set, -+ const struct sk_buff *skb, -+ ip_set_ip_t *hash_ip, -+ const u_int32_t *flags, -+ unsigned char index) -+{ -+ struct ip_set_setlist *map = set->data; -+ int i, res = 0; -+ -+ for (i = 0; i < map->size -+ && map->index[i] != IP_SET_INVALID_ID -+ && res == 0; i++) -+ res = ip_set_testip_kernel(map->index[i], skb, flags); -+ return res; -+} -+ -+static inline int -+insert_setlist(struct ip_set_setlist *map, int i, ip_set_id_t index) -+{ -+ ip_set_id_t tmp; -+ int j; -+ -+ DP("i: %u, last %u\n", i, map->index[map->size - 1]); -+ if (i >= map->size || map->index[map->size - 1] != IP_SET_INVALID_ID) -+ return -ERANGE; -+ -+ for (j = i; j < map->size -+ && index != IP_SET_INVALID_ID; j++) { -+ tmp = map->index[j]; -+ map->index[j] = index; -+ index = tmp; -+ } -+ return 0; -+} -+ -+static int -+setlist_uadd(struct ip_set *set, const void *data, u_int32_t size, -+ ip_set_ip_t *hash_ip) -+{ -+ struct ip_set_setlist *map = set->data; -+ const struct ip_set_req_setlist *req = data; -+ ip_set_id_t index, ref = IP_SET_INVALID_ID; -+ int i, res = -ERANGE; -+ struct ip_set *s; -+ -+ if (req->before && req->ref[0] == '\0') -+ return -EINVAL; -+ -+ index = __ip_set_get_byname(req->name, &s); -+ if (index == IP_SET_INVALID_ID) -+ return -EEXIST; -+ /* "Loop detection" */ -+ if (strcmp(s->type->typename, "setlist") == 0) -+ goto finish; -+ -+ if (req->ref[0] != '\0') { -+ ref = __ip_set_get_byname(req->ref, &s); -+ if (ref == IP_SET_INVALID_ID) { -+ res = -EEXIST; -+ goto finish; -+ } -+ } -+ for (i = 0; i < map->size; i++) { -+ if (map->index[i] != ref) -+ continue; -+ if (req->before) -+ res = insert_setlist(map, i, index); -+ else -+ res = insert_setlist(map, -+ ref == IP_SET_INVALID_ID ? i : i + 1, -+ index); -+ break; -+ } -+ if (ref != IP_SET_INVALID_ID) -+ __ip_set_put_byindex(ref); -+ /* In case of success, we keep the reference to the set */ -+finish: -+ if (res != 0) -+ __ip_set_put_byindex(index); -+ return res; -+} -+ -+static int -+setlist_kadd(struct ip_set *set, -+ const struct sk_buff *skb, -+ ip_set_ip_t *hash_ip, -+ const u_int32_t *flags, -+ unsigned char index) -+{ -+ struct ip_set_setlist *map = set->data; -+ int i, res = -EINVAL; -+ -+ for (i = 0; i < map->size -+ && map->index[i] != IP_SET_INVALID_ID -+ && res != 0; i++) -+ res = ip_set_addip_kernel(map->index[i], skb, flags); -+ return res; -+} -+ -+static inline int -+unshift_setlist(struct ip_set_setlist *map, int i) -+{ -+ int j; -+ -+ for (j = i; j < map->size - 1; j++) -+ map->index[j] = map->index[j+1]; -+ map->index[map->size-1] = IP_SET_INVALID_ID; -+ return 0; -+} -+ -+static int -+setlist_udel(struct ip_set *set, const void *data, u_int32_t size, -+ ip_set_ip_t *hash_ip) -+{ -+ struct ip_set_setlist *map = set->data; -+ const struct ip_set_req_setlist *req = data; -+ ip_set_id_t index, ref = IP_SET_INVALID_ID; -+ int i, res = -EEXIST; -+ struct ip_set *s; -+ -+ if (req->before && req->ref[0] == '\0') -+ return -EINVAL; -+ -+ index = __ip_set_get_byname(req->name, &s); -+ if (index == IP_SET_INVALID_ID) -+ return -EEXIST; -+ if (req->ref[0] != '\0') { -+ ref = __ip_set_get_byname(req->ref, &s); -+ if (ref == IP_SET_INVALID_ID) -+ goto finish; -+ } -+ for (i = 0; i < map->size -+ && map->index[i] != IP_SET_INVALID_ID; i++) { -+ if (req->before) { -+ if (map->index[i] == index -+ && next_index_eq(map, i + 1, ref)) { -+ res = unshift_setlist(map, i); -+ break; -+ } -+ } else if (ref == IP_SET_INVALID_ID) { -+ if (map->index[i] == index) { -+ res = unshift_setlist(map, i); -+ break; -+ } -+ } else if (map->index[i] == ref -+ && next_index_eq(map, i + 1, index)) { -+ res = unshift_setlist(map, i + 1); -+ break; -+ } -+ } -+ if (ref != IP_SET_INVALID_ID) -+ __ip_set_put_byindex(ref); -+finish: -+ __ip_set_put_byindex(index); -+ /* In case of success, release the reference to the set */ -+ if (res == 0) -+ __ip_set_put_byindex(index); -+ return res; -+} -+ -+static int -+setlist_kdel(struct ip_set *set, -+ const struct sk_buff *skb, -+ ip_set_ip_t *hash_ip, -+ const u_int32_t *flags, -+ unsigned char index) -+{ -+ struct ip_set_setlist *map = set->data; -+ int i, res = -EINVAL; -+ -+ for (i = 0; i < map->size -+ && map->index[i] != IP_SET_INVALID_ID -+ && res != 0; i++) -+ res = ip_set_delip_kernel(map->index[i], skb, flags); -+ return res; -+} -+ -+static int -+setlist_create(struct ip_set *set, const void *data, u_int32_t size) -+{ -+ struct ip_set_setlist *map; -+ const struct ip_set_req_setlist_create *req = data; -+ int i; -+ -+ map = kmalloc(sizeof(struct ip_set_setlist) + -+ req->size * sizeof(ip_set_id_t), GFP_KERNEL); -+ if (!map) -+ return -ENOMEM; -+ map->size = req->size; -+ for (i = 0; i < map->size; i++) -+ map->index[i] = IP_SET_INVALID_ID; -+ -+ set->data = map; -+ return 0; -+} -+ -+static void -+setlist_destroy(struct ip_set *set) -+{ -+ struct ip_set_setlist *map = set->data; -+ int i; -+ -+ for (i = 0; i < map->size -+ && map->index[i] != IP_SET_INVALID_ID; i++) -+ __ip_set_put_byindex(map->index[i]); -+ -+ kfree(map); -+ set->data = NULL; -+} -+ -+static void -+setlist_flush(struct ip_set *set) -+{ -+ struct ip_set_setlist *map = set->data; -+ int i; -+ -+ for (i = 0; i < map->size -+ && map->index[i] != IP_SET_INVALID_ID; i++) { -+ __ip_set_put_byindex(map->index[i]); -+ map->index[i] = IP_SET_INVALID_ID; -+ } -+} -+ -+static void -+setlist_list_header(const struct ip_set *set, void *data) -+{ -+ const struct ip_set_setlist *map = set->data; -+ struct ip_set_req_setlist_create *header = data; -+ -+ header->size = map->size; -+} -+ -+static int -+setlist_list_members_size(const struct ip_set *set) -+{ -+ const struct ip_set_setlist *map = set->data; -+ -+ return map->size * sizeof(ip_set_id_t); -+} -+ -+static void -+setlist_list_members(const struct ip_set *set, void *data) -+{ -+ struct ip_set_setlist *map = set->data; -+ int i; -+ -+ for (i = 0; i < map->size; i++) -+ *((ip_set_id_t *)data + i) = ip_set_id(map->index[i]); -+} -+ -+IP_SET_TYPE(setlist, IPSET_TYPE_SETNAME | IPSET_DATA_SINGLE) -+ -+MODULE_LICENSE("GPL"); -+MODULE_AUTHOR("Jozsef Kadlecsik "); -+MODULE_DESCRIPTION("setlist type of IP sets"); -+ -+REGISTER_MODULE(setlist) ---- /dev/null -+++ b/net/ipv4/netfilter/ipt_set.c -@@ -0,0 +1,238 @@ -+/* Copyright (C) 2000-2002 Joakim Axelsson -+ * Patrick Schaaf -+ * Martin Josefsson -+ * Copyright (C) 2003-2004 Jozsef Kadlecsik -+ * -+ * 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. -+ */ -+ -+/* Kernel module to match an IP set. */ -+ -+#include -+#include -+#include -+#include -+ -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,16) -+#include -+#define xt_register_match ipt_register_match -+#define xt_unregister_match ipt_unregister_match -+#define xt_match ipt_match -+#else -+#include -+#endif -+#include -+#include -+ -+static inline int -+match_set(const struct ipt_set_info *info, -+ const struct sk_buff *skb, -+ int inv) -+{ -+ if (ip_set_testip_kernel(info->index, skb, info->flags)) -+ inv = !inv; -+ return inv; -+} -+ -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) -+static int -+match(const struct sk_buff *skb, -+ const struct net_device *in, -+ const struct net_device *out, -+ const void *matchinfo, -+ int offset, -+ const void *hdr, -+ u_int16_t datalen, -+ int *hotdrop) -+#elif LINUX_VERSION_CODE < KERNEL_VERSION(2,6,16) -+static int -+match(const struct sk_buff *skb, -+ const struct net_device *in, -+ const struct net_device *out, -+ const void *matchinfo, -+ int offset, -+ int *hotdrop) -+#elif LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17) -+static int -+match(const struct sk_buff *skb, -+ const struct net_device *in, -+ const struct net_device *out, -+ const void *matchinfo, -+ int offset, -+ unsigned int protoff, -+ int *hotdrop) -+#elif LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23) -+static int -+match(const struct sk_buff *skb, -+ const struct net_device *in, -+ const struct net_device *out, -+ const struct xt_match *match, -+ const void *matchinfo, -+ int offset, -+ unsigned int protoff, -+ int *hotdrop) -+#elif LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28) -+static bool -+match(const struct sk_buff *skb, -+ const struct net_device *in, -+ const struct net_device *out, -+ const struct xt_match *match, -+ const void *matchinfo, -+ int offset, -+ unsigned int protoff, -+ bool *hotdrop) -+#else /* LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28) */ -+static bool -+match(const struct sk_buff *skb, -+ const struct xt_match_param *par) -+#endif -+{ -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28) -+ const struct ipt_set_info_match *info = matchinfo; -+#else -+ const struct ipt_set_info_match *info = par->matchinfo; -+#endif -+ -+ return match_set(&info->match_set, -+ skb, -+ info->match_set.flags[0] & IPSET_MATCH_INV); -+} -+ -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,16) -+static int -+checkentry(const char *tablename, -+ const struct ipt_ip *ip, -+ void *matchinfo, -+ unsigned int matchsize, -+ unsigned int hook_mask) -+#elif LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17) -+static int -+checkentry(const char *tablename, -+ const void *inf, -+ void *matchinfo, -+ unsigned int matchsize, -+ unsigned int hook_mask) -+#elif LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19) -+static int -+checkentry(const char *tablename, -+ const void *inf, -+ const struct xt_match *match, -+ void *matchinfo, -+ unsigned int matchsize, -+ unsigned int hook_mask) -+#elif LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23) -+static int -+checkentry(const char *tablename, -+ const void *inf, -+ const struct xt_match *match, -+ void *matchinfo, -+ unsigned int hook_mask) -+#elif LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28) -+static bool -+checkentry(const char *tablename, -+ const void *inf, -+ const struct xt_match *match, -+ void *matchinfo, -+ unsigned int hook_mask) -+#else /* LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28) */ -+static bool -+checkentry(const struct xt_mtchk_param *par) -+#endif -+{ -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28) -+ struct ipt_set_info_match *info = matchinfo; -+#else -+ struct ipt_set_info_match *info = par->matchinfo; -+#endif -+ ip_set_id_t index; -+ -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17) -+ if (matchsize != IPT_ALIGN(sizeof(struct ipt_set_info_match))) { -+ ip_set_printk("invalid matchsize %d", matchsize); -+ return 0; -+ } -+#endif -+ -+ index = ip_set_get_byindex(info->match_set.index); -+ -+ if (index == IP_SET_INVALID_ID) { -+ ip_set_printk("Cannot find set indentified by id %u to match", -+ info->match_set.index); -+ return 0; /* error */ -+ } -+ if (info->match_set.flags[IP_SET_MAX_BINDINGS] != 0) { -+ ip_set_printk("That's nasty!"); -+ return 0; /* error */ -+ } -+ -+ return 1; -+} -+ -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17) -+static void destroy(void *matchinfo, -+ unsigned int matchsize) -+#elif LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19) -+static void destroy(const struct xt_match *match, -+ void *matchinfo, -+ unsigned int matchsize) -+#elif LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28) -+static void destroy(const struct xt_match *match, -+ void *matchinfo) -+#else /* LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28) */ -+static void destroy(const struct xt_mtdtor_param *par) -+#endif -+{ -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28) -+ struct ipt_set_info_match *info = matchinfo; -+#else -+ struct ipt_set_info_match *info = par->matchinfo; -+#endif -+ -+ -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17) -+ if (matchsize != IPT_ALIGN(sizeof(struct ipt_set_info_match))) { -+ ip_set_printk("invalid matchsize %d", matchsize); -+ return; -+ } -+#endif -+ ip_set_put_byindex(info->match_set.index); -+} -+ -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17) -+static struct xt_match set_match = { -+ .name = "set", -+ .match = &match, -+ .checkentry = &checkentry, -+ .destroy = &destroy, -+ .me = THIS_MODULE -+}; -+#else /* LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,17) */ -+static struct xt_match set_match = { -+ .name = "set", -+ .family = AF_INET, -+ .match = &match, -+ .matchsize = sizeof(struct ipt_set_info_match), -+ .checkentry = &checkentry, -+ .destroy = &destroy, -+ .me = THIS_MODULE -+}; -+#endif -+ -+MODULE_LICENSE("GPL"); -+MODULE_AUTHOR("Jozsef Kadlecsik "); -+MODULE_DESCRIPTION("iptables IP set match module"); -+ -+static int __init ipt_ipset_init(void) -+{ -+ return xt_register_match(&set_match); -+} -+ -+static void __exit ipt_ipset_fini(void) -+{ -+ xt_unregister_match(&set_match); -+} -+ -+module_init(ipt_ipset_init); -+module_exit(ipt_ipset_fini); ---- /dev/null -+++ b/net/ipv4/netfilter/ipt_SET.c -@@ -0,0 +1,242 @@ -+/* Copyright (C) 2000-2002 Joakim Axelsson -+ * Patrick Schaaf -+ * Martin Josefsson -+ * Copyright (C) 2003-2004 Jozsef Kadlecsik -+ * -+ * 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. -+ */ -+ -+/* ipt_SET.c - netfilter target to manipulate IP sets */ -+ -+#include -+#include -+#include -+#include -+ -+#include -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,16) -+#include -+#define xt_register_target ipt_register_target -+#define xt_unregister_target ipt_unregister_target -+#define xt_target ipt_target -+#define XT_CONTINUE IPT_CONTINUE -+#else -+#include -+#endif -+#include -+ -+static unsigned int -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) -+target(struct sk_buff **pskb, -+ unsigned int hooknum, -+ const struct net_device *in, -+ const struct net_device *out, -+ const void *targinfo, -+ void *userinfo) -+#elif LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17) -+target(struct sk_buff **pskb, -+ const struct net_device *in, -+ const struct net_device *out, -+ unsigned int hooknum, -+ const void *targinfo, -+ void *userinfo) -+#elif LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19) -+target(struct sk_buff **pskb, -+ const struct net_device *in, -+ const struct net_device *out, -+ unsigned int hooknum, -+ const struct xt_target *target, -+ const void *targinfo, -+ void *userinfo) -+#elif LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24) -+target(struct sk_buff **pskb, -+ const struct net_device *in, -+ const struct net_device *out, -+ unsigned int hooknum, -+ const struct xt_target *target, -+ const void *targinfo) -+#elif LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28) -+target(struct sk_buff *skb, -+ const struct net_device *in, -+ const struct net_device *out, -+ unsigned int hooknum, -+ const struct xt_target *target, -+ const void *targinfo) -+#else /* LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28) */ -+target(struct sk_buff *skb, -+ const struct xt_target_param *par) -+#endif -+{ -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28) -+ const struct ipt_set_info_target *info = targinfo; -+#else -+ const struct ipt_set_info_target *info = par->targinfo; -+#endif -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24) -+ struct sk_buff *skb = *pskb; -+#endif -+ -+ -+ if (info->add_set.index != IP_SET_INVALID_ID) -+ ip_set_addip_kernel(info->add_set.index, -+ skb, -+ info->add_set.flags); -+ if (info->del_set.index != IP_SET_INVALID_ID) -+ ip_set_delip_kernel(info->del_set.index, -+ skb, -+ info->del_set.flags); -+ -+ return XT_CONTINUE; -+} -+ -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,16) -+static int -+checkentry(const char *tablename, -+ const struct ipt_entry *e, -+ void *targinfo, -+ unsigned int targinfosize, -+ unsigned int hook_mask) -+#elif LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17) -+static int -+checkentry(const char *tablename, -+ const void *e, -+ void *targinfo, -+ unsigned int targinfosize, -+ unsigned int hook_mask) -+#elif LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19) -+static int -+checkentry(const char *tablename, -+ const void *e, -+ const struct xt_target *target, -+ void *targinfo, -+ unsigned int targinfosize, -+ unsigned int hook_mask) -+#elif LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23) -+static int -+checkentry(const char *tablename, -+ const void *e, -+ const struct xt_target *target, -+ void *targinfo, -+ unsigned int hook_mask) -+#elif LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28) -+static bool -+checkentry(const char *tablename, -+ const void *e, -+ const struct xt_target *target, -+ void *targinfo, -+ unsigned int hook_mask) -+#else /* LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28) */ -+static bool -+checkentry(const struct xt_tgchk_param *par) -+#endif -+{ -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28) -+ const struct ipt_set_info_target *info = targinfo; -+#else -+ const struct ipt_set_info_target *info = par->targinfo; -+#endif -+ ip_set_id_t index; -+ -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17) -+ if (targinfosize != IPT_ALIGN(sizeof(*info))) { -+ DP("bad target info size %u", targinfosize); -+ return 0; -+ } -+#endif -+ -+ if (info->add_set.index != IP_SET_INVALID_ID) { -+ index = ip_set_get_byindex(info->add_set.index); -+ if (index == IP_SET_INVALID_ID) { -+ ip_set_printk("cannot find add_set index %u as target", -+ info->add_set.index); -+ return 0; /* error */ -+ } -+ } -+ -+ if (info->del_set.index != IP_SET_INVALID_ID) { -+ index = ip_set_get_byindex(info->del_set.index); -+ if (index == IP_SET_INVALID_ID) { -+ ip_set_printk("cannot find del_set index %u as target", -+ info->del_set.index); -+ return 0; /* error */ -+ } -+ } -+ if (info->add_set.flags[IP_SET_MAX_BINDINGS] != 0 -+ || info->del_set.flags[IP_SET_MAX_BINDINGS] != 0) { -+ ip_set_printk("That's nasty!"); -+ return 0; /* error */ -+ } -+ -+ return 1; -+} -+ -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17) -+static void destroy(void *targetinfo, -+ unsigned int targetsize) -+#elif LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19) -+static void destroy(const struct xt_target *target, -+ void *targetinfo, -+ unsigned int targetsize) -+#elif LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28) -+static void destroy(const struct xt_target *target, -+ void *targetinfo) -+#else /* LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28) */ -+static void destroy(const struct xt_tgdtor_param *par) -+#endif -+{ -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28) -+ const struct ipt_set_info_target *info = targetinfo; -+#else -+ const struct ipt_set_info_target *info = par->targinfo; -+#endif -+ -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17) -+ if (targetsize != IPT_ALIGN(sizeof(struct ipt_set_info_target))) { -+ ip_set_printk("invalid targetsize %d", targetsize); -+ return; -+ } -+#endif -+ if (info->add_set.index != IP_SET_INVALID_ID) -+ ip_set_put_byindex(info->add_set.index); -+ if (info->del_set.index != IP_SET_INVALID_ID) -+ ip_set_put_byindex(info->del_set.index); -+} -+ -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17) -+static struct xt_target SET_target = { -+ .name = "SET", -+ .target = target, -+ .checkentry = checkentry, -+ .destroy = destroy, -+ .me = THIS_MODULE -+}; -+#else /* LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,17) */ -+static struct xt_target SET_target = { -+ .name = "SET", -+ .family = AF_INET, -+ .target = target, -+ .targetsize = sizeof(struct ipt_set_info_target), -+ .checkentry = checkentry, -+ .destroy = destroy, -+ .me = THIS_MODULE -+}; -+#endif -+ -+MODULE_LICENSE("GPL"); -+MODULE_AUTHOR("Jozsef Kadlecsik "); -+MODULE_DESCRIPTION("iptables IP set target module"); -+ -+static int __init ipt_SET_init(void) -+{ -+ return xt_register_target(&SET_target); -+} -+ -+static void __exit ipt_SET_fini(void) -+{ -+ xt_unregister_target(&SET_target); -+} -+ -+module_init(ipt_SET_init); -+module_exit(ipt_SET_fini); ---- a/net/ipv4/netfilter/Kconfig -+++ b/net/ipv4/netfilter/Kconfig -@@ -394,5 +394,146 @@ config IP_NF_ARP_MANGLE - - endif # IP_NF_ARPTABLES - -+config IP_NF_SET -+ tristate "IP set support" -+ depends on INET && NETFILTER -+ help -+ This option adds IP set support to the kernel. -+ In order to define and use sets, you need the userspace utility -+ ipset(8). -+ -+ To compile it as a module, choose M here. If unsure, say N. -+ -+config IP_NF_SET_MAX -+ int "Maximum number of IP sets" -+ default 256 -+ range 2 65534 -+ depends on IP_NF_SET -+ help -+ You can define here default value of the maximum number -+ of IP sets for the kernel. -+ -+ The value can be overriden by the 'max_sets' module -+ parameter of the 'ip_set' module. -+ -+config IP_NF_SET_HASHSIZE -+ int "Hash size for bindings of IP sets" -+ default 1024 -+ depends on IP_NF_SET -+ help -+ You can define here default value of the hash size for -+ bindings of IP sets. -+ -+ The value can be overriden by the 'hash_size' module -+ parameter of the 'ip_set' module. -+ -+config IP_NF_SET_IPMAP -+ tristate "ipmap set support" -+ depends on IP_NF_SET -+ help -+ This option adds the ipmap set type support. -+ -+ To compile it as a module, choose M here. If unsure, say N. -+ -+config IP_NF_SET_MACIPMAP -+ tristate "macipmap set support" -+ depends on IP_NF_SET -+ help -+ This option adds the macipmap set type support. -+ -+ To compile it as a module, choose M here. If unsure, say N. -+ -+config IP_NF_SET_PORTMAP -+ tristate "portmap set support" -+ depends on IP_NF_SET -+ help -+ This option adds the portmap set type support. -+ -+ To compile it as a module, choose M here. If unsure, say N. -+ -+config IP_NF_SET_IPHASH -+ tristate "iphash set support" -+ depends on IP_NF_SET -+ help -+ This option adds the iphash set type support. -+ -+ To compile it as a module, choose M here. If unsure, say N. -+ -+config IP_NF_SET_NETHASH -+ tristate "nethash set support" -+ depends on IP_NF_SET -+ help -+ This option adds the nethash set type support. -+ -+ To compile it as a module, choose M here. If unsure, say N. -+ -+config IP_NF_SET_IPPORTHASH -+ tristate "ipporthash set support" -+ depends on IP_NF_SET -+ help -+ This option adds the ipporthash set type support. -+ -+ To compile it as a module, choose M here. If unsure, say N. -+ -+config IP_NF_SET_IPPORTIPHASH -+ tristate "ipportiphash set support" -+ depends on IP_NF_SET -+ help -+ This option adds the ipportiphash set type support. -+ -+ To compile it as a module, choose M here. If unsure, say N. -+ -+config IP_NF_SET_IPPORTNETHASH -+ tristate "ipportnethash set support" -+ depends on IP_NF_SET -+ help -+ This option adds the ipportnethash set type support. -+ -+ To compile it as a module, choose M here. If unsure, say N. -+ -+config IP_NF_SET_IPTREE -+ tristate "iptree set support" -+ depends on IP_NF_SET -+ help -+ This option adds the iptree set type support. -+ -+ To compile it as a module, choose M here. If unsure, say N. -+ -+config IP_NF_SET_IPTREEMAP -+ tristate "iptreemap set support" -+ depends on IP_NF_SET -+ help -+ This option adds the iptreemap set type support. -+ -+ To compile it as a module, choose M here. If unsure, say N. -+ -+config IP_NF_SET_SETLIST -+ tristate "setlist set support" -+ depends on IP_NF_SET -+ help -+ This option adds the setlist set type support. -+ -+ To compile it as a module, choose M here. If unsure, say N. -+ -+config IP_NF_MATCH_SET -+ tristate "set match support" -+ depends on IP_NF_SET -+ help -+ Set matching matches against given IP sets. -+ You need the ipset utility to create and set up the sets. -+ -+ To compile it as a module, choose M here. If unsure, say N. -+ -+config IP_NF_TARGET_SET -+ tristate "SET target support" -+ depends on IP_NF_SET -+ help -+ The SET target makes possible to add/delete entries -+ in IP sets. -+ You need the ipset utility to create and set up the sets. -+ -+ To compile it as a module, choose M here. If unsure, say N. -+ -+ - endmenu - ---- a/net/ipv4/netfilter/Makefile -+++ b/net/ipv4/netfilter/Makefile -@@ -52,6 +52,7 @@ obj-$(CONFIG_IP_NF_MATCH_ADDRTYPE) += ip - obj-$(CONFIG_IP_NF_MATCH_AH) += ipt_ah.o - obj-$(CONFIG_IP_NF_MATCH_ECN) += ipt_ecn.o - obj-$(CONFIG_IP_NF_MATCH_TTL) += ipt_ttl.o -+obj-$(CONFIG_IP_NF_MATCH_SET) += ipt_set.o - - # targets - obj-$(CONFIG_IP_NF_TARGET_CLUSTERIP) += ipt_CLUSTERIP.o -@@ -63,6 +64,21 @@ obj-$(CONFIG_IP_NF_TARGET_REDIRECT) += i - obj-$(CONFIG_IP_NF_TARGET_REJECT) += ipt_REJECT.o - obj-$(CONFIG_IP_NF_TARGET_TTL) += ipt_TTL.o - obj-$(CONFIG_IP_NF_TARGET_ULOG) += ipt_ULOG.o -+obj-$(CONFIG_IP_NF_TARGET_SET) += ipt_SET.o -+ -+# sets -+obj-$(CONFIG_IP_NF_SET) += ip_set.o -+obj-$(CONFIG_IP_NF_SET_IPMAP) += ip_set_ipmap.o -+obj-$(CONFIG_IP_NF_SET_PORTMAP) += ip_set_portmap.o -+obj-$(CONFIG_IP_NF_SET_MACIPMAP) += ip_set_macipmap.o -+obj-$(CONFIG_IP_NF_SET_IPHASH) += ip_set_iphash.o -+obj-$(CONFIG_IP_NF_SET_NETHASH) += ip_set_nethash.o -+obj-$(CONFIG_IP_NF_SET_IPPORTHASH) += ip_set_ipporthash.o -+obj-$(CONFIG_IP_NF_SET_IPPORTIPHASH) += ip_set_ipportiphash.o -+obj-$(CONFIG_IP_NF_SET_IPPORTNETHASH) += ip_set_ipportnethash.o -+obj-$(CONFIG_IP_NF_SET_IPTREE) += ip_set_iptree.o -+obj-$(CONFIG_IP_NF_SET_IPTREEMAP) += ip_set_iptreemap.o -+obj-$(CONFIG_IP_NF_SET_SETLIST) += ip_set_setlist.o - - # generic ARP tables - obj-$(CONFIG_IP_NF_ARPTABLES) += arp_tables.o diff --git a/target/linux/generic-2.6/patches-2.6.28/150-netfilter_imq.patch b/target/linux/generic-2.6/patches-2.6.28/150-netfilter_imq.patch deleted file mode 100644 index 50e0efdbc..000000000 --- a/target/linux/generic-2.6/patches-2.6.28/150-netfilter_imq.patch +++ /dev/null @@ -1,1256 +0,0 @@ ---- /dev/null -+++ b/drivers/net/imq.c -@@ -0,0 +1,567 @@ -+/* -+ * Pseudo-driver for the intermediate queue device. -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License -+ * as published by the Free Software Foundation; either version -+ * 2 of the License, or (at your option) any later version. -+ * -+ * Authors: Patrick McHardy, -+ * -+ * The first version was written by Martin Devera, -+ * -+ * Credits: Jan Rafaj -+ * - Update patch to 2.4.21 -+ * Sebastian Strollo -+ * - Fix "Dead-loop on netdevice imq"-issue -+ * Marcel Sebek -+ * - Update to 2.6.2-rc1 -+ * -+ * After some time of inactivity there is a group taking care -+ * of IMQ again: http://www.linuximq.net -+ * -+ * -+ * 2004/06/30 - New version of IMQ patch to kernels <=2.6.7 -+ * including the following changes: -+ * -+ * - Correction of ipv6 support "+"s issue (Hasso Tepper) -+ * - Correction of imq_init_devs() issue that resulted in -+ * kernel OOPS unloading IMQ as module (Norbert Buchmuller) -+ * - Addition of functionality to choose number of IMQ devices -+ * during kernel config (Andre Correa) -+ * - Addition of functionality to choose how IMQ hooks on -+ * PRE and POSTROUTING (after or before NAT) (Andre Correa) -+ * - Cosmetic corrections (Norbert Buchmuller) (Andre Correa) -+ * -+ * -+ * 2005/12/16 - IMQ versions between 2.6.7 and 2.6.13 were -+ * released with almost no problems. 2.6.14-x was released -+ * with some important changes: nfcache was removed; After -+ * some weeks of trouble we figured out that some IMQ fields -+ * in skb were missing in skbuff.c - skb_clone and copy_skb_header. -+ * These functions are correctly patched by this new patch version. -+ * -+ * Thanks for all who helped to figure out all the problems with -+ * 2.6.14.x: Patrick McHardy, Rune Kock, VeNoMouS, Max CtRiX, -+ * Kevin Shanahan, Richard Lucassen, Valery Dachev (hopefully -+ * I didn't forget anybody). I apologize again for my lack of time. -+ * -+ * -+ * 2008/06/17 - 2.6.25 - Changed imq.c to use qdisc_run() instead -+ * of qdisc_restart() and moved qdisc_run() to tasklet to avoid -+ * recursive locking. New initialization routines to fix 'rmmod' not -+ * working anymore. Used code from ifb.c. (Jussi Kivilinna) -+ * -+ * 2008/08/06 - 2.6.26 - (JK) -+ * - Replaced tasklet with 'netif_schedule()'. -+ * - Cleaned up and added comments for imq_nf_queue(). -+ * -+ * 2009/04/12 -+ * - Add skb_save_cb/skb_restore_cb helper functions for backuping -+ * control buffer. This is needed because qdisc-layer on kernels -+ * 2.6.27 and newer overwrite control buffer. (Jussi Kivilinna) -+ * - Add better locking for IMQ device. Hopefully this will solve -+ * SMP issues. (Jussi Kivilinna) -+ * - Port to 2.6.27 -+ * - Port to 2.6.28 -+ * -+ * 2009/04/20 - (Jussi Kivilinna) -+ * - Fix rmmod not working -+ * - Use netdevice feature flags to avoid extra packet handling -+ * by core networking layer and possibly increase performance. -+ * -+ * Also, many thanks to pablo Sebastian Greco for making the initial -+ * patch and to those who helped the testing. -+ * -+ * More info at: http://www.linuximq.net/ (Andre Correa) -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) -+ #include -+#endif -+#include -+#include -+#include -+ -+static nf_hookfn imq_nf_hook; -+ -+static struct nf_hook_ops imq_ingress_ipv4 = { -+ .hook = imq_nf_hook, -+ .owner = THIS_MODULE, -+ .pf = PF_INET, -+ .hooknum = NF_INET_PRE_ROUTING, -+#if defined(CONFIG_IMQ_BEHAVIOR_BA) || defined(CONFIG_IMQ_BEHAVIOR_BB) -+ .priority = NF_IP_PRI_MANGLE + 1 -+#else -+ .priority = NF_IP_PRI_NAT_DST + 1 -+#endif -+}; -+ -+static struct nf_hook_ops imq_egress_ipv4 = { -+ .hook = imq_nf_hook, -+ .owner = THIS_MODULE, -+ .pf = PF_INET, -+ .hooknum = NF_INET_POST_ROUTING, -+#if defined(CONFIG_IMQ_BEHAVIOR_AA) || defined(CONFIG_IMQ_BEHAVIOR_BA) -+ .priority = NF_IP_PRI_LAST -+#else -+ .priority = NF_IP_PRI_NAT_SRC - 1 -+#endif -+}; -+ -+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) -+static struct nf_hook_ops imq_ingress_ipv6 = { -+ .hook = imq_nf_hook, -+ .owner = THIS_MODULE, -+ .pf = PF_INET6, -+ .hooknum = NF_INET_PRE_ROUTING, -+#if defined(CONFIG_IMQ_BEHAVIOR_BA) || defined(CONFIG_IMQ_BEHAVIOR_BB) -+ .priority = NF_IP6_PRI_MANGLE + 1 -+#else -+ .priority = NF_IP6_PRI_NAT_DST + 1 -+#endif -+}; -+ -+static struct nf_hook_ops imq_egress_ipv6 = { -+ .hook = imq_nf_hook, -+ .owner = THIS_MODULE, -+ .pf = PF_INET6, -+ .hooknum = NF_INET_POST_ROUTING, -+#if defined(CONFIG_IMQ_BEHAVIOR_AA) || defined(CONFIG_IMQ_BEHAVIOR_BA) -+ .priority = NF_IP6_PRI_LAST -+#else -+ .priority = NF_IP6_PRI_NAT_SRC - 1 -+#endif -+}; -+#endif -+ -+#if defined(CONFIG_IMQ_NUM_DEVS) -+static unsigned int numdevs = CONFIG_IMQ_NUM_DEVS; -+#else -+static unsigned int numdevs = IMQ_MAX_DEVS; -+#endif -+ -+static DEFINE_SPINLOCK(imq_nf_queue_lock); -+ -+static struct net_device *imq_devs_cache[IMQ_MAX_DEVS]; -+ -+ -+static struct net_device_stats *imq_get_stats(struct net_device *dev) -+{ -+ return &dev->stats; -+} -+ -+/* called for packets kfree'd in qdiscs at places other than enqueue */ -+static void imq_skb_destructor(struct sk_buff *skb) -+{ -+ struct nf_queue_entry *entry = skb->nf_queue_entry; -+ -+ if (entry) { -+ nf_queue_entry_release_refs(entry); -+ kfree(entry); -+ } -+ -+ skb_restore_cb(skb); /* kfree backup */ -+} -+ -+static void imq_nf_reinject(struct nf_queue_entry *entry, unsigned int verdict) -+{ -+ int status; -+ -+ if (!entry->next_outfn) { -+ spin_lock_bh(&imq_nf_queue_lock); -+ nf_reinject(entry, verdict); -+ spin_unlock_bh(&imq_nf_queue_lock); -+ return; -+ } -+ -+ rcu_read_lock(); -+ local_bh_disable(); -+ status = entry->next_outfn(entry, entry->next_queuenum); -+ local_bh_enable(); -+ if (status < 0) { -+ nf_queue_entry_release_refs(entry); -+ kfree_skb(entry->skb); -+ kfree(entry); -+ } -+ -+ rcu_read_unlock(); -+} -+ -+static int imq_dev_xmit(struct sk_buff *skb, struct net_device *dev) -+{ -+ dev->stats.tx_bytes += skb->len; -+ dev->stats.tx_packets++; -+ -+ skb->imq_flags = 0; -+ skb->destructor = NULL; -+ -+ skb_restore_cb(skb); /* restore skb->cb */ -+ -+ dev->trans_start = jiffies; -+ imq_nf_reinject(skb->nf_queue_entry, NF_ACCEPT); -+ return 0; -+} -+ -+static int imq_nf_queue(struct nf_queue_entry *entry, unsigned queue_num) -+{ -+ struct net_device *dev; -+ struct sk_buff *skb_orig, *skb, *skb_shared; -+ struct Qdisc *q; -+ struct netdev_queue *txq; -+ int users, index; -+ int retval = -EINVAL; -+ -+ index = entry->skb->imq_flags & IMQ_F_IFMASK; -+ if (unlikely(index > numdevs - 1)) { -+ if (net_ratelimit()) -+ printk(KERN_WARNING -+ "IMQ: invalid device specified, highest is %u\n", -+ numdevs - 1); -+ retval = -EINVAL; -+ goto out; -+ } -+ -+ /* check for imq device by index from cache */ -+ dev = imq_devs_cache[index]; -+ if (unlikely(!dev)) { -+ char buf[8]; -+ -+ /* get device by name and cache result */ -+ snprintf(buf, sizeof(buf), "imq%d", index); -+ dev = dev_get_by_name(&init_net, buf); -+ if (!dev) { -+ /* not found ?!*/ -+ BUG(); -+ retval = -ENODEV; -+ goto out; -+ } -+ -+ imq_devs_cache[index] = dev; -+ dev_put(dev); -+ } -+ -+ if (unlikely(!(dev->flags & IFF_UP))) { -+ entry->skb->imq_flags = 0; -+ imq_nf_reinject(entry, NF_ACCEPT); -+ retval = 0; -+ goto out; -+ } -+ dev->last_rx = jiffies; -+ -+ skb = entry->skb; -+ skb_orig = NULL; -+ -+ /* skb has owner? => make clone */ -+ if (unlikely(skb->destructor)) { -+ skb_orig = skb; -+ skb = skb_clone(skb, GFP_ATOMIC); -+ if (!skb) { -+ retval = -ENOMEM; -+ goto out; -+ } -+ entry->skb = skb; -+ } -+ -+ skb->nf_queue_entry = entry; -+ -+ dev->stats.rx_bytes += skb->len; -+ dev->stats.rx_packets++; -+ -+ txq = dev_pick_tx(dev, skb); -+ -+ q = rcu_dereference(txq->qdisc); -+ if (unlikely(!q->enqueue)) -+ goto packet_not_eaten_by_imq_dev; -+ -+ spin_lock_bh(qdisc_lock(q)); -+ -+ users = atomic_read(&skb->users); -+ -+ skb_shared = skb_get(skb); /* increase reference count by one */ -+ skb_save_cb(skb_shared); /* backup skb->cb, as qdisc layer will -+ overwrite it */ -+ qdisc_enqueue_root(skb_shared, q); /* might kfree_skb */ -+ -+ if (likely(atomic_read(&skb_shared->users) == users + 1)) { -+ kfree_skb(skb_shared); /* decrease reference count by one */ -+ -+ skb->destructor = &imq_skb_destructor; -+ -+ /* cloned? */ -+ if (skb_orig) -+ kfree_skb(skb_orig); /* free original */ -+ -+ spin_unlock_bh(qdisc_lock(q)); -+ -+ /* schedule qdisc dequeue */ -+ __netif_schedule(q); -+ -+ retval = 0; -+ goto out; -+ } else { -+ skb_restore_cb(skb_shared); /* restore skb->cb */ -+ /* qdisc dropped packet and decreased skb reference count of -+ * skb, so we don't really want to and try refree as that would -+ * actually destroy the skb. */ -+ spin_unlock_bh(qdisc_lock(q)); -+ goto packet_not_eaten_by_imq_dev; -+ } -+ -+packet_not_eaten_by_imq_dev: -+ /* cloned? restore original */ -+ if (skb_orig) { -+ kfree_skb(skb); -+ entry->skb = skb_orig; -+ } -+ retval = -1; -+out: -+ return retval; -+} -+ -+static struct nf_queue_handler nfqh = { -+ .name = "imq", -+ .outfn = imq_nf_queue, -+}; -+ -+static unsigned int imq_nf_hook(unsigned int hook, struct sk_buff *pskb, -+ const struct net_device *indev, -+ const struct net_device *outdev, -+ int (*okfn)(struct sk_buff *)) -+{ -+ if (pskb->imq_flags & IMQ_F_ENQUEUE) -+ return NF_QUEUE; -+ -+ return NF_ACCEPT; -+} -+ -+static int imq_close(struct net_device *dev) -+{ -+ netif_stop_queue(dev); -+ return 0; -+} -+ -+static int imq_open(struct net_device *dev) -+{ -+ netif_start_queue(dev); -+ return 0; -+} -+ -+static void imq_setup(struct net_device *dev) -+{ -+ dev->hard_start_xmit = imq_dev_xmit; -+ dev->open = imq_open; -+ dev->get_stats = imq_get_stats; -+ dev->stop = imq_close; -+ dev->type = ARPHRD_VOID; -+ dev->mtu = 16000; -+ dev->tx_queue_len = 11000; -+ dev->flags = IFF_NOARP; -+ dev->features = NETIF_F_SG | NETIF_F_FRAGLIST | -+ NETIF_F_GSO | NETIF_F_HW_CSUM | -+ NETIF_F_HIGHDMA; -+} -+ -+static int imq_validate(struct nlattr *tb[], struct nlattr *data[]) -+{ -+ int ret = 0; -+ -+ if (tb[IFLA_ADDRESS]) { -+ if (nla_len(tb[IFLA_ADDRESS]) != ETH_ALEN) { -+ ret = -EINVAL; -+ goto end; -+ } -+ if (!is_valid_ether_addr(nla_data(tb[IFLA_ADDRESS]))) { -+ ret = -EADDRNOTAVAIL; -+ goto end; -+ } -+ } -+ return 0; -+end: -+ printk(KERN_WARNING "IMQ: imq_validate failed (%d)\n", ret); -+ return ret; -+} -+ -+static struct rtnl_link_ops imq_link_ops __read_mostly = { -+ .kind = "imq", -+ .priv_size = 0, -+ .setup = imq_setup, -+ .validate = imq_validate, -+}; -+ -+static int __init imq_init_hooks(void) -+{ -+ int err; -+ -+ nf_register_queue_imq_handler(&nfqh); -+ -+ err = nf_register_hook(&imq_ingress_ipv4); -+ if (err) -+ goto err1; -+ -+ err = nf_register_hook(&imq_egress_ipv4); -+ if (err) -+ goto err2; -+ -+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) -+ err = nf_register_hook(&imq_ingress_ipv6); -+ if (err) -+ goto err3; -+ -+ err = nf_register_hook(&imq_egress_ipv6); -+ if (err) -+ goto err4; -+#endif -+ -+ return 0; -+ -+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) -+err4: -+ nf_unregister_hook(&imq_ingress_ipv6); -+err3: -+ nf_unregister_hook(&imq_egress_ipv4); -+#endif -+err2: -+ nf_unregister_hook(&imq_ingress_ipv4); -+err1: -+ nf_unregister_queue_imq_handler(); -+ return err; -+} -+ -+static int __init imq_init_one(int index) -+{ -+ struct net_device *dev; -+ int ret; -+ -+ dev = alloc_netdev(0, "imq%d", imq_setup); -+ if (!dev) -+ return -ENOMEM; -+ -+ ret = dev_alloc_name(dev, dev->name); -+ if (ret < 0) -+ goto fail; -+ -+ dev->rtnl_link_ops = &imq_link_ops; -+ ret = register_netdevice(dev); -+ if (ret < 0) -+ goto fail; -+ -+ return 0; -+fail: -+ free_netdev(dev); -+ return ret; -+} -+ -+static int __init imq_init_devs(void) -+{ -+ int err, i; -+ -+ if (numdevs < 1 || numdevs > IMQ_MAX_DEVS) { -+ printk(KERN_ERR "IMQ: numdevs has to be betweed 1 and %u\n", -+ IMQ_MAX_DEVS); -+ return -EINVAL; -+ } -+ -+ rtnl_lock(); -+ err = __rtnl_link_register(&imq_link_ops); -+ -+ for (i = 0; i < numdevs && !err; i++) -+ err = imq_init_one(i); -+ -+ if (err) { -+ __rtnl_link_unregister(&imq_link_ops); -+ memset(imq_devs_cache, 0, sizeof(imq_devs_cache)); -+ } -+ rtnl_unlock(); -+ -+ return err; -+} -+ -+static int __init imq_init_module(void) -+{ -+ int err; -+ -+#if defined(CONFIG_IMQ_NUM_DEVS) -+ BUILD_BUG_ON(CONFIG_IMQ_NUM_DEVS > 16); -+ BUILD_BUG_ON(CONFIG_IMQ_NUM_DEVS < 2); -+ BUILD_BUG_ON(CONFIG_IMQ_NUM_DEVS - 1 > IMQ_F_IFMASK); -+#endif -+ -+ err = imq_init_devs(); -+ if (err) { -+ printk(KERN_ERR "IMQ: Error trying imq_init_devs(net)\n"); -+ return err; -+ } -+ -+ err = imq_init_hooks(); -+ if (err) { -+ printk(KERN_ERR "IMQ: Error trying imq_init_hooks()\n"); -+ rtnl_link_unregister(&imq_link_ops); -+ memset(imq_devs_cache, 0, sizeof(imq_devs_cache)); -+ return err; -+ } -+ -+ printk(KERN_INFO "IMQ driver loaded successfully.\n"); -+ -+#if defined(CONFIG_IMQ_BEHAVIOR_BA) || defined(CONFIG_IMQ_BEHAVIOR_BB) -+ printk(KERN_INFO "\tHooking IMQ before NAT on PREROUTING.\n"); -+#else -+ printk(KERN_INFO "\tHooking IMQ after NAT on PREROUTING.\n"); -+#endif -+#if defined(CONFIG_IMQ_BEHAVIOR_AB) || defined(CONFIG_IMQ_BEHAVIOR_BB) -+ printk(KERN_INFO "\tHooking IMQ before NAT on POSTROUTING.\n"); -+#else -+ printk(KERN_INFO "\tHooking IMQ after NAT on POSTROUTING.\n"); -+#endif -+ -+ return 0; -+} -+ -+static void __exit imq_unhook(void) -+{ -+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) -+ nf_unregister_hook(&imq_ingress_ipv6); -+ nf_unregister_hook(&imq_egress_ipv6); -+#endif -+ nf_unregister_hook(&imq_ingress_ipv4); -+ nf_unregister_hook(&imq_egress_ipv4); -+ -+ nf_unregister_queue_imq_handler(); -+} -+ -+static void __exit imq_cleanup_devs(void) -+{ -+ rtnl_link_unregister(&imq_link_ops); -+ memset(imq_devs_cache, 0, sizeof(imq_devs_cache)); -+} -+ -+static void __exit imq_exit_module(void) -+{ -+ imq_unhook(); -+ imq_cleanup_devs(); -+ printk(KERN_INFO "IMQ driver unloaded successfully.\n"); -+} -+ -+module_init(imq_init_module); -+module_exit(imq_exit_module); -+ -+module_param(numdevs, int, 0); -+MODULE_PARM_DESC(numdevs, "number of IMQ devices (how many imq* devices will " -+ "be created)"); -+MODULE_AUTHOR("http://www.linuximq.net"); -+MODULE_DESCRIPTION("Pseudo-driver for the intermediate queue device. See " -+ "http://www.linuximq.net/ for more information."); -+MODULE_LICENSE("GPL"); -+MODULE_ALIAS_RTNL_LINK("imq"); -+ ---- a/drivers/net/Kconfig -+++ b/drivers/net/Kconfig -@@ -109,6 +109,129 @@ config EQUALIZER - To compile this driver as a module, choose M here: the module - will be called eql. If unsure, say N. - -+config IMQ -+ tristate "IMQ (intermediate queueing device) support" -+ depends on NETDEVICES && NETFILTER -+ ---help--- -+ The IMQ device(s) is used as placeholder for QoS queueing -+ disciplines. Every packet entering/leaving the IP stack can be -+ directed through the IMQ device where it's enqueued/dequeued to the -+ attached qdisc. This allows you to treat network devices as classes -+ and distribute bandwidth among them. Iptables is used to specify -+ through which IMQ device, if any, packets travel. -+ -+ More information at: http://www.linuximq.net/ -+ -+ To compile this driver as a module, choose M here: the module -+ will be called imq. If unsure, say N. -+ -+choice -+ prompt "IMQ behavior (PRE/POSTROUTING)" -+ depends on IMQ -+ default IMQ_BEHAVIOR_AB -+ help -+ -+ This settings defines how IMQ behaves in respect to its -+ hooking in PREROUTING and POSTROUTING. -+ -+ IMQ can work in any of the following ways: -+ -+ PREROUTING | POSTROUTING -+ -----------------|------------------- -+ #1 After NAT | After NAT -+ #2 After NAT | Before NAT -+ #3 Before NAT | After NAT -+ #4 Before NAT | Before NAT -+ -+ The default behavior is to hook before NAT on PREROUTING -+ and after NAT on POSTROUTING (#3). -+ -+ This settings are specially usefull when trying to use IMQ -+ to shape NATed clients. -+ -+ More information can be found at: www.linuximq.net -+ -+ If not sure leave the default settings alone. -+ -+config IMQ_BEHAVIOR_AA -+ bool "IMQ AA" -+ help -+ This settings defines how IMQ behaves in respect to its -+ hooking in PREROUTING and POSTROUTING. -+ -+ Choosing this option will make IMQ hook like this: -+ -+ PREROUTING: After NAT -+ POSTROUTING: After NAT -+ -+ More information can be found at: www.linuximq.net -+ -+ If not sure leave the default settings alone. -+ -+config IMQ_BEHAVIOR_AB -+ bool "IMQ AB" -+ help -+ This settings defines how IMQ behaves in respect to its -+ hooking in PREROUTING and POSTROUTING. -+ -+ Choosing this option will make IMQ hook like this: -+ -+ PREROUTING: After NAT -+ POSTROUTING: Before NAT -+ -+ More information can be found at: www.linuximq.net -+ -+ If not sure leave the default settings alone. -+ -+config IMQ_BEHAVIOR_BA -+ bool "IMQ BA" -+ help -+ This settings defines how IMQ behaves in respect to its -+ hooking in PREROUTING and POSTROUTING. -+ -+ Choosing this option will make IMQ hook like this: -+ -+ PREROUTING: Before NAT -+ POSTROUTING: After NAT -+ -+ More information can be found at: www.linuximq.net -+ -+ If not sure leave the default settings alone. -+ -+config IMQ_BEHAVIOR_BB -+ bool "IMQ BB" -+ help -+ This settings defines how IMQ behaves in respect to its -+ hooking in PREROUTING and POSTROUTING. -+ -+ Choosing this option will make IMQ hook like this: -+ -+ PREROUTING: Before NAT -+ POSTROUTING: Before NAT -+ -+ More information can be found at: www.linuximq.net -+ -+ If not sure leave the default settings alone. -+ -+endchoice -+ -+config IMQ_NUM_DEVS -+ -+ int "Number of IMQ devices" -+ range 2 16 -+ depends on IMQ -+ default "16" -+ help -+ -+ This settings defines how many IMQ devices will be -+ created. -+ -+ The default value is 16. -+ -+ More information can be found at: www.linuximq.net -+ -+ If not sure leave the default settings alone. -+ - config TUN - tristate "Universal TUN/TAP device driver support" - select CRC32 ---- a/drivers/net/Makefile -+++ b/drivers/net/Makefile -@@ -148,6 +148,7 @@ obj-$(CONFIG_SLHC) += slhc.o - obj-$(CONFIG_XEN_NETDEV_FRONTEND) += xen-netfront.o - - obj-$(CONFIG_DUMMY) += dummy.o -+obj-$(CONFIG_IMQ) += imq.o - obj-$(CONFIG_IFB) += ifb.o - obj-$(CONFIG_MACVLAN) += macvlan.o - obj-$(CONFIG_DE600) += de600.o ---- /dev/null -+++ b/include/linux/imq.h -@@ -0,0 +1,13 @@ -+#ifndef _IMQ_H -+#define _IMQ_H -+ -+/* IFMASK (16 device indexes, 0 to 15) and flag(s) fit in 5 bits */ -+#define IMQ_F_BITS 5 -+ -+#define IMQ_F_IFMASK 0x0f -+#define IMQ_F_ENQUEUE 0x10 -+ -+#define IMQ_MAX_DEVS (IMQ_F_IFMASK + 1) -+ -+#endif /* _IMQ_H */ -+ ---- /dev/null -+++ b/include/linux/netfilter_ipv4/ipt_IMQ.h -@@ -0,0 +1,10 @@ -+#ifndef _IPT_IMQ_H -+#define _IPT_IMQ_H -+ -+/* Backwards compatibility for old userspace */ -+#include -+ -+#define ipt_imq_info xt_imq_info -+ -+#endif /* _IPT_IMQ_H */ -+ ---- /dev/null -+++ b/include/linux/netfilter_ipv6/ip6t_IMQ.h -@@ -0,0 +1,10 @@ -+#ifndef _IP6T_IMQ_H -+#define _IP6T_IMQ_H -+ -+/* Backwards compatibility for old userspace */ -+#include -+ -+#define ip6t_imq_info xt_imq_info -+ -+#endif /* _IP6T_IMQ_H */ -+ ---- a/include/linux/skbuff.h -+++ b/include/linux/skbuff.h -@@ -28,6 +28,9 @@ - #include - #include - #include -+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE) -+#include -+#endif - - #define HAVE_ALLOC_SKB /* For the drivers to know */ - #define HAVE_ALIGNABLE_SKB /* Ditto 8) */ -@@ -278,6 +281,9 @@ struct sk_buff { - * first. This is owned by whoever has the skb queued ATM. - */ - char cb[48]; -+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE) -+ void *cb_next; -+#endif - - unsigned int len, - data_len; -@@ -308,6 +314,9 @@ struct sk_buff { - struct nf_conntrack *nfct; - struct sk_buff *nfct_reasm; - #endif -+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE) -+ struct nf_queue_entry *nf_queue_entry; -+#endif - #ifdef CONFIG_BRIDGE_NETFILTER - struct nf_bridge_info *nf_bridge; - #endif -@@ -327,6 +336,9 @@ struct sk_buff { - __u8 do_not_encrypt:1; - #endif - /* 0/13/14 bit hole */ -+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE) -+ __u8 imq_flags:IMQ_F_BITS; -+#endif - - #ifdef CONFIG_NET_DMA - dma_cookie_t dma_cookie; -@@ -367,6 +379,12 @@ extern void skb_dma_unmap(struct device - enum dma_data_direction dir); - #endif - -+ -+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE) -+extern int skb_save_cb(struct sk_buff *skb); -+extern int skb_restore_cb(struct sk_buff *skb); -+#endif -+ - extern void kfree_skb(struct sk_buff *skb); - extern void __kfree_skb(struct sk_buff *skb); - extern struct sk_buff *__alloc_skb(unsigned int size, -@@ -1804,6 +1822,10 @@ static inline void __nf_copy(struct sk_b - dst->nfct_reasm = src->nfct_reasm; - nf_conntrack_get_reasm(src->nfct_reasm); - #endif -+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE) -+ dst->imq_flags = src->imq_flags; -+ dst->nf_queue_entry = src->nf_queue_entry; -+#endif - #ifdef CONFIG_BRIDGE_NETFILTER - dst->nf_bridge = src->nf_bridge; - nf_bridge_get(src->nf_bridge); ---- a/net/core/dev.c -+++ b/net/core/dev.c -@@ -96,6 +96,9 @@ - #include - #include - #include -+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE) -+#include -+#endif - #include - #include - #include -@@ -1655,7 +1658,11 @@ int dev_hard_start_xmit(struct sk_buff * - struct netdev_queue *txq) - { - if (likely(!skb->next)) { -- if (!list_empty(&ptype_all)) -+ if (!list_empty(&ptype_all) -+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE) -+ && !(skb->imq_flags & IMQ_F_ENQUEUE) -+#endif -+ ) - dev_queue_xmit_nit(skb, dev); - - if (netif_needs_gso(dev, skb)) { -@@ -1746,8 +1753,7 @@ static u16 simple_tx_hash(struct net_dev - return (u16) (((u64) hash * dev->real_num_tx_queues) >> 32); - } - --static struct netdev_queue *dev_pick_tx(struct net_device *dev, -- struct sk_buff *skb) -+struct netdev_queue *dev_pick_tx(struct net_device *dev, struct sk_buff *skb) - { - u16 queue_index = 0; - -@@ -1759,6 +1765,7 @@ static struct netdev_queue *dev_pick_tx( - skb_set_queue_mapping(skb, queue_index); - return netdev_get_tx_queue(dev, queue_index); - } -+EXPORT_SYMBOL(dev_pick_tx); - - /** - * dev_queue_xmit - transmit a buffer ---- a/include/linux/netdevice.h -+++ b/include/linux/netdevice.h -@@ -950,6 +950,7 @@ extern int dev_alloc_name(struct net_de - extern int dev_open(struct net_device *dev); - extern int dev_close(struct net_device *dev); - extern void dev_disable_lro(struct net_device *dev); -+extern struct netdev_queue *dev_pick_tx(struct net_device *dev, struct sk_buff *skb); - extern int dev_queue_xmit(struct sk_buff *skb); - extern int register_netdevice(struct net_device *dev); - extern void unregister_netdevice(struct net_device *dev); ---- /dev/null -+++ b/include/linux/netfilter/xt_IMQ.h -@@ -0,0 +1,9 @@ -+#ifndef _XT_IMQ_H -+#define _XT_IMQ_H -+ -+struct xt_imq_info { -+ unsigned int todev; /* target imq device */ -+}; -+ -+#endif /* _XT_IMQ_H */ -+ ---- a/include/net/netfilter/nf_queue.h -+++ b/include/net/netfilter/nf_queue.h -@@ -13,6 +13,12 @@ struct nf_queue_entry { - struct net_device *indev; - struct net_device *outdev; - int (*okfn)(struct sk_buff *); -+ -+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE) -+ int (*next_outfn)(struct nf_queue_entry *entry, -+ unsigned int queuenum); -+ unsigned int next_queuenum; -+#endif - }; - - #define nf_queue_entry_reroute(x) ((void *)x + sizeof(struct nf_queue_entry)) -@@ -30,5 +36,11 @@ extern int nf_unregister_queue_handler(u - const struct nf_queue_handler *qh); - extern void nf_unregister_queue_handlers(const struct nf_queue_handler *qh); - extern void nf_reinject(struct nf_queue_entry *entry, unsigned int verdict); -+extern void nf_queue_entry_release_refs(struct nf_queue_entry *entry); -+ -+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE) -+extern void nf_register_queue_imq_handler(const struct nf_queue_handler *qh); -+extern void nf_unregister_queue_imq_handler(void); -+#endif - - #endif /* _NF_QUEUE_H */ ---- a/net/core/skbuff.c -+++ b/net/core/skbuff.c -@@ -69,6 +69,9 @@ - - static struct kmem_cache *skbuff_head_cache __read_mostly; - static struct kmem_cache *skbuff_fclone_cache __read_mostly; -+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE) -+static struct kmem_cache *skbuff_cb_store_cache __read_mostly; -+#endif - - static void sock_pipe_buf_release(struct pipe_inode_info *pipe, - struct pipe_buffer *buf) -@@ -88,6 +91,80 @@ static int sock_pipe_buf_steal(struct pi - return 1; - } - -+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE) -+/* Control buffer save/restore for IMQ devices */ -+struct skb_cb_table { -+ void *cb_next; -+ atomic_t refcnt; -+ char cb[48]; -+}; -+ -+static DEFINE_SPINLOCK(skb_cb_store_lock); -+ -+int skb_save_cb(struct sk_buff *skb) -+{ -+ struct skb_cb_table *next; -+ -+ next = kmem_cache_alloc(skbuff_cb_store_cache, GFP_ATOMIC); -+ if (!next) -+ return -ENOMEM; -+ -+ BUILD_BUG_ON(sizeof(skb->cb) != sizeof(next->cb)); -+ -+ memcpy(next->cb, skb->cb, sizeof(skb->cb)); -+ next->cb_next = skb->cb_next; -+ -+ atomic_set(&next->refcnt, 1); -+ -+ skb->cb_next = next; -+ return 0; -+} -+EXPORT_SYMBOL(skb_save_cb); -+ -+int skb_restore_cb(struct sk_buff *skb) -+{ -+ struct skb_cb_table *next; -+ -+ if (!skb->cb_next) -+ return 0; -+ -+ next = skb->cb_next; -+ -+ BUILD_BUG_ON(sizeof(skb->cb) != sizeof(next->cb)); -+ -+ memcpy(skb->cb, next->cb, sizeof(skb->cb)); -+ skb->cb_next = next->cb_next; -+ -+ spin_lock(&skb_cb_store_lock); -+ -+ if (atomic_dec_and_test(&next->refcnt)) { -+ kmem_cache_free(skbuff_cb_store_cache, next); -+ } -+ -+ spin_unlock(&skb_cb_store_lock); -+ -+ return 0; -+} -+EXPORT_SYMBOL(skb_restore_cb); -+ -+static void skb_copy_stored_cb(struct sk_buff *new, struct sk_buff *old) -+{ -+ struct skb_cb_table *next; -+ -+ if (!old->cb_next) { -+ new->cb_next = 0; -+ return; -+ } -+ -+ spin_lock(&skb_cb_store_lock); -+ -+ next = old->cb_next; -+ atomic_inc(&next->refcnt); -+ new->cb_next = next; -+ -+ spin_unlock(&skb_cb_store_lock); -+} -+#endif - - /* Pipe buffer operations for a socket. */ - static struct pipe_buf_operations sock_pipe_buf_ops = { -@@ -381,6 +458,15 @@ static void skb_release_head_state(struc - WARN_ON(in_irq()); - skb->destructor(skb); - } -+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE) -+ /* This should not happen. When it does, avoid memleak by restoring -+ the chain of cb-backups. */ -+ while(skb->cb_next != NULL) { -+ printk(KERN_WARNING "kfree_skb: skb->cb_next: %08x\n", -+ skb->cb_next); -+ skb_restore_cb(skb); -+ } -+#endif - #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE) - nf_conntrack_put(skb->nfct); - nf_conntrack_put_reasm(skb->nfct_reasm); -@@ -493,6 +579,9 @@ static void __copy_skb_header(struct sk_ - new->sp = secpath_get(old->sp); - #endif - memcpy(new->cb, old->cb, sizeof(old->cb)); -+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE) -+ skb_copy_stored_cb(new, old); -+#endif - new->csum_start = old->csum_start; - new->csum_offset = old->csum_offset; - new->local_df = old->local_df; -@@ -2397,6 +2486,13 @@ void __init skb_init(void) - 0, - SLAB_HWCACHE_ALIGN|SLAB_PANIC, - NULL); -+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE) -+ skbuff_cb_store_cache = kmem_cache_create("skbuff_cb_store_cache", -+ sizeof(struct skb_cb_table), -+ 0, -+ SLAB_HWCACHE_ALIGN|SLAB_PANIC, -+ NULL); -+#endif - } - - /** ---- a/net/netfilter/Kconfig -+++ b/net/netfilter/Kconfig -@@ -357,6 +357,18 @@ config NETFILTER_XT_TARGET_DSCP - - To compile it as a module, choose M here. If unsure, say N. - -+config NETFILTER_XT_TARGET_IMQ -+ tristate '"IMQ" target support' -+ depends on NETFILTER_XTABLES -+ depends on IP_NF_MANGLE || IP6_NF_MANGLE -+ select IMQ -+ default m if NETFILTER_ADVANCED=n -+ help -+ This option adds a `IMQ' target which is used to specify if and -+ to which imq device packets should get enqueued/dequeued. -+ -+ To compile it as a module, choose M here. If unsure, say N. -+ - config NETFILTER_XT_TARGET_MARK - tristate '"MARK" target support' - default m if NETFILTER_ADVANCED=n ---- a/net/netfilter/Makefile -+++ b/net/netfilter/Makefile -@@ -45,6 +45,7 @@ obj-$(CONFIG_NETFILTER_XT_TARGET_CLASSIF - obj-$(CONFIG_NETFILTER_XT_TARGET_CONNMARK) += xt_CONNMARK.o - obj-$(CONFIG_NETFILTER_XT_TARGET_CONNSECMARK) += xt_CONNSECMARK.o - obj-$(CONFIG_NETFILTER_XT_TARGET_DSCP) += xt_DSCP.o -+obj-$(CONFIG_NETFILTER_XT_TARGET_IMQ) += xt_IMQ.o - obj-$(CONFIG_NETFILTER_XT_TARGET_MARK) += xt_MARK.o - obj-$(CONFIG_NETFILTER_XT_TARGET_NFLOG) += xt_NFLOG.o - obj-$(CONFIG_NETFILTER_XT_TARGET_NFQUEUE) += xt_NFQUEUE.o ---- a/net/netfilter/nf_queue.c -+++ b/net/netfilter/nf_queue.c -@@ -20,6 +20,26 @@ static const struct nf_queue_handler *qu - - static DEFINE_MUTEX(queue_handler_mutex); - -+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE) -+static const struct nf_queue_handler *queue_imq_handler; -+ -+void nf_register_queue_imq_handler(const struct nf_queue_handler *qh) -+{ -+ mutex_lock(&queue_handler_mutex); -+ rcu_assign_pointer(queue_imq_handler, qh); -+ mutex_unlock(&queue_handler_mutex); -+} -+EXPORT_SYMBOL(nf_register_queue_imq_handler); -+ -+void nf_unregister_queue_imq_handler(void) -+{ -+ mutex_lock(&queue_handler_mutex); -+ rcu_assign_pointer(queue_imq_handler, NULL); -+ mutex_unlock(&queue_handler_mutex); -+} -+EXPORT_SYMBOL(nf_unregister_queue_imq_handler); -+#endif -+ - /* return EBUSY when somebody else is registered, return EEXIST if the - * same handler is registered, return 0 in case of success. */ - int nf_register_queue_handler(u_int8_t pf, const struct nf_queue_handler *qh) -@@ -80,7 +100,7 @@ void nf_unregister_queue_handlers(const - } - EXPORT_SYMBOL_GPL(nf_unregister_queue_handlers); - --static void nf_queue_entry_release_refs(struct nf_queue_entry *entry) -+void nf_queue_entry_release_refs(struct nf_queue_entry *entry) - { - /* Release those devices we held, or Alexey will kill me. */ - if (entry->indev) -@@ -100,6 +120,7 @@ static void nf_queue_entry_release_refs( - /* Drop reference to owner of hook which queued us. */ - module_put(entry->elem->owner); - } -+EXPORT_SYMBOL_GPL(nf_queue_entry_release_refs); - - /* - * Any packet that leaves via this function must come back -@@ -121,12 +142,26 @@ static int __nf_queue(struct sk_buff *sk - #endif - const struct nf_afinfo *afinfo; - const struct nf_queue_handler *qh; -+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE) -+ const struct nf_queue_handler *qih = NULL; -+#endif - - /* QUEUE == DROP if noone is waiting, to be safe. */ - rcu_read_lock(); - - qh = rcu_dereference(queue_handler[pf]); -+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE) -+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) -+ if (pf == PF_INET || pf == PF_INET6) -+#else -+ if (pf == PF_INET) -+#endif -+ qih = rcu_dereference(queue_imq_handler); -+ -+ if (!qh && !qih) -+#else /* !IMQ */ - if (!qh) -+#endif - goto err_unlock; - - afinfo = nf_get_afinfo(pf); -@@ -145,6 +180,10 @@ static int __nf_queue(struct sk_buff *sk - .indev = indev, - .outdev = outdev, - .okfn = okfn, -+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE) -+ .next_outfn = qh ? qh->outfn : NULL, -+ .next_queuenum = queuenum, -+#endif - }; - - /* If it's going away, ignore hook. */ -@@ -170,8 +209,19 @@ static int __nf_queue(struct sk_buff *sk - } - #endif - afinfo->saveroute(skb, entry); -+ -+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE) -+ if (qih) { -+ status = qih->outfn(entry, queuenum); -+ goto imq_skip_queue; -+ } -+#endif -+ - status = qh->outfn(entry, queuenum); - -+#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE) -+imq_skip_queue: -+#endif - rcu_read_unlock(); - - if (status < 0) { ---- /dev/null -+++ b/net/netfilter/xt_IMQ.c -@@ -0,0 +1,73 @@ -+/* -+ * This target marks packets to be enqueued to an imq device -+ */ -+#include -+#include -+#include -+#include -+#include -+ -+static unsigned int imq_target(struct sk_buff *pskb, -+ const struct xt_target_param *par) -+{ -+ const struct xt_imq_info *mr = par->targinfo; -+ -+ pskb->imq_flags = (mr->todev & IMQ_F_IFMASK) | IMQ_F_ENQUEUE; -+ -+ return XT_CONTINUE; -+} -+ -+static bool imq_checkentry(const struct xt_tgchk_param *par) -+{ -+ struct xt_imq_info *mr = par->targinfo; -+ -+ if (mr->todev > IMQ_MAX_DEVS - 1) { -+ printk(KERN_WARNING -+ "IMQ: invalid device specified, highest is %u\n", -+ IMQ_MAX_DEVS - 1); -+ return 0; -+ } -+ -+ return 1; -+} -+ -+static struct xt_target xt_imq_reg[] __read_mostly = { -+ { -+ .name = "IMQ", -+ .family = AF_INET, -+ .checkentry = imq_checkentry, -+ .target = imq_target, -+ .targetsize = sizeof(struct xt_imq_info), -+ .table = "mangle", -+ .me = THIS_MODULE -+ }, -+ { -+ .name = "IMQ", -+ .family = AF_INET6, -+ .checkentry = imq_checkentry, -+ .target = imq_target, -+ .targetsize = sizeof(struct xt_imq_info), -+ .table = "mangle", -+ .me = THIS_MODULE -+ }, -+}; -+ -+static int __init imq_init(void) -+{ -+ return xt_register_targets(xt_imq_reg, ARRAY_SIZE(xt_imq_reg)); -+} -+ -+static void __exit imq_fini(void) -+{ -+ xt_unregister_targets(xt_imq_reg, ARRAY_SIZE(xt_imq_reg)); -+} -+ -+module_init(imq_init); -+module_exit(imq_fini); -+ -+MODULE_AUTHOR("http://www.linuximq.net"); -+MODULE_DESCRIPTION("Pseudo-driver for the intermediate queue device. See http://www.linuximq.net/ for more information."); -+MODULE_LICENSE("GPL"); -+MODULE_ALIAS("ipt_IMQ"); -+MODULE_ALIAS("ip6t_IMQ"); -+ diff --git a/target/linux/generic-2.6/patches-2.6.28/180-netfilter_depends.patch b/target/linux/generic-2.6/patches-2.6.28/180-netfilter_depends.patch deleted file mode 100644 index cdfc0b598..000000000 --- a/target/linux/generic-2.6/patches-2.6.28/180-netfilter_depends.patch +++ /dev/null @@ -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 -@@ -467,7 +466,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 diff --git a/target/linux/generic-2.6/patches-2.6.28/190-netfilter_rtsp.patch b/target/linux/generic-2.6/patches-2.6.28/190-netfilter_rtsp.patch deleted file mode 100644 index 29e82084c..000000000 --- a/target/linux/generic-2.6/patches-2.6.28/190-netfilter_rtsp.patch +++ /dev/null @@ -1,1366 +0,0 @@ ---- /dev/null -+++ b/include/linux/netfilter/nf_conntrack_rtsp.h -@@ -0,0 +1,63 @@ -+/* -+ * RTSP extension for IP connection tracking. -+ * (C) 2003 by Tom Marshall -+ * based on ip_conntrack_irc.h -+ * -+ * 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. -+ */ -+#ifndef _IP_CONNTRACK_RTSP_H -+#define _IP_CONNTRACK_RTSP_H -+ -+//#define IP_NF_RTSP_DEBUG 1 -+#define IP_NF_RTSP_VERSION "0.6.21" -+ -+#ifdef __KERNEL__ -+/* port block types */ -+typedef enum { -+ pb_single, /* client_port=x */ -+ pb_range, /* client_port=x-y */ -+ pb_discon /* client_port=x/y (rtspbis) */ -+} portblock_t; -+ -+/* We record seq number and length of rtsp headers here, all in host order. */ -+ -+/* -+ * This structure is per expected connection. It is a member of struct -+ * ip_conntrack_expect. The TCP SEQ for the conntrack expect is stored -+ * there and we are expected to only store the length of the data which -+ * needs replaced. If a packet contains multiple RTSP messages, we create -+ * one expected connection per message. -+ * -+ * We use these variables to mark the entire header block. This may seem -+ * like overkill, but the nature of RTSP requires it. A header may appear -+ * multiple times in a message. We must treat two Transport headers the -+ * same as one Transport header with two entries. -+ */ -+struct ip_ct_rtsp_expect -+{ -+ u_int32_t len; /* length of header block */ -+ portblock_t pbtype; /* Type of port block that was requested */ -+ u_int16_t loport; /* Port that was requested, low or first */ -+ u_int16_t hiport; /* Port that was requested, high or second */ -+#if 0 -+ uint method; /* RTSP method */ -+ uint cseq; /* CSeq from request */ -+#endif -+}; -+ -+extern unsigned int (*nf_nat_rtsp_hook)(struct sk_buff *skb, -+ enum ip_conntrack_info ctinfo, -+ unsigned int matchoff, unsigned int matchlen, -+ struct ip_ct_rtsp_expect *prtspexp, -+ struct nf_conntrack_expect *exp); -+ -+extern void (*nf_nat_rtsp_hook_expectfn)(struct nf_conn *ct, struct nf_conntrack_expect *exp); -+ -+#define RTSP_PORT 554 -+ -+#endif /* __KERNEL__ */ -+ -+#endif /* _IP_CONNTRACK_RTSP_H */ ---- /dev/null -+++ b/include/linux/netfilter_helpers.h -@@ -0,0 +1,133 @@ -+/* -+ * Helpers for netfiler modules. This file provides implementations for basic -+ * functions such as strncasecmp(), etc. -+ * -+ * gcc will warn for defined but unused functions, so we only include the -+ * functions requested. The following macros are used: -+ * NF_NEED_STRNCASECMP nf_strncasecmp() -+ * NF_NEED_STRTOU16 nf_strtou16() -+ * NF_NEED_STRTOU32 nf_strtou32() -+ */ -+#ifndef _NETFILTER_HELPERS_H -+#define _NETFILTER_HELPERS_H -+ -+/* Only include these functions for kernel code. */ -+#ifdef __KERNEL__ -+ -+#include -+#define iseol(c) ( (c) == '\r' || (c) == '\n' ) -+ -+/* -+ * The standard strncasecmp() -+ */ -+#ifdef NF_NEED_STRNCASECMP -+static int -+nf_strncasecmp(const char* s1, const char* s2, u_int32_t len) -+{ -+ if (s1 == NULL || s2 == NULL) -+ { -+ if (s1 == NULL && s2 == NULL) -+ { -+ return 0; -+ } -+ return (s1 == NULL) ? -1 : 1; -+ } -+ while (len > 0 && tolower(*s1) == tolower(*s2)) -+ { -+ len--; -+ s1++; -+ s2++; -+ } -+ return ( (len == 0) ? 0 : (tolower(*s1) - tolower(*s2)) ); -+} -+#endif /* NF_NEED_STRNCASECMP */ -+ -+/* -+ * Parse a string containing a 16-bit unsigned integer. -+ * Returns the number of chars used, or zero if no number is found. -+ */ -+#ifdef NF_NEED_STRTOU16 -+static int -+nf_strtou16(const char* pbuf, u_int16_t* pval) -+{ -+ int n = 0; -+ -+ *pval = 0; -+ while (isdigit(pbuf[n])) -+ { -+ *pval = (*pval * 10) + (pbuf[n] - '0'); -+ n++; -+ } -+ -+ return n; -+} -+#endif /* NF_NEED_STRTOU16 */ -+ -+/* -+ * Parse a string containing a 32-bit unsigned integer. -+ * Returns the number of chars used, or zero if no number is found. -+ */ -+#ifdef NF_NEED_STRTOU32 -+static int -+nf_strtou32(const char* pbuf, u_int32_t* pval) -+{ -+ int n = 0; -+ -+ *pval = 0; -+ while (pbuf[n] >= '0' && pbuf[n] <= '9') -+ { -+ *pval = (*pval * 10) + (pbuf[n] - '0'); -+ n++; -+ } -+ -+ return n; -+} -+#endif /* NF_NEED_STRTOU32 */ -+ -+/* -+ * Given a buffer and length, advance to the next line and mark the current -+ * line. -+ */ -+#ifdef NF_NEED_NEXTLINE -+static int -+nf_nextline(char* p, uint len, uint* poff, uint* plineoff, uint* plinelen) -+{ -+ uint off = *poff; -+ uint physlen = 0; -+ -+ if (off >= len) -+ { -+ return 0; -+ } -+ -+ while (p[off] != '\n') -+ { -+ if (len-off <= 1) -+ { -+ return 0; -+ } -+ -+ physlen++; -+ off++; -+ } -+ -+ /* if we saw a crlf, physlen needs adjusted */ -+ if (physlen > 0 && p[off] == '\n' && p[off-1] == '\r') -+ { -+ physlen--; -+ } -+ -+ /* advance past the newline */ -+ off++; -+ -+ *plineoff = *poff; -+ *plinelen = physlen; -+ *poff = off; -+ -+ return 1; -+} -+#endif /* NF_NEED_NEXTLINE */ -+ -+#endif /* __KERNEL__ */ -+ -+#endif /* _NETFILTER_HELPERS_H */ ---- /dev/null -+++ b/include/linux/netfilter_mime.h -@@ -0,0 +1,89 @@ -+/* -+ * MIME functions for netfilter modules. This file provides implementations -+ * for basic MIME parsing. MIME headers are used in many protocols, such as -+ * HTTP, RTSP, SIP, etc. -+ * -+ * gcc will warn for defined but unused functions, so we only include the -+ * functions requested. The following macros are used: -+ * NF_NEED_MIME_NEXTLINE nf_mime_nextline() -+ */ -+#ifndef _NETFILTER_MIME_H -+#define _NETFILTER_MIME_H -+ -+/* Only include these functions for kernel code. */ -+#ifdef __KERNEL__ -+ -+#include -+ -+/* -+ * Given a buffer and length, advance to the next line and mark the current -+ * line. If the current line is empty, *plinelen will be set to zero. If -+ * not, it will be set to the actual line length (including CRLF). -+ * -+ * 'line' in this context means logical line (includes LWS continuations). -+ * Returns 1 on success, 0 on failure. -+ */ -+#ifdef NF_NEED_MIME_NEXTLINE -+static int -+nf_mime_nextline(char* p, uint len, uint* poff, uint* plineoff, uint* plinelen) -+{ -+ uint off = *poff; -+ uint physlen = 0; -+ int is_first_line = 1; -+ -+ if (off >= len) -+ { -+ return 0; -+ } -+ -+ do -+ { -+ while (p[off] != '\n') -+ { -+ if (len-off <= 1) -+ { -+ return 0; -+ } -+ -+ physlen++; -+ off++; -+ } -+ -+ /* if we saw a crlf, physlen needs adjusted */ -+ if (physlen > 0 && p[off] == '\n' && p[off-1] == '\r') -+ { -+ physlen--; -+ } -+ -+ /* advance past the newline */ -+ off++; -+ -+ /* check for an empty line */ -+ if (physlen == 0) -+ { -+ break; -+ } -+ -+ /* check for colon on the first physical line */ -+ if (is_first_line) -+ { -+ is_first_line = 0; -+ if (memchr(p+(*poff), ':', physlen) == NULL) -+ { -+ return 0; -+ } -+ } -+ } -+ while (p[off] == ' ' || p[off] == '\t'); -+ -+ *plineoff = *poff; -+ *plinelen = (physlen == 0) ? 0 : (off - *poff); -+ *poff = off; -+ -+ return 1; -+} -+#endif /* NF_NEED_MIME_NEXTLINE */ -+ -+#endif /* __KERNEL__ */ -+ -+#endif /* _NETFILTER_MIME_H */ ---- a/net/ipv4/netfilter/Makefile -+++ b/net/ipv4/netfilter/Makefile -@@ -26,6 +26,7 @@ obj-$(CONFIG_NF_NAT_AMANDA) += nf_nat_am - obj-$(CONFIG_NF_NAT_FTP) += nf_nat_ftp.o - obj-$(CONFIG_NF_NAT_H323) += nf_nat_h323.o - obj-$(CONFIG_NF_NAT_IRC) += nf_nat_irc.o -+obj-$(CONFIG_NF_NAT_RTSP) += nf_nat_rtsp.o - obj-$(CONFIG_NF_NAT_PPTP) += nf_nat_pptp.o - obj-$(CONFIG_NF_NAT_SIP) += nf_nat_sip.o - obj-$(CONFIG_NF_NAT_SNMP_BASIC) += nf_nat_snmp_basic.o ---- a/net/netfilter/Kconfig -+++ b/net/netfilter/Kconfig -@@ -267,6 +267,16 @@ config NF_CONNTRACK_TFTP - - To compile it as a module, choose M here. If unsure, say N. - -+config NF_CONNTRACK_RTSP -+ tristate "RTSP protocol support" -+ depends on NF_CONNTRACK -+ help -+ Support the RTSP protocol. This allows UDP transports to be setup -+ properly, including RTP and RDT. -+ -+ If you want to compile it as a module, say 'M' here and read -+ Documentation/modules.txt. If unsure, say 'Y'. -+ - config NF_CT_NETLINK - tristate 'Connection tracking netlink interface' - select NETFILTER_NETLINK ---- a/net/netfilter/Makefile -+++ b/net/netfilter/Makefile -@@ -33,6 +33,7 @@ obj-$(CONFIG_NF_CONNTRACK_PPTP) += nf_co - obj-$(CONFIG_NF_CONNTRACK_SANE) += nf_conntrack_sane.o - obj-$(CONFIG_NF_CONNTRACK_SIP) += nf_conntrack_sip.o - obj-$(CONFIG_NF_CONNTRACK_TFTP) += nf_conntrack_tftp.o -+obj-$(CONFIG_NF_CONNTRACK_RTSP) += nf_conntrack_rtsp.o - - # transparent proxy support - obj-$(CONFIG_NETFILTER_TPROXY) += nf_tproxy_core.o ---- a/net/ipv4/netfilter/Kconfig -+++ b/net/ipv4/netfilter/Kconfig -@@ -257,6 +257,11 @@ config NF_NAT_IRC - depends on NF_CONNTRACK && NF_NAT - default NF_NAT && NF_CONNTRACK_IRC - -+config NF_NAT_RTSP -+ tristate -+ depends on IP_NF_IPTABLES && NF_CONNTRACK && NF_NAT -+ default NF_NAT && NF_CONNTRACK_RTSP -+ - config NF_NAT_TFTP - tristate - depends on NF_CONNTRACK && NF_NAT ---- /dev/null -+++ b/net/netfilter/nf_conntrack_rtsp.c -@@ -0,0 +1,517 @@ -+/* -+ * RTSP extension for IP connection tracking -+ * (C) 2003 by Tom Marshall -+ * based on ip_conntrack_irc.c -+ * -+ * 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. -+ * -+ * Module load syntax: -+ * insmod nf_conntrack_rtsp.o ports=port1,port2,...port -+ * max_outstanding=n setup_timeout=secs -+ * -+ * If no ports are specified, the default will be port 554. -+ * -+ * With max_outstanding you can define the maximum number of not yet -+ * answered SETUP requests per RTSP session (default 8). -+ * With setup_timeout you can specify how long the system waits for -+ * an expected data channel (default 300 seconds). -+ * -+ * 2005-02-13: Harald Welte -+ * - port to 2.6 -+ * - update to recent post-2.6.11 api changes -+ * 2006-09-14: Steven Van Acker -+ * - removed calls to NAT code from conntrack helper: NAT no longer needed to use rtsp-conntrack -+ * 2007-04-18: Michael Guntsche -+ * - Port to new NF API -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+ -+#define NF_NEED_STRNCASECMP -+#define NF_NEED_STRTOU16 -+#define NF_NEED_STRTOU32 -+#define NF_NEED_NEXTLINE -+#include -+#define NF_NEED_MIME_NEXTLINE -+#include -+ -+#include -+#define MAX_SIMUL_SETUP 8 /* XXX: use max_outstanding */ -+#define INFOP(fmt, args...) printk(KERN_INFO "%s: %s: " fmt, __FILE__, __FUNCTION__ , ## args) -+#if 0 -+#define DEBUGP(fmt, args...) printk(KERN_DEBUG "%s: %s: " fmt, __FILE__, __FUNCTION__ , ## args) -+#else -+#define DEBUGP(fmt, args...) -+#endif -+ -+#define MAX_PORTS 8 -+static int ports[MAX_PORTS]; -+static int num_ports = 0; -+static int max_outstanding = 8; -+static unsigned int setup_timeout = 300; -+ -+MODULE_AUTHOR("Tom Marshall "); -+MODULE_DESCRIPTION("RTSP connection tracking module"); -+MODULE_LICENSE("GPL"); -+module_param_array(ports, int, &num_ports, 0400); -+MODULE_PARM_DESC(ports, "port numbers of RTSP servers"); -+module_param(max_outstanding, int, 0400); -+MODULE_PARM_DESC(max_outstanding, "max number of outstanding SETUP requests per RTSP session"); -+module_param(setup_timeout, int, 0400); -+MODULE_PARM_DESC(setup_timeout, "timeout on for unestablished data channels"); -+ -+static char *rtsp_buffer; -+static DEFINE_SPINLOCK(rtsp_buffer_lock); -+ -+unsigned int (*nf_nat_rtsp_hook)(struct sk_buff *skb, -+ enum ip_conntrack_info ctinfo, -+ unsigned int matchoff, unsigned int matchlen,struct ip_ct_rtsp_expect* prtspexp, -+ struct nf_conntrack_expect *exp); -+void (*nf_nat_rtsp_hook_expectfn)(struct nf_conn *ct, struct nf_conntrack_expect *exp); -+ -+EXPORT_SYMBOL_GPL(nf_nat_rtsp_hook); -+ -+/* -+ * Max mappings we will allow for one RTSP connection (for RTP, the number -+ * of allocated ports is twice this value). Note that SMIL burns a lot of -+ * ports so keep this reasonably high. If this is too low, you will see a -+ * lot of "no free client map entries" messages. -+ */ -+#define MAX_PORT_MAPS 16 -+ -+/*** default port list was here in the masq code: 554, 3030, 4040 ***/ -+ -+#define SKIP_WSPACE(ptr,len,off) while(off < len && isspace(*(ptr+off))) { off++; } -+ -+/* -+ * Parse an RTSP packet. -+ * -+ * Returns zero if parsing failed. -+ * -+ * Parameters: -+ * IN ptcp tcp data pointer -+ * IN tcplen tcp data len -+ * IN/OUT ptcpoff points to current tcp offset -+ * OUT phdrsoff set to offset of rtsp headers -+ * OUT phdrslen set to length of rtsp headers -+ * OUT pcseqoff set to offset of CSeq header -+ * OUT pcseqlen set to length of CSeq header -+ */ -+static int -+rtsp_parse_message(char* ptcp, uint tcplen, uint* ptcpoff, -+ uint* phdrsoff, uint* phdrslen, -+ uint* pcseqoff, uint* pcseqlen, -+ uint* transoff, uint* translen) -+{ -+ uint entitylen = 0; -+ uint lineoff; -+ uint linelen; -+ -+ if (!nf_nextline(ptcp, tcplen, ptcpoff, &lineoff, &linelen)) -+ return 0; -+ -+ *phdrsoff = *ptcpoff; -+ while (nf_mime_nextline(ptcp, tcplen, ptcpoff, &lineoff, &linelen)) { -+ if (linelen == 0) { -+ if (entitylen > 0) -+ *ptcpoff += min(entitylen, tcplen - *ptcpoff); -+ break; -+ } -+ if (lineoff+linelen > tcplen) { -+ INFOP("!! overrun !!\n"); -+ break; -+ } -+ -+ if (nf_strncasecmp(ptcp+lineoff, "CSeq:", 5) == 0) { -+ *pcseqoff = lineoff; -+ *pcseqlen = linelen; -+ } -+ -+ if (nf_strncasecmp(ptcp+lineoff, "Transport:", 10) == 0) { -+ *transoff = lineoff; -+ *translen = linelen; -+ } -+ -+ if (nf_strncasecmp(ptcp+lineoff, "Content-Length:", 15) == 0) { -+ uint off = lineoff+15; -+ SKIP_WSPACE(ptcp+lineoff, linelen, off); -+ nf_strtou32(ptcp+off, &entitylen); -+ } -+ } -+ *phdrslen = (*ptcpoff) - (*phdrsoff); -+ -+ return 1; -+} -+ -+/* -+ * Find lo/hi client ports (if any) in transport header -+ * In: -+ * ptcp, tcplen = packet -+ * tranoff, tranlen = buffer to search -+ * -+ * Out: -+ * pport_lo, pport_hi = lo/hi ports (host endian) -+ * -+ * Returns nonzero if any client ports found -+ * -+ * Note: it is valid (and expected) for the client to request multiple -+ * transports, so we need to parse the entire line. -+ */ -+static int -+rtsp_parse_transport(char* ptran, uint tranlen, -+ struct ip_ct_rtsp_expect* prtspexp) -+{ -+ int rc = 0; -+ uint off = 0; -+ -+ if (tranlen < 10 || !iseol(ptran[tranlen-1]) || -+ nf_strncasecmp(ptran, "Transport:", 10) != 0) { -+ INFOP("sanity check failed\n"); -+ return 0; -+ } -+ -+ DEBUGP("tran='%.*s'\n", (int)tranlen, ptran); -+ off += 10; -+ SKIP_WSPACE(ptran, tranlen, off); -+ -+ /* Transport: tran;field;field=val,tran;field;field=val,... */ -+ while (off < tranlen) { -+ const char* pparamend; -+ uint nextparamoff; -+ -+ pparamend = memchr(ptran+off, ',', tranlen-off); -+ pparamend = (pparamend == NULL) ? ptran+tranlen : pparamend+1; -+ nextparamoff = pparamend-ptran; -+ -+ while (off < nextparamoff) { -+ const char* pfieldend; -+ uint nextfieldoff; -+ -+ pfieldend = memchr(ptran+off, ';', nextparamoff-off); -+ nextfieldoff = (pfieldend == NULL) ? nextparamoff : pfieldend-ptran+1; -+ -+ if (strncmp(ptran+off, "client_port=", 12) == 0) { -+ u_int16_t port; -+ uint numlen; -+ -+ off += 12; -+ numlen = nf_strtou16(ptran+off, &port); -+ off += numlen; -+ if (prtspexp->loport != 0 && prtspexp->loport != port) -+ DEBUGP("multiple ports found, port %hu ignored\n", port); -+ else { -+ DEBUGP("lo port found : %hu\n", port); -+ prtspexp->loport = prtspexp->hiport = port; -+ if (ptran[off] == '-') { -+ off++; -+ numlen = nf_strtou16(ptran+off, &port); -+ off += numlen; -+ prtspexp->pbtype = pb_range; -+ prtspexp->hiport = port; -+ -+ // If we have a range, assume rtp: -+ // loport must be even, hiport must be loport+1 -+ if ((prtspexp->loport & 0x0001) != 0 || -+ prtspexp->hiport != prtspexp->loport+1) { -+ DEBUGP("incorrect range: %hu-%hu, correcting\n", -+ prtspexp->loport, prtspexp->hiport); -+ prtspexp->loport &= 0xfffe; -+ prtspexp->hiport = prtspexp->loport+1; -+ } -+ } else if (ptran[off] == '/') { -+ off++; -+ numlen = nf_strtou16(ptran+off, &port); -+ off += numlen; -+ prtspexp->pbtype = pb_discon; -+ prtspexp->hiport = port; -+ } -+ rc = 1; -+ } -+ } -+ -+ /* -+ * Note we don't look for the destination parameter here. -+ * If we are using NAT, the NAT module will handle it. If not, -+ * and the client is sending packets elsewhere, the expectation -+ * will quietly time out. -+ */ -+ -+ off = nextfieldoff; -+ } -+ -+ off = nextparamoff; -+ } -+ -+ return rc; -+} -+ -+void expected(struct nf_conn *ct, struct nf_conntrack_expect *exp) -+{ -+ if(nf_nat_rtsp_hook_expectfn) { -+ nf_nat_rtsp_hook_expectfn(ct,exp); -+ } -+} -+ -+/*** conntrack functions ***/ -+ -+/* outbound packet: client->server */ -+ -+static inline int -+help_out(struct sk_buff *skb, unsigned char *rb_ptr, unsigned int datalen, -+ struct nf_conn *ct, enum ip_conntrack_info ctinfo) -+{ -+ struct ip_ct_rtsp_expect expinfo; -+ -+ int dir = CTINFO2DIR(ctinfo); /* = IP_CT_DIR_ORIGINAL */ -+ //struct tcphdr* tcph = (void*)iph + iph->ihl * 4; -+ //uint tcplen = pktlen - iph->ihl * 4; -+ char* pdata = rb_ptr; -+ //uint datalen = tcplen - tcph->doff * 4; -+ uint dataoff = 0; -+ int ret = NF_ACCEPT; -+ -+ struct nf_conntrack_expect *exp; -+ -+ __be16 be_loport; -+ -+ memset(&expinfo, 0, sizeof(expinfo)); -+ -+ while (dataoff < datalen) { -+ uint cmdoff = dataoff; -+ uint hdrsoff = 0; -+ uint hdrslen = 0; -+ uint cseqoff = 0; -+ uint cseqlen = 0; -+ uint transoff = 0; -+ uint translen = 0; -+ uint off; -+ -+ if (!rtsp_parse_message(pdata, datalen, &dataoff, -+ &hdrsoff, &hdrslen, -+ &cseqoff, &cseqlen, -+ &transoff, &translen)) -+ break; /* not a valid message */ -+ -+ if (strncmp(pdata+cmdoff, "SETUP ", 6) != 0) -+ continue; /* not a SETUP message */ -+ DEBUGP("found a setup message\n"); -+ -+ off = 0; -+ if(translen) { -+ rtsp_parse_transport(pdata+transoff, translen, &expinfo); -+ } -+ -+ if (expinfo.loport == 0) { -+ DEBUGP("no udp transports found\n"); -+ continue; /* no udp transports found */ -+ } -+ -+ DEBUGP("udp transport found, ports=(%d,%hu,%hu)\n", -+ (int)expinfo.pbtype, expinfo.loport, expinfo.hiport); -+ -+ exp = nf_ct_expect_alloc(ct); -+ if (!exp) { -+ ret = NF_DROP; -+ goto out; -+ } -+ -+ be_loport = htons(expinfo.loport); -+ -+ nf_ct_expect_init(exp, NF_CT_EXPECT_CLASS_DEFAULT, -+ ct->tuplehash[!dir].tuple.src.l3num, -+ &ct->tuplehash[!dir].tuple.src.u3, &ct->tuplehash[!dir].tuple.dst.u3, -+ IPPROTO_UDP, NULL, &be_loport); -+ -+ exp->master = ct; -+ -+ exp->expectfn = expected; -+ exp->flags = 0; -+ -+ if (expinfo.pbtype == pb_range) { -+ DEBUGP("Changing expectation mask to handle multiple ports\n"); -+ exp->mask.src.u.udp.port = 0xfffe; -+ } -+ -+ DEBUGP("expect_related %u.%u.%u.%u:%u-%u.%u.%u.%u:%u\n", -+ NIPQUAD(exp->tuple.src.u3.ip), -+ ntohs(exp->tuple.src.u.udp.port), -+ NIPQUAD(exp->tuple.dst.u3.ip), -+ ntohs(exp->tuple.dst.u.udp.port)); -+ -+ if (nf_nat_rtsp_hook) -+ /* pass the request off to the nat helper */ -+ ret = nf_nat_rtsp_hook(skb, ctinfo, hdrsoff, hdrslen, &expinfo, exp); -+ else if (nf_ct_expect_related(exp) != 0) { -+ INFOP("nf_ct_expect_related failed\n"); -+ ret = NF_DROP; -+ } -+ nf_ct_expect_put(exp); -+ goto out; -+ } -+out: -+ -+ return ret; -+} -+ -+ -+static inline int -+help_in(struct sk_buff *skb, size_t pktlen, -+ struct nf_conn* ct, enum ip_conntrack_info ctinfo) -+{ -+ return NF_ACCEPT; -+} -+ -+static int help(struct sk_buff *skb, unsigned int protoff, -+ struct nf_conn *ct, enum ip_conntrack_info ctinfo) -+{ -+ struct tcphdr _tcph, *th; -+ unsigned int dataoff, datalen; -+ char *rb_ptr; -+ int ret = NF_DROP; -+ -+ /* Until there's been traffic both ways, don't look in packets. */ -+ if (ctinfo != IP_CT_ESTABLISHED && -+ ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) { -+ DEBUGP("conntrackinfo = %u\n", ctinfo); -+ return NF_ACCEPT; -+ } -+ -+ /* Not whole TCP header? */ -+ th = skb_header_pointer(skb, protoff, sizeof(_tcph), &_tcph); -+ -+ if (!th) -+ return NF_ACCEPT; -+ -+ /* No data ? */ -+ dataoff = protoff + th->doff*4; -+ datalen = skb->len - dataoff; -+ if (dataoff >= skb->len) -+ return NF_ACCEPT; -+ -+ spin_lock_bh(&rtsp_buffer_lock); -+ rb_ptr = skb_header_pointer(skb, dataoff, -+ skb->len - dataoff, rtsp_buffer); -+ BUG_ON(rb_ptr == NULL); -+ -+#if 0 -+ /* Checksum invalid? Ignore. */ -+ /* FIXME: Source route IP option packets --RR */ -+ if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr, -+ csum_partial((char*)tcph, tcplen, 0))) -+ { -+ DEBUGP("bad csum: %p %u %u.%u.%u.%u %u.%u.%u.%u\n", -+ tcph, tcplen, NIPQUAD(iph->saddr), NIPQUAD(iph->daddr)); -+ return NF_ACCEPT; -+ } -+#endif -+ -+ switch (CTINFO2DIR(ctinfo)) { -+ case IP_CT_DIR_ORIGINAL: -+ ret = help_out(skb, rb_ptr, datalen, ct, ctinfo); -+ break; -+ case IP_CT_DIR_REPLY: -+ DEBUGP("IP_CT_DIR_REPLY\n"); -+ /* inbound packet: server->client */ -+ ret = NF_ACCEPT; -+ break; -+ } -+ -+ spin_unlock_bh(&rtsp_buffer_lock); -+ -+ return ret; -+} -+ -+static struct nf_conntrack_helper rtsp_helpers[MAX_PORTS]; -+static char rtsp_names[MAX_PORTS][10]; -+static struct nf_conntrack_expect_policy rtsp_expect_policy; -+ -+/* This function is intentionally _NOT_ defined as __exit */ -+static void -+fini(void) -+{ -+ int i; -+ for (i = 0; i < num_ports; i++) { -+ DEBUGP("unregistering port %d\n", ports[i]); -+ nf_conntrack_helper_unregister(&rtsp_helpers[i]); -+ } -+ kfree(rtsp_buffer); -+} -+ -+static int __init -+init(void) -+{ -+ int i, ret; -+ struct nf_conntrack_helper *hlpr; -+ char *tmpname; -+ -+ printk("nf_conntrack_rtsp v" IP_NF_RTSP_VERSION " loading\n"); -+ -+ if (max_outstanding < 1) { -+ printk("nf_conntrack_rtsp: max_outstanding must be a positive integer\n"); -+ return -EBUSY; -+ } -+ if (setup_timeout < 0) { -+ printk("nf_conntrack_rtsp: setup_timeout must be a positive integer\n"); -+ return -EBUSY; -+ } -+ -+ rtsp_expect_policy.max_expected = max_outstanding; -+ rtsp_expect_policy.timeout = setup_timeout; -+ -+ rtsp_buffer = kmalloc(65536, GFP_KERNEL); -+ if (!rtsp_buffer) -+ return -ENOMEM; -+ -+ /* If no port given, default to standard rtsp port */ -+ if (ports[0] == 0) { -+ ports[0] = RTSP_PORT; -+ } -+ -+ for (i = 0; (i < MAX_PORTS) && ports[i]; i++) { -+ hlpr = &rtsp_helpers[i]; -+ memset(hlpr, 0, sizeof(struct nf_conntrack_helper)); -+ hlpr->tuple.src.u.tcp.port = htons(ports[i]); -+ hlpr->tuple.dst.protonum = IPPROTO_TCP; -+ hlpr->expect_policy = &rtsp_expect_policy; -+ hlpr->me = THIS_MODULE; -+ hlpr->help = help; -+ -+ tmpname = &rtsp_names[i][0]; -+ if (ports[i] == RTSP_PORT) { -+ sprintf(tmpname, "rtsp"); -+ } else { -+ sprintf(tmpname, "rtsp-%d", i); -+ } -+ hlpr->name = tmpname; -+ -+ DEBUGP("port #%d: %d\n", i, ports[i]); -+ -+ ret = nf_conntrack_helper_register(hlpr); -+ -+ if (ret) { -+ printk("nf_conntrack_rtsp: ERROR registering port %d\n", ports[i]); -+ fini(); -+ return -EBUSY; -+ } -+ num_ports++; -+ } -+ return 0; -+} -+ -+module_init(init); -+module_exit(fini); -+ -+EXPORT_SYMBOL(nf_nat_rtsp_hook_expectfn); -+ ---- /dev/null -+++ b/net/ipv4/netfilter/nf_nat_rtsp.c -@@ -0,0 +1,496 @@ -+/* -+ * RTSP extension for TCP NAT alteration -+ * (C) 2003 by Tom Marshall -+ * based on ip_nat_irc.c -+ * -+ * 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. -+ * -+ * Module load syntax: -+ * insmod nf_nat_rtsp.o ports=port1,port2,...port -+ * stunaddr=
-+ * destaction=[auto|strip|none] -+ * -+ * If no ports are specified, the default will be port 554 only. -+ * -+ * stunaddr specifies the address used to detect that a client is using STUN. -+ * If this address is seen in the destination parameter, it is assumed that -+ * the client has already punched a UDP hole in the firewall, so we don't -+ * mangle the client_port. If none is specified, it is autodetected. It -+ * only needs to be set if you have multiple levels of NAT. It should be -+ * set to the external address that the STUN clients detect. Note that in -+ * this case, it will not be possible for clients to use UDP with servers -+ * between the NATs. -+ * -+ * If no destaction is specified, auto is used. -+ * destaction=auto: strip destination parameter if it is not stunaddr. -+ * destaction=strip: always strip destination parameter (not recommended). -+ * destaction=none: do not touch destination parameter (not recommended). -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#define NF_NEED_STRNCASECMP -+#define NF_NEED_STRTOU16 -+#include -+#define NF_NEED_MIME_NEXTLINE -+#include -+ -+#define INFOP(fmt, args...) printk(KERN_INFO "%s: %s: " fmt, __FILE__, __FUNCTION__ , ## args) -+#if 0 -+#define DEBUGP(fmt, args...) printk(KERN_DEBUG "%s: %s: " fmt, __FILE__, __FUNCTION__ , ## args) -+#else -+#define DEBUGP(fmt, args...) -+#endif -+ -+#define MAX_PORTS 8 -+#define DSTACT_AUTO 0 -+#define DSTACT_STRIP 1 -+#define DSTACT_NONE 2 -+ -+static char* stunaddr = NULL; -+static char* destaction = NULL; -+ -+static u_int32_t extip = 0; -+static int dstact = 0; -+ -+MODULE_AUTHOR("Tom Marshall "); -+MODULE_DESCRIPTION("RTSP network address translation module"); -+MODULE_LICENSE("GPL"); -+module_param(stunaddr, charp, 0644); -+MODULE_PARM_DESC(stunaddr, "Address for detecting STUN"); -+module_param(destaction, charp, 0644); -+MODULE_PARM_DESC(destaction, "Action for destination parameter (auto/strip/none)"); -+ -+#define SKIP_WSPACE(ptr,len,off) while(off < len && isspace(*(ptr+off))) { off++; } -+ -+/*** helper functions ***/ -+ -+static void -+get_skb_tcpdata(struct sk_buff* skb, char** pptcpdata, uint* ptcpdatalen) -+{ -+ struct iphdr* iph = ip_hdr(skb); -+ struct tcphdr* tcph = (void *)iph + ip_hdrlen(skb); -+ -+ *pptcpdata = (char*)tcph + tcph->doff*4; -+ *ptcpdatalen = ((char*)skb_transport_header(skb) + skb->len) - *pptcpdata; -+} -+ -+/*** nat functions ***/ -+ -+/* -+ * Mangle the "Transport:" header: -+ * - Replace all occurences of "client_port=" -+ * - Handle destination parameter -+ * -+ * In: -+ * ct, ctinfo = conntrack context -+ * skb = packet -+ * tranoff = Transport header offset from TCP data -+ * tranlen = Transport header length (incl. CRLF) -+ * rport_lo = replacement low port (host endian) -+ * rport_hi = replacement high port (host endian) -+ * -+ * Returns packet size difference. -+ * -+ * Assumes that a complete transport header is present, ending with CR or LF -+ */ -+static int -+rtsp_mangle_tran(enum ip_conntrack_info ctinfo, -+ struct nf_conntrack_expect* exp, -+ struct ip_ct_rtsp_expect* prtspexp, -+ struct sk_buff* skb, uint tranoff, uint tranlen) -+{ -+ char* ptcp; -+ uint tcplen; -+ char* ptran; -+ char rbuf1[16]; /* Replacement buffer (one port) */ -+ uint rbuf1len; /* Replacement len (one port) */ -+ char rbufa[16]; /* Replacement buffer (all ports) */ -+ uint rbufalen; /* Replacement len (all ports) */ -+ u_int32_t newip; -+ u_int16_t loport, hiport; -+ uint off = 0; -+ uint diff; /* Number of bytes we removed */ -+ -+ struct nf_conn *ct = exp->master; -+ struct nf_conntrack_tuple *t; -+ -+ char szextaddr[15+1]; -+ uint extaddrlen; -+ int is_stun; -+ -+ get_skb_tcpdata(skb, &ptcp, &tcplen); -+ ptran = ptcp+tranoff; -+ -+ if (tranoff+tranlen > tcplen || tcplen-tranoff < tranlen || -+ tranlen < 10 || !iseol(ptran[tranlen-1]) || -+ nf_strncasecmp(ptran, "Transport:", 10) != 0) -+ { -+ INFOP("sanity check failed\n"); -+ return 0; -+ } -+ off += 10; -+ SKIP_WSPACE(ptcp+tranoff, tranlen, off); -+ -+ newip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3.ip; -+ t = &exp->tuple; -+ t->dst.u3.ip = newip; -+ -+ extaddrlen = extip ? sprintf(szextaddr, "%u.%u.%u.%u", NIPQUAD(extip)) -+ : sprintf(szextaddr, "%u.%u.%u.%u", NIPQUAD(newip)); -+ DEBUGP("stunaddr=%s (%s)\n", szextaddr, (extip?"forced":"auto")); -+ -+ rbuf1len = rbufalen = 0; -+ switch (prtspexp->pbtype) -+ { -+ case pb_single: -+ for (loport = prtspexp->loport; loport != 0; loport++) /* XXX: improper wrap? */ -+ { -+ t->dst.u.udp.port = htons(loport); -+ if (nf_ct_expect_related(exp) == 0) -+ { -+ DEBUGP("using port %hu\n", loport); -+ break; -+ } -+ } -+ if (loport != 0) -+ { -+ rbuf1len = sprintf(rbuf1, "%hu", loport); -+ rbufalen = sprintf(rbufa, "%hu", loport); -+ } -+ break; -+ case pb_range: -+ for (loport = prtspexp->loport; loport != 0; loport += 2) /* XXX: improper wrap? */ -+ { -+ t->dst.u.udp.port = htons(loport); -+ if (nf_ct_expect_related(exp) == 0) -+ { -+ hiport = loport + ~exp->mask.src.u.udp.port; -+ DEBUGP("using ports %hu-%hu\n", loport, hiport); -+ break; -+ } -+ } -+ if (loport != 0) -+ { -+ rbuf1len = sprintf(rbuf1, "%hu", loport); -+ rbufalen = sprintf(rbufa, "%hu-%hu", loport, loport+1); -+ } -+ break; -+ case pb_discon: -+ for (loport = prtspexp->loport; loport != 0; loport++) /* XXX: improper wrap? */ -+ { -+ t->dst.u.udp.port = htons(loport); -+ if (nf_ct_expect_related(exp) == 0) -+ { -+ DEBUGP("using port %hu (1 of 2)\n", loport); -+ break; -+ } -+ } -+ for (hiport = prtspexp->hiport; hiport != 0; hiport++) /* XXX: improper wrap? */ -+ { -+ t->dst.u.udp.port = htons(hiport); -+ if (nf_ct_expect_related(exp) == 0) -+ { -+ DEBUGP("using port %hu (2 of 2)\n", hiport); -+ break; -+ } -+ } -+ if (loport != 0 && hiport != 0) -+ { -+ rbuf1len = sprintf(rbuf1, "%hu", loport); -+ if (hiport == loport+1) -+ { -+ rbufalen = sprintf(rbufa, "%hu-%hu", loport, hiport); -+ } -+ else -+ { -+ rbufalen = sprintf(rbufa, "%hu/%hu", loport, hiport); -+ } -+ } -+ break; -+ } -+ -+ if (rbuf1len == 0) -+ { -+ return 0; /* cannot get replacement port(s) */ -+ } -+ -+ /* Transport: tran;field;field=val,tran;field;field=val,... */ -+ while (off < tranlen) -+ { -+ uint saveoff; -+ const char* pparamend; -+ uint nextparamoff; -+ -+ pparamend = memchr(ptran+off, ',', tranlen-off); -+ pparamend = (pparamend == NULL) ? ptran+tranlen : pparamend+1; -+ nextparamoff = pparamend-ptcp; -+ -+ /* -+ * We pass over each param twice. On the first pass, we look for a -+ * destination= field. It is handled by the security policy. If it -+ * is present, allowed, and equal to our external address, we assume -+ * that STUN is being used and we leave the client_port= field alone. -+ */ -+ is_stun = 0; -+ saveoff = off; -+ while (off < nextparamoff) -+ { -+ const char* pfieldend; -+ uint nextfieldoff; -+ -+ pfieldend = memchr(ptran+off, ';', nextparamoff-off); -+ nextfieldoff = (pfieldend == NULL) ? nextparamoff : pfieldend-ptran+1; -+ -+ if (dstact != DSTACT_NONE && strncmp(ptran+off, "destination=", 12) == 0) -+ { -+ if (strncmp(ptran+off+12, szextaddr, extaddrlen) == 0) -+ { -+ is_stun = 1; -+ } -+ if (dstact == DSTACT_STRIP || (dstact == DSTACT_AUTO && !is_stun)) -+ { -+ diff = nextfieldoff-off; -+ if (!nf_nat_mangle_tcp_packet(skb, ct, ctinfo, -+ off, diff, NULL, 0)) -+ { -+ /* mangle failed, all we can do is bail */ -+ nf_ct_unexpect_related(exp); -+ return 0; -+ } -+ get_skb_tcpdata(skb, &ptcp, &tcplen); -+ ptran = ptcp+tranoff; -+ tranlen -= diff; -+ nextparamoff -= diff; -+ nextfieldoff -= diff; -+ } -+ } -+ -+ off = nextfieldoff; -+ } -+ if (is_stun) -+ { -+ continue; -+ } -+ off = saveoff; -+ while (off < nextparamoff) -+ { -+ const char* pfieldend; -+ uint nextfieldoff; -+ -+ pfieldend = memchr(ptran+off, ';', nextparamoff-off); -+ nextfieldoff = (pfieldend == NULL) ? nextparamoff : pfieldend-ptran+1; -+ -+ if (strncmp(ptran+off, "client_port=", 12) == 0) -+ { -+ u_int16_t port; -+ uint numlen; -+ uint origoff; -+ uint origlen; -+ char* rbuf = rbuf1; -+ uint rbuflen = rbuf1len; -+ -+ off += 12; -+ origoff = (ptran-ptcp)+off; -+ origlen = 0; -+ numlen = nf_strtou16(ptran+off, &port); -+ off += numlen; -+ origlen += numlen; -+ if (port != prtspexp->loport) -+ { -+ DEBUGP("multiple ports found, port %hu ignored\n", port); -+ } -+ else -+ { -+ if (ptran[off] == '-' || ptran[off] == '/') -+ { -+ off++; -+ origlen++; -+ numlen = nf_strtou16(ptran+off, &port); -+ off += numlen; -+ origlen += numlen; -+ rbuf = rbufa; -+ rbuflen = rbufalen; -+ } -+ -+ /* -+ * note we cannot just memcpy() if the sizes are the same. -+ * the mangle function does skb resizing, checks for a -+ * cloned skb, and updates the checksums. -+ * -+ * parameter 4 below is offset from start of tcp data. -+ */ -+ diff = origlen-rbuflen; -+ if (!nf_nat_mangle_tcp_packet(skb, ct, ctinfo, -+ origoff, origlen, rbuf, rbuflen)) -+ { -+ /* mangle failed, all we can do is bail */ -+ nf_ct_unexpect_related(exp); -+ return 0; -+ } -+ get_skb_tcpdata(skb, &ptcp, &tcplen); -+ ptran = ptcp+tranoff; -+ tranlen -= diff; -+ nextparamoff -= diff; -+ nextfieldoff -= diff; -+ } -+ } -+ -+ off = nextfieldoff; -+ } -+ -+ off = nextparamoff; -+ } -+ -+ return 1; -+} -+ -+static uint -+help_out(struct sk_buff *skb, enum ip_conntrack_info ctinfo, -+ unsigned int matchoff, unsigned int matchlen, struct ip_ct_rtsp_expect* prtspexp, -+ struct nf_conntrack_expect* exp) -+{ -+ char* ptcp; -+ uint tcplen; -+ uint hdrsoff; -+ uint hdrslen; -+ uint lineoff; -+ uint linelen; -+ uint off; -+ -+ //struct iphdr* iph = (struct iphdr*)skb->nh.iph; -+ //struct tcphdr* tcph = (struct tcphdr*)((void*)iph + iph->ihl*4); -+ -+ get_skb_tcpdata(skb, &ptcp, &tcplen); -+ hdrsoff = matchoff;//exp->seq - ntohl(tcph->seq); -+ hdrslen = matchlen; -+ off = hdrsoff; -+ DEBUGP("NAT rtsp help_out\n"); -+ -+ while (nf_mime_nextline(ptcp, hdrsoff+hdrslen, &off, &lineoff, &linelen)) -+ { -+ if (linelen == 0) -+ { -+ break; -+ } -+ if (off > hdrsoff+hdrslen) -+ { -+ INFOP("!! overrun !!"); -+ break; -+ } -+ DEBUGP("hdr: len=%u, %.*s", linelen, (int)linelen, ptcp+lineoff); -+ -+ if (nf_strncasecmp(ptcp+lineoff, "Transport:", 10) == 0) -+ { -+ uint oldtcplen = tcplen; -+ DEBUGP("hdr: Transport\n"); -+ if (!rtsp_mangle_tran(ctinfo, exp, prtspexp, skb, lineoff, linelen)) -+ { -+ DEBUGP("hdr: Transport mangle failed"); -+ break; -+ } -+ get_skb_tcpdata(skb, &ptcp, &tcplen); -+ hdrslen -= (oldtcplen-tcplen); -+ off -= (oldtcplen-tcplen); -+ lineoff -= (oldtcplen-tcplen); -+ linelen -= (oldtcplen-tcplen); -+ DEBUGP("rep: len=%u, %.*s", linelen, (int)linelen, ptcp+lineoff); -+ } -+ } -+ -+ return NF_ACCEPT; -+} -+ -+static unsigned int -+help(struct sk_buff *skb, enum ip_conntrack_info ctinfo, -+ unsigned int matchoff, unsigned int matchlen, struct ip_ct_rtsp_expect* prtspexp, -+ struct nf_conntrack_expect* exp) -+{ -+ int dir = CTINFO2DIR(ctinfo); -+ int rc = NF_ACCEPT; -+ -+ switch (dir) -+ { -+ case IP_CT_DIR_ORIGINAL: -+ rc = help_out(skb, ctinfo, matchoff, matchlen, prtspexp, exp); -+ break; -+ case IP_CT_DIR_REPLY: -+ DEBUGP("unmangle ! %u\n", ctinfo); -+ /* XXX: unmangle */ -+ rc = NF_ACCEPT; -+ break; -+ } -+ //UNLOCK_BH(&ip_rtsp_lock); -+ -+ return rc; -+} -+ -+static void expected(struct nf_conn* ct, struct nf_conntrack_expect *exp) -+{ -+ struct nf_nat_multi_range_compat mr; -+ u_int32_t newdstip, newsrcip, newip; -+ -+ struct nf_conn *master = ct->master; -+ -+ newdstip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3.ip; -+ newsrcip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3.ip; -+ //FIXME (how to port that ?) -+ //code from 2.4 : newip = (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC) ? newsrcip : newdstip; -+ newip = newdstip; -+ -+ DEBUGP("newsrcip=%u.%u.%u.%u, newdstip=%u.%u.%u.%u, newip=%u.%u.%u.%u\n", -+ NIPQUAD(newsrcip), NIPQUAD(newdstip), NIPQUAD(newip)); -+ -+ mr.rangesize = 1; -+ // We don't want to manip the per-protocol, just the IPs. -+ mr.range[0].flags = IP_NAT_RANGE_MAP_IPS; -+ mr.range[0].min_ip = mr.range[0].max_ip = newip; -+ -+ nf_nat_setup_info(ct, &mr.range[0], IP_NAT_MANIP_DST); -+} -+ -+ -+static void __exit fini(void) -+{ -+ nf_nat_rtsp_hook = NULL; -+ nf_nat_rtsp_hook_expectfn = NULL; -+ synchronize_net(); -+} -+ -+static int __init init(void) -+{ -+ printk("nf_nat_rtsp v" IP_NF_RTSP_VERSION " loading\n"); -+ -+ BUG_ON(nf_nat_rtsp_hook); -+ nf_nat_rtsp_hook = help; -+ nf_nat_rtsp_hook_expectfn = &expected; -+ -+ if (stunaddr != NULL) -+ extip = in_aton(stunaddr); -+ -+ if (destaction != NULL) { -+ if (strcmp(destaction, "auto") == 0) -+ dstact = DSTACT_AUTO; -+ -+ if (strcmp(destaction, "strip") == 0) -+ dstact = DSTACT_STRIP; -+ -+ if (strcmp(destaction, "none") == 0) -+ dstact = DSTACT_NONE; -+ } -+ -+ return 0; -+} -+ -+module_init(init); -+module_exit(fini); diff --git a/target/linux/generic-2.6/patches-2.6.28/200-sched_esfq.patch b/target/linux/generic-2.6/patches-2.6.28/200-sched_esfq.patch deleted file mode 100644 index f9ce66efc..000000000 --- a/target/linux/generic-2.6/patches-2.6.28/200-sched_esfq.patch +++ /dev/null @@ -1,795 +0,0 @@ ---- a/include/linux/pkt_sched.h -+++ b/include/linux/pkt_sched.h -@@ -180,8 +180,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 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,702 @@ -+/* -+ * 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, -+ * -+ * Changes: Alexander Atanasov, -+ * Added dynamic depth,limit,divisor,hash_kind options. -+ * Added dst and src hashes. -+ * -+ * Alexander Clouter, -+ * Ported ESFQ to Linux 2.6. -+ * -+ * Corey Hickey, -+ * 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 -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+/* 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 int esfq_requeue(struct sk_buff *skb, struct Qdisc* sch) -+{ -+ struct esfq_sched_data *q = qdisc_priv(sch); -+ esfq_q_enqueue(skb, q, ESFQ_HEAD); -+ sch->qstats.backlog += skb->len; -+ if (++sch->q.qlen < q->limit - 1) { -+ sch->qstats.requeues++; -+ return 0; -+ } -+ -+ sch->qstats.drops++; -+ esfq_drop(sch); -+ return NET_XMIT_CN; -+} -+ -+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 rtattr *opt) -+{ -+ struct tc_esfq_qopt *ctl = RTA_DATA(opt); -+ esfq_index p = ~0U/2; -+ int i; -+ -+ if (opt && opt->rta_len < RTA_LENGTH(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 = RTA_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; idepth; 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; idepth; i++) -+ esfq_link(q, i); -+ return 0; -+err_case: -+ esfq_q_destroy(q); -+ return -ENOBUFS; -+} -+ -+static int esfq_init(struct Qdisc *sch, struct rtattr *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 rtattr *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; -+ 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; -+ -+ RTA_PUT(skb, TCA_OPTIONS, sizeof(opt), &opt); -+ -+ return skb->len; -+ -+rtattr_failure: -+ skb_trim(skb, b - skb->data); -+ 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, -+ .requeue = esfq_requeue, -+ .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"); diff --git a/target/linux/generic-2.6/patches-2.6.28/201-jhash3.patch b/target/linux/generic-2.6/patches-2.6.28/201-jhash3.patch deleted file mode 100644 index 0218fa19c..000000000 --- a/target/linux/generic-2.6/patches-2.6.28/201-jhash3.patch +++ /dev/null @@ -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 */ diff --git a/target/linux/generic-2.6/patches-2.6.28/202-mips-freestanding.patch b/target/linux/generic-2.6/patches-2.6.28/202-mips-freestanding.patch deleted file mode 100644 index 4844893f3..000000000 --- a/target/linux/generic-2.6/patches-2.6.28/202-mips-freestanding.patch +++ /dev/null @@ -1,12 +0,0 @@ ---- a/arch/mips/Makefile -+++ b/arch/mips/Makefile -@@ -593,6 +593,9 @@ core-$(CONFIG_TOSHIBA_RBTX4927) += arch/ - core-$(CONFIG_TOSHIBA_RBTX4938) += arch/mips/txx9/rbtx4938/ - core-$(CONFIG_TOSHIBA_RBTX4939) += arch/mips/txx9/rbtx4939/ - -+# 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/ - diff --git a/target/linux/generic-2.6/patches-2.6.28/203-slab_maxsize.patch b/target/linux/generic-2.6/patches-2.6.28/203-slab_maxsize.patch deleted file mode 100644 index 25567f848..000000000 --- a/target/linux/generic-2.6/patches-2.6.28/203-slab_maxsize.patch +++ /dev/null @@ -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) diff --git a/target/linux/generic-2.6/patches-2.6.28/204-jffs2_eofdetect.patch b/target/linux/generic-2.6/patches-2.6.28/204-jffs2_eofdetect.patch deleted file mode 100644 index 16d3e1f8e..000000000 --- a/target/linux/generic-2.6/patches-2.6.28/204-jffs2_eofdetect.patch +++ /dev/null @@ -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; diff --git a/target/linux/generic-2.6/patches-2.6.28/205-skb_padding.patch b/target/linux/generic-2.6/patches-2.6.28/205-skb_padding.patch deleted file mode 100644 index 949f887ad..000000000 --- a/target/linux/generic-2.6/patches-2.6.28/205-skb_padding.patch +++ /dev/null @@ -1,56 +0,0 @@ ---- a/include/linux/skbuff.h -+++ b/include/linux/skbuff.h -@@ -1270,11 +1270,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) -@@ -1364,9 +1371,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; - } - -@@ -1439,7 +1446,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; diff --git a/target/linux/generic-2.6/patches-2.6.28/207-powerpc_asm_segment_h.patch b/target/linux/generic-2.6/patches-2.6.28/207-powerpc_asm_segment_h.patch deleted file mode 100644 index 1272e82c7..000000000 --- a/target/linux/generic-2.6/patches-2.6.28/207-powerpc_asm_segment_h.patch +++ /dev/null @@ -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 */ diff --git a/target/linux/generic-2.6/patches-2.6.28/208-rtl8110sb_fix.patch b/target/linux/generic-2.6/patches-2.6.28/208-rtl8110sb_fix.patch deleted file mode 100644 index 9d9ae5023..000000000 --- a/target/linux/generic-2.6/patches-2.6.28/208-rtl8110sb_fix.patch +++ /dev/null @@ -1,42 +0,0 @@ ---- a/drivers/net/r8169.c -+++ b/drivers/net/r8169.c -@@ -1862,7 +1862,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 -@@ -1871,7 +1871,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 -@@ -1880,7 +1880,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 -@@ -3555,10 +3555,12 @@ static irqreturn_t rtl8169_interrupt(int - goto out; - } - -+#if 0 - if (unlikely(status & SYSErr)) { - rtl8169_pcierr_interrupt(dev); - goto out; - } -+#endif - - if (status & LinkChg) - rtl8169_check_link_status(dev, tp, ioaddr); diff --git a/target/linux/generic-2.6/patches-2.6.28/209-mini_fo.patch b/target/linux/generic-2.6/patches-2.6.28/209-mini_fo.patch deleted file mode 100644 index 8b6df7aa9..000000000 --- a/target/linux/generic-2.6/patches-2.6.28/209-mini_fo.patch +++ /dev/null @@ -1,7776 +0,0 @@ ---- a/fs/Kconfig -+++ b/fs/Kconfig -@@ -1013,6 +1013,9 @@ config VXFS_FS - To compile this as a module, choose M here: the module will be - called freevxfs. If unsure, say N. - -+config MINI_FO -+ tristate "Mini fanout overlay filesystem" -+ - config MINIX_FS - tristate "Minix file system support" - depends on BLOCK ---- a/fs/Makefile -+++ b/fs/Makefile -@@ -80,6 +80,7 @@ obj-$(CONFIG_SQUASHFS) += squashfs/ - obj-y += ramfs/ - obj-$(CONFIG_HUGETLBFS) += hugetlbfs/ - obj-$(CONFIG_CODA_FS) += coda/ -+obj-$(CONFIG_MINI_FO) += mini_fo/ - obj-$(CONFIG_MINIX_FS) += minix/ - obj-$(CONFIG_FAT_FS) += fat/ - obj-$(CONFIG_BFS_FS) += bfs/ ---- /dev/null -+++ b/fs/mini_fo/aux.c -@@ -0,0 +1,577 @@ -+/* -+ * Copyright (c) 1997-2003 Erez Zadok -+ * Copyright (c) 2001-2003 Stony Brook University -+ * -+ * For specific licensing information, see the COPYING file distributed with -+ * this package, or get one from ftp://ftp.filesystems.org/pub/fist/COPYING. -+ * -+ * This Copyright notice must be kept intact and distributed with all -+ * fistgen sources INCLUDING sources generated by fistgen. -+ */ -+/* -+ * Copyright (C) 2004, 2005 Markus Klotzbuecher -+ * -+ * 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. -+ */ -+/* -+ * $Id$ -+ */ -+ -+#ifdef HAVE_CONFIG_H -+# include -+#endif -+ -+#include "fist.h" -+#include "mini_fo.h" -+ -+/* check if file exists in storage */ -+int exists_in_storage(dentry_t *dentry) -+{ -+ check_mini_fo_dentry(dentry); -+ if(dtost(dentry) == MODIFIED || dtost(dentry) == CREATED || dtost(dentry) == DEL_REWRITTEN) -+ return 1; -+ return 0; -+} -+ -+/* check if dentry is in an existing state */ -+int is_mini_fo_existant(dentry_t *dentry) -+{ -+ check_mini_fo_dentry(dentry); -+ -+ if(dtost(dentry) == DELETED || dtost(dentry) == NON_EXISTANT) -+ return 0; -+ else -+ return 1; -+} -+ -+/* -+ * This function will create a negative storage dentry for -+ * dentry, what is required for many create like options. -+ * It will create the storage structure if necessary. -+ */ -+int get_neg_sto_dentry(dentry_t *dentry) -+{ -+ int err = 0; -+ unsigned int len; -+ const unsigned char *name; -+ -+ if(!dentry || -+ !dtopd(dentry) || -+ !(dtost(dentry) == UNMODIFIED || -+ dtost(dentry) == NON_EXISTANT || -+ dtost(dentry) == DELETED)) { -+ printk(KERN_CRIT "mini_fo: get_neg_sto_dentry: invalid dentry passed.\n"); -+ err = -1; -+ goto out; -+ } -+ /* Have we got a neg. dentry already? */ -+ if(dtohd2(dentry)) { -+ err = 0; -+ goto out; -+ } -+ if(dtost(dentry->d_parent) == UNMODIFIED) { -+ /* build sto struct */ -+ err = build_sto_structure(dentry->d_parent->d_parent, dentry->d_parent); -+ if(err || -+ dtost(dentry->d_parent) != MODIFIED) { -+ printk(KERN_CRIT "mini_fo: get_neg_sto_dentry: ERROR building sto structure.\n"); -+ err = -1; -+ goto out; -+ } -+ } -+ -+ len = dentry->d_name.len; -+ name = dentry->d_name.name; -+ -+ dtohd2(dentry) = -+ lookup_one_len(name, dtohd2(dentry->d_parent), len); -+ -+ out: -+ return err; -+} -+ -+int check_mini_fo_dentry(dentry_t *dentry) -+{ -+ ASSERT(dentry != NULL); -+ ASSERT(dtopd(dentry) != NULL); -+ ASSERT((dtohd(dentry) != NULL) || (dtohd2(dentry) != NULL)); -+ -+/* if(dtost(dentry) == MODIFIED) { */ -+/* ASSERT(dentry->d_inode != NULL); */ -+/* ASSERT(dtohd(dentry) != NULL); */ -+/* ASSERT(dtohd(dentry)->d_inode != NULL); */ -+/* ASSERT(dtohd2(dentry) != NULL); */ -+/* ASSERT(dtohd2(dentry)->d_inode != NULL); */ -+/* } */ -+/* else if(dtost(dentry) == UNMODIFIED) { */ -+/* ASSERT(dentry->d_inode != NULL); */ -+/* ASSERT( */ -+/* } */ -+ return 0; -+} -+ -+int check_mini_fo_file(file_t *file) -+{ -+ ASSERT(file != NULL); -+ ASSERT(ftopd(file) != NULL); -+ ASSERT(file->f_dentry != NULL); -+ -+ /* violent checking, check depending of state and type -+ * if(S_ISDIR(file->f_dentry->d_inode->i_mode)) {} -+ */ -+ ASSERT((ftohf(file) != NULL) || (ftohf2(file) != NULL)); -+ return 0; -+} -+ -+int check_mini_fo_inode(inode_t *inode) -+{ -+ ASSERT(inode != NULL); -+ ASSERT(itopd(inode) != NULL); -+ ASSERT((itohi(inode) != NULL) || (itohi2(inode) != NULL)); -+ return 0; -+} -+ -+/* -+ * will walk a base path as provided by get_mini_fo_bpath and return -+ * the (hopefully ;-) ) positive dentry of the renamed base dir. -+ * -+ * This does some work of path_init. -+ */ -+dentry_t *bpath_walk(super_block_t *sb, char *bpath) -+{ -+ int err; -+ struct vfsmount *mnt; -+ struct nameidata nd; -+ -+ /* be paranoid */ -+ if(!bpath || bpath[0] != '/') { -+ printk(KERN_CRIT "mini_fo: bpath_walk: Invalid string.\n"); -+ return NULL; -+ } -+ if(!sb || !stopd(sb)) { -+ printk(KERN_CRIT "mini_fo: bpath_walk: Invalid sb.\n"); -+ return NULL; -+ } -+ -+ /* fix this: how do I reach this lock? -+ * read_lock(¤t->fs->lock); */ -+ mnt = mntget(stopd(sb)->hidden_mnt); -+ /* read_unlock(¤t->fs->lock); */ -+ -+ err = vfs_path_lookup(mnt->mnt_root, mnt, bpath+1, 0, &nd); -+ -+ /* validate */ -+ if (err || !nd.dentry || !nd.dentry->d_inode) { -+ printk(KERN_CRIT "mini_fo: bpath_walk: path_walk failed.\n"); -+ return NULL; -+ } -+ return nd.dentry; -+} -+ -+ -+/* returns the full path of the basefile incl. its name */ -+int get_mini_fo_bpath(dentry_t *dentry, char **bpath, int *bpath_len) -+{ -+ char *buf_walker; -+ int len = 0; -+ dentry_t *sky_walker; -+ -+ if(!dentry || !dtohd(dentry)) { -+ printk(KERN_CRIT "mini_fo: get_mini_fo_bpath: invalid dentry passed.\n"); -+ return -1; -+ } -+ sky_walker = dtohd(dentry); -+ -+ do { -+ len += sky_walker->d_name.len + 1 ; /* 1 for '/' */ -+ sky_walker = sky_walker->d_parent; -+ } while(sky_walker != stopd(dentry->d_inode->i_sb)->base_dir_dentry); -+ -+ /* 1 to oil the loop */ -+ *bpath = (char*) kmalloc(len + 1, GFP_KERNEL); -+ if(!*bpath) { -+ printk(KERN_CRIT "mini_fo: get_mini_fo_bpath: out of mem.\n"); -+ return -1; -+ } -+ buf_walker = *bpath+len; /* put it on last char */ -+ *buf_walker = '\n'; -+ sky_walker = dtohd(dentry); -+ -+ do { -+ buf_walker -= sky_walker->d_name.len; -+ strncpy(buf_walker, -+ sky_walker->d_name.name, -+ sky_walker->d_name.len); -+ *(--buf_walker) = '/'; -+ sky_walker = sky_walker->d_parent; -+ } while(sky_walker != stopd(dentry->d_inode->i_sb)->base_dir_dentry); -+ -+ /* bpath_len doesn't count newline! */ -+ *bpath_len = len; -+ return 0; -+} -+ -+int mini_fo_cp_cont(dentry_t *tgt_dentry, struct vfsmount *tgt_mnt, -+ dentry_t *src_dentry, struct vfsmount *src_mnt) -+{ -+ void *buf; -+ mm_segment_t old_fs; -+ file_t *tgt_file; -+ file_t *src_file; -+ int bytes, len, tmp, err; -+ err = 0; -+ -+ if(!(tgt_dentry->d_inode && src_dentry->d_inode)) { -+ printk(KERN_CRIT "mini_fo_cp_cont: ERROR, neg. dentry passed.\n"); -+ err = -EINVAL; -+ goto out; -+ } -+ -+ dget(tgt_dentry); -+ dget(src_dentry); -+ mntget(tgt_mnt); -+ mntget(src_mnt); -+ -+ /* open file write only */ -+ tgt_file = dentry_open(tgt_dentry, tgt_mnt, 0x1); -+ if(!tgt_file || IS_ERR(tgt_file)) { -+ printk(KERN_CRIT "mini_fo_cp_cont: ERROR opening target file.\n"); -+ err = PTR_ERR(tgt_file); -+ goto out_err; -+ } -+ -+ /* open file read only */ -+ src_file = dentry_open(src_dentry, src_mnt, 0x0); -+ if(!src_file || IS_ERR(src_file)) { -+ printk(KERN_CRIT "mini_fo_cp_cont: ERROR opening source file.\n"); -+ err = PTR_ERR(src_file); -+ -+ /* close target file */ -+ fput(tgt_file); -+ goto out_err; -+ } -+ -+ /* check if the filesystem(s) support read respective write */ -+ if(!src_file->f_op->read || !tgt_file->f_op->write) { -+ printk(KERN_CRIT "mini_fo_cp_cont: ERROR, no fs read or write support.\n"); -+ err = -EPERM; -+ goto out_close; -+ } -+ -+ /* allocate a page for transfering the data */ -+ buf = (void *) __get_free_page(GFP_KERNEL); -+ if(!buf) { -+ printk(KERN_CRIT "mini_fo_cp_cont: ERROR, out of kernel mem.\n"); -+ goto out_err; -+ } -+ -+ tgt_file->f_pos = 0; -+ src_file->f_pos = 0; -+ -+ old_fs = get_fs(); -+ set_fs(KERNEL_DS); -+ -+ /* Doing this I assume that a read operation will return a full -+ * buffer while there is still data to read, and a less than -+ * full buffer when all data has been read. -+ */ -+ bytes = len = PAGE_SIZE; -+ while(bytes == len) { -+ bytes = src_file->f_op->read(src_file, buf, len, -+ &src_file->f_pos); -+ tmp = tgt_file->f_op->write(tgt_file, buf, bytes, -+ &tgt_file->f_pos); -+ if(tmp != bytes) { -+ printk(KERN_CRIT "mini_fo_cp_cont: ERROR writing.\n"); -+ goto out_close_unset; -+ } -+ } -+ -+ free_page((unsigned long) buf); -+ set_fs(old_fs); -+ fput(tgt_file); -+ fput(src_file); -+ goto out; -+ -+ out_close_unset: -+ free_page((unsigned long) buf); -+ set_fs(old_fs); -+ -+ out_close: -+ fput(tgt_file); -+ fput(src_file); -+ -+ out_err: -+ dput(tgt_dentry); -+ dput(src_dentry); -+ -+ /* mk: not sure if this need to be done */ -+ mntput(tgt_mnt); -+ mntput(src_mnt); -+ -+ out: -+ return err; -+} -+ -+/* mk: -+ * ndl (no-duplicate list) stuff -+ * This is used in mini_fo_readdir, to save the storage directory contents -+ * and later when reading base, match them against the list in order -+ * to avoid duplicates. -+ */ -+ -+/* add a file specified by name and len to the ndl -+ * Return values: 0 on success, <0 on failure. -+ */ -+int ndl_add_entry(struct readdir_data *rd, const char *name, int len) -+{ -+ struct ndl_entry *tmp_entry; -+ -+ tmp_entry = (struct ndl_entry *) -+ kmalloc(sizeof(struct ndl_entry), GFP_KERNEL); -+ if(!tmp_entry) { -+ printk(KERN_CRIT "mini_fo: ndl_add_entry: out of mem.\n"); -+ return -ENOMEM; -+ } -+ tmp_entry->name = (char*) kmalloc(len, GFP_KERNEL); -+ if(!tmp_entry->name) { -+ printk(KERN_CRIT "mini_fo: ndl_add_entry: out of mem.\n"); -+ return -ENOMEM; -+ } -+ strncpy(tmp_entry->name, name, len); -+ tmp_entry->len = len; -+ -+ list_add(&tmp_entry->list, &rd->ndl_list); -+ rd->ndl_size++; -+ return 0; -+} -+ -+/* delete all list entries and free memory */ -+void ndl_put_list(struct readdir_data *rd) -+{ -+ struct list_head *tmp; -+ struct ndl_entry *tmp_entry; -+ -+ if(rd->ndl_size <= 0) -+ return; -+ while(!list_empty(&rd->ndl_list)) { -+ tmp = rd->ndl_list.next; -+ list_del(tmp); -+ tmp_entry = list_entry(tmp, struct ndl_entry, list); -+ kfree(tmp_entry->name); -+ kfree(tmp_entry); -+ } -+ rd->ndl_size = 0; -+} -+ -+/* Check if a file specified by name and len is in the ndl -+ * Return value: 0 if not in list, 1 if file is found in ndl. -+ */ -+int ndl_check_entry(struct readdir_data *rd, const char *name, int len) -+{ -+ struct list_head *tmp; -+ struct ndl_entry *tmp_entry; -+ -+ if(rd->ndl_size <= 0) -+ return 0; -+ -+ list_for_each(tmp, &rd->ndl_list) { -+ tmp_entry = list_entry(tmp, struct ndl_entry, list); -+ if(tmp_entry->len != len) -+ continue; -+ if(!strncmp(tmp_entry->name, name, len)) -+ return 1; -+ } -+ return 0; -+} -+ -+/* mk: -+ * Recursive function to create corresponding directorys in the storage fs. -+ * The function will build the storage directorys up to dentry. -+ */ -+int build_sto_structure(dentry_t *dir, dentry_t *dentry) -+{ -+ int err; -+ dentry_t *hidden_sto_dentry; -+ dentry_t *hidden_sto_dir_dentry; -+ -+ if(dentry->d_parent != dir) { -+ printk(KERN_CRIT "mini_fo: build_sto_structure: invalid parameter or meta data corruption [1].\n"); -+ return 1; -+ } -+ -+ if(dtost(dir) != MODIFIED) { -+ err = build_sto_structure(dir->d_parent, dentry->d_parent); -+ if(err) -+ return err; -+ } -+ -+ /* ok, coming back again. */ -+ check_mini_fo_dentry(dentry); -+ hidden_sto_dentry = dtohd2(dentry); -+ -+ if(!hidden_sto_dentry) { -+ /* -+ * This is the case after creating the first -+ * hidden_sto_dentry. -+ * After one negative storage_dentry, all pointers to -+ * hidden_storage dentries are set to NULL. We need to -+ * create the negative dentry before we create the storage -+ * file. -+ */ -+ unsigned int len; -+ const unsigned char *name; -+ len = dtohd(dentry)->d_name.len; -+ name = dtohd(dentry)->d_name.name; -+ hidden_sto_dentry = lookup_one_len(name, dtohd2(dir), len); -+ dtohd2(dentry) = hidden_sto_dentry; -+ } -+ -+ /* was: hidden_sto_dir_dentry = lock_parent(hidden_sto_dentry); */ -+ hidden_sto_dir_dentry = dget(hidden_sto_dentry->d_parent); -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16) -+ mutex_lock(&hidden_sto_dir_dentry->d_inode->i_mutex); -+#else -+ down(&hidden_sto_dir_dentry->d_inode->i_sem); -+#endif -+ /* lets be safe */ -+ if(dtohd2(dir) != hidden_sto_dir_dentry) { -+ printk(KERN_CRIT "mini_fo: build_sto_structure: invalid parameter or meta data corruption [2].\n"); -+ return 1; -+ } -+ -+ /* check for errors in lock_parent */ -+ err = PTR_ERR(hidden_sto_dir_dentry); -+ if(IS_ERR(hidden_sto_dir_dentry)) { -+ printk(KERN_CRIT "mini_fo: build_sto_structure: lock_parent failed.\n"); -+ return err; -+ } -+ -+ err = vfs_mkdir(hidden_sto_dir_dentry->d_inode, -+ hidden_sto_dentry, -+ dir->d_inode->i_mode); -+ -+ if(err) { -+ printk(KERN_CRIT "mini_fo: build_sto_structure: failed to create storage dir [1].\n"); -+ /* was: unlock_dir(dir); */ -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16) -+ mutex_unlock(&dir->d_inode->i_mutex); -+#else -+ up(&dir->d_inode->i_sem); -+#endif -+ dput(dir); -+ return err; -+ } -+ -+ /* everything ok! */ -+ if(!dtohd2(dentry)->d_inode) { -+ printk(KERN_CRIT "mini_fo: build_sto_structure: failed to create storage dir [2].\n"); -+ /* was: unlock_dir(dir); */ -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16) -+ mutex_unlock(&dir->d_inode->i_mutex); -+#else -+ up(&dir->d_inode->i_sem); -+#endif -+ dput(dir); -+ return 1; -+ } -+ -+ /* interpose the new inode and set new state */ -+ itohi2(dentry->d_inode) = igrab(dtohd2(dentry)->d_inode); -+ dtopd(dentry)->state = MODIFIED; -+ -+ /* initalize the wol list */ -+ itopd(dentry->d_inode)->deleted_list_size = -1; -+ itopd(dentry->d_inode)->renamed_list_size = -1; -+ meta_build_lists(dentry); -+ -+ fist_copy_attr_all(dentry->d_inode, itohi2(dentry->d_inode)); -+ fist_copy_attr_timesizes(dir->d_inode, -+ hidden_sto_dir_dentry->d_inode); -+ dir->d_inode->i_nlink++; -+ /* was: unlock_dir(hidden_sto_dir_dentry); */ -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16) -+ mutex_unlock(&hidden_sto_dir_dentry->d_inode->i_mutex); -+#else -+ up(&hidden_sto_dir_dentry->d_inode->i_sem); -+#endif -+ dput(hidden_sto_dir_dentry); -+ return 0; -+} -+ -+ -+#if 0 /* unused */ -+ -+/* -+ * Read "len" bytes from "filename" into "buf". -+ * "buf" is in kernel space. -+ */ -+int -+mini_fo_read_file(const char *filename, void *buf, int len) -+{ -+ file_t *filp; -+ mm_segment_t oldfs; -+ int bytes; -+ /* Chroot? Maybe NULL isn't right here */ -+ filp = filp_open(filename, O_RDONLY, 0); -+ if (!filp || IS_ERR(filp)) { -+ printk("mini_fo_read_file err %d\n", (int) PTR_ERR(filp)); -+ return -1; /* or do something else */ -+ } -+ -+ if (!filp->f_op->read) -+ return -2; /* file(system) doesn't allow reads */ -+ -+ /* now read len bytes from offset 0 */ -+ filp->f_pos = 0; /* start offset */ -+ oldfs = get_fs(); -+ set_fs(KERNEL_DS); -+ bytes = filp->f_op->read(filp, buf, len, &filp->f_pos); -+ set_fs(oldfs); -+ -+ /* close the file */ -+ fput(filp); -+ -+ return bytes; -+} -+ -+ -+ -+/* -+ * Write "len" bytes from "buf" to "filename" -+ * "buf" is in kernel space. -+ */ -+int -+mini_fo_write_file(const char *filename, void *buf, int len) -+{ -+ file_t *filp; -+ mm_segment_t oldfs; -+ int bytes; -+ /* Chroot? Maybe NULL isn't right here */ -+ filp = filp_open(filename, O_RDWR|O_CREAT, 0640); -+ if (!filp || IS_ERR(filp)) { -+ printk("mini_fo_write_file err %d\n", (int) PTR_ERR(filp)); -+ return -1; /* or do something else */ -+ } -+ -+ if (!filp->f_op->write) -+ return -2; /* file(system) doesn't allow writes */ -+ -+ /* now write len bytes from offset 0 */ -+ filp->f_pos = 0; /* start offset */ -+ oldfs = get_fs(); -+ set_fs(KERNEL_DS); -+ bytes = filp->f_op->write(filp, buf, len, &filp->f_pos); -+ set_fs(oldfs); -+ -+ /* close the file */ -+ fput(filp); -+ -+ return bytes; -+} -+ -+#endif /* unused */ -+ ---- /dev/null -+++ b/fs/mini_fo/ChangeLog -@@ -0,0 +1,281 @@ -+2006-01-24 Markus Klotzbuecher -+ -+ * Add tons of ugly ifdefs to Ed L. Cashin's mutex patch to -+ retain backwards compatibility. -+ -+2006-01-24 Ed L. Cashin -+ -+ * Support for the new mutex infrastructure -+ (7892f2f48d165a34b0b8130c8a195dfd807b8cb6) -+ -+2005-10-15 Markus Klotzbuecher -+ -+ * Bugfix for a serious memory leak in mini_fo_follow_link. -+ -+2005-09-21 Markus Klotzbuecher -+ -+ * new release 0.6.1 -+ -+ * fix of a compiler warning due to changes in 2.6.13 -+ -+2005-09-21 Klaus Wenninger -+ -+ * file.c: readdir: fix for a bug that caused directory entries -+ to show up twice when using storage filesystems such as -+ minixfs or pramfs. -+ -+2005-06-30 Eric Lammerts -+ -+ * fix for an oops when overwriting a binary thats beeing -+ executed. -+ -+2005-06-09 -+ -+ * Renamed overlay to mini_fo-overlay. -+ -+ * Added mini_fo-merge script to allow merging of storage and base -+ after making modifications. -+ -+2005-05-22 root -+ -+ * Added overlay script that allows to easily mount mini_fo ontop -+ of a given base directory -+ -+2005-05-10 -+ -+ * inode.c: xattr functions return -EOPNOSUPP instead of -+ -ENOSUPP, what confuses "ls -l" -+ -+ * Changed license from LGPL to GPL. -+ -+2005-05-08 root -+ -+ * Makefile: clean it up and added make install and make -+ uninstall. -+ -+2005-05-06 -+ -+ * merged devel branch back to main. [v0-6-0-pre3] -+ -+ * removed unused files print.c and fist_ioctl. [devel-0-0-18] -+ -+ * ioctl: removed fist_ioctl stuff, that is not needed for -+ now. -+ -+2005-05-03 -+ -+ * file.c: simplified mini_fo_open and mini_fo_setattr using -+ new state changing functions. [devel-0-0-17] -+ -+ * inode.c: Fixed getattr state bug (see below) in 2.4 function -+ mini_fo_inode revalidate. -+ -+ * inode.c: found an other bug in mini_fo_getattr. States are not -+ reliable in this function, as a file can be opened, unlinked and -+ the getattr function called. This results in a deleted dentry -+ with an inode. Fix is to ignore states and simply use the inode -+ available. -+ -+2005-04-29 -+ -+ * file.c: Bugfix and cleanup in fasync and fsync. [devel-0-0-16] -+ -+ * file.c: do not use mini_fo_lock so the generic version is -+ used (I guess). -+ -+ * inode.c: getattr, never call getattr on lower files, as this -+ will cause the inum to change. -+ -+ * inode.c: rename_reg_file renamed to rename_nondir, as it -+ doesn't matter as long it't not a dir. Removed all -+ rename_dev_file etc. -+ -+ * tagged as devel-0-0-15 -+ -+ * inode.c: added support for chosing support for extended -+ attrs at compile time by XATTR define in mini_fo.h . -+ -+ * inode.c: fixed mini_fo_getattr to use mini_fo inode and not -+ lower again, what avoids inode number changes that confused -+ rm again. This is the proper solution. -+ -+2005-04-24 -+ -+ * all files: updated Copyright notive to 2005. [devel-0-0-14] -+ -+ * inode.c: fixed mini_fo_getattr to not change the inode -+ number, even if lower files change. -+ -+ * super.c: fixed a bug that caused deleted base file to show -+ up suddenly after some time, or after creating a special -+ file. The problem was that after some time or after special -+ file creating sync_sb_inodes is called by the vfs, that -+ called our mini_fo_put_inode. There was (wrongly) called -+ __meta_put_lists, that nuked the lists, although the inode -+ was going to continue its life. Moving __meta_put_lists to -+ mini_fo_clear_inode, where an inode is really destroyed, -+ solved the problem. -+ -+ -+2005-04-23 -+ -+ * state.c, aux.c: more cleaning up and -+ simplifications. [devel-0-0-13] -+ -+ * inode.c: implemented mini_fo_getattr, that was required for -+ 2.6 because inode_revalidate has been remove there, and the -+ old "du" bug returned. -+ -+ -+2005-04-20 -+ -+ * aux.c: get_neg_sto_dentry(): allow to be called for dentries -+ in state UNMODIFIED, NON_EXISTANT _and_ DELETED. -+ -+2005-04-19 -+ -+ * Fixed a bug under 2.6 that caused files deleted via mini_fo -+ not to be deleted properly and therefore the fs filled up -+ untill no memory was left. [devel-0-0-12] -+ -+ * Added basic hard link support. This means that creating -+ hardlinks will work, but existing ones will be treated as -+ individual files. [devel-0-0-11] -+ -+2005-04-17 -+ -+ * Bugfixes -+ -+2005-04-13 root -+ -+ * Added file state.c for the state transition -+ functions. Doesn't work very well yet, though... -+ -+2005-04-12 -+ -+ * Porting to 2.6 started, which is easier than expected, also -+ due to Olivier previous work. -+ -+2005-04-08 -+ -+ * Fixed the bug that caused du to return invalid sizes of -+ directory trees. The problem was that -+ mini_fo_inode_revalidate didn't always copy the attributes -+ from the base inode properly. -+ -+2005-04-01 Markus Klotzbuecher -+ -+ * Merged devel branch back to main trunk and updated the -+ RELEASE notes. This will be 0-6-0-pre1. -+ -+2005-03-31 Markus Klotzbuecher -+ -+ * Fixed some bugs in rename_reg_file, that only showed up in -+ the kernel compile test. Kernel compiles cleanly ontop of -+ mini_fo, now also make mrproper etc. work. Seems pretty stable. -+ -+2005-03-28 Markus Klotzbuecher -+ -+ * Many, many directory renaming bugfixes and a lot of other -+ cleanup. Dir renaming seems to work relatively stable. -+ -+2005-03-22 Markus Klotzbuecher -+ -+ * Finished implementing lightweight directory renaming. Some -+ basic testing indicates it works fine. -+ Next is to implement testcases for the testsuite and confirm -+ everything is really working ok. -+ -+2005-03-18 Markus Klotzbuecher -+ -+ * Finished implementing meta.c stuff required for directory -+ renaming. -+ -+2005-03-17 Markus Klotzbuecher -+ -+ * Fixed all compile warnings + an extremly old bug that -+ somehow crept in while reworking the wol stuff to the META -+ system. Turning on -Werror again... :-) -+ -+ * Fixed some bugs in the new rename_reg_file function. -+ -+ * Rewrote mini_fo rename and split it into several -+ subfunctions, that handle the different types -+ seperately. Rewrote the regular file function aswell, as it -+ was implemented somewhat inefficient. -+ -+2005-03-16 Markus Klotzbuecher -+ -+ * Implemented new META subsystem, removed old WOL stuff in favor -+ if it. -+ -+ * After some basic testing everything seems ok... -+ -+2005-03-11 Markus Klotzbuecher -+ -+ * Renaming a non regular file caused trouble because I always -+ tried to copy the contents. Now I only do this for regular -+ files. mini_fo_rename still isn't implemented properly, renaming -+ of device files, symlinks etc. results in a empty regular file -+ instead of the proper type. -+ -+ * Directory renaming suddenly works! What a surprise! I guess -+ this is because renaming is implemented as making a copy and -+ removing the original. Still this might not work -+ everywhere... -+ -+2005-03-09 Markus Klotzbuecher -+ -+ * Bugfix, when a mini_fo directory that exists in storage -+ (state: MODIFIED, CREATED and DEL_REWRITTEN) is deleted, a -+ possibly existing WOL file contained in it needs to be -+ deleted too. -+ -+ * Starting cleanup: defined state names in order to get rid of -+ the state numbers. -+ -+2005-03-08 Markus Klotzbuecher -+ -+ * Makefile fix, fist_ioctl was built against wrong sources if ARCH=um -+ -+ * Fixed a bug in dentry.c, mini_fo_d_hash. In state 4 = -+ DEL_REWRITTEN the hash was calculated from the base dentry, -+ which was wrong and and caused assertions in -+ __mini_fo_hidden_dentry to fail. -+ -+2005-02-21 -+ -+ * Implemented directory deleting (inode.c) -+ -+ * main.c: made mini_fo_parse_options a little more robust. -+ -+2004-12-22 -+ -+ * Makefile cleanup and uml stuff, removed unneccessary files -+ -+ * Created a new and hopefully more informative README -+ -+ * CHANGELOG: created a new CHANGELOG and added old entries reversely -+ -+ -+2004-10-24 Gleb Natapov -+ -+ * Fix: owner and group where not correctly copied from base to -+ storage. -+ -+ -+2004-10-05 Gleb Natapov -+ -+ * Implementation of fsync, fasync and lock mini_fo functions. -+ -+ -+2004-09-29 Bob Lee -+ -+ * Fix of a serious pointer bug -+ -+ -+2004-09-28 Gleb Natapov -+ -+ * Implementation of mini_fo_mknod and mini_fo_rename, support -+ for device files. -+ ---- /dev/null -+++ b/fs/mini_fo/dentry.c -@@ -0,0 +1,244 @@ -+/* -+ * Copyright (c) 1997-2003 Erez Zadok -+ * Copyright (c) 2001-2003 Stony Brook University -+ * -+ * For specific licensing information, see the COPYING file distributed with -+ * this package, or get one from ftp://ftp.filesystems.org/pub/fist/COPYING. -+ * -+ * This Copyright notice must be kept intact and distributed with all -+ * fistgen sources INCLUDING sources generated by fistgen. -+ */ -+/* -+ * Copyright (C) 2004, 2005 Markus Klotzbuecher -+ * -+ * 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. -+ */ -+ -+/* -+ * $Id$ -+ */ -+ -+#ifdef HAVE_CONFIG_H -+# include -+#endif -+ -+#include "fist.h" -+#include "mini_fo.h" -+ -+/* -+ * THIS IS A BOOLEAN FUNCTION: returns 1 if valid, 0 otherwise. -+ */ -+STATIC int -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) -+mini_fo_d_revalidate(dentry_t *dentry, struct nameidata *nd) -+#else -+mini_fo_d_revalidate(dentry_t *dentry, int flags) -+#endif -+{ -+ int err1 = 1; /* valid = 1, invalid = 0 */ -+ int err2 = 1; -+ dentry_t *hidden_dentry; -+ dentry_t *hidden_sto_dentry; -+ -+ -+ check_mini_fo_dentry(dentry); -+ -+ hidden_dentry = dtohd(dentry); -+ hidden_sto_dentry = dtohd2(dentry); -+ -+ if(hidden_dentry && -+ hidden_dentry->d_op && -+ hidden_dentry->d_op->d_revalidate) { -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) -+ err1 = hidden_dentry->d_op->d_revalidate(hidden_dentry, nd); -+#else -+ err1 = hidden_dentry->d_op->d_revalidate(hidden_dentry, flags); -+#endif -+ } -+ if(hidden_sto_dentry && -+ hidden_sto_dentry->d_op && -+ hidden_sto_dentry->d_op->d_revalidate) { -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) -+ err2 = hidden_sto_dentry->d_op->d_revalidate(hidden_sto_dentry, -+ nd); -+#else -+ err2 = hidden_sto_dentry->d_op->d_revalidate(hidden_sto_dentry, -+ flags); -+#endif -+ } -+ -+ /* mk: if one of the lower level dentries are valid, -+ * the mini_fo dentry is too. -+ */ -+ return (err1 || err2); -+} -+ -+ -+STATIC int -+mini_fo_d_hash(dentry_t *dentry, qstr_t *name) -+{ -+ int err = 0; -+ dentry_t *hidden_dentry; -+ dentry_t *hidden_sto_dentry; -+ -+ /* hidden_dentry = mini_fo_hidden_dentry(dentry); -+ * hidden_sto_dentry = mini_fo_hidden_sto_dentry(dentry); */ -+ -+ /* state 1, 3, 4, 5: build the hash for the storage dentry */ -+ if((dtopd(dentry)->state == MODIFIED) || -+ (dtopd(dentry)->state == CREATED) || -+ (dtopd(dentry)->state == DEL_REWRITTEN) || -+ (dtopd(dentry)->state == DELETED)) { -+ hidden_sto_dentry = dtohd2(dentry); -+ if(hidden_sto_dentry && -+ hidden_sto_dentry->d_op && -+ hidden_sto_dentry->d_op->d_hash) { -+ err = hidden_sto_dentry->d_op->d_hash(hidden_sto_dentry, name); -+ } -+ goto out; -+ } -+ /* state 2: build the hash for the base dentry */ -+ if(dtopd(dentry)->state == UNMODIFIED) { -+ hidden_dentry = dtohd(dentry); -+ if(hidden_dentry && -+ hidden_dentry->d_op && -+ hidden_dentry->d_op->d_hash) { -+ err = hidden_dentry->d_op->d_hash(hidden_dentry, name); -+ } -+ goto out; -+ } -+ /* state 6: build hash for the dentry that exists */ -+ if(dtopd(dentry)->state == NON_EXISTANT) { -+ hidden_sto_dentry = dtohd2(dentry); -+ if(hidden_sto_dentry && -+ hidden_sto_dentry->d_op && -+ hidden_sto_dentry->d_op->d_hash) { -+ err = hidden_sto_dentry->d_op->d_hash(hidden_sto_dentry, name); -+ goto out; -+ } -+ hidden_dentry = dtohd(dentry); -+ if(hidden_dentry && -+ hidden_dentry->d_op && -+ hidden_dentry->d_op->d_hash) { -+ err = hidden_dentry->d_op->d_hash(hidden_dentry, name); -+ goto out; -+ } -+ } -+ -+ printk(KERN_CRIT "mini_fo: d_hash: invalid state detected.\n"); -+ -+ out: -+ return err; -+} -+ -+ -+STATIC int -+mini_fo_d_compare(dentry_t *dentry, qstr_t *a, qstr_t *b) -+{ -+ int err; -+ dentry_t *hidden_dentry=NULL; -+ -+ /* hidden_dentry = mini_fo_hidden_dentry(dentry); */ -+ if(dtohd2(dentry)) -+ hidden_dentry = dtohd2(dentry); -+ else if(dtohd(dentry)) -+ hidden_dentry = dtohd(dentry); -+ -+ if (hidden_dentry && hidden_dentry->d_op && hidden_dentry->d_op->d_compare) { -+ err = hidden_dentry->d_op->d_compare(hidden_dentry, a, b); -+ } else { -+ err = ((a->len != b->len) || memcmp(a->name, b->name, b->len)); -+ } -+ -+ return err; -+} -+ -+ -+int -+mini_fo_d_delete(dentry_t *dentry) -+{ -+ dentry_t *hidden_dentry; -+ dentry_t *hidden_sto_dentry; -+ int err = 0; -+ -+ /* this could be a negative dentry, so check first */ -+ if (!dtopd(dentry)) { -+ printk(KERN_CRIT "mini_fo_d_delete: negative dentry passed.\n"); -+ goto out; -+ } -+ hidden_dentry = dtohd(dentry); -+ hidden_sto_dentry = dtohd2(dentry); -+ -+ if(hidden_dentry) { -+ if(hidden_dentry->d_op && -+ hidden_dentry->d_op->d_delete) { -+ err = hidden_dentry->d_op->d_delete(hidden_dentry); -+ } -+ } -+ if(hidden_sto_dentry) { -+ if(hidden_sto_dentry->d_op && -+ hidden_sto_dentry->d_op->d_delete) { -+ err = hidden_sto_dentry->d_op->d_delete(hidden_sto_dentry); -+ } -+ } -+ -+ out: -+ return err; -+} -+ -+ -+void -+mini_fo_d_release(dentry_t *dentry) -+{ -+ dentry_t *hidden_dentry; -+ dentry_t *hidden_sto_dentry; -+ -+ -+ /* this could be a negative dentry, so check first */ -+ if (!dtopd(dentry)) { -+ printk(KERN_CRIT "mini_fo_d_release: no private data.\n"); -+ goto out; -+ } -+ hidden_dentry = dtohd(dentry); -+ hidden_sto_dentry = dtohd2(dentry); -+ -+ if(hidden_dentry) { -+ /* decrement hidden dentry's counter and free its inode */ -+ dput(hidden_dentry); -+ } -+ if(hidden_sto_dentry) { -+ /* decrement hidden dentry's counter and free its inode */ -+ dput(hidden_sto_dentry); -+ } -+ -+ /* free private data (mini_fo_dentry_info) here */ -+ kfree(dtopd(dentry)); -+ __dtopd(dentry) = NULL; /* just to be safe */ -+ out: -+ return; -+} -+ -+ -+/* -+ * we don't really need mini_fo_d_iput, because dentry_iput will call iput() if -+ * mini_fo_d_iput is not defined. We left this implemented for ease of -+ * tracing/debugging. -+ */ -+void -+mini_fo_d_iput(dentry_t *dentry, inode_t *inode) -+{ -+ iput(inode); -+} -+ -+ -+struct dentry_operations mini_fo_dops = { -+ d_revalidate: mini_fo_d_revalidate, -+ d_hash: mini_fo_d_hash, -+ d_compare: mini_fo_d_compare, -+ d_release: mini_fo_d_release, -+ d_delete: mini_fo_d_delete, -+ d_iput: mini_fo_d_iput, -+}; ---- /dev/null -+++ b/fs/mini_fo/file.c -@@ -0,0 +1,713 @@ -+/* -+ * Copyright (c) 1997-2003 Erez Zadok -+ * Copyright (c) 2001-2003 Stony Brook University -+ * -+ * For specific licensing information, see the COPYING file distributed with -+ * this package, or get one from ftp://ftp.filesystems.org/pub/fist/COPYING. -+ * -+ * This Copyright notice must be kept intact and distributed with all -+ * fistgen sources INCLUDING sources generated by fistgen. -+ */ -+/* -+ * Copyright (C) 2004, 2005 Markus Klotzbuecher -+ * -+ * 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. -+ */ -+ -+/* -+ * $Id$ -+ */ -+ -+#ifdef HAVE_CONFIG_H -+# include -+#endif -+ -+#include "fist.h" -+#include "mini_fo.h" -+#define ROUND_UP(x) (((x)+sizeof(long)-1) & ~(sizeof(long)-1)) -+ -+/******************* -+ * File Operations * -+ *******************/ -+ -+STATIC loff_t -+mini_fo_llseek(file_t *file, loff_t offset, int origin) -+{ -+ loff_t err; -+ file_t *hidden_file = NULL; -+ -+ if(S_ISDIR(file->f_dentry->d_inode->i_mode)) { -+ /* Check if trying to llseek from a directory */ -+ err = -EISDIR; -+ goto out; -+ } -+ if (ftopd(file) != NULL) { -+ if(ftohf2(file)) { -+ hidden_file = ftohf2(file); -+ } else { -+ hidden_file = ftohf(file); -+ } -+ } -+ -+ /* always set hidden position to this one */ -+ hidden_file->f_pos = file->f_pos; -+ -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) -+ memcpy(&(hidden_file->f_ra), -+ &(file->f_ra), -+ sizeof(struct file_ra_state)); -+#else -+ if (file->f_reada) { /* update readahead information if needed */ -+ hidden_file->f_reada = file->f_reada; -+ hidden_file->f_ramax = file->f_ramax; -+ hidden_file->f_raend = file->f_raend; -+ hidden_file->f_ralen = file->f_ralen; -+ hidden_file->f_rawin = file->f_rawin; -+ } -+#endif -+ if (hidden_file->f_op && hidden_file->f_op->llseek) -+ err = hidden_file->f_op->llseek(hidden_file, offset, origin); -+ else -+ err = generic_file_llseek(hidden_file, offset, origin); -+ -+ if (err < 0) -+ goto out; -+ -+ if (err != file->f_pos) { -+ file->f_pos = err; -+ // ION maybe this? -+ // file->f_pos = hidden_file->f_pos; -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) -+ file->f_reada = 0; -+#endif -+ file->f_version++; -+ } -+ -+ out: -+ return err; -+} -+ -+ -+/* mk: fanout capable */ -+STATIC ssize_t -+mini_fo_read(file_t *file, char *buf, size_t count, loff_t *ppos) -+{ -+ int err = -EINVAL; -+ file_t *hidden_file = NULL; -+ loff_t pos = *ppos; -+ -+ if(S_ISDIR(file->f_dentry->d_inode->i_mode)) { -+ /* Check if trying to read from a directory */ -+ /* printk(KERN_CRIT "mini_fo_read: ERROR: trying to read data from a directory.\n"); */ -+ err = -EISDIR; -+ goto out; -+ } -+ -+ if (ftopd(file) != NULL) { -+ if(ftohf2(file)) { -+ hidden_file = ftohf2(file); -+ } else { -+ hidden_file = ftohf(file); -+ } -+ } -+ -+ if (!hidden_file->f_op || !hidden_file->f_op->read) -+ goto out; -+ -+ err = hidden_file->f_op->read(hidden_file, buf, count, &pos); -+ *ppos = pos; -+ -+ if (err >= 0) { -+ /* atime should also be updated for reads of size zero or more */ -+ fist_copy_attr_atime(file->f_dentry->d_inode, -+ hidden_file->f_dentry->d_inode); -+ } -+ -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) -+ /* -+ * MAJOR HACK -+ * because pread() does not have any way to tell us that it is -+ * our caller, then we don't know for sure if we have to update -+ * the file positions. This hack relies on read() having passed us -+ * the "real" pointer of its struct file's f_pos field. -+ */ -+ if (ppos == &file->f_pos) -+ hidden_file->f_pos = *ppos = pos; -+ if (hidden_file->f_reada) { /* update readahead information if needed */ -+ file->f_reada = hidden_file->f_reada; -+ file->f_ramax = hidden_file->f_ramax; -+ file->f_raend = hidden_file->f_raend; -+ file->f_ralen = hidden_file->f_ralen; -+ file->f_rawin = hidden_file->f_rawin; -+ } -+#else -+ memcpy(&(file->f_ra),&(hidden_file->f_ra),sizeof(struct file_ra_state)); -+#endif -+ -+ out: -+ return err; -+} -+ -+ -+/* this mini_fo_write() does not modify data pages! */ -+STATIC ssize_t -+mini_fo_write(file_t *file, const char *buf, size_t count, loff_t *ppos) -+{ -+ int err = -EINVAL; -+ file_t *hidden_file = NULL; -+ inode_t *inode; -+ inode_t *hidden_inode; -+ loff_t pos = *ppos; -+ -+ /* mk: fan out: */ -+ if (ftopd(file) != NULL) { -+ if(ftohf2(file)) { -+ hidden_file = ftohf2(file); -+ } else { -+ /* This is bad! We have no storage file to write to. This -+ * should never happen because if a file is opened for -+ * writing, a copy should have been made earlier. -+ */ -+ printk(KERN_CRIT "mini_fo: write : ERROR, no storage file to write.\n"); -+ err = -EINVAL; -+ goto out; -+ } -+ } -+ -+ inode = file->f_dentry->d_inode; -+ hidden_inode = itohi2(inode); -+ if(!hidden_inode) { -+ printk(KERN_CRIT "mini_fo: write: no sto inode found, not good.\n"); -+ goto out; -+ } -+ -+ if (!hidden_file->f_op || !hidden_file->f_op->write) -+ goto out; -+ -+ /* adjust for append -- seek to the end of the file */ -+ if (file->f_flags & O_APPEND) -+ pos = inode->i_size; -+ -+ err = hidden_file->f_op->write(hidden_file, buf, count, &pos); -+ -+ /* -+ * copy ctime and mtime from lower layer attributes -+ * atime is unchanged for both layers -+ */ -+ if (err >= 0) -+ fist_copy_attr_times(inode, hidden_inode); -+ -+ *ppos = pos; -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) -+ /* -+ * XXX: MAJOR HACK -+ * -+ * because pwrite() does not have any way to tell us that it is -+ * our caller, then we don't know for sure if we have to update -+ * the file positions. This hack relies on write() having passed us -+ * the "real" pointer of its struct file's f_pos field. -+ */ -+ if (ppos == &file->f_pos) -+ hidden_file->f_pos = *ppos = pos; -+#endif -+ /* update this inode's size */ -+ if (pos > inode->i_size) -+ inode->i_size = pos; -+ -+ out: -+ return err; -+} -+ -+/* Global variable to hold a file_t pointer. -+ * This serves to allow mini_fo_filldir function to know which file is -+ * beeing read, which is required for two reasons: -+ * -+ * - be able to call wol functions in order to avoid listing deleted -+ * base files. -+ * - if we're reading a directory which is in state 1, we need to -+ * maintain a list (in mini_fo_filldir) of which files allready -+ * have been copied to userspace,to detect files existing in base -+ * and storage and not list them twice. -+ */ -+filldir_t mini_fo_filldir_orig; -+file_t *mini_fo_filldir_file; -+ -+/* mainly copied from fs/readdir.c */ -+STATIC int -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,18) -+mini_fo_filldir(void * __buf, const char * name, int namlen, loff_t offset, -+ u64 ino, unsigned int d_type) -+#else -+mini_fo_filldir(void * __buf, const char * name, int namlen, loff_t offset, -+ ino_t ino, unsigned int d_type) -+#endif -+{ -+ struct getdents_callback * buf = (struct getdents_callback *) __buf; -+ file_t* file = mini_fo_filldir_file; -+ -+ /* In theses states we filter meta files in storage (WOL) */ -+ if(file && (dtopd(file->f_dentry)->state == MODIFIED || -+ dtopd(file->f_dentry)->state == CREATED || -+ dtopd(file->f_dentry)->state == DEL_REWRITTEN)) { -+ -+ int tmp = strlen(META_FILENAME); -+ if(tmp == namlen) { -+ if(!strncmp(name, META_FILENAME, namlen)) -+ return 0; -+ } -+ } -+ -+ /* check if we are merging the contents of storage and base */ -+ if(file && dtopd(file->f_dentry)->state == MODIFIED) { -+ /* check if we are still reading storage contents, if -+ * yes, we just save the name of the file for duplicate -+ * checking later. */ -+ -+ if(!ftopd(file)->rd.sto_done) { -+ /* put file into ndl list */ -+ if(ndl_add_entry(&ftopd(file)->rd, name, namlen)) -+ printk(KERN_CRIT "mini_fo_filldir: Error adding to ndl.\n"); -+ } else { -+ /* check if file has been deleted */ -+ if(meta_check_d_entry(file->f_dentry, name, namlen)) -+ return 0; -+ -+ /* do duplicate checking */ -+ if(ndl_check_entry(&ftopd(file)->rd, name, namlen)) -+ return 0; -+ } -+ } -+ -+ return mini_fo_filldir_orig(buf, name, namlen, offset, ino, d_type); -+} -+ -+ -+STATIC int -+mini_fo_readdir(file_t *file, void *dirent, filldir_t filldir) -+{ -+ int err = 0;/* mk: ??? -ENOTDIR; */ -+ file_t *hidden_file = NULL; -+ file_t *hidden_sto_file = NULL; -+ inode_t *inode; -+ struct getdents_callback *buf; -+ int oldcount; -+ -+#if defined(FIST_FILTER_NAME) || defined(FIST_FILTER_SCA) -+ struct mini_fo_getdents_callback buf; -+#endif /* FIST_FILTER_NAME || FIST_FILTER_SCA */ -+ -+ buf = (struct getdents_callback *) dirent; -+ oldcount = buf->count; -+ inode = file->f_dentry->d_inode; -+ mini_fo_filldir_file = file; -+ mini_fo_filldir_orig = filldir; -+ -+ ftopd(file)->rd.sto_done = 0; -+ do { -+ if (ftopd(file) != NULL) { -+ if(ftohf2(file)) { -+ hidden_sto_file = ftohf2(file); -+ err = vfs_readdir(hidden_sto_file, mini_fo_filldir, dirent); -+ file->f_pos = hidden_sto_file->f_pos; -+ if (err > 0) -+ fist_copy_attr_atime(inode, hidden_sto_file->f_dentry->d_inode); -+ /* not finshed yet, we'll be called again */ -+ if (buf->count != oldcount) -+ break; -+ } -+ -+ ftopd(file)->rd.sto_done = 1; -+ -+ if(ftohf(file)) { -+ hidden_file = ftohf(file); -+ err = vfs_readdir(hidden_file, mini_fo_filldir, dirent); -+ file->f_pos = hidden_file->f_pos; -+ if (err > 0) -+ fist_copy_attr_atime(inode, hidden_file->f_dentry->d_inode); -+ } -+ -+ } -+ } while (0); -+ -+ /* mk: -+ * we need to check if all the directory data has been copied to userspace, -+ * or if we will be called again by userspace to complete the operation. -+ */ -+ if(buf->count == oldcount) { -+ ndl_put_list(&ftopd(file)->rd); -+ } -+ -+ /* unset this, safe */ -+ mini_fo_filldir_file = NULL; -+ return err; -+} -+ -+ -+STATIC unsigned int -+mini_fo_poll(file_t *file, poll_table *wait) -+{ -+ unsigned int mask = DEFAULT_POLLMASK; -+ file_t *hidden_file = NULL; -+ -+ if (ftopd(file) != NULL) { -+ if(ftohf2(file)) { -+ hidden_file = ftohf2(file); -+ } else { -+ hidden_file = ftohf(file); -+ } -+ } -+ -+ if (!hidden_file->f_op || !hidden_file->f_op->poll) -+ goto out; -+ -+ mask = hidden_file->f_op->poll(hidden_file, wait); -+ -+ out: -+ return mask; -+} -+ -+/* FIST-LITE special version of mmap */ -+STATIC int -+mini_fo_mmap(file_t *file, vm_area_t *vma) -+{ -+ int err = 0; -+ file_t *hidden_file = NULL; -+ -+ /* fanout capability */ -+ if (ftopd(file) != NULL) { -+ if(ftohf2(file)) { -+ hidden_file = ftohf2(file); -+ } else { -+ hidden_file = ftohf(file); -+ } -+ } -+ -+ ASSERT(hidden_file != NULL); -+ ASSERT(hidden_file->f_op != NULL); -+ ASSERT(hidden_file->f_op->mmap != NULL); -+ -+ vma->vm_file = hidden_file; -+ err = hidden_file->f_op->mmap(hidden_file, vma); -+ get_file(hidden_file); /* make sure it doesn't get freed on us */ -+ fput(file); /* no need to keep extra ref on ours */ -+ -+ return err; -+} -+ -+ -+ -+STATIC int -+mini_fo_open(inode_t *inode, file_t *file) -+{ -+ int err = 0; -+ int hidden_flags; -+ file_t *hidden_file = NULL; -+ dentry_t *hidden_dentry = NULL; -+ -+ /* fanout stuff */ -+ file_t *hidden_sto_file = NULL; -+ dentry_t *hidden_sto_dentry = NULL; -+ -+ __ftopd(file) = -+ kmalloc(sizeof(struct mini_fo_file_info), GFP_KERNEL); -+ if (!ftopd(file)) { -+ err = -ENOMEM; -+ goto out; -+ } -+ -+ /* init the readdir_helper structure */ -+ INIT_LIST_HEAD(&ftopd(file)->rd.ndl_list); -+ ftopd(file)->rd.ndl_size = 0; -+ -+ /* In certain paths this could stay uninitalized and cause trouble */ -+ ftohf(file) = NULL; -+ ftohf2(file) = NULL; -+ hidden_flags = file->f_flags; -+ -+ /* create storage files? */ -+ if(dtost(file->f_dentry) == UNMODIFIED) { -+ if(!IS_WRITE_FLAG(file->f_flags)) { -+ hidden_dentry = dtohd(file->f_dentry); -+ dget(hidden_dentry); -+ /* dentry_open will decrement mnt refcnt if err. -+ * otherwise fput() will do an mntput() for us upon file close. */ -+ mntget(stopd(inode->i_sb)->hidden_mnt); -+ hidden_file = dentry_open(hidden_dentry, -+ stopd(inode->i_sb)->hidden_mnt, -+ hidden_flags); -+ if (IS_ERR(hidden_file)) { -+ err = PTR_ERR(hidden_file); -+ dput(hidden_dentry); -+ goto out; -+ } -+ ftohf(file) = hidden_file; /* link two files */ -+ goto out; -+ } -+ else { -+ if(S_ISDIR(file->f_dentry->d_inode->i_mode)) { -+ err = dir_unmod_to_mod(file->f_dentry); -+ } else -+ err = nondir_unmod_to_mod(file->f_dentry, 1); -+ -+ if (err) { -+ printk("mini_fo_open: ERROR creating storage file.\n"); -+ goto out; -+ } -+ } -+ } -+ hidden_sto_dentry = dtohd2(file->f_dentry); -+ dget(hidden_sto_dentry); -+ -+ if(dtopd(file->f_dentry)->state == MODIFIED) { -+ /* Directorys are special, interpose on both lower level files */ -+ if(S_ISDIR(itohi(inode)->i_mode)) { -+ /* check for invalid file types of lower level files */ -+ if(!(S_ISDIR(itohi(inode)->i_mode) && S_ISDIR(itohi2(inode)->i_mode))) { -+ printk(KERN_CRIT "mini_fo_open: meta data corruption detected.\n"); -+ dput(hidden_sto_dentry); -+ err = -EINVAL; -+ goto out; -+ } -+ -+ /* lower level directorys are ok, open the base file */ -+ hidden_dentry = dtohd(file->f_dentry); -+ dget(hidden_dentry); -+ -+ mntget(stopd(inode->i_sb)->hidden_mnt); -+ hidden_file = dentry_open(hidden_dentry, -+ stopd(inode->i_sb)->hidden_mnt, -+ hidden_flags); -+ if (IS_ERR(hidden_file)) { -+ err = PTR_ERR(hidden_file); -+ dput(hidden_dentry); -+ dput(hidden_sto_dentry); -+ goto out; -+ } -+ ftohf(file) = hidden_file; /* link the two files */ -+ } -+ } -+ -+ if(!exists_in_storage(file->f_dentry)) { -+ printk(KERN_CRIT "mini_fo_open: invalid file state detected.\n"); -+ err = -EINVAL; -+ dput(hidden_sto_dentry); -+ -+ /* If the base file has been opened, we need to close it here */ -+ if(ftohf(file)) { -+ if (hidden_file->f_op && hidden_file->f_op->flush) -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,18) -+ hidden_file->f_op->flush(hidden_file, NULL); -+#else -+ hidden_file->f_op->flush(hidden_file); -+#endif -+ dput(hidden_dentry); -+ } -+ goto out; -+ } -+ -+ /* ok, now we can safely open the storage file */ -+ mntget(stopd(inode->i_sb)->hidden_mnt2); -+ hidden_sto_file = dentry_open(hidden_sto_dentry, -+ stopd(inode->i_sb)->hidden_mnt2, -+ hidden_flags); -+ -+ /* dentry_open dputs the dentry if it fails */ -+ if (IS_ERR(hidden_sto_file)) { -+ err = PTR_ERR(hidden_sto_file); -+ /* close base file if open */ -+ if(ftohf(file)) { -+ if (hidden_file->f_op && hidden_file->f_op->flush) -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,18) -+ hidden_file->f_op->flush(hidden_file, NULL); -+#else -+ hidden_file->f_op->flush(hidden_file); -+#endif -+ dput(hidden_dentry); -+ } -+ goto out; -+ } -+ ftohf2(file) = hidden_sto_file; /* link storage file */ -+ -+ out: -+ if (err < 0 && ftopd(file)) { -+ kfree(ftopd(file)); -+ } -+ return err; -+} -+ -+STATIC int -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,18) -+mini_fo_flush(file_t *file, fl_owner_t id) -+#else -+mini_fo_flush(file_t *file) -+#endif -+{ -+ int err1 = 0; /* assume ok (see open.c:close_fp) */ -+ int err2 = 0; -+ file_t *hidden_file = NULL; -+ -+ check_mini_fo_file(file); -+ -+ /* mk: we don't do any state checking here, as its not worth the time. -+ * Just flush the lower level files if they exist. -+ */ -+ if(ftopd(file) != NULL) { -+ if(ftohf(file) != NULL) { -+ hidden_file = ftohf(file); -+ if (hidden_file->f_op && hidden_file->f_op->flush) -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,18) -+ err1 = hidden_file->f_op->flush(hidden_file, id); -+#else -+ err1 = hidden_file->f_op->flush(hidden_file); -+#endif -+ } -+ if(ftohf2(file) != NULL) { -+ hidden_file = ftohf2(file); -+ if (hidden_file->f_op && hidden_file->f_op->flush) -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,18) -+ err2 = hidden_file->f_op->flush(hidden_file, id); -+#else -+ err2 = hidden_file->f_op->flush(hidden_file); -+#endif -+ } -+ } -+ return (err1 | err2); -+} -+ -+ -+STATIC int -+mini_fo_release(inode_t *inode, file_t *file) -+{ -+ int err = 0; -+ file_t *hidden_file = NULL; -+ -+ if (ftopd(file) != NULL) { -+ if(ftohf(file)) { -+ hidden_file = ftohf(file); -+ fput(hidden_file); -+ } -+ if(ftohf2(file)) { -+ hidden_file = ftohf2(file); -+ fput(hidden_file); -+ } -+ kfree(ftopd(file)); -+ } -+ return err; -+} -+ -+STATIC int -+mini_fo_fsync(file_t *file, dentry_t *dentry, int datasync) -+{ -+ int err1 = 0; -+ int err2 = 0; -+ file_t *hidden_file = NULL; -+ dentry_t *hidden_dentry; -+ -+ check_mini_fo_file(file); -+ -+ if ((hidden_file = ftohf(file)) != NULL) { -+ hidden_dentry = dtohd(dentry); -+ if (hidden_file->f_op && hidden_file->f_op->fsync) { -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16) -+ mutex_lock(&hidden_dentry->d_inode->i_mutex); -+#else -+ down(&hidden_dentry->d_inode->i_sem); -+#endif -+ err1 = hidden_file->f_op->fsync(hidden_file, hidden_dentry, datasync); -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16) -+ mutex_unlock(&hidden_dentry->d_inode->i_mutex); -+#else -+ up(&hidden_dentry->d_inode->i_sem); -+#endif -+ } -+ } -+ -+ if ((hidden_file = ftohf2(file)) != NULL) { -+ hidden_dentry = dtohd2(dentry); -+ if (hidden_file->f_op && hidden_file->f_op->fsync) { -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16) -+ mutex_lock(&hidden_dentry->d_inode->i_mutex); -+#else -+ down(&hidden_dentry->d_inode->i_sem); -+#endif -+ err2 = hidden_file->f_op->fsync(hidden_file, hidden_dentry, datasync); -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16) -+ mutex_unlock(&hidden_dentry->d_inode->i_mutex); -+#else -+ up(&hidden_dentry->d_inode->i_sem); -+#endif -+ } -+ } -+ else -+ goto err; -+ -+err: -+ return (err1 || err2); -+} -+ -+ -+STATIC int -+mini_fo_fasync(int fd, file_t *file, int flag) -+{ -+ int err1 = 0; -+ int err2 = 0; -+ -+ file_t *hidden_file = NULL; -+ -+ check_mini_fo_file(file); -+ -+ if((hidden_file = ftohf(file)) != NULL) { -+ err1 = hidden_file->f_op->fasync(fd, hidden_file, flag); -+ } -+ if((hidden_file = ftohf2(file)) != NULL) { -+ err2 = hidden_file->f_op->fasync(fd, hidden_file, flag); -+ } -+ -+ return (err1 || err2); -+} -+ -+ -+ -+struct file_operations mini_fo_dir_fops = -+ { -+ read: generic_read_dir, -+ write: mini_fo_write, -+ readdir: mini_fo_readdir, -+ poll: mini_fo_poll, -+ /* ioctl: mini_fo_ioctl, */ -+ mmap: mini_fo_mmap, -+ open: mini_fo_open, -+ flush: mini_fo_flush, -+ release: mini_fo_release, -+ fsync: mini_fo_fsync, -+ fasync: mini_fo_fasync, -+ /* not needed lock: mini_fo_lock, */ -+ /* not needed: readv */ -+ /* not needed: writev */ -+ /* not implemented: sendpage */ -+ /* not implemented: get_unmapped_area */ -+ }; -+ -+struct file_operations mini_fo_main_fops = -+ { -+ llseek: mini_fo_llseek, -+ read: mini_fo_read, -+ write: mini_fo_write, -+ readdir: mini_fo_readdir, -+ poll: mini_fo_poll, -+ /* ioctl: mini_fo_ioctl, */ -+ mmap: mini_fo_mmap, -+ open: mini_fo_open, -+ flush: mini_fo_flush, -+ release: mini_fo_release, -+ fsync: mini_fo_fsync, -+ fasync: mini_fo_fasync, -+ /* not needed: lock: mini_fo_lock, */ -+ /* not needed: readv */ -+ /* not needed: writev */ -+ /* not implemented: sendpage */ -+ /* not implemented: get_unmapped_area */ -+ }; ---- /dev/null -+++ b/fs/mini_fo/fist.h -@@ -0,0 +1,252 @@ -+/* -+ * Copyright (c) 1997-2003 Erez Zadok -+ * Copyright (c) 2001-2003 Stony Brook University -+ * -+ * For specific licensing information, see the COPYING file distributed with -+ * this package, or get one from ftp://ftp.filesystems.org/pub/fist/COPYING. -+ * -+ * This Copyright notice must be kept intact and distributed with all -+ * fistgen sources INCLUDING sources generated by fistgen. -+ */ -+/* -+ * Copyright (C) 2004, 2005 Markus Klotzbuecher -+ * -+ * 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. -+ */ -+ -+ -+/* -+ * $Id$ -+ */ -+ -+#ifndef __FIST_H_ -+#define __FIST_H_ -+ -+/* -+ * KERNEL ONLY CODE: -+ */ -+#ifdef __KERNEL__ -+#include -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,19) -+#include -+#else -+#include -+#endif -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) -+#ifdef CONFIG_MODVERSIONS -+# define MODVERSIONS -+# include -+#endif /* CONFIG_MODVERSIONS */ -+#endif /* KERNEL_VERSION < 2.6.0 */ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) -+#include -+#else -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#endif -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,20) -+#include -+#endif -+ -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) -+#include -+#endif -+ -+#include -+ -+#include -+/* #include */ -+#include -+#include -+ -+/* -+ * MACROS: -+ */ -+ -+/* those mapped to ATTR_* were copied from linux/fs.h */ -+#define FA_MODE ATTR_MODE -+#define FA_UID ATTR_UID -+#define FA_GID ATTR_GID -+#define FA_SIZE ATTR_SIZE -+#define FA_ATIME ATTR_ATIME -+#define FA_MTIME ATTR_MTIME -+#define FA_CTIME ATTR_CTIME -+#define FA_ATIME_SET ATTR_ATIME_SET -+#define FA_MTIME_SET ATTR_MTIME_SET -+#define FA_FORCE ATTR_FORCE -+#define FA_ATTR_FLAGS ATTR_ATTR_FLAG -+ -+/* must be greater than all other ATTR_* flags! */ -+#define FA_NLINK 2048 -+#define FA_BLKSIZE 4096 -+#define FA_BLOCKS 8192 -+#define FA_TIMES (FA_ATIME|FA_MTIME|FA_CTIME) -+#define FA_ALL 0 -+ -+/* macros to manage changes between kernels */ -+#define INODE_DATA(i) (&(i)->i_data) -+ -+#define MIN(x,y) ((x < y) ? (x) : (y)) -+#define MAX(x,y) ((x > y) ? (x) : (y)) -+#define MAXPATHLEN PATH_MAX -+ -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,5) -+# define lookup_one_len(a,b,c) lookup_one(a,b) -+#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2,4,5) */ -+ -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,8) -+# define generic_file_llseek default_llseek -+#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2,4,8) */ -+ -+#ifndef SEEK_SET -+# define SEEK_SET 0 -+#endif /* not SEEK_SET */ -+ -+#ifndef SEEK_CUR -+# define SEEK_CUR 1 -+#endif /* not SEEK_CUR */ -+ -+#ifndef SEEK_END -+# define SEEK_END 2 -+#endif /* not SEEK_END */ -+ -+#ifndef DEFAULT_POLLMASK -+# define DEFAULT_POLLMASK (POLLIN | POLLOUT | POLLRDNORM | POLLWRNORM) -+#endif /* not DEFAULT_POLLMASK */ -+ -+/* XXX: fix this so fistgen generates kfree() code directly */ -+#define kfree_s(a,b) kfree(a) -+ -+/* -+ * TYPEDEFS: -+ */ -+typedef struct dentry dentry_t; -+typedef struct file file_t; -+typedef struct inode inode_t; -+typedef inode_t vnode_t; -+typedef struct page page_t; -+typedef struct qstr qstr_t; -+typedef struct super_block super_block_t; -+typedef super_block_t vfs_t; -+typedef struct vm_area_struct vm_area_t; -+ -+ -+/* -+ * EXTERNALS: -+ */ -+ -+#define FPPF(str,page) printk("PPF %s 0x%x/%d: Lck:%d Err:%d Ref:%d Upd:%d Other::%d:%d:%d:%d:\n", \ -+ str, \ -+ (int) page, \ -+ (int) page->index, \ -+ (PageLocked(page) ? 1 : 0), \ -+ (PageError(page) ? 1 : 0), \ -+ (PageReferenced(page) ? 1 : 0), \ -+ (Page_Uptodate(page) ? 1 : 0), \ -+ (PageDecrAfter(page) ? 1 : 0), \ -+ (PageSlab(page) ? 1 : 0), \ -+ (PageSwapCache(page) ? 1 : 0), \ -+ (PageReserved(page) ? 1 : 0) \ -+ ) -+#define EZKDBG printk("EZK %s:%d:%s\n",__FILE__,__LINE__,__FUNCTION__) -+#if 0 -+# define EZKDBG1 printk("EZK %s:%d\n",__FILE__,__LINE__) -+#else -+# define EZKDBG1 -+#endif -+ -+extern int fist_get_debug_value(void); -+extern int fist_set_debug_value(int val); -+#if 0 /* mini_fo doesn't need these */ -+extern void fist_dprint_internal(int level, char *str,...); -+extern void fist_print_dentry(char *str, const dentry_t *dentry); -+extern void fist_print_inode(char *str, const inode_t *inode); -+extern void fist_print_file(char *str, const file_t *file); -+extern void fist_print_buffer_flags(char *str, struct buffer_head *buffer); -+extern void fist_print_page_flags(char *str, page_t *page); -+extern void fist_print_page_bytes(char *str, page_t *page); -+extern void fist_print_pte_flags(char *str, const page_t *page); -+extern void fist_checkinode(inode_t *inode, char *msg); -+extern void fist_print_sb(char *str, const super_block_t *sb); -+ -+/* §$% by mk: special debug functions */ -+extern void fist_mk_print_dentry(char *str, const dentry_t *dentry); -+extern void fist_mk_print_inode(char *str, const inode_t *inode); -+ -+extern char *add_indent(void); -+extern char *del_indent(void); -+#endif/* mini_fo doesn't need these */ -+ -+ -+#define STATIC -+#define ASSERT(EX) \ -+do { \ -+ if (!(EX)) { \ -+ printk(KERN_CRIT "ASSERTION FAILED: %s at %s:%d (%s)\n", #EX, \ -+ __FILE__, __LINE__, __FUNCTION__); \ -+ (*((char *)0))=0; \ -+ } \ -+} while (0) -+/* same ASSERT, but tell me who was the caller of the function */ -+#define ASSERT2(EX) \ -+do { \ -+ if (!(EX)) { \ -+ printk(KERN_CRIT "ASSERTION FAILED (caller): %s at %s:%d (%s)\n", #EX, \ -+ file, line, func); \ -+ (*((char *)0))=0; \ -+ } \ -+} while (0) -+ -+#if 0 /* mini_fo doesn't need these */ -+#define dprintk(format, args...) printk(KERN_DEBUG format, ##args) -+#define fist_dprint(level, str, args...) fist_dprint_internal(level, KERN_DEBUG str, ## args) -+#define print_entry_location() fist_dprint(4, "%sIN: %s %s:%d\n", add_indent(), __FUNCTION__, __FILE__, __LINE__) -+#define print_exit_location() fist_dprint(4, "%s OUT: %s %s:%d\n", del_indent(), __FUNCTION__, __FILE__, __LINE__) -+#define print_exit_status(status) fist_dprint(4, "%s OUT: %s %s:%d, STATUS: %d\n", del_indent(), __FUNCTION__, __FILE__, __LINE__, status) -+#define print_exit_pointer(status) \ -+do { \ -+ if (IS_ERR(status)) \ -+ fist_dprint(4, "%s OUT: %s %s:%d, RESULT: %ld\n", del_indent(), __FUNCTION__, __FILE__, __LINE__, PTR_ERR(status)); \ -+ else \ -+ fist_dprint(4, "%s OUT: %s %s:%d, RESULT: 0x%x\n", del_indent(), __FUNCTION__, __FILE__, __LINE__, PTR_ERR(status)); \ -+} while (0) -+#endif/* mini_fo doesn't need these */ -+ -+#endif /* __KERNEL__ */ -+ -+ -+/* -+ * DEFINITIONS FOR USER AND KERNEL CODE: -+ * (Note: ioctl numbers 1--9 are reserved for fistgen, the rest -+ * are auto-generated automatically based on the user's .fist file.) -+ */ -+# define FIST_IOCTL_GET_DEBUG_VALUE _IOR(0x15, 1, int) -+# define FIST_IOCTL_SET_DEBUG_VALUE _IOW(0x15, 2, int) -+ -+#endif /* not __FIST_H_ */ ---- /dev/null -+++ b/fs/mini_fo/inode.c -@@ -0,0 +1,1564 @@ -+/* -+ * Copyright (c) 1997-2003 Erez Zadok -+ * Copyright (c) 2001-2003 Stony Brook University -+ * -+ * For specific licensing information, see the COPYING file distributed with -+ * this package, or get one from ftp://ftp.filesystems.org/pub/fist/COPYING. -+ * -+ * This Copyright notice must be kept intact and distributed with all -+ * fistgen sources INCLUDING sources generated by fistgen. -+ */ -+/* -+ * Copyright (C) 2004, 2005 Markus Klotzbuecher -+ * -+ * 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. -+ */ -+ -+/* -+ * $Id$ -+ */ -+ -+#ifdef HAVE_CONFIG_H -+# include -+#endif -+ -+#include "fist.h" -+#include "mini_fo.h" -+ -+STATIC int -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) -+mini_fo_create(inode_t *dir, dentry_t *dentry, int mode, struct nameidata *nd) -+#else -+mini_fo_create(inode_t *dir, dentry_t *dentry, int mode) -+#endif -+{ -+ int err = 0; -+ -+ check_mini_fo_dentry(dentry); -+ -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) -+ err = create_sto_reg_file(dentry, mode, nd); -+#else -+ err = create_sto_reg_file(dentry, mode); -+#endif -+ check_mini_fo_dentry(dentry); -+ return err; -+} -+ -+ -+STATIC dentry_t * -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) -+mini_fo_lookup(inode_t *dir, dentry_t *dentry, struct nameidata* nd) -+#else -+mini_fo_lookup(inode_t *dir, dentry_t *dentry) -+#endif -+{ -+ int err = 0; -+ dentry_t *hidden_dir_dentry; -+ dentry_t *hidden_dentry = NULL; -+ -+ dentry_t *hidden_sto_dir_dentry; -+ dentry_t *hidden_sto_dentry = NULL; -+ -+ /* whiteout flag */ -+ int del_flag = 0; -+ char *bpath = NULL; -+ -+ const char *name; -+ unsigned int namelen; -+ -+ /* Don't allow lookups of META-files */ -+ namelen = strlen(META_FILENAME); -+ if(namelen == dentry->d_name.len) { -+ if(!strncmp(dentry->d_name.name, META_FILENAME, namelen)) { -+ err = -ENOENT; -+ goto out; -+ } -+ } -+ -+ hidden_dir_dentry = dtohd(dentry->d_parent); -+ hidden_sto_dir_dentry = dtohd2(dentry->d_parent); -+ -+ name = dentry->d_name.name; -+ namelen = dentry->d_name.len; -+ -+ /* must initialize dentry operations */ -+ dentry->d_op = &mini_fo_dops; -+ -+ /* setup the del_flag */ -+ del_flag = __meta_check_d_entry(dir, name, namelen); -+ bpath = __meta_check_r_entry(dir, name, namelen); -+ -+ /* perform the lookups of base and storage files: -+ * -+ * This caused some serious trouble, as a lookup_one_len passing -+ * a negative dentry oopses. Solution is to only do the lookup -+ * if the dentry is positive, else we set it to NULL -+ * More trouble, who said a *_dir_dentry can't be NULL? -+ */ -+ if(bpath) { -+ /* Cross-Interposing (C), yeah! */ -+ hidden_dentry = bpath_walk(dir->i_sb, bpath); -+ if(!hidden_dentry || !hidden_dentry->d_inode) { -+ printk(KERN_CRIT "mini_fo_lookup: bpath_walk failed.\n"); -+ err= -EINVAL; -+ goto out; -+ } -+ -+ /* this can be set up safely without fear of spaghetti -+ * interposing as it is only used for copying times */ -+ hidden_dir_dentry = hidden_dentry->d_parent; -+ kfree(bpath); -+ } -+ else if(hidden_dir_dentry && hidden_dir_dentry->d_inode) -+ hidden_dentry = -+ lookup_one_len(name, hidden_dir_dentry, namelen); -+ else -+ hidden_dentry = NULL; -+ -+ if(hidden_sto_dir_dentry && hidden_sto_dir_dentry->d_inode) -+ hidden_sto_dentry = -+ lookup_one_len(name, hidden_sto_dir_dentry, namelen); -+ else -+ hidden_sto_dentry = NULL; -+ -+ /* catch error in lookup */ -+ if (IS_ERR(hidden_dentry) || IS_ERR(hidden_sto_dentry)) { -+ /* mk: we need to call dput on the dentry, whose -+ * lookup_one_len operation failed, in order to avoid -+ * unmount trouble. -+ */ -+ if(IS_ERR(hidden_dentry)) { -+ printk(KERN_CRIT "mini_fo_lookup: ERR from base dentry, lookup failed.\n"); -+ err = PTR_ERR(hidden_dentry); -+ } else { -+ dput(hidden_dentry); -+ } -+ if(IS_ERR(hidden_sto_dentry)) { -+ printk(KERN_CRIT "mini_fo_lookup: ERR from storage dentry, lookup failed.\n"); -+ err = PTR_ERR(hidden_sto_dentry); -+ } else { -+ dput(hidden_sto_dentry); -+ } -+ goto out; -+ } -+ -+ /* allocate dentry private data */ -+ __dtopd(dentry) = (struct mini_fo_dentry_info *) -+ kmalloc(sizeof(struct mini_fo_dentry_info), GFP_KERNEL); -+ -+ if (!dtopd(dentry)) { -+ err = -ENOMEM; -+ goto out_dput; -+ } -+ -+ /* check for different states of the mini_fo file to be looked up. */ -+ -+ /* state 1, file has been modified */ -+ if(hidden_dentry && hidden_sto_dentry && -+ hidden_dentry->d_inode && hidden_sto_dentry->d_inode && !del_flag) { -+ -+ /* update parent directory's atime */ -+ fist_copy_attr_atime(dir, hidden_sto_dir_dentry->d_inode); -+ -+ dtopd(dentry)->state = MODIFIED; -+ dtohd(dentry) = hidden_dentry; -+ dtohd2(dentry) = hidden_sto_dentry; -+ -+ err = mini_fo_tri_interpose(hidden_dentry, -+ hidden_sto_dentry, -+ dentry, dir->i_sb, 1); -+ if (err) { -+ printk(KERN_CRIT "mini_fo_lookup: error interposing (state1).\n"); -+ goto out_free; -+ } -+ goto out; -+ } -+ /* state 2, file is unmodified */ -+ if(hidden_dentry && hidden_dentry->d_inode && !del_flag) { -+ -+ fist_copy_attr_atime(dir, hidden_dir_dentry->d_inode); -+ -+ dtopd(dentry)->state = UNMODIFIED; -+ dtohd(dentry) = hidden_dentry; -+ dtohd2(dentry) = hidden_sto_dentry; /* could be negative */ -+ -+ err = mini_fo_tri_interpose(hidden_dentry, -+ hidden_sto_dentry, -+ dentry, dir->i_sb, 1); -+ if (err) { -+ printk(KERN_CRIT "mini_fo_lookup: error interposing (state2).\n"); -+ goto out_free; -+ } -+ goto out; -+ } -+ /* state 3, file has been newly created */ -+ if(hidden_sto_dentry && hidden_sto_dentry->d_inode && !del_flag) { -+ -+ fist_copy_attr_atime(dir, hidden_sto_dir_dentry->d_inode); -+ dtopd(dentry)->state = CREATED; -+ dtohd(dentry) = hidden_dentry; /* could be negative */ -+ dtohd2(dentry) = hidden_sto_dentry; -+ -+ err = mini_fo_tri_interpose(hidden_dentry, -+ hidden_sto_dentry, -+ dentry, dir->i_sb, 1); -+ if (err) { -+ printk(KERN_CRIT "mini_fo_lookup: error interposing (state3).\n"); -+ goto out_free; -+ } -+ goto out; -+ } -+ -+ /* state 4, file has deleted and created again. */ -+ if(hidden_dentry && hidden_sto_dentry && -+ hidden_dentry->d_inode && -+ hidden_sto_dentry->d_inode && del_flag) { -+ -+ fist_copy_attr_atime(dir, hidden_sto_dir_dentry->d_inode); -+ dtopd(dentry)->state = DEL_REWRITTEN; -+ dtohd(dentry) = NULL; -+ dtohd2(dentry) = hidden_sto_dentry; -+ -+ err = mini_fo_tri_interpose(NULL, -+ hidden_sto_dentry, -+ dentry, dir->i_sb, 1); -+ if (err) { -+ printk(KERN_CRIT "mini_fo_lookup: error interposing (state4).\n"); -+ goto out_free; -+ } -+ /* We will never need this dentry again, as the file has been -+ * deleted from base */ -+ dput(hidden_dentry); -+ goto out; -+ } -+ /* state 5, file has been deleted in base */ -+ if(hidden_dentry && hidden_sto_dentry && -+ hidden_dentry->d_inode && -+ !hidden_sto_dentry->d_inode && del_flag) { -+ -+ /* check which parents atime we need for updating */ -+ if(hidden_sto_dir_dentry->d_inode) -+ fist_copy_attr_atime(dir, -+ hidden_sto_dir_dentry->d_inode); -+ else -+ fist_copy_attr_atime(dir, -+ hidden_dir_dentry->d_inode); -+ -+ dtopd(dentry)->state = DELETED; -+ dtohd(dentry) = NULL; -+ dtohd2(dentry) = hidden_sto_dentry; -+ -+ /* add negative dentry to dcache to speed up lookups */ -+ d_add(dentry, NULL); -+ dput(hidden_dentry); -+ goto out; -+ } -+ /* state 6, file does not exist */ -+ if(((hidden_dentry && !hidden_dentry->d_inode) || -+ (hidden_sto_dentry && !hidden_sto_dentry->d_inode)) && !del_flag) -+ { -+ /* check which parents atime we need for updating */ -+ if(hidden_sto_dir_dentry && hidden_sto_dir_dentry->d_inode) -+ fist_copy_attr_atime(dir, hidden_sto_dir_dentry->d_inode); -+ else -+ fist_copy_attr_atime(dir, hidden_dir_dentry->d_inode); -+ -+ dtopd(dentry)->state = NON_EXISTANT; -+ dtohd(dentry) = hidden_dentry; -+ dtohd2(dentry) = hidden_sto_dentry; -+ d_add(dentry, NULL); -+ goto out; -+ } -+ -+ /* if we get to here, were in an invalid state. bad. */ -+ printk(KERN_CRIT "mini_fo_lookup: ERROR, meta data corruption detected.\n"); -+ -+ /* end state checking */ -+ out_free: -+ d_drop(dentry); /* so that our bad dentry will get destroyed */ -+ kfree(dtopd(dentry)); -+ __dtopd(dentry) = NULL; /* be safe */ -+ -+ out_dput: -+ if(hidden_dentry) -+ dput(hidden_dentry); -+ if(hidden_sto_dentry) -+ dput(hidden_sto_dentry); /* drops usage count and marks for release */ -+ -+ out: -+ /* initalize wol if file exists and is directory */ -+ if(dentry->d_inode) { -+ if(S_ISDIR(dentry->d_inode->i_mode)) { -+ itopd(dentry->d_inode)->deleted_list_size = -1; -+ itopd(dentry->d_inode)->renamed_list_size = -1; -+ meta_build_lists(dentry); -+ } -+ } -+ return ERR_PTR(err); -+} -+ -+ -+STATIC int -+mini_fo_link(dentry_t *old_dentry, inode_t *dir, dentry_t *new_dentry) -+{ -+ int err; -+ dentry_t *hidden_old_dentry; -+ dentry_t *hidden_new_dentry; -+ dentry_t *hidden_dir_dentry; -+ -+ -+ check_mini_fo_dentry(old_dentry); -+ check_mini_fo_dentry(new_dentry); -+ check_mini_fo_inode(dir); -+ -+ /* no links to directorys and existing targets target allowed */ -+ if(S_ISDIR(old_dentry->d_inode->i_mode) || -+ is_mini_fo_existant(new_dentry)) { -+ err = -EPERM; -+ goto out; -+ } -+ -+ /* bring it directly from unmod to del_rew */ -+ if(dtost(old_dentry) == UNMODIFIED) { -+ err = nondir_unmod_to_mod(old_dentry, 1); -+ if(err) { -+ err = -EINVAL; -+ goto out; -+ } -+ err = meta_add_d_entry(old_dentry->d_parent, -+ old_dentry->d_name.name, -+ old_dentry->d_name.len); -+ if(err) { -+ err = -EINVAL; -+ goto out; -+ } -+ dput(dtohd(old_dentry)); -+ dtohd(old_dentry) = NULL; -+ dtost(old_dentry) = DEL_REWRITTEN; -+ } -+ -+ err = get_neg_sto_dentry(new_dentry); -+ if(err) { -+ err = -EINVAL; -+ goto out; -+ } -+ -+ hidden_old_dentry = dtohd2(old_dentry); -+ hidden_new_dentry = dtohd2(new_dentry); -+ -+ dget(hidden_old_dentry); -+ dget(hidden_new_dentry); -+ -+ /* was: hidden_dir_dentry = lock_parent(hidden_new_dentry); */ -+ hidden_dir_dentry = dget(hidden_new_dentry->d_parent); -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16) -+ mutex_lock(&hidden_dir_dentry->d_inode->i_mutex); -+#else -+ down(&hidden_dir_dentry->d_inode->i_sem); -+#endif -+ -+ err = vfs_link(hidden_old_dentry, -+ hidden_dir_dentry->d_inode, -+ hidden_new_dentry); -+ if (err || !hidden_new_dentry->d_inode) -+ goto out_lock; -+ -+ dtost(new_dentry) = CREATED; -+ err = mini_fo_tri_interpose(NULL, hidden_new_dentry, new_dentry, dir->i_sb, 0); -+ if (err) -+ goto out_lock; -+ -+ fist_copy_attr_timesizes(dir, hidden_new_dentry->d_inode); -+ /* propagate number of hard-links */ -+ old_dentry->d_inode->i_nlink = itohi2(old_dentry->d_inode)->i_nlink; -+ -+ out_lock: -+ /* was: unlock_dir(hidden_dir_dentry); */ -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16) -+ mutex_unlock(&hidden_dir_dentry->d_inode->i_mutex); -+#else -+ up(&hidden_dir_dentry->d_inode->i_sem); -+#endif -+ dput(hidden_dir_dentry); -+ -+ dput(hidden_new_dentry); -+ dput(hidden_old_dentry); -+ if (!new_dentry->d_inode) -+ d_drop(new_dentry); -+ -+ out: -+ return err; -+} -+ -+ -+STATIC int -+mini_fo_unlink(inode_t *dir, dentry_t *dentry) -+{ -+ int err = 0; -+ -+ dget(dentry); -+ if(dtopd(dentry)->state == MODIFIED) { -+ err = nondir_mod_to_del(dentry); -+ goto out; -+ } -+ else if(dtopd(dentry)->state == UNMODIFIED) { -+ err = nondir_unmod_to_del(dentry); -+ goto out; -+ } -+ else if(dtopd(dentry)->state == CREATED) { -+ err = nondir_creat_to_del(dentry); -+ goto out; -+ } -+ else if(dtopd(dentry)->state == DEL_REWRITTEN) { -+ err = nondir_del_rew_to_del(dentry); -+ goto out; -+ } -+ -+ printk(KERN_CRIT "mini_fo_unlink: ERROR, invalid state detected.\n"); -+ -+ out: -+ fist_copy_attr_times(dir, itohi2(dentry->d_parent->d_inode)); -+ -+ if(!err) { -+ /* is this causing my pain? d_delete(dentry); */ -+ d_drop(dentry); -+ } -+ -+ dput(dentry); -+ return err; -+} -+ -+ -+STATIC int -+mini_fo_symlink(inode_t *dir, dentry_t *dentry, const char *symname) -+{ -+ int err=0; -+ dentry_t *hidden_sto_dentry; -+ dentry_t *hidden_sto_dir_dentry; -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) -+ umode_t mode; -+#endif -+ -+ /* Fail if the symlink file exists */ -+ if(!(dtost(dentry) == DELETED || -+ dtost(dentry) == NON_EXISTANT)) { -+ err = -EEXIST; -+ goto out; -+ } -+ -+ err = get_neg_sto_dentry(dentry); -+ if(err) { -+ err = -EINVAL; -+ goto out; -+ } -+ hidden_sto_dentry = dtohd2(dentry); -+ -+ dget(hidden_sto_dentry); -+ /* was: hidden_sto_dir_dentry = lock_parent(hidden_sto_dentry); */ -+ hidden_sto_dir_dentry = dget(hidden_sto_dentry->d_parent); -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16) -+ mutex_lock(&hidden_sto_dir_dentry->d_inode->i_mutex); -+#else -+ down(&hidden_sto_dir_dentry->d_inode->i_sem); -+#endif -+ -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) -+ mode = S_IALLUGO; -+ err = vfs_symlink(hidden_sto_dir_dentry->d_inode, -+ hidden_sto_dentry, symname, mode); -+#else -+ err = vfs_symlink(hidden_sto_dir_dentry->d_inode, -+ hidden_sto_dentry, -+ symname); -+#endif -+ if (err || !hidden_sto_dentry->d_inode) -+ goto out_lock; -+ -+ if(dtost(dentry) == DELETED) { -+ dtost(dentry) = DEL_REWRITTEN; -+ err = mini_fo_tri_interpose(NULL, hidden_sto_dentry, dentry, dir->i_sb, 0); -+ if(err) -+ goto out_lock; -+ } else if(dtost(dentry) == NON_EXISTANT) { -+ dtost(dentry) = CREATED; -+ err = mini_fo_tri_interpose(dtohd(dentry), hidden_sto_dentry, dentry, dir->i_sb, 0); -+ if(err) -+ goto out_lock; -+ } -+ fist_copy_attr_timesizes(dir, hidden_sto_dir_dentry->d_inode); -+ -+ out_lock: -+ /* was: unlock_dir(hidden_sto_dir_dentry); */ -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16) -+ mutex_unlock(&hidden_sto_dir_dentry->d_inode->i_mutex); -+#else -+ up(&hidden_sto_dir_dentry->d_inode->i_sem); -+#endif -+ dput(hidden_sto_dir_dentry); -+ -+ dput(hidden_sto_dentry); -+ if (!dentry->d_inode) -+ d_drop(dentry); -+ out: -+ return err; -+} -+ -+STATIC int -+mini_fo_mkdir(inode_t *dir, dentry_t *dentry, int mode) -+{ -+ int err; -+ -+ err = create_sto_dir(dentry, mode); -+ -+ check_mini_fo_dentry(dentry); -+ -+ return err; -+} -+ -+ -+STATIC int -+mini_fo_rmdir(inode_t *dir, dentry_t *dentry) -+{ -+ int err = 0; -+ -+ dentry_t *hidden_sto_dentry; -+ dentry_t *hidden_sto_dir_dentry; -+ dentry_t *meta_dentry; -+ inode_t *hidden_sto_dir = NULL; -+ -+ check_mini_fo_dentry(dentry); -+ check_mini_fo_inode(dir); -+ -+ dget(dentry); -+ if(dtopd(dentry)->state == MODIFIED) { -+ /* XXX: disabled, because it does not bother to check files on -+ * the original filesystem - just a hack, but better than simply -+ * removing it without testing */ -+ err = -EINVAL; -+ goto out; -+ -+ hidden_sto_dir = itohi2(dir); -+ hidden_sto_dentry = dtohd2(dentry); -+ -+ /* was:hidden_sto_dir_dentry = lock_parent(hidden_sto_dentry); */ -+ hidden_sto_dir_dentry = dget(hidden_sto_dentry->d_parent); -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16) -+ mutex_lock(&hidden_sto_dir_dentry->d_inode->i_mutex); -+#else -+ down(&hidden_sto_dir_dentry->d_inode->i_sem); -+#endif -+ -+ /* Delete an old WOL file contained in the storage dir */ -+ meta_dentry = lookup_one_len(META_FILENAME, -+ hidden_sto_dentry, -+ strlen(META_FILENAME)); -+ if(meta_dentry->d_inode) { -+ err = vfs_unlink(hidden_sto_dentry->d_inode, meta_dentry); -+ dput(meta_dentry); -+ if(!err) -+ d_delete(meta_dentry); -+ } -+ -+ err = vfs_rmdir(hidden_sto_dir, hidden_sto_dentry); -+ dput(hidden_sto_dentry); -+ if(!err) -+ d_delete(hidden_sto_dentry); -+ -+ /* propagate number of hard-links */ -+ dentry->d_inode->i_nlink = itohi2(dentry->d_inode)->i_nlink; -+ -+ dput(dtohd(dentry)); -+ -+ dtohd(dentry) = NULL; -+ dtopd(dentry)->state = DELETED; -+ -+ /* carefull with R files */ -+ if( __meta_is_r_entry(dir, -+ dentry->d_name.name, -+ dentry->d_name.len) == 1) { -+ err = meta_remove_r_entry(dentry->d_parent, -+ dentry->d_name.name, -+ dentry->d_name.len); -+ if(err) { -+ printk(KERN_CRIT "mini_fo: rmdir: meta_remove_r_entry failed.\n"); -+ goto out; -+ } -+ } -+ else { -+ /* ok, add deleted file to META */ -+ meta_add_d_entry(dentry->d_parent, -+ dentry->d_name.name, -+ dentry->d_name.len); -+ } -+ /* was: unlock_dir(hidden_sto_dir_dentry); */ -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16) -+ mutex_unlock(&hidden_sto_dir_dentry->d_inode->i_mutex); -+#else -+ up(&hidden_sto_dir_dentry->d_inode->i_sem); -+#endif -+ dput(hidden_sto_dir_dentry); -+ goto out; -+ } -+ else if(dtopd(dentry)->state == UNMODIFIED) { -+ /* XXX: simply adding it to the delete list here is fscking dangerous! -+ * as a temporary hack, i will disable rmdir on unmodified directories -+ * for now. -+ */ -+ err = -EINVAL; -+ goto out; -+ -+ err = get_neg_sto_dentry(dentry); -+ if(err) { -+ err = -EINVAL; -+ goto out; -+ } -+ -+ /* dput base dentry, this will relase the inode and free the -+ * dentry, as we will never need it again. */ -+ dput(dtohd(dentry)); -+ dtohd(dentry) = NULL; -+ dtopd(dentry)->state = DELETED; -+ -+ /* add deleted file to META-file */ -+ meta_add_d_entry(dentry->d_parent, -+ dentry->d_name.name, -+ dentry->d_name.len); -+ goto out; -+ } -+ else if(dtopd(dentry)->state == CREATED) { -+ hidden_sto_dir = itohi2(dir); -+ hidden_sto_dentry = dtohd2(dentry); -+ -+ /* was: hidden_sto_dir_dentry = lock_parent(hidden_sto_dentry);*/ -+ hidden_sto_dir_dentry = dget(hidden_sto_dentry->d_parent); -+ -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16) -+ mutex_lock(&hidden_sto_dir_dentry->d_inode->i_mutex); -+#else -+ down(&hidden_sto_dir_dentry->d_inode->i_sem); -+#endif -+ -+ /* Delete an old WOL file contained in the storage dir */ -+ meta_dentry = lookup_one_len(META_FILENAME, -+ hidden_sto_dentry, -+ strlen(META_FILENAME)); -+ if(meta_dentry->d_inode) { -+ /* is this necessary? dget(meta_dentry); */ -+ err = vfs_unlink(hidden_sto_dentry->d_inode, -+ meta_dentry); -+ dput(meta_dentry); -+ if(!err) -+ d_delete(meta_dentry); -+ } -+ -+ err = vfs_rmdir(hidden_sto_dir, hidden_sto_dentry); -+ dput(hidden_sto_dentry); -+ if(!err) -+ d_delete(hidden_sto_dentry); -+ -+ /* propagate number of hard-links */ -+ dentry->d_inode->i_nlink = itohi2(dentry->d_inode)->i_nlink; -+ dtopd(dentry)->state = NON_EXISTANT; -+ -+ /* was: unlock_dir(hidden_sto_dir_dentry); */ -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16) -+ mutex_unlock(&hidden_sto_dir_dentry->d_inode->i_mutex); -+#else -+ up(&hidden_sto_dir_dentry->d_inode->i_sem); -+#endif -+ dput(hidden_sto_dir_dentry); -+ -+ goto out; -+ } -+ else if(dtopd(dentry)->state == DEL_REWRITTEN) { -+ hidden_sto_dir = itohi2(dir); -+ hidden_sto_dentry = dtohd2(dentry); -+ -+ /* was: hidden_sto_dir_dentry = lock_parent(hidden_sto_dentry);*/ -+ hidden_sto_dir_dentry = dget(hidden_sto_dentry->d_parent); -+ -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16) -+ mutex_lock(&hidden_sto_dir_dentry->d_inode->i_mutex); -+#else -+ down(&hidden_sto_dir_dentry->d_inode->i_sem); -+#endif -+ -+ /* Delete an old WOL file contained in the storage dir */ -+ meta_dentry = lookup_one_len(META_FILENAME, -+ hidden_sto_dentry, -+ strlen(META_FILENAME)); -+ if(meta_dentry->d_inode) { -+ /* is this necessary? dget(meta_dentry); */ -+ err = vfs_unlink(hidden_sto_dentry->d_inode, -+ meta_dentry); -+ dput(meta_dentry); -+ if(!err) -+ d_delete(meta_dentry); -+ } -+ -+ err = vfs_rmdir(hidden_sto_dir, hidden_sto_dentry); -+ dput(hidden_sto_dentry); -+ if(!err) -+ d_delete(hidden_sto_dentry); -+ -+ /* propagate number of hard-links */ -+ dentry->d_inode->i_nlink = itohi2(dentry->d_inode)->i_nlink; -+ dtopd(dentry)->state = DELETED; -+ /* was: unlock_dir(hidden_sto_dir_dentry); */ -+ -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16) -+ mutex_unlock(&hidden_sto_dir_dentry->d_inode->i_mutex); -+#else -+ up(&hidden_sto_dir_dentry->d_inode->i_sem); -+#endif -+ dput(hidden_sto_dir_dentry); -+ goto out; -+ } -+ -+ printk(KERN_CRIT "mini_fo_rmdir: ERROR, invalid state detected.\n"); -+ -+ out: -+ if(!err) { -+ d_drop(dentry); -+ } -+ -+ fist_copy_attr_times(dir, itohi2(dentry->d_parent->d_inode)); -+ dput(dentry); -+ -+ return err; -+} -+ -+ -+STATIC int -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) -+mini_fo_mknod(inode_t *dir, dentry_t *dentry, int mode, dev_t dev) -+#else -+mini_fo_mknod(inode_t *dir, dentry_t *dentry, int mode, int dev) -+#endif -+{ -+ int err = 0; -+ -+ check_mini_fo_dentry(dentry); -+ -+ err = create_sto_nod(dentry, mode, dev); -+ if(err) { -+ printk(KERN_CRIT "mini_fo_mknod: creating sto nod failed.\n"); -+ err = -EINVAL; -+ } -+ -+ check_mini_fo_dentry(dentry); -+ return err; -+} -+ -+ -+STATIC int -+mini_fo_rename(inode_t *old_dir, dentry_t *old_dentry, -+ inode_t *new_dir, dentry_t *new_dentry) -+{ -+ /* dispatch */ -+ if(S_ISDIR(old_dentry->d_inode->i_mode)) -+ return rename_directory(old_dir, old_dentry, new_dir, new_dentry); -+ return rename_nondir(old_dir, old_dentry, new_dir, new_dentry); -+ -+} -+ -+int rename_directory(inode_t *old_dir, dentry_t *old_dentry, -+ inode_t *new_dir, dentry_t *new_dentry) -+{ -+ int err, bpath_len; -+ char *bpath; -+ -+ dentry_t *hidden_old_dentry; -+ dentry_t *hidden_new_dentry; -+ dentry_t *hidden_old_dir_dentry; -+ dentry_t *hidden_new_dir_dentry; -+ -+ err = 0; -+ bpath = NULL; -+ bpath_len = 0; -+ -+ /* this is a test, chuck out if it works */ -+ if(!(dtopd(new_dentry)->state == DELETED || -+ dtopd(new_dentry)->state == NON_EXISTANT)) { -+ printk(KERN_CRIT "mini_fo: rename_directory: \ -+ uh, ah, new_dentry not negative.\n"); -+ /* return -1; */ -+ } -+ -+ /* state = UNMODIFIED */ -+ if(dtopd(old_dentry)->state == UNMODIFIED) { -+ err = dir_unmod_to_mod(old_dentry); -+ if (err) -+ goto out; -+ } -+ -+ /* state = MODIFIED */ -+ if(dtopd(old_dentry)->state == MODIFIED) { -+ bpath = meta_check_r_entry(old_dentry->d_parent, -+ old_dentry->d_name.name, -+ old_dentry->d_name.len); -+ if(bpath) { -+ err = meta_remove_r_entry(old_dentry->d_parent, -+ old_dentry->d_name.name, -+ old_dentry->d_name.len); -+ if(err) { -+ printk(KERN_CRIT "mini_fo: rename_directory:\ -+ meta_remove_r_entry \ -+ failed.\n"); -+ goto out; -+ } -+ err = meta_add_r_entry(new_dentry->d_parent, -+ bpath, -+ strlen(bpath), -+ new_dentry->d_name.name, -+ new_dentry->d_name.len); -+ kfree(bpath); -+ } -+ else {/* wol it */ -+ err = meta_add_d_entry(old_dentry->d_parent, -+ old_dentry->d_name.name, -+ old_dentry->d_name.len); -+ if (err) -+ goto out; -+ /* put it on rename list */ -+ err = get_mini_fo_bpath(old_dentry, -+ &bpath, -+ &bpath_len); -+ if (err) -+ goto out; -+ err = meta_add_r_entry(new_dentry->d_parent, -+ bpath, bpath_len, -+ new_dentry->d_name.name, -+ new_dentry->d_name.len); -+ if (err) -+ goto out; -+ } -+ /* no state change, MODIFIED stays MODIFIED */ -+ } -+ /* state = CREATED */ -+ if(dtopd(old_dentry)->state == CREATED || -+ dtopd(old_dentry)->state == DEL_REWRITTEN) { -+ if(dtohd(old_dentry)) -+ dput(dtohd(old_dentry)); -+ -+ if(dtopd(new_dentry)->state == DELETED) { -+ dtopd(old_dentry)->state = DEL_REWRITTEN; -+ dtohd(old_dentry) = NULL; -+ } -+ else if(dtopd(new_dentry)->state == NON_EXISTANT) { -+ dtopd(old_dentry)->state = CREATED; -+ /* steal new dentry's neg. base dentry */ -+ dtohd(old_dentry) = dtohd(new_dentry); -+ dtohd(new_dentry) = NULL; -+ } -+ } -+ if(dtopd(new_dentry)->state == UNMODIFIED || -+ dtopd(new_dentry)->state == NON_EXISTANT) { -+ err = get_neg_sto_dentry(new_dentry); -+ if(err) -+ goto out; -+ } -+ -+ /* now move sto file */ -+ hidden_old_dentry = dtohd2(old_dentry); -+ hidden_new_dentry = dtohd2(new_dentry); -+ -+ dget(hidden_old_dentry); -+ dget(hidden_new_dentry); -+ -+ hidden_old_dir_dentry = dget(hidden_old_dentry->d_parent); -+ hidden_new_dir_dentry = dget(hidden_new_dentry->d_parent); -+ double_lock(hidden_old_dir_dentry, hidden_new_dir_dentry); -+ -+ err = vfs_rename(hidden_old_dir_dentry->d_inode, hidden_old_dentry, -+ hidden_new_dir_dentry->d_inode, hidden_new_dentry); -+ if(err) -+ goto out_lock; -+ -+ fist_copy_attr_all(new_dir, hidden_new_dir_dentry->d_inode); -+ if (new_dir != old_dir) -+ fist_copy_attr_all(old_dir, -+ hidden_old_dir_dentry->d_inode); -+ -+ out_lock: -+ /* double_unlock will dput the new/old parent dentries -+ * whose refcnts were incremented via get_parent above. */ -+ double_unlock(hidden_old_dir_dentry, hidden_new_dir_dentry); -+ dput(hidden_new_dentry); -+ dput(hidden_old_dentry); -+ -+ out: -+ return err; -+} -+ -+int rename_nondir(inode_t *old_dir, dentry_t *old_dentry, -+ inode_t *new_dir, dentry_t *new_dentry) -+{ -+ int err=0; -+ -+ check_mini_fo_dentry(old_dentry); -+ check_mini_fo_dentry(new_dentry); -+ check_mini_fo_inode(old_dir); -+ check_mini_fo_inode(new_dir); -+ -+ /* state: UNMODIFIED */ -+ if(dtost(old_dentry) == UNMODIFIED) { -+ err = nondir_unmod_to_mod(old_dentry, 1); -+ if(err) { -+ err = -EINVAL; -+ goto out; -+ } -+ } -+ -+ /* the easy states */ -+ if(exists_in_storage(old_dentry)) { -+ -+ dentry_t *hidden_old_dentry; -+ dentry_t *hidden_new_dentry; -+ dentry_t *hidden_old_dir_dentry; -+ dentry_t *hidden_new_dir_dentry; -+ -+ /* if old file is MODIFIED, add it to the deleted_list */ -+ if(dtopd(old_dentry)->state == MODIFIED) { -+ meta_add_d_entry(old_dentry->d_parent, -+ old_dentry->d_name.name, -+ old_dentry->d_name.len); -+ -+ dput(dtohd(old_dentry)); -+ } -+ /* if old file is CREATED, we only release the base dentry */ -+ if(dtopd(old_dentry)->state == CREATED) { -+ if(dtohd(old_dentry)) -+ dput(dtohd(old_dentry)); -+ } -+ -+ /* now setup the new states (depends on new_dentry state) */ -+ /* new dentry state = MODIFIED */ -+ if(dtopd(new_dentry)->state == MODIFIED) { -+ meta_add_d_entry(new_dentry->d_parent, -+ new_dentry->d_name.name, -+ new_dentry->d_name.len); -+ -+ /* new dentry will be d_put'ed later by the vfs -+ * so don't do it here -+ * dput(dtohd(new_dentry)); -+ */ -+ dtohd(old_dentry) = NULL; -+ dtopd(old_dentry)->state = DEL_REWRITTEN; -+ } -+ /* new dentry state = UNMODIFIED */ -+ else if(dtopd(new_dentry)->state == UNMODIFIED) { -+ if(get_neg_sto_dentry(new_dentry)) -+ return -EINVAL; -+ -+ meta_add_d_entry(new_dentry->d_parent, -+ new_dentry->d_name.name, -+ new_dentry->d_name.len); -+ -+ /* is this right??? */ -+ /*dput(dtohd(new_dentry));*/ -+ dtohd(old_dentry) = NULL; -+ dtopd(old_dentry)->state = DEL_REWRITTEN; -+ } -+ /* new dentry state = CREATED */ -+ else if(dtopd(new_dentry)->state == CREATED) { -+ /* we keep the neg. base dentry (if exists) */ -+ dtohd(old_dentry) = dtohd(new_dentry); -+ /* ...and set it to Null, or we'll get -+ * dcache.c:345 if it gets dput twice... */ -+ dtohd(new_dentry) = NULL; -+ dtopd(old_dentry)->state = CREATED; -+ } -+ /* new dentry state = NON_EXISTANT */ -+ else if(dtopd(new_dentry)->state == NON_EXISTANT) { -+ if(get_neg_sto_dentry(new_dentry)) -+ return -EINVAL; -+ -+ /* we keep the neg. base dentry (if exists) */ -+ dtohd(old_dentry) = dtohd(new_dentry); -+ /* ...and set it to Null, or we'll get -+ * Dr. dcache.c:345 if it gets dput twice... */ -+ dtohd(new_dentry) = NULL; -+ dtopd(old_dentry)->state = CREATED; -+ } -+ /* new dentry state = DEL_REWRITTEN or DELETED */ -+ else if(dtopd(new_dentry)->state == DEL_REWRITTEN || -+ dtopd(new_dentry)->state == DELETED) { -+ dtohd(old_dentry) = NULL; -+ dtopd(old_dentry)->state = DEL_REWRITTEN; -+ } -+ else { /* not possible, uhh, ahh */ -+ printk(KERN_CRIT -+ "mini_fo: rename_reg_file: invalid state detected [1].\n"); -+ return -1; -+ } -+ -+ /* now we definitely have a sto file */ -+ hidden_old_dentry = dtohd2(old_dentry); -+ hidden_new_dentry = dtohd2(new_dentry); -+ -+ dget(hidden_old_dentry); -+ dget(hidden_new_dentry); -+ -+ hidden_old_dir_dentry = dget(hidden_old_dentry->d_parent); -+ hidden_new_dir_dentry = dget(hidden_new_dentry->d_parent); -+ double_lock(hidden_old_dir_dentry, hidden_new_dir_dentry); -+ -+ err = vfs_rename(hidden_old_dir_dentry->d_inode, -+ hidden_old_dentry, -+ hidden_new_dir_dentry->d_inode, -+ hidden_new_dentry); -+ if(err) -+ goto out_lock; -+ -+ fist_copy_attr_all(new_dir, hidden_new_dir_dentry->d_inode); -+ if (new_dir != old_dir) -+ fist_copy_attr_all(old_dir, hidden_old_dir_dentry->d_inode); -+ -+ out_lock: -+ /* double_unlock will dput the new/old parent dentries -+ * whose refcnts were incremented via get_parent above. -+ */ -+ double_unlock(hidden_old_dir_dentry, hidden_new_dir_dentry); -+ dput(hidden_new_dentry); -+ dput(hidden_old_dentry); -+ out: -+ return err; -+ } -+ else { /* invalid state */ -+ printk(KERN_CRIT "mini_fo: rename_reg_file: ERROR: invalid state detected [2].\n"); -+ return -1; -+ } -+} -+ -+ -+STATIC int -+mini_fo_readlink(dentry_t *dentry, char *buf, int bufsiz) -+{ -+ int err=0; -+ dentry_t *hidden_dentry = NULL; -+ -+ if(dtohd2(dentry) && dtohd2(dentry)->d_inode) { -+ hidden_dentry = dtohd2(dentry); -+ } else if(dtohd(dentry) && dtohd(dentry)->d_inode) { -+ hidden_dentry = dtohd(dentry); -+ } else { -+ goto out; -+ } -+ -+ if (!hidden_dentry->d_inode->i_op || -+ !hidden_dentry->d_inode->i_op->readlink) { -+ err = -EINVAL; goto out; -+ } -+ -+ err = hidden_dentry->d_inode->i_op->readlink(hidden_dentry, -+ buf, -+ bufsiz); -+ if (err > 0) -+ fist_copy_attr_atime(dentry->d_inode, hidden_dentry->d_inode); -+ -+ out: -+ return err; -+} -+ -+ -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,13) -+static int mini_fo_follow_link(dentry_t *dentry, struct nameidata *nd) -+#else -+static void* mini_fo_follow_link(dentry_t *dentry, struct nameidata *nd) -+#endif -+{ -+ char *buf; -+ int len = PAGE_SIZE, err; -+ mm_segment_t old_fs; -+ -+ /* in 2.6 this is freed by mini_fo_put_link called by __do_follow_link */ -+ buf = kmalloc(len, GFP_KERNEL); -+ if (!buf) { -+ err = -ENOMEM; -+ goto out; -+ } -+ -+ /* read the symlink, and then we will follow it */ -+ old_fs = get_fs(); -+ set_fs(KERNEL_DS); -+ err = dentry->d_inode->i_op->readlink(dentry, buf, len); -+ set_fs(old_fs); -+ if (err < 0) { -+ kfree(buf); -+ buf = NULL; -+ goto out; -+ } -+ buf[err] = 0; -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) -+ nd_set_link(nd, buf); -+ err = 0; -+#else -+ err = vfs_follow_link(nd, buf); -+#endif -+ -+ out: -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) -+ kfree(buf); -+#endif -+ -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,13) -+ return err; -+#else -+ return ERR_PTR(err); -+#endif -+} -+ -+STATIC -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,13) -+void mini_fo_put_link(struct dentry *dentry, struct nameidata *nd) -+#else -+void mini_fo_put_link(struct dentry *dentry, struct nameidata *nd, void *cookie) -+#endif -+{ -+ char *link; -+ link = nd_get_link(nd); -+ kfree(link); -+} -+#endif -+ -+STATIC int -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) -+mini_fo_permission(inode_t *inode, int mask, struct nameidata *nd) -+#else -+mini_fo_permission(inode_t *inode, int mask) -+#endif -+{ -+ inode_t *hidden_inode; -+ int mode; -+ int err; -+ -+ if(itohi2(inode)) { -+ hidden_inode = itohi2(inode); -+ } else { -+ hidden_inode = itohi(inode); -+ } -+ mode = inode->i_mode; -+ -+ /* not really needed, as permission handles everything: -+ * err = vfs_permission(inode, mask); -+ * if (err) -+ * goto out; -+ */ -+ -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) -+ err = permission(hidden_inode, mask, nd); -+#else -+ err = permission(hidden_inode, mask); -+#endif -+ -+ /* out: */ -+ return err; -+} -+ -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) -+STATIC int -+mini_fo_inode_revalidate(dentry_t *dentry) -+{ -+ int err = 0; -+ dentry_t *hidden_dentry; -+ inode_t *hidden_inode; -+ -+ ASSERT(dentry->d_inode); -+ ASSERT(itopd(dentry->d_inode)); -+ -+ if(itohi2(dentry->d_inode)) { -+ hidden_dentry = dtohd2(dentry); -+ hidden_inode = hidden_dentry->d_inode; -+ } else if(itohi(dentry->d_inode)) { -+ hidden_dentry = dtohd(dentry); -+ hidden_inode = hidden_dentry->d_inode; -+ } else { -+ printk(KERN_CRIT "mini_fo_inode_revalidate: ERROR, invalid state detected.\n"); -+ err = -ENOENT; -+ goto out; -+ } -+ if (hidden_inode && hidden_inode->i_op && hidden_inode->i_op->revalidate){ -+ err = hidden_inode->i_op->revalidate(hidden_dentry); -+ if (err) -+ goto out; -+ } -+ fist_copy_attr_all(dentry->d_inode, hidden_inode); -+ out: -+ return err; -+} -+#endif -+ -+STATIC int -+mini_fo_setattr(dentry_t *dentry, struct iattr *ia) -+{ -+ int err = 0; -+ -+ check_mini_fo_dentry(dentry); -+ -+ if(!is_mini_fo_existant(dentry)) { -+ printk(KERN_CRIT "mini_fo_setattr: ERROR, invalid state detected [1].\n"); -+ goto out; -+ } -+ -+ if(dtost(dentry) == UNMODIFIED) { -+ if(!IS_COPY_FLAG(ia->ia_valid)) -+ goto out; /* we ignore these changes to base */ -+ -+ if(S_ISDIR(dentry->d_inode->i_mode)) { -+ err = dir_unmod_to_mod(dentry); -+ } else { -+ /* we copy contents if file is not beeing truncated */ -+ if(S_ISREG(dentry->d_inode->i_mode) && -+ !(ia->ia_size == 0 && (ia->ia_valid & ATTR_SIZE))) { -+ err = nondir_unmod_to_mod(dentry, 1); -+ } else -+ err = nondir_unmod_to_mod(dentry, 0); -+ } -+ if(err) { -+ err = -EINVAL; -+ printk(KERN_CRIT "mini_fo_setattr: ERROR changing states.\n"); -+ goto out; -+ } -+ } -+ if(!exists_in_storage(dentry)) { -+ printk(KERN_CRIT "mini_fo_setattr: ERROR, invalid state detected [2].\n"); -+ err = -EINVAL; -+ goto out; -+ } -+ ASSERT(dentry->d_inode); -+ ASSERT(dtohd2(dentry)); -+ ASSERT(itopd(dentry->d_inode)); -+ ASSERT(itohi2(dentry->d_inode)); -+ -+ err = notify_change(dtohd2(dentry), ia); -+ fist_copy_attr_all(dentry->d_inode, itohi2(dentry->d_inode)); -+ out: -+ return err; -+} -+ -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) -+STATIC int -+mini_fo_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat) -+{ -+ int err = 0; -+ dentry_t *hidden_dentry; -+ -+ ASSERT(dentry->d_inode); -+ ASSERT(itopd(dentry->d_inode)); -+ -+ if(itohi2(dentry->d_inode)) { -+ hidden_dentry = dtohd2(dentry); -+ } else if(itohi(dentry->d_inode)) { -+ hidden_dentry = dtohd(dentry); -+ } else { -+ printk(KERN_CRIT "mini_fo_getattr: ERROR, invalid state detected.\n"); -+ err = -ENOENT; -+ goto out; -+ } -+ fist_copy_attr_all(dentry->d_inode, hidden_dentry->d_inode); -+ -+ ASSERT(hidden_dentry); -+ ASSERT(hidden_dentry->d_inode); -+ ASSERT(hidden_dentry->d_inode->i_op); -+ -+ generic_fillattr(dentry->d_inode, stat); -+ if (!stat->blksize) { -+ struct super_block *s = hidden_dentry->d_inode->i_sb; -+ unsigned blocks; -+ blocks = (stat->size+s->s_blocksize-1) >> s->s_blocksize_bits; -+ stat->blocks = (s->s_blocksize / 512) * blocks; -+ stat->blksize = s->s_blocksize; -+ } -+ out: -+ return err; -+} -+#endif -+ -+#if defined(XATTR) && (LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,20)) -+#if 0 /* no xattr_alloc() and xattr_free() */ -+/* This is lifted from fs/xattr.c */ -+static void * -+xattr_alloc(size_t size, size_t limit) -+{ -+ void *ptr; -+ -+ if (size > limit) -+ return ERR_PTR(-E2BIG); -+ -+ if (!size) /* size request, no buffer is needed */ -+ return NULL; -+ else if (size <= PAGE_SIZE) -+ ptr = kmalloc((unsigned long) size, GFP_KERNEL); -+ else -+ ptr = vmalloc((unsigned long) size); -+ if (!ptr) -+ return ERR_PTR(-ENOMEM); -+ return ptr; -+} -+ -+static void -+xattr_free(void *ptr, size_t size) -+{ -+ if (!size) /* size request, no buffer was needed */ -+ return; -+ else if (size <= PAGE_SIZE) -+ kfree(ptr); -+ else -+ vfree(ptr); -+} -+#endif /* no xattr_alloc() and xattr_free() */ -+ -+/* BKL held by caller. -+ * dentry->d_inode->i_sem down -+ */ -+STATIC int -+mini_fo_getxattr(struct dentry *dentry, const char *name, void *value, size_t size) { -+ struct dentry *hidden_dentry = NULL; -+ int err = -EOPNOTSUPP; -+ /* Define these anyway so we don't need as much ifdef'ed code. */ -+ char *encoded_name = NULL; -+ char *encoded_value = NULL; -+ -+ check_mini_fo_dentry(dentry); -+ -+ if(exists_in_storage(dentry)) -+ hidden_dentry = dtohd2(dentry); -+ else -+ hidden_dentry = dtohd(dentry); -+ -+ ASSERT(hidden_dentry); -+ ASSERT(hidden_dentry->d_inode); -+ ASSERT(hidden_dentry->d_inode->i_op); -+ -+ if (hidden_dentry->d_inode->i_op->getxattr) { -+ encoded_name = (char *)name; -+ encoded_value = (char *)value; -+ -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16) -+ mutex_lock(&hidden_dentry->d_inode->i_mutex); -+#else -+ down(&hidden_dentry->d_inode->i_sem); -+#endif -+ /* lock_kernel() already done by caller. */ -+ err = hidden_dentry->d_inode->i_op->getxattr(hidden_dentry, encoded_name, encoded_value, size); -+ /* unlock_kernel() will be done by caller. */ -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16) -+ mutex_lock(&hidden_dentry->d_inode->i_mutex); -+#else -+ up(&hidden_dentry->d_inode->i_sem); -+#endif -+ } -+ return err; -+} -+ -+/* BKL held by caller. -+ * dentry->d_inode->i_sem down -+ */ -+STATIC int -+#if ((LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,21) \ -+ && LINUX_VERSION_CODE <= KERNEL_VERSION(2,4,23)) \ -+ || LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)) -+mini_fo_setxattr(struct dentry *dentry, const char *name, -+ const void *value, size_t size, int flags) -+#else -+mini_fo_setxattr(struct dentry *dentry, const char *name, -+ void *value, size_t size, int flags) -+#endif -+ -+{ -+ struct dentry *hidden_dentry = NULL; -+ int err = -EOPNOTSUPP; -+ -+ /* Define these anyway, so we don't have as much ifdef'ed code. */ -+ char *encoded_value = NULL; -+ char *encoded_name = NULL; -+ -+ check_mini_fo_dentry(dentry); -+ -+ if(exists_in_storage(dentry)) -+ hidden_dentry = dtohd2(dentry); -+ else -+ hidden_dentry = dtohd(dentry); -+ -+ ASSERT(hidden_dentry); -+ ASSERT(hidden_dentry->d_inode); -+ ASSERT(hidden_dentry->d_inode->i_op); -+ -+ if (hidden_dentry->d_inode->i_op->setxattr) { -+ encoded_name = (char *)name; -+ encoded_value = (char *)value; -+ -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16) -+ mutex_lock(&hidden_dentry->d_inode->i_mutex); -+#else -+ down(&hidden_dentry->d_inode->i_sem); -+#endif -+ /* lock_kernel() already done by caller. */ -+ err = hidden_dentry->d_inode->i_op->setxattr(hidden_dentry, encoded_name, encoded_value, size, flags); -+ /* unlock_kernel() will be done by caller. */ -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16) -+ mutex_unlock(&hidden_dentry->d_inode->i_mutex); -+#else -+ up(&hidden_dentry->d_inode->i_sem); -+#endif -+ } -+ return err; -+} -+ -+/* BKL held by caller. -+ * dentry->d_inode->i_sem down -+ */ -+STATIC int -+mini_fo_removexattr(struct dentry *dentry, const char *name) { -+ struct dentry *hidden_dentry = NULL; -+ int err = -EOPNOTSUPP; -+ char *encoded_name; -+ -+ check_mini_fo_dentry(dentry); -+ -+ if(exists_in_storage(dentry)) -+ hidden_dentry = dtohd2(dentry); -+ else -+ hidden_dentry = dtohd(dentry); -+ -+ ASSERT(hidden_dentry); -+ ASSERT(hidden_dentry->d_inode); -+ ASSERT(hidden_dentry->d_inode->i_op); -+ -+ if (hidden_dentry->d_inode->i_op->removexattr) { -+ encoded_name = (char *)name; -+ -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16) -+ mutex_lock(&hidden_dentry->d_inode->i_mutex); -+#else -+ down(&hidden_dentry->d_inode->i_sem); -+#endif -+ /* lock_kernel() already done by caller. */ -+ err = hidden_dentry->d_inode->i_op->removexattr(hidden_dentry, encoded_name); -+ /* unlock_kernel() will be done by caller. */ -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16) -+ mutex_unlock(&hidden_dentry->d_inode->i_mutex); -+#else -+ up(&hidden_dentry->d_inode->i_sem); -+#endif -+ } -+ return err; -+} -+ -+/* BKL held by caller. -+ * dentry->d_inode->i_sem down -+ */ -+STATIC int -+mini_fo_listxattr(struct dentry *dentry, char *list, size_t size) { -+ struct dentry *hidden_dentry = NULL; -+ int err = -EOPNOTSUPP; -+ char *encoded_list = NULL; -+ -+ check_mini_fo_dentry(dentry); -+ -+ if(exists_in_storage(dentry)) -+ hidden_dentry = dtohd2(dentry); -+ else -+ hidden_dentry = dtohd(dentry); -+ -+ ASSERT(hidden_dentry); -+ ASSERT(hidden_dentry->d_inode); -+ ASSERT(hidden_dentry->d_inode->i_op); -+ -+ if (hidden_dentry->d_inode->i_op->listxattr) { -+ encoded_list = list; -+ -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16) -+ mutex_lock(&hidden_dentry->d_inode->i_mutex); -+#else -+ down(&hidden_dentry->d_inode->i_sem); -+#endif -+ /* lock_kernel() already done by caller. */ -+ err = hidden_dentry->d_inode->i_op->listxattr(hidden_dentry, encoded_list, size); -+ /* unlock_kernel() will be done by caller. */ -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16) -+ mutex_unlock(&hidden_dentry->d_inode->i_mutex); -+#else -+ up(&hidden_dentry->d_inode->i_sem); -+#endif -+ } -+ return err; -+} -+# endif /* defined(XATTR) && (LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,20)) */ -+ -+struct inode_operations mini_fo_symlink_iops = -+ { -+ readlink: mini_fo_readlink, -+ follow_link: mini_fo_follow_link, -+ /* mk: permission: mini_fo_permission, */ -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) -+ revalidate: mini_fo_inode_revalidate, -+#endif -+ setattr: mini_fo_setattr, -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) -+ getattr: mini_fo_getattr, -+ put_link: mini_fo_put_link, -+#endif -+ -+#if defined(XATTR) && (LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,20)) -+ setxattr: mini_fo_setxattr, -+ getxattr: mini_fo_getxattr, -+ listxattr: mini_fo_listxattr, -+ removexattr: mini_fo_removexattr -+# endif /* defined(XATTR) && (LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,20)) */ -+ }; -+ -+struct inode_operations mini_fo_dir_iops = -+ { -+ create: mini_fo_create, -+ lookup: mini_fo_lookup, -+ link: mini_fo_link, -+ unlink: mini_fo_unlink, -+ symlink: mini_fo_symlink, -+ mkdir: mini_fo_mkdir, -+ rmdir: mini_fo_rmdir, -+ mknod: mini_fo_mknod, -+ rename: mini_fo_rename, -+ /* no readlink/follow_link for non-symlinks */ -+ // off because we have setattr -+ // truncate: mini_fo_truncate, -+ /* mk:permission: mini_fo_permission, */ -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) -+ revalidate: mini_fo_inode_revalidate, -+#endif -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) -+ getattr: mini_fo_getattr, -+#endif -+ setattr: mini_fo_setattr, -+#if defined(XATTR) && (LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,20)) -+ setxattr: mini_fo_setxattr, -+ getxattr: mini_fo_getxattr, -+ listxattr: mini_fo_listxattr, -+ removexattr: mini_fo_removexattr -+# endif /* XATTR && LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,20) */ -+ }; -+ -+struct inode_operations mini_fo_main_iops = -+ { -+ /* permission: mini_fo_permission, */ -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) -+ revalidate: mini_fo_inode_revalidate, -+#endif -+ setattr: mini_fo_setattr, -+ -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) -+ getattr: mini_fo_getattr, -+#endif -+#if defined(XATTR) && (LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,20)) -+ setxattr: mini_fo_setxattr, -+ getxattr: mini_fo_getxattr, -+ listxattr: mini_fo_listxattr, -+ removexattr: mini_fo_removexattr -+# endif /* XATTR && LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,20) */ -+ }; ---- /dev/null -+++ b/fs/mini_fo/main.c -@@ -0,0 +1,423 @@ -+/* -+ * Copyright (c) 1997-2003 Erez Zadok -+ * Copyright (c) 2001-2003 Stony Brook University -+ * -+ * For specific licensing information, see the COPYING file distributed with -+ * this package, or get one from ftp://ftp.filesystems.org/pub/fist/COPYING. -+ * -+ * This Copyright notice must be kept intact and distributed with all -+ * fistgen sources INCLUDING sources generated by fistgen. -+ */ -+/* -+ * Copyright (C) 2004, 2005 Markus Klotzbuecher -+ * -+ * 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. -+ */ -+ -+/* -+ * $Id$ -+ */ -+ -+#ifdef HAVE_CONFIG_H -+# include -+#endif -+ -+#include "fist.h" -+#include "mini_fo.h" -+#include -+ -+/* This definition must only appear after we include */ -+#ifndef MODULE_LICENSE -+# define MODULE_LICENSE(bison) -+#endif /* not MODULE_LICENSE */ -+ -+/* -+ * This is the mini_fo tri interpose function, which extends the -+ * functionality of the regular interpose by interposing a higher -+ * level inode on top of two lower level ones: the base filesystem -+ * inode and the storage filesystem inode. -+ * -+ * sb we pass is mini_fo's super_block -+ */ -+int -+mini_fo_tri_interpose(dentry_t *hidden_dentry, -+ dentry_t *hidden_sto_dentry, -+ dentry_t *dentry, super_block_t *sb, int flag) -+{ -+ inode_t *hidden_inode = NULL; -+ inode_t *hidden_sto_inode = NULL; /* store corresponding storage inode */ -+ int err = 0; -+ inode_t *inode; -+ -+ /* Pointer to hidden_sto_inode if exists, else to hidden_inode. -+ * This is used to copy the attributes of the correct inode. */ -+ inode_t *master_inode; -+ -+ if(hidden_dentry) -+ hidden_inode = hidden_dentry->d_inode; -+ if(hidden_sto_dentry) -+ hidden_sto_inode = hidden_sto_dentry->d_inode; -+ -+ ASSERT(dentry->d_inode == NULL); -+ -+ /* mk: One of the inodes associated with the dentrys is likely to -+ * be NULL, so carefull: -+ */ -+ ASSERT((hidden_inode != NULL) || (hidden_sto_inode != NULL)); -+ -+ if(hidden_sto_inode) -+ master_inode = hidden_sto_inode; -+ else -+ master_inode = hidden_inode; -+ -+ /* -+ * We allocate our new inode below, by calling iget. -+ * iget will call our read_inode which will initialize some -+ * of the new inode's fields -+ */ -+ -+ /* -+ * original: inode = iget(sb, hidden_inode->i_ino); -+ */ -+ inode = iget(sb, iunique(sb, 25)); -+ if (!inode) { -+ err = -EACCES; /* should be impossible??? */ -+ goto out; -+ } -+ -+ /* -+ * interpose the inode if not already interposed -+ * this is possible if the inode is being reused -+ * XXX: what happens if we get_empty_inode() but there's another already? -+ * for now, ASSERT() that this can't happen; fix later. -+ */ -+ if (itohi(inode) != NULL) { -+ printk(KERN_CRIT "mini_fo_tri_interpose: itohi(inode) != NULL.\n"); -+ } -+ if (itohi2(inode) != NULL) { -+ printk(KERN_CRIT "mini_fo_tri_interpose: itohi2(inode) != NULL.\n"); -+ } -+ -+ /* mk: Carefull, igrab can't handle NULL inodes (ok, why should it?), so -+ * we need to check here: -+ */ -+ if(hidden_inode) -+ itohi(inode) = igrab(hidden_inode); -+ else -+ itohi(inode) = NULL; -+ -+ if(hidden_sto_inode) -+ itohi2(inode) = igrab(hidden_sto_inode); -+ else -+ itohi2(inode) = NULL; -+ -+ -+ /* Use different set of inode ops for symlinks & directories*/ -+ if (S_ISLNK(master_inode->i_mode)) -+ inode->i_op = &mini_fo_symlink_iops; -+ else if (S_ISDIR(master_inode->i_mode)) -+ inode->i_op = &mini_fo_dir_iops; -+ -+ /* Use different set of file ops for directories */ -+ if (S_ISDIR(master_inode->i_mode)) -+ inode->i_fop = &mini_fo_dir_fops; -+ -+ /* properly initialize special inodes */ -+ if (S_ISBLK(master_inode->i_mode) || S_ISCHR(master_inode->i_mode) || -+ S_ISFIFO(master_inode->i_mode) || S_ISSOCK(master_inode->i_mode)) { -+ init_special_inode(inode, master_inode->i_mode, master_inode->i_rdev); -+ } -+ -+ /* Fix our inode's address operations to that of the lower inode */ -+ if (inode->i_mapping->a_ops != master_inode->i_mapping->a_ops) { -+ inode->i_mapping->a_ops = master_inode->i_mapping->a_ops; -+ } -+ -+ /* only (our) lookup wants to do a d_add */ -+ if (flag) -+ d_add(dentry, inode); -+ else -+ d_instantiate(dentry, inode); -+ -+ ASSERT(dtopd(dentry) != NULL); -+ -+ /* all well, copy inode attributes */ -+ fist_copy_attr_all(inode, master_inode); -+ -+ out: -+ return err; -+} -+ -+/* parse mount options "base=" and "sto=" */ -+dentry_t * -+mini_fo_parse_options(super_block_t *sb, char *options) -+{ -+ dentry_t *hidden_root = ERR_PTR(-EINVAL); -+ dentry_t *hidden_root2 = ERR_PTR(-EINVAL); -+ struct nameidata nd, nd2; -+ char *name, *tmp, *end; -+ int err = 0; -+ -+ /* We don't want to go off the end of our arguments later on. */ -+ for (end = options; *end; end++); -+ -+ while (options < end) { -+ tmp = options; -+ while (*tmp && *tmp != ',') -+ tmp++; -+ *tmp = '\0'; -+ if (!strncmp("base=", options, 5)) { -+ name = options + 5; -+ printk(KERN_INFO "mini_fo: using base directory: %s\n", name); -+ -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) -+ if (path_init(name, LOOKUP_FOLLOW, &nd)) -+ err = path_walk(name, &nd); -+#else -+ err = path_lookup(name, LOOKUP_FOLLOW, &nd); -+#endif -+ if (err) { -+ printk(KERN_CRIT "mini_fo: error accessing hidden directory '%s'\n", name); -+ hidden_root = ERR_PTR(err); -+ goto out; -+ } -+ hidden_root = nd.dentry; -+ stopd(sb)->base_dir_dentry = nd.dentry; -+ stopd(sb)->hidden_mnt = nd.mnt; -+ -+ } else if(!strncmp("sto=", options, 4)) { -+ /* parse the storage dir */ -+ name = options + 4; -+ printk(KERN_INFO "mini_fo: using storage directory: %s\n", name); -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) -+ if(path_init(name, LOOKUP_FOLLOW, &nd2)) -+ err = path_walk(name, &nd2); -+#else -+ err = path_lookup(name, LOOKUP_FOLLOW, &nd2); -+#endif -+ if(err) { -+ printk(KERN_CRIT "mini_fo: error accessing hidden storage directory '%s'\n", name); -+ -+ hidden_root2 = ERR_PTR(err); -+ goto out; -+ } -+ hidden_root2 = nd2.dentry; -+ stopd(sb)->storage_dir_dentry = nd2.dentry; -+ stopd(sb)->hidden_mnt2 = nd2.mnt; -+ stohs2(sb) = hidden_root2->d_sb; -+ -+ /* validate storage dir, this is done in -+ * mini_fo_read_super for the base directory. -+ */ -+ if (IS_ERR(hidden_root2)) { -+ printk(KERN_WARNING "mini_fo_parse_options: storage dentry lookup failed (err = %ld)\n", PTR_ERR(hidden_root2)); -+ goto out; -+ } -+ if (!hidden_root2->d_inode) { -+ printk(KERN_WARNING "mini_fo_parse_options: no storage dir to interpose on.\n"); -+ goto out; -+ } -+ stohs2(sb) = hidden_root2->d_sb; -+ } else { -+ printk(KERN_WARNING "mini_fo: unrecognized option '%s'\n", options); -+ hidden_root = ERR_PTR(-EINVAL); -+ goto out; -+ } -+ options = tmp + 1; -+ } -+ -+ out: -+ if(IS_ERR(hidden_root2)) -+ return hidden_root2; -+ return hidden_root; -+} -+ -+ -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) -+static int -+#else -+super_block_t * -+#endif -+mini_fo_read_super(super_block_t *sb, void *raw_data, int silent) -+{ -+ dentry_t *hidden_root; -+ int err = 0; -+ -+ if (!raw_data) { -+ printk(KERN_WARNING "mini_fo_read_super: missing argument\n"); -+ err = -EINVAL; -+ goto out; -+ } -+ /* -+ * Allocate superblock private data -+ */ -+ __stopd(sb) = kmalloc(sizeof(struct mini_fo_sb_info), GFP_KERNEL); -+ if (!stopd(sb)) { -+ printk(KERN_WARNING "%s: out of memory\n", __FUNCTION__); -+ err = -ENOMEM; -+ goto out; -+ } -+ stohs(sb) = NULL; -+ -+ hidden_root = mini_fo_parse_options(sb, raw_data); -+ if (IS_ERR(hidden_root)) { -+ printk(KERN_WARNING "mini_fo_read_super: lookup_dentry failed (err = %ld)\n", PTR_ERR(hidden_root)); -+ err = PTR_ERR(hidden_root); -+ goto out_free; -+ } -+ if (!hidden_root->d_inode) { -+ printk(KERN_WARNING "mini_fo_read_super: no directory to interpose on\n"); -+ goto out_free; -+ } -+ stohs(sb) = hidden_root->d_sb; -+ -+ /* -+ * Linux 2.4.2-ac3 and beyond has code in -+ * mm/filemap.c:generic_file_write() that requires sb->s_maxbytes -+ * to be populated. If not set, all write()s under that sb will -+ * return 0. -+ * -+ * Linux 2.4.4+ automatically sets s_maxbytes to MAX_NON_LFS; -+ * the filesystem should override it only if it supports LFS. -+ */ -+ /* non-SCA code is good to go with LFS */ -+ sb->s_maxbytes = hidden_root->d_sb->s_maxbytes; -+ -+ sb->s_op = &mini_fo_sops; -+ /* -+ * we can't use d_alloc_root if we want to use -+ * our own interpose function unchanged, -+ * so we simply replicate *most* of the code in d_alloc_root here -+ */ -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) -+ sb->s_root = d_alloc(NULL, &(const struct qstr) { "/", 1, 0 }); -+#else -+ sb->s_root = d_alloc(NULL, &(const struct qstr){hash: 0, name: "/", len : 1}); -+#endif -+ if (IS_ERR(sb->s_root)) { -+ printk(KERN_WARNING "mini_fo_read_super: d_alloc failed\n"); -+ err = -ENOMEM; -+ goto out_dput; -+ } -+ -+ sb->s_root->d_op = &mini_fo_dops; -+ sb->s_root->d_sb = sb; -+ sb->s_root->d_parent = sb->s_root; -+ -+ /* link the upper and lower dentries */ -+ __dtopd(sb->s_root) = (struct mini_fo_dentry_info *) -+ kmalloc(sizeof(struct mini_fo_dentry_info), GFP_KERNEL); -+ if (!dtopd(sb->s_root)) { -+ err = -ENOMEM; -+ goto out_dput2; -+ } -+ dtopd(sb->s_root)->state = MODIFIED; -+ dtohd(sb->s_root) = hidden_root; -+ -+ /* fanout relevant, interpose on storage root dentry too */ -+ dtohd2(sb->s_root) = stopd(sb)->storage_dir_dentry; -+ -+ /* ...and call tri-interpose to interpose root dir inodes -+ * if (mini_fo_interpose(hidden_root, sb->s_root, sb, 0)) -+ */ -+ if(mini_fo_tri_interpose(hidden_root, dtohd2(sb->s_root), sb->s_root, sb, 0)) -+ goto out_dput2; -+ -+ /* initalize the wol list */ -+ itopd(sb->s_root->d_inode)->deleted_list_size = -1; -+ itopd(sb->s_root->d_inode)->renamed_list_size = -1; -+ meta_build_lists(sb->s_root); -+ -+ goto out; -+ -+ out_dput2: -+ dput(sb->s_root); -+ out_dput: -+ dput(hidden_root); -+ dput(dtohd2(sb->s_root)); /* release the hidden_sto_dentry too */ -+ out_free: -+ kfree(stopd(sb)); -+ __stopd(sb) = NULL; -+ out: -+ -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) -+ return err; -+#else -+ if (err) { -+ return ERR_PTR(err); -+ } else { -+ return sb; -+ } -+#endif -+} -+ -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,18) -+static int mini_fo_get_sb(struct file_system_type *fs_type, -+ int flags, const char *dev_name, -+ void *raw_data, struct vfsmount *mnt) -+{ -+ return get_sb_nodev(fs_type, flags, raw_data, mini_fo_read_super, mnt); -+} -+#else -+static struct super_block *mini_fo_get_sb(struct file_system_type *fs_type, -+ int flags, const char *dev_name, -+ void *raw_data) -+{ -+ return get_sb_nodev(fs_type, flags, raw_data, mini_fo_read_super); -+} -+#endif -+ -+void mini_fo_kill_block_super(struct super_block *sb) -+{ -+ generic_shutdown_super(sb); -+ /* -+ * XXX: BUG: Halcrow: Things get unstable sometime after this point: -+ * lib/rwsem-spinlock.c:127: spin_is_locked on uninitialized -+ * fs/fs-writeback.c:402: spin_lock(fs/super.c:a0381828) already -+ * locked by fs/fs-writeback.c/402 -+ * -+ * Apparently, someone's not releasing a lock on sb_lock... -+ */ -+} -+ -+static struct file_system_type mini_fo_fs_type = { -+ .owner = THIS_MODULE, -+ .name = "mini_fo", -+ .get_sb = mini_fo_get_sb, -+ .kill_sb = mini_fo_kill_block_super, -+ .fs_flags = 0, -+}; -+ -+ -+#else -+static DECLARE_FSTYPE(mini_fo_fs_type, "mini_fo", mini_fo_read_super, 0); -+#endif -+ -+static int __init init_mini_fo_fs(void) -+{ -+ printk("Registering mini_fo version $Id$\n"); -+ return register_filesystem(&mini_fo_fs_type); -+} -+static void __exit exit_mini_fo_fs(void) -+{ -+ printk("Unregistering mini_fo version $Id$\n"); -+ unregister_filesystem(&mini_fo_fs_type); -+} -+ -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) -+EXPORT_NO_SYMBOLS; -+#endif -+ -+MODULE_AUTHOR("Erez Zadok "); -+MODULE_DESCRIPTION("FiST-generated mini_fo filesystem"); -+MODULE_LICENSE("GPL"); -+ -+/* MODULE_PARM(fist_debug_var, "i"); */ -+/* MODULE_PARM_DESC(fist_debug_var, "Debug level"); */ -+ -+module_init(init_mini_fo_fs) -+module_exit(exit_mini_fo_fs) ---- /dev/null -+++ b/fs/mini_fo/Makefile -@@ -0,0 +1,17 @@ -+# -+# Makefile for mini_fo 2.4 and 2.6 Linux kernels -+# -+# Copyright (C) 2004, 2005 Markus Klotzbuecher -+# -+# 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. -+# -+ -+obj-$(CONFIG_MINI_FO) := mini_fo.o -+mini_fo-objs := meta.o dentry.o file.o inode.o main.o super.o state.o aux.o -+ -+# dependencies -+${mini_fo-objs}: mini_fo.h fist.h -+ ---- /dev/null -+++ b/fs/mini_fo/meta.c -@@ -0,0 +1,1000 @@ -+/* -+ * Copyright (C) 2004, 2005 Markus Klotzbuecher -+ * -+ * 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. -+ */ -+ -+#ifdef HAVE_CONFIG_H -+# include -+#endif /* HAVE_CONFIG_H */ -+#include "fist.h" -+#include "mini_fo.h" -+ -+int meta_build_lists(dentry_t *dentry) -+{ -+ struct mini_fo_inode_info *inode_info; -+ -+ dentry_t *meta_dentry = 0; -+ file_t *meta_file = 0; -+ mm_segment_t old_fs; -+ void *buf; -+ -+ int bytes, len; -+ struct vfsmount *meta_mnt; -+ char *entry; -+ -+ inode_info = itopd(dentry->d_inode); -+ if(!(inode_info->deleted_list_size == -1 && -+ inode_info->renamed_list_size == -1)) { -+ printk(KERN_CRIT "mini_fo: meta_build_lists: \ -+ Error, list(s) not virgin.\n"); -+ return -1; -+ } -+ -+ /* init our meta lists */ -+ INIT_LIST_HEAD(&inode_info->deleted_list); -+ inode_info->deleted_list_size = 0; -+ -+ INIT_LIST_HEAD(&inode_info->renamed_list); -+ inode_info->renamed_list_size = 0; -+ -+ /* might there be a META-file? */ -+ if(dtohd2(dentry) && dtohd2(dentry)->d_inode) { -+ meta_dentry = lookup_one_len(META_FILENAME, -+ dtohd2(dentry), -+ strlen(META_FILENAME)); -+ if(!meta_dentry->d_inode) { -+ dput(meta_dentry); -+ goto out_ok; -+ } -+ /* $%& err, is this correct? */ -+ meta_mnt = stopd(dentry->d_inode->i_sb)->hidden_mnt2; -+ mntget(meta_mnt); -+ -+ -+ /* open META-file for reading */ -+ meta_file = dentry_open(meta_dentry, meta_mnt, 0x0); -+ if(!meta_file || IS_ERR(meta_file)) { -+ printk(KERN_CRIT "mini_fo: meta_build_lists: \ -+ ERROR opening META file.\n"); -+ goto out_err; -+ } -+ -+ /* check if fs supports reading */ -+ if(!meta_file->f_op->read) { -+ printk(KERN_CRIT "mini_fo: meta_build_lists: \ -+ ERROR, fs does not support reading.\n"); -+ goto out_err_close; -+ } -+ -+ /* allocate a page for transfering the data */ -+ buf = (void *) __get_free_page(GFP_KERNEL); -+ if(!buf) { -+ printk(KERN_CRIT "mini_fo: meta_build_lists: \ -+ ERROR, out of mem.\n"); -+ goto out_err_close; -+ } -+ meta_file->f_pos = 0; -+ old_fs = get_fs(); -+ set_fs(KERNEL_DS); -+ do { -+ char *c; -+ bytes = meta_file->f_op->read(meta_file, buf, PAGE_SIZE, &meta_file->f_pos); -+ if(bytes == PAGE_SIZE) { -+ /* trim a cut off filename and adjust f_pos to get it next time */ -+ for(c = (char*) buf+PAGE_SIZE; -+ *c != '\n'; -+ c--, bytes--, meta_file->f_pos--); -+ } -+ entry = (char *) buf; -+ while(entry < (char *) buf+bytes) { -+ -+ char *old_path; -+ char *dir_name; -+ int old_len, new_len; -+ -+ /* len without '\n'*/ -+ len = (int) (strchr(entry, '\n') - entry); -+ switch (*entry) { -+ case 'D': -+ /* format: "D filename" */ -+ meta_list_add_d_entry(dentry, -+ entry+2, -+ len-2); -+ break; -+ case 'R': -+ /* format: "R path/xy/dir newDir" */ -+ old_path = entry+2; -+ dir_name = strchr(old_path, ' ') + 1; -+ old_len = dir_name - old_path - 1; -+ new_len = ((int) entry) + len - ((int ) dir_name); -+ meta_list_add_r_entry(dentry, -+ old_path, -+ old_len, -+ dir_name, -+ new_len); -+ break; -+ default: -+ /* unknown entry type detected */ -+ break; -+ } -+ entry += len+1; -+ } -+ -+ } while(meta_file->f_pos < meta_dentry->d_inode->i_size); -+ -+ free_page((unsigned long) buf); -+ set_fs(old_fs); -+ fput(meta_file); -+ } -+ goto out_ok; -+ -+ out_err_close: -+ fput(meta_file); -+ out_err: -+ mntput(meta_mnt); -+ dput(meta_dentry); -+ return -1; -+ out_ok: -+ return 1; /* check this!!! inode_info->wol_size; */ -+} -+ -+/* cleanups up all lists and free's the mem by dentry */ -+int meta_put_lists(dentry_t *dentry) -+{ -+ if(!dentry || !dentry->d_inode) { -+ printk("mini_fo: meta_put_lists: invalid dentry passed.\n"); -+ return -1; -+ } -+ return __meta_put_lists(dentry->d_inode); -+} -+ -+/* cleanups up all lists and free's the mem by inode */ -+int __meta_put_lists(inode_t *inode) -+{ -+ int err = 0; -+ if(!inode || !itopd(inode)) { -+ printk("mini_fo: __meta_put_lists: invalid inode passed.\n"); -+ return -1; -+ } -+ err = __meta_put_d_list(inode); -+ err |= __meta_put_r_list(inode); -+ return err; -+} -+ -+int meta_sync_lists(dentry_t *dentry) -+{ -+ int err = 0; -+ if(!dentry || !dentry->d_inode) { -+ printk("mini_fo: meta_sync_lists: \ -+ invalid dentry passed.\n"); -+ return -1; -+ } -+ err = meta_sync_d_list(dentry, 0); -+ err |= meta_sync_r_list(dentry, 1); -+ return err; -+} -+ -+ -+/* remove all D entries from the renamed list and free the mem */ -+int __meta_put_d_list(inode_t *inode) -+{ -+ struct list_head *tmp; -+ struct deleted_entry *del_entry; -+ struct mini_fo_inode_info *inode_info; -+ -+ if(!inode || !itopd(inode)) { -+ printk(KERN_CRIT "mini_fo: __meta_put_d_list: \ -+ invalid inode passed.\n"); -+ return -1; -+ } -+ inode_info = itopd(inode); -+ -+ /* nuke the DELETED-list */ -+ if(inode_info->deleted_list_size <= 0) -+ return 0; -+ -+ while(!list_empty(&inode_info->deleted_list)) { -+ tmp = inode_info->deleted_list.next; -+ list_del(tmp); -+ del_entry = list_entry(tmp, struct deleted_entry, list); -+ kfree(del_entry->name); -+ kfree(del_entry); -+ } -+ inode_info->deleted_list_size = 0; -+ -+ return 0; -+} -+ -+/* remove all R entries from the renamed list and free the mem */ -+int __meta_put_r_list(inode_t *inode) -+{ -+ struct list_head *tmp; -+ struct renamed_entry *ren_entry; -+ struct mini_fo_inode_info *inode_info; -+ -+ if(!inode || !itopd(inode)) { -+ printk(KERN_CRIT "mini_fo: meta_put_r_list: invalid inode.\n"); -+ return -1; -+ } -+ inode_info = itopd(inode); -+ -+ /* nuke the RENAMED-list */ -+ if(inode_info->renamed_list_size <= 0) -+ return 0; -+ -+ while(!list_empty(&inode_info->renamed_list)) { -+ tmp = inode_info->renamed_list.next; -+ list_del(tmp); -+ ren_entry = list_entry(tmp, struct renamed_entry, list); -+ kfree(ren_entry->new_name); -+ kfree(ren_entry->old_name); -+ kfree(ren_entry); -+ } -+ inode_info->renamed_list_size = 0; -+ -+ return 0; -+} -+ -+int meta_add_d_entry(dentry_t *dentry, const char *name, int len) -+{ -+ int err = 0; -+ err = meta_list_add_d_entry(dentry, name, len); -+ err |= meta_write_d_entry(dentry,name,len); -+ return err; -+} -+ -+/* add a D entry to the deleted list */ -+int meta_list_add_d_entry(dentry_t *dentry, const char *name, int len) -+{ -+ struct deleted_entry *del_entry; -+ struct mini_fo_inode_info *inode_info; -+ -+ if(!dentry || !dentry->d_inode) { -+ printk(KERN_CRIT "mini_fo: meta_list_add_d_entry: \ -+ invalid dentry passed.\n"); -+ return -1; -+ } -+ inode_info = itopd(dentry->d_inode); -+ -+ if(inode_info->deleted_list_size < 0) -+ return -1; -+ -+ del_entry = (struct deleted_entry *) -+ kmalloc(sizeof(struct deleted_entry), GFP_KERNEL); -+ del_entry->name = (char*) kmalloc(len, GFP_KERNEL); -+ if(!del_entry || !del_entry->name) { -+ printk(KERN_CRIT "mini_fo: meta_list_add_d_entry: \ -+ out of mem.\n"); -+ kfree(del_entry->name); -+ kfree(del_entry); -+ return -ENOMEM; -+ } -+ -+ strncpy(del_entry->name, name, len); -+ del_entry->len = len; -+ -+ list_add(&del_entry->list, &inode_info->deleted_list); -+ inode_info->deleted_list_size++; -+ return 0; -+} -+ -+int meta_add_r_entry(dentry_t *dentry, -+ const char *old_name, int old_len, -+ const char *new_name, int new_len) -+{ -+ int err = 0; -+ err = meta_list_add_r_entry(dentry, -+ old_name, old_len, -+ new_name, new_len); -+ err |= meta_write_r_entry(dentry, -+ old_name, old_len, -+ new_name, new_len); -+ return err; -+} -+ -+/* add a R entry to the renamed list */ -+int meta_list_add_r_entry(dentry_t *dentry, -+ const char *old_name, int old_len, -+ const char *new_name, int new_len) -+{ -+ struct renamed_entry *ren_entry; -+ struct mini_fo_inode_info *inode_info; -+ -+ if(!dentry || !dentry->d_inode) { -+ printk(KERN_CRIT "mini_fo: meta_list_add_r_entry: \ -+ invalid dentry passed.\n"); -+ return -1; -+ } -+ inode_info = itopd(dentry->d_inode); -+ -+ if(inode_info->renamed_list_size < 0) -+ return -1; -+ -+ ren_entry = (struct renamed_entry *) -+ kmalloc(sizeof(struct renamed_entry), GFP_KERNEL); -+ ren_entry->old_name = (char*) kmalloc(old_len, GFP_KERNEL); -+ ren_entry->new_name = (char*) kmalloc(new_len, GFP_KERNEL); -+ -+ if(!ren_entry || !ren_entry->old_name || !ren_entry->new_name) { -+ printk(KERN_CRIT "mini_fo: meta_list_add_r_entry: \ -+ out of mem.\n"); -+ kfree(ren_entry->new_name); -+ kfree(ren_entry->old_name); -+ kfree(ren_entry); -+ return -ENOMEM; -+ } -+ -+ strncpy(ren_entry->old_name, old_name, old_len); -+ ren_entry->old_len = old_len; -+ strncpy(ren_entry->new_name, new_name, new_len); -+ ren_entry->new_len = new_len; -+ -+ list_add(&ren_entry->list, &inode_info->renamed_list); -+ inode_info->renamed_list_size++; -+ return 0; -+} -+ -+ -+int meta_remove_r_entry(dentry_t *dentry, const char *name, int len) -+{ -+ int err = 0; -+ if(!dentry || !dentry->d_inode) { -+ printk(KERN_CRIT -+ "mini_fo: meta_remove_r_entry: \ -+ invalid dentry passed.\n"); -+ return -1; -+ } -+ -+ err = meta_list_remove_r_entry(dentry, name, len); -+ err |= meta_sync_lists(dentry); -+ return err; -+} -+ -+int meta_list_remove_r_entry(dentry_t *dentry, const char *name, int len) -+{ -+ if(!dentry || !dentry->d_inode) { -+ printk(KERN_CRIT -+ "mini_fo: meta_list_remove_r_entry: \ -+ invalid dentry passed.\n"); -+ return -1; -+ } -+ return __meta_list_remove_r_entry(dentry->d_inode, name, len); -+} -+ -+int __meta_list_remove_r_entry(inode_t *inode, const char *name, int len) -+{ -+ struct list_head *tmp; -+ struct renamed_entry *ren_entry; -+ struct mini_fo_inode_info *inode_info; -+ -+ if(!inode || !itopd(inode)) -+ printk(KERN_CRIT -+ "mini_fo: __meta_list_remove_r_entry: \ -+ invalid inode passed.\n"); -+ inode_info = itopd(inode); -+ -+ if(inode_info->renamed_list_size < 0) -+ return -1; -+ if(inode_info->renamed_list_size == 0) -+ return 1; -+ -+ list_for_each(tmp, &inode_info->renamed_list) { -+ ren_entry = list_entry(tmp, struct renamed_entry, list); -+ if(ren_entry->new_len != len) -+ continue; -+ -+ if(!strncmp(ren_entry->new_name, name, len)) { -+ list_del(tmp); -+ kfree(ren_entry->new_name); -+ kfree(ren_entry->old_name); -+ kfree(ren_entry); -+ inode_info->renamed_list_size--; -+ return 0; -+ } -+ } -+ return 1; -+} -+ -+ -+/* append a single D entry to the meta file */ -+int meta_write_d_entry(dentry_t *dentry, const char *name, int len) -+{ -+ dentry_t *meta_dentry = 0; -+ file_t *meta_file = 0; -+ mm_segment_t old_fs; -+ -+ int bytes, err; -+ struct vfsmount *meta_mnt = 0; -+ char *buf; -+ -+ err = 0; -+ -+ if(itopd(dentry->d_inode)->deleted_list_size < 0) { -+ err = -1; -+ goto out; -+ } -+ -+ if(dtopd(dentry)->state == UNMODIFIED) { -+ err = build_sto_structure(dentry->d_parent, dentry); -+ if(err) { -+ printk(KERN_CRIT "mini_fo: meta_write_d_entry: \ -+ build_sto_structure failed.\n"); -+ goto out; -+ } -+ } -+ meta_dentry = lookup_one_len(META_FILENAME, -+ dtohd2(dentry), strlen (META_FILENAME)); -+ -+ /* We need to create a META-file */ -+ if(!meta_dentry->d_inode) { -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) -+ vfs_create(dtohd2(dentry)->d_inode, -+ meta_dentry, -+ S_IRUSR | S_IWUSR, -+ NULL); -+#else -+ vfs_create(dtohd2(dentry)->d_inode, -+ meta_dentry, -+ S_IRUSR | S_IWUSR); -+#endif -+ } -+ /* 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_write_d_entry: \ -+ ERROR opening meta file.\n"); -+ mntput(meta_mnt); /* $%& is this necessary? */ -+ dput(meta_dentry); -+ err = -1; -+ goto out; -+ } -+ -+ /* check if fs supports writing */ -+ if(!meta_file->f_op->write) { -+ printk(KERN_CRIT "mini_fo: meta_write_d_entry: \ -+ ERROR, fs does not support writing.\n"); -+ goto out_err_close; -+ } -+ -+ meta_file->f_pos = meta_dentry->d_inode->i_size; /* append */ -+ old_fs = get_fs(); -+ set_fs(KERNEL_DS); -+ -+ /* size: len for name, 1 for \n and 2 for "D " */ -+ buf = (char *) kmalloc(len+3, GFP_KERNEL); -+ if (!buf) { -+ printk(KERN_CRIT "mini_fo: meta_write_d_entry: \ -+ out of mem.\n"); -+ return -ENOMEM; -+ } -+ -+ buf[0] = 'D'; -+ buf[1] = ' '; -+ strncpy(buf+2, name, len); -+ buf[len+2] = '\n'; -+ bytes = meta_file->f_op->write(meta_file, buf, len+3, -+ &meta_file->f_pos); -+ if(bytes != len+3) { -+ printk(KERN_CRIT "mini_fo: meta_write_d_entry: \ -+ ERROR writing.\n"); -+ err = -1; -+ } -+ kfree(buf); -+ set_fs(old_fs); -+ -+ out_err_close: -+ fput(meta_file); -+ out: -+ return err; -+} -+ -+/* append a single R entry to the meta file */ -+int meta_write_r_entry(dentry_t *dentry, -+ const char *old_name, int old_len, -+ const char *new_name, int new_len) -+{ -+ dentry_t *meta_dentry = 0; -+ file_t *meta_file = 0; -+ mm_segment_t old_fs; -+ -+ int bytes, err, buf_len; -+ struct vfsmount *meta_mnt = 0; -+ char *buf; -+ -+ -+ err = 0; -+ -+ if(itopd(dentry->d_inode)->renamed_list_size < 0) { -+ err = -1; -+ goto out; -+ } -+ -+ /* build the storage structure? */ -+ if(dtopd(dentry)->state == UNMODIFIED) { -+ err = build_sto_structure(dentry->d_parent, dentry); -+ if(err) { -+ printk(KERN_CRIT "mini_fo: meta_write_r_entry: \ -+ build_sto_structure failed.\n"); -+ goto out; -+ } -+ } -+ meta_dentry = lookup_one_len(META_FILENAME, -+ dtohd2(dentry), -+ strlen (META_FILENAME)); -+ if(!meta_dentry->d_inode) { -+ /* We need to create a META-file */ -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) -+ vfs_create(dtohd2(dentry)->d_inode, -+ meta_dentry, S_IRUSR | S_IWUSR, NULL); -+#else -+ vfs_create(dtohd2(dentry)->d_inode, -+ meta_dentry, S_IRUSR | S_IWUSR); -+#endif -+ } -+ /* 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_write_r_entry: \ -+ ERROR opening meta file.\n"); -+ mntput(meta_mnt); -+ dput(meta_dentry); -+ err = -1; -+ goto out; -+ } -+ -+ /* check if fs supports writing */ -+ if(!meta_file->f_op->write) { -+ printk(KERN_CRIT "mini_fo: meta_write_r_entry: \ -+ ERROR, fs does not support writing.\n"); -+ goto out_err_close; -+ } -+ -+ meta_file->f_pos = meta_dentry->d_inode->i_size; /* append */ -+ old_fs = get_fs(); -+ set_fs(KERNEL_DS); -+ -+ /* size: 2 for "R ", old_len+new_len for names, 1 blank+1 \n */ -+ buf_len = old_len + new_len + 4; -+ buf = (char *) kmalloc(buf_len, GFP_KERNEL); -+ if (!buf) { -+ printk(KERN_CRIT "mini_fo: meta_write_r_entry: out of mem.\n"); -+ return -ENOMEM; -+ } -+ -+ buf[0] = 'R'; -+ buf[1] = ' '; -+ strncpy(buf + 2, old_name, old_len); -+ buf[old_len + 2] = ' '; -+ strncpy(buf + old_len + 3, new_name, new_len); -+ buf[buf_len -1] = '\n'; -+ bytes = meta_file->f_op->write(meta_file, buf, buf_len, &meta_file->f_pos); -+ if(bytes != buf_len) { -+ printk(KERN_CRIT "mini_fo: meta_write_r_entry: ERROR writing.\n"); -+ err = -1; -+ } -+ -+ kfree(buf); -+ set_fs(old_fs); -+ -+ out_err_close: -+ fput(meta_file); -+ out: -+ return err; -+} -+ -+/* sync D list to disk, append data if app_flag is 1 */ -+/* check the meta_mnt, which seems not to be used (properly) */ -+ -+int meta_sync_d_list(dentry_t *dentry, int app_flag) -+{ -+ dentry_t *meta_dentry; -+ file_t *meta_file; -+ mm_segment_t old_fs; -+ -+ int bytes, err; -+ struct vfsmount *meta_mnt; -+ char *buf; -+ -+ struct list_head *tmp; -+ struct deleted_entry *del_entry; -+ struct mini_fo_inode_info *inode_info; -+ -+ err = 0; -+ meta_file=0; -+ meta_mnt=0; -+ -+ if(!dentry || !dentry->d_inode) { -+ printk(KERN_CRIT "mini_fo: meta_sync_d_list: \ -+ invalid inode passed.\n"); -+ err = -1; -+ goto out; -+ } -+ inode_info = itopd(dentry->d_inode); -+ -+ if(inode_info->deleted_list_size < 0) { -+ err = -1; -+ goto out; -+ } -+ -+ /* ok, there is something to sync */ -+ -+ /* build the storage structure? */ -+ if(!dtohd2(dentry) && !itohi2(dentry->d_inode)) { -+ err = build_sto_structure(dentry->d_parent, dentry); -+ if(err) { -+ printk(KERN_CRIT "mini_fo: meta_sync_d_list: \ -+ build_sto_structure failed.\n"); -+ goto out; -+ } -+ } -+ meta_dentry = lookup_one_len(META_FILENAME, -+ dtohd2(dentry), -+ strlen(META_FILENAME)); -+ if(!meta_dentry->d_inode) { -+ /* We need to create a META-file */ -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) -+ vfs_create(dtohd2(dentry)->d_inode, -+ meta_dentry, S_IRUSR | S_IWUSR, NULL); -+#else -+ vfs_create(dtohd2(dentry)->d_inode, -+ meta_dentry, S_IRUSR | S_IWUSR); -+#endif -+ app_flag = 0; -+ } -+ /* need we truncate the meta file? */ -+ if(!app_flag) { -+ struct iattr newattrs; -+ newattrs.ia_size = 0; -+ newattrs.ia_valid = ATTR_SIZE | ATTR_CTIME; -+ -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16) -+ mutex_lock(&meta_dentry->d_inode->i_mutex); -+#else -+ down(&meta_dentry->d_inode->i_sem); -+#endif -+ err = notify_change(meta_dentry, &newattrs); -+ -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16) -+ mutex_unlock(&meta_dentry->d_inode->i_mutex); -+#else -+ up(&meta_dentry->d_inode->i_sem); -+#endif -+ -+ if(err || meta_dentry->d_inode->i_size != 0) { -+ printk(KERN_CRIT "mini_fo: meta_sync_d_list: \ -+ ERROR truncating meta file.\n"); -+ goto out_err_close; -+ } -+ } -+ -+ /* 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); -+ */ -+ dput(meta_dentry); -+ err = -1; -+ goto out; -+ } -+ -+ /* check if fs supports writing */ -+ if(!meta_file->f_op->write) { -+ printk(KERN_CRIT "mini_fo: meta_sync_d_list: \ -+ ERROR, fs does not support writing.\n"); -+ goto out_err_close; -+ } -+ -+ meta_file->f_pos = meta_dentry->d_inode->i_size; /* append */ -+ old_fs = get_fs(); -+ set_fs(KERNEL_DS); -+ -+ /* here we go... */ -+ list_for_each(tmp, &inode_info->deleted_list) { -+ del_entry = list_entry(tmp, struct deleted_entry, list); -+ -+ /* size: len for name, 1 for \n and 2 for "D " */ -+ buf = (char *) kmalloc(del_entry->len+3, GFP_KERNEL); -+ if (!buf) { -+ printk(KERN_CRIT "mini_fo: meta_sync_d_list: \ -+ out of mem.\n"); -+ return -ENOMEM; -+ } -+ -+ buf[0] = 'D'; -+ buf[1] = ' '; -+ strncpy(buf+2, del_entry->name, del_entry->len); -+ buf[del_entry->len+2] = '\n'; -+ bytes = meta_file->f_op->write(meta_file, buf, -+ del_entry->len+3, -+ &meta_file->f_pos); -+ if(bytes != del_entry->len+3) { -+ printk(KERN_CRIT "mini_fo: meta_sync_d_list: \ -+ ERROR writing.\n"); -+ err |= -1; -+ } -+ kfree(buf); -+ } -+ set_fs(old_fs); -+ -+ out_err_close: -+ fput(meta_file); -+ out: -+ return err; -+ -+} -+ -+int meta_sync_r_list(dentry_t *dentry, int app_flag) -+{ -+ dentry_t *meta_dentry; -+ file_t *meta_file; -+ mm_segment_t old_fs; -+ -+ int bytes, err, buf_len; -+ struct vfsmount *meta_mnt; -+ char *buf; -+ -+ struct list_head *tmp; -+ struct renamed_entry *ren_entry; -+ struct mini_fo_inode_info *inode_info; -+ -+ err = 0; -+ meta_file=0; -+ meta_mnt=0; -+ -+ if(!dentry || !dentry->d_inode) { -+ printk(KERN_CRIT "mini_fo: meta_sync_r_list: \ -+ invalid dentry passed.\n"); -+ err = -1; -+ goto out; -+ } -+ inode_info = itopd(dentry->d_inode); -+ -+ if(inode_info->deleted_list_size < 0) { -+ err = -1; -+ goto out; -+ } -+ -+ /* ok, there is something to sync */ -+ -+ /* build the storage structure? */ -+ if(!dtohd2(dentry) && !itohi2(dentry->d_inode)) { -+ err = build_sto_structure(dentry->d_parent, dentry); -+ if(err) { -+ printk(KERN_CRIT "mini_fo: meta_sync_r_list: \ -+ build_sto_structure failed.\n"); -+ goto out; -+ } -+ } -+ meta_dentry = lookup_one_len(META_FILENAME, -+ dtohd2(dentry), -+ strlen(META_FILENAME)); -+ if(!meta_dentry->d_inode) { -+ /* We need to create a META-file */ -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) -+ vfs_create(dtohd2(dentry)->d_inode, -+ meta_dentry, S_IRUSR | S_IWUSR, NULL); -+#else -+ vfs_create(dtohd2(dentry)->d_inode, -+ meta_dentry, S_IRUSR | S_IWUSR); -+#endif -+ app_flag = 0; -+ } -+ /* need we truncate the meta file? */ -+ if(!app_flag) { -+ struct iattr newattrs; -+ newattrs.ia_size = 0; -+ newattrs.ia_valid = ATTR_SIZE | ATTR_CTIME; -+ -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16) -+ mutex_lock(&meta_dentry->d_inode->i_mutex); -+#else -+ down(&meta_dentry->d_inode->i_sem); -+#endif -+ err = notify_change(meta_dentry, &newattrs); -+ -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16) -+ mutex_unlock(&meta_dentry->d_inode->i_mutex); -+#else -+ up(&meta_dentry->d_inode->i_sem); -+#endif -+ if(err || meta_dentry->d_inode->i_size != 0) { -+ printk(KERN_CRIT "mini_fo: meta_sync_r_list: \ -+ ERROR truncating meta file.\n"); -+ goto out_err_close; -+ } -+ } -+ -+ /* 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); -+ */ -+ dput(meta_dentry); -+ err = -1; -+ goto out; -+ } -+ -+ /* check if fs supports writing */ -+ if(!meta_file->f_op->write) { -+ printk(KERN_CRIT "mini_fo: meta_sync_r_list: \ -+ ERROR, fs does not support writing.\n"); -+ goto out_err_close; -+ } -+ -+ meta_file->f_pos = meta_dentry->d_inode->i_size; /* append */ -+ old_fs = get_fs(); -+ set_fs(KERNEL_DS); -+ -+ /* here we go... */ -+ list_for_each(tmp, &inode_info->renamed_list) { -+ ren_entry = list_entry(tmp, struct renamed_entry, list); -+ /* size: -+ * 2 for "R ", old_len+new_len for names, 1 blank+1 \n */ -+ buf_len = ren_entry->old_len + ren_entry->new_len + 4; -+ buf = (char *) kmalloc(buf_len, GFP_KERNEL); -+ if (!buf) { -+ printk(KERN_CRIT "mini_fo: meta_sync_r_list: \ -+ out of mem.\n"); -+ return -ENOMEM; -+ } -+ buf[0] = 'R'; -+ buf[1] = ' '; -+ strncpy(buf + 2, ren_entry->old_name, ren_entry->old_len); -+ buf[ren_entry->old_len + 2] = ' '; -+ strncpy(buf + ren_entry->old_len + 3, -+ ren_entry->new_name, ren_entry->new_len); -+ buf[buf_len - 1] = '\n'; -+ bytes = meta_file->f_op->write(meta_file, buf, -+ buf_len, &meta_file->f_pos); -+ if(bytes != buf_len) { -+ printk(KERN_CRIT "mini_fo: meta_sync_r_list: \ -+ ERROR writing.\n"); -+ err |= -1; -+ } -+ kfree(buf); -+ } -+ set_fs(old_fs); -+ -+ out_err_close: -+ fput(meta_file); -+ out: -+ return err; -+} -+ -+int meta_check_d_entry(dentry_t *dentry, const char *name, int len) -+{ -+ if(!dentry || !dentry->d_inode) -+ printk(KERN_CRIT "mini_fo: meta_check_d_dentry: \ -+ invalid dentry passed.\n"); -+ return __meta_check_d_entry(dentry->d_inode, name, len); -+} -+ -+int __meta_check_d_entry(inode_t *inode, const char *name, int len) -+{ -+ struct list_head *tmp; -+ struct deleted_entry *del_entry; -+ struct mini_fo_inode_info *inode_info; -+ -+ if(!inode || !itopd(inode)) -+ printk(KERN_CRIT "mini_fo: __meta_check_d_dentry: \ -+ invalid inode passed.\n"); -+ -+ inode_info = itopd(inode); -+ -+ if(inode_info->deleted_list_size <= 0) -+ return 0; -+ -+ list_for_each(tmp, &inode_info->deleted_list) { -+ del_entry = list_entry(tmp, struct deleted_entry, list); -+ if(del_entry->len != len) -+ continue; -+ -+ if(!strncmp(del_entry->name, name, len)) -+ return 1; -+ } -+ return 0; -+} -+ -+/* -+ * check if file has been renamed and return path to orig. base dir. -+ * Implements no error return values so far, what of course sucks. -+ * String is null terminated.' -+ */ -+char* meta_check_r_entry(dentry_t *dentry, const char *name, int len) -+{ -+ if(!dentry || !dentry->d_inode) { -+ printk(KERN_CRIT "mini_fo: meta_check_r_dentry: \ -+ invalid dentry passed.\n"); -+ return NULL; -+ } -+ return __meta_check_r_entry(dentry->d_inode, name, len); -+} -+ -+char* __meta_check_r_entry(inode_t *inode, const char *name, int len) -+{ -+ struct list_head *tmp; -+ struct renamed_entry *ren_entry; -+ struct mini_fo_inode_info *inode_info; -+ char *old_path; -+ -+ if(!inode || !itopd(inode)) { -+ printk(KERN_CRIT "mini_fo: meta_check_r_dentry: \ -+ invalid inode passed.\n"); -+ return NULL; -+ } -+ inode_info = itopd(inode); -+ -+ if(inode_info->renamed_list_size <= 0) -+ return NULL; -+ -+ list_for_each(tmp, &inode_info->renamed_list) { -+ ren_entry = list_entry(tmp, struct renamed_entry, list); -+ if(ren_entry->new_len != len) -+ continue; -+ -+ if(!strncmp(ren_entry->new_name, name, len)) { -+ old_path = (char *) -+ kmalloc(ren_entry->old_len+1, GFP_KERNEL); -+ strncpy(old_path, -+ ren_entry->old_name, -+ ren_entry->old_len); -+ old_path[ren_entry->old_len]='\0'; -+ return old_path; -+ } -+ } -+ return NULL; -+} -+ -+/* -+ * This version only checks if entry exists and return: -+ * 1 if exists, -+ * 0 if not, -+ * -1 if error. -+ */ -+int meta_is_r_entry(dentry_t *dentry, const char *name, int len) -+{ -+ if(!dentry || !dentry->d_inode) { -+ printk(KERN_CRIT "mini_fo: meta_check_r_dentry [2]: \ -+ invalid dentry passed.\n"); -+ return -1; -+ } -+ return __meta_is_r_entry(dentry->d_inode, name, len); -+} -+ -+int __meta_is_r_entry(inode_t *inode, const char *name, int len) -+{ -+ struct list_head *tmp; -+ struct renamed_entry *ren_entry; -+ struct mini_fo_inode_info *inode_info; -+ -+ if(!inode || !itopd(inode)) { -+ printk(KERN_CRIT "mini_fo: meta_check_r_dentry [2]: \ -+ invalid inode passed.\n"); -+ return -1; -+ } -+ inode_info = itopd(inode); -+ -+ if(inode_info->renamed_list_size <= 0) -+ return -1; -+ -+ list_for_each(tmp, &inode_info->renamed_list) { -+ ren_entry = list_entry(tmp, struct renamed_entry, list); -+ if(ren_entry->new_len != len) -+ continue; -+ -+ if(!strncmp(ren_entry->new_name, name, len)) -+ return 1; -+ } -+ return 0; -+} -+ ---- /dev/null -+++ b/fs/mini_fo/mini_fo.h -@@ -0,0 +1,510 @@ -+/* -+ * Copyright (c) 1997-2003 Erez Zadok -+ * Copyright (c) 2001-2003 Stony Brook University -+ * -+ * For specific licensing information, see the COPYING file distributed with -+ * this package, or get one from ftp://ftp.filesystems.org/pub/fist/COPYING. -+ * -+ * This Copyright notice must be kept intact and distributed with all -+ * fistgen sources INCLUDING sources generated by fistgen. -+ */ -+/* -+ * Copyright (C) 2004, 2005 Markus Klotzbuecher -+ * -+ * 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. -+ */ -+ -+/* -+ * $Id$ -+ */ -+ -+#ifndef __MINI_FO_H_ -+#define __MINI_FO_H_ -+ -+#ifdef __KERNEL__ -+ -+/* META stuff */ -+#define META_FILENAME "META_dAfFgHE39ktF3HD2sr" -+ -+/* use xattrs? */ -+#define XATTR -+ -+/* File attributes that when changed, result in a file beeing copied to storage */ -+#define COPY_FLAGS ATTR_MODE | ATTR_UID | ATTR_GID | ATTR_SIZE -+ -+/* -+ * mini_fo filestates -+ */ -+#define MODIFIED 1 -+#define UNMODIFIED 2 -+#define CREATED 3 -+#define DEL_REWRITTEN 4 -+#define DELETED 5 -+#define NON_EXISTANT 6 -+ -+/* fist file systems superblock magic */ -+# define MINI_FO_SUPER_MAGIC 0xf15f -+ -+/* -+ * STRUCTURES: -+ */ -+ -+/* mini_fo inode data in memory */ -+struct mini_fo_inode_info { -+ inode_t *wii_inode; -+ inode_t *wii_inode2; /* pointer to storage inode */ -+ -+ /* META-data lists */ -+ /* deleted list, ex wol */ -+ struct list_head deleted_list; -+ int deleted_list_size; -+ -+ /* renamed list */ -+ struct list_head renamed_list; -+ int renamed_list_size; -+ -+ /* add other lists here ... */ -+}; -+ -+/* mini_fo dentry data in memory */ -+struct mini_fo_dentry_info { -+ dentry_t *wdi_dentry; -+ dentry_t *wdi_dentry2; /* pointer to storage dentry */ -+ unsigned int state; /* state of the mini_fo dentry */ -+}; -+ -+ -+/* mini_fo super-block data in memory */ -+struct mini_fo_sb_info { -+ super_block_t *wsi_sb, *wsi_sb2; /* mk: might point to the same sb */ -+ struct vfsmount *hidden_mnt, *hidden_mnt2; -+ dentry_t *base_dir_dentry; -+ dentry_t *storage_dir_dentry; -+ ; -+}; -+ -+/* readdir_data, readdir helper struct */ -+struct readdir_data { -+ struct list_head ndl_list; /* linked list head ptr */ -+ int ndl_size; /* list size */ -+ int sto_done; /* flag to show that the storage dir entries have -+ * all been read an now follow base entries */ -+}; -+ -+/* file private data. */ -+struct mini_fo_file_info { -+ struct file *wfi_file; -+ struct file *wfi_file2; /* pointer to storage file */ -+ struct readdir_data rd; -+}; -+ -+/* struct ndl_entry */ -+struct ndl_entry { -+ struct list_head list; -+ char *name; -+ int len; -+}; -+ -+/******************************** -+ * META-data structures -+ ********************************/ -+ -+/* deleted entry */ -+struct deleted_entry { -+ struct list_head list; -+ char *name; -+ int len; -+}; -+ -+/* renamed entry */ -+struct renamed_entry { -+ struct list_head list; -+ char *old_name; /* old directory with full path */ -+ int old_len; /* length of above string */ -+ char *new_name; /* new directory name */ -+ int new_len; /* length of above string */ -+}; -+ -+/* attr_change entry */ -+struct attr_change_entry { -+ struct list_head list; -+ char *name; -+ int len; -+}; -+ -+/* link entry */ -+struct link_entry { -+ struct list_head list; -+ int links_moved; -+ int inum_base; -+ int inum_sto; -+ char *weird_name; -+ int weird_name_len; -+}; -+ -+ -+/* Some other stuff required for mini_fo_filldir64, copied from -+ * fs/readdir.c -+ */ -+ -+#define ROUND_UP64(x) (((x)+sizeof(u64)-1) & ~(sizeof(u64)-1)) -+#define NAME_OFFSET(de) ((int) ((de)->d_name - (char *) (de))) -+ -+ -+struct linux_dirent64 { -+ u64 d_ino; -+ s64 d_off; -+ unsigned short d_reclen; -+ unsigned char d_type; -+ char d_name[0]; -+}; -+ -+ -+struct getdents_callback64 { -+ struct linux_dirent64 * current_dir; -+ struct linux_dirent64 * previous; -+ int count; -+ int error; -+}; -+ -+struct linux_dirent { -+ unsigned long d_ino; -+ unsigned long d_off; -+ unsigned short d_reclen; -+ char d_name[1]; -+}; -+ -+struct getdents_callback { -+ struct linux_dirent * current_dir; -+ struct linux_dirent * previous; -+ int count; -+ int error; -+}; -+ -+ -+/* -+ * MACROS: -+ */ -+ -+/* file TO private_data */ -+# define ftopd(file) ((struct mini_fo_file_info *)((file)->private_data)) -+# define __ftopd(file) ((file)->private_data) -+/* file TO hidden_file */ -+# define ftohf(file) ((ftopd(file))->wfi_file) -+# define ftohf2(file) ((ftopd(file))->wfi_file2) -+ -+/* inode TO private_data */ -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,18) -+# define itopd(ino) ((struct mini_fo_inode_info *)(ino)->i_private) -+# define __itopd(ino) ((ino)->i_private) -+#else -+# define itopd(ino) ((struct mini_fo_inode_info *)(ino)->u.generic_ip) -+# define __itopd(ino) ((ino)->u.generic_ip) -+#endif -+/* inode TO hidden_inode */ -+# define itohi(ino) (itopd(ino)->wii_inode) -+# define itohi2(ino) (itopd(ino)->wii_inode2) -+ -+/* superblock TO private_data */ -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) -+# define stopd(super) ((struct mini_fo_sb_info *)(super)->s_fs_info) -+# define __stopd(super) ((super)->s_fs_info) -+#else -+# define stopd(super) ((struct mini_fo_sb_info *)(super)->u.generic_sbp) -+# define __stopd(super) ((super)->u.generic_sbp) -+#endif -+ -+/* unused? # define vfs2priv stopd */ -+/* superblock TO hidden_superblock */ -+ -+# define stohs(super) (stopd(super)->wsi_sb) -+# define stohs2(super) (stopd(super)->wsi_sb2) -+ -+/* dentry TO private_data */ -+# define dtopd(dentry) ((struct mini_fo_dentry_info *)(dentry)->d_fsdata) -+# define __dtopd(dentry) ((dentry)->d_fsdata) -+/* dentry TO hidden_dentry */ -+# define dtohd(dent) (dtopd(dent)->wdi_dentry) -+# define dtohd2(dent) (dtopd(dent)->wdi_dentry2) -+ -+/* dentry to state */ -+# define dtost(dent) (dtopd(dent)->state) -+# define sbt(sb) ((sb)->s_type->name) -+ -+#define IS_WRITE_FLAG(flag) (flag & (O_RDWR | O_WRONLY | O_APPEND)) -+#define IS_COPY_FLAG(flag) (flag & (COPY_FLAGS)) -+ -+/* macros to simplify non-SCA code */ -+# define MALLOC_PAGE_POINTERS(hidden_pages, num_hidden_pages) -+# define MALLOC_PAGEDATA_POINTERS(hidden_pages_data, num_hidden_pages) -+# define FREE_PAGE_POINTERS(hidden_pages, num) -+# define FREE_PAGEDATA_POINTERS(hidden_pages_data, num) -+# define FOR_EACH_PAGE -+# define CURRENT_HIDDEN_PAGE hidden_page -+# define CURRENT_HIDDEN_PAGEDATA hidden_page_data -+# define CURRENT_HIDDEN_PAGEINDEX page->index -+ -+/* -+ * EXTERNALS: -+ */ -+extern struct file_operations mini_fo_main_fops; -+extern struct file_operations mini_fo_dir_fops; -+extern struct inode_operations mini_fo_main_iops; -+extern struct inode_operations mini_fo_dir_iops; -+extern struct inode_operations mini_fo_symlink_iops; -+extern struct super_operations mini_fo_sops; -+extern struct dentry_operations mini_fo_dops; -+extern struct vm_operations_struct mini_fo_shared_vmops; -+extern struct vm_operations_struct mini_fo_private_vmops; -+extern struct address_space_operations mini_fo_aops; -+ -+#if 0 /* unused by mini_fo */ -+extern int mini_fo_interpose(dentry_t *hidden_dentry, dentry_t *this_dentry, super_block_t *sb, int flag); -+#if defined(FIST_FILTER_DATA) || defined(FIST_FILTER_SCA) -+extern page_t *mini_fo_get1page(file_t *file, int index); -+extern int mini_fo_fill_zeros(file_t *file, page_t *page, unsigned from); -+# endif /* FIST_FILTER_DATA || FIST_FILTER_SCA */ -+ -+ -+# define mini_fo_hidden_dentry(d) __mini_fo_hidden_dentry(__FILE__,__FUNCTION__,__LINE__,(d)) -+# define mini_fo_hidden_sto_dentry(d) __mini_fo_hidden_sto_dentry(__FILE__,__FUNCTION__,__LINE__,(d)) -+ -+extern dentry_t *__mini_fo_hidden_dentry(char *file, char *func, int line, dentry_t *this_dentry); -+extern dentry_t *__mini_fo_hidden_sto_dentry(char *file, char *func, int line, dentry_t *this_dentry); -+ -+extern int mini_fo_read_file(const char *filename, void *buf, int len); -+extern int mini_fo_write_file(const char *filename, void *buf, int len); -+extern dentry_t *fist_lookup(dentry_t *dir, const char *name, vnode_t **out, uid_t uid, gid_t gid); -+#endif /* unused by mini_fo */ -+ -+/* state transition functions */ -+extern int nondir_unmod_to_mod(dentry_t *dentry, int cp_flag); -+extern int nondir_del_rew_to_del(dentry_t *dentry); -+extern int nondir_creat_to_del(dentry_t *dentry); -+extern int nondir_mod_to_del(dentry_t *dentry); -+extern int nondir_unmod_to_del(dentry_t *dentry); -+ -+extern int dir_unmod_to_mod(dentry_t *dentry); -+ -+/* rename specials */ -+extern int rename_directory(inode_t *old_dir, dentry_t *old_dentry, inode_t *new_dir, dentry_t *new_dentry); -+extern int rename_nondir(inode_t *old_dir, dentry_t *old_dentry, inode_t *new_dir, dentry_t *new_dentry); -+ -+/* misc stuff */ -+extern int mini_fo_tri_interpose(dentry_t *hidden_dentry, -+ dentry_t *hidden_sto_dentry, -+ dentry_t *dentry, -+ super_block_t *sb, int flag); -+ -+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,0) -+extern int mini_fo_create(inode_t *dir, dentry_t *dentry, int mode, struct nameidata *nd); -+ -+extern int create_sto_nod(dentry_t *dentry, int mode, dev_t dev); -+extern int create_sto_reg_file(dentry_t *dentry, int mode, struct nameidata *nd); -+#else -+extern int mini_fo_create(inode_t *dir, dentry_t *dentry, int mode); -+ -+extern int create_sto_nod(dentry_t *dentry, int mode, int dev); -+extern int create_sto_reg_file(dentry_t *dentry, int mode); -+#endif -+ -+extern int create_sto_dir(dentry_t *dentry, int mode); -+ -+extern int exists_in_storage(dentry_t *dentry); -+extern int is_mini_fo_existant(dentry_t *dentry); -+extern int get_neg_sto_dentry(dentry_t *dentry); -+extern int build_sto_structure(dentry_t *dir, dentry_t *dentry); -+extern int get_mini_fo_bpath(dentry_t *dentry, char **bpath, int *bpath_len); -+extern dentry_t *bpath_walk(super_block_t *sb, char *bpath); -+extern int bpath_put(dentry_t *dentry); -+ -+/* check_mini_fo types functions */ -+extern int check_mini_fo_dentry(dentry_t *dentry); -+extern int check_mini_fo_file(file_t *file); -+extern int check_mini_fo_inode(inode_t *inode); -+ -+/* General meta functions, can be called from outside of meta.c */ -+extern int meta_build_lists(dentry_t *dentry); -+extern int meta_put_lists(dentry_t *dentry); -+extern int __meta_put_lists(inode_t *inode); -+ -+extern int meta_add_d_entry(dentry_t *dentry, const char *name, int len); -+extern int meta_add_r_entry(dentry_t *dentry, -+ const char *old_name, int old_len, -+ const char *new_name, int new_len); -+ -+extern int meta_remove_r_entry(dentry_t *dentry, const char *name, int len); -+ -+extern int meta_check_d_entry(dentry_t *dentry, const char *name, int len); -+extern int __meta_check_d_entry(inode_t *inode, const char *name, int len); -+ -+extern char* meta_check_r_entry(dentry_t *dentry, const char *name, int len); -+extern char* __meta_check_r_entry(inode_t *inode, const char *name, int len); -+extern int meta_is_r_entry(dentry_t *dentry, const char *name, int len); -+extern int __meta_is_r_entry(inode_t *inode, const char *name, int len); -+ -+/* Specific meta functions, should be called only inside meta.c */ -+extern int __meta_put_d_list(inode_t *inode); -+extern int __meta_put_r_list(inode_t *inode); -+ -+extern int meta_list_add_d_entry(dentry_t *dentry, -+ const char *name, int len); -+extern int meta_list_add_r_entry(dentry_t *dentry, -+ const char *old_name, int old_len, -+ const char *new_name, int new_len); -+ -+extern int meta_list_remove_r_entry(dentry_t *dentry, -+ const char *name, int len); -+ -+extern int __meta_list_remove_r_entry(inode_t *inode, -+ const char *name, int len); -+ -+extern int meta_write_d_entry(dentry_t *dentry, const char *name, int len); -+extern int meta_write_r_entry(dentry_t *dentry, -+ const char *old_name, int old_len, -+ const char *new_name, int new_len); -+ -+extern int meta_sync_lists(dentry_t *dentry); -+extern int meta_sync_d_list(dentry_t *dentry, int app_flag); -+extern int meta_sync_r_list(dentry_t *dentry, int app_flag); -+ -+/* ndl stuff */ -+extern int ndl_add_entry(struct readdir_data *rd, const char *name, int len); -+extern void ndl_put_list(struct readdir_data *rd); -+extern int ndl_check_entry(struct readdir_data *rd, -+ const char *name, int len); -+ -+ -+# define copy_inode_size(dst, src) \ -+ dst->i_size = src->i_size; \ -+ dst->i_blocks = src->i_blocks; -+ -+static inline void -+fist_copy_attr_atime(inode_t *dest, const inode_t *src) -+{ -+ ASSERT(dest != NULL); -+ ASSERT(src != NULL); -+ dest->i_atime = src->i_atime; -+} -+static inline void -+fist_copy_attr_times(inode_t *dest, const inode_t *src) -+{ -+ ASSERT(dest != NULL); -+ ASSERT(src != NULL); -+ dest->i_atime = src->i_atime; -+ dest->i_mtime = src->i_mtime; -+ dest->i_ctime = src->i_ctime; -+} -+static inline void -+fist_copy_attr_timesizes(inode_t *dest, const inode_t *src) -+{ -+ ASSERT(dest != NULL); -+ ASSERT(src != NULL); -+ dest->i_atime = src->i_atime; -+ dest->i_mtime = src->i_mtime; -+ dest->i_ctime = src->i_ctime; -+ copy_inode_size(dest, src); -+} -+static inline void -+fist_copy_attr_all(inode_t *dest, const inode_t *src) -+{ -+ ASSERT(dest != NULL); -+ ASSERT(src != NULL); -+ dest->i_mode = src->i_mode; -+ dest->i_nlink = src->i_nlink; -+ dest->i_uid = src->i_uid; -+ dest->i_gid = src->i_gid; -+ dest->i_rdev = src->i_rdev; -+ dest->i_atime = src->i_atime; -+ dest->i_mtime = src->i_mtime; -+ dest->i_ctime = src->i_ctime; -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19) -+ dest->i_blksize = src->i_blksize; -+#endif -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,12) -+ dest->i_blkbits = src->i_blkbits; -+# endif /* linux 2.4.12 and newer */ -+ copy_inode_size(dest, src); -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) -+ dest->i_attr_flags = src->i_attr_flags; -+#else -+ dest->i_flags = src->i_flags; -+#endif -+} -+ -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) -+/* copied from linux/fs.h */ -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16) -+static inline void double_lock(struct dentry *d1, struct dentry *d2) -+{ -+ struct mutex *m1 = &d1->d_inode->i_mutex; -+ struct mutex *m2 = &d2->d_inode->i_mutex; -+ if (m1 != m2) { -+ if ((unsigned long) m1 < (unsigned long) m2) { -+ struct mutex *tmp = m2; -+ m2 = m1; m1 = tmp; -+ } -+ mutex_lock(m1); -+ } -+ mutex_lock(m2); -+} -+ -+static inline void double_unlock(struct dentry *d1, struct dentry *d2) -+{ -+ struct mutex *m1 = &d1->d_inode->i_mutex; -+ struct mutex *m2 = &d2->d_inode->i_mutex; -+ mutex_unlock(m1); -+ if (m1 != m2) -+ mutex_unlock(m2); -+ dput(d1); -+ dput(d2); -+} -+ -+#else -+static inline void double_down(struct semaphore *s1, struct semaphore *s2) -+{ -+ if (s1 != s2) { -+ if ((unsigned long) s1 < (unsigned long) s2) { -+ struct semaphore *tmp = s2; -+ s2 = s1; s1 = tmp; -+ } -+ down(s1); -+ } -+ down(s2); -+} -+ -+static inline void double_up(struct semaphore *s1, struct semaphore *s2) -+{ -+ up(s1); -+ if (s1 != s2) -+ up(s2); -+} -+ -+static inline void double_lock(struct dentry *d1, struct dentry *d2) -+{ -+ double_down(&d1->d_inode->i_sem, &d2->d_inode->i_sem); -+} -+ -+static inline void double_unlock(struct dentry *d1, struct dentry *d2) -+{ -+ double_up(&d1->d_inode->i_sem,&d2->d_inode->i_sem); -+ dput(d1); -+ dput(d2); -+} -+#endif /* if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16) */ -+#endif /* if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) */ -+#endif /* __KERNEL__ */ -+ -+/* -+ * Definitions for user and kernel code -+ */ -+ -+/* ioctls */ -+ -+#endif /* not __MINI_FO_H_ */ ---- /dev/null -+++ b/fs/mini_fo/mini_fo-merge -@@ -0,0 +1,180 @@ -+#!/bin/bash -+# -+# Copyright (C) 2005 Markus Klotzbuecher -+# 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. -+# -+ -+BASE= -+STO= -+HELP= -+DRYRUN= -+VERBOSE= -+TMP="/tmp/" -+META_NAME="META_dAfFgHE39ktF3HD2sr" -+SKIP_DEL_LIST="skip-delete-list.mini_fo-merge" -+ -+COMMAND= -+exec_command() -+{ -+ if [ x$DRYRUN == "xset" ]; then -+ echo " would run: $COMMAND" -+ elif ! [ x$DRYRUN == "xset" ]; then -+ if [ x$VERBOSE == "xset" ]; then -+ echo " running: $COMMAND" -+ fi -+ eval $COMMAND -+ fi -+} -+ -+usage() -+{ -+cat < -s -+Version 0.1 -+ -+This script merges the contents of a mini_fo storage file system back -+to the base file system. -+ -+!!! Warning: This will modify the base filesystem and can destroy data -+ if used wrongly. -+ -+Options: -+ -b -+ the directory of the base file system. -+ -+ -s -+ the directory of the storage file system. -+ -+ -d dry run, will not change anything and print the commands that -+ would be executed. -+ -+ -t tmp dir for storing temporary file. default: $TMP -+ -+ -v show what operations are performed. -+ -+ -h displays this message. -+ -+EOF -+} -+ -+# parse parameters -+while getopts hdvt:b:s: OPTS -+ do -+ case $OPTS in -+ h) HELP="set";; -+ d) DRYRUN="set";; -+ v) VERBOSE="set";; -+ b) BASE="$OPTARG";; -+ s) STO="$OPTARG";; -+ t) TMP="$OPTARG";; -+ ?) usage -+ exit 1;; -+ esac -+done -+ -+if [ "x$HELP" == "xset" ]; then -+ usage -+ exit -1 -+fi -+ -+if ! [ -d "$BASE" ] || ! [ -d "$STO" ]; then -+ echo -e "$0:\n Error, -s and/or -b argument missing. type $0 -h for help." -+ exit -1; -+fi -+ -+# get full paths -+pushd $STO; STO=`pwd`; popd -+pushd $BASE; BASE=`pwd`; popd -+TMP=${TMP%/} -+ -+ -+cat< /dev/null -+find . -name $META_NAME -type f -print0 | xargs -0 -e grep -e '^R ' | tr -s ':R' ' ' | while read ENTRY; do -+ echo "entry: $ENTRY" -+ META_FILE=`echo $ENTRY | cut -d ' ' -f 1` -+ OLD_B_DIR=`echo $ENTRY | cut -d ' ' -f 2 | sed -e 's/\///'` -+ NEW_NAME=`echo $ENTRY | cut -d ' ' -f 3` -+ NEW_B_DIR=`echo $META_FILE | sed -e "s/$META_NAME/$NEW_NAME/" | sed -e 's/^\.\///'` -+ echo "META_FILE: $META_FILE" -+ echo "OLD_B_DIR: $OLD_B_DIR" -+ echo "NEW_NAME: $NEW_NAME" -+ echo "NEW_B_DIR: $NEW_B_DIR" -+ -+ pushd $BASE &> /dev/null -+ # remove an existing dir in storage -+ COMMAND="rm -rf $NEW_B_DIR"; exec_command -+ COMMAND="cp -R $OLD_B_DIR $NEW_B_DIR"; exec_command -+ echo "" -+ popd &> /dev/null -+ -+ # remember this dir to exclude it from deleting later -+ echo $NEW_B_DIR >> $TMP/$SKIP_DEL_LIST -+done -+ -+# delete all whiteouted files from base -+echo -e "\nDeleting whiteout'ed files from base file system..." -+find . -name $META_NAME -type f -print0 | xargs -0 -e grep -e '^D ' | sed -e 's/:D//' | while read ENTRY; do -+ META_FILE=`echo $ENTRY | cut -d ' ' -f 1` -+ DEL_NAME=`echo $ENTRY | cut -d ' ' -f 2` -+ DEL_FILE=`echo $META_FILE | sed -e "s/$META_NAME/$DEL_NAME/" | sed -e 's/^\.\///'` -+ grep -x $DEL_FILE $TMP/$SKIP_DEL_LIST &> /dev/null -+ if [ $? -ne 0 ]; then -+ pushd $BASE &> /dev/null -+ COMMAND="rm -rf $DEL_FILE"; exec_command -+ popd &> /dev/null -+ else -+ echo " excluding: $DEL_FILE as in skip-del-list." -+ fi -+done -+ -+# create all dirs and update permissions -+echo -e "\nSetting up directory structures in base file system..." -+find . -type d | sed -e 's/^\.\///' | while read DIR; do -+ PERMS=`stat -c %a $DIR` -+ DIR_UID=`stat -c %u $DIR` -+ DIR_GID=`stat -c %g $DIR` -+ pushd $BASE &> /dev/null -+ if ! [ -d $DIR ]; then -+ COMMAND="mkdir -p $DIR"; exec_command -+ fi -+ COMMAND="chmod $PERMS $DIR"; exec_command -+ COMMAND="chown $DIR_UID:$DIR_GID $DIR"; exec_command -+ popd &> /dev/null -+done -+ -+# merge all non-directory files -+echo -e "\nMerging all non-directory files...." -+for i in b c p f l s; do -+ find . -type $i | sed -e 's/^\.\///' | grep -v "$META_NAME" | while read FILE; do -+ pushd $BASE #&> /dev/null -+ COMMAND="cp -df $STO/$FILE $BASE/$FILE"; exec_command -+ popd &> /dev/null -+ done -+done -+popd &> /dev/null -+ -+#rm $TMP/$SKIP_DEL_LIST -+ -+echo "Done!" ---- /dev/null -+++ b/fs/mini_fo/mini_fo-overlay -@@ -0,0 +1,130 @@ -+#!/bin/bash -+# -+# Copyright (C) 2005 Markus Klotzbuecher -+# 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. -+# -+ -+HELP= -+SUFF= -+MNTP= -+MNT_DIR="/mnt" -+STO= -+STO_DIR="/tmp" -+BASE= -+ -+usage() -+{ -+cat <" in $STO_DIR, -+and mount point "mini_fo-" in $MNT_DIR. -+ -+Options: -+ -s -+ add given suffix to storage directory and the mount -+ point. This is usefull for overlaying one base directory -+ several times and avoiding conflicts with storage directory -+ names and mount points. -+ -+ -d -+ change the directory in which the storage directory will be -+ created (default is currently "$STO_DIR". -+ -+ -m -+ use an alternative directory to create the mini_fo -+ mountpoint (default is currently "$MNT_DIR". -+ -+ -h displays this message. -+ -+EOF -+exit 1; -+} -+ -+while getopts hm:s:d: OPTS -+ do -+ case $OPTS in -+ s) SUFF="$OPTARG";; -+ d) STO_DIR="$OPTARG";; -+ m) MNT_DIR="$OPTARG";; -+ h) HELP="set";; -+ ?) usage -+ exit 1;; -+ esac -+done -+shift $(($OPTIND - 1)) -+ -+BASE="$1" -+ -+if [ "x$HELP" == "xset" ]; then -+ usage -+ exit -1 -+fi -+ -+# fix suffix -+if [ "x$SUFF" != "x" ]; then -+ SUFF="-$SUFF" -+fi -+ -+# kill trailing slashes -+MNT_DIR=${MNT_DIR%/} -+STO_DIR=${STO_DIR%/} -+BASE=${BASE%/} -+ -+ -+if ! [ -d "$BASE" ]; then -+ echo "invalid base dir $BASE, run $0 -h for help." -+ exit -1 -+fi -+ -+# check opts -+if ! [ -d "$MNT_DIR" ]; then -+ echo "invalid mount dir $MNT_DIR, run $0 -h for help." -+ exit -1 -+fi -+ -+if ! [ -d "$STO_DIR" ]; then -+ echo "invalid sto_dir_dir $STO_DIR, run $0 -h for help." -+ exit -1 -+fi -+ -+MNTP="$MNT_DIR/mini_fo-`basename $BASE`$SUFF" -+STO="$STO_DIR/sto-`basename $BASE`$SUFF" -+ -+# create the mount point if it doesn't exist -+mkdir -p $MNTP -+if [ $? -ne 0 ]; then -+ echo "Error, failed to create mount point $MNTP" -+fi -+ -+mkdir -p $STO -+if [ $? -ne 0 ]; then -+ echo "Error, failed to create storage dir $STO" -+fi -+ -+# check if fs is already mounted -+mount | grep mini_fo | grep $MNTP &> /dev/null -+if [ $? -eq 0 ]; then -+ echo "Error, existing mini_fo mount at $MNTP." -+ exit -1 -+fi -+ -+mount | grep mini_fo | grep $STO &> /dev/null -+if [ $? -eq 0 ]; then -+ echo "Error, $STO seems to be used already." -+ exit -1 -+fi -+ -+# mount -+mount -t mini_fo -o base=$BASE,sto=$STO $BASE $MNTP -+ -+if [ $? -ne 0 ]; then -+ echo "Error, mounting failed, maybe no permisson to mount?" -+fi ---- /dev/null -+++ b/fs/mini_fo/mmap.c -@@ -0,0 +1,637 @@ -+/* -+ * Copyright (c) 1997-2003 Erez Zadok -+ * Copyright (c) 2001-2003 Stony Brook University -+ * -+ * For specific licensing information, see the COPYING file distributed with -+ * this package, or get one from ftp://ftp.filesystems.org/pub/fist/COPYING. -+ * -+ * This Copyright notice must be kept intact and distributed with all -+ * fistgen sources INCLUDING sources generated by fistgen. -+ */ -+/* -+ * Copyright (C) 2004, 2005 Markus Klotzbuecher -+ * -+ * 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. -+ */ -+ -+/* -+ * $Id$ -+ */ -+ -+#ifdef HAVE_CONFIG_H -+# include -+#endif /* HAVE_CONFIG_H */ -+ -+#include "fist.h" -+#include "mini_fo.h" -+ -+ -+#ifdef FIST_COUNT_WRITES -+/* for counting writes in the middle vs. regular writes */ -+unsigned long count_writes = 0, count_writes_middle = 0; -+#endif /* FIST_COUNT_WRITES */ -+ -+/* forward declaration of commit write and prepare write */ -+STATIC int mini_fo_commit_write(file_t *file, page_t *page, unsigned from, unsigned to); -+STATIC int mini_fo_prepare_write(file_t *file, page_t *page, unsigned from, unsigned to); -+ -+ -+/* -+ * Function for handling creation of holes when lseek-ing past the -+ * end of the file and then writing some data. -+ */ -+int -+mini_fo_fill_zeros(file_t* file, page_t *page, unsigned from) -+{ -+ int err = 0; -+ dentry_t *dentry = file->f_dentry; -+ inode_t *inode = dentry->d_inode; -+ page_t *tmp_page; -+ int index; -+ -+ print_entry_location(); -+ -+ for (index = inode->i_size >> PAGE_CACHE_SHIFT; index < page->index; index++) { -+ tmp_page = mini_fo_get1page(file, index); -+ if (IS_ERR(tmp_page)) { -+ err = PTR_ERR(tmp_page); -+ goto out; -+ } -+ -+ /* -+ * zero out rest of the contents of the page between the appropriate -+ * offsets. -+ */ -+ memset((char*)page_address(tmp_page) + (inode->i_size & ~PAGE_CACHE_MASK), 0, PAGE_CACHE_SIZE - (inode->i_size & ~PAGE_CACHE_MASK)); -+ -+ if (! (err = mini_fo_prepare_write(file, tmp_page, 0, PAGE_CACHE_SIZE))) -+ err = mini_fo_commit_write(file, tmp_page, 0, PAGE_CACHE_SIZE); -+ -+ page_cache_release(tmp_page); -+ if (err < 0) -+ goto out; -+ if (current->need_resched) -+ schedule(); -+ } -+ -+ /* zero out appropriate parts of last page */ -+ -+ /* -+ * if the encoding type is block, then adjust the 'from' (where the -+ * zeroing will start) offset appropriately -+ */ -+ from = from & (~(FIST_ENCODING_BLOCKSIZE - 1)); -+ -+ if ((from - (inode->i_size & ~PAGE_CACHE_MASK)) > 0) { -+ -+ memset((char*)page_address(page) + (inode->i_size & ~PAGE_CACHE_MASK), 0, from - (inode->i_size & ~PAGE_CACHE_MASK)); -+ if (! (err = mini_fo_prepare_write(file, page, 0, PAGE_CACHE_SIZE))) -+ err = mini_fo_commit_write(file, page, 0, PAGE_CACHE_SIZE); -+ -+ if (err < 0) -+ goto out; -+ if (current->need_resched) -+ schedule(); -+ } -+ -+ out: -+ print_exit_status(err); -+ return err; -+} -+ -+ -+ -+STATIC int -+mini_fo_writepage(page_t *page) -+{ -+ int err = -EIO; -+ inode_t *inode; -+ inode_t *hidden_inode; -+ page_t *hidden_page; -+ char *kaddr, *hidden_kaddr; -+ -+ print_entry_location(); -+ -+ inode = page->mapping->host; -+ hidden_inode = itohi(inode); -+ -+ /* -+ * writepage is called when shared mmap'ed files need to write -+ * their pages, while prepare/commit_write are called from the -+ * non-paged write() interface. (However, in 2.3 the two interfaces -+ * share the same cache, while in 2.2 they didn't.) -+ * -+ * So we pretty much have to duplicate much of what commit_write does. -+ */ -+ -+ /* find lower page (returns a locked page) */ -+ hidden_page = grab_cache_page(hidden_inode->i_mapping, page->index); -+ if (!hidden_page) -+ goto out; -+ -+ /* get page address, and encode it */ -+ kaddr = (char *) kmap(page); -+ hidden_kaddr = (char*) kmap(hidden_page); -+ mini_fo_encode_block(kaddr, hidden_kaddr, PAGE_CACHE_SIZE, inode, inode->i_sb, page->index); -+ /* if encode_block could fail, then return error */ -+ kunmap(page); -+ kunmap(hidden_page); -+ -+ /* call lower writepage (expects locked page) */ -+ err = hidden_inode->i_mapping->a_ops->writepage(hidden_page); -+ -+ /* -+ * update mtime and ctime of lower level file system -+ * mini_fo' mtime and ctime are updated by generic_file_write -+ */ -+ hidden_inode->i_mtime = hidden_inode->i_ctime = CURRENT_TIME; -+ -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,1) -+ UnlockPage(hidden_page); /* b/c grab_cache_page locked it */ -+# endif /* kernel older than 2.4.1 */ -+ page_cache_release(hidden_page); /* b/c grab_cache_page increased refcnt */ -+ -+ if (err) -+ ClearPageUptodate(page); -+ else -+ SetPageUptodate(page); -+ out: -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,1) -+ UnlockPage(page); -+# endif /* kernel 2.4.1 and newer */ -+ print_exit_status(err); -+ return err; -+} -+ -+ -+/* -+ * get one page from cache or lower f/s, return error otherwise. -+ * returns unlocked, up-to-date page (if ok), with increased refcnt. -+ */ -+page_t * -+mini_fo_get1page(file_t *file, int index) -+{ -+ page_t *page; -+ dentry_t *dentry; -+ inode_t *inode; -+ struct address_space *mapping; -+ int err; -+ -+ print_entry_location(); -+ -+ dentry = file->f_dentry; /* CPW: Moved below print_entry_location */ -+ inode = dentry->d_inode; -+ mapping = inode->i_mapping; -+ -+ fist_dprint(8, "%s: read page index %d pid %d\n", __FUNCTION__, index, current->pid); -+ if (index < 0) { -+ printk("%s BUG: index=%d\n", __FUNCTION__, index); -+ page = ERR_PTR(-EIO); -+ goto out; -+ } -+ page = read_cache_page(mapping, -+ index, -+ (filler_t *) mapping->a_ops->readpage, -+ (void *) file); -+ if (IS_ERR(page)) -+ goto out; -+ wait_on_page(page); -+ if (!Page_Uptodate(page)) { -+ lock_page(page); -+ err = mapping->a_ops->readpage(file, page); -+ if (err) { -+ page = ERR_PTR(err); -+ goto out; -+ } -+ wait_on_page(page); -+ if (!Page_Uptodate(page)) { -+ page = ERR_PTR(-EIO); -+ goto out; -+ } -+ } -+ -+ out: -+ print_exit_pointer(page); -+ return page; -+} -+ -+ -+/* -+ * get one page from cache or lower f/s, return error otherwise. -+ * similar to get1page, but doesn't guarantee that it will return -+ * an unlocked page. -+ */ -+page_t * -+mini_fo_get1page_cached(file_t *file, int index) -+{ -+ page_t *page; -+ dentry_t *dentry; -+ inode_t *inode; -+ struct address_space *mapping; -+ int err; -+ -+ print_entry_location(); -+ -+ dentry = file->f_dentry; /* CPW: Moved below print_entry_location */ -+ inode = dentry->d_inode; -+ mapping = inode->i_mapping; -+ -+ fist_dprint(8, "%s: read page index %d pid %d\n", __FUNCTION__, index, current->pid); -+ if (index < 0) { -+ printk("%s BUG: index=%d\n", __FUNCTION__, index); -+ page = ERR_PTR(-EIO); -+ goto out; -+ } -+ page = read_cache_page(mapping, -+ index, -+ (filler_t *) mapping->a_ops->readpage, -+ (void *) file); -+ if (IS_ERR(page)) -+ goto out; -+ -+ out: -+ print_exit_pointer(page); -+ return page; -+} -+ -+ -+/* -+ * readpage is called from generic_page_read and the fault handler. -+ * If your file system uses generic_page_read for the read op, it -+ * must implement readpage. -+ * -+ * Readpage expects a locked page, and must unlock it. -+ */ -+STATIC int -+mini_fo_do_readpage(file_t *file, page_t *page) -+{ -+ int err = -EIO; -+ dentry_t *dentry; -+ file_t *hidden_file = NULL; -+ dentry_t *hidden_dentry; -+ inode_t *inode; -+ inode_t *hidden_inode; -+ char *page_data; -+ page_t *hidden_page; -+ char *hidden_page_data; -+ int real_size; -+ -+ print_entry_location(); -+ -+ dentry = file->f_dentry; /* CPW: Moved below print_entry_location */ -+ if (ftopd(file) != NULL) -+ hidden_file = ftohf(file); -+ hidden_dentry = dtohd(dentry); -+ inode = dentry->d_inode; -+ hidden_inode = itohi(inode); -+ -+ fist_dprint(7, "%s: requesting page %d from file %s\n", __FUNCTION__, page->index, dentry->d_name.name); -+ -+ MALLOC_PAGE_POINTERS(hidden_pages, num_hidden_pages); -+ MALLOC_PAGEDATA_POINTERS(hidden_pages_data, num_hidden_pages); -+ FOR_EACH_PAGE -+ CURRENT_HIDDEN_PAGE = NULL; -+ -+ /* find lower page (returns a locked page) */ -+ FOR_EACH_PAGE { -+ fist_dprint(8, "%s: Current page index = %d\n", __FUNCTION__, CURRENT_HIDDEN_PAGEINDEX); -+ CURRENT_HIDDEN_PAGE = read_cache_page(hidden_inode->i_mapping, -+ CURRENT_HIDDEN_PAGEINDEX, -+ (filler_t *) hidden_inode->i_mapping->a_ops->readpage, -+ (void *) hidden_file); -+ if (IS_ERR(CURRENT_HIDDEN_PAGE)) { -+ err = PTR_ERR(CURRENT_HIDDEN_PAGE); -+ CURRENT_HIDDEN_PAGE = NULL; -+ goto out_release; -+ } -+ } -+ -+ /* -+ * wait for the page data to show up -+ * (signaled by readpage as unlocking the page) -+ */ -+ FOR_EACH_PAGE { -+ wait_on_page(CURRENT_HIDDEN_PAGE); -+ if (!Page_Uptodate(CURRENT_HIDDEN_PAGE)) { -+ /* -+ * call readpage() again if we returned from wait_on_page with a -+ * page that's not up-to-date; that can happen when a partial -+ * page has a few buffers which are ok, but not the whole -+ * page. -+ */ -+ lock_page(CURRENT_HIDDEN_PAGE); -+ err = hidden_inode->i_mapping->a_ops->readpage(hidden_file, -+ CURRENT_HIDDEN_PAGE); -+ if (err) { -+ CURRENT_HIDDEN_PAGE = NULL; -+ goto out_release; -+ } -+ wait_on_page(CURRENT_HIDDEN_PAGE); -+ if (!Page_Uptodate(CURRENT_HIDDEN_PAGE)) { -+ err = -EIO; -+ goto out_release; -+ } -+ } -+ } -+ -+ /* map pages, get their addresses */ -+ page_data = (char *) kmap(page); -+ FOR_EACH_PAGE -+ CURRENT_HIDDEN_PAGEDATA = (char *) kmap(CURRENT_HIDDEN_PAGE); -+ -+ /* if decode_block could fail, then return error */ -+ err = 0; -+ real_size = hidden_inode->i_size - (page->index << PAGE_CACHE_SHIFT); -+ if (real_size <= 0) -+ memset(page_data, 0, PAGE_CACHE_SIZE); -+ else if (real_size < PAGE_CACHE_SIZE) { -+ mini_fo_decode_block(hidden_page_data, page_data, real_size, inode, inode->i_sb, page->index); -+ memset(page_data + real_size, 0, PAGE_CACHE_SIZE - real_size); -+ } else -+ mini_fo_decode_block(hidden_page_data, page_data, PAGE_CACHE_SIZE, inode, inode->i_sb, page->index); -+ -+ FOR_EACH_PAGE -+ kunmap(CURRENT_HIDDEN_PAGE); -+ kunmap(page); -+ -+ out_release: -+ FOR_EACH_PAGE -+ if (CURRENT_HIDDEN_PAGE) -+ page_cache_release(CURRENT_HIDDEN_PAGE); /* undo read_cache_page */ -+ -+ FREE_PAGE_POINTERS(hidden_pages, num_hidden_pages); -+ FREE_PAGEDATA_POINTERS(hidden_pages_data, num_hidden_pages); -+ -+ out: -+ if (err == 0) -+ SetPageUptodate(page); -+ else -+ ClearPageUptodate(page); -+ -+ print_exit_status(err); -+ return err; -+} -+ -+ -+STATIC int -+mini_fo_readpage(file_t *file, page_t *page) -+{ -+ int err; -+ print_entry_location(); -+ -+ err = mini_fo_do_readpage(file, page); -+ -+ /* -+ * we have to unlock our page, b/c we _might_ have gotten a locked page. -+ * but we no longer have to wakeup on our page here, b/c UnlockPage does -+ * it -+ */ -+ UnlockPage(page); -+ -+ print_exit_status(err); -+ return err; -+} -+ -+ -+STATIC int -+mini_fo_prepare_write(file_t *file, page_t *page, unsigned from, unsigned to) -+{ -+ int err = 0; -+ -+ print_entry_location(); -+ -+ /* -+ * we call kmap(page) only here, and do the kunmap -+ * and the actual downcalls, including unlockpage and uncache -+ * in commit_write. -+ */ -+ kmap(page); -+ -+ /* fast path for whole page writes */ -+ if (from == 0 && to == PAGE_CACHE_SIZE) -+ goto out; -+ /* read the page to "revalidate" our data */ -+ /* call the helper function which doesn't unlock the page */ -+ if (!Page_Uptodate(page)) -+ err = mini_fo_do_readpage(file, page); -+ -+ out: -+ print_exit_status(err); -+ return err; -+} -+ -+ -+ -+STATIC int -+mini_fo_commit_write(file_t *file, page_t *page, unsigned from, unsigned to) -+{ -+ int err = -ENOMEM; -+ inode_t *inode; -+ inode_t *hidden_inode; -+ page_t *hidden_page; -+ file_t *hidden_file = NULL; -+ loff_t pos; -+ unsigned bytes = to - from; -+ unsigned hidden_from, hidden_to, hidden_bytes; -+ -+ print_entry_location(); -+ -+ inode = page->mapping->host; /* CPW: Moved below print_entry_location */ -+ hidden_inode = itohi(inode); -+ -+ ASSERT(file != NULL); -+ /* -+ * here we have a kmapped page, with data from the user copied -+ * into it. we need to encode_block it, and then call the lower -+ * commit_write. We also need to simulate same behavior of -+ * generic_file_write, and call prepare_write on the lower f/s first. -+ */ -+#ifdef FIST_COUNT_WRITES -+ count_writes++; -+# endif /* FIST_COUNT_WRITES */ -+ -+ /* this is append and/or extend -- we can't have holes so fill them in */ -+ if (page->index > (hidden_inode->i_size >> PAGE_CACHE_SHIFT)) { -+ page_t *tmp_page; -+ int index; -+ for (index = hidden_inode->i_size >> PAGE_CACHE_SHIFT; index < page->index; index++) { -+ tmp_page = mini_fo_get1page(file, index); -+ if (IS_ERR(tmp_page)) { -+ err = PTR_ERR(tmp_page); -+ goto out; -+ } -+ /* zero out the contents of the page at the appropriate offsets */ -+ memset((char*)page_address(tmp_page) + (inode->i_size & ~PAGE_CACHE_MASK), 0, PAGE_CACHE_SIZE - (inode->i_size & ~PAGE_CACHE_MASK)); -+ if (!(err = mini_fo_prepare_write(file, tmp_page, 0, PAGE_CACHE_SIZE))) -+ err = mini_fo_commit_write(file, tmp_page, 0, PAGE_CACHE_SIZE); -+ page_cache_release(tmp_page); -+ if (err < 0) -+ goto out; -+ if (current->need_resched) -+ schedule(); -+ } -+ } -+ -+ if (ftopd(file) != NULL) -+ hidden_file = ftohf(file); -+ -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16) -+ mutex_lock(&hidden_inode->i_mutex); -+#else -+ down(&hidden_inode->i_sem); -+#endif -+ /* find lower page (returns a locked page) */ -+ hidden_page = grab_cache_page(hidden_inode->i_mapping, page->index); -+ if (!hidden_page) -+ goto out; -+ -+#if FIST_ENCODING_BLOCKSIZE > 1 -+# error encoding_blocksize greater than 1 is not yet supported -+# endif /* FIST_ENCODING_BLOCKSIZE > 1 */ -+ -+ hidden_from = from & (~(FIST_ENCODING_BLOCKSIZE - 1)); -+ hidden_to = ((to + FIST_ENCODING_BLOCKSIZE - 1) & (~(FIST_ENCODING_BLOCKSIZE - 1))); -+ if ((page->index << PAGE_CACHE_SHIFT) + to > hidden_inode->i_size) { -+ -+ /* -+ * if this call to commit_write had introduced holes and the code -+ * for handling holes was invoked, then the beginning of this page -+ * must be zeroed out -+ * zero out bytes from 'size_of_file%pagesize' to 'from'. -+ */ -+ if ((hidden_from - (inode->i_size & ~PAGE_CACHE_MASK)) > 0) -+ memset((char*)page_address(page) + (inode->i_size & ~PAGE_CACHE_MASK), 0, hidden_from - (inode->i_size & ~PAGE_CACHE_MASK)); -+ -+ } -+ hidden_bytes = hidden_to - hidden_from; -+ -+ /* call lower prepare_write */ -+ err = -EINVAL; -+ if (hidden_inode->i_mapping && -+ hidden_inode->i_mapping->a_ops && -+ hidden_inode->i_mapping->a_ops->prepare_write) -+ err = hidden_inode->i_mapping->a_ops->prepare_write(hidden_file, -+ hidden_page, -+ hidden_from, -+ hidden_to); -+ if (err) -+ /* don't leave locked pages behind, esp. on an ENOSPC */ -+ goto out_unlock; -+ -+ fist_dprint(8, "%s: encoding %d bytes\n", __FUNCTION__, hidden_bytes); -+ mini_fo_encode_block((char *) page_address(page) + hidden_from, (char*) page_address(hidden_page) + hidden_from, hidden_bytes, inode, inode->i_sb, page->index); -+ /* if encode_block could fail, then goto unlock and return error */ -+ -+ /* call lower commit_write */ -+ err = hidden_inode->i_mapping->a_ops->commit_write(hidden_file, -+ hidden_page, -+ hidden_from, -+ hidden_to); -+ -+ if (err < 0) -+ goto out_unlock; -+ -+ err = bytes; /* convert error to no. of bytes */ -+ -+ inode->i_blocks = hidden_inode->i_blocks; -+ /* we may have to update i_size */ -+ pos = (page->index << PAGE_CACHE_SHIFT) + to; -+ if (pos > inode->i_size) -+ inode->i_size = pos; -+ -+ /* -+ * update mtime and ctime of lower level file system -+ * mini_fo' mtime and ctime are updated by generic_file_write -+ */ -+ hidden_inode->i_mtime = hidden_inode->i_ctime = CURRENT_TIME; -+ -+ mark_inode_dirty_sync(inode); -+ -+ out_unlock: -+ UnlockPage(hidden_page); -+ page_cache_release(hidden_page); -+ kunmap(page); /* kmap was done in prepare_write */ -+ out: -+ /* we must set our page as up-to-date */ -+ if (err < 0) -+ ClearPageUptodate(page); -+ else -+ SetPageUptodate(page); -+ -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16) -+ mutex_unlock(&hidden_inode->i_mutex); -+#else -+ up(&hidden_inode->i_sem); -+#endif -+ print_exit_status(err); -+ return err; /* assume all is ok */ -+} -+ -+ -+STATIC int -+mini_fo_bmap(struct address_space *mapping, long block) -+{ -+ int err = 0; -+ inode_t *inode; -+ inode_t *hidden_inode; -+ -+ print_entry_location(); -+ -+ inode = (inode_t *) mapping->host; -+ hidden_inode = itohi(inode); -+ -+ if (hidden_inode->i_mapping->a_ops->bmap) -+ err = hidden_inode->i_mapping->a_ops->bmap(hidden_inode->i_mapping, block); -+ print_exit_location(); -+ return err; -+} -+ -+ -+/* -+ * This function is copied verbatim from mm/filemap.c. -+ * XXX: It should be simply moved to some header file instead -- bug Al about it! -+ */ -+static inline int sync_page(struct page *page) -+{ -+ struct address_space *mapping = page->mapping; -+ -+ if (mapping && mapping->a_ops && mapping->a_ops->sync_page) -+ return mapping->a_ops->sync_page(page); -+ return 0; -+} -+ -+ -+/* -+ * XXX: we may not need this function if not FIST_FILTER_DATA. -+ * FIXME: for FIST_FILTER_SCA, get all lower pages and sync them each. -+ */ -+STATIC int -+mini_fo_sync_page(page_t *page) -+{ -+ int err = 0; -+ inode_t *inode; -+ inode_t *hidden_inode; -+ page_t *hidden_page; -+ -+ print_entry_location(); -+ -+ inode = page->mapping->host; /* CPW: Moved below print_entry_location */ -+ hidden_inode = itohi(inode); -+ -+ /* find lower page (returns a locked page) */ -+ hidden_page = grab_cache_page(hidden_inode->i_mapping, page->index); -+ if (!hidden_page) -+ goto out; -+ -+ err = sync_page(hidden_page); -+ -+ UnlockPage(hidden_page); /* b/c grab_cache_page locked it */ -+ page_cache_release(hidden_page); /* b/c grab_cache_page increased refcnt */ -+ -+ out: -+ print_exit_status(err); -+ return err; -+} ---- /dev/null -+++ b/fs/mini_fo/README -@@ -0,0 +1,163 @@ -+README for the mini_fo overlay file system -+========================================= -+ -+ -+WHAT IS MINI_FO? -+---------------- -+ -+mini_fo is a virtual kernel file system that can make read-only -+file systems writable. This is done by redirecting modifying operations -+to a writeable location called "storage directory", and leaving the -+original data in the "base directory" untouched. When reading, the -+file system merges the modifed and original data so that only the -+newest versions will appear. This occurs transparently to the user, -+who can access the data like on any other read-write file system. -+ -+Base and storage directories may be located on the same or on -+different partitions and may be of different file system types. While -+the storage directory obviously needs to be writable, the base may or -+may not be writable, what doesn't matter as it will no be modified -+anyway. -+ -+ -+WHAT IS GOOD FOR? -+----------------- -+ -+The primary purpose of the mini_fo file system is to allow easy -+software updates to embedded systems, that often store their root -+file system in a read-only flash file system, but there are many -+more as for example sandboxing, or for allowing live-cds to -+permanently store information. -+ -+ -+BUILDING -+-------- -+This should be simple. Adjust the Makefile to point to the correct -+kernel headers you want to build the module for. Then: -+ -+ # make -+ -+should build "mini_fo.o" for a 2.4 kernel or "mini_fo.ko" for a 2.6 -+kernel. -+ -+If you are building the module for you current kernel, you can install -+the module (as root): -+ -+ # make install -+ -+or uninstall with -+ -+ # make uninstall -+ -+ -+USING THE FILE SYSTEM -+-------------------- -+ -+the general mount syntax is: -+ -+ mount -t mini_fo -o base=,sto=\ -+ -+ -+Example: -+ -+You have mounted a cdrom to /mnt/cdrom and want to modifiy some files -+on it: -+ -+load the module (as root) -+ -+ # insmod mini_fo.o for a 2.4 kernel or -+ -+ # insmod mini_fo.ko for a 2.6 kernel -+ -+ -+create a storage dir in tmp and a mountpoint for mini_fo: -+ -+ # mkdir /tmp/sto -+ # mkdir /mnt/mini_fo -+ -+and mount the mini_fo file system: -+ -+ # mount -t mini_fo -o base=/mnt/cdrom,sto=/tmp/sto /mnt/cdrom /mnt/mini_fo -+ -+ -+Now the data stored on the cd can be accessed via the mini_fo -+mountpoint just like any read-write file system, files can be modified -+and deleted, new ones can be created and so on. When done unmount the -+file system: -+ -+ # unmount /mnt/mini_fo -+ -+Note that if the file system is mounted again using the same storage -+file system, of course it will appear in the modified state again. If -+you remount it using an new empty storage directory, it will be -+unmodified. Therefore by executing: -+ -+ # cd /tmp/sto -+ # rm -rf * -+ -+you can nuke all the changes you made to the original file system. But -+ remember NEVER do this while the mini_fo file system is mounted! -+ -+ -+Alternatively you can use the mini_fo-overlay bash script, that -+simplifies managing mini_fo mounts. See TOOLS Section. -+ -+ -+TOOLS -+----- -+ -+mini_fo-merge (experimental): -+ -+This is a bash script that will merge changes contained in the storage -+directory back to the base directory. This allows mini_fo to function -+as a cache file system by overlaying a slow (network, ...) file system -+and using a fast (ramdisk, ...) as storage. When done, changes can be -+merged back to the (slow) base with mini_fo-merge. See "mini_fo-merge -+-h" for details. -+ -+It can be usefull for merging changes back after a successfull test -+(patches, software updates...) -+ -+ -+mini_fo-overlay: -+ -+This bash script simplifies managing one or more mini_fo mounts. For -+overlaying a directory called "basedir1", you can just call: -+ -+ # mini_fo-overlay basedir1 -+ -+This will mount mini_fo with "basedir1" as base, "/tmp/sto-basedir1/" -+as storage to "/mnt/mini_fo-basedir1/". It has more options though, -+type "mini_fo-overlay -h" for details. -+ -+ -+DOCUMENTATION, REPORTING BUGS, GETTING HELP -+------------------------------------------- -+ -+Please visit the mini_fo project page at: -+ -+http://www.denx.de/twiki/bin/view/Know/MiniFOHome -+ -+ -+WARNINGS -+-------- -+ -+Never modify the base or the storage directorys while the mini_fo -+file system is mounted, or you might crash you system. Simply accessing -+and reading should not cause any trouble. -+ -+Exporting a mini_fo mount point via NFS has not been tested, and may -+or may not work. -+ -+Check the RELEASE_NOTES for details on bugs and features. -+ -+ -+ -+Copyright (C) 2004, 2005 Markus Klotzbuecher -+ -+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. -+ -+ ---- /dev/null -+++ b/fs/mini_fo/RELEASE_NOTES -@@ -0,0 +1,111 @@ -+Release: mini_fo-0.6.1 (v0-6-1) -+Date: 21.09.2005 -+ -+ -+Changes: -+-------- -+v0-6-1: -+ -+- bugfixes (see ChangeLog) -+ -+- two helper scripts "mini_fo_merge" and "mini_fo_overlay" (see -+ README for details). -+ -+v0-6-0: -+ -+- Support for 2.4 and 2.6 (see Makefile) -+ -+- Partial hard link support (creating works as expected, but already -+ existing links in the base file system will be treated as if they -+ were individual files). -+ -+- Various bugfixes and cleanups. -+ -+ -+v0-6-0-pre1: -+ -+- This is mini_fo-0-6-0-pre1! This release is a complete rewrite of -+ many vital mini_fo parts such as the old whiteout list code which -+ has been replaced by the new META subsystem. -+ -+- Light weight directory renaming implemented. This means if a -+ directory is renamed via the mini_fo filesystem this will no longer -+ result in a complete copy in storage, instead only one empty -+ directory will be created. All base filed contained in the original -+ directory stay there until modified. -+ -+- Special files (creating, renaming, deleting etc.) now working. -+ -+- Many bugfixes and cleanup, mini_fo is now a lot more stable. -+ -+ -+v0-5-10: -+ -+- Final release of the 0-5-* versions. Next will be a complete rewrite -+ of many features. This release contains several bugfixes related to -+ directory renaming. -+ -+ -+v0-5-10-pre6: -+ -+- Lots of cleanup and several bugfixes related to directory deleting -+ -+- Directory renaming suddenly works, what is most likely due to the -+ fact tha that "mv" is smart: if the classic rename doesn't work it -+ will assume that source and target file are on different fs and will -+ copy the directory and try to remove the source directory. Until -+ directory removing wasn't implemented, it would fail to do this and -+ rollback. -+ So, directory renaming works for now, but it doesn't yet do what you -+ would expect from a overlay fs, so use with care. -+ -+ -+v0-5-10-pre5: -+ -+- implemented directory deleting -+- made parsing of mount options more stable -+- New format of mount options! (See README) -+- I can't reproduce the unknown panic with 2.4.25 anymore, so I'll -+ happily assume it never existed! -+ -+ -+Implemented features: -+--------------------- -+ -+- creating hard links (see BUGS on already existing hard links) -+- lightweight directory renaming -+- renaming device files, pipes, sockets, etc. -+- creating, renaming, deleting of special files -+- deleting directorys -+- general directory reading (simple "ls" ) -+- creating files in existing directorys -+- creating directorys -+- renaming files. -+- reading and writing files (involves opening) -+- appending to files (creates copy in storage) -+- deleting files -+- llseek works too, what allows editors to work -+- persistency (a deleted file stay deleted over remounts) -+- use of symbolic links -+- creating of device files -+ -+ -+Not (yet) implemented features: -+------------------------------- -+ -+- full hard link support. -+ -+ -+ -+BUGS: -+----- -+ -+Hard links in the base file system will be treated as individual -+files, not as links to one inode. -+ -+The main problem with hard links isn't allowing to create them, but -+their pure existence. If you modify a base hard link, the changes made -+will only show up on this link, the other link will remain in the -+original state. I hope to fix this someday. Please note that this does -+not effect the special hard links '.' and '..', that are handled -+seperately by the lower fs. ---- /dev/null -+++ b/fs/mini_fo/state.c -@@ -0,0 +1,620 @@ -+/* -+ * Copyright (C) 2005 Markus Klotzbuecher -+ * -+ * 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. -+ */ -+ -+#ifdef HAVE_CONFIG_H -+# include -+#endif /* HAVE_CONFIG_H */ -+ -+#include "fist.h" -+#include "mini_fo.h" -+ -+ -+/* create the storage file, setup new states */ -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) -+int create_sto_reg_file(dentry_t *dentry, int mode, struct nameidata *nd) -+#else -+int create_sto_reg_file(dentry_t *dentry, int mode) -+#endif -+{ -+ int err = 0; -+ inode_t *dir; -+ dentry_t *hidden_sto_dentry; -+ dentry_t *hidden_sto_dir_dentry; -+ -+ if(exists_in_storage(dentry)) { -+ printk(KERN_CRIT "mini_fo: create_sto_file: wrong type or state.\n"); -+ err = -EINVAL; -+ goto out; -+ } -+ err = get_neg_sto_dentry(dentry); -+ -+ if (err) { -+ printk(KERN_CRIT "mini_fo: create_sto_file: ERROR getting neg. sto dentry.\n"); -+ goto out; -+ } -+ -+ dir = dentry->d_parent->d_inode; -+ hidden_sto_dentry = dtohd2(dentry); -+ -+ /* lock parent */ -+ hidden_sto_dir_dentry = dget(hidden_sto_dentry->d_parent); -+ -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16) -+ mutex_lock(&hidden_sto_dir_dentry->d_inode->i_mutex); -+#else -+ down(&hidden_sto_dir_dentry->d_inode->i_sem); -+#endif -+ -+ err = PTR_ERR(hidden_sto_dir_dentry); -+ if (IS_ERR(hidden_sto_dir_dentry)) -+ goto out; -+ -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) -+ err = vfs_create(hidden_sto_dir_dentry->d_inode, -+ hidden_sto_dentry, -+ mode, nd); -+#else -+ err = vfs_create(hidden_sto_dir_dentry->d_inode, -+ hidden_sto_dentry, -+ mode); -+#endif -+ if(err) { -+ printk(KERN_CRIT "mini_fo: create_sto_file: ERROR creating sto file.\n"); -+ goto out_lock; -+ } -+ -+ if(!dtohd2(dentry)->d_inode) { -+ printk(KERN_CRIT "mini_fo: create_sto_file: ERROR creating sto file [2].\n"); -+ err = -EINVAL; -+ goto out_lock; -+ } -+ -+ /* interpose the new inode */ -+ if(dtost(dentry) == DELETED) { -+ dtost(dentry) = DEL_REWRITTEN; -+ err = mini_fo_tri_interpose(NULL, hidden_sto_dentry, dentry, dir->i_sb, 0); -+ if(err) -+ goto out_lock; -+ } -+ else if(dtost(dentry) == NON_EXISTANT) { -+ dtost(dentry) = CREATED; -+ err = mini_fo_tri_interpose(dtohd(dentry), hidden_sto_dentry, dentry, dir->i_sb, 0); -+ if(err) -+ goto out_lock; -+ } -+ else if(dtost(dentry) == UNMODIFIED) { -+ dtost(dentry) = MODIFIED; -+ /* interpose on new inode */ -+ if(itohi2(dentry->d_inode) != NULL) { -+ printk(KERN_CRIT "mini_fo: create_sto_file: invalid inode detected.\n"); -+ err = -EINVAL; -+ goto out_lock; -+ } -+ itohi2(dentry->d_inode) = igrab(dtohd2(dentry)->d_inode); -+ } -+ fist_copy_attr_timesizes(dentry->d_parent->d_inode, -+ hidden_sto_dir_dentry->d_inode); -+ -+ out_lock: -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16) -+ mutex_unlock(&hidden_sto_dir_dentry->d_inode->i_mutex); -+#else -+ up(&hidden_sto_dir_dentry->d_inode->i_sem); -+#endif -+ dput(hidden_sto_dir_dentry); -+ out: -+ return err; -+} -+ -+/* create the sto dir, setup states */ -+int create_sto_dir(dentry_t *dentry, int mode) -+{ -+ int err = 0; -+ inode_t *dir; -+ dentry_t *hidden_sto_dentry; -+ dentry_t *hidden_sto_dir_dentry; -+ -+ /* had to take the "!S_ISDIR(mode))" check out, because it failed */ -+ if(exists_in_storage(dentry)) { -+ printk(KERN_CRIT "mini_fo: create_sto_dir: wrong type or state.\\ -+n"); -+ err = -EINVAL; -+ goto out; -+ } -+ -+ err = get_neg_sto_dentry(dentry); -+ if(err) { -+ err = -EINVAL; -+ goto out; -+ } -+ -+ dir = dentry->d_parent->d_inode; -+ hidden_sto_dentry = dtohd2(dentry); -+ -+ /* was: hidden_sto_dir_dentry = lock_parent(hidden_sto_dentry); */ -+ hidden_sto_dir_dentry = dget(hidden_sto_dentry->d_parent); -+ -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16) -+ mutex_lock(&hidden_sto_dir_dentry->d_inode->i_mutex); -+#else -+ down(&hidden_sto_dir_dentry->d_inode->i_sem); -+#endif -+ -+ err = PTR_ERR(hidden_sto_dir_dentry); -+ if (IS_ERR(hidden_sto_dir_dentry)) -+ goto out; -+ -+ err = vfs_mkdir(hidden_sto_dir_dentry->d_inode, -+ hidden_sto_dentry, -+ mode); -+ if(err) { -+ printk(KERN_CRIT "mini_fo: create_sto_dir: ERROR creating sto dir.\n"); -+ goto out_lock; -+ } -+ -+ if(!dtohd2(dentry)->d_inode) { -+ printk(KERN_CRIT "mini_fo: create_sto_dir: ERROR creating sto dir [2].\n"); -+ err = -EINVAL; -+ goto out_lock; -+ } -+ -+ /* interpose the new inode */ -+ if(dtost(dentry) == DELETED) { -+ dtost(dentry) = DEL_REWRITTEN; -+ err = mini_fo_tri_interpose(NULL, hidden_sto_dentry, dentry, dir->i_sb, 0); -+ if(err) -+ goto out_lock; -+ } -+ else if(dtopd(dentry)->state == NON_EXISTANT) { -+ dtopd(dentry)->state = CREATED; -+ err = mini_fo_tri_interpose(dtohd(dentry), hidden_sto_dentry, dentry, dir->i_sb, 0); -+ if(err) -+ goto out_lock; -+ } -+ else if(dtopd(dentry)->state == UNMODIFIED) { -+ dtopd(dentry)->state = MODIFIED; -+ /* interpose on new inode */ -+ if(itohi2(dentry->d_inode) != NULL) { -+ printk(KERN_CRIT "mini_fo: create_sto_dir: ERROR, invalid inode detected.\n"); -+ err = -EINVAL; -+ goto out_lock; -+ } -+ itohi2(dentry->d_inode) = igrab(dtohd2(dentry)->d_inode); -+ } -+ -+ fist_copy_attr_timesizes(dir, hidden_sto_dir_dentry->d_inode); -+ -+ /* initalize the wol list */ -+ itopd(dentry->d_inode)->deleted_list_size = -1; -+ itopd(dentry->d_inode)->renamed_list_size = -1; -+ meta_build_lists(dentry); -+ -+ -+ out_lock: -+ /* was: unlock_dir(hidden_sto_dir_dentry); */ -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16) -+ mutex_unlock(&hidden_sto_dir_dentry->d_inode->i_mutex); -+#else -+ up(&hidden_sto_dir_dentry->d_inode->i_sem); -+#endif -+ dput(hidden_sto_dir_dentry); -+ out: -+ return err; -+} -+ -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) -+int create_sto_nod(dentry_t *dentry, int mode, dev_t dev) -+#else -+int create_sto_nod(dentry_t *dentry, int mode, int dev) -+#endif -+{ -+ int err = 0; -+ inode_t *dir; -+ dentry_t *hidden_sto_dentry; -+ dentry_t *hidden_sto_dir_dentry; -+ -+ if(exists_in_storage(dentry)) { -+ err = -EEXIST; -+ goto out; -+ } -+ err = get_neg_sto_dentry(dentry); -+ -+ if (err) { -+ printk(KERN_CRIT "mini_fo: create_sto_nod: ERROR getting neg. sto dentry.\n"); -+ goto out; -+ } -+ -+ dir = dentry->d_parent->d_inode; -+ hidden_sto_dentry = dtohd2(dentry); -+ -+ /* lock parent */ -+ hidden_sto_dir_dentry = dget(hidden_sto_dentry->d_parent); -+ -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16) -+ mutex_lock(&hidden_sto_dir_dentry->d_inode->i_mutex); -+#else -+ down(&hidden_sto_dir_dentry->d_inode->i_sem); -+#endif -+ -+ err = PTR_ERR(hidden_sto_dir_dentry); -+ if (IS_ERR(hidden_sto_dir_dentry)) -+ goto out; -+ -+ err = vfs_mknod(hidden_sto_dir_dentry->d_inode, hidden_sto_dentry, mode, dev); -+ if(err) -+ goto out_lock; -+ -+ if(!dtohd2(dentry)->d_inode) { -+ printk(KERN_CRIT "mini_fo: create_sto_nod: creating storage inode failed [1].\n"); -+ err = -EINVAL; /* return something indicating failure */ -+ goto out_lock; -+ } -+ -+ /* interpose the new inode */ -+ if(dtost(dentry) == DELETED) { -+ dtost(dentry) = DEL_REWRITTEN; -+ err = mini_fo_tri_interpose(NULL, hidden_sto_dentry, dentry, dir->i_sb, 0); -+ if(err) -+ goto out_lock; -+ } -+ else if(dtost(dentry) == NON_EXISTANT) { -+ dtost(dentry) = CREATED; -+ err = mini_fo_tri_interpose(dtohd(dentry), hidden_sto_dentry, dentry, dir->i_sb, 0); -+ if(err) -+ goto out_lock; -+ } -+ else if(dtost(dentry) == UNMODIFIED) { -+ dtost(dentry) = MODIFIED; -+ /* interpose on new inode */ -+ if(itohi2(dentry->d_inode) != NULL) { -+ printk(KERN_CRIT "mini_fo: create_sto_nod: error, invalid inode detected.\n"); -+ err = -EINVAL; -+ goto out_lock; -+ } -+ itohi2(dentry->d_inode) = igrab(dtohd2(dentry)->d_inode); -+ } -+ -+ fist_copy_attr_timesizes(dir, hidden_sto_dir_dentry->d_inode); -+ -+ out_lock: -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16) -+ mutex_unlock(&hidden_sto_dir_dentry->d_inode->i_mutex); -+#else -+ up(&hidden_sto_dir_dentry->d_inode->i_sem); -+#endif -+ dput(hidden_sto_dir_dentry); -+ out: -+ return err; -+} -+ -+ -+/* unimplemented (and possibly not usefull): -+ -+ nondir-del_to_del_rew -+ nondir-non_exist_to_creat -+ -+ dir-unmod_to_del -+ dir-mod_to_del -+ dir-creat_to_del -+ dir-del_rew_to_del -+ dir-del_to_del_rew -+ dir-non_exist_to_creat -+*/ -+ -+ -+/* bring a file of any type from state UNMODIFIED to MODIFIED */ -+int nondir_unmod_to_mod(dentry_t *dentry, int cp_flag) -+{ -+ int err = 0; -+ struct vfsmount *tgt_mnt; -+ struct vfsmount *src_mnt; -+ dentry_t *tgt_dentry; -+ dentry_t *src_dentry; -+ dentry_t *hidden_sto_dentry; -+ dentry_t *hidden_sto_dir_dentry; -+ -+ check_mini_fo_dentry(dentry); -+ -+ if((dtost(dentry) != UNMODIFIED) || -+ S_ISDIR(dentry->d_inode->i_mode)) { -+ printk(KERN_CRIT "mini_fo: nondir_unmod_to_mod: \ -+ wrong type or state.\n"); -+ err = -1; -+ goto out; -+ } -+ err = get_neg_sto_dentry(dentry); -+ -+ if (err) { -+ printk(KERN_CRIT "mini_fo: nondir_unmod_to_mod: \ -+ ERROR getting neg. sto dentry.\n"); -+ goto out; -+ } -+ -+ /* create sto file */ -+ hidden_sto_dentry = dtohd2(dentry); -+ -+ /* lock parent */ -+ hidden_sto_dir_dentry = dget(hidden_sto_dentry->d_parent); -+ -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16) -+ mutex_lock(&hidden_sto_dir_dentry->d_inode->i_mutex); -+#else -+ down(&hidden_sto_dir_dentry->d_inode->i_sem); -+#endif -+ -+ err = PTR_ERR(hidden_sto_dir_dentry); -+ if (IS_ERR(hidden_sto_dir_dentry)) -+ goto out; -+ -+ /* handle different types of nondirs */ -+ if(S_ISCHR(dentry->d_inode->i_mode) || -+ S_ISBLK(dentry->d_inode->i_mode)) { -+ err = vfs_mknod(hidden_sto_dir_dentry->d_inode, -+ hidden_sto_dentry, -+ dtohd(dentry)->d_inode->i_mode, -+ dtohd(dentry)->d_inode->i_rdev); -+ } -+ -+ else if(S_ISREG(dentry->d_inode->i_mode)) { -+ -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) -+ err = vfs_create(hidden_sto_dir_dentry->d_inode, -+ hidden_sto_dentry, -+ dtohd(dentry)->d_inode->i_mode, NULL); -+#else -+ err = vfs_create(hidden_sto_dir_dentry->d_inode, -+ hidden_sto_dentry, -+ dtohd(dentry)->d_inode->i_mode); -+#endif -+ } -+ if(err) { -+ printk(KERN_CRIT "mini_fo: nondir_unmod_to_mod: \ -+ ERROR creating sto file.\n"); -+ goto out_lock; -+ } -+ -+ /* interpose on new inode */ -+ if(itohi2(dentry->d_inode) != NULL) { -+ printk(KERN_CRIT "mini_fo: nondir_unmod_to_mod: \ -+ ERROR, invalid inode detected.\n"); -+ err = -EINVAL; -+ goto out_lock; -+ } -+ -+ itohi2(dentry->d_inode) = igrab(dtohd2(dentry)->d_inode); -+ -+ fist_copy_attr_timesizes(dentry->d_parent->d_inode, -+ hidden_sto_dir_dentry->d_inode); -+ dtost(dentry) = MODIFIED; -+ -+ /* copy contents if regular file and cp_flag = 1 */ -+ if((cp_flag == 1) && S_ISREG(dentry->d_inode->i_mode)) { -+ -+ /* unlock first */ -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16) -+ mutex_unlock(&hidden_sto_dir_dentry->d_inode->i_mutex); -+#else -+ up(&hidden_sto_dir_dentry->d_inode->i_sem); -+#endif -+ -+ dput(hidden_sto_dir_dentry); -+ -+ tgt_dentry = dtohd2(dentry); -+ tgt_mnt = stopd(dentry->d_inode->i_sb)->hidden_mnt2; -+ src_dentry = dtohd(dentry); -+ src_mnt = stopd(dentry->d_inode->i_sb)->hidden_mnt; -+ -+ err = mini_fo_cp_cont(tgt_dentry, tgt_mnt, -+ src_dentry, src_mnt); -+ if(err) { -+ printk(KERN_CRIT "mini_fo: nondir_unmod_to_mod: \ -+ ERROR copying contents.\n"); -+ } -+ goto out; -+ } -+ -+ out_lock: -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16) -+ mutex_unlock(&hidden_sto_dir_dentry->d_inode->i_mutex); -+#else -+ up(&hidden_sto_dir_dentry->d_inode->i_sem); -+#endif -+ dput(hidden_sto_dir_dentry); -+ out: -+ return err; -+} -+ -+/* this function is currently identical to nondir_creat_to_del */ -+int nondir_del_rew_to_del(dentry_t *dentry) -+{ -+ return nondir_creat_to_del(dentry); -+} -+ -+int nondir_creat_to_del(dentry_t *dentry) -+{ -+ int err = 0; -+ -+ inode_t *hidden_sto_dir_inode; -+ dentry_t *hidden_sto_dir_dentry; -+ dentry_t *hidden_sto_dentry; -+ -+ check_mini_fo_dentry(dentry); -+ -+ /* for now this function serves for both state DEL_REWRITTEN and -+ * CREATED */ -+ if(!(dtost(dentry) == CREATED || (dtost(dentry) == DEL_REWRITTEN)) || -+ S_ISDIR(dentry->d_inode->i_mode)) { -+ printk(KERN_CRIT "mini_fo: nondir_mod_to_del/del_rew_to_del: \ -+ wrong type or state.\n"); -+ err = -1; -+ goto out; -+ } -+ -+ hidden_sto_dir_inode = itohi2(dentry->d_parent->d_inode); -+ hidden_sto_dentry = dtohd2(dentry); -+ -+ /* was: hidden_sto_dir_dentry = lock_parent(hidden_sto_dentry);*/ -+ hidden_sto_dir_dentry = dget(hidden_sto_dentry->d_parent); -+ -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16) -+ mutex_lock(&hidden_sto_dir_dentry->d_inode->i_mutex); -+#else -+ down(&hidden_sto_dir_dentry->d_inode->i_sem); -+#endif -+ -+ /* avoid destroying the hidden inode if the file is in use */ -+ dget(hidden_sto_dentry); -+ err = vfs_unlink(hidden_sto_dir_inode, hidden_sto_dentry); -+ dput(hidden_sto_dentry); -+ if(!err) -+ d_delete(hidden_sto_dentry); -+ -+ /* propagate number of hard-links */ -+ dentry->d_inode->i_nlink = itohi2(dentry->d_inode)->i_nlink; -+ -+ dtost(dentry) = NON_EXISTANT; -+ -+ /* was: unlock_dir(hidden_sto_dir_dentry); */ -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16) -+ mutex_unlock(&hidden_sto_dir_dentry->d_inode->i_mutex); -+#else -+ up(&hidden_sto_dir_dentry->d_inode->i_sem); -+#endif -+ dput(hidden_sto_dir_dentry); -+ -+ out: -+ return err; -+} -+ -+int nondir_mod_to_del(dentry_t *dentry) -+{ -+ int err; -+ dentry_t *hidden_sto_dentry; -+ inode_t *hidden_sto_dir_inode; -+ dentry_t *hidden_sto_dir_dentry; -+ -+ check_mini_fo_dentry(dentry); -+ -+ if(dtost(dentry) != MODIFIED || -+ S_ISDIR(dentry->d_inode->i_mode)) { -+ printk(KERN_CRIT "mini_fo: nondir_mod_to_del: \ -+ wrong type or state.\n"); -+ err = -1; -+ goto out; -+ } -+ -+ hidden_sto_dir_inode = itohi2(dentry->d_parent->d_inode); -+ hidden_sto_dentry = dtohd2(dentry); -+ -+ /* was hidden_sto_dir_dentry = lock_parent(hidden_sto_dentry); */ -+ hidden_sto_dir_dentry = dget(hidden_sto_dentry->d_parent); -+ -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16) -+ mutex_lock(&hidden_sto_dir_dentry->d_inode->i_mutex); -+#else -+ down(&hidden_sto_dir_dentry->d_inode->i_sem); -+#endif -+ -+ /* avoid destroying the hidden inode if the file is in use */ -+ dget(hidden_sto_dentry); -+ err = vfs_unlink(hidden_sto_dir_inode, hidden_sto_dentry); -+ dput(hidden_sto_dentry); -+ if(!err) -+ d_delete(hidden_sto_dentry); -+ -+ /* propagate number of hard-links */ -+ dentry->d_inode->i_nlink = itohi2(dentry->d_inode)->i_nlink; -+ -+ /* dput base dentry, this will relase the inode and free the -+ * dentry, as we will never need it again. */ -+ dput(dtohd(dentry)); -+ dtohd(dentry) = NULL; -+ dtost(dentry) = DELETED; -+ -+ /* add deleted file to META-file */ -+ meta_add_d_entry(dentry->d_parent, -+ dentry->d_name.name, -+ dentry->d_name.len); -+ -+ /* was: unlock_dir(hidden_sto_dir_dentry); */ -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16) -+ mutex_unlock(&hidden_sto_dir_dentry->d_inode->i_mutex); -+#else -+ up(&hidden_sto_dir_dentry->d_inode->i_sem); -+#endif -+ dput(hidden_sto_dir_dentry); -+ -+ out: -+ return err; -+} -+ -+int nondir_unmod_to_del(dentry_t *dentry) -+{ -+ int err = 0; -+ -+ check_mini_fo_dentry(dentry); -+ -+ if(dtost(dentry) != UNMODIFIED || -+ S_ISDIR(dentry->d_inode->i_mode)) { -+ printk(KERN_CRIT "mini_fo: nondir_unmod_to_del: \ -+ wrong type or state.\n"); -+ err = -1; -+ goto out; -+ } -+ -+ /* next we have to get a negative dentry for the storage file */ -+ err = get_neg_sto_dentry(dentry); -+ -+ if(err) -+ goto out; -+ -+ /* add deleted file to META lists */ -+ err = meta_add_d_entry(dentry->d_parent, -+ dentry->d_name.name, -+ dentry->d_name.len); -+ -+ if(err) -+ goto out; -+ -+ /* dput base dentry, this will relase the inode and free the -+ * dentry, as we will never need it again. */ -+ dput(dtohd(dentry)); -+ dtohd(dentry) = NULL; -+ dtost(dentry) = DELETED; -+ -+ out: -+ return err; -+} -+ -+/* bring a dir from state UNMODIFIED to MODIFIED */ -+int dir_unmod_to_mod(dentry_t *dentry) -+{ -+ int err; -+ -+ check_mini_fo_dentry(dentry); -+ -+ if(dtost(dentry) != UNMODIFIED || -+ !S_ISDIR(dentry->d_inode->i_mode)) { -+ printk(KERN_CRIT "mini_fo: dir_unmod_to_mod: \ -+ wrong type or state.\n"); -+ err = -1; -+ goto out; -+ } -+ -+ /* this creates our dir incl. sto. structure */ -+ err = build_sto_structure(dentry->d_parent, dentry); -+ if(err) { -+ printk(KERN_CRIT "mini_fo: dir_unmod_to_mod: \ -+ build_sto_structure failed.\n"); -+ goto out; -+ } -+ out: -+ return err; -+} -+ ---- /dev/null -+++ b/fs/mini_fo/super.c -@@ -0,0 +1,281 @@ -+/* -+ * Copyright (c) 1997-2003 Erez Zadok -+ * Copyright (c) 2001-2003 Stony Brook University -+ * -+ * For specific licensing information, see the COPYING file distributed with -+ * this package, or get one from ftp://ftp.filesystems.org/pub/fist/COPYING. -+ * -+ * This Copyright notice must be kept intact and distributed with all -+ * fistgen sources INCLUDING sources generated by fistgen. -+ */ -+/* -+ * Copyright (C) 2004, 2005 Markus Klotzbuecher -+ * -+ * 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. -+ */ -+ -+/* -+ * $Id$ -+ */ -+ -+#ifdef HAVE_CONFIG_H -+# include -+#endif -+ -+#include "fist.h" -+#include "mini_fo.h" -+ -+ -+STATIC void -+mini_fo_read_inode(inode_t *inode) -+{ -+ static struct address_space_operations mini_fo_empty_aops; -+ -+ __itopd(inode) = kmalloc(sizeof(struct mini_fo_inode_info), GFP_KERNEL); -+ if (!itopd(inode)) { -+ printk("<0>%s:%s:%d: No kernel memory!\n", __FILE__, __FUNCTION__, __LINE__); -+ ASSERT(NULL); -+ } -+ itohi(inode) = NULL; -+ itohi2(inode) = NULL; -+ -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) -+ inode->i_version++; -+#else -+ inode->i_version = ++event; /* increment inode version */ -+#endif -+ inode->i_op = &mini_fo_main_iops; -+ inode->i_fop = &mini_fo_main_fops; -+#if 0 -+ /* -+ * XXX: To export a file system via NFS, it has to have the -+ * FS_REQUIRES_DEV flag, so turn it on. But should we inherit it from -+ * the lower file system, or can we allow our file system to be exported -+ * even if the lower one cannot be natively exported. -+ */ -+ inode->i_sb->s_type->fs_flags |= FS_REQUIRES_DEV; -+ /* -+ * OK, the above was a hack, which is now turned off because it may -+ * cause a panic/oops on some systems. The correct way to export a -+ * "nodev" filesystem is via using nfs-utils > 1.0 and the "fsid=" export -+ * parameter, which requires 2.4.20 or later. -+ */ -+#endif -+ /* I don't think ->a_ops is ever allowed to be NULL */ -+ inode->i_mapping->a_ops = &mini_fo_empty_aops; -+} -+ -+ -+#if defined(FIST_DEBUG) || defined(FIST_FILTER_SCA) -+/* -+ * No need to call write_inode() on the lower inode, as it -+ * will have been marked 'dirty' anyway. But we might need -+ * to write some of our own stuff to disk. -+ */ -+STATIC void -+mini_fo_write_inode(inode_t *inode, int sync) -+{ -+ print_entry_location(); -+ print_exit_location(); -+} -+#endif /* defined(FIST_DEBUG) || defined(FIST_FILTER_SCA) */ -+ -+ -+STATIC void -+mini_fo_put_inode(inode_t *inode) -+{ -+ /* -+ * This is really funky stuff: -+ * Basically, if i_count == 1, iput will then decrement it and this inode will be destroyed. -+ * It is currently holding a reference to the hidden inode. -+ * Therefore, it needs to release that reference by calling iput on the hidden inode. -+ * iput() _will_ do it for us (by calling our clear_inode), but _only_ if i_nlink == 0. -+ * The problem is, NFS keeps i_nlink == 1 for silly_rename'd files. -+ * So we must for our i_nlink to 0 here to trick iput() into calling our clear_inode. -+ */ -+ if (atomic_read(&inode->i_count) == 1) -+ inode->i_nlink = 0; -+} -+ -+ -+#if defined(FIST_DEBUG) || defined(FIST_FILTER_SCA) -+/* -+ * we now define delete_inode, because there are two VFS paths that may -+ * destroy an inode: one of them calls clear inode before doing everything -+ * else that's needed, and the other is fine. This way we truncate the inode -+ * size (and its pages) and then clear our own inode, which will do an iput -+ * on our and the lower inode. -+ */ -+STATIC void -+mini_fo_delete_inode(inode_t *inode) -+{ -+ print_entry_location(); -+ -+ fist_checkinode(inode, "mini_fo_delete_inode IN"); -+ inode->i_size = 0; /* every f/s seems to do that */ -+ clear_inode(inode); -+ -+ print_exit_location(); -+} -+#endif /* defined(FIST_DEBUG) || defined(FIST_FILTER_SCA) */ -+ -+ -+/* final actions when unmounting a file system */ -+STATIC void -+mini_fo_put_super(super_block_t *sb) -+{ -+ if (stopd(sb)) { -+ mntput(stopd(sb)->hidden_mnt); -+ mntput(stopd(sb)->hidden_mnt2); -+ -+ /* mk: no! dput(stopd(sb)->base_dir_dentry); -+ dput(stopd(sb)->storage_dir_dentry); */ -+ -+ kfree(stopd(sb)); -+ __stopd(sb) = NULL; -+ } -+} -+ -+ -+#ifdef NOT_NEEDED -+/* -+ * This is called in do_umount before put_super. -+ * The superblock lock is not held yet. -+ * We probably do not need to define this or call write_super -+ * on the hidden_sb, because sync_supers() will get to hidden_sb -+ * sooner or later. But it is also called from file_fsync()... -+ */ -+STATIC void -+mini_fo_write_super(super_block_t *sb) -+{ -+ return; -+} -+#endif /* NOT_NEEDED */ -+ -+ -+STATIC int -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,18) -+mini_fo_statfs(struct dentry *d, struct kstatfs *buf) -+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) -+mini_fo_statfs(super_block_t *sb, struct kstatfs *buf) -+#else -+mini_fo_statfs(super_block_t *sb, struct statfs *buf) -+#endif -+{ -+ int err = 0; -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,18) -+ struct dentry *hidden_d; -+ -+ hidden_d = dtohd(d); -+ err = vfs_statfs(hidden_d, buf); -+#else -+ super_block_t *hidden_sb; -+ -+ hidden_sb = stohs(sb); -+ err = vfs_statfs(hidden_sb, buf); -+#endif -+ -+ return err; -+} -+ -+ -+/* -+ * XXX: not implemented. This is not allowed yet. -+ * Should we call this on the hidden_sb? Probably not. -+ */ -+STATIC int -+mini_fo_remount_fs(super_block_t *sb, int *flags, char *data) -+{ -+ //printk(KERN_CRIT "mini_fo_remount_fs: WARNING, this function is umimplemented.\n"); -+ return -ENOSYS; -+} -+ -+ -+/* -+ * Called by iput() when the inode reference count reached zero -+ * and the inode is not hashed anywhere. Used to clear anything -+ * that needs to be, before the inode is completely destroyed and put -+ * on the inode free list. -+ */ -+STATIC void -+mini_fo_clear_inode(inode_t *inode) -+{ -+ /* -+ * Decrement a reference to a hidden_inode, which was incremented -+ * by our read_inode when it was created initially. -+ */ -+ -+ /* release the wol_list */ -+ if(S_ISDIR(inode->i_mode)) { -+ __meta_put_lists(inode); -+ } -+ -+ /* mk: fan out fun */ -+ if(itohi(inode)) -+ iput(itohi(inode)); -+ if(itohi2(inode)) -+ iput(itohi2(inode)); -+ -+ // XXX: why this assertion fails? -+ // because it doesn't like us -+ // ASSERT((inode->i_state & I_DIRTY) == 0); -+ kfree(itopd(inode)); -+ __itopd(inode) = NULL; -+} -+ -+ -+/* -+ * Called in do_umount() if the MNT_FORCE flag was used and this -+ * function is defined. See comment in linux/fs/super.c:do_umount(). -+ * Used only in nfs, to kill any pending RPC tasks, so that subsequent -+ * code can actually succeed and won't leave tasks that need handling. -+ * -+ * PS. I wonder if this is somehow useful to undo damage that was -+ * left in the kernel after a user level file server (such as amd) -+ * dies. -+ */ -+STATIC void -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,18) -+mini_fo_umount_begin(struct vfsmount *mnt, int flags) -+{ -+ struct vfsmount *hidden_mnt; -+ -+ hidden_mnt = stopd(mnt->mnt_sb)->hidden_mnt; -+ -+ if (hidden_mnt->mnt_sb->s_op->umount_begin) -+ hidden_mnt->mnt_sb->s_op->umount_begin(hidden_mnt, flags); -+ -+} -+#else -+mini_fo_umount_begin(super_block_t *sb) -+{ -+ super_block_t *hidden_sb; -+ -+ hidden_sb = stohs(sb); -+ -+ if (hidden_sb->s_op->umount_begin) -+ hidden_sb->s_op->umount_begin(hidden_sb); -+ -+} -+#endif -+ -+ -+struct super_operations mini_fo_sops = -+{ -+ read_inode: mini_fo_read_inode, -+#if defined(FIST_DEBUG) || defined(FIST_FILTER_SCA) -+ write_inode: mini_fo_write_inode, -+#endif /* defined(FIST_DEBUG) || defined(FIST_FILTER_SCA) */ -+ put_inode: mini_fo_put_inode, -+#if defined(FIST_DEBUG) || defined(FIST_FILTER_SCA) -+ delete_inode: mini_fo_delete_inode, -+#endif /* defined(FIST_DEBUG) || defined(FIST_FILTER_SCA) */ -+ put_super: mini_fo_put_super, -+ statfs: mini_fo_statfs, -+ remount_fs: mini_fo_remount_fs, -+ clear_inode: mini_fo_clear_inode, -+ umount_begin: mini_fo_umount_begin, -+}; diff --git a/target/linux/generic-2.6/patches-2.6.28/210-mini_fo_2.6.25_fixes.patch b/target/linux/generic-2.6/patches-2.6.28/210-mini_fo_2.6.25_fixes.patch deleted file mode 100644 index d71e3b6fa..000000000 --- a/target/linux/generic-2.6/patches-2.6.28/210-mini_fo_2.6.25_fixes.patch +++ /dev/null @@ -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); - } - - diff --git a/target/linux/generic-2.6/patches-2.6.28/211-mini_fo_2.6.25_dentry_open_war.patch b/target/linux/generic-2.6/patches-2.6.28/211-mini_fo_2.6.25_dentry_open_war.patch deleted file mode 100644 index 48a19429b..000000000 --- a/target/linux/generic-2.6/patches-2.6.28/211-mini_fo_2.6.25_dentry_open_war.patch +++ /dev/null @@ -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; diff --git a/target/linux/generic-2.6/patches-2.6.28/212-mini_fo_2.6.26_fixes.patch b/target/linux/generic-2.6/patches-2.6.28/212-mini_fo_2.6.26_fixes.patch deleted file mode 100644 index 8bd9ba324..000000000 --- a/target/linux/generic-2.6/patches-2.6.28/212-mini_fo_2.6.26_fixes.patch +++ /dev/null @@ -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) */ diff --git a/target/linux/generic-2.6/patches-2.6.28/213-mini_fo_2.6.27_fixes.patch b/target/linux/generic-2.6/patches-2.6.28/213-mini_fo_2.6.27_fixes.patch deleted file mode 100644 index f92c18b25..000000000 --- a/target/linux/generic-2.6/patches-2.6.28/213-mini_fo_2.6.27_fixes.patch +++ /dev/null @@ -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); diff --git a/target/linux/generic-2.6/patches-2.6.28/219-kobject_uevent.patch b/target/linux/generic-2.6/patches-2.6.28/219-kobject_uevent.patch deleted file mode 100644 index 279665e86..000000000 --- a/target/linux/generic-2.6/patches-2.6.28/219-kobject_uevent.patch +++ /dev/null @@ -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; diff --git a/target/linux/generic-2.6/patches-2.6.28/220-sound_kconfig.patch b/target/linux/generic-2.6/patches-2.6.28/220-sound_kconfig.patch deleted file mode 100644 index f374009a6..000000000 --- a/target/linux/generic-2.6/patches-2.6.28/220-sound_kconfig.patch +++ /dev/null @@ -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 diff --git a/target/linux/generic-2.6/patches-2.6.28/230-add-r_arm_v4bx-relocation-for-arm-module-loader.patch b/target/linux/generic-2.6/patches-2.6.28/230-add-r_arm_v4bx-relocation-for-arm-module-loader.patch deleted file mode 100644 index 3e8d1fb0b..000000000 --- a/target/linux/generic-2.6/patches-2.6.28/230-add-r_arm_v4bx-relocation-for-arm-module-loader.patch +++ /dev/null @@ -1,28 +0,0 @@ ---- a/arch/arm/include/asm/elf.h -+++ b/arch/arm/include/asm/elf.h -@@ -50,6 +50,7 @@ typedef struct user_fp elf_fpregset_t; - #define R_ARM_ABS32 2 - #define R_ARM_CALL 28 - #define R_ARM_JUMP24 29 -+#define R_ARM_V4BX 40 - - /* - * These are used to set parameters in the core dumps. ---- a/arch/arm/kernel/module.c -+++ b/arch/arm/kernel/module.c -@@ -136,6 +136,15 @@ apply_relocate(Elf32_Shdr *sechdrs, cons - *(u32 *)loc |= offset & 0x00ffffff; - break; - -+ case R_ARM_V4BX: -+ /* Preserve Rm and the condition code. Alter -+ * other bits to re-code instruction as -+ * MOV PC,Rm. -+ */ -+ *(u32 *)loc &= 0xf000000f; -+ *(u32 *)loc |= 0x01a0f000; -+ break; -+ - default: - printk(KERN_ERR "%s: unknown relocation: %u\n", - module->name, ELF32_R_TYPE(rel->r_info)); diff --git a/target/linux/generic-2.6/patches-2.6.28/240-packet_socket_type.patch b/target/linux/generic-2.6/patches-2.6.28/240-packet_socket_type.patch deleted file mode 100644 index 720d3201f..000000000 --- a/target/linux/generic-2.6/patches-2.6.28/240-packet_socket_type.patch +++ /dev/null @@ -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 - ---- 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; - -@@ -1072,6 +1075,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; -@@ -1411,6 +1415,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: -@@ -1542,6 +1556,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)) diff --git a/target/linux/generic-2.6/patches-2.6.28/250-pppoe_header_pad.patch b/target/linux/generic-2.6/patches-2.6.28/250-pppoe_header_pad.patch deleted file mode 100644 index 87e509992..000000000 --- a/target/linux/generic-2.6/patches-2.6.28/250-pppoe_header_pad.patch +++ /dev/null @@ -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; diff --git a/target/linux/generic-2.6/patches-2.6.28/260-extend_pfifo_fast.patch b/target/linux/generic-2.6/patches-2.6.28/260-extend_pfifo_fast.patch deleted file mode 100644 index 90773f704..000000000 --- a/target/linux/generic-2.6/patches-2.6.28/260-extend_pfifo_fast.patch +++ /dev/null @@ -1,144 +0,0 @@ ---- a/net/sched/sch_generic.c -+++ b/net/sched/sch_generic.c -@@ -382,16 +382,50 @@ static const u8 prio2band[TC_PRIO_MAX+1] - - #define PFIFO_FAST_BANDS 3 - -+struct pfifo_fast_sched_data { -+ struct tcf_proto *filter_list; -+ struct sk_buff_head list[PFIFO_FAST_BANDS]; -+}; -+ - static inline struct sk_buff_head *prio2list(struct sk_buff *skb, - struct Qdisc *qdisc) - { -- struct sk_buff_head *list = qdisc_priv(qdisc); -+ struct pfifo_fast_sched_data *q = qdisc_priv(qdisc); -+ struct sk_buff_head *list = q->list; - return list + prio2band[skb->priority & TC_PRIO_MAX]; - } - -+static int pfifo_fast_filter(struct sk_buff *skb, struct Qdisc* qdisc) -+{ -+#ifdef CONFIG_NET_CLS_ACT -+ struct pfifo_fast_sched_data *q = qdisc_priv(qdisc); -+ int result = 0, ret = NET_XMIT_SUCCESS | __NET_XMIT_STOLEN; -+ struct tcf_result res; -+ -+ if (q->filter_list != NULL) -+ result = tc_classify(skb, q->filter_list, &res); -+ if (result >= 0) { -+ switch (result) { -+ case TC_ACT_STOLEN: -+ case TC_ACT_QUEUED: -+ ret = NET_XMIT_SUCCESS | __NET_XMIT_STOLEN; -+ case TC_ACT_SHOT: -+ kfree_skb(skb); -+ return ret; -+ } -+ } -+#endif -+ return 0; -+} -+ - static int pfifo_fast_enqueue(struct sk_buff *skb, struct Qdisc* qdisc) - { - struct sk_buff_head *list = prio2list(skb, qdisc); -+ int ret; -+ -+ ret = pfifo_fast_filter(skb, qdisc); -+ if (ret) -+ return ret; - - if (skb_queue_len(list) < qdisc_dev(qdisc)->tx_queue_len) { - qdisc->q.qlen++; -@@ -403,8 +437,9 @@ static int pfifo_fast_enqueue(struct sk_ - - static struct sk_buff *pfifo_fast_dequeue(struct Qdisc* qdisc) - { -+ struct pfifo_fast_sched_data *q = qdisc_priv(qdisc); -+ struct sk_buff_head *list = q->list; - int prio; -- struct sk_buff_head *list = qdisc_priv(qdisc); - - for (prio = 0; prio < PFIFO_FAST_BANDS; prio++) { - if (!skb_queue_empty(list + prio)) { -@@ -424,8 +459,9 @@ static int pfifo_fast_requeue(struct sk_ - - static void pfifo_fast_reset(struct Qdisc* qdisc) - { -+ struct pfifo_fast_sched_data *q = qdisc_priv(qdisc); -+ struct sk_buff_head *list = q->list; - int prio; -- struct sk_buff_head *list = qdisc_priv(qdisc); - - for (prio = 0; prio < PFIFO_FAST_BANDS; prio++) - __qdisc_reset_queue(qdisc, list + prio); -@@ -448,8 +484,9 @@ nla_put_failure: - - static int pfifo_fast_init(struct Qdisc *qdisc, struct nlattr *opt) - { -+ struct pfifo_fast_sched_data *q = qdisc_priv(qdisc); -+ struct sk_buff_head *list = q->list; - int prio; -- struct sk_buff_head *list = qdisc_priv(qdisc); - - for (prio = 0; prio < PFIFO_FAST_BANDS; prio++) - skb_queue_head_init(list + prio); -@@ -457,9 +494,36 @@ static int pfifo_fast_init(struct Qdisc - return 0; - } - -+static int pfifo_fast_change_class(struct Qdisc *qdisc, u32 classid, u32 parentid, -+ struct nlattr **tca, unsigned long *arg) -+{ -+ return -EOPNOTSUPP; -+} -+ -+static unsigned long pfifo_fast_get(struct Qdisc *qdisc, u32 classid) -+{ -+ return 0; -+} -+ -+static struct tcf_proto **pfifo_fast_find_tcf(struct Qdisc *qdisc, unsigned long cl) -+{ -+ struct pfifo_fast_sched_data *q = qdisc_priv(qdisc); -+ -+ if (cl) -+ return NULL; -+ return &q->filter_list; -+} -+ -+static const struct Qdisc_class_ops pfifo_fast_class_ops = { -+ .get = pfifo_fast_get, -+ .change = pfifo_fast_change_class, -+ .tcf_chain = pfifo_fast_find_tcf, -+}; -+ - static struct Qdisc_ops pfifo_fast_ops __read_mostly = { - .id = "pfifo_fast", -- .priv_size = PFIFO_FAST_BANDS * sizeof(struct sk_buff_head), -+ .cl_ops = &pfifo_fast_class_ops, -+ .priv_size = sizeof(struct pfifo_fast_sched_data), - .enqueue = pfifo_fast_enqueue, - .dequeue = pfifo_fast_dequeue, - .requeue = pfifo_fast_requeue, -@@ -739,3 +803,18 @@ void dev_shutdown(struct net_device *dev - shutdown_scheduler_queue(dev, &dev->rx_queue, &noop_qdisc); - WARN_ON(timer_pending(&dev->watchdog_timer)); - } -+ -+#ifdef CONFIG_NET_SCHED -+static int __init sch_generic_init(void) -+{ -+ return register_qdisc(&pfifo_fast_ops); -+} -+ -+static void __exit sch_generic_exit(void) -+{ -+ unregister_qdisc(&pfifo_fast_ops); -+} -+ -+module_init(sch_generic_init) -+module_exit(sch_generic_exit) -+#endif diff --git a/target/linux/generic-2.6/patches-2.6.28/300-fix_byteorder_header.patch b/target/linux/generic-2.6/patches-2.6.28/300-fix_byteorder_header.patch deleted file mode 100644 index 5f68085a3..000000000 --- a/target/linux/generic-2.6/patches-2.6.28/300-fix_byteorder_header.patch +++ /dev/null @@ -1,340 +0,0 @@ -glibc headers define both __LITTLE_ENDIAN and __BIG_ENDIAN -which was tripping the check in linux/byteorder.h. Let's -just stay out of userspace's way and use __KERN_{endian} - -The old implementation got away with it as it kept the two -implementations in different headers and conditionally included -the right one. The combined header does checks within each -function body and depends on only one being defined. - -Converted the arches in mainline that have already moved to the -new header, as the other arches merge the will need simlar -fixups. - -Signed-off-by: Harvey Harrison ---- - arch/avr32/include/asm/byteorder.h | 2 +- - arch/mips/include/asm/byteorder.h | 4 +- - arch/sh/include/asm/byteorder.h | 4 +- - arch/sparc/include/asm/byteorder.h | 2 +- - include/linux/byteorder.h | 84 ++++++++++++++++++------------------ - 5 files changed, 48 insertions(+), 48 deletions(-) - ---- a/arch/avr32/include/asm/byteorder.h -+++ b/arch/avr32/include/asm/byteorder.h -@@ -7,7 +7,7 @@ - #include - #include - --#define __BIG_ENDIAN -+#define __KERN_BIG_ENDIAN - #define __SWAB_64_THRU_32__ - - #ifdef __CHECKER__ ---- a/arch/mips/include/asm/byteorder.h -+++ b/arch/mips/include/asm/byteorder.h -@@ -12,9 +12,9 @@ - #include - - #if defined(__MIPSEB__) --# define __BIG_ENDIAN -+# define __KERN_BIG_ENDIAN - #elif defined(__MIPSEL__) --# define __LITTLE_ENDIAN -+# define __KERN_LITTLE_ENDIAN - #else - # error "MIPS, but neither __MIPSEB__, nor __MIPSEL__???" - #endif ---- a/arch/sh/include/asm/byteorder.h -+++ b/arch/sh/include/asm/byteorder.h -@@ -9,9 +9,9 @@ - #include - - #ifdef __LITTLE_ENDIAN__ --# define __LITTLE_ENDIAN -+# define __KERN_LITTLE_ENDIAN - #else --# define __BIG_ENDIAN -+# define __KERN_BIG_ENDIAN - #endif - - #define __SWAB_64_THRU_32__ ---- a/arch/sparc/include/asm/byteorder.h -+++ b/arch/sparc/include/asm/byteorder.h -@@ -4,7 +4,7 @@ - #include - #include - --#define __BIG_ENDIAN -+#define __KERN_BIG_ENDIAN - - #ifdef CONFIG_SPARC32 - #define __SWAB_64_THRU_32__ ---- a/include/linux/byteorder.h -+++ b/include/linux/byteorder.h -@@ -4,33 +4,33 @@ - #include - #include - --#if defined(__LITTLE_ENDIAN) && defined(__BIG_ENDIAN) -+#if defined(__KERN_LITTLE_ENDIAN) && defined(__KERN_BIG_ENDIAN) - # error Fix asm/byteorder.h to define one endianness - #endif - --#if !defined(__LITTLE_ENDIAN) && !defined(__BIG_ENDIAN) -+#if !defined(__KERN_LITTLE_ENDIAN) && !defined(__KERN_BIG_ENDIAN) - # error Fix asm/byteorder.h to define arch endianness - #endif - --#ifdef __LITTLE_ENDIAN --# undef __LITTLE_ENDIAN --# define __LITTLE_ENDIAN 1234 -+#ifdef __KERN_LITTLE_ENDIAN -+# ifndef __LITTLE_ENDIAN -+# define __LITTLE_ENDIAN 1234 -+# endif -+# ifndef __LITTLE_ENDIAN_BITFIELD -+# define __LITTLE_ENDIAN_BITFIELD -+# endif -+#endif -+ -+#ifdef __KERN_BIG_ENDIAN -+# ifndef __BIG_ENDIAN -+# define __BIG_ENDIAN 4321 -+# endif -+# ifndef __BIG_ENDIAN_BITFIELD -+# define __BIG_ENDIAN_BITFIELD -+# endif - #endif - --#ifdef __BIG_ENDIAN --# undef __BIG_ENDIAN --# define __BIG_ENDIAN 4321 --#endif -- --#if defined(__LITTLE_ENDIAN) && !defined(__LITTLE_ENDIAN_BITFIELD) --# define __LITTLE_ENDIAN_BITFIELD --#endif -- --#if defined(__BIG_ENDIAN) && !defined(__BIG_ENDIAN_BITFIELD) --# define __BIG_ENDIAN_BITFIELD --#endif -- --#ifdef __LITTLE_ENDIAN -+#ifdef __KERN_LITTLE_ENDIAN - # define __le16_to_cpu(x) ((__force __u16)(__le16)(x)) - # define __le32_to_cpu(x) ((__force __u32)(__le32)(x)) - # define __le64_to_cpu(x) ((__force __u64)(__le64)(x)) -@@ -46,7 +46,7 @@ - # define __cpu_to_be64(x) ((__force __be64)__swab64(x)) - #endif - --#ifdef __BIG_ENDIAN -+#ifdef __KERN_BIG_ENDIAN - # define __be16_to_cpu(x) ((__force __u16)(__be16)(x)) - # define __be32_to_cpu(x) ((__force __u32)(__be32)(x)) - # define __be64_to_cpu(x) ((__force __u64)(__be64)(x)) -@@ -87,91 +87,91 @@ - - static inline void __le16_to_cpus(__u16 *p) - { --#ifdef __BIG_ENDIAN -+#ifdef __KERN_BIG_ENDIAN - __swab16s(p); - #endif - } - - static inline void __cpu_to_le16s(__u16 *p) - { --#ifdef __BIG_ENDIAN -+#ifdef __KERN_BIG_ENDIAN - __swab16s(p); - #endif - } - - static inline void __le32_to_cpus(__u32 *p) - { --#ifdef __BIG_ENDIAN -+#ifdef __KERN_BIG_ENDIAN - __swab32s(p); - #endif - } - - static inline void __cpu_to_le32s(__u32 *p) - { --#ifdef __BIG_ENDIAN -+#ifdef __KERN_BIG_ENDIAN - __swab32s(p); - #endif - } - - static inline void __le64_to_cpus(__u64 *p) - { --#ifdef __BIG_ENDIAN -+#ifdef __KERN_BIG_ENDIAN - __swab64s(p); - #endif - } - - static inline void __cpu_to_le64s(__u64 *p) - { --#ifdef __BIG_ENDIAN -+#ifdef __KERN_BIG_ENDIAN - __swab64s(p); - #endif - } - - static inline void __be16_to_cpus(__u16 *p) - { --#ifdef __LITTLE_ENDIAN -+#ifdef __KERN_LITTLE_ENDIAN - __swab16s(p); - #endif - } - - static inline void __cpu_to_be16s(__u16 *p) - { --#ifdef __LITTLE_ENDIAN -+#ifdef __KERN_LITTLE_ENDIAN - __swab16s(p); - #endif - } - - static inline void __be32_to_cpus(__u32 *p) - { --#ifdef __LITTLE_ENDIAN -+#ifdef __KERN_LITTLE_ENDIAN - __swab32s(p); - #endif - } - - static inline void __cpu_to_be32s(__u32 *p) - { --#ifdef __LITTLE_ENDIAN -+#ifdef __KERN_LITTLE_ENDIAN - __swab32s(p); - #endif - } - - static inline void __be64_to_cpus(__u64 *p) - { --#ifdef __LITTLE_ENDIAN -+#ifdef __KERN_LITTLE_ENDIAN - __swab64s(p); - #endif - } - - static inline void __cpu_to_be64s(__u64 *p) - { --#ifdef __LITTLE_ENDIAN -+#ifdef __KERN_LITTLE_ENDIAN - __swab64s(p); - #endif - } - - static inline __u16 __le16_to_cpup(const __le16 *p) - { --#ifdef __LITTLE_ENDIAN -+#ifdef __KERN_LITTLE_ENDIAN - return (__force __u16)*p; - #else - return __swab16p((__force __u16 *)p); -@@ -180,7 +180,7 @@ static inline __u16 __le16_to_cpup(const - - static inline __u32 __le32_to_cpup(const __le32 *p) - { --#ifdef __LITTLE_ENDIAN -+#ifdef __KERN_LITTLE_ENDIAN - return (__force __u32)*p; - #else - return __swab32p((__force __u32 *)p); -@@ -189,7 +189,7 @@ static inline __u32 __le32_to_cpup(const - - static inline __u64 __le64_to_cpup(const __le64 *p) - { --#ifdef __LITTLE_ENDIAN -+#ifdef __KERN_LITTLE_ENDIAN - return (__force __u64)*p; - #else - return __swab64p((__force __u64 *)p); -@@ -198,7 +198,7 @@ static inline __u64 __le64_to_cpup(const - - static inline __le16 __cpu_to_le16p(const __u16 *p) - { --#ifdef __LITTLE_ENDIAN -+#ifdef __KERN_LITTLE_ENDIAN - return (__force __le16)*p; - #else - return (__force __le16)__swab16p(p); -@@ -207,7 +207,7 @@ static inline __le16 __cpu_to_le16p(cons - - static inline __le32 __cpu_to_le32p(const __u32 *p) - { --#ifdef __LITTLE_ENDIAN -+#ifdef __KERN_LITTLE_ENDIAN - return (__force __le32)*p; - #else - return (__force __le32)__swab32p(p); -@@ -216,7 +216,7 @@ static inline __le32 __cpu_to_le32p(cons - - static inline __le64 __cpu_to_le64p(const __u64 *p) - { --#ifdef __LITTLE_ENDIAN -+#ifdef __KERN_LITTLE_ENDIAN - return (__force __le64)*p; - #else - return (__force __le64)__swab64p(p); -@@ -225,7 +225,7 @@ static inline __le64 __cpu_to_le64p(cons - - static inline __u16 __be16_to_cpup(const __be16 *p) - { --#ifdef __BIG_ENDIAN -+#ifdef __KERN_BIG_ENDIAN - return (__force __u16)*p; - #else - return __swab16p((__force __u16 *)p); -@@ -234,7 +234,7 @@ static inline __u16 __be16_to_cpup(const - - static inline __u32 __be32_to_cpup(const __be32 *p) - { --#ifdef __BIG_ENDIAN -+#ifdef __KERN_BIG_ENDIAN - return (__force __u32)*p; - #else - return __swab32p((__force __u32 *)p); -@@ -243,7 +243,7 @@ static inline __u32 __be32_to_cpup(const - - static inline __u64 __be64_to_cpup(const __be64 *p) - { --#ifdef __BIG_ENDIAN -+#ifdef __KERN_BIG_ENDIAN - return (__force __u64)*p; - #else - return __swab64p((__force __u64 *)p); -@@ -252,7 +252,7 @@ static inline __u64 __be64_to_cpup(const - - static inline __be16 __cpu_to_be16p(const __u16 *p) - { --#ifdef __BIG_ENDIAN -+#ifdef __KERN_BIG_ENDIAN - return (__force __be16)*p; - #else - return (__force __be16)__swab16p(p); -@@ -261,7 +261,7 @@ static inline __be16 __cpu_to_be16p(cons - - static inline __be32 __cpu_to_be32p(const __u32 *p) - { --#ifdef __BIG_ENDIAN -+#ifdef __KERN_BIG_ENDIAN - return (__force __be32)*p; - #else - return (__force __be32)__swab32p(p); -@@ -270,7 +270,7 @@ static inline __be32 __cpu_to_be32p(cons - - static inline __be64 __cpu_to_be64p(const __u64 *p) - { --#ifdef __BIG_ENDIAN -+#ifdef __KERN_BIG_ENDIAN - return (__force __be64)*p; - #else - return (__force __be64)__swab64p(p); diff --git a/target/linux/generic-2.6/patches-2.6.28/400-ledtrig_morse.patch b/target/linux/generic-2.6/patches-2.6.28/400-ledtrig_morse.patch deleted file mode 100644 index 8d3dd8e6d..000000000 --- a/target/linux/generic-2.6/patches-2.6.28/400-ledtrig_morse.patch +++ /dev/null @@ -1,18 +0,0 @@ ---- a/drivers/leds/Kconfig -+++ b/drivers/leds/Kconfig -@@ -217,4 +217,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 -@@ -30,3 +30,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 diff --git a/target/linux/generic-2.6/patches-2.6.28/402-ledtrig_netdev.patch b/target/linux/generic-2.6/patches-2.6.28/402-ledtrig_netdev.patch deleted file mode 100644 index 105698013..000000000 --- a/target/linux/generic-2.6/patches-2.6.28/402-ledtrig_netdev.patch +++ /dev/null @@ -1,21 +0,0 @@ ---- a/drivers/leds/Kconfig -+++ b/drivers/leds/Kconfig -@@ -221,4 +221,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 -@@ -31,3 +31,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 diff --git a/target/linux/generic-2.6/patches-2.6.28/410-gpio_buttons.patch b/target/linux/generic-2.6/patches-2.6.28/410-gpio_buttons.patch deleted file mode 100644 index 198557aac..000000000 --- a/target/linux/generic-2.6/patches-2.6.28/410-gpio_buttons.patch +++ /dev/null @@ -1,30 +0,0 @@ ---- a/drivers/input/misc/Kconfig -+++ b/drivers/input/misc/Kconfig -@@ -220,4 +220,20 @@ config HP_SDC_RTC - Say Y here if you want to support the built-in real time clock - of the HP SDC controller. - -+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 -@@ -21,3 +21,4 @@ obj-$(CONFIG_HP_SDC_RTC) += hp_sdc_rtc. - obj-$(CONFIG_INPUT_UINPUT) += uinput.o - obj-$(CONFIG_INPUT_APANEL) += apanel.o - obj-$(CONFIG_INPUT_SGI_BTNS) += sgi_btns.o -+obj-$(CONFIG_INPUT_GPIO_BUTTONS) += gpio_buttons.o diff --git a/target/linux/generic-2.6/patches-2.6.28/420-gpiodev.patch b/target/linux/generic-2.6/patches-2.6.28/420-gpiodev.patch deleted file mode 100644 index c7b665a67..000000000 --- a/target/linux/generic-2.6/patches-2.6.28/420-gpiodev.patch +++ /dev/null @@ -1,26 +0,0 @@ ---- a/drivers/char/Kconfig -+++ b/drivers/char/Kconfig -@@ -988,6 +988,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 -@@ -92,6 +92,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 diff --git a/target/linux/generic-2.6/patches-2.6.28/450-i2c_at24_add_kernel_interface_read_write.patch b/target/linux/generic-2.6/patches-2.6.28/450-i2c_at24_add_kernel_interface_read_write.patch deleted file mode 100644 index e360db0e2..000000000 --- a/target/linux/generic-2.6/patches-2.6.28/450-i2c_at24_add_kernel_interface_read_write.patch +++ /dev/null @@ -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 -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 - -Signed-off-by: Kevin Hilman ---- - drivers/i2c/chips/at24.c | 42 +++++++++++++++++++++++++++++++++++------- - include/linux/i2c/at24.h | 10 ++++++++++ - 2 files changed, 45 insertions(+), 7 deletions(-) - ---- a/drivers/i2c/chips/at24.c -+++ b/drivers/i2c/chips/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 */ diff --git a/target/linux/generic-2.6/patches-2.6.28/510-yaffs_support.patch b/target/linux/generic-2.6/patches-2.6.28/510-yaffs_support.patch deleted file mode 100644 index b564d3a4e..000000000 --- a/target/linux/generic-2.6/patches-2.6.28/510-yaffs_support.patch +++ /dev/null @@ -1,17 +0,0 @@ ---- a/fs/Kconfig -+++ b/fs/Kconfig -@@ -182,6 +182,7 @@ config FILE_LOCKING - - source "fs/xfs/Kconfig" - source "fs/gfs2/Kconfig" -+source "fs/yaffs2/Kconfig" - - config OCFS2_FS - tristate "OCFS2 file system support" ---- a/fs/Makefile -+++ b/fs/Makefile -@@ -124,3 +124,4 @@ obj-$(CONFIG_HPPFS) += hppfs/ - obj-$(CONFIG_DEBUG_FS) += debugfs/ - obj-$(CONFIG_OCFS2_FS) += ocfs2/ - obj-$(CONFIG_GFS2_FS) += gfs2/ -+obj-$(CONFIG_YAFFS_FS) += yaffs2/ diff --git a/target/linux/generic-2.6/patches-2.6.28/511-yaffs-cvs-2009-04-24.patch b/target/linux/generic-2.6/patches-2.6.28/511-yaffs-cvs-2009-04-24.patch deleted file mode 100644 index 5c70e79a0..000000000 --- a/target/linux/generic-2.6/patches-2.6.28/511-yaffs-cvs-2009-04-24.patch +++ /dev/null @@ -1,12344 +0,0 @@ ---- a/fs/yaffs2/devextras.h -+++ b/fs/yaffs2/devextras.h -@@ -14,194 +14,135 @@ - */ - - /* -- * This file is just holds extra declarations used during development. -- * Most of these are from kernel includes placed here so we can use them in -- * applications. -+ * This file is just holds extra declarations of macros that would normally -+ * be providesd in the Linux kernel. These macros have been written from -+ * scratch but are functionally equivalent to the Linux ones. - * - */ - - #ifndef __EXTRAS_H__ - #define __EXTRAS_H__ - --#if defined WIN32 --#define __inline__ __inline --#define new newHack --#endif -- --#if !(defined __KERNEL__) || (defined WIN32) - --/* User space defines */ -+#if !(defined __KERNEL__) - -+/* Definition of types */ - typedef unsigned char __u8; - typedef unsigned short __u16; - typedef unsigned __u32; - -+#endif -+ - /* -- * Simple doubly linked list implementation. -- * -- * Some of the internal functions ("__xxx") are useful when -- * manipulating whole lists rather than single entries, as -- * sometimes we already know the next/prev entries and we can -- * generate better code by using them directly rather than -- * using the generic single-entry routines. -+ * This is a simple doubly linked list implementation that matches the -+ * way the Linux kernel doubly linked list implementation works. - */ - --#define prefetch(x) 1 -- --struct list_head { -- struct list_head *next, *prev; -+struct ylist_head { -+ struct ylist_head *next; /* next in chain */ -+ struct ylist_head *prev; /* previous in chain */ - }; - --#define LIST_HEAD_INIT(name) { &(name), &(name) } - --#define LIST_HEAD(name) \ -- struct list_head name = LIST_HEAD_INIT(name) -+/* Initialise a static list */ -+#define YLIST_HEAD(name) \ -+struct ylist_head name = { &(name), &(name)} -+ - --#define INIT_LIST_HEAD(ptr) do { \ -- (ptr)->next = (ptr); (ptr)->prev = (ptr); \ -+ -+/* Initialise a list head to an empty list */ -+#define YINIT_LIST_HEAD(p) \ -+do { \ -+ (p)->next = (p);\ -+ (p)->prev = (p); \ - } while (0) - --/* -- * Insert a new entry between two known consecutive entries. -- * -- * This is only for internal list manipulation where we know -- * the prev/next entries already! -- */ --static __inline__ void __list_add(struct list_head *new, -- struct list_head *prev, -- struct list_head *next) --{ -- next->prev = new; -- new->next = next; -- new->prev = prev; -- prev->next = new; --} - --/** -- * list_add - add a new entry -- * @new: new entry to be added -- * @head: list head to add it after -- * -- * Insert a new entry after the specified head. -- * This is good for implementing stacks. -- */ --static __inline__ void list_add(struct list_head *new, struct list_head *head) -+/* Add an element to a list */ -+static __inline__ void ylist_add(struct ylist_head *newEntry, -+ struct ylist_head *list) - { -- __list_add(new, head, head->next); --} -+ struct ylist_head *listNext = list->next; -+ -+ list->next = newEntry; -+ newEntry->prev = list; -+ newEntry->next = listNext; -+ listNext->prev = newEntry; - --/** -- * list_add_tail - add a new entry -- * @new: new entry to be added -- * @head: list head to add it before -- * -- * Insert a new entry before the specified head. -- * This is useful for implementing queues. -- */ --static __inline__ void list_add_tail(struct list_head *new, -- struct list_head *head) --{ -- __list_add(new, head->prev, head); - } - --/* -- * Delete a list entry by making the prev/next entries -- * point to each other. -- * -- * This is only for internal list manipulation where we know -- * the prev/next entries already! -- */ --static __inline__ void __list_del(struct list_head *prev, -- struct list_head *next) -+static __inline__ void ylist_add_tail(struct ylist_head *newEntry, -+ struct ylist_head *list) - { -- next->prev = prev; -- prev->next = next; -+ struct ylist_head *listPrev = list->prev; -+ -+ list->prev = newEntry; -+ newEntry->next = list; -+ newEntry->prev = listPrev; -+ listPrev->next = newEntry; -+ - } - --/** -- * list_del - deletes entry from list. -- * @entry: the element to delete from the list. -- * Note: list_empty on entry does not return true after this, the entry is -- * in an undefined state. -- */ --static __inline__ void list_del(struct list_head *entry) -+ -+/* Take an element out of its current list, with or without -+ * reinitialising the links.of the entry*/ -+static __inline__ void ylist_del(struct ylist_head *entry) - { -- __list_del(entry->prev, entry->next); -+ struct ylist_head *listNext = entry->next; -+ struct ylist_head *listPrev = entry->prev; -+ -+ listNext->prev = listPrev; -+ listPrev->next = listNext; -+ - } - --/** -- * list_del_init - deletes entry from list and reinitialize it. -- * @entry: the element to delete from the list. -- */ --static __inline__ void list_del_init(struct list_head *entry) -+static __inline__ void ylist_del_init(struct ylist_head *entry) - { -- __list_del(entry->prev, entry->next); -- INIT_LIST_HEAD(entry); -+ ylist_del(entry); -+ entry->next = entry->prev = entry; - } - --/** -- * list_empty - tests whether a list is empty -- * @head: the list to test. -- */ --static __inline__ int list_empty(struct list_head *head) -+ -+/* Test if the list is empty */ -+static __inline__ int ylist_empty(struct ylist_head *entry) - { -- return head->next == head; -+ return (entry->next == entry); - } - --/** -- * list_splice - join two lists -- * @list: the new list to add. -- * @head: the place to add it in the first list. -+ -+/* ylist_entry takes a pointer to a list entry and offsets it to that -+ * we can find a pointer to the object it is embedded in. - */ --static __inline__ void list_splice(struct list_head *list, -- struct list_head *head) --{ -- struct list_head *first = list->next; - -- if (first != list) { -- struct list_head *last = list->prev; -- struct list_head *at = head->next; -- -- first->prev = head; -- head->next = first; -- -- last->next = at; -- at->prev = last; -- } --} - --/** -- * list_entry - get the struct for this entry -- * @ptr: the &struct list_head pointer. -- * @type: the type of the struct this is embedded in. -- * @member: the name of the list_struct within the struct. -- */ --#define list_entry(ptr, type, member) \ -- ((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member))) -- --/** -- * list_for_each - iterate over a list -- * @pos: the &struct list_head to use as a loop counter. -- * @head: the head for your list. -- */ --#define list_for_each(pos, head) \ -- for (pos = (head)->next, prefetch(pos->next); pos != (head); \ -- pos = pos->next, prefetch(pos->next)) -- --/** -- * list_for_each_safe - iterate over a list safe against removal -- * of list entry -- * @pos: the &struct list_head to use as a loop counter. -- * @n: another &struct list_head to use as temporary storage -- * @head: the head for your list. -- */ --#define list_for_each_safe(pos, n, head) \ -- for (pos = (head)->next, n = pos->next; pos != (head); \ -- pos = n, n = pos->next) -+#define ylist_entry(entry, type, member) \ -+ ((type *)((char *)(entry)-(unsigned long)(&((type *)NULL)->member))) - --/* -- * File types -+ -+/* ylist_for_each and list_for_each_safe iterate over lists. -+ * ylist_for_each_safe uses temporary storage to make the list delete safe - */ -+ -+#define ylist_for_each(itervar, list) \ -+ for (itervar = (list)->next; itervar != (list); itervar = itervar->next) -+ -+#define ylist_for_each_safe(itervar, saveVar, list) \ -+ for (itervar = (list)->next, saveVar = (list)->next->next; \ -+ itervar != (list); itervar = saveVar, saveVar = saveVar->next) -+ -+ -+#if !(defined __KERNEL__) -+ -+ -+#ifndef WIN32 -+#include -+#endif -+ -+ -+#ifdef CONFIG_YAFFS_PROVIDE_DEFS -+/* File types */ -+ -+ - #define DT_UNKNOWN 0 - #define DT_FIFO 1 - #define DT_CHR 2 -@@ -212,6 +153,7 @@ static __inline__ void list_splice(struc - #define DT_SOCK 12 - #define DT_WHT 14 - -+ - #ifndef WIN32 - #include - #endif -@@ -227,10 +169,6 @@ static __inline__ void list_splice(struc - #define ATTR_ATIME 16 - #define ATTR_MTIME 32 - #define ATTR_CTIME 64 --#define ATTR_ATIME_SET 128 --#define ATTR_MTIME_SET 256 --#define ATTR_FORCE 512 /* Not a change, but a change it */ --#define ATTR_ATTR_FLAG 1024 - - struct iattr { - unsigned int ia_valid; -@@ -244,21 +182,15 @@ struct iattr { - unsigned int ia_attr_flags; - }; - --#define KERN_DEBUG -+#endif - - #else - --#ifndef WIN32 - #include --#include - #include - #include --#endif - - #endif - --#if defined WIN32 --#undef new --#endif - - #endif ---- a/fs/yaffs2/Kconfig -+++ b/fs/yaffs2/Kconfig -@@ -5,7 +5,7 @@ - config YAFFS_FS - tristate "YAFFS2 file system support" - default n -- depends on MTD -+ depends on MTD_BLOCK - select YAFFS_YAFFS1 - select YAFFS_YAFFS2 - help -@@ -43,7 +43,8 @@ config YAFFS_9BYTE_TAGS - format that you need to continue to support. New data written - also uses the older-style format. Note: Use of this option - generally requires that MTD's oob layout be adjusted to use the -- older-style format. See notes on tags formats and MTD versions. -+ older-style format. See notes on tags formats and MTD versions -+ in yaffs_mtdif1.c. - - If unsure, say N. - -@@ -109,26 +110,6 @@ config YAFFS_DISABLE_LAZY_LOAD - - If unsure, say N. - --config YAFFS_CHECKPOINT_RESERVED_BLOCKS -- int "Reserved blocks for checkpointing" -- depends on YAFFS_YAFFS2 -- default 10 -- help -- Give the number of Blocks to reserve for checkpointing. -- Checkpointing saves the state at unmount so that mounting is -- much faster as a scan of all the flash to regenerate this state -- is not needed. These Blocks are reserved per partition, so if -- you have very small partitions the default (10) may be a mess -- for you. You can set this value to 0, but that does not mean -- checkpointing is disabled at all. There only won't be any -- specially reserved blocks for checkpointing, so if there is -- enough free space on the filesystem, it will be used for -- checkpointing. -- -- If unsure, leave at default (10), but don't wonder if there are -- always 2MB used on your large page device partition (10 x 2k -- pagesize). When using small partitions or when being very small -- on space, you probably want to set this to zero. - - config YAFFS_DISABLE_WIDE_TNODES - bool "Turn off wide tnodes" ---- a/fs/yaffs2/Makefile -+++ b/fs/yaffs2/Makefile -@@ -5,7 +5,6 @@ - obj-$(CONFIG_YAFFS_FS) += yaffs.o - - yaffs-y := yaffs_ecc.o yaffs_fs.o yaffs_guts.o yaffs_checkptrw.o --yaffs-y += yaffs_packedtags2.o yaffs_nand.o yaffs_qsort.o -+yaffs-y += yaffs_packedtags1.o yaffs_packedtags2.o yaffs_nand.o yaffs_qsort.o - yaffs-y += yaffs_tagscompat.o yaffs_tagsvalidity.o --yaffs-y += yaffs_mtdif1.o yaffs_packedtags1.o --yaffs-y += yaffs_mtdif.o yaffs_mtdif2.o -+yaffs-y += yaffs_mtdif.o yaffs_mtdif1.o yaffs_mtdif2.o ---- a/fs/yaffs2/moduleconfig.h -+++ b/fs/yaffs2/moduleconfig.h -@@ -27,12 +27,12 @@ - - /* Default: Not selected */ - /* Meaning: Yaffs does its own ECC, rather than using MTD ECC */ --//#define CONFIG_YAFFS_DOES_ECC -+/* #define CONFIG_YAFFS_DOES_ECC */ - - /* Default: Not selected */ - /* Meaning: ECC byte order is 'wrong'. Only meaningful if */ - /* CONFIG_YAFFS_DOES_ECC is set */ --//#define CONFIG_YAFFS_ECC_WRONG_ORDER -+/* #define CONFIG_YAFFS_ECC_WRONG_ORDER */ - - /* Default: Selected */ - /* Meaning: Disables testing whether chunks are erased before writing to them*/ -@@ -54,11 +54,11 @@ that you need to continue to support. N - older-style format. - Note: Use of this option generally requires that MTD's oob layout be - adjusted to use the older-style format. See notes on tags formats and --MTD versions. -+MTD versions in yaffs_mtdif1.c. - */ - /* Default: Not selected */ - /* Meaning: Use older-style on-NAND data format with pageStatus byte */ --#define CONFIG_YAFFS_9BYTE_TAGS -+/* #define CONFIG_YAFFS_9BYTE_TAGS */ - - #endif /* YAFFS_OUT_OF_TREE */ - ---- a/fs/yaffs2/yaffs_checkptrw.c -+++ b/fs/yaffs2/yaffs_checkptrw.c -@@ -12,48 +12,43 @@ - */ - - const char *yaffs_checkptrw_c_version = -- "$Id: yaffs_checkptrw.c,v 1.14 2007-05-15 20:07:40 charles Exp $"; -+ "$Id: yaffs_checkptrw.c,v 1.18 2009-03-06 17:20:49 wookey Exp $"; - - - #include "yaffs_checkptrw.h" -- -+#include "yaffs_getblockinfo.h" - - static int yaffs_CheckpointSpaceOk(yaffs_Device *dev) - { -- - int blocksAvailable = dev->nErasedBlocks - dev->nReservedBlocks; - - T(YAFFS_TRACE_CHECKPOINT, - (TSTR("checkpt blocks available = %d" TENDSTR), - blocksAvailable)); - -- - return (blocksAvailable <= 0) ? 0 : 1; - } - - - static int yaffs_CheckpointErase(yaffs_Device *dev) - { -- - int i; - -- -- if(!dev->eraseBlockInNAND) -+ if (!dev->eraseBlockInNAND) - return 0; -- T(YAFFS_TRACE_CHECKPOINT,(TSTR("checking blocks %d to %d"TENDSTR), -- dev->internalStartBlock,dev->internalEndBlock)); -+ T(YAFFS_TRACE_CHECKPOINT, (TSTR("checking blocks %d to %d"TENDSTR), -+ dev->internalStartBlock, dev->internalEndBlock)); - -- for(i = dev->internalStartBlock; i <= dev->internalEndBlock; i++) { -- yaffs_BlockInfo *bi = yaffs_GetBlockInfo(dev,i); -- if(bi->blockState == YAFFS_BLOCK_STATE_CHECKPOINT){ -- T(YAFFS_TRACE_CHECKPOINT,(TSTR("erasing checkpt block %d"TENDSTR),i)); -- if(dev->eraseBlockInNAND(dev,i- dev->blockOffset /* realign */)){ -+ for (i = dev->internalStartBlock; i <= dev->internalEndBlock; i++) { -+ yaffs_BlockInfo *bi = yaffs_GetBlockInfo(dev, i); -+ if (bi->blockState == YAFFS_BLOCK_STATE_CHECKPOINT) { -+ T(YAFFS_TRACE_CHECKPOINT, (TSTR("erasing checkpt block %d"TENDSTR), i)); -+ if (dev->eraseBlockInNAND(dev, i - dev->blockOffset /* realign */)) { - bi->blockState = YAFFS_BLOCK_STATE_EMPTY; - dev->nErasedBlocks++; - dev->nFreeChunks += dev->nChunksPerBlock; -- } -- else { -- dev->markNANDBlockBad(dev,i); -+ } else { -+ dev->markNANDBlockBad(dev, i); - bi->blockState = YAFFS_BLOCK_STATE_DEAD; - } - } -@@ -71,23 +66,23 @@ static void yaffs_CheckpointFindNextEras - int blocksAvailable = dev->nErasedBlocks - dev->nReservedBlocks; - T(YAFFS_TRACE_CHECKPOINT, - (TSTR("allocating checkpt block: erased %d reserved %d avail %d next %d "TENDSTR), -- dev->nErasedBlocks,dev->nReservedBlocks,blocksAvailable,dev->checkpointNextBlock)); -+ dev->nErasedBlocks, dev->nReservedBlocks, blocksAvailable, dev->checkpointNextBlock)); - -- if(dev->checkpointNextBlock >= 0 && -- dev->checkpointNextBlock <= dev->internalEndBlock && -- blocksAvailable > 0){ -- -- for(i = dev->checkpointNextBlock; i <= dev->internalEndBlock; i++){ -- yaffs_BlockInfo *bi = yaffs_GetBlockInfo(dev,i); -- if(bi->blockState == YAFFS_BLOCK_STATE_EMPTY){ -+ if (dev->checkpointNextBlock >= 0 && -+ dev->checkpointNextBlock <= dev->internalEndBlock && -+ blocksAvailable > 0) { -+ -+ for (i = dev->checkpointNextBlock; i <= dev->internalEndBlock; i++) { -+ yaffs_BlockInfo *bi = yaffs_GetBlockInfo(dev, i); -+ if (bi->blockState == YAFFS_BLOCK_STATE_EMPTY) { - dev->checkpointNextBlock = i + 1; - dev->checkpointCurrentBlock = i; -- T(YAFFS_TRACE_CHECKPOINT,(TSTR("allocating checkpt block %d"TENDSTR),i)); -+ T(YAFFS_TRACE_CHECKPOINT, (TSTR("allocating checkpt block %d"TENDSTR), i)); - return; - } - } - } -- T(YAFFS_TRACE_CHECKPOINT,(TSTR("out of checkpt blocks"TENDSTR))); -+ T(YAFFS_TRACE_CHECKPOINT, (TSTR("out of checkpt blocks"TENDSTR))); - - dev->checkpointNextBlock = -1; - dev->checkpointCurrentBlock = -1; -@@ -98,30 +93,31 @@ static void yaffs_CheckpointFindNextChec - int i; - yaffs_ExtendedTags tags; - -- T(YAFFS_TRACE_CHECKPOINT,(TSTR("find next checkpt block: start: blocks %d next %d" TENDSTR), -+ T(YAFFS_TRACE_CHECKPOINT, (TSTR("find next checkpt block: start: blocks %d next %d" TENDSTR), - dev->blocksInCheckpoint, dev->checkpointNextBlock)); - -- if(dev->blocksInCheckpoint < dev->checkpointMaxBlocks) -- for(i = dev->checkpointNextBlock; i <= dev->internalEndBlock; i++){ -+ if (dev->blocksInCheckpoint < dev->checkpointMaxBlocks) -+ for (i = dev->checkpointNextBlock; i <= dev->internalEndBlock; i++) { - int chunk = i * dev->nChunksPerBlock; - int realignedChunk = chunk - dev->chunkOffset; - -- dev->readChunkWithTagsFromNAND(dev,realignedChunk,NULL,&tags); -- T(YAFFS_TRACE_CHECKPOINT,(TSTR("find next checkpt block: search: block %d oid %d seq %d eccr %d" TENDSTR), -- i, tags.objectId,tags.sequenceNumber,tags.eccResult)); -+ dev->readChunkWithTagsFromNAND(dev, realignedChunk, -+ NULL, &tags); -+ T(YAFFS_TRACE_CHECKPOINT, (TSTR("find next checkpt block: search: block %d oid %d seq %d eccr %d" TENDSTR), -+ i, tags.objectId, tags.sequenceNumber, tags.eccResult)); - -- if(tags.sequenceNumber == YAFFS_SEQUENCE_CHECKPOINT_DATA){ -+ if (tags.sequenceNumber == YAFFS_SEQUENCE_CHECKPOINT_DATA) { - /* Right kind of block */ - dev->checkpointNextBlock = tags.objectId; - dev->checkpointCurrentBlock = i; - dev->checkpointBlockList[dev->blocksInCheckpoint] = i; - dev->blocksInCheckpoint++; -- T(YAFFS_TRACE_CHECKPOINT,(TSTR("found checkpt block %d"TENDSTR),i)); -+ T(YAFFS_TRACE_CHECKPOINT, (TSTR("found checkpt block %d"TENDSTR), i)); - return; - } - } - -- T(YAFFS_TRACE_CHECKPOINT,(TSTR("found no more checkpt blocks"TENDSTR))); -+ T(YAFFS_TRACE_CHECKPOINT, (TSTR("found no more checkpt blocks"TENDSTR))); - - dev->checkpointNextBlock = -1; - dev->checkpointCurrentBlock = -1; -@@ -133,17 +129,17 @@ int yaffs_CheckpointOpen(yaffs_Device *d - - /* Got the functions we need? */ - if (!dev->writeChunkWithTagsToNAND || -- !dev->readChunkWithTagsFromNAND || -- !dev->eraseBlockInNAND || -- !dev->markNANDBlockBad) -+ !dev->readChunkWithTagsFromNAND || -+ !dev->eraseBlockInNAND || -+ !dev->markNANDBlockBad) - return 0; - -- if(forWriting && !yaffs_CheckpointSpaceOk(dev)) -+ if (forWriting && !yaffs_CheckpointSpaceOk(dev)) - return 0; - -- if(!dev->checkpointBuffer) -- dev->checkpointBuffer = YMALLOC_DMA(dev->nDataBytesPerChunk); -- if(!dev->checkpointBuffer) -+ if (!dev->checkpointBuffer) -+ dev->checkpointBuffer = YMALLOC_DMA(dev->totalBytesPerChunk); -+ if (!dev->checkpointBuffer) - return 0; - - -@@ -159,12 +155,10 @@ int yaffs_CheckpointOpen(yaffs_Device *d - dev->checkpointNextBlock = dev->internalStartBlock; - - /* Erase all the blocks in the checkpoint area */ -- if(forWriting){ -- memset(dev->checkpointBuffer,0,dev->nDataBytesPerChunk); -+ if (forWriting) { -+ memset(dev->checkpointBuffer, 0, dev->nDataBytesPerChunk); - dev->checkpointByteOffset = 0; - return yaffs_CheckpointErase(dev); -- -- - } else { - int i; - /* Set to a value that will kick off a read */ -@@ -174,7 +168,7 @@ int yaffs_CheckpointOpen(yaffs_Device *d - dev->blocksInCheckpoint = 0; - dev->checkpointMaxBlocks = (dev->internalEndBlock - dev->internalStartBlock)/16 + 2; - dev->checkpointBlockList = YMALLOC(sizeof(int) * dev->checkpointMaxBlocks); -- for(i = 0; i < dev->checkpointMaxBlocks; i++) -+ for (i = 0; i < dev->checkpointMaxBlocks; i++) - dev->checkpointBlockList[i] = -1; - } - -@@ -191,18 +185,17 @@ int yaffs_GetCheckpointSum(yaffs_Device - - static int yaffs_CheckpointFlushBuffer(yaffs_Device *dev) - { -- - int chunk; - int realignedChunk; - - yaffs_ExtendedTags tags; - -- if(dev->checkpointCurrentBlock < 0){ -+ if (dev->checkpointCurrentBlock < 0) { - yaffs_CheckpointFindNextErasedBlock(dev); - dev->checkpointCurrentChunk = 0; - } - -- if(dev->checkpointCurrentBlock < 0) -+ if (dev->checkpointCurrentBlock < 0) - return 0; - - tags.chunkDeleted = 0; -@@ -210,10 +203,10 @@ static int yaffs_CheckpointFlushBuffer(y - tags.chunkId = dev->checkpointPageSequence + 1; - tags.sequenceNumber = YAFFS_SEQUENCE_CHECKPOINT_DATA; - tags.byteCount = dev->nDataBytesPerChunk; -- if(dev->checkpointCurrentChunk == 0){ -+ if (dev->checkpointCurrentChunk == 0) { - /* First chunk we write for the block? Set block state to - checkpoint */ -- yaffs_BlockInfo *bi = yaffs_GetBlockInfo(dev,dev->checkpointCurrentBlock); -+ yaffs_BlockInfo *bi = yaffs_GetBlockInfo(dev, dev->checkpointCurrentBlock); - bi->blockState = YAFFS_BLOCK_STATE_CHECKPOINT; - dev->blocksInCheckpoint++; - } -@@ -221,28 +214,29 @@ static int yaffs_CheckpointFlushBuffer(y - chunk = dev->checkpointCurrentBlock * dev->nChunksPerBlock + dev->checkpointCurrentChunk; - - -- T(YAFFS_TRACE_CHECKPOINT,(TSTR("checkpoint wite buffer nand %d(%d:%d) objid %d chId %d" TENDSTR), -- chunk, dev->checkpointCurrentBlock, dev->checkpointCurrentChunk,tags.objectId,tags.chunkId)); -+ T(YAFFS_TRACE_CHECKPOINT, (TSTR("checkpoint wite buffer nand %d(%d:%d) objid %d chId %d" TENDSTR), -+ chunk, dev->checkpointCurrentBlock, dev->checkpointCurrentChunk, tags.objectId, tags.chunkId)); - - realignedChunk = chunk - dev->chunkOffset; - -- dev->writeChunkWithTagsToNAND(dev,realignedChunk,dev->checkpointBuffer,&tags); -+ dev->writeChunkWithTagsToNAND(dev, realignedChunk, -+ dev->checkpointBuffer, &tags); - dev->checkpointByteOffset = 0; - dev->checkpointPageSequence++; - dev->checkpointCurrentChunk++; -- if(dev->checkpointCurrentChunk >= dev->nChunksPerBlock){ -+ if (dev->checkpointCurrentChunk >= dev->nChunksPerBlock) { - dev->checkpointCurrentChunk = 0; - dev->checkpointCurrentBlock = -1; - } -- memset(dev->checkpointBuffer,0,dev->nDataBytesPerChunk); -+ memset(dev->checkpointBuffer, 0, dev->nDataBytesPerChunk); - - return 1; - } - - --int yaffs_CheckpointWrite(yaffs_Device *dev,const void *data, int nBytes) -+int yaffs_CheckpointWrite(yaffs_Device *dev, const void *data, int nBytes) - { -- int i=0; -+ int i = 0; - int ok = 1; - - -@@ -250,17 +244,14 @@ int yaffs_CheckpointWrite(yaffs_Device * - - - -- if(!dev->checkpointBuffer) -+ if (!dev->checkpointBuffer) - return 0; - -- if(!dev->checkpointOpenForWrite) -+ if (!dev->checkpointOpenForWrite) - return -1; - -- while(i < nBytes && ok) { -- -- -- -- dev->checkpointBuffer[dev->checkpointByteOffset] = *dataBytes ; -+ while (i < nBytes && ok) { -+ dev->checkpointBuffer[dev->checkpointByteOffset] = *dataBytes; - dev->checkpointSum += *dataBytes; - dev->checkpointXor ^= *dataBytes; - -@@ -270,18 +261,17 @@ int yaffs_CheckpointWrite(yaffs_Device * - dev->checkpointByteCount++; - - -- if(dev->checkpointByteOffset < 0 || -+ if (dev->checkpointByteOffset < 0 || - dev->checkpointByteOffset >= dev->nDataBytesPerChunk) - ok = yaffs_CheckpointFlushBuffer(dev); -- - } - -- return i; -+ return i; - } - - int yaffs_CheckpointRead(yaffs_Device *dev, void *data, int nBytes) - { -- int i=0; -+ int i = 0; - int ok = 1; - yaffs_ExtendedTags tags; - -@@ -291,52 +281,54 @@ int yaffs_CheckpointRead(yaffs_Device *d - - __u8 *dataBytes = (__u8 *)data; - -- if(!dev->checkpointBuffer) -+ if (!dev->checkpointBuffer) - return 0; - -- if(dev->checkpointOpenForWrite) -+ if (dev->checkpointOpenForWrite) - return -1; - -- while(i < nBytes && ok) { -+ while (i < nBytes && ok) { - - -- if(dev->checkpointByteOffset < 0 || -- dev->checkpointByteOffset >= dev->nDataBytesPerChunk) { -+ if (dev->checkpointByteOffset < 0 || -+ dev->checkpointByteOffset >= dev->nDataBytesPerChunk) { - -- if(dev->checkpointCurrentBlock < 0){ -+ if (dev->checkpointCurrentBlock < 0) { - yaffs_CheckpointFindNextCheckpointBlock(dev); - dev->checkpointCurrentChunk = 0; - } - -- if(dev->checkpointCurrentBlock < 0) -+ if (dev->checkpointCurrentBlock < 0) - ok = 0; - else { -- -- chunk = dev->checkpointCurrentBlock * dev->nChunksPerBlock + -- dev->checkpointCurrentChunk; -+ chunk = dev->checkpointCurrentBlock * -+ dev->nChunksPerBlock + -+ dev->checkpointCurrentChunk; - - realignedChunk = chunk - dev->chunkOffset; - -- /* read in the next chunk */ -- /* printf("read checkpoint page %d\n",dev->checkpointPage); */ -- dev->readChunkWithTagsFromNAND(dev, realignedChunk, -- dev->checkpointBuffer, -- &tags); -- -- if(tags.chunkId != (dev->checkpointPageSequence + 1) || -- tags.sequenceNumber != YAFFS_SEQUENCE_CHECKPOINT_DATA) -- ok = 0; -+ /* read in the next chunk */ -+ /* printf("read checkpoint page %d\n",dev->checkpointPage); */ -+ dev->readChunkWithTagsFromNAND(dev, -+ realignedChunk, -+ dev->checkpointBuffer, -+ &tags); -+ -+ if (tags.chunkId != (dev->checkpointPageSequence + 1) || -+ tags.eccResult > YAFFS_ECC_RESULT_FIXED || -+ tags.sequenceNumber != YAFFS_SEQUENCE_CHECKPOINT_DATA) -+ ok = 0; - - dev->checkpointByteOffset = 0; - dev->checkpointPageSequence++; - dev->checkpointCurrentChunk++; - -- if(dev->checkpointCurrentChunk >= dev->nChunksPerBlock) -+ if (dev->checkpointCurrentChunk >= dev->nChunksPerBlock) - dev->checkpointCurrentBlock = -1; - } - } - -- if(ok){ -+ if (ok) { - *dataBytes = dev->checkpointBuffer[dev->checkpointByteOffset]; - dev->checkpointSum += *dataBytes; - dev->checkpointXor ^= *dataBytes; -@@ -353,17 +345,17 @@ int yaffs_CheckpointRead(yaffs_Device *d - int yaffs_CheckpointClose(yaffs_Device *dev) - { - -- if(dev->checkpointOpenForWrite){ -- if(dev->checkpointByteOffset != 0) -+ if (dev->checkpointOpenForWrite) { -+ if (dev->checkpointByteOffset != 0) - yaffs_CheckpointFlushBuffer(dev); - } else { - int i; -- for(i = 0; i < dev->blocksInCheckpoint && dev->checkpointBlockList[i] >= 0; i++){ -- yaffs_BlockInfo *bi = yaffs_GetBlockInfo(dev,dev->checkpointBlockList[i]); -- if(bi->blockState == YAFFS_BLOCK_STATE_EMPTY) -+ for (i = 0; i < dev->blocksInCheckpoint && dev->checkpointBlockList[i] >= 0; i++) { -+ yaffs_BlockInfo *bi = yaffs_GetBlockInfo(dev, dev->checkpointBlockList[i]); -+ if (bi->blockState == YAFFS_BLOCK_STATE_EMPTY) - bi->blockState = YAFFS_BLOCK_STATE_CHECKPOINT; - else { -- // Todo this looks odd... -+ /* Todo this looks odd... */ - } - } - YFREE(dev->checkpointBlockList); -@@ -374,27 +366,25 @@ int yaffs_CheckpointClose(yaffs_Device * - dev->nErasedBlocks -= dev->blocksInCheckpoint; - - -- T(YAFFS_TRACE_CHECKPOINT,(TSTR("checkpoint byte count %d" TENDSTR), -+ T(YAFFS_TRACE_CHECKPOINT, (TSTR("checkpoint byte count %d" TENDSTR), - dev->checkpointByteCount)); - -- if(dev->checkpointBuffer){ -+ if (dev->checkpointBuffer) { - /* free the buffer */ - YFREE(dev->checkpointBuffer); - dev->checkpointBuffer = NULL; - return 1; -- } -- else -+ } else - return 0; -- - } - - int yaffs_CheckpointInvalidateStream(yaffs_Device *dev) - { - /* Erase the first checksum block */ - -- T(YAFFS_TRACE_CHECKPOINT,(TSTR("checkpoint invalidate"TENDSTR))); -+ T(YAFFS_TRACE_CHECKPOINT, (TSTR("checkpoint invalidate"TENDSTR))); - -- if(!yaffs_CheckpointSpaceOk(dev)) -+ if (!yaffs_CheckpointSpaceOk(dev)) - return 0; - - return yaffs_CheckpointErase(dev); ---- a/fs/yaffs2/yaffs_checkptrw.h -+++ b/fs/yaffs2/yaffs_checkptrw.h -@@ -20,9 +20,9 @@ - - int yaffs_CheckpointOpen(yaffs_Device *dev, int forWriting); - --int yaffs_CheckpointWrite(yaffs_Device *dev,const void *data, int nBytes); -+int yaffs_CheckpointWrite(yaffs_Device *dev, const void *data, int nBytes); - --int yaffs_CheckpointRead(yaffs_Device *dev,void *data, int nBytes); -+int yaffs_CheckpointRead(yaffs_Device *dev, void *data, int nBytes); - - int yaffs_GetCheckpointSum(yaffs_Device *dev, __u32 *sum); - ---- a/fs/yaffs2/yaffs_ecc.c -+++ b/fs/yaffs2/yaffs_ecc.c -@@ -29,7 +29,7 @@ - */ - - const char *yaffs_ecc_c_version = -- "$Id: yaffs_ecc.c,v 1.9 2007-02-14 01:09:06 wookey Exp $"; -+ "$Id: yaffs_ecc.c,v 1.11 2009-03-06 17:20:50 wookey Exp $"; - - #include "yportenv.h" - -@@ -109,12 +109,10 @@ void yaffs_ECCCalculate(const unsigned c - b = column_parity_table[*data++]; - col_parity ^= b; - -- if (b & 0x01) // odd number of bits in the byte -- { -+ if (b & 0x01) { /* odd number of bits in the byte */ - line_parity ^= i; - line_parity_prime ^= ~i; - } -- - } - - ecc[2] = (~col_parity) | 0x03; -@@ -158,7 +156,7 @@ void yaffs_ECCCalculate(const unsigned c - ecc[0] = ~t; - - #ifdef CONFIG_YAFFS_ECC_WRONG_ORDER -- // Swap the bytes into the wrong order -+ /* Swap the bytes into the wrong order */ - t = ecc[0]; - ecc[0] = ecc[1]; - ecc[1] = t; -@@ -189,7 +187,7 @@ int yaffs_ECCCorrect(unsigned char *data - unsigned bit; - - #ifdef CONFIG_YAFFS_ECC_WRONG_ORDER -- // swap the bytes to correct for the wrong order -+ /* swap the bytes to correct for the wrong order */ - unsigned char t; - - t = d0; -@@ -251,7 +249,7 @@ int yaffs_ECCCorrect(unsigned char *data - * ECCxxxOther does ECC calcs on arbitrary n bytes of data - */ - void yaffs_ECCCalculateOther(const unsigned char *data, unsigned nBytes, -- yaffs_ECCOther * eccOther) -+ yaffs_ECCOther *eccOther) - { - unsigned int i; - -@@ -278,8 +276,8 @@ void yaffs_ECCCalculateOther(const unsig - } - - int yaffs_ECCCorrectOther(unsigned char *data, unsigned nBytes, -- yaffs_ECCOther * read_ecc, -- const yaffs_ECCOther * test_ecc) -+ yaffs_ECCOther *read_ecc, -+ const yaffs_ECCOther *test_ecc) - { - unsigned char cDelta; /* column parity delta */ - unsigned lDelta; /* line parity delta */ -@@ -294,8 +292,7 @@ int yaffs_ECCCorrectOther(unsigned char - return 0; /* no error */ - - if (lDelta == ~lDeltaPrime && -- (((cDelta ^ (cDelta >> 1)) & 0x15) == 0x15)) -- { -+ (((cDelta ^ (cDelta >> 1)) & 0x15) == 0x15)) { - /* Single bit (recoverable) error in data */ - - bit = 0; -@@ -307,7 +304,7 @@ int yaffs_ECCCorrectOther(unsigned char - if (cDelta & 0x02) - bit |= 0x01; - -- if(lDelta >= nBytes) -+ if (lDelta >= nBytes) - return -1; - - data[lDelta] ^= (1 << bit); -@@ -316,7 +313,7 @@ int yaffs_ECCCorrectOther(unsigned char - } - - if ((yaffs_CountBits32(lDelta) + yaffs_CountBits32(lDeltaPrime) + -- yaffs_CountBits(cDelta)) == 1) { -+ yaffs_CountBits(cDelta)) == 1) { - /* Reccoverable error in ecc */ - - *read_ecc = *test_ecc; -@@ -326,6 +323,4 @@ int yaffs_ECCCorrectOther(unsigned char - /* Unrecoverable error */ - - return -1; -- - } -- ---- a/fs/yaffs2/yaffs_ecc.h -+++ b/fs/yaffs2/yaffs_ecc.h -@@ -13,15 +13,15 @@ - * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL. - */ - -- /* -- * This code implements the ECC algorithm used in SmartMedia. -- * -- * The ECC comprises 22 bits of parity information and is stuffed into 3 bytes. -- * The two unused bit are set to 1. -- * The ECC can correct single bit errors in a 256-byte page of data. Thus, two such ECC -- * blocks are used on a 512-byte NAND page. -- * -- */ -+/* -+ * This code implements the ECC algorithm used in SmartMedia. -+ * -+ * The ECC comprises 22 bits of parity information and is stuffed into 3 bytes. -+ * The two unused bit are set to 1. -+ * The ECC can correct single bit errors in a 256-byte page of data. Thus, two such ECC -+ * blocks are used on a 512-byte NAND page. -+ * -+ */ - - #ifndef __YAFFS_ECC_H__ - #define __YAFFS_ECC_H__ -@@ -34,11 +34,11 @@ typedef struct { - - void yaffs_ECCCalculate(const unsigned char *data, unsigned char *ecc); - int yaffs_ECCCorrect(unsigned char *data, unsigned char *read_ecc, -- const unsigned char *test_ecc); -+ const unsigned char *test_ecc); - - void yaffs_ECCCalculateOther(const unsigned char *data, unsigned nBytes, -- yaffs_ECCOther * ecc); -+ yaffs_ECCOther *ecc); - int yaffs_ECCCorrectOther(unsigned char *data, unsigned nBytes, -- yaffs_ECCOther * read_ecc, -- const yaffs_ECCOther * test_ecc); -+ yaffs_ECCOther *read_ecc, -+ const yaffs_ECCOther *test_ecc); - #endif ---- a/fs/yaffs2/yaffs_fs.c -+++ b/fs/yaffs2/yaffs_fs.c -@@ -1,7 +1,7 @@ - /* - * YAFFS: Yet Another Flash File System. A NAND-flash specific file system. - * -- * Copyright (C) 2002-2007 Aleph One Ltd. -+ * Copyright (C) 2002-2009 Aleph One Ltd. - * for Toby Churchill Ltd and Brightstar Engineering - * - * Created by Charles Manning -@@ -32,18 +32,17 @@ - */ - - const char *yaffs_fs_c_version = -- "$Id: yaffs_fs.c,v 1.63 2007-09-19 20:35:40 imcd Exp $"; -+ "$Id: yaffs_fs.c,v 1.79 2009-03-17 01:12:00 wookey Exp $"; - extern const char *yaffs_guts_c_version; - - #include --#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)) -+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19)) - #include - #endif - #include - #include - #include - #include --#include - #include - #include - #include -@@ -53,10 +52,12 @@ extern const char *yaffs_guts_c_version; - #include - #include - --#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) -+#include "asm/div64.h" -+ -+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0)) - - #include /* Added NCB 15-8-2003 */ --#include -+#include - #define UnlockPage(p) unlock_page(p) - #define Page_Uptodate(page) test_bit(PG_uptodate, &(page)->flags) - -@@ -69,22 +70,45 @@ extern const char *yaffs_guts_c_version; - #define BDEVNAME_SIZE 0 - #define yaffs_devname(sb, buf) kdevname(sb->s_dev) - --#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)) -+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0)) - /* added NCB 26/5/2006 for 2.4.25-vrs2-tcl1 kernel */ - #define __user - #endif - - #endif - --#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) -+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26)) -+#define YPROC_ROOT (&proc_root) -+#else -+#define YPROC_ROOT NULL -+#endif -+ -+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17)) - #define WRITE_SIZE_STR "writesize" --#define WRITE_SIZE(mtd) (mtd)->writesize -+#define WRITE_SIZE(mtd) ((mtd)->writesize) - #else - #define WRITE_SIZE_STR "oobblock" --#define WRITE_SIZE(mtd) (mtd)->oobblock -+#define WRITE_SIZE(mtd) ((mtd)->oobblock) - #endif - --#include -+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 27)) -+#define YAFFS_USE_WRITE_BEGIN_END 1 -+#else -+#define YAFFS_USE_WRITE_BEGIN_END 0 -+#endif -+ -+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 28)) -+static uint32_t YCALCBLOCKS(uint64_t partition_size, uint32_t block_size) -+{ -+ uint64_t result = partition_size; -+ do_div(result, block_size); -+ return (uint32_t)result; -+} -+#else -+#define YCALCBLOCKS(s, b) ((s)/(b)) -+#endif -+ -+#include - - #include "yportenv.h" - #include "yaffs_guts.h" -@@ -96,28 +120,44 @@ extern const char *yaffs_guts_c_version; - - unsigned int yaffs_traceMask = YAFFS_TRACE_BAD_BLOCKS; - unsigned int yaffs_wr_attempts = YAFFS_WR_ATTEMPTS; -+unsigned int yaffs_auto_checkpoint = 1; - - /* Module Parameters */ --#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) --module_param(yaffs_traceMask,uint,0644); --module_param(yaffs_wr_attempts,uint,0644); -+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0)) -+module_param(yaffs_traceMask, uint, 0644); -+module_param(yaffs_wr_attempts, uint, 0644); -+module_param(yaffs_auto_checkpoint, uint, 0644); -+#else -+MODULE_PARM(yaffs_traceMask, "i"); -+MODULE_PARM(yaffs_wr_attempts, "i"); -+MODULE_PARM(yaffs_auto_checkpoint, "i"); -+#endif -+ -+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 25)) -+/* use iget and read_inode */ -+#define Y_IGET(sb, inum) iget((sb), (inum)) -+static void yaffs_read_inode(struct inode *inode); -+ - #else --MODULE_PARM(yaffs_traceMask,"i"); --MODULE_PARM(yaffs_wr_attempts,"i"); -+/* Call local equivalent */ -+#define YAFFS_USE_OWN_IGET -+#define Y_IGET(sb, inum) yaffs_iget((sb), (inum)) -+ -+static struct inode *yaffs_iget(struct super_block *sb, unsigned long ino); - #endif - - /*#define T(x) printk x */ - --#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,18)) --#define yaffs_InodeToObjectLV(iptr) (iptr)->i_private -+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 18)) -+#define yaffs_InodeToObjectLV(iptr) ((iptr)->i_private) - #else --#define yaffs_InodeToObjectLV(iptr) (iptr)->u.generic_ip -+#define yaffs_InodeToObjectLV(iptr) ((iptr)->u.generic_ip) - #endif - - #define yaffs_InodeToObject(iptr) ((yaffs_Object *)(yaffs_InodeToObjectLV(iptr))) - #define yaffs_DentryToObject(dptr) yaffs_InodeToObject((dptr)->d_inode) - --#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) -+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0)) - #define yaffs_SuperToDevice(sb) ((yaffs_Device *)sb->s_fs_info) - #else - #define yaffs_SuperToDevice(sb) ((yaffs_Device *)sb->u.generic_sbp) -@@ -126,47 +166,49 @@ MODULE_PARM(yaffs_wr_attempts,"i"); - static void yaffs_put_super(struct super_block *sb); - - static ssize_t yaffs_file_write(struct file *f, const char *buf, size_t n, -- loff_t * pos); -+ loff_t *pos); -+static ssize_t yaffs_hold_space(struct file *f); -+static void yaffs_release_space(struct file *f); - --#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) -+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17)) - static int yaffs_file_flush(struct file *file, fl_owner_t id); - #else - static int yaffs_file_flush(struct file *file); - #endif - - static int yaffs_sync_object(struct file *file, struct dentry *dentry, -- int datasync); -+ int datasync); - - static int yaffs_readdir(struct file *f, void *dirent, filldir_t filldir); - --#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) -+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0)) - static int yaffs_create(struct inode *dir, struct dentry *dentry, int mode, - struct nameidata *n); - static struct dentry *yaffs_lookup(struct inode *dir, struct dentry *dentry, -- struct nameidata *n); -+ struct nameidata *n); - #else - static int yaffs_create(struct inode *dir, struct dentry *dentry, int mode); - static struct dentry *yaffs_lookup(struct inode *dir, struct dentry *dentry); - #endif - static int yaffs_link(struct dentry *old_dentry, struct inode *dir, -- struct dentry *dentry); -+ struct dentry *dentry); - static int yaffs_unlink(struct inode *dir, struct dentry *dentry); - static int yaffs_symlink(struct inode *dir, struct dentry *dentry, -- const char *symname); -+ const char *symname); - static int yaffs_mkdir(struct inode *dir, struct dentry *dentry, int mode); - --#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) -+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0)) - static int yaffs_mknod(struct inode *dir, struct dentry *dentry, int mode, -- dev_t dev); -+ dev_t dev); - #else - static int yaffs_mknod(struct inode *dir, struct dentry *dentry, int mode, -- int dev); -+ int dev); - #endif - static int yaffs_rename(struct inode *old_dir, struct dentry *old_dentry, - struct inode *new_dir, struct dentry *new_dentry); - static int yaffs_setattr(struct dentry *dentry, struct iattr *attr); - --#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) -+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17)) - static int yaffs_sync_fs(struct super_block *sb, int wait); - static void yaffs_write_super(struct super_block *sb); - #else -@@ -174,33 +216,47 @@ static int yaffs_sync_fs(struct super_bl - static int yaffs_write_super(struct super_block *sb); - #endif - --#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) -+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17)) - static int yaffs_statfs(struct dentry *dentry, struct kstatfs *buf); --#elif (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) -+#elif (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0)) - static int yaffs_statfs(struct super_block *sb, struct kstatfs *buf); - #else - static int yaffs_statfs(struct super_block *sb, struct statfs *buf); - #endif --static void yaffs_read_inode(struct inode *inode); - -+#ifdef YAFFS_HAS_PUT_INODE - static void yaffs_put_inode(struct inode *inode); -+#endif -+ - static void yaffs_delete_inode(struct inode *); - static void yaffs_clear_inode(struct inode *); - - static int yaffs_readpage(struct file *file, struct page *page); --#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) -+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0)) - static int yaffs_writepage(struct page *page, struct writeback_control *wbc); - #else - static int yaffs_writepage(struct page *page); - #endif -+ -+ -+#if (YAFFS_USE_WRITE_BEGIN_END != 0) -+static int yaffs_write_begin(struct file *filp, struct address_space *mapping, -+ loff_t pos, unsigned len, unsigned flags, -+ struct page **pagep, void **fsdata); -+static int yaffs_write_end(struct file *filp, struct address_space *mapping, -+ loff_t pos, unsigned len, unsigned copied, -+ struct page *pg, void *fsdadata); -+#else - static int yaffs_prepare_write(struct file *f, struct page *pg, -- unsigned offset, unsigned to); -+ unsigned offset, unsigned to); - static int yaffs_commit_write(struct file *f, struct page *pg, unsigned offset, -- unsigned to); -+ unsigned to); - --static int yaffs_readlink(struct dentry *dentry, char __user * buffer, -- int buflen); --#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,13)) -+#endif -+ -+static int yaffs_readlink(struct dentry *dentry, char __user *buffer, -+ int buflen); -+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 13)) - static void *yaffs_follow_link(struct dentry *dentry, struct nameidata *nd); - #else - static int yaffs_follow_link(struct dentry *dentry, struct nameidata *nd); -@@ -209,12 +265,17 @@ static int yaffs_follow_link(struct dent - static struct address_space_operations yaffs_file_address_operations = { - .readpage = yaffs_readpage, - .writepage = yaffs_writepage, -+#if (YAFFS_USE_WRITE_BEGIN_END > 0) -+ .write_begin = yaffs_write_begin, -+ .write_end = yaffs_write_end, -+#else - .prepare_write = yaffs_prepare_write, - .commit_write = yaffs_commit_write, -+#endif - }; - --#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,22)) --static struct file_operations yaffs_file_operations = { -+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 22)) -+static const struct file_operations yaffs_file_operations = { - .read = do_sync_read, - .write = do_sync_write, - .aio_read = generic_file_aio_read, -@@ -224,11 +285,12 @@ static struct file_operations yaffs_file - .fsync = yaffs_sync_object, - .splice_read = generic_file_splice_read, - .splice_write = generic_file_splice_write, -+ .llseek = generic_file_llseek, - }; - --#elif (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,18)) -+#elif (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 18)) - --static struct file_operations yaffs_file_operations = { -+static const struct file_operations yaffs_file_operations = { - .read = do_sync_read, - .write = do_sync_write, - .aio_read = generic_file_aio_read, -@@ -241,29 +303,29 @@ static struct file_operations yaffs_file - - #else - --static struct file_operations yaffs_file_operations = { -+static const struct file_operations yaffs_file_operations = { - .read = generic_file_read, - .write = generic_file_write, - .mmap = generic_file_mmap, - .flush = yaffs_file_flush, - .fsync = yaffs_sync_object, --#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) -+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0)) - .sendfile = generic_file_sendfile, - #endif - }; - #endif - --static struct inode_operations yaffs_file_inode_operations = { -+static const struct inode_operations yaffs_file_inode_operations = { - .setattr = yaffs_setattr, - }; - --static struct inode_operations yaffs_symlink_inode_operations = { -+static const struct inode_operations yaffs_symlink_inode_operations = { - .readlink = yaffs_readlink, - .follow_link = yaffs_follow_link, - .setattr = yaffs_setattr, - }; - --static struct inode_operations yaffs_dir_inode_operations = { -+static const struct inode_operations yaffs_dir_inode_operations = { - .create = yaffs_create, - .lookup = yaffs_lookup, - .link = yaffs_link, -@@ -276,16 +338,21 @@ static struct inode_operations yaffs_dir - .setattr = yaffs_setattr, - }; - --static struct file_operations yaffs_dir_operations = { -+static const struct file_operations yaffs_dir_operations = { - .read = generic_read_dir, - .readdir = yaffs_readdir, - .fsync = yaffs_sync_object, - }; - --static struct super_operations yaffs_super_ops = { -+static const struct super_operations yaffs_super_ops = { - .statfs = yaffs_statfs, -+ -+#ifndef YAFFS_USE_OWN_IGET - .read_inode = yaffs_read_inode, -+#endif -+#ifdef YAFFS_HAS_PUT_INODE - .put_inode = yaffs_put_inode, -+#endif - .put_super = yaffs_put_super, - .delete_inode = yaffs_delete_inode, - .clear_inode = yaffs_clear_inode, -@@ -293,22 +360,21 @@ static struct super_operations yaffs_sup - .write_super = yaffs_write_super, - }; - --static void yaffs_GrossLock(yaffs_Device * dev) -+static void yaffs_GrossLock(yaffs_Device *dev) - { -- T(YAFFS_TRACE_OS, (KERN_DEBUG "yaffs locking\n")); -- -+ T(YAFFS_TRACE_OS, ("yaffs locking %p\n", current)); - down(&dev->grossLock); -+ T(YAFFS_TRACE_OS, ("yaffs locked %p\n", current)); - } - --static void yaffs_GrossUnlock(yaffs_Device * dev) -+static void yaffs_GrossUnlock(yaffs_Device *dev) - { -- T(YAFFS_TRACE_OS, (KERN_DEBUG "yaffs unlocking\n")); -+ T(YAFFS_TRACE_OS, ("yaffs unlocking %p\n", current)); - up(&dev->grossLock); -- - } - --static int yaffs_readlink(struct dentry *dentry, char __user * buffer, -- int buflen) -+static int yaffs_readlink(struct dentry *dentry, char __user *buffer, -+ int buflen) - { - unsigned char *alias; - int ret; -@@ -329,7 +395,7 @@ static int yaffs_readlink(struct dentry - return ret; - } - --#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,13)) -+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 13)) - static void *yaffs_follow_link(struct dentry *dentry, struct nameidata *nd) - #else - static int yaffs_follow_link(struct dentry *dentry, struct nameidata *nd) -@@ -345,32 +411,31 @@ static int yaffs_follow_link(struct dent - - yaffs_GrossUnlock(dev); - -- if (!alias) -- { -+ if (!alias) { - ret = -ENOMEM; - goto out; -- } -+ } - - ret = vfs_follow_link(nd, alias); - kfree(alias); - out: --#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,13)) -- return ERR_PTR (ret); -+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 13)) -+ return ERR_PTR(ret); - #else - return ret; - #endif - } - - struct inode *yaffs_get_inode(struct super_block *sb, int mode, int dev, -- yaffs_Object * obj); -+ yaffs_Object *obj); - - /* - * Lookup is used to find objects in the fs - */ --#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) -+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0)) - - static struct dentry *yaffs_lookup(struct inode *dir, struct dentry *dentry, -- struct nameidata *n) -+ struct nameidata *n) - #else - static struct dentry *yaffs_lookup(struct inode *dir, struct dentry *dentry) - #endif -@@ -383,12 +448,11 @@ static struct dentry *yaffs_lookup(struc - yaffs_GrossLock(dev); - - T(YAFFS_TRACE_OS, -- (KERN_DEBUG "yaffs_lookup for %d:%s\n", -- yaffs_InodeToObject(dir)->objectId, dentry->d_name.name)); -+ ("yaffs_lookup for %d:%s\n", -+ yaffs_InodeToObject(dir)->objectId, dentry->d_name.name)); - -- obj = -- yaffs_FindObjectByName(yaffs_InodeToObject(dir), -- dentry->d_name.name); -+ obj = yaffs_FindObjectByName(yaffs_InodeToObject(dir), -+ dentry->d_name.name); - - obj = yaffs_GetEquivalentObject(obj); /* in case it was a hardlink */ - -@@ -397,13 +461,13 @@ static struct dentry *yaffs_lookup(struc - - if (obj) { - T(YAFFS_TRACE_OS, -- (KERN_DEBUG "yaffs_lookup found %d\n", obj->objectId)); -+ ("yaffs_lookup found %d\n", obj->objectId)); - - inode = yaffs_get_inode(dir->i_sb, obj->yst_mode, 0, obj); - - if (inode) { - T(YAFFS_TRACE_OS, -- (KERN_DEBUG "yaffs_loookup dentry \n")); -+ ("yaffs_loookup dentry \n")); - /* #if 0 asserted by NCB for 2.5/6 compatability - falls through to - * d_add even if NULL inode */ - #if 0 -@@ -416,7 +480,7 @@ static struct dentry *yaffs_lookup(struc - } - - } else { -- T(YAFFS_TRACE_OS, (KERN_DEBUG "yaffs_lookup not found\n")); -+ T(YAFFS_TRACE_OS, ("yaffs_lookup not found\n")); - - } - -@@ -425,20 +489,22 @@ static struct dentry *yaffs_lookup(struc - d_add(dentry, inode); - - return NULL; -- /* return (ERR_PTR(-EIO)); */ -- - } - -+ -+#ifdef YAFFS_HAS_PUT_INODE -+ - /* For now put inode is just for debugging - * Put inode is called when the inode **structure** is put. - */ - static void yaffs_put_inode(struct inode *inode) - { - T(YAFFS_TRACE_OS, -- ("yaffs_put_inode: ino %d, count %d\n", (int)inode->i_ino, -- atomic_read(&inode->i_count))); -+ ("yaffs_put_inode: ino %d, count %d\n", (int)inode->i_ino, -+ atomic_read(&inode->i_count))); - - } -+#endif - - /* clear is called to tell the fs to release any per-inode data it holds */ - static void yaffs_clear_inode(struct inode *inode) -@@ -449,9 +515,9 @@ static void yaffs_clear_inode(struct ino - obj = yaffs_InodeToObject(inode); - - T(YAFFS_TRACE_OS, -- ("yaffs_clear_inode: ino %d, count %d %s\n", (int)inode->i_ino, -- atomic_read(&inode->i_count), -- obj ? "object exists" : "null object")); -+ ("yaffs_clear_inode: ino %d, count %d %s\n", (int)inode->i_ino, -+ atomic_read(&inode->i_count), -+ obj ? "object exists" : "null object")); - - if (obj) { - dev = obj->myDev; -@@ -486,23 +552,23 @@ static void yaffs_delete_inode(struct in - yaffs_Device *dev; - - T(YAFFS_TRACE_OS, -- ("yaffs_delete_inode: ino %d, count %d %s\n", (int)inode->i_ino, -- atomic_read(&inode->i_count), -- obj ? "object exists" : "null object")); -+ ("yaffs_delete_inode: ino %d, count %d %s\n", (int)inode->i_ino, -+ atomic_read(&inode->i_count), -+ obj ? "object exists" : "null object")); - - if (obj) { - dev = obj->myDev; - yaffs_GrossLock(dev); -- yaffs_DeleteFile(obj); -+ yaffs_DeleteObject(obj); - yaffs_GrossUnlock(dev); - } --#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,13)) -- truncate_inode_pages (&inode->i_data, 0); -+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 13)) -+ truncate_inode_pages(&inode->i_data, 0); - #endif - clear_inode(inode); - } - --#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) -+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17)) - static int yaffs_file_flush(struct file *file, fl_owner_t id) - #else - static int yaffs_file_flush(struct file *file) -@@ -513,8 +579,8 @@ static int yaffs_file_flush(struct file - yaffs_Device *dev = obj->myDev; - - T(YAFFS_TRACE_OS, -- (KERN_DEBUG "yaffs_file_flush object %d (%s)\n", obj->objectId, -- obj->dirty ? "dirty" : "clean")); -+ ("yaffs_file_flush object %d (%s)\n", obj->objectId, -+ obj->dirty ? "dirty" : "clean")); - - yaffs_GrossLock(dev); - -@@ -535,15 +601,15 @@ static int yaffs_readpage_nolock(struct - - yaffs_Device *dev; - -- T(YAFFS_TRACE_OS, (KERN_DEBUG "yaffs_readpage at %08x, size %08x\n", -- (unsigned)(pg->index << PAGE_CACHE_SHIFT), -- (unsigned)PAGE_CACHE_SIZE)); -+ T(YAFFS_TRACE_OS, ("yaffs_readpage at %08x, size %08x\n", -+ (unsigned)(pg->index << PAGE_CACHE_SHIFT), -+ (unsigned)PAGE_CACHE_SIZE)); - - obj = yaffs_DentryToObject(f->f_dentry); - - dev = obj->myDev; - --#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) -+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0)) - BUG_ON(!PageLocked(pg)); - #else - if (!PageLocked(pg)) -@@ -555,9 +621,9 @@ static int yaffs_readpage_nolock(struct - - yaffs_GrossLock(dev); - -- ret = -- yaffs_ReadDataFromFile(obj, pg_buf, pg->index << PAGE_CACHE_SHIFT, -- PAGE_CACHE_SIZE); -+ ret = yaffs_ReadDataFromFile(obj, pg_buf, -+ pg->index << PAGE_CACHE_SHIFT, -+ PAGE_CACHE_SIZE); - - yaffs_GrossUnlock(dev); - -@@ -575,7 +641,7 @@ static int yaffs_readpage_nolock(struct - flush_dcache_page(pg); - kunmap(pg); - -- T(YAFFS_TRACE_OS, (KERN_DEBUG "yaffs_readpage done\n")); -+ T(YAFFS_TRACE_OS, ("yaffs_readpage done\n")); - return ret; - } - -@@ -593,7 +659,7 @@ static int yaffs_readpage(struct file *f - - /* writepage inspired by/stolen from smbfs */ - --#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) -+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0)) - static int yaffs_writepage(struct page *page, struct writeback_control *wbc) - #else - static int yaffs_writepage(struct page *page) -@@ -616,12 +682,11 @@ static int yaffs_writepage(struct page * - - if (offset > inode->i_size) { - T(YAFFS_TRACE_OS, -- (KERN_DEBUG -- "yaffs_writepage at %08x, inode size = %08x!!!\n", -- (unsigned)(page->index << PAGE_CACHE_SHIFT), -- (unsigned)inode->i_size)); -+ ("yaffs_writepage at %08x, inode size = %08x!!!\n", -+ (unsigned)(page->index << PAGE_CACHE_SHIFT), -+ (unsigned)inode->i_size)); - T(YAFFS_TRACE_OS, -- (KERN_DEBUG " -> don't care!!\n")); -+ (" -> don't care!!\n")); - unlock_page(page); - return 0; - } -@@ -629,11 +694,10 @@ static int yaffs_writepage(struct page * - end_index = inode->i_size >> PAGE_CACHE_SHIFT; - - /* easy case */ -- if (page->index < end_index) { -+ if (page->index < end_index) - nBytes = PAGE_CACHE_SIZE; -- } else { -+ else - nBytes = inode->i_size & (PAGE_CACHE_SIZE - 1); -- } - - get_page(page); - -@@ -643,19 +707,18 @@ static int yaffs_writepage(struct page * - yaffs_GrossLock(obj->myDev); - - T(YAFFS_TRACE_OS, -- (KERN_DEBUG "yaffs_writepage at %08x, size %08x\n", -- (unsigned)(page->index << PAGE_CACHE_SHIFT), nBytes)); -+ ("yaffs_writepage at %08x, size %08x\n", -+ (unsigned)(page->index << PAGE_CACHE_SHIFT), nBytes)); - T(YAFFS_TRACE_OS, -- (KERN_DEBUG "writepag0: obj = %05x, ino = %05x\n", -- (int)obj->variant.fileVariant.fileSize, (int)inode->i_size)); -+ ("writepag0: obj = %05x, ino = %05x\n", -+ (int)obj->variant.fileVariant.fileSize, (int)inode->i_size)); - -- nWritten = -- yaffs_WriteDataToFile(obj, buffer, page->index << PAGE_CACHE_SHIFT, -- nBytes, 0); -+ nWritten = yaffs_WriteDataToFile(obj, buffer, -+ page->index << PAGE_CACHE_SHIFT, nBytes, 0); - - T(YAFFS_TRACE_OS, -- (KERN_DEBUG "writepag1: obj = %05x, ino = %05x\n", -- (int)obj->variant.fileVariant.fileSize, (int)inode->i_size)); -+ ("writepag1: obj = %05x, ino = %05x\n", -+ (int)obj->variant.fileVariant.fileSize, (int)inode->i_size)); - - yaffs_GrossUnlock(obj->myDev); - -@@ -667,100 +730,207 @@ static int yaffs_writepage(struct page * - return (nWritten == nBytes) ? 0 : -ENOSPC; - } - -+ -+#if (YAFFS_USE_WRITE_BEGIN_END > 0) -+static int yaffs_write_begin(struct file *filp, struct address_space *mapping, -+ loff_t pos, unsigned len, unsigned flags, -+ struct page **pagep, void **fsdata) -+{ -+ struct page *pg = NULL; -+ pgoff_t index = pos >> PAGE_CACHE_SHIFT; -+ uint32_t offset = pos & (PAGE_CACHE_SIZE - 1); -+ uint32_t to = offset + len; -+ -+ int ret = 0; -+ int space_held = 0; -+ -+ T(YAFFS_TRACE_OS, ("start yaffs_write_begin\n")); -+ /* Get a page */ -+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 28) -+ pg = grab_cache_page_write_begin(mapping, index, flags); -+#else -+ pg = __grab_cache_page(mapping, index); -+#endif -+ -+ *pagep = pg; -+ if (!pg) { -+ ret = -ENOMEM; -+ goto out; -+ } -+ /* Get fs space */ -+ space_held = yaffs_hold_space(filp); -+ -+ if (!space_held) { -+ ret = -ENOSPC; -+ goto out; -+ } -+ -+ /* Update page if required */ -+ -+ if (!Page_Uptodate(pg) && (offset || to < PAGE_CACHE_SIZE)) -+ ret = yaffs_readpage_nolock(filp, pg); -+ -+ if (ret) -+ goto out; -+ -+ /* Happy path return */ -+ T(YAFFS_TRACE_OS, ("end yaffs_write_begin - ok\n")); -+ -+ return 0; -+ -+out: -+ T(YAFFS_TRACE_OS, ("end yaffs_write_begin fail returning %d\n", ret)); -+ if (space_held) -+ yaffs_release_space(filp); -+ if (pg) { -+ unlock_page(pg); -+ page_cache_release(pg); -+ } -+ return ret; -+} -+ -+#else -+ - static int yaffs_prepare_write(struct file *f, struct page *pg, -- unsigned offset, unsigned to) -+ unsigned offset, unsigned to) - { -+ T(YAFFS_TRACE_OS, ("yaffs_prepair_write\n")); - -- T(YAFFS_TRACE_OS, (KERN_DEBUG "yaffs_prepair_write\n")); - if (!Page_Uptodate(pg) && (offset || to < PAGE_CACHE_SIZE)) - return yaffs_readpage_nolock(f, pg); -- - return 0; -+} -+#endif -+ -+#if (YAFFS_USE_WRITE_BEGIN_END > 0) -+static int yaffs_write_end(struct file *filp, struct address_space *mapping, -+ loff_t pos, unsigned len, unsigned copied, -+ struct page *pg, void *fsdadata) -+{ -+ int ret = 0; -+ void *addr, *kva; -+ uint32_t offset_into_page = pos & (PAGE_CACHE_SIZE - 1); -+ -+ kva = kmap(pg); -+ addr = kva + offset_into_page; -+ -+ T(YAFFS_TRACE_OS, -+ ("yaffs_write_end addr %x pos %x nBytes %d\n", -+ (unsigned) addr, -+ (int)pos, copied)); -+ -+ ret = yaffs_file_write(filp, addr, copied, &pos); -+ -+ if (ret != copied) { -+ T(YAFFS_TRACE_OS, -+ ("yaffs_write_end not same size ret %d copied %d\n", -+ ret, copied)); -+ SetPageError(pg); -+ ClearPageUptodate(pg); -+ } else { -+ SetPageUptodate(pg); -+ } -+ -+ kunmap(pg); - -+ yaffs_release_space(filp); -+ unlock_page(pg); -+ page_cache_release(pg); -+ return ret; - } -+#else - - static int yaffs_commit_write(struct file *f, struct page *pg, unsigned offset, -- unsigned to) -+ unsigned to) - { -+ void *addr, *kva; - -- void *addr = page_address(pg) + offset; - loff_t pos = (((loff_t) pg->index) << PAGE_CACHE_SHIFT) + offset; - int nBytes = to - offset; - int nWritten; - - unsigned spos = pos; -- unsigned saddr = (unsigned)addr; -+ unsigned saddr; -+ -+ kva = kmap(pg); -+ addr = kva + offset; -+ -+ saddr = (unsigned) addr; - - T(YAFFS_TRACE_OS, -- (KERN_DEBUG "yaffs_commit_write addr %x pos %x nBytes %d\n", saddr, -- spos, nBytes)); -+ ("yaffs_commit_write addr %x pos %x nBytes %d\n", -+ saddr, spos, nBytes)); - - nWritten = yaffs_file_write(f, addr, nBytes, &pos); - - if (nWritten != nBytes) { - T(YAFFS_TRACE_OS, -- (KERN_DEBUG -- "yaffs_commit_write not same size nWritten %d nBytes %d\n", -- nWritten, nBytes)); -+ ("yaffs_commit_write not same size nWritten %d nBytes %d\n", -+ nWritten, nBytes)); - SetPageError(pg); - ClearPageUptodate(pg); - } else { - SetPageUptodate(pg); - } - -+ kunmap(pg); -+ - T(YAFFS_TRACE_OS, -- (KERN_DEBUG "yaffs_commit_write returning %d\n", -- nWritten == nBytes ? 0 : nWritten)); -+ ("yaffs_commit_write returning %d\n", -+ nWritten == nBytes ? 0 : nWritten)); - - return nWritten == nBytes ? 0 : nWritten; -- - } -+#endif -+ - --static void yaffs_FillInodeFromObject(struct inode *inode, yaffs_Object * obj) -+static void yaffs_FillInodeFromObject(struct inode *inode, yaffs_Object *obj) - { - if (inode && obj) { - - - /* Check mode against the variant type and attempt to repair if broken. */ -- __u32 mode = obj->yst_mode; -- switch( obj->variantType ){ -- case YAFFS_OBJECT_TYPE_FILE : -- if( ! S_ISREG(mode) ){ -- obj->yst_mode &= ~S_IFMT; -- obj->yst_mode |= S_IFREG; -- } -- -- break; -- case YAFFS_OBJECT_TYPE_SYMLINK : -- if( ! S_ISLNK(mode) ){ -- obj->yst_mode &= ~S_IFMT; -- obj->yst_mode |= S_IFLNK; -- } -- -- break; -- case YAFFS_OBJECT_TYPE_DIRECTORY : -- if( ! S_ISDIR(mode) ){ -- obj->yst_mode &= ~S_IFMT; -- obj->yst_mode |= S_IFDIR; -- } -- -- break; -- case YAFFS_OBJECT_TYPE_UNKNOWN : -- case YAFFS_OBJECT_TYPE_HARDLINK : -- case YAFFS_OBJECT_TYPE_SPECIAL : -- default: -- /* TODO? */ -- break; -- } -+ __u32 mode = obj->yst_mode; -+ switch (obj->variantType) { -+ case YAFFS_OBJECT_TYPE_FILE: -+ if (!S_ISREG(mode)) { -+ obj->yst_mode &= ~S_IFMT; -+ obj->yst_mode |= S_IFREG; -+ } -+ -+ break; -+ case YAFFS_OBJECT_TYPE_SYMLINK: -+ if (!S_ISLNK(mode)) { -+ obj->yst_mode &= ~S_IFMT; -+ obj->yst_mode |= S_IFLNK; -+ } -+ -+ break; -+ case YAFFS_OBJECT_TYPE_DIRECTORY: -+ if (!S_ISDIR(mode)) { -+ obj->yst_mode &= ~S_IFMT; -+ obj->yst_mode |= S_IFDIR; -+ } -+ -+ break; -+ case YAFFS_OBJECT_TYPE_UNKNOWN: -+ case YAFFS_OBJECT_TYPE_HARDLINK: -+ case YAFFS_OBJECT_TYPE_SPECIAL: -+ default: -+ /* TODO? */ -+ break; -+ } -+ -+ inode->i_flags |= S_NOATIME; - - inode->i_ino = obj->objectId; - inode->i_mode = obj->yst_mode; - inode->i_uid = obj->yst_uid; - inode->i_gid = obj->yst_gid; --#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)) -+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19)) - inode->i_blksize = inode->i_sb->s_blocksize; - #endif --#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) -+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0)) - - inode->i_rdev = old_decode_dev(obj->yst_rdev); - inode->i_atime.tv_sec = (time_t) (obj->yst_atime); -@@ -781,26 +951,25 @@ static void yaffs_FillInodeFromObject(st - inode->i_nlink = yaffs_GetObjectLinkCount(obj); - - T(YAFFS_TRACE_OS, -- (KERN_DEBUG -- "yaffs_FillInode mode %x uid %d gid %d size %d count %d\n", -- inode->i_mode, inode->i_uid, inode->i_gid, -- (int)inode->i_size, atomic_read(&inode->i_count))); -+ ("yaffs_FillInode mode %x uid %d gid %d size %d count %d\n", -+ inode->i_mode, inode->i_uid, inode->i_gid, -+ (int)inode->i_size, atomic_read(&inode->i_count))); - - switch (obj->yst_mode & S_IFMT) { - default: /* fifo, device or socket */ --#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) -+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0)) - init_special_inode(inode, obj->yst_mode, -- old_decode_dev(obj->yst_rdev)); -+ old_decode_dev(obj->yst_rdev)); - #else - init_special_inode(inode, obj->yst_mode, -- (dev_t) (obj->yst_rdev)); -+ (dev_t) (obj->yst_rdev)); - #endif - break; - case S_IFREG: /* file */ - inode->i_op = &yaffs_file_inode_operations; - inode->i_fop = &yaffs_file_operations; - inode->i_mapping->a_ops = -- &yaffs_file_address_operations; -+ &yaffs_file_address_operations; - break; - case S_IFDIR: /* directory */ - inode->i_op = &yaffs_dir_inode_operations; -@@ -817,34 +986,36 @@ static void yaffs_FillInodeFromObject(st - - } else { - T(YAFFS_TRACE_OS, -- (KERN_DEBUG "yaffs_FileInode invalid parameters\n")); -+ ("yaffs_FileInode invalid parameters\n")); - } - - } - - struct inode *yaffs_get_inode(struct super_block *sb, int mode, int dev, -- yaffs_Object * obj) -+ yaffs_Object *obj) - { - struct inode *inode; - - if (!sb) { - T(YAFFS_TRACE_OS, -- (KERN_DEBUG "yaffs_get_inode for NULL super_block!!\n")); -+ ("yaffs_get_inode for NULL super_block!!\n")); - return NULL; - - } - - if (!obj) { - T(YAFFS_TRACE_OS, -- (KERN_DEBUG "yaffs_get_inode for NULL object!!\n")); -+ ("yaffs_get_inode for NULL object!!\n")); - return NULL; - - } - - T(YAFFS_TRACE_OS, -- (KERN_DEBUG "yaffs_get_inode for object %d\n", obj->objectId)); -+ ("yaffs_get_inode for object %d\n", obj->objectId)); - -- inode = iget(sb, obj->objectId); -+ inode = Y_IGET(sb, obj->objectId); -+ if (IS_ERR(inode)) -+ return NULL; - - /* NB Side effect: iget calls back to yaffs_read_inode(). */ - /* iget also increments the inode's i_count */ -@@ -854,7 +1025,7 @@ struct inode *yaffs_get_inode(struct sup - } - - static ssize_t yaffs_file_write(struct file *f, const char *buf, size_t n, -- loff_t * pos) -+ loff_t *pos) - { - yaffs_Object *obj; - int nWritten, ipos; -@@ -869,28 +1040,26 @@ static ssize_t yaffs_file_write(struct f - - inode = f->f_dentry->d_inode; - -- if (!S_ISBLK(inode->i_mode) && f->f_flags & O_APPEND) { -+ if (!S_ISBLK(inode->i_mode) && f->f_flags & O_APPEND) - ipos = inode->i_size; -- } else { -+ else - ipos = *pos; -- } - -- if (!obj) { -+ if (!obj) - T(YAFFS_TRACE_OS, -- (KERN_DEBUG "yaffs_file_write: hey obj is null!\n")); -- } else { -+ ("yaffs_file_write: hey obj is null!\n")); -+ else - T(YAFFS_TRACE_OS, -- (KERN_DEBUG -- "yaffs_file_write about to write writing %d bytes" -- "to object %d at %d\n", -- n, obj->objectId, ipos)); -- } -+ ("yaffs_file_write about to write writing %zu bytes" -+ "to object %d at %d\n", -+ n, obj->objectId, ipos)); - - nWritten = yaffs_WriteDataToFile(obj, buf, ipos, n, 0); - - T(YAFFS_TRACE_OS, -- (KERN_DEBUG "yaffs_file_write writing %d bytes, %d written at %d\n", -- n, nWritten, ipos)); -+ ("yaffs_file_write writing %zu bytes, %d written at %d\n", -+ n, nWritten, ipos)); -+ - if (nWritten > 0) { - ipos += nWritten; - *pos = ipos; -@@ -899,10 +1068,9 @@ static ssize_t yaffs_file_write(struct f - inode->i_blocks = (ipos + 511) >> 9; - - T(YAFFS_TRACE_OS, -- (KERN_DEBUG -- "yaffs_file_write size updated to %d bytes, " -- "%d blocks\n", -- ipos, (int)(inode->i_blocks))); -+ ("yaffs_file_write size updated to %d bytes, " -+ "%d blocks\n", -+ ipos, (int)(inode->i_blocks))); - } - - } -@@ -910,13 +1078,54 @@ static ssize_t yaffs_file_write(struct f - return nWritten == 0 ? -ENOSPC : nWritten; - } - -+/* Space holding and freeing is done to ensure we have space available for write_begin/end */ -+/* For now we just assume few parallel writes and check against a small number. */ -+/* Todo: need to do this with a counter to handle parallel reads better */ -+ -+static ssize_t yaffs_hold_space(struct file *f) -+{ -+ yaffs_Object *obj; -+ yaffs_Device *dev; -+ -+ int nFreeChunks; -+ -+ -+ obj = yaffs_DentryToObject(f->f_dentry); -+ -+ dev = obj->myDev; -+ -+ yaffs_GrossLock(dev); -+ -+ nFreeChunks = yaffs_GetNumberOfFreeChunks(dev); -+ -+ yaffs_GrossUnlock(dev); -+ -+ return (nFreeChunks > 20) ? 1 : 0; -+} -+ -+static void yaffs_release_space(struct file *f) -+{ -+ yaffs_Object *obj; -+ yaffs_Device *dev; -+ -+ -+ obj = yaffs_DentryToObject(f->f_dentry); -+ -+ dev = obj->myDev; -+ -+ yaffs_GrossLock(dev); -+ -+ -+ yaffs_GrossUnlock(dev); -+} -+ - static int yaffs_readdir(struct file *f, void *dirent, filldir_t filldir) - { - yaffs_Object *obj; - yaffs_Device *dev; - struct inode *inode = f->f_dentry->d_inode; - unsigned long offset, curoffs; -- struct list_head *i; -+ struct ylist_head *i; - yaffs_Object *l; - - char name[YAFFS_MAX_NAME_LENGTH + 1]; -@@ -932,24 +1141,20 @@ static int yaffs_readdir(struct file *f, - - if (offset == 0) { - T(YAFFS_TRACE_OS, -- (KERN_DEBUG "yaffs_readdir: entry . ino %d \n", -- (int)inode->i_ino)); -- if (filldir(dirent, ".", 1, offset, inode->i_ino, DT_DIR) -- < 0) { -+ ("yaffs_readdir: entry . ino %d \n", -+ (int)inode->i_ino)); -+ if (filldir(dirent, ".", 1, offset, inode->i_ino, DT_DIR) < 0) - goto out; -- } - offset++; - f->f_pos++; - } - if (offset == 1) { - T(YAFFS_TRACE_OS, -- (KERN_DEBUG "yaffs_readdir: entry .. ino %d \n", -- (int)f->f_dentry->d_parent->d_inode->i_ino)); -- if (filldir -- (dirent, "..", 2, offset, -- f->f_dentry->d_parent->d_inode->i_ino, DT_DIR) < 0) { -+ ("yaffs_readdir: entry .. ino %d \n", -+ (int)f->f_dentry->d_parent->d_inode->i_ino)); -+ if (filldir(dirent, "..", 2, offset, -+ f->f_dentry->d_parent->d_inode->i_ino, DT_DIR) < 0) - goto out; -- } - offset++; - f->f_pos++; - } -@@ -965,35 +1170,32 @@ static int yaffs_readdir(struct file *f, - f->f_version = inode->i_version; - } - -- list_for_each(i, &obj->variant.directoryVariant.children) { -+ ylist_for_each(i, &obj->variant.directoryVariant.children) { - curoffs++; - if (curoffs >= offset) { -- l = list_entry(i, yaffs_Object, siblings); -+ l = ylist_entry(i, yaffs_Object, siblings); - - yaffs_GetObjectName(l, name, - YAFFS_MAX_NAME_LENGTH + 1); - T(YAFFS_TRACE_OS, -- (KERN_DEBUG "yaffs_readdir: %s inode %d\n", name, -+ ("yaffs_readdir: %s inode %d\n", name, - yaffs_GetObjectInode(l))); - - if (filldir(dirent, -- name, -- strlen(name), -- offset, -- yaffs_GetObjectInode(l), -- yaffs_GetObjectType(l)) -- < 0) { -+ name, -+ strlen(name), -+ offset, -+ yaffs_GetObjectInode(l), -+ yaffs_GetObjectType(l)) < 0) - goto up_and_out; -- } - - offset++; - f->f_pos++; - } - } - -- up_and_out: -- out: -- -+up_and_out: -+out: - yaffs_GrossUnlock(dev); - - return 0; -@@ -1002,12 +1204,19 @@ static int yaffs_readdir(struct file *f, - /* - * File creation. Allocate an inode, and we're done.. - */ --#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) -+ -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 29) -+#define YCRED(x) x -+#else -+#define YCRED(x) (x->cred) -+#endif -+ -+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0)) - static int yaffs_mknod(struct inode *dir, struct dentry *dentry, int mode, -- dev_t rdev) -+ dev_t rdev) - #else - static int yaffs_mknod(struct inode *dir, struct dentry *dentry, int mode, -- int rdev) -+ int rdev) - #endif - { - struct inode *inode; -@@ -1018,25 +1227,25 @@ static int yaffs_mknod(struct inode *dir - yaffs_Object *parent = yaffs_InodeToObject(dir); - - int error = -ENOSPC; -- uid_t uid = current->fsuid; -- gid_t gid = (dir->i_mode & S_ISGID) ? dir->i_gid : current->fsgid; -+ uid_t uid = YCRED(current)->fsuid; -+ gid_t gid = (dir->i_mode & S_ISGID) ? dir->i_gid : YCRED(current)->fsgid; - -- if((dir->i_mode & S_ISGID) && S_ISDIR(mode)) -+ if ((dir->i_mode & S_ISGID) && S_ISDIR(mode)) - mode |= S_ISGID; - - if (parent) { - T(YAFFS_TRACE_OS, -- (KERN_DEBUG "yaffs_mknod: parent object %d type %d\n", -- parent->objectId, parent->variantType)); -+ ("yaffs_mknod: parent object %d type %d\n", -+ parent->objectId, parent->variantType)); - } else { - T(YAFFS_TRACE_OS, -- (KERN_DEBUG "yaffs_mknod: could not get parent object\n")); -+ ("yaffs_mknod: could not get parent object\n")); - return -EPERM; - } - - T(YAFFS_TRACE_OS, ("yaffs_mknod: making oject for %s, " -- "mode %x dev %x\n", -- dentry->d_name.name, mode, rdev)); -+ "mode %x dev %x\n", -+ dentry->d_name.name, mode, rdev)); - - dev = parent->myDev; - -@@ -1045,33 +1254,28 @@ static int yaffs_mknod(struct inode *dir - switch (mode & S_IFMT) { - default: - /* Special (socket, fifo, device...) */ -- T(YAFFS_TRACE_OS, (KERN_DEBUG -- "yaffs_mknod: making special\n")); --#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) -- obj = -- yaffs_MknodSpecial(parent, dentry->d_name.name, mode, uid, -- gid, old_encode_dev(rdev)); --#else -- obj = -- yaffs_MknodSpecial(parent, dentry->d_name.name, mode, uid, -- gid, rdev); -+ T(YAFFS_TRACE_OS, ("yaffs_mknod: making special\n")); -+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0)) -+ obj = yaffs_MknodSpecial(parent, dentry->d_name.name, mode, uid, -+ gid, old_encode_dev(rdev)); -+#else -+ obj = yaffs_MknodSpecial(parent, dentry->d_name.name, mode, uid, -+ gid, rdev); - #endif - break; - case S_IFREG: /* file */ -- T(YAFFS_TRACE_OS, (KERN_DEBUG "yaffs_mknod: making file\n")); -- obj = -- yaffs_MknodFile(parent, dentry->d_name.name, mode, uid, -- gid); -+ T(YAFFS_TRACE_OS, ("yaffs_mknod: making file\n")); -+ obj = yaffs_MknodFile(parent, dentry->d_name.name, mode, uid, -+ gid); - break; - case S_IFDIR: /* directory */ - T(YAFFS_TRACE_OS, -- (KERN_DEBUG "yaffs_mknod: making directory\n")); -- obj = -- yaffs_MknodDirectory(parent, dentry->d_name.name, mode, -- uid, gid); -+ ("yaffs_mknod: making directory\n")); -+ obj = yaffs_MknodDirectory(parent, dentry->d_name.name, mode, -+ uid, gid); - break; - case S_IFLNK: /* symlink */ -- T(YAFFS_TRACE_OS, (KERN_DEBUG "yaffs_mknod: making file\n")); -+ T(YAFFS_TRACE_OS, ("yaffs_mknod: making symlink\n")); - obj = NULL; /* Do we ever get here? */ - break; - } -@@ -1083,12 +1287,12 @@ static int yaffs_mknod(struct inode *dir - inode = yaffs_get_inode(dir->i_sb, mode, rdev, obj); - d_instantiate(dentry, inode); - T(YAFFS_TRACE_OS, -- (KERN_DEBUG "yaffs_mknod created object %d count = %d\n", -- obj->objectId, atomic_read(&inode->i_count))); -+ ("yaffs_mknod created object %d count = %d\n", -+ obj->objectId, atomic_read(&inode->i_count))); - error = 0; - } else { - T(YAFFS_TRACE_OS, -- (KERN_DEBUG "yaffs_mknod failed making object\n")); -+ ("yaffs_mknod failed making object\n")); - error = -ENOMEM; - } - -@@ -1098,25 +1302,19 @@ static int yaffs_mknod(struct inode *dir - static int yaffs_mkdir(struct inode *dir, struct dentry *dentry, int mode) - { - int retVal; -- T(YAFFS_TRACE_OS, (KERN_DEBUG "yaffs_mkdir\n")); -+ T(YAFFS_TRACE_OS, ("yaffs_mkdir\n")); - retVal = yaffs_mknod(dir, dentry, mode | S_IFDIR, 0); --#if 0 -- /* attempt to fix dir bug - didn't work */ -- if (!retVal) { -- dget(dentry); -- } --#endif - return retVal; - } - --#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) -+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0)) - static int yaffs_create(struct inode *dir, struct dentry *dentry, int mode, - struct nameidata *n) - #else - static int yaffs_create(struct inode *dir, struct dentry *dentry, int mode) - #endif - { -- T(YAFFS_TRACE_OS, (KERN_DEBUG "yaffs_create\n")); -+ T(YAFFS_TRACE_OS, ("yaffs_create\n")); - return yaffs_mknod(dir, dentry, mode | S_IFREG, 0); - } - -@@ -1127,8 +1325,8 @@ static int yaffs_unlink(struct inode *di - yaffs_Device *dev; - - T(YAFFS_TRACE_OS, -- (KERN_DEBUG "yaffs_unlink %d:%s\n", (int)(dir->i_ino), -- dentry->d_name.name)); -+ ("yaffs_unlink %d:%s\n", (int)(dir->i_ino), -+ dentry->d_name.name)); - - dev = yaffs_InodeToObject(dir)->myDev; - -@@ -1151,82 +1349,74 @@ static int yaffs_unlink(struct inode *di - * Create a link... - */ - static int yaffs_link(struct dentry *old_dentry, struct inode *dir, -- struct dentry *dentry) -+ struct dentry *dentry) - { - struct inode *inode = old_dentry->d_inode; - yaffs_Object *obj = NULL; - yaffs_Object *link = NULL; - yaffs_Device *dev; - -- T(YAFFS_TRACE_OS, (KERN_DEBUG "yaffs_link\n")); -+ T(YAFFS_TRACE_OS, ("yaffs_link\n")); - - obj = yaffs_InodeToObject(inode); - dev = obj->myDev; - - yaffs_GrossLock(dev); - -- if (!S_ISDIR(inode->i_mode)) /* Don't link directories */ -- { -- link = -- yaffs_Link(yaffs_InodeToObject(dir), dentry->d_name.name, -- obj); -- } -+ if (!S_ISDIR(inode->i_mode)) /* Don't link directories */ -+ link = yaffs_Link(yaffs_InodeToObject(dir), dentry->d_name.name, -+ obj); - - if (link) { - old_dentry->d_inode->i_nlink = yaffs_GetObjectLinkCount(obj); - d_instantiate(dentry, old_dentry->d_inode); - atomic_inc(&old_dentry->d_inode->i_count); - T(YAFFS_TRACE_OS, -- (KERN_DEBUG "yaffs_link link count %d i_count %d\n", -- old_dentry->d_inode->i_nlink, -- atomic_read(&old_dentry->d_inode->i_count))); -- -+ ("yaffs_link link count %d i_count %d\n", -+ old_dentry->d_inode->i_nlink, -+ atomic_read(&old_dentry->d_inode->i_count))); - } - - yaffs_GrossUnlock(dev); - -- if (link) { -- -+ if (link) - return 0; -- } - - return -EPERM; - } - - static int yaffs_symlink(struct inode *dir, struct dentry *dentry, -- const char *symname) -+ const char *symname) - { - yaffs_Object *obj; - yaffs_Device *dev; -- uid_t uid = current->fsuid; -- gid_t gid = (dir->i_mode & S_ISGID) ? dir->i_gid : current->fsgid; -+ uid_t uid = YCRED(current)->fsuid; -+ gid_t gid = (dir->i_mode & S_ISGID) ? dir->i_gid : YCRED(current)->fsgid; - -- T(YAFFS_TRACE_OS, (KERN_DEBUG "yaffs_symlink\n")); -+ T(YAFFS_TRACE_OS, ("yaffs_symlink\n")); - - dev = yaffs_InodeToObject(dir)->myDev; - yaffs_GrossLock(dev); - obj = yaffs_MknodSymLink(yaffs_InodeToObject(dir), dentry->d_name.name, -- S_IFLNK | S_IRWXUGO, uid, gid, symname); -+ S_IFLNK | S_IRWXUGO, uid, gid, symname); - yaffs_GrossUnlock(dev); - - if (obj) { -- - struct inode *inode; - - inode = yaffs_get_inode(dir->i_sb, obj->yst_mode, 0, obj); - d_instantiate(dentry, inode); -- T(YAFFS_TRACE_OS, (KERN_DEBUG "symlink created OK\n")); -+ T(YAFFS_TRACE_OS, ("symlink created OK\n")); - return 0; - } else { -- T(YAFFS_TRACE_OS, (KERN_DEBUG "symlink not created\n")); -- -+ T(YAFFS_TRACE_OS, ("symlink not created\n")); - } - - return -ENOMEM; - } - - static int yaffs_sync_object(struct file *file, struct dentry *dentry, -- int datasync) -+ int datasync) - { - - yaffs_Object *obj; -@@ -1236,7 +1426,7 @@ static int yaffs_sync_object(struct file - - dev = obj->myDev; - -- T(YAFFS_TRACE_OS, (KERN_DEBUG "yaffs_sync_object\n")); -+ T(YAFFS_TRACE_OS, ("yaffs_sync_object\n")); - yaffs_GrossLock(dev); - yaffs_FlushFile(obj, 1); - yaffs_GrossUnlock(dev); -@@ -1255,41 +1445,36 @@ static int yaffs_rename(struct inode *ol - int retVal = YAFFS_FAIL; - yaffs_Object *target; - -- T(YAFFS_TRACE_OS, (KERN_DEBUG "yaffs_rename\n")); -+ T(YAFFS_TRACE_OS, ("yaffs_rename\n")); - dev = yaffs_InodeToObject(old_dir)->myDev; - - yaffs_GrossLock(dev); - - /* Check if the target is an existing directory that is not empty. */ -- target = -- yaffs_FindObjectByName(yaffs_InodeToObject(new_dir), -- new_dentry->d_name.name); -+ target = yaffs_FindObjectByName(yaffs_InodeToObject(new_dir), -+ new_dentry->d_name.name); - - - -- if (target && -- target->variantType == YAFFS_OBJECT_TYPE_DIRECTORY && -- !list_empty(&target->variant.directoryVariant.children)) { -+ if (target && target->variantType == YAFFS_OBJECT_TYPE_DIRECTORY && -+ !ylist_empty(&target->variant.directoryVariant.children)) { - -- T(YAFFS_TRACE_OS, (KERN_DEBUG "target is non-empty dir\n")); -+ T(YAFFS_TRACE_OS, ("target is non-empty dir\n")); - - retVal = YAFFS_FAIL; - } else { -- - /* Now does unlinking internally using shadowing mechanism */ -- T(YAFFS_TRACE_OS, (KERN_DEBUG "calling yaffs_RenameObject\n")); -- -- retVal = -- yaffs_RenameObject(yaffs_InodeToObject(old_dir), -- old_dentry->d_name.name, -- yaffs_InodeToObject(new_dir), -- new_dentry->d_name.name); -+ T(YAFFS_TRACE_OS, ("calling yaffs_RenameObject\n")); - -+ retVal = yaffs_RenameObject(yaffs_InodeToObject(old_dir), -+ old_dentry->d_name.name, -+ yaffs_InodeToObject(new_dir), -+ new_dentry->d_name.name); - } - yaffs_GrossUnlock(dev); - - if (retVal == YAFFS_OK) { -- if(target) { -+ if (target) { - new_dentry->d_inode->i_nlink--; - mark_inode_dirty(new_dentry->d_inode); - } -@@ -1298,7 +1483,6 @@ static int yaffs_rename(struct inode *ol - } else { - return -ENOTEMPTY; - } -- - } - - static int yaffs_setattr(struct dentry *dentry, struct iattr *attr) -@@ -1308,15 +1492,15 @@ static int yaffs_setattr(struct dentry * - yaffs_Device *dev; - - T(YAFFS_TRACE_OS, -- (KERN_DEBUG "yaffs_setattr of object %d\n", -- yaffs_InodeToObject(inode)->objectId)); -- -- if ((error = inode_change_ok(inode, attr)) == 0) { -+ ("yaffs_setattr of object %d\n", -+ yaffs_InodeToObject(inode)->objectId)); - -+ error = inode_change_ok(inode, attr); -+ if (error == 0) { - dev = yaffs_InodeToObject(inode)->myDev; - yaffs_GrossLock(dev); - if (yaffs_SetAttributes(yaffs_InodeToObject(inode), attr) == -- YAFFS_OK) { -+ YAFFS_OK) { - error = 0; - } else { - error = -EPERM; -@@ -1328,12 +1512,12 @@ static int yaffs_setattr(struct dentry * - return error; - } - --#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) -+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17)) - static int yaffs_statfs(struct dentry *dentry, struct kstatfs *buf) - { - yaffs_Device *dev = yaffs_DentryToObject(dentry)->myDev; - struct super_block *sb = dentry->d_sb; --#elif (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) -+#elif (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0)) - static int yaffs_statfs(struct super_block *sb, struct kstatfs *buf) - { - yaffs_Device *dev = yaffs_SuperToDevice(sb); -@@ -1343,32 +1527,53 @@ static int yaffs_statfs(struct super_blo - yaffs_Device *dev = yaffs_SuperToDevice(sb); - #endif - -- T(YAFFS_TRACE_OS, (KERN_DEBUG "yaffs_statfs\n")); -+ T(YAFFS_TRACE_OS, ("yaffs_statfs\n")); - - yaffs_GrossLock(dev); - - buf->f_type = YAFFS_MAGIC; - buf->f_bsize = sb->s_blocksize; - buf->f_namelen = 255; -- if (sb->s_blocksize > dev->nDataBytesPerChunk) { -+ -+ if (dev->nDataBytesPerChunk & (dev->nDataBytesPerChunk - 1)) { -+ /* Do this if chunk size is not a power of 2 */ -+ -+ uint64_t bytesInDev; -+ uint64_t bytesFree; -+ -+ bytesInDev = ((uint64_t)((dev->endBlock - dev->startBlock + 1))) * -+ ((uint64_t)(dev->nChunksPerBlock * dev->nDataBytesPerChunk)); -+ -+ do_div(bytesInDev, sb->s_blocksize); /* bytesInDev becomes the number of blocks */ -+ buf->f_blocks = bytesInDev; -+ -+ bytesFree = ((uint64_t)(yaffs_GetNumberOfFreeChunks(dev))) * -+ ((uint64_t)(dev->nDataBytesPerChunk)); -+ -+ do_div(bytesFree, sb->s_blocksize); -+ -+ buf->f_bfree = bytesFree; -+ -+ } else if (sb->s_blocksize > dev->nDataBytesPerChunk) { - - buf->f_blocks = -- (dev->endBlock - dev->startBlock + -- 1) * dev->nChunksPerBlock / (sb->s_blocksize / -- dev->nDataBytesPerChunk); -+ (dev->endBlock - dev->startBlock + 1) * -+ dev->nChunksPerBlock / -+ (sb->s_blocksize / dev->nDataBytesPerChunk); - buf->f_bfree = -- yaffs_GetNumberOfFreeChunks(dev) / (sb->s_blocksize / -- dev->nDataBytesPerChunk); -+ yaffs_GetNumberOfFreeChunks(dev) / -+ (sb->s_blocksize / dev->nDataBytesPerChunk); - } else { -- - buf->f_blocks = -- (dev->endBlock - dev->startBlock + -- 1) * dev->nChunksPerBlock * (dev->nDataBytesPerChunk / -- sb->s_blocksize); -+ (dev->endBlock - dev->startBlock + 1) * -+ dev->nChunksPerBlock * -+ (dev->nDataBytesPerChunk / sb->s_blocksize); -+ - buf->f_bfree = -- yaffs_GetNumberOfFreeChunks(dev) * (dev->nDataBytesPerChunk / -- sb->s_blocksize); -+ yaffs_GetNumberOfFreeChunks(dev) * -+ (dev->nDataBytesPerChunk / sb->s_blocksize); - } -+ - buf->f_files = 0; - buf->f_ffree = 0; - buf->f_bavail = buf->f_bfree; -@@ -1378,18 +1583,19 @@ static int yaffs_statfs(struct super_blo - } - - --/** - static int yaffs_do_sync_fs(struct super_block *sb) - { - - yaffs_Device *dev = yaffs_SuperToDevice(sb); -- T(YAFFS_TRACE_OS, (KERN_DEBUG "yaffs_do_sync_fs\n")); -+ T(YAFFS_TRACE_OS, ("yaffs_do_sync_fs\n")); - -- if(sb->s_dirt) { -+ if (sb->s_dirt) { - yaffs_GrossLock(dev); - -- if(dev) -+ if (dev) { -+ yaffs_FlushEntireDeviceCache(dev); - yaffs_CheckpointSave(dev); -+ } - - yaffs_GrossUnlock(dev); - -@@ -1397,35 +1603,73 @@ static int yaffs_do_sync_fs(struct super - } - return 0; - } --**/ - --#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) -+ -+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17)) - static void yaffs_write_super(struct super_block *sb) - #else - static int yaffs_write_super(struct super_block *sb) - #endif - { - -- T(YAFFS_TRACE_OS, (KERN_DEBUG "yaffs_write_super\n")); --#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18)) -- return 0; /* yaffs_do_sync_fs(sb);*/ -+ T(YAFFS_TRACE_OS, ("yaffs_write_super\n")); -+ if (yaffs_auto_checkpoint >= 2) -+ yaffs_do_sync_fs(sb); -+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18)) -+ return 0; - #endif - } - - --#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) -+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17)) - static int yaffs_sync_fs(struct super_block *sb, int wait) - #else - static int yaffs_sync_fs(struct super_block *sb) - #endif - { -+ T(YAFFS_TRACE_OS, ("yaffs_sync_fs\n")); -+ -+ if (yaffs_auto_checkpoint >= 1) -+ yaffs_do_sync_fs(sb); -+ -+ return 0; -+} -+ -+#ifdef YAFFS_USE_OWN_IGET -+ -+static struct inode *yaffs_iget(struct super_block *sb, unsigned long ino) -+{ -+ struct inode *inode; -+ yaffs_Object *obj; -+ yaffs_Device *dev = yaffs_SuperToDevice(sb); -+ -+ T(YAFFS_TRACE_OS, -+ ("yaffs_iget for %lu\n", ino)); - -- T(YAFFS_TRACE_OS, (KERN_DEBUG "yaffs_sync_fs\n")); -+ inode = iget_locked(sb, ino); -+ if (!inode) -+ return ERR_PTR(-ENOMEM); -+ if (!(inode->i_state & I_NEW)) -+ return inode; -+ -+ /* NB This is called as a side effect of other functions, but -+ * we had to release the lock to prevent deadlocks, so -+ * need to lock again. -+ */ - -- return 0; /* yaffs_do_sync_fs(sb);*/ -+ yaffs_GrossLock(dev); - -+ obj = yaffs_FindObjectByNumber(dev, inode->i_ino); -+ -+ yaffs_FillInodeFromObject(inode, obj); -+ -+ yaffs_GrossUnlock(dev); -+ -+ unlock_new_inode(inode); -+ return inode; - } - -+#else - - static void yaffs_read_inode(struct inode *inode) - { -@@ -1438,7 +1682,7 @@ static void yaffs_read_inode(struct inod - yaffs_Device *dev = yaffs_SuperToDevice(inode->i_sb); - - T(YAFFS_TRACE_OS, -- (KERN_DEBUG "yaffs_read_inode for %d\n", (int)inode->i_ino)); -+ ("yaffs_read_inode for %d\n", (int)inode->i_ino)); - - yaffs_GrossLock(dev); - -@@ -1449,18 +1693,20 @@ static void yaffs_read_inode(struct inod - yaffs_GrossUnlock(dev); - } - --static LIST_HEAD(yaffs_dev_list); -+#endif -+ -+static YLIST_HEAD(yaffs_dev_list); - --#if 0 // not used -+#if 0 /* not used */ - static int yaffs_remount_fs(struct super_block *sb, int *flags, char *data) - { - yaffs_Device *dev = yaffs_SuperToDevice(sb); - -- if( *flags & MS_RDONLY ) { -+ if (*flags & MS_RDONLY) { - struct mtd_info *mtd = yaffs_SuperToDevice(sb)->genericDevice; - - T(YAFFS_TRACE_OS, -- (KERN_DEBUG "yaffs_remount_fs: %s: RO\n", dev->name )); -+ ("yaffs_remount_fs: %s: RO\n", dev->name)); - - yaffs_GrossLock(dev); - -@@ -1472,10 +1718,9 @@ static int yaffs_remount_fs(struct super - mtd->sync(mtd); - - yaffs_GrossUnlock(dev); -- } -- else { -+ } else { - T(YAFFS_TRACE_OS, -- (KERN_DEBUG "yaffs_remount_fs: %s: RW\n", dev->name )); -+ ("yaffs_remount_fs: %s: RW\n", dev->name)); - } - - return 0; -@@ -1486,7 +1731,7 @@ static void yaffs_put_super(struct super - { - yaffs_Device *dev = yaffs_SuperToDevice(sb); - -- T(YAFFS_TRACE_OS, (KERN_DEBUG "yaffs_put_super\n")); -+ T(YAFFS_TRACE_OS, ("yaffs_put_super\n")); - - yaffs_GrossLock(dev); - -@@ -1494,18 +1739,17 @@ static void yaffs_put_super(struct super - - yaffs_CheckpointSave(dev); - -- if (dev->putSuperFunc) { -+ if (dev->putSuperFunc) - dev->putSuperFunc(sb); -- } - - yaffs_Deinitialise(dev); - - yaffs_GrossUnlock(dev); - - /* we assume this is protected by lock_kernel() in mount/umount */ -- list_del(&dev->devList); -+ ylist_del(&dev->devList); - -- if(dev->spareBuffer){ -+ if (dev->spareBuffer) { - YFREE(dev->spareBuffer); - dev->spareBuffer = NULL; - } -@@ -1516,12 +1760,10 @@ static void yaffs_put_super(struct super - - static void yaffs_MTDPutSuper(struct super_block *sb) - { -- - struct mtd_info *mtd = yaffs_SuperToDevice(sb)->genericDevice; - -- if (mtd->sync) { -+ if (mtd->sync) - mtd->sync(mtd); -- } - - put_mtd_device(mtd); - } -@@ -1531,9 +1773,9 @@ static void yaffs_MarkSuperBlockDirty(vo - { - struct super_block *sb = (struct super_block *)vsb; - -- T(YAFFS_TRACE_OS, (KERN_DEBUG "yaffs_MarkSuperBlockDirty() sb = %p\n",sb)); --// if(sb) --// sb->s_dirt = 1; -+ T(YAFFS_TRACE_OS, ("yaffs_MarkSuperBlockDirty() sb = %p\n", sb)); -+ if (sb) -+ sb->s_dirt = 1; - } - - typedef struct { -@@ -1546,48 +1788,48 @@ typedef struct { - #define MAX_OPT_LEN 20 - static int yaffs_parse_options(yaffs_options *options, const char *options_str) - { -- char cur_opt[MAX_OPT_LEN+1]; -+ char cur_opt[MAX_OPT_LEN + 1]; - int p; - int error = 0; - - /* Parse through the options which is a comma seperated list */ - -- while(options_str && *options_str && !error){ -- memset(cur_opt,0,MAX_OPT_LEN+1); -+ while (options_str && *options_str && !error) { -+ memset(cur_opt, 0, MAX_OPT_LEN + 1); - p = 0; - -- while(*options_str && *options_str != ','){ -- if(p < MAX_OPT_LEN){ -+ while (*options_str && *options_str != ',') { -+ if (p < MAX_OPT_LEN) { - cur_opt[p] = *options_str; - p++; - } - options_str++; - } - -- if(!strcmp(cur_opt,"inband-tags")) -+ if (!strcmp(cur_opt, "inband-tags")) - options->inband_tags = 1; -- else if(!strcmp(cur_opt,"no-cache")) -+ else if (!strcmp(cur_opt, "no-cache")) - options->no_cache = 1; -- else if(!strcmp(cur_opt,"no-checkpoint-read")) -+ else if (!strcmp(cur_opt, "no-checkpoint-read")) - options->skip_checkpoint_read = 1; -- else if(!strcmp(cur_opt,"no-checkpoint-write")) -+ else if (!strcmp(cur_opt, "no-checkpoint-write")) - options->skip_checkpoint_write = 1; -- else if(!strcmp(cur_opt,"no-checkpoint")){ -+ else if (!strcmp(cur_opt, "no-checkpoint")) { - options->skip_checkpoint_read = 1; - options->skip_checkpoint_write = 1; - } else { -- printk(KERN_INFO "yaffs: Bad mount option \"%s\"\n",cur_opt); -+ printk(KERN_INFO "yaffs: Bad mount option \"%s\"\n", -+ cur_opt); - error = 1; - } -- - } - - return error; - } - - static struct super_block *yaffs_internal_read_super(int yaffsVersion, -- struct super_block *sb, -- void *data, int silent) -+ struct super_block *sb, -+ void *data, int silent) - { - int nBlocks; - struct inode *inode = NULL; -@@ -1602,6 +1844,7 @@ static struct super_block *yaffs_interna - - sb->s_magic = YAFFS_MAGIC; - sb->s_op = &yaffs_super_ops; -+ sb->s_flags |= MS_NOATIME; - - if (!sb) - printk(KERN_INFO "yaffs: sb is NULL\n"); -@@ -1614,14 +1857,14 @@ static struct super_block *yaffs_interna - sb->s_dev, - yaffs_devname(sb, devname_buf)); - -- if(!data_str) -+ if (!data_str) - data_str = ""; - -- printk(KERN_INFO "yaffs: passed flags \"%s\"\n",data_str); -+ printk(KERN_INFO "yaffs: passed flags \"%s\"\n", data_str); - -- memset(&options,0,sizeof(options)); -+ memset(&options, 0, sizeof(options)); - -- if(yaffs_parse_options(&options,data_str)){ -+ if (yaffs_parse_options(&options, data_str)) { - /* Option parsing failed */ - return NULL; - } -@@ -1645,9 +1888,9 @@ static struct super_block *yaffs_interna - yaffs_devname(sb, devname_buf))); - - /* Check it's an mtd device..... */ -- if (MAJOR(sb->s_dev) != MTD_BLOCK_MAJOR) { -+ if (MAJOR(sb->s_dev) != MTD_BLOCK_MAJOR) - return NULL; /* This isn't an mtd device */ -- } -+ - /* Get the device */ - mtd = get_mtd_device(NULL, MINOR(sb->s_dev)); - if (!mtd) { -@@ -1673,29 +1916,23 @@ static struct super_block *yaffs_interna - T(YAFFS_TRACE_OS, (" %s %d\n", WRITE_SIZE_STR, WRITE_SIZE(mtd))); - T(YAFFS_TRACE_OS, (" oobsize %d\n", mtd->oobsize)); - T(YAFFS_TRACE_OS, (" erasesize %d\n", mtd->erasesize)); -- T(YAFFS_TRACE_OS, (" size %d\n", mtd->size)); -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 29) -+ T(YAFFS_TRACE_OS, (" size %u\n", mtd->size)); -+#else -+ T(YAFFS_TRACE_OS, (" size %lld\n", mtd->size)); -+#endif - - #ifdef CONFIG_YAFFS_AUTO_YAFFS2 - -- if (yaffsVersion == 1 && --#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) -- mtd->writesize >= 2048) { --#else -- mtd->oobblock >= 2048) { --#endif -- T(YAFFS_TRACE_ALWAYS,("yaffs: auto selecting yaffs2\n")); -- yaffsVersion = 2; -+ if (yaffsVersion == 1 && WRITE_SIZE(mtd) >= 2048) { -+ T(YAFFS_TRACE_ALWAYS, ("yaffs: auto selecting yaffs2\n")); -+ yaffsVersion = 2; - } - - /* Added NCB 26/5/2006 for completeness */ -- if (yaffsVersion == 2 && --#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) -- mtd->writesize == 512) { --#else -- mtd->oobblock == 512) { --#endif -- T(YAFFS_TRACE_ALWAYS,("yaffs: auto selecting yaffs1\n")); -- yaffsVersion = 1; -+ if (yaffsVersion == 2 && !options.inband_tags && WRITE_SIZE(mtd) == 512) { -+ T(YAFFS_TRACE_ALWAYS, ("yaffs: auto selecting yaffs1\n")); -+ yaffsVersion = 1; - } - - #endif -@@ -1707,7 +1944,7 @@ static struct super_block *yaffs_interna - !mtd->block_markbad || - !mtd->read || - !mtd->write || --#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) -+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17)) - !mtd->read_oob || !mtd->write_oob) { - #else - !mtd->write_ecc || -@@ -1719,12 +1956,9 @@ static struct super_block *yaffs_interna - return NULL; - } - --#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) -- if (mtd->writesize < YAFFS_MIN_YAFFS2_CHUNK_SIZE || --#else -- if (mtd->oobblock < YAFFS_MIN_YAFFS2_CHUNK_SIZE || --#endif -- mtd->oobsize < YAFFS_MIN_YAFFS2_SPARE_SIZE) { -+ if ((WRITE_SIZE(mtd) < YAFFS_MIN_YAFFS2_CHUNK_SIZE || -+ mtd->oobsize < YAFFS_MIN_YAFFS2_SPARE_SIZE) && -+ !options.inband_tags) { - T(YAFFS_TRACE_ALWAYS, - ("yaffs: MTD device does not have the " - "right page sizes\n")); -@@ -1735,7 +1969,7 @@ static struct super_block *yaffs_interna - if (!mtd->erase || - !mtd->read || - !mtd->write || --#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) -+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17)) - !mtd->read_oob || !mtd->write_oob) { - #else - !mtd->write_ecc || -@@ -1761,7 +1995,7 @@ static struct super_block *yaffs_interna - * Set the yaffs_Device up for mtd - */ - --#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) -+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0)) - sb->s_fs_info = dev = kmalloc(sizeof(yaffs_Device), GFP_KERNEL); - #else - sb->u.generic_sbp = dev = kmalloc(sizeof(yaffs_Device), GFP_KERNEL); -@@ -1780,13 +2014,15 @@ static struct super_block *yaffs_interna - - /* Set up the memory size parameters.... */ - -- nBlocks = mtd->size / (YAFFS_CHUNKS_PER_BLOCK * YAFFS_BYTES_PER_CHUNK); -+ nBlocks = YCALCBLOCKS(mtd->size, (YAFFS_CHUNKS_PER_BLOCK * YAFFS_BYTES_PER_CHUNK)); -+ - dev->startBlock = 0; - dev->endBlock = nBlocks - 1; - dev->nChunksPerBlock = YAFFS_CHUNKS_PER_BLOCK; -- dev->nDataBytesPerChunk = YAFFS_BYTES_PER_CHUNK; -+ dev->totalBytesPerChunk = YAFFS_BYTES_PER_CHUNK; - dev->nReservedBlocks = 5; - dev->nShortOpCaches = (options.no_cache) ? 0 : 10; -+ dev->inbandTags = options.inband_tags; - - /* ... and the functions. */ - if (yaffsVersion == 2) { -@@ -1798,20 +2034,19 @@ static struct super_block *yaffs_interna - dev->queryNANDBlock = nandmtd2_QueryNANDBlock; - dev->spareBuffer = YMALLOC(mtd->oobsize); - dev->isYaffs2 = 1; --#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) -- dev->nDataBytesPerChunk = mtd->writesize; -+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17)) -+ dev->totalBytesPerChunk = mtd->writesize; - dev->nChunksPerBlock = mtd->erasesize / mtd->writesize; - #else -- dev->nDataBytesPerChunk = mtd->oobblock; -+ dev->totalBytesPerChunk = mtd->oobblock; - dev->nChunksPerBlock = mtd->erasesize / mtd->oobblock; - #endif -- nBlocks = mtd->size / mtd->erasesize; -+ nBlocks = YCALCBLOCKS(mtd->size, mtd->erasesize); - -- dev->nCheckpointReservedBlocks = CONFIG_YAFFS_CHECKPOINT_RESERVED_BLOCKS; - dev->startBlock = 0; - dev->endBlock = nBlocks - 1; - } else { --#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) -+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17)) - /* use the MTD interface in yaffs_mtdif1.c */ - dev->writeChunkWithTagsToNAND = - nandmtd1_WriteChunkWithTagsToNAND; -@@ -1847,7 +2082,7 @@ static struct super_block *yaffs_interna - dev->skipCheckpointWrite = options.skip_checkpoint_write; - - /* we assume this is protected by lock_kernel() in mount/umount */ -- list_add_tail(&dev->devList, &yaffs_dev_list); -+ ylist_add_tail(&dev->devList, &yaffs_dev_list); - - init_MUTEX(&dev->grossLock); - -@@ -1884,20 +2119,23 @@ static struct super_block *yaffs_interna - return NULL; - } - sb->s_root = root; -+ sb->s_dirt = !dev->isCheckpointed; -+ T(YAFFS_TRACE_ALWAYS, -+ ("yaffs_read_super: isCheckpointed %d\n", dev->isCheckpointed)); - - T(YAFFS_TRACE_OS, ("yaffs_read_super: done\n")); - return sb; - } - - --#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) -+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0)) - static int yaffs_internal_read_super_mtd(struct super_block *sb, void *data, - int silent) - { - return yaffs_internal_read_super(1, sb, data, silent) ? 0 : -EINVAL; - } - --#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) -+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17)) - static int yaffs_read_super(struct file_system_type *fs, - int flags, const char *dev_name, - void *data, struct vfsmount *mnt) -@@ -1938,14 +2176,14 @@ static DECLARE_FSTYPE(yaffs_fs_type, "ya - - #ifdef CONFIG_YAFFS_YAFFS2 - --#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) -+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0)) - static int yaffs2_internal_read_super_mtd(struct super_block *sb, void *data, - int silent) - { - return yaffs_internal_read_super(2, sb, data, silent) ? 0 : -EINVAL; - } - --#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) -+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17)) - static int yaffs2_read_super(struct file_system_type *fs, - int flags, const char *dev_name, void *data, - struct vfsmount *mnt) -@@ -1990,12 +2228,12 @@ static char *yaffs_dump_dev(char *buf, y - { - buf += sprintf(buf, "startBlock......... %d\n", dev->startBlock); - buf += sprintf(buf, "endBlock........... %d\n", dev->endBlock); -+ buf += sprintf(buf, "totalBytesPerChunk. %d\n", dev->totalBytesPerChunk); - buf += sprintf(buf, "nDataBytesPerChunk. %d\n", dev->nDataBytesPerChunk); - buf += sprintf(buf, "chunkGroupBits..... %d\n", dev->chunkGroupBits); - buf += sprintf(buf, "chunkGroupSize..... %d\n", dev->chunkGroupSize); - buf += sprintf(buf, "nErasedBlocks...... %d\n", dev->nErasedBlocks); - buf += sprintf(buf, "nReservedBlocks.... %d\n", dev->nReservedBlocks); -- buf += sprintf(buf, "nCheckptResBlocks.. %d\n", dev->nCheckpointReservedBlocks); - buf += sprintf(buf, "blocksInCheckpoint. %d\n", dev->blocksInCheckpoint); - buf += sprintf(buf, "nTnodesCreated..... %d\n", dev->nTnodesCreated); - buf += sprintf(buf, "nFreeTnodes........ %d\n", dev->nFreeTnodes); -@@ -2006,10 +2244,8 @@ static char *yaffs_dump_dev(char *buf, y - buf += sprintf(buf, "nPageReads......... %d\n", dev->nPageReads); - buf += sprintf(buf, "nBlockErasures..... %d\n", dev->nBlockErasures); - buf += sprintf(buf, "nGCCopies.......... %d\n", dev->nGCCopies); -- buf += -- sprintf(buf, "garbageCollections. %d\n", dev->garbageCollections); -- buf += -- sprintf(buf, "passiveGCs......... %d\n", -+ buf += sprintf(buf, "garbageCollections. %d\n", dev->garbageCollections); -+ buf += sprintf(buf, "passiveGCs......... %d\n", - dev->passiveGarbageCollections); - buf += sprintf(buf, "nRetriedWrites..... %d\n", dev->nRetriedWrites); - buf += sprintf(buf, "nShortOpCaches..... %d\n", dev->nShortOpCaches); -@@ -2025,6 +2261,7 @@ static char *yaffs_dump_dev(char *buf, y - sprintf(buf, "nBackgroudDeletions %d\n", dev->nBackgroundDeletions); - buf += sprintf(buf, "useNANDECC......... %d\n", dev->useNANDECC); - buf += sprintf(buf, "isYaffs2........... %d\n", dev->isYaffs2); -+ buf += sprintf(buf, "inbandTags......... %d\n", dev->inbandTags); - - return buf; - } -@@ -2033,7 +2270,7 @@ static int yaffs_proc_read(char *page, - char **start, - off_t offset, int count, int *eof, void *data) - { -- struct list_head *item; -+ struct ylist_head *item; - char *buf = page; - int step = offset; - int n = 0; -@@ -2057,8 +2294,8 @@ static int yaffs_proc_read(char *page, - lock_kernel(); - - /* Locate and print the Nth entry. Order N-squared but N is small. */ -- list_for_each(item, &yaffs_dev_list) { -- yaffs_Device *dev = list_entry(item, yaffs_Device, devList); -+ ylist_for_each(item, &yaffs_dev_list) { -+ yaffs_Device *dev = ylist_entry(item, yaffs_Device, devList); - if (n < step) { - n++; - continue; -@@ -2119,7 +2356,7 @@ static int yaffs_proc_write(struct file - char *end; - char *mask_name; - const char *x; -- char substring[MAX_MASK_NAME_LENGTH+1]; -+ char substring[MAX_MASK_NAME_LENGTH + 1]; - int i; - int done = 0; - int add, len = 0; -@@ -2129,9 +2366,8 @@ static int yaffs_proc_write(struct file - - while (!done && (pos < count)) { - done = 1; -- while ((pos < count) && isspace(buf[pos])) { -+ while ((pos < count) && isspace(buf[pos])) - pos++; -- } - - switch (buf[pos]) { - case '+': -@@ -2148,20 +2384,21 @@ static int yaffs_proc_write(struct file - mask_name = NULL; - - mask_bitfield = simple_strtoul(buf + pos, &end, 0); -+ - if (end > buf + pos) { - mask_name = "numeral"; - len = end - (buf + pos); - pos += len; - done = 0; - } else { -- for(x = buf + pos, i = 0; -- (*x == '_' || (*x >='a' && *x <= 'z')) && -- i = 'a' && *x <= 'z')) && -+ i < MAX_MASK_NAME_LENGTH; x++, i++, pos++) -+ substring[i] = *x; - substring[i] = '\0'; - - for (i = 0; mask_flags[i].mask_name != NULL; i++) { -- if(strcmp(substring,mask_flags[i].mask_name) == 0){ -+ if (strcmp(substring, mask_flags[i].mask_name) == 0) { - mask_name = mask_flags[i].mask_name; - mask_bitfield = mask_flags[i].mask_bitfield; - done = 0; -@@ -2172,7 +2409,7 @@ static int yaffs_proc_write(struct file - - if (mask_name != NULL) { - done = 0; -- switch(add) { -+ switch (add) { - case '-': - rg &= ~mask_bitfield; - break; -@@ -2191,13 +2428,13 @@ static int yaffs_proc_write(struct file - - yaffs_traceMask = rg | YAFFS_TRACE_ALWAYS; - -- printk("new trace = 0x%08X\n",yaffs_traceMask); -+ printk(KERN_DEBUG "new trace = 0x%08X\n", yaffs_traceMask); - - if (rg & YAFFS_TRACE_ALWAYS) { - for (i = 0; mask_flags[i].mask_name != NULL; i++) { - char flag; - flag = ((rg & mask_flags[i].mask_bitfield) == mask_flags[i].mask_bitfield) ? '+' : '-'; -- printk("%c%s\n", flag, mask_flags[i].mask_name); -+ printk(KERN_DEBUG "%c%s\n", flag, mask_flags[i].mask_name); - } - } - -@@ -2211,12 +2448,8 @@ struct file_system_to_install { - }; - - static struct file_system_to_install fs_to_install[] = { --//#ifdef CONFIG_YAFFS_YAFFS1 - {&yaffs_fs_type, 0}, --//#endif --//#ifdef CONFIG_YAFFS_YAFFS2 - {&yaffs2_fs_type, 0}, --//#endif - {NULL, 0} - }; - -@@ -2231,15 +2464,14 @@ static int __init init_yaffs_fs(void) - /* Install the proc_fs entry */ - my_proc_entry = create_proc_entry("yaffs", - S_IRUGO | S_IFREG, -- &proc_root); -+ YPROC_ROOT); - - if (my_proc_entry) { - my_proc_entry->write_proc = yaffs_proc_write; - my_proc_entry->read_proc = yaffs_proc_read; - my_proc_entry->data = NULL; -- } else { -+ } else - return -ENOMEM; -- } - - /* Now add the file system entries */ - -@@ -2247,9 +2479,8 @@ static int __init init_yaffs_fs(void) - - while (fsinst->fst && !error) { - error = register_filesystem(fsinst->fst); -- if (!error) { -+ if (!error) - fsinst->installed = 1; -- } - fsinst++; - } - -@@ -2277,7 +2508,7 @@ static void __exit exit_yaffs_fs(void) - T(YAFFS_TRACE_ALWAYS, ("yaffs " __DATE__ " " __TIME__ - " removing. \n")); - -- remove_proc_entry("yaffs", &proc_root); -+ remove_proc_entry("yaffs", YPROC_ROOT); - - fsinst = fs_to_install; - -@@ -2288,7 +2519,6 @@ static void __exit exit_yaffs_fs(void) - } - fsinst++; - } -- - } - - module_init(init_yaffs_fs) ---- /dev/null -+++ b/fs/yaffs2/yaffs_getblockinfo.h -@@ -0,0 +1,34 @@ -+/* -+ * YAFFS: Yet another Flash File System . A NAND-flash specific file system. -+ * -+ * Copyright (C) 2002-2007 Aleph One Ltd. -+ * for Toby Churchill Ltd and Brightstar Engineering -+ * -+ * Created by Charles Manning -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU Lesser General Public License version 2.1 as -+ * published by the Free Software Foundation. -+ * -+ * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL. -+ */ -+ -+#ifndef __YAFFS_GETBLOCKINFO_H__ -+#define __YAFFS_GETBLOCKINFO_H__ -+ -+#include "yaffs_guts.h" -+ -+/* Function to manipulate block info */ -+static Y_INLINE yaffs_BlockInfo *yaffs_GetBlockInfo(yaffs_Device * dev, int blk) -+{ -+ if (blk < dev->internalStartBlock || blk > dev->internalEndBlock) { -+ T(YAFFS_TRACE_ERROR, -+ (TSTR -+ ("**>> yaffs: getBlockInfo block %d is not valid" TENDSTR), -+ blk)); -+ YBUG(); -+ } -+ return &dev->blockInfo[blk - dev->internalStartBlock]; -+} -+ -+#endif ---- a/fs/yaffs2/yaffs_guts.c -+++ b/fs/yaffs2/yaffs_guts.c -@@ -12,16 +12,17 @@ - */ - - const char *yaffs_guts_c_version = -- "$Id: yaffs_guts.c,v 1.49 2007-05-15 20:07:40 charles Exp $"; -+ "$Id: yaffs_guts.c,v 1.82 2009-03-09 04:24:17 charles Exp $"; - - #include "yportenv.h" - - #include "yaffsinterface.h" - #include "yaffs_guts.h" - #include "yaffs_tagsvalidity.h" -+#include "yaffs_getblockinfo.h" - - #include "yaffs_tagscompat.h" --#ifndef CONFIG_YAFFS_USE_OWN_SORT -+#ifndef CONFIG_YAFFS_USE_OWN_SORT - #include "yaffs_qsort.h" - #endif - #include "yaffs_nand.h" -@@ -32,116 +33,116 @@ const char *yaffs_guts_c_version = - #include "yaffs_packedtags2.h" - - --#ifdef CONFIG_YAFFS_WINCE --void yfsd_LockYAFFS(BOOL fsLockOnly); --void yfsd_UnlockYAFFS(BOOL fsLockOnly); --#endif -- - #define YAFFS_PASSIVE_GC_CHUNKS 2 - - #include "yaffs_ecc.h" - - - /* Robustification (if it ever comes about...) */ --static void yaffs_RetireBlock(yaffs_Device * dev, int blockInNAND); --static void yaffs_HandleWriteChunkError(yaffs_Device * dev, int chunkInNAND, int erasedOk); --static void yaffs_HandleWriteChunkOk(yaffs_Device * dev, int chunkInNAND, -- const __u8 * data, -- const yaffs_ExtendedTags * tags); --static void yaffs_HandleUpdateChunk(yaffs_Device * dev, int chunkInNAND, -- const yaffs_ExtendedTags * tags); -+static void yaffs_RetireBlock(yaffs_Device *dev, int blockInNAND); -+static void yaffs_HandleWriteChunkError(yaffs_Device *dev, int chunkInNAND, -+ int erasedOk); -+static void yaffs_HandleWriteChunkOk(yaffs_Device *dev, int chunkInNAND, -+ const __u8 *data, -+ const yaffs_ExtendedTags *tags); -+static void yaffs_HandleUpdateChunk(yaffs_Device *dev, int chunkInNAND, -+ const yaffs_ExtendedTags *tags); - - /* Other local prototypes */ --static int yaffs_UnlinkObject( yaffs_Object *obj); -+static int yaffs_UnlinkObject(yaffs_Object *obj); - static int yaffs_ObjectHasCachedWriteData(yaffs_Object *obj); - - static void yaffs_HardlinkFixup(yaffs_Device *dev, yaffs_Object *hardList); - --static int yaffs_WriteNewChunkWithTagsToNAND(yaffs_Device * dev, -- const __u8 * buffer, -- yaffs_ExtendedTags * tags, -- int useReserve); --static int yaffs_PutChunkIntoFile(yaffs_Object * in, int chunkInInode, -- int chunkInNAND, int inScan); -- --static yaffs_Object *yaffs_CreateNewObject(yaffs_Device * dev, int number, -- yaffs_ObjectType type); --static void yaffs_AddObjectToDirectory(yaffs_Object * directory, -- yaffs_Object * obj); --static int yaffs_UpdateObjectHeader(yaffs_Object * in, const YCHAR * name, -- int force, int isShrink, int shadows); --static void yaffs_RemoveObjectFromDirectory(yaffs_Object * obj); -+static int yaffs_WriteNewChunkWithTagsToNAND(yaffs_Device *dev, -+ const __u8 *buffer, -+ yaffs_ExtendedTags *tags, -+ int useReserve); -+static int yaffs_PutChunkIntoFile(yaffs_Object *in, int chunkInInode, -+ int chunkInNAND, int inScan); -+ -+static yaffs_Object *yaffs_CreateNewObject(yaffs_Device *dev, int number, -+ yaffs_ObjectType type); -+static void yaffs_AddObjectToDirectory(yaffs_Object *directory, -+ yaffs_Object *obj); -+static int yaffs_UpdateObjectHeader(yaffs_Object *in, const YCHAR *name, -+ int force, int isShrink, int shadows); -+static void yaffs_RemoveObjectFromDirectory(yaffs_Object *obj); - static int yaffs_CheckStructures(void); --static int yaffs_DeleteWorker(yaffs_Object * in, yaffs_Tnode * tn, __u32 level, -- int chunkOffset, int *limit); --static int yaffs_DoGenericObjectDeletion(yaffs_Object * in); -- --static yaffs_BlockInfo *yaffs_GetBlockInfo(yaffs_Device * dev, int blockNo); -- --static __u8 *yaffs_GetTempBuffer(yaffs_Device * dev, int lineNo); --static void yaffs_ReleaseTempBuffer(yaffs_Device * dev, __u8 * buffer, -- int lineNo); -+static int yaffs_DeleteWorker(yaffs_Object *in, yaffs_Tnode *tn, __u32 level, -+ int chunkOffset, int *limit); -+static int yaffs_DoGenericObjectDeletion(yaffs_Object *in); -+ -+static yaffs_BlockInfo *yaffs_GetBlockInfo(yaffs_Device *dev, int blockNo); - --static int yaffs_CheckChunkErased(struct yaffs_DeviceStruct *dev, -- int chunkInNAND); - --static int yaffs_UnlinkWorker(yaffs_Object * obj); --static void yaffs_DestroyObject(yaffs_Object * obj); -+static int yaffs_CheckChunkErased(struct yaffs_DeviceStruct *dev, -+ int chunkInNAND); - --static int yaffs_TagsMatch(const yaffs_ExtendedTags * tags, int objectId, -- int chunkInObject); -+static int yaffs_UnlinkWorker(yaffs_Object *obj); - --loff_t yaffs_GetFileSize(yaffs_Object * obj); -+static int yaffs_TagsMatch(const yaffs_ExtendedTags *tags, int objectId, -+ int chunkInObject); - --static int yaffs_AllocateChunk(yaffs_Device * dev, int useReserve, yaffs_BlockInfo **blockUsedPtr); -+static int yaffs_AllocateChunk(yaffs_Device *dev, int useReserve, -+ yaffs_BlockInfo **blockUsedPtr); - --static void yaffs_VerifyFreeChunks(yaffs_Device * dev); -+static void yaffs_VerifyFreeChunks(yaffs_Device *dev); - - static void yaffs_CheckObjectDetailsLoaded(yaffs_Object *in); - -+static void yaffs_VerifyDirectory(yaffs_Object *directory); - #ifdef YAFFS_PARANOID --static int yaffs_CheckFileSanity(yaffs_Object * in); -+static int yaffs_CheckFileSanity(yaffs_Object *in); - #else - #define yaffs_CheckFileSanity(in) - #endif - --static void yaffs_InvalidateWholeChunkCache(yaffs_Object * in); --static void yaffs_InvalidateChunkCache(yaffs_Object * object, int chunkId); -+static void yaffs_InvalidateWholeChunkCache(yaffs_Object *in); -+static void yaffs_InvalidateChunkCache(yaffs_Object *object, int chunkId); - - static void yaffs_InvalidateCheckpoint(yaffs_Device *dev); - --static int yaffs_FindChunkInFile(yaffs_Object * in, int chunkInInode, -- yaffs_ExtendedTags * tags); -+static int yaffs_FindChunkInFile(yaffs_Object *in, int chunkInInode, -+ yaffs_ExtendedTags *tags); - --static __u32 yaffs_GetChunkGroupBase(yaffs_Device *dev, yaffs_Tnode *tn, unsigned pos); --static yaffs_Tnode *yaffs_FindLevel0Tnode(yaffs_Device * dev, -- yaffs_FileStructure * fStruct, -- __u32 chunkId); -+static __u32 yaffs_GetChunkGroupBase(yaffs_Device *dev, yaffs_Tnode *tn, -+ unsigned pos); -+static yaffs_Tnode *yaffs_FindLevel0Tnode(yaffs_Device *dev, -+ yaffs_FileStructure *fStruct, -+ __u32 chunkId); - - - /* Function to calculate chunk and offset */ - --static void yaffs_AddrToChunk(yaffs_Device *dev, loff_t addr, __u32 *chunk, __u32 *offset) -+static void yaffs_AddrToChunk(yaffs_Device *dev, loff_t addr, int *chunkOut, -+ __u32 *offsetOut) - { -- if(dev->chunkShift){ -- /* Easy-peasy power of 2 case */ -- *chunk = (__u32)(addr >> dev->chunkShift); -- *offset = (__u32)(addr & dev->chunkMask); -- } -- else if(dev->crumbsPerChunk) -- { -- /* Case where we're using "crumbs" */ -- *offset = (__u32)(addr & dev->crumbMask); -- addr >>= dev->crumbShift; -- *chunk = ((__u32)addr)/dev->crumbsPerChunk; -- *offset += ((addr - (*chunk * dev->crumbsPerChunk)) << dev->crumbShift); -+ int chunk; -+ __u32 offset; -+ -+ chunk = (__u32)(addr >> dev->chunkShift); -+ -+ if (dev->chunkDiv == 1) { -+ /* easy power of 2 case */ -+ offset = (__u32)(addr & dev->chunkMask); -+ } else { -+ /* Non power-of-2 case */ -+ -+ loff_t chunkBase; -+ -+ chunk /= dev->chunkDiv; -+ -+ chunkBase = ((loff_t)chunk) * dev->nDataBytesPerChunk; -+ offset = (__u32)(addr - chunkBase); - } -- else -- YBUG(); -+ -+ *chunkOut = chunk; -+ *offsetOut = offset; - } - --/* Function to return the number of shifts for a power of 2 greater than or equal -- * to the given number -+/* Function to return the number of shifts for a power of 2 greater than or -+ * equal to the given number - * Note we don't try to cater for all possible numbers and this does not have to - * be hellishly efficient. - */ -@@ -153,13 +154,14 @@ static __u32 ShiftsGE(__u32 x) - - nShifts = extraBits = 0; - -- while(x>1){ -- if(x & 1) extraBits++; -- x>>=1; -+ while (x > 1) { -+ if (x & 1) -+ extraBits++; -+ x >>= 1; - nShifts++; - } - -- if(extraBits) -+ if (extraBits) - nShifts++; - - return nShifts; -@@ -168,16 +170,17 @@ static __u32 ShiftsGE(__u32 x) - /* Function to return the number of shifts to get a 1 in bit 0 - */ - --static __u32 ShiftDiv(__u32 x) -+static __u32 Shifts(__u32 x) - { - int nShifts; - - nShifts = 0; - -- if(!x) return 0; -+ if (!x) -+ return 0; - -- while( !(x&1)){ -- x>>=1; -+ while (!(x&1)) { -+ x >>= 1; - nShifts++; - } - -@@ -195,21 +198,25 @@ static int yaffs_InitialiseTempBuffers(y - int i; - __u8 *buf = (__u8 *)1; - -- memset(dev->tempBuffer,0,sizeof(dev->tempBuffer)); -+ memset(dev->tempBuffer, 0, sizeof(dev->tempBuffer)); - - for (i = 0; buf && i < YAFFS_N_TEMP_BUFFERS; i++) { - dev->tempBuffer[i].line = 0; /* not in use */ - dev->tempBuffer[i].buffer = buf = -- YMALLOC_DMA(dev->nDataBytesPerChunk); -+ YMALLOC_DMA(dev->totalBytesPerChunk); - } - - return buf ? YAFFS_OK : YAFFS_FAIL; -- - } - --static __u8 *yaffs_GetTempBuffer(yaffs_Device * dev, int lineNo) -+__u8 *yaffs_GetTempBuffer(yaffs_Device *dev, int lineNo) - { - int i, j; -+ -+ dev->tempInUse++; -+ if (dev->tempInUse > dev->maxTemp) -+ dev->maxTemp = dev->tempInUse; -+ - for (i = 0; i < YAFFS_N_TEMP_BUFFERS; i++) { - if (dev->tempBuffer[i].line == 0) { - dev->tempBuffer[i].line = lineNo; -@@ -227,9 +234,9 @@ static __u8 *yaffs_GetTempBuffer(yaffs_D - T(YAFFS_TRACE_BUFFERS, - (TSTR("Out of temp buffers at line %d, other held by lines:"), - lineNo)); -- for (i = 0; i < YAFFS_N_TEMP_BUFFERS; i++) { -+ for (i = 0; i < YAFFS_N_TEMP_BUFFERS; i++) - T(YAFFS_TRACE_BUFFERS, (TSTR(" %d "), dev->tempBuffer[i].line)); -- } -+ - T(YAFFS_TRACE_BUFFERS, (TSTR(" " TENDSTR))); - - /* -@@ -242,10 +249,13 @@ static __u8 *yaffs_GetTempBuffer(yaffs_D - - } - --static void yaffs_ReleaseTempBuffer(yaffs_Device * dev, __u8 * buffer, -+void yaffs_ReleaseTempBuffer(yaffs_Device *dev, __u8 *buffer, - int lineNo) - { - int i; -+ -+ dev->tempInUse--; -+ - for (i = 0; i < YAFFS_N_TEMP_BUFFERS; i++) { - if (dev->tempBuffer[i].buffer == buffer) { - dev->tempBuffer[i].line = 0; -@@ -267,27 +277,26 @@ static void yaffs_ReleaseTempBuffer(yaff - /* - * Determine if we have a managed buffer. - */ --int yaffs_IsManagedTempBuffer(yaffs_Device * dev, const __u8 * buffer) -+int yaffs_IsManagedTempBuffer(yaffs_Device *dev, const __u8 *buffer) - { - int i; -+ - for (i = 0; i < YAFFS_N_TEMP_BUFFERS; i++) { - if (dev->tempBuffer[i].buffer == buffer) - return 1; -+ } - -+ for (i = 0; i < dev->nShortOpCaches; i++) { -+ if (dev->srCache[i].data == buffer) -+ return 1; - } - -- for (i = 0; i < dev->nShortOpCaches; i++) { -- if( dev->srCache[i].data == buffer ) -- return 1; -- -- } -- -- if (buffer == dev->checkpointBuffer) -- return 1; -- -- T(YAFFS_TRACE_ALWAYS, -- (TSTR("yaffs: unmaged buffer detected.\n" TENDSTR))); -- return 0; -+ if (buffer == dev->checkpointBuffer) -+ return 1; -+ -+ T(YAFFS_TRACE_ALWAYS, -+ (TSTR("yaffs: unmaged buffer detected.\n" TENDSTR))); -+ return 0; - } - - -@@ -296,62 +305,63 @@ int yaffs_IsManagedTempBuffer(yaffs_Devi - * Chunk bitmap manipulations - */ - --static Y_INLINE __u8 *yaffs_BlockBits(yaffs_Device * dev, int blk) -+static Y_INLINE __u8 *yaffs_BlockBits(yaffs_Device *dev, int blk) - { - if (blk < dev->internalStartBlock || blk > dev->internalEndBlock) { - T(YAFFS_TRACE_ERROR, -- (TSTR("**>> yaffs: BlockBits block %d is not valid" TENDSTR), -- blk)); -+ (TSTR("**>> yaffs: BlockBits block %d is not valid" TENDSTR), -+ blk)); - YBUG(); - } - return dev->chunkBits + -- (dev->chunkBitmapStride * (blk - dev->internalStartBlock)); -+ (dev->chunkBitmapStride * (blk - dev->internalStartBlock)); - } - - static Y_INLINE void yaffs_VerifyChunkBitId(yaffs_Device *dev, int blk, int chunk) - { -- if(blk < dev->internalStartBlock || blk > dev->internalEndBlock || -- chunk < 0 || chunk >= dev->nChunksPerBlock) { -- T(YAFFS_TRACE_ERROR, -- (TSTR("**>> yaffs: Chunk Id (%d:%d) invalid"TENDSTR),blk,chunk)); -- YBUG(); -+ if (blk < dev->internalStartBlock || blk > dev->internalEndBlock || -+ chunk < 0 || chunk >= dev->nChunksPerBlock) { -+ T(YAFFS_TRACE_ERROR, -+ (TSTR("**>> yaffs: Chunk Id (%d:%d) invalid"TENDSTR), -+ blk, chunk)); -+ YBUG(); - } - } - --static Y_INLINE void yaffs_ClearChunkBits(yaffs_Device * dev, int blk) -+static Y_INLINE void yaffs_ClearChunkBits(yaffs_Device *dev, int blk) - { - __u8 *blkBits = yaffs_BlockBits(dev, blk); - - memset(blkBits, 0, dev->chunkBitmapStride); - } - --static Y_INLINE void yaffs_ClearChunkBit(yaffs_Device * dev, int blk, int chunk) -+static Y_INLINE void yaffs_ClearChunkBit(yaffs_Device *dev, int blk, int chunk) - { - __u8 *blkBits = yaffs_BlockBits(dev, blk); - -- yaffs_VerifyChunkBitId(dev,blk,chunk); -+ yaffs_VerifyChunkBitId(dev, blk, chunk); - - blkBits[chunk / 8] &= ~(1 << (chunk & 7)); - } - --static Y_INLINE void yaffs_SetChunkBit(yaffs_Device * dev, int blk, int chunk) -+static Y_INLINE void yaffs_SetChunkBit(yaffs_Device *dev, int blk, int chunk) - { - __u8 *blkBits = yaffs_BlockBits(dev, blk); - -- yaffs_VerifyChunkBitId(dev,blk,chunk); -+ yaffs_VerifyChunkBitId(dev, blk, chunk); - - blkBits[chunk / 8] |= (1 << (chunk & 7)); - } - --static Y_INLINE int yaffs_CheckChunkBit(yaffs_Device * dev, int blk, int chunk) -+static Y_INLINE int yaffs_CheckChunkBit(yaffs_Device *dev, int blk, int chunk) - { - __u8 *blkBits = yaffs_BlockBits(dev, blk); -- yaffs_VerifyChunkBitId(dev,blk,chunk); -+ yaffs_VerifyChunkBitId(dev, blk, chunk); - - return (blkBits[chunk / 8] & (1 << (chunk & 7))) ? 1 : 0; - } - --static Y_INLINE int yaffs_StillSomeChunkBits(yaffs_Device * dev, int blk) -+static Y_INLINE int yaffs_StillSomeChunkBits(yaffs_Device *dev, int blk) - { - __u8 *blkBits = yaffs_BlockBits(dev, blk); - int i; -@@ -363,17 +373,17 @@ static Y_INLINE int yaffs_StillSomeChunk - return 0; - } - --static int yaffs_CountChunkBits(yaffs_Device * dev, int blk) -+static int yaffs_CountChunkBits(yaffs_Device *dev, int blk) - { - __u8 *blkBits = yaffs_BlockBits(dev, blk); - int i; - int n = 0; - for (i = 0; i < dev->chunkBitmapStride; i++) { - __u8 x = *blkBits; -- while(x){ -- if(x & 1) -+ while (x) { -+ if (x & 1) - n++; -- x >>=1; -+ x >>= 1; - } - - blkBits++; -@@ -400,7 +410,7 @@ static int yaffs_SkipNANDVerification(ya - return !(yaffs_traceMask & (YAFFS_TRACE_VERIFY_NAND)); - } - --static const char * blockStateName[] = { -+static const char *blockStateName[] = { - "Unknown", - "Needs scanning", - "Scanning", -@@ -413,64 +423,65 @@ static const char * blockStateName[] = { - "Dead" - }; - --static void yaffs_VerifyBlock(yaffs_Device *dev,yaffs_BlockInfo *bi,int n) -+static void yaffs_VerifyBlock(yaffs_Device *dev, yaffs_BlockInfo *bi, int n) - { - int actuallyUsed; - int inUse; - -- if(yaffs_SkipVerification(dev)) -+ if (yaffs_SkipVerification(dev)) - return; - - /* Report illegal runtime states */ -- if(bi->blockState <0 || bi->blockState >= YAFFS_NUMBER_OF_BLOCK_STATES) -- T(YAFFS_TRACE_VERIFY,(TSTR("Block %d has undefined state %d"TENDSTR),n,bi->blockState)); -+ if (bi->blockState >= YAFFS_NUMBER_OF_BLOCK_STATES) -+ T(YAFFS_TRACE_VERIFY, (TSTR("Block %d has undefined state %d"TENDSTR), n, bi->blockState)); - -- switch(bi->blockState){ -- case YAFFS_BLOCK_STATE_UNKNOWN: -- case YAFFS_BLOCK_STATE_SCANNING: -- case YAFFS_BLOCK_STATE_NEEDS_SCANNING: -- T(YAFFS_TRACE_VERIFY,(TSTR("Block %d has bad run-state %s"TENDSTR), -- n,blockStateName[bi->blockState])); -+ switch (bi->blockState) { -+ case YAFFS_BLOCK_STATE_UNKNOWN: -+ case YAFFS_BLOCK_STATE_SCANNING: -+ case YAFFS_BLOCK_STATE_NEEDS_SCANNING: -+ T(YAFFS_TRACE_VERIFY, (TSTR("Block %d has bad run-state %s"TENDSTR), -+ n, blockStateName[bi->blockState])); - } - - /* Check pages in use and soft deletions are legal */ - - actuallyUsed = bi->pagesInUse - bi->softDeletions; - -- if(bi->pagesInUse < 0 || bi->pagesInUse > dev->nChunksPerBlock || -+ if (bi->pagesInUse < 0 || bi->pagesInUse > dev->nChunksPerBlock || - bi->softDeletions < 0 || bi->softDeletions > dev->nChunksPerBlock || - actuallyUsed < 0 || actuallyUsed > dev->nChunksPerBlock) -- T(YAFFS_TRACE_VERIFY,(TSTR("Block %d has illegal values pagesInUsed %d softDeletions %d"TENDSTR), -- n,bi->pagesInUse,bi->softDeletions)); -+ T(YAFFS_TRACE_VERIFY, (TSTR("Block %d has illegal values pagesInUsed %d softDeletions %d"TENDSTR), -+ n, bi->pagesInUse, bi->softDeletions)); - - - /* Check chunk bitmap legal */ -- inUse = yaffs_CountChunkBits(dev,n); -- if(inUse != bi->pagesInUse) -- T(YAFFS_TRACE_VERIFY,(TSTR("Block %d has inconsistent values pagesInUse %d counted chunk bits %d"TENDSTR), -- n,bi->pagesInUse,inUse)); -+ inUse = yaffs_CountChunkBits(dev, n); -+ if (inUse != bi->pagesInUse) -+ T(YAFFS_TRACE_VERIFY, (TSTR("Block %d has inconsistent values pagesInUse %d counted chunk bits %d"TENDSTR), -+ n, bi->pagesInUse, inUse)); - - /* Check that the sequence number is valid. - * Ten million is legal, but is very unlikely - */ -- if(dev->isYaffs2 && -+ if (dev->isYaffs2 && - (bi->blockState == YAFFS_BLOCK_STATE_ALLOCATING || bi->blockState == YAFFS_BLOCK_STATE_FULL) && -- (bi->sequenceNumber < YAFFS_LOWEST_SEQUENCE_NUMBER || bi->sequenceNumber > 10000000 )) -- T(YAFFS_TRACE_VERIFY,(TSTR("Block %d has suspect sequence number of %d"TENDSTR), -- n,bi->sequenceNumber)); -- -+ (bi->sequenceNumber < YAFFS_LOWEST_SEQUENCE_NUMBER || bi->sequenceNumber > 10000000)) -+ T(YAFFS_TRACE_VERIFY, (TSTR("Block %d has suspect sequence number of %d"TENDSTR), -+ n, bi->sequenceNumber)); - } - --static void yaffs_VerifyCollectedBlock(yaffs_Device *dev,yaffs_BlockInfo *bi,int n) -+static void yaffs_VerifyCollectedBlock(yaffs_Device *dev, yaffs_BlockInfo *bi, -+ int n) - { -- yaffs_VerifyBlock(dev,bi,n); -+ yaffs_VerifyBlock(dev, bi, n); - - /* After collection the block should be in the erased state */ -- /* TODO: This will need to change if we do partial gc */ -+ /* This will need to change if we do partial gc */ - -- if(bi->blockState != YAFFS_BLOCK_STATE_EMPTY){ -- T(YAFFS_TRACE_ERROR,(TSTR("Block %d is in state %d after gc, should be erased"TENDSTR), -- n,bi->blockState)); -+ if (bi->blockState != YAFFS_BLOCK_STATE_COLLECTING && -+ bi->blockState != YAFFS_BLOCK_STATE_EMPTY) { -+ T(YAFFS_TRACE_ERROR, (TSTR("Block %d is in state %d after gc, should be erased"TENDSTR), -+ n, bi->blockState)); - } - } - -@@ -480,52 +491,49 @@ static void yaffs_VerifyBlocks(yaffs_Dev - int nBlocksPerState[YAFFS_NUMBER_OF_BLOCK_STATES]; - int nIllegalBlockStates = 0; - -- -- if(yaffs_SkipVerification(dev)) -+ if (yaffs_SkipVerification(dev)) - return; - -- memset(nBlocksPerState,0,sizeof(nBlocksPerState)); -- -+ memset(nBlocksPerState, 0, sizeof(nBlocksPerState)); - -- for(i = dev->internalStartBlock; i <= dev->internalEndBlock; i++){ -- yaffs_BlockInfo *bi = yaffs_GetBlockInfo(dev,i); -- yaffs_VerifyBlock(dev,bi,i); -+ for (i = dev->internalStartBlock; i <= dev->internalEndBlock; i++) { -+ yaffs_BlockInfo *bi = yaffs_GetBlockInfo(dev, i); -+ yaffs_VerifyBlock(dev, bi, i); - -- if(bi->blockState >=0 && bi->blockState < YAFFS_NUMBER_OF_BLOCK_STATES) -+ if (bi->blockState < YAFFS_NUMBER_OF_BLOCK_STATES) - nBlocksPerState[bi->blockState]++; - else - nIllegalBlockStates++; -- - } - -- T(YAFFS_TRACE_VERIFY,(TSTR(""TENDSTR))); -- T(YAFFS_TRACE_VERIFY,(TSTR("Block summary"TENDSTR))); -+ T(YAFFS_TRACE_VERIFY, (TSTR(""TENDSTR))); -+ T(YAFFS_TRACE_VERIFY, (TSTR("Block summary"TENDSTR))); - -- T(YAFFS_TRACE_VERIFY,(TSTR("%d blocks have illegal states"TENDSTR),nIllegalBlockStates)); -- if(nBlocksPerState[YAFFS_BLOCK_STATE_ALLOCATING] > 1) -- T(YAFFS_TRACE_VERIFY,(TSTR("Too many allocating blocks"TENDSTR))); -+ T(YAFFS_TRACE_VERIFY, (TSTR("%d blocks have illegal states"TENDSTR), nIllegalBlockStates)); -+ if (nBlocksPerState[YAFFS_BLOCK_STATE_ALLOCATING] > 1) -+ T(YAFFS_TRACE_VERIFY, (TSTR("Too many allocating blocks"TENDSTR))); - -- for(i = 0; i < YAFFS_NUMBER_OF_BLOCK_STATES; i++) -+ for (i = 0; i < YAFFS_NUMBER_OF_BLOCK_STATES; i++) - T(YAFFS_TRACE_VERIFY, - (TSTR("%s %d blocks"TENDSTR), -- blockStateName[i],nBlocksPerState[i])); -+ blockStateName[i], nBlocksPerState[i])); - -- if(dev->blocksInCheckpoint != nBlocksPerState[YAFFS_BLOCK_STATE_CHECKPOINT]) -+ if (dev->blocksInCheckpoint != nBlocksPerState[YAFFS_BLOCK_STATE_CHECKPOINT]) - T(YAFFS_TRACE_VERIFY, - (TSTR("Checkpoint block count wrong dev %d count %d"TENDSTR), - dev->blocksInCheckpoint, nBlocksPerState[YAFFS_BLOCK_STATE_CHECKPOINT])); - -- if(dev->nErasedBlocks != nBlocksPerState[YAFFS_BLOCK_STATE_EMPTY]) -+ if (dev->nErasedBlocks != nBlocksPerState[YAFFS_BLOCK_STATE_EMPTY]) - T(YAFFS_TRACE_VERIFY, - (TSTR("Erased block count wrong dev %d count %d"TENDSTR), - dev->nErasedBlocks, nBlocksPerState[YAFFS_BLOCK_STATE_EMPTY])); - -- if(nBlocksPerState[YAFFS_BLOCK_STATE_COLLECTING] > 1) -+ if (nBlocksPerState[YAFFS_BLOCK_STATE_COLLECTING] > 1) - T(YAFFS_TRACE_VERIFY, - (TSTR("Too many collecting blocks %d (max is 1)"TENDSTR), - nBlocksPerState[YAFFS_BLOCK_STATE_COLLECTING])); - -- T(YAFFS_TRACE_VERIFY,(TSTR(""TENDSTR))); -+ T(YAFFS_TRACE_VERIFY, (TSTR(""TENDSTR))); - - } - -@@ -535,26 +543,26 @@ static void yaffs_VerifyBlocks(yaffs_Dev - */ - static void yaffs_VerifyObjectHeader(yaffs_Object *obj, yaffs_ObjectHeader *oh, yaffs_ExtendedTags *tags, int parentCheck) - { -- if(yaffs_SkipVerification(obj->myDev)) -+ if (obj && yaffs_SkipVerification(obj->myDev)) - return; - -- if(!(tags && obj && oh)){ -- T(YAFFS_TRACE_VERIFY, -- (TSTR("Verifying object header tags %x obj %x oh %x"TENDSTR), -- (__u32)tags,(__u32)obj,(__u32)oh)); -+ if (!(tags && obj && oh)) { -+ T(YAFFS_TRACE_VERIFY, -+ (TSTR("Verifying object header tags %x obj %x oh %x"TENDSTR), -+ (__u32)tags, (__u32)obj, (__u32)oh)); - return; - } - -- if(oh->type <= YAFFS_OBJECT_TYPE_UNKNOWN || -- oh->type > YAFFS_OBJECT_TYPE_MAX) -- T(YAFFS_TRACE_VERIFY, -- (TSTR("Obj %d header type is illegal value 0x%x"TENDSTR), -- tags->objectId, oh->type)); -- -- if(tags->objectId != obj->objectId) -- T(YAFFS_TRACE_VERIFY, -- (TSTR("Obj %d header mismatch objectId %d"TENDSTR), -- tags->objectId, obj->objectId)); -+ if (oh->type <= YAFFS_OBJECT_TYPE_UNKNOWN || -+ oh->type > YAFFS_OBJECT_TYPE_MAX) -+ T(YAFFS_TRACE_VERIFY, -+ (TSTR("Obj %d header type is illegal value 0x%x"TENDSTR), -+ tags->objectId, oh->type)); -+ -+ if (tags->objectId != obj->objectId) -+ T(YAFFS_TRACE_VERIFY, -+ (TSTR("Obj %d header mismatch objectId %d"TENDSTR), -+ tags->objectId, obj->objectId)); - - - /* -@@ -563,46 +571,43 @@ static void yaffs_VerifyObjectHeader(yaf - * Tests do not apply to the root object. - */ - -- if(parentCheck && tags->objectId > 1 && !obj->parent) -- T(YAFFS_TRACE_VERIFY, -- (TSTR("Obj %d header mismatch parentId %d obj->parent is NULL"TENDSTR), -- tags->objectId, oh->parentObjectId)); -- -- -- if(parentCheck && obj->parent && -- oh->parentObjectId != obj->parent->objectId && -- (oh->parentObjectId != YAFFS_OBJECTID_UNLINKED || -- obj->parent->objectId != YAFFS_OBJECTID_DELETED)) -- T(YAFFS_TRACE_VERIFY, -- (TSTR("Obj %d header mismatch parentId %d parentObjectId %d"TENDSTR), -- tags->objectId, oh->parentObjectId, obj->parent->objectId)); -+ if (parentCheck && tags->objectId > 1 && !obj->parent) -+ T(YAFFS_TRACE_VERIFY, -+ (TSTR("Obj %d header mismatch parentId %d obj->parent is NULL"TENDSTR), -+ tags->objectId, oh->parentObjectId)); - -+ if (parentCheck && obj->parent && -+ oh->parentObjectId != obj->parent->objectId && -+ (oh->parentObjectId != YAFFS_OBJECTID_UNLINKED || -+ obj->parent->objectId != YAFFS_OBJECTID_DELETED)) -+ T(YAFFS_TRACE_VERIFY, -+ (TSTR("Obj %d header mismatch parentId %d parentObjectId %d"TENDSTR), -+ tags->objectId, oh->parentObjectId, obj->parent->objectId)); - -- if(tags->objectId > 1 && oh->name[0] == 0) /* Null name */ -+ if (tags->objectId > 1 && oh->name[0] == 0) /* Null name */ - T(YAFFS_TRACE_VERIFY, -- (TSTR("Obj %d header name is NULL"TENDSTR), -- obj->objectId)); -+ (TSTR("Obj %d header name is NULL"TENDSTR), -+ obj->objectId)); - -- if(tags->objectId > 1 && ((__u8)(oh->name[0])) == 0xff) /* Trashed name */ -+ if (tags->objectId > 1 && ((__u8)(oh->name[0])) == 0xff) /* Trashed name */ - T(YAFFS_TRACE_VERIFY, -- (TSTR("Obj %d header name is 0xFF"TENDSTR), -- obj->objectId)); -+ (TSTR("Obj %d header name is 0xFF"TENDSTR), -+ obj->objectId)); - } - - - --static int yaffs_VerifyTnodeWorker(yaffs_Object * obj, yaffs_Tnode * tn, -- __u32 level, int chunkOffset) -+static int yaffs_VerifyTnodeWorker(yaffs_Object *obj, yaffs_Tnode *tn, -+ __u32 level, int chunkOffset) - { - int i; - yaffs_Device *dev = obj->myDev; - int ok = 1; -- int nTnodeBytes = (dev->tnodeWidth * YAFFS_NTNODES_LEVEL0)/8; - - if (tn) { - if (level > 0) { - -- for (i = 0; i < YAFFS_NTNODES_INTERNAL && ok; i++){ -+ for (i = 0; i < YAFFS_NTNODES_INTERNAL && ok; i++) { - if (tn->internal[i]) { - ok = yaffs_VerifyTnodeWorker(obj, - tn->internal[i], -@@ -611,20 +616,19 @@ static int yaffs_VerifyTnodeWorker(yaffs - } - } - } else if (level == 0) { -- int i; - yaffs_ExtendedTags tags; - __u32 objectId = obj->objectId; - - chunkOffset <<= YAFFS_TNODES_LEVEL0_BITS; - -- for(i = 0; i < YAFFS_NTNODES_LEVEL0; i++){ -- __u32 theChunk = yaffs_GetChunkGroupBase(dev,tn,i); -+ for (i = 0; i < YAFFS_NTNODES_LEVEL0; i++) { -+ __u32 theChunk = yaffs_GetChunkGroupBase(dev, tn, i); - -- if(theChunk > 0){ -+ if (theChunk > 0) { - /* T(~0,(TSTR("verifying (%d:%d) %d"TENDSTR),tags.objectId,tags.chunkId,theChunk)); */ -- yaffs_ReadChunkWithTagsFromNAND(dev,theChunk,NULL, &tags); -- if(tags.objectId != objectId || tags.chunkId != chunkOffset){ -- T(~0,(TSTR("Object %d chunkId %d NAND mismatch chunk %d tags (%d:%d)"TENDSTR), -+ yaffs_ReadChunkWithTagsFromNAND(dev, theChunk, NULL, &tags); -+ if (tags.objectId != objectId || tags.chunkId != chunkOffset) { -+ T(~0, (TSTR("Object %d chunkId %d NAND mismatch chunk %d tags (%d:%d)"TENDSTR), - objectId, chunkOffset, theChunk, - tags.objectId, tags.chunkId)); - } -@@ -646,13 +650,15 @@ static void yaffs_VerifyFile(yaffs_Objec - __u32 lastChunk; - __u32 x; - __u32 i; -- int ok; - yaffs_Device *dev; - yaffs_ExtendedTags tags; - yaffs_Tnode *tn; - __u32 objectId; - -- if(obj && yaffs_SkipVerification(obj->myDev)) -+ if (!obj) -+ return; -+ -+ if (yaffs_SkipVerification(obj->myDev)) - return; - - dev = obj->myDev; -@@ -662,17 +668,17 @@ static void yaffs_VerifyFile(yaffs_Objec - lastChunk = obj->variant.fileVariant.fileSize / dev->nDataBytesPerChunk + 1; - x = lastChunk >> YAFFS_TNODES_LEVEL0_BITS; - requiredTallness = 0; -- while (x> 0) { -+ while (x > 0) { - x >>= YAFFS_TNODES_INTERNAL_BITS; - requiredTallness++; - } - - actualTallness = obj->variant.fileVariant.topLevel; - -- if(requiredTallness > actualTallness ) -+ if (requiredTallness > actualTallness) - T(YAFFS_TRACE_VERIFY, - (TSTR("Obj %d had tnode tallness %d, needs to be %d"TENDSTR), -- obj->objectId,actualTallness, requiredTallness)); -+ obj->objectId, actualTallness, requiredTallness)); - - - /* Check that the chunks in the tnode tree are all correct. -@@ -680,39 +686,31 @@ static void yaffs_VerifyFile(yaffs_Objec - * checking the tags for every chunk match. - */ - -- if(yaffs_SkipNANDVerification(dev)) -+ if (yaffs_SkipNANDVerification(dev)) - return; - -- for(i = 1; i <= lastChunk; i++){ -- tn = yaffs_FindLevel0Tnode(dev, &obj->variant.fileVariant,i); -+ for (i = 1; i <= lastChunk; i++) { -+ tn = yaffs_FindLevel0Tnode(dev, &obj->variant.fileVariant, i); - - if (tn) { -- __u32 theChunk = yaffs_GetChunkGroupBase(dev,tn,i); -- if(theChunk > 0){ -+ __u32 theChunk = yaffs_GetChunkGroupBase(dev, tn, i); -+ if (theChunk > 0) { - /* T(~0,(TSTR("verifying (%d:%d) %d"TENDSTR),objectId,i,theChunk)); */ -- yaffs_ReadChunkWithTagsFromNAND(dev,theChunk,NULL, &tags); -- if(tags.objectId != objectId || tags.chunkId != i){ -- T(~0,(TSTR("Object %d chunkId %d NAND mismatch chunk %d tags (%d:%d)"TENDSTR), -+ yaffs_ReadChunkWithTagsFromNAND(dev, theChunk, NULL, &tags); -+ if (tags.objectId != objectId || tags.chunkId != i) { -+ T(~0, (TSTR("Object %d chunkId %d NAND mismatch chunk %d tags (%d:%d)"TENDSTR), - objectId, i, theChunk, - tags.objectId, tags.chunkId)); - } - } - } -- - } -- - } - --static void yaffs_VerifyDirectory(yaffs_Object *obj) --{ -- if(obj && yaffs_SkipVerification(obj->myDev)) -- return; -- --} - - static void yaffs_VerifyHardLink(yaffs_Object *obj) - { -- if(obj && yaffs_SkipVerification(obj->myDev)) -+ if (obj && yaffs_SkipVerification(obj->myDev)) - return; - - /* Verify sane equivalent object */ -@@ -720,7 +718,7 @@ static void yaffs_VerifyHardLink(yaffs_O - - static void yaffs_VerifySymlink(yaffs_Object *obj) - { -- if(obj && yaffs_SkipVerification(obj->myDev)) -+ if (obj && yaffs_SkipVerification(obj->myDev)) - return; - - /* Verify symlink string */ -@@ -728,7 +726,7 @@ static void yaffs_VerifySymlink(yaffs_Ob - - static void yaffs_VerifySpecial(yaffs_Object *obj) - { -- if(obj && yaffs_SkipVerification(obj->myDev)) -+ if (obj && yaffs_SkipVerification(obj->myDev)) - return; - } - -@@ -740,14 +738,19 @@ static void yaffs_VerifyObject(yaffs_Obj - __u32 chunkMax; - - __u32 chunkIdOk; -- __u32 chunkIsLive; -+ __u32 chunkInRange; -+ __u32 chunkShouldNotBeDeleted; -+ __u32 chunkValid; -+ -+ if (!obj) -+ return; - -- if(!obj) -+ if (obj->beingCreated) - return; - - dev = obj->myDev; - -- if(yaffs_SkipVerification(dev)) -+ if (yaffs_SkipVerification(dev)) - return; - - /* Check sane object header chunk */ -@@ -755,50 +758,54 @@ static void yaffs_VerifyObject(yaffs_Obj - chunkMin = dev->internalStartBlock * dev->nChunksPerBlock; - chunkMax = (dev->internalEndBlock+1) * dev->nChunksPerBlock - 1; - -- chunkIdOk = (obj->chunkId >= chunkMin && obj->chunkId <= chunkMax); -- chunkIsLive = chunkIdOk && -+ chunkInRange = (((unsigned)(obj->hdrChunk)) >= chunkMin && ((unsigned)(obj->hdrChunk)) <= chunkMax); -+ chunkIdOk = chunkInRange || obj->hdrChunk == 0; -+ chunkValid = chunkInRange && - yaffs_CheckChunkBit(dev, -- obj->chunkId / dev->nChunksPerBlock, -- obj->chunkId % dev->nChunksPerBlock); -- if(!obj->fake && -- (!chunkIdOk || !chunkIsLive)) { -- T(YAFFS_TRACE_VERIFY, -- (TSTR("Obj %d has chunkId %d %s %s"TENDSTR), -- obj->objectId,obj->chunkId, -- chunkIdOk ? "" : ",out of range", -- chunkIsLive || !chunkIdOk ? "" : ",marked as deleted")); -+ obj->hdrChunk / dev->nChunksPerBlock, -+ obj->hdrChunk % dev->nChunksPerBlock); -+ chunkShouldNotBeDeleted = chunkInRange && !chunkValid; -+ -+ if (!obj->fake && -+ (!chunkIdOk || chunkShouldNotBeDeleted)) { -+ T(YAFFS_TRACE_VERIFY, -+ (TSTR("Obj %d has chunkId %d %s %s"TENDSTR), -+ obj->objectId, obj->hdrChunk, -+ chunkIdOk ? "" : ",out of range", -+ chunkShouldNotBeDeleted ? ",marked as deleted" : "")); - } - -- if(chunkIdOk && chunkIsLive &&!yaffs_SkipNANDVerification(dev)) { -+ if (chunkValid && !yaffs_SkipNANDVerification(dev)) { - yaffs_ExtendedTags tags; - yaffs_ObjectHeader *oh; -- __u8 *buffer = yaffs_GetTempBuffer(dev,__LINE__); -+ __u8 *buffer = yaffs_GetTempBuffer(dev, __LINE__); - - oh = (yaffs_ObjectHeader *)buffer; - -- yaffs_ReadChunkWithTagsFromNAND(dev, obj->chunkId,buffer, &tags); -+ yaffs_ReadChunkWithTagsFromNAND(dev, obj->hdrChunk, buffer, -+ &tags); - -- yaffs_VerifyObjectHeader(obj,oh,&tags,1); -+ yaffs_VerifyObjectHeader(obj, oh, &tags, 1); - -- yaffs_ReleaseTempBuffer(dev,buffer,__LINE__); -+ yaffs_ReleaseTempBuffer(dev, buffer, __LINE__); - } - - /* Verify it has a parent */ -- if(obj && !obj->fake && -- (!obj->parent || obj->parent->myDev != dev)){ -- T(YAFFS_TRACE_VERIFY, -- (TSTR("Obj %d has parent pointer %p which does not look like an object"TENDSTR), -- obj->objectId,obj->parent)); -+ if (obj && !obj->fake && -+ (!obj->parent || obj->parent->myDev != dev)) { -+ T(YAFFS_TRACE_VERIFY, -+ (TSTR("Obj %d has parent pointer %p which does not look like an object"TENDSTR), -+ obj->objectId, obj->parent)); - } - - /* Verify parent is a directory */ -- if(obj->parent && obj->parent->variantType != YAFFS_OBJECT_TYPE_DIRECTORY){ -- T(YAFFS_TRACE_VERIFY, -- (TSTR("Obj %d's parent is not a directory (type %d)"TENDSTR), -- obj->objectId,obj->parent->variantType)); -+ if (obj->parent && obj->parent->variantType != YAFFS_OBJECT_TYPE_DIRECTORY) { -+ T(YAFFS_TRACE_VERIFY, -+ (TSTR("Obj %d's parent is not a directory (type %d)"TENDSTR), -+ obj->objectId, obj->parent->variantType)); - } - -- switch(obj->variantType){ -+ switch (obj->variantType) { - case YAFFS_OBJECT_TYPE_FILE: - yaffs_VerifyFile(obj); - break; -@@ -818,33 +825,30 @@ static void yaffs_VerifyObject(yaffs_Obj - default: - T(YAFFS_TRACE_VERIFY, - (TSTR("Obj %d has illegaltype %d"TENDSTR), -- obj->objectId,obj->variantType)); -+ obj->objectId, obj->variantType)); - break; - } -- -- - } - - static void yaffs_VerifyObjects(yaffs_Device *dev) - { - yaffs_Object *obj; - int i; -- struct list_head *lh; -+ struct ylist_head *lh; - -- if(yaffs_SkipVerification(dev)) -+ if (yaffs_SkipVerification(dev)) - return; - - /* Iterate through the objects in each hash entry */ - -- for(i = 0; i < YAFFS_NOBJECT_BUCKETS; i++){ -- list_for_each(lh, &dev->objectBucket[i].list) { -+ for (i = 0; i < YAFFS_NOBJECT_BUCKETS; i++) { -+ ylist_for_each(lh, &dev->objectBucket[i].list) { - if (lh) { -- obj = list_entry(lh, yaffs_Object, hashLink); -+ obj = ylist_entry(lh, yaffs_Object, hashLink); - yaffs_VerifyObject(obj); - } - } -- } -- -+ } - } - - -@@ -855,19 +859,20 @@ static void yaffs_VerifyObjects(yaffs_De - static Y_INLINE int yaffs_HashFunction(int n) - { - n = abs(n); -- return (n % YAFFS_NOBJECT_BUCKETS); -+ return n % YAFFS_NOBJECT_BUCKETS; - } - - /* -- * Access functions to useful fake objects -+ * Access functions to useful fake objects. -+ * Note that root might have a presence in NAND if permissions are set. - */ - --yaffs_Object *yaffs_Root(yaffs_Device * dev) -+yaffs_Object *yaffs_Root(yaffs_Device *dev) - { - return dev->rootDir; - } - --yaffs_Object *yaffs_LostNFound(yaffs_Device * dev) -+yaffs_Object *yaffs_LostNFound(yaffs_Device *dev) - { - return dev->lostNFoundDir; - } -@@ -877,7 +882,7 @@ yaffs_Object *yaffs_LostNFound(yaffs_Dev - * Erased NAND checking functions - */ - --int yaffs_CheckFF(__u8 * buffer, int nBytes) -+int yaffs_CheckFF(__u8 *buffer, int nBytes) - { - /* Horrible, slow implementation */ - while (nBytes--) { -@@ -889,9 +894,8 @@ int yaffs_CheckFF(__u8 * buffer, int nBy - } - - static int yaffs_CheckChunkErased(struct yaffs_DeviceStruct *dev, -- int chunkInNAND) -+ int chunkInNAND) - { -- - int retval = YAFFS_OK; - __u8 *data = yaffs_GetTempBuffer(dev, __LINE__); - yaffs_ExtendedTags tags; -@@ -899,10 +903,9 @@ static int yaffs_CheckChunkErased(struct - - result = yaffs_ReadChunkWithTagsFromNAND(dev, chunkInNAND, data, &tags); - -- if(tags.eccResult > YAFFS_ECC_RESULT_NO_ERROR) -+ if (tags.eccResult > YAFFS_ECC_RESULT_NO_ERROR) - retval = YAFFS_FAIL; - -- - if (!yaffs_CheckFF(data, dev->nDataBytesPerChunk) || tags.chunkUsed) { - T(YAFFS_TRACE_NANDACCESS, - (TSTR("Chunk %d not erased" TENDSTR), chunkInNAND)); -@@ -915,11 +918,10 @@ static int yaffs_CheckChunkErased(struct - - } - -- - static int yaffs_WriteNewChunkWithTagsToNAND(struct yaffs_DeviceStruct *dev, -- const __u8 * data, -- yaffs_ExtendedTags * tags, -- int useReserve) -+ const __u8 *data, -+ yaffs_ExtendedTags *tags, -+ int useReserve) - { - int attempts = 0; - int writeOk = 0; -@@ -972,7 +974,7 @@ static int yaffs_WriteNewChunkWithTagsTo - erasedOk = yaffs_CheckChunkErased(dev, chunk); - if (erasedOk != YAFFS_OK) { - T(YAFFS_TRACE_ERROR, -- (TSTR ("**>> yaffs chunk %d was not erased" -+ (TSTR("**>> yaffs chunk %d was not erased" - TENDSTR), chunk)); - - /* try another chunk */ -@@ -992,7 +994,11 @@ static int yaffs_WriteNewChunkWithTagsTo - /* Copy the data into the robustification buffer */ - yaffs_HandleWriteChunkOk(dev, chunk, data, tags); - -- } while (writeOk != YAFFS_OK && attempts < yaffs_wr_attempts); -+ } while (writeOk != YAFFS_OK && -+ (yaffs_wr_attempts <= 0 || attempts <= yaffs_wr_attempts)); -+ -+ if (!writeOk) -+ chunk = -1; - - if (attempts > 1) { - T(YAFFS_TRACE_ERROR, -@@ -1009,13 +1015,35 @@ static int yaffs_WriteNewChunkWithTagsTo - * Block retiring for handling a broken block. - */ - --static void yaffs_RetireBlock(yaffs_Device * dev, int blockInNAND) -+static void yaffs_RetireBlock(yaffs_Device *dev, int blockInNAND) - { - yaffs_BlockInfo *bi = yaffs_GetBlockInfo(dev, blockInNAND); - - yaffs_InvalidateCheckpoint(dev); - -- yaffs_MarkBlockBad(dev, blockInNAND); -+ if (yaffs_MarkBlockBad(dev, blockInNAND) != YAFFS_OK) { -+ if (yaffs_EraseBlockInNAND(dev, blockInNAND) != YAFFS_OK) { -+ T(YAFFS_TRACE_ALWAYS, (TSTR( -+ "yaffs: Failed to mark bad and erase block %d" -+ TENDSTR), blockInNAND)); -+ } else { -+ yaffs_ExtendedTags tags; -+ int chunkId = blockInNAND * dev->nChunksPerBlock; -+ -+ __u8 *buffer = yaffs_GetTempBuffer(dev, __LINE__); -+ -+ memset(buffer, 0xff, dev->nDataBytesPerChunk); -+ yaffs_InitialiseTags(&tags); -+ tags.sequenceNumber = YAFFS_SEQUENCE_BAD_BLOCK; -+ if (dev->writeChunkWithTagsToNAND(dev, chunkId - -+ dev->chunkOffset, buffer, &tags) != YAFFS_OK) -+ T(YAFFS_TRACE_ALWAYS, (TSTR("yaffs: Failed to " -+ TCONT("write bad block marker to block %d") -+ TENDSTR), blockInNAND)); -+ -+ yaffs_ReleaseTempBuffer(dev, buffer, __LINE__); -+ } -+ } - - bi->blockState = YAFFS_BLOCK_STATE_DEAD; - bi->gcPrioritise = 0; -@@ -1029,49 +1057,45 @@ static void yaffs_RetireBlock(yaffs_Devi - * - */ - --static void yaffs_HandleWriteChunkOk(yaffs_Device * dev, int chunkInNAND, -- const __u8 * data, -- const yaffs_ExtendedTags * tags) -+static void yaffs_HandleWriteChunkOk(yaffs_Device *dev, int chunkInNAND, -+ const __u8 *data, -+ const yaffs_ExtendedTags *tags) - { - } - --static void yaffs_HandleUpdateChunk(yaffs_Device * dev, int chunkInNAND, -- const yaffs_ExtendedTags * tags) -+static void yaffs_HandleUpdateChunk(yaffs_Device *dev, int chunkInNAND, -+ const yaffs_ExtendedTags *tags) - { - } - - void yaffs_HandleChunkError(yaffs_Device *dev, yaffs_BlockInfo *bi) - { -- if(!bi->gcPrioritise){ -+ if (!bi->gcPrioritise) { - bi->gcPrioritise = 1; - dev->hasPendingPrioritisedGCs = 1; -- bi->chunkErrorStrikes ++; -+ bi->chunkErrorStrikes++; - -- if(bi->chunkErrorStrikes > 3){ -+ if (bi->chunkErrorStrikes > 3) { - bi->needsRetiring = 1; /* Too many stikes, so retire this */ - T(YAFFS_TRACE_ALWAYS, (TSTR("yaffs: Block struck out" TENDSTR))); - - } -- - } - } - --static void yaffs_HandleWriteChunkError(yaffs_Device * dev, int chunkInNAND, int erasedOk) -+static void yaffs_HandleWriteChunkError(yaffs_Device *dev, int chunkInNAND, -+ int erasedOk) - { -- - int blockInNAND = chunkInNAND / dev->nChunksPerBlock; - yaffs_BlockInfo *bi = yaffs_GetBlockInfo(dev, blockInNAND); - -- yaffs_HandleChunkError(dev,bi); -+ yaffs_HandleChunkError(dev, bi); - -- -- if(erasedOk ) { -+ if (erasedOk) { - /* Was an actual write failure, so mark the block for retirement */ - bi->needsRetiring = 1; - T(YAFFS_TRACE_ERROR | YAFFS_TRACE_BAD_BLOCKS, - (TSTR("**>> Block %d needs retiring" TENDSTR), blockInNAND)); -- -- - } - - /* Delete the chunk */ -@@ -1081,12 +1105,12 @@ static void yaffs_HandleWriteChunkError( - - /*---------------- Name handling functions ------------*/ - --static __u16 yaffs_CalcNameSum(const YCHAR * name) -+static __u16 yaffs_CalcNameSum(const YCHAR *name) - { - __u16 sum = 0; - __u16 i = 1; - -- YUCHAR *bname = (YUCHAR *) name; -+ const YUCHAR *bname = (const YUCHAR *) name; - if (bname) { - while ((*bname) && (i < (YAFFS_MAX_NAME_LENGTH/2))) { - -@@ -1102,14 +1126,14 @@ static __u16 yaffs_CalcNameSum(const YCH - return sum; - } - --static void yaffs_SetObjectName(yaffs_Object * obj, const YCHAR * name) -+static void yaffs_SetObjectName(yaffs_Object *obj, const YCHAR *name) - { - #ifdef CONFIG_YAFFS_SHORT_NAMES_IN_RAM -- if (name && yaffs_strlen(name) <= YAFFS_SHORT_NAME_LENGTH) { -+ memset(obj->shortName, 0, sizeof(YCHAR) * (YAFFS_SHORT_NAME_LENGTH+1)); -+ if (name && yaffs_strlen(name) <= YAFFS_SHORT_NAME_LENGTH) - yaffs_strcpy(obj->shortName, name); -- } else { -+ else - obj->shortName[0] = _Y('\0'); -- } - #endif - obj->sum = yaffs_CalcNameSum(name); - } -@@ -1126,7 +1150,7 @@ static void yaffs_SetObjectName(yaffs_Ob - * Don't use this function directly - */ - --static int yaffs_CreateTnodes(yaffs_Device * dev, int nTnodes) -+static int yaffs_CreateTnodes(yaffs_Device *dev, int nTnodes) - { - int i; - int tnodeSize; -@@ -1143,6 +1167,9 @@ static int yaffs_CreateTnodes(yaffs_Devi - * Must be a multiple of 32-bits */ - tnodeSize = (dev->tnodeWidth * YAFFS_NTNODES_LEVEL0)/8; - -+ if (tnodeSize < sizeof(yaffs_Tnode)) -+ tnodeSize = sizeof(yaffs_Tnode); -+ - /* make these things */ - - newTnodes = YMALLOC(nTnodes * tnodeSize); -@@ -1150,7 +1177,7 @@ static int yaffs_CreateTnodes(yaffs_Devi - - if (!newTnodes) { - T(YAFFS_TRACE_ERROR, -- (TSTR("yaffs: Could not allocate Tnodes" TENDSTR))); -+ (TSTR("yaffs: Could not allocate Tnodes" TENDSTR))); - return YAFFS_FAIL; - } - -@@ -1170,7 +1197,7 @@ static int yaffs_CreateTnodes(yaffs_Devi - dev->freeTnodes = newTnodes; - #else - /* New hookup for wide tnodes */ -- for(i = 0; i < nTnodes -1; i++) { -+ for (i = 0; i < nTnodes - 1; i++) { - curr = (yaffs_Tnode *) &mem[i * tnodeSize]; - next = (yaffs_Tnode *) &mem[(i+1) * tnodeSize]; - curr->internal[0] = next; -@@ -1197,7 +1224,6 @@ static int yaffs_CreateTnodes(yaffs_Devi - (TSTR - ("yaffs: Could not add tnodes to management list" TENDSTR))); - return YAFFS_FAIL; -- - } else { - tnl->tnodes = newTnodes; - tnl->next = dev->allocatedTnodeList; -@@ -1211,14 +1237,13 @@ static int yaffs_CreateTnodes(yaffs_Devi - - /* GetTnode gets us a clean tnode. Tries to make allocate more if we run out */ - --static yaffs_Tnode *yaffs_GetTnodeRaw(yaffs_Device * dev) -+static yaffs_Tnode *yaffs_GetTnodeRaw(yaffs_Device *dev) - { - yaffs_Tnode *tn = NULL; - - /* If there are none left make more */ -- if (!dev->freeTnodes) { -+ if (!dev->freeTnodes) - yaffs_CreateTnodes(dev, YAFFS_ALLOCATION_NTNODES); -- } - - if (dev->freeTnodes) { - tn = dev->freeTnodes; -@@ -1233,21 +1258,27 @@ static yaffs_Tnode *yaffs_GetTnodeRaw(ya - dev->nFreeTnodes--; - } - -+ dev->nCheckpointBlocksRequired = 0; /* force recalculation*/ -+ - return tn; - } - --static yaffs_Tnode *yaffs_GetTnode(yaffs_Device * dev) -+static yaffs_Tnode *yaffs_GetTnode(yaffs_Device *dev) - { - yaffs_Tnode *tn = yaffs_GetTnodeRaw(dev); -+ int tnodeSize = (dev->tnodeWidth * YAFFS_NTNODES_LEVEL0)/8; - -- if(tn) -- memset(tn, 0, (dev->tnodeWidth * YAFFS_NTNODES_LEVEL0)/8); -+ if (tnodeSize < sizeof(yaffs_Tnode)) -+ tnodeSize = sizeof(yaffs_Tnode); -+ -+ if (tn) -+ memset(tn, 0, tnodeSize); - - return tn; - } - - /* FreeTnode frees up a tnode and puts it back on the free list */ --static void yaffs_FreeTnode(yaffs_Device * dev, yaffs_Tnode * tn) -+static void yaffs_FreeTnode(yaffs_Device *dev, yaffs_Tnode *tn) - { - if (tn) { - #ifdef CONFIG_YAFFS_TNODE_LIST_DEBUG -@@ -1262,9 +1293,10 @@ static void yaffs_FreeTnode(yaffs_Device - dev->freeTnodes = tn; - dev->nFreeTnodes++; - } -+ dev->nCheckpointBlocksRequired = 0; /* force recalculation*/ - } - --static void yaffs_DeinitialiseTnodes(yaffs_Device * dev) -+static void yaffs_DeinitialiseTnodes(yaffs_Device *dev) - { - /* Free the list of allocated tnodes */ - yaffs_TnodeList *tmp; -@@ -1282,71 +1314,72 @@ static void yaffs_DeinitialiseTnodes(yaf - dev->nFreeTnodes = 0; - } - --static void yaffs_InitialiseTnodes(yaffs_Device * dev) -+static void yaffs_InitialiseTnodes(yaffs_Device *dev) - { - dev->allocatedTnodeList = NULL; - dev->freeTnodes = NULL; - dev->nFreeTnodes = 0; - dev->nTnodesCreated = 0; -- - } - - --void yaffs_PutLevel0Tnode(yaffs_Device *dev, yaffs_Tnode *tn, unsigned pos, unsigned val) -+void yaffs_PutLevel0Tnode(yaffs_Device *dev, yaffs_Tnode *tn, unsigned pos, -+ unsigned val) - { -- __u32 *map = (__u32 *)tn; -- __u32 bitInMap; -- __u32 bitInWord; -- __u32 wordInMap; -- __u32 mask; -+ __u32 *map = (__u32 *)tn; -+ __u32 bitInMap; -+ __u32 bitInWord; -+ __u32 wordInMap; -+ __u32 mask; - -- pos &= YAFFS_TNODES_LEVEL0_MASK; -- val >>= dev->chunkGroupBits; -+ pos &= YAFFS_TNODES_LEVEL0_MASK; -+ val >>= dev->chunkGroupBits; - -- bitInMap = pos * dev->tnodeWidth; -- wordInMap = bitInMap /32; -- bitInWord = bitInMap & (32 -1); -+ bitInMap = pos * dev->tnodeWidth; -+ wordInMap = bitInMap / 32; -+ bitInWord = bitInMap & (32 - 1); - -- mask = dev->tnodeMask << bitInWord; -+ mask = dev->tnodeMask << bitInWord; - -- map[wordInMap] &= ~mask; -- map[wordInMap] |= (mask & (val << bitInWord)); -+ map[wordInMap] &= ~mask; -+ map[wordInMap] |= (mask & (val << bitInWord)); - -- if(dev->tnodeWidth > (32-bitInWord)) { -- bitInWord = (32 - bitInWord); -- wordInMap++;; -- mask = dev->tnodeMask >> (/*dev->tnodeWidth -*/ bitInWord); -- map[wordInMap] &= ~mask; -- map[wordInMap] |= (mask & (val >> bitInWord)); -- } -+ if (dev->tnodeWidth > (32 - bitInWord)) { -+ bitInWord = (32 - bitInWord); -+ wordInMap++;; -+ mask = dev->tnodeMask >> (/*dev->tnodeWidth -*/ bitInWord); -+ map[wordInMap] &= ~mask; -+ map[wordInMap] |= (mask & (val >> bitInWord)); -+ } - } - --static __u32 yaffs_GetChunkGroupBase(yaffs_Device *dev, yaffs_Tnode *tn, unsigned pos) -+static __u32 yaffs_GetChunkGroupBase(yaffs_Device *dev, yaffs_Tnode *tn, -+ unsigned pos) - { -- __u32 *map = (__u32 *)tn; -- __u32 bitInMap; -- __u32 bitInWord; -- __u32 wordInMap; -- __u32 val; -+ __u32 *map = (__u32 *)tn; -+ __u32 bitInMap; -+ __u32 bitInWord; -+ __u32 wordInMap; -+ __u32 val; - -- pos &= YAFFS_TNODES_LEVEL0_MASK; -+ pos &= YAFFS_TNODES_LEVEL0_MASK; - -- bitInMap = pos * dev->tnodeWidth; -- wordInMap = bitInMap /32; -- bitInWord = bitInMap & (32 -1); -+ bitInMap = pos * dev->tnodeWidth; -+ wordInMap = bitInMap / 32; -+ bitInWord = bitInMap & (32 - 1); - -- val = map[wordInMap] >> bitInWord; -+ val = map[wordInMap] >> bitInWord; - -- if(dev->tnodeWidth > (32-bitInWord)) { -- bitInWord = (32 - bitInWord); -- wordInMap++;; -- val |= (map[wordInMap] << bitInWord); -- } -+ if (dev->tnodeWidth > (32 - bitInWord)) { -+ bitInWord = (32 - bitInWord); -+ wordInMap++;; -+ val |= (map[wordInMap] << bitInWord); -+ } - -- val &= dev->tnodeMask; -- val <<= dev->chunkGroupBits; -+ val &= dev->tnodeMask; -+ val <<= dev->chunkGroupBits; - -- return val; -+ return val; - } - - /* ------------------- End of individual tnode manipulation -----------------*/ -@@ -1357,24 +1390,21 @@ static __u32 yaffs_GetChunkGroupBase(yaf - */ - - /* FindLevel0Tnode finds the level 0 tnode, if one exists. */ --static yaffs_Tnode *yaffs_FindLevel0Tnode(yaffs_Device * dev, -- yaffs_FileStructure * fStruct, -- __u32 chunkId) -+static yaffs_Tnode *yaffs_FindLevel0Tnode(yaffs_Device *dev, -+ yaffs_FileStructure *fStruct, -+ __u32 chunkId) - { -- - yaffs_Tnode *tn = fStruct->top; - __u32 i; - int requiredTallness; - int level = fStruct->topLevel; - - /* Check sane level and chunk Id */ -- if (level < 0 || level > YAFFS_TNODES_MAX_LEVEL) { -+ if (level < 0 || level > YAFFS_TNODES_MAX_LEVEL) - return NULL; -- } - -- if (chunkId > YAFFS_MAX_CHUNK_ID) { -+ if (chunkId > YAFFS_MAX_CHUNK_ID) - return NULL; -- } - - /* First check we're tall enough (ie enough topLevel) */ - -@@ -1385,22 +1415,17 @@ static yaffs_Tnode *yaffs_FindLevel0Tnod - requiredTallness++; - } - -- if (requiredTallness > fStruct->topLevel) { -- /* Not tall enough, so we can't find it, return NULL. */ -- return NULL; -- } -+ if (requiredTallness > fStruct->topLevel) -+ return NULL; /* Not tall enough, so we can't find it */ - - /* Traverse down to level 0 */ - while (level > 0 && tn) { -- tn = tn-> -- internal[(chunkId >> -- ( YAFFS_TNODES_LEVEL0_BITS + -- (level - 1) * -- YAFFS_TNODES_INTERNAL_BITS) -- ) & -- YAFFS_TNODES_INTERNAL_MASK]; -+ tn = tn->internal[(chunkId >> -+ (YAFFS_TNODES_LEVEL0_BITS + -+ (level - 1) * -+ YAFFS_TNODES_INTERNAL_BITS)) & -+ YAFFS_TNODES_INTERNAL_MASK]; - level--; -- - } - - return tn; -@@ -1417,12 +1442,11 @@ static yaffs_Tnode *yaffs_FindLevel0Tnod - * be plugged into the ttree. - */ - --static yaffs_Tnode *yaffs_AddOrFindLevel0Tnode(yaffs_Device * dev, -- yaffs_FileStructure * fStruct, -- __u32 chunkId, -- yaffs_Tnode *passedTn) -+static yaffs_Tnode *yaffs_AddOrFindLevel0Tnode(yaffs_Device *dev, -+ yaffs_FileStructure *fStruct, -+ __u32 chunkId, -+ yaffs_Tnode *passedTn) - { -- - int requiredTallness; - int i; - int l; -@@ -1432,13 +1456,11 @@ static yaffs_Tnode *yaffs_AddOrFindLevel - - - /* Check sane level and page Id */ -- if (fStruct->topLevel < 0 || fStruct->topLevel > YAFFS_TNODES_MAX_LEVEL) { -+ if (fStruct->topLevel < 0 || fStruct->topLevel > YAFFS_TNODES_MAX_LEVEL) - return NULL; -- } - -- if (chunkId > YAFFS_MAX_CHUNK_ID) { -+ if (chunkId > YAFFS_MAX_CHUNK_ID) - return NULL; -- } - - /* First check we're tall enough (ie enough topLevel) */ - -@@ -1451,7 +1473,7 @@ static yaffs_Tnode *yaffs_AddOrFindLevel - - - if (requiredTallness > fStruct->topLevel) { -- /* Not tall enough,gotta make the tree taller */ -+ /* Not tall enough, gotta make the tree taller */ - for (i = fStruct->topLevel; i < requiredTallness; i++) { - - tn = yaffs_GetTnode(dev); -@@ -1473,27 +1495,27 @@ static yaffs_Tnode *yaffs_AddOrFindLevel - l = fStruct->topLevel; - tn = fStruct->top; - -- if(l > 0) { -+ if (l > 0) { - while (l > 0 && tn) { - x = (chunkId >> -- ( YAFFS_TNODES_LEVEL0_BITS + -+ (YAFFS_TNODES_LEVEL0_BITS + - (l - 1) * YAFFS_TNODES_INTERNAL_BITS)) & - YAFFS_TNODES_INTERNAL_MASK; - - -- if((l>1) && !tn->internal[x]){ -+ if ((l > 1) && !tn->internal[x]) { - /* Add missing non-level-zero tnode */ - tn->internal[x] = yaffs_GetTnode(dev); - -- } else if(l == 1) { -+ } else if (l == 1) { - /* Looking from level 1 at level 0 */ -- if (passedTn) { -+ if (passedTn) { - /* If we already have one, then release it.*/ -- if(tn->internal[x]) -- yaffs_FreeTnode(dev,tn->internal[x]); -+ if (tn->internal[x]) -+ yaffs_FreeTnode(dev, tn->internal[x]); - tn->internal[x] = passedTn; - -- } else if(!tn->internal[x]) { -+ } else if (!tn->internal[x]) { - /* Don't have one, none passed in */ - tn->internal[x] = yaffs_GetTnode(dev); - } -@@ -1504,31 +1526,29 @@ static yaffs_Tnode *yaffs_AddOrFindLevel - } - } else { - /* top is level 0 */ -- if(passedTn) { -- memcpy(tn,passedTn,(dev->tnodeWidth * YAFFS_NTNODES_LEVEL0)/8); -- yaffs_FreeTnode(dev,passedTn); -+ if (passedTn) { -+ memcpy(tn, passedTn, (dev->tnodeWidth * YAFFS_NTNODES_LEVEL0)/8); -+ yaffs_FreeTnode(dev, passedTn); - } - } - - return tn; - } - --static int yaffs_FindChunkInGroup(yaffs_Device * dev, int theChunk, -- yaffs_ExtendedTags * tags, int objectId, -- int chunkInInode) -+static int yaffs_FindChunkInGroup(yaffs_Device *dev, int theChunk, -+ yaffs_ExtendedTags *tags, int objectId, -+ int chunkInInode) - { - int j; - - for (j = 0; theChunk && j < dev->chunkGroupSize; j++) { -- if (yaffs_CheckChunkBit -- (dev, theChunk / dev->nChunksPerBlock, -- theChunk % dev->nChunksPerBlock)) { -+ if (yaffs_CheckChunkBit(dev, theChunk / dev->nChunksPerBlock, -+ theChunk % dev->nChunksPerBlock)) { - yaffs_ReadChunkWithTagsFromNAND(dev, theChunk, NULL, - tags); - if (yaffs_TagsMatch(tags, objectId, chunkInInode)) { - /* found it; */ - return theChunk; -- - } - } - theChunk++; -@@ -1543,7 +1563,7 @@ static int yaffs_FindChunkInGroup(yaffs_ - * Returns 0 if it stopped early due to hitting the limit and the delete is incomplete. - */ - --static int yaffs_DeleteWorker(yaffs_Object * in, yaffs_Tnode * tn, __u32 level, -+static int yaffs_DeleteWorker(yaffs_Object *in, yaffs_Tnode *tn, __u32 level, - int chunkOffset, int *limit) - { - int i; -@@ -1557,7 +1577,6 @@ static int yaffs_DeleteWorker(yaffs_Obje - - if (tn) { - if (level > 0) { -- - for (i = YAFFS_NTNODES_INTERNAL - 1; allDone && i >= 0; - i--) { - if (tn->internal[i]) { -@@ -1565,17 +1584,17 @@ static int yaffs_DeleteWorker(yaffs_Obje - allDone = 0; - } else { - allDone = -- yaffs_DeleteWorker(in, -- tn-> -- internal -- [i], -- level - -- 1, -- (chunkOffset -+ yaffs_DeleteWorker(in, -+ tn-> -+ internal -+ [i], -+ level - -+ 1, -+ (chunkOffset - << - YAFFS_TNODES_INTERNAL_BITS) -- + i, -- limit); -+ + i, -+ limit); - } - if (allDone) { - yaffs_FreeTnode(dev, -@@ -1584,27 +1603,25 @@ static int yaffs_DeleteWorker(yaffs_Obje - tn->internal[i] = NULL; - } - } -- - } - return (allDone) ? 1 : 0; - } else if (level == 0) { - int hitLimit = 0; - - for (i = YAFFS_NTNODES_LEVEL0 - 1; i >= 0 && !hitLimit; -- i--) { -- theChunk = yaffs_GetChunkGroupBase(dev,tn,i); -+ i--) { -+ theChunk = yaffs_GetChunkGroupBase(dev, tn, i); - if (theChunk) { - -- chunkInInode = -- (chunkOffset << -- YAFFS_TNODES_LEVEL0_BITS) + i; -+ chunkInInode = (chunkOffset << -+ YAFFS_TNODES_LEVEL0_BITS) + i; - - foundChunk = -- yaffs_FindChunkInGroup(dev, -- theChunk, -- &tags, -- in->objectId, -- chunkInInode); -+ yaffs_FindChunkInGroup(dev, -+ theChunk, -+ &tags, -+ in->objectId, -+ chunkInInode); - - if (foundChunk > 0) { - yaffs_DeleteChunk(dev, -@@ -1613,14 +1630,13 @@ static int yaffs_DeleteWorker(yaffs_Obje - in->nDataChunks--; - if (limit) { - *limit = *limit - 1; -- if (*limit <= 0) { -+ if (*limit <= 0) - hitLimit = 1; -- } - } - - } - -- yaffs_PutLevel0Tnode(dev,tn,i,0); -+ yaffs_PutLevel0Tnode(dev, tn, i, 0); - } - - } -@@ -1634,9 +1650,8 @@ static int yaffs_DeleteWorker(yaffs_Obje - - } - --static void yaffs_SoftDeleteChunk(yaffs_Device * dev, int chunk) -+static void yaffs_SoftDeleteChunk(yaffs_Device *dev, int chunk) - { -- - yaffs_BlockInfo *theBlock; - - T(YAFFS_TRACE_DELETION, (TSTR("soft delete chunk %d" TENDSTR), chunk)); -@@ -1654,7 +1669,7 @@ static void yaffs_SoftDeleteChunk(yaffs_ - * Thus, essentially this is the same as DeleteWorker except that the chunks are soft deleted. - */ - --static int yaffs_SoftDeleteWorker(yaffs_Object * in, yaffs_Tnode * tn, -+static int yaffs_SoftDeleteWorker(yaffs_Object *in, yaffs_Tnode *tn, - __u32 level, int chunkOffset) - { - int i; -@@ -1691,14 +1706,14 @@ static int yaffs_SoftDeleteWorker(yaffs_ - } else if (level == 0) { - - for (i = YAFFS_NTNODES_LEVEL0 - 1; i >= 0; i--) { -- theChunk = yaffs_GetChunkGroupBase(dev,tn,i); -+ theChunk = yaffs_GetChunkGroupBase(dev, tn, i); - if (theChunk) { - /* Note this does not find the real chunk, only the chunk group. - * We make an assumption that a chunk group is not larger than - * a block. - */ - yaffs_SoftDeleteChunk(dev, theChunk); -- yaffs_PutLevel0Tnode(dev,tn,i,0); -+ yaffs_PutLevel0Tnode(dev, tn, i, 0); - } - - } -@@ -1712,7 +1727,7 @@ static int yaffs_SoftDeleteWorker(yaffs_ - - } - --static void yaffs_SoftDeleteFile(yaffs_Object * obj) -+static void yaffs_SoftDeleteFile(yaffs_Object *obj) - { - if (obj->deleted && - obj->variantType == YAFFS_OBJECT_TYPE_FILE && !obj->softDeleted) { -@@ -1746,8 +1761,8 @@ static void yaffs_SoftDeleteFile(yaffs_O - * by a special case. - */ - --static yaffs_Tnode *yaffs_PruneWorker(yaffs_Device * dev, yaffs_Tnode * tn, -- __u32 level, int del0) -+static yaffs_Tnode *yaffs_PruneWorker(yaffs_Device *dev, yaffs_Tnode *tn, -+ __u32 level, int del0) - { - int i; - int hasData; -@@ -1763,9 +1778,8 @@ static yaffs_Tnode *yaffs_PruneWorker(ya - (i == 0) ? del0 : 1); - } - -- if (tn->internal[i]) { -+ if (tn->internal[i]) - hasData++; -- } - } - - if (hasData == 0 && del0) { -@@ -1781,8 +1795,8 @@ static yaffs_Tnode *yaffs_PruneWorker(ya - - } - --static int yaffs_PruneFileStructure(yaffs_Device * dev, -- yaffs_FileStructure * fStruct) -+static int yaffs_PruneFileStructure(yaffs_Device *dev, -+ yaffs_FileStructure *fStruct) - { - int i; - int hasData; -@@ -1805,9 +1819,8 @@ static int yaffs_PruneFileStructure(yaff - - hasData = 0; - for (i = 1; i < YAFFS_NTNODES_INTERNAL; i++) { -- if (tn->internal[i]) { -+ if (tn->internal[i]) - hasData++; -- } - } - - if (!hasData) { -@@ -1828,7 +1841,7 @@ static int yaffs_PruneFileStructure(yaff - /* yaffs_CreateFreeObjects creates a bunch more objects and - * adds them to the object free list. - */ --static int yaffs_CreateFreeObjects(yaffs_Device * dev, int nObjects) -+static int yaffs_CreateFreeObjects(yaffs_Device *dev, int nObjects) - { - int i; - yaffs_Object *newObjects; -@@ -1842,9 +1855,9 @@ static int yaffs_CreateFreeObjects(yaffs - list = YMALLOC(sizeof(yaffs_ObjectList)); - - if (!newObjects || !list) { -- if(newObjects) -+ if (newObjects) - YFREE(newObjects); -- if(list) -+ if (list) - YFREE(list); - T(YAFFS_TRACE_ALLOCATE, - (TSTR("yaffs: Could not allocate more objects" TENDSTR))); -@@ -1854,7 +1867,7 @@ static int yaffs_CreateFreeObjects(yaffs - /* Hook them into the free list */ - for (i = 0; i < nObjects - 1; i++) { - newObjects[i].siblings.next = -- (struct list_head *)(&newObjects[i + 1]); -+ (struct ylist_head *)(&newObjects[i + 1]); - } - - newObjects[nObjects - 1].siblings.next = (void *)dev->freeObjects; -@@ -1873,85 +1886,109 @@ static int yaffs_CreateFreeObjects(yaffs - - - /* AllocateEmptyObject gets us a clean Object. Tries to make allocate more if we run out */ --static yaffs_Object *yaffs_AllocateEmptyObject(yaffs_Device * dev) -+static yaffs_Object *yaffs_AllocateEmptyObject(yaffs_Device *dev) - { - yaffs_Object *tn = NULL; - -+#ifdef VALGRIND_TEST -+ tn = YMALLOC(sizeof(yaffs_Object)); -+#else - /* If there are none left make more */ -- if (!dev->freeObjects) { -+ if (!dev->freeObjects) - yaffs_CreateFreeObjects(dev, YAFFS_ALLOCATION_NOBJECTS); -- } - - if (dev->freeObjects) { - tn = dev->freeObjects; - dev->freeObjects = -- (yaffs_Object *) (dev->freeObjects->siblings.next); -+ (yaffs_Object *) (dev->freeObjects->siblings.next); - dev->nFreeObjects--; -- -+ } -+#endif -+ if (tn) { - /* Now sweeten it up... */ - - memset(tn, 0, sizeof(yaffs_Object)); -+ tn->beingCreated = 1; -+ - tn->myDev = dev; -- tn->chunkId = -1; -+ tn->hdrChunk = 0; - tn->variantType = YAFFS_OBJECT_TYPE_UNKNOWN; -- INIT_LIST_HEAD(&(tn->hardLinks)); -- INIT_LIST_HEAD(&(tn->hashLink)); -- INIT_LIST_HEAD(&tn->siblings); -+ YINIT_LIST_HEAD(&(tn->hardLinks)); -+ YINIT_LIST_HEAD(&(tn->hashLink)); -+ YINIT_LIST_HEAD(&tn->siblings); -+ -+ -+ /* Now make the directory sane */ -+ if (dev->rootDir) { -+ tn->parent = dev->rootDir; -+ ylist_add(&(tn->siblings), &dev->rootDir->variant.directoryVariant.children); -+ } - - /* Add it to the lost and found directory. - * NB Can't put root or lostNFound in lostNFound so - * check if lostNFound exists first - */ -- if (dev->lostNFoundDir) { -+ if (dev->lostNFoundDir) - yaffs_AddObjectToDirectory(dev->lostNFoundDir, tn); -- } -+ -+ tn->beingCreated = 0; - } - -+ dev->nCheckpointBlocksRequired = 0; /* force recalculation*/ -+ - return tn; - } - --static yaffs_Object *yaffs_CreateFakeDirectory(yaffs_Device * dev, int number, -+static yaffs_Object *yaffs_CreateFakeDirectory(yaffs_Device *dev, int number, - __u32 mode) - { - - yaffs_Object *obj = - yaffs_CreateNewObject(dev, number, YAFFS_OBJECT_TYPE_DIRECTORY); - if (obj) { -- obj->fake = 1; /* it is fake so it has no NAND presence... */ -+ obj->fake = 1; /* it is fake so it might have no NAND presence... */ - obj->renameAllowed = 0; /* ... and we're not allowed to rename it... */ - obj->unlinkAllowed = 0; /* ... or unlink it */ - obj->deleted = 0; - obj->unlinked = 0; - obj->yst_mode = mode; - obj->myDev = dev; -- obj->chunkId = 0; /* Not a valid chunk. */ -+ obj->hdrChunk = 0; /* Not a valid chunk. */ - } - - return obj; - - } - --static void yaffs_UnhashObject(yaffs_Object * tn) -+static void yaffs_UnhashObject(yaffs_Object *tn) - { - int bucket; - yaffs_Device *dev = tn->myDev; - - /* If it is still linked into the bucket list, free from the list */ -- if (!list_empty(&tn->hashLink)) { -- list_del_init(&tn->hashLink); -+ if (!ylist_empty(&tn->hashLink)) { -+ ylist_del_init(&tn->hashLink); - bucket = yaffs_HashFunction(tn->objectId); - dev->objectBucket[bucket].count--; - } -- - } - - /* FreeObject frees up a Object and puts it back on the free list */ --static void yaffs_FreeObject(yaffs_Object * tn) -+static void yaffs_FreeObject(yaffs_Object *tn) - { -- - yaffs_Device *dev = tn->myDev; - --#ifdef __KERNEL__ -+#ifdef __KERNEL__ -+ T(YAFFS_TRACE_OS, (TSTR("FreeObject %p inode %p"TENDSTR), tn, tn->myInode)); -+#endif -+ -+ if (tn->parent) -+ YBUG(); -+ if (!ylist_empty(&tn->siblings)) -+ YBUG(); -+ -+ -+#ifdef __KERNEL__ - if (tn->myInode) { - /* We're still hooked up to a cached inode. - * Don't delete now, but mark for later deletion -@@ -1963,24 +2000,28 @@ static void yaffs_FreeObject(yaffs_Objec - - yaffs_UnhashObject(tn); - -+#ifdef VALGRIND_TEST -+ YFREE(tn); -+#else - /* Link into the free list. */ -- tn->siblings.next = (struct list_head *)(dev->freeObjects); -+ tn->siblings.next = (struct ylist_head *)(dev->freeObjects); - dev->freeObjects = tn; - dev->nFreeObjects++; -+#endif -+ dev->nCheckpointBlocksRequired = 0; /* force recalculation*/ - } - - #ifdef __KERNEL__ - --void yaffs_HandleDeferedFree(yaffs_Object * obj) -+void yaffs_HandleDeferedFree(yaffs_Object *obj) - { -- if (obj->deferedFree) { -+ if (obj->deferedFree) - yaffs_FreeObject(obj); -- } - } - - #endif - --static void yaffs_DeinitialiseObjects(yaffs_Device * dev) -+static void yaffs_DeinitialiseObjects(yaffs_Device *dev) - { - /* Free the list of allocated Objects */ - -@@ -1998,7 +2039,7 @@ static void yaffs_DeinitialiseObjects(ya - dev->nFreeObjects = 0; - } - --static void yaffs_InitialiseObjects(yaffs_Device * dev) -+static void yaffs_InitialiseObjects(yaffs_Device *dev) - { - int i; - -@@ -2007,15 +2048,14 @@ static void yaffs_InitialiseObjects(yaff - dev->nFreeObjects = 0; - - for (i = 0; i < YAFFS_NOBJECT_BUCKETS; i++) { -- INIT_LIST_HEAD(&dev->objectBucket[i].list); -+ YINIT_LIST_HEAD(&dev->objectBucket[i].list); - dev->objectBucket[i].count = 0; - } -- - } - --static int yaffs_FindNiceObjectBucket(yaffs_Device * dev) -+static int yaffs_FindNiceObjectBucket(yaffs_Device *dev) - { -- static int x = 0; -+ static int x; - int i; - int l = 999; - int lowest = 999999; -@@ -2049,7 +2089,7 @@ static int yaffs_FindNiceObjectBucket(ya - return l; - } - --static int yaffs_CreateNewObjectNumber(yaffs_Device * dev) -+static int yaffs_CreateNewObjectNumber(yaffs_Device *dev) - { - int bucket = yaffs_FindNiceObjectBucket(dev); - -@@ -2058,7 +2098,7 @@ static int yaffs_CreateNewObjectNumber(y - */ - - int found = 0; -- struct list_head *i; -+ struct ylist_head *i; - - __u32 n = (__u32) bucket; - -@@ -2068,41 +2108,38 @@ static int yaffs_CreateNewObjectNumber(y - found = 1; - n += YAFFS_NOBJECT_BUCKETS; - if (1 || dev->objectBucket[bucket].count > 0) { -- list_for_each(i, &dev->objectBucket[bucket].list) { -+ ylist_for_each(i, &dev->objectBucket[bucket].list) { - /* If there is already one in the list */ -- if (i -- && list_entry(i, yaffs_Object, -- hashLink)->objectId == n) { -+ if (i && ylist_entry(i, yaffs_Object, -+ hashLink)->objectId == n) { - found = 0; - } - } - } - } - -- - return n; - } - --static void yaffs_HashObject(yaffs_Object * in) -+static void yaffs_HashObject(yaffs_Object *in) - { - int bucket = yaffs_HashFunction(in->objectId); - yaffs_Device *dev = in->myDev; - -- list_add(&in->hashLink, &dev->objectBucket[bucket].list); -+ ylist_add(&in->hashLink, &dev->objectBucket[bucket].list); - dev->objectBucket[bucket].count++; -- - } - --yaffs_Object *yaffs_FindObjectByNumber(yaffs_Device * dev, __u32 number) -+yaffs_Object *yaffs_FindObjectByNumber(yaffs_Device *dev, __u32 number) - { - int bucket = yaffs_HashFunction(number); -- struct list_head *i; -+ struct ylist_head *i; - yaffs_Object *in; - -- list_for_each(i, &dev->objectBucket[bucket].list) { -+ ylist_for_each(i, &dev->objectBucket[bucket].list) { - /* Look if it is in the list */ - if (i) { -- in = list_entry(i, yaffs_Object, hashLink); -+ in = ylist_entry(i, yaffs_Object, hashLink); - if (in->objectId == number) { - #ifdef __KERNEL__ - /* Don't tell the VFS about this one if it is defered free */ -@@ -2118,31 +2155,27 @@ yaffs_Object *yaffs_FindObjectByNumber(y - return NULL; - } - --yaffs_Object *yaffs_CreateNewObject(yaffs_Device * dev, int number, -+yaffs_Object *yaffs_CreateNewObject(yaffs_Device *dev, int number, - yaffs_ObjectType type) - { -- - yaffs_Object *theObject; -- yaffs_Tnode *tn; -+ yaffs_Tnode *tn = NULL; - -- if (number < 0) { -+ if (number < 0) - number = yaffs_CreateNewObjectNumber(dev); -- } - - theObject = yaffs_AllocateEmptyObject(dev); -- if(!theObject) -+ if (!theObject) - return NULL; - -- if(type == YAFFS_OBJECT_TYPE_FILE){ -+ if (type == YAFFS_OBJECT_TYPE_FILE) { - tn = yaffs_GetTnode(dev); -- if(!tn){ -+ if (!tn) { - yaffs_FreeObject(theObject); - return NULL; - } - } - -- -- - if (theObject) { - theObject->fake = 0; - theObject->renameAllowed = 1; -@@ -2171,8 +2204,8 @@ yaffs_Object *yaffs_CreateNewObject(yaff - theObject->variant.fileVariant.top = tn; - break; - case YAFFS_OBJECT_TYPE_DIRECTORY: -- INIT_LIST_HEAD(&theObject->variant.directoryVariant. -- children); -+ YINIT_LIST_HEAD(&theObject->variant.directoryVariant. -+ children); - break; - case YAFFS_OBJECT_TYPE_SYMLINK: - case YAFFS_OBJECT_TYPE_HARDLINK: -@@ -2188,32 +2221,30 @@ yaffs_Object *yaffs_CreateNewObject(yaff - return theObject; - } - --static yaffs_Object *yaffs_FindOrCreateObjectByNumber(yaffs_Device * dev, -+static yaffs_Object *yaffs_FindOrCreateObjectByNumber(yaffs_Device *dev, - int number, - yaffs_ObjectType type) - { - yaffs_Object *theObject = NULL; - -- if (number > 0) { -+ if (number > 0) - theObject = yaffs_FindObjectByNumber(dev, number); -- } - -- if (!theObject) { -+ if (!theObject) - theObject = yaffs_CreateNewObject(dev, number, type); -- } - - return theObject; - - } - - --static YCHAR *yaffs_CloneString(const YCHAR * str) -+static YCHAR *yaffs_CloneString(const YCHAR *str) - { - YCHAR *newStr = NULL; - - if (str && *str) { - newStr = YMALLOC((yaffs_strlen(str) + 1) * sizeof(YCHAR)); -- if(newStr) -+ if (newStr) - yaffs_strcpy(newStr, str); - } - -@@ -2229,29 +2260,31 @@ static YCHAR *yaffs_CloneString(const YC - */ - - static yaffs_Object *yaffs_MknodObject(yaffs_ObjectType type, -- yaffs_Object * parent, -- const YCHAR * name, -+ yaffs_Object *parent, -+ const YCHAR *name, - __u32 mode, - __u32 uid, - __u32 gid, -- yaffs_Object * equivalentObject, -- const YCHAR * aliasString, __u32 rdev) -+ yaffs_Object *equivalentObject, -+ const YCHAR *aliasString, __u32 rdev) - { - yaffs_Object *in; -- YCHAR *str; -+ YCHAR *str = NULL; - - yaffs_Device *dev = parent->myDev; - - /* Check if the entry exists. If it does then fail the call since we don't want a dup.*/ -- if (yaffs_FindObjectByName(parent, name)) { -+ if (yaffs_FindObjectByName(parent, name)) - return NULL; -- } - - in = yaffs_CreateNewObject(dev, -1, type); - -- if(type == YAFFS_OBJECT_TYPE_SYMLINK){ -+ if (!in) -+ return YAFFS_FAIL; -+ -+ if (type == YAFFS_OBJECT_TYPE_SYMLINK) { - str = yaffs_CloneString(aliasString); -- if(!str){ -+ if (!str) { - yaffs_FreeObject(in); - return NULL; - } -@@ -2260,7 +2293,7 @@ static yaffs_Object *yaffs_MknodObject(y - - - if (in) { -- in->chunkId = -1; -+ in->hdrChunk = 0; - in->valid = 1; - in->variantType = type; - -@@ -2293,10 +2326,10 @@ static yaffs_Object *yaffs_MknodObject(y - break; - case YAFFS_OBJECT_TYPE_HARDLINK: - in->variant.hardLinkVariant.equivalentObject = -- equivalentObject; -+ equivalentObject; - in->variant.hardLinkVariant.equivalentObjectId = -- equivalentObject->objectId; -- list_add(&in->hardLinks, &equivalentObject->hardLinks); -+ equivalentObject->objectId; -+ ylist_add(&in->hardLinks, &equivalentObject->hardLinks); - break; - case YAFFS_OBJECT_TYPE_FILE: - case YAFFS_OBJECT_TYPE_DIRECTORY: -@@ -2308,7 +2341,7 @@ static yaffs_Object *yaffs_MknodObject(y - - if (yaffs_UpdateObjectHeader(in, name, 0, 0, 0) < 0) { - /* Could not create the object header, fail the creation */ -- yaffs_DestroyObject(in); -+ yaffs_DeleteObject(in); - in = NULL; - } - -@@ -2317,38 +2350,38 @@ static yaffs_Object *yaffs_MknodObject(y - return in; - } - --yaffs_Object *yaffs_MknodFile(yaffs_Object * parent, const YCHAR * name, -- __u32 mode, __u32 uid, __u32 gid) -+yaffs_Object *yaffs_MknodFile(yaffs_Object *parent, const YCHAR *name, -+ __u32 mode, __u32 uid, __u32 gid) - { - return yaffs_MknodObject(YAFFS_OBJECT_TYPE_FILE, parent, name, mode, -- uid, gid, NULL, NULL, 0); -+ uid, gid, NULL, NULL, 0); - } - --yaffs_Object *yaffs_MknodDirectory(yaffs_Object * parent, const YCHAR * name, -- __u32 mode, __u32 uid, __u32 gid) -+yaffs_Object *yaffs_MknodDirectory(yaffs_Object *parent, const YCHAR *name, -+ __u32 mode, __u32 uid, __u32 gid) - { - return yaffs_MknodObject(YAFFS_OBJECT_TYPE_DIRECTORY, parent, name, - mode, uid, gid, NULL, NULL, 0); - } - --yaffs_Object *yaffs_MknodSpecial(yaffs_Object * parent, const YCHAR * name, -- __u32 mode, __u32 uid, __u32 gid, __u32 rdev) -+yaffs_Object *yaffs_MknodSpecial(yaffs_Object *parent, const YCHAR *name, -+ __u32 mode, __u32 uid, __u32 gid, __u32 rdev) - { - return yaffs_MknodObject(YAFFS_OBJECT_TYPE_SPECIAL, parent, name, mode, - uid, gid, NULL, NULL, rdev); - } - --yaffs_Object *yaffs_MknodSymLink(yaffs_Object * parent, const YCHAR * name, -- __u32 mode, __u32 uid, __u32 gid, -- const YCHAR * alias) -+yaffs_Object *yaffs_MknodSymLink(yaffs_Object *parent, const YCHAR *name, -+ __u32 mode, __u32 uid, __u32 gid, -+ const YCHAR *alias) - { - return yaffs_MknodObject(YAFFS_OBJECT_TYPE_SYMLINK, parent, name, mode, -- uid, gid, NULL, alias, 0); -+ uid, gid, NULL, alias, 0); - } - - /* yaffs_Link returns the object id of the equivalent object.*/ --yaffs_Object *yaffs_Link(yaffs_Object * parent, const YCHAR * name, -- yaffs_Object * equivalentObject) -+yaffs_Object *yaffs_Link(yaffs_Object *parent, const YCHAR *name, -+ yaffs_Object *equivalentObject) - { - /* Get the real object in case we were fed a hard link as an equivalent object */ - equivalentObject = yaffs_GetEquivalentObject(equivalentObject); -@@ -2363,33 +2396,31 @@ yaffs_Object *yaffs_Link(yaffs_Object * - - } - --static int yaffs_ChangeObjectName(yaffs_Object * obj, yaffs_Object * newDir, -- const YCHAR * newName, int force, int shadows) -+static int yaffs_ChangeObjectName(yaffs_Object *obj, yaffs_Object *newDir, -+ const YCHAR *newName, int force, int shadows) - { - int unlinkOp; - int deleteOp; - - yaffs_Object *existingTarget; - -- if (newDir == NULL) { -+ if (newDir == NULL) - newDir = obj->parent; /* use the old directory */ -- } - - if (newDir->variantType != YAFFS_OBJECT_TYPE_DIRECTORY) { - T(YAFFS_TRACE_ALWAYS, - (TSTR -- ("tragendy: yaffs_ChangeObjectName: newDir is not a directory" -+ ("tragedy: yaffs_ChangeObjectName: newDir is not a directory" - TENDSTR))); - YBUG(); - } - - /* TODO: Do we need this different handling for YAFFS2 and YAFFS1?? */ -- if (obj->myDev->isYaffs2) { -+ if (obj->myDev->isYaffs2) - unlinkOp = (newDir == obj->myDev->unlinkedDir); -- } else { -+ else - unlinkOp = (newDir == obj->myDev->unlinkedDir - && obj->variantType == YAFFS_OBJECT_TYPE_FILE); -- } - - deleteOp = (newDir == obj->myDev->deletedDir); - -@@ -2415,40 +2446,40 @@ static int yaffs_ChangeObjectName(yaffs_ - obj->unlinked = 1; - - /* If it is a deletion then we mark it as a shrink for gc purposes. */ -- if (yaffs_UpdateObjectHeader(obj, newName, 0, deleteOp, shadows)>= 0) -+ if (yaffs_UpdateObjectHeader(obj, newName, 0, deleteOp, shadows) >= 0) - return YAFFS_OK; - } - - return YAFFS_FAIL; - } - --int yaffs_RenameObject(yaffs_Object * oldDir, const YCHAR * oldName, -- yaffs_Object * newDir, const YCHAR * newName) -+int yaffs_RenameObject(yaffs_Object *oldDir, const YCHAR *oldName, -+ yaffs_Object *newDir, const YCHAR *newName) - { -- yaffs_Object *obj; -- yaffs_Object *existingTarget; -+ yaffs_Object *obj = NULL; -+ yaffs_Object *existingTarget = NULL; - int force = 0; - -+ -+ if (!oldDir || oldDir->variantType != YAFFS_OBJECT_TYPE_DIRECTORY) -+ YBUG(); -+ if (!newDir || newDir->variantType != YAFFS_OBJECT_TYPE_DIRECTORY) -+ YBUG(); -+ - #ifdef CONFIG_YAFFS_CASE_INSENSITIVE - /* Special case for case insemsitive systems (eg. WinCE). - * While look-up is case insensitive, the name isn't. - * Therefore we might want to change x.txt to X.txt - */ -- if (oldDir == newDir && yaffs_strcmp(oldName, newName) == 0) { -+ if (oldDir == newDir && yaffs_strcmp(oldName, newName) == 0) - force = 1; -- } - #endif - -+ else if (yaffs_strlen(newName) > YAFFS_MAX_NAME_LENGTH) -+ /* ENAMETOOLONG */ -+ return YAFFS_FAIL; -+ - obj = yaffs_FindObjectByName(oldDir, oldName); -- /* Check new name to long. */ -- if (obj->variantType == YAFFS_OBJECT_TYPE_SYMLINK && -- yaffs_strlen(newName) > YAFFS_MAX_ALIAS_LENGTH) -- /* ENAMETOOLONG */ -- return YAFFS_FAIL; -- else if (obj->variantType != YAFFS_OBJECT_TYPE_SYMLINK && -- yaffs_strlen(newName) > YAFFS_MAX_NAME_LENGTH) -- /* ENAMETOOLONG */ -- return YAFFS_FAIL; - - if (obj && obj->renameAllowed) { - -@@ -2456,8 +2487,8 @@ int yaffs_RenameObject(yaffs_Object * ol - - existingTarget = yaffs_FindObjectByName(newDir, newName); - if (existingTarget && -- existingTarget->variantType == YAFFS_OBJECT_TYPE_DIRECTORY && -- !list_empty(&existingTarget->variant.directoryVariant.children)) { -+ existingTarget->variantType == YAFFS_OBJECT_TYPE_DIRECTORY && -+ !ylist_empty(&existingTarget->variant.directoryVariant.children)) { - /* There is a target that is a non-empty directory, so we fail */ - return YAFFS_FAIL; /* EEXIST or ENOTEMPTY */ - } else if (existingTarget && existingTarget != obj) { -@@ -2465,7 +2496,7 @@ int yaffs_RenameObject(yaffs_Object * ol - * but only if it isn't the same object - */ - yaffs_ChangeObjectName(obj, newDir, newName, force, -- existingTarget->objectId); -+ existingTarget->objectId); - yaffs_UnlinkObject(existingTarget); - } - -@@ -2476,7 +2507,7 @@ int yaffs_RenameObject(yaffs_Object * ol - - /*------------------------- Block Management and Page Allocation ----------------*/ - --static int yaffs_InitialiseBlocks(yaffs_Device * dev) -+static int yaffs_InitialiseBlocks(yaffs_Device *dev) - { - int nBlocks = dev->internalEndBlock - dev->internalStartBlock + 1; - -@@ -2487,23 +2518,20 @@ static int yaffs_InitialiseBlocks(yaffs_ - - /* If the first allocation strategy fails, thry the alternate one */ - dev->blockInfo = YMALLOC(nBlocks * sizeof(yaffs_BlockInfo)); -- if(!dev->blockInfo){ -+ if (!dev->blockInfo) { - dev->blockInfo = YMALLOC_ALT(nBlocks * sizeof(yaffs_BlockInfo)); - dev->blockInfoAlt = 1; -- } -- else -+ } else - dev->blockInfoAlt = 0; - -- if(dev->blockInfo){ -- -+ if (dev->blockInfo) { - /* Set up dynamic blockinfo stuff. */ - dev->chunkBitmapStride = (dev->nChunksPerBlock + 7) / 8; /* round up bytes */ - dev->chunkBits = YMALLOC(dev->chunkBitmapStride * nBlocks); -- if(!dev->chunkBits){ -+ if (!dev->chunkBits) { - dev->chunkBits = YMALLOC_ALT(dev->chunkBitmapStride * nBlocks); - dev->chunkBitsAlt = 1; -- } -- else -+ } else - dev->chunkBitsAlt = 0; - } - -@@ -2514,30 +2542,29 @@ static int yaffs_InitialiseBlocks(yaffs_ - } - - return YAFFS_FAIL; -- - } - --static void yaffs_DeinitialiseBlocks(yaffs_Device * dev) -+static void yaffs_DeinitialiseBlocks(yaffs_Device *dev) - { -- if(dev->blockInfoAlt && dev->blockInfo) -+ if (dev->blockInfoAlt && dev->blockInfo) - YFREE_ALT(dev->blockInfo); -- else if(dev->blockInfo) -+ else if (dev->blockInfo) - YFREE(dev->blockInfo); - - dev->blockInfoAlt = 0; - - dev->blockInfo = NULL; - -- if(dev->chunkBitsAlt && dev->chunkBits) -+ if (dev->chunkBitsAlt && dev->chunkBits) - YFREE_ALT(dev->chunkBits); -- else if(dev->chunkBits) -+ else if (dev->chunkBits) - YFREE(dev->chunkBits); - dev->chunkBitsAlt = 0; - dev->chunkBits = NULL; - } - --static int yaffs_BlockNotDisqualifiedFromGC(yaffs_Device * dev, -- yaffs_BlockInfo * bi) -+static int yaffs_BlockNotDisqualifiedFromGC(yaffs_Device *dev, -+ yaffs_BlockInfo *bi) - { - int i; - __u32 seq; -@@ -2556,7 +2583,7 @@ static int yaffs_BlockNotDisqualifiedFro - seq = dev->sequenceNumber; - - for (i = dev->internalStartBlock; i <= dev->internalEndBlock; -- i++) { -+ i++) { - b = yaffs_GetBlockInfo(dev, i); - if (b->blockState == YAFFS_BLOCK_STATE_FULL && - (b->pagesInUse - b->softDeletions) < -@@ -2571,38 +2598,36 @@ static int yaffs_BlockNotDisqualifiedFro - * discarded pages. - */ - return (bi->sequenceNumber <= dev->oldestDirtySequence); -- - } - - /* FindDiretiestBlock is used to select the dirtiest block (or close enough) - * for garbage collection. - */ - --static int yaffs_FindBlockForGarbageCollection(yaffs_Device * dev, -- int aggressive) -+static int yaffs_FindBlockForGarbageCollection(yaffs_Device *dev, -+ int aggressive) - { -- - int b = dev->currentDirtyChecker; - - int i; - int iterations; - int dirtiest = -1; - int pagesInUse = 0; -- int prioritised=0; -+ int prioritised = 0; - yaffs_BlockInfo *bi; - int pendingPrioritisedExist = 0; - - /* First let's see if we need to grab a prioritised block */ -- if(dev->hasPendingPrioritisedGCs){ -- for(i = dev->internalStartBlock; i < dev->internalEndBlock && !prioritised; i++){ -+ if (dev->hasPendingPrioritisedGCs) { -+ for (i = dev->internalStartBlock; i < dev->internalEndBlock && !prioritised; i++) { - - bi = yaffs_GetBlockInfo(dev, i); -- //yaffs_VerifyBlock(dev,bi,i); -+ /* yaffs_VerifyBlock(dev,bi,i); */ - -- if(bi->gcPrioritise) { -+ if (bi->gcPrioritise) { - pendingPrioritisedExist = 1; -- if(bi->blockState == YAFFS_BLOCK_STATE_FULL && -- yaffs_BlockNotDisqualifiedFromGC(dev, bi)){ -+ if (bi->blockState == YAFFS_BLOCK_STATE_FULL && -+ yaffs_BlockNotDisqualifiedFromGC(dev, bi)) { - pagesInUse = (bi->pagesInUse - bi->softDeletions); - dirtiest = i; - prioritised = 1; -@@ -2611,7 +2636,7 @@ static int yaffs_FindBlockForGarbageColl - } - } - -- if(!pendingPrioritisedExist) /* None found, so we can clear this */ -+ if (!pendingPrioritisedExist) /* None found, so we can clear this */ - dev->hasPendingPrioritisedGCs = 0; - } - -@@ -2623,31 +2648,28 @@ static int yaffs_FindBlockForGarbageColl - - dev->nonAggressiveSkip--; - -- if (!aggressive && (dev->nonAggressiveSkip > 0)) { -+ if (!aggressive && (dev->nonAggressiveSkip > 0)) - return -1; -- } - -- if(!prioritised) -+ if (!prioritised) - pagesInUse = -- (aggressive) ? dev->nChunksPerBlock : YAFFS_PASSIVE_GC_CHUNKS + 1; -+ (aggressive) ? dev->nChunksPerBlock : YAFFS_PASSIVE_GC_CHUNKS + 1; - -- if (aggressive) { -+ if (aggressive) - iterations = - dev->internalEndBlock - dev->internalStartBlock + 1; -- } else { -+ else { - iterations = - dev->internalEndBlock - dev->internalStartBlock + 1; - iterations = iterations / 16; -- if (iterations > 200) { -+ if (iterations > 200) - iterations = 200; -- } - } - - for (i = 0; i <= iterations && pagesInUse > 0 && !prioritised; i++) { - b++; -- if (b < dev->internalStartBlock || b > dev->internalEndBlock) { -+ if (b < dev->internalStartBlock || b > dev->internalEndBlock) - b = dev->internalStartBlock; -- } - - if (b < dev->internalStartBlock || b > dev->internalEndBlock) { - T(YAFFS_TRACE_ERROR, -@@ -2657,17 +2679,9 @@ static int yaffs_FindBlockForGarbageColl - - bi = yaffs_GetBlockInfo(dev, b); - --#if 0 -- if (bi->blockState == YAFFS_BLOCK_STATE_CHECKPOINT) { -- dirtiest = b; -- pagesInUse = 0; -- } -- else --#endif -- - if (bi->blockState == YAFFS_BLOCK_STATE_FULL && -- (bi->pagesInUse - bi->softDeletions) < pagesInUse && -- yaffs_BlockNotDisqualifiedFromGC(dev, bi)) { -+ (bi->pagesInUse - bi->softDeletions) < pagesInUse && -+ yaffs_BlockNotDisqualifiedFromGC(dev, bi)) { - dirtiest = b; - pagesInUse = (bi->pagesInUse - bi->softDeletions); - } -@@ -2678,19 +2692,18 @@ static int yaffs_FindBlockForGarbageColl - if (dirtiest > 0) { - T(YAFFS_TRACE_GC, - (TSTR("GC Selected block %d with %d free, prioritised:%d" TENDSTR), dirtiest, -- dev->nChunksPerBlock - pagesInUse,prioritised)); -+ dev->nChunksPerBlock - pagesInUse, prioritised)); - } - - dev->oldestDirtySequence = 0; - -- if (dirtiest > 0) { -+ if (dirtiest > 0) - dev->nonAggressiveSkip = 4; -- } - - return dirtiest; - } - --static void yaffs_BlockBecameDirty(yaffs_Device * dev, int blockNo) -+static void yaffs_BlockBecameDirty(yaffs_Device *dev, int blockNo) - { - yaffs_BlockInfo *bi = yaffs_GetBlockInfo(dev, blockNo); - -@@ -2752,7 +2765,7 @@ static void yaffs_BlockBecameDirty(yaffs - } - } - --static int yaffs_FindBlockForAllocation(yaffs_Device * dev) -+static int yaffs_FindBlockForAllocation(yaffs_Device *dev) - { - int i; - -@@ -2763,7 +2776,7 @@ static int yaffs_FindBlockForAllocation( - * Can't get space to gc - */ - T(YAFFS_TRACE_ERROR, -- (TSTR("yaffs tragedy: no more eraased blocks" TENDSTR))); -+ (TSTR("yaffs tragedy: no more erased blocks" TENDSTR))); - - return -1; - } -@@ -2794,31 +2807,74 @@ static int yaffs_FindBlockForAllocation( - - T(YAFFS_TRACE_ALWAYS, - (TSTR -- ("yaffs tragedy: no more eraased blocks, but there should have been %d" -+ ("yaffs tragedy: no more erased blocks, but there should have been %d" - TENDSTR), dev->nErasedBlocks)); - - return -1; - } - - --// Check if there's space to allocate... --// Thinks.... do we need top make this ths same as yaffs_GetFreeChunks()? --static int yaffs_CheckSpaceForAllocation(yaffs_Device * dev) -+ -+static int yaffs_CalcCheckpointBlocksRequired(yaffs_Device *dev) -+{ -+ if (!dev->nCheckpointBlocksRequired && -+ dev->isYaffs2) { -+ /* Not a valid value so recalculate */ -+ int nBytes = 0; -+ int nBlocks; -+ int devBlocks = (dev->endBlock - dev->startBlock + 1); -+ int tnodeSize; -+ -+ tnodeSize = (dev->tnodeWidth * YAFFS_NTNODES_LEVEL0)/8; -+ -+ if (tnodeSize < sizeof(yaffs_Tnode)) -+ tnodeSize = sizeof(yaffs_Tnode); -+ -+ nBytes += sizeof(yaffs_CheckpointValidity); -+ nBytes += sizeof(yaffs_CheckpointDevice); -+ nBytes += devBlocks * sizeof(yaffs_BlockInfo); -+ nBytes += devBlocks * dev->chunkBitmapStride; -+ nBytes += (sizeof(yaffs_CheckpointObject) + sizeof(__u32)) * (dev->nObjectsCreated - dev->nFreeObjects); -+ nBytes += (tnodeSize + sizeof(__u32)) * (dev->nTnodesCreated - dev->nFreeTnodes); -+ nBytes += sizeof(yaffs_CheckpointValidity); -+ nBytes += sizeof(__u32); /* checksum*/ -+ -+ /* Round up and add 2 blocks to allow for some bad blocks, so add 3 */ -+ -+ nBlocks = (nBytes/(dev->nDataBytesPerChunk * dev->nChunksPerBlock)) + 3; -+ -+ dev->nCheckpointBlocksRequired = nBlocks; -+ } -+ -+ return dev->nCheckpointBlocksRequired; -+} -+ -+/* -+ * Check if there's space to allocate... -+ * Thinks.... do we need top make this ths same as yaffs_GetFreeChunks()? -+ */ -+static int yaffs_CheckSpaceForAllocation(yaffs_Device *dev) - { - int reservedChunks; - int reservedBlocks = dev->nReservedBlocks; - int checkpointBlocks; - -- checkpointBlocks = dev->nCheckpointReservedBlocks - dev->blocksInCheckpoint; -- if(checkpointBlocks < 0) -+ if (dev->isYaffs2) { -+ checkpointBlocks = yaffs_CalcCheckpointBlocksRequired(dev) - -+ dev->blocksInCheckpoint; -+ if (checkpointBlocks < 0) -+ checkpointBlocks = 0; -+ } else { - checkpointBlocks = 0; -+ } - - reservedChunks = ((reservedBlocks + checkpointBlocks) * dev->nChunksPerBlock); - - return (dev->nFreeChunks > reservedChunks); - } - --static int yaffs_AllocateChunk(yaffs_Device * dev, int useReserve, yaffs_BlockInfo **blockUsedPtr) -+static int yaffs_AllocateChunk(yaffs_Device *dev, int useReserve, -+ yaffs_BlockInfo **blockUsedPtr) - { - int retVal; - yaffs_BlockInfo *bi; -@@ -2835,7 +2891,7 @@ static int yaffs_AllocateChunk(yaffs_Dev - } - - if (dev->nErasedBlocks < dev->nReservedBlocks -- && dev->allocationPage == 0) { -+ && dev->allocationPage == 0) { - T(YAFFS_TRACE_ALLOCATE, (TSTR("Allocating reserve" TENDSTR))); - } - -@@ -2844,10 +2900,10 @@ static int yaffs_AllocateChunk(yaffs_Dev - bi = yaffs_GetBlockInfo(dev, dev->allocationBlock); - - retVal = (dev->allocationBlock * dev->nChunksPerBlock) + -- dev->allocationPage; -+ dev->allocationPage; - bi->pagesInUse++; - yaffs_SetChunkBit(dev, dev->allocationBlock, -- dev->allocationPage); -+ dev->allocationPage); - - dev->allocationPage++; - -@@ -2859,43 +2915,43 @@ static int yaffs_AllocateChunk(yaffs_Dev - dev->allocationBlock = -1; - } - -- if(blockUsedPtr) -+ if (blockUsedPtr) - *blockUsedPtr = bi; - - return retVal; - } - - T(YAFFS_TRACE_ERROR, -- (TSTR("!!!!!!!!! Allocator out !!!!!!!!!!!!!!!!!" TENDSTR))); -+ (TSTR("!!!!!!!!! Allocator out !!!!!!!!!!!!!!!!!" TENDSTR))); - - return -1; - } - --static int yaffs_GetErasedChunks(yaffs_Device * dev) -+static int yaffs_GetErasedChunks(yaffs_Device *dev) - { - int n; - - n = dev->nErasedBlocks * dev->nChunksPerBlock; - -- if (dev->allocationBlock > 0) { -+ if (dev->allocationBlock > 0) - n += (dev->nChunksPerBlock - dev->allocationPage); -- } - - return n; - - } - --static int yaffs_GarbageCollectBlock(yaffs_Device * dev, int block) -+static int yaffs_GarbageCollectBlock(yaffs_Device *dev, int block, -+ int wholeBlock) - { - int oldChunk; - int newChunk; -- int chunkInBlock; - int markNAND; - int retVal = YAFFS_OK; - int cleanups = 0; - int i; - int isCheckpointBlock; - int matchingChunk; -+ int maxCopies; - - int chunksBefore = yaffs_GetErasedChunks(dev); - int chunksAfter; -@@ -2911,8 +2967,11 @@ static int yaffs_GarbageCollectBlock(yaf - bi->blockState = YAFFS_BLOCK_STATE_COLLECTING; - - T(YAFFS_TRACE_TRACING, -- (TSTR("Collecting block %d, in use %d, shrink %d, " TENDSTR), block, -- bi->pagesInUse, bi->hasShrinkHeader)); -+ (TSTR("Collecting block %d, in use %d, shrink %d, wholeBlock %d" TENDSTR), -+ block, -+ bi->pagesInUse, -+ bi->hasShrinkHeader, -+ wholeBlock)); - - /*yaffs_VerifyFreeChunks(dev); */ - -@@ -2926,26 +2985,33 @@ static int yaffs_GarbageCollectBlock(yaf - dev->isDoingGC = 1; - - if (isCheckpointBlock || -- !yaffs_StillSomeChunkBits(dev, block)) { -+ !yaffs_StillSomeChunkBits(dev, block)) { - T(YAFFS_TRACE_TRACING, -- (TSTR -- ("Collecting block %d that has no chunks in use" TENDSTR), -- block)); -+ (TSTR -+ ("Collecting block %d that has no chunks in use" TENDSTR), -+ block)); - yaffs_BlockBecameDirty(dev, block); - } else { - - __u8 *buffer = yaffs_GetTempBuffer(dev, __LINE__); - -- yaffs_VerifyBlock(dev,bi,block); -+ yaffs_VerifyBlock(dev, bi, block); - -- for (chunkInBlock = 0, oldChunk = block * dev->nChunksPerBlock; -- chunkInBlock < dev->nChunksPerBlock -- && yaffs_StillSomeChunkBits(dev, block); -- chunkInBlock++, oldChunk++) { -- if (yaffs_CheckChunkBit(dev, block, chunkInBlock)) { -+ maxCopies = (wholeBlock) ? dev->nChunksPerBlock : 10; -+ oldChunk = block * dev->nChunksPerBlock + dev->gcChunk; -+ -+ for (/* init already done */; -+ retVal == YAFFS_OK && -+ dev->gcChunk < dev->nChunksPerBlock && -+ (bi->blockState == YAFFS_BLOCK_STATE_COLLECTING) && -+ maxCopies > 0; -+ dev->gcChunk++, oldChunk++) { -+ if (yaffs_CheckChunkBit(dev, block, dev->gcChunk)) { - - /* This page is in use and might need to be copied off */ - -+ maxCopies--; -+ - markNAND = 1; - - yaffs_InitialiseTags(&tags); -@@ -2959,22 +3025,22 @@ static int yaffs_GarbageCollectBlock(yaf - - T(YAFFS_TRACE_GC_DETAIL, - (TSTR -- ("Collecting page %d, %d %d %d " TENDSTR), -- chunkInBlock, tags.objectId, tags.chunkId, -+ ("Collecting chunk in block %d, %d %d %d " TENDSTR), -+ dev->gcChunk, tags.objectId, tags.chunkId, - tags.byteCount)); - -- if(object && !yaffs_SkipVerification(dev)){ -- if(tags.chunkId == 0) -- matchingChunk = object->chunkId; -- else if(object->softDeleted) -+ if (object && !yaffs_SkipVerification(dev)) { -+ if (tags.chunkId == 0) -+ matchingChunk = object->hdrChunk; -+ else if (object->softDeleted) - matchingChunk = oldChunk; /* Defeat the test */ - else -- matchingChunk = yaffs_FindChunkInFile(object,tags.chunkId,NULL); -+ matchingChunk = yaffs_FindChunkInFile(object, tags.chunkId, NULL); - -- if(oldChunk != matchingChunk) -+ if (oldChunk != matchingChunk) - T(YAFFS_TRACE_ERROR, - (TSTR("gc: page in gc mismatch: %d %d %d %d"TENDSTR), -- oldChunk,matchingChunk,tags.objectId, tags.chunkId)); -+ oldChunk, matchingChunk, tags.objectId, tags.chunkId)); - - } - -@@ -2986,9 +3052,11 @@ static int yaffs_GarbageCollectBlock(yaf - tags.objectId, tags.chunkId, tags.byteCount)); - } - -- if (object && object->deleted -- && tags.chunkId != 0) { -- /* Data chunk in a deleted file, throw it away -+ if (object && -+ object->deleted && -+ object->softDeleted && -+ tags.chunkId != 0) { -+ /* Data chunk in a soft deleted file, throw it away - * It's a soft deleted data chunk, - * No need to copy this, just forget about it and - * fix up the object. -@@ -3003,13 +3071,12 @@ static int yaffs_GarbageCollectBlock(yaf - cleanups++; - } - markNAND = 0; -- } else if (0 -- /* Todo object && object->deleted && object->nDataChunks == 0 */ -- ) { -+ } else if (0) { -+ /* Todo object && object->deleted && object->nDataChunks == 0 */ - /* Deleted object header with no data chunks. - * Can be discarded and the file deleted. - */ -- object->chunkId = 0; -+ object->hdrChunk = 0; - yaffs_FreeTnode(object->myDev, - object->variant. - fileVariant.top); -@@ -3031,17 +3098,14 @@ static int yaffs_GarbageCollectBlock(yaf - * We need to nuke the shrinkheader flags first - * We no longer want the shrinkHeader flag since its work is done - * and if it is left in place it will mess up scanning. -- * Also, clear out any shadowing stuff - */ - - yaffs_ObjectHeader *oh; - oh = (yaffs_ObjectHeader *)buffer; - oh->isShrink = 0; -- oh->shadowsObject = -1; -- tags.extraShadows = 0; - tags.extraIsShrinkHeader = 0; - -- yaffs_VerifyObjectHeader(object,oh,&tags,1); -+ yaffs_VerifyObjectHeader(object, oh, &tags, 1); - } - - newChunk = -@@ -3055,7 +3119,7 @@ static int yaffs_GarbageCollectBlock(yaf - - if (tags.chunkId == 0) { - /* It's a header */ -- object->chunkId = newChunk; -+ object->hdrChunk = newChunk; - object->serial = tags.serialNumber; - } else { - /* It's a data chunk */ -@@ -3067,7 +3131,8 @@ static int yaffs_GarbageCollectBlock(yaf - } - } - -- yaffs_DeleteChunk(dev, oldChunk, markNAND, __LINE__); -+ if (retVal == YAFFS_OK) -+ yaffs_DeleteChunk(dev, oldChunk, markNAND, __LINE__); - - } - } -@@ -3098,18 +3163,25 @@ static int yaffs_GarbageCollectBlock(yaf - - } - -- yaffs_VerifyCollectedBlock(dev,bi,block); -+ yaffs_VerifyCollectedBlock(dev, bi, block); - -- if (chunksBefore >= (chunksAfter = yaffs_GetErasedChunks(dev))) { -+ chunksAfter = yaffs_GetErasedChunks(dev); -+ if (chunksBefore >= chunksAfter) { - T(YAFFS_TRACE_GC, - (TSTR - ("gc did not increase free chunks before %d after %d" - TENDSTR), chunksBefore, chunksAfter)); - } - -+ /* If the gc completed then clear the current gcBlock so that we find another. */ -+ if (bi->blockState != YAFFS_BLOCK_STATE_COLLECTING) { -+ dev->gcBlock = -1; -+ dev->gcChunk = 0; -+ } -+ - dev->isDoingGC = 0; - -- return YAFFS_OK; -+ return retVal; - } - - /* New garbage collector -@@ -3121,7 +3193,7 @@ static int yaffs_GarbageCollectBlock(yaf - * The idea is to help clear out space in a more spread-out manner. - * Dunno if it really does anything useful. - */ --static int yaffs_CheckGarbageCollection(yaffs_Device * dev) -+static int yaffs_CheckGarbageCollection(yaffs_Device *dev) - { - int block; - int aggressive; -@@ -3142,8 +3214,8 @@ static int yaffs_CheckGarbageCollection( - do { - maxTries++; - -- checkpointBlockAdjust = (dev->nCheckpointReservedBlocks - dev->blocksInCheckpoint); -- if(checkpointBlockAdjust < 0) -+ checkpointBlockAdjust = yaffs_CalcCheckpointBlocksRequired(dev) - dev->blocksInCheckpoint; -+ if (checkpointBlockAdjust < 0) - checkpointBlockAdjust = 0; - - if (dev->nErasedBlocks < (dev->nReservedBlocks + checkpointBlockAdjust + 2)) { -@@ -3154,20 +3226,24 @@ static int yaffs_CheckGarbageCollection( - aggressive = 0; - } - -- block = yaffs_FindBlockForGarbageCollection(dev, aggressive); -+ if (dev->gcBlock <= 0) { -+ dev->gcBlock = yaffs_FindBlockForGarbageCollection(dev, aggressive); -+ dev->gcChunk = 0; -+ } -+ -+ block = dev->gcBlock; - - if (block > 0) { - dev->garbageCollections++; -- if (!aggressive) { -+ if (!aggressive) - dev->passiveGarbageCollections++; -- } - - T(YAFFS_TRACE_GC, - (TSTR - ("yaffs: GC erasedBlocks %d aggressive %d" TENDSTR), - dev->nErasedBlocks, aggressive)); - -- gcOk = yaffs_GarbageCollectBlock(dev, block); -+ gcOk = yaffs_GarbageCollectBlock(dev, block, aggressive); - } - - if (dev->nErasedBlocks < (dev->nReservedBlocks) && block > 0) { -@@ -3176,15 +3252,16 @@ static int yaffs_CheckGarbageCollection( - ("yaffs: GC !!!no reclaim!!! erasedBlocks %d after try %d block %d" - TENDSTR), dev->nErasedBlocks, maxTries, block)); - } -- } while ((dev->nErasedBlocks < dev->nReservedBlocks) && (block > 0) -- && (maxTries < 2)); -+ } while ((dev->nErasedBlocks < dev->nReservedBlocks) && -+ (block > 0) && -+ (maxTries < 2)); - - return aggressive ? gcOk : YAFFS_OK; - } - - /*------------------------- TAGS --------------------------------*/ - --static int yaffs_TagsMatch(const yaffs_ExtendedTags * tags, int objectId, -+static int yaffs_TagsMatch(const yaffs_ExtendedTags *tags, int objectId, - int chunkInObject) - { - return (tags->chunkId == chunkInObject && -@@ -3195,8 +3272,8 @@ static int yaffs_TagsMatch(const yaffs_E - - /*-------------------- Data file manipulation -----------------*/ - --static int yaffs_FindChunkInFile(yaffs_Object * in, int chunkInInode, -- yaffs_ExtendedTags * tags) -+static int yaffs_FindChunkInFile(yaffs_Object *in, int chunkInInode, -+ yaffs_ExtendedTags *tags) - { - /*Get the Tnode, then get the level 0 offset chunk offset */ - yaffs_Tnode *tn; -@@ -3214,7 +3291,7 @@ static int yaffs_FindChunkInFile(yaffs_O - tn = yaffs_FindLevel0Tnode(dev, &in->variant.fileVariant, chunkInInode); - - if (tn) { -- theChunk = yaffs_GetChunkGroupBase(dev,tn,chunkInInode); -+ theChunk = yaffs_GetChunkGroupBase(dev, tn, chunkInInode); - - retVal = - yaffs_FindChunkInGroup(dev, theChunk, tags, in->objectId, -@@ -3223,8 +3300,8 @@ static int yaffs_FindChunkInFile(yaffs_O - return retVal; - } - --static int yaffs_FindAndDeleteChunkInFile(yaffs_Object * in, int chunkInInode, -- yaffs_ExtendedTags * tags) -+static int yaffs_FindAndDeleteChunkInFile(yaffs_Object *in, int chunkInInode, -+ yaffs_ExtendedTags *tags) - { - /* Get the Tnode, then get the level 0 offset chunk offset */ - yaffs_Tnode *tn; -@@ -3243,29 +3320,23 @@ static int yaffs_FindAndDeleteChunkInFil - - if (tn) { - -- theChunk = yaffs_GetChunkGroupBase(dev,tn,chunkInInode); -+ theChunk = yaffs_GetChunkGroupBase(dev, tn, chunkInInode); - - retVal = - yaffs_FindChunkInGroup(dev, theChunk, tags, in->objectId, - chunkInInode); - - /* Delete the entry in the filestructure (if found) */ -- if (retVal != -1) { -- yaffs_PutLevel0Tnode(dev,tn,chunkInInode,0); -- } -- } else { -- /*T(("No level 0 found for %d\n", chunkInInode)); */ -+ if (retVal != -1) -+ yaffs_PutLevel0Tnode(dev, tn, chunkInInode, 0); - } - -- if (retVal == -1) { -- /* T(("Could not find %d to delete\n",chunkInInode)); */ -- } - return retVal; - } - - #ifdef YAFFS_PARANOID - --static int yaffs_CheckFileSanity(yaffs_Object * in) -+static int yaffs_CheckFileSanity(yaffs_Object *in) - { - int chunk; - int nChunks; -@@ -3278,10 +3349,8 @@ static int yaffs_CheckFileSanity(yaffs_O - int theChunk; - int chunkDeleted; - -- if (in->variantType != YAFFS_OBJECT_TYPE_FILE) { -- /* T(("Object not a file\n")); */ -+ if (in->variantType != YAFFS_OBJECT_TYPE_FILE) - return YAFFS_FAIL; -- } - - objId = in->objectId; - fSize = in->variant.fileVariant.fileSize; -@@ -3294,7 +3363,7 @@ static int yaffs_CheckFileSanity(yaffs_O - - if (tn) { - -- theChunk = yaffs_GetChunkGroupBase(dev,tn,chunk); -+ theChunk = yaffs_GetChunkGroupBase(dev, tn, chunk); - - if (yaffs_CheckChunkBits - (dev, theChunk / dev->nChunksPerBlock, -@@ -3323,7 +3392,7 @@ static int yaffs_CheckFileSanity(yaffs_O - - #endif - --static int yaffs_PutChunkIntoFile(yaffs_Object * in, int chunkInInode, -+static int yaffs_PutChunkIntoFile(yaffs_Object *in, int chunkInInode, - int chunkInNAND, int inScan) - { - /* NB inScan is zero unless scanning. -@@ -3358,11 +3427,10 @@ static int yaffs_PutChunkIntoFile(yaffs_ - &in->variant.fileVariant, - chunkInInode, - NULL); -- if (!tn) { -+ if (!tn) - return YAFFS_FAIL; -- } - -- existingChunk = yaffs_GetChunkGroupBase(dev,tn,chunkInInode); -+ existingChunk = yaffs_GetChunkGroupBase(dev, tn, chunkInInode); - - if (inScan != 0) { - /* If we're scanning then we need to test for duplicates -@@ -3374,7 +3442,7 @@ static int yaffs_PutChunkIntoFile(yaffs_ - * Update: For backward scanning we don't need to re-read tags so this is quite cheap. - */ - -- if (existingChunk != 0) { -+ if (existingChunk > 0) { - /* NB Right now existing chunk will not be real chunkId if the device >= 32MB - * thus we have to do a FindChunkInFile to get the real chunk id. - * -@@ -3411,8 +3479,10 @@ static int yaffs_PutChunkIntoFile(yaffs_ - * not be loaded during a scan - */ - -- newSerial = newTags.serialNumber; -- existingSerial = existingTags.serialNumber; -+ if (inScan > 0) { -+ newSerial = newTags.serialNumber; -+ existingSerial = existingTags.serialNumber; -+ } - - if ((inScan > 0) && - (in->myDev->isYaffs2 || -@@ -3437,24 +3507,23 @@ static int yaffs_PutChunkIntoFile(yaffs_ - - } - -- if (existingChunk == 0) { -+ if (existingChunk == 0) - in->nDataChunks++; -- } - -- yaffs_PutLevel0Tnode(dev,tn,chunkInInode,chunkInNAND); -+ yaffs_PutLevel0Tnode(dev, tn, chunkInInode, chunkInNAND); - - return YAFFS_OK; - } - --static int yaffs_ReadChunkDataFromObject(yaffs_Object * in, int chunkInInode, -- __u8 * buffer) -+static int yaffs_ReadChunkDataFromObject(yaffs_Object *in, int chunkInInode, -+ __u8 *buffer) - { - int chunkInNAND = yaffs_FindChunkInFile(in, chunkInInode, NULL); - -- if (chunkInNAND >= 0) { -+ if (chunkInNAND >= 0) - return yaffs_ReadChunkWithTagsFromNAND(in->myDev, chunkInNAND, -- buffer,NULL); -- } else { -+ buffer, NULL); -+ else { - T(YAFFS_TRACE_NANDACCESS, - (TSTR("Chunk %d not found zero instead" TENDSTR), - chunkInNAND)); -@@ -3465,7 +3534,7 @@ static int yaffs_ReadChunkDataFromObject - - } - --void yaffs_DeleteChunk(yaffs_Device * dev, int chunkId, int markNAND, int lyn) -+void yaffs_DeleteChunk(yaffs_Device *dev, int chunkId, int markNAND, int lyn) - { - int block; - int page; -@@ -3475,16 +3544,15 @@ void yaffs_DeleteChunk(yaffs_Device * de - if (chunkId <= 0) - return; - -- - dev->nDeletions++; - block = chunkId / dev->nChunksPerBlock; - page = chunkId % dev->nChunksPerBlock; - - -- if(!yaffs_CheckChunkBit(dev,block,page)) -+ if (!yaffs_CheckChunkBit(dev, block, page)) - T(YAFFS_TRACE_VERIFY, -- (TSTR("Deleting invalid chunk %d"TENDSTR), -- chunkId)); -+ (TSTR("Deleting invalid chunk %d"TENDSTR), -+ chunkId)); - - bi = yaffs_GetBlockInfo(dev, block); - -@@ -3524,14 +3592,12 @@ void yaffs_DeleteChunk(yaffs_Device * de - yaffs_BlockBecameDirty(dev, block); - } - -- } else { -- /* T(("Bad news deleting chunk %d\n",chunkId)); */ - } - - } - --static int yaffs_WriteChunkDataToObject(yaffs_Object * in, int chunkInInode, -- const __u8 * buffer, int nBytes, -+static int yaffs_WriteChunkDataToObject(yaffs_Object *in, int chunkInInode, -+ const __u8 *buffer, int nBytes, - int useReserve) - { - /* Find old chunk Need to do this to get serial number -@@ -3561,6 +3627,12 @@ static int yaffs_WriteChunkDataToObject( - (prevChunkId >= 0) ? prevTags.serialNumber + 1 : 1; - newTags.byteCount = nBytes; - -+ if (nBytes < 1 || nBytes > dev->totalBytesPerChunk) { -+ T(YAFFS_TRACE_ERROR, -+ (TSTR("Writing %d bytes to chunk!!!!!!!!!" TENDSTR), nBytes)); -+ YBUG(); -+ } -+ - newChunkId = - yaffs_WriteNewChunkWithTagsToNAND(dev, buffer, &newTags, - useReserve); -@@ -3568,11 +3640,9 @@ static int yaffs_WriteChunkDataToObject( - if (newChunkId >= 0) { - yaffs_PutChunkIntoFile(in, chunkInInode, newChunkId, 0); - -- if (prevChunkId >= 0) { -+ if (prevChunkId >= 0) - yaffs_DeleteChunk(dev, prevChunkId, 1, __LINE__); - -- } -- - yaffs_CheckFileSanity(in); - } - return newChunkId; -@@ -3582,7 +3652,7 @@ static int yaffs_WriteChunkDataToObject( - /* UpdateObjectHeader updates the header on NAND for an object. - * If name is not NULL, then that new name is used. - */ --int yaffs_UpdateObjectHeader(yaffs_Object * in, const YCHAR * name, int force, -+int yaffs_UpdateObjectHeader(yaffs_Object *in, const YCHAR *name, int force, - int isShrink, int shadows) - { - -@@ -3603,9 +3673,12 @@ int yaffs_UpdateObjectHeader(yaffs_Objec - - yaffs_ObjectHeader *oh = NULL; - -- yaffs_strcpy(oldName,"silly old name"); -+ yaffs_strcpy(oldName, _Y("silly old name")); - -- if (!in->fake || force) { -+ -+ if (!in->fake || -+ in == dev->rootDir || /* The rootDir should also be saved */ -+ force) { - - yaffs_CheckGarbageCollection(dev); - yaffs_CheckObjectDetailsLoaded(in); -@@ -3613,13 +3686,13 @@ int yaffs_UpdateObjectHeader(yaffs_Objec - buffer = yaffs_GetTempBuffer(in->myDev, __LINE__); - oh = (yaffs_ObjectHeader *) buffer; - -- prevChunkId = in->chunkId; -+ prevChunkId = in->hdrChunk; - -- if (prevChunkId >= 0) { -+ if (prevChunkId > 0) { - result = yaffs_ReadChunkWithTagsFromNAND(dev, prevChunkId, - buffer, &oldTags); - -- yaffs_VerifyObjectHeader(in,oh,&oldTags,0); -+ yaffs_VerifyObjectHeader(in, oh, &oldTags, 0); - - memcpy(oldName, oh->name, sizeof(oh->name)); - } -@@ -3628,7 +3701,7 @@ int yaffs_UpdateObjectHeader(yaffs_Objec - - oh->type = in->variantType; - oh->yst_mode = in->yst_mode; -- oh->shadowsObject = shadows; -+ oh->shadowsObject = oh->inbandShadowsObject = shadows; - - #ifdef CONFIG_YAFFS_WINCE - oh->win_atime[0] = in->win_atime[0]; -@@ -3645,20 +3718,18 @@ int yaffs_UpdateObjectHeader(yaffs_Objec - oh->yst_ctime = in->yst_ctime; - oh->yst_rdev = in->yst_rdev; - #endif -- if (in->parent) { -+ if (in->parent) - oh->parentObjectId = in->parent->objectId; -- } else { -+ else - oh->parentObjectId = 0; -- } - - if (name && *name) { - memset(oh->name, 0, sizeof(oh->name)); - yaffs_strncpy(oh->name, name, YAFFS_MAX_NAME_LENGTH); -- } else if (prevChunkId>=0) { -+ } else if (prevChunkId >= 0) - memcpy(oh->name, oldName, sizeof(oh->name)); -- } else { -+ else - memset(oh->name, 0, sizeof(oh->name)); -- } - - oh->isShrink = isShrink; - -@@ -3708,7 +3779,7 @@ int yaffs_UpdateObjectHeader(yaffs_Objec - newTags.extraShadows = (oh->shadowsObject > 0) ? 1 : 0; - newTags.extraObjectType = in->variantType; - -- yaffs_VerifyObjectHeader(in,oh,&newTags,1); -+ yaffs_VerifyObjectHeader(in, oh, &newTags, 1); - - /* Create new chunk in NAND */ - newChunkId = -@@ -3717,20 +3788,20 @@ int yaffs_UpdateObjectHeader(yaffs_Objec - - if (newChunkId >= 0) { - -- in->chunkId = newChunkId; -+ in->hdrChunk = newChunkId; - - if (prevChunkId >= 0) { - yaffs_DeleteChunk(dev, prevChunkId, 1, - __LINE__); - } - -- if(!yaffs_ObjectHasCachedWriteData(in)) -+ if (!yaffs_ObjectHasCachedWriteData(in)) - in->dirty = 0; - - /* If this was a shrink, then mark the block that the chunk lives on */ - if (isShrink) { - bi = yaffs_GetBlockInfo(in->myDev, -- newChunkId /in->myDev-> nChunksPerBlock); -+ newChunkId / in->myDev->nChunksPerBlock); - bi->hasShrinkHeader = 1; - } - -@@ -3766,7 +3837,7 @@ static int yaffs_ObjectHasCachedWriteDat - yaffs_ChunkCache *cache; - int nCaches = obj->myDev->nShortOpCaches; - -- for(i = 0; i < nCaches; i++){ -+ for (i = 0; i < nCaches; i++) { - cache = &dev->srCache[i]; - if (cache->object == obj && - cache->dirty) -@@ -3777,7 +3848,7 @@ static int yaffs_ObjectHasCachedWriteDat - } - - --static void yaffs_FlushFilesChunkCache(yaffs_Object * obj) -+static void yaffs_FlushFilesChunkCache(yaffs_Object *obj) - { - yaffs_Device *dev = obj->myDev; - int lowest = -99; /* Stop compiler whining. */ -@@ -3844,16 +3915,16 @@ void yaffs_FlushEntireDeviceCache(yaffs_ - */ - do { - obj = NULL; -- for( i = 0; i < nCaches && !obj; i++) { -+ for (i = 0; i < nCaches && !obj; i++) { - if (dev->srCache[i].object && - dev->srCache[i].dirty) - obj = dev->srCache[i].object; - - } -- if(obj) -+ if (obj) - yaffs_FlushFilesChunkCache(obj); - -- } while(obj); -+ } while (obj); - - } - -@@ -3863,41 +3934,21 @@ void yaffs_FlushEntireDeviceCache(yaffs_ - * Then look for the least recently used non-dirty one. - * Then look for the least recently used dirty one...., flush and look again. - */ --static yaffs_ChunkCache *yaffs_GrabChunkCacheWorker(yaffs_Device * dev) -+static yaffs_ChunkCache *yaffs_GrabChunkCacheWorker(yaffs_Device *dev) - { - int i; -- int usage; -- int theOne; - - if (dev->nShortOpCaches > 0) { - for (i = 0; i < dev->nShortOpCaches; i++) { - if (!dev->srCache[i].object) - return &dev->srCache[i]; - } -+ } - -- return NULL; -+ return NULL; -+} - -- theOne = -1; -- usage = 0; /* just to stop the compiler grizzling */ -- -- for (i = 0; i < dev->nShortOpCaches; i++) { -- if (!dev->srCache[i].dirty && -- ((dev->srCache[i].lastUse < usage && theOne >= 0) || -- theOne < 0)) { -- usage = dev->srCache[i].lastUse; -- theOne = i; -- } -- } -- -- -- return theOne >= 0 ? &dev->srCache[theOne] : NULL; -- } else { -- return NULL; -- } -- --} -- --static yaffs_ChunkCache *yaffs_GrabChunkCache(yaffs_Device * dev) -+static yaffs_ChunkCache *yaffs_GrabChunkCache(yaffs_Device *dev) - { - yaffs_ChunkCache *cache; - yaffs_Object *theObj; -@@ -3927,8 +3978,7 @@ static yaffs_ChunkCache *yaffs_GrabChunk - for (i = 0; i < dev->nShortOpCaches; i++) { - if (dev->srCache[i].object && - !dev->srCache[i].locked && -- (dev->srCache[i].lastUse < usage || !cache)) -- { -+ (dev->srCache[i].lastUse < usage || !cache)) { - usage = dev->srCache[i].lastUse; - theObj = dev->srCache[i].object; - cache = &dev->srCache[i]; -@@ -3950,7 +4000,7 @@ static yaffs_ChunkCache *yaffs_GrabChunk - } - - /* Find a cached chunk */ --static yaffs_ChunkCache *yaffs_FindChunkCache(const yaffs_Object * obj, -+static yaffs_ChunkCache *yaffs_FindChunkCache(const yaffs_Object *obj, - int chunkId) - { - yaffs_Device *dev = obj->myDev; -@@ -3969,7 +4019,7 @@ static yaffs_ChunkCache *yaffs_FindChunk - } - - /* Mark the chunk for the least recently used algorithym */ --static void yaffs_UseChunkCache(yaffs_Device * dev, yaffs_ChunkCache * cache, -+static void yaffs_UseChunkCache(yaffs_Device *dev, yaffs_ChunkCache *cache, - int isAWrite) - { - -@@ -3977,9 +4027,9 @@ static void yaffs_UseChunkCache(yaffs_De - if (dev->srLastUse < 0 || dev->srLastUse > 100000000) { - /* Reset the cache usages */ - int i; -- for (i = 1; i < dev->nShortOpCaches; i++) { -+ for (i = 1; i < dev->nShortOpCaches; i++) - dev->srCache[i].lastUse = 0; -- } -+ - dev->srLastUse = 0; - } - -@@ -3987,9 +4037,8 @@ static void yaffs_UseChunkCache(yaffs_De - - cache->lastUse = dev->srLastUse; - -- if (isAWrite) { -+ if (isAWrite) - cache->dirty = 1; -- } - } - } - -@@ -3997,21 +4046,20 @@ static void yaffs_UseChunkCache(yaffs_De - * Do this when a whole page gets written, - * ie the short cache for this page is no longer valid. - */ --static void yaffs_InvalidateChunkCache(yaffs_Object * object, int chunkId) -+static void yaffs_InvalidateChunkCache(yaffs_Object *object, int chunkId) - { - if (object->myDev->nShortOpCaches > 0) { - yaffs_ChunkCache *cache = yaffs_FindChunkCache(object, chunkId); - -- if (cache) { -+ if (cache) - cache->object = NULL; -- } - } - } - - /* Invalidate all the cache pages associated with this object - * Do this whenever ther file is deleted or resized. - */ --static void yaffs_InvalidateWholeChunkCache(yaffs_Object * in) -+static void yaffs_InvalidateWholeChunkCache(yaffs_Object *in) - { - int i; - yaffs_Device *dev = in->myDev; -@@ -4019,9 +4067,8 @@ static void yaffs_InvalidateWholeChunkCa - if (dev->nShortOpCaches > 0) { - /* Invalidate it. */ - for (i = 0; i < dev->nShortOpCaches; i++) { -- if (dev->srCache[i].object == in) { -+ if (dev->srCache[i].object == in) - dev->srCache[i].object = NULL; -- } - } - } - } -@@ -4029,18 +4076,18 @@ static void yaffs_InvalidateWholeChunkCa - /*--------------------- Checkpointing --------------------*/ - - --static int yaffs_WriteCheckpointValidityMarker(yaffs_Device *dev,int head) -+static int yaffs_WriteCheckpointValidityMarker(yaffs_Device *dev, int head) - { - yaffs_CheckpointValidity cp; - -- memset(&cp,0,sizeof(cp)); -+ memset(&cp, 0, sizeof(cp)); - - cp.structType = sizeof(cp); - cp.magic = YAFFS_MAGIC; - cp.version = YAFFS_CHECKPOINT_VERSION; - cp.head = (head) ? 1 : 0; - -- return (yaffs_CheckpointWrite(dev,&cp,sizeof(cp)) == sizeof(cp))? -+ return (yaffs_CheckpointWrite(dev, &cp, sizeof(cp)) == sizeof(cp)) ? - 1 : 0; - } - -@@ -4049,9 +4096,9 @@ static int yaffs_ReadCheckpointValidityM - yaffs_CheckpointValidity cp; - int ok; - -- ok = (yaffs_CheckpointRead(dev,&cp,sizeof(cp)) == sizeof(cp)); -+ ok = (yaffs_CheckpointRead(dev, &cp, sizeof(cp)) == sizeof(cp)); - -- if(ok) -+ if (ok) - ok = (cp.structType == sizeof(cp)) && - (cp.magic == YAFFS_MAGIC) && - (cp.version == YAFFS_CHECKPOINT_VERSION) && -@@ -4100,21 +4147,21 @@ static int yaffs_WriteCheckpointDevice(y - int ok; - - /* Write device runtime values*/ -- yaffs_DeviceToCheckpointDevice(&cp,dev); -+ yaffs_DeviceToCheckpointDevice(&cp, dev); - cp.structType = sizeof(cp); - -- ok = (yaffs_CheckpointWrite(dev,&cp,sizeof(cp)) == sizeof(cp)); -+ ok = (yaffs_CheckpointWrite(dev, &cp, sizeof(cp)) == sizeof(cp)); - - /* Write block info */ -- if(ok) { -+ if (ok) { - nBytes = nBlocks * sizeof(yaffs_BlockInfo); -- ok = (yaffs_CheckpointWrite(dev,dev->blockInfo,nBytes) == nBytes); -+ ok = (yaffs_CheckpointWrite(dev, dev->blockInfo, nBytes) == nBytes); - } - - /* Write chunk bits */ -- if(ok) { -+ if (ok) { - nBytes = nBlocks * dev->chunkBitmapStride; -- ok = (yaffs_CheckpointWrite(dev,dev->chunkBits,nBytes) == nBytes); -+ ok = (yaffs_CheckpointWrite(dev, dev->chunkBits, nBytes) == nBytes); - } - return ok ? 1 : 0; - -@@ -4128,25 +4175,25 @@ static int yaffs_ReadCheckpointDevice(ya - - int ok; - -- ok = (yaffs_CheckpointRead(dev,&cp,sizeof(cp)) == sizeof(cp)); -- if(!ok) -+ ok = (yaffs_CheckpointRead(dev, &cp, sizeof(cp)) == sizeof(cp)); -+ if (!ok) - return 0; - -- if(cp.structType != sizeof(cp)) -+ if (cp.structType != sizeof(cp)) - return 0; - - -- yaffs_CheckpointDeviceToDevice(dev,&cp); -+ yaffs_CheckpointDeviceToDevice(dev, &cp); - - nBytes = nBlocks * sizeof(yaffs_BlockInfo); - -- ok = (yaffs_CheckpointRead(dev,dev->blockInfo,nBytes) == nBytes); -+ ok = (yaffs_CheckpointRead(dev, dev->blockInfo, nBytes) == nBytes); - -- if(!ok) -+ if (!ok) - return 0; - nBytes = nBlocks * dev->chunkBitmapStride; - -- ok = (yaffs_CheckpointRead(dev,dev->chunkBits,nBytes) == nBytes); -+ ok = (yaffs_CheckpointRead(dev, dev->chunkBits, nBytes) == nBytes); - - return ok ? 1 : 0; - } -@@ -4157,7 +4204,7 @@ static void yaffs_ObjectToCheckpointObje - - cp->objectId = obj->objectId; - cp->parentId = (obj->parent) ? obj->parent->objectId : 0; -- cp->chunkId = obj->chunkId; -+ cp->hdrChunk = obj->hdrChunk; - cp->variantType = obj->variantType; - cp->deleted = obj->deleted; - cp->softDeleted = obj->softDeleted; -@@ -4168,20 +4215,28 @@ static void yaffs_ObjectToCheckpointObje - cp->serial = obj->serial; - cp->nDataChunks = obj->nDataChunks; - -- if(obj->variantType == YAFFS_OBJECT_TYPE_FILE) -+ if (obj->variantType == YAFFS_OBJECT_TYPE_FILE) - cp->fileSizeOrEquivalentObjectId = obj->variant.fileVariant.fileSize; -- else if(obj->variantType == YAFFS_OBJECT_TYPE_HARDLINK) -+ else if (obj->variantType == YAFFS_OBJECT_TYPE_HARDLINK) - cp->fileSizeOrEquivalentObjectId = obj->variant.hardLinkVariant.equivalentObjectId; - } - --static void yaffs_CheckpointObjectToObject( yaffs_Object *obj,yaffs_CheckpointObject *cp) -+static int yaffs_CheckpointObjectToObject(yaffs_Object *obj, yaffs_CheckpointObject *cp) - { - - yaffs_Object *parent; - -+ if (obj->variantType != cp->variantType) { -+ T(YAFFS_TRACE_ERROR, (TSTR("Checkpoint read object %d type %d " -+ TCONT("chunk %d does not match existing object type %d") -+ TENDSTR), cp->objectId, cp->variantType, cp->hdrChunk, -+ obj->variantType)); -+ return 0; -+ } -+ - obj->objectId = cp->objectId; - -- if(cp->parentId) -+ if (cp->parentId) - parent = yaffs_FindOrCreateObjectByNumber( - obj->myDev, - cp->parentId, -@@ -4189,10 +4244,19 @@ static void yaffs_CheckpointObjectToObje - else - parent = NULL; - -- if(parent) -+ if (parent) { -+ if (parent->variantType != YAFFS_OBJECT_TYPE_DIRECTORY) { -+ T(YAFFS_TRACE_ALWAYS, (TSTR("Checkpoint read object %d parent %d type %d" -+ TCONT(" chunk %d Parent type, %d, not directory") -+ TENDSTR), -+ cp->objectId, cp->parentId, cp->variantType, -+ cp->hdrChunk, parent->variantType)); -+ return 0; -+ } - yaffs_AddObjectToDirectory(parent, obj); -+ } - -- obj->chunkId = cp->chunkId; -+ obj->hdrChunk = cp->hdrChunk; - obj->variantType = cp->variantType; - obj->deleted = cp->deleted; - obj->softDeleted = cp->softDeleted; -@@ -4203,29 +4267,34 @@ static void yaffs_CheckpointObjectToObje - obj->serial = cp->serial; - obj->nDataChunks = cp->nDataChunks; - -- if(obj->variantType == YAFFS_OBJECT_TYPE_FILE) -+ if (obj->variantType == YAFFS_OBJECT_TYPE_FILE) - obj->variant.fileVariant.fileSize = cp->fileSizeOrEquivalentObjectId; -- else if(obj->variantType == YAFFS_OBJECT_TYPE_HARDLINK) -+ else if (obj->variantType == YAFFS_OBJECT_TYPE_HARDLINK) - obj->variant.hardLinkVariant.equivalentObjectId = cp->fileSizeOrEquivalentObjectId; - -- if(obj->objectId >= YAFFS_NOBJECT_BUCKETS) -+ if (obj->hdrChunk > 0) - obj->lazyLoaded = 1; -+ return 1; - } - - - --static int yaffs_CheckpointTnodeWorker(yaffs_Object * in, yaffs_Tnode * tn, -- __u32 level, int chunkOffset) -+static int yaffs_CheckpointTnodeWorker(yaffs_Object *in, yaffs_Tnode *tn, -+ __u32 level, int chunkOffset) - { - int i; - yaffs_Device *dev = in->myDev; - int ok = 1; -- int nTnodeBytes = (dev->tnodeWidth * YAFFS_NTNODES_LEVEL0)/8; -+ int tnodeSize = (dev->tnodeWidth * YAFFS_NTNODES_LEVEL0)/8; -+ -+ if (tnodeSize < sizeof(yaffs_Tnode)) -+ tnodeSize = sizeof(yaffs_Tnode); -+ - - if (tn) { - if (level > 0) { - -- for (i = 0; i < YAFFS_NTNODES_INTERNAL && ok; i++){ -+ for (i = 0; i < YAFFS_NTNODES_INTERNAL && ok; i++) { - if (tn->internal[i]) { - ok = yaffs_CheckpointTnodeWorker(in, - tn->internal[i], -@@ -4235,10 +4304,9 @@ static int yaffs_CheckpointTnodeWorker(y - } - } else if (level == 0) { - __u32 baseOffset = chunkOffset << YAFFS_TNODES_LEVEL0_BITS; -- /* printf("write tnode at %d\n",baseOffset); */ -- ok = (yaffs_CheckpointWrite(dev,&baseOffset,sizeof(baseOffset)) == sizeof(baseOffset)); -- if(ok) -- ok = (yaffs_CheckpointWrite(dev,tn,nTnodeBytes) == nTnodeBytes); -+ ok = (yaffs_CheckpointWrite(dev, &baseOffset, sizeof(baseOffset)) == sizeof(baseOffset)); -+ if (ok) -+ ok = (yaffs_CheckpointWrite(dev, tn, tnodeSize) == tnodeSize); - } - } - -@@ -4251,13 +4319,13 @@ static int yaffs_WriteCheckpointTnodes(y - __u32 endMarker = ~0; - int ok = 1; - -- if(obj->variantType == YAFFS_OBJECT_TYPE_FILE){ -+ if (obj->variantType == YAFFS_OBJECT_TYPE_FILE) { - ok = yaffs_CheckpointTnodeWorker(obj, - obj->variant.fileVariant.top, - obj->variant.fileVariant.topLevel, - 0); -- if(ok) -- ok = (yaffs_CheckpointWrite(obj->myDev,&endMarker,sizeof(endMarker)) == -+ if (ok) -+ ok = (yaffs_CheckpointWrite(obj->myDev, &endMarker, sizeof(endMarker)) == - sizeof(endMarker)); - } - -@@ -4272,38 +4340,38 @@ static int yaffs_ReadCheckpointTnodes(ya - yaffs_FileStructure *fileStructPtr = &obj->variant.fileVariant; - yaffs_Tnode *tn; - int nread = 0; -+ int tnodeSize = (dev->tnodeWidth * YAFFS_NTNODES_LEVEL0)/8; - -- ok = (yaffs_CheckpointRead(dev,&baseChunk,sizeof(baseChunk)) == sizeof(baseChunk)); -+ if (tnodeSize < sizeof(yaffs_Tnode)) -+ tnodeSize = sizeof(yaffs_Tnode); - -- while(ok && (~baseChunk)){ -+ ok = (yaffs_CheckpointRead(dev, &baseChunk, sizeof(baseChunk)) == sizeof(baseChunk)); -+ -+ while (ok && (~baseChunk)) { - nread++; - /* Read level 0 tnode */ - - -- /* printf("read tnode at %d\n",baseChunk); */ - tn = yaffs_GetTnodeRaw(dev); -- if(tn) -- ok = (yaffs_CheckpointRead(dev,tn,(dev->tnodeWidth * YAFFS_NTNODES_LEVEL0)/8) == -- (dev->tnodeWidth * YAFFS_NTNODES_LEVEL0)/8); -+ if (tn) -+ ok = (yaffs_CheckpointRead(dev, tn, tnodeSize) == tnodeSize); - else - ok = 0; - -- if(tn && ok){ -+ if (tn && ok) - ok = yaffs_AddOrFindLevel0Tnode(dev, -- fileStructPtr, -- baseChunk, -- tn) ? 1 : 0; -+ fileStructPtr, -+ baseChunk, -+ tn) ? 1 : 0; - -- } -- -- if(ok) -- ok = (yaffs_CheckpointRead(dev,&baseChunk,sizeof(baseChunk)) == sizeof(baseChunk)); -+ if (ok) -+ ok = (yaffs_CheckpointRead(dev, &baseChunk, sizeof(baseChunk)) == sizeof(baseChunk)); - - } - -- T(YAFFS_TRACE_CHECKPOINT,( -+ T(YAFFS_TRACE_CHECKPOINT, ( - TSTR("Checkpoint read tnodes %d records, last %d. ok %d" TENDSTR), -- nread,baseChunk,ok)); -+ nread, baseChunk, ok)); - - return ok ? 1 : 0; - } -@@ -4315,41 +4383,40 @@ static int yaffs_WriteCheckpointObjects( - yaffs_CheckpointObject cp; - int i; - int ok = 1; -- struct list_head *lh; -+ struct ylist_head *lh; - - - /* Iterate through the objects in each hash entry, - * dumping them to the checkpointing stream. - */ - -- for(i = 0; ok && i < YAFFS_NOBJECT_BUCKETS; i++){ -- list_for_each(lh, &dev->objectBucket[i].list) { -+ for (i = 0; ok && i < YAFFS_NOBJECT_BUCKETS; i++) { -+ ylist_for_each(lh, &dev->objectBucket[i].list) { - if (lh) { -- obj = list_entry(lh, yaffs_Object, hashLink); -+ obj = ylist_entry(lh, yaffs_Object, hashLink); - if (!obj->deferedFree) { -- yaffs_ObjectToCheckpointObject(&cp,obj); -+ yaffs_ObjectToCheckpointObject(&cp, obj); - cp.structType = sizeof(cp); - -- T(YAFFS_TRACE_CHECKPOINT,( -+ T(YAFFS_TRACE_CHECKPOINT, ( - TSTR("Checkpoint write object %d parent %d type %d chunk %d obj addr %x" TENDSTR), -- cp.objectId,cp.parentId,cp.variantType,cp.chunkId,(unsigned) obj)); -+ cp.objectId, cp.parentId, cp.variantType, cp.hdrChunk, (unsigned) obj)); - -- ok = (yaffs_CheckpointWrite(dev,&cp,sizeof(cp)) == sizeof(cp)); -+ ok = (yaffs_CheckpointWrite(dev, &cp, sizeof(cp)) == sizeof(cp)); - -- if(ok && obj->variantType == YAFFS_OBJECT_TYPE_FILE){ -+ if (ok && obj->variantType == YAFFS_OBJECT_TYPE_FILE) - ok = yaffs_WriteCheckpointTnodes(obj); -- } - } - } - } -- } -+ } - -- /* Dump end of list */ -- memset(&cp,0xFF,sizeof(yaffs_CheckpointObject)); -+ /* Dump end of list */ -+ memset(&cp, 0xFF, sizeof(yaffs_CheckpointObject)); - cp.structType = sizeof(cp); - -- if(ok) -- ok = (yaffs_CheckpointWrite(dev,&cp,sizeof(cp)) == sizeof(cp)); -+ if (ok) -+ ok = (yaffs_CheckpointWrite(dev, &cp, sizeof(cp)) == sizeof(cp)); - - return ok ? 1 : 0; - } -@@ -4362,38 +4429,39 @@ static int yaffs_ReadCheckpointObjects(y - int done = 0; - yaffs_Object *hardList = NULL; - -- while(ok && !done) { -- ok = (yaffs_CheckpointRead(dev,&cp,sizeof(cp)) == sizeof(cp)); -- if(cp.structType != sizeof(cp)) { -- T(YAFFS_TRACE_CHECKPOINT,(TSTR("struct size %d instead of %d ok %d"TENDSTR), -- cp.structType,sizeof(cp),ok)); -+ while (ok && !done) { -+ ok = (yaffs_CheckpointRead(dev, &cp, sizeof(cp)) == sizeof(cp)); -+ if (cp.structType != sizeof(cp)) { -+ T(YAFFS_TRACE_CHECKPOINT, (TSTR("struct size %d instead of %d ok %d"TENDSTR), -+ cp.structType, sizeof(cp), ok)); - ok = 0; - } - -- T(YAFFS_TRACE_CHECKPOINT,(TSTR("Checkpoint read object %d parent %d type %d chunk %d " TENDSTR), -- cp.objectId,cp.parentId,cp.variantType,cp.chunkId)); -+ T(YAFFS_TRACE_CHECKPOINT, (TSTR("Checkpoint read object %d parent %d type %d chunk %d " TENDSTR), -+ cp.objectId, cp.parentId, cp.variantType, cp.hdrChunk)); - -- if(ok && cp.objectId == ~0) -+ if (ok && cp.objectId == ~0) - done = 1; -- else if(ok){ -- obj = yaffs_FindOrCreateObjectByNumber(dev,cp.objectId, cp.variantType); -- if(obj) { -- yaffs_CheckpointObjectToObject(obj,&cp); -- if(obj->variantType == YAFFS_OBJECT_TYPE_FILE) { -+ else if (ok) { -+ obj = yaffs_FindOrCreateObjectByNumber(dev, cp.objectId, cp.variantType); -+ if (obj) { -+ ok = yaffs_CheckpointObjectToObject(obj, &cp); -+ if (!ok) -+ break; -+ if (obj->variantType == YAFFS_OBJECT_TYPE_FILE) { - ok = yaffs_ReadCheckpointTnodes(obj); -- } else if(obj->variantType == YAFFS_OBJECT_TYPE_HARDLINK) { -+ } else if (obj->variantType == YAFFS_OBJECT_TYPE_HARDLINK) { - obj->hardLinks.next = -- (struct list_head *) -- hardList; -+ (struct ylist_head *) hardList; - hardList = obj; - } -- -- } -+ } else -+ ok = 0; - } - } - -- if(ok) -- yaffs_HardlinkFixup(dev,hardList); -+ if (ok) -+ yaffs_HardlinkFixup(dev, hardList); - - return ok ? 1 : 0; - } -@@ -4403,11 +4471,11 @@ static int yaffs_WriteCheckpointSum(yaff - __u32 checkpointSum; - int ok; - -- yaffs_GetCheckpointSum(dev,&checkpointSum); -+ yaffs_GetCheckpointSum(dev, &checkpointSum); - -- ok = (yaffs_CheckpointWrite(dev,&checkpointSum,sizeof(checkpointSum)) == sizeof(checkpointSum)); -+ ok = (yaffs_CheckpointWrite(dev, &checkpointSum, sizeof(checkpointSum)) == sizeof(checkpointSum)); - -- if(!ok) -+ if (!ok) - return 0; - - return 1; -@@ -4419,14 +4487,14 @@ static int yaffs_ReadCheckpointSum(yaffs - __u32 checkpointSum1; - int ok; - -- yaffs_GetCheckpointSum(dev,&checkpointSum0); -+ yaffs_GetCheckpointSum(dev, &checkpointSum0); - -- ok = (yaffs_CheckpointRead(dev,&checkpointSum1,sizeof(checkpointSum1)) == sizeof(checkpointSum1)); -+ ok = (yaffs_CheckpointRead(dev, &checkpointSum1, sizeof(checkpointSum1)) == sizeof(checkpointSum1)); - -- if(!ok) -+ if (!ok) - return 0; - -- if(checkpointSum0 != checkpointSum1) -+ if (checkpointSum0 != checkpointSum1) - return 0; - - return 1; -@@ -4435,46 +4503,43 @@ static int yaffs_ReadCheckpointSum(yaffs - - static int yaffs_WriteCheckpointData(yaffs_Device *dev) - { -- - int ok = 1; - -- if(dev->skipCheckpointWrite || !dev->isYaffs2){ -- T(YAFFS_TRACE_CHECKPOINT,(TSTR("skipping checkpoint write" TENDSTR))); -+ if (dev->skipCheckpointWrite || !dev->isYaffs2) { -+ T(YAFFS_TRACE_CHECKPOINT, (TSTR("skipping checkpoint write" TENDSTR))); - ok = 0; - } - -- if(ok) -- ok = yaffs_CheckpointOpen(dev,1); -+ if (ok) -+ ok = yaffs_CheckpointOpen(dev, 1); - -- if(ok){ -- T(YAFFS_TRACE_CHECKPOINT,(TSTR("write checkpoint validity" TENDSTR))); -- ok = yaffs_WriteCheckpointValidityMarker(dev,1); -+ if (ok) { -+ T(YAFFS_TRACE_CHECKPOINT, (TSTR("write checkpoint validity" TENDSTR))); -+ ok = yaffs_WriteCheckpointValidityMarker(dev, 1); - } -- if(ok){ -- T(YAFFS_TRACE_CHECKPOINT,(TSTR("write checkpoint device" TENDSTR))); -+ if (ok) { -+ T(YAFFS_TRACE_CHECKPOINT, (TSTR("write checkpoint device" TENDSTR))); - ok = yaffs_WriteCheckpointDevice(dev); - } -- if(ok){ -- T(YAFFS_TRACE_CHECKPOINT,(TSTR("write checkpoint objects" TENDSTR))); -+ if (ok) { -+ T(YAFFS_TRACE_CHECKPOINT, (TSTR("write checkpoint objects" TENDSTR))); - ok = yaffs_WriteCheckpointObjects(dev); - } -- if(ok){ -- T(YAFFS_TRACE_CHECKPOINT,(TSTR("write checkpoint validity" TENDSTR))); -- ok = yaffs_WriteCheckpointValidityMarker(dev,0); -+ if (ok) { -+ T(YAFFS_TRACE_CHECKPOINT, (TSTR("write checkpoint validity" TENDSTR))); -+ ok = yaffs_WriteCheckpointValidityMarker(dev, 0); - } - -- if(ok){ -+ if (ok) - ok = yaffs_WriteCheckpointSum(dev); -- } -- - -- if(!yaffs_CheckpointClose(dev)) -- ok = 0; -+ if (!yaffs_CheckpointClose(dev)) -+ ok = 0; - -- if(ok) -- dev->isCheckpointed = 1; -- else -- dev->isCheckpointed = 0; -+ if (ok) -+ dev->isCheckpointed = 1; -+ else -+ dev->isCheckpointed = 0; - - return dev->isCheckpointed; - } -@@ -4483,43 +4548,43 @@ static int yaffs_ReadCheckpointData(yaff - { - int ok = 1; - -- if(dev->skipCheckpointRead || !dev->isYaffs2){ -- T(YAFFS_TRACE_CHECKPOINT,(TSTR("skipping checkpoint read" TENDSTR))); -+ if (dev->skipCheckpointRead || !dev->isYaffs2) { -+ T(YAFFS_TRACE_CHECKPOINT, (TSTR("skipping checkpoint read" TENDSTR))); - ok = 0; - } - -- if(ok) -- ok = yaffs_CheckpointOpen(dev,0); /* open for read */ -+ if (ok) -+ ok = yaffs_CheckpointOpen(dev, 0); /* open for read */ - -- if(ok){ -- T(YAFFS_TRACE_CHECKPOINT,(TSTR("read checkpoint validity" TENDSTR))); -- ok = yaffs_ReadCheckpointValidityMarker(dev,1); -+ if (ok) { -+ T(YAFFS_TRACE_CHECKPOINT, (TSTR("read checkpoint validity" TENDSTR))); -+ ok = yaffs_ReadCheckpointValidityMarker(dev, 1); - } -- if(ok){ -- T(YAFFS_TRACE_CHECKPOINT,(TSTR("read checkpoint device" TENDSTR))); -+ if (ok) { -+ T(YAFFS_TRACE_CHECKPOINT, (TSTR("read checkpoint device" TENDSTR))); - ok = yaffs_ReadCheckpointDevice(dev); - } -- if(ok){ -- T(YAFFS_TRACE_CHECKPOINT,(TSTR("read checkpoint objects" TENDSTR))); -+ if (ok) { -+ T(YAFFS_TRACE_CHECKPOINT, (TSTR("read checkpoint objects" TENDSTR))); - ok = yaffs_ReadCheckpointObjects(dev); - } -- if(ok){ -- T(YAFFS_TRACE_CHECKPOINT,(TSTR("read checkpoint validity" TENDSTR))); -- ok = yaffs_ReadCheckpointValidityMarker(dev,0); -+ if (ok) { -+ T(YAFFS_TRACE_CHECKPOINT, (TSTR("read checkpoint validity" TENDSTR))); -+ ok = yaffs_ReadCheckpointValidityMarker(dev, 0); - } - -- if(ok){ -+ if (ok) { - ok = yaffs_ReadCheckpointSum(dev); -- T(YAFFS_TRACE_CHECKPOINT,(TSTR("read checkpoint checksum %d" TENDSTR),ok)); -+ T(YAFFS_TRACE_CHECKPOINT, (TSTR("read checkpoint checksum %d" TENDSTR), ok)); - } - -- if(!yaffs_CheckpointClose(dev)) -+ if (!yaffs_CheckpointClose(dev)) - ok = 0; - -- if(ok) -- dev->isCheckpointed = 1; -- else -- dev->isCheckpointed = 0; -+ if (ok) -+ dev->isCheckpointed = 1; -+ else -+ dev->isCheckpointed = 0; - - return ok ? 1 : 0; - -@@ -4527,11 +4592,11 @@ static int yaffs_ReadCheckpointData(yaff - - static void yaffs_InvalidateCheckpoint(yaffs_Device *dev) - { -- if(dev->isCheckpointed || -- dev->blocksInCheckpoint > 0){ -+ if (dev->isCheckpointed || -+ dev->blocksInCheckpoint > 0) { - dev->isCheckpointed = 0; - yaffs_CheckpointInvalidateStream(dev); -- if(dev->superBlock && dev->markSuperBlockDirty) -+ if (dev->superBlock && dev->markSuperBlockDirty) - dev->markSuperBlockDirty(dev->superBlock); - } - } -@@ -4540,18 +4605,18 @@ static void yaffs_InvalidateCheckpoint(y - int yaffs_CheckpointSave(yaffs_Device *dev) - { - -- T(YAFFS_TRACE_CHECKPOINT,(TSTR("save entry: isCheckpointed %d"TENDSTR),dev->isCheckpointed)); -+ T(YAFFS_TRACE_CHECKPOINT, (TSTR("save entry: isCheckpointed %d"TENDSTR), dev->isCheckpointed)); - - yaffs_VerifyObjects(dev); - yaffs_VerifyBlocks(dev); - yaffs_VerifyFreeChunks(dev); - -- if(!dev->isCheckpointed) { -+ if (!dev->isCheckpointed) { - yaffs_InvalidateCheckpoint(dev); - yaffs_WriteCheckpointData(dev); - } - -- T(YAFFS_TRACE_ALWAYS,(TSTR("save exit: isCheckpointed %d"TENDSTR),dev->isCheckpointed)); -+ T(YAFFS_TRACE_ALWAYS, (TSTR("save exit: isCheckpointed %d"TENDSTR), dev->isCheckpointed)); - - return dev->isCheckpointed; - } -@@ -4559,17 +4624,17 @@ int yaffs_CheckpointSave(yaffs_Device *d - int yaffs_CheckpointRestore(yaffs_Device *dev) - { - int retval; -- T(YAFFS_TRACE_CHECKPOINT,(TSTR("restore entry: isCheckpointed %d"TENDSTR),dev->isCheckpointed)); -+ T(YAFFS_TRACE_CHECKPOINT, (TSTR("restore entry: isCheckpointed %d"TENDSTR), dev->isCheckpointed)); - - retval = yaffs_ReadCheckpointData(dev); - -- if(dev->isCheckpointed){ -+ if (dev->isCheckpointed) { - yaffs_VerifyObjects(dev); - yaffs_VerifyBlocks(dev); - yaffs_VerifyFreeChunks(dev); - } - -- T(YAFFS_TRACE_CHECKPOINT,(TSTR("restore exit: isCheckpointed %d"TENDSTR),dev->isCheckpointed)); -+ T(YAFFS_TRACE_CHECKPOINT, (TSTR("restore exit: isCheckpointed %d"TENDSTR), dev->isCheckpointed)); - - return retval; - } -@@ -4584,12 +4649,12 @@ int yaffs_CheckpointRestore(yaffs_Device - * Curve-balls: the first chunk might also be the last chunk. - */ - --int yaffs_ReadDataFromFile(yaffs_Object * in, __u8 * buffer, loff_t offset, -- int nBytes) -+int yaffs_ReadDataFromFile(yaffs_Object *in, __u8 *buffer, loff_t offset, -+ int nBytes) - { - - int chunk; -- int start; -+ __u32 start; - int nToCopy; - int n = nBytes; - int nDone = 0; -@@ -4600,27 +4665,26 @@ int yaffs_ReadDataFromFile(yaffs_Object - dev = in->myDev; - - while (n > 0) { -- //chunk = offset / dev->nDataBytesPerChunk + 1; -- //start = offset % dev->nDataBytesPerChunk; -- yaffs_AddrToChunk(dev,offset,&chunk,&start); -+ /* chunk = offset / dev->nDataBytesPerChunk + 1; */ -+ /* start = offset % dev->nDataBytesPerChunk; */ -+ yaffs_AddrToChunk(dev, offset, &chunk, &start); - chunk++; - - /* OK now check for the curveball where the start and end are in - * the same chunk. - */ -- if ((start + n) < dev->nDataBytesPerChunk) { -+ if ((start + n) < dev->nDataBytesPerChunk) - nToCopy = n; -- } else { -+ else - nToCopy = dev->nDataBytesPerChunk - start; -- } - - cache = yaffs_FindChunkCache(in, chunk); - - /* If the chunk is already in the cache or it is less than a whole chunk -- * then use the cache (if there is caching) -+ * or we're using inband tags then use the cache (if there is caching) - * else bypass the cache. - */ -- if (cache || nToCopy != dev->nDataBytesPerChunk) { -+ if (cache || nToCopy != dev->nDataBytesPerChunk || dev->inbandTags) { - if (dev->nShortOpCaches > 0) { - - /* If we can't find the data in the cache, then load it up. */ -@@ -4641,14 +4705,9 @@ int yaffs_ReadDataFromFile(yaffs_Object - - cache->locked = 1; - --#ifdef CONFIG_YAFFS_WINCE -- yfsd_UnlockYAFFS(TRUE); --#endif -+ - memcpy(buffer, &cache->data[start], nToCopy); - --#ifdef CONFIG_YAFFS_WINCE -- yfsd_LockYAFFS(TRUE); --#endif - cache->locked = 0; - } else { - /* Read into the local buffer then copy..*/ -@@ -4657,41 +4716,19 @@ int yaffs_ReadDataFromFile(yaffs_Object - yaffs_GetTempBuffer(dev, __LINE__); - yaffs_ReadChunkDataFromObject(in, chunk, - localBuffer); --#ifdef CONFIG_YAFFS_WINCE -- yfsd_UnlockYAFFS(TRUE); --#endif -+ - memcpy(buffer, &localBuffer[start], nToCopy); - --#ifdef CONFIG_YAFFS_WINCE -- yfsd_LockYAFFS(TRUE); --#endif -+ - yaffs_ReleaseTempBuffer(dev, localBuffer, - __LINE__); - } - - } else { --#ifdef CONFIG_YAFFS_WINCE -- __u8 *localBuffer = yaffs_GetTempBuffer(dev, __LINE__); -- -- /* Under WinCE can't do direct transfer. Need to use a local buffer. -- * This is because we otherwise screw up WinCE's memory mapper -- */ -- yaffs_ReadChunkDataFromObject(in, chunk, localBuffer); -- --#ifdef CONFIG_YAFFS_WINCE -- yfsd_UnlockYAFFS(TRUE); --#endif -- memcpy(buffer, localBuffer, dev->nDataBytesPerChunk); - --#ifdef CONFIG_YAFFS_WINCE -- yfsd_LockYAFFS(TRUE); -- yaffs_ReleaseTempBuffer(dev, localBuffer, __LINE__); --#endif -- --#else - /* A full chunk. Read directly into the supplied buffer. */ - yaffs_ReadChunkDataFromObject(in, chunk, buffer); --#endif -+ - } - - n -= nToCopy; -@@ -4704,28 +4741,37 @@ int yaffs_ReadDataFromFile(yaffs_Object - return nDone; - } - --int yaffs_WriteDataToFile(yaffs_Object * in, const __u8 * buffer, loff_t offset, -- int nBytes, int writeThrough) -+int yaffs_WriteDataToFile(yaffs_Object *in, const __u8 *buffer, loff_t offset, -+ int nBytes, int writeThrough) - { - - int chunk; -- int start; -+ __u32 start; - int nToCopy; - int n = nBytes; - int nDone = 0; - int nToWriteBack; - int startOfWrite = offset; - int chunkWritten = 0; -- int nBytesRead; -+ __u32 nBytesRead; -+ __u32 chunkStart; - - yaffs_Device *dev; - - dev = in->myDev; - - while (n > 0 && chunkWritten >= 0) { -- //chunk = offset / dev->nDataBytesPerChunk + 1; -- //start = offset % dev->nDataBytesPerChunk; -- yaffs_AddrToChunk(dev,offset,&chunk,&start); -+ /* chunk = offset / dev->nDataBytesPerChunk + 1; */ -+ /* start = offset % dev->nDataBytesPerChunk; */ -+ yaffs_AddrToChunk(dev, offset, &chunk, &start); -+ -+ if (chunk * dev->nDataBytesPerChunk + start != offset || -+ start >= dev->nDataBytesPerChunk) { -+ T(YAFFS_TRACE_ERROR, ( -+ TSTR("AddrToChunk of offset %d gives chunk %d start %d" -+ TENDSTR), -+ (int)offset, chunk, start)); -+ } - chunk++; - - /* OK now check for the curveball where the start and end are in -@@ -4740,25 +4786,32 @@ int yaffs_WriteDataToFile(yaffs_Object * - * we need to write back as much as was there before. - */ - -- nBytesRead = -- in->variant.fileVariant.fileSize - -- ((chunk - 1) * dev->nDataBytesPerChunk); -+ chunkStart = ((chunk - 1) * dev->nDataBytesPerChunk); -+ -+ if (chunkStart > in->variant.fileVariant.fileSize) -+ nBytesRead = 0; /* Past end of file */ -+ else -+ nBytesRead = in->variant.fileVariant.fileSize - chunkStart; - -- if (nBytesRead > dev->nDataBytesPerChunk) { -+ if (nBytesRead > dev->nDataBytesPerChunk) - nBytesRead = dev->nDataBytesPerChunk; -- } - - nToWriteBack = - (nBytesRead > - (start + n)) ? nBytesRead : (start + n); - -+ if (nToWriteBack < 0 || nToWriteBack > dev->nDataBytesPerChunk) -+ YBUG(); -+ - } else { - nToCopy = dev->nDataBytesPerChunk - start; - nToWriteBack = dev->nDataBytesPerChunk; - } - -- if (nToCopy != dev->nDataBytesPerChunk) { -- /* An incomplete start or end chunk (or maybe both start and end chunk) */ -+ if (nToCopy != dev->nDataBytesPerChunk || dev->inbandTags) { -+ /* An incomplete start or end chunk (or maybe both start and end chunk), -+ * or we're using inband tags, so we want to use the cache buffers. -+ */ - if (dev->nShortOpCaches > 0) { - yaffs_ChunkCache *cache; - /* If we can't find the data in the cache, then load the cache */ -@@ -4775,10 +4828,9 @@ int yaffs_WriteDataToFile(yaffs_Object * - yaffs_ReadChunkDataFromObject(in, chunk, - cache-> - data); -- } -- else if(cache && -- !cache->dirty && -- !yaffs_CheckSpaceForAllocation(in->myDev)){ -+ } else if (cache && -+ !cache->dirty && -+ !yaffs_CheckSpaceForAllocation(in->myDev)) { - /* Drop the cache if it was a read cache item and - * no space check has been made for it. - */ -@@ -4788,16 +4840,12 @@ int yaffs_WriteDataToFile(yaffs_Object * - if (cache) { - yaffs_UseChunkCache(dev, cache, 1); - cache->locked = 1; --#ifdef CONFIG_YAFFS_WINCE -- yfsd_UnlockYAFFS(TRUE); --#endif -+ - - memcpy(&cache->data[start], buffer, - nToCopy); - --#ifdef CONFIG_YAFFS_WINCE -- yfsd_LockYAFFS(TRUE); --#endif -+ - cache->locked = 0; - cache->nBytes = nToWriteBack; - -@@ -4825,15 +4873,10 @@ int yaffs_WriteDataToFile(yaffs_Object * - yaffs_ReadChunkDataFromObject(in, chunk, - localBuffer); - --#ifdef CONFIG_YAFFS_WINCE -- yfsd_UnlockYAFFS(TRUE); --#endif -+ - - memcpy(&localBuffer[start], buffer, nToCopy); - --#ifdef CONFIG_YAFFS_WINCE -- yfsd_LockYAFFS(TRUE); --#endif - chunkWritten = - yaffs_WriteChunkDataToObject(in, chunk, - localBuffer, -@@ -4846,31 +4889,15 @@ int yaffs_WriteDataToFile(yaffs_Object * - } - - } else { -- --#ifdef CONFIG_YAFFS_WINCE -- /* Under WinCE can't do direct transfer. Need to use a local buffer. -- * This is because we otherwise screw up WinCE's memory mapper -- */ -- __u8 *localBuffer = yaffs_GetTempBuffer(dev, __LINE__); --#ifdef CONFIG_YAFFS_WINCE -- yfsd_UnlockYAFFS(TRUE); --#endif -- memcpy(localBuffer, buffer, dev->nDataBytesPerChunk); --#ifdef CONFIG_YAFFS_WINCE -- yfsd_LockYAFFS(TRUE); --#endif -- chunkWritten = -- yaffs_WriteChunkDataToObject(in, chunk, localBuffer, -- dev->nDataBytesPerChunk, -- 0); -- yaffs_ReleaseTempBuffer(dev, localBuffer, __LINE__); --#else - /* A full chunk. Write directly from the supplied buffer. */ -+ -+ -+ - chunkWritten = - yaffs_WriteChunkDataToObject(in, chunk, buffer, - dev->nDataBytesPerChunk, - 0); --#endif -+ - /* Since we've overwritten the cached data, we better invalidate it. */ - yaffs_InvalidateChunkCache(in, chunk); - } -@@ -4886,9 +4913,8 @@ int yaffs_WriteDataToFile(yaffs_Object * - - /* Update file object */ - -- if ((startOfWrite + nDone) > in->variant.fileVariant.fileSize) { -+ if ((startOfWrite + nDone) > in->variant.fileVariant.fileSize) - in->variant.fileVariant.fileSize = (startOfWrite + nDone); -- } - - in->dirty = 1; - -@@ -4898,7 +4924,7 @@ int yaffs_WriteDataToFile(yaffs_Object * - - /* ---------------------- File resizing stuff ------------------ */ - --static void yaffs_PruneResizedChunks(yaffs_Object * in, int newSize) -+static void yaffs_PruneResizedChunks(yaffs_Object *in, int newSize) - { - - yaffs_Device *dev = in->myDev; -@@ -4939,11 +4965,11 @@ static void yaffs_PruneResizedChunks(yaf - - } - --int yaffs_ResizeFile(yaffs_Object * in, loff_t newSize) -+int yaffs_ResizeFile(yaffs_Object *in, loff_t newSize) - { - - int oldFileSize = in->variant.fileVariant.fileSize; -- int newSizeOfPartialChunk; -+ __u32 newSizeOfPartialChunk; - int newFullChunks; - - yaffs_Device *dev = in->myDev; -@@ -4955,13 +4981,11 @@ int yaffs_ResizeFile(yaffs_Object * in, - - yaffs_CheckGarbageCollection(dev); - -- if (in->variantType != YAFFS_OBJECT_TYPE_FILE) { -- return yaffs_GetFileSize(in); -- } -+ if (in->variantType != YAFFS_OBJECT_TYPE_FILE) -+ return YAFFS_FAIL; - -- if (newSize == oldFileSize) { -- return oldFileSize; -- } -+ if (newSize == oldFileSize) -+ return YAFFS_OK; - - if (newSize < oldFileSize) { - -@@ -4994,21 +5018,20 @@ int yaffs_ResizeFile(yaffs_Object * in, - } - - -- - /* Write a new object header. - * show we've shrunk the file, if need be - * Do this only if the file is not in the deleted directories. - */ -- if (in->parent->objectId != YAFFS_OBJECTID_UNLINKED && -- in->parent->objectId != YAFFS_OBJECTID_DELETED) { -+ if (in->parent && -+ in->parent->objectId != YAFFS_OBJECTID_UNLINKED && -+ in->parent->objectId != YAFFS_OBJECTID_DELETED) - yaffs_UpdateObjectHeader(in, NULL, 0, - (newSize < oldFileSize) ? 1 : 0, 0); -- } - -- return newSize; -+ return YAFFS_OK; - } - --loff_t yaffs_GetFileSize(yaffs_Object * obj) -+loff_t yaffs_GetFileSize(yaffs_Object *obj) - { - obj = yaffs_GetEquivalentObject(obj); - -@@ -5024,7 +5047,7 @@ loff_t yaffs_GetFileSize(yaffs_Object * - - - --int yaffs_FlushFile(yaffs_Object * in, int updateTime) -+int yaffs_FlushFile(yaffs_Object *in, int updateTime) - { - int retVal; - if (in->dirty) { -@@ -5039,9 +5062,8 @@ int yaffs_FlushFile(yaffs_Object * in, i - #endif - } - -- retVal = -- (yaffs_UpdateObjectHeader(in, NULL, 0, 0, 0) >= -- 0) ? YAFFS_OK : YAFFS_FAIL; -+ retVal = (yaffs_UpdateObjectHeader(in, NULL, 0, 0, 0) >= -+ 0) ? YAFFS_OK : YAFFS_FAIL; - } else { - retVal = YAFFS_OK; - } -@@ -5050,7 +5072,7 @@ int yaffs_FlushFile(yaffs_Object * in, i - - } - --static int yaffs_DoGenericObjectDeletion(yaffs_Object * in) -+static int yaffs_DoGenericObjectDeletion(yaffs_Object *in) - { - - /* First off, invalidate the file's data in the cache, without flushing. */ -@@ -5058,13 +5080,13 @@ static int yaffs_DoGenericObjectDeletion - - if (in->myDev->isYaffs2 && (in->parent != in->myDev->deletedDir)) { - /* Move to the unlinked directory so we have a record that it was deleted. */ -- yaffs_ChangeObjectName(in, in->myDev->deletedDir,"deleted", 0, 0); -+ yaffs_ChangeObjectName(in, in->myDev->deletedDir, _Y("deleted"), 0, 0); - - } - - yaffs_RemoveObjectFromDirectory(in); -- yaffs_DeleteChunk(in->myDev, in->chunkId, 1, __LINE__); -- in->chunkId = -1; -+ yaffs_DeleteChunk(in->myDev, in->hdrChunk, 1, __LINE__); -+ in->hdrChunk = 0; - - yaffs_FreeObject(in); - return YAFFS_OK; -@@ -5075,62 +5097,63 @@ static int yaffs_DoGenericObjectDeletion - * and the inode associated with the file. - * It does not delete the links associated with the file. - */ --static int yaffs_UnlinkFile(yaffs_Object * in) -+static int yaffs_UnlinkFileIfNeeded(yaffs_Object *in) - { - - int retVal; - int immediateDeletion = 0; - -- if (1) { - #ifdef __KERNEL__ -- if (!in->myInode) { -- immediateDeletion = 1; -- -- } -+ if (!in->myInode) -+ immediateDeletion = 1; - #else -- if (in->inUse <= 0) { -- immediateDeletion = 1; -- -- } -+ if (in->inUse <= 0) -+ immediateDeletion = 1; - #endif -- if (immediateDeletion) { -- retVal = -- yaffs_ChangeObjectName(in, in->myDev->deletedDir, -- "deleted", 0, 0); -- T(YAFFS_TRACE_TRACING, -- (TSTR("yaffs: immediate deletion of file %d" TENDSTR), -- in->objectId)); -- in->deleted = 1; -- in->myDev->nDeletedFiles++; -- if (0 && in->myDev->isYaffs2) { -- yaffs_ResizeFile(in, 0); -- } -- yaffs_SoftDeleteFile(in); -- } else { -- retVal = -- yaffs_ChangeObjectName(in, in->myDev->unlinkedDir, -- "unlinked", 0, 0); -- } - -+ if (immediateDeletion) { -+ retVal = -+ yaffs_ChangeObjectName(in, in->myDev->deletedDir, -+ _Y("deleted"), 0, 0); -+ T(YAFFS_TRACE_TRACING, -+ (TSTR("yaffs: immediate deletion of file %d" TENDSTR), -+ in->objectId)); -+ in->deleted = 1; -+ in->myDev->nDeletedFiles++; -+ if (1 || in->myDev->isYaffs2) -+ yaffs_ResizeFile(in, 0); -+ yaffs_SoftDeleteFile(in); -+ } else { -+ retVal = -+ yaffs_ChangeObjectName(in, in->myDev->unlinkedDir, -+ _Y("unlinked"), 0, 0); - } -+ -+ - return retVal; - } - --int yaffs_DeleteFile(yaffs_Object * in) -+int yaffs_DeleteFile(yaffs_Object *in) - { - int retVal = YAFFS_OK; -+ int deleted = in->deleted; -+ -+ yaffs_ResizeFile(in, 0); - - if (in->nDataChunks > 0) { -- /* Use soft deletion if there is data in the file */ -- if (!in->unlinked) { -- retVal = yaffs_UnlinkFile(in); -- } -+ /* Use soft deletion if there is data in the file. -+ * That won't be the case if it has been resized to zero. -+ */ -+ if (!in->unlinked) -+ retVal = yaffs_UnlinkFileIfNeeded(in); -+ - if (retVal == YAFFS_OK && in->unlinked && !in->deleted) { - in->deleted = 1; -+ deleted = 1; - in->myDev->nDeletedFiles++; - yaffs_SoftDeleteFile(in); - } -- return in->deleted ? YAFFS_OK : YAFFS_FAIL; -+ return deleted ? YAFFS_OK : YAFFS_FAIL; - } else { - /* The file has no data chunks so we toss it immediately */ - yaffs_FreeTnode(in->myDev, in->variant.fileVariant.top); -@@ -5141,62 +5164,75 @@ int yaffs_DeleteFile(yaffs_Object * in) - } - } - --static int yaffs_DeleteDirectory(yaffs_Object * in) -+static int yaffs_DeleteDirectory(yaffs_Object *in) - { - /* First check that the directory is empty. */ -- if (list_empty(&in->variant.directoryVariant.children)) { -+ if (ylist_empty(&in->variant.directoryVariant.children)) - return yaffs_DoGenericObjectDeletion(in); -- } - - return YAFFS_FAIL; - - } - --static int yaffs_DeleteSymLink(yaffs_Object * in) -+static int yaffs_DeleteSymLink(yaffs_Object *in) - { - YFREE(in->variant.symLinkVariant.alias); - - return yaffs_DoGenericObjectDeletion(in); - } - --static int yaffs_DeleteHardLink(yaffs_Object * in) -+static int yaffs_DeleteHardLink(yaffs_Object *in) - { - /* remove this hardlink from the list assocaited with the equivalent - * object - */ -- list_del(&in->hardLinks); -+ ylist_del_init(&in->hardLinks); - return yaffs_DoGenericObjectDeletion(in); - } - --static void yaffs_DestroyObject(yaffs_Object * obj) -+int yaffs_DeleteObject(yaffs_Object *obj) - { -+int retVal = -1; - switch (obj->variantType) { - case YAFFS_OBJECT_TYPE_FILE: -- yaffs_DeleteFile(obj); -+ retVal = yaffs_DeleteFile(obj); - break; - case YAFFS_OBJECT_TYPE_DIRECTORY: -- yaffs_DeleteDirectory(obj); -+ return yaffs_DeleteDirectory(obj); - break; - case YAFFS_OBJECT_TYPE_SYMLINK: -- yaffs_DeleteSymLink(obj); -+ retVal = yaffs_DeleteSymLink(obj); - break; - case YAFFS_OBJECT_TYPE_HARDLINK: -- yaffs_DeleteHardLink(obj); -+ retVal = yaffs_DeleteHardLink(obj); - break; - case YAFFS_OBJECT_TYPE_SPECIAL: -- yaffs_DoGenericObjectDeletion(obj); -+ retVal = yaffs_DoGenericObjectDeletion(obj); - break; - case YAFFS_OBJECT_TYPE_UNKNOWN: -+ retVal = 0; - break; /* should not happen. */ - } -+ -+ return retVal; - } - --static int yaffs_UnlinkWorker(yaffs_Object * obj) -+static int yaffs_UnlinkWorker(yaffs_Object *obj) - { - -+ int immediateDeletion = 0; -+ -+#ifdef __KERNEL__ -+ if (!obj->myInode) -+ immediateDeletion = 1; -+#else -+ if (obj->inUse <= 0) -+ immediateDeletion = 1; -+#endif -+ - if (obj->variantType == YAFFS_OBJECT_TYPE_HARDLINK) { - return yaffs_DeleteHardLink(obj); -- } else if (!list_empty(&obj->hardLinks)) { -+ } else if (!ylist_empty(&obj->hardLinks)) { - /* Curve ball: We're unlinking an object that has a hardlink. - * - * This problem arises because we are not strictly following -@@ -5215,24 +5251,24 @@ static int yaffs_UnlinkWorker(yaffs_Obje - int retVal; - YCHAR name[YAFFS_MAX_NAME_LENGTH + 1]; - -- hl = list_entry(obj->hardLinks.next, yaffs_Object, hardLinks); -+ hl = ylist_entry(obj->hardLinks.next, yaffs_Object, hardLinks); - -- list_del_init(&hl->hardLinks); -- list_del_init(&hl->siblings); -+ ylist_del_init(&hl->hardLinks); -+ ylist_del_init(&hl->siblings); - - yaffs_GetObjectName(hl, name, YAFFS_MAX_NAME_LENGTH + 1); - - retVal = yaffs_ChangeObjectName(obj, hl->parent, name, 0, 0); - -- if (retVal == YAFFS_OK) { -+ if (retVal == YAFFS_OK) - retVal = yaffs_DoGenericObjectDeletion(hl); -- } -+ - return retVal; - -- } else { -+ } else if (immediateDeletion) { - switch (obj->variantType) { - case YAFFS_OBJECT_TYPE_FILE: -- return yaffs_UnlinkFile(obj); -+ return yaffs_DeleteFile(obj); - break; - case YAFFS_OBJECT_TYPE_DIRECTORY: - return yaffs_DeleteDirectory(obj); -@@ -5248,21 +5284,22 @@ static int yaffs_UnlinkWorker(yaffs_Obje - default: - return YAFFS_FAIL; - } -- } -+ } else -+ return yaffs_ChangeObjectName(obj, obj->myDev->unlinkedDir, -+ _Y("unlinked"), 0, 0); - } - - --static int yaffs_UnlinkObject( yaffs_Object *obj) -+static int yaffs_UnlinkObject(yaffs_Object *obj) - { - -- if (obj && obj->unlinkAllowed) { -+ if (obj && obj->unlinkAllowed) - return yaffs_UnlinkWorker(obj); -- } - - return YAFFS_FAIL; - - } --int yaffs_Unlink(yaffs_Object * dir, const YCHAR * name) -+int yaffs_Unlink(yaffs_Object *dir, const YCHAR *name) - { - yaffs_Object *obj; - -@@ -5272,8 +5309,8 @@ int yaffs_Unlink(yaffs_Object * dir, con - - /*----------------------- Initialisation Scanning ---------------------- */ - --static void yaffs_HandleShadowedObject(yaffs_Device * dev, int objId, -- int backwardScanning) -+static void yaffs_HandleShadowedObject(yaffs_Device *dev, int objId, -+ int backwardScanning) - { - yaffs_Object *obj; - -@@ -5286,9 +5323,8 @@ static void yaffs_HandleShadowedObject(y - /* Handle YAFFS2 case (backward scanning) - * If the shadowed object exists then ignore. - */ -- if (yaffs_FindObjectByNumber(dev, objId)) { -+ if (yaffs_FindObjectByNumber(dev, objId)) - return; -- } - } - - /* Let's create it (if it does not exist) assuming it is a file so that it can do shrinking etc. -@@ -5297,6 +5333,8 @@ static void yaffs_HandleShadowedObject(y - obj = - yaffs_FindOrCreateObjectByNumber(dev, objId, - YAFFS_OBJECT_TYPE_FILE); -+ if (!obj) -+ return; - yaffs_AddObjectToDirectory(dev->unlinkedDir, obj); - obj->variant.fileVariant.shrinkSize = 0; - obj->valid = 1; /* So that we don't read any other info for this file */ -@@ -5325,44 +5363,77 @@ static void yaffs_HardlinkFixup(yaffs_De - if (in) { - /* Add the hardlink pointers */ - hl->variant.hardLinkVariant.equivalentObject = in; -- list_add(&hl->hardLinks, &in->hardLinks); -+ ylist_add(&hl->hardLinks, &in->hardLinks); - } else { - /* Todo Need to report/handle this better. - * Got a problem... hardlink to a non-existant object - */ - hl->variant.hardLinkVariant.equivalentObject = NULL; -- INIT_LIST_HEAD(&hl->hardLinks); -+ YINIT_LIST_HEAD(&hl->hardLinks); - - } -- - } -+} -+ -+ - -+ -+ -+static int ybicmp(const void *a, const void *b) -+{ -+ register int aseq = ((yaffs_BlockIndex *)a)->seq; -+ register int bseq = ((yaffs_BlockIndex *)b)->seq; -+ register int ablock = ((yaffs_BlockIndex *)a)->block; -+ register int bblock = ((yaffs_BlockIndex *)b)->block; -+ if (aseq == bseq) -+ return ablock - bblock; -+ else -+ return aseq - bseq; - } - - -+struct yaffs_ShadowFixerStruct { -+ int objectId; -+ int shadowedId; -+ struct yaffs_ShadowFixerStruct *next; -+}; -+ - -+static void yaffs_StripDeletedObjects(yaffs_Device *dev) -+{ -+ /* -+ * Sort out state of unlinked and deleted objects after scanning. -+ */ -+ struct ylist_head *i; -+ struct ylist_head *n; -+ yaffs_Object *l; - -+ /* Soft delete all the unlinked files */ -+ ylist_for_each_safe(i, n, -+ &dev->unlinkedDir->variant.directoryVariant.children) { -+ if (i) { -+ l = ylist_entry(i, yaffs_Object, siblings); -+ yaffs_DeleteObject(l); -+ } -+ } - --static int ybicmp(const void *a, const void *b){ -- register int aseq = ((yaffs_BlockIndex *)a)->seq; -- register int bseq = ((yaffs_BlockIndex *)b)->seq; -- register int ablock = ((yaffs_BlockIndex *)a)->block; -- register int bblock = ((yaffs_BlockIndex *)b)->block; -- if( aseq == bseq ) -- return ablock - bblock; -- else -- return aseq - bseq; -+ ylist_for_each_safe(i, n, -+ &dev->deletedDir->variant.directoryVariant.children) { -+ if (i) { -+ l = ylist_entry(i, yaffs_Object, siblings); -+ yaffs_DeleteObject(l); -+ } -+ } - - } - --static int yaffs_Scan(yaffs_Device * dev) -+static int yaffs_Scan(yaffs_Device *dev) - { - yaffs_ExtendedTags tags; - int blk; - int blockIterator; - int startIterator; - int endIterator; -- int nBlocksToScan = 0; - int result; - - int chunk; -@@ -5371,26 +5442,19 @@ static int yaffs_Scan(yaffs_Device * dev - yaffs_BlockState state; - yaffs_Object *hardList = NULL; - yaffs_BlockInfo *bi; -- int sequenceNumber; -+ __u32 sequenceNumber; - yaffs_ObjectHeader *oh; - yaffs_Object *in; - yaffs_Object *parent; -- int nBlocks = dev->internalEndBlock - dev->internalStartBlock + 1; - - int alloc_failed = 0; - -+ struct yaffs_ShadowFixerStruct *shadowFixerList = NULL; -+ - - __u8 *chunkData; - -- yaffs_BlockIndex *blockIndex = NULL; - -- if (dev->isYaffs2) { -- T(YAFFS_TRACE_SCAN, -- (TSTR("yaffs_Scan is not for YAFFS2!" TENDSTR))); -- return YAFFS_FAIL; -- } -- -- //TODO Throw all the yaffs2 stuuf out of yaffs_Scan since it is only for yaffs1 format. - - T(YAFFS_TRACE_SCAN, - (TSTR("yaffs_Scan starts intstartblk %d intendblk %d..." TENDSTR), -@@ -5400,12 +5464,6 @@ static int yaffs_Scan(yaffs_Device * dev - - dev->sequenceNumber = YAFFS_LOWEST_SEQUENCE_NUMBER; - -- if (dev->isYaffs2) { -- blockIndex = YMALLOC(nBlocks * sizeof(yaffs_BlockIndex)); -- if(!blockIndex) -- return YAFFS_FAIL; -- } -- - /* Scan all the blocks to determine their state */ - for (blk = dev->internalStartBlock; blk <= dev->internalEndBlock; blk++) { - bi = yaffs_GetBlockInfo(dev, blk); -@@ -5418,6 +5476,9 @@ static int yaffs_Scan(yaffs_Device * dev - bi->blockState = state; - bi->sequenceNumber = sequenceNumber; - -+ if (bi->sequenceNumber == YAFFS_SEQUENCE_BAD_BLOCK) -+ bi->blockState = state = YAFFS_BLOCK_STATE_DEAD; -+ - T(YAFFS_TRACE_SCAN_DEBUG, - (TSTR("Block scanning block %d state %d seq %d" TENDSTR), blk, - state, sequenceNumber)); -@@ -5430,70 +5491,21 @@ static int yaffs_Scan(yaffs_Device * dev - (TSTR("Block empty " TENDSTR))); - dev->nErasedBlocks++; - dev->nFreeChunks += dev->nChunksPerBlock; -- } else if (state == YAFFS_BLOCK_STATE_NEEDS_SCANNING) { -- -- /* Determine the highest sequence number */ -- if (dev->isYaffs2 && -- sequenceNumber >= YAFFS_LOWEST_SEQUENCE_NUMBER && -- sequenceNumber < YAFFS_HIGHEST_SEQUENCE_NUMBER) { -- -- blockIndex[nBlocksToScan].seq = sequenceNumber; -- blockIndex[nBlocksToScan].block = blk; -- -- nBlocksToScan++; -- -- if (sequenceNumber >= dev->sequenceNumber) { -- dev->sequenceNumber = sequenceNumber; -- } -- } else if (dev->isYaffs2) { -- /* TODO: Nasty sequence number! */ -- T(YAFFS_TRACE_SCAN, -- (TSTR -- ("Block scanning block %d has bad sequence number %d" -- TENDSTR), blk, sequenceNumber)); -- -- } - } - } - -- /* Sort the blocks -- * Dungy old bubble sort for now... -- */ -- if (dev->isYaffs2) { -- yaffs_BlockIndex temp; -- int i; -- int j; -- -- for (i = 0; i < nBlocksToScan; i++) -- for (j = i + 1; j < nBlocksToScan; j++) -- if (blockIndex[i].seq > blockIndex[j].seq) { -- temp = blockIndex[j]; -- blockIndex[j] = blockIndex[i]; -- blockIndex[i] = temp; -- } -- } -- -- /* Now scan the blocks looking at the data. */ -- if (dev->isYaffs2) { -- startIterator = 0; -- endIterator = nBlocksToScan - 1; -- T(YAFFS_TRACE_SCAN_DEBUG, -- (TSTR("%d blocks to be scanned" TENDSTR), nBlocksToScan)); -- } else { -- startIterator = dev->internalStartBlock; -- endIterator = dev->internalEndBlock; -- } -+ startIterator = dev->internalStartBlock; -+ endIterator = dev->internalEndBlock; - - /* For each block.... */ - for (blockIterator = startIterator; !alloc_failed && blockIterator <= endIterator; - blockIterator++) { - -- if (dev->isYaffs2) { -- /* get the block to scan in the correct order */ -- blk = blockIndex[blockIterator].block; -- } else { -- blk = blockIterator; -- } -+ YYIELD(); -+ -+ YYIELD(); -+ -+ blk = blockIterator; - - bi = yaffs_GetBlockInfo(dev, blk); - state = bi->blockState; -@@ -5511,7 +5523,7 @@ static int yaffs_Scan(yaffs_Device * dev - - /* Let's have a good look at this chunk... */ - -- if (!dev->isYaffs2 && tags.chunkDeleted) { -+ if (tags.eccResult == YAFFS_ECC_RESULT_UNFIXED || tags.chunkDeleted) { - /* YAFFS1 only... - * A deleted chunk - */ -@@ -5540,18 +5552,6 @@ static int yaffs_Scan(yaffs_Device * dev - dev->allocationBlockFinder = blk; - /* Set it to here to encourage the allocator to go forth from here. */ - -- /* Yaffs2 sanity check: -- * This should be the one with the highest sequence number -- */ -- if (dev->isYaffs2 -- && (dev->sequenceNumber != -- bi->sequenceNumber)) { -- T(YAFFS_TRACE_ALWAYS, -- (TSTR -- ("yaffs: Allocation block %d was not highest sequence id:" -- " block seq = %d, dev seq = %d" -- TENDSTR), blk,bi->sequenceNumber,dev->sequenceNumber)); -- } - } - - dev->nFreeChunks += (dev->nChunksPerBlock - c); -@@ -5570,11 +5570,11 @@ static int yaffs_Scan(yaffs_Device * dev - * the same chunkId). - */ - -- if(!in) -+ if (!in) - alloc_failed = 1; - -- if(in){ -- if(!yaffs_PutChunkIntoFile(in, tags.chunkId, chunk,1)) -+ if (in) { -+ if (!yaffs_PutChunkIntoFile(in, tags.chunkId, chunk, 1)) - alloc_failed = 1; - } - -@@ -5617,7 +5617,7 @@ static int yaffs_Scan(yaffs_Device * dev - * deleted, and worse still it has changed type. Delete the old object. - */ - -- yaffs_DestroyObject(in); -+ yaffs_DeleteObject(in); - - in = 0; - } -@@ -5627,14 +5627,20 @@ static int yaffs_Scan(yaffs_Device * dev - objectId, - oh->type); - -- if(!in) -+ if (!in) - alloc_failed = 1; - - if (in && oh->shadowsObject > 0) { -- yaffs_HandleShadowedObject(dev, -- oh-> -- shadowsObject, -- 0); -+ -+ struct yaffs_ShadowFixerStruct *fixer; -+ fixer = YMALLOC(sizeof(struct yaffs_ShadowFixerStruct)); -+ if (fixer) { -+ fixer->next = shadowFixerList; -+ shadowFixerList = fixer; -+ fixer->objectId = tags.objectId; -+ fixer->shadowedId = oh->shadowsObject; -+ } -+ - } - - if (in && in->valid) { -@@ -5643,12 +5649,10 @@ static int yaffs_Scan(yaffs_Device * dev - unsigned existingSerial = in->serial; - unsigned newSerial = tags.serialNumber; - -- if (dev->isYaffs2 || -- ((existingSerial + 1) & 3) == -- newSerial) { -+ if (((existingSerial + 1) & 3) == newSerial) { - /* Use new one - destroy the exisiting one */ - yaffs_DeleteChunk(dev, -- in->chunkId, -+ in->hdrChunk, - 1, __LINE__); - in->valid = 0; - } else { -@@ -5681,7 +5685,8 @@ static int yaffs_Scan(yaffs_Device * dev - in->yst_ctime = oh->yst_ctime; - in->yst_rdev = oh->yst_rdev; - #endif -- in->chunkId = chunk; -+ in->hdrChunk = chunk; -+ in->serial = tags.serialNumber; - - } else if (in && !in->valid) { - /* we need to load this info */ -@@ -5705,7 +5710,8 @@ static int yaffs_Scan(yaffs_Device * dev - in->yst_ctime = oh->yst_ctime; - in->yst_rdev = oh->yst_rdev; - #endif -- in->chunkId = chunk; -+ in->hdrChunk = chunk; -+ in->serial = tags.serialNumber; - - yaffs_SetObjectName(in, oh->name); - in->dirty = 0; -@@ -5718,25 +5724,25 @@ static int yaffs_Scan(yaffs_Device * dev - yaffs_FindOrCreateObjectByNumber - (dev, oh->parentObjectId, - YAFFS_OBJECT_TYPE_DIRECTORY); -- if (parent->variantType == -+ if (!parent) -+ alloc_failed = 1; -+ if (parent && parent->variantType == - YAFFS_OBJECT_TYPE_UNKNOWN) { - /* Set up as a directory */ - parent->variantType = -- YAFFS_OBJECT_TYPE_DIRECTORY; -- INIT_LIST_HEAD(&parent->variant. -- directoryVariant. -- children); -- } else if (parent->variantType != -- YAFFS_OBJECT_TYPE_DIRECTORY) -- { -+ YAFFS_OBJECT_TYPE_DIRECTORY; -+ YINIT_LIST_HEAD(&parent->variant. -+ directoryVariant. -+ children); -+ } else if (!parent || parent->variantType != -+ YAFFS_OBJECT_TYPE_DIRECTORY) { - /* Hoosterman, another problem.... - * We're trying to use a non-directory as a directory - */ - - T(YAFFS_TRACE_ERROR, - (TSTR -- ("yaffs tragedy: attempting to use non-directory as" -- " a directory in scan. Put in lost+found." -+ ("yaffs tragedy: attempting to use non-directory as a directory in scan. Put in lost+found." - TENDSTR))); - parent = dev->lostNFoundDir; - } -@@ -5760,15 +5766,6 @@ static int yaffs_Scan(yaffs_Device * dev - /* Todo got a problem */ - break; - case YAFFS_OBJECT_TYPE_FILE: -- if (dev->isYaffs2 -- && oh->isShrink) { -- /* Prune back the shrunken chunks */ -- yaffs_PruneResizedChunks -- (in, oh->fileSize); -- /* Mark the block as having a shrinkHeader */ -- bi->hasShrinkHeader = 1; -- } -- - if (dev->useHeaderFileSize) - - in->variant.fileVariant. -@@ -5778,11 +5775,11 @@ static int yaffs_Scan(yaffs_Device * dev - break; - case YAFFS_OBJECT_TYPE_HARDLINK: - in->variant.hardLinkVariant. -- equivalentObjectId = -- oh->equivalentObjectId; -+ equivalentObjectId = -+ oh->equivalentObjectId; - in->hardLinks.next = -- (struct list_head *) -- hardList; -+ (struct ylist_head *) -+ hardList; - hardList = in; - break; - case YAFFS_OBJECT_TYPE_DIRECTORY: -@@ -5794,15 +5791,17 @@ static int yaffs_Scan(yaffs_Device * dev - case YAFFS_OBJECT_TYPE_SYMLINK: - in->variant.symLinkVariant.alias = - yaffs_CloneString(oh->alias); -- if(!in->variant.symLinkVariant.alias) -+ if (!in->variant.symLinkVariant.alias) - alloc_failed = 1; - break; - } - -+/* - if (parent == dev->deletedDir) { - yaffs_DestroyObject(in); - bi->hasShrinkHeader = 1; - } -+*/ - } - } - } -@@ -5823,10 +5822,6 @@ static int yaffs_Scan(yaffs_Device * dev - - } - -- if (blockIndex) { -- YFREE(blockIndex); -- } -- - - /* Ok, we've done all the scanning. - * Fix up the hard link chains. -@@ -5834,32 +5829,36 @@ static int yaffs_Scan(yaffs_Device * dev - * hardlinks. - */ - -- yaffs_HardlinkFixup(dev,hardList); -+ yaffs_HardlinkFixup(dev, hardList); - -- /* Handle the unlinked files. Since they were left in an unlinked state we should -- * just delete them. -- */ -+ /* Fix up any shadowed objects */ - { -- struct list_head *i; -- struct list_head *n; -+ struct yaffs_ShadowFixerStruct *fixer; -+ yaffs_Object *obj; - -- yaffs_Object *l; -- /* Soft delete all the unlinked files */ -- list_for_each_safe(i, n, -- &dev->unlinkedDir->variant.directoryVariant. -- children) { -- if (i) { -- l = list_entry(i, yaffs_Object, siblings); -- yaffs_DestroyObject(l); -- } -+ while (shadowFixerList) { -+ fixer = shadowFixerList; -+ shadowFixerList = fixer->next; -+ /* Complete the rename transaction by deleting the shadowed object -+ * then setting the object header to unshadowed. -+ */ -+ obj = yaffs_FindObjectByNumber(dev, fixer->shadowedId); -+ if (obj) -+ yaffs_DeleteObject(obj); -+ -+ obj = yaffs_FindObjectByNumber(dev, fixer->objectId); -+ -+ if (obj) -+ yaffs_UpdateObjectHeader(obj, NULL, 1, 0, 0); -+ -+ YFREE(fixer); - } - } - - yaffs_ReleaseTempBuffer(dev, chunkData, __LINE__); - -- if(alloc_failed){ -+ if (alloc_failed) - return YAFFS_FAIL; -- } - - T(YAFFS_TRACE_SCAN, (TSTR("yaffs_Scan ends" TENDSTR))); - -@@ -5871,25 +5870,27 @@ static void yaffs_CheckObjectDetailsLoad - { - __u8 *chunkData; - yaffs_ObjectHeader *oh; -- yaffs_Device *dev = in->myDev; -+ yaffs_Device *dev; - yaffs_ExtendedTags tags; - int result; - int alloc_failed = 0; - -- if(!in) -+ if (!in) - return; - -+ dev = in->myDev; -+ - #if 0 -- T(YAFFS_TRACE_SCAN,(TSTR("details for object %d %s loaded" TENDSTR), -+ T(YAFFS_TRACE_SCAN, (TSTR("details for object %d %s loaded" TENDSTR), - in->objectId, - in->lazyLoaded ? "not yet" : "already")); - #endif - -- if(in->lazyLoaded){ -+ if (in->lazyLoaded && in->hdrChunk > 0) { - in->lazyLoaded = 0; - chunkData = yaffs_GetTempBuffer(dev, __LINE__); - -- result = yaffs_ReadChunkWithTagsFromNAND(dev,in->chunkId,chunkData,&tags); -+ result = yaffs_ReadChunkWithTagsFromNAND(dev, in->hdrChunk, chunkData, &tags); - oh = (yaffs_ObjectHeader *) chunkData; - - in->yst_mode = oh->yst_mode; -@@ -5911,18 +5912,18 @@ static void yaffs_CheckObjectDetailsLoad - #endif - yaffs_SetObjectName(in, oh->name); - -- if(in->variantType == YAFFS_OBJECT_TYPE_SYMLINK){ -- in->variant.symLinkVariant.alias = -+ if (in->variantType == YAFFS_OBJECT_TYPE_SYMLINK) { -+ in->variant.symLinkVariant.alias = - yaffs_CloneString(oh->alias); -- if(!in->variant.symLinkVariant.alias) -+ if (!in->variant.symLinkVariant.alias) - alloc_failed = 1; /* Not returned to caller */ - } - -- yaffs_ReleaseTempBuffer(dev,chunkData, __LINE__); -+ yaffs_ReleaseTempBuffer(dev, chunkData, __LINE__); - } - } - --static int yaffs_ScanBackwards(yaffs_Device * dev) -+static int yaffs_ScanBackwards(yaffs_Device *dev) - { - yaffs_ExtendedTags tags; - int blk; -@@ -5938,7 +5939,7 @@ static int yaffs_ScanBackwards(yaffs_Dev - yaffs_BlockState state; - yaffs_Object *hardList = NULL; - yaffs_BlockInfo *bi; -- int sequenceNumber; -+ __u32 sequenceNumber; - yaffs_ObjectHeader *oh; - yaffs_Object *in; - yaffs_Object *parent; -@@ -5972,12 +5973,12 @@ static int yaffs_ScanBackwards(yaffs_Dev - - blockIndex = YMALLOC(nBlocks * sizeof(yaffs_BlockIndex)); - -- if(!blockIndex) { -+ if (!blockIndex) { - blockIndex = YMALLOC_ALT(nBlocks * sizeof(yaffs_BlockIndex)); - altBlockIndex = 1; - } - -- if(!blockIndex) { -+ if (!blockIndex) { - T(YAFFS_TRACE_SCAN, - (TSTR("yaffs_Scan() could not allocate block index!" TENDSTR))); - return YAFFS_FAIL; -@@ -5999,15 +6000,17 @@ static int yaffs_ScanBackwards(yaffs_Dev - bi->blockState = state; - bi->sequenceNumber = sequenceNumber; - -- if(bi->sequenceNumber == YAFFS_SEQUENCE_CHECKPOINT_DATA) -+ if (bi->sequenceNumber == YAFFS_SEQUENCE_CHECKPOINT_DATA) - bi->blockState = state = YAFFS_BLOCK_STATE_CHECKPOINT; -+ if (bi->sequenceNumber == YAFFS_SEQUENCE_BAD_BLOCK) -+ bi->blockState = state = YAFFS_BLOCK_STATE_DEAD; - - T(YAFFS_TRACE_SCAN_DEBUG, - (TSTR("Block scanning block %d state %d seq %d" TENDSTR), blk, - state, sequenceNumber)); - - -- if(state == YAFFS_BLOCK_STATE_CHECKPOINT){ -+ if (state == YAFFS_BLOCK_STATE_CHECKPOINT) { - dev->blocksInCheckpoint++; - - } else if (state == YAFFS_BLOCK_STATE_DEAD) { -@@ -6021,8 +6024,7 @@ static int yaffs_ScanBackwards(yaffs_Dev - } else if (state == YAFFS_BLOCK_STATE_NEEDS_SCANNING) { - - /* Determine the highest sequence number */ -- if (dev->isYaffs2 && -- sequenceNumber >= YAFFS_LOWEST_SEQUENCE_NUMBER && -+ if (sequenceNumber >= YAFFS_LOWEST_SEQUENCE_NUMBER && - sequenceNumber < YAFFS_HIGHEST_SEQUENCE_NUMBER) { - - blockIndex[nBlocksToScan].seq = sequenceNumber; -@@ -6030,10 +6032,9 @@ static int yaffs_ScanBackwards(yaffs_Dev - - nBlocksToScan++; - -- if (sequenceNumber >= dev->sequenceNumber) { -+ if (sequenceNumber >= dev->sequenceNumber) - dev->sequenceNumber = sequenceNumber; -- } -- } else if (dev->isYaffs2) { -+ } else { - /* TODO: Nasty sequence number! */ - T(YAFFS_TRACE_SCAN, - (TSTR -@@ -6053,11 +6054,13 @@ static int yaffs_ScanBackwards(yaffs_Dev - - /* Sort the blocks */ - #ifndef CONFIG_YAFFS_USE_OWN_SORT -- yaffs_qsort(blockIndex, nBlocksToScan, -- sizeof(yaffs_BlockIndex), ybicmp); -+ { -+ /* Use qsort now. */ -+ yaffs_qsort(blockIndex, nBlocksToScan, sizeof(yaffs_BlockIndex), ybicmp); -+ } - #else - { -- /* Dungy old bubble sort... */ -+ /* Dungy old bubble sort... */ - - yaffs_BlockIndex temp; - int i; -@@ -6075,7 +6078,7 @@ static int yaffs_ScanBackwards(yaffs_Dev - - YYIELD(); - -- T(YAFFS_TRACE_SCAN, (TSTR("...done" TENDSTR))); -+ T(YAFFS_TRACE_SCAN, (TSTR("...done" TENDSTR))); - - /* Now scan the blocks looking at the data. */ - startIterator = 0; -@@ -6085,10 +6088,10 @@ static int yaffs_ScanBackwards(yaffs_Dev - - /* For each block.... backwards */ - for (blockIterator = endIterator; !alloc_failed && blockIterator >= startIterator; -- blockIterator--) { -- /* Cooperative multitasking! This loop can run for so -+ blockIterator--) { -+ /* Cooperative multitasking! This loop can run for so - long that watchdog timers expire. */ -- YYIELD(); -+ YYIELD(); - - /* get the block to scan in the correct order */ - blk = blockIndex[blockIterator].block; -@@ -6127,10 +6130,8 @@ static int yaffs_ScanBackwards(yaffs_Dev - * this is the one being allocated from - */ - -- if(foundChunksInBlock) -- { -+ if (foundChunksInBlock) { - /* This is a chunk that was skipped due to failing the erased check */ -- - } else if (c == 0) { - /* We're looking at the first chunk in the block so the block is unused */ - state = YAFFS_BLOCK_STATE_EMPTY; -@@ -6138,7 +6139,7 @@ static int yaffs_ScanBackwards(yaffs_Dev - } else { - if (state == YAFFS_BLOCK_STATE_NEEDS_SCANNING || - state == YAFFS_BLOCK_STATE_ALLOCATING) { -- if(dev->sequenceNumber == bi->sequenceNumber) { -+ if (dev->sequenceNumber == bi->sequenceNumber) { - /* this is the block being allocated from */ - - T(YAFFS_TRACE_SCAN, -@@ -6150,27 +6151,31 @@ static int yaffs_ScanBackwards(yaffs_Dev - dev->allocationBlock = blk; - dev->allocationPage = c; - dev->allocationBlockFinder = blk; -- } -- else { -+ } else { - /* This is a partially written block that is not - * the current allocation block. This block must have - * had a write failure, so set up for retirement. - */ - -- bi->needsRetiring = 1; -+ /* bi->needsRetiring = 1; ??? TODO */ - bi->gcPrioritise = 1; - - T(YAFFS_TRACE_ALWAYS, -- (TSTR("Partially written block %d being set for retirement" TENDSTR), -+ (TSTR("Partially written block %d detected" TENDSTR), - blk)); - } -- - } -- - } - - dev->nFreeChunks++; - -+ } else if (tags.eccResult == YAFFS_ECC_RESULT_UNFIXED) { -+ T(YAFFS_TRACE_SCAN, -+ (TSTR(" Unfixed ECC in chunk(%d:%d), chunk ignored"TENDSTR), -+ blk, c)); -+ -+ dev->nFreeChunks++; -+ - } else if (tags.chunkId > 0) { - /* chunkId > 0 so it is a data chunk... */ - unsigned int endpos; -@@ -6187,7 +6192,7 @@ static int yaffs_ScanBackwards(yaffs_Dev - tags. - objectId, - YAFFS_OBJECT_TYPE_FILE); -- if(!in){ -+ if (!in) { - /* Out of memory */ - alloc_failed = 1; - } -@@ -6197,8 +6202,8 @@ static int yaffs_ScanBackwards(yaffs_Dev - && chunkBase < - in->variant.fileVariant.shrinkSize) { - /* This has not been invalidated by a resize */ -- if(!yaffs_PutChunkIntoFile(in, tags.chunkId, -- chunk, -1)){ -+ if (!yaffs_PutChunkIntoFile(in, tags.chunkId, -+ chunk, -1)) { - alloc_failed = 1; - } - -@@ -6221,7 +6226,7 @@ static int yaffs_ScanBackwards(yaffs_Dev - scannedFileSize; - } - -- } else if(in) { -+ } else if (in) { - /* This chunk has been invalidated by a resize, so delete */ - yaffs_DeleteChunk(dev, chunk, 1, __LINE__); - -@@ -6242,6 +6247,8 @@ static int yaffs_ScanBackwards(yaffs_Dev - in = yaffs_FindOrCreateObjectByNumber - (dev, tags.objectId, - tags.extraObjectType); -+ if (!in) -+ alloc_failed = 1; - } - - if (!in || -@@ -6251,8 +6258,7 @@ static int yaffs_ScanBackwards(yaffs_Dev - tags.extraShadows || - (!in->valid && - (tags.objectId == YAFFS_OBJECTID_ROOT || -- tags.objectId == YAFFS_OBJECTID_LOSTNFOUND)) -- ) { -+ tags.objectId == YAFFS_OBJECTID_LOSTNFOUND))) { - - /* If we don't have valid info then we need to read the chunk - * TODO In future we can probably defer reading the chunk and -@@ -6266,8 +6272,17 @@ static int yaffs_ScanBackwards(yaffs_Dev - - oh = (yaffs_ObjectHeader *) chunkData; - -- if (!in) -+ if (dev->inbandTags) { -+ /* Fix up the header if they got corrupted by inband tags */ -+ oh->shadowsObject = oh->inbandShadowsObject; -+ oh->isShrink = oh->inbandIsShrink; -+ } -+ -+ if (!in) { - in = yaffs_FindOrCreateObjectByNumber(dev, tags.objectId, oh->type); -+ if (!in) -+ alloc_failed = 1; -+ } - - } - -@@ -6275,10 +6290,9 @@ static int yaffs_ScanBackwards(yaffs_Dev - /* TODO Hoosterman we have a problem! */ - T(YAFFS_TRACE_ERROR, - (TSTR -- ("yaffs tragedy: Could not make object for object %d " -- "at chunk %d during scan" -+ ("yaffs tragedy: Could not make object for object %d at chunk %d during scan" - TENDSTR), tags.objectId, chunk)); -- -+ continue; - } - - if (in->valid) { -@@ -6289,10 +6303,9 @@ static int yaffs_ScanBackwards(yaffs_Dev - - if ((in->variantType == YAFFS_OBJECT_TYPE_FILE) && - ((oh && -- oh-> type == YAFFS_OBJECT_TYPE_FILE)|| -+ oh->type == YAFFS_OBJECT_TYPE_FILE) || - (tags.extraHeaderInfoAvailable && -- tags.extraObjectType == YAFFS_OBJECT_TYPE_FILE)) -- ) { -+ tags.extraObjectType == YAFFS_OBJECT_TYPE_FILE))) { - __u32 thisSize = - (oh) ? oh->fileSize : tags. - extraFileLength; -@@ -6300,7 +6313,9 @@ static int yaffs_ScanBackwards(yaffs_Dev - (oh) ? oh-> - parentObjectId : tags. - extraParentObjectId; -- unsigned isShrink = -+ -+ -+ isShrink = - (oh) ? oh->isShrink : tags. - extraIsShrinkHeader; - -@@ -6323,9 +6338,8 @@ static int yaffs_ScanBackwards(yaffs_Dev - thisSize; - } - -- if (isShrink) { -+ if (isShrink) - bi->hasShrinkHeader = 1; -- } - - } - /* Use existing - destroy this one. */ -@@ -6333,6 +6347,17 @@ static int yaffs_ScanBackwards(yaffs_Dev - - } - -+ if (!in->valid && in->variantType != -+ (oh ? oh->type : tags.extraObjectType)) -+ T(YAFFS_TRACE_ERROR, ( -+ TSTR("yaffs tragedy: Bad object type, " -+ TCONT("%d != %d, for object %d at chunk ") -+ TCONT("%d during scan") -+ TENDSTR), oh ? -+ oh->type : tags.extraObjectType, -+ in->variantType, tags.objectId, -+ chunk)); -+ - if (!in->valid && - (tags.objectId == YAFFS_OBJECTID_ROOT || - tags.objectId == -@@ -6340,7 +6365,7 @@ static int yaffs_ScanBackwards(yaffs_Dev - /* We only load some info, don't fiddle with directory structure */ - in->valid = 1; - -- if(oh) { -+ if (oh) { - in->variantType = oh->type; - - in->yst_mode = oh->yst_mode; -@@ -6365,15 +6390,15 @@ static int yaffs_ScanBackwards(yaffs_Dev - in->lazyLoaded = 1; - } - -- in->chunkId = chunk; -+ in->hdrChunk = chunk; - - } else if (!in->valid) { - /* we need to load this info */ - - in->valid = 1; -- in->chunkId = chunk; -+ in->hdrChunk = chunk; - -- if(oh) { -+ if (oh) { - in->variantType = oh->type; - - in->yst_mode = oh->yst_mode; -@@ -6403,20 +6428,19 @@ static int yaffs_ScanBackwards(yaffs_Dev - yaffs_SetObjectName(in, oh->name); - parent = - yaffs_FindOrCreateObjectByNumber -- (dev, oh->parentObjectId, -- YAFFS_OBJECT_TYPE_DIRECTORY); -+ (dev, oh->parentObjectId, -+ YAFFS_OBJECT_TYPE_DIRECTORY); - - fileSize = oh->fileSize; -- isShrink = oh->isShrink; -+ isShrink = oh->isShrink; - equivalentObjectId = oh->equivalentObjectId; - -- } -- else { -+ } else { - in->variantType = tags.extraObjectType; - parent = - yaffs_FindOrCreateObjectByNumber -- (dev, tags.extraParentObjectId, -- YAFFS_OBJECT_TYPE_DIRECTORY); -+ (dev, tags.extraParentObjectId, -+ YAFFS_OBJECT_TYPE_DIRECTORY); - fileSize = tags.extraFileLength; - isShrink = tags.extraIsShrinkHeader; - equivalentObjectId = tags.extraEquivalentObjectId; -@@ -6425,29 +6449,30 @@ static int yaffs_ScanBackwards(yaffs_Dev - } - in->dirty = 0; - -+ if (!parent) -+ alloc_failed = 1; -+ - /* directory stuff... - * hook up to parent - */ - -- if (parent->variantType == -+ if (parent && parent->variantType == - YAFFS_OBJECT_TYPE_UNKNOWN) { - /* Set up as a directory */ - parent->variantType = -- YAFFS_OBJECT_TYPE_DIRECTORY; -- INIT_LIST_HEAD(&parent->variant. -- directoryVariant. -- children); -- } else if (parent->variantType != -- YAFFS_OBJECT_TYPE_DIRECTORY) -- { -+ YAFFS_OBJECT_TYPE_DIRECTORY; -+ YINIT_LIST_HEAD(&parent->variant. -+ directoryVariant. -+ children); -+ } else if (!parent || parent->variantType != -+ YAFFS_OBJECT_TYPE_DIRECTORY) { - /* Hoosterman, another problem.... - * We're trying to use a non-directory as a directory - */ - - T(YAFFS_TRACE_ERROR, - (TSTR -- ("yaffs tragedy: attempting to use non-directory as" -- " a directory in scan. Put in lost+found." -+ ("yaffs tragedy: attempting to use non-directory as a directory in scan. Put in lost+found." - TENDSTR))); - parent = dev->lostNFoundDir; - } -@@ -6494,12 +6519,12 @@ static int yaffs_ScanBackwards(yaffs_Dev - - break; - case YAFFS_OBJECT_TYPE_HARDLINK: -- if(!itsUnlinked) { -- in->variant.hardLinkVariant.equivalentObjectId = -- equivalentObjectId; -- in->hardLinks.next = -- (struct list_head *) hardList; -- hardList = in; -+ if (!itsUnlinked) { -+ in->variant.hardLinkVariant.equivalentObjectId = -+ equivalentObjectId; -+ in->hardLinks.next = -+ (struct ylist_head *) hardList; -+ hardList = in; - } - break; - case YAFFS_OBJECT_TYPE_DIRECTORY: -@@ -6509,12 +6534,11 @@ static int yaffs_ScanBackwards(yaffs_Dev - /* Do nothing */ - break; - case YAFFS_OBJECT_TYPE_SYMLINK: -- if(oh){ -- in->variant.symLinkVariant.alias = -- yaffs_CloneString(oh-> -- alias); -- if(!in->variant.symLinkVariant.alias) -- alloc_failed = 1; -+ if (oh) { -+ in->variant.symLinkVariant.alias = -+ yaffs_CloneString(oh->alias); -+ if (!in->variant.symLinkVariant.alias) -+ alloc_failed = 1; - } - break; - } -@@ -6551,75 +6575,129 @@ static int yaffs_ScanBackwards(yaffs_Dev - * We should now have scanned all the objects, now it's time to add these - * hardlinks. - */ -- yaffs_HardlinkFixup(dev,hardList); -+ yaffs_HardlinkFixup(dev, hardList); - - -- /* -- * Sort out state of unlinked and deleted objects. -- */ -- { -- struct list_head *i; -- struct list_head *n; -+ yaffs_ReleaseTempBuffer(dev, chunkData, __LINE__); - -- yaffs_Object *l; -+ if (alloc_failed) -+ return YAFFS_FAIL; - -- /* Soft delete all the unlinked files */ -- list_for_each_safe(i, n, -- &dev->unlinkedDir->variant.directoryVariant. -- children) { -- if (i) { -- l = list_entry(i, yaffs_Object, siblings); -- yaffs_DestroyObject(l); -- } -- } -+ T(YAFFS_TRACE_SCAN, (TSTR("yaffs_ScanBackwards ends" TENDSTR))); - -- /* Soft delete all the deletedDir files */ -- list_for_each_safe(i, n, -- &dev->deletedDir->variant.directoryVariant. -- children) { -- if (i) { -- l = list_entry(i, yaffs_Object, siblings); -- yaffs_DestroyObject(l); -+ return YAFFS_OK; -+} - -- } -+/*------------------------------ Directory Functions ----------------------------- */ -+ -+static void yaffs_VerifyObjectInDirectory(yaffs_Object *obj) -+{ -+ struct ylist_head *lh; -+ yaffs_Object *listObj; -+ -+ int count = 0; -+ -+ if (!obj) { -+ T(YAFFS_TRACE_ALWAYS, (TSTR("No object to verify" TENDSTR))); -+ YBUG(); -+ return; -+ } -+ -+ if (yaffs_SkipVerification(obj->myDev)) -+ return; -+ -+ if (!obj->parent) { -+ T(YAFFS_TRACE_ALWAYS, (TSTR("Object does not have parent" TENDSTR))); -+ YBUG(); -+ return; -+ } -+ -+ if (obj->parent->variantType != YAFFS_OBJECT_TYPE_DIRECTORY) { -+ T(YAFFS_TRACE_ALWAYS, (TSTR("Parent is not directory" TENDSTR))); -+ YBUG(); -+ } -+ -+ /* Iterate through the objects in each hash entry */ -+ -+ ylist_for_each(lh, &obj->parent->variant.directoryVariant.children) { -+ if (lh) { -+ listObj = ylist_entry(lh, yaffs_Object, siblings); -+ yaffs_VerifyObject(listObj); -+ if (obj == listObj) -+ count++; - } -+ } -+ -+ if (count != 1) { -+ T(YAFFS_TRACE_ALWAYS, (TSTR("Object in directory %d times" TENDSTR), count)); -+ YBUG(); - } -+} - -- yaffs_ReleaseTempBuffer(dev, chunkData, __LINE__); -+static void yaffs_VerifyDirectory(yaffs_Object *directory) -+{ -+ struct ylist_head *lh; -+ yaffs_Object *listObj; - -- if(alloc_failed){ -- return YAFFS_FAIL; -+ if (!directory) { -+ YBUG(); -+ return; - } - -- T(YAFFS_TRACE_SCAN, (TSTR("yaffs_ScanBackwards ends" TENDSTR))); -+ if (yaffs_SkipFullVerification(directory->myDev)) -+ return; - -- return YAFFS_OK; -+ if (directory->variantType != YAFFS_OBJECT_TYPE_DIRECTORY) { -+ T(YAFFS_TRACE_ALWAYS, (TSTR("Directory has wrong type: %d" TENDSTR), directory->variantType)); -+ YBUG(); -+ } -+ -+ /* Iterate through the objects in each hash entry */ -+ -+ ylist_for_each(lh, &directory->variant.directoryVariant.children) { -+ if (lh) { -+ listObj = ylist_entry(lh, yaffs_Object, siblings); -+ if (listObj->parent != directory) { -+ T(YAFFS_TRACE_ALWAYS, (TSTR("Object in directory list has wrong parent %p" TENDSTR), listObj->parent)); -+ YBUG(); -+ } -+ yaffs_VerifyObjectInDirectory(listObj); -+ } -+ } - } - --/*------------------------------ Directory Functions ----------------------------- */ - --static void yaffs_RemoveObjectFromDirectory(yaffs_Object * obj) -+static void yaffs_RemoveObjectFromDirectory(yaffs_Object *obj) - { - yaffs_Device *dev = obj->myDev; -+ yaffs_Object *parent; -+ -+ yaffs_VerifyObjectInDirectory(obj); -+ parent = obj->parent; -+ -+ yaffs_VerifyDirectory(parent); - -- if(dev && dev->removeObjectCallback) -+ if (dev && dev->removeObjectCallback) - dev->removeObjectCallback(obj); - -- list_del_init(&obj->siblings); -+ -+ ylist_del_init(&obj->siblings); - obj->parent = NULL; -+ -+ yaffs_VerifyDirectory(parent); - } - - --static void yaffs_AddObjectToDirectory(yaffs_Object * directory, -- yaffs_Object * obj) -+static void yaffs_AddObjectToDirectory(yaffs_Object *directory, -+ yaffs_Object *obj) - { -- - if (!directory) { - T(YAFFS_TRACE_ALWAYS, - (TSTR - ("tragedy: Trying to add an object to a null pointer directory" - TENDSTR))); - YBUG(); -+ return; - } - if (directory->variantType != YAFFS_OBJECT_TYPE_DIRECTORY) { - T(YAFFS_TRACE_ALWAYS, -@@ -6631,37 +6709,42 @@ static void yaffs_AddObjectToDirectory(y - - if (obj->siblings.prev == NULL) { - /* Not initialised */ -- INIT_LIST_HEAD(&obj->siblings); -- -- } else if (!list_empty(&obj->siblings)) { -- /* If it is holed up somewhere else, un hook it */ -- yaffs_RemoveObjectFromDirectory(obj); -+ YBUG(); - } -+ -+ -+ yaffs_VerifyDirectory(directory); -+ -+ yaffs_RemoveObjectFromDirectory(obj); -+ -+ - /* Now add it */ -- list_add(&obj->siblings, &directory->variant.directoryVariant.children); -+ ylist_add(&obj->siblings, &directory->variant.directoryVariant.children); - obj->parent = directory; - - if (directory == obj->myDev->unlinkedDir -- || directory == obj->myDev->deletedDir) { -+ || directory == obj->myDev->deletedDir) { - obj->unlinked = 1; - obj->myDev->nUnlinkedFiles++; - obj->renameAllowed = 0; - } -+ -+ yaffs_VerifyDirectory(directory); -+ yaffs_VerifyObjectInDirectory(obj); - } - --yaffs_Object *yaffs_FindObjectByName(yaffs_Object * directory, -- const YCHAR * name) -+yaffs_Object *yaffs_FindObjectByName(yaffs_Object *directory, -+ const YCHAR *name) - { - int sum; - -- struct list_head *i; -+ struct ylist_head *i; - YCHAR buffer[YAFFS_MAX_NAME_LENGTH + 1]; - - yaffs_Object *l; - -- if (!name) { -+ if (!name) - return NULL; -- } - - if (!directory) { - T(YAFFS_TRACE_ALWAYS, -@@ -6669,6 +6752,7 @@ yaffs_Object *yaffs_FindObjectByName(yaf - ("tragedy: yaffs_FindObjectByName: null pointer directory" - TENDSTR))); - YBUG(); -+ return NULL; - } - if (directory->variantType != YAFFS_OBJECT_TYPE_DIRECTORY) { - T(YAFFS_TRACE_ALWAYS, -@@ -6679,28 +6763,27 @@ yaffs_Object *yaffs_FindObjectByName(yaf - - sum = yaffs_CalcNameSum(name); - -- list_for_each(i, &directory->variant.directoryVariant.children) { -+ ylist_for_each(i, &directory->variant.directoryVariant.children) { - if (i) { -- l = list_entry(i, yaffs_Object, siblings); -+ l = ylist_entry(i, yaffs_Object, siblings); -+ -+ if (l->parent != directory) -+ YBUG(); - - yaffs_CheckObjectDetailsLoaded(l); - - /* Special case for lost-n-found */ - if (l->objectId == YAFFS_OBJECTID_LOSTNFOUND) { -- if (yaffs_strcmp(name, YAFFS_LOSTNFOUND_NAME) == 0) { -+ if (yaffs_strcmp(name, YAFFS_LOSTNFOUND_NAME) == 0) - return l; -- } -- } else if (yaffs_SumCompare(l->sum, sum) || l->chunkId <= 0) -- { -- /* LostnFound cunk called Objxxx -+ } else if (yaffs_SumCompare(l->sum, sum) || l->hdrChunk <= 0) { -+ /* LostnFound chunk called Objxxx - * Do a real check - */ - yaffs_GetObjectName(l, buffer, - YAFFS_MAX_NAME_LENGTH); -- if (yaffs_strncmp(name, buffer,YAFFS_MAX_NAME_LENGTH) == 0) { -+ if (yaffs_strncmp(name, buffer, YAFFS_MAX_NAME_LENGTH) == 0) - return l; -- } -- - } - } - } -@@ -6710,10 +6793,10 @@ yaffs_Object *yaffs_FindObjectByName(yaf - - - #if 0 --int yaffs_ApplyToDirectoryChildren(yaffs_Object * theDir, -- int (*fn) (yaffs_Object *)) -+int yaffs_ApplyToDirectoryChildren(yaffs_Object *theDir, -+ int (*fn) (yaffs_Object *)) - { -- struct list_head *i; -+ struct ylist_head *i; - yaffs_Object *l; - - if (!theDir) { -@@ -6722,20 +6805,21 @@ int yaffs_ApplyToDirectoryChildren(yaffs - ("tragedy: yaffs_FindObjectByName: null pointer directory" - TENDSTR))); - YBUG(); -+ return YAFFS_FAIL; - } - if (theDir->variantType != YAFFS_OBJECT_TYPE_DIRECTORY) { - T(YAFFS_TRACE_ALWAYS, - (TSTR - ("tragedy: yaffs_FindObjectByName: non-directory" TENDSTR))); - YBUG(); -+ return YAFFS_FAIL; - } - -- list_for_each(i, &theDir->variant.directoryVariant.children) { -+ ylist_for_each(i, &theDir->variant.directoryVariant.children) { - if (i) { -- l = list_entry(i, yaffs_Object, siblings); -- if (l && !fn(l)) { -+ l = ylist_entry(i, yaffs_Object, siblings); -+ if (l && !fn(l)) - return YAFFS_FAIL; -- } - } - } - -@@ -6748,7 +6832,7 @@ int yaffs_ApplyToDirectoryChildren(yaffs - * actual object. - */ - --yaffs_Object *yaffs_GetEquivalentObject(yaffs_Object * obj) -+yaffs_Object *yaffs_GetEquivalentObject(yaffs_Object *obj) - { - if (obj && obj->variantType == YAFFS_OBJECT_TYPE_HARDLINK) { - /* We want the object id of the equivalent object, not this one */ -@@ -6756,10 +6840,9 @@ yaffs_Object *yaffs_GetEquivalentObject( - yaffs_CheckObjectDetailsLoaded(obj); - } - return obj; -- - } - --int yaffs_GetObjectName(yaffs_Object * obj, YCHAR * name, int buffSize) -+int yaffs_GetObjectName(yaffs_Object *obj, YCHAR *name, int buffSize) - { - memset(name, 0, buffSize * sizeof(YCHAR)); - -@@ -6767,18 +6850,26 @@ int yaffs_GetObjectName(yaffs_Object * o - - if (obj->objectId == YAFFS_OBJECTID_LOSTNFOUND) { - yaffs_strncpy(name, YAFFS_LOSTNFOUND_NAME, buffSize - 1); -- } else if (obj->chunkId <= 0) { -+ } else if (obj->hdrChunk <= 0) { - YCHAR locName[20]; -+ YCHAR numString[20]; -+ YCHAR *x = &numString[19]; -+ unsigned v = obj->objectId; -+ numString[19] = 0; -+ while (v > 0) { -+ x--; -+ *x = '0' + (v % 10); -+ v /= 10; -+ } - /* make up a name */ -- yaffs_sprintf(locName, _Y("%s%d"), YAFFS_LOSTNFOUND_PREFIX, -- obj->objectId); -+ yaffs_strcpy(locName, YAFFS_LOSTNFOUND_PREFIX); -+ yaffs_strcat(locName, x); - yaffs_strncpy(name, locName, buffSize - 1); - - } - #ifdef CONFIG_YAFFS_SHORT_NAMES_IN_RAM -- else if (obj->shortName[0]) { -+ else if (obj->shortName[0]) - yaffs_strcpy(name, obj->shortName); -- } - #endif - else { - int result; -@@ -6788,9 +6879,9 @@ int yaffs_GetObjectName(yaffs_Object * o - - memset(buffer, 0, obj->myDev->nDataBytesPerChunk); - -- if (obj->chunkId >= 0) { -+ if (obj->hdrChunk > 0) { - result = yaffs_ReadChunkWithTagsFromNAND(obj->myDev, -- obj->chunkId, buffer, -+ obj->hdrChunk, buffer, - NULL); - } - yaffs_strncpy(name, oh->name, buffSize - 1); -@@ -6801,46 +6892,43 @@ int yaffs_GetObjectName(yaffs_Object * o - return yaffs_strlen(name); - } - --int yaffs_GetObjectFileLength(yaffs_Object * obj) -+int yaffs_GetObjectFileLength(yaffs_Object *obj) - { -- - /* Dereference any hard linking */ - obj = yaffs_GetEquivalentObject(obj); - -- if (obj->variantType == YAFFS_OBJECT_TYPE_FILE) { -+ if (obj->variantType == YAFFS_OBJECT_TYPE_FILE) - return obj->variant.fileVariant.fileSize; -- } -- if (obj->variantType == YAFFS_OBJECT_TYPE_SYMLINK) { -+ if (obj->variantType == YAFFS_OBJECT_TYPE_SYMLINK) - return yaffs_strlen(obj->variant.symLinkVariant.alias); -- } else { -+ else { - /* Only a directory should drop through to here */ - return obj->myDev->nDataBytesPerChunk; - } - } - --int yaffs_GetObjectLinkCount(yaffs_Object * obj) -+int yaffs_GetObjectLinkCount(yaffs_Object *obj) - { - int count = 0; -- struct list_head *i; -+ struct ylist_head *i; - -- if (!obj->unlinked) { -- count++; /* the object itself */ -- } -- list_for_each(i, &obj->hardLinks) { -- count++; /* add the hard links; */ -- } -- return count; -+ if (!obj->unlinked) -+ count++; /* the object itself */ -+ -+ ylist_for_each(i, &obj->hardLinks) -+ count++; /* add the hard links; */ - -+ return count; - } - --int yaffs_GetObjectInode(yaffs_Object * obj) -+int yaffs_GetObjectInode(yaffs_Object *obj) - { - obj = yaffs_GetEquivalentObject(obj); - - return obj->objectId; - } - --unsigned yaffs_GetObjectType(yaffs_Object * obj) -+unsigned yaffs_GetObjectType(yaffs_Object *obj) - { - obj = yaffs_GetEquivalentObject(obj); - -@@ -6872,19 +6960,18 @@ unsigned yaffs_GetObjectType(yaffs_Objec - } - } - --YCHAR *yaffs_GetSymlinkAlias(yaffs_Object * obj) -+YCHAR *yaffs_GetSymlinkAlias(yaffs_Object *obj) - { - obj = yaffs_GetEquivalentObject(obj); -- if (obj->variantType == YAFFS_OBJECT_TYPE_SYMLINK) { -+ if (obj->variantType == YAFFS_OBJECT_TYPE_SYMLINK) - return yaffs_CloneString(obj->variant.symLinkVariant.alias); -- } else { -+ else - return yaffs_CloneString(_Y("")); -- } - } - - #ifndef CONFIG_YAFFS_WINCE - --int yaffs_SetAttributes(yaffs_Object * obj, struct iattr *attr) -+int yaffs_SetAttributes(yaffs_Object *obj, struct iattr *attr) - { - unsigned int valid = attr->ia_valid; - -@@ -6910,7 +6997,7 @@ int yaffs_SetAttributes(yaffs_Object * o - return YAFFS_OK; - - } --int yaffs_GetAttributes(yaffs_Object * obj, struct iattr *attr) -+int yaffs_GetAttributes(yaffs_Object *obj, struct iattr *attr) - { - unsigned int valid = 0; - -@@ -6934,13 +7021,12 @@ int yaffs_GetAttributes(yaffs_Object * o - attr->ia_valid = valid; - - return YAFFS_OK; -- - } - - #endif - - #if 0 --int yaffs_DumpObject(yaffs_Object * obj) -+int yaffs_DumpObject(yaffs_Object *obj) - { - YCHAR name[257]; - -@@ -6951,7 +7037,7 @@ int yaffs_DumpObject(yaffs_Object * obj) - ("Object %d, inode %d \"%s\"\n dirty %d valid %d serial %d sum %d" - " chunk %d type %d size %d\n" - TENDSTR), obj->objectId, yaffs_GetObjectInode(obj), name, -- obj->dirty, obj->valid, obj->serial, obj->sum, obj->chunkId, -+ obj->dirty, obj->valid, obj->serial, obj->sum, obj->hdrChunk, - yaffs_GetObjectType(obj), yaffs_GetObjectFileLength(obj))); - - return YAFFS_OK; -@@ -6960,7 +7046,7 @@ int yaffs_DumpObject(yaffs_Object * obj) - - /*---------------------------- Initialisation code -------------------------------------- */ - --static int yaffs_CheckDevFunctions(const yaffs_Device * dev) -+static int yaffs_CheckDevFunctions(const yaffs_Device *dev) - { - - /* Common functions, gotta have */ -@@ -7011,7 +7097,7 @@ static int yaffs_CreateInitialDirectorie - yaffs_CreateFakeDirectory(dev, YAFFS_OBJECTID_LOSTNFOUND, - YAFFS_LOSTNFOUND_MODE | S_IFDIR); - -- if(dev->lostNFoundDir && dev->rootDir && dev->unlinkedDir && dev->deletedDir){ -+ if (dev->lostNFoundDir && dev->rootDir && dev->unlinkedDir && dev->deletedDir) { - yaffs_AddObjectToDirectory(dev->rootDir, dev->lostNFoundDir); - return YAFFS_OK; - } -@@ -7019,7 +7105,7 @@ static int yaffs_CreateInitialDirectorie - return YAFFS_FAIL; - } - --int yaffs_GutsInitialise(yaffs_Device * dev) -+int yaffs_GutsInitialise(yaffs_Device *dev) - { - int init_failed = 0; - unsigned x; -@@ -7040,6 +7126,8 @@ int yaffs_GutsInitialise(yaffs_Device * - dev->chunkOffset = 0; - dev->nFreeChunks = 0; - -+ dev->gcBlock = -1; -+ - if (dev->startBlock == 0) { - dev->internalStartBlock = dev->startBlock + 1; - dev->internalEndBlock = dev->endBlock + 1; -@@ -7049,18 +7137,18 @@ int yaffs_GutsInitialise(yaffs_Device * - - /* Check geometry parameters. */ - -- if ((dev->isYaffs2 && dev->nDataBytesPerChunk < 1024) || -- (!dev->isYaffs2 && dev->nDataBytesPerChunk != 512) || -+ if ((!dev->inbandTags && dev->isYaffs2 && dev->totalBytesPerChunk < 1024) || -+ (!dev->isYaffs2 && dev->totalBytesPerChunk < 512) || -+ (dev->inbandTags && !dev->isYaffs2) || - dev->nChunksPerBlock < 2 || - dev->nReservedBlocks < 2 || - dev->internalStartBlock <= 0 || - dev->internalEndBlock <= 0 || -- dev->internalEndBlock <= (dev->internalStartBlock + dev->nReservedBlocks + 2) // otherwise it is too small -- ) { -+ dev->internalEndBlock <= (dev->internalStartBlock + dev->nReservedBlocks + 2)) { /* otherwise it is too small */ - T(YAFFS_TRACE_ALWAYS, - (TSTR -- ("yaffs: NAND geometry problems: chunk size %d, type is yaffs%s " -- TENDSTR), dev->nDataBytesPerChunk, dev->isYaffs2 ? "2" : "")); -+ ("yaffs: NAND geometry problems: chunk size %d, type is yaffs%s, inbandTags %d " -+ TENDSTR), dev->totalBytesPerChunk, dev->isYaffs2 ? "2" : "", dev->inbandTags)); - return YAFFS_FAIL; - } - -@@ -7070,6 +7158,12 @@ int yaffs_GutsInitialise(yaffs_Device * - return YAFFS_FAIL; - } - -+ /* Sort out space for inband tags, if required */ -+ if (dev->inbandTags) -+ dev->nDataBytesPerChunk = dev->totalBytesPerChunk - sizeof(yaffs_PackedTags2TagsPart); -+ else -+ dev->nDataBytesPerChunk = dev->totalBytesPerChunk; -+ - /* Got the right mix of functions? */ - if (!yaffs_CheckDevFunctions(dev)) { - /* Function missing */ -@@ -7097,31 +7191,18 @@ int yaffs_GutsInitialise(yaffs_Device * - - dev->isMounted = 1; - -- -- - /* OK now calculate a few things for the device */ - - /* - * Calculate all the chunk size manipulation numbers: - */ -- /* Start off assuming it is a power of 2 */ -- dev->chunkShift = ShiftDiv(dev->nDataBytesPerChunk); -- dev->chunkMask = (1<chunkShift) - 1; -- -- if(dev->nDataBytesPerChunk == (dev->chunkMask + 1)){ -- /* Yes it is a power of 2, disable crumbs */ -- dev->crumbMask = 0; -- dev->crumbShift = 0; -- dev->crumbsPerChunk = 0; -- } else { -- /* Not a power of 2, use crumbs instead */ -- dev->crumbShift = ShiftDiv(sizeof(yaffs_PackedTags2TagsPart)); -- dev->crumbMask = (1<crumbShift)-1; -- dev->crumbsPerChunk = dev->nDataBytesPerChunk/(1 << dev->crumbShift); -- dev->chunkShift = 0; -- dev->chunkMask = 0; -- } -- -+ x = dev->nDataBytesPerChunk; -+ /* We always use dev->chunkShift and dev->chunkDiv */ -+ dev->chunkShift = Shifts(x); -+ x >>= dev->chunkShift; -+ dev->chunkDiv = x; -+ /* We only use chunk mask if chunkDiv is 1 */ -+ dev->chunkMask = (1<chunkShift) - 1; - - /* - * Calculate chunkGroupBits. -@@ -7133,16 +7214,15 @@ int yaffs_GutsInitialise(yaffs_Device * - bits = ShiftsGE(x); - - /* Set up tnode width if wide tnodes are enabled. */ -- if(!dev->wideTnodesDisabled){ -+ if (!dev->wideTnodesDisabled) { - /* bits must be even so that we end up with 32-bit words */ -- if(bits & 1) -+ if (bits & 1) - bits++; -- if(bits < 16) -+ if (bits < 16) - dev->tnodeWidth = 16; - else - dev->tnodeWidth = bits; -- } -- else -+ } else - dev->tnodeWidth = 16; - - dev->tnodeMask = (1<tnodeWidth)-1; -@@ -7193,7 +7273,7 @@ int yaffs_GutsInitialise(yaffs_Device * - dev->hasPendingPrioritisedGCs = 1; /* Assume the worst for now, will get fixed on first GC */ - - /* Initialise temporary buffers and caches. */ -- if(!yaffs_InitialiseTempBuffers(dev)) -+ if (!yaffs_InitialiseTempBuffers(dev)) - init_failed = 1; - - dev->srCache = NULL; -@@ -7203,25 +7283,26 @@ int yaffs_GutsInitialise(yaffs_Device * - if (!init_failed && - dev->nShortOpCaches > 0) { - int i; -- __u8 *buf; -+ void *buf; - int srCacheBytes = dev->nShortOpCaches * sizeof(yaffs_ChunkCache); - -- if (dev->nShortOpCaches > YAFFS_MAX_SHORT_OP_CACHES) { -+ if (dev->nShortOpCaches > YAFFS_MAX_SHORT_OP_CACHES) - dev->nShortOpCaches = YAFFS_MAX_SHORT_OP_CACHES; -- } - -- buf = dev->srCache = YMALLOC(srCacheBytes); -+ dev->srCache = YMALLOC(srCacheBytes); - -- if(dev->srCache) -- memset(dev->srCache,0,srCacheBytes); -+ buf = (__u8 *) dev->srCache; -+ -+ if (dev->srCache) -+ memset(dev->srCache, 0, srCacheBytes); - - for (i = 0; i < dev->nShortOpCaches && buf; i++) { - dev->srCache[i].object = NULL; - dev->srCache[i].lastUse = 0; - dev->srCache[i].dirty = 0; -- dev->srCache[i].data = buf = YMALLOC_DMA(dev->nDataBytesPerChunk); -+ dev->srCache[i].data = buf = YMALLOC_DMA(dev->totalBytesPerChunk); - } -- if(!buf) -+ if (!buf) - init_failed = 1; - - dev->srLastUse = 0; -@@ -7229,29 +7310,30 @@ int yaffs_GutsInitialise(yaffs_Device * - - dev->cacheHits = 0; - -- if(!init_failed){ -+ if (!init_failed) { - dev->gcCleanupList = YMALLOC(dev->nChunksPerBlock * sizeof(__u32)); -- if(!dev->gcCleanupList) -+ if (!dev->gcCleanupList) - init_failed = 1; - } - -- if (dev->isYaffs2) { -+ if (dev->isYaffs2) - dev->useHeaderFileSize = 1; -- } -- if(!init_failed && !yaffs_InitialiseBlocks(dev)) -+ -+ if (!init_failed && !yaffs_InitialiseBlocks(dev)) - init_failed = 1; - - yaffs_InitialiseTnodes(dev); - yaffs_InitialiseObjects(dev); - -- if(!init_failed && !yaffs_CreateInitialDirectories(dev)) -+ if (!init_failed && !yaffs_CreateInitialDirectories(dev)) - init_failed = 1; - - -- if(!init_failed){ -+ if (!init_failed) { - /* Now scan the flash. */ - if (dev->isYaffs2) { -- if(yaffs_CheckpointRestore(dev)) { -+ if (yaffs_CheckpointRestore(dev)) { -+ yaffs_CheckObjectDetailsLoaded(dev->rootDir); - T(YAFFS_TRACE_ALWAYS, - (TSTR("yaffs: restored from checkpoint" TENDSTR))); - } else { -@@ -7273,24 +7355,25 @@ int yaffs_GutsInitialise(yaffs_Device * - dev->nBackgroundDeletions = 0; - dev->oldestDirtySequence = 0; - -- if(!init_failed && !yaffs_InitialiseBlocks(dev)) -+ if (!init_failed && !yaffs_InitialiseBlocks(dev)) - init_failed = 1; - - yaffs_InitialiseTnodes(dev); - yaffs_InitialiseObjects(dev); - -- if(!init_failed && !yaffs_CreateInitialDirectories(dev)) -+ if (!init_failed && !yaffs_CreateInitialDirectories(dev)) - init_failed = 1; - -- if(!init_failed && !yaffs_ScanBackwards(dev)) -+ if (!init_failed && !yaffs_ScanBackwards(dev)) - init_failed = 1; - } -- }else -- if(!yaffs_Scan(dev)) -+ } else if (!yaffs_Scan(dev)) - init_failed = 1; -+ -+ yaffs_StripDeletedObjects(dev); - } - -- if(init_failed){ -+ if (init_failed) { - /* Clean up the mess */ - T(YAFFS_TRACE_TRACING, - (TSTR("yaffs: yaffs_GutsInitialise() aborted.\n" TENDSTR))); -@@ -7318,7 +7401,7 @@ int yaffs_GutsInitialise(yaffs_Device * - - } - --void yaffs_Deinitialise(yaffs_Device * dev) -+void yaffs_Deinitialise(yaffs_Device *dev) - { - if (dev->isMounted) { - int i; -@@ -7330,7 +7413,7 @@ void yaffs_Deinitialise(yaffs_Device * d - dev->srCache) { - - for (i = 0; i < dev->nShortOpCaches; i++) { -- if(dev->srCache[i].data) -+ if (dev->srCache[i].data) - YFREE(dev->srCache[i].data); - dev->srCache[i].data = NULL; - } -@@ -7341,16 +7424,17 @@ void yaffs_Deinitialise(yaffs_Device * d - - YFREE(dev->gcCleanupList); - -- for (i = 0; i < YAFFS_N_TEMP_BUFFERS; i++) { -+ for (i = 0; i < YAFFS_N_TEMP_BUFFERS; i++) - YFREE(dev->tempBuffer[i].buffer); -- } - - dev->isMounted = 0; -- } - -+ if (dev->deinitialiseNAND) -+ dev->deinitialiseNAND(dev); -+ } - } - --static int yaffs_CountFreeChunks(yaffs_Device * dev) -+static int yaffs_CountFreeChunks(yaffs_Device *dev) - { - int nFree; - int b; -@@ -7358,7 +7442,7 @@ static int yaffs_CountFreeChunks(yaffs_D - yaffs_BlockInfo *blk; - - for (nFree = 0, b = dev->internalStartBlock; b <= dev->internalEndBlock; -- b++) { -+ b++) { - blk = yaffs_GetBlockInfo(dev, b); - - switch (blk->blockState) { -@@ -7373,19 +7457,19 @@ static int yaffs_CountFreeChunks(yaffs_D - default: - break; - } -- - } - - return nFree; - } - --int yaffs_GetNumberOfFreeChunks(yaffs_Device * dev) -+int yaffs_GetNumberOfFreeChunks(yaffs_Device *dev) - { - /* This is what we report to the outside world */ - - int nFree; - int nDirtyCacheChunks; - int blocksForCheckpoint; -+ int i; - - #if 1 - nFree = dev->nFreeChunks; -@@ -7397,12 +7481,9 @@ int yaffs_GetNumberOfFreeChunks(yaffs_De - - /* Now count the number of dirty chunks in the cache and subtract those */ - -- { -- int i; -- for (nDirtyCacheChunks = 0, i = 0; i < dev->nShortOpCaches; i++) { -- if (dev->srCache[i].dirty) -- nDirtyCacheChunks++; -- } -+ for (nDirtyCacheChunks = 0, i = 0; i < dev->nShortOpCaches; i++) { -+ if (dev->srCache[i].dirty) -+ nDirtyCacheChunks++; - } - - nFree -= nDirtyCacheChunks; -@@ -7410,8 +7491,8 @@ int yaffs_GetNumberOfFreeChunks(yaffs_De - nFree -= ((dev->nReservedBlocks + 1) * dev->nChunksPerBlock); - - /* Now we figure out how much to reserve for the checkpoint and report that... */ -- blocksForCheckpoint = dev->nCheckpointReservedBlocks - dev->blocksInCheckpoint; -- if(blocksForCheckpoint < 0) -+ blocksForCheckpoint = yaffs_CalcCheckpointBlocksRequired(dev) - dev->blocksInCheckpoint; -+ if (blocksForCheckpoint < 0) - blocksForCheckpoint = 0; - - nFree -= (blocksForCheckpoint * dev->nChunksPerBlock); -@@ -7425,12 +7506,12 @@ int yaffs_GetNumberOfFreeChunks(yaffs_De - - static int yaffs_freeVerificationFailures; - --static void yaffs_VerifyFreeChunks(yaffs_Device * dev) -+static void yaffs_VerifyFreeChunks(yaffs_Device *dev) - { - int counted; - int difference; - -- if(yaffs_SkipVerification(dev)) -+ if (yaffs_SkipVerification(dev)) - return; - - counted = yaffs_CountFreeChunks(dev); -@@ -7447,23 +7528,25 @@ static void yaffs_VerifyFreeChunks(yaffs - - /*---------------------------------------- YAFFS test code ----------------------*/ - --#define yaffs_CheckStruct(structure,syze, name) \ -- if(sizeof(structure) != syze) \ -- { \ -- T(YAFFS_TRACE_ALWAYS,(TSTR("%s should be %d but is %d\n" TENDSTR),\ -- name,syze,sizeof(structure))); \ -- return YAFFS_FAIL; \ -- } -+#define yaffs_CheckStruct(structure, syze, name) \ -+ do { \ -+ if (sizeof(structure) != syze) { \ -+ T(YAFFS_TRACE_ALWAYS, (TSTR("%s should be %d but is %d\n" TENDSTR),\ -+ name, syze, sizeof(structure))); \ -+ return YAFFS_FAIL; \ -+ } \ -+ } while (0) - - static int yaffs_CheckStructures(void) - { --/* yaffs_CheckStruct(yaffs_Tags,8,"yaffs_Tags") */ --/* yaffs_CheckStruct(yaffs_TagsUnion,8,"yaffs_TagsUnion") */ --/* yaffs_CheckStruct(yaffs_Spare,16,"yaffs_Spare") */ -+/* yaffs_CheckStruct(yaffs_Tags,8,"yaffs_Tags"); */ -+/* yaffs_CheckStruct(yaffs_TagsUnion,8,"yaffs_TagsUnion"); */ -+/* yaffs_CheckStruct(yaffs_Spare,16,"yaffs_Spare"); */ - #ifndef CONFIG_YAFFS_TNODE_LIST_DEBUG -- yaffs_CheckStruct(yaffs_Tnode, 2 * YAFFS_NTNODES_LEVEL0, "yaffs_Tnode") -+ yaffs_CheckStruct(yaffs_Tnode, 2 * YAFFS_NTNODES_LEVEL0, "yaffs_Tnode"); - #endif -- yaffs_CheckStruct(yaffs_ObjectHeader, 512, "yaffs_ObjectHeader") -- -- return YAFFS_OK; -+#ifndef CONFIG_YAFFS_WINCE -+ yaffs_CheckStruct(yaffs_ObjectHeader, 512, "yaffs_ObjectHeader"); -+#endif -+ return YAFFS_OK; - } ---- a/fs/yaffs2/yaffs_guts.h -+++ b/fs/yaffs2/yaffs_guts.h -@@ -90,7 +90,7 @@ - - #define YAFFS_MAX_SHORT_OP_CACHES 20 - --#define YAFFS_N_TEMP_BUFFERS 4 -+#define YAFFS_N_TEMP_BUFFERS 6 - - /* We limit the number attempts at sucessfully saving a chunk of data. - * Small-page devices have 32 pages per block; large-page devices have 64. -@@ -108,6 +108,9 @@ - #define YAFFS_LOWEST_SEQUENCE_NUMBER 0x00001000 - #define YAFFS_HIGHEST_SEQUENCE_NUMBER 0xEFFFFF00 - -+/* Special sequence number for bad block that failed to be marked bad */ -+#define YAFFS_SEQUENCE_BAD_BLOCK 0xFFFF0000 -+ - /* ChunkCache is used for short read/write operations.*/ - typedef struct { - struct yaffs_ObjectStruct *object; -@@ -134,11 +137,10 @@ typedef struct { - typedef struct { - unsigned chunkId:20; - unsigned serialNumber:2; -- unsigned byteCount:10; -+ unsigned byteCountLSB:10; - unsigned objectId:18; - unsigned ecc:12; -- unsigned unusedStuff:2; -- -+ unsigned byteCountMSB:2; - } yaffs_Tags; - - typedef union { -@@ -277,13 +279,13 @@ typedef struct { - - int softDeletions:10; /* number of soft deleted pages */ - int pagesInUse:10; /* number of pages in use */ -- yaffs_BlockState blockState:4; /* One of the above block states */ -+ unsigned blockState:4; /* One of the above block states. NB use unsigned because enum is sometimes an int */ - __u32 needsRetiring:1; /* Data has failed on this block, need to get valid data off */ -- /* and retire the block. */ -- __u32 skipErasedCheck: 1; /* If this is set we can skip the erased check on this block */ -- __u32 gcPrioritise: 1; /* An ECC check or blank check has failed on this block. -+ /* and retire the block. */ -+ __u32 skipErasedCheck:1; /* If this is set we can skip the erased check on this block */ -+ __u32 gcPrioritise:1; /* An ECC check or blank check has failed on this block. - It should be prioritised for GC */ -- __u32 chunkErrorStrikes:3; /* How many times we've had ecc etc failures on this block and tried to reuse it */ -+ __u32 chunkErrorStrikes:3; /* How many times we've had ecc etc failures on this block and tried to reuse it */ - - #ifdef CONFIG_YAFFS_YAFFS2 - __u32 hasShrinkHeader:1; /* This block has at least one shrink object header */ -@@ -300,11 +302,11 @@ typedef struct { - - /* Apply to everything */ - int parentObjectId; -- __u16 sum__NoLongerUsed; /* checksum of name. No longer used */ -+ __u16 sum__NoLongerUsed; /* checksum of name. No longer used */ - YCHAR name[YAFFS_MAX_NAME_LENGTH + 1]; - -- /* Thes following apply to directories, files, symlinks - not hard links */ -- __u32 yst_mode; /* protection */ -+ /* The following apply to directories, files, symlinks - not hard links */ -+ __u32 yst_mode; /* protection */ - - #ifdef CONFIG_YAFFS_WINCE - __u32 notForWinCE[5]; -@@ -331,11 +333,14 @@ typedef struct { - __u32 win_ctime[2]; - __u32 win_atime[2]; - __u32 win_mtime[2]; -- __u32 roomToGrow[4]; - #else -- __u32 roomToGrow[10]; -+ __u32 roomToGrow[6]; -+ - #endif -+ __u32 inbandShadowsObject; -+ __u32 inbandIsShrink; - -+ __u32 reservedSpace[2]; - int shadowsObject; /* This object header shadows the specified object if > 0 */ - - /* isShrink applies to object headers written when we shrink the file (ie resize) */ -@@ -381,7 +386,7 @@ typedef struct { - } yaffs_FileStructure; - - typedef struct { -- struct list_head children; /* list of child links */ -+ struct ylist_head children; /* list of child links */ - } yaffs_DirectoryStructure; - - typedef struct { -@@ -418,23 +423,24 @@ struct yaffs_ObjectStruct { - * still in the inode cache. Free of object is defered. - * until the inode is released. - */ -+ __u8 beingCreated:1; /* This object is still being created so skip some checks. */ - - __u8 serial; /* serial number of chunk in NAND. Cached here */ - __u16 sum; /* sum of the name to speed searching */ - -- struct yaffs_DeviceStruct *myDev; /* The device I'm on */ -+ struct yaffs_DeviceStruct *myDev; /* The device I'm on */ - -- struct list_head hashLink; /* list of objects in this hash bucket */ -+ struct ylist_head hashLink; /* list of objects in this hash bucket */ - -- struct list_head hardLinks; /* all the equivalent hard linked objects */ -+ struct ylist_head hardLinks; /* all the equivalent hard linked objects */ - - /* directory structure stuff */ - /* also used for linking up the free list */ - struct yaffs_ObjectStruct *parent; -- struct list_head siblings; -+ struct ylist_head siblings; - - /* Where's my object header in NAND? */ -- int chunkId; -+ int hdrChunk; - - int nDataChunks; /* Number of data chunks attached to the file. */ - -@@ -485,7 +491,7 @@ struct yaffs_ObjectList_struct { - typedef struct yaffs_ObjectList_struct yaffs_ObjectList; - - typedef struct { -- struct list_head list; -+ struct ylist_head list; - int count; - } yaffs_ObjectBucket; - -@@ -495,11 +501,10 @@ typedef struct { - */ - - typedef struct { -- int structType; -+ int structType; - __u32 objectId; - __u32 parentId; -- int chunkId; -- -+ int hdrChunk; - yaffs_ObjectType variantType:3; - __u8 deleted:1; - __u8 softDeleted:1; -@@ -511,8 +516,7 @@ typedef struct { - - int nDataChunks; - __u32 fileSizeOrEquivalentObjectId; -- --}yaffs_CheckpointObject; -+} yaffs_CheckpointObject; - - /*--------------------- Temporary buffers ---------------- - * -@@ -528,13 +532,13 @@ typedef struct { - /*----------------- Device ---------------------------------*/ - - struct yaffs_DeviceStruct { -- struct list_head devList; -+ struct ylist_head devList; - const char *name; - - /* Entry parameters set up way early. Yaffs sets up the rest.*/ - int nDataBytesPerChunk; /* Should be a power of 2 >= 512 */ - int nChunksPerBlock; /* does not need to be a power of 2 */ -- int nBytesPerSpare; /* spare area size */ -+ int spareBytesPerChunk; /* spare area size */ - int startBlock; /* Start block we're allowed to use */ - int endBlock; /* End block we're allowed to use */ - int nReservedBlocks; /* We want this tuneable so that we can reduce */ -@@ -544,9 +548,7 @@ struct yaffs_DeviceStruct { - /* Stuff used by the shared space checkpointing mechanism */ - /* If this value is zero, then this mechanism is disabled */ - -- int nCheckpointReservedBlocks; /* Blocks to reserve for checkpoint data */ -- -- -+/* int nCheckpointReservedBlocks; */ /* Blocks to reserve for checkpoint data */ - - - int nShortOpCaches; /* If <= 0, then short op caching is disabled, else -@@ -560,30 +562,31 @@ struct yaffs_DeviceStruct { - void *genericDevice; /* Pointer to device context - * On an mtd this holds the mtd pointer. - */ -- void *superBlock; -+ void *superBlock; - - /* NAND access functions (Must be set before calling YAFFS)*/ - -- int (*writeChunkToNAND) (struct yaffs_DeviceStruct * dev, -- int chunkInNAND, const __u8 * data, -- const yaffs_Spare * spare); -- int (*readChunkFromNAND) (struct yaffs_DeviceStruct * dev, -- int chunkInNAND, __u8 * data, -- yaffs_Spare * spare); -- int (*eraseBlockInNAND) (struct yaffs_DeviceStruct * dev, -- int blockInNAND); -- int (*initialiseNAND) (struct yaffs_DeviceStruct * dev); -+ int (*writeChunkToNAND) (struct yaffs_DeviceStruct *dev, -+ int chunkInNAND, const __u8 *data, -+ const yaffs_Spare *spare); -+ int (*readChunkFromNAND) (struct yaffs_DeviceStruct *dev, -+ int chunkInNAND, __u8 *data, -+ yaffs_Spare *spare); -+ int (*eraseBlockInNAND) (struct yaffs_DeviceStruct *dev, -+ int blockInNAND); -+ int (*initialiseNAND) (struct yaffs_DeviceStruct *dev); -+ int (*deinitialiseNAND) (struct yaffs_DeviceStruct *dev); - - #ifdef CONFIG_YAFFS_YAFFS2 -- int (*writeChunkWithTagsToNAND) (struct yaffs_DeviceStruct * dev, -- int chunkInNAND, const __u8 * data, -- const yaffs_ExtendedTags * tags); -- int (*readChunkWithTagsFromNAND) (struct yaffs_DeviceStruct * dev, -- int chunkInNAND, __u8 * data, -- yaffs_ExtendedTags * tags); -- int (*markNANDBlockBad) (struct yaffs_DeviceStruct * dev, int blockNo); -- int (*queryNANDBlock) (struct yaffs_DeviceStruct * dev, int blockNo, -- yaffs_BlockState * state, int *sequenceNumber); -+ int (*writeChunkWithTagsToNAND) (struct yaffs_DeviceStruct *dev, -+ int chunkInNAND, const __u8 *data, -+ const yaffs_ExtendedTags *tags); -+ int (*readChunkWithTagsFromNAND) (struct yaffs_DeviceStruct *dev, -+ int chunkInNAND, __u8 *data, -+ yaffs_ExtendedTags *tags); -+ int (*markNANDBlockBad) (struct yaffs_DeviceStruct *dev, int blockNo); -+ int (*queryNANDBlock) (struct yaffs_DeviceStruct *dev, int blockNo, -+ yaffs_BlockState *state, __u32 *sequenceNumber); - #endif - - int isYaffs2; -@@ -595,10 +598,12 @@ struct yaffs_DeviceStruct { - void (*removeObjectCallback)(struct yaffs_ObjectStruct *obj); - - /* Callback to mark the superblock dirsty */ -- void (*markSuperBlockDirty)(void * superblock); -+ void (*markSuperBlockDirty)(void *superblock); - - int wideTnodesDisabled; /* Set to disable wide tnodes */ - -+ YCHAR *pathDividers; /* String of legal path dividers */ -+ - - /* End of stuff that must be set before initialisation. */ - -@@ -615,16 +620,14 @@ struct yaffs_DeviceStruct { - __u32 tnodeWidth; - __u32 tnodeMask; - -- /* Stuff to support various file offses to chunk/offset translations */ -- /* "Crumbs" for nDataBytesPerChunk not being a power of 2 */ -- __u32 crumbMask; -- __u32 crumbShift; -- __u32 crumbsPerChunk; -- -- /* Straight shifting for nDataBytesPerChunk being a power of 2 */ -- __u32 chunkShift; -- __u32 chunkMask; -- -+ /* Stuff for figuring out file offset to chunk conversions */ -+ __u32 chunkShift; /* Shift value */ -+ __u32 chunkDiv; /* Divisor after shifting: 1 for power-of-2 sizes */ -+ __u32 chunkMask; /* Mask to use for power-of-2 case */ -+ -+ /* Stuff to handle inband tags */ -+ int inbandTags; -+ __u32 totalBytesPerChunk; - - #ifdef __KERNEL__ - -@@ -633,7 +636,7 @@ struct yaffs_DeviceStruct { - __u8 *spareBuffer; /* For mtdif2 use. Don't know the size of the buffer - * at compile time so we have to allocate it. - */ -- void (*putSuperFunc) (struct super_block * sb); -+ void (*putSuperFunc) (struct super_block *sb); - #endif - - int isMounted; -@@ -663,6 +666,8 @@ struct yaffs_DeviceStruct { - __u32 checkpointSum; - __u32 checkpointXor; - -+ int nCheckpointBlocksRequired; /* Number of blocks needed to store current checkpoint set */ -+ - /* Block Info */ - yaffs_BlockInfo *blockInfo; - __u8 *chunkBits; /* bitmap of chunks in use */ -@@ -684,11 +689,15 @@ struct yaffs_DeviceStruct { - yaffs_TnodeList *allocatedTnodeList; - - int isDoingGC; -+ int gcBlock; -+ int gcChunk; - - int nObjectsCreated; - yaffs_Object *freeObjects; - int nFreeObjects; - -+ int nHardLinks; -+ - yaffs_ObjectList *allocatedObjectList; - - yaffs_ObjectBucket objectBucket[YAFFS_NOBJECT_BUCKETS]; -@@ -745,8 +754,10 @@ struct yaffs_DeviceStruct { - int nBackgroundDeletions; /* Count of background deletions. */ - - -+ /* Temporary buffer management */ - yaffs_TempBuffer tempBuffer[YAFFS_N_TEMP_BUFFERS]; - int maxTemp; -+ int tempInUse; - int unmanagedTempAllocations; - int unmanagedTempDeallocations; - -@@ -758,9 +769,9 @@ struct yaffs_DeviceStruct { - - typedef struct yaffs_DeviceStruct yaffs_Device; - --/* The static layout of bllock usage etc is stored in the super block header */ -+/* The static layout of block usage etc is stored in the super block header */ - typedef struct { -- int StructType; -+ int StructType; - int version; - int checkpointStartBlock; - int checkpointEndBlock; -@@ -773,7 +784,7 @@ typedef struct { - * must be preserved over unmount/mount cycles. - */ - typedef struct { -- int structType; -+ int structType; - int nErasedBlocks; - int allocationBlock; /* Current block being allocated off */ - __u32 allocationPage; -@@ -791,57 +802,45 @@ typedef struct { - - - typedef struct { -- int structType; -- __u32 magic; -- __u32 version; -- __u32 head; -+ int structType; -+ __u32 magic; -+ __u32 version; -+ __u32 head; - } yaffs_CheckpointValidity; - --/* Function to manipulate block info */ --static Y_INLINE yaffs_BlockInfo *yaffs_GetBlockInfo(yaffs_Device * dev, int blk) --{ -- if (blk < dev->internalStartBlock || blk > dev->internalEndBlock) { -- T(YAFFS_TRACE_ERROR, -- (TSTR -- ("**>> yaffs: getBlockInfo block %d is not valid" TENDSTR), -- blk)); -- YBUG(); -- } -- return &dev->blockInfo[blk - dev->internalStartBlock]; --} - - /*----------------------- YAFFS Functions -----------------------*/ - --int yaffs_GutsInitialise(yaffs_Device * dev); --void yaffs_Deinitialise(yaffs_Device * dev); -+int yaffs_GutsInitialise(yaffs_Device *dev); -+void yaffs_Deinitialise(yaffs_Device *dev); - --int yaffs_GetNumberOfFreeChunks(yaffs_Device * dev); -+int yaffs_GetNumberOfFreeChunks(yaffs_Device *dev); - --int yaffs_RenameObject(yaffs_Object * oldDir, const YCHAR * oldName, -- yaffs_Object * newDir, const YCHAR * newName); -+int yaffs_RenameObject(yaffs_Object *oldDir, const YCHAR *oldName, -+ yaffs_Object *newDir, const YCHAR *newName); - --int yaffs_Unlink(yaffs_Object * dir, const YCHAR * name); --int yaffs_DeleteFile(yaffs_Object * obj); -+int yaffs_Unlink(yaffs_Object *dir, const YCHAR *name); -+int yaffs_DeleteObject(yaffs_Object *obj); - --int yaffs_GetObjectName(yaffs_Object * obj, YCHAR * name, int buffSize); --int yaffs_GetObjectFileLength(yaffs_Object * obj); --int yaffs_GetObjectInode(yaffs_Object * obj); --unsigned yaffs_GetObjectType(yaffs_Object * obj); --int yaffs_GetObjectLinkCount(yaffs_Object * obj); -+int yaffs_GetObjectName(yaffs_Object *obj, YCHAR *name, int buffSize); -+int yaffs_GetObjectFileLength(yaffs_Object *obj); -+int yaffs_GetObjectInode(yaffs_Object *obj); -+unsigned yaffs_GetObjectType(yaffs_Object *obj); -+int yaffs_GetObjectLinkCount(yaffs_Object *obj); - --int yaffs_SetAttributes(yaffs_Object * obj, struct iattr *attr); --int yaffs_GetAttributes(yaffs_Object * obj, struct iattr *attr); -+int yaffs_SetAttributes(yaffs_Object *obj, struct iattr *attr); -+int yaffs_GetAttributes(yaffs_Object *obj, struct iattr *attr); - - /* File operations */ --int yaffs_ReadDataFromFile(yaffs_Object * obj, __u8 * buffer, loff_t offset, -- int nBytes); --int yaffs_WriteDataToFile(yaffs_Object * obj, const __u8 * buffer, loff_t offset, -- int nBytes, int writeThrough); --int yaffs_ResizeFile(yaffs_Object * obj, loff_t newSize); -- --yaffs_Object *yaffs_MknodFile(yaffs_Object * parent, const YCHAR * name, -- __u32 mode, __u32 uid, __u32 gid); --int yaffs_FlushFile(yaffs_Object * obj, int updateTime); -+int yaffs_ReadDataFromFile(yaffs_Object *obj, __u8 *buffer, loff_t offset, -+ int nBytes); -+int yaffs_WriteDataToFile(yaffs_Object *obj, const __u8 *buffer, loff_t offset, -+ int nBytes, int writeThrough); -+int yaffs_ResizeFile(yaffs_Object *obj, loff_t newSize); -+ -+yaffs_Object *yaffs_MknodFile(yaffs_Object *parent, const YCHAR *name, -+ __u32 mode, __u32 uid, __u32 gid); -+int yaffs_FlushFile(yaffs_Object *obj, int updateTime); - - /* Flushing and checkpointing */ - void yaffs_FlushEntireDeviceCache(yaffs_Device *dev); -@@ -850,33 +849,33 @@ int yaffs_CheckpointSave(yaffs_Device *d - int yaffs_CheckpointRestore(yaffs_Device *dev); - - /* Directory operations */ --yaffs_Object *yaffs_MknodDirectory(yaffs_Object * parent, const YCHAR * name, -- __u32 mode, __u32 uid, __u32 gid); --yaffs_Object *yaffs_FindObjectByName(yaffs_Object * theDir, const YCHAR * name); --int yaffs_ApplyToDirectoryChildren(yaffs_Object * theDir, -+yaffs_Object *yaffs_MknodDirectory(yaffs_Object *parent, const YCHAR *name, -+ __u32 mode, __u32 uid, __u32 gid); -+yaffs_Object *yaffs_FindObjectByName(yaffs_Object *theDir, const YCHAR *name); -+int yaffs_ApplyToDirectoryChildren(yaffs_Object *theDir, - int (*fn) (yaffs_Object *)); - --yaffs_Object *yaffs_FindObjectByNumber(yaffs_Device * dev, __u32 number); -+yaffs_Object *yaffs_FindObjectByNumber(yaffs_Device *dev, __u32 number); - - /* Link operations */ --yaffs_Object *yaffs_Link(yaffs_Object * parent, const YCHAR * name, -- yaffs_Object * equivalentObject); -+yaffs_Object *yaffs_Link(yaffs_Object *parent, const YCHAR *name, -+ yaffs_Object *equivalentObject); - --yaffs_Object *yaffs_GetEquivalentObject(yaffs_Object * obj); -+yaffs_Object *yaffs_GetEquivalentObject(yaffs_Object *obj); - - /* Symlink operations */ --yaffs_Object *yaffs_MknodSymLink(yaffs_Object * parent, const YCHAR * name, -+yaffs_Object *yaffs_MknodSymLink(yaffs_Object *parent, const YCHAR *name, - __u32 mode, __u32 uid, __u32 gid, -- const YCHAR * alias); --YCHAR *yaffs_GetSymlinkAlias(yaffs_Object * obj); -+ const YCHAR *alias); -+YCHAR *yaffs_GetSymlinkAlias(yaffs_Object *obj); - - /* Special inodes (fifos, sockets and devices) */ --yaffs_Object *yaffs_MknodSpecial(yaffs_Object * parent, const YCHAR * name, -+yaffs_Object *yaffs_MknodSpecial(yaffs_Object *parent, const YCHAR *name, - __u32 mode, __u32 uid, __u32 gid, __u32 rdev); - - /* Special directories */ --yaffs_Object *yaffs_Root(yaffs_Device * dev); --yaffs_Object *yaffs_LostNFound(yaffs_Device * dev); -+yaffs_Object *yaffs_Root(yaffs_Device *dev); -+yaffs_Object *yaffs_LostNFound(yaffs_Device *dev); - - #ifdef CONFIG_YAFFS_WINCE - /* CONFIG_YAFFS_WINCE special stuff */ -@@ -885,18 +884,21 @@ void yfsd_WinFileTimeNow(__u32 target[2] - - #ifdef __KERNEL__ - --void yaffs_HandleDeferedFree(yaffs_Object * obj); -+void yaffs_HandleDeferedFree(yaffs_Object *obj); - #endif - - /* Debug dump */ --int yaffs_DumpObject(yaffs_Object * obj); -+int yaffs_DumpObject(yaffs_Object *obj); - --void yaffs_GutsTest(yaffs_Device * dev); -+void yaffs_GutsTest(yaffs_Device *dev); - - /* A few useful functions */ --void yaffs_InitialiseTags(yaffs_ExtendedTags * tags); --void yaffs_DeleteChunk(yaffs_Device * dev, int chunkId, int markNAND, int lyn); --int yaffs_CheckFF(__u8 * buffer, int nBytes); -+void yaffs_InitialiseTags(yaffs_ExtendedTags *tags); -+void yaffs_DeleteChunk(yaffs_Device *dev, int chunkId, int markNAND, int lyn); -+int yaffs_CheckFF(__u8 *buffer, int nBytes); - void yaffs_HandleChunkError(yaffs_Device *dev, yaffs_BlockInfo *bi); - -+__u8 *yaffs_GetTempBuffer(yaffs_Device *dev, int lineNo); -+void yaffs_ReleaseTempBuffer(yaffs_Device *dev, __u8 *buffer, int lineNo); -+ - #endif ---- a/fs/yaffs2/yaffs_mtdif1.c -+++ b/fs/yaffs2/yaffs_mtdif1.c -@@ -26,7 +26,7 @@ - #include "yportenv.h" - #include "yaffs_guts.h" - #include "yaffs_packedtags1.h" --#include "yaffs_tagscompat.h" // for yaffs_CalcTagsECC -+#include "yaffs_tagscompat.h" /* for yaffs_CalcTagsECC */ - - #include "linux/kernel.h" - #include "linux/version.h" -@@ -34,9 +34,9 @@ - #include "linux/mtd/mtd.h" - - /* Don't compile this module if we don't have MTD's mtd_oob_ops interface */ --#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) -+#if (MTD_VERSION_CODE > MTD_VERSION(2, 6, 17)) - --const char *yaffs_mtdif1_c_version = "$Id: yaffs_mtdif1.c,v 1.3 2007/05/15 20:16:11 ian Exp $"; -+const char *yaffs_mtdif1_c_version = "$Id: yaffs_mtdif1.c,v 1.10 2009-03-09 07:41:10 charles Exp $"; - - #ifndef CONFIG_YAFFS_9BYTE_TAGS - # define YTAG1_SIZE 8 -@@ -89,9 +89,9 @@ static struct nand_ecclayout nand_oob_16 - * Returns YAFFS_OK or YAFFS_FAIL. - */ - int nandmtd1_WriteChunkWithTagsToNAND(yaffs_Device *dev, -- int chunkInNAND, const __u8 * data, const yaffs_ExtendedTags * etags) -+ int chunkInNAND, const __u8 *data, const yaffs_ExtendedTags *etags) - { -- struct mtd_info * mtd = dev->genericDevice; -+ struct mtd_info *mtd = dev->genericDevice; - int chunkBytes = dev->nDataBytesPerChunk; - loff_t addr = ((loff_t)chunkInNAND) * chunkBytes; - struct mtd_oob_ops ops; -@@ -146,7 +146,7 @@ int nandmtd1_WriteChunkWithTagsToNAND(ya - - /* Return with empty ExtendedTags but add eccResult. - */ --static int rettags(yaffs_ExtendedTags * etags, int eccResult, int retval) -+static int rettags(yaffs_ExtendedTags *etags, int eccResult, int retval) - { - if (etags) { - memset(etags, 0, sizeof(*etags)); -@@ -169,9 +169,9 @@ static int rettags(yaffs_ExtendedTags * - * Returns YAFFS_OK or YAFFS_FAIL. - */ - int nandmtd1_ReadChunkWithTagsFromNAND(yaffs_Device *dev, -- int chunkInNAND, __u8 * data, yaffs_ExtendedTags * etags) -+ int chunkInNAND, __u8 *data, yaffs_ExtendedTags *etags) - { -- struct mtd_info * mtd = dev->genericDevice; -+ struct mtd_info *mtd = dev->genericDevice; - int chunkBytes = dev->nDataBytesPerChunk; - loff_t addr = ((loff_t)chunkInNAND) * chunkBytes; - int eccres = YAFFS_ECC_RESULT_NO_ERROR; -@@ -189,7 +189,7 @@ int nandmtd1_ReadChunkWithTagsFromNAND(y - ops.datbuf = data; - ops.oobbuf = (__u8 *)&pt1; - --#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)) -+#if (MTD_VERSION_CODE < MTD_VERSION(2, 6, 20)) - /* In MTD 2.6.18 to 2.6.19 nand_base.c:nand_do_read_oob() has a bug; - * help it out with ops.len = ops.ooblen when ops.datbuf == NULL. - */ -@@ -284,11 +284,11 @@ int nandmtd1_ReadChunkWithTagsFromNAND(y - */ - int nandmtd1_MarkNANDBlockBad(struct yaffs_DeviceStruct *dev, int blockNo) - { -- struct mtd_info * mtd = dev->genericDevice; -+ struct mtd_info *mtd = dev->genericDevice; - int blocksize = dev->nChunksPerBlock * dev->nDataBytesPerChunk; - int retval; - -- yaffs_trace(YAFFS_TRACE_BAD_BLOCKS, "marking block %d bad", blockNo); -+ yaffs_trace(YAFFS_TRACE_BAD_BLOCKS, "marking block %d bad\n", blockNo); - - retval = mtd->block_markbad(mtd, (loff_t)blocksize * blockNo); - return (retval) ? YAFFS_FAIL : YAFFS_OK; -@@ -298,7 +298,7 @@ int nandmtd1_MarkNANDBlockBad(struct yaf - * - * Returns YAFFS_OK or YAFFS_FAIL. - */ --static int nandmtd1_TestPrerequists(struct mtd_info * mtd) -+static int nandmtd1_TestPrerequists(struct mtd_info *mtd) - { - /* 2.6.18 has mtd->ecclayout->oobavail */ - /* 2.6.21 has mtd->ecclayout->oobavail and mtd->oobavail */ -@@ -323,10 +323,11 @@ static int nandmtd1_TestPrerequists(stru - * Always returns YAFFS_OK. - */ - int nandmtd1_QueryNANDBlock(struct yaffs_DeviceStruct *dev, int blockNo, -- yaffs_BlockState * pState, int *pSequenceNumber) -+ yaffs_BlockState *pState, __u32 *pSequenceNumber) - { -- struct mtd_info * mtd = dev->genericDevice; -+ struct mtd_info *mtd = dev->genericDevice; - int chunkNo = blockNo * dev->nChunksPerBlock; -+ loff_t addr = (loff_t)chunkNo * dev->nDataBytesPerChunk; - yaffs_ExtendedTags etags; - int state = YAFFS_BLOCK_STATE_DEAD; - int seqnum = 0; -@@ -335,21 +336,22 @@ int nandmtd1_QueryNANDBlock(struct yaffs - /* We don't yet have a good place to test for MTD config prerequists. - * Do it here as we are called during the initial scan. - */ -- if (nandmtd1_TestPrerequists(mtd) != YAFFS_OK) { -+ if (nandmtd1_TestPrerequists(mtd) != YAFFS_OK) - return YAFFS_FAIL; -- } - - retval = nandmtd1_ReadChunkWithTagsFromNAND(dev, chunkNo, NULL, &etags); -+ etags.blockBad = (mtd->block_isbad)(mtd, addr); - if (etags.blockBad) { - yaffs_trace(YAFFS_TRACE_BAD_BLOCKS, -- "block %d is marked bad", blockNo); -+ "block %d is marked bad\n", blockNo); - state = YAFFS_BLOCK_STATE_DEAD; -- } -- else if (etags.chunkUsed) { -+ } else if (etags.eccResult != YAFFS_ECC_RESULT_NO_ERROR) { -+ /* bad tags, need to look more closely */ -+ state = YAFFS_BLOCK_STATE_NEEDS_SCANNING; -+ } else if (etags.chunkUsed) { - state = YAFFS_BLOCK_STATE_NEEDS_SCANNING; - seqnum = etags.sequenceNumber; -- } -- else { -+ } else { - state = YAFFS_BLOCK_STATE_EMPTY; - } - -@@ -360,4 +362,4 @@ int nandmtd1_QueryNANDBlock(struct yaffs - return YAFFS_OK; - } - --#endif /*KERNEL_VERSION*/ -+#endif /*MTD_VERSION*/ ---- a/fs/yaffs2/yaffs_mtdif1.h -+++ b/fs/yaffs2/yaffs_mtdif1.h -@@ -14,15 +14,15 @@ - #ifndef __YAFFS_MTDIF1_H__ - #define __YAFFS_MTDIF1_H__ - --int nandmtd1_WriteChunkWithTagsToNAND(yaffs_Device * dev, int chunkInNAND, -- const __u8 * data, const yaffs_ExtendedTags * tags); -+int nandmtd1_WriteChunkWithTagsToNAND(yaffs_Device *dev, int chunkInNAND, -+ const __u8 *data, const yaffs_ExtendedTags *tags); - --int nandmtd1_ReadChunkWithTagsFromNAND(yaffs_Device * dev, int chunkInNAND, -- __u8 * data, yaffs_ExtendedTags * tags); -+int nandmtd1_ReadChunkWithTagsFromNAND(yaffs_Device *dev, int chunkInNAND, -+ __u8 *data, yaffs_ExtendedTags *tags); - - int nandmtd1_MarkNANDBlockBad(struct yaffs_DeviceStruct *dev, int blockNo); - - int nandmtd1_QueryNANDBlock(struct yaffs_DeviceStruct *dev, int blockNo, -- yaffs_BlockState * state, int *sequenceNumber); -+ yaffs_BlockState *state, __u32 *sequenceNumber); - - #endif ---- a/fs/yaffs2/yaffs_mtdif2.c -+++ b/fs/yaffs2/yaffs_mtdif2.c -@@ -14,7 +14,7 @@ - /* mtd interface for YAFFS2 */ - - const char *yaffs_mtdif2_c_version = -- "$Id: yaffs_mtdif2.c,v 1.17 2007-02-14 01:09:06 wookey Exp $"; -+ "$Id: yaffs_mtdif2.c,v 1.23 2009-03-06 17:20:53 wookey Exp $"; - - #include "yportenv.h" - -@@ -27,19 +27,23 @@ const char *yaffs_mtdif2_c_version = - - #include "yaffs_packedtags2.h" - --int nandmtd2_WriteChunkWithTagsToNAND(yaffs_Device * dev, int chunkInNAND, -- const __u8 * data, -- const yaffs_ExtendedTags * tags) -+/* NB For use with inband tags.... -+ * We assume that the data buffer is of size totalBytersPerChunk so that we can also -+ * use it to load the tags. -+ */ -+int nandmtd2_WriteChunkWithTagsToNAND(yaffs_Device *dev, int chunkInNAND, -+ const __u8 *data, -+ const yaffs_ExtendedTags *tags) - { - struct mtd_info *mtd = (struct mtd_info *)(dev->genericDevice); --#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) -+#if (MTD_VERSION_CODE > MTD_VERSION(2, 6, 17)) - struct mtd_oob_ops ops; - #else - size_t dummy; - #endif - int retval = 0; - -- loff_t addr = ((loff_t) chunkInNAND) * dev->nDataBytesPerChunk; -+ loff_t addr; - - yaffs_PackedTags2 pt; - -@@ -48,46 +52,40 @@ int nandmtd2_WriteChunkWithTagsToNAND(ya - ("nandmtd2_WriteChunkWithTagsToNAND chunk %d data %p tags %p" - TENDSTR), chunkInNAND, data, tags)); - --#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) -- if (tags) -- yaffs_PackTags2(&pt, tags); -- else -- BUG(); /* both tags and data should always be present */ - -- if (data) { -- ops.mode = MTD_OOB_AUTO; -- ops.ooblen = sizeof(pt); -- ops.len = dev->nDataBytesPerChunk; -- ops.ooboffs = 0; -- ops.datbuf = (__u8 *)data; -- ops.oobbuf = (void *)&pt; -- retval = mtd->write_oob(mtd, addr, &ops); -+ addr = ((loff_t) chunkInNAND) * dev->totalBytesPerChunk; -+ -+ /* For yaffs2 writing there must be both data and tags. -+ * If we're using inband tags, then the tags are stuffed into -+ * the end of the data buffer. -+ */ -+ if (!data || !tags) -+ BUG(); -+ else if (dev->inbandTags) { -+ yaffs_PackedTags2TagsPart *pt2tp; -+ pt2tp = (yaffs_PackedTags2TagsPart *)(data + dev->nDataBytesPerChunk); -+ yaffs_PackTags2TagsPart(pt2tp, tags); - } else -- BUG(); /* both tags and data should always be present */ --#else -- if (tags) { - yaffs_PackTags2(&pt, tags); -- } - -- if (data && tags) { -- if (dev->useNANDECC) -- retval = -- mtd->write_ecc(mtd, addr, dev->nDataBytesPerChunk, -- &dummy, data, (__u8 *) & pt, NULL); -- else -- retval = -- mtd->write_ecc(mtd, addr, dev->nDataBytesPerChunk, -- &dummy, data, (__u8 *) & pt, NULL); -- } else { -- if (data) -- retval = -- mtd->write(mtd, addr, dev->nDataBytesPerChunk, &dummy, -- data); -- if (tags) -- retval = -- mtd->write_oob(mtd, addr, mtd->oobsize, &dummy, -- (__u8 *) & pt); -+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17)) -+ ops.mode = MTD_OOB_AUTO; -+ ops.ooblen = (dev->inbandTags) ? 0 : sizeof(pt); -+ ops.len = dev->totalBytesPerChunk; -+ ops.ooboffs = 0; -+ ops.datbuf = (__u8 *)data; -+ ops.oobbuf = (dev->inbandTags) ? NULL : (void *)&pt; -+ retval = mtd->write_oob(mtd, addr, &ops); - -+#else -+ if (!dev->inbandTags) { -+ retval = -+ mtd->write_ecc(mtd, addr, dev->nDataBytesPerChunk, -+ &dummy, data, (__u8 *) &pt, NULL); -+ } else { -+ retval = -+ mtd->write(mtd, addr, dev->totalBytesPerChunk, &dummy, -+ data); - } - #endif - -@@ -97,17 +95,18 @@ int nandmtd2_WriteChunkWithTagsToNAND(ya - return YAFFS_FAIL; - } - --int nandmtd2_ReadChunkWithTagsFromNAND(yaffs_Device * dev, int chunkInNAND, -- __u8 * data, yaffs_ExtendedTags * tags) -+int nandmtd2_ReadChunkWithTagsFromNAND(yaffs_Device *dev, int chunkInNAND, -+ __u8 *data, yaffs_ExtendedTags *tags) - { - struct mtd_info *mtd = (struct mtd_info *)(dev->genericDevice); --#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) -+#if (MTD_VERSION_CODE > MTD_VERSION(2, 6, 17)) - struct mtd_oob_ops ops; - #endif - size_t dummy; - int retval = 0; -+ int localData = 0; - -- loff_t addr = ((loff_t) chunkInNAND) * dev->nDataBytesPerChunk; -+ loff_t addr = ((loff_t) chunkInNAND) * dev->totalBytesPerChunk; - - yaffs_PackedTags2 pt; - -@@ -116,9 +115,20 @@ int nandmtd2_ReadChunkWithTagsFromNAND(y - ("nandmtd2_ReadChunkWithTagsFromNAND chunk %d data %p tags %p" - TENDSTR), chunkInNAND, data, tags)); - --#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) -- if (data && !tags) -- retval = mtd->read(mtd, addr, dev->nDataBytesPerChunk, -+ if (dev->inbandTags) { -+ -+ if (!data) { -+ localData = 1; -+ data = yaffs_GetTempBuffer(dev, __LINE__); -+ } -+ -+ -+ } -+ -+ -+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17)) -+ if (dev->inbandTags || (data && !tags)) -+ retval = mtd->read(mtd, addr, dev->totalBytesPerChunk, - &dummy, data); - else if (tags) { - ops.mode = MTD_OOB_AUTO; -@@ -130,38 +140,42 @@ int nandmtd2_ReadChunkWithTagsFromNAND(y - retval = mtd->read_oob(mtd, addr, &ops); - } - #else -- if (data && tags) { -- if (dev->useNANDECC) { -- retval = -- mtd->read_ecc(mtd, addr, dev->nDataBytesPerChunk, -- &dummy, data, dev->spareBuffer, -- NULL); -- } else { -- retval = -- mtd->read_ecc(mtd, addr, dev->nDataBytesPerChunk, -+ if (!dev->inbandTags && data && tags) { -+ -+ retval = mtd->read_ecc(mtd, addr, dev->nDataBytesPerChunk, - &dummy, data, dev->spareBuffer, - NULL); -- } - } else { - if (data) - retval = - mtd->read(mtd, addr, dev->nDataBytesPerChunk, &dummy, - data); -- if (tags) -+ if (!dev->inbandTags && tags) - retval = - mtd->read_oob(mtd, addr, mtd->oobsize, &dummy, - dev->spareBuffer); - } - #endif - -- memcpy(&pt, dev->spareBuffer, sizeof(pt)); - -- if (tags) -- yaffs_UnpackTags2(tags, &pt); -+ if (dev->inbandTags) { -+ if (tags) { -+ yaffs_PackedTags2TagsPart *pt2tp; -+ pt2tp = (yaffs_PackedTags2TagsPart *)&data[dev->nDataBytesPerChunk]; -+ yaffs_UnpackTags2TagsPart(tags, pt2tp); -+ } -+ } else { -+ if (tags) { -+ memcpy(&pt, dev->spareBuffer, sizeof(pt)); -+ yaffs_UnpackTags2(tags, &pt); -+ } -+ } - -- if(tags && retval == -EBADMSG && tags->eccResult == YAFFS_ECC_RESULT_NO_ERROR) -- tags->eccResult = YAFFS_ECC_RESULT_UNFIXED; -+ if (localData) -+ yaffs_ReleaseTempBuffer(dev, data, __LINE__); - -+ if (tags && retval == -EBADMSG && tags->eccResult == YAFFS_ECC_RESULT_NO_ERROR) -+ tags->eccResult = YAFFS_ECC_RESULT_UNFIXED; - if (retval == 0) - return YAFFS_OK; - else -@@ -178,7 +192,7 @@ int nandmtd2_MarkNANDBlockBad(struct yaf - retval = - mtd->block_markbad(mtd, - blockNo * dev->nChunksPerBlock * -- dev->nDataBytesPerChunk); -+ dev->totalBytesPerChunk); - - if (retval == 0) - return YAFFS_OK; -@@ -188,7 +202,7 @@ int nandmtd2_MarkNANDBlockBad(struct yaf - } - - int nandmtd2_QueryNANDBlock(struct yaffs_DeviceStruct *dev, int blockNo, -- yaffs_BlockState * state, int *sequenceNumber) -+ yaffs_BlockState *state, __u32 *sequenceNumber) - { - struct mtd_info *mtd = (struct mtd_info *)(dev->genericDevice); - int retval; -@@ -198,7 +212,7 @@ int nandmtd2_QueryNANDBlock(struct yaffs - retval = - mtd->block_isbad(mtd, - blockNo * dev->nChunksPerBlock * -- dev->nDataBytesPerChunk); -+ dev->totalBytesPerChunk); - - if (retval) { - T(YAFFS_TRACE_MTD, (TSTR("block is bad" TENDSTR))); ---- a/fs/yaffs2/yaffs_mtdif2.h -+++ b/fs/yaffs2/yaffs_mtdif2.h -@@ -17,13 +17,13 @@ - #define __YAFFS_MTDIF2_H__ - - #include "yaffs_guts.h" --int nandmtd2_WriteChunkWithTagsToNAND(yaffs_Device * dev, int chunkInNAND, -- const __u8 * data, -- const yaffs_ExtendedTags * tags); --int nandmtd2_ReadChunkWithTagsFromNAND(yaffs_Device * dev, int chunkInNAND, -- __u8 * data, yaffs_ExtendedTags * tags); -+int nandmtd2_WriteChunkWithTagsToNAND(yaffs_Device *dev, int chunkInNAND, -+ const __u8 *data, -+ const yaffs_ExtendedTags *tags); -+int nandmtd2_ReadChunkWithTagsFromNAND(yaffs_Device *dev, int chunkInNAND, -+ __u8 *data, yaffs_ExtendedTags *tags); - int nandmtd2_MarkNANDBlockBad(struct yaffs_DeviceStruct *dev, int blockNo); - int nandmtd2_QueryNANDBlock(struct yaffs_DeviceStruct *dev, int blockNo, -- yaffs_BlockState * state, int *sequenceNumber); -+ yaffs_BlockState *state, __u32 *sequenceNumber); - - #endif ---- a/fs/yaffs2/yaffs_mtdif.c -+++ b/fs/yaffs2/yaffs_mtdif.c -@@ -12,7 +12,7 @@ - */ - - const char *yaffs_mtdif_c_version = -- "$Id: yaffs_mtdif.c,v 1.19 2007-02-14 01:09:06 wookey Exp $"; -+ "$Id: yaffs_mtdif.c,v 1.22 2009-03-06 17:20:51 wookey Exp $"; - - #include "yportenv.h" - -@@ -24,7 +24,7 @@ const char *yaffs_mtdif_c_version = - #include "linux/time.h" - #include "linux/mtd/nand.h" - --#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18)) -+#if (MTD_VERSION_CODE < MTD_VERSION(2, 6, 18)) - static struct nand_oobinfo yaffs_oobinfo = { - .useecc = 1, - .eccbytes = 6, -@@ -36,7 +36,7 @@ static struct nand_oobinfo yaffs_noeccin - }; - #endif - --#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) -+#if (MTD_VERSION_CODE > MTD_VERSION(2, 6, 17)) - static inline void translate_spare2oob(const yaffs_Spare *spare, __u8 *oob) - { - oob[0] = spare->tagByte0; -@@ -45,8 +45,8 @@ static inline void translate_spare2oob(c - oob[3] = spare->tagByte3; - oob[4] = spare->tagByte4; - oob[5] = spare->tagByte5 & 0x3f; -- oob[5] |= spare->blockStatus == 'Y' ? 0: 0x80; -- oob[5] |= spare->pageStatus == 0 ? 0: 0x40; -+ oob[5] |= spare->blockStatus == 'Y' ? 0 : 0x80; -+ oob[5] |= spare->pageStatus == 0 ? 0 : 0x40; - oob[6] = spare->tagByte6; - oob[7] = spare->tagByte7; - } -@@ -71,18 +71,18 @@ static inline void translate_oob2spare(y - } - #endif - --int nandmtd_WriteChunkToNAND(yaffs_Device * dev, int chunkInNAND, -- const __u8 * data, const yaffs_Spare * spare) -+int nandmtd_WriteChunkToNAND(yaffs_Device *dev, int chunkInNAND, -+ const __u8 *data, const yaffs_Spare *spare) - { - struct mtd_info *mtd = (struct mtd_info *)(dev->genericDevice); --#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) -+#if (MTD_VERSION_CODE > MTD_VERSION(2, 6, 17)) - struct mtd_oob_ops ops; - #endif - size_t dummy; - int retval = 0; - - loff_t addr = ((loff_t) chunkInNAND) * dev->nDataBytesPerChunk; --#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) -+#if (MTD_VERSION_CODE > MTD_VERSION(2, 6, 17)) - __u8 spareAsBytes[8]; /* OOB */ - - if (data && !spare) -@@ -135,18 +135,18 @@ int nandmtd_WriteChunkToNAND(yaffs_Devic - return YAFFS_FAIL; - } - --int nandmtd_ReadChunkFromNAND(yaffs_Device * dev, int chunkInNAND, __u8 * data, -- yaffs_Spare * spare) -+int nandmtd_ReadChunkFromNAND(yaffs_Device *dev, int chunkInNAND, __u8 *data, -+ yaffs_Spare *spare) - { - struct mtd_info *mtd = (struct mtd_info *)(dev->genericDevice); --#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) -+#if (MTD_VERSION_CODE > MTD_VERSION(2, 6, 17)) - struct mtd_oob_ops ops; - #endif - size_t dummy; - int retval = 0; - - loff_t addr = ((loff_t) chunkInNAND) * dev->nDataBytesPerChunk; --#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) -+#if (MTD_VERSION_CODE > MTD_VERSION(2, 6, 17)) - __u8 spareAsBytes[8]; /* OOB */ - - if (data && !spare) -@@ -205,7 +205,7 @@ int nandmtd_ReadChunkFromNAND(yaffs_Devi - return YAFFS_FAIL; - } - --int nandmtd_EraseBlockInNAND(yaffs_Device * dev, int blockNumber) -+int nandmtd_EraseBlockInNAND(yaffs_Device *dev, int blockNumber) - { - struct mtd_info *mtd = (struct mtd_info *)(dev->genericDevice); - __u32 addr = -@@ -234,7 +234,7 @@ int nandmtd_EraseBlockInNAND(yaffs_Devic - return YAFFS_FAIL; - } - --int nandmtd_InitialiseNAND(yaffs_Device * dev) -+int nandmtd_InitialiseNAND(yaffs_Device *dev) - { - return YAFFS_OK; - } ---- a/fs/yaffs2/yaffs_mtdif.h -+++ b/fs/yaffs2/yaffs_mtdif.h -@@ -18,10 +18,15 @@ - - #include "yaffs_guts.h" - --int nandmtd_WriteChunkToNAND(yaffs_Device * dev, int chunkInNAND, -- const __u8 * data, const yaffs_Spare * spare); --int nandmtd_ReadChunkFromNAND(yaffs_Device * dev, int chunkInNAND, __u8 * data, -- yaffs_Spare * spare); --int nandmtd_EraseBlockInNAND(yaffs_Device * dev, int blockNumber); --int nandmtd_InitialiseNAND(yaffs_Device * dev); -+#if (MTD_VERSION_CODE < MTD_VERSION(2, 6, 18)) -+extern struct nand_oobinfo yaffs_oobinfo; -+extern struct nand_oobinfo yaffs_noeccinfo; -+#endif -+ -+int nandmtd_WriteChunkToNAND(yaffs_Device *dev, int chunkInNAND, -+ const __u8 *data, const yaffs_Spare *spare); -+int nandmtd_ReadChunkFromNAND(yaffs_Device *dev, int chunkInNAND, __u8 *data, -+ yaffs_Spare *spare); -+int nandmtd_EraseBlockInNAND(yaffs_Device *dev, int blockNumber); -+int nandmtd_InitialiseNAND(yaffs_Device *dev); - #endif ---- a/fs/yaffs2/yaffs_nand.c -+++ b/fs/yaffs2/yaffs_nand.c -@@ -12,16 +12,17 @@ - */ - - const char *yaffs_nand_c_version = -- "$Id: yaffs_nand.c,v 1.7 2007-02-14 01:09:06 wookey Exp $"; -+ "$Id: yaffs_nand.c,v 1.10 2009-03-06 17:20:54 wookey Exp $"; - - #include "yaffs_nand.h" - #include "yaffs_tagscompat.h" - #include "yaffs_tagsvalidity.h" - -+#include "yaffs_getblockinfo.h" - --int yaffs_ReadChunkWithTagsFromNAND(yaffs_Device * dev, int chunkInNAND, -- __u8 * buffer, -- yaffs_ExtendedTags * tags) -+int yaffs_ReadChunkWithTagsFromNAND(yaffs_Device *dev, int chunkInNAND, -+ __u8 *buffer, -+ yaffs_ExtendedTags *tags) - { - int result; - yaffs_ExtendedTags localTags; -@@ -29,7 +30,7 @@ int yaffs_ReadChunkWithTagsFromNAND(yaff - int realignedChunkInNAND = chunkInNAND - dev->chunkOffset; - - /* If there are no tags provided, use local tags to get prioritised gc working */ -- if(!tags) -+ if (!tags) - tags = &localTags; - - if (dev->readChunkWithTagsFromNAND) -@@ -40,20 +41,20 @@ int yaffs_ReadChunkWithTagsFromNAND(yaff - realignedChunkInNAND, - buffer, - tags); -- if(tags && -- tags->eccResult > YAFFS_ECC_RESULT_NO_ERROR){ -+ if (tags && -+ tags->eccResult > YAFFS_ECC_RESULT_NO_ERROR) { - - yaffs_BlockInfo *bi = yaffs_GetBlockInfo(dev, chunkInNAND/dev->nChunksPerBlock); -- yaffs_HandleChunkError(dev,bi); -+ yaffs_HandleChunkError(dev, bi); - } - - return result; - } - --int yaffs_WriteChunkWithTagsToNAND(yaffs_Device * dev, -+int yaffs_WriteChunkWithTagsToNAND(yaffs_Device *dev, - int chunkInNAND, -- const __u8 * buffer, -- yaffs_ExtendedTags * tags) -+ const __u8 *buffer, -+ yaffs_ExtendedTags *tags) - { - chunkInNAND -= dev->chunkOffset; - -@@ -84,7 +85,7 @@ int yaffs_WriteChunkWithTagsToNAND(yaffs - tags); - } - --int yaffs_MarkBlockBad(yaffs_Device * dev, int blockNo) -+int yaffs_MarkBlockBad(yaffs_Device *dev, int blockNo) - { - blockNo -= dev->blockOffset; - -@@ -95,10 +96,10 @@ int yaffs_MarkBlockBad(yaffs_Device * de - return yaffs_TagsCompatabilityMarkNANDBlockBad(dev, blockNo); - } - --int yaffs_QueryInitialBlockState(yaffs_Device * dev, -+int yaffs_QueryInitialBlockState(yaffs_Device *dev, - int blockNo, -- yaffs_BlockState * state, -- unsigned *sequenceNumber) -+ yaffs_BlockState *state, -+ __u32 *sequenceNumber) - { - blockNo -= dev->blockOffset; - ---- a/fs/yaffs2/yaffs_nandemul2k.h -+++ b/fs/yaffs2/yaffs_nandemul2k.h -@@ -21,14 +21,14 @@ - #include "yaffs_guts.h" - - int nandemul2k_WriteChunkWithTagsToNAND(struct yaffs_DeviceStruct *dev, -- int chunkInNAND, const __u8 * data, -- yaffs_ExtendedTags * tags); -+ int chunkInNAND, const __u8 *data, -+ const yaffs_ExtendedTags *tags); - int nandemul2k_ReadChunkWithTagsFromNAND(struct yaffs_DeviceStruct *dev, -- int chunkInNAND, __u8 * data, -- yaffs_ExtendedTags * tags); -+ int chunkInNAND, __u8 *data, -+ yaffs_ExtendedTags *tags); - int nandemul2k_MarkNANDBlockBad(struct yaffs_DeviceStruct *dev, int blockNo); - int nandemul2k_QueryNANDBlock(struct yaffs_DeviceStruct *dev, int blockNo, -- yaffs_BlockState * state, int *sequenceNumber); -+ yaffs_BlockState *state, __u32 *sequenceNumber); - int nandemul2k_EraseBlockInNAND(struct yaffs_DeviceStruct *dev, - int blockInNAND); - int nandemul2k_InitialiseNAND(struct yaffs_DeviceStruct *dev); ---- a/fs/yaffs2/yaffs_nand.h -+++ b/fs/yaffs2/yaffs_nand.h -@@ -19,21 +19,21 @@ - - - --int yaffs_ReadChunkWithTagsFromNAND(yaffs_Device * dev, int chunkInNAND, -- __u8 * buffer, -- yaffs_ExtendedTags * tags); -- --int yaffs_WriteChunkWithTagsToNAND(yaffs_Device * dev, -- int chunkInNAND, -- const __u8 * buffer, -- yaffs_ExtendedTags * tags); -- --int yaffs_MarkBlockBad(yaffs_Device * dev, int blockNo); -- --int yaffs_QueryInitialBlockState(yaffs_Device * dev, -- int blockNo, -- yaffs_BlockState * state, -- unsigned *sequenceNumber); -+int yaffs_ReadChunkWithTagsFromNAND(yaffs_Device *dev, int chunkInNAND, -+ __u8 *buffer, -+ yaffs_ExtendedTags *tags); -+ -+int yaffs_WriteChunkWithTagsToNAND(yaffs_Device *dev, -+ int chunkInNAND, -+ const __u8 *buffer, -+ yaffs_ExtendedTags *tags); -+ -+int yaffs_MarkBlockBad(yaffs_Device *dev, int blockNo); -+ -+int yaffs_QueryInitialBlockState(yaffs_Device *dev, -+ int blockNo, -+ yaffs_BlockState *state, -+ unsigned *sequenceNumber); - - int yaffs_EraseBlockInNAND(struct yaffs_DeviceStruct *dev, - int blockInNAND); ---- a/fs/yaffs2/yaffs_packedtags1.c -+++ b/fs/yaffs2/yaffs_packedtags1.c -@@ -14,7 +14,7 @@ - #include "yaffs_packedtags1.h" - #include "yportenv.h" - --void yaffs_PackTags1(yaffs_PackedTags1 * pt, const yaffs_ExtendedTags * t) -+void yaffs_PackTags1(yaffs_PackedTags1 *pt, const yaffs_ExtendedTags *t) - { - pt->chunkId = t->chunkId; - pt->serialNumber = t->serialNumber; -@@ -27,7 +27,7 @@ void yaffs_PackTags1(yaffs_PackedTags1 * - - } - --void yaffs_UnpackTags1(yaffs_ExtendedTags * t, const yaffs_PackedTags1 * pt) -+void yaffs_UnpackTags1(yaffs_ExtendedTags *t, const yaffs_PackedTags1 *pt) - { - static const __u8 allFF[] = - { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, -@@ -35,9 +35,8 @@ void yaffs_UnpackTags1(yaffs_ExtendedTag - - if (memcmp(allFF, pt, sizeof(yaffs_PackedTags1))) { - t->blockBad = 0; -- if (pt->shouldBeFF != 0xFFFFFFFF) { -+ if (pt->shouldBeFF != 0xFFFFFFFF) - t->blockBad = 1; -- } - t->chunkUsed = 1; - t->objectId = pt->objectId; - t->chunkId = pt->chunkId; -@@ -47,6 +46,5 @@ void yaffs_UnpackTags1(yaffs_ExtendedTag - t->serialNumber = pt->serialNumber; - } else { - memset(t, 0, sizeof(yaffs_ExtendedTags)); -- - } - } ---- a/fs/yaffs2/yaffs_packedtags1.h -+++ b/fs/yaffs2/yaffs_packedtags1.h -@@ -32,6 +32,6 @@ typedef struct { - - } yaffs_PackedTags1; - --void yaffs_PackTags1(yaffs_PackedTags1 * pt, const yaffs_ExtendedTags * t); --void yaffs_UnpackTags1(yaffs_ExtendedTags * t, const yaffs_PackedTags1 * pt); -+void yaffs_PackTags1(yaffs_PackedTags1 *pt, const yaffs_ExtendedTags *t); -+void yaffs_UnpackTags1(yaffs_ExtendedTags *t, const yaffs_PackedTags1 *pt); - #endif ---- a/fs/yaffs2/yaffs_packedtags2.c -+++ b/fs/yaffs2/yaffs_packedtags2.c -@@ -37,60 +37,68 @@ - #define EXTRA_OBJECT_TYPE_SHIFT (28) - #define EXTRA_OBJECT_TYPE_MASK ((0x0F) << EXTRA_OBJECT_TYPE_SHIFT) - --static void yaffs_DumpPackedTags2(const yaffs_PackedTags2 * pt) -+ -+static void yaffs_DumpPackedTags2TagsPart(const yaffs_PackedTags2TagsPart *ptt) - { - T(YAFFS_TRACE_MTD, - (TSTR("packed tags obj %d chunk %d byte %d seq %d" TENDSTR), -- pt->t.objectId, pt->t.chunkId, pt->t.byteCount, -- pt->t.sequenceNumber)); -+ ptt->objectId, ptt->chunkId, ptt->byteCount, -+ ptt->sequenceNumber)); -+} -+static void yaffs_DumpPackedTags2(const yaffs_PackedTags2 *pt) -+{ -+ yaffs_DumpPackedTags2TagsPart(&pt->t); - } - --static void yaffs_DumpTags2(const yaffs_ExtendedTags * t) -+static void yaffs_DumpTags2(const yaffs_ExtendedTags *t) - { - T(YAFFS_TRACE_MTD, - (TSTR -- ("ext.tags eccres %d blkbad %d chused %d obj %d chunk%d byte " -- "%d del %d ser %d seq %d" -+ ("ext.tags eccres %d blkbad %d chused %d obj %d chunk%d byte %d del %d ser %d seq %d" - TENDSTR), t->eccResult, t->blockBad, t->chunkUsed, t->objectId, - t->chunkId, t->byteCount, t->chunkDeleted, t->serialNumber, - t->sequenceNumber)); - - } - --void yaffs_PackTags2(yaffs_PackedTags2 * pt, const yaffs_ExtendedTags * t) -+void yaffs_PackTags2TagsPart(yaffs_PackedTags2TagsPart *ptt, -+ const yaffs_ExtendedTags *t) - { -- pt->t.chunkId = t->chunkId; -- pt->t.sequenceNumber = t->sequenceNumber; -- pt->t.byteCount = t->byteCount; -- pt->t.objectId = t->objectId; -+ ptt->chunkId = t->chunkId; -+ ptt->sequenceNumber = t->sequenceNumber; -+ ptt->byteCount = t->byteCount; -+ ptt->objectId = t->objectId; - - if (t->chunkId == 0 && t->extraHeaderInfoAvailable) { - /* Store the extra header info instead */ - /* We save the parent object in the chunkId */ -- pt->t.chunkId = EXTRA_HEADER_INFO_FLAG -+ ptt->chunkId = EXTRA_HEADER_INFO_FLAG - | t->extraParentObjectId; -- if (t->extraIsShrinkHeader) { -- pt->t.chunkId |= EXTRA_SHRINK_FLAG; -- } -- if (t->extraShadows) { -- pt->t.chunkId |= EXTRA_SHADOWS_FLAG; -- } -+ if (t->extraIsShrinkHeader) -+ ptt->chunkId |= EXTRA_SHRINK_FLAG; -+ if (t->extraShadows) -+ ptt->chunkId |= EXTRA_SHADOWS_FLAG; - -- pt->t.objectId &= ~EXTRA_OBJECT_TYPE_MASK; -- pt->t.objectId |= -+ ptt->objectId &= ~EXTRA_OBJECT_TYPE_MASK; -+ ptt->objectId |= - (t->extraObjectType << EXTRA_OBJECT_TYPE_SHIFT); - -- if (t->extraObjectType == YAFFS_OBJECT_TYPE_HARDLINK) { -- pt->t.byteCount = t->extraEquivalentObjectId; -- } else if (t->extraObjectType == YAFFS_OBJECT_TYPE_FILE) { -- pt->t.byteCount = t->extraFileLength; -- } else { -- pt->t.byteCount = 0; -- } -+ if (t->extraObjectType == YAFFS_OBJECT_TYPE_HARDLINK) -+ ptt->byteCount = t->extraEquivalentObjectId; -+ else if (t->extraObjectType == YAFFS_OBJECT_TYPE_FILE) -+ ptt->byteCount = t->extraFileLength; -+ else -+ ptt->byteCount = 0; - } - -- yaffs_DumpPackedTags2(pt); -+ yaffs_DumpPackedTags2TagsPart(ptt); - yaffs_DumpTags2(t); -+} -+ -+ -+void yaffs_PackTags2(yaffs_PackedTags2 *pt, const yaffs_ExtendedTags *t) -+{ -+ yaffs_PackTags2TagsPart(&pt->t, t); - - #ifndef YAFFS_IGNORE_TAGS_ECC - { -@@ -101,82 +109,98 @@ void yaffs_PackTags2(yaffs_PackedTags2 * - #endif - } - --void yaffs_UnpackTags2(yaffs_ExtendedTags * t, yaffs_PackedTags2 * pt) -+ -+void yaffs_UnpackTags2TagsPart(yaffs_ExtendedTags *t, -+ yaffs_PackedTags2TagsPart *ptt) - { - - memset(t, 0, sizeof(yaffs_ExtendedTags)); - - yaffs_InitialiseTags(t); - -- if (pt->t.sequenceNumber != 0xFFFFFFFF) { -- /* Page is in use */ --#ifdef YAFFS_IGNORE_TAGS_ECC -- { -- t->eccResult = YAFFS_ECC_RESULT_NO_ERROR; -- } --#else -- { -- yaffs_ECCOther ecc; -- int result; -- yaffs_ECCCalculateOther((unsigned char *)&pt->t, -- sizeof -- (yaffs_PackedTags2TagsPart), -- &ecc); -- result = -- yaffs_ECCCorrectOther((unsigned char *)&pt->t, -- sizeof -- (yaffs_PackedTags2TagsPart), -- &pt->ecc, &ecc); -- switch(result){ -- case 0: -- t->eccResult = YAFFS_ECC_RESULT_NO_ERROR; -- break; -- case 1: -- t->eccResult = YAFFS_ECC_RESULT_FIXED; -- break; -- case -1: -- t->eccResult = YAFFS_ECC_RESULT_UNFIXED; -- break; -- default: -- t->eccResult = YAFFS_ECC_RESULT_UNKNOWN; -- } -- } --#endif -+ if (ptt->sequenceNumber != 0xFFFFFFFF) { - t->blockBad = 0; - t->chunkUsed = 1; -- t->objectId = pt->t.objectId; -- t->chunkId = pt->t.chunkId; -- t->byteCount = pt->t.byteCount; -+ t->objectId = ptt->objectId; -+ t->chunkId = ptt->chunkId; -+ t->byteCount = ptt->byteCount; - t->chunkDeleted = 0; - t->serialNumber = 0; -- t->sequenceNumber = pt->t.sequenceNumber; -+ t->sequenceNumber = ptt->sequenceNumber; - - /* Do extra header info stuff */ - -- if (pt->t.chunkId & EXTRA_HEADER_INFO_FLAG) { -+ if (ptt->chunkId & EXTRA_HEADER_INFO_FLAG) { - t->chunkId = 0; - t->byteCount = 0; - - t->extraHeaderInfoAvailable = 1; - t->extraParentObjectId = -- pt->t.chunkId & (~(ALL_EXTRA_FLAGS)); -+ ptt->chunkId & (~(ALL_EXTRA_FLAGS)); - t->extraIsShrinkHeader = -- (pt->t.chunkId & EXTRA_SHRINK_FLAG) ? 1 : 0; -+ (ptt->chunkId & EXTRA_SHRINK_FLAG) ? 1 : 0; - t->extraShadows = -- (pt->t.chunkId & EXTRA_SHADOWS_FLAG) ? 1 : 0; -+ (ptt->chunkId & EXTRA_SHADOWS_FLAG) ? 1 : 0; - t->extraObjectType = -- pt->t.objectId >> EXTRA_OBJECT_TYPE_SHIFT; -+ ptt->objectId >> EXTRA_OBJECT_TYPE_SHIFT; - t->objectId &= ~EXTRA_OBJECT_TYPE_MASK; - -- if (t->extraObjectType == YAFFS_OBJECT_TYPE_HARDLINK) { -- t->extraEquivalentObjectId = pt->t.byteCount; -- } else { -- t->extraFileLength = pt->t.byteCount; -+ if (t->extraObjectType == YAFFS_OBJECT_TYPE_HARDLINK) -+ t->extraEquivalentObjectId = ptt->byteCount; -+ else -+ t->extraFileLength = ptt->byteCount; -+ } -+ } -+ -+ yaffs_DumpPackedTags2TagsPart(ptt); -+ yaffs_DumpTags2(t); -+ -+} -+ -+ -+void yaffs_UnpackTags2(yaffs_ExtendedTags *t, yaffs_PackedTags2 *pt) -+{ -+ -+ yaffs_ECCResult eccResult = YAFFS_ECC_RESULT_NO_ERROR; -+ -+ if (pt->t.sequenceNumber != 0xFFFFFFFF) { -+ /* Page is in use */ -+#ifndef YAFFS_IGNORE_TAGS_ECC -+ { -+ yaffs_ECCOther ecc; -+ int result; -+ yaffs_ECCCalculateOther((unsigned char *)&pt->t, -+ sizeof -+ (yaffs_PackedTags2TagsPart), -+ &ecc); -+ result = -+ yaffs_ECCCorrectOther((unsigned char *)&pt->t, -+ sizeof -+ (yaffs_PackedTags2TagsPart), -+ &pt->ecc, &ecc); -+ switch (result) { -+ case 0: -+ eccResult = YAFFS_ECC_RESULT_NO_ERROR; -+ break; -+ case 1: -+ eccResult = YAFFS_ECC_RESULT_FIXED; -+ break; -+ case -1: -+ eccResult = YAFFS_ECC_RESULT_UNFIXED; -+ break; -+ default: -+ eccResult = YAFFS_ECC_RESULT_UNKNOWN; - } - } -+#endif - } - -+ yaffs_UnpackTags2TagsPart(t, &pt->t); -+ -+ t->eccResult = eccResult; -+ - yaffs_DumpPackedTags2(pt); - yaffs_DumpTags2(t); - - } -+ ---- a/fs/yaffs2/yaffs_packedtags2.h -+++ b/fs/yaffs2/yaffs_packedtags2.h -@@ -33,6 +33,11 @@ typedef struct { - yaffs_ECCOther ecc; - } yaffs_PackedTags2; - --void yaffs_PackTags2(yaffs_PackedTags2 * pt, const yaffs_ExtendedTags * t); --void yaffs_UnpackTags2(yaffs_ExtendedTags * t, yaffs_PackedTags2 * pt); -+/* Full packed tags with ECC, used for oob tags */ -+void yaffs_PackTags2(yaffs_PackedTags2 *pt, const yaffs_ExtendedTags *t); -+void yaffs_UnpackTags2(yaffs_ExtendedTags *t, yaffs_PackedTags2 *pt); -+ -+/* Only the tags part (no ECC for use with inband tags */ -+void yaffs_PackTags2TagsPart(yaffs_PackedTags2TagsPart *pt, const yaffs_ExtendedTags *t); -+void yaffs_UnpackTags2TagsPart(yaffs_ExtendedTags *t, yaffs_PackedTags2TagsPart *pt); - #endif ---- a/fs/yaffs2/yaffs_qsort.c -+++ b/fs/yaffs2/yaffs_qsort.c -@@ -28,12 +28,12 @@ - */ - - #include "yportenv.h" --//#include -+/* #include */ - - /* - * Qsort routine from Bentley & McIlroy's "Engineering a Sort Function". - */ --#define swapcode(TYPE, parmi, parmj, n) { \ -+#define swapcode(TYPE, parmi, parmj, n) do { \ - long i = (n) / sizeof (TYPE); \ - register TYPE *pi = (TYPE *) (parmi); \ - register TYPE *pj = (TYPE *) (parmj); \ -@@ -41,28 +41,29 @@ - register TYPE t = *pi; \ - *pi++ = *pj; \ - *pj++ = t; \ -- } while (--i > 0); \ --} -+ } while (--i > 0); \ -+} while (0) - - #define SWAPINIT(a, es) swaptype = ((char *)a - (char *)0) % sizeof(long) || \ -- es % sizeof(long) ? 2 : es == sizeof(long)? 0 : 1; -+ es % sizeof(long) ? 2 : es == sizeof(long) ? 0 : 1; - - static __inline void - swapfunc(char *a, char *b, int n, int swaptype) - { - if (swaptype <= 1) -- swapcode(long, a, b, n) -+ swapcode(long, a, b, n); - else -- swapcode(char, a, b, n) -+ swapcode(char, a, b, n); - } - --#define swap(a, b) \ -+#define yswap(a, b) do { \ - if (swaptype == 0) { \ - long t = *(long *)(a); \ - *(long *)(a) = *(long *)(b); \ - *(long *)(b) = t; \ - } else \ -- swapfunc(a, b, es, swaptype) -+ swapfunc(a, b, es, swaptype); \ -+} while (0) - - #define vecswap(a, b, n) if ((n) > 0) swapfunc(a, b, n, swaptype) - -@@ -70,12 +71,12 @@ static __inline char * - med3(char *a, char *b, char *c, int (*cmp)(const void *, const void *)) - { - return cmp(a, b) < 0 ? -- (cmp(b, c) < 0 ? b : (cmp(a, c) < 0 ? c : a )) -- :(cmp(b, c) > 0 ? b : (cmp(a, c) < 0 ? a : c )); -+ (cmp(b, c) < 0 ? b : (cmp(a, c) < 0 ? c : a)) -+ : (cmp(b, c) > 0 ? b : (cmp(a, c) < 0 ? a : c)); - } - - #ifndef min --#define min(a,b) (((a) < (b)) ? (a) : (b)) -+#define min(a, b) (((a) < (b)) ? (a) : (b)) - #endif - - void -@@ -92,7 +93,7 @@ loop: SWAPINIT(a, es); - for (pm = (char *)a + es; pm < (char *) a + n * es; pm += es) - for (pl = pm; pl > (char *) a && cmp(pl - es, pl) > 0; - pl -= es) -- swap(pl, pl - es); -+ yswap(pl, pl - es); - return; - } - pm = (char *)a + (n / 2) * es; -@@ -107,7 +108,7 @@ loop: SWAPINIT(a, es); - } - pm = med3(pl, pm, pn, cmp); - } -- swap(a, pm); -+ yswap(a, pm); - pa = pb = (char *)a + es; - - pc = pd = (char *)a + (n - 1) * es; -@@ -115,7 +116,7 @@ loop: SWAPINIT(a, es); - while (pb <= pc && (r = cmp(pb, a)) <= 0) { - if (r == 0) { - swap_cnt = 1; -- swap(pa, pb); -+ yswap(pa, pb); - pa += es; - } - pb += es; -@@ -123,14 +124,14 @@ loop: SWAPINIT(a, es); - while (pb <= pc && (r = cmp(pc, a)) >= 0) { - if (r == 0) { - swap_cnt = 1; -- swap(pc, pd); -+ yswap(pc, pd); - pd -= es; - } - pc -= es; - } - if (pb > pc) - break; -- swap(pb, pc); -+ yswap(pb, pc); - swap_cnt = 1; - pb += es; - pc -= es; -@@ -139,7 +140,7 @@ loop: SWAPINIT(a, es); - for (pm = (char *) a + es; pm < (char *) a + n * es; pm += es) - for (pl = pm; pl > (char *) a && cmp(pl - es, pl) > 0; - pl -= es) -- swap(pl, pl - es); -+ yswap(pl, pl - es); - return; - } - -@@ -148,9 +149,11 @@ loop: SWAPINIT(a, es); - vecswap(a, pb - r, r); - r = min((long)(pd - pc), (long)(pn - pd - es)); - vecswap(pb, pn - r, r); -- if ((r = pb - pa) > es) -+ r = pb - pa; -+ if (r > es) - yaffs_qsort(a, r / es, es, cmp); -- if ((r = pd - pc) > es) { -+ r = pd - pc; -+ if (r > es) { - /* Iterate rather than recurse to save stack space */ - a = pn - r; - n = r / es; ---- a/fs/yaffs2/yaffs_qsort.h -+++ b/fs/yaffs2/yaffs_qsort.h -@@ -17,7 +17,7 @@ - #ifndef __YAFFS_QSORT_H__ - #define __YAFFS_QSORT_H__ - --extern void yaffs_qsort (void *const base, size_t total_elems, size_t size, -- int (*cmp)(const void *, const void *)); -+extern void yaffs_qsort(void *const base, size_t total_elems, size_t size, -+ int (*cmp)(const void *, const void *)); - - #endif ---- a/fs/yaffs2/yaffs_tagscompat.c -+++ b/fs/yaffs2/yaffs_tagscompat.c -@@ -14,16 +14,17 @@ - #include "yaffs_guts.h" - #include "yaffs_tagscompat.h" - #include "yaffs_ecc.h" -+#include "yaffs_getblockinfo.h" - --static void yaffs_HandleReadDataError(yaffs_Device * dev, int chunkInNAND); -+static void yaffs_HandleReadDataError(yaffs_Device *dev, int chunkInNAND); - #ifdef NOTYET --static void yaffs_CheckWrittenBlock(yaffs_Device * dev, int chunkInNAND); --static void yaffs_HandleWriteChunkOk(yaffs_Device * dev, int chunkInNAND, -- const __u8 * data, -- const yaffs_Spare * spare); --static void yaffs_HandleUpdateChunk(yaffs_Device * dev, int chunkInNAND, -- const yaffs_Spare * spare); --static void yaffs_HandleWriteChunkError(yaffs_Device * dev, int chunkInNAND); -+static void yaffs_CheckWrittenBlock(yaffs_Device *dev, int chunkInNAND); -+static void yaffs_HandleWriteChunkOk(yaffs_Device *dev, int chunkInNAND, -+ const __u8 *data, -+ const yaffs_Spare *spare); -+static void yaffs_HandleUpdateChunk(yaffs_Device *dev, int chunkInNAND, -+ const yaffs_Spare *spare); -+static void yaffs_HandleWriteChunkError(yaffs_Device *dev, int chunkInNAND); - #endif - - static const char yaffs_countBitsTable[256] = { -@@ -54,13 +55,13 @@ int yaffs_CountBits(__u8 x) - - /********** Tags ECC calculations *********/ - --void yaffs_CalcECC(const __u8 * data, yaffs_Spare * spare) -+void yaffs_CalcECC(const __u8 *data, yaffs_Spare *spare) - { - yaffs_ECCCalculate(data, spare->ecc1); - yaffs_ECCCalculate(&data[256], spare->ecc2); - } - --void yaffs_CalcTagsECC(yaffs_Tags * tags) -+void yaffs_CalcTagsECC(yaffs_Tags *tags) - { - /* Calculate an ecc */ - -@@ -74,9 +75,8 @@ void yaffs_CalcTagsECC(yaffs_Tags * tags - for (i = 0; i < 8; i++) { - for (j = 1; j & 0xff; j <<= 1) { - bit++; -- if (b[i] & j) { -+ if (b[i] & j) - ecc ^= bit; -- } - } - } - -@@ -84,7 +84,7 @@ void yaffs_CalcTagsECC(yaffs_Tags * tags - - } - --int yaffs_CheckECCOnTags(yaffs_Tags * tags) -+int yaffs_CheckECCOnTags(yaffs_Tags *tags) - { - unsigned ecc = tags->ecc; - -@@ -115,8 +115,8 @@ int yaffs_CheckECCOnTags(yaffs_Tags * ta - - /********** Tags **********/ - --static void yaffs_LoadTagsIntoSpare(yaffs_Spare * sparePtr, -- yaffs_Tags * tagsPtr) -+static void yaffs_LoadTagsIntoSpare(yaffs_Spare *sparePtr, -+ yaffs_Tags *tagsPtr) - { - yaffs_TagsUnion *tu = (yaffs_TagsUnion *) tagsPtr; - -@@ -132,8 +132,8 @@ static void yaffs_LoadTagsIntoSpare(yaff - sparePtr->tagByte7 = tu->asBytes[7]; - } - --static void yaffs_GetTagsFromSpare(yaffs_Device * dev, yaffs_Spare * sparePtr, -- yaffs_Tags * tagsPtr) -+static void yaffs_GetTagsFromSpare(yaffs_Device *dev, yaffs_Spare *sparePtr, -+ yaffs_Tags *tagsPtr) - { - yaffs_TagsUnion *tu = (yaffs_TagsUnion *) tagsPtr; - int result; -@@ -148,21 +148,20 @@ static void yaffs_GetTagsFromSpare(yaffs - tu->asBytes[7] = sparePtr->tagByte7; - - result = yaffs_CheckECCOnTags(tagsPtr); -- if (result > 0) { -+ if (result > 0) - dev->tagsEccFixed++; -- } else if (result < 0) { -+ else if (result < 0) - dev->tagsEccUnfixed++; -- } - } - --static void yaffs_SpareInitialise(yaffs_Spare * spare) -+static void yaffs_SpareInitialise(yaffs_Spare *spare) - { - memset(spare, 0xFF, sizeof(yaffs_Spare)); - } - - static int yaffs_WriteChunkToNAND(struct yaffs_DeviceStruct *dev, -- int chunkInNAND, const __u8 * data, -- yaffs_Spare * spare) -+ int chunkInNAND, const __u8 *data, -+ yaffs_Spare *spare) - { - if (chunkInNAND < dev->startBlock * dev->nChunksPerBlock) { - T(YAFFS_TRACE_ERROR, -@@ -177,9 +176,9 @@ static int yaffs_WriteChunkToNAND(struct - - static int yaffs_ReadChunkFromNAND(struct yaffs_DeviceStruct *dev, - int chunkInNAND, -- __u8 * data, -- yaffs_Spare * spare, -- yaffs_ECCResult * eccResult, -+ __u8 *data, -+ yaffs_Spare *spare, -+ yaffs_ECCResult *eccResult, - int doErrorCorrection) - { - int retVal; -@@ -252,9 +251,11 @@ static int yaffs_ReadChunkFromNAND(struc - /* Must allocate enough memory for spare+2*sizeof(int) */ - /* for ecc results from device. */ - struct yaffs_NANDSpare nspare; -- retVal = -- dev->readChunkFromNAND(dev, chunkInNAND, data, -- (yaffs_Spare *) & nspare); -+ -+ memset(&nspare, 0, sizeof(nspare)); -+ -+ retVal = dev->readChunkFromNAND(dev, chunkInNAND, data, -+ (yaffs_Spare *) &nspare); - memcpy(spare, &nspare, sizeof(yaffs_Spare)); - if (data && doErrorCorrection) { - if (nspare.eccres1 > 0) { -@@ -302,8 +303,7 @@ static int yaffs_ReadChunkFromNAND(struc - static int yaffs_CheckChunkErased(struct yaffs_DeviceStruct *dev, - int chunkInNAND) - { -- -- static int init = 0; -+ static int init; - static __u8 cmpbuf[YAFFS_BYTES_PER_CHUNK]; - static __u8 data[YAFFS_BYTES_PER_CHUNK]; - /* Might as well always allocate the larger size for */ -@@ -331,12 +331,12 @@ static int yaffs_CheckChunkErased(struct - * Functions for robustisizing - */ - --static void yaffs_HandleReadDataError(yaffs_Device * dev, int chunkInNAND) -+static void yaffs_HandleReadDataError(yaffs_Device *dev, int chunkInNAND) - { - int blockInNAND = chunkInNAND / dev->nChunksPerBlock; - - /* Mark the block for retirement */ -- yaffs_GetBlockInfo(dev, blockInNAND)->needsRetiring = 1; -+ yaffs_GetBlockInfo(dev, blockInNAND + dev->blockOffset)->needsRetiring = 1; - T(YAFFS_TRACE_ERROR | YAFFS_TRACE_BAD_BLOCKS, - (TSTR("**>>Block %d marked for retirement" TENDSTR), blockInNAND)); - -@@ -348,22 +348,22 @@ static void yaffs_HandleReadDataError(ya - } - - #ifdef NOTYET --static void yaffs_CheckWrittenBlock(yaffs_Device * dev, int chunkInNAND) -+static void yaffs_CheckWrittenBlock(yaffs_Device *dev, int chunkInNAND) - { - } - --static void yaffs_HandleWriteChunkOk(yaffs_Device * dev, int chunkInNAND, -- const __u8 * data, -- const yaffs_Spare * spare) -+static void yaffs_HandleWriteChunkOk(yaffs_Device *dev, int chunkInNAND, -+ const __u8 *data, -+ const yaffs_Spare *spare) - { - } - --static void yaffs_HandleUpdateChunk(yaffs_Device * dev, int chunkInNAND, -- const yaffs_Spare * spare) -+static void yaffs_HandleUpdateChunk(yaffs_Device *dev, int chunkInNAND, -+ const yaffs_Spare *spare) - { - } - --static void yaffs_HandleWriteChunkError(yaffs_Device * dev, int chunkInNAND) -+static void yaffs_HandleWriteChunkError(yaffs_Device *dev, int chunkInNAND) - { - int blockInNAND = chunkInNAND / dev->nChunksPerBlock; - -@@ -373,8 +373,8 @@ static void yaffs_HandleWriteChunkError( - yaffs_DeleteChunk(dev, chunkInNAND, 1, __LINE__); - } - --static int yaffs_VerifyCompare(const __u8 * d0, const __u8 * d1, -- const yaffs_Spare * s0, const yaffs_Spare * s1) -+static int yaffs_VerifyCompare(const __u8 *d0, const __u8 *d1, -+ const yaffs_Spare *s0, const yaffs_Spare *s1) - { - - if (memcmp(d0, d1, YAFFS_BYTES_PER_CHUNK) != 0 || -@@ -398,28 +398,35 @@ static int yaffs_VerifyCompare(const __u - } - #endif /* NOTYET */ - --int yaffs_TagsCompatabilityWriteChunkWithTagsToNAND(yaffs_Device * dev, -- int chunkInNAND, -- const __u8 * data, -- const yaffs_ExtendedTags * -- eTags) -+int yaffs_TagsCompatabilityWriteChunkWithTagsToNAND(yaffs_Device *dev, -+ int chunkInNAND, -+ const __u8 *data, -+ const yaffs_ExtendedTags *eTags) - { - yaffs_Spare spare; - yaffs_Tags tags; - - yaffs_SpareInitialise(&spare); - -- if (eTags->chunkDeleted) { -+ if (eTags->chunkDeleted) - spare.pageStatus = 0; -- } else { -+ else { - tags.objectId = eTags->objectId; - tags.chunkId = eTags->chunkId; -- tags.byteCount = eTags->byteCount; -+ -+ tags.byteCountLSB = eTags->byteCount & 0x3ff; -+ -+ if (dev->nDataBytesPerChunk >= 1024) -+ tags.byteCountMSB = (eTags->byteCount >> 10) & 3; -+ else -+ tags.byteCountMSB = 3; -+ -+ - tags.serialNumber = eTags->serialNumber; - -- if (!dev->useNANDECC && data) { -+ if (!dev->useNANDECC && data) - yaffs_CalcECC(data, &spare); -- } -+ - yaffs_LoadTagsIntoSpare(&spare, &tags); - - } -@@ -427,15 +434,15 @@ int yaffs_TagsCompatabilityWriteChunkWit - return yaffs_WriteChunkToNAND(dev, chunkInNAND, data, &spare); - } - --int yaffs_TagsCompatabilityReadChunkWithTagsFromNAND(yaffs_Device * dev, -+int yaffs_TagsCompatabilityReadChunkWithTagsFromNAND(yaffs_Device *dev, - int chunkInNAND, -- __u8 * data, -- yaffs_ExtendedTags * eTags) -+ __u8 *data, -+ yaffs_ExtendedTags *eTags) - { - - yaffs_Spare spare; - yaffs_Tags tags; -- yaffs_ECCResult eccResult; -+ yaffs_ECCResult eccResult = YAFFS_ECC_RESULT_UNKNOWN; - - static yaffs_Spare spareFF; - static int init; -@@ -466,7 +473,11 @@ int yaffs_TagsCompatabilityReadChunkWith - - eTags->objectId = tags.objectId; - eTags->chunkId = tags.chunkId; -- eTags->byteCount = tags.byteCount; -+ eTags->byteCount = tags.byteCountLSB; -+ -+ if (dev->nDataBytesPerChunk >= 1024) -+ eTags->byteCount |= (((unsigned) tags.byteCountMSB) << 10); -+ - eTags->serialNumber = tags.serialNumber; - } - } -@@ -497,9 +508,9 @@ int yaffs_TagsCompatabilityMarkNANDBlock - } - - int yaffs_TagsCompatabilityQueryNANDBlock(struct yaffs_DeviceStruct *dev, -- int blockNo, yaffs_BlockState * -- state, -- int *sequenceNumber) -+ int blockNo, -+ yaffs_BlockState *state, -+ __u32 *sequenceNumber) - { - - yaffs_Spare spare0, spare1; ---- a/fs/yaffs2/yaffs_tagscompat.h -+++ b/fs/yaffs2/yaffs_tagscompat.h -@@ -17,24 +17,23 @@ - #define __YAFFS_TAGSCOMPAT_H__ - - #include "yaffs_guts.h" --int yaffs_TagsCompatabilityWriteChunkWithTagsToNAND(yaffs_Device * dev, -- int chunkInNAND, -- const __u8 * data, -- const yaffs_ExtendedTags * -- tags); --int yaffs_TagsCompatabilityReadChunkWithTagsFromNAND(yaffs_Device * dev, -- int chunkInNAND, -- __u8 * data, -- yaffs_ExtendedTags * -- tags); -+int yaffs_TagsCompatabilityWriteChunkWithTagsToNAND(yaffs_Device *dev, -+ int chunkInNAND, -+ const __u8 *data, -+ const yaffs_ExtendedTags *tags); -+int yaffs_TagsCompatabilityReadChunkWithTagsFromNAND(yaffs_Device *dev, -+ int chunkInNAND, -+ __u8 *data, -+ yaffs_ExtendedTags *tags); - int yaffs_TagsCompatabilityMarkNANDBlockBad(struct yaffs_DeviceStruct *dev, - int blockNo); - int yaffs_TagsCompatabilityQueryNANDBlock(struct yaffs_DeviceStruct *dev, -- int blockNo, yaffs_BlockState * -- state, int *sequenceNumber); -+ int blockNo, -+ yaffs_BlockState *state, -+ __u32 *sequenceNumber); - --void yaffs_CalcTagsECC(yaffs_Tags * tags); --int yaffs_CheckECCOnTags(yaffs_Tags * tags); -+void yaffs_CalcTagsECC(yaffs_Tags *tags); -+int yaffs_CheckECCOnTags(yaffs_Tags *tags); - int yaffs_CountBits(__u8 byte); - - #endif ---- a/fs/yaffs2/yaffs_tagsvalidity.c -+++ b/fs/yaffs2/yaffs_tagsvalidity.c -@@ -13,14 +13,14 @@ - - #include "yaffs_tagsvalidity.h" - --void yaffs_InitialiseTags(yaffs_ExtendedTags * tags) -+void yaffs_InitialiseTags(yaffs_ExtendedTags *tags) - { - memset(tags, 0, sizeof(yaffs_ExtendedTags)); - tags->validMarker0 = 0xAAAAAAAA; - tags->validMarker1 = 0x55555555; - } - --int yaffs_ValidateTags(yaffs_ExtendedTags * tags) -+int yaffs_ValidateTags(yaffs_ExtendedTags *tags) - { - return (tags->validMarker0 == 0xAAAAAAAA && - tags->validMarker1 == 0x55555555); ---- a/fs/yaffs2/yaffs_tagsvalidity.h -+++ b/fs/yaffs2/yaffs_tagsvalidity.h -@@ -19,6 +19,6 @@ - - #include "yaffs_guts.h" - --void yaffs_InitialiseTags(yaffs_ExtendedTags * tags); --int yaffs_ValidateTags(yaffs_ExtendedTags * tags); -+void yaffs_InitialiseTags(yaffs_ExtendedTags *tags); -+int yaffs_ValidateTags(yaffs_ExtendedTags *tags); - #endif ---- a/fs/yaffs2/yportenv.h -+++ b/fs/yaffs2/yportenv.h -@@ -17,17 +17,28 @@ - #ifndef __YPORTENV_H__ - #define __YPORTENV_H__ - -+/* -+ * Define the MTD version in terms of Linux Kernel versions -+ * This allows yaffs to be used independantly of the kernel -+ * as well as with it. -+ */ -+ -+#define MTD_VERSION(a, b, c) (((a) << 16) + ((b) << 8) + (c)) -+ - #if defined CONFIG_YAFFS_WINCE - - #include "ywinceenv.h" - --#elif defined __KERNEL__ -+#elif defined __KERNEL__ - - #include "moduleconfig.h" - - /* Linux kernel */ -+ - #include --#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)) -+#define MTD_VERSION_CODE LINUX_VERSION_CODE -+ -+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19)) - #include - #endif - #include -@@ -40,12 +51,13 @@ - #define YCHAR char - #define YUCHAR unsigned char - #define _Y(x) x --#define yaffs_strcpy(a,b) strcpy(a,b) --#define yaffs_strncpy(a,b,c) strncpy(a,b,c) --#define yaffs_strncmp(a,b,c) strncmp(a,b,c) --#define yaffs_strlen(s) strlen(s) --#define yaffs_sprintf sprintf --#define yaffs_toupper(a) toupper(a) -+#define yaffs_strcat(a, b) strcat(a, b) -+#define yaffs_strcpy(a, b) strcpy(a, b) -+#define yaffs_strncpy(a, b, c) strncpy(a, b, c) -+#define yaffs_strncmp(a, b, c) strncmp(a, b, c) -+#define yaffs_strlen(s) strlen(s) -+#define yaffs_sprintf sprintf -+#define yaffs_toupper(a) toupper(a) - - #define Y_INLINE inline - -@@ -53,19 +65,19 @@ - #define YAFFS_LOSTNFOUND_PREFIX "obj" - - /* #define YPRINTF(x) printk x */ --#define YMALLOC(x) kmalloc(x,GFP_KERNEL) -+#define YMALLOC(x) kmalloc(x, GFP_NOFS) - #define YFREE(x) kfree(x) - #define YMALLOC_ALT(x) vmalloc(x) - #define YFREE_ALT(x) vfree(x) - #define YMALLOC_DMA(x) YMALLOC(x) - --// KR - added for use in scan so processes aren't blocked indefinitely. -+/* KR - added for use in scan so processes aren't blocked indefinitely. */ - #define YYIELD() schedule() - - #define YAFFS_ROOT_MODE 0666 - #define YAFFS_LOSTNFOUND_MODE 0666 - --#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) -+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0)) - #define Y_CURRENT_TIME CURRENT_TIME.tv_sec - #define Y_TIME_CONVERT(x) (x).tv_sec - #else -@@ -73,11 +85,12 @@ - #define Y_TIME_CONVERT(x) (x) - #endif - --#define yaffs_SumCompare(x,y) ((x) == (y)) --#define yaffs_strcmp(a,b) strcmp(a,b) -+#define yaffs_SumCompare(x, y) ((x) == (y)) -+#define yaffs_strcmp(a, b) strcmp(a, b) - - #define TENDSTR "\n" - #define TSTR(x) KERN_WARNING x -+#define TCONT(x) x - #define TOUT(p) printk p - - #define yaffs_trace(mask, fmt, args...) \ -@@ -90,6 +103,8 @@ - - #elif defined CONFIG_YAFFS_DIRECT - -+#define MTD_VERSION_CODE MTD_VERSION(2, 6, 22) -+ - /* Direct interface */ - #include "ydirectenv.h" - -@@ -111,11 +126,12 @@ - #define YCHAR char - #define YUCHAR unsigned char - #define _Y(x) x --#define yaffs_strcpy(a,b) strcpy(a,b) --#define yaffs_strncpy(a,b,c) strncpy(a,b,c) --#define yaffs_strlen(s) strlen(s) --#define yaffs_sprintf sprintf --#define yaffs_toupper(a) toupper(a) -+#define yaffs_strcat(a, b) strcat(a, b) -+#define yaffs_strcpy(a, b) strcpy(a, b) -+#define yaffs_strncpy(a, b, c) strncpy(a, b, c) -+#define yaffs_strlen(s) strlen(s) -+#define yaffs_sprintf sprintf -+#define yaffs_toupper(a) toupper(a) - - #define Y_INLINE inline - -@@ -133,8 +149,8 @@ - #define YAFFS_ROOT_MODE 0666 - #define YAFFS_LOSTNFOUND_MODE 0666 - --#define yaffs_SumCompare(x,y) ((x) == (y)) --#define yaffs_strcmp(a,b) strcmp(a,b) -+#define yaffs_SumCompare(x, y) ((x) == (y)) -+#define yaffs_strcmp(a, b) strcmp(a, b) - - #else - /* Should have specified a configuration type */ -@@ -178,10 +194,10 @@ extern unsigned int yaffs_wr_attempts; - #define YAFFS_TRACE_ALWAYS 0xF0000000 - - --#define T(mask,p) do{ if((mask) & (yaffs_traceMask | YAFFS_TRACE_ALWAYS)) TOUT(p);} while(0) -+#define T(mask, p) do { if ((mask) & (yaffs_traceMask | YAFFS_TRACE_ALWAYS)) TOUT(p); } while (0) - --#ifndef CONFIG_YAFFS_WINCE --#define YBUG() T(YAFFS_TRACE_BUG,(TSTR("==>> yaffs bug: " __FILE__ " %d" TENDSTR),__LINE__)) -+#ifndef YBUG -+#define YBUG() do {T(YAFFS_TRACE_BUG, (TSTR("==>> yaffs bug: " __FILE__ " %d" TENDSTR), __LINE__)); } while (0) - #endif - - #endif diff --git a/target/linux/generic-2.6/patches-2.6.28/512-yaffs-2.6.28.1-fix.patch b/target/linux/generic-2.6/patches-2.6.28/512-yaffs-2.6.28.1-fix.patch deleted file mode 100644 index b80f481f1..000000000 --- a/target/linux/generic-2.6/patches-2.6.28/512-yaffs-2.6.28.1-fix.patch +++ /dev/null @@ -1,11 +0,0 @@ ---- a/fs/yaffs2/yaffs_fs.c -+++ b/fs/yaffs2/yaffs_fs.c -@@ -746,7 +746,7 @@ static int yaffs_write_begin(struct file - - T(YAFFS_TRACE_OS, ("start yaffs_write_begin\n")); - /* Get a page */ --#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 28) -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28) - pg = grab_cache_page_write_begin(mapping, index, flags); - #else - pg = __grab_cache_page(mapping, index); diff --git a/target/linux/generic-2.6/patches-2.6.28/600-phy_extension.patch b/target/linux/generic-2.6/patches-2.6.28/600-phy_extension.patch deleted file mode 100644 index ed81bf36c..000000000 --- a/target/linux/generic-2.6/patches-2.6.28/600-phy_extension.patch +++ /dev/null @@ -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 -@@ -476,6 +476,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); diff --git a/target/linux/generic-2.6/patches-2.6.28/620-phy_adm6996.patch b/target/linux/generic-2.6/patches-2.6.28/620-phy_adm6996.patch deleted file mode 100644 index 7c98a0f51..000000000 --- a/target/linux/generic-2.6/patches-2.6.28/620-phy_adm6996.patch +++ /dev/null @@ -1,24 +0,0 @@ ---- a/drivers/net/phy/Kconfig -+++ b/drivers/net/phy/Kconfig -@@ -66,6 +66,11 @@ config REALTEK_PHY - ---help--- - Supports the Realtek 821x 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_FIXED_PHY) += fixed.o - obj-$(CONFIG_MDIO_BITBANG) += mdio-bitbang.o diff --git a/target/linux/generic-2.6/patches-2.6.28/630-phy_packets.patch b/target/linux/generic-2.6/patches-2.6.28/630-phy_packets.patch deleted file mode 100644 index c85ec7413..000000000 --- a/target/linux/generic-2.6/patches-2.6.28/630-phy_packets.patch +++ /dev/null @@ -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 -@@ -628,6 +628,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()) diff --git a/target/linux/generic-2.6/patches-2.6.28/650-swconfig.patch b/target/linux/generic-2.6/patches-2.6.28/650-swconfig.patch deleted file mode 100644 index 6825037ce..000000000 --- a/target/linux/generic-2.6/patches-2.6.28/650-swconfig.patch +++ /dev/null @@ -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 diff --git a/target/linux/generic-2.6/patches-2.6.28/670-phy_ip175c.patch b/target/linux/generic-2.6/patches-2.6.28/670-phy_ip175c.patch deleted file mode 100644 index 02a5947aa..000000000 --- a/target/linux/generic-2.6/patches-2.6.28/670-phy_ip175c.patch +++ /dev/null @@ -1,23 +0,0 @@ ---- a/drivers/net/phy/Kconfig -+++ b/drivers/net/phy/Kconfig -@@ -77,6 +77,10 @@ config ADM6996_PHY - ---help--- - Currently supports the ADM6996F switch - -+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 -@@ -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_IP175C_PHY) += ip175c.o - obj-$(CONFIG_REALTEK_PHY) += realtek.o - obj-$(CONFIG_FIXED_PHY) += fixed.o - obj-$(CONFIG_MDIO_BITBANG) += mdio-bitbang.o diff --git a/target/linux/generic-2.6/patches-2.6.28/690-phy_rtl8306.patch b/target/linux/generic-2.6/patches-2.6.28/690-phy_rtl8306.patch deleted file mode 100644 index b56d55b45..000000000 --- a/target/linux/generic-2.6/patches-2.6.28/690-phy_rtl8306.patch +++ /dev/null @@ -1,23 +0,0 @@ ---- a/drivers/net/phy/Kconfig -+++ b/drivers/net/phy/Kconfig -@@ -81,6 +81,10 @@ config IP175C_PHY - tristate "Driver for IC+ IP175C/IP178C switches" - select SWCONFIG - -+config RTL8306_PHY -+ tristate "Driver for Realtek RTL8306S 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_IP175C_PHY) += ip175c.o -+obj-$(CONFIG_RTL8306_PHY) += rtl8306.o - obj-$(CONFIG_REALTEK_PHY) += realtek.o - obj-$(CONFIG_FIXED_PHY) += fixed.o - obj-$(CONFIG_MDIO_BITBANG) += mdio-bitbang.o diff --git a/target/linux/generic-2.6/patches-2.6.28/700-rtc7301.patch b/target/linux/generic-2.6/patches-2.6.28/700-rtc7301.patch deleted file mode 100644 index 96929348e..000000000 --- a/target/linux/generic-2.6/patches-2.6.28/700-rtc7301.patch +++ /dev/null @@ -1,250 +0,0 @@ ---- a/drivers/rtc/Kconfig -+++ b/drivers/rtc/Kconfig -@@ -497,6 +497,15 @@ config RTC_DRV_WM8350 - This driver can also be built as a module. If so, the module - will be called "rtc-wm8350". - -+config RTC_DRV_RTC7301 -+ tristate "Epson RTC-7301 SF/DG" -+ help -+ If you say Y here you will get support for the -+ Epson RTC-7301 SF/DG RTC chips. -+ -+ This driver can also be built as a module. If so, the module -+ will be called rtc-7301. -+ - comment "on-CPU RTC drivers" - - config RTC_DRV_OMAP ---- a/drivers/rtc/Makefile -+++ b/drivers/rtc/Makefile -@@ -58,6 +58,7 @@ obj-$(CONFIG_RTC_DRV_R9701) += rtc-r9701 - obj-$(CONFIG_RTC_DRV_RS5C313) += rtc-rs5c313.o - obj-$(CONFIG_RTC_DRV_RS5C348) += rtc-rs5c348.o - obj-$(CONFIG_RTC_DRV_RS5C372) += rtc-rs5c372.o -+obj-$(CONFIG_RTC_DRV_RTC7301) += rtc-rtc7301.o - obj-$(CONFIG_RTC_DRV_RX8581) += rtc-rx8581.o - obj-$(CONFIG_RTC_DRV_S35390A) += rtc-s35390a.o - obj-$(CONFIG_RTC_DRV_S3C) += rtc-s3c.o ---- /dev/null -+++ b/drivers/rtc/rtc-rtc7301.c -@@ -0,0 +1,219 @@ -+/* -+ * Driver for Epson RTC-7301SF/DG -+ * -+ * Copyright (C) 2009 Jose Vasconcellos -+ * -+ * 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 -+#include -+#include -+#include -+#include -+#include -+ -+#define RTC_NAME "rtc7301" -+#define RTC_VERSION "0.1" -+ -+/* Epson RTC-7301 register addresses */ -+#define RTC7301_SEC 0x00 -+#define RTC7301_SEC10 0x01 -+#define RTC7301_MIN 0x02 -+#define RTC7301_MIN10 0x03 -+#define RTC7301_HOUR 0x04 -+#define RTC7301_HOUR10 0x05 -+#define RTC7301_WEEKDAY 0x06 -+#define RTC7301_DAY 0x07 -+#define RTC7301_DAY10 0x08 -+#define RTC7301_MON 0x09 -+#define RTC7301_MON10 0x0A -+#define RTC7301_YEAR 0x0B -+#define RTC7301_YEAR10 0x0C -+#define RTC7301_YEAR100 0x0D -+#define RTC7301_YEAR1000 0x0E -+#define RTC7301_CTRLREG 0x0F -+ -+static uint8_t __iomem *rtc7301_base; -+ -+#define read_reg(offset) (readb(rtc7301_base + offset) & 0xf) -+#define write_reg(offset, data) writeb(data, rtc7301_base + (offset)) -+ -+#define rtc7301_isbusy() (read_reg(RTC7301_CTRLREG) & 1) -+ -+static void rtc7301_init_settings(void) -+{ -+ int i; -+ -+ write_reg(RTC7301_CTRLREG, 2); -+ write_reg(RTC7301_YEAR1000, 2); -+ udelay(122); -+ -+ /* bank 1 */ -+ write_reg(RTC7301_CTRLREG, 6); -+ for (i=0; i<15; i++) -+ write_reg(i, 0); -+ -+ /* bank 2 */ -+ write_reg(RTC7301_CTRLREG, 14); -+ for (i=0; i<15; i++) -+ write_reg(i, 0); -+ write_reg(RTC7301_CTRLREG, 0); -+} -+ -+static int rtc7301_get_datetime(struct device *dev, struct rtc_time *dt) -+{ -+ int cnt; -+ uint8_t buf[16]; -+ -+ cnt = 0; -+ while (rtc7301_isbusy()) { -+ udelay(244); -+ if (cnt++ > 100) { -+ dev_err(dev, "%s: timeout error %x\n", __func__, rtc7301_base[RTC7301_CTRLREG]); -+ return -EIO; -+ } -+ } -+ -+ for (cnt=0; cnt<16; cnt++) -+ buf[cnt] = read_reg(cnt); -+ -+ if (buf[RTC7301_SEC10] & 8) { -+ dev_err(dev, "%s: RTC not set\n", __func__); -+ return -EINVAL; -+ } -+ -+ memset(dt, 0, sizeof(*dt)); -+ -+ dt->tm_sec = buf[RTC7301_SEC] + buf[RTC7301_SEC10]*10; -+ dt->tm_min = buf[RTC7301_MIN] + buf[RTC7301_MIN10]*10; -+ dt->tm_hour = buf[RTC7301_HOUR] + buf[RTC7301_HOUR10]*10; -+ -+ dt->tm_mday = buf[RTC7301_DAY] + buf[RTC7301_DAY10]*10; -+ dt->tm_mon = buf[RTC7301_MON] + buf[RTC7301_MON10]*10 - 1; -+ dt->tm_year = buf[RTC7301_YEAR] + buf[RTC7301_YEAR10]*10 + -+ buf[RTC7301_YEAR100]*100 + -+ ((buf[RTC7301_YEAR1000] & 3)*1000) - 1900; -+ -+ /* the rtc device may contain illegal values on power up -+ * according to the data sheet. make sure they are valid. -+ */ -+ -+ return rtc_valid_tm(dt); -+} -+ -+static int rtc7301_set_datetime(struct device *dev, struct rtc_time *dt) -+{ -+ int data; -+ -+ data = dt->tm_year + 1900; -+ if (data >= 2100 || data < 1900) -+ return -EINVAL; -+ -+ write_reg(RTC7301_CTRLREG, 2); -+ udelay(122); -+ -+ data = bin2bcd(dt->tm_sec); -+ write_reg(RTC7301_SEC, data); -+ write_reg(RTC7301_SEC10, (data >> 4)); -+ -+ data = bin2bcd(dt->tm_min); -+ write_reg(RTC7301_MIN, data ); -+ write_reg(RTC7301_MIN10, (data >> 4)); -+ -+ data = bin2bcd(dt->tm_hour); -+ write_reg(RTC7301_HOUR, data); -+ write_reg(RTC7301_HOUR10, (data >> 4)); -+ -+ data = bin2bcd(dt->tm_mday); -+ write_reg(RTC7301_DAY, data); -+ write_reg(RTC7301_DAY10, (data>> 4)); -+ -+ data = bin2bcd(dt->tm_mon + 1); -+ write_reg(RTC7301_MON, data); -+ write_reg(RTC7301_MON10, (data >> 4)); -+ -+ data = bin2bcd(dt->tm_year % 100); -+ write_reg(RTC7301_YEAR, data); -+ write_reg(RTC7301_YEAR10, (data >> 4)); -+ data = bin2bcd((1900 + dt->tm_year) / 100); -+ write_reg(RTC7301_YEAR100, data); -+ -+ data = bin2bcd(dt->tm_wday); -+ write_reg(RTC7301_WEEKDAY, data); -+ -+ write_reg(RTC7301_CTRLREG, 0); -+ -+ return 0; -+} -+ -+static const struct rtc_class_ops rtc7301_rtc_ops = { -+ .read_time = rtc7301_get_datetime, -+ .set_time = rtc7301_set_datetime, -+}; -+ -+static int __devinit rtc7301_probe(struct platform_device *pdev) -+{ -+ struct rtc_device *rtc; -+ struct resource *res; -+ -+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -+ if (!res) -+ return -ENOENT; -+ -+ rtc7301_base = ioremap_nocache(res->start, 0x1000 /*res->end - res->start + 1*/); -+ if (!rtc7301_base) -+ return -EINVAL; -+ -+ rtc = rtc_device_register(RTC_NAME, &pdev->dev, -+ &rtc7301_rtc_ops, THIS_MODULE); -+ if (IS_ERR(rtc)) { -+ iounmap(rtc7301_base); -+ return PTR_ERR(rtc); -+ } -+ -+ platform_set_drvdata(pdev, rtc); -+ -+ rtc7301_init_settings(); -+ return 0; -+} -+ -+static int __devexit rtc7301_remove(struct platform_device *pdev) -+{ -+ struct rtc_device *rtc = platform_get_drvdata(pdev); -+ -+ if (rtc) -+ rtc_device_unregister(rtc); -+ if (rtc7301_base) -+ iounmap(rtc7301_base); -+ return 0; -+} -+ -+static struct platform_driver rtc7301_driver = { -+ .driver = { -+ .name = RTC_NAME, -+ .owner = THIS_MODULE, -+ }, -+ .probe = rtc7301_probe, -+ .remove = __devexit_p(rtc7301_remove), -+}; -+ -+static __init int rtc7301_init(void) -+{ -+ return platform_driver_register(&rtc7301_driver); -+} -+module_init(rtc7301_init); -+ -+static __exit void rtc7301_exit(void) -+{ -+ platform_driver_unregister(&rtc7301_driver); -+} -+module_exit(rtc7301_exit); -+ -+MODULE_DESCRIPTION("Epson 7301 RTC driver"); -+MODULE_AUTHOR("Jose Vasconcellos "); -+MODULE_LICENSE("GPL"); -+MODULE_ALIAS("platform:" RTC_NAME); -+MODULE_VERSION(RTC_VERSION); diff --git a/target/linux/generic-2.6/patches-2.6.28/801-usb_serial_endpoint_size.patch b/target/linux/generic-2.6/patches-2.6.28/801-usb_serial_endpoint_size.patch deleted file mode 100644 index 827c350f7..000000000 --- a/target/linux/generic-2.6/patches-2.6.28/801-usb_serial_endpoint_size.patch +++ /dev/null @@ -1,25 +0,0 @@ ---- a/drivers/usb/serial/usb-serial.c -+++ b/drivers/usb/serial/usb-serial.c -@@ -59,6 +59,7 @@ static struct usb_driver usb_serial_driv - drivers depend on it. - */ - -+static ushort maxSize = 0; - static int debug; - /* initially all NULL */ - static struct usb_serial *serial_table[SERIAL_TTY_MINORS]; -@@ -839,7 +840,7 @@ int usb_serial_probe(struct usb_interfac - dev_err(&interface->dev, "No free urbs available\n"); - goto probe_error; - } -- buffer_size = le16_to_cpu(endpoint->wMaxPacketSize); -+ buffer_size = (endpoint->wMaxPacketSize > maxSize) ? endpoint->wMaxPacketSize : maxSize; - port->bulk_in_size = buffer_size; - port->bulk_in_endpointAddress = endpoint->bEndpointAddress; - port->bulk_in_buffer = kmalloc(buffer_size, GFP_KERNEL); -@@ -1268,3 +1269,5 @@ MODULE_LICENSE("GPL"); - - module_param(debug, bool, S_IRUGO | S_IWUSR); - MODULE_PARM_DESC(debug, "Debug enabled or not"); -+module_param(maxSize, ushort,0); -+MODULE_PARM_DESC(maxSize,"User specified USB endpoint size"); diff --git a/target/linux/generic-2.6/patches-2.6.28/840-unable_to_open_console.patch b/target/linux/generic-2.6/patches-2.6.28/840-unable_to_open_console.patch deleted file mode 100644 index b109b0e7c..000000000 --- a/target/linux/generic-2.6/patches-2.6.28/840-unable_to_open_console.patch +++ /dev/null @@ -1,11 +0,0 @@ ---- a/init/main.c -+++ b/init/main.c -@@ -801,7 +801,7 @@ static int noinline init_post(void) - numa_default_policy(); - - if (sys_open((const char __user *) "/dev/console", O_RDWR, 0) < 0) -- printk(KERN_WARNING "Warning: unable to open an initial console.\n"); -+ printk(KERN_WARNING "Please be patient, while OpenWrt loads ...\n"); - - (void) sys_dup(0); - (void) sys_dup(0); diff --git a/target/linux/generic-2.6/patches-2.6.28/900-headers_type_and_time.patch b/target/linux/generic-2.6/patches-2.6.28/900-headers_type_and_time.patch deleted file mode 100644 index f21478b08..000000000 --- a/target/linux/generic-2.6/patches-2.6.28/900-headers_type_and_time.patch +++ /dev/null @@ -1,46 +0,0 @@ ---- a/include/linux/time.h -+++ b/include/linux/time.h -@@ -1,6 +1,10 @@ - #ifndef _LINUX_TIME_H - #define _LINUX_TIME_H - -+#ifndef __KERNEL__ -+#include -+#else -+ - #include - - #ifdef __KERNEL__ -@@ -240,4 +244,6 @@ struct itimerval { - */ - #define TIMER_ABSTIME 0x01 - -+#endif /* __KERNEL__ DEBIAN */ -+ - #endif ---- a/include/linux/types.h -+++ b/include/linux/types.h -@@ -1,6 +1,14 @@ - #ifndef _LINUX_TYPES_H - #define _LINUX_TYPES_H - -+/* Debian: Use userland types instead. */ -+#ifndef __KERNEL__ -+# include -+/* For other kernel headers. */ -+# include -+# include -+#else -+ - #ifdef __KERNEL__ - - #define DECLARE_BITMAP(name,bits) \ -@@ -161,6 +169,8 @@ typedef unsigned long blkcnt_t; - - #endif /* __KERNEL_STRICT_NAMES */ - -+#endif /* __KERNEL__ DEBIAN */ -+ - /* - * Below are truly Linux-specific types that should never collide with - * any application/library that wants linux/types.h. diff --git a/target/linux/generic-2.6/patches-2.6.28/902-darwin_scripts_include.patch b/target/linux/generic-2.6/patches-2.6.28/902-darwin_scripts_include.patch deleted file mode 100644 index 4ff153677..000000000 --- a/target/linux/generic-2.6/patches-2.6.28/902-darwin_scripts_include.patch +++ /dev/null @@ -1,102 +0,0 @@ ---- a/scripts/genksyms/parse.c_shipped -+++ b/scripts/genksyms/parse.c_shipped -@@ -160,7 +160,9 @@ - - - #include -+#ifndef __APPLE__ - #include -+#endif - #include "genksyms.h" - - static int is_typedef; ---- a/scripts/genksyms/parse.y -+++ b/scripts/genksyms/parse.y -@@ -24,7 +24,9 @@ - %{ - - #include -+#ifndef __APPLE__ - #include -+#endif - #include "genksyms.h" - - static int is_typedef; ---- a/scripts/kallsyms.c -+++ b/scripts/kallsyms.c -@@ -22,6 +22,35 @@ - #include - #include - #include -+#ifdef __APPLE__ -+/* Darwin has no memmem implementation, this one is ripped of the uClibc-0.9.28 source */ -+void *memmem (const void *haystack, size_t haystack_len, -+ const void *needle, size_t needle_len) -+{ -+ const char *begin; -+ const char *const last_possible -+ = (const char *) haystack + haystack_len - needle_len; -+ -+ if (needle_len == 0) -+ /* The first occurrence of the empty string is deemed to occur at -+ the beginning of the string. */ -+ return (void *) haystack; -+ -+ /* Sanity check, otherwise the loop might search through the whole -+ memory. */ -+ if (__builtin_expect (haystack_len < needle_len, 0)) -+ return NULL; -+ -+ for (begin = (const char *) haystack; begin <= last_possible; ++begin) -+ if (begin[0] == ((const char *) needle)[0] && -+ !memcmp ((const void *) &begin[1], -+ (const void *) ((const char *) needle + 1), -+ needle_len - 1)) -+ return (void *) begin; -+ -+ return NULL; -+} -+#endif - - #define KSYM_NAME_LEN 128 - ---- a/scripts/kconfig/Makefile -+++ b/scripts/kconfig/Makefile -@@ -97,6 +97,9 @@ check-lxdialog := $(srctree)/$(src)/lxd - # we really need to do so. (Do not call gcc as part of make mrproper) - HOST_EXTRACFLAGS = $(shell $(CONFIG_SHELL) $(check-lxdialog) -ccflags) - HOST_LOADLIBES = $(shell $(CONFIG_SHELL) $(check-lxdialog) -ldflags $(HOSTCC)) -+ifeq ($(shell uname -s),Darwin) -+HOST_LOADLIBES += -lncurses -+endif - - HOST_EXTRACFLAGS += -DLOCALE - ---- a/scripts/mod/mk_elfconfig.c -+++ b/scripts/mod/mk_elfconfig.c -@@ -1,7 +1,11 @@ - #include - #include - #include -+#ifndef __APPLE__ - #include -+#else -+#include "../../../../../tools/sstrip/include/elf.h" -+#endif - - int - main(int argc, char **argv) ---- a/scripts/mod/modpost.h -+++ b/scripts/mod/modpost.h -@@ -7,7 +7,11 @@ - #include - #include - #include -+#if !(defined(__APPLE__) || defined(__CYGWIN__)) - #include -+#else -+#include "../../../../../tools/sstrip/include/elf.h" -+#endif - - #include "elfconfig.h" - diff --git a/target/linux/generic-2.6/patches-2.6.28/903-hostap_txpower.patch b/target/linux/generic-2.6/patches-2.6.28/903-hostap_txpower.patch deleted file mode 100644 index 6b4fc9f23..000000000 --- a/target/linux/generic-2.6/patches-2.6.28/903-hostap_txpower.patch +++ /dev/null @@ -1,154 +0,0 @@ ---- a/drivers/net/wireless/hostap/hostap_ap.c -+++ b/drivers/net/wireless/hostap/hostap_ap.c -@@ -2397,13 +2397,13 @@ int prism2_ap_get_sta_qual(local_info_t - addr[count].sa_family = ARPHRD_ETHER; - memcpy(addr[count].sa_data, sta->addr, ETH_ALEN); - if (sta->last_rx_silence == 0) -- qual[count].qual = sta->last_rx_signal < 27 ? -- 0 : (sta->last_rx_signal - 27) * 92 / 127; -+ qual[count].qual = (sta->last_rx_signal - 156) == 0 ? -+ 0 : (sta->last_rx_signal - 156) * 92 / 64; - else -- qual[count].qual = sta->last_rx_signal - -- sta->last_rx_silence - 35; -- qual[count].level = HFA384X_LEVEL_TO_dBm(sta->last_rx_signal); -- qual[count].noise = HFA384X_LEVEL_TO_dBm(sta->last_rx_silence); -+ qual[count].qual = (sta->last_rx_signal - -+ sta->last_rx_silence) * 92 / 64; -+ qual[count].level = sta->last_rx_signal; -+ qual[count].noise = sta->last_rx_silence; - qual[count].updated = sta->last_rx_updated; - - sta->last_rx_updated = IW_QUAL_DBM; -@@ -2469,13 +2469,13 @@ int prism2_ap_translate_scan(struct net_ - memset(&iwe, 0, sizeof(iwe)); - iwe.cmd = IWEVQUAL; - if (sta->last_rx_silence == 0) -- iwe.u.qual.qual = sta->last_rx_signal < 27 ? -- 0 : (sta->last_rx_signal - 27) * 92 / 127; -+ iwe.u.qual.qual = (sta->last_rx_signal -156) == 0 ? -+ 0 : (sta->last_rx_signal - 156) * 92 / 64; - else -- iwe.u.qual.qual = sta->last_rx_signal - -- sta->last_rx_silence - 35; -- iwe.u.qual.level = HFA384X_LEVEL_TO_dBm(sta->last_rx_signal); -- iwe.u.qual.noise = HFA384X_LEVEL_TO_dBm(sta->last_rx_silence); -+ iwe.u.qual.qual = (sta->last_rx_signal - -+ sta->last_rx_silence) * 92 / 64; -+ iwe.u.qual.level = sta->last_rx_signal; -+ iwe.u.qual.noise = sta->last_rx_silence; - iwe.u.qual.updated = sta->last_rx_updated; - iwe.len = IW_EV_QUAL_LEN; - current_ev = iwe_stream_add_event(info, current_ev, end_buf, ---- a/drivers/net/wireless/hostap/hostap_config.h -+++ b/drivers/net/wireless/hostap/hostap_config.h -@@ -45,4 +45,9 @@ - */ - /* #define PRISM2_NO_STATION_MODES */ - -+/* Enable TX power Setting functions -+ * (min att = -128 , max att = 127) -+ */ -+#define RAW_TXPOWER_SETTING -+ - #endif /* HOSTAP_CONFIG_H */ ---- a/drivers/net/wireless/hostap/hostap.h -+++ b/drivers/net/wireless/hostap/hostap.h -@@ -90,6 +90,7 @@ extern const struct iw_handler_def hosta - extern const struct ethtool_ops prism2_ethtool_ops; - - int hostap_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd); -+int hostap_restore_power(struct net_device *dev); - - - #endif /* HOSTAP_H */ ---- a/drivers/net/wireless/hostap/hostap_hw.c -+++ b/drivers/net/wireless/hostap/hostap_hw.c -@@ -933,6 +933,7 @@ static int hfa384x_set_rid(struct net_de - prism2_hw_reset(dev); - } - -+ hostap_restore_power(dev); - return res; - } - ---- a/drivers/net/wireless/hostap/hostap_info.c -+++ b/drivers/net/wireless/hostap/hostap_info.c -@@ -434,6 +434,11 @@ static void handle_info_queue_linkstatus - } - - /* Get BSSID if we have a valid AP address */ -+ -+ if ( val == HFA384X_LINKSTATUS_CONNECTED || -+ val == HFA384X_LINKSTATUS_DISCONNECTED ) -+ hostap_restore_power(local->dev); -+ - if (connected) { - netif_carrier_on(local->dev); - netif_carrier_on(local->ddev); ---- a/drivers/net/wireless/hostap/hostap_ioctl.c -+++ b/drivers/net/wireless/hostap/hostap_ioctl.c -@@ -1502,23 +1502,20 @@ static int prism2_txpower_hfa386x_to_dBm - val = 255; - - tmp = val; -- tmp >>= 2; - -- return -12 - tmp; -+ return tmp; - } - - static u16 prism2_txpower_dBm_to_hfa386x(int val) - { - signed char tmp; - -- if (val > 20) -- return 128; -- else if (val < -43) -+ if (val > 127) - return 127; -+ else if (val < -128) -+ return 128; - - tmp = val; -- tmp = -12 - tmp; -- tmp <<= 2; - - return (unsigned char) tmp; - } -@@ -4083,3 +4080,35 @@ int hostap_ioctl(struct net_device *dev, - - return ret; - } -+ -+/* BUG FIX: Restore power setting value when lost due to F/W bug */ -+ -+int hostap_restore_power(struct net_device *dev) -+{ -+ struct hostap_interface *iface = dev->priv; -+ local_info_t *local = iface->local; -+ -+ u16 val; -+ int ret = 0; -+ -+ if (local->txpower_type == PRISM2_TXPOWER_OFF) { -+ val = 0xff; /* use all standby and sleep modes */ -+ ret = local->func->cmd(dev, HFA384X_CMDCODE_WRITEMIF, -+ HFA386X_CR_A_D_TEST_MODES2, -+ &val, NULL); -+ } -+ -+#ifdef RAW_TXPOWER_SETTING -+ if (local->txpower_type == PRISM2_TXPOWER_FIXED) { -+ val = HFA384X_TEST_CFG_BIT_ALC; -+ local->func->cmd(dev, HFA384X_CMDCODE_TEST | -+ (HFA384X_TEST_CFG_BITS << 8), 0, &val, NULL); -+ val = prism2_txpower_dBm_to_hfa386x(local->txpower); -+ ret = (local->func->cmd(dev, HFA384X_CMDCODE_WRITEMIF, -+ HFA386X_CR_MANUAL_TX_POWER, &val, NULL)); -+ } -+#endif /* RAW_TXPOWER_SETTING */ -+ return (ret ? -EOPNOTSUPP : 0); -+} -+ -+EXPORT_SYMBOL(hostap_restore_power); diff --git a/target/linux/generic-2.6/patches-2.6.28/903-stddef_include.patch b/target/linux/generic-2.6/patches-2.6.28/903-stddef_include.patch deleted file mode 100644 index 7fe248d8d..000000000 --- a/target/linux/generic-2.6/patches-2.6.28/903-stddef_include.patch +++ /dev/null @@ -1,17 +0,0 @@ ---- a/include/linux/stddef.h -+++ b/include/linux/stddef.h -@@ -16,6 +16,7 @@ enum { - false = 0, - true = 1 - }; -+#endif /* __KERNEL__ */ - - #undef offsetof - #ifdef __compiler_offsetof -@@ -23,6 +24,5 @@ enum { - #else - #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) - #endif --#endif /* __KERNEL__ */ - - #endif diff --git a/target/linux/generic-2.6/patches-2.6.28/905-i386_build.patch b/target/linux/generic-2.6/patches-2.6.28/905-i386_build.patch deleted file mode 100644 index c701fdaa9..000000000 --- a/target/linux/generic-2.6/patches-2.6.28/905-i386_build.patch +++ /dev/null @@ -1,10 +0,0 @@ ---- a/arch/x86/boot/tools/build.c -+++ b/arch/x86/boot/tools/build.c -@@ -29,7 +29,6 @@ - #include - #include - #include --#include - #include - #include - #include diff --git a/target/linux/generic-2.6/patches-2.6.28/906-unifdef_getline.patch b/target/linux/generic-2.6/patches-2.6.28/906-unifdef_getline.patch deleted file mode 100644 index 2b0f1cfc6..000000000 --- a/target/linux/generic-2.6/patches-2.6.28/906-unifdef_getline.patch +++ /dev/null @@ -1,41 +0,0 @@ ---- a/scripts/unifdef.c -+++ b/scripts/unifdef.c -@@ -206,7 +206,11 @@ static void done(void); - static void error(const char *); - static int findsym(const char *); - static void flushline(bool); --static Linetype getline(void); -+#ifndef __CYGWIN__ -+static Linetype __getline(void); -+#else -+static Linetype get_line(void); -+#endif - static Linetype ifeval(const char **); - static void ignoreoff(void); - static void ignoreon(void); -@@ -512,7 +516,11 @@ process(void) - - for (;;) { - linenum++; -- lineval = getline(); -+#ifndef __CYGWIN__ -+ lineval = __getline(); -+#else -+ lineval = get_line(); -+#endif - trans_table[ifstate[depth]][lineval](); - debug("process %s -> %s depth %d", - linetype_name[lineval], -@@ -526,7 +534,11 @@ process(void) - * help from skipcomment(). - */ - static Linetype --getline(void) -+#ifndef __CYGWIN__ -+__getline(void) -+#else -+get_line(void) -+#endif - { - const char *cp; - int cursym; diff --git a/target/linux/generic-2.6/patches-2.6.28/920-00-spi-gpio.patch b/target/linux/generic-2.6/patches-2.6.28/920-00-spi-gpio.patch deleted file mode 100644 index 960e05a58..000000000 --- a/target/linux/generic-2.6/patches-2.6.28/920-00-spi-gpio.patch +++ /dev/null @@ -1,467 +0,0 @@ -Port of the SPI-GPIO driver from 2.6.29-rc4. - ---mb - - - ---- /dev/null -+++ b/drivers/spi/spi_gpio.c -@@ -0,0 +1,360 @@ -+/* -+ * spi_gpio.c - SPI master driver using generic bitbanged GPIO -+ * -+ * Copyright (C) 2006,2008 David Brownell -+ * -+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA. -+ */ -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+ -+ -+/* -+ * This bitbanging SPI master driver should help make systems usable -+ * when a native hardware SPI engine is not available, perhaps because -+ * its driver isn't yet working or because the I/O pins it requires -+ * are used for other purposes. -+ * -+ * platform_device->driver_data ... points to spi_gpio -+ * -+ * spi->controller_state ... reserved for bitbang framework code -+ * spi->controller_data ... holds chipselect GPIO -+ * -+ * spi->master->dev.driver_data ... points to spi_gpio->bitbang -+ */ -+ -+struct spi_gpio { -+ struct spi_bitbang bitbang; -+ struct spi_gpio_platform_data pdata; -+ struct platform_device *pdev; -+}; -+ -+/*----------------------------------------------------------------------*/ -+ -+/* -+ * Because the overhead of going through four GPIO procedure calls -+ * per transferred bit can make performance a problem, this code -+ * is set up so that you can use it in either of two ways: -+ * -+ * - The slow generic way: set up platform_data to hold the GPIO -+ * numbers used for MISO/MOSI/SCK, and issue procedure calls for -+ * each of them. This driver can handle several such busses. -+ * -+ * - The quicker inlined way: only helps with platform GPIO code -+ * that inlines operations for constant GPIOs. This can give -+ * you tight (fast!) inner loops, but each such bus needs a -+ * new driver. You'll define a new C file, with Makefile and -+ * Kconfig support; the C code can be a total of six lines: -+ * -+ * #define DRIVER_NAME "myboard_spi2" -+ * #define SPI_MISO_GPIO 119 -+ * #define SPI_MOSI_GPIO 120 -+ * #define SPI_SCK_GPIO 121 -+ * #define SPI_N_CHIPSEL 4 -+ * #include "spi_gpio.c" -+ */ -+ -+#ifndef DRIVER_NAME -+#define DRIVER_NAME "spi_gpio" -+ -+#define GENERIC_BITBANG /* vs tight inlines */ -+ -+/* all functions referencing these symbols must define pdata */ -+#define SPI_MISO_GPIO ((pdata)->miso) -+#define SPI_MOSI_GPIO ((pdata)->mosi) -+#define SPI_SCK_GPIO ((pdata)->sck) -+ -+#define SPI_N_CHIPSEL ((pdata)->num_chipselect) -+ -+#endif -+ -+/*----------------------------------------------------------------------*/ -+ -+static inline const struct spi_gpio_platform_data * __pure -+spi_to_pdata(const struct spi_device *spi) -+{ -+ const struct spi_bitbang *bang; -+ const struct spi_gpio *spi_gpio; -+ -+ bang = spi_master_get_devdata(spi->master); -+ spi_gpio = container_of(bang, struct spi_gpio, bitbang); -+ return &spi_gpio->pdata; -+} -+ -+/* this is #defined to avoid unused-variable warnings when inlining */ -+#define pdata spi_to_pdata(spi) -+ -+static inline void setsck(const struct spi_device *spi, int is_on) -+{ -+ gpio_set_value(SPI_SCK_GPIO, is_on); -+} -+ -+static inline void setmosi(const struct spi_device *spi, int is_on) -+{ -+ gpio_set_value(SPI_MOSI_GPIO, is_on); -+} -+ -+static inline int getmiso(const struct spi_device *spi) -+{ -+ return gpio_get_value(SPI_MISO_GPIO); -+} -+ -+#undef pdata -+ -+/* -+ * NOTE: this clocks "as fast as we can". It "should" be a function of the -+ * requested device clock. Software overhead means we usually have trouble -+ * reaching even one Mbit/sec (except when we can inline bitops), so for now -+ * we'll just assume we never need additional per-bit slowdowns. -+ */ -+#define spidelay(nsecs) do {} while (0) -+ -+#define EXPAND_BITBANG_TXRX -+#include -+ -+/* -+ * These functions can leverage inline expansion of GPIO calls to shrink -+ * costs for a txrx bit, often by factors of around ten (by instruction -+ * count). That is particularly visible for larger word sizes, but helps -+ * even with default 8-bit words. -+ * -+ * REVISIT overheads calling these functions for each word also have -+ * significant performance costs. Having txrx_bufs() calls that inline -+ * the txrx_word() logic would help performance, e.g. on larger blocks -+ * used with flash storage or MMC/SD. There should also be ways to make -+ * GCC be less stupid about reloading registers inside the I/O loops, -+ * even without inlined GPIO calls; __attribute__((hot)) on GCC 4.3? -+ */ -+ -+static u32 spi_gpio_txrx_word_mode0(struct spi_device *spi, -+ unsigned nsecs, u32 word, u8 bits) -+{ -+ return bitbang_txrx_be_cpha0(spi, nsecs, 0, word, bits); -+} -+ -+static u32 spi_gpio_txrx_word_mode1(struct spi_device *spi, -+ unsigned nsecs, u32 word, u8 bits) -+{ -+ return bitbang_txrx_be_cpha1(spi, nsecs, 0, word, bits); -+} -+ -+static u32 spi_gpio_txrx_word_mode2(struct spi_device *spi, -+ unsigned nsecs, u32 word, u8 bits) -+{ -+ return bitbang_txrx_be_cpha0(spi, nsecs, 1, word, bits); -+} -+ -+static u32 spi_gpio_txrx_word_mode3(struct spi_device *spi, -+ unsigned nsecs, u32 word, u8 bits) -+{ -+ return bitbang_txrx_be_cpha1(spi, nsecs, 1, word, bits); -+} -+ -+/*----------------------------------------------------------------------*/ -+ -+static void spi_gpio_chipselect(struct spi_device *spi, int is_active) -+{ -+ unsigned long cs = (unsigned long) spi->controller_data; -+ -+ /* set initial clock polarity */ -+ if (is_active) -+ setsck(spi, spi->mode & SPI_CPOL); -+ -+ /* SPI is normally active-low */ -+ gpio_set_value(cs, (spi->mode & SPI_CS_HIGH) ? is_active : !is_active); -+} -+ -+static int spi_gpio_setup(struct spi_device *spi) -+{ -+ unsigned long cs = (unsigned long) spi->controller_data; -+ int status = 0; -+ -+ if (spi->bits_per_word > 32) -+ return -EINVAL; -+ -+ if (!spi->controller_state) { -+ status = gpio_request(cs, spi->dev.bus_id); -+ if (status) -+ return status; -+ status = gpio_direction_output(cs, spi->mode & SPI_CS_HIGH); -+ } -+ if (!status) -+ status = spi_bitbang_setup(spi); -+ if (status) { -+ if (!spi->controller_state) -+ gpio_free(cs); -+ } -+ return status; -+} -+ -+static void spi_gpio_cleanup(struct spi_device *spi) -+{ -+ unsigned long cs = (unsigned long) spi->controller_data; -+ -+ gpio_free(cs); -+ spi_bitbang_cleanup(spi); -+} -+ -+static int __init spi_gpio_alloc(unsigned pin, const char *label, bool is_in) -+{ -+ int value; -+ -+ value = gpio_request(pin, label); -+ if (value == 0) { -+ if (is_in) -+ value = gpio_direction_input(pin); -+ else -+ value = gpio_direction_output(pin, 0); -+ } -+ return value; -+} -+ -+static int __init -+spi_gpio_request(struct spi_gpio_platform_data *pdata, const char *label) -+{ -+ int value; -+ -+ /* NOTE: SPI_*_GPIO symbols may reference "pdata" */ -+ -+ value = spi_gpio_alloc(SPI_MOSI_GPIO, label, false); -+ if (value) -+ goto done; -+ -+ value = spi_gpio_alloc(SPI_MISO_GPIO, label, true); -+ if (value) -+ goto free_mosi; -+ -+ value = spi_gpio_alloc(SPI_SCK_GPIO, label, false); -+ if (value) -+ goto free_miso; -+ -+ goto done; -+ -+free_miso: -+ gpio_free(SPI_MISO_GPIO); -+free_mosi: -+ gpio_free(SPI_MOSI_GPIO); -+done: -+ return value; -+} -+ -+static int __init spi_gpio_probe(struct platform_device *pdev) -+{ -+ int status; -+ struct spi_master *master; -+ struct spi_gpio *spi_gpio; -+ struct spi_gpio_platform_data *pdata; -+ -+ pdata = pdev->dev.platform_data; -+#ifdef GENERIC_BITBANG -+ if (!pdata || !pdata->num_chipselect) -+ return -ENODEV; -+#endif -+ -+ status = spi_gpio_request(pdata, dev_name(&pdev->dev)); -+ if (status < 0) -+ return status; -+ -+ master = spi_alloc_master(&pdev->dev, sizeof *spi_gpio); -+ if (!master) { -+ status = -ENOMEM; -+ goto gpio_free; -+ } -+ spi_gpio = spi_master_get_devdata(master); -+ platform_set_drvdata(pdev, spi_gpio); -+ -+ spi_gpio->pdev = pdev; -+ if (pdata) -+ spi_gpio->pdata = *pdata; -+ -+ master->bus_num = pdev->id; -+ master->num_chipselect = SPI_N_CHIPSEL; -+ master->setup = spi_gpio_setup; -+ master->cleanup = spi_gpio_cleanup; -+ -+ spi_gpio->bitbang.master = spi_master_get(master); -+ spi_gpio->bitbang.chipselect = spi_gpio_chipselect; -+ spi_gpio->bitbang.txrx_word[SPI_MODE_0] = spi_gpio_txrx_word_mode0; -+ spi_gpio->bitbang.txrx_word[SPI_MODE_1] = spi_gpio_txrx_word_mode1; -+ spi_gpio->bitbang.txrx_word[SPI_MODE_2] = spi_gpio_txrx_word_mode2; -+ spi_gpio->bitbang.txrx_word[SPI_MODE_3] = spi_gpio_txrx_word_mode3; -+ spi_gpio->bitbang.setup_transfer = spi_bitbang_setup_transfer; -+ spi_gpio->bitbang.flags = SPI_CS_HIGH; -+ -+ status = spi_bitbang_start(&spi_gpio->bitbang); -+ if (status < 0) { -+ spi_master_put(spi_gpio->bitbang.master); -+gpio_free: -+ gpio_free(SPI_MISO_GPIO); -+ gpio_free(SPI_MOSI_GPIO); -+ gpio_free(SPI_SCK_GPIO); -+ spi_master_put(master); -+ } -+ -+ return status; -+} -+ -+static int __exit spi_gpio_remove(struct platform_device *pdev) -+{ -+ struct spi_gpio *spi_gpio; -+ struct spi_gpio_platform_data *pdata; -+ int status; -+ -+ spi_gpio = platform_get_drvdata(pdev); -+ pdata = pdev->dev.platform_data; -+ -+ /* stop() unregisters child devices too */ -+ status = spi_bitbang_stop(&spi_gpio->bitbang); -+ spi_master_put(spi_gpio->bitbang.master); -+ -+ platform_set_drvdata(pdev, NULL); -+ -+ gpio_free(SPI_MISO_GPIO); -+ gpio_free(SPI_MOSI_GPIO); -+ gpio_free(SPI_SCK_GPIO); -+ -+ return status; -+} -+ -+MODULE_ALIAS("platform:" DRIVER_NAME); -+ -+static struct platform_driver spi_gpio_driver = { -+ .driver.name = DRIVER_NAME, -+ .driver.owner = THIS_MODULE, -+ .remove = __exit_p(spi_gpio_remove), -+}; -+ -+static int __init spi_gpio_init(void) -+{ -+ return platform_driver_probe(&spi_gpio_driver, spi_gpio_probe); -+} -+module_init(spi_gpio_init); -+ -+static void __exit spi_gpio_exit(void) -+{ -+ platform_driver_unregister(&spi_gpio_driver); -+} -+module_exit(spi_gpio_exit); -+ -+ -+MODULE_DESCRIPTION("SPI master driver using generic bitbanged GPIO "); -+MODULE_AUTHOR("David Brownell"); -+MODULE_LICENSE("GPL"); ---- /dev/null -+++ b/include/linux/spi/spi_gpio.h -@@ -0,0 +1,60 @@ -+#ifndef __LINUX_SPI_GPIO_H -+#define __LINUX_SPI_GPIO_H -+ -+/* -+ * For each bitbanged SPI bus, set up a platform_device node with: -+ * - name "spi_gpio" -+ * - id the same as the SPI bus number it implements -+ * - dev.platform data pointing to a struct spi_gpio_platform_data -+ * -+ * Or, see the driver code for information about speedups that are -+ * possible on platforms that support inlined access for GPIOs (no -+ * spi_gpio_platform_data is used). -+ * -+ * Use spi_board_info with these busses in the usual way, being sure -+ * that the controller_data being the GPIO used for each device's -+ * chipselect: -+ * -+ * static struct spi_board_info ... [] = { -+ * ... -+ * // this slave uses GPIO 42 for its chipselect -+ * .controller_data = (void *) 42, -+ * ... -+ * // this one uses GPIO 86 for its chipselect -+ * .controller_data = (void *) 86, -+ * ... -+ * }; -+ * -+ * If the bitbanged bus is later switched to a "native" controller, -+ * that platform_device and controller_data should be removed. -+ */ -+ -+/** -+ * struct spi_gpio_platform_data - parameter for bitbanged SPI master -+ * @sck: number of the GPIO used for clock output -+ * @mosi: number of the GPIO used for Master Output, Slave In (MOSI) data -+ * @miso: number of the GPIO used for Master Input, Slave Output (MISO) data -+ * @num_chipselect: how many slaves to allow -+ * -+ * All GPIO signals used with the SPI bus managed through this driver -+ * (chipselects, MOSI, MISO, SCK) must be configured as GPIOs, instead -+ * of some alternate function. -+ * -+ * It can be convenient to use this driver with pins that have alternate -+ * functions associated with a "native" SPI controller if a driver for that -+ * controller is not available, or is missing important functionality. -+ * -+ * On platforms which can do so, configure MISO with a weak pullup unless -+ * there's an external pullup on that signal. That saves power by avoiding -+ * floating signals. (A weak pulldown would save power too, but many -+ * drivers expect to see all-ones data as the no slave "response".) -+ */ -+struct spi_gpio_platform_data { -+ unsigned sck; -+ unsigned mosi; -+ unsigned miso; -+ -+ u16 num_chipselect; -+}; -+ -+#endif /* __LINUX_SPI_GPIO_H */ ---- a/drivers/spi/Kconfig -+++ b/drivers/spi/Kconfig -@@ -100,6 +100,22 @@ config SPI_BUTTERFLY - inexpensive battery powered microcontroller evaluation board. - This same cable can be used to flash new firmware. - -+config SPI_GPIO -+ tristate "GPIO-based bitbanging SPI Master" -+ depends on GENERIC_GPIO -+ select SPI_BITBANG -+ help -+ This simple GPIO bitbanging SPI master uses the arch-neutral GPIO -+ interface to manage MOSI, MISO, SCK, and chipselect signals. SPI -+ slaves connected to a bus using this driver are configured as usual, -+ except that the spi_board_info.controller_data holds the GPIO number -+ for the chipselect used by this controller driver. -+ -+ Note that this driver often won't achieve even 1 Mbit/sec speeds, -+ making it unusually slow for SPI. If your platform can inline -+ GPIO operations, you should be able to leverage that for better -+ speed with a custom version of this driver; see the source code. -+ - config SPI_IMX - tristate "Freescale iMX SPI controller" - depends on ARCH_IMX && EXPERIMENTAL ---- a/drivers/spi/Makefile -+++ b/drivers/spi/Makefile -@@ -16,6 +16,7 @@ obj-$(CONFIG_SPI_BFIN) += spi_bfin5xx. - obj-$(CONFIG_SPI_BITBANG) += spi_bitbang.o - obj-$(CONFIG_SPI_AU1550) += au1550_spi.o - obj-$(CONFIG_SPI_BUTTERFLY) += spi_butterfly.o -+obj-$(CONFIG_SPI_GPIO) += spi_gpio.o - obj-$(CONFIG_SPI_IMX) += spi_imx.o - obj-$(CONFIG_SPI_LM70_LLP) += spi_lm70llp.o - obj-$(CONFIG_SPI_PXA2XX) += pxa2xx_spi.o diff --git a/target/linux/generic-2.6/patches-2.6.28/920-01-hotpluggable-spi-gpio.patch b/target/linux/generic-2.6/patches-2.6.28/920-01-hotpluggable-spi-gpio.patch deleted file mode 100644 index d67607b27..000000000 --- a/target/linux/generic-2.6/patches-2.6.28/920-01-hotpluggable-spi-gpio.patch +++ /dev/null @@ -1,60 +0,0 @@ -Fix spi-gpio for hotplug. - ---mb - - - ---- a/drivers/spi/spi_gpio.c -+++ b/drivers/spi/spi_gpio.c -@@ -213,7 +213,7 @@ static void spi_gpio_cleanup(struct spi_ - spi_bitbang_cleanup(spi); - } - --static int __init spi_gpio_alloc(unsigned pin, const char *label, bool is_in) -+static int __devinit spi_gpio_alloc(unsigned pin, const char *label, bool is_in) - { - int value; - -@@ -227,7 +227,7 @@ static int __init spi_gpio_alloc(unsigne - return value; - } - --static int __init -+static int __devinit - spi_gpio_request(struct spi_gpio_platform_data *pdata, const char *label) - { - int value; -@@ -256,7 +256,7 @@ done: - return value; - } - --static int __init spi_gpio_probe(struct platform_device *pdev) -+static int __devinit spi_gpio_probe(struct platform_device *pdev) - { - int status; - struct spi_master *master; -@@ -312,7 +312,7 @@ gpio_free: - return status; - } - --static int __exit spi_gpio_remove(struct platform_device *pdev) -+static int __devexit spi_gpio_remove(struct platform_device *pdev) - { - struct spi_gpio *spi_gpio; - struct spi_gpio_platform_data *pdata; -@@ -339,12 +339,13 @@ MODULE_ALIAS("platform:" DRIVER_NAME); - static struct platform_driver spi_gpio_driver = { - .driver.name = DRIVER_NAME, - .driver.owner = THIS_MODULE, -- .remove = __exit_p(spi_gpio_remove), -+ .probe = spi_gpio_probe, -+ .remove = __devexit_p(spi_gpio_remove), - }; - - static int __init spi_gpio_init(void) - { -- return platform_driver_probe(&spi_gpio_driver, spi_gpio_probe); -+ return platform_driver_register(&spi_gpio_driver); - } - module_init(spi_gpio_init); - diff --git a/target/linux/generic-2.6/patches-2.6.28/920-02-spi-gpio-without-cs.patch b/target/linux/generic-2.6/patches-2.6.28/920-02-spi-gpio-without-cs.patch deleted file mode 100644 index 8b2198ef1..000000000 --- a/target/linux/generic-2.6/patches-2.6.28/920-02-spi-gpio-without-cs.patch +++ /dev/null @@ -1,73 +0,0 @@ -Optionally omit the CS signal, if there's only one device on the bus. - ---mb - - - ---- a/drivers/spi/spi_gpio.c -+++ b/drivers/spi/spi_gpio.c -@@ -178,8 +178,10 @@ static void spi_gpio_chipselect(struct s - if (is_active) - setsck(spi, spi->mode & SPI_CPOL); - -- /* SPI is normally active-low */ -- gpio_set_value(cs, (spi->mode & SPI_CS_HIGH) ? is_active : !is_active); -+ if (cs != SPI_GPIO_NO_CHIPSELECT) { -+ /* SPI is normally active-low */ -+ gpio_set_value(cs, (spi->mode & SPI_CS_HIGH) ? is_active : !is_active); -+ } - } - - static int spi_gpio_setup(struct spi_device *spi) -@@ -191,15 +193,17 @@ static int spi_gpio_setup(struct spi_dev - return -EINVAL; - - if (!spi->controller_state) { -- status = gpio_request(cs, spi->dev.bus_id); -- if (status) -- return status; -- status = gpio_direction_output(cs, spi->mode & SPI_CS_HIGH); -+ if (cs != SPI_GPIO_NO_CHIPSELECT) { -+ status = gpio_request(cs, spi->dev.bus_id); -+ if (status) -+ return status; -+ status = gpio_direction_output(cs, spi->mode & SPI_CS_HIGH); -+ } - } - if (!status) - status = spi_bitbang_setup(spi); - if (status) { -- if (!spi->controller_state) -+ if (!spi->controller_state && cs != SPI_GPIO_NO_CHIPSELECT) - gpio_free(cs); - } - return status; -@@ -209,7 +213,8 @@ static void spi_gpio_cleanup(struct spi_ - { - unsigned long cs = (unsigned long) spi->controller_data; - -- gpio_free(cs); -+ if (cs != SPI_GPIO_NO_CHIPSELECT) -+ gpio_free(cs); - spi_bitbang_cleanup(spi); - } - ---- a/include/linux/spi/spi_gpio.h -+++ b/include/linux/spi/spi_gpio.h -@@ -25,10 +25,16 @@ - * ... - * }; - * -+ * If chipselect is not used (there's only one device on the bus), assign -+ * SPI_GPIO_NO_CHIPSELECT to the controller_data: -+ * .controller_data = (void *) SPI_GPIO_NO_CHIPSELECT; -+ * - * If the bitbanged bus is later switched to a "native" controller, - * that platform_device and controller_data should be removed. - */ - -+#define SPI_GPIO_NO_CHIPSELECT ((unsigned long)-1l) -+ - /** - * struct spi_gpio_platform_data - parameter for bitbanged SPI master - * @sck: number of the GPIO used for clock output diff --git a/target/linux/generic-2.6/patches-2.6.28/920-03-spi-gpio-fix-miso-bit.patch b/target/linux/generic-2.6/patches-2.6.28/920-03-spi-gpio-fix-miso-bit.patch deleted file mode 100644 index acc7bed92..000000000 --- a/target/linux/generic-2.6/patches-2.6.28/920-03-spi-gpio-fix-miso-bit.patch +++ /dev/null @@ -1,20 +0,0 @@ -SPI-GPIO bitbang: - -gpio_get_value() returns 0 or nonzero, but getmiso() expects 0 or 1. -Sanitize the value to a 0/1 boolean. - ---mb - - - ---- a/drivers/spi/spi_gpio.c -+++ b/drivers/spi/spi_gpio.c -@@ -114,7 +114,7 @@ static inline void setmosi(const struct - - static inline int getmiso(const struct spi_device *spi) - { -- return gpio_get_value(SPI_MISO_GPIO); -+ return !!gpio_get_value(SPI_MISO_GPIO); - } - - #undef pdata diff --git a/target/linux/generic-2.6/patches-2.6.28/920-04-spi-gpio-implement-spi-delay.patch b/target/linux/generic-2.6/patches-2.6.28/920-04-spi-gpio-implement-spi-delay.patch deleted file mode 100644 index 19032881b..000000000 --- a/target/linux/generic-2.6/patches-2.6.28/920-04-spi-gpio-implement-spi-delay.patch +++ /dev/null @@ -1,58 +0,0 @@ -Implement the SPI-GPIO delay function for busses that need speed limitation. - ---mb - - - ---- a/drivers/spi/spi_gpio.c -+++ b/drivers/spi/spi_gpio.c -@@ -21,6 +21,7 @@ - #include - #include - #include -+#include - - #include - #include -@@ -69,6 +70,7 @@ struct spi_gpio { - * #define SPI_MOSI_GPIO 120 - * #define SPI_SCK_GPIO 121 - * #define SPI_N_CHIPSEL 4 -+ * #undef NEED_SPIDELAY - * #include "spi_gpio.c" - */ - -@@ -76,6 +78,7 @@ struct spi_gpio { - #define DRIVER_NAME "spi_gpio" - - #define GENERIC_BITBANG /* vs tight inlines */ -+#define NEED_SPIDELAY 1 - - /* all functions referencing these symbols must define pdata */ - #define SPI_MISO_GPIO ((pdata)->miso) -@@ -120,12 +123,20 @@ static inline int getmiso(const struct s - #undef pdata - - /* -- * NOTE: this clocks "as fast as we can". It "should" be a function of the -- * requested device clock. Software overhead means we usually have trouble -- * reaching even one Mbit/sec (except when we can inline bitops), so for now -- * we'll just assume we never need additional per-bit slowdowns. -+ * NOTE: to clock "as fast as we can", set spi_device.max_speed_hz -+ * and spi_transfer.speed_hz to 0. -+ * Otherwise this is a function of the requested device clock. -+ * Software overhead means we usually have trouble -+ * reaching even one Mbit/sec (except when we can inline bitops). So on small -+ * embedded devices with fast SPI slaves you usually don't need a delay. - */ --#define spidelay(nsecs) do {} while (0) -+static inline void spidelay(unsigned nsecs) -+{ -+#ifdef NEED_SPIDELAY -+ if (unlikely(nsecs)) -+ ndelay(nsecs); -+#endif /* NEED_SPIDELAY */ -+} - - #define EXPAND_BITBANG_TXRX - #include diff --git a/target/linux/generic-2.6/patches-2.6.28/921-gpio_spi_driver.patch b/target/linux/generic-2.6/patches-2.6.28/921-gpio_spi_driver.patch deleted file mode 100644 index 98b764d6f..000000000 --- a/target/linux/generic-2.6/patches-2.6.28/921-gpio_spi_driver.patch +++ /dev/null @@ -1,366 +0,0 @@ -THIS CODE IS DEPRECATED. - -Please use the new mainline SPI-GPIO driver, as of 2.6.29. - ---mb - - - ---- /dev/null -+++ b/include/linux/spi/spi_gpio_old.h -@@ -0,0 +1,73 @@ -+/* -+ * spi_gpio interface to platform code -+ * -+ * Copyright (c) 2008 Piotr Skamruk -+ * Copyright (c) 2008 Michael Buesch -+ * -+ * 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 _LINUX_SPI_SPI_GPIO -+#define _LINUX_SPI_SPI_GPIO -+ -+#include -+#include -+ -+ -+/** -+ * struct spi_gpio_platform_data - Data definitions for a SPI-GPIO device. -+ * -+ * This structure holds information about a GPIO-based SPI device. -+ * -+ * @pin_clk: The GPIO pin number of the CLOCK pin. -+ * -+ * @pin_miso: The GPIO pin number of the MISO pin. -+ * -+ * @pin_mosi: The GPIO pin number of the MOSI pin. -+ * -+ * @pin_cs: The GPIO pin number of the CHIPSELECT pin. -+ * -+ * @cs_activelow: If true, the chip is selected when the CS line is low. -+ * -+ * @no_spi_delay: If true, no delay is done in the lowlevel bitbanging. -+ * Note that doing no delay is not standards compliant, -+ * but it might be needed to speed up transfers on some -+ * slow embedded machines. -+ * -+ * @boardinfo_setup: This callback is called after the -+ * SPI master device was registered, but before the -+ * device is registered. -+ * @boardinfo_setup_data: Data argument passed to boardinfo_setup(). -+ */ -+struct spi_gpio_platform_data { -+ unsigned int pin_clk; -+ unsigned int pin_miso; -+ unsigned int pin_mosi; -+ unsigned int pin_cs; -+ bool cs_activelow; -+ bool no_spi_delay; -+ int (*boardinfo_setup)(struct spi_board_info *bi, -+ struct spi_master *master, -+ void *data); -+ void *boardinfo_setup_data; -+}; -+ -+/** -+ * SPI_GPIO_PLATDEV_NAME - The platform device name string. -+ * -+ * The name string that has to be used for platform_device_alloc -+ * when allocating a spi-gpio device. -+ */ -+#define SPI_GPIO_PLATDEV_NAME "spi-gpio" -+ -+/** -+ * spi_gpio_next_id - Get another platform device ID number. -+ * -+ * This returns the next platform device ID number that has to be used -+ * for platform_device_alloc. The ID is opaque and should not be used for -+ * anything else. -+ */ -+int spi_gpio_next_id(void); -+ -+#endif /* _LINUX_SPI_SPI_GPIO */ ---- /dev/null -+++ b/drivers/spi/spi_gpio_old.c -@@ -0,0 +1,251 @@ -+/* -+ * Bitbanging SPI bus driver using GPIO API -+ * -+ * Copyright (c) 2008 Piotr Skamruk -+ * Copyright (c) 2008 Michael Buesch -+ * -+ * based on spi_s3c2410_gpio.c -+ * Copyright (c) 2006 Ben Dooks -+ * Copyright (c) 2006 Simtec Electronics -+ * and on i2c-gpio.c -+ * Copyright (C) 2007 Atmel Corporation -+ * -+ * 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 -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+ -+struct spi_gpio { -+ struct spi_bitbang bitbang; -+ struct spi_gpio_platform_data *info; -+ struct platform_device *pdev; -+ struct spi_board_info bi; -+}; -+ -+ -+static inline struct spi_gpio *spidev_to_sg(struct spi_device *dev) -+{ -+ return dev->controller_data; -+} -+ -+static inline void setsck(struct spi_device *dev, int val) -+{ -+ struct spi_gpio *sp = spidev_to_sg(dev); -+ gpio_set_value(sp->info->pin_clk, val ? 1 : 0); -+} -+ -+static inline void setmosi(struct spi_device *dev, int val) -+{ -+ struct spi_gpio *sp = spidev_to_sg(dev); -+ gpio_set_value(sp->info->pin_mosi, val ? 1 : 0); -+} -+ -+static inline u32 getmiso(struct spi_device *dev) -+{ -+ struct spi_gpio *sp = spidev_to_sg(dev); -+ return gpio_get_value(sp->info->pin_miso) ? 1 : 0; -+} -+ -+static inline void do_spidelay(struct spi_device *dev, unsigned nsecs) -+{ -+ struct spi_gpio *sp = spidev_to_sg(dev); -+ -+ if (!sp->info->no_spi_delay) -+ ndelay(nsecs); -+} -+ -+#define spidelay(nsecs) do { \ -+ /* Steal the spi_device pointer from our caller. \ -+ * The bitbang-API should probably get fixed here... */ \ -+ do_spidelay(spi, nsecs); \ -+ } while (0) -+ -+#define EXPAND_BITBANG_TXRX -+#include -+ -+static u32 spi_gpio_txrx_mode0(struct spi_device *spi, -+ unsigned nsecs, u32 word, u8 bits) -+{ -+ return bitbang_txrx_be_cpha0(spi, nsecs, 0, word, bits); -+} -+ -+static u32 spi_gpio_txrx_mode1(struct spi_device *spi, -+ unsigned nsecs, u32 word, u8 bits) -+{ -+ return bitbang_txrx_be_cpha1(spi, nsecs, 0, word, bits); -+} -+ -+static u32 spi_gpio_txrx_mode2(struct spi_device *spi, -+ unsigned nsecs, u32 word, u8 bits) -+{ -+ return bitbang_txrx_be_cpha0(spi, nsecs, 1, word, bits); -+} -+ -+static u32 spi_gpio_txrx_mode3(struct spi_device *spi, -+ unsigned nsecs, u32 word, u8 bits) -+{ -+ return bitbang_txrx_be_cpha1(spi, nsecs, 1, word, bits); -+} -+ -+static void spi_gpio_chipselect(struct spi_device *dev, int on) -+{ -+ struct spi_gpio *sp = spidev_to_sg(dev); -+ -+ if (sp->info->cs_activelow) -+ on = !on; -+ gpio_set_value(sp->info->pin_cs, on ? 1 : 0); -+} -+ -+static int spi_gpio_probe(struct platform_device *pdev) -+{ -+ struct spi_master *master; -+ struct spi_gpio_platform_data *pdata; -+ struct spi_gpio *sp; -+ struct spi_device *spidev; -+ int err; -+ -+ pdata = pdev->dev.platform_data; -+ if (!pdata) -+ return -ENXIO; -+ -+ err = -ENOMEM; -+ master = spi_alloc_master(&pdev->dev, sizeof(struct spi_gpio)); -+ if (!master) -+ goto err_alloc_master; -+ -+ sp = spi_master_get_devdata(master); -+ platform_set_drvdata(pdev, sp); -+ sp->info = pdata; -+ -+ err = gpio_request(pdata->pin_clk, "spi_clock"); -+ if (err) -+ goto err_request_clk; -+ err = gpio_request(pdata->pin_mosi, "spi_mosi"); -+ if (err) -+ goto err_request_mosi; -+ err = gpio_request(pdata->pin_miso, "spi_miso"); -+ if (err) -+ goto err_request_miso; -+ err = gpio_request(pdata->pin_cs, "spi_cs"); -+ if (err) -+ goto err_request_cs; -+ -+ sp->bitbang.master = spi_master_get(master); -+ sp->bitbang.master->bus_num = -1; -+ sp->bitbang.master->num_chipselect = 1; -+ sp->bitbang.chipselect = spi_gpio_chipselect; -+ sp->bitbang.txrx_word[SPI_MODE_0] = spi_gpio_txrx_mode0; -+ sp->bitbang.txrx_word[SPI_MODE_1] = spi_gpio_txrx_mode1; -+ sp->bitbang.txrx_word[SPI_MODE_2] = spi_gpio_txrx_mode2; -+ sp->bitbang.txrx_word[SPI_MODE_3] = spi_gpio_txrx_mode3; -+ -+ gpio_direction_output(pdata->pin_clk, 0); -+ gpio_direction_output(pdata->pin_mosi, 0); -+ gpio_direction_output(pdata->pin_cs, -+ pdata->cs_activelow ? 1 : 0); -+ gpio_direction_input(pdata->pin_miso); -+ -+ err = spi_bitbang_start(&sp->bitbang); -+ if (err) -+ goto err_no_bitbang; -+ err = pdata->boardinfo_setup(&sp->bi, master, -+ pdata->boardinfo_setup_data); -+ if (err) -+ goto err_bi_setup; -+ sp->bi.controller_data = sp; -+ spidev = spi_new_device(master, &sp->bi); -+ if (!spidev) -+ goto err_new_dev; -+ -+ return 0; -+ -+err_new_dev: -+err_bi_setup: -+ spi_bitbang_stop(&sp->bitbang); -+err_no_bitbang: -+ spi_master_put(sp->bitbang.master); -+ gpio_free(pdata->pin_cs); -+err_request_cs: -+ gpio_free(pdata->pin_miso); -+err_request_miso: -+ gpio_free(pdata->pin_mosi); -+err_request_mosi: -+ gpio_free(pdata->pin_clk); -+err_request_clk: -+ kfree(master); -+ -+err_alloc_master: -+ return err; -+} -+ -+static int __devexit spi_gpio_remove(struct platform_device *pdev) -+{ -+ struct spi_gpio *sp; -+ struct spi_gpio_platform_data *pdata; -+ -+ pdata = pdev->dev.platform_data; -+ sp = platform_get_drvdata(pdev); -+ -+ gpio_free(pdata->pin_clk); -+ gpio_free(pdata->pin_mosi); -+ gpio_free(pdata->pin_miso); -+ gpio_free(pdata->pin_cs); -+ spi_bitbang_stop(&sp->bitbang); -+ spi_master_put(sp->bitbang.master); -+ -+ return 0; -+} -+ -+static struct platform_driver spi_gpio_driver = { -+ .driver = { -+ .name = SPI_GPIO_PLATDEV_NAME, -+ .owner = THIS_MODULE, -+ }, -+ .probe = spi_gpio_probe, -+ .remove = __devexit_p(spi_gpio_remove), -+}; -+ -+int spi_gpio_next_id(void) -+{ -+ static atomic_t counter = ATOMIC_INIT(-1); -+ -+ return atomic_inc_return(&counter); -+} -+EXPORT_SYMBOL(spi_gpio_next_id); -+ -+static int __init spi_gpio_init(void) -+{ -+ int err; -+ -+ err = platform_driver_register(&spi_gpio_driver); -+ if (err) -+ printk(KERN_ERR "spi-gpio: register failed: %d\n", err); -+ -+ return err; -+} -+module_init(spi_gpio_init); -+ -+static void __exit spi_gpio_exit(void) -+{ -+ platform_driver_unregister(&spi_gpio_driver); -+} -+module_exit(spi_gpio_exit); -+ -+MODULE_AUTHOR("Piot Skamruk "); -+MODULE_AUTHOR("Michael Buesch"); -+MODULE_DESCRIPTION("Platform independent GPIO bitbanging SPI driver"); -+MODULE_LICENSE("GPL v2"); ---- a/drivers/spi/Kconfig -+++ b/drivers/spi/Kconfig -@@ -116,6 +116,15 @@ config SPI_GPIO - GPIO operations, you should be able to leverage that for better - speed with a custom version of this driver; see the source code. - -+config SPI_GPIO_OLD -+ tristate "Old GPIO API based bitbanging SPI controller (DEPRECATED)" -+ depends on SPI_MASTER && GENERIC_GPIO -+ select SPI_BITBANG -+ help -+ This code is deprecated. Please use the new mainline SPI-GPIO driver. -+ -+ If unsure, say N. -+ - config SPI_IMX - tristate "Freescale iMX SPI controller" - depends on ARCH_IMX && EXPERIMENTAL ---- a/drivers/spi/Makefile -+++ b/drivers/spi/Makefile -@@ -17,6 +17,7 @@ obj-$(CONFIG_SPI_BITBANG) += spi_bitban - obj-$(CONFIG_SPI_AU1550) += au1550_spi.o - obj-$(CONFIG_SPI_BUTTERFLY) += spi_butterfly.o - 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_PXA2XX) += pxa2xx_spi.o diff --git a/target/linux/generic-2.6/patches-2.6.28/922-gpiommc.patch b/target/linux/generic-2.6/patches-2.6.28/922-gpiommc.patch deleted file mode 100644 index 5d9e44d73..000000000 --- a/target/linux/generic-2.6/patches-2.6.28/922-gpiommc.patch +++ /dev/null @@ -1,838 +0,0 @@ ---- /dev/null -+++ b/drivers/mmc/host/gpiommc.c -@@ -0,0 +1,608 @@ -+/* -+ * Driver an MMC/SD card on a bitbanging GPIO SPI bus. -+ * This module hooks up the mmc_spi and spi_gpio modules and also -+ * provides a configfs interface. -+ * -+ * Copyright 2008 Michael Buesch -+ * -+ * Licensed under the GNU/GPL. See COPYING for details. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+ -+#define PFX "gpio-mmc: " -+ -+ -+struct gpiommc_device { -+ struct platform_device *pdev; -+ struct platform_device *spi_pdev; -+ struct spi_board_info boardinfo; -+}; -+ -+ -+MODULE_DESCRIPTION("GPIO based MMC driver"); -+MODULE_AUTHOR("Michael Buesch"); -+MODULE_LICENSE("GPL"); -+ -+ -+static int gpiommc_boardinfo_setup(struct spi_board_info *bi, -+ struct spi_master *master, -+ void *data) -+{ -+ struct gpiommc_device *d = data; -+ struct gpiommc_platform_data *pdata = d->pdev->dev.platform_data; -+ -+ /* Bind the SPI master to the MMC-SPI host driver. */ -+ strlcpy(bi->modalias, "mmc_spi", sizeof(bi->modalias)); -+ -+ bi->max_speed_hz = pdata->max_bus_speed; -+ bi->bus_num = master->bus_num; -+ bi->mode = pdata->mode; -+ -+ return 0; -+} -+ -+static int gpiommc_probe(struct platform_device *pdev) -+{ -+ struct gpiommc_platform_data *mmc_pdata = pdev->dev.platform_data; -+ struct spi_gpio_platform_data spi_pdata; -+ struct gpiommc_device *d; -+ int err; -+ -+ err = -ENXIO; -+ if (!mmc_pdata) -+ goto error; -+ -+#ifdef CONFIG_MMC_SPI_MODULE -+ err = request_module("mmc_spi"); -+ if (err) { -+ printk(KERN_WARNING PFX -+ "Failed to request mmc_spi module.\n"); -+ } -+#endif /* CONFIG_MMC_SPI_MODULE */ -+ -+ /* Allocate the GPIO-MMC device */ -+ err = -ENOMEM; -+ d = kzalloc(sizeof(*d), GFP_KERNEL); -+ if (!d) -+ goto error; -+ d->pdev = pdev; -+ -+ /* Create the SPI-GPIO device */ -+ d->spi_pdev = platform_device_alloc(SPI_GPIO_PLATDEV_NAME, -+ spi_gpio_next_id()); -+ if (!d->spi_pdev) -+ goto err_free_d; -+ -+ memset(&spi_pdata, 0, sizeof(spi_pdata)); -+ spi_pdata.pin_clk = mmc_pdata->pins.gpio_clk; -+ spi_pdata.pin_miso = mmc_pdata->pins.gpio_do; -+ spi_pdata.pin_mosi = mmc_pdata->pins.gpio_di; -+ spi_pdata.pin_cs = mmc_pdata->pins.gpio_cs; -+ spi_pdata.cs_activelow = mmc_pdata->pins.cs_activelow; -+ spi_pdata.no_spi_delay = mmc_pdata->no_spi_delay; -+ spi_pdata.boardinfo_setup = gpiommc_boardinfo_setup; -+ spi_pdata.boardinfo_setup_data = d; -+ -+ err = platform_device_add_data(d->spi_pdev, &spi_pdata, -+ sizeof(spi_pdata)); -+ if (err) -+ goto err_free_pdev; -+ err = platform_device_add(d->spi_pdev); -+ if (err) -+ goto err_free_pdata; -+ platform_set_drvdata(pdev, d); -+ -+ printk(KERN_INFO PFX "MMC-Card \"%s\" " -+ "attached to GPIO pins di=%u, do=%u, clk=%u, cs=%u\n", -+ mmc_pdata->name, mmc_pdata->pins.gpio_di, -+ mmc_pdata->pins.gpio_do, -+ mmc_pdata->pins.gpio_clk, -+ mmc_pdata->pins.gpio_cs); -+ -+ return 0; -+ -+err_free_pdata: -+ kfree(d->spi_pdev->dev.platform_data); -+ d->spi_pdev->dev.platform_data = NULL; -+err_free_pdev: -+ platform_device_put(d->spi_pdev); -+err_free_d: -+ kfree(d); -+error: -+ return err; -+} -+ -+static int gpiommc_remove(struct platform_device *pdev) -+{ -+ struct gpiommc_device *d = platform_get_drvdata(pdev); -+ struct gpiommc_platform_data *pdata = d->pdev->dev.platform_data; -+ -+ platform_device_unregister(d->spi_pdev); -+ printk(KERN_INFO PFX "GPIO based MMC-Card \"%s\" removed\n", -+ pdata->name); -+ platform_device_put(d->spi_pdev); -+ -+ return 0; -+} -+ -+#ifdef CONFIG_GPIOMMC_CONFIGFS -+ -+/* A device that was created through configfs */ -+struct gpiommc_configfs_device { -+ struct config_item item; -+ /* The platform device, after registration. */ -+ struct platform_device *pdev; -+ /* The configuration */ -+ struct gpiommc_platform_data pdata; -+}; -+ -+#define GPIO_INVALID -1 -+ -+static inline bool gpiommc_is_registered(struct gpiommc_configfs_device *dev) -+{ -+ return (dev->pdev != NULL); -+} -+ -+static inline struct gpiommc_configfs_device *ci_to_gpiommc(struct config_item *item) -+{ -+ return item ? container_of(item, struct gpiommc_configfs_device, item) : NULL; -+} -+ -+static struct configfs_attribute gpiommc_attr_DI = { -+ .ca_owner = THIS_MODULE, -+ .ca_name = "gpio_data_in", -+ .ca_mode = S_IRUGO | S_IWUSR, -+}; -+ -+static struct configfs_attribute gpiommc_attr_DO = { -+ .ca_owner = THIS_MODULE, -+ .ca_name = "gpio_data_out", -+ .ca_mode = S_IRUGO | S_IWUSR, -+}; -+ -+static struct configfs_attribute gpiommc_attr_CLK = { -+ .ca_owner = THIS_MODULE, -+ .ca_name = "gpio_clock", -+ .ca_mode = S_IRUGO | S_IWUSR, -+}; -+ -+static struct configfs_attribute gpiommc_attr_CS = { -+ .ca_owner = THIS_MODULE, -+ .ca_name = "gpio_chipselect", -+ .ca_mode = S_IRUGO | S_IWUSR, -+}; -+ -+static struct configfs_attribute gpiommc_attr_CS_activelow = { -+ .ca_owner = THIS_MODULE, -+ .ca_name = "gpio_chipselect_activelow", -+ .ca_mode = S_IRUGO | S_IWUSR, -+}; -+ -+static struct configfs_attribute gpiommc_attr_spimode = { -+ .ca_owner = THIS_MODULE, -+ .ca_name = "spi_mode", -+ .ca_mode = S_IRUGO | S_IWUSR, -+}; -+ -+static struct configfs_attribute gpiommc_attr_spidelay = { -+ .ca_owner = THIS_MODULE, -+ .ca_name = "spi_delay", -+ .ca_mode = S_IRUGO | S_IWUSR, -+}; -+ -+static struct configfs_attribute gpiommc_attr_max_bus_speed = { -+ .ca_owner = THIS_MODULE, -+ .ca_name = "max_bus_speed", -+ .ca_mode = S_IRUGO | S_IWUSR, -+}; -+ -+static struct configfs_attribute gpiommc_attr_register = { -+ .ca_owner = THIS_MODULE, -+ .ca_name = "register", -+ .ca_mode = S_IRUGO | S_IWUSR, -+}; -+ -+static struct configfs_attribute *gpiommc_config_attrs[] = { -+ &gpiommc_attr_DI, -+ &gpiommc_attr_DO, -+ &gpiommc_attr_CLK, -+ &gpiommc_attr_CS, -+ &gpiommc_attr_CS_activelow, -+ &gpiommc_attr_spimode, -+ &gpiommc_attr_spidelay, -+ &gpiommc_attr_max_bus_speed, -+ &gpiommc_attr_register, -+ NULL, -+}; -+ -+static ssize_t gpiommc_config_attr_show(struct config_item *item, -+ struct configfs_attribute *attr, -+ char *page) -+{ -+ struct gpiommc_configfs_device *dev = ci_to_gpiommc(item); -+ ssize_t count = 0; -+ unsigned int gpio; -+ int err = 0; -+ -+ if (attr == &gpiommc_attr_DI) { -+ gpio = dev->pdata.pins.gpio_di; -+ if (gpio == GPIO_INVALID) -+ count = snprintf(page, PAGE_SIZE, "not configured\n"); -+ else -+ count = snprintf(page, PAGE_SIZE, "%u\n", gpio); -+ goto out; -+ } -+ if (attr == &gpiommc_attr_DO) { -+ gpio = dev->pdata.pins.gpio_do; -+ if (gpio == GPIO_INVALID) -+ count = snprintf(page, PAGE_SIZE, "not configured\n"); -+ else -+ count = snprintf(page, PAGE_SIZE, "%u\n", gpio); -+ goto out; -+ } -+ if (attr == &gpiommc_attr_CLK) { -+ gpio = dev->pdata.pins.gpio_clk; -+ if (gpio == GPIO_INVALID) -+ count = snprintf(page, PAGE_SIZE, "not configured\n"); -+ else -+ count = snprintf(page, PAGE_SIZE, "%u\n", gpio); -+ goto out; -+ } -+ if (attr == &gpiommc_attr_CS) { -+ gpio = dev->pdata.pins.gpio_cs; -+ if (gpio == GPIO_INVALID) -+ count = snprintf(page, PAGE_SIZE, "not configured\n"); -+ else -+ count = snprintf(page, PAGE_SIZE, "%u\n", gpio); -+ goto out; -+ } -+ if (attr == &gpiommc_attr_CS_activelow) { -+ count = snprintf(page, PAGE_SIZE, "%u\n", -+ dev->pdata.pins.cs_activelow); -+ goto out; -+ } -+ if (attr == &gpiommc_attr_spimode) { -+ count = snprintf(page, PAGE_SIZE, "%u\n", -+ dev->pdata.mode); -+ goto out; -+ } -+ if (attr == &gpiommc_attr_spidelay) { -+ count = snprintf(page, PAGE_SIZE, "%u\n", -+ !dev->pdata.no_spi_delay); -+ goto out; -+ } -+ if (attr == &gpiommc_attr_max_bus_speed) { -+ count = snprintf(page, PAGE_SIZE, "%u\n", -+ dev->pdata.max_bus_speed); -+ goto out; -+ } -+ if (attr == &gpiommc_attr_register) { -+ count = snprintf(page, PAGE_SIZE, "%u\n", -+ gpiommc_is_registered(dev)); -+ goto out; -+ } -+ WARN_ON(1); -+ err = -ENOSYS; -+out: -+ return err ? err : count; -+} -+ -+static int gpiommc_do_register(struct gpiommc_configfs_device *dev, -+ const char *name) -+{ -+ int err; -+ -+ if (gpiommc_is_registered(dev)) -+ return 0; -+ -+ if (!gpio_is_valid(dev->pdata.pins.gpio_di) || -+ !gpio_is_valid(dev->pdata.pins.gpio_do) || -+ !gpio_is_valid(dev->pdata.pins.gpio_clk) || -+ !gpio_is_valid(dev->pdata.pins.gpio_cs)) { -+ printk(KERN_ERR PFX -+ "configfs: Invalid GPIO pin number(s)\n"); -+ return -EINVAL; -+ } -+ -+ strlcpy(dev->pdata.name, name, -+ sizeof(dev->pdata.name)); -+ -+ dev->pdev = platform_device_alloc(GPIOMMC_PLATDEV_NAME, -+ gpiommc_next_id()); -+ if (!dev->pdev) -+ return -ENOMEM; -+ err = platform_device_add_data(dev->pdev, &dev->pdata, -+ sizeof(dev->pdata)); -+ if (err) { -+ platform_device_put(dev->pdev); -+ return err; -+ } -+ err = platform_device_add(dev->pdev); -+ if (err) { -+ platform_device_put(dev->pdev); -+ return err; -+ } -+ -+ return 0; -+} -+ -+static void gpiommc_do_unregister(struct gpiommc_configfs_device *dev) -+{ -+ if (!gpiommc_is_registered(dev)) -+ return; -+ -+ platform_device_unregister(dev->pdev); -+ dev->pdev = NULL; -+} -+ -+static ssize_t gpiommc_config_attr_store(struct config_item *item, -+ struct configfs_attribute *attr, -+ const char *page, size_t count) -+{ -+ struct gpiommc_configfs_device *dev = ci_to_gpiommc(item); -+ int err = -EINVAL; -+ unsigned long data; -+ -+ if (attr == &gpiommc_attr_register) { -+ err = strict_strtoul(page, 10, &data); -+ if (err) -+ goto out; -+ err = -EINVAL; -+ if (data == 1) -+ err = gpiommc_do_register(dev, item->ci_name); -+ if (data == 0) { -+ gpiommc_do_unregister(dev); -+ err = 0; -+ } -+ goto out; -+ } -+ -+ if (gpiommc_is_registered(dev)) { -+ /* The rest of the config parameters can only be set -+ * as long as the device is not registered, yet. */ -+ err = -EBUSY; -+ goto out; -+ } -+ -+ if (attr == &gpiommc_attr_DI) { -+ err = strict_strtoul(page, 10, &data); -+ if (err) -+ goto out; -+ err = -EINVAL; -+ if (!gpio_is_valid(data)) -+ goto out; -+ dev->pdata.pins.gpio_di = data; -+ err = 0; -+ goto out; -+ } -+ if (attr == &gpiommc_attr_DO) { -+ err = strict_strtoul(page, 10, &data); -+ if (err) -+ goto out; -+ err = -EINVAL; -+ if (!gpio_is_valid(data)) -+ goto out; -+ dev->pdata.pins.gpio_do = data; -+ err = 0; -+ goto out; -+ } -+ if (attr == &gpiommc_attr_CLK) { -+ err = strict_strtoul(page, 10, &data); -+ if (err) -+ goto out; -+ err = -EINVAL; -+ if (!gpio_is_valid(data)) -+ goto out; -+ dev->pdata.pins.gpio_clk = data; -+ err = 0; -+ goto out; -+ } -+ if (attr == &gpiommc_attr_CS) { -+ err = strict_strtoul(page, 10, &data); -+ if (err) -+ goto out; -+ err = -EINVAL; -+ if (!gpio_is_valid(data)) -+ goto out; -+ dev->pdata.pins.gpio_cs = data; -+ err = 0; -+ goto out; -+ } -+ if (attr == &gpiommc_attr_CS_activelow) { -+ err = strict_strtoul(page, 10, &data); -+ if (err) -+ goto out; -+ err = -EINVAL; -+ if (data != 0 && data != 1) -+ goto out; -+ dev->pdata.pins.cs_activelow = data; -+ err = 0; -+ goto out; -+ } -+ if (attr == &gpiommc_attr_spimode) { -+ err = strict_strtoul(page, 10, &data); -+ if (err) -+ goto out; -+ err = -EINVAL; -+ switch (data) { -+ case 0: -+ dev->pdata.mode = SPI_MODE_0; -+ break; -+ case 1: -+ dev->pdata.mode = SPI_MODE_1; -+ break; -+ case 2: -+ dev->pdata.mode = SPI_MODE_2; -+ break; -+ case 3: -+ dev->pdata.mode = SPI_MODE_3; -+ break; -+ default: -+ goto out; -+ } -+ err = 0; -+ goto out; -+ } -+ if (attr == &gpiommc_attr_spidelay) { -+ err = strict_strtoul(page, 10, &data); -+ if (err) -+ goto out; -+ err = -EINVAL; -+ if (data != 0 && data != 1) -+ goto out; -+ dev->pdata.no_spi_delay = !data; -+ err = 0; -+ goto out; -+ } -+ if (attr == &gpiommc_attr_max_bus_speed) { -+ err = strict_strtoul(page, 10, &data); -+ if (err) -+ goto out; -+ err = -EINVAL; -+ if (data > UINT_MAX) -+ goto out; -+ dev->pdata.max_bus_speed = data; -+ err = 0; -+ goto out; -+ } -+ WARN_ON(1); -+ err = -ENOSYS; -+out: -+ return err ? err : count; -+} -+ -+static void gpiommc_config_item_release(struct config_item *item) -+{ -+ struct gpiommc_configfs_device *dev = ci_to_gpiommc(item); -+ -+ kfree(dev); -+} -+ -+static struct configfs_item_operations gpiommc_config_item_ops = { -+ .release = gpiommc_config_item_release, -+ .show_attribute = gpiommc_config_attr_show, -+ .store_attribute = gpiommc_config_attr_store, -+}; -+ -+static struct config_item_type gpiommc_dev_ci_type = { -+ .ct_item_ops = &gpiommc_config_item_ops, -+ .ct_attrs = gpiommc_config_attrs, -+ .ct_owner = THIS_MODULE, -+}; -+ -+static struct config_item *gpiommc_make_item(struct config_group *group, -+ const char *name) -+{ -+ struct gpiommc_configfs_device *dev; -+ -+ if (strlen(name) > GPIOMMC_MAX_NAMELEN) { -+ printk(KERN_ERR PFX "configfs: device name too long\n"); -+ return NULL; -+ } -+ -+ dev = kzalloc(sizeof(*dev), GFP_KERNEL); -+ if (!dev) -+ return NULL; -+ -+ config_item_init_type_name(&dev->item, name, -+ &gpiommc_dev_ci_type); -+ -+ /* Assign default configuration */ -+ dev->pdata.pins.gpio_di = GPIO_INVALID; -+ dev->pdata.pins.gpio_do = GPIO_INVALID; -+ dev->pdata.pins.gpio_clk = GPIO_INVALID; -+ dev->pdata.pins.gpio_cs = GPIO_INVALID; -+ dev->pdata.pins.cs_activelow = 1; -+ dev->pdata.mode = SPI_MODE_0; -+ dev->pdata.no_spi_delay = 0; -+ dev->pdata.max_bus_speed = 5000000; /* 5 MHz */ -+ -+ return &(dev->item); -+} -+ -+static void gpiommc_drop_item(struct config_group *group, -+ struct config_item *item) -+{ -+ struct gpiommc_configfs_device *dev = ci_to_gpiommc(item); -+ -+ gpiommc_do_unregister(dev); -+ kfree(dev); -+} -+ -+static struct configfs_group_operations gpiommc_ct_group_ops = { -+ .make_item = gpiommc_make_item, -+ .drop_item = gpiommc_drop_item, -+}; -+ -+static struct config_item_type gpiommc_ci_type = { -+ .ct_group_ops = &gpiommc_ct_group_ops, -+ .ct_owner = THIS_MODULE, -+}; -+ -+static struct configfs_subsystem gpiommc_subsys = { -+ .su_group = { -+ .cg_item = { -+ .ci_namebuf = GPIOMMC_PLATDEV_NAME, -+ .ci_type = &gpiommc_ci_type, -+ }, -+ }, -+ .su_mutex = __MUTEX_INITIALIZER(gpiommc_subsys.su_mutex), -+}; -+ -+#endif /* CONFIG_GPIOMMC_CONFIGFS */ -+ -+static struct platform_driver gpiommc_plat_driver = { -+ .probe = gpiommc_probe, -+ .remove = gpiommc_remove, -+ .driver = { -+ .name = GPIOMMC_PLATDEV_NAME, -+ .owner = THIS_MODULE, -+ }, -+}; -+ -+int gpiommc_next_id(void) -+{ -+ static atomic_t counter = ATOMIC_INIT(-1); -+ -+ return atomic_inc_return(&counter); -+} -+EXPORT_SYMBOL(gpiommc_next_id); -+ -+static int __init gpiommc_modinit(void) -+{ -+ int err; -+ -+ err = platform_driver_register(&gpiommc_plat_driver); -+ if (err) -+ return err; -+ -+#ifdef CONFIG_GPIOMMC_CONFIGFS -+ config_group_init(&gpiommc_subsys.su_group); -+ err = configfs_register_subsystem(&gpiommc_subsys); -+ if (err) { -+ platform_driver_unregister(&gpiommc_plat_driver); -+ return err; -+ } -+#endif /* CONFIG_GPIOMMC_CONFIGFS */ -+ -+ return 0; -+} -+module_init(gpiommc_modinit); -+ -+static void __exit gpiommc_modexit(void) -+{ -+#ifdef CONFIG_GPIOMMC_CONFIGFS -+ configfs_unregister_subsystem(&gpiommc_subsys); -+#endif -+ platform_driver_unregister(&gpiommc_plat_driver); -+} -+module_exit(gpiommc_modexit); ---- a/drivers/mmc/host/Kconfig -+++ b/drivers/mmc/host/Kconfig -@@ -192,3 +192,28 @@ config MMC_TMIO - help - This provides support for the SD/MMC cell found in TC6393XB, - T7L66XB and also ipaq ASIC3 -+ -+config GPIOMMC -+ tristate "MMC/SD over GPIO-based SPI" -+ depends on MMC && MMC_SPI && (SPI_GPIO || SPI_GPIO_OLD) -+ help -+ This driver hooks up the mmc_spi and spi_gpio modules so that -+ MMC/SD cards can be used on a GPIO based bus by bitbanging -+ the SPI protocol in software. -+ -+ This driver provides a configfs interface to dynamically create -+ and destroy GPIO-based MMC/SD card devices. It also provides -+ a platform device interface API. -+ See Documentation/gpiommc.txt for details. -+ -+ The module will be called gpiommc. -+ -+ If unsure, say N. -+ -+config GPIOMMC_CONFIGFS -+ bool -+ depends on GPIOMMC && CONFIGFS_FS -+ default y -+ help -+ This option automatically enables configfs support for gpiommc -+ if configfs is available. ---- a/drivers/mmc/host/Makefile -+++ b/drivers/mmc/host/Makefile -@@ -22,4 +22,5 @@ obj-$(CONFIG_MMC_SPI) += mmc_spi.o - obj-$(CONFIG_MMC_S3C) += s3cmci.o - obj-$(CONFIG_MMC_SDRICOH_CS) += sdricoh_cs.o - obj-$(CONFIG_MMC_TMIO) += tmio_mmc.o -+obj-$(CONFIG_GPIOMMC) += gpiommc.o - ---- /dev/null -+++ b/include/linux/mmc/gpiommc.h -@@ -0,0 +1,71 @@ -+/* -+ * Device driver for MMC/SD cards driven over a GPIO bus. -+ * -+ * Copyright (c) 2008 Michael Buesch -+ * -+ * Licensed under the GNU/GPL version 2. -+ */ -+#ifndef LINUX_GPIOMMC_H_ -+#define LINUX_GPIOMMC_H_ -+ -+#include -+ -+ -+#define GPIOMMC_MAX_NAMELEN 15 -+#define GPIOMMC_MAX_NAMELEN_STR __stringify(GPIOMMC_MAX_NAMELEN) -+ -+/** -+ * struct gpiommc_pins - Hardware pin assignments -+ * -+ * @gpio_di: The GPIO number of the DATA IN pin -+ * @gpio_do: The GPIO number of the DATA OUT pin -+ * @gpio_clk: The GPIO number of the CLOCK pin -+ * @gpio_cs: The GPIO number of the CHIPSELECT pin -+ * @cs_activelow: If true, the chip is considered selected if @gpio_cs is low. -+ */ -+struct gpiommc_pins { -+ unsigned int gpio_di; -+ unsigned int gpio_do; -+ unsigned int gpio_clk; -+ unsigned int gpio_cs; -+ bool cs_activelow; -+}; -+ -+/** -+ * struct gpiommc_platform_data - Platform data for a MMC-over-SPI-GPIO device. -+ * -+ * @name: The unique name string of the device. -+ * @pins: The hardware pin assignments. -+ * @mode: The hardware mode. This is either SPI_MODE_0, -+ * SPI_MODE_1, SPI_MODE_2 or SPI_MODE_3. See the SPI documentation. -+ * @no_spi_delay: Do not use delays in the lowlevel SPI bitbanging code. -+ * This is not standards compliant, but may be required for some -+ * embedded machines to gain reasonable speed. -+ * @max_bus_speed: The maximum speed of the SPI bus, in Hertz. -+ */ -+struct gpiommc_platform_data { -+ char name[GPIOMMC_MAX_NAMELEN + 1]; -+ struct gpiommc_pins pins; -+ u8 mode; -+ bool no_spi_delay; -+ unsigned int max_bus_speed; -+}; -+ -+/** -+ * GPIOMMC_PLATDEV_NAME - The platform device name string. -+ * -+ * The name string that has to be used for platform_device_alloc -+ * when allocating a gpiommc device. -+ */ -+#define GPIOMMC_PLATDEV_NAME "gpiommc" -+ -+/** -+ * gpiommc_next_id - Get another platform device ID number. -+ * -+ * This returns the next platform device ID number that has to be used -+ * for platform_device_alloc. The ID is opaque and should not be used for -+ * anything else. -+ */ -+int gpiommc_next_id(void); -+ -+#endif /* LINUX_GPIOMMC_H_ */ ---- /dev/null -+++ b/Documentation/gpiommc.txt -@@ -0,0 +1,97 @@ -+GPIOMMC - Driver for an MMC/SD card on a bitbanging GPIO SPI bus -+================================================================ -+ -+The gpiommc module hooks up the mmc_spi and spi_gpio modules for running an -+MMC or SD card on GPIO pins. -+ -+Two interfaces for registering a new MMC/SD card device are provided: -+A static platform-device based mechanism and a dynamic configfs based interface. -+ -+ -+Registering devices via platform-device -+======================================= -+ -+The platform-device interface is used for registering MMC/SD devices that are -+part of the hardware platform. This is most useful only for embedded machines -+with MMC/SD devices statically connected to the platform GPIO bus. -+ -+The data structures are declared in . -+ -+To register a new device, define an instance of struct gpiommc_platform_data. -+This structure holds any information about how the device is hooked up to the -+GPIO pins and what hardware modes the device supports. See the docbook-style -+documentation in the header file for more information on the struct fields. -+ -+Then allocate a new instance of a platform device by doing: -+ -+ pdev = platform_device_alloc(GPIOMMC_PLATDEV_NAME, gpiommc_next_id()); -+ -+This will allocate the platform device data structures and hook it up to the -+gpiommc driver. -+Then add the gpiommc_platform_data to the platform device. -+ -+ err = platform_device_add_data(pdev, pdata, sizeof(struct gpiommc_platform_data)); -+ -+You may free the local instance of struct gpiommc_platform_data now. (So the -+struct may be allocated on the stack, too). -+Now simply register the platform device. -+ -+ err = platform_device_add(pdev); -+ -+Done. The gpiommc probe routine will be invoked now and you should see a kernel -+log message for the added device. -+ -+ -+Registering devices via configfs -+================================ -+ -+MMC/SD cards connected via GPIO often are a pretty dynamic thing, as for example -+selfmade hacks for soldering an MMC/SD card to standard GPIO pins on embedded -+hardware are a common situation. -+So we provide a dynamic interface to conveniently handle adding and removing -+devices from userspace, without the need to recompile the kernel. -+ -+The "gpiommc" subdirectory at the configfs mountpoint is used for handling -+the dynamic configuration. -+ -+To create a new device, it must first be allocated with mkdir. -+The following command will allocate a device named "my_mmc": -+ mkdir /config/gpiommc/my_mmc -+ -+There are several configuration files available in the new -+/config/gpiommc/my_mmc/ directory: -+ -+gpio_data_in = The SPI data-IN GPIO pin number. -+gpio_data_out = The SPI data-OUT GPIO pin number. -+gpio_clock = The SPI Clock GPIO pin number. -+gpio_chipselect = The SPI Chipselect GPIO pin number. -+gpio_chipselect_activelow = Boolean. If 0, Chipselect is active-HIGH. -+ If 1, Chipselect is active-LOW. -+spi_mode = The SPI data mode. Can be 0-3. -+spi_delay = Enable all delays in the lowlevel bitbanging. -+max_bus_speed = The maximum SPI bus speed. In Hertz. -+ -+register = Not a configuration parameter. -+ Used to register the configured card -+ with the kernel. -+ -+The device must first get configured and then registered by writing "1" to -+the "register" file. -+The configuration parameters "gpio_data_in", "gpio_data_out", "gpio_clock" -+and "gpio_chipselect" are essential and _must_ be configured before writing -+"1" to the "register" file. The registration will fail, otherwise. -+ -+The default values for the other parameters are: -+gpio_chipselect_activelow = 1 (CS active-LOW) -+spi_mode = 0 (SPI_MODE_0) -+spi_delay = 1 (enabled) -+max_bus_speed = 5000000 (5 Mhz) -+ -+Configuration values can not be changed after registration. To unregister -+the device, write a "0" to the "register" file. The configuration can be -+changed again after unregistering. -+ -+To completely remove the device, simply rmdir the directory -+(/config/gpiommc/my_mmc in this example). -+There's no need to first unregister the device before removing it. That will -+be done automatically. ---- a/MAINTAINERS -+++ b/MAINTAINERS -@@ -1911,6 +1911,11 @@ W: http://moinejf.free.fr - L: video4linux-list@redhat.com - S: Maintained - -+GPIOMMC DRIVER -+P: Michael Buesch -+M: mb@bu3sch.de -+S: Maintained -+ - HARDWARE MONITORING - L: lm-sensors@lm-sensors.org - W: http://www.lm-sensors.org/ diff --git a/target/linux/generic-2.6/patches-2.6.28/923-gpiommc-configfs-locking.patch b/target/linux/generic-2.6/patches-2.6.28/923-gpiommc-configfs-locking.patch deleted file mode 100644 index 2e4e820b2..000000000 --- a/target/linux/generic-2.6/patches-2.6.28/923-gpiommc-configfs-locking.patch +++ /dev/null @@ -1,58 +0,0 @@ -The gpiommc configfs context structure needs locking, as configfs -does not lock access between files. - ---- a/drivers/mmc/host/gpiommc.c -+++ b/drivers/mmc/host/gpiommc.c -@@ -143,6 +143,8 @@ struct gpiommc_configfs_device { - struct platform_device *pdev; - /* The configuration */ - struct gpiommc_platform_data pdata; -+ /* Mutex to protect this structure */ -+ struct mutex mutex; - }; - - #define GPIO_INVALID -1 -@@ -233,6 +235,8 @@ static ssize_t gpiommc_config_attr_show( - unsigned int gpio; - int err = 0; - -+ mutex_lock(&dev->mutex); -+ - if (attr == &gpiommc_attr_DI) { - gpio = dev->pdata.pins.gpio_di; - if (gpio == GPIO_INVALID) -@@ -293,6 +297,8 @@ static ssize_t gpiommc_config_attr_show( - WARN_ON(1); - err = -ENOSYS; - out: -+ mutex_unlock(&dev->mutex); -+ - return err ? err : count; - } - -@@ -352,6 +358,8 @@ static ssize_t gpiommc_config_attr_store - int err = -EINVAL; - unsigned long data; - -+ mutex_lock(&dev->mutex); -+ - if (attr == &gpiommc_attr_register) { - err = strict_strtoul(page, 10, &data); - if (err) -@@ -477,6 +485,8 @@ static ssize_t gpiommc_config_attr_store - WARN_ON(1); - err = -ENOSYS; - out: -+ mutex_unlock(&dev->mutex); -+ - return err ? err : count; - } - -@@ -513,6 +523,7 @@ static struct config_item *gpiommc_make_ - if (!dev) - return NULL; - -+ mutex_init(&dev->mutex); - config_item_init_type_name(&dev->item, name, - &gpiommc_dev_ci_type); - diff --git a/target/linux/generic-2.6/patches-2.6.28/924-cs5535_gpio.patch b/target/linux/generic-2.6/patches-2.6.28/924-cs5535_gpio.patch deleted file mode 100644 index 453affe58..000000000 --- a/target/linux/generic-2.6/patches-2.6.28/924-cs5535_gpio.patch +++ /dev/null @@ -1,102 +0,0 @@ ---- a/drivers/char/cs5535_gpio.c -+++ b/drivers/char/cs5535_gpio.c -@@ -15,6 +15,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -48,6 +49,7 @@ static struct pci_device_id divil_pci[] - MODULE_DEVICE_TABLE(pci, divil_pci); - - static struct cdev cs5535_gpio_cdev; -+static struct class *cs5535_gpio_class; - - /* reserve 32 entries even though some aren't usable */ - #define CS5535_GPIO_COUNT 32 -@@ -66,9 +68,14 @@ static struct gpio_regmap rm[] = - { 0x30, 0x00, '1', '0' }, /* GPIOx_READ_BACK / GPIOx_OUT_VAL */ - { 0x20, 0x20, 'I', 'i' }, /* GPIOx_IN_EN */ - { 0x04, 0x04, 'O', 'o' }, /* GPIOx_OUT_EN */ -+ { 0x10, 0x10, 'A', 'a' }, /* GPIOx_OUT_AUX1_SEL */ -+ { 0x14, 0x14, 'B', 'b' }, /* GPIOx_OUT_AUX2_SEL */ - { 0x08, 0x08, 't', 'T' }, /* GPIOx_OUT_OD_EN */ - { 0x18, 0x18, 'P', 'p' }, /* GPIOx_OUT_PU_EN */ - { 0x1c, 0x1c, 'D', 'd' }, /* GPIOx_OUT_PD_EN */ -+ { 0x24, 0x24, 'N', 'n' }, /* GPIOx_IN_INV_EN */ -+ { 0x0c, 0x0c, 'X', 'x' }, /* GPIOx_OUT_INV_EN */ -+ { 0x00, 0x00, 'H', 'L' }, /* GPIOx_OUT_VAL */ - }; - - -@@ -177,7 +184,7 @@ static int __init cs5535_gpio_init(void) - { - dev_t dev_id; - u32 low, hi; -- int retval; -+ int retval, i; - - if (pci_dev_present(divil_pci) == 0) { - printk(KERN_WARNING NAME ": DIVIL not found\n"); -@@ -232,23 +239,54 @@ static int __init cs5535_gpio_init(void) - major = MAJOR(dev_id); - } - -- if (retval) { -- release_region(gpio_base, CS5535_GPIO_SIZE); -- return -1; -- } -+ if (retval) -+ goto error; - - printk(KERN_DEBUG NAME ": base=%#x mask=%#lx major=%d\n", - gpio_base, mask, major); - - cdev_init(&cs5535_gpio_cdev, &cs5535_gpio_fops); -- cdev_add(&cs5535_gpio_cdev, dev_id, CS5535_GPIO_COUNT); -+ retval = cdev_add(&cs5535_gpio_cdev, dev_id, CS5535_GPIO_COUNT); -+ if (retval) { -+ kobject_put(&cs5535_gpio_cdev.kobj); -+ goto error_region; -+ } -+ -+ cs5535_gpio_class = class_create(THIS_MODULE, "cs5535_gpio"); -+ if (IS_ERR(cs5535_gpio_class)) { -+ printk(KERN_ERR "Error creating cs5535_gpio class\n"); -+ cdev_del(&cs5535_gpio_cdev); -+ retval = PTR_ERR(cs5535_gpio_class); -+ goto error_region; -+ } -+ -+ for (i = 0; i < CS5535_GPIO_COUNT; i++) { -+ if (mask & (1< -- -- .file "crtsavres.S" -- .section ".text" -- --#ifdef CONFIG_CC_OPTIMIZE_FOR_SIZE -- --/* Routines for saving integer registers, called by the compiler. */ --/* Called with r11 pointing to the stack header word of the caller of the */ --/* function, just beyond the end of the integer save area. */ -- --_GLOBAL(_savegpr_14) --_GLOBAL(_save32gpr_14) -- stw 14,-72(11) /* save gp registers */ --_GLOBAL(_savegpr_15) --_GLOBAL(_save32gpr_15) -- stw 15,-68(11) --_GLOBAL(_savegpr_16) --_GLOBAL(_save32gpr_16) -- stw 16,-64(11) --_GLOBAL(_savegpr_17) --_GLOBAL(_save32gpr_17) -- stw 17,-60(11) --_GLOBAL(_savegpr_18) --_GLOBAL(_save32gpr_18) -- stw 18,-56(11) --_GLOBAL(_savegpr_19) --_GLOBAL(_save32gpr_19) -- stw 19,-52(11) --_GLOBAL(_savegpr_20) --_GLOBAL(_save32gpr_20) -- stw 20,-48(11) --_GLOBAL(_savegpr_21) --_GLOBAL(_save32gpr_21) -- stw 21,-44(11) --_GLOBAL(_savegpr_22) --_GLOBAL(_save32gpr_22) -- stw 22,-40(11) --_GLOBAL(_savegpr_23) --_GLOBAL(_save32gpr_23) -- stw 23,-36(11) --_GLOBAL(_savegpr_24) --_GLOBAL(_save32gpr_24) -- stw 24,-32(11) --_GLOBAL(_savegpr_25) --_GLOBAL(_save32gpr_25) -- stw 25,-28(11) --_GLOBAL(_savegpr_26) --_GLOBAL(_save32gpr_26) -- stw 26,-24(11) --_GLOBAL(_savegpr_27) --_GLOBAL(_save32gpr_27) -- stw 27,-20(11) --_GLOBAL(_savegpr_28) --_GLOBAL(_save32gpr_28) -- stw 28,-16(11) --_GLOBAL(_savegpr_29) --_GLOBAL(_save32gpr_29) -- stw 29,-12(11) --_GLOBAL(_savegpr_30) --_GLOBAL(_save32gpr_30) -- stw 30,-8(11) --_GLOBAL(_savegpr_31) --_GLOBAL(_save32gpr_31) -- stw 31,-4(11) -- blr -- --/* Routines for restoring integer registers, called by the compiler. */ --/* Called with r11 pointing to the stack header word of the caller of the */ --/* function, just beyond the end of the integer restore area. */ -- --_GLOBAL(_restgpr_14) --_GLOBAL(_rest32gpr_14) -- lwz 14,-72(11) /* restore gp registers */ --_GLOBAL(_restgpr_15) --_GLOBAL(_rest32gpr_15) -- lwz 15,-68(11) --_GLOBAL(_restgpr_16) --_GLOBAL(_rest32gpr_16) -- lwz 16,-64(11) --_GLOBAL(_restgpr_17) --_GLOBAL(_rest32gpr_17) -- lwz 17,-60(11) --_GLOBAL(_restgpr_18) --_GLOBAL(_rest32gpr_18) -- lwz 18,-56(11) --_GLOBAL(_restgpr_19) --_GLOBAL(_rest32gpr_19) -- lwz 19,-52(11) --_GLOBAL(_restgpr_20) --_GLOBAL(_rest32gpr_20) -- lwz 20,-48(11) --_GLOBAL(_restgpr_21) --_GLOBAL(_rest32gpr_21) -- lwz 21,-44(11) --_GLOBAL(_restgpr_22) --_GLOBAL(_rest32gpr_22) -- lwz 22,-40(11) --_GLOBAL(_restgpr_23) --_GLOBAL(_rest32gpr_23) -- lwz 23,-36(11) --_GLOBAL(_restgpr_24) --_GLOBAL(_rest32gpr_24) -- lwz 24,-32(11) --_GLOBAL(_restgpr_25) --_GLOBAL(_rest32gpr_25) -- lwz 25,-28(11) --_GLOBAL(_restgpr_26) --_GLOBAL(_rest32gpr_26) -- lwz 26,-24(11) --_GLOBAL(_restgpr_27) --_GLOBAL(_rest32gpr_27) -- lwz 27,-20(11) --_GLOBAL(_restgpr_28) --_GLOBAL(_rest32gpr_28) -- lwz 28,-16(11) --_GLOBAL(_restgpr_29) --_GLOBAL(_rest32gpr_29) -- lwz 29,-12(11) --_GLOBAL(_restgpr_30) --_GLOBAL(_rest32gpr_30) -- lwz 30,-8(11) --_GLOBAL(_restgpr_31) --_GLOBAL(_rest32gpr_31) -- lwz 31,-4(11) -- blr -- --/* Routines for restoring integer registers, called by the compiler. */ --/* Called with r11 pointing to the stack header word of the caller of the */ --/* function, just beyond the end of the integer restore area. */ -- --_GLOBAL(_restgpr_14_x) --_GLOBAL(_rest32gpr_14_x) -- lwz 14,-72(11) /* restore gp registers */ --_GLOBAL(_restgpr_15_x) --_GLOBAL(_rest32gpr_15_x) -- lwz 15,-68(11) --_GLOBAL(_restgpr_16_x) --_GLOBAL(_rest32gpr_16_x) -- lwz 16,-64(11) --_GLOBAL(_restgpr_17_x) --_GLOBAL(_rest32gpr_17_x) -- lwz 17,-60(11) --_GLOBAL(_restgpr_18_x) --_GLOBAL(_rest32gpr_18_x) -- lwz 18,-56(11) --_GLOBAL(_restgpr_19_x) --_GLOBAL(_rest32gpr_19_x) -- lwz 19,-52(11) --_GLOBAL(_restgpr_20_x) --_GLOBAL(_rest32gpr_20_x) -- lwz 20,-48(11) --_GLOBAL(_restgpr_21_x) --_GLOBAL(_rest32gpr_21_x) -- lwz 21,-44(11) --_GLOBAL(_restgpr_22_x) --_GLOBAL(_rest32gpr_22_x) -- lwz 22,-40(11) --_GLOBAL(_restgpr_23_x) --_GLOBAL(_rest32gpr_23_x) -- lwz 23,-36(11) --_GLOBAL(_restgpr_24_x) --_GLOBAL(_rest32gpr_24_x) -- lwz 24,-32(11) --_GLOBAL(_restgpr_25_x) --_GLOBAL(_rest32gpr_25_x) -- lwz 25,-28(11) --_GLOBAL(_restgpr_26_x) --_GLOBAL(_rest32gpr_26_x) -- lwz 26,-24(11) --_GLOBAL(_restgpr_27_x) --_GLOBAL(_rest32gpr_27_x) -- lwz 27,-20(11) --_GLOBAL(_restgpr_28_x) --_GLOBAL(_rest32gpr_28_x) -- lwz 28,-16(11) --_GLOBAL(_restgpr_29_x) --_GLOBAL(_rest32gpr_29_x) -- lwz 29,-12(11) --_GLOBAL(_restgpr_30_x) --_GLOBAL(_rest32gpr_30_x) -- lwz 30,-8(11) --_GLOBAL(_restgpr_31_x) --_GLOBAL(_rest32gpr_31_x) -- lwz 0,4(11) -- lwz 31,-4(11) -- mtlr 0 -- mr 1,11 -- blr --#endif ---- a/arch/powerpc/lib/Makefile -+++ b/arch/powerpc/lib/Makefile -@@ -8,7 +8,7 @@ endif - - obj-y := string.o alloc.o \ - checksum_$(CONFIG_WORD_SIZE).o --obj-$(CONFIG_PPC32) += div64.o copy_32.o crtsavres.o -+obj-$(CONFIG_PPC32) += div64.o copy_32.o - obj-$(CONFIG_HAS_IOMEM) += devres.o - - obj-$(CONFIG_PPC64) += copypage_64.o copyuser_64.o \ ---- a/arch/powerpc/Makefile -+++ b/arch/powerpc/Makefile -@@ -92,8 +92,6 @@ endif - else - KBUILD_CFLAGS += $(call cc-option,-mtune=power4) - endif --else --LDFLAGS_MODULE += arch/powerpc/lib/crtsavres.o - endif - - ifeq ($(CONFIG_TUNE_CELL),y) diff --git a/target/linux/generic-2.6/patches-2.6.28/960-arm_lzma_loader.patch b/target/linux/generic-2.6/patches-2.6.28/960-arm_lzma_loader.patch deleted file mode 100644 index 986c28271..000000000 --- a/target/linux/generic-2.6/patches-2.6.28/960-arm_lzma_loader.patch +++ /dev/null @@ -1,719 +0,0 @@ ---- a/arch/arm/boot/compressed/Makefile -+++ b/arch/arm/boot/compressed/Makefile -@@ -67,7 +67,7 @@ endif - - SEDFLAGS = s/TEXT_START/$(ZTEXTADDR)/;s/BSS_START/$(ZBSSADDR)/ - --targets := vmlinux vmlinux.lds piggy.gz piggy.o font.o font.c \ -+targets := vmlinux vmlinux.lds piggy.lzma piggy.o font.o font.c \ - head.o misc.o $(OBJS) - - ifeq ($(CONFIG_FUNCTION_TRACER),y) -@@ -100,10 +100,10 @@ $(obj)/vmlinux: $(obj)/vmlinux.lds $(obj - $(call if_changed,ld) - @: - --$(obj)/piggy.gz: $(obj)/../Image FORCE -- $(call if_changed,gzip) -+$(obj)/piggy.lzma: $(obj)/../Image FORCE -+ $(call if_changed,lzma) - --$(obj)/piggy.o: $(obj)/piggy.gz FORCE -+$(obj)/piggy.o: $(obj)/piggy.lzma FORCE - - CFLAGS_font.o := -Dstatic= - ---- a/arch/arm/boot/compressed/misc.c -+++ b/arch/arm/boot/compressed/misc.c -@@ -166,36 +166,10 @@ static inline __ptr_t memcpy(__ptr_t __d - return __dest; - } - --/* -- * gzip delarations -- */ --#define OF(args) args --#define STATIC static -- --typedef unsigned char uch; --typedef unsigned short ush; --typedef unsigned long ulg; -- --#define WSIZE 0x8000 /* Window size must be at least 32k, */ -+#define WSIZE 0x20000 /* Window size must be at least 128k, */ - /* and a power of two */ - --static uch *inbuf; /* input buffer */ --static uch window[WSIZE]; /* Sliding window buffer */ -- --static unsigned insize; /* valid bytes in inbuf */ --static unsigned inptr; /* index of next byte to be processed in inbuf */ --static unsigned outcnt; /* bytes in output buffer */ -- --/* gzip flag byte */ --#define ASCII_FLAG 0x01 /* bit 0 set: file probably ascii text */ --#define CONTINUATION 0x02 /* bit 1 set: continuation of multi-part gzip file */ --#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */ --#define ORIG_NAME 0x08 /* bit 3 set: original file name present */ --#define COMMENT 0x10 /* bit 4 set: file comment present */ --#define ENCRYPTED 0x20 /* bit 5 set: file is encrypted */ --#define RESERVED 0xC0 /* bit 6,7: reserved */ -- --#define get_byte() (inptr < insize ? inbuf[inptr++] : fill_inbuf()) -+static u8 window[WSIZE]; /* Sliding window buffer */ - - /* Diagnostic functions */ - #ifdef DEBUG -@@ -214,24 +188,21 @@ static unsigned outcnt; /* bytes in out - # define Tracecv(c,x) - #endif - --static int fill_inbuf(void); --static void flush_window(void); - static void error(char *m); - - extern char input_data[]; - extern char input_data_end[]; - --static uch *output_data; --static ulg output_ptr; --static ulg bytes_out; -+static unsigned long output_ptr; -+static unsigned long bytes_out; - - static void error(char *m); - - static void putstr(const char *); - - extern int end; --static ulg free_mem_ptr; --static ulg free_mem_end_ptr; -+static unsigned long free_mem_ptr; -+static unsigned long free_mem_end_ptr; - - #ifdef STANDALONE_DEBUG - #define NO_INFLATE_MALLOC -@@ -239,50 +210,10 @@ static ulg free_mem_end_ptr; - - #define ARCH_HAS_DECOMP_WDOG - --#include "../../../../lib/inflate.c" -- --/* =========================================================================== -- * Fill the input buffer. This is called only when the buffer is empty -- * and at least one byte is really needed. -- */ --int fill_inbuf(void) --{ -- if (insize != 0) -- error("ran out of input data"); -- -- inbuf = input_data; -- insize = &input_data_end[0] - &input_data[0]; -- -- inptr = 1; -- return inbuf[0]; --} -- --/* =========================================================================== -- * Write the output window window[0..outcnt-1] and update crc and bytes_out. -- * (Used for the decompressed data only.) -- */ --void flush_window(void) --{ -- ulg c = crc; -- unsigned n; -- uch *in, *out, ch; -- -- in = window; -- out = &output_data[output_ptr]; -- for (n = 0; n < outcnt; n++) { -- ch = *out++ = *in++; -- c = crc_32_tab[((int)c ^ ch) & 0xff] ^ (c >> 8); -- } -- crc = c; -- bytes_out += (ulg)outcnt; -- output_ptr += (ulg)outcnt; -- outcnt = 0; -- putstr("."); --} -- - #ifndef arch_error - #define arch_error(x) - #endif -+#include "unlzma.c" - - static void error(char *x) - { -@@ -297,20 +228,16 @@ static void error(char *x) - - #ifndef STANDALONE_DEBUG - --ulg --decompress_kernel(ulg output_start, ulg free_mem_ptr_p, ulg free_mem_ptr_end_p, -+unsigned long -+decompress_kernel(unsigned long output_start, unsigned long free_mem_ptr_p, unsigned long free_mem_ptr_end_p, - int arch_id) - { -- output_data = (uch *)output_start; /* Points to kernel start */ -- free_mem_ptr = free_mem_ptr_p; -- free_mem_end_ptr = free_mem_ptr_end_p; - __machine_arch_type = arch_id; - - arch_decomp_setup(); - -- makecrc(); - putstr("Uncompressing Linux..."); -- gunzip(); -+ output_ptr += unlzma((u8 *) output_start, input_data, window); - putstr(" done, booting the kernel.\n"); - return output_ptr; - } -@@ -320,11 +247,8 @@ char output_buffer[1500*1024]; - - int main() - { -- output_data = output_buffer; -- -- makecrc(); - putstr("Uncompressing Linux..."); -- gunzip(); -+ unlzma((u8 *) output_buffer, input_data, window); - putstr("done.\n"); - return 0; - } ---- a/arch/arm/boot/compressed/piggy.S -+++ b/arch/arm/boot/compressed/piggy.S -@@ -1,6 +1,6 @@ - .section .piggydata,#alloc - .globl input_data - input_data: -- .incbin "arch/arm/boot/compressed/piggy.gz" -+ .incbin "arch/arm/boot/compressed/piggy.lzma" - .globl input_data_end - input_data_end: ---- /dev/null -+++ b/arch/arm/boot/compressed/unlzma.c -@@ -0,0 +1,429 @@ -+/* -+ * Copyright (c) 2009 Felix Fietkau -+ * -+ * 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, -+ * 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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -+ * -+ * uncompress.c -+ */ -+ -+#include -+#include -+#include "unlzma.h" -+ -+struct unlzma_ctx { -+ const u8 *next_in; -+ u8 *next_out; -+ u8 *outbuf; -+ -+ /* reader state */ -+ u32 code; -+ u32 range; -+ u32 bound; -+ -+ /* writer state */ -+ u8 previous_byte; -+ ssize_t pos; -+ -+ /* cstate */ -+ int state; -+ u32 rep0, rep1, rep2, rep3; -+ -+ void *workspace; -+} ctx; -+ -+static int inbs = 0; -+static inline u8 -+rc_read(void) -+{ -+#if 0 -+ if (unlikely(++inbs > 16 * 1024)) { -+ putstr("."); -+ inbs = 0; -+ } -+#endif -+ return *(ctx.next_in++); -+} -+ -+ -+static inline void -+rc_get_code(void) -+{ -+ ctx.code = (ctx.code << 8) | rc_read(); -+} -+ -+static inline void -+rc_normalize(void) -+{ -+ if (ctx.range < (1 << RC_TOP_BITS)) { -+ ctx.range <<= 8; -+ rc_get_code(); -+ } -+} -+ -+static inline int -+rc_is_bit_0(u16 *p) -+{ -+ rc_normalize(); -+ ctx.bound = *p * (ctx.range >> RC_MODEL_TOTAL_BITS); -+ return ctx.code < ctx.bound; -+} -+ -+static inline void -+rc_update_bit_0(u16 *p) -+{ -+ ctx.range = ctx.bound; -+ *p += ((1 << RC_MODEL_TOTAL_BITS) - *p) >> RC_MOVE_BITS; -+} -+ -+static inline void -+rc_update_bit_1(u16 *p) -+{ -+ ctx.range -= ctx.bound; -+ ctx.code -= ctx.bound; -+ *p -= *p >> RC_MOVE_BITS; -+} -+ -+static inline bool -+rc_get_bit(u16 *p, int *symbol) -+{ -+ if (rc_is_bit_0(p)) { -+ rc_update_bit_0(p); -+ *symbol *= 2; -+ return 0; -+ } else { -+ rc_update_bit_1(p); -+ *symbol = *symbol * 2 + 1; -+ return 1; -+ } -+} -+ -+static inline int -+rc_direct_bit(void) -+{ -+ rc_normalize(); -+ ctx.range >>= 1; -+ if (ctx.code >= ctx.range) { -+ ctx.code -= ctx.range; -+ return 1; -+ } -+ return 0; -+} -+ -+static inline void -+rc_bit_tree_decode(u16 *p, int num_levels, int *symbol) -+{ -+ int i = num_levels; -+ -+ *symbol = 1; -+ while (i--) -+ rc_get_bit(p + *symbol, symbol); -+ *symbol -= 1 << num_levels; -+} -+ -+static inline u8 -+peek_old_byte(u32 offs) -+{ -+ u32 pos = ctx.pos - offs; -+ return ctx.outbuf[pos]; -+} -+ -+static inline void -+write_byte(u8 byte) -+{ -+ ctx.previous_byte = byte; -+ *(ctx.next_out++) = byte; -+ ctx.pos++; -+} -+ -+ -+static inline void -+copy_byte(u32 offs) -+{ -+ write_byte(peek_old_byte(offs)); -+} -+ -+static inline void -+copy_bytes(u32 rep0, int len) -+{ -+ do { -+ copy_byte(rep0); -+ len--; -+ } while (len != 0); -+} -+ -+static inline void -+process_bit0(u16 *p, int pos_state, u16 *prob, -+ int lc, u32 literal_pos_mask) -+{ -+ int mi = 1; -+ rc_update_bit_0(prob); -+ prob = (p + LZMA_LITERAL + -+ (LZMA_LIT_SIZE -+ * (((ctx.pos & literal_pos_mask) << lc) -+ + (ctx.previous_byte >> (8 - lc)))) -+ ); -+ -+ if (ctx.state >= LZMA_NUM_LIT_STATES) { -+ int match_byte = peek_old_byte(ctx.rep0); -+ do { -+ u16 bit; -+ u16 *prob_lit; -+ -+ match_byte <<= 1; -+ bit = match_byte & 0x100; -+ prob_lit = prob + 0x100 + bit + mi; -+ if (rc_get_bit(prob_lit, &mi) != !!bit) -+ break; -+ } while (mi < 0x100); -+ } -+ while (mi < 0x100) { -+ u16 *prob_lit = prob + mi; -+ rc_get_bit(prob_lit, &mi); -+ } -+ write_byte(mi); -+ if (ctx.state < 4) -+ ctx.state = 0; -+ else if (ctx.state < 10) -+ ctx.state -= 3; -+ else -+ ctx.state -= 6; -+} -+ -+static inline void -+process_bit1(u16 *p, int pos_state, u16 *prob) -+{ -+ int offset; -+ u16 *prob_len; -+ int num_bits; -+ int len; -+ -+ rc_update_bit_1(prob); -+ prob = p + LZMA_IS_REP + ctx.state; -+ if (rc_is_bit_0(prob)) { -+ rc_update_bit_0(prob); -+ ctx.rep3 = ctx.rep2; -+ ctx.rep2 = ctx.rep1; -+ ctx.rep1 = ctx.rep0; -+ ctx.state = ctx.state < LZMA_NUM_LIT_STATES ? 0 : 3; -+ prob = p + LZMA_LEN_CODER; -+ } else { -+ rc_update_bit_1(prob); -+ prob = p + LZMA_IS_REP_G0 + ctx.state; -+ if (rc_is_bit_0(prob)) { -+ rc_update_bit_0(prob); -+ prob = (p + LZMA_IS_REP_0_LONG -+ + (ctx.state << -+ LZMA_NUM_POS_BITS_MAX) + -+ pos_state); -+ if (rc_is_bit_0(prob)) { -+ rc_update_bit_0(prob); -+ -+ ctx.state = ctx.state < LZMA_NUM_LIT_STATES ? -+ 9 : 11; -+ copy_byte(ctx.rep0); -+ return; -+ } else { -+ rc_update_bit_1(prob); -+ } -+ } else { -+ u32 distance; -+ -+ rc_update_bit_1(prob); -+ prob = p + LZMA_IS_REP_G1 + ctx.state; -+ if (rc_is_bit_0(prob)) { -+ rc_update_bit_0(prob); -+ distance = ctx.rep1; -+ } else { -+ rc_update_bit_1(prob); -+ prob = p + LZMA_IS_REP_G2 + ctx.state; -+ if (rc_is_bit_0(prob)) { -+ rc_update_bit_0(prob); -+ distance = ctx.rep2; -+ } else { -+ rc_update_bit_1(prob); -+ distance = ctx.rep3; -+ ctx.rep3 = ctx.rep2; -+ } -+ ctx.rep2 = ctx.rep1; -+ } -+ ctx.rep1 = ctx.rep0; -+ ctx.rep0 = distance; -+ } -+ ctx.state = ctx.state < LZMA_NUM_LIT_STATES ? 8 : 11; -+ prob = p + LZMA_REP_LEN_CODER; -+ } -+ -+ prob_len = prob + LZMA_LEN_CHOICE; -+ if (rc_is_bit_0(prob_len)) { -+ rc_update_bit_0(prob_len); -+ prob_len = (prob + LZMA_LEN_LOW -+ + (pos_state << -+ LZMA_LEN_NUM_LOW_BITS)); -+ offset = 0; -+ num_bits = LZMA_LEN_NUM_LOW_BITS; -+ } else { -+ rc_update_bit_1(prob_len); -+ prob_len = prob + LZMA_LEN_CHOICE_2; -+ if (rc_is_bit_0(prob_len)) { -+ rc_update_bit_0(prob_len); -+ prob_len = (prob + LZMA_LEN_MID -+ + (pos_state << -+ LZMA_LEN_NUM_MID_BITS)); -+ offset = 1 << LZMA_LEN_NUM_LOW_BITS; -+ num_bits = LZMA_LEN_NUM_MID_BITS; -+ } else { -+ rc_update_bit_1(prob_len); -+ prob_len = prob + LZMA_LEN_HIGH; -+ offset = ((1 << LZMA_LEN_NUM_LOW_BITS) -+ + (1 << LZMA_LEN_NUM_MID_BITS)); -+ num_bits = LZMA_LEN_NUM_HIGH_BITS; -+ } -+ } -+ -+ rc_bit_tree_decode(prob_len, num_bits, &len); -+ len += offset; -+ -+ if (ctx.state < 4) { -+ int pos_slot; -+ -+ ctx.state += LZMA_NUM_LIT_STATES; -+ prob = -+ p + LZMA_POS_SLOT + -+ ((len < -+ LZMA_NUM_LEN_TO_POS_STATES ? len : -+ LZMA_NUM_LEN_TO_POS_STATES - 1) -+ << LZMA_NUM_POS_SLOT_BITS); -+ rc_bit_tree_decode(prob, -+ LZMA_NUM_POS_SLOT_BITS, -+ &pos_slot); -+ if (pos_slot >= LZMA_START_POS_MODEL_INDEX) { -+ int i, mi; -+ num_bits = (pos_slot >> 1) - 1; -+ ctx.rep0 = 2 | (pos_slot & 1); -+ if (pos_slot < LZMA_END_POS_MODEL_INDEX) { -+ ctx.rep0 <<= num_bits; -+ prob = p + LZMA_SPEC_POS + -+ ctx.rep0 - pos_slot - 1; -+ } else { -+ num_bits -= LZMA_NUM_ALIGN_BITS; -+ while (num_bits--) -+ ctx.rep0 = (ctx.rep0 << 1) | -+ rc_direct_bit(); -+ prob = p + LZMA_ALIGN; -+ ctx.rep0 <<= LZMA_NUM_ALIGN_BITS; -+ num_bits = LZMA_NUM_ALIGN_BITS; -+ } -+ i = 1; -+ mi = 1; -+ while (num_bits--) { -+ if (rc_get_bit(prob + mi, &mi)) -+ ctx.rep0 |= i; -+ i <<= 1; -+ } -+ } else -+ ctx.rep0 = pos_slot; -+ if (++(ctx.rep0) == 0) -+ return; -+ } -+ -+ len += LZMA_MATCH_MIN_LEN; -+ -+ copy_bytes(ctx.rep0, len); -+} -+ -+ -+static int -+do_unlzma(void) -+{ -+ u8 hdr_buf[sizeof(struct lzma_header)]; -+ struct lzma_header *header = (struct lzma_header *)hdr_buf; -+ u32 pos_state_mask; -+ u32 literal_pos_mask; -+ int lc, pb, lp; -+ int num_probs; -+ int i, mi; -+ u16 *p; -+ -+ for (i = 0; i < sizeof(struct lzma_header); i++) { -+ hdr_buf[i] = rc_read(); -+ } -+ -+ ctx.pos = 0; -+ ctx.state = 0; -+ ctx.rep0 = ctx.rep1 = ctx.rep2 = ctx.rep3 = 1; -+ -+ ctx.previous_byte = 0; -+ ctx.code = 0; -+ ctx.range = 0xFFFFFFFF; -+ -+ if (header->pos >= (9 * 5 * 5)) -+ return -1; -+ -+ mi = 0; -+ lc = header->pos; -+ while (lc >= 9) { -+ mi++; -+ lc -= 9; -+ } -+ pb = 0; -+ lp = mi; -+ while (lp >= 5) { -+ pb++; -+ lp -= 5; -+ } -+ pos_state_mask = (1 << pb) - 1; -+ literal_pos_mask = (1 << lp) - 1; -+ -+ p = (u16 *) ctx.workspace; -+ if (!p) -+ return -1; -+ -+ num_probs = LZMA_LITERAL + (LZMA_LIT_SIZE << (lc + lp)); -+ for (i = 0; i < num_probs; i++) -+ p[i] = (1 << RC_MODEL_TOTAL_BITS) >> 1; -+ -+ for (i = 0; i < 5; i++) -+ rc_get_code(); -+ -+ while (1) { -+ int pos_state = ctx.pos & pos_state_mask; -+ u16 *prob = p + LZMA_IS_MATCH + -+ (ctx.state << LZMA_NUM_POS_BITS_MAX) + pos_state; -+ if (rc_is_bit_0(prob)) -+ process_bit0(p, pos_state, prob, -+ lc, literal_pos_mask); -+ else { -+ process_bit1(p, pos_state, prob); -+ if (ctx.rep0 == 0) -+ break; -+ } -+ } -+ -+ return ctx.pos; -+} -+ -+ -+static int unlzma(unsigned char *dest, const unsigned char *src, unsigned char *workspace) -+{ -+ memset(&ctx, 0, sizeof(ctx)); -+ ctx.outbuf = dest; -+ ctx.next_in = src; -+ ctx.next_out = dest; -+ ctx.workspace = workspace; -+ -+ return do_unlzma(); -+} -+ -+ ---- /dev/null -+++ b/arch/arm/boot/compressed/unlzma.h -@@ -0,0 +1,81 @@ -+/* LZMA uncompresion module for pcomp -+ * Copyright (C) 2009 Felix Fietkau -+ * -+ * Based on: -+ * Initial Linux kernel adaptation -+ * Copyright (C) 2006 Alain < alain@knaff.lu > -+ * -+ * Based on small lzma deflate implementation/Small range coder -+ * implementation for lzma. -+ * Copyright (C) 2006 Aurelien Jacobs < aurel@gnuage.org > -+ * -+ * Based on LzmaDecode.c from the LZMA SDK 4.22 (http://www.7-zip.org/) -+ * Copyright (C) 1999-2005 Igor Pavlov -+ * -+ * 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 __UNLZMA_H -+#define __UNLZMA_H -+ -+struct lzma_header { -+ __u8 pos; -+ __le32 dict_size; -+ __le64 uncompr_size; -+} __attribute__ ((packed)); -+ -+ -+#define RC_TOP_BITS 24 -+#define RC_MOVE_BITS 5 -+#define RC_MODEL_TOTAL_BITS 11 -+ -+#define LZMA_BASE_SIZE 1846 -+#define LZMA_LIT_SIZE 768 -+ -+#define LZMA_NUM_POS_BITS_MAX 4 -+ -+#define LZMA_LEN_NUM_LOW_BITS 3 -+#define LZMA_LEN_NUM_MID_BITS 3 -+#define LZMA_LEN_NUM_HIGH_BITS 8 -+ -+#define LZMA_LEN_CHOICE 0 -+#define LZMA_LEN_CHOICE_2 (LZMA_LEN_CHOICE + 1) -+#define LZMA_LEN_LOW (LZMA_LEN_CHOICE_2 + 1) -+#define LZMA_LEN_MID (LZMA_LEN_LOW \ -+ + (1 << (LZMA_NUM_POS_BITS_MAX + LZMA_LEN_NUM_LOW_BITS))) -+#define LZMA_LEN_HIGH (LZMA_LEN_MID \ -+ +(1 << (LZMA_NUM_POS_BITS_MAX + LZMA_LEN_NUM_MID_BITS))) -+#define LZMA_NUM_LEN_PROBS (LZMA_LEN_HIGH + (1 << LZMA_LEN_NUM_HIGH_BITS)) -+ -+#define LZMA_NUM_STATES 12 -+#define LZMA_NUM_LIT_STATES 7 -+ -+#define LZMA_START_POS_MODEL_INDEX 4 -+#define LZMA_END_POS_MODEL_INDEX 14 -+#define LZMA_NUM_FULL_DISTANCES (1 << (LZMA_END_POS_MODEL_INDEX >> 1)) -+ -+#define LZMA_NUM_POS_SLOT_BITS 6 -+#define LZMA_NUM_LEN_TO_POS_STATES 4 -+ -+#define LZMA_NUM_ALIGN_BITS 4 -+ -+#define LZMA_MATCH_MIN_LEN 2 -+ -+#define LZMA_IS_MATCH 0 -+#define LZMA_IS_REP (LZMA_IS_MATCH + (LZMA_NUM_STATES << LZMA_NUM_POS_BITS_MAX)) -+#define LZMA_IS_REP_G0 (LZMA_IS_REP + LZMA_NUM_STATES) -+#define LZMA_IS_REP_G1 (LZMA_IS_REP_G0 + LZMA_NUM_STATES) -+#define LZMA_IS_REP_G2 (LZMA_IS_REP_G1 + LZMA_NUM_STATES) -+#define LZMA_IS_REP_0_LONG (LZMA_IS_REP_G2 + LZMA_NUM_STATES) -+#define LZMA_POS_SLOT (LZMA_IS_REP_0_LONG \ -+ + (LZMA_NUM_STATES << LZMA_NUM_POS_BITS_MAX)) -+#define LZMA_SPEC_POS (LZMA_POS_SLOT \ -+ +(LZMA_NUM_LEN_TO_POS_STATES << LZMA_NUM_POS_SLOT_BITS)) -+#define LZMA_ALIGN (LZMA_SPEC_POS \ -+ + LZMA_NUM_FULL_DISTANCES - LZMA_END_POS_MODEL_INDEX) -+#define LZMA_LEN_CODER (LZMA_ALIGN + (1 << LZMA_NUM_ALIGN_BITS)) -+#define LZMA_REP_LEN_CODER (LZMA_LEN_CODER + LZMA_NUM_LEN_PROBS) -+#define LZMA_LITERAL (LZMA_REP_LEN_CODER + LZMA_NUM_LEN_PROBS) -+ -+#endif ---- a/scripts/Makefile.lib -+++ b/scripts/Makefile.lib -@@ -182,4 +182,6 @@ cmd_objcopy = $(OBJCOPY) $(OBJCOPYFLAGS) - quiet_cmd_gzip = GZIP $@ - cmd_gzip = gzip -f -9 < $< > $@ - -+quiet_cmd_lzma = LZMA $@ -+cmd_lzma = lzma e $< $@ -lc1 -lp2 -pb2 -eos - diff --git a/target/linux/generic-2.6/patches-2.6.28/970-ocf_kbuild_integration.patch b/target/linux/generic-2.6/patches-2.6.28/970-ocf_kbuild_integration.patch deleted file mode 100644 index ee2cf1b31..000000000 --- a/target/linux/generic-2.6/patches-2.6.28/970-ocf_kbuild_integration.patch +++ /dev/null @@ -1,25 +0,0 @@ ---- a/crypto/Kconfig -+++ b/crypto/Kconfig -@@ -735,6 +735,8 @@ config CRYPTO_ANSI_CPRNG - for cryptographic modules. Uses the Algorithm specified in - ANSI X9.31 A.2.4 - -+source "crypto/ocf/Kconfig" -+ - source "drivers/crypto/Kconfig" - - endif # if CRYPTO ---- a/crypto/Makefile -+++ b/crypto/Makefile -@@ -79,6 +79,11 @@ obj-$(CONFIG_CRYPTO_ANSI_CPRNG) += ansi_ - obj-$(CONFIG_CRYPTO_TEST) += tcrypt.o - - # -+# OCF -+# -+obj-$(CONFIG_OCF_OCF) += ocf/ -+ -+# - # generic algorithms and the async_tx api - # - obj-$(CONFIG_XOR_BLOCKS) += xor.o diff --git a/target/linux/generic-2.6/patches-2.6.28/971-ocf_20080917.patch b/target/linux/generic-2.6/patches-2.6.28/971-ocf_20080917.patch deleted file mode 100644 index 203266c56..000000000 --- a/target/linux/generic-2.6/patches-2.6.28/971-ocf_20080917.patch +++ /dev/null @@ -1,160 +0,0 @@ ---- a/drivers/char/random.c -+++ b/drivers/char/random.c -@@ -129,6 +129,9 @@ - * unsigned int value); - * void add_interrupt_randomness(int irq); - * -+ * void random_input_words(__u32 *buf, size_t wordcount, int ent_count) -+ * int random_input_wait(void); -+ * - * add_input_randomness() uses the input layer interrupt timing, as well as - * the event type information from the hardware. - * -@@ -140,6 +143,13 @@ - * a better measure, since the timing of the disk interrupts are more - * unpredictable. - * -+ * random_input_words() just provides a raw block of entropy to the input -+ * pool, such as from a hardware entropy generator. -+ * -+ * random_input_wait() suspends the caller until such time as the -+ * entropy pool falls below the write threshold, and returns a count of how -+ * much entropy (in bits) is needed to sustain the pool. -+ * - * All of these routines try to estimate how many bits of randomness a - * particular randomness source. They do this by keeping track of the - * first and second order deltas of the event timings. -@@ -689,6 +699,61 @@ void add_disk_randomness(struct gendisk - } - #endif - -+/* -+ * random_input_words - add bulk entropy to pool -+ * -+ * @buf: buffer to add -+ * @wordcount: number of __u32 words to add -+ * @ent_count: total amount of entropy (in bits) to credit -+ * -+ * this provides bulk input of entropy to the input pool -+ * -+ */ -+void random_input_words(__u32 *buf, size_t wordcount, int ent_count) -+{ -+ mix_pool_bytes(&input_pool, buf, wordcount*4); -+ -+ credit_entropy_bits(&input_pool, ent_count); -+ -+ DEBUG_ENT("crediting %d bits => %d\n", -+ ent_count, input_pool.entropy_count); -+ /* -+ * Wake up waiting processes if we have enough -+ * entropy. -+ */ -+ if (input_pool.entropy_count >= random_read_wakeup_thresh) -+ wake_up_interruptible(&random_read_wait); -+} -+EXPORT_SYMBOL(random_input_words); -+ -+/* -+ * random_input_wait - wait until random needs entropy -+ * -+ * this function sleeps until the /dev/random subsystem actually -+ * needs more entropy, and then return the amount of entropy -+ * that it would be nice to have added to the system. -+ */ -+int random_input_wait(void) -+{ -+ int count; -+ -+ wait_event_interruptible(random_write_wait, -+ input_pool.entropy_count < random_write_wakeup_thresh); -+ -+ count = random_write_wakeup_thresh - input_pool.entropy_count; -+ -+ /* likely we got woken up due to a signal */ -+ if (count <= 0) count = random_read_wakeup_thresh; -+ -+ DEBUG_ENT("requesting %d bits from input_wait()er %d<%d\n", -+ count, -+ input_pool.entropy_count, random_write_wakeup_thresh); -+ -+ return count; -+} -+EXPORT_SYMBOL(random_input_wait); -+ -+ - #define EXTRACT_SIZE 10 - - /********************************************************************* ---- a/fs/fcntl.c -+++ b/fs/fcntl.c -@@ -140,6 +140,7 @@ SYSCALL_DEFINE1(dup, unsigned int, filde - } - return ret; - } -+EXPORT_SYMBOL(sys_dup); - - #define SETFL_MASK (O_APPEND | O_NONBLOCK | O_NDELAY | FASYNC | O_DIRECT | O_NOATIME) - ---- a/include/linux/miscdevice.h -+++ b/include/linux/miscdevice.h -@@ -12,6 +12,7 @@ - #define APOLLO_MOUSE_MINOR 7 - #define PC110PAD_MINOR 9 - /*#define ADB_MOUSE_MINOR 10 FIXME OBSOLETE */ -+#define CRYPTODEV_MINOR 70 /* /dev/crypto */ - #define WATCHDOG_MINOR 130 /* Watchdog timer */ - #define TEMP_MINOR 131 /* Temperature Sensor */ - #define RTC_MINOR 135 ---- a/include/linux/random.h -+++ b/include/linux/random.h -@@ -8,6 +8,7 @@ - #define _LINUX_RANDOM_H - - #include -+#include /* for __u32 in user space */ - - /* ioctl()'s for the random number generator */ - -@@ -32,6 +33,30 @@ - /* Clear the entropy pool and associated counters. (Superuser only.) */ - #define RNDCLEARPOOL _IO( 'R', 0x06 ) - -+#ifdef CONFIG_FIPS_RNG -+ -+/* Size of seed value - equal to AES blocksize */ -+#define AES_BLOCK_SIZE_BYTES 16 -+#define SEED_SIZE_BYTES AES_BLOCK_SIZE_BYTES -+/* Size of AES key */ -+#define KEY_SIZE_BYTES 16 -+ -+/* ioctl() structure used by FIPS 140-2 Tests */ -+struct rand_fips_test { -+ unsigned char key[KEY_SIZE_BYTES]; /* Input */ -+ unsigned char datetime[SEED_SIZE_BYTES]; /* Input */ -+ unsigned char seed[SEED_SIZE_BYTES]; /* Input */ -+ unsigned char result[SEED_SIZE_BYTES]; /* Output */ -+}; -+ -+/* FIPS 140-2 RNG Variable Seed Test. (Superuser only.) */ -+#define RNDFIPSVST _IOWR('R', 0x10, struct rand_fips_test) -+ -+/* FIPS 140-2 RNG Monte Carlo Test. (Superuser only.) */ -+#define RNDFIPSMCT _IOWR('R', 0x11, struct rand_fips_test) -+ -+#endif /* #ifdef CONFIG_FIPS_RNG */ -+ - struct rand_pool_info { - int entropy_count; - int buf_size; -@@ -48,6 +73,10 @@ extern void add_input_randomness(unsigne - unsigned int value); - extern void add_interrupt_randomness(int irq); - -+extern void random_input_words(__u32 *buf, size_t wordcount, int ent_count); -+extern int random_input_wait(void); -+#define HAS_RANDOM_INPUT_WAIT 1 -+ - extern void get_random_bytes(void *buf, int nbytes); - void generate_random_uuid(unsigned char uuid_out[16]); - diff --git a/target/linux/generic-2.6/patches-2.6.28/972-ocf_compile_fix.patch b/target/linux/generic-2.6/patches-2.6.28/972-ocf_compile_fix.patch deleted file mode 100644 index a3fa22681..000000000 --- a/target/linux/generic-2.6/patches-2.6.28/972-ocf_compile_fix.patch +++ /dev/null @@ -1,11 +0,0 @@ ---- a/crypto/ocf/cryptosoft.c -+++ b/crypto/ocf/cryptosoft.c -@@ -47,7 +47,7 @@ - #include - #include - #include --#include -+#include - - #include - #include diff --git a/target/linux/generic-2.6/patches-2.6.28/973-ocf_2.6.27_fix.patch b/target/linux/generic-2.6/patches-2.6.28/973-ocf_2.6.27_fix.patch deleted file mode 100644 index ecb9bef51..000000000 --- a/target/linux/generic-2.6/patches-2.6.28/973-ocf_2.6.27_fix.patch +++ /dev/null @@ -1,197 +0,0 @@ ---- a/crypto/ocf/random.c -+++ b/crypto/ocf/random.c -@@ -49,6 +49,7 @@ - #include - #include - #include -+#include - #include - - #ifdef CONFIG_OCF_FIPS -@@ -81,7 +82,7 @@ struct random_op { - - static int random_proc(void *arg); - --static pid_t randomproc = (pid_t) -1; -+static struct task_struct *random_task; - static spinlock_t random_lock; - - /* -@@ -141,13 +142,18 @@ crypto_rregister( - spin_lock_irqsave(&random_lock, flags); - list_add_tail(&rops->random_list, &random_ops); - if (!started) { -- randomproc = kernel_thread(random_proc, NULL, CLONE_FS|CLONE_FILES); -- if (randomproc < 0) { -- ret = randomproc; -+ struct task_struct *t; -+ -+ t = kthread_create(random_proc, NULL, "ocf-random"); -+ if (IS_ERR(t)) { -+ ret = PTR_ERR(t); - printk("crypto: crypto_rregister cannot start random thread; " - "error %d", ret); -- } else -+ } else { -+ random_task = t; -+ wake_up_process(t); - started = 1; -+ } - } - spin_unlock_irqrestore(&random_lock, flags); - -@@ -172,7 +178,7 @@ crypto_runregister_all(u_int32_t driveri - - spin_lock_irqsave(&random_lock, flags); - if (list_empty(&random_ops) && started) -- kill_proc(randomproc, SIGKILL, 1); -+ send_sig(SIGKILL, random_task, 1); - spin_unlock_irqrestore(&random_lock, flags); - return(0); - } -@@ -308,7 +314,7 @@ random_proc(void *arg) - - bad_alloc: - spin_lock_irq(&random_lock); -- randomproc = (pid_t) -1; -+ random_task = NULL; - started = 0; - spin_unlock_irq(&random_lock); - ---- a/crypto/ocf/crypto.c -+++ b/crypto/ocf/crypto.c -@@ -74,6 +74,7 @@ __FBSDID("$FreeBSD: src/sys/opencrypto/c - #include - #include - #include -+#include - #include - - /* -@@ -255,10 +256,10 @@ module_param(crypto_devallowsoft, int, 0 - MODULE_PARM_DESC(crypto_devallowsoft, - "Enable/disable use of software crypto support"); - --static pid_t cryptoproc = (pid_t) -1; -+static struct task_struct *crypto_task; - static struct completion cryptoproc_exited; - static DECLARE_WAIT_QUEUE_HEAD(cryptoproc_wait); --static pid_t cryptoretproc = (pid_t) -1; -+static struct task_struct *cryptoret_task; - static struct completion cryptoretproc_exited; - static DECLARE_WAIT_QUEUE_HEAD(cryptoretproc_wait); - -@@ -1401,7 +1402,7 @@ crypto_proc(void *arg) - wait_event_interruptible(cryptoproc_wait, - !(list_empty(&crp_q) || crypto_all_qblocked) || - !(list_empty(&crp_kq) || crypto_all_kqblocked) || -- cryptoproc == (pid_t) -1); -+ crypto_task == NULL); - crp_sleep = 0; - if (signal_pending (current)) { - #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) -@@ -1414,7 +1415,7 @@ crypto_proc(void *arg) - } - CRYPTO_Q_LOCK(); - dprintk("%s - awake\n", __FUNCTION__); -- if (cryptoproc == (pid_t) -1) -+ if (crypto_task == NULL) - break; - cryptostats.cs_intrs++; - } -@@ -1470,7 +1471,7 @@ crypto_ret_proc(void *arg) - dprintk("%s - sleeping\n", __FUNCTION__); - CRYPTO_RETQ_UNLOCK(); - wait_event_interruptible(cryptoretproc_wait, -- cryptoretproc == (pid_t) -1 || -+ cryptoret_task == NULL || - !list_empty(&crp_ret_q) || - !list_empty(&crp_ret_kq)); - if (signal_pending (current)) { -@@ -1484,7 +1485,7 @@ crypto_ret_proc(void *arg) - } - CRYPTO_RETQ_LOCK(); - dprintk("%s - awake\n", __FUNCTION__); -- if (cryptoretproc == (pid_t) -1) { -+ if (cryptoret_task == NULL) { - dprintk("%s - EXITING!\n", __FUNCTION__); - break; - } -@@ -1597,6 +1598,7 @@ DB_SHOW_COMMAND(kcrypto, db_show_kcrypto - static int - crypto_init(void) - { -+ struct task_struct *t; - int error; - - dprintk("%s(0x%x)\n", __FUNCTION__, (int) crypto_init); -@@ -1643,23 +1645,27 @@ crypto_init(void) - init_completion(&cryptoproc_exited); - init_completion(&cryptoretproc_exited); - -- cryptoproc = 0; /* to avoid race condition where proc runs first */ -- cryptoproc = kernel_thread(crypto_proc, NULL, CLONE_FS|CLONE_FILES); -- if (cryptoproc < 0) { -- error = cryptoproc; -+ crypto_task = NULL; /* to avoid race condition where proc runs first */ -+ t = kthread_create(crypto_proc, NULL, "ocf-crypto"); -+ if (IS_ERR(t)) { -+ error = PTR_ERR(t); - printk("crypto: crypto_init cannot start crypto thread; error %d", - error); - goto bad; - } -+ wake_up_process(t); -+ crypto_task = t; - -- cryptoretproc = 0; /* to avoid race condition where proc runs first */ -- cryptoretproc = kernel_thread(crypto_ret_proc, NULL, CLONE_FS|CLONE_FILES); -- if (cryptoretproc < 0) { -- error = cryptoretproc; -+ cryptoret_task = NULL; /* to avoid race condition where proc runs first */ -+ t = kthread_create(crypto_ret_proc, NULL, "ocf-cryptoret"); -+ if (IS_ERR(t)) { -+ error = PTR_ERR(t); - printk("crypto: crypto_init cannot start cryptoret thread; error %d", - error); - goto bad; - } -+ wake_up_process(t); -+ cryptoret_task = t; - - return 0; - bad: -@@ -1671,7 +1677,7 @@ bad: - static void - crypto_exit(void) - { -- pid_t p; -+ struct task_struct *t; - unsigned long d_flags; - - dprintk("%s()\n", __FUNCTION__); -@@ -1681,18 +1687,18 @@ crypto_exit(void) - */ - - CRYPTO_DRIVER_LOCK(); -- p = cryptoproc; -- cryptoproc = (pid_t) -1; -- kill_proc(p, SIGTERM, 1); -+ t = crypto_task; -+ crypto_task = NULL; -+ send_sig(SIGTERM, t, 1); - wake_up_interruptible(&cryptoproc_wait); - CRYPTO_DRIVER_UNLOCK(); - - wait_for_completion(&cryptoproc_exited); - - CRYPTO_DRIVER_LOCK(); -- p = cryptoretproc; -- cryptoretproc = (pid_t) -1; -- kill_proc(p, SIGTERM, 1); -+ t = cryptoret_task; -+ cryptoret_task = NULL; -+ send_sig(SIGTERM, t, 1); - wake_up_interruptible(&cryptoretproc_wait); - CRYPTO_DRIVER_UNLOCK(); - diff --git a/target/linux/generic-2.6/patches-2.6.28/974-ssb_b43_default_on.patch b/target/linux/generic-2.6/patches-2.6.28/974-ssb_b43_default_on.patch deleted file mode 100644 index 98dde2a3c..000000000 --- a/target/linux/generic-2.6/patches-2.6.28/974-ssb_b43_default_on.patch +++ /dev/null @@ -1,11 +0,0 @@ ---- a/drivers/ssb/Kconfig -+++ b/drivers/ssb/Kconfig -@@ -49,7 +49,7 @@ config SSB_PCIHOST - config SSB_B43_PCI_BRIDGE - bool - depends on SSB_PCIHOST -- default n -+ default y - - config SSB_PCMCIAHOST_POSSIBLE - bool diff --git a/target/linux/generic-2.6/patches-2.6.28/975-ssb-fallback-sprom.patch b/target/linux/generic-2.6/patches-2.6.28/975-ssb-fallback-sprom.patch deleted file mode 100644 index 23d1af727..000000000 --- a/target/linux/generic-2.6/patches-2.6.28/975-ssb-fallback-sprom.patch +++ /dev/null @@ -1,107 +0,0 @@ ---- a/drivers/ssb/pci.c -+++ b/drivers/ssb/pci.c -@@ -514,6 +514,7 @@ unsupported: - static int ssb_pci_sprom_get(struct ssb_bus *bus, - struct ssb_sprom *sprom) - { -+ const struct ssb_sprom *fallback; - int err = -ENOMEM; - u16 *buf; - -@@ -533,12 +534,23 @@ static int ssb_pci_sprom_get(struct ssb_ - bus->sprom_size = SSB_SPROMSIZE_WORDS_R4; - sprom_do_read(bus, buf); - err = sprom_check_crc(buf, bus->sprom_size); -- if (err) -+ if (err) { -+ /* All CRC attempts failed. -+ * Maybe there is no SPROM on the device? -+ * If we have a fallback, use that. */ -+ fallback = ssb_get_fallback_sprom(); -+ if (fallback) { -+ memcpy(sprom, fallback, sizeof(*sprom)); -+ err = 0; -+ goto out_free; -+ } - ssb_printk(KERN_WARNING PFX "WARNING: Invalid" - " SPROM CRC (corrupt SPROM)\n"); -+ } - } - err = sprom_extract(bus, sprom, buf, bus->sprom_size); - -+out_free: - kfree(buf); - out: - return err; ---- a/drivers/ssb/sprom.c -+++ b/drivers/ssb/sprom.c -@@ -14,6 +14,9 @@ - #include "ssb_private.h" - - -+static const struct ssb_sprom *fallback_sprom; -+ -+ - static int sprom2hex(const u16 *sprom, char *buf, size_t buf_len, - size_t sprom_size_words) - { -@@ -131,3 +134,36 @@ out: - return res; - return err ? err : count; - } -+ -+/** -+ * ssb_arch_set_fallback_sprom - Set a fallback SPROM for use if no SPROM is found. -+ * -+ * @sprom: The SPROM data structure to register. -+ * -+ * With this function the architecture implementation may register a fallback -+ * SPROM data structure. The fallback is only used for PCI based SSB devices, -+ * where no valid SPROM can be found in the shadow registers. -+ * -+ * This function is useful for weird architectures that have a half-assed SSB device -+ * hardwired to their PCI bus. -+ * -+ * Note that it does only work with PCI attached SSB devices. PCMCIA devices currently -+ * don't use this fallback. -+ * Architectures must provide the SPROM for native SSB devices anyway, -+ * so the fallback also isn't used for native devices. -+ * -+ * This function is available for architecture code, only. So it is not exported. -+ */ -+int ssb_arch_set_fallback_sprom(const struct ssb_sprom *sprom) -+{ -+ if (fallback_sprom) -+ return -EEXIST; -+ fallback_sprom = sprom; -+ -+ return 0; -+} -+ -+const struct ssb_sprom *ssb_get_fallback_sprom(void) -+{ -+ return fallback_sprom; -+} ---- a/drivers/ssb/ssb_private.h -+++ b/drivers/ssb/ssb_private.h -@@ -131,6 +131,7 @@ ssize_t ssb_attr_sprom_store(struct ssb_ - const char *buf, size_t count, - int (*sprom_check_crc)(const u16 *sprom, size_t size), - int (*sprom_write)(struct ssb_bus *bus, const u16 *sprom)); -+extern const struct ssb_sprom *ssb_get_fallback_sprom(void); - - - /* core.c */ ---- a/include/linux/ssb/ssb.h -+++ b/include/linux/ssb/ssb.h -@@ -339,6 +339,10 @@ extern int ssb_bus_pcmciabus_register(st - - extern void ssb_bus_unregister(struct ssb_bus *bus); - -+/* Set a fallback SPROM. -+ * See kdoc at the function definition for complete documentation. */ -+extern int ssb_arch_set_fallback_sprom(const struct ssb_sprom *sprom); -+ - /* Suspend a SSB bus. - * Call this from the parent bus suspend routine. */ - extern int ssb_bus_suspend(struct ssb_bus *bus); diff --git a/target/linux/generic-2.6/patches-2.6.28/976-ssb_update.patch b/target/linux/generic-2.6/patches-2.6.28/976-ssb_update.patch deleted file mode 100644 index 279a116d9..000000000 --- a/target/linux/generic-2.6/patches-2.6.28/976-ssb_update.patch +++ /dev/null @@ -1,1488 +0,0 @@ ---- /dev/null -+++ b/drivers/ssb/driver_chipcommon_pmu.c -@@ -0,0 +1,602 @@ -+/* -+ * Sonics Silicon Backplane -+ * Broadcom ChipCommon Power Management Unit driver -+ * -+ * Copyright 2009, Michael Buesch -+ * Copyright 2007, Broadcom Corporation -+ * -+ * Licensed under the GNU/GPL. See COPYING for details. -+ */ -+ -+#include -+#include -+#include -+#include -+ -+#include "ssb_private.h" -+ -+static u32 ssb_chipco_pll_read(struct ssb_chipcommon *cc, u32 offset) -+{ -+ chipco_write32(cc, SSB_CHIPCO_PLLCTL_ADDR, offset); -+ return chipco_read32(cc, SSB_CHIPCO_PLLCTL_DATA); -+} -+ -+static void ssb_chipco_pll_write(struct ssb_chipcommon *cc, -+ u32 offset, u32 value) -+{ -+ chipco_write32(cc, SSB_CHIPCO_PLLCTL_ADDR, offset); -+ chipco_write32(cc, SSB_CHIPCO_PLLCTL_DATA, value); -+} -+ -+static void ssb_chipco_regctl_maskset(struct ssb_chipcommon *cc, -+ u32 offset, u32 mask, u32 set) -+{ -+ u32 value; -+ -+ chipco_read32(cc, SSB_CHIPCO_REGCTL_ADDR); -+ chipco_write32(cc, SSB_CHIPCO_REGCTL_ADDR, offset); -+ chipco_read32(cc, SSB_CHIPCO_REGCTL_ADDR); -+ value = chipco_read32(cc, SSB_CHIPCO_REGCTL_DATA); -+ value &= mask; -+ value |= set; -+ chipco_write32(cc, SSB_CHIPCO_REGCTL_DATA, value); -+ chipco_read32(cc, SSB_CHIPCO_REGCTL_DATA); -+} -+ -+struct pmu0_plltab_entry { -+ u16 freq; /* Crystal frequency in kHz.*/ -+ u8 xf; /* Crystal frequency value for PMU control */ -+ u8 wb_int; -+ u32 wb_frac; -+}; -+ -+static const struct pmu0_plltab_entry pmu0_plltab[] = { -+ { .freq = 12000, .xf = 1, .wb_int = 73, .wb_frac = 349525, }, -+ { .freq = 13000, .xf = 2, .wb_int = 67, .wb_frac = 725937, }, -+ { .freq = 14400, .xf = 3, .wb_int = 61, .wb_frac = 116508, }, -+ { .freq = 15360, .xf = 4, .wb_int = 57, .wb_frac = 305834, }, -+ { .freq = 16200, .xf = 5, .wb_int = 54, .wb_frac = 336579, }, -+ { .freq = 16800, .xf = 6, .wb_int = 52, .wb_frac = 399457, }, -+ { .freq = 19200, .xf = 7, .wb_int = 45, .wb_frac = 873813, }, -+ { .freq = 19800, .xf = 8, .wb_int = 44, .wb_frac = 466033, }, -+ { .freq = 20000, .xf = 9, .wb_int = 44, .wb_frac = 0, }, -+ { .freq = 25000, .xf = 10, .wb_int = 70, .wb_frac = 419430, }, -+ { .freq = 26000, .xf = 11, .wb_int = 67, .wb_frac = 725937, }, -+ { .freq = 30000, .xf = 12, .wb_int = 58, .wb_frac = 699050, }, -+ { .freq = 38400, .xf = 13, .wb_int = 45, .wb_frac = 873813, }, -+ { .freq = 40000, .xf = 14, .wb_int = 45, .wb_frac = 0, }, -+}; -+#define SSB_PMU0_DEFAULT_XTALFREQ 20000 -+ -+static const struct pmu0_plltab_entry * pmu0_plltab_find_entry(u32 crystalfreq) -+{ -+ const struct pmu0_plltab_entry *e; -+ unsigned int i; -+ -+ for (i = 0; i < ARRAY_SIZE(pmu0_plltab); i++) { -+ e = &pmu0_plltab[i]; -+ if (e->freq == crystalfreq) -+ return e; -+ } -+ -+ return NULL; -+} -+ -+/* Tune the PLL to the crystal speed. crystalfreq is in kHz. */ -+static void ssb_pmu0_pllinit_r0(struct ssb_chipcommon *cc, -+ u32 crystalfreq) -+{ -+ struct ssb_bus *bus = cc->dev->bus; -+ const struct pmu0_plltab_entry *e = NULL; -+ u32 pmuctl, tmp, pllctl; -+ unsigned int i; -+ -+ if ((bus->chip_id == 0x5354) && !crystalfreq) { -+ /* The 5354 crystal freq is 25MHz */ -+ crystalfreq = 25000; -+ } -+ if (crystalfreq) -+ e = pmu0_plltab_find_entry(crystalfreq); -+ if (!e) -+ e = pmu0_plltab_find_entry(SSB_PMU0_DEFAULT_XTALFREQ); -+ BUG_ON(!e); -+ crystalfreq = e->freq; -+ cc->pmu.crystalfreq = e->freq; -+ -+ /* Check if the PLL already is programmed to this frequency. */ -+ pmuctl = chipco_read32(cc, SSB_CHIPCO_PMU_CTL); -+ if (((pmuctl & SSB_CHIPCO_PMU_CTL_XTALFREQ) >> SSB_CHIPCO_PMU_CTL_XTALFREQ_SHIFT) == e->xf) { -+ /* We're already there... */ -+ return; -+ } -+ -+ ssb_printk(KERN_INFO PFX "Programming PLL to %u.%03u MHz\n", -+ (crystalfreq / 1000), (crystalfreq % 1000)); -+ -+ /* First turn the PLL off. */ -+ switch (bus->chip_id) { -+ case 0x4328: -+ chipco_mask32(cc, SSB_CHIPCO_PMU_MINRES_MSK, -+ ~(1 << SSB_PMURES_4328_BB_PLL_PU)); -+ chipco_mask32(cc, SSB_CHIPCO_PMU_MAXRES_MSK, -+ ~(1 << SSB_PMURES_4328_BB_PLL_PU)); -+ break; -+ case 0x5354: -+ chipco_mask32(cc, SSB_CHIPCO_PMU_MINRES_MSK, -+ ~(1 << SSB_PMURES_5354_BB_PLL_PU)); -+ chipco_mask32(cc, SSB_CHIPCO_PMU_MAXRES_MSK, -+ ~(1 << SSB_PMURES_5354_BB_PLL_PU)); -+ break; -+ default: -+ SSB_WARN_ON(1); -+ } -+ for (i = 1500; i; i--) { -+ tmp = chipco_read32(cc, SSB_CHIPCO_CLKCTLST); -+ if (!(tmp & SSB_CHIPCO_CLKCTLST_HAVEHT)) -+ break; -+ udelay(10); -+ } -+ tmp = chipco_read32(cc, SSB_CHIPCO_CLKCTLST); -+ if (tmp & SSB_CHIPCO_CLKCTLST_HAVEHT) -+ ssb_printk(KERN_EMERG PFX "Failed to turn the PLL off!\n"); -+ -+ /* Set PDIV in PLL control 0. */ -+ pllctl = ssb_chipco_pll_read(cc, SSB_PMU0_PLLCTL0); -+ if (crystalfreq >= SSB_PMU0_PLLCTL0_PDIV_FREQ) -+ pllctl |= SSB_PMU0_PLLCTL0_PDIV_MSK; -+ else -+ pllctl &= ~SSB_PMU0_PLLCTL0_PDIV_MSK; -+ ssb_chipco_pll_write(cc, SSB_PMU0_PLLCTL0, pllctl); -+ -+ /* Set WILD in PLL control 1. */ -+ pllctl = ssb_chipco_pll_read(cc, SSB_PMU0_PLLCTL1); -+ pllctl &= ~SSB_PMU0_PLLCTL1_STOPMOD; -+ pllctl &= ~(SSB_PMU0_PLLCTL1_WILD_IMSK | SSB_PMU0_PLLCTL1_WILD_FMSK); -+ pllctl |= ((u32)e->wb_int << SSB_PMU0_PLLCTL1_WILD_IMSK_SHIFT) & SSB_PMU0_PLLCTL1_WILD_IMSK; -+ pllctl |= ((u32)e->wb_frac << SSB_PMU0_PLLCTL1_WILD_FMSK_SHIFT) & SSB_PMU0_PLLCTL1_WILD_FMSK; -+ if (e->wb_frac == 0) -+ pllctl |= SSB_PMU0_PLLCTL1_STOPMOD; -+ ssb_chipco_pll_write(cc, SSB_PMU0_PLLCTL1, pllctl); -+ -+ /* Set WILD in PLL control 2. */ -+ pllctl = ssb_chipco_pll_read(cc, SSB_PMU0_PLLCTL2); -+ pllctl &= ~SSB_PMU0_PLLCTL2_WILD_IMSKHI; -+ pllctl |= (((u32)e->wb_int >> 4) << SSB_PMU0_PLLCTL2_WILD_IMSKHI_SHIFT) & SSB_PMU0_PLLCTL2_WILD_IMSKHI; -+ ssb_chipco_pll_write(cc, SSB_PMU0_PLLCTL2, pllctl); -+ -+ /* Set the crystalfrequency and the divisor. */ -+ pmuctl = chipco_read32(cc, SSB_CHIPCO_PMU_CTL); -+ pmuctl &= ~SSB_CHIPCO_PMU_CTL_ILP_DIV; -+ pmuctl |= (((crystalfreq + 127) / 128 - 1) << SSB_CHIPCO_PMU_CTL_ILP_DIV_SHIFT) -+ & SSB_CHIPCO_PMU_CTL_ILP_DIV; -+ pmuctl &= ~SSB_CHIPCO_PMU_CTL_XTALFREQ; -+ pmuctl |= ((u32)e->xf << SSB_CHIPCO_PMU_CTL_XTALFREQ_SHIFT) & SSB_CHIPCO_PMU_CTL_XTALFREQ; -+ chipco_write32(cc, SSB_CHIPCO_PMU_CTL, pmuctl); -+} -+ -+struct pmu1_plltab_entry { -+ u16 freq; /* Crystal frequency in kHz.*/ -+ u8 xf; /* Crystal frequency value for PMU control */ -+ u8 ndiv_int; -+ u32 ndiv_frac; -+ u8 p1div; -+ u8 p2div; -+}; -+ -+static const struct pmu1_plltab_entry pmu1_plltab[] = { -+ { .freq = 12000, .xf = 1, .p1div = 3, .p2div = 22, .ndiv_int = 0x9, .ndiv_frac = 0xFFFFEF, }, -+ { .freq = 13000, .xf = 2, .p1div = 1, .p2div = 6, .ndiv_int = 0xb, .ndiv_frac = 0x483483, }, -+ { .freq = 14400, .xf = 3, .p1div = 1, .p2div = 10, .ndiv_int = 0xa, .ndiv_frac = 0x1C71C7, }, -+ { .freq = 15360, .xf = 4, .p1div = 1, .p2div = 5, .ndiv_int = 0xb, .ndiv_frac = 0x755555, }, -+ { .freq = 16200, .xf = 5, .p1div = 1, .p2div = 10, .ndiv_int = 0x5, .ndiv_frac = 0x6E9E06, }, -+ { .freq = 16800, .xf = 6, .p1div = 1, .p2div = 10, .ndiv_int = 0x5, .ndiv_frac = 0x3CF3CF, }, -+ { .freq = 19200, .xf = 7, .p1div = 1, .p2div = 9, .ndiv_int = 0x5, .ndiv_frac = 0x17B425, }, -+ { .freq = 19800, .xf = 8, .p1div = 1, .p2div = 11, .ndiv_int = 0x4, .ndiv_frac = 0xA57EB, }, -+ { .freq = 20000, .xf = 9, .p1div = 1, .p2div = 11, .ndiv_int = 0x4, .ndiv_frac = 0, }, -+ { .freq = 24000, .xf = 10, .p1div = 3, .p2div = 11, .ndiv_int = 0xa, .ndiv_frac = 0, }, -+ { .freq = 25000, .xf = 11, .p1div = 5, .p2div = 16, .ndiv_int = 0xb, .ndiv_frac = 0, }, -+ { .freq = 26000, .xf = 12, .p1div = 1, .p2div = 2, .ndiv_int = 0x10, .ndiv_frac = 0xEC4EC4, }, -+ { .freq = 30000, .xf = 13, .p1div = 3, .p2div = 8, .ndiv_int = 0xb, .ndiv_frac = 0, }, -+ { .freq = 38400, .xf = 14, .p1div = 1, .p2div = 5, .ndiv_int = 0x4, .ndiv_frac = 0x955555, }, -+ { .freq = 40000, .xf = 15, .p1div = 1, .p2div = 2, .ndiv_int = 0xb, .ndiv_frac = 0, }, -+}; -+ -+#define SSB_PMU1_DEFAULT_XTALFREQ 15360 -+ -+static const struct pmu1_plltab_entry * pmu1_plltab_find_entry(u32 crystalfreq) -+{ -+ const struct pmu1_plltab_entry *e; -+ unsigned int i; -+ -+ for (i = 0; i < ARRAY_SIZE(pmu1_plltab); i++) { -+ e = &pmu1_plltab[i]; -+ if (e->freq == crystalfreq) -+ return e; -+ } -+ -+ return NULL; -+} -+ -+/* Tune the PLL to the crystal speed. crystalfreq is in kHz. */ -+static void ssb_pmu1_pllinit_r0(struct ssb_chipcommon *cc, -+ u32 crystalfreq) -+{ -+ struct ssb_bus *bus = cc->dev->bus; -+ const struct pmu1_plltab_entry *e = NULL; -+ u32 buffer_strength = 0; -+ u32 tmp, pllctl, pmuctl; -+ unsigned int i; -+ -+ if (bus->chip_id == 0x4312) { -+ /* We do not touch the BCM4312 PLL and assume -+ * the default crystal settings work out-of-the-box. */ -+ cc->pmu.crystalfreq = 20000; -+ return; -+ } -+ -+ if (crystalfreq) -+ e = pmu1_plltab_find_entry(crystalfreq); -+ if (!e) -+ e = pmu1_plltab_find_entry(SSB_PMU1_DEFAULT_XTALFREQ); -+ BUG_ON(!e); -+ crystalfreq = e->freq; -+ cc->pmu.crystalfreq = e->freq; -+ -+ /* Check if the PLL already is programmed to this frequency. */ -+ pmuctl = chipco_read32(cc, SSB_CHIPCO_PMU_CTL); -+ if (((pmuctl & SSB_CHIPCO_PMU_CTL_XTALFREQ) >> SSB_CHIPCO_PMU_CTL_XTALFREQ_SHIFT) == e->xf) { -+ /* We're already there... */ -+ return; -+ } -+ -+ ssb_printk(KERN_INFO PFX "Programming PLL to %u.%03u MHz\n", -+ (crystalfreq / 1000), (crystalfreq % 1000)); -+ -+ /* First turn the PLL off. */ -+ switch (bus->chip_id) { -+ case 0x4325: -+ chipco_mask32(cc, SSB_CHIPCO_PMU_MINRES_MSK, -+ ~((1 << SSB_PMURES_4325_BBPLL_PWRSW_PU) | -+ (1 << SSB_PMURES_4325_HT_AVAIL))); -+ chipco_mask32(cc, SSB_CHIPCO_PMU_MAXRES_MSK, -+ ~((1 << SSB_PMURES_4325_BBPLL_PWRSW_PU) | -+ (1 << SSB_PMURES_4325_HT_AVAIL))); -+ /* Adjust the BBPLL to 2 on all channels later. */ -+ buffer_strength = 0x222222; -+ break; -+ default: -+ SSB_WARN_ON(1); -+ } -+ for (i = 1500; i; i--) { -+ tmp = chipco_read32(cc, SSB_CHIPCO_CLKCTLST); -+ if (!(tmp & SSB_CHIPCO_CLKCTLST_HAVEHT)) -+ break; -+ udelay(10); -+ } -+ tmp = chipco_read32(cc, SSB_CHIPCO_CLKCTLST); -+ if (tmp & SSB_CHIPCO_CLKCTLST_HAVEHT) -+ ssb_printk(KERN_EMERG PFX "Failed to turn the PLL off!\n"); -+ -+ /* Set p1div and p2div. */ -+ pllctl = ssb_chipco_pll_read(cc, SSB_PMU1_PLLCTL0); -+ pllctl &= ~(SSB_PMU1_PLLCTL0_P1DIV | SSB_PMU1_PLLCTL0_P2DIV); -+ pllctl |= ((u32)e->p1div << SSB_PMU1_PLLCTL0_P1DIV_SHIFT) & SSB_PMU1_PLLCTL0_P1DIV; -+ pllctl |= ((u32)e->p2div << SSB_PMU1_PLLCTL0_P2DIV_SHIFT) & SSB_PMU1_PLLCTL0_P2DIV; -+ ssb_chipco_pll_write(cc, SSB_PMU1_PLLCTL0, pllctl); -+ -+ /* Set ndiv int and ndiv mode */ -+ pllctl = ssb_chipco_pll_read(cc, SSB_PMU1_PLLCTL2); -+ pllctl &= ~(SSB_PMU1_PLLCTL2_NDIVINT | SSB_PMU1_PLLCTL2_NDIVMODE); -+ pllctl |= ((u32)e->ndiv_int << SSB_PMU1_PLLCTL2_NDIVINT_SHIFT) & SSB_PMU1_PLLCTL2_NDIVINT; -+ pllctl |= (1 << SSB_PMU1_PLLCTL2_NDIVMODE_SHIFT) & SSB_PMU1_PLLCTL2_NDIVMODE; -+ ssb_chipco_pll_write(cc, SSB_PMU1_PLLCTL2, pllctl); -+ -+ /* Set ndiv frac */ -+ pllctl = ssb_chipco_pll_read(cc, SSB_PMU1_PLLCTL3); -+ pllctl &= ~SSB_PMU1_PLLCTL3_NDIVFRAC; -+ pllctl |= ((u32)e->ndiv_frac << SSB_PMU1_PLLCTL3_NDIVFRAC_SHIFT) & SSB_PMU1_PLLCTL3_NDIVFRAC; -+ ssb_chipco_pll_write(cc, SSB_PMU1_PLLCTL3, pllctl); -+ -+ /* Change the drive strength, if required. */ -+ if (buffer_strength) { -+ pllctl = ssb_chipco_pll_read(cc, SSB_PMU1_PLLCTL5); -+ pllctl &= ~SSB_PMU1_PLLCTL5_CLKDRV; -+ pllctl |= (buffer_strength << SSB_PMU1_PLLCTL5_CLKDRV_SHIFT) & SSB_PMU1_PLLCTL5_CLKDRV; -+ ssb_chipco_pll_write(cc, SSB_PMU1_PLLCTL5, pllctl); -+ } -+ -+ /* Tune the crystalfreq and the divisor. */ -+ pmuctl = chipco_read32(cc, SSB_CHIPCO_PMU_CTL); -+ pmuctl &= ~(SSB_CHIPCO_PMU_CTL_ILP_DIV | SSB_CHIPCO_PMU_CTL_XTALFREQ); -+ pmuctl |= ((((u32)e->freq + 127) / 128 - 1) << SSB_CHIPCO_PMU_CTL_ILP_DIV_SHIFT) -+ & SSB_CHIPCO_PMU_CTL_ILP_DIV; -+ pmuctl |= ((u32)e->xf << SSB_CHIPCO_PMU_CTL_XTALFREQ_SHIFT) & SSB_CHIPCO_PMU_CTL_XTALFREQ; -+ chipco_write32(cc, SSB_CHIPCO_PMU_CTL, pmuctl); -+} -+ -+static void ssb_pmu_pll_init(struct ssb_chipcommon *cc) -+{ -+ struct ssb_bus *bus = cc->dev->bus; -+ u32 crystalfreq = 0; /* in kHz. 0 = keep default freq. */ -+ -+ if (bus->bustype == SSB_BUSTYPE_SSB) { -+ /* TODO: The user may override the crystal frequency. */ -+ } -+ -+ switch (bus->chip_id) { -+ case 0x4312: -+ case 0x4325: -+ ssb_pmu1_pllinit_r0(cc, crystalfreq); -+ break; -+ case 0x4328: -+ case 0x5354: -+ ssb_pmu0_pllinit_r0(cc, crystalfreq); -+ break; -+ default: -+ ssb_printk(KERN_ERR PFX -+ "ERROR: PLL init unknown for device %04X\n", -+ bus->chip_id); -+ } -+} -+ -+struct pmu_res_updown_tab_entry { -+ u8 resource; /* The resource number */ -+ u16 updown; /* The updown value */ -+}; -+ -+enum pmu_res_depend_tab_task { -+ PMU_RES_DEP_SET = 1, -+ PMU_RES_DEP_ADD, -+ PMU_RES_DEP_REMOVE, -+}; -+ -+struct pmu_res_depend_tab_entry { -+ u8 resource; /* The resource number */ -+ u8 task; /* SET | ADD | REMOVE */ -+ u32 depend; /* The depend mask */ -+}; -+ -+static const struct pmu_res_updown_tab_entry pmu_res_updown_tab_4328a0[] = { -+ { .resource = SSB_PMURES_4328_EXT_SWITCHER_PWM, .updown = 0x0101, }, -+ { .resource = SSB_PMURES_4328_BB_SWITCHER_PWM, .updown = 0x1F01, }, -+ { .resource = SSB_PMURES_4328_BB_SWITCHER_BURST, .updown = 0x010F, }, -+ { .resource = SSB_PMURES_4328_BB_EXT_SWITCHER_BURST, .updown = 0x0101, }, -+ { .resource = SSB_PMURES_4328_ILP_REQUEST, .updown = 0x0202, }, -+ { .resource = SSB_PMURES_4328_RADIO_SWITCHER_PWM, .updown = 0x0F01, }, -+ { .resource = SSB_PMURES_4328_RADIO_SWITCHER_BURST, .updown = 0x0F01, }, -+ { .resource = SSB_PMURES_4328_ROM_SWITCH, .updown = 0x0101, }, -+ { .resource = SSB_PMURES_4328_PA_REF_LDO, .updown = 0x0F01, }, -+ { .resource = SSB_PMURES_4328_RADIO_LDO, .updown = 0x0F01, }, -+ { .resource = SSB_PMURES_4328_AFE_LDO, .updown = 0x0F01, }, -+ { .resource = SSB_PMURES_4328_PLL_LDO, .updown = 0x0F01, }, -+ { .resource = SSB_PMURES_4328_BG_FILTBYP, .updown = 0x0101, }, -+ { .resource = SSB_PMURES_4328_TX_FILTBYP, .updown = 0x0101, }, -+ { .resource = SSB_PMURES_4328_RX_FILTBYP, .updown = 0x0101, }, -+ { .resource = SSB_PMURES_4328_XTAL_PU, .updown = 0x0101, }, -+ { .resource = SSB_PMURES_4328_XTAL_EN, .updown = 0xA001, }, -+ { .resource = SSB_PMURES_4328_BB_PLL_FILTBYP, .updown = 0x0101, }, -+ { .resource = SSB_PMURES_4328_RF_PLL_FILTBYP, .updown = 0x0101, }, -+ { .resource = SSB_PMURES_4328_BB_PLL_PU, .updown = 0x0701, }, -+}; -+ -+static const struct pmu_res_depend_tab_entry pmu_res_depend_tab_4328a0[] = { -+ { -+ /* Adjust ILP Request to avoid forcing EXT/BB into burst mode. */ -+ .resource = SSB_PMURES_4328_ILP_REQUEST, -+ .task = PMU_RES_DEP_SET, -+ .depend = ((1 << SSB_PMURES_4328_EXT_SWITCHER_PWM) | -+ (1 << SSB_PMURES_4328_BB_SWITCHER_PWM)), -+ }, -+}; -+ -+static const struct pmu_res_updown_tab_entry pmu_res_updown_tab_4325a0[] = { -+ { .resource = SSB_PMURES_4325_XTAL_PU, .updown = 0x1501, }, -+}; -+ -+static const struct pmu_res_depend_tab_entry pmu_res_depend_tab_4325a0[] = { -+ { -+ /* Adjust HT-Available dependencies. */ -+ .resource = SSB_PMURES_4325_HT_AVAIL, -+ .task = PMU_RES_DEP_ADD, -+ .depend = ((1 << SSB_PMURES_4325_RX_PWRSW_PU) | -+ (1 << SSB_PMURES_4325_TX_PWRSW_PU) | -+ (1 << SSB_PMURES_4325_LOGEN_PWRSW_PU) | -+ (1 << SSB_PMURES_4325_AFE_PWRSW_PU)), -+ }, -+}; -+ -+static void ssb_pmu_resources_init(struct ssb_chipcommon *cc) -+{ -+ struct ssb_bus *bus = cc->dev->bus; -+ u32 min_msk = 0, max_msk = 0; -+ unsigned int i; -+ const struct pmu_res_updown_tab_entry *updown_tab = NULL; -+ unsigned int updown_tab_size; -+ const struct pmu_res_depend_tab_entry *depend_tab = NULL; -+ unsigned int depend_tab_size; -+ -+ switch (bus->chip_id) { -+ case 0x4312: -+ /* We keep the default settings: -+ * min_msk = 0xCBB -+ * max_msk = 0x7FFFF -+ */ -+ break; -+ case 0x4325: -+ /* Power OTP down later. */ -+ min_msk = (1 << SSB_PMURES_4325_CBUCK_BURST) | -+ (1 << SSB_PMURES_4325_LNLDO2_PU); -+ if (chipco_read32(cc, SSB_CHIPCO_CHIPSTAT) & -+ SSB_CHIPCO_CHST_4325_PMUTOP_2B) -+ min_msk |= (1 << SSB_PMURES_4325_CLDO_CBUCK_BURST); -+ /* The PLL may turn on, if it decides so. */ -+ max_msk = 0xFFFFF; -+ updown_tab = pmu_res_updown_tab_4325a0; -+ updown_tab_size = ARRAY_SIZE(pmu_res_updown_tab_4325a0); -+ depend_tab = pmu_res_depend_tab_4325a0; -+ depend_tab_size = ARRAY_SIZE(pmu_res_depend_tab_4325a0); -+ break; -+ case 0x4328: -+ min_msk = (1 << SSB_PMURES_4328_EXT_SWITCHER_PWM) | -+ (1 << SSB_PMURES_4328_BB_SWITCHER_PWM) | -+ (1 << SSB_PMURES_4328_XTAL_EN); -+ /* The PLL may turn on, if it decides so. */ -+ max_msk = 0xFFFFF; -+ updown_tab = pmu_res_updown_tab_4328a0; -+ updown_tab_size = ARRAY_SIZE(pmu_res_updown_tab_4328a0); -+ depend_tab = pmu_res_depend_tab_4328a0; -+ depend_tab_size = ARRAY_SIZE(pmu_res_depend_tab_4328a0); -+ break; -+ case 0x5354: -+ /* The PLL may turn on, if it decides so. */ -+ max_msk = 0xFFFFF; -+ break; -+ default: -+ ssb_printk(KERN_ERR PFX -+ "ERROR: PMU resource config unknown for device %04X\n", -+ bus->chip_id); -+ } -+ -+ if (updown_tab) { -+ for (i = 0; i < updown_tab_size; i++) { -+ chipco_write32(cc, SSB_CHIPCO_PMU_RES_TABSEL, -+ updown_tab[i].resource); -+ chipco_write32(cc, SSB_CHIPCO_PMU_RES_UPDNTM, -+ updown_tab[i].updown); -+ } -+ } -+ if (depend_tab) { -+ for (i = 0; i < depend_tab_size; i++) { -+ chipco_write32(cc, SSB_CHIPCO_PMU_RES_TABSEL, -+ depend_tab[i].resource); -+ switch (depend_tab[i].task) { -+ case PMU_RES_DEP_SET: -+ chipco_write32(cc, SSB_CHIPCO_PMU_RES_DEPMSK, -+ depend_tab[i].depend); -+ break; -+ case PMU_RES_DEP_ADD: -+ chipco_set32(cc, SSB_CHIPCO_PMU_RES_DEPMSK, -+ depend_tab[i].depend); -+ break; -+ case PMU_RES_DEP_REMOVE: -+ chipco_mask32(cc, SSB_CHIPCO_PMU_RES_DEPMSK, -+ ~(depend_tab[i].depend)); -+ break; -+ default: -+ SSB_WARN_ON(1); -+ } -+ } -+ } -+ -+ /* Set the resource masks. */ -+ if (min_msk) -+ chipco_write32(cc, SSB_CHIPCO_PMU_MINRES_MSK, min_msk); -+ if (max_msk) -+ chipco_write32(cc, SSB_CHIPCO_PMU_MAXRES_MSK, max_msk); -+} -+ -+void ssb_pmu_init(struct ssb_chipcommon *cc) -+{ -+ struct ssb_bus *bus = cc->dev->bus; -+ u32 pmucap; -+ -+ if (!(cc->capabilities & SSB_CHIPCO_CAP_PMU)) -+ return; -+ -+ pmucap = chipco_read32(cc, SSB_CHIPCO_PMU_CAP); -+ cc->pmu.rev = (pmucap & SSB_CHIPCO_PMU_CAP_REVISION); -+ -+ ssb_dprintk(KERN_DEBUG PFX "Found rev %u PMU (capabilities 0x%08X)\n", -+ cc->pmu.rev, pmucap); -+ -+ if (cc->pmu.rev >= 1) { -+ if ((bus->chip_id == 0x4325) && (bus->chip_rev < 2)) { -+ chipco_mask32(cc, SSB_CHIPCO_PMU_CTL, -+ ~SSB_CHIPCO_PMU_CTL_NOILPONW); -+ } else { -+ chipco_set32(cc, SSB_CHIPCO_PMU_CTL, -+ SSB_CHIPCO_PMU_CTL_NOILPONW); -+ } -+ } -+ ssb_pmu_pll_init(cc); -+ ssb_pmu_resources_init(cc); -+} -+ -+void ssb_pmu_set_ldo_voltage(struct ssb_chipcommon *cc, -+ enum ssb_pmu_ldo_volt_id id, u32 voltage) -+{ -+ struct ssb_bus *bus = cc->dev->bus; -+ u32 addr, shift, mask; -+ -+ switch (bus->chip_id) { -+ case 0x4328: -+ case 0x5354: -+ switch (id) { -+ case LDO_VOLT1: -+ addr = 2; -+ shift = 25; -+ mask = 0xF; -+ break; -+ case LDO_VOLT2: -+ addr = 3; -+ shift = 1; -+ mask = 0xF; -+ break; -+ case LDO_VOLT3: -+ addr = 3; -+ shift = 9; -+ mask = 0xF; -+ break; -+ case LDO_PAREF: -+ addr = 3; -+ shift = 17; -+ mask = 0x3F; -+ break; -+ default: -+ SSB_WARN_ON(1); -+ return; -+ } -+ break; -+ case 0x4312: -+ if (SSB_WARN_ON(id != LDO_PAREF)) -+ return; -+ addr = 0; -+ shift = 21; -+ mask = 0x3F; -+ break; -+ default: -+ return; -+ } -+ -+ ssb_chipco_regctl_maskset(cc, addr, ~(mask << shift), -+ (voltage & mask) << shift); -+} -+ -+void ssb_pmu_set_ldo_paref(struct ssb_chipcommon *cc, bool on) -+{ -+ struct ssb_bus *bus = cc->dev->bus; -+ int ldo; -+ -+ switch (bus->chip_id) { -+ case 0x4312: -+ ldo = SSB_PMURES_4312_PA_REF_LDO; -+ break; -+ case 0x4328: -+ ldo = SSB_PMURES_4328_PA_REF_LDO; -+ break; -+ case 0x5354: -+ ldo = SSB_PMURES_5354_PA_REF_LDO; -+ break; -+ default: -+ return; -+ } -+ -+ if (on) -+ chipco_set32(cc, SSB_CHIPCO_PMU_MINRES_MSK, 1 << ldo); -+ else -+ chipco_mask32(cc, SSB_CHIPCO_PMU_MINRES_MSK, ~(1 << ldo)); -+ chipco_read32(cc, SSB_CHIPCO_PMU_MINRES_MSK); //SPEC FIXME found via mmiotrace - dummy read? -+} -+ -+EXPORT_SYMBOL(ssb_pmu_set_ldo_voltage); -+EXPORT_SYMBOL(ssb_pmu_set_ldo_paref); ---- a/drivers/ssb/Kconfig -+++ b/drivers/ssb/Kconfig -@@ -53,11 +53,11 @@ config SSB_B43_PCI_BRIDGE - - config SSB_PCMCIAHOST_POSSIBLE - bool -- depends on SSB && (PCMCIA = y || PCMCIA = SSB) && EXPERIMENTAL -+ depends on SSB && (PCMCIA = y || PCMCIA = SSB) - default y - - config SSB_PCMCIAHOST -- bool "Support for SSB on PCMCIA-bus host (EXPERIMENTAL)" -+ bool "Support for SSB on PCMCIA-bus host" - depends on SSB_PCMCIAHOST_POSSIBLE - select SSB_SPROM - help -@@ -107,14 +107,14 @@ config SSB_DRIVER_PCICORE - If unsure, say Y - - config SSB_PCICORE_HOSTMODE -- bool "Hostmode support for SSB PCI core (EXPERIMENTAL)" -- depends on SSB_DRIVER_PCICORE && SSB_DRIVER_MIPS && EXPERIMENTAL -+ bool "Hostmode support for SSB PCI core" -+ depends on SSB_DRIVER_PCICORE && SSB_DRIVER_MIPS - help - PCIcore hostmode operation (external PCI bus). - - config SSB_DRIVER_MIPS -- bool "SSB Broadcom MIPS core driver (EXPERIMENTAL)" -- depends on SSB && MIPS && EXPERIMENTAL -+ bool "SSB Broadcom MIPS core driver" -+ depends on SSB && MIPS - select SSB_SERIAL - help - Driver for the Sonics Silicon Backplane attached -@@ -126,11 +126,13 @@ config SSB_DRIVER_MIPS - config SSB_EMBEDDED - bool - depends on SSB_DRIVER_MIPS -+ select USB_EHCI_HCD_SSB if USB_EHCI_HCD -+ select USB_OHCI_HCD_SSB if USB_OHCI_HCD - default y - - config SSB_DRIVER_EXTIF -- bool "SSB Broadcom EXTIF core driver (EXPERIMENTAL)" -- depends on SSB_DRIVER_MIPS && EXPERIMENTAL -+ bool "SSB Broadcom EXTIF core driver" -+ depends on SSB_DRIVER_MIPS - help - Driver for the Sonics Silicon Backplane attached - Broadcom EXTIF core. ---- a/drivers/ssb/Makefile -+++ b/drivers/ssb/Makefile -@@ -9,6 +9,7 @@ ssb-$(CONFIG_SSB_PCMCIAHOST) += pcmcia. - - # built-in drivers - ssb-y += driver_chipcommon.o -+ssb-y += driver_chipcommon_pmu.o - ssb-$(CONFIG_SSB_DRIVER_MIPS) += driver_mipscore.o - ssb-$(CONFIG_SSB_DRIVER_EXTIF) += driver_extif.o - ssb-$(CONFIG_SSB_DRIVER_PCICORE) += driver_pcicore.o ---- a/drivers/ssb/b43_pci_bridge.c -+++ b/drivers/ssb/b43_pci_bridge.c -@@ -18,9 +18,11 @@ - - static const struct pci_device_id b43_pci_bridge_tbl[] = { - { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4301) }, -+ { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4306) }, - { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4307) }, - { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4311) }, - { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4312) }, -+ { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4315) }, - { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4318) }, - { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4319) }, - { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4320) }, -@@ -29,6 +31,7 @@ static const struct pci_device_id b43_pc - { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4325) }, - { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4328) }, - { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4329) }, -+ { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x432b) }, - { 0, }, - }; - MODULE_DEVICE_TABLE(pci, b43_pci_bridge_tbl); ---- a/drivers/ssb/main.c -+++ b/drivers/ssb/main.c -@@ -473,6 +473,8 @@ static int ssb_devices_register(struct s - case SSB_BUSTYPE_SSB: - dev->dma_mask = &dev->coherent_dma_mask; - break; -+ default: -+ break; - } - - sdev->dev = dev; -@@ -1359,8 +1361,10 @@ static int __init ssb_modinit(void) - ssb_buses_lock(); - err = ssb_attach_queued_buses(); - ssb_buses_unlock(); -- if (err) -+ if (err) { - bus_unregister(&ssb_bustype); -+ goto out; -+ } - - err = b43_pci_ssb_bridge_init(); - if (err) { -@@ -1376,7 +1380,7 @@ static int __init ssb_modinit(void) - /* don't fail SSB init because of this */ - err = 0; - } -- -+out: - return err; - } - /* ssb must be initialized after PCI but before the ssb drivers. ---- a/drivers/ssb/pci.c -+++ b/drivers/ssb/pci.c -@@ -169,8 +169,14 @@ err_pci: - /* Get the word-offset for a SSB_SPROM_XXX define. */ - #define SPOFF(offset) (((offset) - SSB_SPROM_BASE) / sizeof(u16)) - /* Helper to extract some _offset, which is one of the SSB_SPROM_XXX defines. */ --#define SPEX(_outvar, _offset, _mask, _shift) \ -+#define SPEX16(_outvar, _offset, _mask, _shift) \ - out->_outvar = ((in[SPOFF(_offset)] & (_mask)) >> (_shift)) -+#define SPEX32(_outvar, _offset, _mask, _shift) \ -+ out->_outvar = ((((u32)in[SPOFF((_offset)+2)] << 16 | \ -+ in[SPOFF(_offset)]) & (_mask)) >> (_shift)) -+#define SPEX(_outvar, _offset, _mask, _shift) \ -+ SPEX16(_outvar, _offset, _mask, _shift) -+ - - static inline u8 ssb_crc8(u8 crc, u8 data) - { -@@ -467,6 +473,96 @@ static void sprom_extract_r45(struct ssb - /* TODO - get remaining rev 4 stuff needed */ - } - -+static void sprom_extract_r8(struct ssb_sprom *out, const u16 *in) -+{ -+ int i; -+ u16 v; -+ -+ /* extract the MAC address */ -+ for (i = 0; i < 3; i++) { -+ v = in[SPOFF(SSB_SPROM8_IL0MAC) + i]; -+ *(((__be16 *)out->il0mac) + i) = cpu_to_be16(v); -+ } -+ SPEX(country_code, SSB_SPROM8_CCODE, 0xFFFF, 0); -+ SPEX(boardflags_lo, SSB_SPROM8_BFLLO, 0xFFFF, 0); -+ SPEX(boardflags_hi, SSB_SPROM8_BFLHI, 0xFFFF, 0); -+ SPEX(boardflags2_lo, SSB_SPROM8_BFL2LO, 0xFFFF, 0); -+ SPEX(boardflags2_hi, SSB_SPROM8_BFL2HI, 0xFFFF, 0); -+ SPEX(ant_available_a, SSB_SPROM8_ANTAVAIL, SSB_SPROM8_ANTAVAIL_A, -+ SSB_SPROM8_ANTAVAIL_A_SHIFT); -+ SPEX(ant_available_bg, SSB_SPROM8_ANTAVAIL, SSB_SPROM8_ANTAVAIL_BG, -+ SSB_SPROM8_ANTAVAIL_BG_SHIFT); -+ SPEX(maxpwr_bg, SSB_SPROM8_MAXP_BG, SSB_SPROM8_MAXP_BG_MASK, 0); -+ SPEX(itssi_bg, SSB_SPROM8_MAXP_BG, SSB_SPROM8_ITSSI_BG, -+ SSB_SPROM8_ITSSI_BG_SHIFT); -+ SPEX(maxpwr_a, SSB_SPROM8_MAXP_A, SSB_SPROM8_MAXP_A_MASK, 0); -+ SPEX(itssi_a, SSB_SPROM8_MAXP_A, SSB_SPROM8_ITSSI_A, -+ SSB_SPROM8_ITSSI_A_SHIFT); -+ SPEX(maxpwr_ah, SSB_SPROM8_MAXP_AHL, SSB_SPROM8_MAXP_AH_MASK, 0); -+ SPEX(maxpwr_al, SSB_SPROM8_MAXP_AHL, SSB_SPROM8_MAXP_AL_MASK, -+ SSB_SPROM8_MAXP_AL_SHIFT); -+ SPEX(gpio0, SSB_SPROM8_GPIOA, SSB_SPROM8_GPIOA_P0, 0); -+ SPEX(gpio1, SSB_SPROM8_GPIOA, SSB_SPROM8_GPIOA_P1, -+ SSB_SPROM8_GPIOA_P1_SHIFT); -+ SPEX(gpio2, SSB_SPROM8_GPIOB, SSB_SPROM8_GPIOB_P2, 0); -+ SPEX(gpio3, SSB_SPROM8_GPIOB, SSB_SPROM8_GPIOB_P3, -+ SSB_SPROM8_GPIOB_P3_SHIFT); -+ SPEX(tri2g, SSB_SPROM8_TRI25G, SSB_SPROM8_TRI2G, 0); -+ SPEX(tri5g, SSB_SPROM8_TRI25G, SSB_SPROM8_TRI5G, -+ SSB_SPROM8_TRI5G_SHIFT); -+ SPEX(tri5gl, SSB_SPROM8_TRI5GHL, SSB_SPROM8_TRI5GL, 0); -+ SPEX(tri5gh, SSB_SPROM8_TRI5GHL, SSB_SPROM8_TRI5GH, -+ SSB_SPROM8_TRI5GH_SHIFT); -+ SPEX(rxpo2g, SSB_SPROM8_RXPO, SSB_SPROM8_RXPO2G, 0); -+ SPEX(rxpo5g, SSB_SPROM8_RXPO, SSB_SPROM8_RXPO5G, -+ SSB_SPROM8_RXPO5G_SHIFT); -+ SPEX(rssismf2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_RSSISMF2G, 0); -+ SPEX(rssismc2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_RSSISMC2G, -+ SSB_SPROM8_RSSISMC2G_SHIFT); -+ SPEX(rssisav2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_RSSISAV2G, -+ SSB_SPROM8_RSSISAV2G_SHIFT); -+ SPEX(bxa2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_BXA2G, -+ SSB_SPROM8_BXA2G_SHIFT); -+ SPEX(rssismf5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_RSSISMF5G, 0); -+ SPEX(rssismc5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_RSSISMC5G, -+ SSB_SPROM8_RSSISMC5G_SHIFT); -+ SPEX(rssisav5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_RSSISAV5G, -+ SSB_SPROM8_RSSISAV5G_SHIFT); -+ SPEX(bxa5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_BXA5G, -+ SSB_SPROM8_BXA5G_SHIFT); -+ SPEX(pa0b0, SSB_SPROM8_PA0B0, 0xFFFF, 0); -+ SPEX(pa0b1, SSB_SPROM8_PA0B1, 0xFFFF, 0); -+ SPEX(pa0b2, SSB_SPROM8_PA0B2, 0xFFFF, 0); -+ SPEX(pa1b0, SSB_SPROM8_PA1B0, 0xFFFF, 0); -+ SPEX(pa1b1, SSB_SPROM8_PA1B1, 0xFFFF, 0); -+ SPEX(pa1b2, SSB_SPROM8_PA1B2, 0xFFFF, 0); -+ SPEX(pa1lob0, SSB_SPROM8_PA1LOB0, 0xFFFF, 0); -+ SPEX(pa1lob1, SSB_SPROM8_PA1LOB1, 0xFFFF, 0); -+ SPEX(pa1lob2, SSB_SPROM8_PA1LOB2, 0xFFFF, 0); -+ SPEX(pa1hib0, SSB_SPROM8_PA1HIB0, 0xFFFF, 0); -+ SPEX(pa1hib1, SSB_SPROM8_PA1HIB1, 0xFFFF, 0); -+ SPEX(pa1hib2, SSB_SPROM8_PA1HIB2, 0xFFFF, 0); -+ SPEX(cck2gpo, SSB_SPROM8_CCK2GPO, 0xFFFF, 0); -+ SPEX32(ofdm2gpo, SSB_SPROM8_OFDM2GPO, 0xFFFFFFFF, 0); -+ SPEX32(ofdm5glpo, SSB_SPROM8_OFDM5GLPO, 0xFFFFFFFF, 0); -+ SPEX32(ofdm5gpo, SSB_SPROM8_OFDM5GPO, 0xFFFFFFFF, 0); -+ SPEX32(ofdm5ghpo, SSB_SPROM8_OFDM5GHPO, 0xFFFFFFFF, 0); -+ -+ /* Extract the antenna gain values. */ -+ SPEX(antenna_gain.ghz24.a0, SSB_SPROM8_AGAIN01, -+ SSB_SPROM8_AGAIN0, SSB_SPROM8_AGAIN0_SHIFT); -+ SPEX(antenna_gain.ghz24.a1, SSB_SPROM8_AGAIN01, -+ SSB_SPROM8_AGAIN1, SSB_SPROM8_AGAIN1_SHIFT); -+ SPEX(antenna_gain.ghz24.a2, SSB_SPROM8_AGAIN23, -+ SSB_SPROM8_AGAIN2, SSB_SPROM8_AGAIN2_SHIFT); -+ SPEX(antenna_gain.ghz24.a3, SSB_SPROM8_AGAIN23, -+ SSB_SPROM8_AGAIN3, SSB_SPROM8_AGAIN3_SHIFT); -+ memcpy(&out->antenna_gain.ghz5, &out->antenna_gain.ghz24, -+ sizeof(out->antenna_gain.ghz5)); -+ -+ /* TODO - get remaining rev 8 stuff needed */ -+} -+ - static int sprom_extract(struct ssb_bus *bus, struct ssb_sprom *out, - const u16 *in, u16 size) - { -@@ -487,15 +583,26 @@ static int sprom_extract(struct ssb_bus - out->revision = 4; - sprom_extract_r45(out, in); - } else { -- if (out->revision == 0) -- goto unsupported; -- if (out->revision >= 1 && out->revision <= 3) { -+ switch (out->revision) { -+ case 1: -+ case 2: -+ case 3: - sprom_extract_r123(out, in); -- } -- if (out->revision == 4 || out->revision == 5) -+ break; -+ case 4: -+ case 5: - sprom_extract_r45(out, in); -- if (out->revision > 5) -- goto unsupported; -+ break; -+ case 8: -+ sprom_extract_r8(out, in); -+ break; -+ default: -+ ssb_printk(KERN_WARNING PFX "Unsupported SPROM" -+ " revision %d detected. Will extract" -+ " v1\n", out->revision); -+ out->revision = 1; -+ sprom_extract_r123(out, in); -+ } - } - - if (out->boardflags_lo == 0xFFFF) -@@ -504,11 +611,6 @@ static int sprom_extract(struct ssb_bus - out->boardflags_hi = 0; /* per specs */ - - return 0; --unsupported: -- ssb_printk(KERN_WARNING PFX "Unsupported SPROM revision %d " -- "detected. Will extract v1\n", out->revision); -- sprom_extract_r123(out, in); -- return 0; - } - - static int ssb_pci_sprom_get(struct ssb_bus *bus, ---- a/drivers/ssb/pcmcia.c -+++ b/drivers/ssb/pcmcia.c -@@ -583,7 +583,7 @@ static int ssb_pcmcia_sprom_write_all(st - ssb_printk("."); - err = ssb_pcmcia_sprom_write(bus, i, sprom[i]); - if (err) { -- ssb_printk("\n" KERN_NOTICE PFX -+ ssb_printk(KERN_NOTICE PFX - "Failed to write to SPROM.\n"); - failed = 1; - break; -@@ -591,7 +591,7 @@ static int ssb_pcmcia_sprom_write_all(st - } - err = ssb_pcmcia_sprom_command(bus, SSB_PCMCIA_SPROMCTL_WRITEDIS); - if (err) { -- ssb_printk("\n" KERN_NOTICE PFX -+ ssb_printk(KERN_NOTICE PFX - "Could not disable SPROM write access.\n"); - failed = 1; - } -@@ -678,7 +678,8 @@ int ssb_pcmcia_get_invariants(struct ssb - sprom->board_rev = tuple.TupleData[1]; - break; - case SSB_PCMCIA_CIS_PA: -- GOTO_ERROR_ON(tuple.TupleDataLen != 9, -+ GOTO_ERROR_ON((tuple.TupleDataLen != 9) && -+ (tuple.TupleDataLen != 10), - "pa tpl size"); - sprom->pa0b0 = tuple.TupleData[1] | - ((u16)tuple.TupleData[2] << 8); -@@ -718,7 +719,8 @@ int ssb_pcmcia_get_invariants(struct ssb - sprom->antenna_gain.ghz5.a3 = tuple.TupleData[1]; - break; - case SSB_PCMCIA_CIS_BFLAGS: -- GOTO_ERROR_ON(tuple.TupleDataLen != 3, -+ GOTO_ERROR_ON((tuple.TupleDataLen != 3) && -+ (tuple.TupleDataLen != 5), - "bfl tpl size"); - sprom->boardflags_lo = tuple.TupleData[1] | - ((u16)tuple.TupleData[2] << 8); ---- a/include/linux/ssb/ssb.h -+++ b/include/linux/ssb/ssb.h -@@ -27,24 +27,54 @@ struct ssb_sprom { - u8 et1mdcport; /* MDIO for enet1 */ - u8 board_rev; /* Board revision number from SPROM. */ - u8 country_code; /* Country Code */ -- u8 ant_available_a; /* A-PHY antenna available bits (up to 4) */ -- u8 ant_available_bg; /* B/G-PHY antenna available bits (up to 4) */ -+ u8 ant_available_a; /* 2GHz antenna available bits (up to 4) */ -+ u8 ant_available_bg; /* 5GHz antenna available bits (up to 4) */ - u16 pa0b0; - u16 pa0b1; - u16 pa0b2; - u16 pa1b0; - u16 pa1b1; - u16 pa1b2; -+ u16 pa1lob0; -+ u16 pa1lob1; -+ u16 pa1lob2; -+ u16 pa1hib0; -+ u16 pa1hib1; -+ u16 pa1hib2; - u8 gpio0; /* GPIO pin 0 */ - u8 gpio1; /* GPIO pin 1 */ - u8 gpio2; /* GPIO pin 2 */ - u8 gpio3; /* GPIO pin 3 */ -- u16 maxpwr_a; /* A-PHY Amplifier Max Power (in dBm Q5.2) */ -- u16 maxpwr_bg; /* B/G-PHY Amplifier Max Power (in dBm Q5.2) */ -+ u16 maxpwr_bg; /* 2.4GHz Amplifier Max Power (in dBm Q5.2) */ -+ u16 maxpwr_al; /* 5.2GHz Amplifier Max Power (in dBm Q5.2) */ -+ u16 maxpwr_a; /* 5.3GHz Amplifier Max Power (in dBm Q5.2) */ -+ u16 maxpwr_ah; /* 5.8GHz Amplifier Max Power (in dBm Q5.2) */ - u8 itssi_a; /* Idle TSSI Target for A-PHY */ - u8 itssi_bg; /* Idle TSSI Target for B/G-PHY */ -- u16 boardflags_lo; /* Boardflags (low 16 bits) */ -- u16 boardflags_hi; /* Boardflags (high 16 bits) */ -+ u8 tri2g; /* 2.4GHz TX isolation */ -+ u8 tri5gl; /* 5.2GHz TX isolation */ -+ u8 tri5g; /* 5.3GHz TX isolation */ -+ u8 tri5gh; /* 5.8GHz TX isolation */ -+ u8 rxpo2g; /* 2GHz RX power offset */ -+ u8 rxpo5g; /* 5GHz RX power offset */ -+ u8 rssisav2g; /* 2GHz RSSI params */ -+ u8 rssismc2g; -+ u8 rssismf2g; -+ u8 bxa2g; /* 2GHz BX arch */ -+ u8 rssisav5g; /* 5GHz RSSI params */ -+ u8 rssismc5g; -+ u8 rssismf5g; -+ u8 bxa5g; /* 5GHz BX arch */ -+ u16 cck2gpo; /* CCK power offset */ -+ u32 ofdm2gpo; /* 2.4GHz OFDM power offset */ -+ u32 ofdm5glpo; /* 5.2GHz OFDM power offset */ -+ u32 ofdm5gpo; /* 5.3GHz OFDM power offset */ -+ u32 ofdm5ghpo; /* 5.8GHz OFDM power offset */ -+ u16 boardflags_lo; /* Board flags (bits 0-15) */ -+ u16 boardflags_hi; /* Board flags (bits 16-31) */ -+ u16 boardflags2_lo; /* Board flags (bits 32-47) */ -+ u16 boardflags2_hi; /* Board flags (bits 48-63) */ -+ /* TODO store board flags in a single u64 */ - - /* Antenna gain values for up to 4 antennas - * on each band. Values in dBm/4 (Q5.2). Negative gain means the -@@ -58,7 +88,7 @@ struct ssb_sprom { - } ghz5; /* 5GHz band */ - } antenna_gain; - -- /* TODO - add any parameters needed from rev 2, 3, or 4 SPROMs */ -+ /* TODO - add any parameters needed from rev 2, 3, 4, 5 or 8 SPROMs */ - }; - - /* Information about the PCB the circuitry is soldered on. */ -@@ -208,6 +238,7 @@ enum ssb_bustype { - SSB_BUSTYPE_SSB, /* This SSB bus is the system bus */ - SSB_BUSTYPE_PCI, /* SSB is connected to PCI bus */ - SSB_BUSTYPE_PCMCIA, /* SSB is connected to PCMCIA bus */ -+ SSB_BUSTYPE_SDIO, /* SSB is connected to SDIO bus */ - }; - - /* board_vendor */ -@@ -240,8 +271,12 @@ struct ssb_bus { - - /* The core in the basic address register window. (PCI bus only) */ - struct ssb_device *mapped_device; -- /* Currently mapped PCMCIA segment. (bustype == SSB_BUSTYPE_PCMCIA only) */ -- u8 mapped_pcmcia_seg; -+ union { -+ /* Currently mapped PCMCIA segment. (bustype == SSB_BUSTYPE_PCMCIA only) */ -+ u8 mapped_pcmcia_seg; -+ /* Current SSB base address window for SDIO. */ -+ u32 sdio_sbaddr; -+ }; - /* Lock for core and segment switching. - * On PCMCIA-host busses this is used to protect the whole MMIO access. */ - spinlock_t bar_lock; -@@ -252,6 +287,11 @@ struct ssb_bus { - struct pci_dev *host_pci; - /* Pointer to the PCMCIA device (only if bustype == SSB_BUSTYPE_PCMCIA). */ - struct pcmcia_device *host_pcmcia; -+ /* Pointer to the SDIO device (only if bustype == SSB_BUSTYPE_SDIO). */ -+ struct sdio_func *host_sdio; -+ -+ /* See enum ssb_quirks */ -+ unsigned int quirks; - - #ifdef CONFIG_SSB_SPROM - /* Mutex to protect the SPROM writing. */ -@@ -306,6 +346,11 @@ struct ssb_bus { - #endif /* DEBUG */ - }; - -+enum ssb_quirks { -+ /* SDIO connected card requires performing a read after writing a 32-bit value */ -+ SSB_QUIRK_SDIO_READ_AFTER_WRITE32 = (1 << 0), -+}; -+ - /* The initialization-invariants. */ - struct ssb_init_invariants { - /* Versioning information about the PCB. */ ---- a/include/linux/ssb/ssb_driver_chipcommon.h -+++ b/include/linux/ssb/ssb_driver_chipcommon.h -@@ -181,6 +181,16 @@ - #define SSB_CHIPCO_PROG_WAITCNT 0x0124 - #define SSB_CHIPCO_FLASH_CFG 0x0128 - #define SSB_CHIPCO_FLASH_WAITCNT 0x012C -+#define SSB_CHIPCO_CLKCTLST 0x01E0 /* Clock control and status (rev >= 20) */ -+#define SSB_CHIPCO_CLKCTLST_FORCEALP 0x00000001 /* Force ALP request */ -+#define SSB_CHIPCO_CLKCTLST_FORCEHT 0x00000002 /* Force HT request */ -+#define SSB_CHIPCO_CLKCTLST_FORCEILP 0x00000004 /* Force ILP request */ -+#define SSB_CHIPCO_CLKCTLST_HAVEALPREQ 0x00000008 /* ALP available request */ -+#define SSB_CHIPCO_CLKCTLST_HAVEHTREQ 0x00000010 /* HT available request */ -+#define SSB_CHIPCO_CLKCTLST_HWCROFF 0x00000020 /* Force HW clock request off */ -+#define SSB_CHIPCO_CLKCTLST_HAVEHT 0x00010000 /* HT available */ -+#define SSB_CHIPCO_CLKCTLST_HAVEALP 0x00020000 /* APL available */ -+#define SSB_CHIPCO_HW_WORKAROUND 0x01E4 /* Hardware workaround (rev >= 20) */ - #define SSB_CHIPCO_UART0_DATA 0x0300 - #define SSB_CHIPCO_UART0_IMR 0x0304 - #define SSB_CHIPCO_UART0_FCR 0x0308 -@@ -197,6 +207,196 @@ - #define SSB_CHIPCO_UART1_LSR 0x0414 - #define SSB_CHIPCO_UART1_MSR 0x0418 - #define SSB_CHIPCO_UART1_SCRATCH 0x041C -+/* PMU registers (rev >= 20) */ -+#define SSB_CHIPCO_PMU_CTL 0x0600 /* PMU control */ -+#define SSB_CHIPCO_PMU_CTL_ILP_DIV 0xFFFF0000 /* ILP div mask */ -+#define SSB_CHIPCO_PMU_CTL_ILP_DIV_SHIFT 16 -+#define SSB_CHIPCO_PMU_CTL_NOILPONW 0x00000200 /* No ILP on wait */ -+#define SSB_CHIPCO_PMU_CTL_HTREQEN 0x00000100 /* HT req enable */ -+#define SSB_CHIPCO_PMU_CTL_ALPREQEN 0x00000080 /* ALP req enable */ -+#define SSB_CHIPCO_PMU_CTL_XTALFREQ 0x0000007C /* Crystal freq */ -+#define SSB_CHIPCO_PMU_CTL_XTALFREQ_SHIFT 2 -+#define SSB_CHIPCO_PMU_CTL_ILPDIVEN 0x00000002 /* ILP div enable */ -+#define SSB_CHIPCO_PMU_CTL_LPOSEL 0x00000001 /* LPO sel */ -+#define SSB_CHIPCO_PMU_CAP 0x0604 /* PMU capabilities */ -+#define SSB_CHIPCO_PMU_CAP_REVISION 0x000000FF /* Revision mask */ -+#define SSB_CHIPCO_PMU_STAT 0x0608 /* PMU status */ -+#define SSB_CHIPCO_PMU_STAT_INTPEND 0x00000040 /* Interrupt pending */ -+#define SSB_CHIPCO_PMU_STAT_SBCLKST 0x00000030 /* Backplane clock status? */ -+#define SSB_CHIPCO_PMU_STAT_HAVEALP 0x00000008 /* ALP available */ -+#define SSB_CHIPCO_PMU_STAT_HAVEHT 0x00000004 /* HT available */ -+#define SSB_CHIPCO_PMU_STAT_RESINIT 0x00000003 /* Res init */ -+#define SSB_CHIPCO_PMU_RES_STAT 0x060C /* PMU res status */ -+#define SSB_CHIPCO_PMU_RES_PEND 0x0610 /* PMU res pending */ -+#define SSB_CHIPCO_PMU_TIMER 0x0614 /* PMU timer */ -+#define SSB_CHIPCO_PMU_MINRES_MSK 0x0618 /* PMU min res mask */ -+#define SSB_CHIPCO_PMU_MAXRES_MSK 0x061C /* PMU max res mask */ -+#define SSB_CHIPCO_PMU_RES_TABSEL 0x0620 /* PMU res table sel */ -+#define SSB_CHIPCO_PMU_RES_DEPMSK 0x0624 /* PMU res dep mask */ -+#define SSB_CHIPCO_PMU_RES_UPDNTM 0x0628 /* PMU res updown timer */ -+#define SSB_CHIPCO_PMU_RES_TIMER 0x062C /* PMU res timer */ -+#define SSB_CHIPCO_PMU_CLKSTRETCH 0x0630 /* PMU clockstretch */ -+#define SSB_CHIPCO_PMU_WATCHDOG 0x0634 /* PMU watchdog */ -+#define SSB_CHIPCO_PMU_RES_REQTS 0x0640 /* PMU res req timer sel */ -+#define SSB_CHIPCO_PMU_RES_REQT 0x0644 /* PMU res req timer */ -+#define SSB_CHIPCO_PMU_RES_REQM 0x0648 /* PMU res req mask */ -+#define SSB_CHIPCO_CHIPCTL_ADDR 0x0650 -+#define SSB_CHIPCO_CHIPCTL_DATA 0x0654 -+#define SSB_CHIPCO_REGCTL_ADDR 0x0658 -+#define SSB_CHIPCO_REGCTL_DATA 0x065C -+#define SSB_CHIPCO_PLLCTL_ADDR 0x0660 -+#define SSB_CHIPCO_PLLCTL_DATA 0x0664 -+ -+ -+ -+/** PMU PLL registers */ -+ -+/* PMU rev 0 PLL registers */ -+#define SSB_PMU0_PLLCTL0 0 -+#define SSB_PMU0_PLLCTL0_PDIV_MSK 0x00000001 -+#define SSB_PMU0_PLLCTL0_PDIV_FREQ 25000 /* kHz */ -+#define SSB_PMU0_PLLCTL1 1 -+#define SSB_PMU0_PLLCTL1_WILD_IMSK 0xF0000000 /* Wild int mask (low nibble) */ -+#define SSB_PMU0_PLLCTL1_WILD_IMSK_SHIFT 28 -+#define SSB_PMU0_PLLCTL1_WILD_FMSK 0x0FFFFF00 /* Wild frac mask */ -+#define SSB_PMU0_PLLCTL1_WILD_FMSK_SHIFT 8 -+#define SSB_PMU0_PLLCTL1_STOPMOD 0x00000040 /* Stop mod */ -+#define SSB_PMU0_PLLCTL2 2 -+#define SSB_PMU0_PLLCTL2_WILD_IMSKHI 0x0000000F /* Wild int mask (high nibble) */ -+#define SSB_PMU0_PLLCTL2_WILD_IMSKHI_SHIFT 0 -+ -+/* PMU rev 1 PLL registers */ -+#define SSB_PMU1_PLLCTL0 0 -+#define SSB_PMU1_PLLCTL0_P1DIV 0x00F00000 /* P1 div */ -+#define SSB_PMU1_PLLCTL0_P1DIV_SHIFT 20 -+#define SSB_PMU1_PLLCTL0_P2DIV 0x0F000000 /* P2 div */ -+#define SSB_PMU1_PLLCTL0_P2DIV_SHIFT 24 -+#define SSB_PMU1_PLLCTL1 1 -+#define SSB_PMU1_PLLCTL1_M1DIV 0x000000FF /* M1 div */ -+#define SSB_PMU1_PLLCTL1_M1DIV_SHIFT 0 -+#define SSB_PMU1_PLLCTL1_M2DIV 0x0000FF00 /* M2 div */ -+#define SSB_PMU1_PLLCTL1_M2DIV_SHIFT 8 -+#define SSB_PMU1_PLLCTL1_M3DIV 0x00FF0000 /* M3 div */ -+#define SSB_PMU1_PLLCTL1_M3DIV_SHIFT 16 -+#define SSB_PMU1_PLLCTL1_M4DIV 0xFF000000 /* M4 div */ -+#define SSB_PMU1_PLLCTL1_M4DIV_SHIFT 24 -+#define SSB_PMU1_PLLCTL2 2 -+#define SSB_PMU1_PLLCTL2_M5DIV 0x000000FF /* M5 div */ -+#define SSB_PMU1_PLLCTL2_M5DIV_SHIFT 0 -+#define SSB_PMU1_PLLCTL2_M6DIV 0x0000FF00 /* M6 div */ -+#define SSB_PMU1_PLLCTL2_M6DIV_SHIFT 8 -+#define SSB_PMU1_PLLCTL2_NDIVMODE 0x000E0000 /* NDIV mode */ -+#define SSB_PMU1_PLLCTL2_NDIVMODE_SHIFT 17 -+#define SSB_PMU1_PLLCTL2_NDIVINT 0x1FF00000 /* NDIV int */ -+#define SSB_PMU1_PLLCTL2_NDIVINT_SHIFT 20 -+#define SSB_PMU1_PLLCTL3 3 -+#define SSB_PMU1_PLLCTL3_NDIVFRAC 0x00FFFFFF /* NDIV frac */ -+#define SSB_PMU1_PLLCTL3_NDIVFRAC_SHIFT 0 -+#define SSB_PMU1_PLLCTL4 4 -+#define SSB_PMU1_PLLCTL5 5 -+#define SSB_PMU1_PLLCTL5_CLKDRV 0xFFFFFF00 /* clk drv */ -+#define SSB_PMU1_PLLCTL5_CLKDRV_SHIFT 8 -+ -+/* BCM4312 PLL resource numbers. */ -+#define SSB_PMURES_4312_SWITCHER_BURST 0 -+#define SSB_PMURES_4312_SWITCHER_PWM 1 -+#define SSB_PMURES_4312_PA_REF_LDO 2 -+#define SSB_PMURES_4312_CORE_LDO_BURST 3 -+#define SSB_PMURES_4312_CORE_LDO_PWM 4 -+#define SSB_PMURES_4312_RADIO_LDO 5 -+#define SSB_PMURES_4312_ILP_REQUEST 6 -+#define SSB_PMURES_4312_BG_FILTBYP 7 -+#define SSB_PMURES_4312_TX_FILTBYP 8 -+#define SSB_PMURES_4312_RX_FILTBYP 9 -+#define SSB_PMURES_4312_XTAL_PU 10 -+#define SSB_PMURES_4312_ALP_AVAIL 11 -+#define SSB_PMURES_4312_BB_PLL_FILTBYP 12 -+#define SSB_PMURES_4312_RF_PLL_FILTBYP 13 -+#define SSB_PMURES_4312_HT_AVAIL 14 -+ -+/* BCM4325 PLL resource numbers. */ -+#define SSB_PMURES_4325_BUCK_BOOST_BURST 0 -+#define SSB_PMURES_4325_CBUCK_BURST 1 -+#define SSB_PMURES_4325_CBUCK_PWM 2 -+#define SSB_PMURES_4325_CLDO_CBUCK_BURST 3 -+#define SSB_PMURES_4325_CLDO_CBUCK_PWM 4 -+#define SSB_PMURES_4325_BUCK_BOOST_PWM 5 -+#define SSB_PMURES_4325_ILP_REQUEST 6 -+#define SSB_PMURES_4325_ABUCK_BURST 7 -+#define SSB_PMURES_4325_ABUCK_PWM 8 -+#define SSB_PMURES_4325_LNLDO1_PU 9 -+#define SSB_PMURES_4325_LNLDO2_PU 10 -+#define SSB_PMURES_4325_LNLDO3_PU 11 -+#define SSB_PMURES_4325_LNLDO4_PU 12 -+#define SSB_PMURES_4325_XTAL_PU 13 -+#define SSB_PMURES_4325_ALP_AVAIL 14 -+#define SSB_PMURES_4325_RX_PWRSW_PU 15 -+#define SSB_PMURES_4325_TX_PWRSW_PU 16 -+#define SSB_PMURES_4325_RFPLL_PWRSW_PU 17 -+#define SSB_PMURES_4325_LOGEN_PWRSW_PU 18 -+#define SSB_PMURES_4325_AFE_PWRSW_PU 19 -+#define SSB_PMURES_4325_BBPLL_PWRSW_PU 20 -+#define SSB_PMURES_4325_HT_AVAIL 21 -+ -+/* BCM4328 PLL resource numbers. */ -+#define SSB_PMURES_4328_EXT_SWITCHER_PWM 0 -+#define SSB_PMURES_4328_BB_SWITCHER_PWM 1 -+#define SSB_PMURES_4328_BB_SWITCHER_BURST 2 -+#define SSB_PMURES_4328_BB_EXT_SWITCHER_BURST 3 -+#define SSB_PMURES_4328_ILP_REQUEST 4 -+#define SSB_PMURES_4328_RADIO_SWITCHER_PWM 5 -+#define SSB_PMURES_4328_RADIO_SWITCHER_BURST 6 -+#define SSB_PMURES_4328_ROM_SWITCH 7 -+#define SSB_PMURES_4328_PA_REF_LDO 8 -+#define SSB_PMURES_4328_RADIO_LDO 9 -+#define SSB_PMURES_4328_AFE_LDO 10 -+#define SSB_PMURES_4328_PLL_LDO 11 -+#define SSB_PMURES_4328_BG_FILTBYP 12 -+#define SSB_PMURES_4328_TX_FILTBYP 13 -+#define SSB_PMURES_4328_RX_FILTBYP 14 -+#define SSB_PMURES_4328_XTAL_PU 15 -+#define SSB_PMURES_4328_XTAL_EN 16 -+#define SSB_PMURES_4328_BB_PLL_FILTBYP 17 -+#define SSB_PMURES_4328_RF_PLL_FILTBYP 18 -+#define SSB_PMURES_4328_BB_PLL_PU 19 -+ -+/* BCM5354 PLL resource numbers. */ -+#define SSB_PMURES_5354_EXT_SWITCHER_PWM 0 -+#define SSB_PMURES_5354_BB_SWITCHER_PWM 1 -+#define SSB_PMURES_5354_BB_SWITCHER_BURST 2 -+#define SSB_PMURES_5354_BB_EXT_SWITCHER_BURST 3 -+#define SSB_PMURES_5354_ILP_REQUEST 4 -+#define SSB_PMURES_5354_RADIO_SWITCHER_PWM 5 -+#define SSB_PMURES_5354_RADIO_SWITCHER_BURST 6 -+#define SSB_PMURES_5354_ROM_SWITCH 7 -+#define SSB_PMURES_5354_PA_REF_LDO 8 -+#define SSB_PMURES_5354_RADIO_LDO 9 -+#define SSB_PMURES_5354_AFE_LDO 10 -+#define SSB_PMURES_5354_PLL_LDO 11 -+#define SSB_PMURES_5354_BG_FILTBYP 12 -+#define SSB_PMURES_5354_TX_FILTBYP 13 -+#define SSB_PMURES_5354_RX_FILTBYP 14 -+#define SSB_PMURES_5354_XTAL_PU 15 -+#define SSB_PMURES_5354_XTAL_EN 16 -+#define SSB_PMURES_5354_BB_PLL_FILTBYP 17 -+#define SSB_PMURES_5354_RF_PLL_FILTBYP 18 -+#define SSB_PMURES_5354_BB_PLL_PU 19 -+ -+ -+ -+/** Chip specific Chip-Status register contents. */ -+#define SSB_CHIPCO_CHST_4325_SPROM_OTP_SEL 0x00000003 -+#define SSB_CHIPCO_CHST_4325_DEFCIS_SEL 0 /* OTP is powered up, use def. CIS, no SPROM */ -+#define SSB_CHIPCO_CHST_4325_SPROM_SEL 1 /* OTP is powered up, SPROM is present */ -+#define SSB_CHIPCO_CHST_4325_OTP_SEL 2 /* OTP is powered up, no SPROM */ -+#define SSB_CHIPCO_CHST_4325_OTP_PWRDN 3 /* OTP is powered down, SPROM is present */ -+#define SSB_CHIPCO_CHST_4325_SDIO_USB_MODE 0x00000004 -+#define SSB_CHIPCO_CHST_4325_SDIO_USB_MODE_SHIFT 2 -+#define SSB_CHIPCO_CHST_4325_RCAL_VALID 0x00000008 -+#define SSB_CHIPCO_CHST_4325_RCAL_VALID_SHIFT 3 -+#define SSB_CHIPCO_CHST_4325_RCAL_VALUE 0x000001F0 -+#define SSB_CHIPCO_CHST_4325_RCAL_VALUE_SHIFT 4 -+#define SSB_CHIPCO_CHST_4325_PMUTOP_2B 0x00000200 /* 1 for 2b, 0 for to 2a */ - - - -@@ -353,11 +553,20 @@ - struct ssb_device; - struct ssb_serial_port; - -+/* Data for the PMU, if available. -+ * Check availability with ((struct ssb_chipcommon)->capabilities & SSB_CHIPCO_CAP_PMU) -+ */ -+struct ssb_chipcommon_pmu { -+ u8 rev; /* PMU revision */ -+ u32 crystalfreq; /* The active crystal frequency (in kHz) */ -+}; -+ - struct ssb_chipcommon { - struct ssb_device *dev; - u32 capabilities; - /* Fast Powerup Delay constant */ - u16 fast_pwrup_delay; -+ struct ssb_chipcommon_pmu pmu; - }; - - static inline bool ssb_chipco_available(struct ssb_chipcommon *cc) -@@ -365,6 +574,17 @@ static inline bool ssb_chipco_available( - return (cc->dev != NULL); - } - -+/* Register access */ -+#define chipco_read32(cc, offset) ssb_read32((cc)->dev, offset) -+#define chipco_write32(cc, offset, val) ssb_write32((cc)->dev, offset, val) -+ -+#define chipco_mask32(cc, offset, mask) \ -+ chipco_write32(cc, offset, chipco_read32(cc, offset) & (mask)) -+#define chipco_set32(cc, offset, set) \ -+ chipco_write32(cc, offset, chipco_read32(cc, offset) | (set)) -+#define chipco_maskset32(cc, offset, mask, set) \ -+ chipco_write32(cc, offset, (chipco_read32(cc, offset) & (mask)) | (set)) -+ - extern void ssb_chipcommon_init(struct ssb_chipcommon *cc); - - extern void ssb_chipco_suspend(struct ssb_chipcommon *cc); -@@ -406,4 +626,18 @@ extern int ssb_chipco_serial_init(struct - struct ssb_serial_port *ports); - #endif /* CONFIG_SSB_SERIAL */ - -+/* PMU support */ -+extern void ssb_pmu_init(struct ssb_chipcommon *cc); -+ -+enum ssb_pmu_ldo_volt_id { -+ LDO_PAREF = 0, -+ LDO_VOLT1, -+ LDO_VOLT2, -+ LDO_VOLT3, -+}; -+ -+void ssb_pmu_set_ldo_voltage(struct ssb_chipcommon *cc, -+ enum ssb_pmu_ldo_volt_id id, u32 voltage); -+void ssb_pmu_set_ldo_paref(struct ssb_chipcommon *cc, bool on); -+ - #endif /* LINUX_SSB_CHIPCO_H_ */ ---- a/include/linux/ssb/ssb_regs.h -+++ b/include/linux/ssb/ssb_regs.h -@@ -162,7 +162,7 @@ - - /* SPROM shadow area. If not otherwise noted, fields are - * two bytes wide. Note that the SPROM can _only_ be read -- * in two-byte quantinies. -+ * in two-byte quantities. - */ - #define SSB_SPROMSIZE_WORDS 64 - #define SSB_SPROMSIZE_BYTES (SSB_SPROMSIZE_WORDS * sizeof(u16)) -@@ -326,6 +326,94 @@ - #define SSB_SPROM5_GPIOB_P3 0xFF00 /* Pin 3 */ - #define SSB_SPROM5_GPIOB_P3_SHIFT 8 - -+/* SPROM Revision 8 */ -+#define SSB_SPROM8_BOARDREV 0x1082 /* Board revision */ -+#define SSB_SPROM8_BFLLO 0x1084 /* Board flags (bits 0-15) */ -+#define SSB_SPROM8_BFLHI 0x1086 /* Board flags (bits 16-31) */ -+#define SSB_SPROM8_BFL2LO 0x1088 /* Board flags (bits 32-47) */ -+#define SSB_SPROM8_BFL2HI 0x108A /* Board flags (bits 48-63) */ -+#define SSB_SPROM8_IL0MAC 0x108C /* 6 byte MAC address */ -+#define SSB_SPROM8_CCODE 0x1092 /* 2 byte country code */ -+#define SSB_SPROM8_ANTAVAIL 0x109C /* Antenna available bitfields*/ -+#define SSB_SPROM8_ANTAVAIL_A 0xFF00 /* A-PHY bitfield */ -+#define SSB_SPROM8_ANTAVAIL_A_SHIFT 8 -+#define SSB_SPROM8_ANTAVAIL_BG 0x00FF /* B-PHY and G-PHY bitfield */ -+#define SSB_SPROM8_ANTAVAIL_BG_SHIFT 0 -+#define SSB_SPROM8_AGAIN01 0x109E /* Antenna Gain (in dBm Q5.2) */ -+#define SSB_SPROM8_AGAIN0 0x00FF /* Antenna 0 */ -+#define SSB_SPROM8_AGAIN0_SHIFT 0 -+#define SSB_SPROM8_AGAIN1 0xFF00 /* Antenna 1 */ -+#define SSB_SPROM8_AGAIN1_SHIFT 8 -+#define SSB_SPROM8_AGAIN23 0x10A0 -+#define SSB_SPROM8_AGAIN2 0x00FF /* Antenna 2 */ -+#define SSB_SPROM8_AGAIN2_SHIFT 0 -+#define SSB_SPROM8_AGAIN3 0xFF00 /* Antenna 3 */ -+#define SSB_SPROM8_AGAIN3_SHIFT 8 -+#define SSB_SPROM8_GPIOA 0x1096 /*Gen. Purpose IO # 0 and 1 */ -+#define SSB_SPROM8_GPIOA_P0 0x00FF /* Pin 0 */ -+#define SSB_SPROM8_GPIOA_P1 0xFF00 /* Pin 1 */ -+#define SSB_SPROM8_GPIOA_P1_SHIFT 8 -+#define SSB_SPROM8_GPIOB 0x1098 /* Gen. Purpose IO # 2 and 3 */ -+#define SSB_SPROM8_GPIOB_P2 0x00FF /* Pin 2 */ -+#define SSB_SPROM8_GPIOB_P3 0xFF00 /* Pin 3 */ -+#define SSB_SPROM8_GPIOB_P3_SHIFT 8 -+#define SSB_SPROM8_RSSIPARM2G 0x10A4 /* RSSI params for 2GHz */ -+#define SSB_SPROM8_RSSISMF2G 0x000F -+#define SSB_SPROM8_RSSISMC2G 0x00F0 -+#define SSB_SPROM8_RSSISMC2G_SHIFT 4 -+#define SSB_SPROM8_RSSISAV2G 0x0700 -+#define SSB_SPROM8_RSSISAV2G_SHIFT 8 -+#define SSB_SPROM8_BXA2G 0x1800 -+#define SSB_SPROM8_BXA2G_SHIFT 11 -+#define SSB_SPROM8_RSSIPARM5G 0x10A6 /* RSSI params for 5GHz */ -+#define SSB_SPROM8_RSSISMF5G 0x000F -+#define SSB_SPROM8_RSSISMC5G 0x00F0 -+#define SSB_SPROM8_RSSISMC5G_SHIFT 4 -+#define SSB_SPROM8_RSSISAV5G 0x0700 -+#define SSB_SPROM8_RSSISAV5G_SHIFT 8 -+#define SSB_SPROM8_BXA5G 0x1800 -+#define SSB_SPROM8_BXA5G_SHIFT 11 -+#define SSB_SPROM8_TRI25G 0x10A8 /* TX isolation 2.4&5.3GHz */ -+#define SSB_SPROM8_TRI2G 0x00FF /* TX isolation 2.4GHz */ -+#define SSB_SPROM8_TRI5G 0xFF00 /* TX isolation 5.3GHz */ -+#define SSB_SPROM8_TRI5G_SHIFT 8 -+#define SSB_SPROM8_TRI5GHL 0x10AA /* TX isolation 5.2/5.8GHz */ -+#define SSB_SPROM8_TRI5GL 0x00FF /* TX isolation 5.2GHz */ -+#define SSB_SPROM8_TRI5GH 0xFF00 /* TX isolation 5.8GHz */ -+#define SSB_SPROM8_TRI5GH_SHIFT 8 -+#define SSB_SPROM8_RXPO 0x10AC /* RX power offsets */ -+#define SSB_SPROM8_RXPO2G 0x00FF /* 2GHz RX power offset */ -+#define SSB_SPROM8_RXPO5G 0xFF00 /* 5GHz RX power offset */ -+#define SSB_SPROM8_RXPO5G_SHIFT 8 -+#define SSB_SPROM8_MAXP_BG 0x10C0 /* Max Power 2GHz in path 1 */ -+#define SSB_SPROM8_MAXP_BG_MASK 0x00FF /* Mask for Max Power 2GHz */ -+#define SSB_SPROM8_ITSSI_BG 0xFF00 /* Mask for path 1 itssi_bg */ -+#define SSB_SPROM8_ITSSI_BG_SHIFT 8 -+#define SSB_SPROM8_PA0B0 0x10C2 /* 2GHz power amp settings */ -+#define SSB_SPROM8_PA0B1 0x10C4 -+#define SSB_SPROM8_PA0B2 0x10C6 -+#define SSB_SPROM8_MAXP_A 0x10C8 /* Max Power 5.3GHz */ -+#define SSB_SPROM8_MAXP_A_MASK 0x00FF /* Mask for Max Power 5.3GHz */ -+#define SSB_SPROM8_ITSSI_A 0xFF00 /* Mask for path 1 itssi_a */ -+#define SSB_SPROM8_ITSSI_A_SHIFT 8 -+#define SSB_SPROM8_MAXP_AHL 0x10CA /* Max Power 5.2/5.8GHz */ -+#define SSB_SPROM8_MAXP_AH_MASK 0x00FF /* Mask for Max Power 5.8GHz */ -+#define SSB_SPROM8_MAXP_AL_MASK 0xFF00 /* Mask for Max Power 5.2GHz */ -+#define SSB_SPROM8_MAXP_AL_SHIFT 8 -+#define SSB_SPROM8_PA1B0 0x10CC /* 5.3GHz power amp settings */ -+#define SSB_SPROM8_PA1B1 0x10CE -+#define SSB_SPROM8_PA1B2 0x10D0 -+#define SSB_SPROM8_PA1LOB0 0x10D2 /* 5.2GHz power amp settings */ -+#define SSB_SPROM8_PA1LOB1 0x10D4 -+#define SSB_SPROM8_PA1LOB2 0x10D6 -+#define SSB_SPROM8_PA1HIB0 0x10D8 /* 5.8GHz power amp settings */ -+#define SSB_SPROM8_PA1HIB1 0x10DA -+#define SSB_SPROM8_PA1HIB2 0x10DC -+#define SSB_SPROM8_CCK2GPO 0x1140 /* CCK power offset */ -+#define SSB_SPROM8_OFDM2GPO 0x1142 /* 2.4GHz OFDM power offset */ -+#define SSB_SPROM8_OFDM5GPO 0x1146 /* 5.3GHz OFDM power offset */ -+#define SSB_SPROM8_OFDM5GLPO 0x114A /* 5.2GHz OFDM power offset */ -+#define SSB_SPROM8_OFDM5GHPO 0x114E /* 5.8GHz OFDM power offset */ - - /* Values for SSB_SPROM1_BINF_CCODE */ - enum { ---- a/drivers/ssb/driver_chipcommon.c -+++ b/drivers/ssb/driver_chipcommon.c -@@ -26,19 +26,6 @@ enum ssb_clksrc { - }; - - --static inline u32 chipco_read32(struct ssb_chipcommon *cc, -- u16 offset) --{ -- return ssb_read32(cc->dev, offset); --} -- --static inline void chipco_write32(struct ssb_chipcommon *cc, -- u16 offset, -- u32 value) --{ -- ssb_write32(cc->dev, offset, value); --} -- - static inline u32 chipco_write32_masked(struct ssb_chipcommon *cc, u16 offset, - u32 mask, u32 value) - { -@@ -246,6 +233,7 @@ void ssb_chipcommon_init(struct ssb_chip - { - if (!cc->dev) - return; /* We don't have a ChipCommon */ -+ ssb_pmu_init(cc); - chipco_powercontrol_init(cc); - ssb_chipco_set_clockmode(cc, SSB_CLKMODE_FAST); - calc_fast_powerup_delay(cc); ---- a/drivers/ssb/scan.c -+++ b/drivers/ssb/scan.c -@@ -175,6 +175,8 @@ static u32 scan_read32(struct ssb_bus *b - } else - ssb_pcmcia_switch_segment(bus, 0); - break; -+ default: -+ break; - } - return readl(bus->mmio + offset); - } -@@ -188,6 +190,8 @@ static int scan_switchcore(struct ssb_bu - return ssb_pci_switch_coreidx(bus, coreidx); - case SSB_BUSTYPE_PCMCIA: - return ssb_pcmcia_switch_coreidx(bus, coreidx); -+ default: -+ break; - } - return 0; - } -@@ -206,6 +210,8 @@ void ssb_iounmap(struct ssb_bus *bus) - SSB_BUG_ON(1); /* Can't reach this code. */ - #endif - break; -+ default: -+ break; - } - bus->mmio = NULL; - bus->mapped_device = NULL; -@@ -230,6 +236,8 @@ static void __iomem *ssb_ioremap(struct - SSB_BUG_ON(1); /* Can't reach this code. */ - #endif - break; -+ default: -+ break; - } - - return mmio; diff --git a/target/linux/generic-2.6/patches-2.6.28/977-textsearch_kconfig_hacks.patch b/target/linux/generic-2.6/patches-2.6.28/977-textsearch_kconfig_hacks.patch deleted file mode 100644 index aec5ac321..000000000 --- a/target/linux/generic-2.6/patches-2.6.28/977-textsearch_kconfig_hacks.patch +++ /dev/null @@ -1,23 +0,0 @@ ---- a/lib/Kconfig -+++ b/lib/Kconfig -@@ -119,16 +119,16 @@ config REED_SOLOMON_DEC16 - # Textsearch support is select'ed if needed - # - config TEXTSEARCH -- boolean -+ boolean "Textsearch support" - - config TEXTSEARCH_KMP -- tristate -+ tristate "Textsearch KMP" - - config TEXTSEARCH_BM -- tristate -+ tristate "Textsearch BM" - - config TEXTSEARCH_FSM -- tristate -+ tristate "Textsearch FSM" - - # - # plist support is select#ed if needed diff --git a/target/linux/generic-2.6/patches-2.6.28/979-crypto_add_kconfig_prompts.patch b/target/linux/generic-2.6/patches-2.6.28/979-crypto_add_kconfig_prompts.patch deleted file mode 100644 index df7837dba..000000000 --- a/target/linux/generic-2.6/patches-2.6.28/979-crypto_add_kconfig_prompts.patch +++ /dev/null @@ -1,47 +0,0 @@ ---- a/crypto/Kconfig -+++ b/crypto/Kconfig -@@ -30,7 +30,7 @@ config CRYPTO_FIPS - this is. - - config CRYPTO_ALGAPI -- tristate -+ tristate "ALGAPI" - select CRYPTO_ALGAPI2 - help - This option provides the API for cryptographic algorithms. -@@ -39,7 +39,7 @@ config CRYPTO_ALGAPI2 - tristate - - config CRYPTO_AEAD -- tristate -+ tristate "AEAD" - select CRYPTO_AEAD2 - select CRYPTO_ALGAPI - -@@ -48,7 +48,7 @@ config CRYPTO_AEAD2 - select CRYPTO_ALGAPI2 - - config CRYPTO_BLKCIPHER -- tristate -+ tristate "BLKCIPHER" - select CRYPTO_BLKCIPHER2 - select CRYPTO_ALGAPI - -@@ -58,7 +58,7 @@ config CRYPTO_BLKCIPHER2 - select CRYPTO_RNG2 - - config CRYPTO_HASH -- tristate -+ tristate "HASH" - select CRYPTO_HASH2 - select CRYPTO_ALGAPI - -@@ -67,7 +67,7 @@ config CRYPTO_HASH2 - select CRYPTO_ALGAPI2 - - config CRYPTO_RNG -- tristate -+ tristate "RNG" - select CRYPTO_RNG2 - select CRYPTO_ALGAPI - diff --git a/target/linux/generic-2.6/patches-2.6.28/980-vm_exports.patch b/target/linux/generic-2.6/patches-2.6.28/980-vm_exports.patch deleted file mode 100644 index 023bf295e..000000000 --- a/target/linux/generic-2.6/patches-2.6.28/980-vm_exports.patch +++ /dev/null @@ -1,113 +0,0 @@ ---- a/mm/shmem.c -+++ b/mm/shmem.c -@@ -2480,6 +2480,15 @@ static int shmem_get_sb(struct file_syst - return get_sb_nodev(fs_type, flags, data, shmem_fill_super, mnt); - } - -+void shmem_set_file(struct vm_area_struct *vma, struct file *file) -+{ -+ if (vma->vm_file) -+ fput(vma->vm_file); -+ vma->vm_file = file; -+ vma->vm_ops = &shmem_vm_ops; -+} -+EXPORT_SYMBOL_GPL(shmem_set_file); -+ - static struct file_system_type tmpfs_fs_type = { - .owner = THIS_MODULE, - .name = "tmpfs", -@@ -2600,9 +2609,6 @@ int shmem_zero_setup(struct vm_area_stru - if (IS_ERR(file)) - return PTR_ERR(file); - -- if (vma->vm_file) -- fput(vma->vm_file); -- vma->vm_file = file; -- vma->vm_ops = &shmem_vm_ops; -+ shmem_set_file(vma, file); - return 0; - } ---- a/fs/file.c -+++ b/fs/file.c -@@ -270,6 +270,7 @@ int expand_files(struct files_struct *fi - /* All good, so we try */ - return expand_fdtable(files, nr); - } -+EXPORT_SYMBOL_GPL(expand_files); - - static int count_open_files(struct fdtable *fdt) - { ---- a/kernel/exit.c -+++ b/kernel/exit.c -@@ -509,6 +509,7 @@ struct files_struct *get_files_struct(st - - return files; - } -+EXPORT_SYMBOL_GPL(get_files_struct); - - void put_files_struct(struct files_struct *files) - { -@@ -528,6 +529,7 @@ void put_files_struct(struct files_struc - free_fdtable(fdt); - } - } -+EXPORT_SYMBOL_GPL(put_files_struct); - - void reset_files_struct(struct files_struct *files) - { ---- a/kernel/fork.c -+++ b/kernel/fork.c -@@ -155,6 +155,7 @@ void __put_task_struct(struct task_struc - if (!profile_handoff_task(tsk)) - free_task(tsk); - } -+EXPORT_SYMBOL_GPL(__put_task_struct); - - /* - * macro override instead of weak attribute alias, to workaround ---- a/kernel/sched.c -+++ b/kernel/sched.c -@@ -5064,6 +5064,7 @@ int can_nice(const struct task_struct *p - return (nice_rlim <= p->signal->rlim[RLIMIT_NICE].rlim_cur || - capable(CAP_SYS_NICE)); - } -+EXPORT_SYMBOL_GPL(can_nice); - - #ifdef __ARCH_WANT_SYS_NICE - ---- a/mm/memory.c -+++ b/mm/memory.c -@@ -993,6 +993,7 @@ unsigned long zap_page_range(struct vm_a - tlb_finish_mmu(tlb, address, end); - return end; - } -+EXPORT_SYMBOL_GPL(zap_page_range); - - /** - * zap_vma_ptes - remove ptes mapping the vma -@@ -2271,6 +2272,7 @@ int vmtruncate_range(struct inode *inode - - return 0; - } -+EXPORT_SYMBOL_GPL(vmtruncate_range); - - /* - * We enter with non-exclusive mmap_sem (to exclude vma changes, ---- a/mm/vmalloc.c -+++ b/mm/vmalloc.c -@@ -1002,6 +1002,7 @@ void unmap_kernel_range(unsigned long ad - vunmap_page_range(addr, end); - flush_tlb_kernel_range(addr, end); - } -+EXPORT_SYMBOL_GPL(unmap_kernel_range); - - int map_vm_area(struct vm_struct *area, pgprot_t prot, struct page ***pages) - { -@@ -1107,6 +1108,7 @@ struct vm_struct *get_vm_area(unsigned l - return __get_vm_area_node(size, flags, VMALLOC_START, VMALLOC_END, - -1, GFP_KERNEL, __builtin_return_address(0)); - } -+EXPORT_SYMBOL_GPL(get_vm_area); - - struct vm_struct *get_vm_area_caller(unsigned long size, unsigned long flags, - void *caller) diff --git a/target/linux/generic-2.6/patches-2.6.28/981-vsprintf_backport.patch b/target/linux/generic-2.6/patches-2.6.28/981-vsprintf_backport.patch deleted file mode 100644 index 37589b188..000000000 --- a/target/linux/generic-2.6/patches-2.6.28/981-vsprintf_backport.patch +++ /dev/null @@ -1,888 +0,0 @@ ---- a/lib/vsprintf.c -+++ b/lib/vsprintf.c -@@ -170,6 +170,8 @@ int strict_strtoul(const char *cp, unsig - return -EINVAL; - - val = simple_strtoul(cp, &tail, base); -+ if (tail == cp) -+ return -EINVAL; - if ((*tail == '\0') || - ((len == (size_t)(tail - cp) + 1) && (*tail == '\n'))) { - *res = val; -@@ -241,6 +243,8 @@ int strict_strtoull(const char *cp, unsi - return -EINVAL; - - val = simple_strtoull(cp, &tail, base); -+ if (tail == cp) -+ return -EINVAL; - if ((*tail == '\0') || - ((len == (size_t)(tail - cp) + 1) && (*tail == '\n'))) { - *res = val; -@@ -392,7 +396,38 @@ static noinline char* put_dec(char *buf, - #define SMALL 32 /* Must be 32 == 0x20 */ - #define SPECIAL 64 /* 0x */ - --static char *number(char *buf, char *end, unsigned long long num, int base, int size, int precision, int type) -+enum format_type { -+ FORMAT_TYPE_NONE, /* Just a string part */ -+ FORMAT_TYPE_WIDTH, -+ FORMAT_TYPE_PRECISION, -+ FORMAT_TYPE_CHAR, -+ FORMAT_TYPE_STR, -+ FORMAT_TYPE_PTR, -+ FORMAT_TYPE_PERCENT_CHAR, -+ FORMAT_TYPE_INVALID, -+ FORMAT_TYPE_LONG_LONG, -+ FORMAT_TYPE_ULONG, -+ FORMAT_TYPE_LONG, -+ FORMAT_TYPE_USHORT, -+ FORMAT_TYPE_SHORT, -+ FORMAT_TYPE_UINT, -+ FORMAT_TYPE_INT, -+ FORMAT_TYPE_NRCHARS, -+ FORMAT_TYPE_SIZE_T, -+ FORMAT_TYPE_PTRDIFF -+}; -+ -+struct printf_spec { -+ enum format_type type; -+ int flags; /* flags to number() */ -+ int field_width; /* width of output field */ -+ int base; -+ int precision; /* # of digits/chars */ -+ int qualifier; -+}; -+ -+static char *number(char *buf, char *end, unsigned long long num, -+ struct printf_spec spec) - { - /* we are called with base 8, 10 or 16, only, thus don't need "G..." */ - static const char digits[16] = "0123456789ABCDEF"; /* "GHIJKLMNOPQRSTUVWXYZ"; */ -@@ -400,32 +435,32 @@ static char *number(char *buf, char *end - char tmp[66]; - char sign; - char locase; -- int need_pfx = ((type & SPECIAL) && base != 10); -+ int need_pfx = ((spec.flags & SPECIAL) && spec.base != 10); - int i; - - /* locase = 0 or 0x20. ORing digits or letters with 'locase' - * produces same digits or (maybe lowercased) letters */ -- locase = (type & SMALL); -- if (type & LEFT) -- type &= ~ZEROPAD; -+ locase = (spec.flags & SMALL); -+ if (spec.flags & LEFT) -+ spec.flags &= ~ZEROPAD; - sign = 0; -- if (type & SIGN) { -+ if (spec.flags & SIGN) { - if ((signed long long) num < 0) { - sign = '-'; - num = - (signed long long) num; -- size--; -- } else if (type & PLUS) { -+ spec.field_width--; -+ } else if (spec.flags & PLUS) { - sign = '+'; -- size--; -- } else if (type & SPACE) { -+ spec.field_width--; -+ } else if (spec.flags & SPACE) { - sign = ' '; -- size--; -+ spec.field_width--; - } - } - if (need_pfx) { -- size--; -- if (base == 16) -- size--; -+ spec.field_width--; -+ if (spec.base == 16) -+ spec.field_width--; - } - - /* generate full string in tmp[], in reverse order */ -@@ -437,10 +472,10 @@ static char *number(char *buf, char *end - tmp[i++] = (digits[do_div(num,base)] | locase); - } while (num != 0); - */ -- else if (base != 10) { /* 8 or 16 */ -- int mask = base - 1; -+ else if (spec.base != 10) { /* 8 or 16 */ -+ int mask = spec.base - 1; - int shift = 3; -- if (base == 16) shift = 4; -+ if (spec.base == 16) shift = 4; - do { - tmp[i++] = (digits[((unsigned char)num) & mask] | locase); - num >>= shift; -@@ -450,12 +485,12 @@ static char *number(char *buf, char *end - } - - /* printing 100 using %2d gives "100", not "00" */ -- if (i > precision) -- precision = i; -+ if (i > spec.precision) -+ spec.precision = i; - /* leading space padding */ -- size -= precision; -- if (!(type & (ZEROPAD+LEFT))) { -- while(--size >= 0) { -+ spec.field_width -= spec.precision; -+ if (!(spec.flags & (ZEROPAD+LEFT))) { -+ while(--spec.field_width >= 0) { - if (buf < end) - *buf = ' '; - ++buf; -@@ -472,23 +507,23 @@ static char *number(char *buf, char *end - if (buf < end) - *buf = '0'; - ++buf; -- if (base == 16) { -+ if (spec.base == 16) { - if (buf < end) - *buf = ('X' | locase); - ++buf; - } - } - /* zero or space padding */ -- if (!(type & LEFT)) { -- char c = (type & ZEROPAD) ? '0' : ' '; -- while (--size >= 0) { -+ if (!(spec.flags & LEFT)) { -+ char c = (spec.flags & ZEROPAD) ? '0' : ' '; -+ while (--spec.field_width >= 0) { - if (buf < end) - *buf = c; - ++buf; - } - } - /* hmm even more zero padding? */ -- while (i <= --precision) { -+ while (i <= --spec.precision) { - if (buf < end) - *buf = '0'; - ++buf; -@@ -500,7 +535,7 @@ static char *number(char *buf, char *end - ++buf; - } - /* trailing space padding */ -- while (--size >= 0) { -+ while (--spec.field_width >= 0) { - if (buf < end) - *buf = ' '; - ++buf; -@@ -508,17 +543,17 @@ static char *number(char *buf, char *end - return buf; - } - --static char *string(char *buf, char *end, char *s, int field_width, int precision, int flags) -+static char *string(char *buf, char *end, char *s, struct printf_spec spec) - { - int len, i; - - if ((unsigned long)s < PAGE_SIZE) - s = ""; - -- len = strnlen(s, precision); -+ len = strnlen(s, spec.precision); - -- if (!(flags & LEFT)) { -- while (len < field_width--) { -+ if (!(spec.flags & LEFT)) { -+ while (len < spec.field_width--) { - if (buf < end) - *buf = ' '; - ++buf; -@@ -529,7 +564,7 @@ static char *string(char *buf, char *end - *buf = *s; - ++buf; ++s; - } -- while (len < field_width--) { -+ while (len < spec.field_width--) { - if (buf < end) - *buf = ' '; - ++buf; -@@ -537,21 +572,24 @@ static char *string(char *buf, char *end - return buf; - } - --static char *symbol_string(char *buf, char *end, void *ptr, int field_width, int precision, int flags) -+static char *symbol_string(char *buf, char *end, void *ptr, -+ struct printf_spec spec) - { - unsigned long value = (unsigned long) ptr; - #ifdef CONFIG_KALLSYMS - char sym[KSYM_SYMBOL_LEN]; - sprint_symbol(sym, value); -- return string(buf, end, sym, field_width, precision, flags); -+ return string(buf, end, sym, spec); - #else -- field_width = 2*sizeof(void *); -- flags |= SPECIAL | SMALL | ZEROPAD; -- return number(buf, end, value, 16, field_width, precision, flags); -+ spec.field_width = 2*sizeof(void *); -+ spec.flags |= SPECIAL | SMALL | ZEROPAD; -+ spec.base = 16; -+ return number(buf, end, value, spec); - #endif - } - --static char *resource_string(char *buf, char *end, struct resource *res, int field_width, int precision, int flags) -+static char *resource_string(char *buf, char *end, struct resource *res, -+ struct printf_spec spec) - { - #ifndef IO_RSRC_PRINTK_SIZE - #define IO_RSRC_PRINTK_SIZE 4 -@@ -560,7 +598,11 @@ static char *resource_string(char *buf, - #ifndef MEM_RSRC_PRINTK_SIZE - #define MEM_RSRC_PRINTK_SIZE 8 - #endif -- -+ struct printf_spec num_spec = { -+ .base = 16, -+ .precision = -1, -+ .flags = SPECIAL | SMALL | ZEROPAD, -+ }; - /* room for the actual numbers, the two "0x", -, [, ] and the final zero */ - char sym[4*sizeof(resource_size_t) + 8]; - char *p = sym, *pend = sym + sizeof(sym); -@@ -572,13 +614,73 @@ static char *resource_string(char *buf, - size = MEM_RSRC_PRINTK_SIZE; - - *p++ = '['; -- p = number(p, pend, res->start, 16, size, -1, SPECIAL | SMALL | ZEROPAD); -+ num_spec.field_width = size; -+ p = number(p, pend, res->start, num_spec); - *p++ = '-'; -- p = number(p, pend, res->end, 16, size, -1, SPECIAL | SMALL | ZEROPAD); -+ p = number(p, pend, res->end, num_spec); - *p++ = ']'; - *p = 0; - -- return string(buf, end, sym, field_width, precision, flags); -+ return string(buf, end, sym, spec); -+} -+ -+static char *mac_address_string(char *buf, char *end, u8 *addr, -+ struct printf_spec spec) -+{ -+ char mac_addr[6 * 3]; /* (6 * 2 hex digits), 5 colons and trailing zero */ -+ char *p = mac_addr; -+ int i; -+ -+ for (i = 0; i < 6; i++) { -+ p = pack_hex_byte(p, addr[i]); -+ if (!(spec.flags & SPECIAL) && i != 5) -+ *p++ = ':'; -+ } -+ *p = '\0'; -+ spec.flags &= ~SPECIAL; -+ -+ return string(buf, end, mac_addr, spec); -+} -+ -+static char *ip6_addr_string(char *buf, char *end, u8 *addr, -+ struct printf_spec spec) -+{ -+ char ip6_addr[8 * 5]; /* (8 * 4 hex digits), 7 colons and trailing zero */ -+ char *p = ip6_addr; -+ int i; -+ -+ for (i = 0; i < 8; i++) { -+ p = pack_hex_byte(p, addr[2 * i]); -+ p = pack_hex_byte(p, addr[2 * i + 1]); -+ if (!(spec.flags & SPECIAL) && i != 7) -+ *p++ = ':'; -+ } -+ *p = '\0'; -+ spec.flags &= ~SPECIAL; -+ -+ return string(buf, end, ip6_addr, spec); -+} -+ -+static char *ip4_addr_string(char *buf, char *end, u8 *addr, -+ struct printf_spec spec) -+{ -+ char ip4_addr[4 * 4]; /* (4 * 3 decimal digits), 3 dots and trailing zero */ -+ char temp[3]; /* hold each IP quad in reverse order */ -+ char *p = ip4_addr; -+ int i, digits; -+ -+ for (i = 0; i < 4; i++) { -+ digits = put_dec_trunc(temp, addr[i]) - temp; -+ /* reverse the digits in the quad */ -+ while (digits--) -+ *p++ = temp[digits]; -+ if (i != 3) -+ *p++ = '.'; -+ } -+ *p = '\0'; -+ spec.flags &= ~SPECIAL; -+ -+ return string(buf, end, ip4_addr, spec); - } - - /* -@@ -592,28 +694,244 @@ static char *resource_string(char *buf, - * - 'S' For symbolic direct pointers - * - 'R' For a struct resource pointer, it prints the range of - * addresses (not the name nor the flags) -+ * - 'M' For a 6-byte MAC address, it prints the address in the -+ * usual colon-separated hex notation -+ * - 'I' [46] for IPv4/IPv6 addresses printed in the usual way (dot-separated -+ * decimal for v4 and colon separated network-order 16 bit hex for v6) -+ * - 'i' [46] for 'raw' IPv4/IPv6 addresses, IPv6 omits the colons, IPv4 is -+ * currently the same - * - * Note: The difference between 'S' and 'F' is that on ia64 and ppc64 - * function pointers are really function descriptors, which contain a - * pointer to the real address. - */ --static char *pointer(const char *fmt, char *buf, char *end, void *ptr, int field_width, int precision, int flags) -+static char *pointer(const char *fmt, char *buf, char *end, void *ptr, -+ struct printf_spec spec) - { -+ if (!ptr) -+ return string(buf, end, "(null)", spec); -+ - switch (*fmt) { - case 'F': - ptr = dereference_function_descriptor(ptr); - /* Fallthrough */ - case 'S': -- return symbol_string(buf, end, ptr, field_width, precision, flags); -+ return symbol_string(buf, end, ptr, spec); - case 'R': -- return resource_string(buf, end, ptr, field_width, precision, flags); -+ return resource_string(buf, end, ptr, spec); -+ case 'm': -+ spec.flags |= SPECIAL; -+ /* Fallthrough */ -+ case 'M': -+ return mac_address_string(buf, end, ptr, spec); -+ case 'i': -+ spec.flags |= SPECIAL; -+ /* Fallthrough */ -+ case 'I': -+ if (fmt[1] == '6') -+ return ip6_addr_string(buf, end, ptr, spec); -+ if (fmt[1] == '4') -+ return ip4_addr_string(buf, end, ptr, spec); -+ spec.flags &= ~SPECIAL; -+ break; - } -- flags |= SMALL; -- if (field_width == -1) { -- field_width = 2*sizeof(void *); -- flags |= ZEROPAD; -+ spec.flags |= SMALL; -+ if (spec.field_width == -1) { -+ spec.field_width = 2*sizeof(void *); -+ spec.flags |= ZEROPAD; - } -- return number(buf, end, (unsigned long) ptr, 16, field_width, precision, flags); -+ spec.base = 16; -+ -+ return number(buf, end, (unsigned long) ptr, spec); -+} -+ -+/* -+ * Helper function to decode printf style format. -+ * Each call decode a token from the format and return the -+ * number of characters read (or likely the delta where it wants -+ * to go on the next call). -+ * The decoded token is returned through the parameters -+ * -+ * 'h', 'l', or 'L' for integer fields -+ * 'z' support added 23/7/1999 S.H. -+ * 'z' changed to 'Z' --davidm 1/25/99 -+ * 't' added for ptrdiff_t -+ * -+ * @fmt: the format string -+ * @type of the token returned -+ * @flags: various flags such as +, -, # tokens.. -+ * @field_width: overwritten width -+ * @base: base of the number (octal, hex, ...) -+ * @precision: precision of a number -+ * @qualifier: qualifier of a number (long, size_t, ...) -+ */ -+static int format_decode(const char *fmt, struct printf_spec *spec) -+{ -+ const char *start = fmt; -+ -+ /* we finished early by reading the field width */ -+ if (spec->type == FORMAT_TYPE_WIDTH) { -+ if (spec->field_width < 0) { -+ spec->field_width = -spec->field_width; -+ spec->flags |= LEFT; -+ } -+ spec->type = FORMAT_TYPE_NONE; -+ goto precision; -+ } -+ -+ /* we finished early by reading the precision */ -+ if (spec->type == FORMAT_TYPE_PRECISION) { -+ if (spec->precision < 0) -+ spec->precision = 0; -+ -+ spec->type = FORMAT_TYPE_NONE; -+ goto qualifier; -+ } -+ -+ /* By default */ -+ spec->type = FORMAT_TYPE_NONE; -+ -+ for (; *fmt ; ++fmt) { -+ if (*fmt == '%') -+ break; -+ } -+ -+ /* Return the current non-format string */ -+ if (fmt != start || !*fmt) -+ return fmt - start; -+ -+ /* Process flags */ -+ spec->flags = 0; -+ -+ while (1) { /* this also skips first '%' */ -+ bool found = true; -+ -+ ++fmt; -+ -+ switch (*fmt) { -+ case '-': spec->flags |= LEFT; break; -+ case '+': spec->flags |= PLUS; break; -+ case ' ': spec->flags |= SPACE; break; -+ case '#': spec->flags |= SPECIAL; break; -+ case '0': spec->flags |= ZEROPAD; break; -+ default: found = false; -+ } -+ -+ if (!found) -+ break; -+ } -+ -+ /* get field width */ -+ spec->field_width = -1; -+ -+ if (isdigit(*fmt)) -+ spec->field_width = skip_atoi(&fmt); -+ else if (*fmt == '*') { -+ /* it's the next argument */ -+ spec->type = FORMAT_TYPE_WIDTH; -+ return ++fmt - start; -+ } -+ -+precision: -+ /* get the precision */ -+ spec->precision = -1; -+ if (*fmt == '.') { -+ ++fmt; -+ if (isdigit(*fmt)) { -+ spec->precision = skip_atoi(&fmt); -+ if (spec->precision < 0) -+ spec->precision = 0; -+ } else if (*fmt == '*') { -+ /* it's the next argument */ -+ spec->type = FORMAT_TYPE_PRECISION; -+ return ++fmt - start; -+ } -+ } -+ -+qualifier: -+ /* get the conversion qualifier */ -+ spec->qualifier = -1; -+ if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' || -+ *fmt == 'Z' || *fmt == 'z' || *fmt == 't') { -+ spec->qualifier = *fmt; -+ ++fmt; -+ if (spec->qualifier == 'l' && *fmt == 'l') { -+ spec->qualifier = 'L'; -+ ++fmt; -+ } -+ } -+ -+ /* default base */ -+ spec->base = 10; -+ switch (*fmt) { -+ case 'c': -+ spec->type = FORMAT_TYPE_CHAR; -+ return ++fmt - start; -+ -+ case 's': -+ spec->type = FORMAT_TYPE_STR; -+ return ++fmt - start; -+ -+ case 'p': -+ spec->type = FORMAT_TYPE_PTR; -+ return fmt - start; -+ /* skip alnum */ -+ -+ case 'n': -+ spec->type = FORMAT_TYPE_NRCHARS; -+ return ++fmt - start; -+ -+ case '%': -+ spec->type = FORMAT_TYPE_PERCENT_CHAR; -+ return ++fmt - start; -+ -+ /* integer number formats - set up the flags and "break" */ -+ case 'o': -+ spec->base = 8; -+ break; -+ -+ case 'x': -+ spec->flags |= SMALL; -+ -+ case 'X': -+ spec->base = 16; -+ break; -+ -+ case 'd': -+ case 'i': -+ spec->flags |= SIGN; -+ case 'u': -+ break; -+ -+ default: -+ spec->type = FORMAT_TYPE_INVALID; -+ return fmt - start; -+ } -+ -+ if (spec->qualifier == 'L') -+ spec->type = FORMAT_TYPE_LONG_LONG; -+ else if (spec->qualifier == 'l') { -+ if (spec->flags & SIGN) -+ spec->type = FORMAT_TYPE_LONG; -+ else -+ spec->type = FORMAT_TYPE_ULONG; -+ } else if (spec->qualifier == 'Z' || spec->qualifier == 'z') { -+ spec->type = FORMAT_TYPE_SIZE_T; -+ } else if (spec->qualifier == 't') { -+ spec->type = FORMAT_TYPE_PTRDIFF; -+ } else if (spec->qualifier == 'h') { -+ if (spec->flags & SIGN) -+ spec->type = FORMAT_TYPE_SHORT; -+ else -+ spec->type = FORMAT_TYPE_USHORT; -+ } else { -+ if (spec->flags & SIGN) -+ spec->type = FORMAT_TYPE_INT; -+ else -+ spec->type = FORMAT_TYPE_UINT; -+ } -+ -+ return ++fmt - start; - } - - /** -@@ -642,18 +960,9 @@ static char *pointer(const char *fmt, ch - int vsnprintf(char *buf, size_t size, const char *fmt, va_list args) - { - unsigned long long num; -- int base; - char *str, *end, c; -- -- int flags; /* flags to number() */ -- -- int field_width; /* width of output field */ -- int precision; /* min. # of digits for integers; max -- number of chars for from string */ -- int qualifier; /* 'h', 'l', or 'L' for integer fields */ -- /* 'z' support added 23/7/1999 S.H. */ -- /* 'z' changed to 'Z' --davidm 1/25/99 */ -- /* 't' added for ptrdiff_t */ -+ int read; -+ struct printf_spec spec = {0}; - - /* Reject out-of-range values early. Large positive sizes are - used for unknown buffer sizes. */ -@@ -674,184 +983,137 @@ int vsnprintf(char *buf, size_t size, co - size = end - buf; - } - -- for (; *fmt ; ++fmt) { -- if (*fmt != '%') { -- if (str < end) -- *str = *fmt; -- ++str; -- continue; -- } -+ while (*fmt) { -+ const char *old_fmt = fmt; - -- /* process flags */ -- flags = 0; -- repeat: -- ++fmt; /* this also skips first '%' */ -- switch (*fmt) { -- case '-': flags |= LEFT; goto repeat; -- case '+': flags |= PLUS; goto repeat; -- case ' ': flags |= SPACE; goto repeat; -- case '#': flags |= SPECIAL; goto repeat; -- case '0': flags |= ZEROPAD; goto repeat; -- } -+ read = format_decode(fmt, &spec); - -- /* get field width */ -- field_width = -1; -- if (isdigit(*fmt)) -- field_width = skip_atoi(&fmt); -- else if (*fmt == '*') { -- ++fmt; -- /* it's the next argument */ -- field_width = va_arg(args, int); -- if (field_width < 0) { -- field_width = -field_width; -- flags |= LEFT; -- } -- } -+ fmt += read; - -- /* get the precision */ -- precision = -1; -- if (*fmt == '.') { -- ++fmt; -- if (isdigit(*fmt)) -- precision = skip_atoi(&fmt); -- else if (*fmt == '*') { -- ++fmt; -- /* it's the next argument */ -- precision = va_arg(args, int); -+ switch (spec.type) { -+ case FORMAT_TYPE_NONE: { -+ int copy = read; -+ if (str < end) { -+ if (copy > end - str) -+ copy = end - str; -+ memcpy(str, old_fmt, copy); - } -- if (precision < 0) -- precision = 0; -+ str += read; -+ break; - } - -- /* get the conversion qualifier */ -- qualifier = -1; -- if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' || -- *fmt =='Z' || *fmt == 'z' || *fmt == 't') { -- qualifier = *fmt; -- ++fmt; -- if (qualifier == 'l' && *fmt == 'l') { -- qualifier = 'L'; -- ++fmt; -- } -- } -+ case FORMAT_TYPE_WIDTH: -+ spec.field_width = va_arg(args, int); -+ break; - -- /* default base */ -- base = 10; -+ case FORMAT_TYPE_PRECISION: -+ spec.precision = va_arg(args, int); -+ break; - -- switch (*fmt) { -- case 'c': -- if (!(flags & LEFT)) { -- while (--field_width > 0) { -- if (str < end) -- *str = ' '; -- ++str; -- } -- } -- c = (unsigned char) va_arg(args, int); -- if (str < end) -- *str = c; -- ++str; -- while (--field_width > 0) { -+ case FORMAT_TYPE_CHAR: -+ if (!(spec.flags & LEFT)) { -+ while (--spec.field_width > 0) { - if (str < end) - *str = ' '; - ++str; -- } -- continue; -- -- case 's': -- str = string(str, end, va_arg(args, char *), field_width, precision, flags); -- continue; -- -- case 'p': -- str = pointer(fmt+1, str, end, -- va_arg(args, void *), -- field_width, precision, flags); -- /* Skip all alphanumeric pointer suffixes */ -- while (isalnum(fmt[1])) -- fmt++; -- continue; - -- case 'n': -- /* FIXME: -- * What does C99 say about the overflow case here? */ -- if (qualifier == 'l') { -- long * ip = va_arg(args, long *); -- *ip = (str - buf); -- } else if (qualifier == 'Z' || qualifier == 'z') { -- size_t * ip = va_arg(args, size_t *); -- *ip = (str - buf); -- } else { -- int * ip = va_arg(args, int *); -- *ip = (str - buf); - } -- continue; -- -- case '%': -+ } -+ c = (unsigned char) va_arg(args, int); -+ if (str < end) -+ *str = c; -+ ++str; -+ while (--spec.field_width > 0) { - if (str < end) -- *str = '%'; -+ *str = ' '; - ++str; -- continue; -+ } -+ break; - -- /* integer number formats - set up the flags and "break" */ -- case 'o': -- base = 8; -- break; -+ case FORMAT_TYPE_STR: -+ str = string(str, end, va_arg(args, char *), spec); -+ break; - -- case 'x': -- flags |= SMALL; -- case 'X': -- base = 16; -- break; -+ case FORMAT_TYPE_PTR: -+ str = pointer(fmt+1, str, end, va_arg(args, void *), -+ spec); -+ while (isalnum(*fmt)) -+ fmt++; -+ break; - -- case 'd': -- case 'i': -- flags |= SIGN; -- case 'u': -- break; -+ case FORMAT_TYPE_PERCENT_CHAR: -+ if (str < end) -+ *str = '%'; -+ ++str; -+ break; - -- default: -- if (str < end) -- *str = '%'; -- ++str; -- if (*fmt) { -- if (str < end) -- *str = *fmt; -- ++str; -- } else { -- --fmt; -- } -- continue; -+ case FORMAT_TYPE_INVALID: -+ if (str < end) -+ *str = '%'; -+ ++str; -+ break; -+ -+ case FORMAT_TYPE_NRCHARS: { -+ int qualifier = spec.qualifier; -+ -+ if (qualifier == 'l') { -+ long *ip = va_arg(args, long *); -+ *ip = (str - buf); -+ } else if (qualifier == 'Z' || -+ qualifier == 'z') { -+ size_t *ip = va_arg(args, size_t *); -+ *ip = (str - buf); -+ } else { -+ int *ip = va_arg(args, int *); -+ *ip = (str - buf); -+ } -+ break; - } -- if (qualifier == 'L') -- num = va_arg(args, long long); -- else if (qualifier == 'l') { -- num = va_arg(args, unsigned long); -- if (flags & SIGN) -- num = (signed long) num; -- } else if (qualifier == 'Z' || qualifier == 'z') { -- num = va_arg(args, size_t); -- } else if (qualifier == 't') { -- num = va_arg(args, ptrdiff_t); -- } else if (qualifier == 'h') { -- num = (unsigned short) va_arg(args, int); -- if (flags & SIGN) -- num = (signed short) num; -- } else { -- num = va_arg(args, unsigned int); -- if (flags & SIGN) -- num = (signed int) num; -+ -+ default: -+ switch (spec.type) { -+ case FORMAT_TYPE_LONG_LONG: -+ num = va_arg(args, long long); -+ break; -+ case FORMAT_TYPE_ULONG: -+ num = va_arg(args, unsigned long); -+ break; -+ case FORMAT_TYPE_LONG: -+ num = va_arg(args, long); -+ break; -+ case FORMAT_TYPE_SIZE_T: -+ num = va_arg(args, size_t); -+ break; -+ case FORMAT_TYPE_PTRDIFF: -+ num = va_arg(args, ptrdiff_t); -+ break; -+ case FORMAT_TYPE_USHORT: -+ num = (unsigned short) va_arg(args, int); -+ break; -+ case FORMAT_TYPE_SHORT: -+ num = (short) va_arg(args, int); -+ break; -+ case FORMAT_TYPE_INT: -+ num = (int) va_arg(args, int); -+ break; -+ default: -+ num = va_arg(args, unsigned int); -+ } -+ -+ str = number(str, end, num, spec); - } -- str = number(str, end, num, base, -- field_width, precision, flags); - } -+ - if (size > 0) { - if (str < end) - *str = '\0'; - else - end[-1] = '\0'; - } -+ - /* the trailing null byte doesn't count towards the total */ - return str-buf; -+ - } - EXPORT_SYMBOL(vsnprintf); - diff --git a/target/linux/generic-2.6/patches-2.6.28/985-cris-headers.patch b/target/linux/generic-2.6/patches-2.6.28/985-cris-headers.patch deleted file mode 100644 index 73ede933b..000000000 --- a/target/linux/generic-2.6/patches-2.6.28/985-cris-headers.patch +++ /dev/null @@ -1,27 +0,0 @@ ---- a/arch/cris/include/arch-v10/arch/Kbuild -+++ b/arch/cris/include/arch-v10/arch/Kbuild -@@ -1,3 +1,5 @@ -+header-y += elf.h -+header-y += ptrace.h - header-y += user.h - header-y += svinto.h - header-y += sv_addr_ag.h ---- a/arch/cris/include/asm/Kbuild -+++ b/arch/cris/include/asm/Kbuild -@@ -1,11 +1,14 @@ - include include/asm-generic/Kbuild.asm - --header-y += arch-v10/ --header-y += arch-v32/ -+header-y += ../arch-v10/arch/ -+header-y += ../arch-v32/arch/ - -+header-y += elf.h - header-y += ethernet.h -+header-y += page.h - header-y += rtc.h - header-y += sync_serial.h -+header-y += user.h - - unifdef-y += etraxgpio.h - unifdef-y += rs485.h diff --git a/target/linux/generic-2.6/patches-2.6.28/999-use_preinit_as_init.patch b/target/linux/generic-2.6/patches-2.6.28/999-use_preinit_as_init.patch deleted file mode 100644 index ab104032f..000000000 --- a/target/linux/generic-2.6/patches-2.6.28/999-use_preinit_as_init.patch +++ /dev/null @@ -1,14 +0,0 @@ ---- a/init/main.c -+++ b/init/main.c -@@ -825,10 +825,7 @@ static int noinline init_post(void) - printk(KERN_WARNING "Failed to execute %s. Attempting " - "defaults...\n", execute_command); - } -- run_init_process("/sbin/init"); -- run_init_process("/etc/init"); -- run_init_process("/bin/init"); -- run_init_process("/bin/sh"); -+ run_init_process("/etc/preinit"); - - panic("No init found. Try passing init= option to kernel."); - } diff --git a/target/linux/generic-2.6/patches-2.6.30/015-arm_export___cpu_flush_dcache_page.patch b/target/linux/generic-2.6/patches-2.6.30/015-arm_export___cpu_flush_dcache_page.patch index 5b43c87a8..d778a1f7f 100644 --- a/target/linux/generic-2.6/patches-2.6.30/015-arm_export___cpu_flush_dcache_page.patch +++ b/target/linux/generic-2.6/patches-2.6.30/015-arm_export___cpu_flush_dcache_page.patch @@ -16,8 +16,6 @@ Signed-off-by: Russell King arch/arm/mm/proc-syms.c | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) -diff --git a/arch/arm/mm/proc-syms.c b/arch/arm/mm/proc-syms.c -index 195e48e..ac5c800 100644 --- a/arch/arm/mm/proc-syms.c +++ b/arch/arm/mm/proc-syms.c @@ -27,6 +27,7 @@ EXPORT_SYMBOL(__cpuc_flush_kern_all); @@ -28,6 +26,3 @@ index 195e48e..ac5c800 100644 EXPORT_SYMBOL(dmac_inv_range); /* because of flush_ioremap_region() */ #else EXPORT_SYMBOL(cpu_cache); --- -1.6.5.1 - diff --git a/target/linux/generic-2.6/patches-2.6.30/020-mips_multi_machine_support.patch b/target/linux/generic-2.6/patches-2.6.30/020-mips_multi_machine_support.patch index 57dcc1dc4..2c53f03e8 100644 --- a/target/linux/generic-2.6/patches-2.6.30/020-mips_multi_machine_support.patch +++ b/target/linux/generic-2.6/patches-2.6.30/020-mips_multi_machine_support.patch @@ -1,6 +1,6 @@ --- /dev/null +++ b/include/asm-mips/mips_machine.h -@@ -0,0 +1,46 @@ +@@ -0,0 +1,47 @@ +/* + * Copyright (C) 2008-2009 Gabor Juhos + * @@ -25,6 +25,7 @@ + +void mips_machine_register(struct mips_machine *) __init; +void mips_machine_setup(unsigned long machtype) __init; ++void mips_machine_set_name(char *name) __init; + +extern char *mips_machine_name; + @@ -49,7 +50,7 @@ + --- /dev/null +++ b/arch/mips/kernel/mips_machine.c -@@ -0,0 +1,70 @@ +@@ -0,0 +1,74 @@ +/* + * Copyright (C) 2008-2009 Gabor Juhos + * @@ -88,6 +89,25 @@ + list_add_tail(&mach->list, &mips_machines); +} + ++void __init mips_machine_set_name(char *name) ++{ ++ unsigned int len; ++ char *p; ++ ++ if (name == NULL) ++ return; ++ ++ len = strlen(name); ++ p = kmalloc(len + 1, GFP_KERNEL); ++ if (p) { ++ strncpy(p, name, len); ++ p[len] = '\0'; ++ mips_machine_name = p; ++ } else { ++ printk(KERN_WARNING "MIPS: no memory for machine_name\n"); ++ } ++} ++ +void __init mips_machine_setup(unsigned long machtype) +{ + struct mips_machine *mach; @@ -99,27 +119,12 @@ + return; + } + -+ if (mach->mach_name) { -+ char *name; -+ unsigned int len; -+ -+ len = strlen(mach->mach_name); -+ name = kmalloc(len + 1, GFP_KERNEL); -+ if (name) { -+ strncpy(name, mach->mach_name,len); -+ name[len] = '\0'; -+ mips_machine_name = name; -+ } else { -+ printk(KERN_WARNING "MIPS: no memory for machine_name\n"); -+ } -+ } -+ ++ mips_machine_set_name(mach->mach_name); + 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 diff --git a/target/linux/generic-2.6/patches-2.6.30/022-mips_use_generic_thread_info_allocator.patch b/target/linux/generic-2.6/patches-2.6.30/022-mips_use_generic_thread_info_allocator.patch new file mode 100644 index 000000000..80c34046a --- /dev/null +++ b/target/linux/generic-2.6/patches-2.6.30/022-mips_use_generic_thread_info_allocator.patch @@ -0,0 +1,18 @@ +--- a/arch/mips/include/asm/thread_info.h ++++ b/arch/mips/include/asm/thread_info.h +@@ -85,6 +85,7 @@ register struct thread_info *__current_t + #define THREAD_SIZE (PAGE_SIZE << THREAD_SIZE_ORDER) + #define THREAD_MASK (THREAD_SIZE - 1UL) + ++#if 0 + #define __HAVE_ARCH_THREAD_INFO_ALLOCATOR + + #ifdef CONFIG_DEBUG_STACK_USAGE +@@ -101,6 +102,7 @@ register struct thread_info *__current_t + #endif + + #define free_thread_info(info) kfree(info) ++#endif + + #endif /* !__ASSEMBLY__ */ + diff --git a/target/linux/generic-2.6/patches-2.6.30/027-mips_module_reloc.patch b/target/linux/generic-2.6/patches-2.6.30/027-mips_module_reloc.patch index ca8766267..019489f94 100644 --- a/target/linux/generic-2.6/patches-2.6.30/027-mips_module_reloc.patch +++ b/target/linux/generic-2.6/patches-2.6.30/027-mips_module_reloc.patch @@ -16,10 +16,10 @@ const struct exception_table_entry *dbe_start; const struct exception_table_entry *dbe_end; + -+ void *plt_tbl; -+ unsigned int core_plt_offset; -+ unsigned int core_plt_size; -+ unsigned int init_plt_offset; ++ void *phys_plt_tbl; ++ void *virt_plt_tbl; ++ unsigned int phys_plt_offset; ++ unsigned int virt_plt_offset; }; typedef uint8_t Elf64_Byte; /* Type for a 8-bit quantity. */ @@ -142,7 +142,7 @@ void *module_alloc(unsigned long size) { #ifdef MODULE_START -@@ -58,16 +168,45 @@ void *module_alloc(unsigned long size) +@@ -58,23 +168,101 @@ void *module_alloc(unsigned long size) return __vmalloc_area(area, GFP_KERNEL, PAGE_KERNEL); #else @@ -190,7 +190,26 @@ /* FIXME: If module_region == mod->init_region, trim exception table entries. */ } -@@ -75,6 +214,24 @@ void module_free(struct module *mod, voi + ++static void *__module_alloc(int size, bool phys) ++{ ++ void *ptr; ++ ++ if (phys) ++ ptr = kmalloc(size, GFP_KERNEL); ++ else ++ ptr = vmalloc(size); ++ return ptr; ++} ++ ++static void __module_free(void *ptr) ++{ ++ if (is_phys_addr(ptr)) ++ kfree(ptr); ++ else ++ vfree(ptr); ++} ++ int module_frob_arch_sections(Elf_Ehdr *hdr, Elf_Shdr *sechdrs, char *secstrings, struct module *mod) { @@ -205,17 +224,29 @@ + core_size = get_plt_size(hdr, sechdrs, secstrings, symindex, false); + init_size = get_plt_size(hdr, sechdrs, secstrings, symindex, true); + -+ mod->arch.core_plt_offset = 0; -+ mod->arch.core_plt_size = core_size; -+ mod->arch.init_plt_offset = core_size; -+ mod->arch.plt_tbl = kmalloc(core_size + init_size, GFP_KERNEL); -+ if (!mod->arch.plt_tbl) ++ mod->arch.phys_plt_offset = 0; ++ mod->arch.virt_plt_offset = 0; ++ mod->arch.phys_plt_tbl = NULL; ++ mod->arch.virt_plt_tbl = NULL; ++ ++ if ((core_size + init_size) == 0) ++ return 0; ++ ++ mod->arch.phys_plt_tbl = __module_alloc(core_size + init_size, 1); ++ if (!mod->arch.phys_plt_tbl) + return -ENOMEM; ++ ++ mod->arch.virt_plt_tbl = __module_alloc(core_size + init_size, 0); ++ if (!mod->arch.virt_plt_tbl) { ++ __module_free(mod->arch.phys_plt_tbl); ++ mod->arch.phys_plt_tbl = NULL; ++ return -ENOMEM; ++ } + return 0; } -@@ -97,27 +254,41 @@ static int apply_r_mips_32_rela(struct m +@@ -97,27 +285,37 @@ static int apply_r_mips_32_rela(struct m return 0; } @@ -236,42 +267,39 @@ - return -ENOEXEC; - } + *plt_offset += 4 * sizeof(int); -+ + +- *location = (*location & ~0x03ffffff) | +- ((*location + (v >> 2)) & 0x03ffffff); + /* adjust carry for addiu */ + if (v & 0x00008000) + v += 0x10000; -+ + +- return 0; + tramp[0] = 0x3c190000 | (v >> 16); /* lui t9, hi16 */ + tramp[1] = 0x27390000 | (v & 0xffff); /* addiu t9, t9, lo16 */ + tramp[2] = 0x03200008; /* jr t9 */ + tramp[3] = 0x00000000; /* nop */ - -- *location = (*location & ~0x03ffffff) | -- ((*location + (v >> 2)) & 0x03ffffff); ++ + return (Elf_Addr) tramp; -+} -+ -+static Elf_Addr add_plt_entry(struct module *me, void *location, Elf_Addr v) -+{ -+ if (location >= me->module_core && -+ location < me->module_core + me->core_size) -+ return add_plt_entry_to(&me->arch.core_plt_offset, -+ me->arch.plt_tbl, v); -+ -+ if (location >= me->module_init && -+ location < me->module_init + me->init_size) -+ return add_plt_entry_to(&me->arch.init_plt_offset, -+ me->arch.plt_tbl, v); - - return 0; } -static int apply_r_mips_26_rela(struct module *me, u32 *location, Elf_Addr v) ++static Elf_Addr add_plt_entry(struct module *me, void *location, Elf_Addr v) ++{ ++ if (is_phys_addr(location)) ++ return add_plt_entry_to(&me->arch.phys_plt_offset, ++ me->arch.phys_plt_tbl, v); ++ else ++ return add_plt_entry_to(&me->arch.virt_plt_offset, ++ me->arch.virt_plt_tbl, v); ++ ++} ++ +static int set_r_mips_26(struct module *me, u32 *location, u32 ofs, Elf_Addr v) { if (v % 4) { printk(KERN_ERR "module %s: dangerous relocation\n", me->name); -@@ -125,17 +296,31 @@ static int apply_r_mips_26_rela(struct m +@@ -125,17 +323,31 @@ static int apply_r_mips_26_rela(struct m } if ((v & 0xf0000000) != (((unsigned long)location + 4) & 0xf0000000)) { @@ -306,18 +334,20 @@ static int apply_r_mips_hi16_rel(struct module *me, u32 *location, Elf_Addr v) { struct mips_hi16 *n; -@@ -400,11 +585,23 @@ int module_finalize(const Elf_Ehdr *hdr, +@@ -400,11 +612,32 @@ int module_finalize(const Elf_Ehdr *hdr, list_add(&me->arch.dbe_list, &dbe_list); spin_unlock_irq(&dbe_lock); } + + /* Get rid of the fixup trampoline if we're running the module + * from physically mapped address space */ -+ if (me->arch.core_plt_offset == 0 && -+ me->arch.init_plt_offset == me->arch.core_plt_size && -+ is_phys_addr(me->module_core)) { -+ kfree(me->arch.plt_tbl); -+ me->arch.plt_tbl = NULL; ++ if (me->arch.phys_plt_offset == 0) { ++ __module_free(me->arch.phys_plt_tbl); ++ me->arch.phys_plt_tbl = NULL; ++ } ++ if (me->arch.virt_plt_offset == 0) { ++ __module_free(me->arch.virt_plt_tbl); ++ me->arch.virt_plt_tbl = NULL; + } + return 0; @@ -325,8 +355,15 @@ void module_arch_cleanup(struct module *mod) { -+ if (mod->arch.plt_tbl) -+ kfree(mod->arch.plt_tbl); ++ if (mod->arch.phys_plt_tbl) { ++ __module_free(mod->arch.phys_plt_tbl); ++ mod->arch.phys_plt_tbl = NULL; ++ } ++ if (mod->arch.virt_plt_tbl) { ++ __module_free(mod->arch.virt_plt_tbl); ++ mod->arch.virt_plt_tbl = NULL; ++ } ++ spin_lock_irq(&dbe_lock); list_del(&mod->arch.dbe_list); spin_unlock_irq(&dbe_lock); diff --git a/target/linux/generic-2.6/patches-2.6.30/200-sched_esfq.patch b/target/linux/generic-2.6/patches-2.6.30/200-sched_esfq.patch index f72c0e370..bf123ce78 100644 --- a/target/linux/generic-2.6/patches-2.6.30/200-sched_esfq.patch +++ b/target/linux/generic-2.6/patches-2.6.30/200-sched_esfq.patch @@ -90,7 +90,7 @@ obj-$(CONFIG_NET_SCH_PRIO) += sch_prio.o --- /dev/null +++ b/net/sched/sch_esfq.c -@@ -0,0 +1,700 @@ +@@ -0,0 +1,702 @@ +/* + * net/sched/sch_esfq.c Extended Stochastic Fairness Queueing discipline. + * @@ -144,7 +144,9 @@ +#include +#include +#include ++#ifdef CONFIG_NET_SCH_ESFQ_NFCT +#include ++#endif + +/* Stochastic Fairness Queuing algorithm. + For more comments look at sch_sfq.c. diff --git a/target/linux/generic-2.6/patches-2.6.30/910-hostap_tx_queue_len_fix.patch b/target/linux/generic-2.6/patches-2.6.30/910-hostap_tx_queue_len_fix.patch new file mode 100644 index 000000000..b421662d9 --- /dev/null +++ b/target/linux/generic-2.6/patches-2.6.30/910-hostap_tx_queue_len_fix.patch @@ -0,0 +1,20 @@ +--- a/drivers/net/wireless/hostap/hostap_main.c ++++ b/drivers/net/wireless/hostap/hostap_main.c +@@ -875,15 +875,16 @@ void hostap_setup_dev(struct net_device + + switch(type) { + case HOSTAP_INTERFACE_AP: ++ dev->tx_queue_len = 0; /* use main radio device queue */ + dev->netdev_ops = &hostap_mgmt_netdev_ops; + dev->type = ARPHRD_IEEE80211; + dev->header_ops = &hostap_80211_ops; + break; + case HOSTAP_INTERFACE_MASTER: +- dev->tx_queue_len = 0; /* use main radio device queue */ + dev->netdev_ops = &hostap_master_ops; + break; + default: ++ dev->tx_queue_len = 0; /* use main radio device queue */ + dev->netdev_ops = &hostap_netdev_ops; + } + diff --git a/target/linux/generic-2.6/patches-2.6.31/020-mips_multi_machine_support.patch b/target/linux/generic-2.6/patches-2.6.31/020-mips_multi_machine_support.patch index 5c70b548a..9c41c3c16 100644 --- a/target/linux/generic-2.6/patches-2.6.31/020-mips_multi_machine_support.patch +++ b/target/linux/generic-2.6/patches-2.6.31/020-mips_multi_machine_support.patch @@ -1,6 +1,6 @@ --- /dev/null +++ b/include/asm-mips/mips_machine.h -@@ -0,0 +1,46 @@ +@@ -0,0 +1,47 @@ +/* + * Copyright (C) 2008-2009 Gabor Juhos + * @@ -25,6 +25,7 @@ + +void mips_machine_register(struct mips_machine *) __init; +void mips_machine_setup(unsigned long machtype) __init; ++void mips_machine_set_name(char *name) __init; + +extern char *mips_machine_name; + @@ -49,7 +50,7 @@ + --- /dev/null +++ b/arch/mips/kernel/mips_machine.c -@@ -0,0 +1,70 @@ +@@ -0,0 +1,74 @@ +/* + * Copyright (C) 2008-2009 Gabor Juhos + * @@ -88,6 +89,25 @@ + list_add_tail(&mach->list, &mips_machines); +} + ++void __init mips_machine_set_name(char *name) ++{ ++ unsigned int len; ++ char *p; ++ ++ if (name == NULL) ++ return; ++ ++ len = strlen(name); ++ p = kmalloc(len + 1, GFP_KERNEL); ++ if (p) { ++ strncpy(p, name, len); ++ p[len] = '\0'; ++ mips_machine_name = p; ++ } else { ++ printk(KERN_WARNING "MIPS: no memory for machine_name\n"); ++ } ++} ++ +void __init mips_machine_setup(unsigned long machtype) +{ + struct mips_machine *mach; @@ -99,27 +119,12 @@ + return; + } + -+ if (mach->mach_name) { -+ char *name; -+ unsigned int len; -+ -+ len = strlen(mach->mach_name); -+ name = kmalloc(len + 1, GFP_KERNEL); -+ if (name) { -+ strncpy(name, mach->mach_name,len); -+ name[len] = '\0'; -+ mips_machine_name = name; -+ } else { -+ printk(KERN_WARNING "MIPS: no memory for machine_name\n"); -+ } -+ } -+ ++ mips_machine_set_name(mach->mach_name); + 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 @@ -87,6 +87,7 @@ obj-$(CONFIG_GPIO_TXX9) += gpio_txx9.o diff --git a/target/linux/generic-2.6/patches-2.6.31/022-mips_use_generic_thread_info_allocator.patch b/target/linux/generic-2.6/patches-2.6.31/022-mips_use_generic_thread_info_allocator.patch new file mode 100644 index 000000000..737e51bd2 --- /dev/null +++ b/target/linux/generic-2.6/patches-2.6.31/022-mips_use_generic_thread_info_allocator.patch @@ -0,0 +1,18 @@ +--- a/arch/mips/include/asm/thread_info.h ++++ b/arch/mips/include/asm/thread_info.h +@@ -83,6 +83,7 @@ register struct thread_info *__current_t + #define THREAD_SIZE (PAGE_SIZE << THREAD_SIZE_ORDER) + #define THREAD_MASK (THREAD_SIZE - 1UL) + ++#if 0 + #define __HAVE_ARCH_THREAD_INFO_ALLOCATOR + + #ifdef CONFIG_DEBUG_STACK_USAGE +@@ -99,6 +100,7 @@ register struct thread_info *__current_t + #endif + + #define free_thread_info(info) kfree(info) ++#endif + + #endif /* !__ASSEMBLY__ */ + diff --git a/target/linux/generic-2.6/patches-2.6.31/027-mips_module_reloc.patch b/target/linux/generic-2.6/patches-2.6.31/027-mips_module_reloc.patch index f65a09c94..c0dc64e26 100644 --- a/target/linux/generic-2.6/patches-2.6.31/027-mips_module_reloc.patch +++ b/target/linux/generic-2.6/patches-2.6.31/027-mips_module_reloc.patch @@ -16,10 +16,10 @@ const struct exception_table_entry *dbe_start; const struct exception_table_entry *dbe_end; + -+ void *plt_tbl; -+ unsigned int core_plt_offset; -+ unsigned int core_plt_size; -+ unsigned int init_plt_offset; ++ void *phys_plt_tbl; ++ void *virt_plt_tbl; ++ unsigned int phys_plt_offset; ++ unsigned int virt_plt_offset; }; typedef uint8_t Elf64_Byte; /* Type for a 8-bit quantity. */ @@ -143,7 +143,7 @@ void *module_alloc(unsigned long size) { #ifdef MODULE_START -@@ -58,21 +169,68 @@ void *module_alloc(unsigned long size) +@@ -58,21 +169,99 @@ void *module_alloc(unsigned long size) return __vmalloc_area(area, GFP_KERNEL, PAGE_KERNEL); #else @@ -188,6 +188,25 @@ + } else { + vfree(module_region); + } ++} ++ ++static void *__module_alloc(int size, bool phys) ++{ ++ void *ptr; ++ ++ if (phys) ++ ptr = kmalloc(size, GFP_KERNEL); ++ else ++ ptr = vmalloc(size); ++ return ptr; ++} ++ ++static void __module_free(void *ptr) ++{ ++ if (is_phys_addr(ptr)) ++ kfree(ptr); ++ else ++ vfree(ptr); } int module_frob_arch_sections(Elf_Ehdr *hdr, Elf_Shdr *sechdrs, @@ -204,17 +223,29 @@ + core_size = get_plt_size(hdr, sechdrs, secstrings, symindex, false); + init_size = get_plt_size(hdr, sechdrs, secstrings, symindex, true); + -+ mod->arch.core_plt_offset = 0; -+ mod->arch.core_plt_size = core_size; -+ mod->arch.init_plt_offset = core_size; -+ mod->arch.plt_tbl = kmalloc(core_size + init_size, GFP_KERNEL); -+ if (!mod->arch.plt_tbl) ++ mod->arch.phys_plt_offset = 0; ++ mod->arch.virt_plt_offset = 0; ++ mod->arch.phys_plt_tbl = NULL; ++ mod->arch.virt_plt_tbl = NULL; ++ ++ if ((core_size + init_size) == 0) ++ return 0; ++ ++ mod->arch.phys_plt_tbl = __module_alloc(core_size + init_size, 1); ++ if (!mod->arch.phys_plt_tbl) + return -ENOMEM; ++ ++ mod->arch.virt_plt_tbl = __module_alloc(core_size + init_size, 0); ++ if (!mod->arch.virt_plt_tbl) { ++ __module_free(mod->arch.phys_plt_tbl); ++ mod->arch.phys_plt_tbl = NULL; ++ return -ENOMEM; ++ } + return 0; } -@@ -95,28 +253,40 @@ static int apply_r_mips_32_rela(struct m +@@ -95,28 +284,36 @@ static int apply_r_mips_32_rela(struct m return 0; } @@ -239,38 +270,35 @@ + /* adjust carry for addiu */ + if (v & 0x00008000) + v += 0x10000; -+ + +- *location = (*location & ~0x03ffffff) | +- ((*location + (v >> 2)) & 0x03ffffff); + tramp[0] = 0x3c190000 | (v >> 16); /* lui t9, hi16 */ + tramp[1] = 0x27390000 | (v & 0xffff); /* addiu t9, t9, lo16 */ + tramp[2] = 0x03200008; /* jr t9 */ + tramp[3] = 0x00000000; /* nop */ -- *location = (*location & ~0x03ffffff) | -- ((*location + (v >> 2)) & 0x03ffffff); +- return 0; + return (Elf_Addr) tramp; -+} -+ -+static Elf_Addr add_plt_entry(struct module *me, void *location, Elf_Addr v) -+{ -+ if (location >= me->module_core && -+ location < me->module_core + me->core_size) -+ return add_plt_entry_to(&me->arch.core_plt_offset, -+ me->arch.plt_tbl, v); -+ -+ if (location >= me->module_init && -+ location < me->module_init + me->init_size) -+ return add_plt_entry_to(&me->arch.init_plt_offset, -+ me->arch.plt_tbl, v); - - return 0; } -static int apply_r_mips_26_rela(struct module *me, u32 *location, Elf_Addr v) ++static Elf_Addr add_plt_entry(struct module *me, void *location, Elf_Addr v) ++{ ++ if (is_phys_addr(location)) ++ return add_plt_entry_to(&me->arch.phys_plt_offset, ++ me->arch.phys_plt_tbl, v); ++ else ++ return add_plt_entry_to(&me->arch.virt_plt_offset, ++ me->arch.virt_plt_tbl, v); ++ ++} ++ +static int set_r_mips_26(struct module *me, u32 *location, u32 ofs, Elf_Addr v) { if (v % 4) { pr_err("module %s: dangerous R_MIPS_26 RELArelocation\n", -@@ -125,17 +295,31 @@ static int apply_r_mips_26_rela(struct m +@@ -125,17 +322,31 @@ static int apply_r_mips_26_rela(struct m } if ((v & 0xf0000000) != (((unsigned long)location + 4) & 0xf0000000)) { @@ -305,18 +333,20 @@ static int apply_r_mips_hi16_rel(struct module *me, u32 *location, Elf_Addr v) { struct mips_hi16 *n; -@@ -400,11 +584,23 @@ int module_finalize(const Elf_Ehdr *hdr, +@@ -400,11 +611,32 @@ int module_finalize(const Elf_Ehdr *hdr, list_add(&me->arch.dbe_list, &dbe_list); spin_unlock_irq(&dbe_lock); } + + /* Get rid of the fixup trampoline if we're running the module + * from physically mapped address space */ -+ if (me->arch.core_plt_offset == 0 && -+ me->arch.init_plt_offset == me->arch.core_plt_size && -+ is_phys_addr(me->module_core)) { -+ kfree(me->arch.plt_tbl); -+ me->arch.plt_tbl = NULL; ++ if (me->arch.phys_plt_offset == 0) { ++ __module_free(me->arch.phys_plt_tbl); ++ me->arch.phys_plt_tbl = NULL; ++ } ++ if (me->arch.virt_plt_offset == 0) { ++ __module_free(me->arch.virt_plt_tbl); ++ me->arch.virt_plt_tbl = NULL; + } + return 0; @@ -324,8 +354,15 @@ void module_arch_cleanup(struct module *mod) { -+ if (mod->arch.plt_tbl) -+ kfree(mod->arch.plt_tbl); ++ if (mod->arch.phys_plt_tbl) { ++ __module_free(mod->arch.phys_plt_tbl); ++ mod->arch.phys_plt_tbl = NULL; ++ } ++ if (mod->arch.virt_plt_tbl) { ++ __module_free(mod->arch.virt_plt_tbl); ++ mod->arch.virt_plt_tbl = NULL; ++ } ++ spin_lock_irq(&dbe_lock); list_del(&mod->arch.dbe_list); spin_unlock_irq(&dbe_lock); diff --git a/target/linux/generic-2.6/patches-2.6.31/150-netfilter_imq.patch b/target/linux/generic-2.6/patches-2.6.31/150-netfilter_imq.patch index 70c80c81d..026e9bdee 100644 --- a/target/linux/generic-2.6/patches-2.6.31/150-netfilter_imq.patch +++ b/target/linux/generic-2.6/patches-2.6.31/150-netfilter_imq.patch @@ -811,7 +811,7 @@ extern void kfree_skb(struct sk_buff *skb); extern void consume_skb(struct sk_buff *skb); extern void __kfree_skb(struct sk_buff *skb); -@@ -1974,6 +1992,10 @@ static inline void __nf_copy(struct sk_b +@@ -1976,6 +1994,10 @@ static inline void __nf_copy(struct sk_b dst->nfct_reasm = src->nfct_reasm; nf_conntrack_get_reasm(src->nfct_reasm); #endif @@ -834,7 +834,7 @@ #include #include #include -@@ -1686,7 +1689,11 @@ int dev_hard_start_xmit(struct sk_buff * +@@ -1687,7 +1690,11 @@ int dev_hard_start_xmit(struct sk_buff * int rc; if (likely(!skb->next)) { @@ -847,7 +847,7 @@ dev_queue_xmit_nit(skb, dev); if (netif_needs_gso(dev, skb)) { -@@ -1771,8 +1778,7 @@ u16 skb_tx_hash(const struct net_device +@@ -1772,8 +1779,7 @@ u16 skb_tx_hash(const struct net_device } EXPORT_SYMBOL(skb_tx_hash); @@ -857,7 +857,7 @@ { const struct net_device_ops *ops = dev->netdev_ops; u16 queue_index = 0; -@@ -1785,6 +1791,7 @@ static struct netdev_queue *dev_pick_tx( +@@ -1786,6 +1792,7 @@ static struct netdev_queue *dev_pick_tx( skb_set_queue_mapping(skb, queue_index); return netdev_get_tx_queue(dev, queue_index); } @@ -1033,7 +1033,7 @@ new->csum = old->csum; new->local_df = old->local_df; new->pkt_type = old->pkt_type; -@@ -2778,6 +2867,13 @@ void __init skb_init(void) +@@ -2779,6 +2868,13 @@ void __init skb_init(void) 0, SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL); diff --git a/target/linux/generic-2.6/patches-2.6.31/200-sched_esfq.patch b/target/linux/generic-2.6/patches-2.6.31/200-sched_esfq.patch index fb28e9085..f3636e652 100644 --- a/target/linux/generic-2.6/patches-2.6.31/200-sched_esfq.patch +++ b/target/linux/generic-2.6/patches-2.6.31/200-sched_esfq.patch @@ -90,7 +90,7 @@ obj-$(CONFIG_NET_SCH_PRIO) += sch_prio.o --- /dev/null +++ b/net/sched/sch_esfq.c -@@ -0,0 +1,700 @@ +@@ -0,0 +1,702 @@ +/* + * net/sched/sch_esfq.c Extended Stochastic Fairness Queueing discipline. + * @@ -144,7 +144,9 @@ +#include +#include +#include ++#ifdef CONFIG_NET_SCH_ESFQ_NFCT +#include ++#endif + +/* Stochastic Fairness Queuing algorithm. + For more comments look at sch_sfq.c. diff --git a/target/linux/generic-2.6/patches-2.6.31/230-union_mounts.patch b/target/linux/generic-2.6/patches-2.6.31/230-union_mounts.patch deleted file mode 100644 index b26d5fae8..000000000 --- a/target/linux/generic-2.6/patches-2.6.31/230-union_mounts.patch +++ /dev/null @@ -1,5203 +0,0 @@ ---- /dev/null -+++ b/Documentation/filesystems/union-mounts.txt -@@ -0,0 +1,187 @@ -+VFS based Union Mounts -+---------------------- -+ -+ 1. What are "Union Mounts" -+ 2. The Union Stack -+ 3. Whiteouts, Opaque Directories, and Fallthrus -+ 4. Copy-up -+ 5. Directory Reading -+ 6. Known Problems -+ 7. References -+ -+------------------------------------------------------------------------------- -+ -+1. What are "Union Mounts" -+========================== -+ -+Please note: this is NOT about UnionFS and it is NOT derived work! -+ -+Traditionally the mount operation is opaque, which means that the content of -+the mount point, the directory where the file system is mounted on, is hidden -+by the content of the mounted file system's root directory until the file -+system is unmounted again. Unlike the traditional UNIX mount mechanism, that -+hides the contents of the mount point, a union mount presents a view as if -+both filesystems are merged together. Although only the topmost layer of the -+mount stack can be altered, it appears as if transparent file system mounts -+allow any file to be created, modified or deleted. -+ -+Most people know the concepts and features of union mounts from other -+operating systems like Sun's Translucent Filesystem, Plan9 or BSD. For an -+in-depth review of union mounts and other unioning file systems, see: -+ -+http://lwn.net/Articles/324291/ -+http://lwn.net/Articles/325369/ -+http://lwn.net/Articles/327738/ -+ -+Here are the key features of this implementation: -+- completely VFS based -+- does not change the namespace stacking -+- directory listings have duplicate entries removed in the kernel -+- writable unions: only the topmost file system layer may be writable -+- writable unions: new whiteout filetype handled inside the kernel -+ -+------------------------------------------------------------------------------- -+ -+2. The Union Stack -+================== -+ -+The mounted file systems are organized in the "file system hierarchy" (tree of -+vfsmount structures), which keeps track about the stacking of file systems -+upon each other. The per-directory view on the file system hierarchy is called -+"mount stack" and reflects the order of file systems, which are mounted on a -+specific directory. -+ -+Union mounts present a single unified view of the contents of two or more file -+systems as if they are merged together. Since the information which file -+system objects are part of a unified view is not directly available from the -+file system hierarchy there is a need for a new structure. The file system -+objects, which are part of a unified view are ordered in a so-called "union -+stack". Only directories can be part of a unified view. -+ -+The link between two layers of the union stack is maintained using the -+union_mount structure (#include ): -+ -+struct union_mount { -+ atomic_t u_count; /* reference count */ -+ struct mutex u_mutex; -+ struct list_head u_unions; /* list head for d_unions */ -+ struct hlist_node u_hash; /* list head for searching */ -+ struct hlist_node u_rhash; /* list head for reverse searching */ -+ -+ struct path u_this; /* this is me */ -+ struct path u_next; /* this is what I overlay */ -+}; -+ -+The union_mount structure holds a reference (dget,mntget) to the next lower -+layer of the union stack. Since a dentry can be part of multiple unions -+(e.g. with bind mounts) they are tied together via the d_unions field of the -+dentry structure. -+ -+All union_mount structures are cached in two hash tables, one for lookups of -+the next lower layer of the union stack and one for reverse lookups of the -+next upper layer of the union stack. The reverse lookup is necessary to -+resolve CWD relative path lookups. For calculation of the hash value, the -+(dentry,vfsmount) pair is used. The u_this field is used for the hash table -+which is used in forward lookups and the u_next field for the reverse lookups. -+ -+During every new mount (or mount propagation), a new union_mount structure is -+allocated. A reference to the mountpoint's vfsmount and dentry is taken and -+stored in the u_next field. In almost the same manner an union_mount -+structure is created during the first time lookup of a directory within a -+union mount point. In this case the lookup proceeds to all lower layers of the -+union. Therefore the complete union stack is constructed during lookups. -+ -+The union_mount structures of a dentry are destroyed when the dentry itself is -+destroyed. Therefore the dentry cache is indirectly driving the union_mount -+cache like this is done for inodes too. Please note that lower layer -+union_mount structures are kept in memory until the topmost dentry is -+destroyed. -+ -+------------------------------------------------------------------------------- -+ -+3. Whiteouts, Opaque Directories, and Fallthrus -+=========================================================== -+ -+The whiteout filetype isn't new. It has been there for quite some time now -+but Linux's VFS hasn't used it yet. With the availability of union mount code -+inside the VFS the whiteout filetype is getting important to support writable -+union mounts. For read-only union mounts, support for whiteouts or -+copy-on-open is not necessary. -+ -+The whiteout filetype has the same function as negative dentries: they -+describe a filename which isn't there. The creation of whiteouts needs -+lowlevel filesystem support. At the time of writing this, there is whiteout -+support for tmpfs, ext2 and ext3 available. The VFS is extended to make the -+whiteout handling transparent to all its users. The whiteouts are not -+visible to user-space. -+ -+What happens when we create a directory that was previously whited-out? We -+don't want the directory entries from underlying filesystems to suddenly appear -+in the newly created directory. So we mark the directory opaque (the file -+system must support storage of the opaque flag). -+ -+Fallthrus are directory entries that override the opaque flag on a directory -+for that specific directory entry name (the lookup "falls through" to the next -+layer of the union mount). Fallthrus are mainly useful for implementing -+readdir(). -+ -+------------------------------------------------------------------------------- -+ -+4. Copy-up -+=========== -+ -+Any write to an object on any layer other than the topmost triggers a copy-up -+of the object to the topmost file system. For regular files, the copy-up -+happens when it is opened in writable mode. -+ -+Directories are copied up on open, regardless of intent to write, to simplify -+copy-up of any object located below it in the namespace. Otherwise we have to -+walk the entire pathname to create intermediate directories whenever we do a -+copy-up. This is the same approach as BSD union mounts and uses a negigible -+amount of disk space. Note that the actual directory entries themselves are -+not copied-up from the lower levels until (a) the directory is written to, or -+(b) the first readdir() of the directory (more on that later). -+ -+Rename across different levels of the union is implemented as a copy-up -+operation for regular files. Rename of directories simply returns EXDEV, the -+same as if we tried to rename across different mounts. Most applications have -+to handle this case anyway. Some applications do not expect EXDEV on -+rename operations within the same directory, but these applications will also -+be broken with bind mounts. -+ -+------------------------------------------------------------------------------- -+ -+5. Directory Reading -+==================== -+ -+readdir() is somewhat difficult to implement in a unioning file system. We must -+eliminate duplicates, apply whiteouts, and start up readdir() where we left -+off, given a single f_pos value. Our solution is to copy up all the directory -+entries to the topmost directory the first time readdir() is called on a -+directory. During this copy-up, we skip duplicates and entries covered by -+whiteouts, and then create fallthru entries for each remaining visible dentry. -+Then we mark the whole directory opaque. From then on, we just use the topmost -+file system's normal readdir() operation. -+ -+------------------------------------------------------------------------------- -+ -+6. Known Problems -+================= -+ -+- copyup() for other filetypes that reg and dir (e.g. for chown() on devices) -+- symlinks are untested -+ -+------------------------------------------------------------------------------- -+ -+7. References -+============= -+ -+[1] http://marc.info/?l=linux-fsdevel&m=96035682927821&w=2 -+[2] http://marc.info/?l=linux-fsdevel&m=117681527820133&w=2 -+[3] http://marc.info/?l=linux-fsdevel&m=117913503200362&w=2 -+[4] http://marc.info/?l=linux-fsdevel&m=118231827024394&w=2 -+ -+Authors: -+Jan Blunck -+Bharata B Rao -+Valerie Aurora ---- a/fs/autofs4/autofs_i.h -+++ b/fs/autofs4/autofs_i.h -@@ -130,6 +130,7 @@ struct autofs_sb_info { - int reghost_enabled; - int needs_reghost; - struct super_block *sb; -+ struct vfsmount *mnt; - struct mutex wq_mutex; - spinlock_t fs_lock; - struct autofs_wait_queue *queues; /* Wait queue pointer */ ---- a/fs/autofs4/init.c -+++ b/fs/autofs4/init.c -@@ -17,7 +17,16 @@ - static int autofs_get_sb(struct file_system_type *fs_type, - int flags, const char *dev_name, void *data, struct vfsmount *mnt) - { -- return get_sb_nodev(fs_type, flags, data, autofs4_fill_super, mnt); -+ struct autofs_sb_info *sbi; -+ int ret; -+ -+ ret = get_sb_nodev(fs_type, flags, data, autofs4_fill_super, mnt); -+ if (ret) -+ return ret; -+ -+ sbi = autofs4_sbi(mnt->mnt_sb); -+ sbi->mnt = mnt; -+ return 0; - } - - static struct file_system_type autofs_fs_type = { ---- a/fs/autofs4/root.c -+++ b/fs/autofs4/root.c -@@ -179,6 +179,12 @@ static void *autofs4_follow_link(struct - DPRINTK("dentry=%p %.*s oz_mode=%d nd->flags=%d", - dentry, dentry->d_name.len, dentry->d_name.name, oz_mode, - nd->flags); -+ -+ dput(nd->path.dentry); -+ mntput(nd->path.mnt); -+ nd->path.mnt = mntget(sbi->mnt); -+ nd->path.dentry = dget(dentry); -+ - /* - * For an expire of a covered direct or offset mount we need - * to break out of follow_down() at the autofs mount trigger ---- a/fs/compat.c -+++ b/fs/compat.c -@@ -847,6 +847,9 @@ static int compat_fillonedir(void *__buf - struct compat_old_linux_dirent __user *dirent; - compat_ulong_t d_ino; - -+ if (d_type == DT_WHT) -+ return 0; -+ - if (buf->result) - return -EINVAL; - d_ino = ino; -@@ -918,6 +921,9 @@ static int compat_filldir(void *__buf, c - compat_ulong_t d_ino; - int reclen = ALIGN(NAME_OFFSET(dirent) + namlen + 2, sizeof(compat_long_t)); - -+ if (d_type == DT_WHT) -+ return 0; -+ - buf->error = -EINVAL; /* only used if we fail.. */ - if (reclen > buf->count) - return -EINVAL; -@@ -1007,6 +1013,9 @@ static int compat_filldir64(void * __buf - int reclen = ALIGN(jj + namlen + 1, sizeof(u64)); - u64 off; - -+ if (d_type == DT_WHT) -+ return 0; -+ - buf->error = -EINVAL; /* only used if we fail.. */ - if (reclen > buf->count) - return -EINVAL; ---- a/fs/dcache.c -+++ b/fs/dcache.c -@@ -18,6 +18,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -157,14 +158,19 @@ static void dentry_lru_del_init(struct d - } - - /** -- * d_kill - kill dentry and return parent -+ * __d_kill - kill dentry and return parent - * @dentry: dentry to kill -+ * @list: kill list -+ * @greedy: return parent instead of putting it on the kill list - * - * The dentry must already be unhashed and removed from the LRU. - * -- * If this is the root of the dentry tree, return NULL. -+ * If this is the root of the dentry tree, return NULL. If greedy is zero, we -+ * put the parent of this dentry on the kill list instead. The callers must -+ * make sure that __d_kill_final() is called on all dentries on the kill list. - */ --static struct dentry *d_kill(struct dentry *dentry) -+static struct dentry *__d_kill(struct dentry *dentry, struct list_head *list, -+ int greedy) - __releases(dentry->d_lock) - __releases(dcache_lock) - { -@@ -172,13 +178,78 @@ static struct dentry *d_kill(struct dent - - list_del(&dentry->d_u.d_child); - dentry_stat.nr_dentry--; /* For d_free, below */ -- /*drops the locks, at that point nobody can reach this dentry */ -+ -+ /* -+ * If we are not greedy we just put this on a list for later processing -+ * (follow up to parent, releasing of inode and freeing dentry memory). -+ */ -+ if (!greedy) { -+ list_del_init(&dentry->d_alias); -+ /* at this point nobody can reach this dentry */ -+ list_add(&dentry->d_lru, list); -+ spin_unlock(&dentry->d_lock); -+ spin_unlock(&dcache_lock); -+ __shrink_d_unions(dentry, list); -+ return NULL; -+ } -+ -+ /* drops the locks, at that point nobody can reach this dentry */ - dentry_iput(dentry); -+ /* If the dentry was in an union delete them */ -+ __shrink_d_unions(dentry, list); -+ if (IS_ROOT(dentry)) -+ parent = NULL; -+ else -+ parent = dentry->d_parent; -+ d_free(dentry); -+ return parent; -+} -+ -+void __dput(struct dentry *, struct list_head *, int); -+ -+static void __d_kill_final(struct dentry *dentry, struct list_head *list) -+{ -+ struct dentry *parent; -+ struct inode *inode = dentry->d_inode; -+ -+ if (inode) { -+ dentry->d_inode = NULL; -+ if (!inode->i_nlink) -+ fsnotify_inoderemove(inode); -+ if (dentry->d_op && dentry->d_op->d_iput) -+ dentry->d_op->d_iput(dentry, inode); -+ else -+ iput(inode); -+ } -+ - if (IS_ROOT(dentry)) - parent = NULL; - else - parent = dentry->d_parent; - d_free(dentry); -+ __dput(parent, list, 1); -+} -+ -+/** -+ * d_kill - kill dentry and return parent -+ * @dentry: dentry to kill -+ * -+ * The dentry must already be unhashed and removed from the LRU. -+ * -+ * If this is the root of the dentry tree, return NULL. -+ */ -+static struct dentry *d_kill(struct dentry *dentry) -+{ -+ LIST_HEAD(mortuary); -+ struct dentry *parent; -+ -+ parent = __d_kill(dentry, &mortuary, 1); -+ while (!list_empty(&mortuary)) { -+ dentry = list_entry(mortuary.next, struct dentry, d_lru); -+ list_del(&dentry->d_lru); -+ __d_kill_final(dentry, &mortuary); -+ } -+ - return parent; - } - -@@ -199,19 +270,24 @@ static struct dentry *d_kill(struct dent - * Real recursion would eat up our stack space. - */ - --/* -- * dput - release a dentry -- * @dentry: dentry to release -+/** -+ * __dput - release a dentry -+ * @dentry: dentry to release -+ * @list: kill list argument for __d_kill() -+ * @greedy: greedy argument for __d_kill() - * - * Release a dentry. This will drop the usage count and if appropriate - * call the dentry unlink method as well as removing it from the queues and - * releasing its resources. If the parent dentries were scheduled for release -- * they too may now get deleted. -+ * they too may now get deleted if @greedy is not zero. Otherwise parent is -+ * added to the kill list. The callers must make sure that __d_kill_final() is -+ * called on all dentries on the kill list. -+ * -+ * You probably want to use dput() instead. - * - * no dcache lock, please. - */ -- --void dput(struct dentry *dentry) -+void __dput(struct dentry *dentry, struct list_head *list, int greedy) - { - if (!dentry) - return; -@@ -252,12 +328,35 @@ unhash_it: - kill_it: - /* if dentry was on the d_lru list delete it from there */ - dentry_lru_del(dentry); -- dentry = d_kill(dentry); -+ dentry = __d_kill(dentry, list, greedy); - if (dentry) - goto repeat; - } - - /** -+ * dput - release a dentry -+ * @dentry: dentry to release -+ * -+ * Release a dentry. This will drop the usage count and if appropriate -+ * call the dentry unlink method as well as removing it from the queues and -+ * releasing its resources. If the parent dentries were scheduled for release -+ * they too may now get deleted. -+ * -+ * no dcache lock, please. -+ */ -+void dput(struct dentry *dentry) -+{ -+ LIST_HEAD(mortuary); -+ -+ __dput(dentry, &mortuary, 1); -+ while (!list_empty(&mortuary)) { -+ dentry = list_entry(mortuary.next, struct dentry, d_lru); -+ list_del(&dentry->d_lru); -+ __d_kill_final(dentry, &mortuary); -+ } -+} -+ -+/** - * d_invalidate - invalidate a dentry - * @dentry: dentry to invalidate - * -@@ -689,6 +788,7 @@ static void shrink_dcache_for_umount_sub - iput(inode); - } - -+ shrink_d_unions(dentry); - d_free(dentry); - - /* finished when we fall off the top of the tree, -@@ -951,6 +1051,10 @@ struct dentry *d_alloc(struct dentry * p - INIT_LIST_HEAD(&dentry->d_lru); - INIT_LIST_HEAD(&dentry->d_subdirs); - INIT_LIST_HEAD(&dentry->d_alias); -+#ifdef CONFIG_UNION_MOUNT -+ INIT_LIST_HEAD(&dentry->d_unions); -+ dentry->d_unionized = 0; -+#endif - - if (parent) { - dentry->d_parent = dget(parent); -@@ -981,8 +1085,10 @@ struct dentry *d_alloc_name(struct dentr - /* the caller must hold dcache_lock */ - static void __d_instantiate(struct dentry *dentry, struct inode *inode) - { -- if (inode) -+ if (inode) { -+ dentry->d_flags &= ~(DCACHE_WHITEOUT|DCACHE_FALLTHRU); - list_add(&dentry->d_alias, &inode->i_dentry); -+ } - dentry->d_inode = inode; - fsnotify_d_instantiate(dentry, inode); - } -@@ -1513,7 +1619,9 @@ void d_delete(struct dentry * dentry) - spin_lock(&dentry->d_lock); - isdir = S_ISDIR(dentry->d_inode->i_mode); - if (atomic_read(&dentry->d_count) == 1) { -+ __d_drop_unions(dentry); - dentry_iput(dentry); -+ shrink_d_unions(dentry); - fsnotify_nameremove(dentry, isdir); - return; - } -@@ -1524,14 +1632,14 @@ void d_delete(struct dentry * dentry) - spin_unlock(&dentry->d_lock); - spin_unlock(&dcache_lock); - -+ shrink_d_unions(dentry); - fsnotify_nameremove(dentry, isdir); - } - - static void __d_rehash(struct dentry * entry, struct hlist_head *list) - { -- -- entry->d_flags &= ~DCACHE_UNHASHED; -- hlist_add_head_rcu(&entry->d_hash, list); -+ entry->d_flags &= ~DCACHE_UNHASHED; -+ hlist_add_head_rcu(&entry->d_hash, list); - } - - static void _d_rehash(struct dentry * entry) -@@ -1550,6 +1658,7 @@ void d_rehash(struct dentry * entry) - { - spin_lock(&dcache_lock); - spin_lock(&entry->d_lock); -+ BUG_ON(!d_unhashed(entry)); - _d_rehash(entry); - spin_unlock(&entry->d_lock); - spin_unlock(&dcache_lock); -@@ -2182,7 +2291,9 @@ resume: - struct list_head *tmp = next; - struct dentry *dentry = list_entry(tmp, struct dentry, d_u.d_child); - next = tmp->next; -- if (d_unhashed(dentry)||!dentry->d_inode) -+ if (d_unhashed(dentry)||(!dentry->d_inode && -+ !d_is_whiteout(dentry) && -+ !d_is_fallthru(dentry))) - continue; - if (!list_empty(&dentry->d_subdirs)) { - this_parent = dentry; ---- a/fs/ext2/dir.c -+++ b/fs/ext2/dir.c -@@ -219,7 +219,8 @@ static inline int ext2_match (int len, c - { - if (len != de->name_len) - return 0; -- if (!de->inode) -+ if (!de->inode && ((de->file_type != EXT2_FT_WHT) && -+ (de->file_type != EXT2_FT_FALLTHRU))) - return 0; - return !memcmp(name, de->name, len); - } -@@ -255,6 +256,8 @@ static unsigned char ext2_filetype_table - [EXT2_FT_FIFO] = DT_FIFO, - [EXT2_FT_SOCK] = DT_SOCK, - [EXT2_FT_SYMLINK] = DT_LNK, -+ [EXT2_FT_WHT] = DT_WHT, -+ [EXT2_FT_FALLTHRU] = DT_UNKNOWN, - }; - - #define S_SHIFT 12 -@@ -341,6 +344,18 @@ ext2_readdir (struct file * filp, void * - ext2_put_page(page); - return 0; - } -+ } else if (de->file_type == EXT2_FT_FALLTHRU) { -+ int over; -+ unsigned char d_type = DT_UNKNOWN; -+ -+ offset = (char *)de - kaddr; -+ over = filldir(dirent, de->name, de->name_len, -+ (n<f_pos += ext2_rec_len_from_disk(de->rec_len); - } -@@ -448,6 +463,30 @@ ino_t ext2_inode_by_name(struct inode *d - return res; - } - -+/* Special version for filetype based whiteout support */ -+ino_t ext2_inode_by_dentry(struct inode *dir, struct dentry *dentry) -+{ -+ ino_t res = 0; -+ struct ext2_dir_entry_2 *de; -+ struct page *page; -+ -+ de = ext2_find_entry (dir, &dentry->d_name, &page); -+ if (de) { -+ res = le32_to_cpu(de->inode); -+ if (!res && de->file_type == EXT2_FT_WHT) { -+ spin_lock(&dentry->d_lock); -+ dentry->d_flags |= DCACHE_WHITEOUT; -+ spin_unlock(&dentry->d_lock); -+ } else if(!res && de->file_type == EXT2_FT_FALLTHRU) { -+ spin_lock(&dentry->d_lock); -+ dentry->d_flags |= DCACHE_FALLTHRU; -+ spin_unlock(&dentry->d_lock); -+ } -+ ext2_put_page(page); -+ } -+ return res; -+} -+ - /* Releases the page */ - void ext2_set_link(struct inode *dir, struct ext2_dir_entry_2 *de, - struct page *page, struct inode *inode, int update_times) -@@ -472,9 +511,10 @@ void ext2_set_link(struct inode *dir, st - } - - /* -- * Parent is locked. -+ * Find or append a given dentry to the parent directory - */ --int ext2_add_link (struct dentry *dentry, struct inode *inode) -+static ext2_dirent * ext2_append_entry(struct dentry * dentry, -+ struct page ** page) - { - struct inode *dir = dentry->d_parent->d_inode; - const char *name = dentry->d_name.name; -@@ -482,13 +522,10 @@ int ext2_add_link (struct dentry *dentry - unsigned chunk_size = ext2_chunk_size(dir); - unsigned reclen = EXT2_DIR_REC_LEN(namelen); - unsigned short rec_len, name_len; -- struct page *page = NULL; -- ext2_dirent * de; -+ ext2_dirent * de = NULL; - unsigned long npages = dir_pages(dir); - unsigned long n; - char *kaddr; -- loff_t pos; -- int err; - - /* - * We take care of directory expansion in the same loop. -@@ -498,55 +535,97 @@ int ext2_add_link (struct dentry *dentry - for (n = 0; n <= npages; n++) { - char *dir_end; - -- page = ext2_get_page(dir, n, 0); -- err = PTR_ERR(page); -- if (IS_ERR(page)) -+ *page = ext2_get_page(dir, n, 0); -+ de = ERR_PTR(PTR_ERR(*page)); -+ if (IS_ERR(*page)) - goto out; -- lock_page(page); -- kaddr = page_address(page); -+ lock_page(*page); -+ kaddr = page_address(*page); - dir_end = kaddr + ext2_last_byte(dir, n); - de = (ext2_dirent *)kaddr; - kaddr += PAGE_CACHE_SIZE - reclen; - while ((char *)de <= kaddr) { - if ((char *)de == dir_end) { - /* We hit i_size */ -- name_len = 0; -- rec_len = chunk_size; -+ de->name_len = 0; - de->rec_len = ext2_rec_len_to_disk(chunk_size); - de->inode = 0; -+ de->file_type = 0; - goto got_it; - } - if (de->rec_len == 0) { - ext2_error(dir->i_sb, __func__, - "zero-length directory entry"); -- err = -EIO; -+ de = ERR_PTR(-EIO); - goto out_unlock; - } -- err = -EEXIST; - if (ext2_match (namelen, name, de)) -- goto out_unlock; -+ goto got_it; - name_len = EXT2_DIR_REC_LEN(de->name_len); - rec_len = ext2_rec_len_from_disk(de->rec_len); -- if (!de->inode && rec_len >= reclen) -+ if (!de->inode && (de->file_type != EXT2_FT_WHT) && -+ (de->file_type != EXT2_FT_FALLTHRU) && -+ (rec_len >= reclen)) - goto got_it; - if (rec_len >= name_len + reclen) - goto got_it; - de = (ext2_dirent *) ((char *) de + rec_len); - } -- unlock_page(page); -- ext2_put_page(page); -+ unlock_page(*page); -+ ext2_put_page(*page); - } -+ - BUG(); -- return -EINVAL; - - got_it: -+ return de; -+ /* OFFSET_CACHE */ -+out_unlock: -+ unlock_page(*page); -+ ext2_put_page(*page); -+out: -+ return de; -+} -+ -+/* -+ * Parent is locked. -+ */ -+int ext2_add_link (struct dentry *dentry, struct inode *inode) -+{ -+ struct inode *dir = dentry->d_parent->d_inode; -+ const char *name = dentry->d_name.name; -+ int namelen = dentry->d_name.len; -+ unsigned short rec_len, name_len; -+ ext2_dirent * de; -+ struct page *page; -+ loff_t pos; -+ int err; -+ -+ de = ext2_append_entry(dentry, &page); -+ if (IS_ERR(de)) -+ return PTR_ERR(de); -+ -+ err = -EEXIST; -+ if (ext2_match (namelen, name, de)) { -+ if ((de->file_type == EXT2_FT_WHT) || -+ (de->file_type == EXT2_FT_FALLTHRU)) -+ goto got_it; -+ goto out_unlock; -+ } -+ -+got_it: -+ name_len = EXT2_DIR_REC_LEN(de->name_len); -+ rec_len = ext2_rec_len_from_disk(de->rec_len); -+ - pos = page_offset(page) + - (char*)de - (char*)page_address(page); - err = __ext2_write_begin(NULL, page->mapping, pos, rec_len, 0, - &page, NULL); - if (err) - goto out_unlock; -- if (de->inode) { -+ if (de->inode || (((de->file_type == EXT2_FT_WHT) || -+ (de->file_type == EXT2_FT_FALLTHRU)) && -+ !ext2_match (namelen, name, de))) { - ext2_dirent *de1 = (ext2_dirent *) ((char *) de + name_len); - de1->rec_len = ext2_rec_len_to_disk(rec_len - name_len); - de->rec_len = ext2_rec_len_to_disk(name_len); -@@ -563,7 +642,60 @@ got_it: - /* OFFSET_CACHE */ - out_put: - ext2_put_page(page); --out: -+ return err; -+out_unlock: -+ unlock_page(page); -+ goto out_put; -+} -+ -+/* -+ * Create a fallthru entry. -+ */ -+int ext2_fallthru_entry (struct inode *dir, struct dentry *dentry) -+{ -+ const char *name = dentry->d_name.name; -+ int namelen = dentry->d_name.len; -+ unsigned short rec_len, name_len; -+ ext2_dirent * de; -+ struct page *page; -+ loff_t pos; -+ int err; -+ -+ de = ext2_append_entry(dentry, &page); -+ if (IS_ERR(de)) -+ return PTR_ERR(de); -+ -+ err = -EEXIST; -+ if (ext2_match (namelen, name, de)) -+ goto out_unlock; -+ -+ name_len = EXT2_DIR_REC_LEN(de->name_len); -+ rec_len = ext2_rec_len_from_disk(de->rec_len); -+ -+ pos = page_offset(page) + -+ (char*)de - (char*)page_address(page); -+ err = __ext2_write_begin(NULL, page->mapping, pos, rec_len, 0, -+ &page, NULL); -+ if (err) -+ goto out_unlock; -+ if (de->inode || (de->file_type == EXT2_FT_WHT) || -+ (de->file_type == EXT2_FT_FALLTHRU)) { -+ ext2_dirent *de1 = (ext2_dirent *) ((char *) de + name_len); -+ de1->rec_len = ext2_rec_len_to_disk(rec_len - name_len); -+ de->rec_len = ext2_rec_len_to_disk(name_len); -+ de = de1; -+ } -+ de->name_len = namelen; -+ memcpy(de->name, name, namelen); -+ de->inode = 0; -+ de->file_type = EXT2_FT_FALLTHRU; -+ err = ext2_commit_chunk(page, pos, rec_len); -+ dir->i_mtime = dir->i_ctime = CURRENT_TIME_SEC; -+ EXT2_I(dir)->i_flags &= ~EXT2_BTREE_FL; -+ mark_inode_dirty(dir); -+ /* OFFSET_CACHE */ -+out_put: -+ ext2_put_page(page); - return err; - out_unlock: - unlock_page(page); -@@ -616,6 +748,70 @@ out: - return err; - } - -+int ext2_whiteout_entry (struct inode * dir, struct dentry * dentry, -+ struct ext2_dir_entry_2 * de, struct page * page) -+{ -+ const char *name = dentry->d_name.name; -+ int namelen = dentry->d_name.len; -+ unsigned short rec_len, name_len; -+ loff_t pos; -+ int err; -+ -+ if (!de) { -+ de = ext2_append_entry(dentry, &page); -+ BUG_ON(!de); -+ } -+ -+ err = -EEXIST; -+ if (ext2_match (namelen, name, de) && -+ (de->file_type == EXT2_FT_WHT)) { -+ ext2_error(dir->i_sb, __func__, -+ "entry is already a whiteout in directory #%lu", -+ dir->i_ino); -+ goto out_unlock; -+ } -+ -+ name_len = EXT2_DIR_REC_LEN(de->name_len); -+ rec_len = ext2_rec_len_from_disk(de->rec_len); -+ -+ pos = page_offset(page) + -+ (char*)de - (char*)page_address(page); -+ err = __ext2_write_begin(NULL, page->mapping, pos, rec_len, 0, -+ &page, NULL); -+ if (err) -+ goto out_unlock; -+ /* -+ * We whiteout an existing entry. Do what ext2_delete_entry() would do, -+ * except that we don't need to merge with the previous entry since -+ * we are going to reuse it. -+ */ -+ if (ext2_match (namelen, name, de)) -+ de->inode = 0; -+ if (de->inode || (((de->file_type == EXT2_FT_WHT) || -+ (de->file_type == EXT2_FT_FALLTHRU)) && -+ !ext2_match (namelen, name, de))) { -+ ext2_dirent *de1 = (ext2_dirent *) ((char *) de + name_len); -+ de1->rec_len = ext2_rec_len_to_disk(rec_len - name_len); -+ de->rec_len = ext2_rec_len_to_disk(name_len); -+ de = de1; -+ } -+ de->name_len = namelen; -+ memcpy(de->name, name, namelen); -+ de->inode = 0; -+ de->file_type = EXT2_FT_WHT; -+ err = ext2_commit_chunk(page, pos, rec_len); -+ dir->i_mtime = dir->i_ctime = CURRENT_TIME_SEC; -+ EXT2_I(dir)->i_flags &= ~EXT2_BTREE_FL; -+ mark_inode_dirty(dir); -+ /* OFFSET_CACHE */ -+out_put: -+ ext2_put_page(page); -+ return err; -+out_unlock: -+ unlock_page(page); -+ goto out_put; -+} -+ - /* - * Set the first fragment of directory. - */ ---- a/fs/ext2/ext2.h -+++ b/fs/ext2/ext2.h -@@ -102,9 +102,13 @@ extern void ext2_rsv_window_add(struct s - /* dir.c */ - extern int ext2_add_link (struct dentry *, struct inode *); - extern ino_t ext2_inode_by_name(struct inode *, struct qstr *); -+extern ino_t ext2_inode_by_dentry(struct inode *, struct dentry *); - extern int ext2_make_empty(struct inode *, struct inode *); - extern struct ext2_dir_entry_2 * ext2_find_entry (struct inode *,struct qstr *, struct page **); - extern int ext2_delete_entry (struct ext2_dir_entry_2 *, struct page *); -+extern int ext2_whiteout_entry (struct inode *, struct dentry *, -+ struct ext2_dir_entry_2 *, struct page *); -+extern int ext2_fallthru_entry (struct inode *, struct dentry *); - extern int ext2_empty_dir (struct inode *); - extern struct ext2_dir_entry_2 * ext2_dotdot (struct inode *, struct page **); - extern void ext2_set_link(struct inode *, struct ext2_dir_entry_2 *, struct page *, struct inode *, int); ---- a/fs/ext2/inode.c -+++ b/fs/ext2/inode.c -@@ -1176,7 +1176,8 @@ void ext2_set_inode_flags(struct inode * - { - unsigned int flags = EXT2_I(inode)->i_flags; - -- inode->i_flags &= ~(S_SYNC|S_APPEND|S_IMMUTABLE|S_NOATIME|S_DIRSYNC); -+ inode->i_flags &= ~(S_SYNC|S_APPEND|S_IMMUTABLE|S_NOATIME|S_DIRSYNC| -+ S_OPAQUE); - if (flags & EXT2_SYNC_FL) - inode->i_flags |= S_SYNC; - if (flags & EXT2_APPEND_FL) -@@ -1187,6 +1188,8 @@ void ext2_set_inode_flags(struct inode * - inode->i_flags |= S_NOATIME; - if (flags & EXT2_DIRSYNC_FL) - inode->i_flags |= S_DIRSYNC; -+ if (flags & EXT2_OPAQUE_FL) -+ inode->i_flags |= S_OPAQUE; - } - - /* Propagate flags from i_flags to EXT2_I(inode)->i_flags */ -@@ -1194,8 +1197,8 @@ void ext2_get_inode_flags(struct ext2_in - { - unsigned int flags = ei->vfs_inode.i_flags; - -- ei->i_flags &= ~(EXT2_SYNC_FL|EXT2_APPEND_FL| -- EXT2_IMMUTABLE_FL|EXT2_NOATIME_FL|EXT2_DIRSYNC_FL); -+ ei->i_flags &= ~(EXT2_SYNC_FL|EXT2_APPEND_FL|EXT2_IMMUTABLE_FL| -+ EXT2_NOATIME_FL|EXT2_DIRSYNC_FL|EXT2_OPAQUE_FL); - if (flags & S_SYNC) - ei->i_flags |= EXT2_SYNC_FL; - if (flags & S_APPEND) -@@ -1206,6 +1209,8 @@ void ext2_get_inode_flags(struct ext2_in - ei->i_flags |= EXT2_NOATIME_FL; - if (flags & S_DIRSYNC) - ei->i_flags |= EXT2_DIRSYNC_FL; -+ if (flags & S_OPAQUE) -+ ei->i_flags |= EXT2_OPAQUE_FL; - } - - struct inode *ext2_iget (struct super_block *sb, unsigned long ino) ---- a/fs/ext2/namei.c -+++ b/fs/ext2/namei.c -@@ -54,15 +54,16 @@ static inline int ext2_add_nondir(struct - * Methods themselves. - */ - --static struct dentry *ext2_lookup(struct inode * dir, struct dentry *dentry, struct nameidata *nd) -+static struct dentry *ext2_lookup(struct inode * dir, struct dentry *dentry, -+ struct nameidata *nd) - { - struct inode * inode; - ino_t ino; -- -+ - if (dentry->d_name.len > EXT2_NAME_LEN) - return ERR_PTR(-ENAMETOOLONG); - -- ino = ext2_inode_by_name(dir, &dentry->d_name); -+ ino = ext2_inode_by_dentry(dir, dentry); - inode = NULL; - if (ino) { - inode = ext2_iget(dir->i_sb, ino); -@@ -230,6 +231,10 @@ static int ext2_mkdir(struct inode * dir - else - inode->i_mapping->a_ops = &ext2_aops; - -+ /* if we call mkdir on a whiteout create an opaque directory */ -+ if (dentry->d_flags & DCACHE_WHITEOUT) -+ inode->i_flags |= S_OPAQUE; -+ - inode_inc_link_count(inode); - - err = ext2_make_empty(inode, dir); -@@ -293,6 +298,78 @@ static int ext2_rmdir (struct inode * di - return err; - } - -+/* -+ * Create a whiteout for the dentry -+ */ -+static int ext2_whiteout(struct inode *dir, struct dentry *dentry, -+ struct dentry *new_dentry) -+{ -+ struct inode * inode = dentry->d_inode; -+ struct ext2_dir_entry_2 * de = NULL; -+ struct page * page; -+ int err = -ENOTEMPTY; -+ -+ if (!EXT2_HAS_INCOMPAT_FEATURE(dir->i_sb, -+ EXT2_FEATURE_INCOMPAT_FILETYPE)) { -+ ext2_error (dir->i_sb, "ext2_whiteout", -+ "can't set whiteout filetype"); -+ err = -EPERM; -+ goto out; -+ } -+ -+ if (inode) { -+ if (S_ISDIR(inode->i_mode) && !ext2_empty_dir(inode)) -+ goto out; -+ -+ err = -ENOENT; -+ de = ext2_find_entry (dir, &dentry->d_name, &page); -+ if (!de) -+ goto out; -+ lock_page(page); -+ } -+ -+ err = ext2_whiteout_entry (dir, dentry, de, page); -+ if (err) -+ goto out; -+ -+ spin_lock(&new_dentry->d_lock); -+ new_dentry->d_flags &= ~DCACHE_FALLTHRU; -+ new_dentry->d_flags |= DCACHE_WHITEOUT; -+ spin_unlock(&new_dentry->d_lock); -+ d_add(new_dentry, NULL); -+ -+ if (inode) { -+ inode->i_ctime = dir->i_ctime; -+ inode_dec_link_count(inode); -+ if (S_ISDIR(inode->i_mode)) { -+ inode->i_size = 0; -+ inode_dec_link_count(inode); -+ inode_dec_link_count(dir); -+ } -+ } -+ err = 0; -+out: -+ return err; -+} -+ -+/* -+ * Create a fallthru entry. -+ */ -+static int ext2_fallthru (struct inode *dir, struct dentry *dentry) -+{ -+ int err; -+ -+ err = ext2_fallthru_entry(dir, dentry); -+ if (err) -+ return err; -+ -+ d_instantiate(dentry, NULL); -+ spin_lock(&dentry->d_lock); -+ dentry->d_flags |= DCACHE_FALLTHRU; -+ spin_unlock(&dentry->d_lock); -+ return 0; -+} -+ - static int ext2_rename (struct inode * old_dir, struct dentry * old_dentry, - struct inode * new_dir, struct dentry * new_dentry ) - { -@@ -392,6 +469,8 @@ const struct inode_operations ext2_dir_i - .mkdir = ext2_mkdir, - .rmdir = ext2_rmdir, - .mknod = ext2_mknod, -+ .whiteout = ext2_whiteout, -+ .fallthru = ext2_fallthru, - .rename = ext2_rename, - #ifdef CONFIG_EXT2_FS_XATTR - .setxattr = generic_setxattr, ---- a/fs/ext2/super.c -+++ b/fs/ext2/super.c -@@ -1062,6 +1062,13 @@ static int ext2_fill_super(struct super_ - if (EXT2_HAS_COMPAT_FEATURE(sb, EXT3_FEATURE_COMPAT_HAS_JOURNAL)) - ext2_warning(sb, __func__, - "mounting ext3 filesystem as ext2"); -+ -+ /* -+ * Whiteouts (and fallthrus) require explicit whiteout support. -+ */ -+ if (EXT2_HAS_INCOMPAT_FEATURE(sb, EXT2_FEATURE_INCOMPAT_WHITEOUT)) -+ sb->s_flags |= MS_WHITEOUT; -+ - ext2_setup_super (sb, es, sb->s_flags & MS_RDONLY); - return 0; - ---- a/fs/Kconfig -+++ b/fs/Kconfig -@@ -58,6 +58,14 @@ source "fs/notify/Kconfig" - - source "fs/quota/Kconfig" - -+config UNION_MOUNT -+ bool "Union mount support (EXPERIMENTAL)" -+ depends on EXPERIMENTAL -+ ---help--- -+ If you say Y here, you will be able to mount file systems as -+ union mount stacks. This is a VFS based implementation and -+ should work with all file systems. If unsure, say N. -+ - source "fs/autofs/Kconfig" - source "fs/autofs4/Kconfig" - source "fs/fuse/Kconfig" ---- a/fs/libfs.c -+++ b/fs/libfs.c -@@ -133,6 +133,7 @@ int dcache_readdir(struct file * filp, v - struct dentry *cursor = filp->private_data; - struct list_head *p, *q = &cursor->d_u.d_child; - ino_t ino; -+ int d_type; - int i = filp->f_pos; - - switch (i) { -@@ -158,14 +159,25 @@ int dcache_readdir(struct file * filp, v - for (p=q->next; p != &dentry->d_subdirs; p=p->next) { - struct dentry *next; - next = list_entry(p, struct dentry, d_u.d_child); -- if (d_unhashed(next) || !next->d_inode) -+ if (d_unhashed(next) || (!next->d_inode && !d_is_fallthru(next))) - continue; - -+ if (d_is_fallthru(next)) { -+ /* XXX Make up things we can -+ * only get out of the inode. -+ * Should probably really do a -+ * lookup instead. */ -+ ino = 100; /* XXX Made up number of no significance */ -+ d_type = DT_UNKNOWN; -+ } else { -+ ino = next->d_inode->i_ino; -+ d_type = dt_type(next->d_inode); -+ } -+ - spin_unlock(&dcache_lock); - if (filldir(dirent, next->d_name.name, - next->d_name.len, filp->f_pos, -- next->d_inode->i_ino, -- dt_type(next->d_inode)) < 0) -+ ino, d_type) < 0) - return 0; - spin_lock(&dcache_lock); - /* next is still alive */ ---- a/fs/Makefile -+++ b/fs/Makefile -@@ -52,6 +52,7 @@ obj-$(CONFIG_NFS_COMMON) += nfs_common/ - obj-$(CONFIG_GENERIC_ACL) += generic_acl.o - - obj-y += quota/ -+obj-$(CONFIG_UNION_MOUNT) += union.o - - obj-$(CONFIG_PROC_FS) += proc/ - obj-y += partitions/ ---- a/fs/namei.c -+++ b/fs/namei.c -@@ -33,6 +33,7 @@ - #include - #include - #include -+#include - #include - - #define ACC_MODE(x) ("\000\004\002\006"[(x)&O_ACCMODE]) -@@ -229,16 +230,17 @@ int generic_permission(struct inode *ino - } - - /** -- * inode_permission - check for access rights to a given inode -+ * __inode_permission - check for access rights to a given inode - * @inode: inode to check permission on - * @mask: right to check for (%MAY_READ, %MAY_WRITE, %MAY_EXEC) -+ * @rofs: check for read-only fs - * - * Used to check for read/write/execute permissions on an inode. - * We use "fsuid" for this, letting us set arbitrary permissions - * for filesystem access without changing the "normal" uids which - * are used for other things. - */ --int inode_permission(struct inode *inode, int mask) -+int __inode_permission(struct inode *inode, int mask, int rofs) - { - int retval; - -@@ -248,7 +250,7 @@ int inode_permission(struct inode *inode - /* - * Nobody gets write access to a read-only fs. - */ -- if (IS_RDONLY(inode) && -+ if ((rofs & IS_RDONLY(inode)) && - (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode))) - return -EROFS; - -@@ -276,6 +278,18 @@ int inode_permission(struct inode *inode - } - - /** -+ * inode_permission - check for access rights to a given inode -+ * @inode: inode to check permission on -+ * @mask: right to check for (%MAY_READ, %MAY_WRITE, %MAY_EXEC) -+ * -+ * This version pays attention to the MS_RDONLY flag on the fs. -+ */ -+int inode_permission(struct inode *inode, int mask) -+{ -+ return __inode_permission(inode, mask, 1); -+} -+ -+/** - * file_permission - check for additional access rights to a given file - * @file: file to check access rights for - * @mask: right to check for (%MAY_READ, %MAY_WRITE, %MAY_EXEC) -@@ -404,15 +418,10 @@ do_revalidate(struct dentry *dentry, str - * Internal lookup() using the new generic dcache. - * SMP-safe - */ --static struct dentry * cached_lookup(struct dentry * parent, struct qstr * name, struct nameidata *nd) -+static struct dentry *cache_lookup(struct dentry *parent, struct qstr *name, -+ struct nameidata *nd) - { -- struct dentry * dentry = __d_lookup(parent, name); -- -- /* lockess __d_lookup may fail due to concurrent d_move() -- * in some unrelated directory, so try with d_lookup -- */ -- if (!dentry) -- dentry = d_lookup(parent, name); -+ struct dentry *dentry = d_lookup(parent, name); - - if (dentry && dentry->d_op && dentry->d_op->d_revalidate) - dentry = do_revalidate(dentry, nd); -@@ -421,6 +430,208 @@ static struct dentry * cached_lookup(str - } - - /* -+ * Theory of operation for opaque, whiteout, and fallthru: -+ * -+ * whiteout: Unconditionally stop lookup here - ENOENT -+ * -+ * opaque: Don't lookup in directories lower in the union stack -+ * -+ * fallthru: While looking up an entry, ignore the opaque flag for the -+ * current directory only. -+ * -+ * A union stack is a linked list of directory dentries which appear -+ * in the same place in the namespace. When constructing the union -+ * stack, we include directories below opaque directories so that we -+ * can properly handle fallthrus. All non-fallthru lookups have to -+ * check for the opaque flag on the parent directory and obey it. -+ * -+ * In general, the code pattern is to lookup the the topmost entry -+ * first (either the first visible non-negative dentry or a negative -+ * dentry in the topmost layer of the union), then build the union -+ * stack for the newly looked-up entry (if it is a directory). -+ */ -+ -+/** -+ * __cache_lookup_topmost - lookup the topmost (non-)negative dentry -+ * -+ * @nd - parent's nameidata -+ * @name - pathname part to lookup -+ * @path - found dentry for pathname part -+ * -+ * This is used for union mount lookups from dcache. The first non-negative -+ * dentry is searched on all layers of the union stack. Otherwise the topmost -+ * negative dentry is returned. -+ */ -+static int __cache_lookup_topmost(struct nameidata *nd, struct qstr *name, -+ struct path *path) -+{ -+ struct dentry *dentry; -+ -+ dentry = d_lookup(nd->path.dentry, name); -+ if (dentry && dentry->d_op && dentry->d_op->d_revalidate) -+ dentry = do_revalidate(dentry, nd); -+ -+ /* -+ * Remember the topmost negative dentry in case we don't find anything -+ */ -+ path->dentry = dentry; -+ path->mnt = dentry ? nd->path.mnt : NULL; -+ -+ if (!dentry || (dentry->d_inode || d_is_whiteout(dentry))) -+ return !dentry; -+ -+ /* Keep going through opaque directories if we found a fallthru */ -+ if (IS_OPAQUE(nd->path.dentry->d_inode) && !d_is_fallthru(dentry)) -+ return !dentry; -+ -+ /* look for the first non-negative or whiteout dentry */ -+ -+ while (follow_union_down(&nd->path)) { -+ dentry = d_hash_and_lookup(nd->path.dentry, name); -+ -+ /* -+ * If parts of the union stack are not in the dcache we need -+ * to do a real lookup -+ */ -+ if (!dentry) -+ goto out_dput; -+ -+ /* -+ * If parts of the union don't survive the revalidation we -+ * need to do a real lookup -+ */ -+ if (dentry->d_op && dentry->d_op->d_revalidate) { -+ dentry = do_revalidate(dentry, nd); -+ if (!dentry) -+ goto out_dput; -+ } -+ -+ if (dentry->d_inode || d_is_whiteout(dentry)) -+ goto out_dput; -+ -+ /* Stop the lookup on opaque parent and non-fallthru child */ -+ if (IS_OPAQUE(nd->path.dentry->d_inode) && !d_is_fallthru(dentry)) -+ goto out_dput; -+ -+ dput(dentry); -+ } -+ -+ return !dentry; -+ -+out_dput: -+ dput(path->dentry); -+ path->dentry = dentry; -+ path->mnt = dentry ? mntget(nd->path.mnt) : NULL; -+ return !dentry; -+} -+ -+/** -+ * __cache_lookup_build_union - build the union stack for this part, -+ * cached version -+ * -+ * This is called after you have the topmost dentry in @path. -+ */ -+static int __cache_lookup_build_union(struct nameidata *nd, struct qstr *name, -+ struct path *path) -+{ -+ struct path last = *path; -+ struct dentry *dentry; -+ -+ while (follow_union_down(&nd->path)) { -+ dentry = d_hash_and_lookup(nd->path.dentry, name); -+ if (!dentry) -+ return 1; -+ -+ if (dentry->d_op && dentry->d_op->d_revalidate) { -+ dentry = do_revalidate(dentry, nd); -+ if (!dentry) -+ return 1; -+ } -+ -+ if (d_is_whiteout(dentry)) { -+ dput(dentry); -+ break; -+ } -+ -+ if (!dentry->d_inode) { -+ dput(dentry); -+ continue; -+ } -+ -+ /* only directories can be part of a union stack */ -+ if (!S_ISDIR(dentry->d_inode->i_mode)) { -+ dput(dentry); -+ break; -+ } -+ -+ /* Add the newly discovered dir to the union stack */ -+ append_to_union(last.mnt, last.dentry, nd->path.mnt, dentry); -+ -+ if (last.dentry != path->dentry) -+ path_put(&last); -+ last.dentry = dentry; -+ last.mnt = mntget(nd->path.mnt); -+ } -+ -+ if (last.dentry != path->dentry) -+ path_put(&last); -+ -+ return 0; -+} -+ -+/** -+ * cache_lookup_union - lookup a single pathname part from dcache -+ * -+ * This is a union mount capable version of what d_lookup() & revalidate() -+ * would do. This function returns a valid (union) dentry on success. -+ * -+ * Remember: On failure it means that parts of the union aren't cached. You -+ * should call real_lookup() afterwards to find the proper (union) dentry. -+ */ -+static int cache_lookup_union(struct nameidata *nd, struct qstr *name, -+ struct path *path) -+{ -+ int res ; -+ -+ if (!IS_MNT_UNION(nd->path.mnt)) { -+ path->dentry = cache_lookup(nd->path.dentry, name, nd); -+ path->mnt = path->dentry ? nd->path.mnt : NULL; -+ res = path->dentry ? 0 : 1; -+ } else { -+ struct path safe = { -+ .dentry = nd->path.dentry, -+ .mnt = nd->path.mnt -+ }; -+ -+ path_get(&safe); -+ res = __cache_lookup_topmost(nd, name, path); -+ if (res) -+ goto out; -+ -+ /* only directories can be part of a union stack */ -+ if (!path->dentry->d_inode || -+ !S_ISDIR(path->dentry->d_inode->i_mode)) -+ goto out; -+ -+ /* Build the union stack for this part */ -+ res = __cache_lookup_build_union(nd, name, path); -+ if (res) { -+ dput(path->dentry); -+ if (path->mnt != safe.mnt) -+ mntput(path->mnt); -+ goto out; -+ } -+ -+out: -+ path_put(&nd->path); -+ nd->path.dentry = safe.dentry; -+ nd->path.mnt = safe.mnt; -+ } -+ -+ return res; -+} -+ -+/* - * Short-cut version of permission(), for calling by - * path_walk(), when dcache lock is held. Combines parts - * of permission() and generic_permission(), and tests ONLY for -@@ -467,10 +678,11 @@ ok: - * make sure that nobody added the entry to the dcache in the meantime.. - * SMP-safe - */ --static struct dentry * real_lookup(struct dentry * parent, struct qstr * name, struct nameidata *nd) -+static int real_lookup(struct nameidata *nd, struct qstr *name, -+ struct path *path) - { -- struct dentry * result; -- struct inode *dir = parent->d_inode; -+ struct inode *dir = nd->path.dentry->d_inode; -+ int res = 0; - - mutex_lock(&dir->i_mutex); - /* -@@ -487,27 +699,36 @@ static struct dentry * real_lookup(struc - * - * so doing d_lookup() (with seqlock), instead of lockfree __d_lookup - */ -- result = d_lookup(parent, name); -- if (!result) { -+ path->dentry = d_lookup(nd->path.dentry, name); -+ path->mnt = nd->path.mnt; -+ if (!path->dentry) { - struct dentry *dentry; - - /* Don't create child dentry for a dead directory. */ -- result = ERR_PTR(-ENOENT); -- if (IS_DEADDIR(dir)) -+ if (IS_DEADDIR(dir)) { -+ res = -ENOENT; - goto out_unlock; -+ } - -- dentry = d_alloc(parent, name); -- result = ERR_PTR(-ENOMEM); -+ dentry = d_alloc(nd->path.dentry, name); - if (dentry) { -- result = dir->i_op->lookup(dir, dentry, nd); -- if (result) -+ path->dentry = dir->i_op->lookup(dir, dentry, nd); -+ if (path->dentry) { - dput(dentry); -- else -- result = dentry; -+ if (IS_ERR(path->dentry)) { -+ res = PTR_ERR(path->dentry); -+ path->dentry = NULL; -+ path->mnt = NULL; -+ } -+ } else -+ path->dentry = dentry; -+ } else { -+ res = -ENOMEM; -+ path->mnt = NULL; - } - out_unlock: - mutex_unlock(&dir->i_mutex); -- return result; -+ return res; - } - - /* -@@ -515,12 +736,170 @@ out_unlock: - * we waited on the semaphore. Need to revalidate. - */ - mutex_unlock(&dir->i_mutex); -- if (result->d_op && result->d_op->d_revalidate) { -- result = do_revalidate(result, nd); -- if (!result) -- result = ERR_PTR(-ENOENT); -+ if (path->dentry->d_op && path->dentry->d_op->d_revalidate) { -+ path->dentry = do_revalidate(path->dentry, nd); -+ if (!path->dentry) { -+ res = -ENOENT; -+ path->mnt = NULL; -+ } -+ if (IS_ERR(path->dentry)) { -+ res = PTR_ERR(path->dentry); -+ path->dentry = NULL; -+ path->mnt = NULL; -+ } - } -- return result; -+ -+ return res; -+} -+ -+/** -+ * __real_lookup_topmost - lookup topmost dentry, non-cached version -+ * -+ * If we reach a dentry with restricted access, we just stop the lookup -+ * because we shouldn't see through that dentry. Same thing for dentry -+ * type mismatch and whiteouts. -+ * -+ * FIXME: -+ * - handle union stacks in use -+ * - handle union stacks mounted upon union stacks -+ * - avoid unnecessary allocations of union locks -+ */ -+static int __real_lookup_topmost(struct nameidata *nd, struct qstr *name, -+ struct path *path) -+{ -+ struct path next; -+ int err; -+ -+ err = real_lookup(nd, name, path); -+ if (err) -+ return err; -+ -+ if (path->dentry->d_inode || d_is_whiteout(path->dentry)) -+ return 0; -+ -+ if (IS_OPAQUE(nd->path.dentry->d_inode) && !d_is_fallthru(path->dentry)) -+ return 0; -+ -+ while (follow_union_down(&nd->path)) { -+ name->hash = full_name_hash(name->name, name->len); -+ if (nd->path.dentry->d_op && nd->path.dentry->d_op->d_hash) { -+ err = nd->path.dentry->d_op->d_hash(nd->path.dentry, -+ name); -+ if (err < 0) -+ goto out; -+ } -+ -+ err = real_lookup(nd, name, &next); -+ if (err) -+ goto out; -+ -+ if (next.dentry->d_inode || d_is_whiteout(next.dentry)) { -+ dput(path->dentry); -+ mntget(next.mnt); -+ *path = next; -+ goto out; -+ } -+ -+ if (IS_OPAQUE(nd->path.dentry->d_inode) && !d_is_fallthru(next.dentry)) -+ goto out; -+ -+ dput(next.dentry); -+ } -+out: -+ if (err) -+ dput(path->dentry); -+ return err; -+} -+ -+/** -+ * __real_lookup_build_union: build the union stack for this pathname -+ * part, non-cached version -+ * -+ * Called when not all parts of the union stack are in cache -+ */ -+ -+static int __real_lookup_build_union(struct nameidata *nd, struct qstr *name, -+ struct path *path) -+{ -+ struct path last = *path; -+ struct path next; -+ int err = 0; -+ -+ while (follow_union_down(&nd->path)) { -+ /* We need to recompute the hash for lower layer lookups */ -+ name->hash = full_name_hash(name->name, name->len); -+ if (nd->path.dentry->d_op && nd->path.dentry->d_op->d_hash) { -+ err = nd->path.dentry->d_op->d_hash(nd->path.dentry, -+ name); -+ if (err < 0) -+ goto out; -+ } -+ -+ err = real_lookup(nd, name, &next); -+ if (err) -+ goto out; -+ -+ if (d_is_whiteout(next.dentry)) { -+ dput(next.dentry); -+ break; -+ } -+ -+ if (!next.dentry->d_inode) { -+ dput(next.dentry); -+ continue; -+ } -+ -+ /* only directories can be part of a union stack */ -+ if (!S_ISDIR(next.dentry->d_inode->i_mode)) { -+ dput(next.dentry); -+ break; -+ } -+ -+ /* now we know we found something "real" */ -+ append_to_union(last.mnt, last.dentry, next.mnt, next.dentry); -+ -+ if (last.dentry != path->dentry) -+ path_put(&last); -+ last.dentry = next.dentry; -+ last.mnt = mntget(next.mnt); -+ } -+ -+ if (last.dentry != path->dentry) -+ path_put(&last); -+out: -+ return err; -+} -+ -+static int real_lookup_union(struct nameidata *nd, struct qstr *name, -+ struct path *path) -+{ -+ struct path safe = { .dentry = nd->path.dentry, .mnt = nd->path.mnt }; -+ int res ; -+ -+ path_get(&safe); -+ res = __real_lookup_topmost(nd, name, path); -+ if (res) -+ goto out; -+ -+ /* only directories can be part of a union stack */ -+ if (!path->dentry->d_inode || -+ !S_ISDIR(path->dentry->d_inode->i_mode)) -+ goto out; -+ -+ /* Build the union stack for this part */ -+ res = __real_lookup_build_union(nd, name, path); -+ if (res) { -+ dput(path->dentry); -+ if (path->mnt != safe.mnt) -+ mntput(path->mnt); -+ goto out; -+ } -+ -+out: -+ path_put(&nd->path); -+ nd->path.dentry = safe.dentry; -+ nd->path.mnt = safe.mnt; -+ return res; - } - - /* -@@ -623,11 +1002,8 @@ static __always_inline int __do_follow_l - touch_atime(path->mnt, dentry); - nd_set_link(nd, NULL); - -- if (path->mnt != nd->path.mnt) { -- path_to_nameidata(path, nd); -- dget(dentry); -- } -- mntget(path->mnt); -+ if (path->mnt == nd->path.mnt) -+ mntget(nd->path.mnt); - cookie = dentry->d_inode->i_op->follow_link(dentry, nd); - error = PTR_ERR(cookie); - if (!IS_ERR(cookie)) { -@@ -715,7 +1091,7 @@ static int __follow_mount(struct path *p - return res; - } - --static void follow_mount(struct path *path) -+void follow_mount(struct path *path) - { - while (d_mountpoint(path->dentry)) { - struct vfsmount *mounted = lookup_mnt(path); -@@ -780,6 +1156,7 @@ static __always_inline void follow_dotdo - nd->path.mnt = parent; - } - follow_mount(&nd->path); -+ follow_union_mount(&nd->path); - } - - /* -@@ -790,35 +1167,55 @@ static __always_inline void follow_dotdo - static int do_lookup(struct nameidata *nd, struct qstr *name, - struct path *path) - { -- struct vfsmount *mnt = nd->path.mnt; -- struct dentry *dentry = __d_lookup(nd->path.dentry, name); -+ int err; -+ -+ if (IS_MNT_UNION(nd->path.mnt)) -+ goto need_union_lookup; - -- if (!dentry) -+ path->dentry = __d_lookup(nd->path.dentry, name); -+ path->mnt = nd->path.mnt; -+ if (!path->dentry) - goto need_lookup; -- if (dentry->d_op && dentry->d_op->d_revalidate) -+ if (path->dentry->d_op && path->dentry->d_op->d_revalidate) - goto need_revalidate; -+ - done: -- path->mnt = mnt; -- path->dentry = dentry; -- __follow_mount(path); -+ if (nd->path.mnt != path->mnt) { -+ nd->um_flags |= LAST_LOWLEVEL; -+ follow_mount(path); -+ } else -+ __follow_mount(path); -+ follow_union_mount(path); - return 0; - - need_lookup: -- dentry = real_lookup(nd->path.dentry, name, nd); -- if (IS_ERR(dentry)) -+ err = real_lookup(nd, name, path); -+ if (err) -+ goto fail; -+ goto done; -+ -+need_union_lookup: -+ err = cache_lookup_union(nd, name, path); -+ if (!err && path->dentry) -+ goto done; -+ -+ err = real_lookup_union(nd, name, path); -+ if (err) - goto fail; - goto done; - - need_revalidate: -- dentry = do_revalidate(dentry, nd); -- if (!dentry) -+ path->dentry = do_revalidate(path->dentry, nd); -+ if (!path->dentry) - goto need_lookup; -- if (IS_ERR(dentry)) -+ if (IS_ERR(path->dentry)) { -+ err = PTR_ERR(path->dentry); - goto fail; -+ } - goto done; - - fail: -- return PTR_ERR(dentry); -+ return err; - } - - /* -@@ -845,6 +1242,8 @@ static int __link_path_walk(const char * - if (nd->depth) - lookup_flags = LOOKUP_FOLLOW | (nd->flags & LOOKUP_CONTINUE); - -+ follow_union_mount(&nd->path); -+ - /* At this point we know we have a real path component. */ - for(;;) { - unsigned long hash; -@@ -913,6 +1312,44 @@ static int __link_path_walk(const char * - if (err) - break; - -+ /* -+ * We want to create this element on the top level -+ * file system in two cases: -+ * -+ * - We are specifically told to - LOOKUP_TOPMOST. -+ * - This is a directory, and it does not yet exist on -+ * the top level. Various tricks only work if -+ * directories always exist on the top level. -+ * -+ * In either case, only create this element on the top -+ * level if the last element is located on the lower -+ * level. If the last element is located on the top -+ * level, then every single element in the path -+ * already exists on the top level. -+ * -+ * Note that we can assume that the parent is on the -+ * top level since we always create the directory on -+ * the top level. -+ */ -+ -+ if ((nd->um_flags & LAST_LOWLEVEL) && -+ ((next.dentry->d_inode && -+ S_ISDIR(next.dentry->d_inode->i_mode) && -+ (nd->path.mnt != next.mnt)) || -+ (nd->flags & LOOKUP_TOPMOST))) { -+ struct dentry *dentry; -+ -+ dentry = union_create_topmost(nd, &this, &next); -+ if (IS_ERR(dentry)) { -+ err = PTR_ERR(dentry); -+ goto out_dput; -+ } -+ path_put_conditional(&next, nd); -+ next.mnt = nd->path.mnt; -+ next.dentry = dentry; -+ nd->um_flags &= ~LAST_LOWLEVEL; -+ } -+ - err = -ENOENT; - inode = next.dentry->d_inode; - if (!inode) -@@ -962,6 +1399,25 @@ last_component: - err = do_lookup(nd, &this, &next); - if (err) - break; -+ -+ if ((nd->um_flags & LAST_LOWLEVEL) && -+ ((next.dentry->d_inode && -+ S_ISDIR(next.dentry->d_inode->i_mode) && -+ (nd->path.mnt != next.mnt)) || -+ (nd->flags & LOOKUP_TOPMOST))) { -+ struct dentry *dentry; -+ -+ dentry = union_create_topmost(nd, &this, &next); -+ if (IS_ERR(dentry)) { -+ err = PTR_ERR(dentry); -+ goto out_dput; -+ } -+ path_put_conditional(&next, nd); -+ next.mnt = nd->path.mnt; -+ next.dentry = dentry; -+ nd->um_flags &= ~LAST_LOWLEVEL; -+ } -+ - inode = next.dentry->d_inode; - if ((lookup_flags & LOOKUP_FOLLOW) - && inode && inode->i_op->follow_link) { -@@ -1029,6 +1485,7 @@ static int path_init(int dfd, const char - - nd->last_type = LAST_ROOT; /* if there are only slashes... */ - nd->flags = flags; -+ nd->um_flags = 0; - nd->depth = 0; - nd->root.mnt = NULL; - -@@ -1172,61 +1629,437 @@ static int path_lookup_open(int dfd, con - } - - static struct dentry *__lookup_hash(struct qstr *name, -- struct dentry *base, struct nameidata *nd) -+ struct dentry *base, struct nameidata *nd) -+{ -+ struct dentry *dentry; -+ struct inode *inode; -+ int err; -+ -+ inode = base->d_inode; -+ -+ /* -+ * See if the low-level filesystem might want -+ * to use its own hash.. -+ */ -+ if (base->d_op && base->d_op->d_hash) { -+ err = base->d_op->d_hash(base, name); -+ dentry = ERR_PTR(err); -+ if (err < 0) -+ goto out; -+ } -+ -+ dentry = cache_lookup(base, name, nd); -+ if (!dentry) { -+ struct dentry *new; -+ -+ /* Don't create child dentry for a dead directory. */ -+ dentry = ERR_PTR(-ENOENT); -+ if (IS_DEADDIR(inode)) -+ goto out; -+ -+ new = d_alloc(base, name); -+ dentry = ERR_PTR(-ENOMEM); -+ if (!new) -+ goto out; -+ dentry = inode->i_op->lookup(inode, new, nd); -+ if (!dentry) -+ dentry = new; -+ else -+ dput(new); -+ } -+out: -+ return dentry; -+} -+ -+/* -+ * Restricted form of lookup. Doesn't follow links, single-component only, -+ * needs parent already locked. Doesn't follow mounts. -+ * SMP-safe. -+ */ -+static int lookup_hash(struct nameidata *nd, struct qstr *name, -+ struct path *path) -+{ -+ int err; -+ -+ err = inode_permission(nd->path.dentry->d_inode, MAY_EXEC); -+ if (err) -+ return err; -+ path->mnt = nd->path.mnt; -+ path->dentry = __lookup_hash(name, nd->path.dentry, nd); -+ if (IS_ERR(path->dentry)) { -+ err = PTR_ERR(path->dentry); -+ path->dentry = NULL; -+ path->mnt = NULL; -+ } -+ return err; -+} -+ -+static int __hash_lookup_topmost(struct nameidata *nd, struct qstr *name, -+ struct path *path) -+{ -+ struct path next; -+ int err; -+ -+ err = lookup_hash(nd, name, path); -+ if (err) -+ return err; -+ -+ if (path->dentry->d_inode || d_is_whiteout(path->dentry)) -+ return 0; -+ -+ if (IS_OPAQUE(nd->path.dentry->d_inode) && !d_is_fallthru(path->dentry)) -+ return 0; -+ -+ while (follow_union_down(&nd->path)) { -+ name->hash = full_name_hash(name->name, name->len); -+ if (nd->path.dentry->d_op && nd->path.dentry->d_op->d_hash) { -+ err = nd->path.dentry->d_op->d_hash(nd->path.dentry, -+ name); -+ if (err < 0) -+ goto out; -+ } -+ -+ mutex_lock(&nd->path.dentry->d_inode->i_mutex); -+ err = lookup_hash(nd, name, &next); -+ mutex_unlock(&nd->path.dentry->d_inode->i_mutex); -+ if (err) -+ goto out; -+ -+ if (next.dentry->d_inode || d_is_whiteout(next.dentry)) { -+ dput(path->dentry); -+ mntget(next.mnt); -+ *path = next; -+ goto out; -+ } -+ -+ if (IS_OPAQUE(nd->path.dentry->d_inode) && !d_is_fallthru(next.dentry)) -+ goto out; -+ -+ dput(next.dentry); -+ } -+out: -+ if (err) -+ dput(path->dentry); -+ return err; -+} -+ -+static int __hash_lookup_build_union(struct nameidata *nd, struct qstr *name, -+ struct path *path) -+{ -+ struct path last = *path; -+ struct path next; -+ int err = 0; -+ -+ while (follow_union_down(&nd->path)) { -+ /* We need to recompute the hash for lower layer lookups */ -+ name->hash = full_name_hash(name->name, name->len); -+ if (nd->path.dentry->d_op && nd->path.dentry->d_op->d_hash) { -+ err = nd->path.dentry->d_op->d_hash(nd->path.dentry, -+ name); -+ if (err < 0) -+ goto out; -+ } -+ -+ mutex_lock(&nd->path.dentry->d_inode->i_mutex); -+ err = lookup_hash(nd, name, &next); -+ mutex_unlock(&nd->path.dentry->d_inode->i_mutex); -+ if (err) -+ goto out; -+ -+ if (d_is_whiteout(next.dentry)) { -+ dput(next.dentry); -+ break; -+ } -+ -+ if (!next.dentry->d_inode) { -+ dput(next.dentry); -+ continue; -+ } -+ -+ /* only directories can be part of a union stack */ -+ if (!S_ISDIR(next.dentry->d_inode->i_mode)) { -+ dput(next.dentry); -+ break; -+ } -+ -+ /* now we know we found something "real" */ -+ append_to_union(last.mnt, last.dentry, next.mnt, next.dentry); -+ -+ if (last.dentry != path->dentry) -+ path_put(&last); -+ last.dentry = next.dentry; -+ last.mnt = mntget(next.mnt); -+ } -+ -+ if (last.dentry != path->dentry) -+ path_put(&last); -+out: -+ return err; -+} -+ -+int hash_lookup_union(struct nameidata *nd, struct qstr *name, -+ struct path *path) -+{ -+ struct path safe = { .dentry = nd->path.dentry, .mnt = nd->path.mnt }; -+ int res ; -+ -+ path_get(&safe); -+ res = __hash_lookup_topmost(nd, name, path); -+ if (res) -+ goto out; -+ -+ /* only directories can be part of a union stack */ -+ if (!path->dentry->d_inode || -+ !S_ISDIR(path->dentry->d_inode->i_mode)) -+ goto out; -+ -+ /* Build the union stack for this part */ -+ res = __hash_lookup_build_union(nd, name, path); -+ if (res) { -+ dput(path->dentry); -+ if (path->mnt != safe.mnt) -+ mntput(path->mnt); -+ goto out; -+ } -+ -+out: -+ path_put(&nd->path); -+ nd->path.dentry = safe.dentry; -+ nd->path.mnt = safe.mnt; -+ return res; -+} -+ -+/** -+ * do_union_hash_lookup() - walk down the union stack and lookup_hash() -+ * @nd: nameidata of parent to lookup from -+ * @name: pathname component to lookup -+ * @path: path to store result of lookup in -+ * -+ * Walk down the union stack and search for single pathname component name. It -+ * is assumed that the caller already did a lookup_hash() in the topmost parent -+ * that gave negative lookup result. Therefore this does call lookup_hash() in -+ * every lower layer (!) of the union stack. If a directory is found the union -+ * stack for that is assembled as well. -+ * -+ * Note: -+ * The caller needs to take care of holding a valid reference to the topmost -+ * parent. -+ * On error we leave @path untouched as well as when we don't find anything. -+ */ -+static int do_union_hash_lookup(struct nameidata *nd, struct qstr *name, -+ struct path *path) -+{ -+ struct path next; -+ int err = 0; -+ -+ while (follow_union_down(&nd->path)) { -+ /* rehash because of d_op->d_hash() by the previous layer */ -+ name->hash = full_name_hash(name->name, name->len); -+ -+ mutex_lock(&nd->path.dentry->d_inode->i_mutex); -+ err = lookup_hash(nd, name, &next); -+ mutex_unlock(&nd->path.dentry->d_inode->i_mutex); -+ -+ if (err) -+ break; -+ -+ if (next.dentry->d_inode) { -+ mntget(next.mnt); -+ if (!S_ISDIR(next.dentry->d_inode->i_mode)) { -+ *path = next; -+ break; -+ } -+ err = __hash_lookup_build_union(nd, name, &next); -+ if (err) -+ path_put(&next); -+ else -+ *path = next; -+ break; -+ } -+ -+ path_put_conditional(&next, nd); -+ -+ if ((IS_OPAQUE(nd->path.dentry->d_inode) && -+ !d_is_fallthru(next.dentry)) || -+ d_is_whiteout(next.dentry)) -+ break; -+ } -+ -+ return err; -+} -+ -+/** -+ * _hash_lookup_union() - lookup single pathname component -+ * @nd: nameidata of parent to lookup from -+ * @name: pathname component to lookup -+ * @path: path to store result of lookup in -+ * -+ * Returns the topmost parent locked and the target dentry found in the union -+ * or the topmost negative target dentry otherwise. -+ * -+ * Note: -+ * Returns topmost parent locked even on error. -+ */ -+static int _hash_lookup_union(struct nameidata *nd, struct qstr *name, -+ struct path *path) -+{ -+ struct path parent = nd->path; -+ struct path topmost; -+ int err; -+ -+ mutex_lock(&nd->path.dentry->d_inode->i_mutex); -+ err = lookup_hash(nd, name, path); -+ if (err) -+ return err; -+ -+ /* return if we found something and it isn't a directory we are done */ -+ if (path->dentry->d_inode && !S_ISDIR(path->dentry->d_inode->i_mode)) -+ return 0; -+ -+ /* stop lookup if the parent directory is marked opaque */ -+ if ((IS_OPAQUE(nd->path.dentry->d_inode) && -+ !d_is_fallthru(path->dentry)) || -+ d_is_whiteout(path->dentry)) -+ return 0; -+ -+ if (!strcmp(path->mnt->mnt_sb->s_type->name, "proc") || -+ !strcmp(path->mnt->mnt_sb->s_type->name, "sysfs")) -+ return 0; -+ -+ mutex_unlock(&nd->path.dentry->d_inode->i_mutex); -+ -+ /* -+ * safe a reference to the topmost parent for walking the union stack -+ */ -+ path_get(&parent); -+ topmost = *path; -+ -+ if (path->dentry->d_inode && S_ISDIR(path->dentry->d_inode->i_mode)) { -+ err = __hash_lookup_build_union(nd, name, path); -+ if (err) -+ goto err_lock_parent; -+ goto out_lock_and_revalidate_parent; -+ } -+ -+ err = do_union_hash_lookup(nd, name, path); -+ if (err) -+ goto err_lock_parent; -+ -+out_lock_and_revalidate_parent: -+ /* seems that we haven't found anything, so return the topmost */ -+ path_to_nameidata(&parent, nd); -+ mutex_lock(&nd->path.dentry->d_inode->i_mutex); -+ -+ if (topmost.dentry == path->dentry) { -+ spin_lock(&path->dentry->d_lock); -+ if (nd->path.dentry != path->dentry->d_parent) { -+ spin_unlock(&path->dentry->d_lock); -+ dput(path->dentry); -+ name->hash = full_name_hash(name->name, name->len); -+ err = lookup_hash(nd, name, path); -+ if (err) -+ return err; -+ /* FIXME: What if we find a directory here ... */ -+ return err; -+ } -+ spin_unlock(&path->dentry->d_lock); -+ } else -+ dput(topmost.dentry); -+ -+ return 0; -+ -+err_lock_parent: -+ path_to_nameidata(&parent, nd); -+ path_put_conditional(path, nd); -+ mutex_lock(&nd->path.dentry->d_inode->i_mutex); -+ return err; -+} -+ -+/** -+ * lookup_rename_source() - lookup the source used by rename -+ * -+ * This is a special version of _hash_lookup_union() which becomes necessary -+ * for finding the source of a rename on union mounts. -+ * -+ * See comment for _hash_lookup_union() above. -+ */ -+static int lookup_rename_source(struct nameidata *oldnd, -+ struct nameidata *newnd, -+ struct dentry **trap, struct qstr *name, -+ struct path *old) - { -- struct dentry *dentry; -- struct inode *inode; -+ struct path parent = oldnd->path; -+ struct path topmost; - int err; - -- inode = base->d_inode; -+ err = lookup_hash(oldnd, name, old); -+ if (err) -+ return err; -+ -+ /* return if we found something and it isn't a directory we are done */ -+ if (old->dentry->d_inode && !S_ISDIR(old->dentry->d_inode->i_mode)) -+ return 0; -+ -+ /* stop lookup if the parent directory is marked opaque */ -+ if ((IS_OPAQUE(oldnd->path.dentry->d_inode) && -+ !d_is_fallthru(old->dentry)) || -+ d_is_whiteout(old->dentry)) -+ return 0; -+ -+ if (!strcmp(old->mnt->mnt_sb->s_type->name, "proc") || -+ !strcmp(old->mnt->mnt_sb->s_type->name, "sysfs")) -+ return 0; -+ -+ unlock_rename(oldnd->path.dentry, newnd->path.dentry); - - /* -- * See if the low-level filesystem might want -- * to use its own hash.. -+ * safe a reference to the topmost parent for walking the union stack - */ -- if (base->d_op && base->d_op->d_hash) { -- err = base->d_op->d_hash(base, name); -- dentry = ERR_PTR(err); -- if (err < 0) -- goto out; -+ path_get(&parent); -+ topmost = *old; -+ -+ if (old->dentry->d_inode && S_ISDIR(old->dentry->d_inode->i_mode)) { -+ err = __hash_lookup_build_union(oldnd, name, old); -+ if (err) -+ goto err_lock; -+ goto out_lock_and_revalidate_parent; - } - -- dentry = cached_lookup(base, name, nd); -- if (!dentry) { -- struct dentry *new; -+ err = do_union_hash_lookup(oldnd, name, old); -+ if (err) -+ goto err_lock; - -- /* Don't create child dentry for a dead directory. */ -- dentry = ERR_PTR(-ENOENT); -- if (IS_DEADDIR(inode)) -- goto out; -+out_lock_and_revalidate_parent: -+ path_to_nameidata(&parent, oldnd); -+ *trap = lock_rename(oldnd->path.dentry, newnd->path.dentry); - -- new = d_alloc(base, name); -- dentry = ERR_PTR(-ENOMEM); -- if (!new) -- goto out; -- dentry = inode->i_op->lookup(inode, new, nd); -- if (!dentry) -- dentry = new; -- else -- dput(new); -- } --out: -- return dentry; --} -+ /* -+ * If we return the topmost dentry we have to make sure that it has not -+ * been moved away while we gave up the topmost parents i_mutex lock. -+ */ -+ if (topmost.dentry == old->dentry) { -+ spin_lock(&old->dentry->d_lock); -+ if (oldnd->path.dentry != old->dentry->d_parent) { -+ spin_unlock(&old->dentry->d_lock); -+ dput(old->dentry); -+ name->hash = full_name_hash(name->name, name->len); -+ err = lookup_hash(oldnd, name, old); -+ if (err) -+ return err; -+ /* FIXME: What if we find a directory here ... */ -+ return err; -+ } -+ spin_unlock(&old->dentry->d_lock); -+ } else -+ dput(topmost.dentry); - --/* -- * Restricted form of lookup. Doesn't follow links, single-component only, -- * needs parent already locked. Doesn't follow mounts. -- * SMP-safe. -- */ --static struct dentry *lookup_hash(struct nameidata *nd) --{ -- int err; -+ return 0; - -- err = inode_permission(nd->path.dentry->d_inode, MAY_EXEC); -- if (err) -- return ERR_PTR(err); -- return __lookup_hash(&nd->last, nd->path.dentry, nd); -+err_lock: -+ path_to_nameidata(&parent, oldnd); -+ path_put_conditional(old, oldnd); -+ *trap = lock_rename(oldnd->path.dentry, newnd->path.dentry); -+ return err; - } - - static int __lookup_one_len(const char *name, struct qstr *this, -@@ -1502,8 +2335,9 @@ int vfs_create(struct inode *dir, struct - return error; - } - --int may_open(struct path *path, int acc_mode, int flag) -+int may_open(struct nameidata *nd, int acc_mode, int flag) - { -+ struct path *path = &nd->path; - struct dentry *dentry = path->dentry; - struct inode *inode = dentry->d_inode; - int error; -@@ -1529,7 +2363,7 @@ int may_open(struct path *path, int acc_ - break; - } - -- error = inode_permission(inode, acc_mode); -+ error = union_permission(path, acc_mode); - if (error) - return error; - -@@ -1577,6 +2411,9 @@ int may_open(struct path *path, int acc_ - if (!error) - error = security_path_truncate(path, 0, - ATTR_MTIME|ATTR_CTIME|ATTR_OPEN); -+ /* XXX don't copy up file data */ -+ if (is_unionized(path->dentry, path->mnt)) -+ error = union_copyup(nd, flag /* XXX not used */); - if (!error) { - vfs_dq_init(inode); - -@@ -1623,7 +2460,7 @@ out_unlock: - if (error) - return error; - /* Don't check for write permission, don't truncate */ -- return may_open(&nd->path, 0, flag & ~O_TRUNC); -+ return may_open(nd, 0, flag & ~O_TRUNC); - } - - /* -@@ -1738,12 +2575,10 @@ struct file *do_filp_open(int dfd, const - if (flag & O_EXCL) - nd.flags |= LOOKUP_EXCL; - mutex_lock(&dir->d_inode->i_mutex); -- path.dentry = lookup_hash(&nd); -- path.mnt = nd.path.mnt; -+ error = hash_lookup_union(&nd, &nd.last, &path); - - do_last: -- error = PTR_ERR(path.dentry); -- if (IS_ERR(path.dentry)) { -+ if (error) { - mutex_unlock(&dir->d_inode->i_mutex); - goto exit; - } -@@ -1803,10 +2638,23 @@ do_last: - if (path.dentry->d_inode->i_op->follow_link) - goto do_link; - -- path_to_nameidata(&path, &nd); - error = -EISDIR; - if (path.dentry->d_inode && S_ISDIR(path.dentry->d_inode->i_mode)) -- goto exit; -+ goto exit_dput; -+ -+ /* -+ * If this file is on a lower layer of the union stack, copy it to the -+ * topmost layer before opening it -+ */ -+ if (path.dentry->d_inode && -+ (path.dentry->d_parent != dir) && -+ S_ISREG(path.dentry->d_inode->i_mode)) { -+ error = __union_copyup(&path, &nd, &path); -+ if (error) -+ goto exit_dput; -+ } -+ -+ path_to_nameidata(&path, &nd); - ok: - /* - * Consider: -@@ -1824,12 +2672,18 @@ ok: - if (error) - goto exit; - } -- error = may_open(&nd.path, acc_mode, flag); -+ error = may_open(&nd, acc_mode, flag); - if (error) { - if (will_write) - mnt_drop_write(nd.path.mnt); - goto exit; - } -+ /* Okay, all permissions go, now copy up */ -+ if (!(flag & O_CREAT) && (flag & FMODE_WRITE)) { -+ error = union_copyup(&nd, flag /* XXX not used */); -+ if (error) -+ goto exit; -+ } - filp = nameidata_to_filp(&nd, open_flag); - if (IS_ERR(filp)) - ima_counts_put(&nd.path, -@@ -1904,8 +2758,7 @@ do_link: - } - dir = nd.path.dentry; - mutex_lock(&dir->d_inode->i_mutex); -- path.dentry = lookup_hash(&nd); -- path.mnt = nd.path.mnt; -+ error = hash_lookup_union(&nd, &nd.last, &path); - __putname(nd.last.name); - goto do_last; - } -@@ -1939,7 +2792,8 @@ EXPORT_SYMBOL(filp_open); - */ - struct dentry *lookup_create(struct nameidata *nd, int is_dir) - { -- struct dentry *dentry = ERR_PTR(-EEXIST); -+ struct path path = { .dentry = ERR_PTR(-EEXIST) } ; -+ int err; - - mutex_lock_nested(&nd->path.dentry->d_inode->i_mutex, I_MUTEX_PARENT); - /* -@@ -1955,11 +2809,13 @@ struct dentry *lookup_create(struct name - /* - * Do the final lookup. - */ -- dentry = lookup_hash(nd); -- if (IS_ERR(dentry)) -+ err = hash_lookup_union(nd, &nd->last, &path); -+ if (err) { -+ path.dentry = ERR_PTR(err); - goto fail; -+ } - -- if (dentry->d_inode) -+ if (path.dentry->d_inode) - goto eexist; - /* - * Special case - lookup gave negative, but... we had foo/bar/ -@@ -1968,15 +2824,17 @@ struct dentry *lookup_create(struct name - * been asking for (non-existent) directory. -ENOENT for you. - */ - if (unlikely(!is_dir && nd->last.name[nd->last.len])) { -- dput(dentry); -- dentry = ERR_PTR(-ENOENT); -+ path_put_conditional(&path, nd); -+ path.dentry = ERR_PTR(-ENOENT); - } -- return dentry; -+ if (nd->path.mnt != path.mnt) -+ mntput(path.mnt); -+ return path.dentry; - eexist: -- dput(dentry); -- dentry = ERR_PTR(-EEXIST); -+ path_put_conditional(&path, nd); -+ path.dentry = ERR_PTR(-EEXIST); - fail: -- return dentry; -+ return path.dentry; - } - EXPORT_SYMBOL_GPL(lookup_create); - -@@ -2088,6 +2946,7 @@ SYSCALL_DEFINE3(mknod, const char __user - int vfs_mkdir(struct inode *dir, struct dentry *dentry, int mode) - { - int error = may_create(dir, dentry); -+ int opaque = 0; - - if (error) - return error; -@@ -2101,9 +2960,18 @@ int vfs_mkdir(struct inode *dir, struct - return error; - - vfs_dq_init(dir); -+ -+ if (d_is_whiteout(dentry)) -+ opaque = 1; -+ - error = dir->i_op->mkdir(dir, dentry, mode); -- if (!error) -+ if (!error) { - fsnotify_mkdir(dir, dentry); -+ if (opaque) { -+ dentry->d_inode->i_flags |= S_OPAQUE; -+ mark_inode_dirty(dentry->d_inode); -+ } -+ } - return error; - } - -@@ -2149,6 +3017,212 @@ SYSCALL_DEFINE2(mkdir, const char __user - return sys_mkdirat(AT_FDCWD, pathname, mode); - } - -+ -+/* Checks on the victim for whiteout */ -+static inline int may_whiteout(struct inode *dir, struct dentry *victim, -+ int isdir) -+{ -+ int err; -+ -+ /* from may_create() */ -+ if (IS_DEADDIR(dir)) -+ return -ENOENT; -+ err = inode_permission(dir, MAY_WRITE | MAY_EXEC); -+ if (err) -+ return err; -+ -+ /* from may_delete() */ -+ if (IS_APPEND(dir)) -+ return -EPERM; -+ if (!victim->d_inode) -+ return 0; -+ if (check_sticky(dir, victim->d_inode) || -+ IS_APPEND(victim->d_inode) || -+ IS_IMMUTABLE(victim->d_inode)) -+ return -EPERM; -+ if (isdir) { -+ if (!S_ISDIR(victim->d_inode->i_mode)) -+ return -ENOTDIR; -+ if (IS_ROOT(victim)) -+ return -EBUSY; -+ } else if (S_ISDIR(victim->d_inode->i_mode)) -+ return -EISDIR; -+ if (victim->d_flags & DCACHE_NFSFS_RENAMED) -+ return -EBUSY; -+ return 0; -+} -+ -+/** -+ * vfs_whiteout: creates a white-out for the given directory entry -+ * @dir: parent inode -+ * @dentry: directory entry to white-out -+ * -+ * Simply white-out a given directory entry. This functionality is usually used -+ * in the sense of unlink. Therefore the given dentry can still be in-use and -+ * contains an in-use inode. The filesystem has to do what unlink or rmdir -+ * would in that case. Since the dentry still might be in-use we have to -+ * provide a fresh unhashed dentry that whiteout can fill the new inode into. -+ * In that case the given dentry is dropped and the fresh dentry containing the -+ * whiteout is rehashed instead. If the given dentry is unused, the whiteout -+ * inode is instantiated into it instead. -+ * -+ * After this returns with success, don't make any assumptions about the inode. -+ * Just dput() it dentry. -+ */ -+static int vfs_whiteout(struct inode *dir, struct dentry *dentry, int isdir) -+{ -+ int err; -+ struct inode *old_inode = dentry->d_inode; -+ struct dentry *parent, *whiteout; -+ -+ err = may_whiteout(dir, dentry, isdir); -+ if (err) -+ return err; -+ -+ BUG_ON(dentry->d_parent->d_inode != dir); -+ -+ if (!dir->i_op || !dir->i_op->whiteout) -+ return -EOPNOTSUPP; -+ -+ if (old_inode) { -+ vfs_dq_init(dir); -+ -+ mutex_lock(&old_inode->i_mutex); -+ if (isdir) -+ dentry_unhash(dentry); -+ if (d_mountpoint(dentry)) -+ err = -EBUSY; -+ else { -+ if (isdir) -+ err = security_inode_rmdir(dir, dentry); -+ else -+ err = security_inode_unlink(dir, dentry); -+ } -+ } -+ -+ parent = dget_parent(dentry); -+ whiteout = d_alloc_name(parent, dentry->d_name.name); -+ -+ if (!err) -+ err = dir->i_op->whiteout(dir, dentry, whiteout); -+ -+ if (old_inode) { -+ mutex_unlock(&old_inode->i_mutex); -+ if (!err) { -+ fsnotify_link_count(old_inode); -+ d_delete(dentry); -+ } -+ if (isdir) -+ dput(dentry); -+ } -+ -+ dput(whiteout); -+ dput(parent); -+ return err; -+} -+ -+int path_whiteout(struct path *dir_path, struct dentry *dentry, int isdir) -+{ -+ int error = mnt_want_write(dir_path->mnt); -+ -+ if (!error) { -+ error = vfs_whiteout(dir_path->dentry->d_inode, dentry, isdir); -+ mnt_drop_write(dir_path->mnt); -+ } -+ -+ return error; -+} -+EXPORT_SYMBOL(path_whiteout); -+ -+/* -+ * This is abusing readdir to check if a union directory is logically empty. -+ * Al Viro barfed when he saw this, but Val said: "Well, at this point I'm -+ * aiming for working, pretty can come later" -+ */ -+static int filldir_is_empty(void *__buf, const char *name, int namlen, -+ loff_t offset, u64 ino, unsigned int d_type) -+{ -+ int *is_empty = (int *)__buf; -+ -+ switch (namlen) { -+ case 2: -+ if (name[1] != '.') -+ break; -+ case 1: -+ if (name[0] != '.') -+ break; -+ return 0; -+ } -+ -+ if (d_type == DT_WHT) -+ return 0; -+ -+ (*is_empty) = 0; -+ return 0; -+} -+ -+static int directory_is_empty(struct dentry *dentry, struct vfsmount *mnt) -+{ -+ struct file *file; -+ int err; -+ int is_empty = 1; -+ -+ BUG_ON(!S_ISDIR(dentry->d_inode->i_mode)); -+ -+ /* references for the file pointer */ -+ dget(dentry); -+ mntget(mnt); -+ -+ file = dentry_open(dentry, mnt, O_RDONLY, current_cred()); -+ if (IS_ERR(file)) -+ return 0; -+ -+ err = vfs_readdir(file, filldir_is_empty, &is_empty); -+ -+ fput(file); -+ return is_empty; -+} -+ -+static int do_whiteout(struct nameidata *nd, struct path *path, int isdir) -+{ -+ struct path safe = { .dentry = dget(nd->path.dentry), -+ .mnt = mntget(nd->path.mnt) }; -+ struct dentry *dentry = path->dentry; -+ int err; -+ -+ err = may_whiteout(nd->path.dentry->d_inode, dentry, isdir); -+ if (err) -+ goto out; -+ -+ err = -ENOENT; -+ if (!dentry->d_inode) -+ goto out; -+ -+ err = -ENOTEMPTY; -+ if (isdir && !directory_is_empty(path->dentry, path->mnt)) -+ goto out; -+ -+ if (nd->path.dentry != dentry->d_parent) { -+ dentry = __lookup_hash(&path->dentry->d_name, nd->path.dentry, -+ nd); -+ err = PTR_ERR(dentry); -+ if (IS_ERR(dentry)) -+ goto out; -+ -+ dput(path->dentry); -+ if (path->mnt != safe.mnt) -+ mntput(path->mnt); -+ path->mnt = nd->path.mnt; -+ path->dentry = dentry; -+ } -+ -+ err = vfs_whiteout(nd->path.dentry->d_inode, dentry, isdir); -+ -+out: -+ path_put(&safe); -+ return err; -+} -+ - /* - * We try to drop the dentry early: we should have - * a usage count of 2 if we're the only user of this -@@ -2213,7 +3287,7 @@ static long do_rmdir(int dfd, const char - { - int error = 0; - char * name; -- struct dentry *dentry; -+ struct path path; - struct nameidata nd; - - error = user_path_parent(dfd, pathname, &nd, &name); -@@ -2235,21 +3309,24 @@ static long do_rmdir(int dfd, const char - nd.flags &= ~LOOKUP_PARENT; - - mutex_lock_nested(&nd.path.dentry->d_inode->i_mutex, I_MUTEX_PARENT); -- dentry = lookup_hash(&nd); -- error = PTR_ERR(dentry); -- if (IS_ERR(dentry)) -+ error = hash_lookup_union(&nd, &nd.last, &path); -+ if (error) - goto exit2; -+ if (is_unionized(nd.path.dentry, nd.path.mnt)) { -+ error = do_whiteout(&nd, &path, 1); -+ goto exit3; -+ } - error = mnt_want_write(nd.path.mnt); - if (error) - goto exit3; -- error = security_path_rmdir(&nd.path, dentry); -+ error = security_path_rmdir(&nd.path, path.dentry); - if (error) - goto exit4; -- error = vfs_rmdir(nd.path.dentry->d_inode, dentry); -+ error = vfs_rmdir(nd.path.dentry->d_inode, path.dentry); - exit4: - mnt_drop_write(nd.path.mnt); - exit3: -- dput(dentry); -+ path_put_conditional(&path, &nd); - exit2: - mutex_unlock(&nd.path.dentry->d_inode->i_mutex); - exit1: -@@ -2304,7 +3381,7 @@ static long do_unlinkat(int dfd, const c - { - int error; - char *name; -- struct dentry *dentry; -+ struct path path; - struct nameidata nd; - struct inode *inode = NULL; - -@@ -2319,26 +3396,29 @@ static long do_unlinkat(int dfd, const c - nd.flags &= ~LOOKUP_PARENT; - - mutex_lock_nested(&nd.path.dentry->d_inode->i_mutex, I_MUTEX_PARENT); -- dentry = lookup_hash(&nd); -- error = PTR_ERR(dentry); -- if (!IS_ERR(dentry)) { -+ error = hash_lookup_union(&nd, &nd.last, &path); -+ if (!error) { - /* Why not before? Because we want correct error value */ - if (nd.last.name[nd.last.len]) - goto slashes; -- inode = dentry->d_inode; -+ inode = path.dentry->d_inode; - if (inode) - atomic_inc(&inode->i_count); -+ if (is_unionized(nd.path.dentry, nd.path.mnt)) { -+ error = do_whiteout(&nd, &path, 0); -+ goto exit2; -+ } - error = mnt_want_write(nd.path.mnt); - if (error) - goto exit2; -- error = security_path_unlink(&nd.path, dentry); -+ error = security_path_unlink(&nd.path, path.dentry); - if (error) - goto exit3; -- error = vfs_unlink(nd.path.dentry->d_inode, dentry); -+ error = vfs_unlink(nd.path.dentry->d_inode, path.dentry); - exit3: - mnt_drop_write(nd.path.mnt); - exit2: -- dput(dentry); -+ path_put_conditional(&path, &nd); - } - mutex_unlock(&nd.path.dentry->d_inode->i_mutex); - if (inode) -@@ -2349,8 +3429,8 @@ exit1: - return error; - - slashes: -- error = !dentry->d_inode ? -ENOENT : -- S_ISDIR(dentry->d_inode->i_mode) ? -EISDIR : -ENOTDIR; -+ error = !path.dentry->d_inode ? -ENOENT : -+ S_ISDIR(path.dentry->d_inode->i_mode) ? -EISDIR : -ENOTDIR; - goto exit2; - } - -@@ -2686,11 +3766,96 @@ int vfs_rename(struct inode *old_dir, st - return error; - } - -+static int vfs_rename_union(struct nameidata *oldnd, struct path *old, -+ struct nameidata *newnd, struct path *new) -+{ -+ struct inode *old_dir = oldnd->path.dentry->d_inode; -+ struct inode *new_dir = newnd->path.dentry->d_inode; -+ struct qstr old_name; -+ char *name; -+ struct dentry *dentry; -+ int error; -+ -+ if (old->dentry->d_inode == new->dentry->d_inode) -+ return 0; -+ error = may_whiteout(old_dir, old->dentry, 0); -+ if (error) -+ return error; -+ if (!old_dir->i_op || !old_dir->i_op->whiteout) -+ return -EPERM; -+ -+ if (!new->dentry->d_inode) -+ error = may_create(new_dir, new->dentry); -+ else -+ error = may_delete(new_dir, new->dentry, 0); -+ if (error) -+ return error; -+ -+ vfs_dq_init(old_dir); -+ vfs_dq_init(new_dir); -+ -+ error = -EBUSY; -+ if (d_mountpoint(old->dentry) || d_mountpoint(new->dentry)) -+ return error; -+ -+ error = -ENOMEM; -+ name = kmalloc(old->dentry->d_name.len, GFP_KERNEL); -+ if (!name) -+ return error; -+ strncpy(name, old->dentry->d_name.name, old->dentry->d_name.len); -+ name[old->dentry->d_name.len] = 0; -+ old_name.len = old->dentry->d_name.len; -+ old_name.hash = old->dentry->d_name.hash; -+ old_name.name = name; -+ -+ /* possibly delete the existing new file */ -+ if ((newnd->path.dentry == new->dentry->d_parent) && -+ new->dentry->d_inode) { -+ /* FIXME: inode may be truncated while we hold a lock */ -+ error = vfs_unlink(new_dir, new->dentry); -+ if (error) -+ goto freename; -+ -+ dentry = __lookup_hash(&new->dentry->d_name, -+ newnd->path.dentry, newnd); -+ if (IS_ERR(dentry)) -+ goto freename; -+ -+ dput(new->dentry); -+ new->dentry = dentry; -+ } -+ -+ /* copyup to the new file */ -+ error = __union_copyup(old, newnd, new); -+ if (error) -+ goto freename; -+ -+ /* whiteout the old file */ -+ dentry = __lookup_hash(&old_name, oldnd->path.dentry, oldnd); -+ error = PTR_ERR(dentry); -+ if (IS_ERR(dentry)) -+ goto freename; -+ error = vfs_whiteout(old_dir, dentry, 0); -+ dput(dentry); -+ -+ /* FIXME: This is acutally unlink() && create() ... */ -+/* -+ if (!error) { -+ const char *new_name = old_dentry->d_name.name; -+ fsnotify_move(old_dir, new_dir, old_name.name, new_name, 0, -+ new_dentry->d_inode, old_dentry->d_inode); -+ } -+*/ -+freename: -+ kfree(old_name.name); -+ return error; -+} -+ - SYSCALL_DEFINE4(renameat, int, olddfd, const char __user *, oldname, - int, newdfd, const char __user *, newname) - { - struct dentry *old_dir, *new_dir; -- struct dentry *old_dentry, *new_dentry; -+ struct path old, new; - struct dentry *trap; - struct nameidata oldnd, newnd; - char *from; -@@ -2724,16 +3889,28 @@ SYSCALL_DEFINE4(renameat, int, olddfd, c - - trap = lock_rename(new_dir, old_dir); - -- old_dentry = lookup_hash(&oldnd); -- error = PTR_ERR(old_dentry); -- if (IS_ERR(old_dentry)) -+ /* -+ * For union mounts we need to call a giant lookup_rename_source() -+ * instead. -+ * First lock_rename() and look on the topmost fs like you would do in -+ * the normal rename, if you find something which is not a directory, -+ * go ahead and lookup target and do normal rename. -+ * If you find a negative dentry, unlock_rename() and continue as -+ * _hash_lookup_union() would do without locking the topmost parent -+ * at the end. After that do lock_rename() of the source parent and the -+ * target parent and do a copyup with additional whiteout creation at -+ * the end. -+ */ -+// error = hash_lookup_union(&oldnd, &oldnd.last, &old); -+ error = lookup_rename_source(&oldnd, &newnd, &trap, &oldnd.last, &old); -+ if (error) - goto exit3; - /* source must exist */ - error = -ENOENT; -- if (!old_dentry->d_inode) -+ if (!old.dentry->d_inode) - goto exit4; - /* unless the source is a directory trailing slashes give -ENOTDIR */ -- if (!S_ISDIR(old_dentry->d_inode->i_mode)) { -+ if (!S_ISDIR(old.dentry->d_inode->i_mode)) { - error = -ENOTDIR; - if (oldnd.last.name[oldnd.last.len]) - goto exit4; -@@ -2742,32 +3919,44 @@ SYSCALL_DEFINE4(renameat, int, olddfd, c - } - /* source should not be ancestor of target */ - error = -EINVAL; -- if (old_dentry == trap) -+ if (old.dentry == trap) - goto exit4; -- new_dentry = lookup_hash(&newnd); -- error = PTR_ERR(new_dentry); -- if (IS_ERR(new_dentry)) -+ /* target is always on topmost fs, even with unions */ -+ error = lookup_hash(&newnd, &newnd.last, &new); -+ if (error) - goto exit4; - /* target should not be an ancestor of source */ - error = -ENOTEMPTY; -- if (new_dentry == trap) -+ if (new.dentry == trap) -+ goto exit5; -+ /* renaming of directories on unions is done by the user-space */ -+ error = -EXDEV; -+ if (is_unionized(oldnd.path.dentry, oldnd.path.mnt) && -+ S_ISDIR(old.dentry->d_inode->i_mode)) - goto exit5; -+// if (is_unionized(newnd.path.dentry, newnd.path.mnt)) -+// goto exit5; - - error = mnt_want_write(oldnd.path.mnt); - if (error) - goto exit5; -- error = security_path_rename(&oldnd.path, old_dentry, -- &newnd.path, new_dentry); -+ error = security_path_rename(&oldnd.path, old.dentry, -+ &newnd.path, new.dentry); - if (error) - goto exit6; -- error = vfs_rename(old_dir->d_inode, old_dentry, -- new_dir->d_inode, new_dentry); -+ if (is_unionized(oldnd.path.dentry, oldnd.path.mnt) && -+ (old.dentry->d_parent != oldnd.path.dentry)) { -+ error = vfs_rename_union(&oldnd, &old, &newnd, &new); -+ goto exit6; -+ } -+ error = vfs_rename(old_dir->d_inode, old.dentry, -+ new_dir->d_inode, new.dentry); - exit6: - mnt_drop_write(oldnd.path.mnt); - exit5: -- dput(new_dentry); -+ path_put_conditional(&new, &newnd); - exit4: -- dput(old_dentry); -+ path_put_conditional(&old, &oldnd); - exit3: - unlock_rename(new_dir, old_dir); - exit2: ---- a/fs/namespace.c -+++ b/fs/namespace.c -@@ -29,6 +29,7 @@ - #include - #include - #include -+#include - #include - #include - #include "pnode.h" -@@ -150,6 +151,9 @@ struct vfsmount *alloc_vfsmnt(const char - INIT_LIST_HEAD(&mnt->mnt_share); - INIT_LIST_HEAD(&mnt->mnt_slave_list); - INIT_LIST_HEAD(&mnt->mnt_slave); -+#ifdef CONFIG_UNION_MOUNT -+ INIT_LIST_HEAD(&mnt->mnt_unions); -+#endif - #ifdef CONFIG_SMP - mnt->mnt_writers = alloc_percpu(int); - if (!mnt->mnt_writers) -@@ -469,6 +473,7 @@ static void __touch_mnt_namespace(struct - - static void detach_mnt(struct vfsmount *mnt, struct path *old_path) - { -+ detach_mnt_union(mnt); - old_path->dentry = mnt->mnt_mountpoint; - old_path->mnt = mnt->mnt_parent; - mnt->mnt_parent = mnt; -@@ -492,6 +497,7 @@ static void attach_mnt(struct vfsmount * - list_add_tail(&mnt->mnt_hash, mount_hashtable + - hash(path->mnt, path->dentry)); - list_add_tail(&mnt->mnt_child, &path->mnt->mnt_mounts); -+ attach_mnt_union(mnt, path->mnt, path->dentry); - } - - /* -@@ -514,6 +520,7 @@ static void commit_tree(struct vfsmount - list_add_tail(&mnt->mnt_hash, mount_hashtable + - hash(parent, mnt->mnt_mountpoint)); - list_add_tail(&mnt->mnt_child, &parent->mnt_mounts); -+ attach_mnt_union(mnt, mnt->mnt_parent, mnt->mnt_mountpoint); - touch_mnt_namespace(n); - } - -@@ -770,6 +777,7 @@ static void show_mnt_opts(struct seq_fil - { MNT_NODIRATIME, ",nodiratime" }, - { MNT_RELATIME, ",relatime" }, - { MNT_STRICTATIME, ",strictatime" }, -+ { MNT_UNION, ",union" }, - { 0, NULL } - }; - const struct proc_fs_info *fs_infop; -@@ -984,6 +992,7 @@ void release_mounts(struct list_head *he - struct dentry *dentry; - struct vfsmount *m; - spin_lock(&vfsmount_lock); -+ detach_mnt_union(mnt); - dentry = mnt->mnt_mountpoint; - m = mnt->mnt_parent; - mnt->mnt_mountpoint = mnt->mnt_root; -@@ -1102,6 +1111,11 @@ static int do_umount(struct vfsmount *mn - spin_unlock(&vfsmount_lock); - if (retval) - security_sb_umount_busy(mnt); -+ /* If this was a union mount, we are no longer a read-only -+ * user on the underlying mount */ -+ if (mnt->mnt_flags & MNT_UNION) -+ mnt->mnt_parent->mnt_sb->s_readonly_users--; -+ - up_write(&namespace_sem); - release_mounts(&umount_list); - return retval; -@@ -1426,6 +1440,10 @@ static int do_change_type(struct path *p - if (path->dentry != path->mnt->mnt_root) - return -EINVAL; - -+ /* Don't change the type of union mounts */ -+ if (IS_MNT_UNION(path->mnt)) -+ return -EINVAL; -+ - down_write(&namespace_sem); - if (type == MS_SHARED) { - err = invent_group_ids(mnt, recurse); -@@ -1444,10 +1462,65 @@ static int do_change_type(struct path *p - } - - /* -+ * Mount-time check of upper and lower layer file systems to see if we -+ * can union mount one on the other. -+ * -+ * Union mounts must follow these rules: -+ * -+ * - The lower layer must be read-only. This avoids lots of nasty -+ * unsolvable races where file system structures disappear suddenly. -+ * XXX - Checking the vfsmnt for read-only is a temporary hack; the -+ * file system could be mounted read-write elsewhere. We need to -+ * enforce read-only at the superblock level (patches coming). -+ * -+ * - The upper layer must be writable. This isn't an absolute -+ * requirement; right now we need it to make readdir() work since we -+ * copy up directory entries to the top level. A possible -+ * workaround is to mount a tmpfs file system transparently over the -+ * top. -+ * -+ * - The upper layer must support whiteouts and fallthrus (if it is -+ * writeable). -+ * -+ * - The lower layer must not also be a union mount. This is just to -+ * make life simpler for now, there is no inherent limitation on the -+ * number of layers. -+ * -+ * XXX - Check other mount flags for incompatibilities - I'm sure -+ * there are some. -+ */ -+ -+static int -+check_union_mnt(struct path *mntpnt, struct vfsmount *top_mnt, int mnt_flags) -+{ -+ struct vfsmount *lower_mnt = mntpnt->mnt; -+ -+ /* Is this even a union mount? */ -+ if (!(mnt_flags & MNT_UNION)) -+ return 0; -+ -+ /* Lower layer must be read-only and not a union mount */ -+ if (!(lower_mnt->mnt_sb->s_flags & MS_RDONLY) || -+ (lower_mnt->mnt_flags & MNT_UNION)) -+ return -EBUSY; -+ -+ /* Upper layer must be writable */ -+ if (mnt_flags & MNT_READONLY) -+ return -EROFS; -+ -+ /* Upper layer must support whiteouts and fallthrus */ -+ if (!(top_mnt->mnt_sb->s_flags & MS_WHITEOUT)) -+ return -EINVAL; -+ -+ /* All good! */ -+ return 0; -+} -+ -+/* - * do loopback mount. - */ --static int do_loopback(struct path *path, char *old_name, -- int recurse) -+static int do_loopback(struct path *path, char *old_name, int recurse, -+ int mnt_flags) - { - struct path old_path; - struct vfsmount *mnt = NULL; -@@ -1477,6 +1550,13 @@ static int do_loopback(struct path *path - if (!mnt) - goto out; - -+ err = check_union_mnt(&old_path, mnt, mnt_flags); -+ if (err) -+ goto out; -+ -+ if (mnt_flags & MNT_UNION) -+ mnt->mnt_flags |= MNT_UNION; -+ - err = graft_tree(mnt, path); - if (err) { - LIST_HEAD(umount_list); -@@ -1486,6 +1566,10 @@ static int do_loopback(struct path *path - release_mounts(&umount_list); - } - -+ /* If this is a union mount, add ourselves to the readonly users */ -+ if (mnt_flags & MNT_UNION) -+ mnt->mnt_parent->mnt_sb->s_readonly_users++; -+ - out: - up_write(&namespace_sem); - path_put(&old_path); -@@ -1570,6 +1654,13 @@ static int do_move_mount(struct path *pa - if (err) - return err; - -+ /* moving to or from a union mount is not supported */ -+ err = -EINVAL; -+ if (IS_MNT_UNION(path->mnt)) -+ goto exit; -+ if (IS_MNT_UNION(old_path.mnt)) -+ goto exit; -+ - down_write(&namespace_sem); - while (d_mountpoint(path->dentry) && - follow_down(path)) -@@ -1627,6 +1718,7 @@ out: - up_write(&namespace_sem); - if (!err) - path_put(&parent_path); -+exit: - path_put(&old_path); - return err; - } -@@ -1684,10 +1776,18 @@ int do_add_mount(struct vfsmount *newmnt - if (S_ISLNK(newmnt->mnt_root->d_inode->i_mode)) - goto unlock; - -+ err = check_union_mnt(path, newmnt, mnt_flags); -+ if (err) -+ goto unlock; -+ - newmnt->mnt_flags = mnt_flags; - if ((err = graft_tree(newmnt, path))) - goto unlock; - -+ /* If this is a union mount, add ourselves to the readonly users */ -+ if (mnt_flags & MNT_UNION) -+ newmnt->mnt_parent->mnt_sb->s_readonly_users++; -+ - if (fslist) /* add to the specified expiration list */ - list_add_tail(&newmnt->mnt_expire, fslist); - -@@ -1925,10 +2025,12 @@ long do_mount(char *dev_name, char *dir_ - mnt_flags &= ~(MNT_RELATIME | MNT_NOATIME); - if (flags & MS_RDONLY) - mnt_flags |= MNT_READONLY; -+ if (flags & MS_UNION) -+ mnt_flags |= MNT_UNION; - - flags &= ~(MS_NOSUID | MS_NOEXEC | MS_NODEV | MS_ACTIVE | - MS_NOATIME | MS_NODIRATIME | MS_RELATIME| MS_KERNMOUNT | -- MS_STRICTATIME); -+ MS_STRICTATIME | MS_UNION); - - /* ... and get the mountpoint */ - retval = kern_path(dir_name, LOOKUP_FOLLOW, &path); -@@ -1944,7 +2046,8 @@ long do_mount(char *dev_name, char *dir_ - retval = do_remount(&path, flags & ~MS_REMOUNT, mnt_flags, - data_page); - else if (flags & MS_BIND) -- retval = do_loopback(&path, dev_name, flags & MS_REC); -+ retval = do_loopback(&path, dev_name, flags & MS_REC, -+ mnt_flags); - else if (flags & (MS_SHARED | MS_PRIVATE | MS_SLAVE | MS_UNBINDABLE)) - retval = do_change_type(&path, flags); - else if (flags & MS_MOVE) -@@ -2179,6 +2282,8 @@ SYSCALL_DEFINE2(pivot_root, const char _ - if (d_unlinked(old.dentry)) - goto out2; - error = -EBUSY; -+ follow_union_down(&new); -+ follow_union_down(&root); - if (new.mnt == root.mnt || - old.mnt == root.mnt) - goto out2; /* loop, on the same file system */ ---- a/fs/nfsctl.c -+++ b/fs/nfsctl.c -@@ -38,10 +38,10 @@ static struct file *do_open(char *name, - return ERR_PTR(error); - - if (flags == O_RDWR) -- error = may_open(&nd.path, MAY_READ|MAY_WRITE, -- FMODE_READ|FMODE_WRITE); -+ error = may_open(&nd, MAY_READ|MAY_WRITE, -+ FMODE_READ|FMODE_WRITE); - else -- error = may_open(&nd.path, MAY_WRITE, FMODE_WRITE); -+ error = may_open(&nd, MAY_WRITE, FMODE_WRITE); - - if (!error) - return dentry_open(nd.path.dentry, nd.path.mnt, flags, ---- a/fs/nfsd/nfs3xdr.c -+++ b/fs/nfsd/nfs3xdr.c -@@ -884,6 +884,11 @@ encode_entry(struct readdir_cd *ccd, con - int elen; /* estimated entry length in words */ - int num_entry_words = 0; /* actual number of words */ - -+ if (d_type == DT_WHT) { -+ cd->common.err = nfs_ok; -+ return 0; -+ } -+ - if (cd->offset) { - u64 offset64 = offset; - ---- a/fs/nfsd/nfs4xdr.c -+++ b/fs/nfsd/nfs4xdr.c -@@ -2263,7 +2263,7 @@ nfsd4_encode_dirent(void *ccdv, const ch - __be32 nfserr = nfserr_toosmall; - - /* In nfsv4, "." and ".." never make it onto the wire.. */ -- if (name && isdotent(name, namlen)) { -+ if (d_type == DT_WHT || (name && isdotent(name, namlen))) { - cd->common.err = nfs_ok; - return 0; - } ---- a/fs/nfsd/nfsxdr.c -+++ b/fs/nfsd/nfsxdr.c -@@ -513,6 +513,10 @@ nfssvc_encode_entry(void *ccdv, const ch - namlen, name, offset, ino); - */ - -+ if (d_type == DT_WHT) { -+ cd->common.err = nfs_ok; -+ return 0; -+ } - if (offset > ~((u32) 0)) { - cd->common.err = nfserr_fbig; - return -EINVAL; ---- a/fs/open.c -+++ b/fs/open.c -@@ -30,6 +30,7 @@ - #include - #include - #include -+#include - - int vfs_statfs(struct dentry *dentry, struct kstatfs *buf) - { -@@ -222,69 +223,69 @@ int do_truncate(struct dentry *dentry, l - return err; - } - --static long do_sys_truncate(const char __user *pathname, loff_t length) -+static int __do_ftruncate(struct file *file, unsigned long length, int small) - { -- struct path path; -- struct inode *inode; -+ struct inode * inode; -+ struct dentry *dentry; - int error; - - error = -EINVAL; -- if (length < 0) /* sorry, but loff_t says... */ -+ if (length < 0) - goto out; -+ /* explicitly opened as large or we are on 64-bit box */ -+ if (file->f_flags & O_LARGEFILE) -+ small = 0; - -- error = user_path(pathname, &path); -- if (error) -+ dentry = file->f_path.dentry; -+ inode = dentry->d_inode; -+ error = -EINVAL; -+ if (!S_ISREG(inode->i_mode) || !(file->f_mode & FMODE_WRITE)) - goto out; -- inode = path.dentry->d_inode; -- -- /* For directories it's -EISDIR, for other non-regulars - -EINVAL */ -- error = -EISDIR; -- if (S_ISDIR(inode->i_mode)) -- goto dput_and_out; - - error = -EINVAL; -- if (!S_ISREG(inode->i_mode)) -- goto dput_and_out; -- -- error = mnt_want_write(path.mnt); -- if (error) -- goto dput_and_out; -+ /* Cannot ftruncate over 2^31 bytes without large file support */ -+ if (small && length > MAX_NON_LFS) - -- error = inode_permission(inode, MAY_WRITE); -- if (error) -- goto mnt_drop_write_and_out; -+ goto out; - - error = -EPERM; - if (IS_APPEND(inode)) -- goto mnt_drop_write_and_out; -+ goto out; - -- error = get_write_access(inode); -- if (error) -- goto mnt_drop_write_and_out; -+ error = locks_verify_truncate(inode, file, length); -+ if (!error) -+ error = security_path_truncate(&file->f_path, length, -+ ATTR_MTIME|ATTR_CTIME); -+ if (!error) -+ /* Already copied up for union, opened with write */ -+ error = do_truncate(dentry, length, ATTR_MTIME|ATTR_CTIME, file); -+out: -+ return error; -+} - -- /* -- * Make sure that there are no leases. get_write_access() protects -- * against the truncate racing with a lease-granting setlease(). -- */ -- error = break_lease(inode, FMODE_WRITE); -- if (error) -- goto put_write_and_out; -+static long do_sys_truncate(const char __user *pathname, loff_t length) -+{ -+ struct file *file; -+ char *tmp; -+ int error; - -- error = locks_verify_truncate(inode, NULL, length); -- if (!error) -- error = security_path_truncate(&path, length, 0); -- if (!error) { -- vfs_dq_init(inode); -- error = do_truncate(path.dentry, length, 0, NULL); -- } -+ error = -EINVAL; -+ if (length < 0) /* sorry, but loff_t says... */ -+ return error; - --put_write_and_out: -- put_write_access(inode); --mnt_drop_write_and_out: -- mnt_drop_write(path.mnt); --dput_and_out: -- path_put(&path); --out: -+ tmp = getname(pathname); -+ if (IS_ERR(tmp)) -+ return PTR_ERR(tmp); -+ -+ file = filp_open(tmp, O_RDWR | O_LARGEFILE, 0); -+ putname(tmp); -+ -+ if (IS_ERR(file)) -+ return PTR_ERR(file); -+ -+ error = __do_ftruncate(file, length, 0); -+ -+ fput(file); - return error; - } - -@@ -296,45 +297,16 @@ SYSCALL_DEFINE2(truncate, const char __u - - static long do_sys_ftruncate(unsigned int fd, loff_t length, int small) - { -- struct inode * inode; -- struct dentry *dentry; - struct file * file; - int error; - -- error = -EINVAL; -- if (length < 0) -- goto out; - error = -EBADF; - file = fget(fd); - if (!file) - goto out; - -- /* explicitly opened as large or we are on 64-bit box */ -- if (file->f_flags & O_LARGEFILE) -- small = 0; -- -- dentry = file->f_path.dentry; -- inode = dentry->d_inode; -- error = -EINVAL; -- if (!S_ISREG(inode->i_mode) || !(file->f_mode & FMODE_WRITE)) -- goto out_putf; -- -- error = -EINVAL; -- /* Cannot ftruncate over 2^31 bytes without large file support */ -- if (small && length > MAX_NON_LFS) -- goto out_putf; -+ error = __do_ftruncate(file, length, small); - -- error = -EPERM; -- if (IS_APPEND(inode)) -- goto out_putf; -- -- error = locks_verify_truncate(inode, file, length); -- if (!error) -- error = security_path_truncate(&file->f_path, length, -- ATTR_MTIME|ATTR_CTIME); -- if (!error) -- error = do_truncate(dentry, length, ATTR_MTIME|ATTR_CTIME, file); --out_putf: - fput(file); - out: - return error; -@@ -493,7 +465,8 @@ SYSCALL_DEFINE3(faccessat, int, dfd, con - goto out_path_release; - } - -- res = inode_permission(inode, mode | MAY_ACCESS); -+ res = union_permission(&path, mode | MAY_ACCESS); -+ - /* SuS v2 requires we report a read only fs too */ - if (res || !(mode & S_IWOTH) || special_file(inode->i_mode)) - goto out_path_release; -@@ -507,7 +480,8 @@ SYSCALL_DEFINE3(faccessat, int, dfd, con - * inherently racy and know that the fs may change - * state before we even see this result. - */ -- if (__mnt_is_readonly(path.mnt)) -+ if ((!is_unionized(path.dentry, path.mnt) && -+ (__mnt_is_readonly(path.mnt)))) - res = -EROFS; - - out_path_release: -@@ -553,20 +527,19 @@ SYSCALL_DEFINE1(fchdir, unsigned int, fd - error = -EBADF; - file = fget(fd); - if (!file) -- goto out; -+ return error; - - inode = file->f_path.dentry->d_inode; - - error = -ENOTDIR; - if (!S_ISDIR(inode->i_mode)) -- goto out_putf; -+ goto out; - - error = inode_permission(inode, MAY_EXEC | MAY_ACCESS); - if (!error) - set_fs_pwd(current->fs, &file->f_path); --out_putf: -- fput(file); - out: -+ fput(file); - return error; - } - ---- a/fs/readdir.c -+++ b/fs/readdir.c -@@ -16,6 +16,7 @@ - #include - #include - #include -+#include - - #include - -@@ -36,9 +37,24 @@ int vfs_readdir(struct file *file, filld - - res = -ENOENT; - if (!IS_DEADDIR(inode)) { -+ /* -+ * XXX Think harder about locking for -+ * union_copyup_dir. Currently we lock the topmost -+ * directory and hold that lock while sequentially -+ * acquiring and dropping locks for the directories -+ * below this one in the union stack. -+ */ -+ if (is_unionized(file->f_path.dentry, file->f_path.mnt) && -+ !IS_OPAQUE(inode)) { -+ res = union_copyup_dir(&file->f_path); -+ if (res) -+ goto out_unlock; -+ } -+ - res = file->f_op->readdir(file, buf, filler); - file_accessed(file); - } -+out_unlock: - mutex_unlock(&inode->i_mutex); - out: - return res; -@@ -77,6 +93,9 @@ static int fillonedir(void * __buf, cons - struct old_linux_dirent __user * dirent; - unsigned long d_ino; - -+ if (d_type == DT_WHT) -+ return 0; -+ - if (buf->result) - return -EINVAL; - d_ino = ino; -@@ -154,6 +173,9 @@ static int filldir(void * __buf, const c - unsigned long d_ino; - int reclen = ALIGN(NAME_OFFSET(dirent) + namlen + 2, sizeof(long)); - -+ if (d_type == DT_WHT) -+ return 0; -+ - buf->error = -EINVAL; /* only used if we fail.. */ - if (reclen > buf->count) - return -EINVAL; -@@ -239,6 +261,9 @@ static int filldir64(void * __buf, const - struct getdents_callback64 * buf = (struct getdents_callback64 *) __buf; - int reclen = ALIGN(NAME_OFFSET(dirent) + namlen + 1, sizeof(u64)); - -+ if (d_type == DT_WHT) -+ return 0; -+ - buf->error = -EINVAL; /* only used if we fail.. */ - if (reclen > buf->count) - return -EINVAL; ---- a/fs/super.c -+++ b/fs/super.c -@@ -553,6 +553,15 @@ int do_remount_sb(struct super_block *sb - } - remount_rw = !(flags & MS_RDONLY) && (sb->s_flags & MS_RDONLY); - -+ /* If we are remounting read/write, make sure that none of the -+ users require read-only for correct operation (such as -+ union mounts). */ -+ if (remount_rw && sb->s_readonly_users) { -+ printk(KERN_INFO "%s: In use by %d read-only user(s)\n", -+ sb->s_id, sb->s_readonly_users); -+ return -EROFS; -+ } -+ - if (sb->s_op->remount_fs) { - retval = sb->s_op->remount_fs(sb, &flags, data); - if (retval) -@@ -889,6 +898,11 @@ vfs_kern_mount(struct file_system_type * - if (error) - goto out_sb; - -+ error = -EROFS; -+ if (!(flags & MS_RDONLY) && -+ (mnt->mnt_sb->s_readonly_users)) -+ goto out_sb; -+ - mnt->mnt_mountpoint = mnt->mnt_root; - mnt->mnt_parent = mnt; - up_write(&mnt->mnt_sb->s_umount); ---- /dev/null -+++ b/fs/union.c -@@ -0,0 +1,981 @@ -+/* -+ * VFS based union mount for Linux -+ * -+ * Copyright (C) 2004-2007 IBM Corporation, IBM Deutschland Entwicklung GmbH. -+ * Copyright (C) 2007-2009 Novell Inc. -+ * -+ * Author(s): Jan Blunck (j.blunck@tu-harburg.de) -+ * Valerie Aurora -+ * -+ * 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. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+/* -+ * This is borrowed from fs/inode.c. The hashtable for lookups. Somebody -+ * should try to make this good - I've just made it work. -+ */ -+static unsigned int union_hash_mask __read_mostly; -+static unsigned int union_hash_shift __read_mostly; -+static struct hlist_head *union_hashtable __read_mostly; -+static unsigned int union_rhash_mask __read_mostly; -+static unsigned int union_rhash_shift __read_mostly; -+static struct hlist_head *union_rhashtable __read_mostly; -+ -+/* -+ * Locking Rules: -+ * - dcache_lock (for union_rlookup() only) -+ * - union_lock -+ */ -+DEFINE_SPINLOCK(union_lock); -+ -+static struct kmem_cache *union_cache __read_mostly; -+ -+static unsigned long hash(struct dentry *dentry, struct vfsmount *mnt) -+{ -+ unsigned long tmp; -+ -+ tmp = ((unsigned long)mnt * (unsigned long)dentry) ^ -+ (GOLDEN_RATIO_PRIME + (unsigned long)mnt) / L1_CACHE_BYTES; -+ tmp = tmp ^ ((tmp ^ GOLDEN_RATIO_PRIME) >> union_hash_shift); -+ return tmp & union_hash_mask; -+} -+ -+static __initdata unsigned long union_hash_entries; -+ -+static int __init set_union_hash_entries(char *str) -+{ -+ if (!str) -+ return 0; -+ union_hash_entries = simple_strtoul(str, &str, 0); -+ return 1; -+} -+ -+__setup("union_hash_entries=", set_union_hash_entries); -+ -+static int __init init_union(void) -+{ -+ int loop; -+ -+ union_cache = KMEM_CACHE(union_mount, SLAB_PANIC | SLAB_MEM_SPREAD); -+ union_hashtable = alloc_large_system_hash("Union-cache", -+ sizeof(struct hlist_head), -+ union_hash_entries, -+ 14, -+ 0, -+ &union_hash_shift, -+ &union_hash_mask, -+ 0); -+ -+ for (loop = 0; loop < (1 << union_hash_shift); loop++) -+ INIT_HLIST_HEAD(&union_hashtable[loop]); -+ -+ -+ union_rhashtable = alloc_large_system_hash("rUnion-cache", -+ sizeof(struct hlist_head), -+ union_hash_entries, -+ 14, -+ 0, -+ &union_rhash_shift, -+ &union_rhash_mask, -+ 0); -+ -+ for (loop = 0; loop < (1 << union_rhash_shift); loop++) -+ INIT_HLIST_HEAD(&union_rhashtable[loop]); -+ -+ return 0; -+} -+ -+fs_initcall(init_union); -+ -+struct union_mount *union_alloc(struct dentry *this, struct vfsmount *this_mnt, -+ struct dentry *next, struct vfsmount *next_mnt) -+{ -+ struct union_mount *um; -+ -+ BUG_ON(!S_ISDIR(this->d_inode->i_mode)); -+ BUG_ON(!S_ISDIR(next->d_inode->i_mode)); -+ -+ um = kmem_cache_alloc(union_cache, GFP_ATOMIC); -+ if (!um) -+ return NULL; -+ -+ atomic_set(&um->u_count, 1); -+ INIT_LIST_HEAD(&um->u_unions); -+ INIT_LIST_HEAD(&um->u_list); -+ INIT_HLIST_NODE(&um->u_hash); -+ INIT_HLIST_NODE(&um->u_rhash); -+ -+ um->u_this.mnt = this_mnt; -+ um->u_this.dentry = this; -+ um->u_next.mnt = mntget(next_mnt); -+ um->u_next.dentry = dget(next); -+ -+ return um; -+} -+ -+struct union_mount *union_get(struct union_mount *um) -+{ -+ BUG_ON(!atomic_read(&um->u_count)); -+ atomic_inc(&um->u_count); -+ return um; -+} -+ -+static int __union_put(struct union_mount *um) -+{ -+ if (!atomic_dec_and_test(&um->u_count)) -+ return 0; -+ -+ BUG_ON(!hlist_unhashed(&um->u_hash)); -+ BUG_ON(!hlist_unhashed(&um->u_rhash)); -+ -+ kmem_cache_free(union_cache, um); -+ return 1; -+} -+ -+void union_put(struct union_mount *um) -+{ -+ struct path tmp = um->u_next; -+ -+ if (__union_put(um)) -+ path_put(&tmp); -+} -+ -+static void __union_hash(struct union_mount *um) -+{ -+ hlist_add_head(&um->u_hash, union_hashtable + -+ hash(um->u_this.dentry, um->u_this.mnt)); -+ hlist_add_head(&um->u_rhash, union_rhashtable + -+ hash(um->u_next.dentry, um->u_next.mnt)); -+} -+ -+static void __union_unhash(struct union_mount *um) -+{ -+ hlist_del_init(&um->u_hash); -+ hlist_del_init(&um->u_rhash); -+} -+ -+struct union_mount *union_lookup(struct dentry *dentry, struct vfsmount *mnt) -+{ -+ struct hlist_head *head = union_hashtable + hash(dentry, mnt); -+ struct hlist_node *node; -+ struct union_mount *um; -+ -+ hlist_for_each_entry(um, node, head, u_hash) { -+ if ((um->u_this.dentry == dentry) && -+ (um->u_this.mnt == mnt)) -+ return um; -+ } -+ -+ return NULL; -+} -+ -+struct union_mount *union_rlookup(struct dentry *dentry, struct vfsmount *mnt) -+{ -+ struct hlist_head *head = union_rhashtable + hash(dentry, mnt); -+ struct hlist_node *node; -+ struct union_mount *um; -+ -+ hlist_for_each_entry(um, node, head, u_rhash) { -+ if ((um->u_next.dentry == dentry) && -+ (um->u_next.mnt == mnt)) -+ return um; -+ } -+ -+ return NULL; -+} -+ -+/* -+ * is_unionized - check if a dentry lives on a union mounted file system -+ * -+ * This tests if a dentry is living on an union mounted file system by walking -+ * the file system hierarchy. -+ */ -+int is_unionized(struct dentry *dentry, struct vfsmount *mnt) -+{ -+ struct path this = { .mnt = mntget(mnt), -+ .dentry = dget(dentry) }; -+ struct vfsmount *tmp; -+ -+ do { -+ /* check if there is an union mounted on top of us */ -+ spin_lock(&vfsmount_lock); -+ list_for_each_entry(tmp, &this.mnt->mnt_mounts, mnt_child) { -+ if (!(tmp->mnt_flags & MNT_UNION)) -+ continue; -+ /* Isn't this a bug? */ -+ if (this.dentry->d_sb != tmp->mnt_mountpoint->d_sb) -+ continue; -+ if (is_subdir(this.dentry, tmp->mnt_mountpoint)) { -+ spin_unlock(&vfsmount_lock); -+ path_put(&this); -+ return 1; -+ } -+ } -+ spin_unlock(&vfsmount_lock); -+ -+ /* check our mountpoint next */ -+ tmp = mntget(this.mnt->mnt_parent); -+ dput(this.dentry); -+ this.dentry = dget(this.mnt->mnt_mountpoint); -+ mntput(this.mnt); -+ this.mnt = tmp; -+ } while (this.mnt != this.mnt->mnt_parent); -+ -+ path_put(&this); -+ return 0; -+} -+ -+int append_to_union(struct vfsmount *mnt, struct dentry *dentry, -+ struct vfsmount *dest_mnt, struct dentry *dest_dentry) -+{ -+ struct union_mount *this, *um; -+ -+ BUG_ON(!IS_MNT_UNION(mnt)); -+ -+ this = union_alloc(dentry, mnt, dest_dentry, dest_mnt); -+ if (!this) -+ return -ENOMEM; -+ -+ spin_lock(&union_lock); -+ um = union_lookup(dentry, mnt); -+ if (um) { -+ BUG_ON((um->u_next.dentry != dest_dentry) || -+ (um->u_next.mnt != dest_mnt)); -+ spin_unlock(&union_lock); -+ union_put(this); -+ return 0; -+ } -+ list_add(&this->u_list, &mnt->mnt_unions); -+ list_add(&this->u_unions, &dentry->d_unions); -+ dest_dentry->d_unionized++; -+ __union_hash(this); -+ spin_unlock(&union_lock); -+ return 0; -+} -+ -+/* -+ * follow_union_down - follow the union stack one layer down -+ * -+ * This is called to traverse the union stack from one layer to the next -+ * overlayed one. follow_union_down() is called by various lookup functions -+ * that are aware of union mounts. -+ * -+ * Returns non-zero if followed to the next layer, zero otherwise. -+ */ -+int follow_union_down(struct path *path) -+{ -+ struct union_mount *um; -+ -+ if (!IS_MNT_UNION(path->mnt)) -+ return 0; -+ -+ spin_lock(&union_lock); -+ um = union_lookup(path->dentry, path->mnt); -+ spin_unlock(&union_lock); -+ if (um) { -+ path_get(&um->u_next); -+ dput(path->dentry); -+ path->dentry = um->u_next.dentry; -+ mntput(path->mnt); -+ path->mnt = um->u_next.mnt; -+ return 1; -+ } -+ return 0; -+} -+ -+/* -+ * follow_union_mount - follow the union stack to the topmost layer -+ * -+ * This is called to traverse the union stack to the topmost layer. This is -+ * necessary for following parent pointers in an union mount. -+ * -+ * Returns none zero if followed to the topmost layer, zero otherwise. -+ */ -+int follow_union_mount(struct path *path) -+{ -+ struct union_mount *um; -+ int res = 0; -+ -+ while (IS_UNION(path->dentry)) { -+ spin_lock(&dcache_lock); -+ spin_lock(&union_lock); -+ um = union_rlookup(path->dentry, path->mnt); -+ if (um) -+ path_get(&um->u_this); -+ spin_unlock(&union_lock); -+ spin_unlock(&dcache_lock); -+ -+ /* -+ * Q: Aaargh, how do I validate the topmost dentry pointer? -+ * A: Eeeeasy! We took the dcache_lock and union_lock. Since -+ * this protects from any dput'ng going on, we know that the -+ * dentry is valid since the union is unhashed under -+ * dcache_lock too. -+ */ -+ if (!um) -+ break; -+ dput(path->dentry); -+ path->dentry = um->u_this.dentry; -+ mntput(path->mnt); -+ path->mnt = um->u_this.mnt; -+ res = 1; -+ } -+ -+ return res; -+} -+ -+/* -+ * Union mount copyup support -+ */ -+ -+extern int hash_lookup_union(struct nameidata *, struct qstr *, struct path *); -+extern void follow_mount(struct path *); -+ -+/* -+ * union_relookup_topmost - lookup and create the topmost path to dentry -+ * @nd: pointer to nameidata -+ * @flags: lookup flags -+ */ -+static int union_relookup_topmost(struct nameidata *nd, int flags) -+{ -+ int err; -+ char *kbuf, *name; -+ struct nameidata this; -+ -+ kbuf = (char *)__get_free_page(GFP_KERNEL); -+ if (!kbuf) -+ return -ENOMEM; -+ -+ name = d_path(&nd->path, kbuf, PAGE_SIZE); -+ err = PTR_ERR(name); -+ if (IS_ERR(name)) -+ goto free_page; -+ -+ err = path_lookup(name, flags|LOOKUP_CREATE|LOOKUP_TOPMOST, &this); -+ if (err) -+ goto free_page; -+ -+ path_put(&nd->path); -+ nd->path.dentry = this.path.dentry; -+ nd->path.mnt = this.path.mnt; -+ -+ /* -+ * the nd->flags should be unchanged -+ */ -+ BUG_ON(this.um_flags & LAST_LOWLEVEL); -+ nd->um_flags &= ~LAST_LOWLEVEL; -+ free_page: -+ free_page((unsigned long)kbuf); -+ return err; -+} -+ -+static void __update_fs_pwd(struct path *path, struct dentry *dentry, -+ struct vfsmount *mnt) -+{ -+ struct path old = { NULL, NULL }; -+ -+ write_lock(¤t->fs->lock); -+ if (current->fs->pwd.dentry == path->dentry) { -+ old = current->fs->pwd; -+ path_get(¤t->fs->pwd); -+ } -+ write_unlock(¤t->fs->lock); -+ -+ if (old.dentry) -+ path_put(&old); -+ -+ return; -+} -+ -+/** -+ * union_permission - check for access rights to a given inode -+ * @inode: inode to check permission on -+ * @mask: right to check for (%MAY_READ, %MAY_WRITE, %MAY_EXEC) -+ * -+ * In a union mount, the top layer is always read-write and the bottom -+ * is always read-only. Ignore the read-only flag on the lower fs. -+ * -+ * Only need for certain activities, like checking to see if write -+ * access is ok. -+ */ -+ -+int union_permission(struct path *path, int mask) -+{ -+ struct inode *inode = path->dentry->d_inode; -+ -+ if (!is_unionized(path->dentry, path->mnt)) -+ return inode_permission(inode, mask); -+ -+ /* Tell __inode_permission to ignore MS_RDONLY */ -+ return __inode_permission(inode, mask, 0); -+} -+ -+/* -+ * union_create_topmost - create the topmost path component -+ * @nd: pointer to nameidata of the base directory -+ * @name: pointer to file name -+ * @path: pointer to path of the overlaid file -+ * -+ * This is called by __link_path_walk() to create the directories on a path -+ * when it is called with LOOKUP_TOPMOST. -+ */ -+struct dentry *union_create_topmost(struct nameidata *nd, struct qstr *name, -+ struct path *path) -+{ -+ struct dentry *dentry, *parent = nd->path.dentry; -+ int res, mode = path->dentry->d_inode->i_mode; -+ -+ if (parent->d_sb == path->dentry->d_sb) -+ return ERR_PTR(-EEXIST); -+ -+ mutex_lock(&parent->d_inode->i_mutex); -+ dentry = lookup_one_len(name->name, nd->path.dentry, name->len); -+ if (IS_ERR(dentry)) -+ goto out_unlock; -+ -+ switch (mode & S_IFMT) { -+ case S_IFREG: -+ /* -+ * FIXME: Does this make any sense in this case? -+ * Special case - lookup gave negative, but... we had foo/bar/ -+ * From the vfs_mknod() POV we just have a negative dentry - -+ * all is fine. Let's be bastards - you had / on the end,you've -+ * been asking for (non-existent) directory. -ENOENT for you. -+ */ -+ if (name->name[name->len] && !dentry->d_inode) { -+ dput(dentry); -+ dentry = ERR_PTR(-ENOENT); -+ goto out_unlock; -+ } -+ -+ res = vfs_create(parent->d_inode, dentry, mode, nd); -+ if (res) { -+ dput(dentry); -+ dentry = ERR_PTR(res); -+ goto out_unlock; -+ } -+ break; -+ case S_IFDIR: -+ res = vfs_mkdir(parent->d_inode, dentry, mode); -+ if (res) { -+ dput(dentry); -+ dentry = ERR_PTR(res); -+ goto out_unlock; -+ } -+ -+ res = append_to_union(nd->path.mnt, dentry, path->mnt, -+ path->dentry); -+ if (res) { -+ dput(dentry); -+ dentry = ERR_PTR(res); -+ goto out_unlock; -+ } -+ break; -+ default: -+ dput(dentry); -+ dentry = ERR_PTR(-EINVAL); -+ goto out_unlock; -+ } -+ -+ /* FIXME: Really necessary ??? */ -+/* __update_fs_pwd(path, dentry, nd->path.mnt); */ -+ -+ out_unlock: -+ mutex_unlock(&parent->d_inode->i_mutex); -+ return dentry; -+} -+ -+static int union_copy_file(struct dentry *old_dentry, struct vfsmount *old_mnt, -+ struct dentry *new_dentry, struct vfsmount *new_mnt) -+{ -+ int ret; -+ size_t size; -+ loff_t offset; -+ struct file *old_file, *new_file; -+ const struct cred *cred = current_cred(); -+ -+ dget(old_dentry); -+ mntget(old_mnt); -+ old_file = dentry_open(old_dentry, old_mnt, O_RDONLY, cred); -+ if (IS_ERR(old_file)) -+ return PTR_ERR(old_file); -+ -+ dget(new_dentry); -+ mntget(new_mnt); -+ new_file = dentry_open(new_dentry, new_mnt, O_WRONLY, cred); -+ ret = PTR_ERR(new_file); -+ if (IS_ERR(new_file)) -+ goto fput_old; -+ -+ /* XXX be smart by using a length param, which indicates max -+ * data we'll want (e.g., we are about to truncate to 0 or 10 -+ * bytes or something */ -+ size = i_size_read(old_file->f_path.dentry->d_inode); -+ if (((size_t)size != size) || ((ssize_t)size != size)) { -+ ret = -EFBIG; -+ goto fput_new; -+ } -+ -+ offset = 0; -+ ret = do_splice_direct(old_file, &offset, new_file, size, -+ SPLICE_F_MOVE); -+ if (ret >= 0) -+ ret = 0; -+ fput_new: -+ fput(new_file); -+ fput_old: -+ fput(old_file); -+ return ret; -+} -+ -+/** -+ * __union_copyup - copy a file to the topmost directory -+ * @old: pointer to path of the old file name -+ * @new_nd: pointer to nameidata of the topmost directory -+ * @new: pointer to path of the new file name -+ * -+ * The topmost directory @new_nd must already be locked. Creates the topmost -+ * file if it doesn't exist yet. -+ */ -+int __union_copyup(struct path *old, struct nameidata *new_nd, -+ struct path *new) -+{ -+ struct dentry *dentry; -+ int error; -+ -+ /* Maybe this should be -EINVAL */ -+ if (S_ISDIR(old->dentry->d_inode->i_mode)) -+ return -EISDIR; -+ -+ if (new_nd->path.dentry != new->dentry->d_parent) { -+ mutex_lock(&new_nd->path.dentry->d_inode->i_mutex); -+ dentry = lookup_one_len(new->dentry->d_name.name, -+ new_nd->path.dentry, -+ new->dentry->d_name.len); -+ mutex_unlock(&new_nd->path.dentry->d_inode->i_mutex); -+ if (IS_ERR(dentry)) -+ return PTR_ERR(dentry); -+ error = -EEXIST; -+ if (dentry->d_inode) -+ goto out_dput; -+ } else -+ dentry = dget(new->dentry); -+ -+ if (!dentry->d_inode) { -+ error = vfs_create(new_nd->path.dentry->d_inode, dentry, -+ old->dentry->d_inode->i_mode, new_nd); -+ if (error) -+ goto out_dput; -+ } -+ -+ BUG_ON(!S_ISREG(old->dentry->d_inode->i_mode)); -+ error = union_copy_file(old->dentry, old->mnt, dentry, -+ new_nd->path.mnt); -+ if (error) { -+ /* FIXME: are there return value we should not -+ * BUG() on ? */ -+ BUG_ON(vfs_unlink(new_nd->path.dentry->d_inode, -+ dentry)); -+ goto out_dput; -+ } -+ -+ dput(new->dentry); -+ new->dentry = dentry; -+ if (new->mnt != new_nd->path.mnt) -+ mntput(new->mnt); -+ new->mnt = new_nd->path.mnt; -+ return error; -+ -+out_dput: -+ dput(dentry); -+ return error; -+} -+ -+/* -+ * union_copyup - copy a file to the topmost layer of the union stack -+ * @nd: nameidata pointer to the file -+ * @flags: flags given to open_namei -+ */ -+int union_copyup(struct nameidata *nd, int flags /* XXX not used */) -+{ -+ struct qstr this; -+ char *name; -+ struct dentry *dir; -+ struct path path; -+ int err; -+ -+ if (!is_unionized(nd->path.dentry, nd->path.mnt)) -+ return 0; -+ if (!S_ISREG(nd->path.dentry->d_inode->i_mode)) -+ return 0; -+ -+ /* safe the name for hash_lookup_union() */ -+ this.len = nd->path.dentry->d_name.len; -+ this.hash = nd->path.dentry->d_name.hash; -+ name = kmalloc(this.len + 1, GFP_KERNEL); -+ if (!name) -+ return -ENOMEM; -+ this.name = name; -+ memcpy(name, nd->path.dentry->d_name.name, nd->path.dentry->d_name.len); -+ name[this.len] = 0; -+ -+ err = union_relookup_topmost(nd, nd->flags|LOOKUP_PARENT); -+ if (err) { -+ kfree(name); -+ return err; -+ } -+ nd->flags &= ~LOOKUP_PARENT; -+ -+ dir = nd->path.dentry; -+ mutex_lock(&dir->d_inode->i_mutex); -+ err = hash_lookup_union(nd, &this, &path); -+ mutex_unlock(&dir->d_inode->i_mutex); -+ kfree(name); -+ if (err) -+ return err; -+ -+ err = -ENOENT; -+ if (!path.dentry->d_inode) -+ goto exit_dput; -+ -+ /* Necessary?! I guess not ... */ -+ follow_mount(&path); -+ -+ err = -ENOENT; -+ if (!path.dentry->d_inode) -+ goto exit_dput; -+ -+ err = -EISDIR; -+ if (!S_ISREG(path.dentry->d_inode->i_mode)) -+ goto exit_dput; -+ -+ if (path.dentry->d_parent != nd->path.dentry) { -+ err = __union_copyup(&path, nd, &path); -+ if (err) -+ goto exit_dput; -+ } -+ -+ dput(nd->path.dentry); -+ if (nd->path.mnt != path.mnt) -+ mntput(nd->path.mnt); -+ nd->path = path; -+ return 0; -+ -+exit_dput: -+ dput(path.dentry); -+ if (path.mnt != nd->path.mnt) -+ mntput(path.mnt); -+ return err; -+} -+ -+/* -+ * This must be called when unhashing a dentry. This is called with dcache_lock -+ * and unhashes all unions this dentry is in. -+ */ -+void __d_drop_unions(struct dentry *dentry) -+{ -+ struct union_mount *this, *next; -+ -+ spin_lock(&union_lock); -+ list_for_each_entry_safe(this, next, &dentry->d_unions, u_unions) -+ __union_unhash(this); -+ spin_unlock(&union_lock); -+} -+EXPORT_SYMBOL_GPL(__d_drop_unions); -+ -+/* -+ * This must be called after __d_drop_unions() without holding any locks. -+ * Note: The dentry might still be reachable via a lookup but at that time it -+ * already a negative dentry. Otherwise it would be unhashed. The union_mount -+ * structure itself is still reachable through mnt->mnt_unions (which we -+ * protect against with union_lock). -+ */ -+void shrink_d_unions(struct dentry *dentry) -+{ -+ struct union_mount *this, *next; -+ -+repeat: -+ spin_lock(&union_lock); -+ list_for_each_entry_safe(this, next, &dentry->d_unions, u_unions) { -+ BUG_ON(!hlist_unhashed(&this->u_hash)); -+ BUG_ON(!hlist_unhashed(&this->u_rhash)); -+ list_del(&this->u_list); -+ list_del(&this->u_unions); -+ this->u_next.dentry->d_unionized--; -+ spin_unlock(&union_lock); -+ union_put(this); -+ goto repeat; -+ } -+ spin_unlock(&union_lock); -+} -+ -+extern void __dput(struct dentry *, struct list_head *, int); -+ -+/* -+ * This is the special variant for use in dput() only. -+ */ -+void __shrink_d_unions(struct dentry *dentry, struct list_head *list) -+{ -+ struct union_mount *this, *next; -+ -+ BUG_ON(!d_unhashed(dentry)); -+ -+repeat: -+ spin_lock(&union_lock); -+ list_for_each_entry_safe(this, next, &dentry->d_unions, u_unions) { -+ struct dentry *n_dentry = this->u_next.dentry; -+ struct vfsmount *n_mnt = this->u_next.mnt; -+ -+ BUG_ON(!hlist_unhashed(&this->u_hash)); -+ BUG_ON(!hlist_unhashed(&this->u_rhash)); -+ list_del(&this->u_list); -+ list_del(&this->u_unions); -+ this->u_next.dentry->d_unionized--; -+ spin_unlock(&union_lock); -+ if (__union_put(this)) { -+ __dput(n_dentry, list, 0); -+ mntput(n_mnt); -+ } -+ goto repeat; -+ } -+ spin_unlock(&union_lock); -+} -+ -+/* -+ * Remove all union_mounts structures belonging to this vfsmount from the -+ * union lookup hashtable and so on ... -+ */ -+void shrink_mnt_unions(struct vfsmount *mnt) -+{ -+ struct union_mount *this, *next; -+ -+repeat: -+ spin_lock(&union_lock); -+ list_for_each_entry_safe(this, next, &mnt->mnt_unions, u_list) { -+ if (this->u_this.dentry == mnt->mnt_root) -+ continue; -+ __union_unhash(this); -+ list_del(&this->u_list); -+ list_del(&this->u_unions); -+ this->u_next.dentry->d_unionized--; -+ spin_unlock(&union_lock); -+ union_put(this); -+ goto repeat; -+ } -+ spin_unlock(&union_lock); -+} -+ -+int attach_mnt_union(struct vfsmount *mnt, struct vfsmount *dest_mnt, -+ struct dentry *dest_dentry) -+{ -+ if (!IS_MNT_UNION(mnt)) -+ return 0; -+ -+ return append_to_union(mnt, mnt->mnt_root, dest_mnt, dest_dentry); -+} -+ -+void detach_mnt_union(struct vfsmount *mnt) -+{ -+ struct union_mount *um; -+ -+ if (!IS_MNT_UNION(mnt)) -+ return; -+ -+ shrink_mnt_unions(mnt); -+ -+ spin_lock(&union_lock); -+ um = union_lookup(mnt->mnt_root, mnt); -+ __union_unhash(um); -+ list_del(&um->u_list); -+ list_del(&um->u_unions); -+ um->u_next.dentry->d_unionized--; -+ spin_unlock(&union_lock); -+ union_put(um); -+ return; -+} -+ -+/** -+ * union_copyup_dir_one - copy up a single directory entry -+ * -+ * Individual directory entry copyup function for union_copyup_dir. -+ * We get the entries from higher level layers first. -+ */ -+ -+static int union_copyup_dir_one(void *buf, const char *name, int namlen, -+ loff_t offset, u64 ino, unsigned int d_type) -+{ -+ struct dentry *topmost_dentry = (struct dentry *) buf; -+ struct dentry *dentry; -+ int err = 0; -+ -+ switch (namlen) { -+ case 2: -+ if (name[1] != '.') -+ break; -+ case 1: -+ if (name[0] != '.') -+ break; -+ return 0; -+ } -+ -+ /* Lookup this entry in the topmost directory */ -+ dentry = lookup_one_len(name, topmost_dentry, namlen); -+ -+ if (IS_ERR(dentry)) { -+ printk(KERN_INFO "error looking up %s\n", dentry->d_name.name); -+ goto out; -+ } -+ -+ /* -+ * If the entry already exists, one of the following is true: -+ * it was already copied up (due to an earlier lookup), an -+ * entry with the same name already exists on the topmost file -+ * system, it is a whiteout, or it is a fallthru. In each -+ * case, the top level entry masks any entries from lower file -+ * systems, so don't copy up this entry. -+ */ -+ if (dentry->d_inode || d_is_whiteout(dentry) || -+ d_is_fallthru(dentry)) { -+ printk(KERN_INFO "skipping copy of %s\n", dentry->d_name.name); -+ goto out_dput; -+ } -+ -+ /* -+ * If the entry doesn't exist, create a fallthru entry in the -+ * topmost file system. All possible directory types are -+ * used, so each file system must implement its own way of -+ * storing a fallthru entry. -+ */ -+ printk(KERN_INFO "creating fallthru for %s\n", dentry->d_name.name); -+ err = topmost_dentry->d_inode->i_op->fallthru(topmost_dentry->d_inode, -+ dentry); -+ /* FIXME */ -+ BUG_ON(err); -+ /* -+ * At this point, we have a negative dentry marked as fallthru -+ * in the cache. We could potentially lookup the entry lower -+ * level file system and turn this into a positive dentry -+ * right now, but it is not clear that would be a performance -+ * win and adds more opportunities to fail. -+ */ -+out_dput: -+ dput(dentry); -+out: -+ return 0; -+} -+ -+/** -+ * union_copyup_dir - copy up low-level directory entries to topmost dir -+ * -+ * readdir() is difficult to support on union file systems for two -+ * reasons: We must eliminate duplicates and apply whiteouts, and we -+ * must return something in f_pos that lets us restart in the same -+ * place when we return. Our solution is to, on first readdir() of -+ * the directory, copy up all visible entries from the low-level file -+ * systems and mark the entries that refer to low-level file system -+ * objects as "fallthru" entries. -+ */ -+ -+int union_copyup_dir(struct path *topmost_path) -+{ -+ struct dentry *topmost_dentry = topmost_path->dentry; -+ struct path path = *topmost_path; -+ int res = 0; -+ -+ /* -+ * Skip opaque dirs. -+ */ -+ if (IS_OPAQUE(topmost_dentry->d_inode)) -+ return 0; -+ -+ /* -+ * Mark this dir opaque to show that we have already copied up -+ * the lower entries. Only fallthru entries pass through to -+ * the underlying file system. -+ * -+ * XXX Deal with the lower file system changing. This could -+ * be through running a tool over the top level file system to -+ * make directories transparent again, or we could check the -+ * mtime of the underlying directory. -+ */ -+ -+ topmost_dentry->d_inode->i_flags |= S_OPAQUE; -+ mark_inode_dirty(topmost_dentry->d_inode); -+ -+ /* -+ * Loop through each dir on each level copying up the entries -+ * to the topmost. -+ */ -+ -+ /* Don't drop the caller's reference to the topmost path */ -+ path_get(&path); -+ while (follow_union_down(&path)) { -+ struct file * ftmp; -+ struct inode * inode; -+ -+ /* XXX Permit fallthrus on lower-level? Would need to -+ * pass in opaque flag to union_copyup_dir_one() and -+ * only copy up fallthru entries there. We allow -+ * fallthrus in lower level opaque directories on -+ * lookup, so for consistency we should do one or the -+ * other in both places. */ -+ if (IS_OPAQUE(path.dentry->d_inode)) -+ break; -+ -+ /* dentry_open() doesn't get a path reference itself */ -+ path_get(&path); -+ ftmp = dentry_open(path.dentry, path.mnt, -+ O_RDONLY | O_DIRECTORY | O_NOATIME, -+ current_cred()); -+ if (IS_ERR(ftmp)) { -+ printk (KERN_ERR "unable to open dir %s for " -+ "directory copyup: %ld\n", -+ path.dentry->d_name.name, PTR_ERR(ftmp)); -+ continue; -+ } -+ -+ inode = path.dentry->d_inode; -+ mutex_lock(&inode->i_mutex); -+ -+ res = -ENOENT; -+ if (IS_DEADDIR(inode)) -+ goto out_fput; -+ /* -+ * Read the whole directory, calling our directory -+ * entry copyup function on each entry. Pass in the -+ * topmost dentry as our private data so we can create -+ * new entries in the topmost directory. -+ */ -+ res = ftmp->f_op->readdir(ftmp, topmost_dentry, -+ union_copyup_dir_one); -+out_fput: -+ mutex_unlock(&inode->i_mutex); -+ fput(ftmp); -+ -+ if (res) -+ break; -+ } -+ path_put(&path); -+ return res; -+} ---- a/include/linux/dcache.h -+++ b/include/linux/dcache.h -@@ -101,6 +101,15 @@ struct dentry { - struct dentry *d_parent; /* parent directory */ - struct qstr d_name; - -+#ifdef CONFIG_UNION_MOUNT -+ /* -+ * The following fields are used by the VFS based union mount -+ * implementation. Both are protected by union_lock! -+ */ -+ struct list_head d_unions; /* list of union_mount's */ -+ unsigned int d_unionized; /* unions referencing this dentry */ -+#endif -+ - struct list_head d_lru; /* LRU list */ - /* - * d_child and d_rcu can share memory -@@ -186,6 +195,9 @@ d_iput: no no no yes - - #define DCACHE_FSNOTIFY_PARENT_WATCHED 0x0080 /* Parent inode is watched by some fsnotify listener */ - -+#define DCACHE_WHITEOUT 0x0100 /* This negative dentry is a whiteout */ -+#define DCACHE_FALLTHRU 0x0200 /* Keep looking in the file system below */ -+ - extern spinlock_t dcache_lock; - extern seqlock_t rename_lock; - -@@ -205,12 +217,20 @@ extern seqlock_t rename_lock; - * __d_drop requires dentry->d_lock. - */ - -+#ifdef CONFIG_UNION_MOUNT -+extern void __d_drop_unions(struct dentry *); -+#endif -+ - static inline void __d_drop(struct dentry *dentry) - { - if (!(dentry->d_flags & DCACHE_UNHASHED)) { - dentry->d_flags |= DCACHE_UNHASHED; - hlist_del_rcu(&dentry->d_hash); - } -+#ifdef CONFIG_UNION_MOUNT -+ /* remove dentry from the union hashtable */ -+ __d_drop_unions(dentry); -+#endif - } - - static inline void d_drop(struct dentry *dentry) -@@ -358,6 +378,16 @@ static inline int d_unlinked(struct dent - return d_unhashed(dentry) && !IS_ROOT(dentry); - } - -+static inline int d_is_whiteout(struct dentry *dentry) -+{ -+ return (dentry->d_flags & DCACHE_WHITEOUT); -+} -+ -+static inline int d_is_fallthru(struct dentry *dentry) -+{ -+ return (dentry->d_flags & DCACHE_FALLTHRU); -+} -+ - static inline struct dentry *dget_parent(struct dentry *dentry) - { - struct dentry *ret; ---- a/include/linux/ext2_fs.h -+++ b/include/linux/ext2_fs.h -@@ -189,6 +189,7 @@ struct ext2_group_desc - #define EXT2_NOTAIL_FL FS_NOTAIL_FL /* file tail should not be merged */ - #define EXT2_DIRSYNC_FL FS_DIRSYNC_FL /* dirsync behaviour (directories only) */ - #define EXT2_TOPDIR_FL FS_TOPDIR_FL /* Top of directory hierarchies*/ -+#define EXT2_OPAQUE_FL 0x00040000 - #define EXT2_RESERVED_FL FS_RESERVED_FL /* reserved for ext2 lib */ - - #define EXT2_FL_USER_VISIBLE FS_FL_USER_VISIBLE /* User visible flags */ -@@ -503,10 +504,12 @@ struct ext2_super_block { - #define EXT3_FEATURE_INCOMPAT_RECOVER 0x0004 - #define EXT3_FEATURE_INCOMPAT_JOURNAL_DEV 0x0008 - #define EXT2_FEATURE_INCOMPAT_META_BG 0x0010 -+#define EXT2_FEATURE_INCOMPAT_WHITEOUT 0x0020 - #define EXT2_FEATURE_INCOMPAT_ANY 0xffffffff - - #define EXT2_FEATURE_COMPAT_SUPP EXT2_FEATURE_COMPAT_EXT_ATTR - #define EXT2_FEATURE_INCOMPAT_SUPP (EXT2_FEATURE_INCOMPAT_FILETYPE| \ -+ EXT2_FEATURE_INCOMPAT_WHITEOUT| \ - EXT2_FEATURE_INCOMPAT_META_BG) - #define EXT2_FEATURE_RO_COMPAT_SUPP (EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER| \ - EXT2_FEATURE_RO_COMPAT_LARGE_FILE| \ -@@ -573,6 +576,8 @@ enum { - EXT2_FT_FIFO, - EXT2_FT_SOCK, - EXT2_FT_SYMLINK, -+ EXT2_FT_WHT, -+ EXT2_FT_FALLTHRU, - EXT2_FT_MAX - }; - ---- a/include/linux/fs.h -+++ b/include/linux/fs.h -@@ -188,6 +188,7 @@ struct inodes_stat_t { - #define MS_REMOUNT 32 /* Alter flags of a mounted FS */ - #define MS_MANDLOCK 64 /* Allow mandatory locks on an FS */ - #define MS_DIRSYNC 128 /* Directory modifications are synchronous */ -+#define MS_UNION 256 - #define MS_NOATIME 1024 /* Do not update access times. */ - #define MS_NODIRATIME 2048 /* Do not update directory access times */ - #define MS_BIND 4096 -@@ -205,6 +206,7 @@ struct inodes_stat_t { - #define MS_KERNMOUNT (1<<22) /* this is a kern_mount call */ - #define MS_I_VERSION (1<<23) /* Update inode I_version field */ - #define MS_STRICTATIME (1<<24) /* Always perform atime updates */ -+#define MS_WHITEOUT (1<<26) /* fs does support white-out filetype */ - #define MS_ACTIVE (1<<30) - #define MS_NOUSER (1<<31) - -@@ -231,6 +233,7 @@ struct inodes_stat_t { - #define S_NOCMTIME 128 /* Do not update file c/mtime */ - #define S_SWAPFILE 256 /* Do not truncate: swapon got its bmaps */ - #define S_PRIVATE 512 /* Inode is fs-internal */ -+#define S_OPAQUE 1024 /* Directory is opaque */ - - /* - * Note that nosuid etc flags are inode-specific: setting some file-system -@@ -266,6 +269,8 @@ struct inodes_stat_t { - #define IS_SWAPFILE(inode) ((inode)->i_flags & S_SWAPFILE) - #define IS_PRIVATE(inode) ((inode)->i_flags & S_PRIVATE) - -+#define IS_OPAQUE(inode) ((inode)->i_flags & S_OPAQUE) -+ - /* the read-only stuff doesn't really belong here, but any other place is - probably as bad and I don't want to create yet another include file. */ - -@@ -1379,6 +1384,11 @@ struct super_block { - * generic_show_options() - */ - char *s_options; -+ -+ /* -+ * Users who require read-only access - e.g., union mounts -+ */ -+ int s_readonly_users; - }; - - extern struct timespec current_fs_time(struct super_block *sb); -@@ -1521,6 +1531,8 @@ struct inode_operations { - int (*mkdir) (struct inode *,struct dentry *,int); - int (*rmdir) (struct inode *,struct dentry *); - int (*mknod) (struct inode *,struct dentry *,int,dev_t); -+ int (*whiteout) (struct inode *, struct dentry *, struct dentry *); -+ int (*fallthru) (struct inode *, struct dentry *); - int (*rename) (struct inode *, struct dentry *, - struct inode *, struct dentry *); - int (*readlink) (struct dentry *, char __user *,int); -@@ -2094,6 +2106,7 @@ extern void emergency_remount(void); - extern sector_t bmap(struct inode *, sector_t); - #endif - extern int notify_change(struct dentry *, struct iattr *); -+extern int __inode_permission(struct inode *inode, int mask, int rofs); - extern int inode_permission(struct inode *, int); - extern int generic_permission(struct inode *, int, - int (*check_acl)(struct inode *, int)); -@@ -2121,7 +2134,7 @@ extern void free_write_pipe(struct file - - extern struct file *do_filp_open(int dfd, const char *pathname, - int open_flag, int mode, int acc_mode); --extern int may_open(struct path *, int, int); -+extern int may_open(struct nameidata *, int, int); - - extern int kernel_read(struct file *, loff_t, char *, unsigned long); - extern struct file * open_exec(const char *); ---- a/include/linux/mount.h -+++ b/include/linux/mount.h -@@ -35,6 +35,7 @@ struct mnt_namespace; - #define MNT_SHARED 0x1000 /* if the vfsmount is a shared mount */ - #define MNT_UNBINDABLE 0x2000 /* if the vfsmount is a unbindable mount */ - #define MNT_PNODE_MASK 0x3000 /* propagation flag mask */ -+#define MNT_UNION 0x4000 /* if the vfsmount is a union mount */ - - struct vfsmount { - struct list_head mnt_hash; -@@ -53,6 +54,9 @@ struct vfsmount { - struct list_head mnt_slave_list;/* list of slave mounts */ - struct list_head mnt_slave; /* slave list entry */ - struct vfsmount *mnt_master; /* slave is on master->mnt_slave_list */ -+#ifdef CONFIG_UNION_MOUNT -+ struct list_head mnt_unions; /* list of union_mount structures */ -+#endif - struct mnt_namespace *mnt_ns; /* containing namespace */ - int mnt_id; /* mount identifier */ - int mnt_group_id; /* peer group identifier */ ---- a/include/linux/namei.h -+++ b/include/linux/namei.h -@@ -20,6 +20,7 @@ struct nameidata { - struct qstr last; - struct path root; - unsigned int flags; -+ unsigned int um_flags; - int last_type; - unsigned depth; - char *saved_names[MAX_NESTED_LINKS + 1]; -@@ -35,6 +36,9 @@ struct nameidata { - */ - enum {LAST_NORM, LAST_ROOT, LAST_DOT, LAST_DOTDOT, LAST_BIND}; - -+#define LAST_UNION 0x01 -+#define LAST_LOWLEVEL 0x02 -+ - /* - * The bitmask for a lookup event: - * - follow links at the end -@@ -49,6 +53,8 @@ enum {LAST_NORM, LAST_ROOT, LAST_DOT, LA - #define LOOKUP_CONTINUE 4 - #define LOOKUP_PARENT 16 - #define LOOKUP_REVAL 64 -+#define LOOKUP_TOPMOST 128 -+ - /* - * Intent data - */ ---- /dev/null -+++ b/include/linux/union.h -@@ -0,0 +1,84 @@ -+/* -+ * VFS based union mount for Linux -+ * -+ * Copyright (C) 2004-2007 IBM Corporation, IBM Deutschland Entwicklung GmbH. -+ * Copyright (C) 2007 Novell Inc. -+ * Author(s): Jan Blunck (j.blunck@tu-harburg.de) -+ * -+ * 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. -+ * -+ */ -+#ifndef __LINUX_UNION_H -+#define __LINUX_UNION_H -+#ifdef __KERNEL__ -+ -+#include -+#include -+ -+struct dentry; -+struct vfsmount; -+ -+#ifdef CONFIG_UNION_MOUNT -+ -+/* -+ * The new union mount structure. -+ */ -+struct union_mount { -+ atomic_t u_count; /* reference count */ -+ struct mutex u_mutex; -+ struct list_head u_unions; /* list head for d_unions */ -+ struct list_head u_list; /* list head for mnt_unions */ -+ struct hlist_node u_hash; /* list head for seaching */ -+ struct hlist_node u_rhash; /* list head for reverse seaching */ -+ -+ struct path u_this; /* this is me */ -+ struct path u_next; /* this is what I overlay */ -+}; -+ -+#define IS_UNION(dentry) (!list_empty(&(dentry)->d_unions) || \ -+ (dentry)->d_unionized) -+#define IS_MNT_UNION(mnt) ((mnt)->mnt_flags & MNT_UNION) -+ -+extern int is_unionized(struct dentry *, struct vfsmount *); -+extern int append_to_union(struct vfsmount *, struct dentry *, -+ struct vfsmount *, struct dentry *); -+extern int follow_union_down(struct path *); -+extern int follow_union_mount(struct path *); -+extern void __d_drop_unions(struct dentry *); -+extern void shrink_d_unions(struct dentry *); -+extern void __shrink_d_unions(struct dentry *, struct list_head *); -+extern int attach_mnt_union(struct vfsmount *, struct vfsmount *, -+ struct dentry *); -+extern void detach_mnt_union(struct vfsmount *); -+extern struct dentry *union_create_topmost(struct nameidata *, struct qstr *, -+ struct path *); -+extern int __union_copyup(struct path *, struct nameidata *, struct path *); -+extern int union_copyup(struct nameidata *, int); -+extern int union_copyup_dir(struct path *path); -+extern int union_permission(struct path *, int); -+ -+#else /* CONFIG_UNION_MOUNT */ -+ -+#define IS_UNION(x) (0) -+#define IS_MNT_UNION(x) (0) -+#define is_unionized(x, y) (0) -+#define append_to_union(x1, y1, x2, y2) ({ BUG(); (0); }) -+#define follow_union_down(x) ({ (0); }) -+#define follow_union_mount(x) ({ (0); }) -+#define __d_drop_unions(x) do { } while (0) -+#define shrink_d_unions(x) do { } while (0) -+#define __shrink_d_unions(x,y) do { } while (0) -+#define attach_mnt_union(x, y, z) do { } while (0) -+#define detach_mnt_union(x) do { } while (0) -+#define union_create_topmost(x, y, z) ({ BUG(); (NULL); }) -+#define __union_copyup(x, y, z) ({ BUG(); (0); }) -+#define union_copyup(x, y) ({ (0); }) -+#define union_copyup_dir(x) ({ BUG(); (0); }) -+#define union_permission(x, y) inode_permission(x->dentry->d_inode, y) -+ -+#endif /* CONFIG_UNION_MOUNT */ -+#endif /* __KERNEL__ */ -+#endif /* __LINUX_UNION_H */ ---- a/mm/shmem.c -+++ b/mm/shmem.c -@@ -1794,6 +1794,118 @@ static int shmem_statfs(struct dentry *d - return 0; - } - -+static int shmem_rmdir(struct inode *dir, struct dentry *dentry); -+static int shmem_unlink(struct inode *dir, struct dentry *dentry); -+ -+/* -+ * Create a dentry to signify a whiteout. -+ */ -+static int shmem_whiteout(struct inode *dir, struct dentry *old_dentry, -+ struct dentry *new_dentry) -+{ -+ struct shmem_sb_info *sbinfo = SHMEM_SB(dir->i_sb); -+ struct dentry *dentry; -+ -+ if (!(dir->i_sb->s_flags & MS_WHITEOUT)) -+ return -EPERM; -+ -+ /* This gives us a proper initialized negative dentry */ -+ dentry = simple_lookup(dir, new_dentry, NULL); -+ if (dentry && IS_ERR(dentry)) -+ return PTR_ERR(dentry); -+ -+ /* -+ * No ordinary (disk based) filesystem counts whiteouts as inodes; -+ * but each new link needs a new dentry, pinning lowmem, and -+ * tmpfs dentries cannot be pruned until they are unlinked. -+ */ -+ if (sbinfo->max_inodes) { -+ spin_lock(&sbinfo->stat_lock); -+ if (!sbinfo->free_inodes) { -+ spin_unlock(&sbinfo->stat_lock); -+ return -ENOSPC; -+ } -+ sbinfo->free_inodes--; -+ spin_unlock(&sbinfo->stat_lock); -+ } -+ -+ if (old_dentry->d_inode || d_is_fallthru(old_dentry)) { -+ if (old_dentry->d_inode && S_ISDIR(old_dentry->d_inode->i_mode)) -+ shmem_rmdir(dir, old_dentry); -+ else -+ shmem_unlink(dir, old_dentry); -+ } -+ -+ dir->i_size += BOGO_DIRENT_SIZE; -+ dir->i_ctime = dir->i_mtime = CURRENT_TIME; -+ /* Extra pinning count for the created dentry */ -+ dget(new_dentry); -+ spin_lock(&new_dentry->d_lock); -+ new_dentry->d_flags |= DCACHE_WHITEOUT; -+ spin_unlock(&new_dentry->d_lock); -+ return 0; -+} -+ -+static void shmem_d_instantiate(struct inode *dir, struct dentry *dentry, -+ struct inode *inode); -+ -+/* -+ * Create a dentry to signify a fallthru. A fallthru lets us read the -+ * low-level dentries into the dcache once on the first readdir() and -+ * then -+ */ -+static int shmem_fallthru(struct inode *dir, struct dentry *dentry) -+{ -+ struct shmem_sb_info *sbinfo = SHMEM_SB(dir->i_sb); -+ -+ /* FIXME: this is stupid */ -+ if (!(dir->i_sb->s_flags & MS_WHITEOUT)) -+ return -EPERM; -+ -+ if (dentry->d_inode || d_is_fallthru(dentry) || d_is_whiteout(dentry)) -+ return -EEXIST; -+ -+ /* -+ * Each new link needs a new dentry, pinning lowmem, and tmpfs -+ * dentries cannot be pruned until they are unlinked. -+ */ -+ if (sbinfo->max_inodes) { -+ spin_lock(&sbinfo->stat_lock); -+ if (!sbinfo->free_inodes) { -+ spin_unlock(&sbinfo->stat_lock); -+ return -ENOSPC; -+ } -+ sbinfo->free_inodes--; -+ spin_unlock(&sbinfo->stat_lock); -+ } -+ -+ shmem_d_instantiate(dir, dentry, NULL); -+ dir->i_ctime = dir->i_mtime = CURRENT_TIME; -+ -+ spin_lock(&dentry->d_lock); -+ dentry->d_flags |= DCACHE_FALLTHRU; -+ spin_unlock(&dentry->d_lock); -+ return 0; -+} -+ -+static void shmem_d_instantiate(struct inode *dir, struct dentry *dentry, -+ struct inode *inode) -+{ -+ if (d_is_whiteout(dentry)) { -+ /* Re-using an existing whiteout */ -+ shmem_free_inode(dir->i_sb); -+ if (S_ISDIR(inode->i_mode)) -+ inode->i_mode |= S_OPAQUE; -+ } else if (d_is_fallthru(dentry)) { -+ shmem_free_inode(dir->i_sb); -+ } else { -+ /* New dentry */ -+ dir->i_size += BOGO_DIRENT_SIZE; -+ dget(dentry); /* Extra count - pin the dentry in core */ -+ } -+ /* Will clear DCACHE_WHITEOUT and DCACHE_FALLTHRU flags */ -+ d_instantiate(dentry, inode); -+} - /* - * File creation. Allocate an inode, and we're done.. - */ -@@ -1818,15 +1930,16 @@ shmem_mknod(struct inode *dir, struct de - iput(inode); - return error; - } -+ - if (dir->i_mode & S_ISGID) { - inode->i_gid = dir->i_gid; - if (S_ISDIR(mode)) - inode->i_mode |= S_ISGID; - } -- dir->i_size += BOGO_DIRENT_SIZE; -+ -+ shmem_d_instantiate(dir, dentry, inode); -+ - dir->i_ctime = dir->i_mtime = CURRENT_TIME; -- d_instantiate(dentry, inode); -- dget(dentry); /* Extra count - pin the dentry in core */ - } - return error; - } -@@ -1864,12 +1977,11 @@ static int shmem_link(struct dentry *old - if (ret) - goto out; - -- dir->i_size += BOGO_DIRENT_SIZE; -+ shmem_d_instantiate(dir, dentry, inode); -+ - inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME; - inc_nlink(inode); - atomic_inc(&inode->i_count); /* New dentry reference */ -- dget(dentry); /* Extra pinning count for the created dentry */ -- d_instantiate(dentry, inode); - out: - return ret; - } -@@ -1878,21 +1990,63 @@ static int shmem_unlink(struct inode *di - { - struct inode *inode = dentry->d_inode; - -- if (inode->i_nlink > 1 && !S_ISDIR(inode->i_mode)) -- shmem_free_inode(inode->i_sb); -+ if (d_is_whiteout(dentry) || d_is_fallthru(dentry) || -+ (inode->i_nlink > 1 && !S_ISDIR(inode->i_mode))) -+ shmem_free_inode(dir->i_sb); - -+ if (inode) { -+ inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME; -+ drop_nlink(inode); -+ } - dir->i_size -= BOGO_DIRENT_SIZE; -- inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME; -- drop_nlink(inode); - dput(dentry); /* Undo the count from "create" - this does all the work */ - return 0; - } - -+static void shmem_dir_unlink_whiteouts(struct inode *dir, struct dentry *dentry) -+{ -+ if (!dentry->d_inode) -+ return; -+ -+ /* Remove whiteouts from logical empty directory */ -+ if (S_ISDIR(dentry->d_inode->i_mode) && -+ dentry->d_inode->i_sb->s_flags & MS_WHITEOUT) { -+ struct dentry *child, *next; -+ LIST_HEAD(list); -+ -+ spin_lock(&dcache_lock); -+ list_for_each_entry(child, &dentry->d_subdirs, d_u.d_child) { -+ spin_lock(&child->d_lock); -+ /* Unlink fallthrus too */ -+ if (d_is_whiteout(child) || d_is_fallthru(child)) { -+ __d_drop(child); -+ if (!list_empty(&child->d_lru)) { -+ list_del(&child->d_lru); -+ dentry_stat.nr_unused--; -+ } -+ list_add(&child->d_lru, &list); -+ } -+ spin_unlock(&child->d_lock); -+ } -+ spin_unlock(&dcache_lock); -+ -+ list_for_each_entry_safe(child, next, &list, d_lru) { -+ spin_lock(&child->d_lock); -+ list_del_init(&child->d_lru); -+ spin_unlock(&child->d_lock); -+ -+ shmem_unlink(dentry->d_inode, child); -+ } -+ } -+} -+ - static int shmem_rmdir(struct inode *dir, struct dentry *dentry) - { - if (!simple_empty(dentry)) - return -ENOTEMPTY; - -+ /* Remove whiteouts from logical empty directory */ -+ shmem_dir_unlink_whiteouts(dir, dentry); - drop_nlink(dentry->d_inode); - drop_nlink(dir); - return shmem_unlink(dir, dentry); -@@ -1901,7 +2055,7 @@ static int shmem_rmdir(struct inode *dir - /* - * The VFS layer already does all the dentry stuff for rename, - * we just have to decrement the usage count for the target if -- * it exists so that the VFS layer correctly free's it when it -+ * it exists so that the VFS layer correctly frees it when it - * gets overwritten. - */ - static int shmem_rename(struct inode *old_dir, struct dentry *old_dentry, struct inode *new_dir, struct dentry *new_dentry) -@@ -1912,7 +2066,12 @@ static int shmem_rename(struct inode *ol - if (!simple_empty(new_dentry)) - return -ENOTEMPTY; - -+ if (d_is_whiteout(new_dentry)) -+ shmem_unlink(new_dir, new_dentry); -+ - if (new_dentry->d_inode) { -+ /* Remove whiteouts from logical empty directory */ -+ shmem_dir_unlink_whiteouts(new_dir, new_dentry); - (void) shmem_unlink(new_dir, new_dentry); - if (they_are_dirs) - drop_nlink(old_dir); -@@ -1977,12 +2136,12 @@ static int shmem_symlink(struct inode *d - set_page_dirty(page); - page_cache_release(page); - } -+ -+ shmem_d_instantiate(dir, dentry, inode); -+ - if (dir->i_mode & S_ISGID) - inode->i_gid = dir->i_gid; -- dir->i_size += BOGO_DIRENT_SIZE; - dir->i_ctime = dir->i_mtime = CURRENT_TIME; -- d_instantiate(dentry, inode); -- dget(dentry); - return 0; - } - -@@ -2363,6 +2522,12 @@ static int shmem_fill_super(struct super - if (!root) - goto failed_iput; - sb->s_root = root; -+ -+#ifdef CONFIG_TMPFS -+ if (!(sb->s_flags & MS_NOUSER)) -+ sb->s_flags |= MS_WHITEOUT; -+#endif -+ - return 0; - - failed_iput: -@@ -2462,6 +2627,8 @@ static const struct inode_operations shm - .rmdir = shmem_rmdir, - .mknod = shmem_mknod, - .rename = shmem_rename, -+ .whiteout = shmem_whiteout, -+ .fallthru = shmem_fallthru, - #endif - #ifdef CONFIG_TMPFS_POSIX_ACL - .setattr = shmem_notify_change, diff --git a/target/linux/generic-2.6/patches-2.6.31/231-union_mounts_bind_fix.patch b/target/linux/generic-2.6/patches-2.6.31/231-union_mounts_bind_fix.patch deleted file mode 100644 index 4bd3f7351..000000000 --- a/target/linux/generic-2.6/patches-2.6.31/231-union_mounts_bind_fix.patch +++ /dev/null @@ -1,11 +0,0 @@ ---- a/fs/namespace.c -+++ b/fs/namespace.c -@@ -1550,7 +1550,7 @@ static int do_loopback(struct path *path - if (!mnt) - goto out; - -- err = check_union_mnt(&old_path, mnt, mnt_flags); -+ err = check_union_mnt(path, mnt, mnt_flags); - if (err) - goto out; - diff --git a/target/linux/generic-2.6/patches-2.6.31/232-union_mounts_compile_fix.patch b/target/linux/generic-2.6/patches-2.6.31/232-union_mounts_compile_fix.patch deleted file mode 100644 index b20b845aa..000000000 --- a/target/linux/generic-2.6/patches-2.6.31/232-union_mounts_compile_fix.patch +++ /dev/null @@ -1,11 +0,0 @@ ---- a/include/linux/union.h -+++ b/include/linux/union.h -@@ -77,7 +77,7 @@ extern int union_permission(struct path - #define __union_copyup(x, y, z) ({ BUG(); (0); }) - #define union_copyup(x, y) ({ (0); }) - #define union_copyup_dir(x) ({ BUG(); (0); }) --#define union_permission(x, y) inode_permission(x->dentry->d_inode, y) -+#define union_permission(x, y) inode_permission((x)->dentry->d_inode, y) - - #endif /* CONFIG_UNION_MOUNT */ - #endif /* __KERNEL__ */ diff --git a/target/linux/generic-2.6/patches-2.6.31/233-jffs2_whiteout_support.patch b/target/linux/generic-2.6/patches-2.6.31/233-jffs2_whiteout_support.patch deleted file mode 100644 index 3ae20c30d..000000000 --- a/target/linux/generic-2.6/patches-2.6.31/233-jffs2_whiteout_support.patch +++ /dev/null @@ -1,186 +0,0 @@ ---- a/fs/jffs2/dir.c -+++ b/fs/jffs2/dir.c -@@ -34,6 +34,9 @@ static int jffs2_mknod (struct inode *,s - static int jffs2_rename (struct inode *, struct dentry *, - struct inode *, struct dentry *); - -+static int jffs2_whiteout (struct inode *, struct dentry *, struct dentry *); -+static int jffs2_fallthru (struct inode *, struct dentry *); -+ - const struct file_operations jffs2_dir_operations = - { - .read = generic_read_dir, -@@ -55,6 +58,8 @@ const struct inode_operations jffs2_dir_ - .rmdir = jffs2_rmdir, - .mknod = jffs2_mknod, - .rename = jffs2_rename, -+ .fallthru = jffs2_fallthru, -+ .whiteout = jffs2_whiteout, - .permission = jffs2_permission, - .setattr = jffs2_setattr, - .setxattr = jffs2_setxattr, -@@ -98,8 +103,21 @@ static struct dentry *jffs2_lookup(struc - fd = fd_list; - } - } -- if (fd) -- ino = fd->ino; -+ if (fd) { -+ spin_lock(&target->d_lock); -+ switch(fd->type) { -+ case DT_WHT: -+ target->d_flags |= DCACHE_WHITEOUT; -+ break; -+ case DT_UNKNOWN: -+ target->d_flags |= DCACHE_FALLTHRU; -+ break; -+ default: -+ ino = fd->ino; -+ break; -+ } -+ spin_unlock(&target->d_lock); -+ } - mutex_unlock(&dir_f->sem); - if (ino) { - inode = jffs2_iget(dir_i->i_sb, ino); -@@ -155,7 +173,9 @@ static int jffs2_readdir(struct file *fi - fd->name, fd->ino, fd->type, curofs, offset)); - continue; - } -- if (!fd->ino) { -+ if (fd->type == DT_UNKNOWN) -+ fd->ino = 100; /* XXX: arbitrary */ -+ else if (!fd->ino && (fd->type != DT_WHT)) { - D2(printk(KERN_DEBUG "Skipping deletion dirent \"%s\"\n", fd->name)); - offset++; - continue; -@@ -498,6 +518,11 @@ static int jffs2_mkdir (struct inode *di - return PTR_ERR(inode); - } - -+ if (dentry->d_flags & DCACHE_WHITEOUT) { -+ inode->i_flags |= S_OPAQUE; -+ ri->flags = cpu_to_je16(JFFS2_INO_FLAG_OPAQUE); -+ } -+ - inode->i_op = &jffs2_dir_inode_operations; - inode->i_fop = &jffs2_dir_operations; - -@@ -779,6 +804,82 @@ static int jffs2_mknod (struct inode *di - return 0; - } - -+static int jffs2_fallthru (struct inode *dir, struct dentry *dentry) -+{ -+ struct jffs2_sb_info *c = JFFS2_SB_INFO(dir->i_sb); -+ uint32_t now; -+ int ret; -+ -+ now = get_seconds(); -+ ret = jffs2_do_link(c, JFFS2_INODE_INFO(dir), 0, DT_UNKNOWN, -+ dentry->d_name.name, dentry->d_name.len, now); -+ if (ret) -+ return ret; -+ -+ d_instantiate(dentry, NULL); -+ spin_lock(&dentry->d_lock); -+ dentry->d_flags |= DCACHE_FALLTHRU; -+ spin_unlock(&dentry->d_lock); -+ -+ return 0; -+} -+ -+static int jffs2_whiteout (struct inode *dir, struct dentry *old_dentry, -+ struct dentry *new_dentry) -+{ -+ struct jffs2_sb_info *c = JFFS2_SB_INFO(dir->i_sb); -+ struct jffs2_inode_info *victim_f = NULL; -+ uint32_t now; -+ int ret; -+ -+ /* If it's a directory, then check whether it is really empty -+ */ -+ if (new_dentry->d_inode) { -+ victim_f = JFFS2_INODE_INFO(old_dentry->d_inode); -+ if (S_ISDIR(old_dentry->d_inode->i_mode)) { -+ struct jffs2_full_dirent *fd; -+ -+ mutex_lock(&victim_f->sem); -+ for (fd = victim_f->dents; fd; fd = fd->next) { -+ if (fd->ino) { -+ mutex_unlock(&victim_f->sem); -+ return -ENOTEMPTY; -+ } -+ } -+ mutex_unlock(&victim_f->sem); -+ } -+ } -+ -+ now = get_seconds(); -+ ret = jffs2_do_link(c, JFFS2_INODE_INFO(dir), 0, DT_WHT, -+ new_dentry->d_name.name, new_dentry->d_name.len, now); -+ if (ret) -+ return ret; -+ -+ spin_lock(&new_dentry->d_lock); -+ new_dentry->d_flags &= ~DCACHE_FALLTHRU; -+ new_dentry->d_flags |= DCACHE_WHITEOUT; -+ spin_unlock(&new_dentry->d_lock); -+ d_add(new_dentry, NULL); -+ -+ if (victim_f) { -+ /* There was a victim. Kill it off nicely */ -+ drop_nlink(old_dentry->d_inode); -+ /* Don't oops if the victim was a dirent pointing to an -+ inode which didn't exist. */ -+ if (victim_f->inocache) { -+ mutex_lock(&victim_f->sem); -+ if (S_ISDIR(old_dentry->d_inode->i_mode)) -+ victim_f->inocache->pino_nlink = 0; -+ else -+ victim_f->inocache->pino_nlink--; -+ mutex_unlock(&victim_f->sem); -+ } -+ } -+ -+ return 0; -+} -+ - static int jffs2_rename (struct inode *old_dir_i, struct dentry *old_dentry, - struct inode *new_dir_i, struct dentry *new_dentry) - { ---- a/fs/jffs2/fs.c -+++ b/fs/jffs2/fs.c -@@ -301,6 +301,10 @@ struct inode *jffs2_iget(struct super_bl - - inode->i_op = &jffs2_dir_inode_operations; - inode->i_fop = &jffs2_dir_operations; -+ -+ if (je16_to_cpu(latest_node.flags) & JFFS2_INO_FLAG_OPAQUE) -+ inode->i_flags |= S_OPAQUE; -+ - break; - } - case S_IFREG: ---- a/fs/jffs2/super.c -+++ b/fs/jffs2/super.c -@@ -172,7 +172,7 @@ static int jffs2_fill_super(struct super - - sb->s_op = &jffs2_super_operations; - sb->s_export_op = &jffs2_export_ops; -- sb->s_flags = sb->s_flags | MS_NOATIME; -+ sb->s_flags = sb->s_flags | MS_NOATIME | MS_WHITEOUT; - sb->s_xattr = jffs2_xattr_handlers; - #ifdef CONFIG_JFFS2_FS_POSIX_ACL - sb->s_flags |= MS_POSIXACL; ---- a/include/linux/jffs2.h -+++ b/include/linux/jffs2.h -@@ -87,6 +87,8 @@ - #define JFFS2_INO_FLAG_USERCOMPR 2 /* User has requested a specific - compression type */ - -+#define JFFS2_INO_FLAG_OPAQUE 4 /* Directory is opaque (for union mounts) */ -+ - - /* These can go once we've made sure we've caught all uses without - byteswapping */ diff --git a/target/linux/generic-2.6/patches-2.6.31/234-union_mounts_no_debug.patch b/target/linux/generic-2.6/patches-2.6.31/234-union_mounts_no_debug.patch deleted file mode 100644 index deabd4304..000000000 --- a/target/linux/generic-2.6/patches-2.6.31/234-union_mounts_no_debug.patch +++ /dev/null @@ -1,30 +0,0 @@ ---- a/fs/union.c -+++ b/fs/union.c -@@ -842,10 +842,8 @@ static int union_copyup_dir_one(void *bu - /* Lookup this entry in the topmost directory */ - dentry = lookup_one_len(name, topmost_dentry, namlen); - -- if (IS_ERR(dentry)) { -- printk(KERN_INFO "error looking up %s\n", dentry->d_name.name); -+ if (IS_ERR(dentry)) - goto out; -- } - - /* - * If the entry already exists, one of the following is true: -@@ -857,7 +855,6 @@ static int union_copyup_dir_one(void *bu - */ - if (dentry->d_inode || d_is_whiteout(dentry) || - d_is_fallthru(dentry)) { -- printk(KERN_INFO "skipping copy of %s\n", dentry->d_name.name); - goto out_dput; - } - -@@ -867,7 +864,6 @@ static int union_copyup_dir_one(void *bu - * used, so each file system must implement its own way of - * storing a fallthru entry. - */ -- printk(KERN_INFO "creating fallthru for %s\n", dentry->d_name.name); - err = topmost_dentry->d_inode->i_op->fallthru(topmost_dentry->d_inode, - dentry); - /* FIXME */ diff --git a/target/linux/generic-2.6/patches-2.6.31/235-union_mount_fixes.patch b/target/linux/generic-2.6/patches-2.6.31/235-union_mount_fixes.patch deleted file mode 100644 index cea135105..000000000 --- a/target/linux/generic-2.6/patches-2.6.31/235-union_mount_fixes.patch +++ /dev/null @@ -1,117 +0,0 @@ ---- a/fs/namespace.c -+++ b/fs/namespace.c -@@ -1656,8 +1656,10 @@ static int do_move_mount(struct path *pa - - /* moving to or from a union mount is not supported */ - err = -EINVAL; -+#if 0 - if (IS_MNT_UNION(path->mnt)) - goto exit; -+#endif - if (IS_MNT_UNION(old_path.mnt)) - goto exit; - ---- a/fs/union.c -+++ b/fs/union.c -@@ -260,8 +260,6 @@ int append_to_union(struct vfsmount *mnt - spin_lock(&union_lock); - um = union_lookup(dentry, mnt); - if (um) { -- BUG_ON((um->u_next.dentry != dest_dentry) || -- (um->u_next.mnt != dest_mnt)); - spin_unlock(&union_lock); - union_put(this); - return 0; -@@ -274,6 +272,23 @@ int append_to_union(struct vfsmount *mnt - return 0; - } - -+int follow_union_mountpoint(struct path *path) -+{ -+ struct path new_path = *path; -+ -+ path_get(&new_path); -+ while (follow_union_down(&new_path)) { -+ if (new_path.dentry != new_path.mnt->mnt_root) -+ continue; -+ -+ path_put(path); -+ *path = new_path; -+ return 1; -+ } -+ path_put(&new_path); -+ return 0; -+} -+ - /* - * follow_union_down - follow the union stack one layer down - * ---- a/include/linux/union.h -+++ b/include/linux/union.h -@@ -47,6 +47,7 @@ extern int append_to_union(struct vfsmou - struct vfsmount *, struct dentry *); - extern int follow_union_down(struct path *); - extern int follow_union_mount(struct path *); -+extern int follow_union_mountpoint(struct path *path); - extern void __d_drop_unions(struct dentry *); - extern void shrink_d_unions(struct dentry *); - extern void __shrink_d_unions(struct dentry *, struct list_head *); -@@ -68,6 +69,7 @@ extern int union_permission(struct path - #define append_to_union(x1, y1, x2, y2) ({ BUG(); (0); }) - #define follow_union_down(x) ({ (0); }) - #define follow_union_mount(x) ({ (0); }) -+#define follow_union_mountpoint(x) ({ (0); }) - #define __d_drop_unions(x) do { } while (0) - #define shrink_d_unions(x) do { } while (0) - #define __shrink_d_unions(x,y) do { } while (0) ---- a/fs/namei.c -+++ b/fs/namei.c -@@ -613,6 +613,9 @@ static int cache_lookup_union(struct nam - !S_ISDIR(path->dentry->d_inode->i_mode)) - goto out; - -+ if (follow_union_mountpoint(path)) -+ goto out; -+ - /* Build the union stack for this part */ - res = __cache_lookup_build_union(nd, name, path); - if (res) { -@@ -886,6 +889,9 @@ static int real_lookup_union(struct name - !S_ISDIR(path->dentry->d_inode->i_mode)) - goto out; - -+ if (follow_union_mountpoint(path)) -+ goto out; -+ - /* Build the union stack for this part */ - res = __real_lookup_build_union(nd, name, path); - if (res) { -@@ -1813,6 +1819,9 @@ int hash_lookup_union(struct nameidata * - !S_ISDIR(path->dentry->d_inode->i_mode)) - goto out; - -+ if (follow_union_mountpoint(path)) -+ goto out; -+ - /* Build the union stack for this part */ - res = __hash_lookup_build_union(nd, name, path); - if (res) { ---- a/fs/readdir.c -+++ b/fs/readdir.c -@@ -17,6 +17,7 @@ - #include - #include - #include -+#include - - #include - -@@ -45,7 +46,7 @@ int vfs_readdir(struct file *file, filld - * below this one in the union stack. - */ - if (is_unionized(file->f_path.dentry, file->f_path.mnt) && -- !IS_OPAQUE(inode)) { -+ !IS_OPAQUE(inode) && IS_MNT_UNION(file->f_path.mnt)) { - res = union_copyup_dir(&file->f_path); - if (res) - goto out_unlock; diff --git a/target/linux/generic-2.6/patches-2.6.31/510-yaffs_support.patch b/target/linux/generic-2.6/patches-2.6.31/510-yaffs_support.patch index 287f79303..08a1efc29 100644 --- a/target/linux/generic-2.6/patches-2.6.31/510-yaffs_support.patch +++ b/target/linux/generic-2.6/patches-2.6.31/510-yaffs_support.patch @@ -1,6 +1,6 @@ --- a/fs/Kconfig +++ b/fs/Kconfig -@@ -196,6 +196,7 @@ source "fs/sysv/Kconfig" +@@ -188,6 +188,7 @@ source "fs/sysv/Kconfig" source "fs/ufs/Kconfig" source "fs/exofs/Kconfig" source "fs/nilfs2/Kconfig" @@ -10,7 +10,7 @@ --- a/fs/Makefile +++ b/fs/Makefile -@@ -126,3 +126,4 @@ obj-$(CONFIG_OCFS2_FS) += ocfs2/ +@@ -125,3 +125,4 @@ obj-$(CONFIG_OCFS2_FS) += ocfs2/ obj-$(CONFIG_BTRFS_FS) += btrfs/ obj-$(CONFIG_GFS2_FS) += gfs2/ obj-$(CONFIG_EXOFS_FS) += exofs/ diff --git a/target/linux/generic-2.6/patches-2.6.31/840-unable_to_open_console.patch b/target/linux/generic-2.6/patches-2.6.31/840-unable_to_open_console.patch index d9e443a66..b90a247a8 100644 --- a/target/linux/generic-2.6/patches-2.6.31/840-unable_to_open_console.patch +++ b/target/linux/generic-2.6/patches-2.6.31/840-unable_to_open_console.patch @@ -1,6 +1,6 @@ --- a/init/main.c +++ b/init/main.c -@@ -844,7 +844,7 @@ static noinline int init_post(void) +@@ -839,7 +839,7 @@ static noinline int init_post(void) numa_default_policy(); if (sys_open((const char __user *) "/dev/console", O_RDWR, 0) < 0) diff --git a/target/linux/generic-2.6/patches-2.6.31/980-vm_exports.patch b/target/linux/generic-2.6/patches-2.6.31/980-vm_exports.patch index 8ad4cb296..1b8f3a930 100644 --- a/target/linux/generic-2.6/patches-2.6.31/980-vm_exports.patch +++ b/target/linux/generic-2.6/patches-2.6.31/980-vm_exports.patch @@ -1,6 +1,6 @@ --- a/mm/shmem.c +++ b/mm/shmem.c -@@ -2769,6 +2769,16 @@ int shmem_unuse(swp_entry_t entry, struc +@@ -2602,6 +2602,16 @@ int shmem_unuse(swp_entry_t entry, struc /* common code */ @@ -17,7 +17,7 @@ /** * shmem_file_setup - get an unlinked file living in tmpfs * @name: name for dentry (to be seen in /proc//maps -@@ -2848,10 +2858,7 @@ int shmem_zero_setup(struct vm_area_stru +@@ -2681,10 +2691,7 @@ int shmem_zero_setup(struct vm_area_stru if (IS_ERR(file)) return PTR_ERR(file); diff --git a/target/linux/generic-2.6/patches-2.6.31/999-use_preinit_as_init.patch b/target/linux/generic-2.6/patches-2.6.31/999-use_preinit_as_init.patch index 5d1f61ff0..c85113ddd 100644 --- a/target/linux/generic-2.6/patches-2.6.31/999-use_preinit_as_init.patch +++ b/target/linux/generic-2.6/patches-2.6.31/999-use_preinit_as_init.patch @@ -1,6 +1,6 @@ --- a/init/main.c +++ b/init/main.c -@@ -868,10 +868,7 @@ static noinline int init_post(void) +@@ -863,10 +863,7 @@ static noinline int init_post(void) printk(KERN_WARNING "Failed to execute %s. Attempting " "defaults...\n", execute_command); } diff --git a/target/linux/generic-2.6/patches-2.6.32/013-gcc4_inline_fix.patch b/target/linux/generic-2.6/patches-2.6.32/013-gcc4_inline_fix.patch index 9997ff283..77ab40543 100644 --- a/target/linux/generic-2.6/patches-2.6.32/013-gcc4_inline_fix.patch +++ b/target/linux/generic-2.6/patches-2.6.32/013-gcc4_inline_fix.patch @@ -1,8 +1,8 @@ --- a/arch/mips/include/asm/system.h +++ b/arch/mips/include/asm/system.h -@@ -197,7 +197,7 @@ extern __u64 __xchg_u64_unsupported_on_3 - if something tries to do an invalid xchg(). */ - extern void __xchg_called_with_bad_pointer(void); +@@ -194,7 +194,7 @@ extern __u64 __xchg_u64_unsupported_on_3 + #define __xchg_u64 __xchg_u64_unsupported_on_32bit_kernels + #endif -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) diff --git a/target/linux/generic-2.6/patches-2.6.32/020-mips_multi_machine_support.patch b/target/linux/generic-2.6/patches-2.6.32/020-mips_multi_machine_support.patch index 3ffd2f331..4c98b73f8 100644 --- a/target/linux/generic-2.6/patches-2.6.32/020-mips_multi_machine_support.patch +++ b/target/linux/generic-2.6/patches-2.6.32/020-mips_multi_machine_support.patch @@ -1,6 +1,6 @@ --- /dev/null +++ b/include/asm-mips/mips_machine.h -@@ -0,0 +1,46 @@ +@@ -0,0 +1,47 @@ +/* + * Copyright (C) 2008-2009 Gabor Juhos + * @@ -25,6 +25,7 @@ + +void mips_machine_register(struct mips_machine *) __init; +void mips_machine_setup(unsigned long machtype) __init; ++void mips_machine_set_name(char *name) __init; + +extern char *mips_machine_name; + @@ -49,7 +50,7 @@ + --- /dev/null +++ b/arch/mips/kernel/mips_machine.c -@@ -0,0 +1,70 @@ +@@ -0,0 +1,74 @@ +/* + * Copyright (C) 2008-2009 Gabor Juhos + * @@ -88,6 +89,25 @@ + list_add_tail(&mach->list, &mips_machines); +} + ++void __init mips_machine_set_name(char *name) ++{ ++ unsigned int len; ++ char *p; ++ ++ if (name == NULL) ++ return; ++ ++ len = strlen(name); ++ p = kmalloc(len + 1, GFP_KERNEL); ++ if (p) { ++ strncpy(p, name, len); ++ p[len] = '\0'; ++ mips_machine_name = p; ++ } else { ++ printk(KERN_WARNING "MIPS: no memory for machine_name\n"); ++ } ++} ++ +void __init mips_machine_setup(unsigned long machtype) +{ + struct mips_machine *mach; @@ -99,27 +119,12 @@ + return; + } + -+ if (mach->mach_name) { -+ char *name; -+ unsigned int len; -+ -+ len = strlen(mach->mach_name); -+ name = kmalloc(len + 1, GFP_KERNEL); -+ if (name) { -+ strncpy(name, mach->mach_name,len); -+ name[len] = '\0'; -+ mips_machine_name = name; -+ } else { -+ printk(KERN_WARNING "MIPS: no memory for machine_name\n"); -+ } -+ } -+ ++ mips_machine_set_name(mach->mach_name); + 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 @@ -87,6 +87,7 @@ obj-$(CONFIG_GPIO_TXX9) += gpio_txx9.o @@ -132,7 +137,7 @@ --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig -@@ -840,6 +840,9 @@ config MIPS_DISABLE_OBSOLETE_IDE +@@ -854,6 +854,9 @@ config MIPS_DISABLE_OBSOLETE_IDE config SYNC_R4K bool diff --git a/target/linux/generic-2.6/patches-2.6.32/021-mips_image_cmdline_hack.patch b/target/linux/generic-2.6/patches-2.6.32/021-mips_image_cmdline_hack.patch index 5efd93d35..8b9cfe32c 100644 --- a/target/linux/generic-2.6/patches-2.6.32/021-mips_image_cmdline_hack.patch +++ b/target/linux/generic-2.6/patches-2.6.32/021-mips_image_cmdline_hack.patch @@ -1,6 +1,6 @@ --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig -@@ -843,6 +843,10 @@ config SYNC_R4K +@@ -857,6 +857,10 @@ config SYNC_R4K config MIPS_MACHINE def_bool n diff --git a/target/linux/generic-2.6/patches-2.6.32/022-mips_use_generic_thread_info_allocator.patch b/target/linux/generic-2.6/patches-2.6.32/022-mips_use_generic_thread_info_allocator.patch new file mode 100644 index 000000000..786afd1dc --- /dev/null +++ b/target/linux/generic-2.6/patches-2.6.32/022-mips_use_generic_thread_info_allocator.patch @@ -0,0 +1,18 @@ +--- a/arch/mips/include/asm/thread_info.h ++++ b/arch/mips/include/asm/thread_info.h +@@ -83,6 +83,7 @@ register struct thread_info *__current_t + #define THREAD_SIZE (PAGE_SIZE << THREAD_SIZE_ORDER) + #define THREAD_MASK (THREAD_SIZE - 1UL) + ++#if 0 + #define __HAVE_ARCH_THREAD_INFO_ALLOCATOR + + #ifdef CONFIG_DEBUG_STACK_USAGE +@@ -92,6 +93,7 @@ register struct thread_info *__current_t + #endif + + #define free_thread_info(info) kfree(info) ++#endif + + #endif /* !__ASSEMBLY__ */ + diff --git a/target/linux/generic-2.6/patches-2.6.32/025-mips_disable_fpu.patch b/target/linux/generic-2.6/patches-2.6.32/025-mips_disable_fpu.patch index 43383916c..e1e9f7369 100644 --- a/target/linux/generic-2.6/patches-2.6.32/025-mips_disable_fpu.patch +++ b/target/linux/generic-2.6/patches-2.6.32/025-mips_disable_fpu.patch @@ -8,7 +8,7 @@ Signed-off-by: Florian Fainelli -- --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig -@@ -828,6 +828,17 @@ config I8259 +@@ -842,6 +842,17 @@ config I8259 config MIPS_BONITO64 bool diff --git a/target/linux/generic-2.6/patches-2.6.32/027-mips_module_reloc.patch b/target/linux/generic-2.6/patches-2.6.32/027-mips_module_reloc.patch index f65a09c94..c0dc64e26 100644 --- a/target/linux/generic-2.6/patches-2.6.32/027-mips_module_reloc.patch +++ b/target/linux/generic-2.6/patches-2.6.32/027-mips_module_reloc.patch @@ -16,10 +16,10 @@ const struct exception_table_entry *dbe_start; const struct exception_table_entry *dbe_end; + -+ void *plt_tbl; -+ unsigned int core_plt_offset; -+ unsigned int core_plt_size; -+ unsigned int init_plt_offset; ++ void *phys_plt_tbl; ++ void *virt_plt_tbl; ++ unsigned int phys_plt_offset; ++ unsigned int virt_plt_offset; }; typedef uint8_t Elf64_Byte; /* Type for a 8-bit quantity. */ @@ -143,7 +143,7 @@ void *module_alloc(unsigned long size) { #ifdef MODULE_START -@@ -58,21 +169,68 @@ void *module_alloc(unsigned long size) +@@ -58,21 +169,99 @@ void *module_alloc(unsigned long size) return __vmalloc_area(area, GFP_KERNEL, PAGE_KERNEL); #else @@ -188,6 +188,25 @@ + } else { + vfree(module_region); + } ++} ++ ++static void *__module_alloc(int size, bool phys) ++{ ++ void *ptr; ++ ++ if (phys) ++ ptr = kmalloc(size, GFP_KERNEL); ++ else ++ ptr = vmalloc(size); ++ return ptr; ++} ++ ++static void __module_free(void *ptr) ++{ ++ if (is_phys_addr(ptr)) ++ kfree(ptr); ++ else ++ vfree(ptr); } int module_frob_arch_sections(Elf_Ehdr *hdr, Elf_Shdr *sechdrs, @@ -204,17 +223,29 @@ + core_size = get_plt_size(hdr, sechdrs, secstrings, symindex, false); + init_size = get_plt_size(hdr, sechdrs, secstrings, symindex, true); + -+ mod->arch.core_plt_offset = 0; -+ mod->arch.core_plt_size = core_size; -+ mod->arch.init_plt_offset = core_size; -+ mod->arch.plt_tbl = kmalloc(core_size + init_size, GFP_KERNEL); -+ if (!mod->arch.plt_tbl) ++ mod->arch.phys_plt_offset = 0; ++ mod->arch.virt_plt_offset = 0; ++ mod->arch.phys_plt_tbl = NULL; ++ mod->arch.virt_plt_tbl = NULL; ++ ++ if ((core_size + init_size) == 0) ++ return 0; ++ ++ mod->arch.phys_plt_tbl = __module_alloc(core_size + init_size, 1); ++ if (!mod->arch.phys_plt_tbl) + return -ENOMEM; ++ ++ mod->arch.virt_plt_tbl = __module_alloc(core_size + init_size, 0); ++ if (!mod->arch.virt_plt_tbl) { ++ __module_free(mod->arch.phys_plt_tbl); ++ mod->arch.phys_plt_tbl = NULL; ++ return -ENOMEM; ++ } + return 0; } -@@ -95,28 +253,40 @@ static int apply_r_mips_32_rela(struct m +@@ -95,28 +284,36 @@ static int apply_r_mips_32_rela(struct m return 0; } @@ -239,38 +270,35 @@ + /* adjust carry for addiu */ + if (v & 0x00008000) + v += 0x10000; -+ + +- *location = (*location & ~0x03ffffff) | +- ((*location + (v >> 2)) & 0x03ffffff); + tramp[0] = 0x3c190000 | (v >> 16); /* lui t9, hi16 */ + tramp[1] = 0x27390000 | (v & 0xffff); /* addiu t9, t9, lo16 */ + tramp[2] = 0x03200008; /* jr t9 */ + tramp[3] = 0x00000000; /* nop */ -- *location = (*location & ~0x03ffffff) | -- ((*location + (v >> 2)) & 0x03ffffff); +- return 0; + return (Elf_Addr) tramp; -+} -+ -+static Elf_Addr add_plt_entry(struct module *me, void *location, Elf_Addr v) -+{ -+ if (location >= me->module_core && -+ location < me->module_core + me->core_size) -+ return add_plt_entry_to(&me->arch.core_plt_offset, -+ me->arch.plt_tbl, v); -+ -+ if (location >= me->module_init && -+ location < me->module_init + me->init_size) -+ return add_plt_entry_to(&me->arch.init_plt_offset, -+ me->arch.plt_tbl, v); - - return 0; } -static int apply_r_mips_26_rela(struct module *me, u32 *location, Elf_Addr v) ++static Elf_Addr add_plt_entry(struct module *me, void *location, Elf_Addr v) ++{ ++ if (is_phys_addr(location)) ++ return add_plt_entry_to(&me->arch.phys_plt_offset, ++ me->arch.phys_plt_tbl, v); ++ else ++ return add_plt_entry_to(&me->arch.virt_plt_offset, ++ me->arch.virt_plt_tbl, v); ++ ++} ++ +static int set_r_mips_26(struct module *me, u32 *location, u32 ofs, Elf_Addr v) { if (v % 4) { pr_err("module %s: dangerous R_MIPS_26 RELArelocation\n", -@@ -125,17 +295,31 @@ static int apply_r_mips_26_rela(struct m +@@ -125,17 +322,31 @@ static int apply_r_mips_26_rela(struct m } if ((v & 0xf0000000) != (((unsigned long)location + 4) & 0xf0000000)) { @@ -305,18 +333,20 @@ static int apply_r_mips_hi16_rel(struct module *me, u32 *location, Elf_Addr v) { struct mips_hi16 *n; -@@ -400,11 +584,23 @@ int module_finalize(const Elf_Ehdr *hdr, +@@ -400,11 +611,32 @@ int module_finalize(const Elf_Ehdr *hdr, list_add(&me->arch.dbe_list, &dbe_list); spin_unlock_irq(&dbe_lock); } + + /* Get rid of the fixup trampoline if we're running the module + * from physically mapped address space */ -+ if (me->arch.core_plt_offset == 0 && -+ me->arch.init_plt_offset == me->arch.core_plt_size && -+ is_phys_addr(me->module_core)) { -+ kfree(me->arch.plt_tbl); -+ me->arch.plt_tbl = NULL; ++ if (me->arch.phys_plt_offset == 0) { ++ __module_free(me->arch.phys_plt_tbl); ++ me->arch.phys_plt_tbl = NULL; ++ } ++ if (me->arch.virt_plt_offset == 0) { ++ __module_free(me->arch.virt_plt_tbl); ++ me->arch.virt_plt_tbl = NULL; + } + return 0; @@ -324,8 +354,15 @@ void module_arch_cleanup(struct module *mod) { -+ if (mod->arch.plt_tbl) -+ kfree(mod->arch.plt_tbl); ++ if (mod->arch.phys_plt_tbl) { ++ __module_free(mod->arch.phys_plt_tbl); ++ mod->arch.phys_plt_tbl = NULL; ++ } ++ if (mod->arch.virt_plt_tbl) { ++ __module_free(mod->arch.virt_plt_tbl); ++ mod->arch.virt_plt_tbl = NULL; ++ } ++ spin_lock_irq(&dbe_lock); list_del(&mod->arch.dbe_list); spin_unlock_irq(&dbe_lock); diff --git a/target/linux/generic-2.6/patches-2.6.32/200-sched_esfq.patch b/target/linux/generic-2.6/patches-2.6.32/200-sched_esfq.patch index fb28e9085..f3636e652 100644 --- a/target/linux/generic-2.6/patches-2.6.32/200-sched_esfq.patch +++ b/target/linux/generic-2.6/patches-2.6.32/200-sched_esfq.patch @@ -90,7 +90,7 @@ obj-$(CONFIG_NET_SCH_PRIO) += sch_prio.o --- /dev/null +++ b/net/sched/sch_esfq.c -@@ -0,0 +1,700 @@ +@@ -0,0 +1,702 @@ +/* + * net/sched/sch_esfq.c Extended Stochastic Fairness Queueing discipline. + * @@ -144,7 +144,9 @@ +#include +#include +#include ++#ifdef CONFIG_NET_SCH_ESFQ_NFCT +#include ++#endif + +/* Stochastic Fairness Queuing algorithm. + For more comments look at sch_sfq.c. diff --git a/target/linux/generic-2.6/patches-2.6.32/230-union_mounts.patch b/target/linux/generic-2.6/patches-2.6.32/230-union_mounts.patch deleted file mode 100644 index 23236a07c..000000000 --- a/target/linux/generic-2.6/patches-2.6.32/230-union_mounts.patch +++ /dev/null @@ -1,5203 +0,0 @@ ---- /dev/null -+++ b/Documentation/filesystems/union-mounts.txt -@@ -0,0 +1,187 @@ -+VFS based Union Mounts -+---------------------- -+ -+ 1. What are "Union Mounts" -+ 2. The Union Stack -+ 3. Whiteouts, Opaque Directories, and Fallthrus -+ 4. Copy-up -+ 5. Directory Reading -+ 6. Known Problems -+ 7. References -+ -+------------------------------------------------------------------------------- -+ -+1. What are "Union Mounts" -+========================== -+ -+Please note: this is NOT about UnionFS and it is NOT derived work! -+ -+Traditionally the mount operation is opaque, which means that the content of -+the mount point, the directory where the file system is mounted on, is hidden -+by the content of the mounted file system's root directory until the file -+system is unmounted again. Unlike the traditional UNIX mount mechanism, that -+hides the contents of the mount point, a union mount presents a view as if -+both filesystems are merged together. Although only the topmost layer of the -+mount stack can be altered, it appears as if transparent file system mounts -+allow any file to be created, modified or deleted. -+ -+Most people know the concepts and features of union mounts from other -+operating systems like Sun's Translucent Filesystem, Plan9 or BSD. For an -+in-depth review of union mounts and other unioning file systems, see: -+ -+http://lwn.net/Articles/324291/ -+http://lwn.net/Articles/325369/ -+http://lwn.net/Articles/327738/ -+ -+Here are the key features of this implementation: -+- completely VFS based -+- does not change the namespace stacking -+- directory listings have duplicate entries removed in the kernel -+- writable unions: only the topmost file system layer may be writable -+- writable unions: new whiteout filetype handled inside the kernel -+ -+------------------------------------------------------------------------------- -+ -+2. The Union Stack -+================== -+ -+The mounted file systems are organized in the "file system hierarchy" (tree of -+vfsmount structures), which keeps track about the stacking of file systems -+upon each other. The per-directory view on the file system hierarchy is called -+"mount stack" and reflects the order of file systems, which are mounted on a -+specific directory. -+ -+Union mounts present a single unified view of the contents of two or more file -+systems as if they are merged together. Since the information which file -+system objects are part of a unified view is not directly available from the -+file system hierarchy there is a need for a new structure. The file system -+objects, which are part of a unified view are ordered in a so-called "union -+stack". Only directories can be part of a unified view. -+ -+The link between two layers of the union stack is maintained using the -+union_mount structure (#include ): -+ -+struct union_mount { -+ atomic_t u_count; /* reference count */ -+ struct mutex u_mutex; -+ struct list_head u_unions; /* list head for d_unions */ -+ struct hlist_node u_hash; /* list head for searching */ -+ struct hlist_node u_rhash; /* list head for reverse searching */ -+ -+ struct path u_this; /* this is me */ -+ struct path u_next; /* this is what I overlay */ -+}; -+ -+The union_mount structure holds a reference (dget,mntget) to the next lower -+layer of the union stack. Since a dentry can be part of multiple unions -+(e.g. with bind mounts) they are tied together via the d_unions field of the -+dentry structure. -+ -+All union_mount structures are cached in two hash tables, one for lookups of -+the next lower layer of the union stack and one for reverse lookups of the -+next upper layer of the union stack. The reverse lookup is necessary to -+resolve CWD relative path lookups. For calculation of the hash value, the -+(dentry,vfsmount) pair is used. The u_this field is used for the hash table -+which is used in forward lookups and the u_next field for the reverse lookups. -+ -+During every new mount (or mount propagation), a new union_mount structure is -+allocated. A reference to the mountpoint's vfsmount and dentry is taken and -+stored in the u_next field. In almost the same manner an union_mount -+structure is created during the first time lookup of a directory within a -+union mount point. In this case the lookup proceeds to all lower layers of the -+union. Therefore the complete union stack is constructed during lookups. -+ -+The union_mount structures of a dentry are destroyed when the dentry itself is -+destroyed. Therefore the dentry cache is indirectly driving the union_mount -+cache like this is done for inodes too. Please note that lower layer -+union_mount structures are kept in memory until the topmost dentry is -+destroyed. -+ -+------------------------------------------------------------------------------- -+ -+3. Whiteouts, Opaque Directories, and Fallthrus -+=========================================================== -+ -+The whiteout filetype isn't new. It has been there for quite some time now -+but Linux's VFS hasn't used it yet. With the availability of union mount code -+inside the VFS the whiteout filetype is getting important to support writable -+union mounts. For read-only union mounts, support for whiteouts or -+copy-on-open is not necessary. -+ -+The whiteout filetype has the same function as negative dentries: they -+describe a filename which isn't there. The creation of whiteouts needs -+lowlevel filesystem support. At the time of writing this, there is whiteout -+support for tmpfs, ext2 and ext3 available. The VFS is extended to make the -+whiteout handling transparent to all its users. The whiteouts are not -+visible to user-space. -+ -+What happens when we create a directory that was previously whited-out? We -+don't want the directory entries from underlying filesystems to suddenly appear -+in the newly created directory. So we mark the directory opaque (the file -+system must support storage of the opaque flag). -+ -+Fallthrus are directory entries that override the opaque flag on a directory -+for that specific directory entry name (the lookup "falls through" to the next -+layer of the union mount). Fallthrus are mainly useful for implementing -+readdir(). -+ -+------------------------------------------------------------------------------- -+ -+4. Copy-up -+=========== -+ -+Any write to an object on any layer other than the topmost triggers a copy-up -+of the object to the topmost file system. For regular files, the copy-up -+happens when it is opened in writable mode. -+ -+Directories are copied up on open, regardless of intent to write, to simplify -+copy-up of any object located below it in the namespace. Otherwise we have to -+walk the entire pathname to create intermediate directories whenever we do a -+copy-up. This is the same approach as BSD union mounts and uses a negigible -+amount of disk space. Note that the actual directory entries themselves are -+not copied-up from the lower levels until (a) the directory is written to, or -+(b) the first readdir() of the directory (more on that later). -+ -+Rename across different levels of the union is implemented as a copy-up -+operation for regular files. Rename of directories simply returns EXDEV, the -+same as if we tried to rename across different mounts. Most applications have -+to handle this case anyway. Some applications do not expect EXDEV on -+rename operations within the same directory, but these applications will also -+be broken with bind mounts. -+ -+------------------------------------------------------------------------------- -+ -+5. Directory Reading -+==================== -+ -+readdir() is somewhat difficult to implement in a unioning file system. We must -+eliminate duplicates, apply whiteouts, and start up readdir() where we left -+off, given a single f_pos value. Our solution is to copy up all the directory -+entries to the topmost directory the first time readdir() is called on a -+directory. During this copy-up, we skip duplicates and entries covered by -+whiteouts, and then create fallthru entries for each remaining visible dentry. -+Then we mark the whole directory opaque. From then on, we just use the topmost -+file system's normal readdir() operation. -+ -+------------------------------------------------------------------------------- -+ -+6. Known Problems -+================= -+ -+- copyup() for other filetypes that reg and dir (e.g. for chown() on devices) -+- symlinks are untested -+ -+------------------------------------------------------------------------------- -+ -+7. References -+============= -+ -+[1] http://marc.info/?l=linux-fsdevel&m=96035682927821&w=2 -+[2] http://marc.info/?l=linux-fsdevel&m=117681527820133&w=2 -+[3] http://marc.info/?l=linux-fsdevel&m=117913503200362&w=2 -+[4] http://marc.info/?l=linux-fsdevel&m=118231827024394&w=2 -+ -+Authors: -+Jan Blunck -+Bharata B Rao -+Valerie Aurora ---- a/fs/autofs4/autofs_i.h -+++ b/fs/autofs4/autofs_i.h -@@ -130,6 +130,7 @@ struct autofs_sb_info { - int reghost_enabled; - int needs_reghost; - struct super_block *sb; -+ struct vfsmount *mnt; - struct mutex wq_mutex; - spinlock_t fs_lock; - struct autofs_wait_queue *queues; /* Wait queue pointer */ ---- a/fs/autofs4/init.c -+++ b/fs/autofs4/init.c -@@ -17,7 +17,16 @@ - static int autofs_get_sb(struct file_system_type *fs_type, - int flags, const char *dev_name, void *data, struct vfsmount *mnt) - { -- return get_sb_nodev(fs_type, flags, data, autofs4_fill_super, mnt); -+ struct autofs_sb_info *sbi; -+ int ret; -+ -+ ret = get_sb_nodev(fs_type, flags, data, autofs4_fill_super, mnt); -+ if (ret) -+ return ret; -+ -+ sbi = autofs4_sbi(mnt->mnt_sb); -+ sbi->mnt = mnt; -+ return 0; - } - - static struct file_system_type autofs_fs_type = { ---- a/fs/autofs4/root.c -+++ b/fs/autofs4/root.c -@@ -179,6 +179,12 @@ static void *autofs4_follow_link(struct - DPRINTK("dentry=%p %.*s oz_mode=%d nd->flags=%d", - dentry, dentry->d_name.len, dentry->d_name.name, oz_mode, - nd->flags); -+ -+ dput(nd->path.dentry); -+ mntput(nd->path.mnt); -+ nd->path.mnt = mntget(sbi->mnt); -+ nd->path.dentry = dget(dentry); -+ - /* - * For an expire of a covered direct or offset mount we need - * to break out of follow_down() at the autofs mount trigger ---- a/fs/compat.c -+++ b/fs/compat.c -@@ -840,6 +840,9 @@ static int compat_fillonedir(void *__buf - struct compat_old_linux_dirent __user *dirent; - compat_ulong_t d_ino; - -+ if (d_type == DT_WHT) -+ return 0; -+ - if (buf->result) - return -EINVAL; - d_ino = ino; -@@ -911,6 +914,9 @@ static int compat_filldir(void *__buf, c - compat_ulong_t d_ino; - int reclen = ALIGN(NAME_OFFSET(dirent) + namlen + 2, sizeof(compat_long_t)); - -+ if (d_type == DT_WHT) -+ return 0; -+ - buf->error = -EINVAL; /* only used if we fail.. */ - if (reclen > buf->count) - return -EINVAL; -@@ -1000,6 +1006,9 @@ static int compat_filldir64(void * __buf - int reclen = ALIGN(jj + namlen + 1, sizeof(u64)); - u64 off; - -+ if (d_type == DT_WHT) -+ return 0; -+ - buf->error = -EINVAL; /* only used if we fail.. */ - if (reclen > buf->count) - return -EINVAL; ---- a/fs/dcache.c -+++ b/fs/dcache.c -@@ -18,6 +18,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -158,14 +159,19 @@ static void dentry_lru_del_init(struct d - } - - /** -- * d_kill - kill dentry and return parent -+ * __d_kill - kill dentry and return parent - * @dentry: dentry to kill -+ * @list: kill list -+ * @greedy: return parent instead of putting it on the kill list - * - * The dentry must already be unhashed and removed from the LRU. - * -- * If this is the root of the dentry tree, return NULL. -+ * If this is the root of the dentry tree, return NULL. If greedy is zero, we -+ * put the parent of this dentry on the kill list instead. The callers must -+ * make sure that __d_kill_final() is called on all dentries on the kill list. - */ --static struct dentry *d_kill(struct dentry *dentry) -+static struct dentry *__d_kill(struct dentry *dentry, struct list_head *list, -+ int greedy) - __releases(dentry->d_lock) - __releases(dcache_lock) - { -@@ -173,13 +179,78 @@ static struct dentry *d_kill(struct dent - - list_del(&dentry->d_u.d_child); - dentry_stat.nr_dentry--; /* For d_free, below */ -- /*drops the locks, at that point nobody can reach this dentry */ -+ -+ /* -+ * If we are not greedy we just put this on a list for later processing -+ * (follow up to parent, releasing of inode and freeing dentry memory). -+ */ -+ if (!greedy) { -+ list_del_init(&dentry->d_alias); -+ /* at this point nobody can reach this dentry */ -+ list_add(&dentry->d_lru, list); -+ spin_unlock(&dentry->d_lock); -+ spin_unlock(&dcache_lock); -+ __shrink_d_unions(dentry, list); -+ return NULL; -+ } -+ -+ /* drops the locks, at that point nobody can reach this dentry */ - dentry_iput(dentry); -+ /* If the dentry was in an union delete them */ -+ __shrink_d_unions(dentry, list); -+ if (IS_ROOT(dentry)) -+ parent = NULL; -+ else -+ parent = dentry->d_parent; -+ d_free(dentry); -+ return parent; -+} -+ -+void __dput(struct dentry *, struct list_head *, int); -+ -+static void __d_kill_final(struct dentry *dentry, struct list_head *list) -+{ -+ struct dentry *parent; -+ struct inode *inode = dentry->d_inode; -+ -+ if (inode) { -+ dentry->d_inode = NULL; -+ if (!inode->i_nlink) -+ fsnotify_inoderemove(inode); -+ if (dentry->d_op && dentry->d_op->d_iput) -+ dentry->d_op->d_iput(dentry, inode); -+ else -+ iput(inode); -+ } -+ - if (IS_ROOT(dentry)) - parent = NULL; - else - parent = dentry->d_parent; - d_free(dentry); -+ __dput(parent, list, 1); -+} -+ -+/** -+ * d_kill - kill dentry and return parent -+ * @dentry: dentry to kill -+ * -+ * The dentry must already be unhashed and removed from the LRU. -+ * -+ * If this is the root of the dentry tree, return NULL. -+ */ -+static struct dentry *d_kill(struct dentry *dentry) -+{ -+ LIST_HEAD(mortuary); -+ struct dentry *parent; -+ -+ parent = __d_kill(dentry, &mortuary, 1); -+ while (!list_empty(&mortuary)) { -+ dentry = list_entry(mortuary.next, struct dentry, d_lru); -+ list_del(&dentry->d_lru); -+ __d_kill_final(dentry, &mortuary); -+ } -+ - return parent; - } - -@@ -200,19 +271,24 @@ static struct dentry *d_kill(struct dent - * Real recursion would eat up our stack space. - */ - --/* -- * dput - release a dentry -- * @dentry: dentry to release -+/** -+ * __dput - release a dentry -+ * @dentry: dentry to release -+ * @list: kill list argument for __d_kill() -+ * @greedy: greedy argument for __d_kill() - * - * Release a dentry. This will drop the usage count and if appropriate - * call the dentry unlink method as well as removing it from the queues and - * releasing its resources. If the parent dentries were scheduled for release -- * they too may now get deleted. -+ * they too may now get deleted if @greedy is not zero. Otherwise parent is -+ * added to the kill list. The callers must make sure that __d_kill_final() is -+ * called on all dentries on the kill list. -+ * -+ * You probably want to use dput() instead. - * - * no dcache lock, please. - */ -- --void dput(struct dentry *dentry) -+void __dput(struct dentry *dentry, struct list_head *list, int greedy) - { - if (!dentry) - return; -@@ -253,12 +329,35 @@ unhash_it: - kill_it: - /* if dentry was on the d_lru list delete it from there */ - dentry_lru_del(dentry); -- dentry = d_kill(dentry); -+ dentry = __d_kill(dentry, list, greedy); - if (dentry) - goto repeat; - } - - /** -+ * dput - release a dentry -+ * @dentry: dentry to release -+ * -+ * Release a dentry. This will drop the usage count and if appropriate -+ * call the dentry unlink method as well as removing it from the queues and -+ * releasing its resources. If the parent dentries were scheduled for release -+ * they too may now get deleted. -+ * -+ * no dcache lock, please. -+ */ -+void dput(struct dentry *dentry) -+{ -+ LIST_HEAD(mortuary); -+ -+ __dput(dentry, &mortuary, 1); -+ while (!list_empty(&mortuary)) { -+ dentry = list_entry(mortuary.next, struct dentry, d_lru); -+ list_del(&dentry->d_lru); -+ __d_kill_final(dentry, &mortuary); -+ } -+} -+ -+/** - * d_invalidate - invalidate a dentry - * @dentry: dentry to invalidate - * -@@ -690,6 +789,7 @@ static void shrink_dcache_for_umount_sub - iput(inode); - } - -+ shrink_d_unions(dentry); - d_free(dentry); - - /* finished when we fall off the top of the tree, -@@ -952,6 +1052,10 @@ struct dentry *d_alloc(struct dentry * p - INIT_LIST_HEAD(&dentry->d_lru); - INIT_LIST_HEAD(&dentry->d_subdirs); - INIT_LIST_HEAD(&dentry->d_alias); -+#ifdef CONFIG_UNION_MOUNT -+ INIT_LIST_HEAD(&dentry->d_unions); -+ dentry->d_unionized = 0; -+#endif - - if (parent) { - dentry->d_parent = dget(parent); -@@ -982,8 +1086,10 @@ struct dentry *d_alloc_name(struct dentr - /* the caller must hold dcache_lock */ - static void __d_instantiate(struct dentry *dentry, struct inode *inode) - { -- if (inode) -+ if (inode) { -+ dentry->d_flags &= ~(DCACHE_WHITEOUT|DCACHE_FALLTHRU); - list_add(&dentry->d_alias, &inode->i_dentry); -+ } - dentry->d_inode = inode; - fsnotify_d_instantiate(dentry, inode); - } -@@ -1514,7 +1620,9 @@ void d_delete(struct dentry * dentry) - spin_lock(&dentry->d_lock); - isdir = S_ISDIR(dentry->d_inode->i_mode); - if (atomic_read(&dentry->d_count) == 1) { -+ __d_drop_unions(dentry); - dentry_iput(dentry); -+ shrink_d_unions(dentry); - fsnotify_nameremove(dentry, isdir); - return; - } -@@ -1525,14 +1633,14 @@ void d_delete(struct dentry * dentry) - spin_unlock(&dentry->d_lock); - spin_unlock(&dcache_lock); - -+ shrink_d_unions(dentry); - fsnotify_nameremove(dentry, isdir); - } - - static void __d_rehash(struct dentry * entry, struct hlist_head *list) - { -- -- entry->d_flags &= ~DCACHE_UNHASHED; -- hlist_add_head_rcu(&entry->d_hash, list); -+ entry->d_flags &= ~DCACHE_UNHASHED; -+ hlist_add_head_rcu(&entry->d_hash, list); - } - - static void _d_rehash(struct dentry * entry) -@@ -1551,6 +1659,7 @@ void d_rehash(struct dentry * entry) - { - spin_lock(&dcache_lock); - spin_lock(&entry->d_lock); -+ BUG_ON(!d_unhashed(entry)); - _d_rehash(entry); - spin_unlock(&entry->d_lock); - spin_unlock(&dcache_lock); -@@ -2183,7 +2292,9 @@ resume: - struct list_head *tmp = next; - struct dentry *dentry = list_entry(tmp, struct dentry, d_u.d_child); - next = tmp->next; -- if (d_unhashed(dentry)||!dentry->d_inode) -+ if (d_unhashed(dentry)||(!dentry->d_inode && -+ !d_is_whiteout(dentry) && -+ !d_is_fallthru(dentry))) - continue; - if (!list_empty(&dentry->d_subdirs)) { - this_parent = dentry; ---- a/fs/ext2/dir.c -+++ b/fs/ext2/dir.c -@@ -219,7 +219,8 @@ static inline int ext2_match (int len, c - { - if (len != de->name_len) - return 0; -- if (!de->inode) -+ if (!de->inode && ((de->file_type != EXT2_FT_WHT) && -+ (de->file_type != EXT2_FT_FALLTHRU))) - return 0; - return !memcmp(name, de->name, len); - } -@@ -255,6 +256,8 @@ static unsigned char ext2_filetype_table - [EXT2_FT_FIFO] = DT_FIFO, - [EXT2_FT_SOCK] = DT_SOCK, - [EXT2_FT_SYMLINK] = DT_LNK, -+ [EXT2_FT_WHT] = DT_WHT, -+ [EXT2_FT_FALLTHRU] = DT_UNKNOWN, - }; - - #define S_SHIFT 12 -@@ -341,6 +344,18 @@ ext2_readdir (struct file * filp, void * - ext2_put_page(page); - return 0; - } -+ } else if (de->file_type == EXT2_FT_FALLTHRU) { -+ int over; -+ unsigned char d_type = DT_UNKNOWN; -+ -+ offset = (char *)de - kaddr; -+ over = filldir(dirent, de->name, de->name_len, -+ (n<f_pos += ext2_rec_len_from_disk(de->rec_len); - } -@@ -448,6 +463,30 @@ ino_t ext2_inode_by_name(struct inode *d - return res; - } - -+/* Special version for filetype based whiteout support */ -+ino_t ext2_inode_by_dentry(struct inode *dir, struct dentry *dentry) -+{ -+ ino_t res = 0; -+ struct ext2_dir_entry_2 *de; -+ struct page *page; -+ -+ de = ext2_find_entry (dir, &dentry->d_name, &page); -+ if (de) { -+ res = le32_to_cpu(de->inode); -+ if (!res && de->file_type == EXT2_FT_WHT) { -+ spin_lock(&dentry->d_lock); -+ dentry->d_flags |= DCACHE_WHITEOUT; -+ spin_unlock(&dentry->d_lock); -+ } else if(!res && de->file_type == EXT2_FT_FALLTHRU) { -+ spin_lock(&dentry->d_lock); -+ dentry->d_flags |= DCACHE_FALLTHRU; -+ spin_unlock(&dentry->d_lock); -+ } -+ ext2_put_page(page); -+ } -+ return res; -+} -+ - /* Releases the page */ - void ext2_set_link(struct inode *dir, struct ext2_dir_entry_2 *de, - struct page *page, struct inode *inode, int update_times) -@@ -472,9 +511,10 @@ void ext2_set_link(struct inode *dir, st - } - - /* -- * Parent is locked. -+ * Find or append a given dentry to the parent directory - */ --int ext2_add_link (struct dentry *dentry, struct inode *inode) -+static ext2_dirent * ext2_append_entry(struct dentry * dentry, -+ struct page ** page) - { - struct inode *dir = dentry->d_parent->d_inode; - const char *name = dentry->d_name.name; -@@ -482,13 +522,10 @@ int ext2_add_link (struct dentry *dentry - unsigned chunk_size = ext2_chunk_size(dir); - unsigned reclen = EXT2_DIR_REC_LEN(namelen); - unsigned short rec_len, name_len; -- struct page *page = NULL; -- ext2_dirent * de; -+ ext2_dirent * de = NULL; - unsigned long npages = dir_pages(dir); - unsigned long n; - char *kaddr; -- loff_t pos; -- int err; - - /* - * We take care of directory expansion in the same loop. -@@ -498,55 +535,97 @@ int ext2_add_link (struct dentry *dentry - for (n = 0; n <= npages; n++) { - char *dir_end; - -- page = ext2_get_page(dir, n, 0); -- err = PTR_ERR(page); -- if (IS_ERR(page)) -+ *page = ext2_get_page(dir, n, 0); -+ de = ERR_PTR(PTR_ERR(*page)); -+ if (IS_ERR(*page)) - goto out; -- lock_page(page); -- kaddr = page_address(page); -+ lock_page(*page); -+ kaddr = page_address(*page); - dir_end = kaddr + ext2_last_byte(dir, n); - de = (ext2_dirent *)kaddr; - kaddr += PAGE_CACHE_SIZE - reclen; - while ((char *)de <= kaddr) { - if ((char *)de == dir_end) { - /* We hit i_size */ -- name_len = 0; -- rec_len = chunk_size; -+ de->name_len = 0; - de->rec_len = ext2_rec_len_to_disk(chunk_size); - de->inode = 0; -+ de->file_type = 0; - goto got_it; - } - if (de->rec_len == 0) { - ext2_error(dir->i_sb, __func__, - "zero-length directory entry"); -- err = -EIO; -+ de = ERR_PTR(-EIO); - goto out_unlock; - } -- err = -EEXIST; - if (ext2_match (namelen, name, de)) -- goto out_unlock; -+ goto got_it; - name_len = EXT2_DIR_REC_LEN(de->name_len); - rec_len = ext2_rec_len_from_disk(de->rec_len); -- if (!de->inode && rec_len >= reclen) -+ if (!de->inode && (de->file_type != EXT2_FT_WHT) && -+ (de->file_type != EXT2_FT_FALLTHRU) && -+ (rec_len >= reclen)) - goto got_it; - if (rec_len >= name_len + reclen) - goto got_it; - de = (ext2_dirent *) ((char *) de + rec_len); - } -- unlock_page(page); -- ext2_put_page(page); -+ unlock_page(*page); -+ ext2_put_page(*page); - } -+ - BUG(); -- return -EINVAL; - - got_it: -+ return de; -+ /* OFFSET_CACHE */ -+out_unlock: -+ unlock_page(*page); -+ ext2_put_page(*page); -+out: -+ return de; -+} -+ -+/* -+ * Parent is locked. -+ */ -+int ext2_add_link (struct dentry *dentry, struct inode *inode) -+{ -+ struct inode *dir = dentry->d_parent->d_inode; -+ const char *name = dentry->d_name.name; -+ int namelen = dentry->d_name.len; -+ unsigned short rec_len, name_len; -+ ext2_dirent * de; -+ struct page *page; -+ loff_t pos; -+ int err; -+ -+ de = ext2_append_entry(dentry, &page); -+ if (IS_ERR(de)) -+ return PTR_ERR(de); -+ -+ err = -EEXIST; -+ if (ext2_match (namelen, name, de)) { -+ if ((de->file_type == EXT2_FT_WHT) || -+ (de->file_type == EXT2_FT_FALLTHRU)) -+ goto got_it; -+ goto out_unlock; -+ } -+ -+got_it: -+ name_len = EXT2_DIR_REC_LEN(de->name_len); -+ rec_len = ext2_rec_len_from_disk(de->rec_len); -+ - pos = page_offset(page) + - (char*)de - (char*)page_address(page); - err = __ext2_write_begin(NULL, page->mapping, pos, rec_len, 0, - &page, NULL); - if (err) - goto out_unlock; -- if (de->inode) { -+ if (de->inode || (((de->file_type == EXT2_FT_WHT) || -+ (de->file_type == EXT2_FT_FALLTHRU)) && -+ !ext2_match (namelen, name, de))) { - ext2_dirent *de1 = (ext2_dirent *) ((char *) de + name_len); - de1->rec_len = ext2_rec_len_to_disk(rec_len - name_len); - de->rec_len = ext2_rec_len_to_disk(name_len); -@@ -563,7 +642,60 @@ got_it: - /* OFFSET_CACHE */ - out_put: - ext2_put_page(page); --out: -+ return err; -+out_unlock: -+ unlock_page(page); -+ goto out_put; -+} -+ -+/* -+ * Create a fallthru entry. -+ */ -+int ext2_fallthru_entry (struct inode *dir, struct dentry *dentry) -+{ -+ const char *name = dentry->d_name.name; -+ int namelen = dentry->d_name.len; -+ unsigned short rec_len, name_len; -+ ext2_dirent * de; -+ struct page *page; -+ loff_t pos; -+ int err; -+ -+ de = ext2_append_entry(dentry, &page); -+ if (IS_ERR(de)) -+ return PTR_ERR(de); -+ -+ err = -EEXIST; -+ if (ext2_match (namelen, name, de)) -+ goto out_unlock; -+ -+ name_len = EXT2_DIR_REC_LEN(de->name_len); -+ rec_len = ext2_rec_len_from_disk(de->rec_len); -+ -+ pos = page_offset(page) + -+ (char*)de - (char*)page_address(page); -+ err = __ext2_write_begin(NULL, page->mapping, pos, rec_len, 0, -+ &page, NULL); -+ if (err) -+ goto out_unlock; -+ if (de->inode || (de->file_type == EXT2_FT_WHT) || -+ (de->file_type == EXT2_FT_FALLTHRU)) { -+ ext2_dirent *de1 = (ext2_dirent *) ((char *) de + name_len); -+ de1->rec_len = ext2_rec_len_to_disk(rec_len - name_len); -+ de->rec_len = ext2_rec_len_to_disk(name_len); -+ de = de1; -+ } -+ de->name_len = namelen; -+ memcpy(de->name, name, namelen); -+ de->inode = 0; -+ de->file_type = EXT2_FT_FALLTHRU; -+ err = ext2_commit_chunk(page, pos, rec_len); -+ dir->i_mtime = dir->i_ctime = CURRENT_TIME_SEC; -+ EXT2_I(dir)->i_flags &= ~EXT2_BTREE_FL; -+ mark_inode_dirty(dir); -+ /* OFFSET_CACHE */ -+out_put: -+ ext2_put_page(page); - return err; - out_unlock: - unlock_page(page); -@@ -616,6 +748,70 @@ out: - return err; - } - -+int ext2_whiteout_entry (struct inode * dir, struct dentry * dentry, -+ struct ext2_dir_entry_2 * de, struct page * page) -+{ -+ const char *name = dentry->d_name.name; -+ int namelen = dentry->d_name.len; -+ unsigned short rec_len, name_len; -+ loff_t pos; -+ int err; -+ -+ if (!de) { -+ de = ext2_append_entry(dentry, &page); -+ BUG_ON(!de); -+ } -+ -+ err = -EEXIST; -+ if (ext2_match (namelen, name, de) && -+ (de->file_type == EXT2_FT_WHT)) { -+ ext2_error(dir->i_sb, __func__, -+ "entry is already a whiteout in directory #%lu", -+ dir->i_ino); -+ goto out_unlock; -+ } -+ -+ name_len = EXT2_DIR_REC_LEN(de->name_len); -+ rec_len = ext2_rec_len_from_disk(de->rec_len); -+ -+ pos = page_offset(page) + -+ (char*)de - (char*)page_address(page); -+ err = __ext2_write_begin(NULL, page->mapping, pos, rec_len, 0, -+ &page, NULL); -+ if (err) -+ goto out_unlock; -+ /* -+ * We whiteout an existing entry. Do what ext2_delete_entry() would do, -+ * except that we don't need to merge with the previous entry since -+ * we are going to reuse it. -+ */ -+ if (ext2_match (namelen, name, de)) -+ de->inode = 0; -+ if (de->inode || (((de->file_type == EXT2_FT_WHT) || -+ (de->file_type == EXT2_FT_FALLTHRU)) && -+ !ext2_match (namelen, name, de))) { -+ ext2_dirent *de1 = (ext2_dirent *) ((char *) de + name_len); -+ de1->rec_len = ext2_rec_len_to_disk(rec_len - name_len); -+ de->rec_len = ext2_rec_len_to_disk(name_len); -+ de = de1; -+ } -+ de->name_len = namelen; -+ memcpy(de->name, name, namelen); -+ de->inode = 0; -+ de->file_type = EXT2_FT_WHT; -+ err = ext2_commit_chunk(page, pos, rec_len); -+ dir->i_mtime = dir->i_ctime = CURRENT_TIME_SEC; -+ EXT2_I(dir)->i_flags &= ~EXT2_BTREE_FL; -+ mark_inode_dirty(dir); -+ /* OFFSET_CACHE */ -+out_put: -+ ext2_put_page(page); -+ return err; -+out_unlock: -+ unlock_page(page); -+ goto out_put; -+} -+ - /* - * Set the first fragment of directory. - */ ---- a/fs/ext2/ext2.h -+++ b/fs/ext2/ext2.h -@@ -102,9 +102,13 @@ extern void ext2_rsv_window_add(struct s - /* dir.c */ - extern int ext2_add_link (struct dentry *, struct inode *); - extern ino_t ext2_inode_by_name(struct inode *, struct qstr *); -+extern ino_t ext2_inode_by_dentry(struct inode *, struct dentry *); - extern int ext2_make_empty(struct inode *, struct inode *); - extern struct ext2_dir_entry_2 * ext2_find_entry (struct inode *,struct qstr *, struct page **); - extern int ext2_delete_entry (struct ext2_dir_entry_2 *, struct page *); -+extern int ext2_whiteout_entry (struct inode *, struct dentry *, -+ struct ext2_dir_entry_2 *, struct page *); -+extern int ext2_fallthru_entry (struct inode *, struct dentry *); - extern int ext2_empty_dir (struct inode *); - extern struct ext2_dir_entry_2 * ext2_dotdot (struct inode *, struct page **); - extern void ext2_set_link(struct inode *, struct ext2_dir_entry_2 *, struct page *, struct inode *, int); ---- a/fs/ext2/inode.c -+++ b/fs/ext2/inode.c -@@ -1178,7 +1178,8 @@ void ext2_set_inode_flags(struct inode * - { - unsigned int flags = EXT2_I(inode)->i_flags; - -- inode->i_flags &= ~(S_SYNC|S_APPEND|S_IMMUTABLE|S_NOATIME|S_DIRSYNC); -+ inode->i_flags &= ~(S_SYNC|S_APPEND|S_IMMUTABLE|S_NOATIME|S_DIRSYNC| -+ S_OPAQUE); - if (flags & EXT2_SYNC_FL) - inode->i_flags |= S_SYNC; - if (flags & EXT2_APPEND_FL) -@@ -1189,6 +1190,8 @@ void ext2_set_inode_flags(struct inode * - inode->i_flags |= S_NOATIME; - if (flags & EXT2_DIRSYNC_FL) - inode->i_flags |= S_DIRSYNC; -+ if (flags & EXT2_OPAQUE_FL) -+ inode->i_flags |= S_OPAQUE; - } - - /* Propagate flags from i_flags to EXT2_I(inode)->i_flags */ -@@ -1196,8 +1199,8 @@ void ext2_get_inode_flags(struct ext2_in - { - unsigned int flags = ei->vfs_inode.i_flags; - -- ei->i_flags &= ~(EXT2_SYNC_FL|EXT2_APPEND_FL| -- EXT2_IMMUTABLE_FL|EXT2_NOATIME_FL|EXT2_DIRSYNC_FL); -+ ei->i_flags &= ~(EXT2_SYNC_FL|EXT2_APPEND_FL|EXT2_IMMUTABLE_FL| -+ EXT2_NOATIME_FL|EXT2_DIRSYNC_FL|EXT2_OPAQUE_FL); - if (flags & S_SYNC) - ei->i_flags |= EXT2_SYNC_FL; - if (flags & S_APPEND) -@@ -1208,6 +1211,8 @@ void ext2_get_inode_flags(struct ext2_in - ei->i_flags |= EXT2_NOATIME_FL; - if (flags & S_DIRSYNC) - ei->i_flags |= EXT2_DIRSYNC_FL; -+ if (flags & S_OPAQUE) -+ ei->i_flags |= EXT2_OPAQUE_FL; - } - - struct inode *ext2_iget (struct super_block *sb, unsigned long ino) ---- a/fs/ext2/namei.c -+++ b/fs/ext2/namei.c -@@ -54,15 +54,16 @@ static inline int ext2_add_nondir(struct - * Methods themselves. - */ - --static struct dentry *ext2_lookup(struct inode * dir, struct dentry *dentry, struct nameidata *nd) -+static struct dentry *ext2_lookup(struct inode * dir, struct dentry *dentry, -+ struct nameidata *nd) - { - struct inode * inode; - ino_t ino; -- -+ - if (dentry->d_name.len > EXT2_NAME_LEN) - return ERR_PTR(-ENAMETOOLONG); - -- ino = ext2_inode_by_name(dir, &dentry->d_name); -+ ino = ext2_inode_by_dentry(dir, dentry); - inode = NULL; - if (ino) { - inode = ext2_iget(dir->i_sb, ino); -@@ -230,6 +231,10 @@ static int ext2_mkdir(struct inode * dir - else - inode->i_mapping->a_ops = &ext2_aops; - -+ /* if we call mkdir on a whiteout create an opaque directory */ -+ if (dentry->d_flags & DCACHE_WHITEOUT) -+ inode->i_flags |= S_OPAQUE; -+ - inode_inc_link_count(inode); - - err = ext2_make_empty(inode, dir); -@@ -293,6 +298,78 @@ static int ext2_rmdir (struct inode * di - return err; - } - -+/* -+ * Create a whiteout for the dentry -+ */ -+static int ext2_whiteout(struct inode *dir, struct dentry *dentry, -+ struct dentry *new_dentry) -+{ -+ struct inode * inode = dentry->d_inode; -+ struct ext2_dir_entry_2 * de = NULL; -+ struct page * page; -+ int err = -ENOTEMPTY; -+ -+ if (!EXT2_HAS_INCOMPAT_FEATURE(dir->i_sb, -+ EXT2_FEATURE_INCOMPAT_FILETYPE)) { -+ ext2_error (dir->i_sb, "ext2_whiteout", -+ "can't set whiteout filetype"); -+ err = -EPERM; -+ goto out; -+ } -+ -+ if (inode) { -+ if (S_ISDIR(inode->i_mode) && !ext2_empty_dir(inode)) -+ goto out; -+ -+ err = -ENOENT; -+ de = ext2_find_entry (dir, &dentry->d_name, &page); -+ if (!de) -+ goto out; -+ lock_page(page); -+ } -+ -+ err = ext2_whiteout_entry (dir, dentry, de, page); -+ if (err) -+ goto out; -+ -+ spin_lock(&new_dentry->d_lock); -+ new_dentry->d_flags &= ~DCACHE_FALLTHRU; -+ new_dentry->d_flags |= DCACHE_WHITEOUT; -+ spin_unlock(&new_dentry->d_lock); -+ d_add(new_dentry, NULL); -+ -+ if (inode) { -+ inode->i_ctime = dir->i_ctime; -+ inode_dec_link_count(inode); -+ if (S_ISDIR(inode->i_mode)) { -+ inode->i_size = 0; -+ inode_dec_link_count(inode); -+ inode_dec_link_count(dir); -+ } -+ } -+ err = 0; -+out: -+ return err; -+} -+ -+/* -+ * Create a fallthru entry. -+ */ -+static int ext2_fallthru (struct inode *dir, struct dentry *dentry) -+{ -+ int err; -+ -+ err = ext2_fallthru_entry(dir, dentry); -+ if (err) -+ return err; -+ -+ d_instantiate(dentry, NULL); -+ spin_lock(&dentry->d_lock); -+ dentry->d_flags |= DCACHE_FALLTHRU; -+ spin_unlock(&dentry->d_lock); -+ return 0; -+} -+ - static int ext2_rename (struct inode * old_dir, struct dentry * old_dentry, - struct inode * new_dir, struct dentry * new_dentry ) - { -@@ -392,6 +469,8 @@ const struct inode_operations ext2_dir_i - .mkdir = ext2_mkdir, - .rmdir = ext2_rmdir, - .mknod = ext2_mknod, -+ .whiteout = ext2_whiteout, -+ .fallthru = ext2_fallthru, - .rename = ext2_rename, - #ifdef CONFIG_EXT2_FS_XATTR - .setxattr = generic_setxattr, ---- a/fs/ext2/super.c -+++ b/fs/ext2/super.c -@@ -1062,6 +1062,13 @@ static int ext2_fill_super(struct super_ - if (EXT2_HAS_COMPAT_FEATURE(sb, EXT3_FEATURE_COMPAT_HAS_JOURNAL)) - ext2_warning(sb, __func__, - "mounting ext3 filesystem as ext2"); -+ -+ /* -+ * Whiteouts (and fallthrus) require explicit whiteout support. -+ */ -+ if (EXT2_HAS_INCOMPAT_FEATURE(sb, EXT2_FEATURE_INCOMPAT_WHITEOUT)) -+ sb->s_flags |= MS_WHITEOUT; -+ - ext2_setup_super (sb, es, sb->s_flags & MS_RDONLY); - return 0; - ---- a/fs/Kconfig -+++ b/fs/Kconfig -@@ -59,6 +59,14 @@ source "fs/notify/Kconfig" - - source "fs/quota/Kconfig" - -+config UNION_MOUNT -+ bool "Union mount support (EXPERIMENTAL)" -+ depends on EXPERIMENTAL -+ ---help--- -+ If you say Y here, you will be able to mount file systems as -+ union mount stacks. This is a VFS based implementation and -+ should work with all file systems. If unsure, say N. -+ - source "fs/autofs/Kconfig" - source "fs/autofs4/Kconfig" - source "fs/fuse/Kconfig" ---- a/fs/libfs.c -+++ b/fs/libfs.c -@@ -133,6 +133,7 @@ int dcache_readdir(struct file * filp, v - struct dentry *cursor = filp->private_data; - struct list_head *p, *q = &cursor->d_u.d_child; - ino_t ino; -+ int d_type; - int i = filp->f_pos; - - switch (i) { -@@ -158,14 +159,25 @@ int dcache_readdir(struct file * filp, v - for (p=q->next; p != &dentry->d_subdirs; p=p->next) { - struct dentry *next; - next = list_entry(p, struct dentry, d_u.d_child); -- if (d_unhashed(next) || !next->d_inode) -+ if (d_unhashed(next) || (!next->d_inode && !d_is_fallthru(next))) - continue; - -+ if (d_is_fallthru(next)) { -+ /* XXX Make up things we can -+ * only get out of the inode. -+ * Should probably really do a -+ * lookup instead. */ -+ ino = 100; /* XXX Made up number of no significance */ -+ d_type = DT_UNKNOWN; -+ } else { -+ ino = next->d_inode->i_ino; -+ d_type = dt_type(next->d_inode); -+ } -+ - spin_unlock(&dcache_lock); - if (filldir(dirent, next->d_name.name, - next->d_name.len, filp->f_pos, -- next->d_inode->i_ino, -- dt_type(next->d_inode)) < 0) -+ ino, d_type) < 0) - return 0; - spin_lock(&dcache_lock); - /* next is still alive */ ---- a/fs/Makefile -+++ b/fs/Makefile -@@ -52,6 +52,7 @@ obj-$(CONFIG_NFS_COMMON) += nfs_common/ - obj-$(CONFIG_GENERIC_ACL) += generic_acl.o - - obj-y += quota/ -+obj-$(CONFIG_UNION_MOUNT) += union.o - - obj-$(CONFIG_PROC_FS) += proc/ - obj-y += partitions/ ---- a/fs/namei.c -+++ b/fs/namei.c -@@ -33,6 +33,7 @@ - #include - #include - #include -+#include - #include - - #define ACC_MODE(x) ("\000\004\002\006"[(x)&O_ACCMODE]) -@@ -242,16 +243,17 @@ int generic_permission(struct inode *ino - } - - /** -- * inode_permission - check for access rights to a given inode -+ * __inode_permission - check for access rights to a given inode - * @inode: inode to check permission on - * @mask: right to check for (%MAY_READ, %MAY_WRITE, %MAY_EXEC) -+ * @rofs: check for read-only fs - * - * Used to check for read/write/execute permissions on an inode. - * We use "fsuid" for this, letting us set arbitrary permissions - * for filesystem access without changing the "normal" uids which - * are used for other things. - */ --int inode_permission(struct inode *inode, int mask) -+int __inode_permission(struct inode *inode, int mask, int rofs) - { - int retval; - -@@ -261,7 +263,7 @@ int inode_permission(struct inode *inode - /* - * Nobody gets write access to a read-only fs. - */ -- if (IS_RDONLY(inode) && -+ if ((rofs & IS_RDONLY(inode)) && - (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode))) - return -EROFS; - -@@ -289,6 +291,18 @@ int inode_permission(struct inode *inode - } - - /** -+ * inode_permission - check for access rights to a given inode -+ * @inode: inode to check permission on -+ * @mask: right to check for (%MAY_READ, %MAY_WRITE, %MAY_EXEC) -+ * -+ * This version pays attention to the MS_RDONLY flag on the fs. -+ */ -+int inode_permission(struct inode *inode, int mask) -+{ -+ return __inode_permission(inode, mask, 1); -+} -+ -+/** - * file_permission - check for additional access rights to a given file - * @file: file to check access rights for - * @mask: right to check for (%MAY_READ, %MAY_WRITE, %MAY_EXEC) -@@ -417,15 +431,10 @@ do_revalidate(struct dentry *dentry, str - * Internal lookup() using the new generic dcache. - * SMP-safe - */ --static struct dentry * cached_lookup(struct dentry * parent, struct qstr * name, struct nameidata *nd) -+static struct dentry *cache_lookup(struct dentry *parent, struct qstr *name, -+ struct nameidata *nd) - { -- struct dentry * dentry = __d_lookup(parent, name); -- -- /* lockess __d_lookup may fail due to concurrent d_move() -- * in some unrelated directory, so try with d_lookup -- */ -- if (!dentry) -- dentry = d_lookup(parent, name); -+ struct dentry *dentry = d_lookup(parent, name); - - if (dentry && dentry->d_op && dentry->d_op->d_revalidate) - dentry = do_revalidate(dentry, nd); -@@ -434,6 +443,208 @@ static struct dentry * cached_lookup(str - } - - /* -+ * Theory of operation for opaque, whiteout, and fallthru: -+ * -+ * whiteout: Unconditionally stop lookup here - ENOENT -+ * -+ * opaque: Don't lookup in directories lower in the union stack -+ * -+ * fallthru: While looking up an entry, ignore the opaque flag for the -+ * current directory only. -+ * -+ * A union stack is a linked list of directory dentries which appear -+ * in the same place in the namespace. When constructing the union -+ * stack, we include directories below opaque directories so that we -+ * can properly handle fallthrus. All non-fallthru lookups have to -+ * check for the opaque flag on the parent directory and obey it. -+ * -+ * In general, the code pattern is to lookup the the topmost entry -+ * first (either the first visible non-negative dentry or a negative -+ * dentry in the topmost layer of the union), then build the union -+ * stack for the newly looked-up entry (if it is a directory). -+ */ -+ -+/** -+ * __cache_lookup_topmost - lookup the topmost (non-)negative dentry -+ * -+ * @nd - parent's nameidata -+ * @name - pathname part to lookup -+ * @path - found dentry for pathname part -+ * -+ * This is used for union mount lookups from dcache. The first non-negative -+ * dentry is searched on all layers of the union stack. Otherwise the topmost -+ * negative dentry is returned. -+ */ -+static int __cache_lookup_topmost(struct nameidata *nd, struct qstr *name, -+ struct path *path) -+{ -+ struct dentry *dentry; -+ -+ dentry = d_lookup(nd->path.dentry, name); -+ if (dentry && dentry->d_op && dentry->d_op->d_revalidate) -+ dentry = do_revalidate(dentry, nd); -+ -+ /* -+ * Remember the topmost negative dentry in case we don't find anything -+ */ -+ path->dentry = dentry; -+ path->mnt = dentry ? nd->path.mnt : NULL; -+ -+ if (!dentry || (dentry->d_inode || d_is_whiteout(dentry))) -+ return !dentry; -+ -+ /* Keep going through opaque directories if we found a fallthru */ -+ if (IS_OPAQUE(nd->path.dentry->d_inode) && !d_is_fallthru(dentry)) -+ return !dentry; -+ -+ /* look for the first non-negative or whiteout dentry */ -+ -+ while (follow_union_down(&nd->path)) { -+ dentry = d_hash_and_lookup(nd->path.dentry, name); -+ -+ /* -+ * If parts of the union stack are not in the dcache we need -+ * to do a real lookup -+ */ -+ if (!dentry) -+ goto out_dput; -+ -+ /* -+ * If parts of the union don't survive the revalidation we -+ * need to do a real lookup -+ */ -+ if (dentry->d_op && dentry->d_op->d_revalidate) { -+ dentry = do_revalidate(dentry, nd); -+ if (!dentry) -+ goto out_dput; -+ } -+ -+ if (dentry->d_inode || d_is_whiteout(dentry)) -+ goto out_dput; -+ -+ /* Stop the lookup on opaque parent and non-fallthru child */ -+ if (IS_OPAQUE(nd->path.dentry->d_inode) && !d_is_fallthru(dentry)) -+ goto out_dput; -+ -+ dput(dentry); -+ } -+ -+ return !dentry; -+ -+out_dput: -+ dput(path->dentry); -+ path->dentry = dentry; -+ path->mnt = dentry ? mntget(nd->path.mnt) : NULL; -+ return !dentry; -+} -+ -+/** -+ * __cache_lookup_build_union - build the union stack for this part, -+ * cached version -+ * -+ * This is called after you have the topmost dentry in @path. -+ */ -+static int __cache_lookup_build_union(struct nameidata *nd, struct qstr *name, -+ struct path *path) -+{ -+ struct path last = *path; -+ struct dentry *dentry; -+ -+ while (follow_union_down(&nd->path)) { -+ dentry = d_hash_and_lookup(nd->path.dentry, name); -+ if (!dentry) -+ return 1; -+ -+ if (dentry->d_op && dentry->d_op->d_revalidate) { -+ dentry = do_revalidate(dentry, nd); -+ if (!dentry) -+ return 1; -+ } -+ -+ if (d_is_whiteout(dentry)) { -+ dput(dentry); -+ break; -+ } -+ -+ if (!dentry->d_inode) { -+ dput(dentry); -+ continue; -+ } -+ -+ /* only directories can be part of a union stack */ -+ if (!S_ISDIR(dentry->d_inode->i_mode)) { -+ dput(dentry); -+ break; -+ } -+ -+ /* Add the newly discovered dir to the union stack */ -+ append_to_union(last.mnt, last.dentry, nd->path.mnt, dentry); -+ -+ if (last.dentry != path->dentry) -+ path_put(&last); -+ last.dentry = dentry; -+ last.mnt = mntget(nd->path.mnt); -+ } -+ -+ if (last.dentry != path->dentry) -+ path_put(&last); -+ -+ return 0; -+} -+ -+/** -+ * cache_lookup_union - lookup a single pathname part from dcache -+ * -+ * This is a union mount capable version of what d_lookup() & revalidate() -+ * would do. This function returns a valid (union) dentry on success. -+ * -+ * Remember: On failure it means that parts of the union aren't cached. You -+ * should call real_lookup() afterwards to find the proper (union) dentry. -+ */ -+static int cache_lookup_union(struct nameidata *nd, struct qstr *name, -+ struct path *path) -+{ -+ int res ; -+ -+ if (!IS_MNT_UNION(nd->path.mnt)) { -+ path->dentry = cache_lookup(nd->path.dentry, name, nd); -+ path->mnt = path->dentry ? nd->path.mnt : NULL; -+ res = path->dentry ? 0 : 1; -+ } else { -+ struct path safe = { -+ .dentry = nd->path.dentry, -+ .mnt = nd->path.mnt -+ }; -+ -+ path_get(&safe); -+ res = __cache_lookup_topmost(nd, name, path); -+ if (res) -+ goto out; -+ -+ /* only directories can be part of a union stack */ -+ if (!path->dentry->d_inode || -+ !S_ISDIR(path->dentry->d_inode->i_mode)) -+ goto out; -+ -+ /* Build the union stack for this part */ -+ res = __cache_lookup_build_union(nd, name, path); -+ if (res) { -+ dput(path->dentry); -+ if (path->mnt != safe.mnt) -+ mntput(path->mnt); -+ goto out; -+ } -+ -+out: -+ path_put(&nd->path); -+ nd->path.dentry = safe.dentry; -+ nd->path.mnt = safe.mnt; -+ } -+ -+ return res; -+} -+ -+/* - * Short-cut version of permission(), for calling by - * path_walk(), when dcache lock is held. Combines parts - * of permission() and generic_permission(), and tests ONLY for -@@ -473,10 +684,11 @@ ok: - * make sure that nobody added the entry to the dcache in the meantime.. - * SMP-safe - */ --static struct dentry * real_lookup(struct dentry * parent, struct qstr * name, struct nameidata *nd) -+static int real_lookup(struct nameidata *nd, struct qstr *name, -+ struct path *path) - { -- struct dentry * result; -- struct inode *dir = parent->d_inode; -+ struct inode *dir = nd->path.dentry->d_inode; -+ int res = 0; - - mutex_lock(&dir->i_mutex); - /* -@@ -493,27 +705,36 @@ static struct dentry * real_lookup(struc - * - * so doing d_lookup() (with seqlock), instead of lockfree __d_lookup - */ -- result = d_lookup(parent, name); -- if (!result) { -+ path->dentry = d_lookup(nd->path.dentry, name); -+ path->mnt = nd->path.mnt; -+ if (!path->dentry) { - struct dentry *dentry; - - /* Don't create child dentry for a dead directory. */ -- result = ERR_PTR(-ENOENT); -- if (IS_DEADDIR(dir)) -+ if (IS_DEADDIR(dir)) { -+ res = -ENOENT; - goto out_unlock; -+ } - -- dentry = d_alloc(parent, name); -- result = ERR_PTR(-ENOMEM); -+ dentry = d_alloc(nd->path.dentry, name); - if (dentry) { -- result = dir->i_op->lookup(dir, dentry, nd); -- if (result) -+ path->dentry = dir->i_op->lookup(dir, dentry, nd); -+ if (path->dentry) { - dput(dentry); -- else -- result = dentry; -+ if (IS_ERR(path->dentry)) { -+ res = PTR_ERR(path->dentry); -+ path->dentry = NULL; -+ path->mnt = NULL; -+ } -+ } else -+ path->dentry = dentry; -+ } else { -+ res = -ENOMEM; -+ path->mnt = NULL; - } - out_unlock: - mutex_unlock(&dir->i_mutex); -- return result; -+ return res; - } - - /* -@@ -521,12 +742,170 @@ out_unlock: - * we waited on the semaphore. Need to revalidate. - */ - mutex_unlock(&dir->i_mutex); -- if (result->d_op && result->d_op->d_revalidate) { -- result = do_revalidate(result, nd); -- if (!result) -- result = ERR_PTR(-ENOENT); -+ if (path->dentry->d_op && path->dentry->d_op->d_revalidate) { -+ path->dentry = do_revalidate(path->dentry, nd); -+ if (!path->dentry) { -+ res = -ENOENT; -+ path->mnt = NULL; -+ } -+ if (IS_ERR(path->dentry)) { -+ res = PTR_ERR(path->dentry); -+ path->dentry = NULL; -+ path->mnt = NULL; -+ } - } -- return result; -+ -+ return res; -+} -+ -+/** -+ * __real_lookup_topmost - lookup topmost dentry, non-cached version -+ * -+ * If we reach a dentry with restricted access, we just stop the lookup -+ * because we shouldn't see through that dentry. Same thing for dentry -+ * type mismatch and whiteouts. -+ * -+ * FIXME: -+ * - handle union stacks in use -+ * - handle union stacks mounted upon union stacks -+ * - avoid unnecessary allocations of union locks -+ */ -+static int __real_lookup_topmost(struct nameidata *nd, struct qstr *name, -+ struct path *path) -+{ -+ struct path next; -+ int err; -+ -+ err = real_lookup(nd, name, path); -+ if (err) -+ return err; -+ -+ if (path->dentry->d_inode || d_is_whiteout(path->dentry)) -+ return 0; -+ -+ if (IS_OPAQUE(nd->path.dentry->d_inode) && !d_is_fallthru(path->dentry)) -+ return 0; -+ -+ while (follow_union_down(&nd->path)) { -+ name->hash = full_name_hash(name->name, name->len); -+ if (nd->path.dentry->d_op && nd->path.dentry->d_op->d_hash) { -+ err = nd->path.dentry->d_op->d_hash(nd->path.dentry, -+ name); -+ if (err < 0) -+ goto out; -+ } -+ -+ err = real_lookup(nd, name, &next); -+ if (err) -+ goto out; -+ -+ if (next.dentry->d_inode || d_is_whiteout(next.dentry)) { -+ dput(path->dentry); -+ mntget(next.mnt); -+ *path = next; -+ goto out; -+ } -+ -+ if (IS_OPAQUE(nd->path.dentry->d_inode) && !d_is_fallthru(next.dentry)) -+ goto out; -+ -+ dput(next.dentry); -+ } -+out: -+ if (err) -+ dput(path->dentry); -+ return err; -+} -+ -+/** -+ * __real_lookup_build_union: build the union stack for this pathname -+ * part, non-cached version -+ * -+ * Called when not all parts of the union stack are in cache -+ */ -+ -+static int __real_lookup_build_union(struct nameidata *nd, struct qstr *name, -+ struct path *path) -+{ -+ struct path last = *path; -+ struct path next; -+ int err = 0; -+ -+ while (follow_union_down(&nd->path)) { -+ /* We need to recompute the hash for lower layer lookups */ -+ name->hash = full_name_hash(name->name, name->len); -+ if (nd->path.dentry->d_op && nd->path.dentry->d_op->d_hash) { -+ err = nd->path.dentry->d_op->d_hash(nd->path.dentry, -+ name); -+ if (err < 0) -+ goto out; -+ } -+ -+ err = real_lookup(nd, name, &next); -+ if (err) -+ goto out; -+ -+ if (d_is_whiteout(next.dentry)) { -+ dput(next.dentry); -+ break; -+ } -+ -+ if (!next.dentry->d_inode) { -+ dput(next.dentry); -+ continue; -+ } -+ -+ /* only directories can be part of a union stack */ -+ if (!S_ISDIR(next.dentry->d_inode->i_mode)) { -+ dput(next.dentry); -+ break; -+ } -+ -+ /* now we know we found something "real" */ -+ append_to_union(last.mnt, last.dentry, next.mnt, next.dentry); -+ -+ if (last.dentry != path->dentry) -+ path_put(&last); -+ last.dentry = next.dentry; -+ last.mnt = mntget(next.mnt); -+ } -+ -+ if (last.dentry != path->dentry) -+ path_put(&last); -+out: -+ return err; -+} -+ -+static int real_lookup_union(struct nameidata *nd, struct qstr *name, -+ struct path *path) -+{ -+ struct path safe = { .dentry = nd->path.dentry, .mnt = nd->path.mnt }; -+ int res ; -+ -+ path_get(&safe); -+ res = __real_lookup_topmost(nd, name, path); -+ if (res) -+ goto out; -+ -+ /* only directories can be part of a union stack */ -+ if (!path->dentry->d_inode || -+ !S_ISDIR(path->dentry->d_inode->i_mode)) -+ goto out; -+ -+ /* Build the union stack for this part */ -+ res = __real_lookup_build_union(nd, name, path); -+ if (res) { -+ dput(path->dentry); -+ if (path->mnt != safe.mnt) -+ mntput(path->mnt); -+ goto out; -+ } -+ -+out: -+ path_put(&nd->path); -+ nd->path.dentry = safe.dentry; -+ nd->path.mnt = safe.mnt; -+ return res; - } - - /* -@@ -629,11 +1008,8 @@ static __always_inline int __do_follow_l - touch_atime(path->mnt, dentry); - nd_set_link(nd, NULL); - -- if (path->mnt != nd->path.mnt) { -- path_to_nameidata(path, nd); -- dget(dentry); -- } -- mntget(path->mnt); -+ if (path->mnt == nd->path.mnt) -+ mntget(nd->path.mnt); - cookie = dentry->d_inode->i_op->follow_link(dentry, nd); - error = PTR_ERR(cookie); - if (!IS_ERR(cookie)) { -@@ -721,7 +1097,7 @@ static int __follow_mount(struct path *p - return res; - } - --static void follow_mount(struct path *path) -+void follow_mount(struct path *path) - { - while (d_mountpoint(path->dentry)) { - struct vfsmount *mounted = lookup_mnt(path); -@@ -786,6 +1162,7 @@ static __always_inline void follow_dotdo - nd->path.mnt = parent; - } - follow_mount(&nd->path); -+ follow_union_mount(&nd->path); - } - - /* -@@ -796,35 +1173,55 @@ static __always_inline void follow_dotdo - static int do_lookup(struct nameidata *nd, struct qstr *name, - struct path *path) - { -- struct vfsmount *mnt = nd->path.mnt; -- struct dentry *dentry = __d_lookup(nd->path.dentry, name); -+ int err; -+ -+ if (IS_MNT_UNION(nd->path.mnt)) -+ goto need_union_lookup; - -- if (!dentry) -+ path->dentry = __d_lookup(nd->path.dentry, name); -+ path->mnt = nd->path.mnt; -+ if (!path->dentry) - goto need_lookup; -- if (dentry->d_op && dentry->d_op->d_revalidate) -+ if (path->dentry->d_op && path->dentry->d_op->d_revalidate) - goto need_revalidate; -+ - done: -- path->mnt = mnt; -- path->dentry = dentry; -- __follow_mount(path); -+ if (nd->path.mnt != path->mnt) { -+ nd->um_flags |= LAST_LOWLEVEL; -+ follow_mount(path); -+ } else -+ __follow_mount(path); -+ follow_union_mount(path); - return 0; - - need_lookup: -- dentry = real_lookup(nd->path.dentry, name, nd); -- if (IS_ERR(dentry)) -+ err = real_lookup(nd, name, path); -+ if (err) -+ goto fail; -+ goto done; -+ -+need_union_lookup: -+ err = cache_lookup_union(nd, name, path); -+ if (!err && path->dentry) -+ goto done; -+ -+ err = real_lookup_union(nd, name, path); -+ if (err) - goto fail; - goto done; - - need_revalidate: -- dentry = do_revalidate(dentry, nd); -- if (!dentry) -+ path->dentry = do_revalidate(path->dentry, nd); -+ if (!path->dentry) - goto need_lookup; -- if (IS_ERR(dentry)) -+ if (IS_ERR(path->dentry)) { -+ err = PTR_ERR(path->dentry); - goto fail; -+ } - goto done; - - fail: -- return PTR_ERR(dentry); -+ return err; - } - - /* -@@ -851,6 +1248,8 @@ static int __link_path_walk(const char * - if (nd->depth) - lookup_flags = LOOKUP_FOLLOW | (nd->flags & LOOKUP_CONTINUE); - -+ follow_union_mount(&nd->path); -+ - /* At this point we know we have a real path component. */ - for(;;) { - unsigned long hash; -@@ -913,6 +1312,44 @@ static int __link_path_walk(const char * - if (err) - break; - -+ /* -+ * We want to create this element on the top level -+ * file system in two cases: -+ * -+ * - We are specifically told to - LOOKUP_TOPMOST. -+ * - This is a directory, and it does not yet exist on -+ * the top level. Various tricks only work if -+ * directories always exist on the top level. -+ * -+ * In either case, only create this element on the top -+ * level if the last element is located on the lower -+ * level. If the last element is located on the top -+ * level, then every single element in the path -+ * already exists on the top level. -+ * -+ * Note that we can assume that the parent is on the -+ * top level since we always create the directory on -+ * the top level. -+ */ -+ -+ if ((nd->um_flags & LAST_LOWLEVEL) && -+ ((next.dentry->d_inode && -+ S_ISDIR(next.dentry->d_inode->i_mode) && -+ (nd->path.mnt != next.mnt)) || -+ (nd->flags & LOOKUP_TOPMOST))) { -+ struct dentry *dentry; -+ -+ dentry = union_create_topmost(nd, &this, &next); -+ if (IS_ERR(dentry)) { -+ err = PTR_ERR(dentry); -+ goto out_dput; -+ } -+ path_put_conditional(&next, nd); -+ next.mnt = nd->path.mnt; -+ next.dentry = dentry; -+ nd->um_flags &= ~LAST_LOWLEVEL; -+ } -+ - err = -ENOENT; - inode = next.dentry->d_inode; - if (!inode) -@@ -962,6 +1399,25 @@ last_component: - err = do_lookup(nd, &this, &next); - if (err) - break; -+ -+ if ((nd->um_flags & LAST_LOWLEVEL) && -+ ((next.dentry->d_inode && -+ S_ISDIR(next.dentry->d_inode->i_mode) && -+ (nd->path.mnt != next.mnt)) || -+ (nd->flags & LOOKUP_TOPMOST))) { -+ struct dentry *dentry; -+ -+ dentry = union_create_topmost(nd, &this, &next); -+ if (IS_ERR(dentry)) { -+ err = PTR_ERR(dentry); -+ goto out_dput; -+ } -+ path_put_conditional(&next, nd); -+ next.mnt = nd->path.mnt; -+ next.dentry = dentry; -+ nd->um_flags &= ~LAST_LOWLEVEL; -+ } -+ - inode = next.dentry->d_inode; - if ((lookup_flags & LOOKUP_FOLLOW) - && inode && inode->i_op->follow_link) { -@@ -1029,6 +1485,7 @@ static int path_init(int dfd, const char - - nd->last_type = LAST_ROOT; /* if there are only slashes... */ - nd->flags = flags; -+ nd->um_flags = 0; - nd->depth = 0; - nd->root.mnt = NULL; - -@@ -1172,61 +1629,437 @@ static int path_lookup_open(int dfd, con - } - - static struct dentry *__lookup_hash(struct qstr *name, -- struct dentry *base, struct nameidata *nd) -+ struct dentry *base, struct nameidata *nd) -+{ -+ struct dentry *dentry; -+ struct inode *inode; -+ int err; -+ -+ inode = base->d_inode; -+ -+ /* -+ * See if the low-level filesystem might want -+ * to use its own hash.. -+ */ -+ if (base->d_op && base->d_op->d_hash) { -+ err = base->d_op->d_hash(base, name); -+ dentry = ERR_PTR(err); -+ if (err < 0) -+ goto out; -+ } -+ -+ dentry = cache_lookup(base, name, nd); -+ if (!dentry) { -+ struct dentry *new; -+ -+ /* Don't create child dentry for a dead directory. */ -+ dentry = ERR_PTR(-ENOENT); -+ if (IS_DEADDIR(inode)) -+ goto out; -+ -+ new = d_alloc(base, name); -+ dentry = ERR_PTR(-ENOMEM); -+ if (!new) -+ goto out; -+ dentry = inode->i_op->lookup(inode, new, nd); -+ if (!dentry) -+ dentry = new; -+ else -+ dput(new); -+ } -+out: -+ return dentry; -+} -+ -+/* -+ * Restricted form of lookup. Doesn't follow links, single-component only, -+ * needs parent already locked. Doesn't follow mounts. -+ * SMP-safe. -+ */ -+static int lookup_hash(struct nameidata *nd, struct qstr *name, -+ struct path *path) -+{ -+ int err; -+ -+ err = inode_permission(nd->path.dentry->d_inode, MAY_EXEC); -+ if (err) -+ return err; -+ path->mnt = nd->path.mnt; -+ path->dentry = __lookup_hash(name, nd->path.dentry, nd); -+ if (IS_ERR(path->dentry)) { -+ err = PTR_ERR(path->dentry); -+ path->dentry = NULL; -+ path->mnt = NULL; -+ } -+ return err; -+} -+ -+static int __hash_lookup_topmost(struct nameidata *nd, struct qstr *name, -+ struct path *path) -+{ -+ struct path next; -+ int err; -+ -+ err = lookup_hash(nd, name, path); -+ if (err) -+ return err; -+ -+ if (path->dentry->d_inode || d_is_whiteout(path->dentry)) -+ return 0; -+ -+ if (IS_OPAQUE(nd->path.dentry->d_inode) && !d_is_fallthru(path->dentry)) -+ return 0; -+ -+ while (follow_union_down(&nd->path)) { -+ name->hash = full_name_hash(name->name, name->len); -+ if (nd->path.dentry->d_op && nd->path.dentry->d_op->d_hash) { -+ err = nd->path.dentry->d_op->d_hash(nd->path.dentry, -+ name); -+ if (err < 0) -+ goto out; -+ } -+ -+ mutex_lock(&nd->path.dentry->d_inode->i_mutex); -+ err = lookup_hash(nd, name, &next); -+ mutex_unlock(&nd->path.dentry->d_inode->i_mutex); -+ if (err) -+ goto out; -+ -+ if (next.dentry->d_inode || d_is_whiteout(next.dentry)) { -+ dput(path->dentry); -+ mntget(next.mnt); -+ *path = next; -+ goto out; -+ } -+ -+ if (IS_OPAQUE(nd->path.dentry->d_inode) && !d_is_fallthru(next.dentry)) -+ goto out; -+ -+ dput(next.dentry); -+ } -+out: -+ if (err) -+ dput(path->dentry); -+ return err; -+} -+ -+static int __hash_lookup_build_union(struct nameidata *nd, struct qstr *name, -+ struct path *path) -+{ -+ struct path last = *path; -+ struct path next; -+ int err = 0; -+ -+ while (follow_union_down(&nd->path)) { -+ /* We need to recompute the hash for lower layer lookups */ -+ name->hash = full_name_hash(name->name, name->len); -+ if (nd->path.dentry->d_op && nd->path.dentry->d_op->d_hash) { -+ err = nd->path.dentry->d_op->d_hash(nd->path.dentry, -+ name); -+ if (err < 0) -+ goto out; -+ } -+ -+ mutex_lock(&nd->path.dentry->d_inode->i_mutex); -+ err = lookup_hash(nd, name, &next); -+ mutex_unlock(&nd->path.dentry->d_inode->i_mutex); -+ if (err) -+ goto out; -+ -+ if (d_is_whiteout(next.dentry)) { -+ dput(next.dentry); -+ break; -+ } -+ -+ if (!next.dentry->d_inode) { -+ dput(next.dentry); -+ continue; -+ } -+ -+ /* only directories can be part of a union stack */ -+ if (!S_ISDIR(next.dentry->d_inode->i_mode)) { -+ dput(next.dentry); -+ break; -+ } -+ -+ /* now we know we found something "real" */ -+ append_to_union(last.mnt, last.dentry, next.mnt, next.dentry); -+ -+ if (last.dentry != path->dentry) -+ path_put(&last); -+ last.dentry = next.dentry; -+ last.mnt = mntget(next.mnt); -+ } -+ -+ if (last.dentry != path->dentry) -+ path_put(&last); -+out: -+ return err; -+} -+ -+int hash_lookup_union(struct nameidata *nd, struct qstr *name, -+ struct path *path) -+{ -+ struct path safe = { .dentry = nd->path.dentry, .mnt = nd->path.mnt }; -+ int res ; -+ -+ path_get(&safe); -+ res = __hash_lookup_topmost(nd, name, path); -+ if (res) -+ goto out; -+ -+ /* only directories can be part of a union stack */ -+ if (!path->dentry->d_inode || -+ !S_ISDIR(path->dentry->d_inode->i_mode)) -+ goto out; -+ -+ /* Build the union stack for this part */ -+ res = __hash_lookup_build_union(nd, name, path); -+ if (res) { -+ dput(path->dentry); -+ if (path->mnt != safe.mnt) -+ mntput(path->mnt); -+ goto out; -+ } -+ -+out: -+ path_put(&nd->path); -+ nd->path.dentry = safe.dentry; -+ nd->path.mnt = safe.mnt; -+ return res; -+} -+ -+/** -+ * do_union_hash_lookup() - walk down the union stack and lookup_hash() -+ * @nd: nameidata of parent to lookup from -+ * @name: pathname component to lookup -+ * @path: path to store result of lookup in -+ * -+ * Walk down the union stack and search for single pathname component name. It -+ * is assumed that the caller already did a lookup_hash() in the topmost parent -+ * that gave negative lookup result. Therefore this does call lookup_hash() in -+ * every lower layer (!) of the union stack. If a directory is found the union -+ * stack for that is assembled as well. -+ * -+ * Note: -+ * The caller needs to take care of holding a valid reference to the topmost -+ * parent. -+ * On error we leave @path untouched as well as when we don't find anything. -+ */ -+static int do_union_hash_lookup(struct nameidata *nd, struct qstr *name, -+ struct path *path) -+{ -+ struct path next; -+ int err = 0; -+ -+ while (follow_union_down(&nd->path)) { -+ /* rehash because of d_op->d_hash() by the previous layer */ -+ name->hash = full_name_hash(name->name, name->len); -+ -+ mutex_lock(&nd->path.dentry->d_inode->i_mutex); -+ err = lookup_hash(nd, name, &next); -+ mutex_unlock(&nd->path.dentry->d_inode->i_mutex); -+ -+ if (err) -+ break; -+ -+ if (next.dentry->d_inode) { -+ mntget(next.mnt); -+ if (!S_ISDIR(next.dentry->d_inode->i_mode)) { -+ *path = next; -+ break; -+ } -+ err = __hash_lookup_build_union(nd, name, &next); -+ if (err) -+ path_put(&next); -+ else -+ *path = next; -+ break; -+ } -+ -+ path_put_conditional(&next, nd); -+ -+ if ((IS_OPAQUE(nd->path.dentry->d_inode) && -+ !d_is_fallthru(next.dentry)) || -+ d_is_whiteout(next.dentry)) -+ break; -+ } -+ -+ return err; -+} -+ -+/** -+ * _hash_lookup_union() - lookup single pathname component -+ * @nd: nameidata of parent to lookup from -+ * @name: pathname component to lookup -+ * @path: path to store result of lookup in -+ * -+ * Returns the topmost parent locked and the target dentry found in the union -+ * or the topmost negative target dentry otherwise. -+ * -+ * Note: -+ * Returns topmost parent locked even on error. -+ */ -+static int _hash_lookup_union(struct nameidata *nd, struct qstr *name, -+ struct path *path) -+{ -+ struct path parent = nd->path; -+ struct path topmost; -+ int err; -+ -+ mutex_lock(&nd->path.dentry->d_inode->i_mutex); -+ err = lookup_hash(nd, name, path); -+ if (err) -+ return err; -+ -+ /* return if we found something and it isn't a directory we are done */ -+ if (path->dentry->d_inode && !S_ISDIR(path->dentry->d_inode->i_mode)) -+ return 0; -+ -+ /* stop lookup if the parent directory is marked opaque */ -+ if ((IS_OPAQUE(nd->path.dentry->d_inode) && -+ !d_is_fallthru(path->dentry)) || -+ d_is_whiteout(path->dentry)) -+ return 0; -+ -+ if (!strcmp(path->mnt->mnt_sb->s_type->name, "proc") || -+ !strcmp(path->mnt->mnt_sb->s_type->name, "sysfs")) -+ return 0; -+ -+ mutex_unlock(&nd->path.dentry->d_inode->i_mutex); -+ -+ /* -+ * safe a reference to the topmost parent for walking the union stack -+ */ -+ path_get(&parent); -+ topmost = *path; -+ -+ if (path->dentry->d_inode && S_ISDIR(path->dentry->d_inode->i_mode)) { -+ err = __hash_lookup_build_union(nd, name, path); -+ if (err) -+ goto err_lock_parent; -+ goto out_lock_and_revalidate_parent; -+ } -+ -+ err = do_union_hash_lookup(nd, name, path); -+ if (err) -+ goto err_lock_parent; -+ -+out_lock_and_revalidate_parent: -+ /* seems that we haven't found anything, so return the topmost */ -+ path_to_nameidata(&parent, nd); -+ mutex_lock(&nd->path.dentry->d_inode->i_mutex); -+ -+ if (topmost.dentry == path->dentry) { -+ spin_lock(&path->dentry->d_lock); -+ if (nd->path.dentry != path->dentry->d_parent) { -+ spin_unlock(&path->dentry->d_lock); -+ dput(path->dentry); -+ name->hash = full_name_hash(name->name, name->len); -+ err = lookup_hash(nd, name, path); -+ if (err) -+ return err; -+ /* FIXME: What if we find a directory here ... */ -+ return err; -+ } -+ spin_unlock(&path->dentry->d_lock); -+ } else -+ dput(topmost.dentry); -+ -+ return 0; -+ -+err_lock_parent: -+ path_to_nameidata(&parent, nd); -+ path_put_conditional(path, nd); -+ mutex_lock(&nd->path.dentry->d_inode->i_mutex); -+ return err; -+} -+ -+/** -+ * lookup_rename_source() - lookup the source used by rename -+ * -+ * This is a special version of _hash_lookup_union() which becomes necessary -+ * for finding the source of a rename on union mounts. -+ * -+ * See comment for _hash_lookup_union() above. -+ */ -+static int lookup_rename_source(struct nameidata *oldnd, -+ struct nameidata *newnd, -+ struct dentry **trap, struct qstr *name, -+ struct path *old) - { -- struct dentry *dentry; -- struct inode *inode; -+ struct path parent = oldnd->path; -+ struct path topmost; - int err; - -- inode = base->d_inode; -+ err = lookup_hash(oldnd, name, old); -+ if (err) -+ return err; -+ -+ /* return if we found something and it isn't a directory we are done */ -+ if (old->dentry->d_inode && !S_ISDIR(old->dentry->d_inode->i_mode)) -+ return 0; -+ -+ /* stop lookup if the parent directory is marked opaque */ -+ if ((IS_OPAQUE(oldnd->path.dentry->d_inode) && -+ !d_is_fallthru(old->dentry)) || -+ d_is_whiteout(old->dentry)) -+ return 0; -+ -+ if (!strcmp(old->mnt->mnt_sb->s_type->name, "proc") || -+ !strcmp(old->mnt->mnt_sb->s_type->name, "sysfs")) -+ return 0; -+ -+ unlock_rename(oldnd->path.dentry, newnd->path.dentry); - - /* -- * See if the low-level filesystem might want -- * to use its own hash.. -+ * safe a reference to the topmost parent for walking the union stack - */ -- if (base->d_op && base->d_op->d_hash) { -- err = base->d_op->d_hash(base, name); -- dentry = ERR_PTR(err); -- if (err < 0) -- goto out; -+ path_get(&parent); -+ topmost = *old; -+ -+ if (old->dentry->d_inode && S_ISDIR(old->dentry->d_inode->i_mode)) { -+ err = __hash_lookup_build_union(oldnd, name, old); -+ if (err) -+ goto err_lock; -+ goto out_lock_and_revalidate_parent; - } - -- dentry = cached_lookup(base, name, nd); -- if (!dentry) { -- struct dentry *new; -+ err = do_union_hash_lookup(oldnd, name, old); -+ if (err) -+ goto err_lock; - -- /* Don't create child dentry for a dead directory. */ -- dentry = ERR_PTR(-ENOENT); -- if (IS_DEADDIR(inode)) -- goto out; -+out_lock_and_revalidate_parent: -+ path_to_nameidata(&parent, oldnd); -+ *trap = lock_rename(oldnd->path.dentry, newnd->path.dentry); - -- new = d_alloc(base, name); -- dentry = ERR_PTR(-ENOMEM); -- if (!new) -- goto out; -- dentry = inode->i_op->lookup(inode, new, nd); -- if (!dentry) -- dentry = new; -- else -- dput(new); -- } --out: -- return dentry; --} -+ /* -+ * If we return the topmost dentry we have to make sure that it has not -+ * been moved away while we gave up the topmost parents i_mutex lock. -+ */ -+ if (topmost.dentry == old->dentry) { -+ spin_lock(&old->dentry->d_lock); -+ if (oldnd->path.dentry != old->dentry->d_parent) { -+ spin_unlock(&old->dentry->d_lock); -+ dput(old->dentry); -+ name->hash = full_name_hash(name->name, name->len); -+ err = lookup_hash(oldnd, name, old); -+ if (err) -+ return err; -+ /* FIXME: What if we find a directory here ... */ -+ return err; -+ } -+ spin_unlock(&old->dentry->d_lock); -+ } else -+ dput(topmost.dentry); - --/* -- * Restricted form of lookup. Doesn't follow links, single-component only, -- * needs parent already locked. Doesn't follow mounts. -- * SMP-safe. -- */ --static struct dentry *lookup_hash(struct nameidata *nd) --{ -- int err; -+ return 0; - -- err = inode_permission(nd->path.dentry->d_inode, MAY_EXEC); -- if (err) -- return ERR_PTR(err); -- return __lookup_hash(&nd->last, nd->path.dentry, nd); -+err_lock: -+ path_to_nameidata(&parent, oldnd); -+ path_put_conditional(old, oldnd); -+ *trap = lock_rename(oldnd->path.dentry, newnd->path.dentry); -+ return err; - } - - static int __lookup_one_len(const char *name, struct qstr *this, -@@ -1502,8 +2335,9 @@ int vfs_create(struct inode *dir, struct - return error; - } - --int may_open(struct path *path, int acc_mode, int flag) -+int may_open(struct nameidata *nd, int acc_mode, int flag) - { -+ struct path *path = &nd->path; - struct dentry *dentry = path->dentry; - struct inode *inode = dentry->d_inode; - int error; -@@ -1529,7 +2363,7 @@ int may_open(struct path *path, int acc_ - break; - } - -- error = inode_permission(inode, acc_mode); -+ error = union_permission(path, acc_mode); - if (error) - return error; - -@@ -1577,6 +2411,9 @@ int may_open(struct path *path, int acc_ - if (!error) - error = security_path_truncate(path, 0, - ATTR_MTIME|ATTR_CTIME|ATTR_OPEN); -+ /* XXX don't copy up file data */ -+ if (is_unionized(path->dentry, path->mnt)) -+ error = union_copyup(nd, flag /* XXX not used */); - if (!error) { - vfs_dq_init(inode); - -@@ -1623,7 +2460,7 @@ out_unlock: - if (error) - return error; - /* Don't check for write permission, don't truncate */ -- return may_open(&nd->path, 0, flag & ~O_TRUNC); -+ return may_open(nd, 0, flag & ~O_TRUNC); - } - - /* -@@ -1738,12 +2575,10 @@ struct file *do_filp_open(int dfd, const - if (flag & O_EXCL) - nd.flags |= LOOKUP_EXCL; - mutex_lock(&dir->d_inode->i_mutex); -- path.dentry = lookup_hash(&nd); -- path.mnt = nd.path.mnt; -+ error = hash_lookup_union(&nd, &nd.last, &path); - - do_last: -- error = PTR_ERR(path.dentry); -- if (IS_ERR(path.dentry)) { -+ if (error) { - mutex_unlock(&dir->d_inode->i_mutex); - goto exit; - } -@@ -1803,10 +2638,23 @@ do_last: - if (path.dentry->d_inode->i_op->follow_link) - goto do_link; - -- path_to_nameidata(&path, &nd); - error = -EISDIR; - if (path.dentry->d_inode && S_ISDIR(path.dentry->d_inode->i_mode)) -- goto exit; -+ goto exit_dput; -+ -+ /* -+ * If this file is on a lower layer of the union stack, copy it to the -+ * topmost layer before opening it -+ */ -+ if (path.dentry->d_inode && -+ (path.dentry->d_parent != dir) && -+ S_ISREG(path.dentry->d_inode->i_mode)) { -+ error = __union_copyup(&path, &nd, &path); -+ if (error) -+ goto exit_dput; -+ } -+ -+ path_to_nameidata(&path, &nd); - ok: - /* - * Consider: -@@ -1824,12 +2672,18 @@ ok: - if (error) - goto exit; - } -- error = may_open(&nd.path, acc_mode, flag); -+ error = may_open(&nd, acc_mode, flag); - if (error) { - if (will_write) - mnt_drop_write(nd.path.mnt); - goto exit; - } -+ /* Okay, all permissions go, now copy up */ -+ if (!(flag & O_CREAT) && (flag & FMODE_WRITE)) { -+ error = union_copyup(&nd, flag /* XXX not used */); -+ if (error) -+ goto exit; -+ } - filp = nameidata_to_filp(&nd, open_flag); - if (IS_ERR(filp)) - ima_counts_put(&nd.path, -@@ -1904,8 +2758,7 @@ do_link: - } - dir = nd.path.dentry; - mutex_lock(&dir->d_inode->i_mutex); -- path.dentry = lookup_hash(&nd); -- path.mnt = nd.path.mnt; -+ error = hash_lookup_union(&nd, &nd.last, &path); - __putname(nd.last.name); - goto do_last; - } -@@ -1939,7 +2792,8 @@ EXPORT_SYMBOL(filp_open); - */ - struct dentry *lookup_create(struct nameidata *nd, int is_dir) - { -- struct dentry *dentry = ERR_PTR(-EEXIST); -+ struct path path = { .dentry = ERR_PTR(-EEXIST) } ; -+ int err; - - mutex_lock_nested(&nd->path.dentry->d_inode->i_mutex, I_MUTEX_PARENT); - /* -@@ -1955,11 +2809,13 @@ struct dentry *lookup_create(struct name - /* - * Do the final lookup. - */ -- dentry = lookup_hash(nd); -- if (IS_ERR(dentry)) -+ err = hash_lookup_union(nd, &nd->last, &path); -+ if (err) { -+ path.dentry = ERR_PTR(err); - goto fail; -+ } - -- if (dentry->d_inode) -+ if (path.dentry->d_inode) - goto eexist; - /* - * Special case - lookup gave negative, but... we had foo/bar/ -@@ -1968,15 +2824,17 @@ struct dentry *lookup_create(struct name - * been asking for (non-existent) directory. -ENOENT for you. - */ - if (unlikely(!is_dir && nd->last.name[nd->last.len])) { -- dput(dentry); -- dentry = ERR_PTR(-ENOENT); -+ path_put_conditional(&path, nd); -+ path.dentry = ERR_PTR(-ENOENT); - } -- return dentry; -+ if (nd->path.mnt != path.mnt) -+ mntput(path.mnt); -+ return path.dentry; - eexist: -- dput(dentry); -- dentry = ERR_PTR(-EEXIST); -+ path_put_conditional(&path, nd); -+ path.dentry = ERR_PTR(-EEXIST); - fail: -- return dentry; -+ return path.dentry; - } - EXPORT_SYMBOL_GPL(lookup_create); - -@@ -2088,6 +2946,7 @@ SYSCALL_DEFINE3(mknod, const char __user - int vfs_mkdir(struct inode *dir, struct dentry *dentry, int mode) - { - int error = may_create(dir, dentry); -+ int opaque = 0; - - if (error) - return error; -@@ -2101,9 +2960,18 @@ int vfs_mkdir(struct inode *dir, struct - return error; - - vfs_dq_init(dir); -+ -+ if (d_is_whiteout(dentry)) -+ opaque = 1; -+ - error = dir->i_op->mkdir(dir, dentry, mode); -- if (!error) -+ if (!error) { - fsnotify_mkdir(dir, dentry); -+ if (opaque) { -+ dentry->d_inode->i_flags |= S_OPAQUE; -+ mark_inode_dirty(dentry->d_inode); -+ } -+ } - return error; - } - -@@ -2149,6 +3017,212 @@ SYSCALL_DEFINE2(mkdir, const char __user - return sys_mkdirat(AT_FDCWD, pathname, mode); - } - -+ -+/* Checks on the victim for whiteout */ -+static inline int may_whiteout(struct inode *dir, struct dentry *victim, -+ int isdir) -+{ -+ int err; -+ -+ /* from may_create() */ -+ if (IS_DEADDIR(dir)) -+ return -ENOENT; -+ err = inode_permission(dir, MAY_WRITE | MAY_EXEC); -+ if (err) -+ return err; -+ -+ /* from may_delete() */ -+ if (IS_APPEND(dir)) -+ return -EPERM; -+ if (!victim->d_inode) -+ return 0; -+ if (check_sticky(dir, victim->d_inode) || -+ IS_APPEND(victim->d_inode) || -+ IS_IMMUTABLE(victim->d_inode)) -+ return -EPERM; -+ if (isdir) { -+ if (!S_ISDIR(victim->d_inode->i_mode)) -+ return -ENOTDIR; -+ if (IS_ROOT(victim)) -+ return -EBUSY; -+ } else if (S_ISDIR(victim->d_inode->i_mode)) -+ return -EISDIR; -+ if (victim->d_flags & DCACHE_NFSFS_RENAMED) -+ return -EBUSY; -+ return 0; -+} -+ -+/** -+ * vfs_whiteout: creates a white-out for the given directory entry -+ * @dir: parent inode -+ * @dentry: directory entry to white-out -+ * -+ * Simply white-out a given directory entry. This functionality is usually used -+ * in the sense of unlink. Therefore the given dentry can still be in-use and -+ * contains an in-use inode. The filesystem has to do what unlink or rmdir -+ * would in that case. Since the dentry still might be in-use we have to -+ * provide a fresh unhashed dentry that whiteout can fill the new inode into. -+ * In that case the given dentry is dropped and the fresh dentry containing the -+ * whiteout is rehashed instead. If the given dentry is unused, the whiteout -+ * inode is instantiated into it instead. -+ * -+ * After this returns with success, don't make any assumptions about the inode. -+ * Just dput() it dentry. -+ */ -+static int vfs_whiteout(struct inode *dir, struct dentry *dentry, int isdir) -+{ -+ int err; -+ struct inode *old_inode = dentry->d_inode; -+ struct dentry *parent, *whiteout; -+ -+ err = may_whiteout(dir, dentry, isdir); -+ if (err) -+ return err; -+ -+ BUG_ON(dentry->d_parent->d_inode != dir); -+ -+ if (!dir->i_op || !dir->i_op->whiteout) -+ return -EOPNOTSUPP; -+ -+ if (old_inode) { -+ vfs_dq_init(dir); -+ -+ mutex_lock(&old_inode->i_mutex); -+ if (isdir) -+ dentry_unhash(dentry); -+ if (d_mountpoint(dentry)) -+ err = -EBUSY; -+ else { -+ if (isdir) -+ err = security_inode_rmdir(dir, dentry); -+ else -+ err = security_inode_unlink(dir, dentry); -+ } -+ } -+ -+ parent = dget_parent(dentry); -+ whiteout = d_alloc_name(parent, dentry->d_name.name); -+ -+ if (!err) -+ err = dir->i_op->whiteout(dir, dentry, whiteout); -+ -+ if (old_inode) { -+ mutex_unlock(&old_inode->i_mutex); -+ if (!err) { -+ fsnotify_link_count(old_inode); -+ d_delete(dentry); -+ } -+ if (isdir) -+ dput(dentry); -+ } -+ -+ dput(whiteout); -+ dput(parent); -+ return err; -+} -+ -+int path_whiteout(struct path *dir_path, struct dentry *dentry, int isdir) -+{ -+ int error = mnt_want_write(dir_path->mnt); -+ -+ if (!error) { -+ error = vfs_whiteout(dir_path->dentry->d_inode, dentry, isdir); -+ mnt_drop_write(dir_path->mnt); -+ } -+ -+ return error; -+} -+EXPORT_SYMBOL(path_whiteout); -+ -+/* -+ * This is abusing readdir to check if a union directory is logically empty. -+ * Al Viro barfed when he saw this, but Val said: "Well, at this point I'm -+ * aiming for working, pretty can come later" -+ */ -+static int filldir_is_empty(void *__buf, const char *name, int namlen, -+ loff_t offset, u64 ino, unsigned int d_type) -+{ -+ int *is_empty = (int *)__buf; -+ -+ switch (namlen) { -+ case 2: -+ if (name[1] != '.') -+ break; -+ case 1: -+ if (name[0] != '.') -+ break; -+ return 0; -+ } -+ -+ if (d_type == DT_WHT) -+ return 0; -+ -+ (*is_empty) = 0; -+ return 0; -+} -+ -+static int directory_is_empty(struct dentry *dentry, struct vfsmount *mnt) -+{ -+ struct file *file; -+ int err; -+ int is_empty = 1; -+ -+ BUG_ON(!S_ISDIR(dentry->d_inode->i_mode)); -+ -+ /* references for the file pointer */ -+ dget(dentry); -+ mntget(mnt); -+ -+ file = dentry_open(dentry, mnt, O_RDONLY, current_cred()); -+ if (IS_ERR(file)) -+ return 0; -+ -+ err = vfs_readdir(file, filldir_is_empty, &is_empty); -+ -+ fput(file); -+ return is_empty; -+} -+ -+static int do_whiteout(struct nameidata *nd, struct path *path, int isdir) -+{ -+ struct path safe = { .dentry = dget(nd->path.dentry), -+ .mnt = mntget(nd->path.mnt) }; -+ struct dentry *dentry = path->dentry; -+ int err; -+ -+ err = may_whiteout(nd->path.dentry->d_inode, dentry, isdir); -+ if (err) -+ goto out; -+ -+ err = -ENOENT; -+ if (!dentry->d_inode) -+ goto out; -+ -+ err = -ENOTEMPTY; -+ if (isdir && !directory_is_empty(path->dentry, path->mnt)) -+ goto out; -+ -+ if (nd->path.dentry != dentry->d_parent) { -+ dentry = __lookup_hash(&path->dentry->d_name, nd->path.dentry, -+ nd); -+ err = PTR_ERR(dentry); -+ if (IS_ERR(dentry)) -+ goto out; -+ -+ dput(path->dentry); -+ if (path->mnt != safe.mnt) -+ mntput(path->mnt); -+ path->mnt = nd->path.mnt; -+ path->dentry = dentry; -+ } -+ -+ err = vfs_whiteout(nd->path.dentry->d_inode, dentry, isdir); -+ -+out: -+ path_put(&safe); -+ return err; -+} -+ - /* - * We try to drop the dentry early: we should have - * a usage count of 2 if we're the only user of this -@@ -2213,7 +3287,7 @@ static long do_rmdir(int dfd, const char - { - int error = 0; - char * name; -- struct dentry *dentry; -+ struct path path; - struct nameidata nd; - - error = user_path_parent(dfd, pathname, &nd, &name); -@@ -2235,21 +3309,24 @@ static long do_rmdir(int dfd, const char - nd.flags &= ~LOOKUP_PARENT; - - mutex_lock_nested(&nd.path.dentry->d_inode->i_mutex, I_MUTEX_PARENT); -- dentry = lookup_hash(&nd); -- error = PTR_ERR(dentry); -- if (IS_ERR(dentry)) -+ error = hash_lookup_union(&nd, &nd.last, &path); -+ if (error) - goto exit2; -+ if (is_unionized(nd.path.dentry, nd.path.mnt)) { -+ error = do_whiteout(&nd, &path, 1); -+ goto exit3; -+ } - error = mnt_want_write(nd.path.mnt); - if (error) - goto exit3; -- error = security_path_rmdir(&nd.path, dentry); -+ error = security_path_rmdir(&nd.path, path.dentry); - if (error) - goto exit4; -- error = vfs_rmdir(nd.path.dentry->d_inode, dentry); -+ error = vfs_rmdir(nd.path.dentry->d_inode, path.dentry); - exit4: - mnt_drop_write(nd.path.mnt); - exit3: -- dput(dentry); -+ path_put_conditional(&path, &nd); - exit2: - mutex_unlock(&nd.path.dentry->d_inode->i_mutex); - exit1: -@@ -2304,7 +3381,7 @@ static long do_unlinkat(int dfd, const c - { - int error; - char *name; -- struct dentry *dentry; -+ struct path path; - struct nameidata nd; - struct inode *inode = NULL; - -@@ -2319,26 +3396,29 @@ static long do_unlinkat(int dfd, const c - nd.flags &= ~LOOKUP_PARENT; - - mutex_lock_nested(&nd.path.dentry->d_inode->i_mutex, I_MUTEX_PARENT); -- dentry = lookup_hash(&nd); -- error = PTR_ERR(dentry); -- if (!IS_ERR(dentry)) { -+ error = hash_lookup_union(&nd, &nd.last, &path); -+ if (!error) { - /* Why not before? Because we want correct error value */ - if (nd.last.name[nd.last.len]) - goto slashes; -- inode = dentry->d_inode; -+ inode = path.dentry->d_inode; - if (inode) - atomic_inc(&inode->i_count); -+ if (is_unionized(nd.path.dentry, nd.path.mnt)) { -+ error = do_whiteout(&nd, &path, 0); -+ goto exit2; -+ } - error = mnt_want_write(nd.path.mnt); - if (error) - goto exit2; -- error = security_path_unlink(&nd.path, dentry); -+ error = security_path_unlink(&nd.path, path.dentry); - if (error) - goto exit3; -- error = vfs_unlink(nd.path.dentry->d_inode, dentry); -+ error = vfs_unlink(nd.path.dentry->d_inode, path.dentry); - exit3: - mnt_drop_write(nd.path.mnt); - exit2: -- dput(dentry); -+ path_put_conditional(&path, &nd); - } - mutex_unlock(&nd.path.dentry->d_inode->i_mutex); - if (inode) -@@ -2349,8 +3429,8 @@ exit1: - return error; - - slashes: -- error = !dentry->d_inode ? -ENOENT : -- S_ISDIR(dentry->d_inode->i_mode) ? -EISDIR : -ENOTDIR; -+ error = !path.dentry->d_inode ? -ENOENT : -+ S_ISDIR(path.dentry->d_inode->i_mode) ? -EISDIR : -ENOTDIR; - goto exit2; - } - -@@ -2686,11 +3766,96 @@ int vfs_rename(struct inode *old_dir, st - return error; - } - -+static int vfs_rename_union(struct nameidata *oldnd, struct path *old, -+ struct nameidata *newnd, struct path *new) -+{ -+ struct inode *old_dir = oldnd->path.dentry->d_inode; -+ struct inode *new_dir = newnd->path.dentry->d_inode; -+ struct qstr old_name; -+ char *name; -+ struct dentry *dentry; -+ int error; -+ -+ if (old->dentry->d_inode == new->dentry->d_inode) -+ return 0; -+ error = may_whiteout(old_dir, old->dentry, 0); -+ if (error) -+ return error; -+ if (!old_dir->i_op || !old_dir->i_op->whiteout) -+ return -EPERM; -+ -+ if (!new->dentry->d_inode) -+ error = may_create(new_dir, new->dentry); -+ else -+ error = may_delete(new_dir, new->dentry, 0); -+ if (error) -+ return error; -+ -+ vfs_dq_init(old_dir); -+ vfs_dq_init(new_dir); -+ -+ error = -EBUSY; -+ if (d_mountpoint(old->dentry) || d_mountpoint(new->dentry)) -+ return error; -+ -+ error = -ENOMEM; -+ name = kmalloc(old->dentry->d_name.len, GFP_KERNEL); -+ if (!name) -+ return error; -+ strncpy(name, old->dentry->d_name.name, old->dentry->d_name.len); -+ name[old->dentry->d_name.len] = 0; -+ old_name.len = old->dentry->d_name.len; -+ old_name.hash = old->dentry->d_name.hash; -+ old_name.name = name; -+ -+ /* possibly delete the existing new file */ -+ if ((newnd->path.dentry == new->dentry->d_parent) && -+ new->dentry->d_inode) { -+ /* FIXME: inode may be truncated while we hold a lock */ -+ error = vfs_unlink(new_dir, new->dentry); -+ if (error) -+ goto freename; -+ -+ dentry = __lookup_hash(&new->dentry->d_name, -+ newnd->path.dentry, newnd); -+ if (IS_ERR(dentry)) -+ goto freename; -+ -+ dput(new->dentry); -+ new->dentry = dentry; -+ } -+ -+ /* copyup to the new file */ -+ error = __union_copyup(old, newnd, new); -+ if (error) -+ goto freename; -+ -+ /* whiteout the old file */ -+ dentry = __lookup_hash(&old_name, oldnd->path.dentry, oldnd); -+ error = PTR_ERR(dentry); -+ if (IS_ERR(dentry)) -+ goto freename; -+ error = vfs_whiteout(old_dir, dentry, 0); -+ dput(dentry); -+ -+ /* FIXME: This is acutally unlink() && create() ... */ -+/* -+ if (!error) { -+ const char *new_name = old_dentry->d_name.name; -+ fsnotify_move(old_dir, new_dir, old_name.name, new_name, 0, -+ new_dentry->d_inode, old_dentry->d_inode); -+ } -+*/ -+freename: -+ kfree(old_name.name); -+ return error; -+} -+ - SYSCALL_DEFINE4(renameat, int, olddfd, const char __user *, oldname, - int, newdfd, const char __user *, newname) - { - struct dentry *old_dir, *new_dir; -- struct dentry *old_dentry, *new_dentry; -+ struct path old, new; - struct dentry *trap; - struct nameidata oldnd, newnd; - char *from; -@@ -2724,16 +3889,28 @@ SYSCALL_DEFINE4(renameat, int, olddfd, c - - trap = lock_rename(new_dir, old_dir); - -- old_dentry = lookup_hash(&oldnd); -- error = PTR_ERR(old_dentry); -- if (IS_ERR(old_dentry)) -+ /* -+ * For union mounts we need to call a giant lookup_rename_source() -+ * instead. -+ * First lock_rename() and look on the topmost fs like you would do in -+ * the normal rename, if you find something which is not a directory, -+ * go ahead and lookup target and do normal rename. -+ * If you find a negative dentry, unlock_rename() and continue as -+ * _hash_lookup_union() would do without locking the topmost parent -+ * at the end. After that do lock_rename() of the source parent and the -+ * target parent and do a copyup with additional whiteout creation at -+ * the end. -+ */ -+// error = hash_lookup_union(&oldnd, &oldnd.last, &old); -+ error = lookup_rename_source(&oldnd, &newnd, &trap, &oldnd.last, &old); -+ if (error) - goto exit3; - /* source must exist */ - error = -ENOENT; -- if (!old_dentry->d_inode) -+ if (!old.dentry->d_inode) - goto exit4; - /* unless the source is a directory trailing slashes give -ENOTDIR */ -- if (!S_ISDIR(old_dentry->d_inode->i_mode)) { -+ if (!S_ISDIR(old.dentry->d_inode->i_mode)) { - error = -ENOTDIR; - if (oldnd.last.name[oldnd.last.len]) - goto exit4; -@@ -2742,32 +3919,44 @@ SYSCALL_DEFINE4(renameat, int, olddfd, c - } - /* source should not be ancestor of target */ - error = -EINVAL; -- if (old_dentry == trap) -+ if (old.dentry == trap) - goto exit4; -- new_dentry = lookup_hash(&newnd); -- error = PTR_ERR(new_dentry); -- if (IS_ERR(new_dentry)) -+ /* target is always on topmost fs, even with unions */ -+ error = lookup_hash(&newnd, &newnd.last, &new); -+ if (error) - goto exit4; - /* target should not be an ancestor of source */ - error = -ENOTEMPTY; -- if (new_dentry == trap) -+ if (new.dentry == trap) -+ goto exit5; -+ /* renaming of directories on unions is done by the user-space */ -+ error = -EXDEV; -+ if (is_unionized(oldnd.path.dentry, oldnd.path.mnt) && -+ S_ISDIR(old.dentry->d_inode->i_mode)) - goto exit5; -+// if (is_unionized(newnd.path.dentry, newnd.path.mnt)) -+// goto exit5; - - error = mnt_want_write(oldnd.path.mnt); - if (error) - goto exit5; -- error = security_path_rename(&oldnd.path, old_dentry, -- &newnd.path, new_dentry); -+ error = security_path_rename(&oldnd.path, old.dentry, -+ &newnd.path, new.dentry); - if (error) - goto exit6; -- error = vfs_rename(old_dir->d_inode, old_dentry, -- new_dir->d_inode, new_dentry); -+ if (is_unionized(oldnd.path.dentry, oldnd.path.mnt) && -+ (old.dentry->d_parent != oldnd.path.dentry)) { -+ error = vfs_rename_union(&oldnd, &old, &newnd, &new); -+ goto exit6; -+ } -+ error = vfs_rename(old_dir->d_inode, old.dentry, -+ new_dir->d_inode, new.dentry); - exit6: - mnt_drop_write(oldnd.path.mnt); - exit5: -- dput(new_dentry); -+ path_put_conditional(&new, &newnd); - exit4: -- dput(old_dentry); -+ path_put_conditional(&old, &oldnd); - exit3: - unlock_rename(new_dir, old_dir); - exit2: ---- a/fs/namespace.c -+++ b/fs/namespace.c -@@ -29,6 +29,7 @@ - #include - #include - #include -+#include - #include - #include - #include "pnode.h" -@@ -150,6 +151,9 @@ struct vfsmount *alloc_vfsmnt(const char - INIT_LIST_HEAD(&mnt->mnt_share); - INIT_LIST_HEAD(&mnt->mnt_slave_list); - INIT_LIST_HEAD(&mnt->mnt_slave); -+#ifdef CONFIG_UNION_MOUNT -+ INIT_LIST_HEAD(&mnt->mnt_unions); -+#endif - #ifdef CONFIG_SMP - mnt->mnt_writers = alloc_percpu(int); - if (!mnt->mnt_writers) -@@ -469,6 +473,7 @@ static void __touch_mnt_namespace(struct - - static void detach_mnt(struct vfsmount *mnt, struct path *old_path) - { -+ detach_mnt_union(mnt); - old_path->dentry = mnt->mnt_mountpoint; - old_path->mnt = mnt->mnt_parent; - mnt->mnt_parent = mnt; -@@ -492,6 +497,7 @@ static void attach_mnt(struct vfsmount * - list_add_tail(&mnt->mnt_hash, mount_hashtable + - hash(path->mnt, path->dentry)); - list_add_tail(&mnt->mnt_child, &path->mnt->mnt_mounts); -+ attach_mnt_union(mnt, path->mnt, path->dentry); - } - - /* -@@ -514,6 +520,7 @@ static void commit_tree(struct vfsmount - list_add_tail(&mnt->mnt_hash, mount_hashtable + - hash(parent, mnt->mnt_mountpoint)); - list_add_tail(&mnt->mnt_child, &parent->mnt_mounts); -+ attach_mnt_union(mnt, mnt->mnt_parent, mnt->mnt_mountpoint); - touch_mnt_namespace(n); - } - -@@ -770,6 +777,7 @@ static void show_mnt_opts(struct seq_fil - { MNT_NODIRATIME, ",nodiratime" }, - { MNT_RELATIME, ",relatime" }, - { MNT_STRICTATIME, ",strictatime" }, -+ { MNT_UNION, ",union" }, - { 0, NULL } - }; - const struct proc_fs_info *fs_infop; -@@ -984,6 +992,7 @@ void release_mounts(struct list_head *he - struct dentry *dentry; - struct vfsmount *m; - spin_lock(&vfsmount_lock); -+ detach_mnt_union(mnt); - dentry = mnt->mnt_mountpoint; - m = mnt->mnt_parent; - mnt->mnt_mountpoint = mnt->mnt_root; -@@ -1102,6 +1111,11 @@ static int do_umount(struct vfsmount *mn - spin_unlock(&vfsmount_lock); - if (retval) - security_sb_umount_busy(mnt); -+ /* If this was a union mount, we are no longer a read-only -+ * user on the underlying mount */ -+ if (mnt->mnt_flags & MNT_UNION) -+ mnt->mnt_parent->mnt_sb->s_readonly_users--; -+ - up_write(&namespace_sem); - release_mounts(&umount_list); - return retval; -@@ -1426,6 +1440,10 @@ static int do_change_type(struct path *p - if (path->dentry != path->mnt->mnt_root) - return -EINVAL; - -+ /* Don't change the type of union mounts */ -+ if (IS_MNT_UNION(path->mnt)) -+ return -EINVAL; -+ - down_write(&namespace_sem); - if (type == MS_SHARED) { - err = invent_group_ids(mnt, recurse); -@@ -1444,10 +1462,65 @@ static int do_change_type(struct path *p - } - - /* -+ * Mount-time check of upper and lower layer file systems to see if we -+ * can union mount one on the other. -+ * -+ * Union mounts must follow these rules: -+ * -+ * - The lower layer must be read-only. This avoids lots of nasty -+ * unsolvable races where file system structures disappear suddenly. -+ * XXX - Checking the vfsmnt for read-only is a temporary hack; the -+ * file system could be mounted read-write elsewhere. We need to -+ * enforce read-only at the superblock level (patches coming). -+ * -+ * - The upper layer must be writable. This isn't an absolute -+ * requirement; right now we need it to make readdir() work since we -+ * copy up directory entries to the top level. A possible -+ * workaround is to mount a tmpfs file system transparently over the -+ * top. -+ * -+ * - The upper layer must support whiteouts and fallthrus (if it is -+ * writeable). -+ * -+ * - The lower layer must not also be a union mount. This is just to -+ * make life simpler for now, there is no inherent limitation on the -+ * number of layers. -+ * -+ * XXX - Check other mount flags for incompatibilities - I'm sure -+ * there are some. -+ */ -+ -+static int -+check_union_mnt(struct path *mntpnt, struct vfsmount *top_mnt, int mnt_flags) -+{ -+ struct vfsmount *lower_mnt = mntpnt->mnt; -+ -+ /* Is this even a union mount? */ -+ if (!(mnt_flags & MNT_UNION)) -+ return 0; -+ -+ /* Lower layer must be read-only and not a union mount */ -+ if (!(lower_mnt->mnt_sb->s_flags & MS_RDONLY) || -+ (lower_mnt->mnt_flags & MNT_UNION)) -+ return -EBUSY; -+ -+ /* Upper layer must be writable */ -+ if (mnt_flags & MNT_READONLY) -+ return -EROFS; -+ -+ /* Upper layer must support whiteouts and fallthrus */ -+ if (!(top_mnt->mnt_sb->s_flags & MS_WHITEOUT)) -+ return -EINVAL; -+ -+ /* All good! */ -+ return 0; -+} -+ -+/* - * do loopback mount. - */ --static int do_loopback(struct path *path, char *old_name, -- int recurse) -+static int do_loopback(struct path *path, char *old_name, int recurse, -+ int mnt_flags) - { - struct path old_path; - struct vfsmount *mnt = NULL; -@@ -1477,6 +1550,13 @@ static int do_loopback(struct path *path - if (!mnt) - goto out; - -+ err = check_union_mnt(&old_path, mnt, mnt_flags); -+ if (err) -+ goto out; -+ -+ if (mnt_flags & MNT_UNION) -+ mnt->mnt_flags |= MNT_UNION; -+ - err = graft_tree(mnt, path); - if (err) { - LIST_HEAD(umount_list); -@@ -1486,6 +1566,10 @@ static int do_loopback(struct path *path - release_mounts(&umount_list); - } - -+ /* If this is a union mount, add ourselves to the readonly users */ -+ if (mnt_flags & MNT_UNION) -+ mnt->mnt_parent->mnt_sb->s_readonly_users++; -+ - out: - up_write(&namespace_sem); - path_put(&old_path); -@@ -1570,6 +1654,13 @@ static int do_move_mount(struct path *pa - if (err) - return err; - -+ /* moving to or from a union mount is not supported */ -+ err = -EINVAL; -+ if (IS_MNT_UNION(path->mnt)) -+ goto exit; -+ if (IS_MNT_UNION(old_path.mnt)) -+ goto exit; -+ - down_write(&namespace_sem); - while (d_mountpoint(path->dentry) && - follow_down(path)) -@@ -1627,6 +1718,7 @@ out: - up_write(&namespace_sem); - if (!err) - path_put(&parent_path); -+exit: - path_put(&old_path); - return err; - } -@@ -1684,10 +1776,18 @@ int do_add_mount(struct vfsmount *newmnt - if (S_ISLNK(newmnt->mnt_root->d_inode->i_mode)) - goto unlock; - -+ err = check_union_mnt(path, newmnt, mnt_flags); -+ if (err) -+ goto unlock; -+ - newmnt->mnt_flags = mnt_flags; - if ((err = graft_tree(newmnt, path))) - goto unlock; - -+ /* If this is a union mount, add ourselves to the readonly users */ -+ if (mnt_flags & MNT_UNION) -+ newmnt->mnt_parent->mnt_sb->s_readonly_users++; -+ - if (fslist) /* add to the specified expiration list */ - list_add_tail(&newmnt->mnt_expire, fslist); - -@@ -1940,10 +2040,12 @@ long do_mount(char *dev_name, char *dir_ - mnt_flags &= ~(MNT_RELATIME | MNT_NOATIME); - if (flags & MS_RDONLY) - mnt_flags |= MNT_READONLY; -+ if (flags & MS_UNION) -+ mnt_flags |= MNT_UNION; - - flags &= ~(MS_NOSUID | MS_NOEXEC | MS_NODEV | MS_ACTIVE | - MS_NOATIME | MS_NODIRATIME | MS_RELATIME| MS_KERNMOUNT | -- MS_STRICTATIME); -+ MS_STRICTATIME | MS_UNION); - - /* ... and get the mountpoint */ - retval = kern_path(dir_name, LOOKUP_FOLLOW, &path); -@@ -1959,7 +2061,8 @@ long do_mount(char *dev_name, char *dir_ - retval = do_remount(&path, flags & ~MS_REMOUNT, mnt_flags, - data_page); - else if (flags & MS_BIND) -- retval = do_loopback(&path, dev_name, flags & MS_REC); -+ retval = do_loopback(&path, dev_name, flags & MS_REC, -+ mnt_flags); - else if (flags & (MS_SHARED | MS_PRIVATE | MS_SLAVE | MS_UNBINDABLE)) - retval = do_change_type(&path, flags); - else if (flags & MS_MOVE) -@@ -2196,6 +2299,8 @@ SYSCALL_DEFINE2(pivot_root, const char _ - if (d_unlinked(old.dentry)) - goto out2; - error = -EBUSY; -+ follow_union_down(&new); -+ follow_union_down(&root); - if (new.mnt == root.mnt || - old.mnt == root.mnt) - goto out2; /* loop, on the same file system */ ---- a/fs/nfsctl.c -+++ b/fs/nfsctl.c -@@ -38,10 +38,10 @@ static struct file *do_open(char *name, - return ERR_PTR(error); - - if (flags == O_RDWR) -- error = may_open(&nd.path, MAY_READ|MAY_WRITE, -- FMODE_READ|FMODE_WRITE); -+ error = may_open(&nd, MAY_READ|MAY_WRITE, -+ FMODE_READ|FMODE_WRITE); - else -- error = may_open(&nd.path, MAY_WRITE, FMODE_WRITE); -+ error = may_open(&nd, MAY_WRITE, FMODE_WRITE); - - if (!error) - return dentry_open(nd.path.dentry, nd.path.mnt, flags, ---- a/fs/nfsd/nfs3xdr.c -+++ b/fs/nfsd/nfs3xdr.c -@@ -898,6 +898,11 @@ encode_entry(struct readdir_cd *ccd, con - int elen; /* estimated entry length in words */ - int num_entry_words = 0; /* actual number of words */ - -+ if (d_type == DT_WHT) { -+ cd->common.err = nfs_ok; -+ return 0; -+ } -+ - if (cd->offset) { - u64 offset64 = offset; - ---- a/fs/nfsd/nfs4xdr.c -+++ b/fs/nfsd/nfs4xdr.c -@@ -2261,7 +2261,7 @@ nfsd4_encode_dirent(void *ccdv, const ch - __be32 nfserr = nfserr_toosmall; - - /* In nfsv4, "." and ".." never make it onto the wire.. */ -- if (name && isdotent(name, namlen)) { -+ if (d_type == DT_WHT || (name && isdotent(name, namlen))) { - cd->common.err = nfs_ok; - return 0; - } ---- a/fs/nfsd/nfsxdr.c -+++ b/fs/nfsd/nfsxdr.c -@@ -513,6 +513,10 @@ nfssvc_encode_entry(void *ccdv, const ch - namlen, name, offset, ino); - */ - -+ if (d_type == DT_WHT) { -+ cd->common.err = nfs_ok; -+ return 0; -+ } - if (offset > ~((u32) 0)) { - cd->common.err = nfserr_fbig; - return -EINVAL; ---- a/fs/open.c -+++ b/fs/open.c -@@ -30,6 +30,7 @@ - #include - #include - #include -+#include - - int vfs_statfs(struct dentry *dentry, struct kstatfs *buf) - { -@@ -224,69 +225,69 @@ int do_truncate(struct dentry *dentry, l - return ret; - } - --static long do_sys_truncate(const char __user *pathname, loff_t length) -+static int __do_ftruncate(struct file *file, unsigned long length, int small) - { -- struct path path; -- struct inode *inode; -+ struct inode * inode; -+ struct dentry *dentry; - int error; - - error = -EINVAL; -- if (length < 0) /* sorry, but loff_t says... */ -+ if (length < 0) - goto out; -+ /* explicitly opened as large or we are on 64-bit box */ -+ if (file->f_flags & O_LARGEFILE) -+ small = 0; - -- error = user_path(pathname, &path); -- if (error) -+ dentry = file->f_path.dentry; -+ inode = dentry->d_inode; -+ error = -EINVAL; -+ if (!S_ISREG(inode->i_mode) || !(file->f_mode & FMODE_WRITE)) - goto out; -- inode = path.dentry->d_inode; -- -- /* For directories it's -EISDIR, for other non-regulars - -EINVAL */ -- error = -EISDIR; -- if (S_ISDIR(inode->i_mode)) -- goto dput_and_out; - - error = -EINVAL; -- if (!S_ISREG(inode->i_mode)) -- goto dput_and_out; -- -- error = mnt_want_write(path.mnt); -- if (error) -- goto dput_and_out; -+ /* Cannot ftruncate over 2^31 bytes without large file support */ -+ if (small && length > MAX_NON_LFS) - -- error = inode_permission(inode, MAY_WRITE); -- if (error) -- goto mnt_drop_write_and_out; -+ goto out; - - error = -EPERM; - if (IS_APPEND(inode)) -- goto mnt_drop_write_and_out; -+ goto out; - -- error = get_write_access(inode); -- if (error) -- goto mnt_drop_write_and_out; -+ error = locks_verify_truncate(inode, file, length); -+ if (!error) -+ error = security_path_truncate(&file->f_path, length, -+ ATTR_MTIME|ATTR_CTIME); -+ if (!error) -+ /* Already copied up for union, opened with write */ -+ error = do_truncate(dentry, length, ATTR_MTIME|ATTR_CTIME, file); -+out: -+ return error; -+} - -- /* -- * Make sure that there are no leases. get_write_access() protects -- * against the truncate racing with a lease-granting setlease(). -- */ -- error = break_lease(inode, FMODE_WRITE); -- if (error) -- goto put_write_and_out; -+static long do_sys_truncate(const char __user *pathname, loff_t length) -+{ -+ struct file *file; -+ char *tmp; -+ int error; - -- error = locks_verify_truncate(inode, NULL, length); -- if (!error) -- error = security_path_truncate(&path, length, 0); -- if (!error) { -- vfs_dq_init(inode); -- error = do_truncate(path.dentry, length, 0, NULL); -- } -+ error = -EINVAL; -+ if (length < 0) /* sorry, but loff_t says... */ -+ return error; - --put_write_and_out: -- put_write_access(inode); --mnt_drop_write_and_out: -- mnt_drop_write(path.mnt); --dput_and_out: -- path_put(&path); --out: -+ tmp = getname(pathname); -+ if (IS_ERR(tmp)) -+ return PTR_ERR(tmp); -+ -+ file = filp_open(tmp, O_RDWR | O_LARGEFILE, 0); -+ putname(tmp); -+ -+ if (IS_ERR(file)) -+ return PTR_ERR(file); -+ -+ error = __do_ftruncate(file, length, 0); -+ -+ fput(file); - return error; - } - -@@ -297,45 +298,16 @@ SYSCALL_DEFINE2(truncate, const char __u - - static long do_sys_ftruncate(unsigned int fd, loff_t length, int small) - { -- struct inode * inode; -- struct dentry *dentry; - struct file * file; - int error; - -- error = -EINVAL; -- if (length < 0) -- goto out; - error = -EBADF; - file = fget(fd); - if (!file) - goto out; - -- /* explicitly opened as large or we are on 64-bit box */ -- if (file->f_flags & O_LARGEFILE) -- small = 0; -- -- dentry = file->f_path.dentry; -- inode = dentry->d_inode; -- error = -EINVAL; -- if (!S_ISREG(inode->i_mode) || !(file->f_mode & FMODE_WRITE)) -- goto out_putf; -- -- error = -EINVAL; -- /* Cannot ftruncate over 2^31 bytes without large file support */ -- if (small && length > MAX_NON_LFS) -- goto out_putf; -+ error = __do_ftruncate(file, length, small); - -- error = -EPERM; -- if (IS_APPEND(inode)) -- goto out_putf; -- -- error = locks_verify_truncate(inode, file, length); -- if (!error) -- error = security_path_truncate(&file->f_path, length, -- ATTR_MTIME|ATTR_CTIME); -- if (!error) -- error = do_truncate(dentry, length, ATTR_MTIME|ATTR_CTIME, file); --out_putf: - fput(file); - out: - return error; -@@ -494,7 +466,8 @@ SYSCALL_DEFINE3(faccessat, int, dfd, con - goto out_path_release; - } - -- res = inode_permission(inode, mode | MAY_ACCESS); -+ res = union_permission(&path, mode | MAY_ACCESS); -+ - /* SuS v2 requires we report a read only fs too */ - if (res || !(mode & S_IWOTH) || special_file(inode->i_mode)) - goto out_path_release; -@@ -508,7 +481,8 @@ SYSCALL_DEFINE3(faccessat, int, dfd, con - * inherently racy and know that the fs may change - * state before we even see this result. - */ -- if (__mnt_is_readonly(path.mnt)) -+ if ((!is_unionized(path.dentry, path.mnt) && -+ (__mnt_is_readonly(path.mnt)))) - res = -EROFS; - - out_path_release: -@@ -554,20 +528,19 @@ SYSCALL_DEFINE1(fchdir, unsigned int, fd - error = -EBADF; - file = fget(fd); - if (!file) -- goto out; -+ return error; - - inode = file->f_path.dentry->d_inode; - - error = -ENOTDIR; - if (!S_ISDIR(inode->i_mode)) -- goto out_putf; -+ goto out; - - error = inode_permission(inode, MAY_EXEC | MAY_ACCESS); - if (!error) - set_fs_pwd(current->fs, &file->f_path); --out_putf: -- fput(file); - out: -+ fput(file); - return error; - } - ---- a/fs/readdir.c -+++ b/fs/readdir.c -@@ -16,6 +16,7 @@ - #include - #include - #include -+#include - - #include - -@@ -36,9 +37,24 @@ int vfs_readdir(struct file *file, filld - - res = -ENOENT; - if (!IS_DEADDIR(inode)) { -+ /* -+ * XXX Think harder about locking for -+ * union_copyup_dir. Currently we lock the topmost -+ * directory and hold that lock while sequentially -+ * acquiring and dropping locks for the directories -+ * below this one in the union stack. -+ */ -+ if (is_unionized(file->f_path.dentry, file->f_path.mnt) && -+ !IS_OPAQUE(inode)) { -+ res = union_copyup_dir(&file->f_path); -+ if (res) -+ goto out_unlock; -+ } -+ - res = file->f_op->readdir(file, buf, filler); - file_accessed(file); - } -+out_unlock: - mutex_unlock(&inode->i_mutex); - out: - return res; -@@ -77,6 +93,9 @@ static int fillonedir(void * __buf, cons - struct old_linux_dirent __user * dirent; - unsigned long d_ino; - -+ if (d_type == DT_WHT) -+ return 0; -+ - if (buf->result) - return -EINVAL; - d_ino = ino; -@@ -154,6 +173,9 @@ static int filldir(void * __buf, const c - unsigned long d_ino; - int reclen = ALIGN(NAME_OFFSET(dirent) + namlen + 2, sizeof(long)); - -+ if (d_type == DT_WHT) -+ return 0; -+ - buf->error = -EINVAL; /* only used if we fail.. */ - if (reclen > buf->count) - return -EINVAL; -@@ -239,6 +261,9 @@ static int filldir64(void * __buf, const - struct getdents_callback64 * buf = (struct getdents_callback64 *) __buf; - int reclen = ALIGN(NAME_OFFSET(dirent) + namlen + 1, sizeof(u64)); - -+ if (d_type == DT_WHT) -+ return 0; -+ - buf->error = -EINVAL; /* only used if we fail.. */ - if (reclen > buf->count) - return -EINVAL; ---- a/fs/super.c -+++ b/fs/super.c -@@ -596,6 +596,15 @@ int do_remount_sb(struct super_block *sb - } - remount_rw = !(flags & MS_RDONLY) && (sb->s_flags & MS_RDONLY); - -+ /* If we are remounting read/write, make sure that none of the -+ users require read-only for correct operation (such as -+ union mounts). */ -+ if (remount_rw && sb->s_readonly_users) { -+ printk(KERN_INFO "%s: In use by %d read-only user(s)\n", -+ sb->s_id, sb->s_readonly_users); -+ return -EROFS; -+ } -+ - if (sb->s_op->remount_fs) { - retval = sb->s_op->remount_fs(sb, &flags, data); - if (retval) -@@ -953,6 +962,11 @@ vfs_kern_mount(struct file_system_type * - WARN((mnt->mnt_sb->s_maxbytes < 0), "%s set sb->s_maxbytes to " - "negative value (%lld)\n", type->name, mnt->mnt_sb->s_maxbytes); - -+ error = -EROFS; -+ if (!(flags & MS_RDONLY) && -+ (mnt->mnt_sb->s_readonly_users)) -+ goto out_sb; -+ - mnt->mnt_mountpoint = mnt->mnt_root; - mnt->mnt_parent = mnt; - up_write(&mnt->mnt_sb->s_umount); ---- /dev/null -+++ b/fs/union.c -@@ -0,0 +1,981 @@ -+/* -+ * VFS based union mount for Linux -+ * -+ * Copyright (C) 2004-2007 IBM Corporation, IBM Deutschland Entwicklung GmbH. -+ * Copyright (C) 2007-2009 Novell Inc. -+ * -+ * Author(s): Jan Blunck (j.blunck@tu-harburg.de) -+ * Valerie Aurora -+ * -+ * 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. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+/* -+ * This is borrowed from fs/inode.c. The hashtable for lookups. Somebody -+ * should try to make this good - I've just made it work. -+ */ -+static unsigned int union_hash_mask __read_mostly; -+static unsigned int union_hash_shift __read_mostly; -+static struct hlist_head *union_hashtable __read_mostly; -+static unsigned int union_rhash_mask __read_mostly; -+static unsigned int union_rhash_shift __read_mostly; -+static struct hlist_head *union_rhashtable __read_mostly; -+ -+/* -+ * Locking Rules: -+ * - dcache_lock (for union_rlookup() only) -+ * - union_lock -+ */ -+DEFINE_SPINLOCK(union_lock); -+ -+static struct kmem_cache *union_cache __read_mostly; -+ -+static unsigned long hash(struct dentry *dentry, struct vfsmount *mnt) -+{ -+ unsigned long tmp; -+ -+ tmp = ((unsigned long)mnt * (unsigned long)dentry) ^ -+ (GOLDEN_RATIO_PRIME + (unsigned long)mnt) / L1_CACHE_BYTES; -+ tmp = tmp ^ ((tmp ^ GOLDEN_RATIO_PRIME) >> union_hash_shift); -+ return tmp & union_hash_mask; -+} -+ -+static __initdata unsigned long union_hash_entries; -+ -+static int __init set_union_hash_entries(char *str) -+{ -+ if (!str) -+ return 0; -+ union_hash_entries = simple_strtoul(str, &str, 0); -+ return 1; -+} -+ -+__setup("union_hash_entries=", set_union_hash_entries); -+ -+static int __init init_union(void) -+{ -+ int loop; -+ -+ union_cache = KMEM_CACHE(union_mount, SLAB_PANIC | SLAB_MEM_SPREAD); -+ union_hashtable = alloc_large_system_hash("Union-cache", -+ sizeof(struct hlist_head), -+ union_hash_entries, -+ 14, -+ 0, -+ &union_hash_shift, -+ &union_hash_mask, -+ 0); -+ -+ for (loop = 0; loop < (1 << union_hash_shift); loop++) -+ INIT_HLIST_HEAD(&union_hashtable[loop]); -+ -+ -+ union_rhashtable = alloc_large_system_hash("rUnion-cache", -+ sizeof(struct hlist_head), -+ union_hash_entries, -+ 14, -+ 0, -+ &union_rhash_shift, -+ &union_rhash_mask, -+ 0); -+ -+ for (loop = 0; loop < (1 << union_rhash_shift); loop++) -+ INIT_HLIST_HEAD(&union_rhashtable[loop]); -+ -+ return 0; -+} -+ -+fs_initcall(init_union); -+ -+struct union_mount *union_alloc(struct dentry *this, struct vfsmount *this_mnt, -+ struct dentry *next, struct vfsmount *next_mnt) -+{ -+ struct union_mount *um; -+ -+ BUG_ON(!S_ISDIR(this->d_inode->i_mode)); -+ BUG_ON(!S_ISDIR(next->d_inode->i_mode)); -+ -+ um = kmem_cache_alloc(union_cache, GFP_ATOMIC); -+ if (!um) -+ return NULL; -+ -+ atomic_set(&um->u_count, 1); -+ INIT_LIST_HEAD(&um->u_unions); -+ INIT_LIST_HEAD(&um->u_list); -+ INIT_HLIST_NODE(&um->u_hash); -+ INIT_HLIST_NODE(&um->u_rhash); -+ -+ um->u_this.mnt = this_mnt; -+ um->u_this.dentry = this; -+ um->u_next.mnt = mntget(next_mnt); -+ um->u_next.dentry = dget(next); -+ -+ return um; -+} -+ -+struct union_mount *union_get(struct union_mount *um) -+{ -+ BUG_ON(!atomic_read(&um->u_count)); -+ atomic_inc(&um->u_count); -+ return um; -+} -+ -+static int __union_put(struct union_mount *um) -+{ -+ if (!atomic_dec_and_test(&um->u_count)) -+ return 0; -+ -+ BUG_ON(!hlist_unhashed(&um->u_hash)); -+ BUG_ON(!hlist_unhashed(&um->u_rhash)); -+ -+ kmem_cache_free(union_cache, um); -+ return 1; -+} -+ -+void union_put(struct union_mount *um) -+{ -+ struct path tmp = um->u_next; -+ -+ if (__union_put(um)) -+ path_put(&tmp); -+} -+ -+static void __union_hash(struct union_mount *um) -+{ -+ hlist_add_head(&um->u_hash, union_hashtable + -+ hash(um->u_this.dentry, um->u_this.mnt)); -+ hlist_add_head(&um->u_rhash, union_rhashtable + -+ hash(um->u_next.dentry, um->u_next.mnt)); -+} -+ -+static void __union_unhash(struct union_mount *um) -+{ -+ hlist_del_init(&um->u_hash); -+ hlist_del_init(&um->u_rhash); -+} -+ -+struct union_mount *union_lookup(struct dentry *dentry, struct vfsmount *mnt) -+{ -+ struct hlist_head *head = union_hashtable + hash(dentry, mnt); -+ struct hlist_node *node; -+ struct union_mount *um; -+ -+ hlist_for_each_entry(um, node, head, u_hash) { -+ if ((um->u_this.dentry == dentry) && -+ (um->u_this.mnt == mnt)) -+ return um; -+ } -+ -+ return NULL; -+} -+ -+struct union_mount *union_rlookup(struct dentry *dentry, struct vfsmount *mnt) -+{ -+ struct hlist_head *head = union_rhashtable + hash(dentry, mnt); -+ struct hlist_node *node; -+ struct union_mount *um; -+ -+ hlist_for_each_entry(um, node, head, u_rhash) { -+ if ((um->u_next.dentry == dentry) && -+ (um->u_next.mnt == mnt)) -+ return um; -+ } -+ -+ return NULL; -+} -+ -+/* -+ * is_unionized - check if a dentry lives on a union mounted file system -+ * -+ * This tests if a dentry is living on an union mounted file system by walking -+ * the file system hierarchy. -+ */ -+int is_unionized(struct dentry *dentry, struct vfsmount *mnt) -+{ -+ struct path this = { .mnt = mntget(mnt), -+ .dentry = dget(dentry) }; -+ struct vfsmount *tmp; -+ -+ do { -+ /* check if there is an union mounted on top of us */ -+ spin_lock(&vfsmount_lock); -+ list_for_each_entry(tmp, &this.mnt->mnt_mounts, mnt_child) { -+ if (!(tmp->mnt_flags & MNT_UNION)) -+ continue; -+ /* Isn't this a bug? */ -+ if (this.dentry->d_sb != tmp->mnt_mountpoint->d_sb) -+ continue; -+ if (is_subdir(this.dentry, tmp->mnt_mountpoint)) { -+ spin_unlock(&vfsmount_lock); -+ path_put(&this); -+ return 1; -+ } -+ } -+ spin_unlock(&vfsmount_lock); -+ -+ /* check our mountpoint next */ -+ tmp = mntget(this.mnt->mnt_parent); -+ dput(this.dentry); -+ this.dentry = dget(this.mnt->mnt_mountpoint); -+ mntput(this.mnt); -+ this.mnt = tmp; -+ } while (this.mnt != this.mnt->mnt_parent); -+ -+ path_put(&this); -+ return 0; -+} -+ -+int append_to_union(struct vfsmount *mnt, struct dentry *dentry, -+ struct vfsmount *dest_mnt, struct dentry *dest_dentry) -+{ -+ struct union_mount *this, *um; -+ -+ BUG_ON(!IS_MNT_UNION(mnt)); -+ -+ this = union_alloc(dentry, mnt, dest_dentry, dest_mnt); -+ if (!this) -+ return -ENOMEM; -+ -+ spin_lock(&union_lock); -+ um = union_lookup(dentry, mnt); -+ if (um) { -+ BUG_ON((um->u_next.dentry != dest_dentry) || -+ (um->u_next.mnt != dest_mnt)); -+ spin_unlock(&union_lock); -+ union_put(this); -+ return 0; -+ } -+ list_add(&this->u_list, &mnt->mnt_unions); -+ list_add(&this->u_unions, &dentry->d_unions); -+ dest_dentry->d_unionized++; -+ __union_hash(this); -+ spin_unlock(&union_lock); -+ return 0; -+} -+ -+/* -+ * follow_union_down - follow the union stack one layer down -+ * -+ * This is called to traverse the union stack from one layer to the next -+ * overlayed one. follow_union_down() is called by various lookup functions -+ * that are aware of union mounts. -+ * -+ * Returns non-zero if followed to the next layer, zero otherwise. -+ */ -+int follow_union_down(struct path *path) -+{ -+ struct union_mount *um; -+ -+ if (!IS_MNT_UNION(path->mnt)) -+ return 0; -+ -+ spin_lock(&union_lock); -+ um = union_lookup(path->dentry, path->mnt); -+ spin_unlock(&union_lock); -+ if (um) { -+ path_get(&um->u_next); -+ dput(path->dentry); -+ path->dentry = um->u_next.dentry; -+ mntput(path->mnt); -+ path->mnt = um->u_next.mnt; -+ return 1; -+ } -+ return 0; -+} -+ -+/* -+ * follow_union_mount - follow the union stack to the topmost layer -+ * -+ * This is called to traverse the union stack to the topmost layer. This is -+ * necessary for following parent pointers in an union mount. -+ * -+ * Returns none zero if followed to the topmost layer, zero otherwise. -+ */ -+int follow_union_mount(struct path *path) -+{ -+ struct union_mount *um; -+ int res = 0; -+ -+ while (IS_UNION(path->dentry)) { -+ spin_lock(&dcache_lock); -+ spin_lock(&union_lock); -+ um = union_rlookup(path->dentry, path->mnt); -+ if (um) -+ path_get(&um->u_this); -+ spin_unlock(&union_lock); -+ spin_unlock(&dcache_lock); -+ -+ /* -+ * Q: Aaargh, how do I validate the topmost dentry pointer? -+ * A: Eeeeasy! We took the dcache_lock and union_lock. Since -+ * this protects from any dput'ng going on, we know that the -+ * dentry is valid since the union is unhashed under -+ * dcache_lock too. -+ */ -+ if (!um) -+ break; -+ dput(path->dentry); -+ path->dentry = um->u_this.dentry; -+ mntput(path->mnt); -+ path->mnt = um->u_this.mnt; -+ res = 1; -+ } -+ -+ return res; -+} -+ -+/* -+ * Union mount copyup support -+ */ -+ -+extern int hash_lookup_union(struct nameidata *, struct qstr *, struct path *); -+extern void follow_mount(struct path *); -+ -+/* -+ * union_relookup_topmost - lookup and create the topmost path to dentry -+ * @nd: pointer to nameidata -+ * @flags: lookup flags -+ */ -+static int union_relookup_topmost(struct nameidata *nd, int flags) -+{ -+ int err; -+ char *kbuf, *name; -+ struct nameidata this; -+ -+ kbuf = (char *)__get_free_page(GFP_KERNEL); -+ if (!kbuf) -+ return -ENOMEM; -+ -+ name = d_path(&nd->path, kbuf, PAGE_SIZE); -+ err = PTR_ERR(name); -+ if (IS_ERR(name)) -+ goto free_page; -+ -+ err = path_lookup(name, flags|LOOKUP_CREATE|LOOKUP_TOPMOST, &this); -+ if (err) -+ goto free_page; -+ -+ path_put(&nd->path); -+ nd->path.dentry = this.path.dentry; -+ nd->path.mnt = this.path.mnt; -+ -+ /* -+ * the nd->flags should be unchanged -+ */ -+ BUG_ON(this.um_flags & LAST_LOWLEVEL); -+ nd->um_flags &= ~LAST_LOWLEVEL; -+ free_page: -+ free_page((unsigned long)kbuf); -+ return err; -+} -+ -+static void __update_fs_pwd(struct path *path, struct dentry *dentry, -+ struct vfsmount *mnt) -+{ -+ struct path old = { NULL, NULL }; -+ -+ write_lock(¤t->fs->lock); -+ if (current->fs->pwd.dentry == path->dentry) { -+ old = current->fs->pwd; -+ path_get(¤t->fs->pwd); -+ } -+ write_unlock(¤t->fs->lock); -+ -+ if (old.dentry) -+ path_put(&old); -+ -+ return; -+} -+ -+/** -+ * union_permission - check for access rights to a given inode -+ * @inode: inode to check permission on -+ * @mask: right to check for (%MAY_READ, %MAY_WRITE, %MAY_EXEC) -+ * -+ * In a union mount, the top layer is always read-write and the bottom -+ * is always read-only. Ignore the read-only flag on the lower fs. -+ * -+ * Only need for certain activities, like checking to see if write -+ * access is ok. -+ */ -+ -+int union_permission(struct path *path, int mask) -+{ -+ struct inode *inode = path->dentry->d_inode; -+ -+ if (!is_unionized(path->dentry, path->mnt)) -+ return inode_permission(inode, mask); -+ -+ /* Tell __inode_permission to ignore MS_RDONLY */ -+ return __inode_permission(inode, mask, 0); -+} -+ -+/* -+ * union_create_topmost - create the topmost path component -+ * @nd: pointer to nameidata of the base directory -+ * @name: pointer to file name -+ * @path: pointer to path of the overlaid file -+ * -+ * This is called by __link_path_walk() to create the directories on a path -+ * when it is called with LOOKUP_TOPMOST. -+ */ -+struct dentry *union_create_topmost(struct nameidata *nd, struct qstr *name, -+ struct path *path) -+{ -+ struct dentry *dentry, *parent = nd->path.dentry; -+ int res, mode = path->dentry->d_inode->i_mode; -+ -+ if (parent->d_sb == path->dentry->d_sb) -+ return ERR_PTR(-EEXIST); -+ -+ mutex_lock(&parent->d_inode->i_mutex); -+ dentry = lookup_one_len(name->name, nd->path.dentry, name->len); -+ if (IS_ERR(dentry)) -+ goto out_unlock; -+ -+ switch (mode & S_IFMT) { -+ case S_IFREG: -+ /* -+ * FIXME: Does this make any sense in this case? -+ * Special case - lookup gave negative, but... we had foo/bar/ -+ * From the vfs_mknod() POV we just have a negative dentry - -+ * all is fine. Let's be bastards - you had / on the end,you've -+ * been asking for (non-existent) directory. -ENOENT for you. -+ */ -+ if (name->name[name->len] && !dentry->d_inode) { -+ dput(dentry); -+ dentry = ERR_PTR(-ENOENT); -+ goto out_unlock; -+ } -+ -+ res = vfs_create(parent->d_inode, dentry, mode, nd); -+ if (res) { -+ dput(dentry); -+ dentry = ERR_PTR(res); -+ goto out_unlock; -+ } -+ break; -+ case S_IFDIR: -+ res = vfs_mkdir(parent->d_inode, dentry, mode); -+ if (res) { -+ dput(dentry); -+ dentry = ERR_PTR(res); -+ goto out_unlock; -+ } -+ -+ res = append_to_union(nd->path.mnt, dentry, path->mnt, -+ path->dentry); -+ if (res) { -+ dput(dentry); -+ dentry = ERR_PTR(res); -+ goto out_unlock; -+ } -+ break; -+ default: -+ dput(dentry); -+ dentry = ERR_PTR(-EINVAL); -+ goto out_unlock; -+ } -+ -+ /* FIXME: Really necessary ??? */ -+/* __update_fs_pwd(path, dentry, nd->path.mnt); */ -+ -+ out_unlock: -+ mutex_unlock(&parent->d_inode->i_mutex); -+ return dentry; -+} -+ -+static int union_copy_file(struct dentry *old_dentry, struct vfsmount *old_mnt, -+ struct dentry *new_dentry, struct vfsmount *new_mnt) -+{ -+ int ret; -+ size_t size; -+ loff_t offset; -+ struct file *old_file, *new_file; -+ const struct cred *cred = current_cred(); -+ -+ dget(old_dentry); -+ mntget(old_mnt); -+ old_file = dentry_open(old_dentry, old_mnt, O_RDONLY, cred); -+ if (IS_ERR(old_file)) -+ return PTR_ERR(old_file); -+ -+ dget(new_dentry); -+ mntget(new_mnt); -+ new_file = dentry_open(new_dentry, new_mnt, O_WRONLY, cred); -+ ret = PTR_ERR(new_file); -+ if (IS_ERR(new_file)) -+ goto fput_old; -+ -+ /* XXX be smart by using a length param, which indicates max -+ * data we'll want (e.g., we are about to truncate to 0 or 10 -+ * bytes or something */ -+ size = i_size_read(old_file->f_path.dentry->d_inode); -+ if (((size_t)size != size) || ((ssize_t)size != size)) { -+ ret = -EFBIG; -+ goto fput_new; -+ } -+ -+ offset = 0; -+ ret = do_splice_direct(old_file, &offset, new_file, size, -+ SPLICE_F_MOVE); -+ if (ret >= 0) -+ ret = 0; -+ fput_new: -+ fput(new_file); -+ fput_old: -+ fput(old_file); -+ return ret; -+} -+ -+/** -+ * __union_copyup - copy a file to the topmost directory -+ * @old: pointer to path of the old file name -+ * @new_nd: pointer to nameidata of the topmost directory -+ * @new: pointer to path of the new file name -+ * -+ * The topmost directory @new_nd must already be locked. Creates the topmost -+ * file if it doesn't exist yet. -+ */ -+int __union_copyup(struct path *old, struct nameidata *new_nd, -+ struct path *new) -+{ -+ struct dentry *dentry; -+ int error; -+ -+ /* Maybe this should be -EINVAL */ -+ if (S_ISDIR(old->dentry->d_inode->i_mode)) -+ return -EISDIR; -+ -+ if (new_nd->path.dentry != new->dentry->d_parent) { -+ mutex_lock(&new_nd->path.dentry->d_inode->i_mutex); -+ dentry = lookup_one_len(new->dentry->d_name.name, -+ new_nd->path.dentry, -+ new->dentry->d_name.len); -+ mutex_unlock(&new_nd->path.dentry->d_inode->i_mutex); -+ if (IS_ERR(dentry)) -+ return PTR_ERR(dentry); -+ error = -EEXIST; -+ if (dentry->d_inode) -+ goto out_dput; -+ } else -+ dentry = dget(new->dentry); -+ -+ if (!dentry->d_inode) { -+ error = vfs_create(new_nd->path.dentry->d_inode, dentry, -+ old->dentry->d_inode->i_mode, new_nd); -+ if (error) -+ goto out_dput; -+ } -+ -+ BUG_ON(!S_ISREG(old->dentry->d_inode->i_mode)); -+ error = union_copy_file(old->dentry, old->mnt, dentry, -+ new_nd->path.mnt); -+ if (error) { -+ /* FIXME: are there return value we should not -+ * BUG() on ? */ -+ BUG_ON(vfs_unlink(new_nd->path.dentry->d_inode, -+ dentry)); -+ goto out_dput; -+ } -+ -+ dput(new->dentry); -+ new->dentry = dentry; -+ if (new->mnt != new_nd->path.mnt) -+ mntput(new->mnt); -+ new->mnt = new_nd->path.mnt; -+ return error; -+ -+out_dput: -+ dput(dentry); -+ return error; -+} -+ -+/* -+ * union_copyup - copy a file to the topmost layer of the union stack -+ * @nd: nameidata pointer to the file -+ * @flags: flags given to open_namei -+ */ -+int union_copyup(struct nameidata *nd, int flags /* XXX not used */) -+{ -+ struct qstr this; -+ char *name; -+ struct dentry *dir; -+ struct path path; -+ int err; -+ -+ if (!is_unionized(nd->path.dentry, nd->path.mnt)) -+ return 0; -+ if (!S_ISREG(nd->path.dentry->d_inode->i_mode)) -+ return 0; -+ -+ /* safe the name for hash_lookup_union() */ -+ this.len = nd->path.dentry->d_name.len; -+ this.hash = nd->path.dentry->d_name.hash; -+ name = kmalloc(this.len + 1, GFP_KERNEL); -+ if (!name) -+ return -ENOMEM; -+ this.name = name; -+ memcpy(name, nd->path.dentry->d_name.name, nd->path.dentry->d_name.len); -+ name[this.len] = 0; -+ -+ err = union_relookup_topmost(nd, nd->flags|LOOKUP_PARENT); -+ if (err) { -+ kfree(name); -+ return err; -+ } -+ nd->flags &= ~LOOKUP_PARENT; -+ -+ dir = nd->path.dentry; -+ mutex_lock(&dir->d_inode->i_mutex); -+ err = hash_lookup_union(nd, &this, &path); -+ mutex_unlock(&dir->d_inode->i_mutex); -+ kfree(name); -+ if (err) -+ return err; -+ -+ err = -ENOENT; -+ if (!path.dentry->d_inode) -+ goto exit_dput; -+ -+ /* Necessary?! I guess not ... */ -+ follow_mount(&path); -+ -+ err = -ENOENT; -+ if (!path.dentry->d_inode) -+ goto exit_dput; -+ -+ err = -EISDIR; -+ if (!S_ISREG(path.dentry->d_inode->i_mode)) -+ goto exit_dput; -+ -+ if (path.dentry->d_parent != nd->path.dentry) { -+ err = __union_copyup(&path, nd, &path); -+ if (err) -+ goto exit_dput; -+ } -+ -+ dput(nd->path.dentry); -+ if (nd->path.mnt != path.mnt) -+ mntput(nd->path.mnt); -+ nd->path = path; -+ return 0; -+ -+exit_dput: -+ dput(path.dentry); -+ if (path.mnt != nd->path.mnt) -+ mntput(path.mnt); -+ return err; -+} -+ -+/* -+ * This must be called when unhashing a dentry. This is called with dcache_lock -+ * and unhashes all unions this dentry is in. -+ */ -+void __d_drop_unions(struct dentry *dentry) -+{ -+ struct union_mount *this, *next; -+ -+ spin_lock(&union_lock); -+ list_for_each_entry_safe(this, next, &dentry->d_unions, u_unions) -+ __union_unhash(this); -+ spin_unlock(&union_lock); -+} -+EXPORT_SYMBOL_GPL(__d_drop_unions); -+ -+/* -+ * This must be called after __d_drop_unions() without holding any locks. -+ * Note: The dentry might still be reachable via a lookup but at that time it -+ * already a negative dentry. Otherwise it would be unhashed. The union_mount -+ * structure itself is still reachable through mnt->mnt_unions (which we -+ * protect against with union_lock). -+ */ -+void shrink_d_unions(struct dentry *dentry) -+{ -+ struct union_mount *this, *next; -+ -+repeat: -+ spin_lock(&union_lock); -+ list_for_each_entry_safe(this, next, &dentry->d_unions, u_unions) { -+ BUG_ON(!hlist_unhashed(&this->u_hash)); -+ BUG_ON(!hlist_unhashed(&this->u_rhash)); -+ list_del(&this->u_list); -+ list_del(&this->u_unions); -+ this->u_next.dentry->d_unionized--; -+ spin_unlock(&union_lock); -+ union_put(this); -+ goto repeat; -+ } -+ spin_unlock(&union_lock); -+} -+ -+extern void __dput(struct dentry *, struct list_head *, int); -+ -+/* -+ * This is the special variant for use in dput() only. -+ */ -+void __shrink_d_unions(struct dentry *dentry, struct list_head *list) -+{ -+ struct union_mount *this, *next; -+ -+ BUG_ON(!d_unhashed(dentry)); -+ -+repeat: -+ spin_lock(&union_lock); -+ list_for_each_entry_safe(this, next, &dentry->d_unions, u_unions) { -+ struct dentry *n_dentry = this->u_next.dentry; -+ struct vfsmount *n_mnt = this->u_next.mnt; -+ -+ BUG_ON(!hlist_unhashed(&this->u_hash)); -+ BUG_ON(!hlist_unhashed(&this->u_rhash)); -+ list_del(&this->u_list); -+ list_del(&this->u_unions); -+ this->u_next.dentry->d_unionized--; -+ spin_unlock(&union_lock); -+ if (__union_put(this)) { -+ __dput(n_dentry, list, 0); -+ mntput(n_mnt); -+ } -+ goto repeat; -+ } -+ spin_unlock(&union_lock); -+} -+ -+/* -+ * Remove all union_mounts structures belonging to this vfsmount from the -+ * union lookup hashtable and so on ... -+ */ -+void shrink_mnt_unions(struct vfsmount *mnt) -+{ -+ struct union_mount *this, *next; -+ -+repeat: -+ spin_lock(&union_lock); -+ list_for_each_entry_safe(this, next, &mnt->mnt_unions, u_list) { -+ if (this->u_this.dentry == mnt->mnt_root) -+ continue; -+ __union_unhash(this); -+ list_del(&this->u_list); -+ list_del(&this->u_unions); -+ this->u_next.dentry->d_unionized--; -+ spin_unlock(&union_lock); -+ union_put(this); -+ goto repeat; -+ } -+ spin_unlock(&union_lock); -+} -+ -+int attach_mnt_union(struct vfsmount *mnt, struct vfsmount *dest_mnt, -+ struct dentry *dest_dentry) -+{ -+ if (!IS_MNT_UNION(mnt)) -+ return 0; -+ -+ return append_to_union(mnt, mnt->mnt_root, dest_mnt, dest_dentry); -+} -+ -+void detach_mnt_union(struct vfsmount *mnt) -+{ -+ struct union_mount *um; -+ -+ if (!IS_MNT_UNION(mnt)) -+ return; -+ -+ shrink_mnt_unions(mnt); -+ -+ spin_lock(&union_lock); -+ um = union_lookup(mnt->mnt_root, mnt); -+ __union_unhash(um); -+ list_del(&um->u_list); -+ list_del(&um->u_unions); -+ um->u_next.dentry->d_unionized--; -+ spin_unlock(&union_lock); -+ union_put(um); -+ return; -+} -+ -+/** -+ * union_copyup_dir_one - copy up a single directory entry -+ * -+ * Individual directory entry copyup function for union_copyup_dir. -+ * We get the entries from higher level layers first. -+ */ -+ -+static int union_copyup_dir_one(void *buf, const char *name, int namlen, -+ loff_t offset, u64 ino, unsigned int d_type) -+{ -+ struct dentry *topmost_dentry = (struct dentry *) buf; -+ struct dentry *dentry; -+ int err = 0; -+ -+ switch (namlen) { -+ case 2: -+ if (name[1] != '.') -+ break; -+ case 1: -+ if (name[0] != '.') -+ break; -+ return 0; -+ } -+ -+ /* Lookup this entry in the topmost directory */ -+ dentry = lookup_one_len(name, topmost_dentry, namlen); -+ -+ if (IS_ERR(dentry)) { -+ printk(KERN_INFO "error looking up %s\n", dentry->d_name.name); -+ goto out; -+ } -+ -+ /* -+ * If the entry already exists, one of the following is true: -+ * it was already copied up (due to an earlier lookup), an -+ * entry with the same name already exists on the topmost file -+ * system, it is a whiteout, or it is a fallthru. In each -+ * case, the top level entry masks any entries from lower file -+ * systems, so don't copy up this entry. -+ */ -+ if (dentry->d_inode || d_is_whiteout(dentry) || -+ d_is_fallthru(dentry)) { -+ printk(KERN_INFO "skipping copy of %s\n", dentry->d_name.name); -+ goto out_dput; -+ } -+ -+ /* -+ * If the entry doesn't exist, create a fallthru entry in the -+ * topmost file system. All possible directory types are -+ * used, so each file system must implement its own way of -+ * storing a fallthru entry. -+ */ -+ printk(KERN_INFO "creating fallthru for %s\n", dentry->d_name.name); -+ err = topmost_dentry->d_inode->i_op->fallthru(topmost_dentry->d_inode, -+ dentry); -+ /* FIXME */ -+ BUG_ON(err); -+ /* -+ * At this point, we have a negative dentry marked as fallthru -+ * in the cache. We could potentially lookup the entry lower -+ * level file system and turn this into a positive dentry -+ * right now, but it is not clear that would be a performance -+ * win and adds more opportunities to fail. -+ */ -+out_dput: -+ dput(dentry); -+out: -+ return 0; -+} -+ -+/** -+ * union_copyup_dir - copy up low-level directory entries to topmost dir -+ * -+ * readdir() is difficult to support on union file systems for two -+ * reasons: We must eliminate duplicates and apply whiteouts, and we -+ * must return something in f_pos that lets us restart in the same -+ * place when we return. Our solution is to, on first readdir() of -+ * the directory, copy up all visible entries from the low-level file -+ * systems and mark the entries that refer to low-level file system -+ * objects as "fallthru" entries. -+ */ -+ -+int union_copyup_dir(struct path *topmost_path) -+{ -+ struct dentry *topmost_dentry = topmost_path->dentry; -+ struct path path = *topmost_path; -+ int res = 0; -+ -+ /* -+ * Skip opaque dirs. -+ */ -+ if (IS_OPAQUE(topmost_dentry->d_inode)) -+ return 0; -+ -+ /* -+ * Mark this dir opaque to show that we have already copied up -+ * the lower entries. Only fallthru entries pass through to -+ * the underlying file system. -+ * -+ * XXX Deal with the lower file system changing. This could -+ * be through running a tool over the top level file system to -+ * make directories transparent again, or we could check the -+ * mtime of the underlying directory. -+ */ -+ -+ topmost_dentry->d_inode->i_flags |= S_OPAQUE; -+ mark_inode_dirty(topmost_dentry->d_inode); -+ -+ /* -+ * Loop through each dir on each level copying up the entries -+ * to the topmost. -+ */ -+ -+ /* Don't drop the caller's reference to the topmost path */ -+ path_get(&path); -+ while (follow_union_down(&path)) { -+ struct file * ftmp; -+ struct inode * inode; -+ -+ /* XXX Permit fallthrus on lower-level? Would need to -+ * pass in opaque flag to union_copyup_dir_one() and -+ * only copy up fallthru entries there. We allow -+ * fallthrus in lower level opaque directories on -+ * lookup, so for consistency we should do one or the -+ * other in both places. */ -+ if (IS_OPAQUE(path.dentry->d_inode)) -+ break; -+ -+ /* dentry_open() doesn't get a path reference itself */ -+ path_get(&path); -+ ftmp = dentry_open(path.dentry, path.mnt, -+ O_RDONLY | O_DIRECTORY | O_NOATIME, -+ current_cred()); -+ if (IS_ERR(ftmp)) { -+ printk (KERN_ERR "unable to open dir %s for " -+ "directory copyup: %ld\n", -+ path.dentry->d_name.name, PTR_ERR(ftmp)); -+ continue; -+ } -+ -+ inode = path.dentry->d_inode; -+ mutex_lock(&inode->i_mutex); -+ -+ res = -ENOENT; -+ if (IS_DEADDIR(inode)) -+ goto out_fput; -+ /* -+ * Read the whole directory, calling our directory -+ * entry copyup function on each entry. Pass in the -+ * topmost dentry as our private data so we can create -+ * new entries in the topmost directory. -+ */ -+ res = ftmp->f_op->readdir(ftmp, topmost_dentry, -+ union_copyup_dir_one); -+out_fput: -+ mutex_unlock(&inode->i_mutex); -+ fput(ftmp); -+ -+ if (res) -+ break; -+ } -+ path_put(&path); -+ return res; -+} ---- a/include/linux/dcache.h -+++ b/include/linux/dcache.h -@@ -101,6 +101,15 @@ struct dentry { - struct dentry *d_parent; /* parent directory */ - struct qstr d_name; - -+#ifdef CONFIG_UNION_MOUNT -+ /* -+ * The following fields are used by the VFS based union mount -+ * implementation. Both are protected by union_lock! -+ */ -+ struct list_head d_unions; /* list of union_mount's */ -+ unsigned int d_unionized; /* unions referencing this dentry */ -+#endif -+ - struct list_head d_lru; /* LRU list */ - /* - * d_child and d_rcu can share memory -@@ -186,6 +195,9 @@ d_iput: no no no yes - - #define DCACHE_FSNOTIFY_PARENT_WATCHED 0x0080 /* Parent inode is watched by some fsnotify listener */ - -+#define DCACHE_WHITEOUT 0x0100 /* This negative dentry is a whiteout */ -+#define DCACHE_FALLTHRU 0x0200 /* Keep looking in the file system below */ -+ - extern spinlock_t dcache_lock; - extern seqlock_t rename_lock; - -@@ -205,12 +217,20 @@ extern seqlock_t rename_lock; - * __d_drop requires dentry->d_lock. - */ - -+#ifdef CONFIG_UNION_MOUNT -+extern void __d_drop_unions(struct dentry *); -+#endif -+ - static inline void __d_drop(struct dentry *dentry) - { - if (!(dentry->d_flags & DCACHE_UNHASHED)) { - dentry->d_flags |= DCACHE_UNHASHED; - hlist_del_rcu(&dentry->d_hash); - } -+#ifdef CONFIG_UNION_MOUNT -+ /* remove dentry from the union hashtable */ -+ __d_drop_unions(dentry); -+#endif - } - - static inline void d_drop(struct dentry *dentry) -@@ -358,6 +378,16 @@ static inline int d_unlinked(struct dent - return d_unhashed(dentry) && !IS_ROOT(dentry); - } - -+static inline int d_is_whiteout(struct dentry *dentry) -+{ -+ return (dentry->d_flags & DCACHE_WHITEOUT); -+} -+ -+static inline int d_is_fallthru(struct dentry *dentry) -+{ -+ return (dentry->d_flags & DCACHE_FALLTHRU); -+} -+ - static inline struct dentry *dget_parent(struct dentry *dentry) - { - struct dentry *ret; ---- a/include/linux/ext2_fs.h -+++ b/include/linux/ext2_fs.h -@@ -189,6 +189,7 @@ struct ext2_group_desc - #define EXT2_NOTAIL_FL FS_NOTAIL_FL /* file tail should not be merged */ - #define EXT2_DIRSYNC_FL FS_DIRSYNC_FL /* dirsync behaviour (directories only) */ - #define EXT2_TOPDIR_FL FS_TOPDIR_FL /* Top of directory hierarchies*/ -+#define EXT2_OPAQUE_FL 0x00040000 - #define EXT2_RESERVED_FL FS_RESERVED_FL /* reserved for ext2 lib */ - - #define EXT2_FL_USER_VISIBLE FS_FL_USER_VISIBLE /* User visible flags */ -@@ -503,10 +504,12 @@ struct ext2_super_block { - #define EXT3_FEATURE_INCOMPAT_RECOVER 0x0004 - #define EXT3_FEATURE_INCOMPAT_JOURNAL_DEV 0x0008 - #define EXT2_FEATURE_INCOMPAT_META_BG 0x0010 -+#define EXT2_FEATURE_INCOMPAT_WHITEOUT 0x0020 - #define EXT2_FEATURE_INCOMPAT_ANY 0xffffffff - - #define EXT2_FEATURE_COMPAT_SUPP EXT2_FEATURE_COMPAT_EXT_ATTR - #define EXT2_FEATURE_INCOMPAT_SUPP (EXT2_FEATURE_INCOMPAT_FILETYPE| \ -+ EXT2_FEATURE_INCOMPAT_WHITEOUT| \ - EXT2_FEATURE_INCOMPAT_META_BG) - #define EXT2_FEATURE_RO_COMPAT_SUPP (EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER| \ - EXT2_FEATURE_RO_COMPAT_LARGE_FILE| \ -@@ -573,6 +576,8 @@ enum { - EXT2_FT_FIFO, - EXT2_FT_SOCK, - EXT2_FT_SYMLINK, -+ EXT2_FT_WHT, -+ EXT2_FT_FALLTHRU, - EXT2_FT_MAX - }; - ---- a/include/linux/fs.h -+++ b/include/linux/fs.h -@@ -188,6 +188,7 @@ struct inodes_stat_t { - #define MS_REMOUNT 32 /* Alter flags of a mounted FS */ - #define MS_MANDLOCK 64 /* Allow mandatory locks on an FS */ - #define MS_DIRSYNC 128 /* Directory modifications are synchronous */ -+#define MS_UNION 256 - #define MS_NOATIME 1024 /* Do not update access times. */ - #define MS_NODIRATIME 2048 /* Do not update directory access times */ - #define MS_BIND 4096 -@@ -205,6 +206,7 @@ struct inodes_stat_t { - #define MS_KERNMOUNT (1<<22) /* this is a kern_mount call */ - #define MS_I_VERSION (1<<23) /* Update inode I_version field */ - #define MS_STRICTATIME (1<<24) /* Always perform atime updates */ -+#define MS_WHITEOUT (1<<26) /* fs does support white-out filetype */ - #define MS_ACTIVE (1<<30) - #define MS_NOUSER (1<<31) - -@@ -231,6 +233,7 @@ struct inodes_stat_t { - #define S_NOCMTIME 128 /* Do not update file c/mtime */ - #define S_SWAPFILE 256 /* Do not truncate: swapon got its bmaps */ - #define S_PRIVATE 512 /* Inode is fs-internal */ -+#define S_OPAQUE 1024 /* Directory is opaque */ - - /* - * Note that nosuid etc flags are inode-specific: setting some file-system -@@ -266,6 +269,8 @@ struct inodes_stat_t { - #define IS_SWAPFILE(inode) ((inode)->i_flags & S_SWAPFILE) - #define IS_PRIVATE(inode) ((inode)->i_flags & S_PRIVATE) - -+#define IS_OPAQUE(inode) ((inode)->i_flags & S_OPAQUE) -+ - /* the read-only stuff doesn't really belong here, but any other place is - probably as bad and I don't want to create yet another include file. */ - -@@ -1380,6 +1385,11 @@ struct super_block { - * generic_show_options() - */ - char *s_options; -+ -+ /* -+ * Users who require read-only access - e.g., union mounts -+ */ -+ int s_readonly_users; - }; - - extern struct timespec current_fs_time(struct super_block *sb); -@@ -1517,6 +1527,8 @@ struct inode_operations { - int (*mkdir) (struct inode *,struct dentry *,int); - int (*rmdir) (struct inode *,struct dentry *); - int (*mknod) (struct inode *,struct dentry *,int,dev_t); -+ int (*whiteout) (struct inode *, struct dentry *, struct dentry *); -+ int (*fallthru) (struct inode *, struct dentry *); - int (*rename) (struct inode *, struct dentry *, - struct inode *, struct dentry *); - int (*readlink) (struct dentry *, char __user *,int); -@@ -2108,6 +2120,7 @@ extern void emergency_remount(void); - extern sector_t bmap(struct inode *, sector_t); - #endif - extern int notify_change(struct dentry *, struct iattr *); -+extern int __inode_permission(struct inode *inode, int mask, int rofs); - extern int inode_permission(struct inode *, int); - extern int generic_permission(struct inode *, int, - int (*check_acl)(struct inode *, int)); -@@ -2135,7 +2148,7 @@ extern void free_write_pipe(struct file - - extern struct file *do_filp_open(int dfd, const char *pathname, - int open_flag, int mode, int acc_mode); --extern int may_open(struct path *, int, int); -+extern int may_open(struct nameidata *, int, int); - - extern int kernel_read(struct file *, loff_t, char *, unsigned long); - extern struct file * open_exec(const char *); ---- a/include/linux/mount.h -+++ b/include/linux/mount.h -@@ -35,6 +35,7 @@ struct mnt_namespace; - #define MNT_SHARED 0x1000 /* if the vfsmount is a shared mount */ - #define MNT_UNBINDABLE 0x2000 /* if the vfsmount is a unbindable mount */ - #define MNT_PNODE_MASK 0x3000 /* propagation flag mask */ -+#define MNT_UNION 0x4000 /* if the vfsmount is a union mount */ - - struct vfsmount { - struct list_head mnt_hash; -@@ -53,6 +54,9 @@ struct vfsmount { - struct list_head mnt_slave_list;/* list of slave mounts */ - struct list_head mnt_slave; /* slave list entry */ - struct vfsmount *mnt_master; /* slave is on master->mnt_slave_list */ -+#ifdef CONFIG_UNION_MOUNT -+ struct list_head mnt_unions; /* list of union_mount structures */ -+#endif - struct mnt_namespace *mnt_ns; /* containing namespace */ - int mnt_id; /* mount identifier */ - int mnt_group_id; /* peer group identifier */ ---- a/include/linux/namei.h -+++ b/include/linux/namei.h -@@ -20,6 +20,7 @@ struct nameidata { - struct qstr last; - struct path root; - unsigned int flags; -+ unsigned int um_flags; - int last_type; - unsigned depth; - char *saved_names[MAX_NESTED_LINKS + 1]; -@@ -35,6 +36,9 @@ struct nameidata { - */ - enum {LAST_NORM, LAST_ROOT, LAST_DOT, LAST_DOTDOT, LAST_BIND}; - -+#define LAST_UNION 0x01 -+#define LAST_LOWLEVEL 0x02 -+ - /* - * The bitmask for a lookup event: - * - follow links at the end -@@ -49,6 +53,8 @@ enum {LAST_NORM, LAST_ROOT, LAST_DOT, LA - #define LOOKUP_CONTINUE 4 - #define LOOKUP_PARENT 16 - #define LOOKUP_REVAL 64 -+#define LOOKUP_TOPMOST 128 -+ - /* - * Intent data - */ ---- /dev/null -+++ b/include/linux/union.h -@@ -0,0 +1,84 @@ -+/* -+ * VFS based union mount for Linux -+ * -+ * Copyright (C) 2004-2007 IBM Corporation, IBM Deutschland Entwicklung GmbH. -+ * Copyright (C) 2007 Novell Inc. -+ * Author(s): Jan Blunck (j.blunck@tu-harburg.de) -+ * -+ * 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. -+ * -+ */ -+#ifndef __LINUX_UNION_H -+#define __LINUX_UNION_H -+#ifdef __KERNEL__ -+ -+#include -+#include -+ -+struct dentry; -+struct vfsmount; -+ -+#ifdef CONFIG_UNION_MOUNT -+ -+/* -+ * The new union mount structure. -+ */ -+struct union_mount { -+ atomic_t u_count; /* reference count */ -+ struct mutex u_mutex; -+ struct list_head u_unions; /* list head for d_unions */ -+ struct list_head u_list; /* list head for mnt_unions */ -+ struct hlist_node u_hash; /* list head for seaching */ -+ struct hlist_node u_rhash; /* list head for reverse seaching */ -+ -+ struct path u_this; /* this is me */ -+ struct path u_next; /* this is what I overlay */ -+}; -+ -+#define IS_UNION(dentry) (!list_empty(&(dentry)->d_unions) || \ -+ (dentry)->d_unionized) -+#define IS_MNT_UNION(mnt) ((mnt)->mnt_flags & MNT_UNION) -+ -+extern int is_unionized(struct dentry *, struct vfsmount *); -+extern int append_to_union(struct vfsmount *, struct dentry *, -+ struct vfsmount *, struct dentry *); -+extern int follow_union_down(struct path *); -+extern int follow_union_mount(struct path *); -+extern void __d_drop_unions(struct dentry *); -+extern void shrink_d_unions(struct dentry *); -+extern void __shrink_d_unions(struct dentry *, struct list_head *); -+extern int attach_mnt_union(struct vfsmount *, struct vfsmount *, -+ struct dentry *); -+extern void detach_mnt_union(struct vfsmount *); -+extern struct dentry *union_create_topmost(struct nameidata *, struct qstr *, -+ struct path *); -+extern int __union_copyup(struct path *, struct nameidata *, struct path *); -+extern int union_copyup(struct nameidata *, int); -+extern int union_copyup_dir(struct path *path); -+extern int union_permission(struct path *, int); -+ -+#else /* CONFIG_UNION_MOUNT */ -+ -+#define IS_UNION(x) (0) -+#define IS_MNT_UNION(x) (0) -+#define is_unionized(x, y) (0) -+#define append_to_union(x1, y1, x2, y2) ({ BUG(); (0); }) -+#define follow_union_down(x) ({ (0); }) -+#define follow_union_mount(x) ({ (0); }) -+#define __d_drop_unions(x) do { } while (0) -+#define shrink_d_unions(x) do { } while (0) -+#define __shrink_d_unions(x,y) do { } while (0) -+#define attach_mnt_union(x, y, z) do { } while (0) -+#define detach_mnt_union(x) do { } while (0) -+#define union_create_topmost(x, y, z) ({ BUG(); (NULL); }) -+#define __union_copyup(x, y, z) ({ BUG(); (0); }) -+#define union_copyup(x, y) ({ (0); }) -+#define union_copyup_dir(x) ({ BUG(); (0); }) -+#define union_permission(x, y) inode_permission(x->dentry->d_inode, y) -+ -+#endif /* CONFIG_UNION_MOUNT */ -+#endif /* __KERNEL__ */ -+#endif /* __LINUX_UNION_H */ ---- a/mm/shmem.c -+++ b/mm/shmem.c -@@ -1798,6 +1798,118 @@ static int shmem_statfs(struct dentry *d - return 0; - } - -+static int shmem_rmdir(struct inode *dir, struct dentry *dentry); -+static int shmem_unlink(struct inode *dir, struct dentry *dentry); -+ -+/* -+ * Create a dentry to signify a whiteout. -+ */ -+static int shmem_whiteout(struct inode *dir, struct dentry *old_dentry, -+ struct dentry *new_dentry) -+{ -+ struct shmem_sb_info *sbinfo = SHMEM_SB(dir->i_sb); -+ struct dentry *dentry; -+ -+ if (!(dir->i_sb->s_flags & MS_WHITEOUT)) -+ return -EPERM; -+ -+ /* This gives us a proper initialized negative dentry */ -+ dentry = simple_lookup(dir, new_dentry, NULL); -+ if (dentry && IS_ERR(dentry)) -+ return PTR_ERR(dentry); -+ -+ /* -+ * No ordinary (disk based) filesystem counts whiteouts as inodes; -+ * but each new link needs a new dentry, pinning lowmem, and -+ * tmpfs dentries cannot be pruned until they are unlinked. -+ */ -+ if (sbinfo->max_inodes) { -+ spin_lock(&sbinfo->stat_lock); -+ if (!sbinfo->free_inodes) { -+ spin_unlock(&sbinfo->stat_lock); -+ return -ENOSPC; -+ } -+ sbinfo->free_inodes--; -+ spin_unlock(&sbinfo->stat_lock); -+ } -+ -+ if (old_dentry->d_inode || d_is_fallthru(old_dentry)) { -+ if (old_dentry->d_inode && S_ISDIR(old_dentry->d_inode->i_mode)) -+ shmem_rmdir(dir, old_dentry); -+ else -+ shmem_unlink(dir, old_dentry); -+ } -+ -+ dir->i_size += BOGO_DIRENT_SIZE; -+ dir->i_ctime = dir->i_mtime = CURRENT_TIME; -+ /* Extra pinning count for the created dentry */ -+ dget(new_dentry); -+ spin_lock(&new_dentry->d_lock); -+ new_dentry->d_flags |= DCACHE_WHITEOUT; -+ spin_unlock(&new_dentry->d_lock); -+ return 0; -+} -+ -+static void shmem_d_instantiate(struct inode *dir, struct dentry *dentry, -+ struct inode *inode); -+ -+/* -+ * Create a dentry to signify a fallthru. A fallthru lets us read the -+ * low-level dentries into the dcache once on the first readdir() and -+ * then -+ */ -+static int shmem_fallthru(struct inode *dir, struct dentry *dentry) -+{ -+ struct shmem_sb_info *sbinfo = SHMEM_SB(dir->i_sb); -+ -+ /* FIXME: this is stupid */ -+ if (!(dir->i_sb->s_flags & MS_WHITEOUT)) -+ return -EPERM; -+ -+ if (dentry->d_inode || d_is_fallthru(dentry) || d_is_whiteout(dentry)) -+ return -EEXIST; -+ -+ /* -+ * Each new link needs a new dentry, pinning lowmem, and tmpfs -+ * dentries cannot be pruned until they are unlinked. -+ */ -+ if (sbinfo->max_inodes) { -+ spin_lock(&sbinfo->stat_lock); -+ if (!sbinfo->free_inodes) { -+ spin_unlock(&sbinfo->stat_lock); -+ return -ENOSPC; -+ } -+ sbinfo->free_inodes--; -+ spin_unlock(&sbinfo->stat_lock); -+ } -+ -+ shmem_d_instantiate(dir, dentry, NULL); -+ dir->i_ctime = dir->i_mtime = CURRENT_TIME; -+ -+ spin_lock(&dentry->d_lock); -+ dentry->d_flags |= DCACHE_FALLTHRU; -+ spin_unlock(&dentry->d_lock); -+ return 0; -+} -+ -+static void shmem_d_instantiate(struct inode *dir, struct dentry *dentry, -+ struct inode *inode) -+{ -+ if (d_is_whiteout(dentry)) { -+ /* Re-using an existing whiteout */ -+ shmem_free_inode(dir->i_sb); -+ if (S_ISDIR(inode->i_mode)) -+ inode->i_mode |= S_OPAQUE; -+ } else if (d_is_fallthru(dentry)) { -+ shmem_free_inode(dir->i_sb); -+ } else { -+ /* New dentry */ -+ dir->i_size += BOGO_DIRENT_SIZE; -+ dget(dentry); /* Extra count - pin the dentry in core */ -+ } -+ /* Will clear DCACHE_WHITEOUT and DCACHE_FALLTHRU flags */ -+ d_instantiate(dentry, inode); -+} - /* - * File creation. Allocate an inode, and we're done.. - */ -@@ -1822,15 +1934,16 @@ shmem_mknod(struct inode *dir, struct de - iput(inode); - return error; - } -+ - if (dir->i_mode & S_ISGID) { - inode->i_gid = dir->i_gid; - if (S_ISDIR(mode)) - inode->i_mode |= S_ISGID; - } -- dir->i_size += BOGO_DIRENT_SIZE; -+ -+ shmem_d_instantiate(dir, dentry, inode); -+ - dir->i_ctime = dir->i_mtime = CURRENT_TIME; -- d_instantiate(dentry, inode); -- dget(dentry); /* Extra count - pin the dentry in core */ - } - return error; - } -@@ -1868,12 +1981,11 @@ static int shmem_link(struct dentry *old - if (ret) - goto out; - -- dir->i_size += BOGO_DIRENT_SIZE; -+ shmem_d_instantiate(dir, dentry, inode); -+ - inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME; - inc_nlink(inode); - atomic_inc(&inode->i_count); /* New dentry reference */ -- dget(dentry); /* Extra pinning count for the created dentry */ -- d_instantiate(dentry, inode); - out: - return ret; - } -@@ -1882,21 +1994,63 @@ static int shmem_unlink(struct inode *di - { - struct inode *inode = dentry->d_inode; - -- if (inode->i_nlink > 1 && !S_ISDIR(inode->i_mode)) -- shmem_free_inode(inode->i_sb); -+ if (d_is_whiteout(dentry) || d_is_fallthru(dentry) || -+ (inode->i_nlink > 1 && !S_ISDIR(inode->i_mode))) -+ shmem_free_inode(dir->i_sb); - -+ if (inode) { -+ inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME; -+ drop_nlink(inode); -+ } - dir->i_size -= BOGO_DIRENT_SIZE; -- inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME; -- drop_nlink(inode); - dput(dentry); /* Undo the count from "create" - this does all the work */ - return 0; - } - -+static void shmem_dir_unlink_whiteouts(struct inode *dir, struct dentry *dentry) -+{ -+ if (!dentry->d_inode) -+ return; -+ -+ /* Remove whiteouts from logical empty directory */ -+ if (S_ISDIR(dentry->d_inode->i_mode) && -+ dentry->d_inode->i_sb->s_flags & MS_WHITEOUT) { -+ struct dentry *child, *next; -+ LIST_HEAD(list); -+ -+ spin_lock(&dcache_lock); -+ list_for_each_entry(child, &dentry->d_subdirs, d_u.d_child) { -+ spin_lock(&child->d_lock); -+ /* Unlink fallthrus too */ -+ if (d_is_whiteout(child) || d_is_fallthru(child)) { -+ __d_drop(child); -+ if (!list_empty(&child->d_lru)) { -+ list_del(&child->d_lru); -+ dentry_stat.nr_unused--; -+ } -+ list_add(&child->d_lru, &list); -+ } -+ spin_unlock(&child->d_lock); -+ } -+ spin_unlock(&dcache_lock); -+ -+ list_for_each_entry_safe(child, next, &list, d_lru) { -+ spin_lock(&child->d_lock); -+ list_del_init(&child->d_lru); -+ spin_unlock(&child->d_lock); -+ -+ shmem_unlink(dentry->d_inode, child); -+ } -+ } -+} -+ - static int shmem_rmdir(struct inode *dir, struct dentry *dentry) - { - if (!simple_empty(dentry)) - return -ENOTEMPTY; - -+ /* Remove whiteouts from logical empty directory */ -+ shmem_dir_unlink_whiteouts(dir, dentry); - drop_nlink(dentry->d_inode); - drop_nlink(dir); - return shmem_unlink(dir, dentry); -@@ -1905,7 +2059,7 @@ static int shmem_rmdir(struct inode *dir - /* - * The VFS layer already does all the dentry stuff for rename, - * we just have to decrement the usage count for the target if -- * it exists so that the VFS layer correctly free's it when it -+ * it exists so that the VFS layer correctly frees it when it - * gets overwritten. - */ - static int shmem_rename(struct inode *old_dir, struct dentry *old_dentry, struct inode *new_dir, struct dentry *new_dentry) -@@ -1916,7 +2070,12 @@ static int shmem_rename(struct inode *ol - if (!simple_empty(new_dentry)) - return -ENOTEMPTY; - -+ if (d_is_whiteout(new_dentry)) -+ shmem_unlink(new_dir, new_dentry); -+ - if (new_dentry->d_inode) { -+ /* Remove whiteouts from logical empty directory */ -+ shmem_dir_unlink_whiteouts(new_dir, new_dentry); - (void) shmem_unlink(new_dir, new_dentry); - if (they_are_dirs) - drop_nlink(old_dir); -@@ -1981,12 +2140,12 @@ static int shmem_symlink(struct inode *d - unlock_page(page); - page_cache_release(page); - } -+ -+ shmem_d_instantiate(dir, dentry, inode); -+ - if (dir->i_mode & S_ISGID) - inode->i_gid = dir->i_gid; -- dir->i_size += BOGO_DIRENT_SIZE; - dir->i_ctime = dir->i_mtime = CURRENT_TIME; -- d_instantiate(dentry, inode); -- dget(dentry); - return 0; - } - -@@ -2363,6 +2522,12 @@ int shmem_fill_super(struct super_block - if (!root) - goto failed_iput; - sb->s_root = root; -+ -+#ifdef CONFIG_TMPFS -+ if (!(sb->s_flags & MS_NOUSER)) -+ sb->s_flags |= MS_WHITEOUT; -+#endif -+ - return 0; - - failed_iput: -@@ -2463,6 +2628,8 @@ static const struct inode_operations shm - .rmdir = shmem_rmdir, - .mknod = shmem_mknod, - .rename = shmem_rename, -+ .whiteout = shmem_whiteout, -+ .fallthru = shmem_fallthru, - #endif - #ifdef CONFIG_TMPFS_POSIX_ACL - .setattr = shmem_notify_change, diff --git a/target/linux/generic-2.6/patches-2.6.32/231-union_mounts_bind_fix.patch b/target/linux/generic-2.6/patches-2.6.32/231-union_mounts_bind_fix.patch deleted file mode 100644 index 4bd3f7351..000000000 --- a/target/linux/generic-2.6/patches-2.6.32/231-union_mounts_bind_fix.patch +++ /dev/null @@ -1,11 +0,0 @@ ---- a/fs/namespace.c -+++ b/fs/namespace.c -@@ -1550,7 +1550,7 @@ static int do_loopback(struct path *path - if (!mnt) - goto out; - -- err = check_union_mnt(&old_path, mnt, mnt_flags); -+ err = check_union_mnt(path, mnt, mnt_flags); - if (err) - goto out; - diff --git a/target/linux/generic-2.6/patches-2.6.32/232-union_mounts_compile_fix.patch b/target/linux/generic-2.6/patches-2.6.32/232-union_mounts_compile_fix.patch deleted file mode 100644 index b20b845aa..000000000 --- a/target/linux/generic-2.6/patches-2.6.32/232-union_mounts_compile_fix.patch +++ /dev/null @@ -1,11 +0,0 @@ ---- a/include/linux/union.h -+++ b/include/linux/union.h -@@ -77,7 +77,7 @@ extern int union_permission(struct path - #define __union_copyup(x, y, z) ({ BUG(); (0); }) - #define union_copyup(x, y) ({ (0); }) - #define union_copyup_dir(x) ({ BUG(); (0); }) --#define union_permission(x, y) inode_permission(x->dentry->d_inode, y) -+#define union_permission(x, y) inode_permission((x)->dentry->d_inode, y) - - #endif /* CONFIG_UNION_MOUNT */ - #endif /* __KERNEL__ */ diff --git a/target/linux/generic-2.6/patches-2.6.32/233-jffs2_whiteout_support.patch b/target/linux/generic-2.6/patches-2.6.32/233-jffs2_whiteout_support.patch deleted file mode 100644 index 6583ac3d9..000000000 --- a/target/linux/generic-2.6/patches-2.6.32/233-jffs2_whiteout_support.patch +++ /dev/null @@ -1,186 +0,0 @@ ---- a/fs/jffs2/dir.c -+++ b/fs/jffs2/dir.c -@@ -34,6 +34,9 @@ static int jffs2_mknod (struct inode *,s - static int jffs2_rename (struct inode *, struct dentry *, - struct inode *, struct dentry *); - -+static int jffs2_whiteout (struct inode *, struct dentry *, struct dentry *); -+static int jffs2_fallthru (struct inode *, struct dentry *); -+ - const struct file_operations jffs2_dir_operations = - { - .read = generic_read_dir, -@@ -55,6 +58,8 @@ const struct inode_operations jffs2_dir_ - .rmdir = jffs2_rmdir, - .mknod = jffs2_mknod, - .rename = jffs2_rename, -+ .fallthru = jffs2_fallthru, -+ .whiteout = jffs2_whiteout, - .check_acl = jffs2_check_acl, - .setattr = jffs2_setattr, - .setxattr = jffs2_setxattr, -@@ -98,8 +103,21 @@ static struct dentry *jffs2_lookup(struc - fd = fd_list; - } - } -- if (fd) -- ino = fd->ino; -+ if (fd) { -+ spin_lock(&target->d_lock); -+ switch(fd->type) { -+ case DT_WHT: -+ target->d_flags |= DCACHE_WHITEOUT; -+ break; -+ case DT_UNKNOWN: -+ target->d_flags |= DCACHE_FALLTHRU; -+ break; -+ default: -+ ino = fd->ino; -+ break; -+ } -+ spin_unlock(&target->d_lock); -+ } - mutex_unlock(&dir_f->sem); - if (ino) { - inode = jffs2_iget(dir_i->i_sb, ino); -@@ -155,7 +173,9 @@ static int jffs2_readdir(struct file *fi - fd->name, fd->ino, fd->type, curofs, offset)); - continue; - } -- if (!fd->ino) { -+ if (fd->type == DT_UNKNOWN) -+ fd->ino = 100; /* XXX: arbitrary */ -+ else if (!fd->ino && (fd->type != DT_WHT)) { - D2(printk(KERN_DEBUG "Skipping deletion dirent \"%s\"\n", fd->name)); - offset++; - continue; -@@ -498,6 +518,11 @@ static int jffs2_mkdir (struct inode *di - return PTR_ERR(inode); - } - -+ if (dentry->d_flags & DCACHE_WHITEOUT) { -+ inode->i_flags |= S_OPAQUE; -+ ri->flags = cpu_to_je16(JFFS2_INO_FLAG_OPAQUE); -+ } -+ - inode->i_op = &jffs2_dir_inode_operations; - inode->i_fop = &jffs2_dir_operations; - -@@ -779,6 +804,82 @@ static int jffs2_mknod (struct inode *di - return 0; - } - -+static int jffs2_fallthru (struct inode *dir, struct dentry *dentry) -+{ -+ struct jffs2_sb_info *c = JFFS2_SB_INFO(dir->i_sb); -+ uint32_t now; -+ int ret; -+ -+ now = get_seconds(); -+ ret = jffs2_do_link(c, JFFS2_INODE_INFO(dir), 0, DT_UNKNOWN, -+ dentry->d_name.name, dentry->d_name.len, now); -+ if (ret) -+ return ret; -+ -+ d_instantiate(dentry, NULL); -+ spin_lock(&dentry->d_lock); -+ dentry->d_flags |= DCACHE_FALLTHRU; -+ spin_unlock(&dentry->d_lock); -+ -+ return 0; -+} -+ -+static int jffs2_whiteout (struct inode *dir, struct dentry *old_dentry, -+ struct dentry *new_dentry) -+{ -+ struct jffs2_sb_info *c = JFFS2_SB_INFO(dir->i_sb); -+ struct jffs2_inode_info *victim_f = NULL; -+ uint32_t now; -+ int ret; -+ -+ /* If it's a directory, then check whether it is really empty -+ */ -+ if (new_dentry->d_inode) { -+ victim_f = JFFS2_INODE_INFO(old_dentry->d_inode); -+ if (S_ISDIR(old_dentry->d_inode->i_mode)) { -+ struct jffs2_full_dirent *fd; -+ -+ mutex_lock(&victim_f->sem); -+ for (fd = victim_f->dents; fd; fd = fd->next) { -+ if (fd->ino) { -+ mutex_unlock(&victim_f->sem); -+ return -ENOTEMPTY; -+ } -+ } -+ mutex_unlock(&victim_f->sem); -+ } -+ } -+ -+ now = get_seconds(); -+ ret = jffs2_do_link(c, JFFS2_INODE_INFO(dir), 0, DT_WHT, -+ new_dentry->d_name.name, new_dentry->d_name.len, now); -+ if (ret) -+ return ret; -+ -+ spin_lock(&new_dentry->d_lock); -+ new_dentry->d_flags &= ~DCACHE_FALLTHRU; -+ new_dentry->d_flags |= DCACHE_WHITEOUT; -+ spin_unlock(&new_dentry->d_lock); -+ d_add(new_dentry, NULL); -+ -+ if (victim_f) { -+ /* There was a victim. Kill it off nicely */ -+ drop_nlink(old_dentry->d_inode); -+ /* Don't oops if the victim was a dirent pointing to an -+ inode which didn't exist. */ -+ if (victim_f->inocache) { -+ mutex_lock(&victim_f->sem); -+ if (S_ISDIR(old_dentry->d_inode->i_mode)) -+ victim_f->inocache->pino_nlink = 0; -+ else -+ victim_f->inocache->pino_nlink--; -+ mutex_unlock(&victim_f->sem); -+ } -+ } -+ -+ return 0; -+} -+ - static int jffs2_rename (struct inode *old_dir_i, struct dentry *old_dentry, - struct inode *new_dir_i, struct dentry *new_dentry) - { ---- a/fs/jffs2/fs.c -+++ b/fs/jffs2/fs.c -@@ -301,6 +301,10 @@ struct inode *jffs2_iget(struct super_bl - - inode->i_op = &jffs2_dir_inode_operations; - inode->i_fop = &jffs2_dir_operations; -+ -+ if (je16_to_cpu(latest_node.flags) & JFFS2_INO_FLAG_OPAQUE) -+ inode->i_flags |= S_OPAQUE; -+ - break; - } - case S_IFREG: ---- a/fs/jffs2/super.c -+++ b/fs/jffs2/super.c -@@ -172,7 +172,7 @@ static int jffs2_fill_super(struct super - - sb->s_op = &jffs2_super_operations; - sb->s_export_op = &jffs2_export_ops; -- sb->s_flags = sb->s_flags | MS_NOATIME; -+ sb->s_flags = sb->s_flags | MS_NOATIME | MS_WHITEOUT; - sb->s_xattr = jffs2_xattr_handlers; - #ifdef CONFIG_JFFS2_FS_POSIX_ACL - sb->s_flags |= MS_POSIXACL; ---- a/include/linux/jffs2.h -+++ b/include/linux/jffs2.h -@@ -87,6 +87,8 @@ - #define JFFS2_INO_FLAG_USERCOMPR 2 /* User has requested a specific - compression type */ - -+#define JFFS2_INO_FLAG_OPAQUE 4 /* Directory is opaque (for union mounts) */ -+ - - /* These can go once we've made sure we've caught all uses without - byteswapping */ diff --git a/target/linux/generic-2.6/patches-2.6.32/234-union_mounts_no_debug.patch b/target/linux/generic-2.6/patches-2.6.32/234-union_mounts_no_debug.patch deleted file mode 100644 index deabd4304..000000000 --- a/target/linux/generic-2.6/patches-2.6.32/234-union_mounts_no_debug.patch +++ /dev/null @@ -1,30 +0,0 @@ ---- a/fs/union.c -+++ b/fs/union.c -@@ -842,10 +842,8 @@ static int union_copyup_dir_one(void *bu - /* Lookup this entry in the topmost directory */ - dentry = lookup_one_len(name, topmost_dentry, namlen); - -- if (IS_ERR(dentry)) { -- printk(KERN_INFO "error looking up %s\n", dentry->d_name.name); -+ if (IS_ERR(dentry)) - goto out; -- } - - /* - * If the entry already exists, one of the following is true: -@@ -857,7 +855,6 @@ static int union_copyup_dir_one(void *bu - */ - if (dentry->d_inode || d_is_whiteout(dentry) || - d_is_fallthru(dentry)) { -- printk(KERN_INFO "skipping copy of %s\n", dentry->d_name.name); - goto out_dput; - } - -@@ -867,7 +864,6 @@ static int union_copyup_dir_one(void *bu - * used, so each file system must implement its own way of - * storing a fallthru entry. - */ -- printk(KERN_INFO "creating fallthru for %s\n", dentry->d_name.name); - err = topmost_dentry->d_inode->i_op->fallthru(topmost_dentry->d_inode, - dentry); - /* FIXME */ diff --git a/target/linux/generic-2.6/patches-2.6.32/235-union_mount_fixes.patch b/target/linux/generic-2.6/patches-2.6.32/235-union_mount_fixes.patch deleted file mode 100644 index ff1fba01b..000000000 --- a/target/linux/generic-2.6/patches-2.6.32/235-union_mount_fixes.patch +++ /dev/null @@ -1,117 +0,0 @@ ---- a/fs/namespace.c -+++ b/fs/namespace.c -@@ -1656,8 +1656,10 @@ static int do_move_mount(struct path *pa - - /* moving to or from a union mount is not supported */ - err = -EINVAL; -+#if 0 - if (IS_MNT_UNION(path->mnt)) - goto exit; -+#endif - if (IS_MNT_UNION(old_path.mnt)) - goto exit; - ---- a/fs/union.c -+++ b/fs/union.c -@@ -260,8 +260,6 @@ int append_to_union(struct vfsmount *mnt - spin_lock(&union_lock); - um = union_lookup(dentry, mnt); - if (um) { -- BUG_ON((um->u_next.dentry != dest_dentry) || -- (um->u_next.mnt != dest_mnt)); - spin_unlock(&union_lock); - union_put(this); - return 0; -@@ -274,6 +272,23 @@ int append_to_union(struct vfsmount *mnt - return 0; - } - -+int follow_union_mountpoint(struct path *path) -+{ -+ struct path new_path = *path; -+ -+ path_get(&new_path); -+ while (follow_union_down(&new_path)) { -+ if (new_path.dentry != new_path.mnt->mnt_root) -+ continue; -+ -+ path_put(path); -+ *path = new_path; -+ return 1; -+ } -+ path_put(&new_path); -+ return 0; -+} -+ - /* - * follow_union_down - follow the union stack one layer down - * ---- a/include/linux/union.h -+++ b/include/linux/union.h -@@ -47,6 +47,7 @@ extern int append_to_union(struct vfsmou - struct vfsmount *, struct dentry *); - extern int follow_union_down(struct path *); - extern int follow_union_mount(struct path *); -+extern int follow_union_mountpoint(struct path *path); - extern void __d_drop_unions(struct dentry *); - extern void shrink_d_unions(struct dentry *); - extern void __shrink_d_unions(struct dentry *, struct list_head *); -@@ -68,6 +69,7 @@ extern int union_permission(struct path - #define append_to_union(x1, y1, x2, y2) ({ BUG(); (0); }) - #define follow_union_down(x) ({ (0); }) - #define follow_union_mount(x) ({ (0); }) -+#define follow_union_mountpoint(x) ({ (0); }) - #define __d_drop_unions(x) do { } while (0) - #define shrink_d_unions(x) do { } while (0) - #define __shrink_d_unions(x,y) do { } while (0) ---- a/fs/namei.c -+++ b/fs/namei.c -@@ -626,6 +626,9 @@ static int cache_lookup_union(struct nam - !S_ISDIR(path->dentry->d_inode->i_mode)) - goto out; - -+ if (follow_union_mountpoint(path)) -+ goto out; -+ - /* Build the union stack for this part */ - res = __cache_lookup_build_union(nd, name, path); - if (res) { -@@ -892,6 +895,9 @@ static int real_lookup_union(struct name - !S_ISDIR(path->dentry->d_inode->i_mode)) - goto out; - -+ if (follow_union_mountpoint(path)) -+ goto out; -+ - /* Build the union stack for this part */ - res = __real_lookup_build_union(nd, name, path); - if (res) { -@@ -1813,6 +1819,9 @@ int hash_lookup_union(struct nameidata * - !S_ISDIR(path->dentry->d_inode->i_mode)) - goto out; - -+ if (follow_union_mountpoint(path)) -+ goto out; -+ - /* Build the union stack for this part */ - res = __hash_lookup_build_union(nd, name, path); - if (res) { ---- a/fs/readdir.c -+++ b/fs/readdir.c -@@ -17,6 +17,7 @@ - #include - #include - #include -+#include - - #include - -@@ -45,7 +46,7 @@ int vfs_readdir(struct file *file, filld - * below this one in the union stack. - */ - if (is_unionized(file->f_path.dentry, file->f_path.mnt) && -- !IS_OPAQUE(inode)) { -+ !IS_OPAQUE(inode) && IS_MNT_UNION(file->f_path.mnt)) { - res = union_copyup_dir(&file->f_path); - if (res) - goto out_unlock; diff --git a/target/linux/generic-2.6/patches-2.6.32/510-yaffs_support.patch b/target/linux/generic-2.6/patches-2.6.32/510-yaffs_support.patch index fe549c30c..e490452e5 100644 --- a/target/linux/generic-2.6/patches-2.6.32/510-yaffs_support.patch +++ b/target/linux/generic-2.6/patches-2.6.32/510-yaffs_support.patch @@ -10,7 +10,7 @@ --- a/fs/Makefile +++ b/fs/Makefile -@@ -126,3 +126,4 @@ obj-$(CONFIG_OCFS2_FS) += ocfs2/ +@@ -125,3 +125,4 @@ obj-$(CONFIG_OCFS2_FS) += ocfs2/ obj-$(CONFIG_BTRFS_FS) += btrfs/ obj-$(CONFIG_GFS2_FS) += gfs2/ obj-$(CONFIG_EXOFS_FS) += exofs/ diff --git a/target/linux/generic-2.6/patches-2.6.32/651-swconfig-2.6.32-fix.patch b/target/linux/generic-2.6/patches-2.6.32/651-swconfig-2.6.32-fix.patch new file mode 100644 index 000000000..bc8f8fcff --- /dev/null +++ b/target/linux/generic-2.6/patches-2.6.32/651-swconfig-2.6.32-fix.patch @@ -0,0 +1,29 @@ +--- a/drivers/net/phy/swconfig.c ++++ b/drivers/net/phy/swconfig.c +@@ -335,7 +335,7 @@ swconfig_send_multipart(struct swconfig_ + if (cb->close(cb, arg) < 0) + goto error; + } +- err = genlmsg_unicast(cb->msg, info->snd_pid); ++ err = genlmsg_reply(cb->msg, info); + cb->msg = NULL; + if (err < 0) + goto error; +@@ -419,7 +419,7 @@ swconfig_list_attrs(struct sk_buff *skb, + if (!cb.msg) + return 0; + +- return genlmsg_unicast(cb.msg, info->snd_pid); ++ return genlmsg_reply(cb.msg, info); + + error: + if (cb.msg) +@@ -728,7 +728,7 @@ swconfig_get_attr(struct sk_buff *skb, s + goto nla_put_failure; + + swconfig_put_dev(dev); +- return genlmsg_unicast(msg, info->snd_pid); ++ return genlmsg_reply(msg, info); + + nla_put_failure: + if (msg) diff --git a/target/linux/generic-2.6/patches-2.6.32/840-unable_to_open_console.patch b/target/linux/generic-2.6/patches-2.6.32/840-unable_to_open_console.patch index 15b546112..c9a277468 100644 --- a/target/linux/generic-2.6/patches-2.6.32/840-unable_to_open_console.patch +++ b/target/linux/generic-2.6/patches-2.6.32/840-unable_to_open_console.patch @@ -1,6 +1,6 @@ --- a/init/main.c +++ b/init/main.c -@@ -817,7 +817,7 @@ static noinline int init_post(void) +@@ -812,7 +812,7 @@ static noinline int init_post(void) numa_default_policy(); if (sys_open((const char __user *) "/dev/console", O_RDWR, 0) < 0) diff --git a/target/linux/generic-2.6/patches-2.6.32/922-gpiommc.patch b/target/linux/generic-2.6/patches-2.6.32/922-gpiommc.patch index e2547eda8..27779a813 100644 --- a/target/linux/generic-2.6/patches-2.6.32/922-gpiommc.patch +++ b/target/linux/generic-2.6/patches-2.6.32/922-gpiommc.patch @@ -829,7 +829,7 @@ +be done automatically. --- a/MAINTAINERS +++ b/MAINTAINERS -@@ -2348,6 +2348,11 @@ T: git git://git.kernel.org/pub/scm/linu +@@ -2377,6 +2377,11 @@ T: git git://git.kernel.org/pub/scm/linu S: Maintained F: drivers/media/video/gspca/ diff --git a/target/linux/generic-2.6/patches-2.6.32/980-vm_exports.patch b/target/linux/generic-2.6/patches-2.6.32/980-vm_exports.patch index 91f85c2b6..724b1f030 100644 --- a/target/linux/generic-2.6/patches-2.6.32/980-vm_exports.patch +++ b/target/linux/generic-2.6/patches-2.6.32/980-vm_exports.patch @@ -1,6 +1,6 @@ --- a/mm/shmem.c +++ b/mm/shmem.c -@@ -2775,6 +2775,16 @@ int shmem_lock(struct file *file, int lo +@@ -2608,6 +2608,16 @@ int shmem_lock(struct file *file, int lo /* common code */ @@ -17,7 +17,7 @@ /** * shmem_file_setup - get an unlinked file living in tmpfs * @name: name for dentry (to be seen in /proc//maps -@@ -2854,9 +2864,6 @@ int shmem_zero_setup(struct vm_area_stru +@@ -2687,9 +2697,6 @@ int shmem_zero_setup(struct vm_area_stru if (IS_ERR(file)) return PTR_ERR(file); @@ -68,7 +68,7 @@ * macro override instead of weak attribute alias, to workaround --- a/kernel/sched.c +++ b/kernel/sched.c -@@ -6075,6 +6075,7 @@ int can_nice(const struct task_struct *p +@@ -6095,6 +6095,7 @@ int can_nice(const struct task_struct *p return (nice_rlim <= p->signal->rlim[RLIMIT_NICE].rlim_cur || capable(CAP_SYS_NICE)); } diff --git a/target/linux/generic-2.6/patches-2.6.32/999-use_preinit_as_init.patch b/target/linux/generic-2.6/patches-2.6.32/999-use_preinit_as_init.patch index 7bea5256d..0a52a87e8 100644 --- a/target/linux/generic-2.6/patches-2.6.32/999-use_preinit_as_init.patch +++ b/target/linux/generic-2.6/patches-2.6.32/999-use_preinit_as_init.patch @@ -1,6 +1,6 @@ --- a/init/main.c +++ b/init/main.c -@@ -841,10 +841,7 @@ static noinline int init_post(void) +@@ -836,10 +836,7 @@ static noinline int init_post(void) printk(KERN_WARNING "Failed to execute %s. Attempting " "defaults...\n", execute_command); } diff --git a/target/linux/goldfish/Makefile b/target/linux/goldfish/Makefile index 59a778c34..84342fded 100644 --- a/target/linux/goldfish/Makefile +++ b/target/linux/goldfish/Makefile @@ -12,7 +12,7 @@ BOARDNAME:=Goldfish (Android Emulator) FEATURES:= CFLAGS:=-O2 -pipe -march=armv5te -mtune=xscale -funit-at-a-time -LINUX_VERSION:=2.6.30.9 +LINUX_VERSION:=2.6.30.10 DEVICE_TYPE=phone diff --git a/target/linux/ifxmips/Makefile b/target/linux/ifxmips/Makefile index 14ee8831f..addeef681 100644 --- a/target/linux/ifxmips/Makefile +++ b/target/linux/ifxmips/Makefile @@ -11,7 +11,7 @@ BOARD:=ifxmips BOARDNAME:=Infineon Mips FEATURES:=squashfs jffs2 atm -LINUX_VERSION:=2.6.30.9 +LINUX_VERSION:=2.6.30.10 CFLAGS=-Os -pipe -mips32r2 -mtune=mips32r2 -funit-at-a-time diff --git a/target/linux/ifxmips/config-2.6.30 b/target/linux/ifxmips/config-2.6.30 index b9167f631..0dffd566b 100644 --- a/target/linux/ifxmips/config-2.6.30 +++ b/target/linux/ifxmips/config-2.6.30 @@ -142,6 +142,7 @@ CONFIG_SERIAL_IFXMIPS=y # CONFIG_SIBYTE_SENTOSA is not set # CONFIG_SIBYTE_SWARM is not set # CONFIG_SLOW_WORK is not set +CONFIG_SQUASHFS_SUPPORT_LZMA=y CONFIG_SWAP_IO_SPACE=y CONFIG_SWCONFIG=y CONFIG_SYS_HAS_CPU_MIPS32_R1=y diff --git a/target/linux/ifxmips/nfs/config-2.6.28 b/target/linux/ifxmips/nfs/config-default similarity index 100% rename from target/linux/ifxmips/nfs/config-2.6.28 rename to target/linux/ifxmips/nfs/config-default diff --git a/target/linux/iop32x/Makefile b/target/linux/iop32x/Makefile index 6f3e78167..9bb89eee4 100644 --- a/target/linux/iop32x/Makefile +++ b/target/linux/iop32x/Makefile @@ -11,7 +11,7 @@ BOARD:=iop32x BOARDNAME:=Intel IOP32x FEATURES:=squashfs jffs2 -LINUX_VERSION:=2.6.30.9 +LINUX_VERSION:=2.6.30.10 include $(INCLUDE_DIR)/target.mk diff --git a/target/linux/ixp4xx/Makefile b/target/linux/ixp4xx/Makefile index 8c31e220d..819309ed4 100644 --- a/target/linux/ixp4xx/Makefile +++ b/target/linux/ixp4xx/Makefile @@ -12,7 +12,7 @@ BOARDNAME:=Intel IXP4xx FEATURES:=squashfs SUBTARGETS=generic harddisk -LINUX_VERSION:=2.6.28.10 +LINUX_VERSION:=2.6.30.10 include $(INCLUDE_DIR)/target.mk diff --git a/target/linux/ixp4xx/config-2.6.28 b/target/linux/ixp4xx/config-2.6.28 deleted file mode 100644 index 7311cae84..000000000 --- a/target/linux/ixp4xx/config-2.6.28 +++ /dev/null @@ -1,212 +0,0 @@ -# CONFIG_8139TOO is not set -# CONFIG_AEABI is not set -CONFIG_ALIGNMENT_TRAP=y -# CONFIG_ARCH_ADI_COYOTE is not set -# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set -CONFIG_ARCH_FLATMEM_HAS_HOLES=y -# CONFIG_ARCH_HAS_ILOG2_U32 is not set -# CONFIG_ARCH_HAS_ILOG2_U64 is not set -CONFIG_ARCH_IXCDP1100=y -CONFIG_ARCH_IXDP425=y -CONFIG_ARCH_IXDP4XX=y -CONFIG_ARCH_IXP4XX=y -# CONFIG_ARCH_PRPMC1100 is not set -CONFIG_ARCH_SUPPORTS_AOUT=y -CONFIG_ARCH_SUPPORTS_BIG_ENDIAN=y -# CONFIG_ARCH_SUPPORTS_MSI is not set -CONFIG_ARCH_SUSPEND_POSSIBLE=y -# CONFIG_ARM_THUMB is not set -CONFIG_ARM=y -# CONFIG_ARPD is not set -# CONFIG_ARTHUR is not set -CONFIG_AT24=y -# CONFIG_ATA is not set -# CONFIG_ATMEL is not set -# CONFIG_ATM is not set -# CONFIG_BINFMT_AOUT is not set -CONFIG_BITREVERSE=y -# CONFIG_BONDING is not set -CONFIG_BOUNCE=y -# CONFIG_BSD_DISKLABEL is not set -# CONFIG_CIFS_STATS is not set -CONFIG_CLASSIC_RCU=y -CONFIG_CMDLINE="root=/dev/mtdblock2 rootfstype=squashfs,jffs2 noinitrd console=ttyS0,115200" -CONFIG_CPU_32v5=y -CONFIG_CPU_32=y -CONFIG_CPU_ABRT_EV5T=y -CONFIG_CPU_BIG_ENDIAN=y -CONFIG_CPU_CACHE_VIVT=y -CONFIG_CPU_CP15_MMU=y -CONFIG_CPU_CP15=y -CONFIG_CPU_IXP43X=y -CONFIG_CPU_IXP46X=y -CONFIG_CPU_PABRT_NOIFAR=y -CONFIG_CPU_TLB_V4WBI=y -CONFIG_CPU_XSCALE=y -CONFIG_CRC16=y -# CONFIG_DEBUG_USER is not set -CONFIG_DEVPORT=y -# CONFIG_DM9000 is not set -CONFIG_DMABOUNCE_DEBUG=y -CONFIG_DMABOUNCE=y -CONFIG_DNOTIFY=y -# CONFIG_FPE_FASTFPE is not set -# CONFIG_FPE_NWFPE is not set -CONFIG_FRAME_POINTER=y -CONFIG_FS_POSIX_ACL=y -CONFIG_GENERIC_CLOCKEVENTS_BUILD=y -CONFIG_GENERIC_CLOCKEVENTS=y -# CONFIG_GENERIC_FIND_FIRST_BIT is not set -# CONFIG_GENERIC_FIND_NEXT_BIT is not set -CONFIG_GENERIC_GPIO=y -CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y -CONFIG_GPIO_DEVICE=y -CONFIG_GPIO_GW_I2C_PLD=y -CONFIG_GPIO_SYSFS=y -# CONFIG_HAMRADIO is not set -CONFIG_HARDIRQS_SW_RESEND=y -CONFIG_HAS_DMA=y -CONFIG_HAS_IOMEM=y -CONFIG_HAS_IOPORT=y -CONFIG_HAVE_ARCH_KGDB=y -# CONFIG_HAVE_ARCH_TRACEHOOK is not set -# CONFIG_HAVE_CLK is not set -# CONFIG_HAVE_DMA_ATTRS is not set -CONFIG_HAVE_DYNAMIC_FTRACE=y -# CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS is not set -CONFIG_HAVE_FTRACE=y -CONFIG_HAVE_GENERIC_DMA_COHERENT=y -CONFIG_HAVE_IDE=y -# CONFIG_HAVE_IOREMAP_PROT is not set -CONFIG_HAVE_KPROBES=y -CONFIG_HAVE_KRETPROBES=y -CONFIG_HAVE_LATENCYTOP_SUPPORT=y -CONFIG_HAVE_OPROFILE=y -# CONFIG_HERMES is not set -# CONFIG_HID is not set -CONFIG_HID_SUPPORT=y -# CONFIG_HWMON_DEBUG_CHIP is not set -CONFIG_HWMON_VID=y -CONFIG_HWMON=y -CONFIG_HW_RANDOM_IXP4XX=y -CONFIG_HW_RANDOM=y -CONFIG_I2C_ALGOBIT=y -CONFIG_I2C_BOARDINFO=y -CONFIG_I2C_CHARDEV=y -CONFIG_I2C_GPIO=y -# CONFIG_I2C_IOP3XX is not set -# CONFIG_I2C_ISCH is not set -CONFIG_I2C=y -# CONFIG_IDE is not set -CONFIG_INITRAMFS_SOURCE="" -# CONFIG_INPUT is not set -# CONFIG_INPUT_IXP4XX_BEEPER is not set -CONFIG_IP_MROUTE=y -CONFIG_IP_PIMSM_V1=y -CONFIG_IP_PIMSM_V2=y -# CONFIG_ISDN is not set -# CONFIG_IWMMXT is not set -CONFIG_IXP4XX_ETH=y -# CONFIG_IXP4XX_INDIRECT_PCI is not set -CONFIG_IXP4XX_NPE=y -CONFIG_IXP4XX_QMGR=y -CONFIG_IXP4XX_WATCHDOG=y -CONFIG_LEDS_FSG=y -CONFIG_LEDS_GPIO=y -CONFIG_LEDS_LATCH=y -# CONFIG_LEDS_PCA9532 is not set -# CONFIG_LEDS_PCA955X is not set -CONFIG_LEGACY_PTY_COUNT=256 -CONFIG_LEGACY_PTYS=y -# CONFIG_LLC2 is not set -CONFIG_MACH_AP1000=y -CONFIG_MACH_AVILA=y -CONFIG_MACH_CAMBRIA=y -CONFIG_MACH_COMPEX=y -CONFIG_MACH_DSMG600=y -CONFIG_MACH_FSG=y -CONFIG_MACH_GATEWAY7001=y -# CONFIG_MACH_GTWX5715 is not set -# CONFIG_MACH_IXDP465 is not set -CONFIG_MACH_IXDPG425=y -# CONFIG_MACH_KIXRP435 is not set -CONFIG_MACH_LOFT=y -CONFIG_MACH_MI424WR=y -CONFIG_MACH_NAS100D=y -CONFIG_MACH_NSLU2=y -CONFIG_MACH_PRONGHORNMETRO=y -CONFIG_MACH_PRONGHORN=y -CONFIG_MACH_SIDEWINDER=y -CONFIG_MACH_TW5334=y -CONFIG_MACH_USR8200=y -CONFIG_MACH_WG302V1=y -CONFIG_MACH_WG302V2=y -CONFIG_MACH_WRT300NV2=y -# CONFIG_MEDIA_TUNER is not set -# CONFIG_MEDIA_TUNER_MT20XX is not set -# CONFIG_MEDIA_TUNER_SIMPLE is not set -# CONFIG_MEDIA_TUNER_TDA8290 is not set -# CONFIG_MEDIA_TUNER_TDA9887 is not set -# CONFIG_MEDIA_TUNER_TEA5761 is not set -# CONFIG_MEDIA_TUNER_TEA5767 is not set -# CONFIG_MEDIA_TUNER_XC2028 is not set -# CONFIG_MEDIA_TUNER_XC5000 is not set -# CONFIG_MINIX_FS is not set -CONFIG_MTD_CFI_ADV_OPTIONS=y -# CONFIG_MTD_CFI_GEOMETRY is not set -CONFIG_MTD_IXP4XX=y -CONFIG_MTD_OTP=y -CONFIG_MTD_REDBOOT_PARTS=y -# CONFIG_NLS_CODEPAGE_437 is not set -# CONFIG_NLS_CODEPAGE_850 is not set -# CONFIG_NLS_ISO8859_15 is not set -# CONFIG_NLS_ISO8859_1 is not set -# CONFIG_NLS_KOI8_R is not set -# CONFIG_NO_IOPORT is not set -# CONFIG_OUTER_CACHE is not set -CONFIG_PAGEFLAGS_EXTENDED=y -# CONFIG_PATA_ARTOP is not set -# CONFIG_PATA_IXP4XX_CF is not set -# CONFIG_R6040 is not set -CONFIG_RTC_CLASS=y -CONFIG_RTC_DRV_DS1672=y -CONFIG_RTC_DRV_ISL1208=y -CONFIG_RTC_DRV_PCF8563=y -CONFIG_RTC_DRV_X1205=y -# CONFIG_SCSI_MULTI_LUN is not set -# CONFIG_SCSI_WAIT_SCAN is not set -# CONFIG_SENSORS_AD7414 is not set -CONFIG_SENSORS_AD7418=y -# CONFIG_SENSORS_EEPROM is not set -CONFIG_SENSORS_MAX6650=y -# CONFIG_SENSORS_PC87360 is not set -CONFIG_SENSORS_W83781D=y -# CONFIG_SERIAL_8250_EXTENDED is not set -CONFIG_SERIAL_8250_NR_UARTS=4 -CONFIG_SERIAL_8250_RUNTIME_UARTS=4 -CONFIG_SLABINFO=y -CONFIG_SND_USB=y -CONFIG_SPLIT_PTLOCK_CPUS=4096 -CONFIG_SYS_SUPPORTS_APM_EMULATION=y -CONFIG_UID16=y -CONFIG_USB_EHCI_BIG_ENDIAN_DESC=y -CONFIG_USB_EHCI_BIG_ENDIAN_MMIO=y -# CONFIG_USB_EHCI_HCD is not set -CONFIG_USB_EHCI_ROOT_HUB_TT=y -CONFIG_USB_EHCI_TT_NEWSCHED=y -# CONFIG_USB is not set -# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set -# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set -# CONFIG_USB_OHCI_HCD is not set -CONFIG_USB_SUPPORT=y -# CONFIG_USB_UHCI_HCD is not set -CONFIG_VECTORS_BASE=0xffff0000 -# CONFIG_VGASTATE is not set -# CONFIG_VIA_RHINE is not set -# CONFIG_VIA_VELOCITY is not set -# CONFIG_VIDEO_MEDIA is not set -CONFIG_VM_EVENT_COUNTERS=y -CONFIG_WATCHDOG_NOWAYOUT=y -CONFIG_XSCALE_PMU=y -CONFIG_ZBOOT_ROM_BSS=0x0 -CONFIG_ZBOOT_ROM_TEXT=0x0 diff --git a/target/linux/ixp4xx/config-2.6.30 b/target/linux/ixp4xx/config-2.6.30 index b569faa5e..982e9b7d2 100644 --- a/target/linux/ixp4xx/config-2.6.30 +++ b/target/linux/ixp4xx/config-2.6.30 @@ -82,6 +82,7 @@ CONFIG_I2C_GPIO=y # CONFIG_I2C_IOP3XX is not set CONFIG_I2C=y CONFIG_INITRAMFS_SOURCE="" +# CONFIG_INPUT_IXP4XX_BEEPER is not set CONFIG_IP_MROUTE=y CONFIG_IP_PIMSM_V1=y CONFIG_IP_PIMSM_V2=y diff --git a/target/linux/ixp4xx/patches-2.6.28/010-ixp43x_pci_fixup.patch b/target/linux/ixp4xx/patches-2.6.28/010-ixp43x_pci_fixup.patch deleted file mode 100644 index 35af7f4fa..000000000 --- a/target/linux/ixp4xx/patches-2.6.28/010-ixp43x_pci_fixup.patch +++ /dev/null @@ -1,11 +0,0 @@ ---- a/arch/arm/mach-ixp4xx/include/mach/hardware.h -+++ b/arch/arm/mach-ixp4xx/include/mach/hardware.h -@@ -18,7 +18,7 @@ - #define __ASM_ARCH_HARDWARE_H__ - - #define PCIBIOS_MIN_IO 0x00001000 --#define PCIBIOS_MIN_MEM (cpu_is_ixp43x() ? 0x40000000 : 0x48000000) -+#define PCIBIOS_MIN_MEM 0x48000000 - - /* - * We override the standard dma-mask routines for bouncing. diff --git a/target/linux/ixp4xx/patches-2.6.28/020-gateworks_i2c_pld.patch b/target/linux/ixp4xx/patches-2.6.28/020-gateworks_i2c_pld.patch deleted file mode 100644 index 6a9f65f89..000000000 --- a/target/linux/ixp4xx/patches-2.6.28/020-gateworks_i2c_pld.patch +++ /dev/null @@ -1,420 +0,0 @@ ---- /dev/null -+++ b/drivers/gpio/gw_i2c_pld.c -@@ -0,0 +1,370 @@ -+/* -+ * Gateworks I2C PLD GPIO expander -+ * -+ * Copyright (C) 2009 Gateworks Corporation -+ * -+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+ -+static const struct i2c_device_id gw_i2c_pld_id[] = { -+ { "gw_i2c_pld", 8 }, -+ { } -+}; -+MODULE_DEVICE_TABLE(i2c, gw_i2c_pld_id); -+ -+/* -+ * The Gateworks I2C PLD chip only expose one read and one -+ * write register. Writing a "one" bit (to match the reset state) lets -+ * that pin be used as an input. It is an open-drain model. -+ */ -+ -+struct gw_i2c_pld { -+ struct gpio_chip chip; -+ struct i2c_client *client; -+ unsigned out; /* software latch */ -+}; -+ -+/*-------------------------------------------------------------------------*/ -+ -+/* -+ * The Gateworks I2C PLD chip does not properly send the acknowledge bit -+ * thus we cannot use standard i2c_smbus functions. We have recreated -+ * our own here, but we still use the mutex_lock to lock the i2c_bus -+ * as the device still exists on the I2C bus. -+*/ -+ -+#define PLD_SCL_GPIO 6 -+#define PLD_SDA_GPIO 7 -+ -+#define SCL_LO() gpio_line_set(PLD_SCL_GPIO, IXP4XX_GPIO_LOW) -+#define SCL_HI() gpio_line_set(PLD_SCL_GPIO, IXP4XX_GPIO_HIGH) -+#define SCL_EN() gpio_line_config(PLD_SCL_GPIO, IXP4XX_GPIO_OUT) -+#define SDA_LO() gpio_line_set(PLD_SDA_GPIO, IXP4XX_GPIO_LOW) -+#define SDA_HI() gpio_line_set(PLD_SDA_GPIO, IXP4XX_GPIO_HIGH) -+#define SDA_EN() gpio_line_config(PLD_SDA_GPIO, IXP4XX_GPIO_OUT) -+#define SDA_DIS() gpio_line_config(PLD_SDA_GPIO, IXP4XX_GPIO_IN) -+#define SDA_IN(x) gpio_line_get(PLD_SDA_GPIO, &x); -+ -+static int i2c_pld_write_byte(int address, int byte) -+{ -+ int i; -+ -+ address = (address << 1) & ~0x1; -+ -+ SDA_HI(); -+ SDA_EN(); -+ SCL_EN(); -+ SCL_HI(); -+ SDA_LO(); -+ SCL_LO(); -+ -+ for (i = 7; i >= 0; i--) -+ { -+ if (address & (1 << i)) -+ SDA_HI(); -+ else -+ SDA_LO(); -+ -+ SCL_HI(); -+ SCL_LO(); -+ } -+ -+ SDA_DIS(); -+ SCL_HI(); -+ SDA_IN(i); -+ SCL_LO(); -+ SDA_EN(); -+ -+ for (i = 7; i >= 0; i--) -+ { -+ if (byte & (1 << i)) -+ SDA_HI(); -+ else -+ SDA_LO(); -+ SCL_HI(); -+ SCL_LO(); -+ } -+ -+ SDA_DIS(); -+ SCL_HI(); -+ SDA_IN(i); -+ SCL_LO(); -+ -+ SDA_HI(); -+ SDA_EN(); -+ -+ SDA_LO(); -+ SCL_HI(); -+ SDA_HI(); -+ SCL_LO(); -+ SCL_HI(); -+ -+ return 0; -+} -+ -+static unsigned int i2c_pld_read_byte(int address) -+{ -+ int i = 0, byte = 0; -+ int bit; -+ -+ address = (address << 1) | 0x1; -+ -+ SDA_HI(); -+ SDA_EN(); -+ SCL_EN(); -+ SCL_HI(); -+ SDA_LO(); -+ SCL_LO(); -+ -+ for (i = 7; i >= 0; i--) -+ { -+ if (address & (1 << i)) -+ SDA_HI(); -+ else -+ SDA_LO(); -+ -+ SCL_HI(); -+ SCL_LO(); -+ } -+ -+ SDA_DIS(); -+ SCL_HI(); -+ SDA_IN(i); -+ SCL_LO(); -+ SDA_EN(); -+ -+ SDA_DIS(); -+ for (i = 7; i >= 0; i--) -+ { -+ SCL_HI(); -+ SDA_IN(bit); -+ byte |= bit << i; -+ SCL_LO(); -+ } -+ -+ SDA_LO(); -+ SCL_HI(); -+ SDA_HI(); -+ SCL_LO(); -+ SCL_HI(); -+ -+ return byte; -+} -+ -+ -+static int gw_i2c_pld_input8(struct gpio_chip *chip, unsigned offset) -+{ -+ int ret; -+ struct gw_i2c_pld *gpio = container_of(chip, struct gw_i2c_pld, chip); -+ struct i2c_adapter *adap = gpio->client->adapter; -+ -+ if (in_atomic() || irqs_disabled()) { -+ ret = mutex_trylock(&adap->bus_lock); -+ if (!ret) -+ /* I2C activity is ongoing. */ -+ return -EAGAIN; -+ } else { -+ mutex_lock_nested(&adap->bus_lock, adap->level); -+ } -+ -+ gpio->out |= (1 << offset); -+ -+ ret = i2c_pld_write_byte(gpio->client->addr, gpio->out); -+ -+ mutex_unlock(&adap->bus_lock); -+ -+ return ret; -+} -+ -+static int gw_i2c_pld_get8(struct gpio_chip *chip, unsigned offset) -+{ -+ int ret; -+ s32 value; -+ struct gw_i2c_pld *gpio = container_of(chip, struct gw_i2c_pld, chip); -+ struct i2c_adapter *adap = gpio->client->adapter; -+ -+ if (in_atomic() || irqs_disabled()) { -+ ret = mutex_trylock(&adap->bus_lock); -+ if (!ret) -+ /* I2C activity is ongoing. */ -+ return -EAGAIN; -+ } else { -+ mutex_lock_nested(&adap->bus_lock, adap->level); -+ } -+ -+ value = i2c_pld_read_byte(gpio->client->addr); -+ -+ mutex_unlock(&adap->bus_lock); -+ -+ return (value < 0) ? 0 : (value & (1 << offset)); -+} -+ -+static int gw_i2c_pld_output8(struct gpio_chip *chip, unsigned offset, int value) -+{ -+ int ret; -+ -+ struct gw_i2c_pld *gpio = container_of(chip, struct gw_i2c_pld, chip); -+ struct i2c_adapter *adap = gpio->client->adapter; -+ -+ unsigned bit = 1 << offset; -+ -+ if (in_atomic() || irqs_disabled()) { -+ ret = mutex_trylock(&adap->bus_lock); -+ if (!ret) -+ /* I2C activity is ongoing. */ -+ return -EAGAIN; -+ } else { -+ mutex_lock_nested(&adap->bus_lock, adap->level); -+ } -+ -+ -+ if (value) -+ gpio->out |= bit; -+ else -+ gpio->out &= ~bit; -+ -+ ret = i2c_pld_write_byte(gpio->client->addr, gpio->out); -+ -+ mutex_unlock(&adap->bus_lock); -+ -+ return ret; -+} -+ -+static void gw_i2c_pld_set8(struct gpio_chip *chip, unsigned offset, int value) -+{ -+ gw_i2c_pld_output8(chip, offset, value); -+} -+ -+/*-------------------------------------------------------------------------*/ -+ -+static int gw_i2c_pld_probe(struct i2c_client *client, -+ const struct i2c_device_id *id) -+{ -+ struct gw_i2c_pld_platform_data *pdata; -+ struct gw_i2c_pld *gpio; -+ int status; -+ -+ pdata = client->dev.platform_data; -+ if (!pdata) -+ return -ENODEV; -+ -+ /* Allocate, initialize, and register this gpio_chip. */ -+ gpio = kzalloc(sizeof *gpio, GFP_KERNEL); -+ if (!gpio) -+ return -ENOMEM; -+ -+ gpio->chip.base = pdata->gpio_base; -+ gpio->chip.can_sleep = 1; -+ gpio->chip.dev = &client->dev; -+ gpio->chip.owner = THIS_MODULE; -+ -+ gpio->chip.ngpio = pdata->nr_gpio; -+ gpio->chip.direction_input = gw_i2c_pld_input8; -+ gpio->chip.get = gw_i2c_pld_get8; -+ gpio->chip.direction_output = gw_i2c_pld_output8; -+ gpio->chip.set = gw_i2c_pld_set8; -+ -+ gpio->chip.label = client->name; -+ -+ gpio->client = client; -+ i2c_set_clientdata(client, gpio); -+ -+ gpio->out = 0xFF; -+ -+ status = gpiochip_add(&gpio->chip); -+ if (status < 0) -+ goto fail; -+ -+ dev_info(&client->dev, "gpios %d..%d on a %s%s\n", -+ gpio->chip.base, -+ gpio->chip.base + gpio->chip.ngpio - 1, -+ client->name, -+ client->irq ? " (irq ignored)" : ""); -+ -+ /* Let platform code set up the GPIOs and their users. -+ * Now is the first time anyone could use them. -+ */ -+ if (pdata->setup) { -+ status = pdata->setup(client, -+ gpio->chip.base, gpio->chip.ngpio, -+ pdata->context); -+ if (status < 0) -+ dev_warn(&client->dev, "setup --> %d\n", status); -+ } -+ -+ return 0; -+ -+fail: -+ dev_dbg(&client->dev, "probe error %d for '%s'\n", -+ status, client->name); -+ kfree(gpio); -+ return status; -+} -+ -+static int gw_i2c_pld_remove(struct i2c_client *client) -+{ -+ struct gw_i2c_pld_platform_data *pdata = client->dev.platform_data; -+ struct gw_i2c_pld *gpio = i2c_get_clientdata(client); -+ int status = 0; -+ -+ if (pdata->teardown) { -+ status = pdata->teardown(client, -+ gpio->chip.base, gpio->chip.ngpio, -+ pdata->context); -+ if (status < 0) { -+ dev_err(&client->dev, "%s --> %d\n", -+ "teardown", status); -+ return status; -+ } -+ } -+ -+ status = gpiochip_remove(&gpio->chip); -+ if (status == 0) -+ kfree(gpio); -+ else -+ dev_err(&client->dev, "%s --> %d\n", "remove", status); -+ return status; -+} -+ -+static struct i2c_driver gw_i2c_pld_driver = { -+ .driver = { -+ .name = "gw_i2c_pld", -+ .owner = THIS_MODULE, -+ }, -+ .probe = gw_i2c_pld_probe, -+ .remove = gw_i2c_pld_remove, -+ .id_table = gw_i2c_pld_id, -+}; -+ -+static int __init gw_i2c_pld_init(void) -+{ -+ return i2c_add_driver(&gw_i2c_pld_driver); -+} -+module_init(gw_i2c_pld_init); -+ -+static void __exit gw_i2c_pld_exit(void) -+{ -+ i2c_del_driver(&gw_i2c_pld_driver); -+} -+module_exit(gw_i2c_pld_exit); -+ -+MODULE_LICENSE("GPL"); -+MODULE_AUTHOR("Chris Lang"); ---- a/drivers/gpio/Kconfig -+++ b/drivers/gpio/Kconfig -@@ -160,6 +160,14 @@ config GPIO_BT8XX - - If unsure, say N. - -+config GPIO_GW_I2C_PLD -+ tristate "Gateworks I2C PLD GPIO Expander" -+ depends on I2C -+ help -+ Say yes here to provide access to the Gateworks I2C PLD GPIO -+ Expander. This is used at least on the GW2358-4. -+ -+ - comment "SPI GPIO expanders:" - - config GPIO_MAX7301 ---- a/drivers/gpio/Makefile -+++ b/drivers/gpio/Makefile -@@ -12,3 +12,4 @@ obj-$(CONFIG_GPIO_PCF857X) += pcf857x.o - obj-$(CONFIG_GPIO_TWL4030) += twl4030-gpio.o - obj-$(CONFIG_GPIO_XILINX) += xilinx_gpio.o - obj-$(CONFIG_GPIO_BT8XX) += bt8xxgpio.o -+obj-$(CONFIG_GPIO_GW_I2C_PLD) += gw_i2c_pld.o ---- /dev/null -+++ b/include/linux/i2c/gw_i2c_pld.h -@@ -0,0 +1,20 @@ -+#ifndef __LINUX_GW_I2C_PLD_H -+#define __LINUX_GW_I2C_PLD_H -+ -+/** -+ * The Gateworks I2C PLD Implements an additional 8 bits of GPIO through the PLD -+ */ -+ -+struct gw_i2c_pld_platform_data { -+ unsigned gpio_base; -+ unsigned nr_gpio; -+ int (*setup)(struct i2c_client *client, -+ int gpio, unsigned ngpio, -+ void *context); -+ int (*teardown)(struct i2c_client *client, -+ int gpio, unsigned ngpio, -+ void *context); -+ void *context; -+}; -+ -+#endif /* __LINUX_GW_I2C_PLD_H */ diff --git a/target/linux/ixp4xx/patches-2.6.28/090-increase_entropy_pools.patch b/target/linux/ixp4xx/patches-2.6.28/090-increase_entropy_pools.patch deleted file mode 100644 index 5cf81db23..000000000 --- a/target/linux/ixp4xx/patches-2.6.28/090-increase_entropy_pools.patch +++ /dev/null @@ -1,15 +0,0 @@ ---- a/drivers/char/random.c -+++ b/drivers/char/random.c -@@ -259,9 +259,9 @@ - /* - * Configuration information - */ --#define INPUT_POOL_WORDS 128 --#define OUTPUT_POOL_WORDS 32 --#define SEC_XFER_SIZE 512 -+#define INPUT_POOL_WORDS 256 -+#define OUTPUT_POOL_WORDS 64 -+#define SEC_XFER_SIZE 1024 - - /* - * The minimum number of bits of entropy before we wake up a read on diff --git a/target/linux/ixp4xx/patches-2.6.28/100-wg302v2_gateway7001_mac_plat_info.patch b/target/linux/ixp4xx/patches-2.6.28/100-wg302v2_gateway7001_mac_plat_info.patch deleted file mode 100644 index a19a4085a..000000000 --- a/target/linux/ixp4xx/patches-2.6.28/100-wg302v2_gateway7001_mac_plat_info.patch +++ /dev/null @@ -1,68 +0,0 @@ ---- a/arch/arm/mach-ixp4xx/gateway7001-setup.c -+++ b/arch/arm/mach-ixp4xx/gateway7001-setup.c -@@ -76,9 +76,35 @@ static struct platform_device gateway700 - .resource = &gateway7001_uart_resource, - }; - -+static struct eth_plat_info gateway7001_plat_eth[] = { -+ { -+ .phy = 1, -+ .rxq = 3, -+ .txreadyq = 20, -+ }, { -+ .phy = 2, -+ .rxq = 4, -+ .txreadyq = 21, -+ } -+}; -+ -+static struct platform_device gateway7001_eth[] = { -+ { -+ .name = "ixp4xx_eth", -+ .id = IXP4XX_ETH_NPEB, -+ .dev.platform_data = gateway7001_plat_eth, -+ }, { -+ .name = "ixp4xx_eth", -+ .id = IXP4XX_ETH_NPEC, -+ .dev.platform_data = gateway7001_plat_eth + 1, -+ } -+}; -+ - static struct platform_device *gateway7001_devices[] __initdata = { - &gateway7001_flash, -- &gateway7001_uart -+ &gateway7001_uart, -+ &gateway7001_eth[0], -+ &gateway7001_eth[1], - }; - - static void __init gateway7001_init(void) ---- a/arch/arm/mach-ixp4xx/wg302v2-setup.c -+++ b/arch/arm/mach-ixp4xx/wg302v2-setup.c -@@ -77,9 +77,26 @@ static struct platform_device wg302v2_ua - .resource = &wg302v2_uart_resource, - }; - -+static struct eth_plat_info wg302v2_plat_eth[] = { -+ { -+ .phy = 8, -+ .rxq = 3, -+ .txreadyq = 20, -+ } -+}; -+ -+static struct platform_device wg302v2_eth[] = { -+ { -+ .name = "ixp4xx_eth", -+ .id = IXP4XX_ETH_NPEB, -+ .dev.platform_data = wg302v2_plat_eth, -+ } -+}; -+ - static struct platform_device *wg302v2_devices[] __initdata = { - &wg302v2_flash, - &wg302v2_uart, -+ &wg302v2_eth[0], - }; - - static void __init wg302v2_init(void) diff --git a/target/linux/ixp4xx/patches-2.6.28/105-wg302v1_support.patch b/target/linux/ixp4xx/patches-2.6.28/105-wg302v1_support.patch deleted file mode 100644 index 600813f17..000000000 --- a/target/linux/ixp4xx/patches-2.6.28/105-wg302v1_support.patch +++ /dev/null @@ -1,257 +0,0 @@ ---- a/arch/arm/configs/ixp4xx_defconfig -+++ b/arch/arm/configs/ixp4xx_defconfig -@@ -155,6 +155,7 @@ CONFIG_MACH_AVILA=y - CONFIG_MACH_LOFT=y - CONFIG_ARCH_ADI_COYOTE=y - CONFIG_MACH_GATEWAY7001=y -+CONFIG_MACH_WG302V1=y - CONFIG_MACH_WG302V2=y - CONFIG_ARCH_IXDP425=y - CONFIG_MACH_IXDPG425=y ---- a/arch/arm/mach-ixp4xx/Kconfig -+++ b/arch/arm/mach-ixp4xx/Kconfig -@@ -49,6 +49,14 @@ config MACH_GATEWAY7001 - 7001 Access Point. For more information on this platform, - see http://openwrt.org - -+config MACH_WG302V1 -+ bool "Netgear WG302 v1 / WAG302 v1" -+ select PCI -+ help -+ Say 'Y' here if you want your kernel to support Netgear's -+ WG302 v1 or WAG302 v1 Access Points. For more information -+ on this platform, see http://openwrt.org -+ - config MACH_WG302V2 - bool "Netgear WG302 v2 / WAG302 v2" - select PCI ---- a/arch/arm/mach-ixp4xx/Makefile -+++ b/arch/arm/mach-ixp4xx/Makefile -@@ -14,6 +14,7 @@ obj-pci-$(CONFIG_MACH_NSLU2) += nslu2-p - obj-pci-$(CONFIG_MACH_NAS100D) += nas100d-pci.o - obj-pci-$(CONFIG_MACH_DSMG600) += dsmg600-pci.o - obj-pci-$(CONFIG_MACH_GATEWAY7001) += gateway7001-pci.o -+obj-pci-$(CONFIG_MACH_WG302V1) += wg302v1-pci.o - obj-pci-$(CONFIG_MACH_WG302V2) += wg302v2-pci.o - obj-pci-$(CONFIG_MACH_FSG) += fsg-pci.o - -@@ -28,6 +29,7 @@ obj-$(CONFIG_MACH_NSLU2) += nslu2-setup. - obj-$(CONFIG_MACH_NAS100D) += nas100d-setup.o - obj-$(CONFIG_MACH_DSMG600) += dsmg600-setup.o - obj-$(CONFIG_MACH_GATEWAY7001) += gateway7001-setup.o -+obj-$(CONFIG_MACH_WG302V1) += wg302v1-setup.o - obj-$(CONFIG_MACH_WG302V2) += wg302v2-setup.o - obj-$(CONFIG_MACH_FSG) += fsg-setup.o - ---- /dev/null -+++ b/arch/arm/mach-ixp4xx/wg302v1-pci.c -@@ -0,0 +1,64 @@ -+/* -+ * arch/arch/mach-ixp4xx/wg302v1-pci.c -+ * -+ * PCI setup routines for the Netgear WG302 v1 and WAG302 v1 -+ * -+ * Copyright (C) 2008 Imre Kaloz -+ * -+ * based on coyote-pci.c: -+ * Copyright (C) 2002 Jungo Software Technologies. -+ * Copyright (C) 2003 MontaVista Software, Inc. -+ * -+ * Maintainer: Imre Kaloz -+ * -+ * 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 -+#include -+#include -+#include -+ -+#include -+#include -+ -+#include -+ -+void __init wg302v1_pci_preinit(void) -+{ -+ set_irq_type(IRQ_IXP4XX_GPIO8, IRQ_TYPE_LEVEL_LOW); -+ set_irq_type(IRQ_IXP4XX_GPIO10, IRQ_TYPE_LEVEL_LOW); -+ -+ ixp4xx_pci_preinit(); -+} -+ -+static int __init wg302v1_map_irq(struct pci_dev *dev, u8 slot, u8 pin) -+{ -+ if (slot == 1) -+ return IRQ_IXP4XX_GPIO8; -+ else if (slot == 2) -+ return IRQ_IXP4XX_GPIO10; -+ else -+ return -1; -+} -+ -+struct hw_pci wg302v1_pci __initdata = { -+ .nr_controllers = 1, -+ .preinit = wg302v1_pci_preinit, -+ .swizzle = pci_std_swizzle, -+ .setup = ixp4xx_setup, -+ .scan = ixp4xx_scan_bus, -+ .map_irq = wg302v1_map_irq, -+}; -+ -+int __init wg302v1_pci_init(void) -+{ -+ if (machine_is_wg302v1()) -+ pci_common_init(&wg302v1_pci); -+ return 0; -+} -+ -+subsys_initcall(wg302v1_pci_init); ---- /dev/null -+++ b/arch/arm/mach-ixp4xx/wg302v1-setup.c -@@ -0,0 +1,142 @@ -+/* -+ * arch/arm/mach-ixp4xx/wg302v1-setup.c -+ * -+ * Board setup for the Netgear WG302 v1 and WAG302 v1 -+ * -+ * Copyright (C) 2008 Imre Kaloz -+ * -+ * based on coyote-setup.c: -+ * Copyright (C) 2003-2005 MontaVista Software, Inc. -+ * -+ * Author: Imre Kaloz -+ * -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+static struct flash_platform_data wg302v1_flash_data = { -+ .map_name = "cfi_probe", -+ .width = 2, -+}; -+ -+static struct resource wg302v1_flash_resource = { -+ .flags = IORESOURCE_MEM, -+}; -+ -+static struct platform_device wg302v1_flash = { -+ .name = "IXP4XX-Flash", -+ .id = 0, -+ .dev = { -+ .platform_data = &wg302v1_flash_data, -+ }, -+ .num_resources = 1, -+ .resource = &wg302v1_flash_resource, -+}; -+ -+static struct resource wg302v1_uart_resources[] = { -+ { -+ .start = IXP4XX_UART1_BASE_PHYS, -+ .end = IXP4XX_UART1_BASE_PHYS + 0x0fff, -+ .flags = IORESOURCE_MEM, -+ }, -+ { -+ .start = IXP4XX_UART2_BASE_PHYS, -+ .end = IXP4XX_UART2_BASE_PHYS + 0x0fff, -+ .flags = IORESOURCE_MEM, -+ } -+}; -+ -+static struct plat_serial8250_port wg302v1_uart_data[] = { -+ { -+ .mapbase = IXP4XX_UART1_BASE_PHYS, -+ .membase = (char *)IXP4XX_UART1_BASE_VIRT + REG_OFFSET, -+ .irq = IRQ_IXP4XX_UART1, -+ .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST, -+ .iotype = UPIO_MEM, -+ .regshift = 2, -+ .uartclk = IXP4XX_UART_XTAL, -+ }, -+ { -+ .mapbase = IXP4XX_UART2_BASE_PHYS, -+ .membase = (char *)IXP4XX_UART2_BASE_VIRT + REG_OFFSET, -+ .irq = IRQ_IXP4XX_UART2, -+ .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST, -+ .iotype = UPIO_MEM, -+ .regshift = 2, -+ .uartclk = IXP4XX_UART_XTAL, -+ }, -+ { }, -+}; -+ -+static struct platform_device wg302v1_uart = { -+ .name = "serial8250", -+ .id = PLAT8250_DEV_PLATFORM, -+ .dev = { -+ .platform_data = wg302v1_uart_data, -+ }, -+ .num_resources = 2, -+ .resource = wg302v1_uart_resources, -+}; -+ -+static struct eth_plat_info wg302v1_plat_eth[] = { -+ { -+ .phy = 30, -+ .rxq = 3, -+ .txreadyq = 20, -+ } -+}; -+ -+static struct platform_device wg302v1_eth[] = { -+ { -+ .name = "ixp4xx_eth", -+ .id = IXP4XX_ETH_NPEB, -+ .dev.platform_data = wg302v1_plat_eth, -+ } -+}; -+ -+static struct platform_device *wg302v1_devices[] __initdata = { -+ &wg302v1_flash, -+ &wg302v1_uart, -+ &wg302v1_eth[0], -+}; -+ -+static void __init wg302v1_init(void) -+{ -+ ixp4xx_sys_init(); -+ -+ wg302v1_flash_resource.start = IXP4XX_EXP_BUS_BASE(0); -+ wg302v1_flash_resource.end = IXP4XX_EXP_BUS_BASE(0) + SZ_32M - 1; -+ -+ *IXP4XX_EXP_CS0 |= IXP4XX_FLASH_WRITABLE; -+ *IXP4XX_EXP_CS1 = *IXP4XX_EXP_CS0; -+ -+ platform_add_devices(wg302v1_devices, ARRAY_SIZE(wg302v1_devices)); -+} -+ -+#ifdef CONFIG_MACH_WG302V1 -+MACHINE_START(WG302V1, "Netgear WG302 v1 / WAG302 v1") -+ /* Maintainer: Imre Kaloz */ -+ .phys_io = IXP4XX_PERIPHERAL_BASE_PHYS, -+ .io_pg_offst = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc, -+ .map_io = ixp4xx_map_io, -+ .init_irq = ixp4xx_init_irq, -+ .timer = &ixp4xx_timer, -+ .boot_params = 0x0100, -+ .init_machine = wg302v1_init, -+MACHINE_END -+#endif diff --git a/target/linux/ixp4xx/patches-2.6.28/110-pronghorn_series_support.patch b/target/linux/ixp4xx/patches-2.6.28/110-pronghorn_series_support.patch deleted file mode 100644 index 9b81e2eee..000000000 --- a/target/linux/ixp4xx/patches-2.6.28/110-pronghorn_series_support.patch +++ /dev/null @@ -1,387 +0,0 @@ ---- a/arch/arm/configs/ixp4xx_defconfig -+++ b/arch/arm/configs/ixp4xx_defconfig -@@ -157,6 +157,8 @@ CONFIG_ARCH_ADI_COYOTE=y - CONFIG_MACH_GATEWAY7001=y - CONFIG_MACH_WG302V1=y - CONFIG_MACH_WG302V2=y -+CONFIG_MACH_PRONGHORN=y -+CONFIG_MACH_PRONGHORNMETRO=y - CONFIG_ARCH_IXDP425=y - CONFIG_MACH_IXDPG425=y - CONFIG_MACH_IXDP465=y ---- a/arch/arm/mach-ixp4xx/Kconfig -+++ b/arch/arm/mach-ixp4xx/Kconfig -@@ -65,6 +65,22 @@ config MACH_WG302V2 - WG302 v2 or WAG302 v2 Access Points. For more information - on this platform, see http://openwrt.org - -+config MACH_PRONGHORN -+ bool "ADI Pronghorn series" -+ select PCI -+ help -+ Say 'Y' here if you want your kernel to support the ADI -+ Engineering Pronghorn series. For more -+ information on this platform, see http://www.adiengineering.com -+ -+# -+# There're only minimal differences kernel-wise between the Pronghorn and -+# Pronghorn Metro boards - they use different chip selects to drive the -+# CF slot connected to the expansion bus, so we just enable them together. -+# -+config MACH_PRONGHORNMETRO -+ def_bool MACH_PRONGHORN -+ - config ARCH_IXDP425 - bool "IXDP425" - help ---- a/arch/arm/mach-ixp4xx/Makefile -+++ b/arch/arm/mach-ixp4xx/Makefile -@@ -17,6 +17,7 @@ obj-pci-$(CONFIG_MACH_GATEWAY7001) += ga - obj-pci-$(CONFIG_MACH_WG302V1) += wg302v1-pci.o - obj-pci-$(CONFIG_MACH_WG302V2) += wg302v2-pci.o - obj-pci-$(CONFIG_MACH_FSG) += fsg-pci.o -+obj-pci-$(CONFIG_MACH_PRONGHORN) += pronghorn-pci.o - - obj-y += common.o - -@@ -32,6 +33,7 @@ obj-$(CONFIG_MACH_GATEWAY7001) += gatewa - obj-$(CONFIG_MACH_WG302V1) += wg302v1-setup.o - obj-$(CONFIG_MACH_WG302V2) += wg302v2-setup.o - obj-$(CONFIG_MACH_FSG) += fsg-setup.o -+obj-$(CONFIG_MACH_PRONGHORN) += pronghorn-setup.o - - obj-$(CONFIG_PCI) += $(obj-pci-$(CONFIG_PCI)) common-pci.o - obj-$(CONFIG_IXP4XX_QMGR) += ixp4xx_qmgr.o ---- /dev/null -+++ b/arch/arm/mach-ixp4xx/pronghorn-pci.c -@@ -0,0 +1,70 @@ -+/* -+ * arch/arch/mach-ixp4xx/pronghorn-pci.c -+ * -+ * PCI setup routines for ADI Engineering Pronghorn series -+ * -+ * Copyright (C) 2008 Imre Kaloz -+ * -+ * based on coyote-pci.c: -+ * Copyright (C) 2002 Jungo Software Technologies. -+ * Copyright (C) 2003 MontaVista Softwrae, Inc. -+ * -+ * Maintainer: Imre Kaloz -+ * -+ * 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 -+#include -+#include -+#include -+ -+#include -+#include -+ -+#include -+ -+void __init pronghorn_pci_preinit(void) -+{ -+ set_irq_type(IRQ_IXP4XX_GPIO4, IRQ_TYPE_LEVEL_LOW); -+ set_irq_type(IRQ_IXP4XX_GPIO6, IRQ_TYPE_LEVEL_LOW); -+ set_irq_type(IRQ_IXP4XX_GPIO11, IRQ_TYPE_LEVEL_LOW); -+ set_irq_type(IRQ_IXP4XX_GPIO1, IRQ_TYPE_LEVEL_LOW); -+ -+ ixp4xx_pci_preinit(); -+} -+ -+static int __init pronghorn_map_irq(struct pci_dev *dev, u8 slot, u8 pin) -+{ -+ if (slot == 13) -+ return IRQ_IXP4XX_GPIO4; -+ else if (slot == 14) -+ return IRQ_IXP4XX_GPIO6; -+ else if (slot == 15) -+ return IRQ_IXP4XX_GPIO11; -+ else if (slot == 16) -+ return IRQ_IXP4XX_GPIO1; -+ else -+ return -1; -+} -+ -+struct hw_pci pronghorn_pci __initdata = { -+ .nr_controllers = 1, -+ .preinit = pronghorn_pci_preinit, -+ .swizzle = pci_std_swizzle, -+ .setup = ixp4xx_setup, -+ .scan = ixp4xx_scan_bus, -+ .map_irq = pronghorn_map_irq, -+}; -+ -+int __init pronghorn_pci_init(void) -+{ -+ if (machine_is_pronghorn() || machine_is_pronghorn_metro()) -+ pci_common_init(&pronghorn_pci); -+ return 0; -+} -+ -+subsys_initcall(pronghorn_pci_init); ---- /dev/null -+++ b/arch/arm/mach-ixp4xx/pronghorn-setup.c -@@ -0,0 +1,245 @@ -+/* -+ * arch/arm/mach-ixp4xx/pronghorn-setup.c -+ * -+ * Board setup for the ADI Engineering Pronghorn series -+ * -+ * Copyright (C) 2008 Imre Kaloz -+ * -+ * based on coyote-setup.c: -+ * Copyright (C) 2003-2005 MontaVista Software, Inc. -+ * -+ * Author: Imre Kaloz -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+static struct flash_platform_data pronghorn_flash_data = { -+ .map_name = "cfi_probe", -+ .width = 2, -+}; -+ -+static struct resource pronghorn_flash_resource = { -+ .flags = IORESOURCE_MEM, -+}; -+ -+static struct platform_device pronghorn_flash = { -+ .name = "IXP4XX-Flash", -+ .id = 0, -+ .dev = { -+ .platform_data = &pronghorn_flash_data, -+ }, -+ .num_resources = 1, -+ .resource = &pronghorn_flash_resource, -+}; -+ -+static struct resource pronghorn_uart_resources [] = { -+ { -+ .start = IXP4XX_UART1_BASE_PHYS, -+ .end = IXP4XX_UART1_BASE_PHYS + 0x0fff, -+ .flags = IORESOURCE_MEM -+ }, -+ { -+ .start = IXP4XX_UART2_BASE_PHYS, -+ .end = IXP4XX_UART2_BASE_PHYS + 0x0fff, -+ .flags = IORESOURCE_MEM -+ } -+}; -+ -+static struct plat_serial8250_port pronghorn_uart_data[] = { -+ { -+ .mapbase = IXP4XX_UART1_BASE_PHYS, -+ .membase = (char *)IXP4XX_UART1_BASE_VIRT + REG_OFFSET, -+ .irq = IRQ_IXP4XX_UART1, -+ .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST, -+ .iotype = UPIO_MEM, -+ .regshift = 2, -+ .uartclk = IXP4XX_UART_XTAL, -+ }, -+ { -+ .mapbase = IXP4XX_UART2_BASE_PHYS, -+ .membase = (char *)IXP4XX_UART2_BASE_VIRT + REG_OFFSET, -+ .irq = IRQ_IXP4XX_UART2, -+ .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST, -+ .iotype = UPIO_MEM, -+ .regshift = 2, -+ .uartclk = IXP4XX_UART_XTAL, -+ }, -+ { }, -+}; -+ -+static struct platform_device pronghorn_uart = { -+ .name = "serial8250", -+ .id = PLAT8250_DEV_PLATFORM, -+ .dev = { -+ .platform_data = pronghorn_uart_data, -+ }, -+ .num_resources = 2, -+ .resource = pronghorn_uart_resources, -+}; -+ -+static struct i2c_gpio_platform_data pronghorn_i2c_gpio_data = { -+ .sda_pin = 9, -+ .scl_pin = 10, -+}; -+ -+static struct platform_device pronghorn_i2c_gpio = { -+ .name = "i2c-gpio", -+ .id = 0, -+ .dev = { -+ .platform_data = &pronghorn_i2c_gpio_data, -+ }, -+}; -+ -+static struct gpio_led pronghorn_led_pin[] = { -+ { -+ .name = "pronghorn:green:status", -+ .gpio = 7, -+ } -+}; -+ -+static struct gpio_led_platform_data pronghorn_led_data = { -+ .num_leds = 1, -+ .leds = pronghorn_led_pin, -+}; -+ -+static struct platform_device pronghorn_led = { -+ .name = "leds-gpio", -+ .id = -1, -+ .dev.platform_data = &pronghorn_led_data, -+}; -+ -+static struct resource pronghorn_pata_resources[] = { -+ { -+ .flags = IORESOURCE_MEM -+ }, -+ { -+ .flags = IORESOURCE_MEM, -+ }, -+ { -+ .name = "intrq", -+ .start = IRQ_IXP4XX_GPIO0, -+ .end = IRQ_IXP4XX_GPIO0, -+ .flags = IORESOURCE_IRQ, -+ }, -+}; -+ -+static struct ixp4xx_pata_data pronghorn_pata_data = { -+ .cs0_bits = 0xbfff0043, -+ .cs1_bits = 0xbfff0043, -+}; -+ -+static struct platform_device pronghorn_pata = { -+ .name = "pata_ixp4xx_cf", -+ .id = 0, -+ .dev.platform_data = &pronghorn_pata_data, -+ .num_resources = ARRAY_SIZE(pronghorn_pata_resources), -+ .resource = pronghorn_pata_resources, -+}; -+ -+static struct eth_plat_info pronghorn_plat_eth[] = { -+ { -+ .phy = 0, -+ .rxq = 3, -+ .txreadyq = 20, -+ }, { -+ .phy = 1, -+ .rxq = 4, -+ .txreadyq = 21, -+ } -+}; -+ -+static struct platform_device pronghorn_eth[] = { -+ { -+ .name = "ixp4xx_eth", -+ .id = IXP4XX_ETH_NPEB, -+ .dev.platform_data = pronghorn_plat_eth, -+ }, { -+ .name = "ixp4xx_eth", -+ .id = IXP4XX_ETH_NPEC, -+ .dev.platform_data = pronghorn_plat_eth + 1, -+ } -+}; -+ -+static struct platform_device *pronghorn_devices[] __initdata = { -+ &pronghorn_flash, -+ &pronghorn_uart, -+ &pronghorn_led, -+ &pronghorn_eth[0], -+ &pronghorn_eth[1], -+}; -+ -+static void __init pronghorn_init(void) -+{ -+ ixp4xx_sys_init(); -+ -+ pronghorn_flash_resource.start = IXP4XX_EXP_BUS_BASE(0); -+ pronghorn_flash_resource.end = IXP4XX_EXP_BUS_BASE(0) + SZ_32M - 1; -+ -+ *IXP4XX_EXP_CS0 |= IXP4XX_FLASH_WRITABLE; -+ *IXP4XX_EXP_CS1 = *IXP4XX_EXP_CS0; -+ -+ platform_add_devices(pronghorn_devices, ARRAY_SIZE(pronghorn_devices)); -+ -+ if (machine_is_pronghorn()) { -+ pronghorn_pata_resources[0].start = IXP4XX_EXP_BUS_BASE(2); -+ pronghorn_pata_resources[0].end = IXP4XX_EXP_BUS_END(2); -+ -+ pronghorn_pata_resources[1].start = IXP4XX_EXP_BUS_BASE(3); -+ pronghorn_pata_resources[1].end = IXP4XX_EXP_BUS_END(3); -+ -+ pronghorn_pata_data.cs0_cfg = IXP4XX_EXP_CS2; -+ pronghorn_pata_data.cs1_cfg = IXP4XX_EXP_CS3; -+ } else { -+ pronghorn_pata_resources[0].start = IXP4XX_EXP_BUS_BASE(3); -+ pronghorn_pata_resources[0].end = IXP4XX_EXP_BUS_END(3); -+ -+ pronghorn_pata_resources[1].start = IXP4XX_EXP_BUS_BASE(4); -+ pronghorn_pata_resources[1].end = IXP4XX_EXP_BUS_END(4); -+ -+ pronghorn_pata_data.cs0_cfg = IXP4XX_EXP_CS3; -+ pronghorn_pata_data.cs1_cfg = IXP4XX_EXP_CS4; -+ -+ platform_device_register(&pronghorn_i2c_gpio); -+ } -+ -+ platform_device_register(&pronghorn_pata); -+} -+ -+MACHINE_START(PRONGHORN, "ADI Engineering Pronghorn") -+ /* Maintainer: Imre Kaloz */ -+ .phys_io = IXP4XX_PERIPHERAL_BASE_PHYS, -+ .io_pg_offst = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc, -+ .map_io = ixp4xx_map_io, -+ .init_irq = ixp4xx_init_irq, -+ .timer = &ixp4xx_timer, -+ .boot_params = 0x0100, -+ .init_machine = pronghorn_init, -+MACHINE_END -+ -+MACHINE_START(PRONGHORNMETRO, "ADI Engineering Pronghorn Metro") -+ /* Maintainer: Imre Kaloz */ -+ .phys_io = IXP4XX_PERIPHERAL_BASE_PHYS, -+ .io_pg_offst = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc, -+ .map_io = ixp4xx_map_io, -+ .init_irq = ixp4xx_init_irq, -+ .timer = &ixp4xx_timer, -+ .boot_params = 0x0100, -+ .init_machine = pronghorn_init, -+MACHINE_END ---- a/arch/arm/mach-ixp4xx/include/mach/uncompress.h -+++ b/arch/arm/mach-ixp4xx/include/mach/uncompress.h -@@ -41,7 +41,8 @@ static __inline__ void __arch_decomp_set - * Some boards are using UART2 as console - */ - if (machine_is_adi_coyote() || machine_is_gtwx5715() || -- machine_is_gateway7001() || machine_is_wg302v2()) -+ machine_is_gateway7001() || machine_is_wg302v2() || -+ machine_is_pronghorn() || machine_is_pronghorn_metro()) - uart_base = (volatile u32*) IXP4XX_UART2_BASE_PHYS; - else - uart_base = (volatile u32*) IXP4XX_UART1_BASE_PHYS; diff --git a/target/linux/ixp4xx/patches-2.6.28/111-pronghorn_swap_uarts.patch b/target/linux/ixp4xx/patches-2.6.28/111-pronghorn_swap_uarts.patch deleted file mode 100644 index b9fa50768..000000000 --- a/target/linux/ixp4xx/patches-2.6.28/111-pronghorn_swap_uarts.patch +++ /dev/null @@ -1,44 +0,0 @@ ---- a/arch/arm/mach-ixp4xx/pronghorn-setup.c -+++ b/arch/arm/mach-ixp4xx/pronghorn-setup.c -@@ -51,31 +51,31 @@ static struct platform_device pronghorn_ - - static struct resource pronghorn_uart_resources [] = { - { -- .start = IXP4XX_UART1_BASE_PHYS, -- .end = IXP4XX_UART1_BASE_PHYS + 0x0fff, -+ .start = IXP4XX_UART2_BASE_PHYS, -+ .end = IXP4XX_UART2_BASE_PHYS + 0x0fff, - .flags = IORESOURCE_MEM - }, - { -- .start = IXP4XX_UART2_BASE_PHYS, -- .end = IXP4XX_UART2_BASE_PHYS + 0x0fff, -+ .start = IXP4XX_UART1_BASE_PHYS, -+ .end = IXP4XX_UART1_BASE_PHYS + 0x0fff, - .flags = IORESOURCE_MEM - } - }; - - static struct plat_serial8250_port pronghorn_uart_data[] = { - { -- .mapbase = IXP4XX_UART1_BASE_PHYS, -- .membase = (char *)IXP4XX_UART1_BASE_VIRT + REG_OFFSET, -- .irq = IRQ_IXP4XX_UART1, -+ .mapbase = IXP4XX_UART2_BASE_PHYS, -+ .membase = (char *)IXP4XX_UART2_BASE_VIRT + REG_OFFSET, -+ .irq = IRQ_IXP4XX_UART2, - .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST, - .iotype = UPIO_MEM, - .regshift = 2, - .uartclk = IXP4XX_UART_XTAL, - }, - { -- .mapbase = IXP4XX_UART2_BASE_PHYS, -- .membase = (char *)IXP4XX_UART2_BASE_VIRT + REG_OFFSET, -- .irq = IRQ_IXP4XX_UART2, -+ .mapbase = IXP4XX_UART1_BASE_PHYS, -+ .membase = (char *)IXP4XX_UART1_BASE_VIRT + REG_OFFSET, -+ .irq = IRQ_IXP4XX_UART1, - .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST, - .iotype = UPIO_MEM, - .regshift = 2, diff --git a/target/linux/ixp4xx/patches-2.6.28/115-sidewinder_support.patch b/target/linux/ixp4xx/patches-2.6.28/115-sidewinder_support.patch deleted file mode 100644 index af03d33a6..000000000 --- a/target/linux/ixp4xx/patches-2.6.28/115-sidewinder_support.patch +++ /dev/null @@ -1,282 +0,0 @@ -From 60bdaaaf3446b4237566c6e04855186fc7bd766b Mon Sep 17 00:00:00 2001 -From: Imre Kaloz -Date: Sun, 13 Jul 2008 22:46:45 +0200 -Subject: [PATCH] Add support for the ADI Sidewinder - -Signed-off-by: Imre Kaloz ---- - arch/arm/mach-ixp4xx/Kconfig | 10 ++- - arch/arm/mach-ixp4xx/Makefile | 2 + - arch/arm/mach-ixp4xx/sidewinder-pci.c | 68 ++++++++++++++ - arch/arm/mach-ixp4xx/sidewinder-setup.c | 151 +++++++++++++++++++++++++++++++ - 4 files changed, 230 insertions(+), 1 deletions(-) - create mode 100644 arch/arm/mach-ixp4xx/sidewinder-pci.c - create mode 100644 arch/arm/mach-ixp4xx/sidewinder-setup.c - ---- a/arch/arm/mach-ixp4xx/Kconfig -+++ b/arch/arm/mach-ixp4xx/Kconfig -@@ -81,6 +81,14 @@ config MACH_PRONGHORN - config MACH_PRONGHORNMETRO - def_bool MACH_PRONGHORN - -+config MACH_SIDEWINDER -+ bool "ADI Sidewinder" -+ select PCI -+ help -+ Say 'Y' here if you want your kernel to support the ADI -+ Engineering Sidewinder board. For more information on this -+ platform, see http://www.adiengineering.com -+ - config ARCH_IXDP425 - bool "IXDP425" - help -@@ -163,7 +171,7 @@ config MACH_FSG - # - config CPU_IXP46X - bool -- depends on MACH_IXDP465 -+ depends on MACH_IXDP465 || MACH_SIDEWINDER - default y - - config CPU_IXP43X ---- a/arch/arm/mach-ixp4xx/Makefile -+++ b/arch/arm/mach-ixp4xx/Makefile -@@ -18,6 +18,7 @@ obj-pci-$(CONFIG_MACH_WG302V1) += wg302 - obj-pci-$(CONFIG_MACH_WG302V2) += wg302v2-pci.o - obj-pci-$(CONFIG_MACH_FSG) += fsg-pci.o - obj-pci-$(CONFIG_MACH_PRONGHORN) += pronghorn-pci.o -+obj-pci-$(CONFIG_MACH_SIDEWINDER) += sidewinder-pci.o - - obj-y += common.o - -@@ -34,6 +35,7 @@ obj-$(CONFIG_MACH_WG302V1) += wg302v1-se - obj-$(CONFIG_MACH_WG302V2) += wg302v2-setup.o - obj-$(CONFIG_MACH_FSG) += fsg-setup.o - obj-$(CONFIG_MACH_PRONGHORN) += pronghorn-setup.o -+obj-$(CONFIG_MACH_SIDEWINDER) += sidewinder-setup.o - - obj-$(CONFIG_PCI) += $(obj-pci-$(CONFIG_PCI)) common-pci.o - obj-$(CONFIG_IXP4XX_QMGR) += ixp4xx_qmgr.o ---- /dev/null -+++ b/arch/arm/mach-ixp4xx/sidewinder-pci.c -@@ -0,0 +1,68 @@ -+/* -+ * arch/arch/mach-ixp4xx/pronghornmetro-pci.c -+ * -+ * PCI setup routines for ADI Engineering Sidewinder -+ * -+ * Copyright (C) 2008 Imre Kaloz -+ * -+ * based on coyote-pci.c: -+ * Copyright (C) 2002 Jungo Software Technologies. -+ * Copyright (C) 2003 MontaVista Softwrae, Inc. -+ * -+ * Maintainer: Imre Kaloz -+ * -+ * 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 -+#include -+#include -+#include -+ -+#include -+#include -+#include -+ -+#include -+ -+void __init sidewinder_pci_preinit(void) -+{ -+ set_irq_type(IRQ_IXP4XX_GPIO11, IRQ_TYPE_LEVEL_LOW); -+ set_irq_type(IRQ_IXP4XX_GPIO10, IRQ_TYPE_LEVEL_LOW); -+ set_irq_type(IRQ_IXP4XX_GPIO9, IRQ_TYPE_LEVEL_LOW); -+ -+ ixp4xx_pci_preinit(); -+} -+ -+static int __init sidewinder_map_irq(struct pci_dev *dev, u8 slot, u8 pin) -+{ -+ if (slot == 1) -+ return IRQ_IXP4XX_GPIO11; -+ else if (slot == 2) -+ return IRQ_IXP4XX_GPIO10; -+ else if (slot == 3) -+ return IRQ_IXP4XX_GPIO9; -+ else -+ return -1; -+} -+ -+struct hw_pci sidewinder_pci __initdata = { -+ .nr_controllers = 1, -+ .preinit = sidewinder_pci_preinit, -+ .swizzle = pci_std_swizzle, -+ .setup = ixp4xx_setup, -+ .scan = ixp4xx_scan_bus, -+ .map_irq = sidewinder_map_irq, -+}; -+ -+int __init sidewinder_pci_init(void) -+{ -+ if (machine_is_sidewinder()) -+ pci_common_init(&sidewinder_pci); -+ return 0; -+} -+ -+subsys_initcall(sidewinder_pci_init); ---- /dev/null -+++ b/arch/arm/mach-ixp4xx/sidewinder-setup.c -@@ -0,0 +1,149 @@ -+/* -+ * arch/arm/mach-ixp4xx/sidewinder-setup.c -+ * -+ * Board setup for the ADI Engineering Sidewinder -+ * -+ * Copyright (C) 2008 Imre Kaloz -+ * -+ * based on coyote-setup.c: -+ * Copyright (C) 2003-2005 MontaVista Software, Inc. -+ * -+ * Author: Imre Kaloz -+ */ -+ -+#include -+#include -+#include -+ -+#include -+#include -+#include -+ -+static struct flash_platform_data sidewinder_flash_data = { -+ .map_name = "cfi_probe", -+ .width = 2, -+}; -+ -+static struct resource sidewinder_flash_resource = { -+ .flags = IORESOURCE_MEM, -+}; -+ -+static struct platform_device sidewinder_flash = { -+ .name = "IXP4XX-Flash", -+ .id = 0, -+ .dev = { -+ .platform_data = &sidewinder_flash_data, -+ }, -+ .num_resources = 1, -+ .resource = &sidewinder_flash_resource, -+}; -+ -+static struct resource sidewinder_uart_resources[] = { -+ { -+ .start = IXP4XX_UART1_BASE_PHYS, -+ .end = IXP4XX_UART1_BASE_PHYS + 0x0fff, -+ .flags = IORESOURCE_MEM, -+ }, -+ { -+ .start = IXP4XX_UART2_BASE_PHYS, -+ .end = IXP4XX_UART2_BASE_PHYS + 0x0fff, -+ .flags = IORESOURCE_MEM, -+ } -+}; -+ -+static struct plat_serial8250_port sidewinder_uart_data[] = { -+ { -+ .mapbase = IXP4XX_UART1_BASE_PHYS, -+ .membase = (char *)IXP4XX_UART1_BASE_VIRT + REG_OFFSET, -+ .irq = IRQ_IXP4XX_UART1, -+ .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST, -+ .iotype = UPIO_MEM, -+ .regshift = 2, -+ .uartclk = IXP4XX_UART_XTAL, -+ }, -+ { -+ .mapbase = IXP4XX_UART2_BASE_PHYS, -+ .membase = (char *)IXP4XX_UART2_BASE_VIRT + REG_OFFSET, -+ .irq = IRQ_IXP4XX_UART2, -+ .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST, -+ .iotype = UPIO_MEM, -+ .regshift = 2, -+ .uartclk = IXP4XX_UART_XTAL, -+ }, -+ { }, -+}; -+ -+static struct platform_device sidewinder_uart = { -+ .name = "serial8250", -+ .id = PLAT8250_DEV_PLATFORM, -+ .dev = { -+ .platform_data = sidewinder_uart_data, -+ }, -+ .num_resources = ARRAY_SIZE(sidewinder_uart_resources), -+ .resource = sidewinder_uart_resources, -+}; -+ -+static struct eth_plat_info sidewinder_plat_eth[] = { -+ { -+ .phy = 5, -+ .rxq = 3, -+ .txreadyq = 20, -+ }, { -+ .phy = IXP4XX_ETH_PHY_MAX_ADDR, -+ .phy_mask = 0x1e, -+ .rxq = 4, -+ .txreadyq = 21, -+ }, { -+ .phy = 31, -+ .rxq = 2, -+ .txreadyq = 19, -+ } -+}; -+ -+static struct platform_device sidewinder_eth[] = { -+ { -+ .name = "ixp4xx_eth", -+ .id = IXP4XX_ETH_NPEB, -+ .dev.platform_data = sidewinder_plat_eth, -+ }, { -+ .name = "ixp4xx_eth", -+ .id = IXP4XX_ETH_NPEC, -+ .dev.platform_data = sidewinder_plat_eth + 1, -+ }, { -+ .name = "ixp4xx_eth", -+ .id = IXP4XX_ETH_NPEA, -+ .dev.platform_data = sidewinder_plat_eth + 2, -+ } -+}; -+ -+static struct platform_device *sidewinder_devices[] __initdata = { -+ &sidewinder_flash, -+ &sidewinder_uart, -+ &sidewinder_eth[0], -+ &sidewinder_eth[1], -+ &sidewinder_eth[2], -+}; -+ -+static void __init sidewinder_init(void) -+{ -+ ixp4xx_sys_init(); -+ -+ sidewinder_flash_resource.start = IXP4XX_EXP_BUS_BASE(0); -+ sidewinder_flash_resource.end = IXP4XX_EXP_BUS_BASE(0) + SZ_64M - 1; -+ -+ *IXP4XX_EXP_CS0 |= IXP4XX_FLASH_WRITABLE; -+ *IXP4XX_EXP_CS1 = *IXP4XX_EXP_CS0; -+ -+ platform_add_devices(sidewinder_devices, ARRAY_SIZE(sidewinder_devices)); -+} -+ -+MACHINE_START(SIDEWINDER, "ADI Engineering Sidewinder") -+ /* Maintainer: Imre Kaloz */ -+ .phys_io = IXP4XX_PERIPHERAL_BASE_PHYS, -+ .io_pg_offst = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc, -+ .map_io = ixp4xx_map_io, -+ .init_irq = ixp4xx_init_irq, -+ .timer = &ixp4xx_timer, -+ .boot_params = 0x0100, -+ .init_machine = sidewinder_init, -+MACHINE_END diff --git a/target/linux/ixp4xx/patches-2.6.28/116-sidewinder_fis_location.patch b/target/linux/ixp4xx/patches-2.6.28/116-sidewinder_fis_location.patch deleted file mode 100644 index 1d0a98398..000000000 --- a/target/linux/ixp4xx/patches-2.6.28/116-sidewinder_fis_location.patch +++ /dev/null @@ -1,30 +0,0 @@ ---- a/drivers/mtd/redboot.c -+++ b/drivers/mtd/redboot.c -@@ -13,6 +13,8 @@ - - #define BOARD_CONFIG_PART "boardconfig" - -+#include -+ - struct fis_image_desc { - unsigned char name[16]; // Null terminated name - uint32_t flash_base; // Address within FLASH of image -@@ -30,7 +32,8 @@ struct fis_list { - struct fis_list *next; - }; - --static int directory = CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK; -+int directory = CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK; -+ - module_param(directory, int, 0); - - static inline int redboot_checksum(struct fis_image_desc *img) -@@ -59,6 +62,8 @@ static int parse_redboot_partitions(stru - #ifdef CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED - static char nullstring[] = "unallocated"; - #endif -+ if (machine_is_sidewinder()) -+ directory = -5; - - if ( directory < 0 ) { - offset = master->size + directory * master->erasesize; diff --git a/target/linux/ixp4xx/patches-2.6.28/120-compex_support.patch b/target/linux/ixp4xx/patches-2.6.28/120-compex_support.patch deleted file mode 100644 index 571a480ff..000000000 --- a/target/linux/ixp4xx/patches-2.6.28/120-compex_support.patch +++ /dev/null @@ -1,212 +0,0 @@ -From 24025a2dcf1248079dd3019fac6ed955252d277f Mon Sep 17 00:00:00 2001 -From: Imre Kaloz -Date: Mon, 14 Jul 2008 21:56:34 +0200 -Subject: [PATCH] Add support for the Compex WP18 / NP18A boards - -Signed-off-by: Imre Kaloz ---- - arch/arm/mach-ixp4xx/Kconfig | 8 ++ - arch/arm/mach-ixp4xx/Makefile | 2 + - arch/arm/mach-ixp4xx/compex-setup.c | 136 +++++++++++++++++++++++++++++++++++ - arch/arm/mach-ixp4xx/ixdp425-pci.c | 3 +- - arch/arm/tools/mach-types | 2 +- - 5 files changed, 149 insertions(+), 2 deletions(-) - create mode 100644 arch/arm/mach-ixp4xx/compex-setup.c - ---- a/arch/arm/mach-ixp4xx/Kconfig -+++ b/arch/arm/mach-ixp4xx/Kconfig -@@ -89,6 +89,14 @@ config MACH_SIDEWINDER - Engineering Sidewinder board. For more information on this - platform, see http://www.adiengineering.com - -+config MACH_COMPEX -+ bool "Compex WP18 / NP18A" -+ select PCI -+ help -+ Say 'Y' here if you want your kernel to support Compex' -+ WP18 or NP18A boards. For more information on this -+ platform, see http://www.compex.com.sg/home/OEM/product_ap.htm -+ - config ARCH_IXDP425 - bool "IXDP425" - help ---- a/arch/arm/mach-ixp4xx/Makefile -+++ b/arch/arm/mach-ixp4xx/Makefile -@@ -19,6 +19,7 @@ obj-pci-$(CONFIG_MACH_WG302V2) += wg302 - obj-pci-$(CONFIG_MACH_FSG) += fsg-pci.o - obj-pci-$(CONFIG_MACH_PRONGHORN) += pronghorn-pci.o - obj-pci-$(CONFIG_MACH_SIDEWINDER) += sidewinder-pci.o -+obj-pci-$(CONFIG_MACH_COMPEX) += ixdp425-pci.o - - obj-y += common.o - -@@ -36,6 +37,7 @@ obj-$(CONFIG_MACH_WG302V2) += wg302v2-se - obj-$(CONFIG_MACH_FSG) += fsg-setup.o - obj-$(CONFIG_MACH_PRONGHORN) += pronghorn-setup.o - obj-$(CONFIG_MACH_SIDEWINDER) += sidewinder-setup.o -+obj-$(CONFIG_MACH_COMPEX) += compex-setup.o - - obj-$(CONFIG_PCI) += $(obj-pci-$(CONFIG_PCI)) common-pci.o - obj-$(CONFIG_IXP4XX_QMGR) += ixp4xx_qmgr.o ---- /dev/null -+++ b/arch/arm/mach-ixp4xx/compex-setup.c -@@ -0,0 +1,136 @@ -+/* -+ * arch/arm/mach-ixp4xx/compex-setup.c -+ * -+ * Compex WP18 / NP18A board-setup -+ * -+ * Copyright (C) 2008 Imre Kaloz -+ * -+ * based on coyote-setup.c: -+ * Copyright (C) 2003-2005 MontaVista Software, Inc. -+ * -+ * Author: Imre Kaloz -+ */ -+ -+#include -+#include -+#include -+ -+#include -+#include -+#include -+ -+static struct flash_platform_data compex_flash_data = { -+ .map_name = "cfi_probe", -+ .width = 2, -+}; -+ -+static struct resource compex_flash_resource = { -+ .flags = IORESOURCE_MEM, -+}; -+ -+static struct platform_device compex_flash = { -+ .name = "IXP4XX-Flash", -+ .id = 0, -+ .dev = { -+ .platform_data = &compex_flash_data, -+ }, -+ .num_resources = 1, -+ .resource = &compex_flash_resource, -+}; -+ -+static struct resource compex_uart_resources[] = { -+ { -+ .start = IXP4XX_UART1_BASE_PHYS, -+ .end = IXP4XX_UART1_BASE_PHYS + 0x0fff, -+ .flags = IORESOURCE_MEM -+ }, -+ { -+ .start = IXP4XX_UART2_BASE_PHYS, -+ .end = IXP4XX_UART2_BASE_PHYS + 0x0fff, -+ .flags = IORESOURCE_MEM -+ } -+}; -+ -+static struct plat_serial8250_port compex_uart_data[] = { -+ { -+ .mapbase = IXP4XX_UART1_BASE_PHYS, -+ .membase = (char *)IXP4XX_UART1_BASE_VIRT + REG_OFFSET, -+ .irq = IRQ_IXP4XX_UART1, -+ .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST, -+ .iotype = UPIO_MEM, -+ .regshift = 2, -+ .uartclk = IXP4XX_UART_XTAL, -+ }, -+ { -+ .mapbase = IXP4XX_UART2_BASE_PHYS, -+ .membase = (char *)IXP4XX_UART2_BASE_VIRT + REG_OFFSET, -+ .irq = IRQ_IXP4XX_UART2, -+ .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST, -+ .iotype = UPIO_MEM, -+ .regshift = 2, -+ .uartclk = IXP4XX_UART_XTAL, -+ }, -+ { }, -+}; -+ -+static struct platform_device compex_uart = { -+ .name = "serial8250", -+ .id = PLAT8250_DEV_PLATFORM, -+ .dev.platform_data = compex_uart_data, -+ .num_resources = 2, -+ .resource = compex_uart_resources, -+}; -+ -+static struct eth_plat_info compex_plat_eth[] = { -+ { -+ .phy = IXP4XX_ETH_PHY_MAX_ADDR, -+ .phy_mask = 0xf0000, -+ .rxq = 3, -+ .txreadyq = 20, -+ }, { -+ .phy = 3, -+ .rxq = 4, -+ .txreadyq = 21, -+ } -+}; -+ -+static struct platform_device compex_eth[] = { -+ { -+ .name = "ixp4xx_eth", -+ .id = IXP4XX_ETH_NPEB, -+ .dev.platform_data = compex_plat_eth, -+ }, { -+ .name = "ixp4xx_eth", -+ .id = IXP4XX_ETH_NPEC, -+ .dev.platform_data = compex_plat_eth + 1, -+ } -+}; -+ -+static struct platform_device *compex_devices[] __initdata = { -+ &compex_flash, -+ &compex_uart, -+ &compex_eth[0], -+ &compex_eth[1], -+}; -+ -+static void __init compex_init(void) -+{ -+ ixp4xx_sys_init(); -+ -+ compex_flash_resource.start = IXP4XX_EXP_BUS_BASE(0); -+ compex_flash_resource.end = -+ IXP4XX_EXP_BUS_BASE(0) + SZ_32M - 1; -+ -+ platform_add_devices(compex_devices, ARRAY_SIZE(compex_devices)); -+} -+ -+MACHINE_START(COMPEX, "Compex WP18 / NP18A") -+ /* Maintainer: Imre Kaloz */ -+ .phys_io = IXP4XX_PERIPHERAL_BASE_PHYS, -+ .io_pg_offst = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc, -+ .map_io = ixp4xx_map_io, -+ .init_irq = ixp4xx_init_irq, -+ .timer = &ixp4xx_timer, -+ .boot_params = 0x0100, -+ .init_machine = compex_init, -+MACHINE_END ---- a/arch/arm/mach-ixp4xx/ixdp425-pci.c -+++ b/arch/arm/mach-ixp4xx/ixdp425-pci.c -@@ -66,7 +66,8 @@ struct hw_pci ixdp425_pci __initdata = { - int __init ixdp425_pci_init(void) - { - if (machine_is_ixdp425() || machine_is_ixcdp1100() || -- machine_is_ixdp465() || machine_is_kixrp435()) -+ machine_is_ixdp465() || machine_is_kixrp435() || -+ machine_is_compex()) - pci_common_init(&ixdp425_pci); - return 0; - } ---- a/arch/arm/tools/mach-types -+++ b/arch/arm/tools/mach-types -@@ -1273,7 +1273,7 @@ oiab MACH_OIAB OIAB 1269 - smdk6400 MACH_SMDK6400 SMDK6400 1270 - nokia_n800 MACH_NOKIA_N800 NOKIA_N800 1271 - greenphone MACH_GREENPHONE GREENPHONE 1272 --compex42x MACH_COMPEXWP18 COMPEXWP18 1273 -+compex MACH_COMPEX COMPEX 1273 - xmate MACH_XMATE XMATE 1274 - energizer MACH_ENERGIZER ENERGIZER 1275 - ime1 MACH_IME1 IME1 1276 diff --git a/target/linux/ixp4xx/patches-2.6.28/130-wrt300nv2_support.patch b/target/linux/ixp4xx/patches-2.6.28/130-wrt300nv2_support.patch deleted file mode 100644 index 48d5ee291..000000000 --- a/target/linux/ixp4xx/patches-2.6.28/130-wrt300nv2_support.patch +++ /dev/null @@ -1,225 +0,0 @@ ---- a/arch/arm/mach-ixp4xx/Kconfig -+++ b/arch/arm/mach-ixp4xx/Kconfig -@@ -97,6 +97,14 @@ config MACH_COMPEX - WP18 or NP18A boards. For more information on this - platform, see http://www.compex.com.sg/home/OEM/product_ap.htm - -+config MACH_WRT300NV2 -+ bool "Linksys WRT300N v2" -+ select PCI -+ help -+ Say 'Y' here if you want your kernel to support Linksys' -+ WRT300N v2 router. For more information on this -+ platform, see http://openwrt.org -+ - config ARCH_IXDP425 - bool "IXDP425" - help ---- a/arch/arm/mach-ixp4xx/Makefile -+++ b/arch/arm/mach-ixp4xx/Makefile -@@ -20,6 +20,7 @@ obj-pci-$(CONFIG_MACH_FSG) += fsg-pci.o - obj-pci-$(CONFIG_MACH_PRONGHORN) += pronghorn-pci.o - obj-pci-$(CONFIG_MACH_SIDEWINDER) += sidewinder-pci.o - obj-pci-$(CONFIG_MACH_COMPEX) += ixdp425-pci.o -+obj-pci-$(CONFIG_MACH_WRT300NV2) += wrt300nv2-pci.o - - obj-y += common.o - -@@ -38,6 +39,7 @@ obj-$(CONFIG_MACH_FSG) += fsg-setup.o - obj-$(CONFIG_MACH_PRONGHORN) += pronghorn-setup.o - obj-$(CONFIG_MACH_SIDEWINDER) += sidewinder-setup.o - obj-$(CONFIG_MACH_COMPEX) += compex-setup.o -+obj-$(CONFIG_MACH_WRT300NV2) += wrt300nv2-setup.o - - obj-$(CONFIG_PCI) += $(obj-pci-$(CONFIG_PCI)) common-pci.o - obj-$(CONFIG_IXP4XX_QMGR) += ixp4xx_qmgr.o ---- /dev/null -+++ b/arch/arm/mach-ixp4xx/wrt300nv2-pci.c -@@ -0,0 +1,65 @@ -+/* -+ * arch/arch/mach-ixp4xx/wrt300nv2-pci.c -+ * -+ * PCI setup routines for Linksys WRT300N v2 -+ * -+ * Copyright (C) 2007 Imre Kaloz -+ * -+ * based on coyote-pci.c: -+ * Copyright (C) 2002 Jungo Software Technologies. -+ * Copyright (C) 2003 MontaVista Softwrae, Inc. -+ * -+ * Maintainer: Imre Kaloz -+ * -+ * 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 -+#include -+#include -+#include -+ -+#include -+#include -+#include -+ -+#include -+ -+extern void ixp4xx_pci_preinit(void); -+extern int ixp4xx_setup(int nr, struct pci_sys_data *sys); -+extern struct pci_bus *ixp4xx_scan_bus(int nr, struct pci_sys_data *sys); -+ -+void __init wrt300nv2_pci_preinit(void) -+{ -+ set_irq_type(IRQ_IXP4XX_GPIO8, IRQ_TYPE_LEVEL_LOW); -+ -+ ixp4xx_pci_preinit(); -+} -+ -+static int __init wrt300nv2_map_irq(struct pci_dev *dev, u8 slot, u8 pin) -+{ -+ if (slot == 1) -+ return IRQ_IXP4XX_GPIO8; -+ else return -1; -+} -+ -+struct hw_pci wrt300nv2_pci __initdata = { -+ .nr_controllers = 1, -+ .preinit = wrt300nv2_pci_preinit, -+ .swizzle = pci_std_swizzle, -+ .setup = ixp4xx_setup, -+ .scan = ixp4xx_scan_bus, -+ .map_irq = wrt300nv2_map_irq, -+}; -+ -+int __init wrt300nv2_pci_init(void) -+{ -+ if (machine_is_wrt300nv2()) -+ pci_common_init(&wrt300nv2_pci); -+ return 0; -+} -+ -+subsys_initcall(wrt300nv2_pci_init); ---- /dev/null -+++ b/arch/arm/mach-ixp4xx/wrt300nv2-setup.c -@@ -0,0 +1,108 @@ -+/* -+ * arch/arm/mach-ixp4xx/wrt300nv2-setup.c -+ * -+ * Board setup for the Linksys WRT300N v2 -+ * -+ * Copyright (C) 2007 Imre Kaloz -+ * -+ * based on coyote-setup.c: -+ * Copyright (C) 2003-2005 MontaVista Software, Inc. -+ * -+ * Author: Imre Kaloz -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+static struct flash_platform_data wrt300nv2_flash_data = { -+ .map_name = "cfi_probe", -+ .width = 2, -+}; -+ -+static struct resource wrt300nv2_flash_resource = { -+ .flags = IORESOURCE_MEM, -+}; -+ -+static struct platform_device wrt300nv2_flash = { -+ .name = "IXP4XX-Flash", -+ .id = 0, -+ .dev = { -+ .platform_data = &wrt300nv2_flash_data, -+ }, -+ .num_resources = 1, -+ .resource = &wrt300nv2_flash_resource, -+}; -+ -+static struct resource wrt300nv2_uart_resource = { -+ .start = IXP4XX_UART2_BASE_PHYS, -+ .end = IXP4XX_UART2_BASE_PHYS + 0x0fff, -+ .flags = IORESOURCE_MEM, -+}; -+ -+static struct plat_serial8250_port wrt300nv2_uart_data[] = { -+ { -+ .mapbase = IXP4XX_UART2_BASE_PHYS, -+ .membase = (char *)IXP4XX_UART2_BASE_VIRT + REG_OFFSET, -+ .irq = IRQ_IXP4XX_UART2, -+ .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST, -+ .iotype = UPIO_MEM, -+ .regshift = 2, -+ .uartclk = IXP4XX_UART_XTAL, -+ }, -+ { }, -+}; -+ -+static struct platform_device wrt300nv2_uart = { -+ .name = "serial8250", -+ .id = PLAT8250_DEV_PLATFORM, -+ .dev = { -+ .platform_data = wrt300nv2_uart_data, -+ }, -+ .num_resources = 1, -+ .resource = &wrt300nv2_uart_resource, -+}; -+ -+static struct platform_device *wrt300nv2_devices[] __initdata = { -+ &wrt300nv2_flash, -+ &wrt300nv2_uart -+}; -+ -+static void __init wrt300nv2_init(void) -+{ -+ ixp4xx_sys_init(); -+ -+ wrt300nv2_flash_resource.start = IXP4XX_EXP_BUS_BASE(0); -+ wrt300nv2_flash_resource.end = IXP4XX_EXP_BUS_BASE(0) + SZ_32M - 1; -+ -+ *IXP4XX_EXP_CS0 |= IXP4XX_FLASH_WRITABLE; -+ *IXP4XX_EXP_CS1 = *IXP4XX_EXP_CS0; -+ -+ platform_add_devices(wrt300nv2_devices, ARRAY_SIZE(wrt300nv2_devices)); -+} -+ -+#ifdef CONFIG_MACH_WRT300NV2 -+MACHINE_START(WRT300NV2, "Linksys WRT300N v2") -+ /* Maintainer: Imre Kaloz */ -+ .phys_io = IXP4XX_PERIPHERAL_BASE_PHYS, -+ .io_pg_offst = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc, -+ .map_io = ixp4xx_map_io, -+ .init_irq = ixp4xx_init_irq, -+ .timer = &ixp4xx_timer, -+ .boot_params = 0x0100, -+ .init_machine = wrt300nv2_init, -+MACHINE_END -+#endif ---- a/arch/arm/mach-ixp4xx/include/mach/uncompress.h -+++ b/arch/arm/mach-ixp4xx/include/mach/uncompress.h -@@ -42,7 +42,7 @@ static __inline__ void __arch_decomp_set - */ - if (machine_is_adi_coyote() || machine_is_gtwx5715() || - machine_is_gateway7001() || machine_is_wg302v2() || -- machine_is_pronghorn() || machine_is_pronghorn_metro()) -+ machine_is_pronghorn() || machine_is_pronghorn_metro() || machine_is_wrt300nv2()) - uart_base = (volatile u32*) IXP4XX_UART2_BASE_PHYS; - else - uart_base = (volatile u32*) IXP4XX_UART1_BASE_PHYS; diff --git a/target/linux/ixp4xx/patches-2.6.28/131-wrt300nv2_mac_plat_info.patch b/target/linux/ixp4xx/patches-2.6.28/131-wrt300nv2_mac_plat_info.patch deleted file mode 100644 index 3ab68c4f3..000000000 --- a/target/linux/ixp4xx/patches-2.6.28/131-wrt300nv2_mac_plat_info.patch +++ /dev/null @@ -1,40 +0,0 @@ ---- a/arch/arm/mach-ixp4xx/wrt300nv2-setup.c -+++ b/arch/arm/mach-ixp4xx/wrt300nv2-setup.c -@@ -76,9 +76,36 @@ static struct platform_device wrt300nv2_ - .resource = &wrt300nv2_uart_resource, - }; - -+/* Built-in 10/100 Ethernet MAC interfaces */ -+static struct eth_plat_info wrt300nv2_plat_eth[] = { -+ { -+ .phy = -1, -+ .rxq = 3, -+ .txreadyq = 20, -+ }, { -+ .phy = 1, -+ .rxq = 4, -+ .txreadyq = 21, -+ } -+}; -+ -+static struct platform_device wrt300nv2_eth[] = { -+ { -+ .name = "ixp4xx_eth", -+ .id = IXP4XX_ETH_NPEB, -+ .dev.platform_data = wrt300nv2_plat_eth, -+ }, { -+ .name = "ixp4xx_eth", -+ .id = IXP4XX_ETH_NPEC, -+ .dev.platform_data = wrt300nv2_plat_eth + 1, -+ } -+}; -+ - static struct platform_device *wrt300nv2_devices[] __initdata = { - &wrt300nv2_flash, -- &wrt300nv2_uart -+ &wrt300nv2_uart, -+ &wrt300nv2_eth[0], -+ &wrt300nv2_eth[1], - }; - - static void __init wrt300nv2_init(void) diff --git a/target/linux/ixp4xx/patches-2.6.28/150-lanready_ap1000_support.patch b/target/linux/ixp4xx/patches-2.6.28/150-lanready_ap1000_support.patch deleted file mode 100644 index 283bbf836..000000000 --- a/target/linux/ixp4xx/patches-2.6.28/150-lanready_ap1000_support.patch +++ /dev/null @@ -1,200 +0,0 @@ ---- /dev/null -+++ b/arch/arm/mach-ixp4xx/ap1000-setup.c -@@ -0,0 +1,151 @@ -+/* -+ * arch/arm/mach-ixp4xx/ap1000-setup.c -+ * -+ * Lanready AP-1000 -+ * -+ * Copyright (C) 2007 Imre Kaloz -+ * -+ * based on ixdp425-setup.c: -+ * Copyright (C) 2003-2005 MontaVista Software, Inc. -+ * -+ * Author: Imre Kaloz -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+static struct flash_platform_data ap1000_flash_data = { -+ .map_name = "cfi_probe", -+ .width = 2, -+}; -+ -+static struct resource ap1000_flash_resource = { -+ .flags = IORESOURCE_MEM, -+}; -+ -+static struct platform_device ap1000_flash = { -+ .name = "IXP4XX-Flash", -+ .id = 0, -+ .dev = { -+ .platform_data = &ap1000_flash_data, -+ }, -+ .num_resources = 1, -+ .resource = &ap1000_flash_resource, -+}; -+ -+static struct resource ap1000_uart_resources[] = { -+ { -+ .start = IXP4XX_UART1_BASE_PHYS, -+ .end = IXP4XX_UART1_BASE_PHYS + 0x0fff, -+ .flags = IORESOURCE_MEM -+ }, -+ { -+ .start = IXP4XX_UART2_BASE_PHYS, -+ .end = IXP4XX_UART2_BASE_PHYS + 0x0fff, -+ .flags = IORESOURCE_MEM -+ } -+}; -+ -+static struct plat_serial8250_port ap1000_uart_data[] = { -+ { -+ .mapbase = IXP4XX_UART1_BASE_PHYS, -+ .membase = (char *)IXP4XX_UART1_BASE_VIRT + REG_OFFSET, -+ .irq = IRQ_IXP4XX_UART1, -+ .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST, -+ .iotype = UPIO_MEM, -+ .regshift = 2, -+ .uartclk = IXP4XX_UART_XTAL, -+ }, -+ { -+ .mapbase = IXP4XX_UART2_BASE_PHYS, -+ .membase = (char *)IXP4XX_UART2_BASE_VIRT + REG_OFFSET, -+ .irq = IRQ_IXP4XX_UART2, -+ .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST, -+ .iotype = UPIO_MEM, -+ .regshift = 2, -+ .uartclk = IXP4XX_UART_XTAL, -+ }, -+ { }, -+}; -+ -+static struct platform_device ap1000_uart = { -+ .name = "serial8250", -+ .id = PLAT8250_DEV_PLATFORM, -+ .dev.platform_data = ap1000_uart_data, -+ .num_resources = 2, -+ .resource = ap1000_uart_resources -+}; -+ -+static struct platform_device *ap1000_devices[] __initdata = { -+ &ap1000_flash, -+ &ap1000_uart -+}; -+ -+static char ap1000_mem_fixup[] __initdata = "mem=64M "; -+ -+static void __init ap1000_fixup(struct machine_desc *desc, -+ struct tag *tags, char **cmdline, struct meminfo *mi) -+ -+{ -+ struct tag *t = tags; -+ char *p = *cmdline; -+ -+ /* Find the end of the tags table, taking note of any cmdline tag. */ -+ for (; t->hdr.size; t = tag_next(t)) { -+ if (t->hdr.tag == ATAG_CMDLINE) { -+ p = t->u.cmdline.cmdline; -+ } -+ } -+ -+ /* Overwrite the end of the table with a new cmdline tag. */ -+ t->hdr.tag = ATAG_CMDLINE; -+ t->hdr.size = (sizeof (struct tag_header) + -+ strlen(ap1000_mem_fixup) + strlen(p) + 1 + 4) >> 2; -+ strlcpy(t->u.cmdline.cmdline, ap1000_mem_fixup, COMMAND_LINE_SIZE); -+ strlcpy(t->u.cmdline.cmdline + strlen(ap1000_mem_fixup), p, -+ COMMAND_LINE_SIZE - strlen(ap1000_mem_fixup)); -+ -+ /* Terminate the table. */ -+ t = tag_next(t); -+ t->hdr.tag = ATAG_NONE; -+ t->hdr.size = 0; -+} -+ -+static void __init ap1000_init(void) -+{ -+ ixp4xx_sys_init(); -+ -+ ap1000_flash_resource.start = IXP4XX_EXP_BUS_BASE(0); -+ ap1000_flash_resource.end = -+ IXP4XX_EXP_BUS_BASE(0) + ixp4xx_exp_bus_size - 1; -+ -+ platform_add_devices(ap1000_devices, ARRAY_SIZE(ap1000_devices)); -+} -+ -+#ifdef CONFIG_MACH_AP1000 -+MACHINE_START(AP1000, "Lanready AP-1000") -+ /* Maintainer: Imre Kaloz */ -+ .phys_io = IXP4XX_PERIPHERAL_BASE_PHYS, -+ .io_pg_offst = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc, -+ .fixup = ap1000_fixup, -+ .map_io = ixp4xx_map_io, -+ .init_irq = ixp4xx_init_irq, -+ .timer = &ixp4xx_timer, -+ .boot_params = 0x0100, -+ .init_machine = ap1000_init, -+MACHINE_END -+#endif ---- a/arch/arm/mach-ixp4xx/ixdp425-pci.c -+++ b/arch/arm/mach-ixp4xx/ixdp425-pci.c -@@ -67,7 +67,7 @@ int __init ixdp425_pci_init(void) - { - if (machine_is_ixdp425() || machine_is_ixcdp1100() || - machine_is_ixdp465() || machine_is_kixrp435() || -- machine_is_compex()) -+ machine_is_compex() || machine_is_ap1000()) - pci_common_init(&ixdp425_pci); - return 0; - } ---- a/arch/arm/mach-ixp4xx/Kconfig -+++ b/arch/arm/mach-ixp4xx/Kconfig -@@ -105,6 +105,14 @@ config MACH_WRT300NV2 - WRT300N v2 router. For more information on this - platform, see http://openwrt.org - -+config MACH_AP1000 -+ bool "Lanready AP-1000" -+ select PCI -+ help -+ Say 'Y' here if you want your kernel to support Lanready's -+ AP1000 board. For more information on this -+ platform, see http://openwrt.org -+ - config ARCH_IXDP425 - bool "IXDP425" - help ---- a/arch/arm/mach-ixp4xx/Makefile -+++ b/arch/arm/mach-ixp4xx/Makefile -@@ -21,6 +21,7 @@ obj-pci-$(CONFIG_MACH_PRONGHORN) += pron - obj-pci-$(CONFIG_MACH_SIDEWINDER) += sidewinder-pci.o - obj-pci-$(CONFIG_MACH_COMPEX) += ixdp425-pci.o - obj-pci-$(CONFIG_MACH_WRT300NV2) += wrt300nv2-pci.o -+obj-pci-$(CONFIG_MACH_AP1000) += ixdp425-pci.o - - obj-y += common.o - -@@ -40,6 +41,7 @@ obj-$(CONFIG_MACH_PRONGHORN) += pronghor - obj-$(CONFIG_MACH_SIDEWINDER) += sidewinder-setup.o - obj-$(CONFIG_MACH_COMPEX) += compex-setup.o - obj-$(CONFIG_MACH_WRT300NV2) += wrt300nv2-setup.o -+obj-$(CONFIG_MACH_AP1000) += ap1000-setup.o - - obj-$(CONFIG_PCI) += $(obj-pci-$(CONFIG_PCI)) common-pci.o - obj-$(CONFIG_IXP4XX_QMGR) += ixp4xx_qmgr.o diff --git a/target/linux/ixp4xx/patches-2.6.28/151-lanready_ap1000_mac_plat_info.patch b/target/linux/ixp4xx/patches-2.6.28/151-lanready_ap1000_mac_plat_info.patch deleted file mode 100644 index a1214d567..000000000 --- a/target/linux/ixp4xx/patches-2.6.28/151-lanready_ap1000_mac_plat_info.patch +++ /dev/null @@ -1,41 +0,0 @@ ---- a/arch/arm/mach-ixp4xx/ap1000-setup.c -+++ b/arch/arm/mach-ixp4xx/ap1000-setup.c -@@ -90,9 +90,37 @@ static struct platform_device ap1000_uar - .resource = ap1000_uart_resources - }; - -+/* Built-in 10/100 Ethernet MAC interfaces */ -+static struct eth_plat_info ap1000_plat_eth[] = { -+ { -+ .phy = IXP4XX_ETH_PHY_MAX_ADDR, -+ .phy_mask = 0x1e, -+ .rxq = 3, -+ .txreadyq = 20, -+ }, { -+ .phy = 5, -+ .rxq = 4, -+ .txreadyq = 21, -+ } -+}; -+ -+static struct platform_device ap1000_eth[] = { -+ { -+ .name = "ixp4xx_eth", -+ .id = IXP4XX_ETH_NPEB, -+ .dev.platform_data = ap1000_plat_eth, -+ }, { -+ .name = "ixp4xx_eth", -+ .id = IXP4XX_ETH_NPEC, -+ .dev.platform_data = ap1000_plat_eth + 1, -+ } -+}; -+ - static struct platform_device *ap1000_devices[] __initdata = { - &ap1000_flash, -- &ap1000_uart -+ &ap1000_uart, -+ &ap1000_eth[0], -+ &ap1000_eth[1], - }; - - static char ap1000_mem_fixup[] __initdata = "mem=64M "; diff --git a/target/linux/ixp4xx/patches-2.6.28/162-wg302v1_mem_fixup.patch b/target/linux/ixp4xx/patches-2.6.28/162-wg302v1_mem_fixup.patch deleted file mode 100644 index 684db4475..000000000 --- a/target/linux/ixp4xx/patches-2.6.28/162-wg302v1_mem_fixup.patch +++ /dev/null @@ -1,47 +0,0 @@ ---- a/arch/arm/mach-ixp4xx/wg302v1-setup.c -+++ b/arch/arm/mach-ixp4xx/wg302v1-setup.c -@@ -115,6 +115,36 @@ static struct platform_device *wg302v1_d - &wg302v1_eth[0], - }; - -+static char wg302v1_mem_fixup[] __initdata = "mem=32M "; -+ -+static void __init wg302v1_fixup(struct machine_desc *desc, -+ struct tag *tags, char **cmdline, struct meminfo *mi) -+ -+{ -+ struct tag *t = tags; -+ char *p = *cmdline; -+ -+ /* Find the end of the tags table, taking note of any cmdline tag. */ -+ for (; t->hdr.size; t = tag_next(t)) { -+ if (t->hdr.tag == ATAG_CMDLINE) { -+ p = t->u.cmdline.cmdline; -+ } -+ } -+ -+ /* Overwrite the end of the table with a new cmdline tag. */ -+ t->hdr.tag = ATAG_CMDLINE; -+ t->hdr.size = (sizeof (struct tag_header) + -+ strlen(wg302v1_mem_fixup) + strlen(p) + 1 + 4) >> 2; -+ strlcpy(t->u.cmdline.cmdline, wg302v1_mem_fixup, COMMAND_LINE_SIZE); -+ strlcpy(t->u.cmdline.cmdline + strlen(wg302v1_mem_fixup), p, -+ COMMAND_LINE_SIZE - strlen(wg302v1_mem_fixup)); -+ -+ /* Terminate the table. */ -+ t = tag_next(t); -+ t->hdr.tag = ATAG_NONE; -+ t->hdr.size = 0; -+} -+ - static void __init wg302v1_init(void) - { - ixp4xx_sys_init(); -@@ -133,6 +163,7 @@ MACHINE_START(WG302V1, "Netgear WG302 v1 - /* Maintainer: Imre Kaloz */ - .phys_io = IXP4XX_PERIPHERAL_BASE_PHYS, - .io_pg_offst = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc, -+ .fixup = wg302v1_fixup, - .map_io = ixp4xx_map_io, - .init_irq = ixp4xx_init_irq, - .timer = &ixp4xx_timer, diff --git a/target/linux/ixp4xx/patches-2.6.28/170-ixdpg425_mac_plat_info.patch b/target/linux/ixp4xx/patches-2.6.28/170-ixdpg425_mac_plat_info.patch deleted file mode 100644 index 772b697aa..000000000 --- a/target/linux/ixp4xx/patches-2.6.28/170-ixdpg425_mac_plat_info.patch +++ /dev/null @@ -1,41 +0,0 @@ ---- a/arch/arm/mach-ixp4xx/coyote-setup.c -+++ b/arch/arm/mach-ixp4xx/coyote-setup.c -@@ -73,9 +73,37 @@ static struct platform_device coyote_uar - .resource = &coyote_uart_resource, - }; - -+/* Built-in 10/100 Ethernet MAC interfaces */ -+static struct eth_plat_info ixdpg425_plat_eth[] = { -+ { -+ .phy = 5, -+ .rxq = 3, -+ .txreadyq = 20, -+ }, { -+ .phy = 4, -+ .rxq = 4, -+ .txreadyq = 21, -+ } -+}; -+ -+static struct platform_device ixdpg425_eth[] = { -+ { -+ .name = "ixp4xx_eth", -+ .id = IXP4XX_ETH_NPEB, -+ .dev.platform_data = ixdpg425_plat_eth, -+ }, { -+ .name = "ixp4xx_eth", -+ .id = IXP4XX_ETH_NPEC, -+ .dev.platform_data = ixdpg425_plat_eth + 1, -+ } -+}; -+ -+ - static struct platform_device *coyote_devices[] __initdata = { - &coyote_flash, -- &coyote_uart -+ &coyote_uart, -+ &ixdpg425_eth[0], -+ &ixdpg425_eth[1], - }; - - static void __init coyote_init(void) diff --git a/target/linux/ixp4xx/patches-2.6.28/180-tw5334_support.patch b/target/linux/ixp4xx/patches-2.6.28/180-tw5334_support.patch deleted file mode 100644 index 81010f9e8..000000000 --- a/target/linux/ixp4xx/patches-2.6.28/180-tw5334_support.patch +++ /dev/null @@ -1,284 +0,0 @@ ---- a/arch/arm/mach-ixp4xx/Kconfig -+++ b/arch/arm/mach-ixp4xx/Kconfig -@@ -158,6 +158,14 @@ config ARCH_PRPMC1100 - PrPCM1100 Processor Mezanine Module. For more information on - this platform, see . - -+config MACH_TW5334 -+ bool "Titan Wireless TW-533-4" -+ select PCI -+ help -+ Say 'Y' here if you want your kernel to support the Titan -+ Wireless TW533-4. For more information on this platform, -+ see http://openwrt.org -+ - config MACH_NAS100D - bool - prompt "NAS100D" ---- a/arch/arm/mach-ixp4xx/Makefile -+++ b/arch/arm/mach-ixp4xx/Makefile -@@ -22,6 +22,7 @@ obj-pci-$(CONFIG_MACH_SIDEWINDER) += sid - obj-pci-$(CONFIG_MACH_COMPEX) += ixdp425-pci.o - obj-pci-$(CONFIG_MACH_WRT300NV2) += wrt300nv2-pci.o - obj-pci-$(CONFIG_MACH_AP1000) += ixdp425-pci.o -+obj-pci-$(CONFIG_MACH_TW5334) += tw5334-pci.o - - obj-y += common.o - -@@ -42,6 +43,7 @@ obj-$(CONFIG_MACH_SIDEWINDER) += sidewin - obj-$(CONFIG_MACH_COMPEX) += compex-setup.o - obj-$(CONFIG_MACH_WRT300NV2) += wrt300nv2-setup.o - obj-$(CONFIG_MACH_AP1000) += ap1000-setup.o -+obj-$(CONFIG_MACH_TW5334) += tw5334-setup.o - - obj-$(CONFIG_PCI) += $(obj-pci-$(CONFIG_PCI)) common-pci.o - obj-$(CONFIG_IXP4XX_QMGR) += ixp4xx_qmgr.o ---- /dev/null -+++ b/arch/arm/mach-ixp4xx/tw5334-setup.c -@@ -0,0 +1,162 @@ -+/* -+ * arch/arm/mach-ixp4xx/tw5334-setup.c -+ * -+ * Board setup for the Titan Wireless TW-533-4 -+ * -+ * Copyright (C) 2008 Imre Kaloz -+ * -+ * based on coyote-setup.c: -+ * Copyright (C) 2003-2005 MontaVista Software, Inc. -+ * -+ * Author: Imre Kaloz -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+static struct flash_platform_data tw5334_flash_data = { -+ .map_name = "cfi_probe", -+ .width = 2, -+}; -+ -+static struct resource tw5334_flash_resource = { -+ .flags = IORESOURCE_MEM, -+}; -+ -+static struct platform_device tw5334_flash = { -+ .name = "IXP4XX-Flash", -+ .id = 0, -+ .dev = { -+ .platform_data = &tw5334_flash_data, -+ }, -+ .num_resources = 1, -+ .resource = &tw5334_flash_resource, -+}; -+ -+static struct resource tw5334_uart_resource = { -+ .start = IXP4XX_UART2_BASE_PHYS, -+ .end = IXP4XX_UART2_BASE_PHYS + 0x0fff, -+ .flags = IORESOURCE_MEM, -+}; -+ -+static struct plat_serial8250_port tw5334_uart_data[] = { -+ { -+ .mapbase = IXP4XX_UART2_BASE_PHYS, -+ .membase = (char *)IXP4XX_UART2_BASE_VIRT + REG_OFFSET, -+ .irq = IRQ_IXP4XX_UART2, -+ .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST, -+ .iotype = UPIO_MEM, -+ .regshift = 2, -+ .uartclk = IXP4XX_UART_XTAL, -+ }, -+ { }, -+}; -+ -+static struct platform_device tw5334_uart = { -+ .name = "serial8250", -+ .id = PLAT8250_DEV_PLATFORM, -+ .dev = { -+ .platform_data = tw5334_uart_data, -+ }, -+ .num_resources = 1, -+ .resource = &tw5334_uart_resource, -+}; -+ -+/* Built-in 10/100 Ethernet MAC interfaces */ -+static struct eth_plat_info tw5334_plat_eth[] = { -+ { -+ .phy = 0, -+ .rxq = 3, -+ .txreadyq = 20, -+ }, { -+ .phy = 1, -+ .rxq = 4, -+ .txreadyq = 21, -+ } -+}; -+ -+static struct platform_device tw5334_eth[] = { -+ { -+ .name = "ixp4xx_eth", -+ .id = IXP4XX_ETH_NPEB, -+ .dev.platform_data = tw5334_plat_eth, -+ }, { -+ .name = "ixp4xx_eth", -+ .id = IXP4XX_ETH_NPEC, -+ .dev.platform_data = tw5334_plat_eth + 1, -+ } -+}; -+ -+static struct platform_device *tw5334_devices[] __initdata = { -+ &tw5334_flash, -+ &tw5334_uart, -+ &tw5334_eth[0], -+ &tw5334_eth[1], -+}; -+ -+static void __init tw5334_init(void) -+{ -+ DECLARE_MAC_BUF(mac_buf); -+ uint8_t __iomem *f; -+ int i; -+ -+ ixp4xx_sys_init(); -+ -+ tw5334_flash_resource.start = IXP4XX_EXP_BUS_BASE(0); -+ tw5334_flash_resource.end = IXP4XX_EXP_BUS_BASE(0) + SZ_32M - 1; -+ -+ *IXP4XX_EXP_CS0 |= IXP4XX_FLASH_WRITABLE; -+ *IXP4XX_EXP_CS1 = *IXP4XX_EXP_CS0; -+ -+ platform_add_devices(tw5334_devices, ARRAY_SIZE(tw5334_devices)); -+ -+ /* -+ * Map in a portion of the flash and read the MAC addresses. -+ * Since it is stored in BE in the flash itself, we need to -+ * byteswap it if we're in LE mode. -+ */ -+ f = ioremap(IXP4XX_EXP_BUS_BASE(0), 0x1000000); -+ if (f) { -+ for (i = 0; i < 6; i++) -+#ifdef __ARMEB__ -+ tw5334_plat_eth[0].hwaddr[i] = readb(f + 0xFC0422 + i); -+ tw5334_plat_eth[1].hwaddr[i] = readb(f + 0xFC043B + i); -+#else -+ tw5334_plat_eth[0].hwaddr[i] = readb(f + 0xFC0422 + (i^3)); -+ tw5334_plat_eth[1].hwaddr[i] = readb(f + 0xFC043B + (i^3)); -+#endif -+ iounmap(f); -+ } -+ printk(KERN_INFO "TW-533-4: Using MAC address %s for port 0\n", -+ print_mac(mac_buf, tw5334_plat_eth[0].hwaddr)); -+ printk(KERN_INFO "TW-533-4: Using MAC address %s for port 1\n", -+ print_mac(mac_buf, tw5334_plat_eth[1].hwaddr)); -+} -+ -+#ifdef CONFIG_MACH_TW5334 -+MACHINE_START(TW5334, "Titan Wireless TW-533-4") -+ /* Maintainer: Imre Kaloz */ -+ .phys_io = IXP4XX_PERIPHERAL_BASE_PHYS, -+ .io_pg_offst = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc, -+ .map_io = ixp4xx_map_io, -+ .init_irq = ixp4xx_init_irq, -+ .timer = &ixp4xx_timer, -+ .boot_params = 0x0100, -+ .init_machine = tw5334_init, -+MACHINE_END -+#endif ---- /dev/null -+++ b/arch/arm/mach-ixp4xx/tw5334-pci.c -@@ -0,0 +1,69 @@ -+/* -+ * arch/arch/mach-ixp4xx/tw5334-pci.c -+ * -+ * PCI setup routines for the Titan Wireless TW-533-4 -+ * -+ * Copyright (C) 2008 Imre Kaloz -+ * -+ * based on coyote-pci.c: -+ * Copyright (C) 2002 Jungo Software Technologies. -+ * Copyright (C) 2003 MontaVista Softwrae, Inc. -+ * -+ * Maintainer: Imre Kaloz -+ * -+ * 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 -+#include -+#include -+#include -+ -+#include -+#include -+ -+#include -+ -+void __init tw5334_pci_preinit(void) -+{ -+ set_irq_type(IRQ_IXP4XX_GPIO6, IRQ_TYPE_LEVEL_LOW); -+ set_irq_type(IRQ_IXP4XX_GPIO2, IRQ_TYPE_LEVEL_LOW); -+ set_irq_type(IRQ_IXP4XX_GPIO1, IRQ_TYPE_LEVEL_LOW); -+ set_irq_type(IRQ_IXP4XX_GPIO0, IRQ_TYPE_LEVEL_LOW); -+ -+ ixp4xx_pci_preinit(); -+} -+ -+static int __init tw5334_map_irq(struct pci_dev *dev, u8 slot, u8 pin) -+{ -+ if (slot == 12) -+ return IRQ_IXP4XX_GPIO6; -+ else if (slot == 13) -+ return IRQ_IXP4XX_GPIO2; -+ else if (slot == 14) -+ return IRQ_IXP4XX_GPIO1; -+ else if (slot == 15) -+ return IRQ_IXP4XX_GPIO0; -+ else return -1; -+} -+ -+struct hw_pci tw5334_pci __initdata = { -+ .nr_controllers = 1, -+ .preinit = tw5334_pci_preinit, -+ .swizzle = pci_std_swizzle, -+ .setup = ixp4xx_setup, -+ .scan = ixp4xx_scan_bus, -+ .map_irq = tw5334_map_irq, -+}; -+ -+int __init tw5334_pci_init(void) -+{ -+ if (machine_is_tw5334()) -+ pci_common_init(&tw5334_pci); -+ return 0; -+} -+ -+subsys_initcall(tw5334_pci_init); ---- a/arch/arm/mach-ixp4xx/include/mach/uncompress.h -+++ b/arch/arm/mach-ixp4xx/include/mach/uncompress.h -@@ -42,7 +42,8 @@ static __inline__ void __arch_decomp_set - */ - if (machine_is_adi_coyote() || machine_is_gtwx5715() || - machine_is_gateway7001() || machine_is_wg302v2() || -- machine_is_pronghorn() || machine_is_pronghorn_metro() || machine_is_wrt300nv2()) -+ machine_is_pronghorn() || machine_is_pronghorn_metro() || machine_is_wrt300nv2() || -+ machine_is_tw5334()) - uart_base = (volatile u32*) IXP4XX_UART2_BASE_PHYS; - else - uart_base = (volatile u32*) IXP4XX_UART1_BASE_PHYS; diff --git a/target/linux/ixp4xx/patches-2.6.28/185-mi424wr_support.patch b/target/linux/ixp4xx/patches-2.6.28/185-mi424wr_support.patch deleted file mode 100644 index 1836130f5..000000000 --- a/target/linux/ixp4xx/patches-2.6.28/185-mi424wr_support.patch +++ /dev/null @@ -1,465 +0,0 @@ ---- /dev/null -+++ b/arch/arm/mach-ixp4xx/mi424wr-pci.c -@@ -0,0 +1,71 @@ -+/* -+ * arch/arm/mach-ixp4xx/mi424wr-pci.c -+ * -+ * Actiontec MI424WR board-level PCI initialization -+ * -+ * Copyright (C) 2008 Jose Vasconcellos -+ * -+ * Maintainer: Jose Vasconcellos -+ * -+ * 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 -+#include -+#include -+#include -+ -+#include -+#include -+ -+/* PCI controller GPIO to IRQ pin mappings -+ * This information was obtained from Actiontec's GPL release. -+ * -+ * INTA INTB -+ * SLOT 13 8 6 -+ * SLOT 14 7 8 -+ * SLOT 15 6 7 -+ */ -+ -+void __init mi424wr_pci_preinit(void) -+{ -+ set_irq_type(IRQ_IXP4XX_GPIO6, IRQ_TYPE_LEVEL_LOW); -+ set_irq_type(IRQ_IXP4XX_GPIO7, IRQ_TYPE_LEVEL_LOW); -+ set_irq_type(IRQ_IXP4XX_GPIO8, IRQ_TYPE_LEVEL_LOW); -+ -+ ixp4xx_pci_preinit(); -+} -+ -+static int __init mi424wr_map_irq(struct pci_dev *dev, u8 slot, u8 pin) -+{ -+ if (slot == 13) -+ return IRQ_IXP4XX_GPIO8; -+ if (slot == 14) -+ return IRQ_IXP4XX_GPIO7; -+ if (slot == 15) -+ return IRQ_IXP4XX_GPIO6; -+ -+ return -1; -+} -+ -+struct hw_pci mi424wr_pci __initdata = { -+ .nr_controllers = 1, -+ .preinit = mi424wr_pci_preinit, -+ .swizzle = pci_std_swizzle, -+ .setup = ixp4xx_setup, -+ .scan = ixp4xx_scan_bus, -+ .map_irq = mi424wr_map_irq, -+}; -+ -+int __init mi424wr_pci_init(void) -+{ -+ if (machine_is_mi424wr()) -+ pci_common_init(&mi424wr_pci); -+ return 0; -+} -+ -+subsys_initcall(mi424wr_pci_init); -+ ---- /dev/null -+++ b/arch/arm/mach-ixp4xx/mi424wr-setup.c -@@ -0,0 +1,344 @@ -+/* -+ * arch/arm/mach-ixp4xx/mi424wr-setup.c -+ * -+ * Actiontec MI424-WR board setup -+ * Copyright (c) 2008 Jose Vasconcellos -+ * -+ * Based on Gemtek GTWX5715 by -+ * Copyright (C) 2004 George T. Joseph -+ * Derived from Coyote -+ * -+ * 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, MA 02111-1307, USA. -+ * -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+/* -+ * GPIO 2,3,4 and 9 are hard wired to the Micrel/Kendin KS8995M Switch -+ * and operate as an SPI type interface. The details of the interface -+ * are available on Kendin/Micrel's web site. -+ */ -+ -+#define MI424WR_KSSPI_SELECT 9 -+#define MI424WR_KSSPI_TXD 4 -+#define MI424WR_KSSPI_CLOCK 2 -+#define MI424WR_KSSPI_RXD 3 -+ -+/* -+ * The "reset" button is wired to GPIO 10. -+ * The GPIO is brought "low" when the button is pushed. -+ */ -+ -+#define MI424WR_BUTTON_GPIO 10 -+#define MI424WR_BUTTON_IRQ IRQ_IXP4XX_GPIO10 -+ -+#define MI424WR_MOCA_WAN_LED 11 -+ -+/* Latch on CS1 - taken from Actiontec's 2.4 source code -+ * -+ * default latch value -+ * 0 - power alarm led (red) 0 (off) -+ * 1 - power led (green) 0 (off) -+ * 2 - wireless led (green) 1 (off) -+ * 3 - no internet led (red) 0 (off) -+ * 4 - internet ok led (green) 0 (off) -+ * 5 - moca LAN 0 (off) -+ * 6 - WAN alarm led (red) 0 (off) -+ * 7 - PCI reset 1 (not reset) -+ * 8 - IP phone 1 led (green) 1 (off) -+ * 9 - IP phone 2 led (green) 1 (off) -+ * 10 - VOIP ready led (green) 1 (off) -+ * 11 - PSTN relay 1 control 0 (PSTN) -+ * 12 - PSTN relay 1 control 0 (PSTN) -+ * 13 - N/A -+ * 14 - N/A -+ * 15 - N/A -+ */ -+ -+#define MI424WR_LATCH_MASK 0x04 -+#define MI424WR_LATCH_DEFAULT 0x1f86 -+ -+#define MI424WR_LATCH_ALARM_LED 0x00 -+#define MI424WR_LATCH_POWER_LED 0x01 -+#define MI424WR_LATCH_WIRELESS_LED 0x02 -+#define MI424WR_LATCH_INET_DOWN_LED 0x03 -+#define MI424WR_LATCH_INET_OK_LED 0x04 -+#define MI424WR_LATCH_MOCA_LAN_LED 0x05 -+#define MI424WR_LATCH_WAN_ALARM_LED 0x06 -+#define MI424WR_LATCH_PCI_RESET 0x07 -+#define MI424WR_LATCH_PHONE1_LED 0x08 -+#define MI424WR_LATCH_PHONE2_LED 0x09 -+#define MI424WR_LATCH_VOIP_LED 0x10 -+#define MI424WR_LATCH_PSTN_RELAY1 0x11 -+#define MI424WR_LATCH_PSTN_RELAY2 0x12 -+ -+/* initialize CS1 to default timings, Intel style, 16-bit bus */ -+#define MI424WR_CS1_CONFIG 0x80000002 -+ -+/* Define both UARTs but they are not easily accessible. -+ */ -+ -+static struct resource mi424wr_uart_resources[] = { -+ { -+ .start = IXP4XX_UART1_BASE_PHYS, -+ .end = IXP4XX_UART1_BASE_PHYS + 0x0fff, -+ .flags = IORESOURCE_MEM, -+ }, -+ { -+ .start = IXP4XX_UART2_BASE_PHYS, -+ .end = IXP4XX_UART2_BASE_PHYS + 0x0fff, -+ .flags = IORESOURCE_MEM, -+ } -+}; -+ -+ -+static struct plat_serial8250_port mi424wr_uart_platform_data[] = { -+ { -+ .mapbase = IXP4XX_UART1_BASE_PHYS, -+ .membase = (char *)IXP4XX_UART1_BASE_VIRT + REG_OFFSET, -+ .irq = IRQ_IXP4XX_UART1, -+ .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST, -+ .iotype = UPIO_MEM, -+ .regshift = 2, -+ .uartclk = IXP4XX_UART_XTAL, -+ }, -+ { -+ .mapbase = IXP4XX_UART2_BASE_PHYS, -+ .membase = (char *)IXP4XX_UART2_BASE_VIRT + REG_OFFSET, -+ .irq = IRQ_IXP4XX_UART2, -+ .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST, -+ .iotype = UPIO_MEM, -+ .regshift = 2, -+ .uartclk = IXP4XX_UART_XTAL, -+ }, -+ { }, -+}; -+ -+static struct platform_device mi424wr_uart_device = { -+ .name = "serial8250", -+ .id = PLAT8250_DEV_PLATFORM, -+ .dev.platform_data = mi424wr_uart_platform_data, -+ .num_resources = ARRAY_SIZE(mi424wr_uart_resources), -+ .resource = mi424wr_uart_resources, -+}; -+ -+static struct flash_platform_data mi424wr_flash_data = { -+ .map_name = "cfi_probe", -+ .width = 2, -+}; -+ -+static struct resource mi424wr_flash_resource = { -+ .flags = IORESOURCE_MEM, -+}; -+ -+static struct platform_device mi424wr_flash = { -+ .name = "IXP4XX-Flash", -+ .id = 0, -+ .dev.platform_data = &mi424wr_flash_data, -+ .num_resources = 1, -+ .resource = &mi424wr_flash_resource, -+}; -+ -+static int mi424wr_spi_boardinfo_setup(struct spi_board_info *bi, -+ struct spi_master *master, void *data) -+{ -+ -+ strlcpy(bi->modalias, "spi-ks8995", sizeof(bi->modalias)); -+ -+ bi->max_speed_hz = 5000000 /* Hz */; -+ bi->bus_num = master->bus_num; -+ bi->mode = SPI_MODE_0; -+ -+ return 0; -+} -+ -+static struct spi_gpio_platform_data mi424wr_spi_bus_data = { -+ .pin_cs = MI424WR_KSSPI_SELECT, -+ .pin_clk = MI424WR_KSSPI_CLOCK, -+ .pin_miso = MI424WR_KSSPI_RXD, -+ .pin_mosi = MI424WR_KSSPI_TXD, -+ .cs_activelow = 1, -+ .no_spi_delay = 1, -+ .boardinfo_setup = mi424wr_spi_boardinfo_setup, -+}; -+ -+static struct gpio_led mi424wr_gpio_led[] = { -+ { -+ .name = "moca-wan", /* green led */ -+ .gpio = MI424WR_MOCA_WAN_LED, -+ .active_low = 0, -+ } -+}; -+ -+static struct gpio_led_platform_data mi424wr_gpio_leds_data = { -+ .num_leds = 1, -+ .leds = mi424wr_gpio_led, -+}; -+ -+static struct platform_device mi424wr_gpio_leds = { -+ .name = "leds-gpio", -+ .id = -1, -+ .dev.platform_data = &mi424wr_gpio_leds_data, -+}; -+ -+static uint16_t latch_value = MI424WR_LATCH_DEFAULT; -+static uint16_t __iomem *iobase; -+ -+static void mi424wr_latch_set_led(u8 bit, enum led_brightness value) -+{ -+ -+ if (((MI424WR_LATCH_MASK >> bit) & 1) ^ (value == LED_OFF)) -+ latch_value &= ~(0x1 << bit); -+ else -+ latch_value |= (0x1 << bit); -+ -+ __raw_writew(latch_value, iobase); -+ -+} -+ -+static struct latch_led mi424wr_latch_led[] = { -+ { -+ .name = "power-alarm", -+ .bit = MI424WR_LATCH_ALARM_LED, -+ }, -+ { -+ .name = "power-ok", -+ .bit = MI424WR_LATCH_POWER_LED, -+ }, -+ { -+ .name = "wireless", /* green led */ -+ .bit = MI424WR_LATCH_WIRELESS_LED, -+ }, -+ { -+ .name = "inet-down", /* red led */ -+ .bit = MI424WR_LATCH_INET_DOWN_LED, -+ }, -+ { -+ .name = "inet-up", /* green led */ -+ .bit = MI424WR_LATCH_INET_OK_LED, -+ }, -+ { -+ .name = "moca-lan", /* green led */ -+ .bit = MI424WR_LATCH_MOCA_LAN_LED, -+ }, -+ { -+ .name = "wan-alarm", /* red led */ -+ .bit = MI424WR_LATCH_WAN_ALARM_LED, -+ } -+}; -+ -+static struct latch_led_platform_data mi424wr_latch_leds_data = { -+ .num_leds = ARRAY_SIZE(mi424wr_latch_led), -+ .mem = 0x51000000, -+ .leds = mi424wr_latch_led, -+ .set_led = mi424wr_latch_set_led, -+}; -+ -+static struct platform_device mi424wr_latch_leds = { -+ .name = "leds-latch", -+ .id = -1, -+ .dev.platform_data = &mi424wr_latch_leds_data, -+}; -+ -+static struct platform_device mi424wr_spi_bus = { -+ .name = "spi-gpio", -+ .id = 0, -+ .dev.platform_data = &mi424wr_spi_bus_data, -+}; -+ -+static struct eth_plat_info mi424wr_npeb_data = { -+ .phy = 17, /* KS8721 */ -+ .rxq = 3, -+ .txreadyq = 20, -+}; -+ -+static struct eth_plat_info mi424wr_npec_data = { -+ .phy = IXP4XX_ETH_PHY_MAX_ADDR, -+ .phy_mask = 0x1e, /* ports 1-4 of the KS8995 switch */ -+ .rxq = 4, -+ .txreadyq = 21, -+}; -+ -+static struct platform_device mi424wr_npe_devices[] = { -+ { -+ .name = "ixp4xx_eth", -+ .id = IXP4XX_ETH_NPEC, -+ .dev.platform_data = &mi424wr_npec_data, -+ }, { -+ .name = "ixp4xx_eth", -+ .id = IXP4XX_ETH_NPEB, -+ .dev.platform_data = &mi424wr_npeb_data, -+ } -+}; -+ -+static struct platform_device *mi424wr_devices[] __initdata = { -+ &mi424wr_uart_device, -+ &mi424wr_flash, -+ &mi424wr_gpio_leds, -+ &mi424wr_latch_leds, -+ &mi424wr_spi_bus, -+ &mi424wr_npe_devices[0], -+ &mi424wr_npe_devices[1], -+}; -+ -+static void __init mi424wr_init(void) -+{ -+ ixp4xx_sys_init(); -+ -+ mi424wr_flash_resource.start = IXP4XX_EXP_BUS_BASE(0); -+ mi424wr_flash_resource.end = IXP4XX_EXP_BUS_BASE(0) + SZ_8M - 1; -+ -+ *IXP4XX_EXP_CS0 |= IXP4XX_FLASH_WRITABLE; -+ *IXP4XX_EXP_CS1 = MI424WR_CS1_CONFIG; -+ -+ /* configure button as input -+ */ -+ gpio_line_config(MI424WR_BUTTON_GPIO, IXP4XX_GPIO_IN); -+ -+ /* Initialize LEDs and enables PCI bus. -+ */ -+ iobase = ioremap_nocache(IXP4XX_EXP_BUS_BASE(1), 0x1000); -+ __raw_writew(latch_value, iobase); -+ -+ platform_add_devices(mi424wr_devices, ARRAY_SIZE(mi424wr_devices)); -+} -+ -+ -+MACHINE_START(MI424WR, "Actiontec MI424WR") -+ /* Maintainer: Jose Vasconcellos */ -+ .phys_io = IXP4XX_UART2_BASE_PHYS, -+ .io_pg_offst = ((IXP4XX_UART2_BASE_VIRT) >> 18) & 0xfffc, -+ .map_io = ixp4xx_map_io, -+ .init_irq = ixp4xx_init_irq, -+ .timer = &ixp4xx_timer, -+ .boot_params = 0x0100, -+ .init_machine = mi424wr_init, -+MACHINE_END -+ ---- a/arch/arm/mach-ixp4xx/Makefile -+++ b/arch/arm/mach-ixp4xx/Makefile -@@ -23,6 +23,7 @@ obj-pci-$(CONFIG_MACH_COMPEX) += ixdp42 - obj-pci-$(CONFIG_MACH_WRT300NV2) += wrt300nv2-pci.o - obj-pci-$(CONFIG_MACH_AP1000) += ixdp425-pci.o - obj-pci-$(CONFIG_MACH_TW5334) += tw5334-pci.o -+obj-pci-$(CONFIG_MACH_MI424WR) += mi424wr-pci.o - - obj-y += common.o - -@@ -44,6 +45,7 @@ obj-$(CONFIG_MACH_COMPEX) += compex-setu - obj-$(CONFIG_MACH_WRT300NV2) += wrt300nv2-setup.o - obj-$(CONFIG_MACH_AP1000) += ap1000-setup.o - obj-$(CONFIG_MACH_TW5334) += tw5334-setup.o -+obj-$(CONFIG_MACH_MI424WR) += mi424wr-setup.o - - obj-$(CONFIG_PCI) += $(obj-pci-$(CONFIG_PCI)) common-pci.o - obj-$(CONFIG_IXP4XX_QMGR) += ixp4xx_qmgr.o ---- a/arch/arm/mach-ixp4xx/Kconfig -+++ b/arch/arm/mach-ixp4xx/Kconfig -@@ -229,6 +229,13 @@ config MACH_GTWX5715 - "High Speed" UART is n/c (as far as I can tell) - 20 Pin ARM/Xscale JTAG interface on J2 - -+config MACH_MI424WR -+ bool "Actiontec MI424WR" -+ depends on ARCH_IXP4XX -+ select PCI -+ help -+ Add support for the Actiontec MI424-WR. -+ - comment "IXP4xx Options" - - config IXP4XX_INDIRECT_PCI ---- a/arch/arm/configs/ixp4xx_defconfig -+++ b/arch/arm/configs/ixp4xx_defconfig -@@ -172,6 +172,7 @@ CONFIG_MACH_FSG=y - CONFIG_CPU_IXP46X=y - CONFIG_CPU_IXP43X=y - CONFIG_MACH_GTWX5715=y -+CONFIG_MACH_MI424WR=y - - # - # IXP4xx Options diff --git a/target/linux/ixp4xx/patches-2.6.28/190-cambria_support.patch b/target/linux/ixp4xx/patches-2.6.28/190-cambria_support.patch deleted file mode 100644 index d1a9f8506..000000000 --- a/target/linux/ixp4xx/patches-2.6.28/190-cambria_support.patch +++ /dev/null @@ -1,553 +0,0 @@ ---- /dev/null -+++ b/arch/arm/mach-ixp4xx/cambria-pci.c -@@ -0,0 +1,74 @@ -+/* -+ * arch/arch/mach-ixp4xx/cambria-pci.c -+ * -+ * PCI setup routines for Gateworks Cambria series -+ * -+ * Copyright (C) 2008 Imre Kaloz -+ * -+ * based on coyote-pci.c: -+ * Copyright (C) 2002 Jungo Software Technologies. -+ * Copyright (C) 2003 MontaVista Softwrae, Inc. -+ * -+ * Maintainer: Imre Kaloz -+ * -+ * 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 -+#include -+#include -+#include -+ -+#include -+#include -+#include -+ -+#include -+ -+extern void ixp4xx_pci_preinit(void); -+extern int ixp4xx_setup(int nr, struct pci_sys_data *sys); -+extern struct pci_bus *ixp4xx_scan_bus(int nr, struct pci_sys_data *sys); -+ -+void __init cambria_pci_preinit(void) -+{ -+ set_irq_type(IRQ_IXP4XX_GPIO11, IRQ_TYPE_LEVEL_LOW); -+ set_irq_type(IRQ_IXP4XX_GPIO10, IRQ_TYPE_LEVEL_LOW); -+ set_irq_type(IRQ_IXP4XX_GPIO9, IRQ_TYPE_LEVEL_LOW); -+ set_irq_type(IRQ_IXP4XX_GPIO8, IRQ_TYPE_LEVEL_LOW); -+ -+ ixp4xx_pci_preinit(); -+} -+ -+static int __init cambria_map_irq(struct pci_dev *dev, u8 slot, u8 pin) -+{ -+ if (slot == 1) -+ return IRQ_IXP4XX_GPIO11; -+ else if (slot == 2) -+ return IRQ_IXP4XX_GPIO10; -+ else if (slot == 3) -+ return IRQ_IXP4XX_GPIO9; -+ else if (slot == 4) -+ return IRQ_IXP4XX_GPIO8; -+ else return -1; -+} -+ -+struct hw_pci cambria_pci __initdata = { -+ .nr_controllers = 1, -+ .preinit = cambria_pci_preinit, -+ .swizzle = pci_std_swizzle, -+ .setup = ixp4xx_setup, -+ .scan = ixp4xx_scan_bus, -+ .map_irq = cambria_map_irq, -+}; -+ -+int __init cambria_pci_init(void) -+{ -+ if (machine_is_cambria()) -+ pci_common_init(&cambria_pci); -+ return 0; -+} -+ -+subsys_initcall(cambria_pci_init); ---- /dev/null -+++ b/arch/arm/mach-ixp4xx/cambria-setup.c -@@ -0,0 +1,429 @@ -+/* -+ * arch/arm/mach-ixp4xx/cambria-setup.c -+ * -+ * Board setup for the Gateworks Cambria series -+ * -+ * Copyright (C) 2008 Imre Kaloz -+ * -+ * based on coyote-setup.c: -+ * Copyright (C) 2003-2005 MontaVista Software, Inc. -+ * -+ * Author: Imre Kaloz -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+struct cambria_board_info { -+ unsigned char *model; -+ void (*setup)(void); -+}; -+ -+static struct cambria_board_info *cambria_info __initdata; -+ -+static struct flash_platform_data cambria_flash_data = { -+ .map_name = "cfi_probe", -+ .width = 2, -+}; -+ -+static struct resource cambria_flash_resource = { -+ .flags = IORESOURCE_MEM, -+}; -+ -+static struct platform_device cambria_flash = { -+ .name = "IXP4XX-Flash", -+ .id = 0, -+ .dev = { -+ .platform_data = &cambria_flash_data, -+ }, -+ .num_resources = 1, -+ .resource = &cambria_flash_resource, -+}; -+ -+static struct i2c_gpio_platform_data cambria_i2c_gpio_data = { -+ .sda_pin = 7, -+ .scl_pin = 6, -+}; -+ -+static struct platform_device cambria_i2c_gpio = { -+ .name = "i2c-gpio", -+ .id = 0, -+ .dev = { -+ .platform_data = &cambria_i2c_gpio_data, -+ }, -+}; -+ -+static struct eth_plat_info cambria_npec_data = { -+ .phy = 1, -+ .rxq = 4, -+ .txreadyq = 21, -+}; -+ -+static struct eth_plat_info cambria_npea_data = { -+ .phy = 2, -+ .rxq = 2, -+ .txreadyq = 19, -+}; -+ -+static struct platform_device cambria_npec_device = { -+ .name = "ixp4xx_eth", -+ .id = IXP4XX_ETH_NPEC, -+ .dev.platform_data = &cambria_npec_data, -+}; -+ -+static struct platform_device cambria_npea_device = { -+ .name = "ixp4xx_eth", -+ .id = IXP4XX_ETH_NPEA, -+ .dev.platform_data = &cambria_npea_data, -+}; -+ -+static struct resource cambria_uart_resource = { -+ .start = IXP4XX_UART1_BASE_PHYS, -+ .end = IXP4XX_UART1_BASE_PHYS + 0x0fff, -+ .flags = IORESOURCE_MEM, -+}; -+ -+static struct plat_serial8250_port cambria_uart_data[] = { -+ { -+ .mapbase = IXP4XX_UART1_BASE_PHYS, -+ .membase = (char *)IXP4XX_UART1_BASE_VIRT + REG_OFFSET, -+ .irq = IRQ_IXP4XX_UART1, -+ .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST, -+ .iotype = UPIO_MEM, -+ .regshift = 2, -+ .uartclk = IXP4XX_UART_XTAL, -+ }, -+ { }, -+}; -+ -+static struct platform_device cambria_uart = { -+ .name = "serial8250", -+ .id = PLAT8250_DEV_PLATFORM, -+ .dev = { -+ .platform_data = cambria_uart_data, -+ }, -+ .num_resources = 1, -+ .resource = &cambria_uart_resource, -+}; -+ -+static struct resource cambria_pata_resources[] = { -+ { -+ .flags = IORESOURCE_MEM -+ }, -+ { -+ .flags = IORESOURCE_MEM, -+ }, -+ { -+ .name = "intrq", -+ .start = IRQ_IXP4XX_GPIO12, -+ .end = IRQ_IXP4XX_GPIO12, -+ .flags = IORESOURCE_IRQ, -+ }, -+}; -+ -+static struct ixp4xx_pata_data cambria_pata_data = { -+ .cs0_bits = 0xbfff3c03, -+ .cs1_bits = 0xbfff3c03, -+}; -+ -+static struct platform_device cambria_pata = { -+ .name = "pata_ixp4xx_cf", -+ .id = 0, -+ .dev.platform_data = &cambria_pata_data, -+ .num_resources = ARRAY_SIZE(cambria_pata_resources), -+ .resource = cambria_pata_resources, -+}; -+ -+static struct gpio_led cambria_gpio_leds[] = { -+ { -+ .name = "user", /* green led */ -+ .gpio = 5, -+ .active_low = 1, -+ } -+}; -+ -+static struct gpio_led_platform_data cambria_gpio_leds_data = { -+ .num_leds = 1, -+ .leds = cambria_gpio_leds, -+}; -+ -+static struct platform_device cambria_gpio_leds_device = { -+ .name = "leds-gpio", -+ .id = -1, -+ .dev.platform_data = &cambria_gpio_leds_data, -+}; -+ -+static struct latch_led cambria_latch_leds[] = { -+ { -+ .name = "ledA", /* green led */ -+ .bit = 0, -+ }, -+ { -+ .name = "ledB", /* green led */ -+ .bit = 1, -+ }, -+ { -+ .name = "ledC", /* green led */ -+ .bit = 2, -+ }, -+ { -+ .name = "ledD", /* green led */ -+ .bit = 3, -+ }, -+ { -+ .name = "ledE", /* green led */ -+ .bit = 4, -+ }, -+ { -+ .name = "ledF", /* green led */ -+ .bit = 5, -+ }, -+ { -+ .name = "ledG", /* green led */ -+ .bit = 6, -+ }, -+ { -+ .name = "ledH", /* green led */ -+ .bit = 7, -+ } -+}; -+ -+static struct latch_led_platform_data cambria_latch_leds_data = { -+ .num_leds = 8, -+ .leds = cambria_latch_leds, -+ .mem = 0x53F40000, -+}; -+ -+static struct platform_device cambria_latch_leds_device = { -+ .name = "leds-latch", -+ .id = -1, -+ .dev.platform_data = &cambria_latch_leds_data, -+}; -+ -+static struct resource cambria_usb0_resources[] = { -+ { -+ .start = 0xCD000000, -+ .end = 0xCD000300, -+ .flags = IORESOURCE_MEM, -+ }, -+ { -+ .start = 32, -+ .flags = IORESOURCE_IRQ, -+ }, -+}; -+ -+static struct resource cambria_usb1_resources[] = { -+ { -+ .start = 0xCE000000, -+ .end = 0xCE000300, -+ .flags = IORESOURCE_MEM, -+ }, -+ { -+ .start = 33, -+ .flags = IORESOURCE_IRQ, -+ }, -+}; -+ -+static u64 ehci_dma_mask = ~(u32)0; -+ -+static struct platform_device cambria_usb0_device = { -+ .name = "ixp4xx-ehci", -+ .id = 0, -+ .resource = cambria_usb0_resources, -+ .num_resources = ARRAY_SIZE(cambria_usb0_resources), -+ .dev = { -+ .dma_mask = &ehci_dma_mask, -+ .coherent_dma_mask = 0xffffffff, -+ }, -+}; -+ -+static struct platform_device cambria_usb1_device = { -+ .name = "ixp4xx-ehci", -+ .id = 1, -+ .resource = cambria_usb1_resources, -+ .num_resources = ARRAY_SIZE(cambria_usb1_resources), -+ .dev = { -+ .dma_mask = &ehci_dma_mask, -+ .coherent_dma_mask = 0xffffffff, -+ }, -+}; -+ -+static struct platform_device *cambria_devices[] __initdata = { -+ &cambria_i2c_gpio, -+ &cambria_flash, -+ &cambria_uart, -+}; -+ -+static void __init cambria_gw23xx_setup(void) -+{ -+ platform_device_register(&cambria_npec_device); -+ platform_device_register(&cambria_npea_device); -+} -+ -+static void __init cambria_gw2350_setup(void) -+{ -+ platform_device_register(&cambria_npec_device); -+ platform_device_register(&cambria_npea_device); -+ -+ platform_device_register(&cambria_usb0_device); -+ platform_device_register(&cambria_usb1_device); -+ -+ platform_device_register(&cambria_gpio_leds_device); -+} -+ -+static void __init cambria_gw2358_setup(void) -+{ -+ platform_device_register(&cambria_npec_device); -+ platform_device_register(&cambria_npea_device); -+ -+ platform_device_register(&cambria_usb0_device); -+ platform_device_register(&cambria_usb1_device); -+ -+ platform_device_register(&cambria_pata); -+ -+ platform_device_register(&cambria_latch_leds_device); -+} -+ -+static struct cambria_board_info cambria_boards[] __initdata = { -+ { -+ .model = "GW2350", -+ .setup = cambria_gw2350_setup, -+ }, { -+ .model = "GW2358", -+ .setup = cambria_gw2358_setup, -+ } -+}; -+ -+static struct cambria_board_info * __init cambria_find_board_info(char *model) -+{ -+ int i; -+ -+ for (i = 0; i < ARRAY_SIZE(cambria_boards); i++) { -+ struct cambria_board_info *info = &cambria_boards[i]; -+ if (strcmp(info->model, model) == 0) -+ return info; -+ } -+ -+ return NULL; -+} -+ -+static struct at24_iface *at24_if; -+ -+static int at24_setup(struct at24_iface *iface, void *context) -+{ -+ char mac_addr[ETH_ALEN]; -+ char model[6]; -+ -+ at24_if = iface; -+ -+ /* Read MAC addresses */ -+ if (at24_if->read(at24_if, mac_addr, 0x0, 6) == 6) { -+ memcpy(&cambria_npec_data.hwaddr, mac_addr, ETH_ALEN); -+ } -+ if (at24_if->read(at24_if, mac_addr, 0x6, 6) == 6) { -+ memcpy(&cambria_npea_data.hwaddr, mac_addr, ETH_ALEN); -+ } -+ -+ /* Read the first 6 bytes of the model number */ -+ if (at24_if->read(at24_if, model, 0x20, 6) == 6) { -+ cambria_info = cambria_find_board_info(model); -+ } -+ -+ return 0; -+} -+ -+static struct at24_platform_data cambria_eeprom_info = { -+ .byte_len = 1024, -+ .page_size = 16, -+ .flags = AT24_FLAG_READONLY, -+ .setup = at24_setup, -+}; -+ -+static struct i2c_board_info __initdata cambria_i2c_board_info[] = { -+ { -+ I2C_BOARD_INFO("ds1672", 0x68), -+ }, -+ { -+ I2C_BOARD_INFO("ad7418", 0x28), -+ }, -+ { -+ I2C_BOARD_INFO("24c08", 0x51), -+ .platform_data = &cambria_eeprom_info -+ }, -+}; -+ -+static void __init cambria_init(void) -+{ -+ ixp4xx_sys_init(); -+ -+ cambria_flash_resource.start = IXP4XX_EXP_BUS_BASE(0); -+ cambria_flash_resource.end = IXP4XX_EXP_BUS_BASE(0) + SZ_32M - 1; -+ -+ *IXP4XX_EXP_CS0 |= IXP4XX_FLASH_WRITABLE; -+ *IXP4XX_EXP_CS1 = *IXP4XX_EXP_CS0; -+ -+ platform_add_devices(cambria_devices, ARRAY_SIZE(cambria_devices)); -+ -+ cambria_pata_resources[0].start = 0x53e00000; -+ cambria_pata_resources[0].end = 0x53e3ffff; -+ -+ cambria_pata_resources[1].start = 0x53e40000; -+ cambria_pata_resources[1].end = 0x53e7ffff; -+ -+ cambria_pata_data.cs0_cfg = IXP4XX_EXP_CS3; -+ cambria_pata_data.cs1_cfg = IXP4XX_EXP_CS3; -+ -+ i2c_register_board_info(0, cambria_i2c_board_info, -+ ARRAY_SIZE(cambria_i2c_board_info)); -+} -+ -+static int __init cambria_model_setup(void) -+{ -+ if (!machine_is_cambria()) -+ return 0; -+ -+ if (cambria_info) { -+ printk(KERN_DEBUG "Running on Gateworks Cambria %s\n", -+ cambria_info->model); -+ cambria_info->setup(); -+ } else { -+ printk(KERN_INFO "Unknown/missing Cambria model number" -+ " -- defaults will be used\n"); -+ cambria_gw23xx_setup(); -+ } -+ -+ return 0; -+} -+late_initcall(cambria_model_setup); -+ -+MACHINE_START(CAMBRIA, "Gateworks Cambria series") -+ /* Maintainer: Imre Kaloz */ -+ .phys_io = IXP4XX_PERIPHERAL_BASE_PHYS, -+ .io_pg_offst = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc, -+ .map_io = ixp4xx_map_io, -+ .init_irq = ixp4xx_init_irq, -+ .timer = &ixp4xx_timer, -+ .boot_params = 0x0100, -+ .init_machine = cambria_init, -+MACHINE_END ---- a/arch/arm/mach-ixp4xx/Kconfig -+++ b/arch/arm/mach-ixp4xx/Kconfig -@@ -25,6 +25,14 @@ config MACH_AVILA - Avila Network Platform. For more information on this platform, - see . - -+config MACH_CAMBRIA -+ bool "Cambria" -+ select PCI -+ help -+ Say 'Y' here if you want your kernel to support the Gateworks -+ Cambria series. For more information on this platform, -+ see . -+ - config MACH_LOFT - bool "Loft" - depends on MACH_AVILA -@@ -208,7 +216,7 @@ config CPU_IXP46X - - config CPU_IXP43X - bool -- depends on MACH_KIXRP435 -+ depends on MACH_KIXRP435 || MACH_CAMBRIA - default y - - config MACH_GTWX5715 ---- a/arch/arm/mach-ixp4xx/Makefile -+++ b/arch/arm/mach-ixp4xx/Makefile -@@ -7,6 +7,7 @@ obj-pci-n := - - obj-pci-$(CONFIG_ARCH_IXDP4XX) += ixdp425-pci.o - obj-pci-$(CONFIG_MACH_AVILA) += avila-pci.o -+obj-pci-$(CONFIG_MACH_CAMBRIA) += cambria-pci.o - obj-pci-$(CONFIG_MACH_IXDPG425) += ixdpg425-pci.o - obj-pci-$(CONFIG_ARCH_ADI_COYOTE) += coyote-pci.o - obj-pci-$(CONFIG_MACH_GTWX5715) += gtwx5715-pci.o -@@ -29,6 +30,7 @@ obj-y += common.o - - obj-$(CONFIG_ARCH_IXDP4XX) += ixdp425-setup.o - obj-$(CONFIG_MACH_AVILA) += avila-setup.o -+obj-$(CONFIG_MACH_CAMBRIA) += cambria-setup.o - obj-$(CONFIG_MACH_IXDPG425) += coyote-setup.o - obj-$(CONFIG_ARCH_ADI_COYOTE) += coyote-setup.o - obj-$(CONFIG_MACH_GTWX5715) += gtwx5715-setup.o diff --git a/target/linux/ixp4xx/patches-2.6.28/191-cambria_optional_uart.patch b/target/linux/ixp4xx/patches-2.6.28/191-cambria_optional_uart.patch deleted file mode 100644 index 6d800d8d7..000000000 --- a/target/linux/ixp4xx/patches-2.6.28/191-cambria_optional_uart.patch +++ /dev/null @@ -1,178 +0,0 @@ ---- a/arch/arm/mach-ixp4xx/cambria-setup.c -+++ b/arch/arm/mach-ixp4xx/cambria-setup.c -@@ -34,6 +34,7 @@ - #include - #include - #include -+#include - - struct cambria_board_info { - unsigned char *model; -@@ -127,6 +128,45 @@ static struct platform_device cambria_ua - .resource = &cambria_uart_resource, - }; - -+static struct resource cambria_optional_uart_resources[] = { -+ { -+ .start = 0x52000000, -+ .end = 0x52000fff, -+ .flags = IORESOURCE_MEM -+ }, -+ { -+ .start = 0x53000000, -+ .end = 0x53000fff, -+ .flags = IORESOURCE_MEM -+ } -+}; -+ -+static struct plat_serial8250_port cambria_optional_uart_data[] = { -+ { -+ .flags = UPF_BOOT_AUTOCONF, -+ .iotype = UPIO_MEM_DELAY, -+ .regshift = 0, -+ .uartclk = 1843200, -+ .rw_delay = 2, -+ }, -+ { -+ .flags = UPF_BOOT_AUTOCONF, -+ .iotype = UPIO_MEM_DELAY, -+ .regshift = 0, -+ .uartclk = 1843200, -+ .rw_delay = 2, -+ }, -+ { }, -+}; -+ -+static struct platform_device cambria_optional_uart = { -+ .name = "serial8250", -+ .id = PLAT8250_DEV_PLATFORM1, -+ .dev.platform_data = cambria_optional_uart_data, -+ .num_resources = 2, -+ .resource = cambria_optional_uart_resources, -+}; -+ - static struct resource cambria_pata_resources[] = { - { - .flags = IORESOURCE_MEM -@@ -283,6 +323,19 @@ static void __init cambria_gw23xx_setup( - - static void __init cambria_gw2350_setup(void) - { -+ *IXP4XX_EXP_CS2 = 0xBFFF3C43; -+ set_irq_type(IRQ_IXP4XX_GPIO3, IRQ_TYPE_EDGE_RISING); -+ cambria_optional_uart_data[0].mapbase = 0x52FF0000; -+ cambria_optional_uart_data[0].membase = (void __iomem *)ioremap(0x52FF0000, 0x0fff); -+ cambria_optional_uart_data[0].irq = IRQ_IXP4XX_GPIO3; -+ -+ *IXP4XX_EXP_CS3 = 0xBFFF3C43; -+ set_irq_type(IRQ_IXP4XX_GPIO4, IRQ_TYPE_EDGE_RISING); -+ cambria_optional_uart_data[1].mapbase = 0x53FF0000; -+ cambria_optional_uart_data[1].membase = (void __iomem *)ioremap(0x53FF0000, 0x0fff); -+ cambria_optional_uart_data[1].irq = IRQ_IXP4XX_GPIO4; -+ -+ platform_device_register(&cambria_optional_uart); - platform_device_register(&cambria_npec_device); - platform_device_register(&cambria_npea_device); - -@@ -294,6 +347,19 @@ static void __init cambria_gw2350_setup( - - static void __init cambria_gw2358_setup(void) - { -+ *IXP4XX_EXP_CS3 = 0xBFFF3C43; -+ set_irq_type(IRQ_IXP4XX_GPIO3, IRQ_TYPE_EDGE_RISING); -+ cambria_optional_uart_data[0].mapbase = 0x53FC0000; -+ cambria_optional_uart_data[0].membase = (void __iomem *)ioremap(0x53FC0000, 0x0fff); -+ cambria_optional_uart_data[0].irq = IRQ_IXP4XX_GPIO3; -+ -+ set_irq_type(IRQ_IXP4XX_GPIO4, IRQ_TYPE_EDGE_RISING); -+ cambria_optional_uart_data[1].mapbase = 0x53F80000; -+ cambria_optional_uart_data[1].membase = (void __iomem *)ioremap(0x53F80000, 0x0fff); -+ cambria_optional_uart_data[1].irq = IRQ_IXP4XX_GPIO4; -+ -+ platform_device_register(&cambria_optional_uart); -+ - platform_device_register(&cambria_npec_device); - platform_device_register(&cambria_npea_device); - ---- a/include/linux/serial_8250.h -+++ b/include/linux/serial_8250.h -@@ -26,6 +26,7 @@ struct plat_serial8250_port { - void *private_data; - unsigned char regshift; /* register shift */ - unsigned char iotype; /* UPIO_* */ -+ unsigned int rw_delay; /* udelay for slower busses IXP4XX Expansion Bus */ - unsigned char hub6; - upf_t flags; /* UPF_* flags */ - }; ---- a/include/linux/serial_core.h -+++ b/include/linux/serial_core.h -@@ -262,6 +262,7 @@ struct uart_port { - #define UPIO_TSI (5) /* Tsi108/109 type IO */ - #define UPIO_DWAPB (6) /* DesignWare APB UART */ - #define UPIO_RM9000 (7) /* RM9000 type IO */ -+#define UPIO_MEM_DELAY (8) - - unsigned int read_status_mask; /* driver specific */ - unsigned int ignore_status_mask; /* driver specific */ -@@ -301,6 +302,7 @@ struct uart_port { - - unsigned int mctrl; /* current modem ctrl settings */ - unsigned int timeout; /* character-based timeout */ -+ unsigned int rw_delay; /* udelay for slow busses, IXP4XX Expansion Bus */ - unsigned int type; /* port type */ - const struct uart_ops *ops; - unsigned int custom_divisor; ---- a/drivers/serial/8250.c -+++ b/drivers/serial/8250.c -@@ -373,6 +373,8 @@ static unsigned int serial_in(struct uar - outb(up->port.hub6 - 1 + offset, up->port.iobase); - return inb(up->port.iobase + 1); - -+ case UPIO_MEM_DELAY: -+ udelay(up->port.rw_delay); - case UPIO_MEM: - case UPIO_DWAPB: - return readb(up->port.membase + offset); -@@ -411,6 +413,8 @@ serial_out(struct uart_8250_port *up, in - outb(value, up->port.iobase + 1); - break; - -+ case UPIO_MEM_DELAY: -+ udelay(up->port.rw_delay); - case UPIO_MEM: - writeb(value, up->port.membase + offset); - break; -@@ -2823,6 +2827,7 @@ static int __devinit serial8250_probe(st - port.hub6 = p->hub6; - port.private_data = p->private_data; - port.dev = &dev->dev; -+ port.rw_delay = p->rw_delay; - if (share_irqs) - port.flags |= UPF_SHARE_IRQ; - ret = serial8250_register_port(&port); -@@ -2972,6 +2977,7 @@ int serial8250_register_port(struct uart - uart->port.iotype = port->iotype; - uart->port.flags = port->flags | UPF_BOOT_AUTOCONF; - uart->port.mapbase = port->mapbase; -+ uart->port.rw_delay = port->rw_delay; - uart->port.private_data = port->private_data; - if (port->dev) - uart->port.dev = port->dev; ---- a/drivers/serial/serial_core.c -+++ b/drivers/serial/serial_core.c -@@ -2161,6 +2161,7 @@ uart_report_port(struct uart_driver *drv - snprintf(address, sizeof(address), - "I/O 0x%lx offset 0x%x", port->iobase, port->hub6); - break; -+ case UPIO_MEM_DELAY: - case UPIO_MEM: - case UPIO_MEM32: - case UPIO_AU: -@@ -2577,6 +2578,7 @@ int uart_match_port(struct uart_port *po - case UPIO_HUB6: - return (port1->iobase == port2->iobase) && - (port1->hub6 == port2->hub6); -+ case UPIO_MEM_DELAY: - case UPIO_MEM: - case UPIO_MEM32: - case UPIO_AU: diff --git a/target/linux/ixp4xx/patches-2.6.28/192-cambria_gpio_device.patch b/target/linux/ixp4xx/patches-2.6.28/192-cambria_gpio_device.patch deleted file mode 100644 index d785c3a8c..000000000 --- a/target/linux/ixp4xx/patches-2.6.28/192-cambria_gpio_device.patch +++ /dev/null @@ -1,46 +0,0 @@ ---- a/arch/arm/mach-ixp4xx/cambria-setup.c -+++ b/arch/arm/mach-ixp4xx/cambria-setup.c -@@ -214,6 +214,20 @@ static struct platform_device cambria_gp - .dev.platform_data = &cambria_gpio_leds_data, - }; - -+static struct resource cambria_gpio_resources[] = { -+ { -+ .name = "gpio", -+ .flags = 0, -+ }, -+}; -+ -+static struct platform_device cambria_gpio = { -+ .name = "GPIODEV", -+ .id = -1, -+ .num_resources = ARRAY_SIZE(cambria_gpio_resources), -+ .resource = cambria_gpio_resources, -+}; -+ - static struct latch_led cambria_latch_leds[] = { - { - .name = "ledA", /* green led */ -@@ -335,6 +349,11 @@ static void __init cambria_gw2350_setup( - cambria_optional_uart_data[1].membase = (void __iomem *)ioremap(0x53FF0000, 0x0fff); - cambria_optional_uart_data[1].irq = IRQ_IXP4XX_GPIO4; - -+ cambria_gpio_resources[0].start = (1 << 0) | (1 << 1) | (1 << 2) | (1 << 3) | (1 << 4) |\ -+ (1 << 5) | (1 << 8) | (1 << 9) | (1 << 12); -+ cambria_gpio_resources[0].end = cambria_gpio_resources[0].start; -+ -+ platform_device_register(&cambria_gpio); - platform_device_register(&cambria_optional_uart); - platform_device_register(&cambria_npec_device); - platform_device_register(&cambria_npea_device); -@@ -358,6 +377,10 @@ static void __init cambria_gw2358_setup( - cambria_optional_uart_data[1].membase = (void __iomem *)ioremap(0x53F80000, 0x0fff); - cambria_optional_uart_data[1].irq = IRQ_IXP4XX_GPIO4; - -+ cambria_gpio_resources[0].start = (1 << 14); -+ cambria_gpio_resources[0].end = cambria_gpio_resources[0].start; -+ -+ platform_device_register(&cambria_gpio); - platform_device_register(&cambria_optional_uart); - - platform_device_register(&cambria_npec_device); diff --git a/target/linux/ixp4xx/patches-2.6.28/193-cambria_pld_gpio.patch b/target/linux/ixp4xx/patches-2.6.28/193-cambria_pld_gpio.patch deleted file mode 100644 index 299630f17..000000000 --- a/target/linux/ixp4xx/patches-2.6.28/193-cambria_pld_gpio.patch +++ /dev/null @@ -1,107 +0,0 @@ ---- a/arch/arm/mach-ixp4xx/cambria-setup.c -+++ b/arch/arm/mach-ixp4xx/cambria-setup.c -@@ -12,11 +12,14 @@ - */ - - #include -+#include - #include - #include - #include -+#include - #include - #include -+#include - #include - #include - #include -@@ -323,6 +326,39 @@ static struct platform_device cambria_us - }, - }; - -+static struct gw_i2c_pld_platform_data gw_i2c_pld_data0 = { -+ .gpio_base = 16, -+ .nr_gpio = 8, -+}; -+ -+static struct gw_i2c_pld_platform_data gw_i2c_pld_data1 = { -+ .gpio_base = 24, -+ .nr_gpio = 2, -+}; -+ -+ -+static struct gpio_button cambria_gpio_buttons[] = { -+ { -+ .desc = "user", -+ .type = EV_KEY, -+ .code = BTN_0, -+ .threshold = 2, -+ .gpio = 25, -+ } -+}; -+ -+static struct gpio_buttons_platform_data cambria_gpio_buttons_data = { -+ .poll_interval = 500, -+ .nbuttons = 1, -+ .buttons = cambria_gpio_buttons, -+}; -+ -+static struct platform_device cambria_gpio_buttons_device = { -+ .name = "gpio-buttons", -+ .id = -1, -+ .dev.platform_data = &cambria_gpio_buttons_data, -+}; -+ - static struct platform_device *cambria_devices[] __initdata = { - &cambria_i2c_gpio, - &cambria_flash, -@@ -331,6 +367,11 @@ static struct platform_device *cambria_d - - static void __init cambria_gw23xx_setup(void) - { -+ cambria_gpio_resources[0].start = (1 << 0) | (1 << 1) | (1 << 2) | (1 << 3) | (1 << 4) |\ -+ (1 << 5) | (1 << 8) | (1 << 9) | (1 << 12); -+ cambria_gpio_resources[0].end = cambria_gpio_resources[0].start; -+ -+ platform_device_register(&cambria_gpio); - platform_device_register(&cambria_npec_device); - platform_device_register(&cambria_npea_device); - } -@@ -377,7 +418,8 @@ static void __init cambria_gw2358_setup( - cambria_optional_uart_data[1].membase = (void __iomem *)ioremap(0x53F80000, 0x0fff); - cambria_optional_uart_data[1].irq = IRQ_IXP4XX_GPIO4; - -- cambria_gpio_resources[0].start = (1 << 14); -+ cambria_gpio_resources[0].start = (1 << 14) | (1 << 16) | (1 << 17) | (1 << 18) |\ -+ (1 << 19) | (1 << 20) | (1 << 24) | (1 << 25); - cambria_gpio_resources[0].end = cambria_gpio_resources[0].start; - - platform_device_register(&cambria_gpio); -@@ -391,7 +433,12 @@ static void __init cambria_gw2358_setup( - - platform_device_register(&cambria_pata); - -+ cambria_gpio_leds[0].gpio = 24; -+ platform_device_register(&cambria_gpio_leds_device); -+ - platform_device_register(&cambria_latch_leds_device); -+ -+ platform_device_register(&cambria_gpio_buttons_device); - } - - static struct cambria_board_info cambria_boards[] __initdata = { -@@ -460,6 +507,14 @@ static struct i2c_board_info __initdata - I2C_BOARD_INFO("24c08", 0x51), - .platform_data = &cambria_eeprom_info - }, -+ { -+ I2C_BOARD_INFO("gw_i2c_pld", 0x56), -+ .platform_data = &gw_i2c_pld_data0, -+ }, -+ { -+ I2C_BOARD_INFO("gw_i2c_pld", 0x57), -+ .platform_data = &gw_i2c_pld_data1, -+ }, - }; - - static void __init cambria_init(void) diff --git a/target/linux/ixp4xx/patches-2.6.28/201-npe_driver_print_license_location.patch b/target/linux/ixp4xx/patches-2.6.28/201-npe_driver_print_license_location.patch deleted file mode 100644 index 64c179845..000000000 --- a/target/linux/ixp4xx/patches-2.6.28/201-npe_driver_print_license_location.patch +++ /dev/null @@ -1,11 +0,0 @@ ---- a/arch/arm/mach-ixp4xx/ixp4xx_npe.c -+++ b/arch/arm/mach-ixp4xx/ixp4xx_npe.c -@@ -592,6 +592,8 @@ int npe_load_firmware(struct npe *npe, c - npe_reset(npe); - #endif - -+ print_npe(KERN_INFO, npe, "firmware's license can be found in /usr/share/doc/LICENSE.IPL\n"); -+ - print_npe(KERN_INFO, npe, "firmware functionality 0x%X, " - "revision 0x%X:%X\n", (image->id >> 16) & 0xFF, - (image->id >> 8) & 0xFF, image->id & 0xFF); diff --git a/target/linux/ixp4xx/patches-2.6.28/202-npe_driver_switch_support.patch b/target/linux/ixp4xx/patches-2.6.28/202-npe_driver_switch_support.patch deleted file mode 100644 index a256c97d6..000000000 --- a/target/linux/ixp4xx/patches-2.6.28/202-npe_driver_switch_support.patch +++ /dev/null @@ -1,246 +0,0 @@ ---- a/drivers/net/arm/ixp4xx_eth.c -+++ b/drivers/net/arm/ixp4xx_eth.c -@@ -165,14 +165,15 @@ struct port { - struct net_device *netdev; - struct napi_struct napi; - struct net_device_stats stat; -- struct mii_if_info mii; -+ struct mii_if_info mii[IXP4XX_ETH_PHY_MAX_ADDR]; - struct delayed_work mdio_thread; - struct eth_plat_info *plat; - buffer_t *rx_buff_tab[RX_DESCS], *tx_buff_tab[TX_DESCS]; - struct desc *desc_tab; /* coherent */ - u32 desc_tab_phys; - int id; /* logical port ID */ -- u16 mii_bmcr; -+ u16 mii_bmcr[IXP4XX_ETH_PHY_MAX_ADDR]; -+ int phy_count; - }; - - /* NPE message structure */ -@@ -316,12 +317,13 @@ static void mdio_write(struct net_device - spin_unlock_irqrestore(&mdio_lock, flags); - } - --static void phy_reset(struct net_device *dev, int phy_id) -+static void phy_reset(struct net_device *dev, int idx) - { - struct port *port = netdev_priv(dev); -+ int phy_id = port->mii[idx].phy_id; - int cycles = 0; - -- mdio_write(dev, phy_id, MII_BMCR, port->mii_bmcr | BMCR_RESET); -+ mdio_write(dev, phy_id, MII_BMCR, port->mii_bmcr[idx] | BMCR_RESET); - - while (cycles < MAX_MII_RESET_RETRIES) { - if (!(mdio_read(dev, phy_id, MII_BMCR) & BMCR_RESET)) { -@@ -335,12 +337,12 @@ static void phy_reset(struct net_device - cycles++; - } - -- printk(KERN_ERR "%s: MII reset failed\n", dev->name); -+ printk(KERN_ERR "%s: MII reset failed on PHY%2d\n", dev->name, phy_id); - } - --static void eth_set_duplex(struct port *port) -+static void eth_set_duplex(struct port *port, int full_duplex) - { -- if (port->mii.full_duplex) -+ if (full_duplex) - __raw_writel(DEFAULT_TX_CNTRL0 & ~TX_CNTRL0_HALFDUPLEX, - &port->regs->tx_control[0]); - else -@@ -348,7 +350,7 @@ static void eth_set_duplex(struct port * - &port->regs->tx_control[0]); - } - -- -+#if 0 - static void phy_check_media(struct port *port, int init) - { - if (mii_check_media(&port->mii, 1, init)) -@@ -367,7 +369,63 @@ static void phy_check_media(struct port - } - } - } -+#else -+static void phy_update_link(struct net_device *dev, int link) -+{ -+ int prev_link = netif_carrier_ok(dev); -+ -+ if (!prev_link && link) { -+ printk(KERN_INFO "%s: link up\n", dev->name); -+ netif_carrier_on(dev); -+ } else if (prev_link && !link) { -+ printk(KERN_INFO "%s: link down\n", dev->name); -+ netif_carrier_off(dev); -+ } -+} -+ -+static void phy_check_media(struct port *port, int init) -+{ -+ struct net_device *dev = port->netdev; -+ -+ if (port->phy_count == 1) { -+ struct mii_if_info *mii = &port->mii[0]; -+ -+ if (mii_check_media(mii, 1, init)) -+ eth_set_duplex(port, mii->full_duplex); -+ -+ if (mii->force_media) /* mii_check_media() doesn't work */ -+ phy_update_link(dev, mii_link_ok(mii)); -+ } else { -+ int cur_link = 0; -+ int i; -+ -+ if (init) -+ eth_set_duplex(port, 1); -+ -+ for (i = 0; i < port->phy_count; i++) -+ cur_link |= mii_link_ok(&port->mii[i]); -+ -+ phy_update_link(dev, cur_link); -+ } -+} -+#endif -+ -+static void phy_power_down(struct net_device *dev, int idx) -+{ -+ struct port *port = netdev_priv(dev); -+ int phy_id = port->mii[idx].phy_id; -+ -+ port->mii_bmcr[idx] = mdio_read(dev, phy_id, MII_BMCR) & -+ ~(BMCR_RESET | BMCR_PDOWN); -+ mdio_write(dev, phy_id, MII_BMCR, port->mii_bmcr[idx] | BMCR_PDOWN); -+} -+ -+static void phy_power_up(struct net_device *dev, int idx) -+{ -+ struct port *port = netdev_priv(dev); - -+ mdio_write(dev, port->mii[idx].phy_id, MII_BMCR, port->mii_bmcr[idx]); -+} - - static void mdio_thread(struct work_struct *work) - { -@@ -791,9 +849,12 @@ static int eth_ioctl(struct net_device * - - if (!netif_running(dev)) - return -EINVAL; -- err = generic_mii_ioctl(&port->mii, if_mii(req), cmd, &duplex_chg); -+ if (port->phy_count != 1) -+ return -EOPNOTSUPP; -+ -+ err = generic_mii_ioctl(&port->mii[0], if_mii(req), cmd, &duplex_chg); - if (duplex_chg) -- eth_set_duplex(port); -+ eth_set_duplex(port, port->mii[0].full_duplex); - return err; - } - -@@ -946,7 +1007,8 @@ static int eth_open(struct net_device *d - } - } - -- mdio_write(dev, port->plat->phy, MII_BMCR, port->mii_bmcr); -+ for (i = 0; i < port->phy_count; i++) -+ phy_power_up(dev, i); - - memset(&msg, 0, sizeof(msg)); - msg.cmd = NPE_VLAN_SETRXQOSENTRY; -@@ -1106,10 +1168,8 @@ static int eth_close(struct net_device * - printk(KERN_CRIT "%s: unable to disable loopback\n", - dev->name); - -- port->mii_bmcr = mdio_read(dev, port->plat->phy, MII_BMCR) & -- ~(BMCR_RESET | BMCR_PDOWN); /* may have been altered */ -- mdio_write(dev, port->plat->phy, MII_BMCR, -- port->mii_bmcr | BMCR_PDOWN); -+ for (i = 0; i < port->phy_count; i++) -+ phy_power_down(dev, i); - - if (!ports_open) - qmgr_disable_irq(TXDONE_QUEUE); -@@ -1119,6 +1179,42 @@ static int eth_close(struct net_device * - return 0; - } - -+static void eth_add_phy(struct net_device *dev, int phy_id) -+{ -+ struct port *port = netdev_priv(dev); -+ int i; -+ -+ i = port->phy_count++; -+ -+ port->mii[i].dev = dev; -+ port->mii[i].mdio_read = mdio_read; -+ port->mii[i].mdio_write = mdio_write; -+ port->mii[i].phy_id = phy_id; -+ port->mii[i].phy_id_mask = 0x1F; -+ port->mii[i].reg_num_mask = 0x1F; -+ -+ printk(KERN_INFO "%s: MII PHY %i on %s\n", dev->name, phy_id, -+ npe_name(port->npe)); -+ -+ phy_reset(dev, i); -+ phy_power_down(dev, i); -+} -+ -+static void eth_init_mii(struct net_device *dev) -+{ -+ struct port *port = netdev_priv(dev); -+ -+ if (port->plat->phy < IXP4XX_ETH_PHY_MAX_ADDR) { -+ eth_add_phy(dev, port->plat->phy); -+ } else { -+ int i; -+ for (i = 0; i < IXP4XX_ETH_PHY_MAX_ADDR; i++) -+ if (port->plat->phy_mask & (1U << i)) -+ eth_add_phy(dev, i); -+ } -+ -+} -+ - static int __devinit eth_init_one(struct platform_device *pdev) - { - struct port *port; -@@ -1191,20 +1287,7 @@ static int __devinit eth_init_one(struct - __raw_writel(DEFAULT_CORE_CNTRL, &port->regs->core_control); - udelay(50); - -- port->mii.dev = dev; -- port->mii.mdio_read = mdio_read; -- port->mii.mdio_write = mdio_write; -- port->mii.phy_id = plat->phy; -- port->mii.phy_id_mask = 0x1F; -- port->mii.reg_num_mask = 0x1F; -- -- printk(KERN_INFO "%s: MII PHY %i on %s\n", dev->name, plat->phy, -- npe_name(port->npe)); -- -- phy_reset(dev, plat->phy); -- port->mii_bmcr = mdio_read(dev, plat->phy, MII_BMCR) & -- ~(BMCR_RESET | BMCR_PDOWN); -- mdio_write(dev, plat->phy, MII_BMCR, port->mii_bmcr | BMCR_PDOWN); -+ eth_init_mii(dev); - - INIT_DELAYED_WORK(&port->mdio_thread, mdio_thread); - return 0; ---- a/arch/arm/mach-ixp4xx/include/mach/platform.h -+++ b/arch/arm/mach-ixp4xx/include/mach/platform.h -@@ -95,12 +95,15 @@ struct sys_timer; - #define IXP4XX_ETH_NPEB 0x10 - #define IXP4XX_ETH_NPEC 0x20 - -+#define IXP4XX_ETH_PHY_MAX_ADDR 32 -+ - /* Information about built-in Ethernet MAC interfaces */ - struct eth_plat_info { - u8 phy; /* MII PHY ID, 0 - 31 */ - u8 rxq; /* configurable, currently 0 - 31 only */ - u8 txreadyq; - u8 hwaddr[6]; -+ u32 phy_mask; - }; - - /* Information about built-in HSS (synchronous serial) interfaces */ diff --git a/target/linux/ixp4xx/patches-2.6.28/203-npe_driver_phy_reset_autoneg.patch b/target/linux/ixp4xx/patches-2.6.28/203-npe_driver_phy_reset_autoneg.patch deleted file mode 100644 index b6519f034..000000000 --- a/target/linux/ixp4xx/patches-2.6.28/203-npe_driver_phy_reset_autoneg.patch +++ /dev/null @@ -1,42 +0,0 @@ ---- a/drivers/net/arm/ixp4xx_eth.c -+++ b/drivers/net/arm/ixp4xx_eth.c -@@ -322,8 +322,12 @@ static void phy_reset(struct net_device - struct port *port = netdev_priv(dev); - int phy_id = port->mii[idx].phy_id; - int cycles = 0; -+ u16 bmcr; - -- mdio_write(dev, phy_id, MII_BMCR, port->mii_bmcr[idx] | BMCR_RESET); -+ /* reset the PHY */ -+ bmcr = mdio_read(dev, phy_id, MII_BMCR); -+ bmcr |= BMCR_ANENABLE; -+ mdio_write(dev, phy_id, MII_BMCR, bmcr | BMCR_RESET); - - while (cycles < MAX_MII_RESET_RETRIES) { - if (!(mdio_read(dev, phy_id, MII_BMCR) & BMCR_RESET)) { -@@ -331,13 +335,23 @@ static void phy_reset(struct net_device - printk(KERN_DEBUG "%s: phy_reset() took %i cycles\n", - dev->name, cycles); - #endif -- return; -+ break; - } - udelay(1); - cycles++; - } - -- printk(KERN_ERR "%s: MII reset failed on PHY%2d\n", dev->name, phy_id); -+ if (cycles == MAX_MII_RESET_RETRIES) { -+ printk(KERN_ERR "%s: MII reset failed on PHY%2d\n", dev->name, -+ phy_id); -+ return; -+ } -+ -+ /* restart auto negotiation */ -+ bmcr = mdio_read(dev, phy_id, MII_BMCR); -+ bmcr |= (BMCR_ANENABLE | BMCR_ANRESTART); -+ mdio_write(dev, phy_id, MII_BMCR, bmcr); -+ - } - - static void eth_set_duplex(struct port *port, int full_duplex) diff --git a/target/linux/ixp4xx/patches-2.6.28/204-npe_driver_ixp43x_support.patch b/target/linux/ixp4xx/patches-2.6.28/204-npe_driver_ixp43x_support.patch deleted file mode 100644 index 240370b8a..000000000 --- a/target/linux/ixp4xx/patches-2.6.28/204-npe_driver_ixp43x_support.patch +++ /dev/null @@ -1,94 +0,0 @@ -From cba5c286f3ea34ea4767fc00c705434a00fe2c37 Mon Sep 17 00:00:00 2001 -From: Imre Kaloz -Date: Thu, 26 Jun 2008 01:58:02 +0200 -Subject: [PATCH] Add support for the ethernet ports on IXP43x - ---- - arch/arm/mach-ixp4xx/ixp4xx_npe.c | 6 +++--- - drivers/net/arm/ixp4xx_eth.c | 13 +++++++++---- - include/asm-arm/arch-ixp4xx/cpu.h | 2 ++ - include/asm-arm/arch-ixp4xx/ixp4xx-regs.h | 7 ++++--- - 4 files changed, 18 insertions(+), 10 deletions(-) - ---- a/arch/arm/mach-ixp4xx/ixp4xx_npe.c -+++ b/arch/arm/mach-ixp4xx/ixp4xx_npe.c -@@ -575,8 +575,8 @@ int npe_load_firmware(struct npe *npe, c - for (i = 0; i < image->size; i++) - image->data[i] = swab32(image->data[i]); - -- if (!cpu_is_ixp46x() && ((image->id >> 28) & 0xF /* device ID */)) { -- print_npe(KERN_INFO, npe, "IXP46x firmware ignored on " -+ if (cpu_is_ixp42x() && ((image->id >> 28) & 0xF /* device ID */)) { -+ print_npe(KERN_INFO, npe, "IXP46x/IXP43x firmware ignored on " - "IXP42x\n"); - goto err; - } -@@ -598,7 +598,7 @@ int npe_load_firmware(struct npe *npe, c - "revision 0x%X:%X\n", (image->id >> 16) & 0xFF, - (image->id >> 8) & 0xFF, image->id & 0xFF); - -- if (!cpu_is_ixp46x()) { -+ if (cpu_is_ixp42x()) { - if (!npe->id) - instr_size = NPE_A_42X_INSTR_SIZE; - else ---- a/drivers/net/arm/ixp4xx_eth.c -+++ b/drivers/net/arm/ixp4xx_eth.c -@@ -32,6 +32,7 @@ - #include - #include - #include -+#include - #include - #include - -@@ -1337,12 +1338,16 @@ static struct platform_driver drv = { - - static int __init eth_init_module(void) - { -- if (!(ixp4xx_read_feature_bits() & IXP4XX_FEATURE_NPEB_ETH0)) -- return -ENOSYS; - -- /* All MII PHY accesses use NPE-B Ethernet registers */ - spin_lock_init(&mdio_lock); -- mdio_regs = (struct eth_regs __iomem *)IXP4XX_EthB_BASE_VIRT; -+ if (!cpu_is_ixp43x()) -+ /* All MII PHY accesses use NPE-B Ethernet registers */ -+ mdio_regs = (struct eth_regs __iomem *)IXP4XX_EthB_BASE_VIRT; -+ -+ else -+ /* IXP43x lacks NPE-B and uses NPE-C for MII PHY access */ -+ mdio_regs = (struct eth_regs __iomem *)IXP4XX_EthC_BASE_VIRT; -+ - __raw_writel(DEFAULT_CORE_CNTRL, &mdio_regs->core_control); - - return platform_driver_register(&drv); ---- a/arch/arm/mach-ixp4xx/include/mach/cpu.h -+++ b/arch/arm/mach-ixp4xx/include/mach/cpu.h -@@ -35,6 +35,8 @@ static inline u32 ixp4xx_read_feature_bi - val &= ~IXP4XX_FEATURE_RESERVED; - if (!cpu_is_ixp46x()) - val &= ~IXP4XX_FEATURE_IXP46X_ONLY; -+ if (cpu_is_ixp42x()) -+ val &= ~IXP4XX_FEATURE_IXP43X_46X; - - return val; - } ---- a/arch/arm/mach-ixp4xx/include/mach/ixp4xx-regs.h -+++ b/arch/arm/mach-ixp4xx/include/mach/ixp4xx-regs.h -@@ -628,11 +628,12 @@ - #define IXP4XX_FEATURE_XSCALE_MAX_FREQ (3 << 22) - #define IXP4XX_FEATURE_RESERVED (0xFF << 24) - --#define IXP4XX_FEATURE_IXP46X_ONLY (IXP4XX_FEATURE_ECC_TIMESYNC | \ -+#define IXP4XX_FEATURE_IXP43X_46X (IXP4XX_FEATURE_ECC_TIMESYNC | \ - IXP4XX_FEATURE_USB_HOST | \ - IXP4XX_FEATURE_NPEA_ETH | \ -- IXP4XX_FEATURE_NPEB_ETH_1_TO_3 | \ -- IXP4XX_FEATURE_RSA | \ - IXP4XX_FEATURE_XSCALE_MAX_FREQ) - -+#define IXP4XX_FEATURE_IXP46X_ONLY (IXP4XX_FEATURE_NPEB_ETH_1_TO_3 | \ -+ IXP4XX_FEATURE_RSA) -+ - #endif diff --git a/target/linux/ixp4xx/patches-2.6.28/210-npe_hss.patch b/target/linux/ixp4xx/patches-2.6.28/210-npe_hss.patch deleted file mode 100644 index 49ea5e090..000000000 --- a/target/linux/ixp4xx/patches-2.6.28/210-npe_hss.patch +++ /dev/null @@ -1,2917 +0,0 @@ ---- a/drivers/net/wan/Kconfig -+++ b/drivers/net/wan/Kconfig -@@ -333,6 +333,15 @@ config DSCC4_PCI_RST - - Say Y if your card supports this feature. - -+config IXP4XX_HSS -+ tristate "IXP4xx HSS (synchronous serial port) support" -+ depends on HDLC && ARM && ARCH_IXP4XX -+ select IXP4XX_NPE -+ select IXP4XX_QMGR -+ help -+ Say Y here if you want to use built-in HSS ports -+ on IXP4xx processor. -+ - config DLCI - tristate "Frame Relay DLCI support" - ---help--- ---- a/drivers/net/wan/Makefile -+++ b/drivers/net/wan/Makefile -@@ -41,6 +41,7 @@ obj-$(CONFIG_C101) += c101.o - obj-$(CONFIG_WANXL) += wanxl.o - obj-$(CONFIG_PCI200SYN) += pci200syn.o - obj-$(CONFIG_PC300TOO) += pc300too.o -+obj-$(CONFIG_IXP4XX_HSS) += ixp4xx_hss.o - - clean-files := wanxlfw.inc - $(obj)/wanxl.o: $(obj)/wanxlfw.inc ---- /dev/null -+++ b/drivers/net/wan/ixp4xx_hss.c -@@ -0,0 +1,2886 @@ -+/* -+ * Intel IXP4xx HSS (synchronous serial port) driver for Linux -+ * -+ * Copyright (C) 2007 Krzysztof Halasa -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of version 2 of the GNU General Public License -+ * as published by the Free Software Foundation. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#define DEBUG_QUEUES 0 -+#define DEBUG_DESC 0 -+#define DEBUG_RX 0 -+#define DEBUG_TX 0 -+#define DEBUG_PKT_BYTES 0 -+#define DEBUG_CLOSE 0 -+#define DEBUG_FRAMER 0 -+ -+#define DRV_NAME "ixp4xx_hss" -+ -+#define PKT_EXTRA_FLAGS 0 /* orig 1 */ -+#define TX_FRAME_SYNC_OFFSET 0 /* channelized */ -+#define PKT_NUM_PIPES 1 /* 1, 2 or 4 */ -+#define PKT_PIPE_FIFO_SIZEW 4 /* total 4 dwords per HSS */ -+ -+#define RX_DESCS 16 /* also length of all RX queues */ -+#define TX_DESCS 16 /* also length of all TX queues */ -+ -+#define POOL_ALLOC_SIZE (sizeof(struct desc) * (RX_DESCS + TX_DESCS)) -+#define RX_SIZE (HDLC_MAX_MRU + 4) /* NPE needs more space */ -+#define MAX_CLOSE_WAIT 1000 /* microseconds */ -+#define HSS_COUNT 2 -+#define MIN_FRAME_SIZE 16 /* bits */ -+#define MAX_FRAME_SIZE 257 /* 256 bits + framing bit */ -+#define MAX_CHANNELS (MAX_FRAME_SIZE / 8) -+#define MAX_CHAN_DEVICES 32 -+#define CHANNEL_HDLC 0xFE -+#define CHANNEL_UNUSED 0xFF -+ -+#define NAPI_WEIGHT 16 -+#define CHAN_RX_TRIGGER 16 /* 8 RX frames = 1 ms @ E1 */ -+#define CHAN_RX_FRAMES 64 -+#define MAX_CHAN_RX_BAD_SYNC (CHAN_RX_TRIGGER / 2 /* pairs */ - 3) -+#define CHAN_TX_LIST_FRAMES 16 /* bytes/channel per list, 16 - 48 */ -+#define CHAN_TX_LISTS 8 -+#define CHAN_TX_FRAMES (CHAN_TX_LIST_FRAMES * CHAN_TX_LISTS) -+#define CHAN_QUEUE_LEN 16 /* minimum possible */ -+ -+ -+/* Queue IDs */ -+#define HSS0_CHL_RXTRIG_QUEUE 12 /* orig size = 32 dwords */ -+#define HSS0_PKT_RX_QUEUE 13 /* orig size = 32 dwords */ -+#define HSS0_PKT_TX0_QUEUE 14 /* orig size = 16 dwords */ -+#define HSS0_PKT_TX1_QUEUE 15 -+#define HSS0_PKT_TX2_QUEUE 16 -+#define HSS0_PKT_TX3_QUEUE 17 -+#define HSS0_PKT_RXFREE0_QUEUE 18 /* orig size = 16 dwords */ -+#define HSS0_PKT_RXFREE1_QUEUE 19 -+#define HSS0_PKT_RXFREE2_QUEUE 20 -+#define HSS0_PKT_RXFREE3_QUEUE 21 -+#define HSS0_PKT_TXDONE_QUEUE 22 /* orig size = 64 dwords */ -+ -+#define HSS1_CHL_RXTRIG_QUEUE 10 -+#define HSS1_PKT_RX_QUEUE 0 -+#define HSS1_PKT_TX0_QUEUE 5 -+#define HSS1_PKT_TX1_QUEUE 6 -+#define HSS1_PKT_TX2_QUEUE 7 -+#define HSS1_PKT_TX3_QUEUE 8 -+#define HSS1_PKT_RXFREE0_QUEUE 1 -+#define HSS1_PKT_RXFREE1_QUEUE 2 -+#define HSS1_PKT_RXFREE2_QUEUE 3 -+#define HSS1_PKT_RXFREE3_QUEUE 4 -+#define HSS1_PKT_TXDONE_QUEUE 9 -+ -+#define NPE_PKT_MODE_HDLC 0 -+#define NPE_PKT_MODE_RAW 1 -+#define NPE_PKT_MODE_56KMODE 2 -+#define NPE_PKT_MODE_56KENDIAN_MSB 4 -+ -+/* PKT_PIPE_HDLC_CFG_WRITE flags */ -+#define PKT_HDLC_IDLE_ONES 0x1 /* default = flags */ -+#define PKT_HDLC_CRC_32 0x2 /* default = CRC-16 */ -+#define PKT_HDLC_MSB_ENDIAN 0x4 /* default = LE */ -+ -+ -+/* hss_config, PCRs */ -+/* Frame sync sampling, default = active low */ -+#define PCR_FRM_SYNC_ACTIVE_HIGH 0x40000000 -+#define PCR_FRM_SYNC_FALLINGEDGE 0x80000000 -+#define PCR_FRM_SYNC_RISINGEDGE 0xC0000000 -+ -+/* Frame sync pin: input (default) or output generated off a given clk edge */ -+#define PCR_FRM_SYNC_OUTPUT_FALLING 0x20000000 -+#define PCR_FRM_SYNC_OUTPUT_RISING 0x30000000 -+ -+/* Frame and data clock sampling on edge, default = falling */ -+#define PCR_FCLK_EDGE_RISING 0x08000000 -+#define PCR_DCLK_EDGE_RISING 0x04000000 -+ -+/* Clock direction, default = input */ -+#define PCR_SYNC_CLK_DIR_OUTPUT 0x02000000 -+ -+/* Generate/Receive frame pulses, default = enabled */ -+#define PCR_FRM_PULSE_DISABLED 0x01000000 -+ -+ /* Data rate is full (default) or half the configured clk speed */ -+#define PCR_HALF_CLK_RATE 0x00200000 -+ -+/* Invert data between NPE and HSS FIFOs? (default = no) */ -+#define PCR_DATA_POLARITY_INVERT 0x00100000 -+ -+/* TX/RX endianness, default = LSB */ -+#define PCR_MSB_ENDIAN 0x00080000 -+ -+/* Normal (default) / open drain mode (TX only) */ -+#define PCR_TX_PINS_OPEN_DRAIN 0x00040000 -+ -+/* No framing bit transmitted and expected on RX? (default = framing bit) */ -+#define PCR_SOF_NO_FBIT 0x00020000 -+ -+/* Drive data pins? */ -+#define PCR_TX_DATA_ENABLE 0x00010000 -+ -+/* Voice 56k type: drive the data pins low (default), high, high Z */ -+#define PCR_TX_V56K_HIGH 0x00002000 -+#define PCR_TX_V56K_HIGH_IMP 0x00004000 -+ -+/* Unassigned type: drive the data pins low (default), high, high Z */ -+#define PCR_TX_UNASS_HIGH 0x00000800 -+#define PCR_TX_UNASS_HIGH_IMP 0x00001000 -+ -+/* T1 @ 1.544MHz only: Fbit dictated in FIFO (default) or high Z */ -+#define PCR_TX_FB_HIGH_IMP 0x00000400 -+ -+/* 56k data endiannes - which bit unused: high (default) or low */ -+#define PCR_TX_56KE_BIT_0_UNUSED 0x00000200 -+ -+/* 56k data transmission type: 32/8 bit data (default) or 56K data */ -+#define PCR_TX_56KS_56K_DATA 0x00000100 -+ -+/* hss_config, cCR */ -+/* Number of packetized clients, default = 1 */ -+#define CCR_NPE_HFIFO_2_HDLC 0x04000000 -+#define CCR_NPE_HFIFO_3_OR_4HDLC 0x08000000 -+ -+/* default = no loopback */ -+#define CCR_LOOPBACK 0x02000000 -+ -+/* HSS number, default = 0 (first) */ -+#define CCR_SECOND_HSS 0x01000000 -+ -+ -+/* hss_config, clkCR: main:10, num:10, denom:12 */ -+#define CLK42X_SPEED_EXP ((0x3FF << 22) | ( 2 << 12) | 15) /*65 KHz*/ -+ -+#define CLK42X_SPEED_512KHZ (( 130 << 22) | ( 2 << 12) | 15) -+#define CLK42X_SPEED_1536KHZ (( 43 << 22) | ( 18 << 12) | 47) -+#define CLK42X_SPEED_1544KHZ (( 43 << 22) | ( 33 << 12) | 192) -+#define CLK42X_SPEED_2048KHZ (( 32 << 22) | ( 34 << 12) | 63) -+#define CLK42X_SPEED_4096KHZ (( 16 << 22) | ( 34 << 12) | 127) -+#define CLK42X_SPEED_8192KHZ (( 8 << 22) | ( 34 << 12) | 255) -+ -+#define CLK46X_SPEED_512KHZ (( 130 << 22) | ( 24 << 12) | 127) -+#define CLK46X_SPEED_1536KHZ (( 43 << 22) | (152 << 12) | 383) -+#define CLK46X_SPEED_1544KHZ (( 43 << 22) | ( 66 << 12) | 385) -+#define CLK46X_SPEED_2048KHZ (( 32 << 22) | (280 << 12) | 511) -+#define CLK46X_SPEED_4096KHZ (( 16 << 22) | (280 << 12) | 1023) -+#define CLK46X_SPEED_8192KHZ (( 8 << 22) | (280 << 12) | 2047) -+ -+ -+/* hss_config, LUT entries */ -+#define TDMMAP_UNASSIGNED 0 -+#define TDMMAP_HDLC 1 /* HDLC - packetized */ -+#define TDMMAP_VOICE56K 2 /* Voice56K - 7-bit channelized */ -+#define TDMMAP_VOICE64K 3 /* Voice64K - 8-bit channelized */ -+ -+/* offsets into HSS config */ -+#define HSS_CONFIG_TX_PCR 0x00 /* port configuration registers */ -+#define HSS_CONFIG_RX_PCR 0x04 -+#define HSS_CONFIG_CORE_CR 0x08 /* loopback control, HSS# */ -+#define HSS_CONFIG_CLOCK_CR 0x0C /* clock generator control */ -+#define HSS_CONFIG_TX_FCR 0x10 /* frame configuration registers */ -+#define HSS_CONFIG_RX_FCR 0x14 -+#define HSS_CONFIG_TX_LUT 0x18 /* channel look-up tables */ -+#define HSS_CONFIG_RX_LUT 0x38 -+ -+ -+/* NPE command codes */ -+/* writes the ConfigWord value to the location specified by offset */ -+#define PORT_CONFIG_WRITE 0x40 -+ -+/* triggers the NPE to load the contents of the configuration table */ -+#define PORT_CONFIG_LOAD 0x41 -+ -+/* triggers the NPE to return an HssErrorReadResponse message */ -+#define PORT_ERROR_READ 0x42 -+ -+/* reset NPE internal status and enable the HssChannelized operation */ -+#define CHAN_FLOW_ENABLE 0x43 -+#define CHAN_FLOW_DISABLE 0x44 -+#define CHAN_IDLE_PATTERN_WRITE 0x45 -+#define CHAN_NUM_CHANS_WRITE 0x46 -+#define CHAN_RX_BUF_ADDR_WRITE 0x47 -+#define CHAN_RX_BUF_CFG_WRITE 0x48 -+#define CHAN_TX_BLK_CFG_WRITE 0x49 -+#define CHAN_TX_BUF_ADDR_WRITE 0x4A -+#define CHAN_TX_BUF_SIZE_WRITE 0x4B -+#define CHAN_TSLOTSWITCH_ENABLE 0x4C -+#define CHAN_TSLOTSWITCH_DISABLE 0x4D -+ -+/* downloads the gainWord value for a timeslot switching channel associated -+ with bypassNum */ -+#define CHAN_TSLOTSWITCH_GCT_DOWNLOAD 0x4E -+ -+/* triggers the NPE to reset internal status and enable the HssPacketized -+ operation for the flow specified by pPipe */ -+#define PKT_PIPE_FLOW_ENABLE 0x50 -+#define PKT_PIPE_FLOW_DISABLE 0x51 -+#define PKT_NUM_PIPES_WRITE 0x52 -+#define PKT_PIPE_FIFO_SIZEW_WRITE 0x53 -+#define PKT_PIPE_HDLC_CFG_WRITE 0x54 -+#define PKT_PIPE_IDLE_PATTERN_WRITE 0x55 -+#define PKT_PIPE_RX_SIZE_WRITE 0x56 -+#define PKT_PIPE_MODE_WRITE 0x57 -+ -+/* HDLC packet status values - desc->status */ -+#define ERR_SHUTDOWN 1 /* stop or shutdown occurrance */ -+#define ERR_HDLC_ALIGN 2 /* HDLC alignment error */ -+#define ERR_HDLC_FCS 3 /* HDLC Frame Check Sum error */ -+#define ERR_RXFREE_Q_EMPTY 4 /* RX-free queue became empty while receiving -+ this packet (if buf_len < pkt_len) */ -+#define ERR_HDLC_TOO_LONG 5 /* HDLC frame size too long */ -+#define ERR_HDLC_ABORT 6 /* abort sequence received */ -+#define ERR_DISCONNECTING 7 /* disconnect is in progress */ -+ -+ -+enum mode {MODE_HDLC = 0, MODE_RAW, MODE_G704}; -+enum error_bit {TX_ERROR_BIT = 0, RX_ERROR_BIT = 1}; -+enum alignment { NOT_ALIGNED = 0, EVEN_FIRST, ODD_FIRST }; -+ -+#ifdef __ARMEB__ -+typedef struct sk_buff buffer_t; -+#define free_buffer dev_kfree_skb -+#define free_buffer_irq dev_kfree_skb_irq -+#else -+typedef void buffer_t; -+#define free_buffer kfree -+#define free_buffer_irq kfree -+#endif -+ -+struct chan_device { -+ struct cdev cdev; -+ struct device *dev; -+ struct port *port; -+ unsigned int open_count, excl_open; -+ unsigned int tx_first, tx_count, rx_first, rx_count; /* bytes */ -+ unsigned long errors_bitmap; -+ u8 id, chan_count; -+ u8 log_channels[MAX_CHANNELS]; -+}; -+ -+struct port { -+ struct device *dev; -+ struct npe *npe; -+ struct net_device *netdev; -+ struct napi_struct napi; -+ struct hss_plat_info *plat; -+ buffer_t *rx_buff_tab[RX_DESCS], *tx_buff_tab[TX_DESCS]; -+ struct desc *desc_tab; /* coherent */ -+ u32 desc_tab_phys; -+ unsigned int id; -+ atomic_t chan_tx_irq_number, chan_rx_irq_number; -+ wait_queue_head_t chan_tx_waitq, chan_rx_waitq; -+ u8 hdlc_cfg; -+ -+ /* the following fields must be protected by npe_lock */ -+ enum mode mode; -+ unsigned int clock_type, clock_rate, loopback; -+ unsigned int frame_size, frame_sync_offset; -+ -+ struct chan_device *chan_devices[MAX_CHAN_DEVICES]; -+ u8 *chan_buf; -+ u32 chan_tx_buf_phys, chan_rx_buf_phys; -+ unsigned int chan_open_count, hdlc_open; -+ unsigned int chan_started, initialized, just_set_offset; -+ enum alignment aligned, carrier; -+ unsigned int chan_last_rx, chan_last_tx; -+ /* assigned channels, may be invalid with given frame length or mode */ -+ u8 channels[MAX_CHANNELS]; -+ int msg_count; -+}; -+ -+/* NPE message structure */ -+struct msg { -+#ifdef __ARMEB__ -+ u8 cmd, unused, hss_port, index; -+ union { -+ struct { u8 data8a, data8b, data8c, data8d; }; -+ struct { u16 data16a, data16b; }; -+ struct { u32 data32; }; -+ }; -+#else -+ u8 index, hss_port, unused, cmd; -+ union { -+ struct { u8 data8d, data8c, data8b, data8a; }; -+ struct { u16 data16b, data16a; }; -+ struct { u32 data32; }; -+ }; -+#endif -+}; -+ -+/* HDLC packet descriptor */ -+struct desc { -+ u32 next; /* pointer to next buffer, unused */ -+ -+#ifdef __ARMEB__ -+ u16 buf_len; /* buffer length */ -+ u16 pkt_len; /* packet length */ -+ u32 data; /* pointer to data buffer in RAM */ -+ u8 status; -+ u8 error_count; -+ u16 __reserved; -+#else -+ u16 pkt_len; /* packet length */ -+ u16 buf_len; /* buffer length */ -+ u32 data; /* pointer to data buffer in RAM */ -+ u16 __reserved; -+ u8 error_count; -+ u8 status; -+#endif -+ u32 __reserved1[4]; -+}; -+ -+ -+#define rx_desc_phys(port, n) ((port)->desc_tab_phys + \ -+ (n) * sizeof(struct desc)) -+#define rx_desc_ptr(port, n) (&(port)->desc_tab[n]) -+ -+#define tx_desc_phys(port, n) ((port)->desc_tab_phys + \ -+ ((n) + RX_DESCS) * sizeof(struct desc)) -+#define tx_desc_ptr(port, n) (&(port)->desc_tab[(n) + RX_DESCS]) -+ -+#define chan_tx_buf_len(port) (port->frame_size / 8 * CHAN_TX_FRAMES) -+#define chan_tx_lists_len(port) (port->frame_size / 8 * CHAN_TX_LISTS * \ -+ sizeof(u32)) -+#define chan_rx_buf_len(port) (port->frame_size / 8 * CHAN_RX_FRAMES) -+ -+#define chan_tx_buf(port) ((port)->chan_buf) -+#define chan_tx_lists(port) (chan_tx_buf(port) + chan_tx_buf_len(port)) -+#define chan_rx_buf(port) (chan_tx_lists(port) + chan_tx_lists_len(port)) -+ -+#define chan_tx_lists_phys(port) ((port)->chan_tx_buf_phys + \ -+ chan_tx_buf_len(port)) -+ -+static int hss_prepare_chan(struct port *port); -+void hss_chan_stop(struct port *port); -+ -+/***************************************************************************** -+ * global variables -+ ****************************************************************************/ -+ -+static struct class *hss_class; -+static int chan_major; -+static int ports_open; -+static struct dma_pool *dma_pool; -+static spinlock_t npe_lock; -+ -+static const struct { -+ int tx, txdone, rx, rxfree, chan; -+}queue_ids[2] = {{HSS0_PKT_TX0_QUEUE, HSS0_PKT_TXDONE_QUEUE, HSS0_PKT_RX_QUEUE, -+ HSS0_PKT_RXFREE0_QUEUE, HSS0_CHL_RXTRIG_QUEUE}, -+ {HSS1_PKT_TX0_QUEUE, HSS1_PKT_TXDONE_QUEUE, HSS1_PKT_RX_QUEUE, -+ HSS1_PKT_RXFREE0_QUEUE, HSS1_CHL_RXTRIG_QUEUE}, -+}; -+ -+/***************************************************************************** -+ * utility functions -+ ****************************************************************************/ -+ -+static inline struct port* dev_to_port(struct net_device *dev) -+{ -+ return dev_to_hdlc(dev)->priv; -+} -+ -+static inline struct chan_device* inode_to_chan_dev(struct inode *inode) -+{ -+ return container_of(inode->i_cdev, struct chan_device, cdev); -+} -+ -+#ifndef __ARMEB__ -+static inline void memcpy_swab32(u32 *dest, u32 *src, int cnt) -+{ -+ int i; -+ for (i = 0; i < cnt; i++) -+ dest[i] = swab32(src[i]); -+} -+#endif -+ -+static int get_number(const char **buf, size_t *len, unsigned int *ptr, -+ unsigned int min, unsigned int max) -+{ -+ char *endp; -+ unsigned long val = simple_strtoul(*buf, &endp, 10); -+ -+ if (endp == *buf || endp - *buf > *len || val < min || val > max) -+ return -EINVAL; -+ *len -= endp - *buf; -+ *buf = endp; -+ *ptr = val; -+ return 0; -+} -+ -+static int parse_channels(const char **buf, size_t *len, u8 *channels) -+{ -+ unsigned int ch, next = 0; -+ -+ if (*len && (*buf)[*len - 1] == '\n') -+ (*len)--; -+ -+ memset(channels, 0, MAX_CHANNELS); -+ -+ if (!*len) -+ return 0; -+ -+ /* Format: "A,B-C,...", A > B > C */ -+ while (1) { -+ if (get_number(buf, len, &ch, next, MAX_CHANNELS - 1)) -+ return -EINVAL; -+ channels[ch] = 1; -+ next = ch + 1; -+ if (!*len) -+ break; -+ if (**buf == ',') { -+ (*buf)++; -+ (*len)--; -+ continue; -+ } -+ if (**buf != '-') -+ return -EINVAL; -+ (*buf)++; -+ (*len)--; -+ if (get_number(buf, len, &ch, next, MAX_CHANNELS - 1)) -+ return -EINVAL; -+ while (next <= ch) -+ channels[next++] = 1; -+ if (!*len) -+ break; -+ if (**buf != ',') -+ return -EINVAL; -+ (*buf)++; -+ (*len)--; -+ } -+ return 1; -+} -+ -+static size_t print_channels(struct port *port, char *buf, u8 id) -+{ -+ unsigned int ch, cnt = 0; -+ size_t len = 0; -+ -+ for (ch = 0; ch < MAX_CHANNELS; ch++) -+ if (port->channels[ch] == id) { -+ if (cnt == 0) { -+ sprintf(buf + len, "%s%u", len ? "," : "", ch); -+ len += strlen(buf + len); -+ } -+ cnt++; -+ } else { -+ if (cnt > 1) { -+ sprintf(buf + len, "-%u", ch - 1); -+ len += strlen(buf + len); -+ } -+ cnt = 0; -+ } -+ if (cnt > 1) { -+ sprintf(buf + len, "-%u", ch - 1); -+ len += strlen(buf + len); -+ } -+ -+ buf[len++] = '\n'; -+ return len; -+} -+ -+static inline unsigned int sub_offset(unsigned int a, unsigned int b, -+ unsigned int modulo) -+{ -+ return (modulo /* make sure the result >= 0 */ + a - b) % modulo; -+} -+ -+/***************************************************************************** -+ * HSS access -+ ****************************************************************************/ -+ -+static void hss_config_load(struct port *port) -+{ -+ struct msg msg; -+ -+ do { -+ memset(&msg, 0, sizeof(msg)); -+ msg.cmd = PORT_CONFIG_LOAD; -+ msg.hss_port = port->id; -+ if (npe_send_message(port->npe, &msg, "HSS_LOAD_CONFIG")) -+ break; -+ if (npe_recv_message(port->npe, &msg, "HSS_LOAD_CONFIG")) -+ break; -+ -+ /* HSS_LOAD_CONFIG for port #1 returns port_id = #4 */ -+ if (msg.cmd != PORT_CONFIG_LOAD || msg.data32) -+ break; -+ -+ /* HDLC may stop working without this */ -+ npe_recv_message(port->npe, &msg, "FLUSH_IT"); -+ return; -+ } while (0); -+ -+ printk(KERN_CRIT "HSS-%i: unable to reload HSS configuration\n", -+ port->id); -+ BUG(); -+} -+ -+static void hss_config_set_pcr(struct port *port) -+{ -+ struct msg msg; -+ -+ do { -+ memset(&msg, 0, sizeof(msg)); -+ msg.cmd = PORT_CONFIG_WRITE; -+ msg.hss_port = port->id; -+ msg.index = HSS_CONFIG_TX_PCR; -+ msg.data32 = PCR_FRM_SYNC_OUTPUT_RISING | PCR_MSB_ENDIAN | -+ PCR_TX_DATA_ENABLE; -+ if (port->frame_size % 8 == 0) -+ msg.data32 |= PCR_SOF_NO_FBIT; -+ if (port->clock_type == CLOCK_INT) -+ msg.data32 |= PCR_SYNC_CLK_DIR_OUTPUT; -+ if (npe_send_message(port->npe, &msg, "HSS_SET_TX_PCR")) -+ break; -+ -+ msg.index = HSS_CONFIG_RX_PCR; -+ msg.data32 ^= PCR_TX_DATA_ENABLE | PCR_DCLK_EDGE_RISING; -+ if (npe_send_message(port->npe, &msg, "HSS_SET_RX_PCR")) -+ break; -+ return; -+ } while (0); -+ -+ printk(KERN_CRIT "HSS-%i: unable to set HSS PCR registers\n", port->id); -+ BUG(); -+} -+ -+static void hss_config_set_hdlc_cfg(struct port *port) -+{ -+ struct msg msg; -+ -+ memset(&msg, 0, sizeof(msg)); -+ msg.cmd = PKT_PIPE_HDLC_CFG_WRITE; -+ msg.hss_port = port->id; -+ msg.data8a = port->hdlc_cfg; /* rx_cfg */ -+ msg.data8b = port->hdlc_cfg | (PKT_EXTRA_FLAGS << 3); /* tx_cfg */ -+ if (npe_send_message(port->npe, &msg, "HSS_SET_HDLC_CFG")) { -+ printk(KERN_CRIT "HSS-%i: unable to set HSS HDLC" -+ " configuration\n", port->id); -+ BUG(); -+ } -+} -+ -+static void hss_config_set_core(struct port *port) -+{ -+ struct msg msg; -+ -+ memset(&msg, 0, sizeof(msg)); -+ msg.cmd = PORT_CONFIG_WRITE; -+ msg.hss_port = port->id; -+ msg.index = HSS_CONFIG_CORE_CR; -+ msg.data32 = (port->loopback ? CCR_LOOPBACK : 0) | -+ (port->id ? CCR_SECOND_HSS : 0); -+ if (npe_send_message(port->npe, &msg, "HSS_SET_CORE_CR")) { -+ printk(KERN_CRIT "HSS-%i: unable to set HSS core control" -+ " register\n", port->id); -+ BUG(); -+ } -+} -+ -+static void hss_config_set_line(struct port *port) -+{ -+ struct msg msg; -+ -+ hss_config_set_pcr(port); -+ hss_config_set_core(port); -+ -+ memset(&msg, 0, sizeof(msg)); -+ msg.cmd = PORT_CONFIG_WRITE; -+ msg.hss_port = port->id; -+ msg.index = HSS_CONFIG_CLOCK_CR; -+ msg.data32 = CLK42X_SPEED_2048KHZ /* FIXME */; -+ if (npe_send_message(port->npe, &msg, "HSS_SET_CLOCK_CR")) { -+ printk(KERN_CRIT "HSS-%i: unable to set HSS clock control" -+ " register\n", port->id); -+ BUG(); -+ } -+} -+ -+static void hss_config_set_rx_frame(struct port *port) -+{ -+ struct msg msg; -+ -+ memset(&msg, 0, sizeof(msg)); -+ msg.cmd = PORT_CONFIG_WRITE; -+ msg.hss_port = port->id; -+ msg.index = HSS_CONFIG_RX_FCR; -+ msg.data16a = port->frame_sync_offset; -+ msg.data16b = port->frame_size - 1; -+ if (npe_send_message(port->npe, &msg, "HSS_SET_RX_FCR")) { -+ printk(KERN_CRIT "HSS-%i: unable to set HSS RX frame size" -+ " and offset\n", port->id); -+ BUG(); -+ } -+} -+ -+static void hss_config_set_frame(struct port *port) -+{ -+ struct msg msg; -+ -+ memset(&msg, 0, sizeof(msg)); -+ msg.cmd = PORT_CONFIG_WRITE; -+ msg.hss_port = port->id; -+ msg.index = HSS_CONFIG_TX_FCR; -+ msg.data16a = TX_FRAME_SYNC_OFFSET; -+ msg.data16b = port->frame_size - 1; -+ if (npe_send_message(port->npe, &msg, "HSS_SET_TX_FCR")) { -+ printk(KERN_CRIT "HSS-%i: unable to set HSS TX frame size" -+ " and offset\n", port->id); -+ BUG(); -+ } -+ hss_config_set_rx_frame(port); -+} -+ -+static void hss_config_set_lut(struct port *port) -+{ -+ struct msg msg; -+ int chan_count = 0, log_chan = 0, i, ch; -+ u32 lut[MAX_CHANNELS / 4]; -+ -+ memset(lut, 0, sizeof(lut)); -+ for (i = 0; i < MAX_CHAN_DEVICES; i++) -+ if (port->chan_devices[i]) -+ port->chan_devices[i]->chan_count = 0; -+ -+ memset(&msg, 0, sizeof(msg)); -+ msg.cmd = PORT_CONFIG_WRITE; -+ msg.hss_port = port->id; -+ -+ for (ch = 0; ch < MAX_CHANNELS; ch++) { -+ struct chan_device *chdev = NULL; -+ unsigned int entry; -+ -+ if (port->channels[ch] < MAX_CHAN_DEVICES /* assigned */) -+ chdev = port->chan_devices[port->channels[ch]]; -+ -+ if (port->mode == MODE_G704 && ch == 0) -+ entry = TDMMAP_VOICE64K; /* PCM-31 pattern */ -+ else if (port->mode == MODE_HDLC || -+ port->channels[ch] == CHANNEL_HDLC) -+ entry = TDMMAP_HDLC; -+ else if (chdev && chdev->open_count) { -+ entry = TDMMAP_VOICE64K; -+ chdev->log_channels[chdev->chan_count++] = log_chan; -+ } else -+ entry = TDMMAP_UNASSIGNED; -+ if (entry == TDMMAP_VOICE64K) { -+ chan_count++; -+ log_chan++; -+ } -+ -+ msg.data32 >>= 2; -+ msg.data32 |= entry << 30; -+ -+ if (ch % 16 == 15) { -+ msg.index = HSS_CONFIG_TX_LUT + ((ch / 4) & ~3); -+ if (npe_send_message(port->npe, &msg, "HSS_SET_TX_LUT")) -+ break; -+ -+ msg.index += HSS_CONFIG_RX_LUT - HSS_CONFIG_TX_LUT; -+ if (npe_send_message(port->npe, &msg, "HSS_SET_RX_LUT")) -+ break; -+ } -+ } -+ if (ch != MAX_CHANNELS) { -+ printk(KERN_CRIT "HSS-%i: unable to set HSS channel look-up" -+ " table\n", port->id); -+ BUG(); -+ } -+ -+ hss_config_set_frame(port); -+ -+ if (!chan_count) -+ return; -+ -+ memset(&msg, 0, sizeof(msg)); -+ msg.cmd = CHAN_NUM_CHANS_WRITE; -+ msg.hss_port = port->id; -+ msg.data8a = chan_count; -+ if (npe_send_message(port->npe, &msg, "CHAN_NUM_CHANS_WRITE")) { -+ printk(KERN_CRIT "HSS-%i: unable to set HSS channel count\n", -+ port->id); -+ BUG(); -+ } -+ -+ /* don't leak data */ -+ // FIXME memset(chan_tx_buf(port), 0, CHAN_TX_FRAMES * chan_count); -+ if (port->mode == MODE_G704) /* G.704 PCM-31 sync pattern */ -+ for (i = 0; i < CHAN_TX_FRAMES; i += 4) -+ *(u32*)(chan_tx_buf(port) + i) = 0x9BDF9BDF; -+ -+ for (i = 0; i < CHAN_TX_LISTS; i++) { -+ u32 phys = port->chan_tx_buf_phys + i * CHAN_TX_LIST_FRAMES; -+ u32 *list = ((u32 *)chan_tx_lists(port)) + i * chan_count; -+ for (ch = 0; ch < chan_count; ch++) -+ list[ch] = phys + ch * CHAN_TX_FRAMES; -+ } -+ dma_sync_single(port->dev, port->chan_tx_buf_phys, -+ chan_tx_buf_len(port) + chan_tx_lists_len(port), -+ DMA_TO_DEVICE); -+} -+ -+static u32 hss_config_get_status(struct port *port) -+{ -+ struct msg msg; -+ -+ do { -+ memset(&msg, 0, sizeof(msg)); -+ msg.cmd = PORT_ERROR_READ; -+ msg.hss_port = port->id; -+ if (npe_send_message(port->npe, &msg, "PORT_ERROR_READ")) -+ break; -+ if (npe_recv_message(port->npe, &msg, "PORT_ERROR_READ")) -+ break; -+ -+ return msg.data32; -+ } while (0); -+ -+ printk(KERN_CRIT "HSS-%i: unable to read HSS status\n", port->id); -+ BUG(); -+} -+ -+static void hss_config_start_chan(struct port *port) -+{ -+ struct msg msg; -+ -+ port->chan_last_tx = 0; -+ port->chan_last_rx = 0; -+ -+ do { -+ memset(&msg, 0, sizeof(msg)); -+ msg.cmd = CHAN_RX_BUF_ADDR_WRITE; -+ msg.hss_port = port->id; -+ msg.data32 = port->chan_rx_buf_phys; -+ if (npe_send_message(port->npe, &msg, "CHAN_RX_BUF_ADDR_WRITE")) -+ break; -+ -+ memset(&msg, 0, sizeof(msg)); -+ msg.cmd = CHAN_TX_BUF_ADDR_WRITE; -+ msg.hss_port = port->id; -+ msg.data32 = chan_tx_lists_phys(port); -+ if (npe_send_message(port->npe, &msg, "CHAN_TX_BUF_ADDR_WRITE")) -+ break; -+ -+ memset(&msg, 0, sizeof(msg)); -+ msg.cmd = CHAN_FLOW_ENABLE; -+ msg.hss_port = port->id; -+ if (npe_send_message(port->npe, &msg, "CHAN_FLOW_ENABLE")) -+ break; -+ port->chan_started = 1; -+ return; -+ } while (0); -+ -+ printk(KERN_CRIT "HSS-%i: unable to start channelized flow\n", -+ port->id); -+ BUG(); -+} -+ -+static void hss_config_stop_chan(struct port *port) -+{ -+ struct msg msg; -+ -+ if (!port->chan_started) -+ return; -+ -+ memset(&msg, 0, sizeof(msg)); -+ msg.cmd = CHAN_FLOW_DISABLE; -+ msg.hss_port = port->id; -+ if (npe_send_message(port->npe, &msg, "CHAN_FLOW_DISABLE")) { -+ printk(KERN_CRIT "HSS-%i: unable to stop channelized flow\n", -+ port->id); -+ BUG(); -+ } -+ hss_config_get_status(port); /* make sure it's halted */ -+} -+ -+static void hss_config_start_hdlc(struct port *port) -+{ -+ struct msg msg; -+ -+ memset(&msg, 0, sizeof(msg)); -+ msg.cmd = PKT_PIPE_FLOW_ENABLE; -+ msg.hss_port = port->id; -+ msg.data32 = 0; -+ if (npe_send_message(port->npe, &msg, "HSS_ENABLE_PKT_PIPE")) { -+ printk(KERN_CRIT "HSS-%i: unable to stop packetized flow\n", -+ port->id); -+ BUG(); -+ } -+} -+ -+static void hss_config_stop_hdlc(struct port *port) -+{ -+ struct msg msg; -+ -+ memset(&msg, 0, sizeof(msg)); -+ msg.cmd = PKT_PIPE_FLOW_DISABLE; -+ msg.hss_port = port->id; -+ if (npe_send_message(port->npe, &msg, "HSS_DISABLE_PKT_PIPE")) { -+ printk(KERN_CRIT "HSS-%i: unable to stop packetized flow\n", -+ port->id); -+ BUG(); -+ } -+ hss_config_get_status(port); /* make sure it's halted */ -+} -+ -+static int hss_config_load_firmware(struct port *port) -+{ -+ struct msg msg; -+ -+ if (port->initialized) -+ return 0; -+ -+ if (!npe_running(port->npe)) { -+ int err; -+ if ((err = npe_load_firmware(port->npe, npe_name(port->npe), -+ port->dev))) -+ return err; -+ } -+ -+ do { -+ /* HSS main configuration */ -+ hss_config_set_line(port); -+ -+ hss_config_set_frame(port); -+ -+ /* HDLC mode configuration */ -+ memset(&msg, 0, sizeof(msg)); -+ msg.cmd = PKT_NUM_PIPES_WRITE; -+ msg.hss_port = port->id; -+ msg.data8a = PKT_NUM_PIPES; -+ if (npe_send_message(port->npe, &msg, "HSS_SET_PKT_PIPES")) -+ break; -+ -+ msg.cmd = PKT_PIPE_FIFO_SIZEW_WRITE; -+ msg.data8a = PKT_PIPE_FIFO_SIZEW; -+ if (npe_send_message(port->npe, &msg, "HSS_SET_PKT_FIFO")) -+ break; -+ -+ msg.cmd = PKT_PIPE_MODE_WRITE; -+ msg.data8a = NPE_PKT_MODE_HDLC; -+ /* msg.data8b = inv_mask */ -+ /* msg.data8c = or_mask */ -+ if (npe_send_message(port->npe, &msg, "HSS_SET_PKT_MODE")) -+ break; -+ -+ msg.cmd = PKT_PIPE_RX_SIZE_WRITE; -+ msg.data16a = HDLC_MAX_MRU; /* including CRC */ -+ if (npe_send_message(port->npe, &msg, "HSS_SET_PKT_RX_SIZE")) -+ break; -+ -+ msg.cmd = PKT_PIPE_IDLE_PATTERN_WRITE; -+ msg.data32 = 0x7F7F7F7F; /* ??? FIXME */ -+ if (npe_send_message(port->npe, &msg, "HSS_SET_PKT_IDLE")) -+ break; -+ -+ /* Channelized operation settings */ -+ memset(&msg, 0, sizeof(msg)); -+ msg.cmd = CHAN_TX_BLK_CFG_WRITE; -+ msg.hss_port = port->id; -+ msg.data8b = (CHAN_TX_LIST_FRAMES & ~7) / 2; -+ msg.data8a = msg.data8b / 4; -+ msg.data8d = CHAN_TX_LIST_FRAMES - msg.data8b; -+ msg.data8c = msg.data8d / 4; -+ if (npe_send_message(port->npe, &msg, "CHAN_TX_BLK_CFG_WRITE")) -+ break; -+ -+ memset(&msg, 0, sizeof(msg)); -+ msg.cmd = CHAN_RX_BUF_CFG_WRITE; -+ msg.hss_port = port->id; -+ msg.data8a = CHAN_RX_TRIGGER / 8; -+ msg.data8b = CHAN_RX_FRAMES; -+ if (npe_send_message(port->npe, &msg, "CHAN_RX_BUF_CFG_WRITE")) -+ break; -+ -+ memset(&msg, 0, sizeof(msg)); -+ msg.cmd = CHAN_TX_BUF_SIZE_WRITE; -+ msg.hss_port = port->id; -+ msg.data8a = CHAN_TX_LISTS; -+ if (npe_send_message(port->npe, &msg, "CHAN_TX_BUF_SIZE_WRITE")) -+ break; -+ -+ port->initialized = 1; -+ return 0; -+ } while (0); -+ -+ printk(KERN_CRIT "HSS-%i: unable to start HSS operation\n", port->id); -+ BUG(); -+} -+ -+/***************************************************************************** -+ * packetized (HDLC) operation -+ ****************************************************************************/ -+ -+static inline void debug_pkt(struct net_device *dev, const char *func, -+ u8 *data, int len) -+{ -+#if DEBUG_PKT_BYTES -+ int i; -+ -+ printk(KERN_DEBUG "%s: %s(%i) ", dev->name, func, len); -+ for (i = 0; i < len; i++) { -+ if (i >= DEBUG_PKT_BYTES) -+ break; -+ printk(KERN_DEBUG "%s%02X", !(i % 4) ? " " : "", data[i]); -+ } -+ printk(KERN_DEBUG "\n"); -+#endif -+} -+ -+ -+static inline void debug_desc(u32 phys, struct desc *desc) -+{ -+#if DEBUG_DESC -+ printk(KERN_DEBUG "%X: %X %3X %3X %08X %X %X\n", -+ phys, desc->next, desc->buf_len, desc->pkt_len, -+ desc->data, desc->status, desc->error_count); -+#endif -+} -+ -+static inline void debug_queue(unsigned int queue, int is_get, u32 phys) -+{ -+#if DEBUG_QUEUES -+ static struct { -+ int queue; -+ char *name; -+ } names[] = { -+ { HSS0_PKT_TX0_QUEUE, "TX#0 " }, -+ { HSS0_PKT_TXDONE_QUEUE, "TX-done#0 " }, -+ { HSS0_PKT_RX_QUEUE, "RX#0 " }, -+ { HSS0_PKT_RXFREE0_QUEUE, "RX-free#0 " }, -+ { HSS1_PKT_TX0_QUEUE, "TX#1 " }, -+ { HSS1_PKT_TXDONE_QUEUE, "TX-done#1 " }, -+ { HSS1_PKT_RX_QUEUE, "RX#1 " }, -+ { HSS1_PKT_RXFREE0_QUEUE, "RX-free#1 " }, -+ }; -+ int i; -+ -+ for (i = 0; i < ARRAY_SIZE(names); i++) -+ if (names[i].queue == queue) -+ break; -+ -+ printk(KERN_DEBUG "Queue %i %s%s %X\n", queue, -+ i < ARRAY_SIZE(names) ? names[i].name : "", -+ is_get ? "->" : "<-", phys); -+#endif -+} -+ -+static inline u32 queue_get_entry(unsigned int queue) -+{ -+ u32 phys = qmgr_get_entry(queue); -+ debug_queue(queue, 1, phys); -+ return phys; -+} -+ -+static inline int queue_get_desc(unsigned int queue, struct port *port, -+ int is_tx) -+{ -+ u32 phys, tab_phys, n_desc; -+ struct desc *tab; -+ -+ if (!(phys = queue_get_entry(queue))) -+ return -1; -+ -+ BUG_ON(phys & 0x1F); -+ tab_phys = is_tx ? tx_desc_phys(port, 0) : rx_desc_phys(port, 0); -+ tab = is_tx ? tx_desc_ptr(port, 0) : rx_desc_ptr(port, 0); -+ n_desc = (phys - tab_phys) / sizeof(struct desc); -+ BUG_ON(n_desc >= (is_tx ? TX_DESCS : RX_DESCS)); -+ debug_desc(phys, &tab[n_desc]); -+ BUG_ON(tab[n_desc].next); -+ return n_desc; -+} -+ -+static inline void queue_put_desc(unsigned int queue, u32 phys, -+ struct desc *desc) -+{ -+ debug_queue(queue, 0, phys); -+ debug_desc(phys, desc); -+ BUG_ON(phys & 0x1F); -+ qmgr_put_entry(queue, phys); -+ BUG_ON(qmgr_stat_overflow(queue)); -+} -+ -+ -+static inline void dma_unmap_tx(struct port *port, struct desc *desc) -+{ -+#ifdef __ARMEB__ -+ dma_unmap_single(&port->netdev->dev, desc->data, -+ desc->buf_len, DMA_TO_DEVICE); -+#else -+ dma_unmap_single(&port->netdev->dev, desc->data & ~3, -+ ALIGN((desc->data & 3) + desc->buf_len, 4), -+ DMA_TO_DEVICE); -+#endif -+} -+ -+ -+static void hss_hdlc_set_carrier(void *pdev, int carrier) -+{ -+ struct net_device *netdev = pdev; -+ struct port *port = dev_to_port(netdev); -+ unsigned long flags; -+ -+ spin_lock_irqsave(&npe_lock, flags); -+ port->carrier = carrier; -+ if (!port->loopback) { -+ if (carrier) -+ netif_carrier_on(netdev); -+ else -+ netif_carrier_off(netdev); -+ } -+ spin_unlock_irqrestore(&npe_lock, flags); -+} -+ -+static void hss_hdlc_rx_irq(void *pdev) -+{ -+ struct net_device *dev = pdev; -+ struct port *port = dev_to_port(dev); -+ -+#if DEBUG_RX -+ printk(KERN_DEBUG "%s: hss_hdlc_rx_irq\n", dev->name); -+#endif -+ qmgr_disable_irq(queue_ids[port->id].rx); -+ netif_rx_schedule(dev, &port->napi); -+} -+ -+static int hss_hdlc_poll(struct napi_struct *napi, int budget) -+{ -+ struct port *port = container_of(napi, struct port, napi); -+ struct net_device *dev = port->netdev; -+ unsigned int rxq = queue_ids[port->id].rx; -+ unsigned int rxfreeq = queue_ids[port->id].rxfree; -+ struct net_device_stats *stats = hdlc_stats(dev); -+ int received = 0; -+ -+#if DEBUG_RX -+ printk(KERN_DEBUG "%s: hss_hdlc_poll\n", dev->name); -+#endif -+ -+ while (received < budget) { -+ struct sk_buff *skb; -+ struct desc *desc; -+ int n; -+#ifdef __ARMEB__ -+ struct sk_buff *temp; -+ u32 phys; -+#endif -+ -+ if ((n = queue_get_desc(rxq, port, 0)) < 0) { -+ received = 0; /* No packet received */ -+#if DEBUG_RX -+ printk(KERN_DEBUG "%s: hss_hdlc_poll" -+ " netif_rx_complete\n", dev->name); -+#endif -+ netif_rx_complete(dev, napi); -+ qmgr_enable_irq(rxq); -+ if (!qmgr_stat_empty(rxq) && -+ netif_rx_reschedule(dev, napi)) { -+#if DEBUG_RX -+ printk(KERN_DEBUG "%s: hss_hdlc_poll" -+ " netif_rx_reschedule succeeded\n", -+ dev->name); -+#endif -+ qmgr_disable_irq(rxq); -+ continue; -+ } -+#if DEBUG_RX -+ printk(KERN_DEBUG "%s: hss_hdlc_poll all done\n", -+ dev->name); -+#endif -+ return 0; /* all work done */ -+ } -+ -+ desc = rx_desc_ptr(port, n); -+#if 0 /* FIXME - error_count counts modulo 256, perhaps we should use it */ -+ if (desc->error_count) -+ printk(KERN_DEBUG "%s: hss_hdlc_poll status 0x%02X" -+ " errors %u\n", dev->name, desc->status, -+ desc->error_count); -+#endif -+ skb = NULL; -+ switch (desc->status) { -+ case 0: -+#ifdef __ARMEB__ -+ if ((skb = netdev_alloc_skb(dev, RX_SIZE)) != NULL) { -+ phys = dma_map_single(&dev->dev, skb->data, -+ RX_SIZE, -+ DMA_FROM_DEVICE); -+ if (dma_mapping_error(phys)) { -+ dev_kfree_skb(skb); -+ skb = NULL; -+ } -+ } -+#else -+ skb = netdev_alloc_skb(dev, desc->pkt_len); -+#endif -+ if (!skb) -+ stats->rx_dropped++; -+ break; -+ case ERR_HDLC_ALIGN: -+ case ERR_HDLC_ABORT: -+ stats->rx_frame_errors++; -+ stats->rx_errors++; -+ break; -+ case ERR_HDLC_FCS: -+ stats->rx_crc_errors++; -+ stats->rx_errors++; -+ break; -+ case ERR_HDLC_TOO_LONG: -+ stats->rx_length_errors++; -+ stats->rx_errors++; -+ break; -+ default: /* FIXME - remove printk */ -+ printk(KERN_ERR "%s: hss_hdlc_poll: status 0x%02X" -+ " errors %u\n", dev->name, desc->status, -+ desc->error_count); -+ stats->rx_errors++; -+ } -+ -+ if (!skb) { -+ /* put the desc back on RX-ready queue */ -+ desc->buf_len = RX_SIZE; -+ desc->pkt_len = desc->status = 0; -+ queue_put_desc(rxfreeq, rx_desc_phys(port, n), desc); -+ continue; -+ } -+ -+ /* process received frame */ -+#ifdef __ARMEB__ -+ temp = skb; -+ skb = port->rx_buff_tab[n]; -+ dma_unmap_single(&dev->dev, desc->data, -+ RX_SIZE, DMA_FROM_DEVICE); -+#else -+ dma_sync_single(&dev->dev, desc->data, -+ RX_SIZE, DMA_FROM_DEVICE); -+ memcpy_swab32((u32 *)skb->data, (u32 *)port->rx_buff_tab[n], -+ ALIGN(desc->pkt_len, 4) / 4); -+#endif -+ skb_put(skb, desc->pkt_len); -+ -+ debug_pkt(dev, "hss_hdlc_poll", skb->data, skb->len); -+ -+ skb->protocol = hdlc_type_trans(skb, dev); -+ dev->last_rx = jiffies; -+ stats->rx_packets++; -+ stats->rx_bytes += skb->len; -+ netif_receive_skb(skb); -+ -+ /* put the new buffer on RX-free queue */ -+#ifdef __ARMEB__ -+ port->rx_buff_tab[n] = temp; -+ desc->data = phys; -+#endif -+ desc->buf_len = RX_SIZE; -+ desc->pkt_len = 0; -+ queue_put_desc(rxfreeq, rx_desc_phys(port, n), desc); -+ received++; -+ } -+#if DEBUG_RX -+ printk(KERN_DEBUG "hss_hdlc_poll: end, not all work done\n"); -+#endif -+ return received; /* not all work done */ -+} -+ -+ -+static void hss_hdlc_txdone_irq(void *pdev) -+{ -+ struct net_device *dev = pdev; -+ struct port *port = dev_to_port(dev); -+ struct net_device_stats *stats = hdlc_stats(dev); -+ int n_desc; -+ -+#if DEBUG_TX -+ printk(KERN_DEBUG DRV_NAME ": hss_hdlc_txdone_irq\n"); -+#endif -+ while ((n_desc = queue_get_desc(queue_ids[port->id].txdone, -+ port, 1)) >= 0) { -+ struct desc *desc; -+ int start; -+ -+ desc = tx_desc_ptr(port, n_desc); -+ -+ stats->tx_packets++; -+ stats->tx_bytes += desc->pkt_len; -+ -+ dma_unmap_tx(port, desc); -+#if DEBUG_TX -+ printk(KERN_DEBUG "%s: hss_hdlc_txdone_irq free %p\n", -+ dev->name, port->tx_buff_tab[n_desc]); -+#endif -+ free_buffer_irq(port->tx_buff_tab[n_desc]); -+ port->tx_buff_tab[n_desc] = NULL; -+ -+ start = qmgr_stat_empty(port->plat->txreadyq); -+ queue_put_desc(port->plat->txreadyq, -+ tx_desc_phys(port, n_desc), desc); -+ if (start) { -+#if DEBUG_TX -+ printk(KERN_DEBUG "%s: hss_hdlc_txdone_irq xmit" -+ " ready\n", dev->name); -+#endif -+ netif_wake_queue(dev); -+ } -+ } -+} -+ -+static int hss_hdlc_xmit(struct sk_buff *skb, struct net_device *dev) -+{ -+ struct port *port = dev_to_port(dev); -+ struct net_device_stats *stats = hdlc_stats(dev); -+ unsigned int txreadyq = port->plat->txreadyq; -+ int len, offset, bytes, n; -+ void *mem; -+ u32 phys; -+ struct desc *desc; -+ -+#if DEBUG_TX -+ printk(KERN_DEBUG "%s: hss_hdlc_xmit\n", dev->name); -+#endif -+ -+ if (unlikely(skb->len > HDLC_MAX_MRU)) { -+ dev_kfree_skb(skb); -+ stats->tx_errors++; -+ return NETDEV_TX_OK; -+ } -+ -+ debug_pkt(dev, "hss_hdlc_xmit", skb->data, skb->len); -+ -+ len = skb->len; -+#ifdef __ARMEB__ -+ offset = 0; /* no need to keep alignment */ -+ bytes = len; -+ mem = skb->data; -+#else -+ offset = (int)skb->data & 3; /* keep 32-bit alignment */ -+ bytes = ALIGN(offset + len, 4); -+ if (!(mem = kmalloc(bytes, GFP_ATOMIC))) { -+ dev_kfree_skb(skb); -+ stats->tx_dropped++; -+ return NETDEV_TX_OK; -+ } -+ memcpy_swab32(mem, (u32 *)((int)skb->data & ~3), bytes / 4); -+ dev_kfree_skb(skb); -+#endif -+ -+ phys = dma_map_single(&dev->dev, mem, bytes, DMA_TO_DEVICE); -+ if (dma_mapping_error(phys)) { -+#ifdef __ARMEB__ -+ dev_kfree_skb(skb); -+#else -+ kfree(mem); -+#endif -+ stats->tx_dropped++; -+ return NETDEV_TX_OK; -+ } -+ -+ n = queue_get_desc(txreadyq, port, 1); -+ BUG_ON(n < 0); -+ desc = tx_desc_ptr(port, n); -+ -+#ifdef __ARMEB__ -+ port->tx_buff_tab[n] = skb; -+#else -+ port->tx_buff_tab[n] = mem; -+#endif -+ desc->data = phys + offset; -+ desc->buf_len = desc->pkt_len = len; -+ -+ wmb(); -+ queue_put_desc(queue_ids[port->id].tx, tx_desc_phys(port, n), desc); -+ dev->trans_start = jiffies; -+ -+ if (qmgr_stat_empty(txreadyq)) { -+#if DEBUG_TX -+ printk(KERN_DEBUG "%s: hss_hdlc_xmit queue full\n", dev->name); -+#endif -+ netif_stop_queue(dev); -+ /* we could miss TX ready interrupt */ -+ if (!qmgr_stat_empty(txreadyq)) { -+#if DEBUG_TX -+ printk(KERN_DEBUG "%s: hss_hdlc_xmit ready again\n", -+ dev->name); -+#endif -+ netif_wake_queue(dev); -+ } -+ } -+ -+#if DEBUG_TX -+ printk(KERN_DEBUG "%s: hss_hdlc_xmit end\n", dev->name); -+#endif -+ return NETDEV_TX_OK; -+} -+ -+ -+static int request_hdlc_queues(struct port *port) -+{ -+ int err; -+ -+ err = qmgr_request_queue(queue_ids[port->id].rxfree, RX_DESCS, 0, 0); -+ if (err) -+ return err; -+ -+ err = qmgr_request_queue(queue_ids[port->id].rx, RX_DESCS, 0, 0); -+ if (err) -+ goto rel_rxfree; -+ -+ err = qmgr_request_queue(queue_ids[port->id].tx, TX_DESCS, 0, 0); -+ if (err) -+ goto rel_rx; -+ -+ err = qmgr_request_queue(port->plat->txreadyq, TX_DESCS, 0, 0); -+ if (err) -+ goto rel_tx; -+ -+ err = qmgr_request_queue(queue_ids[port->id].txdone, TX_DESCS, 0, 0); -+ if (err) -+ goto rel_txready; -+ return 0; -+ -+rel_txready: -+ qmgr_release_queue(port->plat->txreadyq); -+rel_tx: -+ qmgr_release_queue(queue_ids[port->id].tx); -+rel_rx: -+ qmgr_release_queue(queue_ids[port->id].rx); -+rel_rxfree: -+ qmgr_release_queue(queue_ids[port->id].rxfree); -+ printk(KERN_DEBUG "%s: unable to request hardware queues\n", -+ port->netdev->name); -+ return err; -+} -+ -+static void release_hdlc_queues(struct port *port) -+{ -+ qmgr_release_queue(queue_ids[port->id].rxfree); -+ qmgr_release_queue(queue_ids[port->id].rx); -+ qmgr_release_queue(queue_ids[port->id].txdone); -+ qmgr_release_queue(queue_ids[port->id].tx); -+ qmgr_release_queue(port->plat->txreadyq); -+} -+ -+static int init_hdlc_queues(struct port *port) -+{ -+ int i; -+ -+ if (!ports_open) -+ if (!(dma_pool = dma_pool_create(DRV_NAME, NULL, -+ POOL_ALLOC_SIZE, 32, 0))) -+ return -ENOMEM; -+ -+ if (!(port->desc_tab = dma_pool_alloc(dma_pool, GFP_KERNEL, -+ &port->desc_tab_phys))) -+ return -ENOMEM; -+ memset(port->desc_tab, 0, POOL_ALLOC_SIZE); -+ memset(port->rx_buff_tab, 0, sizeof(port->rx_buff_tab)); /* tables */ -+ memset(port->tx_buff_tab, 0, sizeof(port->tx_buff_tab)); -+ -+ /* Setup RX buffers */ -+ for (i = 0; i < RX_DESCS; i++) { -+ struct desc *desc = rx_desc_ptr(port, i); -+ buffer_t *buff; -+ void *data; -+#ifdef __ARMEB__ -+ if (!(buff = netdev_alloc_skb(port->netdev, RX_SIZE))) -+ return -ENOMEM; -+ data = buff->data; -+#else -+ if (!(buff = kmalloc(RX_SIZE, GFP_KERNEL))) -+ return -ENOMEM; -+ data = buff; -+#endif -+ desc->buf_len = RX_SIZE; -+ desc->data = dma_map_single(&port->netdev->dev, data, -+ RX_SIZE, DMA_FROM_DEVICE); -+ if (dma_mapping_error(desc->data)) { -+ free_buffer(buff); -+ return -EIO; -+ } -+ port->rx_buff_tab[i] = buff; -+ } -+ -+ return 0; -+} -+ -+static void destroy_hdlc_queues(struct port *port) -+{ -+ int i; -+ -+ if (port->desc_tab) { -+ for (i = 0; i < RX_DESCS; i++) { -+ struct desc *desc = rx_desc_ptr(port, i); -+ buffer_t *buff = port->rx_buff_tab[i]; -+ if (buff) { -+ dma_unmap_single(&port->netdev->dev, -+ desc->data, RX_SIZE, -+ DMA_FROM_DEVICE); -+ free_buffer(buff); -+ } -+ } -+ for (i = 0; i < TX_DESCS; i++) { -+ struct desc *desc = tx_desc_ptr(port, i); -+ buffer_t *buff = port->tx_buff_tab[i]; -+ if (buff) { -+ dma_unmap_tx(port, desc); -+ free_buffer(buff); -+ } -+ } -+ dma_pool_free(dma_pool, port->desc_tab, port->desc_tab_phys); -+ port->desc_tab = NULL; -+ } -+ -+ if (!ports_open && dma_pool) { -+ dma_pool_destroy(dma_pool); -+ dma_pool = NULL; -+ } -+} -+ -+static int hss_hdlc_open(struct net_device *dev) -+{ -+ struct port *port = dev_to_port(dev); -+ unsigned long flags; -+ int i, err = 0; -+ -+ if ((err = hdlc_open(dev))) -+ return err; -+ -+ if ((err = request_hdlc_queues(port))) -+ goto err_hdlc_close; -+ -+ if ((err = init_hdlc_queues(port))) -+ goto err_destroy_queues; -+ -+ spin_lock_irqsave(&npe_lock, flags); -+ -+ if (port->mode == MODE_G704 && port->channels[0] == CHANNEL_HDLC) { -+ err = -EBUSY; /* channel #0 is used for G.704 framing */ -+ goto err_unlock; -+ } -+ if (port->mode != MODE_HDLC) -+ for (i = port->frame_size / 8; i < MAX_CHANNELS; i++) -+ if (port->channels[i] == CHANNEL_HDLC) { -+ err = -ECHRNG; /* frame too short */ -+ goto err_unlock; -+ } -+ -+ if ((err = hss_config_load_firmware(port))) -+ goto err_unlock; -+ -+ if (!port->chan_open_count && port->plat->open) -+ if ((err = port->plat->open(port->id, dev, -+ hss_hdlc_set_carrier))) -+ goto err_unlock; -+ -+ if (port->mode == MODE_G704 && !port->chan_open_count) -+ if ((err = hss_prepare_chan(port))) -+ goto err_plat_close; -+ -+ spin_unlock_irqrestore(&npe_lock, flags); -+ -+ /* Populate queues with buffers, no failure after this point */ -+ for (i = 0; i < TX_DESCS; i++) -+ queue_put_desc(port->plat->txreadyq, -+ tx_desc_phys(port, i), tx_desc_ptr(port, i)); -+ -+ for (i = 0; i < RX_DESCS; i++) -+ queue_put_desc(queue_ids[port->id].rxfree, -+ rx_desc_phys(port, i), rx_desc_ptr(port, i)); -+ -+ napi_enable(&port->napi); -+ netif_start_queue(dev); -+ -+ qmgr_set_irq(queue_ids[port->id].rx, QUEUE_IRQ_SRC_NOT_EMPTY, -+ hss_hdlc_rx_irq, dev); -+ -+ qmgr_set_irq(queue_ids[port->id].txdone, QUEUE_IRQ_SRC_NOT_EMPTY, -+ hss_hdlc_txdone_irq, dev); -+ qmgr_enable_irq(queue_ids[port->id].txdone); -+ -+ ports_open++; -+ port->hdlc_open = 1; -+ -+ hss_config_set_hdlc_cfg(port); -+ hss_config_set_lut(port); -+ hss_config_load(port); -+ -+ if (port->mode == MODE_G704 && !port->chan_open_count) -+ hss_config_start_chan(port); -+ -+ hss_config_start_hdlc(port); -+ -+ /* we may already have RX data, enables IRQ */ -+ netif_rx_schedule(dev, &port->napi); -+ return 0; -+ -+err_plat_close: -+ if (!port->chan_open_count && port->plat->close) -+ port->plat->close(port->id, dev); -+err_unlock: -+ spin_unlock_irqrestore(&npe_lock, flags); -+err_destroy_queues: -+ destroy_hdlc_queues(port); -+ release_hdlc_queues(port); -+err_hdlc_close: -+ hdlc_close(dev); -+ return err; -+} -+ -+static int hss_hdlc_close(struct net_device *dev) -+{ -+ struct port *port = dev_to_port(dev); -+ unsigned long flags; -+ int i, buffs = RX_DESCS; /* allocated RX buffers */ -+ -+ spin_lock_irqsave(&npe_lock, flags); -+ ports_open--; -+ port->hdlc_open = 0; -+ qmgr_disable_irq(queue_ids[port->id].rx); -+ netif_stop_queue(dev); -+ napi_disable(&port->napi); -+ -+ hss_config_stop_hdlc(port); -+ -+ if (port->mode == MODE_G704 && !port->chan_open_count) -+ hss_chan_stop(port); -+ -+ while (queue_get_desc(queue_ids[port->id].rxfree, port, 0) >= 0) -+ buffs--; -+ while (queue_get_desc(queue_ids[port->id].rx, port, 0) >= 0) -+ buffs--; -+ -+ if (buffs) -+ printk(KERN_CRIT "%s: unable to drain RX queue, %i buffer(s)" -+ " left in NPE\n", dev->name, buffs); -+ -+ buffs = TX_DESCS; -+ while (queue_get_desc(queue_ids[port->id].tx, port, 1) >= 0) -+ buffs--; /* cancel TX */ -+ -+ i = 0; -+ do { -+ while (queue_get_desc(port->plat->txreadyq, port, 1) >= 0) -+ buffs--; -+ if (!buffs) -+ break; -+ } while (++i < MAX_CLOSE_WAIT); -+ -+ if (buffs) -+ printk(KERN_CRIT "%s: unable to drain TX queue, %i buffer(s) " -+ "left in NPE\n", dev->name, buffs); -+#if DEBUG_CLOSE -+ if (!buffs) -+ printk(KERN_DEBUG "Draining TX queues took %i cycles\n", i); -+#endif -+ qmgr_disable_irq(queue_ids[port->id].txdone); -+ -+ if (!port->chan_open_count && port->plat->close) -+ port->plat->close(port->id, dev); -+ spin_unlock_irqrestore(&npe_lock, flags); -+ -+ destroy_hdlc_queues(port); -+ release_hdlc_queues(port); -+ hdlc_close(dev); -+ return 0; -+} -+ -+ -+static int hss_hdlc_attach(struct net_device *dev, unsigned short encoding, -+ unsigned short parity) -+{ -+ struct port *port = dev_to_port(dev); -+ -+ if (encoding != ENCODING_NRZ) -+ return -EINVAL; -+ -+ switch(parity) { -+ case PARITY_CRC16_PR1_CCITT: -+ port->hdlc_cfg = 0; -+ return 0; -+ -+ case PARITY_CRC32_PR1_CCITT: -+ port->hdlc_cfg = PKT_HDLC_CRC_32; -+ return 0; -+ -+ default: -+ return -EINVAL; -+ } -+} -+ -+ -+static int hss_hdlc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) -+{ -+ const size_t size = sizeof(sync_serial_settings); -+ sync_serial_settings new_line; -+ sync_serial_settings __user *line = ifr->ifr_settings.ifs_ifsu.sync; -+ struct port *port = dev_to_port(dev); -+ unsigned long flags; -+ int i, clk; -+ -+ if (cmd != SIOCWANDEV) -+ return hdlc_ioctl(dev, ifr, cmd); -+ -+ switch(ifr->ifr_settings.type) { -+ case IF_GET_IFACE: -+ ifr->ifr_settings.type = IF_IFACE_V35; -+ if (ifr->ifr_settings.size < size) { -+ ifr->ifr_settings.size = size; /* data size wanted */ -+ return -ENOBUFS; -+ } -+ memset(&new_line, 0, sizeof(new_line)); -+ new_line.clock_type = port->clock_type; -+ new_line.clock_rate = port->clock_rate; -+ new_line.loopback = port->loopback; -+ if (copy_to_user(line, &new_line, size)) -+ return -EFAULT; -+ -+ if (!port->chan_buf) -+ return 0; -+ -+ dma_sync_single(&dev->dev, port->chan_rx_buf_phys, -+ chan_rx_buf_len(port), DMA_FROM_DEVICE); -+ printk(KERN_DEBUG "RX:\n"); -+ for (i = 0; i < chan_rx_buf_len(port); i++) { -+ if (i % 32 == 0) -+ printk(KERN_DEBUG "%03X ", i); -+ printk("%02X%c", chan_rx_buf(port)[i], -+ (i + 1) % 32 ? ' ' : '\n'); -+ } -+ -+#if 0 -+ printk(KERN_DEBUG "TX:\n"); -+ for (i = 0; i < /*CHAN_TX_FRAMES * 2*/ chan_tx_buf_len(port) -+ + chan_tx_lists_len(port); i++) { -+ if (i % 32 == 0) -+ printk(KERN_DEBUG "%03X ", i); -+ printk("%02X%c", chan_tx_buf(port)[i], -+ (i + 1) % 32 ? ' ' : '\n'); -+ } -+#endif -+ port->msg_count = 10; -+ return 0; -+ -+ case IF_IFACE_SYNC_SERIAL: -+ case IF_IFACE_V35: -+ if(!capable(CAP_NET_ADMIN)) -+ return -EPERM; -+ if (copy_from_user(&new_line, line, size)) -+ return -EFAULT; -+ -+ clk = new_line.clock_type; -+ if (port->plat->set_clock) -+ clk = port->plat->set_clock(port->id, clk); -+ -+ if (clk != CLOCK_EXT && clk != CLOCK_INT) -+ return -EINVAL; /* No such clock setting */ -+ -+ if (new_line.loopback != 0 && new_line.loopback != 1) -+ return -EINVAL; -+ -+ port->clock_type = clk; /* Update settings */ -+ /* FIXME port->clock_rate = new_line.clock_rate */; -+ port->loopback = new_line.loopback; -+ -+ spin_lock_irqsave(&npe_lock, flags); -+ -+ if (port->chan_open_count || port->hdlc_open) { -+ hss_config_set_line(port); -+ hss_config_load(port); -+ } -+ if (port->loopback || port->carrier) -+ netif_carrier_on(port->netdev); -+ else -+ netif_carrier_off(port->netdev); -+ spin_unlock_irqrestore(&npe_lock, flags); -+ -+ return 0; -+ -+ default: -+ return hdlc_ioctl(dev, ifr, cmd); -+ } -+} -+ -+/***************************************************************************** -+ * channelized (G.704) operation -+ ****************************************************************************/ -+ -+static void g704_rx_framer(struct port *port, unsigned int offset) -+{ -+ u8 *data = chan_rx_buf(port) + sub_offset(offset, CHAN_RX_TRIGGER, -+ CHAN_RX_FRAMES); -+ unsigned int bit, frame, bad_even = 0, bad_odd = 0, cnt; -+ unsigned int is_first = port->just_set_offset; -+ u8 zeros_even, zeros_odd, ones_even, ones_odd; -+ enum alignment aligned; -+ -+ port->just_set_offset = 0; -+ dma_sync_single(port->dev, port->chan_rx_buf_phys, CHAN_RX_FRAMES, -+ DMA_FROM_DEVICE); -+ -+ /* check if aligned first */ -+ for (frame = 0; frame < CHAN_RX_TRIGGER && -+ (bad_even <= MAX_CHAN_RX_BAD_SYNC || -+ bad_odd <= MAX_CHAN_RX_BAD_SYNC); frame += 2) { -+ u8 ve = data[frame]; -+ u8 vo = data[frame + 1]; -+ -+ if ((ve & 0x7F) != 0x1B || !(vo & 0x40)) -+ bad_even++; -+ -+ if ((vo & 0x7F) != 0x1B || !(ve & 0x40)) -+ bad_odd++; -+ } -+ -+ if (bad_even <= MAX_CHAN_RX_BAD_SYNC) -+ aligned = EVEN_FIRST; -+ else if (bad_odd <= MAX_CHAN_RX_BAD_SYNC) -+ aligned = ODD_FIRST; -+ else -+ aligned = NOT_ALIGNED; -+ -+ if (aligned != NOT_ALIGNED) { -+ if (aligned == port->aligned) -+ return; /* no change */ -+ if (printk_ratelimit()) -+ printk(KERN_INFO "HSS-%i: synchronized at %u (%s frame" -+ " first)\n", port->id, port->frame_sync_offset, -+ aligned == EVEN_FIRST ? "even" : "odd"); -+ port->aligned = aligned; -+ -+ atomic_inc(&port->chan_tx_irq_number); -+ wake_up_interruptible(&port->chan_tx_waitq); -+ atomic_inc(&port->chan_rx_irq_number); -+ wake_up_interruptible(&port->chan_rx_waitq); -+ return; -+ } -+ -+ /* not aligned */ -+ if (port->aligned != NOT_ALIGNED && printk_ratelimit()) { -+ printk(KERN_INFO "HSS-%i: lost alignment\n", port->id); -+ port->aligned = NOT_ALIGNED; -+#if DEBUG_FRAMER -+ for (cnt = 0; cnt < CHAN_RX_FRAMES; cnt++) -+ printk("%c%02X%s", cnt == offset ? '>' : ' ', -+ chan_rx_buf(port)[cnt], -+ (cnt + 1) % 32 ? "" : "\n"); -+#endif -+ -+ for (cnt = 0; cnt < MAX_CHAN_DEVICES; cnt++) -+ if (port->chan_devices[cnt]) { -+ set_bit(TX_ERROR_BIT, &port->chan_devices[cnt] -+ ->errors_bitmap); -+ set_bit(RX_ERROR_BIT, &port->chan_devices[cnt] -+ ->errors_bitmap); -+ } -+ atomic_inc(&port->chan_tx_irq_number); -+ wake_up_interruptible(&port->chan_tx_waitq); -+ atomic_inc(&port->chan_rx_irq_number); -+ wake_up_interruptible(&port->chan_rx_waitq); -+ } -+ -+ if (is_first) -+ return; -+ -+ zeros_even = zeros_odd = 0; -+ ones_even = ones_odd = 0xFF; -+ for (frame = 0; frame < CHAN_RX_TRIGGER; frame += 2) { -+ zeros_even |= data[frame]; -+ zeros_odd |= data[frame + 1]; -+ ones_even &= data[frame]; -+ ones_odd &= data[frame + 1]; -+ } -+ -+ for (bit = 0; bit < 7; bit++) { -+ if ((zeros_even & ~0x9B) == 0 && (ones_even & 0x1B) == 0x1B && -+ (ones_odd & 0x40) == 0x40) { -+ aligned = EVEN_FIRST; /* maybe */ -+ break; -+ } -+ if ((zeros_odd & ~0x9B) == 0 && (ones_odd & 0x1B) == 0x1B && -+ (ones_even & 0x40) == 0x40) { -+ aligned = ODD_FIRST; /* maybe */ -+ break; -+ } -+ zeros_even <<= 1; -+ ones_even = ones_even << 1 | 1; -+ zeros_odd <<= 1; -+ ones_odd = ones_odd << 1 | 1; -+ } -+ -+ port->frame_sync_offset += port->frame_size - bit; -+ port->frame_sync_offset %= port->frame_size; -+ port->just_set_offset = 1; -+ -+#if DEBUG_FRAMER -+ if (bit == 7) -+ printk(KERN_DEBUG "HSS-%i: trying frame sync at %u\n", -+ port->id, port->frame_sync_offset); -+ else -+ printk(KERN_DEBUG "HSS-%i: found possible frame sync pattern at" -+ " %u (%s frame first)\n", port->id, -+ port->frame_sync_offset, -+ aligned == EVEN_FIRST ? "even" : "odd"); -+#endif -+ -+ hss_config_set_rx_frame(port); -+ hss_config_load(port); -+} -+ -+static void chan_process_tx_irq(struct chan_device *chan_dev, int offset) -+{ -+ /* in bytes */ -+ unsigned int buff_len = CHAN_TX_FRAMES * chan_dev->chan_count; -+ unsigned int list_len = CHAN_TX_LIST_FRAMES * chan_dev->chan_count; -+ int eaten, last_offset = chan_dev->port->chan_last_tx * list_len; -+ -+ offset *= list_len; -+ eaten = sub_offset(offset, last_offset, buff_len); -+ -+ if (chan_dev->tx_count > eaten + 2 * list_len) { -+ /* two pages must be reserved for the transmitter */ -+ chan_dev->tx_first += eaten; -+ chan_dev->tx_first %= buff_len; -+ chan_dev->tx_count -= eaten; -+ } else { -+ /* FIXME check -+ 0 -+ 1 tx_first (may still be transmited) -+ 2 tx_offset (currently reported by the NPE) -+ 3 tx_first + 2 * list_len (free to write here) -+ 4 -+ 5 -+ */ -+ -+ /* printk(KERN_DEBUG "TX buffer underflow\n"); */ -+ chan_dev->tx_first = sub_offset(offset, list_len, buff_len); -+ chan_dev->tx_count = 2 * list_len; /* reserve */ -+ set_bit(TX_ERROR_BIT, &chan_dev->errors_bitmap); -+ } -+} -+ -+static void chan_process_rx_irq(struct chan_device *chan_dev, int offset) -+{ -+ /* in bytes */ -+ unsigned int buff_len = CHAN_RX_FRAMES * chan_dev->chan_count; -+ unsigned int trig_len = CHAN_RX_TRIGGER * chan_dev->chan_count; -+ int last_offset = chan_dev->port->chan_last_rx * chan_dev->chan_count; -+ -+ offset *= chan_dev->chan_count; -+ chan_dev->rx_count += sub_offset(offset, last_offset + trig_len, -+ buff_len) + trig_len; -+ if (chan_dev->rx_count > buff_len - 2 * trig_len) { -+ /* two pages - offset[0] and offset[1] are lost - FIXME check */ -+ /* printk(KERN_DEBUG "RX buffer overflow\n"); */ -+ chan_dev->rx_first = (offset + 2 * trig_len) % buff_len; -+ chan_dev->rx_count = buff_len - 2 * trig_len; -+ set_bit(RX_ERROR_BIT, &chan_dev->errors_bitmap); -+ } -+} -+ -+static void hss_chan_irq(void *pdev) -+{ -+ struct port *port = pdev; -+ u32 v; -+ -+#if DEBUG_RX -+ printk(KERN_DEBUG DRV_NAME ": hss_chan_irq\n"); -+#endif -+ spin_lock(&npe_lock); -+ while ((v = qmgr_get_entry(queue_ids[port->id].chan))) { -+ unsigned int first, errors, tx_list, rx_frame; -+ int i, bad; -+ -+ first = v >> 24; -+ errors = (v >> 16) & 0xFF; -+ tx_list = (v >> 8) & 0xFF; -+ rx_frame = v & 0xFF; -+ -+ if (port->msg_count) { -+ printk(KERN_DEBUG "chan_irq hss %i jiffies %lu first" -+ " 0x%02X errors 0x%02X tx_list 0x%02X rx_frame" -+ " 0x%02X\n", port->id, jiffies, first, errors, -+ tx_list, rx_frame); -+ port->msg_count--; -+ } -+ -+ BUG_ON(rx_frame % CHAN_RX_TRIGGER); -+ BUG_ON(rx_frame >= CHAN_RX_FRAMES); -+ BUG_ON(tx_list >= CHAN_TX_LISTS); -+ -+ bad = port->mode == MODE_G704 && port->aligned == NOT_ALIGNED; -+ if (!bad && tx_list != port->chan_last_tx) { -+ if (tx_list != (port->chan_last_tx + 1) % CHAN_TX_LISTS) -+ printk(KERN_DEBUG "Skipped an IRQ? Tx last %i" -+ " current %i\n", port->chan_last_tx, -+ tx_list); -+ for (i = 0; i < MAX_CHAN_DEVICES; i++) { -+ if (!port->chan_devices[i] || -+ !port->chan_devices[i]->open_count) -+ continue; -+ chan_process_tx_irq(port->chan_devices[i], -+ tx_list); -+ } -+ atomic_inc(&port->chan_tx_irq_number); -+#if 0 -+ printk(KERN_DEBUG "wakeing up TX jiff %lu\n", -+ jiffies, errors); -+#endif -+ wake_up_interruptible(&port->chan_tx_waitq); -+ } -+ -+ if (rx_frame != (port->chan_last_rx + CHAN_RX_TRIGGER) % -+ CHAN_RX_FRAMES) -+ printk(KERN_DEBUG "Skipped an IRQ? Rx last %i" -+ " current %i\n", port->chan_last_rx, rx_frame); -+ -+ if (port->mode == MODE_G704) -+ g704_rx_framer(port, rx_frame); -+ -+ if (!bad && -+ (port->mode != MODE_G704 || port->aligned != NOT_ALIGNED)) { -+ for (i = 0; i < MAX_CHAN_DEVICES; i++) { -+ if (!port->chan_devices[i] || -+ !port->chan_devices[i]->open_count) -+ continue; -+ chan_process_rx_irq(port->chan_devices[i], -+ rx_frame); -+ } -+ atomic_inc(&port->chan_rx_irq_number); -+ wake_up_interruptible(&port->chan_rx_waitq); -+ } -+ port->chan_last_tx = tx_list; -+ port->chan_last_rx = rx_frame; -+ } -+ spin_unlock(&npe_lock); -+} -+ -+ -+static int hss_prepare_chan(struct port *port) -+{ -+ int err; -+ -+ if ((err = hss_config_load_firmware(port))) -+ return err; -+ -+ if ((err = qmgr_request_queue(queue_ids[port->id].chan, -+ CHAN_QUEUE_LEN, 0, 0))) -+ return err; -+ -+ if (!(port->chan_buf = kmalloc(chan_tx_buf_len(port) + -+ chan_tx_lists_len(port) + -+ chan_rx_buf_len(port), GFP_KERNEL))) { -+ goto release_queue; -+ err = -ENOBUFS; -+ } -+ -+ port->chan_tx_buf_phys = dma_map_single(port->dev, chan_tx_buf(port), -+ chan_tx_buf_len(port) + -+ chan_tx_lists_len(port), -+ DMA_TO_DEVICE); -+ if (dma_mapping_error(port->chan_tx_buf_phys)) { -+ err = -EIO; -+ goto free; -+ } -+ -+ port->chan_rx_buf_phys = dma_map_single(port->dev, chan_rx_buf(port), -+ chan_rx_buf_len(port), -+ DMA_FROM_DEVICE); -+ if (dma_mapping_error(port->chan_rx_buf_phys)) { -+ err = -EIO; -+ goto unmap_tx; -+ } -+ -+ qmgr_set_irq(queue_ids[port->id].chan, QUEUE_IRQ_SRC_NOT_EMPTY, -+ hss_chan_irq, port); -+ qmgr_enable_irq(queue_ids[port->id].chan); -+ hss_chan_irq(port); -+ return 0; -+ -+unmap_tx: -+ dma_unmap_single(port->dev, port->chan_tx_buf_phys, -+ chan_tx_buf_len(port) + chan_tx_lists_len(port), -+ DMA_TO_DEVICE); -+free: -+ kfree(port->chan_buf); -+ port->chan_buf = NULL; -+release_queue: -+ qmgr_release_queue(queue_ids[port->id].chan); -+ return err; -+} -+ -+void hss_chan_stop(struct port *port) -+{ -+ if (!port->chan_open_count && !port->hdlc_open) -+ qmgr_disable_irq(queue_ids[port->id].chan); -+ -+ hss_config_stop_chan(port); -+ hss_config_set_lut(port); -+ hss_config_load(port); -+ -+ if (!port->chan_open_count && !port->hdlc_open) { -+ dma_unmap_single(port->dev, port->chan_tx_buf_phys, -+ chan_tx_buf_len(port) + -+ chan_tx_lists_len(port), DMA_TO_DEVICE); -+ dma_unmap_single(port->dev, port->chan_rx_buf_phys, -+ chan_rx_buf_len(port), DMA_FROM_DEVICE); -+ kfree(port->chan_buf); -+ port->chan_buf = NULL; -+ qmgr_release_queue(queue_ids[port->id].chan); -+ } -+} -+ -+static int hss_chan_open(struct inode *inode, struct file *file) -+{ -+ struct chan_device *chan_dev = inode_to_chan_dev(inode); -+ struct port *port = chan_dev->port; -+ unsigned long flags; -+ int i, err = 0; -+ -+ spin_lock_irqsave(&npe_lock, flags); -+ -+ if (chan_dev->open_count) { -+ if (chan_dev->excl_open || (file->f_flags & O_EXCL)) -+ err = -EBUSY; -+ else -+ chan_dev->open_count++; -+ goto out; -+ } -+ -+ if (port->mode == MODE_HDLC) { -+ err = -ENOSYS; -+ goto out; -+ } -+ -+ if (port->mode == MODE_G704 && port->channels[0] == chan_dev->id) { -+ err = -EBUSY; /* channel #0 is used for G.704 signaling */ -+ goto out; -+ } -+ for (i = MAX_CHANNELS; i > port->frame_size / 8; i--) -+ if (port->channels[i - 1] == chan_dev->id) { -+ err = -ECHRNG; /* frame too short */ -+ goto out; -+ } -+ -+ chan_dev->rx_first = chan_dev->tx_first = 0; -+ chan_dev->rx_count = chan_dev->tx_count = 0; -+ clear_bit(TX_ERROR_BIT, &chan_dev->errors_bitmap); -+ clear_bit(RX_ERROR_BIT, &chan_dev->errors_bitmap); -+ -+ if (!port->chan_open_count && !port->hdlc_open) { -+ if (port->plat->open) -+ if ((err = port->plat->open(port->id, port->netdev, -+ hss_hdlc_set_carrier))) -+ goto out; -+ if ((err = hss_prepare_chan(port))) { -+ if (port->plat->close) -+ port->plat->close(port->id, port->netdev); -+ goto out; -+ } -+ } -+ -+ hss_config_stop_chan(port); -+ chan_dev->open_count++; -+ port->chan_open_count++; -+ chan_dev->excl_open = !!file->f_flags & O_EXCL; -+ -+ hss_config_set_lut(port); -+ hss_config_load(port); -+ hss_config_start_chan(port); -+out: -+ spin_unlock_irqrestore(&npe_lock, flags); -+ return err; -+} -+ -+static int hss_chan_release(struct inode *inode, struct file *file) -+{ -+ struct chan_device *chan_dev = inode_to_chan_dev(inode); -+ struct port *port = chan_dev->port; -+ unsigned long flags; -+ -+ spin_lock_irqsave(&npe_lock, flags); -+ -+ if (!--chan_dev->open_count) { -+ if (!--port->chan_open_count && !port->hdlc_open) { -+ hss_chan_stop(port); -+ if (port->plat->close) -+ port->plat->close(port->id, port->netdev); -+ } else { -+ hss_config_stop_chan(port); -+ hss_config_set_lut(port); -+ hss_config_set_line(port); // -+ hss_config_start_chan(port); -+ } -+ } -+ -+ spin_unlock_irqrestore(&npe_lock, flags); -+ return 0; -+} -+ -+static ssize_t hss_chan_read(struct file *file, char __user *buf, size_t count, -+ loff_t *f_pos) -+{ -+ struct chan_device *chan_dev = inode_to_chan_dev -+ (file->f_path.dentry->d_inode); -+ struct port *port = chan_dev->port; -+ unsigned long flags; -+ u8 *rx_buf; -+ int res = 0, loops = 0; -+ -+ spin_lock_irqsave(&npe_lock, flags); -+ -+ while (1) { -+ int prev_irq = atomic_read(&port->chan_rx_irq_number); -+#if 0 -+ if (test_and_clear_bit(RX_ERROR_BIT, &chan_dev->errors_bitmap) -+ || (port->mode == G704 && port->aligned == NOT_ALIGNED)) { -+ res = -EIO; -+ goto out; -+ } -+#endif -+ if (count == 0) -+ goto out; /* no need to wait */ -+ -+ if (chan_dev->rx_count) -+ break; -+ -+ spin_unlock_irqrestore(&npe_lock, flags); -+ loops++; -+ if ((res = wait_event_interruptible -+ (port->chan_rx_waitq, -+ atomic_read(&port->chan_rx_irq_number) != prev_irq))) -+ goto out; -+ spin_lock_irqsave(&npe_lock, flags); -+ continue; -+ } -+ -+ dma_sync_single(port->dev, port->chan_rx_buf_phys, -+ chan_rx_buf_len(port), DMA_FROM_DEVICE); -+ -+#if 0 -+ if (loops > 1) -+ printk(KERN_DEBUG "ENTRY rx_first %u rx_count %u count %i" -+ " last_rx %u loops %i\n", chan_dev->rx_first, -+ chan_dev->rx_count, count, port->chan_last_rx, loops); -+#endif -+ rx_buf = chan_rx_buf(port); -+ while (chan_dev->rx_count > 0 && res < count) { -+ unsigned int chan = chan_dev->rx_first % chan_dev->chan_count; -+ unsigned int frame = chan_dev->rx_first / chan_dev->chan_count; -+ -+ chan = chan_dev->log_channels[chan]; -+ if (put_user(rx_buf[chan * CHAN_RX_FRAMES + frame], buf++)) { -+ res = -EFAULT; -+ goto out; -+ } -+ chan_dev->rx_first++; -+ chan_dev->rx_first %= CHAN_RX_FRAMES * chan_dev->chan_count; -+ chan_dev->rx_count--; -+ res++; -+ } -+out: -+#if 0 -+ printk(KERN_DEBUG "EXIT rx_first %u rx_count %u res %i\n", -+ chan_dev->rx_first, chan_dev->rx_count, res); -+#endif -+ spin_unlock_irqrestore(&npe_lock, flags); -+ return res; -+} -+ -+static ssize_t hss_chan_write(struct file *file, const char __user *buf, -+ size_t count, loff_t *f_pos) -+{ -+ struct chan_device *chan_dev = inode_to_chan_dev -+ (file->f_path.dentry->d_inode); -+ struct port *port = chan_dev->port; -+ unsigned long flags; -+ u8 *tx_buf; -+ int res = 0, loops = 0; -+ -+ spin_lock_irqsave(&npe_lock, flags); -+ while (1) { -+ int prev_irq = atomic_read(&port->chan_tx_irq_number); -+#if 0 -+ if (test_and_clear_bit(TX_ERROR_BIT, &chan_dev->errors_bitmap) -+ || (port->mode == G704 && port->aligned == NOT_ALIGNED)) { -+ res = -EIO; -+ goto out; -+ } -+#endif -+ if (count == 0) -+ goto out; /* no need to wait */ -+ -+ if (chan_dev->tx_count < CHAN_TX_FRAMES * chan_dev->chan_count) -+ break; -+ -+ spin_unlock_irqrestore(&npe_lock, flags); -+ loops++; -+ if ((res = wait_event_interruptible -+ (port->chan_tx_waitq, -+ atomic_read (&port->chan_tx_irq_number) != prev_irq))) -+ goto out; -+ spin_lock_irqsave(&npe_lock, flags); -+ continue; -+ } -+ -+#if 0 -+ if (loops > 1) -+ printk(KERN_DEBUG "ENTRY TX_first %u tx_count %u count %i" -+ " last_tx %u loops %i\n", chan_dev->tx_first, -+ chan_dev->tx_count, count, port->chan_last_tx, loops); -+#endif -+ tx_buf = chan_tx_buf(port); -+ while (chan_dev->tx_count < CHAN_TX_FRAMES * chan_dev->chan_count && -+ res < count) { -+ unsigned int tail, chan, frame; -+ -+ tail = (chan_dev->tx_first + chan_dev->tx_count) % -+ (CHAN_TX_FRAMES * chan_dev->chan_count); -+ chan = tail % chan_dev->chan_count; -+ frame = tail / chan_dev->chan_count; -+ chan = chan_dev->log_channels[chan]; -+ -+ if (get_user(tx_buf[chan * CHAN_TX_FRAMES + frame], buf++)) { -+ printk(KERN_DEBUG "BUG? TX %u %u %u\n", -+ tail, chan, frame); -+ res = -EFAULT; -+ goto out_sync; -+ } -+ chan_dev->tx_count++; -+ res++; -+ } -+out_sync: -+ dma_sync_single(port->dev, port->chan_tx_buf_phys, -+ chan_tx_buf_len(port), DMA_TO_DEVICE); -+out: -+#if 0 -+ printk(KERN_DEBUG "EXIT TX_first %u tx_count %u res %i\n", -+ chan_dev->tx_first, chan_dev->tx_count, res); -+#endif -+ spin_unlock_irqrestore(&npe_lock, flags); -+ return res; -+} -+ -+ -+static unsigned int hss_chan_poll(struct file *file, poll_table *wait) -+{ -+ struct chan_device *chan_dev = inode_to_chan_dev -+ (file->f_path.dentry->d_inode); -+ struct port *port = chan_dev->port; -+ unsigned long flags; -+ unsigned int mask = 0; -+ -+ spin_lock_irqsave(&npe_lock, flags); -+ poll_wait(file, &port->chan_tx_waitq, wait); -+ poll_wait(file, &port->chan_rx_waitq, wait); -+ -+ if (chan_dev->tx_count < CHAN_TX_FRAMES * chan_dev->chan_count) -+ mask |= POLLOUT | POLLWRNORM; -+ if (chan_dev->rx_count) -+ mask |= POLLIN | POLLRDNORM; -+ spin_unlock_irqrestore(&npe_lock, flags); -+ return mask; -+} -+ -+/***************************************************************************** -+ * channelized device sysfs attributes -+ ****************************************************************************/ -+ -+static ssize_t chan_show_chan(struct device *dev, struct device_attribute *attr, -+ char *buf) -+{ -+ struct chan_device *chan_dev = dev_get_drvdata(dev); -+ -+ return print_channels(chan_dev->port, buf, chan_dev->id); -+} -+ -+static ssize_t chan_set_chan(struct device *dev, struct device_attribute *attr, -+ const char *buf, size_t len) -+{ -+ struct chan_device *chan_dev = dev_get_drvdata(dev); -+ struct port *port = chan_dev->port; -+ unsigned long flags; -+ unsigned int ch; -+ size_t orig_len = len; -+ int err; -+ -+ if (len && buf[len - 1] == '\n') -+ len--; -+ -+ if (len != 7 || memcmp(buf, "destroy", 7)) -+ return -EINVAL; -+ -+ spin_lock_irqsave(&npe_lock, flags); -+ cdev_del(&chan_dev->cdev); -+ -+ for (ch = 0; ch < MAX_CHANNELS; ch++) -+ if (port->channels[ch] == chan_dev->id) -+ port->channels[ch] = CHANNEL_UNUSED; -+ port->chan_devices[chan_dev->id] = NULL; -+ kfree(chan_dev); -+ spin_unlock_irqrestore(&npe_lock, flags); -+ -+ if ((err = device_schedule_callback(dev, device_unregister))) -+ return err; -+ return orig_len; -+} -+ -+static struct device_attribute chan_attr = -+ __ATTR(channels, 0644, chan_show_chan, chan_set_chan); -+ -+/***************************************************************************** -+ * main sysfs attributes -+ ****************************************************************************/ -+ -+static const struct file_operations chan_fops = { -+ .owner = THIS_MODULE, -+ .llseek = no_llseek, -+ .read = hss_chan_read, -+ .write = hss_chan_write, -+ .poll = hss_chan_poll, -+ .open = hss_chan_open, -+ .release = hss_chan_release, -+}; -+ -+static ssize_t create_chan(struct device *dev, struct device_attribute *attr, -+ const char *buf, size_t len) -+{ -+ struct port *port = dev_get_drvdata(dev); -+ struct chan_device *chan_dev; -+ u8 channels[MAX_CHANNELS]; -+ size_t orig_len = len; -+ unsigned long flags; -+ unsigned int ch, id; -+ int minor, err; -+ -+ if ((err = parse_channels(&buf, &len, channels)) < 1) -+ return err; -+ -+ if (!(chan_dev = kzalloc(sizeof(struct chan_device), GFP_KERNEL))) -+ return -ENOBUFS; -+ -+ spin_lock_irqsave(&npe_lock, flags); -+ -+ if (port->mode != MODE_RAW && port->mode != MODE_G704) { -+ err = -EINVAL; -+ goto free; -+ } -+ -+ for (ch = 0; ch < MAX_CHANNELS; ch++) -+ if (channels[ch] && port->channels[ch] != CHANNEL_UNUSED) { -+ printk(KERN_DEBUG "Channel #%i already in use\n", ch); -+ err = -EBUSY; -+ goto free; -+ } -+ -+ for (id = 0; id < MAX_CHAN_DEVICES; id++) -+ if (port->chan_devices[id] == NULL) -+ break; -+ -+ if (id == MAX_CHAN_DEVICES) { -+ err = -EBUSY; -+ goto free; -+ } -+ -+ for (ch = 0; ch < MAX_CHANNELS; ch++) -+ if (channels[ch]) -+ break; -+ -+ minor = port->id * MAX_CHAN_DEVICES + ch; -+ chan_dev->id = id; -+ chan_dev->port = port; -+ chan_dev->dev = device_create(hss_class, dev, MKDEV(chan_major, minor), -+ "hss%uch%u", port->id, ch); -+ if (IS_ERR(chan_dev->dev)) { -+ err = PTR_ERR(chan_dev->dev); -+ goto free; -+ } -+ -+ cdev_init(&chan_dev->cdev, &chan_fops); -+ chan_dev->cdev.owner = THIS_MODULE; -+ if ((err = cdev_add(&chan_dev->cdev, MKDEV(chan_major, minor), 1))) -+ goto destroy_device; -+ -+ for (ch = 0; ch < MAX_CHANNELS; ch++) -+ if (channels[ch]) -+ port->channels[ch] = id; -+ port->chan_devices[id] = chan_dev; -+ dev_set_drvdata(chan_dev->dev, chan_dev); -+ BUG_ON(device_create_file(chan_dev->dev, &chan_attr)); -+ -+ spin_unlock_irqrestore(&npe_lock, flags); -+ return orig_len; -+ -+destroy_device: -+ device_unregister(chan_dev->dev); -+free: -+ kfree(chan_dev); -+ spin_unlock_irqrestore(&npe_lock, flags); -+ return err; -+} -+ -+static ssize_t show_hdlc_chan(struct device *dev, struct device_attribute *attr, -+ char *buf) -+{ -+ return print_channels(dev_get_drvdata(dev), buf, CHANNEL_HDLC); -+} -+ -+static ssize_t set_hdlc_chan(struct device *dev, struct device_attribute *attr, -+ const char *buf, size_t len) -+{ -+ struct port *port = dev_get_drvdata(dev); -+ u8 channels[MAX_CHANNELS]; -+ size_t orig_len = len; -+ unsigned long flags; -+ unsigned int ch; -+ int err; -+ -+ if ((err = parse_channels(&buf, &len, channels)) < 0) -+ return err; -+ -+ spin_lock_irqsave(&npe_lock, flags); -+ -+ if (port->mode != MODE_RAW && port->mode != MODE_G704) { -+ err = -EINVAL; -+ goto err; -+ } -+ -+ for (ch = 0; ch < MAX_CHANNELS; ch++) -+ if (channels[ch] && -+ port->channels[ch] != CHANNEL_UNUSED && -+ port->channels[ch] != CHANNEL_HDLC) { -+ printk(KERN_DEBUG "Channel #%i already in use\n", ch); -+ err = -EBUSY; -+ goto err; -+ } -+ -+ for (ch = 0; ch < MAX_CHANNELS; ch++) -+ if (channels[ch]) -+ port->channels[ch] = CHANNEL_HDLC; -+ else if (port->channels[ch] == CHANNEL_HDLC) -+ port->channels[ch] = CHANNEL_UNUSED; -+ -+ if (port->chan_open_count || port->hdlc_open) { -+ hss_config_set_lut(port); -+ hss_config_load(port); -+ } -+ -+ spin_unlock_irqrestore(&npe_lock, flags); -+ return orig_len; -+ -+err: -+ spin_unlock_irqrestore(&npe_lock, flags); -+ return err; -+} -+ -+static ssize_t show_clock_type(struct device *dev, -+ struct device_attribute *attr, char *buf) -+{ -+ struct port *port = dev_get_drvdata(dev); -+ -+ strcpy(buf, port->clock_type == CLOCK_INT ? "int\n" : "ext\n"); -+ return 5; -+} -+ -+static ssize_t set_clock_type(struct device *dev, struct device_attribute *attr, -+ const char *buf, size_t len) -+{ -+ struct port *port = dev_get_drvdata(dev); -+ size_t orig_len = len; -+ unsigned long flags; -+ unsigned int clk, err; -+ -+ if (len && buf[len - 1] == '\n') -+ len--; -+ -+ if (len != 3) -+ return -EINVAL; -+ if (!memcmp(buf, "ext", 3)) -+ clk = CLOCK_EXT; -+ else if (!memcmp(buf, "int", 3)) -+ clk = CLOCK_INT; -+ else -+ return -EINVAL; -+ -+ spin_lock_irqsave(&npe_lock, flags); -+ if (port->plat->set_clock) -+ clk = port->plat->set_clock(port->id, clk); -+ if (clk != CLOCK_EXT && clk != CLOCK_INT) { -+ err = -EINVAL; /* plat->set_clock shouldn't change the state */ -+ goto err; -+ } -+ port->clock_type = clk; -+ if (port->chan_open_count || port->hdlc_open) { -+ hss_config_set_line(port); -+ hss_config_load(port); -+ } -+ spin_unlock_irqrestore(&npe_lock, flags); -+ -+ return orig_len; -+err: -+ spin_unlock_irqrestore(&npe_lock, flags); -+ return err; -+} -+ -+static ssize_t show_clock_rate(struct device *dev, -+ struct device_attribute *attr, char *buf) -+{ -+ struct port *port = dev_get_drvdata(dev); -+ -+ sprintf(buf, "%u\n", port->clock_rate); -+ return strlen(buf) + 1; -+} -+ -+static ssize_t set_clock_rate(struct device *dev, struct device_attribute *attr, -+ const char *buf, size_t len) -+{ -+#if 0 -+ struct port *port = dev_get_drvdata(dev); -+ size_t orig_len = len; -+ unsigned long flags; -+ unsigned int rate; -+ -+ if (len && buf[len - 1] == '\n') -+ len--; -+ -+ if (get_number(&buf, &len, &rate, 1, 0xFFFFFFFFu)) -+ return -EINVAL; -+ if (len) -+ return -EINVAL; -+ -+ spin_lock_irqsave(&npe_lock, flags); -+ port->clock_rate = rate; -+ spin_unlock_irqrestore(&npe_lock, flags); -+ return orig_len; -+#endif -+ return -EINVAL; /* FIXME not yet supported */ -+} -+ -+static ssize_t show_frame_size(struct device *dev, -+ struct device_attribute *attr, char *buf) -+{ -+ struct port *port = dev_get_drvdata(dev); -+ -+ if (port->mode != MODE_RAW && port->mode != MODE_G704) -+ return -EINVAL; -+ -+ sprintf(buf, "%u\n", port->frame_size); -+ return strlen(buf) + 1; -+} -+ -+static ssize_t set_frame_size(struct device *dev, struct device_attribute *attr, -+ const char *buf, size_t len) -+{ -+ struct port *port = dev_get_drvdata(dev); -+ size_t ret = len; -+ unsigned long flags; -+ unsigned int size; -+ -+ if (len && buf[len - 1] == '\n') -+ len--; -+ -+ if (get_number(&buf, &len, &size, MIN_FRAME_SIZE, MAX_FRAME_SIZE)) -+ return -EINVAL; -+ if (len || size % 8 > 1) -+ return -EINVAL; -+ -+ spin_lock_irqsave(&npe_lock, flags); -+ if (port->mode != MODE_RAW && port->mode != MODE_G704) -+ ret = -EINVAL; -+ else if (!port->chan_open_count && !port->hdlc_open) -+ ret = -EBUSY; -+ else { -+ port->frame_size = size; -+ port->frame_sync_offset = 0; -+ } -+ spin_unlock_irqrestore(&npe_lock, flags); -+ return ret; -+} -+ -+static ssize_t show_frame_offset(struct device *dev, -+ struct device_attribute *attr, char *buf) -+{ -+ struct port *port = dev_get_drvdata(dev); -+ -+ sprintf(buf, "%u\n", port->frame_sync_offset); -+ return strlen(buf) + 1; -+} -+ -+static ssize_t set_frame_offset(struct device *dev, -+ struct device_attribute *attr, -+ const char *buf, size_t len) -+{ -+ struct port *port = dev_get_drvdata(dev); -+ size_t orig_len = len; -+ unsigned long flags; -+ unsigned int offset; -+ -+ if (len && buf[len - 1] == '\n') -+ len--; -+ -+ if (get_number(&buf, &len, &offset, 0, port->frame_size - 1)) -+ return -EINVAL; -+ if (len) -+ return -EINVAL; -+ -+ spin_lock_irqsave(&npe_lock, flags); -+ -+ port->frame_sync_offset = offset; -+ if (port->chan_open_count || port->hdlc_open) { -+ hss_config_set_rx_frame(port); -+ hss_config_load(port); -+ } -+ -+ spin_unlock_irqrestore(&npe_lock, flags); -+ return orig_len; -+} -+ -+static ssize_t show_loopback(struct device *dev, struct device_attribute *attr, -+ char *buf) -+{ -+ struct port *port = dev_get_drvdata(dev); -+ -+ sprintf(buf, "%u\n", port->loopback); -+ return strlen(buf) + 1; -+} -+ -+static ssize_t set_loopback(struct device *dev, struct device_attribute *attr, -+ const char *buf, size_t len) -+{ -+ struct port *port = dev_get_drvdata(dev); -+ size_t orig_len = len; -+ unsigned long flags; -+ unsigned int lb; -+ -+ if (len && buf[len - 1] == '\n') -+ len--; -+ -+ if (get_number(&buf, &len, &lb, 0, 1)) -+ return -EINVAL; -+ if (len) -+ return -EINVAL; -+ -+ spin_lock_irqsave(&npe_lock, flags); -+ -+ if (port->loopback != lb) { -+ port->loopback = lb; -+ if (port->chan_open_count || port->hdlc_open) { -+ hss_config_set_core(port); -+ hss_config_load(port); -+ } -+ if (port->loopback || port->carrier) -+ netif_carrier_on(port->netdev); -+ else -+ netif_carrier_off(port->netdev); -+ } -+ -+ spin_unlock_irqrestore(&npe_lock, flags); -+ return orig_len; -+} -+ -+static ssize_t show_mode(struct device *dev, struct device_attribute *attr, -+ char *buf) -+{ -+ struct port *port = dev_get_drvdata(dev); -+ -+ switch(port->mode) { -+ case MODE_RAW: -+ strcpy(buf, "raw\n"); -+ break; -+ case MODE_G704: -+ strcpy(buf, "g704\n"); -+ break; -+ default: -+ strcpy(buf, "hdlc\n"); -+ break; -+ } -+ return strlen(buf) + 1; -+} -+ -+static ssize_t set_mode(struct device *dev, struct device_attribute *attr, -+ const char *buf, size_t len) -+{ -+ struct port *port = dev_get_drvdata(dev); -+ size_t ret = len; -+ unsigned long flags; -+ -+ if (len && buf[len - 1] == '\n') -+ len--; -+ -+ spin_lock_irqsave(&npe_lock, flags); -+ -+ if (port->chan_open_count || port->hdlc_open) { -+ ret = -EBUSY; -+ } else if (len == 4 && !memcmp(buf, "hdlc", 4)) -+ port->mode = MODE_HDLC; -+ else if (len == 3 && !memcmp(buf, "raw", 3)) -+ port->mode = MODE_RAW; -+ else if (len == 4 && !memcmp(buf, "g704", 4)) -+ port->mode = MODE_G704; -+ else -+ ret = -EINVAL; -+ -+ spin_unlock_irqrestore(&npe_lock, flags); -+ return ret; -+} -+ -+static struct device_attribute hss_attrs[] = { -+ __ATTR(create_chan, 0200, NULL, create_chan), -+ __ATTR(hdlc_chan, 0644, show_hdlc_chan, set_hdlc_chan), -+ __ATTR(clock_type, 0644, show_clock_type, set_clock_type), -+ __ATTR(clock_rate, 0644, show_clock_rate, set_clock_rate), -+ __ATTR(frame_size, 0644, show_frame_size, set_frame_size), -+ __ATTR(frame_offset, 0644, show_frame_offset, set_frame_offset), -+ __ATTR(loopback, 0644, show_loopback, set_loopback), -+ __ATTR(mode, 0644, show_mode, set_mode), -+}; -+ -+/***************************************************************************** -+ * initialization -+ ****************************************************************************/ -+ -+static int __devinit hss_init_one(struct platform_device *pdev) -+{ -+ struct port *port; -+ struct net_device *dev; -+ hdlc_device *hdlc; -+ int i, err; -+ -+ if ((port = kzalloc(sizeof(*port), GFP_KERNEL)) == NULL) -+ return -ENOMEM; -+ platform_set_drvdata(pdev, port); -+ port->id = pdev->id; -+ -+ if ((port->npe = npe_request(0)) == NULL) { -+ err = -ENOSYS; -+ goto err_free; -+ } -+ -+ port->dev = &pdev->dev; -+ port->plat = pdev->dev.platform_data; -+ if ((port->netdev = dev = alloc_hdlcdev(port)) == NULL) { -+ err = -ENOMEM; -+ goto err_plat; -+ } -+ -+ SET_NETDEV_DEV(dev, &pdev->dev); -+ hdlc = dev_to_hdlc(dev); -+ hdlc->attach = hss_hdlc_attach; -+ hdlc->xmit = hss_hdlc_xmit; -+ dev->open = hss_hdlc_open; -+ dev->stop = hss_hdlc_close; -+ dev->do_ioctl = hss_hdlc_ioctl; -+ dev->tx_queue_len = 100; -+ port->clock_type = CLOCK_EXT; -+ port->clock_rate = 2048000; -+ port->frame_size = 256; /* E1 */ -+ memset(port->channels, CHANNEL_UNUSED, sizeof(port->channels)); -+ init_waitqueue_head(&port->chan_tx_waitq); -+ init_waitqueue_head(&port->chan_rx_waitq); -+ netif_napi_add(dev, &port->napi, hss_hdlc_poll, NAPI_WEIGHT); -+ -+ if ((err = register_hdlc_device(dev))) /* HDLC mode by default */ -+ goto err_free_netdev; -+ -+ for (i = 0; i < ARRAY_SIZE(hss_attrs); i++) -+ BUG_ON(device_create_file(port->dev, &hss_attrs[i])); -+ -+ printk(KERN_INFO "%s: HSS-%i\n", dev->name, port->id); -+ return 0; -+ -+err_free_netdev: -+ free_netdev(dev); -+err_plat: -+ npe_release(port->npe); -+ platform_set_drvdata(pdev, NULL); -+err_free: -+ kfree(port); -+ return err; -+} -+ -+static int __devexit hss_remove_one(struct platform_device *pdev) -+{ -+ struct port *port = platform_get_drvdata(pdev); -+ int i; -+ -+ for (i = 0; i < ARRAY_SIZE(hss_attrs); i++) -+ device_remove_file(port->dev, &hss_attrs[i]); -+ -+ unregister_hdlc_device(port->netdev); -+ free_netdev(port->netdev); -+ npe_release(port->npe); -+ platform_set_drvdata(pdev, NULL); -+ kfree(port); -+ return 0; -+} -+ -+static struct platform_driver drv = { -+ .driver.name = DRV_NAME, -+ .probe = hss_init_one, -+ .remove = hss_remove_one, -+}; -+ -+static int __init hss_init_module(void) -+{ -+ int err; -+ dev_t rdev; -+ -+ if ((ixp4xx_read_feature_bits() & -+ (IXP4XX_FEATURE_HDLC | IXP4XX_FEATURE_HSS)) != -+ (IXP4XX_FEATURE_HDLC | IXP4XX_FEATURE_HSS)) -+ return -ENOSYS; -+ -+ if ((err = alloc_chrdev_region(&rdev, 0, HSS_COUNT * MAX_CHAN_DEVICES, -+ "hss"))) -+ return err; -+ -+ spin_lock_init(&npe_lock); -+ -+ if (IS_ERR(hss_class = class_create(THIS_MODULE, "hss"))) { -+ printk(KERN_ERR "Can't register device class 'hss'\n"); -+ err = PTR_ERR(hss_class); -+ goto free_chrdev; -+ } -+ if ((err = platform_driver_register(&drv))) -+ goto destroy_class; -+ -+ chan_major = MAJOR(rdev); -+ return 0; -+ -+destroy_class: -+ class_destroy(hss_class); -+free_chrdev: -+ unregister_chrdev_region(MKDEV(chan_major, 0), -+ HSS_COUNT * MAX_CHAN_DEVICES); -+ return err; -+} -+ -+static void __exit hss_cleanup_module(void) -+{ -+ platform_driver_unregister(&drv); -+ class_destroy(hss_class); -+ unregister_chrdev_region(MKDEV(chan_major, 0), -+ HSS_COUNT * MAX_CHAN_DEVICES); -+} -+ -+MODULE_AUTHOR("Krzysztof Halasa"); -+MODULE_DESCRIPTION("Intel IXP4xx HSS driver"); -+MODULE_LICENSE("GPL v2"); -+MODULE_ALIAS("platform:ixp4xx_hss"); -+module_init(hss_init_module); -+module_exit(hss_cleanup_module); diff --git a/target/linux/ixp4xx/patches-2.6.28/295-latch_led_driver.patch b/target/linux/ixp4xx/patches-2.6.28/295-latch_led_driver.patch deleted file mode 100644 index e0900f465..000000000 --- a/target/linux/ixp4xx/patches-2.6.28/295-latch_led_driver.patch +++ /dev/null @@ -1,199 +0,0 @@ ---- a/drivers/leds/Kconfig -+++ b/drivers/leds/Kconfig -@@ -119,6 +119,12 @@ config LEDS_GPIO - outputs. To be useful the particular board must have LEDs - and they must be connected to the GPIO lines. - -+config LEDS_LATCH -+ tristate "LED Support for Memory Latched LEDs" -+ depends on LEDS_CLASS -+ help -+ -- To Do -- -+ - config LEDS_HP_DISK - tristate "LED Support for disk protection LED on HP notebooks" - depends on LEDS_CLASS && ACPI ---- /dev/null -+++ b/drivers/leds/leds-latch.c -@@ -0,0 +1,149 @@ -+/* -+ * LEDs driver for Memory Latched Devices -+ * -+ * Copyright (C) 2008 Gateworks Corp. -+ * Chris Lang -+ * -+ * 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 -+#include -+#include -+#include -+#include -+#include -+#include -+ -+static unsigned int mem_keep = 0xFF; -+static spinlock_t mem_lock; -+static unsigned char *iobase; -+ -+struct latch_led_data { -+ struct led_classdev cdev; -+ struct work_struct work; -+ u8 new_level; -+ u8 bit; -+ void (*set_led)(u8 bit, enum led_brightness value); -+}; -+ -+static void latch_set_led(u8 bit, enum led_brightness value) -+{ -+ if (value == LED_OFF) -+ mem_keep |= (0x1 << bit); -+ else -+ mem_keep &= ~(0x1 << bit); -+ -+ writeb(mem_keep, iobase); -+} -+ -+static void latch_led_set(struct led_classdev *led_cdev, -+ enum led_brightness value) -+{ -+ struct latch_led_data *led_dat = -+ container_of(led_cdev, struct latch_led_data, cdev); -+ -+ spin_lock(mem_lock); -+ -+ led_dat->set_led(led_dat->bit, value); -+ -+ spin_unlock(mem_lock); -+} -+ -+static int latch_led_probe(struct platform_device *pdev) -+{ -+ struct latch_led_platform_data *pdata = pdev->dev.platform_data; -+ struct latch_led *cur_led; -+ struct latch_led_data *leds_data, *led_dat; -+ int i, ret = 0; -+ -+ if (!pdata) -+ return -EBUSY; -+ -+ leds_data = kzalloc(sizeof(struct latch_led_data) * pdata->num_leds, -+ GFP_KERNEL); -+ if (!leds_data) -+ return -ENOMEM; -+ -+ for (i = 0; i < pdata->num_leds; i++) { -+ cur_led = &pdata->leds[i]; -+ led_dat = &leds_data[i]; -+ -+ led_dat->cdev.name = cur_led->name; -+ led_dat->cdev.default_trigger = cur_led->default_trigger; -+ led_dat->cdev.brightness_set = latch_led_set; -+ led_dat->cdev.brightness = LED_OFF; -+ led_dat->bit = cur_led->bit; -+ led_dat->set_led = pdata->set_led ? pdata->set_led : latch_set_led; -+ -+ ret = led_classdev_register(&pdev->dev, &led_dat->cdev); -+ if (ret < 0) { -+ goto err; -+ } -+ } -+ -+ if (!pdata->set_led) { -+ iobase = ioremap_nocache(pdata->mem, 0x1000); -+ writeb(0xFF, iobase); -+ } -+ platform_set_drvdata(pdev, leds_data); -+ -+ return 0; -+ -+err: -+ if (i > 0) { -+ for (i = i - 1; i >= 0; i--) { -+ led_classdev_unregister(&leds_data[i].cdev); -+ } -+ } -+ -+ kfree(leds_data); -+ -+ return ret; -+} -+ -+static int __devexit latch_led_remove(struct platform_device *pdev) -+{ -+ int i; -+ struct latch_led_platform_data *pdata = pdev->dev.platform_data; -+ struct latch_led_data *leds_data; -+ -+ leds_data = platform_get_drvdata(pdev); -+ -+ for (i = 0; i < pdata->num_leds; i++) { -+ led_classdev_unregister(&leds_data[i].cdev); -+ cancel_work_sync(&leds_data[i].work); -+ } -+ -+ kfree(leds_data); -+ -+ return 0; -+} -+ -+static struct platform_driver latch_led_driver = { -+ .probe = latch_led_probe, -+ .remove = __devexit_p(latch_led_remove), -+ .driver = { -+ .name = "leds-latch", -+ .owner = THIS_MODULE, -+ }, -+}; -+ -+static int __init latch_led_init(void) -+{ -+ return platform_driver_register(&latch_led_driver); -+} -+ -+static void __exit latch_led_exit(void) -+{ -+ platform_driver_unregister(&latch_led_driver); -+} -+ -+module_init(latch_led_init); -+module_exit(latch_led_exit); -+ -+MODULE_AUTHOR("Chris Lang "); -+MODULE_DESCRIPTION("Latch LED driver"); -+MODULE_LICENSE("GPL"); ---- a/drivers/leds/Makefile -+++ b/drivers/leds/Makefile -@@ -18,6 +18,7 @@ obj-$(CONFIG_LEDS_COBALT_RAQ) += leds-c - obj-$(CONFIG_LEDS_SUNFIRE) += leds-sunfire.o - obj-$(CONFIG_LEDS_PCA9532) += leds-pca9532.o - obj-$(CONFIG_LEDS_GPIO) += leds-gpio.o -+obj-$(CONFIG_LEDS_LATCH) += leds-latch.o - obj-$(CONFIG_LEDS_CLEVO_MAIL) += leds-clevo-mail.o - obj-$(CONFIG_LEDS_HP6XX) += leds-hp6xx.o - obj-$(CONFIG_LEDS_FSG) += leds-fsg.o ---- a/include/linux/leds.h -+++ b/include/linux/leds.h -@@ -148,5 +148,19 @@ struct gpio_led_platform_data { - unsigned long *delay_off); - }; - -+/* For the leds-latch driver */ -+struct latch_led { -+ const char *name; -+ char *default_trigger; -+ unsigned bit; -+}; -+ -+struct latch_led_platform_data { -+ int num_leds; -+ u32 mem; -+ struct latch_led *leds; -+ void (*set_led)(u8 bit, enum led_brightness value); -+}; -+ - - #endif /* __LINUX_LEDS_H_INCLUDED */ diff --git a/target/linux/ixp4xx/patches-2.6.28/300-avila_fetch_mac.patch b/target/linux/ixp4xx/patches-2.6.28/300-avila_fetch_mac.patch deleted file mode 100644 index 4581bdd34..000000000 --- a/target/linux/ixp4xx/patches-2.6.28/300-avila_fetch_mac.patch +++ /dev/null @@ -1,244 +0,0 @@ ---- a/arch/arm/mach-ixp4xx/avila-setup.c -+++ b/arch/arm/mach-ixp4xx/avila-setup.c -@@ -14,10 +14,16 @@ - #include - #include - #include -+#include -+#include -+#include - #include - #include - #include - #include -+#include -+#include -+ - #include - - #include -@@ -29,6 +35,13 @@ - #include - #include - -+struct avila_board_info { -+ unsigned char *model; -+ void (*setup)(void); -+}; -+ -+static struct avila_board_info *avila_info __initdata; -+ - static struct flash_platform_data avila_flash_data = { - .map_name = "cfi_probe", - .width = 2, -@@ -132,16 +145,181 @@ static struct platform_device avila_pata - .resource = avila_pata_resources, - }; - -+/* Built-in 10/100 Ethernet MAC interfaces */ -+static struct eth_plat_info avila_npeb_data = { -+ .phy = 0, -+ .rxq = 3, -+ .txreadyq = 20, -+}; -+ -+static struct eth_plat_info avila_npec_data = { -+ .phy = 1, -+ .rxq = 4, -+ .txreadyq = 21, -+}; -+ -+static struct platform_device avila_npeb_device = { -+ .name = "ixp4xx_eth", -+ .id = IXP4XX_ETH_NPEB, -+ .dev.platform_data = &avila_npeb_data, -+}; -+ -+static struct platform_device avila_npec_device = { -+ .name = "ixp4xx_eth", -+ .id = IXP4XX_ETH_NPEC, -+ .dev.platform_data = &avila_npec_data, -+}; -+ - static struct platform_device *avila_devices[] __initdata = { - &avila_i2c_gpio, - &avila_flash, - &avila_uart - }; - -+static void __init avila_gw23xx_setup(void) -+{ -+ platform_device_register(&avila_npeb_device); -+ platform_device_register(&avila_npec_device); -+} -+ -+static void __init avila_gw2342_setup(void) -+{ -+ platform_device_register(&avila_npeb_device); -+ platform_device_register(&avila_npec_device); -+} -+ -+static void __init avila_gw2345_setup(void) -+{ -+ avila_npeb_data.phy = IXP4XX_ETH_PHY_MAX_ADDR; -+ avila_npeb_data.phy_mask = 0x1e; /* ports 1-4 of the KS8995 switch */ -+ platform_device_register(&avila_npeb_device); -+ -+ avila_npec_data.phy = 5; /* port 5 of the KS8995 switch */ -+ platform_device_register(&avila_npec_device); -+} -+ -+static void __init avila_gw2347_setup(void) -+{ -+ platform_device_register(&avila_npeb_device); -+} -+ -+static void __init avila_gw2348_setup(void) -+{ -+ platform_device_register(&avila_npeb_device); -+ platform_device_register(&avila_npec_device); -+} -+ -+static void __init avila_gw2353_setup(void) -+{ -+ platform_device_register(&avila_npeb_device); -+} -+ -+static void __init avila_gw2355_setup(void) -+{ -+ avila_npeb_data.phy = IXP4XX_ETH_PHY_MAX_ADDR; -+ avila_npeb_data.phy_mask = 0x1e; /* ports 1-4 of the KS8995 switch */ -+ platform_device_register(&avila_npeb_device); -+ -+ avila_npec_data.phy = 16; -+ platform_device_register(&avila_npec_device); -+} -+ -+static void __init avila_gw2357_setup(void) -+{ -+ platform_device_register(&avila_npeb_device); -+} -+ -+static struct avila_board_info avila_boards[] __initdata = { -+ { -+ .model = "GW2342", -+ .setup = avila_gw2342_setup, -+ }, { -+ .model = "GW2345", -+ .setup = avila_gw2345_setup, -+ }, { -+ .model = "GW2347", -+ .setup = avila_gw2347_setup, -+ }, { -+ .model = "GW2348", -+ .setup = avila_gw2348_setup, -+ }, { -+ .model = "GW2353", -+ .setup = avila_gw2353_setup, -+ }, { -+ .model = "GW2355", -+ .setup = avila_gw2355_setup, -+ }, { -+ .model = "GW2357", -+ .setup = avila_gw2357_setup, -+ } -+}; -+ -+static struct avila_board_info * __init avila_find_board_info(char *model) -+{ -+ int i; -+ -+ for (i = 0; i < ARRAY_SIZE(avila_boards); i++) { -+ struct avila_board_info *info = &avila_boards[i]; -+ if (strcmp(info->model, model) == 0) -+ return info; -+ } -+ -+ return NULL; -+} -+ -+static struct at24_iface *at24_if; -+ -+static int at24_setup(struct at24_iface *iface, void *context) -+{ -+ char mac_addr[ETH_ALEN]; -+ char model[6]; -+ -+ at24_if = iface; -+ -+ /* Read MAC addresses */ -+ if (at24_if->read(at24_if, mac_addr, 0x0, 6) == 6) { -+ memcpy(&avila_npeb_data.hwaddr, mac_addr, ETH_ALEN); -+ } -+ if (at24_if->read(at24_if, mac_addr, 0x6, 6) == 6) { -+ memcpy(&avila_npec_data.hwaddr, mac_addr, ETH_ALEN); -+ } -+ -+ /* Read the first 6 bytes of the model number */ -+ if (at24_if->read(at24_if, model, 0x20, 6) == 6) { -+ avila_info = avila_find_board_info(model); -+ } -+ -+ return 0; -+} -+ -+static struct at24_platform_data avila_eeprom_info = { -+ .byte_len = 1024, -+ .page_size = 16, -+ .flags = AT24_FLAG_READONLY, -+ .setup = at24_setup, -+}; -+ -+static struct i2c_board_info __initdata avila_i2c_board_info[] = { -+ { -+ I2C_BOARD_INFO("ds1672", 0x68), -+ }, -+ { -+ I2C_BOARD_INFO("ad7418", 0x28), -+ }, -+ { -+ I2C_BOARD_INFO("24c08", 0x51), -+ .platform_data = &avila_eeprom_info -+ }, -+}; -+ - static void __init avila_init(void) - { - ixp4xx_sys_init(); - -+ /* -+ * These devices are present on all Avila models and don't need any -+ * model specific setup. -+ */ - avila_flash_resource.start = IXP4XX_EXP_BUS_BASE(0); - avila_flash_resource.end = - IXP4XX_EXP_BUS_BASE(0) + ixp4xx_exp_bus_size - 1; -@@ -159,7 +337,28 @@ static void __init avila_init(void) - - platform_device_register(&avila_pata); - -+ i2c_register_board_info(0, avila_i2c_board_info, -+ ARRAY_SIZE(avila_i2c_board_info)); -+} -+ -+static int __init avila_model_setup(void) -+{ -+ if (!machine_is_avila()) -+ return 0; -+ -+ if (avila_info) { -+ printk(KERN_DEBUG "Running on Gateworks Avila %s\n", -+ avila_info->model); -+ avila_info->setup(); -+ } else { -+ printk(KERN_INFO "Unknown/missing Avila model number" -+ " -- defaults will be used\n"); -+ avila_gw23xx_setup(); -+ } -+ -+ return 0; - } -+late_initcall(avila_model_setup); - - MACHINE_START(AVILA, "Gateworks Avila Network Platform") - /* Maintainer: Deepak Saxena */ diff --git a/target/linux/ixp4xx/patches-2.6.28/301-avila_led.patch b/target/linux/ixp4xx/patches-2.6.28/301-avila_led.patch deleted file mode 100644 index 2bd0e1609..000000000 --- a/target/linux/ixp4xx/patches-2.6.28/301-avila_led.patch +++ /dev/null @@ -1,171 +0,0 @@ ---- a/arch/arm/mach-ixp4xx/avila-setup.c -+++ b/arch/arm/mach-ixp4xx/avila-setup.c -@@ -24,6 +24,7 @@ - #include - #include - -+#include - #include - - #include -@@ -170,6 +171,72 @@ static struct platform_device avila_npec - .dev.platform_data = &avila_npec_data, - }; - -+static struct gpio_led avila_gpio_leds[] = { -+ { -+ .name = "user", /* green led */ -+ .gpio = AVILA_GW23XX_LED_USER_GPIO, -+ .active_low = 1, -+ } -+}; -+ -+static struct gpio_led_platform_data avila_gpio_leds_data = { -+ .num_leds = 1, -+ .leds = avila_gpio_leds, -+}; -+ -+static struct platform_device avila_gpio_leds_device = { -+ .name = "leds-gpio", -+ .id = -1, -+ .dev.platform_data = &avila_gpio_leds_data, -+}; -+ -+static struct latch_led avila_latch_leds[] = { -+ { -+ .name = "led0", /* green led */ -+ .bit = 0, -+ }, -+ { -+ .name = "led1", /* green led */ -+ .bit = 1, -+ }, -+ { -+ .name = "led2", /* green led */ -+ .bit = 2, -+ }, -+ { -+ .name = "led3", /* green led */ -+ .bit = 3, -+ }, -+ { -+ .name = "led4", /* green led */ -+ .bit = 4, -+ }, -+ { -+ .name = "led5", /* green led */ -+ .bit = 5, -+ }, -+ { -+ .name = "led6", /* green led */ -+ .bit = 6, -+ }, -+ { -+ .name = "led7", /* green led */ -+ .bit = 7, -+ } -+}; -+ -+static struct latch_led_platform_data avila_latch_leds_data = { -+ .num_leds = 8, -+ .leds = avila_latch_leds, -+ .mem = 0x51000000, -+}; -+ -+static struct platform_device avila_latch_leds_device = { -+ .name = "leds-latch", -+ .id = -1, -+ .dev.platform_data = &avila_latch_leds_data, -+}; -+ - static struct platform_device *avila_devices[] __initdata = { - &avila_i2c_gpio, - &avila_flash, -@@ -180,12 +247,16 @@ static void __init avila_gw23xx_setup(vo - { - platform_device_register(&avila_npeb_device); - platform_device_register(&avila_npec_device); -+ -+ platform_device_register(&avila_gpio_leds_device); - } - - static void __init avila_gw2342_setup(void) - { - platform_device_register(&avila_npeb_device); - platform_device_register(&avila_npec_device); -+ -+ platform_device_register(&avila_gpio_leds_device); - } - - static void __init avila_gw2345_setup(void) -@@ -196,22 +267,30 @@ static void __init avila_gw2345_setup(vo - - avila_npec_data.phy = 5; /* port 5 of the KS8995 switch */ - platform_device_register(&avila_npec_device); -+ -+ platform_device_register(&avila_gpio_leds_device); - } - - static void __init avila_gw2347_setup(void) - { - platform_device_register(&avila_npeb_device); -+ -+ avila_gpio_leds[0].gpio = AVILA_GW23X7_LED_USER_GPIO; -+ platform_device_register(&avila_gpio_leds_device); - } - - static void __init avila_gw2348_setup(void) - { - platform_device_register(&avila_npeb_device); - platform_device_register(&avila_npec_device); -+ -+ platform_device_register(&avila_gpio_leds_device); - } - - static void __init avila_gw2353_setup(void) - { - platform_device_register(&avila_npeb_device); -+ platform_device_register(&avila_gpio_leds_device); - } - - static void __init avila_gw2355_setup(void) -@@ -222,11 +301,29 @@ static void __init avila_gw2355_setup(vo - - avila_npec_data.phy = 16; - platform_device_register(&avila_npec_device); -+ -+ platform_device_register(&avila_gpio_leds_device); -+ -+ *IXP4XX_EXP_CS4 |= 0xbfff3c03; -+ avila_latch_leds[0].name = "RXD"; -+ avila_latch_leds[1].name = "TXD"; -+ avila_latch_leds[2].name = "POL"; -+ avila_latch_leds[3].name = "LNK"; -+ avila_latch_leds[4].name = "ERR"; -+ avila_latch_leds_data.num_leds = 5; -+ avila_latch_leds_data.mem = 0x54000000; -+ platform_device_register(&avila_latch_leds_device); - } - - static void __init avila_gw2357_setup(void) - { - platform_device_register(&avila_npeb_device); -+ -+ avila_gpio_leds[0].gpio = AVILA_GW23X7_LED_USER_GPIO; -+ platform_device_register(&avila_gpio_leds_device); -+ -+ *IXP4XX_EXP_CS1 |= 0xbfff3c03; -+ platform_device_register(&avila_latch_leds_device); - } - - static struct avila_board_info avila_boards[] __initdata = { ---- a/arch/arm/mach-ixp4xx/include/mach/avila.h -+++ b/arch/arm/mach-ixp4xx/include/mach/avila.h -@@ -36,4 +36,6 @@ - #define AVILA_PCI_INTC_PIN 9 - #define AVILA_PCI_INTD_PIN 8 - -- -+/* User LEDs */ -+#define AVILA_GW23XX_LED_USER_GPIO 3 -+#define AVILA_GW23X7_LED_USER_GPIO 4 diff --git a/target/linux/ixp4xx/patches-2.6.28/302-avila_gpio_device.patch b/target/linux/ixp4xx/patches-2.6.28/302-avila_gpio_device.patch deleted file mode 100644 index 3b75a59f7..000000000 --- a/target/linux/ixp4xx/patches-2.6.28/302-avila_gpio_device.patch +++ /dev/null @@ -1,41 +0,0 @@ ---- a/arch/arm/mach-ixp4xx/avila-setup.c -+++ b/arch/arm/mach-ixp4xx/avila-setup.c -@@ -237,10 +237,28 @@ static struct platform_device avila_latc - .dev.platform_data = &avila_latch_leds_data, - }; - -+static struct resource avila_gpio_resources[] = { -+ { -+ .name = "gpio", -+ /* FIXME: gpio mask should be model specific */ -+ .start = AVILA_GPIO_MASK, -+ .end = AVILA_GPIO_MASK, -+ .flags = 0, -+ }, -+}; -+ -+static struct platform_device avila_gpio = { -+ .name = "GPIODEV", -+ .id = -1, -+ .num_resources = ARRAY_SIZE(avila_gpio_resources), -+ .resource = avila_gpio_resources, -+}; -+ - static struct platform_device *avila_devices[] __initdata = { - &avila_i2c_gpio, - &avila_flash, -- &avila_uart -+ &avila_uart, -+ &avila_gpio, - }; - - static void __init avila_gw23xx_setup(void) ---- a/arch/arm/mach-ixp4xx/include/mach/avila.h -+++ b/arch/arm/mach-ixp4xx/include/mach/avila.h -@@ -39,3 +39,6 @@ - /* User LEDs */ - #define AVILA_GW23XX_LED_USER_GPIO 3 - #define AVILA_GW23X7_LED_USER_GPIO 4 -+ -+/* gpio mask used by platform device */ -+#define AVILA_GPIO_MASK (1 << 1) | (1 << 3) | (1 << 5) | (1 << 7) | (1 << 9) diff --git a/target/linux/ixp4xx/patches-2.6.28/303-avila_gw23x7_phy_quirk.patch b/target/linux/ixp4xx/patches-2.6.28/303-avila_gw23x7_phy_quirk.patch deleted file mode 100644 index 5810d68b2..000000000 --- a/target/linux/ixp4xx/patches-2.6.28/303-avila_gw23x7_phy_quirk.patch +++ /dev/null @@ -1,46 +0,0 @@ ---- a/arch/arm/mach-ixp4xx/avila-setup.c -+++ b/arch/arm/mach-ixp4xx/avila-setup.c -@@ -291,6 +291,7 @@ static void __init avila_gw2345_setup(vo - - static void __init avila_gw2347_setup(void) - { -+ avila_npeb_data.quirks |= IXP4XX_ETH_QUIRK_GW23X7; - platform_device_register(&avila_npeb_device); - - avila_gpio_leds[0].gpio = AVILA_GW23X7_LED_USER_GPIO; -@@ -335,6 +336,7 @@ static void __init avila_gw2355_setup(vo - - static void __init avila_gw2357_setup(void) - { -+ avila_npeb_data.quirks |= IXP4XX_ETH_QUIRK_GW23X7; - platform_device_register(&avila_npeb_device); - - avila_gpio_leds[0].gpio = AVILA_GW23X7_LED_USER_GPIO; ---- a/drivers/net/arm/ixp4xx_eth.c -+++ b/drivers/net/arm/ixp4xx_eth.c -@@ -348,6 +348,14 @@ static void phy_reset(struct net_device - return; - } - -+ if (port->plat->quirks & IXP4XX_ETH_QUIRK_GW23X7) { -+ mdio_write(dev, 1, 0x19, -+ (mdio_read(dev, 1, 0x19) & 0xfffe) | 0x8000); -+ -+ printk(KERN_DEBUG "%s: phy_id of the DP83848 changed to 0\n", -+ dev->name); -+ } -+ - /* restart auto negotiation */ - bmcr = mdio_read(dev, phy_id, MII_BMCR); - bmcr |= (BMCR_ANENABLE | BMCR_ANRESTART); ---- a/arch/arm/mach-ixp4xx/include/mach/platform.h -+++ b/arch/arm/mach-ixp4xx/include/mach/platform.h -@@ -104,6 +104,8 @@ struct eth_plat_info { - u8 txreadyq; - u8 hwaddr[6]; - u32 phy_mask; -+ u32 quirks; -+#define IXP4XX_ETH_QUIRK_GW23X7 0x00000001 - }; - - /* Information about built-in HSS (synchronous serial) interfaces */ diff --git a/target/linux/ixp4xx/patches-2.6.28/304-ixp4xx_eth_jumboframe.patch b/target/linux/ixp4xx/patches-2.6.28/304-ixp4xx_eth_jumboframe.patch deleted file mode 100644 index 8f76f7c27..000000000 --- a/target/linux/ixp4xx/patches-2.6.28/304-ixp4xx_eth_jumboframe.patch +++ /dev/null @@ -1,86 +0,0 @@ ---- a/drivers/net/arm/ixp4xx_eth.c -+++ b/drivers/net/arm/ixp4xx_eth.c -@@ -54,7 +54,7 @@ - - #define POOL_ALLOC_SIZE (sizeof(struct desc) * (RX_DESCS + TX_DESCS)) - #define REGS_SIZE 0x1000 --#define MAX_MRU 1536 /* 0x600 */ -+#define MAX_MRU (14320 - ETH_HLEN - ETH_FCS_LEN) - #define RX_BUFF_SIZE ALIGN((NET_IP_ALIGN) + MAX_MRU, 4) - - #define NAPI_WEIGHT 16 -@@ -1011,6 +1011,32 @@ static void destroy_queues(struct port * - } - } - -+static int eth_do_change_mtu(struct net_device *dev, int mtu) -+{ -+ struct port *port; -+ struct msg msg; -+ /* adjust for ethernet headers */ -+ int framesize = mtu + ETH_HLEN + ETH_FCS_LEN; -+ -+ port = netdev_priv(dev); -+ -+ memset(&msg, 0, sizeof(msg)); -+ msg.cmd = NPE_SETMAXFRAMELENGTHS; -+ msg.eth_id = port->id; -+ -+ /* max rx/tx 64 byte blocks */ -+ msg.byte2 = ((framesize + 63) / 64) << 8; -+ msg.byte3 = ((framesize + 63) / 64) << 8; -+ -+ msg.byte4 = msg.byte6 = framesize >> 8; -+ msg.byte5 = msg.byte7 = framesize & 0xff; -+ -+ if (npe_send_recv_message(port->npe, &msg, "ETH_SET_MAX_FRAME_LENGTH")) -+ return -EIO; -+ -+ return 0; -+} -+ - static int eth_open(struct net_device *dev) - { - struct port *port = netdev_priv(dev); -@@ -1061,6 +1087,8 @@ static int eth_open(struct net_device *d - if (npe_send_recv_message(port->npe, &msg, "ETH_SET_FIREWALL_MODE")) - return -EIO; - -+ eth_do_change_mtu(dev, dev->mtu); -+ - if ((err = request_queues(port)) != 0) - return err; - -@@ -1238,6 +1266,24 @@ static void eth_init_mii(struct net_devi - - } - -+static int eth_change_mtu(struct net_device *dev, int mtu) -+{ -+ int ret; -+ -+ if (mtu > MAX_MRU) -+ return -EINVAL; -+ -+ if (dev->flags & IFF_UP) { -+ ret = eth_do_change_mtu(dev, mtu); -+ if (ret < 0) -+ return ret; -+ } -+ -+ dev->mtu = mtu; -+ -+ return 0; -+} -+ - static int __devinit eth_init_one(struct platform_device *pdev) - { - struct port *port; -@@ -1272,6 +1318,7 @@ static int __devinit eth_init_one(struct - goto err_free; - } - -+ dev->change_mtu = eth_change_mtu; - dev->open = eth_open; - dev->hard_start_xmit = eth_xmit; - dev->stop = eth_close; diff --git a/target/linux/ixp4xx/patches-2.6.28/310-gtwx5717_spi_bus.patch b/target/linux/ixp4xx/patches-2.6.28/310-gtwx5717_spi_bus.patch deleted file mode 100644 index e6013d758..000000000 --- a/target/linux/ixp4xx/patches-2.6.28/310-gtwx5717_spi_bus.patch +++ /dev/null @@ -1,53 +0,0 @@ ---- a/arch/arm/mach-ixp4xx/gtwx5715-setup.c -+++ b/arch/arm/mach-ixp4xx/gtwx5715-setup.c -@@ -29,6 +29,8 @@ - #include - #include - -+#include -+ - #include - #include - #include -@@ -121,9 +123,41 @@ static struct platform_device gtwx5715_f - .resource = >wx5715_flash_resource, - }; - -+static int gtwx5715_spi_boardinfo_setup(struct spi_board_info *bi, -+ struct spi_master *master, void *data) -+{ -+ -+ strlcpy(bi->modalias, "spi-ks8995", sizeof(bi->modalias)); -+ -+ bi->max_speed_hz = 5000000 /* Hz */; -+ bi->bus_num = master->bus_num; -+ bi->mode = SPI_MODE_0; -+ -+ return 0; -+} -+ -+static struct spi_gpio_platform_data gtwx5715_spi_bus_data = { -+ .pin_cs = GTWX5715_KSSPI_SELECT, -+ .pin_clk = GTWX5715_KSSPI_CLOCK, -+ .pin_miso = GTWX5715_KSSPI_RXD, -+ .pin_mosi = GTWX5715_KSSPI_TXD, -+ .cs_activelow = 1, -+ .no_spi_delay = 1, -+ .boardinfo_setup = gtwx5715_spi_boardinfo_setup, -+}; -+ -+static struct platform_device gtwx5715_spi_bus = { -+ .name = "spi-gpio", -+ .id = 0, -+ .dev = { -+ .platform_data = >wx5715_spi_bus_data, -+ }, -+}; -+ - static struct platform_device *gtwx5715_devices[] __initdata = { - >wx5715_uart_device, - >wx5715_flash, -+ >wx5715_spi_bus, - }; - - static void __init gtwx5715_init(void) diff --git a/target/linux/ixp4xx/patches-2.6.28/311-gtwx5717_mac_plat_info.patch b/target/linux/ixp4xx/patches-2.6.28/311-gtwx5717_mac_plat_info.patch deleted file mode 100644 index 29f329017..000000000 --- a/target/linux/ixp4xx/patches-2.6.28/311-gtwx5717_mac_plat_info.patch +++ /dev/null @@ -1,40 +0,0 @@ ---- a/arch/arm/mach-ixp4xx/gtwx5715-setup.c -+++ b/arch/arm/mach-ixp4xx/gtwx5715-setup.c -@@ -154,10 +154,37 @@ static struct platform_device gtwx5715_s - }, - }; - -+static struct eth_plat_info gtwx5715_npeb_data = { -+ .phy = IXP4XX_ETH_PHY_MAX_ADDR, -+ .phy_mask = 0x1e, /* ports 1-4 of the KS8995 switch */ -+ .rxq = 3, -+ .txreadyq = 20, -+}; -+ -+static struct eth_plat_info gtwx5715_npec_data = { -+ .phy = 5, /* port 5 of the KS8995 switch */ -+ .rxq = 4, -+ .txreadyq = 21, -+}; -+ -+static struct platform_device gtwx5715_npeb_device = { -+ .name = "ixp4xx_eth", -+ .id = IXP4XX_ETH_NPEB, -+ .dev.platform_data = >wx5715_npeb_data, -+}; -+ -+static struct platform_device gtwx5715_npec_device = { -+ .name = "ixp4xx_eth", -+ .id = IXP4XX_ETH_NPEC, -+ .dev.platform_data = >wx5715_npec_data, -+}; -+ - static struct platform_device *gtwx5715_devices[] __initdata = { - >wx5715_uart_device, - >wx5715_flash, - >wx5715_spi_bus, -+ >wx5715_npeb_device, -+ >wx5715_npec_device, - }; - - static void __init gtwx5715_init(void) diff --git a/target/linux/ixp4xx/patches-2.6.28/312-ixp4xx_pata_optimization.patch b/target/linux/ixp4xx/patches-2.6.28/312-ixp4xx_pata_optimization.patch deleted file mode 100644 index d6489a7fb..000000000 --- a/target/linux/ixp4xx/patches-2.6.28/312-ixp4xx_pata_optimization.patch +++ /dev/null @@ -1,137 +0,0 @@ ---- a/drivers/ata/pata_ixp4xx_cf.c -+++ b/drivers/ata/pata_ixp4xx_cf.c -@@ -24,17 +24,58 @@ - #include - - #define DRV_NAME "pata_ixp4xx_cf" --#define DRV_VERSION "0.2" -+#define DRV_VERSION "0.3" - - static int ixp4xx_set_mode(struct ata_link *link, struct ata_device **error) - { - struct ata_device *dev; -+ struct ixp4xx_pata_data *data = link->ap->host->dev->platform_data; -+ unsigned int pio_mask; - - ata_link_for_each_dev(dev, link) { -+ if (dev->id[ATA_ID_FIELD_VALID] & (1 << 1)){ -+ pio_mask = dev->id[ATA_ID_PIO_MODES] & 0x03; -+ if (pio_mask & (1 << 1)){ -+ pio_mask = 4; -+ }else{ -+ pio_mask = 3; -+ } -+ }else{ -+ pio_mask = (dev->id[ATA_ID_OLD_PIO_MODES] >> 8); -+ } -+ switch (pio_mask){ -+ case 0: -+ ata_dev_printk(dev, KERN_INFO, "configured for PIO0\n"); -+ dev->pio_mode = XFER_PIO_0; -+ dev->xfer_mode = XFER_PIO_0; -+ *data->cs0_cfg = 0x8a473c03; -+ break; -+ case 1: -+ ata_dev_printk(dev, KERN_INFO, "configured for PIO1\n"); -+ dev->pio_mode = XFER_PIO_1; -+ dev->xfer_mode = XFER_PIO_1; -+ *data->cs0_cfg = 0x86433c03; -+ break; -+ case 2: -+ ata_dev_printk(dev, KERN_INFO, "configured for PIO2\n"); -+ dev->pio_mode = XFER_PIO_2; -+ dev->xfer_mode = XFER_PIO_2; -+ *data->cs0_cfg = 0x82413c03; -+ break; -+ case 3: -+ ata_dev_printk(dev, KERN_INFO, "configured for PIO3\n"); -+ dev->pio_mode = XFER_PIO_3; -+ dev->xfer_mode = XFER_PIO_3; -+ *data->cs0_cfg = 0x80823c03; -+ break; -+ case 4: -+ ata_dev_printk(dev, KERN_INFO, "configured for PIO4\n"); -+ dev->pio_mode = XFER_PIO_4; -+ dev->xfer_mode = XFER_PIO_4; -+ *data->cs0_cfg = 0x80403c03; -+ break; -+ } - if (ata_dev_enabled(dev)) { -- ata_dev_printk(dev, KERN_INFO, "configured for PIO0\n"); -- dev->pio_mode = XFER_PIO_0; -- dev->xfer_mode = XFER_PIO_0; - dev->xfer_shift = ATA_SHIFT_PIO; - dev->flags |= ATA_DFLAG_PIO; - } -@@ -48,6 +89,7 @@ static unsigned int ixp4xx_mmio_data_xfe - unsigned int i; - unsigned int words = buflen >> 1; - u16 *buf16 = (u16 *) buf; -+ unsigned int pio_mask; - struct ata_port *ap = dev->link->ap; - void __iomem *mmio = ap->ioaddr.data_addr; - struct ixp4xx_pata_data *data = ap->host->dev->platform_data; -@@ -55,8 +97,34 @@ static unsigned int ixp4xx_mmio_data_xfe - /* set the expansion bus in 16bit mode and restore - * 8 bit mode after the transaction. - */ -- *data->cs0_cfg &= ~(0x01); -- udelay(100); -+ if (dev->id[ATA_ID_FIELD_VALID] & (1 << 1)){ -+ pio_mask = dev->id[ATA_ID_PIO_MODES] & 0x03; -+ if (pio_mask & (1 << 1)){ -+ pio_mask = 4; -+ }else{ -+ pio_mask = 3; -+ } -+ }else{ -+ pio_mask = (dev->id[ATA_ID_OLD_PIO_MODES] >> 8); -+ } -+ switch (pio_mask){ -+ case 0: -+ *data->cs0_cfg = 0xa9643c42; -+ break; -+ case 1: -+ *data->cs0_cfg = 0x85033c42; -+ break; -+ case 2: -+ *data->cs0_cfg = 0x80b23c42; -+ break; -+ case 3: -+ *data->cs0_cfg = 0x80823c42; -+ break; -+ case 4: -+ *data->cs0_cfg = 0x80403c42; -+ break; -+ } -+ udelay(5); - - /* Transfer multiple of 2 bytes */ - if (rw == READ) -@@ -81,8 +149,24 @@ static unsigned int ixp4xx_mmio_data_xfe - words++; - } - -- udelay(100); -- *data->cs0_cfg |= 0x01; -+ udelay(5); -+ switch (pio_mask){ -+ case 0: -+ *data->cs0_cfg = 0x8a473c03; -+ break; -+ case 1: -+ *data->cs0_cfg = 0x86433c03; -+ break; -+ case 2: -+ *data->cs0_cfg = 0x82413c03; -+ break; -+ case 3: -+ *data->cs0_cfg = 0x80823c03; -+ break; -+ case 4: -+ *data->cs0_cfg = 0x80403c03; -+ break; -+ } - - return words << 1; - } diff --git a/target/linux/ixp4xx/patches-2.6.28/400-dmabounce.patch b/target/linux/ixp4xx/patches-2.6.28/400-dmabounce.patch deleted file mode 100644 index af68a55b1..000000000 --- a/target/linux/ixp4xx/patches-2.6.28/400-dmabounce.patch +++ /dev/null @@ -1,27 +0,0 @@ ---- a/arch/arm/common/dmabounce.c -+++ b/arch/arm/common/dmabounce.c -@@ -117,6 +117,10 @@ alloc_safe_buffer(struct dmabounce_devic - } else if (size <= device_info->large.size) { - pool = &device_info->large; - } else { -+#ifdef CONFIG_DMABOUNCE_DEBUG -+ printk(KERN_INFO "A dma bounce buffer outside the pool size was requested. Requested size was 0x%08X\nThe calling code was :\n", size); -+ dump_stack(); -+#endif - pool = NULL; - } - ---- a/arch/arm/mach-ixp4xx/Kconfig -+++ b/arch/arm/mach-ixp4xx/Kconfig -@@ -246,6 +246,11 @@ config MACH_MI424WR - - comment "IXP4xx Options" - -+config DMABOUNCE_DEBUG -+ bool "Enable DMABounce debuging" -+ default n -+ depends on DMABOUNCE -+ - config IXP4XX_INDIRECT_PCI - bool "Use indirect PCI memory access" - depends on PCI diff --git a/target/linux/ixp4xx/patches-2.6.28/401-avila_pci_dev.patch b/target/linux/ixp4xx/patches-2.6.28/401-avila_pci_dev.patch deleted file mode 100644 index 3e5087f34..000000000 --- a/target/linux/ixp4xx/patches-2.6.28/401-avila_pci_dev.patch +++ /dev/null @@ -1,11 +0,0 @@ ---- a/arch/arm/mach-ixp4xx/include/mach/avila.h -+++ b/arch/arm/mach-ixp4xx/include/mach/avila.h -@@ -25,7 +25,7 @@ - /* - * AVILA PCI IRQs - */ --#define AVILA_PCI_MAX_DEV 4 -+#define AVILA_PCI_MAX_DEV 6 - #define LOFT_PCI_MAX_DEV 6 - #define AVILA_PCI_IRQ_LINES 4 - diff --git a/target/linux/ixp4xx/patches-2.6.28/402-ixp4xx_gpiolib.patch b/target/linux/ixp4xx/patches-2.6.28/402-ixp4xx_gpiolib.patch deleted file mode 100644 index b9b73057f..000000000 --- a/target/linux/ixp4xx/patches-2.6.28/402-ixp4xx_gpiolib.patch +++ /dev/null @@ -1,125 +0,0 @@ ---- a/arch/arm/mach-ixp4xx/common.c -+++ b/arch/arm/mach-ixp4xx/common.c -@@ -36,6 +36,7 @@ - #include - #include - #include -+#include - - #include - #include -@@ -374,12 +375,39 @@ static struct platform_device *ixp46x_de - unsigned long ixp4xx_exp_bus_size; - EXPORT_SYMBOL(ixp4xx_exp_bus_size); - -+static int ixp4xx_gpio_direction_input(struct gpio_chip *chip, unsigned gpio) -+{ -+ gpio_line_config(gpio, IXP4XX_GPIO_IN); -+ return 0; -+} -+EXPORT_SYMBOL(ixp4xx_gpio_direction_input); -+ -+static int ixp4xx_gpio_direction_output(struct gpio_chip *chip, unsigned gpio, int level) -+{ -+ gpio_line_set(gpio, level); -+ gpio_line_config(gpio, IXP4XX_GPIO_OUT); -+ return 0; -+} -+EXPORT_SYMBOL(ixp4xx_gpio_direction_output); -+ -+static struct gpio_chip ixp4xx_gpio_chip = { -+ .label = "IXP4XX_GPIO_CHIP", -+ .direction_input = ixp4xx_gpio_direction_input, -+ .direction_output = ixp4xx_gpio_direction_output, -+ .get = gpio_get_value, -+ .set = gpio_set_value, -+ .base = 0, -+ .ngpio = 16, -+}; -+ - void __init ixp4xx_sys_init(void) - { - ixp4xx_exp_bus_size = SZ_16M; - - platform_add_devices(ixp4xx_devices, ARRAY_SIZE(ixp4xx_devices)); - -+ gpiochip_add(&ixp4xx_gpio_chip); -+ - if (cpu_is_ixp46x()) { - int region; - ---- a/arch/arm/Kconfig -+++ b/arch/arm/Kconfig -@@ -355,6 +355,7 @@ config ARCH_IXP4XX - select GENERIC_GPIO - select GENERIC_TIME - select GENERIC_CLOCKEVENTS -+ select ARCH_REQUIRE_GPIOLIB - select DMABOUNCE if PCI - help - Support for Intel's IXP4XX (XScale) family of processors. ---- a/arch/arm/mach-ixp4xx/include/mach/gpio.h -+++ b/arch/arm/mach-ixp4xx/include/mach/gpio.h -@@ -27,47 +27,31 @@ - - #include - #include -+#include /* cansleep wrappers */ - --static inline int gpio_request(unsigned gpio, const char *label) --{ -- return 0; --} -- --static inline void gpio_free(unsigned gpio) --{ -- might_sleep(); -- -- return; --} -- --static inline int gpio_direction_input(unsigned gpio) --{ -- gpio_line_config(gpio, IXP4XX_GPIO_IN); -- return 0; --} -- --static inline int gpio_direction_output(unsigned gpio, int level) --{ -- gpio_line_set(gpio, level); -- gpio_line_config(gpio, IXP4XX_GPIO_OUT); -- return 0; --} -+#define NR_BUILTIN_GPIO 16 - - static inline int gpio_get_value(unsigned gpio) - { -- int value; -- -- gpio_line_get(gpio, &value); -- -- return value; -+ if (gpio < NR_BUILTIN_GPIO) -+ { -+ int value; -+ gpio_line_get(gpio, &value); -+ return value; -+ } -+ else -+ return __gpio_get_value(gpio); - } - - static inline void gpio_set_value(unsigned gpio, int value) - { -- gpio_line_set(gpio, value); -+ if (gpio < NR_BUILTIN_GPIO) -+ gpio_line_set(gpio, value); -+ else -+ __gpio_set_value(gpio, value); - } - --#include /* cansleep wrappers */ -+#define gpio_cansleep __gpio_cansleep - - extern int gpio_to_irq(int gpio); - extern int irq_to_gpio(int gpio); diff --git a/target/linux/ixp4xx/patches-2.6.28/500-usr8200_support.patch b/target/linux/ixp4xx/patches-2.6.28/500-usr8200_support.patch deleted file mode 100644 index d0175044d..000000000 --- a/target/linux/ixp4xx/patches-2.6.28/500-usr8200_support.patch +++ /dev/null @@ -1,342 +0,0 @@ ---- a/arch/arm/mach-ixp4xx/Kconfig -+++ b/arch/arm/mach-ixp4xx/Kconfig -@@ -97,6 +97,14 @@ config MACH_SIDEWINDER - Engineering Sidewinder board. For more information on this - platform, see http://www.adiengineering.com - -+config MACH_USR8200 -+ bool "USRobotics USR8200" -+ select PCI -+ help -+ Say 'Y' here if you want your kernel to support the USRobotics -+ USR8200 router board. For more information on this platform, see -+ http://openwrt.org -+ - config MACH_COMPEX - bool "Compex WP18 / NP18A" - select PCI ---- a/arch/arm/mach-ixp4xx/Makefile -+++ b/arch/arm/mach-ixp4xx/Makefile -@@ -25,6 +25,7 @@ obj-pci-$(CONFIG_MACH_WRT300NV2) += wrt - obj-pci-$(CONFIG_MACH_AP1000) += ixdp425-pci.o - obj-pci-$(CONFIG_MACH_TW5334) += tw5334-pci.o - obj-pci-$(CONFIG_MACH_MI424WR) += mi424wr-pci.o -+obj-pci-$(CONFIG_MACH_USR8200) += usr8200-pci.o - - obj-y += common.o - -@@ -48,6 +49,7 @@ obj-$(CONFIG_MACH_WRT300NV2) += wrt300nv - obj-$(CONFIG_MACH_AP1000) += ap1000-setup.o - obj-$(CONFIG_MACH_TW5334) += tw5334-setup.o - obj-$(CONFIG_MACH_MI424WR) += mi424wr-setup.o -+obj-$(CONFIG_MACH_USR8200) += usr8200-setup.o - - obj-$(CONFIG_PCI) += $(obj-pci-$(CONFIG_PCI)) common-pci.o - obj-$(CONFIG_IXP4XX_QMGR) += ixp4xx_qmgr.o ---- /dev/null -+++ b/arch/arm/mach-ixp4xx/usr8200-pci.c -@@ -0,0 +1,78 @@ -+/* -+ * arch/arch/mach-ixp4xx/usr8200-pci.c -+ * -+ * PCI setup routines for USRobotics USR8200 -+ * -+ * Copyright (C) 2008 Peter Denison -+ * -+ * based on pronghorn-pci.c -+ * Copyright (C) 2008 Imre Kaloz -+ * based on coyote-pci.c: -+ * Copyright (C) 2002 Jungo Software Technologies. -+ * Copyright (C) 2003 MontaVista Softwrae, Inc. -+ * -+ * Maintainer: Peter Denison -+ * -+ * 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 -+#include -+#include -+#include -+ -+#include -+#include -+ -+#include -+ -+void __init usr8200_pci_preinit(void) -+{ -+ set_irq_type(IRQ_IXP4XX_GPIO7, IRQ_TYPE_LEVEL_LOW); -+ set_irq_type(IRQ_IXP4XX_GPIO8, IRQ_TYPE_LEVEL_LOW); -+ set_irq_type(IRQ_IXP4XX_GPIO9, IRQ_TYPE_LEVEL_LOW); -+ set_irq_type(IRQ_IXP4XX_GPIO10, IRQ_TYPE_LEVEL_LOW); -+ set_irq_type(IRQ_IXP4XX_GPIO11, IRQ_TYPE_LEVEL_LOW); -+ -+ ixp4xx_pci_preinit(); -+} -+ -+static int __init usr8200_map_irq(struct pci_dev *dev, u8 slot, u8 pin) -+{ -+ if (slot == 14) -+ return IRQ_IXP4XX_GPIO7; -+ else if (slot == 15) -+ return IRQ_IXP4XX_GPIO8; -+ else if (slot == 16) { -+ if (pin == 1) -+ return IRQ_IXP4XX_GPIO11; -+ else if (pin == 2) -+ return IRQ_IXP4XX_GPIO10; -+ else if (pin == 3) -+ return IRQ_IXP4XX_GPIO9; -+ else -+ return -1; -+ } else -+ return -1; -+} -+ -+struct hw_pci usr8200_pci __initdata = { -+ .nr_controllers = 1, -+ .preinit = usr8200_pci_preinit, -+ .swizzle = pci_std_swizzle, -+ .setup = ixp4xx_setup, -+ .scan = ixp4xx_scan_bus, -+ .map_irq = usr8200_map_irq, -+}; -+ -+int __init usr8200_pci_init(void) -+{ -+ if (machine_is_usr8200()) -+ pci_common_init(&usr8200_pci); -+ return 0; -+} -+ -+subsys_initcall(usr8200_pci_init); ---- /dev/null -+++ b/arch/arm/mach-ixp4xx/usr8200-setup.c -@@ -0,0 +1,212 @@ -+/* -+ * arch/arm/mach-ixp4xx/usr8200-setup.c -+ * -+ * Board setup for the USRobotics USR8200 -+ * -+ * Copyright (C) 2008 Peter Denison -+ * -+ * based on pronghorn-setup.c: -+ * Copyright (C) 2008 Imre Kaloz -+ * based on coyote-setup.c: -+ * Copyright (C) 2003-2005 MontaVista Software, Inc. -+ * -+ * Author: Peter Denison -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+static struct flash_platform_data usr8200_flash_data = { -+ .map_name = "cfi_probe", -+ .width = 2, -+}; -+ -+static struct resource usr8200_flash_resource = { -+ .flags = IORESOURCE_MEM, -+}; -+ -+static struct platform_device usr8200_flash = { -+ .name = "IXP4XX-Flash", -+ .id = 0, -+ .dev = { -+ .platform_data = &usr8200_flash_data, -+ }, -+ .num_resources = 1, -+ .resource = &usr8200_flash_resource, -+}; -+ -+static struct resource usr8200_uart_resources [] = { -+ { -+ .start = IXP4XX_UART2_BASE_PHYS, -+ .end = IXP4XX_UART2_BASE_PHYS + 0x0fff, -+ .flags = IORESOURCE_MEM -+ }, -+ { -+ .start = IXP4XX_UART1_BASE_PHYS, -+ .end = IXP4XX_UART1_BASE_PHYS + 0x0fff, -+ .flags = IORESOURCE_MEM -+ } -+}; -+ -+static struct plat_serial8250_port usr8200_uart_data[] = { -+ { -+ .mapbase = IXP4XX_UART2_BASE_PHYS, -+ .membase = (char *)IXP4XX_UART2_BASE_VIRT + REG_OFFSET, -+ .irq = IRQ_IXP4XX_UART2, -+ .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST, -+ .iotype = UPIO_MEM, -+ .regshift = 2, -+ .uartclk = IXP4XX_UART_XTAL, -+ }, -+ { -+ .mapbase = IXP4XX_UART1_BASE_PHYS, -+ .membase = (char *)IXP4XX_UART1_BASE_VIRT + REG_OFFSET, -+ .irq = IRQ_IXP4XX_UART1, -+ .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST, -+ .iotype = UPIO_MEM, -+ .regshift = 2, -+ .uartclk = IXP4XX_UART_XTAL, -+ }, -+ { }, -+}; -+ -+static struct platform_device usr8200_uart = { -+ .name = "serial8250", -+ .id = PLAT8250_DEV_PLATFORM, -+ .dev = { -+ .platform_data = usr8200_uart_data, -+ }, -+ .num_resources = 2, -+ .resource = usr8200_uart_resources, -+}; -+ -+static struct gpio_led usr8200_led_pin[] = { -+ { -+ .name = "usr8200:usb1", -+ .gpio = 0, -+ .active_low = 1, -+ }, -+ { -+ .name = "usr8200:usb2", -+ .gpio = 1, -+ .active_low = 1, -+ }, -+ { -+ .name = "usr8200:ieee1394", -+ .gpio = 2, -+ .active_low = 1, -+ }, -+ { -+ .name = "usr8200:internal", -+ .gpio = 3, -+ .active_low = 1, -+ }, -+ { -+ .name = "usr8200:power", -+ .gpio = 14, -+ } -+}; -+ -+static struct gpio_led_platform_data usr8200_led_data = { -+ .num_leds = ARRAY_SIZE(usr8200_led_pin), -+ .leds = usr8200_led_pin, -+}; -+ -+static struct platform_device usr8200_led = { -+ .name = "leds-gpio", -+ .id = -1, -+ .dev.platform_data = &usr8200_led_data, -+}; -+ -+static struct eth_plat_info usr8200_plat_eth[] = { -+ { /* NPEC - LAN with Marvell 88E6060 switch */ -+ .phy = IXP4XX_ETH_PHY_MAX_ADDR, -+ .phy_mask = 0x0F0000, -+ .rxq = 4, -+ .txreadyq = 21, -+ }, { /* NPEB - WAN */ -+ .phy = 9, -+ .rxq = 3, -+ .txreadyq = 20, -+ } -+}; -+ -+static struct platform_device usr8200_eth[] = { -+ { -+ .name = "ixp4xx_eth", -+ .id = IXP4XX_ETH_NPEC, -+ .dev.platform_data = usr8200_plat_eth, -+ }, { -+ .name = "ixp4xx_eth", -+ .id = IXP4XX_ETH_NPEB, -+ .dev.platform_data = usr8200_plat_eth + 1, -+ } -+}; -+ -+static struct resource usr8200_rtc_resources = { -+ .flags = IORESOURCE_MEM -+}; -+ -+static struct platform_device usr8200_rtc = { -+ .name = "rtc7301", -+ .id = 0, -+ .num_resources = 1, -+ .resource = &usr8200_rtc_resources, -+}; -+ -+static struct platform_device *usr8200_devices[] __initdata = { -+ &usr8200_flash, -+ &usr8200_uart, -+ &usr8200_led, -+ &usr8200_eth[0], -+ &usr8200_eth[1], -+ &usr8200_rtc, -+}; -+ -+static void __init usr8200_init(void) -+{ -+ ixp4xx_sys_init(); -+ -+ usr8200_flash_resource.start = IXP4XX_EXP_BUS_BASE(0); -+ usr8200_flash_resource.end = IXP4XX_EXP_BUS_BASE(0) + SZ_16M - 1; -+ -+ usr8200_rtc_resources.start = IXP4XX_EXP_BUS_BASE(2); -+ usr8200_rtc_resources.end = IXP4XX_EXP_BUS_BASE(2) + 0x01ff; -+ -+ *IXP4XX_EXP_CS0 |= IXP4XX_FLASH_WRITABLE; -+ *IXP4XX_EXP_CS2 = 0x3fff000 | IXP4XX_EXP_BUS_SIZE(0) | IXP4XX_EXP_BUS_WR_EN | -+ IXP4XX_EXP_BUS_CS_EN | IXP4XX_EXP_BUS_BYTE_EN; -+ *IXP4XX_GPIO_GPCLKR = 0x01100000; -+ -+ /* configure button as input */ -+ gpio_line_config(12, IXP4XX_GPIO_IN); -+ -+ platform_add_devices(usr8200_devices, ARRAY_SIZE(usr8200_devices)); -+} -+ -+MACHINE_START(USR8200, "USRobotics USR8200") -+ /* Maintainer: Peter Denison */ -+ .phys_io = IXP4XX_PERIPHERAL_BASE_PHYS, -+ .io_pg_offst = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc, -+ .map_io = ixp4xx_map_io, -+ .init_irq = ixp4xx_init_irq, -+ .timer = &ixp4xx_timer, -+ .boot_params = 0x0100, -+ .init_machine = usr8200_init, -+MACHINE_END ---- a/arch/arm/mach-ixp4xx/include/mach/uncompress.h -+++ b/arch/arm/mach-ixp4xx/include/mach/uncompress.h -@@ -43,7 +43,7 @@ static __inline__ void __arch_decomp_set - if (machine_is_adi_coyote() || machine_is_gtwx5715() || - machine_is_gateway7001() || machine_is_wg302v2() || - machine_is_pronghorn() || machine_is_pronghorn_metro() || machine_is_wrt300nv2() || -- machine_is_tw5334()) -+ machine_is_tw5334() || machine_is_usr8200()) - uart_base = (volatile u32*) IXP4XX_UART2_BASE_PHYS; - else - uart_base = (volatile u32*) IXP4XX_UART1_BASE_PHYS; diff --git a/target/linux/ixp4xx/patches-2.6.30/600-dma_performance.patch b/target/linux/ixp4xx/patches-2.6.30/600-dma_performance.patch new file mode 100644 index 000000000..5aac26ee8 --- /dev/null +++ b/target/linux/ixp4xx/patches-2.6.30/600-dma_performance.patch @@ -0,0 +1,13 @@ +--- a/net/core/skbuff.c ++++ b/net/core/skbuff.c +@@ -260,6 +260,10 @@ struct sk_buff *__alloc_skb(unsigned int + if (!skb) + goto out; + ++#ifdef CONFIG_ARCH_IXP4XX ++ gfp_mask |= GFP_DMA; ++#endif ++ + size = SKB_DATA_ALIGN(size); + data = kmalloc_node_track_caller(size + sizeof(struct skb_shared_info), + gfp_mask, node); diff --git a/target/linux/kirkwood/Makefile b/target/linux/kirkwood/Makefile index a82ca0e0b..a1e9e5f57 100644 --- a/target/linux/kirkwood/Makefile +++ b/target/linux/kirkwood/Makefile @@ -11,7 +11,7 @@ BOARD:=kirkwood BOARDNAME:=Marvell Kirkwood FEATURES:=tgz usb -LINUX_VERSION:=2.6.30.9 +LINUX_VERSION:=2.6.30.10 include $(INCLUDE_DIR)/target.mk diff --git a/target/linux/mpc52xx/Makefile b/target/linux/mpc52xx/Makefile index 0e5e81db6..8e2a8cdaa 100644 --- a/target/linux/mpc52xx/Makefile +++ b/target/linux/mpc52xx/Makefile @@ -11,8 +11,7 @@ BOARD:=mpc52xx BOARDNAME:=Freescale MPC52xx FEATURES:=tgz ext2 -LINUX_VERSION:=2.6.30.9 -LINUX_KARCH:=powerpc +LINUX_VERSION:=2.6.30.10 include $(INCLUDE_DIR)/target.mk diff --git a/target/linux/mpc52xx/config-2.6.30 b/target/linux/mpc52xx/config-2.6.30 index fb97478ef..9faed93d2 100644 --- a/target/linux/mpc52xx/config-2.6.30 +++ b/target/linux/mpc52xx/config-2.6.30 @@ -155,6 +155,7 @@ CONFIG_OF=y # CONFIG_PACKET_MMAP is not set CONFIG_PAGEFLAGS_EXTENDED=y CONFIG_PAGE_OFFSET=0xc0000000 +# CONFIG_PATA_MPC52xx is not set # CONFIG_PARTITION_ADVANCED is not set CONFIG_PCI_DOMAINS=y # CONFIG_PCIEPORTBUS is not set diff --git a/target/linux/mpc83xx/Makefile b/target/linux/mpc83xx/Makefile index 4dca6165e..1bbfa768d 100644 --- a/target/linux/mpc83xx/Makefile +++ b/target/linux/mpc83xx/Makefile @@ -1,5 +1,5 @@ # -# Copyright (C) 2007-2009 OpenWrt.org +# Copyright (C) 2007-2010 OpenWrt.org # # This is free software, licensed under the GNU General Public License v2. # See /LICENSE for more information. @@ -9,10 +9,9 @@ include $(TOPDIR)/rules.mk ARCH:=powerpc BOARD:=mpc83xx BOARDNAME:=Freescale MPC83xx -FEATURES:=tgz broken +FEATURES:=squashfs tgz broken -LINUX_VERSION:=2.6.30.9 -LINUX_KARCH:=powerpc +LINUX_VERSION:=2.6.31.11 include $(INCLUDE_DIR)/target.mk diff --git a/target/linux/mpc83xx/config-default b/target/linux/mpc83xx/config-default index b1cf4feb0..bbb69d5c6 100644 --- a/target/linux/mpc83xx/config-default +++ b/target/linux/mpc83xx/config-default @@ -21,21 +21,15 @@ CONFIG_ARCH_SUSPEND_POSSIBLE=y CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y # CONFIG_ASP834x is not set CONFIG_ATA=y +# CONFIG_ATA_PIIX is not set CONFIG_AUDIT_ARCH=y -# CONFIG_BINARY_PRINTF is not set CONFIG_BITREVERSE=y # CONFIG_BOOTX_TEXT is not set CONFIG_BOUNCE=y # CONFIG_BRIQ_PANEL is not set CONFIG_CC_OPTIMIZE_FOR_SIZE=y -CONFIG_CMDLINE_BOOL=y CONFIG_CMDLINE="console=ttyS0,115200" -CONFIG_CRYPTO_AEAD2=y -CONFIG_CRYPTO_BLKCIPHER2=y -CONFIG_CRYPTO_HASH2=y -CONFIG_CRYPTO_MANAGER2=y -CONFIG_CRYPTO_RNG2=y -CONFIG_CRYPTO_WORKQUEUE=y +CONFIG_CMDLINE_BOOL=y CONFIG_DECOMPRESS_LZMA=y CONFIG_DEFAULT_UIMAGE=y CONFIG_DEVPORT=y @@ -44,19 +38,23 @@ CONFIG_DTC=y CONFIG_EARLY_PRINTK=y # CONFIG_EDAC is not set # CONFIG_EMBEDDED6xx is not set +CONFIG_EXTRA_TARGETS="uImage.fit.mpc8377_wlan" CONFIG_FORCE_MAX_ZONEORDER=11 # CONFIG_FSL_EMB_PERFMON is not set CONFIG_FSL_PCI=y CONFIG_FSL_PQ_MDIO=y CONFIG_FSL_SOC=y # CONFIG_FSL_ULI1575 is not set +# CONFIG_FSNOTIFY is not set +CONFIG_GENERIC_ATOMIC64=y CONFIG_GENERIC_BUG=y -CONFIG_GENERIC_CLOCKEVENTS_BUILD=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=y # CONFIG_GENERIC_IOMAP is not set CONFIG_GENERIC_ISA_DMA=y CONFIG_GENERIC_NVRAM=y @@ -83,26 +81,27 @@ CONFIG_HAVE_KPROBES=y CONFIG_HAVE_KRETPROBES=y CONFIG_HAVE_LATENCYTOP_SUPPORT=y CONFIG_HAVE_LMB=y -CONFIG_HAVE_MLOCK=y CONFIG_HAVE_OPROFILE=y +CONFIG_HAVE_PERF_COUNTERS=y # CONFIG_HAVE_SETUP_PER_CPU_AREA is not set # CONFIG_HVC_RTAS is not set -# CONFIG_HVC_UDBG is not set CONFIG_HW_RANDOM=y -# CONFIG_HZ_100 is not set CONFIG_HZ=250 +# CONFIG_HZ_100 is not set CONFIG_HZ_250=y CONFIG_INITRAMFS_SOURCE="" # CONFIG_IOMMU_HELPER is not set CONFIG_IPIC=y -CONFIG_IRQ_PER_CPU=y # CONFIG_IRQSTACKS is not set -CONFIG_ISA_DMA_API=y +CONFIG_IRQ_PER_CPU=y # CONFIG_ISA is not set +CONFIG_ISA_DMA_API=y # CONFIG_JFFS2_FS is not set CONFIG_KERNEL_START=0xc0000000 +# CONFIG_KMETER1 is not set # CONFIG_LEDS_GPIO is not set CONFIG_LOWMEM_SIZE=0x30000000 +CONFIG_MAC80211_DEFAULT_PS_VALUE=0 # CONFIG_MACINTOSH_DRIVERS is not set # CONFIG_MMIO_NVRAM is not set # CONFIG_MPC5121_ADS is not set @@ -115,34 +114,37 @@ CONFIG_LOWMEM_SIZE=0x30000000 # CONFIG_MPC836x_MDS is not set # CONFIG_MPC836x_RDK is not set # CONFIG_MPC837x_MDS is not set -# CONFIG_MPC837x_RDB is not set +CONFIG_MPC837x_RDB=y # CONFIG_MPC8xxx_GPIO is not set -# CONFIG_MPIC_WEIRD is not set CONFIG_MPIC=y +# CONFIG_MPIC_WEIRD is not set # CONFIG_MTD_CFI is not set +CONFIG_MTD_NAND=y # CONFIG_MTD_NAND_FSL_ELBC is not set # CONFIG_MTD_NAND_FSL_UPM is not set CONFIG_MTD_NAND_RB_PPC=y -CONFIG_MTD_NAND=y # CONFIG_MTD_OF_PARTS is not set +# CONFIG_MV643XX_ETH is not set +CONFIG_OF=y CONFIG_OF_DEVICE=y CONFIG_OF_GPIO=y -CONFIG_OF=y +CONFIG_OF_MDIO=y CONFIG_PAGEFLAGS_EXTENDED=y CONFIG_PAGE_OFFSET=0xc0000000 CONFIG_PATA_RB_PPC=m +CONFIG_PCIEAER=y +# CONFIG_PCIEAER_INJECT is not set +CONFIG_PCIEPORTBUS=y +# CONFIG_PCIE_ECRC is not set CONFIG_PCI_DISABLE_COMMON_QUIRKS=y CONFIG_PCI_DOMAINS=y -# CONFIG_PCIEPORTBUS is not set CONFIG_PCSPKR_PLATFORM=y +# CONFIG_PERF_COUNTERS is not set CONFIG_PHYLIB=y CONFIG_PHYSICAL_START=0x00000000 -# CONFIG_PPC_16K_PAGES is not set -# CONFIG_PPC_256K_PAGES is not set +CONFIG_PPC=y CONFIG_PPC32=y -CONFIG_PPC_4K_PAGES=y # CONFIG_PPC64 is not set -# CONFIG_PPC_64K_PAGES is not set # CONFIG_PPC_82xx is not set CONFIG_PPC_83xx=y # CONFIG_PPC_85xx is not set @@ -150,14 +152,17 @@ CONFIG_PPC_83xx=y # CONFIG_PPC_8xx is not set # CONFIG_PPC_970_NAP is not set CONFIG_PPC_BOOK3S=y +CONFIG_PPC_BOOK3S_32=y # CONFIG_PPC_CELL is not set # CONFIG_PPC_CELL_NATIVE is not set -CONFIG_PPC_CHRP=y +# CONFIG_PPC_CHRP is not set # CONFIG_PPC_CLOCK is not set # CONFIG_PPC_DCR_MMIO is not set # CONFIG_PPC_DCR_NATIVE is not set +CONFIG_PPC_DISABLE_WERROR=y # CONFIG_PPC_EARLY_DEBUG is not set CONFIG_PPC_FPU=y +CONFIG_PPC_HAVE_PMU_SUPPORT=y CONFIG_PPC_I8259=y # CONFIG_PPC_INDIRECT_IO is not set CONFIG_PPC_INDIRECT_PCI=y @@ -166,16 +171,17 @@ CONFIG_PPC_LIB_RHEAP=y CONFIG_PPC_MPC106=y # CONFIG_PPC_MPC52xx is not set CONFIG_PPC_MPC834x=y +CONFIG_PPC_MPC837x=y CONFIG_PPC_NATIVE=y -CONFIG_PPC_OF_BOOT_TRAMPOLINE=y CONFIG_PPC_OF=y +CONFIG_PPC_OF_BOOT_TRAMPOLINE=y CONFIG_PPC_PCI_CHOICE=y # CONFIG_PPC_PMAC is not set CONFIG_PPC_RTAS=y -CONFIG_PPC_STD_MMU_32=y CONFIG_PPC_STD_MMU=y +CONFIG_PPC_STD_MMU_32=y CONFIG_PPC_UDBG_16550=y -CONFIG_PPC=y +CONFIG_PPC_WERROR=y # CONFIG_PQ2ADS is not set CONFIG_PRINT_STACK_DEPTH=64 CONFIG_PROC_DEVICETREE=y @@ -198,12 +204,10 @@ CONFIG_SERIAL_8250_EXTENDED=y CONFIG_SERIAL_8250_SHARE_IRQ=y CONFIG_SERIAL_OF_PLATFORM=y # CONFIG_SERIAL_QE is not set -# CONFIG_SIMPLE_GPIO is not set -# CONFIG_SLOW_WORK is not set # CONFIG_SQUASHFS is not set +# CONFIG_SWIOTLB is not set CONFIG_TASK_SIZE=0xc0000000 # CONFIG_TAU is not set -CONFIG_TRACING_SUPPORT=y # CONFIG_UCC_GETH is not set # CONFIG_UDBG_RTAS_CONSOLE is not set # CONFIG_WATCHDOG_RTAS is not set diff --git a/target/linux/mpc83xx/files/scripts/mkits.sh b/target/linux/mpc83xx/files/scripts/mkits.sh new file mode 100755 index 000000000..3b02b6950 --- /dev/null +++ b/target/linux/mpc83xx/files/scripts/mkits.sh @@ -0,0 +1,111 @@ +#!/bin/bash +# +# Licensed under the terms of the GNU GPL License version 2 or later. +# +# Author: Peter Tyser +# +# U-Boot firmware supports the booting of images in the Flattened Image +# Tree (FIT) format. The FIT format uses a device tree structure to +# describe a kernel image, device tree blob, ramdisk, etc. This script +# creates an Image Tree Source (.its file) which can be passed to the +# 'mkimage' utility to generate an Image Tree Blob (.itb file). The .itb +# file can then be booted by U-Boot (or other bootloaders which support +# FIT images). See doc/uImage.FIT/howto.txt in U-Boot source code for +# additional information on FIT images. +# + +usage() { + echo "Usage: `basename $0` -A arch -C comp -a addr -e entry" \ + "-v version -k kernel [-d dtb] -o its_file" + echo -e "\t-A ==> set architecture to 'arch'" + echo -e "\t-C ==> set compression type 'comp'" + echo -e "\t-a ==> set load address to 'addr' (hex)" + echo -e "\t-e ==> set entry point to 'entry' (hex)" + echo -e "\t-v ==> set kernel version to 'version'" + echo -e "\t-k ==> include kernel image 'kernel'" + echo -e "\t-d ==> include Device Tree Blob 'dtb'" + echo -e "\t-o ==> create output file 'its_file'" + exit 1 +} + +while getopts ":A:C:a:d:e:k:o:v:" OPTION +do + case $OPTION in + A ) ARCH=$OPTARG;; + C ) COMPRESS=$OPTARG;; + a ) LOAD_ADDR=$OPTARG;; + d ) DTB=$OPTARG;; + e ) ENTRY_ADDR=$OPTARG;; + k ) KERNEL=$OPTARG;; + o ) OUTPUT=$OPTARG;; + v ) VERSION=$OPTARG;; + * ) echo "Invalid option passed to '$0' (options:$@)" + usage;; + esac +done + +# Make sure user entered all required parameters +if [ -z "${ARCH}" ] || [ -z "${COMPRESS}" ] || [ -z "${LOAD_ADDR}" ] || \ + [ -z "${ENTRY_ADDR}" ] || [ -z "${VERSION}" ] || [ -z "${KERNEL}" ] || \ + [ -z "${OUTPUT}" ]; then + usage +fi + +# Create a default, fully populated DTS file +DATA="/dts-v1/; + +/ { + description = \"Linux kernel ${VERSION}\"; + #address-cells = <1>; + + images { + kernel@1 { + description = \"Linux Kernel ${VERSION}\"; + data = /incbin/(\"${KERNEL}\"); + type = \"kernel\"; + arch = \"${ARCH}\"; + os = \"linux\"; + compression = \"${COMPRESS}\"; + load = <${LOAD_ADDR}>; + entry = <${ENTRY_ADDR}>; + hash@1 { + algo = \"crc32\"; + }; + hash@2 { + algo = \"sha1\"; + }; + }; + + fdt@1 { /* start fdt */ + description = \"Flattened Device Tree blob\"; + data = /incbin/(\"${DTB}\"); + type = \"flat_dt\"; + arch = \"${ARCH}\"; + compression = \"none\"; + hash@1 { + algo = \"crc32\"; + }; + hash@2 { + algo = \"sha1\"; + }; + }; /* end fdt */ + }; + + configurations { + default = \"config@1\"; + config@1 { + description = \"Default Linux kernel\"; + kernel = \"kernel@1\"; + fdt = \"fdt@1\"; + }; + }; +};" + +# Conditionally strip fdt information out of tree +if [ -z "${DTB}" ]; then + DATA=`echo "$DATA" | sed '/start fdt/,/end fdt/d'` + DATA=`echo "$DATA" | sed '/fdt/d'` +fi + +# Write .its file to disk +echo "$DATA" > ${OUTPUT} diff --git a/target/linux/mpc83xx/image/Makefile b/target/linux/mpc83xx/image/Makefile index 1483786e8..ed0012899 100644 --- a/target/linux/mpc83xx/image/Makefile +++ b/target/linux/mpc83xx/image/Makefile @@ -1,5 +1,5 @@ # -# Copyright (C) 2009 OpenWrt.org +# Copyright (C) 2009-2010 OpenWrt.org # # This is free software, licensed under the GNU General Public License v2. # See /LICENSE for more information. @@ -22,10 +22,9 @@ endef define Image/Build/squashfs $(call prepare_generic_squashfs,$(KDIR)/root.squashfs) ( \ - dd if=$(LINUX_DIR)/arch/powerpc/boot/uImage bs=1920k conv=sync; \ - dd if=$(KDIR)/openwrt-canyonlands.dtb bs=128k conv=sync; \ + dd if=$(LINUX_DIR)/arch/powerpc/boot/uImage.fit.mpc8377_wlan bs=3072k conv=sync; \ dd if=$(KDIR)/root.$(1) bs=256k conv=sync; \ - ) > $(BIN_DIR)/openwrt-$(BOARD)-canyonlands-$(1).img + ) > $(BIN_DIR)/openwrt-$(BOARD)-mpc8377_wlan-$(1).img endef $(eval $(call BuildImage)) diff --git a/target/linux/mpc83xx/patches/001-rb600.patch b/target/linux/mpc83xx/patches/001-rb600.patch index 233723090..98db9e226 100644 --- a/target/linux/mpc83xx/patches/001-rb600.patch +++ b/target/linux/mpc83xx/patches/001-rb600.patch @@ -358,7 +358,7 @@ ;; --- a/arch/powerpc/kernel/Makefile +++ b/arch/powerpc/kernel/Makefile -@@ -97,9 +97,11 @@ obj-$(CONFIG_FUNCTION_GRAPH_TRACER) += f +@@ -104,9 +104,11 @@ obj32-$(CONFIG_PPC_PERF_CTRS) += mpc7450 obj-$(CONFIG_8XX_MINIMAL_FPEMU) += softemu8xx.o @@ -369,7 +369,7 @@ +endif obj-$(CONFIG_PPC64) += $(obj64-y) - + obj-$(CONFIG_PPC32) += $(obj32-y) --- a/arch/powerpc/platforms/83xx/Kconfig +++ b/arch/powerpc/platforms/83xx/Kconfig @@ -30,6 +30,15 @@ config MPC832x_RDB @@ -732,7 +732,7 @@ menu "CPU Frequency drivers" --- a/arch/powerpc/sysdev/Makefile +++ b/arch/powerpc/sysdev/Makefile -@@ -50,3 +50,5 @@ obj-$(CONFIG_UCODE_PATCH) += micropatch. +@@ -56,3 +56,5 @@ obj-$(CONFIG_PPC_MPC52xx) += mpc5xxx_clo ifeq ($(CONFIG_SUSPEND),y) obj-$(CONFIG_6xx) += 6xx-suspend.o endif @@ -966,7 +966,7 @@ +EXPORT_SYMBOL(localbus_unmap); --- a/drivers/ata/Kconfig +++ b/drivers/ata/Kconfig -@@ -734,5 +734,12 @@ config PATA_BF54X +@@ -751,5 +751,12 @@ config PATA_BF54X If unsure, say N. @@ -981,8 +981,8 @@ endif # ATA --- a/drivers/ata/Makefile +++ b/drivers/ata/Makefile -@@ -73,6 +73,7 @@ obj-$(CONFIG_PATA_OCTEON_CF) += pata_oct - obj-$(CONFIG_PATA_PLATFORM) += pata_platform.o +@@ -75,6 +75,7 @@ obj-$(CONFIG_PATA_PLATFORM) += pata_plat + obj-$(CONFIG_PATA_AT91) += pata_at91.o obj-$(CONFIG_PATA_OF_PLATFORM) += pata_of_platform.o obj-$(CONFIG_PATA_ICSIDE) += pata_icside.o +obj-$(CONFIG_PATA_RB_PPC) += pata_rbppc_cf.o @@ -1695,7 +1695,7 @@ +module_exit(rbppc_exit); --- a/drivers/mtd/nand/Kconfig +++ b/drivers/mtd/nand/Kconfig -@@ -380,6 +380,13 @@ config MTD_NAND_PLATFORM +@@ -386,6 +386,13 @@ config MTD_NAND_PLATFORM devices. You will need to provide platform-specific functions via platform_data. @@ -1711,7 +1711,7 @@ depends on MTD_NAND && USB --- a/drivers/mtd/nand/Makefile +++ b/drivers/mtd/nand/Makefile -@@ -30,6 +30,7 @@ obj-$(CONFIG_MTD_NAND_BASLER_EXCITE) += +@@ -31,6 +31,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 diff --git a/target/linux/mpc83xx/patches/002-mpc8377e-wlan_support.patch b/target/linux/mpc83xx/patches/002-mpc8377e-wlan_support.patch new file mode 100644 index 000000000..68634bf78 --- /dev/null +++ b/target/linux/mpc83xx/patches/002-mpc8377e-wlan_support.patch @@ -0,0 +1,524 @@ +From fda4bd9bac78efd2f9d566c52956d297bc03e8d9 Mon Sep 17 00:00:00 2001 +From: Anton Vorontsov +Date: Sat, 25 Jul 2009 01:42:17 +0400 +Subject: [PATCH] powerpc/83xx: Add support for MPC8377E-WLAN boards + +MPC8377E-WLAN are basically RDB boards except: + +- RAM extended to 512 MB; +- NAND flash removed, NOR flash extended to 64 MB; +- Vitesse VSC7385 5-port switch removed, RTL8211B PHY added; +- Power management MCU removed; +- PCI slot removed, another mini-PCI slot added (IRQ routing changed); +- USB3300 PHY's ID pin grounded, thus USB port is host-only. + +Signed-off-by: Anton Vorontsov +Signed-off-by: Kumar Gala +Signed-off-by: Benjamin Herrenschmidt +--- + arch/powerpc/boot/dts/mpc8377_wlan.dts | 464 +++++++++++++++++++++++++++++ + arch/powerpc/platforms/83xx/Kconfig | 4 +- + arch/powerpc/platforms/83xx/mpc837x_rdb.c | 5 +- + 3 files changed, 469 insertions(+), 4 deletions(-) + create mode 100644 arch/powerpc/boot/dts/mpc8377_wlan.dts + +--- /dev/null ++++ b/arch/powerpc/boot/dts/mpc8377_wlan.dts +@@ -0,0 +1,464 @@ ++/* ++ * MPC8377E WLAN Device Tree Source ++ * ++ * Copyright 2007-2009 Freescale Semiconductor Inc. ++ * Copyright 2009 MontaVista Software, Inc. ++ * ++ * 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. ++ */ ++ ++/dts-v1/; ++ ++/ { ++ compatible = "fsl,mpc8377wlan"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ aliases { ++ ethernet0 = &enet0; ++ ethernet1 = &enet1; ++ serial0 = &serial0; ++ serial1 = &serial1; ++ pci0 = &pci0; ++ pci1 = &pci1; ++ pci2 = &pci2; ++ }; ++ ++ cpus { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ PowerPC,8377@0 { ++ device_type = "cpu"; ++ reg = <0x0>; ++ d-cache-line-size = <32>; ++ i-cache-line-size = <32>; ++ d-cache-size = <32768>; ++ i-cache-size = <32768>; ++ timebase-frequency = <0>; ++ bus-frequency = <0>; ++ clock-frequency = <0>; ++ }; ++ }; ++ ++ memory { ++ device_type = "memory"; ++ reg = <0x00000000 0x20000000>; // 512MB at 0 ++ }; ++ ++ localbus@e0005000 { ++ #address-cells = <2>; ++ #size-cells = <1>; ++ compatible = "fsl,mpc8377-elbc", "fsl,elbc", "simple-bus"; ++ reg = <0xe0005000 0x1000>; ++ interrupts = <77 0x8>; ++ interrupt-parent = <&ipic>; ++ ranges = <0x0 0x0 0xfc000000 0x04000000>; ++ ++ flash@0,0 { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ compatible = "cfi-flash"; ++ reg = <0x0 0x0 0x4000000>; ++ bank-width = <2>; ++ device-width = <1>; ++ ++ partition@0 { ++ reg = <0 0x8000>; ++ label = "u-boot"; ++ read-only; ++ }; ++ ++ partition@a0000 { ++ reg = <0xa0000 0x300000>; ++ label = "kernel"; ++ }; ++ ++ partition@3a0000 { ++ reg = <0x3a0000 0x3c60000>; ++ label = "rootfs"; ++ }; ++ }; ++ }; ++ ++ immr@e0000000 { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ device_type = "soc"; ++ compatible = "simple-bus"; ++ ranges = <0x0 0xe0000000 0x00100000>; ++ reg = <0xe0000000 0x00000200>; ++ bus-frequency = <0>; ++ ++ wdt@200 { ++ device_type = "watchdog"; ++ compatible = "mpc83xx_wdt"; ++ reg = <0x200 0x100>; ++ }; ++ ++ gpio1: gpio-controller@c00 { ++ #gpio-cells = <2>; ++ compatible = "fsl,mpc8377-gpio", "fsl,mpc8349-gpio"; ++ reg = <0xc00 0x100>; ++ interrupts = <74 0x8>; ++ interrupt-parent = <&ipic>; ++ gpio-controller; ++ }; ++ ++ gpio2: gpio-controller@d00 { ++ #gpio-cells = <2>; ++ compatible = "fsl,mpc8377-gpio", "fsl,mpc8349-gpio"; ++ reg = <0xd00 0x100>; ++ interrupts = <75 0x8>; ++ interrupt-parent = <&ipic>; ++ gpio-controller; ++ }; ++ ++ sleep-nexus { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ compatible = "simple-bus"; ++ sleep = <&pmc 0x0c000000>; ++ ranges; ++ ++ i2c@3000 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ cell-index = <0>; ++ compatible = "fsl-i2c"; ++ reg = <0x3000 0x100>; ++ interrupts = <14 0x8>; ++ interrupt-parent = <&ipic>; ++ dfsrr; ++ ++ at24@50 { ++ compatible = "at24,24c256"; ++ reg = <0x50>; ++ }; ++ ++ rtc@68 { ++ compatible = "dallas,ds1339"; ++ reg = <0x68>; ++ }; ++ }; ++ ++ sdhci@2e000 { ++ compatible = "fsl,mpc8377-esdhc", "fsl,esdhc"; ++ reg = <0x2e000 0x1000>; ++ interrupts = <42 0x8>; ++ interrupt-parent = <&ipic>; ++ clock-frequency = <133333333>; ++ }; ++ }; ++ ++ i2c@3100 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ cell-index = <1>; ++ compatible = "fsl-i2c"; ++ reg = <0x3100 0x100>; ++ interrupts = <15 0x8>; ++ interrupt-parent = <&ipic>; ++ dfsrr; ++ }; ++ ++ spi@7000 { ++ cell-index = <0>; ++ compatible = "fsl,spi"; ++ reg = <0x7000 0x1000>; ++ interrupts = <16 0x8>; ++ interrupt-parent = <&ipic>; ++ mode = "cpu"; ++ }; ++ ++ dma@82a8 { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ compatible = "fsl,mpc8377-dma", "fsl,elo-dma"; ++ reg = <0x82a8 4>; ++ ranges = <0 0x8100 0x1a8>; ++ interrupt-parent = <&ipic>; ++ interrupts = <71 8>; ++ cell-index = <0>; ++ dma-channel@0 { ++ compatible = "fsl,mpc8377-dma-channel", "fsl,elo-dma-channel"; ++ reg = <0 0x80>; ++ cell-index = <0>; ++ interrupt-parent = <&ipic>; ++ interrupts = <71 8>; ++ }; ++ dma-channel@80 { ++ compatible = "fsl,mpc8377-dma-channel", "fsl,elo-dma-channel"; ++ reg = <0x80 0x80>; ++ cell-index = <1>; ++ interrupt-parent = <&ipic>; ++ interrupts = <71 8>; ++ }; ++ dma-channel@100 { ++ compatible = "fsl,mpc8377-dma-channel", "fsl,elo-dma-channel"; ++ reg = <0x100 0x80>; ++ cell-index = <2>; ++ interrupt-parent = <&ipic>; ++ interrupts = <71 8>; ++ }; ++ dma-channel@180 { ++ compatible = "fsl,mpc8377-dma-channel", "fsl,elo-dma-channel"; ++ reg = <0x180 0x28>; ++ cell-index = <3>; ++ interrupt-parent = <&ipic>; ++ interrupts = <71 8>; ++ }; ++ }; ++ ++ usb@23000 { ++ compatible = "fsl-usb2-dr"; ++ reg = <0x23000 0x1000>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ interrupt-parent = <&ipic>; ++ interrupts = <38 0x8>; ++ phy_type = "ulpi"; ++ sleep = <&pmc 0x00c00000>; ++ }; ++ ++ enet0: ethernet@24000 { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ cell-index = <0>; ++ device_type = "network"; ++ model = "eTSEC"; ++ compatible = "gianfar"; ++ reg = <0x24000 0x1000>; ++ ranges = <0x0 0x24000 0x1000>; ++ local-mac-address = [ 00 00 00 00 00 00 ]; ++ interrupts = <32 0x8 33 0x8 34 0x8>; ++ phy-connection-type = "mii"; ++ interrupt-parent = <&ipic>; ++ tbi-handle = <&tbi0>; ++ phy-handle = <&phy2>; ++ sleep = <&pmc 0xc0000000>; ++ fsl,magic-packet; ++ ++ mdio@520 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ compatible = "fsl,gianfar-mdio"; ++ reg = <0x520 0x20>; ++ ++ phy2: ethernet-phy@2 { ++ interrupt-parent = <&ipic>; ++ interrupts = <17 0x8>; ++ reg = <0x2>; ++ device_type = "ethernet-phy"; ++ }; ++ ++ phy3: ethernet-phy@3 { ++ interrupt-parent = <&ipic>; ++ interrupts = <18 0x8>; ++ reg = <0x3>; ++ device_type = "ethernet-phy"; ++ }; ++ ++ tbi0: tbi-phy@11 { ++ reg = <0x11>; ++ device_type = "tbi-phy"; ++ }; ++ }; ++ }; ++ ++ enet1: ethernet@25000 { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ cell-index = <1>; ++ device_type = "network"; ++ model = "eTSEC"; ++ compatible = "gianfar"; ++ reg = <0x25000 0x1000>; ++ ranges = <0x0 0x25000 0x1000>; ++ local-mac-address = [ 00 00 00 00 00 00 ]; ++ interrupts = <35 0x8 36 0x8 37 0x8>; ++ phy-connection-type = "mii"; ++ interrupt-parent = <&ipic>; ++ phy-handle = <&phy3>; ++ tbi-handle = <&tbi1>; ++ sleep = <&pmc 0x30000000>; ++ fsl,magic-packet; ++ ++ mdio@520 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ compatible = "fsl,gianfar-tbi"; ++ reg = <0x520 0x20>; ++ ++ tbi1: tbi-phy@11 { ++ reg = <0x11>; ++ device_type = "tbi-phy"; ++ }; ++ }; ++ }; ++ ++ serial0: serial@4500 { ++ cell-index = <0>; ++ device_type = "serial"; ++ compatible = "ns16550"; ++ reg = <0x4500 0x100>; ++ clock-frequency = <0>; ++ interrupts = <9 0x8>; ++ interrupt-parent = <&ipic>; ++ }; ++ ++ serial1: serial@4600 { ++ cell-index = <1>; ++ device_type = "serial"; ++ compatible = "ns16550"; ++ reg = <0x4600 0x100>; ++ clock-frequency = <0>; ++ interrupts = <10 0x8>; ++ interrupt-parent = <&ipic>; ++ }; ++ ++ crypto@30000 { ++ compatible = "fsl,sec3.0", "fsl,sec2.4", "fsl,sec2.2", ++ "fsl,sec2.1", "fsl,sec2.0"; ++ reg = <0x30000 0x10000>; ++ interrupts = <11 0x8>; ++ interrupt-parent = <&ipic>; ++ fsl,num-channels = <4>; ++ fsl,channel-fifo-len = <24>; ++ fsl,exec-units-mask = <0x9fe>; ++ fsl,descriptor-types-mask = <0x3ab0ebf>; ++ sleep = <&pmc 0x03000000>; ++ }; ++ ++ sata@18000 { ++ compatible = "fsl,mpc8377-sata", "fsl,pq-sata"; ++ reg = <0x18000 0x1000>; ++ interrupts = <44 0x8>; ++ interrupt-parent = <&ipic>; ++ sleep = <&pmc 0x000000c0>; ++ }; ++ ++ sata@19000 { ++ compatible = "fsl,mpc8377-sata", "fsl,pq-sata"; ++ reg = <0x19000 0x1000>; ++ interrupts = <45 0x8>; ++ interrupt-parent = <&ipic>; ++ sleep = <&pmc 0x00000030>; ++ }; ++ ++ /* IPIC ++ * interrupts cell = ++ * sense values match linux IORESOURCE_IRQ_* defines: ++ * sense == 8: Level, low assertion ++ * sense == 2: Edge, high-to-low change ++ */ ++ ipic: interrupt-controller@700 { ++ compatible = "fsl,ipic"; ++ interrupt-controller; ++ #address-cells = <0>; ++ #interrupt-cells = <2>; ++ reg = <0x700 0x100>; ++ }; ++ ++ pmc: power@b00 { ++ compatible = "fsl,mpc8377-pmc", "fsl,mpc8349-pmc"; ++ reg = <0xb00 0x100 0xa00 0x100>; ++ interrupts = <80 0x8>; ++ interrupt-parent = <&ipic>; ++ }; ++ }; ++ ++ pci0: pci@e0008500 { ++ interrupt-map-mask = <0xf800 0 0 7>; ++ interrupt-map = < ++ /* IRQ5 = 21 = 0x15, IRQ6 = 0x16, IRQ7 = 23 = 0x17 */ ++ ++ /* IDSEL AD14 IRQ6 inta */ ++ 0x7000 0x0 0x0 0x1 &ipic 22 0x8 ++ ++ /* IDSEL AD15 IRQ5 inta */ ++ 0x7800 0x0 0x0 0x1 &ipic 21 0x8>; ++ interrupt-parent = <&ipic>; ++ interrupts = <66 0x8>; ++ bus-range = <0 0>; ++ ranges = <0x02000000 0x0 0x90000000 0x90000000 0x0 0x10000000 ++ 0x42000000 0x0 0x80000000 0x80000000 0x0 0x10000000 ++ 0x01000000 0x0 0x00000000 0xe0300000 0x0 0x00100000>; ++ sleep = <&pmc 0x00010000>; ++ clock-frequency = <66666666>; ++ #interrupt-cells = <1>; ++ #size-cells = <2>; ++ #address-cells = <3>; ++ reg = <0xe0008500 0x100 /* internal registers */ ++ 0xe0008300 0x8>; /* config space access registers */ ++ compatible = "fsl,mpc8349-pci"; ++ device_type = "pci"; ++ }; ++ ++ pci1: pcie@e0009000 { ++ #address-cells = <3>; ++ #size-cells = <2>; ++ #interrupt-cells = <1>; ++ device_type = "pci"; ++ compatible = "fsl,mpc8377-pcie", "fsl,mpc8314-pcie"; ++ reg = <0xe0009000 0x00001000>; ++ ranges = <0x02000000 0 0xa8000000 0xa8000000 0 0x10000000 ++ 0x01000000 0 0x00000000 0xb8000000 0 0x00800000>; ++ bus-range = <0 255>; ++ interrupt-map-mask = <0xf800 0 0 7>; ++ interrupt-map = <0 0 0 1 &ipic 1 8 ++ 0 0 0 2 &ipic 1 8 ++ 0 0 0 3 &ipic 1 8 ++ 0 0 0 4 &ipic 1 8>; ++ sleep = <&pmc 0x00300000>; ++ clock-frequency = <0>; ++ ++ pcie@0 { ++ #address-cells = <3>; ++ #size-cells = <2>; ++ device_type = "pci"; ++ reg = <0 0 0 0 0>; ++ ranges = <0x02000000 0 0xa8000000 ++ 0x02000000 0 0xa8000000 ++ 0 0x10000000 ++ 0x01000000 0 0x00000000 ++ 0x01000000 0 0x00000000 ++ 0 0x00800000>; ++ }; ++ }; ++ ++ pci2: pcie@e000a000 { ++ #address-cells = <3>; ++ #size-cells = <2>; ++ #interrupt-cells = <1>; ++ device_type = "pci"; ++ compatible = "fsl,mpc8377-pcie", "fsl,mpc8314-pcie"; ++ reg = <0xe000a000 0x00001000>; ++ ranges = <0x02000000 0 0xc8000000 0xc8000000 0 0x10000000 ++ 0x01000000 0 0x00000000 0xd8000000 0 0x00800000>; ++ bus-range = <0 255>; ++ interrupt-map-mask = <0xf800 0 0 7>; ++ interrupt-map = <0 0 0 1 &ipic 2 8 ++ 0 0 0 2 &ipic 2 8 ++ 0 0 0 3 &ipic 2 8 ++ 0 0 0 4 &ipic 2 8>; ++ sleep = <&pmc 0x000c0000>; ++ clock-frequency = <0>; ++ ++ pcie@0 { ++ #address-cells = <3>; ++ #size-cells = <2>; ++ device_type = "pci"; ++ reg = <0 0 0 0 0>; ++ ranges = <0x02000000 0 0xc8000000 ++ 0x02000000 0 0xc8000000 ++ 0 0x10000000 ++ 0x01000000 0 0x00000000 ++ 0x01000000 0 0x00000000 ++ 0 0x00800000>; ++ }; ++ }; ++}; +--- a/arch/powerpc/platforms/83xx/Kconfig ++++ b/arch/powerpc/platforms/83xx/Kconfig +@@ -84,11 +84,11 @@ config MPC837x_MDS + This option enables support for the MPC837x MDS Processor Board. + + config MPC837x_RDB +- bool "Freescale MPC837x RDB" ++ bool "Freescale MPC837x RDB/WLAN" + select DEFAULT_UIMAGE + select PPC_MPC837x + help +- This option enables support for the MPC837x RDB Board. ++ This option enables support for the MPC837x RDB and WLAN Boards. + + config SBC834x + bool "Wind River SBC834x" +--- a/arch/powerpc/platforms/83xx/mpc837x_rdb.c ++++ b/arch/powerpc/platforms/83xx/mpc837x_rdb.c +@@ -86,11 +86,12 @@ static int __init mpc837x_rdb_probe(void + + return of_flat_dt_is_compatible(root, "fsl,mpc8377rdb") || + of_flat_dt_is_compatible(root, "fsl,mpc8378rdb") || +- of_flat_dt_is_compatible(root, "fsl,mpc8379rdb"); ++ of_flat_dt_is_compatible(root, "fsl,mpc8379rdb") || ++ of_flat_dt_is_compatible(root, "fsl,mpc8377wlan"); + } + + define_machine(mpc837x_rdb) { +- .name = "MPC837x RDB", ++ .name = "MPC837x RDB/WLAN", + .probe = mpc837x_rdb_probe, + .setup_arch = mpc837x_rdb_setup_arch, + .init_IRQ = mpc837x_rdb_init_IRQ, diff --git a/target/linux/mpc83xx/patches/003-esdhc_wp-inverted_property.patch b/target/linux/mpc83xx/patches/003-esdhc_wp-inverted_property.patch new file mode 100644 index 000000000..50c199a4d --- /dev/null +++ b/target/linux/mpc83xx/patches/003-esdhc_wp-inverted_property.patch @@ -0,0 +1,113 @@ +From 50dfe70fe9e216cf356830194630f9a39e498d76 Mon Sep 17 00:00:00 2001 +From: Anton Vorontsov +Date: Tue, 22 Sep 2009 16:45:14 -0700 +Subject: [PATCH] powerpc: introduce and document sdhci,wp-inverted property for eSDHC + +eSDHC block in MPC837x SOCs reports inverted write-protect state, soon +sdhci-of driver will look for sdhci,wp-inverted properties to decide +whether apply a specific quirk. + +So, document the property and add it to device tree source files. + +Signed-off-by: Anton Vorontsov +Cc: Pierre Ossman +Cc: Kumar Gala +Cc: David Vrabel +Cc: Ben Dooks +Cc: Sascha Hauer +Cc: Benjamin Herrenschmidt +Cc: +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +--- + Documentation/powerpc/dts-bindings/fsl/esdhc.txt | 2 ++ + arch/powerpc/boot/dts/mpc8377_mds.dts | 1 + + arch/powerpc/boot/dts/mpc8377_rdb.dts | 1 + + arch/powerpc/boot/dts/mpc8377_wlan.dts | 1 + + arch/powerpc/boot/dts/mpc8378_mds.dts | 1 + + arch/powerpc/boot/dts/mpc8378_rdb.dts | 1 + + arch/powerpc/boot/dts/mpc8379_mds.dts | 1 + + arch/powerpc/boot/dts/mpc8379_rdb.dts | 1 + + 8 files changed, 9 insertions(+), 0 deletions(-) + +--- a/Documentation/powerpc/dts-bindings/fsl/esdhc.txt ++++ b/Documentation/powerpc/dts-bindings/fsl/esdhc.txt +@@ -10,6 +10,8 @@ Required properties: + - interrupts : should contain eSDHC interrupt. + - interrupt-parent : interrupt source phandle. + - clock-frequency : specifies eSDHC base clock frequency. ++ - sdhci,wp-inverted : (optional) specifies that eSDHC controller ++ reports inverted write-protect state; + - sdhci,1-bit-only : (optional) specifies that a controller can + only handle 1-bit data transfers. + +--- a/arch/powerpc/boot/dts/mpc8377_mds.dts ++++ b/arch/powerpc/boot/dts/mpc8377_mds.dts +@@ -159,6 +159,7 @@ + reg = <0x2e000 0x1000>; + interrupts = <42 0x8>; + interrupt-parent = <&ipic>; ++ sdhci,wp-inverted; + /* Filled in by U-Boot */ + clock-frequency = <0>; + }; +--- a/arch/powerpc/boot/dts/mpc8377_rdb.dts ++++ b/arch/powerpc/boot/dts/mpc8377_rdb.dts +@@ -173,6 +173,7 @@ + reg = <0x2e000 0x1000>; + interrupts = <42 0x8>; + interrupt-parent = <&ipic>; ++ sdhci,wp-inverted; + /* Filled in by U-Boot */ + clock-frequency = <0>; + }; +--- a/arch/powerpc/boot/dts/mpc8377_wlan.dts ++++ b/arch/powerpc/boot/dts/mpc8377_wlan.dts +@@ -150,6 +150,7 @@ + reg = <0x2e000 0x1000>; + interrupts = <42 0x8>; + interrupt-parent = <&ipic>; ++ sdhci,wp-inverted; + clock-frequency = <133333333>; + }; + }; +--- a/arch/powerpc/boot/dts/mpc8378_mds.dts ++++ b/arch/powerpc/boot/dts/mpc8378_mds.dts +@@ -159,6 +159,7 @@ + reg = <0x2e000 0x1000>; + interrupts = <42 0x8>; + interrupt-parent = <&ipic>; ++ sdhci,wp-inverted; + /* Filled in by U-Boot */ + clock-frequency = <0>; + }; +--- a/arch/powerpc/boot/dts/mpc8378_rdb.dts ++++ b/arch/powerpc/boot/dts/mpc8378_rdb.dts +@@ -173,6 +173,7 @@ + reg = <0x2e000 0x1000>; + interrupts = <42 0x8>; + interrupt-parent = <&ipic>; ++ sdhci,wp-inverted; + /* Filled in by U-Boot */ + clock-frequency = <0>; + }; +--- a/arch/powerpc/boot/dts/mpc8379_mds.dts ++++ b/arch/powerpc/boot/dts/mpc8379_mds.dts +@@ -157,6 +157,7 @@ + reg = <0x2e000 0x1000>; + interrupts = <42 0x8>; + interrupt-parent = <&ipic>; ++ sdhci,wp-inverted; + /* Filled in by U-Boot */ + clock-frequency = <0>; + }; +--- a/arch/powerpc/boot/dts/mpc8379_rdb.dts ++++ b/arch/powerpc/boot/dts/mpc8379_rdb.dts +@@ -171,6 +171,7 @@ + reg = <0x2e000 0x1000>; + interrupts = <42 0x8>; + interrupt-parent = <&ipic>; ++ sdhci,wp-inverted; + /* Filled in by U-Boot */ + clock-frequency = <0>; + }; diff --git a/target/linux/mpc83xx/patches/004-mpc8377e-wlan_u-boot_size_fix.patch b/target/linux/mpc83xx/patches/004-mpc8377e-wlan_u-boot_size_fix.patch new file mode 100644 index 000000000..8cf95f611 --- /dev/null +++ b/target/linux/mpc83xx/patches/004-mpc8377e-wlan_u-boot_size_fix.patch @@ -0,0 +1,24 @@ +From 850f785a1f8c8448db4d70983595b2b088cf60b7 Mon Sep 17 00:00:00 2001 +From: Anton Vorontsov +Date: Fri, 16 Oct 2009 20:47:22 +0400 +Subject: [PATCH] powerpc/83xx: Fix u-boot partion size for MPC8377E-WLAN boards + +u-boot partition size should be 0x80000 (512 KB), not 0x8000 (32 KB). + +Signed-off-by: Anton Vorontsov +Signed-off-by: Kumar Gala +--- + arch/powerpc/boot/dts/mpc8377_wlan.dts | 2 +- + 1 files changed, 1 insertions(+), 1 deletions(-) + +--- a/arch/powerpc/boot/dts/mpc8377_wlan.dts ++++ b/arch/powerpc/boot/dts/mpc8377_wlan.dts +@@ -67,7 +67,7 @@ + device-width = <1>; + + partition@0 { +- reg = <0 0x8000>; ++ reg = <0 0x80000>; + label = "u-boot"; + read-only; + }; diff --git a/target/linux/mpc83xx/patches/005-powerpc_mkuboot.patch b/target/linux/mpc83xx/patches/005-powerpc_mkuboot.patch new file mode 100644 index 000000000..8e200b1a6 --- /dev/null +++ b/target/linux/mpc83xx/patches/005-powerpc_mkuboot.patch @@ -0,0 +1,30 @@ +--- a/arch/powerpc/boot/wrapper ++++ b/arch/powerpc/boot/wrapper +@@ -43,6 +43,9 @@ gzip=.gz + # cross-compilation prefix + CROSS= + ++# mkimage wrapper script ++MKIMAGE=$srctree/scripts/mkuboot.sh ++ + # directory for object and other files used by this script + object=arch/powerpc/boot + objbin=$object +@@ -262,7 +265,7 @@ membase=`${CROSS}objdump -p "$kernel" | + case "$platform" in + uboot) + rm -f "$ofile" +- mkimage -A ppc -O linux -T kernel -C gzip -a $membase -e $membase \ ++ ${MKIMAGE} -A ppc -O linux -T kernel -C gzip -a $membase -e $membase \ + $uboot_version -d "$vmz" "$ofile" + if [ -z "$cacheit" ]; then + rm -f "$vmz" +@@ -322,7 +325,7 @@ coff) + ;; + cuboot*) + gzip -f -9 "$ofile" +- mkimage -A ppc -O linux -T kernel -C gzip -a "$base" -e "$entry" \ ++ ${MKIMAGE} -A ppc -O linux -T kernel -C gzip -a "$base" -e "$entry" \ + $uboot_version -d "$ofile".gz "$ofile" + ;; + treeboot*) diff --git a/target/linux/mpc83xx/patches/006-powerpc_create_fit_uImages.patch b/target/linux/mpc83xx/patches/006-powerpc_create_fit_uImages.patch new file mode 100644 index 000000000..d553c675d --- /dev/null +++ b/target/linux/mpc83xx/patches/006-powerpc_create_fit_uImages.patch @@ -0,0 +1,94 @@ +--- a/arch/powerpc/Makefile ++++ b/arch/powerpc/Makefile +@@ -157,7 +157,8 @@ drivers-$(CONFIG_OPROFILE) += arch/power + # Default to zImage, override when needed + all: zImage + +-BOOT_TARGETS = zImage zImage.initrd uImage zImage% dtbImage% treeImage.% cuImage.% simpleImage.% ++BOOT_TARGETS = zImage zImage.initrd uImage uImage.fit.% zImage% dtbImage% \ ++ treeImage.% cuImage.% simpleImage.% + + PHONY += $(BOOT_TARGETS) + +@@ -173,6 +174,7 @@ define archhelp + @echo '* zImage - Build default images selected by kernel config' + @echo ' zImage.* - Compressed kernel image (arch/$(ARCH)/boot/zImage.*)' + @echo ' uImage - U-Boot native image format' ++ @echo ' uImage.fit.
- U-Boot Flattened Image Tree image format' + @echo ' cuImage.
- Backwards compatible U-Boot image for older' + @echo ' versions which do not support device trees' + @echo ' dtbImage.
- zImage with an embedded device tree blob' +--- a/arch/powerpc/boot/.gitignore ++++ b/arch/powerpc/boot/.gitignore +@@ -19,6 +19,7 @@ kernel-vmlinux.strip.c + kernel-vmlinux.strip.gz + mktree + uImage ++uImage.fit.* + cuImage.* + dtbImage.* + treeImage.* +--- a/arch/powerpc/boot/Makefile ++++ b/arch/powerpc/boot/Makefile +@@ -306,6 +306,9 @@ $(obj)/zImage.iseries: vmlinux + $(obj)/uImage: vmlinux $(wrapperbits) + $(call if_changed,wrap,uboot) + ++$(obj)/uImage.fit.%: vmlinux $(obj)/%.dtb $(wrapperbits) ++ $(call if_changed,wrap,uboot.fit,,$(obj)/$*.dtb) ++ + $(obj)/cuImage.initrd.%: vmlinux $(obj)/%.dtb $(wrapperbits) + $(call if_changed,wrap,cuboot-$*,,$(obj)/$*.dtb,$(obj)/ramdisk.image.gz) + +@@ -345,7 +348,7 @@ install: $(CONFIGURE) $(addprefix $(obj) + + # anything not in $(targets) + clean-files += $(image-) $(initrd-) cuImage.* dtbImage.* treeImage.* \ +- zImage zImage.initrd zImage.chrp zImage.coff zImage.holly \ ++ uImage.* zImage zImage.initrd zImage.chrp zImage.coff zImage.holly \ + zImage.iseries zImage.miboot zImage.pmac zImage.pseries \ + simpleImage.* otheros.bld *.dtb + +--- a/arch/powerpc/boot/wrapper ++++ b/arch/powerpc/boot/wrapper +@@ -46,6 +46,9 @@ CROSS= + # mkimage wrapper script + MKIMAGE=$srctree/scripts/mkuboot.sh + ++# script to generate an .its file for uImage.fit.* images ++MKITS=$srctree/scripts/mkits.sh ++ + # directory for object and other files used by this script + object=arch/powerpc/boot + objbin=$object +@@ -156,7 +159,7 @@ coff) + lds=$object/zImage.coff.lds + link_address='0x500000' + ;; +-miboot|uboot) ++miboot|uboot|uboot.fit) + # miboot and U-boot want just the bare bits, not an ELF binary + ext=bin + objflags="-O binary" +@@ -272,6 +275,21 @@ uboot) + fi + exit 0 + ;; ++uboot.fit) ++ rm -f "$ofile" ++ ${MKITS} -A ppc -C gzip -a $membase -e $membase -v $version \ ++ -d "$srctree/$dtb" -k "$srctree/$vmz" -o "$object/uImage.its" ++ ++ # mkimage calls dtc for FIT images so use kernel dtc if necessary ++ export PATH=$PATH:$srctree/scripts/dtc ++ ++ ${MKIMAGE} -f "$object/uImage.its" "$ofile" ++ rm "$object/uImage.its" ++ if [ -z "$cacheit" ]; then ++ rm -f "$vmz" ++ fi ++ exit 0 ++ ;; + esac + + addsec() { diff --git a/target/linux/octeon/Makefile b/target/linux/octeon/Makefile index b5b2e35e9..ca4b9fc0d 100644 --- a/target/linux/octeon/Makefile +++ b/target/linux/octeon/Makefile @@ -12,7 +12,7 @@ BOARDNAME:=Cavium Networks Octeon FEATURES:=squashfs jffs2 pci usb CFLAGS:=-Os -pipe -mtune=octeon -funit-at-a-time -LINUX_VERSION:=2.6.30.9 +LINUX_VERSION:=2.6.30.10 include $(INCLUDE_DIR)/target.mk diff --git a/target/linux/olpc/Makefile b/target/linux/olpc/Makefile deleted file mode 100644 index fb535c976..000000000 --- a/target/linux/olpc/Makefile +++ /dev/null @@ -1,23 +0,0 @@ -# -# Copyright (C) 2006-2009 OpenWrt.org -# -# This is free software, licensed under the GNU General Public License v2. -# See /LICENSE for more information. -# -include $(TOPDIR)/rules.mk - -ARCH=i386 -BOARD:=olpc -BOARDNAME:=OLPC XO-1 -FEATURES:=squashfs ext2 - -LINUX_VERSION:=2.6.30.9 - -include $(INCLUDE_DIR)/target.mk -DEFAULT_PACKAGES += kmod-natsemi kmod-ne2k-pci kmod-libertas - -$(eval $(call Target,generic)) -$(eval $(call BuildTarget)) -$(eval $(call $(if $(CONFIG_TARGET_ROOTFS_ISO),RequireCommand,Ignore),mkisofs, \ - Please install mkisofs. \ -)) diff --git a/target/linux/olpc/base-files/etc/X11/xorg.conf b/target/linux/olpc/base-files/etc/X11/xorg.conf deleted file mode 100644 index d98a8f87a..000000000 --- a/target/linux/olpc/base-files/etc/X11/xorg.conf +++ /dev/null @@ -1,71 +0,0 @@ -# xorg configuration - -Section "ServerLayout" - Identifier "Default Layout" - Screen 0 "Screen0" 0 0 - InputDevice "Mouse0" "CorePointer" - InputDevice "Keyboard0" "CoreKeyboard" -EndSection - -Section "Files" - FontPath "/usr/lib/X11/fonts/misc" -EndSection - -Section "Module" - Load "dbe" - Load "extmod" - Load "fbdevhw" -# Load "glx" - Load "record" - Load "freetype" - Load "type1" -EndSection - -Section "InputDevice" - Identifier "Keyboard0" - Driver "keyboard" - Option "XkbModel" "pc105" - Option "XkbLayout" "us" -EndSection - -Section "InputDevice" - Identifier "Mouse0" - Driver "mouse" - Option "Protocol" "PS/2" - Option "Device" "/dev/psaux" - Option "ZAxisMapping" "4 5" - Option "Emulate3Buttons" "yes" -EndSection - -Section "Monitor" - Identifier "Monitor0" - VendorName "Monitor Vendor" - ModelName "OWRT" - Option "dpms" -EndSection - -Section "Device" - Identifier "FBDev" - Driver "fbdev" - #Option "shadowfb" "off" - VideoRam 4096 -EndSection - -Section "Screen" - Identifier "Screen0" - Device "FBDev" - Monitor "Monitor0" - DefaultDepth 16 - - SubSection "Display" - Depth 16 - Modes "1200x900-75" - EndSubsection - -EndSection - -Section "DRI" - Group 0 - Mode 0666 -EndSection - diff --git a/target/linux/olpc/base-files/etc/config/network b/target/linux/olpc/base-files/etc/config/network deleted file mode 100644 index faa8f0e78..000000000 --- a/target/linux/olpc/base-files/etc/config/network +++ /dev/null @@ -1,11 +0,0 @@ -# Copyright (C) 2006 OpenWrt.org - -config interface loopback - option ifname lo - option proto static - option ipaddr 127.0.0.1 - option netmask 255.0.0.0 - -config interface wlan - option ifname eth0 - option proto dhcp diff --git a/target/linux/olpc/base-files/etc/preinit.arch b/target/linux/olpc/base-files/etc/preinit.arch deleted file mode 100644 index f29f0d448..000000000 --- a/target/linux/olpc/base-files/etc/preinit.arch +++ /dev/null @@ -1,2 +0,0 @@ -mount -t proc none /proc -grep 'failsafe=' /proc/cmdline && export FAILSAFE=true diff --git a/target/linux/olpc/base-files/lib/upgrade/platform.sh b/target/linux/olpc/base-files/lib/upgrade/platform.sh deleted file mode 100644 index ffd0b93ab..000000000 --- a/target/linux/olpc/base-files/lib/upgrade/platform.sh +++ /dev/null @@ -1,27 +0,0 @@ -platform_check_image() { - [ "$ARGC" -gt 1 ] && return 1 - - case "$(get_magic_word "$1")" in - 48eb) return 0;; - *) - echo "Invalid image type" - return 1 - ;; - esac -} - -platform_do_upgrade() { - get_image "$1" > /dev/hda - sync -} - -x86_prepare_ext2() { - # if we're running from ext2, we need to make sure that we have a mtd - # partition that points to the active rootfs partition. - # however this only matters if we actually need to preserve the config files - [ "$SAVE_CONFIG" -eq 1 ] && return 0 - grep rootfs /proc/mtd >/dev/null || { - echo /dev/hda2,65536,rootfs > /sys/module/block2mtd/parameters/block2mtd - } -} -append sysupgrade_pre_upgrade x86_prepare_ext2 diff --git a/target/linux/olpc/config-2.6.30 b/target/linux/olpc/config-2.6.30 deleted file mode 100644 index 808d8ee7b..000000000 --- a/target/linux/olpc/config-2.6.30 +++ /dev/null @@ -1,522 +0,0 @@ -CONFIG_4KSTACKS=y -# CONFIG_64BIT is not set -CONFIG_ACPI_AC=y -# CONFIG_ACPI_ASUS is not set -CONFIG_ACPI_BATTERY=y -CONFIG_ACPI_BLACKLIST_YEAR=0 -CONFIG_ACPI_BUTTON=y -# CONFIG_ACPI_CONTAINER is not set -# CONFIG_ACPI_CUSTOM_DSDT is not set -# CONFIG_ACPI_DEBUG is not set -# CONFIG_ACPI_DOCK is not set -CONFIG_ACPI_FAN=y -# CONFIG_ACPI_PCI_SLOT is not set -CONFIG_ACPI_PROCESSOR=y -CONFIG_ACPI_PROC_EVENT=y -# CONFIG_ACPI_PROCFS is not set -CONFIG_ACPI_PROCFS_POWER=y -# CONFIG_ACPI_SBS is not set -CONFIG_ACPI_SLEEP=y -CONFIG_ACPI_SYSFS_POWER=y -CONFIG_ACPI_THERMAL=y -# CONFIG_ACPI_TOSHIBA is not set -# CONFIG_ACPI_WMI is not set -CONFIG_ACPI=y -# CONFIG_AGP is not set -# CONFIG_APM is not set -CONFIG_ARCH_DEFCONFIG="arch/x86/configs/i386_defconfig" -CONFIG_ARCH_HAS_CACHE_LINE_SIZE=y -CONFIG_ARCH_HAS_CPU_IDLE_WAIT=y -CONFIG_ARCH_HAS_CPU_RELAX=y -CONFIG_ARCH_HAS_DEFAULT_IDLE=y -CONFIG_ARCH_HIBERNATION_POSSIBLE=y -CONFIG_ARCH_MAY_HAVE_PC_FDC=y -# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set -CONFIG_ARCH_POPULATES_NODE_MAP=y -CONFIG_ARCH_SELECT_MEMORY_MODEL=y -CONFIG_ARCH_SPARSEMEM_ENABLE=y -CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y -CONFIG_ARCH_SUPPORTS_MSI=y -CONFIG_ARCH_SUPPORTS_OPTIMIZED_INLINING=y -CONFIG_ARCH_SUSPEND_POSSIBLE=y -CONFIG_ARCH_WANT_FRAME_POINTERS=y -CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y -# CONFIG_ASUS_LAPTOP is not set -# CONFIG_AUDIT_ARCH is not set -CONFIG_BACKLIGHT_CLASS_DEVICE=y -CONFIG_BACKLIGHT_GENERIC=y -CONFIG_BACKLIGHT_LCD_SUPPORT=y -# CONFIG_BACKLIGHT_MBP_NVIDIA is not set -# CONFIG_BACKLIGHT_PROGEAR is not set -# CONFIG_BACKLIGHT_SAHARA is not set -# CONFIG_BACKTRACE_SELF_TEST is not set -CONFIG_BATTERY_OLPC=y -CONFIG_BINARY_PRINTF=y -CONFIG_BINFMT_MISC=y -CONFIG_BITREVERSE=y -# CONFIG_BLK_DEV is not set -CONFIG_BLK_DEV_SD=y -CONFIG_BLK_DEV_SR_VENDOR=y -CONFIG_BLK_DEV_SR=y -# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set -CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0 -# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set -CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0 -# CONFIG_BOOT_PRINTK_DELAY is not set -CONFIG_BOUNCE=y -CONFIG_CAN_PM_TRACE=y -# CONFIG_CC_STACKPROTECTOR is not set -CONFIG_CHR_DEV_SG=y -CONFIG_CLOCKSOURCE_WATCHDOG=y -# CONFIG_CMDLINE_BOOL is not set -# CONFIG_COMPAL_LAPTOP is not set -CONFIG_COMPAT_VDSO=y -CONFIG_CONSOLE_TRANSLATIONS=y -# CONFIG_CPA_DEBUG is not set -# CONFIG_CPU_FREQ_DEBUG is not set -# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set -# CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND is not set -CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y -# CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE is not set -# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set -# CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set -# CONFIG_CPU_FREQ_GOV_ONDEMAND is not set -CONFIG_CPU_FREQ_GOV_PERFORMANCE=y -# CONFIG_CPU_FREQ_GOV_POWERSAVE is not set -# CONFIG_CPU_FREQ_GOV_USERSPACE is not set -# CONFIG_CPU_FREQ_STAT_DETAILS is not set -CONFIG_CPU_FREQ_STAT=y -CONFIG_CPU_FREQ_TABLE=y -CONFIG_CPU_FREQ=y -CONFIG_CPU_IDLE_GOV_LADDER=y -CONFIG_CPU_IDLE_GOV_MENU=y -CONFIG_CPU_IDLE=y -CONFIG_CPU_SUP_AMD=y -# CONFIG_CPU_SUP_CENTAUR is not set -# CONFIG_CPU_SUP_CYRIX_32 is not set -# CONFIG_CPU_SUP_INTEL is not set -# CONFIG_CPU_SUP_TRANSMETA_32 is not set -# CONFIG_CPU_SUP_UMC_32 is not set -CONFIG_CRYPTO_AEAD2=y -CONFIG_CRYPTO_BLKCIPHER2=y -CONFIG_CRYPTO_HASH2=y -CONFIG_CRYPTO_MANAGER2=y -CONFIG_CRYPTO_RNG2=y -CONFIG_CRYPTO_WORKQUEUE=y -# CONFIG_CS5535_GPIO is not set -# CONFIG_DCDBAS is not set -# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set -# CONFIG_DEBUG_BOOT_PARAMS is not set -# CONFIG_DEBUG_DEVRES is not set -# CONFIG_DEBUG_DRIVER is not set -# CONFIG_DEBUG_INFO is not set -CONFIG_DEBUG_KERNEL=y -# CONFIG_DEBUG_KOBJECT is not set -# CONFIG_DEBUG_LIST is not set -# CONFIG_DEBUG_LOCK_ALLOC is not set -# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set -# CONFIG_DEBUG_MUTEXES is not set -# CONFIG_DEBUG_NOTIFIERS is not set -# CONFIG_DEBUG_NX_TEST is not set -# CONFIG_DEBUG_OBJECTS is not set -# CONFIG_DEBUG_PAGEALLOC is not set -# CONFIG_DEBUG_RODATA is not set -# CONFIG_DEBUG_RT_MUTEXES is not set -# CONFIG_DEBUG_SG is not set -# CONFIG_DEBUG_SHIRQ is not set -# CONFIG_DEBUG_SLAB is not set -# CONFIG_DEBUG_SPINLOCK is not set -# CONFIG_DEBUG_SPINLOCK_SLEEP is not set -# CONFIG_DEBUG_STACKOVERFLOW is not set -# CONFIG_DEBUG_STACK_USAGE is not set -# CONFIG_DEBUG_VIRTUAL is not set -# CONFIG_DEBUG_VM is not set -# CONFIG_DEBUG_WRITECOUNT is not set -CONFIG_DECOMPRESS_LZMA=y -CONFIG_DEFAULT_IO_DELAY_TYPE=0 -# CONFIG_DELL_RBU is not set -CONFIG_DETECT_HUNG_TASK=y -CONFIG_DETECT_SOFTLOCKUP=y -CONFIG_DEVPORT=y -CONFIG_DISPLAY_SUPPORT=y -# CONFIG_DMA_API_DEBUG is not set -CONFIG_DMIID=y -CONFIG_DMI=y -CONFIG_DOUBLEFAULT=y -CONFIG_DUMMY_CONSOLE=y -# CONFIG_EARLY_PRINTK_DBGP is not set -CONFIG_EARLY_PRINTK=y -# CONFIG_EDAC is not set -# CONFIG_EDD is not set -# CONFIG_EEEPC_LAPTOP is not set -# CONFIG_EFI is not set -CONFIG_ELF_CORE=y -CONFIG_EXT2_FS=y -CONFIG_FAST_CMPXCHG_LOCAL=y -# CONFIG_FAULT_INJECTION is not set -CONFIG_FB_CFB_COPYAREA=y -CONFIG_FB_CFB_FILLRECT=y -CONFIG_FB_CFB_IMAGEBLIT=y -# CONFIG_FB_GEODE_GX1 is not set -# CONFIG_FB_GEODE_GX is not set -CONFIG_FB_GEODE_LX=y -CONFIG_FB_GEODE=y -CONFIG_FB=y -# CONFIG_FCOE_FNIC is not set -# CONFIG_FIRMWARE_EDID is not set -# CONFIG_FIRMWARE_MEMMAP is not set -CONFIG_FIX_EARLYCON_MEM=y -CONFIG_FONT_8x16=y -CONFIG_FONT_8x8=y -# CONFIG_FONTS is not set -CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y -CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y -CONFIG_FRAMEBUFFER_CONSOLE=y -# CONFIG_FRAME_POINTER is not set -CONFIG_FREEZER=y -# CONFIG_FTRACE_STARTUP_TEST is not set -# CONFIG_FTRACE_SYSCALLS is not set -# CONFIG_FUJITSU_LAPTOP is not set -CONFIG_GENERIC_BUG=y -CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y -CONFIG_GENERIC_CLOCKEVENTS_BUILD=y -CONFIG_GENERIC_CLOCKEVENTS=y -CONFIG_GENERIC_CMOS_UPDATE=y -# CONFIG_GENERIC_CPU is not set -CONFIG_GENERIC_FIND_FIRST_BIT=y -CONFIG_GENERIC_FIND_LAST_BIT=y -CONFIG_GENERIC_FIND_NEXT_BIT=y -CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y -CONFIG_GENERIC_IOMAP=y -CONFIG_GENERIC_ISA_DMA=y -# CONFIG_GENERIC_TIME_VSYSCALL is not set -CONFIG_GEODE_MFGPT_TIMER=y -# CONFIG_HAMRADIO is not set -# CONFIG_HANGCHECK_TIMER is not set -CONFIG_HAS_DMA=y -CONFIG_HAS_IOMEM=y -CONFIG_HAS_IOPORT=y -CONFIG_HAVE_AOUT=y -CONFIG_HAVE_ARCH_KGDB=y -CONFIG_HAVE_ARCH_TRACEHOOK=y -CONFIG_HAVE_ATOMIC_IOMAP=y -# CONFIG_HAVE_CPUMASK_OF_CPU_MAP is not set -CONFIG_HAVE_DMA_API_DEBUG=y -CONFIG_HAVE_DYNAMIC_FTRACE=y -CONFIG_HAVE_DYNAMIC_PER_CPU_AREA=y -CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y -CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y -CONFIG_HAVE_FTRACE_SYSCALLS=y -CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y -CONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST=y -CONFIG_HAVE_FUNCTION_TRACER=y -CONFIG_HAVE_GENERIC_DMA_COHERENT=y -CONFIG_HAVE_IDE=y -CONFIG_HAVE_IOREMAP_PROT=y -CONFIG_HAVE_KERNEL_BZIP2=y -CONFIG_HAVE_KERNEL_GZIP=y -CONFIG_HAVE_KERNEL_LZMA=y -CONFIG_HAVE_KPROBES=y -CONFIG_HAVE_KRETPROBES=y -CONFIG_HAVE_KVM_IRQCHIP=y -CONFIG_HAVE_KVM=y -CONFIG_HAVE_LATENCYTOP_SUPPORT=y -CONFIG_HAVE_MLOCK=y -CONFIG_HAVE_MMIOTRACE_SUPPORT=y -CONFIG_HAVE_OPROFILE=y -CONFIG_HAVE_SETUP_PER_CPU_AREA=y -CONFIG_HAVE_UNSTABLE_SCHED_CLOCK=y -CONFIG_HIBERNATION=y -CONFIG_HID_SUPPORT=y -CONFIG_HID=y -# CONFIG_HIGHMEM4G is not set -# CONFIG_HIGHMEM64G is not set -CONFIG_HPET_EMULATE_RTC=y -# CONFIG_HPET is not set -CONFIG_HPET_TIMER=y -CONFIG_HT_IRQ=y -# CONFIG_HUGETLBFS is not set -CONFIG_HW_CONSOLE=y -# CONFIG_HW_RANDOM_AMD is not set -CONFIG_HW_RANDOM_GEODE=y -# CONFIG_HW_RANDOM_INTEL is not set -CONFIG_HW_RANDOM_VIA=y -CONFIG_HW_RANDOM=y -# CONFIG_I8K is not set -# CONFIG_IMA is not set -CONFIG_INITRAMFS_SOURCE="" -CONFIG_INPUT_EVDEV=y -CONFIG_INPUT_KEYBOARD=y -# CONFIG_INPUT_MOUSEDEV_PSAUX is not set -CONFIG_INPUT_MOUSEDEV_SCREEN_X=1200 -CONFIG_INPUT_MOUSEDEV_SCREEN_Y=900 -CONFIG_INPUT_MOUSEDEV=y -CONFIG_INPUT_MOUSE=y -CONFIG_INPUT=y -# CONFIG_INPUT_YEALINK is not set -# CONFIG_INTEL_MENLOW is not set -CONFIG_IO_DELAY_0X80=y -# CONFIG_IO_DELAY_0XED is not set -# CONFIG_IO_DELAY_NONE is not set -CONFIG_IO_DELAY_TYPE_0X80=0 -CONFIG_IO_DELAY_TYPE_0XED=1 -CONFIG_IO_DELAY_TYPE_NONE=3 -CONFIG_IO_DELAY_TYPE_UDELAY=2 -# CONFIG_IO_DELAY_UDELAY is not set -# CONFIG_IOMMU_API is not set -# CONFIG_IOMMU_HELPER is not set -CONFIG_ISA_DMA_API=y -# CONFIG_ISA is not set -# CONFIG_ISCSI_IBFT_FIND is not set -# CONFIG_ISDN is not set -# CONFIG_KALLSYMS_ALL is not set -CONFIG_KALLSYMS=y -# CONFIG_KERNEL_BZIP2 is not set -CONFIG_KERNEL_GZIP=y -# CONFIG_KERNEL_LZMA is not set -# CONFIG_KEXEC_JUMP is not set -CONFIG_KEXEC=y -CONFIG_KEYBOARD_ATKBD=y -# CONFIG_KEYBOARD_LKKBD is not set -# CONFIG_KEYBOARD_NEWTON is not set -# CONFIG_KEYBOARD_STOWAWAY is not set -# CONFIG_KEYBOARD_SUNKBD is not set -# CONFIG_KEYBOARD_XTKBD is not set -# CONFIG_KGDB is not set -CONFIG_KTIME_SCALAR=y -CONFIG_LCD_CLASS_DEVICE=y -# CONFIG_LCD_ILI9320 is not set -# CONFIG_LCD_PLATFORM is not set -# CONFIG_LEDS_ALIX2 is not set -# CONFIG_LEDS_CLEVO_MAIL is not set -# CONFIG_LOCK_STAT is not set -# CONFIG_LOGO is not set -# CONFIG_M386 is not set -# CONFIG_M486 is not set -# CONFIG_M586 is not set -# CONFIG_M586MMX is not set -# CONFIG_M586TSC is not set -# CONFIG_M686 is not set -# CONFIG_MACINTOSH_DRIVERS is not set -CONFIG_MARKERS=y -# CONFIG_MATH_EMULATION is not set -# CONFIG_MCA is not set -# CONFIG_MCORE2 is not set -# CONFIG_MCRUSOE is not set -# CONFIG_MCYRIXIII is not set -# CONFIG_MEFFICEON is not set -# CONFIG_MEMTEST is not set -# CONFIG_MGEODEGX1 is not set -CONFIG_MGEODE_LX=y -# CONFIG_MICROCODE is not set -# CONFIG_MISC_DEVICES is not set -# CONFIG_MK6 is not set -# CONFIG_MK7 is not set -# CONFIG_MK8 is not set -CONFIG_MMC_BLOCK=y -CONFIG_MMC_SDHCI=y -CONFIG_MMC=y -# CONFIG_MMIOTRACE is not set -# CONFIG_MOUSE_BCM5974 is not set -CONFIG_MOUSE_PS2_ALPS=y -# CONFIG_MOUSE_PS2_ELANTECH is not set -CONFIG_MOUSE_PS2_LIFEBOOK=y -CONFIG_MOUSE_PS2_LOGIPS2PP=y -CONFIG_MOUSE_PS2_OLPC=y -CONFIG_MOUSE_PS2_SYNAPTICS=y -# CONFIG_MOUSE_PS2_TOUCHKIT is not set -CONFIG_MOUSE_PS2_TRACKPOINT=y -CONFIG_MOUSE_PS2=y -# CONFIG_MOUSE_SERIAL is not set -# CONFIG_MOUSE_VSXXXAA is not set -# CONFIG_MPENTIUM4 is not set -# CONFIG_MPENTIUMIII is not set -# CONFIG_MPENTIUMII is not set -# CONFIG_MPENTIUMM is not set -# CONFIG_MPSC is not set -# CONFIG_MSI_LAPTOP is not set -CONFIG_MTD_BLOCK2MTD=y -# CONFIG_MTD_CFI is not set -CONFIG_MTD_CMDLINE_PARTS=y -CONFIG_MTD_PCI=y -# CONFIG_MTD_TS5500 is not set -# CONFIG_MTRR is not set -# CONFIG_MVIAC3_2 is not set -# CONFIG_MVIAC7 is not set -# CONFIG_MWINCHIP3D is not set -# CONFIG_MWINCHIPC6 is not set -# CONFIG_NETDEV_1000 is not set -# CONFIG_NET_DROP_MONITOR is not set -# CONFIG_NET_ETHERNET is not set -# CONFIG_NETWORK_FILESYSTEMS is not set -CONFIG_NOHIGHMEM=y -CONFIG_NO_HZ=y -CONFIG_NOP_TRACER=y -CONFIG_NR_CPUS=1 -# CONFIG_NSC_GPIO is not set -CONFIG_NVRAM=y -CONFIG_OLPC=y -CONFIG_OPROFILE=y -# CONFIG_OPTIMIZE_INLINING is not set -CONFIG_PAGEFLAGS_EXTENDED=y -CONFIG_PAGE_OFFSET=0xC0000000 -# CONFIG_PANASONIC_LAPTOP is not set -# CONFIG_PARAVIRT_GUEST is not set -# CONFIG_PARTITION_ADVANCED is not set -# CONFIG_PC8736x_GPIO is not set -# CONFIG_PCI_DEBUG is not set -CONFIG_PCI_DIRECT=y -CONFIG_PCI_DOMAINS=y -# CONFIG_PCIEPORTBUS is not set -# CONFIG_PCI_GOANY is not set -# CONFIG_PCI_GOBIOS is not set -# CONFIG_PCI_GODIRECT is not set -# CONFIG_PCI_GOMMCONFIG is not set -CONFIG_PCI_GOOLPC=y -CONFIG_PCI_OLPC=y -CONFIG_PCSPKR_PLATFORM=y -# CONFIG_PDA_POWER is not set -CONFIG_PHYSICAL_ALIGN=0x100000 -CONFIG_PHYSICAL_START=0x100000 -CONFIG_PM_DEBUG=y -CONFIG_PM_SLEEP=y -CONFIG_PM_STD_PARTITION="" -# CONFIG_PM_TRACE_RTC is not set -# CONFIG_PM_VERBOSE is not set -CONFIG_PM=y -CONFIG_PNPACPI=y -CONFIG_PNP_DEBUG_MESSAGES=y -CONFIG_PNP=y -# CONFIG_POWER_SUPPLY_DEBUG is not set -CONFIG_POWER_SUPPLY=y -# CONFIG_POWER_TRACER is not set -# CONFIG_PREEMPT_NONE is not set -CONFIG_PREEMPT_VOLUNTARY=y -CONFIG_PROCESSOR_SELECT=y -CONFIG_PROFILING=y -# CONFIG_PROVE_LOCKING is not set -# CONFIG_PROVIDE_OHCI1394_DMA_INIT is not set -# CONFIG_RCU_TORTURE_TEST is not set -CONFIG_RELAY=y -# CONFIG_RELOCATABLE is not set -CONFIG_RING_BUFFER=y -CONFIG_RTC=y -# CONFIG_RT_MUTEX_TESTER is not set -# CONFIG_RWSEM_GENERIC_SPINLOCK is not set -CONFIG_RWSEM_XCHGADD_ALGORITHM=y -CONFIG_SCHED_DEBUG=y -CONFIG_SCHED_HRTICK=y -CONFIG_SCHED_OMIT_FRAME_POINTER=y -CONFIG_SCHEDSTATS=y -CONFIG_SCSI=y -# CONFIG_SCx200 is not set -# CONFIG_SDIO_UART is not set -# CONFIG_SERIAL_8250_EXTENDED is not set -CONFIG_SERIAL_8250_PCI=y -CONFIG_SERIAL_8250_PNP=y -# CONFIG_SERIO_CT82C710 is not set -CONFIG_SERIO_I8042=y -CONFIG_SERIO_LIBPS2=y -# CONFIG_SERIO_PCIPS2 is not set -# CONFIG_SERIO_RAW is not set -CONFIG_SERIO_SERPORT=y -CONFIG_SERIO=y -# CONFIG_SLOW_WORK is not set -# CONFIG_SONYPI is not set -# CONFIG_SPARSE_IRQ is not set -CONFIG_SPARSEMEM_STATIC=y -CONFIG_STACKTRACE=y -CONFIG_STRICT_DEVMEM=y -CONFIG_SUSPEND_FREEZER=y -CONFIG_SUSPEND=y -# CONFIG_SYSPROF_TRACER is not set -# CONFIG_TC1100_WMI is not set -# CONFIG_TELCLOCK is not set -CONFIG_THERMAL=y -# CONFIG_THINKPAD_ACPI is not set -CONFIG_TIMER_STATS=y -# CONFIG_TOSHIBA is not set -CONFIG_TRACEPOINTS=y -CONFIG_TRACING_SUPPORT=y -CONFIG_TRACING=y -CONFIG_UID16=y -CONFIG_USB_EHCI_HCD=y -CONFIG_USB_EHCI_TT_NEWSCHED=y -# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set -# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set -CONFIG_USB_OHCI_HCD=y -CONFIG_USB_STORAGE=y -CONFIG_USB_SUPPORT=y -CONFIG_USB_SUSPEND=y -CONFIG_USB_UHCI_HCD=y -CONFIG_USB=y -CONFIG_USER_STACKTRACE_SUPPORT=y -CONFIG_VGACON_SOFT_SCROLLBACK_SIZE=64 -CONFIG_VGACON_SOFT_SCROLLBACK=y -CONFIG_VGA_CONSOLE=y -CONFIG_VM86=y -CONFIG_VM_EVENT_COUNTERS=y -# CONFIG_VMSPLIT_2G_OPT is not set -# CONFIG_VMSPLIT_3G_OPT is not set -CONFIG_VT_CONSOLE=y -# CONFIG_VT_HW_CONSOLE_BINDING is not set -CONFIG_VT=y -# CONFIG_WATCHDOG is not set -CONFIG_X86_32_LAZY_GS=y -CONFIG_X86_32=y -# CONFIG_X86_64 is not set -# CONFIG_X86_ACPI_CPUFREQ is not set -CONFIG_X86_BSWAP=y -# CONFIG_X86_CHECK_BIOS_CORRUPTION is not set -CONFIG_X86_CMPXCHG=y -# CONFIG_X86_CPU_DEBUG is not set -# CONFIG_X86_CPUFREQ_NFORCE2 is not set -# CONFIG_X86_CPUID is not set -CONFIG_X86_CPU=y -CONFIG_X86_DEBUGCTLMSR=y -# CONFIG_X86_DS is not set -# CONFIG_X86_ELAN is not set -# CONFIG_X86_E_POWERSAVER is not set -CONFIG_X86_EXTENDED_PLATFORM=y -CONFIG_X86_GENERIC=y -# CONFIG_X86_GX_SUSPMOD is not set -CONFIG_X86_INTEL_USERCOPY=y -CONFIG_X86_INTERNODE_CACHE_BYTES=64 -CONFIG_X86_INVLPG=y -CONFIG_X86_IO_APIC=y -CONFIG_X86_L1_CACHE_BYTES=64 -CONFIG_X86_L1_CACHE_SHIFT=5 -CONFIG_X86_LOCAL_APIC=y -# CONFIG_X86_LONGHAUL is not set -# CONFIG_X86_LONGRUN is not set -# CONFIG_X86_MCE is not set -CONFIG_X86_MINIMUM_CPU_FAMILY=4 -CONFIG_X86_MPPARSE=y -# CONFIG_X86_MSR is not set -# CONFIG_X86_P4_CLOCKMOD is not set -# CONFIG_X86_PAE is not set -CONFIG_X86_PLATFORM_DEVICES=y -CONFIG_X86_PM_TIMER=y -CONFIG_X86_POPAD_OK=y -# CONFIG_X86_POWERNOW_K6 is not set -# CONFIG_X86_POWERNOW_K7 is not set -# CONFIG_X86_POWERNOW_K8 is not set -# CONFIG_X86_PTDUMP is not set -# CONFIG_X86_RDC321X is not set -# CONFIG_X86_REBOOTFIXUPS is not set -# CONFIG_X86_REROUTE_FOR_BROKEN_BOOT_IRQS is not set -# CONFIG_X86_RESERVE_LOW_64K is not set -# CONFIG_X86_SPEEDSTEP_CENTRINO is not set -# CONFIG_X86_SPEEDSTEP_ICH is not set -# CONFIG_X86_SPEEDSTEP_LIB is not set -# CONFIG_X86_SPEEDSTEP_SMI is not set -CONFIG_X86_TSC=y -CONFIG_X86_UP_APIC=y -CONFIG_X86_UP_IOAPIC=y -CONFIG_X86_USE_3DNOW=y -CONFIG_X86_USE_PPRO_CHECKSUM=y -CONFIG_X86_VERBOSE_BOOTUP=y -CONFIG_X86_WP_WORKS_OK=y -CONFIG_X86_XADD=y -CONFIG_X86=y -# CONFIG_ZONE_DMA32 is not set diff --git a/target/linux/olpc/generic/profiles/000-Generic.mk b/target/linux/olpc/generic/profiles/000-Generic.mk deleted file mode 100644 index d7e6b7eb1..000000000 --- a/target/linux/olpc/generic/profiles/000-Generic.mk +++ /dev/null @@ -1,16 +0,0 @@ -# -# Copyright (C) 2006 OpenWrt.org -# -# This is free software, licensed under the GNU General Public License v2. -# See /LICENSE for more information. -# - -define Profile/Generic - NAME:=Generic - PACKAGES:= -endef - -define Profile/Generic/Description - Generic Profile -endef -$(eval $(call Profile,Generic)) diff --git a/target/linux/olpc/generic/target.mk b/target/linux/olpc/generic/target.mk deleted file mode 100644 index ea16d6379..000000000 --- a/target/linux/olpc/generic/target.mk +++ /dev/null @@ -1,6 +0,0 @@ -SUBTARGET:=generic - -define Target/Description - Build firmware images for OLPC -endef - diff --git a/target/linux/olpc/image/Config.in b/target/linux/olpc/image/Config.in deleted file mode 100644 index 27bbb961a..000000000 --- a/target/linux/olpc/image/Config.in +++ /dev/null @@ -1,23 +0,0 @@ -config OLPC_BOOTSCRIPT_IMAGES - bool "Build images with bootscript" - depends TARGET_olpc - depends TARGET_ROOTFS_EXT2FS || TARGET_ROOTFS_JFFS2 || TARGET_ROOTFS_SQUASHFS || TARGET_ROOTFS_ISO - default y - -config OLPC_BOOTSCRIPT_IMAGES_PAD - bool "Pad bootscript images to filesystem size (for JFFS2)" - depends OLPC_BOOTSCRIPT_IMAGES - -config OLPC_BOOTSCRIPT_KERNELPART - int "Kernel partition size (in MB)" - depends OLPC_BOOTSCRIPT_IMAGES - default 4 - -config OLPC_BOOTSCRIPT_ROOTPART - string - prompt "Root partition on target device" if OLPC_BOOTSCRIPT_IMAGES - default "/dev/sda2" - help - The root partition on the final device. If you don't know, - you probably want the default (/dev/sda2). - diff --git a/target/linux/olpc/image/Makefile b/target/linux/olpc/image/Makefile deleted file mode 100644 index 7ba712da6..000000000 --- a/target/linux/olpc/image/Makefile +++ /dev/null @@ -1,64 +0,0 @@ -# -# Copyright (C) 2007-2008 OpenWrt.org -# -# This is free software, licensed under the GNU General Public License v2. -# See /LICENSE for more information. -# -include $(TOPDIR)/rules.mk -include $(INCLUDE_DIR)/image.mk - -export PATH=$(TARGET_PATH):/sbin -ROOTPART=$(strip $(subst ",, $(CONFIG_OLPC_BOOTSCRIPT_ROOTPART))) -#"))")) # fix vim's broken syntax highlighting - -ROOTDELAY=10 - -ifeq ($(CONFIG_OLPC_BOOTSCRIPT_IMAGES),y) - define Image/cmdline/squashfs - block2mtd.block2mtd=$(ROOTPART),65536,rootfs root=/dev/mtdblock0 rootfstype=squashfs rootdelay=$(ROOTDELAY) - endef - - define Image/cmdline/jffs2-64k - block2mtd.block2mtd=$(ROOTPART),65536,rootfs root=/dev/mtdblock0 rootfstype=jffs2 rootdelay=$(ROOTDELAY) - endef - - define Image/cmdline/jffs2-128k - block2mtd.block2mtd=$(ROOTPART),131072,rootfs root=/dev/mtdblock0 rootfstype=jffs2 rootdelay=$(ROOTDELAY) - endef - - define Image/cmdline/ext2 - root=$(ROOTPART) rootfstype=ext2 rootwait - endef - - define Image/Build/bootscript - # left here because the image builder doesnt need these - $(INSTALL_DIR) $(KDIR)/root.bootscript/boot - $(CP) $(KDIR)/bzImage $(KDIR)/root.bootscript/boot/vmlinuz - sed -e 's#@CMDLINE@#$(strip $(call Image/cmdline/$(1))) $(BOOTOPTS)#g' \ - ./olpc.fth > $(KDIR)/root.bootscript/boot/olpc.fth - PADDING="$(CONFIG_OLPC_BOOTSCRIPT_IMAGES_PAD)" PATH="$(TARGET_PATH)" ./gen_image.sh $(BIN_DIR)/openwrt-$(BOARD)-$(1).image $(CONFIG_OLPC_BOOTSCRIPT_KERNELPART) $(KDIR)/root.bootscript $(CONFIG_TARGET_ROOTFS_FSPART) $(KDIR)/root.$(1) - endef -endif - -define Image/Prepare - cp $(LINUX_DIR)/arch/x86/boot/bzImage $(KDIR)/bzImage - $(call Image/Prepare/bootscript) -endef - -define Image/Build/squashfs - $(call prepare_generic_squashfs,$(KDIR)/root.squashfs) -endef - -define Image/BuildKernel - $(CP) $(KDIR)/bzImage $(BIN_DIR)/openwrt-$(BOARD)-vmlinuz -endef - -define Image/Build - $(call Image/Build/$(1)) - $(call Image/Build/bootscript,$(1)) - $(CP) $(KDIR)/root.$(1) $(BIN_DIR)/openwrt-$(BOARD)-$(1).fs - $(CP) $(KDIR)/bzImage $(BIN_DIR)/openwrt-$(BOARD)-vmlinuz -endef - -$(eval $(call BuildImage)) - diff --git a/target/linux/olpc/image/olpc.fth b/target/linux/olpc/image/olpc.fth deleted file mode 100644 index 5914be660..000000000 --- a/target/linux/olpc/image/olpc.fth +++ /dev/null @@ -1,5 +0,0 @@ -\ Boot script -" u:\boot\vmlinuz" to boot-device -" @CMDLINE@ noinitrd console=ttyS0,115200 console=tty0" to boot-file -unfreeze -boot diff --git a/target/linux/olpc/patches-2.6.30/300-block2mtd_init.patch b/target/linux/olpc/patches-2.6.30/300-block2mtd_init.patch deleted file mode 100644 index 12165b52b..000000000 --- a/target/linux/olpc/patches-2.6.30/300-block2mtd_init.patch +++ /dev/null @@ -1,210 +0,0 @@ ---- a/arch/x86/kernel/vmlinux_32.lds.S -+++ b/arch/x86/kernel/vmlinux_32.lds.S -@@ -136,6 +136,12 @@ SECTIONS - INITCALLS - __initcall_end = .; - } -+ .root_initcall.init : AT(ADDR(.root_initcall.init) - LOAD_OFFSET) { -+ __root_initcall_start = .; -+ INITCALLS_ROOT -+ __root_initcall_end = .; -+ } -+ - .con_initcall.init : AT(ADDR(.con_initcall.init) - LOAD_OFFSET) { - __con_initcall_start = .; - *(.con_initcall.init) ---- a/drivers/mtd/devices/block2mtd.c -+++ b/drivers/mtd/devices/block2mtd.c -@@ -18,10 +18,18 @@ - #include - #include - #include -+#include -+#include - - #define ERROR(fmt, args...) printk(KERN_ERR "block2mtd: " fmt "\n" , ## args) - #define INFO(fmt, args...) printk(KERN_INFO "block2mtd: " fmt "\n" , ## args) - -+struct retry { -+ struct list_head list; -+ const char *val; -+}; -+ -+static LIST_HEAD(retry_list); - - /* Info for the block device */ - struct block2mtd_dev { -@@ -33,10 +41,34 @@ struct block2mtd_dev { - char devname[0]; - }; - -+static int block2mtd_setup2(const char *val); - - /* Static info about the MTD, used in cleanup_module */ - static LIST_HEAD(blkmtd_device_list); - -+static int add_retry(const char *val) { -+ struct retry *r = kmalloc(sizeof(struct retry), GFP_KERNEL); -+ -+ INIT_LIST_HEAD(&r->list); -+ r->val = val; -+ list_add(&r->list, &retry_list); -+ -+ return 0; -+} -+ -+static int __init process_retries(void) { -+ struct list_head *p, *tmp; -+ -+ list_for_each_safe(p, tmp, &retry_list) { -+ struct retry *r = list_entry(p, struct retry, list); -+ block2mtd_setup2(r->val); -+ msleep(100); -+ list_del(p); -+ kfree(r); -+ } -+ return 0; -+} -+rootfs_initcall(process_retries); - - static struct page *page_read(struct address_space *mapping, int index) - { -@@ -510,7 +542,9 @@ static int block2mtd_setup2(const char * - if (token[2] && (strlen(token[2]) + 1 > 80)) - parse_err("mtd device name too long"); - -- add_device(name, erase_size, token[2]); -+ if (add_device(name, erase_size, token[2]) == NULL) { -+ add_retry(val); -+ } - - return 0; - } ---- a/include/asm-generic/vmlinux.lds.h -+++ b/include/asm-generic/vmlinux.lds.h -@@ -447,12 +447,14 @@ - *(.initcall4s.init) \ - *(.initcall5.init) \ - *(.initcall5s.init) \ -- *(.initcallrootfs.init) \ - *(.initcall6.init) \ - *(.initcall6s.init) \ - *(.initcall7.init) \ - *(.initcall7s.init) - -+#define INITCALLS_ROOT \ -+ *(.initcallrootfs.init) -+ - /** - * PERCPU_VADDR - define output section for percpu area - * @vaddr: explicit base address (optional) ---- a/init/do_mounts.c -+++ b/init/do_mounts.c -@@ -176,16 +176,8 @@ static int __init fs_names_setup(char *s - return 1; - } - --static unsigned int __initdata root_delay; --static int __init root_delay_setup(char *str) --{ -- root_delay = simple_strtoul(str, NULL, 0); -- return 1; --} -- - __setup("rootflags=", root_data_setup); - __setup("rootfstype=", fs_names_setup); --__setup("rootdelay=", root_delay_setup); - - static void __init get_fs_names(char *page) - { -@@ -365,23 +357,6 @@ void __init prepare_namespace(void) - { - int is_floppy; - -- if (root_delay) { -- printk(KERN_INFO "Waiting %dsec before mounting root device...\n", -- root_delay); -- ssleep(root_delay); -- } -- -- /* -- * wait for the known devices to complete their probing -- * -- * Note: this is a potential source of long boot delays. -- * For example, it is not atypical to wait 5 seconds here -- * for the touchpad of a laptop to initialize. -- */ -- wait_for_device_probe(); -- -- md_run_setup(); -- - if (saved_root_name[0]) { - root_device_name = saved_root_name; - if (!strncmp(root_device_name, "mtd", 3) || ---- a/init/main.c -+++ b/init/main.c -@@ -76,6 +76,7 @@ - #ifdef CONFIG_X86_LOCAL_APIC - #include - #endif -+#include "do_mounts.h" - - static int kernel_init(void *); - -@@ -752,12 +753,13 @@ int do_one_initcall(initcall_t fn) - - - extern initcall_t __initcall_start[], __initcall_end[], __early_initcall_end[]; -+extern initcall_t __root_initcall_start[], __root_initcall_end[]; - --static void __init do_initcalls(void) -+static void __init do_initcalls(initcall_t *start, initcall_t *end) - { - initcall_t *call; - -- for (call = __early_initcall_end; call < __initcall_end; call++) -+ for (call = start; call < end; call++) - do_one_initcall(*call); - - /* Make sure there is no pending stuff from the initcall sequence */ -@@ -779,7 +781,7 @@ static void __init do_basic_setup(void) - usermodehelper_init(); - driver_init(); - init_irq_proc(); -- do_initcalls(); -+ do_initcalls(__early_initcall_end, __initcall_end); - } - - static void __init do_pre_smp_initcalls(void) -@@ -840,6 +842,13 @@ static noinline int init_post(void) - panic("No init found. Try passing init= option to kernel."); - } - -+static unsigned int __initdata root_delay; -+static int __init root_delay_setup(char *str) -+{ -+ root_delay = simple_strtoul(str, NULL, 0); -+ return 1; -+} -+__setup("rootdelay=", root_delay_setup); - static int __init kernel_init(void * unused) - { - lock_kernel(); -@@ -879,7 +888,16 @@ static int __init kernel_init(void * unu - - if (sys_access((const char __user *) ramdisk_execute_command, 0) != 0) { - ramdisk_execute_command = NULL; -- prepare_namespace(); -+ if (root_delay) { -+ printk(KERN_INFO "Waiting %desc before mounting root device...\n", -+ root_delay); -+ ssleep(root_delay); -+ } -+ while (driver_probe_done() != 0) -+ msleep(100); -+ md_run_setup(); -+ do_initcalls(__root_initcall_start, __root_initcall_end); -+ prepare_namespace(); - } - - /* diff --git a/target/linux/omap35xx/Makefile b/target/linux/omap35xx/Makefile new file mode 100644 index 000000000..2ccfc1ac2 --- /dev/null +++ b/target/linux/omap35xx/Makefile @@ -0,0 +1,26 @@ +# +# Copyright (C) 2006-2009 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# +include $(TOPDIR)/rules.mk + +ARCH:=arm +BOARD:=omap35xx +BOARDNAME:=TI OMAP35xx +FEATURES:=broken +SUBTARGETS=generic + +LINUX_VERSION:=2.6.32.3 +KERNELNAME:="uImage" + +DEVICE_TYPE=developerboard + +define Target/Description + omap35xx arm +endef + +include $(INCLUDE_DIR)/target.mk + +$(eval $(call BuildTarget)) diff --git a/target/linux/omap35xx/base-files/etc/config/network b/target/linux/omap35xx/base-files/etc/config/network new file mode 100755 index 000000000..2ea5a4b04 --- /dev/null +++ b/target/linux/omap35xx/base-files/etc/config/network @@ -0,0 +1,14 @@ +# Copyright (C) 2006 OpenWrt.org + +config interface loopback + option ifname lo + option proto static + option ipaddr 127.0.0.1 + option netmask 255.0.0.0 + +config interface lan + option ifname usb0 + option type bridge + option proto static + option ipaddr 192.168.1.1 + option netmask 255.255.255.0 diff --git a/target/linux/omap35xx/base-files/etc/inittab b/target/linux/omap35xx/base-files/etc/inittab new file mode 100644 index 000000000..89626ecda --- /dev/null +++ b/target/linux/omap35xx/base-files/etc/inittab @@ -0,0 +1,7 @@ +::sysinit:/etc/init.d/rcS S boot +::shutdown:/etc/init.d/rcS K stop +tts/0::askfirst:/bin/ash --login +ttyS0::askfirst:/bin/ash --login +ttyS1::askfirst:/bin/ash --login +ttyS2::askfirst:/bin/ash --login +tty1::askfirst:/bin/ash --login diff --git a/target/linux/omap35xx/config-2.6.32 b/target/linux/omap35xx/config-2.6.32 new file mode 100644 index 000000000..5b79b4276 --- /dev/null +++ b/target/linux/omap35xx/config-2.6.32 @@ -0,0 +1,2106 @@ +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.32-rc5 +# Thu Dec 10 00:13:17 2009 +# +CONFIG_ARM=y +CONFIG_SYS_SUPPORTS_APM_EMULATION=y +CONFIG_GENERIC_GPIO=y +CONFIG_GENERIC_TIME=y +CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_GENERIC_HARDIRQS=y +CONFIG_STACKTRACE_SUPPORT=y +CONFIG_HAVE_LATENCYTOP_SUPPORT=y +CONFIG_LOCKDEP_SUPPORT=y +CONFIG_TRACE_IRQFLAGS_SUPPORT=y +CONFIG_HARDIRQS_SW_RESEND=y +CONFIG_GENERIC_IRQ_PROBE=y +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_ARCH_HAS_CPUFREQ=y +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y +CONFIG_VECTORS_BASE=0xffff0000 +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" +CONFIG_CONSTRUCTORS=y + +# +# General setup +# +CONFIG_EXPERIMENTAL=y +CONFIG_BROKEN_ON_SMP=y +CONFIG_INIT_ENV_ARG_LIMIT=32 +CONFIG_LOCALVERSION="" +CONFIG_LOCALVERSION_AUTO=y +CONFIG_HAVE_KERNEL_GZIP=y +CONFIG_HAVE_KERNEL_LZMA=y +CONFIG_HAVE_KERNEL_LZO=y +# CONFIG_KERNEL_GZIP is not set +# CONFIG_KERNEL_BZIP2 is not set +CONFIG_KERNEL_LZMA=y +# CONFIG_KERNEL_LZO is not set +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +CONFIG_SYSVIPC_SYSCTL=y +# CONFIG_POSIX_MQUEUE is not set +CONFIG_BSD_PROCESS_ACCT=y +# CONFIG_BSD_PROCESS_ACCT_V3 is not set +# CONFIG_TASKSTATS is not set +# CONFIG_AUDIT is not set + +# +# RCU Subsystem +# +CONFIG_TREE_RCU=y +# CONFIG_TREE_PREEMPT_RCU is not set +# CONFIG_RCU_TRACE is not set +CONFIG_RCU_FANOUT=32 +# CONFIG_RCU_FANOUT_EXACT is not set +# CONFIG_TREE_RCU_TRACE is not set +# CONFIG_IKCONFIG is not set +CONFIG_LOG_BUF_SHIFT=14 +CONFIG_GROUP_SCHED=y +CONFIG_FAIR_GROUP_SCHED=y +# CONFIG_RT_GROUP_SCHED is not set +CONFIG_USER_SCHED=y +# CONFIG_CGROUP_SCHED is not set +# CONFIG_CGROUPS is not set +CONFIG_SYSFS_DEPRECATED=y +CONFIG_SYSFS_DEPRECATED_V2=y +# CONFIG_RELAY is not set +# CONFIG_NAMESPACES is not set +CONFIG_BLK_DEV_INITRD=y +CONFIG_INITRAMFS_SOURCE="" +# CONFIG_RD_GZIP is not set +# CONFIG_RD_BZIP2 is not set +CONFIG_RD_LZMA=y +# CONFIG_RD_LZO is not set +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_SYSCTL=y +CONFIG_ANON_INODES=y +CONFIG_EMBEDDED=y +CONFIG_UID16=y +# CONFIG_SYSCTL_SYSCALL is not set +# CONFIG_KALLSYMS is not set +CONFIG_HOTPLUG=y +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_SIGNALFD=y +CONFIG_TIMERFD=y +CONFIG_EVENTFD=y +CONFIG_SHMEM=y +CONFIG_AIO=y + +# +# Kernel Performance Events And Counters +# +CONFIG_VM_EVENT_COUNTERS=y +CONFIG_COMPAT_BRK=y +CONFIG_SLAB=y +# CONFIG_SLUB is not set +# CONFIG_SLOB is not set +# CONFIG_PROFILING is not set +CONFIG_HAVE_OPROFILE=y +CONFIG_HAVE_KPROBES=y +CONFIG_HAVE_KRETPROBES=y +CONFIG_HAVE_CLK=y + +# +# GCOV-based kernel profiling +# +# CONFIG_GCOV_KERNEL is not set +# CONFIG_SLOW_WORK is not set +CONFIG_HAVE_GENERIC_DMA_COHERENT=y +CONFIG_SLABINFO=y +CONFIG_RT_MUTEXES=y +CONFIG_BASE_SMALL=0 +CONFIG_MODULES=y +# CONFIG_MODULE_FORCE_LOAD is not set +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +CONFIG_MODVERSIONS=y +CONFIG_MODULE_SRCVERSION_ALL=y +CONFIG_BLOCK=y +# CONFIG_LBDAF is not set +# CONFIG_BLK_DEV_BSG is not set +# CONFIG_BLK_DEV_INTEGRITY is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +CONFIG_DEFAULT_AS=y +# CONFIG_DEFAULT_DEADLINE is not set +# CONFIG_DEFAULT_CFQ is not set +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="anticipatory" +CONFIG_FREEZER=y + +# +# System Type +# +CONFIG_MMU=y +# CONFIG_ARCH_AAEC2000 is not set +# CONFIG_ARCH_INTEGRATOR is not set +# CONFIG_ARCH_REALVIEW is not set +# CONFIG_ARCH_VERSATILE is not set +# CONFIG_ARCH_AT91 is not set +# CONFIG_ARCH_CLPS711X is not set +# CONFIG_ARCH_GEMINI is not set +# CONFIG_ARCH_EBSA110 is not set +# CONFIG_ARCH_EP93XX is not set +# CONFIG_ARCH_FOOTBRIDGE is not set +# CONFIG_ARCH_MXC is not set +# CONFIG_ARCH_STMP3XXX is not set +# CONFIG_ARCH_NETX is not set +# CONFIG_ARCH_H720X is not set +# CONFIG_ARCH_NOMADIK is not set +# CONFIG_ARCH_IOP13XX is not set +# CONFIG_ARCH_IOP32X is not set +# CONFIG_ARCH_IOP33X is not set +# CONFIG_ARCH_IXP23XX is not set +# CONFIG_ARCH_IXP2000 is not set +# CONFIG_ARCH_IXP4XX is not set +# CONFIG_ARCH_L7200 is not set +# CONFIG_ARCH_KIRKWOOD is not set +# CONFIG_ARCH_LOKI is not set +# CONFIG_ARCH_MV78XX0 is not set +# CONFIG_ARCH_ORION5X is not set +# CONFIG_ARCH_MMP is not set +# CONFIG_ARCH_KS8695 is not set +# CONFIG_ARCH_NS9XXX is not set +# CONFIG_ARCH_W90X900 is not set +# CONFIG_ARCH_PNX4008 is not set +# CONFIG_ARCH_PXA is not set +# CONFIG_ARCH_MSM is not set +# CONFIG_ARCH_RPC is not set +# CONFIG_ARCH_SA1100 is not set +# CONFIG_ARCH_S3C2410 is not set +# CONFIG_ARCH_S3C64XX is not set +# CONFIG_ARCH_S5PC1XX is not set +# CONFIG_ARCH_SHARK is not set +# CONFIG_ARCH_LH7A40X is not set +# CONFIG_ARCH_U300 is not set +# CONFIG_ARCH_DAVINCI is not set +CONFIG_ARCH_OMAP=y +# CONFIG_ARCH_BCMRING is not set + +# +# TI OMAP Implementations +# +CONFIG_ARCH_OMAP_OTG=y +# CONFIG_ARCH_OMAP1 is not set +# CONFIG_ARCH_OMAP2 is not set +CONFIG_ARCH_OMAP3=y +# CONFIG_ARCH_OMAP4 is not set + +# +# OMAP Feature Selections +# +# CONFIG_OMAP_DEBUG_POWERDOMAIN is not set +# CONFIG_OMAP_DEBUG_CLOCKDOMAIN is not set +# CONFIG_OMAP_RESET_CLOCKS is not set +# CONFIG_OMAP_MUX is not set +CONFIG_OMAP_MCBSP=y +# CONFIG_OMAP_MBOX_FWK is not set +# CONFIG_OMAP_MPU_TIMER is not set +CONFIG_OMAP_32K_TIMER=y +CONFIG_OMAP_32K_TIMER_HZ=128 +CONFIG_OMAP_DM_TIMER=y +# CONFIG_OMAP_LL_DEBUG_UART1 is not set +# CONFIG_OMAP_LL_DEBUG_UART2 is not set +CONFIG_OMAP_LL_DEBUG_UART3=y +# CONFIG_OMAP_PM_NONE is not set +CONFIG_OMAP_PM_NOOP=y +CONFIG_ARCH_OMAP34XX=y +CONFIG_ARCH_OMAP3430=y + +# +# OMAP Board Type +# +CONFIG_MACH_OMAP3_BEAGLE=y +# CONFIG_MACH_OMAP_LDP is not set +# CONFIG_MACH_OVERO is not set +# CONFIG_MACH_OMAP3EVM is not set +# CONFIG_MACH_OMAP3_PANDORA is not set +# CONFIG_MACH_OMAP_3430SDP is not set +# CONFIG_MACH_NOKIA_RX51 is not set +# CONFIG_MACH_OMAP_ZOOM2 is not set + +# +# Processor Type +# +CONFIG_CPU_32=y +CONFIG_CPU_32v6K=y +CONFIG_CPU_V7=y +CONFIG_CPU_32v7=y +CONFIG_CPU_ABRT_EV7=y +CONFIG_CPU_PABRT_V7=y +CONFIG_CPU_CACHE_V7=y +CONFIG_CPU_CACHE_VIPT=y +CONFIG_CPU_COPY_V6=y +CONFIG_CPU_TLB_V7=y +CONFIG_CPU_HAS_ASID=y +CONFIG_CPU_CP15=y +CONFIG_CPU_CP15_MMU=y + +# +# Processor Features +# +CONFIG_ARM_THUMB=y +# CONFIG_ARM_THUMBEE is not set +# CONFIG_CPU_ICACHE_DISABLE is not set +# CONFIG_CPU_DCACHE_DISABLE is not set +# CONFIG_CPU_BPREDICT_DISABLE is not set +CONFIG_HAS_TLS_REG=y +CONFIG_ARM_L1_CACHE_SHIFT=6 +# CONFIG_ARM_ERRATA_430973 is not set +# CONFIG_ARM_ERRATA_458693 is not set +# CONFIG_ARM_ERRATA_460075 is not set +CONFIG_COMMON_CLKDEV=y + +# +# Bus support +# +# CONFIG_PCI_SYSCALL is not set +# CONFIG_ARCH_SUPPORTS_MSI is not set +# CONFIG_PCCARD is not set + +# +# Kernel Features +# +CONFIG_TICK_ONESHOT=y +CONFIG_NO_HZ=y +CONFIG_HIGH_RES_TIMERS=y +CONFIG_GENERIC_CLOCKEVENTS_BUILD=y +CONFIG_VMSPLIT_3G=y +# CONFIG_VMSPLIT_2G is not set +# CONFIG_VMSPLIT_1G is not set +CONFIG_PAGE_OFFSET=0xC0000000 +CONFIG_PREEMPT_NONE=y +# CONFIG_PREEMPT_VOLUNTARY is not set +# CONFIG_PREEMPT is not set +CONFIG_HZ=128 +# CONFIG_THUMB2_KERNEL is not set +CONFIG_AEABI=y +# CONFIG_OABI_COMPAT is not set +# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set +# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set +# CONFIG_HIGHMEM is not set +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +# CONFIG_DISCONTIGMEM_MANUAL is not set +# CONFIG_SPARSEMEM_MANUAL is not set +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +CONFIG_PAGEFLAGS_EXTENDED=y +CONFIG_SPLIT_PTLOCK_CPUS=4 +# CONFIG_PHYS_ADDR_T_64BIT is not set +CONFIG_ZONE_DMA_FLAG=0 +CONFIG_VIRT_TO_BUS=y +CONFIG_HAVE_MLOCK=y +CONFIG_HAVE_MLOCKED_PAGE_BIT=y +# CONFIG_KSM is not set +CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 +# CONFIG_LEDS is not set +CONFIG_ALIGNMENT_TRAP=y +# CONFIG_UACCESS_WITH_MEMCPY is not set + +# +# Boot options +# +CONFIG_ZBOOT_ROM_TEXT=0x0 +CONFIG_ZBOOT_ROM_BSS=0x0 +CONFIG_CMDLINE="root=/dev/nfs nfsroot=192.168.0.1:/home/user/buildroot ip=192.168.0.2:192.168.0.1:192.168.0.1:255.255.255.0:tgt:eth0:off rw console=ttyS2,115200n8" +# CONFIG_XIP_KERNEL is not set +# CONFIG_KEXEC is not set + +# +# CPU Power Management +# +# CONFIG_CPU_FREQ is not set +# CONFIG_CPU_IDLE is not set + +# +# Floating point emulation +# + +# +# At least one emulation must be selected +# +CONFIG_VFP=y +CONFIG_VFPv3=y +# CONFIG_NEON is not set + +# +# Userspace binary formats +# +CONFIG_BINFMT_ELF=y +# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set +CONFIG_HAVE_AOUT=y +# CONFIG_BINFMT_AOUT is not set +CONFIG_BINFMT_MISC=y + +# +# Power management options +# +CONFIG_PM=y +# CONFIG_PM_DEBUG is not set +CONFIG_PM_SLEEP=y +CONFIG_SUSPEND=y +CONFIG_SUSPEND_FREEZER=y +# CONFIG_APM_EMULATION is not set +CONFIG_PM_RUNTIME=y +CONFIG_ARCH_SUSPEND_POSSIBLE=y +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +# CONFIG_PACKET_MMAP is not set +CONFIG_UNIX=y +CONFIG_XFRM=y +# CONFIG_XFRM_USER is not set +# CONFIG_XFRM_SUB_POLICY is not set +# CONFIG_XFRM_MIGRATE is not set +# CONFIG_XFRM_STATISTICS is not set +CONFIG_NET_KEY=y +# CONFIG_NET_KEY_MIGRATE is not set +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_FIB_HASH=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_IP_PNP_BOOTP=y +CONFIG_IP_PNP_RARP=y +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_ARPD is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_INET_XFRM_TUNNEL is not set +# CONFIG_INET_TUNNEL is not set +CONFIG_INET_XFRM_MODE_TRANSPORT=y +CONFIG_INET_XFRM_MODE_TUNNEL=y +CONFIG_INET_XFRM_MODE_BEET=y +# CONFIG_INET_LRO is not set +CONFIG_INET_DIAG=y +CONFIG_INET_TCP_DIAG=y +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_CUBIC=y +CONFIG_DEFAULT_TCP_CONG="cubic" +# CONFIG_TCP_MD5SIG is not set +# CONFIG_IPV6 is not set +# CONFIG_NETWORK_SECMARK is not set +# CONFIG_NETFILTER is not set +# CONFIG_IP_DCCP is not set +# CONFIG_IP_SCTP is not set +# CONFIG_RDS is not set +# CONFIG_TIPC is not set +# CONFIG_ATM is not set +# CONFIG_BRIDGE is not set +# CONFIG_NET_DSA is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_PHONET is not set +# CONFIG_IEEE802154 is not set +# CONFIG_NET_SCHED is not set +# CONFIG_DCB is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_HAMRADIO is not set +# CONFIG_CAN is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set +# CONFIG_AF_RXRPC is not set +CONFIG_WIRELESS=y +# CONFIG_CFG80211 is not set +CONFIG_CFG80211_DEFAULT_PS_VALUE=0 +CONFIG_WIRELESS_OLD_REGULATORY=y +# CONFIG_WIRELESS_EXT is not set +# CONFIG_LIB80211 is not set +# CONFIG_LIB80211_CRYPT_WEP is not set +# CONFIG_LIB80211_CRYPT_CCMP is not set +# CONFIG_LIB80211_CRYPT_TKIP is not set + +# +# CFG80211 needs to be enabled for MAC80211 +# +# CONFIG_WIMAX is not set +# CONFIG_RFKILL is not set +# CONFIG_NET_9P is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" +CONFIG_DEVTMPFS=y +CONFIG_DEVTMPFS_MOUNT=y +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +# CONFIG_FW_LOADER is not set +CONFIG_DEBUG_DRIVER=y +# CONFIG_DEBUG_DEVRES is not set +# CONFIG_SYS_HYPERVISOR is not set +# CONFIG_CONNECTOR is not set +CONFIG_MTD=y +CONFIG_MTD_DEBUG=y +CONFIG_MTD_DEBUG_VERBOSE=2 +# CONFIG_MTD_TESTS is not set +# CONFIG_MTD_CONCAT is not set +CONFIG_MTD_PARTITIONS=y +CONFIG_MTD_ROOTFS_ROOT_DEV=y +CONFIG_MTD_ROOTFS_SPLIT=y +# CONFIG_MTD_REDBOOT_PARTS is not set +# CONFIG_MTD_CMDLINE_PARTS is not set +# CONFIG_MTD_AFS_PARTS is not set +CONFIG_MTD_AR7_PARTS=y + +# +# User Modules And Translation Layers +# +CONFIG_MTD_CHAR=y +CONFIG_MTD_BLKDEVS=y +CONFIG_MTD_BLOCK=y +# CONFIG_FTL is not set +# CONFIG_NFTL is not set +# CONFIG_INFTL is not set +# CONFIG_RFD_FTL is not set +# CONFIG_SSFDC is not set +# CONFIG_MTD_OOPS is not set + +# +# RAM/ROM/Flash chip drivers +# +# CONFIG_MTD_CFI is not set +# CONFIG_MTD_JEDECPROBE is not set +CONFIG_MTD_MAP_BANK_WIDTH_1=y +CONFIG_MTD_MAP_BANK_WIDTH_2=y +CONFIG_MTD_MAP_BANK_WIDTH_4=y +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set +# CONFIG_MTD_RAM is not set +# CONFIG_MTD_ROM is not set +# CONFIG_MTD_ABSENT is not set + +# +# Mapping drivers for chip access +# +# CONFIG_MTD_COMPLEX_MAPPINGS is not set +# CONFIG_MTD_PLATRAM is not set + +# +# Self-contained MTD device drivers +# +# CONFIG_MTD_DATAFLASH is not set +# CONFIG_MTD_M25P80 is not set +# CONFIG_MTD_SST25L is not set +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_PHRAM is not set +# CONFIG_MTD_MTDRAM is not set +CONFIG_MTD_BLOCK2MTD=y + +# +# Disk-On-Chip Device Drivers +# +# CONFIG_MTD_DOC2000 is not set +# CONFIG_MTD_DOC2001 is not set +# CONFIG_MTD_DOC2001PLUS is not set +CONFIG_MTD_NAND=y +# CONFIG_MTD_NAND_VERIFY_WRITE is not set +# CONFIG_MTD_NAND_ECC_SMC is not set +# CONFIG_MTD_NAND_MUSEUM_IDS is not set +CONFIG_MTD_NAND_GPIO=y +CONFIG_MTD_NAND_OMAP2=y +CONFIG_MTD_NAND_OMAP_PREFETCH=y +# CONFIG_MTD_NAND_OMAP_PREFETCH_DMA is not set +CONFIG_MTD_NAND_IDS=y +# CONFIG_MTD_NAND_DISKONCHIP is not set +# CONFIG_MTD_NAND_NANDSIM is not set +CONFIG_MTD_NAND_PLATFORM=y +# CONFIG_MTD_ALAUDA is not set +# CONFIG_MTD_ONENAND is not set + +# +# LPDDR flash memory drivers +# +# CONFIG_MTD_LPDDR is not set + +# +# UBI - Unsorted block images +# +# CONFIG_MTD_UBI is not set +# CONFIG_PARPORT is not set +CONFIG_BLK_DEV=y +# CONFIG_BLK_DEV_COW_COMMON is not set +CONFIG_BLK_DEV_LOOP=y +# CONFIG_BLK_DEV_CRYPTOLOOP is not set +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_UB is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=16384 +# CONFIG_BLK_DEV_XIP is not set +# CONFIG_CDROM_PKTCDVD is not set +# CONFIG_ATA_OVER_ETH is not set +# CONFIG_MG_DISK is not set +# CONFIG_MISC_DEVICES is not set +CONFIG_HAVE_IDE=y +# CONFIG_IDE is not set + +# +# SCSI device support +# +# CONFIG_RAID_ATTRS is not set +CONFIG_SCSI=y +CONFIG_SCSI_DMA=y +# CONFIG_SCSI_TGT is not set +# CONFIG_SCSI_NETLINK is not set +CONFIG_SCSI_PROC_FS=y + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=y +# CONFIG_CHR_DEV_ST is not set +# CONFIG_CHR_DEV_OSST is not set +# CONFIG_BLK_DEV_SR is not set +# CONFIG_CHR_DEV_SG is not set +# CONFIG_CHR_DEV_SCH is not set +# CONFIG_SCSI_MULTI_LUN is not set +# CONFIG_SCSI_CONSTANTS is not set +# CONFIG_SCSI_LOGGING is not set +# CONFIG_SCSI_SCAN_ASYNC is not set +CONFIG_SCSI_WAIT_SCAN=m + +# +# SCSI Transports +# +# CONFIG_SCSI_SPI_ATTRS is not set +# CONFIG_SCSI_FC_ATTRS is not set +# CONFIG_SCSI_ISCSI_ATTRS is not set +# CONFIG_SCSI_SAS_LIBSAS is not set +# CONFIG_SCSI_SRP_ATTRS is not set +CONFIG_SCSI_LOWLEVEL=y +# CONFIG_ISCSI_TCP is not set +# CONFIG_LIBFC is not set +# CONFIG_LIBFCOE is not set +# CONFIG_SCSI_DEBUG is not set +# CONFIG_SCSI_DH is not set +# CONFIG_SCSI_OSD_INITIATOR is not set +# CONFIG_ATA is not set +# CONFIG_MD is not set +CONFIG_NETDEVICES=y +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_MACVLAN is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set +# CONFIG_VETH is not set +# CONFIG_NET_ETHERNET is not set +# CONFIG_NETDEV_1000 is not set +# CONFIG_NETDEV_10000 is not set +CONFIG_WLAN=y +# CONFIG_WLAN_PRE80211 is not set +# CONFIG_WLAN_80211 is not set + +# +# Enable WiMAX (Networking options) to see the WiMAX drivers +# + +# +# USB Network Adapters +# +# CONFIG_USB_CATC is not set +# CONFIG_USB_KAWETH is not set +# CONFIG_USB_PEGASUS is not set +# CONFIG_USB_RTL8150 is not set +# CONFIG_USB_USBNET is not set +# CONFIG_WAN is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set +# CONFIG_NETCONSOLE is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set +# CONFIG_ISDN is not set +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y +# CONFIG_INPUT_FF_MEMLESS is not set +# CONFIG_INPUT_POLLDEV is not set + +# +# Userland interfaces +# +# CONFIG_INPUT_MOUSEDEV is not set +# CONFIG_INPUT_JOYDEV is not set +CONFIG_INPUT_EVDEV=y +# CONFIG_INPUT_EVBUG is not set + +# +# Input Device Drivers +# +CONFIG_INPUT_KEYBOARD=y +# CONFIG_KEYBOARD_ADP5588 is not set +CONFIG_KEYBOARD_ATKBD=y +# CONFIG_QT2160 is not set +# CONFIG_KEYBOARD_LKKBD is not set +# CONFIG_KEYBOARD_GPIO is not set +# CONFIG_KEYBOARD_MATRIX is not set +# CONFIG_KEYBOARD_LM8323 is not set +# CONFIG_KEYBOARD_MAX7359 is not set +# CONFIG_KEYBOARD_NEWTON is not set +# CONFIG_KEYBOARD_OPENCORES is not set +# CONFIG_KEYBOARD_STOWAWAY is not set +# CONFIG_KEYBOARD_SUNKBD is not set +# CONFIG_KEYBOARD_TWL4030 is not set +# CONFIG_KEYBOARD_XTKBD is not set +CONFIG_INPUT_MOUSE=y +CONFIG_MOUSE_PS2=y +# CONFIG_MOUSE_PS2_ALPS is not set +# CONFIG_MOUSE_PS2_LOGIPS2PP is not set +# CONFIG_MOUSE_PS2_SYNAPTICS is not set +# CONFIG_MOUSE_PS2_TRACKPOINT is not set +# CONFIG_MOUSE_PS2_ELANTECH is not set +# CONFIG_MOUSE_PS2_SENTELIC is not set +# CONFIG_MOUSE_PS2_TOUCHKIT is not set +# CONFIG_MOUSE_SERIAL is not set +# CONFIG_MOUSE_APPLETOUCH is not set +# CONFIG_MOUSE_BCM5974 is not set +# CONFIG_MOUSE_VSXXXAA is not set +# CONFIG_MOUSE_GPIO is not set +# CONFIG_MOUSE_SYNAPTICS_I2C is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TABLET is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Hardware I/O ports +# +CONFIG_SERIO=y +CONFIG_SERIO_SERPORT=y +CONFIG_SERIO_LIBPS2=y +# CONFIG_SERIO_RAW is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_CONSOLE_TRANSLATIONS=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +# CONFIG_VT_HW_CONSOLE_BINDING is not set +CONFIG_DEVKMEM=y +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_NR_UARTS=32 +CONFIG_SERIAL_8250_RUNTIME_UARTS=4 +CONFIG_SERIAL_8250_EXTENDED=y +CONFIG_SERIAL_8250_MANY_PORTS=y +CONFIG_SERIAL_8250_SHARE_IRQ=y +CONFIG_SERIAL_8250_DETECT_IRQ=y +CONFIG_SERIAL_8250_RSA=y + +# +# Non-8250 serial port support +# +# CONFIG_SERIAL_MAX3100 is not set +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_UNIX98_PTYS=y +# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set +# CONFIG_LEGACY_PTYS is not set +# CONFIG_IPMI_HANDLER is not set +CONFIG_HW_RANDOM=y +# CONFIG_HW_RANDOM_TIMERIOMEM is not set +# CONFIG_R3964 is not set +# CONFIG_GPIO_DEVICE is not set +# CONFIG_RAW_DRIVER is not set +# CONFIG_TCG_TPM is not set +CONFIG_I2C=y +CONFIG_I2C_BOARDINFO=y +# CONFIG_I2C_COMPAT is not set +CONFIG_I2C_CHARDEV=y +CONFIG_I2C_HELPER_AUTO=y +CONFIG_I2C_ALGOBIT=y + +# +# I2C Hardware Bus support +# + +# +# I2C system bus drivers (mostly embedded / system-on-chip) +# +# CONFIG_I2C_DESIGNWARE is not set +CONFIG_I2C_GPIO=y +# CONFIG_I2C_OCORES is not set +CONFIG_I2C_OMAP=y +# CONFIG_I2C_SIMTEC is not set + +# +# External I2C/SMBus adapter drivers +# +# CONFIG_I2C_PARPORT_LIGHT is not set +# CONFIG_I2C_TAOS_EVM is not set +# CONFIG_I2C_TINY_USB is not set + +# +# Other I2C/SMBus bus drivers +# +# CONFIG_I2C_PCA_PLATFORM is not set +# CONFIG_I2C_STUB is not set + +# +# Miscellaneous I2C Chip support +# +# CONFIG_DS1682 is not set +# CONFIG_SENSORS_TSL2550 is not set +# CONFIG_I2C_DEBUG_CORE is not set +# CONFIG_I2C_DEBUG_ALGO is not set +# CONFIG_I2C_DEBUG_BUS is not set +# CONFIG_I2C_DEBUG_CHIP is not set +CONFIG_SPI=y +# CONFIG_SPI_DEBUG is not set +CONFIG_SPI_MASTER=y + +# +# SPI Master Controller Drivers +# +# CONFIG_SPI_BITBANG is not set +# CONFIG_SPI_GPIO is not set +# CONFIG_SPI_GPIO_OLD is not set +CONFIG_SPI_OMAP24XX=y + +# +# SPI Protocol Masters +# +CONFIG_SPI_SPIDEV=y +# CONFIG_SPI_TLE62X0 is not set + +# +# PPS support +# +# CONFIG_PPS is not set +CONFIG_ARCH_REQUIRE_GPIOLIB=y +CONFIG_GPIOLIB=y +# CONFIG_DEBUG_GPIO is not set +# CONFIG_GPIO_SYSFS is not set + +# +# Memory mapped GPIO expanders: +# + +# +# I2C GPIO expanders: +# +# CONFIG_GPIO_MAX732X is not set +# CONFIG_GPIO_PCA953X is not set +# CONFIG_GPIO_PCF857X is not set +CONFIG_GPIO_TWL4030=y + +# +# PCI GPIO expanders: +# + +# +# SPI GPIO expanders: +# +# CONFIG_GPIO_MAX7301 is not set +# CONFIG_GPIO_MCP23S08 is not set +# CONFIG_GPIO_MC33880 is not set + +# +# AC97 GPIO expanders: +# +# CONFIG_W1 is not set +CONFIG_POWER_SUPPLY=y +# CONFIG_POWER_SUPPLY_DEBUG is not set +# CONFIG_PDA_POWER is not set +# CONFIG_BATTERY_DS2760 is not set +# CONFIG_BATTERY_DS2782 is not set +# CONFIG_BATTERY_BQ27x00 is not set +# CONFIG_BATTERY_MAX17040 is not set +CONFIG_HWMON=y +# CONFIG_HWMON_VID is not set +# CONFIG_HWMON_DEBUG_CHIP is not set + +# +# Native drivers +# +# CONFIG_SENSORS_AD7414 is not set +# CONFIG_SENSORS_AD7418 is not set +# CONFIG_SENSORS_ADCXX is not set +# CONFIG_SENSORS_ADM1021 is not set +# CONFIG_SENSORS_ADM1025 is not set +# CONFIG_SENSORS_ADM1026 is not set +# CONFIG_SENSORS_ADM1029 is not set +# CONFIG_SENSORS_ADM1031 is not set +# CONFIG_SENSORS_ADM9240 is not set +# CONFIG_SENSORS_ADT7462 is not set +# CONFIG_SENSORS_ADT7470 is not set +# CONFIG_SENSORS_ADT7473 is not set +# CONFIG_SENSORS_ADT7475 is not set +# CONFIG_SENSORS_ATXP1 is not set +# CONFIG_SENSORS_DS1621 is not set +# CONFIG_SENSORS_F71805F is not set +# CONFIG_SENSORS_F71882FG is not set +# CONFIG_SENSORS_F75375S is not set +# CONFIG_SENSORS_G760A is not set +# CONFIG_SENSORS_GL518SM is not set +# CONFIG_SENSORS_GL520SM is not set +# CONFIG_SENSORS_IT87 is not set +# CONFIG_SENSORS_LM63 is not set +# CONFIG_SENSORS_LM70 is not set +# CONFIG_SENSORS_LM75 is not set +# CONFIG_SENSORS_LM77 is not set +# CONFIG_SENSORS_LM78 is not set +# CONFIG_SENSORS_LM80 is not set +# CONFIG_SENSORS_LM83 is not set +# CONFIG_SENSORS_LM85 is not set +# CONFIG_SENSORS_LM87 is not set +# CONFIG_SENSORS_LM90 is not set +# CONFIG_SENSORS_LM92 is not set +# CONFIG_SENSORS_LM93 is not set +# CONFIG_SENSORS_LTC4215 is not set +# CONFIG_SENSORS_LTC4245 is not set +# CONFIG_SENSORS_LM95241 is not set +# CONFIG_SENSORS_MAX1111 is not set +# CONFIG_SENSORS_MAX1619 is not set +# CONFIG_SENSORS_MAX6650 is not set +# CONFIG_SENSORS_PC87360 is not set +# CONFIG_SENSORS_PC87427 is not set +# CONFIG_SENSORS_PCF8591 is not set +# CONFIG_SENSORS_SHT15 is not set +# CONFIG_SENSORS_DME1737 is not set +# CONFIG_SENSORS_SMSC47M1 is not set +# CONFIG_SENSORS_SMSC47M192 is not set +# CONFIG_SENSORS_SMSC47B397 is not set +# CONFIG_SENSORS_ADS7828 is not set +# CONFIG_SENSORS_THMC50 is not set +# CONFIG_SENSORS_TMP401 is not set +# CONFIG_SENSORS_TMP421 is not set +# CONFIG_SENSORS_VT1211 is not set +# CONFIG_SENSORS_W83781D is not set +# CONFIG_SENSORS_W83791D is not set +# CONFIG_SENSORS_W83792D is not set +# CONFIG_SENSORS_W83793 is not set +# CONFIG_SENSORS_W83L785TS is not set +# CONFIG_SENSORS_W83L786NG is not set +# CONFIG_SENSORS_W83627HF is not set +# CONFIG_SENSORS_W83627EHF is not set +# CONFIG_SENSORS_LIS3_SPI is not set +CONFIG_THERMAL=y +CONFIG_THERMAL_HWMON=y +CONFIG_WATCHDOG=y +# CONFIG_WATCHDOG_NOWAYOUT is not set + +# +# Watchdog Device Drivers +# +# CONFIG_SOFT_WATCHDOG is not set +CONFIG_OMAP_WATCHDOG=y +CONFIG_TWL4030_WATCHDOG=y + +# +# USB-based Watchdog Cards +# +# CONFIG_USBPCWATCHDOG is not set +CONFIG_SSB_POSSIBLE=y + +# +# Sonics Silicon Backplane +# +# CONFIG_SSB is not set + +# +# Multifunction device drivers +# +# CONFIG_MFD_CORE is not set +# CONFIG_MFD_SM501 is not set +# CONFIG_MFD_ASIC3 is not set +# CONFIG_HTC_EGPIO is not set +# CONFIG_HTC_PASIC3 is not set +# CONFIG_TPS65010 is not set +CONFIG_TWL4030_CORE=y +# CONFIG_TWL4030_POWER is not set +# CONFIG_MFD_TMIO is not set +# CONFIG_MFD_T7L66XB is not set +# CONFIG_MFD_TC6387XB is not set +# CONFIG_MFD_TC6393XB is not set +# CONFIG_PMIC_DA903X is not set +# CONFIG_MFD_WM8400 is not set +# CONFIG_MFD_WM831X is not set +# CONFIG_MFD_WM8350_I2C is not set +# CONFIG_MFD_PCF50633 is not set +# CONFIG_MFD_MC13783 is not set +# CONFIG_AB3100_CORE is not set +# CONFIG_EZX_PCAP is not set +CONFIG_REGULATOR=y +# CONFIG_REGULATOR_DEBUG is not set +# CONFIG_REGULATOR_FIXED_VOLTAGE is not set +# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set +# CONFIG_REGULATOR_USERSPACE_CONSUMER is not set +# CONFIG_REGULATOR_BQ24022 is not set +# CONFIG_REGULATOR_MAX1586 is not set +CONFIG_REGULATOR_TWL4030=y +# CONFIG_REGULATOR_LP3971 is not set +# CONFIG_REGULATOR_TPS65023 is not set +# CONFIG_REGULATOR_TPS6507X is not set +CONFIG_MEDIA_SUPPORT=y + +# +# Multimedia core support +# +CONFIG_VIDEO_DEV=y +CONFIG_VIDEO_V4L2_COMMON=y +# CONFIG_VIDEO_ALLOW_V4L1 is not set +CONFIG_VIDEO_V4L1_COMPAT=y +# CONFIG_DVB_CORE is not set +CONFIG_VIDEO_MEDIA=y + +# +# Multimedia drivers +# +# CONFIG_MEDIA_ATTACH is not set +CONFIG_MEDIA_TUNER=y +# CONFIG_MEDIA_TUNER_CUSTOMISE is not set +CONFIG_MEDIA_TUNER_SIMPLE=y +CONFIG_MEDIA_TUNER_TDA8290=y +CONFIG_MEDIA_TUNER_TDA9887=y +CONFIG_MEDIA_TUNER_TEA5761=y +CONFIG_MEDIA_TUNER_TEA5767=y +CONFIG_MEDIA_TUNER_MT20XX=y +CONFIG_MEDIA_TUNER_XC2028=y +CONFIG_MEDIA_TUNER_XC5000=y +CONFIG_MEDIA_TUNER_MC44S803=y +CONFIG_VIDEO_V4L2=y +CONFIG_VIDEO_CAPTURE_DRIVERS=y +# CONFIG_VIDEO_ADV_DEBUG is not set +# CONFIG_VIDEO_FIXED_MINOR_RANGES is not set +# CONFIG_VIDEO_HELPER_CHIPS_AUTO is not set + +# +# Encoders/decoders and other helper chips +# + +# +# Audio decoders +# +# CONFIG_VIDEO_TVAUDIO is not set +# CONFIG_VIDEO_TDA7432 is not set +# CONFIG_VIDEO_TDA9840 is not set +# CONFIG_VIDEO_TDA9875 is not set +# CONFIG_VIDEO_TEA6415C is not set +# CONFIG_VIDEO_TEA6420 is not set +# CONFIG_VIDEO_MSP3400 is not set +# CONFIG_VIDEO_CS5345 is not set +# CONFIG_VIDEO_CS53L32A is not set +# CONFIG_VIDEO_M52790 is not set +# CONFIG_VIDEO_TLV320AIC23B is not set +# CONFIG_VIDEO_WM8775 is not set +# CONFIG_VIDEO_WM8739 is not set +# CONFIG_VIDEO_VP27SMPX is not set + +# +# RDS decoders +# +# CONFIG_VIDEO_SAA6588 is not set + +# +# Video decoders +# +# CONFIG_VIDEO_ADV7180 is not set +# CONFIG_VIDEO_BT819 is not set +# CONFIG_VIDEO_BT856 is not set +# CONFIG_VIDEO_BT866 is not set +# CONFIG_VIDEO_KS0127 is not set +# CONFIG_VIDEO_OV7670 is not set +# CONFIG_VIDEO_MT9V011 is not set +# CONFIG_VIDEO_TCM825X is not set +# CONFIG_VIDEO_SAA7110 is not set +# CONFIG_VIDEO_SAA711X is not set +# CONFIG_VIDEO_SAA717X is not set +# CONFIG_VIDEO_TVP514X is not set +# CONFIG_VIDEO_TVP5150 is not set +# CONFIG_VIDEO_VPX3220 is not set + +# +# Video and audio decoders +# +# CONFIG_VIDEO_CX25840 is not set + +# +# MPEG video encoders +# +# CONFIG_VIDEO_CX2341X is not set + +# +# Video encoders +# +# CONFIG_VIDEO_SAA7127 is not set +# CONFIG_VIDEO_SAA7185 is not set +# CONFIG_VIDEO_ADV7170 is not set +# CONFIG_VIDEO_ADV7175 is not set +# CONFIG_VIDEO_THS7303 is not set +# CONFIG_VIDEO_ADV7343 is not set + +# +# Video improvement chips +# +# CONFIG_VIDEO_UPD64031A is not set +# CONFIG_VIDEO_UPD64083 is not set +# CONFIG_VIDEO_VIVI is not set +# CONFIG_VIDEO_SAA5246A is not set +# CONFIG_VIDEO_SAA5249 is not set +# CONFIG_SOC_CAMERA is not set +CONFIG_V4L_USB_DRIVERS=y +CONFIG_USB_VIDEO_CLASS=m +CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV=y +CONFIG_USB_GSPCA=m +# CONFIG_USB_M5602 is not set +# CONFIG_USB_STV06XX is not set +# CONFIG_USB_GL860 is not set +# CONFIG_USB_GSPCA_CONEX is not set +# CONFIG_USB_GSPCA_ETOMS is not set +# CONFIG_USB_GSPCA_FINEPIX is not set +# CONFIG_USB_GSPCA_JEILINJ is not set +# CONFIG_USB_GSPCA_MARS is not set +# CONFIG_USB_GSPCA_MR97310A is not set +# CONFIG_USB_GSPCA_OV519 is not set +# CONFIG_USB_GSPCA_OV534 is not set +# CONFIG_USB_GSPCA_PAC207 is not set +# CONFIG_USB_GSPCA_PAC7311 is not set +# CONFIG_USB_GSPCA_SN9C20X is not set +# CONFIG_USB_GSPCA_SONIXB is not set +# CONFIG_USB_GSPCA_SONIXJ is not set +# CONFIG_USB_GSPCA_SPCA500 is not set +# CONFIG_USB_GSPCA_SPCA501 is not set +# CONFIG_USB_GSPCA_SPCA505 is not set +# CONFIG_USB_GSPCA_SPCA506 is not set +# CONFIG_USB_GSPCA_SPCA508 is not set +# CONFIG_USB_GSPCA_SPCA561 is not set +# CONFIG_USB_GSPCA_SQ905 is not set +# CONFIG_USB_GSPCA_SQ905C is not set +# CONFIG_USB_GSPCA_STK014 is not set +# CONFIG_USB_GSPCA_SUNPLUS is not set +# CONFIG_USB_GSPCA_T613 is not set +# CONFIG_USB_GSPCA_TV8532 is not set +# CONFIG_USB_GSPCA_VC032X is not set +# CONFIG_USB_GSPCA_ZC3XX is not set +# CONFIG_VIDEO_PVRUSB2 is not set +# CONFIG_VIDEO_HDPVR is not set +# CONFIG_VIDEO_EM28XX is not set +# CONFIG_VIDEO_CX231XX is not set +# CONFIG_VIDEO_USBVISION is not set +# CONFIG_USB_ET61X251 is not set +# CONFIG_USB_SN9C102 is not set +# CONFIG_USB_ZC0301 is not set +# CONFIG_USB_PWC_INPUT_EVDEV is not set +# CONFIG_USB_ZR364XX is not set +# CONFIG_USB_STKWEBCAM is not set +# CONFIG_USB_S2255 is not set +# CONFIG_RADIO_ADAPTERS is not set +# CONFIG_DAB is not set + +# +# Graphics support +# +# CONFIG_VGASTATE is not set +# CONFIG_VIDEO_OUTPUT_CONTROL is not set +CONFIG_FB=y +# CONFIG_FIRMWARE_EDID is not set +# CONFIG_FB_DDC is not set +# CONFIG_FB_BOOT_VESA_SUPPORT is not set +CONFIG_FB_CFB_FILLRECT=y +CONFIG_FB_CFB_COPYAREA=y +CONFIG_FB_CFB_IMAGEBLIT=y +# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set +# CONFIG_FB_SYS_FILLRECT is not set +# CONFIG_FB_SYS_COPYAREA is not set +# CONFIG_FB_SYS_IMAGEBLIT is not set +# CONFIG_FB_FOREIGN_ENDIAN is not set +# CONFIG_FB_SYS_FOPS is not set +# CONFIG_FB_SVGALIB is not set +# CONFIG_FB_MACMODES is not set +# CONFIG_FB_BACKLIGHT is not set +# CONFIG_FB_MODE_HELPERS is not set +# CONFIG_FB_TILEBLITTING is not set + +# +# Frame buffer hardware drivers +# +# CONFIG_FB_S1D13XXX is not set +# CONFIG_FB_VIRTUAL is not set +# CONFIG_FB_METRONOME is not set +# CONFIG_FB_MB862XX is not set +# CONFIG_FB_BROADSHEET is not set +# CONFIG_FB_OMAP_BOOTLOADER_INIT is not set +CONFIG_OMAP2_VRAM=y +CONFIG_OMAP2_VRFB=y +CONFIG_OMAP2_DSS=y +CONFIG_OMAP2_VRAM_SIZE=12 +CONFIG_OMAP2_DSS_DEBUG_SUPPORT=y +CONFIG_OMAP2_DSS_RFBI=y +CONFIG_OMAP2_DSS_VENC=y +# CONFIG_OMAP2_DSS_SDI is not set +CONFIG_OMAP2_DSS_DSI=y +# CONFIG_OMAP2_DSS_USE_DSI_PLL is not set +CONFIG_OMAP2_DSS_FAKE_VSYNC=y +CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK=0 +CONFIG_FB_OMAP2=y +CONFIG_FB_OMAP2_DEBUG_SUPPORT=y +CONFIG_FB_OMAP2_FORCE_AUTO_UPDATE=y +CONFIG_FB_OMAP2_NUM_FBS=3 + +# +# OMAP2/3 Display Device Drivers +# +CONFIG_PANEL_GENERIC=y +CONFIG_PANEL_SAMSUNG_LTE430WQ_F0C=y +CONFIG_PANEL_SHARP_LS037V7DW01=y +CONFIG_PANEL_TAAL=y +CONFIG_BACKLIGHT_LCD_SUPPORT=y +CONFIG_LCD_CLASS_DEVICE=y +# CONFIG_LCD_LMS283GF05 is not set +# CONFIG_LCD_LTV350QV is not set +# CONFIG_LCD_ILI9320 is not set +# CONFIG_LCD_TDO24M is not set +# CONFIG_LCD_VGG2432A4 is not set +CONFIG_LCD_PLATFORM=y +CONFIG_BACKLIGHT_CLASS_DEVICE=y +CONFIG_BACKLIGHT_GENERIC=y + +# +# Display device support +# +CONFIG_DISPLAY_SUPPORT=y + +# +# Display hardware drivers +# + +# +# Console display driver support +# +# CONFIG_VGA_CONSOLE is not set +CONFIG_DUMMY_CONSOLE=y +CONFIG_FRAMEBUFFER_CONSOLE=y +CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y +CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y +CONFIG_FONTS=y +CONFIG_FONT_8x8=y +CONFIG_FONT_8x16=y +# CONFIG_FONT_6x11 is not set +# CONFIG_FONT_7x14 is not set +# CONFIG_FONT_PEARL_8x8 is not set +# CONFIG_FONT_ACORN_8x8 is not set +# CONFIG_FONT_MINI_4x6 is not set +# CONFIG_FONT_SUN8x16 is not set +# CONFIG_FONT_SUN12x22 is not set +# CONFIG_FONT_10x18 is not set +# CONFIG_LOGO is not set +CONFIG_SOUND=y +CONFIG_SOUND_OSS_CORE=y +CONFIG_SOUND_OSS_CORE_PRECLAIM=y +CONFIG_SND=y +CONFIG_SND_TIMER=y +CONFIG_SND_PCM=y +# CONFIG_SND_HWDEP is not set +CONFIG_SND_JACK=y +CONFIG_SND_SEQUENCER=y +# CONFIG_SND_SEQ_DUMMY is not set +CONFIG_SND_OSSEMUL=y +# CONFIG_SND_MIXER_OSS is not set +# CONFIG_SND_PCM_OSS is not set +CONFIG_SND_SEQUENCER_OSS=y +# CONFIG_SND_HRTIMER is not set +# CONFIG_SND_DYNAMIC_MINORS is not set +# CONFIG_SND_SUPPORT_OLD_API is not set +CONFIG_SND_VERBOSE_PROCFS=y +# CONFIG_SND_VERBOSE_PRINTK is not set +# CONFIG_SND_DEBUG is not set +# CONFIG_SND_RAWMIDI_SEQ is not set +# CONFIG_SND_OPL3_LIB_SEQ is not set +# CONFIG_SND_OPL4_LIB_SEQ is not set +# CONFIG_SND_SBAWE_SEQ is not set +# CONFIG_SND_EMU10K1_SEQ is not set +# CONFIG_SND_DRIVERS is not set +# CONFIG_SND_ARM is not set +# CONFIG_SND_SPI is not set +CONFIG_SND_USB=y +# CONFIG_SND_USB_AUDIO is not set +# CONFIG_SND_USB_CAIAQ is not set +CONFIG_SND_SOC=y +CONFIG_SND_OMAP_SOC=y +CONFIG_SND_OMAP_SOC_MCBSP=y +CONFIG_SND_OMAP_SOC_OMAP3_BEAGLE=y +CONFIG_SND_SOC_I2C_AND_SPI=y +CONFIG_SND_SOC_ALL_CODECS=y +CONFIG_SND_SOC_WM_HUBS=y +CONFIG_SND_SOC_AD1836=y +CONFIG_SND_SOC_AD1938=y +CONFIG_SND_SOC_AD73311=y +CONFIG_SND_SOC_AK4104=y +CONFIG_SND_SOC_AK4535=y +CONFIG_SND_SOC_AK4642=y +CONFIG_SND_SOC_CS4270=y +CONFIG_SND_SOC_L3=y +CONFIG_SND_SOC_PCM3008=y +CONFIG_SND_SOC_SPDIF=y +CONFIG_SND_SOC_SSM2602=y +CONFIG_SND_SOC_TLV320AIC23=y +CONFIG_SND_SOC_TLV320AIC26=y +CONFIG_SND_SOC_TLV320AIC3X=y +CONFIG_SND_SOC_TWL4030=y +CONFIG_SND_SOC_UDA134X=y +CONFIG_SND_SOC_UDA1380=y +CONFIG_SND_SOC_WM8510=y +CONFIG_SND_SOC_WM8523=y +CONFIG_SND_SOC_WM8580=y +CONFIG_SND_SOC_WM8728=y +CONFIG_SND_SOC_WM8731=y +CONFIG_SND_SOC_WM8750=y +CONFIG_SND_SOC_WM8753=y +CONFIG_SND_SOC_WM8776=y +CONFIG_SND_SOC_WM8900=y +CONFIG_SND_SOC_WM8903=y +CONFIG_SND_SOC_WM8940=y +CONFIG_SND_SOC_WM8960=y +CONFIG_SND_SOC_WM8961=y +CONFIG_SND_SOC_WM8971=y +CONFIG_SND_SOC_WM8974=y +CONFIG_SND_SOC_WM8988=y +CONFIG_SND_SOC_WM8990=y +CONFIG_SND_SOC_WM8993=y +CONFIG_SND_SOC_WM9081=y +CONFIG_SND_SOC_MAX9877=y +# CONFIG_SOUND_PRIME is not set +CONFIG_HID_SUPPORT=y +CONFIG_HID=m +# CONFIG_HIDRAW is not set + +# +# USB Input Devices +# +CONFIG_USB_HID=m +# CONFIG_HID_PID is not set +# CONFIG_USB_HIDDEV is not set + +# +# USB HID Boot Protocol drivers +# +# CONFIG_USB_KBD is not set +# CONFIG_USB_MOUSE is not set + +# +# Special HID drivers +# +# CONFIG_HID_A4TECH is not set +# CONFIG_HID_APPLE is not set +# CONFIG_HID_BELKIN is not set +# CONFIG_HID_CHERRY is not set +# CONFIG_HID_CHICONY is not set +# CONFIG_HID_CYPRESS is not set +# CONFIG_HID_DRAGONRISE is not set +# CONFIG_HID_EZKEY is not set +# CONFIG_HID_KYE is not set +# CONFIG_HID_GYRATION is not set +# CONFIG_HID_TWINHAN is not set +# CONFIG_HID_KENSINGTON is not set +# CONFIG_HID_LOGITECH is not set +# CONFIG_HID_MICROSOFT is not set +# CONFIG_HID_MONTEREY is not set +# CONFIG_HID_NTRIG is not set +# CONFIG_HID_PANTHERLORD is not set +# CONFIG_HID_PETALYNX is not set +# CONFIG_HID_SAMSUNG is not set +# CONFIG_HID_SONY is not set +# CONFIG_HID_SUNPLUS is not set +# CONFIG_HID_GREENASIA is not set +# CONFIG_HID_SMARTJOYPLUS is not set +# CONFIG_HID_TOPSEED is not set +# CONFIG_HID_THRUSTMASTER is not set +# CONFIG_HID_ZEROPLUS is not set +CONFIG_USB_SUPPORT=y +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y +CONFIG_USB_ARCH_HAS_EHCI=y +CONFIG_USB=y +CONFIG_USB_DEBUG=y +CONFIG_USB_ANNOUNCE_NEW_DEVICES=y + +# +# Miscellaneous USB options +# +CONFIG_USB_DEVICEFS=y +CONFIG_USB_DEVICE_CLASS=y +# CONFIG_USB_DYNAMIC_MINORS is not set +CONFIG_USB_SUSPEND=y +# CONFIG_USB_OTG is not set +# CONFIG_USB_OTG_WHITELIST is not set +# CONFIG_USB_OTG_BLACKLIST_HUB is not set +# CONFIG_USB_MON is not set +# CONFIG_USB_WUSB is not set +# CONFIG_USB_WUSB_CBAF is not set + +# +# USB Host Controller Drivers +# +# CONFIG_USB_C67X00_HCD is not set +CONFIG_USB_EHCI_HCD=y +CONFIG_USB_EHCI_ROOT_HUB_TT=y +# CONFIG_USB_EHCI_TT_NEWSCHED is not set +# CONFIG_USB_OXU210HP_HCD is not set +# CONFIG_USB_ISP116X_HCD is not set +# CONFIG_USB_ISP1760_HCD is not set +# CONFIG_USB_ISP1362_HCD is not set +CONFIG_USB_OHCI_HCD=m +# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set +# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set +CONFIG_USB_OHCI_LITTLE_ENDIAN=y +# CONFIG_USB_SL811_HCD is not set +# CONFIG_USB_R8A66597_HCD is not set +# CONFIG_USB_HWA_HCD is not set +CONFIG_USB_MUSB_HDRC=y +CONFIG_USB_MUSB_SOC=y + +# +# OMAP 343x high speed USB support +# +# CONFIG_USB_MUSB_HOST is not set +CONFIG_USB_MUSB_PERIPHERAL=y +# CONFIG_USB_MUSB_OTG is not set +CONFIG_USB_GADGET_MUSB_HDRC=y +# CONFIG_MUSB_PIO_ONLY is not set +CONFIG_USB_INVENTRA_DMA=y +# CONFIG_USB_TI_CPPI_DMA is not set +# CONFIG_USB_MUSB_DEBUG is not set + +# +# USB Device Class drivers +# +# CONFIG_USB_ACM is not set +# CONFIG_USB_PRINTER is not set +# CONFIG_USB_WDM is not set +# CONFIG_USB_TMC is not set + +# +# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may +# + +# +# also be needed; see USB_STORAGE Help for more info +# +CONFIG_USB_STORAGE=y +# CONFIG_USB_STORAGE_DEBUG is not set +CONFIG_USB_STORAGE_DATAFAB=y +CONFIG_USB_STORAGE_FREECOM=y +# CONFIG_USB_STORAGE_ISD200 is not set +CONFIG_USB_STORAGE_USBAT=y +CONFIG_USB_STORAGE_SDDR09=y +CONFIG_USB_STORAGE_SDDR55=y +CONFIG_USB_STORAGE_JUMPSHOT=y +CONFIG_USB_STORAGE_ALAUDA=y +# CONFIG_USB_STORAGE_ONETOUCH is not set +CONFIG_USB_STORAGE_KARMA=y +# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set +# CONFIG_USB_LIBUSUAL is not set + +# +# USB Imaging devices +# +# CONFIG_USB_MDC800 is not set +# CONFIG_USB_MICROTEK is not set + +# +# USB port drivers +# +CONFIG_USB_SERIAL=y +# CONFIG_USB_SERIAL_CONSOLE is not set +CONFIG_USB_EZUSB=y +CONFIG_USB_SERIAL_GENERIC=y +# CONFIG_USB_SERIAL_AIRCABLE is not set +# CONFIG_USB_SERIAL_ARK3116 is not set +# CONFIG_USB_SERIAL_BELKIN is not set +# CONFIG_USB_SERIAL_CH341 is not set +# CONFIG_USB_SERIAL_WHITEHEAT is not set +# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set +# CONFIG_USB_SERIAL_CP210X is not set +# CONFIG_USB_SERIAL_CYPRESS_M8 is not set +# CONFIG_USB_SERIAL_EMPEG is not set +CONFIG_USB_SERIAL_FTDI_SIO=y +# CONFIG_USB_SERIAL_FUNSOFT is not set +# CONFIG_USB_SERIAL_VISOR is not set +# CONFIG_USB_SERIAL_IPAQ is not set +# CONFIG_USB_SERIAL_IR is not set +# CONFIG_USB_SERIAL_EDGEPORT is not set +# CONFIG_USB_SERIAL_EDGEPORT_TI is not set +# CONFIG_USB_SERIAL_GARMIN is not set +# CONFIG_USB_SERIAL_IPW is not set +# CONFIG_USB_SERIAL_IUU is not set +# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set +# CONFIG_USB_SERIAL_KEYSPAN is not set +# CONFIG_USB_SERIAL_KLSI is not set +# CONFIG_USB_SERIAL_KOBIL_SCT is not set +# CONFIG_USB_SERIAL_MCT_U232 is not set +# CONFIG_USB_SERIAL_MOS7720 is not set +# CONFIG_USB_SERIAL_MOS7840 is not set +# CONFIG_USB_SERIAL_MOTOROLA is not set +# CONFIG_USB_SERIAL_NAVMAN is not set +CONFIG_USB_SERIAL_PL2303=y +# CONFIG_USB_SERIAL_OTI6858 is not set +# CONFIG_USB_SERIAL_QUALCOMM is not set +# CONFIG_USB_SERIAL_SPCP8X5 is not set +# CONFIG_USB_SERIAL_HP4X is not set +# CONFIG_USB_SERIAL_SAFE is not set +# CONFIG_USB_SERIAL_SIEMENS_MPI is not set +# CONFIG_USB_SERIAL_SIERRAWIRELESS is not set +# CONFIG_USB_SERIAL_SYMBOL is not set +# CONFIG_USB_SERIAL_TI is not set +# CONFIG_USB_SERIAL_CYBERJACK is not set +# CONFIG_USB_SERIAL_XIRCOM is not set +# CONFIG_USB_SERIAL_OPTION is not set +# CONFIG_USB_SERIAL_OMNINET is not set +# CONFIG_USB_SERIAL_OPTICON is not set +# CONFIG_USB_SERIAL_DEBUG is not set + +# +# USB Miscellaneous drivers +# +# CONFIG_USB_EMI62 is not set +# CONFIG_USB_EMI26 is not set +# CONFIG_USB_ADUTUX is not set +# CONFIG_USB_SEVSEG is not set +# CONFIG_USB_RIO500 is not set +# CONFIG_USB_LEGOTOWER is not set +# CONFIG_USB_LCD is not set +# CONFIG_USB_BERRY_CHARGE is not set +# CONFIG_USB_LED is not set +# CONFIG_USB_CYPRESS_CY7C63 is not set +# CONFIG_USB_CYTHERM is not set +# CONFIG_USB_IDMOUSE is not set +# CONFIG_USB_FTDI_ELAN is not set +# CONFIG_USB_APPLEDISPLAY is not set +# CONFIG_USB_SISUSBVGA is not set +# CONFIG_USB_LD is not set +# CONFIG_USB_TRANCEVIBRATOR is not set +# CONFIG_USB_IOWARRIOR is not set +# CONFIG_USB_TEST is not set +# CONFIG_USB_ISIGHTFW is not set +# CONFIG_USB_VST is not set +CONFIG_USB_GADGET=y +CONFIG_USB_GADGET_DEBUG=y +# CONFIG_USB_GADGET_DEBUG_FILES is not set +# CONFIG_USB_GADGET_DEBUG_FS is not set +CONFIG_USB_GADGET_VBUS_DRAW=500 +CONFIG_USB_GADGET_SELECTED=y +# CONFIG_USB_GADGET_AT91 is not set +# CONFIG_USB_GADGET_ATMEL_USBA is not set +# CONFIG_USB_GADGET_FSL_USB2 is not set +# CONFIG_USB_GADGET_LH7A40X is not set +# CONFIG_USB_GADGET_OMAP is not set +# CONFIG_USB_GADGET_PXA25X is not set +# CONFIG_USB_GADGET_R8A66597 is not set +# CONFIG_USB_GADGET_PXA27X is not set +# CONFIG_USB_GADGET_S3C_HSOTG is not set +# CONFIG_USB_GADGET_IMX is not set +# CONFIG_USB_GADGET_S3C2410 is not set +# CONFIG_USB_GADGET_M66592 is not set +# CONFIG_USB_GADGET_AMD5536UDC is not set +# CONFIG_USB_GADGET_FSL_QE is not set +# CONFIG_USB_GADGET_CI13XXX is not set +# CONFIG_USB_GADGET_NET2280 is not set +# CONFIG_USB_GADGET_GOKU is not set +# CONFIG_USB_GADGET_LANGWELL is not set +# CONFIG_USB_GADGET_DUMMY_HCD is not set +CONFIG_USB_GADGET_DUALSPEED=y +# CONFIG_USB_ZERO is not set +# CONFIG_USB_AUDIO is not set +# CONFIG_USB_ETH is not set +# CONFIG_USB_GADGETFS is not set +# CONFIG_USB_FILE_STORAGE is not set +CONFIG_USB_G_SERIAL=y +# CONFIG_USB_MIDI_GADGET is not set +# CONFIG_USB_G_PRINTER is not set +# CONFIG_USB_CDC_COMPOSITE is not set + +# +# OTG and related infrastructure +# +CONFIG_USB_OTG_UTILS=y +# CONFIG_USB_GPIO_VBUS is not set +# CONFIG_ISP1301_OMAP is not set +CONFIG_TWL4030_USB=y +# CONFIG_NOP_USB_XCEIV is not set +CONFIG_MMC=y +# CONFIG_MMC_DEBUG is not set +# CONFIG_MMC_UNSAFE_RESUME is not set + +# +# MMC/SD/SDIO Card Drivers +# +CONFIG_MMC_BLOCK=y +CONFIG_MMC_BLOCK_BOUNCE=y +# CONFIG_SDIO_UART is not set +# CONFIG_MMC_TEST is not set + +# +# MMC/SD/SDIO Host Controller Drivers +# +# CONFIG_MMC_SDHCI is not set +CONFIG_MMC_OMAP=y +CONFIG_MMC_OMAP_HS=y +# CONFIG_MMC_AT91 is not set +# CONFIG_MMC_ATMELMCI is not set +CONFIG_MMC_SPI=y +# CONFIG_MEMSTICK is not set +CONFIG_NEW_LEDS=y +CONFIG_LEDS_CLASS=y + +# +# LED drivers +# +# CONFIG_LEDS_PCA9532 is not set +# CONFIG_LEDS_GPIO is not set +# CONFIG_LEDS_LP3944 is not set +# CONFIG_LEDS_PCA955X is not set +# CONFIG_LEDS_DAC124S085 is not set +# CONFIG_LEDS_BD2802 is not set + +# +# LED Triggers +# +# CONFIG_LEDS_TRIGGERS is not set +# CONFIG_ACCESSIBILITY is not set +CONFIG_RTC_LIB=y +CONFIG_RTC_CLASS=y +CONFIG_RTC_HCTOSYS=y +CONFIG_RTC_HCTOSYS_DEVICE="rtc0" +# CONFIG_RTC_DEBUG is not set + +# +# RTC interfaces +# +CONFIG_RTC_INTF_SYSFS=y +CONFIG_RTC_INTF_PROC=y +CONFIG_RTC_INTF_DEV=y +# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set +# CONFIG_RTC_DRV_TEST is not set + +# +# I2C RTC drivers +# +# CONFIG_RTC_DRV_DS1307 is not set +# CONFIG_RTC_DRV_DS1374 is not set +# CONFIG_RTC_DRV_DS1672 is not set +# CONFIG_RTC_DRV_MAX6900 is not set +# CONFIG_RTC_DRV_RS5C372 is not set +# CONFIG_RTC_DRV_ISL1208 is not set +# CONFIG_RTC_DRV_X1205 is not set +# CONFIG_RTC_DRV_PCF8563 is not set +# CONFIG_RTC_DRV_PCF8583 is not set +# CONFIG_RTC_DRV_M41T80 is not set +CONFIG_RTC_DRV_TWL4030=y +# CONFIG_RTC_DRV_S35390A is not set +# CONFIG_RTC_DRV_FM3130 is not set +# CONFIG_RTC_DRV_RX8581 is not set +# CONFIG_RTC_DRV_RX8025 is not set + +# +# SPI RTC drivers +# +# CONFIG_RTC_DRV_M41T94 is not set +# CONFIG_RTC_DRV_DS1305 is not set +# CONFIG_RTC_DRV_DS1390 is not set +# CONFIG_RTC_DRV_MAX6902 is not set +# CONFIG_RTC_DRV_R9701 is not set +# CONFIG_RTC_DRV_RS5C348 is not set +# CONFIG_RTC_DRV_DS3234 is not set +# CONFIG_RTC_DRV_PCF2123 is not set + +# +# Platform RTC drivers +# +# CONFIG_RTC_DRV_CMOS is not set +# CONFIG_RTC_DRV_DS1286 is not set +# CONFIG_RTC_DRV_DS1511 is not set +# CONFIG_RTC_DRV_DS1553 is not set +# CONFIG_RTC_DRV_DS1742 is not set +# CONFIG_RTC_DRV_STK17TA8 is not set +# CONFIG_RTC_DRV_M48T86 is not set +# CONFIG_RTC_DRV_M48T35 is not set +# CONFIG_RTC_DRV_M48T59 is not set +# CONFIG_RTC_DRV_BQ4802 is not set +# CONFIG_RTC_DRV_V3020 is not set +# CONFIG_RTC_DRV_RTC7301 is not set + +# +# on-CPU RTC drivers +# +# CONFIG_DMADEVICES is not set +# CONFIG_AUXDISPLAY is not set +# CONFIG_UIO is not set + +# +# TI VLYNQ +# +CONFIG_STAGING=y +# CONFIG_STAGING_EXCLUDE_BUILD is not set +# CONFIG_USB_IP_COMMON is not set +# CONFIG_ECHO is not set +# CONFIG_COMEDI is not set +# CONFIG_ASUS_OLED is not set +# CONFIG_INPUT_MIMIO is not set +# CONFIG_TRANZPORT is not set + +# +# Android +# +# CONFIG_ANDROID is not set + +# +# Qualcomm MSM Camera And Video +# + +# +# Camera Sensor Selection +# +# CONFIG_INPUT_GPIO is not set +# CONFIG_DST is not set +# CONFIG_POHMELFS is not set +# CONFIG_PLAN9AUTH is not set +# CONFIG_LINE6_USB is not set +# CONFIG_USB_SERIAL_QUATECH2 is not set +# CONFIG_USB_SERIAL_QUATECH_USB2 is not set +# CONFIG_FB_UDL is not set + +# +# RAR Register Driver +# +# CONFIG_RAR_REGISTER is not set +# CONFIG_IIO is not set + +# +# CBUS support +# +# CONFIG_CBUS is not set + +# +# File systems +# +CONFIG_EXT2_FS=y +# CONFIG_EXT2_FS_XATTR is not set +# CONFIG_EXT2_FS_XIP is not set +CONFIG_EXT3_FS=y +# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set +# CONFIG_EXT3_FS_XATTR is not set +CONFIG_EXT4_FS=m +CONFIG_EXT4_FS_XATTR=y +CONFIG_EXT4_FS_POSIX_ACL=y +CONFIG_EXT4_FS_SECURITY=y +# CONFIG_EXT4_DEBUG is not set +CONFIG_JBD=y +# CONFIG_JBD_DEBUG is not set +CONFIG_JBD2=m +# CONFIG_JBD2_DEBUG is not set +CONFIG_FS_MBCACHE=m +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +CONFIG_FS_POSIX_ACL=y +CONFIG_XFS_FS=m +# CONFIG_XFS_QUOTA is not set +# CONFIG_XFS_POSIX_ACL is not set +# CONFIG_XFS_RT is not set +# CONFIG_XFS_DEBUG is not set +# CONFIG_OCFS2_FS is not set +# CONFIG_BTRFS_FS is not set +# CONFIG_NILFS2_FS is not set +# CONFIG_YAFFS_FS is not set +CONFIG_FILE_LOCKING=y +CONFIG_FSNOTIFY=y +CONFIG_DNOTIFY=y +CONFIG_INOTIFY=y +CONFIG_INOTIFY_USER=y +# CONFIG_QUOTA is not set +# CONFIG_UNION_MOUNT is not set +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set +CONFIG_FUSE_FS=m +# CONFIG_CUSE is not set + +# +# Caches +# +# CONFIG_FSCACHE is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +CONFIG_FAT_FS=y +CONFIG_MSDOS_FS=y +CONFIG_VFAT_FS=y +CONFIG_FAT_DEFAULT_CODEPAGE=437 +CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_SYSCTL=y +CONFIG_PROC_PAGE_MONITOR=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +# CONFIG_TMPFS_POSIX_ACL is not set +# CONFIG_HUGETLB_PAGE is not set +# CONFIG_CONFIGFS_FS is not set +CONFIG_MISC_FILESYSTEMS=y +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +CONFIG_HFSPLUS_FS=m +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +CONFIG_JFFS2_FS=y +CONFIG_JFFS2_FS_DEBUG=0 +CONFIG_JFFS2_FS_WRITEBUFFER=y +# CONFIG_JFFS2_FS_WBUF_VERIFY is not set +# CONFIG_JFFS2_SUMMARY is not set +# CONFIG_JFFS2_FS_XATTR is not set +# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set +CONFIG_JFFS2_ZLIB=y +# CONFIG_JFFS2_LZO is not set +CONFIG_JFFS2_RTIME=y +# CONFIG_JFFS2_RUBIN is not set +# CONFIG_CRAMFS is not set +CONFIG_SQUASHFS=y +CONFIG_SQUASHFS_LZMA=y +# CONFIG_SQUASHFS_EMBEDDED is not set +CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3 +# CONFIG_VXFS_FS is not set +CONFIG_MINI_FO=y +# CONFIG_MINIX_FS is not set +# CONFIG_OMFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set +# CONFIG_NETWORK_FILESYSTEMS is not set +CONFIG_EXPORTFS=m + +# +# Partition Types +# +CONFIG_PARTITION_ADVANCED=y +# CONFIG_ACORN_PARTITION is not set +# CONFIG_OSF_PARTITION is not set +# CONFIG_AMIGA_PARTITION is not set +# CONFIG_ATARI_PARTITION is not set +# CONFIG_MAC_PARTITION is not set +CONFIG_MSDOS_PARTITION=y +# CONFIG_BSD_DISKLABEL is not set +# CONFIG_MINIX_SUBPARTITION is not set +# CONFIG_SOLARIS_X86_PARTITION is not set +# CONFIG_UNIXWARE_DISKLABEL is not set +# CONFIG_LDM_PARTITION is not set +# CONFIG_SGI_PARTITION is not set +# CONFIG_ULTRIX_PARTITION is not set +# CONFIG_SUN_PARTITION is not set +# CONFIG_KARMA_PARTITION is not set +# CONFIG_EFI_PARTITION is not set +# CONFIG_SYSV68_PARTITION is not set +CONFIG_NLS=y +CONFIG_NLS_DEFAULT="iso8859-1" +CONFIG_NLS_CODEPAGE_437=y +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +# CONFIG_NLS_CODEPAGE_850 is not set +# CONFIG_NLS_CODEPAGE_852 is not set +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +# CONFIG_NLS_CODEPAGE_936 is not set +# CONFIG_NLS_CODEPAGE_950 is not set +# CONFIG_NLS_CODEPAGE_932 is not set +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_CODEPAGE_1250 is not set +# CONFIG_NLS_CODEPAGE_1251 is not set +# CONFIG_NLS_ASCII is not set +CONFIG_NLS_ISO8859_1=y +# CONFIG_NLS_ISO8859_2 is not set +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_13 is not set +# CONFIG_NLS_ISO8859_14 is not set +# CONFIG_NLS_ISO8859_15 is not set +# CONFIG_NLS_KOI8_R is not set +# CONFIG_NLS_KOI8_U is not set +CONFIG_NLS_UTF8=m +# CONFIG_DLM is not set + +# +# Kernel hacking +# +# CONFIG_PRINTK_TIME is not set +CONFIG_ENABLE_WARN_DEPRECATED=y +CONFIG_ENABLE_MUST_CHECK=y +CONFIG_FRAME_WARN=1024 +CONFIG_MAGIC_SYSRQ=y +CONFIG_STRIP_ASM_SYMS=y +# CONFIG_UNUSED_SYMBOLS is not set +CONFIG_DEBUG_FS=y +# CONFIG_HEADERS_CHECK is not set +CONFIG_DEBUG_KERNEL=y +# CONFIG_DEBUG_SHIRQ is not set +CONFIG_DETECT_SOFTLOCKUP=y +# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set +CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0 +CONFIG_DETECT_HUNG_TASK=y +# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set +CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0 +CONFIG_SCHED_DEBUG=y +# CONFIG_SCHEDSTATS is not set +# CONFIG_TIMER_STATS is not set +# CONFIG_DEBUG_OBJECTS is not set +# CONFIG_DEBUG_SLAB is not set +# CONFIG_DEBUG_KMEMLEAK is not set +# CONFIG_DEBUG_RT_MUTEXES is not set +# CONFIG_RT_MUTEX_TESTER is not set +# CONFIG_DEBUG_SPINLOCK is not set +CONFIG_DEBUG_MUTEXES=y +# CONFIG_DEBUG_LOCK_ALLOC is not set +# CONFIG_PROVE_LOCKING is not set +# CONFIG_LOCK_STAT is not set +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set +# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set +# CONFIG_DEBUG_KOBJECT is not set +# CONFIG_DEBUG_BUGVERBOSE is not set +CONFIG_DEBUG_INFO=y +# CONFIG_DEBUG_VM is not set +# CONFIG_DEBUG_WRITECOUNT is not set +# CONFIG_DEBUG_MEMORY_INIT is not set +# CONFIG_DEBUG_LIST is not set +# CONFIG_DEBUG_SG is not set +# CONFIG_DEBUG_NOTIFIERS is not set +# CONFIG_DEBUG_CREDENTIALS is not set +CONFIG_FRAME_POINTER=y +# CONFIG_BOOT_PRINTK_DELAY is not set +# CONFIG_RCU_TORTURE_TEST is not set +# CONFIG_RCU_CPU_STALL_DETECTOR is not set +# CONFIG_BACKTRACE_SELF_TEST is not set +# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set +# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set +# CONFIG_FAULT_INJECTION is not set +# CONFIG_LATENCYTOP is not set +# CONFIG_PAGE_POISONING is not set +CONFIG_HAVE_FUNCTION_TRACER=y +CONFIG_TRACING_SUPPORT=y +# CONFIG_FTRACE is not set +# CONFIG_DYNAMIC_DEBUG is not set +# CONFIG_SAMPLES is not set +CONFIG_HAVE_ARCH_KGDB=y +# CONFIG_KGDB is not set +# CONFIG_ARM_UNWIND is not set +# CONFIG_DEBUG_USER is not set +# CONFIG_DEBUG_ERRORS is not set +# CONFIG_DEBUG_STACK_USAGE is not set +# CONFIG_DEBUG_LL is not set + +# +# Security options +# +# CONFIG_KEYS is not set +# CONFIG_SECURITY is not set +# CONFIG_SECURITYFS is not set +# CONFIG_SECURITY_FILE_CAPABILITIES is not set +CONFIG_CRYPTO=y + +# +# Crypto core or helper +# +CONFIG_CRYPTO_ALGAPI=y +CONFIG_CRYPTO_ALGAPI2=y +CONFIG_CRYPTO_AEAD=m +CONFIG_CRYPTO_AEAD2=y +CONFIG_CRYPTO_BLKCIPHER=y +CONFIG_CRYPTO_BLKCIPHER2=y +CONFIG_CRYPTO_HASH=y +CONFIG_CRYPTO_HASH2=y +# CONFIG_CRYPTO_RNG is not set +CONFIG_CRYPTO_RNG2=y +CONFIG_CRYPTO_PCOMP=y +CONFIG_CRYPTO_MANAGER=y +CONFIG_CRYPTO_MANAGER2=y +# CONFIG_CRYPTO_GF128MUL is not set +# CONFIG_CRYPTO_NULL is not set +CONFIG_CRYPTO_WORKQUEUE=y +# CONFIG_CRYPTO_CRYPTD is not set +# CONFIG_CRYPTO_AUTHENC is not set +# CONFIG_CRYPTO_TEST is not set + +# +# Authenticated Encryption with Associated Data +# +# CONFIG_CRYPTO_CCM is not set +# CONFIG_CRYPTO_GCM is not set +# CONFIG_CRYPTO_SEQIV is not set + +# +# Block modes +# +CONFIG_CRYPTO_CBC=y +# CONFIG_CRYPTO_CTR is not set +# CONFIG_CRYPTO_CTS is not set +CONFIG_CRYPTO_ECB=m +# CONFIG_CRYPTO_LRW is not set +CONFIG_CRYPTO_PCBC=m +# CONFIG_CRYPTO_XTS is not set + +# +# Hash modes +# +CONFIG_CRYPTO_HMAC=m +# CONFIG_CRYPTO_XCBC is not set +# CONFIG_CRYPTO_VMAC is not set + +# +# Digest +# +CONFIG_CRYPTO_CRC32C=y +# CONFIG_CRYPTO_GHASH is not set +# CONFIG_CRYPTO_MD4 is not set +CONFIG_CRYPTO_MD5=y +# CONFIG_CRYPTO_MICHAEL_MIC is not set +# CONFIG_CRYPTO_RMD128 is not set +# CONFIG_CRYPTO_RMD160 is not set +# CONFIG_CRYPTO_RMD256 is not set +# CONFIG_CRYPTO_RMD320 is not set +# CONFIG_CRYPTO_SHA1 is not set +# CONFIG_CRYPTO_SHA256 is not set +# CONFIG_CRYPTO_SHA512 is not set +# CONFIG_CRYPTO_TGR192 is not set +# CONFIG_CRYPTO_WP512 is not set + +# +# Ciphers +# +CONFIG_CRYPTO_AES=m +# CONFIG_CRYPTO_ANUBIS is not set +CONFIG_CRYPTO_ARC4=m +# CONFIG_CRYPTO_BLOWFISH is not set +# CONFIG_CRYPTO_CAMELLIA is not set +# CONFIG_CRYPTO_CAST5 is not set +# CONFIG_CRYPTO_CAST6 is not set +CONFIG_CRYPTO_DES=y +# CONFIG_CRYPTO_FCRYPT is not set +# CONFIG_CRYPTO_KHAZAD is not set +# CONFIG_CRYPTO_SALSA20 is not set +# CONFIG_CRYPTO_SEED is not set +# CONFIG_CRYPTO_SERPENT is not set +# CONFIG_CRYPTO_TEA is not set +# CONFIG_CRYPTO_TWOFISH is not set + +# +# Compression +# +CONFIG_CRYPTO_DEFLATE=m +CONFIG_CRYPTO_ZLIB=y +# CONFIG_CRYPTO_LZO is not set + +# +# Random Number Generation +# +# CONFIG_CRYPTO_ANSI_CPRNG is not set + +# +# OCF Configuration +# +# CONFIG_OCF_OCF is not set +CONFIG_CRYPTO_HW=y +# CONFIG_BINARY_PRINTF is not set + +# +# Library routines +# +CONFIG_BITREVERSE=y +CONFIG_GENERIC_FIND_LAST_BIT=y +CONFIG_CRC_CCITT=y +CONFIG_CRC16=m +# CONFIG_CRC_T10DIF is not set +CONFIG_CRC_ITU_T=y +CONFIG_CRC32=y +CONFIG_CRC7=y +CONFIG_LIBCRC32C=y +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=y +CONFIG_DECOMPRESS_LZMA=y +CONFIG_DECOMPRESS_LZMA_NEEDED=y +CONFIG_TEXTSEARCH=y +# CONFIG_TEXTSEARCH_KMP is not set +# CONFIG_TEXTSEARCH_BM is not set +# CONFIG_TEXTSEARCH_FSM is not set +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT=y +CONFIG_HAS_DMA=y +CONFIG_NLATTR=y diff --git a/target/linux/omap35xx/files/boot-mmc.cmd b/target/linux/omap35xx/files/boot-mmc.cmd new file mode 100644 index 000000000..5e3b34845 --- /dev/null +++ b/target/linux/omap35xx/files/boot-mmc.cmd @@ -0,0 +1,10 @@ +echo ----------------------------- +echo u-boot.cmd +echo Kernel: MMC0P1:uImage +echo RootFS: MMC0P2 +echo VideoMode: 640x480@60 +echo VideoSpec: omapfb:vram:2M,vram:4M +echo ----------------------------- +setenv bootargs 'console=ttyS2,115200n8 console=tty0 root=/dev/mmcblk0p2 rw rootwait nohz=off video=omapfb:vram:1M,vxres:640,vyres:480' +fatload mmc 0 83000000 uImage +bootm 83000000 diff --git a/target/linux/omap35xx/generic/profiles/beagleboard.mk b/target/linux/omap35xx/generic/profiles/beagleboard.mk new file mode 100644 index 000000000..69ecdbb82 --- /dev/null +++ b/target/linux/omap35xx/generic/profiles/beagleboard.mk @@ -0,0 +1,16 @@ +# +# Copyright (C) 2006 - 2009 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +define Profile/Beagleboard + NAME:=beagleboard + FEATURES:=ext2 usb +endef + +define Profile/Beagleboard/Description + Beagleboard - www.beagleboard.org +endef +$(eval $(call Profile,Beagleboard)) diff --git a/target/linux/omap35xx/generic/target.mk b/target/linux/omap35xx/generic/target.mk new file mode 100644 index 000000000..30d8f2332 --- /dev/null +++ b/target/linux/omap35xx/generic/target.mk @@ -0,0 +1,6 @@ +BOARDNAME:=Generic + +define Target/Description + Build firmware images for ti omap35xx based boards +endef + diff --git a/target/linux/omap35xx/image/Makefile b/target/linux/omap35xx/image/Makefile new file mode 100755 index 000000000..14b34174d --- /dev/null +++ b/target/linux/omap35xx/image/Makefile @@ -0,0 +1,36 @@ +# +# Copyright (C) 2006 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +include $(TOPDIR)/rules.mk +include $(INCLUDE_DIR)/image.mk + +JFFS2_BLOCKSIZE=128k +JFFS2OPTS += --little-endian --pagesize=0x800 --no-cleanmarkers --pad +MAKE += -j5 + +define Image/BuildKernel + $(TARGET_CROSS)objcopy -O binary -R .note -R .comment -S $(LINUX_DIR)/arch/arm/boot/compressed/vmlinux linux.bin + mkimage -A arm -O linux -T kernel -C none -a 80008000 -e 80008000 -n "OpenWRT Kernel Image beagleboard" -d linux.bin uImage + mkimage -A arm -O linux -T script -C none -a 0 -e 0 -n 'uImage.bin+mmc2' -d ../files/boot-mmc.cmd boot.scr + + mv uImage $(BIN_DIR)/openwrt-$(BOARD)-$(KERNEL)-uImage + mv boot.scr $(BIN_DIR)/boot.scr + rm linux.bin +endef + +define Image/Build/squashfs + $(call prepare_generic_squashfs,$(BIN_DIR)/openwrt-$(BOARD)-$(KERNEL)-root.$(1)) +endef + +define Image/Build + $(CP) $(KDIR)/root.$(1) $(BIN_DIR)/openwrt-$(BOARD)-$(KERNEL)-root.$(1) + PADDING="true" PATH="$(TARGET_PATH)" ./gen_image.sh $(BIN_DIR)/openwrt-$(BOARD)-$(1).image 4 $(KDIR)/root.bootscript 240 $(KDIR)/root.$(1) + $(call Image/Build/$(1),$(1)) +endef + + +$(eval $(call BuildImage)) diff --git a/target/linux/olpc/image/gen_image.sh b/target/linux/omap35xx/image/gen_image.sh similarity index 100% rename from target/linux/olpc/image/gen_image.sh rename to target/linux/omap35xx/image/gen_image.sh diff --git a/target/linux/omap35xx/patches-2.6.32/001-DSS2.patch b/target/linux/omap35xx/patches-2.6.32/001-DSS2.patch new file mode 100644 index 000000000..ca760bc60 --- /dev/null +++ b/target/linux/omap35xx/patches-2.6.32/001-DSS2.patch @@ -0,0 +1,22831 @@ +diff --git a/Documentation/arm/OMAP/DSS b/Documentation/arm/OMAP/DSS +new file mode 100644 +index 0000000..0af0e9e +--- /dev/null ++++ b/Documentation/arm/OMAP/DSS +@@ -0,0 +1,317 @@ ++OMAP2/3 Display Subsystem ++------------------------- ++ ++This is an almost total rewrite of the OMAP FB driver in drivers/video/omap ++(let's call it DSS1). The main differences between DSS1 and DSS2 are DSI, ++TV-out and multiple display support, but there are lots of small improvements ++also. ++ ++The DSS2 driver (omapdss module) is in arch/arm/plat-omap/dss/, and the FB, ++panel and controller drivers are in drivers/video/omap2/. DSS1 and DSS2 live ++currently side by side, you can choose which one to use. ++ ++Features ++-------- ++ ++Working and tested features include: ++ ++- MIPI DPI (parallel) output ++- MIPI DSI output in command mode ++- MIPI DBI (RFBI) output ++- SDI output ++- TV output ++- All pieces can be compiled as a module or inside kernel ++- Use DISPC to update any of the outputs ++- Use CPU to update RFBI or DSI output ++- OMAP DISPC planes ++- RGB16, RGB24 packed, RGB24 unpacked ++- YUV2, UYVY ++- Scaling ++- Adjusting DSS FCK to find a good pixel clock ++- Use DSI DPLL to create DSS FCK ++ ++Tested boards include: ++- OMAP3 SDP board ++- Beagle board ++- N810 ++ ++omapdss driver ++-------------- ++ ++The DSS driver does not itself have any support for Linux framebuffer, V4L or ++such like the current ones, but it has an internal kernel API that upper level ++drivers can use. ++ ++The DSS driver models OMAP's overlays, overlay managers and displays in a ++flexible way to enable non-common multi-display configuration. In addition to ++modelling the hardware overlays, omapdss supports virtual overlays and overlay ++managers. These can be used when updating a display with CPU or system DMA. ++ ++Panel and controller drivers ++---------------------------- ++ ++The drivers implement panel or controller specific functionality and are not ++usually visible to users except through omapfb driver. They register ++themselves to the DSS driver. ++ ++omapfb driver ++------------- ++ ++The omapfb driver implements arbitrary number of standard linux framebuffers. ++These framebuffers can be routed flexibly to any overlays, thus allowing very ++dynamic display architecture. ++ ++The driver exports some omapfb specific ioctls, which are compatible with the ++ioctls in the old driver. ++ ++The rest of the non standard features are exported via sysfs. Whether the final ++implementation will use sysfs, or ioctls, is still open. ++ ++V4L2 drivers ++------------ ++ ++V4L2 is being implemented in TI. ++ ++From omapdss point of view the V4L2 drivers should be similar to framebuffer ++driver. ++ ++Architecture ++-------------------- ++ ++Some clarification what the different components do: ++ ++ - Framebuffer is a memory area inside OMAP's SRAM/SDRAM that contains the ++ pixel data for the image. Framebuffer has width and height and color ++ depth. ++ - Overlay defines where the pixels are read from and where they go on the ++ screen. The overlay may be smaller than framebuffer, thus displaying only ++ part of the framebuffer. The position of the overlay may be changed if ++ the overlay is smaller than the display. ++ - Overlay manager combines the overlays in to one image and feeds them to ++ display. ++ - Display is the actual physical display device. ++ ++A framebuffer can be connected to multiple overlays to show the same pixel data ++on all of the overlays. Note that in this case the overlay input sizes must be ++the same, but, in case of video overlays, the output size can be different. Any ++framebuffer can be connected to any overlay. ++ ++An overlay can be connected to one overlay manager. Also DISPC overlays can be ++connected only to DISPC overlay managers, and virtual overlays can be only ++connected to virtual overlays. ++ ++An overlay manager can be connected to one display. There are certain ++restrictions which kinds of displays an overlay manager can be connected: ++ ++ - DISPC TV overlay manager can be only connected to TV display. ++ - Virtual overlay managers can only be connected to DBI or DSI displays. ++ - DISPC LCD overlay manager can be connected to all displays, except TV ++ display. ++ ++Sysfs ++----- ++The sysfs interface is mainly used for testing. I don't think sysfs ++interface is the best for this in the final version, but I don't quite know ++what would be the best interfaces for these things. ++ ++The sysfs interface is divided to two parts: DSS and FB. ++ ++/sys/class/graphics/fb? directory: ++mirror 0=off, 1=on ++rotate Rotation 0-3 for 0, 90, 180, 270 degrees ++rotate_type 0 = DMA rotation, 1 = VRFB rotation ++overlays List of overlay numbers to which framebuffer pixels go ++phys_addr Physical address of the framebuffer ++virt_addr Virtual address of the framebuffer ++size Size of the framebuffer ++ ++/sys/devices/platform/omapdss/overlay? directory: ++enabled 0=off, 1=on ++input_size width,height (ie. the framebuffer size) ++manager Destination overlay manager name ++name ++output_size width,height ++position x,y ++screen_width width ++global_alpha global alpha 0-255 0=transparent 255=opaque ++ ++/sys/devices/platform/omapdss/manager? directory: ++display Destination display ++name ++alpha_blending_enabled 0=off, 1=on ++trans_key_enabled 0=off, 1=on ++trans_key_type gfx-destination, video-source ++trans_key_value transparency color key (RGB24) ++default_color default background color (RGB24) ++ ++/sys/devices/platform/omapdss/display? directory: ++ctrl_name Controller name ++mirror 0=off, 1=on ++update_mode 0=off, 1=auto, 2=manual ++enabled 0=off, 1=on ++name ++rotate Rotation 0-3 for 0, 90, 180, 270 degrees ++timings Display timings (pixclock,xres/hfp/hbp/hsw,yres/vfp/vbp/vsw) ++ When writing, two special timings are accepted for tv-out: ++ "pal" and "ntsc" ++panel_name ++tear_elim Tearing elimination 0=off, 1=on ++ ++There are also some debugfs files at /omapdss/ which show information ++about clocks and registers. ++ ++Examples ++-------- ++ ++The following definitions have been made for the examples below: ++ ++ovl0=/sys/devices/platform/omapdss/overlay0 ++ovl1=/sys/devices/platform/omapdss/overlay1 ++ovl2=/sys/devices/platform/omapdss/overlay2 ++ ++mgr0=/sys/devices/platform/omapdss/manager0 ++mgr1=/sys/devices/platform/omapdss/manager1 ++ ++lcd=/sys/devices/platform/omapdss/display0 ++dvi=/sys/devices/platform/omapdss/display1 ++tv=/sys/devices/platform/omapdss/display2 ++ ++fb0=/sys/class/graphics/fb0 ++fb1=/sys/class/graphics/fb1 ++fb2=/sys/class/graphics/fb2 ++ ++Default setup on OMAP3 SDP ++-------------------------- ++ ++Here's the default setup on OMAP3 SDP board. All planes go to LCD. DVI ++and TV-out are not in use. The columns from left to right are: ++framebuffers, overlays, overlay managers, displays. Framebuffers are ++handled by omapfb, and the rest by the DSS. ++ ++FB0 --- GFX -\ DVI ++FB1 --- VID1 --+- LCD ---- LCD ++FB2 --- VID2 -/ TV ----- TV ++ ++Example: Switch from LCD to DVI ++---------------------- ++ ++w=`cat $dvi/timings | cut -d "," -f 2 | cut -d "/" -f 1` ++h=`cat $dvi/timings | cut -d "," -f 3 | cut -d "/" -f 1` ++ ++echo "0" > $lcd/enabled ++echo "" > $mgr0/display ++fbset -fb /dev/fb0 -xres $w -yres $h -vxres $w -vyres $h ++# at this point you have to switch the dvi/lcd dip-switch from the omap board ++echo "dvi" > $mgr0/display ++echo "1" > $dvi/enabled ++ ++After this the configuration looks like: ++ ++FB0 --- GFX -\ -- DVI ++FB1 --- VID1 --+- LCD -/ LCD ++FB2 --- VID2 -/ TV ----- TV ++ ++Example: Clone GFX overlay to LCD and TV ++------------------------------- ++ ++w=`cat $tv/timings | cut -d "," -f 2 | cut -d "/" -f 1` ++h=`cat $tv/timings | cut -d "," -f 3 | cut -d "/" -f 1` ++ ++echo "0" > $ovl0/enabled ++echo "0" > $ovl1/enabled ++ ++echo "" > $fb1/overlays ++echo "0,1" > $fb0/overlays ++ ++echo "$w,$h" > $ovl1/output_size ++echo "tv" > $ovl1/manager ++ ++echo "1" > $ovl0/enabled ++echo "1" > $ovl1/enabled ++ ++echo "1" > $tv/enabled ++ ++After this the configuration looks like (only relevant parts shown): ++ ++FB0 +-- GFX ---- LCD ---- LCD ++ \- VID1 ---- TV ---- TV ++ ++Misc notes ++---------- ++ ++OMAP FB allocates the framebuffer memory using the OMAP VRAM allocator. ++ ++Using DSI DPLL to generate pixel clock it is possible produce the pixel clock ++of 86.5MHz (max possible), and with that you get 1280x1024@57 output from DVI. ++ ++Rotation and mirroring currently only supports RGB565 and RGB8888 modes. VRFB ++does not support mirroring. ++ ++VRFB rotation requires much more memory than non-rotated framebuffer, so you ++probably need to increase your vram setting before using VRFB rotation. Also, ++many applications may not work with VRFB if they do not pay attention to all ++framebuffer parameters. ++ ++Kernel boot arguments ++--------------------- ++ ++vram= ++ - Amount of total VRAM to preallocate. For example, "10M". omapfb ++ allocates memory for framebuffers from VRAM. ++ ++omapfb.mode=:[,...] ++ - Default video mode for specified displays. For example, ++ "dvi:800x400MR-24@60". See drivers/video/modedb.c. ++ There are also two special modes: "pal" and "ntsc" that ++ can be used to tv out. ++ ++omapfb.vram=:[@][,...] ++ - VRAM allocated for a framebuffer. Normally omapfb allocates vram ++ depending on the display size. With this you can manually allocate ++ more or define the physical address of each framebuffer. For example, ++ "1:4M" to allocate 4M for fb1. ++ ++omapfb.debug= ++ - Enable debug printing. You have to have OMAPFB debug support enabled ++ in kernel config. ++ ++omapfb.test= ++ - Draw test pattern to framebuffer whenever framebuffer settings change. ++ You need to have OMAPFB debug support enabled in kernel config. ++ ++omapfb.vrfb= ++ - Use VRFB rotation for all framebuffers. ++ ++omapfb.rotate= ++ - Default rotation applied to all framebuffers. ++ 0 - 0 degree rotation ++ 1 - 90 degree rotation ++ 2 - 180 degree rotation ++ 3 - 270 degree rotation ++ ++omapfb.mirror= ++ - Default mirror for all framebuffers. Only works with DMA rotation. ++ ++omapdss.def_disp= ++ - Name of default display, to which all overlays will be connected. ++ Common examples are "lcd" or "tv". ++ ++omapdss.debug= ++ - Enable debug printing. You have to have DSS debug support enabled in ++ kernel config. ++ ++TODO ++---- ++ ++DSS locking ++ ++Error checking ++- Lots of checks are missing or implemented just as BUG() ++ ++System DMA update for DSI ++- Can be used for RGB16 and RGB24P modes. Probably not for RGB24U (how ++ to skip the empty byte?) ++ ++OMAP1 support ++- Not sure if needed ++ +diff --git a/MAINTAINERS b/MAINTAINERS +index 8824115..3f5d39f 100644 +--- a/MAINTAINERS ++++ b/MAINTAINERS +@@ -3819,6 +3819,23 @@ L: linux-omap@vger.kernel.org + S: Maintained + F: drivers/video/omap/ + ++OMAP DISPLAY SUBSYSTEM SUPPORT (DSS2) ++M: Tomi Valkeinen ++L: linux-fbdev-devel@lists.sourceforge.net (moderated for non-subscribers) ++L: linux-omap@vger.kernel.org ++S: Maintained ++F: drivers/video/omap2/dss/ ++F: drivers/video/omap2/vrfb.c ++F: drivers/video/omap2/vram.c ++F: Documentation/arm/OMAP/DSS ++ ++OMAP FRAMEBUFFER SUPPORT (FOR DSS2) ++M: Tomi Valkeinen ++L: linux-fbdev-devel@lists.sourceforge.net (moderated for non-subscribers) ++L: linux-omap@vger.kernel.org ++S: Maintained ++F: drivers/video/omap2/omapfb/ ++ + OMAP MMC SUPPORT + M: Jarkko Lavinen + L: linux-omap@vger.kernel.org +diff --git a/arch/arm/configs/omap_3430sdp_defconfig b/arch/arm/configs/omap_3430sdp_defconfig +index 8a4a7e2..59e26e4 100644 +--- a/arch/arm/configs/omap_3430sdp_defconfig ++++ b/arch/arm/configs/omap_3430sdp_defconfig +@@ -1336,10 +1336,33 @@ CONFIG_FB_CFB_IMAGEBLIT=y + # + # CONFIG_FB_S1D13XXX is not set + # CONFIG_FB_VIRTUAL is not set +-CONFIG_FB_OMAP=y +-# CONFIG_FB_OMAP_LCDC_EXTERNAL is not set ++# CONFIG_FB_METRONOME is not set ++# CONFIG_FB_MB862XX is not set ++# CONFIG_FB_BROADSHEET is not set ++# CONFIG_FB_OMAP_LCD_VGA is not set + # CONFIG_FB_OMAP_BOOTLOADER_INIT is not set +-CONFIG_FB_OMAP_CONSISTENT_DMA_SIZE=2 ++CONFIG_OMAP2_VRAM=y ++CONFIG_OMAP2_VRFB=y ++CONFIG_OMAP2_DSS=y ++CONFIG_OMAP2_VRAM_SIZE=4 ++CONFIG_OMAP2_DSS_DEBUG_SUPPORT=y ++# CONFIG_OMAP2_DSS_RFBI is not set ++CONFIG_OMAP2_DSS_VENC=y ++# CONFIG_OMAP2_DSS_SDI is not set ++# CONFIG_OMAP2_DSS_DSI is not set ++# CONFIG_OMAP2_DSS_FAKE_VSYNC is not set ++CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK=0 ++CONFIG_FB_OMAP2=y ++CONFIG_FB_OMAP2_DEBUG_SUPPORT=y ++# CONFIG_FB_OMAP2_FORCE_AUTO_UPDATE is not set ++CONFIG_FB_OMAP2_NUM_FBS=3 ++ ++# ++# OMAP2/3 Display Device Drivers ++# ++CONFIG_PANEL_GENERIC=y ++# CONFIG_PANEL_SAMSUNG_LTE430WQ_F0C is not set ++CONFIG_PANEL_SHARP_LS037V7DW01=y + # CONFIG_BACKLIGHT_LCD_SUPPORT is not set + + # +diff --git a/arch/arm/mach-omap1/board-nokia770.c b/arch/arm/mach-omap1/board-nokia770.c +index ed2a48a..6fbde33 100644 +--- a/arch/arm/mach-omap1/board-nokia770.c ++++ b/arch/arm/mach-omap1/board-nokia770.c +@@ -14,6 +14,7 @@ + #include + #include + #include ++#include + + #include + #include +@@ -32,7 +33,6 @@ + #include + #include + #include +-#include + #include + #include + #include +diff --git a/arch/arm/mach-omap2/board-3430sdp.c b/arch/arm/mach-omap2/board-3430sdp.c +index efaf053..60631be 100644 +--- a/arch/arm/mach-omap2/board-3430sdp.c ++++ b/arch/arm/mach-omap2/board-3430sdp.c +@@ -36,6 +36,7 @@ + #include + #include + #include ++#include + + #include + #include +@@ -152,31 +153,152 @@ static struct spi_board_info sdp3430_spi_board_info[] __initdata = { + }, + }; + +-static struct platform_device sdp3430_lcd_device = { +- .name = "sdp2430_lcd", +- .id = -1, ++ ++#define SDP3430_LCD_PANEL_BACKLIGHT_GPIO 8 ++#define SDP3430_LCD_PANEL_ENABLE_GPIO 5 ++ ++static unsigned backlight_gpio; ++static unsigned enable_gpio; ++static int lcd_enabled; ++static int dvi_enabled; ++ ++static void __init sdp3430_display_init(void) ++{ ++ int r; ++ ++ enable_gpio = SDP3430_LCD_PANEL_ENABLE_GPIO; ++ backlight_gpio = SDP3430_LCD_PANEL_BACKLIGHT_GPIO; ++ ++ r = gpio_request(enable_gpio, "LCD reset"); ++ if (r) { ++ printk(KERN_ERR "failed to get LCD reset GPIO\n"); ++ goto err0; ++ } ++ ++ r = gpio_request(backlight_gpio, "LCD Backlight"); ++ if (r) { ++ printk(KERN_ERR "failed to get LCD backlight GPIO\n"); ++ goto err1; ++ } ++ ++ gpio_direction_output(enable_gpio, 0); ++ gpio_direction_output(backlight_gpio, 0); ++ ++ return; ++err1: ++ gpio_free(enable_gpio); ++err0: ++ return; ++} ++ ++static int sdp3430_panel_enable_lcd(struct omap_dss_device *dssdev) ++{ ++ if (dvi_enabled) { ++ printk(KERN_ERR "cannot enable LCD, DVI is enabled\n"); ++ return -EINVAL; ++ } ++ ++ gpio_direction_output(enable_gpio, 1); ++ gpio_direction_output(backlight_gpio, 1); ++ ++ lcd_enabled = 1; ++ ++ return 0; ++} ++ ++static void sdp3430_panel_disable_lcd(struct omap_dss_device *dssdev) ++{ ++ lcd_enabled = 0; ++ ++ gpio_direction_output(enable_gpio, 0); ++ gpio_direction_output(backlight_gpio, 0); ++} ++ ++static int sdp3430_panel_enable_dvi(struct omap_dss_device *dssdev) ++{ ++ if (lcd_enabled) { ++ printk(KERN_ERR "cannot enable DVI, LCD is enabled\n"); ++ return -EINVAL; ++ } ++ ++ dvi_enabled = 1; ++ ++ return 0; ++} ++ ++static void sdp3430_panel_disable_dvi(struct omap_dss_device *dssdev) ++{ ++ dvi_enabled = 0; ++} ++ ++static int sdp3430_panel_enable_tv(struct omap_dss_device *dssdev) ++{ ++ return 0; ++} ++ ++static void sdp3430_panel_disable_tv(struct omap_dss_device *dssdev) ++{ ++} ++ ++ ++static struct omap_dss_device sdp3430_lcd_device = { ++ .name = "lcd", ++ .driver_name = "sharp_ls_panel", ++ .type = OMAP_DISPLAY_TYPE_DPI, ++ .phy.dpi.data_lines = 16, ++ .platform_enable = sdp3430_panel_enable_lcd, ++ .platform_disable = sdp3430_panel_disable_lcd, + }; + +-static struct regulator_consumer_supply sdp3430_vdac_supply = { +- .supply = "vdac", +- .dev = &sdp3430_lcd_device.dev, ++static struct omap_dss_device sdp3430_dvi_device = { ++ .name = "dvi", ++ .driver_name = "generic_panel", ++ .type = OMAP_DISPLAY_TYPE_DPI, ++ .phy.dpi.data_lines = 24, ++ .platform_enable = sdp3430_panel_enable_dvi, ++ .platform_disable = sdp3430_panel_disable_dvi, + }; + +-static struct regulator_consumer_supply sdp3430_vdvi_supply = { +- .supply = "vdvi", +- .dev = &sdp3430_lcd_device.dev, ++static struct omap_dss_device sdp3430_tv_device = { ++ .name = "tv", ++ .driver_name = "venc", ++ .type = OMAP_DISPLAY_TYPE_VENC, ++ .phy.venc.type = OMAP_DSS_VENC_TYPE_SVIDEO, ++ .platform_enable = sdp3430_panel_enable_tv, ++ .platform_disable = sdp3430_panel_disable_tv, + }; + +-static struct platform_device *sdp3430_devices[] __initdata = { ++ ++static struct omap_dss_device *sdp3430_dss_devices[] = { + &sdp3430_lcd_device, ++ &sdp3430_dvi_device, ++ &sdp3430_tv_device, + }; + +-static struct omap_lcd_config sdp3430_lcd_config __initdata = { +- .ctrl_name = "internal", ++static struct omap_dss_board_info sdp3430_dss_data = { ++ .num_devices = ARRAY_SIZE(sdp3430_dss_devices), ++ .devices = sdp3430_dss_devices, ++ .default_device = &sdp3430_lcd_device, ++}; ++ ++static struct platform_device sdp3430_dss_device = { ++ .name = "omapdss", ++ .id = -1, ++ .dev = { ++ .platform_data = &sdp3430_dss_data, ++ }, ++}; ++ ++static struct regulator_consumer_supply sdp3430_vdda_dac_supply = { ++ .supply = "vdda_dac", ++ .dev = &sdp3430_dss_device.dev, ++}; ++ ++static struct platform_device *sdp3430_devices[] __initdata = { ++ &sdp3430_dss_device, + }; + + static struct omap_board_config_kernel sdp3430_config[] __initdata = { +- { OMAP_TAG_LCD, &sdp3430_lcd_config }, + }; + + static void __init omap_3430sdp_init_irq(void) +@@ -392,22 +514,34 @@ static struct regulator_init_data sdp3430_vdac = { + | REGULATOR_CHANGE_STATUS, + }, + .num_consumer_supplies = 1, +- .consumer_supplies = &sdp3430_vdac_supply, ++ .consumer_supplies = &sdp3430_vdda_dac_supply, + }; + + /* VPLL2 for digital video outputs */ ++static struct regulator_consumer_supply sdp3430_vpll2_supplies[] = { ++ { ++ .supply = "vdvi", ++ .dev = &sdp3430_lcd_device.dev, ++ }, ++ { ++ .supply = "vdds_dsi", ++ .dev = &sdp3430_dss_device.dev, ++ } ++}; ++ + static struct regulator_init_data sdp3430_vpll2 = { + .constraints = { + .name = "VDVI", + .min_uV = 1800000, + .max_uV = 1800000, ++ .apply_uV = true, + .valid_modes_mask = REGULATOR_MODE_NORMAL + | REGULATOR_MODE_STANDBY, + .valid_ops_mask = REGULATOR_CHANGE_MODE + | REGULATOR_CHANGE_STATUS, + }, +- .num_consumer_supplies = 1, +- .consumer_supplies = &sdp3430_vdvi_supply, ++ .num_consumer_supplies = ARRAY_SIZE(sdp3430_vpll2_supplies), ++ .consumer_supplies = sdp3430_vpll2_supplies, + }; + + static struct twl4030_platform_data sdp3430_twldata = { +@@ -499,6 +633,7 @@ static void __init omap_3430sdp_init(void) + omap_serial_init(); + usb_musb_init(); + board_smc91x_init(); ++ sdp3430_display_init(); + enable_board_wakeup_source(); + } + +diff --git a/arch/arm/mach-omap2/clock24xx.c b/arch/arm/mach-omap2/clock24xx.c +index e2dbedd..8524067 100644 +--- a/arch/arm/mach-omap2/clock24xx.c ++++ b/arch/arm/mach-omap2/clock24xx.c +@@ -116,10 +116,10 @@ static struct omap_clk omap24xx_clks[] = { + CLK(NULL, "mdm_ick", &mdm_ick, CK_243X), + CLK(NULL, "mdm_osc_ck", &mdm_osc_ck, CK_243X), + /* DSS domain clocks */ +- CLK("omapfb", "ick", &dss_ick, CK_243X | CK_242X), +- CLK("omapfb", "dss1_fck", &dss1_fck, CK_243X | CK_242X), +- CLK("omapfb", "dss2_fck", &dss2_fck, CK_243X | CK_242X), +- CLK("omapfb", "tv_fck", &dss_54m_fck, CK_243X | CK_242X), ++ CLK("omapdss", "ick", &dss_ick, CK_243X | CK_242X), ++ CLK("omapdss", "dss1_fck", &dss1_fck, CK_243X | CK_242X), ++ CLK("omapdss", "dss2_fck", &dss2_fck, CK_243X | CK_242X), ++ CLK("omapdss", "tv_fck", &dss_54m_fck, CK_243X | CK_242X), + /* L3 domain clocks */ + CLK(NULL, "core_l3_ck", &core_l3_ck, CK_243X | CK_242X), + CLK(NULL, "ssi_fck", &ssi_ssr_sst_fck, CK_243X | CK_242X), +diff --git a/arch/arm/mach-omap2/clock34xx.c b/arch/arm/mach-omap2/clock34xx.c +index 489556e..0a7e9ac 100644 +--- a/arch/arm/mach-omap2/clock34xx.c ++++ b/arch/arm/mach-omap2/clock34xx.c +@@ -236,13 +236,13 @@ static struct omap_clk omap34xx_clks[] = { + CLK("omap_rng", "ick", &rng_ick, CK_343X), + CLK(NULL, "sha11_ick", &sha11_ick, CK_343X), + CLK(NULL, "des1_ick", &des1_ick, CK_343X), +- CLK("omapfb", "dss1_fck", &dss1_alwon_fck_3430es1, CK_3430ES1), +- CLK("omapfb", "dss1_fck", &dss1_alwon_fck_3430es2, CK_3430ES2), +- CLK("omapfb", "tv_fck", &dss_tv_fck, CK_343X), +- CLK("omapfb", "video_fck", &dss_96m_fck, CK_343X), +- CLK("omapfb", "dss2_fck", &dss2_alwon_fck, CK_343X), +- CLK("omapfb", "ick", &dss_ick_3430es1, CK_3430ES1), +- CLK("omapfb", "ick", &dss_ick_3430es2, CK_3430ES2), ++ CLK("omapdss", "dss1_fck", &dss1_alwon_fck_3430es1, CK_3430ES1), ++ CLK("omapdss", "dss1_fck", &dss1_alwon_fck_3430es2, CK_3430ES2), ++ CLK("omapdss", "tv_fck", &dss_tv_fck, CK_343X), ++ CLK("omapdss", "video_fck", &dss_96m_fck, CK_343X), ++ CLK("omapdss", "dss2_fck", &dss2_alwon_fck, CK_343X), ++ CLK("omapdss", "ick", &dss_ick_3430es1, CK_3430ES1), ++ CLK("omapdss", "ick", &dss_ick_3430es2, CK_3430ES2), + CLK(NULL, "cam_mclk", &cam_mclk, CK_343X), + CLK(NULL, "cam_ick", &cam_ick, CK_343X), + CLK(NULL, "csi2_96m_fck", &csi2_96m_fck, CK_343X), +diff --git a/arch/arm/mach-omap2/io.c b/arch/arm/mach-omap2/io.c +index e3a3bad..adbb905 100644 +--- a/arch/arm/mach-omap2/io.c ++++ b/arch/arm/mach-omap2/io.c +@@ -22,17 +22,18 @@ + #include + #include + #include ++#include + + #include + + #include + + #include +-#include + #include + #include + #include + #include ++#include + + #ifndef CONFIG_ARCH_OMAP4 /* FIXME: Remove this once clkdev is ready */ + #include "clock.h" +@@ -246,6 +247,7 @@ void __init omap2_map_common_io(void) + omap2_check_revision(); + omap_sram_init(); + omapfb_reserve_sdram(); ++ omap_vram_reserve_sdram(); + } + + /* +diff --git a/arch/arm/mach-omap2/sdrc.c b/arch/arm/mach-omap2/sdrc.c +index 9e3bd4f..6a5a2c5 100644 +--- a/arch/arm/mach-omap2/sdrc.c ++++ b/arch/arm/mach-omap2/sdrc.c +@@ -133,3 +133,19 @@ void __init omap2_sdrc_init(struct omap_sdrc_params *sdrc_cs0, + (1 << SDRC_POWER_PAGEPOLICY_SHIFT); + sdrc_write_reg(l, SDRC_POWER); + } ++ ++void omap2_sms_write_rot_control(u32 val, unsigned ctx) ++{ ++ sms_write_reg(val, SMS_ROT_CONTROL(ctx)); ++} ++ ++void omap2_sms_write_rot_size(u32 val, unsigned ctx) ++{ ++ sms_write_reg(val, SMS_ROT_SIZE(ctx)); ++} ++ ++void omap2_sms_write_rot_physical_ba(u32 val, unsigned ctx) ++{ ++ sms_write_reg(val, SMS_ROT_PHYSICAL_BA(ctx)); ++} ++ +diff --git a/arch/arm/plat-omap/fb.c b/arch/arm/plat-omap/fb.c +index 3746222..70fbeae 100644 +--- a/arch/arm/plat-omap/fb.c ++++ b/arch/arm/plat-omap/fb.c +@@ -28,13 +28,13 @@ + #include + #include + #include ++#include + + #include + #include + + #include + #include +-#include + + #if defined(CONFIG_FB_OMAP) || defined(CONFIG_FB_OMAP_MODULE) + +@@ -327,7 +327,33 @@ static inline int omap_init_fb(void) + + arch_initcall(omap_init_fb); + +-#else ++#elif defined(CONFIG_FB_OMAP2) || defined(CONFIG_FB_OMAP2_MODULE) ++ ++static u64 omap_fb_dma_mask = ~(u32)0; ++static struct omapfb_platform_data omapfb_config; ++ ++static struct platform_device omap_fb_device = { ++ .name = "omapfb", ++ .id = -1, ++ .dev = { ++ .dma_mask = &omap_fb_dma_mask, ++ .coherent_dma_mask = ~(u32)0, ++ .platform_data = &omapfb_config, ++ }, ++ .num_resources = 0, ++}; ++ ++void omapfb_set_platform_data(struct omapfb_platform_data *data) ++{ ++ omapfb_config = *data; ++} ++ ++static inline int omap_init_fb(void) ++{ ++ return platform_device_register(&omap_fb_device); ++} ++ ++arch_initcall(omap_init_fb); + + void omapfb_reserve_sdram(void) {} + unsigned long omapfb_reserve_sram(unsigned long sram_pstart, +@@ -339,5 +365,16 @@ unsigned long omapfb_reserve_sram(unsigned long sram_pstart, + return 0; + } + ++#else ++ ++void omapfb_reserve_sdram(void) {} ++unsigned long omapfb_reserve_sram(unsigned long sram_pstart, ++ unsigned long sram_vstart, ++ unsigned long sram_size, ++ unsigned long start_avail, ++ unsigned long size_avail) ++{ ++ return 0; ++} + + #endif +diff --git a/arch/arm/plat-omap/include/mach/display.h b/arch/arm/plat-omap/include/mach/display.h +new file mode 100644 +index 0000000..4c7422e +--- /dev/null ++++ b/arch/arm/plat-omap/include/mach/display.h +@@ -0,0 +1,540 @@ ++/* ++ * linux/include/asm-arm/arch-omap/display.h ++ * ++ * Copyright (C) 2008 Nokia Corporation ++ * Author: Tomi Valkeinen ++ * ++ * 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. ++ * ++ * 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, see . ++ */ ++ ++#ifndef __ASM_ARCH_OMAP_DISPLAY_H ++#define __ASM_ARCH_OMAP_DISPLAY_H ++ ++#include ++#include ++#include ++#include ++ ++#define DISPC_IRQ_FRAMEDONE (1 << 0) ++#define DISPC_IRQ_VSYNC (1 << 1) ++#define DISPC_IRQ_EVSYNC_EVEN (1 << 2) ++#define DISPC_IRQ_EVSYNC_ODD (1 << 3) ++#define DISPC_IRQ_ACBIAS_COUNT_STAT (1 << 4) ++#define DISPC_IRQ_PROG_LINE_NUM (1 << 5) ++#define DISPC_IRQ_GFX_FIFO_UNDERFLOW (1 << 6) ++#define DISPC_IRQ_GFX_END_WIN (1 << 7) ++#define DISPC_IRQ_PAL_GAMMA_MASK (1 << 8) ++#define DISPC_IRQ_OCP_ERR (1 << 9) ++#define DISPC_IRQ_VID1_FIFO_UNDERFLOW (1 << 10) ++#define DISPC_IRQ_VID1_END_WIN (1 << 11) ++#define DISPC_IRQ_VID2_FIFO_UNDERFLOW (1 << 12) ++#define DISPC_IRQ_VID2_END_WIN (1 << 13) ++#define DISPC_IRQ_SYNC_LOST (1 << 14) ++#define DISPC_IRQ_SYNC_LOST_DIGIT (1 << 15) ++#define DISPC_IRQ_WAKEUP (1 << 16) ++ ++struct omap_dss_device; ++struct omap_overlay_manager; ++ ++enum omap_display_type { ++ OMAP_DISPLAY_TYPE_NONE = 0, ++ OMAP_DISPLAY_TYPE_DPI = 1 << 0, ++ OMAP_DISPLAY_TYPE_DBI = 1 << 1, ++ OMAP_DISPLAY_TYPE_SDI = 1 << 2, ++ OMAP_DISPLAY_TYPE_DSI = 1 << 3, ++ OMAP_DISPLAY_TYPE_VENC = 1 << 4, ++}; ++ ++enum omap_plane { ++ OMAP_DSS_GFX = 0, ++ OMAP_DSS_VIDEO1 = 1, ++ OMAP_DSS_VIDEO2 = 2 ++}; ++ ++enum omap_channel { ++ OMAP_DSS_CHANNEL_LCD = 0, ++ OMAP_DSS_CHANNEL_DIGIT = 1, ++}; ++ ++enum omap_color_mode { ++ OMAP_DSS_COLOR_CLUT1 = 1 << 0, /* BITMAP 1 */ ++ OMAP_DSS_COLOR_CLUT2 = 1 << 1, /* BITMAP 2 */ ++ OMAP_DSS_COLOR_CLUT4 = 1 << 2, /* BITMAP 4 */ ++ OMAP_DSS_COLOR_CLUT8 = 1 << 3, /* BITMAP 8 */ ++ OMAP_DSS_COLOR_RGB12U = 1 << 4, /* RGB12, 16-bit container */ ++ OMAP_DSS_COLOR_ARGB16 = 1 << 5, /* ARGB16 */ ++ OMAP_DSS_COLOR_RGB16 = 1 << 6, /* RGB16 */ ++ OMAP_DSS_COLOR_RGB24U = 1 << 7, /* RGB24, 32-bit container */ ++ OMAP_DSS_COLOR_RGB24P = 1 << 8, /* RGB24, 24-bit container */ ++ OMAP_DSS_COLOR_YUV2 = 1 << 9, /* YUV2 4:2:2 co-sited */ ++ OMAP_DSS_COLOR_UYVY = 1 << 10, /* UYVY 4:2:2 co-sited */ ++ OMAP_DSS_COLOR_ARGB32 = 1 << 11, /* ARGB32 */ ++ OMAP_DSS_COLOR_RGBA32 = 1 << 12, /* RGBA32 */ ++ OMAP_DSS_COLOR_RGBX32 = 1 << 13, /* RGBx32 */ ++ ++ OMAP_DSS_COLOR_GFX_OMAP3 = ++ OMAP_DSS_COLOR_CLUT1 | OMAP_DSS_COLOR_CLUT2 | ++ OMAP_DSS_COLOR_CLUT4 | OMAP_DSS_COLOR_CLUT8 | ++ OMAP_DSS_COLOR_RGB12U | OMAP_DSS_COLOR_ARGB16 | ++ OMAP_DSS_COLOR_RGB16 | OMAP_DSS_COLOR_RGB24U | ++ OMAP_DSS_COLOR_RGB24P | OMAP_DSS_COLOR_ARGB32 | ++ OMAP_DSS_COLOR_RGBA32 | OMAP_DSS_COLOR_RGBX32, ++ ++ OMAP_DSS_COLOR_VID_OMAP3 = ++ OMAP_DSS_COLOR_RGB12U | OMAP_DSS_COLOR_ARGB16 | ++ OMAP_DSS_COLOR_RGB16 | OMAP_DSS_COLOR_RGB24U | ++ OMAP_DSS_COLOR_RGB24P | OMAP_DSS_COLOR_ARGB32 | ++ OMAP_DSS_COLOR_RGBA32 | OMAP_DSS_COLOR_RGBX32 | ++ OMAP_DSS_COLOR_YUV2 | OMAP_DSS_COLOR_UYVY, ++}; ++ ++enum omap_lcd_display_type { ++ OMAP_DSS_LCD_DISPLAY_STN, ++ OMAP_DSS_LCD_DISPLAY_TFT, ++}; ++ ++enum omap_dss_load_mode { ++ OMAP_DSS_LOAD_CLUT_AND_FRAME = 0, ++ OMAP_DSS_LOAD_CLUT_ONLY = 1, ++ OMAP_DSS_LOAD_FRAME_ONLY = 2, ++ OMAP_DSS_LOAD_CLUT_ONCE_FRAME = 3, ++}; ++ ++enum omap_dss_trans_key_type { ++ OMAP_DSS_COLOR_KEY_GFX_DST = 0, ++ OMAP_DSS_COLOR_KEY_VID_SRC = 1, ++}; ++ ++enum omap_rfbi_te_mode { ++ OMAP_DSS_RFBI_TE_MODE_1 = 1, ++ OMAP_DSS_RFBI_TE_MODE_2 = 2, ++}; ++ ++enum omap_panel_config { ++ OMAP_DSS_LCD_IVS = 1<<0, ++ OMAP_DSS_LCD_IHS = 1<<1, ++ OMAP_DSS_LCD_IPC = 1<<2, ++ OMAP_DSS_LCD_IEO = 1<<3, ++ OMAP_DSS_LCD_RF = 1<<4, ++ OMAP_DSS_LCD_ONOFF = 1<<5, ++ ++ OMAP_DSS_LCD_TFT = 1<<20, ++}; ++ ++enum omap_dss_venc_type { ++ OMAP_DSS_VENC_TYPE_COMPOSITE, ++ OMAP_DSS_VENC_TYPE_SVIDEO, ++}; ++ ++enum omap_display_caps { ++ OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE = 1 << 0, ++}; ++ ++enum omap_dss_update_mode { ++ OMAP_DSS_UPDATE_DISABLED = 0, ++ OMAP_DSS_UPDATE_AUTO, ++ OMAP_DSS_UPDATE_MANUAL, ++}; ++ ++enum omap_dss_display_state { ++ OMAP_DSS_DISPLAY_DISABLED = 0, ++ OMAP_DSS_DISPLAY_ACTIVE, ++ OMAP_DSS_DISPLAY_SUSPENDED, ++}; ++ ++/* XXX perhaps this should be removed */ ++enum omap_dss_overlay_managers { ++ OMAP_DSS_OVL_MGR_LCD, ++ OMAP_DSS_OVL_MGR_TV, ++}; ++ ++enum omap_dss_rotation_type { ++ OMAP_DSS_ROT_DMA = 0, ++ OMAP_DSS_ROT_VRFB = 1, ++}; ++ ++enum omap_overlay_caps { ++ OMAP_DSS_OVL_CAP_SCALE = 1 << 0, ++ OMAP_DSS_OVL_CAP_DISPC = 1 << 1, ++}; ++ ++enum omap_overlay_manager_caps { ++ OMAP_DSS_OVL_MGR_CAP_DISPC = 1 << 0, ++}; ++ ++/* RFBI */ ++ ++struct rfbi_timings { ++ int cs_on_time; ++ int cs_off_time; ++ int we_on_time; ++ int we_off_time; ++ int re_on_time; ++ int re_off_time; ++ int we_cycle_time; ++ int re_cycle_time; ++ int cs_pulse_width; ++ int access_time; ++ ++ int clk_div; ++ ++ u32 tim[5]; /* set by rfbi_convert_timings() */ ++ ++ int converted; ++}; ++ ++void omap_rfbi_write_command(const void *buf, u32 len); ++void omap_rfbi_read_data(void *buf, u32 len); ++void omap_rfbi_write_data(const void *buf, u32 len); ++void omap_rfbi_write_pixels(const void __iomem *buf, int scr_width, ++ u16 x, u16 y, ++ u16 w, u16 h); ++int omap_rfbi_enable_te(bool enable, unsigned line); ++int omap_rfbi_setup_te(enum omap_rfbi_te_mode mode, ++ unsigned hs_pulse_time, unsigned vs_pulse_time, ++ int hs_pol_inv, int vs_pol_inv, int extif_div); ++ ++/* DSI */ ++void dsi_bus_lock(void); ++void dsi_bus_unlock(void); ++int dsi_vc_dcs_write(int channel, u8 *data, int len); ++int dsi_vc_dcs_write_nosync(int channel, u8 *data, int len); ++int dsi_vc_dcs_read(int channel, u8 dcs_cmd, u8 *buf, int buflen); ++int dsi_vc_set_max_rx_packet_size(int channel, u16 len); ++int dsi_vc_send_null(int channel); ++int dsi_vc_send_bta_sync(int channel); ++ ++/* Board specific data */ ++struct omap_dss_board_info { ++ int (*get_last_off_on_transaction_id)(struct device *dev); ++ int num_devices; ++ struct omap_dss_device **devices; ++ struct omap_dss_device *default_device; ++}; ++ ++struct omap_video_timings { ++ /* Unit: pixels */ ++ u16 x_res; ++ /* Unit: pixels */ ++ u16 y_res; ++ /* Unit: KHz */ ++ u32 pixel_clock; ++ /* Unit: pixel clocks */ ++ u16 hsw; /* Horizontal synchronization pulse width */ ++ /* Unit: pixel clocks */ ++ u16 hfp; /* Horizontal front porch */ ++ /* Unit: pixel clocks */ ++ u16 hbp; /* Horizontal back porch */ ++ /* Unit: line clocks */ ++ u16 vsw; /* Vertical synchronization pulse width */ ++ /* Unit: line clocks */ ++ u16 vfp; /* Vertical front porch */ ++ /* Unit: line clocks */ ++ u16 vbp; /* Vertical back porch */ ++}; ++ ++#ifdef CONFIG_OMAP2_DSS_VENC ++/* Hardcoded timings for tv modes. Venc only uses these to ++ * identify the mode, and does not actually use the configs ++ * itself. However, the configs should be something that ++ * a normal monitor can also show */ ++const extern struct omap_video_timings omap_dss_pal_timings; ++const extern struct omap_video_timings omap_dss_ntsc_timings; ++#endif ++ ++struct omap_overlay_info { ++ bool enabled; ++ ++ u32 paddr; ++ void __iomem *vaddr; ++ u16 screen_width; ++ u16 width; ++ u16 height; ++ enum omap_color_mode color_mode; ++ u8 rotation; ++ enum omap_dss_rotation_type rotation_type; ++ bool mirror; ++ ++ u16 pos_x; ++ u16 pos_y; ++ u16 out_width; /* if 0, out_width == width */ ++ u16 out_height; /* if 0, out_height == height */ ++ u8 global_alpha; ++}; ++ ++struct omap_overlay { ++ struct kobject kobj; ++ struct list_head list; ++ ++ /* static fields */ ++ const char *name; ++ int id; ++ enum omap_color_mode supported_modes; ++ enum omap_overlay_caps caps; ++ ++ /* dynamic fields */ ++ struct omap_overlay_manager *manager; ++ struct omap_overlay_info info; ++ ++ /* if true, info has been changed, but not applied() yet */ ++ bool info_dirty; ++ ++ int (*set_manager)(struct omap_overlay *ovl, ++ struct omap_overlay_manager *mgr); ++ int (*unset_manager)(struct omap_overlay *ovl); ++ ++ int (*set_overlay_info)(struct omap_overlay *ovl, ++ struct omap_overlay_info *info); ++ void (*get_overlay_info)(struct omap_overlay *ovl, ++ struct omap_overlay_info *info); ++ ++ int (*wait_for_go)(struct omap_overlay *ovl); ++}; ++ ++struct omap_overlay_manager_info { ++ u32 default_color; ++ ++ enum omap_dss_trans_key_type trans_key_type; ++ u32 trans_key; ++ bool trans_enabled; ++ ++ bool alpha_enabled; ++}; ++ ++struct omap_overlay_manager { ++ struct kobject kobj; ++ struct list_head list; ++ ++ /* static fields */ ++ const char *name; ++ int id; ++ enum omap_overlay_manager_caps caps; ++ int num_overlays; ++ struct omap_overlay **overlays; ++ enum omap_display_type supported_displays; ++ ++ /* dynamic fields */ ++ struct omap_dss_device *device; ++ struct omap_overlay_manager_info info; ++ ++ bool device_changed; ++ /* if true, info has been changed but not applied() yet */ ++ bool info_dirty; ++ ++ int (*set_device)(struct omap_overlay_manager *mgr, ++ struct omap_dss_device *dssdev); ++ int (*unset_device)(struct omap_overlay_manager *mgr); ++ ++ int (*set_manager_info)(struct omap_overlay_manager *mgr, ++ struct omap_overlay_manager_info *info); ++ void (*get_manager_info)(struct omap_overlay_manager *mgr, ++ struct omap_overlay_manager_info *info); ++ ++ int (*apply)(struct omap_overlay_manager *mgr); ++ int (*wait_for_go)(struct omap_overlay_manager *mgr); ++}; ++ ++struct omap_dss_device { ++ struct device dev; ++ ++ enum omap_display_type type; ++ ++ union { ++ struct { ++ u8 data_lines; ++ } dpi; ++ ++ struct { ++ u8 channel; ++ u8 data_lines; ++ } rfbi; ++ ++ struct { ++ u8 datapairs; ++ } sdi; ++ ++ struct { ++ u8 clk_lane; ++ u8 clk_pol; ++ u8 data1_lane; ++ u8 data1_pol; ++ u8 data2_lane; ++ u8 data2_pol; ++ unsigned long lp_clk_hz; ++ unsigned long ddr_clk_hz; ++ ++ bool ext_te; ++ u8 ext_te_gpio; ++ } dsi; ++ ++ struct { ++ enum omap_dss_venc_type type; ++ bool invert_polarity; ++ } venc; ++ } phy; ++ ++ struct { ++ struct omap_video_timings timings; ++ ++ int acbi; /* ac-bias pin transitions per interrupt */ ++ /* Unit: line clocks */ ++ int acb; /* ac-bias pin frequency */ ++ ++ enum omap_panel_config config; ++ ++ u8 recommended_bpp; ++ ++ struct omap_dss_device *ctrl; ++ } panel; ++ ++ struct { ++ u8 pixel_size; ++ struct rfbi_timings rfbi_timings; ++ struct omap_dss_device *panel; ++ } ctrl; ++ ++ int reset_gpio; ++ ++ int max_backlight_level; ++ ++ const char *name; ++ ++ /* used to match device to driver */ ++ const char *driver_name; ++ ++ void *data; ++ ++ struct omap_dss_driver *driver; ++ ++ /* helper variable for driver suspend/resume */ ++ bool activate_after_resume; ++ ++ enum omap_display_caps caps; ++ ++ struct omap_overlay_manager *manager; ++ ++ enum omap_dss_display_state state; ++ ++ int (*enable)(struct omap_dss_device *dssdev); ++ void (*disable)(struct omap_dss_device *dssdev); ++ ++ int (*suspend)(struct omap_dss_device *dssdev); ++ int (*resume)(struct omap_dss_device *dssdev); ++ ++ void (*get_resolution)(struct omap_dss_device *dssdev, ++ u16 *xres, u16 *yres); ++ int (*get_recommended_bpp)(struct omap_dss_device *dssdev); ++ ++ int (*check_timings)(struct omap_dss_device *dssdev, ++ struct omap_video_timings *timings); ++ void (*set_timings)(struct omap_dss_device *dssdev, ++ struct omap_video_timings *timings); ++ void (*get_timings)(struct omap_dss_device *dssdev, ++ struct omap_video_timings *timings); ++ int (*update)(struct omap_dss_device *dssdev, ++ u16 x, u16 y, u16 w, u16 h); ++ int (*sync)(struct omap_dss_device *dssdev); ++ int (*wait_vsync)(struct omap_dss_device *dssdev); ++ ++ int (*set_update_mode)(struct omap_dss_device *dssdev, ++ enum omap_dss_update_mode); ++ enum omap_dss_update_mode (*get_update_mode) ++ (struct omap_dss_device *dssdev); ++ ++ int (*enable_te)(struct omap_dss_device *dssdev, bool enable); ++ int (*get_te)(struct omap_dss_device *dssdev); ++ ++ u8 (*get_rotate)(struct omap_dss_device *dssdev); ++ int (*set_rotate)(struct omap_dss_device *dssdev, u8 rotate); ++ ++ bool (*get_mirror)(struct omap_dss_device *dssdev); ++ int (*set_mirror)(struct omap_dss_device *dssdev, bool enable); ++ ++ int (*run_test)(struct omap_dss_device *dssdev, int test); ++ int (*memory_read)(struct omap_dss_device *dssdev, ++ void *buf, size_t size, ++ u16 x, u16 y, u16 w, u16 h); ++ ++ int (*set_wss)(struct omap_dss_device *dssdev, u32 wss); ++ u32 (*get_wss)(struct omap_dss_device *dssdev); ++ ++ /* platform specific */ ++ int (*platform_enable)(struct omap_dss_device *dssdev); ++ void (*platform_disable)(struct omap_dss_device *dssdev); ++ int (*set_backlight)(struct omap_dss_device *dssdev, int level); ++ int (*get_backlight)(struct omap_dss_device *dssdev); ++}; ++ ++struct omap_dss_driver { ++ struct device_driver driver; ++ ++ int (*probe)(struct omap_dss_device *); ++ void (*remove)(struct omap_dss_device *); ++ ++ int (*enable)(struct omap_dss_device *display); ++ void (*disable)(struct omap_dss_device *display); ++ int (*suspend)(struct omap_dss_device *display); ++ int (*resume)(struct omap_dss_device *display); ++ int (*run_test)(struct omap_dss_device *display, int test); ++ ++ void (*setup_update)(struct omap_dss_device *dssdev, ++ u16 x, u16 y, u16 w, u16 h); ++ ++ int (*enable_te)(struct omap_dss_device *dssdev, bool enable); ++ int (*wait_for_te)(struct omap_dss_device *dssdev); ++ ++ u8 (*get_rotate)(struct omap_dss_device *dssdev); ++ int (*set_rotate)(struct omap_dss_device *dssdev, u8 rotate); ++ ++ bool (*get_mirror)(struct omap_dss_device *dssdev); ++ int (*set_mirror)(struct omap_dss_device *dssdev, bool enable); ++ ++ int (*memory_read)(struct omap_dss_device *dssdev, ++ void *buf, size_t size, ++ u16 x, u16 y, u16 w, u16 h); ++}; ++ ++int omap_dss_register_driver(struct omap_dss_driver *); ++void omap_dss_unregister_driver(struct omap_dss_driver *); ++ ++int omap_dss_register_device(struct omap_dss_device *); ++void omap_dss_unregister_device(struct omap_dss_device *); ++ ++void omap_dss_get_device(struct omap_dss_device *dssdev); ++void omap_dss_put_device(struct omap_dss_device *dssdev); ++#define for_each_dss_dev(d) while ((d = omap_dss_get_next_device(d)) != NULL) ++struct omap_dss_device *omap_dss_get_next_device(struct omap_dss_device *from); ++struct omap_dss_device *omap_dss_find_device(void *data, ++ int (*match)(struct omap_dss_device *dssdev, void *data)); ++ ++int omap_dss_start_device(struct omap_dss_device *dssdev); ++void omap_dss_stop_device(struct omap_dss_device *dssdev); ++ ++int omap_dss_get_num_overlay_managers(void); ++struct omap_overlay_manager *omap_dss_get_overlay_manager(int num); ++ ++int omap_dss_get_num_overlays(void); ++struct omap_overlay *omap_dss_get_overlay(int num); ++ ++typedef void (*omap_dispc_isr_t) (void *arg, u32 mask); ++int omap_dispc_register_isr(omap_dispc_isr_t isr, void *arg, u32 mask); ++int omap_dispc_unregister_isr(omap_dispc_isr_t isr, void *arg, u32 mask); ++ ++int omap_dispc_wait_for_irq_timeout(u32 irqmask, unsigned long timeout); ++int omap_dispc_wait_for_irq_interruptible_timeout(u32 irqmask, ++ unsigned long timeout); ++ ++#define to_dss_driver(x) container_of((x), struct omap_dss_driver, driver) ++#define to_dss_device(x) container_of((x), struct omap_dss_device, dev) ++ ++#endif +diff --git a/arch/arm/plat-omap/include/mach/omapfb.h b/arch/arm/plat-omap/include/mach/omapfb.h +deleted file mode 100644 +index b226bdf..0000000 +--- a/arch/arm/plat-omap/include/mach/omapfb.h ++++ /dev/null +@@ -1,398 +0,0 @@ +-/* +- * File: arch/arm/plat-omap/include/mach/omapfb.h +- * +- * Framebuffer driver for TI OMAP boards +- * +- * Copyright (C) 2004 Nokia Corporation +- * Author: Imre Deak +- * +- * 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, MA 02111-1307, USA. +- */ +- +-#ifndef __OMAPFB_H +-#define __OMAPFB_H +- +-#include +-#include +- +-/* IOCTL commands. */ +- +-#define OMAP_IOW(num, dtype) _IOW('O', num, dtype) +-#define OMAP_IOR(num, dtype) _IOR('O', num, dtype) +-#define OMAP_IOWR(num, dtype) _IOWR('O', num, dtype) +-#define OMAP_IO(num) _IO('O', num) +- +-#define OMAPFB_MIRROR OMAP_IOW(31, int) +-#define OMAPFB_SYNC_GFX OMAP_IO(37) +-#define OMAPFB_VSYNC OMAP_IO(38) +-#define OMAPFB_SET_UPDATE_MODE OMAP_IOW(40, int) +-#define OMAPFB_GET_CAPS OMAP_IOR(42, struct omapfb_caps) +-#define OMAPFB_GET_UPDATE_MODE OMAP_IOW(43, int) +-#define OMAPFB_LCD_TEST OMAP_IOW(45, int) +-#define OMAPFB_CTRL_TEST OMAP_IOW(46, int) +-#define OMAPFB_UPDATE_WINDOW_OLD OMAP_IOW(47, struct omapfb_update_window_old) +-#define OMAPFB_SET_COLOR_KEY OMAP_IOW(50, struct omapfb_color_key) +-#define OMAPFB_GET_COLOR_KEY OMAP_IOW(51, struct omapfb_color_key) +-#define OMAPFB_SETUP_PLANE OMAP_IOW(52, struct omapfb_plane_info) +-#define OMAPFB_QUERY_PLANE OMAP_IOW(53, struct omapfb_plane_info) +-#define OMAPFB_UPDATE_WINDOW OMAP_IOW(54, struct omapfb_update_window) +-#define OMAPFB_SETUP_MEM OMAP_IOW(55, struct omapfb_mem_info) +-#define OMAPFB_QUERY_MEM OMAP_IOW(56, struct omapfb_mem_info) +- +-#define OMAPFB_CAPS_GENERIC_MASK 0x00000fff +-#define OMAPFB_CAPS_LCDC_MASK 0x00fff000 +-#define OMAPFB_CAPS_PANEL_MASK 0xff000000 +- +-#define OMAPFB_CAPS_MANUAL_UPDATE 0x00001000 +-#define OMAPFB_CAPS_TEARSYNC 0x00002000 +-#define OMAPFB_CAPS_PLANE_RELOCATE_MEM 0x00004000 +-#define OMAPFB_CAPS_PLANE_SCALE 0x00008000 +-#define OMAPFB_CAPS_WINDOW_PIXEL_DOUBLE 0x00010000 +-#define OMAPFB_CAPS_WINDOW_SCALE 0x00020000 +-#define OMAPFB_CAPS_WINDOW_OVERLAY 0x00040000 +-#define OMAPFB_CAPS_WINDOW_ROTATE 0x00080000 +-#define OMAPFB_CAPS_SET_BACKLIGHT 0x01000000 +- +-/* Values from DSP must map to lower 16-bits */ +-#define OMAPFB_FORMAT_MASK 0x00ff +-#define OMAPFB_FORMAT_FLAG_DOUBLE 0x0100 +-#define OMAPFB_FORMAT_FLAG_TEARSYNC 0x0200 +-#define OMAPFB_FORMAT_FLAG_FORCE_VSYNC 0x0400 +-#define OMAPFB_FORMAT_FLAG_ENABLE_OVERLAY 0x0800 +-#define OMAPFB_FORMAT_FLAG_DISABLE_OVERLAY 0x1000 +- +-#define OMAPFB_EVENT_READY 1 +-#define OMAPFB_EVENT_DISABLED 2 +- +-#define OMAPFB_MEMTYPE_SDRAM 0 +-#define OMAPFB_MEMTYPE_SRAM 1 +-#define OMAPFB_MEMTYPE_MAX 1 +- +-enum omapfb_color_format { +- OMAPFB_COLOR_RGB565 = 0, +- OMAPFB_COLOR_YUV422, +- OMAPFB_COLOR_YUV420, +- OMAPFB_COLOR_CLUT_8BPP, +- OMAPFB_COLOR_CLUT_4BPP, +- OMAPFB_COLOR_CLUT_2BPP, +- OMAPFB_COLOR_CLUT_1BPP, +- OMAPFB_COLOR_RGB444, +- OMAPFB_COLOR_YUY422, +-}; +- +-struct omapfb_update_window { +- __u32 x, y; +- __u32 width, height; +- __u32 format; +- __u32 out_x, out_y; +- __u32 out_width, out_height; +- __u32 reserved[8]; +-}; +- +-struct omapfb_update_window_old { +- __u32 x, y; +- __u32 width, height; +- __u32 format; +-}; +- +-enum omapfb_plane { +- OMAPFB_PLANE_GFX = 0, +- OMAPFB_PLANE_VID1, +- OMAPFB_PLANE_VID2, +-}; +- +-enum omapfb_channel_out { +- OMAPFB_CHANNEL_OUT_LCD = 0, +- OMAPFB_CHANNEL_OUT_DIGIT, +-}; +- +-struct omapfb_plane_info { +- __u32 pos_x; +- __u32 pos_y; +- __u8 enabled; +- __u8 channel_out; +- __u8 mirror; +- __u8 reserved1; +- __u32 out_width; +- __u32 out_height; +- __u32 reserved2[12]; +-}; +- +-struct omapfb_mem_info { +- __u32 size; +- __u8 type; +- __u8 reserved[3]; +-}; +- +-struct omapfb_caps { +- __u32 ctrl; +- __u32 plane_color; +- __u32 wnd_color; +-}; +- +-enum omapfb_color_key_type { +- OMAPFB_COLOR_KEY_DISABLED = 0, +- OMAPFB_COLOR_KEY_GFX_DST, +- OMAPFB_COLOR_KEY_VID_SRC, +-}; +- +-struct omapfb_color_key { +- __u8 channel_out; +- __u32 background; +- __u32 trans_key; +- __u8 key_type; +-}; +- +-enum omapfb_update_mode { +- OMAPFB_UPDATE_DISABLED = 0, +- OMAPFB_AUTO_UPDATE, +- OMAPFB_MANUAL_UPDATE +-}; +- +-#ifdef __KERNEL__ +- +-#include +-#include +-#include +-#include +- +-#include +- +-#define OMAP_LCDC_INV_VSYNC 0x0001 +-#define OMAP_LCDC_INV_HSYNC 0x0002 +-#define OMAP_LCDC_INV_PIX_CLOCK 0x0004 +-#define OMAP_LCDC_INV_OUTPUT_EN 0x0008 +-#define OMAP_LCDC_HSVS_RISING_EDGE 0x0010 +-#define OMAP_LCDC_HSVS_OPPOSITE 0x0020 +- +-#define OMAP_LCDC_SIGNAL_MASK 0x003f +- +-#define OMAP_LCDC_PANEL_TFT 0x0100 +- +-#define OMAPFB_PLANE_XRES_MIN 8 +-#define OMAPFB_PLANE_YRES_MIN 8 +- +-#ifdef CONFIG_ARCH_OMAP1 +-#define OMAPFB_PLANE_NUM 1 +-#else +-#define OMAPFB_PLANE_NUM 3 +-#endif +- +-struct omapfb_device; +- +-struct lcd_panel { +- const char *name; +- int config; /* TFT/STN, signal inversion */ +- int bpp; /* Pixel format in fb mem */ +- int data_lines; /* Lines on LCD HW interface */ +- +- int x_res, y_res; +- int pixel_clock; /* In kHz */ +- int hsw; /* Horizontal synchronization +- pulse width */ +- int hfp; /* Horizontal front porch */ +- int hbp; /* Horizontal back porch */ +- int vsw; /* Vertical synchronization +- pulse width */ +- int vfp; /* Vertical front porch */ +- int vbp; /* Vertical back porch */ +- int acb; /* ac-bias pin frequency */ +- int pcd; /* pixel clock divider. +- Obsolete use pixel_clock instead */ +- +- int (*init) (struct lcd_panel *panel, +- struct omapfb_device *fbdev); +- void (*cleanup) (struct lcd_panel *panel); +- int (*enable) (struct lcd_panel *panel); +- void (*disable) (struct lcd_panel *panel); +- unsigned long (*get_caps) (struct lcd_panel *panel); +- int (*set_bklight_level)(struct lcd_panel *panel, +- unsigned int level); +- unsigned int (*get_bklight_level)(struct lcd_panel *panel); +- unsigned int (*get_bklight_max) (struct lcd_panel *panel); +- int (*run_test) (struct lcd_panel *panel, int test_num); +-}; +- +-struct extif_timings { +- int cs_on_time; +- int cs_off_time; +- int we_on_time; +- int we_off_time; +- int re_on_time; +- int re_off_time; +- int we_cycle_time; +- int re_cycle_time; +- int cs_pulse_width; +- int access_time; +- +- int clk_div; +- +- u32 tim[5]; /* set by extif->convert_timings */ +- +- int converted; +-}; +- +-struct lcd_ctrl_extif { +- int (*init) (struct omapfb_device *fbdev); +- void (*cleanup) (void); +- void (*get_clk_info) (u32 *clk_period, u32 *max_clk_div); +- unsigned long (*get_max_tx_rate)(void); +- int (*convert_timings) (struct extif_timings *timings); +- void (*set_timings) (const struct extif_timings *timings); +- void (*set_bits_per_cycle)(int bpc); +- void (*write_command) (const void *buf, unsigned int len); +- void (*read_data) (void *buf, unsigned int len); +- void (*write_data) (const void *buf, unsigned int len); +- void (*transfer_area) (int width, int height, +- void (callback)(void * data), void *data); +- int (*setup_tearsync) (unsigned pin_cnt, +- unsigned hs_pulse_time, unsigned vs_pulse_time, +- int hs_pol_inv, int vs_pol_inv, int div); +- int (*enable_tearsync) (int enable, unsigned line); +- +- unsigned long max_transmit_size; +-}; +- +-struct omapfb_notifier_block { +- struct notifier_block nb; +- void *data; +- int plane_idx; +-}; +- +-typedef int (*omapfb_notifier_callback_t)(struct notifier_block *, +- unsigned long event, +- void *fbi); +- +-struct omapfb_mem_region { +- u32 paddr; +- void __iomem *vaddr; +- unsigned long size; +- u8 type; /* OMAPFB_PLANE_MEM_* */ +- unsigned alloc:1; /* allocated by the driver */ +- unsigned map:1; /* kernel mapped by the driver */ +-}; +- +-struct omapfb_mem_desc { +- int region_cnt; +- struct omapfb_mem_region region[OMAPFB_PLANE_NUM]; +-}; +- +-struct lcd_ctrl { +- const char *name; +- void *data; +- +- int (*init) (struct omapfb_device *fbdev, +- int ext_mode, +- struct omapfb_mem_desc *req_md); +- void (*cleanup) (void); +- void (*bind_client) (struct omapfb_notifier_block *nb); +- void (*get_caps) (int plane, struct omapfb_caps *caps); +- int (*set_update_mode)(enum omapfb_update_mode mode); +- enum omapfb_update_mode (*get_update_mode)(void); +- int (*setup_plane) (int plane, int channel_out, +- unsigned long offset, +- int screen_width, +- int pos_x, int pos_y, int width, +- int height, int color_mode); +- int (*set_rotate) (int angle); +- int (*setup_mem) (int plane, size_t size, +- int mem_type, unsigned long *paddr); +- int (*mmap) (struct fb_info *info, +- struct vm_area_struct *vma); +- int (*set_scale) (int plane, +- int orig_width, int orig_height, +- int out_width, int out_height); +- int (*enable_plane) (int plane, int enable); +- int (*update_window) (struct fb_info *fbi, +- struct omapfb_update_window *win, +- void (*callback)(void *), +- void *callback_data); +- void (*sync) (void); +- void (*suspend) (void); +- void (*resume) (void); +- int (*run_test) (int test_num); +- int (*setcolreg) (u_int regno, u16 red, u16 green, +- u16 blue, u16 transp, +- int update_hw_mem); +- int (*set_color_key) (struct omapfb_color_key *ck); +- int (*get_color_key) (struct omapfb_color_key *ck); +-}; +- +-enum omapfb_state { +- OMAPFB_DISABLED = 0, +- OMAPFB_SUSPENDED= 99, +- OMAPFB_ACTIVE = 100 +-}; +- +-struct omapfb_plane_struct { +- int idx; +- struct omapfb_plane_info info; +- enum omapfb_color_format color_mode; +- struct omapfb_device *fbdev; +-}; +- +-struct omapfb_device { +- int state; +- int ext_lcdc; /* Using external +- LCD controller */ +- struct mutex rqueue_mutex; +- +- int palette_size; +- u32 pseudo_palette[17]; +- +- struct lcd_panel *panel; /* LCD panel */ +- const struct lcd_ctrl *ctrl; /* LCD controller */ +- const struct lcd_ctrl *int_ctrl; /* internal LCD ctrl */ +- struct lcd_ctrl_extif *ext_if; /* LCD ctrl external +- interface */ +- struct device *dev; +- struct fb_var_screeninfo new_var; /* for mode changes */ +- +- struct omapfb_mem_desc mem_desc; +- struct fb_info *fb_info[OMAPFB_PLANE_NUM]; +-}; +- +-struct omapfb_platform_data { +- struct omap_lcd_config lcd; +- struct omapfb_mem_desc mem_desc; +- void *ctrl_platform_data; +-}; +- +-#ifdef CONFIG_ARCH_OMAP1 +-extern struct lcd_ctrl omap1_lcd_ctrl; +-#else +-extern struct lcd_ctrl omap2_disp_ctrl; +-#endif +- +-extern void omapfb_reserve_sdram(void); +-extern void omapfb_register_panel(struct lcd_panel *panel); +-extern void omapfb_write_first_pixel(struct omapfb_device *fbdev, u16 pixval); +-extern void omapfb_notify_clients(struct omapfb_device *fbdev, +- unsigned long event); +-extern int omapfb_register_client(struct omapfb_notifier_block *nb, +- omapfb_notifier_callback_t callback, +- void *callback_data); +-extern int omapfb_unregister_client(struct omapfb_notifier_block *nb); +-extern int omapfb_update_window_async(struct fb_info *fbi, +- struct omapfb_update_window *win, +- void (*callback)(void *), +- void *callback_data); +- +-/* in arch/arm/plat-omap/fb.c */ +-extern void omapfb_set_ctrl_platform_data(void *pdata); +- +-#endif /* __KERNEL__ */ +- +-#endif /* __OMAPFB_H */ +diff --git a/arch/arm/plat-omap/include/mach/sdrc.h b/arch/arm/plat-omap/include/mach/sdrc.h +index 1c09c78..3b157ce 100644 +--- a/arch/arm/plat-omap/include/mach/sdrc.h ++++ b/arch/arm/plat-omap/include/mach/sdrc.h +@@ -88,7 +88,10 @@ + + /* SMS register offsets - read/write with sms_{read,write}_reg() */ + +-#define SMS_SYSCONFIG 0x010 ++#define SMS_SYSCONFIG 0x010 ++#define SMS_ROT_CONTROL(context) (0x180 + 0x10 * context) ++#define SMS_ROT_SIZE(context) (0x184 + 0x10 * context) ++#define SMS_ROT_PHYSICAL_BA(context) (0x188 + 0x10 * context) + /* REVISIT: fill in other SMS registers here */ + + +@@ -121,6 +124,10 @@ int omap2_sdrc_get_params(unsigned long r, + struct omap_sdrc_params **sdrc_cs0, + struct omap_sdrc_params **sdrc_cs1); + ++void omap2_sms_write_rot_control(u32 val, unsigned ctx); ++void omap2_sms_write_rot_size(u32 val, unsigned ctx); ++void omap2_sms_write_rot_physical_ba(u32 val, unsigned ctx); ++ + #ifdef CONFIG_ARCH_OMAP2 + + struct memory_timings { +diff --git a/arch/arm/plat-omap/include/mach/vram.h b/arch/arm/plat-omap/include/mach/vram.h +new file mode 100644 +index 0000000..fe72f81 +--- /dev/null ++++ b/arch/arm/plat-omap/include/mach/vram.h +@@ -0,0 +1,63 @@ ++/* ++ * VRAM manager for OMAP ++ * ++ * Copyright (C) 2009 Nokia Corporation ++ * Author: Tomi Valkeinen ++ * ++ * 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. ++ * ++ * 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, MA 02111-1307, USA. ++ */ ++ ++#ifndef __OMAP_VRAM_H__ ++#define __OMAP_VRAM_H__ ++ ++#include ++#include ++ ++#define OMAP_VRAM_MEMTYPE_SDRAM 0 ++#define OMAP_VRAM_MEMTYPE_SRAM 1 ++#define OMAP_VRAM_MEMTYPE_MAX 1 ++ ++extern int omap_vram_add_region(unsigned long paddr, size_t size); ++extern int omap_vram_free(unsigned long paddr, size_t size); ++extern int omap_vram_alloc(int mtype, size_t size, unsigned long *paddr); ++extern int omap_vram_reserve(unsigned long paddr, size_t size); ++extern void omap_vram_get_info(unsigned long *vram, unsigned long *free_vram, ++ unsigned long *largest_free_block); ++ ++#ifdef CONFIG_OMAP2_VRAM ++extern void omap_vram_set_sdram_vram(u32 size, u32 start); ++extern void omap_vram_set_sram_vram(u32 size, u32 start); ++ ++extern void omap_vram_reserve_sdram(void); ++extern unsigned long omap_vram_reserve_sram(unsigned long sram_pstart, ++ unsigned long sram_vstart, ++ unsigned long sram_size, ++ unsigned long pstart_avail, ++ unsigned long size_avail); ++#else ++static inline void omap_vram_set_sdram_vram(u32 size, u32 start) { } ++static inline void omap_vram_set_sram_vram(u32 size, u32 start) { } ++ ++static inline void omap_vram_reserve_sdram(void) { } ++static inline unsigned long omap_vram_reserve_sram(unsigned long sram_pstart, ++ unsigned long sram_vstart, ++ unsigned long sram_size, ++ unsigned long pstart_avail, ++ unsigned long size_avail) ++{ ++ return 0; ++} ++#endif ++ ++#endif +diff --git a/arch/arm/plat-omap/include/mach/vrfb.h b/arch/arm/plat-omap/include/mach/vrfb.h +new file mode 100644 +index 0000000..8790612 +--- /dev/null ++++ b/arch/arm/plat-omap/include/mach/vrfb.h +@@ -0,0 +1,46 @@ ++/* ++ * VRFB Rotation Engine ++ * ++ * Copyright (C) 2009 Nokia Corporation ++ * Author: Tomi Valkeinen ++ * ++ * 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. ++ * ++ * 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, MA 02111-1307, USA. ++ */ ++ ++#ifndef __OMAP_VRFB_H__ ++#define __OMAP_VRFB_H__ ++ ++#define OMAP_VRFB_LINE_LEN 2048 ++ ++struct vrfb { ++ u8 context; ++ void __iomem *vaddr[4]; ++ unsigned long paddr[4]; ++ u16 xoffset; ++ u16 yoffset; ++ u8 bytespp; ++}; ++ ++extern int omap_vrfb_request_ctx(struct vrfb *vrfb); ++extern void omap_vrfb_release_ctx(struct vrfb *vrfb); ++extern void omap_vrfb_suspend_ctx(struct vrfb *vrfb); ++extern void omap_vrfb_resume_ctx(struct vrfb *vrfb); ++extern void omap_vrfb_adjust_size(u16 *width, u16 *height, ++ u8 bytespp); ++extern void omap_vrfb_setup(struct vrfb *vrfb, unsigned long paddr, ++ u16 width, u16 height, ++ unsigned bytespp, bool yuv_mode); ++extern void omap_vrfb_restore_context(void); ++ ++#endif /* __VRFB_H */ +diff --git a/arch/arm/plat-omap/sram.c b/arch/arm/plat-omap/sram.c +index 75d1f26..aa9fb63 100644 +--- a/arch/arm/plat-omap/sram.c ++++ b/arch/arm/plat-omap/sram.c +@@ -28,6 +28,7 @@ + #include + #include + #include ++#include + + #include + +@@ -185,6 +186,13 @@ void __init omap_detect_sram(void) + omap_sram_start + SRAM_BOOTLOADER_SZ, + omap_sram_size - SRAM_BOOTLOADER_SZ); + omap_sram_size -= reserved; ++ ++ reserved = omap_vram_reserve_sram(omap_sram_start, omap_sram_base, ++ omap_sram_size, ++ omap_sram_start + SRAM_BOOTLOADER_SZ, ++ omap_sram_size - SRAM_BOOTLOADER_SZ); ++ omap_sram_size -= reserved; ++ + omap_sram_ceil = omap_sram_base + omap_sram_size; + } + +diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig +index 9bbb285..af0448f 100644 +--- a/drivers/video/Kconfig ++++ b/drivers/video/Kconfig +@@ -2161,6 +2161,7 @@ config FB_BROADSHEET + a bridge adapter. + + source "drivers/video/omap/Kconfig" ++source "drivers/video/omap2/Kconfig" + + source "drivers/video/backlight/Kconfig" + source "drivers/video/display/Kconfig" +diff --git a/drivers/video/Makefile b/drivers/video/Makefile +index 80232e1..0f8da33 100644 +--- a/drivers/video/Makefile ++++ b/drivers/video/Makefile +@@ -124,6 +124,7 @@ obj-$(CONFIG_FB_SM501) += sm501fb.o + obj-$(CONFIG_FB_XILINX) += xilinxfb.o + obj-$(CONFIG_FB_SH_MOBILE_LCDC) += sh_mobile_lcdcfb.o + obj-$(CONFIG_FB_OMAP) += omap/ ++obj-y += omap2/ + obj-$(CONFIG_XEN_FBDEV_FRONTEND) += xen-fbfront.o + obj-$(CONFIG_FB_CARMINE) += carminefb.o + obj-$(CONFIG_FB_MB862XX) += mb862xx/ +diff --git a/drivers/video/omap/Kconfig b/drivers/video/omap/Kconfig +index 551e3e9..455c605 100644 +--- a/drivers/video/omap/Kconfig ++++ b/drivers/video/omap/Kconfig +@@ -1,6 +1,7 @@ + config FB_OMAP + tristate "OMAP frame buffer support (EXPERIMENTAL)" +- depends on FB && ARCH_OMAP ++ depends on FB && ARCH_OMAP && (OMAP2_DSS = "n") ++ + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT +@@ -72,7 +73,7 @@ config FB_OMAP_LCD_MIPID + + config FB_OMAP_BOOTLOADER_INIT + bool "Check bootloader initialization" +- depends on FB_OMAP ++ depends on FB_OMAP || FB_OMAP2 + help + Say Y here if you want to enable checking if the bootloader has + already initialized the display controller. In this case the +diff --git a/drivers/video/omap/blizzard.c b/drivers/video/omap/blizzard.c +index 70dadf9..e0d693e 100644 +--- a/drivers/video/omap/blizzard.c ++++ b/drivers/video/omap/blizzard.c +@@ -27,9 +27,9 @@ + #include + + #include +-#include + #include + ++#include "omapfb.h" + #include "dispc.h" + + #define MODULE_NAME "blizzard" +diff --git a/drivers/video/omap/dispc.c b/drivers/video/omap/dispc.c +index f16e421..3f828e6 100644 +--- a/drivers/video/omap/dispc.c ++++ b/drivers/video/omap/dispc.c +@@ -24,11 +24,12 @@ + #include + #include + #include ++#include + + #include +-#include + #include + ++#include "omapfb.h" + #include "dispc.h" + + #define MODULE_NAME "dispc" +@@ -188,6 +189,11 @@ static struct { + struct omapfb_color_key color_key; + } dispc; + ++static struct platform_device omapdss_device = { ++ .name = "omapdss", ++ .id = -1, ++}; ++ + static void enable_lcd_clocks(int enable); + + static void inline dispc_write_reg(int idx, u32 val) +@@ -907,20 +913,20 @@ static irqreturn_t omap_dispc_irq_handler(int irq, void *dev) + + static int get_dss_clocks(void) + { +- dispc.dss_ick = clk_get(dispc.fbdev->dev, "ick"); ++ dispc.dss_ick = clk_get(&omapdss_device.dev, "ick"); + if (IS_ERR(dispc.dss_ick)) { + dev_err(dispc.fbdev->dev, "can't get ick\n"); + return PTR_ERR(dispc.dss_ick); + } + +- dispc.dss1_fck = clk_get(dispc.fbdev->dev, "dss1_fck"); ++ dispc.dss1_fck = clk_get(&omapdss_device.dev, "dss1_fck"); + if (IS_ERR(dispc.dss1_fck)) { + dev_err(dispc.fbdev->dev, "can't get dss1_fck\n"); + clk_put(dispc.dss_ick); + return PTR_ERR(dispc.dss1_fck); + } + +- dispc.dss_54m_fck = clk_get(dispc.fbdev->dev, "tv_fck"); ++ dispc.dss_54m_fck = clk_get(&omapdss_device.dev, "tv_fck"); + if (IS_ERR(dispc.dss_54m_fck)) { + dev_err(dispc.fbdev->dev, "can't get tv_fck\n"); + clk_put(dispc.dss_ick); +@@ -1371,6 +1377,12 @@ static int omap_dispc_init(struct omapfb_device *fbdev, int ext_mode, + int skip_init = 0; + int i; + ++ r = platform_device_register(&omapdss_device); ++ if (r) { ++ dev_err(fbdev->dev, "can't register omapdss device\n"); ++ return r; ++ } ++ + memset(&dispc, 0, sizeof(dispc)); + + dispc.base = ioremap(DISPC_BASE, SZ_1K); +@@ -1508,6 +1520,7 @@ static void omap_dispc_cleanup(void) + free_irq(INT_24XX_DSS_IRQ, dispc.fbdev); + put_dss_clocks(); + iounmap(dispc.base); ++ platform_device_unregister(&omapdss_device); + } + + const struct lcd_ctrl omap2_int_ctrl = { +diff --git a/drivers/video/omap/hwa742.c b/drivers/video/omap/hwa742.c +index ca51583..b84fb7c 100644 +--- a/drivers/video/omap/hwa742.c ++++ b/drivers/video/omap/hwa742.c +@@ -27,8 +27,8 @@ + #include + + #include +-#include + #include ++#include "omapfb.h" + + #define HWA742_REV_CODE_REG 0x0 + #define HWA742_CONFIG_REG 0x2 +diff --git a/drivers/video/omap/lcd_2430sdp.c b/drivers/video/omap/lcd_2430sdp.c +index 393712b..7b7690a 100644 +--- a/drivers/video/omap/lcd_2430sdp.c ++++ b/drivers/video/omap/lcd_2430sdp.c +@@ -28,9 +28,10 @@ + #include + + #include +-#include + #include + ++#include "omapfb.h" ++ + #define SDP2430_LCD_PANEL_BACKLIGHT_GPIO 91 + #define SDP2430_LCD_PANEL_ENABLE_GPIO 154 + #define SDP3430_LCD_PANEL_BACKLIGHT_GPIO 24 +diff --git a/drivers/video/omap/lcd_ams_delta.c b/drivers/video/omap/lcd_ams_delta.c +index 1f74399..1d3fd13 100644 +--- a/drivers/video/omap/lcd_ams_delta.c ++++ b/drivers/video/omap/lcd_ams_delta.c +@@ -27,7 +27,8 @@ + + #include + #include +-#include ++ ++#include "omapfb.h" + + #define AMS_DELTA_DEFAULT_CONTRAST 112 + +diff --git a/drivers/video/omap/lcd_apollon.c b/drivers/video/omap/lcd_apollon.c +index 626ae3a..e099ad1 100644 +--- a/drivers/video/omap/lcd_apollon.c ++++ b/drivers/video/omap/lcd_apollon.c +@@ -26,7 +26,8 @@ + + #include + #include +-#include ++ ++#include "omapfb.h" + + /* #define USE_35INCH_LCD 1 */ + +diff --git a/drivers/video/omap/lcd_h3.c b/drivers/video/omap/lcd_h3.c +index 417ae5e..8df6887 100644 +--- a/drivers/video/omap/lcd_h3.c ++++ b/drivers/video/omap/lcd_h3.c +@@ -24,7 +24,7 @@ + #include + + #include +-#include ++#include "omapfb.h" + + #define MODULE_NAME "omapfb-lcd_h3" + +diff --git a/drivers/video/omap/lcd_h4.c b/drivers/video/omap/lcd_h4.c +index 0c398bd..03a06a9 100644 +--- a/drivers/video/omap/lcd_h4.c ++++ b/drivers/video/omap/lcd_h4.c +@@ -22,7 +22,7 @@ + #include + #include + +-#include ++#include "omapfb.h" + + static int h4_panel_init(struct lcd_panel *panel, struct omapfb_device *fbdev) + { +diff --git a/drivers/video/omap/lcd_inn1510.c b/drivers/video/omap/lcd_inn1510.c +index cdbd8bb..18f1422 100644 +--- a/drivers/video/omap/lcd_inn1510.c ++++ b/drivers/video/omap/lcd_inn1510.c +@@ -24,7 +24,7 @@ + #include + + #include +-#include ++#include "omapfb.h" + + static int innovator1510_panel_init(struct lcd_panel *panel, + struct omapfb_device *fbdev) +diff --git a/drivers/video/omap/lcd_inn1610.c b/drivers/video/omap/lcd_inn1610.c +index 268f7f8..9fff86f 100644 +--- a/drivers/video/omap/lcd_inn1610.c ++++ b/drivers/video/omap/lcd_inn1610.c +@@ -23,7 +23,7 @@ + #include + + #include +-#include ++#include "omapfb.h" + + #define MODULE_NAME "omapfb-lcd_h3" + +diff --git a/drivers/video/omap/lcd_ldp.c b/drivers/video/omap/lcd_ldp.c +index dbfe897..44a43ea 100644 +--- a/drivers/video/omap/lcd_ldp.c ++++ b/drivers/video/omap/lcd_ldp.c +@@ -28,9 +28,10 @@ + + #include + #include +-#include + #include + ++#include "omapfb.h" ++ + #define LCD_PANEL_BACKLIGHT_GPIO (15 + OMAP_MAX_GPIO_LINES) + #define LCD_PANEL_ENABLE_GPIO (7 + OMAP_MAX_GPIO_LINES) + +diff --git a/drivers/video/omap/lcd_mipid.c b/drivers/video/omap/lcd_mipid.c +index 918ee89..62e1975 100644 +--- a/drivers/video/omap/lcd_mipid.c ++++ b/drivers/video/omap/lcd_mipid.c +@@ -23,9 +23,10 @@ + #include + #include + +-#include + #include + ++#include "omapfb.h" ++ + #define MIPID_MODULE_NAME "lcd_mipid" + + #define MIPID_CMD_READ_DISP_ID 0x04 +diff --git a/drivers/video/omap/lcd_omap2evm.c b/drivers/video/omap/lcd_omap2evm.c +index 7a2bbe2..c3be87c 100644 +--- a/drivers/video/omap/lcd_omap2evm.c ++++ b/drivers/video/omap/lcd_omap2evm.c +@@ -27,9 +27,10 @@ + #include + + #include +-#include + #include + ++#include "omapfb.h" ++ + #define LCD_PANEL_ENABLE_GPIO 154 + #define LCD_PANEL_LR 128 + #define LCD_PANEL_UD 129 +diff --git a/drivers/video/omap/lcd_omap3beagle.c b/drivers/video/omap/lcd_omap3beagle.c +index 4011910..0608a25 100644 +--- a/drivers/video/omap/lcd_omap3beagle.c ++++ b/drivers/video/omap/lcd_omap3beagle.c +@@ -26,9 +26,10 @@ + #include + + #include +-#include + #include + ++#include "omapfb.h" ++ + #define LCD_PANEL_ENABLE_GPIO 170 + + static int omap3beagle_panel_init(struct lcd_panel *panel, +diff --git a/drivers/video/omap/lcd_omap3evm.c b/drivers/video/omap/lcd_omap3evm.c +index b6a4c2c..c204afb 100644 +--- a/drivers/video/omap/lcd_omap3evm.c ++++ b/drivers/video/omap/lcd_omap3evm.c +@@ -26,9 +26,10 @@ + #include + + #include +-#include + #include + ++#include "omapfb.h" ++ + #define LCD_PANEL_ENABLE_GPIO 153 + #define LCD_PANEL_LR 2 + #define LCD_PANEL_UD 3 +diff --git a/drivers/video/omap/lcd_osk.c b/drivers/video/omap/lcd_osk.c +index b3fa88b..5755b5c 100644 +--- a/drivers/video/omap/lcd_osk.c ++++ b/drivers/video/omap/lcd_osk.c +@@ -25,7 +25,7 @@ + + #include + #include +-#include ++#include "omapfb.h" + + static int osk_panel_init(struct lcd_panel *panel, struct omapfb_device *fbdev) + { +diff --git a/drivers/video/omap/lcd_overo.c b/drivers/video/omap/lcd_overo.c +index 2bc5c92..63ebb1f 100644 +--- a/drivers/video/omap/lcd_overo.c ++++ b/drivers/video/omap/lcd_overo.c +@@ -25,9 +25,10 @@ + + #include + #include +-#include + #include + ++#include "omapfb.h" ++ + #define LCD_ENABLE 144 + + static int overo_panel_init(struct lcd_panel *panel, +diff --git a/drivers/video/omap/lcd_palmte.c b/drivers/video/omap/lcd_palmte.c +index 4bf3c79..7e11a75 100644 +--- a/drivers/video/omap/lcd_palmte.c ++++ b/drivers/video/omap/lcd_palmte.c +@@ -24,7 +24,7 @@ + #include + + #include +-#include ++#include "omapfb.h" + + static int palmte_panel_init(struct lcd_panel *panel, + struct omapfb_device *fbdev) +diff --git a/drivers/video/omap/lcd_palmtt.c b/drivers/video/omap/lcd_palmtt.c +index 48ea1f9..ff0e6d7 100644 +--- a/drivers/video/omap/lcd_palmtt.c ++++ b/drivers/video/omap/lcd_palmtt.c +@@ -30,7 +30,7 @@ GPIO13 - screen blanking + #include + + #include +-#include ++#include "omapfb.h" + + static int palmtt_panel_init(struct lcd_panel *panel, + struct omapfb_device *fbdev) +diff --git a/drivers/video/omap/lcd_palmz71.c b/drivers/video/omap/lcd_palmz71.c +index 0697d29..2334e56 100644 +--- a/drivers/video/omap/lcd_palmz71.c ++++ b/drivers/video/omap/lcd_palmz71.c +@@ -24,7 +24,7 @@ + #include + #include + +-#include ++#include "omapfb.h" + + static int palmz71_panel_init(struct lcd_panel *panel, + struct omapfb_device *fbdev) +diff --git a/drivers/video/omap/lcdc.c b/drivers/video/omap/lcdc.c +index ab39492..520ed97 100644 +--- a/drivers/video/omap/lcdc.c ++++ b/drivers/video/omap/lcdc.c +@@ -30,10 +30,11 @@ + #include + + #include +-#include + + #include + ++#include "omapfb.h" ++ + #include "lcdc.h" + + #define MODULE_NAME "lcdc" +diff --git a/drivers/video/omap/omapfb.h b/drivers/video/omap/omapfb.h +new file mode 100644 +index 0000000..46e4714 +--- /dev/null ++++ b/drivers/video/omap/omapfb.h +@@ -0,0 +1,227 @@ ++/* ++ * File: drivers/video/omap/omapfb.h ++ * ++ * Framebuffer driver for TI OMAP boards ++ * ++ * Copyright (C) 2004 Nokia Corporation ++ * Author: Imre Deak ++ * ++ * 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, MA 02111-1307, USA. ++ */ ++ ++#ifndef __OMAPFB_H ++#define __OMAPFB_H ++ ++#include ++#include ++#include ++ ++#define OMAPFB_EVENT_READY 1 ++#define OMAPFB_EVENT_DISABLED 2 ++ ++#define OMAP_LCDC_INV_VSYNC 0x0001 ++#define OMAP_LCDC_INV_HSYNC 0x0002 ++#define OMAP_LCDC_INV_PIX_CLOCK 0x0004 ++#define OMAP_LCDC_INV_OUTPUT_EN 0x0008 ++#define OMAP_LCDC_HSVS_RISING_EDGE 0x0010 ++#define OMAP_LCDC_HSVS_OPPOSITE 0x0020 ++ ++#define OMAP_LCDC_SIGNAL_MASK 0x003f ++ ++#define OMAP_LCDC_PANEL_TFT 0x0100 ++ ++#define OMAPFB_PLANE_XRES_MIN 8 ++#define OMAPFB_PLANE_YRES_MIN 8 ++ ++struct omapfb_device; ++ ++struct lcd_panel { ++ const char *name; ++ int config; /* TFT/STN, signal inversion */ ++ int bpp; /* Pixel format in fb mem */ ++ int data_lines; /* Lines on LCD HW interface */ ++ ++ int x_res, y_res; ++ int pixel_clock; /* In kHz */ ++ int hsw; /* Horizontal synchronization ++ pulse width */ ++ int hfp; /* Horizontal front porch */ ++ int hbp; /* Horizontal back porch */ ++ int vsw; /* Vertical synchronization ++ pulse width */ ++ int vfp; /* Vertical front porch */ ++ int vbp; /* Vertical back porch */ ++ int acb; /* ac-bias pin frequency */ ++ int pcd; /* pixel clock divider. ++ Obsolete use pixel_clock instead */ ++ ++ int (*init) (struct lcd_panel *panel, ++ struct omapfb_device *fbdev); ++ void (*cleanup) (struct lcd_panel *panel); ++ int (*enable) (struct lcd_panel *panel); ++ void (*disable) (struct lcd_panel *panel); ++ unsigned long (*get_caps) (struct lcd_panel *panel); ++ int (*set_bklight_level)(struct lcd_panel *panel, ++ unsigned int level); ++ unsigned int (*get_bklight_level)(struct lcd_panel *panel); ++ unsigned int (*get_bklight_max) (struct lcd_panel *panel); ++ int (*run_test) (struct lcd_panel *panel, int test_num); ++}; ++ ++struct extif_timings { ++ int cs_on_time; ++ int cs_off_time; ++ int we_on_time; ++ int we_off_time; ++ int re_on_time; ++ int re_off_time; ++ int we_cycle_time; ++ int re_cycle_time; ++ int cs_pulse_width; ++ int access_time; ++ ++ int clk_div; ++ ++ u32 tim[5]; /* set by extif->convert_timings */ ++ ++ int converted; ++}; ++ ++struct lcd_ctrl_extif { ++ int (*init) (struct omapfb_device *fbdev); ++ void (*cleanup) (void); ++ void (*get_clk_info) (u32 *clk_period, u32 *max_clk_div); ++ unsigned long (*get_max_tx_rate)(void); ++ int (*convert_timings) (struct extif_timings *timings); ++ void (*set_timings) (const struct extif_timings *timings); ++ void (*set_bits_per_cycle)(int bpc); ++ void (*write_command) (const void *buf, unsigned int len); ++ void (*read_data) (void *buf, unsigned int len); ++ void (*write_data) (const void *buf, unsigned int len); ++ void (*transfer_area) (int width, int height, ++ void (callback)(void *data), void *data); ++ int (*setup_tearsync) (unsigned pin_cnt, ++ unsigned hs_pulse_time, unsigned vs_pulse_time, ++ int hs_pol_inv, int vs_pol_inv, int div); ++ int (*enable_tearsync) (int enable, unsigned line); ++ ++ unsigned long max_transmit_size; ++}; ++ ++struct omapfb_notifier_block { ++ struct notifier_block nb; ++ void *data; ++ int plane_idx; ++}; ++ ++typedef int (*omapfb_notifier_callback_t)(struct notifier_block *, ++ unsigned long event, ++ void *fbi); ++ ++struct lcd_ctrl { ++ const char *name; ++ void *data; ++ ++ int (*init) (struct omapfb_device *fbdev, ++ int ext_mode, ++ struct omapfb_mem_desc *req_md); ++ void (*cleanup) (void); ++ void (*bind_client) (struct omapfb_notifier_block *nb); ++ void (*get_caps) (int plane, struct omapfb_caps *caps); ++ int (*set_update_mode)(enum omapfb_update_mode mode); ++ enum omapfb_update_mode (*get_update_mode)(void); ++ int (*setup_plane) (int plane, int channel_out, ++ unsigned long offset, ++ int screen_width, ++ int pos_x, int pos_y, int width, ++ int height, int color_mode); ++ int (*set_rotate) (int angle); ++ int (*setup_mem) (int plane, size_t size, ++ int mem_type, unsigned long *paddr); ++ int (*mmap) (struct fb_info *info, ++ struct vm_area_struct *vma); ++ int (*set_scale) (int plane, ++ int orig_width, int orig_height, ++ int out_width, int out_height); ++ int (*enable_plane) (int plane, int enable); ++ int (*update_window) (struct fb_info *fbi, ++ struct omapfb_update_window *win, ++ void (*callback)(void *), ++ void *callback_data); ++ void (*sync) (void); ++ void (*suspend) (void); ++ void (*resume) (void); ++ int (*run_test) (int test_num); ++ int (*setcolreg) (u_int regno, u16 red, u16 green, ++ u16 blue, u16 transp, ++ int update_hw_mem); ++ int (*set_color_key) (struct omapfb_color_key *ck); ++ int (*get_color_key) (struct omapfb_color_key *ck); ++}; ++ ++enum omapfb_state { ++ OMAPFB_DISABLED = 0, ++ OMAPFB_SUSPENDED = 99, ++ OMAPFB_ACTIVE = 100 ++}; ++ ++struct omapfb_plane_struct { ++ int idx; ++ struct omapfb_plane_info info; ++ enum omapfb_color_format color_mode; ++ struct omapfb_device *fbdev; ++}; ++ ++struct omapfb_device { ++ int state; ++ int ext_lcdc; /* Using external ++ LCD controller */ ++ struct mutex rqueue_mutex; ++ ++ int palette_size; ++ u32 pseudo_palette[17]; ++ ++ struct lcd_panel *panel; /* LCD panel */ ++ const struct lcd_ctrl *ctrl; /* LCD controller */ ++ const struct lcd_ctrl *int_ctrl; /* internal LCD ctrl */ ++ struct lcd_ctrl_extif *ext_if; /* LCD ctrl external ++ interface */ ++ struct device *dev; ++ struct fb_var_screeninfo new_var; /* for mode changes */ ++ ++ struct omapfb_mem_desc mem_desc; ++ struct fb_info *fb_info[OMAPFB_PLANE_NUM]; ++}; ++ ++#ifdef CONFIG_ARCH_OMAP1 ++extern struct lcd_ctrl omap1_lcd_ctrl; ++#else ++extern struct lcd_ctrl omap2_disp_ctrl; ++#endif ++ ++extern void omapfb_register_panel(struct lcd_panel *panel); ++extern void omapfb_write_first_pixel(struct omapfb_device *fbdev, u16 pixval); ++extern void omapfb_notify_clients(struct omapfb_device *fbdev, ++ unsigned long event); ++extern int omapfb_register_client(struct omapfb_notifier_block *nb, ++ omapfb_notifier_callback_t callback, ++ void *callback_data); ++extern int omapfb_unregister_client(struct omapfb_notifier_block *nb); ++extern int omapfb_update_window_async(struct fb_info *fbi, ++ struct omapfb_update_window *win, ++ void (*callback)(void *), ++ void *callback_data); ++ ++#endif /* __OMAPFB_H */ +diff --git a/drivers/video/omap/omapfb_main.c b/drivers/video/omap/omapfb_main.c +index 0d0c8c8..a27614d 100644 +--- a/drivers/video/omap/omapfb_main.c ++++ b/drivers/video/omap/omapfb_main.c +@@ -29,8 +29,8 @@ + #include + + #include +-#include + ++#include "omapfb.h" + #include "lcdc.h" + #include "dispc.h" + +diff --git a/drivers/video/omap/rfbi.c b/drivers/video/omap/rfbi.c +index ee01e84..fed7b1b 100644 +--- a/drivers/video/omap/rfbi.c ++++ b/drivers/video/omap/rfbi.c +@@ -27,8 +27,7 @@ + #include + #include + +-#include +- ++#include "omapfb.h" + #include "dispc.h" + + /* To work around an RFBI transfer rate limitation */ +diff --git a/drivers/video/omap/sossi.c b/drivers/video/omap/sossi.c +index a769462..6853627 100644 +--- a/drivers/video/omap/sossi.c ++++ b/drivers/video/omap/sossi.c +@@ -25,8 +25,8 @@ + #include + + #include +-#include + ++#include "omapfb.h" + #include "lcdc.h" + + #define MODULE_NAME "omapfb-sossi" +diff --git a/drivers/video/omap2/Kconfig b/drivers/video/omap2/Kconfig +new file mode 100644 +index 0000000..d877c36 +--- /dev/null ++++ b/drivers/video/omap2/Kconfig +@@ -0,0 +1,9 @@ ++config OMAP2_VRAM ++ bool ++ ++config OMAP2_VRFB ++ bool ++ ++source "drivers/video/omap2/dss/Kconfig" ++source "drivers/video/omap2/omapfb/Kconfig" ++source "drivers/video/omap2/displays/Kconfig" +diff --git a/drivers/video/omap2/Makefile b/drivers/video/omap2/Makefile +new file mode 100644 +index 0000000..d853d05 +--- /dev/null ++++ b/drivers/video/omap2/Makefile +@@ -0,0 +1,6 @@ ++obj-$(CONFIG_OMAP2_VRAM) += vram.o ++obj-$(CONFIG_OMAP2_VRFB) += vrfb.o ++ ++obj-y += dss/ ++obj-y += omapfb/ ++obj-y += displays/ +diff --git a/drivers/video/omap2/displays/Kconfig b/drivers/video/omap2/displays/Kconfig +new file mode 100644 +index 0000000..79d2861 +--- /dev/null ++++ b/drivers/video/omap2/displays/Kconfig +@@ -0,0 +1,28 @@ ++menu "OMAP2/3 Display Device Drivers" ++ depends on OMAP2_DSS ++ ++config PANEL_GENERIC ++ tristate "Generic Panel" ++ help ++ Generic panel driver. ++ Used for DVI output for Beagle and OMAP3 SDP. ++ ++config PANEL_SAMSUNG_LTE430WQ_F0C ++ tristate "Samsung LTE430WQ-F0C LCD Panel" ++ depends on OMAP2_DSS ++ help ++ LCD Panel used on Overo Palo43 ++ ++config PANEL_SHARP_LS037V7DW01 ++ tristate "Sharp LS037V7DW01 LCD Panel" ++ depends on OMAP2_DSS ++ help ++ LCD Panel used in TI's SDP3430 and EVM boards ++ ++config PANEL_TAAL ++ tristate "Taal DSI Panel" ++ depends on OMAP2_DSS_DSI ++ help ++ Taal DSI command mode panel from TPO. ++ ++endmenu +diff --git a/drivers/video/omap2/displays/Makefile b/drivers/video/omap2/displays/Makefile +new file mode 100644 +index 0000000..d44e765 +--- /dev/null ++++ b/drivers/video/omap2/displays/Makefile +@@ -0,0 +1,5 @@ ++obj-$(CONFIG_PANEL_GENERIC) += panel-generic.o ++obj-$(CONFIG_PANEL_SAMSUNG_LTE430WQ_F0C) += panel-samsung-lte430wq-f0c.o ++obj-$(CONFIG_PANEL_SHARP_LS037V7DW01) += panel-sharp-ls037v7dw01.o ++ ++obj-$(CONFIG_PANEL_TAAL) += panel-taal.o +diff --git a/drivers/video/omap2/displays/panel-generic.c b/drivers/video/omap2/displays/panel-generic.c +new file mode 100644 +index 0000000..738147e +--- /dev/null ++++ b/drivers/video/omap2/displays/panel-generic.c +@@ -0,0 +1,104 @@ ++/* ++ * Generic panel support ++ * ++ * Copyright (C) 2008 Nokia Corporation ++ * Author: Tomi Valkeinen ++ * ++ * 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. ++ * ++ * 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, see . ++ */ ++ ++#include ++#include ++ ++#include ++ ++static struct omap_video_timings generic_panel_timings = { ++ /* 640 x 480 @ 60 Hz Reduced blanking VESA CVT 0.31M3-R */ ++ .x_res = 640, ++ .y_res = 480, ++ .pixel_clock = 23500, ++ .hfp = 48, ++ .hsw = 32, ++ .hbp = 80, ++ .vfp = 3, ++ .vsw = 4, ++ .vbp = 7, ++}; ++ ++static int generic_panel_probe(struct omap_dss_device *dssdev) ++{ ++ dssdev->panel.config = OMAP_DSS_LCD_TFT; ++ dssdev->panel.timings = generic_panel_timings; ++ ++ return 0; ++} ++ ++static void generic_panel_remove(struct omap_dss_device *dssdev) ++{ ++} ++ ++static int generic_panel_enable(struct omap_dss_device *dssdev) ++{ ++ int r = 0; ++ ++ if (dssdev->platform_enable) ++ r = dssdev->platform_enable(dssdev); ++ ++ return r; ++} ++ ++static void generic_panel_disable(struct omap_dss_device *dssdev) ++{ ++ if (dssdev->platform_disable) ++ dssdev->platform_disable(dssdev); ++} ++ ++static int generic_panel_suspend(struct omap_dss_device *dssdev) ++{ ++ generic_panel_disable(dssdev); ++ return 0; ++} ++ ++static int generic_panel_resume(struct omap_dss_device *dssdev) ++{ ++ return generic_panel_enable(dssdev); ++} ++ ++static struct omap_dss_driver generic_driver = { ++ .probe = generic_panel_probe, ++ .remove = generic_panel_remove, ++ ++ .enable = generic_panel_enable, ++ .disable = generic_panel_disable, ++ .suspend = generic_panel_suspend, ++ .resume = generic_panel_resume, ++ ++ .driver = { ++ .name = "generic_panel", ++ .owner = THIS_MODULE, ++ }, ++}; ++ ++static int __init generic_panel_drv_init(void) ++{ ++ return omap_dss_register_driver(&generic_driver); ++} ++ ++static void __exit generic_panel_drv_exit(void) ++{ ++ omap_dss_unregister_driver(&generic_driver); ++} ++ ++module_init(generic_panel_drv_init); ++module_exit(generic_panel_drv_exit); ++MODULE_LICENSE("GPL"); +diff --git a/drivers/video/omap2/displays/panel-samsung-lte430wq-f0c.c b/drivers/video/omap2/displays/panel-samsung-lte430wq-f0c.c +new file mode 100644 +index 0000000..eafe581 +--- /dev/null ++++ b/drivers/video/omap2/displays/panel-samsung-lte430wq-f0c.c +@@ -0,0 +1,113 @@ ++/* ++ * LCD panel driver for Samsung LTE430WQ-F0C ++ * ++ * Author: Steve Sakoman ++ * ++ * 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. ++ * ++ * 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, see . ++ */ ++ ++#include ++#include ++ ++#include ++ ++static struct omap_video_timings samsung_lte_timings = { ++ .x_res = 480, ++ .y_res = 272, ++ ++ .pixel_clock = 9200, ++ ++ .hsw = 41, ++ .hfp = 8, ++ .hbp = 45-41, ++ ++ .vsw = 10, ++ .vfp = 4, ++ .vbp = 12-10, ++}; ++ ++static int samsung_lte_panel_probe(struct omap_dss_device *dssdev) ++{ ++ dssdev->panel.config = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IVS | ++ OMAP_DSS_LCD_IHS; ++ dssdev->panel.timings = samsung_lte_timings; ++ ++ return 0; ++} ++ ++static void samsung_lte_panel_remove(struct omap_dss_device *dssdev) ++{ ++} ++ ++static int samsung_lte_panel_enable(struct omap_dss_device *dssdev) ++{ ++ int r = 0; ++ ++ /* wait couple of vsyncs until enabling the LCD */ ++ msleep(50); ++ ++ if (dssdev->platform_enable) ++ r = dssdev->platform_enable(dssdev); ++ ++ return r; ++} ++ ++static void samsung_lte_panel_disable(struct omap_dss_device *dssdev) ++{ ++ if (dssdev->platform_disable) ++ dssdev->platform_disable(dssdev); ++ ++ /* wait at least 5 vsyncs after disabling the LCD */ ++ ++ msleep(100); ++} ++ ++static int samsung_lte_panel_suspend(struct omap_dss_device *dssdev) ++{ ++ samsung_lte_panel_disable(dssdev); ++ return 0; ++} ++ ++static int samsung_lte_panel_resume(struct omap_dss_device *dssdev) ++{ ++ return samsung_lte_panel_enable(dssdev); ++} ++ ++static struct omap_dss_driver samsung_lte_driver = { ++ .probe = samsung_lte_panel_probe, ++ .remove = samsung_lte_panel_remove, ++ ++ .enable = samsung_lte_panel_enable, ++ .disable = samsung_lte_panel_disable, ++ .suspend = samsung_lte_panel_suspend, ++ .resume = samsung_lte_panel_resume, ++ ++ .driver = { ++ .name = "samsung_lte_panel", ++ .owner = THIS_MODULE, ++ }, ++}; ++ ++static int __init samsung_lte_panel_drv_init(void) ++{ ++ return omap_dss_register_driver(&samsung_lte_driver); ++} ++ ++static void __exit samsung_lte_panel_drv_exit(void) ++{ ++ omap_dss_unregister_driver(&samsung_lte_driver); ++} ++ ++module_init(samsung_lte_panel_drv_init); ++module_exit(samsung_lte_panel_drv_exit); ++MODULE_LICENSE("GPL"); +diff --git a/drivers/video/omap2/displays/panel-sharp-ls037v7dw01.c b/drivers/video/omap2/displays/panel-sharp-ls037v7dw01.c +new file mode 100644 +index 0000000..2f8f0df +--- /dev/null ++++ b/drivers/video/omap2/displays/panel-sharp-ls037v7dw01.c +@@ -0,0 +1,153 @@ ++/* ++ * LCD panel driver for Sharp LS037V7DW01 ++ * ++ * Copyright (C) 2008 Nokia Corporation ++ * Author: Tomi Valkeinen ++ * ++ * 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. ++ * ++ * 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, see . ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++struct sharp_data { ++ /* XXX This regulator should actually be in SDP board file, not here, ++ * as it doesn't actually power the LCD, but something else that ++ * affects the output to LCD (I think. Somebody clarify). It doesn't do ++ * harm here, as SDP is the only board using this currently */ ++ struct regulator *vdvi_reg; ++}; ++ ++static struct omap_video_timings sharp_ls_timings = { ++ .x_res = 480, ++ .y_res = 640, ++ ++ .pixel_clock = 19200, ++ ++ .hsw = 2, ++ .hfp = 1, ++ .hbp = 28, ++ ++ .vsw = 1, ++ .vfp = 1, ++ .vbp = 1, ++}; ++ ++static int sharp_ls_panel_probe(struct omap_dss_device *dssdev) ++{ ++ struct sharp_data *sd; ++ ++ dssdev->panel.config = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IVS | ++ OMAP_DSS_LCD_IHS; ++ dssdev->panel.acb = 0x28; ++ dssdev->panel.timings = sharp_ls_timings; ++ ++ sd = kzalloc(sizeof(*sd), GFP_KERNEL); ++ if (!sd) ++ return -ENOMEM; ++ ++ dev_set_drvdata(&dssdev->dev, sd); ++ ++ sd->vdvi_reg = regulator_get(&dssdev->dev, "vdvi"); ++ if (IS_ERR(sd->vdvi_reg)) { ++ kfree(sd); ++ pr_err("failed to get VDVI regulator\n"); ++ return PTR_ERR(sd->vdvi_reg); ++ } ++ ++ return 0; ++} ++ ++static void sharp_ls_panel_remove(struct omap_dss_device *dssdev) ++{ ++ struct sharp_data *sd = dev_get_drvdata(&dssdev->dev); ++ ++ regulator_put(sd->vdvi_reg); ++ ++ kfree(sd); ++} ++ ++static int sharp_ls_panel_enable(struct omap_dss_device *dssdev) ++{ ++ struct sharp_data *sd = dev_get_drvdata(&dssdev->dev); ++ int r = 0; ++ ++ /* wait couple of vsyncs until enabling the LCD */ ++ msleep(50); ++ ++ regulator_enable(sd->vdvi_reg); ++ ++ if (dssdev->platform_enable) ++ r = dssdev->platform_enable(dssdev); ++ ++ return r; ++} ++ ++static void sharp_ls_panel_disable(struct omap_dss_device *dssdev) ++{ ++ struct sharp_data *sd = dev_get_drvdata(&dssdev->dev); ++ ++ if (dssdev->platform_disable) ++ dssdev->platform_disable(dssdev); ++ ++ regulator_disable(sd->vdvi_reg); ++ ++ /* wait at least 5 vsyncs after disabling the LCD */ ++ ++ msleep(100); ++} ++ ++static int sharp_ls_panel_suspend(struct omap_dss_device *dssdev) ++{ ++ sharp_ls_panel_disable(dssdev); ++ return 0; ++} ++ ++static int sharp_ls_panel_resume(struct omap_dss_device *dssdev) ++{ ++ return sharp_ls_panel_enable(dssdev); ++} ++ ++static struct omap_dss_driver sharp_ls_driver = { ++ .probe = sharp_ls_panel_probe, ++ .remove = sharp_ls_panel_remove, ++ ++ .enable = sharp_ls_panel_enable, ++ .disable = sharp_ls_panel_disable, ++ .suspend = sharp_ls_panel_suspend, ++ .resume = sharp_ls_panel_resume, ++ ++ .driver = { ++ .name = "sharp_ls_panel", ++ .owner = THIS_MODULE, ++ }, ++}; ++ ++static int __init sharp_ls_panel_drv_init(void) ++{ ++ return omap_dss_register_driver(&sharp_ls_driver); ++} ++ ++static void __exit sharp_ls_panel_drv_exit(void) ++{ ++ omap_dss_unregister_driver(&sharp_ls_driver); ++} ++ ++module_init(sharp_ls_panel_drv_init); ++module_exit(sharp_ls_panel_drv_exit); ++MODULE_LICENSE("GPL"); +diff --git a/drivers/video/omap2/displays/panel-taal.c b/drivers/video/omap2/displays/panel-taal.c +new file mode 100644 +index 0000000..84f0d47 +--- /dev/null ++++ b/drivers/video/omap2/displays/panel-taal.c +@@ -0,0 +1,900 @@ ++/* ++ * Taal DSI command mode panel ++ * ++ * Copyright (C) 2009 Nokia Corporation ++ * Author: Tomi Valkeinen ++ * ++ * 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. ++ * ++ * 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, see . ++ */ ++ ++/*#define DEBUG*/ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++/* DSI Virtual channel. Hardcoded for now. */ ++#define TCH 0 ++ ++#define DCS_READ_NUM_ERRORS 0x05 ++#define DCS_READ_POWER_MODE 0x0a ++#define DCS_READ_MADCTL 0x0b ++#define DCS_READ_PIXEL_FORMAT 0x0c ++#define DCS_SLEEP_IN 0x10 ++#define DCS_SLEEP_OUT 0x11 ++#define DCS_DISPLAY_OFF 0x28 ++#define DCS_DISPLAY_ON 0x29 ++#define DCS_COLUMN_ADDR 0x2a ++#define DCS_PAGE_ADDR 0x2b ++#define DCS_MEMORY_WRITE 0x2c ++#define DCS_TEAR_OFF 0x34 ++#define DCS_TEAR_ON 0x35 ++#define DCS_MEM_ACC_CTRL 0x36 ++#define DCS_PIXEL_FORMAT 0x3a ++#define DCS_BRIGHTNESS 0x51 ++#define DCS_CTRL_DISPLAY 0x53 ++#define DCS_WRITE_CABC 0x55 ++#define DCS_READ_CABC 0x56 ++#define DCS_GET_ID1 0xda ++#define DCS_GET_ID2 0xdb ++#define DCS_GET_ID3 0xdc ++ ++struct taal_data { ++ struct backlight_device *bldev; ++ ++ unsigned long hw_guard_end; /* next value of jiffies when we can ++ * issue the next sleep in/out command ++ */ ++ unsigned long hw_guard_wait; /* max guard time in jiffies */ ++ ++ struct omap_dss_device *dssdev; ++ ++ bool enabled; ++ u8 rotate; ++ bool mirror; ++ ++ bool te_enabled; ++ bool use_ext_te; ++ struct completion te_completion; ++ ++ bool use_dsi_bl; ++ ++ bool cabc_broken; ++ unsigned cabc_mode; ++ ++ bool intro_printed; ++}; ++ ++static void hw_guard_start(struct taal_data *td, int guard_msec) ++{ ++ td->hw_guard_wait = msecs_to_jiffies(guard_msec); ++ td->hw_guard_end = jiffies + td->hw_guard_wait; ++} ++ ++static void hw_guard_wait(struct taal_data *td) ++{ ++ unsigned long wait = td->hw_guard_end - jiffies; ++ ++ if ((long)wait > 0 && wait <= td->hw_guard_wait) { ++ set_current_state(TASK_UNINTERRUPTIBLE); ++ schedule_timeout(wait); ++ } ++} ++ ++static int taal_dcs_read_1(u8 dcs_cmd, u8 *data) ++{ ++ int r; ++ u8 buf[1]; ++ ++ r = dsi_vc_dcs_read(TCH, dcs_cmd, buf, 1); ++ ++ if (r < 0) ++ return r; ++ ++ *data = buf[0]; ++ ++ return 0; ++} ++ ++static int taal_dcs_write_0(u8 dcs_cmd) ++{ ++ return dsi_vc_dcs_write(TCH, &dcs_cmd, 1); ++} ++ ++static int taal_dcs_write_1(u8 dcs_cmd, u8 param) ++{ ++ u8 buf[2]; ++ buf[0] = dcs_cmd; ++ buf[1] = param; ++ return dsi_vc_dcs_write(TCH, buf, 2); ++} ++ ++static int taal_sleep_in(struct taal_data *td) ++ ++{ ++ u8 cmd; ++ int r; ++ ++ hw_guard_wait(td); ++ ++ cmd = DCS_SLEEP_IN; ++ r = dsi_vc_dcs_write_nosync(TCH, &cmd, 1); ++ if (r) ++ return r; ++ ++ hw_guard_start(td, 120); ++ ++ msleep(5); ++ ++ return 0; ++} ++ ++static int taal_sleep_out(struct taal_data *td) ++{ ++ int r; ++ ++ hw_guard_wait(td); ++ ++ r = taal_dcs_write_0(DCS_SLEEP_OUT); ++ if (r) ++ return r; ++ ++ hw_guard_start(td, 120); ++ ++ msleep(5); ++ ++ return 0; ++} ++ ++static int taal_get_id(u8 *id1, u8 *id2, u8 *id3) ++{ ++ int r; ++ ++ r = taal_dcs_read_1(DCS_GET_ID1, id1); ++ if (r) ++ return r; ++ r = taal_dcs_read_1(DCS_GET_ID2, id2); ++ if (r) ++ return r; ++ r = taal_dcs_read_1(DCS_GET_ID3, id3); ++ if (r) ++ return r; ++ ++ return 0; ++} ++ ++static int taal_set_addr_mode(u8 rotate, bool mirror) ++{ ++ int r; ++ u8 mode; ++ int b5, b6, b7; ++ ++ r = taal_dcs_read_1(DCS_READ_MADCTL, &mode); ++ if (r) ++ return r; ++ ++ switch (rotate) { ++ default: ++ case 0: ++ b7 = 0; ++ b6 = 0; ++ b5 = 0; ++ break; ++ case 1: ++ b7 = 0; ++ b6 = 1; ++ b5 = 1; ++ break; ++ case 2: ++ b7 = 1; ++ b6 = 1; ++ b5 = 0; ++ break; ++ case 3: ++ b7 = 1; ++ b6 = 0; ++ b5 = 1; ++ break; ++ } ++ ++ if (mirror) ++ b6 = !b6; ++ ++ mode &= ~((1<<7) | (1<<6) | (1<<5)); ++ mode |= (b7 << 7) | (b6 << 6) | (b5 << 5); ++ ++ return taal_dcs_write_1(DCS_MEM_ACC_CTRL, mode); ++} ++ ++static int taal_set_update_window(u16 x, u16 y, u16 w, u16 h) ++{ ++ int r; ++ u16 x1 = x; ++ u16 x2 = x + w - 1; ++ u16 y1 = y; ++ u16 y2 = y + h - 1; ++ ++ u8 buf[5]; ++ buf[0] = DCS_COLUMN_ADDR; ++ buf[1] = (x1 >> 8) & 0xff; ++ buf[2] = (x1 >> 0) & 0xff; ++ buf[3] = (x2 >> 8) & 0xff; ++ buf[4] = (x2 >> 0) & 0xff; ++ ++ r = dsi_vc_dcs_write_nosync(TCH, buf, sizeof(buf)); ++ if (r) ++ return r; ++ ++ buf[0] = DCS_PAGE_ADDR; ++ buf[1] = (y1 >> 8) & 0xff; ++ buf[2] = (y1 >> 0) & 0xff; ++ buf[3] = (y2 >> 8) & 0xff; ++ buf[4] = (y2 >> 0) & 0xff; ++ ++ r = dsi_vc_dcs_write_nosync(TCH, buf, sizeof(buf)); ++ if (r) ++ return r; ++ ++ dsi_vc_send_bta_sync(TCH); ++ ++ return r; ++} ++ ++static int taal_bl_update_status(struct backlight_device *dev) ++{ ++ struct omap_dss_device *dssdev = dev_get_drvdata(&dev->dev); ++ struct taal_data *td = dev_get_drvdata(&dssdev->dev); ++ int r; ++ int level; ++ ++ if (dev->props.fb_blank == FB_BLANK_UNBLANK && ++ dev->props.power == FB_BLANK_UNBLANK) ++ level = dev->props.brightness; ++ else ++ level = 0; ++ ++ dev_dbg(&dssdev->dev, "update brightness to %d\n", level); ++ ++ if (td->use_dsi_bl) { ++ if (td->enabled) { ++ dsi_bus_lock(); ++ r = taal_dcs_write_1(DCS_BRIGHTNESS, level); ++ dsi_bus_unlock(); ++ if (r) ++ return r; ++ } ++ } else { ++ if (!dssdev->set_backlight) ++ return -EINVAL; ++ ++ r = dssdev->set_backlight(dssdev, level); ++ if (r) ++ return r; ++ } ++ ++ return 0; ++} ++ ++static int taal_bl_get_intensity(struct backlight_device *dev) ++{ ++ if (dev->props.fb_blank == FB_BLANK_UNBLANK && ++ dev->props.power == FB_BLANK_UNBLANK) ++ return dev->props.brightness; ++ ++ return 0; ++} ++ ++static struct backlight_ops taal_bl_ops = { ++ .get_brightness = taal_bl_get_intensity, ++ .update_status = taal_bl_update_status, ++}; ++ ++static void taal_get_timings(struct omap_dss_device *dssdev, ++ struct omap_video_timings *timings) ++{ ++ *timings = dssdev->panel.timings; ++} ++ ++static void taal_get_resolution(struct omap_dss_device *dssdev, ++ u16 *xres, u16 *yres) ++{ ++ struct taal_data *td = dev_get_drvdata(&dssdev->dev); ++ ++ if (td->rotate == 0 || td->rotate == 2) { ++ *xres = dssdev->panel.timings.x_res; ++ *yres = dssdev->panel.timings.y_res; ++ } else { ++ *yres = dssdev->panel.timings.x_res; ++ *xres = dssdev->panel.timings.y_res; ++ } ++} ++ ++static irqreturn_t taal_te_isr(int irq, void *data) ++{ ++ struct omap_dss_device *dssdev = data; ++ struct taal_data *td = dev_get_drvdata(&dssdev->dev); ++ ++ complete_all(&td->te_completion); ++ ++ return IRQ_HANDLED; ++} ++ ++static ssize_t taal_num_errors_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct omap_dss_device *dssdev = to_dss_device(dev); ++ struct taal_data *td = dev_get_drvdata(&dssdev->dev); ++ u8 errors; ++ int r; ++ ++ if (td->enabled) { ++ dsi_bus_lock(); ++ r = taal_dcs_read_1(DCS_READ_NUM_ERRORS, &errors); ++ dsi_bus_unlock(); ++ } else { ++ r = -ENODEV; ++ } ++ ++ if (r) ++ return r; ++ ++ return snprintf(buf, PAGE_SIZE, "%d\n", errors); ++} ++ ++static ssize_t taal_hw_revision_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct omap_dss_device *dssdev = to_dss_device(dev); ++ struct taal_data *td = dev_get_drvdata(&dssdev->dev); ++ u8 id1, id2, id3; ++ int r; ++ ++ if (td->enabled) { ++ dsi_bus_lock(); ++ r = taal_get_id(&id1, &id2, &id3); ++ dsi_bus_unlock(); ++ } else { ++ r = -ENODEV; ++ } ++ ++ if (r) ++ return r; ++ ++ return snprintf(buf, PAGE_SIZE, "%02x.%02x.%02x\n", id1, id2, id3); ++} ++ ++static const char *cabc_modes[] = { ++ "off", /* used also always when CABC is not supported */ ++ "ui", ++ "still-image", ++ "moving-image", ++}; ++ ++static ssize_t show_cabc_mode(struct device *dev, ++ struct device_attribute *attr, ++ char *buf) ++{ ++ struct omap_dss_device *dssdev = to_dss_device(dev); ++ struct taal_data *td = dev_get_drvdata(&dssdev->dev); ++ const char *mode_str; ++ int mode; ++ int len; ++ ++ mode = td->cabc_mode; ++ ++ mode_str = "unknown"; ++ if (mode >= 0 && mode < ARRAY_SIZE(cabc_modes)) ++ mode_str = cabc_modes[mode]; ++ len = snprintf(buf, PAGE_SIZE, "%s\n", mode_str); ++ ++ return len < PAGE_SIZE - 1 ? len : PAGE_SIZE - 1; ++} ++ ++static ssize_t store_cabc_mode(struct device *dev, ++ struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ struct omap_dss_device *dssdev = to_dss_device(dev); ++ struct taal_data *td = dev_get_drvdata(&dssdev->dev); ++ int i; ++ ++ for (i = 0; i < ARRAY_SIZE(cabc_modes); i++) { ++ if (sysfs_streq(cabc_modes[i], buf)) ++ break; ++ } ++ ++ if (i == ARRAY_SIZE(cabc_modes)) ++ return -EINVAL; ++ ++ if (td->enabled) { ++ dsi_bus_lock(); ++ if (!td->cabc_broken) ++ taal_dcs_write_1(DCS_WRITE_CABC, i); ++ dsi_bus_unlock(); ++ } ++ ++ td->cabc_mode = i; ++ ++ return count; ++} ++ ++static ssize_t show_cabc_available_modes(struct device *dev, ++ struct device_attribute *attr, ++ char *buf) ++{ ++ int len; ++ int i; ++ ++ for (i = 0, len = 0; ++ len < PAGE_SIZE && i < ARRAY_SIZE(cabc_modes); i++) ++ len += snprintf(&buf[len], PAGE_SIZE - len, "%s%s%s", ++ i ? " " : "", cabc_modes[i], ++ i == ARRAY_SIZE(cabc_modes) - 1 ? "\n" : ""); ++ ++ return len < PAGE_SIZE ? len : PAGE_SIZE - 1; ++} ++ ++static DEVICE_ATTR(num_dsi_errors, S_IRUGO, taal_num_errors_show, NULL); ++static DEVICE_ATTR(hw_revision, S_IRUGO, taal_hw_revision_show, NULL); ++static DEVICE_ATTR(cabc_mode, S_IRUGO | S_IWUSR, ++ show_cabc_mode, store_cabc_mode); ++static DEVICE_ATTR(cabc_available_modes, S_IRUGO, ++ show_cabc_available_modes, NULL); ++ ++static struct attribute *taal_attrs[] = { ++ &dev_attr_num_dsi_errors.attr, ++ &dev_attr_hw_revision.attr, ++ &dev_attr_cabc_mode.attr, ++ &dev_attr_cabc_available_modes.attr, ++ NULL, ++}; ++ ++static struct attribute_group taal_attr_group = { ++ .attrs = taal_attrs, ++}; ++ ++static int taal_probe(struct omap_dss_device *dssdev) ++{ ++ struct taal_data *td; ++ struct backlight_device *bldev; ++ int r; ++ ++ const struct omap_video_timings taal_panel_timings = { ++ .x_res = 864, ++ .y_res = 480, ++ }; ++ ++ dev_dbg(&dssdev->dev, "probe\n"); ++ ++ dssdev->panel.config = OMAP_DSS_LCD_TFT; ++ dssdev->panel.timings = taal_panel_timings; ++ dssdev->ctrl.pixel_size = 24; ++ ++ td = kzalloc(sizeof(*td), GFP_KERNEL); ++ if (!td) { ++ r = -ENOMEM; ++ goto err0; ++ } ++ ++ dev_set_drvdata(&dssdev->dev, td); ++ ++ dssdev->get_timings = taal_get_timings; ++ dssdev->get_resolution = taal_get_resolution; ++ ++ /* if no platform set_backlight() defined, presume DSI backlight ++ * control */ ++ if (!dssdev->set_backlight) ++ td->use_dsi_bl = true; ++ ++ bldev = backlight_device_register("taal", &dssdev->dev, dssdev, ++ &taal_bl_ops); ++ if (IS_ERR(bldev)) { ++ r = PTR_ERR(bldev); ++ goto err1; ++ } ++ ++ td->bldev = bldev; ++ ++ bldev->props.fb_blank = FB_BLANK_UNBLANK; ++ bldev->props.power = FB_BLANK_UNBLANK; ++ if (td->use_dsi_bl) { ++ bldev->props.max_brightness = 255; ++ bldev->props.brightness = 255; ++ } else { ++ bldev->props.max_brightness = 127; ++ bldev->props.brightness = 127; ++ } ++ ++ taal_bl_update_status(bldev); ++ ++ if (dssdev->phy.dsi.ext_te) { ++ int gpio = dssdev->phy.dsi.ext_te_gpio; ++ ++ r = gpio_request(gpio, "taal irq"); ++ if (r) { ++ dev_err(&dssdev->dev, "GPIO request failed\n"); ++ goto err2; ++ } ++ ++ gpio_direction_input(gpio); ++ ++ r = request_irq(gpio_to_irq(gpio), taal_te_isr, ++ IRQF_DISABLED | IRQF_TRIGGER_RISING, ++ "taal vsync", dssdev); ++ ++ if (r) { ++ dev_err(&dssdev->dev, "IRQ request failed\n"); ++ gpio_free(gpio); ++ goto err2; ++ } ++ ++ init_completion(&td->te_completion); ++ ++ td->use_ext_te = true; ++ } ++ ++ r = sysfs_create_group(&dssdev->dev.kobj, &taal_attr_group); ++ if (r) { ++ dev_err(&dssdev->dev, "failed to create sysfs files\n"); ++ goto err3; ++ } ++ ++ return 0; ++err3: ++ if (td->use_ext_te) { ++ int gpio = dssdev->phy.dsi.ext_te_gpio; ++ free_irq(gpio_to_irq(gpio), dssdev); ++ gpio_free(gpio); ++ } ++err2: ++ backlight_device_unregister(bldev); ++err1: ++ kfree(td); ++err0: ++ return r; ++} ++ ++static void taal_remove(struct omap_dss_device *dssdev) ++{ ++ struct taal_data *td = dev_get_drvdata(&dssdev->dev); ++ struct backlight_device *bldev; ++ ++ dev_dbg(&dssdev->dev, "remove\n"); ++ ++ sysfs_remove_group(&dssdev->dev.kobj, &taal_attr_group); ++ ++ if (td->use_ext_te) { ++ int gpio = dssdev->phy.dsi.ext_te_gpio; ++ free_irq(gpio_to_irq(gpio), dssdev); ++ gpio_free(gpio); ++ } ++ ++ bldev = td->bldev; ++ bldev->props.power = FB_BLANK_POWERDOWN; ++ taal_bl_update_status(bldev); ++ backlight_device_unregister(bldev); ++ ++ kfree(td); ++} ++ ++static int taal_enable(struct omap_dss_device *dssdev) ++{ ++ struct taal_data *td = dev_get_drvdata(&dssdev->dev); ++ u8 id1, id2, id3; ++ int r; ++ ++ dev_dbg(&dssdev->dev, "enable\n"); ++ ++ if (dssdev->platform_enable) { ++ r = dssdev->platform_enable(dssdev); ++ if (r) ++ return r; ++ } ++ ++ /* it seems we have to wait a bit until taal is ready */ ++ msleep(5); ++ ++ r = taal_sleep_out(td); ++ if (r) ++ return r; ++ ++ r = taal_get_id(&id1, &id2, &id3); ++ if (r) ++ return r; ++ ++ /* on early revisions CABC is broken */ ++ if (id2 == 0x00 || id2 == 0xff || id2 == 0x81) ++ td->cabc_broken = true; ++ ++ taal_dcs_write_1(DCS_BRIGHTNESS, 0xff); ++ taal_dcs_write_1(DCS_CTRL_DISPLAY, (1<<2) | (1<<5)); /* BL | BCTRL */ ++ ++ taal_dcs_write_1(DCS_PIXEL_FORMAT, 0x7); /* 24bit/pixel */ ++ ++ taal_set_addr_mode(td->rotate, td->mirror); ++ if (!td->cabc_broken) ++ taal_dcs_write_1(DCS_WRITE_CABC, td->cabc_mode); ++ ++ taal_dcs_write_0(DCS_DISPLAY_ON); ++ ++ td->enabled = 1; ++ ++ if (!td->intro_printed) { ++ dev_info(&dssdev->dev, "revision %02x.%02x.%02x\n", ++ id1, id2, id3); ++ if (td->cabc_broken) ++ dev_info(&dssdev->dev, ++ "old Taal version, CABC disabled\n"); ++ td->intro_printed = true; ++ } ++ ++ return 0; ++} ++ ++static void taal_disable(struct omap_dss_device *dssdev) ++{ ++ struct taal_data *td = dev_get_drvdata(&dssdev->dev); ++ ++ dev_dbg(&dssdev->dev, "disable\n"); ++ ++ taal_dcs_write_0(DCS_DISPLAY_OFF); ++ taal_sleep_in(td); ++ ++ /* wait a bit so that the message goes through */ ++ msleep(10); ++ ++ if (dssdev->platform_disable) ++ dssdev->platform_disable(dssdev); ++ ++ td->enabled = 0; ++} ++ ++static int taal_suspend(struct omap_dss_device *dssdev) ++{ ++ struct taal_data *td = dev_get_drvdata(&dssdev->dev); ++ struct backlight_device *bldev = td->bldev; ++ ++ bldev->props.power = FB_BLANK_POWERDOWN; ++ taal_bl_update_status(bldev); ++ ++ return 0; ++} ++ ++static int taal_resume(struct omap_dss_device *dssdev) ++{ ++ struct taal_data *td = dev_get_drvdata(&dssdev->dev); ++ struct backlight_device *bldev = td->bldev; ++ ++ bldev->props.power = FB_BLANK_UNBLANK; ++ taal_bl_update_status(bldev); ++ ++ return 0; ++} ++ ++static void taal_setup_update(struct omap_dss_device *dssdev, ++ u16 x, u16 y, u16 w, u16 h) ++{ ++ taal_set_update_window(x, y, w, h); ++} ++ ++static int taal_enable_te(struct omap_dss_device *dssdev, bool enable) ++{ ++ struct taal_data *td = dev_get_drvdata(&dssdev->dev); ++ int r; ++ ++ td->te_enabled = enable; ++ ++ if (enable) ++ r = taal_dcs_write_1(DCS_TEAR_ON, 0); ++ else ++ r = taal_dcs_write_0(DCS_TEAR_OFF); ++ ++ return r; ++} ++ ++static int taal_wait_te(struct omap_dss_device *dssdev) ++{ ++ struct taal_data *td = dev_get_drvdata(&dssdev->dev); ++ long wait = msecs_to_jiffies(500); ++ ++ if (!td->use_ext_te || !td->te_enabled) ++ return 0; ++ ++ INIT_COMPLETION(td->te_completion); ++ wait = wait_for_completion_timeout(&td->te_completion, wait); ++ if (wait == 0) { ++ dev_err(&dssdev->dev, "timeout waiting TE\n"); ++ return -ETIME; ++ } ++ ++ return 0; ++} ++ ++static int taal_rotate(struct omap_dss_device *dssdev, u8 rotate) ++{ ++ struct taal_data *td = dev_get_drvdata(&dssdev->dev); ++ int r; ++ ++ dev_dbg(&dssdev->dev, "rotate %d\n", rotate); ++ ++ if (td->enabled) { ++ r = taal_set_addr_mode(rotate, td->mirror); ++ ++ if (r) ++ return r; ++ } ++ ++ td->rotate = rotate; ++ ++ return 0; ++} ++ ++static u8 taal_get_rotate(struct omap_dss_device *dssdev) ++{ ++ struct taal_data *td = dev_get_drvdata(&dssdev->dev); ++ return td->rotate; ++} ++ ++static int taal_mirror(struct omap_dss_device *dssdev, bool enable) ++{ ++ struct taal_data *td = dev_get_drvdata(&dssdev->dev); ++ int r; ++ ++ dev_dbg(&dssdev->dev, "mirror %d\n", enable); ++ ++ if (td->enabled) { ++ r = taal_set_addr_mode(td->rotate, enable); ++ ++ if (r) ++ return r; ++ } ++ ++ td->mirror = enable; ++ ++ return 0; ++} ++ ++static bool taal_get_mirror(struct omap_dss_device *dssdev) ++{ ++ struct taal_data *td = dev_get_drvdata(&dssdev->dev); ++ return td->mirror; ++} ++ ++static int taal_run_test(struct omap_dss_device *dssdev, int test_num) ++{ ++ u8 id1, id2, id3; ++ int r; ++ ++ r = taal_dcs_read_1(DCS_GET_ID1, &id1); ++ if (r) ++ return r; ++ r = taal_dcs_read_1(DCS_GET_ID2, &id2); ++ if (r) ++ return r; ++ r = taal_dcs_read_1(DCS_GET_ID3, &id3); ++ if (r) ++ return r; ++ ++ return 0; ++} ++ ++static int taal_memory_read(struct omap_dss_device *dssdev, ++ void *buf, size_t size, ++ u16 x, u16 y, u16 w, u16 h) ++{ ++ int r; ++ int first = 1; ++ int plen; ++ unsigned buf_used = 0; ++ ++ if (size < w * h * 3) ++ return -ENOMEM; ++ ++ size = min(w * h * 3, ++ dssdev->panel.timings.x_res * ++ dssdev->panel.timings.y_res * 3); ++ ++ /* plen 1 or 2 goes into short packet. until checksum error is fixed, ++ * use short packets. plen 32 works, but bigger packets seem to cause ++ * an error. */ ++ if (size % 2) ++ plen = 1; ++ else ++ plen = 2; ++ ++ taal_setup_update(dssdev, x, y, w, h); ++ ++ r = dsi_vc_set_max_rx_packet_size(TCH, plen); ++ if (r) ++ return r; ++ ++ while (buf_used < size) { ++ u8 dcs_cmd = first ? 0x2e : 0x3e; ++ first = 0; ++ ++ r = dsi_vc_dcs_read(TCH, dcs_cmd, ++ buf + buf_used, size - buf_used); ++ ++ if (r < 0) { ++ dev_err(&dssdev->dev, "read error\n"); ++ goto err; ++ } ++ ++ buf_used += r; ++ ++ if (r < plen) { ++ dev_err(&dssdev->dev, "short read\n"); ++ break; ++ } ++ } ++ ++ r = buf_used; ++ ++err: ++ dsi_vc_set_max_rx_packet_size(TCH, 1); ++ ++ return r; ++} ++ ++static struct omap_dss_driver taal_driver = { ++ .probe = taal_probe, ++ .remove = taal_remove, ++ ++ .enable = taal_enable, ++ .disable = taal_disable, ++ .suspend = taal_suspend, ++ .resume = taal_resume, ++ ++ .setup_update = taal_setup_update, ++ .enable_te = taal_enable_te, ++ .wait_for_te = taal_wait_te, ++ .set_rotate = taal_rotate, ++ .get_rotate = taal_get_rotate, ++ .set_mirror = taal_mirror, ++ .get_mirror = taal_get_mirror, ++ .run_test = taal_run_test, ++ .memory_read = taal_memory_read, ++ ++ .driver = { ++ .name = "taal", ++ .owner = THIS_MODULE, ++ }, ++}; ++ ++static int __init taal_init(void) ++{ ++ omap_dss_register_driver(&taal_driver); ++ ++ return 0; ++} ++ ++static void __exit taal_exit(void) ++{ ++ omap_dss_unregister_driver(&taal_driver); ++} ++ ++module_init(taal_init); ++module_exit(taal_exit); ++ ++MODULE_AUTHOR("Tomi Valkeinen "); ++MODULE_DESCRIPTION("Taal Driver"); ++MODULE_LICENSE("GPL"); +diff --git a/drivers/video/omap2/dss/Kconfig b/drivers/video/omap2/dss/Kconfig +new file mode 100644 +index 0000000..71d8dec +--- /dev/null ++++ b/drivers/video/omap2/dss/Kconfig +@@ -0,0 +1,89 @@ ++menuconfig OMAP2_DSS ++ tristate "OMAP2/3 Display Subsystem support (EXPERIMENTAL)" ++ depends on ARCH_OMAP2 || ARCH_OMAP3 ++ help ++ OMAP2/3 Display Subsystem support. ++ ++if OMAP2_DSS ++ ++config OMAP2_VRAM_SIZE ++ int "VRAM size (MB)" ++ range 0 32 ++ default 0 ++ help ++ The amount of SDRAM to reserve at boot time for video RAM use. ++ This VRAM will be used by omapfb and other drivers that need ++ large continuous RAM area for video use. ++ ++ You can also set this with "vram=" kernel argument, or ++ in the board file. ++ ++config OMAP2_DSS_DEBUG_SUPPORT ++ bool "Debug support" ++ default y ++ help ++ This enables debug messages. You need to enable printing ++ with 'debug' module parameter. ++ ++config OMAP2_DSS_RFBI ++ bool "RFBI support" ++ default n ++ help ++ MIPI DBI, or RFBI (Remote Framebuffer Interface), support. ++ ++config OMAP2_DSS_VENC ++ bool "VENC support" ++ default y ++ help ++ OMAP Video Encoder support. ++ ++config OMAP2_DSS_SDI ++ bool "SDI support" ++ depends on ARCH_OMAP3 ++ default n ++ help ++ SDI (Serial Display Interface) support. ++ ++config OMAP2_DSS_DSI ++ bool "DSI support" ++ depends on ARCH_OMAP3 ++ default n ++ help ++ MIPI DSI support. ++ ++config OMAP2_DSS_USE_DSI_PLL ++ bool "Use DSI PLL for PCLK (EXPERIMENTAL)" ++ default n ++ depends on OMAP2_DSS_DSI ++ help ++ Use DSI PLL to generate pixel clock. Currently only for DPI output. ++ DSI PLL can be used to generate higher and more precise pixel clocks. ++ ++config OMAP2_DSS_FAKE_VSYNC ++ bool "Fake VSYNC irq from manual update displays" ++ default n ++ help ++ If this is selected, DSI will generate a fake DISPC VSYNC interrupt ++ when DSI has sent a frame. This is only needed with DSI or RFBI ++ displays using manual mode, and you want VSYNC to, for example, ++ time animation. ++ ++config OMAP2_DSS_MIN_FCK_PER_PCK ++ int "Minimum FCK/PCK ratio (for scaling)" ++ range 0 32 ++ default 0 ++ help ++ This can be used to adjust the minimum FCK/PCK ratio. ++ ++ With this you can make sure that DISPC FCK is at least ++ n x PCK. Video plane scaling requires higher FCK than ++ normally. ++ ++ If this is set to 0, there's no extra constraint on the ++ DISPC FCK. However, the FCK will at minimum be ++ 2xPCK (if active matrix) or 3xPCK (if passive matrix). ++ ++ Max FCK is 173MHz, so this doesn't work if your PCK ++ is very high. ++ ++endif +diff --git a/drivers/video/omap2/dss/Makefile b/drivers/video/omap2/dss/Makefile +new file mode 100644 +index 0000000..980c72c +--- /dev/null ++++ b/drivers/video/omap2/dss/Makefile +@@ -0,0 +1,6 @@ ++obj-$(CONFIG_OMAP2_DSS) += omapdss.o ++omapdss-y := core.o dss.o dispc.o dpi.o display.o manager.o overlay.o ++omapdss-$(CONFIG_OMAP2_DSS_RFBI) += rfbi.o ++omapdss-$(CONFIG_OMAP2_DSS_VENC) += venc.o ++omapdss-$(CONFIG_OMAP2_DSS_SDI) += sdi.o ++omapdss-$(CONFIG_OMAP2_DSS_DSI) += dsi.o +diff --git a/drivers/video/omap2/dss/core.c b/drivers/video/omap2/dss/core.c +new file mode 100644 +index 0000000..e8d430c +--- /dev/null ++++ b/drivers/video/omap2/dss/core.c +@@ -0,0 +1,917 @@ ++/* ++ * linux/drivers/video/omap2/dss/core.c ++ * ++ * Copyright (C) 2009 Nokia Corporation ++ * Author: Tomi Valkeinen ++ * ++ * Some code and ideas taken from drivers/video/omap/ driver ++ * by Imre Deak. ++ * ++ * 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. ++ * ++ * 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, see . ++ */ ++ ++#define DSS_SUBSYS_NAME "CORE" ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++ ++#include "dss.h" ++ ++static struct { ++ struct platform_device *pdev; ++ int ctx_id; ++ ++ struct clk *dss_ick; ++ struct clk *dss1_fck; ++ struct clk *dss2_fck; ++ struct clk *dss_54m_fck; ++ struct clk *dss_96m_fck; ++ unsigned num_clks_enabled; ++} core; ++ ++static void dss_clk_enable_all_no_ctx(void); ++static void dss_clk_disable_all_no_ctx(void); ++static void dss_clk_enable_no_ctx(enum dss_clock clks); ++static void dss_clk_disable_no_ctx(enum dss_clock clks); ++ ++static char *def_disp_name; ++module_param_named(def_disp, def_disp_name, charp, 0); ++MODULE_PARM_DESC(def_disp_name, "default display name"); ++ ++#ifdef DEBUG ++unsigned int dss_debug; ++module_param_named(debug, dss_debug, bool, 0644); ++#endif ++ ++/* CONTEXT */ ++static int dss_get_ctx_id(void) ++{ ++ struct omap_dss_board_info *pdata = core.pdev->dev.platform_data; ++ int r; ++ ++ if (!pdata->get_last_off_on_transaction_id) ++ return 0; ++ r = pdata->get_last_off_on_transaction_id(&core.pdev->dev); ++ if (r < 0) { ++ dev_err(&core.pdev->dev, "getting transaction ID failed, " ++ "will force context restore\n"); ++ r = -1; ++ } ++ return r; ++} ++ ++int dss_need_ctx_restore(void) ++{ ++ int id = dss_get_ctx_id(); ++ ++ if (id < 0 || id != core.ctx_id) { ++ DSSDBG("ctx id %d -> id %d\n", ++ core.ctx_id, id); ++ core.ctx_id = id; ++ return 1; ++ } else { ++ return 0; ++ } ++} ++ ++static void save_all_ctx(void) ++{ ++ DSSDBG("save context\n"); ++ ++ dss_clk_enable_no_ctx(DSS_CLK_ICK | DSS_CLK_FCK1); ++ ++ dss_save_context(); ++ dispc_save_context(); ++#ifdef CONFIG_OMAP2_DSS_DSI ++ dsi_save_context(); ++#endif ++ ++ dss_clk_disable_no_ctx(DSS_CLK_ICK | DSS_CLK_FCK1); ++} ++ ++static void restore_all_ctx(void) ++{ ++ DSSDBG("restore context\n"); ++ ++ dss_clk_enable_all_no_ctx(); ++ ++ dss_restore_context(); ++ dispc_restore_context(); ++#ifdef CONFIG_OMAP2_DSS_DSI ++ dsi_restore_context(); ++#endif ++ ++ dss_clk_disable_all_no_ctx(); ++} ++ ++/* CLOCKS */ ++void dss_dump_clocks(struct seq_file *s) ++{ ++ int i; ++ struct clk *clocks[5] = { ++ core.dss_ick, ++ core.dss1_fck, ++ core.dss2_fck, ++ core.dss_54m_fck, ++ core.dss_96m_fck ++ }; ++ ++ seq_printf(s, "- dss -\n"); ++ ++ seq_printf(s, "internal clk count\t%u\n", core.num_clks_enabled); ++ ++ for (i = 0; i < 5; i++) { ++ if (!clocks[i]) ++ continue; ++ seq_printf(s, "%-15s\t%lu\t%d\n", ++ clocks[i]->name, ++ clk_get_rate(clocks[i]), ++ clocks[i]->usecount); ++ } ++} ++ ++static int dss_get_clock(struct clk **clock, const char *clk_name) ++{ ++ struct clk *clk; ++ ++ clk = clk_get(&core.pdev->dev, clk_name); ++ ++ if (IS_ERR(clk)) { ++ DSSERR("can't get clock %s", clk_name); ++ return PTR_ERR(clk); ++ } ++ ++ *clock = clk; ++ ++ DSSDBG("clk %s, rate %ld\n", clk_name, clk_get_rate(clk)); ++ ++ return 0; ++} ++ ++static int dss_get_clocks(void) ++{ ++ int r; ++ ++ core.dss_ick = NULL; ++ core.dss1_fck = NULL; ++ core.dss2_fck = NULL; ++ core.dss_54m_fck = NULL; ++ core.dss_96m_fck = NULL; ++ ++ r = dss_get_clock(&core.dss_ick, "ick"); ++ if (r) ++ goto err; ++ ++ r = dss_get_clock(&core.dss1_fck, "dss1_fck"); ++ if (r) ++ goto err; ++ ++ r = dss_get_clock(&core.dss2_fck, "dss2_fck"); ++ if (r) ++ goto err; ++ ++ r = dss_get_clock(&core.dss_54m_fck, "tv_fck"); ++ if (r) ++ goto err; ++ ++ r = dss_get_clock(&core.dss_96m_fck, "video_fck"); ++ if (r) ++ goto err; ++ ++ return 0; ++ ++err: ++ if (core.dss_ick) ++ clk_put(core.dss_ick); ++ if (core.dss1_fck) ++ clk_put(core.dss1_fck); ++ if (core.dss2_fck) ++ clk_put(core.dss2_fck); ++ if (core.dss_54m_fck) ++ clk_put(core.dss_54m_fck); ++ if (core.dss_96m_fck) ++ clk_put(core.dss_96m_fck); ++ ++ return r; ++} ++ ++static void dss_put_clocks(void) ++{ ++ if (core.dss_96m_fck) ++ clk_put(core.dss_96m_fck); ++ clk_put(core.dss_54m_fck); ++ clk_put(core.dss1_fck); ++ clk_put(core.dss2_fck); ++ clk_put(core.dss_ick); ++} ++ ++unsigned long dss_clk_get_rate(enum dss_clock clk) ++{ ++ switch (clk) { ++ case DSS_CLK_ICK: ++ return clk_get_rate(core.dss_ick); ++ case DSS_CLK_FCK1: ++ return clk_get_rate(core.dss1_fck); ++ case DSS_CLK_FCK2: ++ return clk_get_rate(core.dss2_fck); ++ case DSS_CLK_54M: ++ return clk_get_rate(core.dss_54m_fck); ++ case DSS_CLK_96M: ++ return clk_get_rate(core.dss_96m_fck); ++ } ++ ++ BUG(); ++ return 0; ++} ++ ++static unsigned count_clk_bits(enum dss_clock clks) ++{ ++ unsigned num_clks = 0; ++ ++ if (clks & DSS_CLK_ICK) ++ ++num_clks; ++ if (clks & DSS_CLK_FCK1) ++ ++num_clks; ++ if (clks & DSS_CLK_FCK2) ++ ++num_clks; ++ if (clks & DSS_CLK_54M) ++ ++num_clks; ++ if (clks & DSS_CLK_96M) ++ ++num_clks; ++ ++ return num_clks; ++} ++ ++static void dss_clk_enable_no_ctx(enum dss_clock clks) ++{ ++ unsigned num_clks = count_clk_bits(clks); ++ ++ if (clks & DSS_CLK_ICK) ++ clk_enable(core.dss_ick); ++ if (clks & DSS_CLK_FCK1) ++ clk_enable(core.dss1_fck); ++ if (clks & DSS_CLK_FCK2) ++ clk_enable(core.dss2_fck); ++ if (clks & DSS_CLK_54M) ++ clk_enable(core.dss_54m_fck); ++ if (clks & DSS_CLK_96M) ++ clk_enable(core.dss_96m_fck); ++ ++ core.num_clks_enabled += num_clks; ++} ++ ++void dss_clk_enable(enum dss_clock clks) ++{ ++ dss_clk_enable_no_ctx(clks); ++ ++ if (cpu_is_omap34xx() && dss_need_ctx_restore()) ++ restore_all_ctx(); ++} ++ ++static void dss_clk_disable_no_ctx(enum dss_clock clks) ++{ ++ unsigned num_clks = count_clk_bits(clks); ++ ++ if (clks & DSS_CLK_ICK) ++ clk_disable(core.dss_ick); ++ if (clks & DSS_CLK_FCK1) ++ clk_disable(core.dss1_fck); ++ if (clks & DSS_CLK_FCK2) ++ clk_disable(core.dss2_fck); ++ if (clks & DSS_CLK_54M) ++ clk_disable(core.dss_54m_fck); ++ if (clks & DSS_CLK_96M) ++ clk_disable(core.dss_96m_fck); ++ ++ core.num_clks_enabled -= num_clks; ++} ++ ++void dss_clk_disable(enum dss_clock clks) ++{ ++ if (cpu_is_omap34xx()) { ++ unsigned num_clks = count_clk_bits(clks); ++ ++ BUG_ON(core.num_clks_enabled < num_clks); ++ ++ if (core.num_clks_enabled == num_clks) ++ save_all_ctx(); ++ } ++ ++ dss_clk_disable_no_ctx(clks); ++} ++ ++static void dss_clk_enable_all_no_ctx(void) ++{ ++ enum dss_clock clks; ++ ++ clks = DSS_CLK_ICK | DSS_CLK_FCK1 | DSS_CLK_FCK2 | DSS_CLK_54M; ++ if (cpu_is_omap34xx()) ++ clks |= DSS_CLK_96M; ++ dss_clk_enable_no_ctx(clks); ++} ++ ++static void dss_clk_disable_all_no_ctx(void) ++{ ++ enum dss_clock clks; ++ ++ clks = DSS_CLK_ICK | DSS_CLK_FCK1 | DSS_CLK_FCK2 | DSS_CLK_54M; ++ if (cpu_is_omap34xx()) ++ clks |= DSS_CLK_96M; ++ dss_clk_disable_no_ctx(clks); ++} ++ ++static void dss_clk_disable_all(void) ++{ ++ enum dss_clock clks; ++ ++ clks = DSS_CLK_ICK | DSS_CLK_FCK1 | DSS_CLK_FCK2 | DSS_CLK_54M; ++ if (cpu_is_omap34xx()) ++ clks |= DSS_CLK_96M; ++ dss_clk_disable(clks); ++} ++ ++/* DEBUGFS */ ++#if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT) ++static void dss_debug_dump_clocks(struct seq_file *s) ++{ ++ dss_dump_clocks(s); ++ dispc_dump_clocks(s); ++#ifdef CONFIG_OMAP2_DSS_DSI ++ dsi_dump_clocks(s); ++#endif ++} ++ ++static int dss_debug_show(struct seq_file *s, void *unused) ++{ ++ void (*func)(struct seq_file *) = s->private; ++ func(s); ++ return 0; ++} ++ ++static int dss_debug_open(struct inode *inode, struct file *file) ++{ ++ return single_open(file, dss_debug_show, inode->i_private); ++} ++ ++static const struct file_operations dss_debug_fops = { ++ .open = dss_debug_open, ++ .read = seq_read, ++ .llseek = seq_lseek, ++ .release = single_release, ++}; ++ ++static struct dentry *dss_debugfs_dir; ++ ++static int dss_initialize_debugfs(void) ++{ ++ dss_debugfs_dir = debugfs_create_dir("omapdss", NULL); ++ if (IS_ERR(dss_debugfs_dir)) { ++ int err = PTR_ERR(dss_debugfs_dir); ++ dss_debugfs_dir = NULL; ++ return err; ++ } ++ ++ debugfs_create_file("clk", S_IRUGO, dss_debugfs_dir, ++ &dss_debug_dump_clocks, &dss_debug_fops); ++ ++ debugfs_create_file("dss", S_IRUGO, dss_debugfs_dir, ++ &dss_dump_regs, &dss_debug_fops); ++ debugfs_create_file("dispc", S_IRUGO, dss_debugfs_dir, ++ &dispc_dump_regs, &dss_debug_fops); ++#ifdef CONFIG_OMAP2_DSS_RFBI ++ debugfs_create_file("rfbi", S_IRUGO, dss_debugfs_dir, ++ &rfbi_dump_regs, &dss_debug_fops); ++#endif ++#ifdef CONFIG_OMAP2_DSS_DSI ++ debugfs_create_file("dsi", S_IRUGO, dss_debugfs_dir, ++ &dsi_dump_regs, &dss_debug_fops); ++#endif ++#ifdef CONFIG_OMAP2_DSS_VENC ++ debugfs_create_file("venc", S_IRUGO, dss_debugfs_dir, ++ &venc_dump_regs, &dss_debug_fops); ++#endif ++ return 0; ++} ++ ++static void dss_uninitialize_debugfs(void) ++{ ++ if (dss_debugfs_dir) ++ debugfs_remove_recursive(dss_debugfs_dir); ++} ++#endif /* CONFIG_DEBUG_FS && CONFIG_OMAP2_DSS_DEBUG_SUPPORT */ ++ ++/* PLATFORM DEVICE */ ++static int omap_dss_probe(struct platform_device *pdev) ++{ ++ struct omap_dss_board_info *pdata = pdev->dev.platform_data; ++ int skip_init = 0; ++ int r; ++ int i; ++ ++ core.pdev = pdev; ++ ++ dss_init_overlay_managers(pdev); ++ dss_init_overlays(pdev); ++ ++ r = dss_get_clocks(); ++ if (r) ++ goto fail0; ++ ++ dss_clk_enable_all_no_ctx(); ++ ++ core.ctx_id = dss_get_ctx_id(); ++ DSSDBG("initial ctx id %u\n", core.ctx_id); ++ ++#ifdef CONFIG_FB_OMAP_BOOTLOADER_INIT ++ /* DISPC_CONTROL */ ++ if (omap_readl(0x48050440) & 1) /* LCD enabled? */ ++ skip_init = 1; ++#endif ++ ++ r = dss_init(skip_init); ++ if (r) { ++ DSSERR("Failed to initialize DSS\n"); ++ goto fail0; ++ } ++ ++#ifdef CONFIG_OMAP2_DSS_RFBI ++ r = rfbi_init(); ++ if (r) { ++ DSSERR("Failed to initialize rfbi\n"); ++ goto fail0; ++ } ++#endif ++ ++ r = dpi_init(); ++ if (r) { ++ DSSERR("Failed to initialize dpi\n"); ++ goto fail0; ++ } ++ ++ r = dispc_init(); ++ if (r) { ++ DSSERR("Failed to initialize dispc\n"); ++ goto fail0; ++ } ++#ifdef CONFIG_OMAP2_DSS_VENC ++ r = venc_init(pdev); ++ if (r) { ++ DSSERR("Failed to initialize venc\n"); ++ goto fail0; ++ } ++#endif ++ if (cpu_is_omap34xx()) { ++#ifdef CONFIG_OMAP2_DSS_SDI ++ r = sdi_init(skip_init); ++ if (r) { ++ DSSERR("Failed to initialize SDI\n"); ++ goto fail0; ++ } ++#endif ++#ifdef CONFIG_OMAP2_DSS_DSI ++ r = dsi_init(pdev); ++ if (r) { ++ DSSERR("Failed to initialize DSI\n"); ++ goto fail0; ++ } ++#endif ++ } ++ ++#if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT) ++ r = dss_initialize_debugfs(); ++ if (r) ++ goto fail0; ++#endif ++ ++ for (i = 0; i < pdata->num_devices; ++i) { ++ struct omap_dss_device *dssdev = pdata->devices[i]; ++ ++ r = omap_dss_register_device(dssdev); ++ if (r) ++ DSSERR("device reg failed %d\n", i); ++ ++ if (def_disp_name && strcmp(def_disp_name, dssdev->name) == 0) ++ pdata->default_device = dssdev; ++ } ++ ++ dss_clk_disable_all(); ++ ++ return 0; ++ ++ /* XXX fail correctly */ ++fail0: ++ return r; ++} ++ ++static int omap_dss_remove(struct platform_device *pdev) ++{ ++ struct omap_dss_board_info *pdata = pdev->dev.platform_data; ++ int i; ++ int c; ++ ++#if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT) ++ dss_uninitialize_debugfs(); ++#endif ++ ++#ifdef CONFIG_OMAP2_DSS_VENC ++ venc_exit(); ++#endif ++ dispc_exit(); ++ dpi_exit(); ++#ifdef CONFIG_OMAP2_DSS_RFBI ++ rfbi_exit(); ++#endif ++ if (cpu_is_omap34xx()) { ++#ifdef CONFIG_OMAP2_DSS_DSI ++ dsi_exit(); ++#endif ++#ifdef CONFIG_OMAP2_DSS_SDI ++ sdi_exit(); ++#endif ++ } ++ ++ dss_exit(); ++ ++ /* these should be removed at some point */ ++ c = core.dss_ick->usecount; ++ if (c > 0) { ++ DSSERR("warning: dss_ick usecount %d, disabling\n", c); ++ while (c-- > 0) ++ clk_disable(core.dss_ick); ++ } ++ ++ c = core.dss1_fck->usecount; ++ if (c > 0) { ++ DSSERR("warning: dss1_fck usecount %d, disabling\n", c); ++ while (c-- > 0) ++ clk_disable(core.dss1_fck); ++ } ++ ++ c = core.dss2_fck->usecount; ++ if (c > 0) { ++ DSSERR("warning: dss2_fck usecount %d, disabling\n", c); ++ while (c-- > 0) ++ clk_disable(core.dss2_fck); ++ } ++ ++ c = core.dss_54m_fck->usecount; ++ if (c > 0) { ++ DSSERR("warning: dss_54m_fck usecount %d, disabling\n", c); ++ while (c-- > 0) ++ clk_disable(core.dss_54m_fck); ++ } ++ ++ if (core.dss_96m_fck) { ++ c = core.dss_96m_fck->usecount; ++ if (c > 0) { ++ DSSERR("warning: dss_96m_fck usecount %d, disabling\n", ++ c); ++ while (c-- > 0) ++ clk_disable(core.dss_96m_fck); ++ } ++ } ++ ++ dss_put_clocks(); ++ ++ dss_uninit_overlays(pdev); ++ dss_uninit_overlay_managers(pdev); ++ ++ for (i = 0; i < pdata->num_devices; ++i) ++ omap_dss_unregister_device(pdata->devices[i]); ++ ++ return 0; ++} ++ ++static void omap_dss_shutdown(struct platform_device *pdev) ++{ ++ DSSDBG("shutdown\n"); ++} ++ ++static int omap_dss_suspend(struct platform_device *pdev, pm_message_t state) ++{ ++ DSSDBG("suspend %d\n", state.event); ++ ++ return dss_suspend_all_devices(); ++} ++ ++static int omap_dss_resume(struct platform_device *pdev) ++{ ++ DSSDBG("resume\n"); ++ ++ return dss_resume_all_devices(); ++} ++ ++static struct platform_driver omap_dss_driver = { ++ .probe = omap_dss_probe, ++ .remove = omap_dss_remove, ++ .shutdown = omap_dss_shutdown, ++ .suspend = omap_dss_suspend, ++ .resume = omap_dss_resume, ++ .driver = { ++ .name = "omapdss", ++ .owner = THIS_MODULE, ++ }, ++}; ++ ++/* BUS */ ++static int dss_bus_match(struct device *dev, struct device_driver *driver) ++{ ++ struct omap_dss_device *dssdev = to_dss_device(dev); ++ ++ DSSDBG("bus_match. dev %s/%s, drv %s\n", ++ dev_name(dev), dssdev->driver_name, driver->name); ++ ++ return strcmp(dssdev->driver_name, driver->name) == 0; ++} ++ ++static ssize_t device_name_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct omap_dss_device *dssdev = to_dss_device(dev); ++ return snprintf(buf, PAGE_SIZE, "%s\n", ++ dssdev->name ? ++ dssdev->name : ""); ++} ++ ++static struct device_attribute default_dev_attrs[] = { ++ __ATTR(name, S_IRUGO, device_name_show, NULL), ++ __ATTR_NULL, ++}; ++ ++static ssize_t driver_name_show(struct device_driver *drv, char *buf) ++{ ++ struct omap_dss_driver *dssdrv = to_dss_driver(drv); ++ return snprintf(buf, PAGE_SIZE, "%s\n", ++ dssdrv->driver.name ? ++ dssdrv->driver.name : ""); ++} ++static struct driver_attribute default_drv_attrs[] = { ++ __ATTR(name, S_IRUGO, driver_name_show, NULL), ++ __ATTR_NULL, ++}; ++ ++static struct bus_type dss_bus_type = { ++ .name = "omapdss", ++ .match = dss_bus_match, ++ .dev_attrs = default_dev_attrs, ++ .drv_attrs = default_drv_attrs, ++}; ++ ++static void dss_bus_release(struct device *dev) ++{ ++ DSSDBG("bus_release\n"); ++} ++ ++static struct device dss_bus = { ++ .release = dss_bus_release, ++}; ++ ++struct bus_type *dss_get_bus(void) ++{ ++ return &dss_bus_type; ++} ++ ++/* DRIVER */ ++static int dss_driver_probe(struct device *dev) ++{ ++ int r; ++ struct omap_dss_driver *dssdrv = to_dss_driver(dev->driver); ++ struct omap_dss_device *dssdev = to_dss_device(dev); ++ struct omap_dss_board_info *pdata = core.pdev->dev.platform_data; ++ bool force; ++ ++ DSSDBG("driver_probe: dev %s/%s, drv %s\n", ++ dev_name(dev), dssdev->driver_name, ++ dssdrv->driver.name); ++ ++ dss_init_device(core.pdev, dssdev); ++ ++ /* skip this if the device is behind a ctrl */ ++ if (!dssdev->panel.ctrl) { ++ force = pdata->default_device == dssdev; ++ dss_recheck_connections(dssdev, force); ++ } ++ ++ r = dssdrv->probe(dssdev); ++ ++ if (r) { ++ DSSERR("driver probe failed: %d\n", r); ++ return r; ++ } ++ ++ DSSDBG("probe done for device %s\n", dev_name(dev)); ++ ++ dssdev->driver = dssdrv; ++ ++ return 0; ++} ++ ++static int dss_driver_remove(struct device *dev) ++{ ++ struct omap_dss_driver *dssdrv = to_dss_driver(dev->driver); ++ struct omap_dss_device *dssdev = to_dss_device(dev); ++ ++ DSSDBG("driver_remove: dev %s/%s\n", dev_name(dev), ++ dssdev->driver_name); ++ ++ dssdrv->remove(dssdev); ++ ++ dss_uninit_device(core.pdev, dssdev); ++ ++ dssdev->driver = NULL; ++ ++ return 0; ++} ++ ++int omap_dss_register_driver(struct omap_dss_driver *dssdriver) ++{ ++ dssdriver->driver.bus = &dss_bus_type; ++ dssdriver->driver.probe = dss_driver_probe; ++ dssdriver->driver.remove = dss_driver_remove; ++ return driver_register(&dssdriver->driver); ++} ++EXPORT_SYMBOL(omap_dss_register_driver); ++ ++void omap_dss_unregister_driver(struct omap_dss_driver *dssdriver) ++{ ++ driver_unregister(&dssdriver->driver); ++} ++EXPORT_SYMBOL(omap_dss_unregister_driver); ++ ++/* DEVICE */ ++static void reset_device(struct device *dev, int check) ++{ ++ u8 *dev_p = (u8 *)dev; ++ u8 *dev_end = dev_p + sizeof(*dev); ++ void *saved_pdata; ++ ++ saved_pdata = dev->platform_data; ++ if (check) { ++ /* ++ * Check if there is any other setting than platform_data ++ * in struct device; warn that these will be reset by our ++ * init. ++ */ ++ dev->platform_data = NULL; ++ while (dev_p < dev_end) { ++ if (*dev_p) { ++ WARN("%s: struct device fields will be " ++ "discarded\n", ++ __func__); ++ break; ++ } ++ dev_p++; ++ } ++ } ++ memset(dev, 0, sizeof(*dev)); ++ dev->platform_data = saved_pdata; ++} ++ ++ ++static void omap_dss_dev_release(struct device *dev) ++{ ++ reset_device(dev, 0); ++} ++ ++int omap_dss_register_device(struct omap_dss_device *dssdev) ++{ ++ static int dev_num; ++ static int panel_num; ++ int r; ++ ++ WARN_ON(!dssdev->driver_name); ++ ++ reset_device(&dssdev->dev, 1); ++ dssdev->dev.bus = &dss_bus_type; ++ dssdev->dev.parent = &dss_bus; ++ dssdev->dev.release = omap_dss_dev_release; ++ dev_set_name(&dssdev->dev, "display%d", dev_num++); ++ r = device_register(&dssdev->dev); ++ if (r) ++ return r; ++ ++ if (dssdev->ctrl.panel) { ++ struct omap_dss_device *panel = dssdev->ctrl.panel; ++ ++ panel->panel.ctrl = dssdev; ++ ++ reset_device(&panel->dev, 1); ++ panel->dev.bus = &dss_bus_type; ++ panel->dev.parent = &dssdev->dev; ++ panel->dev.release = omap_dss_dev_release; ++ dev_set_name(&panel->dev, "panel%d", panel_num++); ++ r = device_register(&panel->dev); ++ if (r) ++ return r; ++ } ++ ++ return 0; ++} ++ ++void omap_dss_unregister_device(struct omap_dss_device *dssdev) ++{ ++ device_unregister(&dssdev->dev); ++ ++ if (dssdev->ctrl.panel) { ++ struct omap_dss_device *panel = dssdev->ctrl.panel; ++ device_unregister(&panel->dev); ++ } ++} ++ ++/* BUS */ ++static int omap_dss_bus_register(void) ++{ ++ int r; ++ ++ r = bus_register(&dss_bus_type); ++ if (r) { ++ DSSERR("bus register failed\n"); ++ return r; ++ } ++ ++ dev_set_name(&dss_bus, "omapdss"); ++ r = device_register(&dss_bus); ++ if (r) { ++ DSSERR("bus driver register failed\n"); ++ bus_unregister(&dss_bus_type); ++ return r; ++ } ++ ++ return 0; ++} ++ ++/* INIT */ ++ ++#ifdef CONFIG_OMAP2_DSS_MODULE ++static void omap_dss_bus_unregister(void) ++{ ++ device_unregister(&dss_bus); ++ ++ bus_unregister(&dss_bus_type); ++} ++ ++static int __init omap_dss_init(void) ++{ ++ int r; ++ ++ r = omap_dss_bus_register(); ++ if (r) ++ return r; ++ ++ r = platform_driver_register(&omap_dss_driver); ++ if (r) { ++ omap_dss_bus_unregister(); ++ return r; ++ } ++ ++ return 0; ++} ++ ++static void __exit omap_dss_exit(void) ++{ ++ platform_driver_unregister(&omap_dss_driver); ++ ++ omap_dss_bus_unregister(); ++} ++ ++module_init(omap_dss_init); ++module_exit(omap_dss_exit); ++#else ++static int __init omap_dss_init(void) ++{ ++ return omap_dss_bus_register(); ++} ++ ++static int __init omap_dss_init2(void) ++{ ++ return platform_driver_register(&omap_dss_driver); ++} ++ ++core_initcall(omap_dss_init); ++device_initcall(omap_dss_init2); ++#endif ++ ++MODULE_AUTHOR("Tomi Valkeinen "); ++MODULE_DESCRIPTION("OMAP2/3 Display Subsystem"); ++MODULE_LICENSE("GPL v2"); ++ +diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c +new file mode 100644 +index 0000000..d648475 +--- /dev/null ++++ b/drivers/video/omap2/dss/dispc.c +@@ -0,0 +1,3182 @@ ++/* ++ * linux/drivers/video/omap2/dss/dispc.c ++ * ++ * Copyright (C) 2009 Nokia Corporation ++ * Author: Tomi Valkeinen ++ * ++ * Some code and ideas taken from drivers/video/omap/ driver ++ * by Imre Deak. ++ * ++ * 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. ++ * ++ * 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, see . ++ */ ++ ++#define DSS_SUBSYS_NAME "DISPC" ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++#include ++ ++#include "dss.h" ++ ++/* DISPC */ ++#define DISPC_BASE 0x48050400 ++ ++#define DISPC_SZ_REGS SZ_1K ++ ++struct dispc_reg { u16 idx; }; ++ ++#define DISPC_REG(idx) ((const struct dispc_reg) { idx }) ++ ++/* DISPC common */ ++#define DISPC_REVISION DISPC_REG(0x0000) ++#define DISPC_SYSCONFIG DISPC_REG(0x0010) ++#define DISPC_SYSSTATUS DISPC_REG(0x0014) ++#define DISPC_IRQSTATUS DISPC_REG(0x0018) ++#define DISPC_IRQENABLE DISPC_REG(0x001C) ++#define DISPC_CONTROL DISPC_REG(0x0040) ++#define DISPC_CONFIG DISPC_REG(0x0044) ++#define DISPC_CAPABLE DISPC_REG(0x0048) ++#define DISPC_DEFAULT_COLOR0 DISPC_REG(0x004C) ++#define DISPC_DEFAULT_COLOR1 DISPC_REG(0x0050) ++#define DISPC_TRANS_COLOR0 DISPC_REG(0x0054) ++#define DISPC_TRANS_COLOR1 DISPC_REG(0x0058) ++#define DISPC_LINE_STATUS DISPC_REG(0x005C) ++#define DISPC_LINE_NUMBER DISPC_REG(0x0060) ++#define DISPC_TIMING_H DISPC_REG(0x0064) ++#define DISPC_TIMING_V DISPC_REG(0x0068) ++#define DISPC_POL_FREQ DISPC_REG(0x006C) ++#define DISPC_DIVISOR DISPC_REG(0x0070) ++#define DISPC_GLOBAL_ALPHA DISPC_REG(0x0074) ++#define DISPC_SIZE_DIG DISPC_REG(0x0078) ++#define DISPC_SIZE_LCD DISPC_REG(0x007C) ++ ++/* DISPC GFX plane */ ++#define DISPC_GFX_BA0 DISPC_REG(0x0080) ++#define DISPC_GFX_BA1 DISPC_REG(0x0084) ++#define DISPC_GFX_POSITION DISPC_REG(0x0088) ++#define DISPC_GFX_SIZE DISPC_REG(0x008C) ++#define DISPC_GFX_ATTRIBUTES DISPC_REG(0x00A0) ++#define DISPC_GFX_FIFO_THRESHOLD DISPC_REG(0x00A4) ++#define DISPC_GFX_FIFO_SIZE_STATUS DISPC_REG(0x00A8) ++#define DISPC_GFX_ROW_INC DISPC_REG(0x00AC) ++#define DISPC_GFX_PIXEL_INC DISPC_REG(0x00B0) ++#define DISPC_GFX_WINDOW_SKIP DISPC_REG(0x00B4) ++#define DISPC_GFX_TABLE_BA DISPC_REG(0x00B8) ++ ++#define DISPC_DATA_CYCLE1 DISPC_REG(0x01D4) ++#define DISPC_DATA_CYCLE2 DISPC_REG(0x01D8) ++#define DISPC_DATA_CYCLE3 DISPC_REG(0x01DC) ++ ++#define DISPC_CPR_COEF_R DISPC_REG(0x0220) ++#define DISPC_CPR_COEF_G DISPC_REG(0x0224) ++#define DISPC_CPR_COEF_B DISPC_REG(0x0228) ++ ++#define DISPC_GFX_PRELOAD DISPC_REG(0x022C) ++ ++/* DISPC Video plane, n = 0 for VID1 and n = 1 for VID2 */ ++#define DISPC_VID_REG(n, idx) DISPC_REG(0x00BC + (n)*0x90 + idx) ++ ++#define DISPC_VID_BA0(n) DISPC_VID_REG(n, 0x0000) ++#define DISPC_VID_BA1(n) DISPC_VID_REG(n, 0x0004) ++#define DISPC_VID_POSITION(n) DISPC_VID_REG(n, 0x0008) ++#define DISPC_VID_SIZE(n) DISPC_VID_REG(n, 0x000C) ++#define DISPC_VID_ATTRIBUTES(n) DISPC_VID_REG(n, 0x0010) ++#define DISPC_VID_FIFO_THRESHOLD(n) DISPC_VID_REG(n, 0x0014) ++#define DISPC_VID_FIFO_SIZE_STATUS(n) DISPC_VID_REG(n, 0x0018) ++#define DISPC_VID_ROW_INC(n) DISPC_VID_REG(n, 0x001C) ++#define DISPC_VID_PIXEL_INC(n) DISPC_VID_REG(n, 0x0020) ++#define DISPC_VID_FIR(n) DISPC_VID_REG(n, 0x0024) ++#define DISPC_VID_PICTURE_SIZE(n) DISPC_VID_REG(n, 0x0028) ++#define DISPC_VID_ACCU0(n) DISPC_VID_REG(n, 0x002C) ++#define DISPC_VID_ACCU1(n) DISPC_VID_REG(n, 0x0030) ++ ++/* coef index i = {0, 1, 2, 3, 4, 5, 6, 7} */ ++#define DISPC_VID_FIR_COEF_H(n, i) DISPC_REG(0x00F0 + (n)*0x90 + (i)*0x8) ++/* coef index i = {0, 1, 2, 3, 4, 5, 6, 7} */ ++#define DISPC_VID_FIR_COEF_HV(n, i) DISPC_REG(0x00F4 + (n)*0x90 + (i)*0x8) ++/* coef index i = {0, 1, 2, 3, 4} */ ++#define DISPC_VID_CONV_COEF(n, i) DISPC_REG(0x0130 + (n)*0x90 + (i)*0x4) ++/* coef index i = {0, 1, 2, 3, 4, 5, 6, 7} */ ++#define DISPC_VID_FIR_COEF_V(n, i) DISPC_REG(0x01E0 + (n)*0x20 + (i)*0x4) ++ ++#define DISPC_VID_PRELOAD(n) DISPC_REG(0x230 + (n)*0x04) ++ ++ ++#define DISPC_IRQ_MASK_ERROR (DISPC_IRQ_GFX_FIFO_UNDERFLOW | \ ++ DISPC_IRQ_OCP_ERR | \ ++ DISPC_IRQ_VID1_FIFO_UNDERFLOW | \ ++ DISPC_IRQ_VID2_FIFO_UNDERFLOW | \ ++ DISPC_IRQ_SYNC_LOST | \ ++ DISPC_IRQ_SYNC_LOST_DIGIT) ++ ++#define DISPC_MAX_NR_ISRS 8 ++ ++struct omap_dispc_isr_data { ++ omap_dispc_isr_t isr; ++ void *arg; ++ u32 mask; ++}; ++ ++#define REG_GET(idx, start, end) \ ++ FLD_GET(dispc_read_reg(idx), start, end) ++ ++#define REG_FLD_MOD(idx, val, start, end) \ ++ dispc_write_reg(idx, FLD_MOD(dispc_read_reg(idx), val, start, end)) ++ ++static const struct dispc_reg dispc_reg_att[] = { DISPC_GFX_ATTRIBUTES, ++ DISPC_VID_ATTRIBUTES(0), ++ DISPC_VID_ATTRIBUTES(1) }; ++ ++static struct { ++ void __iomem *base; ++ ++ struct clk *dpll4_m4_ck; ++ ++ unsigned long cache_req_pck; ++ unsigned long cache_prate; ++ struct dispc_clock_info cache_cinfo; ++ ++ u32 fifo_size[3]; ++ ++ spinlock_t irq_lock; ++ u32 irq_error_mask; ++ struct omap_dispc_isr_data registered_isr[DISPC_MAX_NR_ISRS]; ++ u32 error_irqs; ++ struct work_struct error_work; ++ ++ u32 ctx[DISPC_SZ_REGS / sizeof(u32)]; ++} dispc; ++ ++static void _omap_dispc_set_irqs(void); ++ ++static inline void dispc_write_reg(const struct dispc_reg idx, u32 val) ++{ ++ __raw_writel(val, dispc.base + idx.idx); ++} ++ ++static inline u32 dispc_read_reg(const struct dispc_reg idx) ++{ ++ return __raw_readl(dispc.base + idx.idx); ++} ++ ++#define SR(reg) \ ++ dispc.ctx[(DISPC_##reg).idx / sizeof(u32)] = dispc_read_reg(DISPC_##reg) ++#define RR(reg) \ ++ dispc_write_reg(DISPC_##reg, dispc.ctx[(DISPC_##reg).idx / sizeof(u32)]) ++ ++void dispc_save_context(void) ++{ ++ if (cpu_is_omap24xx()) ++ return; ++ ++ SR(SYSCONFIG); ++ SR(IRQENABLE); ++ SR(CONTROL); ++ SR(CONFIG); ++ SR(DEFAULT_COLOR0); ++ SR(DEFAULT_COLOR1); ++ SR(TRANS_COLOR0); ++ SR(TRANS_COLOR1); ++ SR(LINE_NUMBER); ++ SR(TIMING_H); ++ SR(TIMING_V); ++ SR(POL_FREQ); ++ SR(DIVISOR); ++ SR(GLOBAL_ALPHA); ++ SR(SIZE_DIG); ++ SR(SIZE_LCD); ++ ++ SR(GFX_BA0); ++ SR(GFX_BA1); ++ SR(GFX_POSITION); ++ SR(GFX_SIZE); ++ SR(GFX_ATTRIBUTES); ++ SR(GFX_FIFO_THRESHOLD); ++ SR(GFX_ROW_INC); ++ SR(GFX_PIXEL_INC); ++ SR(GFX_WINDOW_SKIP); ++ SR(GFX_TABLE_BA); ++ ++ SR(DATA_CYCLE1); ++ SR(DATA_CYCLE2); ++ SR(DATA_CYCLE3); ++ ++ SR(CPR_COEF_R); ++ SR(CPR_COEF_G); ++ SR(CPR_COEF_B); ++ ++ SR(GFX_PRELOAD); ++ ++ /* VID1 */ ++ SR(VID_BA0(0)); ++ SR(VID_BA1(0)); ++ SR(VID_POSITION(0)); ++ SR(VID_SIZE(0)); ++ SR(VID_ATTRIBUTES(0)); ++ SR(VID_FIFO_THRESHOLD(0)); ++ SR(VID_ROW_INC(0)); ++ SR(VID_PIXEL_INC(0)); ++ SR(VID_FIR(0)); ++ SR(VID_PICTURE_SIZE(0)); ++ SR(VID_ACCU0(0)); ++ SR(VID_ACCU1(0)); ++ ++ SR(VID_FIR_COEF_H(0, 0)); ++ SR(VID_FIR_COEF_H(0, 1)); ++ SR(VID_FIR_COEF_H(0, 2)); ++ SR(VID_FIR_COEF_H(0, 3)); ++ SR(VID_FIR_COEF_H(0, 4)); ++ SR(VID_FIR_COEF_H(0, 5)); ++ SR(VID_FIR_COEF_H(0, 6)); ++ SR(VID_FIR_COEF_H(0, 7)); ++ ++ SR(VID_FIR_COEF_HV(0, 0)); ++ SR(VID_FIR_COEF_HV(0, 1)); ++ SR(VID_FIR_COEF_HV(0, 2)); ++ SR(VID_FIR_COEF_HV(0, 3)); ++ SR(VID_FIR_COEF_HV(0, 4)); ++ SR(VID_FIR_COEF_HV(0, 5)); ++ SR(VID_FIR_COEF_HV(0, 6)); ++ SR(VID_FIR_COEF_HV(0, 7)); ++ ++ SR(VID_CONV_COEF(0, 0)); ++ SR(VID_CONV_COEF(0, 1)); ++ SR(VID_CONV_COEF(0, 2)); ++ SR(VID_CONV_COEF(0, 3)); ++ SR(VID_CONV_COEF(0, 4)); ++ ++ SR(VID_FIR_COEF_V(0, 0)); ++ SR(VID_FIR_COEF_V(0, 1)); ++ SR(VID_FIR_COEF_V(0, 2)); ++ SR(VID_FIR_COEF_V(0, 3)); ++ SR(VID_FIR_COEF_V(0, 4)); ++ SR(VID_FIR_COEF_V(0, 5)); ++ SR(VID_FIR_COEF_V(0, 6)); ++ SR(VID_FIR_COEF_V(0, 7)); ++ ++ SR(VID_PRELOAD(0)); ++ ++ /* VID2 */ ++ SR(VID_BA0(1)); ++ SR(VID_BA1(1)); ++ SR(VID_POSITION(1)); ++ SR(VID_SIZE(1)); ++ SR(VID_ATTRIBUTES(1)); ++ SR(VID_FIFO_THRESHOLD(1)); ++ SR(VID_ROW_INC(1)); ++ SR(VID_PIXEL_INC(1)); ++ SR(VID_FIR(1)); ++ SR(VID_PICTURE_SIZE(1)); ++ SR(VID_ACCU0(1)); ++ SR(VID_ACCU1(1)); ++ ++ SR(VID_FIR_COEF_H(1, 0)); ++ SR(VID_FIR_COEF_H(1, 1)); ++ SR(VID_FIR_COEF_H(1, 2)); ++ SR(VID_FIR_COEF_H(1, 3)); ++ SR(VID_FIR_COEF_H(1, 4)); ++ SR(VID_FIR_COEF_H(1, 5)); ++ SR(VID_FIR_COEF_H(1, 6)); ++ SR(VID_FIR_COEF_H(1, 7)); ++ ++ SR(VID_FIR_COEF_HV(1, 0)); ++ SR(VID_FIR_COEF_HV(1, 1)); ++ SR(VID_FIR_COEF_HV(1, 2)); ++ SR(VID_FIR_COEF_HV(1, 3)); ++ SR(VID_FIR_COEF_HV(1, 4)); ++ SR(VID_FIR_COEF_HV(1, 5)); ++ SR(VID_FIR_COEF_HV(1, 6)); ++ SR(VID_FIR_COEF_HV(1, 7)); ++ ++ SR(VID_CONV_COEF(1, 0)); ++ SR(VID_CONV_COEF(1, 1)); ++ SR(VID_CONV_COEF(1, 2)); ++ SR(VID_CONV_COEF(1, 3)); ++ SR(VID_CONV_COEF(1, 4)); ++ ++ SR(VID_FIR_COEF_V(1, 0)); ++ SR(VID_FIR_COEF_V(1, 1)); ++ SR(VID_FIR_COEF_V(1, 2)); ++ SR(VID_FIR_COEF_V(1, 3)); ++ SR(VID_FIR_COEF_V(1, 4)); ++ SR(VID_FIR_COEF_V(1, 5)); ++ SR(VID_FIR_COEF_V(1, 6)); ++ SR(VID_FIR_COEF_V(1, 7)); ++ ++ SR(VID_PRELOAD(1)); ++} ++ ++void dispc_restore_context(void) ++{ ++ RR(SYSCONFIG); ++ RR(IRQENABLE); ++ /*RR(CONTROL);*/ ++ RR(CONFIG); ++ RR(DEFAULT_COLOR0); ++ RR(DEFAULT_COLOR1); ++ RR(TRANS_COLOR0); ++ RR(TRANS_COLOR1); ++ RR(LINE_NUMBER); ++ RR(TIMING_H); ++ RR(TIMING_V); ++ RR(POL_FREQ); ++ RR(DIVISOR); ++ RR(GLOBAL_ALPHA); ++ RR(SIZE_DIG); ++ RR(SIZE_LCD); ++ ++ RR(GFX_BA0); ++ RR(GFX_BA1); ++ RR(GFX_POSITION); ++ RR(GFX_SIZE); ++ RR(GFX_ATTRIBUTES); ++ RR(GFX_FIFO_THRESHOLD); ++ RR(GFX_ROW_INC); ++ RR(GFX_PIXEL_INC); ++ RR(GFX_WINDOW_SKIP); ++ RR(GFX_TABLE_BA); ++ ++ RR(DATA_CYCLE1); ++ RR(DATA_CYCLE2); ++ RR(DATA_CYCLE3); ++ ++ RR(CPR_COEF_R); ++ RR(CPR_COEF_G); ++ RR(CPR_COEF_B); ++ ++ RR(GFX_PRELOAD); ++ ++ /* VID1 */ ++ RR(VID_BA0(0)); ++ RR(VID_BA1(0)); ++ RR(VID_POSITION(0)); ++ RR(VID_SIZE(0)); ++ RR(VID_ATTRIBUTES(0)); ++ RR(VID_FIFO_THRESHOLD(0)); ++ RR(VID_ROW_INC(0)); ++ RR(VID_PIXEL_INC(0)); ++ RR(VID_FIR(0)); ++ RR(VID_PICTURE_SIZE(0)); ++ RR(VID_ACCU0(0)); ++ RR(VID_ACCU1(0)); ++ ++ RR(VID_FIR_COEF_H(0, 0)); ++ RR(VID_FIR_COEF_H(0, 1)); ++ RR(VID_FIR_COEF_H(0, 2)); ++ RR(VID_FIR_COEF_H(0, 3)); ++ RR(VID_FIR_COEF_H(0, 4)); ++ RR(VID_FIR_COEF_H(0, 5)); ++ RR(VID_FIR_COEF_H(0, 6)); ++ RR(VID_FIR_COEF_H(0, 7)); ++ ++ RR(VID_FIR_COEF_HV(0, 0)); ++ RR(VID_FIR_COEF_HV(0, 1)); ++ RR(VID_FIR_COEF_HV(0, 2)); ++ RR(VID_FIR_COEF_HV(0, 3)); ++ RR(VID_FIR_COEF_HV(0, 4)); ++ RR(VID_FIR_COEF_HV(0, 5)); ++ RR(VID_FIR_COEF_HV(0, 6)); ++ RR(VID_FIR_COEF_HV(0, 7)); ++ ++ RR(VID_CONV_COEF(0, 0)); ++ RR(VID_CONV_COEF(0, 1)); ++ RR(VID_CONV_COEF(0, 2)); ++ RR(VID_CONV_COEF(0, 3)); ++ RR(VID_CONV_COEF(0, 4)); ++ ++ RR(VID_FIR_COEF_V(0, 0)); ++ RR(VID_FIR_COEF_V(0, 1)); ++ RR(VID_FIR_COEF_V(0, 2)); ++ RR(VID_FIR_COEF_V(0, 3)); ++ RR(VID_FIR_COEF_V(0, 4)); ++ RR(VID_FIR_COEF_V(0, 5)); ++ RR(VID_FIR_COEF_V(0, 6)); ++ RR(VID_FIR_COEF_V(0, 7)); ++ ++ RR(VID_PRELOAD(0)); ++ ++ /* VID2 */ ++ RR(VID_BA0(1)); ++ RR(VID_BA1(1)); ++ RR(VID_POSITION(1)); ++ RR(VID_SIZE(1)); ++ RR(VID_ATTRIBUTES(1)); ++ RR(VID_FIFO_THRESHOLD(1)); ++ RR(VID_ROW_INC(1)); ++ RR(VID_PIXEL_INC(1)); ++ RR(VID_FIR(1)); ++ RR(VID_PICTURE_SIZE(1)); ++ RR(VID_ACCU0(1)); ++ RR(VID_ACCU1(1)); ++ ++ RR(VID_FIR_COEF_H(1, 0)); ++ RR(VID_FIR_COEF_H(1, 1)); ++ RR(VID_FIR_COEF_H(1, 2)); ++ RR(VID_FIR_COEF_H(1, 3)); ++ RR(VID_FIR_COEF_H(1, 4)); ++ RR(VID_FIR_COEF_H(1, 5)); ++ RR(VID_FIR_COEF_H(1, 6)); ++ RR(VID_FIR_COEF_H(1, 7)); ++ ++ RR(VID_FIR_COEF_HV(1, 0)); ++ RR(VID_FIR_COEF_HV(1, 1)); ++ RR(VID_FIR_COEF_HV(1, 2)); ++ RR(VID_FIR_COEF_HV(1, 3)); ++ RR(VID_FIR_COEF_HV(1, 4)); ++ RR(VID_FIR_COEF_HV(1, 5)); ++ RR(VID_FIR_COEF_HV(1, 6)); ++ RR(VID_FIR_COEF_HV(1, 7)); ++ ++ RR(VID_CONV_COEF(1, 0)); ++ RR(VID_CONV_COEF(1, 1)); ++ RR(VID_CONV_COEF(1, 2)); ++ RR(VID_CONV_COEF(1, 3)); ++ RR(VID_CONV_COEF(1, 4)); ++ ++ RR(VID_FIR_COEF_V(1, 0)); ++ RR(VID_FIR_COEF_V(1, 1)); ++ RR(VID_FIR_COEF_V(1, 2)); ++ RR(VID_FIR_COEF_V(1, 3)); ++ RR(VID_FIR_COEF_V(1, 4)); ++ RR(VID_FIR_COEF_V(1, 5)); ++ RR(VID_FIR_COEF_V(1, 6)); ++ RR(VID_FIR_COEF_V(1, 7)); ++ ++ RR(VID_PRELOAD(1)); ++ ++ /* enable last, because LCD & DIGIT enable are here */ ++ RR(CONTROL); ++} ++ ++#undef SR ++#undef RR ++ ++static inline void enable_clocks(bool enable) ++{ ++ if (enable) ++ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); ++ else ++ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); ++} ++ ++bool dispc_go_busy(enum omap_channel channel) ++{ ++ int bit; ++ ++ if (channel == OMAP_DSS_CHANNEL_LCD) ++ bit = 5; /* GOLCD */ ++ else ++ bit = 6; /* GODIGIT */ ++ ++ return REG_GET(DISPC_CONTROL, bit, bit) == 1; ++} ++ ++void dispc_go(enum omap_channel channel) ++{ ++ int bit; ++ ++ enable_clocks(1); ++ ++ if (channel == OMAP_DSS_CHANNEL_LCD) ++ bit = 0; /* LCDENABLE */ ++ else ++ bit = 1; /* DIGITALENABLE */ ++ ++ /* if the channel is not enabled, we don't need GO */ ++ if (REG_GET(DISPC_CONTROL, bit, bit) == 0) ++ goto end; ++ ++ if (channel == OMAP_DSS_CHANNEL_LCD) ++ bit = 5; /* GOLCD */ ++ else ++ bit = 6; /* GODIGIT */ ++ ++ if (REG_GET(DISPC_CONTROL, bit, bit) == 1) { ++ DSSERR("GO bit not down for channel %d\n", channel); ++ goto end; ++ } ++ ++ DSSDBG("GO %s\n", channel == OMAP_DSS_CHANNEL_LCD ? "LCD" : "DIGIT"); ++ ++ REG_FLD_MOD(DISPC_CONTROL, 1, bit, bit); ++end: ++ enable_clocks(0); ++} ++ ++static void _dispc_write_firh_reg(enum omap_plane plane, int reg, u32 value) ++{ ++ BUG_ON(plane == OMAP_DSS_GFX); ++ ++ dispc_write_reg(DISPC_VID_FIR_COEF_H(plane-1, reg), value); ++} ++ ++static void _dispc_write_firhv_reg(enum omap_plane plane, int reg, u32 value) ++{ ++ BUG_ON(plane == OMAP_DSS_GFX); ++ ++ dispc_write_reg(DISPC_VID_FIR_COEF_HV(plane-1, reg), value); ++} ++ ++static void _dispc_write_firv_reg(enum omap_plane plane, int reg, u32 value) ++{ ++ BUG_ON(plane == OMAP_DSS_GFX); ++ ++ dispc_write_reg(DISPC_VID_FIR_COEF_V(plane-1, reg), value); ++} ++ ++static void _dispc_set_scale_coef(enum omap_plane plane, int hscaleup, ++ int vscaleup, int five_taps) ++{ ++ /* Coefficients for horizontal up-sampling */ ++ static const u32 coef_hup[8] = { ++ 0x00800000, ++ 0x0D7CF800, ++ 0x1E70F5FF, ++ 0x335FF5FE, ++ 0xF74949F7, ++ 0xF55F33FB, ++ 0xF5701EFE, ++ 0xF87C0DFF, ++ }; ++ ++ /* Coefficients for horizontal down-sampling */ ++ static const u32 coef_hdown[8] = { ++ 0x24382400, ++ 0x28371FFE, ++ 0x2C361BFB, ++ 0x303516F9, ++ 0x11343311, ++ 0x1635300C, ++ 0x1B362C08, ++ 0x1F372804, ++ }; ++ ++ /* Coefficients for horizontal and vertical up-sampling */ ++ static const u32 coef_hvup[2][8] = { ++ { ++ 0x00800000, ++ 0x037B02FF, ++ 0x0C6F05FE, ++ 0x205907FB, ++ 0x00404000, ++ 0x075920FE, ++ 0x056F0CFF, ++ 0x027B0300, ++ }, ++ { ++ 0x00800000, ++ 0x0D7CF8FF, ++ 0x1E70F5FE, ++ 0x335FF5FB, ++ 0xF7404000, ++ 0xF55F33FE, ++ 0xF5701EFF, ++ 0xF87C0D00, ++ }, ++ }; ++ ++ /* Coefficients for horizontal and vertical down-sampling */ ++ static const u32 coef_hvdown[2][8] = { ++ { ++ 0x24382400, ++ 0x28391F04, ++ 0x2D381B08, ++ 0x3237170C, ++ 0x123737F7, ++ 0x173732F9, ++ 0x1B382DFB, ++ 0x1F3928FE, ++ }, ++ { ++ 0x24382400, ++ 0x28371F04, ++ 0x2C361B08, ++ 0x3035160C, ++ 0x113433F7, ++ 0x163530F9, ++ 0x1B362CFB, ++ 0x1F3728FE, ++ }, ++ }; ++ ++ /* Coefficients for vertical up-sampling */ ++ static const u32 coef_vup[8] = { ++ 0x00000000, ++ 0x0000FF00, ++ 0x0000FEFF, ++ 0x0000FBFE, ++ 0x000000F7, ++ 0x0000FEFB, ++ 0x0000FFFE, ++ 0x000000FF, ++ }; ++ ++ ++ /* Coefficients for vertical down-sampling */ ++ static const u32 coef_vdown[8] = { ++ 0x00000000, ++ 0x000004FE, ++ 0x000008FB, ++ 0x00000CF9, ++ 0x0000F711, ++ 0x0000F90C, ++ 0x0000FB08, ++ 0x0000FE04, ++ }; ++ ++ const u32 *h_coef; ++ const u32 *hv_coef; ++ const u32 *hv_coef_mod; ++ const u32 *v_coef; ++ int i; ++ ++ if (hscaleup) ++ h_coef = coef_hup; ++ else ++ h_coef = coef_hdown; ++ ++ if (vscaleup) { ++ hv_coef = coef_hvup[five_taps]; ++ v_coef = coef_vup; ++ ++ if (hscaleup) ++ hv_coef_mod = NULL; ++ else ++ hv_coef_mod = coef_hvdown[five_taps]; ++ } else { ++ hv_coef = coef_hvdown[five_taps]; ++ v_coef = coef_vdown; ++ ++ if (hscaleup) ++ hv_coef_mod = coef_hvup[five_taps]; ++ else ++ hv_coef_mod = NULL; ++ } ++ ++ for (i = 0; i < 8; i++) { ++ u32 h, hv; ++ ++ h = h_coef[i]; ++ ++ hv = hv_coef[i]; ++ ++ if (hv_coef_mod) { ++ hv &= 0xffffff00; ++ hv |= (hv_coef_mod[i] & 0xff); ++ } ++ ++ _dispc_write_firh_reg(plane, i, h); ++ _dispc_write_firhv_reg(plane, i, hv); ++ } ++ ++ if (!five_taps) ++ return; ++ ++ for (i = 0; i < 8; i++) { ++ u32 v; ++ v = v_coef[i]; ++ _dispc_write_firv_reg(plane, i, v); ++ } ++} ++ ++static void _dispc_setup_color_conv_coef(void) ++{ ++ const struct color_conv_coef { ++ int ry, rcr, rcb, gy, gcr, gcb, by, bcr, bcb; ++ int full_range; ++ } ctbl_bt601_5 = { ++ 298, 409, 0, 298, -208, -100, 298, 0, 517, 0, ++ }; ++ ++ const struct color_conv_coef *ct; ++ ++#define CVAL(x, y) (FLD_VAL(x, 26, 16) | FLD_VAL(y, 10, 0)) ++ ++ ct = &ctbl_bt601_5; ++ ++ dispc_write_reg(DISPC_VID_CONV_COEF(0, 0), CVAL(ct->rcr, ct->ry)); ++ dispc_write_reg(DISPC_VID_CONV_COEF(0, 1), CVAL(ct->gy, ct->rcb)); ++ dispc_write_reg(DISPC_VID_CONV_COEF(0, 2), CVAL(ct->gcb, ct->gcr)); ++ dispc_write_reg(DISPC_VID_CONV_COEF(0, 3), CVAL(ct->bcr, ct->by)); ++ dispc_write_reg(DISPC_VID_CONV_COEF(0, 4), CVAL(0, ct->bcb)); ++ ++ dispc_write_reg(DISPC_VID_CONV_COEF(1, 0), CVAL(ct->rcr, ct->ry)); ++ dispc_write_reg(DISPC_VID_CONV_COEF(1, 1), CVAL(ct->gy, ct->rcb)); ++ dispc_write_reg(DISPC_VID_CONV_COEF(1, 2), CVAL(ct->gcb, ct->gcr)); ++ dispc_write_reg(DISPC_VID_CONV_COEF(1, 3), CVAL(ct->bcr, ct->by)); ++ dispc_write_reg(DISPC_VID_CONV_COEF(1, 4), CVAL(0, ct->bcb)); ++ ++#undef CVAL ++ ++ REG_FLD_MOD(DISPC_VID_ATTRIBUTES(0), ct->full_range, 11, 11); ++ REG_FLD_MOD(DISPC_VID_ATTRIBUTES(1), ct->full_range, 11, 11); ++} ++ ++ ++static void _dispc_set_plane_ba0(enum omap_plane plane, u32 paddr) ++{ ++ const struct dispc_reg ba0_reg[] = { DISPC_GFX_BA0, ++ DISPC_VID_BA0(0), ++ DISPC_VID_BA0(1) }; ++ ++ dispc_write_reg(ba0_reg[plane], paddr); ++} ++ ++static void _dispc_set_plane_ba1(enum omap_plane plane, u32 paddr) ++{ ++ const struct dispc_reg ba1_reg[] = { DISPC_GFX_BA1, ++ DISPC_VID_BA1(0), ++ DISPC_VID_BA1(1) }; ++ ++ dispc_write_reg(ba1_reg[plane], paddr); ++} ++ ++static void _dispc_set_plane_pos(enum omap_plane plane, int x, int y) ++{ ++ const struct dispc_reg pos_reg[] = { DISPC_GFX_POSITION, ++ DISPC_VID_POSITION(0), ++ DISPC_VID_POSITION(1) }; ++ ++ u32 val = FLD_VAL(y, 26, 16) | FLD_VAL(x, 10, 0); ++ dispc_write_reg(pos_reg[plane], val); ++} ++ ++static void _dispc_set_pic_size(enum omap_plane plane, int width, int height) ++{ ++ const struct dispc_reg siz_reg[] = { DISPC_GFX_SIZE, ++ DISPC_VID_PICTURE_SIZE(0), ++ DISPC_VID_PICTURE_SIZE(1) }; ++ u32 val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0); ++ dispc_write_reg(siz_reg[plane], val); ++} ++ ++static void _dispc_set_vid_size(enum omap_plane plane, int width, int height) ++{ ++ u32 val; ++ const struct dispc_reg vsi_reg[] = { DISPC_VID_SIZE(0), ++ DISPC_VID_SIZE(1) }; ++ ++ BUG_ON(plane == OMAP_DSS_GFX); ++ ++ val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0); ++ dispc_write_reg(vsi_reg[plane-1], val); ++} ++ ++static void _dispc_setup_global_alpha(enum omap_plane plane, u8 global_alpha) ++{ ++ ++ BUG_ON(plane == OMAP_DSS_VIDEO1); ++ ++ if (plane == OMAP_DSS_GFX) ++ REG_FLD_MOD(DISPC_GLOBAL_ALPHA, global_alpha, 7, 0); ++ else if (plane == OMAP_DSS_VIDEO2) ++ REG_FLD_MOD(DISPC_GLOBAL_ALPHA, global_alpha, 23, 16); ++} ++ ++static void _dispc_set_pix_inc(enum omap_plane plane, s32 inc) ++{ ++ const struct dispc_reg ri_reg[] = { DISPC_GFX_PIXEL_INC, ++ DISPC_VID_PIXEL_INC(0), ++ DISPC_VID_PIXEL_INC(1) }; ++ ++ dispc_write_reg(ri_reg[plane], inc); ++} ++ ++static void _dispc_set_row_inc(enum omap_plane plane, s32 inc) ++{ ++ const struct dispc_reg ri_reg[] = { DISPC_GFX_ROW_INC, ++ DISPC_VID_ROW_INC(0), ++ DISPC_VID_ROW_INC(1) }; ++ ++ dispc_write_reg(ri_reg[plane], inc); ++} ++ ++static void _dispc_set_color_mode(enum omap_plane plane, ++ enum omap_color_mode color_mode) ++{ ++ u32 m = 0; ++ ++ switch (color_mode) { ++ case OMAP_DSS_COLOR_CLUT1: ++ m = 0x0; break; ++ case OMAP_DSS_COLOR_CLUT2: ++ m = 0x1; break; ++ case OMAP_DSS_COLOR_CLUT4: ++ m = 0x2; break; ++ case OMAP_DSS_COLOR_CLUT8: ++ m = 0x3; break; ++ case OMAP_DSS_COLOR_RGB12U: ++ m = 0x4; break; ++ case OMAP_DSS_COLOR_ARGB16: ++ m = 0x5; break; ++ case OMAP_DSS_COLOR_RGB16: ++ m = 0x6; break; ++ case OMAP_DSS_COLOR_RGB24U: ++ m = 0x8; break; ++ case OMAP_DSS_COLOR_RGB24P: ++ m = 0x9; break; ++ case OMAP_DSS_COLOR_YUV2: ++ m = 0xa; break; ++ case OMAP_DSS_COLOR_UYVY: ++ m = 0xb; break; ++ case OMAP_DSS_COLOR_ARGB32: ++ m = 0xc; break; ++ case OMAP_DSS_COLOR_RGBA32: ++ m = 0xd; break; ++ case OMAP_DSS_COLOR_RGBX32: ++ m = 0xe; break; ++ default: ++ BUG(); break; ++ } ++ ++ REG_FLD_MOD(dispc_reg_att[plane], m, 4, 1); ++} ++ ++static void _dispc_set_channel_out(enum omap_plane plane, ++ enum omap_channel channel) ++{ ++ int shift; ++ u32 val; ++ ++ switch (plane) { ++ case OMAP_DSS_GFX: ++ shift = 8; ++ break; ++ case OMAP_DSS_VIDEO1: ++ case OMAP_DSS_VIDEO2: ++ shift = 16; ++ break; ++ default: ++ BUG(); ++ return; ++ } ++ ++ val = dispc_read_reg(dispc_reg_att[plane]); ++ val = FLD_MOD(val, channel, shift, shift); ++ dispc_write_reg(dispc_reg_att[plane], val); ++} ++ ++void dispc_set_burst_size(enum omap_plane plane, ++ enum omap_burst_size burst_size) ++{ ++ int shift; ++ u32 val; ++ ++ enable_clocks(1); ++ ++ switch (plane) { ++ case OMAP_DSS_GFX: ++ shift = 6; ++ break; ++ case OMAP_DSS_VIDEO1: ++ case OMAP_DSS_VIDEO2: ++ shift = 14; ++ break; ++ default: ++ BUG(); ++ return; ++ } ++ ++ val = dispc_read_reg(dispc_reg_att[plane]); ++ val = FLD_MOD(val, burst_size, shift+1, shift); ++ dispc_write_reg(dispc_reg_att[plane], val); ++ ++ enable_clocks(0); ++} ++ ++static void _dispc_set_vid_color_conv(enum omap_plane plane, bool enable) ++{ ++ u32 val; ++ ++ BUG_ON(plane == OMAP_DSS_GFX); ++ ++ val = dispc_read_reg(dispc_reg_att[plane]); ++ val = FLD_MOD(val, enable, 9, 9); ++ dispc_write_reg(dispc_reg_att[plane], val); ++} ++ ++void dispc_enable_replication(enum omap_plane plane, bool enable) ++{ ++ int bit; ++ ++ if (plane == OMAP_DSS_GFX) ++ bit = 5; ++ else ++ bit = 10; ++ ++ enable_clocks(1); ++ REG_FLD_MOD(dispc_reg_att[plane], enable, bit, bit); ++ enable_clocks(0); ++} ++ ++void dispc_set_lcd_size(u16 width, u16 height) ++{ ++ u32 val; ++ BUG_ON((width > (1 << 11)) || (height > (1 << 11))); ++ val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0); ++ enable_clocks(1); ++ dispc_write_reg(DISPC_SIZE_LCD, val); ++ enable_clocks(0); ++} ++ ++void dispc_set_digit_size(u16 width, u16 height) ++{ ++ u32 val; ++ BUG_ON((width > (1 << 11)) || (height > (1 << 11))); ++ val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0); ++ enable_clocks(1); ++ dispc_write_reg(DISPC_SIZE_DIG, val); ++ enable_clocks(0); ++} ++ ++static void dispc_read_plane_fifo_sizes(void) ++{ ++ const struct dispc_reg fsz_reg[] = { DISPC_GFX_FIFO_SIZE_STATUS, ++ DISPC_VID_FIFO_SIZE_STATUS(0), ++ DISPC_VID_FIFO_SIZE_STATUS(1) }; ++ u32 size; ++ int plane; ++ ++ enable_clocks(1); ++ ++ for (plane = 0; plane < ARRAY_SIZE(dispc.fifo_size); ++plane) { ++ if (cpu_is_omap24xx()) ++ size = FLD_GET(dispc_read_reg(fsz_reg[plane]), 8, 0); ++ else if (cpu_is_omap34xx()) ++ size = FLD_GET(dispc_read_reg(fsz_reg[plane]), 10, 0); ++ else ++ BUG(); ++ ++ dispc.fifo_size[plane] = size; ++ } ++ ++ enable_clocks(0); ++} ++ ++u32 dispc_get_plane_fifo_size(enum omap_plane plane) ++{ ++ return dispc.fifo_size[plane]; ++} ++ ++void dispc_setup_plane_fifo(enum omap_plane plane, u32 low, u32 high) ++{ ++ const struct dispc_reg ftrs_reg[] = { DISPC_GFX_FIFO_THRESHOLD, ++ DISPC_VID_FIFO_THRESHOLD(0), ++ DISPC_VID_FIFO_THRESHOLD(1) }; ++ enable_clocks(1); ++ ++ DSSDBG("fifo(%d) low/high old %u/%u, new %u/%u\n", ++ plane, ++ REG_GET(ftrs_reg[plane], 11, 0), ++ REG_GET(ftrs_reg[plane], 27, 16), ++ low, high); ++ ++ if (cpu_is_omap24xx()) ++ dispc_write_reg(ftrs_reg[plane], ++ FLD_VAL(high, 24, 16) | FLD_VAL(low, 8, 0)); ++ else ++ dispc_write_reg(ftrs_reg[plane], ++ FLD_VAL(high, 27, 16) | FLD_VAL(low, 11, 0)); ++ ++ enable_clocks(0); ++} ++ ++void dispc_enable_fifomerge(bool enable) ++{ ++ enable_clocks(1); ++ ++ DSSDBG("FIFO merge %s\n", enable ? "enabled" : "disabled"); ++ REG_FLD_MOD(DISPC_CONFIG, enable ? 1 : 0, 14, 14); ++ ++ enable_clocks(0); ++} ++ ++static void _dispc_set_fir(enum omap_plane plane, int hinc, int vinc) ++{ ++ u32 val; ++ const struct dispc_reg fir_reg[] = { DISPC_VID_FIR(0), ++ DISPC_VID_FIR(1) }; ++ ++ BUG_ON(plane == OMAP_DSS_GFX); ++ ++ if (cpu_is_omap24xx()) ++ val = FLD_VAL(vinc, 27, 16) | FLD_VAL(hinc, 11, 0); ++ else ++ val = FLD_VAL(vinc, 28, 16) | FLD_VAL(hinc, 12, 0); ++ dispc_write_reg(fir_reg[plane-1], val); ++} ++ ++static void _dispc_set_vid_accu0(enum omap_plane plane, int haccu, int vaccu) ++{ ++ u32 val; ++ const struct dispc_reg ac0_reg[] = { DISPC_VID_ACCU0(0), ++ DISPC_VID_ACCU0(1) }; ++ ++ BUG_ON(plane == OMAP_DSS_GFX); ++ ++ val = FLD_VAL(vaccu, 25, 16) | FLD_VAL(haccu, 9, 0); ++ dispc_write_reg(ac0_reg[plane-1], val); ++} ++ ++static void _dispc_set_vid_accu1(enum omap_plane plane, int haccu, int vaccu) ++{ ++ u32 val; ++ const struct dispc_reg ac1_reg[] = { DISPC_VID_ACCU1(0), ++ DISPC_VID_ACCU1(1) }; ++ ++ BUG_ON(plane == OMAP_DSS_GFX); ++ ++ val = FLD_VAL(vaccu, 25, 16) | FLD_VAL(haccu, 9, 0); ++ dispc_write_reg(ac1_reg[plane-1], val); ++} ++ ++ ++static void _dispc_set_scaling(enum omap_plane plane, ++ u16 orig_width, u16 orig_height, ++ u16 out_width, u16 out_height, ++ bool ilace, bool five_taps, ++ bool fieldmode) ++{ ++ int fir_hinc; ++ int fir_vinc; ++ int hscaleup, vscaleup; ++ int accu0 = 0; ++ int accu1 = 0; ++ u32 l; ++ ++ BUG_ON(plane == OMAP_DSS_GFX); ++ ++ hscaleup = orig_width <= out_width; ++ vscaleup = orig_height <= out_height; ++ ++ _dispc_set_scale_coef(plane, hscaleup, vscaleup, five_taps); ++ ++ if (!orig_width || orig_width == out_width) ++ fir_hinc = 0; ++ else ++ fir_hinc = 1024 * orig_width / out_width; ++ ++ if (!orig_height || orig_height == out_height) ++ fir_vinc = 0; ++ else ++ fir_vinc = 1024 * orig_height / out_height; ++ ++ _dispc_set_fir(plane, fir_hinc, fir_vinc); ++ ++ l = dispc_read_reg(dispc_reg_att[plane]); ++ l &= ~((0x0f << 5) | (0x3 << 21)); ++ ++ l |= fir_hinc ? (1 << 5) : 0; ++ l |= fir_vinc ? (1 << 6) : 0; ++ ++ l |= hscaleup ? 0 : (1 << 7); ++ l |= vscaleup ? 0 : (1 << 8); ++ ++ l |= five_taps ? (1 << 21) : 0; ++ l |= five_taps ? (1 << 22) : 0; ++ ++ dispc_write_reg(dispc_reg_att[plane], l); ++ ++ /* ++ * field 0 = even field = bottom field ++ * field 1 = odd field = top field ++ */ ++ if (ilace && !fieldmode) { ++ accu1 = 0; ++ accu0 = (fir_vinc / 2) & 0x3ff; ++ if (accu0 >= 1024/2) { ++ accu1 = 1024/2; ++ accu0 -= accu1; ++ } ++ } ++ ++ _dispc_set_vid_accu0(plane, 0, accu0); ++ _dispc_set_vid_accu1(plane, 0, accu1); ++} ++ ++static void _dispc_set_rotation_attrs(enum omap_plane plane, u8 rotation, ++ bool mirroring, enum omap_color_mode color_mode) ++{ ++ if (color_mode == OMAP_DSS_COLOR_YUV2 || ++ color_mode == OMAP_DSS_COLOR_UYVY) { ++ int vidrot = 0; ++ ++ if (mirroring) { ++ switch (rotation) { ++ case 0: ++ vidrot = 2; ++ break; ++ case 1: ++ vidrot = 1; ++ break; ++ case 2: ++ vidrot = 0; ++ break; ++ case 3: ++ vidrot = 3; ++ break; ++ } ++ } else { ++ switch (rotation) { ++ case 0: ++ vidrot = 0; ++ break; ++ case 1: ++ vidrot = 1; ++ break; ++ case 2: ++ vidrot = 2; ++ break; ++ case 3: ++ vidrot = 3; ++ break; ++ } ++ } ++ ++ REG_FLD_MOD(dispc_reg_att[plane], vidrot, 13, 12); ++ ++ if (rotation == 1 || rotation == 3) ++ REG_FLD_MOD(dispc_reg_att[plane], 0x1, 18, 18); ++ else ++ REG_FLD_MOD(dispc_reg_att[plane], 0x0, 18, 18); ++ } else { ++ REG_FLD_MOD(dispc_reg_att[plane], 0, 13, 12); ++ REG_FLD_MOD(dispc_reg_att[plane], 0, 18, 18); ++ } ++} ++ ++static s32 pixinc(int pixels, u8 ps) ++{ ++ if (pixels == 1) ++ return 1; ++ else if (pixels > 1) ++ return 1 + (pixels - 1) * ps; ++ else if (pixels < 0) ++ return 1 - (-pixels + 1) * ps; ++ else ++ BUG(); ++} ++ ++static void calc_vrfb_rotation_offset(u8 rotation, bool mirror, ++ u16 screen_width, ++ u16 width, u16 height, ++ enum omap_color_mode color_mode, bool fieldmode, ++ unsigned int field_offset, ++ unsigned *offset0, unsigned *offset1, ++ s32 *row_inc, s32 *pix_inc) ++{ ++ u8 ps; ++ ++ switch (color_mode) { ++ case OMAP_DSS_COLOR_RGB16: ++ case OMAP_DSS_COLOR_ARGB16: ++ ps = 2; ++ break; ++ ++ case OMAP_DSS_COLOR_RGB24P: ++ ps = 3; ++ break; ++ ++ case OMAP_DSS_COLOR_RGB24U: ++ case OMAP_DSS_COLOR_ARGB32: ++ case OMAP_DSS_COLOR_RGBA32: ++ case OMAP_DSS_COLOR_RGBX32: ++ case OMAP_DSS_COLOR_YUV2: ++ case OMAP_DSS_COLOR_UYVY: ++ ps = 4; ++ break; ++ ++ default: ++ BUG(); ++ return; ++ } ++ ++ DSSDBG("calc_rot(%d): scrw %d, %dx%d\n", rotation, screen_width, ++ width, height); ++ ++ /* ++ * field 0 = even field = bottom field ++ * field 1 = odd field = top field ++ */ ++ switch (rotation + mirror * 4) { ++ case 0: ++ case 2: ++ /* ++ * If the pixel format is YUV or UYVY divide the width ++ * of the image by 2 for 0 and 180 degree rotation. ++ */ ++ if (color_mode == OMAP_DSS_COLOR_YUV2 || ++ color_mode == OMAP_DSS_COLOR_UYVY) ++ width = width >> 1; ++ case 1: ++ case 3: ++ *offset1 = 0; ++ if (field_offset) ++ *offset0 = field_offset * screen_width * ps; ++ else ++ *offset0 = 0; ++ ++ *row_inc = pixinc(1 + (screen_width - width) + ++ (fieldmode ? screen_width : 0), ++ ps); ++ *pix_inc = pixinc(1, ps); ++ break; ++ ++ case 4: ++ case 6: ++ /* If the pixel format is YUV or UYVY divide the width ++ * of the image by 2 for 0 degree and 180 degree ++ */ ++ if (color_mode == OMAP_DSS_COLOR_YUV2 || ++ color_mode == OMAP_DSS_COLOR_UYVY) ++ width = width >> 1; ++ case 5: ++ case 7: ++ *offset1 = 0; ++ if (field_offset) ++ *offset0 = field_offset * screen_width * ps; ++ else ++ *offset0 = 0; ++ *row_inc = pixinc(1 - (screen_width + width) - ++ (fieldmode ? screen_width : 0), ++ ps); ++ *pix_inc = pixinc(1, ps); ++ break; ++ ++ default: ++ BUG(); ++ } ++} ++ ++static void calc_dma_rotation_offset(u8 rotation, bool mirror, ++ u16 screen_width, ++ u16 width, u16 height, ++ enum omap_color_mode color_mode, bool fieldmode, ++ unsigned int field_offset, ++ unsigned *offset0, unsigned *offset1, ++ s32 *row_inc, s32 *pix_inc) ++{ ++ u8 ps; ++ u16 fbw, fbh; ++ ++ switch (color_mode) { ++ case OMAP_DSS_COLOR_RGB16: ++ case OMAP_DSS_COLOR_ARGB16: ++ ps = 2; ++ break; ++ ++ case OMAP_DSS_COLOR_RGB24P: ++ ps = 3; ++ break; ++ ++ case OMAP_DSS_COLOR_RGB24U: ++ case OMAP_DSS_COLOR_ARGB32: ++ case OMAP_DSS_COLOR_RGBA32: ++ case OMAP_DSS_COLOR_RGBX32: ++ ps = 4; ++ break; ++ ++ case OMAP_DSS_COLOR_YUV2: ++ case OMAP_DSS_COLOR_UYVY: ++ ps = 2; ++ break; ++ default: ++ BUG(); ++ return; ++ } ++ ++ DSSDBG("calc_rot(%d): scrw %d, %dx%d\n", rotation, screen_width, ++ width, height); ++ ++ /* width & height are overlay sizes, convert to fb sizes */ ++ ++ if (rotation == 0 || rotation == 2) { ++ fbw = width; ++ fbh = height; ++ } else { ++ fbw = height; ++ fbh = width; ++ } ++ ++ /* ++ * field 0 = even field = bottom field ++ * field 1 = odd field = top field ++ */ ++ switch (rotation + mirror * 4) { ++ case 0: ++ *offset1 = 0; ++ if (field_offset) ++ *offset0 = *offset1 + field_offset * screen_width * ps; ++ else ++ *offset0 = *offset1; ++ *row_inc = pixinc(1 + (screen_width - fbw) + ++ (fieldmode ? screen_width : 0), ++ ps); ++ *pix_inc = pixinc(1, ps); ++ break; ++ case 1: ++ *offset1 = screen_width * (fbh - 1) * ps; ++ if (field_offset) ++ *offset0 = *offset1 + field_offset * ps; ++ else ++ *offset0 = *offset1; ++ *row_inc = pixinc(screen_width * (fbh - 1) + 1 + ++ (fieldmode ? 1 : 0), ps); ++ *pix_inc = pixinc(-screen_width, ps); ++ break; ++ case 2: ++ *offset1 = (screen_width * (fbh - 1) + fbw - 1) * ps; ++ if (field_offset) ++ *offset0 = *offset1 - field_offset * screen_width * ps; ++ else ++ *offset0 = *offset1; ++ *row_inc = pixinc(-1 - ++ (screen_width - fbw) - ++ (fieldmode ? screen_width : 0), ++ ps); ++ *pix_inc = pixinc(-1, ps); ++ break; ++ case 3: ++ *offset1 = (fbw - 1) * ps; ++ if (field_offset) ++ *offset0 = *offset1 - field_offset * ps; ++ else ++ *offset0 = *offset1; ++ *row_inc = pixinc(-screen_width * (fbh - 1) - 1 - ++ (fieldmode ? 1 : 0), ps); ++ *pix_inc = pixinc(screen_width, ps); ++ break; ++ ++ /* mirroring */ ++ case 0 + 4: ++ *offset1 = (fbw - 1) * ps; ++ if (field_offset) ++ *offset0 = *offset1 + field_offset * screen_width * ps; ++ else ++ *offset0 = *offset1; ++ *row_inc = pixinc(screen_width * 2 - 1 + ++ (fieldmode ? screen_width : 0), ++ ps); ++ *pix_inc = pixinc(-1, ps); ++ break; ++ ++ case 1 + 4: ++ *offset1 = 0; ++ if (field_offset) ++ *offset0 = *offset1 + field_offset * ps; ++ else ++ *offset0 = *offset1; ++ *row_inc = pixinc(-screen_width * (fbh - 1) + 1 + ++ (fieldmode ? 1 : 0), ++ ps); ++ *pix_inc = pixinc(screen_width, ps); ++ break; ++ ++ case 2 + 4: ++ *offset1 = screen_width * (fbh - 1) * ps; ++ if (field_offset) ++ *offset0 = *offset1 - field_offset * screen_width * ps; ++ else ++ *offset0 = *offset1; ++ *row_inc = pixinc(1 - screen_width * 2 - ++ (fieldmode ? screen_width : 0), ++ ps); ++ *pix_inc = pixinc(1, ps); ++ break; ++ ++ case 3 + 4: ++ *offset1 = (screen_width * (fbh - 1) + fbw - 1) * ps; ++ if (field_offset) ++ *offset0 = *offset1 - field_offset * ps; ++ else ++ *offset0 = *offset1; ++ *row_inc = pixinc(screen_width * (fbh - 1) - 1 - ++ (fieldmode ? 1 : 0), ++ ps); ++ *pix_inc = pixinc(-screen_width, ps); ++ break; ++ ++ default: ++ BUG(); ++ } ++} ++ ++static unsigned long calc_fclk_five_taps(u16 width, u16 height, ++ u16 out_width, u16 out_height, enum omap_color_mode color_mode) ++{ ++ u32 fclk = 0; ++ /* FIXME venc pclk? */ ++ u64 tmp, pclk = dispc_pclk_rate(); ++ ++ if (height > out_height) { ++ /* FIXME get real display PPL */ ++ unsigned int ppl = 800; ++ ++ tmp = pclk * height * out_width; ++ do_div(tmp, 2 * out_height * ppl); ++ fclk = tmp; ++ ++ if (height > 2 * out_height && ppl != out_width) { ++ tmp = pclk * (height - 2 * out_height) * out_width; ++ do_div(tmp, 2 * out_height * (ppl - out_width)); ++ fclk = max(fclk, (u32) tmp); ++ } ++ } ++ ++ if (width > out_width) { ++ tmp = pclk * width; ++ do_div(tmp, out_width); ++ fclk = max(fclk, (u32) tmp); ++ ++ if (color_mode == OMAP_DSS_COLOR_RGB24U) ++ fclk <<= 1; ++ } ++ ++ return fclk; ++} ++ ++static unsigned long calc_fclk(u16 width, u16 height, ++ u16 out_width, u16 out_height) ++{ ++ unsigned int hf, vf; ++ ++ /* ++ * FIXME how to determine the 'A' factor ++ * for the no downscaling case ? ++ */ ++ ++ if (width > 3 * out_width) ++ hf = 4; ++ else if (width > 2 * out_width) ++ hf = 3; ++ else if (width > out_width) ++ hf = 2; ++ else ++ hf = 1; ++ ++ if (height > out_height) ++ vf = 2; ++ else ++ vf = 1; ++ ++ /* FIXME venc pclk? */ ++ return dispc_pclk_rate() * vf * hf; ++} ++ ++void dispc_set_channel_out(enum omap_plane plane, enum omap_channel channel_out) ++{ ++ enable_clocks(1); ++ _dispc_set_channel_out(plane, channel_out); ++ enable_clocks(0); ++} ++ ++static int _dispc_setup_plane(enum omap_plane plane, ++ u32 paddr, u16 screen_width, ++ u16 pos_x, u16 pos_y, ++ u16 width, u16 height, ++ u16 out_width, u16 out_height, ++ enum omap_color_mode color_mode, ++ bool ilace, ++ enum omap_dss_rotation_type rotation_type, ++ u8 rotation, int mirror, ++ u8 global_alpha) ++{ ++ const int maxdownscale = cpu_is_omap34xx() ? 4 : 2; ++ bool five_taps = 0; ++ bool fieldmode = 0; ++ int cconv = 0; ++ unsigned offset0, offset1; ++ s32 row_inc; ++ s32 pix_inc; ++ u16 frame_height = height; ++ unsigned int field_offset = 0; ++ ++ if (paddr == 0) ++ return -EINVAL; ++ ++ if (ilace && height == out_height) ++ fieldmode = 1; ++ ++ if (ilace) { ++ if (fieldmode) ++ height /= 2; ++ pos_y /= 2; ++ out_height /= 2; ++ ++ DSSDBG("adjusting for ilace: height %d, pos_y %d, " ++ "out_height %d\n", ++ height, pos_y, out_height); ++ } ++ ++ if (plane == OMAP_DSS_GFX) { ++ if (width != out_width || height != out_height) ++ return -EINVAL; ++ ++ switch (color_mode) { ++ case OMAP_DSS_COLOR_ARGB16: ++ case OMAP_DSS_COLOR_RGB16: ++ case OMAP_DSS_COLOR_RGB24P: ++ case OMAP_DSS_COLOR_RGB24U: ++ case OMAP_DSS_COLOR_ARGB32: ++ case OMAP_DSS_COLOR_RGBA32: ++ case OMAP_DSS_COLOR_RGBX32: ++ break; ++ ++ default: ++ return -EINVAL; ++ } ++ } else { ++ /* video plane */ ++ ++ unsigned long fclk = 0; ++ ++ if (out_width < width / maxdownscale || ++ out_width > width * 8) ++ return -EINVAL; ++ ++ if (out_height < height / maxdownscale || ++ out_height > height * 8) ++ return -EINVAL; ++ ++ switch (color_mode) { ++ case OMAP_DSS_COLOR_RGB16: ++ case OMAP_DSS_COLOR_RGB24P: ++ case OMAP_DSS_COLOR_RGB24U: ++ case OMAP_DSS_COLOR_RGBX32: ++ break; ++ ++ case OMAP_DSS_COLOR_ARGB16: ++ case OMAP_DSS_COLOR_ARGB32: ++ case OMAP_DSS_COLOR_RGBA32: ++ if (plane == OMAP_DSS_VIDEO1) ++ return -EINVAL; ++ break; ++ ++ case OMAP_DSS_COLOR_YUV2: ++ case OMAP_DSS_COLOR_UYVY: ++ cconv = 1; ++ break; ++ ++ default: ++ return -EINVAL; ++ } ++ ++ /* Must use 5-tap filter? */ ++ five_taps = height > out_height * 2; ++ ++ if (!five_taps) { ++ fclk = calc_fclk(width, height, ++ out_width, out_height); ++ ++ /* Try 5-tap filter if 3-tap fclk is too high */ ++ if (cpu_is_omap34xx() && height > out_height && ++ fclk > dispc_fclk_rate()) ++ five_taps = true; ++ } ++ ++ if (width > (2048 >> five_taps)) ++ return -EINVAL; ++ ++ if (five_taps) ++ fclk = calc_fclk_five_taps(width, height, ++ out_width, out_height, color_mode); ++ ++ DSSDBG("required fclk rate = %lu Hz\n", fclk); ++ DSSDBG("current fclk rate = %lu Hz\n", dispc_fclk_rate()); ++ ++ if (fclk > dispc_fclk_rate()) { ++ DSSERR("failed to set up scaling, " ++ "required fclk rate = %lu Hz, " ++ "current fclk rate = %lu Hz\n", ++ fclk, dispc_fclk_rate()); ++ return -EINVAL; ++ } ++ } ++ ++ if (ilace && !fieldmode) { ++ /* ++ * when downscaling the bottom field may have to start several ++ * source lines below the top field. Unfortunately ACCUI ++ * registers will only hold the fractional part of the offset ++ * so the integer part must be added to the base address of the ++ * bottom field. ++ */ ++ if (!height || height == out_height) ++ field_offset = 0; ++ else ++ field_offset = height / out_height / 2; ++ } ++ ++ /* Fields are independent but interleaved in memory. */ ++ if (fieldmode) ++ field_offset = 1; ++ ++ if (rotation_type == OMAP_DSS_ROT_DMA) ++ calc_dma_rotation_offset(rotation, mirror, ++ screen_width, width, frame_height, color_mode, ++ fieldmode, field_offset, ++ &offset0, &offset1, &row_inc, &pix_inc); ++ else ++ calc_vrfb_rotation_offset(rotation, mirror, ++ screen_width, width, frame_height, color_mode, ++ fieldmode, field_offset, ++ &offset0, &offset1, &row_inc, &pix_inc); ++ ++ DSSDBG("offset0 %u, offset1 %u, row_inc %d, pix_inc %d\n", ++ offset0, offset1, row_inc, pix_inc); ++ ++ _dispc_set_color_mode(plane, color_mode); ++ ++ _dispc_set_plane_ba0(plane, paddr + offset0); ++ _dispc_set_plane_ba1(plane, paddr + offset1); ++ ++ _dispc_set_row_inc(plane, row_inc); ++ _dispc_set_pix_inc(plane, pix_inc); ++ ++ DSSDBG("%d,%d %dx%d -> %dx%d\n", pos_x, pos_y, width, height, ++ out_width, out_height); ++ ++ _dispc_set_plane_pos(plane, pos_x, pos_y); ++ ++ _dispc_set_pic_size(plane, width, height); ++ ++ if (plane != OMAP_DSS_GFX) { ++ _dispc_set_scaling(plane, width, height, ++ out_width, out_height, ++ ilace, five_taps, fieldmode); ++ _dispc_set_vid_size(plane, out_width, out_height); ++ _dispc_set_vid_color_conv(plane, cconv); ++ } ++ ++ _dispc_set_rotation_attrs(plane, rotation, mirror, color_mode); ++ ++ if (plane != OMAP_DSS_VIDEO1) ++ _dispc_setup_global_alpha(plane, global_alpha); ++ ++ return 0; ++} ++ ++static void _dispc_enable_plane(enum omap_plane plane, bool enable) ++{ ++ REG_FLD_MOD(dispc_reg_att[plane], enable ? 1 : 0, 0, 0); ++} ++ ++static void dispc_disable_isr(void *data, u32 mask) ++{ ++ struct completion *compl = data; ++ complete(compl); ++} ++ ++static void _enable_lcd_out(bool enable) ++{ ++ REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 0, 0); ++} ++ ++void dispc_enable_lcd_out(bool enable) ++{ ++ struct completion frame_done_completion; ++ bool is_on; ++ int r; ++ ++ enable_clocks(1); ++ ++ /* When we disable LCD output, we need to wait until frame is done. ++ * Otherwise the DSS is still working, and turning off the clocks ++ * prevents DSS from going to OFF mode */ ++ is_on = REG_GET(DISPC_CONTROL, 0, 0); ++ ++ if (!enable && is_on) { ++ init_completion(&frame_done_completion); ++ ++ r = omap_dispc_register_isr(dispc_disable_isr, ++ &frame_done_completion, ++ DISPC_IRQ_FRAMEDONE); ++ ++ if (r) ++ DSSERR("failed to register FRAMEDONE isr\n"); ++ } ++ ++ _enable_lcd_out(enable); ++ ++ if (!enable && is_on) { ++ if (!wait_for_completion_timeout(&frame_done_completion, ++ msecs_to_jiffies(100))) ++ DSSERR("timeout waiting for FRAME DONE\n"); ++ ++ r = omap_dispc_unregister_isr(dispc_disable_isr, ++ &frame_done_completion, ++ DISPC_IRQ_FRAMEDONE); ++ ++ if (r) ++ DSSERR("failed to unregister FRAMEDONE isr\n"); ++ } ++ ++ enable_clocks(0); ++} ++ ++static void _enable_digit_out(bool enable) ++{ ++ REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 1, 1); ++} ++ ++void dispc_enable_digit_out(bool enable) ++{ ++ struct completion frame_done_completion; ++ int r; ++ ++ enable_clocks(1); ++ ++ if (REG_GET(DISPC_CONTROL, 1, 1) == enable) { ++ enable_clocks(0); ++ return; ++ } ++ ++ if (enable) { ++ unsigned long flags; ++ /* When we enable digit output, we'll get an extra digit ++ * sync lost interrupt, that we need to ignore */ ++ spin_lock_irqsave(&dispc.irq_lock, flags); ++ dispc.irq_error_mask &= ~DISPC_IRQ_SYNC_LOST_DIGIT; ++ _omap_dispc_set_irqs(); ++ spin_unlock_irqrestore(&dispc.irq_lock, flags); ++ } ++ ++ /* When we disable digit output, we need to wait until fields are done. ++ * Otherwise the DSS is still working, and turning off the clocks ++ * prevents DSS from going to OFF mode. And when enabling, we need to ++ * wait for the extra sync losts */ ++ init_completion(&frame_done_completion); ++ ++ r = omap_dispc_register_isr(dispc_disable_isr, &frame_done_completion, ++ DISPC_IRQ_EVSYNC_EVEN | DISPC_IRQ_EVSYNC_ODD); ++ if (r) ++ DSSERR("failed to register EVSYNC isr\n"); ++ ++ _enable_digit_out(enable); ++ ++ /* XXX I understand from TRM that we should only wait for the ++ * current field to complete. But it seems we have to wait ++ * for both fields */ ++ if (!wait_for_completion_timeout(&frame_done_completion, ++ msecs_to_jiffies(100))) ++ DSSERR("timeout waiting for EVSYNC\n"); ++ ++ if (!wait_for_completion_timeout(&frame_done_completion, ++ msecs_to_jiffies(100))) ++ DSSERR("timeout waiting for EVSYNC\n"); ++ ++ r = omap_dispc_unregister_isr(dispc_disable_isr, ++ &frame_done_completion, ++ DISPC_IRQ_EVSYNC_EVEN | DISPC_IRQ_EVSYNC_ODD); ++ if (r) ++ DSSERR("failed to unregister EVSYNC isr\n"); ++ ++ if (enable) { ++ unsigned long flags; ++ spin_lock_irqsave(&dispc.irq_lock, flags); ++ dispc.irq_error_mask = DISPC_IRQ_MASK_ERROR; ++ dispc_write_reg(DISPC_IRQSTATUS, DISPC_IRQ_SYNC_LOST_DIGIT); ++ _omap_dispc_set_irqs(); ++ spin_unlock_irqrestore(&dispc.irq_lock, flags); ++ } ++ ++ enable_clocks(0); ++} ++ ++void dispc_lcd_enable_signal_polarity(bool act_high) ++{ ++ enable_clocks(1); ++ REG_FLD_MOD(DISPC_CONTROL, act_high ? 1 : 0, 29, 29); ++ enable_clocks(0); ++} ++ ++void dispc_lcd_enable_signal(bool enable) ++{ ++ enable_clocks(1); ++ REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 28, 28); ++ enable_clocks(0); ++} ++ ++void dispc_pck_free_enable(bool enable) ++{ ++ enable_clocks(1); ++ REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 27, 27); ++ enable_clocks(0); ++} ++ ++void dispc_enable_fifohandcheck(bool enable) ++{ ++ enable_clocks(1); ++ REG_FLD_MOD(DISPC_CONFIG, enable ? 1 : 0, 16, 16); ++ enable_clocks(0); ++} ++ ++ ++void dispc_set_lcd_display_type(enum omap_lcd_display_type type) ++{ ++ int mode; ++ ++ switch (type) { ++ case OMAP_DSS_LCD_DISPLAY_STN: ++ mode = 0; ++ break; ++ ++ case OMAP_DSS_LCD_DISPLAY_TFT: ++ mode = 1; ++ break; ++ ++ default: ++ BUG(); ++ return; ++ } ++ ++ enable_clocks(1); ++ REG_FLD_MOD(DISPC_CONTROL, mode, 3, 3); ++ enable_clocks(0); ++} ++ ++void dispc_set_loadmode(enum omap_dss_load_mode mode) ++{ ++ enable_clocks(1); ++ REG_FLD_MOD(DISPC_CONFIG, mode, 2, 1); ++ enable_clocks(0); ++} ++ ++ ++void dispc_set_default_color(enum omap_channel channel, u32 color) ++{ ++ const struct dispc_reg def_reg[] = { DISPC_DEFAULT_COLOR0, ++ DISPC_DEFAULT_COLOR1 }; ++ ++ enable_clocks(1); ++ dispc_write_reg(def_reg[channel], color); ++ enable_clocks(0); ++} ++ ++u32 dispc_get_default_color(enum omap_channel channel) ++{ ++ const struct dispc_reg def_reg[] = { DISPC_DEFAULT_COLOR0, ++ DISPC_DEFAULT_COLOR1 }; ++ u32 l; ++ ++ BUG_ON(channel != OMAP_DSS_CHANNEL_DIGIT && ++ channel != OMAP_DSS_CHANNEL_LCD); ++ ++ enable_clocks(1); ++ l = dispc_read_reg(def_reg[channel]); ++ enable_clocks(0); ++ ++ return l; ++} ++ ++void dispc_set_trans_key(enum omap_channel ch, ++ enum omap_dss_trans_key_type type, ++ u32 trans_key) ++{ ++ const struct dispc_reg tr_reg[] = { ++ DISPC_TRANS_COLOR0, DISPC_TRANS_COLOR1 }; ++ ++ enable_clocks(1); ++ if (ch == OMAP_DSS_CHANNEL_LCD) ++ REG_FLD_MOD(DISPC_CONFIG, type, 11, 11); ++ else /* OMAP_DSS_CHANNEL_DIGIT */ ++ REG_FLD_MOD(DISPC_CONFIG, type, 13, 13); ++ ++ dispc_write_reg(tr_reg[ch], trans_key); ++ enable_clocks(0); ++} ++ ++void dispc_get_trans_key(enum omap_channel ch, ++ enum omap_dss_trans_key_type *type, ++ u32 *trans_key) ++{ ++ const struct dispc_reg tr_reg[] = { ++ DISPC_TRANS_COLOR0, DISPC_TRANS_COLOR1 }; ++ ++ enable_clocks(1); ++ if (type) { ++ if (ch == OMAP_DSS_CHANNEL_LCD) ++ *type = REG_GET(DISPC_CONFIG, 11, 11); ++ else if (ch == OMAP_DSS_CHANNEL_DIGIT) ++ *type = REG_GET(DISPC_CONFIG, 13, 13); ++ else ++ BUG(); ++ } ++ ++ if (trans_key) ++ *trans_key = dispc_read_reg(tr_reg[ch]); ++ enable_clocks(0); ++} ++ ++void dispc_enable_trans_key(enum omap_channel ch, bool enable) ++{ ++ enable_clocks(1); ++ if (ch == OMAP_DSS_CHANNEL_LCD) ++ REG_FLD_MOD(DISPC_CONFIG, enable, 10, 10); ++ else /* OMAP_DSS_CHANNEL_DIGIT */ ++ REG_FLD_MOD(DISPC_CONFIG, enable, 12, 12); ++ enable_clocks(0); ++} ++void dispc_enable_alpha_blending(enum omap_channel ch, bool enable) ++{ ++ enable_clocks(1); ++ if (ch == OMAP_DSS_CHANNEL_LCD) ++ REG_FLD_MOD(DISPC_CONFIG, enable, 18, 18); ++ else /* OMAP_DSS_CHANNEL_DIGIT */ ++ REG_FLD_MOD(DISPC_CONFIG, enable, 19, 19); ++ enable_clocks(0); ++} ++bool dispc_alpha_blending_enabled(enum omap_channel ch) ++{ ++ bool enabled; ++ ++ enable_clocks(1); ++ if (ch == OMAP_DSS_CHANNEL_LCD) ++ enabled = REG_GET(DISPC_CONFIG, 18, 18); ++ else if (ch == OMAP_DSS_CHANNEL_DIGIT) ++ enabled = REG_GET(DISPC_CONFIG, 18, 18); ++ else ++ BUG(); ++ enable_clocks(0); ++ ++ return enabled; ++ ++} ++ ++ ++bool dispc_trans_key_enabled(enum omap_channel ch) ++{ ++ bool enabled; ++ ++ enable_clocks(1); ++ if (ch == OMAP_DSS_CHANNEL_LCD) ++ enabled = REG_GET(DISPC_CONFIG, 10, 10); ++ else if (ch == OMAP_DSS_CHANNEL_DIGIT) ++ enabled = REG_GET(DISPC_CONFIG, 12, 12); ++ else ++ BUG(); ++ enable_clocks(0); ++ ++ return enabled; ++} ++ ++ ++void dispc_set_tft_data_lines(u8 data_lines) ++{ ++ int code; ++ ++ switch (data_lines) { ++ case 12: ++ code = 0; ++ break; ++ case 16: ++ code = 1; ++ break; ++ case 18: ++ code = 2; ++ break; ++ case 24: ++ code = 3; ++ break; ++ default: ++ BUG(); ++ return; ++ } ++ ++ enable_clocks(1); ++ REG_FLD_MOD(DISPC_CONTROL, code, 9, 8); ++ enable_clocks(0); ++} ++ ++void dispc_set_parallel_interface_mode(enum omap_parallel_interface_mode mode) ++{ ++ u32 l; ++ int stallmode; ++ int gpout0 = 1; ++ int gpout1; ++ ++ switch (mode) { ++ case OMAP_DSS_PARALLELMODE_BYPASS: ++ stallmode = 0; ++ gpout1 = 1; ++ break; ++ ++ case OMAP_DSS_PARALLELMODE_RFBI: ++ stallmode = 1; ++ gpout1 = 0; ++ break; ++ ++ case OMAP_DSS_PARALLELMODE_DSI: ++ stallmode = 1; ++ gpout1 = 1; ++ break; ++ ++ default: ++ BUG(); ++ return; ++ } ++ ++ enable_clocks(1); ++ ++ l = dispc_read_reg(DISPC_CONTROL); ++ ++ l = FLD_MOD(l, stallmode, 11, 11); ++ l = FLD_MOD(l, gpout0, 15, 15); ++ l = FLD_MOD(l, gpout1, 16, 16); ++ ++ dispc_write_reg(DISPC_CONTROL, l); ++ ++ enable_clocks(0); ++} ++ ++static bool _dispc_lcd_timings_ok(int hsw, int hfp, int hbp, ++ int vsw, int vfp, int vbp) ++{ ++ if (cpu_is_omap24xx() || omap_rev() < OMAP3430_REV_ES3_0) { ++ if (hsw < 1 || hsw > 64 || ++ hfp < 1 || hfp > 256 || ++ hbp < 1 || hbp > 256 || ++ vsw < 1 || vsw > 64 || ++ vfp < 0 || vfp > 255 || ++ vbp < 0 || vbp > 255) ++ return false; ++ } else { ++ if (hsw < 1 || hsw > 256 || ++ hfp < 1 || hfp > 4096 || ++ hbp < 1 || hbp > 4096 || ++ vsw < 1 || vsw > 256 || ++ vfp < 0 || vfp > 4095 || ++ vbp < 0 || vbp > 4095) ++ return false; ++ } ++ ++ return true; ++} ++ ++bool dispc_lcd_timings_ok(struct omap_video_timings *timings) ++{ ++ return _dispc_lcd_timings_ok(timings->hsw, timings->hfp, ++ timings->hbp, timings->vsw, ++ timings->vfp, timings->vbp); ++} ++ ++static void _dispc_set_lcd_timings(int hsw, int hfp, int hbp, ++ int vsw, int vfp, int vbp) ++{ ++ u32 timing_h, timing_v; ++ ++ if (cpu_is_omap24xx() || omap_rev() < OMAP3430_REV_ES3_0) { ++ timing_h = FLD_VAL(hsw-1, 5, 0) | FLD_VAL(hfp-1, 15, 8) | ++ FLD_VAL(hbp-1, 27, 20); ++ ++ timing_v = FLD_VAL(vsw-1, 5, 0) | FLD_VAL(vfp, 15, 8) | ++ FLD_VAL(vbp, 27, 20); ++ } else { ++ timing_h = FLD_VAL(hsw-1, 7, 0) | FLD_VAL(hfp-1, 19, 8) | ++ FLD_VAL(hbp-1, 31, 20); ++ ++ timing_v = FLD_VAL(vsw-1, 7, 0) | FLD_VAL(vfp, 19, 8) | ++ FLD_VAL(vbp, 31, 20); ++ } ++ ++ enable_clocks(1); ++ dispc_write_reg(DISPC_TIMING_H, timing_h); ++ dispc_write_reg(DISPC_TIMING_V, timing_v); ++ enable_clocks(0); ++} ++ ++/* change name to mode? */ ++void dispc_set_lcd_timings(struct omap_video_timings *timings) ++{ ++ unsigned xtot, ytot; ++ unsigned long ht, vt; ++ ++ if (!_dispc_lcd_timings_ok(timings->hsw, timings->hfp, ++ timings->hbp, timings->vsw, ++ timings->vfp, timings->vbp)) ++ BUG(); ++ ++ _dispc_set_lcd_timings(timings->hsw, timings->hfp, timings->hbp, ++ timings->vsw, timings->vfp, timings->vbp); ++ ++ dispc_set_lcd_size(timings->x_res, timings->y_res); ++ ++ xtot = timings->x_res + timings->hfp + timings->hsw + timings->hbp; ++ ytot = timings->y_res + timings->vfp + timings->vsw + timings->vbp; ++ ++ ht = (timings->pixel_clock * 1000) / xtot; ++ vt = (timings->pixel_clock * 1000) / xtot / ytot; ++ ++ DSSDBG("xres %u yres %u\n", timings->x_res, timings->y_res); ++ DSSDBG("pck %u\n", timings->pixel_clock); ++ DSSDBG("hsw %d hfp %d hbp %d vsw %d vfp %d vbp %d\n", ++ timings->hsw, timings->hfp, timings->hbp, ++ timings->vsw, timings->vfp, timings->vbp); ++ ++ DSSDBG("hsync %luHz, vsync %luHz\n", ht, vt); ++} ++ ++void dispc_set_lcd_divisor(u16 lck_div, u16 pck_div) ++{ ++ BUG_ON(lck_div < 1); ++ BUG_ON(pck_div < 2); ++ ++ enable_clocks(1); ++ dispc_write_reg(DISPC_DIVISOR, ++ FLD_VAL(lck_div, 23, 16) | FLD_VAL(pck_div, 7, 0)); ++ enable_clocks(0); ++} ++ ++static void dispc_get_lcd_divisor(int *lck_div, int *pck_div) ++{ ++ u32 l; ++ l = dispc_read_reg(DISPC_DIVISOR); ++ *lck_div = FLD_GET(l, 23, 16); ++ *pck_div = FLD_GET(l, 7, 0); ++} ++ ++unsigned long dispc_fclk_rate(void) ++{ ++ unsigned long r = 0; ++ ++ if (dss_get_dispc_clk_source() == 0) ++ r = dss_clk_get_rate(DSS_CLK_FCK1); ++ else ++#ifdef CONFIG_OMAP2_DSS_DSI ++ r = dsi_get_dsi1_pll_rate(); ++#else ++ BUG(); ++#endif ++ return r; ++} ++ ++unsigned long dispc_lclk_rate(void) ++{ ++ int lcd; ++ unsigned long r; ++ u32 l; ++ ++ l = dispc_read_reg(DISPC_DIVISOR); ++ ++ lcd = FLD_GET(l, 23, 16); ++ ++ r = dispc_fclk_rate(); ++ ++ return r / lcd; ++} ++ ++unsigned long dispc_pclk_rate(void) ++{ ++ int lcd, pcd; ++ unsigned long r; ++ u32 l; ++ ++ l = dispc_read_reg(DISPC_DIVISOR); ++ ++ lcd = FLD_GET(l, 23, 16); ++ pcd = FLD_GET(l, 7, 0); ++ ++ r = dispc_fclk_rate(); ++ ++ return r / lcd / pcd; ++} ++ ++void dispc_dump_clocks(struct seq_file *s) ++{ ++ int lcd, pcd; ++ ++ enable_clocks(1); ++ ++ dispc_get_lcd_divisor(&lcd, &pcd); ++ ++ seq_printf(s, "- dispc -\n"); ++ ++ seq_printf(s, "dispc fclk source = %s\n", ++ dss_get_dispc_clk_source() == 0 ? ++ "dss1_alwon_fclk" : "dsi1_pll_fclk"); ++ ++ seq_printf(s, "pixel clk = %lu / %d / %d = %lu\n", ++ dispc_fclk_rate(), ++ lcd, pcd, ++ dispc_pclk_rate()); ++ ++ enable_clocks(0); ++} ++ ++void dispc_dump_regs(struct seq_file *s) ++{ ++#define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, dispc_read_reg(r)) ++ ++ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); ++ ++ DUMPREG(DISPC_REVISION); ++ DUMPREG(DISPC_SYSCONFIG); ++ DUMPREG(DISPC_SYSSTATUS); ++ DUMPREG(DISPC_IRQSTATUS); ++ DUMPREG(DISPC_IRQENABLE); ++ DUMPREG(DISPC_CONTROL); ++ DUMPREG(DISPC_CONFIG); ++ DUMPREG(DISPC_CAPABLE); ++ DUMPREG(DISPC_DEFAULT_COLOR0); ++ DUMPREG(DISPC_DEFAULT_COLOR1); ++ DUMPREG(DISPC_TRANS_COLOR0); ++ DUMPREG(DISPC_TRANS_COLOR1); ++ DUMPREG(DISPC_LINE_STATUS); ++ DUMPREG(DISPC_LINE_NUMBER); ++ DUMPREG(DISPC_TIMING_H); ++ DUMPREG(DISPC_TIMING_V); ++ DUMPREG(DISPC_POL_FREQ); ++ DUMPREG(DISPC_DIVISOR); ++ DUMPREG(DISPC_GLOBAL_ALPHA); ++ DUMPREG(DISPC_SIZE_DIG); ++ DUMPREG(DISPC_SIZE_LCD); ++ ++ DUMPREG(DISPC_GFX_BA0); ++ DUMPREG(DISPC_GFX_BA1); ++ DUMPREG(DISPC_GFX_POSITION); ++ DUMPREG(DISPC_GFX_SIZE); ++ DUMPREG(DISPC_GFX_ATTRIBUTES); ++ DUMPREG(DISPC_GFX_FIFO_THRESHOLD); ++ DUMPREG(DISPC_GFX_FIFO_SIZE_STATUS); ++ DUMPREG(DISPC_GFX_ROW_INC); ++ DUMPREG(DISPC_GFX_PIXEL_INC); ++ DUMPREG(DISPC_GFX_WINDOW_SKIP); ++ DUMPREG(DISPC_GFX_TABLE_BA); ++ ++ DUMPREG(DISPC_DATA_CYCLE1); ++ DUMPREG(DISPC_DATA_CYCLE2); ++ DUMPREG(DISPC_DATA_CYCLE3); ++ ++ DUMPREG(DISPC_CPR_COEF_R); ++ DUMPREG(DISPC_CPR_COEF_G); ++ DUMPREG(DISPC_CPR_COEF_B); ++ ++ DUMPREG(DISPC_GFX_PRELOAD); ++ ++ DUMPREG(DISPC_VID_BA0(0)); ++ DUMPREG(DISPC_VID_BA1(0)); ++ DUMPREG(DISPC_VID_POSITION(0)); ++ DUMPREG(DISPC_VID_SIZE(0)); ++ DUMPREG(DISPC_VID_ATTRIBUTES(0)); ++ DUMPREG(DISPC_VID_FIFO_THRESHOLD(0)); ++ DUMPREG(DISPC_VID_FIFO_SIZE_STATUS(0)); ++ DUMPREG(DISPC_VID_ROW_INC(0)); ++ DUMPREG(DISPC_VID_PIXEL_INC(0)); ++ DUMPREG(DISPC_VID_FIR(0)); ++ DUMPREG(DISPC_VID_PICTURE_SIZE(0)); ++ DUMPREG(DISPC_VID_ACCU0(0)); ++ DUMPREG(DISPC_VID_ACCU1(0)); ++ ++ DUMPREG(DISPC_VID_BA0(1)); ++ DUMPREG(DISPC_VID_BA1(1)); ++ DUMPREG(DISPC_VID_POSITION(1)); ++ DUMPREG(DISPC_VID_SIZE(1)); ++ DUMPREG(DISPC_VID_ATTRIBUTES(1)); ++ DUMPREG(DISPC_VID_FIFO_THRESHOLD(1)); ++ DUMPREG(DISPC_VID_FIFO_SIZE_STATUS(1)); ++ DUMPREG(DISPC_VID_ROW_INC(1)); ++ DUMPREG(DISPC_VID_PIXEL_INC(1)); ++ DUMPREG(DISPC_VID_FIR(1)); ++ DUMPREG(DISPC_VID_PICTURE_SIZE(1)); ++ DUMPREG(DISPC_VID_ACCU0(1)); ++ DUMPREG(DISPC_VID_ACCU1(1)); ++ ++ DUMPREG(DISPC_VID_FIR_COEF_H(0, 0)); ++ DUMPREG(DISPC_VID_FIR_COEF_H(0, 1)); ++ DUMPREG(DISPC_VID_FIR_COEF_H(0, 2)); ++ DUMPREG(DISPC_VID_FIR_COEF_H(0, 3)); ++ DUMPREG(DISPC_VID_FIR_COEF_H(0, 4)); ++ DUMPREG(DISPC_VID_FIR_COEF_H(0, 5)); ++ DUMPREG(DISPC_VID_FIR_COEF_H(0, 6)); ++ DUMPREG(DISPC_VID_FIR_COEF_H(0, 7)); ++ DUMPREG(DISPC_VID_FIR_COEF_HV(0, 0)); ++ DUMPREG(DISPC_VID_FIR_COEF_HV(0, 1)); ++ DUMPREG(DISPC_VID_FIR_COEF_HV(0, 2)); ++ DUMPREG(DISPC_VID_FIR_COEF_HV(0, 3)); ++ DUMPREG(DISPC_VID_FIR_COEF_HV(0, 4)); ++ DUMPREG(DISPC_VID_FIR_COEF_HV(0, 5)); ++ DUMPREG(DISPC_VID_FIR_COEF_HV(0, 6)); ++ DUMPREG(DISPC_VID_FIR_COEF_HV(0, 7)); ++ DUMPREG(DISPC_VID_CONV_COEF(0, 0)); ++ DUMPREG(DISPC_VID_CONV_COEF(0, 1)); ++ DUMPREG(DISPC_VID_CONV_COEF(0, 2)); ++ DUMPREG(DISPC_VID_CONV_COEF(0, 3)); ++ DUMPREG(DISPC_VID_CONV_COEF(0, 4)); ++ DUMPREG(DISPC_VID_FIR_COEF_V(0, 0)); ++ DUMPREG(DISPC_VID_FIR_COEF_V(0, 1)); ++ DUMPREG(DISPC_VID_FIR_COEF_V(0, 2)); ++ DUMPREG(DISPC_VID_FIR_COEF_V(0, 3)); ++ DUMPREG(DISPC_VID_FIR_COEF_V(0, 4)); ++ DUMPREG(DISPC_VID_FIR_COEF_V(0, 5)); ++ DUMPREG(DISPC_VID_FIR_COEF_V(0, 6)); ++ DUMPREG(DISPC_VID_FIR_COEF_V(0, 7)); ++ ++ DUMPREG(DISPC_VID_FIR_COEF_H(1, 0)); ++ DUMPREG(DISPC_VID_FIR_COEF_H(1, 1)); ++ DUMPREG(DISPC_VID_FIR_COEF_H(1, 2)); ++ DUMPREG(DISPC_VID_FIR_COEF_H(1, 3)); ++ DUMPREG(DISPC_VID_FIR_COEF_H(1, 4)); ++ DUMPREG(DISPC_VID_FIR_COEF_H(1, 5)); ++ DUMPREG(DISPC_VID_FIR_COEF_H(1, 6)); ++ DUMPREG(DISPC_VID_FIR_COEF_H(1, 7)); ++ DUMPREG(DISPC_VID_FIR_COEF_HV(1, 0)); ++ DUMPREG(DISPC_VID_FIR_COEF_HV(1, 1)); ++ DUMPREG(DISPC_VID_FIR_COEF_HV(1, 2)); ++ DUMPREG(DISPC_VID_FIR_COEF_HV(1, 3)); ++ DUMPREG(DISPC_VID_FIR_COEF_HV(1, 4)); ++ DUMPREG(DISPC_VID_FIR_COEF_HV(1, 5)); ++ DUMPREG(DISPC_VID_FIR_COEF_HV(1, 6)); ++ DUMPREG(DISPC_VID_FIR_COEF_HV(1, 7)); ++ DUMPREG(DISPC_VID_CONV_COEF(1, 0)); ++ DUMPREG(DISPC_VID_CONV_COEF(1, 1)); ++ DUMPREG(DISPC_VID_CONV_COEF(1, 2)); ++ DUMPREG(DISPC_VID_CONV_COEF(1, 3)); ++ DUMPREG(DISPC_VID_CONV_COEF(1, 4)); ++ DUMPREG(DISPC_VID_FIR_COEF_V(1, 0)); ++ DUMPREG(DISPC_VID_FIR_COEF_V(1, 1)); ++ DUMPREG(DISPC_VID_FIR_COEF_V(1, 2)); ++ DUMPREG(DISPC_VID_FIR_COEF_V(1, 3)); ++ DUMPREG(DISPC_VID_FIR_COEF_V(1, 4)); ++ DUMPREG(DISPC_VID_FIR_COEF_V(1, 5)); ++ DUMPREG(DISPC_VID_FIR_COEF_V(1, 6)); ++ DUMPREG(DISPC_VID_FIR_COEF_V(1, 7)); ++ ++ DUMPREG(DISPC_VID_PRELOAD(0)); ++ DUMPREG(DISPC_VID_PRELOAD(1)); ++ ++ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); ++#undef DUMPREG ++} ++ ++static void _dispc_set_pol_freq(bool onoff, bool rf, bool ieo, bool ipc, ++ bool ihs, bool ivs, u8 acbi, u8 acb) ++{ ++ u32 l = 0; ++ ++ DSSDBG("onoff %d rf %d ieo %d ipc %d ihs %d ivs %d acbi %d acb %d\n", ++ onoff, rf, ieo, ipc, ihs, ivs, acbi, acb); ++ ++ l |= FLD_VAL(onoff, 17, 17); ++ l |= FLD_VAL(rf, 16, 16); ++ l |= FLD_VAL(ieo, 15, 15); ++ l |= FLD_VAL(ipc, 14, 14); ++ l |= FLD_VAL(ihs, 13, 13); ++ l |= FLD_VAL(ivs, 12, 12); ++ l |= FLD_VAL(acbi, 11, 8); ++ l |= FLD_VAL(acb, 7, 0); ++ ++ enable_clocks(1); ++ dispc_write_reg(DISPC_POL_FREQ, l); ++ enable_clocks(0); ++} ++ ++void dispc_set_pol_freq(enum omap_panel_config config, u8 acbi, u8 acb) ++{ ++ _dispc_set_pol_freq((config & OMAP_DSS_LCD_ONOFF) != 0, ++ (config & OMAP_DSS_LCD_RF) != 0, ++ (config & OMAP_DSS_LCD_IEO) != 0, ++ (config & OMAP_DSS_LCD_IPC) != 0, ++ (config & OMAP_DSS_LCD_IHS) != 0, ++ (config & OMAP_DSS_LCD_IVS) != 0, ++ acbi, acb); ++} ++ ++void find_lck_pck_divs(bool is_tft, unsigned long req_pck, unsigned long fck, ++ u16 *lck_div, u16 *pck_div) ++{ ++ u16 pcd_min = is_tft ? 2 : 3; ++ unsigned long best_pck; ++ u16 best_ld, cur_ld; ++ u16 best_pd, cur_pd; ++ ++ best_pck = 0; ++ best_ld = 0; ++ best_pd = 0; ++ ++ for (cur_ld = 1; cur_ld <= 255; ++cur_ld) { ++ unsigned long lck = fck / cur_ld; ++ ++ for (cur_pd = pcd_min; cur_pd <= 255; ++cur_pd) { ++ unsigned long pck = lck / cur_pd; ++ long old_delta = abs(best_pck - req_pck); ++ long new_delta = abs(pck - req_pck); ++ ++ if (best_pck == 0 || new_delta < old_delta) { ++ best_pck = pck; ++ best_ld = cur_ld; ++ best_pd = cur_pd; ++ ++ if (pck == req_pck) ++ goto found; ++ } ++ ++ if (pck < req_pck) ++ break; ++ } ++ ++ if (lck / pcd_min < req_pck) ++ break; ++ } ++ ++found: ++ *lck_div = best_ld; ++ *pck_div = best_pd; ++} ++ ++int dispc_calc_clock_div(bool is_tft, unsigned long req_pck, ++ struct dispc_clock_info *cinfo) ++{ ++ unsigned long prate; ++ struct dispc_clock_info cur, best; ++ int match = 0; ++ int min_fck_per_pck; ++ unsigned long fck_rate = dss_clk_get_rate(DSS_CLK_FCK1); ++ ++ if (cpu_is_omap34xx()) ++ prate = clk_get_rate(clk_get_parent(dispc.dpll4_m4_ck)); ++ else ++ prate = 0; ++ ++ if (req_pck == dispc.cache_req_pck && ++ ((cpu_is_omap34xx() && prate == dispc.cache_prate) || ++ dispc.cache_cinfo.fck == fck_rate)) { ++ DSSDBG("dispc clock info found from cache.\n"); ++ *cinfo = dispc.cache_cinfo; ++ return 0; ++ } ++ ++ min_fck_per_pck = CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK; ++ ++ if (min_fck_per_pck && ++ req_pck * min_fck_per_pck > DISPC_MAX_FCK) { ++ DSSERR("Requested pixel clock not possible with the current " ++ "OMAP2_DSS_MIN_FCK_PER_PCK setting. Turning " ++ "the constraint off.\n"); ++ min_fck_per_pck = 0; ++ } ++ ++retry: ++ memset(&cur, 0, sizeof(cur)); ++ memset(&best, 0, sizeof(best)); ++ ++ if (cpu_is_omap24xx()) { ++ /* XXX can we change the clock on omap2? */ ++ cur.fck = dss_clk_get_rate(DSS_CLK_FCK1); ++ cur.fck_div = 1; ++ ++ match = 1; ++ ++ find_lck_pck_divs(is_tft, req_pck, cur.fck, ++ &cur.lck_div, &cur.pck_div); ++ ++ cur.lck = cur.fck / cur.lck_div; ++ cur.pck = cur.lck / cur.pck_div; ++ ++ best = cur; ++ ++ goto found; ++ } else if (cpu_is_omap34xx()) { ++ for (cur.fck_div = 16; cur.fck_div > 0; --cur.fck_div) { ++ cur.fck = prate / cur.fck_div * 2; ++ ++ if (cur.fck > DISPC_MAX_FCK) ++ continue; ++ ++ if (min_fck_per_pck && ++ cur.fck < req_pck * min_fck_per_pck) ++ continue; ++ ++ match = 1; ++ ++ find_lck_pck_divs(is_tft, req_pck, cur.fck, ++ &cur.lck_div, &cur.pck_div); ++ ++ cur.lck = cur.fck / cur.lck_div; ++ cur.pck = cur.lck / cur.pck_div; ++ ++ if (abs(cur.pck - req_pck) < abs(best.pck - req_pck)) { ++ best = cur; ++ ++ if (cur.pck == req_pck) ++ goto found; ++ } ++ } ++ } else { ++ BUG(); ++ } ++ ++found: ++ if (!match) { ++ if (min_fck_per_pck) { ++ DSSERR("Could not find suitable clock settings.\n" ++ "Turning FCK/PCK constraint off and" ++ "trying again.\n"); ++ min_fck_per_pck = 0; ++ goto retry; ++ } ++ ++ DSSERR("Could not find suitable clock settings.\n"); ++ ++ return -EINVAL; ++ } ++ ++ if (cinfo) ++ *cinfo = best; ++ ++ dispc.cache_req_pck = req_pck; ++ dispc.cache_prate = prate; ++ dispc.cache_cinfo = best; ++ ++ return 0; ++} ++ ++int dispc_set_clock_div(struct dispc_clock_info *cinfo) ++{ ++ unsigned long prate; ++ int r; ++ ++ if (cpu_is_omap34xx()) { ++ prate = clk_get_rate(clk_get_parent(dispc.dpll4_m4_ck)); ++ DSSDBG("dpll4_m4 = %ld\n", prate); ++ } ++ ++ DSSDBG("fck = %ld (%d)\n", cinfo->fck, cinfo->fck_div); ++ DSSDBG("lck = %ld (%d)\n", cinfo->lck, cinfo->lck_div); ++ DSSDBG("pck = %ld (%d)\n", cinfo->pck, cinfo->pck_div); ++ ++ if (cpu_is_omap34xx()) { ++ r = clk_set_rate(dispc.dpll4_m4_ck, prate / cinfo->fck_div); ++ if (r) ++ return r; ++ } ++ ++ dispc_set_lcd_divisor(cinfo->lck_div, cinfo->pck_div); ++ ++ return 0; ++} ++ ++int dispc_get_clock_div(struct dispc_clock_info *cinfo) ++{ ++ cinfo->fck = dss_clk_get_rate(DSS_CLK_FCK1); ++ ++ if (cpu_is_omap34xx()) { ++ unsigned long prate; ++ prate = clk_get_rate(clk_get_parent(dispc.dpll4_m4_ck)); ++ cinfo->fck_div = prate / (cinfo->fck / 2); ++ } else { ++ cinfo->fck_div = 0; ++ } ++ ++ cinfo->lck_div = REG_GET(DISPC_DIVISOR, 23, 16); ++ cinfo->pck_div = REG_GET(DISPC_DIVISOR, 7, 0); ++ ++ cinfo->lck = cinfo->fck / cinfo->lck_div; ++ cinfo->pck = cinfo->lck / cinfo->pck_div; ++ ++ return 0; ++} ++ ++/* dispc.irq_lock has to be locked by the caller */ ++static void _omap_dispc_set_irqs(void) ++{ ++ u32 mask; ++ u32 old_mask; ++ int i; ++ struct omap_dispc_isr_data *isr_data; ++ ++ mask = dispc.irq_error_mask; ++ ++ for (i = 0; i < DISPC_MAX_NR_ISRS; i++) { ++ isr_data = &dispc.registered_isr[i]; ++ ++ if (isr_data->isr == NULL) ++ continue; ++ ++ mask |= isr_data->mask; ++ } ++ ++ enable_clocks(1); ++ ++ old_mask = dispc_read_reg(DISPC_IRQENABLE); ++ /* clear the irqstatus for newly enabled irqs */ ++ dispc_write_reg(DISPC_IRQSTATUS, (mask ^ old_mask) & mask); ++ ++ dispc_write_reg(DISPC_IRQENABLE, mask); ++ ++ enable_clocks(0); ++} ++ ++int omap_dispc_register_isr(omap_dispc_isr_t isr, void *arg, u32 mask) ++{ ++ int i; ++ int ret; ++ unsigned long flags; ++ struct omap_dispc_isr_data *isr_data; ++ ++ if (isr == NULL) ++ return -EINVAL; ++ ++ spin_lock_irqsave(&dispc.irq_lock, flags); ++ ++ /* check for duplicate entry */ ++ for (i = 0; i < DISPC_MAX_NR_ISRS; i++) { ++ isr_data = &dispc.registered_isr[i]; ++ if (isr_data->isr == isr && isr_data->arg == arg && ++ isr_data->mask == mask) { ++ ret = -EINVAL; ++ goto err; ++ } ++ } ++ ++ isr_data = NULL; ++ ret = -EBUSY; ++ ++ for (i = 0; i < DISPC_MAX_NR_ISRS; i++) { ++ isr_data = &dispc.registered_isr[i]; ++ ++ if (isr_data->isr != NULL) ++ continue; ++ ++ isr_data->isr = isr; ++ isr_data->arg = arg; ++ isr_data->mask = mask; ++ ret = 0; ++ ++ break; ++ } ++ ++ _omap_dispc_set_irqs(); ++ ++ spin_unlock_irqrestore(&dispc.irq_lock, flags); ++ ++ return 0; ++err: ++ spin_unlock_irqrestore(&dispc.irq_lock, flags); ++ ++ return ret; ++} ++EXPORT_SYMBOL(omap_dispc_register_isr); ++ ++int omap_dispc_unregister_isr(omap_dispc_isr_t isr, void *arg, u32 mask) ++{ ++ int i; ++ unsigned long flags; ++ int ret = -EINVAL; ++ struct omap_dispc_isr_data *isr_data; ++ ++ spin_lock_irqsave(&dispc.irq_lock, flags); ++ ++ for (i = 0; i < DISPC_MAX_NR_ISRS; i++) { ++ isr_data = &dispc.registered_isr[i]; ++ if (isr_data->isr != isr || isr_data->arg != arg || ++ isr_data->mask != mask) ++ continue; ++ ++ /* found the correct isr */ ++ ++ isr_data->isr = NULL; ++ isr_data->arg = NULL; ++ isr_data->mask = 0; ++ ++ ret = 0; ++ break; ++ } ++ ++ if (ret == 0) ++ _omap_dispc_set_irqs(); ++ ++ spin_unlock_irqrestore(&dispc.irq_lock, flags); ++ ++ return ret; ++} ++EXPORT_SYMBOL(omap_dispc_unregister_isr); ++ ++#ifdef DEBUG ++static void print_irq_status(u32 status) ++{ ++ if ((status & dispc.irq_error_mask) == 0) ++ return; ++ ++ printk(KERN_DEBUG "DISPC IRQ: 0x%x: ", status); ++ ++#define PIS(x) \ ++ if (status & DISPC_IRQ_##x) \ ++ printk(#x " "); ++ PIS(GFX_FIFO_UNDERFLOW); ++ PIS(OCP_ERR); ++ PIS(VID1_FIFO_UNDERFLOW); ++ PIS(VID2_FIFO_UNDERFLOW); ++ PIS(SYNC_LOST); ++ PIS(SYNC_LOST_DIGIT); ++#undef PIS ++ ++ printk("\n"); ++} ++#endif ++ ++/* Called from dss.c. Note that we don't touch clocks here, ++ * but we presume they are on because we got an IRQ. However, ++ * an irq handler may turn the clocks off, so we may not have ++ * clock later in the function. */ ++void dispc_irq_handler(void) ++{ ++ int i; ++ u32 irqstatus; ++ u32 handledirqs = 0; ++ u32 unhandled_errors; ++ struct omap_dispc_isr_data *isr_data; ++ struct omap_dispc_isr_data registered_isr[DISPC_MAX_NR_ISRS]; ++ ++ spin_lock(&dispc.irq_lock); ++ ++ irqstatus = dispc_read_reg(DISPC_IRQSTATUS); ++ ++#ifdef DEBUG ++ if (dss_debug) ++ print_irq_status(irqstatus); ++#endif ++ /* Ack the interrupt. Do it here before clocks are possibly turned ++ * off */ ++ dispc_write_reg(DISPC_IRQSTATUS, irqstatus); ++ ++ /* make a copy and unlock, so that isrs can unregister ++ * themselves */ ++ memcpy(registered_isr, dispc.registered_isr, ++ sizeof(registered_isr)); ++ ++ spin_unlock(&dispc.irq_lock); ++ ++ for (i = 0; i < DISPC_MAX_NR_ISRS; i++) { ++ isr_data = ®istered_isr[i]; ++ ++ if (!isr_data->isr) ++ continue; ++ ++ if (isr_data->mask & irqstatus) { ++ isr_data->isr(isr_data->arg, irqstatus); ++ handledirqs |= isr_data->mask; ++ } ++ } ++ ++ spin_lock(&dispc.irq_lock); ++ ++ unhandled_errors = irqstatus & ~handledirqs & dispc.irq_error_mask; ++ ++ if (unhandled_errors) { ++ dispc.error_irqs |= unhandled_errors; ++ ++ dispc.irq_error_mask &= ~unhandled_errors; ++ _omap_dispc_set_irqs(); ++ ++ schedule_work(&dispc.error_work); ++ } ++ ++ spin_unlock(&dispc.irq_lock); ++} ++ ++static void dispc_error_worker(struct work_struct *work) ++{ ++ int i; ++ u32 errors; ++ unsigned long flags; ++ ++ spin_lock_irqsave(&dispc.irq_lock, flags); ++ errors = dispc.error_irqs; ++ dispc.error_irqs = 0; ++ spin_unlock_irqrestore(&dispc.irq_lock, flags); ++ ++ if (errors & DISPC_IRQ_GFX_FIFO_UNDERFLOW) { ++ DSSERR("GFX_FIFO_UNDERFLOW, disabling GFX\n"); ++ for (i = 0; i < omap_dss_get_num_overlays(); ++i) { ++ struct omap_overlay *ovl; ++ ovl = omap_dss_get_overlay(i); ++ ++ if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC)) ++ continue; ++ ++ if (ovl->id == 0) { ++ dispc_enable_plane(ovl->id, 0); ++ dispc_go(ovl->manager->id); ++ mdelay(50); ++ break; ++ } ++ } ++ } ++ ++ if (errors & DISPC_IRQ_VID1_FIFO_UNDERFLOW) { ++ DSSERR("VID1_FIFO_UNDERFLOW, disabling VID1\n"); ++ for (i = 0; i < omap_dss_get_num_overlays(); ++i) { ++ struct omap_overlay *ovl; ++ ovl = omap_dss_get_overlay(i); ++ ++ if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC)) ++ continue; ++ ++ if (ovl->id == 1) { ++ dispc_enable_plane(ovl->id, 0); ++ dispc_go(ovl->manager->id); ++ mdelay(50); ++ break; ++ } ++ } ++ } ++ ++ if (errors & DISPC_IRQ_VID2_FIFO_UNDERFLOW) { ++ DSSERR("VID2_FIFO_UNDERFLOW, disabling VID2\n"); ++ for (i = 0; i < omap_dss_get_num_overlays(); ++i) { ++ struct omap_overlay *ovl; ++ ovl = omap_dss_get_overlay(i); ++ ++ if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC)) ++ continue; ++ ++ if (ovl->id == 2) { ++ dispc_enable_plane(ovl->id, 0); ++ dispc_go(ovl->manager->id); ++ mdelay(50); ++ break; ++ } ++ } ++ } ++ ++ if (errors & DISPC_IRQ_SYNC_LOST) { ++ struct omap_overlay_manager *manager = NULL; ++ bool enable = false; ++ ++ DSSERR("SYNC_LOST, disabling LCD\n"); ++ ++ for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) { ++ struct omap_overlay_manager *mgr; ++ mgr = omap_dss_get_overlay_manager(i); ++ ++ if (mgr->id == OMAP_DSS_CHANNEL_LCD) { ++ manager = mgr; ++ enable = mgr->device->state == ++ OMAP_DSS_DISPLAY_ACTIVE; ++ mgr->device->disable(mgr->device); ++ break; ++ } ++ } ++ ++ if (manager) { ++ for (i = 0; i < omap_dss_get_num_overlays(); ++i) { ++ struct omap_overlay *ovl; ++ ovl = omap_dss_get_overlay(i); ++ ++ if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC)) ++ continue; ++ ++ if (ovl->id != 0 && ovl->manager == manager) ++ dispc_enable_plane(ovl->id, 0); ++ } ++ ++ dispc_go(manager->id); ++ mdelay(50); ++ if (enable) ++ manager->device->enable(manager->device); ++ } ++ } ++ ++ if (errors & DISPC_IRQ_SYNC_LOST_DIGIT) { ++ struct omap_overlay_manager *manager = NULL; ++ bool enable = false; ++ ++ DSSERR("SYNC_LOST_DIGIT, disabling TV\n"); ++ ++ for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) { ++ struct omap_overlay_manager *mgr; ++ mgr = omap_dss_get_overlay_manager(i); ++ ++ if (mgr->id == OMAP_DSS_CHANNEL_DIGIT) { ++ manager = mgr; ++ enable = mgr->device->state == ++ OMAP_DSS_DISPLAY_ACTIVE; ++ mgr->device->disable(mgr->device); ++ break; ++ } ++ } ++ ++ if (manager) { ++ for (i = 0; i < omap_dss_get_num_overlays(); ++i) { ++ struct omap_overlay *ovl; ++ ovl = omap_dss_get_overlay(i); ++ ++ if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC)) ++ continue; ++ ++ if (ovl->id != 0 && ovl->manager == manager) ++ dispc_enable_plane(ovl->id, 0); ++ } ++ ++ dispc_go(manager->id); ++ mdelay(50); ++ if (enable) ++ manager->device->enable(manager->device); ++ } ++ } ++ ++ if (errors & DISPC_IRQ_OCP_ERR) { ++ DSSERR("OCP_ERR\n"); ++ for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) { ++ struct omap_overlay_manager *mgr; ++ mgr = omap_dss_get_overlay_manager(i); ++ ++ if (mgr->caps & OMAP_DSS_OVL_CAP_DISPC) ++ mgr->device->disable(mgr->device); ++ } ++ } ++ ++ spin_lock_irqsave(&dispc.irq_lock, flags); ++ dispc.irq_error_mask |= errors; ++ _omap_dispc_set_irqs(); ++ spin_unlock_irqrestore(&dispc.irq_lock, flags); ++} ++ ++int omap_dispc_wait_for_irq_timeout(u32 irqmask, unsigned long timeout) ++{ ++ void dispc_irq_wait_handler(void *data, u32 mask) ++ { ++ complete((struct completion *)data); ++ } ++ ++ int r; ++ DECLARE_COMPLETION_ONSTACK(completion); ++ ++ r = omap_dispc_register_isr(dispc_irq_wait_handler, &completion, ++ irqmask); ++ ++ if (r) ++ return r; ++ ++ timeout = wait_for_completion_timeout(&completion, timeout); ++ ++ omap_dispc_unregister_isr(dispc_irq_wait_handler, &completion, irqmask); ++ ++ if (timeout == 0) ++ return -ETIMEDOUT; ++ ++ if (timeout == -ERESTARTSYS) ++ return -ERESTARTSYS; ++ ++ return 0; ++} ++ ++int omap_dispc_wait_for_irq_interruptible_timeout(u32 irqmask, ++ unsigned long timeout) ++{ ++ void dispc_irq_wait_handler(void *data, u32 mask) ++ { ++ complete((struct completion *)data); ++ } ++ ++ int r; ++ DECLARE_COMPLETION_ONSTACK(completion); ++ ++ r = omap_dispc_register_isr(dispc_irq_wait_handler, &completion, ++ irqmask); ++ ++ if (r) ++ return r; ++ ++ timeout = wait_for_completion_interruptible_timeout(&completion, ++ timeout); ++ ++ omap_dispc_unregister_isr(dispc_irq_wait_handler, &completion, irqmask); ++ ++ if (timeout == 0) ++ return -ETIMEDOUT; ++ ++ if (timeout == -ERESTARTSYS) ++ return -ERESTARTSYS; ++ ++ return 0; ++} ++ ++#ifdef CONFIG_OMAP2_DSS_FAKE_VSYNC ++void dispc_fake_vsync_irq(void) ++{ ++ u32 irqstatus = DISPC_IRQ_VSYNC; ++ int i; ++ ++ for (i = 0; i < DISPC_MAX_NR_ISRS; i++) { ++ struct omap_dispc_isr_data *isr_data; ++ isr_data = &dispc.registered_isr[i]; ++ ++ if (!isr_data->isr) ++ continue; ++ ++ if (isr_data->mask & irqstatus) ++ isr_data->isr(isr_data->arg, irqstatus); ++ } ++} ++#endif ++ ++static void _omap_dispc_initialize_irq(void) ++{ ++ unsigned long flags; ++ ++ spin_lock_irqsave(&dispc.irq_lock, flags); ++ ++ memset(dispc.registered_isr, 0, sizeof(dispc.registered_isr)); ++ ++ dispc.irq_error_mask = DISPC_IRQ_MASK_ERROR; ++ ++ /* there's SYNC_LOST_DIGIT waiting after enabling the DSS, ++ * so clear it */ ++ dispc_write_reg(DISPC_IRQSTATUS, dispc_read_reg(DISPC_IRQSTATUS)); ++ ++ _omap_dispc_set_irqs(); ++ ++ spin_unlock_irqrestore(&dispc.irq_lock, flags); ++} ++ ++void dispc_enable_sidle(void) ++{ ++ REG_FLD_MOD(DISPC_SYSCONFIG, 2, 4, 3); /* SIDLEMODE: smart idle */ ++} ++ ++void dispc_disable_sidle(void) ++{ ++ REG_FLD_MOD(DISPC_SYSCONFIG, 1, 4, 3); /* SIDLEMODE: no idle */ ++} ++ ++static void _omap_dispc_initial_config(void) ++{ ++ u32 l; ++ ++ l = dispc_read_reg(DISPC_SYSCONFIG); ++ l = FLD_MOD(l, 2, 13, 12); /* MIDLEMODE: smart standby */ ++ l = FLD_MOD(l, 2, 4, 3); /* SIDLEMODE: smart idle */ ++ l = FLD_MOD(l, 1, 2, 2); /* ENWAKEUP */ ++ l = FLD_MOD(l, 1, 0, 0); /* AUTOIDLE */ ++ dispc_write_reg(DISPC_SYSCONFIG, l); ++ ++ /* FUNCGATED */ ++ REG_FLD_MOD(DISPC_CONFIG, 1, 9, 9); ++ ++ /* L3 firewall setting: enable access to OCM RAM */ ++ if (cpu_is_omap24xx()) ++ __raw_writel(0x402000b0, OMAP2_IO_ADDRESS(0x680050a0)); ++ ++ _dispc_setup_color_conv_coef(); ++ ++ dispc_set_loadmode(OMAP_DSS_LOAD_FRAME_ONLY); ++ ++ dispc_read_plane_fifo_sizes(); ++} ++ ++int dispc_init(void) ++{ ++ u32 rev; ++ ++ spin_lock_init(&dispc.irq_lock); ++ ++ INIT_WORK(&dispc.error_work, dispc_error_worker); ++ ++ dispc.base = ioremap(DISPC_BASE, DISPC_SZ_REGS); ++ if (!dispc.base) { ++ DSSERR("can't ioremap DISPC\n"); ++ return -ENOMEM; ++ } ++ ++ if (cpu_is_omap34xx()) { ++ dispc.dpll4_m4_ck = clk_get(NULL, "dpll4_m4_ck"); ++ if (IS_ERR(dispc.dpll4_m4_ck)) { ++ DSSERR("Failed to get dpll4_m4_ck\n"); ++ return -ENODEV; ++ } ++ } ++ ++ enable_clocks(1); ++ ++ _omap_dispc_initial_config(); ++ ++ _omap_dispc_initialize_irq(); ++ ++ dispc_save_context(); ++ ++ rev = dispc_read_reg(DISPC_REVISION); ++ printk(KERN_INFO "OMAP DISPC rev %d.%d\n", ++ FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0)); ++ ++ enable_clocks(0); ++ ++ return 0; ++} ++ ++void dispc_exit(void) ++{ ++ if (cpu_is_omap34xx()) ++ clk_put(dispc.dpll4_m4_ck); ++ iounmap(dispc.base); ++} ++ ++int dispc_enable_plane(enum omap_plane plane, bool enable) ++{ ++ DSSDBG("dispc_enable_plane %d, %d\n", plane, enable); ++ ++ enable_clocks(1); ++ _dispc_enable_plane(plane, enable); ++ enable_clocks(0); ++ ++ return 0; ++} ++ ++int dispc_setup_plane(enum omap_plane plane, ++ u32 paddr, u16 screen_width, ++ u16 pos_x, u16 pos_y, ++ u16 width, u16 height, ++ u16 out_width, u16 out_height, ++ enum omap_color_mode color_mode, ++ bool ilace, ++ enum omap_dss_rotation_type rotation_type, ++ u8 rotation, bool mirror, u8 global_alpha) ++{ ++ int r = 0; ++ ++ DSSDBG("dispc_setup_plane %d, pa %x, sw %d, %d,%d, %dx%d -> " ++ "%dx%d, ilace %d, cmode %x, rot %d, mir %d\n", ++ plane, paddr, screen_width, pos_x, pos_y, ++ width, height, ++ out_width, out_height, ++ ilace, color_mode, ++ rotation, mirror); ++ ++ enable_clocks(1); ++ ++ r = _dispc_setup_plane(plane, ++ paddr, screen_width, ++ pos_x, pos_y, ++ width, height, ++ out_width, out_height, ++ color_mode, ilace, ++ rotation_type, ++ rotation, mirror, ++ global_alpha); ++ ++ enable_clocks(0); ++ ++ return r; ++} +diff --git a/drivers/video/omap2/dss/display.c b/drivers/video/omap2/dss/display.c +new file mode 100644 +index 0000000..6b5d0cf +--- /dev/null ++++ b/drivers/video/omap2/dss/display.c +@@ -0,0 +1,658 @@ ++/* ++ * linux/drivers/video/omap2/dss/display.c ++ * ++ * Copyright (C) 2009 Nokia Corporation ++ * Author: Tomi Valkeinen ++ * ++ * Some code and ideas taken from drivers/video/omap/ driver ++ * by Imre Deak. ++ * ++ * 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. ++ * ++ * 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, see . ++ */ ++ ++#define DSS_SUBSYS_NAME "DISPLAY" ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include "dss.h" ++ ++static LIST_HEAD(display_list); ++ ++static ssize_t display_enabled_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct omap_dss_device *dssdev = to_dss_device(dev); ++ bool enabled = dssdev->state != OMAP_DSS_DISPLAY_DISABLED; ++ ++ return snprintf(buf, PAGE_SIZE, "%d\n", enabled); ++} ++ ++static ssize_t display_enabled_store(struct device *dev, ++ struct device_attribute *attr, ++ const char *buf, size_t size) ++{ ++ struct omap_dss_device *dssdev = to_dss_device(dev); ++ bool enabled, r; ++ ++ enabled = simple_strtoul(buf, NULL, 10); ++ ++ if (enabled != (dssdev->state != OMAP_DSS_DISPLAY_DISABLED)) { ++ if (enabled) { ++ r = dssdev->enable(dssdev); ++ if (r) ++ return r; ++ } else { ++ dssdev->disable(dssdev); ++ } ++ } ++ ++ return size; ++} ++ ++static ssize_t display_upd_mode_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct omap_dss_device *dssdev = to_dss_device(dev); ++ enum omap_dss_update_mode mode = OMAP_DSS_UPDATE_AUTO; ++ if (dssdev->get_update_mode) ++ mode = dssdev->get_update_mode(dssdev); ++ return snprintf(buf, PAGE_SIZE, "%d\n", mode); ++} ++ ++static ssize_t display_upd_mode_store(struct device *dev, ++ struct device_attribute *attr, ++ const char *buf, size_t size) ++{ ++ struct omap_dss_device *dssdev = to_dss_device(dev); ++ int val, r; ++ enum omap_dss_update_mode mode; ++ ++ val = simple_strtoul(buf, NULL, 10); ++ ++ switch (val) { ++ case OMAP_DSS_UPDATE_DISABLED: ++ case OMAP_DSS_UPDATE_AUTO: ++ case OMAP_DSS_UPDATE_MANUAL: ++ mode = (enum omap_dss_update_mode)val; ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ r = dssdev->set_update_mode(dssdev, mode); ++ if (r) ++ return r; ++ ++ return size; ++} ++ ++static ssize_t display_tear_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct omap_dss_device *dssdev = to_dss_device(dev); ++ return snprintf(buf, PAGE_SIZE, "%d\n", ++ dssdev->get_te ? dssdev->get_te(dssdev) : 0); ++} ++ ++static ssize_t display_tear_store(struct device *dev, ++ struct device_attribute *attr, const char *buf, size_t size) ++{ ++ struct omap_dss_device *dssdev = to_dss_device(dev); ++ unsigned long te; ++ int r; ++ ++ if (!dssdev->enable_te || !dssdev->get_te) ++ return -ENOENT; ++ ++ te = simple_strtoul(buf, NULL, 0); ++ ++ r = dssdev->enable_te(dssdev, te); ++ if (r) ++ return r; ++ ++ return size; ++} ++ ++static ssize_t display_timings_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct omap_dss_device *dssdev = to_dss_device(dev); ++ struct omap_video_timings t; ++ ++ if (!dssdev->get_timings) ++ return -ENOENT; ++ ++ dssdev->get_timings(dssdev, &t); ++ ++ return snprintf(buf, PAGE_SIZE, "%u,%u/%u/%u/%u,%u/%u/%u/%u\n", ++ t.pixel_clock, ++ t.x_res, t.hfp, t.hbp, t.hsw, ++ t.y_res, t.vfp, t.vbp, t.vsw); ++} ++ ++static ssize_t display_timings_store(struct device *dev, ++ struct device_attribute *attr, const char *buf, size_t size) ++{ ++ struct omap_dss_device *dssdev = to_dss_device(dev); ++ struct omap_video_timings t; ++ int r, found; ++ ++ if (!dssdev->set_timings || !dssdev->check_timings) ++ return -ENOENT; ++ ++ found = 0; ++#ifdef CONFIG_OMAP2_DSS_VENC ++ if (strncmp("pal", buf, 3) == 0) { ++ t = omap_dss_pal_timings; ++ found = 1; ++ } else if (strncmp("ntsc", buf, 4) == 0) { ++ t = omap_dss_ntsc_timings; ++ found = 1; ++ } ++#endif ++ if (!found && sscanf(buf, "%u,%hu/%hu/%hu/%hu,%hu/%hu/%hu/%hu", ++ &t.pixel_clock, ++ &t.x_res, &t.hfp, &t.hbp, &t.hsw, ++ &t.y_res, &t.vfp, &t.vbp, &t.vsw) != 9) ++ return -EINVAL; ++ ++ r = dssdev->check_timings(dssdev, &t); ++ if (r) ++ return r; ++ ++ dssdev->set_timings(dssdev, &t); ++ ++ return size; ++} ++ ++static ssize_t display_rotate_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct omap_dss_device *dssdev = to_dss_device(dev); ++ int rotate; ++ if (!dssdev->get_rotate) ++ return -ENOENT; ++ rotate = dssdev->get_rotate(dssdev); ++ return snprintf(buf, PAGE_SIZE, "%u\n", rotate); ++} ++ ++static ssize_t display_rotate_store(struct device *dev, ++ struct device_attribute *attr, const char *buf, size_t size) ++{ ++ struct omap_dss_device *dssdev = to_dss_device(dev); ++ unsigned long rot; ++ int r; ++ ++ if (!dssdev->set_rotate || !dssdev->get_rotate) ++ return -ENOENT; ++ ++ rot = simple_strtoul(buf, NULL, 0); ++ ++ r = dssdev->set_rotate(dssdev, rot); ++ if (r) ++ return r; ++ ++ return size; ++} ++ ++static ssize_t display_mirror_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct omap_dss_device *dssdev = to_dss_device(dev); ++ int mirror; ++ if (!dssdev->get_mirror) ++ return -ENOENT; ++ mirror = dssdev->get_mirror(dssdev); ++ return snprintf(buf, PAGE_SIZE, "%u\n", mirror); ++} ++ ++static ssize_t display_mirror_store(struct device *dev, ++ struct device_attribute *attr, const char *buf, size_t size) ++{ ++ struct omap_dss_device *dssdev = to_dss_device(dev); ++ unsigned long mirror; ++ int r; ++ ++ if (!dssdev->set_mirror || !dssdev->get_mirror) ++ return -ENOENT; ++ ++ mirror = simple_strtoul(buf, NULL, 0); ++ ++ r = dssdev->set_mirror(dssdev, mirror); ++ if (r) ++ return r; ++ ++ return size; ++} ++ ++static ssize_t display_wss_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct omap_dss_device *dssdev = to_dss_device(dev); ++ unsigned int wss; ++ ++ if (!dssdev->get_wss) ++ return -ENOENT; ++ ++ wss = dssdev->get_wss(dssdev); ++ ++ return snprintf(buf, PAGE_SIZE, "0x%05x\n", wss); ++} ++ ++static ssize_t display_wss_store(struct device *dev, ++ struct device_attribute *attr, const char *buf, size_t size) ++{ ++ struct omap_dss_device *dssdev = to_dss_device(dev); ++ unsigned long wss; ++ int r; ++ ++ if (!dssdev->get_wss || !dssdev->set_wss) ++ return -ENOENT; ++ ++ if (strict_strtoul(buf, 0, &wss)) ++ return -EINVAL; ++ ++ if (wss > 0xfffff) ++ return -EINVAL; ++ ++ r = dssdev->set_wss(dssdev, wss); ++ if (r) ++ return r; ++ ++ return size; ++} ++ ++static DEVICE_ATTR(enabled, S_IRUGO|S_IWUSR, ++ display_enabled_show, display_enabled_store); ++static DEVICE_ATTR(update_mode, S_IRUGO|S_IWUSR, ++ display_upd_mode_show, display_upd_mode_store); ++static DEVICE_ATTR(tear_elim, S_IRUGO|S_IWUSR, ++ display_tear_show, display_tear_store); ++static DEVICE_ATTR(timings, S_IRUGO|S_IWUSR, ++ display_timings_show, display_timings_store); ++static DEVICE_ATTR(rotate, S_IRUGO|S_IWUSR, ++ display_rotate_show, display_rotate_store); ++static DEVICE_ATTR(mirror, S_IRUGO|S_IWUSR, ++ display_mirror_show, display_mirror_store); ++static DEVICE_ATTR(wss, S_IRUGO|S_IWUSR, ++ display_wss_show, display_wss_store); ++ ++static struct device_attribute *display_sysfs_attrs[] = { ++ &dev_attr_enabled, ++ &dev_attr_update_mode, ++ &dev_attr_tear_elim, ++ &dev_attr_timings, ++ &dev_attr_rotate, ++ &dev_attr_mirror, ++ &dev_attr_wss, ++ NULL ++}; ++ ++static void default_get_resolution(struct omap_dss_device *dssdev, ++ u16 *xres, u16 *yres) ++{ ++ *xres = dssdev->panel.timings.x_res; ++ *yres = dssdev->panel.timings.y_res; ++} ++ ++void default_get_overlay_fifo_thresholds(enum omap_plane plane, ++ u32 fifo_size, enum omap_burst_size *burst_size, ++ u32 *fifo_low, u32 *fifo_high) ++{ ++ unsigned burst_size_bytes; ++ ++ *burst_size = OMAP_DSS_BURST_16x32; ++ burst_size_bytes = 16 * 32 / 8; ++ ++ *fifo_high = fifo_size - 1; ++ *fifo_low = fifo_size - burst_size_bytes; ++} ++ ++static int default_wait_vsync(struct omap_dss_device *dssdev) ++{ ++ unsigned long timeout = msecs_to_jiffies(500); ++ u32 irq; ++ ++ if (dssdev->type == OMAP_DISPLAY_TYPE_VENC) ++ irq = DISPC_IRQ_EVSYNC_ODD; ++ else ++ irq = DISPC_IRQ_VSYNC; ++ ++ return omap_dispc_wait_for_irq_interruptible_timeout(irq, timeout); ++} ++ ++static int default_get_recommended_bpp(struct omap_dss_device *dssdev) ++{ ++ if (dssdev->panel.recommended_bpp) ++ return dssdev->panel.recommended_bpp; ++ ++ switch (dssdev->type) { ++ case OMAP_DISPLAY_TYPE_DPI: ++ if (dssdev->phy.dpi.data_lines == 24) ++ return 24; ++ else ++ return 16; ++ ++ case OMAP_DISPLAY_TYPE_DBI: ++ case OMAP_DISPLAY_TYPE_DSI: ++ if (dssdev->ctrl.pixel_size == 24) ++ return 24; ++ else ++ return 16; ++ case OMAP_DISPLAY_TYPE_VENC: ++ case OMAP_DISPLAY_TYPE_SDI: ++ return 24; ++ return 24; ++ default: ++ BUG(); ++ } ++} ++ ++/* Checks if replication logic should be used. Only use for active matrix, ++ * when overlay is in RGB12U or RGB16 mode, and LCD interface is ++ * 18bpp or 24bpp */ ++bool dss_use_replication(struct omap_dss_device *dssdev, ++ enum omap_color_mode mode) ++{ ++ int bpp; ++ ++ if (mode != OMAP_DSS_COLOR_RGB12U && mode != OMAP_DSS_COLOR_RGB16) ++ return false; ++ ++ if (dssdev->type == OMAP_DISPLAY_TYPE_DPI && ++ (dssdev->panel.config & OMAP_DSS_LCD_TFT) == 0) ++ return false; ++ ++ switch (dssdev->type) { ++ case OMAP_DISPLAY_TYPE_DPI: ++ bpp = dssdev->phy.dpi.data_lines; ++ break; ++ case OMAP_DISPLAY_TYPE_VENC: ++ case OMAP_DISPLAY_TYPE_SDI: ++ bpp = 24; ++ break; ++ case OMAP_DISPLAY_TYPE_DBI: ++ case OMAP_DISPLAY_TYPE_DSI: ++ bpp = dssdev->ctrl.pixel_size; ++ break; ++ default: ++ BUG(); ++ } ++ ++ return bpp > 16; ++} ++ ++void dss_init_device(struct platform_device *pdev, ++ struct omap_dss_device *dssdev) ++{ ++ struct device_attribute *attr; ++ int i; ++ int r; ++ ++ switch (dssdev->type) { ++ case OMAP_DISPLAY_TYPE_DPI: ++#ifdef CONFIG_OMAP2_DSS_RFBI ++ case OMAP_DISPLAY_TYPE_DBI: ++#endif ++#ifdef CONFIG_OMAP2_DSS_SDI ++ case OMAP_DISPLAY_TYPE_SDI: ++#endif ++#ifdef CONFIG_OMAP2_DSS_DSI ++ case OMAP_DISPLAY_TYPE_DSI: ++#endif ++#ifdef CONFIG_OMAP2_DSS_VENC ++ case OMAP_DISPLAY_TYPE_VENC: ++#endif ++ break; ++ default: ++ DSSERR("Support for display '%s' not compiled in.\n", ++ dssdev->name); ++ return; ++ } ++ ++ dssdev->get_resolution = default_get_resolution; ++ dssdev->get_recommended_bpp = default_get_recommended_bpp; ++ dssdev->wait_vsync = default_wait_vsync; ++ ++ switch (dssdev->type) { ++ case OMAP_DISPLAY_TYPE_DPI: ++ r = dpi_init_display(dssdev); ++ break; ++#ifdef CONFIG_OMAP2_DSS_RFBI ++ case OMAP_DISPLAY_TYPE_DBI: ++ r = rfbi_init_display(dssdev); ++ break; ++#endif ++#ifdef CONFIG_OMAP2_DSS_VENC ++ case OMAP_DISPLAY_TYPE_VENC: ++ r = venc_init_display(dssdev); ++ break; ++#endif ++#ifdef CONFIG_OMAP2_DSS_SDI ++ case OMAP_DISPLAY_TYPE_SDI: ++ r = sdi_init_display(dssdev); ++ break; ++#endif ++#ifdef CONFIG_OMAP2_DSS_DSI ++ case OMAP_DISPLAY_TYPE_DSI: ++ r = dsi_init_display(dssdev); ++ break; ++#endif ++ default: ++ BUG(); ++ } ++ ++ if (r) { ++ DSSERR("failed to init display %s\n", dssdev->name); ++ return; ++ } ++ ++ /* create device sysfs files */ ++ i = 0; ++ while ((attr = display_sysfs_attrs[i++]) != NULL) { ++ r = device_create_file(&dssdev->dev, attr); ++ if (r) ++ DSSERR("failed to create sysfs file\n"); ++ } ++ ++ /* create display? sysfs links */ ++ r = sysfs_create_link(&pdev->dev.kobj, &dssdev->dev.kobj, ++ dev_name(&dssdev->dev)); ++ if (r) ++ DSSERR("failed to create sysfs display link\n"); ++} ++ ++void dss_uninit_device(struct platform_device *pdev, ++ struct omap_dss_device *dssdev) ++{ ++ struct device_attribute *attr; ++ int i = 0; ++ ++ sysfs_remove_link(&pdev->dev.kobj, dev_name(&dssdev->dev)); ++ ++ while ((attr = display_sysfs_attrs[i++]) != NULL) ++ device_remove_file(&dssdev->dev, attr); ++ ++ if (dssdev->manager) ++ dssdev->manager->unset_device(dssdev->manager); ++} ++ ++static int dss_suspend_device(struct device *dev, void *data) ++{ ++ int r; ++ struct omap_dss_device *dssdev = to_dss_device(dev); ++ ++ if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) { ++ dssdev->activate_after_resume = false; ++ return 0; ++ } ++ ++ if (!dssdev->suspend) { ++ DSSERR("display '%s' doesn't implement suspend\n", ++ dssdev->name); ++ return -ENOSYS; ++ } ++ ++ r = dssdev->suspend(dssdev); ++ if (r) ++ return r; ++ ++ dssdev->activate_after_resume = true; ++ ++ return 0; ++} ++ ++int dss_suspend_all_devices(void) ++{ ++ int r; ++ struct bus_type *bus = dss_get_bus(); ++ ++ r = bus_for_each_dev(bus, NULL, NULL, dss_suspend_device); ++ if (r) { ++ /* resume all displays that were suspended */ ++ dss_resume_all_devices(); ++ return r; ++ } ++ ++ return 0; ++} ++ ++static int dss_resume_device(struct device *dev, void *data) ++{ ++ int r; ++ struct omap_dss_device *dssdev = to_dss_device(dev); ++ ++ if (dssdev->activate_after_resume && dssdev->resume) { ++ r = dssdev->resume(dssdev); ++ if (r) ++ return r; ++ } ++ ++ dssdev->activate_after_resume = false; ++ ++ return 0; ++} ++ ++int dss_resume_all_devices(void) ++{ ++ struct bus_type *bus = dss_get_bus(); ++ ++ return bus_for_each_dev(bus, NULL, NULL, dss_resume_device); ++} ++ ++ ++void omap_dss_get_device(struct omap_dss_device *dssdev) ++{ ++ get_device(&dssdev->dev); ++} ++EXPORT_SYMBOL(omap_dss_get_device); ++ ++void omap_dss_put_device(struct omap_dss_device *dssdev) ++{ ++ put_device(&dssdev->dev); ++} ++EXPORT_SYMBOL(omap_dss_put_device); ++ ++/* ref count of the found device is incremented. ref count ++ * of from-device is decremented. */ ++struct omap_dss_device *omap_dss_get_next_device(struct omap_dss_device *from) ++{ ++ struct device *dev; ++ struct device *dev_start = NULL; ++ struct omap_dss_device *dssdev = NULL; ++ ++ int match(struct device *dev, void *data) ++ { ++ /* skip panels connected to controllers */ ++ if (to_dss_device(dev)->panel.ctrl) ++ return 0; ++ ++ return 1; ++ } ++ ++ if (from) ++ dev_start = &from->dev; ++ dev = bus_find_device(dss_get_bus(), dev_start, NULL, match); ++ if (dev) ++ dssdev = to_dss_device(dev); ++ if (from) ++ put_device(&from->dev); ++ ++ return dssdev; ++} ++EXPORT_SYMBOL(omap_dss_get_next_device); ++ ++struct omap_dss_device *omap_dss_find_device(void *data, ++ int (*match)(struct omap_dss_device *dssdev, void *data)) ++{ ++ struct omap_dss_device *dssdev = NULL; ++ ++ while ((dssdev = omap_dss_get_next_device(dssdev)) != NULL) { ++ if (match(dssdev, data)) ++ return dssdev; ++ } ++ ++ return NULL; ++} ++EXPORT_SYMBOL(omap_dss_find_device); ++ ++int omap_dss_start_device(struct omap_dss_device *dssdev) ++{ ++ int r; ++ ++ if (!dssdev->driver) { ++ DSSDBG("no driver\n"); ++ r = -ENODEV; ++ goto err0; ++ } ++ ++ if (dssdev->ctrl.panel && !dssdev->ctrl.panel->driver) { ++ DSSDBG("no panel driver\n"); ++ r = -ENODEV; ++ goto err0; ++ } ++ ++ if (!try_module_get(dssdev->dev.driver->owner)) { ++ r = -ENODEV; ++ goto err0; ++ } ++ ++ if (dssdev->ctrl.panel) { ++ if (!try_module_get(dssdev->ctrl.panel->dev.driver->owner)) { ++ r = -ENODEV; ++ goto err1; ++ } ++ } ++ ++ return 0; ++err1: ++ module_put(dssdev->dev.driver->owner); ++err0: ++ return r; ++} ++EXPORT_SYMBOL(omap_dss_start_device); ++ ++void omap_dss_stop_device(struct omap_dss_device *dssdev) ++{ ++ if (dssdev->ctrl.panel) ++ module_put(dssdev->ctrl.panel->dev.driver->owner); ++ ++ module_put(dssdev->dev.driver->owner); ++} ++EXPORT_SYMBOL(omap_dss_stop_device); ++ +diff --git a/drivers/video/omap2/dss/dpi.c b/drivers/video/omap2/dss/dpi.c +new file mode 100644 +index 0000000..b6543c8 +--- /dev/null ++++ b/drivers/video/omap2/dss/dpi.c +@@ -0,0 +1,388 @@ ++/* ++ * linux/drivers/video/omap2/dss/dpi.c ++ * ++ * Copyright (C) 2009 Nokia Corporation ++ * Author: Tomi Valkeinen ++ * ++ * Some code and ideas taken from drivers/video/omap/ driver ++ * by Imre Deak. ++ * ++ * 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. ++ * ++ * 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, see . ++ */ ++ ++#define DSS_SUBSYS_NAME "DPI" ++ ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++#include "dss.h" ++ ++static struct { ++ int update_enabled; ++} dpi; ++ ++#ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL ++static int dpi_set_dsi_clk(bool is_tft, unsigned long pck_req, ++ unsigned long *fck, int *lck_div, int *pck_div) ++{ ++ struct dsi_clock_info cinfo; ++ int r; ++ ++ r = dsi_pll_calc_pck(is_tft, pck_req, &cinfo); ++ if (r) ++ return r; ++ ++ r = dsi_pll_program(&cinfo); ++ if (r) ++ return r; ++ ++ dss_select_clk_source(0, 1); ++ ++ dispc_set_lcd_divisor(cinfo.lck_div, cinfo.pck_div); ++ ++ *fck = cinfo.dsi1_pll_fclk; ++ *lck_div = cinfo.lck_div; ++ *pck_div = cinfo.pck_div; ++ ++ return 0; ++} ++#else ++static int dpi_set_dispc_clk(bool is_tft, unsigned long pck_req, ++ unsigned long *fck, int *lck_div, int *pck_div) ++{ ++ struct dispc_clock_info cinfo; ++ int r; ++ ++ r = dispc_calc_clock_div(is_tft, pck_req, &cinfo); ++ if (r) ++ return r; ++ ++ r = dispc_set_clock_div(&cinfo); ++ if (r) ++ return r; ++ ++ *fck = cinfo.fck; ++ *lck_div = cinfo.lck_div; ++ *pck_div = cinfo.pck_div; ++ ++ return 0; ++} ++#endif ++ ++static int dpi_set_mode(struct omap_dss_device *dssdev) ++{ ++ struct omap_video_timings *t = &dssdev->panel.timings; ++ int lck_div, pck_div; ++ unsigned long fck; ++ unsigned long pck; ++ bool is_tft; ++ int r = 0; ++ ++ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); ++ ++ dispc_set_pol_freq(dssdev->panel.config, dssdev->panel.acbi, ++ dssdev->panel.acb); ++ ++ is_tft = (dssdev->panel.config & OMAP_DSS_LCD_TFT) != 0; ++ ++#ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL ++ r = dpi_set_dsi_clk(is_tft, t->pixel_clock * 1000, ++ &fck, &lck_div, &pck_div); ++#else ++ r = dpi_set_dispc_clk(is_tft, t->pixel_clock * 1000, ++ &fck, &lck_div, &pck_div); ++#endif ++ if (r) ++ goto err0; ++ ++ pck = fck / lck_div / pck_div / 1000; ++ ++ if (pck != t->pixel_clock) { ++ DSSWARN("Could not find exact pixel clock. " ++ "Requested %d kHz, got %lu kHz\n", ++ t->pixel_clock, pck); ++ ++ t->pixel_clock = pck; ++ } ++ ++ dispc_set_lcd_timings(t); ++ ++err0: ++ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); ++ return r; ++} ++ ++static int dpi_basic_init(struct omap_dss_device *dssdev) ++{ ++ bool is_tft; ++ ++ is_tft = (dssdev->panel.config & OMAP_DSS_LCD_TFT) != 0; ++ ++ dispc_set_parallel_interface_mode(OMAP_DSS_PARALLELMODE_BYPASS); ++ dispc_set_lcd_display_type(is_tft ? OMAP_DSS_LCD_DISPLAY_TFT : ++ OMAP_DSS_LCD_DISPLAY_STN); ++ dispc_set_tft_data_lines(dssdev->phy.dpi.data_lines); ++ ++ return 0; ++} ++ ++static int dpi_display_enable(struct omap_dss_device *dssdev) ++{ ++ int r; ++ ++ r = omap_dss_start_device(dssdev); ++ if (r) { ++ DSSERR("failed to start device\n"); ++ goto err0; ++ } ++ ++ if (dssdev->state != OMAP_DSS_DISPLAY_DISABLED) { ++ DSSERR("display already enabled\n"); ++ r = -EINVAL; ++ goto err1; ++ } ++ ++ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); ++ ++ r = dpi_basic_init(dssdev); ++ if (r) ++ goto err2; ++ ++#ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL ++ dss_clk_enable(DSS_CLK_FCK2); ++ r = dsi_pll_init(0, 1); ++ if (r) ++ goto err3; ++#endif ++ r = dpi_set_mode(dssdev); ++ if (r) ++ goto err4; ++ ++ mdelay(2); ++ ++ dispc_enable_lcd_out(1); ++ ++ r = dssdev->driver->enable(dssdev); ++ if (r) ++ goto err5; ++ ++ dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; ++ ++ return 0; ++ ++err5: ++ dispc_enable_lcd_out(0); ++err4: ++#ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL ++ dsi_pll_uninit(); ++err3: ++ dss_clk_disable(DSS_CLK_FCK2); ++#endif ++err2: ++ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); ++err1: ++ omap_dss_stop_device(dssdev); ++err0: ++ return r; ++} ++ ++static int dpi_display_resume(struct omap_dss_device *dssdev); ++ ++static void dpi_display_disable(struct omap_dss_device *dssdev) ++{ ++ if (dssdev->state == OMAP_DSS_DISPLAY_DISABLED) ++ return; ++ ++ if (dssdev->state == OMAP_DSS_DISPLAY_SUSPENDED) ++ dpi_display_resume(dssdev); ++ ++ dssdev->driver->disable(dssdev); ++ ++ dispc_enable_lcd_out(0); ++ ++#ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL ++ dss_select_clk_source(0, 0); ++ dsi_pll_uninit(); ++ dss_clk_disable(DSS_CLK_FCK2); ++#endif ++ ++ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); ++ ++ dssdev->state = OMAP_DSS_DISPLAY_DISABLED; ++ ++ omap_dss_stop_device(dssdev); ++} ++ ++static int dpi_display_suspend(struct omap_dss_device *dssdev) ++{ ++ if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) ++ return -EINVAL; ++ ++ DSSDBG("dpi_display_suspend\n"); ++ ++ if (dssdev->driver->suspend) ++ dssdev->driver->suspend(dssdev); ++ ++ dispc_enable_lcd_out(0); ++ ++ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); ++ ++ dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED; ++ ++ return 0; ++} ++ ++static int dpi_display_resume(struct omap_dss_device *dssdev) ++{ ++ if (dssdev->state != OMAP_DSS_DISPLAY_SUSPENDED) ++ return -EINVAL; ++ ++ DSSDBG("dpi_display_resume\n"); ++ ++ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); ++ ++ dispc_enable_lcd_out(1); ++ ++ if (dssdev->driver->resume) ++ dssdev->driver->resume(dssdev); ++ ++ dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; ++ ++ return 0; ++} ++ ++static void dpi_set_timings(struct omap_dss_device *dssdev, ++ struct omap_video_timings *timings) ++{ ++ DSSDBG("dpi_set_timings\n"); ++ dssdev->panel.timings = *timings; ++ if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) { ++ dpi_set_mode(dssdev); ++ dispc_go(OMAP_DSS_CHANNEL_LCD); ++ } ++} ++ ++static int dpi_check_timings(struct omap_dss_device *dssdev, ++ struct omap_video_timings *timings) ++{ ++ bool is_tft; ++ int r; ++ int lck_div, pck_div; ++ unsigned long fck; ++ unsigned long pck; ++ ++ if (!dispc_lcd_timings_ok(timings)) ++ return -EINVAL; ++ ++ if (timings->pixel_clock == 0) ++ return -EINVAL; ++ ++ is_tft = (dssdev->panel.config & OMAP_DSS_LCD_TFT) != 0; ++ ++#ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL ++ { ++ struct dsi_clock_info cinfo; ++ r = dsi_pll_calc_pck(is_tft, timings->pixel_clock * 1000, ++ &cinfo); ++ ++ if (r) ++ return r; ++ ++ fck = cinfo.dsi1_pll_fclk; ++ lck_div = cinfo.lck_div; ++ pck_div = cinfo.pck_div; ++ } ++#else ++ { ++ struct dispc_clock_info cinfo; ++ r = dispc_calc_clock_div(is_tft, timings->pixel_clock * 1000, ++ &cinfo); ++ ++ if (r) ++ return r; ++ ++ fck = cinfo.fck; ++ lck_div = cinfo.lck_div; ++ pck_div = cinfo.pck_div; ++ } ++#endif ++ ++ pck = fck / lck_div / pck_div / 1000; ++ ++ timings->pixel_clock = pck; ++ ++ return 0; ++} ++ ++static void dpi_get_timings(struct omap_dss_device *dssdev, ++ struct omap_video_timings *timings) ++{ ++ *timings = dssdev->panel.timings; ++} ++ ++static int dpi_display_set_update_mode(struct omap_dss_device *dssdev, ++ enum omap_dss_update_mode mode) ++{ ++ if (mode == OMAP_DSS_UPDATE_MANUAL) ++ return -EINVAL; ++ ++ if (mode == OMAP_DSS_UPDATE_DISABLED) { ++ dispc_enable_lcd_out(0); ++ dpi.update_enabled = 0; ++ } else { ++ dispc_enable_lcd_out(1); ++ dpi.update_enabled = 1; ++ } ++ ++ return 0; ++} ++ ++static enum omap_dss_update_mode dpi_display_get_update_mode( ++ struct omap_dss_device *dssdev) ++{ ++ return dpi.update_enabled ? OMAP_DSS_UPDATE_AUTO : ++ OMAP_DSS_UPDATE_DISABLED; ++} ++ ++int dpi_init_display(struct omap_dss_device *dssdev) ++{ ++ DSSDBG("init_display\n"); ++ ++ dssdev->enable = dpi_display_enable; ++ dssdev->disable = dpi_display_disable; ++ dssdev->suspend = dpi_display_suspend; ++ dssdev->resume = dpi_display_resume; ++ dssdev->set_timings = dpi_set_timings; ++ dssdev->check_timings = dpi_check_timings; ++ dssdev->get_timings = dpi_get_timings; ++ dssdev->set_update_mode = dpi_display_set_update_mode; ++ dssdev->get_update_mode = dpi_display_get_update_mode; ++ ++ return 0; ++} ++ ++int dpi_init(void) ++{ ++ return 0; ++} ++ ++void dpi_exit(void) ++{ ++} ++ +diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c +new file mode 100644 +index 0000000..d43b9ce +--- /dev/null ++++ b/drivers/video/omap2/dss/dsi.c +@@ -0,0 +1,3509 @@ ++/* ++ * linux/drivers/video/omap2/dss/dsi.c ++ * ++ * Copyright (C) 2009 Nokia Corporation ++ * Author: Tomi Valkeinen ++ * ++ * 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. ++ * ++ * 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, see . ++ */ ++ ++#define DSS_SUBSYS_NAME "DSI" ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++#include "dss.h" ++ ++/*#define VERBOSE_IRQ*/ ++ ++#define DSI_BASE 0x4804FC00 ++ ++struct dsi_reg { u16 idx; }; ++ ++#define DSI_REG(idx) ((const struct dsi_reg) { idx }) ++ ++#define DSI_SZ_REGS SZ_1K ++/* DSI Protocol Engine */ ++ ++#define DSI_REVISION DSI_REG(0x0000) ++#define DSI_SYSCONFIG DSI_REG(0x0010) ++#define DSI_SYSSTATUS DSI_REG(0x0014) ++#define DSI_IRQSTATUS DSI_REG(0x0018) ++#define DSI_IRQENABLE DSI_REG(0x001C) ++#define DSI_CTRL DSI_REG(0x0040) ++#define DSI_COMPLEXIO_CFG1 DSI_REG(0x0048) ++#define DSI_COMPLEXIO_IRQ_STATUS DSI_REG(0x004C) ++#define DSI_COMPLEXIO_IRQ_ENABLE DSI_REG(0x0050) ++#define DSI_CLK_CTRL DSI_REG(0x0054) ++#define DSI_TIMING1 DSI_REG(0x0058) ++#define DSI_TIMING2 DSI_REG(0x005C) ++#define DSI_VM_TIMING1 DSI_REG(0x0060) ++#define DSI_VM_TIMING2 DSI_REG(0x0064) ++#define DSI_VM_TIMING3 DSI_REG(0x0068) ++#define DSI_CLK_TIMING DSI_REG(0x006C) ++#define DSI_TX_FIFO_VC_SIZE DSI_REG(0x0070) ++#define DSI_RX_FIFO_VC_SIZE DSI_REG(0x0074) ++#define DSI_COMPLEXIO_CFG2 DSI_REG(0x0078) ++#define DSI_RX_FIFO_VC_FULLNESS DSI_REG(0x007C) ++#define DSI_VM_TIMING4 DSI_REG(0x0080) ++#define DSI_TX_FIFO_VC_EMPTINESS DSI_REG(0x0084) ++#define DSI_VM_TIMING5 DSI_REG(0x0088) ++#define DSI_VM_TIMING6 DSI_REG(0x008C) ++#define DSI_VM_TIMING7 DSI_REG(0x0090) ++#define DSI_STOPCLK_TIMING DSI_REG(0x0094) ++#define DSI_VC_CTRL(n) DSI_REG(0x0100 + (n * 0x20)) ++#define DSI_VC_TE(n) DSI_REG(0x0104 + (n * 0x20)) ++#define DSI_VC_LONG_PACKET_HEADER(n) DSI_REG(0x0108 + (n * 0x20)) ++#define DSI_VC_LONG_PACKET_PAYLOAD(n) DSI_REG(0x010C + (n * 0x20)) ++#define DSI_VC_SHORT_PACKET_HEADER(n) DSI_REG(0x0110 + (n * 0x20)) ++#define DSI_VC_IRQSTATUS(n) DSI_REG(0x0118 + (n * 0x20)) ++#define DSI_VC_IRQENABLE(n) DSI_REG(0x011C + (n * 0x20)) ++ ++/* DSIPHY_SCP */ ++ ++#define DSI_DSIPHY_CFG0 DSI_REG(0x200 + 0x0000) ++#define DSI_DSIPHY_CFG1 DSI_REG(0x200 + 0x0004) ++#define DSI_DSIPHY_CFG2 DSI_REG(0x200 + 0x0008) ++#define DSI_DSIPHY_CFG5 DSI_REG(0x200 + 0x0014) ++ ++/* DSI_PLL_CTRL_SCP */ ++ ++#define DSI_PLL_CONTROL DSI_REG(0x300 + 0x0000) ++#define DSI_PLL_STATUS DSI_REG(0x300 + 0x0004) ++#define DSI_PLL_GO DSI_REG(0x300 + 0x0008) ++#define DSI_PLL_CONFIGURATION1 DSI_REG(0x300 + 0x000C) ++#define DSI_PLL_CONFIGURATION2 DSI_REG(0x300 + 0x0010) ++ ++#define REG_GET(idx, start, end) \ ++ FLD_GET(dsi_read_reg(idx), start, end) ++ ++#define REG_FLD_MOD(idx, val, start, end) \ ++ dsi_write_reg(idx, FLD_MOD(dsi_read_reg(idx), val, start, end)) ++ ++/* Global interrupts */ ++#define DSI_IRQ_VC0 (1 << 0) ++#define DSI_IRQ_VC1 (1 << 1) ++#define DSI_IRQ_VC2 (1 << 2) ++#define DSI_IRQ_VC3 (1 << 3) ++#define DSI_IRQ_WAKEUP (1 << 4) ++#define DSI_IRQ_RESYNC (1 << 5) ++#define DSI_IRQ_PLL_LOCK (1 << 7) ++#define DSI_IRQ_PLL_UNLOCK (1 << 8) ++#define DSI_IRQ_PLL_RECALL (1 << 9) ++#define DSI_IRQ_COMPLEXIO_ERR (1 << 10) ++#define DSI_IRQ_HS_TX_TIMEOUT (1 << 14) ++#define DSI_IRQ_LP_RX_TIMEOUT (1 << 15) ++#define DSI_IRQ_TE_TRIGGER (1 << 16) ++#define DSI_IRQ_ACK_TRIGGER (1 << 17) ++#define DSI_IRQ_SYNC_LOST (1 << 18) ++#define DSI_IRQ_LDO_POWER_GOOD (1 << 19) ++#define DSI_IRQ_TA_TIMEOUT (1 << 20) ++#define DSI_IRQ_ERROR_MASK \ ++ (DSI_IRQ_HS_TX_TIMEOUT | DSI_IRQ_LP_RX_TIMEOUT | DSI_IRQ_SYNC_LOST | \ ++ DSI_IRQ_TA_TIMEOUT) ++#define DSI_IRQ_CHANNEL_MASK 0xf ++ ++/* Virtual channel interrupts */ ++#define DSI_VC_IRQ_CS (1 << 0) ++#define DSI_VC_IRQ_ECC_CORR (1 << 1) ++#define DSI_VC_IRQ_PACKET_SENT (1 << 2) ++#define DSI_VC_IRQ_FIFO_TX_OVF (1 << 3) ++#define DSI_VC_IRQ_FIFO_RX_OVF (1 << 4) ++#define DSI_VC_IRQ_BTA (1 << 5) ++#define DSI_VC_IRQ_ECC_NO_CORR (1 << 6) ++#define DSI_VC_IRQ_FIFO_TX_UDF (1 << 7) ++#define DSI_VC_IRQ_PP_BUSY_CHANGE (1 << 8) ++#define DSI_VC_IRQ_ERROR_MASK \ ++ (DSI_VC_IRQ_CS | DSI_VC_IRQ_ECC_CORR | DSI_VC_IRQ_FIFO_TX_OVF | \ ++ DSI_VC_IRQ_FIFO_RX_OVF | DSI_VC_IRQ_ECC_NO_CORR | \ ++ DSI_VC_IRQ_FIFO_TX_UDF) ++ ++/* ComplexIO interrupts */ ++#define DSI_CIO_IRQ_ERRSYNCESC1 (1 << 0) ++#define DSI_CIO_IRQ_ERRSYNCESC2 (1 << 1) ++#define DSI_CIO_IRQ_ERRSYNCESC3 (1 << 2) ++#define DSI_CIO_IRQ_ERRESC1 (1 << 5) ++#define DSI_CIO_IRQ_ERRESC2 (1 << 6) ++#define DSI_CIO_IRQ_ERRESC3 (1 << 7) ++#define DSI_CIO_IRQ_ERRCONTROL1 (1 << 10) ++#define DSI_CIO_IRQ_ERRCONTROL2 (1 << 11) ++#define DSI_CIO_IRQ_ERRCONTROL3 (1 << 12) ++#define DSI_CIO_IRQ_STATEULPS1 (1 << 15) ++#define DSI_CIO_IRQ_STATEULPS2 (1 << 16) ++#define DSI_CIO_IRQ_STATEULPS3 (1 << 17) ++#define DSI_CIO_IRQ_ERRCONTENTIONLP0_1 (1 << 20) ++#define DSI_CIO_IRQ_ERRCONTENTIONLP1_1 (1 << 21) ++#define DSI_CIO_IRQ_ERRCONTENTIONLP0_2 (1 << 22) ++#define DSI_CIO_IRQ_ERRCONTENTIONLP1_2 (1 << 23) ++#define DSI_CIO_IRQ_ERRCONTENTIONLP0_3 (1 << 24) ++#define DSI_CIO_IRQ_ERRCONTENTIONLP1_3 (1 << 25) ++#define DSI_CIO_IRQ_ULPSACTIVENOT_ALL0 (1 << 30) ++#define DSI_CIO_IRQ_ULPSACTIVENOT_ALL1 (1 << 31) ++ ++#define DSI_DT_DCS_SHORT_WRITE_0 0x05 ++#define DSI_DT_DCS_SHORT_WRITE_1 0x15 ++#define DSI_DT_DCS_READ 0x06 ++#define DSI_DT_SET_MAX_RET_PKG_SIZE 0x37 ++#define DSI_DT_NULL_PACKET 0x09 ++#define DSI_DT_DCS_LONG_WRITE 0x39 ++ ++#define DSI_DT_RX_ACK_WITH_ERR 0x02 ++#define DSI_DT_RX_DCS_LONG_READ 0x1c ++#define DSI_DT_RX_SHORT_READ_1 0x21 ++#define DSI_DT_RX_SHORT_READ_2 0x22 ++ ++#define FINT_MAX 2100000 ++#define FINT_MIN 750000 ++#define REGN_MAX (1 << 7) ++#define REGM_MAX ((1 << 11) - 1) ++#define REGM3_MAX (1 << 4) ++#define REGM4_MAX (1 << 4) ++ ++enum fifo_size { ++ DSI_FIFO_SIZE_0 = 0, ++ DSI_FIFO_SIZE_32 = 1, ++ DSI_FIFO_SIZE_64 = 2, ++ DSI_FIFO_SIZE_96 = 3, ++ DSI_FIFO_SIZE_128 = 4, ++}; ++ ++enum dsi_vc_mode { ++ DSI_VC_MODE_L4 = 0, ++ DSI_VC_MODE_VP, ++}; ++ ++struct dsi_update_region { ++ bool dirty; ++ u16 x, y, w, h; ++ struct omap_dss_device *device; ++}; ++ ++static struct ++{ ++ void __iomem *base; ++ ++ unsigned long dsi1_pll_fclk; /* Hz */ ++ unsigned long dsi2_pll_fclk; /* Hz */ ++ unsigned long dsiphy; /* Hz */ ++ unsigned long ddr_clk; /* Hz */ ++ ++ struct regulator *vdds_dsi_reg; ++ ++ struct { ++ enum dsi_vc_mode mode; ++ struct omap_dss_device *dssdev; ++ enum fifo_size fifo_size; ++ int dest_per; /* destination peripheral 0-3 */ ++ } vc[4]; ++ ++ struct mutex lock; ++ struct mutex bus_lock; ++ ++ unsigned pll_locked; ++ ++ struct completion bta_completion; ++ ++ struct task_struct *thread; ++ wait_queue_head_t waitqueue; ++ ++ spinlock_t update_lock; ++ bool framedone_received; ++ struct dsi_update_region update_region; ++ struct dsi_update_region active_update_region; ++ struct completion update_completion; ++ ++ enum omap_dss_update_mode user_update_mode; ++ enum omap_dss_update_mode update_mode; ++ bool te_enabled; ++ bool use_ext_te; ++ ++ unsigned long cache_req_pck; ++ unsigned long cache_clk_freq; ++ struct dsi_clock_info cache_cinfo; ++ ++ u32 errors; ++ spinlock_t errors_lock; ++#ifdef DEBUG ++ ktime_t perf_setup_time; ++ ktime_t perf_start_time; ++ ktime_t perf_start_time_auto; ++ int perf_measure_frames; ++#endif ++ int debug_read; ++ int debug_write; ++} dsi; ++ ++#ifdef DEBUG ++static unsigned int dsi_perf; ++module_param_named(dsi_perf, dsi_perf, bool, 0644); ++#endif ++ ++static inline void dsi_write_reg(const struct dsi_reg idx, u32 val) ++{ ++ __raw_writel(val, dsi.base + idx.idx); ++} ++ ++static inline u32 dsi_read_reg(const struct dsi_reg idx) ++{ ++ return __raw_readl(dsi.base + idx.idx); ++} ++ ++ ++void dsi_save_context(void) ++{ ++} ++ ++void dsi_restore_context(void) ++{ ++} ++ ++void dsi_bus_lock(void) ++{ ++ mutex_lock(&dsi.bus_lock); ++} ++EXPORT_SYMBOL(dsi_bus_lock); ++ ++void dsi_bus_unlock(void) ++{ ++ mutex_unlock(&dsi.bus_lock); ++} ++EXPORT_SYMBOL(dsi_bus_unlock); ++ ++static inline int wait_for_bit_change(const struct dsi_reg idx, int bitnum, ++ int value) ++{ ++ int t = 100000; ++ ++ while (REG_GET(idx, bitnum, bitnum) != value) { ++ if (--t == 0) ++ return !value; ++ } ++ ++ return value; ++} ++ ++#ifdef DEBUG ++static void dsi_perf_mark_setup(void) ++{ ++ dsi.perf_setup_time = ktime_get(); ++} ++ ++static void dsi_perf_mark_start(void) ++{ ++ dsi.perf_start_time = ktime_get(); ++} ++ ++static void dsi_perf_mark_start_auto(void) ++{ ++ dsi.perf_measure_frames = 0; ++ dsi.perf_start_time_auto = ktime_get(); ++} ++ ++static void dsi_perf_show(const char *name) ++{ ++ ktime_t t, setup_time, trans_time; ++ u32 total_bytes; ++ u32 setup_us, trans_us, total_us; ++ ++ if (!dsi_perf) ++ return; ++ ++ if (dsi.update_mode == OMAP_DSS_UPDATE_DISABLED) ++ return; ++ ++ t = ktime_get(); ++ ++ setup_time = ktime_sub(dsi.perf_start_time, dsi.perf_setup_time); ++ setup_us = (u32)ktime_to_us(setup_time); ++ if (setup_us == 0) ++ setup_us = 1; ++ ++ trans_time = ktime_sub(t, dsi.perf_start_time); ++ trans_us = (u32)ktime_to_us(trans_time); ++ if (trans_us == 0) ++ trans_us = 1; ++ ++ total_us = setup_us + trans_us; ++ ++ total_bytes = dsi.active_update_region.w * ++ dsi.active_update_region.h * ++ dsi.active_update_region.device->ctrl.pixel_size / 8; ++ ++ if (dsi.update_mode == OMAP_DSS_UPDATE_AUTO) { ++ static u32 s_total_trans_us, s_total_setup_us; ++ static u32 s_min_trans_us = 0xffffffff, s_min_setup_us; ++ static u32 s_max_trans_us, s_max_setup_us; ++ const int numframes = 100; ++ ktime_t total_time_auto; ++ u32 total_time_auto_us; ++ ++ dsi.perf_measure_frames++; ++ ++ if (setup_us < s_min_setup_us) ++ s_min_setup_us = setup_us; ++ ++ if (setup_us > s_max_setup_us) ++ s_max_setup_us = setup_us; ++ ++ s_total_setup_us += setup_us; ++ ++ if (trans_us < s_min_trans_us) ++ s_min_trans_us = trans_us; ++ ++ if (trans_us > s_max_trans_us) ++ s_max_trans_us = trans_us; ++ ++ s_total_trans_us += trans_us; ++ ++ if (dsi.perf_measure_frames < numframes) ++ return; ++ ++ total_time_auto = ktime_sub(t, dsi.perf_start_time_auto); ++ total_time_auto_us = (u32)ktime_to_us(total_time_auto); ++ ++ printk(KERN_INFO "DSI(%s): %u fps, setup %u/%u/%u, " ++ "trans %u/%u/%u\n", ++ name, ++ 1000 * 1000 * numframes / total_time_auto_us, ++ s_min_setup_us, ++ s_max_setup_us, ++ s_total_setup_us / numframes, ++ s_min_trans_us, ++ s_max_trans_us, ++ s_total_trans_us / numframes); ++ ++ s_total_setup_us = 0; ++ s_min_setup_us = 0xffffffff; ++ s_max_setup_us = 0; ++ s_total_trans_us = 0; ++ s_min_trans_us = 0xffffffff; ++ s_max_trans_us = 0; ++ dsi_perf_mark_start_auto(); ++ } else { ++ printk(KERN_INFO "DSI(%s): %u us + %u us = %u us (%uHz), " ++ "%u bytes, %u kbytes/sec\n", ++ name, ++ setup_us, ++ trans_us, ++ total_us, ++ 1000*1000 / total_us, ++ total_bytes, ++ total_bytes * 1000 / total_us); ++ } ++} ++#else ++#define dsi_perf_mark_setup() ++#define dsi_perf_mark_start() ++#define dsi_perf_mark_start_auto() ++#define dsi_perf_show(x) ++#endif ++ ++static void print_irq_status(u32 status) ++{ ++#ifndef VERBOSE_IRQ ++ if ((status & ~DSI_IRQ_CHANNEL_MASK) == 0) ++ return; ++#endif ++ printk(KERN_DEBUG "DSI IRQ: 0x%x: ", status); ++ ++#define PIS(x) \ ++ if (status & DSI_IRQ_##x) \ ++ printk(#x " "); ++#ifdef VERBOSE_IRQ ++ PIS(VC0); ++ PIS(VC1); ++ PIS(VC2); ++ PIS(VC3); ++#endif ++ PIS(WAKEUP); ++ PIS(RESYNC); ++ PIS(PLL_LOCK); ++ PIS(PLL_UNLOCK); ++ PIS(PLL_RECALL); ++ PIS(COMPLEXIO_ERR); ++ PIS(HS_TX_TIMEOUT); ++ PIS(LP_RX_TIMEOUT); ++ PIS(TE_TRIGGER); ++ PIS(ACK_TRIGGER); ++ PIS(SYNC_LOST); ++ PIS(LDO_POWER_GOOD); ++ PIS(TA_TIMEOUT); ++#undef PIS ++ ++ printk("\n"); ++} ++ ++static void print_irq_status_vc(int channel, u32 status) ++{ ++#ifndef VERBOSE_IRQ ++ if ((status & ~DSI_VC_IRQ_PACKET_SENT) == 0) ++ return; ++#endif ++ printk(KERN_DEBUG "DSI VC(%d) IRQ 0x%x: ", channel, status); ++ ++#define PIS(x) \ ++ if (status & DSI_VC_IRQ_##x) \ ++ printk(#x " "); ++ PIS(CS); ++ PIS(ECC_CORR); ++#ifdef VERBOSE_IRQ ++ PIS(PACKET_SENT); ++#endif ++ PIS(FIFO_TX_OVF); ++ PIS(FIFO_RX_OVF); ++ PIS(BTA); ++ PIS(ECC_NO_CORR); ++ PIS(FIFO_TX_UDF); ++ PIS(PP_BUSY_CHANGE); ++#undef PIS ++ printk("\n"); ++} ++ ++static void print_irq_status_cio(u32 status) ++{ ++ printk(KERN_DEBUG "DSI CIO IRQ 0x%x: ", status); ++ ++#define PIS(x) \ ++ if (status & DSI_CIO_IRQ_##x) \ ++ printk(#x " "); ++ PIS(ERRSYNCESC1); ++ PIS(ERRSYNCESC2); ++ PIS(ERRSYNCESC3); ++ PIS(ERRESC1); ++ PIS(ERRESC2); ++ PIS(ERRESC3); ++ PIS(ERRCONTROL1); ++ PIS(ERRCONTROL2); ++ PIS(ERRCONTROL3); ++ PIS(STATEULPS1); ++ PIS(STATEULPS2); ++ PIS(STATEULPS3); ++ PIS(ERRCONTENTIONLP0_1); ++ PIS(ERRCONTENTIONLP1_1); ++ PIS(ERRCONTENTIONLP0_2); ++ PIS(ERRCONTENTIONLP1_2); ++ PIS(ERRCONTENTIONLP0_3); ++ PIS(ERRCONTENTIONLP1_3); ++ PIS(ULPSACTIVENOT_ALL0); ++ PIS(ULPSACTIVENOT_ALL1); ++#undef PIS ++ ++ printk("\n"); ++} ++ ++static int debug_irq; ++ ++/* called from dss */ ++void dsi_irq_handler(void) ++{ ++ u32 irqstatus, vcstatus, ciostatus; ++ int i; ++ ++ irqstatus = dsi_read_reg(DSI_IRQSTATUS); ++ ++ if (irqstatus & DSI_IRQ_ERROR_MASK) { ++ DSSERR("DSI error, irqstatus %x\n", irqstatus); ++ print_irq_status(irqstatus); ++ spin_lock(&dsi.errors_lock); ++ dsi.errors |= irqstatus & DSI_IRQ_ERROR_MASK; ++ spin_unlock(&dsi.errors_lock); ++ } else if (debug_irq) { ++ print_irq_status(irqstatus); ++ } ++ ++ for (i = 0; i < 4; ++i) { ++ if ((irqstatus & (1<phy.dsi.lp_clk_hz; ++ ++ for (n = 1; n < (1 << 13) - 1; ++n) { ++ lp_clk = dsi_fclk / 2 / n; ++ if (lp_clk <= lp_clk_req) ++ break; ++ } ++ ++ if (n == (1 << 13) - 1) { ++ DSSERR("Failed to find LP_CLK_DIVISOR\n"); ++ return -EINVAL; ++ } ++ ++ DSSDBG("LP_CLK_DIV %u, LP_CLK %lu (req %lu)\n", n, lp_clk, lp_clk_req); ++ ++ REG_FLD_MOD(DSI_CLK_CTRL, n, 12, 0); /* LP_CLK_DIVISOR */ ++ if (dsi_fclk > 30*1000*1000) ++ REG_FLD_MOD(DSI_CLK_CTRL, 1, 21, 21); /* LP_RX_SYNCHRO_ENABLE */ ++ ++ return 0; ++} ++ ++ ++enum dsi_pll_power_state { ++ DSI_PLL_POWER_OFF = 0x0, ++ DSI_PLL_POWER_ON_HSCLK = 0x1, ++ DSI_PLL_POWER_ON_ALL = 0x2, ++ DSI_PLL_POWER_ON_DIV = 0x3, ++}; ++ ++static int dsi_pll_power(enum dsi_pll_power_state state) ++{ ++ int t = 0; ++ ++ REG_FLD_MOD(DSI_CLK_CTRL, state, 31, 30); /* PLL_PWR_CMD */ ++ ++ /* PLL_PWR_STATUS */ ++ while (FLD_GET(dsi_read_reg(DSI_CLK_CTRL), 29, 28) != state) { ++ udelay(1); ++ if (t++ > 1000) { ++ DSSERR("Failed to set DSI PLL power mode to %d\n", ++ state); ++ return -ENODEV; ++ } ++ } ++ ++ return 0; ++} ++ ++int dsi_pll_calc_pck(bool is_tft, unsigned long req_pck, ++ struct dsi_clock_info *cinfo) ++{ ++ struct dsi_clock_info cur, best; ++ int min_fck_per_pck; ++ int match = 0; ++ unsigned long dss_clk_fck2; ++ ++ dss_clk_fck2 = dss_clk_get_rate(DSS_CLK_FCK2); ++ ++ if (req_pck == dsi.cache_req_pck && ++ dsi.cache_cinfo.clkin == dss_clk_fck2) { ++ DSSDBG("DSI clock info found from cache\n"); ++ *cinfo = dsi.cache_cinfo; ++ return 0; ++ } ++ ++ min_fck_per_pck = CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK; ++ ++ if (min_fck_per_pck && ++ req_pck * min_fck_per_pck > DISPC_MAX_FCK) { ++ DSSERR("Requested pixel clock not possible with the current " ++ "OMAP2_DSS_MIN_FCK_PER_PCK setting. Turning " ++ "the constraint off.\n"); ++ min_fck_per_pck = 0; ++ } ++ ++ DSSDBG("dsi_pll_calc\n"); ++ ++retry: ++ memset(&best, 0, sizeof(best)); ++ ++ memset(&cur, 0, sizeof(cur)); ++ cur.clkin = dss_clk_fck2; ++ cur.use_dss2_fck = 1; ++ cur.highfreq = 0; ++ ++ /* no highfreq: 0.75MHz < Fint = clkin / regn < 2.1MHz */ ++ /* highfreq: 0.75MHz < Fint = clkin / (2*regn) < 2.1MHz */ ++ /* To reduce PLL lock time, keep Fint high (around 2 MHz) */ ++ for (cur.regn = 1; cur.regn < REGN_MAX; ++cur.regn) { ++ if (cur.highfreq == 0) ++ cur.fint = cur.clkin / cur.regn; ++ else ++ cur.fint = cur.clkin / (2 * cur.regn); ++ ++ if (cur.fint > FINT_MAX || cur.fint < FINT_MIN) ++ continue; ++ ++ /* DSIPHY(MHz) = (2 * regm / regn) * (clkin / (highfreq + 1)) */ ++ for (cur.regm = 1; cur.regm < REGM_MAX; ++cur.regm) { ++ unsigned long a, b; ++ ++ a = 2 * cur.regm * (cur.clkin/1000); ++ b = cur.regn * (cur.highfreq + 1); ++ cur.dsiphy = a / b * 1000; ++ ++ if (cur.dsiphy > 1800 * 1000 * 1000) ++ break; ++ ++ /* DSI1_PLL_FCLK(MHz) = DSIPHY(MHz) / regm3 < 173MHz */ ++ for (cur.regm3 = 1; cur.regm3 < REGM3_MAX; ++ ++cur.regm3) { ++ cur.dsi1_pll_fclk = cur.dsiphy / cur.regm3; ++ ++ /* this will narrow down the search a bit, ++ * but still give pixclocks below what was ++ * requested */ ++ if (cur.dsi1_pll_fclk < req_pck) ++ break; ++ ++ if (cur.dsi1_pll_fclk > DISPC_MAX_FCK) ++ continue; ++ ++ if (min_fck_per_pck && ++ cur.dsi1_pll_fclk < ++ req_pck * min_fck_per_pck) ++ continue; ++ ++ match = 1; ++ ++ find_lck_pck_divs(is_tft, req_pck, ++ cur.dsi1_pll_fclk, ++ &cur.lck_div, ++ &cur.pck_div); ++ ++ cur.lck = cur.dsi1_pll_fclk / cur.lck_div; ++ cur.pck = cur.lck / cur.pck_div; ++ ++ if (abs(cur.pck - req_pck) < ++ abs(best.pck - req_pck)) { ++ best = cur; ++ ++ if (cur.pck == req_pck) ++ goto found; ++ } ++ } ++ } ++ } ++found: ++ if (!match) { ++ if (min_fck_per_pck) { ++ DSSERR("Could not find suitable clock settings.\n" ++ "Turning FCK/PCK constraint off and" ++ "trying again.\n"); ++ min_fck_per_pck = 0; ++ goto retry; ++ } ++ ++ DSSERR("Could not find suitable clock settings.\n"); ++ ++ return -EINVAL; ++ } ++ ++ /* DSI2_PLL_FCLK (regm4) is not used. Set it to something sane. */ ++ best.regm4 = best.dsiphy / 48000000; ++ if (best.regm4 > REGM4_MAX) ++ best.regm4 = REGM4_MAX; ++ else if (best.regm4 == 0) ++ best.regm4 = 1; ++ best.dsi2_pll_fclk = best.dsiphy / best.regm4; ++ ++ if (cinfo) ++ *cinfo = best; ++ ++ dsi.cache_req_pck = req_pck; ++ dsi.cache_clk_freq = 0; ++ dsi.cache_cinfo = best; ++ ++ return 0; ++} ++ ++static int dsi_pll_calc_ddrfreq(unsigned long clk_freq, ++ struct dsi_clock_info *cinfo) ++{ ++ struct dsi_clock_info cur, best; ++ const bool use_dss2_fck = 1; ++ unsigned long datafreq; ++ unsigned long dss_clk_fck2; ++ ++ DSSDBG("dsi_pll_calc_ddrfreq\n"); ++ ++ dss_clk_fck2 = dss_clk_get_rate(DSS_CLK_FCK2); ++ ++ if (clk_freq == dsi.cache_clk_freq && ++ dsi.cache_cinfo.clkin == dss_clk_fck2) { ++ DSSDBG("DSI clock info found from cache\n"); ++ *cinfo = dsi.cache_cinfo; ++ return 0; ++ } ++ ++ datafreq = clk_freq * 4; ++ ++ memset(&best, 0, sizeof(best)); ++ ++ memset(&cur, 0, sizeof(cur)); ++ cur.use_dss2_fck = use_dss2_fck; ++ if (use_dss2_fck) { ++ cur.clkin = dss_clk_fck2; ++ cur.highfreq = 0; ++ } else { ++ cur.clkin = dispc_pclk_rate(); ++ if (cur.clkin < 32000000) ++ cur.highfreq = 0; ++ else ++ cur.highfreq = 1; ++ } ++ ++ /* no highfreq: 0.75MHz < Fint = clkin / regn < 2.1MHz */ ++ /* highfreq: 0.75MHz < Fint = clkin / (2*regn) < 2.1MHz */ ++ /* To reduce PLL lock time, keep Fint high (around 2 MHz) */ ++ for (cur.regn = 1; cur.regn < REGN_MAX; ++cur.regn) { ++ if (cur.highfreq == 0) ++ cur.fint = cur.clkin / cur.regn; ++ else ++ cur.fint = cur.clkin / (2 * cur.regn); ++ ++ if (cur.fint > FINT_MAX || cur.fint < FINT_MIN) ++ continue; ++ ++ /* DSIPHY(MHz) = (2 * regm / regn) * (clkin / (highfreq + 1)) */ ++ for (cur.regm = 1; cur.regm < REGM_MAX; ++cur.regm) { ++ unsigned long a, b; ++ ++ a = 2 * cur.regm * (cur.clkin/1000); ++ b = cur.regn * (cur.highfreq + 1); ++ cur.dsiphy = a / b * 1000; ++ ++ if (cur.dsiphy > 1800 * 1000 * 1000) ++ break; ++ ++ if (abs(cur.dsiphy - datafreq) < ++ abs(best.dsiphy - datafreq)) { ++ best = cur; ++ /* DSSDBG("best %ld\n", best.dsiphy); */ ++ } ++ ++ if (cur.dsiphy == datafreq) ++ goto found; ++ } ++ } ++found: ++ /* DSI1_PLL_FCLK (regm3) is not used. Set it to something sane. */ ++ best.regm3 = best.dsiphy / 48000000; ++ if (best.regm3 > REGM3_MAX) ++ best.regm3 = REGM3_MAX; ++ else if (best.regm3 == 0) ++ best.regm3 = 1; ++ best.dsi1_pll_fclk = best.dsiphy / best.regm3; ++ ++ /* DSI2_PLL_FCLK (regm4) is not used. Set it to something sane. */ ++ best.regm4 = best.dsiphy / 48000000; ++ if (best.regm4 > REGM4_MAX) ++ best.regm4 = REGM4_MAX; ++ else if (best.regm4 == 0) ++ best.regm4 = 1; ++ best.dsi2_pll_fclk = best.dsiphy / best.regm4; ++ ++ if (cinfo) ++ *cinfo = best; ++ ++ dsi.cache_clk_freq = clk_freq; ++ dsi.cache_req_pck = 0; ++ dsi.cache_cinfo = best; ++ ++ return 0; ++} ++ ++int dsi_pll_program(struct dsi_clock_info *cinfo) ++{ ++ int r = 0; ++ u32 l; ++ ++ DSSDBG("dsi_pll_program\n"); ++ ++ dsi.dsiphy = cinfo->dsiphy; ++ dsi.ddr_clk = dsi.dsiphy / 4; ++ dsi.dsi1_pll_fclk = cinfo->dsi1_pll_fclk; ++ dsi.dsi2_pll_fclk = cinfo->dsi2_pll_fclk; ++ ++ DSSDBG("DSI Fint %ld\n", cinfo->fint); ++ ++ DSSDBG("clkin (%s) rate %ld, highfreq %d\n", ++ cinfo->use_dss2_fck ? "dss2_fck" : "pclkfree", ++ cinfo->clkin, ++ cinfo->highfreq); ++ ++ /* DSIPHY == CLKIN4DDR */ ++ DSSDBG("DSIPHY = 2 * %d / %d * %lu / %d = %lu\n", ++ cinfo->regm, ++ cinfo->regn, ++ cinfo->clkin, ++ cinfo->highfreq + 1, ++ cinfo->dsiphy); ++ ++ DSSDBG("Data rate on 1 DSI lane %ld Mbps\n", ++ dsi.dsiphy / 1000 / 1000 / 2); ++ ++ DSSDBG("Clock lane freq %ld Hz\n", dsi.ddr_clk); ++ ++ DSSDBG("regm3 = %d, dsi1_pll_fclk = %lu\n", ++ cinfo->regm3, cinfo->dsi1_pll_fclk); ++ DSSDBG("regm4 = %d, dsi2_pll_fclk = %lu\n", ++ cinfo->regm4, cinfo->dsi2_pll_fclk); ++ ++ REG_FLD_MOD(DSI_PLL_CONTROL, 0, 0, 0); /* DSI_PLL_AUTOMODE = manual */ ++ ++ l = dsi_read_reg(DSI_PLL_CONFIGURATION1); ++ l = FLD_MOD(l, 1, 0, 0); /* DSI_PLL_STOPMODE */ ++ l = FLD_MOD(l, cinfo->regn - 1, 7, 1); /* DSI_PLL_REGN */ ++ l = FLD_MOD(l, cinfo->regm, 18, 8); /* DSI_PLL_REGM */ ++ l = FLD_MOD(l, cinfo->regm3 - 1, 22, 19); /* DSI_CLOCK_DIV */ ++ l = FLD_MOD(l, cinfo->regm4 - 1, 26, 23); /* DSIPROTO_CLOCK_DIV */ ++ dsi_write_reg(DSI_PLL_CONFIGURATION1, l); ++ ++ l = dsi_read_reg(DSI_PLL_CONFIGURATION2); ++ l = FLD_MOD(l, 7, 4, 1); /* DSI_PLL_FREQSEL */ ++ /* DSI_PLL_CLKSEL */ ++ l = FLD_MOD(l, cinfo->use_dss2_fck ? 0 : 1, 11, 11); ++ l = FLD_MOD(l, cinfo->highfreq, 12, 12); /* DSI_PLL_HIGHFREQ */ ++ l = FLD_MOD(l, 1, 13, 13); /* DSI_PLL_REFEN */ ++ l = FLD_MOD(l, 0, 14, 14); /* DSIPHY_CLKINEN */ ++ l = FLD_MOD(l, 1, 20, 20); /* DSI_HSDIVBYPASS */ ++ dsi_write_reg(DSI_PLL_CONFIGURATION2, l); ++ ++ REG_FLD_MOD(DSI_PLL_GO, 1, 0, 0); /* DSI_PLL_GO */ ++ ++ if (wait_for_bit_change(DSI_PLL_GO, 0, 0) != 0) { ++ DSSERR("dsi pll go bit not going down.\n"); ++ r = -EIO; ++ goto err; ++ } ++ ++ if (wait_for_bit_change(DSI_PLL_STATUS, 1, 1) != 1) { ++ DSSERR("cannot lock PLL\n"); ++ r = -EIO; ++ goto err; ++ } ++ ++ dsi.pll_locked = 1; ++ ++ l = dsi_read_reg(DSI_PLL_CONFIGURATION2); ++ l = FLD_MOD(l, 0, 0, 0); /* DSI_PLL_IDLE */ ++ l = FLD_MOD(l, 0, 5, 5); /* DSI_PLL_PLLLPMODE */ ++ l = FLD_MOD(l, 0, 6, 6); /* DSI_PLL_LOWCURRSTBY */ ++ l = FLD_MOD(l, 0, 7, 7); /* DSI_PLL_TIGHTPHASELOCK */ ++ l = FLD_MOD(l, 0, 8, 8); /* DSI_PLL_DRIFTGUARDEN */ ++ l = FLD_MOD(l, 0, 10, 9); /* DSI_PLL_LOCKSEL */ ++ l = FLD_MOD(l, 1, 13, 13); /* DSI_PLL_REFEN */ ++ l = FLD_MOD(l, 1, 14, 14); /* DSIPHY_CLKINEN */ ++ l = FLD_MOD(l, 0, 15, 15); /* DSI_BYPASSEN */ ++ l = FLD_MOD(l, 1, 16, 16); /* DSS_CLOCK_EN */ ++ l = FLD_MOD(l, 0, 17, 17); /* DSS_CLOCK_PWDN */ ++ l = FLD_MOD(l, 1, 18, 18); /* DSI_PROTO_CLOCK_EN */ ++ l = FLD_MOD(l, 0, 19, 19); /* DSI_PROTO_CLOCK_PWDN */ ++ l = FLD_MOD(l, 0, 20, 20); /* DSI_HSDIVBYPASS */ ++ dsi_write_reg(DSI_PLL_CONFIGURATION2, l); ++ ++ DSSDBG("PLL config done\n"); ++err: ++ return r; ++} ++ ++int dsi_pll_init(bool enable_hsclk, bool enable_hsdiv) ++{ ++ int r = 0; ++ enum dsi_pll_power_state pwstate; ++ struct dispc_clock_info cinfo; ++ ++ DSSDBG("PLL init\n"); ++ ++ enable_clocks(1); ++ dsi_enable_pll_clock(1); ++ ++ /* XXX this should be calculated depending on the screen size, ++ * required framerate and DSI speed. ++ * For now 48MHz is enough for 864x480@60 with 360Mbps/lane ++ * with two lanes */ ++ r = dispc_calc_clock_div(1, 48 * 1000 * 1000, &cinfo); ++ if (r) ++ goto err0; ++ ++ r = dispc_set_clock_div(&cinfo); ++ if (r) { ++ DSSERR("Failed to set basic clocks\n"); ++ goto err0; ++ } ++ ++ r = regulator_enable(dsi.vdds_dsi_reg); ++ if (r) ++ goto err0; ++ ++ /* XXX PLL does not come out of reset without this... */ ++ dispc_pck_free_enable(1); ++ ++ if (wait_for_bit_change(DSI_PLL_STATUS, 0, 1) != 1) { ++ DSSERR("PLL not coming out of reset.\n"); ++ r = -ENODEV; ++ goto err1; ++ } ++ ++ /* XXX ... but if left on, we get problems when planes do not ++ * fill the whole display. No idea about this */ ++ dispc_pck_free_enable(0); ++ ++ if (enable_hsclk && enable_hsdiv) ++ pwstate = DSI_PLL_POWER_ON_ALL; ++ else if (enable_hsclk) ++ pwstate = DSI_PLL_POWER_ON_HSCLK; ++ else if (enable_hsdiv) ++ pwstate = DSI_PLL_POWER_ON_DIV; ++ else ++ pwstate = DSI_PLL_POWER_OFF; ++ ++ r = dsi_pll_power(pwstate); ++ ++ if (r) ++ goto err1; ++ ++ DSSDBG("PLL init done\n"); ++ ++ return 0; ++err1: ++ regulator_disable(dsi.vdds_dsi_reg); ++err0: ++ enable_clocks(0); ++ dsi_enable_pll_clock(0); ++ return r; ++} ++ ++void dsi_pll_uninit(void) ++{ ++ enable_clocks(0); ++ dsi_enable_pll_clock(0); ++ ++ dsi.pll_locked = 0; ++ dsi_pll_power(DSI_PLL_POWER_OFF); ++ regulator_disable(dsi.vdds_dsi_reg); ++ DSSDBG("PLL uninit done\n"); ++} ++ ++unsigned long dsi_get_dsi1_pll_rate(void) ++{ ++ return dsi.dsi1_pll_fclk; ++} ++ ++unsigned long dsi_get_dsi2_pll_rate(void) ++{ ++ return dsi.dsi2_pll_fclk; ++} ++ ++void dsi_dump_clocks(struct seq_file *s) ++{ ++ int clksel; ++ ++ enable_clocks(1); ++ ++ clksel = REG_GET(DSI_PLL_CONFIGURATION2, 11, 11); ++ ++ seq_printf(s, "- dsi -\n"); ++ ++ seq_printf(s, "dsi fclk source = %s\n", ++ dss_get_dsi_clk_source() == 0 ? ++ "dss1_alwon_fclk" : "dsi2_pll_fclk"); ++ ++ seq_printf(s, "dsi pll source = %s\n", ++ clksel == 0 ? ++ "dss2_alwon_fclk" : "pclkfree"); ++ ++ seq_printf(s, "DSIPHY\t\t%lu\nDDR_CLK\t\t%lu\n", ++ dsi.dsiphy, dsi.ddr_clk); ++ ++ seq_printf(s, "dsi1_pll_fck\t%lu (%s)\n" ++ "dsi2_pll_fck\t%lu (%s)\n", ++ dsi.dsi1_pll_fclk, ++ dss_get_dispc_clk_source() == 0 ? "off" : "on", ++ dsi.dsi2_pll_fclk, ++ dss_get_dsi_clk_source() == 0 ? "off" : "on"); ++ ++ enable_clocks(0); ++} ++ ++void dsi_dump_regs(struct seq_file *s) ++{ ++#define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, dsi_read_reg(r)) ++ ++ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); ++ ++ DUMPREG(DSI_REVISION); ++ DUMPREG(DSI_SYSCONFIG); ++ DUMPREG(DSI_SYSSTATUS); ++ DUMPREG(DSI_IRQSTATUS); ++ DUMPREG(DSI_IRQENABLE); ++ DUMPREG(DSI_CTRL); ++ DUMPREG(DSI_COMPLEXIO_CFG1); ++ DUMPREG(DSI_COMPLEXIO_IRQ_STATUS); ++ DUMPREG(DSI_COMPLEXIO_IRQ_ENABLE); ++ DUMPREG(DSI_CLK_CTRL); ++ DUMPREG(DSI_TIMING1); ++ DUMPREG(DSI_TIMING2); ++ DUMPREG(DSI_VM_TIMING1); ++ DUMPREG(DSI_VM_TIMING2); ++ DUMPREG(DSI_VM_TIMING3); ++ DUMPREG(DSI_CLK_TIMING); ++ DUMPREG(DSI_TX_FIFO_VC_SIZE); ++ DUMPREG(DSI_RX_FIFO_VC_SIZE); ++ DUMPREG(DSI_COMPLEXIO_CFG2); ++ DUMPREG(DSI_RX_FIFO_VC_FULLNESS); ++ DUMPREG(DSI_VM_TIMING4); ++ DUMPREG(DSI_TX_FIFO_VC_EMPTINESS); ++ DUMPREG(DSI_VM_TIMING5); ++ DUMPREG(DSI_VM_TIMING6); ++ DUMPREG(DSI_VM_TIMING7); ++ DUMPREG(DSI_STOPCLK_TIMING); ++ ++ DUMPREG(DSI_VC_CTRL(0)); ++ DUMPREG(DSI_VC_TE(0)); ++ DUMPREG(DSI_VC_LONG_PACKET_HEADER(0)); ++ DUMPREG(DSI_VC_LONG_PACKET_PAYLOAD(0)); ++ DUMPREG(DSI_VC_SHORT_PACKET_HEADER(0)); ++ DUMPREG(DSI_VC_IRQSTATUS(0)); ++ DUMPREG(DSI_VC_IRQENABLE(0)); ++ ++ DUMPREG(DSI_VC_CTRL(1)); ++ DUMPREG(DSI_VC_TE(1)); ++ DUMPREG(DSI_VC_LONG_PACKET_HEADER(1)); ++ DUMPREG(DSI_VC_LONG_PACKET_PAYLOAD(1)); ++ DUMPREG(DSI_VC_SHORT_PACKET_HEADER(1)); ++ DUMPREG(DSI_VC_IRQSTATUS(1)); ++ DUMPREG(DSI_VC_IRQENABLE(1)); ++ ++ DUMPREG(DSI_VC_CTRL(2)); ++ DUMPREG(DSI_VC_TE(2)); ++ DUMPREG(DSI_VC_LONG_PACKET_HEADER(2)); ++ DUMPREG(DSI_VC_LONG_PACKET_PAYLOAD(2)); ++ DUMPREG(DSI_VC_SHORT_PACKET_HEADER(2)); ++ DUMPREG(DSI_VC_IRQSTATUS(2)); ++ DUMPREG(DSI_VC_IRQENABLE(2)); ++ ++ DUMPREG(DSI_VC_CTRL(3)); ++ DUMPREG(DSI_VC_TE(3)); ++ DUMPREG(DSI_VC_LONG_PACKET_HEADER(3)); ++ DUMPREG(DSI_VC_LONG_PACKET_PAYLOAD(3)); ++ DUMPREG(DSI_VC_SHORT_PACKET_HEADER(3)); ++ DUMPREG(DSI_VC_IRQSTATUS(3)); ++ DUMPREG(DSI_VC_IRQENABLE(3)); ++ ++ DUMPREG(DSI_DSIPHY_CFG0); ++ DUMPREG(DSI_DSIPHY_CFG1); ++ DUMPREG(DSI_DSIPHY_CFG2); ++ DUMPREG(DSI_DSIPHY_CFG5); ++ ++ DUMPREG(DSI_PLL_CONTROL); ++ DUMPREG(DSI_PLL_STATUS); ++ DUMPREG(DSI_PLL_GO); ++ DUMPREG(DSI_PLL_CONFIGURATION1); ++ DUMPREG(DSI_PLL_CONFIGURATION2); ++ ++ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); ++#undef DUMPREG ++} ++ ++enum dsi_complexio_power_state { ++ DSI_COMPLEXIO_POWER_OFF = 0x0, ++ DSI_COMPLEXIO_POWER_ON = 0x1, ++ DSI_COMPLEXIO_POWER_ULPS = 0x2, ++}; ++ ++static int dsi_complexio_power(enum dsi_complexio_power_state state) ++{ ++ int t = 0; ++ ++ /* PWR_CMD */ ++ REG_FLD_MOD(DSI_COMPLEXIO_CFG1, state, 28, 27); ++ ++ /* PWR_STATUS */ ++ while (FLD_GET(dsi_read_reg(DSI_COMPLEXIO_CFG1), 26, 25) != state) { ++ udelay(1); ++ if (t++ > 1000) { ++ DSSERR("failed to set complexio power state to " ++ "%d\n", state); ++ return -ENODEV; ++ } ++ } ++ ++ return 0; ++} ++ ++static void dsi_complexio_config(struct omap_dss_device *dssdev) ++{ ++ u32 r; ++ ++ int clk_lane = dssdev->phy.dsi.clk_lane; ++ int data1_lane = dssdev->phy.dsi.data1_lane; ++ int data2_lane = dssdev->phy.dsi.data2_lane; ++ int clk_pol = dssdev->phy.dsi.clk_pol; ++ int data1_pol = dssdev->phy.dsi.data1_pol; ++ int data2_pol = dssdev->phy.dsi.data2_pol; ++ ++ r = dsi_read_reg(DSI_COMPLEXIO_CFG1); ++ r = FLD_MOD(r, clk_lane, 2, 0); ++ r = FLD_MOD(r, clk_pol, 3, 3); ++ r = FLD_MOD(r, data1_lane, 6, 4); ++ r = FLD_MOD(r, data1_pol, 7, 7); ++ r = FLD_MOD(r, data2_lane, 10, 8); ++ r = FLD_MOD(r, data2_pol, 11, 11); ++ dsi_write_reg(DSI_COMPLEXIO_CFG1, r); ++ ++ /* The configuration of the DSI complex I/O (number of data lanes, ++ position, differential order) should not be changed while ++ DSS.DSI_CLK_CRTRL[20] LP_CLK_ENABLE bit is set to 1. In order for ++ the hardware to take into account a new configuration of the complex ++ I/O (done in DSS.DSI_COMPLEXIO_CFG1 register), it is recommended to ++ follow this sequence: First set the DSS.DSI_CTRL[0] IF_EN bit to 1, ++ then reset the DSS.DSI_CTRL[0] IF_EN to 0, then set ++ DSS.DSI_CLK_CTRL[20] LP_CLK_ENABLE to 1 and finally set again the ++ DSS.DSI_CTRL[0] IF_EN bit to 1. If the sequence is not followed, the ++ DSI complex I/O configuration is unknown. */ ++ ++ /* ++ REG_FLD_MOD(DSI_CTRL, 1, 0, 0); ++ REG_FLD_MOD(DSI_CTRL, 0, 0, 0); ++ REG_FLD_MOD(DSI_CLK_CTRL, 1, 20, 20); ++ REG_FLD_MOD(DSI_CTRL, 1, 0, 0); ++ */ ++} ++ ++static inline unsigned ns2ddr(unsigned ns) ++{ ++ /* convert time in ns to ddr ticks, rounding up */ ++ return (ns * (dsi.ddr_clk/1000/1000) + 999) / 1000; ++} ++ ++static inline unsigned ddr2ns(unsigned ddr) ++{ ++ return ddr * 1000 * 1000 / (dsi.ddr_clk / 1000); ++} ++ ++static void dsi_complexio_timings(void) ++{ ++ u32 r; ++ u32 ths_prepare, ths_prepare_ths_zero, ths_trail, ths_exit; ++ u32 tlpx_half, tclk_trail, tclk_zero; ++ u32 tclk_prepare; ++ ++ /* calculate timings */ ++ ++ /* 1 * DDR_CLK = 2 * UI */ ++ ++ /* min 40ns + 4*UI max 85ns + 6*UI */ ++ ths_prepare = ns2ddr(70) + 2; ++ ++ /* min 145ns + 10*UI */ ++ ths_prepare_ths_zero = ns2ddr(175) + 2; ++ ++ /* min max(8*UI, 60ns+4*UI) */ ++ ths_trail = ns2ddr(60) + 5; ++ ++ /* min 100ns */ ++ ths_exit = ns2ddr(145); ++ ++ /* tlpx min 50n */ ++ tlpx_half = ns2ddr(25); ++ ++ /* min 60ns */ ++ tclk_trail = ns2ddr(60) + 2; ++ ++ /* min 38ns, max 95ns */ ++ tclk_prepare = ns2ddr(65); ++ ++ /* min tclk-prepare + tclk-zero = 300ns */ ++ tclk_zero = ns2ddr(260); ++ ++ DSSDBG("ths_prepare %u (%uns), ths_prepare_ths_zero %u (%uns)\n", ++ ths_prepare, ddr2ns(ths_prepare), ++ ths_prepare_ths_zero, ddr2ns(ths_prepare_ths_zero)); ++ DSSDBG("ths_trail %u (%uns), ths_exit %u (%uns)\n", ++ ths_trail, ddr2ns(ths_trail), ++ ths_exit, ddr2ns(ths_exit)); ++ ++ DSSDBG("tlpx_half %u (%uns), tclk_trail %u (%uns), " ++ "tclk_zero %u (%uns)\n", ++ tlpx_half, ddr2ns(tlpx_half), ++ tclk_trail, ddr2ns(tclk_trail), ++ tclk_zero, ddr2ns(tclk_zero)); ++ DSSDBG("tclk_prepare %u (%uns)\n", ++ tclk_prepare, ddr2ns(tclk_prepare)); ++ ++ /* program timings */ ++ ++ r = dsi_read_reg(DSI_DSIPHY_CFG0); ++ r = FLD_MOD(r, ths_prepare, 31, 24); ++ r = FLD_MOD(r, ths_prepare_ths_zero, 23, 16); ++ r = FLD_MOD(r, ths_trail, 15, 8); ++ r = FLD_MOD(r, ths_exit, 7, 0); ++ dsi_write_reg(DSI_DSIPHY_CFG0, r); ++ ++ r = dsi_read_reg(DSI_DSIPHY_CFG1); ++ r = FLD_MOD(r, tlpx_half, 22, 16); ++ r = FLD_MOD(r, tclk_trail, 15, 8); ++ r = FLD_MOD(r, tclk_zero, 7, 0); ++ dsi_write_reg(DSI_DSIPHY_CFG1, r); ++ ++ r = dsi_read_reg(DSI_DSIPHY_CFG2); ++ r = FLD_MOD(r, tclk_prepare, 7, 0); ++ dsi_write_reg(DSI_DSIPHY_CFG2, r); ++} ++ ++ ++static int dsi_complexio_init(struct omap_dss_device *dssdev) ++{ ++ int r = 0; ++ ++ DSSDBG("dsi_complexio_init\n"); ++ ++ /* CIO_CLK_ICG, enable L3 clk to CIO */ ++ REG_FLD_MOD(DSI_CLK_CTRL, 1, 14, 14); ++ ++ /* A dummy read using the SCP interface to any DSIPHY register is ++ * required after DSIPHY reset to complete the reset of the DSI complex ++ * I/O. */ ++ dsi_read_reg(DSI_DSIPHY_CFG5); ++ ++ if (wait_for_bit_change(DSI_DSIPHY_CFG5, 30, 1) != 1) { ++ DSSERR("ComplexIO PHY not coming out of reset.\n"); ++ r = -ENODEV; ++ goto err; ++ } ++ ++ dsi_complexio_config(dssdev); ++ ++ r = dsi_complexio_power(DSI_COMPLEXIO_POWER_ON); ++ ++ if (r) ++ goto err; ++ ++ if (wait_for_bit_change(DSI_COMPLEXIO_CFG1, 29, 1) != 1) { ++ DSSERR("ComplexIO not coming out of reset.\n"); ++ r = -ENODEV; ++ goto err; ++ } ++ ++ if (wait_for_bit_change(DSI_COMPLEXIO_CFG1, 21, 1) != 1) { ++ DSSERR("ComplexIO LDO power down.\n"); ++ r = -ENODEV; ++ goto err; ++ } ++ ++ dsi_complexio_timings(); ++ ++ /* ++ The configuration of the DSI complex I/O (number of data lanes, ++ position, differential order) should not be changed while ++ DSS.DSI_CLK_CRTRL[20] LP_CLK_ENABLE bit is set to 1. For the ++ hardware to recognize a new configuration of the complex I/O (done ++ in DSS.DSI_COMPLEXIO_CFG1 register), it is recommended to follow ++ this sequence: First set the DSS.DSI_CTRL[0] IF_EN bit to 1, next ++ reset the DSS.DSI_CTRL[0] IF_EN to 0, then set DSS.DSI_CLK_CTRL[20] ++ LP_CLK_ENABLE to 1, and finally, set again the DSS.DSI_CTRL[0] IF_EN ++ bit to 1. If the sequence is not followed, the DSi complex I/O ++ configuration is undetermined. ++ */ ++ dsi_if_enable(1); ++ dsi_if_enable(0); ++ REG_FLD_MOD(DSI_CLK_CTRL, 1, 20, 20); /* LP_CLK_ENABLE */ ++ dsi_if_enable(1); ++ dsi_if_enable(0); ++ ++ DSSDBG("CIO init done\n"); ++err: ++ return r; ++} ++ ++static void dsi_complexio_uninit(void) ++{ ++ dsi_complexio_power(DSI_COMPLEXIO_POWER_OFF); ++} ++ ++static int _dsi_wait_reset(void) ++{ ++ int i = 0; ++ ++ while (REG_GET(DSI_SYSSTATUS, 0, 0) == 0) { ++ if (i++ > 5) { ++ DSSERR("soft reset failed\n"); ++ return -ENODEV; ++ } ++ udelay(1); ++ } ++ ++ return 0; ++} ++ ++static int _dsi_reset(void) ++{ ++ /* Soft reset */ ++ REG_FLD_MOD(DSI_SYSCONFIG, 1, 1, 1); ++ return _dsi_wait_reset(); ++} ++ ++ ++static void dsi_config_tx_fifo(enum fifo_size size1, enum fifo_size size2, ++ enum fifo_size size3, enum fifo_size size4) ++{ ++ u32 r = 0; ++ int add = 0; ++ int i; ++ ++ dsi.vc[0].fifo_size = size1; ++ dsi.vc[1].fifo_size = size2; ++ dsi.vc[2].fifo_size = size3; ++ dsi.vc[3].fifo_size = size4; ++ ++ for (i = 0; i < 4; i++) { ++ u8 v; ++ int size = dsi.vc[i].fifo_size; ++ ++ if (add + size > 4) { ++ DSSERR("Illegal FIFO configuration\n"); ++ BUG(); ++ } ++ ++ v = FLD_VAL(add, 2, 0) | FLD_VAL(size, 7, 4); ++ r |= v << (8 * i); ++ /*DSSDBG("TX FIFO vc %d: size %d, add %d\n", i, size, add); */ ++ add += size; ++ } ++ ++ dsi_write_reg(DSI_TX_FIFO_VC_SIZE, r); ++} ++ ++static void dsi_config_rx_fifo(enum fifo_size size1, enum fifo_size size2, ++ enum fifo_size size3, enum fifo_size size4) ++{ ++ u32 r = 0; ++ int add = 0; ++ int i; ++ ++ dsi.vc[0].fifo_size = size1; ++ dsi.vc[1].fifo_size = size2; ++ dsi.vc[2].fifo_size = size3; ++ dsi.vc[3].fifo_size = size4; ++ ++ for (i = 0; i < 4; i++) { ++ u8 v; ++ int size = dsi.vc[i].fifo_size; ++ ++ if (add + size > 4) { ++ DSSERR("Illegal FIFO configuration\n"); ++ BUG(); ++ } ++ ++ v = FLD_VAL(add, 2, 0) | FLD_VAL(size, 7, 4); ++ r |= v << (8 * i); ++ /*DSSDBG("RX FIFO vc %d: size %d, add %d\n", i, size, add); */ ++ add += size; ++ } ++ ++ dsi_write_reg(DSI_RX_FIFO_VC_SIZE, r); ++} ++ ++static int dsi_force_tx_stop_mode_io(void) ++{ ++ u32 r; ++ ++ r = dsi_read_reg(DSI_TIMING1); ++ r = FLD_MOD(r, 1, 15, 15); /* FORCE_TX_STOP_MODE_IO */ ++ dsi_write_reg(DSI_TIMING1, r); ++ ++ if (wait_for_bit_change(DSI_TIMING1, 15, 0) != 0) { ++ DSSERR("TX_STOP bit not going down\n"); ++ return -EIO; ++ } ++ ++ return 0; ++} ++ ++static void dsi_vc_print_status(int channel) ++{ ++ u32 r; ++ ++ r = dsi_read_reg(DSI_VC_CTRL(channel)); ++ DSSDBG("vc %d: TX_FIFO_NOT_EMPTY %d, BTA_EN %d, VC_BUSY %d, " ++ "TX_FIFO_FULL %d, RX_FIFO_NOT_EMPTY %d, ", ++ channel, ++ FLD_GET(r, 5, 5), ++ FLD_GET(r, 6, 6), ++ FLD_GET(r, 15, 15), ++ FLD_GET(r, 16, 16), ++ FLD_GET(r, 20, 20)); ++ ++ r = dsi_read_reg(DSI_TX_FIFO_VC_EMPTINESS); ++ DSSDBG("EMPTINESS %d\n", (r >> (8 * channel)) & 0xff); ++} ++ ++static int dsi_vc_enable(int channel, bool enable) ++{ ++ if (dsi.update_mode != OMAP_DSS_UPDATE_AUTO) ++ DSSDBG("dsi_vc_enable channel %d, enable %d\n", ++ channel, enable); ++ ++ enable = enable ? 1 : 0; ++ ++ REG_FLD_MOD(DSI_VC_CTRL(channel), enable, 0, 0); ++ ++ if (wait_for_bit_change(DSI_VC_CTRL(channel), 0, enable) != enable) { ++ DSSERR("Failed to set dsi_vc_enable to %d\n", enable); ++ return -EIO; ++ } ++ ++ return 0; ++} ++ ++static void dsi_vc_initial_config(int channel) ++{ ++ u32 r; ++ ++ DSSDBGF("%d", channel); ++ ++ r = dsi_read_reg(DSI_VC_CTRL(channel)); ++ ++ if (FLD_GET(r, 15, 15)) /* VC_BUSY */ ++ DSSERR("VC(%d) busy when trying to configure it!\n", ++ channel); ++ ++ r = FLD_MOD(r, 0, 1, 1); /* SOURCE, 0 = L4 */ ++ r = FLD_MOD(r, 0, 2, 2); /* BTA_SHORT_EN */ ++ r = FLD_MOD(r, 0, 3, 3); /* BTA_LONG_EN */ ++ r = FLD_MOD(r, 0, 4, 4); /* MODE, 0 = command */ ++ r = FLD_MOD(r, 1, 7, 7); /* CS_TX_EN */ ++ r = FLD_MOD(r, 1, 8, 8); /* ECC_TX_EN */ ++ r = FLD_MOD(r, 0, 9, 9); /* MODE_SPEED, high speed on/off */ ++ ++ r = FLD_MOD(r, 4, 29, 27); /* DMA_RX_REQ_NB = no dma */ ++ r = FLD_MOD(r, 4, 23, 21); /* DMA_TX_REQ_NB = no dma */ ++ ++ dsi_write_reg(DSI_VC_CTRL(channel), r); ++ ++ dsi.vc[channel].mode = DSI_VC_MODE_L4; ++} ++ ++static void dsi_vc_config_l4(int channel) ++{ ++ if (dsi.vc[channel].mode == DSI_VC_MODE_L4) ++ return; ++ ++ DSSDBGF("%d", channel); ++ ++ dsi_vc_enable(channel, 0); ++ ++ if (REG_GET(DSI_VC_CTRL(channel), 15, 15)) /* VC_BUSY */ ++ DSSERR("vc(%d) busy when trying to config for L4\n", channel); ++ ++ REG_FLD_MOD(DSI_VC_CTRL(channel), 0, 1, 1); /* SOURCE, 0 = L4 */ ++ ++ dsi_vc_enable(channel, 1); ++ ++ dsi.vc[channel].mode = DSI_VC_MODE_L4; ++} ++ ++static void dsi_vc_config_vp(int channel) ++{ ++ if (dsi.vc[channel].mode == DSI_VC_MODE_VP) ++ return; ++ ++ DSSDBGF("%d", channel); ++ ++ dsi_vc_enable(channel, 0); ++ ++ if (REG_GET(DSI_VC_CTRL(channel), 15, 15)) /* VC_BUSY */ ++ DSSERR("vc(%d) busy when trying to config for VP\n", channel); ++ ++ REG_FLD_MOD(DSI_VC_CTRL(channel), 1, 1, 1); /* SOURCE, 1 = video port */ ++ ++ dsi_vc_enable(channel, 1); ++ ++ dsi.vc[channel].mode = DSI_VC_MODE_VP; ++} ++ ++ ++static void dsi_vc_enable_hs(int channel, bool enable) ++{ ++ DSSDBG("dsi_vc_enable_hs(%d, %d)\n", channel, enable); ++ ++ dsi_vc_enable(channel, 0); ++ dsi_if_enable(0); ++ ++ REG_FLD_MOD(DSI_VC_CTRL(channel), enable, 9, 9); ++ ++ dsi_vc_enable(channel, 1); ++ dsi_if_enable(1); ++ ++ dsi_force_tx_stop_mode_io(); ++} ++ ++static void dsi_vc_flush_long_data(int channel) ++{ ++ while (REG_GET(DSI_VC_CTRL(channel), 20, 20)) { ++ u32 val; ++ val = dsi_read_reg(DSI_VC_SHORT_PACKET_HEADER(channel)); ++ DSSDBG("\t\tb1 %#02x b2 %#02x b3 %#02x b4 %#02x\n", ++ (val >> 0) & 0xff, ++ (val >> 8) & 0xff, ++ (val >> 16) & 0xff, ++ (val >> 24) & 0xff); ++ } ++} ++ ++static void dsi_show_rx_ack_with_err(u16 err) ++{ ++ DSSERR("\tACK with ERROR (%#x):\n", err); ++ if (err & (1 << 0)) ++ DSSERR("\t\tSoT Error\n"); ++ if (err & (1 << 1)) ++ DSSERR("\t\tSoT Sync Error\n"); ++ if (err & (1 << 2)) ++ DSSERR("\t\tEoT Sync Error\n"); ++ if (err & (1 << 3)) ++ DSSERR("\t\tEscape Mode Entry Command Error\n"); ++ if (err & (1 << 4)) ++ DSSERR("\t\tLP Transmit Sync Error\n"); ++ if (err & (1 << 5)) ++ DSSERR("\t\tHS Receive Timeout Error\n"); ++ if (err & (1 << 6)) ++ DSSERR("\t\tFalse Control Error\n"); ++ if (err & (1 << 7)) ++ DSSERR("\t\t(reserved7)\n"); ++ if (err & (1 << 8)) ++ DSSERR("\t\tECC Error, single-bit (corrected)\n"); ++ if (err & (1 << 9)) ++ DSSERR("\t\tECC Error, multi-bit (not corrected)\n"); ++ if (err & (1 << 10)) ++ DSSERR("\t\tChecksum Error\n"); ++ if (err & (1 << 11)) ++ DSSERR("\t\tData type not recognized\n"); ++ if (err & (1 << 12)) ++ DSSERR("\t\tInvalid VC ID\n"); ++ if (err & (1 << 13)) ++ DSSERR("\t\tInvalid Transmission Length\n"); ++ if (err & (1 << 14)) ++ DSSERR("\t\t(reserved14)\n"); ++ if (err & (1 << 15)) ++ DSSERR("\t\tDSI Protocol Violation\n"); ++} ++ ++static u16 dsi_vc_flush_receive_data(int channel) ++{ ++ /* RX_FIFO_NOT_EMPTY */ ++ while (REG_GET(DSI_VC_CTRL(channel), 20, 20)) { ++ u32 val; ++ u8 dt; ++ val = dsi_read_reg(DSI_VC_SHORT_PACKET_HEADER(channel)); ++ DSSDBG("\trawval %#08x\n", val); ++ dt = FLD_GET(val, 5, 0); ++ if (dt == DSI_DT_RX_ACK_WITH_ERR) { ++ u16 err = FLD_GET(val, 23, 8); ++ dsi_show_rx_ack_with_err(err); ++ } else if (dt == DSI_DT_RX_SHORT_READ_1) { ++ DSSDBG("\tDCS short response, 1 byte: %#x\n", ++ FLD_GET(val, 23, 8)); ++ } else if (dt == DSI_DT_RX_SHORT_READ_2) { ++ DSSDBG("\tDCS short response, 2 byte: %#x\n", ++ FLD_GET(val, 23, 8)); ++ } else if (dt == DSI_DT_RX_DCS_LONG_READ) { ++ DSSDBG("\tDCS long response, len %d\n", ++ FLD_GET(val, 23, 8)); ++ dsi_vc_flush_long_data(channel); ++ } else { ++ DSSERR("\tunknown datatype 0x%02x\n", dt); ++ } ++ } ++ return 0; ++} ++ ++static int dsi_vc_send_bta(int channel) ++{ ++ if (dsi.update_mode != OMAP_DSS_UPDATE_AUTO && ++ (dsi.debug_write || dsi.debug_read)) ++ DSSDBG("dsi_vc_send_bta %d\n", channel); ++ ++ WARN_ON(!mutex_is_locked(&dsi.bus_lock)); ++ ++ if (REG_GET(DSI_VC_CTRL(channel), 20, 20)) { /* RX_FIFO_NOT_EMPTY */ ++ DSSERR("rx fifo not empty when sending BTA, dumping data:\n"); ++ dsi_vc_flush_receive_data(channel); ++ } ++ ++ REG_FLD_MOD(DSI_VC_CTRL(channel), 1, 6, 6); /* BTA_EN */ ++ ++ return 0; ++} ++ ++int dsi_vc_send_bta_sync(int channel) ++{ ++ int r = 0; ++ u32 err; ++ ++ INIT_COMPLETION(dsi.bta_completion); ++ ++ dsi_vc_enable_bta_irq(channel); ++ ++ r = dsi_vc_send_bta(channel); ++ if (r) ++ goto err; ++ ++ if (wait_for_completion_timeout(&dsi.bta_completion, ++ msecs_to_jiffies(500)) == 0) { ++ DSSERR("Failed to receive BTA\n"); ++ r = -EIO; ++ goto err; ++ } ++ ++ err = dsi_get_errors(); ++ if (err) { ++ DSSERR("Error while sending BTA: %x\n", err); ++ r = -EIO; ++ goto err; ++ } ++err: ++ dsi_vc_disable_bta_irq(channel); ++ ++ return r; ++} ++EXPORT_SYMBOL(dsi_vc_send_bta_sync); ++ ++static inline void dsi_vc_write_long_header(int channel, u8 data_type, ++ u16 len, u8 ecc) ++{ ++ u32 val; ++ u8 data_id; ++ ++ WARN_ON(!mutex_is_locked(&dsi.bus_lock)); ++ ++ /*data_id = data_type | channel << 6; */ ++ data_id = data_type | dsi.vc[channel].dest_per << 6; ++ ++ val = FLD_VAL(data_id, 7, 0) | FLD_VAL(len, 23, 8) | ++ FLD_VAL(ecc, 31, 24); ++ ++ dsi_write_reg(DSI_VC_LONG_PACKET_HEADER(channel), val); ++} ++ ++static inline void dsi_vc_write_long_payload(int channel, ++ u8 b1, u8 b2, u8 b3, u8 b4) ++{ ++ u32 val; ++ ++ val = b4 << 24 | b3 << 16 | b2 << 8 | b1 << 0; ++ ++/* DSSDBG("\twriting %02x, %02x, %02x, %02x (%#010x)\n", ++ b1, b2, b3, b4, val); */ ++ ++ dsi_write_reg(DSI_VC_LONG_PACKET_PAYLOAD(channel), val); ++} ++ ++static int dsi_vc_send_long(int channel, u8 data_type, u8 *data, u16 len, ++ u8 ecc) ++{ ++ /*u32 val; */ ++ int i; ++ u8 *p; ++ int r = 0; ++ u8 b1, b2, b3, b4; ++ ++ if (dsi.debug_write) ++ DSSDBG("dsi_vc_send_long, %d bytes\n", len); ++ ++ /* len + header */ ++ if (dsi.vc[channel].fifo_size * 32 * 4 < len + 4) { ++ DSSERR("unable to send long packet: packet too long.\n"); ++ return -EINVAL; ++ } ++ ++ dsi_vc_config_l4(channel); ++ ++ dsi_vc_write_long_header(channel, data_type, len, ecc); ++ ++ /*dsi_vc_print_status(0); */ ++ ++ p = data; ++ for (i = 0; i < len >> 2; i++) { ++ if (dsi.debug_write) ++ DSSDBG("\tsending full packet %d\n", i); ++ /*dsi_vc_print_status(0); */ ++ ++ b1 = *p++; ++ b2 = *p++; ++ b3 = *p++; ++ b4 = *p++; ++ ++ dsi_vc_write_long_payload(channel, b1, b2, b3, b4); ++ } ++ ++ i = len % 4; ++ if (i) { ++ b1 = 0; b2 = 0; b3 = 0; ++ ++ if (dsi.debug_write) ++ DSSDBG("\tsending remainder bytes %d\n", i); ++ ++ switch (i) { ++ case 3: ++ b1 = *p++; ++ b2 = *p++; ++ b3 = *p++; ++ break; ++ case 2: ++ b1 = *p++; ++ b2 = *p++; ++ break; ++ case 1: ++ b1 = *p++; ++ break; ++ } ++ ++ dsi_vc_write_long_payload(channel, b1, b2, b3, 0); ++ } ++ ++ return r; ++} ++ ++static int dsi_vc_send_short(int channel, u8 data_type, u16 data, u8 ecc) ++{ ++ u32 r; ++ u8 data_id; ++ ++ WARN_ON(!mutex_is_locked(&dsi.bus_lock)); ++ ++ if (dsi.debug_write) ++ DSSDBG("dsi_vc_send_short(ch%d, dt %#x, b1 %#x, b2 %#x)\n", ++ channel, ++ data_type, data & 0xff, (data >> 8) & 0xff); ++ ++ dsi_vc_config_l4(channel); ++ ++ if (FLD_GET(dsi_read_reg(DSI_VC_CTRL(channel)), 16, 16)) { ++ DSSERR("ERROR FIFO FULL, aborting transfer\n"); ++ return -EINVAL; ++ } ++ ++ data_id = data_type | channel << 6; ++ ++ r = (data_id << 0) | (data << 8) | (ecc << 24); ++ ++ dsi_write_reg(DSI_VC_SHORT_PACKET_HEADER(channel), r); ++ ++ return 0; ++} ++ ++int dsi_vc_send_null(int channel) ++{ ++ u8 nullpkg[] = {0, 0, 0, 0}; ++ return dsi_vc_send_long(0, DSI_DT_NULL_PACKET, nullpkg, 4, 0); ++} ++EXPORT_SYMBOL(dsi_vc_send_null); ++ ++int dsi_vc_dcs_write_nosync(int channel, u8 *data, int len) ++{ ++ int r; ++ ++ BUG_ON(len == 0); ++ ++ if (len == 1) { ++ r = dsi_vc_send_short(channel, DSI_DT_DCS_SHORT_WRITE_0, ++ data[0], 0); ++ } else if (len == 2) { ++ r = dsi_vc_send_short(channel, DSI_DT_DCS_SHORT_WRITE_1, ++ data[0] | (data[1] << 8), 0); ++ } else { ++ /* 0x39 = DCS Long Write */ ++ r = dsi_vc_send_long(channel, DSI_DT_DCS_LONG_WRITE, ++ data, len, 0); ++ } ++ ++ return r; ++} ++EXPORT_SYMBOL(dsi_vc_dcs_write_nosync); ++ ++int dsi_vc_dcs_write(int channel, u8 *data, int len) ++{ ++ int r; ++ ++ r = dsi_vc_dcs_write_nosync(channel, data, len); ++ if (r) ++ return r; ++ ++ r = dsi_vc_send_bta_sync(channel); ++ ++ return r; ++} ++EXPORT_SYMBOL(dsi_vc_dcs_write); ++ ++int dsi_vc_dcs_read(int channel, u8 dcs_cmd, u8 *buf, int buflen) ++{ ++ u32 val; ++ u8 dt; ++ int r; ++ ++ if (dsi.debug_read) ++ DSSDBG("dsi_vc_dcs_read(ch%d, dcs_cmd %u)\n", channel, dcs_cmd); ++ ++ r = dsi_vc_send_short(channel, DSI_DT_DCS_READ, dcs_cmd, 0); ++ if (r) ++ return r; ++ ++ r = dsi_vc_send_bta_sync(channel); ++ if (r) ++ return r; ++ ++ /* RX_FIFO_NOT_EMPTY */ ++ if (REG_GET(DSI_VC_CTRL(channel), 20, 20) == 0) { ++ DSSERR("RX fifo empty when trying to read.\n"); ++ return -EIO; ++ } ++ ++ val = dsi_read_reg(DSI_VC_SHORT_PACKET_HEADER(channel)); ++ if (dsi.debug_read) ++ DSSDBG("\theader: %08x\n", val); ++ dt = FLD_GET(val, 5, 0); ++ if (dt == DSI_DT_RX_ACK_WITH_ERR) { ++ u16 err = FLD_GET(val, 23, 8); ++ dsi_show_rx_ack_with_err(err); ++ return -EIO; ++ ++ } else if (dt == DSI_DT_RX_SHORT_READ_1) { ++ u8 data = FLD_GET(val, 15, 8); ++ if (dsi.debug_read) ++ DSSDBG("\tDCS short response, 1 byte: %02x\n", data); ++ ++ if (buflen < 1) ++ return -EIO; ++ ++ buf[0] = data; ++ ++ return 1; ++ } else if (dt == DSI_DT_RX_SHORT_READ_2) { ++ u16 data = FLD_GET(val, 23, 8); ++ if (dsi.debug_read) ++ DSSDBG("\tDCS short response, 2 byte: %04x\n", data); ++ ++ if (buflen < 2) ++ return -EIO; ++ ++ buf[0] = data & 0xff; ++ buf[1] = (data >> 8) & 0xff; ++ ++ return 2; ++ } else if (dt == DSI_DT_RX_DCS_LONG_READ) { ++ int w; ++ int len = FLD_GET(val, 23, 8); ++ if (dsi.debug_read) ++ DSSDBG("\tDCS long response, len %d\n", len); ++ ++ if (len > buflen) ++ return -EIO; ++ ++ /* two byte checksum ends the packet, not included in len */ ++ for (w = 0; w < len + 2;) { ++ int b; ++ val = dsi_read_reg(DSI_VC_SHORT_PACKET_HEADER(channel)); ++ if (dsi.debug_read) ++ DSSDBG("\t\t%02x %02x %02x %02x\n", ++ (val >> 0) & 0xff, ++ (val >> 8) & 0xff, ++ (val >> 16) & 0xff, ++ (val >> 24) & 0xff); ++ ++ for (b = 0; b < 4; ++b) { ++ if (w < len) ++ buf[w] = (val >> (b * 8)) & 0xff; ++ /* we discard the 2 byte checksum */ ++ ++w; ++ } ++ } ++ ++ return len; ++ ++ } else { ++ DSSERR("\tunknown datatype 0x%02x\n", dt); ++ return -EIO; ++ } ++} ++EXPORT_SYMBOL(dsi_vc_dcs_read); ++ ++ ++int dsi_vc_set_max_rx_packet_size(int channel, u16 len) ++{ ++ return dsi_vc_send_short(channel, DSI_DT_SET_MAX_RET_PKG_SIZE, ++ len, 0); ++} ++EXPORT_SYMBOL(dsi_vc_set_max_rx_packet_size); ++ ++ ++static int dsi_set_lp_rx_timeout(int ns, int x4, int x16) ++{ ++ u32 r; ++ unsigned long fck; ++ int ticks; ++ ++ /* ticks in DSI_FCK */ ++ ++ fck = dsi_fclk_rate(); ++ ticks = (fck / 1000 / 1000) * ns / 1000; ++ ++ if (ticks > 0x1fff) { ++ DSSERR("LP_TX_TO too high\n"); ++ return -EINVAL; ++ } ++ ++ r = dsi_read_reg(DSI_TIMING2); ++ r = FLD_MOD(r, 1, 15, 15); /* LP_RX_TO */ ++ r = FLD_MOD(r, x16, 14, 14); /* LP_RX_TO_X16 */ ++ r = FLD_MOD(r, x4, 13, 13); /* LP_RX_TO_X4 */ ++ r = FLD_MOD(r, ticks, 12, 0); /* LP_RX_COUNTER */ ++ dsi_write_reg(DSI_TIMING2, r); ++ ++ DSSDBG("LP_RX_TO %ld ns (%#x ticks)\n", ++ (ticks * (x16 ? 16 : 1) * (x4 ? 4 : 1) * 1000) / ++ (fck / 1000 / 1000), ++ ticks); ++ ++ return 0; ++} ++ ++static int dsi_set_ta_timeout(int ns, int x8, int x16) ++{ ++ u32 r; ++ unsigned long fck; ++ int ticks; ++ ++ /* ticks in DSI_FCK */ ++ ++ fck = dsi_fclk_rate(); ++ ticks = (fck / 1000 / 1000) * ns / 1000; ++ ++ if (ticks > 0x1fff) { ++ DSSERR("TA_TO too high\n"); ++ return -EINVAL; ++ } ++ ++ r = dsi_read_reg(DSI_TIMING1); ++ r = FLD_MOD(r, 1, 31, 31); /* TA_TO */ ++ r = FLD_MOD(r, x16, 30, 30); /* TA_TO_X16 */ ++ r = FLD_MOD(r, x8, 29, 29); /* TA_TO_X8 */ ++ r = FLD_MOD(r, ticks, 28, 16); /* TA_TO_COUNTER */ ++ dsi_write_reg(DSI_TIMING1, r); ++ ++ DSSDBG("TA_TO %ld ns (%#x ticks)\n", ++ (ticks * (x16 ? 16 : 1) * (x8 ? 8 : 1) * 1000) / ++ (fck / 1000 / 1000), ++ ticks); ++ ++ return 0; ++} ++ ++static int dsi_set_stop_state_counter(int ns, int x4, int x16) ++{ ++ u32 r; ++ unsigned long fck; ++ int ticks; ++ ++ /* ticks in DSI_FCK */ ++ ++ fck = dsi_fclk_rate(); ++ ticks = (fck / 1000 / 1000) * ns / 1000; ++ ++ if (ticks > 0x1fff) { ++ DSSERR("STOP_STATE_COUNTER_IO too high\n"); ++ return -EINVAL; ++ } ++ ++ r = dsi_read_reg(DSI_TIMING1); ++ r = FLD_MOD(r, 1, 15, 15); /* FORCE_TX_STOP_MODE_IO */ ++ r = FLD_MOD(r, x16, 14, 14); /* STOP_STATE_X16_IO */ ++ r = FLD_MOD(r, x4, 13, 13); /* STOP_STATE_X4_IO */ ++ r = FLD_MOD(r, ticks, 12, 0); /* STOP_STATE_COUNTER_IO */ ++ dsi_write_reg(DSI_TIMING1, r); ++ ++ DSSDBG("STOP_STATE_COUNTER %ld ns (%#x ticks)\n", ++ (ticks * (x16 ? 16 : 1) * (x4 ? 4 : 1) * 1000) / ++ (fck / 1000 / 1000), ++ ticks); ++ ++ return 0; ++} ++ ++static int dsi_set_hs_tx_timeout(int ns, int x4, int x16) ++{ ++ u32 r; ++ unsigned long fck; ++ int ticks; ++ ++ /* ticks in TxByteClkHS */ ++ ++ fck = dsi.ddr_clk / 4; ++ ticks = (fck / 1000 / 1000) * ns / 1000; ++ ++ if (ticks > 0x1fff) { ++ DSSERR("HS_TX_TO too high\n"); ++ return -EINVAL; ++ } ++ ++ r = dsi_read_reg(DSI_TIMING2); ++ r = FLD_MOD(r, 1, 31, 31); /* HS_TX_TO */ ++ r = FLD_MOD(r, x16, 30, 30); /* HS_TX_TO_X16 */ ++ r = FLD_MOD(r, x4, 29, 29); /* HS_TX_TO_X8 (4 really) */ ++ r = FLD_MOD(r, ticks, 28, 16); /* HS_TX_TO_COUNTER */ ++ dsi_write_reg(DSI_TIMING2, r); ++ ++ DSSDBG("HS_TX_TO %ld ns (%#x ticks)\n", ++ (ticks * (x16 ? 16 : 1) * (x4 ? 4 : 1) * 1000) / ++ (fck / 1000 / 1000), ++ ticks); ++ ++ return 0; ++} ++static int dsi_proto_config(struct omap_dss_device *dssdev) ++{ ++ u32 r; ++ int buswidth = 0; ++ int div; ++ ++ dsi_config_tx_fifo(DSI_FIFO_SIZE_128, ++ DSI_FIFO_SIZE_0, ++ DSI_FIFO_SIZE_0, ++ DSI_FIFO_SIZE_0); ++ ++ dsi_config_rx_fifo(DSI_FIFO_SIZE_128, ++ DSI_FIFO_SIZE_0, ++ DSI_FIFO_SIZE_0, ++ DSI_FIFO_SIZE_0); ++ ++ /* XXX what values for the timeouts? */ ++ dsi_set_stop_state_counter(1000, 0, 0); ++ ++ dsi_set_ta_timeout(50000, 1, 1); ++ ++ /* 3000ns * 16 */ ++ dsi_set_lp_rx_timeout(3000, 0, 1); ++ ++ /* 10000ns * 4 */ ++ dsi_set_hs_tx_timeout(10000, 1, 0); ++ ++ switch (dssdev->ctrl.pixel_size) { ++ case 16: ++ buswidth = 0; ++ break; ++ case 18: ++ buswidth = 1; ++ break; ++ case 24: ++ buswidth = 2; ++ break; ++ default: ++ BUG(); ++ } ++ ++ r = dsi_read_reg(DSI_CTRL); ++ r = FLD_MOD(r, 1, 1, 1); /* CS_RX_EN */ ++ r = FLD_MOD(r, 1, 2, 2); /* ECC_RX_EN */ ++ r = FLD_MOD(r, 1, 3, 3); /* TX_FIFO_ARBITRATION */ ++ ++ div = dispc_lclk_rate() / dispc_pclk_rate(); ++ r = FLD_MOD(r, div == 2 ? 0 : 1, 4, 4); /* VP_CLK_RATIO */ ++ r = FLD_MOD(r, buswidth, 7, 6); /* VP_DATA_BUS_WIDTH */ ++ r = FLD_MOD(r, 0, 8, 8); /* VP_CLK_POL */ ++ r = FLD_MOD(r, 2, 13, 12); /* LINE_BUFFER, 2 lines */ ++ r = FLD_MOD(r, 1, 14, 14); /* TRIGGER_RESET_MODE */ ++ r = FLD_MOD(r, 1, 19, 19); /* EOT_ENABLE */ ++ r = FLD_MOD(r, 1, 24, 24); /* DCS_CMD_ENABLE */ ++ r = FLD_MOD(r, 0, 25, 25); /* DCS_CMD_CODE, 1=start, 0=continue */ ++ ++ dsi_write_reg(DSI_CTRL, r); ++ ++ dsi_vc_initial_config(0); ++ ++ /* set all vc targets to peripheral 0 */ ++ dsi.vc[0].dest_per = 0; ++ dsi.vc[1].dest_per = 0; ++ dsi.vc[2].dest_per = 0; ++ dsi.vc[3].dest_per = 0; ++ ++ return 0; ++} ++ ++static void dsi_proto_timings(struct omap_dss_device *dssdev) ++{ ++ unsigned tlpx, tclk_zero, tclk_prepare, tclk_trail; ++ unsigned tclk_pre, tclk_post; ++ unsigned ths_prepare, ths_prepare_ths_zero, ths_zero; ++ unsigned ths_trail, ths_exit; ++ unsigned ddr_clk_pre, ddr_clk_post; ++ unsigned enter_hs_mode_lat, exit_hs_mode_lat; ++ unsigned ths_eot; ++ u32 r; ++ ++ r = dsi_read_reg(DSI_DSIPHY_CFG0); ++ ths_prepare = FLD_GET(r, 31, 24); ++ ths_prepare_ths_zero = FLD_GET(r, 23, 16); ++ ths_zero = ths_prepare_ths_zero - ths_prepare; ++ ths_trail = FLD_GET(r, 15, 8); ++ ths_exit = FLD_GET(r, 7, 0); ++ ++ r = dsi_read_reg(DSI_DSIPHY_CFG1); ++ tlpx = FLD_GET(r, 22, 16) * 2; ++ tclk_trail = FLD_GET(r, 15, 8); ++ tclk_zero = FLD_GET(r, 7, 0); ++ ++ r = dsi_read_reg(DSI_DSIPHY_CFG2); ++ tclk_prepare = FLD_GET(r, 7, 0); ++ ++ /* min 8*UI */ ++ tclk_pre = 20; ++ /* min 60ns + 52*UI */ ++ tclk_post = ns2ddr(60) + 26; ++ ++ /* ths_eot is 2 for 2 datalanes and 4 for 1 datalane */ ++ if (dssdev->phy.dsi.data1_lane != 0 && ++ dssdev->phy.dsi.data2_lane != 0) ++ ths_eot = 2; ++ else ++ ths_eot = 4; ++ ++ ddr_clk_pre = DIV_ROUND_UP(tclk_pre + tlpx + tclk_zero + tclk_prepare, ++ 4); ++ ddr_clk_post = DIV_ROUND_UP(tclk_post + tclk_trail, 4) + ths_eot; ++ ++ BUG_ON(ddr_clk_pre == 0 || ddr_clk_pre > 255); ++ BUG_ON(ddr_clk_post == 0 || ddr_clk_post > 255); ++ ++ r = dsi_read_reg(DSI_CLK_TIMING); ++ r = FLD_MOD(r, ddr_clk_pre, 15, 8); ++ r = FLD_MOD(r, ddr_clk_post, 7, 0); ++ dsi_write_reg(DSI_CLK_TIMING, r); ++ ++ DSSDBG("ddr_clk_pre %u, ddr_clk_post %u\n", ++ ddr_clk_pre, ++ ddr_clk_post); ++ ++ enter_hs_mode_lat = 1 + DIV_ROUND_UP(tlpx, 4) + ++ DIV_ROUND_UP(ths_prepare, 4) + ++ DIV_ROUND_UP(ths_zero + 3, 4); ++ ++ exit_hs_mode_lat = DIV_ROUND_UP(ths_trail + ths_exit, 4) + 1 + ths_eot; ++ ++ r = FLD_VAL(enter_hs_mode_lat, 31, 16) | ++ FLD_VAL(exit_hs_mode_lat, 15, 0); ++ dsi_write_reg(DSI_VM_TIMING7, r); ++ ++ DSSDBG("enter_hs_mode_lat %u, exit_hs_mode_lat %u\n", ++ enter_hs_mode_lat, exit_hs_mode_lat); ++} ++ ++ ++#define DSI_DECL_VARS \ ++ int __dsi_cb = 0; u32 __dsi_cv = 0; ++ ++#define DSI_FLUSH(ch) \ ++ if (__dsi_cb > 0) { \ ++ /*DSSDBG("sending long packet %#010x\n", __dsi_cv);*/ \ ++ dsi_write_reg(DSI_VC_LONG_PACKET_PAYLOAD(ch), __dsi_cv); \ ++ __dsi_cb = __dsi_cv = 0; \ ++ } ++ ++#define DSI_PUSH(ch, data) \ ++ do { \ ++ __dsi_cv |= (data) << (__dsi_cb * 8); \ ++ /*DSSDBG("cv = %#010x, cb = %d\n", __dsi_cv, __dsi_cb);*/ \ ++ if (++__dsi_cb > 3) \ ++ DSI_FLUSH(ch); \ ++ } while (0) ++ ++static int dsi_update_screen_l4(struct omap_dss_device *dssdev, ++ int x, int y, int w, int h) ++{ ++ /* Note: supports only 24bit colors in 32bit container */ ++ int first = 1; ++ int fifo_stalls = 0; ++ int max_dsi_packet_size; ++ int max_data_per_packet; ++ int max_pixels_per_packet; ++ int pixels_left; ++ int bytespp = dssdev->ctrl.pixel_size / 8; ++ int scr_width; ++ u32 __iomem *data; ++ int start_offset; ++ int horiz_inc; ++ int current_x; ++ struct omap_overlay *ovl; ++ ++ debug_irq = 0; ++ ++ DSSDBG("dsi_update_screen_l4 (%d,%d %dx%d)\n", ++ x, y, w, h); ++ ++ ovl = dssdev->manager->overlays[0]; ++ ++ if (ovl->info.color_mode != OMAP_DSS_COLOR_RGB24U) ++ return -EINVAL; ++ ++ if (dssdev->ctrl.pixel_size != 24) ++ return -EINVAL; ++ ++ scr_width = ovl->info.screen_width; ++ data = ovl->info.vaddr; ++ ++ start_offset = scr_width * y + x; ++ horiz_inc = scr_width - w; ++ current_x = x; ++ ++ /* We need header(4) + DCSCMD(1) + pixels(numpix*bytespp) bytes ++ * in fifo */ ++ ++ /* When using CPU, max long packet size is TX buffer size */ ++ max_dsi_packet_size = dsi.vc[0].fifo_size * 32 * 4; ++ ++ /* we seem to get better perf if we divide the tx fifo to half, ++ and while the other half is being sent, we fill the other half ++ max_dsi_packet_size /= 2; */ ++ ++ max_data_per_packet = max_dsi_packet_size - 4 - 1; ++ ++ max_pixels_per_packet = max_data_per_packet / bytespp; ++ ++ DSSDBG("max_pixels_per_packet %d\n", max_pixels_per_packet); ++ ++ pixels_left = w * h; ++ ++ DSSDBG("total pixels %d\n", pixels_left); ++ ++ data += start_offset; ++ ++ while (pixels_left > 0) { ++ /* 0x2c = write_memory_start */ ++ /* 0x3c = write_memory_continue */ ++ u8 dcs_cmd = first ? 0x2c : 0x3c; ++ int pixels; ++ DSI_DECL_VARS; ++ first = 0; ++ ++#if 1 ++ /* using fifo not empty */ ++ /* TX_FIFO_NOT_EMPTY */ ++ while (FLD_GET(dsi_read_reg(DSI_VC_CTRL(0)), 5, 5)) { ++ udelay(1); ++ fifo_stalls++; ++ if (fifo_stalls > 0xfffff) { ++ DSSERR("fifo stalls overflow, pixels left %d\n", ++ pixels_left); ++ dsi_if_enable(0); ++ return -EIO; ++ } ++ } ++#elif 1 ++ /* using fifo emptiness */ ++ while ((REG_GET(DSI_TX_FIFO_VC_EMPTINESS, 7, 0)+1)*4 < ++ max_dsi_packet_size) { ++ fifo_stalls++; ++ if (fifo_stalls > 0xfffff) { ++ DSSERR("fifo stalls overflow, pixels left %d\n", ++ pixels_left); ++ dsi_if_enable(0); ++ return -EIO; ++ } ++ } ++#else ++ while ((REG_GET(DSI_TX_FIFO_VC_EMPTINESS, 7, 0)+1)*4 == 0) { ++ fifo_stalls++; ++ if (fifo_stalls > 0xfffff) { ++ DSSERR("fifo stalls overflow, pixels left %d\n", ++ pixels_left); ++ dsi_if_enable(0); ++ return -EIO; ++ } ++ } ++#endif ++ pixels = min(max_pixels_per_packet, pixels_left); ++ ++ pixels_left -= pixels; ++ ++ dsi_vc_write_long_header(0, DSI_DT_DCS_LONG_WRITE, ++ 1 + pixels * bytespp, 0); ++ ++ DSI_PUSH(0, dcs_cmd); ++ ++ while (pixels-- > 0) { ++ u32 pix = __raw_readl(data++); ++ ++ DSI_PUSH(0, (pix >> 16) & 0xff); ++ DSI_PUSH(0, (pix >> 8) & 0xff); ++ DSI_PUSH(0, (pix >> 0) & 0xff); ++ ++ current_x++; ++ if (current_x == x+w) { ++ current_x = x; ++ data += horiz_inc; ++ } ++ } ++ ++ DSI_FLUSH(0); ++ } ++ ++ return 0; ++} ++ ++static void dsi_update_screen_dispc(struct omap_dss_device *dssdev, ++ u16 x, u16 y, u16 w, u16 h) ++{ ++ int bytespp = dssdev->ctrl.pixel_size / 8; ++ int len; ++ int total_len; ++ int packet_payload; ++ int packet_len; ++ u32 l; ++ bool use_te_trigger; ++ const int channel = 0; ++ ++ use_te_trigger = dsi.te_enabled && !dsi.use_ext_te; ++ ++ if (dsi.update_mode != OMAP_DSS_UPDATE_AUTO) ++ DSSDBG("dsi_update_screen_dispc(%d,%d %dx%d)\n", ++ x, y, w, h); ++ ++ len = w * h * bytespp; ++ ++ /* XXX: one packet could be longer, I think? Line buffer is ++ * 1024 x 24bits, but we have to put DCS cmd there also. ++ * 1023 * 3 should work, but causes strange color effects. */ ++ packet_payload = min(w, (u16)1020) * bytespp; ++ ++ packet_len = packet_payload + 1; /* 1 byte for DCS cmd */ ++ total_len = (len / packet_payload) * packet_len; ++ ++ if (len % packet_payload) ++ total_len += (len % packet_payload) + 1; ++ ++ if (0) ++ dsi_vc_print_status(1); ++ ++ l = FLD_VAL(total_len, 23, 0); /* TE_SIZE */ ++ dsi_write_reg(DSI_VC_TE(channel), l); ++ ++ dsi_vc_write_long_header(channel, DSI_DT_DCS_LONG_WRITE, packet_len, 0); ++ ++ if (use_te_trigger) ++ l = FLD_MOD(l, 1, 30, 30); /* TE_EN */ ++ else ++ l = FLD_MOD(l, 1, 31, 31); /* TE_START */ ++ dsi_write_reg(DSI_VC_TE(channel), l); ++ ++ /* We put SIDLEMODE to no-idle for the duration of the transfer, ++ * because DSS interrupts are not capable of waking up the CPU and the ++ * framedone interrupt could be delayed for quite a long time. I think ++ * the same goes for any DSS interrupts, but for some reason I have not ++ * seen the problem anywhere else than here. ++ */ ++ dispc_disable_sidle(); ++ ++ dss_start_update(dssdev); ++ ++ if (use_te_trigger) { ++ /* disable LP_RX_TO, so that we can receive TE. Time to wait ++ * for TE is longer than the timer allows */ ++ REG_FLD_MOD(DSI_TIMING2, 0, 15, 15); /* LP_RX_TO */ ++ ++ dsi_vc_send_bta(channel); ++ } ++} ++ ++static void dsi_framedone_irq_callback(void *data, u32 mask) ++{ ++ /* Note: We get FRAMEDONE when DISPC has finished sending pixels and ++ * turns itself off. However, DSI still has the pixels in its buffers, ++ * and is sending the data. ++ */ ++ ++ /* SIDLEMODE back to smart-idle */ ++ dispc_enable_sidle(); ++ ++ dsi.framedone_received = true; ++ wake_up(&dsi.waitqueue); ++} ++ ++static void dsi_set_update_region(struct omap_dss_device *dssdev, ++ u16 x, u16 y, u16 w, u16 h) ++{ ++ spin_lock(&dsi.update_lock); ++ if (dsi.update_region.dirty) { ++ dsi.update_region.x = min(x, dsi.update_region.x); ++ dsi.update_region.y = min(y, dsi.update_region.y); ++ dsi.update_region.w = max(w, dsi.update_region.w); ++ dsi.update_region.h = max(h, dsi.update_region.h); ++ } else { ++ dsi.update_region.x = x; ++ dsi.update_region.y = y; ++ dsi.update_region.w = w; ++ dsi.update_region.h = h; ++ } ++ ++ dsi.update_region.device = dssdev; ++ dsi.update_region.dirty = true; ++ ++ spin_unlock(&dsi.update_lock); ++ ++} ++ ++static void dsi_start_auto_update(struct omap_dss_device *dssdev) ++{ ++ u16 w, h; ++ int i; ++ ++ DSSDBG("starting auto update\n"); ++ ++ /* In automatic mode the overlay settings are applied like on DPI/SDI. ++ * Mark the overlays dirty, so that we get the overlays configured, as ++ * manual mode has left them in bad shape after config partia planes */ ++ for (i = 0; i < omap_dss_get_num_overlays(); ++i) { ++ struct omap_overlay *ovl; ++ ovl = omap_dss_get_overlay(i); ++ if (ovl->manager == dssdev->manager) ++ ovl->info_dirty = true; ++ } ++ dssdev->manager->apply(dssdev->manager); ++ ++ dssdev->get_resolution(dssdev, &w, &h); ++ ++ dsi_set_update_region(dssdev, 0, 0, w, h); ++ ++ dsi_perf_mark_start_auto(); ++ ++ wake_up(&dsi.waitqueue); ++} ++ ++static int dsi_set_te(struct omap_dss_device *dssdev, bool enable) ++{ ++ int r; ++ r = dssdev->driver->enable_te(dssdev, enable); ++ /* XXX for some reason, DSI TE breaks if we don't wait here. ++ * Panel bug? Needs more studying */ ++ msleep(100); ++ return r; ++} ++ ++static void dsi_handle_framedone(void) ++{ ++ int r; ++ const int channel = 0; ++ bool use_te_trigger; ++ ++ use_te_trigger = dsi.te_enabled && !dsi.use_ext_te; ++ ++ if (dsi.update_mode != OMAP_DSS_UPDATE_AUTO) ++ DSSDBG("FRAMEDONE\n"); ++ ++ if (use_te_trigger) { ++ /* enable LP_RX_TO again after the TE */ ++ REG_FLD_MOD(DSI_TIMING2, 1, 15, 15); /* LP_RX_TO */ ++ } ++ ++ /* Send BTA after the frame. We need this for the TE to work, as TE ++ * trigger is only sent for BTAs without preceding packet. Thus we need ++ * to BTA after the pixel packets so that next BTA will cause TE ++ * trigger. ++ * ++ * This is not needed when TE is not in use, but we do it anyway to ++ * make sure that the transfer has been completed. It would be more ++ * optimal, but more complex, to wait only just before starting next ++ * transfer. */ ++ r = dsi_vc_send_bta_sync(channel); ++ if (r) ++ DSSERR("BTA after framedone failed\n"); ++ ++#ifdef CONFIG_OMAP2_DSS_FAKE_VSYNC ++ dispc_fake_vsync_irq(); ++#endif ++} ++ ++static int dsi_update_thread(void *data) ++{ ++ unsigned long timeout; ++ struct omap_dss_device *device; ++ u16 x, y, w, h; ++ ++ while (1) { ++ bool sched; ++ ++ wait_event_interruptible(dsi.waitqueue, ++ dsi.update_mode == OMAP_DSS_UPDATE_AUTO || ++ (dsi.update_mode == OMAP_DSS_UPDATE_MANUAL && ++ dsi.update_region.dirty == true) || ++ kthread_should_stop()); ++ ++ if (kthread_should_stop()) ++ break; ++ ++ dsi_bus_lock(); ++ ++ if (dsi.update_mode == OMAP_DSS_UPDATE_DISABLED || ++ kthread_should_stop()) { ++ dsi_bus_unlock(); ++ break; ++ } ++ ++ dsi_perf_mark_setup(); ++ ++ if (dsi.update_region.dirty) { ++ spin_lock(&dsi.update_lock); ++ dsi.active_update_region = dsi.update_region; ++ dsi.update_region.dirty = false; ++ spin_unlock(&dsi.update_lock); ++ } ++ ++ device = dsi.active_update_region.device; ++ x = dsi.active_update_region.x; ++ y = dsi.active_update_region.y; ++ w = dsi.active_update_region.w; ++ h = dsi.active_update_region.h; ++ ++ if (device->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) { ++ ++ if (dsi.update_mode == OMAP_DSS_UPDATE_MANUAL) { ++ dss_setup_partial_planes(device, ++ &x, &y, &w, &h); ++#if 1 ++ /* XXX there seems to be a bug in this driver ++ * or OMAP hardware. Some updates with certain ++ * widths and x coordinates fail. These widths ++ * are always odd, so "fix" it here for now */ ++ if (w & 1) { ++ u16 dw, dh; ++ device->get_resolution(device, ++ &dw, &dh); ++ if (x + w == dw) ++ x &= ~1; ++ ++w; ++ ++ dss_setup_partial_planes(device, ++ &x, &y, &w, &h); ++ } ++#endif ++ } ++ ++ dispc_set_lcd_size(w, h); ++ } ++ ++ if (dsi.active_update_region.dirty) { ++ dsi.active_update_region.dirty = false; ++ /* XXX TODO we don't need to send the coords, if they ++ * are the same that are already programmed to the ++ * panel. That should speed up manual update a bit */ ++ device->driver->setup_update(device, x, y, w, h); ++ } ++ ++ dsi_perf_mark_start(); ++ ++ if (device->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) { ++ dsi_vc_config_vp(0); ++ ++ if (dsi.te_enabled && dsi.use_ext_te) ++ device->driver->wait_for_te(device); ++ ++ dsi.framedone_received = false; ++ ++ dsi_update_screen_dispc(device, x, y, w, h); ++ ++ /* wait for framedone */ ++ timeout = msecs_to_jiffies(1000); ++ timeout = wait_event_timeout(dsi.waitqueue, ++ dsi.framedone_received == true, ++ timeout); ++ ++ if (timeout == 0) { ++ DSSERR("framedone timeout\n"); ++ DSSERR("failed update %d,%d %dx%d\n", ++ x, y, w, h); ++ ++ dispc_enable_sidle(); ++ dispc_enable_lcd_out(0); ++ } else { ++ dsi_handle_framedone(); ++ dsi_perf_show("DISPC"); ++ } ++ } else { ++ dsi_update_screen_l4(device, x, y, w, h); ++ dsi_perf_show("L4"); ++ } ++ ++ sched = atomic_read(&dsi.bus_lock.count) < 0; ++ ++ complete_all(&dsi.update_completion); ++ ++ dsi_bus_unlock(); ++ ++ /* XXX We need to give others chance to get the bus lock. Is ++ * there a better way for this? */ ++ if (dsi.update_mode == OMAP_DSS_UPDATE_AUTO && sched) ++ schedule_timeout_interruptible(1); ++ } ++ ++ DSSDBG("update thread exiting\n"); ++ ++ return 0; ++} ++ ++ ++ ++/* Display funcs */ ++ ++static int dsi_display_init_dispc(struct omap_dss_device *dssdev) ++{ ++ int r; ++ ++ r = omap_dispc_register_isr(dsi_framedone_irq_callback, NULL, ++ DISPC_IRQ_FRAMEDONE); ++ if (r) { ++ DSSERR("can't get FRAMEDONE irq\n"); ++ return r; ++ } ++ ++ dispc_set_lcd_display_type(OMAP_DSS_LCD_DISPLAY_TFT); ++ ++ dispc_set_parallel_interface_mode(OMAP_DSS_PARALLELMODE_DSI); ++ dispc_enable_fifohandcheck(1); ++ ++ dispc_set_tft_data_lines(dssdev->ctrl.pixel_size); ++ ++ { ++ struct omap_video_timings timings = { ++ .hsw = 1, ++ .hfp = 1, ++ .hbp = 1, ++ .vsw = 1, ++ .vfp = 0, ++ .vbp = 0, ++ }; ++ ++ dispc_set_lcd_timings(&timings); ++ } ++ ++ return 0; ++} ++ ++static void dsi_display_uninit_dispc(struct omap_dss_device *dssdev) ++{ ++ omap_dispc_unregister_isr(dsi_framedone_irq_callback, NULL, ++ DISPC_IRQ_FRAMEDONE); ++} ++ ++static int dsi_display_init_dsi(struct omap_dss_device *dssdev) ++{ ++ struct dsi_clock_info cinfo; ++ int r; ++ ++ _dsi_print_reset_status(); ++ ++ r = dsi_pll_init(1, 0); ++ if (r) ++ goto err0; ++ ++ r = dsi_pll_calc_ddrfreq(dssdev->phy.dsi.ddr_clk_hz, &cinfo); ++ if (r) ++ goto err1; ++ ++ r = dsi_pll_program(&cinfo); ++ if (r) ++ goto err1; ++ ++ DSSDBG("PLL OK\n"); ++ ++ r = dsi_complexio_init(dssdev); ++ if (r) ++ goto err1; ++ ++ _dsi_print_reset_status(); ++ ++ dsi_proto_timings(dssdev); ++ dsi_set_lp_clk_divisor(dssdev); ++ ++ if (1) ++ _dsi_print_reset_status(); ++ ++ r = dsi_proto_config(dssdev); ++ if (r) ++ goto err2; ++ ++ /* enable interface */ ++ dsi_vc_enable(0, 1); ++ dsi_if_enable(1); ++ dsi_force_tx_stop_mode_io(); ++ ++ if (dssdev->driver->enable) { ++ r = dssdev->driver->enable(dssdev); ++ if (r) ++ goto err3; ++ } ++ ++ /* enable high-speed after initial config */ ++ dsi_vc_enable_hs(0, 1); ++ ++ return 0; ++err3: ++ dsi_if_enable(0); ++err2: ++ dsi_complexio_uninit(); ++err1: ++ dsi_pll_uninit(); ++err0: ++ return r; ++} ++ ++static void dsi_display_uninit_dsi(struct omap_dss_device *dssdev) ++{ ++ if (dssdev->driver->disable) ++ dssdev->driver->disable(dssdev); ++ ++ dsi_complexio_uninit(); ++ dsi_pll_uninit(); ++} ++ ++static int dsi_core_init(void) ++{ ++ /* Autoidle */ ++ REG_FLD_MOD(DSI_SYSCONFIG, 1, 0, 0); ++ ++ /* ENWAKEUP */ ++ REG_FLD_MOD(DSI_SYSCONFIG, 1, 2, 2); ++ ++ /* SIDLEMODE smart-idle */ ++ REG_FLD_MOD(DSI_SYSCONFIG, 2, 4, 3); ++ ++ _dsi_initialize_irq(); ++ ++ return 0; ++} ++ ++static int dsi_display_enable(struct omap_dss_device *dssdev) ++{ ++ int r = 0; ++ ++ DSSDBG("dsi_display_enable\n"); ++ ++ mutex_lock(&dsi.lock); ++ dsi_bus_lock(); ++ ++ r = omap_dss_start_device(dssdev); ++ if (r) { ++ DSSERR("failed to start device\n"); ++ goto err0; ++ } ++ ++ if (dssdev->state != OMAP_DSS_DISPLAY_DISABLED) { ++ DSSERR("dssdev already enabled\n"); ++ r = -EINVAL; ++ goto err1; ++ } ++ ++ enable_clocks(1); ++ dsi_enable_pll_clock(1); ++ ++ r = _dsi_reset(); ++ if (r) ++ goto err2; ++ ++ dsi_core_init(); ++ ++ r = dsi_display_init_dispc(dssdev); ++ if (r) ++ goto err2; ++ ++ r = dsi_display_init_dsi(dssdev); ++ if (r) ++ goto err3; ++ ++ dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; ++ ++ dsi.use_ext_te = dssdev->phy.dsi.ext_te; ++ r = dsi_set_te(dssdev, dsi.te_enabled); ++ if (r) ++ goto err3; ++ ++ dsi.update_mode = dsi.user_update_mode; ++ if (dsi.update_mode == OMAP_DSS_UPDATE_AUTO) ++ dsi_start_auto_update(dssdev); ++ ++ dsi_bus_unlock(); ++ mutex_unlock(&dsi.lock); ++ ++ return 0; ++ ++err3: ++ dsi_display_uninit_dispc(dssdev); ++err2: ++ enable_clocks(0); ++ dsi_enable_pll_clock(0); ++err1: ++ omap_dss_stop_device(dssdev); ++err0: ++ dsi_bus_unlock(); ++ mutex_unlock(&dsi.lock); ++ DSSDBG("dsi_display_enable FAILED\n"); ++ return r; ++} ++ ++static void dsi_display_disable(struct omap_dss_device *dssdev) ++{ ++ DSSDBG("dsi_display_disable\n"); ++ ++ mutex_lock(&dsi.lock); ++ dsi_bus_lock(); ++ ++ if (dssdev->state == OMAP_DSS_DISPLAY_DISABLED || ++ dssdev->state == OMAP_DSS_DISPLAY_SUSPENDED) ++ goto end; ++ ++ dsi.update_mode = OMAP_DSS_UPDATE_DISABLED; ++ dssdev->state = OMAP_DSS_DISPLAY_DISABLED; ++ ++ dsi_display_uninit_dispc(dssdev); ++ ++ dsi_display_uninit_dsi(dssdev); ++ ++ enable_clocks(0); ++ dsi_enable_pll_clock(0); ++ ++ omap_dss_stop_device(dssdev); ++end: ++ dsi_bus_unlock(); ++ mutex_unlock(&dsi.lock); ++} ++ ++static int dsi_display_suspend(struct omap_dss_device *dssdev) ++{ ++ DSSDBG("dsi_display_suspend\n"); ++ ++ mutex_lock(&dsi.lock); ++ dsi_bus_lock(); ++ ++ if (dssdev->state == OMAP_DSS_DISPLAY_DISABLED || ++ dssdev->state == OMAP_DSS_DISPLAY_SUSPENDED) ++ goto end; ++ ++ dsi.update_mode = OMAP_DSS_UPDATE_DISABLED; ++ dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED; ++ ++ dsi_display_uninit_dispc(dssdev); ++ ++ dsi_display_uninit_dsi(dssdev); ++ ++ enable_clocks(0); ++ dsi_enable_pll_clock(0); ++end: ++ dsi_bus_unlock(); ++ mutex_unlock(&dsi.lock); ++ ++ return 0; ++} ++ ++static int dsi_display_resume(struct omap_dss_device *dssdev) ++{ ++ int r; ++ ++ DSSDBG("dsi_display_resume\n"); ++ ++ mutex_lock(&dsi.lock); ++ dsi_bus_lock(); ++ ++ if (dssdev->state != OMAP_DSS_DISPLAY_SUSPENDED) { ++ DSSERR("dssdev not suspended\n"); ++ r = -EINVAL; ++ goto err0; ++ } ++ ++ enable_clocks(1); ++ dsi_enable_pll_clock(1); ++ ++ r = _dsi_reset(); ++ if (r) ++ goto err1; ++ ++ dsi_core_init(); ++ ++ r = dsi_display_init_dispc(dssdev); ++ if (r) ++ goto err1; ++ ++ r = dsi_display_init_dsi(dssdev); ++ if (r) ++ goto err2; ++ ++ dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; ++ ++ r = dsi_set_te(dssdev, dsi.te_enabled); ++ if (r) ++ goto err2; ++ ++ dsi.update_mode = dsi.user_update_mode; ++ if (dsi.update_mode == OMAP_DSS_UPDATE_AUTO) ++ dsi_start_auto_update(dssdev); ++ ++ dsi_bus_unlock(); ++ mutex_unlock(&dsi.lock); ++ ++ return 0; ++ ++err2: ++ dsi_display_uninit_dispc(dssdev); ++err1: ++ enable_clocks(0); ++ dsi_enable_pll_clock(0); ++err0: ++ dsi_bus_unlock(); ++ mutex_unlock(&dsi.lock); ++ DSSDBG("dsi_display_resume FAILED\n"); ++ return r; ++} ++ ++static int dsi_display_update(struct omap_dss_device *dssdev, ++ u16 x, u16 y, u16 w, u16 h) ++{ ++ int r = 0; ++ u16 dw, dh; ++ ++ DSSDBG("dsi_display_update(%d,%d %dx%d)\n", x, y, w, h); ++ ++ mutex_lock(&dsi.lock); ++ ++ if (dsi.update_mode != OMAP_DSS_UPDATE_MANUAL) ++ goto end; ++ ++ if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) ++ goto end; ++ ++ dssdev->get_resolution(dssdev, &dw, &dh); ++ ++ if (x > dw || y > dh) ++ goto end; ++ ++ if (x + w > dw) ++ w = dw - x; ++ ++ if (y + h > dh) ++ h = dh - y; ++ ++ if (w == 0 || h == 0) ++ goto end; ++ ++ dsi_set_update_region(dssdev, x, y, w, h); ++ ++ wake_up(&dsi.waitqueue); ++ ++end: ++ mutex_unlock(&dsi.lock); ++ ++ return r; ++} ++ ++static int dsi_display_sync(struct omap_dss_device *dssdev) ++{ ++ bool wait; ++ ++ DSSDBG("dsi_display_sync()\n"); ++ ++ mutex_lock(&dsi.lock); ++ dsi_bus_lock(); ++ ++ if (dsi.update_mode == OMAP_DSS_UPDATE_MANUAL && ++ dsi.update_region.dirty) { ++ INIT_COMPLETION(dsi.update_completion); ++ wait = true; ++ } else { ++ wait = false; ++ } ++ ++ dsi_bus_unlock(); ++ mutex_unlock(&dsi.lock); ++ ++ if (wait) ++ wait_for_completion_interruptible(&dsi.update_completion); ++ ++ DSSDBG("dsi_display_sync() done\n"); ++ return 0; ++} ++ ++static int dsi_display_set_update_mode(struct omap_dss_device *dssdev, ++ enum omap_dss_update_mode mode) ++{ ++ DSSDBGF("%d", mode); ++ ++ mutex_lock(&dsi.lock); ++ dsi_bus_lock(); ++ ++ if (dsi.update_mode != mode) { ++ dsi.user_update_mode = mode; ++ dsi.update_mode = mode; ++ ++ if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE && ++ mode == OMAP_DSS_UPDATE_AUTO) ++ dsi_start_auto_update(dssdev); ++ } ++ ++ dsi_bus_unlock(); ++ mutex_unlock(&dsi.lock); ++ ++ return 0; ++} ++ ++static enum omap_dss_update_mode dsi_display_get_update_mode( ++ struct omap_dss_device *dssdev) ++{ ++ return dsi.update_mode; ++} ++ ++ ++static int dsi_display_enable_te(struct omap_dss_device *dssdev, bool enable) ++{ ++ int r = 0; ++ ++ DSSDBGF("%d", enable); ++ ++ if (!dssdev->driver->enable_te) ++ return -ENOENT; ++ ++ dsi_bus_lock(); ++ ++ dsi.te_enabled = enable; ++ ++ if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) ++ goto end; ++ ++ r = dsi_set_te(dssdev, enable); ++end: ++ dsi_bus_unlock(); ++ ++ return r; ++} ++ ++static int dsi_display_get_te(struct omap_dss_device *dssdev) ++{ ++ return dsi.te_enabled; ++} ++ ++static int dsi_display_set_rotate(struct omap_dss_device *dssdev, u8 rotate) ++{ ++ ++ DSSDBGF("%d", rotate); ++ ++ if (!dssdev->driver->set_rotate || !dssdev->driver->get_rotate) ++ return -EINVAL; ++ ++ dsi_bus_lock(); ++ dssdev->driver->set_rotate(dssdev, rotate); ++ if (dsi.update_mode == OMAP_DSS_UPDATE_AUTO) { ++ u16 w, h; ++ /* the display dimensions may have changed, so set a new ++ * update region */ ++ dssdev->get_resolution(dssdev, &w, &h); ++ dsi_set_update_region(dssdev, 0, 0, w, h); ++ } ++ dsi_bus_unlock(); ++ ++ return 0; ++} ++ ++static u8 dsi_display_get_rotate(struct omap_dss_device *dssdev) ++{ ++ if (!dssdev->driver->set_rotate || !dssdev->driver->get_rotate) ++ return 0; ++ ++ return dssdev->driver->get_rotate(dssdev); ++} ++ ++static int dsi_display_set_mirror(struct omap_dss_device *dssdev, bool mirror) ++{ ++ DSSDBGF("%d", mirror); ++ ++ if (!dssdev->driver->set_mirror || !dssdev->driver->get_mirror) ++ return -EINVAL; ++ ++ dsi_bus_lock(); ++ dssdev->driver->set_mirror(dssdev, mirror); ++ dsi_bus_unlock(); ++ ++ return 0; ++} ++ ++static bool dsi_display_get_mirror(struct omap_dss_device *dssdev) ++{ ++ if (!dssdev->driver->set_mirror || !dssdev->driver->get_mirror) ++ return 0; ++ ++ return dssdev->driver->get_mirror(dssdev); ++} ++ ++static int dsi_display_run_test(struct omap_dss_device *dssdev, int test_num) ++{ ++ int r; ++ ++ if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) ++ return -EIO; ++ ++ DSSDBGF("%d", test_num); ++ ++ dsi_bus_lock(); ++ ++ /* run test first in low speed mode */ ++ dsi_vc_enable_hs(0, 0); ++ ++ if (dssdev->driver->run_test) { ++ r = dssdev->driver->run_test(dssdev, test_num); ++ if (r) ++ goto end; ++ } ++ ++ /* then in high speed */ ++ dsi_vc_enable_hs(0, 1); ++ ++ if (dssdev->driver->run_test) { ++ r = dssdev->driver->run_test(dssdev, test_num); ++ if (r) ++ goto end; ++ } ++ ++end: ++ dsi_vc_enable_hs(0, 1); ++ ++ dsi_bus_unlock(); ++ ++ return r; ++} ++ ++static int dsi_display_memory_read(struct omap_dss_device *dssdev, ++ void *buf, size_t size, ++ u16 x, u16 y, u16 w, u16 h) ++{ ++ int r; ++ ++ DSSDBGF(""); ++ ++ if (!dssdev->driver->memory_read) ++ return -EINVAL; ++ ++ if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) ++ return -EIO; ++ ++ dsi_bus_lock(); ++ ++ r = dssdev->driver->memory_read(dssdev, buf, size, ++ x, y, w, h); ++ ++ dsi_bus_unlock(); ++ ++ return r; ++} ++ ++void dsi_get_overlay_fifo_thresholds(enum omap_plane plane, ++ u32 fifo_size, enum omap_burst_size *burst_size, ++ u32 *fifo_low, u32 *fifo_high) ++{ ++ unsigned burst_size_bytes; ++ ++ *burst_size = OMAP_DSS_BURST_16x32; ++ burst_size_bytes = 16 * 32 / 8; ++ ++ *fifo_high = fifo_size - burst_size_bytes; ++ *fifo_low = 0; ++} ++ ++int dsi_init_display(struct omap_dss_device *dssdev) ++{ ++ DSSDBG("DSI init\n"); ++ ++ dssdev->enable = dsi_display_enable; ++ dssdev->disable = dsi_display_disable; ++ dssdev->suspend = dsi_display_suspend; ++ dssdev->resume = dsi_display_resume; ++ dssdev->update = dsi_display_update; ++ dssdev->sync = dsi_display_sync; ++ dssdev->set_update_mode = dsi_display_set_update_mode; ++ dssdev->get_update_mode = dsi_display_get_update_mode; ++ dssdev->enable_te = dsi_display_enable_te; ++ dssdev->get_te = dsi_display_get_te; ++ ++ dssdev->get_rotate = dsi_display_get_rotate; ++ dssdev->set_rotate = dsi_display_set_rotate; ++ ++ dssdev->get_mirror = dsi_display_get_mirror; ++ dssdev->set_mirror = dsi_display_set_mirror; ++ ++ dssdev->run_test = dsi_display_run_test; ++ dssdev->memory_read = dsi_display_memory_read; ++ ++ dssdev->caps = OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE; ++ ++ dsi.vc[0].dssdev = dssdev; ++ dsi.vc[1].dssdev = dssdev; ++ ++ return 0; ++} ++ ++int dsi_init(struct platform_device *pdev) ++{ ++ u32 rev; ++ struct sched_param param = { ++ .sched_priority = MAX_USER_RT_PRIO-1 ++ }; ++ ++ spin_lock_init(&dsi.errors_lock); ++ dsi.errors = 0; ++ ++ /* XXX fail properly */ ++ ++ init_completion(&dsi.bta_completion); ++ init_completion(&dsi.update_completion); ++ ++ dsi.thread = kthread_create(dsi_update_thread, NULL, "dsi"); ++ if (IS_ERR(dsi.thread)) { ++ DSSERR("cannot create kthread\n"); ++ return PTR_ERR(dsi.thread); ++ } ++ sched_setscheduler(dsi.thread, SCHED_FIFO, ¶m); ++ ++ init_waitqueue_head(&dsi.waitqueue); ++ spin_lock_init(&dsi.update_lock); ++ ++ mutex_init(&dsi.lock); ++ mutex_init(&dsi.bus_lock); ++ ++ dsi.update_mode = OMAP_DSS_UPDATE_DISABLED; ++ dsi.user_update_mode = OMAP_DSS_UPDATE_DISABLED; ++ ++ dsi.base = ioremap(DSI_BASE, DSI_SZ_REGS); ++ if (!dsi.base) { ++ DSSERR("can't ioremap DSI\n"); ++ return -ENOMEM; ++ } ++ ++ dsi.vdds_dsi_reg = regulator_get(&pdev->dev, "vdds_dsi"); ++ if (IS_ERR(dsi.vdds_dsi_reg)) { ++ iounmap(dsi.base); ++ DSSERR("can't get VDDS_DSI regulator\n"); ++ return PTR_ERR(dsi.vdds_dsi_reg); ++ } ++ ++ enable_clocks(1); ++ ++ rev = dsi_read_reg(DSI_REVISION); ++ printk(KERN_INFO "OMAP DSI rev %d.%d\n", ++ FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0)); ++ ++ enable_clocks(0); ++ ++ wake_up_process(dsi.thread); ++ ++ return 0; ++} ++ ++void dsi_exit(void) ++{ ++ kthread_stop(dsi.thread); ++ ++ regulator_put(dsi.vdds_dsi_reg); ++ ++ iounmap(dsi.base); ++ ++ DSSDBG("omap_dsi_exit\n"); ++} ++ +diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c +new file mode 100644 +index 0000000..aab9758 +--- /dev/null ++++ b/drivers/video/omap2/dss/dss.c +@@ -0,0 +1,347 @@ ++/* ++ * linux/drivers/video/omap2/dss/dss.c ++ * ++ * Copyright (C) 2009 Nokia Corporation ++ * Author: Tomi Valkeinen ++ * ++ * Some code and ideas taken from drivers/video/omap/ driver ++ * by Imre Deak. ++ * ++ * 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. ++ * ++ * 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, see . ++ */ ++ ++#define DSS_SUBSYS_NAME "DSS" ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include "dss.h" ++ ++#define DSS_BASE 0x48050000 ++ ++#define DSS_SZ_REGS SZ_512 ++ ++struct dss_reg { ++ u16 idx; ++}; ++ ++#define DSS_REG(idx) ((const struct dss_reg) { idx }) ++ ++#define DSS_REVISION DSS_REG(0x0000) ++#define DSS_SYSCONFIG DSS_REG(0x0010) ++#define DSS_SYSSTATUS DSS_REG(0x0014) ++#define DSS_IRQSTATUS DSS_REG(0x0018) ++#define DSS_CONTROL DSS_REG(0x0040) ++#define DSS_SDI_CONTROL DSS_REG(0x0044) ++#define DSS_PLL_CONTROL DSS_REG(0x0048) ++#define DSS_SDI_STATUS DSS_REG(0x005C) ++ ++#define REG_GET(idx, start, end) \ ++ FLD_GET(dss_read_reg(idx), start, end) ++ ++#define REG_FLD_MOD(idx, val, start, end) \ ++ dss_write_reg(idx, FLD_MOD(dss_read_reg(idx), val, start, end)) ++ ++static struct { ++ void __iomem *base; ++ ++ u32 ctx[DSS_SZ_REGS / sizeof(u32)]; ++} dss; ++ ++static int _omap_dss_wait_reset(void); ++ ++static inline void dss_write_reg(const struct dss_reg idx, u32 val) ++{ ++ __raw_writel(val, dss.base + idx.idx); ++} ++ ++static inline u32 dss_read_reg(const struct dss_reg idx) ++{ ++ return __raw_readl(dss.base + idx.idx); ++} ++ ++#define SR(reg) \ ++ dss.ctx[(DSS_##reg).idx / sizeof(u32)] = dss_read_reg(DSS_##reg) ++#define RR(reg) \ ++ dss_write_reg(DSS_##reg, dss.ctx[(DSS_##reg).idx / sizeof(u32)]) ++ ++void dss_save_context(void) ++{ ++ if (cpu_is_omap24xx()) ++ return; ++ ++ SR(SYSCONFIG); ++ SR(CONTROL); ++ ++#ifdef CONFIG_OMAP2_DSS_SDI ++ SR(SDI_CONTROL); ++ SR(PLL_CONTROL); ++#endif ++} ++ ++void dss_restore_context(void) ++{ ++ if (_omap_dss_wait_reset()) ++ DSSERR("DSS not coming out of reset after sleep\n"); ++ ++ RR(SYSCONFIG); ++ RR(CONTROL); ++ ++#ifdef CONFIG_OMAP2_DSS_SDI ++ RR(SDI_CONTROL); ++ RR(PLL_CONTROL); ++#endif ++} ++ ++#undef SR ++#undef RR ++ ++void dss_sdi_init(u8 datapairs) ++{ ++ u32 l; ++ ++ BUG_ON(datapairs > 3 || datapairs < 1); ++ ++ l = dss_read_reg(DSS_SDI_CONTROL); ++ l = FLD_MOD(l, 0xf, 19, 15); /* SDI_PDIV */ ++ l = FLD_MOD(l, datapairs-1, 3, 2); /* SDI_PRSEL */ ++ l = FLD_MOD(l, 2, 1, 0); /* SDI_BWSEL */ ++ dss_write_reg(DSS_SDI_CONTROL, l); ++ ++ l = dss_read_reg(DSS_PLL_CONTROL); ++ l = FLD_MOD(l, 0x7, 25, 22); /* SDI_PLL_FREQSEL */ ++ l = FLD_MOD(l, 0xb, 16, 11); /* SDI_PLL_REGN */ ++ l = FLD_MOD(l, 0xb4, 10, 1); /* SDI_PLL_REGM */ ++ dss_write_reg(DSS_PLL_CONTROL, l); ++} ++ ++void dss_sdi_enable(void) ++{ ++ dispc_pck_free_enable(1); ++ ++ /* Reset SDI PLL */ ++ REG_FLD_MOD(DSS_PLL_CONTROL, 1, 18, 18); /* SDI_PLL_SYSRESET */ ++ udelay(1); /* wait 2x PCLK */ ++ ++ /* Lock SDI PLL */ ++ REG_FLD_MOD(DSS_PLL_CONTROL, 1, 28, 28); /* SDI_PLL_GOBIT */ ++ ++ /* Waiting for PLL lock request to complete */ ++ while (dss_read_reg(DSS_SDI_STATUS) & (1 << 6)) ++ ; ++ ++ /* Clearing PLL_GO bit */ ++ REG_FLD_MOD(DSS_PLL_CONTROL, 0, 28, 28); ++ ++ /* Waiting for PLL to lock */ ++ while (!(dss_read_reg(DSS_SDI_STATUS) & (1 << 5))) ++ ; ++ ++ dispc_lcd_enable_signal(1); ++ ++ /* Waiting for SDI reset to complete */ ++ while (!(dss_read_reg(DSS_SDI_STATUS) & (1 << 2))) ++ ; ++} ++ ++void dss_sdi_disable(void) ++{ ++ dispc_lcd_enable_signal(0); ++ ++ dispc_pck_free_enable(0); ++ ++ /* Reset SDI PLL */ ++ REG_FLD_MOD(DSS_PLL_CONTROL, 0, 18, 18); /* SDI_PLL_SYSRESET */ ++} ++ ++void dss_dump_regs(struct seq_file *s) ++{ ++#define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, dss_read_reg(r)) ++ ++ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); ++ ++ DUMPREG(DSS_REVISION); ++ DUMPREG(DSS_SYSCONFIG); ++ DUMPREG(DSS_SYSSTATUS); ++ DUMPREG(DSS_IRQSTATUS); ++ DUMPREG(DSS_CONTROL); ++ DUMPREG(DSS_SDI_CONTROL); ++ DUMPREG(DSS_PLL_CONTROL); ++ DUMPREG(DSS_SDI_STATUS); ++ ++ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); ++#undef DUMPREG ++} ++ ++void dss_select_clk_source(bool dsi, bool dispc) ++{ ++ u32 r; ++ r = dss_read_reg(DSS_CONTROL); ++ r = FLD_MOD(r, dsi, 1, 1); /* DSI_CLK_SWITCH */ ++ r = FLD_MOD(r, dispc, 0, 0); /* DISPC_CLK_SWITCH */ ++ dss_write_reg(DSS_CONTROL, r); ++} ++ ++int dss_get_dsi_clk_source(void) ++{ ++ return FLD_GET(dss_read_reg(DSS_CONTROL), 1, 1); ++} ++ ++int dss_get_dispc_clk_source(void) ++{ ++ return FLD_GET(dss_read_reg(DSS_CONTROL), 0, 0); ++} ++ ++static irqreturn_t dss_irq_handler_omap2(int irq, void *arg) ++{ ++ dispc_irq_handler(); ++ ++ return IRQ_HANDLED; ++} ++ ++static irqreturn_t dss_irq_handler_omap3(int irq, void *arg) ++{ ++ u32 irqstatus; ++ ++ irqstatus = dss_read_reg(DSS_IRQSTATUS); ++ ++ if (irqstatus & (1<<0)) /* DISPC_IRQ */ ++ dispc_irq_handler(); ++#ifdef CONFIG_OMAP2_DSS_DSI ++ if (irqstatus & (1<<1)) /* DSI_IRQ */ ++ dsi_irq_handler(); ++#endif ++ ++ return IRQ_HANDLED; ++} ++ ++static int _omap_dss_wait_reset(void) ++{ ++ unsigned timeout = 1000; ++ ++ while (REG_GET(DSS_SYSSTATUS, 0, 0) == 0) { ++ udelay(1); ++ if (!--timeout) { ++ DSSERR("soft reset failed\n"); ++ return -ENODEV; ++ } ++ } ++ ++ return 0; ++} ++ ++static int _omap_dss_reset(void) ++{ ++ /* Soft reset */ ++ REG_FLD_MOD(DSS_SYSCONFIG, 1, 1, 1); ++ return _omap_dss_wait_reset(); ++} ++ ++void dss_set_venc_output(enum omap_dss_venc_type type) ++{ ++ int l = 0; ++ ++ if (type == OMAP_DSS_VENC_TYPE_COMPOSITE) ++ l = 0; ++ else if (type == OMAP_DSS_VENC_TYPE_SVIDEO) ++ l = 1; ++ else ++ BUG(); ++ ++ /* venc out selection. 0 = comp, 1 = svideo */ ++ REG_FLD_MOD(DSS_CONTROL, l, 6, 6); ++} ++ ++void dss_set_dac_pwrdn_bgz(bool enable) ++{ ++ REG_FLD_MOD(DSS_CONTROL, enable, 5, 5); /* DAC Power-Down Control */ ++} ++ ++int dss_init(bool skip_init) ++{ ++ int r; ++ u32 rev; ++ ++ dss.base = ioremap(DSS_BASE, DSS_SZ_REGS); ++ if (!dss.base) { ++ DSSERR("can't ioremap DSS\n"); ++ r = -ENOMEM; ++ goto fail0; ++ } ++ ++ if (!skip_init) { ++ /* disable LCD and DIGIT output. This seems to fix the synclost ++ * problem that we get, if the bootloader starts the DSS and ++ * the kernel resets it */ ++ omap_writel(omap_readl(0x48050440) & ~0x3, 0x48050440); ++ ++ /* We need to wait here a bit, otherwise we sometimes start to ++ * get synclost errors, and after that only power cycle will ++ * restore DSS functionality. I have no idea why this happens. ++ * And we have to wait _before_ resetting the DSS, but after ++ * enabling clocks. ++ */ ++ msleep(50); ++ ++ _omap_dss_reset(); ++ } ++ ++ /* autoidle */ ++ REG_FLD_MOD(DSS_SYSCONFIG, 1, 0, 0); ++ ++ /* Select DPLL */ ++ REG_FLD_MOD(DSS_CONTROL, 0, 0, 0); ++ ++#ifdef CONFIG_OMAP2_DSS_VENC ++ REG_FLD_MOD(DSS_CONTROL, 1, 4, 4); /* venc dac demen */ ++ REG_FLD_MOD(DSS_CONTROL, 1, 3, 3); /* venc clock 4x enable */ ++ REG_FLD_MOD(DSS_CONTROL, 0, 2, 2); /* venc clock mode = normal */ ++#endif ++ ++ r = request_irq(INT_24XX_DSS_IRQ, ++ cpu_is_omap24xx() ++ ? dss_irq_handler_omap2 ++ : dss_irq_handler_omap3, ++ 0, "OMAP DSS", NULL); ++ ++ if (r < 0) { ++ DSSERR("omap2 dss: request_irq failed\n"); ++ goto fail1; ++ } ++ ++ dss_save_context(); ++ ++ rev = dss_read_reg(DSS_REVISION); ++ printk(KERN_INFO "OMAP DSS rev %d.%d\n", ++ FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0)); ++ ++ return 0; ++ ++fail1: ++ iounmap(dss.base); ++fail0: ++ return r; ++} ++ ++void dss_exit(void) ++{ ++ free_irq(INT_24XX_DSS_IRQ, NULL); ++ ++ iounmap(dss.base); ++} ++ +diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h +new file mode 100644 +index 0000000..50f7f5f +--- /dev/null ++++ b/drivers/video/omap2/dss/dss.h +@@ -0,0 +1,356 @@ ++/* ++ * linux/drivers/video/omap2/dss/dss.h ++ * ++ * Copyright (C) 2009 Nokia Corporation ++ * Author: Tomi Valkeinen ++ * ++ * Some code and ideas taken from drivers/video/omap/ driver ++ * by Imre Deak. ++ * ++ * 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. ++ * ++ * 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, see . ++ */ ++ ++#ifndef __OMAP2_DSS_H ++#define __OMAP2_DSS_H ++ ++#ifdef CONFIG_OMAP2_DSS_DEBUG_SUPPORT ++#define DEBUG ++#endif ++ ++#ifdef DEBUG ++extern unsigned int dss_debug; ++#ifdef DSS_SUBSYS_NAME ++#define DSSDBG(format, ...) \ ++ if (dss_debug) \ ++ printk(KERN_DEBUG "omapdss " DSS_SUBSYS_NAME ": " format, \ ++ ## __VA_ARGS__) ++#else ++#define DSSDBG(format, ...) \ ++ if (dss_debug) \ ++ printk(KERN_DEBUG "omapdss: " format, ## __VA_ARGS__) ++#endif ++ ++#ifdef DSS_SUBSYS_NAME ++#define DSSDBGF(format, ...) \ ++ if (dss_debug) \ ++ printk(KERN_DEBUG "omapdss " DSS_SUBSYS_NAME \ ++ ": %s(" format ")\n", \ ++ __func__, \ ++ ## __VA_ARGS__) ++#else ++#define DSSDBGF(format, ...) \ ++ if (dss_debug) \ ++ printk(KERN_DEBUG "omapdss: " \ ++ ": %s(" format ")\n", \ ++ __func__, \ ++ ## __VA_ARGS__) ++#endif ++ ++#else /* DEBUG */ ++#define DSSDBG(format, ...) ++#define DSSDBGF(format, ...) ++#endif ++ ++ ++#ifdef DSS_SUBSYS_NAME ++#define DSSERR(format, ...) \ ++ printk(KERN_ERR "omapdss " DSS_SUBSYS_NAME " error: " format, \ ++ ## __VA_ARGS__) ++#else ++#define DSSERR(format, ...) \ ++ printk(KERN_ERR "omapdss error: " format, ## __VA_ARGS__) ++#endif ++ ++#ifdef DSS_SUBSYS_NAME ++#define DSSINFO(format, ...) \ ++ printk(KERN_INFO "omapdss " DSS_SUBSYS_NAME ": " format, \ ++ ## __VA_ARGS__) ++#else ++#define DSSINFO(format, ...) \ ++ printk(KERN_INFO "omapdss: " format, ## __VA_ARGS__) ++#endif ++ ++#ifdef DSS_SUBSYS_NAME ++#define DSSWARN(format, ...) \ ++ printk(KERN_WARNING "omapdss " DSS_SUBSYS_NAME ": " format, \ ++ ## __VA_ARGS__) ++#else ++#define DSSWARN(format, ...) \ ++ printk(KERN_WARNING "omapdss: " format, ## __VA_ARGS__) ++#endif ++ ++/* OMAP TRM gives bitfields as start:end, where start is the higher bit ++ number. For example 7:0 */ ++#define FLD_MASK(start, end) (((1 << (start - end + 1)) - 1) << (end)) ++#define FLD_VAL(val, start, end) (((val) << end) & FLD_MASK(start, end)) ++#define FLD_GET(val, start, end) (((val) & FLD_MASK(start, end)) >> (end)) ++#define FLD_MOD(orig, val, start, end) \ ++ (((orig) & ~FLD_MASK(start, end)) | FLD_VAL(val, start, end)) ++ ++#define DISPC_MAX_FCK 173000000 ++ ++enum omap_burst_size { ++ OMAP_DSS_BURST_4x32 = 0, ++ OMAP_DSS_BURST_8x32 = 1, ++ OMAP_DSS_BURST_16x32 = 2, ++}; ++ ++enum omap_parallel_interface_mode { ++ OMAP_DSS_PARALLELMODE_BYPASS, /* MIPI DPI */ ++ OMAP_DSS_PARALLELMODE_RFBI, /* MIPI DBI */ ++ OMAP_DSS_PARALLELMODE_DSI, ++}; ++ ++enum dss_clock { ++ DSS_CLK_ICK = 1 << 0, ++ DSS_CLK_FCK1 = 1 << 1, ++ DSS_CLK_FCK2 = 1 << 2, ++ DSS_CLK_54M = 1 << 3, ++ DSS_CLK_96M = 1 << 4, ++}; ++ ++struct dispc_clock_info { ++ /* rates that we get with dividers below */ ++ unsigned long fck; ++ unsigned long lck; ++ unsigned long pck; ++ ++ /* dividers */ ++ u16 fck_div; ++ u16 lck_div; ++ u16 pck_div; ++}; ++ ++struct dsi_clock_info { ++ /* rates that we get with dividers below */ ++ unsigned long fint; ++ unsigned long dsiphy; ++ unsigned long clkin; ++ unsigned long dsi1_pll_fclk; ++ unsigned long dsi2_pll_fclk; ++ unsigned long lck; ++ unsigned long pck; ++ ++ /* dividers */ ++ u16 regn; ++ u16 regm; ++ u16 regm3; ++ u16 regm4; ++ ++ u16 lck_div; ++ u16 pck_div; ++ ++ u8 highfreq; ++ bool use_dss2_fck; ++}; ++ ++struct seq_file; ++struct platform_device; ++ ++/* core */ ++void dss_clk_enable(enum dss_clock clks); ++void dss_clk_disable(enum dss_clock clks); ++unsigned long dss_clk_get_rate(enum dss_clock clk); ++int dss_need_ctx_restore(void); ++void dss_dump_clocks(struct seq_file *s); ++struct bus_type *dss_get_bus(void); ++ ++/* display */ ++int dss_suspend_all_devices(void); ++int dss_resume_all_devices(void); ++ ++void dss_init_device(struct platform_device *pdev, ++ struct omap_dss_device *dssdev); ++void dss_uninit_device(struct platform_device *pdev, ++ struct omap_dss_device *dssdev); ++bool dss_use_replication(struct omap_dss_device *dssdev, ++ enum omap_color_mode mode); ++void default_get_overlay_fifo_thresholds(enum omap_plane plane, ++ u32 fifo_size, enum omap_burst_size *burst_size, ++ u32 *fifo_low, u32 *fifo_high); ++ ++/* manager */ ++int dss_init_overlay_managers(struct platform_device *pdev); ++void dss_uninit_overlay_managers(struct platform_device *pdev); ++int dss_mgr_wait_for_go_ovl(struct omap_overlay *ovl); ++void dss_setup_partial_planes(struct omap_dss_device *dssdev, ++ u16 *x, u16 *y, u16 *w, u16 *h); ++void dss_start_update(struct omap_dss_device *dssdev); ++ ++/* overlay */ ++void dss_init_overlays(struct platform_device *pdev); ++void dss_uninit_overlays(struct platform_device *pdev); ++int dss_check_overlay(struct omap_overlay *ovl, struct omap_dss_device *dssdev); ++void dss_overlay_setup_dispc_manager(struct omap_overlay_manager *mgr); ++#ifdef L4_EXAMPLE ++void dss_overlay_setup_l4_manager(struct omap_overlay_manager *mgr); ++#endif ++void dss_recheck_connections(struct omap_dss_device *dssdev, bool force); ++ ++/* DSS */ ++int dss_init(bool skip_init); ++void dss_exit(void); ++ ++void dss_save_context(void); ++void dss_restore_context(void); ++ ++void dss_dump_regs(struct seq_file *s); ++ ++void dss_sdi_init(u8 datapairs); ++void dss_sdi_enable(void); ++void dss_sdi_disable(void); ++ ++void dss_select_clk_source(bool dsi, bool dispc); ++int dss_get_dsi_clk_source(void); ++int dss_get_dispc_clk_source(void); ++void dss_set_venc_output(enum omap_dss_venc_type type); ++void dss_set_dac_pwrdn_bgz(bool enable); ++ ++/* SDI */ ++int sdi_init(bool skip_init); ++void sdi_exit(void); ++int sdi_init_display(struct omap_dss_device *display); ++ ++/* DSI */ ++int dsi_init(struct platform_device *pdev); ++void dsi_exit(void); ++ ++void dsi_dump_clocks(struct seq_file *s); ++void dsi_dump_regs(struct seq_file *s); ++ ++void dsi_save_context(void); ++void dsi_restore_context(void); ++ ++int dsi_init_display(struct omap_dss_device *display); ++void dsi_irq_handler(void); ++unsigned long dsi_get_dsi1_pll_rate(void); ++unsigned long dsi_get_dsi2_pll_rate(void); ++int dsi_pll_calc_pck(bool is_tft, unsigned long req_pck, ++ struct dsi_clock_info *cinfo); ++int dsi_pll_program(struct dsi_clock_info *cinfo); ++int dsi_pll_init(bool enable_hsclk, bool enable_hsdiv); ++void dsi_pll_uninit(void); ++void dsi_get_overlay_fifo_thresholds(enum omap_plane plane, ++ u32 fifo_size, enum omap_burst_size *burst_size, ++ u32 *fifo_low, u32 *fifo_high); ++ ++/* DPI */ ++int dpi_init(void); ++void dpi_exit(void); ++int dpi_init_display(struct omap_dss_device *dssdev); ++ ++/* DISPC */ ++int dispc_init(void); ++void dispc_exit(void); ++void dispc_dump_clocks(struct seq_file *s); ++void dispc_dump_regs(struct seq_file *s); ++void dispc_irq_handler(void); ++void dispc_fake_vsync_irq(void); ++ ++void dispc_save_context(void); ++void dispc_restore_context(void); ++ ++void dispc_enable_sidle(void); ++void dispc_disable_sidle(void); ++ ++void dispc_lcd_enable_signal_polarity(bool act_high); ++void dispc_lcd_enable_signal(bool enable); ++void dispc_pck_free_enable(bool enable); ++void dispc_enable_fifohandcheck(bool enable); ++ ++void dispc_set_lcd_size(u16 width, u16 height); ++void dispc_set_digit_size(u16 width, u16 height); ++u32 dispc_get_plane_fifo_size(enum omap_plane plane); ++void dispc_setup_plane_fifo(enum omap_plane plane, u32 low, u32 high); ++void dispc_enable_fifomerge(bool enable); ++void dispc_set_burst_size(enum omap_plane plane, ++ enum omap_burst_size burst_size); ++ ++void dispc_set_plane_ba0(enum omap_plane plane, u32 paddr); ++void dispc_set_plane_ba1(enum omap_plane plane, u32 paddr); ++void dispc_set_plane_pos(enum omap_plane plane, u16 x, u16 y); ++void dispc_set_plane_size(enum omap_plane plane, u16 width, u16 height); ++void dispc_set_channel_out(enum omap_plane plane, ++ enum omap_channel channel_out); ++ ++int dispc_setup_plane(enum omap_plane plane, ++ u32 paddr, u16 screen_width, ++ u16 pos_x, u16 pos_y, ++ u16 width, u16 height, ++ u16 out_width, u16 out_height, ++ enum omap_color_mode color_mode, ++ bool ilace, ++ enum omap_dss_rotation_type rotation_type, ++ u8 rotation, bool mirror, ++ u8 global_alpha); ++ ++bool dispc_go_busy(enum omap_channel channel); ++void dispc_go(enum omap_channel channel); ++void dispc_enable_lcd_out(bool enable); ++void dispc_enable_digit_out(bool enable); ++int dispc_enable_plane(enum omap_plane plane, bool enable); ++void dispc_enable_replication(enum omap_plane plane, bool enable); ++ ++void dispc_set_parallel_interface_mode(enum omap_parallel_interface_mode mode); ++void dispc_set_tft_data_lines(u8 data_lines); ++void dispc_set_lcd_display_type(enum omap_lcd_display_type type); ++void dispc_set_loadmode(enum omap_dss_load_mode mode); ++ ++void dispc_set_default_color(enum omap_channel channel, u32 color); ++u32 dispc_get_default_color(enum omap_channel channel); ++void dispc_set_trans_key(enum omap_channel ch, ++ enum omap_dss_trans_key_type type, ++ u32 trans_key); ++void dispc_get_trans_key(enum omap_channel ch, ++ enum omap_dss_trans_key_type *type, ++ u32 *trans_key); ++void dispc_enable_trans_key(enum omap_channel ch, bool enable); ++void dispc_enable_alpha_blending(enum omap_channel ch, bool enable); ++bool dispc_trans_key_enabled(enum omap_channel ch); ++bool dispc_alpha_blending_enabled(enum omap_channel ch); ++ ++bool dispc_lcd_timings_ok(struct omap_video_timings *timings); ++void dispc_set_lcd_timings(struct omap_video_timings *timings); ++unsigned long dispc_fclk_rate(void); ++unsigned long dispc_lclk_rate(void); ++unsigned long dispc_pclk_rate(void); ++void dispc_set_pol_freq(enum omap_panel_config config, u8 acbi, u8 acb); ++void find_lck_pck_divs(bool is_tft, unsigned long req_pck, unsigned long fck, ++ u16 *lck_div, u16 *pck_div); ++int dispc_calc_clock_div(bool is_tft, unsigned long req_pck, ++ struct dispc_clock_info *cinfo); ++int dispc_set_clock_div(struct dispc_clock_info *cinfo); ++int dispc_get_clock_div(struct dispc_clock_info *cinfo); ++void dispc_set_lcd_divisor(u16 lck_div, u16 pck_div); ++ ++ ++/* VENC */ ++int venc_init(struct platform_device *pdev); ++void venc_exit(void); ++void venc_dump_regs(struct seq_file *s); ++int venc_init_display(struct omap_dss_device *display); ++ ++/* RFBI */ ++int rfbi_init(void); ++void rfbi_exit(void); ++void rfbi_dump_regs(struct seq_file *s); ++ ++int rfbi_configure(int rfbi_module, int bpp, int lines); ++void rfbi_enable_rfbi(bool enable); ++void rfbi_transfer_area(u16 width, u16 height, ++ void (callback)(void *data), void *data); ++void rfbi_set_timings(int rfbi_module, struct rfbi_timings *t); ++unsigned long rfbi_get_max_tx_rate(void); ++int rfbi_init_display(struct omap_dss_device *display); ++ ++#endif +diff --git a/drivers/video/omap2/dss/manager.c b/drivers/video/omap2/dss/manager.c +new file mode 100644 +index 0000000..7ee0b2b +--- /dev/null ++++ b/drivers/video/omap2/dss/manager.c +@@ -0,0 +1,1487 @@ ++/* ++ * linux/drivers/video/omap2/dss/manager.c ++ * ++ * Copyright (C) 2009 Nokia Corporation ++ * Author: Tomi Valkeinen ++ * ++ * Some code and ideas taken from drivers/video/omap/ driver ++ * by Imre Deak. ++ * ++ * 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. ++ * ++ * 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, see . ++ */ ++ ++#define DSS_SUBSYS_NAME "MANAGER" ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++ ++#include "dss.h" ++ ++static int num_managers; ++static struct list_head manager_list; ++ ++static ssize_t manager_name_show(struct omap_overlay_manager *mgr, char *buf) ++{ ++ return snprintf(buf, PAGE_SIZE, "%s\n", mgr->name); ++} ++ ++static ssize_t manager_display_show(struct omap_overlay_manager *mgr, char *buf) ++{ ++ return snprintf(buf, PAGE_SIZE, "%s\n", ++ mgr->device ? mgr->device->name : ""); ++} ++ ++static ssize_t manager_display_store(struct omap_overlay_manager *mgr, ++ const char *buf, size_t size) ++{ ++ int r = 0; ++ size_t len = size; ++ struct omap_dss_device *dssdev = NULL; ++ ++ int match(struct omap_dss_device *dssdev, void *data) ++ { ++ const char *str = data; ++ return sysfs_streq(dssdev->name, str); ++ } ++ ++ if (buf[size-1] == '\n') ++ --len; ++ ++ if (len > 0) ++ dssdev = omap_dss_find_device((void *)buf, match); ++ ++ if (len > 0 && dssdev == NULL) ++ return -EINVAL; ++ ++ if (dssdev) ++ DSSDBG("display %s found\n", dssdev->name); ++ ++ if (mgr->device) { ++ r = mgr->unset_device(mgr); ++ if (r) { ++ DSSERR("failed to unset display\n"); ++ goto put_device; ++ } ++ } ++ ++ if (dssdev) { ++ r = mgr->set_device(mgr, dssdev); ++ if (r) { ++ DSSERR("failed to set manager\n"); ++ goto put_device; ++ } ++ ++ r = mgr->apply(mgr); ++ if (r) { ++ DSSERR("failed to apply dispc config\n"); ++ goto put_device; ++ } ++ } ++ ++put_device: ++ if (dssdev) ++ omap_dss_put_device(dssdev); ++ ++ return r ? r : size; ++} ++ ++static ssize_t manager_default_color_show(struct omap_overlay_manager *mgr, ++ char *buf) ++{ ++ return snprintf(buf, PAGE_SIZE, "%d\n", mgr->info.default_color); ++} ++ ++static ssize_t manager_default_color_store(struct omap_overlay_manager *mgr, ++ const char *buf, size_t size) ++{ ++ struct omap_overlay_manager_info info; ++ u32 color; ++ int r; ++ ++ if (sscanf(buf, "%d", &color) != 1) ++ return -EINVAL; ++ ++ mgr->get_manager_info(mgr, &info); ++ ++ info.default_color = color; ++ ++ r = mgr->set_manager_info(mgr, &info); ++ if (r) ++ return r; ++ ++ r = mgr->apply(mgr); ++ if (r) ++ return r; ++ ++ return size; ++} ++ ++static const char *trans_key_type_str[] = { ++ "gfx-destination", ++ "video-source", ++}; ++ ++static ssize_t manager_trans_key_type_show(struct omap_overlay_manager *mgr, ++ char *buf) ++{ ++ enum omap_dss_trans_key_type key_type; ++ ++ key_type = mgr->info.trans_key_type; ++ BUG_ON(key_type >= ARRAY_SIZE(trans_key_type_str)); ++ ++ return snprintf(buf, PAGE_SIZE, "%s\n", trans_key_type_str[key_type]); ++} ++ ++static ssize_t manager_trans_key_type_store(struct omap_overlay_manager *mgr, ++ const char *buf, size_t size) ++{ ++ enum omap_dss_trans_key_type key_type; ++ struct omap_overlay_manager_info info; ++ int r; ++ ++ for (key_type = OMAP_DSS_COLOR_KEY_GFX_DST; ++ key_type < ARRAY_SIZE(trans_key_type_str); key_type++) { ++ if (sysfs_streq(buf, trans_key_type_str[key_type])) ++ break; ++ } ++ ++ if (key_type == ARRAY_SIZE(trans_key_type_str)) ++ return -EINVAL; ++ ++ mgr->get_manager_info(mgr, &info); ++ ++ info.trans_key_type = key_type; ++ ++ r = mgr->set_manager_info(mgr, &info); ++ if (r) ++ return r; ++ ++ r = mgr->apply(mgr); ++ if (r) ++ return r; ++ ++ return size; ++} ++ ++static ssize_t manager_trans_key_value_show(struct omap_overlay_manager *mgr, ++ char *buf) ++{ ++ return snprintf(buf, PAGE_SIZE, "%d\n", mgr->info.trans_key); ++} ++ ++static ssize_t manager_trans_key_value_store(struct omap_overlay_manager *mgr, ++ const char *buf, size_t size) ++{ ++ struct omap_overlay_manager_info info; ++ u32 key_value; ++ int r; ++ ++ if (sscanf(buf, "%d", &key_value) != 1) ++ return -EINVAL; ++ ++ mgr->get_manager_info(mgr, &info); ++ ++ info.trans_key = key_value; ++ ++ r = mgr->set_manager_info(mgr, &info); ++ if (r) ++ return r; ++ ++ r = mgr->apply(mgr); ++ if (r) ++ return r; ++ ++ return size; ++} ++ ++static ssize_t manager_trans_key_enabled_show(struct omap_overlay_manager *mgr, ++ char *buf) ++{ ++ return snprintf(buf, PAGE_SIZE, "%d\n", mgr->info.trans_enabled); ++} ++ ++static ssize_t manager_trans_key_enabled_store(struct omap_overlay_manager *mgr, ++ const char *buf, size_t size) ++{ ++ struct omap_overlay_manager_info info; ++ int enable; ++ int r; ++ ++ if (sscanf(buf, "%d", &enable) != 1) ++ return -EINVAL; ++ ++ mgr->get_manager_info(mgr, &info); ++ ++ info.trans_enabled = enable ? true : false; ++ ++ r = mgr->set_manager_info(mgr, &info); ++ if (r) ++ return r; ++ ++ r = mgr->apply(mgr); ++ if (r) ++ return r; ++ ++ return size; ++} ++ ++static ssize_t manager_alpha_blending_enabled_show( ++ struct omap_overlay_manager *mgr, char *buf) ++{ ++ return snprintf(buf, PAGE_SIZE, "%d\n", mgr->info.alpha_enabled); ++} ++ ++static ssize_t manager_alpha_blending_enabled_store( ++ struct omap_overlay_manager *mgr, ++ const char *buf, size_t size) ++{ ++ struct omap_overlay_manager_info info; ++ int enable; ++ int r; ++ ++ if (sscanf(buf, "%d", &enable) != 1) ++ return -EINVAL; ++ ++ mgr->get_manager_info(mgr, &info); ++ ++ info.alpha_enabled = enable ? true : false; ++ ++ r = mgr->set_manager_info(mgr, &info); ++ if (r) ++ return r; ++ ++ r = mgr->apply(mgr); ++ if (r) ++ return r; ++ ++ return size; ++} ++ ++struct manager_attribute { ++ struct attribute attr; ++ ssize_t (*show)(struct omap_overlay_manager *, char *); ++ ssize_t (*store)(struct omap_overlay_manager *, const char *, size_t); ++}; ++ ++#define MANAGER_ATTR(_name, _mode, _show, _store) \ ++ struct manager_attribute manager_attr_##_name = \ ++ __ATTR(_name, _mode, _show, _store) ++ ++static MANAGER_ATTR(name, S_IRUGO, manager_name_show, NULL); ++static MANAGER_ATTR(display, S_IRUGO|S_IWUSR, ++ manager_display_show, manager_display_store); ++static MANAGER_ATTR(default_color, S_IRUGO|S_IWUSR, ++ manager_default_color_show, manager_default_color_store); ++static MANAGER_ATTR(trans_key_type, S_IRUGO|S_IWUSR, ++ manager_trans_key_type_show, manager_trans_key_type_store); ++static MANAGER_ATTR(trans_key_value, S_IRUGO|S_IWUSR, ++ manager_trans_key_value_show, manager_trans_key_value_store); ++static MANAGER_ATTR(trans_key_enabled, S_IRUGO|S_IWUSR, ++ manager_trans_key_enabled_show, ++ manager_trans_key_enabled_store); ++static MANAGER_ATTR(alpha_blending_enabled, S_IRUGO|S_IWUSR, ++ manager_alpha_blending_enabled_show, ++ manager_alpha_blending_enabled_store); ++ ++ ++static struct attribute *manager_sysfs_attrs[] = { ++ &manager_attr_name.attr, ++ &manager_attr_display.attr, ++ &manager_attr_default_color.attr, ++ &manager_attr_trans_key_type.attr, ++ &manager_attr_trans_key_value.attr, ++ &manager_attr_trans_key_enabled.attr, ++ &manager_attr_alpha_blending_enabled.attr, ++ NULL ++}; ++ ++static ssize_t manager_attr_show(struct kobject *kobj, struct attribute *attr, ++ char *buf) ++{ ++ struct omap_overlay_manager *manager; ++ struct manager_attribute *manager_attr; ++ ++ manager = container_of(kobj, struct omap_overlay_manager, kobj); ++ manager_attr = container_of(attr, struct manager_attribute, attr); ++ ++ if (!manager_attr->show) ++ return -ENOENT; ++ ++ return manager_attr->show(manager, buf); ++} ++ ++static ssize_t manager_attr_store(struct kobject *kobj, struct attribute *attr, ++ const char *buf, size_t size) ++{ ++ struct omap_overlay_manager *manager; ++ struct manager_attribute *manager_attr; ++ ++ manager = container_of(kobj, struct omap_overlay_manager, kobj); ++ manager_attr = container_of(attr, struct manager_attribute, attr); ++ ++ if (!manager_attr->store) ++ return -ENOENT; ++ ++ return manager_attr->store(manager, buf, size); ++} ++ ++static struct sysfs_ops manager_sysfs_ops = { ++ .show = manager_attr_show, ++ .store = manager_attr_store, ++}; ++ ++static struct kobj_type manager_ktype = { ++ .sysfs_ops = &manager_sysfs_ops, ++ .default_attrs = manager_sysfs_attrs, ++}; ++ ++/* ++ * We have 4 levels of cache for the dispc settings. First two are in SW and ++ * the latter two in HW. ++ * ++ * +--------------------+ ++ * |overlay/manager_info| ++ * +--------------------+ ++ * v ++ * apply() ++ * v ++ * +--------------------+ ++ * | dss_cache | ++ * +--------------------+ ++ * v ++ * configure() ++ * v ++ * +--------------------+ ++ * | shadow registers | ++ * +--------------------+ ++ * v ++ * VFP or lcd/digit_enable ++ * v ++ * +--------------------+ ++ * | registers | ++ * +--------------------+ ++ */ ++ ++struct overlay_cache_data { ++ /* If true, cache changed, but not written to shadow registers. Set ++ * in apply(), cleared when registers written. */ ++ bool dirty; ++ /* If true, shadow registers contain changed values not yet in real ++ * registers. Set when writing to shadow registers, cleared at ++ * VSYNC/EVSYNC */ ++ bool shadow_dirty; ++ ++ bool enabled; ++ ++ u32 paddr; ++ void __iomem *vaddr; ++ u16 screen_width; ++ u16 width; ++ u16 height; ++ enum omap_color_mode color_mode; ++ u8 rotation; ++ enum omap_dss_rotation_type rotation_type; ++ bool mirror; ++ ++ u16 pos_x; ++ u16 pos_y; ++ u16 out_width; /* if 0, out_width == width */ ++ u16 out_height; /* if 0, out_height == height */ ++ u8 global_alpha; ++ ++ enum omap_channel channel; ++ bool replication; ++ bool ilace; ++ ++ enum omap_burst_size burst_size; ++ u32 fifo_low; ++ u32 fifo_high; ++ ++ bool manual_update; ++}; ++ ++struct manager_cache_data { ++ /* If true, cache changed, but not written to shadow registers. Set ++ * in apply(), cleared when registers written. */ ++ bool dirty; ++ /* If true, shadow registers contain changed values not yet in real ++ * registers. Set when writing to shadow registers, cleared at ++ * VSYNC/EVSYNC */ ++ bool shadow_dirty; ++ ++ u32 default_color; ++ ++ enum omap_dss_trans_key_type trans_key_type; ++ u32 trans_key; ++ bool trans_enabled; ++ ++ bool alpha_enabled; ++ ++ bool manual_upd_display; ++ bool manual_update; ++ bool do_manual_update; ++ ++ /* manual update region */ ++ u16 x, y, w, h; ++}; ++ ++static struct { ++ spinlock_t lock; ++ struct overlay_cache_data overlay_cache[3]; ++ struct manager_cache_data manager_cache[2]; ++ ++ bool irq_enabled; ++} dss_cache; ++ ++ ++ ++static int omap_dss_set_device(struct omap_overlay_manager *mgr, ++ struct omap_dss_device *dssdev) ++{ ++ int i; ++ int r; ++ ++ if (dssdev->manager) { ++ DSSERR("display '%s' already has a manager '%s'\n", ++ dssdev->name, dssdev->manager->name); ++ return -EINVAL; ++ } ++ ++ if ((mgr->supported_displays & dssdev->type) == 0) { ++ DSSERR("display '%s' does not support manager '%s'\n", ++ dssdev->name, mgr->name); ++ return -EINVAL; ++ } ++ ++ for (i = 0; i < mgr->num_overlays; i++) { ++ struct omap_overlay *ovl = mgr->overlays[i]; ++ ++ if (ovl->manager != mgr || !ovl->info.enabled) ++ continue; ++ ++ r = dss_check_overlay(ovl, dssdev); ++ if (r) ++ return r; ++ } ++ ++ dssdev->manager = mgr; ++ mgr->device = dssdev; ++ mgr->device_changed = true; ++ ++ return 0; ++} ++ ++static int omap_dss_unset_device(struct omap_overlay_manager *mgr) ++{ ++ if (!mgr->device) { ++ DSSERR("failed to unset display, display not set.\n"); ++ return -EINVAL; ++ } ++ ++ mgr->device->manager = NULL; ++ mgr->device = NULL; ++ mgr->device_changed = true; ++ ++ return 0; ++} ++ ++static int dss_mgr_wait_for_go(struct omap_overlay_manager *mgr) ++{ ++ unsigned long timeout = msecs_to_jiffies(500); ++ struct manager_cache_data *mc; ++ enum omap_channel channel; ++ u32 irq; ++ int r; ++ int i; ++ ++ if (!mgr->device) ++ return 0; ++ ++ if (mgr->device->type == OMAP_DISPLAY_TYPE_VENC) { ++ irq = DISPC_IRQ_EVSYNC_ODD | DISPC_IRQ_EVSYNC_EVEN; ++ channel = OMAP_DSS_CHANNEL_DIGIT; ++ } else { ++ if (mgr->device->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) { ++ enum omap_dss_update_mode mode; ++ mode = mgr->device->get_update_mode(mgr->device); ++ if (mode != OMAP_DSS_UPDATE_AUTO) ++ return 0; ++ ++ irq = DISPC_IRQ_FRAMEDONE; ++ } else { ++ irq = DISPC_IRQ_VSYNC; ++ } ++ channel = OMAP_DSS_CHANNEL_LCD; ++ } ++ ++ mc = &dss_cache.manager_cache[mgr->id]; ++ i = 0; ++ while (1) { ++ unsigned long flags; ++ bool shadow_dirty, dirty; ++ ++ spin_lock_irqsave(&dss_cache.lock, flags); ++ dirty = mc->dirty; ++ shadow_dirty = mc->shadow_dirty; ++ spin_unlock_irqrestore(&dss_cache.lock, flags); ++ ++ if (!dirty && !shadow_dirty) { ++ r = 0; ++ break; ++ } ++ ++ /* 4 iterations is the worst case: ++ * 1 - initial iteration, dirty = true (between VFP and VSYNC) ++ * 2 - first VSYNC, dirty = true ++ * 3 - dirty = false, shadow_dirty = true ++ * 4 - shadow_dirty = false */ ++ if (i++ == 3) { ++ DSSERR("mgr(%d)->wait_for_go() not finishing\n", ++ mgr->id); ++ r = 0; ++ break; ++ } ++ ++ r = omap_dispc_wait_for_irq_interruptible_timeout(irq, timeout); ++ if (r == -ERESTARTSYS) ++ break; ++ ++ if (r) { ++ DSSERR("mgr(%d)->wait_for_go() timeout\n", mgr->id); ++ break; ++ } ++ } ++ ++ return r; ++} ++ ++int dss_mgr_wait_for_go_ovl(struct omap_overlay *ovl) ++{ ++ unsigned long timeout = msecs_to_jiffies(500); ++ enum omap_channel channel; ++ struct overlay_cache_data *oc; ++ struct omap_dss_device *dssdev; ++ u32 irq; ++ int r; ++ int i; ++ ++ if (!ovl->manager || !ovl->manager->device) ++ return 0; ++ ++ dssdev = ovl->manager->device; ++ ++ if (dssdev->type == OMAP_DISPLAY_TYPE_VENC) { ++ irq = DISPC_IRQ_EVSYNC_ODD | DISPC_IRQ_EVSYNC_EVEN; ++ channel = OMAP_DSS_CHANNEL_DIGIT; ++ } else { ++ if (dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) { ++ enum omap_dss_update_mode mode; ++ mode = dssdev->get_update_mode(dssdev); ++ if (mode != OMAP_DSS_UPDATE_AUTO) ++ return 0; ++ ++ irq = DISPC_IRQ_FRAMEDONE; ++ } else { ++ irq = DISPC_IRQ_VSYNC; ++ } ++ channel = OMAP_DSS_CHANNEL_LCD; ++ } ++ ++ oc = &dss_cache.overlay_cache[ovl->id]; ++ i = 0; ++ while (1) { ++ unsigned long flags; ++ bool shadow_dirty, dirty; ++ ++ spin_lock_irqsave(&dss_cache.lock, flags); ++ dirty = oc->dirty; ++ shadow_dirty = oc->shadow_dirty; ++ spin_unlock_irqrestore(&dss_cache.lock, flags); ++ ++ if (!dirty && !shadow_dirty) { ++ r = 0; ++ break; ++ } ++ ++ /* 4 iterations is the worst case: ++ * 1 - initial iteration, dirty = true (between VFP and VSYNC) ++ * 2 - first VSYNC, dirty = true ++ * 3 - dirty = false, shadow_dirty = true ++ * 4 - shadow_dirty = false */ ++ if (i++ == 3) { ++ DSSERR("ovl(%d)->wait_for_go() not finishing\n", ++ ovl->id); ++ r = 0; ++ break; ++ } ++ ++ r = omap_dispc_wait_for_irq_interruptible_timeout(irq, timeout); ++ if (r == -ERESTARTSYS) ++ break; ++ ++ if (r) { ++ DSSERR("ovl(%d)->wait_for_go() timeout\n", ovl->id); ++ break; ++ } ++ } ++ ++ return r; ++} ++ ++static int overlay_enabled(struct omap_overlay *ovl) ++{ ++ return ovl->info.enabled && ovl->manager && ovl->manager->device; ++} ++ ++/* Is rect1 a subset of rect2? */ ++static bool rectangle_subset(int x1, int y1, int w1, int h1, ++ int x2, int y2, int w2, int h2) ++{ ++ if (x1 < x2 || y1 < y2) ++ return false; ++ ++ if (x1 + w1 > x2 + w2) ++ return false; ++ ++ if (y1 + h1 > y2 + h2) ++ return false; ++ ++ return true; ++} ++ ++/* Do rect1 and rect2 overlap? */ ++static bool rectangle_intersects(int x1, int y1, int w1, int h1, ++ int x2, int y2, int w2, int h2) ++{ ++ if (x1 >= x2 + w2) ++ return false; ++ ++ if (x2 >= x1 + w1) ++ return false; ++ ++ if (y1 >= y2 + h2) ++ return false; ++ ++ if (y2 >= y1 + h1) ++ return false; ++ ++ return true; ++} ++ ++static bool dispc_is_overlay_scaled(struct overlay_cache_data *oc) ++{ ++ if (oc->out_width != 0 && oc->width != oc->out_width) ++ return true; ++ ++ if (oc->out_height != 0 && oc->height != oc->out_height) ++ return true; ++ ++ return false; ++} ++ ++static int configure_overlay(enum omap_plane plane) ++{ ++ struct overlay_cache_data *c; ++ struct manager_cache_data *mc; ++ u16 outw, outh; ++ u16 x, y, w, h; ++ u32 paddr; ++ int r; ++ ++ DSSDBGF("%d", plane); ++ ++ c = &dss_cache.overlay_cache[plane]; ++ ++ if (!c->enabled) { ++ dispc_enable_plane(plane, 0); ++ return 0; ++ } ++ ++ mc = &dss_cache.manager_cache[c->channel]; ++ ++ x = c->pos_x; ++ y = c->pos_y; ++ w = c->width; ++ h = c->height; ++ outw = c->out_width == 0 ? c->width : c->out_width; ++ outh = c->out_height == 0 ? c->height : c->out_height; ++ paddr = c->paddr; ++ ++ if (c->manual_update && mc->do_manual_update) { ++ unsigned bpp; ++ /* If the overlay is outside the update region, disable it */ ++ if (!rectangle_intersects(mc->x, mc->y, mc->w, mc->h, ++ x, y, outw, outh)) { ++ dispc_enable_plane(plane, 0); ++ return 0; ++ } ++ ++ switch (c->color_mode) { ++ case OMAP_DSS_COLOR_RGB16: ++ case OMAP_DSS_COLOR_ARGB16: ++ case OMAP_DSS_COLOR_YUV2: ++ case OMAP_DSS_COLOR_UYVY: ++ bpp = 16; ++ break; ++ ++ case OMAP_DSS_COLOR_RGB24P: ++ bpp = 24; ++ break; ++ ++ case OMAP_DSS_COLOR_RGB24U: ++ case OMAP_DSS_COLOR_ARGB32: ++ case OMAP_DSS_COLOR_RGBA32: ++ case OMAP_DSS_COLOR_RGBX32: ++ bpp = 32; ++ break; ++ ++ default: ++ BUG(); ++ } ++ ++ if (dispc_is_overlay_scaled(c)) { ++ /* If the overlay is scaled, the update area has ++ * already been enlarged to cover the whole overlay. We ++ * only need to adjust x/y here */ ++ x = c->pos_x - mc->x; ++ y = c->pos_y - mc->y; ++ } else { ++ if (mc->x > c->pos_x) { ++ x = 0; ++ w -= (mc->x - c->pos_x); ++ paddr += (mc->x - c->pos_x) * bpp / 8; ++ } else { ++ x = c->pos_x - mc->x; ++ } ++ ++ if (mc->y > c->pos_y) { ++ y = 0; ++ h -= (mc->y - c->pos_y); ++ paddr += (mc->y - c->pos_y) * c->screen_width * ++ bpp / 8; ++ } else { ++ y = c->pos_y - mc->y; ++ } ++ ++ if (mc->w < (x+w)) ++ w -= (x+w) - (mc->w); ++ ++ if (mc->h < (y+h)) ++ h -= (y+h) - (mc->h); ++ ++ outw = w; ++ outh = h; ++ } ++ } ++ ++ r = dispc_setup_plane(plane, ++ paddr, ++ c->screen_width, ++ x, y, ++ w, h, ++ outw, outh, ++ c->color_mode, ++ c->ilace, ++ c->rotation_type, ++ c->rotation, ++ c->mirror, ++ c->global_alpha); ++ ++ if (r) { ++ /* this shouldn't happen */ ++ DSSERR("dispc_setup_plane failed for ovl %d\n", plane); ++ dispc_enable_plane(plane, 0); ++ return r; ++ } ++ ++ dispc_enable_replication(plane, c->replication); ++ ++ dispc_set_burst_size(plane, c->burst_size); ++ dispc_setup_plane_fifo(plane, c->fifo_low, c->fifo_high); ++ ++ dispc_enable_plane(plane, 1); ++ ++ return 0; ++} ++ ++static void configure_manager(enum omap_channel channel) ++{ ++ struct manager_cache_data *c; ++ ++ DSSDBGF("%d", channel); ++ ++ c = &dss_cache.manager_cache[channel]; ++ ++ dispc_set_trans_key(channel, c->trans_key_type, c->trans_key); ++ dispc_enable_trans_key(channel, c->trans_enabled); ++ dispc_enable_alpha_blending(channel, c->alpha_enabled); ++} ++ ++/* configure_dispc() tries to write values from cache to shadow registers. ++ * It writes only to those managers/overlays that are not busy. ++ * returns 0 if everything could be written to shadow registers. ++ * returns 1 if not everything could be written to shadow registers. */ ++static int configure_dispc(void) ++{ ++ struct overlay_cache_data *oc; ++ struct manager_cache_data *mc; ++ const int num_ovls = ARRAY_SIZE(dss_cache.overlay_cache); ++ const int num_mgrs = ARRAY_SIZE(dss_cache.manager_cache); ++ int i; ++ int r; ++ bool mgr_busy[2]; ++ bool mgr_go[2]; ++ bool busy; ++ ++ r = 0; ++ busy = false; ++ ++ mgr_busy[0] = dispc_go_busy(0); ++ mgr_busy[1] = dispc_go_busy(1); ++ mgr_go[0] = false; ++ mgr_go[1] = false; ++ ++ /* Commit overlay settings */ ++ for (i = 0; i < num_ovls; ++i) { ++ oc = &dss_cache.overlay_cache[i]; ++ mc = &dss_cache.manager_cache[oc->channel]; ++ ++ if (!oc->dirty) ++ continue; ++ ++ if (oc->manual_update && !mc->do_manual_update) ++ continue; ++ ++ if (mgr_busy[oc->channel]) { ++ busy = true; ++ continue; ++ } ++ ++ r = configure_overlay(i); ++ if (r) ++ DSSERR("configure_overlay %d failed\n", i); ++ ++ oc->dirty = false; ++ oc->shadow_dirty = true; ++ mgr_go[oc->channel] = true; ++ } ++ ++ /* Commit manager settings */ ++ for (i = 0; i < num_mgrs; ++i) { ++ mc = &dss_cache.manager_cache[i]; ++ ++ if (!mc->dirty) ++ continue; ++ ++ if (mc->manual_update && !mc->do_manual_update) ++ continue; ++ ++ if (mgr_busy[i]) { ++ busy = true; ++ continue; ++ } ++ ++ configure_manager(i); ++ mc->dirty = false; ++ mc->shadow_dirty = true; ++ mgr_go[i] = true; ++ } ++ ++ /* set GO */ ++ for (i = 0; i < num_mgrs; ++i) { ++ mc = &dss_cache.manager_cache[i]; ++ ++ if (!mgr_go[i]) ++ continue; ++ ++ /* We don't need GO with manual update display. LCD iface will ++ * always be turned off after frame, and new settings will be ++ * taken in to use at next update */ ++ if (!mc->manual_upd_display) ++ dispc_go(i); ++ } ++ ++ if (busy) ++ r = 1; ++ else ++ r = 0; ++ ++ return r; ++} ++ ++/* Configure dispc for partial update. Return possibly modified update ++ * area */ ++void dss_setup_partial_planes(struct omap_dss_device *dssdev, ++ u16 *xi, u16 *yi, u16 *wi, u16 *hi) ++{ ++ struct overlay_cache_data *oc; ++ struct manager_cache_data *mc; ++ const int num_ovls = ARRAY_SIZE(dss_cache.overlay_cache); ++ struct omap_overlay_manager *mgr; ++ int i; ++ u16 x, y, w, h; ++ unsigned long flags; ++ ++ x = *xi; ++ y = *yi; ++ w = *wi; ++ h = *hi; ++ ++ DSSDBG("dispc_setup_partial_planes %d,%d %dx%d\n", ++ *xi, *yi, *wi, *hi); ++ ++ mgr = dssdev->manager; ++ ++ if (!mgr) { ++ DSSDBG("no manager\n"); ++ return; ++ } ++ ++ spin_lock_irqsave(&dss_cache.lock, flags); ++ ++ /* We need to show the whole overlay if it is scaled. So look for ++ * those, and make the update area larger if found. ++ * Also mark the overlay cache dirty */ ++ for (i = 0; i < num_ovls; ++i) { ++ unsigned x1, y1, x2, y2; ++ unsigned outw, outh; ++ ++ oc = &dss_cache.overlay_cache[i]; ++ ++ if (oc->channel != mgr->id) ++ continue; ++ ++ oc->dirty = true; ++ ++ if (!oc->enabled) ++ continue; ++ ++ if (!dispc_is_overlay_scaled(oc)) ++ continue; ++ ++ outw = oc->out_width == 0 ? oc->width : oc->out_width; ++ outh = oc->out_height == 0 ? oc->height : oc->out_height; ++ ++ /* is the overlay outside the update region? */ ++ if (!rectangle_intersects(x, y, w, h, ++ oc->pos_x, oc->pos_y, ++ outw, outh)) ++ continue; ++ ++ /* if the overlay totally inside the update region? */ ++ if (rectangle_subset(oc->pos_x, oc->pos_y, outw, outh, ++ x, y, w, h)) ++ continue; ++ ++ if (x > oc->pos_x) ++ x1 = oc->pos_x; ++ else ++ x1 = x; ++ ++ if (y > oc->pos_y) ++ y1 = oc->pos_y; ++ else ++ y1 = y; ++ ++ if ((x + w) < (oc->pos_x + outw)) ++ x2 = oc->pos_x + outw; ++ else ++ x2 = x + w; ++ ++ if ((y + h) < (oc->pos_y + outh)) ++ y2 = oc->pos_y + outh; ++ else ++ y2 = y + h; ++ ++ x = x1; ++ y = y1; ++ w = x2 - x1; ++ h = y2 - y1; ++ ++ DSSDBG("changing upd area due to ovl(%d) scaling %d,%d %dx%d\n", ++ i, x, y, w, h); ++ } ++ ++ mc = &dss_cache.manager_cache[mgr->id]; ++ mc->do_manual_update = true; ++ mc->x = x; ++ mc->y = y; ++ mc->w = w; ++ mc->h = h; ++ ++ configure_dispc(); ++ ++ mc->do_manual_update = false; ++ ++ spin_unlock_irqrestore(&dss_cache.lock, flags); ++ ++ *xi = x; ++ *yi = y; ++ *wi = w; ++ *hi = h; ++} ++ ++void dss_start_update(struct omap_dss_device *dssdev) ++{ ++ struct manager_cache_data *mc; ++ struct overlay_cache_data *oc; ++ const int num_ovls = ARRAY_SIZE(dss_cache.overlay_cache); ++ const int num_mgrs = ARRAY_SIZE(dss_cache.manager_cache); ++ struct omap_overlay_manager *mgr; ++ int i; ++ ++ mgr = dssdev->manager; ++ ++ for (i = 0; i < num_ovls; ++i) { ++ oc = &dss_cache.overlay_cache[i]; ++ if (oc->channel != mgr->id) ++ continue; ++ ++ oc->shadow_dirty = false; ++ } ++ ++ for (i = 0; i < num_mgrs; ++i) { ++ mc = &dss_cache.manager_cache[i]; ++ if (mgr->id != i) ++ continue; ++ ++ mc->shadow_dirty = false; ++ } ++ ++ dispc_enable_lcd_out(1); ++} ++ ++static void dss_apply_irq_handler(void *data, u32 mask) ++{ ++ struct manager_cache_data *mc; ++ struct overlay_cache_data *oc; ++ const int num_ovls = ARRAY_SIZE(dss_cache.overlay_cache); ++ const int num_mgrs = ARRAY_SIZE(dss_cache.manager_cache); ++ int i, r; ++ bool mgr_busy[2]; ++ ++ mgr_busy[0] = dispc_go_busy(0); ++ mgr_busy[1] = dispc_go_busy(1); ++ ++ spin_lock(&dss_cache.lock); ++ ++ for (i = 0; i < num_ovls; ++i) { ++ oc = &dss_cache.overlay_cache[i]; ++ if (!mgr_busy[oc->channel]) ++ oc->shadow_dirty = false; ++ } ++ ++ for (i = 0; i < num_mgrs; ++i) { ++ mc = &dss_cache.manager_cache[i]; ++ if (!mgr_busy[i]) ++ mc->shadow_dirty = false; ++ } ++ ++ r = configure_dispc(); ++ if (r == 1) ++ goto end; ++ ++ /* re-read busy flags */ ++ mgr_busy[0] = dispc_go_busy(0); ++ mgr_busy[1] = dispc_go_busy(1); ++ ++ /* keep running as long as there are busy managers, so that ++ * we can collect overlay-applied information */ ++ for (i = 0; i < num_mgrs; ++i) { ++ if (mgr_busy[i]) ++ goto end; ++ } ++ ++ omap_dispc_unregister_isr(dss_apply_irq_handler, NULL, ++ DISPC_IRQ_VSYNC | DISPC_IRQ_EVSYNC_ODD | ++ DISPC_IRQ_EVSYNC_EVEN); ++ dss_cache.irq_enabled = false; ++ ++end: ++ spin_unlock(&dss_cache.lock); ++} ++ ++static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr) ++{ ++ struct overlay_cache_data *oc; ++ struct manager_cache_data *mc; ++ int i; ++ struct omap_overlay *ovl; ++ int num_planes_enabled = 0; ++ bool use_fifomerge; ++ unsigned long flags; ++ int r; ++ ++ DSSDBG("omap_dss_mgr_apply(%s)\n", mgr->name); ++ ++ spin_lock_irqsave(&dss_cache.lock, flags); ++ ++ /* Configure overlays */ ++ for (i = 0; i < omap_dss_get_num_overlays(); ++i) { ++ struct omap_dss_device *dssdev; ++ ++ ovl = omap_dss_get_overlay(i); ++ ++ if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC)) ++ continue; ++ ++ oc = &dss_cache.overlay_cache[ovl->id]; ++ ++ if (!overlay_enabled(ovl)) { ++ if (oc->enabled) { ++ oc->enabled = false; ++ oc->dirty = true; ++ } ++ continue; ++ } ++ ++ if (!ovl->info_dirty) { ++ if (oc->enabled) ++ ++num_planes_enabled; ++ continue; ++ } ++ ++ dssdev = ovl->manager->device; ++ ++ if (dss_check_overlay(ovl, dssdev)) { ++ if (oc->enabled) { ++ oc->enabled = false; ++ oc->dirty = true; ++ } ++ continue; ++ } ++ ++ ovl->info_dirty = false; ++ oc->dirty = true; ++ ++ oc->paddr = ovl->info.paddr; ++ oc->vaddr = ovl->info.vaddr; ++ oc->screen_width = ovl->info.screen_width; ++ oc->width = ovl->info.width; ++ oc->height = ovl->info.height; ++ oc->color_mode = ovl->info.color_mode; ++ oc->rotation = ovl->info.rotation; ++ oc->rotation_type = ovl->info.rotation_type; ++ oc->mirror = ovl->info.mirror; ++ oc->pos_x = ovl->info.pos_x; ++ oc->pos_y = ovl->info.pos_y; ++ oc->out_width = ovl->info.out_width; ++ oc->out_height = ovl->info.out_height; ++ oc->global_alpha = ovl->info.global_alpha; ++ ++ oc->replication = ++ dss_use_replication(dssdev, ovl->info.color_mode); ++ ++ oc->ilace = dssdev->type == OMAP_DISPLAY_TYPE_VENC; ++ ++ oc->channel = ovl->manager->id; ++ ++ oc->enabled = true; ++ ++ oc->manual_update = ++ dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE && ++ dssdev->get_update_mode(dssdev) != OMAP_DSS_UPDATE_AUTO; ++ ++ ++num_planes_enabled; ++ } ++ ++ /* Configure managers */ ++ list_for_each_entry(mgr, &manager_list, list) { ++ struct omap_dss_device *dssdev; ++ ++ if (!(mgr->caps & OMAP_DSS_OVL_MGR_CAP_DISPC)) ++ continue; ++ ++ mc = &dss_cache.manager_cache[mgr->id]; ++ ++ if (mgr->device_changed) { ++ mgr->device_changed = false; ++ mgr->info_dirty = true; ++ } ++ ++ if (!mgr->info_dirty) ++ continue; ++ ++ if (!mgr->device) ++ continue; ++ ++ dssdev = mgr->device; ++ ++ mgr->info_dirty = false; ++ mc->dirty = true; ++ ++ mc->default_color = mgr->info.default_color; ++ mc->trans_key_type = mgr->info.trans_key_type; ++ mc->trans_key = mgr->info.trans_key; ++ mc->trans_enabled = mgr->info.trans_enabled; ++ mc->alpha_enabled = mgr->info.alpha_enabled; ++ ++ mc->manual_upd_display = ++ dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE; ++ ++ mc->manual_update = ++ dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE && ++ dssdev->get_update_mode(dssdev) != OMAP_DSS_UPDATE_AUTO; ++ } ++ ++ /* XXX TODO: Try to get fifomerge working. The problem is that it ++ * affects both managers, not individually but at the same time. This ++ * means the change has to be well synchronized. I guess the proper way ++ * is to have a two step process for fifo merge: ++ * fifomerge enable: ++ * 1. disable other planes, leaving one plane enabled ++ * 2. wait until the planes are disabled on HW ++ * 3. config merged fifo thresholds, enable fifomerge ++ * fifomerge disable: ++ * 1. config unmerged fifo thresholds, disable fifomerge ++ * 2. wait until fifo changes are in HW ++ * 3. enable planes ++ */ ++ use_fifomerge = false; ++ ++ /* Configure overlay fifos */ ++ for (i = 0; i < omap_dss_get_num_overlays(); ++i) { ++ struct omap_dss_device *dssdev; ++ u32 size; ++ ++ ovl = omap_dss_get_overlay(i); ++ ++ if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC)) ++ continue; ++ ++ oc = &dss_cache.overlay_cache[ovl->id]; ++ ++ if (!oc->enabled) ++ continue; ++ ++ dssdev = ovl->manager->device; ++ ++ size = dispc_get_plane_fifo_size(ovl->id); ++ if (use_fifomerge) ++ size *= 3; ++ ++ switch (dssdev->type) { ++ case OMAP_DISPLAY_TYPE_DPI: ++ case OMAP_DISPLAY_TYPE_DBI: ++ case OMAP_DISPLAY_TYPE_SDI: ++ case OMAP_DISPLAY_TYPE_VENC: ++ default_get_overlay_fifo_thresholds(ovl->id, size, ++ &oc->burst_size, &oc->fifo_low, ++ &oc->fifo_high); ++ break; ++#ifdef CONFIG_OMAP2_DSS_DSI ++ case OMAP_DISPLAY_TYPE_DSI: ++ dsi_get_overlay_fifo_thresholds(ovl->id, size, ++ &oc->burst_size, &oc->fifo_low, ++ &oc->fifo_high); ++ break; ++#endif ++ default: ++ BUG(); ++ } ++ } ++ ++ r = 0; ++ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); ++ if (!dss_cache.irq_enabled) { ++ r = omap_dispc_register_isr(dss_apply_irq_handler, NULL, ++ DISPC_IRQ_VSYNC | DISPC_IRQ_EVSYNC_ODD | ++ DISPC_IRQ_EVSYNC_EVEN); ++ dss_cache.irq_enabled = true; ++ } ++ configure_dispc(); ++ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); ++ ++ spin_unlock_irqrestore(&dss_cache.lock, flags); ++ ++ return r; ++} ++ ++static int dss_check_manager(struct omap_overlay_manager *mgr) ++{ ++ /* OMAP supports only graphics source transparency color key and alpha ++ * blending simultaneously. See TRM 15.4.2.4.2.2 Alpha Mode */ ++ ++ if (mgr->info.alpha_enabled && mgr->info.trans_enabled && ++ mgr->info.trans_key_type != OMAP_DSS_COLOR_KEY_GFX_DST) ++ return -EINVAL; ++ ++ return 0; ++} ++ ++static int omap_dss_mgr_set_info(struct omap_overlay_manager *mgr, ++ struct omap_overlay_manager_info *info) ++{ ++ int r; ++ struct omap_overlay_manager_info old_info; ++ ++ old_info = mgr->info; ++ mgr->info = *info; ++ ++ r = dss_check_manager(mgr); ++ if (r) { ++ mgr->info = old_info; ++ return r; ++ } ++ ++ mgr->info_dirty = true; ++ ++ return 0; ++} ++ ++static void omap_dss_mgr_get_info(struct omap_overlay_manager *mgr, ++ struct omap_overlay_manager_info *info) ++{ ++ *info = mgr->info; ++} ++ ++static void omap_dss_add_overlay_manager(struct omap_overlay_manager *manager) ++{ ++ ++num_managers; ++ list_add_tail(&manager->list, &manager_list); ++} ++ ++int dss_init_overlay_managers(struct platform_device *pdev) ++{ ++ int i, r; ++ ++ spin_lock_init(&dss_cache.lock); ++ ++ INIT_LIST_HEAD(&manager_list); ++ ++ num_managers = 0; ++ ++ for (i = 0; i < 2; ++i) { ++ struct omap_overlay_manager *mgr; ++ mgr = kzalloc(sizeof(*mgr), GFP_KERNEL); ++ ++ BUG_ON(mgr == NULL); ++ ++ switch (i) { ++ case 0: ++ mgr->name = "lcd"; ++ mgr->id = OMAP_DSS_CHANNEL_LCD; ++ mgr->supported_displays = ++ OMAP_DISPLAY_TYPE_DPI | OMAP_DISPLAY_TYPE_DBI | ++ OMAP_DISPLAY_TYPE_SDI | OMAP_DISPLAY_TYPE_DSI; ++ break; ++ case 1: ++ mgr->name = "tv"; ++ mgr->id = OMAP_DSS_CHANNEL_DIGIT; ++ mgr->supported_displays = OMAP_DISPLAY_TYPE_VENC; ++ break; ++ } ++ ++ mgr->set_device = &omap_dss_set_device; ++ mgr->unset_device = &omap_dss_unset_device; ++ mgr->apply = &omap_dss_mgr_apply; ++ mgr->set_manager_info = &omap_dss_mgr_set_info; ++ mgr->get_manager_info = &omap_dss_mgr_get_info; ++ mgr->wait_for_go = &dss_mgr_wait_for_go; ++ ++ mgr->caps = OMAP_DSS_OVL_MGR_CAP_DISPC; ++ ++ dss_overlay_setup_dispc_manager(mgr); ++ ++ omap_dss_add_overlay_manager(mgr); ++ ++ r = kobject_init_and_add(&mgr->kobj, &manager_ktype, ++ &pdev->dev.kobj, "manager%d", i); ++ ++ if (r) { ++ DSSERR("failed to create sysfs file\n"); ++ continue; ++ } ++ } ++ ++#ifdef L4_EXAMPLE ++ { ++ int omap_dss_mgr_apply_l4(struct omap_overlay_manager *mgr) ++ { ++ DSSDBG("omap_dss_mgr_apply_l4(%s)\n", mgr->name); ++ ++ return 0; ++ } ++ ++ struct omap_overlay_manager *mgr; ++ mgr = kzalloc(sizeof(*mgr), GFP_KERNEL); ++ ++ BUG_ON(mgr == NULL); ++ ++ mgr->name = "l4"; ++ mgr->supported_displays = ++ OMAP_DISPLAY_TYPE_DBI | OMAP_DISPLAY_TYPE_DSI; ++ ++ mgr->set_device = &omap_dss_set_device; ++ mgr->unset_device = &omap_dss_unset_device; ++ mgr->apply = &omap_dss_mgr_apply_l4; ++ mgr->set_manager_info = &omap_dss_mgr_set_info; ++ mgr->get_manager_info = &omap_dss_mgr_get_info; ++ ++ dss_overlay_setup_l4_manager(mgr); ++ ++ omap_dss_add_overlay_manager(mgr); ++ ++ r = kobject_init_and_add(&mgr->kobj, &manager_ktype, ++ &pdev->dev.kobj, "managerl4"); ++ ++ if (r) ++ DSSERR("failed to create sysfs file\n"); ++ } ++#endif ++ ++ return 0; ++} ++ ++void dss_uninit_overlay_managers(struct platform_device *pdev) ++{ ++ struct omap_overlay_manager *mgr; ++ ++ while (!list_empty(&manager_list)) { ++ mgr = list_first_entry(&manager_list, ++ struct omap_overlay_manager, list); ++ list_del(&mgr->list); ++ kobject_del(&mgr->kobj); ++ kobject_put(&mgr->kobj); ++ kfree(mgr); ++ } ++ ++ num_managers = 0; ++} ++ ++int omap_dss_get_num_overlay_managers(void) ++{ ++ return num_managers; ++} ++EXPORT_SYMBOL(omap_dss_get_num_overlay_managers); ++ ++struct omap_overlay_manager *omap_dss_get_overlay_manager(int num) ++{ ++ int i = 0; ++ struct omap_overlay_manager *mgr; ++ ++ list_for_each_entry(mgr, &manager_list, list) { ++ if (i++ == num) ++ return mgr; ++ } ++ ++ return NULL; ++} ++EXPORT_SYMBOL(omap_dss_get_overlay_manager); ++ +diff --git a/drivers/video/omap2/dss/overlay.c b/drivers/video/omap2/dss/overlay.c +new file mode 100644 +index 0000000..c7cb81b +--- /dev/null ++++ b/drivers/video/omap2/dss/overlay.c +@@ -0,0 +1,673 @@ ++/* ++ * linux/drivers/video/omap2/dss/overlay.c ++ * ++ * Copyright (C) 2009 Nokia Corporation ++ * Author: Tomi Valkeinen ++ * ++ * Some code and ideas taken from drivers/video/omap/ driver ++ * by Imre Deak. ++ * ++ * 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. ++ * ++ * 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, see . ++ */ ++ ++#define DSS_SUBSYS_NAME "OVERLAY" ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#include "dss.h" ++ ++static int num_overlays; ++static struct list_head overlay_list; ++ ++static ssize_t overlay_name_show(struct omap_overlay *ovl, char *buf) ++{ ++ return snprintf(buf, PAGE_SIZE, "%s\n", ovl->name); ++} ++ ++static ssize_t overlay_manager_show(struct omap_overlay *ovl, char *buf) ++{ ++ return snprintf(buf, PAGE_SIZE, "%s\n", ++ ovl->manager ? ovl->manager->name : ""); ++} ++ ++static ssize_t overlay_manager_store(struct omap_overlay *ovl, const char *buf, ++ size_t size) ++{ ++ int i, r; ++ struct omap_overlay_manager *mgr = NULL; ++ struct omap_overlay_manager *old_mgr; ++ int len = size; ++ ++ if (buf[size-1] == '\n') ++ --len; ++ ++ if (len > 0) { ++ for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) { ++ mgr = omap_dss_get_overlay_manager(i); ++ ++ if (strncmp(buf, mgr->name, len) == 0) ++ break; ++ ++ mgr = NULL; ++ } ++ } ++ ++ if (len > 0 && mgr == NULL) ++ return -EINVAL; ++ ++ if (mgr) ++ DSSDBG("manager %s found\n", mgr->name); ++ ++ if (mgr == ovl->manager) ++ return size; ++ ++ old_mgr = ovl->manager; ++ ++ /* detach old manager */ ++ if (old_mgr) { ++ r = ovl->unset_manager(ovl); ++ if (r) { ++ DSSERR("detach failed\n"); ++ return r; ++ } ++ ++ r = old_mgr->apply(old_mgr); ++ if (r) ++ return r; ++ } ++ ++ if (mgr) { ++ r = ovl->set_manager(ovl, mgr); ++ if (r) { ++ DSSERR("Failed to attach overlay\n"); ++ return r; ++ } ++ ++ r = mgr->apply(mgr); ++ if (r) ++ return r; ++ } ++ ++ return size; ++} ++ ++static ssize_t overlay_input_size_show(struct omap_overlay *ovl, char *buf) ++{ ++ return snprintf(buf, PAGE_SIZE, "%d,%d\n", ++ ovl->info.width, ovl->info.height); ++} ++ ++static ssize_t overlay_screen_width_show(struct omap_overlay *ovl, char *buf) ++{ ++ return snprintf(buf, PAGE_SIZE, "%d\n", ovl->info.screen_width); ++} ++ ++static ssize_t overlay_position_show(struct omap_overlay *ovl, char *buf) ++{ ++ return snprintf(buf, PAGE_SIZE, "%d,%d\n", ++ ovl->info.pos_x, ovl->info.pos_y); ++} ++ ++static ssize_t overlay_position_store(struct omap_overlay *ovl, ++ const char *buf, size_t size) ++{ ++ int r; ++ char *last; ++ struct omap_overlay_info info; ++ ++ ovl->get_overlay_info(ovl, &info); ++ ++ info.pos_x = simple_strtoul(buf, &last, 10); ++ ++last; ++ if (last - buf >= size) ++ return -EINVAL; ++ ++ info.pos_y = simple_strtoul(last, &last, 10); ++ ++ r = ovl->set_overlay_info(ovl, &info); ++ if (r) ++ return r; ++ ++ if (ovl->manager) { ++ r = ovl->manager->apply(ovl->manager); ++ if (r) ++ return r; ++ } ++ ++ return size; ++} ++ ++static ssize_t overlay_output_size_show(struct omap_overlay *ovl, char *buf) ++{ ++ return snprintf(buf, PAGE_SIZE, "%d,%d\n", ++ ovl->info.out_width, ovl->info.out_height); ++} ++ ++static ssize_t overlay_output_size_store(struct omap_overlay *ovl, ++ const char *buf, size_t size) ++{ ++ int r; ++ char *last; ++ struct omap_overlay_info info; ++ ++ ovl->get_overlay_info(ovl, &info); ++ ++ info.out_width = simple_strtoul(buf, &last, 10); ++ ++last; ++ if (last - buf >= size) ++ return -EINVAL; ++ ++ info.out_height = simple_strtoul(last, &last, 10); ++ ++ r = ovl->set_overlay_info(ovl, &info); ++ if (r) ++ return r; ++ ++ if (ovl->manager) { ++ r = ovl->manager->apply(ovl->manager); ++ if (r) ++ return r; ++ } ++ ++ return size; ++} ++ ++static ssize_t overlay_enabled_show(struct omap_overlay *ovl, char *buf) ++{ ++ return snprintf(buf, PAGE_SIZE, "%d\n", ovl->info.enabled); ++} ++ ++static ssize_t overlay_enabled_store(struct omap_overlay *ovl, const char *buf, ++ size_t size) ++{ ++ int r; ++ struct omap_overlay_info info; ++ ++ ovl->get_overlay_info(ovl, &info); ++ ++ info.enabled = simple_strtoul(buf, NULL, 10); ++ ++ r = ovl->set_overlay_info(ovl, &info); ++ if (r) ++ return r; ++ ++ if (ovl->manager) { ++ r = ovl->manager->apply(ovl->manager); ++ if (r) ++ return r; ++ } ++ ++ return size; ++} ++ ++static ssize_t overlay_global_alpha_show(struct omap_overlay *ovl, char *buf) ++{ ++ return snprintf(buf, PAGE_SIZE, "%d\n", ++ ovl->info.global_alpha); ++} ++ ++static ssize_t overlay_global_alpha_store(struct omap_overlay *ovl, ++ const char *buf, size_t size) ++{ ++ int r; ++ struct omap_overlay_info info; ++ ++ ovl->get_overlay_info(ovl, &info); ++ ++ /* Video1 plane does not support global alpha ++ * to always make it 255 completely opaque ++ */ ++ if (ovl->id == OMAP_DSS_VIDEO1) ++ info.global_alpha = 255; ++ else ++ info.global_alpha = simple_strtoul(buf, NULL, 10); ++ ++ r = ovl->set_overlay_info(ovl, &info); ++ if (r) ++ return r; ++ ++ if (ovl->manager) { ++ r = ovl->manager->apply(ovl->manager); ++ if (r) ++ return r; ++ } ++ ++ return size; ++} ++ ++struct overlay_attribute { ++ struct attribute attr; ++ ssize_t (*show)(struct omap_overlay *, char *); ++ ssize_t (*store)(struct omap_overlay *, const char *, size_t); ++}; ++ ++#define OVERLAY_ATTR(_name, _mode, _show, _store) \ ++ struct overlay_attribute overlay_attr_##_name = \ ++ __ATTR(_name, _mode, _show, _store) ++ ++static OVERLAY_ATTR(name, S_IRUGO, overlay_name_show, NULL); ++static OVERLAY_ATTR(manager, S_IRUGO|S_IWUSR, ++ overlay_manager_show, overlay_manager_store); ++static OVERLAY_ATTR(input_size, S_IRUGO, overlay_input_size_show, NULL); ++static OVERLAY_ATTR(screen_width, S_IRUGO, overlay_screen_width_show, NULL); ++static OVERLAY_ATTR(position, S_IRUGO|S_IWUSR, ++ overlay_position_show, overlay_position_store); ++static OVERLAY_ATTR(output_size, S_IRUGO|S_IWUSR, ++ overlay_output_size_show, overlay_output_size_store); ++static OVERLAY_ATTR(enabled, S_IRUGO|S_IWUSR, ++ overlay_enabled_show, overlay_enabled_store); ++static OVERLAY_ATTR(global_alpha, S_IRUGO|S_IWUSR, ++ overlay_global_alpha_show, overlay_global_alpha_store); ++ ++static struct attribute *overlay_sysfs_attrs[] = { ++ &overlay_attr_name.attr, ++ &overlay_attr_manager.attr, ++ &overlay_attr_input_size.attr, ++ &overlay_attr_screen_width.attr, ++ &overlay_attr_position.attr, ++ &overlay_attr_output_size.attr, ++ &overlay_attr_enabled.attr, ++ &overlay_attr_global_alpha.attr, ++ NULL ++}; ++ ++static ssize_t overlay_attr_show(struct kobject *kobj, struct attribute *attr, ++ char *buf) ++{ ++ struct omap_overlay *overlay; ++ struct overlay_attribute *overlay_attr; ++ ++ overlay = container_of(kobj, struct omap_overlay, kobj); ++ overlay_attr = container_of(attr, struct overlay_attribute, attr); ++ ++ if (!overlay_attr->show) ++ return -ENOENT; ++ ++ return overlay_attr->show(overlay, buf); ++} ++ ++static ssize_t overlay_attr_store(struct kobject *kobj, struct attribute *attr, ++ const char *buf, size_t size) ++{ ++ struct omap_overlay *overlay; ++ struct overlay_attribute *overlay_attr; ++ ++ overlay = container_of(kobj, struct omap_overlay, kobj); ++ overlay_attr = container_of(attr, struct overlay_attribute, attr); ++ ++ if (!overlay_attr->store) ++ return -ENOENT; ++ ++ return overlay_attr->store(overlay, buf, size); ++} ++ ++static struct sysfs_ops overlay_sysfs_ops = { ++ .show = overlay_attr_show, ++ .store = overlay_attr_store, ++}; ++ ++static struct kobj_type overlay_ktype = { ++ .sysfs_ops = &overlay_sysfs_ops, ++ .default_attrs = overlay_sysfs_attrs, ++}; ++ ++/* Check if overlay parameters are compatible with display */ ++int dss_check_overlay(struct omap_overlay *ovl, struct omap_dss_device *dssdev) ++{ ++ struct omap_overlay_info *info; ++ u16 outw, outh; ++ u16 dw, dh; ++ ++ if (!dssdev) ++ return 0; ++ ++ if (!ovl->info.enabled) ++ return 0; ++ ++ info = &ovl->info; ++ ++ if (info->paddr == 0) { ++ DSSDBG("check_overlay failed: paddr 0\n"); ++ return -EINVAL; ++ } ++ ++ dssdev->get_resolution(dssdev, &dw, &dh); ++ ++ DSSDBG("check_overlay %d: (%d,%d %dx%d -> %dx%d) disp (%dx%d)\n", ++ ovl->id, ++ info->pos_x, info->pos_y, ++ info->width, info->height, ++ info->out_width, info->out_height, ++ dw, dh); ++ ++ if ((ovl->caps & OMAP_DSS_OVL_CAP_SCALE) == 0) { ++ outw = info->width; ++ outh = info->height; ++ } else { ++ if (info->out_width == 0) ++ outw = info->width; ++ else ++ outw = info->out_width; ++ ++ if (info->out_height == 0) ++ outh = info->height; ++ else ++ outh = info->out_height; ++ } ++ ++ if (dw < info->pos_x + outw) { ++ DSSDBG("check_overlay failed 1: %d < %d + %d\n", ++ dw, info->pos_x, outw); ++ return -EINVAL; ++ } ++ ++ if (dh < info->pos_y + outh) { ++ DSSDBG("check_overlay failed 2: %d < %d + %d\n", ++ dh, info->pos_y, outh); ++ return -EINVAL; ++ } ++ ++ if ((ovl->supported_modes & info->color_mode) == 0) { ++ DSSERR("overlay doesn't support mode %d\n", info->color_mode); ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++static int dss_ovl_set_overlay_info(struct omap_overlay *ovl, ++ struct omap_overlay_info *info) ++{ ++ int r; ++ struct omap_overlay_info old_info; ++ ++ old_info = ovl->info; ++ ovl->info = *info; ++ ++ if (ovl->manager) { ++ r = dss_check_overlay(ovl, ovl->manager->device); ++ if (r) { ++ ovl->info = old_info; ++ return r; ++ } ++ } ++ ++ ovl->info_dirty = true; ++ ++ return 0; ++} ++ ++static void dss_ovl_get_overlay_info(struct omap_overlay *ovl, ++ struct omap_overlay_info *info) ++{ ++ *info = ovl->info; ++} ++ ++static int dss_ovl_wait_for_go(struct omap_overlay *ovl) ++{ ++ return dss_mgr_wait_for_go_ovl(ovl); ++} ++ ++static int omap_dss_set_manager(struct omap_overlay *ovl, ++ struct omap_overlay_manager *mgr) ++{ ++ if (!mgr) ++ return -EINVAL; ++ ++ if (ovl->manager) { ++ DSSERR("overlay '%s' already has a manager '%s'\n", ++ ovl->name, ovl->manager->name); ++ return -EINVAL; ++ } ++ ++ if (ovl->info.enabled) { ++ DSSERR("overlay has to be disabled to change the manager\n"); ++ return -EINVAL; ++ } ++ ++ ovl->manager = mgr; ++ ++ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); ++ /* XXX: on manual update display, in auto update mode, a bug happens ++ * here. When an overlay is first enabled on LCD, then it's disabled, ++ * and the manager is changed to TV, we sometimes get SYNC_LOST_DIGIT ++ * errors. Waiting before changing the channel_out fixes it. I'm ++ * guessing that the overlay is still somehow being used for the LCD, ++ * but I don't understand how or why. */ ++ msleep(40); ++ dispc_set_channel_out(ovl->id, mgr->id); ++ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); ++ ++ return 0; ++} ++ ++static int omap_dss_unset_manager(struct omap_overlay *ovl) ++{ ++ int r; ++ ++ if (!ovl->manager) { ++ DSSERR("failed to detach overlay: manager not set\n"); ++ return -EINVAL; ++ } ++ ++ if (ovl->info.enabled) { ++ DSSERR("overlay has to be disabled to unset the manager\n"); ++ return -EINVAL; ++ } ++ ++ r = ovl->wait_for_go(ovl); ++ if (r) ++ return r; ++ ++ ovl->manager = NULL; ++ ++ return 0; ++} ++ ++int omap_dss_get_num_overlays(void) ++{ ++ return num_overlays; ++} ++EXPORT_SYMBOL(omap_dss_get_num_overlays); ++ ++struct omap_overlay *omap_dss_get_overlay(int num) ++{ ++ int i = 0; ++ struct omap_overlay *ovl; ++ ++ list_for_each_entry(ovl, &overlay_list, list) { ++ if (i++ == num) ++ return ovl; ++ } ++ ++ return NULL; ++} ++EXPORT_SYMBOL(omap_dss_get_overlay); ++ ++static void omap_dss_add_overlay(struct omap_overlay *overlay) ++{ ++ ++num_overlays; ++ list_add_tail(&overlay->list, &overlay_list); ++} ++ ++static struct omap_overlay *dispc_overlays[3]; ++ ++void dss_overlay_setup_dispc_manager(struct omap_overlay_manager *mgr) ++{ ++ mgr->num_overlays = 3; ++ mgr->overlays = dispc_overlays; ++} ++ ++#ifdef L4_EXAMPLE ++static struct omap_overlay *l4_overlays[1]; ++void dss_overlay_setup_l4_manager(struct omap_overlay_manager *mgr) ++{ ++ mgr->num_overlays = 1; ++ mgr->overlays = l4_overlays; ++} ++#endif ++ ++void dss_init_overlays(struct platform_device *pdev) ++{ ++ int i, r; ++ ++ INIT_LIST_HEAD(&overlay_list); ++ ++ num_overlays = 0; ++ ++ for (i = 0; i < 3; ++i) { ++ struct omap_overlay *ovl; ++ ovl = kzalloc(sizeof(*ovl), GFP_KERNEL); ++ ++ BUG_ON(ovl == NULL); ++ ++ switch (i) { ++ case 0: ++ ovl->name = "gfx"; ++ ovl->id = OMAP_DSS_GFX; ++ ovl->supported_modes = OMAP_DSS_COLOR_GFX_OMAP3; ++ ovl->caps = OMAP_DSS_OVL_CAP_DISPC; ++ ovl->info.global_alpha = 255; ++ break; ++ case 1: ++ ovl->name = "vid1"; ++ ovl->id = OMAP_DSS_VIDEO1; ++ ovl->supported_modes = OMAP_DSS_COLOR_VID_OMAP3; ++ ovl->caps = OMAP_DSS_OVL_CAP_SCALE | ++ OMAP_DSS_OVL_CAP_DISPC; ++ ovl->info.global_alpha = 255; ++ break; ++ case 2: ++ ovl->name = "vid2"; ++ ovl->id = OMAP_DSS_VIDEO2; ++ ovl->supported_modes = OMAP_DSS_COLOR_VID_OMAP3; ++ ovl->caps = OMAP_DSS_OVL_CAP_SCALE | ++ OMAP_DSS_OVL_CAP_DISPC; ++ ovl->info.global_alpha = 255; ++ break; ++ } ++ ++ ovl->set_manager = &omap_dss_set_manager; ++ ovl->unset_manager = &omap_dss_unset_manager; ++ ovl->set_overlay_info = &dss_ovl_set_overlay_info; ++ ovl->get_overlay_info = &dss_ovl_get_overlay_info; ++ ovl->wait_for_go = &dss_ovl_wait_for_go; ++ ++ omap_dss_add_overlay(ovl); ++ ++ r = kobject_init_and_add(&ovl->kobj, &overlay_ktype, ++ &pdev->dev.kobj, "overlay%d", i); ++ ++ if (r) { ++ DSSERR("failed to create sysfs file\n"); ++ continue; ++ } ++ ++ dispc_overlays[i] = ovl; ++ } ++ ++#ifdef L4_EXAMPLE ++ { ++ struct omap_overlay *ovl; ++ ovl = kzalloc(sizeof(*ovl), GFP_KERNEL); ++ ++ BUG_ON(ovl == NULL); ++ ++ ovl->name = "l4"; ++ ovl->supported_modes = OMAP_DSS_COLOR_RGB24U; ++ ++ ovl->set_manager = &omap_dss_set_manager; ++ ovl->unset_manager = &omap_dss_unset_manager; ++ ovl->set_overlay_info = &dss_ovl_set_overlay_info; ++ ovl->get_overlay_info = &dss_ovl_get_overlay_info; ++ ++ omap_dss_add_overlay(ovl); ++ ++ r = kobject_init_and_add(&ovl->kobj, &overlay_ktype, ++ &pdev->dev.kobj, "overlayl4"); ++ ++ if (r) ++ DSSERR("failed to create sysfs file\n"); ++ ++ l4_overlays[0] = ovl; ++ } ++#endif ++} ++ ++/* connect overlays to the new device, if not already connected. if force ++ * selected, connect always. */ ++void dss_recheck_connections(struct omap_dss_device *dssdev, bool force) ++{ ++ int i; ++ struct omap_overlay_manager *lcd_mgr; ++ struct omap_overlay_manager *tv_mgr; ++ struct omap_overlay_manager *mgr = NULL; ++ ++ lcd_mgr = omap_dss_get_overlay_manager(OMAP_DSS_OVL_MGR_LCD); ++ tv_mgr = omap_dss_get_overlay_manager(OMAP_DSS_OVL_MGR_TV); ++ ++ if (dssdev->type != OMAP_DISPLAY_TYPE_VENC) { ++ if (!lcd_mgr->device || force) { ++ if (lcd_mgr->device) ++ lcd_mgr->unset_device(lcd_mgr); ++ lcd_mgr->set_device(lcd_mgr, dssdev); ++ mgr = lcd_mgr; ++ } ++ } ++ ++ if (dssdev->type == OMAP_DISPLAY_TYPE_VENC) { ++ if (!tv_mgr->device || force) { ++ if (tv_mgr->device) ++ tv_mgr->unset_device(tv_mgr); ++ tv_mgr->set_device(tv_mgr, dssdev); ++ mgr = tv_mgr; ++ } ++ } ++ ++ if (mgr) { ++ for (i = 0; i < 3; i++) { ++ struct omap_overlay *ovl; ++ ovl = omap_dss_get_overlay(i); ++ if (!ovl->manager || force) { ++ if (ovl->manager) ++ omap_dss_unset_manager(ovl); ++ omap_dss_set_manager(ovl, mgr); ++ } ++ } ++ } ++} ++ ++void dss_uninit_overlays(struct platform_device *pdev) ++{ ++ struct omap_overlay *ovl; ++ ++ while (!list_empty(&overlay_list)) { ++ ovl = list_first_entry(&overlay_list, ++ struct omap_overlay, list); ++ list_del(&ovl->list); ++ kobject_del(&ovl->kobj); ++ kobject_put(&ovl->kobj); ++ kfree(ovl); ++ } ++ ++ num_overlays = 0; ++} ++ +diff --git a/drivers/video/omap2/dss/rfbi.c b/drivers/video/omap2/dss/rfbi.c +new file mode 100644 +index 0000000..9dd2349 +--- /dev/null ++++ b/drivers/video/omap2/dss/rfbi.c +@@ -0,0 +1,1310 @@ ++/* ++ * linux/drivers/video/omap2/dss/rfbi.c ++ * ++ * Copyright (C) 2009 Nokia Corporation ++ * Author: Tomi Valkeinen ++ * ++ * Some code and ideas taken from drivers/video/omap/ driver ++ * by Imre Deak. ++ * ++ * 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. ++ * ++ * 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, see . ++ */ ++ ++#define DSS_SUBSYS_NAME "RFBI" ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include "dss.h" ++ ++/*#define MEASURE_PERF*/ ++ ++#define RFBI_BASE 0x48050800 ++ ++struct rfbi_reg { u16 idx; }; ++ ++#define RFBI_REG(idx) ((const struct rfbi_reg) { idx }) ++ ++#define RFBI_REVISION RFBI_REG(0x0000) ++#define RFBI_SYSCONFIG RFBI_REG(0x0010) ++#define RFBI_SYSSTATUS RFBI_REG(0x0014) ++#define RFBI_CONTROL RFBI_REG(0x0040) ++#define RFBI_PIXEL_CNT RFBI_REG(0x0044) ++#define RFBI_LINE_NUMBER RFBI_REG(0x0048) ++#define RFBI_CMD RFBI_REG(0x004c) ++#define RFBI_PARAM RFBI_REG(0x0050) ++#define RFBI_DATA RFBI_REG(0x0054) ++#define RFBI_READ RFBI_REG(0x0058) ++#define RFBI_STATUS RFBI_REG(0x005c) ++ ++#define RFBI_CONFIG(n) RFBI_REG(0x0060 + (n)*0x18) ++#define RFBI_ONOFF_TIME(n) RFBI_REG(0x0064 + (n)*0x18) ++#define RFBI_CYCLE_TIME(n) RFBI_REG(0x0068 + (n)*0x18) ++#define RFBI_DATA_CYCLE1(n) RFBI_REG(0x006c + (n)*0x18) ++#define RFBI_DATA_CYCLE2(n) RFBI_REG(0x0070 + (n)*0x18) ++#define RFBI_DATA_CYCLE3(n) RFBI_REG(0x0074 + (n)*0x18) ++ ++#define RFBI_VSYNC_WIDTH RFBI_REG(0x0090) ++#define RFBI_HSYNC_WIDTH RFBI_REG(0x0094) ++ ++#define RFBI_CMD_FIFO_LEN_BYTES (16 * sizeof(struct update_param)) ++ ++#define REG_FLD_MOD(idx, val, start, end) \ ++ rfbi_write_reg(idx, FLD_MOD(rfbi_read_reg(idx), val, start, end)) ++ ++/* To work around an RFBI transfer rate limitation */ ++#define OMAP_RFBI_RATE_LIMIT 1 ++ ++enum omap_rfbi_cycleformat { ++ OMAP_DSS_RFBI_CYCLEFORMAT_1_1 = 0, ++ OMAP_DSS_RFBI_CYCLEFORMAT_2_1 = 1, ++ OMAP_DSS_RFBI_CYCLEFORMAT_3_1 = 2, ++ OMAP_DSS_RFBI_CYCLEFORMAT_3_2 = 3, ++}; ++ ++enum omap_rfbi_datatype { ++ OMAP_DSS_RFBI_DATATYPE_12 = 0, ++ OMAP_DSS_RFBI_DATATYPE_16 = 1, ++ OMAP_DSS_RFBI_DATATYPE_18 = 2, ++ OMAP_DSS_RFBI_DATATYPE_24 = 3, ++}; ++ ++enum omap_rfbi_parallelmode { ++ OMAP_DSS_RFBI_PARALLELMODE_8 = 0, ++ OMAP_DSS_RFBI_PARALLELMODE_9 = 1, ++ OMAP_DSS_RFBI_PARALLELMODE_12 = 2, ++ OMAP_DSS_RFBI_PARALLELMODE_16 = 3, ++}; ++ ++enum update_cmd { ++ RFBI_CMD_UPDATE = 0, ++ RFBI_CMD_SYNC = 1, ++}; ++ ++static int rfbi_convert_timings(struct rfbi_timings *t); ++static void rfbi_get_clk_info(u32 *clk_period, u32 *max_clk_div); ++static void process_cmd_fifo(void); ++ ++static struct { ++ void __iomem *base; ++ ++ unsigned long l4_khz; ++ ++ enum omap_rfbi_datatype datatype; ++ enum omap_rfbi_parallelmode parallelmode; ++ ++ enum omap_rfbi_te_mode te_mode; ++ int te_enabled; ++ ++ void (*framedone_callback)(void *data); ++ void *framedone_callback_data; ++ ++ struct omap_dss_device *dssdev[2]; ++ ++ struct kfifo *cmd_fifo; ++ spinlock_t cmd_lock; ++ struct completion cmd_done; ++ atomic_t cmd_fifo_full; ++ atomic_t cmd_pending; ++#ifdef MEASURE_PERF ++ unsigned perf_bytes; ++ ktime_t perf_setup_time; ++ ktime_t perf_start_time; ++#endif ++} rfbi; ++ ++struct update_region { ++ u16 x; ++ u16 y; ++ u16 w; ++ u16 h; ++}; ++ ++struct update_param { ++ u8 rfbi_module; ++ u8 cmd; ++ ++ union { ++ struct update_region r; ++ struct completion *sync; ++ } par; ++}; ++ ++static inline void rfbi_write_reg(const struct rfbi_reg idx, u32 val) ++{ ++ __raw_writel(val, rfbi.base + idx.idx); ++} ++ ++static inline u32 rfbi_read_reg(const struct rfbi_reg idx) ++{ ++ return __raw_readl(rfbi.base + idx.idx); ++} ++ ++static void rfbi_enable_clocks(bool enable) ++{ ++ if (enable) ++ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); ++ else ++ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); ++} ++ ++void omap_rfbi_write_command(const void *buf, u32 len) ++{ ++ rfbi_enable_clocks(1); ++ switch (rfbi.parallelmode) { ++ case OMAP_DSS_RFBI_PARALLELMODE_8: ++ { ++ const u8 *b = buf; ++ for (; len; len--) ++ rfbi_write_reg(RFBI_CMD, *b++); ++ break; ++ } ++ ++ case OMAP_DSS_RFBI_PARALLELMODE_16: ++ { ++ const u16 *w = buf; ++ BUG_ON(len & 1); ++ for (; len; len -= 2) ++ rfbi_write_reg(RFBI_CMD, *w++); ++ break; ++ } ++ ++ case OMAP_DSS_RFBI_PARALLELMODE_9: ++ case OMAP_DSS_RFBI_PARALLELMODE_12: ++ default: ++ BUG(); ++ } ++ rfbi_enable_clocks(0); ++} ++EXPORT_SYMBOL(omap_rfbi_write_command); ++ ++void omap_rfbi_read_data(void *buf, u32 len) ++{ ++ rfbi_enable_clocks(1); ++ switch (rfbi.parallelmode) { ++ case OMAP_DSS_RFBI_PARALLELMODE_8: ++ { ++ u8 *b = buf; ++ for (; len; len--) { ++ rfbi_write_reg(RFBI_READ, 0); ++ *b++ = rfbi_read_reg(RFBI_READ); ++ } ++ break; ++ } ++ ++ case OMAP_DSS_RFBI_PARALLELMODE_16: ++ { ++ u16 *w = buf; ++ BUG_ON(len & ~1); ++ for (; len; len -= 2) { ++ rfbi_write_reg(RFBI_READ, 0); ++ *w++ = rfbi_read_reg(RFBI_READ); ++ } ++ break; ++ } ++ ++ case OMAP_DSS_RFBI_PARALLELMODE_9: ++ case OMAP_DSS_RFBI_PARALLELMODE_12: ++ default: ++ BUG(); ++ } ++ rfbi_enable_clocks(0); ++} ++EXPORT_SYMBOL(omap_rfbi_read_data); ++ ++void omap_rfbi_write_data(const void *buf, u32 len) ++{ ++ rfbi_enable_clocks(1); ++ switch (rfbi.parallelmode) { ++ case OMAP_DSS_RFBI_PARALLELMODE_8: ++ { ++ const u8 *b = buf; ++ for (; len; len--) ++ rfbi_write_reg(RFBI_PARAM, *b++); ++ break; ++ } ++ ++ case OMAP_DSS_RFBI_PARALLELMODE_16: ++ { ++ const u16 *w = buf; ++ BUG_ON(len & 1); ++ for (; len; len -= 2) ++ rfbi_write_reg(RFBI_PARAM, *w++); ++ break; ++ } ++ ++ case OMAP_DSS_RFBI_PARALLELMODE_9: ++ case OMAP_DSS_RFBI_PARALLELMODE_12: ++ default: ++ BUG(); ++ ++ } ++ rfbi_enable_clocks(0); ++} ++EXPORT_SYMBOL(omap_rfbi_write_data); ++ ++void omap_rfbi_write_pixels(const void __iomem *buf, int scr_width, ++ u16 x, u16 y, ++ u16 w, u16 h) ++{ ++ int start_offset = scr_width * y + x; ++ int horiz_offset = scr_width - w; ++ int i; ++ ++ rfbi_enable_clocks(1); ++ ++ if (rfbi.datatype == OMAP_DSS_RFBI_DATATYPE_16 && ++ rfbi.parallelmode == OMAP_DSS_RFBI_PARALLELMODE_8) { ++ const u16 __iomem *pd = buf; ++ pd += start_offset; ++ ++ for (; h; --h) { ++ for (i = 0; i < w; ++i) { ++ const u8 __iomem *b = (const u8 __iomem *)pd; ++ rfbi_write_reg(RFBI_PARAM, __raw_readb(b+1)); ++ rfbi_write_reg(RFBI_PARAM, __raw_readb(b+0)); ++ ++pd; ++ } ++ pd += horiz_offset; ++ } ++ } else if (rfbi.datatype == OMAP_DSS_RFBI_DATATYPE_24 && ++ rfbi.parallelmode == OMAP_DSS_RFBI_PARALLELMODE_8) { ++ const u32 __iomem *pd = buf; ++ pd += start_offset; ++ ++ for (; h; --h) { ++ for (i = 0; i < w; ++i) { ++ const u8 __iomem *b = (const u8 __iomem *)pd; ++ rfbi_write_reg(RFBI_PARAM, __raw_readb(b+2)); ++ rfbi_write_reg(RFBI_PARAM, __raw_readb(b+1)); ++ rfbi_write_reg(RFBI_PARAM, __raw_readb(b+0)); ++ ++pd; ++ } ++ pd += horiz_offset; ++ } ++ } else if (rfbi.datatype == OMAP_DSS_RFBI_DATATYPE_16 && ++ rfbi.parallelmode == OMAP_DSS_RFBI_PARALLELMODE_16) { ++ const u16 __iomem *pd = buf; ++ pd += start_offset; ++ ++ for (; h; --h) { ++ for (i = 0; i < w; ++i) { ++ rfbi_write_reg(RFBI_PARAM, __raw_readw(pd)); ++ ++pd; ++ } ++ pd += horiz_offset; ++ } ++ } else { ++ BUG(); ++ } ++ ++ rfbi_enable_clocks(0); ++} ++EXPORT_SYMBOL(omap_rfbi_write_pixels); ++ ++#ifdef MEASURE_PERF ++static void perf_mark_setup(void) ++{ ++ rfbi.perf_setup_time = ktime_get(); ++} ++ ++static void perf_mark_start(void) ++{ ++ rfbi.perf_start_time = ktime_get(); ++} ++ ++static void perf_show(const char *name) ++{ ++ ktime_t t, setup_time, trans_time; ++ u32 total_bytes; ++ u32 setup_us, trans_us, total_us; ++ ++ t = ktime_get(); ++ ++ setup_time = ktime_sub(rfbi.perf_start_time, rfbi.perf_setup_time); ++ setup_us = (u32)ktime_to_us(setup_time); ++ if (setup_us == 0) ++ setup_us = 1; ++ ++ trans_time = ktime_sub(t, rfbi.perf_start_time); ++ trans_us = (u32)ktime_to_us(trans_time); ++ if (trans_us == 0) ++ trans_us = 1; ++ ++ total_us = setup_us + trans_us; ++ ++ total_bytes = rfbi.perf_bytes; ++ ++ DSSINFO("%s update %u us + %u us = %u us (%uHz), %u bytes, " ++ "%u kbytes/sec\n", ++ name, ++ setup_us, ++ trans_us, ++ total_us, ++ 1000*1000 / total_us, ++ total_bytes, ++ total_bytes * 1000 / total_us); ++} ++#else ++#define perf_mark_setup() ++#define perf_mark_start() ++#define perf_show(x) ++#endif ++ ++void rfbi_transfer_area(u16 width, u16 height, ++ void (callback)(void *data), void *data) ++{ ++ u32 l; ++ ++ /*BUG_ON(callback == 0);*/ ++ BUG_ON(rfbi.framedone_callback != NULL); ++ ++ DSSDBG("rfbi_transfer_area %dx%d\n", width, height); ++ ++ dispc_set_lcd_size(width, height); ++ ++ dispc_enable_lcd_out(1); ++ ++ rfbi.framedone_callback = callback; ++ rfbi.framedone_callback_data = data; ++ ++ rfbi_enable_clocks(1); ++ ++ rfbi_write_reg(RFBI_PIXEL_CNT, width * height); ++ ++ l = rfbi_read_reg(RFBI_CONTROL); ++ l = FLD_MOD(l, 1, 0, 0); /* enable */ ++ if (!rfbi.te_enabled) ++ l = FLD_MOD(l, 1, 4, 4); /* ITE */ ++ ++ perf_mark_start(); ++ ++ rfbi_write_reg(RFBI_CONTROL, l); ++} ++ ++static void framedone_callback(void *data, u32 mask) ++{ ++ void (*callback)(void *data); ++ ++ DSSDBG("FRAMEDONE\n"); ++ ++ perf_show("DISPC"); ++ ++ REG_FLD_MOD(RFBI_CONTROL, 0, 0, 0); ++ ++ rfbi_enable_clocks(0); ++ ++ callback = rfbi.framedone_callback; ++ rfbi.framedone_callback = NULL; ++ ++ /*callback(rfbi.framedone_callback_data);*/ ++ ++ atomic_set(&rfbi.cmd_pending, 0); ++ ++ process_cmd_fifo(); ++} ++ ++#if 1 /* VERBOSE */ ++static void rfbi_print_timings(void) ++{ ++ u32 l; ++ u32 time; ++ ++ l = rfbi_read_reg(RFBI_CONFIG(0)); ++ time = 1000000000 / rfbi.l4_khz; ++ if (l & (1 << 4)) ++ time *= 2; ++ ++ DSSDBG("Tick time %u ps\n", time); ++ l = rfbi_read_reg(RFBI_ONOFF_TIME(0)); ++ DSSDBG("CSONTIME %d, CSOFFTIME %d, WEONTIME %d, WEOFFTIME %d, " ++ "REONTIME %d, REOFFTIME %d\n", ++ l & 0x0f, (l >> 4) & 0x3f, (l >> 10) & 0x0f, (l >> 14) & 0x3f, ++ (l >> 20) & 0x0f, (l >> 24) & 0x3f); ++ ++ l = rfbi_read_reg(RFBI_CYCLE_TIME(0)); ++ DSSDBG("WECYCLETIME %d, RECYCLETIME %d, CSPULSEWIDTH %d, " ++ "ACCESSTIME %d\n", ++ (l & 0x3f), (l >> 6) & 0x3f, (l >> 12) & 0x3f, ++ (l >> 22) & 0x3f); ++} ++#else ++static void rfbi_print_timings(void) {} ++#endif ++ ++ ++ ++ ++static u32 extif_clk_period; ++ ++static inline unsigned long round_to_extif_ticks(unsigned long ps, int div) ++{ ++ int bus_tick = extif_clk_period * div; ++ return (ps + bus_tick - 1) / bus_tick * bus_tick; ++} ++ ++static int calc_reg_timing(struct rfbi_timings *t, int div) ++{ ++ t->clk_div = div; ++ ++ t->cs_on_time = round_to_extif_ticks(t->cs_on_time, div); ++ ++ t->we_on_time = round_to_extif_ticks(t->we_on_time, div); ++ t->we_off_time = round_to_extif_ticks(t->we_off_time, div); ++ t->we_cycle_time = round_to_extif_ticks(t->we_cycle_time, div); ++ ++ t->re_on_time = round_to_extif_ticks(t->re_on_time, div); ++ t->re_off_time = round_to_extif_ticks(t->re_off_time, div); ++ t->re_cycle_time = round_to_extif_ticks(t->re_cycle_time, div); ++ ++ t->access_time = round_to_extif_ticks(t->access_time, div); ++ t->cs_off_time = round_to_extif_ticks(t->cs_off_time, div); ++ t->cs_pulse_width = round_to_extif_ticks(t->cs_pulse_width, div); ++ ++ DSSDBG("[reg]cson %d csoff %d reon %d reoff %d\n", ++ t->cs_on_time, t->cs_off_time, t->re_on_time, t->re_off_time); ++ DSSDBG("[reg]weon %d weoff %d recyc %d wecyc %d\n", ++ t->we_on_time, t->we_off_time, t->re_cycle_time, ++ t->we_cycle_time); ++ DSSDBG("[reg]rdaccess %d cspulse %d\n", ++ t->access_time, t->cs_pulse_width); ++ ++ return rfbi_convert_timings(t); ++} ++ ++static int calc_extif_timings(struct rfbi_timings *t) ++{ ++ u32 max_clk_div; ++ int div; ++ ++ rfbi_get_clk_info(&extif_clk_period, &max_clk_div); ++ for (div = 1; div <= max_clk_div; div++) { ++ if (calc_reg_timing(t, div) == 0) ++ break; ++ } ++ ++ if (div <= max_clk_div) ++ return 0; ++ ++ DSSERR("can't setup timings\n"); ++ return -1; ++} ++ ++ ++void rfbi_set_timings(int rfbi_module, struct rfbi_timings *t) ++{ ++ int r; ++ ++ if (!t->converted) { ++ r = calc_extif_timings(t); ++ if (r < 0) ++ DSSERR("Failed to calc timings\n"); ++ } ++ ++ BUG_ON(!t->converted); ++ ++ rfbi_enable_clocks(1); ++ rfbi_write_reg(RFBI_ONOFF_TIME(rfbi_module), t->tim[0]); ++ rfbi_write_reg(RFBI_CYCLE_TIME(rfbi_module), t->tim[1]); ++ ++ /* TIMEGRANULARITY */ ++ REG_FLD_MOD(RFBI_CONFIG(rfbi_module), ++ (t->tim[2] ? 1 : 0), 4, 4); ++ ++ rfbi_print_timings(); ++ rfbi_enable_clocks(0); ++} ++ ++static int ps_to_rfbi_ticks(int time, int div) ++{ ++ unsigned long tick_ps; ++ int ret; ++ ++ /* Calculate in picosecs to yield more exact results */ ++ tick_ps = 1000000000 / (rfbi.l4_khz) * div; ++ ++ ret = (time + tick_ps - 1) / tick_ps; ++ ++ return ret; ++} ++ ++#ifdef OMAP_RFBI_RATE_LIMIT ++unsigned long rfbi_get_max_tx_rate(void) ++{ ++ unsigned long l4_rate, dss1_rate; ++ int min_l4_ticks = 0; ++ int i; ++ ++ /* According to TI this can't be calculated so make the ++ * adjustments for a couple of known frequencies and warn for ++ * others. ++ */ ++ static const struct { ++ unsigned long l4_clk; /* HZ */ ++ unsigned long dss1_clk; /* HZ */ ++ unsigned long min_l4_ticks; ++ } ftab[] = { ++ { 55, 132, 7, }, /* 7.86 MPix/s */ ++ { 110, 110, 12, }, /* 9.16 MPix/s */ ++ { 110, 132, 10, }, /* 11 Mpix/s */ ++ { 120, 120, 10, }, /* 12 Mpix/s */ ++ { 133, 133, 10, }, /* 13.3 Mpix/s */ ++ }; ++ ++ l4_rate = rfbi.l4_khz / 1000; ++ dss1_rate = dss_clk_get_rate(DSS_CLK_FCK1) / 1000000; ++ ++ for (i = 0; i < ARRAY_SIZE(ftab); i++) { ++ /* Use a window instead of an exact match, to account ++ * for different DPLL multiplier / divider pairs. ++ */ ++ if (abs(ftab[i].l4_clk - l4_rate) < 3 && ++ abs(ftab[i].dss1_clk - dss1_rate) < 3) { ++ min_l4_ticks = ftab[i].min_l4_ticks; ++ break; ++ } ++ } ++ if (i == ARRAY_SIZE(ftab)) { ++ /* Can't be sure, return anyway the maximum not ++ * rate-limited. This might cause a problem only for the ++ * tearing synchronisation. ++ */ ++ DSSERR("can't determine maximum RFBI transfer rate\n"); ++ return rfbi.l4_khz * 1000; ++ } ++ return rfbi.l4_khz * 1000 / min_l4_ticks; ++} ++#else ++int rfbi_get_max_tx_rate(void) ++{ ++ return rfbi.l4_khz * 1000; ++} ++#endif ++ ++static void rfbi_get_clk_info(u32 *clk_period, u32 *max_clk_div) ++{ ++ *clk_period = 1000000000 / rfbi.l4_khz; ++ *max_clk_div = 2; ++} ++ ++static int rfbi_convert_timings(struct rfbi_timings *t) ++{ ++ u32 l; ++ int reon, reoff, weon, weoff, cson, csoff, cs_pulse; ++ int actim, recyc, wecyc; ++ int div = t->clk_div; ++ ++ if (div <= 0 || div > 2) ++ return -1; ++ ++ /* Make sure that after conversion it still holds that: ++ * weoff > weon, reoff > reon, recyc >= reoff, wecyc >= weoff, ++ * csoff > cson, csoff >= max(weoff, reoff), actim > reon ++ */ ++ weon = ps_to_rfbi_ticks(t->we_on_time, div); ++ weoff = ps_to_rfbi_ticks(t->we_off_time, div); ++ if (weoff <= weon) ++ weoff = weon + 1; ++ if (weon > 0x0f) ++ return -1; ++ if (weoff > 0x3f) ++ return -1; ++ ++ reon = ps_to_rfbi_ticks(t->re_on_time, div); ++ reoff = ps_to_rfbi_ticks(t->re_off_time, div); ++ if (reoff <= reon) ++ reoff = reon + 1; ++ if (reon > 0x0f) ++ return -1; ++ if (reoff > 0x3f) ++ return -1; ++ ++ cson = ps_to_rfbi_ticks(t->cs_on_time, div); ++ csoff = ps_to_rfbi_ticks(t->cs_off_time, div); ++ if (csoff <= cson) ++ csoff = cson + 1; ++ if (csoff < max(weoff, reoff)) ++ csoff = max(weoff, reoff); ++ if (cson > 0x0f) ++ return -1; ++ if (csoff > 0x3f) ++ return -1; ++ ++ l = cson; ++ l |= csoff << 4; ++ l |= weon << 10; ++ l |= weoff << 14; ++ l |= reon << 20; ++ l |= reoff << 24; ++ ++ t->tim[0] = l; ++ ++ actim = ps_to_rfbi_ticks(t->access_time, div); ++ if (actim <= reon) ++ actim = reon + 1; ++ if (actim > 0x3f) ++ return -1; ++ ++ wecyc = ps_to_rfbi_ticks(t->we_cycle_time, div); ++ if (wecyc < weoff) ++ wecyc = weoff; ++ if (wecyc > 0x3f) ++ return -1; ++ ++ recyc = ps_to_rfbi_ticks(t->re_cycle_time, div); ++ if (recyc < reoff) ++ recyc = reoff; ++ if (recyc > 0x3f) ++ return -1; ++ ++ cs_pulse = ps_to_rfbi_ticks(t->cs_pulse_width, div); ++ if (cs_pulse > 0x3f) ++ return -1; ++ ++ l = wecyc; ++ l |= recyc << 6; ++ l |= cs_pulse << 12; ++ l |= actim << 22; ++ ++ t->tim[1] = l; ++ ++ t->tim[2] = div - 1; ++ ++ t->converted = 1; ++ ++ return 0; ++} ++ ++/* xxx FIX module selection missing */ ++int omap_rfbi_setup_te(enum omap_rfbi_te_mode mode, ++ unsigned hs_pulse_time, unsigned vs_pulse_time, ++ int hs_pol_inv, int vs_pol_inv, int extif_div) ++{ ++ int hs, vs; ++ int min; ++ u32 l; ++ ++ hs = ps_to_rfbi_ticks(hs_pulse_time, 1); ++ vs = ps_to_rfbi_ticks(vs_pulse_time, 1); ++ if (hs < 2) ++ return -EDOM; ++ if (mode == OMAP_DSS_RFBI_TE_MODE_2) ++ min = 2; ++ else /* OMAP_DSS_RFBI_TE_MODE_1 */ ++ min = 4; ++ if (vs < min) ++ return -EDOM; ++ if (vs == hs) ++ return -EINVAL; ++ rfbi.te_mode = mode; ++ DSSDBG("setup_te: mode %d hs %d vs %d hs_inv %d vs_inv %d\n", ++ mode, hs, vs, hs_pol_inv, vs_pol_inv); ++ ++ rfbi_enable_clocks(1); ++ rfbi_write_reg(RFBI_HSYNC_WIDTH, hs); ++ rfbi_write_reg(RFBI_VSYNC_WIDTH, vs); ++ ++ l = rfbi_read_reg(RFBI_CONFIG(0)); ++ if (hs_pol_inv) ++ l &= ~(1 << 21); ++ else ++ l |= 1 << 21; ++ if (vs_pol_inv) ++ l &= ~(1 << 20); ++ else ++ l |= 1 << 20; ++ rfbi_enable_clocks(0); ++ ++ return 0; ++} ++EXPORT_SYMBOL(omap_rfbi_setup_te); ++ ++/* xxx FIX module selection missing */ ++int omap_rfbi_enable_te(bool enable, unsigned line) ++{ ++ u32 l; ++ ++ DSSDBG("te %d line %d mode %d\n", enable, line, rfbi.te_mode); ++ if (line > (1 << 11) - 1) ++ return -EINVAL; ++ ++ rfbi_enable_clocks(1); ++ l = rfbi_read_reg(RFBI_CONFIG(0)); ++ l &= ~(0x3 << 2); ++ if (enable) { ++ rfbi.te_enabled = 1; ++ l |= rfbi.te_mode << 2; ++ } else ++ rfbi.te_enabled = 0; ++ rfbi_write_reg(RFBI_CONFIG(0), l); ++ rfbi_write_reg(RFBI_LINE_NUMBER, line); ++ rfbi_enable_clocks(0); ++ ++ return 0; ++} ++EXPORT_SYMBOL(omap_rfbi_enable_te); ++ ++#if 0 ++static void rfbi_enable_config(int enable1, int enable2) ++{ ++ u32 l; ++ int cs = 0; ++ ++ if (enable1) ++ cs |= 1<<0; ++ if (enable2) ++ cs |= 1<<1; ++ ++ rfbi_enable_clocks(1); ++ ++ l = rfbi_read_reg(RFBI_CONTROL); ++ ++ l = FLD_MOD(l, cs, 3, 2); ++ l = FLD_MOD(l, 0, 1, 1); ++ ++ rfbi_write_reg(RFBI_CONTROL, l); ++ ++ ++ l = rfbi_read_reg(RFBI_CONFIG(0)); ++ l = FLD_MOD(l, 0, 3, 2); /* TRIGGERMODE: ITE */ ++ /*l |= FLD_VAL(2, 8, 7); */ /* L4FORMAT, 2pix/L4 */ ++ /*l |= FLD_VAL(0, 8, 7); */ /* L4FORMAT, 1pix/L4 */ ++ ++ l = FLD_MOD(l, 0, 16, 16); /* A0POLARITY */ ++ l = FLD_MOD(l, 1, 20, 20); /* TE_VSYNC_POLARITY */ ++ l = FLD_MOD(l, 1, 21, 21); /* HSYNCPOLARITY */ ++ ++ l = FLD_MOD(l, OMAP_DSS_RFBI_PARALLELMODE_8, 1, 0); ++ rfbi_write_reg(RFBI_CONFIG(0), l); ++ ++ rfbi_enable_clocks(0); ++} ++#endif ++ ++int rfbi_configure(int rfbi_module, int bpp, int lines) ++{ ++ u32 l; ++ int cycle1 = 0, cycle2 = 0, cycle3 = 0; ++ enum omap_rfbi_cycleformat cycleformat; ++ enum omap_rfbi_datatype datatype; ++ enum omap_rfbi_parallelmode parallelmode; ++ ++ switch (bpp) { ++ case 12: ++ datatype = OMAP_DSS_RFBI_DATATYPE_12; ++ break; ++ case 16: ++ datatype = OMAP_DSS_RFBI_DATATYPE_16; ++ break; ++ case 18: ++ datatype = OMAP_DSS_RFBI_DATATYPE_18; ++ break; ++ case 24: ++ datatype = OMAP_DSS_RFBI_DATATYPE_24; ++ break; ++ default: ++ BUG(); ++ return 1; ++ } ++ rfbi.datatype = datatype; ++ ++ switch (lines) { ++ case 8: ++ parallelmode = OMAP_DSS_RFBI_PARALLELMODE_8; ++ break; ++ case 9: ++ parallelmode = OMAP_DSS_RFBI_PARALLELMODE_9; ++ break; ++ case 12: ++ parallelmode = OMAP_DSS_RFBI_PARALLELMODE_12; ++ break; ++ case 16: ++ parallelmode = OMAP_DSS_RFBI_PARALLELMODE_16; ++ break; ++ default: ++ BUG(); ++ return 1; ++ } ++ rfbi.parallelmode = parallelmode; ++ ++ if ((bpp % lines) == 0) { ++ switch (bpp / lines) { ++ case 1: ++ cycleformat = OMAP_DSS_RFBI_CYCLEFORMAT_1_1; ++ break; ++ case 2: ++ cycleformat = OMAP_DSS_RFBI_CYCLEFORMAT_2_1; ++ break; ++ case 3: ++ cycleformat = OMAP_DSS_RFBI_CYCLEFORMAT_3_1; ++ break; ++ default: ++ BUG(); ++ return 1; ++ } ++ } else if ((2 * bpp % lines) == 0) { ++ if ((2 * bpp / lines) == 3) ++ cycleformat = OMAP_DSS_RFBI_CYCLEFORMAT_3_2; ++ else { ++ BUG(); ++ return 1; ++ } ++ } else { ++ BUG(); ++ return 1; ++ } ++ ++ switch (cycleformat) { ++ case OMAP_DSS_RFBI_CYCLEFORMAT_1_1: ++ cycle1 = lines; ++ break; ++ ++ case OMAP_DSS_RFBI_CYCLEFORMAT_2_1: ++ cycle1 = lines; ++ cycle2 = lines; ++ break; ++ ++ case OMAP_DSS_RFBI_CYCLEFORMAT_3_1: ++ cycle1 = lines; ++ cycle2 = lines; ++ cycle3 = lines; ++ break; ++ ++ case OMAP_DSS_RFBI_CYCLEFORMAT_3_2: ++ cycle1 = lines; ++ cycle2 = (lines / 2) | ((lines / 2) << 16); ++ cycle3 = (lines << 16); ++ break; ++ } ++ ++ rfbi_enable_clocks(1); ++ ++ REG_FLD_MOD(RFBI_CONTROL, 0, 3, 2); /* clear CS */ ++ ++ l = 0; ++ l |= FLD_VAL(parallelmode, 1, 0); ++ l |= FLD_VAL(0, 3, 2); /* TRIGGERMODE: ITE */ ++ l |= FLD_VAL(0, 4, 4); /* TIMEGRANULARITY */ ++ l |= FLD_VAL(datatype, 6, 5); ++ /* l |= FLD_VAL(2, 8, 7); */ /* L4FORMAT, 2pix/L4 */ ++ l |= FLD_VAL(0, 8, 7); /* L4FORMAT, 1pix/L4 */ ++ l |= FLD_VAL(cycleformat, 10, 9); ++ l |= FLD_VAL(0, 12, 11); /* UNUSEDBITS */ ++ l |= FLD_VAL(0, 16, 16); /* A0POLARITY */ ++ l |= FLD_VAL(0, 17, 17); /* REPOLARITY */ ++ l |= FLD_VAL(0, 18, 18); /* WEPOLARITY */ ++ l |= FLD_VAL(0, 19, 19); /* CSPOLARITY */ ++ l |= FLD_VAL(1, 20, 20); /* TE_VSYNC_POLARITY */ ++ l |= FLD_VAL(1, 21, 21); /* HSYNCPOLARITY */ ++ rfbi_write_reg(RFBI_CONFIG(rfbi_module), l); ++ ++ rfbi_write_reg(RFBI_DATA_CYCLE1(rfbi_module), cycle1); ++ rfbi_write_reg(RFBI_DATA_CYCLE2(rfbi_module), cycle2); ++ rfbi_write_reg(RFBI_DATA_CYCLE3(rfbi_module), cycle3); ++ ++ ++ l = rfbi_read_reg(RFBI_CONTROL); ++ l = FLD_MOD(l, rfbi_module+1, 3, 2); /* Select CSx */ ++ l = FLD_MOD(l, 0, 1, 1); /* clear bypass */ ++ rfbi_write_reg(RFBI_CONTROL, l); ++ ++ ++ DSSDBG("RFBI config: bpp %d, lines %d, cycles: 0x%x 0x%x 0x%x\n", ++ bpp, lines, cycle1, cycle2, cycle3); ++ ++ rfbi_enable_clocks(0); ++ ++ return 0; ++} ++EXPORT_SYMBOL(rfbi_configure); ++ ++static int rfbi_find_display(struct omap_dss_device *dssdev) ++{ ++ if (dssdev == rfbi.dssdev[0]) ++ return 0; ++ ++ if (dssdev == rfbi.dssdev[1]) ++ return 1; ++ ++ BUG(); ++ return -1; ++} ++ ++ ++static void signal_fifo_waiters(void) ++{ ++ if (atomic_read(&rfbi.cmd_fifo_full) > 0) { ++ /* DSSDBG("SIGNALING: Fifo not full for waiter!\n"); */ ++ complete(&rfbi.cmd_done); ++ atomic_dec(&rfbi.cmd_fifo_full); ++ } ++} ++ ++/* returns 1 for async op, and 0 for sync op */ ++static int do_update(struct omap_dss_device *dssdev, struct update_region *upd) ++{ ++ u16 x = upd->x; ++ u16 y = upd->y; ++ u16 w = upd->w; ++ u16 h = upd->h; ++ ++ perf_mark_setup(); ++ ++ if (dssdev->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) { ++ /*dssdev->driver->enable_te(dssdev, 1); */ ++ dss_setup_partial_planes(dssdev, &x, &y, &w, &h); ++ } ++ ++#ifdef MEASURE_PERF ++ rfbi.perf_bytes = w * h * 2; /* XXX always 16bit */ ++#endif ++ ++ dssdev->driver->setup_update(dssdev, x, y, w, h); ++ ++ if (dssdev->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) { ++ rfbi_transfer_area(w, h, NULL, NULL); ++ return 1; ++ } else { ++ struct omap_overlay *ovl; ++ void __iomem *addr; ++ int scr_width; ++ ++ ovl = dssdev->manager->overlays[0]; ++ scr_width = ovl->info.screen_width; ++ addr = ovl->info.vaddr; ++ ++ omap_rfbi_write_pixels(addr, scr_width, x, y, w, h); ++ ++ perf_show("L4"); ++ ++ return 0; ++ } ++} ++ ++static void process_cmd_fifo(void) ++{ ++ int len; ++ struct update_param p; ++ struct omap_dss_device *dssdev; ++ unsigned long flags; ++ ++ if (atomic_inc_return(&rfbi.cmd_pending) != 1) ++ return; ++ ++ while (true) { ++ spin_lock_irqsave(rfbi.cmd_fifo->lock, flags); ++ ++ len = __kfifo_get(rfbi.cmd_fifo, (unsigned char *)&p, ++ sizeof(struct update_param)); ++ if (len == 0) { ++ DSSDBG("nothing more in fifo\n"); ++ atomic_set(&rfbi.cmd_pending, 0); ++ spin_unlock_irqrestore(rfbi.cmd_fifo->lock, flags); ++ break; ++ } ++ ++ /* DSSDBG("fifo full %d\n", rfbi.cmd_fifo_full.counter);*/ ++ ++ spin_unlock_irqrestore(rfbi.cmd_fifo->lock, flags); ++ ++ BUG_ON(len != sizeof(struct update_param)); ++ BUG_ON(p.rfbi_module > 1); ++ ++ dssdev = rfbi.dssdev[p.rfbi_module]; ++ ++ if (p.cmd == RFBI_CMD_UPDATE) { ++ if (do_update(dssdev, &p.par.r)) ++ break; /* async op */ ++ } else if (p.cmd == RFBI_CMD_SYNC) { ++ DSSDBG("Signaling SYNC done!\n"); ++ complete(p.par.sync); ++ } else ++ BUG(); ++ } ++ ++ signal_fifo_waiters(); ++} ++ ++static void rfbi_push_cmd(struct update_param *p) ++{ ++ int ret; ++ ++ while (1) { ++ unsigned long flags; ++ int available; ++ ++ spin_lock_irqsave(rfbi.cmd_fifo->lock, flags); ++ available = RFBI_CMD_FIFO_LEN_BYTES - ++ __kfifo_len(rfbi.cmd_fifo); ++ ++/* DSSDBG("%d bytes left in fifo\n", available); */ ++ if (available < sizeof(struct update_param)) { ++ DSSDBG("Going to wait because FIFO FULL..\n"); ++ spin_unlock_irqrestore(rfbi.cmd_fifo->lock, flags); ++ atomic_inc(&rfbi.cmd_fifo_full); ++ wait_for_completion(&rfbi.cmd_done); ++ /*DSSDBG("Woke up because fifo not full anymore\n");*/ ++ continue; ++ } ++ ++ ret = __kfifo_put(rfbi.cmd_fifo, (unsigned char *)p, ++ sizeof(struct update_param)); ++/* DSSDBG("pushed %d bytes\n", ret);*/ ++ ++ spin_unlock_irqrestore(rfbi.cmd_fifo->lock, flags); ++ ++ BUG_ON(ret != sizeof(struct update_param)); ++ ++ break; ++ } ++} ++ ++static void rfbi_push_update(int rfbi_module, int x, int y, int w, int h) ++{ ++ struct update_param p; ++ ++ p.rfbi_module = rfbi_module; ++ p.cmd = RFBI_CMD_UPDATE; ++ ++ p.par.r.x = x; ++ p.par.r.y = y; ++ p.par.r.w = w; ++ p.par.r.h = h; ++ ++ DSSDBG("RFBI pushed %d,%d %dx%d\n", x, y, w, h); ++ ++ rfbi_push_cmd(&p); ++ ++ process_cmd_fifo(); ++} ++ ++static void rfbi_push_sync(int rfbi_module, struct completion *sync_comp) ++{ ++ struct update_param p; ++ ++ p.rfbi_module = rfbi_module; ++ p.cmd = RFBI_CMD_SYNC; ++ p.par.sync = sync_comp; ++ ++ rfbi_push_cmd(&p); ++ ++ DSSDBG("RFBI sync pushed to cmd fifo\n"); ++ ++ process_cmd_fifo(); ++} ++ ++void rfbi_dump_regs(struct seq_file *s) ++{ ++#define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, rfbi_read_reg(r)) ++ ++ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); ++ ++ DUMPREG(RFBI_REVISION); ++ DUMPREG(RFBI_SYSCONFIG); ++ DUMPREG(RFBI_SYSSTATUS); ++ DUMPREG(RFBI_CONTROL); ++ DUMPREG(RFBI_PIXEL_CNT); ++ DUMPREG(RFBI_LINE_NUMBER); ++ DUMPREG(RFBI_CMD); ++ DUMPREG(RFBI_PARAM); ++ DUMPREG(RFBI_DATA); ++ DUMPREG(RFBI_READ); ++ DUMPREG(RFBI_STATUS); ++ ++ DUMPREG(RFBI_CONFIG(0)); ++ DUMPREG(RFBI_ONOFF_TIME(0)); ++ DUMPREG(RFBI_CYCLE_TIME(0)); ++ DUMPREG(RFBI_DATA_CYCLE1(0)); ++ DUMPREG(RFBI_DATA_CYCLE2(0)); ++ DUMPREG(RFBI_DATA_CYCLE3(0)); ++ ++ DUMPREG(RFBI_CONFIG(1)); ++ DUMPREG(RFBI_ONOFF_TIME(1)); ++ DUMPREG(RFBI_CYCLE_TIME(1)); ++ DUMPREG(RFBI_DATA_CYCLE1(1)); ++ DUMPREG(RFBI_DATA_CYCLE2(1)); ++ DUMPREG(RFBI_DATA_CYCLE3(1)); ++ ++ DUMPREG(RFBI_VSYNC_WIDTH); ++ DUMPREG(RFBI_HSYNC_WIDTH); ++ ++ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); ++#undef DUMPREG ++} ++ ++int rfbi_init(void) ++{ ++ u32 rev; ++ u32 l; ++ ++ spin_lock_init(&rfbi.cmd_lock); ++ rfbi.cmd_fifo = kfifo_alloc(RFBI_CMD_FIFO_LEN_BYTES, GFP_KERNEL, ++ &rfbi.cmd_lock); ++ if (IS_ERR(rfbi.cmd_fifo)) ++ return -ENOMEM; ++ ++ init_completion(&rfbi.cmd_done); ++ atomic_set(&rfbi.cmd_fifo_full, 0); ++ atomic_set(&rfbi.cmd_pending, 0); ++ ++ rfbi.base = ioremap(RFBI_BASE, SZ_256); ++ if (!rfbi.base) { ++ DSSERR("can't ioremap RFBI\n"); ++ return -ENOMEM; ++ } ++ ++ rfbi_enable_clocks(1); ++ ++ msleep(10); ++ ++ rfbi.l4_khz = dss_clk_get_rate(DSS_CLK_ICK) / 1000; ++ ++ /* Enable autoidle and smart-idle */ ++ l = rfbi_read_reg(RFBI_SYSCONFIG); ++ l |= (1 << 0) | (2 << 3); ++ rfbi_write_reg(RFBI_SYSCONFIG, l); ++ ++ rev = rfbi_read_reg(RFBI_REVISION); ++ printk(KERN_INFO "OMAP RFBI rev %d.%d\n", ++ FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0)); ++ ++ rfbi_enable_clocks(0); ++ ++ return 0; ++} ++ ++void rfbi_exit(void) ++{ ++ DSSDBG("rfbi_exit\n"); ++ ++ kfifo_free(rfbi.cmd_fifo); ++ ++ iounmap(rfbi.base); ++} ++ ++/* struct omap_display support */ ++static int rfbi_display_update(struct omap_dss_device *dssdev, ++ u16 x, u16 y, u16 w, u16 h) ++{ ++ int rfbi_module; ++ ++ if (w == 0 || h == 0) ++ return 0; ++ ++ rfbi_module = rfbi_find_display(dssdev); ++ ++ rfbi_push_update(rfbi_module, x, y, w, h); ++ ++ return 0; ++} ++ ++static int rfbi_display_sync(struct omap_dss_device *dssdev) ++{ ++ struct completion sync_comp; ++ int rfbi_module; ++ ++ rfbi_module = rfbi_find_display(dssdev); ++ ++ init_completion(&sync_comp); ++ rfbi_push_sync(rfbi_module, &sync_comp); ++ DSSDBG("Waiting for SYNC to happen...\n"); ++ wait_for_completion(&sync_comp); ++ DSSDBG("Released from SYNC\n"); ++ return 0; ++} ++ ++static int rfbi_display_enable_te(struct omap_dss_device *dssdev, bool enable) ++{ ++ dssdev->driver->enable_te(dssdev, enable); ++ return 0; ++} ++ ++static int rfbi_display_enable(struct omap_dss_device *dssdev) ++{ ++ int r; ++ ++ r = omap_dss_start_device(dssdev); ++ if (r) { ++ DSSERR("failed to start device\n"); ++ goto err0; ++ } ++ ++ r = omap_dispc_register_isr(framedone_callback, NULL, ++ DISPC_IRQ_FRAMEDONE); ++ if (r) { ++ DSSERR("can't get FRAMEDONE irq\n"); ++ goto err1; ++ } ++ ++ dispc_set_lcd_display_type(OMAP_DSS_LCD_DISPLAY_TFT); ++ ++ dispc_set_parallel_interface_mode(OMAP_DSS_PARALLELMODE_RFBI); ++ ++ dispc_set_tft_data_lines(dssdev->ctrl.pixel_size); ++ ++ rfbi_configure(dssdev->phy.rfbi.channel, ++ dssdev->ctrl.pixel_size, ++ dssdev->phy.rfbi.data_lines); ++ ++ rfbi_set_timings(dssdev->phy.rfbi.channel, ++ &dssdev->ctrl.rfbi_timings); ++ ++ ++ if (dssdev->driver->enable) { ++ r = dssdev->driver->enable(dssdev); ++ if (r) ++ goto err2; ++ } ++ ++ return 0; ++err2: ++ omap_dispc_unregister_isr(framedone_callback, NULL, ++ DISPC_IRQ_FRAMEDONE); ++err1: ++ omap_dss_stop_device(dssdev); ++err0: ++ return r; ++} ++ ++static void rfbi_display_disable(struct omap_dss_device *dssdev) ++{ ++ dssdev->driver->disable(dssdev); ++ omap_dispc_unregister_isr(framedone_callback, NULL, ++ DISPC_IRQ_FRAMEDONE); ++ omap_dss_stop_device(dssdev); ++} ++ ++int rfbi_init_display(struct omap_dss_device *dssdev) ++{ ++ dssdev->enable = rfbi_display_enable; ++ dssdev->disable = rfbi_display_disable; ++ dssdev->update = rfbi_display_update; ++ dssdev->sync = rfbi_display_sync; ++ dssdev->enable_te = rfbi_display_enable_te; ++ ++ rfbi.dssdev[dssdev->phy.rfbi.channel] = dssdev; ++ ++ dssdev->caps = OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE; ++ ++ return 0; ++} +diff --git a/drivers/video/omap2/dss/sdi.c b/drivers/video/omap2/dss/sdi.c +new file mode 100644 +index 0000000..a9c727e +--- /dev/null ++++ b/drivers/video/omap2/dss/sdi.c +@@ -0,0 +1,261 @@ ++/* ++ * linux/drivers/video/omap2/dss/sdi.c ++ * ++ * Copyright (C) 2009 Nokia Corporation ++ * Author: Tomi Valkeinen ++ * ++ * 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. ++ * ++ * 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, see . ++ */ ++ ++#define DSS_SUBSYS_NAME "SDI" ++ ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include "dss.h" ++ ++static struct { ++ bool skip_init; ++ bool update_enabled; ++} sdi; ++ ++static void sdi_basic_init(void) ++{ ++ dispc_set_parallel_interface_mode(OMAP_DSS_PARALLELMODE_BYPASS); ++ ++ dispc_set_lcd_display_type(OMAP_DSS_LCD_DISPLAY_TFT); ++ dispc_set_tft_data_lines(24); ++ dispc_lcd_enable_signal_polarity(1); ++} ++ ++static int sdi_display_enable(struct omap_dss_device *dssdev) ++{ ++ struct omap_video_timings *t = &dssdev->panel.timings; ++ struct dispc_clock_info cinfo; ++ u16 lck_div, pck_div; ++ unsigned long fck; ++ unsigned long pck; ++ int r; ++ ++ r = omap_dss_start_device(dssdev); ++ if (r) { ++ DSSERR("failed to start device\n"); ++ goto err0; ++ } ++ ++ if (dssdev->state != OMAP_DSS_DISPLAY_DISABLED) { ++ DSSERR("dssdev already enabled\n"); ++ r = -EINVAL; ++ goto err1; ++ } ++ ++ /* In case of skip_init sdi_init has already enabled the clocks */ ++ if (!sdi.skip_init) ++ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); ++ ++ sdi_basic_init(); ++ ++ /* 15.5.9.1.2 */ ++ dssdev->panel.config |= OMAP_DSS_LCD_RF | OMAP_DSS_LCD_ONOFF; ++ ++ dispc_set_pol_freq(dssdev->panel.config, dssdev->panel.acbi, ++ dssdev->panel.acb); ++ ++ if (!sdi.skip_init) ++ r = dispc_calc_clock_div(1, t->pixel_clock * 1000, ++ &cinfo); ++ else ++ r = dispc_get_clock_div(&cinfo); ++ ++ if (r) ++ goto err2; ++ ++ fck = cinfo.fck; ++ lck_div = cinfo.lck_div; ++ pck_div = cinfo.pck_div; ++ ++ pck = fck / lck_div / pck_div / 1000; ++ ++ if (pck != t->pixel_clock) { ++ DSSWARN("Could not find exact pixel clock. Requested %d kHz, " ++ "got %lu kHz\n", ++ t->pixel_clock, pck); ++ ++ t->pixel_clock = pck; ++ } ++ ++ ++ dispc_set_lcd_timings(t); ++ ++ r = dispc_set_clock_div(&cinfo); ++ if (r) ++ goto err2; ++ ++ if (!sdi.skip_init) { ++ dss_sdi_init(dssdev->phy.sdi.datapairs); ++ dss_sdi_enable(); ++ mdelay(2); ++ } ++ ++ dispc_enable_lcd_out(1); ++ ++ if (dssdev->driver->enable) { ++ r = dssdev->driver->enable(dssdev); ++ if (r) ++ goto err3; ++ } ++ ++ dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; ++ ++ sdi.skip_init = 0; ++ ++ return 0; ++err3: ++ dispc_enable_lcd_out(0); ++err2: ++ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); ++err1: ++ omap_dss_stop_device(dssdev); ++err0: ++ return r; ++} ++ ++static int sdi_display_resume(struct omap_dss_device *dssdev); ++ ++static void sdi_display_disable(struct omap_dss_device *dssdev) ++{ ++ if (dssdev->state == OMAP_DSS_DISPLAY_DISABLED) ++ return; ++ ++ if (dssdev->state == OMAP_DSS_DISPLAY_SUSPENDED) ++ sdi_display_resume(dssdev); ++ ++ if (dssdev->driver->disable) ++ dssdev->driver->disable(dssdev); ++ ++ dispc_enable_lcd_out(0); ++ ++ dss_sdi_disable(); ++ ++ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); ++ ++ dssdev->state = OMAP_DSS_DISPLAY_DISABLED; ++ ++ omap_dss_stop_device(dssdev); ++} ++ ++static int sdi_display_suspend(struct omap_dss_device *dssdev) ++{ ++ if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) ++ return -EINVAL; ++ ++ if (dssdev->driver->suspend) ++ dssdev->driver->suspend(dssdev); ++ ++ dispc_enable_lcd_out(0); ++ ++ dss_sdi_disable(); ++ ++ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); ++ ++ dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED; ++ ++ return 0; ++} ++ ++static int sdi_display_resume(struct omap_dss_device *dssdev) ++{ ++ if (dssdev->state != OMAP_DSS_DISPLAY_SUSPENDED) ++ return -EINVAL; ++ ++ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); ++ ++ dss_sdi_enable(); ++ mdelay(2); ++ ++ dispc_enable_lcd_out(1); ++ ++ if (dssdev->driver->resume) ++ dssdev->driver->resume(dssdev); ++ ++ dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; ++ ++ return 0; ++} ++ ++static int sdi_display_set_update_mode(struct omap_dss_device *dssdev, ++ enum omap_dss_update_mode mode) ++{ ++ if (mode == OMAP_DSS_UPDATE_MANUAL) ++ return -EINVAL; ++ ++ if (mode == OMAP_DSS_UPDATE_DISABLED) { ++ dispc_enable_lcd_out(0); ++ sdi.update_enabled = 0; ++ } else { ++ dispc_enable_lcd_out(1); ++ sdi.update_enabled = 1; ++ } ++ ++ return 0; ++} ++ ++static enum omap_dss_update_mode sdi_display_get_update_mode( ++ struct omap_dss_device *dssdev) ++{ ++ return sdi.update_enabled ? OMAP_DSS_UPDATE_AUTO : ++ OMAP_DSS_UPDATE_DISABLED; ++} ++ ++static void sdi_get_timings(struct omap_dss_device *dssdev, ++ struct omap_video_timings *timings) ++{ ++ *timings = dssdev->panel.timings; ++} ++ ++int sdi_init_display(struct omap_dss_device *dssdev) ++{ ++ DSSDBG("SDI init\n"); ++ ++ dssdev->enable = sdi_display_enable; ++ dssdev->disable = sdi_display_disable; ++ dssdev->suspend = sdi_display_suspend; ++ dssdev->resume = sdi_display_resume; ++ dssdev->set_update_mode = sdi_display_set_update_mode; ++ dssdev->get_update_mode = sdi_display_get_update_mode; ++ dssdev->get_timings = sdi_get_timings; ++ ++ return 0; ++} ++ ++int sdi_init(bool skip_init) ++{ ++ /* we store this for first display enable, then clear it */ ++ sdi.skip_init = skip_init; ++ ++ /* ++ * Enable clocks already here, otherwise there would be a toggle ++ * of them until sdi_display_enable is called. ++ */ ++ if (skip_init) ++ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); ++ return 0; ++} ++ ++void sdi_exit(void) ++{ ++} +diff --git a/drivers/video/omap2/dss/venc.c b/drivers/video/omap2/dss/venc.c +new file mode 100644 +index 0000000..cf7827e +--- /dev/null ++++ b/drivers/video/omap2/dss/venc.c +@@ -0,0 +1,797 @@ ++/* ++ * linux/drivers/video/omap2/dss/venc.c ++ * ++ * Copyright (C) 2009 Nokia Corporation ++ * Author: Tomi Valkeinen ++ * ++ * VENC settings from TI's DSS driver ++ * ++ * 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. ++ * ++ * 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, see . ++ */ ++ ++#define DSS_SUBSYS_NAME "VENC" ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++ ++#include "dss.h" ++ ++#define VENC_BASE 0x48050C00 ++ ++/* Venc registers */ ++#define VENC_REV_ID 0x00 ++#define VENC_STATUS 0x04 ++#define VENC_F_CONTROL 0x08 ++#define VENC_VIDOUT_CTRL 0x10 ++#define VENC_SYNC_CTRL 0x14 ++#define VENC_LLEN 0x1C ++#define VENC_FLENS 0x20 ++#define VENC_HFLTR_CTRL 0x24 ++#define VENC_CC_CARR_WSS_CARR 0x28 ++#define VENC_C_PHASE 0x2C ++#define VENC_GAIN_U 0x30 ++#define VENC_GAIN_V 0x34 ++#define VENC_GAIN_Y 0x38 ++#define VENC_BLACK_LEVEL 0x3C ++#define VENC_BLANK_LEVEL 0x40 ++#define VENC_X_COLOR 0x44 ++#define VENC_M_CONTROL 0x48 ++#define VENC_BSTAMP_WSS_DATA 0x4C ++#define VENC_S_CARR 0x50 ++#define VENC_LINE21 0x54 ++#define VENC_LN_SEL 0x58 ++#define VENC_L21__WC_CTL 0x5C ++#define VENC_HTRIGGER_VTRIGGER 0x60 ++#define VENC_SAVID__EAVID 0x64 ++#define VENC_FLEN__FAL 0x68 ++#define VENC_LAL__PHASE_RESET 0x6C ++#define VENC_HS_INT_START_STOP_X 0x70 ++#define VENC_HS_EXT_START_STOP_X 0x74 ++#define VENC_VS_INT_START_X 0x78 ++#define VENC_VS_INT_STOP_X__VS_INT_START_Y 0x7C ++#define VENC_VS_INT_STOP_Y__VS_EXT_START_X 0x80 ++#define VENC_VS_EXT_STOP_X__VS_EXT_START_Y 0x84 ++#define VENC_VS_EXT_STOP_Y 0x88 ++#define VENC_AVID_START_STOP_X 0x90 ++#define VENC_AVID_START_STOP_Y 0x94 ++#define VENC_FID_INT_START_X__FID_INT_START_Y 0xA0 ++#define VENC_FID_INT_OFFSET_Y__FID_EXT_START_X 0xA4 ++#define VENC_FID_EXT_START_Y__FID_EXT_OFFSET_Y 0xA8 ++#define VENC_TVDETGP_INT_START_STOP_X 0xB0 ++#define VENC_TVDETGP_INT_START_STOP_Y 0xB4 ++#define VENC_GEN_CTRL 0xB8 ++#define VENC_OUTPUT_CONTROL 0xC4 ++#define VENC_OUTPUT_TEST 0xC8 ++#define VENC_DAC_B__DAC_C 0xC8 ++ ++struct venc_config { ++ u32 f_control; ++ u32 vidout_ctrl; ++ u32 sync_ctrl; ++ u32 llen; ++ u32 flens; ++ u32 hfltr_ctrl; ++ u32 cc_carr_wss_carr; ++ u32 c_phase; ++ u32 gain_u; ++ u32 gain_v; ++ u32 gain_y; ++ u32 black_level; ++ u32 blank_level; ++ u32 x_color; ++ u32 m_control; ++ u32 bstamp_wss_data; ++ u32 s_carr; ++ u32 line21; ++ u32 ln_sel; ++ u32 l21__wc_ctl; ++ u32 htrigger_vtrigger; ++ u32 savid__eavid; ++ u32 flen__fal; ++ u32 lal__phase_reset; ++ u32 hs_int_start_stop_x; ++ u32 hs_ext_start_stop_x; ++ u32 vs_int_start_x; ++ u32 vs_int_stop_x__vs_int_start_y; ++ u32 vs_int_stop_y__vs_ext_start_x; ++ u32 vs_ext_stop_x__vs_ext_start_y; ++ u32 vs_ext_stop_y; ++ u32 avid_start_stop_x; ++ u32 avid_start_stop_y; ++ u32 fid_int_start_x__fid_int_start_y; ++ u32 fid_int_offset_y__fid_ext_start_x; ++ u32 fid_ext_start_y__fid_ext_offset_y; ++ u32 tvdetgp_int_start_stop_x; ++ u32 tvdetgp_int_start_stop_y; ++ u32 gen_ctrl; ++}; ++ ++/* from TRM */ ++static const struct venc_config venc_config_pal_trm = { ++ .f_control = 0, ++ .vidout_ctrl = 1, ++ .sync_ctrl = 0x40, ++ .llen = 0x35F, /* 863 */ ++ .flens = 0x270, /* 624 */ ++ .hfltr_ctrl = 0, ++ .cc_carr_wss_carr = 0x2F7225ED, ++ .c_phase = 0, ++ .gain_u = 0x111, ++ .gain_v = 0x181, ++ .gain_y = 0x140, ++ .black_level = 0x3B, ++ .blank_level = 0x3B, ++ .x_color = 0x7, ++ .m_control = 0x2, ++ .bstamp_wss_data = 0x3F, ++ .s_carr = 0x2A098ACB, ++ .line21 = 0, ++ .ln_sel = 0x01290015, ++ .l21__wc_ctl = 0x0000F603, ++ .htrigger_vtrigger = 0, ++ ++ .savid__eavid = 0x06A70108, ++ .flen__fal = 0x00180270, ++ .lal__phase_reset = 0x00040135, ++ .hs_int_start_stop_x = 0x00880358, ++ .hs_ext_start_stop_x = 0x000F035F, ++ .vs_int_start_x = 0x01A70000, ++ .vs_int_stop_x__vs_int_start_y = 0x000001A7, ++ .vs_int_stop_y__vs_ext_start_x = 0x01AF0000, ++ .vs_ext_stop_x__vs_ext_start_y = 0x000101AF, ++ .vs_ext_stop_y = 0x00000025, ++ .avid_start_stop_x = 0x03530083, ++ .avid_start_stop_y = 0x026C002E, ++ .fid_int_start_x__fid_int_start_y = 0x0001008A, ++ .fid_int_offset_y__fid_ext_start_x = 0x002E0138, ++ .fid_ext_start_y__fid_ext_offset_y = 0x01380001, ++ ++ .tvdetgp_int_start_stop_x = 0x00140001, ++ .tvdetgp_int_start_stop_y = 0x00010001, ++ .gen_ctrl = 0x00FF0000, ++}; ++ ++/* from TRM */ ++static const struct venc_config venc_config_ntsc_trm = { ++ .f_control = 0, ++ .vidout_ctrl = 1, ++ .sync_ctrl = 0x8040, ++ .llen = 0x359, ++ .flens = 0x20C, ++ .hfltr_ctrl = 0, ++ .cc_carr_wss_carr = 0x043F2631, ++ .c_phase = 0, ++ .gain_u = 0x102, ++ .gain_v = 0x16C, ++ .gain_y = 0x12F, ++ .black_level = 0x43, ++ .blank_level = 0x38, ++ .x_color = 0x7, ++ .m_control = 0x1, ++ .bstamp_wss_data = 0x38, ++ .s_carr = 0x21F07C1F, ++ .line21 = 0, ++ .ln_sel = 0x01310011, ++ .l21__wc_ctl = 0x0000F003, ++ .htrigger_vtrigger = 0, ++ ++ .savid__eavid = 0x069300F4, ++ .flen__fal = 0x0016020C, ++ .lal__phase_reset = 0x00060107, ++ .hs_int_start_stop_x = 0x008E0350, ++ .hs_ext_start_stop_x = 0x000F0359, ++ .vs_int_start_x = 0x01A00000, ++ .vs_int_stop_x__vs_int_start_y = 0x020701A0, ++ .vs_int_stop_y__vs_ext_start_x = 0x01AC0024, ++ .vs_ext_stop_x__vs_ext_start_y = 0x020D01AC, ++ .vs_ext_stop_y = 0x00000006, ++ .avid_start_stop_x = 0x03480078, ++ .avid_start_stop_y = 0x02060024, ++ .fid_int_start_x__fid_int_start_y = 0x0001008A, ++ .fid_int_offset_y__fid_ext_start_x = 0x01AC0106, ++ .fid_ext_start_y__fid_ext_offset_y = 0x01060006, ++ ++ .tvdetgp_int_start_stop_x = 0x00140001, ++ .tvdetgp_int_start_stop_y = 0x00010001, ++ .gen_ctrl = 0x00F90000, ++}; ++ ++static const struct venc_config venc_config_pal_bdghi = { ++ .f_control = 0, ++ .vidout_ctrl = 0, ++ .sync_ctrl = 0, ++ .hfltr_ctrl = 0, ++ .x_color = 0, ++ .line21 = 0, ++ .ln_sel = 21, ++ .htrigger_vtrigger = 0, ++ .tvdetgp_int_start_stop_x = 0x00140001, ++ .tvdetgp_int_start_stop_y = 0x00010001, ++ .gen_ctrl = 0x00FB0000, ++ ++ .llen = 864-1, ++ .flens = 625-1, ++ .cc_carr_wss_carr = 0x2F7625ED, ++ .c_phase = 0xDF, ++ .gain_u = 0x111, ++ .gain_v = 0x181, ++ .gain_y = 0x140, ++ .black_level = 0x3e, ++ .blank_level = 0x3e, ++ .m_control = 0<<2 | 1<<1, ++ .bstamp_wss_data = 0x42, ++ .s_carr = 0x2a098acb, ++ .l21__wc_ctl = 0<<13 | 0x16<<8 | 0<<0, ++ .savid__eavid = 0x06A70108, ++ .flen__fal = 23<<16 | 624<<0, ++ .lal__phase_reset = 2<<17 | 310<<0, ++ .hs_int_start_stop_x = 0x00920358, ++ .hs_ext_start_stop_x = 0x000F035F, ++ .vs_int_start_x = 0x1a7<<16, ++ .vs_int_stop_x__vs_int_start_y = 0x000601A7, ++ .vs_int_stop_y__vs_ext_start_x = 0x01AF0036, ++ .vs_ext_stop_x__vs_ext_start_y = 0x27101af, ++ .vs_ext_stop_y = 0x05, ++ .avid_start_stop_x = 0x03530082, ++ .avid_start_stop_y = 0x0270002E, ++ .fid_int_start_x__fid_int_start_y = 0x0005008A, ++ .fid_int_offset_y__fid_ext_start_x = 0x002E0138, ++ .fid_ext_start_y__fid_ext_offset_y = 0x01380005, ++}; ++ ++const struct omap_video_timings omap_dss_pal_timings = { ++ .x_res = 720, ++ .y_res = 574, ++ .pixel_clock = 13500, ++ .hsw = 64, ++ .hfp = 12, ++ .hbp = 68, ++ .vsw = 5, ++ .vfp = 5, ++ .vbp = 41, ++}; ++EXPORT_SYMBOL(omap_dss_pal_timings); ++ ++const struct omap_video_timings omap_dss_ntsc_timings = { ++ .x_res = 720, ++ .y_res = 482, ++ .pixel_clock = 13500, ++ .hsw = 64, ++ .hfp = 16, ++ .hbp = 58, ++ .vsw = 6, ++ .vfp = 6, ++ .vbp = 31, ++}; ++EXPORT_SYMBOL(omap_dss_ntsc_timings); ++ ++static struct { ++ void __iomem *base; ++ struct mutex venc_lock; ++ u32 wss_data; ++ struct regulator *vdda_dac_reg; ++} venc; ++ ++static inline void venc_write_reg(int idx, u32 val) ++{ ++ __raw_writel(val, venc.base + idx); ++} ++ ++static inline u32 venc_read_reg(int idx) ++{ ++ u32 l = __raw_readl(venc.base + idx); ++ return l; ++} ++ ++static void venc_write_config(const struct venc_config *config) ++{ ++ DSSDBG("write venc conf\n"); ++ ++ venc_write_reg(VENC_LLEN, config->llen); ++ venc_write_reg(VENC_FLENS, config->flens); ++ venc_write_reg(VENC_CC_CARR_WSS_CARR, config->cc_carr_wss_carr); ++ venc_write_reg(VENC_C_PHASE, config->c_phase); ++ venc_write_reg(VENC_GAIN_U, config->gain_u); ++ venc_write_reg(VENC_GAIN_V, config->gain_v); ++ venc_write_reg(VENC_GAIN_Y, config->gain_y); ++ venc_write_reg(VENC_BLACK_LEVEL, config->black_level); ++ venc_write_reg(VENC_BLANK_LEVEL, config->blank_level); ++ venc_write_reg(VENC_M_CONTROL, config->m_control); ++ venc_write_reg(VENC_BSTAMP_WSS_DATA, config->bstamp_wss_data | ++ venc.wss_data); ++ venc_write_reg(VENC_S_CARR, config->s_carr); ++ venc_write_reg(VENC_L21__WC_CTL, config->l21__wc_ctl); ++ venc_write_reg(VENC_SAVID__EAVID, config->savid__eavid); ++ venc_write_reg(VENC_FLEN__FAL, config->flen__fal); ++ venc_write_reg(VENC_LAL__PHASE_RESET, config->lal__phase_reset); ++ venc_write_reg(VENC_HS_INT_START_STOP_X, config->hs_int_start_stop_x); ++ venc_write_reg(VENC_HS_EXT_START_STOP_X, config->hs_ext_start_stop_x); ++ venc_write_reg(VENC_VS_INT_START_X, config->vs_int_start_x); ++ venc_write_reg(VENC_VS_INT_STOP_X__VS_INT_START_Y, ++ config->vs_int_stop_x__vs_int_start_y); ++ venc_write_reg(VENC_VS_INT_STOP_Y__VS_EXT_START_X, ++ config->vs_int_stop_y__vs_ext_start_x); ++ venc_write_reg(VENC_VS_EXT_STOP_X__VS_EXT_START_Y, ++ config->vs_ext_stop_x__vs_ext_start_y); ++ venc_write_reg(VENC_VS_EXT_STOP_Y, config->vs_ext_stop_y); ++ venc_write_reg(VENC_AVID_START_STOP_X, config->avid_start_stop_x); ++ venc_write_reg(VENC_AVID_START_STOP_Y, config->avid_start_stop_y); ++ venc_write_reg(VENC_FID_INT_START_X__FID_INT_START_Y, ++ config->fid_int_start_x__fid_int_start_y); ++ venc_write_reg(VENC_FID_INT_OFFSET_Y__FID_EXT_START_X, ++ config->fid_int_offset_y__fid_ext_start_x); ++ venc_write_reg(VENC_FID_EXT_START_Y__FID_EXT_OFFSET_Y, ++ config->fid_ext_start_y__fid_ext_offset_y); ++ ++ venc_write_reg(VENC_DAC_B__DAC_C, venc_read_reg(VENC_DAC_B__DAC_C)); ++ venc_write_reg(VENC_VIDOUT_CTRL, config->vidout_ctrl); ++ venc_write_reg(VENC_HFLTR_CTRL, config->hfltr_ctrl); ++ venc_write_reg(VENC_X_COLOR, config->x_color); ++ venc_write_reg(VENC_LINE21, config->line21); ++ venc_write_reg(VENC_LN_SEL, config->ln_sel); ++ venc_write_reg(VENC_HTRIGGER_VTRIGGER, config->htrigger_vtrigger); ++ venc_write_reg(VENC_TVDETGP_INT_START_STOP_X, ++ config->tvdetgp_int_start_stop_x); ++ venc_write_reg(VENC_TVDETGP_INT_START_STOP_Y, ++ config->tvdetgp_int_start_stop_y); ++ venc_write_reg(VENC_GEN_CTRL, config->gen_ctrl); ++ venc_write_reg(VENC_F_CONTROL, config->f_control); ++ venc_write_reg(VENC_SYNC_CTRL, config->sync_ctrl); ++} ++ ++static void venc_reset(void) ++{ ++ int t = 1000; ++ ++ venc_write_reg(VENC_F_CONTROL, 1<<8); ++ while (venc_read_reg(VENC_F_CONTROL) & (1<<8)) { ++ if (--t == 0) { ++ DSSERR("Failed to reset venc\n"); ++ return; ++ } ++ } ++ ++ /* the magical sleep that makes things work */ ++ msleep(20); ++} ++ ++static void venc_enable_clocks(int enable) ++{ ++ if (enable) ++ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1 | DSS_CLK_54M | ++ DSS_CLK_96M); ++ else ++ dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1 | DSS_CLK_54M | ++ DSS_CLK_96M); ++} ++ ++static const struct venc_config *venc_timings_to_config( ++ struct omap_video_timings *timings) ++{ ++ if (memcmp(&omap_dss_pal_timings, timings, sizeof(*timings)) == 0) ++ return &venc_config_pal_trm; ++ ++ if (memcmp(&omap_dss_ntsc_timings, timings, sizeof(*timings)) == 0) ++ return &venc_config_ntsc_trm; ++ ++ BUG(); ++} ++ ++ ++ ++ ++ ++/* driver */ ++static int venc_panel_probe(struct omap_dss_device *dssdev) ++{ ++ dssdev->panel.timings = omap_dss_pal_timings; ++ ++ return 0; ++} ++ ++static void venc_panel_remove(struct omap_dss_device *dssdev) ++{ ++} ++ ++static int venc_panel_enable(struct omap_dss_device *dssdev) ++{ ++ int r = 0; ++ ++ /* wait couple of vsyncs until enabling the LCD */ ++ msleep(50); ++ ++ if (dssdev->platform_enable) ++ r = dssdev->platform_enable(dssdev); ++ ++ return r; ++} ++ ++static void venc_panel_disable(struct omap_dss_device *dssdev) ++{ ++ if (dssdev->platform_disable) ++ dssdev->platform_disable(dssdev); ++ ++ /* wait at least 5 vsyncs after disabling the LCD */ ++ ++ msleep(100); ++} ++ ++static int venc_panel_suspend(struct omap_dss_device *dssdev) ++{ ++ venc_panel_disable(dssdev); ++ return 0; ++} ++ ++static int venc_panel_resume(struct omap_dss_device *dssdev) ++{ ++ return venc_panel_enable(dssdev); ++} ++ ++static struct omap_dss_driver venc_driver = { ++ .probe = venc_panel_probe, ++ .remove = venc_panel_remove, ++ ++ .enable = venc_panel_enable, ++ .disable = venc_panel_disable, ++ .suspend = venc_panel_suspend, ++ .resume = venc_panel_resume, ++ ++ .driver = { ++ .name = "venc", ++ .owner = THIS_MODULE, ++ }, ++}; ++/* driver end */ ++ ++ ++ ++int venc_init(struct platform_device *pdev) ++{ ++ u8 rev_id; ++ ++ mutex_init(&venc.venc_lock); ++ ++ venc.wss_data = 0; ++ ++ venc.base = ioremap(VENC_BASE, SZ_1K); ++ if (!venc.base) { ++ DSSERR("can't ioremap VENC\n"); ++ return -ENOMEM; ++ } ++ ++ venc.vdda_dac_reg = regulator_get(&pdev->dev, "vdda_dac"); ++ if (IS_ERR(venc.vdda_dac_reg)) { ++ iounmap(venc.base); ++ DSSERR("can't get VDDA_DAC regulator\n"); ++ return PTR_ERR(venc.vdda_dac_reg); ++ } ++ ++ venc_enable_clocks(1); ++ ++ rev_id = (u8)(venc_read_reg(VENC_REV_ID) & 0xff); ++ printk(KERN_INFO "OMAP VENC rev %d\n", rev_id); ++ ++ venc_enable_clocks(0); ++ ++ return omap_dss_register_driver(&venc_driver); ++} ++ ++void venc_exit(void) ++{ ++ omap_dss_unregister_driver(&venc_driver); ++ ++ regulator_put(venc.vdda_dac_reg); ++ ++ iounmap(venc.base); ++} ++ ++static void venc_power_on(struct omap_dss_device *dssdev) ++{ ++ u32 l; ++ ++ venc_enable_clocks(1); ++ ++ venc_reset(); ++ venc_write_config(venc_timings_to_config(&dssdev->panel.timings)); ++ ++ dss_set_venc_output(dssdev->phy.venc.type); ++ dss_set_dac_pwrdn_bgz(1); ++ ++ l = 0; ++ ++ if (dssdev->phy.venc.type == OMAP_DSS_VENC_TYPE_COMPOSITE) ++ l |= 1 << 1; ++ else /* S-Video */ ++ l |= (1 << 0) | (1 << 2); ++ ++ if (dssdev->phy.venc.invert_polarity == false) ++ l |= 1 << 3; ++ ++ venc_write_reg(VENC_OUTPUT_CONTROL, l); ++ ++ dispc_set_digit_size(dssdev->panel.timings.x_res, ++ dssdev->panel.timings.y_res/2); ++ ++ regulator_enable(venc.vdda_dac_reg); ++ ++ if (dssdev->platform_enable) ++ dssdev->platform_enable(dssdev); ++ ++ dispc_enable_digit_out(1); ++} ++ ++static void venc_power_off(struct omap_dss_device *dssdev) ++{ ++ venc_write_reg(VENC_OUTPUT_CONTROL, 0); ++ dss_set_dac_pwrdn_bgz(0); ++ ++ dispc_enable_digit_out(0); ++ ++ if (dssdev->platform_disable) ++ dssdev->platform_disable(dssdev); ++ ++ regulator_disable(venc.vdda_dac_reg); ++ ++ venc_enable_clocks(0); ++} ++ ++static int venc_enable_display(struct omap_dss_device *dssdev) ++{ ++ int r = 0; ++ ++ DSSDBG("venc_enable_display\n"); ++ ++ mutex_lock(&venc.venc_lock); ++ ++ if (dssdev->state != OMAP_DSS_DISPLAY_DISABLED) { ++ r = -EINVAL; ++ goto err; ++ } ++ ++ venc_power_on(dssdev); ++ ++ venc.wss_data = 0; ++ ++ dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; ++err: ++ mutex_unlock(&venc.venc_lock); ++ ++ return r; ++} ++ ++static void venc_disable_display(struct omap_dss_device *dssdev) ++{ ++ DSSDBG("venc_disable_display\n"); ++ ++ mutex_lock(&venc.venc_lock); ++ ++ if (dssdev->state == OMAP_DSS_DISPLAY_DISABLED) ++ goto end; ++ ++ if (dssdev->state == OMAP_DSS_DISPLAY_SUSPENDED) { ++ /* suspended is the same as disabled with venc */ ++ dssdev->state = OMAP_DSS_DISPLAY_DISABLED; ++ goto end; ++ } ++ ++ venc_power_off(dssdev); ++ ++ dssdev->state = OMAP_DSS_DISPLAY_DISABLED; ++end: ++ mutex_unlock(&venc.venc_lock); ++} ++ ++static int venc_display_suspend(struct omap_dss_device *dssdev) ++{ ++ int r = 0; ++ ++ DSSDBG("venc_display_suspend\n"); ++ ++ mutex_lock(&venc.venc_lock); ++ ++ if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) { ++ r = -EINVAL; ++ goto err; ++ } ++ ++ venc_power_off(dssdev); ++ ++ dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED; ++err: ++ mutex_unlock(&venc.venc_lock); ++ ++ return r; ++} ++ ++static int venc_display_resume(struct omap_dss_device *dssdev) ++{ ++ int r = 0; ++ ++ DSSDBG("venc_display_resume\n"); ++ ++ mutex_lock(&venc.venc_lock); ++ ++ if (dssdev->state != OMAP_DSS_DISPLAY_SUSPENDED) { ++ r = -EINVAL; ++ goto err; ++ } ++ ++ venc_power_on(dssdev); ++ ++ dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; ++err: ++ mutex_unlock(&venc.venc_lock); ++ ++ return r; ++} ++ ++static void venc_get_timings(struct omap_dss_device *dssdev, ++ struct omap_video_timings *timings) ++{ ++ *timings = dssdev->panel.timings; ++} ++ ++static void venc_set_timings(struct omap_dss_device *dssdev, ++ struct omap_video_timings *timings) ++{ ++ DSSDBG("venc_set_timings\n"); ++ ++ /* Reset WSS data when the TV standard changes. */ ++ if (memcmp(&dssdev->panel.timings, timings, sizeof(*timings))) ++ venc.wss_data = 0; ++ ++ dssdev->panel.timings = *timings; ++ if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) { ++ /* turn the venc off and on to get new timings to use */ ++ venc_disable_display(dssdev); ++ venc_enable_display(dssdev); ++ } ++} ++ ++static int venc_check_timings(struct omap_dss_device *dssdev, ++ struct omap_video_timings *timings) ++{ ++ DSSDBG("venc_check_timings\n"); ++ ++ if (memcmp(&omap_dss_pal_timings, timings, sizeof(*timings)) == 0) ++ return 0; ++ ++ if (memcmp(&omap_dss_ntsc_timings, timings, sizeof(*timings)) == 0) ++ return 0; ++ ++ return -EINVAL; ++} ++ ++static u32 venc_get_wss(struct omap_dss_device *dssdev) ++{ ++ /* Invert due to VENC_L21_WC_CTL:INV=1 */ ++ return (venc.wss_data >> 8) ^ 0xfffff; ++} ++ ++static int venc_set_wss(struct omap_dss_device *dssdev, u32 wss) ++{ ++ const struct venc_config *config; ++ ++ DSSDBG("venc_set_wss\n"); ++ ++ mutex_lock(&venc.venc_lock); ++ ++ config = venc_timings_to_config(&dssdev->panel.timings); ++ ++ /* Invert due to VENC_L21_WC_CTL:INV=1 */ ++ venc.wss_data = (wss ^ 0xfffff) << 8; ++ ++ venc_enable_clocks(1); ++ ++ venc_write_reg(VENC_BSTAMP_WSS_DATA, config->bstamp_wss_data | ++ venc.wss_data); ++ ++ venc_enable_clocks(0); ++ ++ mutex_unlock(&venc.venc_lock); ++ ++ return 0; ++} ++ ++static enum omap_dss_update_mode venc_display_get_update_mode( ++ struct omap_dss_device *dssdev) ++{ ++ if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) ++ return OMAP_DSS_UPDATE_AUTO; ++ else ++ return OMAP_DSS_UPDATE_DISABLED; ++} ++ ++int venc_init_display(struct omap_dss_device *dssdev) ++{ ++ DSSDBG("init_display\n"); ++ ++ dssdev->enable = venc_enable_display; ++ dssdev->disable = venc_disable_display; ++ dssdev->suspend = venc_display_suspend; ++ dssdev->resume = venc_display_resume; ++ dssdev->get_timings = venc_get_timings; ++ dssdev->set_timings = venc_set_timings; ++ dssdev->check_timings = venc_check_timings; ++ dssdev->get_wss = venc_get_wss; ++ dssdev->set_wss = venc_set_wss; ++ dssdev->get_update_mode = venc_display_get_update_mode; ++ ++ return 0; ++} ++ ++void venc_dump_regs(struct seq_file *s) ++{ ++#define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, venc_read_reg(r)) ++ ++ venc_enable_clocks(1); ++ ++ DUMPREG(VENC_F_CONTROL); ++ DUMPREG(VENC_VIDOUT_CTRL); ++ DUMPREG(VENC_SYNC_CTRL); ++ DUMPREG(VENC_LLEN); ++ DUMPREG(VENC_FLENS); ++ DUMPREG(VENC_HFLTR_CTRL); ++ DUMPREG(VENC_CC_CARR_WSS_CARR); ++ DUMPREG(VENC_C_PHASE); ++ DUMPREG(VENC_GAIN_U); ++ DUMPREG(VENC_GAIN_V); ++ DUMPREG(VENC_GAIN_Y); ++ DUMPREG(VENC_BLACK_LEVEL); ++ DUMPREG(VENC_BLANK_LEVEL); ++ DUMPREG(VENC_X_COLOR); ++ DUMPREG(VENC_M_CONTROL); ++ DUMPREG(VENC_BSTAMP_WSS_DATA); ++ DUMPREG(VENC_S_CARR); ++ DUMPREG(VENC_LINE21); ++ DUMPREG(VENC_LN_SEL); ++ DUMPREG(VENC_L21__WC_CTL); ++ DUMPREG(VENC_HTRIGGER_VTRIGGER); ++ DUMPREG(VENC_SAVID__EAVID); ++ DUMPREG(VENC_FLEN__FAL); ++ DUMPREG(VENC_LAL__PHASE_RESET); ++ DUMPREG(VENC_HS_INT_START_STOP_X); ++ DUMPREG(VENC_HS_EXT_START_STOP_X); ++ DUMPREG(VENC_VS_INT_START_X); ++ DUMPREG(VENC_VS_INT_STOP_X__VS_INT_START_Y); ++ DUMPREG(VENC_VS_INT_STOP_Y__VS_EXT_START_X); ++ DUMPREG(VENC_VS_EXT_STOP_X__VS_EXT_START_Y); ++ DUMPREG(VENC_VS_EXT_STOP_Y); ++ DUMPREG(VENC_AVID_START_STOP_X); ++ DUMPREG(VENC_AVID_START_STOP_Y); ++ DUMPREG(VENC_FID_INT_START_X__FID_INT_START_Y); ++ DUMPREG(VENC_FID_INT_OFFSET_Y__FID_EXT_START_X); ++ DUMPREG(VENC_FID_EXT_START_Y__FID_EXT_OFFSET_Y); ++ DUMPREG(VENC_TVDETGP_INT_START_STOP_X); ++ DUMPREG(VENC_TVDETGP_INT_START_STOP_Y); ++ DUMPREG(VENC_GEN_CTRL); ++ DUMPREG(VENC_OUTPUT_CONTROL); ++ DUMPREG(VENC_OUTPUT_TEST); ++ ++ venc_enable_clocks(0); ++ ++#undef DUMPREG ++} +diff --git a/drivers/video/omap2/omapfb/Kconfig b/drivers/video/omap2/omapfb/Kconfig +new file mode 100644 +index 0000000..bb694cc +--- /dev/null ++++ b/drivers/video/omap2/omapfb/Kconfig +@@ -0,0 +1,37 @@ ++menuconfig FB_OMAP2 ++ tristate "OMAP2/3 frame buffer support (EXPERIMENTAL)" ++ depends on FB && OMAP2_DSS ++ ++ select OMAP2_VRAM ++ select OMAP2_VRFB ++ select FB_CFB_FILLRECT ++ select FB_CFB_COPYAREA ++ select FB_CFB_IMAGEBLIT ++ help ++ Frame buffer driver for OMAP2/3 based boards. ++ ++config FB_OMAP2_DEBUG_SUPPORT ++ bool "Debug support for OMAP2/3 FB" ++ default y ++ depends on FB_OMAP2 ++ help ++ Support for debug output. You have to enable the actual printing ++ with debug module parameter. ++ ++config FB_OMAP2_FORCE_AUTO_UPDATE ++ bool "Force main display to automatic update mode" ++ depends on FB_OMAP2 ++ help ++ Forces main display to automatic update mode (if possible), ++ and also enables tearsync (if possible). By default ++ displays that support manual update are started in manual ++ update mode. ++ ++config FB_OMAP2_NUM_FBS ++ int "Number of framebuffers" ++ range 1 10 ++ default 3 ++ depends on FB_OMAP2 ++ help ++ Select the number of framebuffers created. OMAP2/3 has 3 overlays ++ so normally this would be 3. +diff --git a/drivers/video/omap2/omapfb/Makefile b/drivers/video/omap2/omapfb/Makefile +new file mode 100644 +index 0000000..51c2e00 +--- /dev/null ++++ b/drivers/video/omap2/omapfb/Makefile +@@ -0,0 +1,2 @@ ++obj-$(CONFIG_FB_OMAP2) += omapfb.o ++omapfb-y := omapfb-main.o omapfb-sysfs.o omapfb-ioctl.o +diff --git a/drivers/video/omap2/omapfb/omapfb-ioctl.c b/drivers/video/omap2/omapfb/omapfb-ioctl.c +new file mode 100644 +index 0000000..70fb64e +--- /dev/null ++++ b/drivers/video/omap2/omapfb/omapfb-ioctl.c +@@ -0,0 +1,727 @@ ++/* ++ * linux/drivers/video/omap2/omapfb-ioctl.c ++ * ++ * Copyright (C) 2008 Nokia Corporation ++ * Author: Tomi Valkeinen ++ * ++ * Some code and ideas taken from drivers/video/omap/ driver ++ * by Imre Deak. ++ * ++ * 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. ++ * ++ * 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, see . ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++#include "omapfb.h" ++ ++static int omapfb_setup_plane(struct fb_info *fbi, struct omapfb_plane_info *pi) ++{ ++ struct omapfb_info *ofbi = FB2OFB(fbi); ++ struct omapfb2_device *fbdev = ofbi->fbdev; ++ struct omap_dss_device *display = fb2display(fbi); ++ struct omap_overlay *ovl; ++ struct omap_overlay_info info; ++ int r = 0; ++ ++ DBG("omapfb_setup_plane\n"); ++ ++ if (ofbi->num_overlays != 1) { ++ r = -EINVAL; ++ goto out; ++ } ++ ++ /* XXX uses only the first overlay */ ++ ovl = ofbi->overlays[0]; ++ ++ if (pi->enabled && !ofbi->region.size) { ++ /* ++ * This plane's memory was freed, can't enable it ++ * until it's reallocated. ++ */ ++ r = -EINVAL; ++ goto out; ++ } ++ ++ ovl->get_overlay_info(ovl, &info); ++ ++ info.pos_x = pi->pos_x; ++ info.pos_y = pi->pos_y; ++ info.out_width = pi->out_width; ++ info.out_height = pi->out_height; ++ info.enabled = pi->enabled; ++ ++ r = ovl->set_overlay_info(ovl, &info); ++ if (r) ++ goto out; ++ ++ if (ovl->manager) { ++ r = ovl->manager->apply(ovl->manager); ++ if (r) ++ goto out; ++ } ++ ++ if (display) { ++ u16 w, h; ++ ++ if (display->sync) ++ display->sync(display); ++ ++ display->get_resolution(display, &w, &h); ++ ++ if (display->update) ++ display->update(display, 0, 0, w, h); ++ } ++ ++out: ++ if (r) ++ dev_err(fbdev->dev, "setup_plane failed\n"); ++ return r; ++} ++ ++static int omapfb_query_plane(struct fb_info *fbi, struct omapfb_plane_info *pi) ++{ ++ struct omapfb_info *ofbi = FB2OFB(fbi); ++ ++ if (ofbi->num_overlays != 1) { ++ memset(pi, 0, sizeof(*pi)); ++ } else { ++ struct omap_overlay_info *ovli; ++ struct omap_overlay *ovl; ++ ++ ovl = ofbi->overlays[0]; ++ ovli = &ovl->info; ++ ++ pi->pos_x = ovli->pos_x; ++ pi->pos_y = ovli->pos_y; ++ pi->enabled = ovli->enabled; ++ pi->channel_out = 0; /* xxx */ ++ pi->mirror = 0; ++ pi->out_width = ovli->out_width; ++ pi->out_height = ovli->out_height; ++ } ++ ++ return 0; ++} ++ ++static int omapfb_setup_mem(struct fb_info *fbi, struct omapfb_mem_info *mi) ++{ ++ struct omapfb_info *ofbi = FB2OFB(fbi); ++ struct omapfb2_device *fbdev = ofbi->fbdev; ++ struct omapfb2_mem_region *rg; ++ int r, i; ++ size_t size; ++ ++ if (mi->type > OMAPFB_MEMTYPE_MAX) ++ return -EINVAL; ++ ++ size = PAGE_ALIGN(mi->size); ++ ++ rg = &ofbi->region; ++ ++ for (i = 0; i < ofbi->num_overlays; i++) { ++ if (ofbi->overlays[i]->info.enabled) ++ return -EBUSY; ++ } ++ ++ if (rg->size != size || rg->type != mi->type) { ++ r = omapfb_realloc_fbmem(fbi, size, mi->type); ++ if (r) { ++ dev_err(fbdev->dev, "realloc fbmem failed\n"); ++ return r; ++ } ++ } ++ ++ return 0; ++} ++ ++static int omapfb_query_mem(struct fb_info *fbi, struct omapfb_mem_info *mi) ++{ ++ struct omapfb_info *ofbi = FB2OFB(fbi); ++ struct omapfb2_mem_region *rg; ++ ++ rg = &ofbi->region; ++ memset(mi, 0, sizeof(*mi)); ++ ++ mi->size = rg->size; ++ mi->type = rg->type; ++ ++ return 0; ++} ++ ++static int omapfb_update_window(struct fb_info *fbi, ++ u32 x, u32 y, u32 w, u32 h) ++{ ++ struct omap_dss_device *display = fb2display(fbi); ++ u16 dw, dh; ++ ++ if (!display) ++ return 0; ++ ++ if (w == 0 || h == 0) ++ return 0; ++ ++ display->get_resolution(display, &dw, &dh); ++ ++ if (x + w > dw || y + h > dh) ++ return -EINVAL; ++ ++ display->update(display, x, y, w, h); ++ ++ return 0; ++} ++ ++static int omapfb_set_update_mode(struct fb_info *fbi, ++ enum omapfb_update_mode mode) ++{ ++ struct omap_dss_device *display = fb2display(fbi); ++ enum omap_dss_update_mode um; ++ int r; ++ ++ if (!display || !display->set_update_mode) ++ return -EINVAL; ++ ++ switch (mode) { ++ case OMAPFB_UPDATE_DISABLED: ++ um = OMAP_DSS_UPDATE_DISABLED; ++ break; ++ ++ case OMAPFB_AUTO_UPDATE: ++ um = OMAP_DSS_UPDATE_AUTO; ++ break; ++ ++ case OMAPFB_MANUAL_UPDATE: ++ um = OMAP_DSS_UPDATE_MANUAL; ++ break; ++ ++ default: ++ return -EINVAL; ++ } ++ ++ r = display->set_update_mode(display, um); ++ ++ return r; ++} ++ ++static int omapfb_get_update_mode(struct fb_info *fbi, ++ enum omapfb_update_mode *mode) ++{ ++ struct omap_dss_device *display = fb2display(fbi); ++ enum omap_dss_update_mode m; ++ ++ if (!display || !display->get_update_mode) ++ return -EINVAL; ++ ++ m = display->get_update_mode(display); ++ ++ switch (m) { ++ case OMAP_DSS_UPDATE_DISABLED: ++ *mode = OMAPFB_UPDATE_DISABLED; ++ break; ++ case OMAP_DSS_UPDATE_AUTO: ++ *mode = OMAPFB_AUTO_UPDATE; ++ break; ++ case OMAP_DSS_UPDATE_MANUAL: ++ *mode = OMAPFB_MANUAL_UPDATE; ++ break; ++ default: ++ BUG(); ++ } ++ ++ return 0; ++} ++ ++/* XXX this color key handling is a hack... */ ++static struct omapfb_color_key omapfb_color_keys[2]; ++ ++static int _omapfb_set_color_key(struct omap_overlay_manager *mgr, ++ struct omapfb_color_key *ck) ++{ ++ struct omap_overlay_manager_info info; ++ enum omap_dss_trans_key_type kt; ++ int r; ++ ++ mgr->get_manager_info(mgr, &info); ++ ++ if (ck->key_type == OMAPFB_COLOR_KEY_DISABLED) { ++ info.trans_enabled = false; ++ omapfb_color_keys[mgr->id] = *ck; ++ ++ r = mgr->set_manager_info(mgr, &info); ++ if (r) ++ return r; ++ ++ r = mgr->apply(mgr); ++ ++ return r; ++ } ++ ++ switch (ck->key_type) { ++ case OMAPFB_COLOR_KEY_GFX_DST: ++ kt = OMAP_DSS_COLOR_KEY_GFX_DST; ++ break; ++ case OMAPFB_COLOR_KEY_VID_SRC: ++ kt = OMAP_DSS_COLOR_KEY_VID_SRC; ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ info.default_color = ck->background; ++ info.trans_key = ck->trans_key; ++ info.trans_key_type = kt; ++ info.trans_enabled = true; ++ ++ omapfb_color_keys[mgr->id] = *ck; ++ ++ r = mgr->set_manager_info(mgr, &info); ++ if (r) ++ return r; ++ ++ r = mgr->apply(mgr); ++ ++ return r; ++} ++ ++static int omapfb_set_color_key(struct fb_info *fbi, ++ struct omapfb_color_key *ck) ++{ ++ struct omapfb_info *ofbi = FB2OFB(fbi); ++ struct omapfb2_device *fbdev = ofbi->fbdev; ++ int r; ++ int i; ++ struct omap_overlay_manager *mgr = NULL; ++ ++ omapfb_lock(fbdev); ++ ++ for (i = 0; i < ofbi->num_overlays; i++) { ++ if (ofbi->overlays[i]->manager) { ++ mgr = ofbi->overlays[i]->manager; ++ break; ++ } ++ } ++ ++ if (!mgr) { ++ r = -EINVAL; ++ goto err; ++ } ++ ++ r = _omapfb_set_color_key(mgr, ck); ++err: ++ omapfb_unlock(fbdev); ++ ++ return r; ++} ++ ++static int omapfb_get_color_key(struct fb_info *fbi, ++ struct omapfb_color_key *ck) ++{ ++ struct omapfb_info *ofbi = FB2OFB(fbi); ++ struct omapfb2_device *fbdev = ofbi->fbdev; ++ struct omap_overlay_manager *mgr = NULL; ++ int r = 0; ++ int i; ++ ++ omapfb_lock(fbdev); ++ ++ for (i = 0; i < ofbi->num_overlays; i++) { ++ if (ofbi->overlays[i]->manager) { ++ mgr = ofbi->overlays[i]->manager; ++ break; ++ } ++ } ++ ++ if (!mgr) { ++ r = -EINVAL; ++ goto err; ++ } ++ ++ *ck = omapfb_color_keys[mgr->id]; ++err: ++ omapfb_unlock(fbdev); ++ ++ return r; ++} ++ ++static int omapfb_memory_read(struct fb_info *fbi, ++ struct omapfb_memory_read *mr) ++{ ++ struct omap_dss_device *display = fb2display(fbi); ++ void *buf; ++ int r; ++ ++ if (!display || !display->memory_read) ++ return -ENOENT; ++ ++ if (!access_ok(VERIFY_WRITE, mr->buffer, mr->buffer_size)) ++ return -EFAULT; ++ ++ if (mr->w * mr->h * 3 > mr->buffer_size) ++ return -EINVAL; ++ ++ buf = vmalloc(mr->buffer_size); ++ if (!buf) { ++ DBG("vmalloc failed\n"); ++ return -ENOMEM; ++ } ++ ++ r = display->memory_read(display, buf, mr->buffer_size, ++ mr->x, mr->y, mr->w, mr->h); ++ ++ if (r > 0) { ++ if (copy_to_user(mr->buffer, buf, mr->buffer_size)) ++ r = -EFAULT; ++ } ++ ++ vfree(buf); ++ ++ return r; ++} ++ ++static int omapfb_get_ovl_colormode(struct omapfb2_device *fbdev, ++ struct omapfb_ovl_colormode *mode) ++{ ++ int ovl_idx = mode->overlay_idx; ++ int mode_idx = mode->mode_idx; ++ struct omap_overlay *ovl; ++ enum omap_color_mode supported_modes; ++ struct fb_var_screeninfo var; ++ int i; ++ ++ if (ovl_idx >= fbdev->num_overlays) ++ return -ENODEV; ++ ovl = fbdev->overlays[ovl_idx]; ++ supported_modes = ovl->supported_modes; ++ ++ mode_idx = mode->mode_idx; ++ ++ for (i = 0; i < sizeof(supported_modes) * 8; i++) { ++ if (!(supported_modes & (1 << i))) ++ continue; ++ /* ++ * It's possible that the FB doesn't support a mode ++ * that is supported by the overlay, so call the ++ * following here. ++ */ ++ if (dss_mode_to_fb_mode(1 << i, &var) < 0) ++ continue; ++ ++ mode_idx--; ++ if (mode_idx < 0) ++ break; ++ } ++ ++ if (i == sizeof(supported_modes) * 8) ++ return -ENOENT; ++ ++ mode->bits_per_pixel = var.bits_per_pixel; ++ mode->nonstd = var.nonstd; ++ mode->red = var.red; ++ mode->green = var.green; ++ mode->blue = var.blue; ++ mode->transp = var.transp; ++ ++ return 0; ++} ++ ++static int omapfb_wait_for_go(struct fb_info *fbi) ++{ ++ struct omapfb_info *ofbi = FB2OFB(fbi); ++ int r = 0; ++ int i; ++ ++ for (i = 0; i < ofbi->num_overlays; ++i) { ++ struct omap_overlay *ovl = ofbi->overlays[i]; ++ r = ovl->wait_for_go(ovl); ++ if (r) ++ break; ++ } ++ ++ return r; ++} ++ ++int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg) ++{ ++ struct omapfb_info *ofbi = FB2OFB(fbi); ++ struct omapfb2_device *fbdev = ofbi->fbdev; ++ struct omap_dss_device *display = fb2display(fbi); ++ ++ union { ++ struct omapfb_update_window_old uwnd_o; ++ struct omapfb_update_window uwnd; ++ struct omapfb_plane_info plane_info; ++ struct omapfb_caps caps; ++ struct omapfb_mem_info mem_info; ++ struct omapfb_color_key color_key; ++ struct omapfb_ovl_colormode ovl_colormode; ++ enum omapfb_update_mode update_mode; ++ int test_num; ++ struct omapfb_memory_read memory_read; ++ struct omapfb_vram_info vram_info; ++ } p; ++ ++ int r = 0; ++ ++ switch (cmd) { ++ case OMAPFB_SYNC_GFX: ++ DBG("ioctl SYNC_GFX\n"); ++ if (!display || !display->sync) { ++ /* DSS1 never returns an error here, so we neither */ ++ /*r = -EINVAL;*/ ++ break; ++ } ++ ++ r = display->sync(display); ++ break; ++ ++ case OMAPFB_UPDATE_WINDOW_OLD: ++ DBG("ioctl UPDATE_WINDOW_OLD\n"); ++ if (!display || !display->update) { ++ r = -EINVAL; ++ break; ++ } ++ ++ if (copy_from_user(&p.uwnd_o, ++ (void __user *)arg, ++ sizeof(p.uwnd_o))) { ++ r = -EFAULT; ++ break; ++ } ++ ++ r = omapfb_update_window(fbi, p.uwnd_o.x, p.uwnd_o.y, ++ p.uwnd_o.width, p.uwnd_o.height); ++ break; ++ ++ case OMAPFB_UPDATE_WINDOW: ++ DBG("ioctl UPDATE_WINDOW\n"); ++ if (!display || !display->update) { ++ r = -EINVAL; ++ break; ++ } ++ ++ if (copy_from_user(&p.uwnd, (void __user *)arg, ++ sizeof(p.uwnd))) { ++ r = -EFAULT; ++ break; ++ } ++ ++ r = omapfb_update_window(fbi, p.uwnd.x, p.uwnd.y, ++ p.uwnd.width, p.uwnd.height); ++ break; ++ ++ case OMAPFB_SETUP_PLANE: ++ DBG("ioctl SETUP_PLANE\n"); ++ if (copy_from_user(&p.plane_info, (void __user *)arg, ++ sizeof(p.plane_info))) ++ r = -EFAULT; ++ else ++ r = omapfb_setup_plane(fbi, &p.plane_info); ++ break; ++ ++ case OMAPFB_QUERY_PLANE: ++ DBG("ioctl QUERY_PLANE\n"); ++ r = omapfb_query_plane(fbi, &p.plane_info); ++ if (r < 0) ++ break; ++ if (copy_to_user((void __user *)arg, &p.plane_info, ++ sizeof(p.plane_info))) ++ r = -EFAULT; ++ break; ++ ++ case OMAPFB_SETUP_MEM: ++ DBG("ioctl SETUP_MEM\n"); ++ if (copy_from_user(&p.mem_info, (void __user *)arg, ++ sizeof(p.mem_info))) ++ r = -EFAULT; ++ else ++ r = omapfb_setup_mem(fbi, &p.mem_info); ++ break; ++ ++ case OMAPFB_QUERY_MEM: ++ DBG("ioctl QUERY_MEM\n"); ++ r = omapfb_query_mem(fbi, &p.mem_info); ++ if (r < 0) ++ break; ++ if (copy_to_user((void __user *)arg, &p.mem_info, ++ sizeof(p.mem_info))) ++ r = -EFAULT; ++ break; ++ ++ case OMAPFB_GET_CAPS: ++ DBG("ioctl GET_CAPS\n"); ++ if (!display) { ++ r = -EINVAL; ++ break; ++ } ++ ++ memset(&p.caps, 0, sizeof(p.caps)); ++ p.caps.ctrl = display->caps; ++ ++ if (copy_to_user((void __user *)arg, &p.caps, sizeof(p.caps))) ++ r = -EFAULT; ++ break; ++ ++ case OMAPFB_GET_OVERLAY_COLORMODE: ++ DBG("ioctl GET_OVERLAY_COLORMODE\n"); ++ if (copy_from_user(&p.ovl_colormode, (void __user *)arg, ++ sizeof(p.ovl_colormode))) { ++ r = -EFAULT; ++ break; ++ } ++ r = omapfb_get_ovl_colormode(fbdev, &p.ovl_colormode); ++ if (r < 0) ++ break; ++ if (copy_to_user((void __user *)arg, &p.ovl_colormode, ++ sizeof(p.ovl_colormode))) ++ r = -EFAULT; ++ break; ++ ++ case OMAPFB_SET_UPDATE_MODE: ++ DBG("ioctl SET_UPDATE_MODE\n"); ++ if (get_user(p.update_mode, (int __user *)arg)) ++ r = -EFAULT; ++ else ++ r = omapfb_set_update_mode(fbi, p.update_mode); ++ break; ++ ++ case OMAPFB_GET_UPDATE_MODE: ++ DBG("ioctl GET_UPDATE_MODE\n"); ++ r = omapfb_get_update_mode(fbi, &p.update_mode); ++ if (r) ++ break; ++ if (put_user(p.update_mode, ++ (enum omapfb_update_mode __user *)arg)) ++ r = -EFAULT; ++ break; ++ ++ case OMAPFB_SET_COLOR_KEY: ++ DBG("ioctl SET_COLOR_KEY\n"); ++ if (copy_from_user(&p.color_key, (void __user *)arg, ++ sizeof(p.color_key))) ++ r = -EFAULT; ++ else ++ r = omapfb_set_color_key(fbi, &p.color_key); ++ break; ++ ++ case OMAPFB_GET_COLOR_KEY: ++ DBG("ioctl GET_COLOR_KEY\n"); ++ r = omapfb_get_color_key(fbi, &p.color_key); ++ if (r) ++ break; ++ if (copy_to_user((void __user *)arg, &p.color_key, ++ sizeof(p.color_key))) ++ r = -EFAULT; ++ break; ++ ++ case OMAPFB_WAITFORVSYNC: ++ DBG("ioctl WAITFORVSYNC\n"); ++ if (!display) { ++ r = -EINVAL; ++ break; ++ } ++ ++ r = display->wait_vsync(display); ++ break; ++ ++ case OMAPFB_WAITFORGO: ++ DBG("ioctl WAITFORGO\n"); ++ if (!display) { ++ r = -EINVAL; ++ break; ++ } ++ ++ r = omapfb_wait_for_go(fbi); ++ break; ++ ++ /* LCD and CTRL tests do the same thing for backward ++ * compatibility */ ++ case OMAPFB_LCD_TEST: ++ DBG("ioctl LCD_TEST\n"); ++ if (get_user(p.test_num, (int __user *)arg)) { ++ r = -EFAULT; ++ break; ++ } ++ if (!display || !display->run_test) { ++ r = -EINVAL; ++ break; ++ } ++ ++ r = display->run_test(display, p.test_num); ++ ++ break; ++ ++ case OMAPFB_CTRL_TEST: ++ DBG("ioctl CTRL_TEST\n"); ++ if (get_user(p.test_num, (int __user *)arg)) { ++ r = -EFAULT; ++ break; ++ } ++ if (!display || !display->run_test) { ++ r = -EINVAL; ++ break; ++ } ++ ++ r = display->run_test(display, p.test_num); ++ ++ break; ++ ++ case OMAPFB_MEMORY_READ: ++ DBG("ioctl MEMORY_READ\n"); ++ ++ if (copy_from_user(&p.memory_read, (void __user *)arg, ++ sizeof(p.memory_read))) { ++ r = -EFAULT; ++ break; ++ } ++ ++ r = omapfb_memory_read(fbi, &p.memory_read); ++ ++ break; ++ ++ case OMAPFB_GET_VRAM_INFO: { ++ unsigned long vram, free, largest; ++ ++ DBG("ioctl GET_VRAM_INFO\n"); ++ ++ omap_vram_get_info(&vram, &free, &largest); ++ p.vram_info.total = vram; ++ p.vram_info.free = free; ++ p.vram_info.largest_free_block = largest; ++ ++ if (copy_to_user((void __user *)arg, &p.vram_info, ++ sizeof(p.vram_info))) ++ r = -EFAULT; ++ break; ++ } ++ ++ default: ++ dev_err(fbdev->dev, "Unknown ioctl 0x%x\n", cmd); ++ r = -EINVAL; ++ } ++ ++ if (r < 0) ++ DBG("ioctl failed: %d\n", r); ++ ++ return r; ++} ++ ++ +diff --git a/drivers/video/omap2/omapfb/omapfb-main.c b/drivers/video/omap2/omapfb/omapfb-main.c +new file mode 100644 +index 0000000..7f5ec3b +--- /dev/null ++++ b/drivers/video/omap2/omapfb/omapfb-main.c +@@ -0,0 +1,2137 @@ ++/* ++ * linux/drivers/video/omap2/omapfb-main.c ++ * ++ * Copyright (C) 2008 Nokia Corporation ++ * Author: Tomi Valkeinen ++ * ++ * Some code and ideas taken from drivers/video/omap/ driver ++ * by Imre Deak. ++ * ++ * 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. ++ * ++ * 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, see . ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++#include "omapfb.h" ++ ++#define MODULE_NAME "omapfb" ++ ++#define OMAPFB_PLANE_XRES_MIN 8 ++#define OMAPFB_PLANE_YRES_MIN 8 ++ ++static char *def_mode; ++static char *def_vram; ++static int def_vrfb; ++static int def_rotate; ++static int def_mirror; ++ ++#ifdef DEBUG ++unsigned int omapfb_debug; ++module_param_named(debug, omapfb_debug, bool, 0644); ++static unsigned int omapfb_test_pattern; ++module_param_named(test, omapfb_test_pattern, bool, 0644); ++#endif ++ ++static int omapfb_fb_init(struct omapfb2_device *fbdev, struct fb_info *fbi); ++ ++#ifdef DEBUG ++static void draw_pixel(struct fb_info *fbi, int x, int y, unsigned color) ++{ ++ struct fb_var_screeninfo *var = &fbi->var; ++ struct fb_fix_screeninfo *fix = &fbi->fix; ++ void __iomem *addr = fbi->screen_base; ++ const unsigned bytespp = var->bits_per_pixel >> 3; ++ const unsigned line_len = fix->line_length / bytespp; ++ ++ int r = (color >> 16) & 0xff; ++ int g = (color >> 8) & 0xff; ++ int b = (color >> 0) & 0xff; ++ ++ if (var->bits_per_pixel == 16) { ++ u16 __iomem *p = (u16 __iomem *)addr; ++ p += y * line_len + x; ++ ++ r = r * 32 / 256; ++ g = g * 64 / 256; ++ b = b * 32 / 256; ++ ++ __raw_writew((r << 11) | (g << 5) | (b << 0), p); ++ } else if (var->bits_per_pixel == 24) { ++ u8 __iomem *p = (u8 __iomem *)addr; ++ p += (y * line_len + x) * 3; ++ ++ __raw_writeb(b, p + 0); ++ __raw_writeb(g, p + 1); ++ __raw_writeb(r, p + 2); ++ } else if (var->bits_per_pixel == 32) { ++ u32 __iomem *p = (u32 __iomem *)addr; ++ p += y * line_len + x; ++ __raw_writel(color, p); ++ } ++} ++ ++static void fill_fb(struct fb_info *fbi) ++{ ++ struct fb_var_screeninfo *var = &fbi->var; ++ const short w = var->xres_virtual; ++ const short h = var->yres_virtual; ++ void __iomem *addr = fbi->screen_base; ++ int y, x; ++ ++ if (!addr) ++ return; ++ ++ DBG("fill_fb %dx%d, line_len %d bytes\n", w, h, fbi->fix.line_length); ++ ++ for (y = 0; y < h; y++) { ++ for (x = 0; x < w; x++) { ++ if (x < 20 && y < 20) ++ draw_pixel(fbi, x, y, 0xffffff); ++ else if (x < 20 && (y > 20 && y < h - 20)) ++ draw_pixel(fbi, x, y, 0xff); ++ else if (y < 20 && (x > 20 && x < w - 20)) ++ draw_pixel(fbi, x, y, 0xff00); ++ else if (x > w - 20 && (y > 20 && y < h - 20)) ++ draw_pixel(fbi, x, y, 0xff0000); ++ else if (y > h - 20 && (x > 20 && x < w - 20)) ++ draw_pixel(fbi, x, y, 0xffff00); ++ else if (x == 20 || x == w - 20 || ++ y == 20 || y == h - 20) ++ draw_pixel(fbi, x, y, 0xffffff); ++ else if (x == y || w - x == h - y) ++ draw_pixel(fbi, x, y, 0xff00ff); ++ else if (w - x == y || x == h - y) ++ draw_pixel(fbi, x, y, 0x00ffff); ++ else if (x > 20 && y > 20 && x < w - 20 && y < h - 20) { ++ int t = x * 3 / w; ++ unsigned r = 0, g = 0, b = 0; ++ unsigned c; ++ if (var->bits_per_pixel == 16) { ++ if (t == 0) ++ b = (y % 32) * 256 / 32; ++ else if (t == 1) ++ g = (y % 64) * 256 / 64; ++ else if (t == 2) ++ r = (y % 32) * 256 / 32; ++ } else { ++ if (t == 0) ++ b = (y % 256); ++ else if (t == 1) ++ g = (y % 256); ++ else if (t == 2) ++ r = (y % 256); ++ } ++ c = (r << 16) | (g << 8) | (b << 0); ++ draw_pixel(fbi, x, y, c); ++ } else { ++ draw_pixel(fbi, x, y, 0); ++ } ++ } ++ } ++} ++#endif ++ ++static unsigned omapfb_get_vrfb_offset(struct omapfb_info *ofbi, int rot) ++{ ++ struct vrfb *vrfb = &ofbi->region.vrfb; ++ unsigned offset; ++ ++ switch (rot) { ++ case FB_ROTATE_UR: ++ offset = 0; ++ break; ++ case FB_ROTATE_CW: ++ offset = vrfb->yoffset; ++ break; ++ case FB_ROTATE_UD: ++ offset = vrfb->yoffset * OMAP_VRFB_LINE_LEN + vrfb->xoffset; ++ break; ++ case FB_ROTATE_CCW: ++ offset = vrfb->xoffset * OMAP_VRFB_LINE_LEN; ++ break; ++ default: ++ BUG(); ++ } ++ ++ offset *= vrfb->bytespp; ++ ++ return offset; ++} ++ ++static u32 omapfb_get_region_rot_paddr(struct omapfb_info *ofbi, int rot) ++{ ++ if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) { ++ return ofbi->region.vrfb.paddr[rot] ++ + omapfb_get_vrfb_offset(ofbi, rot); ++ } else { ++ return ofbi->region.paddr; ++ } ++} ++ ++static u32 omapfb_get_region_paddr(struct omapfb_info *ofbi) ++{ ++ if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) ++ return ofbi->region.vrfb.paddr[0]; ++ else ++ return ofbi->region.paddr; ++} ++ ++static void __iomem *omapfb_get_region_vaddr(struct omapfb_info *ofbi) ++{ ++ if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) ++ return ofbi->region.vrfb.vaddr[0]; ++ else ++ return ofbi->region.vaddr; ++} ++ ++static struct omapfb_colormode omapfb_colormodes[] = { ++ { ++ .dssmode = OMAP_DSS_COLOR_UYVY, ++ .bits_per_pixel = 16, ++ .nonstd = OMAPFB_COLOR_YUV422, ++ }, { ++ .dssmode = OMAP_DSS_COLOR_YUV2, ++ .bits_per_pixel = 16, ++ .nonstd = OMAPFB_COLOR_YUY422, ++ }, { ++ .dssmode = OMAP_DSS_COLOR_ARGB16, ++ .bits_per_pixel = 16, ++ .red = { .length = 4, .offset = 8, .msb_right = 0 }, ++ .green = { .length = 4, .offset = 4, .msb_right = 0 }, ++ .blue = { .length = 4, .offset = 0, .msb_right = 0 }, ++ .transp = { .length = 4, .offset = 12, .msb_right = 0 }, ++ }, { ++ .dssmode = OMAP_DSS_COLOR_RGB16, ++ .bits_per_pixel = 16, ++ .red = { .length = 5, .offset = 11, .msb_right = 0 }, ++ .green = { .length = 6, .offset = 5, .msb_right = 0 }, ++ .blue = { .length = 5, .offset = 0, .msb_right = 0 }, ++ .transp = { .length = 0, .offset = 0, .msb_right = 0 }, ++ }, { ++ .dssmode = OMAP_DSS_COLOR_RGB24P, ++ .bits_per_pixel = 24, ++ .red = { .length = 8, .offset = 16, .msb_right = 0 }, ++ .green = { .length = 8, .offset = 8, .msb_right = 0 }, ++ .blue = { .length = 8, .offset = 0, .msb_right = 0 }, ++ .transp = { .length = 0, .offset = 0, .msb_right = 0 }, ++ }, { ++ .dssmode = OMAP_DSS_COLOR_RGB24U, ++ .bits_per_pixel = 32, ++ .red = { .length = 8, .offset = 16, .msb_right = 0 }, ++ .green = { .length = 8, .offset = 8, .msb_right = 0 }, ++ .blue = { .length = 8, .offset = 0, .msb_right = 0 }, ++ .transp = { .length = 0, .offset = 0, .msb_right = 0 }, ++ }, { ++ .dssmode = OMAP_DSS_COLOR_ARGB32, ++ .bits_per_pixel = 32, ++ .red = { .length = 8, .offset = 16, .msb_right = 0 }, ++ .green = { .length = 8, .offset = 8, .msb_right = 0 }, ++ .blue = { .length = 8, .offset = 0, .msb_right = 0 }, ++ .transp = { .length = 8, .offset = 24, .msb_right = 0 }, ++ }, { ++ .dssmode = OMAP_DSS_COLOR_RGBA32, ++ .bits_per_pixel = 32, ++ .red = { .length = 8, .offset = 24, .msb_right = 0 }, ++ .green = { .length = 8, .offset = 16, .msb_right = 0 }, ++ .blue = { .length = 8, .offset = 8, .msb_right = 0 }, ++ .transp = { .length = 8, .offset = 0, .msb_right = 0 }, ++ }, { ++ .dssmode = OMAP_DSS_COLOR_RGBX32, ++ .bits_per_pixel = 32, ++ .red = { .length = 8, .offset = 24, .msb_right = 0 }, ++ .green = { .length = 8, .offset = 16, .msb_right = 0 }, ++ .blue = { .length = 8, .offset = 8, .msb_right = 0 }, ++ .transp = { .length = 0, .offset = 0, .msb_right = 0 }, ++ }, ++}; ++ ++static bool cmp_var_to_colormode(struct fb_var_screeninfo *var, ++ struct omapfb_colormode *color) ++{ ++ bool cmp_component(struct fb_bitfield *f1, struct fb_bitfield *f2) ++ { ++ return f1->length == f2->length && ++ f1->offset == f2->offset && ++ f1->msb_right == f2->msb_right; ++ } ++ ++ if (var->bits_per_pixel == 0 || ++ var->red.length == 0 || ++ var->blue.length == 0 || ++ var->green.length == 0) ++ return 0; ++ ++ return var->bits_per_pixel == color->bits_per_pixel && ++ cmp_component(&var->red, &color->red) && ++ cmp_component(&var->green, &color->green) && ++ cmp_component(&var->blue, &color->blue) && ++ cmp_component(&var->transp, &color->transp); ++} ++ ++static void assign_colormode_to_var(struct fb_var_screeninfo *var, ++ struct omapfb_colormode *color) ++{ ++ var->bits_per_pixel = color->bits_per_pixel; ++ var->nonstd = color->nonstd; ++ var->red = color->red; ++ var->green = color->green; ++ var->blue = color->blue; ++ var->transp = color->transp; ++} ++ ++static enum omap_color_mode fb_mode_to_dss_mode(struct fb_var_screeninfo *var) ++{ ++ enum omap_color_mode dssmode; ++ int i; ++ ++ /* first match with nonstd field */ ++ if (var->nonstd) { ++ for (i = 0; i < ARRAY_SIZE(omapfb_colormodes); ++i) { ++ struct omapfb_colormode *mode = &omapfb_colormodes[i]; ++ if (var->nonstd == mode->nonstd) { ++ assign_colormode_to_var(var, mode); ++ return mode->dssmode; ++ } ++ } ++ ++ return -EINVAL; ++ } ++ ++ /* then try exact match of bpp and colors */ ++ for (i = 0; i < ARRAY_SIZE(omapfb_colormodes); ++i) { ++ struct omapfb_colormode *mode = &omapfb_colormodes[i]; ++ if (cmp_var_to_colormode(var, mode)) { ++ assign_colormode_to_var(var, mode); ++ return mode->dssmode; ++ } ++ } ++ ++ /* match with bpp if user has not filled color fields ++ * properly */ ++ switch (var->bits_per_pixel) { ++ case 1: ++ dssmode = OMAP_DSS_COLOR_CLUT1; ++ break; ++ case 2: ++ dssmode = OMAP_DSS_COLOR_CLUT2; ++ break; ++ case 4: ++ dssmode = OMAP_DSS_COLOR_CLUT4; ++ break; ++ case 8: ++ dssmode = OMAP_DSS_COLOR_CLUT8; ++ break; ++ case 12: ++ dssmode = OMAP_DSS_COLOR_RGB12U; ++ break; ++ case 16: ++ dssmode = OMAP_DSS_COLOR_RGB16; ++ break; ++ case 24: ++ dssmode = OMAP_DSS_COLOR_RGB24P; ++ break; ++ case 32: ++ dssmode = OMAP_DSS_COLOR_RGB24U; ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ for (i = 0; i < ARRAY_SIZE(omapfb_colormodes); ++i) { ++ struct omapfb_colormode *mode = &omapfb_colormodes[i]; ++ if (dssmode == mode->dssmode) { ++ assign_colormode_to_var(var, mode); ++ return mode->dssmode; ++ } ++ } ++ ++ return -EINVAL; ++} ++ ++int dss_mode_to_fb_mode(enum omap_color_mode dssmode, ++ struct fb_var_screeninfo *var) ++{ ++ int i; ++ ++ for (i = 0; i < ARRAY_SIZE(omapfb_colormodes); ++i) { ++ struct omapfb_colormode *mode = &omapfb_colormodes[i]; ++ if (dssmode == mode->dssmode) { ++ assign_colormode_to_var(var, mode); ++ return 0; ++ } ++ } ++ return -ENOENT; ++} ++ ++void set_fb_fix(struct fb_info *fbi) ++{ ++ struct fb_fix_screeninfo *fix = &fbi->fix; ++ struct fb_var_screeninfo *var = &fbi->var; ++ struct omapfb_info *ofbi = FB2OFB(fbi); ++ struct omapfb2_mem_region *rg = &ofbi->region; ++ ++ DBG("set_fb_fix\n"); ++ ++ /* used by open/write in fbmem.c */ ++ fbi->screen_base = (char __iomem *)omapfb_get_region_vaddr(ofbi); ++ ++ DBG("changing rotation to %d\n", var->rotate); ++ ++ /* used by mmap in fbmem.c */ ++ if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) { ++ switch (var->nonstd) { ++ case OMAPFB_COLOR_YUV422: ++ case OMAPFB_COLOR_YUY422: ++ fix->line_length = ++ (OMAP_VRFB_LINE_LEN * var->bits_per_pixel) >> 2; ++ break; ++ default: ++ fix->line_length = ++ (OMAP_VRFB_LINE_LEN * var->bits_per_pixel) >> 3; ++ break; ++ } ++ } else ++ fix->line_length = ++ (var->xres_virtual * var->bits_per_pixel) >> 3; ++ fix->smem_start = omapfb_get_region_paddr(ofbi); ++ fix->smem_len = rg->size; ++ ++ fix->type = FB_TYPE_PACKED_PIXELS; ++ ++ if (var->nonstd) ++ fix->visual = FB_VISUAL_PSEUDOCOLOR; ++ else { ++ switch (var->bits_per_pixel) { ++ case 32: ++ case 24: ++ case 16: ++ case 12: ++ fix->visual = FB_VISUAL_TRUECOLOR; ++ /* 12bpp is stored in 16 bits */ ++ break; ++ case 1: ++ case 2: ++ case 4: ++ case 8: ++ fix->visual = FB_VISUAL_PSEUDOCOLOR; ++ break; ++ } ++ } ++ ++ fix->accel = FB_ACCEL_NONE; ++ ++ fix->xpanstep = 1; ++ fix->ypanstep = 1; ++ ++ if (rg->size && ofbi->rotation_type == OMAP_DSS_ROT_VRFB) { ++ unsigned bytespp; ++ bool yuv_mode; ++ enum omap_color_mode mode; ++ ++ mode = fb_mode_to_dss_mode(var); ++ ++ bytespp = var->bits_per_pixel >> 3; ++ ++ if (mode == OMAP_DSS_COLOR_YUV2 || mode == OMAP_DSS_COLOR_UYVY) ++ yuv_mode = true; ++ else ++ yuv_mode = false; ++ ++ omap_vrfb_setup(&rg->vrfb, rg->paddr, ++ var->xres_virtual, ++ var->yres_virtual, ++ bytespp, yuv_mode); ++ } ++} ++ ++/* check new var and possibly modify it to be ok */ ++int check_fb_var(struct fb_info *fbi, struct fb_var_screeninfo *var) ++{ ++ struct omapfb_info *ofbi = FB2OFB(fbi); ++ struct omap_dss_device *display = fb2display(fbi); ++ unsigned long max_frame_size; ++ unsigned long line_size; ++ int xres_min, yres_min; ++ int xres_max, yres_max; ++ enum omap_color_mode mode = 0; ++ int i; ++ int bytespp; ++ ++ DBG("check_fb_var %d\n", ofbi->id); ++ ++ if (ofbi->region.size == 0) ++ return 0; ++ ++ mode = fb_mode_to_dss_mode(var); ++ if (mode < 0) { ++ DBG("cannot convert var to omap dss mode\n"); ++ return -EINVAL; ++ } ++ ++ for (i = 0; i < ofbi->num_overlays; ++i) { ++ if ((ofbi->overlays[i]->supported_modes & mode) == 0) { ++ DBG("invalid mode\n"); ++ return -EINVAL; ++ } ++ } ++ ++ if (var->rotate < 0 || var->rotate > 3) ++ return -EINVAL; ++ ++ xres_min = OMAPFB_PLANE_XRES_MIN; ++ xres_max = 2048; ++ yres_min = OMAPFB_PLANE_YRES_MIN; ++ yres_max = 2048; ++ ++ bytespp = var->bits_per_pixel >> 3; ++ ++ /* XXX: some applications seem to set virtual res to 0. */ ++ if (var->xres_virtual == 0) ++ var->xres_virtual = var->xres; ++ ++ if (var->yres_virtual == 0) ++ var->yres_virtual = var->yres; ++ ++ if (var->xres_virtual < xres_min || var->yres_virtual < yres_min) ++ return -EINVAL; ++ ++ if (var->xres < xres_min) ++ var->xres = xres_min; ++ if (var->yres < yres_min) ++ var->yres = yres_min; ++ if (var->xres > xres_max) ++ var->xres = xres_max; ++ if (var->yres > yres_max) ++ var->yres = yres_max; ++ ++ if (var->xres > var->xres_virtual) ++ var->xres = var->xres_virtual; ++ if (var->yres > var->yres_virtual) ++ var->yres = var->yres_virtual; ++ ++ if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) ++ line_size = OMAP_VRFB_LINE_LEN * bytespp; ++ else ++ line_size = var->xres_virtual * bytespp; ++ ++ max_frame_size = ofbi->region.size; ++ ++ DBG("max frame size %lu, line size %lu\n", max_frame_size, line_size); ++ ++ if (line_size * var->yres_virtual > max_frame_size) { ++ DBG("can't fit FB into memory, reducing y\n"); ++ var->yres_virtual = max_frame_size / line_size; ++ ++ if (var->yres_virtual < yres_min) ++ var->yres_virtual = yres_min; ++ ++ if (var->yres > var->yres_virtual) ++ var->yres = var->yres_virtual; ++ } ++ ++ if (line_size * var->yres_virtual > max_frame_size) { ++ DBG("can't fit FB into memory, reducing x\n"); ++ if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) ++ return -EINVAL; ++ ++ var->xres_virtual = max_frame_size / var->yres_virtual / ++ bytespp; ++ ++ if (var->xres_virtual < xres_min) ++ var->xres_virtual = xres_min; ++ ++ if (var->xres > var->xres_virtual) ++ var->xres = var->xres_virtual; ++ ++ line_size = var->xres_virtual * bytespp; ++ } ++ ++ if (line_size * var->yres_virtual > max_frame_size) { ++ DBG("cannot fit FB to memory\n"); ++ return -EINVAL; ++ } ++ ++ if (var->xres + var->xoffset > var->xres_virtual) ++ var->xoffset = var->xres_virtual - var->xres; ++ if (var->yres + var->yoffset > var->yres_virtual) ++ var->yoffset = var->yres_virtual - var->yres; ++ ++ DBG("xres = %d, yres = %d, vxres = %d, vyres = %d\n", ++ var->xres, var->yres, ++ var->xres_virtual, var->yres_virtual); ++ ++ var->height = -1; ++ var->width = -1; ++ var->grayscale = 0; ++ ++ if (display && display->get_timings) { ++ struct omap_video_timings timings; ++ display->get_timings(display, &timings); ++ ++ /* pixclock in ps, the rest in pixclock */ ++ var->pixclock = timings.pixel_clock != 0 ? ++ KHZ2PICOS(timings.pixel_clock) : ++ 0; ++ var->left_margin = timings.hfp; ++ var->right_margin = timings.hbp; ++ var->upper_margin = timings.vfp; ++ var->lower_margin = timings.vbp; ++ var->hsync_len = timings.hsw; ++ var->vsync_len = timings.vsw; ++ } else { ++ var->pixclock = 0; ++ var->left_margin = 0; ++ var->right_margin = 0; ++ var->upper_margin = 0; ++ var->lower_margin = 0; ++ var->hsync_len = 0; ++ var->vsync_len = 0; ++ } ++ ++ /* TODO: get these from panel->config */ ++ var->vmode = FB_VMODE_NONINTERLACED; ++ var->sync = 0; ++ ++ return 0; ++} ++ ++/* ++ * --------------------------------------------------------------------------- ++ * fbdev framework callbacks ++ * --------------------------------------------------------------------------- ++ */ ++static int omapfb_open(struct fb_info *fbi, int user) ++{ ++ return 0; ++} ++ ++static int omapfb_release(struct fb_info *fbi, int user) ++{ ++#if 0 ++ struct omapfb_info *ofbi = FB2OFB(fbi); ++ struct omapfb2_device *fbdev = ofbi->fbdev; ++ struct omap_dss_device *display = fb2display(fbi); ++ ++ DBG("Closing fb with plane index %d\n", ofbi->id); ++ ++ omapfb_lock(fbdev); ++ ++ if (display && display->get_update_mode && display->update) { ++ /* XXX this update should be removed, I think. But it's ++ * good for debugging */ ++ if (display->get_update_mode(display) == ++ OMAP_DSS_UPDATE_MANUAL) { ++ u16 w, h; ++ ++ if (display->sync) ++ display->sync(display); ++ ++ display->get_resolution(display, &w, &h); ++ display->update(display, 0, 0, w, h); ++ } ++ } ++ ++ if (display && display->sync) ++ display->sync(display); ++ ++ omapfb_unlock(fbdev); ++#endif ++ return 0; ++} ++ ++/* setup overlay according to the fb */ ++static int omapfb_setup_overlay(struct fb_info *fbi, struct omap_overlay *ovl, ++ u16 posx, u16 posy, u16 outw, u16 outh) ++{ ++ int r = 0; ++ struct omapfb_info *ofbi = FB2OFB(fbi); ++ struct fb_var_screeninfo *var = &fbi->var; ++ struct fb_fix_screeninfo *fix = &fbi->fix; ++ enum omap_color_mode mode = 0; ++ int offset; ++ u32 data_start_p; ++ void __iomem *data_start_v; ++ struct omap_overlay_info info; ++ int xres, yres; ++ int screen_width; ++ int mirror; ++ int rotation = var->rotate; ++ int i; ++ ++ for (i = 0; i < ofbi->num_overlays; i++) { ++ if (ovl != ofbi->overlays[i]) ++ continue; ++ ++ rotation = (rotation + ofbi->rotation[i]) % 4; ++ break; ++ } ++ ++ DBG("setup_overlay %d, posx %d, posy %d, outw %d, outh %d\n", ofbi->id, ++ posx, posy, outw, outh); ++ ++ if (rotation == FB_ROTATE_CW || rotation == FB_ROTATE_CCW) { ++ xres = var->yres; ++ yres = var->xres; ++ } else { ++ xres = var->xres; ++ yres = var->yres; ++ } ++ ++ offset = ((var->yoffset * var->xres_virtual + ++ var->xoffset) * var->bits_per_pixel) >> 3; ++ ++ if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) { ++ data_start_p = omapfb_get_region_rot_paddr(ofbi, rotation); ++ data_start_v = NULL; ++ } else { ++ data_start_p = omapfb_get_region_paddr(ofbi); ++ data_start_v = omapfb_get_region_vaddr(ofbi); ++ } ++ ++ data_start_p += offset; ++ data_start_v += offset; ++ ++ mode = fb_mode_to_dss_mode(var); ++ ++ if (mode == -EINVAL) { ++ DBG("fb_mode_to_dss_mode failed"); ++ r = -EINVAL; ++ goto err; ++ } ++ ++ switch (var->nonstd) { ++ case OMAPFB_COLOR_YUV422: ++ case OMAPFB_COLOR_YUY422: ++ if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) { ++ screen_width = fix->line_length ++ / (var->bits_per_pixel >> 2); ++ break; ++ } ++ default: ++ screen_width = fix->line_length / (var->bits_per_pixel >> 3); ++ break; ++ } ++ ++ ovl->get_overlay_info(ovl, &info); ++ ++ if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) ++ mirror = 0; ++ else ++ mirror = ofbi->mirror; ++ ++ info.paddr = data_start_p; ++ info.vaddr = data_start_v; ++ info.screen_width = screen_width; ++ info.width = xres; ++ info.height = yres; ++ info.color_mode = mode; ++ info.rotation_type = ofbi->rotation_type; ++ info.rotation = rotation; ++ info.mirror = mirror; ++ ++ info.pos_x = posx; ++ info.pos_y = posy; ++ info.out_width = outw; ++ info.out_height = outh; ++ ++ r = ovl->set_overlay_info(ovl, &info); ++ if (r) { ++ DBG("ovl->setup_overlay_info failed\n"); ++ goto err; ++ } ++ ++ return 0; ++ ++err: ++ DBG("setup_overlay failed\n"); ++ return r; ++} ++ ++/* apply var to the overlay */ ++int omapfb_apply_changes(struct fb_info *fbi, int init) ++{ ++ int r = 0; ++ struct omapfb_info *ofbi = FB2OFB(fbi); ++ struct fb_var_screeninfo *var = &fbi->var; ++ struct omap_overlay *ovl; ++ u16 posx, posy; ++ u16 outw, outh; ++ int i; ++ ++#ifdef DEBUG ++ if (omapfb_test_pattern) ++ fill_fb(fbi); ++#endif ++ ++ for (i = 0; i < ofbi->num_overlays; i++) { ++ ovl = ofbi->overlays[i]; ++ ++ DBG("apply_changes, fb %d, ovl %d\n", ofbi->id, ovl->id); ++ ++ if (ofbi->region.size == 0) { ++ /* the fb is not available. disable the overlay */ ++ omapfb_overlay_enable(ovl, 0); ++ if (!init && ovl->manager) ++ ovl->manager->apply(ovl->manager); ++ continue; ++ } ++ ++ if (init || (ovl->caps & OMAP_DSS_OVL_CAP_SCALE) == 0) { ++ int rotation = (var->rotate + ofbi->rotation[i]) % 4; ++ if (rotation == FB_ROTATE_CW || ++ rotation == FB_ROTATE_CCW) { ++ outw = var->yres; ++ outh = var->xres; ++ } else { ++ outw = var->xres; ++ outh = var->yres; ++ } ++ } else { ++ outw = ovl->info.out_width; ++ outh = ovl->info.out_height; ++ } ++ ++ if (init) { ++ posx = 0; ++ posy = 0; ++ } else { ++ posx = ovl->info.pos_x; ++ posy = ovl->info.pos_y; ++ } ++ ++ r = omapfb_setup_overlay(fbi, ovl, posx, posy, outw, outh); ++ if (r) ++ goto err; ++ ++ if (!init && ovl->manager) ++ ovl->manager->apply(ovl->manager); ++ } ++ return 0; ++err: ++ DBG("apply_changes failed\n"); ++ return r; ++} ++ ++/* checks var and eventually tweaks it to something supported, ++ * DO NOT MODIFY PAR */ ++static int omapfb_check_var(struct fb_var_screeninfo *var, struct fb_info *fbi) ++{ ++ int r; ++ ++ DBG("check_var(%d)\n", FB2OFB(fbi)->id); ++ ++ r = check_fb_var(fbi, var); ++ ++ return r; ++} ++ ++/* set the video mode according to info->var */ ++static int omapfb_set_par(struct fb_info *fbi) ++{ ++ int r; ++ ++ DBG("set_par(%d)\n", FB2OFB(fbi)->id); ++ ++ set_fb_fix(fbi); ++ r = omapfb_apply_changes(fbi, 0); ++ ++ return r; ++} ++ ++static int omapfb_pan_display(struct fb_var_screeninfo *var, ++ struct fb_info *fbi) ++{ ++ struct omapfb_info *ofbi = FB2OFB(fbi); ++ int r = 0; ++ ++ DBG("pan_display(%d)\n", ofbi->id); ++ ++ if (var->xoffset != fbi->var.xoffset || ++ var->yoffset != fbi->var.yoffset) { ++ struct fb_var_screeninfo new_var; ++ ++ new_var = fbi->var; ++ new_var.xoffset = var->xoffset; ++ new_var.yoffset = var->yoffset; ++ ++ r = check_fb_var(fbi, &new_var); ++ ++ if (r == 0) { ++ fbi->var = new_var; ++ set_fb_fix(fbi); ++ r = omapfb_apply_changes(fbi, 0); ++ } ++ } ++ ++ return r; ++} ++ ++static void mmap_user_open(struct vm_area_struct *vma) ++{ ++ struct omapfb_info *ofbi = (struct omapfb_info *)vma->vm_private_data; ++ ++ atomic_inc(&ofbi->map_count); ++} ++ ++static void mmap_user_close(struct vm_area_struct *vma) ++{ ++ struct omapfb_info *ofbi = (struct omapfb_info *)vma->vm_private_data; ++ ++ atomic_dec(&ofbi->map_count); ++} ++ ++static struct vm_operations_struct mmap_user_ops = { ++ .open = mmap_user_open, ++ .close = mmap_user_close, ++}; ++ ++static int omapfb_mmap(struct fb_info *fbi, struct vm_area_struct *vma) ++{ ++ struct omapfb_info *ofbi = FB2OFB(fbi); ++ struct fb_fix_screeninfo *fix = &fbi->fix; ++ unsigned long off; ++ unsigned long start; ++ u32 len; ++ ++ if (vma->vm_end - vma->vm_start == 0) ++ return 0; ++ if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT)) ++ return -EINVAL; ++ off = vma->vm_pgoff << PAGE_SHIFT; ++ ++ start = omapfb_get_region_paddr(ofbi); ++ len = fix->smem_len; ++ if (off >= len) ++ return -EINVAL; ++ if ((vma->vm_end - vma->vm_start + off) > len) ++ return -EINVAL; ++ ++ off += start; ++ ++ DBG("user mmap region start %lx, len %d, off %lx\n", start, len, off); ++ ++ vma->vm_pgoff = off >> PAGE_SHIFT; ++ vma->vm_flags |= VM_IO | VM_RESERVED; ++ vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot); ++ vma->vm_ops = &mmap_user_ops; ++ vma->vm_private_data = ofbi; ++ if (io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT, ++ vma->vm_end - vma->vm_start, vma->vm_page_prot)) ++ return -EAGAIN; ++ /* vm_ops.open won't be called for mmap itself. */ ++ atomic_inc(&ofbi->map_count); ++ return 0; ++} ++ ++/* Store a single color palette entry into a pseudo palette or the hardware ++ * palette if one is available. For now we support only 16bpp and thus store ++ * the entry only to the pseudo palette. ++ */ ++static int _setcolreg(struct fb_info *fbi, u_int regno, u_int red, u_int green, ++ u_int blue, u_int transp, int update_hw_pal) ++{ ++ /*struct omapfb_info *ofbi = FB2OFB(fbi);*/ ++ /*struct omapfb2_device *fbdev = ofbi->fbdev;*/ ++ struct fb_var_screeninfo *var = &fbi->var; ++ int r = 0; ++ ++ enum omapfb_color_format mode = OMAPFB_COLOR_RGB24U; /* XXX */ ++ ++ /*switch (plane->color_mode) {*/ ++ switch (mode) { ++ case OMAPFB_COLOR_YUV422: ++ case OMAPFB_COLOR_YUV420: ++ case OMAPFB_COLOR_YUY422: ++ r = -EINVAL; ++ break; ++ case OMAPFB_COLOR_CLUT_8BPP: ++ case OMAPFB_COLOR_CLUT_4BPP: ++ case OMAPFB_COLOR_CLUT_2BPP: ++ case OMAPFB_COLOR_CLUT_1BPP: ++ /* ++ if (fbdev->ctrl->setcolreg) ++ r = fbdev->ctrl->setcolreg(regno, red, green, blue, ++ transp, update_hw_pal); ++ */ ++ /* Fallthrough */ ++ r = -EINVAL; ++ break; ++ case OMAPFB_COLOR_RGB565: ++ case OMAPFB_COLOR_RGB444: ++ case OMAPFB_COLOR_RGB24P: ++ case OMAPFB_COLOR_RGB24U: ++ if (r != 0) ++ break; ++ ++ if (regno < 0) { ++ r = -EINVAL; ++ break; ++ } ++ ++ if (regno < 16) { ++ u16 pal; ++ pal = ((red >> (16 - var->red.length)) << ++ var->red.offset) | ++ ((green >> (16 - var->green.length)) << ++ var->green.offset) | ++ (blue >> (16 - var->blue.length)); ++ ((u32 *)(fbi->pseudo_palette))[regno] = pal; ++ } ++ break; ++ default: ++ BUG(); ++ } ++ return r; ++} ++ ++static int omapfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, ++ u_int transp, struct fb_info *info) ++{ ++ DBG("setcolreg\n"); ++ ++ return _setcolreg(info, regno, red, green, blue, transp, 1); ++} ++ ++static int omapfb_setcmap(struct fb_cmap *cmap, struct fb_info *info) ++{ ++ int count, index, r; ++ u16 *red, *green, *blue, *transp; ++ u16 trans = 0xffff; ++ ++ DBG("setcmap\n"); ++ ++ red = cmap->red; ++ green = cmap->green; ++ blue = cmap->blue; ++ transp = cmap->transp; ++ index = cmap->start; ++ ++ for (count = 0; count < cmap->len; count++) { ++ if (transp) ++ trans = *transp++; ++ r = _setcolreg(info, index++, *red++, *green++, *blue++, trans, ++ count == cmap->len - 1); ++ if (r != 0) ++ return r; ++ } ++ ++ return 0; ++} ++ ++static void omapfb_vrfb_suspend_all(struct omapfb2_device *fbdev) ++{ ++ int i; ++ ++ for (i = 0; i < fbdev->num_fbs; i++) { ++ struct omapfb_info *ofbi = FB2OFB(fbdev->fbs[i]); ++ ++ if (ofbi->region.vrfb.vaddr[0]) ++ omap_vrfb_suspend_ctx(&ofbi->region.vrfb); ++ } ++} ++ ++static void omapfb_vrfb_resume_all(struct omapfb2_device *fbdev) ++{ ++ int i; ++ ++ for (i = 0; i < fbdev->num_fbs; i++) { ++ struct omapfb_info *ofbi = FB2OFB(fbdev->fbs[i]); ++ ++ if (ofbi->region.vrfb.vaddr[0]) ++ omap_vrfb_resume_ctx(&ofbi->region.vrfb); ++ } ++} ++ ++static int omapfb_blank(int blank, struct fb_info *fbi) ++{ ++ struct omapfb_info *ofbi = FB2OFB(fbi); ++ struct omapfb2_device *fbdev = ofbi->fbdev; ++ struct omap_dss_device *display = fb2display(fbi); ++ int do_update = 0; ++ int r = 0; ++ ++ omapfb_lock(fbdev); ++ ++ switch (blank) { ++ case FB_BLANK_UNBLANK: ++ if (display->state != OMAP_DSS_DISPLAY_SUSPENDED) ++ goto exit; ++ ++ omapfb_vrfb_resume_all(fbdev); ++ ++ if (display->resume) ++ r = display->resume(display); ++ ++ if (r == 0 && display->get_update_mode && ++ display->get_update_mode(display) == ++ OMAP_DSS_UPDATE_MANUAL) ++ do_update = 1; ++ ++ break; ++ ++ case FB_BLANK_NORMAL: ++ /* FB_BLANK_NORMAL could be implemented. ++ * Needs DSS additions. */ ++ case FB_BLANK_VSYNC_SUSPEND: ++ case FB_BLANK_HSYNC_SUSPEND: ++ case FB_BLANK_POWERDOWN: ++ if (display->state != OMAP_DSS_DISPLAY_ACTIVE) ++ goto exit; ++ ++ if (display->suspend) ++ r = display->suspend(display); ++ ++ omapfb_vrfb_suspend_all(fbdev); ++ ++ break; ++ ++ default: ++ r = -EINVAL; ++ } ++ ++exit: ++ omapfb_unlock(fbdev); ++ ++ if (r == 0 && do_update && display->update) { ++ u16 w, h; ++ display->get_resolution(display, &w, &h); ++ ++ r = display->update(display, 0, 0, w, h); ++ } ++ ++ return r; ++} ++ ++#if 0 ++/* XXX fb_read and fb_write are needed for VRFB */ ++ssize_t omapfb_write(struct fb_info *info, const char __user *buf, ++ size_t count, loff_t *ppos) ++{ ++ DBG("omapfb_write %d, %lu\n", count, (unsigned long)*ppos); ++ /* XXX needed for VRFB */ ++ return count; ++} ++#endif ++ ++static struct fb_ops omapfb_ops = { ++ .owner = THIS_MODULE, ++ .fb_open = omapfb_open, ++ .fb_release = omapfb_release, ++ .fb_fillrect = cfb_fillrect, ++ .fb_copyarea = cfb_copyarea, ++ .fb_imageblit = cfb_imageblit, ++ .fb_blank = omapfb_blank, ++ .fb_ioctl = omapfb_ioctl, ++ .fb_check_var = omapfb_check_var, ++ .fb_set_par = omapfb_set_par, ++ .fb_pan_display = omapfb_pan_display, ++ .fb_mmap = omapfb_mmap, ++ .fb_setcolreg = omapfb_setcolreg, ++ .fb_setcmap = omapfb_setcmap, ++ /*.fb_write = omapfb_write,*/ ++}; ++ ++static void omapfb_free_fbmem(struct fb_info *fbi) ++{ ++ struct omapfb_info *ofbi = FB2OFB(fbi); ++ struct omapfb2_device *fbdev = ofbi->fbdev; ++ struct omapfb2_mem_region *rg; ++ ++ rg = &ofbi->region; ++ ++ if (rg->paddr) ++ if (omap_vram_free(rg->paddr, rg->size)) ++ dev_err(fbdev->dev, "VRAM FREE failed\n"); ++ ++ if (rg->vaddr) ++ iounmap(rg->vaddr); ++ ++ if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) { ++ /* unmap the 0 angle rotation */ ++ if (rg->vrfb.vaddr[0]) { ++ iounmap(rg->vrfb.vaddr[0]); ++ omap_vrfb_release_ctx(&rg->vrfb); ++ } ++ } ++ ++ rg->vaddr = NULL; ++ rg->paddr = 0; ++ rg->alloc = 0; ++ rg->size = 0; ++} ++ ++static void clear_fb_info(struct fb_info *fbi) ++{ ++ memset(&fbi->var, 0, sizeof(fbi->var)); ++ memset(&fbi->fix, 0, sizeof(fbi->fix)); ++ strlcpy(fbi->fix.id, MODULE_NAME, sizeof(fbi->fix.id)); ++} ++ ++static int omapfb_free_all_fbmem(struct omapfb2_device *fbdev) ++{ ++ int i; ++ ++ DBG("free all fbmem\n"); ++ ++ for (i = 0; i < fbdev->num_fbs; i++) { ++ struct fb_info *fbi = fbdev->fbs[i]; ++ omapfb_free_fbmem(fbi); ++ clear_fb_info(fbi); ++ } ++ ++ return 0; ++} ++ ++static int omapfb_alloc_fbmem(struct fb_info *fbi, unsigned long size, ++ unsigned long paddr) ++{ ++ struct omapfb_info *ofbi = FB2OFB(fbi); ++ struct omapfb2_device *fbdev = ofbi->fbdev; ++ struct omapfb2_mem_region *rg; ++ void __iomem *vaddr; ++ int r; ++ ++ rg = &ofbi->region; ++ memset(rg, 0, sizeof(*rg)); ++ ++ size = PAGE_ALIGN(size); ++ ++ if (!paddr) { ++ DBG("allocating %lu bytes for fb %d\n", size, ofbi->id); ++ r = omap_vram_alloc(OMAP_VRAM_MEMTYPE_SDRAM, size, &paddr); ++ } else { ++ DBG("reserving %lu bytes at %lx for fb %d\n", size, paddr, ++ ofbi->id); ++ r = omap_vram_reserve(paddr, size); ++ } ++ ++ if (r) { ++ dev_err(fbdev->dev, "failed to allocate framebuffer\n"); ++ return -ENOMEM; ++ } ++ ++ if (ofbi->rotation_type != OMAP_DSS_ROT_VRFB) { ++ vaddr = ioremap_wc(paddr, size); ++ ++ if (!vaddr) { ++ dev_err(fbdev->dev, "failed to ioremap framebuffer\n"); ++ omap_vram_free(paddr, size); ++ return -ENOMEM; ++ } ++ ++ DBG("allocated VRAM paddr %lx, vaddr %p\n", paddr, vaddr); ++ } else { ++ void __iomem *va; ++ ++ r = omap_vrfb_request_ctx(&rg->vrfb); ++ if (r) { ++ dev_err(fbdev->dev, "vrfb create ctx failed\n"); ++ return r; ++ } ++ ++ /* only ioremap the 0 angle view */ ++ va = ioremap_wc(rg->vrfb.paddr[0], size); ++ ++ if (!va) { ++ printk(KERN_ERR "vrfb: ioremap failed\n"); ++ omap_vrfb_release_ctx(&rg->vrfb); ++ return -ENOMEM; ++ } ++ ++ DBG("ioremapped vrfb area 0 to %p\n", va); ++ ++ rg->vrfb.vaddr[0] = va; ++ ++ vaddr = NULL; ++ } ++ ++ rg->paddr = paddr; ++ rg->vaddr = vaddr; ++ rg->size = size; ++ rg->alloc = 1; ++ ++ return 0; ++} ++ ++/* allocate fbmem using display resolution as reference */ ++static int omapfb_alloc_fbmem_display(struct fb_info *fbi, unsigned long size, ++ unsigned long paddr) ++{ ++ struct omapfb_info *ofbi = FB2OFB(fbi); ++ struct omap_dss_device *display; ++ int bytespp; ++ ++ display = fb2display(fbi); ++ ++ if (!display) ++ return 0; ++ ++ switch (display->get_recommended_bpp(display)) { ++ case 16: ++ bytespp = 2; ++ break; ++ case 24: ++ bytespp = 4; ++ break; ++ default: ++ bytespp = 4; ++ break; ++ } ++ ++ if (!size) { ++ u16 w, h; ++ ++ display->get_resolution(display, &w, &h); ++ ++ if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) { ++#ifdef DEBUG ++ int oldw = w, oldh = h; ++#endif ++ ++ omap_vrfb_adjust_size(&w, &h, bytespp); ++ ++ /* Because we change the resolution of the 0 degree ++ * view, we need to alloc max(w, h) for height */ ++ h = max(w, h); ++ w = OMAP_VRFB_LINE_LEN; ++ ++ DBG("adjusting fb mem size for VRFB, %dx%d -> %dx%d\n", ++ oldw, oldh, w, h); ++ } ++ ++ size = w * h * bytespp; ++ } ++ ++ if (!size) ++ return 0; ++ ++ return omapfb_alloc_fbmem(fbi, size, paddr); ++} ++ ++static enum omap_color_mode fb_format_to_dss_mode(enum omapfb_color_format fmt) ++{ ++ enum omap_color_mode mode; ++ ++ switch (fmt) { ++ case OMAPFB_COLOR_RGB565: ++ mode = OMAP_DSS_COLOR_RGB16; ++ break; ++ case OMAPFB_COLOR_YUV422: ++ mode = OMAP_DSS_COLOR_YUV2; ++ break; ++ case OMAPFB_COLOR_CLUT_8BPP: ++ mode = OMAP_DSS_COLOR_CLUT8; ++ break; ++ case OMAPFB_COLOR_CLUT_4BPP: ++ mode = OMAP_DSS_COLOR_CLUT4; ++ break; ++ case OMAPFB_COLOR_CLUT_2BPP: ++ mode = OMAP_DSS_COLOR_CLUT2; ++ break; ++ case OMAPFB_COLOR_CLUT_1BPP: ++ mode = OMAP_DSS_COLOR_CLUT1; ++ break; ++ case OMAPFB_COLOR_RGB444: ++ mode = OMAP_DSS_COLOR_RGB12U; ++ break; ++ case OMAPFB_COLOR_YUY422: ++ mode = OMAP_DSS_COLOR_UYVY; ++ break; ++ case OMAPFB_COLOR_ARGB16: ++ mode = OMAP_DSS_COLOR_ARGB16; ++ break; ++ case OMAPFB_COLOR_RGB24U: ++ mode = OMAP_DSS_COLOR_RGB24U; ++ break; ++ case OMAPFB_COLOR_RGB24P: ++ mode = OMAP_DSS_COLOR_RGB24P; ++ break; ++ case OMAPFB_COLOR_ARGB32: ++ mode = OMAP_DSS_COLOR_ARGB32; ++ break; ++ case OMAPFB_COLOR_RGBA32: ++ mode = OMAP_DSS_COLOR_RGBA32; ++ break; ++ case OMAPFB_COLOR_RGBX32: ++ mode = OMAP_DSS_COLOR_RGBX32; ++ break; ++ default: ++ mode = -EINVAL; ++ } ++ ++ return mode; ++} ++ ++static int omapfb_parse_vram_param(const char *param, int max_entries, ++ unsigned long *sizes, unsigned long *paddrs) ++{ ++ int fbnum; ++ unsigned long size; ++ unsigned long paddr = 0; ++ char *p, *start; ++ ++ start = (char *)param; ++ ++ while (1) { ++ p = start; ++ ++ fbnum = simple_strtoul(p, &p, 10); ++ ++ if (p == param) ++ return -EINVAL; ++ ++ if (*p != ':') ++ return -EINVAL; ++ ++ if (fbnum >= max_entries) ++ return -EINVAL; ++ ++ size = memparse(p + 1, &p); ++ ++ if (!size) ++ return -EINVAL; ++ ++ paddr = 0; ++ ++ if (*p == '@') { ++ paddr = simple_strtoul(p + 1, &p, 16); ++ ++ if (!paddr) ++ return -EINVAL; ++ ++ } ++ ++ paddrs[fbnum] = paddr; ++ sizes[fbnum] = size; ++ ++ if (*p == 0) ++ break; ++ ++ if (*p != ',') ++ return -EINVAL; ++ ++ ++p; ++ ++ start = p; ++ } ++ ++ return 0; ++} ++ ++static int omapfb_allocate_all_fbs(struct omapfb2_device *fbdev) ++{ ++ int i, r; ++ unsigned long vram_sizes[10]; ++ unsigned long vram_paddrs[10]; ++ ++ memset(&vram_sizes, 0, sizeof(vram_sizes)); ++ memset(&vram_paddrs, 0, sizeof(vram_paddrs)); ++ ++ if (def_vram && omapfb_parse_vram_param(def_vram, 10, ++ vram_sizes, vram_paddrs)) { ++ dev_err(fbdev->dev, "failed to parse vram parameter\n"); ++ ++ memset(&vram_sizes, 0, sizeof(vram_sizes)); ++ memset(&vram_paddrs, 0, sizeof(vram_paddrs)); ++ } ++ ++ if (fbdev->dev->platform_data) { ++ struct omapfb_platform_data *opd; ++ opd = fbdev->dev->platform_data; ++ for (i = 0; i < opd->mem_desc.region_cnt; ++i) { ++ if (!vram_sizes[i]) { ++ unsigned long size; ++ unsigned long paddr; ++ ++ size = opd->mem_desc.region[i].size; ++ paddr = opd->mem_desc.region[i].paddr; ++ ++ vram_sizes[i] = size; ++ vram_paddrs[i] = paddr; ++ } ++ } ++ } ++ ++ for (i = 0; i < fbdev->num_fbs; i++) { ++ /* allocate memory automatically only for fb0, or if ++ * excplicitly defined with vram or plat data option */ ++ if (i == 0 || vram_sizes[i] != 0) { ++ r = omapfb_alloc_fbmem_display(fbdev->fbs[i], ++ vram_sizes[i], vram_paddrs[i]); ++ ++ if (r) ++ return r; ++ } ++ } ++ ++ for (i = 0; i < fbdev->num_fbs; i++) { ++ struct omapfb_info *ofbi = FB2OFB(fbdev->fbs[i]); ++ struct omapfb2_mem_region *rg; ++ rg = &ofbi->region; ++ ++ DBG("region%d phys %08x virt %p size=%lu\n", ++ i, ++ rg->paddr, ++ rg->vaddr, ++ rg->size); ++ } ++ ++ return 0; ++} ++ ++int omapfb_realloc_fbmem(struct fb_info *fbi, unsigned long size, int type) ++{ ++ struct omapfb_info *ofbi = FB2OFB(fbi); ++ struct omapfb2_device *fbdev = ofbi->fbdev; ++ struct omap_dss_device *display = fb2display(fbi); ++ struct omapfb2_mem_region *rg = &ofbi->region; ++ unsigned long old_size = rg->size; ++ unsigned long old_paddr = rg->paddr; ++ int old_type = rg->type; ++ int r; ++ ++ if (type > OMAPFB_MEMTYPE_MAX) ++ return -EINVAL; ++ ++ size = PAGE_ALIGN(size); ++ ++ if (old_size == size && old_type == type) ++ return 0; ++ ++ if (display && display->sync) ++ display->sync(display); ++ ++ omapfb_free_fbmem(fbi); ++ ++ if (size == 0) { ++ clear_fb_info(fbi); ++ return 0; ++ } ++ ++ r = omapfb_alloc_fbmem(fbi, size, 0); ++ ++ if (r) { ++ if (old_size) ++ omapfb_alloc_fbmem(fbi, old_size, old_paddr); ++ ++ if (rg->size == 0) ++ clear_fb_info(fbi); ++ ++ return r; ++ } ++ ++ if (old_size == size) ++ return 0; ++ ++ if (old_size == 0) { ++ DBG("initializing fb %d\n", ofbi->id); ++ r = omapfb_fb_init(fbdev, fbi); ++ if (r) { ++ DBG("omapfb_fb_init failed\n"); ++ goto err; ++ } ++ r = omapfb_apply_changes(fbi, 1); ++ if (r) { ++ DBG("omapfb_apply_changes failed\n"); ++ goto err; ++ } ++ } else { ++ struct fb_var_screeninfo new_var; ++ memcpy(&new_var, &fbi->var, sizeof(new_var)); ++ r = check_fb_var(fbi, &new_var); ++ if (r) ++ goto err; ++ memcpy(&fbi->var, &new_var, sizeof(fbi->var)); ++ set_fb_fix(fbi); ++ } ++ ++ return 0; ++err: ++ omapfb_free_fbmem(fbi); ++ clear_fb_info(fbi); ++ return r; ++} ++ ++/* initialize fb_info, var, fix to something sane based on the display */ ++static int omapfb_fb_init(struct omapfb2_device *fbdev, struct fb_info *fbi) ++{ ++ struct fb_var_screeninfo *var = &fbi->var; ++ struct omap_dss_device *display = fb2display(fbi); ++ struct omapfb_info *ofbi = FB2OFB(fbi); ++ int r = 0; ++ ++ fbi->fbops = &omapfb_ops; ++ fbi->flags = FBINFO_FLAG_DEFAULT; ++ fbi->pseudo_palette = fbdev->pseudo_palette; ++ ++ if (ofbi->region.size == 0) { ++ clear_fb_info(fbi); ++ return 0; ++ } ++ ++ var->nonstd = 0; ++ var->bits_per_pixel = 0; ++ ++ var->rotate = def_rotate; ++ ++ /* ++ * Check if there is a default color format set in the board file, ++ * and use this format instead the default deducted from the ++ * display bpp. ++ */ ++ if (fbdev->dev->platform_data) { ++ struct omapfb_platform_data *opd; ++ int id = ofbi->id; ++ ++ opd = fbdev->dev->platform_data; ++ if (opd->mem_desc.region[id].format_used) { ++ enum omap_color_mode mode; ++ enum omapfb_color_format format; ++ ++ format = opd->mem_desc.region[id].format; ++ mode = fb_format_to_dss_mode(format); ++ if (mode < 0) { ++ r = mode; ++ goto err; ++ } ++ r = dss_mode_to_fb_mode(mode, var); ++ if (r < 0) ++ goto err; ++ } ++ } ++ ++ if (display) { ++ u16 w, h; ++ int rotation = (var->rotate + ofbi->rotation[0]) % 4; ++ ++ display->get_resolution(display, &w, &h); ++ ++ if (rotation == FB_ROTATE_CW || ++ rotation == FB_ROTATE_CCW) { ++ var->xres = h; ++ var->yres = w; ++ } else { ++ var->xres = w; ++ var->yres = h; ++ } ++ ++ var->xres_virtual = var->xres; ++ var->yres_virtual = var->yres; ++ ++ if (!var->bits_per_pixel) { ++ switch (display->get_recommended_bpp(display)) { ++ case 16: ++ var->bits_per_pixel = 16; ++ break; ++ case 24: ++ var->bits_per_pixel = 32; ++ break; ++ default: ++ dev_err(fbdev->dev, "illegal display " ++ "bpp\n"); ++ return -EINVAL; ++ } ++ } ++ } else { ++ /* if there's no display, let's just guess some basic values */ ++ var->xres = 320; ++ var->yres = 240; ++ var->xres_virtual = var->xres; ++ var->yres_virtual = var->yres; ++ if (!var->bits_per_pixel) ++ var->bits_per_pixel = 16; ++ } ++ ++ r = check_fb_var(fbi, var); ++ if (r) ++ goto err; ++ ++ set_fb_fix(fbi); ++ ++ r = fb_alloc_cmap(&fbi->cmap, 256, 0); ++ if (r) ++ dev_err(fbdev->dev, "unable to allocate color map memory\n"); ++ ++err: ++ return r; ++} ++ ++static void fbinfo_cleanup(struct omapfb2_device *fbdev, struct fb_info *fbi) ++{ ++ fb_dealloc_cmap(&fbi->cmap); ++} ++ ++ ++static void omapfb_free_resources(struct omapfb2_device *fbdev) ++{ ++ int i; ++ ++ DBG("free_resources\n"); ++ ++ if (fbdev == NULL) ++ return; ++ ++ for (i = 0; i < fbdev->num_fbs; i++) ++ unregister_framebuffer(fbdev->fbs[i]); ++ ++ /* free the reserved fbmem */ ++ omapfb_free_all_fbmem(fbdev); ++ ++ for (i = 0; i < fbdev->num_fbs; i++) { ++ fbinfo_cleanup(fbdev, fbdev->fbs[i]); ++ framebuffer_release(fbdev->fbs[i]); ++ } ++ ++ for (i = 0; i < fbdev->num_displays; i++) { ++ if (fbdev->displays[i]->state != OMAP_DSS_DISPLAY_DISABLED) ++ fbdev->displays[i]->disable(fbdev->displays[i]); ++ ++ omap_dss_put_device(fbdev->displays[i]); ++ } ++ ++ dev_set_drvdata(fbdev->dev, NULL); ++ kfree(fbdev); ++} ++ ++static int omapfb_create_framebuffers(struct omapfb2_device *fbdev) ++{ ++ int r, i; ++ ++ fbdev->num_fbs = 0; ++ ++ DBG("create %d framebuffers\n", CONFIG_FB_OMAP2_NUM_FBS); ++ ++ /* allocate fb_infos */ ++ for (i = 0; i < CONFIG_FB_OMAP2_NUM_FBS; i++) { ++ struct fb_info *fbi; ++ struct omapfb_info *ofbi; ++ ++ fbi = framebuffer_alloc(sizeof(struct omapfb_info), ++ fbdev->dev); ++ ++ if (fbi == NULL) { ++ dev_err(fbdev->dev, ++ "unable to allocate memory for plane info\n"); ++ return -ENOMEM; ++ } ++ ++ clear_fb_info(fbi); ++ ++ fbdev->fbs[i] = fbi; ++ ++ ofbi = FB2OFB(fbi); ++ ofbi->fbdev = fbdev; ++ ofbi->id = i; ++ ++ /* assign these early, so that fb alloc can use them */ ++ ofbi->rotation_type = def_vrfb ? OMAP_DSS_ROT_VRFB : ++ OMAP_DSS_ROT_DMA; ++ ofbi->mirror = def_mirror; ++ ++ fbdev->num_fbs++; ++ } ++ ++ DBG("fb_infos allocated\n"); ++ ++ /* assign overlays for the fbs */ ++ for (i = 0; i < min(fbdev->num_fbs, fbdev->num_overlays); i++) { ++ struct omapfb_info *ofbi = FB2OFB(fbdev->fbs[i]); ++ ++ ofbi->overlays[0] = fbdev->overlays[i]; ++ ofbi->num_overlays = 1; ++ } ++ ++ /* allocate fb memories */ ++ r = omapfb_allocate_all_fbs(fbdev); ++ if (r) { ++ dev_err(fbdev->dev, "failed to allocate fbmem\n"); ++ return r; ++ } ++ ++ DBG("fbmems allocated\n"); ++ ++ /* setup fb_infos */ ++ for (i = 0; i < fbdev->num_fbs; i++) { ++ r = omapfb_fb_init(fbdev, fbdev->fbs[i]); ++ if (r) { ++ dev_err(fbdev->dev, "failed to setup fb_info\n"); ++ return r; ++ } ++ } ++ ++ DBG("fb_infos initialized\n"); ++ ++ for (i = 0; i < fbdev->num_fbs; i++) { ++ r = register_framebuffer(fbdev->fbs[i]); ++ if (r != 0) { ++ dev_err(fbdev->dev, ++ "registering framebuffer %d failed\n", i); ++ return r; ++ } ++ } ++ ++ DBG("framebuffers registered\n"); ++ ++ for (i = 0; i < fbdev->num_fbs; i++) { ++ r = omapfb_apply_changes(fbdev->fbs[i], 1); ++ if (r) { ++ dev_err(fbdev->dev, "failed to change mode\n"); ++ return r; ++ } ++ } ++ ++ DBG("create sysfs for fbs\n"); ++ r = omapfb_create_sysfs(fbdev); ++ if (r) { ++ dev_err(fbdev->dev, "failed to create sysfs entries\n"); ++ return r; ++ } ++ ++ /* Enable fb0 */ ++ if (fbdev->num_fbs > 0) { ++ struct omapfb_info *ofbi = FB2OFB(fbdev->fbs[0]); ++ ++ if (ofbi->num_overlays > 0) { ++ struct omap_overlay *ovl = ofbi->overlays[0]; ++ ++ r = omapfb_overlay_enable(ovl, 1); ++ ++ if (r) { ++ dev_err(fbdev->dev, ++ "failed to enable overlay\n"); ++ return r; ++ } ++ } ++ } ++ ++ DBG("create_framebuffers done\n"); ++ ++ return 0; ++} ++ ++static int omapfb_mode_to_timings(const char *mode_str, ++ struct omap_video_timings *timings, u8 *bpp) ++{ ++ struct fb_info fbi; ++ struct fb_var_screeninfo var; ++ struct fb_ops fbops; ++ int r; ++ ++#ifdef CONFIG_OMAP2_DSS_VENC ++ if (strcmp(mode_str, "pal") == 0) { ++ *timings = omap_dss_pal_timings; ++ *bpp = 0; ++ return 0; ++ } else if (strcmp(mode_str, "ntsc") == 0) { ++ *timings = omap_dss_ntsc_timings; ++ *bpp = 0; ++ return 0; ++ } ++#endif ++ ++ /* this is quite a hack, but I wanted to use the modedb and for ++ * that we need fb_info and var, so we create dummy ones */ ++ ++ memset(&fbi, 0, sizeof(fbi)); ++ memset(&var, 0, sizeof(var)); ++ memset(&fbops, 0, sizeof(fbops)); ++ fbi.fbops = &fbops; ++ ++ r = fb_find_mode(&var, &fbi, mode_str, NULL, 0, NULL, 24); ++ ++ if (r != 0) { ++ timings->pixel_clock = PICOS2KHZ(var.pixclock); ++ timings->hfp = var.left_margin; ++ timings->hbp = var.right_margin; ++ timings->vfp = var.upper_margin; ++ timings->vbp = var.lower_margin; ++ timings->hsw = var.hsync_len; ++ timings->vsw = var.vsync_len; ++ timings->x_res = var.xres; ++ timings->y_res = var.yres; ++ ++ switch (var.bits_per_pixel) { ++ case 16: ++ *bpp = 16; ++ break; ++ case 24: ++ case 32: ++ default: ++ *bpp = 24; ++ break; ++ } ++ ++ return 0; ++ } else { ++ return -EINVAL; ++ } ++} ++ ++static int omapfb_set_def_mode(struct omap_dss_device *display, char *mode_str) ++{ ++ int r; ++ u8 bpp; ++ struct omap_video_timings timings; ++ ++ r = omapfb_mode_to_timings(mode_str, &timings, &bpp); ++ if (r) ++ return r; ++ ++ display->panel.recommended_bpp = bpp; ++ ++ if (!display->check_timings || !display->set_timings) ++ return -EINVAL; ++ ++ r = display->check_timings(display, &timings); ++ if (r) ++ return r; ++ ++ display->set_timings(display, &timings); ++ ++ return 0; ++} ++ ++static int omapfb_parse_def_modes(struct omapfb2_device *fbdev) ++{ ++ char *str, *options, *this_opt; ++ int r = 0; ++ ++ str = kmalloc(strlen(def_mode) + 1, GFP_KERNEL); ++ strcpy(str, def_mode); ++ options = str; ++ ++ while (!r && (this_opt = strsep(&options, ",")) != NULL) { ++ char *p, *display_str, *mode_str; ++ struct omap_dss_device *display; ++ int i; ++ ++ p = strchr(this_opt, ':'); ++ if (!p) { ++ r = -EINVAL; ++ break; ++ } ++ ++ *p = 0; ++ display_str = this_opt; ++ mode_str = p + 1; ++ ++ display = NULL; ++ for (i = 0; i < fbdev->num_displays; ++i) { ++ if (strcmp(fbdev->displays[i]->name, ++ display_str) == 0) { ++ display = fbdev->displays[i]; ++ break; ++ } ++ } ++ ++ if (!display) { ++ r = -EINVAL; ++ break; ++ } ++ ++ r = omapfb_set_def_mode(display, mode_str); ++ if (r) ++ break; ++ } ++ ++ kfree(str); ++ ++ return r; ++} ++ ++static int omapfb_probe(struct platform_device *pdev) ++{ ++ struct omapfb2_device *fbdev = NULL; ++ int r = 0; ++ int i; ++ struct omap_overlay *ovl; ++ struct omap_dss_device *def_display; ++ struct omap_dss_device *dssdev; ++ ++ DBG("omapfb_probe\n"); ++ ++ if (pdev->num_resources != 0) { ++ dev_err(&pdev->dev, "probed for an unknown device\n"); ++ r = -ENODEV; ++ goto err0; ++ } ++ ++ fbdev = kzalloc(sizeof(struct omapfb2_device), GFP_KERNEL); ++ if (fbdev == NULL) { ++ r = -ENOMEM; ++ goto err0; ++ } ++ ++ mutex_init(&fbdev->mtx); ++ ++ fbdev->dev = &pdev->dev; ++ platform_set_drvdata(pdev, fbdev); ++ ++ fbdev->num_displays = 0; ++ dssdev = NULL; ++ for_each_dss_dev(dssdev) { ++ omap_dss_get_device(dssdev); ++ fbdev->displays[fbdev->num_displays++] = dssdev; ++ } ++ ++ if (fbdev->num_displays == 0) { ++ dev_err(&pdev->dev, "no displays\n"); ++ r = -EINVAL; ++ goto cleanup; ++ } ++ ++ fbdev->num_overlays = omap_dss_get_num_overlays(); ++ for (i = 0; i < fbdev->num_overlays; i++) ++ fbdev->overlays[i] = omap_dss_get_overlay(i); ++ ++ fbdev->num_managers = omap_dss_get_num_overlay_managers(); ++ for (i = 0; i < fbdev->num_managers; i++) ++ fbdev->managers[i] = omap_dss_get_overlay_manager(i); ++ ++ if (def_mode && strlen(def_mode) > 0) { ++ if (omapfb_parse_def_modes(fbdev)) ++ dev_warn(&pdev->dev, "cannot parse default modes\n"); ++ } ++ ++ r = omapfb_create_framebuffers(fbdev); ++ if (r) ++ goto cleanup; ++ ++ for (i = 0; i < fbdev->num_managers; i++) { ++ struct omap_overlay_manager *mgr; ++ mgr = fbdev->managers[i]; ++ r = mgr->apply(mgr); ++ if (r) ++ dev_warn(fbdev->dev, "failed to apply dispc config\n"); ++ } ++ ++ DBG("mgr->apply'ed\n"); ++ ++ /* gfx overlay should be the default one. find a display ++ * connected to that, and use it as default display */ ++ ovl = omap_dss_get_overlay(0); ++ if (ovl->manager && ovl->manager->device) { ++ def_display = ovl->manager->device; ++ } else { ++ dev_warn(&pdev->dev, "cannot find default display\n"); ++ def_display = NULL; ++ } ++ ++ if (def_display) { ++ u16 w, h; ++ r = def_display->enable(def_display); ++ if (r) ++ dev_warn(fbdev->dev, "Failed to enable display '%s'\n", ++ def_display->name); ++ ++ /* set the update mode */ ++ if (def_display->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) { ++#ifdef CONFIG_FB_OMAP2_FORCE_AUTO_UPDATE ++ if (def_display->enable_te) ++ def_display->enable_te(def_display, 1); ++ if (def_display->set_update_mode) ++ def_display->set_update_mode(def_display, ++ OMAP_DSS_UPDATE_AUTO); ++#else /* MANUAL_UPDATE */ ++ if (def_display->enable_te) ++ def_display->enable_te(def_display, 0); ++ if (def_display->set_update_mode) ++ def_display->set_update_mode(def_display, ++ OMAP_DSS_UPDATE_MANUAL); ++ ++ def_display->get_resolution(def_display, &w, &h); ++ def_display->update(def_display, 0, 0, w, h); ++#endif ++ } else { ++ if (def_display->set_update_mode) ++ def_display->set_update_mode(def_display, ++ OMAP_DSS_UPDATE_AUTO); ++ } ++ } ++ ++ return 0; ++ ++cleanup: ++ omapfb_free_resources(fbdev); ++err0: ++ dev_err(&pdev->dev, "failed to setup omapfb\n"); ++ return r; ++} ++ ++static int omapfb_remove(struct platform_device *pdev) ++{ ++ struct omapfb2_device *fbdev = platform_get_drvdata(pdev); ++ ++ /* FIXME: wait till completion of pending events */ ++ ++ omapfb_remove_sysfs(fbdev); ++ ++ omapfb_free_resources(fbdev); ++ ++ return 0; ++} ++ ++static struct platform_driver omapfb_driver = { ++ .probe = omapfb_probe, ++ .remove = omapfb_remove, ++ .driver = { ++ .name = "omapfb", ++ .owner = THIS_MODULE, ++ }, ++}; ++ ++static int __init omapfb_init(void) ++{ ++ DBG("omapfb_init\n"); ++ ++ if (platform_driver_register(&omapfb_driver)) { ++ printk(KERN_ERR "failed to register omapfb driver\n"); ++ return -ENODEV; ++ } ++ ++ return 0; ++} ++ ++static void __exit omapfb_exit(void) ++{ ++ DBG("omapfb_exit\n"); ++ platform_driver_unregister(&omapfb_driver); ++} ++ ++module_param_named(mode, def_mode, charp, 0); ++module_param_named(vram, def_vram, charp, 0); ++module_param_named(rotate, def_rotate, int, 0); ++module_param_named(vrfb, def_vrfb, bool, 0); ++module_param_named(mirror, def_mirror, bool, 0); ++ ++/* late_initcall to let panel/ctrl drivers loaded first. ++ * I guess better option would be a more dynamic approach, ++ * so that omapfb reacts to new panels when they are loaded */ ++late_initcall(omapfb_init); ++/*module_init(omapfb_init);*/ ++module_exit(omapfb_exit); ++ ++MODULE_AUTHOR("Tomi Valkeinen "); ++MODULE_DESCRIPTION("OMAP2/3 Framebuffer"); ++MODULE_LICENSE("GPL v2"); +diff --git a/drivers/video/omap2/omapfb/omapfb-sysfs.c b/drivers/video/omap2/omapfb/omapfb-sysfs.c +new file mode 100644 +index 0000000..ef30e0e +--- /dev/null ++++ b/drivers/video/omap2/omapfb/omapfb-sysfs.c +@@ -0,0 +1,507 @@ ++/* ++ * linux/drivers/video/omap2/omapfb-sysfs.c ++ * ++ * Copyright (C) 2008 Nokia Corporation ++ * Author: Tomi Valkeinen ++ * ++ * Some code and ideas taken from drivers/video/omap/ driver ++ * by Imre Deak. ++ * ++ * 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. ++ * ++ * 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, see . ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++ ++#include "omapfb.h" ++ ++static ssize_t show_rotate_type(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct fb_info *fbi = dev_get_drvdata(dev); ++ struct omapfb_info *ofbi = FB2OFB(fbi); ++ ++ return snprintf(buf, PAGE_SIZE, "%d\n", ofbi->rotation_type); ++} ++ ++static ssize_t store_rotate_type(struct device *dev, ++ struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ struct fb_info *fbi = dev_get_drvdata(dev); ++ struct omapfb_info *ofbi = FB2OFB(fbi); ++ enum omap_dss_rotation_type rot_type; ++ int r; ++ ++ rot_type = simple_strtoul(buf, NULL, 0); ++ ++ if (rot_type != OMAP_DSS_ROT_DMA && rot_type != OMAP_DSS_ROT_VRFB) ++ return -EINVAL; ++ ++ lock_fb_info(fbi); ++ ++ r = 0; ++ if (rot_type == ofbi->rotation_type) ++ goto out; ++ ++ if (ofbi->region.size) { ++ r = -EBUSY; ++ goto out; ++ } ++ ++ ofbi->rotation_type = rot_type; ++ ++ /* ++ * Since the VRAM for this FB is not allocated at the moment we don't ++ * need to do any further parameter checking at this point. ++ */ ++out: ++ unlock_fb_info(fbi); ++ ++ return r ? r : count; ++} ++ ++ ++static ssize_t show_mirror(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct fb_info *fbi = dev_get_drvdata(dev); ++ struct omapfb_info *ofbi = FB2OFB(fbi); ++ ++ return snprintf(buf, PAGE_SIZE, "%d\n", ofbi->mirror); ++} ++ ++static ssize_t store_mirror(struct device *dev, ++ struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ struct fb_info *fbi = dev_get_drvdata(dev); ++ struct omapfb_info *ofbi = FB2OFB(fbi); ++ bool mirror; ++ int r; ++ struct fb_var_screeninfo new_var; ++ ++ mirror = simple_strtoul(buf, NULL, 0); ++ ++ if (mirror != 0 && mirror != 1) ++ return -EINVAL; ++ ++ lock_fb_info(fbi); ++ ++ ofbi->mirror = mirror; ++ ++ memcpy(&new_var, &fbi->var, sizeof(new_var)); ++ r = check_fb_var(fbi, &new_var); ++ if (r) ++ goto out; ++ memcpy(&fbi->var, &new_var, sizeof(fbi->var)); ++ ++ set_fb_fix(fbi); ++ ++ r = omapfb_apply_changes(fbi, 0); ++ if (r) ++ goto out; ++ ++ r = count; ++out: ++ unlock_fb_info(fbi); ++ ++ return r; ++} ++ ++static ssize_t show_overlays(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct fb_info *fbi = dev_get_drvdata(dev); ++ struct omapfb_info *ofbi = FB2OFB(fbi); ++ struct omapfb2_device *fbdev = ofbi->fbdev; ++ ssize_t l = 0; ++ int t; ++ ++ omapfb_lock(fbdev); ++ lock_fb_info(fbi); ++ ++ for (t = 0; t < ofbi->num_overlays; t++) { ++ struct omap_overlay *ovl = ofbi->overlays[t]; ++ int ovlnum; ++ ++ for (ovlnum = 0; ovlnum < fbdev->num_overlays; ++ovlnum) ++ if (ovl == fbdev->overlays[ovlnum]) ++ break; ++ ++ l += snprintf(buf + l, PAGE_SIZE - l, "%s%d", ++ t == 0 ? "" : ",", ovlnum); ++ } ++ ++ l += snprintf(buf + l, PAGE_SIZE - l, "\n"); ++ ++ unlock_fb_info(fbi); ++ omapfb_unlock(fbdev); ++ ++ return l; ++} ++ ++static struct omapfb_info *get_overlay_fb(struct omapfb2_device *fbdev, ++ struct omap_overlay *ovl) ++{ ++ int i, t; ++ ++ for (i = 0; i < fbdev->num_fbs; i++) { ++ struct omapfb_info *ofbi = FB2OFB(fbdev->fbs[i]); ++ ++ for (t = 0; t < ofbi->num_overlays; t++) { ++ if (ofbi->overlays[t] == ovl) ++ return ofbi; ++ } ++ } ++ ++ return NULL; ++} ++ ++static ssize_t store_overlays(struct device *dev, struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ struct fb_info *fbi = dev_get_drvdata(dev); ++ struct omapfb_info *ofbi = FB2OFB(fbi); ++ struct omapfb2_device *fbdev = ofbi->fbdev; ++ struct omap_overlay *ovls[OMAPFB_MAX_OVL_PER_FB]; ++ struct omap_overlay *ovl; ++ int num_ovls, r, i; ++ int len; ++ bool added = false; ++ ++ num_ovls = 0; ++ ++ len = strlen(buf); ++ if (buf[len - 1] == '\n') ++ len = len - 1; ++ ++ omapfb_lock(fbdev); ++ lock_fb_info(fbi); ++ ++ if (len > 0) { ++ char *p = (char *)buf; ++ int ovlnum; ++ ++ while (p < buf + len) { ++ int found; ++ if (num_ovls == OMAPFB_MAX_OVL_PER_FB) { ++ r = -EINVAL; ++ goto out; ++ } ++ ++ ovlnum = simple_strtoul(p, &p, 0); ++ if (ovlnum > fbdev->num_overlays) { ++ r = -EINVAL; ++ goto out; ++ } ++ ++ found = 0; ++ for (i = 0; i < num_ovls; ++i) { ++ if (ovls[i] == fbdev->overlays[ovlnum]) { ++ found = 1; ++ break; ++ } ++ } ++ ++ if (!found) ++ ovls[num_ovls++] = fbdev->overlays[ovlnum]; ++ ++ p++; ++ } ++ } ++ ++ for (i = 0; i < num_ovls; ++i) { ++ struct omapfb_info *ofbi2 = get_overlay_fb(fbdev, ovls[i]); ++ if (ofbi2 && ofbi2 != ofbi) { ++ dev_err(fbdev->dev, "overlay already in use\n"); ++ r = -EINVAL; ++ goto out; ++ } ++ } ++ ++ /* detach unused overlays */ ++ for (i = 0; i < ofbi->num_overlays; ++i) { ++ int t, found; ++ ++ ovl = ofbi->overlays[i]; ++ ++ found = 0; ++ ++ for (t = 0; t < num_ovls; ++t) { ++ if (ovl == ovls[t]) { ++ found = 1; ++ break; ++ } ++ } ++ ++ if (found) ++ continue; ++ ++ DBG("detaching %d\n", ofbi->overlays[i]->id); ++ ++ omapfb_overlay_enable(ovl, 0); ++ ++ if (ovl->manager) ++ ovl->manager->apply(ovl->manager); ++ ++ for (t = i + 1; t < ofbi->num_overlays; t++) { ++ ofbi->rotation[t-1] = ofbi->rotation[t]; ++ ofbi->overlays[t-1] = ofbi->overlays[t]; ++ } ++ ++ ofbi->num_overlays--; ++ i--; ++ } ++ ++ for (i = 0; i < num_ovls; ++i) { ++ int t, found; ++ ++ ovl = ovls[i]; ++ ++ found = 0; ++ ++ for (t = 0; t < ofbi->num_overlays; ++t) { ++ if (ovl == ofbi->overlays[t]) { ++ found = 1; ++ break; ++ } ++ } ++ ++ if (found) ++ continue; ++ ofbi->rotation[ofbi->num_overlays] = 0; ++ ofbi->overlays[ofbi->num_overlays++] = ovl; ++ ++ added = true; ++ } ++ ++ if (added) { ++ r = omapfb_apply_changes(fbi, 0); ++ if (r) ++ goto out; ++ } ++ ++ r = count; ++out: ++ unlock_fb_info(fbi); ++ omapfb_unlock(fbdev); ++ ++ return r; ++} ++ ++static ssize_t show_overlays_rotate(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct fb_info *fbi = dev_get_drvdata(dev); ++ struct omapfb_info *ofbi = FB2OFB(fbi); ++ ssize_t l = 0; ++ int t; ++ ++ lock_fb_info(fbi); ++ ++ for (t = 0; t < ofbi->num_overlays; t++) { ++ l += snprintf(buf + l, PAGE_SIZE - l, "%s%d", ++ t == 0 ? "" : ",", ofbi->rotation[t]); ++ } ++ ++ l += snprintf(buf + l, PAGE_SIZE - l, "\n"); ++ ++ unlock_fb_info(fbi); ++ ++ return l; ++} ++ ++static ssize_t store_overlays_rotate(struct device *dev, ++ struct device_attribute *attr, const char *buf, size_t count) ++{ ++ struct fb_info *fbi = dev_get_drvdata(dev); ++ struct omapfb_info *ofbi = FB2OFB(fbi); ++ int num_ovls = 0, r, i; ++ int len; ++ bool changed = false; ++ u8 rotation[OMAPFB_MAX_OVL_PER_FB]; ++ ++ len = strlen(buf); ++ if (buf[len - 1] == '\n') ++ len = len - 1; ++ ++ lock_fb_info(fbi); ++ ++ if (len > 0) { ++ char *p = (char *)buf; ++ ++ while (p < buf + len) { ++ int rot; ++ ++ if (num_ovls == ofbi->num_overlays) { ++ r = -EINVAL; ++ goto out; ++ } ++ ++ rot = simple_strtoul(p, &p, 0); ++ if (rot < 0 || rot > 3) { ++ r = -EINVAL; ++ goto out; ++ } ++ ++ if (ofbi->rotation[num_ovls] != rot) ++ changed = true; ++ ++ rotation[num_ovls++] = rot; ++ ++ p++; ++ } ++ } ++ ++ if (num_ovls != ofbi->num_overlays) { ++ r = -EINVAL; ++ goto out; ++ } ++ ++ if (changed) { ++ for (i = 0; i < num_ovls; ++i) ++ ofbi->rotation[i] = rotation[i]; ++ ++ r = omapfb_apply_changes(fbi, 0); ++ if (r) ++ goto out; ++ ++ /* FIXME error handling? */ ++ } ++ ++ r = count; ++out: ++ unlock_fb_info(fbi); ++ ++ return r; ++} ++ ++static ssize_t show_size(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct fb_info *fbi = dev_get_drvdata(dev); ++ struct omapfb_info *ofbi = FB2OFB(fbi); ++ ++ return snprintf(buf, PAGE_SIZE, "%lu\n", ofbi->region.size); ++} ++ ++static ssize_t store_size(struct device *dev, struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ struct fb_info *fbi = dev_get_drvdata(dev); ++ struct omapfb_info *ofbi = FB2OFB(fbi); ++ unsigned long size; ++ int r; ++ int i; ++ ++ size = PAGE_ALIGN(simple_strtoul(buf, NULL, 0)); ++ ++ lock_fb_info(fbi); ++ ++ for (i = 0; i < ofbi->num_overlays; i++) { ++ if (ofbi->overlays[i]->info.enabled) { ++ r = -EBUSY; ++ goto out; ++ } ++ } ++ ++ if (size != ofbi->region.size) { ++ r = omapfb_realloc_fbmem(fbi, size, ofbi->region.type); ++ if (r) { ++ dev_err(dev, "realloc fbmem failed\n"); ++ goto out; ++ } ++ } ++ ++ r = count; ++out: ++ unlock_fb_info(fbi); ++ ++ return r; ++} ++ ++static ssize_t show_phys(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct fb_info *fbi = dev_get_drvdata(dev); ++ struct omapfb_info *ofbi = FB2OFB(fbi); ++ ++ return snprintf(buf, PAGE_SIZE, "%0x\n", ofbi->region.paddr); ++} ++ ++static ssize_t show_virt(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct fb_info *fbi = dev_get_drvdata(dev); ++ struct omapfb_info *ofbi = FB2OFB(fbi); ++ ++ return snprintf(buf, PAGE_SIZE, "%p\n", ofbi->region.vaddr); ++} ++ ++static struct device_attribute omapfb_attrs[] = { ++ __ATTR(rotate_type, S_IRUGO | S_IWUSR, show_rotate_type, ++ store_rotate_type), ++ __ATTR(mirror, S_IRUGO | S_IWUSR, show_mirror, store_mirror), ++ __ATTR(size, S_IRUGO | S_IWUSR, show_size, store_size), ++ __ATTR(overlays, S_IRUGO | S_IWUSR, show_overlays, store_overlays), ++ __ATTR(overlays_rotate, S_IRUGO | S_IWUSR, show_overlays_rotate, ++ store_overlays_rotate), ++ __ATTR(phys_addr, S_IRUGO, show_phys, NULL), ++ __ATTR(virt_addr, S_IRUGO, show_virt, NULL), ++}; ++ ++int omapfb_create_sysfs(struct omapfb2_device *fbdev) ++{ ++ int i; ++ int r; ++ ++ DBG("create sysfs for fbs\n"); ++ for (i = 0; i < fbdev->num_fbs; i++) { ++ int t; ++ for (t = 0; t < ARRAY_SIZE(omapfb_attrs); t++) { ++ r = device_create_file(fbdev->fbs[i]->dev, ++ &omapfb_attrs[t]); ++ ++ if (r) { ++ dev_err(fbdev->dev, "failed to create sysfs " ++ "file\n"); ++ return r; ++ } ++ } ++ } ++ ++ return 0; ++} ++ ++void omapfb_remove_sysfs(struct omapfb2_device *fbdev) ++{ ++ int i, t; ++ ++ DBG("remove sysfs for fbs\n"); ++ for (i = 0; i < fbdev->num_fbs; i++) { ++ for (t = 0; t < ARRAY_SIZE(omapfb_attrs); t++) ++ device_remove_file(fbdev->fbs[i]->dev, ++ &omapfb_attrs[t]); ++ } ++} ++ +diff --git a/drivers/video/omap2/omapfb/omapfb.h b/drivers/video/omap2/omapfb/omapfb.h +new file mode 100644 +index 0000000..d9ee986 +--- /dev/null ++++ b/drivers/video/omap2/omapfb/omapfb.h +@@ -0,0 +1,146 @@ ++/* ++ * linux/drivers/video/omap2/omapfb.h ++ * ++ * Copyright (C) 2008 Nokia Corporation ++ * Author: Tomi Valkeinen ++ * ++ * Some code and ideas taken from drivers/video/omap/ driver ++ * by Imre Deak. ++ * ++ * 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. ++ * ++ * 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, see . ++ */ ++ ++#ifndef __DRIVERS_VIDEO_OMAP2_OMAPFB_H__ ++#define __DRIVERS_VIDEO_OMAP2_OMAPFB_H__ ++ ++#ifdef CONFIG_FB_OMAP2_DEBUG_SUPPORT ++#define DEBUG ++#endif ++ ++#include ++ ++#ifdef DEBUG ++extern unsigned int omapfb_debug; ++#define DBG(format, ...) \ ++ if (omapfb_debug) \ ++ printk(KERN_DEBUG "OMAPFB: " format, ## __VA_ARGS__) ++#else ++#define DBG(format, ...) ++#endif ++ ++#define FB2OFB(fb_info) ((struct omapfb_info *)(fb_info->par)) ++ ++/* max number of overlays to which a framebuffer data can be direct */ ++#define OMAPFB_MAX_OVL_PER_FB 3 ++ ++struct omapfb2_mem_region { ++ u32 paddr; ++ void __iomem *vaddr; ++ struct vrfb vrfb; ++ unsigned long size; ++ u8 type; /* OMAPFB_PLANE_MEM_* */ ++ bool alloc; /* allocated by the driver */ ++ bool map; /* kernel mapped by the driver */ ++}; ++ ++/* appended to fb_info */ ++struct omapfb_info { ++ int id; ++ struct omapfb2_mem_region region; ++ atomic_t map_count; ++ int num_overlays; ++ struct omap_overlay *overlays[OMAPFB_MAX_OVL_PER_FB]; ++ struct omapfb2_device *fbdev; ++ enum omap_dss_rotation_type rotation_type; ++ u8 rotation[OMAPFB_MAX_OVL_PER_FB]; ++ bool mirror; ++}; ++ ++struct omapfb2_device { ++ struct device *dev; ++ struct mutex mtx; ++ ++ u32 pseudo_palette[17]; ++ ++ int state; ++ ++ unsigned num_fbs; ++ struct fb_info *fbs[10]; ++ ++ unsigned num_displays; ++ struct omap_dss_device *displays[10]; ++ unsigned num_overlays; ++ struct omap_overlay *overlays[10]; ++ unsigned num_managers; ++ struct omap_overlay_manager *managers[10]; ++}; ++ ++struct omapfb_colormode { ++ enum omap_color_mode dssmode; ++ u32 bits_per_pixel; ++ u32 nonstd; ++ struct fb_bitfield red; ++ struct fb_bitfield green; ++ struct fb_bitfield blue; ++ struct fb_bitfield transp; ++}; ++ ++void set_fb_fix(struct fb_info *fbi); ++int check_fb_var(struct fb_info *fbi, struct fb_var_screeninfo *var); ++int omapfb_realloc_fbmem(struct fb_info *fbi, unsigned long size, int type); ++int omapfb_apply_changes(struct fb_info *fbi, int init); ++ ++int omapfb_create_sysfs(struct omapfb2_device *fbdev); ++void omapfb_remove_sysfs(struct omapfb2_device *fbdev); ++ ++int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg); ++ ++int dss_mode_to_fb_mode(enum omap_color_mode dssmode, ++ struct fb_var_screeninfo *var); ++ ++/* find the display connected to this fb, if any */ ++static inline struct omap_dss_device *fb2display(struct fb_info *fbi) ++{ ++ struct omapfb_info *ofbi = FB2OFB(fbi); ++ int i; ++ ++ /* XXX: returns the display connected to first attached overlay */ ++ for (i = 0; i < ofbi->num_overlays; i++) { ++ if (ofbi->overlays[i]->manager) ++ return ofbi->overlays[i]->manager->device; ++ } ++ ++ return NULL; ++} ++ ++static inline void omapfb_lock(struct omapfb2_device *fbdev) ++{ ++ mutex_lock(&fbdev->mtx); ++} ++ ++static inline void omapfb_unlock(struct omapfb2_device *fbdev) ++{ ++ mutex_unlock(&fbdev->mtx); ++} ++ ++static inline int omapfb_overlay_enable(struct omap_overlay *ovl, ++ int enable) ++{ ++ struct omap_overlay_info info; ++ ++ ovl->get_overlay_info(ovl, &info); ++ info.enabled = enable; ++ return ovl->set_overlay_info(ovl, &info); ++} ++ ++#endif +diff --git a/drivers/video/omap2/vram.c b/drivers/video/omap2/vram.c +new file mode 100644 +index 0000000..634ce23 +--- /dev/null ++++ b/drivers/video/omap2/vram.c +@@ -0,0 +1,655 @@ ++/* ++ * VRAM manager for OMAP ++ * ++ * Copyright (C) 2009 Nokia Corporation ++ * Author: Tomi Valkeinen ++ * ++ * 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. ++ * ++ * 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, MA 02111-1307, USA. ++ */ ++ ++/*#define DEBUG*/ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#include ++#include ++#include ++ ++#ifdef DEBUG ++#define DBG(format, ...) pr_debug("VRAM: " format, ## __VA_ARGS__) ++#else ++#define DBG(format, ...) ++#endif ++ ++#define OMAP2_SRAM_START 0x40200000 ++/* Maximum size, in reality this is smaller if SRAM is partially locked. */ ++#define OMAP2_SRAM_SIZE 0xa0000 /* 640k */ ++ ++/* postponed regions are used to temporarily store region information at boot ++ * time when we cannot yet allocate the region list */ ++#define MAX_POSTPONED_REGIONS 10 ++ ++static bool vram_initialized; ++static int postponed_cnt; ++static struct { ++ unsigned long paddr; ++ size_t size; ++} postponed_regions[MAX_POSTPONED_REGIONS]; ++ ++struct vram_alloc { ++ struct list_head list; ++ unsigned long paddr; ++ unsigned pages; ++}; ++ ++struct vram_region { ++ struct list_head list; ++ struct list_head alloc_list; ++ unsigned long paddr; ++ unsigned pages; ++}; ++ ++static DEFINE_MUTEX(region_mutex); ++static LIST_HEAD(region_list); ++ ++static inline int region_mem_type(unsigned long paddr) ++{ ++ if (paddr >= OMAP2_SRAM_START && ++ paddr < OMAP2_SRAM_START + OMAP2_SRAM_SIZE) ++ return OMAP_VRAM_MEMTYPE_SRAM; ++ else ++ return OMAP_VRAM_MEMTYPE_SDRAM; ++} ++ ++static struct vram_region *omap_vram_create_region(unsigned long paddr, ++ unsigned pages) ++{ ++ struct vram_region *rm; ++ ++ rm = kzalloc(sizeof(*rm), GFP_KERNEL); ++ ++ if (rm) { ++ INIT_LIST_HEAD(&rm->alloc_list); ++ rm->paddr = paddr; ++ rm->pages = pages; ++ } ++ ++ return rm; ++} ++ ++#if 0 ++static void omap_vram_free_region(struct vram_region *vr) ++{ ++ list_del(&vr->list); ++ kfree(vr); ++} ++#endif ++ ++static struct vram_alloc *omap_vram_create_allocation(struct vram_region *vr, ++ unsigned long paddr, unsigned pages) ++{ ++ struct vram_alloc *va; ++ struct vram_alloc *new; ++ ++ new = kzalloc(sizeof(*va), GFP_KERNEL); ++ ++ if (!new) ++ return NULL; ++ ++ new->paddr = paddr; ++ new->pages = pages; ++ ++ list_for_each_entry(va, &vr->alloc_list, list) { ++ if (va->paddr > new->paddr) ++ break; ++ } ++ ++ list_add_tail(&new->list, &va->list); ++ ++ return new; ++} ++ ++static void omap_vram_free_allocation(struct vram_alloc *va) ++{ ++ list_del(&va->list); ++ kfree(va); ++} ++ ++int omap_vram_add_region(unsigned long paddr, size_t size) ++{ ++ struct vram_region *rm; ++ unsigned pages; ++ ++ if (vram_initialized) { ++ DBG("adding region paddr %08lx size %d\n", ++ paddr, size); ++ ++ size &= PAGE_MASK; ++ pages = size >> PAGE_SHIFT; ++ ++ rm = omap_vram_create_region(paddr, pages); ++ if (rm == NULL) ++ return -ENOMEM; ++ ++ list_add(&rm->list, ®ion_list); ++ } else { ++ if (postponed_cnt == MAX_POSTPONED_REGIONS) ++ return -ENOMEM; ++ ++ postponed_regions[postponed_cnt].paddr = paddr; ++ postponed_regions[postponed_cnt].size = size; ++ ++ ++postponed_cnt; ++ } ++ return 0; ++} ++ ++int omap_vram_free(unsigned long paddr, size_t size) ++{ ++ struct vram_region *rm; ++ struct vram_alloc *alloc; ++ unsigned start, end; ++ ++ DBG("free mem paddr %08lx size %d\n", paddr, size); ++ ++ size = PAGE_ALIGN(size); ++ ++ mutex_lock(®ion_mutex); ++ ++ list_for_each_entry(rm, ®ion_list, list) { ++ list_for_each_entry(alloc, &rm->alloc_list, list) { ++ start = alloc->paddr; ++ end = alloc->paddr + (alloc->pages >> PAGE_SHIFT); ++ ++ if (start >= paddr && end < paddr + size) ++ goto found; ++ } ++ } ++ ++ mutex_unlock(®ion_mutex); ++ return -EINVAL; ++ ++found: ++ omap_vram_free_allocation(alloc); ++ ++ mutex_unlock(®ion_mutex); ++ return 0; ++} ++EXPORT_SYMBOL(omap_vram_free); ++ ++static int _omap_vram_reserve(unsigned long paddr, unsigned pages) ++{ ++ struct vram_region *rm; ++ struct vram_alloc *alloc; ++ size_t size; ++ ++ size = pages << PAGE_SHIFT; ++ ++ list_for_each_entry(rm, ®ion_list, list) { ++ unsigned long start, end; ++ ++ DBG("checking region %lx %d\n", rm->paddr, rm->pages); ++ ++ if (region_mem_type(rm->paddr) != region_mem_type(paddr)) ++ continue; ++ ++ start = rm->paddr; ++ end = start + (rm->pages << PAGE_SHIFT) - 1; ++ if (start > paddr || end < paddr + size - 1) ++ continue; ++ ++ DBG("block ok, checking allocs\n"); ++ ++ list_for_each_entry(alloc, &rm->alloc_list, list) { ++ end = alloc->paddr - 1; ++ ++ if (start <= paddr && end >= paddr + size - 1) ++ goto found; ++ ++ start = alloc->paddr + (alloc->pages << PAGE_SHIFT); ++ } ++ ++ end = rm->paddr + (rm->pages << PAGE_SHIFT) - 1; ++ ++ if (!(start <= paddr && end >= paddr + size - 1)) ++ continue; ++found: ++ DBG("found area start %lx, end %lx\n", start, end); ++ ++ if (omap_vram_create_allocation(rm, paddr, pages) == NULL) ++ return -ENOMEM; ++ ++ return 0; ++ } ++ ++ return -ENOMEM; ++} ++ ++int omap_vram_reserve(unsigned long paddr, size_t size) ++{ ++ unsigned pages; ++ int r; ++ ++ DBG("reserve mem paddr %08lx size %d\n", paddr, size); ++ ++ size = PAGE_ALIGN(size); ++ pages = size >> PAGE_SHIFT; ++ ++ mutex_lock(®ion_mutex); ++ ++ r = _omap_vram_reserve(paddr, pages); ++ ++ mutex_unlock(®ion_mutex); ++ ++ return r; ++} ++EXPORT_SYMBOL(omap_vram_reserve); ++ ++static void _omap_vram_dma_cb(int lch, u16 ch_status, void *data) ++{ ++ struct completion *compl = data; ++ complete(compl); ++} ++ ++static int _omap_vram_clear(u32 paddr, unsigned pages) ++{ ++ struct completion compl; ++ unsigned elem_count; ++ unsigned frame_count; ++ int r; ++ int lch; ++ ++ init_completion(&compl); ++ ++ r = omap_request_dma(OMAP_DMA_NO_DEVICE, "VRAM DMA", ++ _omap_vram_dma_cb, ++ &compl, &lch); ++ if (r) { ++ pr_err("VRAM: request_dma failed for memory clear\n"); ++ return -EBUSY; ++ } ++ ++ elem_count = pages * PAGE_SIZE / 4; ++ frame_count = 1; ++ ++ omap_set_dma_transfer_params(lch, OMAP_DMA_DATA_TYPE_S32, ++ elem_count, frame_count, ++ OMAP_DMA_SYNC_ELEMENT, ++ 0, 0); ++ ++ omap_set_dma_dest_params(lch, 0, OMAP_DMA_AMODE_POST_INC, ++ paddr, 0, 0); ++ ++ omap_set_dma_color_mode(lch, OMAP_DMA_CONSTANT_FILL, 0x000000); ++ ++ omap_start_dma(lch); ++ ++ if (wait_for_completion_timeout(&compl, msecs_to_jiffies(1000)) == 0) { ++ omap_stop_dma(lch); ++ pr_err("VRAM: dma timeout while clearing memory\n"); ++ r = -EIO; ++ goto err; ++ } ++ ++ r = 0; ++err: ++ omap_free_dma(lch); ++ ++ return r; ++} ++ ++static int _omap_vram_alloc(int mtype, unsigned pages, unsigned long *paddr) ++{ ++ struct vram_region *rm; ++ struct vram_alloc *alloc; ++ ++ list_for_each_entry(rm, ®ion_list, list) { ++ unsigned long start, end; ++ ++ DBG("checking region %lx %d\n", rm->paddr, rm->pages); ++ ++ if (region_mem_type(rm->paddr) != mtype) ++ continue; ++ ++ start = rm->paddr; ++ ++ list_for_each_entry(alloc, &rm->alloc_list, list) { ++ end = alloc->paddr; ++ ++ if (end - start >= pages << PAGE_SHIFT) ++ goto found; ++ ++ start = alloc->paddr + (alloc->pages << PAGE_SHIFT); ++ } ++ ++ end = rm->paddr + (rm->pages << PAGE_SHIFT); ++found: ++ if (end - start < pages << PAGE_SHIFT) ++ continue; ++ ++ DBG("found %lx, end %lx\n", start, end); ++ ++ alloc = omap_vram_create_allocation(rm, start, pages); ++ if (alloc == NULL) ++ return -ENOMEM; ++ ++ *paddr = start; ++ ++ _omap_vram_clear(start, pages); ++ ++ return 0; ++ } ++ ++ return -ENOMEM; ++} ++ ++int omap_vram_alloc(int mtype, size_t size, unsigned long *paddr) ++{ ++ unsigned pages; ++ int r; ++ ++ BUG_ON(mtype > OMAP_VRAM_MEMTYPE_MAX || !size); ++ ++ DBG("alloc mem type %d size %d\n", mtype, size); ++ ++ size = PAGE_ALIGN(size); ++ pages = size >> PAGE_SHIFT; ++ ++ mutex_lock(®ion_mutex); ++ ++ r = _omap_vram_alloc(mtype, pages, paddr); ++ ++ mutex_unlock(®ion_mutex); ++ ++ return r; ++} ++EXPORT_SYMBOL(omap_vram_alloc); ++ ++void omap_vram_get_info(unsigned long *vram, ++ unsigned long *free_vram, ++ unsigned long *largest_free_block) ++{ ++ struct vram_region *vr; ++ struct vram_alloc *va; ++ ++ *vram = 0; ++ *free_vram = 0; ++ *largest_free_block = 0; ++ ++ mutex_lock(®ion_mutex); ++ ++ list_for_each_entry(vr, ®ion_list, list) { ++ unsigned free; ++ unsigned long pa; ++ ++ pa = vr->paddr; ++ *vram += vr->pages << PAGE_SHIFT; ++ ++ list_for_each_entry(va, &vr->alloc_list, list) { ++ free = va->paddr - pa; ++ *free_vram += free; ++ if (free > *largest_free_block) ++ *largest_free_block = free; ++ pa = va->paddr + (va->pages << PAGE_SHIFT); ++ } ++ ++ free = vr->paddr + (vr->pages << PAGE_SHIFT) - pa; ++ *free_vram += free; ++ if (free > *largest_free_block) ++ *largest_free_block = free; ++ } ++ ++ mutex_unlock(®ion_mutex); ++} ++EXPORT_SYMBOL(omap_vram_get_info); ++ ++#if defined(CONFIG_DEBUG_FS) ++static int vram_debug_show(struct seq_file *s, void *unused) ++{ ++ struct vram_region *vr; ++ struct vram_alloc *va; ++ unsigned size; ++ ++ mutex_lock(®ion_mutex); ++ ++ list_for_each_entry(vr, ®ion_list, list) { ++ size = vr->pages << PAGE_SHIFT; ++ seq_printf(s, "%08lx-%08lx (%d bytes)\n", ++ vr->paddr, vr->paddr + size - 1, ++ size); ++ ++ list_for_each_entry(va, &vr->alloc_list, list) { ++ size = va->pages << PAGE_SHIFT; ++ seq_printf(s, " %08lx-%08lx (%d bytes)\n", ++ va->paddr, va->paddr + size - 1, ++ size); ++ } ++ } ++ ++ mutex_unlock(®ion_mutex); ++ ++ return 0; ++} ++ ++static int vram_debug_open(struct inode *inode, struct file *file) ++{ ++ return single_open(file, vram_debug_show, inode->i_private); ++} ++ ++static const struct file_operations vram_debug_fops = { ++ .open = vram_debug_open, ++ .read = seq_read, ++ .llseek = seq_lseek, ++ .release = single_release, ++}; ++ ++static int __init omap_vram_create_debugfs(void) ++{ ++ struct dentry *d; ++ ++ d = debugfs_create_file("vram", S_IRUGO, NULL, ++ NULL, &vram_debug_fops); ++ if (IS_ERR(d)) ++ return PTR_ERR(d); ++ ++ return 0; ++} ++#endif ++ ++static __init int omap_vram_init(void) ++{ ++ int i; ++ ++ vram_initialized = 1; ++ ++ for (i = 0; i < postponed_cnt; i++) ++ omap_vram_add_region(postponed_regions[i].paddr, ++ postponed_regions[i].size); ++ ++#ifdef CONFIG_DEBUG_FS ++ if (omap_vram_create_debugfs()) ++ pr_err("VRAM: Failed to create debugfs file\n"); ++#endif ++ ++ return 0; ++} ++ ++arch_initcall(omap_vram_init); ++ ++/* boottime vram alloc stuff */ ++ ++/* set from board file */ ++static u32 omap_vram_sram_start __initdata; ++static u32 omap_vram_sram_size __initdata; ++ ++/* set from board file */ ++static u32 omap_vram_sdram_start __initdata; ++static u32 omap_vram_sdram_size __initdata; ++ ++/* set from kernel cmdline */ ++static u32 omap_vram_def_sdram_size __initdata; ++static u32 omap_vram_def_sdram_start __initdata; ++ ++static void __init omap_vram_early_vram(char **p) ++{ ++ omap_vram_def_sdram_size = memparse(*p, p); ++ if (**p == ',') ++ omap_vram_def_sdram_start = simple_strtoul((*p) + 1, p, 16); ++} ++__early_param("vram=", omap_vram_early_vram); ++ ++/* ++ * Called from map_io. We need to call to this early enough so that we ++ * can reserve the fixed SDRAM regions before VM could get hold of them. ++ */ ++void __init omap_vram_reserve_sdram(void) ++{ ++ struct bootmem_data *bdata; ++ unsigned long sdram_start, sdram_size; ++ u32 paddr; ++ u32 size = 0; ++ ++ /* cmdline arg overrides the board file definition */ ++ if (omap_vram_def_sdram_size) { ++ size = omap_vram_def_sdram_size; ++ paddr = omap_vram_def_sdram_start; ++ } ++ ++ if (!size) { ++ size = omap_vram_sdram_size; ++ paddr = omap_vram_sdram_start; ++ } ++ ++#ifdef CONFIG_OMAP2_VRAM_SIZE ++ if (!size) { ++ size = CONFIG_OMAP2_VRAM_SIZE * 1024 * 1024; ++ paddr = 0; ++ } ++#endif ++ ++ if (!size) ++ return; ++ ++ size = PAGE_ALIGN(size); ++ ++ bdata = NODE_DATA(0)->bdata; ++ sdram_start = bdata->node_min_pfn << PAGE_SHIFT; ++ sdram_size = (bdata->node_low_pfn << PAGE_SHIFT) - sdram_start; ++ ++ if (paddr) { ++ if ((paddr & ~PAGE_MASK) || paddr < sdram_start || ++ paddr + size > sdram_start + sdram_size) { ++ pr_err("Illegal SDRAM region for VRAM\n"); ++ return; ++ } ++ ++ if (reserve_bootmem(paddr, size, BOOTMEM_EXCLUSIVE) < 0) { ++ pr_err("FB: failed to reserve VRAM\n"); ++ return; ++ } ++ } else { ++ if (size > sdram_size) { ++ pr_err("Illegal SDRAM size for VRAM\n"); ++ return; ++ } ++ ++ paddr = virt_to_phys(alloc_bootmem_pages(size)); ++ BUG_ON(paddr & ~PAGE_MASK); ++ } ++ ++ omap_vram_add_region(paddr, size); ++ ++ pr_info("Reserving %u bytes SDRAM for VRAM\n", size); ++} ++ ++/* ++ * Called at sram init time, before anything is pushed to the SRAM stack. ++ * Because of the stack scheme, we will allocate everything from the ++ * start of the lowest address region to the end of SRAM. This will also ++ * include padding for page alignment and possible holes between regions. ++ * ++ * As opposed to the SDRAM case, we'll also do any dynamic allocations at ++ * this point, since the driver built as a module would have problem with ++ * freeing / reallocating the regions. ++ */ ++unsigned long __init omap_vram_reserve_sram(unsigned long sram_pstart, ++ unsigned long sram_vstart, ++ unsigned long sram_size, ++ unsigned long pstart_avail, ++ unsigned long size_avail) ++{ ++ unsigned long pend_avail; ++ unsigned long reserved; ++ u32 paddr; ++ u32 size; ++ ++ paddr = omap_vram_sram_start; ++ size = omap_vram_sram_size; ++ ++ if (!size) ++ return 0; ++ ++ reserved = 0; ++ pend_avail = pstart_avail + size_avail; ++ ++ if (!paddr) { ++ /* Dynamic allocation */ ++ if ((size_avail & PAGE_MASK) < size) { ++ pr_err("Not enough SRAM for VRAM\n"); ++ return 0; ++ } ++ size_avail = (size_avail - size) & PAGE_MASK; ++ paddr = pstart_avail + size_avail; ++ } ++ ++ if (paddr < sram_pstart || ++ paddr + size > sram_pstart + sram_size) { ++ pr_err("Illegal SRAM region for VRAM\n"); ++ return 0; ++ } ++ ++ /* Reserve everything above the start of the region. */ ++ if (pend_avail - paddr > reserved) ++ reserved = pend_avail - paddr; ++ size_avail = pend_avail - reserved - pstart_avail; ++ ++ omap_vram_add_region(paddr, size); ++ ++ if (reserved) ++ pr_info("Reserving %lu bytes SRAM for VRAM\n", reserved); ++ ++ return reserved; ++} ++ ++void __init omap_vram_set_sdram_vram(u32 size, u32 start) ++{ ++ omap_vram_sdram_start = start; ++ omap_vram_sdram_size = size; ++} ++ ++void __init omap_vram_set_sram_vram(u32 size, u32 start) ++{ ++ omap_vram_sram_start = start; ++ omap_vram_sram_size = size; ++} +diff --git a/drivers/video/omap2/vrfb.c b/drivers/video/omap2/vrfb.c +new file mode 100644 +index 0000000..8726689 +--- /dev/null ++++ b/drivers/video/omap2/vrfb.c +@@ -0,0 +1,277 @@ ++/* ++ * VRFB Rotation Engine ++ * ++ * Copyright (C) 2009 Nokia Corporation ++ * Author: Tomi Valkeinen ++ * ++ * 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. ++ * ++ * 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, MA 02111-1307, USA. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++/*#define DEBUG*/ ++ ++#ifdef DEBUG ++#define DBG(format, ...) pr_debug("VRFB: " format, ## __VA_ARGS__) ++#else ++#define DBG(format, ...) ++#endif ++ ++#define SMS_ROT_VIRT_BASE(context, rot) \ ++ (((context >= 4) ? 0xD0000000 : 0x70000000) \ ++ + (0x4000000 * (context)) \ ++ + (0x1000000 * (rot))) ++ ++#define OMAP_VRFB_SIZE (2048 * 2048 * 4) ++ ++#define VRFB_PAGE_WIDTH_EXP 5 /* Assuming SDRAM pagesize= 1024 */ ++#define VRFB_PAGE_HEIGHT_EXP 5 /* 1024 = 2^5 * 2^5 */ ++#define VRFB_PAGE_WIDTH (1 << VRFB_PAGE_WIDTH_EXP) ++#define VRFB_PAGE_HEIGHT (1 << VRFB_PAGE_HEIGHT_EXP) ++#define SMS_IMAGEHEIGHT_OFFSET 16 ++#define SMS_IMAGEWIDTH_OFFSET 0 ++#define SMS_PH_OFFSET 8 ++#define SMS_PW_OFFSET 4 ++#define SMS_PS_OFFSET 0 ++ ++#define VRFB_NUM_CTXS 12 ++/* bitmap of reserved contexts */ ++static unsigned long ctx_map; ++/* bitmap of contexts for which we have to keep the HW context valid */ ++static unsigned long ctx_map_active; ++ ++static DEFINE_MUTEX(ctx_lock); ++ ++/* ++ * Access to this happens from client drivers or the PM core after wake-up. ++ * For the first case we require locking at the driver level, for the second ++ * we don't need locking, since no drivers will run until after the wake-up ++ * has finished. ++ */ ++static struct { ++ u32 physical_ba; ++ u32 control; ++ u32 size; ++} vrfb_hw_context[VRFB_NUM_CTXS]; ++ ++static inline void restore_hw_context(int ctx) ++{ ++ omap2_sms_write_rot_control(vrfb_hw_context[ctx].control, ctx); ++ omap2_sms_write_rot_size(vrfb_hw_context[ctx].size, ctx); ++ omap2_sms_write_rot_physical_ba(vrfb_hw_context[ctx].physical_ba, ctx); ++} ++ ++void omap_vrfb_restore_context(void) ++{ ++ int i; ++ unsigned long map = ctx_map_active; ++ ++ for (i = ffs(map); i; i = ffs(map)) { ++ /* i=1..32 */ ++ i--; ++ map &= ~(1 << i); ++ restore_hw_context(i); ++ } ++} ++ ++void omap_vrfb_adjust_size(u16 *width, u16 *height, ++ u8 bytespp) ++{ ++ *width = ALIGN(*width * bytespp, VRFB_PAGE_WIDTH) / bytespp; ++ *height = ALIGN(*height, VRFB_PAGE_HEIGHT); ++} ++EXPORT_SYMBOL(omap_vrfb_adjust_size); ++ ++void omap_vrfb_setup(struct vrfb *vrfb, unsigned long paddr, ++ u16 width, u16 height, ++ unsigned bytespp, bool yuv_mode) ++{ ++ unsigned pixel_size_exp; ++ u16 vrfb_width; ++ u16 vrfb_height; ++ u8 ctx = vrfb->context; ++ u32 size; ++ u32 control; ++ ++ DBG("omapfb_set_vrfb(%d, %lx, %dx%d, %d)\n", ctx, paddr, ++ width, height, color_mode); ++ ++ /* For YUV2 and UYVY modes VRFB needs to handle pixels a bit ++ * differently. See TRM. */ ++ if (yuv_mode) { ++ bytespp *= 2; ++ width /= 2; ++ } ++ ++ if (bytespp == 4) ++ pixel_size_exp = 2; ++ else if (bytespp == 2) ++ pixel_size_exp = 1; ++ else ++ BUG(); ++ ++ vrfb_width = ALIGN(width * bytespp, VRFB_PAGE_WIDTH) / bytespp; ++ vrfb_height = ALIGN(height, VRFB_PAGE_HEIGHT); ++ ++ DBG("vrfb w %u, h %u bytespp %d\n", vrfb_width, vrfb_height, bytespp); ++ ++ size = vrfb_width << SMS_IMAGEWIDTH_OFFSET; ++ size |= vrfb_height << SMS_IMAGEHEIGHT_OFFSET; ++ ++ control = pixel_size_exp << SMS_PS_OFFSET; ++ control |= VRFB_PAGE_WIDTH_EXP << SMS_PW_OFFSET; ++ control |= VRFB_PAGE_HEIGHT_EXP << SMS_PH_OFFSET; ++ ++ vrfb_hw_context[ctx].physical_ba = paddr; ++ vrfb_hw_context[ctx].size = size; ++ vrfb_hw_context[ctx].control = control; ++ ++ omap2_sms_write_rot_physical_ba(paddr, ctx); ++ omap2_sms_write_rot_size(size, ctx); ++ omap2_sms_write_rot_control(control, ctx); ++ ++ DBG("vrfb offset pixels %d, %d\n", ++ vrfb_width - width, vrfb_height - height); ++ ++ vrfb->xoffset = vrfb_width - width; ++ vrfb->yoffset = vrfb_height - height; ++ vrfb->bytespp = bytespp; ++} ++EXPORT_SYMBOL(omap_vrfb_setup); ++ ++void omap_vrfb_release_ctx(struct vrfb *vrfb) ++{ ++ int rot; ++ int ctx = vrfb->context; ++ ++ if (ctx == 0xff) ++ return; ++ ++ DBG("release ctx %d\n", ctx); ++ ++ mutex_lock(&ctx_lock); ++ ++ BUG_ON(!(ctx_map & (1 << ctx))); ++ ++ clear_bit(ctx, &ctx_map_active); ++ clear_bit(ctx, &ctx_map); ++ ++ for (rot = 0; rot < 4; ++rot) { ++ if (vrfb->paddr[rot]) { ++ release_mem_region(vrfb->paddr[rot], OMAP_VRFB_SIZE); ++ vrfb->paddr[rot] = 0; ++ } ++ } ++ ++ vrfb->context = 0xff; ++ ++ mutex_unlock(&ctx_lock); ++} ++EXPORT_SYMBOL(omap_vrfb_release_ctx); ++ ++int omap_vrfb_request_ctx(struct vrfb *vrfb) ++{ ++ int rot; ++ u32 paddr; ++ u8 ctx; ++ int r; ++ ++ DBG("request ctx\n"); ++ ++ mutex_lock(&ctx_lock); ++ ++ for (ctx = 0; ctx < VRFB_NUM_CTXS; ++ctx) ++ if ((ctx_map & (1 << ctx)) == 0) ++ break; ++ ++ if (ctx == VRFB_NUM_CTXS) { ++ pr_err("vrfb: no free contexts\n"); ++ r = -EBUSY; ++ goto out; ++ } ++ ++ DBG("found free ctx %d\n", ctx); ++ ++ set_bit(ctx, &ctx_map); ++ WARN_ON(ctx_map_active & (1 << ctx)); ++ set_bit(ctx, &ctx_map_active); ++ ++ memset(vrfb, 0, sizeof(*vrfb)); ++ ++ vrfb->context = ctx; ++ ++ for (rot = 0; rot < 4; ++rot) { ++ paddr = SMS_ROT_VIRT_BASE(ctx, rot); ++ if (!request_mem_region(paddr, OMAP_VRFB_SIZE, "vrfb")) { ++ pr_err("vrfb: failed to reserve VRFB " ++ "area for ctx %d, rotation %d\n", ++ ctx, rot * 90); ++ omap_vrfb_release_ctx(vrfb); ++ r = -ENOMEM; ++ goto out; ++ } ++ ++ vrfb->paddr[rot] = paddr; ++ ++ DBG("VRFB %d/%d: %lx\n", ctx, rot*90, vrfb->paddr[rot]); ++ } ++ ++ r = 0; ++out: ++ mutex_unlock(&ctx_lock); ++ return r; ++} ++EXPORT_SYMBOL(omap_vrfb_request_ctx); ++ ++void omap_vrfb_suspend_ctx(struct vrfb *vrfb) ++{ ++ DBG("suspend ctx %d\n", vrfb->context); ++ mutex_lock(&ctx_lock); ++ ++ BUG_ON(vrfb->context >= VRFB_NUM_CTXS); ++ BUG_ON(!((1 << vrfb->context) & ctx_map_active)); ++ ++ clear_bit(vrfb->context, &ctx_map_active); ++ mutex_unlock(&ctx_lock); ++} ++EXPORT_SYMBOL(omap_vrfb_suspend_ctx); ++ ++void omap_vrfb_resume_ctx(struct vrfb *vrfb) ++{ ++ DBG("resume ctx %d\n", vrfb->context); ++ mutex_lock(&ctx_lock); ++ ++ BUG_ON(vrfb->context >= VRFB_NUM_CTXS); ++ BUG_ON((1 << vrfb->context) & ctx_map_active); ++ ++ /* ++ * omap_vrfb_restore_context is normally called by the core domain ++ * save / restore logic, but since this VRFB context was suspended ++ * those calls didn't actually restore the context and now we might ++ * have an invalid context. Do an explicit restore here. ++ */ ++ restore_hw_context(vrfb->context); ++ set_bit(vrfb->context, &ctx_map_active); ++ mutex_unlock(&ctx_lock); ++} ++EXPORT_SYMBOL(omap_vrfb_resume_ctx); ++ +diff --git a/include/linux/omapfb.h b/include/linux/omapfb.h +new file mode 100644 +index 0000000..52e0987 +--- /dev/null ++++ b/include/linux/omapfb.h +@@ -0,0 +1,242 @@ ++/* ++ * File: include/linux/omapfb.h ++ * ++ * Framebuffer driver for TI OMAP boards ++ * ++ * Copyright (C) 2004 Nokia Corporation ++ * Author: Imre Deak ++ * ++ * 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, MA 02111-1307, USA. ++ */ ++ ++#ifndef __LINUX_OMAPFB_H__ ++#define __LINUX_OMAPFB_H__ ++ ++#include ++#include ++#include ++ ++/* IOCTL commands. */ ++ ++#define OMAP_IOW(num, dtype) _IOW('O', num, dtype) ++#define OMAP_IOR(num, dtype) _IOR('O', num, dtype) ++#define OMAP_IOWR(num, dtype) _IOWR('O', num, dtype) ++#define OMAP_IO(num) _IO('O', num) ++ ++#define OMAPFB_MIRROR OMAP_IOW(31, int) ++#define OMAPFB_SYNC_GFX OMAP_IO(37) ++#define OMAPFB_VSYNC OMAP_IO(38) ++#define OMAPFB_SET_UPDATE_MODE OMAP_IOW(40, int) ++#define OMAPFB_GET_CAPS OMAP_IOR(42, struct omapfb_caps) ++#define OMAPFB_GET_UPDATE_MODE OMAP_IOW(43, int) ++#define OMAPFB_LCD_TEST OMAP_IOW(45, int) ++#define OMAPFB_CTRL_TEST OMAP_IOW(46, int) ++#define OMAPFB_UPDATE_WINDOW_OLD OMAP_IOW(47, struct omapfb_update_window_old) ++#define OMAPFB_SET_COLOR_KEY OMAP_IOW(50, struct omapfb_color_key) ++#define OMAPFB_GET_COLOR_KEY OMAP_IOW(51, struct omapfb_color_key) ++#define OMAPFB_SETUP_PLANE OMAP_IOW(52, struct omapfb_plane_info) ++#define OMAPFB_QUERY_PLANE OMAP_IOW(53, struct omapfb_plane_info) ++#define OMAPFB_UPDATE_WINDOW OMAP_IOW(54, struct omapfb_update_window) ++#define OMAPFB_SETUP_MEM OMAP_IOW(55, struct omapfb_mem_info) ++#define OMAPFB_QUERY_MEM OMAP_IOW(56, struct omapfb_mem_info) ++#define OMAPFB_WAITFORVSYNC OMAP_IO(57) ++#define OMAPFB_MEMORY_READ OMAP_IOR(58, struct omapfb_memory_read) ++#define OMAPFB_GET_OVERLAY_COLORMODE OMAP_IOR(59, struct omapfb_ovl_colormode) ++#define OMAPFB_WAITFORGO OMAP_IO(60) ++#define OMAPFB_GET_VRAM_INFO OMAP_IOR(61, struct omapfb_vram_info) ++ ++#define OMAPFB_CAPS_GENERIC_MASK 0x00000fff ++#define OMAPFB_CAPS_LCDC_MASK 0x00fff000 ++#define OMAPFB_CAPS_PANEL_MASK 0xff000000 ++ ++#define OMAPFB_CAPS_MANUAL_UPDATE 0x00001000 ++#define OMAPFB_CAPS_TEARSYNC 0x00002000 ++#define OMAPFB_CAPS_PLANE_RELOCATE_MEM 0x00004000 ++#define OMAPFB_CAPS_PLANE_SCALE 0x00008000 ++#define OMAPFB_CAPS_WINDOW_PIXEL_DOUBLE 0x00010000 ++#define OMAPFB_CAPS_WINDOW_SCALE 0x00020000 ++#define OMAPFB_CAPS_WINDOW_OVERLAY 0x00040000 ++#define OMAPFB_CAPS_WINDOW_ROTATE 0x00080000 ++#define OMAPFB_CAPS_SET_BACKLIGHT 0x01000000 ++ ++/* Values from DSP must map to lower 16-bits */ ++#define OMAPFB_FORMAT_MASK 0x00ff ++#define OMAPFB_FORMAT_FLAG_DOUBLE 0x0100 ++#define OMAPFB_FORMAT_FLAG_TEARSYNC 0x0200 ++#define OMAPFB_FORMAT_FLAG_FORCE_VSYNC 0x0400 ++#define OMAPFB_FORMAT_FLAG_ENABLE_OVERLAY 0x0800 ++#define OMAPFB_FORMAT_FLAG_DISABLE_OVERLAY 0x1000 ++ ++#define OMAPFB_MEMTYPE_SDRAM 0 ++#define OMAPFB_MEMTYPE_SRAM 1 ++#define OMAPFB_MEMTYPE_MAX 1 ++ ++enum omapfb_color_format { ++ OMAPFB_COLOR_RGB565 = 0, ++ OMAPFB_COLOR_YUV422, ++ OMAPFB_COLOR_YUV420, ++ OMAPFB_COLOR_CLUT_8BPP, ++ OMAPFB_COLOR_CLUT_4BPP, ++ OMAPFB_COLOR_CLUT_2BPP, ++ OMAPFB_COLOR_CLUT_1BPP, ++ OMAPFB_COLOR_RGB444, ++ OMAPFB_COLOR_YUY422, ++ ++ OMAPFB_COLOR_ARGB16, ++ OMAPFB_COLOR_RGB24U, /* RGB24, 32-bit container */ ++ OMAPFB_COLOR_RGB24P, /* RGB24, 24-bit container */ ++ OMAPFB_COLOR_ARGB32, ++ OMAPFB_COLOR_RGBA32, ++ OMAPFB_COLOR_RGBX32, ++}; ++ ++struct omapfb_update_window { ++ __u32 x, y; ++ __u32 width, height; ++ __u32 format; ++ __u32 out_x, out_y; ++ __u32 out_width, out_height; ++ __u32 reserved[8]; ++}; ++ ++struct omapfb_update_window_old { ++ __u32 x, y; ++ __u32 width, height; ++ __u32 format; ++}; ++ ++enum omapfb_plane { ++ OMAPFB_PLANE_GFX = 0, ++ OMAPFB_PLANE_VID1, ++ OMAPFB_PLANE_VID2, ++}; ++ ++enum omapfb_channel_out { ++ OMAPFB_CHANNEL_OUT_LCD = 0, ++ OMAPFB_CHANNEL_OUT_DIGIT, ++}; ++ ++struct omapfb_plane_info { ++ __u32 pos_x; ++ __u32 pos_y; ++ __u8 enabled; ++ __u8 channel_out; ++ __u8 mirror; ++ __u8 reserved1; ++ __u32 out_width; ++ __u32 out_height; ++ __u32 reserved2[12]; ++}; ++ ++struct omapfb_mem_info { ++ __u32 size; ++ __u8 type; ++ __u8 reserved[3]; ++}; ++ ++struct omapfb_caps { ++ __u32 ctrl; ++ __u32 plane_color; ++ __u32 wnd_color; ++}; ++ ++enum omapfb_color_key_type { ++ OMAPFB_COLOR_KEY_DISABLED = 0, ++ OMAPFB_COLOR_KEY_GFX_DST, ++ OMAPFB_COLOR_KEY_VID_SRC, ++}; ++ ++struct omapfb_color_key { ++ __u8 channel_out; ++ __u32 background; ++ __u32 trans_key; ++ __u8 key_type; ++}; ++ ++enum omapfb_update_mode { ++ OMAPFB_UPDATE_DISABLED = 0, ++ OMAPFB_AUTO_UPDATE, ++ OMAPFB_MANUAL_UPDATE ++}; ++ ++struct omapfb_memory_read { ++ __u16 x; ++ __u16 y; ++ __u16 w; ++ __u16 h; ++ size_t buffer_size; ++ void __user *buffer; ++}; ++ ++struct omapfb_ovl_colormode { ++ __u8 overlay_idx; ++ __u8 mode_idx; ++ __u32 bits_per_pixel; ++ __u32 nonstd; ++ struct fb_bitfield red; ++ struct fb_bitfield green; ++ struct fb_bitfield blue; ++ struct fb_bitfield transp; ++}; ++ ++struct omapfb_vram_info { ++ __u32 total; ++ __u32 free; ++ __u32 largest_free_block; ++ __u32 reserved[5]; ++}; ++ ++#ifdef __KERNEL__ ++ ++#include ++ ++#ifdef CONFIG_ARCH_OMAP1 ++#define OMAPFB_PLANE_NUM 1 ++#else ++#define OMAPFB_PLANE_NUM 3 ++#endif ++ ++struct omapfb_mem_region { ++ u32 paddr; ++ void __iomem *vaddr; ++ unsigned long size; ++ u8 type; /* OMAPFB_PLANE_MEM_* */ ++ enum omapfb_color_format format;/* OMAPFB_COLOR_* */ ++ unsigned format_used:1; /* Must be set when format is set. ++ * Needed b/c of the badly chosen 0 ++ * base for OMAPFB_COLOR_* values ++ */ ++ unsigned alloc:1; /* allocated by the driver */ ++ unsigned map:1; /* kernel mapped by the driver */ ++}; ++ ++struct omapfb_mem_desc { ++ int region_cnt; ++ struct omapfb_mem_region region[OMAPFB_PLANE_NUM]; ++}; ++ ++struct omapfb_platform_data { ++ struct omap_lcd_config lcd; ++ struct omapfb_mem_desc mem_desc; ++ void *ctrl_platform_data; ++}; ++ ++/* in arch/arm/plat-omap/fb.c */ ++extern void omapfb_set_ctrl_platform_data(void *pdata); ++extern void omapfb_reserve_sdram(void); ++ ++#endif ++ ++#endif /* __OMAPFB_H */ diff --git a/target/linux/omap35xx/patches-2.6.32/002-OMAP.patch b/target/linux/omap35xx/patches-2.6.32/002-OMAP.patch new file mode 100644 index 000000000..925d7a869 --- /dev/null +++ b/target/linux/omap35xx/patches-2.6.32/002-OMAP.patch @@ -0,0 +1,9839 @@ +diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig +index 1c4119c..e861e32 100644 +--- a/arch/arm/Kconfig ++++ b/arch/arm/Kconfig +@@ -1508,6 +1508,10 @@ source "net/Kconfig" + + source "drivers/Kconfig" + ++if ARCH_OMAP ++source "drivers/cbus/Kconfig" ++endif ++ + source "fs/Kconfig" + + source "arch/arm/Kconfig.debug" +diff --git a/arch/arm/configs/n8x0_defconfig b/arch/arm/configs/n8x0_defconfig +index 8da75de..264f52b 100644 +--- a/arch/arm/configs/n8x0_defconfig ++++ b/arch/arm/configs/n8x0_defconfig +@@ -304,7 +304,7 @@ CONFIG_ALIGNMENT_TRAP=y + CONFIG_ZBOOT_ROM_TEXT=0x10C08000 + CONFIG_ZBOOT_ROM_BSS=0x10200000 + # CONFIG_ZBOOT_ROM is not set +-CONFIG_CMDLINE="root=1f03 rootfstype=jffs2 console=ttyS0,115200n8" ++CONFIG_CMDLINE="root=1f03 rootfstype=jffs2 console=ttyS2,115200n8" + # CONFIG_XIP_KERNEL is not set + # CONFIG_KEXEC is not set + +diff --git a/arch/arm/mach-omap1/board-fsample.c b/arch/arm/mach-omap1/board-fsample.c +index a7ead1b..74720e6 100644 +--- a/arch/arm/mach-omap1/board-fsample.c ++++ b/arch/arm/mach-omap1/board-fsample.c +@@ -107,7 +107,7 @@ static struct resource smc91x_resources[] = { + .flags = IORESOURCE_MEM, + }, + [1] = { +- .start = INT_730_MPU_EXT_NIRQ, ++ .start = INT_7XX_MPU_EXT_NIRQ, + .end = 0, + .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE, + }, +@@ -196,8 +196,8 @@ static struct platform_device smc91x_device = { + + static struct resource kp_resources[] = { + [0] = { +- .start = INT_730_MPUIO_KEYPAD, +- .end = INT_730_MPUIO_KEYPAD, ++ .start = INT_7XX_MPUIO_KEYPAD, ++ .end = INT_7XX_MPUIO_KEYPAD, + .flags = IORESOURCE_IRQ, + }, + }; +@@ -309,7 +309,7 @@ static void __init omap_fsample_map_io(void) + /* + * Hold GSM Reset until needed + */ +- omap_writew(omap_readw(OMAP730_DSP_M_CTL) & ~1, OMAP730_DSP_M_CTL); ++ omap_writew(omap_readw(OMAP7XX_DSP_M_CTL) & ~1, OMAP7XX_DSP_M_CTL); + + /* + * UARTs -> done automagically by 8250 driver +@@ -320,21 +320,21 @@ static void __init omap_fsample_map_io(void) + */ + + /* Flash: CS0 timings setup */ +- omap_writel(0x0000fff3, OMAP730_FLASH_CFG_0); +- omap_writel(0x00000088, OMAP730_FLASH_ACFG_0); ++ omap_writel(0x0000fff3, OMAP7XX_FLASH_CFG_0); ++ omap_writel(0x00000088, OMAP7XX_FLASH_ACFG_0); + + /* + * Ethernet support through the debug board + * CS1 timings setup + */ +- omap_writel(0x0000fff3, OMAP730_FLASH_CFG_1); +- omap_writel(0x00000000, OMAP730_FLASH_ACFG_1); ++ omap_writel(0x0000fff3, OMAP7XX_FLASH_CFG_1); ++ omap_writel(0x00000000, OMAP7XX_FLASH_ACFG_1); + + /* + * Configure MPU_EXT_NIRQ IO in IO_CONF9 register, + * It is used as the Ethernet controller interrupt + */ +- omap_writel(omap_readl(OMAP730_IO_CONF_9) & 0x1FFFFFFF, OMAP730_IO_CONF_9); ++ omap_writel(omap_readl(OMAP7XX_IO_CONF_9) & 0x1FFFFFFF, OMAP7XX_IO_CONF_9); + } + + MACHINE_START(OMAP_FSAMPLE, "OMAP730 F-Sample") +diff --git a/arch/arm/mach-omap1/board-perseus2.c b/arch/arm/mach-omap1/board-perseus2.c +index 8340669..2f897cf 100644 +--- a/arch/arm/mach-omap1/board-perseus2.c ++++ b/arch/arm/mach-omap1/board-perseus2.c +@@ -74,7 +74,7 @@ static struct resource smc91x_resources[] = { + .flags = IORESOURCE_MEM, + }, + [1] = { +- .start = INT_730_MPU_EXT_NIRQ, ++ .start = INT_7XX_MPU_EXT_NIRQ, + .end = 0, + .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE, + }, +@@ -163,8 +163,8 @@ static struct platform_device smc91x_device = { + + static struct resource kp_resources[] = { + [0] = { +- .start = INT_730_MPUIO_KEYPAD, +- .end = INT_730_MPUIO_KEYPAD, ++ .start = INT_7XX_MPUIO_KEYPAD, ++ .end = INT_7XX_MPUIO_KEYPAD, + .flags = IORESOURCE_IRQ, + }, + }; +@@ -270,7 +270,7 @@ static void __init omap_perseus2_map_io(void) + /* + * Hold GSM Reset until needed + */ +- omap_writew(omap_readw(OMAP730_DSP_M_CTL) & ~1, OMAP730_DSP_M_CTL); ++ omap_writew(omap_readw(OMAP7XX_DSP_M_CTL) & ~1, OMAP7XX_DSP_M_CTL); + + /* + * UARTs -> done automagically by 8250 driver +@@ -281,21 +281,21 @@ static void __init omap_perseus2_map_io(void) + */ + + /* Flash: CS0 timings setup */ +- omap_writel(0x0000fff3, OMAP730_FLASH_CFG_0); +- omap_writel(0x00000088, OMAP730_FLASH_ACFG_0); ++ omap_writel(0x0000fff3, OMAP7XX_FLASH_CFG_0); ++ omap_writel(0x00000088, OMAP7XX_FLASH_ACFG_0); + + /* + * Ethernet support through the debug board + * CS1 timings setup + */ +- omap_writel(0x0000fff3, OMAP730_FLASH_CFG_1); +- omap_writel(0x00000000, OMAP730_FLASH_ACFG_1); ++ omap_writel(0x0000fff3, OMAP7XX_FLASH_CFG_1); ++ omap_writel(0x00000000, OMAP7XX_FLASH_ACFG_1); + + /* + * Configure MPU_EXT_NIRQ IO in IO_CONF9 register, + * It is used as the Ethernet controller interrupt + */ +- omap_writel(omap_readl(OMAP730_IO_CONF_9) & 0x1FFFFFFF, OMAP730_IO_CONF_9); ++ omap_writel(omap_readl(OMAP7XX_IO_CONF_9) & 0x1FFFFFFF, OMAP7XX_IO_CONF_9); + } + + MACHINE_START(OMAP_PERSEUS2, "OMAP730 Perseus2") +diff --git a/arch/arm/mach-omap1/clock.c b/arch/arm/mach-omap1/clock.c +index 436eed2..5f77b83 100644 +--- a/arch/arm/mach-omap1/clock.c ++++ b/arch/arm/mach-omap1/clock.c +@@ -69,13 +69,13 @@ struct omap_clk { + } + + #define CK_310 (1 << 0) +-#define CK_730 (1 << 1) ++#define CK_7XX (1 << 1) + #define CK_1510 (1 << 2) + #define CK_16XX (1 << 3) + + static struct omap_clk omap_clks[] = { + /* non-ULPD clocks */ +- CLK(NULL, "ck_ref", &ck_ref, CK_16XX | CK_1510 | CK_310), ++ CLK(NULL, "ck_ref", &ck_ref, CK_16XX | CK_1510 | CK_310 | CK_7XX), + CLK(NULL, "ck_dpll1", &ck_dpll1, CK_16XX | CK_1510 | CK_310), + /* CK_GEN1 clocks */ + CLK(NULL, "ck_dpll1out", &ck_dpll1out.clk, CK_16XX), +@@ -83,7 +83,7 @@ static struct omap_clk omap_clks[] = { + CLK(NULL, "arm_ck", &arm_ck, CK_16XX | CK_1510 | CK_310), + CLK(NULL, "armper_ck", &armper_ck.clk, CK_16XX | CK_1510 | CK_310), + CLK(NULL, "arm_gpio_ck", &arm_gpio_ck, CK_1510 | CK_310), +- CLK(NULL, "armxor_ck", &armxor_ck.clk, CK_16XX | CK_1510 | CK_310), ++ CLK(NULL, "armxor_ck", &armxor_ck.clk, CK_16XX | CK_1510 | CK_310 | CK_7XX), + CLK(NULL, "armtim_ck", &armtim_ck.clk, CK_16XX | CK_1510 | CK_310), + CLK("omap_wdt", "fck", &armwdt_ck.clk, CK_16XX | CK_1510 | CK_310), + CLK("omap_wdt", "ick", &armper_ck.clk, CK_16XX), +@@ -97,7 +97,7 @@ static struct omap_clk omap_clks[] = { + CLK(NULL, "dspxor_ck", &dspxor_ck, CK_16XX | CK_1510 | CK_310), + CLK(NULL, "dsptim_ck", &dsptim_ck, CK_16XX | CK_1510 | CK_310), + /* CK_GEN3 clocks */ +- CLK(NULL, "tc_ck", &tc_ck.clk, CK_16XX | CK_1510 | CK_310 | CK_730), ++ CLK(NULL, "tc_ck", &tc_ck.clk, CK_16XX | CK_1510 | CK_310 | CK_7XX), + CLK(NULL, "tipb_ck", &tipb_ck, CK_1510 | CK_310), + CLK(NULL, "l3_ocpi_ck", &l3_ocpi_ck, CK_16XX), + CLK(NULL, "tc1_ck", &tc1_ck, CK_16XX), +@@ -108,7 +108,7 @@ static struct omap_clk omap_clks[] = { + CLK(NULL, "lb_ck", &lb_ck.clk, CK_1510 | CK_310), + CLK(NULL, "rhea1_ck", &rhea1_ck, CK_16XX), + CLK(NULL, "rhea2_ck", &rhea2_ck, CK_16XX), +- CLK(NULL, "lcd_ck", &lcd_ck_16xx, CK_16XX | CK_730), ++ CLK(NULL, "lcd_ck", &lcd_ck_16xx, CK_16XX | CK_7XX), + CLK(NULL, "lcd_ck", &lcd_ck_1510.clk, CK_1510 | CK_310), + /* ULPD clocks */ + CLK(NULL, "uart1_ck", &uart1_1510, CK_1510 | CK_310), +@@ -398,7 +398,7 @@ static int omap1_select_table_rate(struct clk * clk, unsigned long rate) + * Reprogramming the DPLL is tricky, it must be done from SRAM. + * (on 730, bit 13 must always be 1) + */ +- if (cpu_is_omap730()) ++ if (cpu_is_omap7xx()) + omap_sram_reprogram_clock(ptr->dpllctl_val, ptr->ckctl_val | 0x2000); + else + omap_sram_reprogram_clock(ptr->dpllctl_val, ptr->ckctl_val); +@@ -783,8 +783,8 @@ int __init omap1_clk_init(void) + cpu_mask |= CK_16XX; + if (cpu_is_omap1510()) + cpu_mask |= CK_1510; +- if (cpu_is_omap730()) +- cpu_mask |= CK_730; ++ if (cpu_is_omap7xx()) ++ cpu_mask |= CK_7XX; + if (cpu_is_omap310()) + cpu_mask |= CK_310; + +@@ -800,7 +800,7 @@ int __init omap1_clk_init(void) + crystal_type = info->system_clock_type; + } + +-#if defined(CONFIG_ARCH_OMAP730) ++#if defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850) + ck_ref.rate = 13000000; + #elif defined(CONFIG_ARCH_OMAP16XX) + if (crystal_type == 2) +@@ -847,7 +847,7 @@ int __init omap1_clk_init(void) + printk(KERN_ERR "System frequencies not set. Check your config.\n"); + /* Guess sane values (60MHz) */ + omap_writew(0x2290, DPLL_CTL); +- omap_writew(cpu_is_omap730() ? 0x3005 : 0x1005, ARM_CKCTL); ++ omap_writew(cpu_is_omap7xx() ? 0x3005 : 0x1005, ARM_CKCTL); + ck_dpll1.rate = 60000000; + } + #endif +@@ -862,7 +862,7 @@ int __init omap1_clk_init(void) + + #if defined(CONFIG_MACH_OMAP_PERSEUS2) || defined(CONFIG_MACH_OMAP_FSAMPLE) + /* Select slicer output as OMAP input clock */ +- omap_writew(omap_readw(OMAP730_PCC_UPLD_CTRL) & ~0x1, OMAP730_PCC_UPLD_CTRL); ++ omap_writew(omap_readw(OMAP7XX_PCC_UPLD_CTRL) & ~0x1, OMAP7XX_PCC_UPLD_CTRL); + #endif + + /* Amstrad Delta wants BCLK high when inactive */ +@@ -873,7 +873,7 @@ int __init omap1_clk_init(void) + + /* Turn off DSP and ARM_TIMXO. Make sure ARM_INTHCK is not divided */ + /* (on 730, bit 13 must not be cleared) */ +- if (cpu_is_omap730()) ++ if (cpu_is_omap7xx()) + omap_writew(omap_readw(ARM_CKCTL) & 0x2fff, ARM_CKCTL); + else + omap_writew(omap_readw(ARM_CKCTL) & 0x0fff, ARM_CKCTL); +diff --git a/arch/arm/mach-omap1/io.c b/arch/arm/mach-omap1/io.c +index 7030f92..a27df2c 100644 +--- a/arch/arm/mach-omap1/io.c ++++ b/arch/arm/mach-omap1/io.c +@@ -36,33 +36,17 @@ static struct map_desc omap_io_desc[] __initdata = { + } + }; + +-#ifdef CONFIG_ARCH_OMAP730 +-static struct map_desc omap730_io_desc[] __initdata = { ++#if defined (CONFIG_ARCH_OMAP730) || defined (CONFIG_ARCH_OMAP850) ++static struct map_desc omap7xx_io_desc[] __initdata = { + { +- .virtual = OMAP730_DSP_BASE, +- .pfn = __phys_to_pfn(OMAP730_DSP_START), +- .length = OMAP730_DSP_SIZE, ++ .virtual = OMAP7XX_DSP_BASE, ++ .pfn = __phys_to_pfn(OMAP7XX_DSP_START), ++ .length = OMAP7XX_DSP_SIZE, + .type = MT_DEVICE + }, { +- .virtual = OMAP730_DSPREG_BASE, +- .pfn = __phys_to_pfn(OMAP730_DSPREG_START), +- .length = OMAP730_DSPREG_SIZE, +- .type = MT_DEVICE +- } +-}; +-#endif +- +-#ifdef CONFIG_ARCH_OMAP850 +-static struct map_desc omap850_io_desc[] __initdata = { +- { +- .virtual = OMAP850_DSP_BASE, +- .pfn = __phys_to_pfn(OMAP850_DSP_START), +- .length = OMAP850_DSP_SIZE, +- .type = MT_DEVICE +- }, { +- .virtual = OMAP850_DSPREG_BASE, +- .pfn = __phys_to_pfn(OMAP850_DSPREG_START), +- .length = OMAP850_DSPREG_SIZE, ++ .virtual = OMAP7XX_DSPREG_BASE, ++ .pfn = __phys_to_pfn(OMAP7XX_DSPREG_START), ++ .length = OMAP7XX_DSPREG_SIZE, + .type = MT_DEVICE + } + }; +@@ -120,18 +104,11 @@ void __init omap1_map_common_io(void) + */ + omap_check_revision(); + +-#ifdef CONFIG_ARCH_OMAP730 +- if (cpu_is_omap730()) { +- iotable_init(omap730_io_desc, ARRAY_SIZE(omap730_io_desc)); +- } +-#endif +- +-#ifdef CONFIG_ARCH_OMAP850 +- if (cpu_is_omap850()) { +- iotable_init(omap850_io_desc, ARRAY_SIZE(omap850_io_desc)); ++#if defined (CONFIG_ARCH_OMAP730) || defined (CONFIG_ARCH_OMAP850) ++ if (cpu_is_omap7xx()) { ++ iotable_init(omap7xx_io_desc, ARRAY_SIZE(omap7xx_io_desc)); + } + #endif +- + #ifdef CONFIG_ARCH_OMAP15XX + if (cpu_is_omap15xx()) { + iotable_init(omap1510_io_desc, ARRAY_SIZE(omap1510_io_desc)); +diff --git a/arch/arm/mach-omap1/irq.c b/arch/arm/mach-omap1/irq.c +index de03c84..8f98b58 100644 +--- a/arch/arm/mach-omap1/irq.c ++++ b/arch/arm/mach-omap1/irq.c +@@ -137,16 +137,8 @@ static void omap_irq_set_cfg(int irq, int fiq, int priority, int trigger) + irq_bank_writel(val, bank, offset); + } + +-#ifdef CONFIG_ARCH_OMAP730 +-static struct omap_irq_bank omap730_irq_banks[] = { +- { .base_reg = OMAP_IH1_BASE, .trigger_map = 0xb3f8e22f }, +- { .base_reg = OMAP_IH2_BASE, .trigger_map = 0xfdb9c1f2 }, +- { .base_reg = OMAP_IH2_BASE + 0x100, .trigger_map = 0x800040f3 }, +-}; +-#endif +- +-#ifdef CONFIG_ARCH_OMAP850 +-static struct omap_irq_bank omap850_irq_banks[] = { ++#if defined (CONFIG_ARCH_OMAP730) || defined (CONFIG_ARCH_OMAP850) ++static struct omap_irq_bank omap7xx_irq_banks[] = { + { .base_reg = OMAP_IH1_BASE, .trigger_map = 0xb3f8e22f }, + { .base_reg = OMAP_IH2_BASE, .trigger_map = 0xfdb9c1f2 }, + { .base_reg = OMAP_IH2_BASE + 0x100, .trigger_map = 0x800040f3 }, +@@ -186,16 +178,10 @@ void __init omap_init_irq(void) + { + int i, j; + +-#ifdef CONFIG_ARCH_OMAP730 +- if (cpu_is_omap730()) { +- irq_banks = omap730_irq_banks; +- irq_bank_count = ARRAY_SIZE(omap730_irq_banks); +- } +-#endif +-#ifdef CONFIG_ARCH_OMAP850 +- if (cpu_is_omap850()) { +- irq_banks = omap850_irq_banks; +- irq_bank_count = ARRAY_SIZE(omap850_irq_banks); ++#if defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850) ++ if (cpu_is_omap7xx()) { ++ irq_banks = omap7xx_irq_banks; ++ irq_bank_count = ARRAY_SIZE(omap7xx_irq_banks); + } + #endif + #ifdef CONFIG_ARCH_OMAP15XX +@@ -247,10 +233,8 @@ void __init omap_init_irq(void) + + /* Unmask level 2 handler */ + +- if (cpu_is_omap730()) +- omap_unmask_irq(INT_730_IH2_IRQ); +- else if (cpu_is_omap850()) +- omap_unmask_irq(INT_850_IH2_IRQ); ++ if (cpu_is_omap7xx()) ++ omap_unmask_irq(INT_7XX_IH2_IRQ); + else if (cpu_is_omap15xx()) + omap_unmask_irq(INT_1510_IH2_IRQ); + else if (cpu_is_omap16xx()) +diff --git a/arch/arm/mach-omap1/mcbsp.c b/arch/arm/mach-omap1/mcbsp.c +index 505d98c..3a51cb2 100644 +--- a/arch/arm/mach-omap1/mcbsp.c ++++ b/arch/arm/mach-omap1/mcbsp.c +@@ -79,29 +79,29 @@ static struct omap_mcbsp_ops omap1_mcbsp_ops = { + .free = omap1_mcbsp_free, + }; + +-#ifdef CONFIG_ARCH_OMAP730 +-static struct omap_mcbsp_platform_data omap730_mcbsp_pdata[] = { ++#if defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850) ++static struct omap_mcbsp_platform_data omap7xx_mcbsp_pdata[] = { + { +- .phys_base = OMAP730_MCBSP1_BASE, ++ .phys_base = OMAP7XX_MCBSP1_BASE, + .dma_rx_sync = OMAP_DMA_MCBSP1_RX, + .dma_tx_sync = OMAP_DMA_MCBSP1_TX, +- .rx_irq = INT_730_McBSP1RX, +- .tx_irq = INT_730_McBSP1TX, ++ .rx_irq = INT_7XX_McBSP1RX, ++ .tx_irq = INT_7XX_McBSP1TX, + .ops = &omap1_mcbsp_ops, + }, + { +- .phys_base = OMAP730_MCBSP2_BASE, ++ .phys_base = OMAP7XX_MCBSP2_BASE, + .dma_rx_sync = OMAP_DMA_MCBSP3_RX, + .dma_tx_sync = OMAP_DMA_MCBSP3_TX, +- .rx_irq = INT_730_McBSP2RX, +- .tx_irq = INT_730_McBSP2TX, ++ .rx_irq = INT_7XX_McBSP2RX, ++ .tx_irq = INT_7XX_McBSP2TX, + .ops = &omap1_mcbsp_ops, + }, + }; +-#define OMAP730_MCBSP_PDATA_SZ ARRAY_SIZE(omap730_mcbsp_pdata) ++#define OMAP7XX_MCBSP_PDATA_SZ ARRAY_SIZE(omap7xx_mcbsp_pdata) + #else +-#define omap730_mcbsp_pdata NULL +-#define OMAP730_MCBSP_PDATA_SZ 0 ++#define omap7xx_mcbsp_pdata NULL ++#define OMAP7XX_MCBSP_PDATA_SZ 0 + #endif + + #ifdef CONFIG_ARCH_OMAP15XX +@@ -172,8 +172,8 @@ static struct omap_mcbsp_platform_data omap16xx_mcbsp_pdata[] = { + + int __init omap1_mcbsp_init(void) + { +- if (cpu_is_omap730()) +- omap_mcbsp_count = OMAP730_MCBSP_PDATA_SZ; ++ if (cpu_is_omap7xx()) ++ omap_mcbsp_count = OMAP7XX_MCBSP_PDATA_SZ; + if (cpu_is_omap15xx()) + omap_mcbsp_count = OMAP15XX_MCBSP_PDATA_SZ; + if (cpu_is_omap16xx()) +@@ -184,9 +184,9 @@ int __init omap1_mcbsp_init(void) + if (!mcbsp_ptr) + return -ENOMEM; + +- if (cpu_is_omap730()) +- omap_mcbsp_register_board_cfg(omap730_mcbsp_pdata, +- OMAP730_MCBSP_PDATA_SZ); ++ if (cpu_is_omap7xx()) ++ omap_mcbsp_register_board_cfg(omap7xx_mcbsp_pdata, ++ OMAP7XX_MCBSP_PDATA_SZ); + + if (cpu_is_omap15xx()) + omap_mcbsp_register_board_cfg(omap15xx_mcbsp_pdata, +diff --git a/arch/arm/mach-omap1/mux.c b/arch/arm/mach-omap1/mux.c +index 721e0d9..d59899d 100644 +--- a/arch/arm/mach-omap1/mux.c ++++ b/arch/arm/mach-omap1/mux.c +@@ -35,47 +35,28 @@ + + static struct omap_mux_cfg arch_mux_cfg; + +-#ifdef CONFIG_ARCH_OMAP730 +-static struct pin_config __initdata_or_module omap730_pins[] = { +-MUX_CFG_730("E2_730_KBR0", 12, 21, 0, 20, 1, 0) +-MUX_CFG_730("J7_730_KBR1", 12, 25, 0, 24, 1, 0) +-MUX_CFG_730("E1_730_KBR2", 12, 29, 0, 28, 1, 0) +-MUX_CFG_730("F3_730_KBR3", 13, 1, 0, 0, 1, 0) +-MUX_CFG_730("D2_730_KBR4", 13, 5, 0, 4, 1, 0) +-MUX_CFG_730("C2_730_KBC0", 13, 9, 0, 8, 1, 0) +-MUX_CFG_730("D3_730_KBC1", 13, 13, 0, 12, 1, 0) +-MUX_CFG_730("E4_730_KBC2", 13, 17, 0, 16, 1, 0) +-MUX_CFG_730("F4_730_KBC3", 13, 21, 0, 20, 1, 0) +-MUX_CFG_730("E3_730_KBC4", 13, 25, 0, 24, 1, 0) +- +-MUX_CFG_730("AA17_730_USB_DM", 2, 21, 0, 20, 0, 0) +-MUX_CFG_730("W16_730_USB_PU_EN", 2, 25, 0, 24, 0, 0) +-MUX_CFG_730("W17_730_USB_VBUSI", 2, 29, 0, 28, 0, 0) ++#if defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850) ++static struct pin_config __initdata_or_module omap7xx_pins[] = { ++MUX_CFG_7XX("E2_7XX_KBR0", 12, 21, 0, 20, 1, 0) ++MUX_CFG_7XX("J7_7XX_KBR1", 12, 25, 0, 24, 1, 0) ++MUX_CFG_7XX("E1_7XX_KBR2", 12, 29, 0, 28, 1, 0) ++MUX_CFG_7XX("F3_7XX_KBR3", 13, 1, 0, 0, 1, 0) ++MUX_CFG_7XX("D2_7XX_KBR4", 13, 5, 0, 4, 1, 0) ++MUX_CFG_7XX("C2_7XX_KBC0", 13, 9, 0, 8, 1, 0) ++MUX_CFG_7XX("D3_7XX_KBC1", 13, 13, 0, 12, 1, 0) ++MUX_CFG_7XX("E4_7XX_KBC2", 13, 17, 0, 16, 1, 0) ++MUX_CFG_7XX("F4_7XX_KBC3", 13, 21, 0, 20, 1, 0) ++MUX_CFG_7XX("E3_7XX_KBC4", 13, 25, 0, 24, 1, 0) ++ ++MUX_CFG_7XX("AA17_7XX_USB_DM", 2, 21, 0, 20, 0, 0) ++MUX_CFG_7XX("W16_7XX_USB_PU_EN", 2, 25, 0, 24, 0, 0) ++MUX_CFG_7XX("W17_7XX_USB_VBUSI", 2, 29, 0, 28, 0, 0) + }; +-#define OMAP730_PINS_SZ ARRAY_SIZE(omap730_pins) ++#define OMAP7XX_PINS_SZ ARRAY_SIZE(omap7xx_pins) + #else +-#define omap730_pins NULL +-#define OMAP730_PINS_SZ 0 +-#endif /* CONFIG_ARCH_OMAP730 */ +- +-#ifdef CONFIG_ARCH_OMAP850 +-struct pin_config __initdata_or_module omap850_pins[] = { +-MUX_CFG_850("E2_850_KBR0", 12, 21, 0, 20, 1, 0) +-MUX_CFG_850("J7_850_KBR1", 12, 25, 0, 24, 1, 0) +-MUX_CFG_850("E1_850_KBR2", 12, 29, 0, 28, 1, 0) +-MUX_CFG_850("F3_850_KBR3", 13, 1, 0, 0, 1, 0) +-MUX_CFG_850("D2_850_KBR4", 13, 5, 0, 4, 1, 0) +-MUX_CFG_850("C2_850_KBC0", 13, 9, 0, 8, 1, 0) +-MUX_CFG_850("D3_850_KBC1", 13, 13, 0, 12, 1, 0) +-MUX_CFG_850("E4_850_KBC2", 13, 17, 0, 16, 1, 0) +-MUX_CFG_850("F4_850_KBC3", 13, 21, 0, 20, 1, 0) +-MUX_CFG_850("E3_850_KBC4", 13, 25, 0, 24, 1, 0) +- +-MUX_CFG_850("AA17_850_USB_DM", 2, 21, 0, 20, 0, 0) +-MUX_CFG_850("W16_850_USB_PU_EN", 2, 25, 0, 24, 0, 0) +-MUX_CFG_850("W17_850_USB_VBUSI", 2, 29, 0, 28, 0, 0) +-}; +-#endif ++#define omap7xx_pins NULL ++#define OMAP7XX_PINS_SZ 0 ++#endif /* CONFIG_ARCH_OMAP730 || CONFIG_ARCH_OMAP850 */ + + #if defined(CONFIG_ARCH_OMAP15XX) || defined(CONFIG_ARCH_OMAP16XX) + static struct pin_config __initdata_or_module omap1xxx_pins[] = { +@@ -438,11 +419,6 @@ int __init_or_module omap1_cfg_reg(const struct pin_config *cfg) + printk(" %s (0x%08x) = 0x%08x -> 0x%08x\n", + cfg->pull_name, cfg->pull_reg, pull_orig, pull); + } +- +-#ifdef CONFIG_ARCH_OMAP850 +- omap_mux_register(omap850_pins, ARRAY_SIZE(omap850_pins)); +-#endif +- + #endif + + #ifdef CONFIG_OMAP_MUX_ERRORS +@@ -454,9 +430,9 @@ int __init_or_module omap1_cfg_reg(const struct pin_config *cfg) + + int __init omap1_mux_init(void) + { +- if (cpu_is_omap730()) { +- arch_mux_cfg.pins = omap730_pins; +- arch_mux_cfg.size = OMAP730_PINS_SZ; ++ if (cpu_is_omap7xx()) { ++ arch_mux_cfg.pins = omap7xx_pins; ++ arch_mux_cfg.size = OMAP7XX_PINS_SZ; + arch_mux_cfg.cfg_reg = omap1_cfg_reg; + } + +diff --git a/arch/arm/mach-omap1/pm.c b/arch/arm/mach-omap1/pm.c +index 5218943..10f4e4a 100644 +--- a/arch/arm/mach-omap1/pm.c ++++ b/arch/arm/mach-omap1/pm.c +@@ -62,7 +62,7 @@ + static unsigned int arm_sleep_save[ARM_SLEEP_SAVE_SIZE]; + static unsigned short dsp_sleep_save[DSP_SLEEP_SAVE_SIZE]; + static unsigned short ulpd_sleep_save[ULPD_SLEEP_SAVE_SIZE]; +-static unsigned int mpui730_sleep_save[MPUI730_SLEEP_SAVE_SIZE]; ++static unsigned int mpui7xx_sleep_save[MPUI7XX_SLEEP_SAVE_SIZE]; + static unsigned int mpui1510_sleep_save[MPUI1510_SLEEP_SAVE_SIZE]; + static unsigned int mpui1610_sleep_save[MPUI1610_SLEEP_SAVE_SIZE]; + +@@ -183,9 +183,9 @@ static void omap_pm_wakeup_setup(void) + * drivers must still separately call omap_set_gpio_wakeup() to + * wake up to a GPIO interrupt. + */ +- if (cpu_is_omap730()) +- level1_wake = OMAP_IRQ_BIT(INT_730_GPIO_BANK1) | +- OMAP_IRQ_BIT(INT_730_IH2_IRQ); ++ if (cpu_is_omap7xx()) ++ level1_wake = OMAP_IRQ_BIT(INT_7XX_GPIO_BANK1) | ++ OMAP_IRQ_BIT(INT_7XX_IH2_IRQ); + else if (cpu_is_omap15xx()) + level1_wake = OMAP_IRQ_BIT(INT_GPIO_BANK1) | + OMAP_IRQ_BIT(INT_1510_IH2_IRQ); +@@ -195,10 +195,10 @@ static void omap_pm_wakeup_setup(void) + + omap_writel(~level1_wake, OMAP_IH1_MIR); + +- if (cpu_is_omap730()) { ++ if (cpu_is_omap7xx()) { + omap_writel(~level2_wake, OMAP_IH2_0_MIR); +- omap_writel(~(OMAP_IRQ_BIT(INT_730_WAKE_UP_REQ) | +- OMAP_IRQ_BIT(INT_730_MPUIO_KEYPAD)), ++ omap_writel(~(OMAP_IRQ_BIT(INT_7XX_WAKE_UP_REQ) | ++ OMAP_IRQ_BIT(INT_7XX_MPUIO_KEYPAD)), + OMAP_IH2_1_MIR); + } else if (cpu_is_omap15xx()) { + level2_wake |= OMAP_IRQ_BIT(INT_KEYBOARD); +@@ -253,15 +253,15 @@ void omap1_pm_suspend(void) + * Save interrupt, MPUI, ARM and UPLD control registers. + */ + +- if (cpu_is_omap730()) { +- MPUI730_SAVE(OMAP_IH1_MIR); +- MPUI730_SAVE(OMAP_IH2_0_MIR); +- MPUI730_SAVE(OMAP_IH2_1_MIR); +- MPUI730_SAVE(MPUI_CTRL); +- MPUI730_SAVE(MPUI_DSP_BOOT_CONFIG); +- MPUI730_SAVE(MPUI_DSP_API_CONFIG); +- MPUI730_SAVE(EMIFS_CONFIG); +- MPUI730_SAVE(EMIFF_SDRAM_CONFIG); ++ if (cpu_is_omap7xx()) { ++ MPUI7XX_SAVE(OMAP_IH1_MIR); ++ MPUI7XX_SAVE(OMAP_IH2_0_MIR); ++ MPUI7XX_SAVE(OMAP_IH2_1_MIR); ++ MPUI7XX_SAVE(MPUI_CTRL); ++ MPUI7XX_SAVE(MPUI_DSP_BOOT_CONFIG); ++ MPUI7XX_SAVE(MPUI_DSP_API_CONFIG); ++ MPUI7XX_SAVE(EMIFS_CONFIG); ++ MPUI7XX_SAVE(EMIFF_SDRAM_CONFIG); + + } else if (cpu_is_omap15xx()) { + MPUI1510_SAVE(OMAP_IH1_MIR); +@@ -306,7 +306,7 @@ void omap1_pm_suspend(void) + omap_writew(omap_readw(ARM_RSTCT1) & ~(1 << DSP_EN), ARM_RSTCT1); + + /* shut down dsp_ck */ +- if (!cpu_is_omap730()) ++ if (!cpu_is_omap7xx()) + omap_writew(omap_readw(ARM_CKCTL) & ~(1 << EN_DSPCK), ARM_CKCTL); + + /* temporarily enabling api_ck to access DSP registers */ +@@ -383,12 +383,12 @@ void omap1_pm_suspend(void) + ULPD_RESTORE(ULPD_CLOCK_CTRL); + ULPD_RESTORE(ULPD_STATUS_REQ); + +- if (cpu_is_omap730()) { +- MPUI730_RESTORE(EMIFS_CONFIG); +- MPUI730_RESTORE(EMIFF_SDRAM_CONFIG); +- MPUI730_RESTORE(OMAP_IH1_MIR); +- MPUI730_RESTORE(OMAP_IH2_0_MIR); +- MPUI730_RESTORE(OMAP_IH2_1_MIR); ++ if (cpu_is_omap7xx()) { ++ MPUI7XX_RESTORE(EMIFS_CONFIG); ++ MPUI7XX_RESTORE(EMIFF_SDRAM_CONFIG); ++ MPUI7XX_RESTORE(OMAP_IH1_MIR); ++ MPUI7XX_RESTORE(OMAP_IH2_0_MIR); ++ MPUI7XX_RESTORE(OMAP_IH2_1_MIR); + } else if (cpu_is_omap15xx()) { + MPUI1510_RESTORE(MPUI_CTRL); + MPUI1510_RESTORE(MPUI_DSP_BOOT_CONFIG); +@@ -461,13 +461,13 @@ static int omap_pm_read_proc( + ULPD_SAVE(ULPD_DPLL_CTRL); + ULPD_SAVE(ULPD_POWER_CTRL); + +- if (cpu_is_omap730()) { +- MPUI730_SAVE(MPUI_CTRL); +- MPUI730_SAVE(MPUI_DSP_STATUS); +- MPUI730_SAVE(MPUI_DSP_BOOT_CONFIG); +- MPUI730_SAVE(MPUI_DSP_API_CONFIG); +- MPUI730_SAVE(EMIFF_SDRAM_CONFIG); +- MPUI730_SAVE(EMIFS_CONFIG); ++ if (cpu_is_omap7xx()) { ++ MPUI7XX_SAVE(MPUI_CTRL); ++ MPUI7XX_SAVE(MPUI_DSP_STATUS); ++ MPUI7XX_SAVE(MPUI_DSP_BOOT_CONFIG); ++ MPUI7XX_SAVE(MPUI_DSP_API_CONFIG); ++ MPUI7XX_SAVE(EMIFF_SDRAM_CONFIG); ++ MPUI7XX_SAVE(EMIFS_CONFIG); + } else if (cpu_is_omap15xx()) { + MPUI1510_SAVE(MPUI_CTRL); + MPUI1510_SAVE(MPUI_DSP_STATUS); +@@ -517,20 +517,20 @@ static int omap_pm_read_proc( + ULPD_SHOW(ULPD_STATUS_REQ), + ULPD_SHOW(ULPD_POWER_CTRL)); + +- if (cpu_is_omap730()) { ++ if (cpu_is_omap7xx()) { + my_buffer_offset += sprintf(my_base + my_buffer_offset, +- "MPUI730_CTRL_REG 0x%-8x \n" +- "MPUI730_DSP_STATUS_REG: 0x%-8x \n" +- "MPUI730_DSP_BOOT_CONFIG_REG: 0x%-8x \n" +- "MPUI730_DSP_API_CONFIG_REG: 0x%-8x \n" +- "MPUI730_SDRAM_CONFIG_REG: 0x%-8x \n" +- "MPUI730_EMIFS_CONFIG_REG: 0x%-8x \n", +- MPUI730_SHOW(MPUI_CTRL), +- MPUI730_SHOW(MPUI_DSP_STATUS), +- MPUI730_SHOW(MPUI_DSP_BOOT_CONFIG), +- MPUI730_SHOW(MPUI_DSP_API_CONFIG), +- MPUI730_SHOW(EMIFF_SDRAM_CONFIG), +- MPUI730_SHOW(EMIFS_CONFIG)); ++ "MPUI7XX_CTRL_REG 0x%-8x \n" ++ "MPUI7XX_DSP_STATUS_REG: 0x%-8x \n" ++ "MPUI7XX_DSP_BOOT_CONFIG_REG: 0x%-8x \n" ++ "MPUI7XX_DSP_API_CONFIG_REG: 0x%-8x \n" ++ "MPUI7XX_SDRAM_CONFIG_REG: 0x%-8x \n" ++ "MPUI7XX_EMIFS_CONFIG_REG: 0x%-8x \n", ++ MPUI7XX_SHOW(MPUI_CTRL), ++ MPUI7XX_SHOW(MPUI_DSP_STATUS), ++ MPUI7XX_SHOW(MPUI_DSP_BOOT_CONFIG), ++ MPUI7XX_SHOW(MPUI_DSP_API_CONFIG), ++ MPUI7XX_SHOW(EMIFF_SDRAM_CONFIG), ++ MPUI7XX_SHOW(EMIFS_CONFIG)); + } else if (cpu_is_omap15xx()) { + my_buffer_offset += sprintf(my_base + my_buffer_offset, + "MPUI1510_CTRL_REG 0x%-8x \n" +@@ -668,9 +668,9 @@ static int __init omap_pm_init(void) + * These routines need to be in SRAM as that's the only + * memory the MPU can see when it wakes up. + */ +- if (cpu_is_omap730()) { +- omap_sram_suspend = omap_sram_push(omap730_cpu_suspend, +- omap730_cpu_suspend_sz); ++ if (cpu_is_omap7xx()) { ++ omap_sram_suspend = omap_sram_push(omap7xx_cpu_suspend, ++ omap7xx_cpu_suspend_sz); + } else if (cpu_is_omap15xx()) { + omap_sram_suspend = omap_sram_push(omap1510_cpu_suspend, + omap1510_cpu_suspend_sz); +@@ -686,8 +686,8 @@ static int __init omap_pm_init(void) + + pm_idle = omap1_pm_idle; + +- if (cpu_is_omap730()) +- setup_irq(INT_730_WAKE_UP_REQ, &omap_wakeup_irq); ++ if (cpu_is_omap7xx()) ++ setup_irq(INT_7XX_WAKE_UP_REQ, &omap_wakeup_irq); + else if (cpu_is_omap16xx()) + setup_irq(INT_1610_WAKE_UP_REQ, &omap_wakeup_irq); + +@@ -700,8 +700,8 @@ static int __init omap_pm_init(void) + omap_writew(ULPD_POWER_CTRL_REG_VAL, ULPD_POWER_CTRL); + + /* Configure IDLECT3 */ +- if (cpu_is_omap730()) +- omap_writel(OMAP730_IDLECT3_VAL, OMAP730_IDLECT3); ++ if (cpu_is_omap7xx()) ++ omap_writel(OMAP7XX_IDLECT3_VAL, OMAP7XX_IDLECT3); + else if (cpu_is_omap16xx()) + omap_writel(OMAP1610_IDLECT3_VAL, OMAP1610_IDLECT3); + +diff --git a/arch/arm/mach-omap1/pm.h b/arch/arm/mach-omap1/pm.h +index c4f05bd..56a6479 100644 +--- a/arch/arm/mach-omap1/pm.h ++++ b/arch/arm/mach-omap1/pm.h +@@ -98,13 +98,14 @@ + #define OMAP1610_IDLECT3 0xfffece24 + #define OMAP1610_IDLE_LOOP_REQUEST 0x0400 + +-#define OMAP730_IDLECT1_SLEEP_VAL 0x16c7 +-#define OMAP730_IDLECT2_SLEEP_VAL 0x09c7 +-#define OMAP730_IDLECT3_VAL 0x3f +-#define OMAP730_IDLECT3 0xfffece24 +-#define OMAP730_IDLE_LOOP_REQUEST 0x0C00 ++#define OMAP7XX_IDLECT1_SLEEP_VAL 0x16c7 ++#define OMAP7XX_IDLECT2_SLEEP_VAL 0x09c7 ++#define OMAP7XX_IDLECT3_VAL 0x3f ++#define OMAP7XX_IDLECT3 0xfffece24 ++#define OMAP7XX_IDLE_LOOP_REQUEST 0x0C00 + + #if !defined(CONFIG_ARCH_OMAP730) && \ ++ !defined(CONFIG_ARCH_OMAP850) && \ + !defined(CONFIG_ARCH_OMAP15XX) && \ + !defined(CONFIG_ARCH_OMAP16XX) + #warning "Power management for this processor not implemented yet" +@@ -122,17 +123,17 @@ extern void allow_idle_sleep(void); + extern void omap1_pm_idle(void); + extern void omap1_pm_suspend(void); + +-extern void omap730_cpu_suspend(unsigned short, unsigned short); ++extern void omap7xx_cpu_suspend(unsigned short, unsigned short); + extern void omap1510_cpu_suspend(unsigned short, unsigned short); + extern void omap1610_cpu_suspend(unsigned short, unsigned short); +-extern void omap730_idle_loop_suspend(void); ++extern void omap7xx_idle_loop_suspend(void); + extern void omap1510_idle_loop_suspend(void); + extern void omap1610_idle_loop_suspend(void); + +-extern unsigned int omap730_cpu_suspend_sz; ++extern unsigned int omap7xx_cpu_suspend_sz; + extern unsigned int omap1510_cpu_suspend_sz; + extern unsigned int omap1610_cpu_suspend_sz; +-extern unsigned int omap730_idle_loop_suspend_sz; ++extern unsigned int omap7xx_idle_loop_suspend_sz; + extern unsigned int omap1510_idle_loop_suspend_sz; + extern unsigned int omap1610_idle_loop_suspend_sz; + +@@ -155,9 +156,9 @@ extern void omap_serial_wake_trigger(int enable); + #define ULPD_RESTORE(x) omap_writew((ulpd_sleep_save[ULPD_SLEEP_SAVE_##x]), (x)) + #define ULPD_SHOW(x) ulpd_sleep_save[ULPD_SLEEP_SAVE_##x] + +-#define MPUI730_SAVE(x) mpui730_sleep_save[MPUI730_SLEEP_SAVE_##x] = omap_readl(x) +-#define MPUI730_RESTORE(x) omap_writel((mpui730_sleep_save[MPUI730_SLEEP_SAVE_##x]), (x)) +-#define MPUI730_SHOW(x) mpui730_sleep_save[MPUI730_SLEEP_SAVE_##x] ++#define MPUI7XX_SAVE(x) mpui7xx_sleep_save[MPUI7XX_SLEEP_SAVE_##x] = omap_readl(x) ++#define MPUI7XX_RESTORE(x) omap_writel((mpui7xx_sleep_save[MPUI7XX_SLEEP_SAVE_##x]), (x)) ++#define MPUI7XX_SHOW(x) mpui7xx_sleep_save[MPUI7XX_SLEEP_SAVE_##x] + + #define MPUI1510_SAVE(x) mpui1510_sleep_save[MPUI1510_SLEEP_SAVE_##x] = omap_readl(x) + #define MPUI1510_RESTORE(x) omap_writel((mpui1510_sleep_save[MPUI1510_SLEEP_SAVE_##x]), (x)) +@@ -232,24 +233,24 @@ enum mpui1510_save_state { + #endif + }; + +-enum mpui730_save_state { +- MPUI730_SLEEP_SAVE_START = 0, ++enum mpui7xx_save_state { ++ MPUI7XX_SLEEP_SAVE_START = 0, + /* + * MPUI registers 32 bits + */ +- MPUI730_SLEEP_SAVE_MPUI_CTRL, +- MPUI730_SLEEP_SAVE_MPUI_DSP_BOOT_CONFIG, +- MPUI730_SLEEP_SAVE_MPUI_DSP_API_CONFIG, +- MPUI730_SLEEP_SAVE_MPUI_DSP_STATUS, +- MPUI730_SLEEP_SAVE_EMIFF_SDRAM_CONFIG, +- MPUI730_SLEEP_SAVE_EMIFS_CONFIG, +- MPUI730_SLEEP_SAVE_OMAP_IH1_MIR, +- MPUI730_SLEEP_SAVE_OMAP_IH2_0_MIR, +- MPUI730_SLEEP_SAVE_OMAP_IH2_1_MIR, +-#if defined(CONFIG_ARCH_OMAP730) +- MPUI730_SLEEP_SAVE_SIZE ++ MPUI7XX_SLEEP_SAVE_MPUI_CTRL, ++ MPUI7XX_SLEEP_SAVE_MPUI_DSP_BOOT_CONFIG, ++ MPUI7XX_SLEEP_SAVE_MPUI_DSP_API_CONFIG, ++ MPUI7XX_SLEEP_SAVE_MPUI_DSP_STATUS, ++ MPUI7XX_SLEEP_SAVE_EMIFF_SDRAM_CONFIG, ++ MPUI7XX_SLEEP_SAVE_EMIFS_CONFIG, ++ MPUI7XX_SLEEP_SAVE_OMAP_IH1_MIR, ++ MPUI7XX_SLEEP_SAVE_OMAP_IH2_0_MIR, ++ MPUI7XX_SLEEP_SAVE_OMAP_IH2_1_MIR, ++#if defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850) ++ MPUI7XX_SLEEP_SAVE_SIZE + #else +- MPUI730_SLEEP_SAVE_SIZE = 0 ++ MPUI7XX_SLEEP_SAVE_SIZE = 0 + #endif + }; + +diff --git a/arch/arm/mach-omap1/serial.c b/arch/arm/mach-omap1/serial.c +index d496e50..332c516 100644 +--- a/arch/arm/mach-omap1/serial.c ++++ b/arch/arm/mach-omap1/serial.c +@@ -64,7 +64,6 @@ static void __init omap_serial_reset(struct plat_serial8250_port *p) + + static struct plat_serial8250_port serial_platform_data[] = { + { +- .membase = OMAP1_IO_ADDRESS(OMAP_UART1_BASE), + .mapbase = OMAP_UART1_BASE, + .irq = INT_UART1, + .flags = UPF_BOOT_AUTOCONF, +@@ -73,7 +72,6 @@ static struct plat_serial8250_port serial_platform_data[] = { + .uartclk = OMAP16XX_BASE_BAUD * 16, + }, + { +- .membase = OMAP1_IO_ADDRESS(OMAP_UART2_BASE), + .mapbase = OMAP_UART2_BASE, + .irq = INT_UART2, + .flags = UPF_BOOT_AUTOCONF, +@@ -82,7 +80,6 @@ static struct plat_serial8250_port serial_platform_data[] = { + .uartclk = OMAP16XX_BASE_BAUD * 16, + }, + { +- .membase = OMAP1_IO_ADDRESS(OMAP_UART3_BASE), + .mapbase = OMAP_UART3_BASE, + .irq = INT_UART3, + .flags = UPF_BOOT_AUTOCONF, +@@ -90,7 +87,6 @@ static struct plat_serial8250_port serial_platform_data[] = { + .regshift = 2, + .uartclk = OMAP16XX_BASE_BAUD * 16, + }, +- { }, + }; + + static struct platform_device serial_device = { +@@ -110,18 +106,11 @@ void __init omap_serial_init(void) + { + int i; + +- if (cpu_is_omap730()) { ++ if (cpu_is_omap7xx()) { + serial_platform_data[0].regshift = 0; + serial_platform_data[1].regshift = 0; +- serial_platform_data[0].irq = INT_730_UART_MODEM_1; +- serial_platform_data[1].irq = INT_730_UART_MODEM_IRDA_2; +- } +- +- if (cpu_is_omap850()) { +- serial_platform_data[0].regshift = 0; +- serial_platform_data[1].regshift = 0; +- serial_platform_data[0].irq = INT_850_UART_MODEM_1; +- serial_platform_data[1].irq = INT_850_UART_MODEM_IRDA_2; ++ serial_platform_data[0].irq = INT_7XX_UART_MODEM_1; ++ serial_platform_data[1].irq = INT_7XX_UART_MODEM_IRDA_2; + } + + if (cpu_is_omap15xx()) { +@@ -130,9 +119,17 @@ void __init omap_serial_init(void) + serial_platform_data[2].uartclk = OMAP1510_BASE_BAUD * 16; + } + +- for (i = 0; i < OMAP_MAX_NR_PORTS; i++) { ++ for (i = 0; i < ARRAY_SIZE(serial_platform_data); i++) { + unsigned char reg; + ++ /* Static mapping, never released */ ++ serial_platform_data[i].membase = ++ ioremap(serial_platform_data[i].mapbase, SZ_2K); ++ if (!serial_platform_data[i].membase) { ++ printk(KERN_ERR "Could not ioremap uart%i\n", i); ++ continue; ++ } ++ + switch (i) { + case 0: + uart1_ck = clk_get(NULL, "uart1_ck"); +diff --git a/arch/arm/mach-omap1/sleep.S b/arch/arm/mach-omap1/sleep.S +index 22e8568..ef771ce 100644 +--- a/arch/arm/mach-omap1/sleep.S ++++ b/arch/arm/mach-omap1/sleep.S +@@ -1,7 +1,7 @@ + /* + * linux/arch/arm/mach-omap1/sleep.S + * +- * Low-level OMAP730/1510/1610 sleep/wakeUp support ++ * Low-level OMAP7XX/1510/1610 sleep/wakeUp support + * + * Initial SA1110 code: + * Copyright (c) 2001 Cliff Brake +@@ -57,8 +57,8 @@ + * + */ + +-#if defined(CONFIG_ARCH_OMAP730) +-ENTRY(omap730_cpu_suspend) ++#if defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850) ++ENTRY(omap7xx_cpu_suspend) + + @ save registers on stack + stmfd sp!, {r0 - r12, lr} +@@ -91,13 +91,13 @@ ENTRY(omap730_cpu_suspend) + + @ turn off clock domains + @ do not disable PERCK (0x04) +- mov r5, #OMAP730_IDLECT2_SLEEP_VAL & 0xff +- orr r5, r5, #OMAP730_IDLECT2_SLEEP_VAL & 0xff00 ++ mov r5, #OMAP7XX_IDLECT2_SLEEP_VAL & 0xff ++ orr r5, r5, #OMAP7XX_IDLECT2_SLEEP_VAL & 0xff00 + strh r5, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff] + + @ request ARM idle +- mov r3, #OMAP730_IDLECT1_SLEEP_VAL & 0xff +- orr r3, r3, #OMAP730_IDLECT1_SLEEP_VAL & 0xff00 ++ mov r3, #OMAP7XX_IDLECT1_SLEEP_VAL & 0xff ++ orr r3, r3, #OMAP7XX_IDLECT1_SLEEP_VAL & 0xff00 + strh r3, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff] + + @ disable instruction cache +@@ -113,7 +113,7 @@ ENTRY(omap730_cpu_suspend) + mov r2, #0 + mcr p15, 0, r2, c7, c0, 4 @ wait for interrupt + /* +- * omap730_cpu_suspend()'s resume point. ++ * omap7xx_cpu_suspend()'s resume point. + * + * It will just start executing here, so we'll restore stuff from the + * stack. +@@ -132,9 +132,9 @@ ENTRY(omap730_cpu_suspend) + @ restore regs and return + ldmfd sp!, {r0 - r12, pc} + +-ENTRY(omap730_cpu_suspend_sz) +- .word . - omap730_cpu_suspend +-#endif /* CONFIG_ARCH_OMAP730 */ ++ENTRY(omap7xx_cpu_suspend_sz) ++ .word . - omap7xx_cpu_suspend ++#endif /* CONFIG_ARCH_OMAP730 || CONFIG_ARCH_OMAP850 */ + + #ifdef CONFIG_ARCH_OMAP15XX + ENTRY(omap1510_cpu_suspend) +diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile +index 8cb1677..6b7702f 100644 +--- a/arch/arm/mach-omap2/Makefile ++++ b/arch/arm/mach-omap2/Makefile +@@ -80,6 +80,7 @@ obj-$(CONFIG_MACH_OMAP_4430SDP) += board-4430sdp.o + # Platform specific device init code + obj-y += usb-musb.o + obj-$(CONFIG_MACH_OMAP2_TUSB6010) += usb-tusb6010.o ++obj-y += usb-ehci.o + + onenand-$(CONFIG_MTD_ONENAND_OMAP2) := gpmc-onenand.o + obj-y += $(onenand-m) $(onenand-y) +diff --git a/arch/arm/mach-omap2/board-2430sdp.c b/arch/arm/mach-omap2/board-2430sdp.c +index 42217b3..e032a33 100644 +--- a/arch/arm/mach-omap2/board-2430sdp.c ++++ b/arch/arm/mach-omap2/board-2430sdp.c +@@ -221,7 +221,7 @@ static void __init omap_2430sdp_map_io(void) + MACHINE_START(OMAP_2430SDP, "OMAP2430 sdp2430 board") + /* Maintainer: Syed Khasim - Texas Instruments Inc */ + .phys_io = 0x48000000, +- .io_pg_offst = ((0xd8000000) >> 18) & 0xfffc, ++ .io_pg_offst = ((0xfa000000) >> 18) & 0xfffc, + .boot_params = 0x80000100, + .map_io = omap_2430sdp_map_io, + .init_irq = omap_2430sdp_init_irq, +diff --git a/arch/arm/mach-omap2/board-3430sdp.c b/arch/arm/mach-omap2/board-3430sdp.c +index efaf053..81aabac 100644 +--- a/arch/arm/mach-omap2/board-3430sdp.c ++++ b/arch/arm/mach-omap2/board-3430sdp.c +@@ -484,6 +484,18 @@ static void enable_board_wakeup_source(void) + omap_cfg_reg(AF26_34XX_SYS_NIRQ); /* T2 interrupt line (keypad) */ + } + ++static struct ehci_hcd_omap_platform_data ehci_pdata __initconst = { ++ ++ .port_mode[0] = EHCI_HCD_OMAP_MODE_PHY, ++ .port_mode[1] = EHCI_HCD_OMAP_MODE_PHY, ++ .port_mode[2] = EHCI_HCD_OMAP_MODE_UNKNOWN, ++ ++ .phy_reset = true, ++ .reset_gpio_port[0] = 57, ++ .reset_gpio_port[1] = 61, ++ .reset_gpio_port[2] = -EINVAL ++}; ++ + static void __init omap_3430sdp_init(void) + { + omap3430_i2c_init(); +@@ -500,6 +512,7 @@ static void __init omap_3430sdp_init(void) + usb_musb_init(); + board_smc91x_init(); + enable_board_wakeup_source(); ++ usb_ehci_init(&ehci_pdata); + } + + static void __init omap_3430sdp_map_io(void) +@@ -511,7 +524,7 @@ static void __init omap_3430sdp_map_io(void) + MACHINE_START(OMAP_3430SDP, "OMAP3430 3430SDP board") + /* Maintainer: Syed Khasim - Texas Instruments Inc */ + .phys_io = 0x48000000, +- .io_pg_offst = ((0xd8000000) >> 18) & 0xfffc, ++ .io_pg_offst = ((0xfa000000) >> 18) & 0xfffc, + .boot_params = 0x80000100, + .map_io = omap_3430sdp_map_io, + .init_irq = omap_3430sdp_init_irq, +diff --git a/arch/arm/mach-omap2/board-4430sdp.c b/arch/arm/mach-omap2/board-4430sdp.c +index eb37c40..50a62f2 100644 +--- a/arch/arm/mach-omap2/board-4430sdp.c ++++ b/arch/arm/mach-omap2/board-4430sdp.c +@@ -52,8 +52,17 @@ static struct omap_board_config_kernel sdp4430_config[] __initdata = { + + static void __init gic_init_irq(void) + { +- gic_dist_init(0, OMAP2_IO_ADDRESS(OMAP44XX_GIC_DIST_BASE), 29); +- gic_cpu_init(0, OMAP2_IO_ADDRESS(OMAP44XX_GIC_CPU_BASE)); ++ void __iomem *base; ++ ++ /* Static mapping, never released */ ++ base = ioremap(OMAP44XX_GIC_DIST_BASE, SZ_4K); ++ BUG_ON(!base); ++ gic_dist_init(0, base, 29); ++ ++ /* Static mapping, never released */ ++ base = ioremap(OMAP44XX_GIC_CPU_BASE, SZ_256); ++ BUG_ON(!base); ++ gic_cpu_init(0, OMAP44XX_GIC_CPU_BASE); + } + + static void __init omap_4430sdp_init_irq(void) +@@ -84,7 +93,7 @@ static void __init omap_4430sdp_map_io(void) + MACHINE_START(OMAP_4430SDP, "OMAP4430 4430SDP board") + /* Maintainer: Santosh Shilimkar - Texas Instruments Inc */ + .phys_io = 0x48000000, +- .io_pg_offst = ((0xd8000000) >> 18) & 0xfffc, ++ .io_pg_offst = ((0xfa000000) >> 18) & 0xfffc, + .boot_params = 0x80000100, + .map_io = omap_4430sdp_map_io, + .init_irq = omap_4430sdp_init_irq, +diff --git a/arch/arm/mach-omap2/board-apollon.c b/arch/arm/mach-omap2/board-apollon.c +index a113228..e8a0e56 100644 +--- a/arch/arm/mach-omap2/board-apollon.c ++++ b/arch/arm/mach-omap2/board-apollon.c +@@ -333,7 +333,7 @@ static void __init omap_apollon_map_io(void) + MACHINE_START(OMAP_APOLLON, "OMAP24xx Apollon") + /* Maintainer: Kyungmin Park */ + .phys_io = 0x48000000, +- .io_pg_offst = ((0xd8000000) >> 18) & 0xfffc, ++ .io_pg_offst = ((0xfa000000) >> 18) & 0xfffc, + .boot_params = 0x80000100, + .map_io = omap_apollon_map_io, + .init_irq = omap_apollon_init_irq, +diff --git a/arch/arm/mach-omap2/board-generic.c b/arch/arm/mach-omap2/board-generic.c +index 2e09a1c..1a139c0 100644 +--- a/arch/arm/mach-omap2/board-generic.c ++++ b/arch/arm/mach-omap2/board-generic.c +@@ -56,7 +56,7 @@ static void __init omap_generic_map_io(void) + MACHINE_START(OMAP_GENERIC, "Generic OMAP24xx") + /* Maintainer: Paul Mundt */ + .phys_io = 0x48000000, +- .io_pg_offst = ((0xd8000000) >> 18) & 0xfffc, ++ .io_pg_offst = ((0xfa000000) >> 18) & 0xfffc, + .boot_params = 0x80000100, + .map_io = omap_generic_map_io, + .init_irq = omap_generic_init_irq, +diff --git a/arch/arm/mach-omap2/board-h4.c b/arch/arm/mach-omap2/board-h4.c +index eaa02d0..86f78f3 100644 +--- a/arch/arm/mach-omap2/board-h4.c ++++ b/arch/arm/mach-omap2/board-h4.c +@@ -376,7 +376,7 @@ static void __init omap_h4_map_io(void) + MACHINE_START(OMAP_H4, "OMAP2420 H4 board") + /* Maintainer: Paul Mundt */ + .phys_io = 0x48000000, +- .io_pg_offst = ((0xd8000000) >> 18) & 0xfffc, ++ .io_pg_offst = ((0xfa000000) >> 18) & 0xfffc, + .boot_params = 0x80000100, + .map_io = omap_h4_map_io, + .init_irq = omap_h4_init_irq, +diff --git a/arch/arm/mach-omap2/board-ldp.c b/arch/arm/mach-omap2/board-ldp.c +index d110a7f..4ccc01a 100644 +--- a/arch/arm/mach-omap2/board-ldp.c ++++ b/arch/arm/mach-omap2/board-ldp.c +@@ -399,7 +399,7 @@ static void __init omap_ldp_map_io(void) + + MACHINE_START(OMAP_LDP, "OMAP LDP board") + .phys_io = 0x48000000, +- .io_pg_offst = ((0xd8000000) >> 18) & 0xfffc, ++ .io_pg_offst = ((0xfa000000) >> 18) & 0xfffc, + .boot_params = 0x80000100, + .map_io = omap_ldp_map_io, + .init_irq = omap_ldp_init_irq, +diff --git a/arch/arm/mach-omap2/board-n8x0.c b/arch/arm/mach-omap2/board-n8x0.c +index 8341632..2f6ccba 100644 +--- a/arch/arm/mach-omap2/board-n8x0.c ++++ b/arch/arm/mach-omap2/board-n8x0.c +@@ -121,7 +121,7 @@ static void __init n8x0_init_machine(void) + + MACHINE_START(NOKIA_N800, "Nokia N800") + .phys_io = 0x48000000, +- .io_pg_offst = ((0xd8000000) >> 18) & 0xfffc, ++ .io_pg_offst = ((0xfa000000) >> 18) & 0xfffc, + .boot_params = 0x80000100, + .map_io = n8x0_map_io, + .init_irq = n8x0_init_irq, +@@ -131,7 +131,7 @@ MACHINE_END + + MACHINE_START(NOKIA_N810, "Nokia N810") + .phys_io = 0x48000000, +- .io_pg_offst = ((0xd8000000) >> 18) & 0xfffc, ++ .io_pg_offst = ((0xfa000000) >> 18) & 0xfffc, + .boot_params = 0x80000100, + .map_io = n8x0_map_io, + .init_irq = n8x0_init_irq, +@@ -141,7 +141,7 @@ MACHINE_END + + MACHINE_START(NOKIA_N810_WIMAX, "Nokia N810 WiMAX") + .phys_io = 0x48000000, +- .io_pg_offst = ((0xd8000000) >> 18) & 0xfffc, ++ .io_pg_offst = ((0xfa000000) >> 18) & 0xfffc, + .boot_params = 0x80000100, + .map_io = n8x0_map_io, + .init_irq = n8x0_init_irq, +diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c +index 70df6b4..9824073 100644 +--- a/arch/arm/mach-omap2/board-omap3beagle.c ++++ b/arch/arm/mach-omap2/board-omap3beagle.c +@@ -400,6 +400,18 @@ static void __init omap3beagle_flash_init(void) + } + } + ++static struct ehci_hcd_omap_platform_data ehci_pdata __initconst = { ++ ++ .port_mode[0] = EHCI_HCD_OMAP_MODE_PHY, ++ .port_mode[1] = EHCI_HCD_OMAP_MODE_PHY, ++ .port_mode[2] = EHCI_HCD_OMAP_MODE_UNKNOWN, ++ ++ .phy_reset = true, ++ .reset_gpio_port[0] = -EINVAL, ++ .reset_gpio_port[1] = 147, ++ .reset_gpio_port[2] = -EINVAL ++}; ++ + static void __init omap3_beagle_init(void) + { + omap3_beagle_i2c_init(); +@@ -413,6 +425,7 @@ static void __init omap3_beagle_init(void) + gpio_direction_output(170, true); + + usb_musb_init(); ++ usb_ehci_init(&ehci_pdata); + omap3beagle_flash_init(); + + /* Ensure SDRC pins are mux'd for self-refresh */ +@@ -429,7 +442,7 @@ static void __init omap3_beagle_map_io(void) + MACHINE_START(OMAP3_BEAGLE, "OMAP3 Beagle Board") + /* Maintainer: Syed Mohammed Khasim - http://beagleboard.org */ + .phys_io = 0x48000000, +- .io_pg_offst = ((0xd8000000) >> 18) & 0xfffc, ++ .io_pg_offst = ((0xfa000000) >> 18) & 0xfffc, + .boot_params = 0x80000100, + .map_io = omap3_beagle_map_io, + .init_irq = omap3_beagle_init_irq, +diff --git a/arch/arm/mach-omap2/board-omap3evm.c b/arch/arm/mach-omap2/board-omap3evm.c +index e4ec0c5..9e0b6e6 100644 +--- a/arch/arm/mach-omap2/board-omap3evm.c ++++ b/arch/arm/mach-omap2/board-omap3evm.c +@@ -297,6 +297,18 @@ static struct platform_device *omap3_evm_devices[] __initdata = { + &omap3evm_smc911x_device, + }; + ++static struct ehci_hcd_omap_platform_data ehci_pdata __initconst = { ++ ++ .port_mode[0] = EHCI_HCD_OMAP_MODE_UNKNOWN, ++ .port_mode[1] = EHCI_HCD_OMAP_MODE_PHY, ++ .port_mode[2] = EHCI_HCD_OMAP_MODE_UNKNOWN, ++ ++ .phy_reset = true, ++ .reset_gpio_port[0] = -EINVAL, ++ .reset_gpio_port[1] = 135, ++ .reset_gpio_port[2] = -EINVAL ++}; ++ + static void __init omap3_evm_init(void) + { + omap3_evm_i2c_init(); +@@ -312,6 +324,9 @@ static void __init omap3_evm_init(void) + usb_nop_xceiv_register(); + #endif + usb_musb_init(); ++ /* Setup EHCI phy reset padconfig */ ++ omap_cfg_reg(AF4_34XX_GPIO135_OUT); ++ usb_ehci_init(&ehci_pdata); + ads7846_dev_init(); + } + +@@ -324,7 +339,7 @@ static void __init omap3_evm_map_io(void) + MACHINE_START(OMAP3EVM, "OMAP3 EVM") + /* Maintainer: Syed Mohammed Khasim - Texas Instruments */ + .phys_io = 0x48000000, +- .io_pg_offst = ((0xd8000000) >> 18) & 0xfffc, ++ .io_pg_offst = ((0xfa000000) >> 18) & 0xfffc, + .boot_params = 0x80000100, + .map_io = omap3_evm_map_io, + .init_irq = omap3_evm_init_irq, +diff --git a/arch/arm/mach-omap2/board-omap3pandora.c b/arch/arm/mach-omap2/board-omap3pandora.c +index 7f6bf87..82b2486 100644 +--- a/arch/arm/mach-omap2/board-omap3pandora.c ++++ b/arch/arm/mach-omap2/board-omap3pandora.c +@@ -387,6 +387,18 @@ static struct platform_device *omap3pandora_devices[] __initdata = { + &pandora_keys_gpio, + }; + ++static struct ehci_hcd_omap_platform_data ehci_pdata __initconst = { ++ ++ .port_mode[0] = EHCI_HCD_OMAP_MODE_PHY, ++ .port_mode[1] = EHCI_HCD_OMAP_MODE_UNKNOWN, ++ .port_mode[2] = EHCI_HCD_OMAP_MODE_UNKNOWN, ++ ++ .phy_reset = true, ++ .reset_gpio_port[0] = 16, ++ .reset_gpio_port[1] = -EINVAL, ++ .reset_gpio_port[2] = -EINVAL ++}; ++ + static void __init omap3pandora_init(void) + { + omap3pandora_i2c_init(); +@@ -396,6 +408,7 @@ static void __init omap3pandora_init(void) + spi_register_board_info(omap3pandora_spi_board_info, + ARRAY_SIZE(omap3pandora_spi_board_info)); + omap3pandora_ads7846_init(); ++ usb_ehci_init(&ehci_pdata); + pandora_keys_gpio_init(); + usb_musb_init(); + +@@ -412,7 +425,7 @@ static void __init omap3pandora_map_io(void) + + MACHINE_START(OMAP3_PANDORA, "Pandora Handheld Console") + .phys_io = 0x48000000, +- .io_pg_offst = ((0xd8000000) >> 18) & 0xfffc, ++ .io_pg_offst = ((0xfa000000) >> 18) & 0xfffc, + .boot_params = 0x80000100, + .map_io = omap3pandora_map_io, + .init_irq = omap3pandora_init_irq, +diff --git a/arch/arm/mach-omap2/board-overo.c b/arch/arm/mach-omap2/board-overo.c +index 9917d2f..d50a3f0 100644 +--- a/arch/arm/mach-omap2/board-overo.c ++++ b/arch/arm/mach-omap2/board-overo.c +@@ -384,6 +384,18 @@ static struct platform_device *overo_devices[] __initdata = { + &overo_lcd_device, + }; + ++static struct ehci_hcd_omap_platform_data ehci_pdata __initconst = { ++ .port_mode[0] = EHCI_HCD_OMAP_MODE_UNKNOWN, ++ .port_mode[1] = EHCI_HCD_OMAP_MODE_PHY, ++ .port_mode[2] = EHCI_HCD_OMAP_MODE_UNKNOWN, ++ ++ .phy_reset = true, ++ .reset_gpio_port[0] = -EINVAL, ++ .reset_gpio_port[1] = OVERO_GPIO_USBH_NRESET, ++ .reset_gpio_port[2] = -EINVAL ++}; ++ ++ + static void __init overo_init(void) + { + overo_i2c_init(); +@@ -391,6 +403,7 @@ static void __init overo_init(void) + omap_serial_init(); + overo_flash_init(); + usb_musb_init(); ++ usb_ehci_init(&ehci_pdata); + overo_ads7846_init(); + overo_init_smsc911x(); + +@@ -433,14 +446,6 @@ static void __init overo_init(void) + else + printk(KERN_ERR "could not obtain gpio for " + "OVERO_GPIO_USBH_CPEN\n"); +- +- if ((gpio_request(OVERO_GPIO_USBH_NRESET, +- "OVERO_GPIO_USBH_NRESET") == 0) && +- (gpio_direction_output(OVERO_GPIO_USBH_NRESET, 1) == 0)) +- gpio_export(OVERO_GPIO_USBH_NRESET, 0); +- else +- printk(KERN_ERR "could not obtain gpio for " +- "OVERO_GPIO_USBH_NRESET\n"); + } + + static void __init overo_map_io(void) +@@ -451,7 +456,7 @@ static void __init overo_map_io(void) + + MACHINE_START(OVERO, "Gumstix Overo") + .phys_io = 0x48000000, +- .io_pg_offst = ((0xd8000000) >> 18) & 0xfffc, ++ .io_pg_offst = ((0xfa000000) >> 18) & 0xfffc, + .boot_params = 0x80000100, + .map_io = overo_map_io, + .init_irq = overo_init_irq, +diff --git a/arch/arm/mach-omap2/board-rx51.c b/arch/arm/mach-omap2/board-rx51.c +index f9196c3..c973812 100644 +--- a/arch/arm/mach-omap2/board-rx51.c ++++ b/arch/arm/mach-omap2/board-rx51.c +@@ -85,7 +85,7 @@ static void __init rx51_map_io(void) + MACHINE_START(NOKIA_RX51, "Nokia RX-51 board") + /* Maintainer: Lauri Leukkunen */ + .phys_io = 0x48000000, +- .io_pg_offst = ((0xd8000000) >> 18) & 0xfffc, ++ .io_pg_offst = ((0xfa000000) >> 18) & 0xfffc, + .boot_params = 0x80000100, + .map_io = rx51_map_io, + .init_irq = rx51_init_irq, +diff --git a/arch/arm/mach-omap2/board-zoom2.c b/arch/arm/mach-omap2/board-zoom2.c +index fd3369d..48bd2af 100644 +--- a/arch/arm/mach-omap2/board-zoom2.c ++++ b/arch/arm/mach-omap2/board-zoom2.c +@@ -283,7 +283,7 @@ static void __init omap_zoom2_map_io(void) + + MACHINE_START(OMAP_ZOOM2, "OMAP Zoom2 board") + .phys_io = 0x48000000, +- .io_pg_offst = ((0xd8000000) >> 18) & 0xfffc, ++ .io_pg_offst = ((0xfa000000) >> 18) & 0xfffc, + .boot_params = 0x80000100, + .map_io = omap_zoom2_map_io, + .init_irq = omap_zoom2_init_irq, +diff --git a/arch/arm/mach-omap2/cm.h b/arch/arm/mach-omap2/cm.h +index cfd0b72..a2fcfcc 100644 +--- a/arch/arm/mach-omap2/cm.h ++++ b/arch/arm/mach-omap2/cm.h +@@ -17,11 +17,11 @@ + #include "prcm-common.h" + + #define OMAP2420_CM_REGADDR(module, reg) \ +- OMAP2_IO_ADDRESS(OMAP2420_CM_BASE + (module) + (reg)) ++ OMAP2_L4_IO_ADDRESS(OMAP2420_CM_BASE + (module) + (reg)) + #define OMAP2430_CM_REGADDR(module, reg) \ +- OMAP2_IO_ADDRESS(OMAP2430_CM_BASE + (module) + (reg)) ++ OMAP2_L4_IO_ADDRESS(OMAP2430_CM_BASE + (module) + (reg)) + #define OMAP34XX_CM_REGADDR(module, reg) \ +- OMAP2_IO_ADDRESS(OMAP3430_CM_BASE + (module) + (reg)) ++ OMAP2_L4_IO_ADDRESS(OMAP3430_CM_BASE + (module) + (reg)) + + /* + * Architecture-specific global CM registers +diff --git a/arch/arm/mach-omap2/id.c b/arch/arm/mach-omap2/id.c +index a98201c..71d5568 100644 +--- a/arch/arm/mach-omap2/id.c ++++ b/arch/arm/mach-omap2/id.c +@@ -28,6 +28,7 @@ + static struct omap_chip_id omap_chip; + static unsigned int omap_revision; + ++u32 omap3_features; + + unsigned int omap_rev(void) + { +@@ -155,12 +156,37 @@ void __init omap24xx_check_revision(void) + pr_info("\n"); + } + +-void __init omap34xx_check_revision(void) ++#define OMAP3_CHECK_FEATURE(status,feat) \ ++ if (((status & OMAP3_ ##feat## _MASK) \ ++ >> OMAP3_ ##feat## _SHIFT) != FEAT_ ##feat## _NONE) { \ ++ omap3_features |= OMAP3_HAS_ ##feat; \ ++ } ++ ++void __init omap3_check_features(void) ++{ ++ u32 status; ++ ++ omap3_features = 0; ++ ++ status = omap_ctrl_readl(OMAP3_CONTROL_OMAP_STATUS); ++ ++ OMAP3_CHECK_FEATURE(status, L2CACHE); ++ OMAP3_CHECK_FEATURE(status, IVA); ++ OMAP3_CHECK_FEATURE(status, SGX); ++ OMAP3_CHECK_FEATURE(status, NEON); ++ OMAP3_CHECK_FEATURE(status, ISP); ++ ++ /* ++ * TODO: Get additional info (where applicable) ++ * e.g. Size of L2 cache. ++ */ ++} ++ ++void __init omap3_check_revision(void) + { + u32 cpuid, idcode; + u16 hawkeye; + u8 rev; +- char *rev_name = "ES1.0"; + + /* + * We cannot access revision registers on ES1.0. +@@ -170,7 +196,7 @@ void __init omap34xx_check_revision(void) + cpuid = read_cpuid(CPUID_ID); + if ((((cpuid >> 4) & 0xfff) == 0xc08) && ((cpuid & 0xf) == 0x0)) { + omap_revision = OMAP3430_REV_ES1_0; +- goto out; ++ return; + } + + /* +@@ -183,33 +209,111 @@ void __init omap34xx_check_revision(void) + hawkeye = (idcode >> 12) & 0xffff; + rev = (idcode >> 28) & 0xff; + +- if (hawkeye == 0xb7ae) { ++ switch (hawkeye) { ++ case 0xb7ae: ++ /* Handle 34xx/35xx devices */ + switch (rev) { +- case 0: ++ case 0: /* Take care of early samples */ ++ case 1: + omap_revision = OMAP3430_REV_ES2_0; +- rev_name = "ES2.0"; + break; + case 2: + omap_revision = OMAP3430_REV_ES2_1; +- rev_name = "ES2.1"; + break; + case 3: + omap_revision = OMAP3430_REV_ES3_0; +- rev_name = "ES3.0"; + break; + case 4: + omap_revision = OMAP3430_REV_ES3_1; +- rev_name = "ES3.1"; + break; + default: + /* Use the latest known revision as default */ + omap_revision = OMAP3430_REV_ES3_1; +- rev_name = "Unknown revision\n"; + } ++ break; ++ case 0xb891: ++ /* Handle 36xx devices */ ++ switch (rev) { ++ case 0: ++ omap_revision = OMAP3630_REV_ES1_0; ++ break; ++ default: ++ /* Use the latest known revision as default */ ++ omap_revision = OMAP3630_REV_ES1_0; ++ } ++ break; ++ default: ++ /* Unknown default to latest silicon rev as default*/ ++ omap_revision = OMAP3630_REV_ES1_0; + } ++} + +-out: +- pr_info("OMAP%04x %s\n", omap_rev() >> 16, rev_name); ++#define OMAP3_SHOW_FEATURE(feat) \ ++ if (omap3_has_ ##feat()) { \ ++ pr_info (" - "#feat" : Y"); \ ++ } else { \ ++ pr_info (" - "#feat" : N"); \ ++ } ++ ++void __init omap3_cpuinfo(void) ++{ ++ u8 rev = GET_OMAP_REVISION(); ++ char cpu_name[16], cpu_rev[16]; ++ ++ /* OMAP3430 and OMAP3530 are assumed to be same. ++ * ++ * OMAP3525, OMAP3515 and OMAP3503 can be detected only based ++ * on available features. Upon detection, update the CPU id ++ * and CPU class bits. ++ */ ++ if (cpu_is_omap3630()) ++ strcpy(cpu_name, "3630"); ++ else if (omap3_has_iva() && omap3_has_sgx()) ++ strcpy(cpu_name, "3430/3530"); ++ else if (omap3_has_sgx()) { ++ omap_revision = OMAP3525_REV(rev); ++ strcpy(cpu_name, "3525"); ++ } ++ else if (omap3_has_iva()) { ++ omap_revision = OMAP3515_REV(rev); ++ strcpy(cpu_name, "3515"); ++ } ++ else { ++ omap_revision = OMAP3503_REV(rev); ++ strcpy(cpu_name, "3503"); ++ } ++ ++ switch (rev) { ++ case OMAP_REVBITS_00: ++ strcpy(cpu_rev, "1.0"); ++ break; ++ case OMAP_REVBITS_10: ++ strcpy(cpu_rev, "2.0"); ++ break; ++ case OMAP_REVBITS_20: ++ strcpy(cpu_rev, "2.1"); ++ break; ++ case OMAP_REVBITS_30: ++ strcpy(cpu_rev, "3.0"); ++ break; ++ case OMAP_REVBITS_40: ++ strcpy(cpu_rev, "3.1"); ++ break; ++ default: ++ /* Use the latest known revision as default */ ++ strcpy(cpu_rev, "3.1"); ++ } ++ ++ /* ++ * Print verbose information ++ */ ++ pr_info("OMAP%s ES%s\n", cpu_name, cpu_rev); ++ ++ OMAP3_SHOW_FEATURE(l2cache); ++ OMAP3_SHOW_FEATURE(iva); ++ OMAP3_SHOW_FEATURE(sgx); ++ OMAP3_SHOW_FEATURE(neon); ++ OMAP3_SHOW_FEATURE(isp); + } + + /* +@@ -223,8 +327,11 @@ void __init omap2_check_revision(void) + */ + if (cpu_is_omap24xx()) + omap24xx_check_revision(); +- else if (cpu_is_omap34xx()) +- omap34xx_check_revision(); ++ else if (cpu_is_omap34xx()) { ++ omap3_check_features(); ++ omap3_check_revision(); ++ omap3_cpuinfo(); ++ } + else if (cpu_is_omap44xx()) { + printk(KERN_INFO "FIXME: CPU revision = OMAP4430\n"); + return; +diff --git a/arch/arm/mach-omap2/io.c b/arch/arm/mach-omap2/io.c +index e3a3bad..fc62953 100644 +--- a/arch/arm/mach-omap2/io.c ++++ b/arch/arm/mach-omap2/io.c +@@ -203,6 +203,24 @@ static struct map_desc omap44xx_io_desc[] __initdata = { + .type = MT_DEVICE, + }, + { ++ .virtual = OMAP44XX_EMIF1_VIRT, ++ .pfn = __phys_to_pfn(OMAP44XX_EMIF1_PHYS), ++ .length = OMAP44XX_EMIF1_SIZE, ++ .type = MT_DEVICE, ++ }, ++ { ++ .virtual = OMAP44XX_EMIF2_VIRT, ++ .pfn = __phys_to_pfn(OMAP44XX_EMIF2_PHYS), ++ .length = OMAP44XX_EMIF2_SIZE, ++ .type = MT_DEVICE, ++ }, ++ { ++ .virtual = OMAP44XX_DMM_VIRT, ++ .pfn = __phys_to_pfn(OMAP44XX_DMM_PHYS), ++ .length = OMAP44XX_DMM_SIZE, ++ .type = MT_DEVICE, ++ }, ++ { + .virtual = L4_PER_44XX_VIRT, + .pfn = __phys_to_pfn(L4_PER_44XX_PHYS), + .length = L4_PER_44XX_SIZE, +diff --git a/arch/arm/mach-omap2/irq.c b/arch/arm/mach-omap2/irq.c +index b828638..1db121f 100644 +--- a/arch/arm/mach-omap2/irq.c ++++ b/arch/arm/mach-omap2/irq.c +@@ -178,12 +178,20 @@ void __init omap_init_irq(void) + int i; + + for (i = 0; i < ARRAY_SIZE(irq_banks); i++) { ++ unsigned long base; + struct omap_irq_bank *bank = irq_banks + i; + + if (cpu_is_omap24xx()) +- bank->base_reg = OMAP2_IO_ADDRESS(OMAP24XX_IC_BASE); ++ base = OMAP24XX_IC_BASE; + else if (cpu_is_omap34xx()) +- bank->base_reg = OMAP2_IO_ADDRESS(OMAP34XX_IC_BASE); ++ base = OMAP34XX_IC_BASE; ++ ++ /* Static mapping, never released */ ++ bank->base_reg = ioremap(base, SZ_4K); ++ if (!bank->base_reg) { ++ printk(KERN_ERR "Could not ioremap irq bank%i\n", i); ++ continue; ++ } + + omap_irq_bank_init_one(bank); + +diff --git a/arch/arm/mach-omap2/omap-smp.c b/arch/arm/mach-omap2/omap-smp.c +index 48ee295..a1b618c 100644 +--- a/arch/arm/mach-omap2/omap-smp.c ++++ b/arch/arm/mach-omap2/omap-smp.c +@@ -26,11 +26,11 @@ + #include + + /* Registers used for communicating startup information */ +-#define OMAP4_AUXCOREBOOT_REG0 (OMAP44XX_VA_WKUPGEN_BASE + 0x800) +-#define OMAP4_AUXCOREBOOT_REG1 (OMAP44XX_VA_WKUPGEN_BASE + 0x804) ++static void __iomem *omap4_auxcoreboot_reg0; ++static void __iomem *omap4_auxcoreboot_reg1; + + /* SCU base address */ +-static void __iomem *scu_base = OMAP44XX_VA_SCU_BASE; ++static void __iomem *scu_base; + + /* + * Use SCU config register to count number of cores +@@ -46,6 +46,8 @@ static DEFINE_SPINLOCK(boot_lock); + + void __cpuinit platform_secondary_init(unsigned int cpu) + { ++ void __iomem *gic_cpu_base; ++ + trace_hardirqs_off(); + + /* +@@ -54,7 +56,10 @@ void __cpuinit platform_secondary_init(unsigned int cpu) + * for us: do so + */ + +- gic_cpu_init(0, OMAP2_IO_ADDRESS(OMAP44XX_GIC_CPU_BASE)); ++ /* Static mapping, never released */ ++ gic_cpu_base = ioremap(OMAP44XX_GIC_CPU_BASE, SZ_256); ++ BUG_ON(!gic_cpu_base); ++ gic_cpu_init(0, gic_cpu_base); + + /* + * Synchronise with the boot thread. +@@ -79,7 +84,7 @@ int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle) + * the AuxCoreBoot1 register is updated with cpu state + * A barrier is added to ensure that write buffer is drained + */ +- __raw_writel(cpu, OMAP4_AUXCOREBOOT_REG1); ++ __raw_writel(cpu, omap4_auxcoreboot_reg1); + smp_wmb(); + + timeout = jiffies + (1 * HZ); +@@ -104,7 +109,7 @@ static void __init wakeup_secondary(void) + * A barrier is added to ensure that write buffer is drained + */ + __raw_writel(virt_to_phys(omap_secondary_startup), \ +- OMAP4_AUXCOREBOOT_REG0); ++ omap4_auxcoreboot_reg0); + smp_wmb(); + + /* +@@ -130,6 +135,7 @@ void __init smp_prepare_cpus(unsigned int max_cpus) + { + unsigned int ncores = get_core_count(); + unsigned int cpu = smp_processor_id(); ++ void __iomem *omap4_wkupgen_base; + int i; + + /* sanity check */ +@@ -161,6 +167,16 @@ void __init smp_prepare_cpus(unsigned int max_cpus) + for (i = 0; i < max_cpus; i++) + set_cpu_present(i, true); + ++ /* Never released */ ++ omap4_wkupgen_base = ioremap(OMAP44XX_WKUPGEN_BASE, SZ_4K); ++ BUG_ON(!omap4_wkupgen_base); ++ omap4_auxcoreboot_reg0 = omap4_wkupgen_base + 0x800; ++ omap4_auxcoreboot_reg0 = omap4_wkupgen_base + 0x804; ++ ++ /* Never released */ ++ scu_base = ioremap(OMAP44XX_GIC_CPU_BASE, SZ_256); ++ BUG_ON(!scu_base); ++ + if (max_cpus > 1) { + /* + * Enable the local timer or broadcast device for the +diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c +index d2e0f1c..8ac8798 100644 +--- a/arch/arm/mach-omap2/omap_hwmod.c ++++ b/arch/arm/mach-omap2/omap_hwmod.c +@@ -496,6 +496,7 @@ static void __iomem *_find_mpu_rt_base(struct omap_hwmod *oh, u8 index) + struct omap_hwmod_addr_space *mem; + int i; + int found = 0; ++ void __iomem *va_start; + + if (!oh || oh->slaves_cnt == 0) + return NULL; +@@ -509,16 +510,20 @@ static void __iomem *_find_mpu_rt_base(struct omap_hwmod *oh, u8 index) + } + } + +- /* XXX use ioremap() instead? */ +- +- if (found) ++ if (found) { ++ va_start = ioremap(mem->pa_start, mem->pa_end - mem->pa_start); ++ if (!va_start) { ++ pr_err("omap_hwmod: %s: Could not ioremap\n", oh->name); ++ return NULL; ++ } + pr_debug("omap_hwmod: %s: MPU register target at va %p\n", +- oh->name, OMAP2_IO_ADDRESS(mem->pa_start)); +- else ++ oh->name, va_start); ++ } else { + pr_debug("omap_hwmod: %s: no MPU register target found\n", + oh->name); ++ } + +- return (found) ? OMAP2_IO_ADDRESS(mem->pa_start) : NULL; ++ return (found) ? va_start : NULL; + } + + /** +@@ -1148,6 +1153,7 @@ int omap_hwmod_unregister(struct omap_hwmod *oh) + pr_debug("omap_hwmod: %s: unregistering\n", oh->name); + + mutex_lock(&omap_hwmod_mutex); ++ iounmap(oh->_rt_va); + list_del(&oh->node); + mutex_unlock(&omap_hwmod_mutex); + +diff --git a/arch/arm/mach-omap2/pm-debug.c b/arch/arm/mach-omap2/pm-debug.c +index 2fc4d6a..deed1dd 100644 +--- a/arch/arm/mach-omap2/pm-debug.c ++++ b/arch/arm/mach-omap2/pm-debug.c +@@ -51,7 +51,8 @@ int omap2_pm_debug; + regs[reg_count++].val = __raw_readl(reg) + #define DUMP_INTC_REG(reg, off) \ + regs[reg_count].name = #reg; \ +- regs[reg_count++].val = __raw_readl(OMAP2_IO_ADDRESS(0x480fe000 + (off))) ++ regs[reg_count++].val = \ ++ __raw_readl(OMAP2_L4_IO_ADDRESS(0x480fe000 + (off))) + + static int __init pm_dbg_init(void); + +diff --git a/arch/arm/mach-omap2/prm.h b/arch/arm/mach-omap2/prm.h +index 03c467c..a117f85 100644 +--- a/arch/arm/mach-omap2/prm.h ++++ b/arch/arm/mach-omap2/prm.h +@@ -17,11 +17,11 @@ + #include "prcm-common.h" + + #define OMAP2420_PRM_REGADDR(module, reg) \ +- OMAP2_IO_ADDRESS(OMAP2420_PRM_BASE + (module) + (reg)) ++ OMAP2_L4_IO_ADDRESS(OMAP2420_PRM_BASE + (module) + (reg)) + #define OMAP2430_PRM_REGADDR(module, reg) \ +- OMAP2_IO_ADDRESS(OMAP2430_PRM_BASE + (module) + (reg)) ++ OMAP2_L4_IO_ADDRESS(OMAP2430_PRM_BASE + (module) + (reg)) + #define OMAP34XX_PRM_REGADDR(module, reg) \ +- OMAP2_IO_ADDRESS(OMAP3430_PRM_BASE + (module) + (reg)) ++ OMAP2_L4_IO_ADDRESS(OMAP3430_PRM_BASE + (module) + (reg)) + + /* + * Architecture-specific global PRM registers +diff --git a/arch/arm/mach-omap2/sdrc.h b/arch/arm/mach-omap2/sdrc.h +index 0837eda..345183d 100644 +--- a/arch/arm/mach-omap2/sdrc.h ++++ b/arch/arm/mach-omap2/sdrc.h +@@ -48,9 +48,12 @@ static inline u32 sms_read_reg(u16 reg) + return __raw_readl(OMAP_SMS_REGADDR(reg)); + } + #else +-#define OMAP242X_SDRC_REGADDR(reg) OMAP2_IO_ADDRESS(OMAP2420_SDRC_BASE + (reg)) +-#define OMAP243X_SDRC_REGADDR(reg) OMAP2_IO_ADDRESS(OMAP243X_SDRC_BASE + (reg)) +-#define OMAP34XX_SDRC_REGADDR(reg) OMAP2_IO_ADDRESS(OMAP343X_SDRC_BASE + (reg)) ++#define OMAP242X_SDRC_REGADDR(reg) \ ++ OMAP2_L3_IO_ADDRESS(OMAP2420_SDRC_BASE + (reg)) ++#define OMAP243X_SDRC_REGADDR(reg) \ ++ OMAP2_L3_IO_ADDRESS(OMAP243X_SDRC_BASE + (reg)) ++#define OMAP34XX_SDRC_REGADDR(reg) \ ++ OMAP2_L3_IO_ADDRESS(OMAP343X_SDRC_BASE + (reg)) + #endif /* __ASSEMBLER__ */ + + #endif +diff --git a/arch/arm/mach-omap2/serial.c b/arch/arm/mach-omap2/serial.c +index ae21868..7f722a7 100644 +--- a/arch/arm/mach-omap2/serial.c ++++ b/arch/arm/mach-omap2/serial.c +@@ -73,7 +73,6 @@ static LIST_HEAD(uart_list); + + static struct plat_serial8250_port serial_platform_data0[] = { + { +- .membase = OMAP2_IO_ADDRESS(OMAP_UART1_BASE), + .mapbase = OMAP_UART1_BASE, + .irq = 72, + .flags = UPF_BOOT_AUTOCONF, +@@ -87,7 +86,6 @@ static struct plat_serial8250_port serial_platform_data0[] = { + + static struct plat_serial8250_port serial_platform_data1[] = { + { +- .membase = OMAP2_IO_ADDRESS(OMAP_UART2_BASE), + .mapbase = OMAP_UART2_BASE, + .irq = 73, + .flags = UPF_BOOT_AUTOCONF, +@@ -101,7 +99,6 @@ static struct plat_serial8250_port serial_platform_data1[] = { + + static struct plat_serial8250_port serial_platform_data2[] = { + { +- .membase = OMAP2_IO_ADDRESS(OMAP_UART3_BASE), + .mapbase = OMAP_UART3_BASE, + .irq = 74, + .flags = UPF_BOOT_AUTOCONF, +@@ -110,7 +107,6 @@ static struct plat_serial8250_port serial_platform_data2[] = { + .uartclk = OMAP24XX_BASE_BAUD * 16, + }, { + #ifdef CONFIG_ARCH_OMAP4 +- .membase = OMAP2_IO_ADDRESS(OMAP_UART4_BASE), + .mapbase = OMAP_UART4_BASE, + .irq = 70, + .flags = UPF_BOOT_AUTOCONF, +@@ -126,7 +122,6 @@ static struct plat_serial8250_port serial_platform_data2[] = { + #ifdef CONFIG_ARCH_OMAP4 + static struct plat_serial8250_port serial_platform_data3[] = { + { +- .membase = OMAP2_IO_ADDRESS(OMAP_UART4_BASE), + .mapbase = OMAP_UART4_BASE, + .irq = 70, + .flags = UPF_BOOT_AUTOCONF, +@@ -549,7 +544,7 @@ static inline void omap_uart_idle_init(struct omap_uart_state *uart) {} + #define DEV_CREATE_FILE(dev, attr) + #endif /* CONFIG_PM */ + +-static struct omap_uart_state omap_uart[OMAP_MAX_NR_PORTS] = { ++static struct omap_uart_state omap_uart[] = { + { + .pdev = { + .name = "serial8250", +@@ -599,12 +594,22 @@ void __init omap_serial_early_init(void) + * if not needed. + */ + +- for (i = 0; i < OMAP_MAX_NR_PORTS; i++) { ++ for (i = 0; i < ARRAY_SIZE(omap_uart); i++) { + struct omap_uart_state *uart = &omap_uart[i]; + struct platform_device *pdev = &uart->pdev; + struct device *dev = &pdev->dev; + struct plat_serial8250_port *p = dev->platform_data; + ++ /* ++ * Module 4KB + L4 interconnect 4KB ++ * Static mapping, never released ++ */ ++ p->membase = ioremap(p->mapbase, SZ_8K); ++ if (!p->membase) { ++ printk(KERN_ERR "ioremap failed for uart%i\n", i + 1); ++ continue; ++ } ++ + sprintf(name, "uart%d_ick", i+1); + uart->ick = clk_get(NULL, name); + if (IS_ERR(uart->ick)) { +@@ -641,7 +646,7 @@ void __init omap_serial_init(void) + { + int i; + +- for (i = 0; i < OMAP_MAX_NR_PORTS; i++) { ++ for (i = 0; i < ARRAY_SIZE(omap_uart); i++) { + struct omap_uart_state *uart = &omap_uart[i]; + struct platform_device *pdev = &uart->pdev; + struct device *dev = &pdev->dev; +diff --git a/arch/arm/mach-omap2/sram242x.S b/arch/arm/mach-omap2/sram242x.S +index 9b62208..92e6e1a 100644 +--- a/arch/arm/mach-omap2/sram242x.S ++++ b/arch/arm/mach-omap2/sram242x.S +@@ -128,7 +128,7 @@ omap242x_sdi_prcm_voltctrl: + prcm_mask_val: + .word 0xFFFF3FFC + omap242x_sdi_timer_32ksynct_cr: +- .word OMAP2_IO_ADDRESS(OMAP2420_32KSYNCT_BASE + 0x010) ++ .word OMAP2_L4_IO_ADDRESS(OMAP2420_32KSYNCT_BASE + 0x010) + ENTRY(omap242x_sram_ddr_init_sz) + .word . - omap242x_sram_ddr_init + +@@ -224,7 +224,7 @@ omap242x_srs_prcm_voltctrl: + ddr_prcm_mask_val: + .word 0xFFFF3FFC + omap242x_srs_timer_32ksynct: +- .word OMAP2_IO_ADDRESS(OMAP2420_32KSYNCT_BASE + 0x010) ++ .word OMAP2_L4_IO_ADDRESS(OMAP2420_32KSYNCT_BASE + 0x010) + + ENTRY(omap242x_sram_reprogram_sdrc_sz) + .word . - omap242x_sram_reprogram_sdrc +diff --git a/arch/arm/mach-omap2/sram243x.S b/arch/arm/mach-omap2/sram243x.S +index df2cd92..ab49736 100644 +--- a/arch/arm/mach-omap2/sram243x.S ++++ b/arch/arm/mach-omap2/sram243x.S +@@ -128,7 +128,7 @@ omap243x_sdi_prcm_voltctrl: + prcm_mask_val: + .word 0xFFFF3FFC + omap243x_sdi_timer_32ksynct_cr: +- .word OMAP2_IO_ADDRESS(OMAP2430_32KSYNCT_BASE + 0x010) ++ .word OMAP2_L4_IO_ADDRESS(OMAP2430_32KSYNCT_BASE + 0x010) + ENTRY(omap243x_sram_ddr_init_sz) + .word . - omap243x_sram_ddr_init + +@@ -224,7 +224,7 @@ omap243x_srs_prcm_voltctrl: + ddr_prcm_mask_val: + .word 0xFFFF3FFC + omap243x_srs_timer_32ksynct: +- .word OMAP2_IO_ADDRESS(OMAP2430_32KSYNCT_BASE + 0x010) ++ .word OMAP2_L4_IO_ADDRESS(OMAP2430_32KSYNCT_BASE + 0x010) + + ENTRY(omap243x_sram_reprogram_sdrc_sz) + .word . - omap243x_sram_reprogram_sdrc +diff --git a/arch/arm/mach-omap2/timer-gp.c b/arch/arm/mach-omap2/timer-gp.c +index e2338c0..cd72970 100644 +--- a/arch/arm/mach-omap2/timer-gp.c ++++ b/arch/arm/mach-omap2/timer-gp.c +@@ -231,7 +231,8 @@ static void __init omap2_gp_clocksource_init(void) + static void __init omap2_gp_timer_init(void) + { + #ifdef CONFIG_LOCAL_TIMERS +- twd_base = OMAP2_IO_ADDRESS(OMAP44XX_LOCAL_TWD_BASE); ++ twd_base = ioremap(OMAP44XX_LOCAL_TWD_BASE, SZ_256); ++ BUG_ON(!twd_base); + #endif + omap_dm_timer_init(); + +diff --git a/arch/arm/mach-omap2/usb-ehci.c b/arch/arm/mach-omap2/usb-ehci.c +new file mode 100644 +index 0000000..a29c8ca +--- /dev/null ++++ b/arch/arm/mach-omap2/usb-ehci.c +@@ -0,0 +1,192 @@ ++/* ++ * linux/arch/arm/mach-omap2/usb-ehci.c ++ * ++ * This file will contain the board specific details for the ++ * Synopsys EHCI host controller on OMAP3430 ++ * ++ * Copyright (C) 2007 Texas Instruments ++ * Author: Vikram Pandita ++ * ++ * Generalization by: ++ * Felipe Balbi ++ * ++ * 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 ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++#if defined(CONFIG_USB_EHCI_HCD) || defined(CONFIG_USB_EHCI_HCD_MODULE) ++ ++static struct resource ehci_resources[] = { ++ { ++ .start = OMAP34XX_EHCI_BASE, ++ .end = OMAP34XX_EHCI_BASE + SZ_1K - 1, ++ .flags = IORESOURCE_MEM, ++ }, ++ { ++ .start = OMAP34XX_UHH_CONFIG_BASE, ++ .end = OMAP34XX_UHH_CONFIG_BASE + SZ_1K - 1, ++ .flags = IORESOURCE_MEM, ++ }, ++ { ++ .start = OMAP34XX_USBTLL_BASE, ++ .end = OMAP34XX_USBTLL_BASE + SZ_4K - 1, ++ .flags = IORESOURCE_MEM, ++ }, ++ { /* general IRQ */ ++ .start = INT_34XX_EHCI_IRQ, ++ .flags = IORESOURCE_IRQ, ++ } ++}; ++ ++static u64 ehci_dmamask = ~(u32)0; ++static struct platform_device ehci_device = { ++ .name = "ehci-omap", ++ .id = 0, ++ .dev = { ++ .dma_mask = &ehci_dmamask, ++ .coherent_dma_mask = 0xffffffff, ++ .platform_data = NULL, ++ }, ++ .num_resources = ARRAY_SIZE(ehci_resources), ++ .resource = ehci_resources, ++}; ++ ++/* MUX settings for EHCI pins */ ++/* ++ * setup_ehci_io_mux - initialize IO pad mux for USBHOST ++ */ ++static void setup_ehci_io_mux(enum ehci_hcd_omap_mode *port_mode) ++{ ++ switch (port_mode[0]) { ++ case EHCI_HCD_OMAP_MODE_PHY: ++ omap_cfg_reg(Y9_3430_USB1HS_PHY_STP); ++ omap_cfg_reg(Y8_3430_USB1HS_PHY_CLK); ++ omap_cfg_reg(AA14_3430_USB1HS_PHY_DIR); ++ omap_cfg_reg(AA11_3430_USB1HS_PHY_NXT); ++ omap_cfg_reg(W13_3430_USB1HS_PHY_DATA0); ++ omap_cfg_reg(W12_3430_USB1HS_PHY_DATA1); ++ omap_cfg_reg(W11_3430_USB1HS_PHY_DATA2); ++ omap_cfg_reg(Y11_3430_USB1HS_PHY_DATA3); ++ omap_cfg_reg(W9_3430_USB1HS_PHY_DATA4); ++ omap_cfg_reg(Y12_3430_USB1HS_PHY_DATA5); ++ omap_cfg_reg(W8_3430_USB1HS_PHY_DATA6); ++ omap_cfg_reg(Y13_3430_USB1HS_PHY_DATA7); ++ break; ++ case EHCI_HCD_OMAP_MODE_TLL: ++ omap_cfg_reg(Y9_3430_USB1HS_TLL_STP); ++ omap_cfg_reg(Y8_3430_USB1HS_TLL_CLK); ++ omap_cfg_reg(AA14_3430_USB1HS_TLL_DIR); ++ omap_cfg_reg(AA11_3430_USB1HS_TLL_NXT); ++ omap_cfg_reg(W13_3430_USB1HS_TLL_DATA0); ++ omap_cfg_reg(W12_3430_USB1HS_TLL_DATA1); ++ omap_cfg_reg(W11_3430_USB1HS_TLL_DATA2); ++ omap_cfg_reg(Y11_3430_USB1HS_TLL_DATA3); ++ omap_cfg_reg(W9_3430_USB1HS_TLL_DATA4); ++ omap_cfg_reg(Y12_3430_USB1HS_TLL_DATA5); ++ omap_cfg_reg(W8_3430_USB1HS_TLL_DATA6); ++ omap_cfg_reg(Y13_3430_USB1HS_TLL_DATA7); ++ break; ++ case EHCI_HCD_OMAP_MODE_UNKNOWN: ++ /* FALLTHROUGH */ ++ default: ++ break; ++ } ++ ++ switch (port_mode[1]) { ++ case EHCI_HCD_OMAP_MODE_PHY: ++ omap_cfg_reg(AA10_3430_USB2HS_PHY_STP); ++ omap_cfg_reg(AA8_3430_USB2HS_PHY_CLK); ++ omap_cfg_reg(AA9_3430_USB2HS_PHY_DIR); ++ omap_cfg_reg(AB11_3430_USB2HS_PHY_NXT); ++ omap_cfg_reg(AB10_3430_USB2HS_PHY_DATA0); ++ omap_cfg_reg(AB9_3430_USB2HS_PHY_DATA1); ++ omap_cfg_reg(W3_3430_USB2HS_PHY_DATA2); ++ omap_cfg_reg(T4_3430_USB2HS_PHY_DATA3); ++ omap_cfg_reg(T3_3430_USB2HS_PHY_DATA4); ++ omap_cfg_reg(R3_3430_USB2HS_PHY_DATA5); ++ omap_cfg_reg(R4_3430_USB2HS_PHY_DATA6); ++ omap_cfg_reg(T2_3430_USB2HS_PHY_DATA7); ++ break; ++ case EHCI_HCD_OMAP_MODE_TLL: ++ omap_cfg_reg(AA10_3430_USB2HS_TLL_STP); ++ omap_cfg_reg(AA8_3430_USB2HS_TLL_CLK); ++ omap_cfg_reg(AA9_3430_USB2HS_TLL_DIR); ++ omap_cfg_reg(AB11_3430_USB2HS_TLL_NXT); ++ omap_cfg_reg(AB10_3430_USB2HS_TLL_DATA0); ++ omap_cfg_reg(AB9_3430_USB2HS_TLL_DATA1); ++ omap_cfg_reg(W3_3430_USB2HS_TLL_DATA2); ++ omap_cfg_reg(T4_3430_USB2HS_TLL_DATA3); ++ omap_cfg_reg(T3_3430_USB2HS_TLL_DATA4); ++ omap_cfg_reg(R3_3430_USB2HS_TLL_DATA5); ++ omap_cfg_reg(R4_3430_USB2HS_TLL_DATA6); ++ omap_cfg_reg(T2_3430_USB2HS_TLL_DATA7); ++ break; ++ case EHCI_HCD_OMAP_MODE_UNKNOWN: ++ /* FALLTHROUGH */ ++ default: ++ break; ++ } ++ ++ switch (port_mode[2]) { ++ case EHCI_HCD_OMAP_MODE_PHY: ++ printk(KERN_WARNING "Port3 can't be used in PHY mode\n"); ++ break; ++ case EHCI_HCD_OMAP_MODE_TLL: ++ omap_cfg_reg(AB3_3430_USB3HS_TLL_STP); ++ omap_cfg_reg(AA6_3430_USB3HS_TLL_CLK); ++ omap_cfg_reg(AA3_3430_USB3HS_TLL_DIR); ++ omap_cfg_reg(Y3_3430_USB3HS_TLL_NXT); ++ omap_cfg_reg(AA5_3430_USB3HS_TLL_DATA0); ++ omap_cfg_reg(Y4_3430_USB3HS_TLL_DATA1); ++ omap_cfg_reg(Y5_3430_USB3HS_TLL_DATA2); ++ omap_cfg_reg(W5_3430_USB3HS_TLL_DATA3); ++ omap_cfg_reg(AB12_3430_USB3HS_TLL_DATA4); ++ omap_cfg_reg(AB13_3430_USB3HS_TLL_DATA5); ++ omap_cfg_reg(AA13_3430_USB3HS_TLL_DATA6); ++ omap_cfg_reg(AA12_3430_USB3HS_TLL_DATA7); ++ break; ++ case EHCI_HCD_OMAP_MODE_UNKNOWN: ++ /* FALLTHROUGH */ ++ default: ++ break; ++ } ++ ++ return; ++} ++ ++void __init usb_ehci_init(struct ehci_hcd_omap_platform_data *pdata) ++{ ++ platform_device_add_data(&ehci_device, pdata, sizeof(*pdata)); ++ ++ /* Setup Pin IO MUX for EHCI */ ++ if (cpu_is_omap34xx()) ++ setup_ehci_io_mux(pdata->port_mode); ++ ++ if (platform_device_register(&ehci_device) < 0) { ++ printk(KERN_ERR "Unable to register HS-USB (EHCI) device\n"); ++ return; ++ } ++} ++ ++#else ++ ++void __init usb_ehci_init(struct ehci_hcd_omap_platform_data *pdata) ++ ++{ ++} ++ ++#endif /* CONFIG_USB_EHCI_HCD */ ++ +diff --git a/arch/arm/plat-omap/common.c b/arch/arm/plat-omap/common.c +index 3a4768d..1aa58d2 100644 +--- a/arch/arm/plat-omap/common.c ++++ b/arch/arm/plat-omap/common.c +@@ -224,12 +224,12 @@ static void __init __omap2_set_globals(struct omap_globals *omap2_globals) + + static struct omap_globals omap242x_globals = { + .class = OMAP242X_CLASS, +- .tap = OMAP2_IO_ADDRESS(0x48014000), +- .sdrc = OMAP2_IO_ADDRESS(OMAP2420_SDRC_BASE), +- .sms = OMAP2_IO_ADDRESS(OMAP2420_SMS_BASE), +- .ctrl = OMAP2_IO_ADDRESS(OMAP2420_CTRL_BASE), +- .prm = OMAP2_IO_ADDRESS(OMAP2420_PRM_BASE), +- .cm = OMAP2_IO_ADDRESS(OMAP2420_CM_BASE), ++ .tap = OMAP2_L4_IO_ADDRESS(0x48014000), ++ .sdrc = OMAP2_L3_IO_ADDRESS(OMAP2420_SDRC_BASE), ++ .sms = OMAP2_L3_IO_ADDRESS(OMAP2420_SMS_BASE), ++ .ctrl = OMAP2_L4_IO_ADDRESS(OMAP2420_CTRL_BASE), ++ .prm = OMAP2_L4_IO_ADDRESS(OMAP2420_PRM_BASE), ++ .cm = OMAP2_L4_IO_ADDRESS(OMAP2420_CM_BASE), + }; + + void __init omap2_set_globals_242x(void) +@@ -242,12 +242,12 @@ void __init omap2_set_globals_242x(void) + + static struct omap_globals omap243x_globals = { + .class = OMAP243X_CLASS, +- .tap = OMAP2_IO_ADDRESS(0x4900a000), +- .sdrc = OMAP2_IO_ADDRESS(OMAP243X_SDRC_BASE), +- .sms = OMAP2_IO_ADDRESS(OMAP243X_SMS_BASE), +- .ctrl = OMAP2_IO_ADDRESS(OMAP243X_CTRL_BASE), +- .prm = OMAP2_IO_ADDRESS(OMAP2430_PRM_BASE), +- .cm = OMAP2_IO_ADDRESS(OMAP2430_CM_BASE), ++ .tap = OMAP2_L4_IO_ADDRESS(0x4900a000), ++ .sdrc = OMAP2_L3_IO_ADDRESS(OMAP243X_SDRC_BASE), ++ .sms = OMAP2_L3_IO_ADDRESS(OMAP243X_SMS_BASE), ++ .ctrl = OMAP2_L4_IO_ADDRESS(OMAP243X_CTRL_BASE), ++ .prm = OMAP2_L4_IO_ADDRESS(OMAP2430_PRM_BASE), ++ .cm = OMAP2_L4_IO_ADDRESS(OMAP2430_CM_BASE), + }; + + void __init omap2_set_globals_243x(void) +@@ -260,12 +260,12 @@ void __init omap2_set_globals_243x(void) + + static struct omap_globals omap343x_globals = { + .class = OMAP343X_CLASS, +- .tap = OMAP2_IO_ADDRESS(0x4830A000), +- .sdrc = OMAP2_IO_ADDRESS(OMAP343X_SDRC_BASE), +- .sms = OMAP2_IO_ADDRESS(OMAP343X_SMS_BASE), +- .ctrl = OMAP2_IO_ADDRESS(OMAP343X_CTRL_BASE), +- .prm = OMAP2_IO_ADDRESS(OMAP3430_PRM_BASE), +- .cm = OMAP2_IO_ADDRESS(OMAP3430_CM_BASE), ++ .tap = OMAP2_L4_IO_ADDRESS(0x4830A000), ++ .sdrc = OMAP2_L3_IO_ADDRESS(OMAP343X_SDRC_BASE), ++ .sms = OMAP2_L3_IO_ADDRESS(OMAP343X_SMS_BASE), ++ .ctrl = OMAP2_L4_IO_ADDRESS(OMAP343X_CTRL_BASE), ++ .prm = OMAP2_L4_IO_ADDRESS(OMAP3430_PRM_BASE), ++ .cm = OMAP2_L4_IO_ADDRESS(OMAP3430_CM_BASE), + }; + + void __init omap2_set_globals_343x(void) +@@ -277,10 +277,10 @@ void __init omap2_set_globals_343x(void) + #if defined(CONFIG_ARCH_OMAP4) + static struct omap_globals omap4_globals = { + .class = OMAP443X_CLASS, +- .tap = OMAP2_IO_ADDRESS(0x4830a000), +- .ctrl = OMAP2_IO_ADDRESS(OMAP443X_CTRL_BASE), +- .prm = OMAP2_IO_ADDRESS(OMAP4430_PRM_BASE), +- .cm = OMAP2_IO_ADDRESS(OMAP4430_CM_BASE), ++ .tap = OMAP2_L4_IO_ADDRESS(0x4830a000), ++ .ctrl = OMAP2_L4_IO_ADDRESS(OMAP443X_CTRL_BASE), ++ .prm = OMAP2_L4_IO_ADDRESS(OMAP4430_PRM_BASE), ++ .cm = OMAP2_L4_IO_ADDRESS(OMAP4430_CM_BASE), + }; + + void __init omap2_set_globals_443x(void) +diff --git a/arch/arm/plat-omap/devices.c b/arch/arm/plat-omap/devices.c +index a64b692..d2f5475 100644 +--- a/arch/arm/plat-omap/devices.c ++++ b/arch/arm/plat-omap/devices.c +@@ -113,17 +113,17 @@ static void omap_init_kp(void) + omap_cfg_reg(E19_1610_KBR4); + omap_cfg_reg(N19_1610_KBR5); + } else if (machine_is_omap_perseus2() || machine_is_omap_fsample()) { +- omap_cfg_reg(E2_730_KBR0); +- omap_cfg_reg(J7_730_KBR1); +- omap_cfg_reg(E1_730_KBR2); +- omap_cfg_reg(F3_730_KBR3); +- omap_cfg_reg(D2_730_KBR4); +- +- omap_cfg_reg(C2_730_KBC0); +- omap_cfg_reg(D3_730_KBC1); +- omap_cfg_reg(E4_730_KBC2); +- omap_cfg_reg(F4_730_KBC3); +- omap_cfg_reg(E3_730_KBC4); ++ omap_cfg_reg(E2_7XX_KBR0); ++ omap_cfg_reg(J7_7XX_KBR1); ++ omap_cfg_reg(E1_7XX_KBR2); ++ omap_cfg_reg(F3_7XX_KBR3); ++ omap_cfg_reg(D2_7XX_KBR4); ++ ++ omap_cfg_reg(C2_7XX_KBC0); ++ omap_cfg_reg(D3_7XX_KBC1); ++ omap_cfg_reg(E4_7XX_KBC2); ++ omap_cfg_reg(F4_7XX_KBC3); ++ omap_cfg_reg(E3_7XX_KBC4); + } else if (machine_is_omap_h4()) { + omap_cfg_reg(T19_24XX_KBR0); + omap_cfg_reg(R19_24XX_KBR1); +diff --git a/arch/arm/plat-omap/dma.c b/arch/arm/plat-omap/dma.c +index 0eb676d..034686d 100644 +--- a/arch/arm/plat-omap/dma.c ++++ b/arch/arm/plat-omap/dma.c +@@ -2347,40 +2347,46 @@ EXPORT_SYMBOL(omap_stop_lcd_dma); + + static int __init omap_init_dma(void) + { ++ unsigned long base; + int ch, r; + + if (cpu_class_is_omap1()) { +- omap_dma_base = OMAP1_IO_ADDRESS(OMAP1_DMA_BASE); ++ base = OMAP1_DMA_BASE; + dma_lch_count = OMAP1_LOGICAL_DMA_CH_COUNT; + } else if (cpu_is_omap24xx()) { +- omap_dma_base = OMAP2_IO_ADDRESS(OMAP24XX_DMA4_BASE); ++ base = OMAP24XX_DMA4_BASE; + dma_lch_count = OMAP_DMA4_LOGICAL_DMA_CH_COUNT; + } else if (cpu_is_omap34xx()) { +- omap_dma_base = OMAP2_IO_ADDRESS(OMAP34XX_DMA4_BASE); ++ base = OMAP34XX_DMA4_BASE; + dma_lch_count = OMAP_DMA4_LOGICAL_DMA_CH_COUNT; + } else if (cpu_is_omap44xx()) { +- omap_dma_base = OMAP2_IO_ADDRESS(OMAP44XX_DMA4_BASE); ++ base = OMAP44XX_DMA4_BASE; + dma_lch_count = OMAP_DMA4_LOGICAL_DMA_CH_COUNT; + } else { + pr_err("DMA init failed for unsupported omap\n"); + return -ENODEV; + } + ++ omap_dma_base = ioremap(base, SZ_4K); ++ BUG_ON(!omap_dma_base); ++ + if (cpu_class_is_omap2() && omap_dma_reserve_channels + && (omap_dma_reserve_channels <= dma_lch_count)) + dma_lch_count = omap_dma_reserve_channels; + + dma_chan = kzalloc(sizeof(struct omap_dma_lch) * dma_lch_count, + GFP_KERNEL); +- if (!dma_chan) +- return -ENOMEM; ++ if (!dma_chan) { ++ r = -ENOMEM; ++ goto out_unmap; ++ } + + if (cpu_class_is_omap2()) { + dma_linked_lch = kzalloc(sizeof(struct dma_link_info) * + dma_lch_count, GFP_KERNEL); + if (!dma_linked_lch) { +- kfree(dma_chan); +- return -ENOMEM; ++ r = -ENOMEM; ++ goto out_free; + } + } + +@@ -2454,7 +2460,7 @@ static int __init omap_init_dma(void) + for (i = 0; i < ch; i++) + free_irq(omap1_dma_irq[i], + (void *) (i + 1)); +- return r; ++ goto out_free; + } + } + } +@@ -2496,11 +2502,19 @@ static int __init omap_init_dma(void) + "(error %d)\n", r); + for (i = 0; i < dma_chan_count; i++) + free_irq(omap1_dma_irq[i], (void *) (i + 1)); +- return r; ++ goto out_free; + } + } + + return 0; ++ ++out_free: ++ kfree(dma_chan); ++ ++out_unmap: ++ iounmap(omap_dma_base); ++ ++ return r; + } + + arch_initcall(omap_init_dma); +diff --git a/arch/arm/plat-omap/dmtimer.c b/arch/arm/plat-omap/dmtimer.c +index d325b54..e4e848e 100644 +--- a/arch/arm/plat-omap/dmtimer.c ++++ b/arch/arm/plat-omap/dmtimer.c +@@ -742,16 +742,17 @@ EXPORT_SYMBOL_GPL(omap_dm_timers_active); + int __init omap_dm_timer_init(void) + { + struct omap_dm_timer *timer; +- int i; ++ int i, map_size = SZ_8K; /* Module 4KB + L4 4KB except on omap1 */ + + if (!(cpu_is_omap16xx() || cpu_class_is_omap2())) + return -ENODEV; + + spin_lock_init(&dm_timer_lock); + +- if (cpu_class_is_omap1()) ++ if (cpu_class_is_omap1()) { + dm_timers = omap1_dm_timers; +- else if (cpu_is_omap24xx()) { ++ map_size = SZ_2K; ++ } else if (cpu_is_omap24xx()) { + dm_timers = omap2_dm_timers; + dm_source_names = omap2_dm_source_names; + dm_source_clocks = omap2_dm_source_clocks; +@@ -774,10 +775,11 @@ int __init omap_dm_timer_init(void) + + for (i = 0; i < dm_timer_count; i++) { + timer = &dm_timers[i]; +- if (cpu_class_is_omap1()) +- timer->io_base = OMAP1_IO_ADDRESS(timer->phys_base); +- else +- timer->io_base = OMAP2_IO_ADDRESS(timer->phys_base); ++ ++ /* Static mapping, never released */ ++ timer->io_base = ioremap(timer->phys_base, map_size); ++ BUG_ON(!timer->io_base); ++ + #if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3) || \ + defined(CONFIG_ARCH_OMAP4) + if (cpu_class_is_omap2()) { +diff --git a/arch/arm/plat-omap/gpio.c b/arch/arm/plat-omap/gpio.c +index 71ebd7f..14c3506 100644 +--- a/arch/arm/plat-omap/gpio.c ++++ b/arch/arm/plat-omap/gpio.c +@@ -31,7 +31,7 @@ + /* + * OMAP1510 GPIO registers + */ +-#define OMAP1510_GPIO_BASE OMAP1_IO_ADDRESS(0xfffce000) ++#define OMAP1510_GPIO_BASE 0xfffce000 + #define OMAP1510_GPIO_DATA_INPUT 0x00 + #define OMAP1510_GPIO_DATA_OUTPUT 0x04 + #define OMAP1510_GPIO_DIR_CONTROL 0x08 +@@ -45,10 +45,10 @@ + /* + * OMAP1610 specific GPIO registers + */ +-#define OMAP1610_GPIO1_BASE OMAP1_IO_ADDRESS(0xfffbe400) +-#define OMAP1610_GPIO2_BASE OMAP1_IO_ADDRESS(0xfffbec00) +-#define OMAP1610_GPIO3_BASE OMAP1_IO_ADDRESS(0xfffbb400) +-#define OMAP1610_GPIO4_BASE OMAP1_IO_ADDRESS(0xfffbbc00) ++#define OMAP1610_GPIO1_BASE 0xfffbe400 ++#define OMAP1610_GPIO2_BASE 0xfffbec00 ++#define OMAP1610_GPIO3_BASE 0xfffbb400 ++#define OMAP1610_GPIO4_BASE 0xfffbbc00 + #define OMAP1610_GPIO_REVISION 0x0000 + #define OMAP1610_GPIO_SYSCONFIG 0x0010 + #define OMAP1610_GPIO_SYSSTATUS 0x0014 +@@ -68,52 +68,36 @@ + #define OMAP1610_GPIO_SET_DATAOUT 0x00f0 + + /* +- * OMAP730 specific GPIO registers ++ * OMAP7XX specific GPIO registers + */ +-#define OMAP730_GPIO1_BASE OMAP1_IO_ADDRESS(0xfffbc000) +-#define OMAP730_GPIO2_BASE OMAP1_IO_ADDRESS(0xfffbc800) +-#define OMAP730_GPIO3_BASE OMAP1_IO_ADDRESS(0xfffbd000) +-#define OMAP730_GPIO4_BASE OMAP1_IO_ADDRESS(0xfffbd800) +-#define OMAP730_GPIO5_BASE OMAP1_IO_ADDRESS(0xfffbe000) +-#define OMAP730_GPIO6_BASE OMAP1_IO_ADDRESS(0xfffbe800) +-#define OMAP730_GPIO_DATA_INPUT 0x00 +-#define OMAP730_GPIO_DATA_OUTPUT 0x04 +-#define OMAP730_GPIO_DIR_CONTROL 0x08 +-#define OMAP730_GPIO_INT_CONTROL 0x0c +-#define OMAP730_GPIO_INT_MASK 0x10 +-#define OMAP730_GPIO_INT_STATUS 0x14 +- +-/* +- * OMAP850 specific GPIO registers +- */ +-#define OMAP850_GPIO1_BASE OMAP1_IO_ADDRESS(0xfffbc000) +-#define OMAP850_GPIO2_BASE OMAP1_IO_ADDRESS(0xfffbc800) +-#define OMAP850_GPIO3_BASE OMAP1_IO_ADDRESS(0xfffbd000) +-#define OMAP850_GPIO4_BASE OMAP1_IO_ADDRESS(0xfffbd800) +-#define OMAP850_GPIO5_BASE OMAP1_IO_ADDRESS(0xfffbe000) +-#define OMAP850_GPIO6_BASE OMAP1_IO_ADDRESS(0xfffbe800) +-#define OMAP850_GPIO_DATA_INPUT 0x00 +-#define OMAP850_GPIO_DATA_OUTPUT 0x04 +-#define OMAP850_GPIO_DIR_CONTROL 0x08 +-#define OMAP850_GPIO_INT_CONTROL 0x0c +-#define OMAP850_GPIO_INT_MASK 0x10 +-#define OMAP850_GPIO_INT_STATUS 0x14 +- +-#define OMAP1_MPUIO_VBASE OMAP1_IO_ADDRESS(OMAP1_MPUIO_BASE) ++#define OMAP7XX_GPIO1_BASE 0xfffbc000 ++#define OMAP7XX_GPIO2_BASE 0xfffbc800 ++#define OMAP7XX_GPIO3_BASE 0xfffbd000 ++#define OMAP7XX_GPIO4_BASE 0xfffbd800 ++#define OMAP7XX_GPIO5_BASE 0xfffbe000 ++#define OMAP7XX_GPIO6_BASE 0xfffbe800 ++#define OMAP7XX_GPIO_DATA_INPUT 0x00 ++#define OMAP7XX_GPIO_DATA_OUTPUT 0x04 ++#define OMAP7XX_GPIO_DIR_CONTROL 0x08 ++#define OMAP7XX_GPIO_INT_CONTROL 0x0c ++#define OMAP7XX_GPIO_INT_MASK 0x10 ++#define OMAP7XX_GPIO_INT_STATUS 0x14 ++ ++#define OMAP1_MPUIO_VBASE OMAP1_MPUIO_BASE + + /* + * omap24xx specific GPIO registers + */ +-#define OMAP242X_GPIO1_BASE OMAP2_IO_ADDRESS(0x48018000) +-#define OMAP242X_GPIO2_BASE OMAP2_IO_ADDRESS(0x4801a000) +-#define OMAP242X_GPIO3_BASE OMAP2_IO_ADDRESS(0x4801c000) +-#define OMAP242X_GPIO4_BASE OMAP2_IO_ADDRESS(0x4801e000) ++#define OMAP242X_GPIO1_BASE 0x48018000 ++#define OMAP242X_GPIO2_BASE 0x4801a000 ++#define OMAP242X_GPIO3_BASE 0x4801c000 ++#define OMAP242X_GPIO4_BASE 0x4801e000 + +-#define OMAP243X_GPIO1_BASE OMAP2_IO_ADDRESS(0x4900C000) +-#define OMAP243X_GPIO2_BASE OMAP2_IO_ADDRESS(0x4900E000) +-#define OMAP243X_GPIO3_BASE OMAP2_IO_ADDRESS(0x49010000) +-#define OMAP243X_GPIO4_BASE OMAP2_IO_ADDRESS(0x49012000) +-#define OMAP243X_GPIO5_BASE OMAP2_IO_ADDRESS(0x480B6000) ++#define OMAP243X_GPIO1_BASE 0x4900C000 ++#define OMAP243X_GPIO2_BASE 0x4900E000 ++#define OMAP243X_GPIO3_BASE 0x49010000 ++#define OMAP243X_GPIO4_BASE 0x49012000 ++#define OMAP243X_GPIO5_BASE 0x480B6000 + + #define OMAP24XX_GPIO_REVISION 0x0000 + #define OMAP24XX_GPIO_SYSCONFIG 0x0010 +@@ -170,24 +154,25 @@ + * omap34xx specific GPIO registers + */ + +-#define OMAP34XX_GPIO1_BASE OMAP2_IO_ADDRESS(0x48310000) +-#define OMAP34XX_GPIO2_BASE OMAP2_IO_ADDRESS(0x49050000) +-#define OMAP34XX_GPIO3_BASE OMAP2_IO_ADDRESS(0x49052000) +-#define OMAP34XX_GPIO4_BASE OMAP2_IO_ADDRESS(0x49054000) +-#define OMAP34XX_GPIO5_BASE OMAP2_IO_ADDRESS(0x49056000) +-#define OMAP34XX_GPIO6_BASE OMAP2_IO_ADDRESS(0x49058000) ++#define OMAP34XX_GPIO1_BASE 0x48310000 ++#define OMAP34XX_GPIO2_BASE 0x49050000 ++#define OMAP34XX_GPIO3_BASE 0x49052000 ++#define OMAP34XX_GPIO4_BASE 0x49054000 ++#define OMAP34XX_GPIO5_BASE 0x49056000 ++#define OMAP34XX_GPIO6_BASE 0x49058000 + + /* + * OMAP44XX specific GPIO registers + */ +-#define OMAP44XX_GPIO1_BASE OMAP2_IO_ADDRESS(0x4a310000) +-#define OMAP44XX_GPIO2_BASE OMAP2_IO_ADDRESS(0x48055000) +-#define OMAP44XX_GPIO3_BASE OMAP2_IO_ADDRESS(0x48057000) +-#define OMAP44XX_GPIO4_BASE OMAP2_IO_ADDRESS(0x48059000) +-#define OMAP44XX_GPIO5_BASE OMAP2_IO_ADDRESS(0x4805B000) +-#define OMAP44XX_GPIO6_BASE OMAP2_IO_ADDRESS(0x4805D000) ++#define OMAP44XX_GPIO1_BASE 0x4a310000 ++#define OMAP44XX_GPIO2_BASE 0x48055000 ++#define OMAP44XX_GPIO3_BASE 0x48057000 ++#define OMAP44XX_GPIO4_BASE 0x48059000 ++#define OMAP44XX_GPIO5_BASE 0x4805B000 ++#define OMAP44XX_GPIO6_BASE 0x4805D000 + + struct gpio_bank { ++ unsigned long pbase; + void __iomem *base; + u16 irq; + u16 virtual_irq_start; +@@ -215,96 +200,111 @@ struct gpio_bank { + #define METHOD_MPUIO 0 + #define METHOD_GPIO_1510 1 + #define METHOD_GPIO_1610 2 +-#define METHOD_GPIO_730 3 +-#define METHOD_GPIO_850 4 ++#define METHOD_GPIO_7XX 3 + #define METHOD_GPIO_24XX 5 + + #ifdef CONFIG_ARCH_OMAP16XX + static struct gpio_bank gpio_bank_1610[5] = { +- { OMAP1_MPUIO_VBASE, INT_MPUIO, IH_MPUIO_BASE, METHOD_MPUIO}, +- { OMAP1610_GPIO1_BASE, INT_GPIO_BANK1, IH_GPIO_BASE, METHOD_GPIO_1610 }, +- { OMAP1610_GPIO2_BASE, INT_1610_GPIO_BANK2, IH_GPIO_BASE + 16, METHOD_GPIO_1610 }, +- { OMAP1610_GPIO3_BASE, INT_1610_GPIO_BANK3, IH_GPIO_BASE + 32, METHOD_GPIO_1610 }, +- { OMAP1610_GPIO4_BASE, INT_1610_GPIO_BANK4, IH_GPIO_BASE + 48, METHOD_GPIO_1610 }, ++ { OMAP1_MPUIO_VBASE, 0, INT_MPUIO, IH_MPUIO_BASE, ++ METHOD_MPUIO }, ++ { OMAP1610_GPIO1_BASE, 0, INT_GPIO_BANK1, IH_GPIO_BASE, ++ METHOD_GPIO_1610 }, ++ { OMAP1610_GPIO2_BASE, 0, INT_1610_GPIO_BANK2, IH_GPIO_BASE + 16, ++ METHOD_GPIO_1610 }, ++ { OMAP1610_GPIO3_BASE, 0, INT_1610_GPIO_BANK3, IH_GPIO_BASE + 32, ++ METHOD_GPIO_1610 }, ++ { OMAP1610_GPIO4_BASE, 0, INT_1610_GPIO_BANK4, IH_GPIO_BASE + 48, ++ METHOD_GPIO_1610 }, + }; + #endif + + #ifdef CONFIG_ARCH_OMAP15XX + static struct gpio_bank gpio_bank_1510[2] = { +- { OMAP1_MPUIO_VBASE, INT_MPUIO, IH_MPUIO_BASE, METHOD_MPUIO }, +- { OMAP1510_GPIO_BASE, INT_GPIO_BANK1, IH_GPIO_BASE, METHOD_GPIO_1510 } +-}; +-#endif +- +-#ifdef CONFIG_ARCH_OMAP730 +-static struct gpio_bank gpio_bank_730[7] = { +- { OMAP1_MPUIO_VBASE, INT_730_MPUIO, IH_MPUIO_BASE, METHOD_MPUIO }, +- { OMAP730_GPIO1_BASE, INT_730_GPIO_BANK1, IH_GPIO_BASE, METHOD_GPIO_730 }, +- { OMAP730_GPIO2_BASE, INT_730_GPIO_BANK2, IH_GPIO_BASE + 32, METHOD_GPIO_730 }, +- { OMAP730_GPIO3_BASE, INT_730_GPIO_BANK3, IH_GPIO_BASE + 64, METHOD_GPIO_730 }, +- { OMAP730_GPIO4_BASE, INT_730_GPIO_BANK4, IH_GPIO_BASE + 96, METHOD_GPIO_730 }, +- { OMAP730_GPIO5_BASE, INT_730_GPIO_BANK5, IH_GPIO_BASE + 128, METHOD_GPIO_730 }, +- { OMAP730_GPIO6_BASE, INT_730_GPIO_BANK6, IH_GPIO_BASE + 160, METHOD_GPIO_730 }, ++ { OMAP1_MPUIO_VBASE, 0, INT_MPUIO, IH_MPUIO_BASE, ++ METHOD_MPUIO }, ++ { OMAP1510_GPIO_BASE, 0, INT_GPIO_BANK1, IH_GPIO_BASE, ++ METHOD_GPIO_1510 } + }; + #endif + +-#ifdef CONFIG_ARCH_OMAP850 +-static struct gpio_bank gpio_bank_850[7] = { +- { OMAP1_MPUIO_VBASE, INT_850_MPUIO, IH_MPUIO_BASE, METHOD_MPUIO }, +- { OMAP850_GPIO1_BASE, INT_850_GPIO_BANK1, IH_GPIO_BASE, METHOD_GPIO_850 }, +- { OMAP850_GPIO2_BASE, INT_850_GPIO_BANK2, IH_GPIO_BASE + 32, METHOD_GPIO_850 }, +- { OMAP850_GPIO3_BASE, INT_850_GPIO_BANK3, IH_GPIO_BASE + 64, METHOD_GPIO_850 }, +- { OMAP850_GPIO4_BASE, INT_850_GPIO_BANK4, IH_GPIO_BASE + 96, METHOD_GPIO_850 }, +- { OMAP850_GPIO5_BASE, INT_850_GPIO_BANK5, IH_GPIO_BASE + 128, METHOD_GPIO_850 }, +- { OMAP850_GPIO6_BASE, INT_850_GPIO_BANK6, IH_GPIO_BASE + 160, METHOD_GPIO_850 }, ++#if defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850) ++static struct gpio_bank gpio_bank_7xx[7] = { ++ { OMAP1_MPUIO_VBASE, 0, INT_7XX_MPUIO, IH_MPUIO_BASE, ++ METHOD_MPUIO }, ++ { OMAP7XX_GPIO1_BASE, 0, INT_7XX_GPIO_BANK1, IH_GPIO_BASE, ++ METHOD_GPIO_7XX }, ++ { OMAP7XX_GPIO2_BASE, 0, INT_7XX_GPIO_BANK2, IH_GPIO_BASE + 32, ++ METHOD_GPIO_7XX }, ++ { OMAP7XX_GPIO3_BASE, 0, INT_7XX_GPIO_BANK3, IH_GPIO_BASE + 64, ++ METHOD_GPIO_7XX }, ++ { OMAP7XX_GPIO4_BASE, 0, INT_7XX_GPIO_BANK4, IH_GPIO_BASE + 96, ++ METHOD_GPIO_7XX }, ++ { OMAP7XX_GPIO5_BASE, 0, INT_7XX_GPIO_BANK5, IH_GPIO_BASE + 128, ++ METHOD_GPIO_7XX }, ++ { OMAP7XX_GPIO6_BASE, 0, INT_7XX_GPIO_BANK6, IH_GPIO_BASE + 160, ++ METHOD_GPIO_7XX }, + }; + #endif + +- + #ifdef CONFIG_ARCH_OMAP24XX + + static struct gpio_bank gpio_bank_242x[4] = { +- { OMAP242X_GPIO1_BASE, INT_24XX_GPIO_BANK1, IH_GPIO_BASE, METHOD_GPIO_24XX }, +- { OMAP242X_GPIO2_BASE, INT_24XX_GPIO_BANK2, IH_GPIO_BASE + 32, METHOD_GPIO_24XX }, +- { OMAP242X_GPIO3_BASE, INT_24XX_GPIO_BANK3, IH_GPIO_BASE + 64, METHOD_GPIO_24XX }, +- { OMAP242X_GPIO4_BASE, INT_24XX_GPIO_BANK4, IH_GPIO_BASE + 96, METHOD_GPIO_24XX }, ++ { OMAP242X_GPIO1_BASE, 0, INT_24XX_GPIO_BANK1, IH_GPIO_BASE, ++ METHOD_GPIO_24XX }, ++ { OMAP242X_GPIO2_BASE, 0, INT_24XX_GPIO_BANK2, IH_GPIO_BASE + 32, ++ METHOD_GPIO_24XX }, ++ { OMAP242X_GPIO3_BASE, 0, INT_24XX_GPIO_BANK3, IH_GPIO_BASE + 64, ++ METHOD_GPIO_24XX }, ++ { OMAP242X_GPIO4_BASE, 0, INT_24XX_GPIO_BANK4, IH_GPIO_BASE + 96, ++ METHOD_GPIO_24XX }, + }; + + static struct gpio_bank gpio_bank_243x[5] = { +- { OMAP243X_GPIO1_BASE, INT_24XX_GPIO_BANK1, IH_GPIO_BASE, METHOD_GPIO_24XX }, +- { OMAP243X_GPIO2_BASE, INT_24XX_GPIO_BANK2, IH_GPIO_BASE + 32, METHOD_GPIO_24XX }, +- { OMAP243X_GPIO3_BASE, INT_24XX_GPIO_BANK3, IH_GPIO_BASE + 64, METHOD_GPIO_24XX }, +- { OMAP243X_GPIO4_BASE, INT_24XX_GPIO_BANK4, IH_GPIO_BASE + 96, METHOD_GPIO_24XX }, +- { OMAP243X_GPIO5_BASE, INT_24XX_GPIO_BANK5, IH_GPIO_BASE + 128, METHOD_GPIO_24XX }, ++ { OMAP243X_GPIO1_BASE, 0, INT_24XX_GPIO_BANK1, IH_GPIO_BASE, ++ METHOD_GPIO_24XX }, ++ { OMAP243X_GPIO2_BASE, 0, INT_24XX_GPIO_BANK2, IH_GPIO_BASE + 32, ++ METHOD_GPIO_24XX }, ++ { OMAP243X_GPIO3_BASE, 0, INT_24XX_GPIO_BANK3, IH_GPIO_BASE + 64, ++ METHOD_GPIO_24XX }, ++ { OMAP243X_GPIO4_BASE, 0, INT_24XX_GPIO_BANK4, IH_GPIO_BASE + 96, ++ METHOD_GPIO_24XX }, ++ { OMAP243X_GPIO5_BASE, 0, INT_24XX_GPIO_BANK5, IH_GPIO_BASE + 128, ++ METHOD_GPIO_24XX }, + }; + + #endif + + #ifdef CONFIG_ARCH_OMAP34XX + static struct gpio_bank gpio_bank_34xx[6] = { +- { OMAP34XX_GPIO1_BASE, INT_34XX_GPIO_BANK1, IH_GPIO_BASE, METHOD_GPIO_24XX }, +- { OMAP34XX_GPIO2_BASE, INT_34XX_GPIO_BANK2, IH_GPIO_BASE + 32, METHOD_GPIO_24XX }, +- { OMAP34XX_GPIO3_BASE, INT_34XX_GPIO_BANK3, IH_GPIO_BASE + 64, METHOD_GPIO_24XX }, +- { OMAP34XX_GPIO4_BASE, INT_34XX_GPIO_BANK4, IH_GPIO_BASE + 96, METHOD_GPIO_24XX }, +- { OMAP34XX_GPIO5_BASE, INT_34XX_GPIO_BANK5, IH_GPIO_BASE + 128, METHOD_GPIO_24XX }, +- { OMAP34XX_GPIO6_BASE, INT_34XX_GPIO_BANK6, IH_GPIO_BASE + 160, METHOD_GPIO_24XX }, ++ { OMAP34XX_GPIO1_BASE, 0, INT_34XX_GPIO_BANK1, IH_GPIO_BASE, ++ METHOD_GPIO_24XX }, ++ { OMAP34XX_GPIO2_BASE, 0, INT_34XX_GPIO_BANK2, IH_GPIO_BASE + 32, ++ METHOD_GPIO_24XX }, ++ { OMAP34XX_GPIO3_BASE, 0, INT_34XX_GPIO_BANK3, IH_GPIO_BASE + 64, ++ METHOD_GPIO_24XX }, ++ { OMAP34XX_GPIO4_BASE, 0, INT_34XX_GPIO_BANK4, IH_GPIO_BASE + 96, ++ METHOD_GPIO_24XX }, ++ { OMAP34XX_GPIO5_BASE, 0, INT_34XX_GPIO_BANK5, IH_GPIO_BASE + 128, ++ METHOD_GPIO_24XX }, ++ { OMAP34XX_GPIO6_BASE, 0, INT_34XX_GPIO_BANK6, IH_GPIO_BASE + 160, ++ METHOD_GPIO_24XX }, + }; + + #endif + + #ifdef CONFIG_ARCH_OMAP4 + static struct gpio_bank gpio_bank_44xx[6] = { +- { OMAP44XX_GPIO1_BASE, INT_44XX_GPIO_BANK1, IH_GPIO_BASE, \ ++ { OMAP44XX_GPIO1_BASE, 0, INT_44XX_GPIO_BANK1, IH_GPIO_BASE, + METHOD_GPIO_24XX }, +- { OMAP44XX_GPIO2_BASE, INT_44XX_GPIO_BANK2, IH_GPIO_BASE + 32, \ ++ { OMAP44XX_GPIO2_BASE, 0, INT_44XX_GPIO_BANK2, IH_GPIO_BASE + 32, + METHOD_GPIO_24XX }, +- { OMAP44XX_GPIO3_BASE, INT_44XX_GPIO_BANK3, IH_GPIO_BASE + 64, \ ++ { OMAP44XX_GPIO3_BASE, 0, INT_44XX_GPIO_BANK3, IH_GPIO_BASE + 64, + METHOD_GPIO_24XX }, +- { OMAP44XX_GPIO4_BASE, INT_44XX_GPIO_BANK4, IH_GPIO_BASE + 96, \ ++ { OMAP44XX_GPIO4_BASE, 0, INT_44XX_GPIO_BANK4, IH_GPIO_BASE + 96, + METHOD_GPIO_24XX }, +- { OMAP44XX_GPIO5_BASE, INT_44XX_GPIO_BANK5, IH_GPIO_BASE + 128, \ ++ { OMAP44XX_GPIO5_BASE, 0, INT_44XX_GPIO_BANK5, IH_GPIO_BASE + 128, + METHOD_GPIO_24XX }, +- { OMAP44XX_GPIO6_BASE, INT_44XX_GPIO_BANK6, IH_GPIO_BASE + 160, \ ++ { OMAP44XX_GPIO6_BASE, 0, INT_44XX_GPIO_BANK6, IH_GPIO_BASE + 160, + METHOD_GPIO_24XX }, + }; + +@@ -373,7 +373,7 @@ static inline int gpio_valid(int gpio) + + static int check_gpio(int gpio) + { +- if (unlikely(gpio_valid(gpio)) < 0) { ++ if (unlikely(gpio_valid(gpio) < 0)) { + printk(KERN_ERR "omap-gpio: invalid GPIO %d\n", gpio); + dump_stack(); + return -1; +@@ -402,14 +402,9 @@ static void _set_gpio_direction(struct gpio_bank *bank, int gpio, int is_input) + reg += OMAP1610_GPIO_DIRECTION; + break; + #endif +-#ifdef CONFIG_ARCH_OMAP730 +- case METHOD_GPIO_730: +- reg += OMAP730_GPIO_DIR_CONTROL; +- break; +-#endif +-#ifdef CONFIG_ARCH_OMAP850 +- case METHOD_GPIO_850: +- reg += OMAP850_GPIO_DIR_CONTROL; ++#if defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850) ++ case METHOD_GPIO_7XX: ++ reg += OMAP7XX_GPIO_DIR_CONTROL; + break; + #endif + #if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) +@@ -469,19 +464,9 @@ static void _set_gpio_dataout(struct gpio_bank *bank, int gpio, int enable) + l = 1 << gpio; + break; + #endif +-#ifdef CONFIG_ARCH_OMAP730 +- case METHOD_GPIO_730: +- reg += OMAP730_GPIO_DATA_OUTPUT; +- l = __raw_readl(reg); +- if (enable) +- l |= 1 << gpio; +- else +- l &= ~(1 << gpio); +- break; +-#endif +-#ifdef CONFIG_ARCH_OMAP850 +- case METHOD_GPIO_850: +- reg += OMAP850_GPIO_DATA_OUTPUT; ++#if defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850) ++ case METHOD_GPIO_7XX: ++ reg += OMAP7XX_GPIO_DATA_OUTPUT; + l = __raw_readl(reg); + if (enable) + l |= 1 << gpio; +@@ -537,14 +522,9 @@ static int _get_gpio_datain(struct gpio_bank *bank, int gpio) + reg += OMAP1610_GPIO_DATAIN; + break; + #endif +-#ifdef CONFIG_ARCH_OMAP730 +- case METHOD_GPIO_730: +- reg += OMAP730_GPIO_DATA_INPUT; +- break; +-#endif +-#ifdef CONFIG_ARCH_OMAP850 +- case METHOD_GPIO_850: +- reg += OMAP850_GPIO_DATA_INPUT; ++#if defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850) ++ case METHOD_GPIO_7XX: ++ reg += OMAP7XX_GPIO_DATA_INPUT; + break; + #endif + #if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) +@@ -588,14 +568,9 @@ static int _get_gpio_dataout(struct gpio_bank *bank, int gpio) + reg += OMAP1610_GPIO_DATAOUT; + break; + #endif +-#ifdef CONFIG_ARCH_OMAP730 +- case METHOD_GPIO_730: +- reg += OMAP730_GPIO_DATA_OUTPUT; +- break; +-#endif +-#ifdef CONFIG_ARCH_OMAP850 +- case METHOD_GPIO_850: +- reg += OMAP850_GPIO_DATA_OUTPUT; ++#if defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850) ++ case METHOD_GPIO_7XX: ++ reg += OMAP7XX_GPIO_DATA_OUTPUT; + break; + #endif + #if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) || \ +@@ -797,21 +772,9 @@ static int _set_gpio_triggering(struct gpio_bank *bank, int gpio, int trigger) + __raw_writel(1 << gpio, bank->base + OMAP1610_GPIO_CLEAR_WAKEUPENA); + break; + #endif +-#ifdef CONFIG_ARCH_OMAP730 +- case METHOD_GPIO_730: +- reg += OMAP730_GPIO_INT_CONTROL; +- l = __raw_readl(reg); +- if (trigger & IRQ_TYPE_EDGE_RISING) +- l |= 1 << gpio; +- else if (trigger & IRQ_TYPE_EDGE_FALLING) +- l &= ~(1 << gpio); +- else +- goto bad; +- break; +-#endif +-#ifdef CONFIG_ARCH_OMAP850 +- case METHOD_GPIO_850: +- reg += OMAP850_GPIO_INT_CONTROL; ++#if defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850) ++ case METHOD_GPIO_7XX: ++ reg += OMAP7XX_GPIO_INT_CONTROL; + l = __raw_readl(reg); + if (trigger & IRQ_TYPE_EDGE_RISING) + l |= 1 << gpio; +@@ -897,14 +860,9 @@ static void _clear_gpio_irqbank(struct gpio_bank *bank, int gpio_mask) + reg += OMAP1610_GPIO_IRQSTATUS1; + break; + #endif +-#ifdef CONFIG_ARCH_OMAP730 +- case METHOD_GPIO_730: +- reg += OMAP730_GPIO_INT_STATUS; +- break; +-#endif +-#ifdef CONFIG_ARCH_OMAP850 +- case METHOD_GPIO_850: +- reg += OMAP850_GPIO_INT_STATUS; ++#if defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850) ++ case METHOD_GPIO_7XX: ++ reg += OMAP7XX_GPIO_INT_STATUS; + break; + #endif + #if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) +@@ -971,16 +929,9 @@ static u32 _get_gpio_irqbank_mask(struct gpio_bank *bank) + mask = 0xffff; + break; + #endif +-#ifdef CONFIG_ARCH_OMAP730 +- case METHOD_GPIO_730: +- reg += OMAP730_GPIO_INT_MASK; +- mask = 0xffffffff; +- inv = 1; +- break; +-#endif +-#ifdef CONFIG_ARCH_OMAP850 +- case METHOD_GPIO_850: +- reg += OMAP850_GPIO_INT_MASK; ++#if defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850) ++ case METHOD_GPIO_7XX: ++ reg += OMAP7XX_GPIO_INT_MASK; + mask = 0xffffffff; + inv = 1; + break; +@@ -1044,19 +995,9 @@ static void _enable_gpio_irqbank(struct gpio_bank *bank, int gpio_mask, int enab + l = gpio_mask; + break; + #endif +-#ifdef CONFIG_ARCH_OMAP730 +- case METHOD_GPIO_730: +- reg += OMAP730_GPIO_INT_MASK; +- l = __raw_readl(reg); +- if (enable) +- l &= ~(gpio_mask); +- else +- l |= gpio_mask; +- break; +-#endif +-#ifdef CONFIG_ARCH_OMAP850 +- case METHOD_GPIO_850: +- reg += OMAP850_GPIO_INT_MASK; ++#if defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850) ++ case METHOD_GPIO_7XX: ++ reg += OMAP7XX_GPIO_INT_MASK; + l = __raw_readl(reg); + if (enable) + l &= ~(gpio_mask); +@@ -1249,13 +1190,9 @@ static void gpio_irq_handler(unsigned int irq, struct irq_desc *desc) + if (bank->method == METHOD_GPIO_1610) + isr_reg = bank->base + OMAP1610_GPIO_IRQSTATUS1; + #endif +-#ifdef CONFIG_ARCH_OMAP730 +- if (bank->method == METHOD_GPIO_730) +- isr_reg = bank->base + OMAP730_GPIO_INT_STATUS; +-#endif +-#ifdef CONFIG_ARCH_OMAP850 +- if (bank->method == METHOD_GPIO_850) +- isr_reg = bank->base + OMAP850_GPIO_INT_STATUS; ++#if defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850) ++ if (bank->method == METHOD_GPIO_7XX) ++ isr_reg = bank->base + OMAP7XX_GPIO_INT_STATUS; + #endif + #if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) + if (bank->method == METHOD_GPIO_24XX) +@@ -1524,11 +1461,8 @@ static int gpio_is_input(struct gpio_bank *bank, int mask) + case METHOD_GPIO_1610: + reg += OMAP1610_GPIO_DIRECTION; + break; +- case METHOD_GPIO_730: +- reg += OMAP730_GPIO_DIR_CONTROL; +- break; +- case METHOD_GPIO_850: +- reg += OMAP850_GPIO_DIR_CONTROL; ++ case METHOD_GPIO_7XX: ++ reg += OMAP7XX_GPIO_DIR_CONTROL; + break; + case METHOD_GPIO_24XX: + reg += OMAP24XX_GPIO_OE; +@@ -1607,6 +1541,23 @@ static struct clk * gpio5_fck; + static struct clk *gpio_iclks[OMAP34XX_NR_GPIOS]; + #endif + ++static void __init omap_gpio_show_rev(void) ++{ ++ u32 rev; ++ ++ if (cpu_is_omap16xx()) ++ rev = __raw_readw(gpio_bank[1].base + OMAP1610_GPIO_REVISION); ++ else if (cpu_is_omap24xx() || cpu_is_omap34xx()) ++ rev = __raw_readl(gpio_bank[0].base + OMAP24XX_GPIO_REVISION); ++ else if (cpu_is_omap44xx()) ++ rev = __raw_readl(gpio_bank[0].base + OMAP4_GPIO_REVISION); ++ else ++ return; ++ ++ printk(KERN_INFO "OMAP GPIO hardware version %d.%d\n", ++ (rev >> 4) & 0x0f, rev & 0x0f); ++} ++ + /* This lock class tells lockdep that GPIO irqs are in a different + * category than their parents, so it won't report false recursion. + */ +@@ -1617,6 +1568,7 @@ static int __init _omap_gpio_init(void) + int i; + int gpio = 0; + struct gpio_bank *bank; ++ int bank_size = SZ_8K; /* Module 4KB + L4 4KB except on omap1 */ + char clk_name[11]; + + initialized = 1; +@@ -1679,77 +1631,45 @@ static int __init _omap_gpio_init(void) + + #ifdef CONFIG_ARCH_OMAP15XX + if (cpu_is_omap15xx()) { +- printk(KERN_INFO "OMAP1510 GPIO hardware\n"); + gpio_bank_count = 2; + gpio_bank = gpio_bank_1510; ++ bank_size = SZ_2K; + } + #endif + #if defined(CONFIG_ARCH_OMAP16XX) + if (cpu_is_omap16xx()) { +- u32 rev; +- + gpio_bank_count = 5; + gpio_bank = gpio_bank_1610; +- rev = __raw_readw(gpio_bank[1].base + OMAP1610_GPIO_REVISION); +- printk(KERN_INFO "OMAP GPIO hardware version %d.%d\n", +- (rev >> 4) & 0x0f, rev & 0x0f); ++ bank_size = SZ_2K; + } + #endif +-#ifdef CONFIG_ARCH_OMAP730 +- if (cpu_is_omap730()) { +- printk(KERN_INFO "OMAP730 GPIO hardware\n"); +- gpio_bank_count = 7; +- gpio_bank = gpio_bank_730; +- } +-#endif +-#ifdef CONFIG_ARCH_OMAP850 +- if (cpu_is_omap850()) { +- printk(KERN_INFO "OMAP850 GPIO hardware\n"); ++#if defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850) ++ if (cpu_is_omap7xx()) { + gpio_bank_count = 7; +- gpio_bank = gpio_bank_850; ++ gpio_bank = gpio_bank_7xx; ++ bank_size = SZ_2K; + } + #endif +- + #ifdef CONFIG_ARCH_OMAP24XX + if (cpu_is_omap242x()) { +- int rev; +- + gpio_bank_count = 4; + gpio_bank = gpio_bank_242x; +- rev = __raw_readl(gpio_bank[0].base + OMAP24XX_GPIO_REVISION); +- printk(KERN_INFO "OMAP242x GPIO hardware version %d.%d\n", +- (rev >> 4) & 0x0f, rev & 0x0f); + } + if (cpu_is_omap243x()) { +- int rev; +- + gpio_bank_count = 5; + gpio_bank = gpio_bank_243x; +- rev = __raw_readl(gpio_bank[0].base + OMAP24XX_GPIO_REVISION); +- printk(KERN_INFO "OMAP243x GPIO hardware version %d.%d\n", +- (rev >> 4) & 0x0f, rev & 0x0f); + } + #endif + #ifdef CONFIG_ARCH_OMAP34XX + if (cpu_is_omap34xx()) { +- int rev; +- + gpio_bank_count = OMAP34XX_NR_GPIOS; + gpio_bank = gpio_bank_34xx; +- rev = __raw_readl(gpio_bank[0].base + OMAP24XX_GPIO_REVISION); +- printk(KERN_INFO "OMAP34xx GPIO hardware version %d.%d\n", +- (rev >> 4) & 0x0f, rev & 0x0f); + } + #endif + #ifdef CONFIG_ARCH_OMAP4 + if (cpu_is_omap44xx()) { +- int rev; +- + gpio_bank_count = OMAP34XX_NR_GPIOS; + gpio_bank = gpio_bank_44xx; +- rev = __raw_readl(gpio_bank[0].base + OMAP4_GPIO_REVISION); +- printk(KERN_INFO "OMAP44xx GPIO hardware version %d.%d\n", +- (rev >> 4) & 0x0f, rev & 0x0f); + } + #endif + for (i = 0; i < gpio_bank_count; i++) { +@@ -1757,6 +1677,14 @@ static int __init _omap_gpio_init(void) + + bank = &gpio_bank[i]; + spin_lock_init(&bank->lock); ++ ++ /* Static mapping, never released */ ++ bank->base = ioremap(bank->pbase, bank_size); ++ if (!bank->base) { ++ printk(KERN_ERR "Could not ioremap gpio bank%i\n", i); ++ continue; ++ } ++ + if (bank_is_mpuio(bank)) + __raw_writew(0xffff, bank->base + OMAP_MPUIO_GPIO_MASKIT); + if (cpu_is_omap15xx() && bank->method == METHOD_GPIO_1510) { +@@ -1768,11 +1696,11 @@ static int __init _omap_gpio_init(void) + __raw_writew(0xffff, bank->base + OMAP1610_GPIO_IRQSTATUS1); + __raw_writew(0x0014, bank->base + OMAP1610_GPIO_SYSCONFIG); + } +- if (cpu_is_omap7xx() && bank->method == METHOD_GPIO_730) { +- __raw_writel(0xffffffff, bank->base + OMAP730_GPIO_INT_MASK); +- __raw_writel(0x00000000, bank->base + OMAP730_GPIO_INT_STATUS); ++ if (cpu_is_omap7xx() && bank->method == METHOD_GPIO_7XX) { ++ __raw_writel(0xffffffff, bank->base + OMAP7XX_GPIO_INT_MASK); ++ __raw_writel(0x00000000, bank->base + OMAP7XX_GPIO_INT_STATUS); + +- gpio_count = 32; /* 730 has 32-bit GPIOs */ ++ gpio_count = 32; /* 7xx has 32-bit GPIOs */ + } + + #if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) || \ +@@ -1862,6 +1790,8 @@ static int __init _omap_gpio_init(void) + if (cpu_is_omap34xx()) + omap_writel(1 << 0, 0x48306814); + ++ omap_gpio_show_rev(); ++ + return 0; + } + +@@ -2160,8 +2090,7 @@ static int dbg_gpio_show(struct seq_file *s, void *unused) + + if (bank_is_mpuio(bank)) + gpio = OMAP_MPUIO(0); +- else if (cpu_class_is_omap2() || cpu_is_omap730() || +- cpu_is_omap850()) ++ else if (cpu_class_is_omap2() || cpu_is_omap7xx()) + bankwidth = 32; + + for (j = 0; j < bankwidth; j++, gpio++, mask <<= 1) { +diff --git a/arch/arm/plat-omap/include/mach/control.h b/arch/arm/plat-omap/include/mach/control.h +index 826d317..fdb6300 100644 +--- a/arch/arm/plat-omap/include/mach/control.h ++++ b/arch/arm/plat-omap/include/mach/control.h +@@ -20,15 +20,18 @@ + + #ifndef __ASSEMBLY__ + #define OMAP242X_CTRL_REGADDR(reg) \ +- OMAP2_IO_ADDRESS(OMAP242X_CTRL_BASE + (reg)) ++ OMAP2_L4_IO_ADDRESS(OMAP242X_CTRL_BASE + (reg)) + #define OMAP243X_CTRL_REGADDR(reg) \ +- OMAP2_IO_ADDRESS(OMAP243X_CTRL_BASE + (reg)) ++ OMAP2_L4_IO_ADDRESS(OMAP243X_CTRL_BASE + (reg)) + #define OMAP343X_CTRL_REGADDR(reg) \ +- OMAP2_IO_ADDRESS(OMAP343X_CTRL_BASE + (reg)) ++ OMAP2_L4_IO_ADDRESS(OMAP343X_CTRL_BASE + (reg)) + #else +-#define OMAP242X_CTRL_REGADDR(reg) OMAP2_IO_ADDRESS(OMAP242X_CTRL_BASE + (reg)) +-#define OMAP243X_CTRL_REGADDR(reg) OMAP2_IO_ADDRESS(OMAP243X_CTRL_BASE + (reg)) +-#define OMAP343X_CTRL_REGADDR(reg) OMAP2_IO_ADDRESS(OMAP343X_CTRL_BASE + (reg)) ++#define OMAP242X_CTRL_REGADDR(reg) \ ++ OMAP2_L4_IO_ADDRESS(OMAP242X_CTRL_BASE + (reg)) ++#define OMAP243X_CTRL_REGADDR(reg) \ ++ OMAP2_L4_IO_ADDRESS(OMAP243X_CTRL_BASE + (reg)) ++#define OMAP343X_CTRL_REGADDR(reg) \ ++ OMAP2_L4_IO_ADDRESS(OMAP343X_CTRL_BASE + (reg)) + #endif /* __ASSEMBLY__ */ + + /* +@@ -202,6 +205,40 @@ + #define OMAP3_PADCONF_WAKEUPEVENT0 (1 << 15) + #define OMAP3_PADCONF_WAKEUPENABLE0 (1 << 14) + ++/* ++ * CONTROL OMAP STATUS register to identify OMAP3 features ++ */ ++#define OMAP3_CONTROL_OMAP_STATUS 0x044c ++ ++#define OMAP3_SGX_SHIFT 13 ++#define OMAP3_SGX_MASK (3 << OMAP3_SGX_SHIFT) ++#define FEAT_SGX_FULL 0 ++#define FEAT_SGX_HALF 1 ++#define FEAT_SGX_NONE 2 ++ ++#define OMAP3_IVA_SHIFT 12 ++#define OMAP3_IVA_MASK (1 << OMAP3_SGX_SHIFT) ++#define FEAT_IVA 0 ++#define FEAT_IVA_NONE 1 ++ ++#define OMAP3_L2CACHE_SHIFT 10 ++#define OMAP3_L2CACHE_MASK (3 << OMAP3_L2CACHE_SHIFT) ++#define FEAT_L2CACHE_NONE 0 ++#define FEAT_L2CACHE_64KB 1 ++#define FEAT_L2CACHE_128KB 2 ++#define FEAT_L2CACHE_256KB 3 ++ ++#define OMAP3_ISP_SHIFT 5 ++#define OMAP3_ISP_MASK (1<< OMAP3_ISP_SHIFT) ++#define FEAT_ISP 0 ++#define FEAT_ISP_NONE 1 ++ ++#define OMAP3_NEON_SHIFT 4 ++#define OMAP3_NEON_MASK (1<< OMAP3_NEON_SHIFT) ++#define FEAT_NEON 0 ++#define FEAT_NEON_NONE 1 ++ ++ + #ifndef __ASSEMBLY__ + #if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3) || \ + defined(CONFIG_ARCH_OMAP4) +diff --git a/arch/arm/plat-omap/include/mach/cpu.h b/arch/arm/plat-omap/include/mach/cpu.h +index f129efb..7cb0556 100644 +--- a/arch/arm/plat-omap/include/mach/cpu.h ++++ b/arch/arm/plat-omap/include/mach/cpu.h +@@ -30,6 +30,8 @@ + #ifndef __ASM_ARCH_OMAP_CPU_H + #define __ASM_ARCH_OMAP_CPU_H + ++#include ++ + /* + * Omap device type i.e. EMU/HS/TST/GP/BAD + */ +@@ -57,6 +59,23 @@ struct omap_chip_id { + unsigned int omap_rev(void); + + /* ++ * Define CPU revision bits ++ * ++ * Verbose meaning of the revision bits may be different for a silicon ++ * family. This difference can be handled separately. ++ */ ++#define OMAP_REVBITS_00 0x00 ++#define OMAP_REVBITS_10 0x10 ++#define OMAP_REVBITS_20 0x20 ++#define OMAP_REVBITS_30 0x30 ++#define OMAP_REVBITS_40 0x40 ++ ++/* ++ * Get the CPU revision for OMAP devices ++ */ ++#define GET_OMAP_REVISION() ((omap_rev() >> 8) & 0xff) ++ ++/* + * Test if multicore OMAP support is needed + */ + #undef MULTI_OMAP1 +@@ -161,6 +180,7 @@ IS_OMAP_CLASS(34xx, 0x34) + IS_OMAP_SUBCLASS(242x, 0x242) + IS_OMAP_SUBCLASS(243x, 0x243) + IS_OMAP_SUBCLASS(343x, 0x343) ++IS_OMAP_SUBCLASS(363x, 0x363) + + #define cpu_is_omap7xx() 0 + #define cpu_is_omap15xx() 0 +@@ -301,7 +321,12 @@ IS_OMAP_TYPE(3430, 0x3430) + #define cpu_is_omap2422() 0 + #define cpu_is_omap2423() 0 + #define cpu_is_omap2430() 0 ++#define cpu_is_omap3503() 0 ++#define cpu_is_omap3515() 0 ++#define cpu_is_omap3525() 0 ++#define cpu_is_omap3530() 0 + #define cpu_is_omap3430() 0 ++#define cpu_is_omap3630() 0 + + /* + * Whether we have MULTI_OMAP1 or not, we still need to distinguish +@@ -351,7 +376,23 @@ IS_OMAP_TYPE(3430, 0x3430) + + #if defined(CONFIG_ARCH_OMAP34XX) + # undef cpu_is_omap3430 ++# undef cpu_is_omap3503 ++# undef cpu_is_omap3515 ++# undef cpu_is_omap3525 ++# undef cpu_is_omap3530 + # define cpu_is_omap3430() is_omap3430() ++# define cpu_is_omap3503 (cpu_is_omap3430() && \ ++ (!omap3_has_iva()) && \ ++ (!omap3_has_sgx())) ++# define cpu_is_omap3515 (cpu_is_omap3430() && \ ++ (omap3_has_iva()) && \ ++ (!omap3_has_sgx())) ++# define cpu_is_omap3525 (cpu_is_omap3430() && \ ++ (omap3_has_sgx()) && \ ++ (!omap3_has_iva())) ++# define cpu_is_omap3530 (cpu_is_omap3430()) ++# undef cpu_is_omap3630 ++# define cpu_is_omap3630() is_omap363x() + #endif + + # if defined(CONFIG_ARCH_OMAP4) +@@ -382,6 +423,14 @@ IS_OMAP_TYPE(3430, 0x3430) + #define OMAP3430_REV_ES3_0 0x34303034 + #define OMAP3430_REV_ES3_1 0x34304034 + ++#define OMAP3630_REV_ES1_0 0x36300034 ++ ++#define OMAP35XX_CLASS 0x35000034 ++#define OMAP3503_REV(v) (OMAP35XX_CLASS | (0x3503 << 16) | (v << 12)) ++#define OMAP3515_REV(v) (OMAP35XX_CLASS | (0x3515 << 16) | (v << 12)) ++#define OMAP3525_REV(v) (OMAP35XX_CLASS | (0x3525 << 16) | (v << 12)) ++#define OMAP3530_REV(v) (OMAP35XX_CLASS | (0x3530 << 16) | (v << 12)) ++ + #define OMAP443X_CLASS 0x44300034 + + /* +@@ -423,4 +472,27 @@ IS_OMAP_TYPE(3430, 0x3430) + int omap_chip_is(struct omap_chip_id oci); + void omap2_check_revision(void); + ++/* ++ * Runtime detection of OMAP3 features ++ */ ++extern u32 omap3_features; ++ ++#define OMAP3_HAS_L2CACHE BIT(0) ++#define OMAP3_HAS_IVA BIT(1) ++#define OMAP3_HAS_SGX BIT(2) ++#define OMAP3_HAS_NEON BIT(3) ++#define OMAP3_HAS_ISP BIT(4) ++ ++#define OMAP3_HAS_FEATURE(feat,flag) \ ++static inline unsigned int omap3_has_ ##feat(void) \ ++{ \ ++ return (omap3_features & OMAP3_HAS_ ##flag); \ ++} \ ++ ++OMAP3_HAS_FEATURE(l2cache, L2CACHE) ++OMAP3_HAS_FEATURE(sgx, SGX) ++OMAP3_HAS_FEATURE(iva, IVA) ++OMAP3_HAS_FEATURE(neon, NEON) ++OMAP3_HAS_FEATURE(isp, ISP) ++ + #endif +diff --git a/arch/arm/plat-omap/include/mach/debug-macro.S b/arch/arm/plat-omap/include/mach/debug-macro.S +index ac24050..63bb06d 100644 +--- a/arch/arm/plat-omap/include/mach/debug-macro.S ++++ b/arch/arm/plat-omap/include/mach/debug-macro.S +@@ -27,7 +27,7 @@ + + #elif CONFIG_ARCH_OMAP2 + moveq \rx, #0x48000000 @ physical base address +- movne \rx, #0xd8000000 @ virtual base ++ movne \rx, #0xfa000000 @ virtual base + orr \rx, \rx, #0x0006a000 + #ifdef CONFIG_OMAP_LL_DEBUG_UART2 + add \rx, \rx, #0x00002000 @ UART 2 +@@ -38,7 +38,7 @@ + + #elif defined(CONFIG_ARCH_OMAP3) || defined(CONFIG_ARCH_OMAP4) + moveq \rx, #0x48000000 @ physical base address +- movne \rx, #0xd8000000 @ virtual base ++ movne \rx, #0xfa000000 @ virtual base + orr \rx, \rx, #0x0006a000 + #ifdef CONFIG_OMAP_LL_DEBUG_UART2 + add \rx, \rx, #0x00002000 @ UART 2 +diff --git a/arch/arm/plat-omap/include/mach/entry-macro.S b/arch/arm/plat-omap/include/mach/entry-macro.S +index a559299..2aea566 100644 +--- a/arch/arm/plat-omap/include/mach/entry-macro.S ++++ b/arch/arm/plat-omap/include/mach/entry-macro.S +@@ -17,11 +17,11 @@ + + #if defined(CONFIG_ARCH_OMAP1) + +-#if defined(CONFIG_ARCH_OMAP730) && \ ++#if (defined(CONFIG_ARCH_OMAP730)||defined(CONFIG_ARCH_OMAP850)) && \ + (defined(CONFIG_ARCH_OMAP15XX) || defined(CONFIG_ARCH_OMAP16XX)) +-#error "FIXME: OMAP730 doesn't support multiple-OMAP" +-#elif defined(CONFIG_ARCH_OMAP730) +-#define INT_IH2_IRQ INT_730_IH2_IRQ ++#error "FIXME: OMAP7XX doesn't support multiple-OMAP" ++#elif defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850) ++#define INT_IH2_IRQ INT_7XX_IH2_IRQ + #elif defined(CONFIG_ARCH_OMAP15XX) + #define INT_IH2_IRQ INT_1510_IH2_IRQ + #elif defined(CONFIG_ARCH_OMAP16XX) +@@ -68,9 +68,9 @@ + + /* REVISIT: This should be set dynamically if CONFIG_MULTI_OMAP2 is selected */ + #if defined(CONFIG_ARCH_OMAP2420) || defined(CONFIG_ARCH_OMAP2430) +-#define OMAP2_VA_IC_BASE OMAP2_IO_ADDRESS(OMAP24XX_IC_BASE) ++#define OMAP2_VA_IC_BASE OMAP2_L4_IO_ADDRESS(OMAP24XX_IC_BASE) + #elif defined(CONFIG_ARCH_OMAP34XX) +-#define OMAP2_VA_IC_BASE OMAP2_IO_ADDRESS(OMAP34XX_IC_BASE) ++#define OMAP2_VA_IC_BASE OMAP2_L4_IO_ADDRESS(OMAP34XX_IC_BASE) + #endif + #if defined(CONFIG_ARCH_OMAP4) + #include +@@ -104,6 +104,8 @@ + + .endm + #else ++#define OMAP44XX_VA_GIC_CPU_BASE OMAP2_L4_IO_ADDRESS(OMAP44XX_GIC_CPU_BASE) ++ + /* + * The interrupt numbering scheme is defined in the + * interrupt controller spec. To wit: +diff --git a/arch/arm/plat-omap/include/mach/hardware.h b/arch/arm/plat-omap/include/mach/hardware.h +index 26c1fbf..99c4241 100644 +--- a/arch/arm/plat-omap/include/mach/hardware.h ++++ b/arch/arm/plat-omap/include/mach/hardware.h +@@ -280,7 +280,7 @@ + * --------------------------------------------------------------------------- + */ + +-#include "omap730.h" ++#include "omap7xx.h" + #include "omap1510.h" + #include "omap16xx.h" + #include "omap24xx.h" +diff --git a/arch/arm/plat-omap/include/mach/io.h b/arch/arm/plat-omap/include/mach/io.h +index 8d32df3..7e5319f 100644 +--- a/arch/arm/plat-omap/include/mach/io.h ++++ b/arch/arm/plat-omap/include/mach/io.h +@@ -63,8 +63,24 @@ + #define OMAP1_IO_OFFSET 0x01000000 /* Virtual IO = 0xfefb0000 */ + #define OMAP1_IO_ADDRESS(pa) IOMEM((pa) - OMAP1_IO_OFFSET) + +-#define OMAP2_IO_OFFSET 0x90000000 +-#define OMAP2_IO_ADDRESS(pa) IOMEM((pa) + OMAP2_IO_OFFSET) /* L3 and L4 */ ++#define OMAP2_L3_IO_OFFSET 0x90000000 ++#define OMAP2_L3_IO_ADDRESS(pa) IOMEM((pa) + OMAP2_L3_IO_OFFSET) /* L3 */ ++ ++ ++#define OMAP2_L4_IO_OFFSET 0xb2000000 ++#define OMAP2_L4_IO_ADDRESS(pa) IOMEM((pa) + OMAP2_L4_IO_OFFSET) /* L4 */ ++ ++#define OMAP4_L3_IO_OFFSET 0xb4000000 ++#define OMAP4_L3_IO_ADDRESS(pa) IOMEM((pa) + OMAP4_L3_IO_OFFSET) /* L3 */ ++ ++#define OMAP4_L3_PER_IO_OFFSET 0xb1100000 ++#define OMAP4_L3_PER_IO_ADDRESS(pa) IOMEM((pa) + OMAP4_L3_PER_IO_OFFSET) ++ ++#define OMAP4_GPMC_IO_OFFSET 0xa9000000 ++#define OMAP4_GPMC_IO_ADDRESS(pa) IOMEM((pa) + OMAP4_GPMC_IO_OFFSET) ++ ++#define OMAP2_EMU_IO_OFFSET 0xaa800000 /* Emulation */ ++#define OMAP2_EMU_IO_ADDRESS(pa) IOMEM((pa) + OMAP2_EMU_IO_OFFSET) + + /* + * ---------------------------------------------------------------------------- +@@ -83,24 +99,27 @@ + */ + + /* We map both L3 and L4 on OMAP2 */ +-#define L3_24XX_PHYS L3_24XX_BASE /* 0x68000000 */ +-#define L3_24XX_VIRT 0xf8000000 ++#define L3_24XX_PHYS L3_24XX_BASE /* 0x68000000 --> 0xf8000000*/ ++#define L3_24XX_VIRT (L3_24XX_PHYS + OMAP2_L3_IO_OFFSET) + #define L3_24XX_SIZE SZ_1M /* 44kB of 128MB used, want 1MB sect */ +-#define L4_24XX_PHYS L4_24XX_BASE /* 0x48000000 */ +-#define L4_24XX_VIRT 0xd8000000 ++#define L4_24XX_PHYS L4_24XX_BASE /* 0x48000000 --> 0xfa000000 */ ++#define L4_24XX_VIRT (L4_24XX_PHYS + OMAP2_L4_IO_OFFSET) + #define L4_24XX_SIZE SZ_1M /* 1MB of 128MB used, want 1MB sect */ + +-#define L4_WK_243X_PHYS L4_WK_243X_BASE /* 0x49000000 */ +-#define L4_WK_243X_VIRT 0xd9000000 ++#define L4_WK_243X_PHYS L4_WK_243X_BASE /* 0x49000000 --> 0xfb000000 */ ++#define L4_WK_243X_VIRT (L4_WK_243X_PHYS + OMAP2_L4_IO_OFFSET) + #define L4_WK_243X_SIZE SZ_1M +-#define OMAP243X_GPMC_PHYS OMAP243X_GPMC_BASE /* 0x49000000 */ +-#define OMAP243X_GPMC_VIRT 0xFE000000 ++#define OMAP243X_GPMC_PHYS OMAP243X_GPMC_BASE ++#define OMAP243X_GPMC_VIRT (OMAP243X_GPMC_PHYS + OMAP2_L3_IO_OFFSET) ++ /* 0x6e000000 --> 0xfe000000 */ + #define OMAP243X_GPMC_SIZE SZ_1M + #define OMAP243X_SDRC_PHYS OMAP243X_SDRC_BASE +-#define OMAP243X_SDRC_VIRT 0xFD000000 ++ /* 0x6D000000 --> 0xfd000000 */ ++#define OMAP243X_SDRC_VIRT (OMAP243X_SDRC_PHYS + OMAP2_L3_IO_OFFSET) + #define OMAP243X_SDRC_SIZE SZ_1M + #define OMAP243X_SMS_PHYS OMAP243X_SMS_BASE +-#define OMAP243X_SMS_VIRT 0xFC000000 ++ /* 0x6c000000 --> 0xfc000000 */ ++#define OMAP243X_SMS_VIRT (OMAP243X_SMS_PHYS + OMAP2_L3_IO_OFFSET) + #define OMAP243X_SMS_SIZE SZ_1M + + /* DSP */ +@@ -121,12 +140,12 @@ + */ + + /* We map both L3 and L4 on OMAP3 */ +-#define L3_34XX_PHYS L3_34XX_BASE /* 0x68000000 */ +-#define L3_34XX_VIRT 0xf8000000 ++#define L3_34XX_PHYS L3_34XX_BASE /* 0x68000000 --> 0xf8000000 */ ++#define L3_34XX_VIRT (L3_34XX_PHYS + OMAP2_L3_IO_OFFSET) + #define L3_34XX_SIZE SZ_1M /* 44kB of 128MB used, want 1MB sect */ + +-#define L4_34XX_PHYS L4_34XX_BASE /* 0x48000000 */ +-#define L4_34XX_VIRT 0xd8000000 ++#define L4_34XX_PHYS L4_34XX_BASE /* 0x48000000 --> 0xfa000000 */ ++#define L4_34XX_VIRT (L4_34XX_PHYS + OMAP2_L4_IO_OFFSET) + #define L4_34XX_SIZE SZ_4M /* 1MB of 128MB used, want 1MB sect */ + + /* +@@ -134,28 +153,33 @@ + * VPOM3430 was not working for Int controller + */ + +-#define L4_WK_34XX_PHYS L4_WK_34XX_BASE /* 0x48300000 */ +-#define L4_WK_34XX_VIRT 0xd8300000 ++#define L4_WK_34XX_PHYS L4_WK_34XX_BASE /* 0x48300000 --> 0xfa300000 */ ++#define L4_WK_34XX_VIRT (L4_WK_34XX_PHYS + OMAP2_L4_IO_OFFSET) + #define L4_WK_34XX_SIZE SZ_1M + +-#define L4_PER_34XX_PHYS L4_PER_34XX_BASE /* 0x49000000 */ +-#define L4_PER_34XX_VIRT 0xd9000000 ++#define L4_PER_34XX_PHYS L4_PER_34XX_BASE ++ /* 0x49000000 --> 0xfb000000 */ ++#define L4_PER_34XX_VIRT (L4_PER_34XX_PHYS + OMAP2_L4_IO_OFFSET) + #define L4_PER_34XX_SIZE SZ_1M + +-#define L4_EMU_34XX_PHYS L4_EMU_34XX_BASE /* 0x54000000 */ +-#define L4_EMU_34XX_VIRT 0xe4000000 +-#define L4_EMU_34XX_SIZE SZ_64M ++#define L4_EMU_34XX_PHYS L4_EMU_34XX_BASE ++ /* 0x54000000 --> 0xfe800000 */ ++#define L4_EMU_34XX_VIRT (L4_EMU_34XX_PHYS + OMAP2_EMU_IO_OFFSET) ++#define L4_EMU_34XX_SIZE SZ_8M + +-#define OMAP34XX_GPMC_PHYS OMAP34XX_GPMC_BASE /* 0x6E000000 */ +-#define OMAP34XX_GPMC_VIRT 0xFE000000 ++#define OMAP34XX_GPMC_PHYS OMAP34XX_GPMC_BASE ++ /* 0x6e000000 --> 0xfe000000 */ ++#define OMAP34XX_GPMC_VIRT (OMAP34XX_GPMC_PHYS + OMAP2_L3_IO_OFFSET) + #define OMAP34XX_GPMC_SIZE SZ_1M + +-#define OMAP343X_SMS_PHYS OMAP343X_SMS_BASE /* 0x6C000000 */ +-#define OMAP343X_SMS_VIRT 0xFC000000 ++#define OMAP343X_SMS_PHYS OMAP343X_SMS_BASE ++ /* 0x6c000000 --> 0xfc000000 */ ++#define OMAP343X_SMS_VIRT (OMAP343X_SMS_PHYS + OMAP2_L3_IO_OFFSET) + #define OMAP343X_SMS_SIZE SZ_1M + +-#define OMAP343X_SDRC_PHYS OMAP343X_SDRC_BASE /* 0x6D000000 */ +-#define OMAP343X_SDRC_VIRT 0xFD000000 ++#define OMAP343X_SDRC_PHYS OMAP343X_SDRC_BASE ++ /* 0x6D000000 --> 0xfd000000 */ ++#define OMAP343X_SDRC_VIRT (OMAP343X_SDRC_PHYS + OMAP2_L3_IO_OFFSET) + #define OMAP343X_SDRC_SIZE SZ_1M + + /* DSP */ +@@ -176,32 +200,54 @@ + */ + + /* We map both L3 and L4 on OMAP4 */ +-#define L3_44XX_PHYS L3_44XX_BASE +-#define L3_44XX_VIRT 0xd4000000 ++#define L3_44XX_PHYS L3_44XX_BASE /* 0x44000000 --> 0xf8000000 */ ++#define L3_44XX_VIRT (L3_44XX_PHYS + OMAP4_L3_IO_OFFSET) + #define L3_44XX_SIZE SZ_1M + +-#define L4_44XX_PHYS L4_44XX_BASE +-#define L4_44XX_VIRT 0xda000000 ++#define L4_44XX_PHYS L4_44XX_BASE /* 0x4a000000 --> 0xfc000000 */ ++#define L4_44XX_VIRT (L4_44XX_PHYS + OMAP2_L4_IO_OFFSET) + #define L4_44XX_SIZE SZ_4M + + +-#define L4_WK_44XX_PHYS L4_WK_44XX_BASE +-#define L4_WK_44XX_VIRT 0xda300000 ++#define L4_WK_44XX_PHYS L4_WK_44XX_BASE /* 0x4a300000 --> 0xfc300000 */ ++#define L4_WK_44XX_VIRT (L4_WK_44XX_PHYS + OMAP2_L4_IO_OFFSET) + #define L4_WK_44XX_SIZE SZ_1M + + #define L4_PER_44XX_PHYS L4_PER_44XX_BASE +-#define L4_PER_44XX_VIRT 0xd8000000 ++ /* 0x48000000 --> 0xfa000000 */ ++#define L4_PER_44XX_VIRT (L4_PER_44XX_PHYS + OMAP2_L4_IO_OFFSET) + #define L4_PER_44XX_SIZE SZ_4M + ++#define L4_ABE_44XX_PHYS L4_ABE_44XX_BASE ++ /* 0x49000000 --> 0xfb000000 */ ++#define L4_ABE_44XX_VIRT (L4_ABE_44XX_PHYS + OMAP2_L4_IO_OFFSET) ++#define L4_ABE_44XX_SIZE SZ_1M ++ + #define L4_EMU_44XX_PHYS L4_EMU_44XX_BASE +-#define L4_EMU_44XX_VIRT 0xe4000000 +-#define L4_EMU_44XX_SIZE SZ_64M ++ /* 0x54000000 --> 0xfe800000 */ ++#define L4_EMU_44XX_VIRT (L4_EMU_44XX_PHYS + OMAP2_EMU_IO_OFFSET) ++#define L4_EMU_44XX_SIZE SZ_8M + + #define OMAP44XX_GPMC_PHYS OMAP44XX_GPMC_BASE +-#define OMAP44XX_GPMC_VIRT 0xe0000000 ++ /* 0x50000000 --> 0xf9000000 */ ++#define OMAP44XX_GPMC_VIRT (OMAP44XX_GPMC_PHYS + OMAP4_GPMC_IO_OFFSET) + #define OMAP44XX_GPMC_SIZE SZ_1M + + ++#define OMAP44XX_EMIF1_PHYS OMAP44XX_EMIF1_BASE ++ /* 0x4c000000 --> 0xfd100000 */ ++#define OMAP44XX_EMIF1_VIRT (OMAP44XX_EMIF1_PHYS + OMAP4_L3_PER_IO_OFFSET) ++#define OMAP44XX_EMIF1_SIZE SZ_1M ++ ++#define OMAP44XX_EMIF2_PHYS OMAP44XX_EMIF2_BASE ++ /* 0x4d000000 --> 0xfd200000 */ ++#define OMAP44XX_EMIF2_VIRT (OMAP44XX_EMIF2_PHYS + OMAP4_L3_PER_IO_OFFSET) ++#define OMAP44XX_EMIF2_SIZE SZ_1M ++ ++#define OMAP44XX_DMM_PHYS OMAP44XX_DMM_BASE ++ /* 0x4e000000 --> 0xfd300000 */ ++#define OMAP44XX_DMM_VIRT (OMAP44XX_DMM_PHYS + OMAP4_L3_PER_IO_OFFSET) ++#define OMAP44XX_DMM_SIZE SZ_1M + /* + * ---------------------------------------------------------------------------- + * Omap specific register access +diff --git a/arch/arm/plat-omap/include/mach/irqs.h b/arch/arm/plat-omap/include/mach/irqs.h +index 28a1650..6a6d028 100644 +--- a/arch/arm/plat-omap/include/mach/irqs.h ++++ b/arch/arm/plat-omap/include/mach/irqs.h +@@ -86,49 +86,26 @@ + #define INT_1610_SSR_FIFO_0 29 + + /* +- * OMAP-730 specific IRQ numbers for interrupt handler 1 ++ * OMAP-7xx specific IRQ numbers for interrupt handler 1 + */ +-#define INT_730_IH2_FIQ 0 +-#define INT_730_IH2_IRQ 1 +-#define INT_730_USB_NON_ISO 2 +-#define INT_730_USB_ISO 3 +-#define INT_730_ICR 4 +-#define INT_730_EAC 5 +-#define INT_730_GPIO_BANK1 6 +-#define INT_730_GPIO_BANK2 7 +-#define INT_730_GPIO_BANK3 8 +-#define INT_730_McBSP2TX 10 +-#define INT_730_McBSP2RX 11 +-#define INT_730_McBSP2RX_OVF 12 +-#define INT_730_LCD_LINE 14 +-#define INT_730_GSM_PROTECT 15 +-#define INT_730_TIMER3 16 +-#define INT_730_GPIO_BANK5 17 +-#define INT_730_GPIO_BANK6 18 +-#define INT_730_SPGIO_WR 29 +- +-/* +- * OMAP-850 specific IRQ numbers for interrupt handler 1 +- */ +-#define INT_850_IH2_FIQ 0 +-#define INT_850_IH2_IRQ 1 +-#define INT_850_USB_NON_ISO 2 +-#define INT_850_USB_ISO 3 +-#define INT_850_ICR 4 +-#define INT_850_EAC 5 +-#define INT_850_GPIO_BANK1 6 +-#define INT_850_GPIO_BANK2 7 +-#define INT_850_GPIO_BANK3 8 +-#define INT_850_McBSP2TX 10 +-#define INT_850_McBSP2RX 11 +-#define INT_850_McBSP2RX_OVF 12 +-#define INT_850_LCD_LINE 14 +-#define INT_850_GSM_PROTECT 15 +-#define INT_850_TIMER3 16 +-#define INT_850_GPIO_BANK5 17 +-#define INT_850_GPIO_BANK6 18 +-#define INT_850_SPGIO_WR 29 +- ++#define INT_7XX_IH2_FIQ 0 ++#define INT_7XX_IH2_IRQ 1 ++#define INT_7XX_USB_NON_ISO 2 ++#define INT_7XX_USB_ISO 3 ++#define INT_7XX_ICR 4 ++#define INT_7XX_EAC 5 ++#define INT_7XX_GPIO_BANK1 6 ++#define INT_7XX_GPIO_BANK2 7 ++#define INT_7XX_GPIO_BANK3 8 ++#define INT_7XX_McBSP2TX 10 ++#define INT_7XX_McBSP2RX 11 ++#define INT_7XX_McBSP2RX_OVF 12 ++#define INT_7XX_LCD_LINE 14 ++#define INT_7XX_GSM_PROTECT 15 ++#define INT_7XX_TIMER3 16 ++#define INT_7XX_GPIO_BANK5 17 ++#define INT_7XX_GPIO_BANK6 18 ++#define INT_7XX_SPGIO_WR 29 + + /* + * IRQ numbers for interrupt handler 2 +@@ -206,120 +183,62 @@ + #define INT_1610_SHA1MD5 (91 + IH2_BASE) + + /* +- * OMAP-730 specific IRQ numbers for interrupt handler 2 +- */ +-#define INT_730_HW_ERRORS (0 + IH2_BASE) +-#define INT_730_NFIQ_PWR_FAIL (1 + IH2_BASE) +-#define INT_730_CFCD (2 + IH2_BASE) +-#define INT_730_CFIREQ (3 + IH2_BASE) +-#define INT_730_I2C (4 + IH2_BASE) +-#define INT_730_PCC (5 + IH2_BASE) +-#define INT_730_MPU_EXT_NIRQ (6 + IH2_BASE) +-#define INT_730_SPI_100K_1 (7 + IH2_BASE) +-#define INT_730_SYREN_SPI (8 + IH2_BASE) +-#define INT_730_VLYNQ (9 + IH2_BASE) +-#define INT_730_GPIO_BANK4 (10 + IH2_BASE) +-#define INT_730_McBSP1TX (11 + IH2_BASE) +-#define INT_730_McBSP1RX (12 + IH2_BASE) +-#define INT_730_McBSP1RX_OF (13 + IH2_BASE) +-#define INT_730_UART_MODEM_IRDA_2 (14 + IH2_BASE) +-#define INT_730_UART_MODEM_1 (15 + IH2_BASE) +-#define INT_730_MCSI (16 + IH2_BASE) +-#define INT_730_uWireTX (17 + IH2_BASE) +-#define INT_730_uWireRX (18 + IH2_BASE) +-#define INT_730_SMC_CD (19 + IH2_BASE) +-#define INT_730_SMC_IREQ (20 + IH2_BASE) +-#define INT_730_HDQ_1WIRE (21 + IH2_BASE) +-#define INT_730_TIMER32K (22 + IH2_BASE) +-#define INT_730_MMC_SDIO (23 + IH2_BASE) +-#define INT_730_UPLD (24 + IH2_BASE) +-#define INT_730_USB_HHC_1 (27 + IH2_BASE) +-#define INT_730_USB_HHC_2 (28 + IH2_BASE) +-#define INT_730_USB_GENI (29 + IH2_BASE) +-#define INT_730_USB_OTG (30 + IH2_BASE) +-#define INT_730_CAMERA_IF (31 + IH2_BASE) +-#define INT_730_RNG (32 + IH2_BASE) +-#define INT_730_DUAL_MODE_TIMER (33 + IH2_BASE) +-#define INT_730_DBB_RF_EN (34 + IH2_BASE) +-#define INT_730_MPUIO_KEYPAD (35 + IH2_BASE) +-#define INT_730_SHA1_MD5 (36 + IH2_BASE) +-#define INT_730_SPI_100K_2 (37 + IH2_BASE) +-#define INT_730_RNG_IDLE (38 + IH2_BASE) +-#define INT_730_MPUIO (39 + IH2_BASE) +-#define INT_730_LLPC_LCD_CTRL_CAN_BE_OFF (40 + IH2_BASE) +-#define INT_730_LLPC_OE_FALLING (41 + IH2_BASE) +-#define INT_730_LLPC_OE_RISING (42 + IH2_BASE) +-#define INT_730_LLPC_VSYNC (43 + IH2_BASE) +-#define INT_730_WAKE_UP_REQ (46 + IH2_BASE) +-#define INT_730_DMA_CH6 (53 + IH2_BASE) +-#define INT_730_DMA_CH7 (54 + IH2_BASE) +-#define INT_730_DMA_CH8 (55 + IH2_BASE) +-#define INT_730_DMA_CH9 (56 + IH2_BASE) +-#define INT_730_DMA_CH10 (57 + IH2_BASE) +-#define INT_730_DMA_CH11 (58 + IH2_BASE) +-#define INT_730_DMA_CH12 (59 + IH2_BASE) +-#define INT_730_DMA_CH13 (60 + IH2_BASE) +-#define INT_730_DMA_CH14 (61 + IH2_BASE) +-#define INT_730_DMA_CH15 (62 + IH2_BASE) +-#define INT_730_NAND (63 + IH2_BASE) +- +-/* +- * OMAP-850 specific IRQ numbers for interrupt handler 2 ++ * OMAP-7xx specific IRQ numbers for interrupt handler 2 + */ +-#define INT_850_HW_ERRORS (0 + IH2_BASE) +-#define INT_850_NFIQ_PWR_FAIL (1 + IH2_BASE) +-#define INT_850_CFCD (2 + IH2_BASE) +-#define INT_850_CFIREQ (3 + IH2_BASE) +-#define INT_850_I2C (4 + IH2_BASE) +-#define INT_850_PCC (5 + IH2_BASE) +-#define INT_850_MPU_EXT_NIRQ (6 + IH2_BASE) +-#define INT_850_SPI_100K_1 (7 + IH2_BASE) +-#define INT_850_SYREN_SPI (8 + IH2_BASE) +-#define INT_850_VLYNQ (9 + IH2_BASE) +-#define INT_850_GPIO_BANK4 (10 + IH2_BASE) +-#define INT_850_McBSP1TX (11 + IH2_BASE) +-#define INT_850_McBSP1RX (12 + IH2_BASE) +-#define INT_850_McBSP1RX_OF (13 + IH2_BASE) +-#define INT_850_UART_MODEM_IRDA_2 (14 + IH2_BASE) +-#define INT_850_UART_MODEM_1 (15 + IH2_BASE) +-#define INT_850_MCSI (16 + IH2_BASE) +-#define INT_850_uWireTX (17 + IH2_BASE) +-#define INT_850_uWireRX (18 + IH2_BASE) +-#define INT_850_SMC_CD (19 + IH2_BASE) +-#define INT_850_SMC_IREQ (20 + IH2_BASE) +-#define INT_850_HDQ_1WIRE (21 + IH2_BASE) +-#define INT_850_TIMER32K (22 + IH2_BASE) +-#define INT_850_MMC_SDIO (23 + IH2_BASE) +-#define INT_850_UPLD (24 + IH2_BASE) +-#define INT_850_USB_HHC_1 (27 + IH2_BASE) +-#define INT_850_USB_HHC_2 (28 + IH2_BASE) +-#define INT_850_USB_GENI (29 + IH2_BASE) +-#define INT_850_USB_OTG (30 + IH2_BASE) +-#define INT_850_CAMERA_IF (31 + IH2_BASE) +-#define INT_850_RNG (32 + IH2_BASE) +-#define INT_850_DUAL_MODE_TIMER (33 + IH2_BASE) +-#define INT_850_DBB_RF_EN (34 + IH2_BASE) +-#define INT_850_MPUIO_KEYPAD (35 + IH2_BASE) +-#define INT_850_SHA1_MD5 (36 + IH2_BASE) +-#define INT_850_SPI_100K_2 (37 + IH2_BASE) +-#define INT_850_RNG_IDLE (38 + IH2_BASE) +-#define INT_850_MPUIO (39 + IH2_BASE) +-#define INT_850_LLPC_LCD_CTRL_CAN_BE_OFF (40 + IH2_BASE) +-#define INT_850_LLPC_OE_FALLING (41 + IH2_BASE) +-#define INT_850_LLPC_OE_RISING (42 + IH2_BASE) +-#define INT_850_LLPC_VSYNC (43 + IH2_BASE) +-#define INT_850_WAKE_UP_REQ (46 + IH2_BASE) +-#define INT_850_DMA_CH6 (53 + IH2_BASE) +-#define INT_850_DMA_CH7 (54 + IH2_BASE) +-#define INT_850_DMA_CH8 (55 + IH2_BASE) +-#define INT_850_DMA_CH9 (56 + IH2_BASE) +-#define INT_850_DMA_CH10 (57 + IH2_BASE) +-#define INT_850_DMA_CH11 (58 + IH2_BASE) +-#define INT_850_DMA_CH12 (59 + IH2_BASE) +-#define INT_850_DMA_CH13 (60 + IH2_BASE) +-#define INT_850_DMA_CH14 (61 + IH2_BASE) +-#define INT_850_DMA_CH15 (62 + IH2_BASE) +-#define INT_850_NAND (63 + IH2_BASE) ++#define INT_7XX_HW_ERRORS (0 + IH2_BASE) ++#define INT_7XX_NFIQ_PWR_FAIL (1 + IH2_BASE) ++#define INT_7XX_CFCD (2 + IH2_BASE) ++#define INT_7XX_CFIREQ (3 + IH2_BASE) ++#define INT_7XX_I2C (4 + IH2_BASE) ++#define INT_7XX_PCC (5 + IH2_BASE) ++#define INT_7XX_MPU_EXT_NIRQ (6 + IH2_BASE) ++#define INT_7XX_SPI_100K_1 (7 + IH2_BASE) ++#define INT_7XX_SYREN_SPI (8 + IH2_BASE) ++#define INT_7XX_VLYNQ (9 + IH2_BASE) ++#define INT_7XX_GPIO_BANK4 (10 + IH2_BASE) ++#define INT_7XX_McBSP1TX (11 + IH2_BASE) ++#define INT_7XX_McBSP1RX (12 + IH2_BASE) ++#define INT_7XX_McBSP1RX_OF (13 + IH2_BASE) ++#define INT_7XX_UART_MODEM_IRDA_2 (14 + IH2_BASE) ++#define INT_7XX_UART_MODEM_1 (15 + IH2_BASE) ++#define INT_7XX_MCSI (16 + IH2_BASE) ++#define INT_7XX_uWireTX (17 + IH2_BASE) ++#define INT_7XX_uWireRX (18 + IH2_BASE) ++#define INT_7XX_SMC_CD (19 + IH2_BASE) ++#define INT_7XX_SMC_IREQ (20 + IH2_BASE) ++#define INT_7XX_HDQ_1WIRE (21 + IH2_BASE) ++#define INT_7XX_TIMER32K (22 + IH2_BASE) ++#define INT_7XX_MMC_SDIO (23 + IH2_BASE) ++#define INT_7XX_UPLD (24 + IH2_BASE) ++#define INT_7XX_USB_HHC_1 (27 + IH2_BASE) ++#define INT_7XX_USB_HHC_2 (28 + IH2_BASE) ++#define INT_7XX_USB_GENI (29 + IH2_BASE) ++#define INT_7XX_USB_OTG (30 + IH2_BASE) ++#define INT_7XX_CAMERA_IF (31 + IH2_BASE) ++#define INT_7XX_RNG (32 + IH2_BASE) ++#define INT_7XX_DUAL_MODE_TIMER (33 + IH2_BASE) ++#define INT_7XX_DBB_RF_EN (34 + IH2_BASE) ++#define INT_7XX_MPUIO_KEYPAD (35 + IH2_BASE) ++#define INT_7XX_SHA1_MD5 (36 + IH2_BASE) ++#define INT_7XX_SPI_100K_2 (37 + IH2_BASE) ++#define INT_7XX_RNG_IDLE (38 + IH2_BASE) ++#define INT_7XX_MPUIO (39 + IH2_BASE) ++#define INT_7XX_LLPC_LCD_CTRL_CAN_BE_OFF (40 + IH2_BASE) ++#define INT_7XX_LLPC_OE_FALLING (41 + IH2_BASE) ++#define INT_7XX_LLPC_OE_RISING (42 + IH2_BASE) ++#define INT_7XX_LLPC_VSYNC (43 + IH2_BASE) ++#define INT_7XX_WAKE_UP_REQ (46 + IH2_BASE) ++#define INT_7XX_DMA_CH6 (53 + IH2_BASE) ++#define INT_7XX_DMA_CH7 (54 + IH2_BASE) ++#define INT_7XX_DMA_CH8 (55 + IH2_BASE) ++#define INT_7XX_DMA_CH9 (56 + IH2_BASE) ++#define INT_7XX_DMA_CH10 (57 + IH2_BASE) ++#define INT_7XX_DMA_CH11 (58 + IH2_BASE) ++#define INT_7XX_DMA_CH12 (59 + IH2_BASE) ++#define INT_7XX_DMA_CH13 (60 + IH2_BASE) ++#define INT_7XX_DMA_CH14 (61 + IH2_BASE) ++#define INT_7XX_DMA_CH15 (62 + IH2_BASE) ++#define INT_7XX_NAND (63 + IH2_BASE) + + #define INT_24XX_SYS_NIRQ 7 + #define INT_24XX_SDMA_IRQ0 12 +diff --git a/arch/arm/plat-omap/include/mach/mcbsp.h b/arch/arm/plat-omap/include/mach/mcbsp.h +index e0d6eca..7e9cae3 100644 +--- a/arch/arm/plat-omap/include/mach/mcbsp.h ++++ b/arch/arm/plat-omap/include/mach/mcbsp.h +@@ -30,8 +30,8 @@ + #include + #include + +-#define OMAP730_MCBSP1_BASE 0xfffb1000 +-#define OMAP730_MCBSP2_BASE 0xfffb1800 ++#define OMAP7XX_MCBSP1_BASE 0xfffb1000 ++#define OMAP7XX_MCBSP2_BASE 0xfffb1800 + + #define OMAP1510_MCBSP1_BASE 0xe1011800 + #define OMAP1510_MCBSP2_BASE 0xfffb1000 +@@ -58,7 +58,7 @@ + #define OMAP44XX_MCBSP3_BASE 0x49026000 + #define OMAP44XX_MCBSP4_BASE 0x48074000 + +-#if defined(CONFIG_ARCH_OMAP15XX) || defined(CONFIG_ARCH_OMAP16XX) || defined(CONFIG_ARCH_OMAP730) ++#if defined(CONFIG_ARCH_OMAP15XX) || defined(CONFIG_ARCH_OMAP16XX) || defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850) + + #define OMAP_MCBSP_REG_DRR2 0x00 + #define OMAP_MCBSP_REG_DRR1 0x02 +diff --git a/arch/arm/plat-omap/include/mach/mux.h b/arch/arm/plat-omap/include/mach/mux.h +index 0f49d2d..f3c1d8a 100644 +--- a/arch/arm/plat-omap/include/mach/mux.h ++++ b/arch/arm/plat-omap/include/mach/mux.h +@@ -51,23 +51,13 @@ + .pu_pd_reg = PU_PD_SEL_##reg, \ + .pu_pd_val = status, + +-#define MUX_REG_730(reg, mode_offset, mode) .mux_reg_name = "OMAP730_IO_CONF_"#reg, \ +- .mux_reg = OMAP730_IO_CONF_##reg, \ ++#define MUX_REG_7XX(reg, mode_offset, mode) .mux_reg_name = "OMAP7XX_IO_CONF_"#reg, \ ++ .mux_reg = OMAP7XX_IO_CONF_##reg, \ + .mask_offset = mode_offset, \ + .mask = mode, + +-#define PULL_REG_730(reg, bit, status) .pull_name = "OMAP730_IO_CONF_"#reg, \ +- .pull_reg = OMAP730_IO_CONF_##reg, \ +- .pull_bit = bit, \ +- .pull_val = status, +- +-#define MUX_REG_850(reg, mode_offset, mode) .mux_reg_name = "OMAP850_IO_CONF_"#reg, \ +- .mux_reg = OMAP850_IO_CONF_##reg, \ +- .mask_offset = mode_offset, \ +- .mask = mode, +- +-#define PULL_REG_850(reg, bit, status) .pull_name = "OMAP850_IO_CONF_"#reg, \ +- .pull_reg = OMAP850_IO_CONF_##reg, \ ++#define PULL_REG_7XX(reg, bit, status) .pull_name = "OMAP7XX_IO_CONF_"#reg, \ ++ .pull_reg = OMAP7XX_IO_CONF_##reg, \ + .pull_bit = bit, \ + .pull_val = status, + +@@ -84,21 +74,12 @@ + #define PU_PD_REG(reg, status) .pu_pd_reg = PU_PD_SEL_##reg, \ + .pu_pd_val = status, + +-#define MUX_REG_730(reg, mode_offset, mode) \ +- .mux_reg = OMAP730_IO_CONF_##reg, \ ++#define MUX_REG_7XX(reg, mode_offset, mode) \ ++ .mux_reg = OMAP7XX_IO_CONF_##reg, \ + .mask_offset = mode_offset, \ + .mask = mode, + +-#define PULL_REG_730(reg, bit, status) .pull_reg = OMAP730_IO_CONF_##reg, \ +- .pull_bit = bit, \ +- .pull_val = status, +- +-#define MUX_REG_850(reg, mode_offset, mode) \ +- .mux_reg = OMAP850_IO_CONF_##reg, \ +- .mask_offset = mode_offset, \ +- .mask = mode, +- +-#define PULL_REG_850(reg, bit, status) .pull_reg = OMAP850_IO_CONF_##reg, \ ++#define PULL_REG_7XX(reg, bit, status) .pull_reg = OMAP7XX_IO_CONF_##reg, \ + .pull_bit = bit, \ + .pull_val = status, + +@@ -118,32 +99,21 @@ + + /* + * OMAP730/850 has a slightly different config for the pin mux. +- * - config regs are the OMAP730_IO_CONF_x regs (see omap730.h) regs and ++ * - config regs are the OMAP7XX_IO_CONF_x regs (see omap730.h) regs and + * not the FUNC_MUX_CTRL_x regs from hardware.h + * - for pull-up/down, only has one enable bit which is is in the same register + * as mux config + */ +-#define MUX_CFG_730(desc, mux_reg, mode_offset, mode, \ ++#define MUX_CFG_7XX(desc, mux_reg, mode_offset, mode, \ + pull_bit, pull_status, debug_status)\ + { \ + .name = desc, \ + .debug = debug_status, \ +- MUX_REG_730(mux_reg, mode_offset, mode) \ +- PULL_REG_730(mux_reg, pull_bit, pull_status) \ ++ MUX_REG_7XX(mux_reg, mode_offset, mode) \ ++ PULL_REG_7XX(mux_reg, pull_bit, pull_status) \ + PU_PD_REG(NA, 0) \ + }, + +-#define MUX_CFG_850(desc, mux_reg, mode_offset, mode, \ +- pull_bit, pull_status, debug_status)\ +-{ \ +- .name = desc, \ +- .debug = debug_status, \ +- MUX_REG_850(mux_reg, mode_offset, mode) \ +- PULL_REG_850(mux_reg, pull_bit, pull_status) \ +- PU_PD_REG(NA, 0) \ +-}, +- +- + #define MUX_CFG_24XX(desc, reg_offset, mode, \ + pull_en, pull_mode, dbg) \ + { \ +@@ -232,45 +202,25 @@ struct pin_config { + + }; + +-enum omap730_index { ++enum omap7xx_index { + /* OMAP 730 keyboard */ +- E2_730_KBR0, +- J7_730_KBR1, +- E1_730_KBR2, +- F3_730_KBR3, +- D2_730_KBR4, +- C2_730_KBC0, +- D3_730_KBC1, +- E4_730_KBC2, +- F4_730_KBC3, +- E3_730_KBC4, +- +- /* USB */ +- AA17_730_USB_DM, +- W16_730_USB_PU_EN, +- W17_730_USB_VBUSI, +-}; +- +-enum omap850_index { +- /* OMAP 850 keyboard */ +- E2_850_KBR0, +- J7_850_KBR1, +- E1_850_KBR2, +- F3_850_KBR3, +- D2_850_KBR4, +- C2_850_KBC0, +- D3_850_KBC1, +- E4_850_KBC2, +- F4_850_KBC3, +- E3_850_KBC4, ++ E2_7XX_KBR0, ++ J7_7XX_KBR1, ++ E1_7XX_KBR2, ++ F3_7XX_KBR3, ++ D2_7XX_KBR4, ++ C2_7XX_KBC0, ++ D3_7XX_KBC1, ++ E4_7XX_KBC2, ++ F4_7XX_KBC3, ++ E3_7XX_KBC4, + + /* USB */ +- AA17_850_USB_DM, +- W16_850_USB_PU_EN, +- W17_850_USB_VBUSI, ++ AA17_7XX_USB_DM, ++ W16_7XX_USB_PU_EN, ++ W17_7XX_USB_VBUSI, + }; + +- + enum omap1xxx_index { + /* UART1 (BT_UART_GATING)*/ + UART1_TX = 0, +diff --git a/arch/arm/plat-omap/include/mach/omap34xx.h b/arch/arm/plat-omap/include/mach/omap34xx.h +index f8d186a..4655707 100644 +--- a/arch/arm/plat-omap/include/mach/omap34xx.h ++++ b/arch/arm/plat-omap/include/mach/omap34xx.h +@@ -74,8 +74,12 @@ + + #define OMAP34XX_IVA_INTC_BASE 0x40000000 + #define OMAP34XX_HSUSB_OTG_BASE (L4_34XX_BASE + 0xAB000) +-#define OMAP34XX_HSUSB_HOST_BASE (L4_34XX_BASE + 0x64000) + #define OMAP34XX_USBTLL_BASE (L4_34XX_BASE + 0x62000) ++#define OMAP34XX_UHH_CONFIG_BASE (L4_34XX_BASE + 0x64000) ++#define OMAP34XX_OHCI_BASE (L4_34XX_BASE + 0x64400) ++#define OMAP34XX_EHCI_BASE (L4_34XX_BASE + 0x64800) ++#define OMAP34XX_SR1_BASE 0x480C9000 ++#define OMAP34XX_SR2_BASE 0x480CB000 + + #define OMAP34XX_MAILBOX_BASE (L4_34XX_BASE + 0x94000) + +diff --git a/arch/arm/plat-omap/include/mach/omap44xx.h b/arch/arm/plat-omap/include/mach/omap44xx.h +index b3ba5ac..3361897 100644 +--- a/arch/arm/plat-omap/include/mach/omap44xx.h ++++ b/arch/arm/plat-omap/include/mach/omap44xx.h +@@ -22,6 +22,9 @@ + #define L4_PER_44XX_BASE 0x48000000 + #define L4_EMU_44XX_BASE 0x54000000 + #define L3_44XX_BASE 0x44000000 ++#define OMAP44XX_EMIF1_BASE 0x4c000000 ++#define OMAP44XX_EMIF2_BASE 0x4d000000 ++#define OMAP44XX_DMM_BASE 0x4e000000 + #define OMAP4430_32KSYNCT_BASE 0x4a304000 + #define OMAP4430_CM_BASE 0x4a004000 + #define OMAP4430_PRM_BASE 0x48306000 +@@ -33,14 +36,9 @@ + #define IRQ_SIR_IRQ 0x0040 + #define OMAP44XX_GIC_DIST_BASE 0x48241000 + #define OMAP44XX_GIC_CPU_BASE 0x48240100 +-#define OMAP44XX_VA_GIC_CPU_BASE OMAP2_IO_ADDRESS(OMAP44XX_GIC_CPU_BASE) + #define OMAP44XX_SCU_BASE 0x48240000 +-#define OMAP44XX_VA_SCU_BASE OMAP2_IO_ADDRESS(OMAP44XX_SCU_BASE) + #define OMAP44XX_LOCAL_TWD_BASE 0x48240600 +-#define OMAP44XX_VA_LOCAL_TWD_BASE OMAP2_IO_ADDRESS(OMAP44XX_LOCAL_TWD_BASE) +-#define OMAP44XX_LOCAL_TWD_SIZE 0x00000100 + #define OMAP44XX_WKUPGEN_BASE 0x48281000 +-#define OMAP44XX_VA_WKUPGEN_BASE OMAP2_IO_ADDRESS(OMAP44XX_WKUPGEN_BASE) + + #endif /* __ASM_ARCH_OMAP44XX_H */ + +diff --git a/arch/arm/plat-omap/include/mach/omap7xx.h b/arch/arm/plat-omap/include/mach/omap7xx.h +new file mode 100644 +index 0000000..53f5241 +--- /dev/null ++++ b/arch/arm/plat-omap/include/mach/omap7xx.h +@@ -0,0 +1,104 @@ ++/* arch/arm/plat-omap/include/mach/omap7xx.h ++ * ++ * Hardware definitions for TI OMAP7XX processor. ++ * ++ * Cleanup for Linux-2.6 by Dirk Behme ++ * Adapted for omap850 by Zebediah C. McClure ++ * Adapted for omap7xx by Alistair Buxton ++ * ++ * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED ++ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN ++ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, ++ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT ++ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF ++ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ++ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF ++ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ * ++ * 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., ++ * 675 Mass Ave, Cambridge, MA 02139, USA. ++ */ ++ ++#ifndef __ASM_ARCH_OMAP7XX_H ++#define __ASM_ARCH_OMAP7XX_H ++ ++/* ++ * ---------------------------------------------------------------------------- ++ * Base addresses ++ * ---------------------------------------------------------------------------- ++ */ ++ ++/* Syntax: XX_BASE = Virtual base address, XX_START = Physical base address */ ++ ++#define OMAP7XX_DSP_BASE 0xE0000000 ++#define OMAP7XX_DSP_SIZE 0x50000 ++#define OMAP7XX_DSP_START 0xE0000000 ++ ++#define OMAP7XX_DSPREG_BASE 0xE1000000 ++#define OMAP7XX_DSPREG_SIZE SZ_128K ++#define OMAP7XX_DSPREG_START 0xE1000000 ++ ++/* ++ * ---------------------------------------------------------------------------- ++ * OMAP7XX specific configuration registers ++ * ---------------------------------------------------------------------------- ++ */ ++#define OMAP7XX_CONFIG_BASE 0xfffe1000 ++#define OMAP7XX_IO_CONF_0 0xfffe1070 ++#define OMAP7XX_IO_CONF_1 0xfffe1074 ++#define OMAP7XX_IO_CONF_2 0xfffe1078 ++#define OMAP7XX_IO_CONF_3 0xfffe107c ++#define OMAP7XX_IO_CONF_4 0xfffe1080 ++#define OMAP7XX_IO_CONF_5 0xfffe1084 ++#define OMAP7XX_IO_CONF_6 0xfffe1088 ++#define OMAP7XX_IO_CONF_7 0xfffe108c ++#define OMAP7XX_IO_CONF_8 0xfffe1090 ++#define OMAP7XX_IO_CONF_9 0xfffe1094 ++#define OMAP7XX_IO_CONF_10 0xfffe1098 ++#define OMAP7XX_IO_CONF_11 0xfffe109c ++#define OMAP7XX_IO_CONF_12 0xfffe10a0 ++#define OMAP7XX_IO_CONF_13 0xfffe10a4 ++ ++#define OMAP7XX_MODE_1 0xfffe1010 ++#define OMAP7XX_MODE_2 0xfffe1014 ++ ++/* CSMI specials: in terms of base + offset */ ++#define OMAP7XX_MODE2_OFFSET 0x14 ++ ++/* ++ * ---------------------------------------------------------------------------- ++ * OMAP7XX traffic controller configuration registers ++ * ---------------------------------------------------------------------------- ++ */ ++#define OMAP7XX_FLASH_CFG_0 0xfffecc10 ++#define OMAP7XX_FLASH_ACFG_0 0xfffecc50 ++#define OMAP7XX_FLASH_CFG_1 0xfffecc14 ++#define OMAP7XX_FLASH_ACFG_1 0xfffecc54 ++ ++/* ++ * ---------------------------------------------------------------------------- ++ * OMAP7XX DSP control registers ++ * ---------------------------------------------------------------------------- ++ */ ++#define OMAP7XX_ICR_BASE 0xfffbb800 ++#define OMAP7XX_DSP_M_CTL 0xfffbb804 ++#define OMAP7XX_DSP_MMU_BASE 0xfffed200 ++ ++/* ++ * ---------------------------------------------------------------------------- ++ * OMAP7XX PCC_UPLD configuration registers ++ * ---------------------------------------------------------------------------- ++ */ ++#define OMAP7XX_PCC_UPLD_CTRL_BASE (0xfffe0900) ++#define OMAP7XX_PCC_UPLD_CTRL (OMAP7XX_PCC_UPLD_CTRL_BASE + 0x00) ++ ++#endif /* __ASM_ARCH_OMAP7XX_H */ ++ +diff --git a/arch/arm/plat-omap/include/mach/sdrc.h b/arch/arm/plat-omap/include/mach/sdrc.h +index 1c09c78..7b58a5f 100644 +--- a/arch/arm/plat-omap/include/mach/sdrc.h ++++ b/arch/arm/plat-omap/include/mach/sdrc.h +@@ -80,11 +80,11 @@ + */ + + #define OMAP242X_SMS_REGADDR(reg) \ +- (void __iomem *)OMAP2_IO_ADDRESS(OMAP2420_SMS_BASE + reg) ++ (void __iomem *)OMAP2_L3_IO_ADDRESS(OMAP2420_SMS_BASE + reg) + #define OMAP243X_SMS_REGADDR(reg) \ +- (void __iomem *)OMAP2_IO_ADDRESS(OMAP243X_SMS_BASE + reg) ++ (void __iomem *)OMAP2_L3_IO_ADDRESS(OMAP243X_SMS_BASE + reg) + #define OMAP343X_SMS_REGADDR(reg) \ +- (void __iomem *)OMAP2_IO_ADDRESS(OMAP343X_SMS_BASE + reg) ++ (void __iomem *)OMAP2_L3_IO_ADDRESS(OMAP343X_SMS_BASE + reg) + + /* SMS register offsets - read/write with sms_{read,write}_reg() */ + +diff --git a/arch/arm/plat-omap/include/mach/serial.h b/arch/arm/plat-omap/include/mach/serial.h +index e249186..9951345 100644 +--- a/arch/arm/plat-omap/include/mach/serial.h ++++ b/arch/arm/plat-omap/include/mach/serial.h +@@ -20,26 +20,22 @@ + #define OMAP_UART1_BASE 0xfffb0000 + #define OMAP_UART2_BASE 0xfffb0800 + #define OMAP_UART3_BASE 0xfffb9800 +-#define OMAP_MAX_NR_PORTS 3 + #elif defined(CONFIG_ARCH_OMAP2) + /* OMAP2 serial ports */ + #define OMAP_UART1_BASE 0x4806a000 + #define OMAP_UART2_BASE 0x4806c000 + #define OMAP_UART3_BASE 0x4806e000 +-#define OMAP_MAX_NR_PORTS 3 + #elif defined(CONFIG_ARCH_OMAP3) + /* OMAP3 serial ports */ + #define OMAP_UART1_BASE 0x4806a000 + #define OMAP_UART2_BASE 0x4806c000 + #define OMAP_UART3_BASE 0x49020000 +-#define OMAP_MAX_NR_PORTS 3 + #elif defined(CONFIG_ARCH_OMAP4) + /* OMAP4 serial ports */ + #define OMAP_UART1_BASE 0x4806a000 + #define OMAP_UART2_BASE 0x4806c000 + #define OMAP_UART3_BASE 0x48020000 + #define OMAP_UART4_BASE 0x4806e000 +-#define OMAP_MAX_NR_PORTS 4 + #endif + + #define OMAP1510_BASE_BAUD (12000000/16) +diff --git a/arch/arm/plat-omap/include/mach/uncompress.h b/arch/arm/plat-omap/include/mach/uncompress.h +index 0814c5f..ddf7b88 100644 +--- a/arch/arm/plat-omap/include/mach/uncompress.h ++++ b/arch/arm/plat-omap/include/mach/uncompress.h +@@ -25,6 +25,7 @@ unsigned int system_rev; + + #define UART_OMAP_MDR1 0x08 /* mode definition register */ + #define OMAP_ID_730 0x355F ++#define OMAP_ID_850 0x362C + #define ID_MASK 0x7fff + #define check_port(base, shift) ((base[UART_OMAP_MDR1 << shift] & 7) == 0) + #define omap_get_id() ((*(volatile unsigned int *)(0xfffed404)) >> 12) & ID_MASK +@@ -53,7 +54,7 @@ static void putc(int c) + /* MMU is not on, so cpu_is_omapXXXX() won't work here */ + unsigned int omap_id = omap_get_id(); + +- if (omap_id == OMAP_ID_730) ++ if (omap_id == OMAP_ID_730 || omap_id == OMAP_ID_850) + shift = 0; + + if (check_port(uart, shift)) +diff --git a/arch/arm/plat-omap/include/mach/usb.h b/arch/arm/plat-omap/include/mach/usb.h +index f337e17..a4068a4 100644 +--- a/arch/arm/plat-omap/include/mach/usb.h ++++ b/arch/arm/plat-omap/include/mach/usb.h +@@ -5,6 +5,21 @@ + + #include + ++#define OMAP3_HS_USB_PORTS 3 ++enum ehci_hcd_omap_mode { ++ EHCI_HCD_OMAP_MODE_UNKNOWN, ++ EHCI_HCD_OMAP_MODE_PHY, ++ EHCI_HCD_OMAP_MODE_TLL, ++}; ++ ++struct ehci_hcd_omap_platform_data { ++ enum ehci_hcd_omap_mode port_mode[OMAP3_HS_USB_PORTS]; ++ unsigned phy_reset:1; ++ ++ /* have to be valid if phy_reset is true and portx is in phy mode */ ++ int reset_gpio_port[OMAP3_HS_USB_PORTS]; ++}; ++ + /*-------------------------------------------------------------------------*/ + + #define OMAP1_OTG_BASE 0xfffb0400 +@@ -29,6 +44,8 @@ + + extern void usb_musb_init(void); + ++extern void usb_ehci_init(struct ehci_hcd_omap_platform_data *pdata); ++ + #endif + + void omap_usb_init(struct omap_usb_config *pdata); +diff --git a/arch/arm/plat-omap/include/mach/vmalloc.h b/arch/arm/plat-omap/include/mach/vmalloc.h +index b97dfaf..9eebf62 100644 +--- a/arch/arm/plat-omap/include/mach/vmalloc.h ++++ b/arch/arm/plat-omap/include/mach/vmalloc.h +@@ -17,5 +17,5 @@ + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +-#define VMALLOC_END (PAGE_OFFSET + 0x18000000) ++#define VMALLOC_END (PAGE_OFFSET + 0x38000000) + +diff --git a/arch/arm/plat-omap/io.c b/arch/arm/plat-omap/io.c +index b6defa2..93c1d53 100644 +--- a/arch/arm/plat-omap/io.c ++++ b/arch/arm/plat-omap/io.c +@@ -13,7 +13,7 @@ + #include + #include + +-#include ++#include + #include + #include + #include +@@ -33,13 +33,13 @@ void __iomem *omap_ioremap(unsigned long p, size_t size, unsigned int type) + if (BETWEEN(p, OMAP1_IO_PHYS, OMAP1_IO_SIZE)) + return XLATE(p, OMAP1_IO_PHYS, OMAP1_IO_VIRT); + } +- if (cpu_is_omap730()) { +- if (BETWEEN(p, OMAP730_DSP_BASE, OMAP730_DSP_SIZE)) +- return XLATE(p, OMAP730_DSP_BASE, OMAP730_DSP_START); ++ if (cpu_is_omap7xx()) { ++ if (BETWEEN(p, OMAP7XX_DSP_BASE, OMAP7XX_DSP_SIZE)) ++ return XLATE(p, OMAP7XX_DSP_BASE, OMAP7XX_DSP_START); + +- if (BETWEEN(p, OMAP730_DSPREG_BASE, OMAP730_DSPREG_SIZE)) +- return XLATE(p, OMAP730_DSPREG_BASE, +- OMAP730_DSPREG_START); ++ if (BETWEEN(p, OMAP7XX_DSPREG_BASE, OMAP7XX_DSPREG_SIZE)) ++ return XLATE(p, OMAP7XX_DSPREG_BASE, ++ OMAP7XX_DSPREG_START); + } + if (cpu_is_omap15xx()) { + if (BETWEEN(p, OMAP1510_DSP_BASE, OMAP1510_DSP_SIZE)) +@@ -114,6 +114,14 @@ void __iomem *omap_ioremap(unsigned long p, size_t size, unsigned int type) + return XLATE(p, L4_WK_44XX_PHYS, L4_WK_44XX_VIRT); + if (BETWEEN(p, OMAP44XX_GPMC_PHYS, OMAP44XX_GPMC_SIZE)) + return XLATE(p, OMAP44XX_GPMC_PHYS, OMAP44XX_GPMC_VIRT); ++ if (BETWEEN(p, OMAP44XX_EMIF1_PHYS, OMAP44XX_EMIF1_SIZE)) ++ return XLATE(p, OMAP44XX_EMIF1_PHYS, \ ++ OMAP44XX_EMIF1_VIRT); ++ if (BETWEEN(p, OMAP44XX_EMIF2_PHYS, OMAP44XX_EMIF2_SIZE)) ++ return XLATE(p, OMAP44XX_EMIF2_PHYS, \ ++ OMAP44XX_EMIF2_VIRT); ++ if (BETWEEN(p, OMAP44XX_DMM_PHYS, OMAP44XX_DMM_SIZE)) ++ return XLATE(p, OMAP44XX_DMM_PHYS, OMAP44XX_DMM_VIRT); + if (BETWEEN(p, L4_PER_44XX_PHYS, L4_PER_44XX_SIZE)) + return XLATE(p, L4_PER_44XX_PHYS, L4_PER_44XX_VIRT); + if (BETWEEN(p, L4_EMU_44XX_PHYS, L4_EMU_44XX_SIZE)) +@@ -142,7 +150,7 @@ u8 omap_readb(u32 pa) + if (cpu_class_is_omap1()) + return __raw_readb(OMAP1_IO_ADDRESS(pa)); + else +- return __raw_readb(OMAP2_IO_ADDRESS(pa)); ++ return __raw_readb(OMAP2_L4_IO_ADDRESS(pa)); + } + EXPORT_SYMBOL(omap_readb); + +@@ -151,7 +159,7 @@ u16 omap_readw(u32 pa) + if (cpu_class_is_omap1()) + return __raw_readw(OMAP1_IO_ADDRESS(pa)); + else +- return __raw_readw(OMAP2_IO_ADDRESS(pa)); ++ return __raw_readw(OMAP2_L4_IO_ADDRESS(pa)); + } + EXPORT_SYMBOL(omap_readw); + +@@ -160,7 +168,7 @@ u32 omap_readl(u32 pa) + if (cpu_class_is_omap1()) + return __raw_readl(OMAP1_IO_ADDRESS(pa)); + else +- return __raw_readl(OMAP2_IO_ADDRESS(pa)); ++ return __raw_readl(OMAP2_L4_IO_ADDRESS(pa)); + } + EXPORT_SYMBOL(omap_readl); + +@@ -169,7 +177,7 @@ void omap_writeb(u8 v, u32 pa) + if (cpu_class_is_omap1()) + __raw_writeb(v, OMAP1_IO_ADDRESS(pa)); + else +- __raw_writeb(v, OMAP2_IO_ADDRESS(pa)); ++ __raw_writeb(v, OMAP2_L4_IO_ADDRESS(pa)); + } + EXPORT_SYMBOL(omap_writeb); + +@@ -178,7 +186,7 @@ void omap_writew(u16 v, u32 pa) + if (cpu_class_is_omap1()) + __raw_writew(v, OMAP1_IO_ADDRESS(pa)); + else +- __raw_writew(v, OMAP2_IO_ADDRESS(pa)); ++ __raw_writew(v, OMAP2_L4_IO_ADDRESS(pa)); + } + EXPORT_SYMBOL(omap_writew); + +@@ -187,6 +195,6 @@ void omap_writel(u32 v, u32 pa) + if (cpu_class_is_omap1()) + __raw_writel(v, OMAP1_IO_ADDRESS(pa)); + else +- __raw_writel(v, OMAP2_IO_ADDRESS(pa)); ++ __raw_writel(v, OMAP2_L4_IO_ADDRESS(pa)); + } + EXPORT_SYMBOL(omap_writel); +diff --git a/arch/arm/plat-omap/omap_device.c b/arch/arm/plat-omap/omap_device.c +index 2c409fc..12513f4 100644 +--- a/arch/arm/plat-omap/omap_device.c ++++ b/arch/arm/plat-omap/omap_device.c +@@ -103,21 +103,6 @@ + /* Private functions */ + + /** +- * _read_32ksynct - read the OMAP 32K sync timer +- * +- * Returns the current value of the 32KiHz synchronization counter. +- * XXX this should be generalized to simply read the system clocksource. +- * XXX this should be moved to a separate synctimer32k.c file +- */ +-static u32 _read_32ksynct(void) +-{ +- if (!cpu_class_is_omap2()) +- BUG(); +- +- return __raw_readl(OMAP2_IO_ADDRESS(OMAP_32KSYNCT_BASE + 0x010)); +-} +- +-/** + * _omap_device_activate - increase device readiness + * @od: struct omap_device * + * @ignore_lat: increase to latency target (0) or full readiness (1)? +@@ -133,13 +118,13 @@ static u32 _read_32ksynct(void) + */ + static int _omap_device_activate(struct omap_device *od, u8 ignore_lat) + { +- u32 a, b; ++ struct timespec a, b, c; + + pr_debug("omap_device: %s: activating\n", od->pdev.name); + + while (od->pm_lat_level > 0) { + struct omap_device_pm_latency *odpl; +- int act_lat = 0; ++ unsigned long long act_lat = 0; + + od->pm_lat_level--; + +@@ -149,20 +134,22 @@ static int _omap_device_activate(struct omap_device *od, u8 ignore_lat) + (od->dev_wakeup_lat <= od->_dev_wakeup_lat_limit)) + break; + +- a = _read_32ksynct(); ++ getnstimeofday(&a); + + /* XXX check return code */ + odpl->activate_func(od); + +- b = _read_32ksynct(); ++ getnstimeofday(&b); + +- act_lat = (b - a) >> 15; /* 32KiHz cycles to microseconds */ ++ c = timespec_sub(b, a); ++ act_lat = timespec_to_ns(&c) * NSEC_PER_USEC; + + pr_debug("omap_device: %s: pm_lat %d: activate: elapsed time " +- "%d usec\n", od->pdev.name, od->pm_lat_level, act_lat); ++ "%llu usec\n", od->pdev.name, od->pm_lat_level, ++ act_lat); + + WARN(act_lat > odpl->activate_lat, "omap_device: %s.%d: " +- "activate step %d took longer than expected (%d > %d)\n", ++ "activate step %d took longer than expected (%llu > %d)\n", + od->pdev.name, od->pdev.id, od->pm_lat_level, + act_lat, odpl->activate_lat); + +@@ -188,13 +175,13 @@ static int _omap_device_activate(struct omap_device *od, u8 ignore_lat) + */ + static int _omap_device_deactivate(struct omap_device *od, u8 ignore_lat) + { +- u32 a, b; ++ struct timespec a, b, c; + + pr_debug("omap_device: %s: deactivating\n", od->pdev.name); + + while (od->pm_lat_level < od->pm_lats_cnt) { + struct omap_device_pm_latency *odpl; +- int deact_lat = 0; ++ unsigned long long deact_lat = 0; + + odpl = od->pm_lats + od->pm_lat_level; + +@@ -203,23 +190,24 @@ static int _omap_device_deactivate(struct omap_device *od, u8 ignore_lat) + od->_dev_wakeup_lat_limit)) + break; + +- a = _read_32ksynct(); ++ getnstimeofday(&a); + + /* XXX check return code */ + odpl->deactivate_func(od); + +- b = _read_32ksynct(); ++ getnstimeofday(&b); + +- deact_lat = (b - a) >> 15; /* 32KiHz cycles to microseconds */ ++ c = timespec_sub(b, a); ++ deact_lat = timespec_to_ns(&c) * NSEC_PER_USEC; + + pr_debug("omap_device: %s: pm_lat %d: deactivate: elapsed time " +- "%d usec\n", od->pdev.name, od->pm_lat_level, ++ "%llu usec\n", od->pdev.name, od->pm_lat_level, + deact_lat); + + WARN(deact_lat > odpl->deactivate_lat, "omap_device: %s.%d: " +- "deactivate step %d took longer than expected (%d > %d)\n", +- od->pdev.name, od->pdev.id, od->pm_lat_level, +- deact_lat, odpl->deactivate_lat); ++ "deactivate step %d took longer than expected " ++ "(%llu > %d)\n", od->pdev.name, od->pdev.id, ++ od->pm_lat_level, deact_lat, odpl->deactivate_lat); + + od->dev_wakeup_lat += odpl->activate_lat; + +diff --git a/arch/arm/plat-omap/sram.c b/arch/arm/plat-omap/sram.c +index 75d1f26..4144f81 100644 +--- a/arch/arm/plat-omap/sram.c ++++ b/arch/arm/plat-omap/sram.c +@@ -41,14 +41,14 @@ + #define OMAP1_SRAM_VA VMALLOC_END + #define OMAP2_SRAM_PA 0x40200000 + #define OMAP2_SRAM_PUB_PA 0x4020f800 +-#define OMAP2_SRAM_VA 0xe3000000 ++#define OMAP2_SRAM_VA 0xfe400000 + #define OMAP2_SRAM_PUB_VA (OMAP2_SRAM_VA + 0x800) + #define OMAP3_SRAM_PA 0x40200000 +-#define OMAP3_SRAM_VA 0xe3000000 ++#define OMAP3_SRAM_VA 0xfe400000 + #define OMAP3_SRAM_PUB_PA 0x40208000 + #define OMAP3_SRAM_PUB_VA (OMAP3_SRAM_VA + 0x8000) + #define OMAP4_SRAM_PA 0x40200000 /*0x402f0000*/ +-#define OMAP4_SRAM_VA 0xd7000000 /*0xd70f0000*/ ++#define OMAP4_SRAM_VA 0xfe400000 /*0xfe4f0000*/ + + #if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) + #define SRAM_BOOTLOADER_SZ 0x00 +@@ -56,16 +56,16 @@ + #define SRAM_BOOTLOADER_SZ 0x80 + #endif + +-#define OMAP24XX_VA_REQINFOPERM0 OMAP2_IO_ADDRESS(0x68005048) +-#define OMAP24XX_VA_READPERM0 OMAP2_IO_ADDRESS(0x68005050) +-#define OMAP24XX_VA_WRITEPERM0 OMAP2_IO_ADDRESS(0x68005058) ++#define OMAP24XX_VA_REQINFOPERM0 OMAP2_L3_IO_ADDRESS(0x68005048) ++#define OMAP24XX_VA_READPERM0 OMAP2_L3_IO_ADDRESS(0x68005050) ++#define OMAP24XX_VA_WRITEPERM0 OMAP2_L3_IO_ADDRESS(0x68005058) + +-#define OMAP34XX_VA_REQINFOPERM0 OMAP2_IO_ADDRESS(0x68012848) +-#define OMAP34XX_VA_READPERM0 OMAP2_IO_ADDRESS(0x68012850) +-#define OMAP34XX_VA_WRITEPERM0 OMAP2_IO_ADDRESS(0x68012858) +-#define OMAP34XX_VA_ADDR_MATCH2 OMAP2_IO_ADDRESS(0x68012880) +-#define OMAP34XX_VA_SMS_RG_ATT0 OMAP2_IO_ADDRESS(0x6C000048) +-#define OMAP34XX_VA_CONTROL_STAT OMAP2_IO_ADDRESS(0x480022F0) ++#define OMAP34XX_VA_REQINFOPERM0 OMAP2_L3_IO_ADDRESS(0x68012848) ++#define OMAP34XX_VA_READPERM0 OMAP2_L3_IO_ADDRESS(0x68012850) ++#define OMAP34XX_VA_WRITEPERM0 OMAP2_L3_IO_ADDRESS(0x68012858) ++#define OMAP34XX_VA_ADDR_MATCH2 OMAP2_L3_IO_ADDRESS(0x68012880) ++#define OMAP34XX_VA_SMS_RG_ATT0 OMAP2_L3_IO_ADDRESS(0x6C000048) ++#define OMAP34XX_VA_CONTROL_STAT OMAP2_L4_IO_ADDRESS(0x480022F0) + + #define GP_DEVICE 0x300 + +diff --git a/arch/arm/plat-omap/usb.c b/arch/arm/plat-omap/usb.c +index 509f2ed..3c40b85 100644 +--- a/arch/arm/plat-omap/usb.c ++++ b/arch/arm/plat-omap/usb.c +@@ -614,8 +614,8 @@ omap_otg_init(struct omap_usb_config *config) + if (config->otg || config->register_host) { + syscon &= ~HST_IDLE_EN; + ohci_device.dev.platform_data = config; +- if (cpu_is_omap730()) +- ohci_resources[1].start = INT_730_USB_HHC_1; ++ if (cpu_is_omap7xx()) ++ ohci_resources[1].start = INT_7XX_USB_HHC_1; + status = platform_device_register(&ohci_device); + if (status) + pr_debug("can't register OHCI device, %d\n", status); +@@ -626,8 +626,8 @@ omap_otg_init(struct omap_usb_config *config) + if (config->otg) { + syscon &= ~OTG_IDLE_EN; + otg_device.dev.platform_data = config; +- if (cpu_is_omap730()) +- otg_resources[1].start = INT_730_USB_OTG; ++ if (cpu_is_omap7xx()) ++ otg_resources[1].start = INT_7XX_USB_OTG; + status = platform_device_register(&otg_device); + if (status) + pr_debug("can't register OTG device, %d\n", status); +@@ -731,7 +731,7 @@ static inline void omap_1510_usb_init(struct omap_usb_config *config) {} + + void __init omap_usb_init(struct omap_usb_config *pdata) + { +- if (cpu_is_omap730() || cpu_is_omap16xx() || cpu_is_omap24xx()) ++ if (cpu_is_omap7xx() || cpu_is_omap16xx() || cpu_is_omap24xx()) + omap_otg_init(pdata); + else if (cpu_is_omap15xx()) + omap_1510_usb_init(pdata); +diff --git a/drivers/Makefile b/drivers/Makefile +index 6ee53c7..086857c 100644 +--- a/drivers/Makefile ++++ b/drivers/Makefile +@@ -72,7 +72,7 @@ obj-$(CONFIG_GAMEPORT) += input/gameport/ + obj-$(CONFIG_INPUT) += input/ + obj-$(CONFIG_I2O) += message/ + obj-$(CONFIG_RTC_LIB) += rtc/ +-obj-y += i2c/ media/ ++obj-y += i2c/ media/ cbus/ + obj-$(CONFIG_PPS) += pps/ + obj-$(CONFIG_W1) += w1/ + obj-$(CONFIG_POWER_SUPPLY) += power/ +diff --git a/drivers/cbus/Kconfig b/drivers/cbus/Kconfig +new file mode 100644 +index 0000000..25f8039 +--- /dev/null ++++ b/drivers/cbus/Kconfig +@@ -0,0 +1,89 @@ ++# ++# CBUS device configuration ++# ++ ++menu "CBUS support" ++ ++config CBUS ++ depends on ARCH_OMAP ++ bool "CBUS support on OMAP" ++ ---help--- ++ CBUS is a proprietary serial protocol by Nokia. It is mainly ++ used for accessing Energy Management auxiliary chips. ++ ++ If you want CBUS support, you should say Y here. ++ ++config CBUS_TAHVO ++ depends on CBUS ++ bool "Support for Tahvo" ++ ---help--- ++ Tahvo is a mixed signal ASIC with some system features ++ ++ If you want Tahvo support, you should say Y here. ++ ++config CBUS_TAHVO_USER ++ depends on CBUS_TAHVO ++ bool "Support for Tahvo user space functions" ++ ---help--- ++ If you want support for Tahvo's user space read/write etc. functions, ++ you should say Y here. ++ ++config CBUS_TAHVO_USB ++ depends on CBUS_TAHVO && USB ++ tristate "Support for Tahvo USB transceiver" ++ ---help--- ++ If you want Tahvo support for USB transceiver, say Y or M here. ++ ++config CBUS_TAHVO_USB_HOST_BY_DEFAULT ++ depends on CBUS_TAHVO_USB && USB_OTG ++ boolean "Device in USB host mode by default" ++ ---help--- ++ Say Y here, if you want the device to enter USB host mode ++ by default on bootup. ++ ++config CBUS_RETU ++ depends on CBUS ++ bool "Support for Retu" ++ ---help--- ++ Retu is a mixed signal ASIC with some system features ++ ++ If you want Retu support, you should say Y here. ++ ++config CBUS_RETU_USER ++ depends on CBUS_RETU ++ bool "Support for Retu user space functions" ++ ---help--- ++ If you want support for Retu's user space read/write etc. functions, ++ you should say Y here. ++ ++config CBUS_RETU_POWERBUTTON ++ depends on CBUS_RETU ++ bool "Support for Retu power button" ++ ---help--- ++ The power button on Nokia 770 is connected to the Retu ASIC. ++ ++ If you want support for the Retu power button, you should say Y here. ++ ++config CBUS_RETU_RTC ++ depends on CBUS_RETU && SYSFS ++ tristate "Support for Retu pseudo-RTC" ++ ---help--- ++ Say Y here if you want support for the device that alleges to be an ++ RTC in Retu. This will expose a sysfs interface for it. ++ ++config CBUS_RETU_WDT ++ depends on CBUS_RETU && SYSFS ++ tristate "Support for Retu watchdog timer" ++ ---help--- ++ Say Y here if you want support for the watchdog in Retu. This will ++ expose a sysfs interface to grok it. ++ ++config CBUS_RETU_HEADSET ++ depends on CBUS_RETU && SYSFS ++ tristate "Support for headset detection with Retu/Vilma" ++ ---help--- ++ Say Y here if you want support detecting a headset that's connected ++ to Retu/Vilma. Detection state and events are exposed through ++ sysfs. ++ ++endmenu +diff --git a/drivers/cbus/Makefile b/drivers/cbus/Makefile +new file mode 100644 +index 0000000..347c2a4 +--- /dev/null ++++ b/drivers/cbus/Makefile +@@ -0,0 +1,14 @@ ++# ++# Makefile for CBUS. ++# ++ ++obj-$(CONFIG_CBUS) += cbus.o ++obj-$(CONFIG_CBUS_TAHVO) += tahvo.o ++obj-$(CONFIG_CBUS_RETU) += retu.o ++obj-$(CONFIG_CBUS_TAHVO_USB) += tahvo-usb.o ++obj-$(CONFIG_CBUS_RETU_POWERBUTTON) += retu-pwrbutton.o ++obj-$(CONFIG_CBUS_RETU_RTC) += retu-rtc.o ++obj-$(CONFIG_CBUS_RETU_WDT) += retu-wdt.o ++obj-$(CONFIG_CBUS_TAHVO_USER) += tahvo-user.o ++obj-$(CONFIG_CBUS_RETU_USER) += retu-user.o ++obj-$(CONFIG_CBUS_RETU_HEADSET) += retu-headset.o +diff --git a/drivers/cbus/cbus.c b/drivers/cbus/cbus.c +new file mode 100644 +index 0000000..774acce +--- /dev/null ++++ b/drivers/cbus/cbus.c +@@ -0,0 +1,293 @@ ++/* ++ * drivers/cbus/cbus.c ++ * ++ * Support functions for CBUS serial protocol ++ * ++ * Copyright (C) 2004, 2005 Nokia Corporation ++ * ++ * Written by Juha Yrjölä , ++ * David Weinehall , and ++ * Mikko Ylinen ++ * ++ * 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 for more details. ++ * ++ * 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, MA 02111-1307 USA ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++ ++#include ++ ++#include "cbus.h" ++ ++struct cbus_host *cbus_host = NULL; ++ ++#ifdef CONFIG_ARCH_OMAP1 ++/* We use our own MPUIO functions to get closer to 1MHz bus speed */ ++ ++static inline void cbus_set_gpio_direction(u32 base, int mpuio, int is_input) ++{ ++ u16 w; ++ ++ mpuio &= 0x0f; ++ w = __raw_readw(base + OMAP_MPUIO_IO_CNTL); ++ if (is_input) ++ w |= 1 << mpuio; ++ else ++ w &= ~(1 << mpuio); ++ __raw_writew(w, base + OMAP_MPUIO_IO_CNTL); ++ ++} ++ ++static inline void cbus_set_gpio_dataout(u32 base, int mpuio, int enable) ++{ ++ u16 w; ++ ++ mpuio &= 0x0f; ++ w = __raw_readw(base + OMAP_MPUIO_OUTPUT); ++ if (enable) ++ w |= 1 << mpuio; ++ else ++ w &= ~(1 << mpuio); ++ __raw_writew(w, base + OMAP_MPUIO_OUTPUT); ++} ++ ++static inline int cbus_get_gpio_datain(u32 base, int mpuio) ++{ ++ mpuio &= 0x0f; ++ ++ return (__raw_readw(base + OMAP_MPUIO_INPUT_LATCH) & (1 << mpuio)) != 0; ++} ++ ++static void cbus_send_bit(struct cbus_host *host, u32 base, int bit, ++ int set_to_input) ++{ ++ cbus_set_gpio_dataout(base, host->dat_gpio, bit ? 1 : 0); ++ cbus_set_gpio_dataout(base, host->clk_gpio, 1); ++ ++ /* The data bit is read on the rising edge of CLK */ ++ if (set_to_input) ++ cbus_set_gpio_direction(base, host->dat_gpio, 1); ++ ++ cbus_set_gpio_dataout(base, host->clk_gpio, 0); ++} ++ ++static u8 cbus_receive_bit(struct cbus_host *host, u32 base) ++{ ++ u8 ret; ++ ++ cbus_set_gpio_dataout(base, host->clk_gpio, 1); ++ ret = cbus_get_gpio_datain(base, host->dat_gpio); ++ cbus_set_gpio_dataout(base, host->clk_gpio, 0); ++ ++ return ret; ++} ++ ++#define cbus_output(base, gpio, val) cbus_set_gpio_direction(base, gpio, 0) ++ ++#else ++ ++#define cbus_output(base, gpio, val) gpio_direction_output(gpio, val) ++#define cbus_set_gpio_dataout(base, gpio, enable) gpio_set_value(gpio, enable) ++#define cbus_get_gpio_datain(base, int, gpio) gpio_get_value(gpio) ++ ++static void _cbus_send_bit(struct cbus_host *host, int bit, int set_to_input) ++{ ++ gpio_set_value(host->dat_gpio, bit ? 1 : 0); ++ gpio_set_value(host->clk_gpio, 1); ++ ++ /* The data bit is read on the rising edge of CLK */ ++ if (set_to_input) ++ gpio_direction_input(host->dat_gpio); ++ ++ gpio_set_value(host->clk_gpio, 0); ++} ++ ++static u8 _cbus_receive_bit(struct cbus_host *host) ++{ ++ u8 ret; ++ ++ gpio_set_value(host->clk_gpio, 1); ++ ret = gpio_get_value(host->dat_gpio); ++ gpio_set_value(host->clk_gpio, 0); ++ ++ return ret; ++} ++ ++#define cbus_send_bit(host, base, bit, set_to_input) _cbus_send_bit(host, bit, set_to_input) ++#define cbus_receive_bit(host, base) _cbus_receive_bit(host) ++ ++#endif ++ ++static int cbus_transfer(struct cbus_host *host, int dev, int reg, int data) ++{ ++ int i; ++ int is_read = 0; ++ unsigned long flags; ++ u32 base; ++ ++#ifdef CONFIG_ARCH_OMAP1 ++ base = OMAP1_IO_ADDRESS(OMAP_MPUIO_BASE); ++#else ++ base = 0; ++#endif ++ ++ if (data < 0) ++ is_read = 1; ++ ++ /* We don't want interrupts disturbing our transfer */ ++ spin_lock_irqsave(&host->lock, flags); ++ ++ /* Reset state and start of transfer, SEL stays down during transfer */ ++ cbus_set_gpio_dataout(base, host->sel_gpio, 0); ++ ++ /* Set the DAT pin to output */ ++ cbus_output(base, host->dat_gpio, 1); ++ ++ /* Send the device address */ ++ for (i = 3; i > 0; i--) ++ cbus_send_bit(host, base, dev & (1 << (i - 1)), 0); ++ ++ /* Send the rw flag */ ++ cbus_send_bit(host, base, is_read, 0); ++ ++ /* Send the register address */ ++ for (i = 5; i > 0; i--) { ++ int set_to_input = 0; ++ ++ if (is_read && i == 1) ++ set_to_input = 1; ++ ++ cbus_send_bit(host, base, reg & (1 << (i - 1)), set_to_input); ++ } ++ ++ if (!is_read) { ++ for (i = 16; i > 0; i--) ++ cbus_send_bit(host, base, data & (1 << (i - 1)), 0); ++ } else { ++ cbus_set_gpio_dataout(base, host->clk_gpio, 1); ++ data = 0; ++ ++ for (i = 16; i > 0; i--) { ++ u8 bit = cbus_receive_bit(host, base); ++ ++ if (bit) ++ data |= 1 << (i - 1); ++ } ++ } ++ ++ /* Indicate end of transfer, SEL goes up until next transfer */ ++ cbus_set_gpio_dataout(base, host->sel_gpio, 1); ++ cbus_set_gpio_dataout(base, host->clk_gpio, 1); ++ cbus_set_gpio_dataout(base, host->clk_gpio, 0); ++ ++ spin_unlock_irqrestore(&host->lock, flags); ++ ++ return is_read ? data : 0; ++} ++ ++/* ++ * Read a given register from the device ++ */ ++int cbus_read_reg(struct cbus_host *host, int dev, int reg) ++{ ++ return cbus_host ? cbus_transfer(host, dev, reg, -1) : -ENODEV; ++} ++ ++/* ++ * Write to a given register of the device ++ */ ++int cbus_write_reg(struct cbus_host *host, int dev, int reg, u16 val) ++{ ++ return cbus_host ? cbus_transfer(host, dev, reg, (int)val) : -ENODEV; ++} ++ ++int __init cbus_bus_init(void) ++{ ++ const struct omap_cbus_config * cbus_config; ++ struct cbus_host *chost; ++ int ret; ++ ++ chost = kmalloc(sizeof (*chost), GFP_KERNEL); ++ if (chost == NULL) ++ return -ENOMEM; ++ ++ memset(chost, 0, sizeof (*chost)); ++ ++ spin_lock_init(&chost->lock); ++ ++ cbus_config = omap_get_config(OMAP_TAG_CBUS, struct omap_cbus_config); ++ ++ if (cbus_config == NULL) { ++ printk(KERN_ERR "cbus: Unable to retrieve config data\n"); ++ return -ENODATA; ++ } ++ ++ chost->clk_gpio = cbus_config->clk_gpio; ++ chost->dat_gpio = cbus_config->dat_gpio; ++ chost->sel_gpio = cbus_config->sel_gpio; ++ ++#ifdef CONFIG_ARCH_OMAP1 ++ if (!OMAP_GPIO_IS_MPUIO(chost->clk_gpio) || ++ !OMAP_GPIO_IS_MPUIO(chost->dat_gpio) || ++ !OMAP_GPIO_IS_MPUIO(chost->sel_gpio)) { ++ printk(KERN_ERR "cbus: Only MPUIO pins supported\n"); ++ ret = -ENODEV; ++ goto exit1; ++ } ++#endif ++ ++ if ((ret = gpio_request(chost->clk_gpio, "CBUS clk")) < 0) ++ goto exit1; ++ ++ if ((ret = gpio_request(chost->dat_gpio, "CBUS data")) < 0) ++ goto exit2; ++ ++ if ((ret = gpio_request(chost->sel_gpio, "CBUS sel")) < 0) ++ goto exit3; ++ ++ gpio_direction_output(chost->clk_gpio, 0); ++ gpio_direction_input(chost->dat_gpio); ++ gpio_direction_output(chost->sel_gpio, 1); ++ ++ gpio_set_value(chost->clk_gpio, 1); ++ gpio_set_value(chost->clk_gpio, 0); ++ ++ cbus_host = chost; ++ ++ return 0; ++exit3: ++ gpio_free(chost->dat_gpio); ++exit2: ++ gpio_free(chost->clk_gpio); ++exit1: ++ kfree(chost); ++ return ret; ++} ++ ++subsys_initcall(cbus_bus_init); ++ ++EXPORT_SYMBOL(cbus_host); ++EXPORT_SYMBOL(cbus_read_reg); ++EXPORT_SYMBOL(cbus_write_reg); ++ ++MODULE_DESCRIPTION("CBUS serial protocol"); ++MODULE_LICENSE("GPL"); ++MODULE_AUTHOR("Juha Yrjölä, David Weinehall, and Mikko Ylinen"); +diff --git a/drivers/cbus/cbus.h b/drivers/cbus/cbus.h +new file mode 100644 +index 0000000..957224c +--- /dev/null ++++ b/drivers/cbus/cbus.h +@@ -0,0 +1,36 @@ ++/* ++ * drivers/cbus/cbus.h ++ * ++ * Copyright (C) 2004, 2005 Nokia Corporation ++ * ++ * Written by Juha Yrjölä and ++ * David Weinehall ++ * ++ * 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 for more details. ++ * ++ * 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, MA 02111-1307 USA ++ */ ++ ++#ifndef __DRIVERS_CBUS_CBUS_H ++#define __DRIVERS_CBUS_CBUS_H ++ ++struct cbus_host { ++ int clk_gpio, dat_gpio, sel_gpio; ++ spinlock_t lock; ++}; ++ ++extern struct cbus_host *cbus_host; ++ ++extern int cbus_read_reg(struct cbus_host *host, int dev, int reg); ++extern int cbus_write_reg(struct cbus_host *host, int dev, int reg, u16 val); ++ ++#endif /* __DRIVERS_CBUS_CBUS_H */ +diff --git a/drivers/cbus/retu-headset.c b/drivers/cbus/retu-headset.c +new file mode 100644 +index 0000000..e798bc2 +--- /dev/null ++++ b/drivers/cbus/retu-headset.c +@@ -0,0 +1,355 @@ ++/** ++ * Retu/Vilma headset detection ++ * ++ * Copyright (C) 2006 Nokia Corporation ++ * ++ * Written by Juha Yrjölä ++ * ++ * 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 for more details. ++ * ++ * 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, MA 02111-1307 USA ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "retu.h" ++ ++#define RETU_ADC_CHANNEL_HOOKDET 0x05 ++ ++#define RETU_HEADSET_KEY KEY_PHONE ++ ++struct retu_headset { ++ spinlock_t lock; ++ struct mutex mutex; ++ struct platform_device *pdev; ++ struct input_dev *idev; ++ unsigned bias_enabled; ++ unsigned detection_enabled; ++ unsigned pressed; ++ struct timer_list enable_timer; ++ struct timer_list detect_timer; ++}; ++ ++static void retu_headset_set_bias(int enable) ++{ ++ if (enable) { ++ retu_set_clear_reg_bits(RETU_REG_AUDTXR, ++ (1 << 0) | (1 << 1), 0); ++ msleep(2); ++ retu_set_clear_reg_bits(RETU_REG_AUDTXR, 1 << 3, 0); ++ } else { ++ retu_set_clear_reg_bits(RETU_REG_AUDTXR, 0, ++ (1 << 0) | (1 << 1) | (1 << 3)); ++ } ++} ++ ++static void retu_headset_enable(struct retu_headset *hs) ++{ ++ mutex_lock(&hs->mutex); ++ if (!hs->bias_enabled) { ++ hs->bias_enabled = 1; ++ retu_headset_set_bias(1); ++ } ++ mutex_unlock(&hs->mutex); ++} ++ ++static void retu_headset_disable(struct retu_headset *hs) ++{ ++ mutex_lock(&hs->mutex); ++ if (hs->bias_enabled) { ++ hs->bias_enabled = 0; ++ retu_headset_set_bias(0); ++ } ++ mutex_unlock(&hs->mutex); ++} ++ ++static void retu_headset_det_enable(struct retu_headset *hs) ++{ ++ mutex_lock(&hs->mutex); ++ if (!hs->detection_enabled) { ++ hs->detection_enabled = 1; ++ retu_set_clear_reg_bits(RETU_REG_CC1, (1 << 10) | (1 << 8), 0); ++ retu_enable_irq(RETU_INT_HOOK); ++ } ++ mutex_unlock(&hs->mutex); ++} ++ ++static void retu_headset_det_disable(struct retu_headset *hs) ++{ ++ unsigned long flags; ++ ++ mutex_lock(&hs->mutex); ++ if (hs->detection_enabled) { ++ hs->detection_enabled = 0; ++ retu_disable_irq(RETU_INT_HOOK); ++ del_timer_sync(&hs->enable_timer); ++ del_timer_sync(&hs->detect_timer); ++ spin_lock_irqsave(&hs->lock, flags); ++ if (hs->pressed) ++ input_report_key(hs->idev, RETU_HEADSET_KEY, 0); ++ spin_unlock_irqrestore(&hs->lock, flags); ++ retu_set_clear_reg_bits(RETU_REG_CC1, 0, (1 << 10) | (1 << 8)); ++ } ++ mutex_unlock(&hs->mutex); ++} ++ ++static ssize_t retu_headset_hookdet_show(struct device *dev, ++ struct device_attribute *attr, ++ char *buf) ++{ ++ int val; ++ ++ val = retu_read_adc(RETU_ADC_CHANNEL_HOOKDET); ++ return sprintf(buf, "%d\n", val); ++} ++ ++static DEVICE_ATTR(hookdet, S_IRUGO, retu_headset_hookdet_show, NULL); ++ ++static ssize_t retu_headset_enable_show(struct device *dev, ++ struct device_attribute *attr, ++ char *buf) ++{ ++ struct retu_headset *hs = dev_get_drvdata(dev); ++ ++ return sprintf(buf, "%u\n", hs->bias_enabled); ++} ++ ++static ssize_t retu_headset_enable_store(struct device *dev, ++ struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ struct retu_headset *hs = dev_get_drvdata(dev); ++ int enable; ++ ++ if (sscanf(buf, "%u", &enable) != 1) ++ return -EINVAL; ++ if (enable) ++ retu_headset_enable(hs); ++ else ++ retu_headset_disable(hs); ++ return count; ++} ++ ++static DEVICE_ATTR(enable, S_IRUGO | S_IWUSR | S_IWGRP, ++ retu_headset_enable_show, retu_headset_enable_store); ++ ++static ssize_t retu_headset_enable_det_show(struct device *dev, ++ struct device_attribute *attr, ++ char *buf) ++{ ++ struct retu_headset *hs = dev_get_drvdata(dev); ++ ++ return sprintf(buf, "%u\n", hs->detection_enabled); ++} ++ ++static ssize_t retu_headset_enable_det_store(struct device *dev, ++ struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ struct retu_headset *hs = dev_get_drvdata(dev); ++ int enable; ++ ++ if (sscanf(buf, "%u", &enable) != 1) ++ return -EINVAL; ++ if (enable) ++ retu_headset_det_enable(hs); ++ else ++ retu_headset_det_disable(hs); ++ return count; ++} ++ ++static DEVICE_ATTR(enable_det, S_IRUGO | S_IWUSR | S_IWGRP, ++ retu_headset_enable_det_show, ++ retu_headset_enable_det_store); ++ ++static void retu_headset_hook_interrupt(unsigned long arg) ++{ ++ struct retu_headset *hs = (struct retu_headset *) arg; ++ unsigned long flags; ++ ++ retu_ack_irq(RETU_INT_HOOK); ++ spin_lock_irqsave(&hs->lock, flags); ++ if (!hs->pressed) { ++ /* Headset button was just pressed down. */ ++ hs->pressed = 1; ++ input_report_key(hs->idev, RETU_HEADSET_KEY, 1); ++ } ++ spin_unlock_irqrestore(&hs->lock, flags); ++ retu_set_clear_reg_bits(RETU_REG_CC1, 0, (1 << 10) | (1 << 8)); ++ mod_timer(&hs->enable_timer, jiffies + msecs_to_jiffies(50)); ++} ++ ++static void retu_headset_enable_timer(unsigned long arg) ++{ ++ struct retu_headset *hs = (struct retu_headset *) arg; ++ ++ retu_set_clear_reg_bits(RETU_REG_CC1, (1 << 10) | (1 << 8), 0); ++ mod_timer(&hs->detect_timer, jiffies + msecs_to_jiffies(350)); ++} ++ ++static void retu_headset_detect_timer(unsigned long arg) ++{ ++ struct retu_headset *hs = (struct retu_headset *) arg; ++ unsigned long flags; ++ ++ spin_lock_irqsave(&hs->lock, flags); ++ if (hs->pressed) { ++ hs->pressed = 0; ++ input_report_key(hs->idev, RETU_HEADSET_KEY, 0); ++ } ++ spin_unlock_irqrestore(&hs->lock, flags); ++} ++ ++static int __init retu_headset_probe(struct platform_device *pdev) ++{ ++ struct retu_headset *hs; ++ int r; ++ ++ hs = kzalloc(sizeof(*hs), GFP_KERNEL); ++ if (hs == NULL) ++ return -ENOMEM; ++ ++ hs->pdev = pdev; ++ ++ hs->idev = input_allocate_device(); ++ if (hs->idev == NULL) { ++ r = -ENOMEM; ++ goto err1; ++ } ++ hs->idev->name = "retu-headset"; ++ hs->idev->dev.parent = &pdev->dev; ++ set_bit(EV_KEY, hs->idev->evbit); ++ set_bit(RETU_HEADSET_KEY, hs->idev->keybit); ++ r = input_register_device(hs->idev); ++ if (r < 0) ++ goto err2; ++ ++ r = device_create_file(&pdev->dev, &dev_attr_hookdet); ++ if (r < 0) ++ goto err3; ++ r = device_create_file(&pdev->dev, &dev_attr_enable); ++ if (r < 0) ++ goto err4; ++ r = device_create_file(&pdev->dev, &dev_attr_enable_det); ++ if (r < 0) ++ goto err5; ++ platform_set_drvdata(pdev, hs); ++ ++ spin_lock_init(&hs->lock); ++ mutex_init(&hs->mutex); ++ setup_timer(&hs->enable_timer, retu_headset_enable_timer, ++ (unsigned long) hs); ++ setup_timer(&hs->detect_timer, retu_headset_detect_timer, ++ (unsigned long) hs); ++ ++ r = retu_request_irq(RETU_INT_HOOK, retu_headset_hook_interrupt, ++ (unsigned long) hs, "hookdet"); ++ if (r != 0) { ++ dev_err(&pdev->dev, "hookdet IRQ not available\n"); ++ goto err6; ++ } ++ retu_disable_irq(RETU_INT_HOOK); ++ return 0; ++err6: ++ device_remove_file(&pdev->dev, &dev_attr_enable_det); ++err5: ++ device_remove_file(&pdev->dev, &dev_attr_enable); ++err4: ++ device_remove_file(&pdev->dev, &dev_attr_hookdet); ++err3: ++ input_unregister_device(hs->idev); ++err2: ++ input_free_device(hs->idev); ++err1: ++ kfree(hs); ++ return r; ++} ++ ++static int retu_headset_remove(struct platform_device *pdev) ++{ ++ struct retu_headset *hs = platform_get_drvdata(pdev); ++ ++ device_remove_file(&pdev->dev, &dev_attr_hookdet); ++ device_remove_file(&pdev->dev, &dev_attr_enable); ++ device_remove_file(&pdev->dev, &dev_attr_enable_det); ++ retu_headset_disable(hs); ++ retu_headset_det_disable(hs); ++ retu_free_irq(RETU_INT_HOOK); ++ input_unregister_device(hs->idev); ++ input_free_device(hs->idev); ++ return 0; ++} ++ ++static int retu_headset_suspend(struct platform_device *pdev, ++ pm_message_t mesg) ++{ ++ struct retu_headset *hs = platform_get_drvdata(pdev); ++ ++ mutex_lock(&hs->mutex); ++ if (hs->bias_enabled) ++ retu_headset_set_bias(0); ++ mutex_unlock(&hs->mutex); ++ ++ return 0; ++} ++ ++static int retu_headset_resume(struct platform_device *pdev) ++{ ++ struct retu_headset *hs = platform_get_drvdata(pdev); ++ ++ mutex_lock(&hs->mutex); ++ if (hs->bias_enabled) ++ retu_headset_set_bias(1); ++ mutex_unlock(&hs->mutex); ++ ++ return 0; ++} ++ ++static struct platform_driver retu_headset_driver = { ++ .probe = retu_headset_probe, ++ .remove = retu_headset_remove, ++ .suspend = retu_headset_suspend, ++ .resume = retu_headset_resume, ++ .driver = { ++ .name = "retu-headset", ++ }, ++}; ++ ++static int __init retu_headset_init(void) ++{ ++ int r; ++ ++ printk(KERN_INFO "Retu/Vilma headset driver initializing\n"); ++ ++ r = platform_driver_register(&retu_headset_driver); ++ if (r < 0) ++ return r; ++ ++ return 0; ++} ++ ++static void __exit retu_headset_exit(void) ++{ ++ platform_driver_unregister(&retu_headset_driver); ++} ++ ++module_init(retu_headset_init); ++module_exit(retu_headset_exit); ++ ++MODULE_DESCRIPTION("Retu/Vilma headset detection"); ++MODULE_LICENSE("GPL"); ++MODULE_AUTHOR("Juha Yrjölä"); +diff --git a/drivers/cbus/retu-pwrbutton.c b/drivers/cbus/retu-pwrbutton.c +new file mode 100644 +index 0000000..38d7aa4 +--- /dev/null ++++ b/drivers/cbus/retu-pwrbutton.c +@@ -0,0 +1,118 @@ ++/** ++ * drivers/cbus/retu-pwrbutton.c ++ * ++ * Driver for sending retu power button event to input-layer ++ * ++ * Copyright (C) 2004 Nokia Corporation ++ * ++ * Written by Ari Saastamoinen ++ * ++ * Contact Juha Yrjölä ++ * ++ * 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 for more details. ++ * ++ * 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, MA 02111-1307 USA ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "retu.h" ++ ++#define RETU_STATUS_PWRONX (1 << 5) ++ ++#define PWRBTN_DELAY 20 ++#define PWRBTN_UP 0 ++#define PWRBTN_PRESSED 1 ++ ++static int pwrbtn_state; ++static struct input_dev *pwrbtn_dev; ++static struct timer_list pwrbtn_timer; ++ ++static void retubutton_timer_func(unsigned long arg) ++{ ++ int state; ++ ++ if (retu_read_reg(RETU_REG_STATUS) & RETU_STATUS_PWRONX) ++ state = PWRBTN_UP; ++ else ++ state = PWRBTN_PRESSED; ++ ++ if (pwrbtn_state != state) { ++ input_report_key(pwrbtn_dev, KEY_POWER, state); ++ pwrbtn_state = state; ++ } ++} ++ ++/** ++ * Interrupt function is called whenever power button key is pressed ++ * or released. ++ */ ++static void retubutton_irq(unsigned long arg) ++{ ++ retu_ack_irq(RETU_INT_PWR); ++ mod_timer(&pwrbtn_timer, jiffies + msecs_to_jiffies(PWRBTN_DELAY)); ++} ++ ++/** ++ * Init function. ++ * Allocates interrupt for power button and registers itself to input layer. ++ */ ++static int __init retubutton_init(void) ++{ ++ int irq; ++ ++ printk(KERN_INFO "Retu power button driver initialized\n"); ++ irq = RETU_INT_PWR; ++ ++ init_timer(&pwrbtn_timer); ++ pwrbtn_timer.function = retubutton_timer_func; ++ ++ if (retu_request_irq(irq, &retubutton_irq, 0, "PwrOnX") < 0) { ++ printk(KERN_ERR "%s@%s: Cannot allocate irq\n", ++ __FUNCTION__, __FILE__); ++ return -EBUSY; ++ } ++ ++ pwrbtn_dev = input_allocate_device(); ++ if (!pwrbtn_dev) ++ return -ENOMEM; ++ ++ pwrbtn_dev->evbit[0] = BIT_MASK(EV_KEY); ++ pwrbtn_dev->keybit[BIT_WORD(KEY_POWER)] = BIT_MASK(KEY_POWER); ++ pwrbtn_dev->name = "retu-pwrbutton"; ++ ++ return input_register_device(pwrbtn_dev); ++} ++ ++/** ++ * Cleanup function which is called when driver is unloaded ++ */ ++static void __exit retubutton_exit(void) ++{ ++ retu_free_irq(RETU_INT_PWR); ++ del_timer_sync(&pwrbtn_timer); ++ input_unregister_device(pwrbtn_dev); ++} ++ ++module_init(retubutton_init); ++module_exit(retubutton_exit); ++ ++MODULE_DESCRIPTION("Retu Power Button"); ++MODULE_LICENSE("GPL"); ++MODULE_AUTHOR("Ari Saastamoinen"); +diff --git a/drivers/cbus/retu-rtc.c b/drivers/cbus/retu-rtc.c +new file mode 100644 +index 0000000..1ebc33b +--- /dev/null ++++ b/drivers/cbus/retu-rtc.c +@@ -0,0 +1,477 @@ ++/** ++ * drivers/cbus/retu-rtc.c ++ * ++ * Support for Retu RTC ++ * ++ * Copyright (C) 2004, 2005 Nokia Corporation ++ * ++ * Written by Paul Mundt and ++ * Igor Stoppa ++ * ++ * The Retu RTC is essentially a partial read-only RTC that gives us Retu's ++ * idea of what time actually is. It's left as a userspace excercise to map ++ * this back to time in the real world and ensure that calibration settings ++ * are sane to compensate for any horrible drift (on account of not being able ++ * to set the clock to anything). ++ * ++ * Days are semi-writeable. Namely, Retu will only track 255 days for us ++ * consecutively, after which the counter is explicitly stuck at 255 until ++ * someone comes along and clears it with a write. In the event that no one ++ * comes along and clears it, we no longer have any idea what day it is. ++ * ++ * 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 for more details. ++ * ++ * 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, MA 02111-1307 USA ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "cbus.h" ++#include "retu.h" ++ ++static struct mutex retu_rtc_mutex; ++static u16 retu_rtc_alarm_expired; ++static u16 retu_rtc_reset_occurred; ++ ++static DECLARE_COMPLETION(retu_rtc_exited); ++static DECLARE_COMPLETION(retu_rtc_sync); ++ ++static void retu_rtc_barrier(void); ++ ++static void retu_rtc_device_release(struct device *dev) ++{ ++ complete(&retu_rtc_exited); ++} ++ ++static ssize_t retu_rtc_time_show(struct device *dev, struct device_attribute *attr, ++ char *buf) ++{ ++ u16 dsr, hmr, dsr2; ++ ++ mutex_lock(&retu_rtc_mutex); ++ ++ do { ++ u16 dummy; ++ ++ /* ++ * Not being in_interrupt() for a retu rtc IRQ, we need to ++ * read twice for consistency.. ++ */ ++ dummy = retu_read_reg(RETU_REG_RTCDSR); ++ dsr = retu_read_reg(RETU_REG_RTCDSR); ++ ++ dummy = retu_read_reg(RETU_REG_RTCHMR); ++ hmr = retu_read_reg(RETU_REG_RTCHMR); ++ ++ dummy = retu_read_reg(RETU_REG_RTCDSR); ++ dsr2 = retu_read_reg(RETU_REG_RTCDSR); ++ } while ((dsr != dsr2)); ++ ++ mutex_unlock(&retu_rtc_mutex); ++ ++ /* ++ * Format a 32-bit date-string for userspace ++ * ++ * days | hours | minutes | seconds ++ * ++ * 8 bits for each. ++ * ++ * This mostly sucks because days and seconds are tracked in RTCDSR ++ * while hours and minutes are tracked in RTCHMR. And yes, there ++ * really are no words that can describe an 8 bit day register (or ++ * rather, none that will be reprinted here). ++ */ ++ return sprintf(buf, "0x%08x\n", (((dsr >> 8) & 0xff) << 24) | ++ (((hmr >> 8) & 0x1f) << 16) | ++ ((hmr & 0x3f) << 8) | (dsr & 0x3f)); ++} ++ ++static ssize_t retu_rtc_time_store(struct device *dev, struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ mutex_lock(&retu_rtc_mutex); ++ /* ++ * Writing anything to the day counter forces it to 0 ++ * The seconds counter would be cleared by resetting the minutes counter, ++ * however this won't happen, since we are using the hh:mm counters as ++ * a set of free running counters and the day counter as a multiple ++ * overflow holder. ++ */ ++ ++ /* Reset day counter, but keep Temperature Shutdown state */ ++ retu_write_reg(RETU_REG_RTCDSR, ++ retu_read_reg(RETU_REG_RTCDSR) & (1 << 6)); ++ ++ mutex_unlock(&retu_rtc_mutex); ++ ++ return count; ++} ++ ++static DEVICE_ATTR(time, S_IRUGO | S_IWUSR, retu_rtc_time_show, ++ retu_rtc_time_store); ++ ++ ++static ssize_t retu_rtc_reset_show(struct device *dev, struct device_attribute *attr, char *buf) ++{ ++ /* ++ * Returns the status of the rtc ++ * ++ * 0: no reset has occurred or the status has been cleared ++ * 1: a reset has occurred ++ * ++ * RTC needs to be reset only when both main battery ++ * _AND_ backup battery are discharged ++ */ ++ return sprintf(buf, "%u\n", retu_rtc_reset_occurred); ++} ++ ++static void retu_rtc_do_reset(void) ++{ ++ u16 ccr1; ++ ++ ccr1 = retu_read_reg(RETU_REG_CC1); ++ /* RTC in reset */ ++ retu_write_reg(RETU_REG_CC1, ccr1 | 0x0001); ++ /* RTC in normal operating mode */ ++ retu_write_reg(RETU_REG_CC1, ccr1 & ~0x0001); ++ ++ retu_rtc_barrier(); ++ /* Disable alarm and RTC WD */ ++ retu_write_reg(RETU_REG_RTCHMAR, 0x7f3f); ++ /* Set Calibration register to default value */ ++ retu_write_reg(RETU_REG_RTCCALR, 0x00c0); ++ ++ retu_rtc_alarm_expired = 0; ++ retu_rtc_reset_occurred = 1; ++} ++ ++static ssize_t retu_rtc_reset_store(struct device *dev, struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ unsigned choice; ++ ++ if(sscanf(buf, "%u", &choice) != 1) ++ return count; ++ mutex_lock(&retu_rtc_mutex); ++ if (choice == 0) ++ retu_rtc_reset_occurred = 0; ++ else if (choice == 1) ++ retu_rtc_do_reset(); ++ mutex_unlock(&retu_rtc_mutex); ++ return count; ++} ++ ++static DEVICE_ATTR(reset, S_IRUGO | S_IWUSR, retu_rtc_reset_show, ++ retu_rtc_reset_store); ++ ++static ssize_t retu_rtc_alarm_show(struct device *dev, struct device_attribute *attr, ++ char *buf) ++{ ++ u16 chmar; ++ ssize_t retval; ++ ++ mutex_lock(&retu_rtc_mutex); ++ /* ++ * Format a 16-bit date-string for userspace ++ * ++ * hours | minutes ++ * 8 bits for each. ++ */ ++ chmar = retu_read_reg(RETU_REG_RTCHMAR); ++ /* No shifting needed, only masking unrelated bits */ ++ retval = sprintf(buf, "0x%04x\n", chmar & 0x1f3f); ++ mutex_unlock(&retu_rtc_mutex); ++ ++ return retval; ++} ++ ++static ssize_t retu_rtc_alarm_store(struct device *dev, struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ u16 chmar; ++ unsigned alrm; ++ unsigned hours; ++ unsigned minutes; ++ ++ mutex_lock(&retu_rtc_mutex); ++ ++ if(sscanf(buf, "%x", &alrm) != 1) ++ return count; ++ hours = (alrm >> 8) & 0x001f; ++ minutes = (alrm >> 0) & 0x003f; ++ if ((hours < 24 && minutes < 60) || (hours == 24 && minutes == 60)) { ++ /* ++ * OK, the time format for the alarm is valid (including the ++ * disabling values) ++ */ ++ /* Keeps the RTC watchdog status */ ++ chmar = retu_read_reg(RETU_REG_RTCHMAR) & 0x6000; ++ chmar |= alrm & 0x1f3f; /* Stores the requested alarm */ ++ retu_rtc_barrier(); ++ retu_write_reg(RETU_REG_RTCHMAR, chmar); ++ /* If the alarm is being disabled */ ++ if (hours == 24 && minutes == 60) { ++ /* disable the interrupt */ ++ retu_disable_irq(RETU_INT_RTCA); ++ retu_rtc_alarm_expired = 0; ++ } else ++ /* enable the interrupt */ ++ retu_enable_irq(RETU_INT_RTCA); ++ } ++ mutex_unlock(&retu_rtc_mutex); ++ ++ return count; ++} ++ ++static DEVICE_ATTR(alarm, S_IRUGO | S_IWUSR, retu_rtc_alarm_show, ++ retu_rtc_alarm_store); ++ ++static ssize_t retu_rtc_alarm_expired_show(struct device *dev, struct device_attribute *attr, ++ char *buf) ++{ ++ ssize_t retval; ++ ++ retval = sprintf(buf, "%u\n", retu_rtc_alarm_expired); ++ ++ return retval; ++} ++ ++static ssize_t retu_rtc_alarm_expired_store(struct device *dev, struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ retu_rtc_alarm_expired = 0; ++ ++ return count; ++} ++ ++static DEVICE_ATTR(alarm_expired, S_IRUGO | S_IWUSR, retu_rtc_alarm_expired_show, ++ retu_rtc_alarm_expired_store); ++ ++ ++static ssize_t retu_rtc_cal_show(struct device *dev, struct device_attribute *attr, ++ char *buf) ++{ ++ u16 rtccalr1; ++ ++ mutex_lock(&retu_rtc_mutex); ++ rtccalr1 = retu_read_reg(RETU_REG_RTCCALR); ++ mutex_unlock(&retu_rtc_mutex); ++ ++ /* ++ * Shows the status of the Calibration Register. ++ * ++ * Default, after power loss: 0x0000 ++ * Default, for R&D: 0x00C0 ++ * Default, for factory: 0x00?? ++ * ++ */ ++ return sprintf(buf, "0x%04x\n", rtccalr1 & 0x00ff); ++} ++ ++static ssize_t retu_rtc_cal_store(struct device *dev, struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ unsigned calibration_value; ++ ++ if (sscanf(buf, "%x", &calibration_value) != 1) ++ return count; ++ ++ mutex_lock(&retu_rtc_mutex); ++ retu_rtc_barrier(); ++ retu_write_reg(RETU_REG_RTCCALR, calibration_value & 0x00ff); ++ mutex_unlock(&retu_rtc_mutex); ++ ++ return count; ++} ++ ++static DEVICE_ATTR(cal, S_IRUGO | S_IWUSR, retu_rtc_cal_show, ++ retu_rtc_cal_store); ++ ++static struct platform_device retu_rtc_device; ++ ++static void retu_rtca_disable(void) ++{ ++ retu_disable_irq(RETU_INT_RTCA); ++ retu_rtc_alarm_expired = 1; ++ retu_rtc_barrier(); ++ retu_write_reg(RETU_REG_RTCHMAR, (24 << 8) | 60); ++} ++ ++static void retu_rtca_expired(struct work_struct *unused) ++{ ++ retu_rtca_disable(); ++ sysfs_notify(&retu_rtc_device.dev.kobj, NULL, "alarm_expired"); ++} ++ ++DECLARE_WORK(retu_rtca_work, retu_rtca_expired); ++ ++/* ++ * RTCHMR RTCHMAR RTCCAL must be accessed within 0.9 s since the seconds ++ * interrupt has been signaled in the IDR register ++ */ ++static void retu_rtcs_interrupt(unsigned long unused) ++{ ++ retu_ack_irq(RETU_INT_RTCS); ++ complete_all(&retu_rtc_sync); ++} ++ ++static void retu_rtca_interrupt(unsigned long unused) ++{ ++ retu_ack_irq(RETU_INT_RTCA); ++ schedule_work(&retu_rtca_work); ++} ++ ++static int retu_rtc_init_irq(void) ++{ ++ int ret; ++ ++ ret = retu_request_irq(RETU_INT_RTCS, retu_rtcs_interrupt, 0, "RTCS"); ++ if (ret != 0) ++ return ret; ++ /* ++ * We will take care of enabling and disabling the interrupt ++ * elsewhere, so leave it off by default.. ++ */ ++ retu_disable_irq(RETU_INT_RTCS); ++ ++ ret = retu_request_irq(RETU_INT_RTCA, retu_rtca_interrupt, 0, "RTCA"); ++ if (ret != 0) { ++ retu_free_irq(RETU_INT_RTCS); ++ return ret; ++ } ++ retu_disable_irq(RETU_INT_RTCA); ++ ++ return 0; ++} ++ ++ ++static int __devinit retu_rtc_probe(struct device *dev) ++{ ++ int r; ++ ++ retu_rtc_alarm_expired = retu_read_reg(RETU_REG_IDR) & ++ (0x1 << RETU_INT_RTCA); ++ ++ if ((r = retu_rtc_init_irq()) != 0) ++ return r; ++ ++ mutex_init(&retu_rtc_mutex); ++ ++ /* If the calibration register is zero, we've probably lost ++ * power */ ++ if (retu_read_reg(RETU_REG_RTCCALR) & 0x00ff) ++ retu_rtc_reset_occurred = 0; ++ else ++ retu_rtc_do_reset(); ++ ++ if ((r = device_create_file(dev, &dev_attr_time)) != 0) ++ return r; ++ else if ((r = device_create_file(dev, &dev_attr_reset)) != 0) ++ goto err_unregister_time; ++ else if ((r = device_create_file(dev, &dev_attr_alarm)) != 0) ++ goto err_unregister_reset; ++ else if ((r = device_create_file(dev, &dev_attr_alarm_expired)) != 0) ++ goto err_unregister_alarm; ++ else if ((r = device_create_file(dev, &dev_attr_cal)) != 0) ++ goto err_unregister_alarm_expired; ++ else ++ return r; ++ ++err_unregister_alarm_expired: ++ device_remove_file(dev, &dev_attr_alarm_expired); ++err_unregister_alarm: ++ device_remove_file(dev, &dev_attr_alarm); ++err_unregister_reset: ++ device_remove_file(dev, &dev_attr_reset); ++err_unregister_time: ++ device_remove_file(dev, &dev_attr_time); ++ return r; ++} ++ ++static int __devexit retu_rtc_remove(struct device *dev) ++{ ++ retu_disable_irq(RETU_INT_RTCS); ++ retu_free_irq(RETU_INT_RTCS); ++ retu_free_irq(RETU_INT_RTCA); ++ device_remove_file(dev, &dev_attr_cal); ++ device_remove_file(dev, &dev_attr_alarm_expired); ++ device_remove_file(dev, &dev_attr_alarm); ++ device_remove_file(dev, &dev_attr_reset); ++ device_remove_file(dev, &dev_attr_time); ++ return 0; ++} ++ ++static struct device_driver retu_rtc_driver = { ++ .name = "retu-rtc", ++ .bus = &platform_bus_type, ++ .probe = retu_rtc_probe, ++ .remove = __devexit_p(retu_rtc_remove), ++}; ++ ++static struct platform_device retu_rtc_device = { ++ .name = "retu-rtc", ++ .id = -1, ++ .dev = { ++ .release = retu_rtc_device_release, ++ }, ++}; ++ ++/* This function provides syncronization with the RTCS interrupt handler */ ++static void retu_rtc_barrier(void) ++{ ++ INIT_COMPLETION(retu_rtc_sync); ++ retu_ack_irq(RETU_INT_RTCS); ++ retu_enable_irq(RETU_INT_RTCS); ++ wait_for_completion(&retu_rtc_sync); ++ retu_disable_irq(RETU_INT_RTCS); ++} ++ ++static int __init retu_rtc_init(void) ++{ ++ int ret; ++ ++ init_completion(&retu_rtc_exited); ++ ++ if ((ret = driver_register(&retu_rtc_driver)) != 0) ++ return ret; ++ ++ if ((ret = platform_device_register(&retu_rtc_device)) != 0) ++ goto err_unregister_driver; ++ ++ return 0; ++ ++err_unregister_driver: ++ driver_unregister(&retu_rtc_driver); ++ return ret; ++} ++ ++static void __exit retu_rtc_exit(void) ++{ ++ platform_device_unregister(&retu_rtc_device); ++ driver_unregister(&retu_rtc_driver); ++ ++ wait_for_completion(&retu_rtc_exited); ++} ++ ++module_init(retu_rtc_init); ++module_exit(retu_rtc_exit); ++ ++MODULE_DESCRIPTION("Retu RTC"); ++MODULE_LICENSE("GPL"); ++MODULE_AUTHOR("Paul Mundt and Igor Stoppa"); +diff --git a/drivers/cbus/retu-user.c b/drivers/cbus/retu-user.c +new file mode 100644 +index 0000000..74a7d61 +--- /dev/null ++++ b/drivers/cbus/retu-user.c +@@ -0,0 +1,423 @@ ++/** ++ * drivers/cbus/retu-user.c ++ * ++ * Retu user space interface functions ++ * ++ * Copyright (C) 2004, 2005 Nokia Corporation ++ * ++ * Written by Mikko Ylinen ++ * ++ * 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 for more details. ++ * ++ * 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, MA 02111-1307 USA ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#include "retu.h" ++ ++#include "user_retu_tahvo.h" ++ ++/* Maximum size of IRQ node buffer/pool */ ++#define RETU_MAX_IRQ_BUF_LEN 16 ++ ++#define PFX "retu-user: " ++ ++/* Bitmap for marking the interrupt sources as having the handlers */ ++static u32 retu_irq_bits; ++ ++/* For allowing only one user process to subscribe to the retu interrupts */ ++static struct file *retu_irq_subscr = NULL; ++ ++/* For poll and IRQ passing */ ++struct retu_irq { ++ u32 id; ++ struct list_head node; ++}; ++ ++static spinlock_t retu_irqs_lock; ++static struct retu_irq *retu_irq_block; ++static LIST_HEAD(retu_irqs); ++static LIST_HEAD(retu_irqs_reserve); ++ ++/* Wait queue - used when user wants to read the device */ ++DECLARE_WAIT_QUEUE_HEAD(retu_user_waitqueue); ++ ++/* Semaphore to protect irq subscription sequence */ ++static struct mutex retu_mutex; ++ ++/* This array specifies RETU register types (read/write/toggle) */ ++static const u8 retu_access_bits[] = { ++ 1, ++ 4, ++ 3, ++ 3, ++ 1, ++ 3, ++ 3, ++ 0, ++ 3, ++ 3, ++ 3, ++ 3, ++ 3, ++ 3, ++ 3, ++ 4, ++ 4, ++ 3, ++ 0, ++ 0, ++ 0, ++ 0, ++ 1, ++ 3, ++ 3, ++ 3, ++ 3, ++ 3, ++ 3, ++ 3, ++ 3, ++ 3 ++}; ++ ++/* ++ * The handler for all RETU interrupts. ++ * ++ * arg is the interrupt source in RETU. ++ */ ++static void retu_user_irq_handler(unsigned long arg) ++{ ++ struct retu_irq *irq; ++ ++ retu_ack_irq(arg); ++ ++ spin_lock(&retu_irqs_lock); ++ if (list_empty(&retu_irqs_reserve)) { ++ spin_unlock(&retu_irqs_lock); ++ return; ++ } ++ irq = list_entry((&retu_irqs_reserve)->next, struct retu_irq, node); ++ irq->id = arg; ++ list_move_tail(&irq->node, &retu_irqs); ++ spin_unlock(&retu_irqs_lock); ++ ++ /* wake up waiting thread */ ++ wake_up(&retu_user_waitqueue); ++} ++ ++/* ++ * This routine sets up the interrupt handler and marks an interrupt source ++ * in RETU as a candidate for signal delivery to the user process. ++ */ ++static int retu_user_subscribe_to_irq(int id, struct file *filp) ++{ ++ int ret; ++ ++ mutex_lock(&retu_mutex); ++ if ((retu_irq_subscr != NULL) && (retu_irq_subscr != filp)) { ++ mutex_unlock(&retu_mutex); ++ return -EBUSY; ++ } ++ /* Store the file pointer of the first user process registering IRQs */ ++ retu_irq_subscr = filp; ++ mutex_unlock(&retu_mutex); ++ ++ if (retu_irq_bits & (1 << id)) ++ return 0; ++ ++ ret = retu_request_irq(id, retu_user_irq_handler, id, ""); ++ if (ret < 0) ++ return ret; ++ ++ /* Mark that this interrupt has a handler */ ++ retu_irq_bits |= 1 << id; ++ ++ return 0; ++} ++ ++/* ++ * Unregisters all RETU interrupt handlers. ++ */ ++static void retu_unreg_irq_handlers(void) ++{ ++ int id; ++ ++ if (!retu_irq_bits) ++ return; ++ ++ for (id = 0; id < MAX_RETU_IRQ_HANDLERS; id++) ++ if (retu_irq_bits & (1 << id)) ++ retu_free_irq(id); ++ ++ retu_irq_bits = 0; ++} ++ ++/* ++ * Write to RETU register. ++ * Returns 0 upon success, a negative error value otherwise. ++ */ ++static int retu_user_write_with_mask(u32 field, u16 value) ++{ ++ u32 mask; ++ u32 reg; ++ u_short tmp; ++ unsigned long flags; ++ ++ mask = MASK(field); ++ reg = REG(field); ++ ++ /* Detect bad mask and reg */ ++ if (mask == 0 || reg > RETU_REG_MAX || ++ retu_access_bits[reg] == READ_ONLY) { ++ printk(KERN_ERR PFX "invalid arguments (reg=%#x, mask=%#x)\n", ++ reg, mask); ++ return -EINVAL; ++ } ++ ++ /* Justify value according to mask */ ++ while (!(mask & 1)) { ++ value = value << 1; ++ mask = mask >> 1; ++ } ++ ++ spin_lock_irqsave(&retu_lock, flags); ++ if (retu_access_bits[reg] == TOGGLE) { ++ /* No need to detect previous content of register */ ++ tmp = 0; ++ } else { ++ /* Read current value of register */ ++ tmp = retu_read_reg(reg); ++ } ++ ++ /* Generate new value */ ++ tmp = (tmp & ~MASK(field)) | (value & MASK(field)); ++ /* Write data to RETU */ ++ retu_write_reg(reg, tmp); ++ spin_unlock_irqrestore(&retu_lock, flags); ++ ++ return 0; ++} ++ ++/* ++ * Read RETU register. ++ */ ++static u32 retu_user_read_with_mask(u32 field) ++{ ++ u_short value; ++ u32 mask, reg; ++ ++ mask = MASK(field); ++ reg = REG(field); ++ ++ /* Detect bad mask and reg */ ++ if (mask == 0 || reg > RETU_REG_MAX) { ++ printk(KERN_ERR PFX "invalid arguments (reg=%#x, mask=%#x)\n", ++ reg, mask); ++ return -EINVAL; ++ } ++ ++ /* Read the register */ ++ value = retu_read_reg(reg) & mask; ++ ++ /* Right justify value */ ++ while (!(mask & 1)) { ++ value = value >> 1; ++ mask = mask >> 1; ++ } ++ ++ return value; ++} ++ ++/* ++ * Close device ++ */ ++static int retu_close(struct inode *inode, struct file *filp) ++{ ++ /* Unregister all interrupts that have been registered */ ++ if (retu_irq_subscr == filp) { ++ retu_unreg_irq_handlers(); ++ retu_irq_subscr = NULL; ++ } ++ ++ return 0; ++} ++ ++/* ++ * Device control (ioctl) ++ */ ++static int retu_ioctl(struct inode *inode, struct file *filp, ++ unsigned int cmd, unsigned long arg) ++{ ++ struct retu_tahvo_write_parms par; ++ int ret; ++ ++ switch (cmd) { ++ case URT_IOCT_IRQ_SUBSCR: ++ return retu_user_subscribe_to_irq(arg, filp); ++ case RETU_IOCH_READ: ++ return retu_user_read_with_mask(arg); ++ case RETU_IOCX_WRITE: ++ ret = copy_from_user(&par, (void __user *) arg, sizeof(par)); ++ if (ret) ++ printk(KERN_ERR "copy_from_user failed: %d\n", ret); ++ par.result = retu_user_write_with_mask(par.field, par.value); ++ ret = copy_to_user((void __user *) arg, &par, sizeof(par)); ++ if (ret) ++ printk(KERN_ERR "copy_to_user failed: %d\n", ret); ++ break; ++ case RETU_IOCH_ADC_READ: ++ return retu_read_adc(arg); ++ default: ++ return -ENOIOCTLCMD; ++ } ++ return 0; ++} ++ ++/* ++ * Read from device ++ */ ++static ssize_t retu_read(struct file *filp, char *buf, size_t count, ++ loff_t * offp) ++{ ++ struct retu_irq *irq; ++ ++ u32 nr, i; ++ ++ /* read not permitted if neither filp nor anyone has registered IRQs */ ++ if (retu_irq_subscr != filp) ++ return -EPERM; ++ ++ if ((count < sizeof(u32)) || ((count % sizeof(u32)) != 0)) ++ return -EINVAL; ++ ++ nr = count / sizeof(u32); ++ ++ for (i = 0; i < nr; i++) { ++ unsigned long flags; ++ u32 irq_id; ++ int ret; ++ ++ ret = wait_event_interruptible(retu_user_waitqueue, ++ !list_empty(&retu_irqs)); ++ if (ret < 0) ++ return ret; ++ ++ spin_lock_irqsave(&retu_irqs_lock, flags); ++ irq = list_entry((&retu_irqs)->next, struct retu_irq, node); ++ irq_id = irq->id; ++ list_move(&irq->node, &retu_irqs_reserve); ++ spin_unlock_irqrestore(&retu_irqs_lock, flags); ++ ++ ret = copy_to_user(buf + i * sizeof(irq_id), &irq_id, ++ sizeof(irq_id)); ++ if (ret) ++ printk(KERN_ERR "copy_to_user failed: %d\n", ret); ++ } ++ ++ return count; ++} ++ ++/* ++ * Poll method ++ */ ++static unsigned retu_poll(struct file *filp, struct poll_table_struct *pt) ++{ ++ if (!list_empty(&retu_irqs)) ++ return POLLIN; ++ ++ poll_wait(filp, &retu_user_waitqueue, pt); ++ ++ if (!list_empty(&retu_irqs)) ++ return POLLIN; ++ else ++ return 0; ++} ++ ++static struct file_operations retu_user_fileops = { ++ .owner = THIS_MODULE, ++ .ioctl = retu_ioctl, ++ .read = retu_read, ++ .release = retu_close, ++ .poll = retu_poll ++}; ++ ++static struct miscdevice retu_device = { ++ .minor = MISC_DYNAMIC_MINOR, ++ .name = "retu", ++ .fops = &retu_user_fileops ++}; ++ ++/* ++ * Initialization ++ * ++ * @return 0 if successful, error value otherwise. ++ */ ++int retu_user_init(void) ++{ ++ struct retu_irq *irq; ++ int res, i; ++ ++ irq = kmalloc(sizeof(*irq) * RETU_MAX_IRQ_BUF_LEN, GFP_KERNEL); ++ if (irq == NULL) { ++ printk(KERN_ERR PFX "kmalloc failed\n"); ++ return -ENOMEM; ++ } ++ memset(irq, 0, sizeof(*irq) * RETU_MAX_IRQ_BUF_LEN); ++ for (i = 0; i < RETU_MAX_IRQ_BUF_LEN; i++) ++ list_add(&irq[i].node, &retu_irqs_reserve); ++ ++ retu_irq_block = irq; ++ ++ spin_lock_init(&retu_irqs_lock); ++ mutex_init(&retu_mutex); ++ ++ /* Request a misc device */ ++ res = misc_register(&retu_device); ++ if (res < 0) { ++ printk(KERN_ERR PFX "unable to register misc device for %s\n", ++ retu_device.name); ++ kfree(irq); ++ return res; ++ } ++ ++ return 0; ++} ++ ++/* ++ * Cleanup. ++ */ ++void retu_user_cleanup(void) ++{ ++ /* Unregister our misc device */ ++ misc_deregister(&retu_device); ++ /* Unregister and disable all RETU interrupts used by this module */ ++ retu_unreg_irq_handlers(); ++ kfree(retu_irq_block); ++} ++ ++MODULE_DESCRIPTION("Retu ASIC user space functions"); ++MODULE_LICENSE("GPL"); ++MODULE_AUTHOR("Mikko Ylinen"); +diff --git a/drivers/cbus/retu-wdt.c b/drivers/cbus/retu-wdt.c +new file mode 100644 +index 0000000..b7b20b7 +--- /dev/null ++++ b/drivers/cbus/retu-wdt.c +@@ -0,0 +1,202 @@ ++/** ++ * drivers/cbus/retu-wdt.c ++ * ++ * Driver for Retu watchdog ++ * ++ * Copyright (C) 2004, 2005 Nokia Corporation ++ * ++ * Written by Amit Kucheria ++ * ++ * 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 for more details. ++ * ++ * 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, MA 02111-1307 USA ++ */ ++ ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++ ++#include "cbus.h" ++#include "retu.h" ++ ++/* Watchdog timeout in seconds */ ++#define RETU_WDT_MIN_TIMER 0 ++#define RETU_WDT_DEFAULT_TIMER 32 ++#define RETU_WDT_MAX_TIMER 63 ++ ++static struct completion retu_wdt_completion; ++static DEFINE_MUTEX(retu_wdt_mutex); ++ ++/* Current period of watchdog */ ++static unsigned int period_val = RETU_WDT_DEFAULT_TIMER; ++static int counter_param = RETU_WDT_MAX_TIMER; ++ ++static int retu_modify_counter(unsigned int new) ++{ ++ int ret = 0; ++ ++ if (new < RETU_WDT_MIN_TIMER || new > RETU_WDT_MAX_TIMER) ++ return -EINVAL; ++ ++ mutex_lock(&retu_wdt_mutex); ++ ++ period_val = new; ++ retu_write_reg(RETU_REG_WATCHDOG, (u16)period_val); ++ ++ mutex_unlock(&retu_wdt_mutex); ++ return ret; ++} ++ ++static ssize_t retu_wdt_period_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ /* Show current max counter */ ++ return sprintf(buf, "%u\n", (u16)period_val); ++} ++ ++static ssize_t retu_wdt_period_store(struct device *dev, ++ struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ unsigned int new_period; ++ int ret; ++ ++ if (sscanf(buf, "%u", &new_period) != 1) { ++ printk(KERN_ALERT "retu_wdt_period_store: Invalid input\n"); ++ return -EINVAL; ++ } ++ ++ ret = retu_modify_counter(new_period); ++ if (ret < 0) ++ return ret; ++ ++ return strnlen(buf, count); ++} ++ ++static ssize_t retu_wdt_counter_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ u16 counter; ++ ++ /* Show current value in watchdog counter */ ++ counter = retu_read_reg(RETU_REG_WATCHDOG); ++ ++ /* Only the 5 LSB are important */ ++ return snprintf(buf, PAGE_SIZE, "%u\n", (counter & 0x3F)); ++} ++ ++static DEVICE_ATTR(period, S_IRUGO | S_IWUSR, retu_wdt_period_show, \ ++ retu_wdt_period_store); ++static DEVICE_ATTR(counter, S_IRUGO, retu_wdt_counter_show, NULL); ++ ++static int __devinit retu_wdt_probe(struct device *dev) ++{ ++ int ret; ++ ++ ret = device_create_file(dev, &dev_attr_period); ++ if (ret) { ++ printk(KERN_ERR "retu_wdt_probe: Error creating " ++ "sys device file: period\n"); ++ return ret; ++ } ++ ++ ret = device_create_file(dev, &dev_attr_counter); ++ if (ret) { ++ device_remove_file(dev, &dev_attr_period); ++ printk(KERN_ERR "retu_wdt_probe: Error creating " ++ "sys device file: counter\n"); ++ } ++ ++ return ret; ++} ++ ++static int __devexit retu_wdt_remove(struct device *dev) ++{ ++ device_remove_file(dev, &dev_attr_period); ++ device_remove_file(dev, &dev_attr_counter); ++ return 0; ++} ++ ++static void retu_wdt_device_release(struct device *dev) ++{ ++ complete(&retu_wdt_completion); ++} ++ ++static struct platform_device retu_wdt_device = { ++ .name = "retu-watchdog", ++ .id = -1, ++ .dev = { ++ .release = retu_wdt_device_release, ++ }, ++}; ++ ++static struct device_driver retu_wdt_driver = { ++ .name = "retu-watchdog", ++ .bus = &platform_bus_type, ++ .probe = retu_wdt_probe, ++ .remove = __devexit_p(retu_wdt_remove), ++}; ++ ++static int __init retu_wdt_init(void) ++{ ++ int ret; ++ ++ init_completion(&retu_wdt_completion); ++ ++ ret = driver_register(&retu_wdt_driver); ++ if (ret) ++ return ret; ++ ++ ret = platform_device_register(&retu_wdt_device); ++ if (ret) ++ goto exit1; ++ ++ /* passed as module parameter? */ ++ ret = retu_modify_counter(counter_param); ++ if (ret == -EINVAL) { ++ ret = retu_modify_counter(RETU_WDT_DEFAULT_TIMER); ++ printk(KERN_INFO ++ "retu_wdt_init: Intializing to default value\n"); ++ } ++ ++ printk(KERN_INFO "Retu watchdog driver initialized\n"); ++ return ret; ++ ++exit1: ++ driver_unregister(&retu_wdt_driver); ++ wait_for_completion(&retu_wdt_completion); ++ ++ return ret; ++} ++ ++static void __exit retu_wdt_exit(void) ++{ ++ platform_device_unregister(&retu_wdt_device); ++ driver_unregister(&retu_wdt_driver); ++ ++ wait_for_completion(&retu_wdt_completion); ++} ++ ++module_init(retu_wdt_init); ++module_exit(retu_wdt_exit); ++module_param(counter_param, int, 0); ++ ++MODULE_DESCRIPTION("Retu WatchDog"); ++MODULE_AUTHOR("Amit Kucheria"); ++MODULE_LICENSE("GPL"); ++ +diff --git a/drivers/cbus/retu.c b/drivers/cbus/retu.c +new file mode 100644 +index 0000000..84d7840 +--- /dev/null ++++ b/drivers/cbus/retu.c +@@ -0,0 +1,467 @@ ++/** ++ * drivers/cbus/retu.c ++ * ++ * Support functions for Retu ASIC ++ * ++ * Copyright (C) 2004, 2005 Nokia Corporation ++ * ++ * Written by Juha Yrjölä , ++ * David Weinehall , and ++ * Mikko Ylinen ++ * ++ * 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 for more details. ++ * ++ * 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, MA 02111-1307 USA ++ */ ++ ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#include ++#include ++#include ++ ++#include "cbus.h" ++#include "retu.h" ++ ++#define RETU_ID 0x01 ++#define PFX "retu: " ++ ++static int retu_initialized; ++static int retu_irq_pin; ++static int retu_is_vilma; ++ ++static struct tasklet_struct retu_tasklet; ++spinlock_t retu_lock = SPIN_LOCK_UNLOCKED; ++ ++static struct completion device_release; ++ ++struct retu_irq_handler_desc { ++ int (*func)(unsigned long); ++ unsigned long arg; ++ char name[8]; ++}; ++ ++static struct retu_irq_handler_desc retu_irq_handlers[MAX_RETU_IRQ_HANDLERS]; ++ ++/** ++ * retu_read_reg - Read a value from a register in Retu ++ * @reg: the register to read from ++ * ++ * This function returns the contents of the specified register ++ */ ++int retu_read_reg(int reg) ++{ ++ BUG_ON(!retu_initialized); ++ return cbus_read_reg(cbus_host, RETU_ID, reg); ++} ++ ++/** ++ * retu_write_reg - Write a value to a register in Retu ++ * @reg: the register to write to ++ * @reg: the value to write to the register ++ * ++ * This function writes a value to the specified register ++ */ ++void retu_write_reg(int reg, u16 val) ++{ ++ BUG_ON(!retu_initialized); ++ cbus_write_reg(cbus_host, RETU_ID, reg, val); ++} ++ ++void retu_set_clear_reg_bits(int reg, u16 set, u16 clear) ++{ ++ unsigned long flags; ++ u16 w; ++ ++ spin_lock_irqsave(&retu_lock, flags); ++ w = retu_read_reg(reg); ++ w &= ~clear; ++ w |= set; ++ retu_write_reg(reg, w); ++ spin_unlock_irqrestore(&retu_lock, flags); ++} ++ ++#define ADC_MAX_CHAN_NUMBER 13 ++ ++int retu_read_adc(int channel) ++{ ++ unsigned long flags; ++ int res; ++ ++ if (channel < 0 || channel > ADC_MAX_CHAN_NUMBER) ++ return -EINVAL; ++ ++ spin_lock_irqsave(&retu_lock, flags); ++ ++ if ((channel == 8) && retu_is_vilma) { ++ int scr = retu_read_reg(RETU_REG_ADCSCR); ++ int ch = (retu_read_reg(RETU_REG_ADCR) >> 10) & 0xf; ++ if (((scr & 0xff) != 0) && (ch != 8)) ++ retu_write_reg (RETU_REG_ADCSCR, (scr & ~0xff)); ++ } ++ ++ /* Select the channel and read result */ ++ retu_write_reg(RETU_REG_ADCR, channel << 10); ++ res = retu_read_reg(RETU_REG_ADCR) & 0x3ff; ++ ++ if (retu_is_vilma) ++ retu_write_reg(RETU_REG_ADCR, (1 << 13)); ++ ++ /* Unlock retu */ ++ spin_unlock_irqrestore(&retu_lock, flags); ++ ++ return res; ++} ++ ++ ++static u16 retu_disable_bogus_irqs(u16 mask) ++{ ++ int i; ++ ++ for (i = 0; i < MAX_RETU_IRQ_HANDLERS; i++) { ++ if (mask & (1 << i)) ++ continue; ++ if (retu_irq_handlers[i].func != NULL) ++ continue; ++ /* an IRQ was enabled but we don't have a handler for it */ ++ printk(KERN_INFO PFX "disabling bogus IRQ %d\n", i); ++ mask |= (1 << i); ++ } ++ return mask; ++} ++ ++/* ++ * Disable given RETU interrupt ++ */ ++void retu_disable_irq(int id) ++{ ++ unsigned long flags; ++ u16 mask; ++ ++ spin_lock_irqsave(&retu_lock, flags); ++ mask = retu_read_reg(RETU_REG_IMR); ++ mask |= 1 << id; ++ mask = retu_disable_bogus_irqs(mask); ++ retu_write_reg(RETU_REG_IMR, mask); ++ spin_unlock_irqrestore(&retu_lock, flags); ++} ++ ++/* ++ * Enable given RETU interrupt ++ */ ++void retu_enable_irq(int id) ++{ ++ unsigned long flags; ++ u16 mask; ++ ++ if (id == 3) { ++ printk("Enabling Retu IRQ %d\n", id); ++ dump_stack(); ++ } ++ spin_lock_irqsave(&retu_lock, flags); ++ mask = retu_read_reg(RETU_REG_IMR); ++ mask &= ~(1 << id); ++ mask = retu_disable_bogus_irqs(mask); ++ retu_write_reg(RETU_REG_IMR, mask); ++ spin_unlock_irqrestore(&retu_lock, flags); ++} ++ ++/* ++ * Acknowledge given RETU interrupt ++ */ ++void retu_ack_irq(int id) ++{ ++ retu_write_reg(RETU_REG_IDR, 1 << id); ++} ++ ++/* ++ * RETU interrupt handler. Only schedules the tasklet. ++ */ ++static irqreturn_t retu_irq_handler(int irq, void *dev_id) ++{ ++ tasklet_schedule(&retu_tasklet); ++ return IRQ_HANDLED; ++} ++ ++/* ++ * Tasklet handler ++ */ ++static void retu_tasklet_handler(unsigned long data) ++{ ++ struct retu_irq_handler_desc *hnd; ++ u16 id; ++ u16 im; ++ int i; ++ ++ for (;;) { ++ id = retu_read_reg(RETU_REG_IDR); ++ im = ~retu_read_reg(RETU_REG_IMR); ++ id &= im; ++ ++ if (!id) ++ break; ++ ++ for (i = 0; id != 0; i++, id >>= 1) { ++ if (!(id & 1)) ++ continue; ++ hnd = &retu_irq_handlers[i]; ++ if (hnd->func == NULL) { ++ /* Spurious retu interrupt - disable and ack it */ ++ printk(KERN_INFO "Spurious Retu interrupt " ++ "(id %d)\n", i); ++ retu_disable_irq(i); ++ retu_ack_irq(i); ++ continue; ++ } ++ hnd->func(hnd->arg); ++ /* ++ * Don't acknowledge the interrupt here ++ * It must be done explicitly ++ */ ++ } ++ } ++} ++ ++/* ++ * Register the handler for a given RETU interrupt source. ++ */ ++int retu_request_irq(int id, void *irq_handler, unsigned long arg, char *name) ++{ ++ struct retu_irq_handler_desc *hnd; ++ ++ if (irq_handler == NULL || id >= MAX_RETU_IRQ_HANDLERS || ++ name == NULL) { ++ printk(KERN_ERR PFX "Invalid arguments to %s\n", ++ __FUNCTION__); ++ return -EINVAL; ++ } ++ hnd = &retu_irq_handlers[id]; ++ if (hnd->func != NULL) { ++ printk(KERN_ERR PFX "IRQ %d already reserved\n", id); ++ return -EBUSY; ++ } ++ printk(KERN_INFO PFX "Registering interrupt %d for device %s\n", ++ id, name); ++ hnd->func = irq_handler; ++ hnd->arg = arg; ++ strlcpy(hnd->name, name, sizeof(hnd->name)); ++ ++ retu_ack_irq(id); ++ retu_enable_irq(id); ++ ++ return 0; ++} ++ ++/* ++ * Unregister the handler for a given RETU interrupt source. ++ */ ++void retu_free_irq(int id) ++{ ++ struct retu_irq_handler_desc *hnd; ++ ++ if (id >= MAX_RETU_IRQ_HANDLERS) { ++ printk(KERN_ERR PFX "Invalid argument to %s\n", ++ __FUNCTION__); ++ return; ++ } ++ hnd = &retu_irq_handlers[id]; ++ if (hnd->func == NULL) { ++ printk(KERN_ERR PFX "IRQ %d already freed\n", id); ++ return; ++ } ++ ++ retu_disable_irq(id); ++ hnd->func = NULL; ++} ++ ++/** ++ * retu_power_off - Shut down power to system ++ * ++ * This function puts the system in power off state ++ */ ++static void retu_power_off(void) ++{ ++ /* Ignore power button state */ ++ retu_write_reg(RETU_REG_CC1, retu_read_reg(RETU_REG_CC1) | 2); ++ /* Expire watchdog immediately */ ++ retu_write_reg(RETU_REG_WATCHDOG, 0); ++ /* Wait for poweroff*/ ++ for (;;); ++} ++ ++/** ++ * retu_probe - Probe for Retu ASIC ++ * @dev: the Retu device ++ * ++ * Probe for the Retu ASIC and allocate memory ++ * for its device-struct if found ++ */ ++static int __devinit retu_probe(struct device *dev) ++{ ++ const struct omap_em_asic_bb5_config * em_asic_config; ++ int rev, ret; ++ ++ /* Prepare tasklet */ ++ tasklet_init(&retu_tasklet, retu_tasklet_handler, 0); ++ ++ em_asic_config = omap_get_config(OMAP_TAG_EM_ASIC_BB5, ++ struct omap_em_asic_bb5_config); ++ if (em_asic_config == NULL) { ++ printk(KERN_ERR PFX "Unable to retrieve config data\n"); ++ return -ENODATA; ++ } ++ ++ retu_irq_pin = em_asic_config->retu_irq_gpio; ++ ++ if ((ret = gpio_request(retu_irq_pin, "RETU irq")) < 0) { ++ printk(KERN_ERR PFX "Unable to reserve IRQ GPIO\n"); ++ return ret; ++ } ++ ++ /* Set the pin as input */ ++ gpio_direction_input(retu_irq_pin); ++ ++ /* Rising edge triggers the IRQ */ ++ set_irq_type(gpio_to_irq(retu_irq_pin), IRQ_TYPE_EDGE_RISING); ++ ++ retu_initialized = 1; ++ ++ rev = retu_read_reg(RETU_REG_ASICR) & 0xff; ++ if (rev & (1 << 7)) ++ retu_is_vilma = 1; ++ ++ printk(KERN_INFO "%s v%d.%d found\n", retu_is_vilma ? "Vilma" : "Retu", ++ (rev >> 4) & 0x07, rev & 0x0f); ++ ++ /* Mask all RETU interrupts */ ++ retu_write_reg(RETU_REG_IMR, 0xffff); ++ ++ ret = request_irq(gpio_to_irq(retu_irq_pin), retu_irq_handler, 0, ++ "retu", 0); ++ if (ret < 0) { ++ printk(KERN_ERR PFX "Unable to register IRQ handler\n"); ++ gpio_free(retu_irq_pin); ++ return ret; ++ } ++ set_irq_wake(gpio_to_irq(retu_irq_pin), 1); ++ ++ /* Register power off function */ ++ pm_power_off = retu_power_off; ++ ++#ifdef CONFIG_CBUS_RETU_USER ++ /* Initialize user-space interface */ ++ if (retu_user_init() < 0) { ++ printk(KERN_ERR "Unable to initialize driver\n"); ++ free_irq(gpio_to_irq(retu_irq_pin), 0); ++ gpio_free(retu_irq_pin); ++ return ret; ++ } ++#endif ++ ++ return 0; ++} ++ ++static int retu_remove(struct device *dev) ++{ ++#ifdef CONFIG_CBUS_RETU_USER ++ retu_user_cleanup(); ++#endif ++ /* Mask all RETU interrupts */ ++ retu_write_reg(RETU_REG_IMR, 0xffff); ++ free_irq(gpio_to_irq(retu_irq_pin), 0); ++ gpio_free(retu_irq_pin); ++ tasklet_kill(&retu_tasklet); ++ ++ return 0; ++} ++ ++static void retu_device_release(struct device *dev) ++{ ++ complete(&device_release); ++} ++ ++static struct device_driver retu_driver = { ++ .name = "retu", ++ .bus = &platform_bus_type, ++ .probe = retu_probe, ++ .remove = retu_remove, ++}; ++ ++static struct platform_device retu_device = { ++ .name = "retu", ++ .id = -1, ++ .dev = { ++ .release = retu_device_release, ++ } ++}; ++ ++/** ++ * retu_init - initialise Retu driver ++ * ++ * Initialise the Retu driver and return 0 if everything worked ok ++ */ ++static int __init retu_init(void) ++{ ++ int ret = 0; ++ ++ printk(KERN_INFO "Retu/Vilma driver initialising\n"); ++ ++ init_completion(&device_release); ++ ++ if ((ret = driver_register(&retu_driver)) < 0) ++ return ret; ++ ++ if ((ret = platform_device_register(&retu_device)) < 0) { ++ driver_unregister(&retu_driver); ++ return ret; ++ } ++ return 0; ++} ++ ++/* ++ * Cleanup ++ */ ++static void __exit retu_exit(void) ++{ ++ platform_device_unregister(&retu_device); ++ driver_unregister(&retu_driver); ++ wait_for_completion(&device_release); ++} ++ ++EXPORT_SYMBOL(retu_request_irq); ++EXPORT_SYMBOL(retu_free_irq); ++EXPORT_SYMBOL(retu_enable_irq); ++EXPORT_SYMBOL(retu_disable_irq); ++EXPORT_SYMBOL(retu_ack_irq); ++EXPORT_SYMBOL(retu_read_reg); ++EXPORT_SYMBOL(retu_write_reg); ++ ++subsys_initcall(retu_init); ++module_exit(retu_exit); ++ ++MODULE_DESCRIPTION("Retu ASIC control"); ++MODULE_LICENSE("GPL"); ++MODULE_AUTHOR("Juha Yrjölä, David Weinehall, and Mikko Ylinen"); +diff --git a/drivers/cbus/retu.h b/drivers/cbus/retu.h +new file mode 100644 +index 0000000..c9e044c +--- /dev/null ++++ b/drivers/cbus/retu.h +@@ -0,0 +1,77 @@ ++/** ++ * drivers/cbus/retu.h ++ * ++ * Copyright (C) 2004, 2005 Nokia Corporation ++ * ++ * Written by Juha Yrjölä and ++ * David Weinehall ++ * ++ * 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 for more details. ++ * ++ * 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, MA 02111-1307 USA ++ */ ++ ++#ifndef __DRIVERS_CBUS_RETU_H ++#define __DRIVERS_CBUS_RETU_H ++ ++#include ++ ++/* Registers */ ++#define RETU_REG_ASICR 0x00 /* ASIC ID & revision */ ++#define RETU_REG_IDR 0x01 /* Interrupt ID */ ++#define RETU_REG_IMR 0x02 /* Interrupt mask */ ++#define RETU_REG_RTCDSR 0x03 /* RTC seconds register */ ++#define RETU_REG_RTCHMR 0x04 /* RTC hours and minutes register */ ++#define RETU_REG_RTCHMAR 0x05 /* RTC hours and minutes alarm and time set register */ ++#define RETU_REG_RTCCALR 0x06 /* RTC calibration register */ ++#define RETU_REG_ADCR 0x08 /* ADC result */ ++#define RETU_REG_ADCSCR 0x09 /* ADC sample ctrl */ ++#define RETU_REG_CC1 0x0d /* Common control register 1 */ ++#define RETU_REG_CC2 0x0e /* Common control register 2 */ ++#define RETU_REG_CTRL_CLR 0x0f /* Regulator clear register */ ++#define RETU_REG_CTRL_SET 0x10 /* Regulator set register */ ++#define RETU_REG_STATUS 0x16 /* Status register */ ++#define RETU_REG_WATCHDOG 0x17 /* Watchdog register */ ++#define RETU_REG_AUDTXR 0x18 /* Audio Codec Tx register */ ++#define RETU_REG_MAX 0x1f ++ ++/* Interrupt sources */ ++#define RETU_INT_PWR 0 ++#define RETU_INT_CHAR 1 ++#define RETU_INT_RTCS 2 ++#define RETU_INT_RTCM 3 ++#define RETU_INT_RTCD 4 ++#define RETU_INT_RTCA 5 ++#define RETU_INT_HOOK 6 ++#define RETU_INT_HEAD 7 ++#define RETU_INT_ADCS 8 ++ ++#define MAX_RETU_IRQ_HANDLERS 16 ++ ++int retu_read_reg(int reg); ++void retu_write_reg(int reg, u16 val); ++void retu_set_clear_reg_bits(int reg, u16 set, u16 clear); ++int retu_read_adc(int channel); ++int retu_request_irq(int id, void *irq_handler, unsigned long arg, char *name); ++void retu_free_irq(int id); ++void retu_enable_irq(int id); ++void retu_disable_irq(int id); ++void retu_ack_irq(int id); ++ ++#ifdef CONFIG_CBUS_RETU_USER ++int retu_user_init(void); ++void retu_user_cleanup(void); ++#endif ++ ++extern spinlock_t retu_lock; ++ ++#endif /* __DRIVERS_CBUS_RETU_H */ +diff --git a/drivers/cbus/tahvo-usb.c b/drivers/cbus/tahvo-usb.c +new file mode 100644 +index 0000000..d8ad836 +--- /dev/null ++++ b/drivers/cbus/tahvo-usb.c +@@ -0,0 +1,777 @@ ++/** ++ * drivers/cbus/tahvo-usb.c ++ * ++ * Tahvo USB transeiver ++ * ++ * Copyright (C) 2005-2006 Nokia Corporation ++ * ++ * Parts copied from drivers/i2c/chips/isp1301_omap.c ++ * Copyright (C) 2004 Texas Instruments ++ * Copyright (C) 2004 David Brownell ++ * ++ * Written by Juha Yrjölä , ++ * Tony Lindgren , and ++ * Timo Teräs ++ * ++ * 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 for more details. ++ * ++ * 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, MA 02111-1307 USA ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++ ++#include "cbus.h" ++#include "tahvo.h" ++ ++#define DRIVER_NAME "tahvo-usb" ++ ++#define USBR_SLAVE_CONTROL (1 << 8) ++#define USBR_VPPVIO_SW (1 << 7) ++#define USBR_SPEED (1 << 6) ++#define USBR_REGOUT (1 << 5) ++#define USBR_MASTER_SW2 (1 << 4) ++#define USBR_MASTER_SW1 (1 << 3) ++#define USBR_SLAVE_SW (1 << 2) ++#define USBR_NSUSPEND (1 << 1) ++#define USBR_SEMODE (1 << 0) ++ ++/* bits in OTG_CTRL */ ++ ++/* Bits that are controlled by OMAP OTG and are read-only */ ++#define OTG_CTRL_OMAP_MASK (OTG_PULLDOWN|OTG_PULLUP|OTG_DRV_VBUS|\ ++ OTG_PD_VBUS|OTG_PU_VBUS|OTG_PU_ID) ++/* Bits that are controlled by transceiver */ ++#define OTG_CTRL_XCVR_MASK (OTG_ASESSVLD|OTG_BSESSEND|\ ++ OTG_BSESSVLD|OTG_VBUSVLD|OTG_ID) ++/* Bits that are controlled by system */ ++#define OTG_CTRL_SYS_MASK (OTG_A_BUSREQ|OTG_A_SETB_HNPEN|OTG_B_BUSREQ|\ ++ OTG_B_HNPEN|OTG_BUSDROP) ++ ++#if defined(CONFIG_USB_OHCI_HCD) && !defined(CONFIG_USB_OTG) ++#error tahvo-otg.c does not work with OCHI yet! ++#endif ++ ++#define TAHVO_MODE_HOST 0 ++#define TAHVO_MODE_PERIPHERAL 1 ++ ++#ifdef CONFIG_USB_OTG ++#define TAHVO_MODE(tu) (tu)->tahvo_mode ++#elif defined(CONFIG_USB_GADGET_OMAP) ++#define TAHVO_MODE(tu) TAHVO_MODE_PERIPHERAL ++#else ++#define TAHVO_MODE(tu) TAHVO_MODE_HOST ++#endif ++ ++struct tahvo_usb { ++ struct platform_device *pt_dev; ++ struct otg_transceiver otg; ++ int vbus_state; ++ struct work_struct irq_work; ++ struct mutex serialize; ++#ifdef CONFIG_USB_OTG ++ int tahvo_mode; ++#endif ++}; ++static struct platform_device tahvo_usb_device; ++ ++/* ++ * --------------------------------------------------------------------------- ++ * OTG related functions ++ * ++ * These shoud be separated into omap-otg.c driver module, as they are used ++ * by various transceivers. These functions are needed in the UDC-only case ++ * as well. These functions are copied from GPL isp1301_omap.c ++ * --------------------------------------------------------------------------- ++ */ ++static struct platform_device *tahvo_otg_dev; ++ ++static irqreturn_t omap_otg_irq(int irq, void *arg) ++{ ++ struct platform_device *otg_dev = (struct platform_device *) arg; ++ struct tahvo_usb *tu = (struct tahvo_usb *) otg_dev->dev.driver_data; ++ u16 otg_irq; ++ ++ otg_irq = omap_readw(OTG_IRQ_SRC); ++ if (otg_irq & OPRT_CHG) { ++ omap_writew(OPRT_CHG, OTG_IRQ_SRC); ++ } else if (otg_irq & B_SRP_TMROUT) { ++ omap_writew(B_SRP_TMROUT, OTG_IRQ_SRC); ++ } else if (otg_irq & B_HNP_FAIL) { ++ omap_writew(B_HNP_FAIL, OTG_IRQ_SRC); ++ } else if (otg_irq & A_SRP_DETECT) { ++ omap_writew(A_SRP_DETECT, OTG_IRQ_SRC); ++ } else if (otg_irq & A_REQ_TMROUT) { ++ omap_writew(A_REQ_TMROUT, OTG_IRQ_SRC); ++ } else if (otg_irq & A_VBUS_ERR) { ++ omap_writew(A_VBUS_ERR, OTG_IRQ_SRC); ++ } else if (otg_irq & DRIVER_SWITCH) { ++ if ((!(omap_readl(OTG_CTRL) & OTG_DRIVER_SEL)) && ++ tu->otg.host && tu->otg.state == OTG_STATE_A_HOST) { ++ /* role is host */ ++ usb_bus_start_enum(tu->otg.host, ++ tu->otg.host->otg_port); ++ } ++ omap_writew(DRIVER_SWITCH, OTG_IRQ_SRC); ++ } else ++ return IRQ_NONE; ++ ++ return IRQ_HANDLED; ++ ++} ++ ++static int omap_otg_init(void) ++{ ++ u32 l; ++ ++#ifdef CONFIG_USB_OTG ++ if (!tahvo_otg_dev) { ++ printk("tahvo-usb: no tahvo_otg_dev\n"); ++ return -ENODEV; ++ } ++#endif ++ ++ l = omap_readl(OTG_SYSCON_1); ++ l &= ~OTG_IDLE_EN; ++ omap_writel(l, OTG_SYSCON_1); ++ udelay(100); ++ ++ /* some of these values are board-specific... */ ++ l = omap_readl(OTG_SYSCON_2); ++ l |= OTG_EN ++ /* for B-device: */ ++ | SRP_GPDATA /* 9msec Bdev D+ pulse */ ++ | SRP_GPDVBUS /* discharge after VBUS pulse */ ++ // | (3 << 24) /* 2msec VBUS pulse */ ++ /* for A-device: */ ++ | (0 << 20) /* 200ms nominal A_WAIT_VRISE timer */ ++ | SRP_DPW /* detect 167+ns SRP pulses */ ++ | SRP_DATA | SRP_VBUS; /* accept both kinds of SRP pulse */ ++ omap_writel(l, OTG_SYSCON_2); ++ ++ omap_writew(DRIVER_SWITCH | OPRT_CHG ++ | B_SRP_TMROUT | B_HNP_FAIL ++ | A_VBUS_ERR | A_SRP_DETECT | A_REQ_TMROUT, ++ OTG_IRQ_EN); ++ l = omap_readl(OTG_SYSCON_2); ++ l |= OTG_EN; ++ omap_writel(l, OTG_SYSCON_2); ++ ++ return 0; ++} ++ ++static int omap_otg_probe(struct device *dev) ++{ ++ int ret; ++ ++ tahvo_otg_dev = to_platform_device(dev); ++ ret = omap_otg_init(); ++ if (ret != 0) { ++ printk(KERN_ERR "tahvo-usb: omap_otg_init failed\n"); ++ return ret; ++ } ++ ++ return request_irq(tahvo_otg_dev->resource[1].start, ++ omap_otg_irq, IRQF_DISABLED, DRIVER_NAME, ++ &tahvo_usb_device); ++} ++ ++static int omap_otg_remove(struct device *dev) ++{ ++ free_irq(tahvo_otg_dev->resource[1].start, &tahvo_usb_device); ++ tahvo_otg_dev = NULL; ++ ++ return 0; ++} ++ ++struct device_driver omap_otg_driver = { ++ .name = "omap_otg", ++ .bus = &platform_bus_type, ++ .probe = omap_otg_probe, ++ .remove = omap_otg_remove, ++}; ++ ++/* ++ * --------------------------------------------------------------------------- ++ * Tahvo related functions ++ * These are Nokia proprietary code, except for the OTG register settings, ++ * which are copied from isp1301.c ++ * --------------------------------------------------------------------------- ++ */ ++static ssize_t vbus_state_show(struct device *device, ++ struct device_attribute *attr, char *buf) ++{ ++ struct tahvo_usb *tu = (struct tahvo_usb*) device->driver_data; ++ return sprintf(buf, "%d\n", tu->vbus_state); ++} ++static DEVICE_ATTR(vbus_state, 0444, vbus_state_show, NULL); ++ ++int vbus_active = 0; ++ ++#if 0 ++ ++static int host_suspend(struct tahvo_usb *tu) ++{ ++ struct device *dev; ++ ++ if (!tu->otg.host) ++ return -ENODEV; ++ ++ /* Currently ASSUMES only the OTG port matters; ++ * other ports could be active... ++ */ ++ dev = tu->otg.host->controller; ++ return dev->driver->suspend(dev, PMSG_SUSPEND); ++} ++ ++static int host_resume(struct tahvo_usb *tu) ++{ ++ struct device *dev; ++ ++ if (!tu->otg.host) ++ return -ENODEV; ++ ++ dev = tu->otg.host->controller; ++ return dev->driver->resume(dev); ++} ++ ++#else ++ ++static int host_suspend(struct tahvo_usb *tu) ++{ ++ return 0; ++} ++ ++static int host_resume(struct tahvo_usb *tu) ++{ ++ return 0; ++} ++ ++#endif ++ ++static void check_vbus_state(struct tahvo_usb *tu) ++{ ++ int reg, prev_state; ++ ++ reg = tahvo_read_reg(TAHVO_REG_IDSR); ++ if (reg & 0x01) { ++ u32 l; ++ ++ vbus_active = 1; ++ switch (tu->otg.state) { ++ case OTG_STATE_B_IDLE: ++ /* Enable the gadget driver */ ++ if (tu->otg.gadget) ++ usb_gadget_vbus_connect(tu->otg.gadget); ++ /* Set B-session valid and not B-sessio ended to indicate ++ * Vbus to be ok. */ ++ l = omap_readl(OTG_CTRL); ++ l &= ~OTG_BSESSEND; ++ l |= OTG_BSESSVLD; ++ omap_writel(l, OTG_CTRL); ++ ++ tu->otg.state = OTG_STATE_B_PERIPHERAL; ++ break; ++ case OTG_STATE_A_IDLE: ++ /* Session is now valid assuming the USB hub is driving Vbus */ ++ tu->otg.state = OTG_STATE_A_HOST; ++ host_resume(tu); ++ break; ++ default: ++ break; ++ } ++ printk("USB cable connected\n"); ++ } else { ++ switch (tu->otg.state) { ++ case OTG_STATE_B_PERIPHERAL: ++ if (tu->otg.gadget) ++ usb_gadget_vbus_disconnect(tu->otg.gadget); ++ tu->otg.state = OTG_STATE_B_IDLE; ++ break; ++ case OTG_STATE_A_HOST: ++ tu->otg.state = OTG_STATE_A_IDLE; ++ break; ++ default: ++ break; ++ } ++ printk("USB cable disconnected\n"); ++ vbus_active = 0; ++ } ++ ++ prev_state = tu->vbus_state; ++ tu->vbus_state = reg & 0x01; ++ if (prev_state != tu->vbus_state) ++ sysfs_notify(&tu->pt_dev->dev.kobj, NULL, "vbus_state"); ++} ++ ++static void tahvo_usb_become_host(struct tahvo_usb *tu) ++{ ++ u32 l; ++ ++ /* Clear system and transceiver controlled bits ++ * also mark the A-session is always valid */ ++ omap_otg_init(); ++ ++ l = omap_readl(OTG_CTRL); ++ l &= ~(OTG_CTRL_XCVR_MASK | OTG_CTRL_SYS_MASK); ++ l |= OTG_ASESSVLD; ++ omap_writel(l, OTG_CTRL); ++ ++ /* Power up the transceiver in USB host mode */ ++ tahvo_write_reg(TAHVO_REG_USBR, USBR_REGOUT | USBR_NSUSPEND | ++ USBR_MASTER_SW2 | USBR_MASTER_SW1); ++ tu->otg.state = OTG_STATE_A_IDLE; ++ ++ check_vbus_state(tu); ++} ++ ++static void tahvo_usb_stop_host(struct tahvo_usb *tu) ++{ ++ host_suspend(tu); ++ tu->otg.state = OTG_STATE_A_IDLE; ++} ++ ++static void tahvo_usb_become_peripheral(struct tahvo_usb *tu) ++{ ++ u32 l; ++ ++ /* Clear system and transceiver controlled bits ++ * and enable ID to mark peripheral mode and ++ * BSESSEND to mark no Vbus */ ++ omap_otg_init(); ++ l = omap_readl(OTG_CTRL); ++ l &= ~(OTG_CTRL_XCVR_MASK | OTG_CTRL_SYS_MASK | OTG_BSESSVLD); ++ l |= OTG_ID | OTG_BSESSEND; ++ omap_writel(l, OTG_CTRL); ++ ++ /* Power up transceiver and set it in USB perhiperal mode */ ++ tahvo_write_reg(TAHVO_REG_USBR, USBR_SLAVE_CONTROL | USBR_REGOUT | USBR_NSUSPEND | USBR_SLAVE_SW); ++ tu->otg.state = OTG_STATE_B_IDLE; ++ ++ check_vbus_state(tu); ++} ++ ++static void tahvo_usb_stop_peripheral(struct tahvo_usb *tu) ++{ ++ u32 l; ++ ++ l = omap_readl(OTG_CTRL); ++ l &= ~OTG_BSESSVLD; ++ l |= OTG_BSESSEND; ++ omap_writel(l, OTG_CTRL); ++ ++ if (tu->otg.gadget) ++ usb_gadget_vbus_disconnect(tu->otg.gadget); ++ tu->otg.state = OTG_STATE_B_IDLE; ++ ++} ++ ++static void tahvo_usb_power_off(struct tahvo_usb *tu) ++{ ++ u32 l; ++ int id; ++ ++ /* Disable gadget controller if any */ ++ if (tu->otg.gadget) ++ usb_gadget_vbus_disconnect(tu->otg.gadget); ++ ++ host_suspend(tu); ++ ++ /* Disable OTG and interrupts */ ++ if (TAHVO_MODE(tu) == TAHVO_MODE_PERIPHERAL) ++ id = OTG_ID; ++ else ++ id = 0; ++ l = omap_readl(OTG_CTRL); ++ l &= ~(OTG_CTRL_XCVR_MASK | OTG_CTRL_SYS_MASK | OTG_BSESSVLD); ++ l |= id | OTG_BSESSEND; ++ omap_writel(l, OTG_CTRL); ++ omap_writew(0, OTG_IRQ_EN); ++ ++ l = omap_readl(OTG_SYSCON_2); ++ l &= ~OTG_EN; ++ omap_writel(l, OTG_SYSCON_2); ++ ++ l = omap_readl(OTG_SYSCON_1); ++ l |= OTG_IDLE_EN; ++ omap_writel(l, OTG_SYSCON_1); ++ ++ /* Power off transceiver */ ++ tahvo_write_reg(TAHVO_REG_USBR, 0); ++ tu->otg.state = OTG_STATE_UNDEFINED; ++} ++ ++ ++static int tahvo_usb_set_power(struct otg_transceiver *dev, unsigned mA) ++{ ++ struct tahvo_usb *tu = container_of(dev, struct tahvo_usb, otg); ++ ++ dev_dbg(&tu->pt_dev->dev, "set_power %d mA\n", mA); ++ ++ if (dev->state == OTG_STATE_B_PERIPHERAL) { ++ /* REVISIT: Can Tahvo charge battery from VBUS? */ ++ } ++ return 0; ++} ++ ++static int tahvo_usb_set_suspend(struct otg_transceiver *dev, int suspend) ++{ ++ struct tahvo_usb *tu = container_of(dev, struct tahvo_usb, otg); ++ u16 w; ++ ++ dev_dbg(&tu->pt_dev->dev, "set_suspend\n"); ++ ++ w = tahvo_read_reg(TAHVO_REG_USBR); ++ if (suspend) ++ w &= ~USBR_NSUSPEND; ++ else ++ w |= USBR_NSUSPEND; ++ tahvo_write_reg(TAHVO_REG_USBR, w); ++ ++ return 0; ++} ++ ++static int tahvo_usb_start_srp(struct otg_transceiver *dev) ++{ ++ struct tahvo_usb *tu = container_of(dev, struct tahvo_usb, otg); ++ u32 otg_ctrl; ++ ++ dev_dbg(&tu->pt_dev->dev, "start_srp\n"); ++ ++ if (!dev || tu->otg.state != OTG_STATE_B_IDLE) ++ return -ENODEV; ++ ++ otg_ctrl = omap_readl(OTG_CTRL); ++ if (!(otg_ctrl & OTG_BSESSEND)) ++ return -EINVAL; ++ ++ otg_ctrl |= OTG_B_BUSREQ; ++ otg_ctrl &= ~OTG_A_BUSREQ & OTG_CTRL_SYS_MASK; ++ omap_writel(otg_ctrl, OTG_CTRL); ++ tu->otg.state = OTG_STATE_B_SRP_INIT; ++ ++ return 0; ++} ++ ++static int tahvo_usb_start_hnp(struct otg_transceiver *otg) ++{ ++ struct tahvo_usb *tu = container_of(otg, struct tahvo_usb, otg); ++ ++ dev_dbg(&tu->pt_dev->dev, "start_hnp\n"); ++#ifdef CONFIG_USB_OTG ++ /* REVISIT: Add this for OTG */ ++#endif ++ return -EINVAL; ++} ++ ++static int tahvo_usb_set_host(struct otg_transceiver *otg, struct usb_bus *host) ++{ ++ struct tahvo_usb *tu = container_of(otg, struct tahvo_usb, otg); ++ u32 l; ++ ++ dev_dbg(&tu->pt_dev->dev, "set_host %p\n", host); ++ ++ if (otg == NULL) ++ return -ENODEV; ++ ++#if defined(CONFIG_USB_OTG) || !defined(CONFIG_USB_GADGET_OMAP) ++ ++ mutex_lock(&tu->serialize); ++ ++ if (host == NULL) { ++ if (TAHVO_MODE(tu) == TAHVO_MODE_HOST) ++ tahvo_usb_power_off(tu); ++ tu->otg.host = NULL; ++ mutex_unlock(&tu->serialize); ++ return 0; ++ } ++ ++ l = omap_readl(OTG_SYSCON_1); ++ l &= ~(OTG_IDLE_EN | HST_IDLE_EN | DEV_IDLE_EN); ++ omap_writel(l, OTG_SYSCON_1); ++ ++ if (TAHVO_MODE(tu) == TAHVO_MODE_HOST) { ++ tu->otg.host = NULL; ++ tahvo_usb_become_host(tu); ++ } else ++ host_suspend(tu); ++ ++ tu->otg.host = host; ++ ++ mutex_unlock(&tu->serialize); ++#else ++ /* No host mode configured, so do not allow host controlled to be set */ ++ return -EINVAL; ++#endif ++ ++ return 0; ++} ++ ++static int tahvo_usb_set_peripheral(struct otg_transceiver *otg, struct usb_gadget *gadget) ++{ ++ struct tahvo_usb *tu = container_of(otg, struct tahvo_usb, otg); ++ ++ dev_dbg(&tu->pt_dev->dev, "set_peripheral %p\n", gadget); ++ ++ if (!otg) ++ return -ENODEV; ++ ++#if defined(CONFIG_USB_OTG) || defined(CONFIG_USB_GADGET_OMAP) ++ ++ mutex_lock(&tu->serialize); ++ ++ if (!gadget) { ++ if (TAHVO_MODE(tu) == TAHVO_MODE_PERIPHERAL) ++ tahvo_usb_power_off(tu); ++ tu->otg.gadget = NULL; ++ mutex_unlock(&tu->serialize); ++ return 0; ++ } ++ ++ tu->otg.gadget = gadget; ++ if (TAHVO_MODE(tu) == TAHVO_MODE_PERIPHERAL) ++ tahvo_usb_become_peripheral(tu); ++ ++ mutex_unlock(&tu->serialize); ++#else ++ /* No gadget mode configured, so do not allow host controlled to be set */ ++ return -EINVAL; ++#endif ++ ++ return 0; ++} ++ ++static void tahvo_usb_irq_work(struct work_struct *work) ++{ ++ struct tahvo_usb *tu = container_of(work, struct tahvo_usb, irq_work); ++ ++ mutex_lock(&tu->serialize); ++ check_vbus_state(tu); ++ mutex_unlock(&tu->serialize); ++} ++ ++static void tahvo_usb_vbus_interrupt(unsigned long arg) ++{ ++ struct tahvo_usb *tu = (struct tahvo_usb *) arg; ++ ++ tahvo_ack_irq(TAHVO_INT_VBUSON); ++ /* Seems we need this to acknowledge the interrupt */ ++ tahvo_read_reg(TAHVO_REG_IDSR); ++ schedule_work(&tu->irq_work); ++} ++ ++#ifdef CONFIG_USB_OTG ++static ssize_t otg_mode_show(struct device *device, ++ struct device_attribute *attr, char *buf) ++{ ++ struct tahvo_usb *tu = (struct tahvo_usb*) device->driver_data; ++ switch (tu->tahvo_mode) { ++ case TAHVO_MODE_HOST: ++ return sprintf(buf, "host\n"); ++ case TAHVO_MODE_PERIPHERAL: ++ return sprintf(buf, "peripheral\n"); ++ } ++ return sprintf(buf, "unknown\n"); ++} ++ ++static ssize_t otg_mode_store(struct device *device, ++ struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ struct tahvo_usb *tu = (struct tahvo_usb*) device->driver_data; ++ int r; ++ ++ r = strlen(buf); ++ mutex_lock(&tu->serialize); ++ if (strncmp(buf, "host", 4) == 0) { ++ if (tu->tahvo_mode == TAHVO_MODE_PERIPHERAL) ++ tahvo_usb_stop_peripheral(tu); ++ tu->tahvo_mode = TAHVO_MODE_HOST; ++ if (tu->otg.host) { ++ printk(KERN_INFO "Selected HOST mode: host controller present.\n"); ++ tahvo_usb_become_host(tu); ++ } else { ++ printk(KERN_INFO "Selected HOST mode: no host controller, powering off.\n"); ++ tahvo_usb_power_off(tu); ++ } ++ } else if (strncmp(buf, "peripheral", 10) == 0) { ++ if (tu->tahvo_mode == TAHVO_MODE_HOST) ++ tahvo_usb_stop_host(tu); ++ tu->tahvo_mode = TAHVO_MODE_PERIPHERAL; ++ if (tu->otg.gadget) { ++ printk(KERN_INFO "Selected PERIPHERAL mode: gadget driver present.\n"); ++ tahvo_usb_become_peripheral(tu); ++ } else { ++ printk(KERN_INFO "Selected PERIPHERAL mode: no gadget driver, powering off.\n"); ++ tahvo_usb_power_off(tu); ++ } ++ } else ++ r = -EINVAL; ++ ++ mutex_unlock(&tu->serialize); ++ return r; ++} ++ ++static DEVICE_ATTR(otg_mode, 0644, otg_mode_show, otg_mode_store); ++#endif ++ ++static int tahvo_usb_probe(struct device *dev) ++{ ++ struct tahvo_usb *tu; ++ int ret; ++ ++ dev_dbg(dev, "probe\n"); ++ ++ /* Create driver data */ ++ tu = kmalloc(sizeof(*tu), GFP_KERNEL); ++ if (!tu) ++ return -ENOMEM; ++ memset(tu, 0, sizeof(*tu)); ++ tu->pt_dev = container_of(dev, struct platform_device, dev); ++#ifdef CONFIG_USB_OTG ++ /* Default mode */ ++#ifdef CONFIG_CBUS_TAHVO_USB_HOST_BY_DEFAULT ++ tu->tahvo_mode = TAHVO_MODE_HOST; ++#else ++ tu->tahvo_mode = TAHVO_MODE_PERIPHERAL; ++#endif ++#endif ++ ++ INIT_WORK(&tu->irq_work, tahvo_usb_irq_work); ++ mutex_init(&tu->serialize); ++ ++ /* Set initial state, so that we generate kevents only on ++ * state changes */ ++ tu->vbus_state = tahvo_read_reg(TAHVO_REG_IDSR) & 0x01; ++ ++ /* We cannot enable interrupt until omap_udc is initialized */ ++ ret = tahvo_request_irq(TAHVO_INT_VBUSON, tahvo_usb_vbus_interrupt, ++ (unsigned long) tu, "vbus_interrupt"); ++ if (ret != 0) { ++ kfree(tu); ++ printk(KERN_ERR "Could not register Tahvo interrupt for VBUS\n"); ++ return ret; ++ } ++ ++ /* Attributes */ ++ ret = device_create_file(dev, &dev_attr_vbus_state); ++#ifdef CONFIG_USB_OTG ++ ret |= device_create_file(dev, &dev_attr_otg_mode); ++#endif ++ if (ret) ++ printk(KERN_ERR "attribute creation failed: %d\n", ret); ++ ++ /* Create OTG interface */ ++ tahvo_usb_power_off(tu); ++ tu->otg.state = OTG_STATE_UNDEFINED; ++ tu->otg.label = DRIVER_NAME; ++ tu->otg.set_host = tahvo_usb_set_host; ++ tu->otg.set_peripheral = tahvo_usb_set_peripheral; ++ tu->otg.set_power = tahvo_usb_set_power; ++ tu->otg.set_suspend = tahvo_usb_set_suspend; ++ tu->otg.start_srp = tahvo_usb_start_srp; ++ tu->otg.start_hnp = tahvo_usb_start_hnp; ++ ++ ret = otg_set_transceiver(&tu->otg); ++ if (ret < 0) { ++ printk(KERN_ERR "Cannot register USB transceiver\n"); ++ kfree(tu); ++ tahvo_free_irq(TAHVO_INT_VBUSON); ++ return ret; ++ } ++ ++ dev->driver_data = tu; ++ ++ /* Act upon current vbus state once at startup. A vbus state irq may or ++ * may not be generated in addition to this. */ ++ schedule_work(&tu->irq_work); ++ return 0; ++} ++ ++static int tahvo_usb_remove(struct device *dev) ++{ ++ dev_dbg(dev, "remove\n"); ++ ++ tahvo_free_irq(TAHVO_INT_VBUSON); ++ flush_scheduled_work(); ++ otg_set_transceiver(0); ++ device_remove_file(dev, &dev_attr_vbus_state); ++#ifdef CONFIG_USB_OTG ++ device_remove_file(dev, &dev_attr_otg_mode); ++#endif ++ return 0; ++} ++ ++static struct device_driver tahvo_usb_driver = { ++ .name = "tahvo-usb", ++ .bus = &platform_bus_type, ++ .probe = tahvo_usb_probe, ++ .remove = tahvo_usb_remove, ++}; ++ ++static struct platform_device tahvo_usb_device = { ++ .name = "tahvo-usb", ++ .id = -1, ++}; ++ ++static int __init tahvo_usb_init(void) ++{ ++ int ret = 0; ++ ++ printk(KERN_INFO "Tahvo USB transceiver driver initializing\n"); ++ ret = driver_register(&tahvo_usb_driver); ++ if (ret) ++ return ret; ++ ret = platform_device_register(&tahvo_usb_device); ++ if (ret < 0) { ++ driver_unregister(&tahvo_usb_driver); ++ return ret; ++ } ++ ret = driver_register(&omap_otg_driver); ++ if (ret) { ++ platform_device_unregister(&tahvo_usb_device); ++ driver_unregister(&tahvo_usb_driver); ++ return ret; ++ } ++ return 0; ++} ++ ++subsys_initcall(tahvo_usb_init); ++ ++static void __exit tahvo_usb_exit(void) ++{ ++ driver_unregister(&omap_otg_driver); ++ platform_device_unregister(&tahvo_usb_device); ++ driver_unregister(&tahvo_usb_driver); ++} ++module_exit(tahvo_usb_exit); ++ ++MODULE_DESCRIPTION("Tahvo USB OTG Transceiver Driver"); ++MODULE_LICENSE("GPL"); ++MODULE_AUTHOR("Juha Yrjölä, Tony Lindgren, and Timo Teräs"); +diff --git a/drivers/cbus/tahvo-user.c b/drivers/cbus/tahvo-user.c +new file mode 100644 +index 0000000..873d648 +--- /dev/null ++++ b/drivers/cbus/tahvo-user.c +@@ -0,0 +1,405 @@ ++/** ++ * drivers/cbus/tahvo-user.c ++ * ++ * Tahvo user space interface functions ++ * ++ * Copyright (C) 2004, 2005 Nokia Corporation ++ * ++ * Written by Mikko Ylinen ++ * ++ * 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 for more details. ++ * ++ * 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, MA 02111-1307 USA ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#include "tahvo.h" ++ ++#include "user_retu_tahvo.h" ++ ++/* Maximum size of IRQ node buffer/pool */ ++#define TAHVO_MAX_IRQ_BUF_LEN 16 ++ ++#define PFX "tahvo-user: " ++ ++/* Bitmap for marking the interrupt sources as having the handlers */ ++static u32 tahvo_irq_bits; ++ ++/* For allowing only one user process to subscribe to the tahvo interrupts */ ++static struct file *tahvo_irq_subscr = NULL; ++ ++/* For poll and IRQ passing */ ++struct tahvo_irq { ++ u32 id; ++ struct list_head node; ++}; ++ ++static spinlock_t tahvo_irqs_lock; ++static struct tahvo_irq *tahvo_irq_block; ++static LIST_HEAD(tahvo_irqs); ++static LIST_HEAD(tahvo_irqs_reserve); ++ ++/* Wait queue - used when user wants to read the device */ ++DECLARE_WAIT_QUEUE_HEAD(tahvo_user_waitqueue); ++ ++/* Semaphore to protect irq subscription sequence */ ++static struct mutex tahvo_mutex; ++ ++/* This array specifies TAHVO register types (read/write/toggle) */ ++static const u8 tahvo_access_bits[] = { ++ 1, ++ 4, ++ 1, ++ 3, ++ 3, ++ 3, ++ 3, ++ 3, ++ 3, ++ 3, ++ 3, ++ 3, ++ 3, ++ 1 ++}; ++ ++/* ++ * The handler for all TAHVO interrupts. ++ * ++ * arg is the interrupt source in TAHVO. ++ */ ++static void tahvo_user_irq_handler(unsigned long arg) ++{ ++ struct tahvo_irq *irq; ++ ++ /* user has to re-enable the interrupt once ready ++ * for receiving them again */ ++ tahvo_disable_irq(arg); ++ tahvo_ack_irq(arg); ++ ++ spin_lock(&tahvo_irqs_lock); ++ if (list_empty(&tahvo_irqs_reserve)) { ++ spin_unlock(&tahvo_irqs_lock); ++ return; ++ } ++ irq = list_entry((&tahvo_irqs_reserve)->next, struct tahvo_irq, node); ++ irq->id = arg; ++ list_move_tail(&irq->node, &tahvo_irqs); ++ spin_unlock(&tahvo_irqs_lock); ++ ++ /* wake up waiting thread */ ++ wake_up(&tahvo_user_waitqueue); ++} ++ ++/* ++ * This routine sets up the interrupt handler and marks an interrupt source ++ * in TAHVO as a candidate for signal delivery to the user process. ++ */ ++static int tahvo_user_subscribe_to_irq(int id, struct file *filp) ++{ ++ int ret; ++ ++ mutex_lock(&tahvo_mutex); ++ if ((tahvo_irq_subscr != NULL) && (tahvo_irq_subscr != filp)) { ++ mutex_unlock(&tahvo_mutex); ++ return -EBUSY; ++ } ++ /* Store the file pointer of the first user process registering IRQs */ ++ tahvo_irq_subscr = filp; ++ mutex_unlock(&tahvo_mutex); ++ ++ if (tahvo_irq_bits & (1 << id)) ++ return 0; ++ ++ ret = tahvo_request_irq(id, tahvo_user_irq_handler, id, ""); ++ if (ret < 0) ++ return ret; ++ ++ /* Mark that this interrupt has a handler */ ++ tahvo_irq_bits |= 1 << id; ++ ++ return 0; ++} ++ ++/* ++ * Unregister all TAHVO interrupt handlers ++ */ ++static void tahvo_unreg_irq_handlers(void) ++{ ++ int id; ++ ++ if (!tahvo_irq_bits) ++ return; ++ ++ for (id = 0; id < MAX_TAHVO_IRQ_HANDLERS; id++) ++ if (tahvo_irq_bits & (1 << id)) ++ tahvo_free_irq(id); ++ ++ tahvo_irq_bits = 0; ++} ++ ++/* ++ * Write to TAHVO register. ++ * Returns 0 upon success, a negative error value otherwise. ++ */ ++static int tahvo_user_write_with_mask(u32 field, u16 value) ++{ ++ u32 mask; ++ u32 reg; ++ u_short tmp; ++ unsigned long flags; ++ ++ mask = MASK(field); ++ reg = REG(field); ++ ++ /* Detect bad mask and reg */ ++ if (mask == 0 || reg > TAHVO_REG_MAX || ++ tahvo_access_bits[reg] == READ_ONLY) { ++ printk(KERN_ERR PFX "invalid arguments (reg=%#x, mask=%#x)\n", ++ reg, mask); ++ return -EINVAL; ++ } ++ ++ /* Justify value according to mask */ ++ while (!(mask & 1)) { ++ value = value << 1; ++ mask = mask >> 1; ++ } ++ ++ spin_lock_irqsave(&tahvo_lock, flags); ++ if (tahvo_access_bits[reg] == TOGGLE) { ++ /* No need to detect previous content of register */ ++ tmp = 0; ++ } else { ++ /* Read current value of register */ ++ tmp = tahvo_read_reg(reg); ++ } ++ /* Generate a new value */ ++ tmp = (tmp & ~MASK(field)) | (value & MASK(field)); ++ /* Write data to TAHVO */ ++ tahvo_write_reg(reg, tmp); ++ spin_unlock_irqrestore(&tahvo_lock, flags); ++ ++ return 0; ++} ++ ++/* ++ * Read TAHVO register. ++ */ ++static u32 tahvo_user_read_with_mask(u32 field) ++{ ++ u_short value; ++ u32 mask, reg; ++ ++ mask = MASK(field); ++ reg = REG(field); ++ ++ /* Detect bad mask and reg */ ++ if (mask == 0 || reg > TAHVO_REG_MAX) { ++ printk(KERN_ERR PFX "invalid arguments (reg=%#x, mask=%#x)\n", ++ reg, mask); ++ return -EINVAL; ++ } ++ ++ /* Read the register */ ++ value = tahvo_read_reg(reg) & mask; ++ ++ /* Right justify value */ ++ while (!(mask & 1)) { ++ value = value >> 1; ++ mask = mask >> 1; ++ } ++ ++ return value; ++} ++ ++/* ++ * Close device ++ */ ++static int tahvo_close(struct inode *inode, struct file *filp) ++{ ++ /* Unregister all interrupts that have been registered */ ++ if (tahvo_irq_subscr == filp) { ++ tahvo_unreg_irq_handlers(); ++ tahvo_irq_subscr = NULL; ++ } ++ ++ return 0; ++} ++ ++/* ++ * Device control (ioctl) ++ */ ++static int tahvo_ioctl(struct inode *inode, struct file *filp, ++ unsigned int cmd, unsigned long arg) ++{ ++ struct retu_tahvo_write_parms par; ++ int ret; ++ ++ switch (cmd) { ++ case URT_IOCT_IRQ_SUBSCR: ++ return tahvo_user_subscribe_to_irq(arg, filp); ++ case TAHVO_IOCH_READ: ++ return tahvo_user_read_with_mask(arg); ++ case TAHVO_IOCX_WRITE: ++ ret = copy_from_user(&par, (void __user *) arg, sizeof(par)); ++ if (ret) ++ printk(KERN_ERR "copy_from_user failed: %d\n", ret); ++ par.result = tahvo_user_write_with_mask(par.field, par.value); ++ ret = copy_to_user((void __user *) arg, &par, sizeof(par)); ++ if (ret) ++ printk(KERN_ERR "copy_to_user failed: %d\n", ret); ++ break; ++ default: ++ return -ENOIOCTLCMD; ++ } ++ return 0; ++} ++ ++/* ++ * Read from device ++ */ ++static ssize_t tahvo_read(struct file *filp, char *buf, size_t count, ++ loff_t * offp) ++{ ++ struct tahvo_irq *irq; ++ ++ u32 nr, i; ++ ++ /* read not permitted if neither filp nor anyone has registered IRQs */ ++ if (tahvo_irq_subscr != filp) ++ return -EPERM; ++ ++ if ((count < sizeof(u32)) || ((count % sizeof(u32)) != 0)) ++ return -EINVAL; ++ ++ nr = count / sizeof(u32); ++ ++ for (i = 0; i < nr; i++) { ++ unsigned long flags; ++ u32 irq_id; ++ int ret; ++ ++ ret = wait_event_interruptible(tahvo_user_waitqueue, ++ !list_empty(&tahvo_irqs)); ++ if (ret < 0) ++ return ret; ++ ++ spin_lock_irqsave(&tahvo_irqs_lock, flags); ++ irq = list_entry((&tahvo_irqs)->next, struct tahvo_irq, node); ++ irq_id = irq->id; ++ list_move(&irq->node, &tahvo_irqs_reserve); ++ spin_unlock_irqrestore(&tahvo_irqs_lock, flags); ++ ++ ret = copy_to_user(buf + i * sizeof(irq_id), &irq_id, ++ sizeof(irq_id)); ++ if (ret) ++ printk(KERN_ERR "copy_to_user failed: %d\n", ret); ++ } ++ ++ return count; ++} ++ ++/* ++ * Poll method ++ */ ++static unsigned tahvo_poll(struct file *filp, struct poll_table_struct *pt) ++{ ++ if (!list_empty(&tahvo_irqs)) ++ return POLLIN; ++ ++ poll_wait(filp, &tahvo_user_waitqueue, pt); ++ ++ if (!list_empty(&tahvo_irqs)) ++ return POLLIN; ++ else ++ return 0; ++} ++ ++static struct file_operations tahvo_user_fileops = { ++ .owner = THIS_MODULE, ++ .ioctl = tahvo_ioctl, ++ .read = tahvo_read, ++ .release = tahvo_close, ++ .poll = tahvo_poll ++}; ++ ++static struct miscdevice tahvo_device = { ++ .minor = MISC_DYNAMIC_MINOR, ++ .name = "tahvo", ++ .fops = &tahvo_user_fileops ++}; ++ ++/* ++ * Initialization ++ * ++ * @return 0 if successful, error value otherwise. ++ */ ++int tahvo_user_init(void) ++{ ++ struct tahvo_irq *irq; ++ int res, i; ++ ++ irq = kmalloc(sizeof(*irq) * TAHVO_MAX_IRQ_BUF_LEN, GFP_KERNEL); ++ if (irq == NULL) { ++ printk(KERN_ERR PFX "kmalloc failed\n"); ++ return -ENOMEM; ++ } ++ memset(irq, 0, sizeof(*irq) * TAHVO_MAX_IRQ_BUF_LEN); ++ for (i = 0; i < TAHVO_MAX_IRQ_BUF_LEN; i++) ++ list_add(&irq[i].node, &tahvo_irqs_reserve); ++ ++ tahvo_irq_block = irq; ++ ++ spin_lock_init(&tahvo_irqs_lock); ++ mutex_init(&tahvo_mutex); ++ ++ /* Request a misc device */ ++ res = misc_register(&tahvo_device); ++ if (res < 0) { ++ printk(KERN_ERR PFX "unable to register misc device for %s\n", ++ tahvo_device.name); ++ kfree(irq); ++ return res; ++ } ++ ++ return 0; ++} ++ ++/* ++ * Cleanup. ++ */ ++void tahvo_user_cleanup(void) ++{ ++ /* Unregister our misc device */ ++ misc_deregister(&tahvo_device); ++ /* Unregister and disable all TAHVO interrupts */ ++ tahvo_unreg_irq_handlers(); ++ kfree(tahvo_irq_block); ++} ++ ++MODULE_DESCRIPTION("Tahvo ASIC user space functions"); ++MODULE_LICENSE("GPL"); ++MODULE_AUTHOR("Mikko Ylinen"); +diff --git a/drivers/cbus/tahvo.c b/drivers/cbus/tahvo.c +new file mode 100644 +index 0000000..e734c4c +--- /dev/null ++++ b/drivers/cbus/tahvo.c +@@ -0,0 +1,442 @@ ++/** ++ * drivers/cbus/tahvo.c ++ * ++ * Support functions for Tahvo ASIC ++ * ++ * Copyright (C) 2004, 2005 Nokia Corporation ++ * ++ * Written by Juha Yrjölä , ++ * David Weinehall , and ++ * Mikko Ylinen ++ * ++ * 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 for more details. ++ * ++ * 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, MA 02111-1307 USA ++ */ ++ ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#include ++#include ++#include ++ ++#include "cbus.h" ++#include "tahvo.h" ++ ++#define TAHVO_ID 0x02 ++#define PFX "tahvo: " ++ ++static int tahvo_initialized; ++static int tahvo_irq_pin; ++static int tahvo_is_betty; ++ ++static struct tasklet_struct tahvo_tasklet; ++spinlock_t tahvo_lock = SPIN_LOCK_UNLOCKED; ++ ++static struct completion device_release; ++ ++struct tahvo_irq_handler_desc { ++ int (*func)(unsigned long); ++ unsigned long arg; ++ char name[8]; ++}; ++ ++static struct tahvo_irq_handler_desc tahvo_irq_handlers[MAX_TAHVO_IRQ_HANDLERS]; ++ ++/** ++ * tahvo_read_reg - Read a value from a register in Tahvo ++ * @reg: the register to read from ++ * ++ * This function returns the contents of the specified register ++ */ ++int tahvo_read_reg(int reg) ++{ ++ BUG_ON(!tahvo_initialized); ++ return cbus_read_reg(cbus_host, TAHVO_ID, reg); ++} ++ ++/** ++ * tahvo_write_reg - Write a value to a register in Tahvo ++ * @reg: the register to write to ++ * @reg: the value to write to the register ++ * ++ * This function writes a value to the specified register ++ */ ++void tahvo_write_reg(int reg, u16 val) ++{ ++ BUG_ON(!tahvo_initialized); ++ cbus_write_reg(cbus_host, TAHVO_ID, reg, val); ++} ++ ++/** ++ * tahvo_set_clear_reg_bits - set and clear register bits atomically ++ * @reg: the register to write to ++ * @bits: the bits to set ++ * ++ * This function sets and clears the specified Tahvo register bits atomically ++ */ ++void tahvo_set_clear_reg_bits(int reg, u16 set, u16 clear) ++{ ++ unsigned long flags; ++ u16 w; ++ ++ spin_lock_irqsave(&tahvo_lock, flags); ++ w = tahvo_read_reg(reg); ++ w &= ~clear; ++ w |= set; ++ tahvo_write_reg(reg, w); ++ spin_unlock_irqrestore(&tahvo_lock, flags); ++} ++ ++/* ++ * Disable given TAHVO interrupt ++ */ ++void tahvo_disable_irq(int id) ++{ ++ unsigned long flags; ++ u16 mask; ++ ++ spin_lock_irqsave(&tahvo_lock, flags); ++ mask = tahvo_read_reg(TAHVO_REG_IMR); ++ mask |= 1 << id; ++ tahvo_write_reg(TAHVO_REG_IMR, mask); ++ spin_unlock_irqrestore(&tahvo_lock, flags); ++} ++ ++/* ++ * Enable given TAHVO interrupt ++ */ ++void tahvo_enable_irq(int id) ++{ ++ unsigned long flags; ++ u16 mask; ++ ++ spin_lock_irqsave(&tahvo_lock, flags); ++ mask = tahvo_read_reg(TAHVO_REG_IMR); ++ mask &= ~(1 << id); ++ tahvo_write_reg(TAHVO_REG_IMR, mask); ++ spin_unlock_irqrestore(&tahvo_lock, flags); ++} ++ ++/* ++ * Acknowledge given TAHVO interrupt ++ */ ++void tahvo_ack_irq(int id) ++{ ++ tahvo_write_reg(TAHVO_REG_IDR, 1 << id); ++} ++ ++static int tahvo_7bit_backlight; ++ ++int tahvo_get_backlight_level(void) ++{ ++ int mask; ++ ++ if (tahvo_7bit_backlight) ++ mask = 0x7f; ++ else ++ mask = 0x0f; ++ return tahvo_read_reg(TAHVO_REG_LEDPWMR) & mask; ++} ++ ++int tahvo_get_max_backlight_level(void) ++{ ++ if (tahvo_7bit_backlight) ++ return 0x7f; ++ else ++ return 0x0f; ++} ++ ++void tahvo_set_backlight_level(int level) ++{ ++ int max_level; ++ ++ max_level = tahvo_get_max_backlight_level(); ++ if (level > max_level) ++ level = max_level; ++ tahvo_write_reg(TAHVO_REG_LEDPWMR, level); ++} ++ ++/* ++ * TAHVO interrupt handler. Only schedules the tasklet. ++ */ ++static irqreturn_t tahvo_irq_handler(int irq, void *dev_id) ++{ ++ tasklet_schedule(&tahvo_tasklet); ++ return IRQ_HANDLED; ++} ++ ++/* ++ * Tasklet handler ++ */ ++static void tahvo_tasklet_handler(unsigned long data) ++{ ++ struct tahvo_irq_handler_desc *hnd; ++ u16 id; ++ u16 im; ++ int i; ++ ++ for (;;) { ++ id = tahvo_read_reg(TAHVO_REG_IDR); ++ im = ~tahvo_read_reg(TAHVO_REG_IMR); ++ id &= im; ++ ++ if (!id) ++ break; ++ ++ for (i = 0; id != 0; i++, id >>= 1) { ++ if (!(id & 1)) ++ continue; ++ hnd = &tahvo_irq_handlers[i]; ++ if (hnd->func == NULL) { ++ /* Spurious tahvo interrupt - just ack it */ ++ printk(KERN_INFO "Spurious Tahvo interrupt " ++ "(id %d)\n", i); ++ tahvo_disable_irq(i); ++ tahvo_ack_irq(i); ++ continue; ++ } ++ hnd->func(hnd->arg); ++ /* ++ * Don't acknowledge the interrupt here ++ * It must be done explicitly ++ */ ++ } ++ } ++} ++ ++/* ++ * Register the handler for a given TAHVO interrupt source. ++ */ ++int tahvo_request_irq(int id, void *irq_handler, unsigned long arg, char *name) ++{ ++ struct tahvo_irq_handler_desc *hnd; ++ ++ if (irq_handler == NULL || id >= MAX_TAHVO_IRQ_HANDLERS || ++ name == NULL) { ++ printk(KERN_ERR PFX "Invalid arguments to %s\n", ++ __FUNCTION__); ++ return -EINVAL; ++ } ++ hnd = &tahvo_irq_handlers[id]; ++ if (hnd->func != NULL) { ++ printk(KERN_ERR PFX "IRQ %d already reserved\n", id); ++ return -EBUSY; ++ } ++ printk(KERN_INFO PFX "Registering interrupt %d for device %s\n", ++ id, name); ++ hnd->func = irq_handler; ++ hnd->arg = arg; ++ strlcpy(hnd->name, name, sizeof(hnd->name)); ++ ++ tahvo_ack_irq(id); ++ tahvo_enable_irq(id); ++ ++ return 0; ++} ++ ++/* ++ * Unregister the handler for a given TAHVO interrupt source. ++ */ ++void tahvo_free_irq(int id) ++{ ++ struct tahvo_irq_handler_desc *hnd; ++ ++ if (id >= MAX_TAHVO_IRQ_HANDLERS) { ++ printk(KERN_ERR PFX "Invalid argument to %s\n", ++ __FUNCTION__); ++ return; ++ } ++ hnd = &tahvo_irq_handlers[id]; ++ if (hnd->func == NULL) { ++ printk(KERN_ERR PFX "IRQ %d already freed\n", id); ++ return; ++ } ++ ++ tahvo_disable_irq(id); ++ hnd->func = NULL; ++} ++ ++/** ++ * tahvo_probe - Probe for Tahvo ASIC ++ * @dev: the Tahvo device ++ * ++ * Probe for the Tahvo ASIC and allocate memory ++ * for its device-struct if found ++ */ ++static int __devinit tahvo_probe(struct device *dev) ++{ ++ const struct omap_em_asic_bb5_config * em_asic_config; ++ int rev, id, ret; ++ ++ /* Prepare tasklet */ ++ tasklet_init(&tahvo_tasklet, tahvo_tasklet_handler, 0); ++ ++ em_asic_config = omap_get_config(OMAP_TAG_EM_ASIC_BB5, ++ struct omap_em_asic_bb5_config); ++ if (em_asic_config == NULL) { ++ printk(KERN_ERR PFX "Unable to retrieve config data\n"); ++ return -ENODATA; ++ } ++ ++ tahvo_initialized = 1; ++ ++ rev = tahvo_read_reg(TAHVO_REG_ASICR); ++ ++ id = (rev >> 8) & 0xff; ++ if (id == 0x03) { ++ if ((rev & 0xff) >= 0x50) ++ tahvo_7bit_backlight = 1; ++ } else if (id == 0x0b) { ++ tahvo_is_betty = 1; ++ tahvo_7bit_backlight = 1; ++ } else { ++ printk(KERN_ERR "Tahvo/Betty chip not found"); ++ return -ENODEV; ++ } ++ ++ printk(KERN_INFO "%s v%d.%d found\n", tahvo_is_betty ? "Betty" : "Tahvo", ++ (rev >> 4) & 0x0f, rev & 0x0f); ++ ++ tahvo_irq_pin = em_asic_config->tahvo_irq_gpio; ++ ++ if ((ret = gpio_request(tahvo_irq_pin, "TAHVO irq")) < 0) { ++ printk(KERN_ERR PFX "Unable to reserve IRQ GPIO\n"); ++ return ret; ++ } ++ ++ /* Set the pin as input */ ++ gpio_direction_input(tahvo_irq_pin); ++ ++ /* Rising edge triggers the IRQ */ ++ set_irq_type(gpio_to_irq(tahvo_irq_pin), IRQ_TYPE_EDGE_RISING); ++ ++ /* Mask all TAHVO interrupts */ ++ tahvo_write_reg(TAHVO_REG_IMR, 0xffff); ++ ++ ret = request_irq(gpio_to_irq(tahvo_irq_pin), tahvo_irq_handler, 0, ++ "tahvo", 0); ++ if (ret < 0) { ++ printk(KERN_ERR PFX "Unable to register IRQ handler\n"); ++ gpio_free(tahvo_irq_pin); ++ return ret; ++ } ++#ifdef CONFIG_CBUS_TAHVO_USER ++ /* Initialize user-space interface */ ++ if (tahvo_user_init() < 0) { ++ printk(KERN_ERR "Unable to initialize driver\n"); ++ free_irq(gpio_to_irq(tahvo_irq_pin), 0); ++ gpio_free(tahvo_irq_pin); ++ return ret; ++ } ++#endif ++ return 0; ++} ++ ++static int tahvo_remove(struct device *dev) ++{ ++#ifdef CONFIG_CBUS_TAHVO_USER ++ tahvo_user_cleanup(); ++#endif ++ /* Mask all TAHVO interrupts */ ++ tahvo_write_reg(TAHVO_REG_IMR, 0xffff); ++ free_irq(gpio_to_irq(tahvo_irq_pin), 0); ++ gpio_free(tahvo_irq_pin); ++ tasklet_kill(&tahvo_tasklet); ++ ++ return 0; ++} ++ ++static void tahvo_device_release(struct device *dev) ++{ ++ complete(&device_release); ++} ++ ++static struct device_driver tahvo_driver = { ++ .name = "tahvo", ++ .bus = &platform_bus_type, ++ .probe = tahvo_probe, ++ .remove = tahvo_remove, ++}; ++ ++static struct platform_device tahvo_device = { ++ .name = "tahvo", ++ .id = -1, ++ .dev = { ++ .release = tahvo_device_release, ++ } ++}; ++ ++/** ++ * tahvo_init - initialise Tahvo driver ++ * ++ * Initialise the Tahvo driver and return 0 if everything worked ok ++ */ ++static int __init tahvo_init(void) ++{ ++ int ret = 0; ++ ++ printk(KERN_INFO "Tahvo/Betty driver initialising\n"); ++ ++ init_completion(&device_release); ++ ++ if ((ret = driver_register(&tahvo_driver)) < 0) ++ return ret; ++ ++ if ((ret = platform_device_register(&tahvo_device)) < 0) { ++ driver_unregister(&tahvo_driver); ++ return ret; ++ } ++ return 0; ++} ++ ++/* ++ * Cleanup ++ */ ++static void __exit tahvo_exit(void) ++{ ++ platform_device_unregister(&tahvo_device); ++ driver_unregister(&tahvo_driver); ++ wait_for_completion(&device_release); ++} ++ ++EXPORT_SYMBOL(tahvo_request_irq); ++EXPORT_SYMBOL(tahvo_free_irq); ++EXPORT_SYMBOL(tahvo_enable_irq); ++EXPORT_SYMBOL(tahvo_disable_irq); ++EXPORT_SYMBOL(tahvo_ack_irq); ++EXPORT_SYMBOL(tahvo_read_reg); ++EXPORT_SYMBOL(tahvo_write_reg); ++EXPORT_SYMBOL(tahvo_get_backlight_level); ++EXPORT_SYMBOL(tahvo_get_max_backlight_level); ++EXPORT_SYMBOL(tahvo_set_backlight_level); ++ ++subsys_initcall(tahvo_init); ++module_exit(tahvo_exit); ++ ++MODULE_DESCRIPTION("Tahvo ASIC control"); ++MODULE_LICENSE("GPL"); ++MODULE_AUTHOR("Juha Yrjölä, David Weinehall, and Mikko Ylinen"); +diff --git a/drivers/cbus/tahvo.h b/drivers/cbus/tahvo.h +new file mode 100644 +index 0000000..b7a8ee1 +--- /dev/null ++++ b/drivers/cbus/tahvo.h +@@ -0,0 +1,61 @@ ++/* ++ * drivers/cbus/tahvo.h ++ * ++ * Copyright (C) 2004, 2005 Nokia Corporation ++ * ++ * Written by Juha Yrjölä and ++ * David Weinehall ++ * ++ * 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 for more details. ++ * ++ * 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, MA 02111-1307 USA ++ */ ++ ++#ifndef __DRIVERS_CBUS_TAHVO_H ++#define __DRIVERS_CBUS_TAHVO_H ++ ++#include ++ ++/* Registers */ ++#define TAHVO_REG_ASICR 0x00 /* ASIC ID & revision */ ++#define TAHVO_REG_IDR 0x01 /* Interrupt ID */ ++#define TAHVO_REG_IDSR 0x02 /* Interrupt status */ ++#define TAHVO_REG_IMR 0x03 /* Interrupt mask */ ++#define TAHVO_REG_LEDPWMR 0x05 /* LED PWM */ ++#define TAHVO_REG_USBR 0x06 /* USB control */ ++#define TAHVO_REG_MAX 0x0d ++ ++/* Interrupt sources */ ++#define TAHVO_INT_VBUSON 0 ++ ++#define MAX_TAHVO_IRQ_HANDLERS 8 ++ ++int tahvo_read_reg(int reg); ++void tahvo_write_reg(int reg, u16 val); ++void tahvo_set_clear_reg_bits(int reg, u16 set, u16 clear); ++int tahvo_request_irq(int id, void *irq_handler, unsigned long arg, char *name); ++void tahvo_free_irq(int id); ++void tahvo_enable_irq(int id); ++void tahvo_disable_irq(int id); ++void tahvo_ack_irq(int id); ++int tahvo_get_backlight_level(void); ++int tahvo_get_max_backlight_level(void); ++void tahvo_set_backlight_level(int level); ++ ++#ifdef CONFIG_CBUS_TAHVO_USER ++int tahvo_user_init(void); ++void tahvo_user_cleanup(void); ++#endif ++ ++extern spinlock_t tahvo_lock; ++ ++#endif /* __DRIVERS_CBUS_TAHVO_H */ +diff --git a/drivers/cbus/user_retu_tahvo.h b/drivers/cbus/user_retu_tahvo.h +new file mode 100644 +index 0000000..a5c2190 +--- /dev/null ++++ b/drivers/cbus/user_retu_tahvo.h +@@ -0,0 +1,75 @@ ++/** ++ * drivers/cbus/user_retu_tahvo.h ++ * ++ * Copyright (C) 2004, 2005 Nokia Corporation ++ * ++ * Written by Mikko Ylinen ++ * ++ * Definitions and types used by both retu-user and tahvo-user. ++ * ++ * 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 for more details. ++ * ++ * 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, MA 02111-1307 USA ++ */ ++ ++#ifndef _USER_RETU_TAHVO_H ++#define _USER_RETU_TAHVO_H ++ ++/* Chip IDs */ ++#define CHIP_RETU 1 ++#define CHIP_TAHVO 2 ++ ++/* Register access type bits */ ++#define READ_ONLY 1 ++#define WRITE_ONLY 2 ++#define READ_WRITE 3 ++#define TOGGLE 4 ++ ++#define MASK(field) ((u16)(field & 0xFFFF)) ++#define REG(field) ((u16)((field >> 16) & 0x3F)) ++ ++/*** IOCTL definitions. These should be kept in sync with user space **********/ ++ ++#define URT_IOC_MAGIC '`' ++ ++/* ++ * IOCTL function naming conventions: ++ * ================================== ++ * 0 -- No argument and return value ++ * S -- Set through a pointer ++ * T -- Tell directly with the argument value ++ * G -- Reply by setting through a pointer ++ * Q -- response is on the return value ++ * X -- S and G atomically ++ * H -- T and Q atomically ++ */ ++ ++/* General */ ++#define URT_IOCT_IRQ_SUBSCR _IO(URT_IOC_MAGIC, 0) ++ ++/* RETU */ ++#define RETU_IOCH_READ _IO(URT_IOC_MAGIC, 1) ++#define RETU_IOCX_WRITE _IO(URT_IOC_MAGIC, 2) ++#define RETU_IOCH_ADC_READ _IO(URT_IOC_MAGIC, 3) ++ ++/* TAHVO */ ++#define TAHVO_IOCH_READ _IO(URT_IOC_MAGIC, 4) ++#define TAHVO_IOCX_WRITE _IO(URT_IOC_MAGIC, 5) ++ ++/* This structure is used for writing RETU/TAHVO registers */ ++struct retu_tahvo_write_parms { ++ u32 field; ++ u16 value; ++ u8 result; ++}; ++ ++#endif +diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c +index 4487cc0..0aecaae 100644 +--- a/drivers/mmc/host/omap_hsmmc.c ++++ b/drivers/mmc/host/omap_hsmmc.c +@@ -2013,7 +2013,7 @@ static struct platform_driver omap_hsmmc_driver = { + static int __init omap_hsmmc_init(void) + { + /* Register the MMC driver */ +- return platform_driver_register(&omap_hsmmc_driver); ++ return platform_driver_probe(&omap_hsmmc_driver, omap_hsmmc_probe); + } + + static void __exit omap_hsmmc_cleanup(void) +diff --git a/drivers/spi/omap_uwire.c b/drivers/spi/omap_uwire.c +index e75ba9b..7bcf409 100644 +--- a/drivers/spi/omap_uwire.c ++++ b/drivers/spi/omap_uwire.c +@@ -52,7 +52,7 @@ + #include + + #include +-#include /* OMAP730_IO_CONF registers */ ++#include /* OMAP7XX_IO_CONF registers */ + + + /* FIXME address is now a platform device resource, +@@ -504,7 +504,7 @@ static int __init uwire_probe(struct platform_device *pdev) + } + clk_enable(uwire->ck); + +- if (cpu_is_omap730()) ++ if (cpu_is_omap7xx()) + uwire_idx_shift = 1; + else + uwire_idx_shift = 2; +@@ -573,8 +573,8 @@ static int __init omap_uwire_init(void) + } + if (machine_is_omap_perseus2()) { + /* configure pins: MPU_UW_nSCS1, MPU_UW_SDO, MPU_UW_SCLK */ +- int val = omap_readl(OMAP730_IO_CONF_9) & ~0x00EEE000; +- omap_writel(val | 0x00AAA000, OMAP730_IO_CONF_9); ++ int val = omap_readl(OMAP7XX_IO_CONF_9) & ~0x00EEE000; ++ omap_writel(val | 0x00AAA000, OMAP7XX_IO_CONF_9); + } + + return platform_driver_probe(&uwire_driver, uwire_probe); +diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig +index 2407508..5620e92 100644 +--- a/drivers/usb/Kconfig ++++ b/drivers/usb/Kconfig +@@ -60,6 +60,7 @@ config USB_ARCH_HAS_EHCI + default y if ARCH_IXP4XX + default y if ARCH_W90X900 + default y if ARCH_AT91SAM9G45 ++ default y if ARCH_OMAP34XX + default PCI + + # ARM SA1111 chips have a non-PCI based "OHCI-compatible" USB host interface. +diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c +index 9835e07..44c208c 100644 +--- a/drivers/usb/host/ehci-hcd.c ++++ b/drivers/usb/host/ehci-hcd.c +@@ -1108,6 +1108,11 @@ MODULE_LICENSE ("GPL"); + #define PLATFORM_DRIVER ehci_hcd_au1xxx_driver + #endif + ++#ifdef CONFIG_ARCH_OMAP34XX ++#include "ehci-omap.c" ++#define PLATFORM_DRIVER ehci_hcd_omap_driver ++#endif ++ + #ifdef CONFIG_PPC_PS3 + #include "ehci-ps3.c" + #define PS3_SYSTEM_BUS_DRIVER ps3_ehci_driver +diff --git a/drivers/usb/host/ehci-omap.c b/drivers/usb/host/ehci-omap.c +new file mode 100644 +index 0000000..7ba8df3 +--- /dev/null ++++ b/drivers/usb/host/ehci-omap.c +@@ -0,0 +1,755 @@ ++/* ++ * ehci-omap.c - driver for USBHOST on OMAP 34xx processor ++ * ++ * Bus Glue for OMAP34xx USBHOST 3 port EHCI controller ++ * Tested on OMAP3430 ES2.0 SDP ++ * ++ * Copyright (C) 2007-2008 Texas Instruments, Inc. ++ * Author: Vikram Pandita ++ * ++ * Copyright (C) 2009 Nokia Corporation ++ * Contact: Felipe Balbi ++ * ++ * Based on "ehci-fsl.c" and "ehci-au1xxx.c" ehci glue layers ++ * ++ * 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, MA 02111-1307 USA ++ * ++ * TODO (last updated Feb 23rd, 2009): ++ * - add kernel-doc ++ * - enable AUTOIDLE ++ * - move DPLL5 programming to clock fw ++ * - add suspend/resume ++ * - move workarounds to board-files ++ */ ++ ++#include ++#include ++#include ++#include ++ ++/* ++ * OMAP USBHOST Register addresses: VIRTUAL ADDRESSES ++ * Use ehci_omap_readl()/ehci_omap_writel() functions ++ */ ++ ++/* TLL Register Set */ ++#define OMAP_USBTLL_REVISION (0x00) ++#define OMAP_USBTLL_SYSCONFIG (0x10) ++#define OMAP_USBTLL_SYSCONFIG_CACTIVITY (1 << 8) ++#define OMAP_USBTLL_SYSCONFIG_SIDLEMODE (1 << 3) ++#define OMAP_USBTLL_SYSCONFIG_ENAWAKEUP (1 << 2) ++#define OMAP_USBTLL_SYSCONFIG_SOFTRESET (1 << 1) ++#define OMAP_USBTLL_SYSCONFIG_AUTOIDLE (1 << 0) ++ ++#define OMAP_USBTLL_SYSSTATUS (0x14) ++#define OMAP_USBTLL_SYSSTATUS_RESETDONE (1 << 0) ++ ++#define OMAP_USBTLL_IRQSTATUS (0x18) ++#define OMAP_USBTLL_IRQENABLE (0x1C) ++ ++#define OMAP_TLL_SHARED_CONF (0x30) ++#define OMAP_TLL_SHARED_CONF_USB_90D_DDR_EN (1 << 6) ++#define OMAP_TLL_SHARED_CONF_USB_180D_SDR_EN (1 << 5) ++#define OMAP_TLL_SHARED_CONF_USB_DIVRATION (1 << 2) ++#define OMAP_TLL_SHARED_CONF_FCLK_REQ (1 << 1) ++#define OMAP_TLL_SHARED_CONF_FCLK_IS_ON (1 << 0) ++ ++#define OMAP_TLL_CHANNEL_CONF(num) (0x040 + 0x004 * num) ++#define OMAP_TLL_CHANNEL_CONF_ULPINOBITSTUFF (1 << 11) ++#define OMAP_TLL_CHANNEL_CONF_ULPI_ULPIAUTOIDLE (1 << 10) ++#define OMAP_TLL_CHANNEL_CONF_UTMIAUTOIDLE (1 << 9) ++#define OMAP_TLL_CHANNEL_CONF_ULPIDDRMODE (1 << 8) ++#define OMAP_TLL_CHANNEL_CONF_CHANEN (1 << 0) ++ ++#define OMAP_TLL_ULPI_FUNCTION_CTRL(num) (0x804 + 0x100 * num) ++#define OMAP_TLL_ULPI_INTERFACE_CTRL(num) (0x807 + 0x100 * num) ++#define OMAP_TLL_ULPI_OTG_CTRL(num) (0x80A + 0x100 * num) ++#define OMAP_TLL_ULPI_INT_EN_RISE(num) (0x80D + 0x100 * num) ++#define OMAP_TLL_ULPI_INT_EN_FALL(num) (0x810 + 0x100 * num) ++#define OMAP_TLL_ULPI_INT_STATUS(num) (0x813 + 0x100 * num) ++#define OMAP_TLL_ULPI_INT_LATCH(num) (0x814 + 0x100 * num) ++#define OMAP_TLL_ULPI_DEBUG(num) (0x815 + 0x100 * num) ++#define OMAP_TLL_ULPI_SCRATCH_REGISTER(num) (0x816 + 0x100 * num) ++ ++#define OMAP_TLL_CHANNEL_COUNT 3 ++#define OMAP_TLL_CHANNEL_1_EN_MASK (1 << 1) ++#define OMAP_TLL_CHANNEL_2_EN_MASK (1 << 2) ++#define OMAP_TLL_CHANNEL_3_EN_MASK (1 << 4) ++ ++/* UHH Register Set */ ++#define OMAP_UHH_REVISION (0x00) ++#define OMAP_UHH_SYSCONFIG (0x10) ++#define OMAP_UHH_SYSCONFIG_MIDLEMODE (1 << 12) ++#define OMAP_UHH_SYSCONFIG_CACTIVITY (1 << 8) ++#define OMAP_UHH_SYSCONFIG_SIDLEMODE (1 << 3) ++#define OMAP_UHH_SYSCONFIG_ENAWAKEUP (1 << 2) ++#define OMAP_UHH_SYSCONFIG_SOFTRESET (1 << 1) ++#define OMAP_UHH_SYSCONFIG_AUTOIDLE (1 << 0) ++ ++#define OMAP_UHH_SYSSTATUS (0x14) ++#define OMAP_UHH_HOSTCONFIG (0x40) ++#define OMAP_UHH_HOSTCONFIG_ULPI_BYPASS (1 << 0) ++#define OMAP_UHH_HOSTCONFIG_ULPI_P1_BYPASS (1 << 0) ++#define OMAP_UHH_HOSTCONFIG_ULPI_P2_BYPASS (1 << 11) ++#define OMAP_UHH_HOSTCONFIG_ULPI_P3_BYPASS (1 << 12) ++#define OMAP_UHH_HOSTCONFIG_INCR4_BURST_EN (1 << 2) ++#define OMAP_UHH_HOSTCONFIG_INCR8_BURST_EN (1 << 3) ++#define OMAP_UHH_HOSTCONFIG_INCR16_BURST_EN (1 << 4) ++#define OMAP_UHH_HOSTCONFIG_INCRX_ALIGN_EN (1 << 5) ++#define OMAP_UHH_HOSTCONFIG_P1_CONNECT_STATUS (1 << 8) ++#define OMAP_UHH_HOSTCONFIG_P2_CONNECT_STATUS (1 << 9) ++#define OMAP_UHH_HOSTCONFIG_P3_CONNECT_STATUS (1 << 10) ++ ++#define OMAP_UHH_DEBUG_CSR (0x44) ++ ++/* EHCI Register Set */ ++#define EHCI_INSNREG05_ULPI (0xA4) ++#define EHCI_INSNREG05_ULPI_CONTROL_SHIFT 31 ++#define EHCI_INSNREG05_ULPI_PORTSEL_SHIFT 24 ++#define EHCI_INSNREG05_ULPI_OPSEL_SHIFT 22 ++#define EHCI_INSNREG05_ULPI_REGADD_SHIFT 16 ++#define EHCI_INSNREG05_ULPI_EXTREGADD_SHIFT 8 ++#define EHCI_INSNREG05_ULPI_WRDATA_SHIFT 0 ++ ++/*-------------------------------------------------------------------------*/ ++ ++static inline void ehci_omap_writel(void __iomem *base, u32 reg, u32 val) ++{ ++ __raw_writel(val, base + reg); ++} ++ ++static inline u32 ehci_omap_readl(void __iomem *base, u32 reg) ++{ ++ return __raw_readl(base + reg); ++} ++ ++static inline void ehci_omap_writeb(void __iomem *base, u8 reg, u8 val) ++{ ++ __raw_writeb(val, base + reg); ++} ++ ++static inline u8 ehci_omap_readb(void __iomem *base, u8 reg) ++{ ++ return __raw_readb(base + reg); ++} ++ ++/*-------------------------------------------------------------------------*/ ++ ++struct ehci_hcd_omap { ++ struct ehci_hcd *ehci; ++ struct device *dev; ++ ++ struct clk *usbhost_ick; ++ struct clk *usbhost2_120m_fck; ++ struct clk *usbhost1_48m_fck; ++ struct clk *usbtll_fck; ++ struct clk *usbtll_ick; ++ ++ /* FIXME the following two workarounds are ++ * board specific not silicon-specific so these ++ * should be moved to board-file instead. ++ * ++ * Maybe someone from TI will know better which ++ * board is affected and needs the workarounds ++ * to be applied ++ */ ++ ++ /* gpio for resetting phy */ ++ int reset_gpio_port[OMAP3_HS_USB_PORTS]; ++ ++ /* phy reset workaround */ ++ int phy_reset; ++ ++ /* desired phy_mode: TLL, PHY */ ++ enum ehci_hcd_omap_mode port_mode[OMAP3_HS_USB_PORTS]; ++ ++ void __iomem *uhh_base; ++ void __iomem *tll_base; ++ void __iomem *ehci_base; ++}; ++ ++/*-------------------------------------------------------------------------*/ ++ ++static void omap_usb_utmi_init(struct ehci_hcd_omap *omap, u8 tll_channel_mask) ++{ ++ unsigned reg; ++ int i; ++ ++ /* Program the 3 TLL channels upfront */ ++ for (i = 0; i < OMAP_TLL_CHANNEL_COUNT; i++) { ++ reg = ehci_omap_readl(omap->tll_base, OMAP_TLL_CHANNEL_CONF(i)); ++ ++ /* Disable AutoIdle, BitStuffing and use SDR Mode */ ++ reg &= ~(OMAP_TLL_CHANNEL_CONF_UTMIAUTOIDLE ++ | OMAP_TLL_CHANNEL_CONF_ULPINOBITSTUFF ++ | OMAP_TLL_CHANNEL_CONF_ULPIDDRMODE); ++ ehci_omap_writel(omap->tll_base, OMAP_TLL_CHANNEL_CONF(i), reg); ++ } ++ ++ /* Program Common TLL register */ ++ reg = ehci_omap_readl(omap->tll_base, OMAP_TLL_SHARED_CONF); ++ reg |= (OMAP_TLL_SHARED_CONF_FCLK_IS_ON ++ | OMAP_TLL_SHARED_CONF_USB_DIVRATION ++ | OMAP_TLL_SHARED_CONF_USB_180D_SDR_EN); ++ reg &= ~OMAP_TLL_SHARED_CONF_USB_90D_DDR_EN; ++ ++ ehci_omap_writel(omap->tll_base, OMAP_TLL_SHARED_CONF, reg); ++ ++ /* Enable channels now */ ++ for (i = 0; i < OMAP_TLL_CHANNEL_COUNT; i++) { ++ reg = ehci_omap_readl(omap->tll_base, OMAP_TLL_CHANNEL_CONF(i)); ++ ++ /* Enable only the reg that is needed */ ++ if (!(tll_channel_mask & 1<tll_base, OMAP_TLL_CHANNEL_CONF(i), reg); ++ ++ ehci_omap_writeb(omap->tll_base, ++ OMAP_TLL_ULPI_SCRATCH_REGISTER(i), 0xbe); ++ dev_dbg(omap->dev, "ULPI_SCRATCH_REG[ch=%d]= 0x%02x\n", ++ i+1, ehci_omap_readb(omap->tll_base, ++ OMAP_TLL_ULPI_SCRATCH_REGISTER(i))); ++ } ++} ++ ++/*-------------------------------------------------------------------------*/ ++ ++/* omap_start_ehc ++ * - Start the TI USBHOST controller ++ */ ++static int omap_start_ehc(struct ehci_hcd_omap *omap, struct usb_hcd *hcd) ++{ ++ unsigned long timeout = jiffies + msecs_to_jiffies(1000); ++ u8 tll_ch_mask = 0; ++ unsigned reg = 0; ++ int ret = 0; ++ ++ dev_dbg(omap->dev, "starting TI EHCI USB Controller\n"); ++ ++ /* Enable Clocks for USBHOST */ ++ omap->usbhost_ick = clk_get(omap->dev, "usbhost_ick"); ++ if (IS_ERR(omap->usbhost_ick)) { ++ ret = PTR_ERR(omap->usbhost_ick); ++ goto err_host_ick; ++ } ++ clk_enable(omap->usbhost_ick); ++ ++ omap->usbhost2_120m_fck = clk_get(omap->dev, "usbhost_120m_fck"); ++ if (IS_ERR(omap->usbhost2_120m_fck)) { ++ ret = PTR_ERR(omap->usbhost2_120m_fck); ++ goto err_host_120m_fck; ++ } ++ clk_enable(omap->usbhost2_120m_fck); ++ ++ omap->usbhost1_48m_fck = clk_get(omap->dev, "usbhost_48m_fck"); ++ if (IS_ERR(omap->usbhost1_48m_fck)) { ++ ret = PTR_ERR(omap->usbhost1_48m_fck); ++ goto err_host_48m_fck; ++ } ++ clk_enable(omap->usbhost1_48m_fck); ++ ++ if (omap->phy_reset) { ++ /* Refer: ISSUE1 */ ++ if (gpio_is_valid(omap->reset_gpio_port[0])) { ++ gpio_request(omap->reset_gpio_port[0], ++ "USB1 PHY reset"); ++ gpio_direction_output(omap->reset_gpio_port[0], 0); ++ } ++ ++ if (gpio_is_valid(omap->reset_gpio_port[1])) { ++ gpio_request(omap->reset_gpio_port[1], ++ "USB2 PHY reset"); ++ gpio_direction_output(omap->reset_gpio_port[1], 0); ++ } ++ ++ /* Hold the PHY in RESET for enough time till DIR is high */ ++ udelay(10); ++ } ++ ++ /* Configure TLL for 60Mhz clk for ULPI */ ++ omap->usbtll_fck = clk_get(omap->dev, "usbtll_fck"); ++ if (IS_ERR(omap->usbtll_fck)) { ++ ret = PTR_ERR(omap->usbtll_fck); ++ goto err_tll_fck; ++ } ++ clk_enable(omap->usbtll_fck); ++ ++ omap->usbtll_ick = clk_get(omap->dev, "usbtll_ick"); ++ if (IS_ERR(omap->usbtll_ick)) { ++ ret = PTR_ERR(omap->usbtll_ick); ++ goto err_tll_ick; ++ } ++ clk_enable(omap->usbtll_ick); ++ ++ /* perform TLL soft reset, and wait until reset is complete */ ++ ehci_omap_writel(omap->tll_base, OMAP_USBTLL_SYSCONFIG, ++ OMAP_USBTLL_SYSCONFIG_SOFTRESET); ++ ++ /* Wait for TLL reset to complete */ ++ while (!(ehci_omap_readl(omap->tll_base, OMAP_USBTLL_SYSSTATUS) ++ & OMAP_USBTLL_SYSSTATUS_RESETDONE)) { ++ cpu_relax(); ++ ++ if (time_after(jiffies, timeout)) { ++ dev_dbg(omap->dev, "operation timed out\n"); ++ ret = -EINVAL; ++ goto err_sys_status; ++ } ++ } ++ ++ dev_dbg(omap->dev, "TLL RESET DONE\n"); ++ ++ /* (1<<3) = no idle mode only for initial debugging */ ++ ehci_omap_writel(omap->tll_base, OMAP_USBTLL_SYSCONFIG, ++ OMAP_USBTLL_SYSCONFIG_ENAWAKEUP | ++ OMAP_USBTLL_SYSCONFIG_SIDLEMODE | ++ OMAP_USBTLL_SYSCONFIG_CACTIVITY); ++ ++ ++ /* Put UHH in NoIdle/NoStandby mode */ ++ reg = ehci_omap_readl(omap->uhh_base, OMAP_UHH_SYSCONFIG); ++ reg |= (OMAP_UHH_SYSCONFIG_ENAWAKEUP ++ | OMAP_UHH_SYSCONFIG_SIDLEMODE ++ | OMAP_UHH_SYSCONFIG_CACTIVITY ++ | OMAP_UHH_SYSCONFIG_MIDLEMODE); ++ reg &= ~OMAP_UHH_SYSCONFIG_AUTOIDLE; ++ ++ ehci_omap_writel(omap->uhh_base, OMAP_UHH_SYSCONFIG, reg); ++ ++ reg = ehci_omap_readl(omap->uhh_base, OMAP_UHH_HOSTCONFIG); ++ ++ /* setup ULPI bypass and burst configurations */ ++ reg |= (OMAP_UHH_HOSTCONFIG_INCR4_BURST_EN ++ | OMAP_UHH_HOSTCONFIG_INCR8_BURST_EN ++ | OMAP_UHH_HOSTCONFIG_INCR16_BURST_EN); ++ reg &= ~OMAP_UHH_HOSTCONFIG_INCRX_ALIGN_EN; ++ ++ if (omap->port_mode[0] == EHCI_HCD_OMAP_MODE_UNKNOWN) ++ reg &= ~OMAP_UHH_HOSTCONFIG_P1_CONNECT_STATUS; ++ if (omap->port_mode[1] == EHCI_HCD_OMAP_MODE_UNKNOWN) ++ reg &= ~OMAP_UHH_HOSTCONFIG_P2_CONNECT_STATUS; ++ if (omap->port_mode[2] == EHCI_HCD_OMAP_MODE_UNKNOWN) ++ reg &= ~OMAP_UHH_HOSTCONFIG_P3_CONNECT_STATUS; ++ ++ /* Bypass the TLL module for PHY mode operation */ ++ if (omap_rev() <= OMAP3430_REV_ES2_1) { ++ dev_dbg(omap->dev, "OMAP3 ES version <= ES2.1 \n"); ++ if ((omap->port_mode[0] == EHCI_HCD_OMAP_MODE_PHY) || ++ (omap->port_mode[1] == EHCI_HCD_OMAP_MODE_PHY) || ++ (omap->port_mode[2] == EHCI_HCD_OMAP_MODE_PHY)) ++ reg &= ~OMAP_UHH_HOSTCONFIG_ULPI_BYPASS; ++ else ++ reg |= OMAP_UHH_HOSTCONFIG_ULPI_BYPASS; ++ } else { ++ dev_dbg(omap->dev, "OMAP3 ES version > ES2.1\n"); ++ if (omap->port_mode[0] == EHCI_HCD_OMAP_MODE_PHY) ++ reg &= ~OMAP_UHH_HOSTCONFIG_ULPI_P1_BYPASS; ++ else if (omap->port_mode[0] == EHCI_HCD_OMAP_MODE_TLL) ++ reg |= OMAP_UHH_HOSTCONFIG_ULPI_P1_BYPASS; ++ ++ if (omap->port_mode[1] == EHCI_HCD_OMAP_MODE_PHY) ++ reg &= ~OMAP_UHH_HOSTCONFIG_ULPI_P2_BYPASS; ++ else if (omap->port_mode[1] == EHCI_HCD_OMAP_MODE_TLL) ++ reg |= OMAP_UHH_HOSTCONFIG_ULPI_P2_BYPASS; ++ ++ if (omap->port_mode[2] == EHCI_HCD_OMAP_MODE_PHY) ++ reg &= ~OMAP_UHH_HOSTCONFIG_ULPI_P3_BYPASS; ++ else if (omap->port_mode[2] == EHCI_HCD_OMAP_MODE_TLL) ++ reg |= OMAP_UHH_HOSTCONFIG_ULPI_P3_BYPASS; ++ ++ } ++ ehci_omap_writel(omap->uhh_base, OMAP_UHH_HOSTCONFIG, reg); ++ dev_dbg(omap->dev, "UHH setup done, uhh_hostconfig=%x\n", reg); ++ ++ ++ if ((omap->port_mode[0] == EHCI_HCD_OMAP_MODE_TLL) || ++ (omap->port_mode[1] == EHCI_HCD_OMAP_MODE_TLL) || ++ (omap->port_mode[2] == EHCI_HCD_OMAP_MODE_TLL)) { ++ ++ if (omap->port_mode[0] == EHCI_HCD_OMAP_MODE_TLL) ++ tll_ch_mask |= OMAP_TLL_CHANNEL_1_EN_MASK; ++ if (omap->port_mode[1] == EHCI_HCD_OMAP_MODE_TLL) ++ tll_ch_mask |= OMAP_TLL_CHANNEL_2_EN_MASK; ++ if (omap->port_mode[2] == EHCI_HCD_OMAP_MODE_TLL) ++ tll_ch_mask |= OMAP_TLL_CHANNEL_3_EN_MASK; ++ ++ /* Enable UTMI mode for required TLL channels */ ++ omap_usb_utmi_init(omap, tll_ch_mask); ++ } ++ ++ if (omap->phy_reset) { ++ /* Refer ISSUE1: ++ * Hold the PHY in RESET for enough time till ++ * PHY is settled and ready ++ */ ++ udelay(10); ++ ++ if (gpio_is_valid(omap->reset_gpio_port[0])) ++ gpio_set_value(omap->reset_gpio_port[0], 1); ++ ++ if (gpio_is_valid(omap->reset_gpio_port[1])) ++ gpio_set_value(omap->reset_gpio_port[1], 1); ++ } ++ ++ return 0; ++ ++err_sys_status: ++ clk_disable(omap->usbtll_ick); ++ clk_put(omap->usbtll_ick); ++ ++err_tll_ick: ++ clk_disable(omap->usbtll_fck); ++ clk_put(omap->usbtll_fck); ++ ++err_tll_fck: ++ clk_disable(omap->usbhost1_48m_fck); ++ clk_put(omap->usbhost1_48m_fck); ++ ++ if (omap->phy_reset) { ++ if (gpio_is_valid(omap->reset_gpio_port[0])) ++ gpio_free(omap->reset_gpio_port[0]); ++ ++ if (gpio_is_valid(omap->reset_gpio_port[1])) ++ gpio_free(omap->reset_gpio_port[1]); ++ } ++ ++err_host_48m_fck: ++ clk_disable(omap->usbhost2_120m_fck); ++ clk_put(omap->usbhost2_120m_fck); ++ ++err_host_120m_fck: ++ clk_disable(omap->usbhost_ick); ++ clk_put(omap->usbhost_ick); ++ ++err_host_ick: ++ return ret; ++} ++ ++static void omap_stop_ehc(struct ehci_hcd_omap *omap, struct usb_hcd *hcd) ++{ ++ unsigned long timeout = jiffies + msecs_to_jiffies(100); ++ ++ dev_dbg(omap->dev, "stopping TI EHCI USB Controller\n"); ++ ++ /* Reset OMAP modules for insmod/rmmod to work */ ++ ehci_omap_writel(omap->uhh_base, OMAP_UHH_SYSCONFIG, ++ OMAP_UHH_SYSCONFIG_SOFTRESET); ++ while (!(ehci_omap_readl(omap->uhh_base, OMAP_UHH_SYSSTATUS) ++ & (1 << 0))) { ++ cpu_relax(); ++ ++ if (time_after(jiffies, timeout)) ++ dev_dbg(omap->dev, "operation timed out\n"); ++ } ++ ++ while (!(ehci_omap_readl(omap->uhh_base, OMAP_UHH_SYSSTATUS) ++ & (1 << 1))) { ++ cpu_relax(); ++ ++ if (time_after(jiffies, timeout)) ++ dev_dbg(omap->dev, "operation timed out\n"); ++ } ++ ++ while (!(ehci_omap_readl(omap->uhh_base, OMAP_UHH_SYSSTATUS) ++ & (1 << 2))) { ++ cpu_relax(); ++ ++ if (time_after(jiffies, timeout)) ++ dev_dbg(omap->dev, "operation timed out\n"); ++ } ++ ++ ehci_omap_writel(omap->tll_base, OMAP_USBTLL_SYSCONFIG, (1 << 1)); ++ ++ while (!(ehci_omap_readl(omap->tll_base, OMAP_USBTLL_SYSSTATUS) ++ & (1 << 0))) { ++ cpu_relax(); ++ ++ if (time_after(jiffies, timeout)) ++ dev_dbg(omap->dev, "operation timed out\n"); ++ } ++ ++ if (omap->usbtll_fck != NULL) { ++ clk_disable(omap->usbtll_fck); ++ clk_put(omap->usbtll_fck); ++ omap->usbtll_fck = NULL; ++ } ++ ++ if (omap->usbhost_ick != NULL) { ++ clk_disable(omap->usbhost_ick); ++ clk_put(omap->usbhost_ick); ++ omap->usbhost_ick = NULL; ++ } ++ ++ if (omap->usbhost1_48m_fck != NULL) { ++ clk_disable(omap->usbhost1_48m_fck); ++ clk_put(omap->usbhost1_48m_fck); ++ omap->usbhost1_48m_fck = NULL; ++ } ++ ++ if (omap->usbhost2_120m_fck != NULL) { ++ clk_disable(omap->usbhost2_120m_fck); ++ clk_put(omap->usbhost2_120m_fck); ++ omap->usbhost2_120m_fck = NULL; ++ } ++ ++ if (omap->usbtll_ick != NULL) { ++ clk_disable(omap->usbtll_ick); ++ clk_put(omap->usbtll_ick); ++ omap->usbtll_ick = NULL; ++ } ++ ++ if (omap->phy_reset) { ++ if (gpio_is_valid(omap->reset_gpio_port[0])) ++ gpio_free(omap->reset_gpio_port[0]); ++ ++ if (gpio_is_valid(omap->reset_gpio_port[1])) ++ gpio_free(omap->reset_gpio_port[1]); ++ } ++ ++ dev_dbg(omap->dev, "Clock to USB host has been disabled\n"); ++} ++ ++/*-------------------------------------------------------------------------*/ ++ ++static const struct hc_driver ehci_omap_hc_driver; ++ ++/* configure so an HC device and id are always provided */ ++/* always called with process context; sleeping is OK */ ++ ++/** ++ * ehci_hcd_omap_probe - initialize TI-based HCDs ++ * ++ * Allocates basic resources for this USB host controller, and ++ * then invokes the start() method for the HCD associated with it ++ * through the hotplug entry's driver_data. ++ */ ++static int ehci_hcd_omap_probe(struct platform_device *pdev) ++{ ++ struct ehci_hcd_omap_platform_data *pdata = pdev->dev.platform_data; ++ struct ehci_hcd_omap *omap; ++ struct resource *res; ++ struct usb_hcd *hcd; ++ ++ int irq = platform_get_irq(pdev, 0); ++ int ret = -ENODEV; ++ ++ if (!pdata) { ++ dev_dbg(&pdev->dev, "missing platform_data\n"); ++ goto err_pdata; ++ } ++ ++ if (usb_disabled()) ++ goto err_disabled; ++ ++ omap = kzalloc(sizeof(*omap), GFP_KERNEL); ++ if (!omap) { ++ ret = -ENOMEM; ++ goto err_create_hcd; ++ } ++ ++ hcd = usb_create_hcd(&ehci_omap_hc_driver, &pdev->dev, ++ dev_name(&pdev->dev)); ++ if (!hcd) { ++ dev_dbg(&pdev->dev, "failed to create hcd with err %d\n", ret); ++ ret = -ENOMEM; ++ goto err_create_hcd; ++ } ++ ++ platform_set_drvdata(pdev, omap); ++ omap->dev = &pdev->dev; ++ omap->phy_reset = pdata->phy_reset; ++ omap->reset_gpio_port[0] = pdata->reset_gpio_port[0]; ++ omap->reset_gpio_port[1] = pdata->reset_gpio_port[1]; ++ omap->reset_gpio_port[2] = pdata->reset_gpio_port[2]; ++ omap->port_mode[0] = pdata->port_mode[0]; ++ omap->port_mode[1] = pdata->port_mode[1]; ++ omap->port_mode[2] = pdata->port_mode[2]; ++ omap->ehci = hcd_to_ehci(hcd); ++ omap->ehci->sbrn = 0x20; ++ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ ++ hcd->rsrc_start = res->start; ++ hcd->rsrc_len = resource_size(res); ++ ++ hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len); ++ if (!hcd->regs) { ++ dev_err(&pdev->dev, "EHCI ioremap failed\n"); ++ ret = -ENOMEM; ++ goto err_ioremap; ++ } ++ ++ /* we know this is the memory we want, no need to ioremap again */ ++ omap->ehci->caps = hcd->regs; ++ omap->ehci_base = hcd->regs; ++ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 1); ++ omap->uhh_base = ioremap(res->start, resource_size(res)); ++ if (!omap->uhh_base) { ++ dev_err(&pdev->dev, "UHH ioremap failed\n"); ++ ret = -ENOMEM; ++ goto err_uhh_ioremap; ++ } ++ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 2); ++ omap->tll_base = ioremap(res->start, resource_size(res)); ++ if (!omap->tll_base) { ++ dev_err(&pdev->dev, "TLL ioremap failed\n"); ++ ret = -ENOMEM; ++ goto err_tll_ioremap; ++ } ++ ++ ret = omap_start_ehc(omap, hcd); ++ if (ret) { ++ dev_dbg(&pdev->dev, "failed to start ehci\n"); ++ goto err_start; ++ } ++ ++ omap->ehci->regs = hcd->regs ++ + HC_LENGTH(readl(&omap->ehci->caps->hc_capbase)); ++ ++ /* cache this readonly data; minimize chip reads */ ++ omap->ehci->hcs_params = readl(&omap->ehci->caps->hcs_params); ++ ++ /* SET 1 micro-frame Interrupt interval */ ++ writel(readl(&omap->ehci->regs->command) | (1 << 16), ++ &omap->ehci->regs->command); ++ ++ ret = usb_add_hcd(hcd, irq, IRQF_DISABLED | IRQF_SHARED); ++ if (ret) { ++ dev_dbg(&pdev->dev, "failed to add hcd with err %d\n", ret); ++ goto err_add_hcd; ++ } ++ ++ return 0; ++ ++err_add_hcd: ++ omap_stop_ehc(omap, hcd); ++ ++err_start: ++ iounmap(omap->tll_base); ++ ++err_tll_ioremap: ++ iounmap(omap->uhh_base); ++ ++err_uhh_ioremap: ++ iounmap(hcd->regs); ++ ++err_ioremap: ++ usb_put_hcd(hcd); ++ ++err_create_hcd: ++err_disabled: ++err_pdata: ++ return ret; ++} ++ ++/* may be called without controller electrically present */ ++/* may be called with controller, bus, and devices active */ ++ ++/** ++ * ehci_hcd_omap_remove - shutdown processing for EHCI HCDs ++ * @pdev: USB Host Controller being removed ++ * ++ * Reverses the effect of usb_ehci_hcd_omap_probe(), first invoking ++ * the HCD's stop() method. It is always called from a thread ++ * context, normally "rmmod", "apmd", or something similar. ++ */ ++static int ehci_hcd_omap_remove(struct platform_device *pdev) ++{ ++ struct ehci_hcd_omap *omap = platform_get_drvdata(pdev); ++ struct usb_hcd *hcd = ehci_to_hcd(omap->ehci); ++ ++ usb_remove_hcd(hcd); ++ omap_stop_ehc(omap, hcd); ++ iounmap(hcd->regs); ++ iounmap(omap->tll_base); ++ iounmap(omap->uhh_base); ++ usb_put_hcd(hcd); ++ ++ return 0; ++} ++ ++static void ehci_hcd_omap_shutdown(struct platform_device *pdev) ++{ ++ struct ehci_hcd_omap *omap = platform_get_drvdata(pdev); ++ struct usb_hcd *hcd = ehci_to_hcd(omap->ehci); ++ ++ if (hcd->driver->shutdown) ++ hcd->driver->shutdown(hcd); ++} ++ ++static struct platform_driver ehci_hcd_omap_driver = { ++ .probe = ehci_hcd_omap_probe, ++ .remove = ehci_hcd_omap_remove, ++ .shutdown = ehci_hcd_omap_shutdown, ++ /*.suspend = ehci_hcd_omap_suspend, */ ++ /*.resume = ehci_hcd_omap_resume, */ ++ .driver = { ++ .name = "ehci-omap", ++ } ++}; ++ ++/*-------------------------------------------------------------------------*/ ++ ++static const struct hc_driver ehci_omap_hc_driver = { ++ .description = hcd_name, ++ .product_desc = "OMAP-EHCI Host Controller", ++ .hcd_priv_size = sizeof(struct ehci_hcd), ++ ++ /* ++ * generic hardware linkage ++ */ ++ .irq = ehci_irq, ++ .flags = HCD_MEMORY | HCD_USB2, ++ ++ /* ++ * basic lifecycle operations ++ */ ++ .reset = ehci_init, ++ .start = ehci_run, ++ .stop = ehci_stop, ++ .shutdown = ehci_shutdown, ++ ++ /* ++ * managing i/o requests and associated device resources ++ */ ++ .urb_enqueue = ehci_urb_enqueue, ++ .urb_dequeue = ehci_urb_dequeue, ++ .endpoint_disable = ehci_endpoint_disable, ++ .endpoint_reset = ehci_endpoint_reset, ++ ++ /* ++ * scheduling support ++ */ ++ .get_frame_number = ehci_get_frame, ++ ++ /* ++ * root hub support ++ */ ++ .hub_status_data = ehci_hub_status_data, ++ .hub_control = ehci_hub_control, ++ .bus_suspend = ehci_bus_suspend, ++ .bus_resume = ehci_bus_resume, ++ ++ .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete, ++}; ++ ++MODULE_ALIAS("platform:omap-ehci"); ++MODULE_AUTHOR("Texas Instruments, Inc."); ++MODULE_AUTHOR("Felipe Balbi "); ++ +diff --git a/drivers/video/omap/dispc.c b/drivers/video/omap/dispc.c +index f16e421..6f957ce 100644 +--- a/drivers/video/omap/dispc.c ++++ b/drivers/video/omap/dispc.c +@@ -204,6 +204,7 @@ static u32 inline dispc_read_reg(int idx) + /* Select RFBI or bypass mode */ + static void enable_rfbi_mode(int enable) + { ++ void __iomem *rfbi_control; + u32 l; + + l = dispc_read_reg(DISPC_CONTROL); +@@ -216,9 +217,15 @@ static void enable_rfbi_mode(int enable) + dispc_write_reg(DISPC_CONTROL, l); + + /* Set bypass mode in RFBI module */ +- l = __raw_readl(OMAP2_IO_ADDRESS(RFBI_CONTROL)); ++ rfbi_control = ioremap(RFBI_CONTROL, SZ_1K); ++ if (!rfbi_control) { ++ pr_err("Unable to ioremap rfbi_control\n"); ++ return; ++ } ++ l = __raw_readl(rfbi_control); + l |= enable ? 0 : (1 << 1); +- __raw_writel(l, OMAP2_IO_ADDRESS(RFBI_CONTROL)); ++ __raw_writel(l, rfbi_control); ++ iounmap(rfbi_control); + } + + static void set_lcd_data_lines(int data_lines) +@@ -1367,6 +1374,7 @@ static int omap_dispc_init(struct omapfb_device *fbdev, int ext_mode, + int r; + u32 l; + struct lcd_panel *panel = fbdev->panel; ++ void __iomem *ram_fw_base; + int tmo = 10000; + int skip_init = 0; + int i; +@@ -1441,7 +1449,13 @@ static int omap_dispc_init(struct omapfb_device *fbdev, int ext_mode, + } + + /* L3 firewall setting: enable access to OCM RAM */ +- __raw_writel(0x402000b0, OMAP2_IO_ADDRESS(0x680050a0)); ++ ram_fw_base = ioremap(0x68005000, SZ_1K); ++ if (!ram_fw_base) { ++ dev_err(dispc.fbdev->dev, "Cannot ioremap to enable OCM RAM\n"); ++ goto fail1; ++ } ++ __raw_writel(0x402000b0, ram_fw_base + 0xa0); ++ iounmap(ram_fw_base); + + if ((r = alloc_palette_ram()) < 0) + goto fail2; diff --git a/target/linux/omap35xx/patches-2.6.32/003-enable_dss2_beagleboard.patch b/target/linux/omap35xx/patches-2.6.32/003-enable_dss2_beagleboard.patch new file mode 100644 index 000000000..6ef4cbffd --- /dev/null +++ b/target/linux/omap35xx/patches-2.6.32/003-enable_dss2_beagleboard.patch @@ -0,0 +1,195 @@ +--- a/arch/arm/mach-omap2/board-omap3beagle.c 2009-11-27 02:38:04.000000000 +0100 ++++ b/arch/arm/mach-omap2/board-omap3beagle.c 2009-11-27 00:36:10.511677848 +0100 +@@ -23,6 +23,7 @@ + #include + #include + #include ++#include + + #include + #include +@@ -44,6 +45,7 @@ + #include + #include + #include ++#include + + #include "mmc-twl4030.h" + +@@ -106,6 +108,92 @@ static struct platform_device omap3beagl + .resource = &omap3beagle_nand_resource, + }; + ++/* DSS */ ++ ++static int beagle_enable_dvi(struct omap_dss_device *dssdev) ++{ ++ if (dssdev->reset_gpio != -1) ++ gpio_set_value(dssdev->reset_gpio, 1); ++ ++ return 0; ++} ++ ++static void beagle_disable_dvi(struct omap_dss_device *dssdev) ++{ ++ if (dssdev->reset_gpio != -1) ++ gpio_set_value(dssdev->reset_gpio, 0); ++} ++ ++static struct omap_dss_device beagle_dvi_device = { ++ .type = OMAP_DISPLAY_TYPE_DPI, ++ .name = "dvi", ++ .driver_name = "generic_panel", ++ .phy.dpi.data_lines = 24, ++ .reset_gpio = 170, ++ .platform_enable = beagle_enable_dvi, ++ .platform_disable = beagle_disable_dvi, ++}; ++ ++static int beagle_panel_enable_tv(struct omap_dss_device *dssdev) ++{ ++ return 0; ++} ++ ++static void beagle_panel_disable_tv(struct omap_dss_device *dssdev) ++{ ++} ++ ++static struct omap_dss_device beagle_tv_device = { ++ .name = "tv", ++ .driver_name = "venc", ++ .type = OMAP_DISPLAY_TYPE_VENC, ++ .phy.venc.type = OMAP_DSS_VENC_TYPE_SVIDEO, ++ .platform_enable = beagle_panel_enable_tv, ++ .platform_disable = beagle_panel_disable_tv, ++}; ++ ++static struct omap_dss_device *beagle_dss_devices[] = { ++ &beagle_dvi_device, ++ &beagle_tv_device, ++}; ++ ++static struct omap_dss_board_info beagle_dss_data = { ++ .num_devices = ARRAY_SIZE(beagle_dss_devices), ++ .devices = beagle_dss_devices, ++ .default_device = &beagle_dvi_device, ++}; ++ ++static struct platform_device beagle_dss_device = { ++ .name = "omapdss", ++ .id = -1, ++ .dev = { ++ .platform_data = &beagle_dss_data, ++ }, ++}; ++ ++static struct regulator_consumer_supply beagle_vdda_dac_supply = { ++ .supply = "vdda_dac", ++ .dev = &beagle_dss_device.dev, ++}; ++ ++static struct regulator_consumer_supply beagle_vdds_dsi_supply = { ++ .supply = "vdds_dsi", ++ .dev = &beagle_dss_device.dev, ++}; ++ ++static void __init beagle_display_init(void) ++{ ++ int r; ++ ++ r = gpio_request(beagle_dvi_device.reset_gpio, "DVI reset"); ++ if (r < 0) { ++ printk(KERN_ERR "Unable to get DVI reset GPIO\n"); ++ return; ++ } ++ ++ gpio_direction_output(beagle_dvi_device.reset_gpio, 0); ++} ++ + #include "sdram-micron-mt46h32m32lf-6.h" + + static struct twl4030_hsmmc_info mmc[] = { +@@ -117,15 +205,6 @@ static struct twl4030_hsmmc_info mmc[] = + {} /* Terminator */ + }; + +-static struct platform_device omap3_beagle_lcd_device = { +- .name = "omap3beagle_lcd", +- .id = -1, +-}; +- +-static struct omap_lcd_config omap3_beagle_lcd_config __initdata = { +- .ctrl_name = "internal", +-}; +- + static struct regulator_consumer_supply beagle_vmmc1_supply = { + .supply = "vmmc", + }; +@@ -181,15 +260,6 @@ static struct twl4030_gpio_platform_data + .setup = beagle_twl_gpio_setup, + }; + +-static struct regulator_consumer_supply beagle_vdac_supply = { +- .supply = "vdac", +- .dev = &omap3_beagle_lcd_device.dev, +-}; +- +-static struct regulator_consumer_supply beagle_vdvi_supply = { +- .supply = "vdvi", +- .dev = &omap3_beagle_lcd_device.dev, +-}; + + /* VMMC1 for MMC1 pins CMD, CLK, DAT0..DAT3 (20 mA, plus card == max 220 mA) */ + static struct regulator_init_data beagle_vmmc1 = { +@@ -226,13 +296,14 @@ static struct regulator_init_data beagle + .constraints = { + .min_uV = 1800000, + .max_uV = 1800000, ++ .apply_uV = true, + .valid_modes_mask = REGULATOR_MODE_NORMAL + | REGULATOR_MODE_STANDBY, + .valid_ops_mask = REGULATOR_CHANGE_MODE + | REGULATOR_CHANGE_STATUS, + }, + .num_consumer_supplies = 1, +- .consumer_supplies = &beagle_vdac_supply, ++ .consumer_supplies = &beagle_vdda_dac_supply, + }; + + /* VPLL2 for digital video outputs */ +@@ -247,7 +318,7 @@ static struct regulator_init_data beagle + | REGULATOR_CHANGE_STATUS, + }, + .num_consumer_supplies = 1, +- .consumer_supplies = &beagle_vdvi_supply, ++ .consumer_supplies = &beagle_vdds_dsi_supply, + }; + + static struct twl4030_usb_data beagle_usb_data = { +@@ -340,7 +411,6 @@ static struct platform_device keys_gpio + }; + + static struct omap_board_config_kernel omap3_beagle_config[] __initdata = { +- { OMAP_TAG_LCD, &omap3_beagle_lcd_config }, + }; + + static void __init omap3_beagle_init_irq(void) +@@ -357,7 +427,7 @@ static void __init omap3_beagle_init_irq + } + + static struct platform_device *omap3_beagle_devices[] __initdata = { +- &omap3_beagle_lcd_device, ++ &beagle_dss_device, + &leds_gpio, + &keys_gpio, + }; +@@ -420,9 +490,6 @@ static void __init omap3_beagle_init(voi + omap_serial_init(); + + omap_cfg_reg(J25_34XX_GPIO170); +- gpio_request(170, "DVI_nPD"); +- /* REVISIT leave DVI powered down until it's needed ... */ +- gpio_direction_output(170, true); + + usb_musb_init(); + usb_ehci_init(&ehci_pdata); diff --git a/target/linux/omap35xx/patches-2.6.32/004-compile_fix_dispc.patch b/target/linux/omap35xx/patches-2.6.32/004-compile_fix_dispc.patch new file mode 100644 index 000000000..7b8554dd5 --- /dev/null +++ b/target/linux/omap35xx/patches-2.6.32/004-compile_fix_dispc.patch @@ -0,0 +1,13 @@ +--- a/drivers/video/omap2/dss/dispc.c 2009-11-29 18:41:44.396505079 +0100 ++++ b/drivers/video/omap2/dss/dispc.c 2009-11-09 00:19:03.466830538 +0100 +@@ -3077,8 +3077,8 @@ static void _omap_dispc_initial_config(v + REG_FLD_MOD(DISPC_CONFIG, 1, 9, 9); + + /* L3 firewall setting: enable access to OCM RAM */ +- if (cpu_is_omap24xx()) +- __raw_writel(0x402000b0, OMAP2_IO_ADDRESS(0x680050a0)); ++// if (cpu_is_omap24xx()) ++// __raw_writel(0x402000b0, OMAP2_IO_ADDRESS(0x680050a0)); + + _dispc_setup_color_conv_coef(); + diff --git a/target/linux/orion/Makefile b/target/linux/orion/Makefile index 48fe61bdc..f3a671ba7 100644 --- a/target/linux/orion/Makefile +++ b/target/linux/orion/Makefile @@ -12,7 +12,7 @@ BOARDNAME:=Marvell Orion FEATURES:=squashfs SUBTARGETS=generic harddisk -LINUX_VERSION:=2.6.30.9 +LINUX_VERSION:=2.6.30.10 include $(INCLUDE_DIR)/target.mk diff --git a/target/linux/orion/image/Makefile b/target/linux/orion/image/Makefile index 21d01a105..338af419d 100644 --- a/target/linux/orion/image/Makefile +++ b/target/linux/orion/image/Makefile @@ -1,9 +1,10 @@ # -# Copyright (C) 2008 OpenWrt.org +# Copyright (C) 2008-2009 OpenWrt.org # # This is free software, licensed under the GNU General Public License v2. # See /LICENSE for more information. # + include $(TOPDIR)/rules.mk include $(INCLUDE_DIR)/image.mk @@ -48,7 +49,25 @@ define Image/Build/Netgear endef define Image/Build/Linksys -# placeholder for the WRT350N v2 + # WRT350N v2 sysupgrade image + ( \ + dd if="${KDIR}/$2-uImage" bs=$5 conv=sync; \ + dd if="${KDIR}/root.$1" bs=64k conv=sync; \ + ) > "${BIN_DIR}/openwrt-$2-$1.img" + # WRT350N v2 webupgrade image for stock firmware + rm -rf "${TMP_DIR}/$2_webupgrade" + mkdir "${TMP_DIR}/$2_webupgrade" + # create parameter file + echo ":kernel $5 ${BIN_DIR}/openwrt-$2-uImage" >"${TMP_DIR}/$2_webupgrade/$2.par" + echo ":rootfs 0 ${KDIR}/root.$1" >>"${TMP_DIR}/$2_webupgrade/$2.par" + # create webupgrade file + ( cd "${TMP_DIR}/$2_webupgrade"; \ + "${STAGING_DIR_HOST}/bin/$2-builder" \ + -v "${TMP_DIR}/$2_webupgrade/$2.par" \ + "${BIN_DIR}/openwrt-$2-$(1)-webupgrade.img"; \ + $(CP) openwrt-$2-$(1)-webupgrade.bin $(BIN_DIR)/openwrt-$2-$(1)-recovery.bin; \ + ) + rm -rf "${TMP_DIR}/$2_webupgrade" endef define Image/Build/Freecom @@ -64,7 +83,7 @@ endef define Image/Build $(call Image/Build/$(1),$(1)) $(call Image/Build/Netgear,$(1),wnr854t,NG_WNR854T,$(1)) - $(call Image/Build/Linksys,$(1),wrt350nv2,WNR350Nv2,$(1)) + $(call Image/Build/Linksys,$(1),wrt350nv2,WNR350Nv2,$(1),1048576) # 5th parameter is kernel mtd size 0x00100000 = 1048576 / 0x001A0000 = 1703936 $(call Image/Build/Freecom,$(1),dt2,DT,$(1)) endef diff --git a/target/linux/ppc40x/Makefile b/target/linux/ppc40x/Makefile index 94c2a3bb8..910dccde3 100644 --- a/target/linux/ppc40x/Makefile +++ b/target/linux/ppc40x/Makefile @@ -12,8 +12,7 @@ BOARDNAME:=AMCC/IBM PPC40x FEATURES:=squashfs CFLAGS:=-Os -pipe -funit-at-a-time -mcpu=405 -LINUX_VERSION:=2.6.30.9 -LINUX_KARCH:=powerpc +LINUX_VERSION:=2.6.30.10 include $(INCLUDE_DIR)/target.mk diff --git a/target/linux/ppc44x/Makefile b/target/linux/ppc44x/Makefile index 6d9f59380..5b536adaf 100644 --- a/target/linux/ppc44x/Makefile +++ b/target/linux/ppc44x/Makefile @@ -12,8 +12,7 @@ BOARDNAME:=AMCC/IBM PPC44x FEATURES:=squashfs CFLAGS:=-Os -pipe -funit-at-a-time -mcpu=440 -LINUX_VERSION:=2.6.30.9 -LINUX_KARCH:=powerpc +LINUX_VERSION:=2.6.30.10 include $(INCLUDE_DIR)/target.mk diff --git a/target/linux/ps3/Makefile b/target/linux/ps3/Makefile index 79f17fb0c..e36e333cf 100644 --- a/target/linux/ps3/Makefile +++ b/target/linux/ps3/Makefile @@ -13,7 +13,7 @@ MAINTAINER:=Geoff Levand SUBTARGETS=petitboot FEATURES+=powerpc64 -LINUX_VERSION:=2.6.30.9 +LINUX_VERSION:=2.6.30.10 KERNEL_CC:= diff --git a/target/linux/pxcab/Makefile b/target/linux/pxcab/Makefile index 308c452e2..7ca7c0536 100644 --- a/target/linux/pxcab/Makefile +++ b/target/linux/pxcab/Makefile @@ -11,7 +11,7 @@ BOARD:=pxcab BOARDNAME:=PowerXCell Accelerator Board FEATURES+=powerpc64 fpu ramdisk -LINUX_VERSION:=2.6.30.9 +LINUX_VERSION:=2.6.30.10 KERNEL_CC:= diff --git a/target/linux/ramips/Makefile b/target/linux/ramips/Makefile index f391a6a43..cf094f396 100644 --- a/target/linux/ramips/Makefile +++ b/target/linux/ramips/Makefile @@ -13,7 +13,7 @@ SUBTARGETS:=rt288x rt305x CFLAGS:=-Os -pipe -mips32r2 -mtune=mips32r2 -funit-at-a-time FEATURES:=squashfs broken -LINUX_VERSION:=2.6.30.9 +LINUX_VERSION:=2.6.30.10 include $(INCLUDE_DIR)/target.mk DEFAULT_PACKAGES+=kmod-leds-gpio diff --git a/target/linux/rb532/Makefile b/target/linux/rb532/Makefile index 770a42804..e6233463a 100644 --- a/target/linux/rb532/Makefile +++ b/target/linux/rb532/Makefile @@ -11,7 +11,7 @@ BOARD:=rb532 BOARDNAME:=Mikrotik RouterBoard 532 FEATURES:=jffs2 pci tgz -LINUX_VERSION:=2.6.30.9 +LINUX_VERSION:=2.6.30.10 include $(INCLUDE_DIR)/target.mk DEFAULT_PACKAGES += hostapd-mini kmod-madwifi kmod-input-rb532 diff --git a/target/linux/rdc/Makefile b/target/linux/rdc/Makefile index 2d9d1fb83..a8ca8f856 100644 --- a/target/linux/rdc/Makefile +++ b/target/linux/rdc/Makefile @@ -11,9 +11,9 @@ BOARD:=rdc BOARDNAME:=RDC 321x FEATURES:=squashfs jffs2 pci usb pcmcia CFLAGS:=-Os -pipe -march=i486 -funit-at-a-time -SUBTARGETS:=amit ar525w r8610 dir-450 sitecom +SUBTARGETS:=amit ar525w r8610 dir-450 sitecom bifferboard -LINUX_VERSION:=2.6.30.9 +LINUX_VERSION:=2.6.30.10 include $(INCLUDE_DIR)/target.mk @@ -25,7 +25,3 @@ define Target/Description endef $(eval $(call BuildTarget)) - -$(eval $(call RequireCommand,lzma, \ - Please install lzma-4.4x. \ -)) diff --git a/target/linux/rdc/base-files/etc/preinit.arch b/target/linux/rdc/base-files/etc/preinit.arch index 8f21b1f9e..fd456f8b2 100644 --- a/target/linux/rdc/base-files/etc/preinit.arch +++ b/target/linux/rdc/base-files/etc/preinit.arch @@ -1,8 +1,23 @@ -# Copyright (C) 2008 OpenWrt.org +# Copyright (C) 2009 OpenWrt.org -ash -c ". /etc/functions.sh -hdr=\$(find_mtd_part productinfo) -[ \$(find_mtd_part productinfo_parthdr) ] || rev=reverse -[ \"\$hdr\" ] && mac=\$(hexdump -n 6 -e '6/1 \",0x%X\"' \$hdr |cut -c2-) -[ \"\$mac\" = \"0x0,0x0,0x0,0x0,0x0,0x0\" ] && unset mac -[ \"\$mac\" ] && insmod r6040 \$rev mac_base=\$mac" +. /etc/functions.sh + +insmod r6040 + +kernel=$(grep magic /proc/mtd | awk -F: '{print $1}') +[ -n $kernel ] && hdr=$(dd if=/dev/$kernel count=4 bs=1 2> /dev/null) +[ "$hdr" = "CSYS" ] && config=$(find_mtd_part config) +if [ -n "$config" ]; then + mac0=$(hexdump -n 6 -e '6/1 ":%X"' -s 24583 $config | cut -c2-) + [ "$mac0" = "FF:FF:FF:FF:FF:FF" -o "$mac0" = "0:0:0:0:0:0" ] && unset mac0 + mac1=$(hexdump -n 6 -e '6/1 ":%X"' -s 24589 $config | cut -c2-) + [ "$mac1" = "FF:FF:FF:FF:FF:FF" -o "$mac0" = "0:0:0:0:0:0" ] && unset mac1 +fi +if [ -n $mac0 ]; then + logger -t kernel -p user.info "r6040: Setting MAC for eth0 to $mac0" + ifconfig eth0 hw ether $mac0 +fi +if [ -n $mac1 ]; then + logger -t kernel -p user.info "r6040: Setting MAC for eth1 to $mac1" + ifconfig eth1 hw ether $mac1 +fi diff --git a/target/linux/rdc/bifferboard/config-2.6.30 b/target/linux/rdc/bifferboard/config-2.6.30 new file mode 100644 index 000000000..e37e74ca0 --- /dev/null +++ b/target/linux/rdc/bifferboard/config-2.6.30 @@ -0,0 +1,8 @@ +CONFIG_CMDLINE="console=ttyS0,115200 rootfstype=squashfs,jffs2" +# CONFIG_MTD_PHYSMAP is not set +CONFIG_MTD_RDC3210=y +CONFIG_MTD_RDC3210_ALLOW_JFFS2=y +CONFIG_MTD_RDC3210_BUSWIDTH=2 +# CONFIG_MTD_RDC3210_FACTORY_PRESENT is not set +CONFIG_MTD_RDC3210_SIZE=0x800000 +# CONFIG_MTD_RDC3210_STATIC_MAP is not set diff --git a/target/linux/rdc/bifferboard/target.mk b/target/linux/rdc/bifferboard/target.mk new file mode 100644 index 000000000..24dd13f5a --- /dev/null +++ b/target/linux/rdc/bifferboard/target.mk @@ -0,0 +1 @@ +BOARDNAME:=Bifferboard diff --git a/target/linux/rdc/config-2.6.28 b/target/linux/rdc/config-2.6.28 deleted file mode 100644 index 3d5a66145..000000000 --- a/target/linux/rdc/config-2.6.28 +++ /dev/null @@ -1,273 +0,0 @@ -# CONFIG_4KSTACKS is not set -# CONFIG_60XX_WDT is not set -# CONFIG_64BIT is not set -# CONFIG_8139TOO is not set -# CONFIG_ACQUIRE_WDT is not set -# CONFIG_ADVANTECH_WDT is not set -# CONFIG_AGP is not set -# CONFIG_ALIM1535_WDT is not set -CONFIG_ARCH_DEFCONFIG="arch/x86/configs/i386_defconfig" -CONFIG_ARCH_HAS_CACHE_LINE_SIZE=y -CONFIG_ARCH_HAS_CPU_IDLE_WAIT=y -CONFIG_ARCH_HAS_CPU_RELAX=y -CONFIG_ARCH_HAS_DEFAULT_IDLE=y -CONFIG_ARCH_HIBERNATION_POSSIBLE=y -CONFIG_ARCH_MAY_HAVE_PC_FDC=y -# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set -CONFIG_ARCH_POPULATES_NODE_MAP=y -CONFIG_ARCH_SELECT_MEMORY_MODEL=y -CONFIG_ARCH_SPARSEMEM_ENABLE=y -# CONFIG_ARCH_SUPPORTS_MSI is not set -CONFIG_ARCH_SUPPORTS_OPTIMIZED_INLINING=y -CONFIG_ARCH_SUSPEND_POSSIBLE=y -CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y -# CONFIG_AUDIT_ARCH is not set -# CONFIG_BINFMT_AOUT is not set -CONFIG_BITREVERSE=y -CONFIG_BLK_DEV_RAM_COUNT=16 -CONFIG_BLK_DEV_RAM_SIZE=4096 -CONFIG_BLK_DEV_RAM=y -CONFIG_BOUNCE=y -CONFIG_CC_OPTIMIZE_FOR_SIZE=y -CONFIG_CLASSIC_RCU=y -CONFIG_CLOCKSOURCE_WATCHDOG=y -CONFIG_CMDLINE_BOOL=y -CONFIG_CMDLINE="console=ttyS0,38400 rootfstype=squashfs,jffs2" -# CONFIG_CMDLINE_OVERRIDE is not set -# CONFIG_COMPAT_VDSO is not set -# CONFIG_CPU5_WDT is not set -# CONFIG_CPU_SUP_AMD is not set -# CONFIG_CPU_SUP_CENTAUR_32 is not set -CONFIG_CPU_SUP_CYRIX_32=y -# CONFIG_CPU_SUP_INTEL is not set -# CONFIG_CPU_SUP_TRANSMETA_32 is not set -# CONFIG_CPU_SUP_UMC_32 is not set -# CONFIG_CS5535_GPIO is not set -# CONFIG_DCDBAS is not set -CONFIG_DEFAULT_IO_DELAY_TYPE=0 -# CONFIG_DELL_RBU is not set -CONFIG_DEVPORT=y -# CONFIG_DMI is not set -CONFIG_DOUBLEFAULT=y -# CONFIG_EARLY_PRINTK_DBGP is not set -CONFIG_EARLY_PRINTK=y -# CONFIG_EDAC is not set -# CONFIG_EDD is not set -# CONFIG_EUROTECH_WDT is not set -CONFIG_FAST_CMPXCHG_LOCAL=y -CONFIG_FIRMWARE_MEMMAP=y -CONFIG_FIX_EARLYCON_MEM=y -CONFIG_GENERIC_BUG=y -CONFIG_GENERIC_CLOCKEVENTS_BUILD=y -CONFIG_GENERIC_CLOCKEVENTS=y -CONFIG_GENERIC_CMOS_UPDATE=y -# CONFIG_GENERIC_CPU is not set -CONFIG_GENERIC_FIND_FIRST_BIT=y -CONFIG_GENERIC_FIND_NEXT_BIT=y -CONFIG_GENERIC_IOMAP=y -CONFIG_GENERIC_ISA_DMA=y -# CONFIG_GENERIC_TIME_VSYSCALL is not set -# CONFIG_GEN_RTC is not set -# CONFIG_HANGCHECK_TIMER is not set -CONFIG_HAS_DMA=y -CONFIG_HAS_IOMEM=y -CONFIG_HAS_IOPORT=y -CONFIG_HAVE_AOUT=y -CONFIG_HAVE_ARCH_KGDB=y -CONFIG_HAVE_ARCH_TRACEHOOK=y -CONFIG_HAVE_ATOMIC_IOMAP=y -# CONFIG_HAVE_CPUMASK_OF_CPU_MAP is not set -CONFIG_HAVE_DYNAMIC_FTRACE=y -CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y -CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y -CONFIG_HAVE_FUNCTION_TRACER=y -CONFIG_HAVE_GENERIC_DMA_COHERENT=y -CONFIG_HAVE_IDE=y -CONFIG_HAVE_IOREMAP_PROT=y -CONFIG_HAVE_KPROBES=y -CONFIG_HAVE_KRETPROBES=y -CONFIG_HAVE_KVM=y -CONFIG_HAVE_LATENCYTOP_SUPPORT=y -CONFIG_HAVE_OPROFILE=y -# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set -CONFIG_HAVE_UNSTABLE_SCHED_CLOCK=y -# CONFIG_HIGHMEM4G is not set -# CONFIG_HIGHMEM64G is not set -# CONFIG_HIGH_RES_TIMERS is not set -# CONFIG_HPET_TIMER is not set -# CONFIG_HP_WATCHDOG is not set -CONFIG_HUGETLBFS=y -CONFIG_HUGETLB_PAGE=y -# CONFIG_HW_RANDOM_AMD is not set -# CONFIG_HW_RANDOM_GEODE is not set -# CONFIG_HW_RANDOM_INTEL is not set -# CONFIG_HW_RANDOM_VIA is not set -CONFIG_HW_RANDOM=y -# CONFIG_HZ_100 is not set -CONFIG_HZ=250 -CONFIG_HZ_250=y -# CONFIG_I6300ESB_WDT is not set -# CONFIG_I8K is not set -# CONFIG_IB700_WDT is not set -# CONFIG_IBMASR is not set -# CONFIG_IDE is not set -CONFIG_INITRAMFS_SOURCE="" -CONFIG_IO_DELAY_0X80=y -# CONFIG_IO_DELAY_0XED is not set -# CONFIG_IO_DELAY_NONE is not set -CONFIG_IO_DELAY_TYPE_0X80=0 -CONFIG_IO_DELAY_TYPE_0XED=1 -CONFIG_IO_DELAY_TYPE_NONE=3 -CONFIG_IO_DELAY_TYPE_UDELAY=2 -# CONFIG_IO_DELAY_UDELAY is not set -# CONFIG_IOMMU_HELPER is not set -CONFIG_ISA_DMA_API=y -# CONFIG_ISA is not set -# CONFIG_ISCSI_IBFT_FIND is not set -# CONFIG_IT8712F_WDT is not set -# CONFIG_IT87_WDT is not set -# CONFIG_ITCO_WDT is not set -# CONFIG_KERNEL_BZIP2 is not set -# CONFIG_KERNEL_GZIP is not set -CONFIG_KERNEL_LZMA=y -CONFIG_KTIME_SCALAR=y -CONFIG_LBD=y -# CONFIG_LEDS_TRIGGER_HEARTBEAT is not set -# CONFIG_LEDS_TRIGGER_NETDEV is not set -# CONFIG_LEDS_TRIGGER_TIMER is not set -CONFIG_LSF=y -# CONFIG_M386 is not set -CONFIG_M486=y -# CONFIG_M586 is not set -# CONFIG_M586MMX is not set -# CONFIG_M586TSC is not set -# CONFIG_M686 is not set -# CONFIG_MACHZ_WDT is not set -# CONFIG_MACINTOSH_DRIVERS is not set -CONFIG_MATH_EMULATION=y -# CONFIG_MCA is not set -# CONFIG_MCORE2 is not set -# CONFIG_MCRUSOE is not set -# CONFIG_MCYRIXIII is not set -# CONFIG_MEFFICEON is not set -# CONFIG_MEMTEST is not set -# CONFIG_MGEODEGX1 is not set -# CONFIG_MGEODE_LX is not set -# CONFIG_MICROCODE is not set -# CONFIG_MK6 is not set -# CONFIG_MK7 is not set -# CONFIG_MK8 is not set -CONFIG_MODULE_FORCE_UNLOAD=y -# CONFIG_MPENTIUM4 is not set -# CONFIG_MPENTIUMIII is not set -# CONFIG_MPENTIUMII is not set -# CONFIG_MPENTIUMM is not set -# CONFIG_MPSC is not set -# CONFIG_MTD_CFI_INTELEXT is not set -CONFIG_MTD_CMDLINE_PARTS=y -# CONFIG_MTD_COMPLEX_MAPPINGS is not set -CONFIG_MTD_CONCAT=y -# CONFIG_MTD_NETSC520 is not set -CONFIG_MTD_PHYSMAP_BANKWIDTH=2 -CONFIG_MTD_PHYSMAP_LEN=0 -CONFIG_MTD_PHYSMAP_START=0x8000000 -CONFIG_MTD_PHYSMAP=y -# CONFIG_MTD_R8610 is not set -# CONFIG_MTD_RDC3210 is not set -# CONFIG_MTD_SC520CDP is not set -# CONFIG_MTD_TS5500 is not set -# CONFIG_MTRR is not set -# CONFIG_MVIAC3_2 is not set -# CONFIG_MVIAC7 is not set -# CONFIG_MWINCHIP3D is not set -# CONFIG_MWINCHIPC6 is not set -CONFIG_NOHIGHMEM=y -# CONFIG_NSC_GPIO is not set -# CONFIG_OLPC is not set -# CONFIG_OPTIMIZE_INLINING is not set -CONFIG_PAGEFLAGS_EXTENDED=y -CONFIG_PAGE_OFFSET=0xC0000000 -# CONFIG_PARAVIRT_GUEST is not set -# CONFIG_PC8736x_GPIO is not set -# CONFIG_PC87413_WDT is not set -CONFIG_PCI_BIOS=y -CONFIG_PCI_DIRECT=y -CONFIG_PCI_DOMAINS=y -# CONFIG_PCIEPORTBUS is not set -CONFIG_PCI_GOANY=y -# CONFIG_PCI_GOBIOS is not set -# CONFIG_PCI_GODIRECT is not set -# CONFIG_PCI_GOMMCONFIG is not set -# CONFIG_PCI_GOOLPC is not set -CONFIG_PHYSICAL_ALIGN=0x100000 -CONFIG_PHYSICAL_START=0x100000 -CONFIG_PROCESSOR_SELECT=y -# CONFIG_PROVIDE_OHCI1394_DMA_INIT is not set -# CONFIG_R6040 is not set -# CONFIG_RD_BZIP2 is not set -# CONFIG_RDC321X_WDT is not set -CONFIG_RD_GZIP=y -# CONFIG_RD_LZMA is not set -# CONFIG_RELOCATABLE is not set -# CONFIG_RTC is not set -# CONFIG_RWSEM_GENERIC_SPINLOCK is not set -CONFIG_RWSEM_XCHGADD_ALGORITHM=y -# CONFIG_SBC7240_WDT is not set -# CONFIG_SBC8360_WDT is not set -# CONFIG_SBC_EPX_C3_WATCHDOG is not set -# CONFIG_SC1200_WDT is not set -# CONFIG_SC520_WDT is not set -# CONFIG_SCHED_HRTICK is not set -CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y -# CONFIG_SCSI_DMA is not set -# CONFIG_SCx200 is not set -# CONFIG_SERIAL_8250_EXTENDED is not set -# CONFIG_SMSC37B787_WDT is not set -CONFIG_SPARSEMEM_STATIC=y -# CONFIG_STRICT_DEVMEM is not set -# CONFIG_SYSPROF_TRACER is not set -# CONFIG_TELCLOCK is not set -# CONFIG_TOSHIBA is not set -CONFIG_UID16=y -CONFIG_USB_SUPPORT=y -# CONFIG_VGASTATE is not set -# CONFIG_VIA_RHINE is not set -# CONFIG_VM86 is not set -CONFIG_VM_EVENT_COUNTERS=y -# CONFIG_VMSPLIT_2G_OPT is not set -# CONFIG_VMSPLIT_3G_OPT is not set -# CONFIG_W83697UG_WDT is not set -# CONFIG_WAFER_WDT is not set -CONFIG_X86_32=y -# CONFIG_X86_64 is not set -CONFIG_X86_ALIGNMENT_16=y -CONFIG_X86_BIOS_REBOOT=y -CONFIG_X86_BSWAP=y -# CONFIG_X86_CHECK_BIOS_CORRUPTION is not set -CONFIG_X86_CMPXCHG=y -# CONFIG_X86_CPUID is not set -CONFIG_X86_CPU=y -# CONFIG_X86_ELAN is not set -CONFIG_X86_F00F_BUG=y -# CONFIG_X86_GENERICARCH is not set -# CONFIG_X86_GENERIC is not set -CONFIG_X86_INVLPG=y -CONFIG_X86_L1_CACHE_SHIFT=4 -# CONFIG_X86_MCE is not set -CONFIG_X86_MINIMUM_CPU_FAMILY=4 -# CONFIG_X86_MSR is not set -# CONFIG_X86_PAE is not set -CONFIG_X86_PC=y -CONFIG_X86_POPAD_OK=y -# CONFIG_X86_PPRO_FENCE is not set -CONFIG_X86_RDC321X=y -CONFIG_X86_REBOOTFIXUPS=y -# CONFIG_X86_RESERVE_LOW_64K is not set -# CONFIG_X86_UP_APIC is not set -# CONFIG_X86_VERBOSE_BOOTUP is not set -# CONFIG_X86_VOYAGER is not set -# CONFIG_X86_VSMP is not set -CONFIG_X86_WP_WORKS_OK=y -CONFIG_X86_XADD=y -CONFIG_X86=y -# CONFIG_ZONE_DMA32 is not set diff --git a/target/linux/rdc/config-2.6.30 b/target/linux/rdc/config-2.6.30 index 0113a58db..52a5d0722 100644 --- a/target/linux/rdc/config-2.6.30 +++ b/target/linux/rdc/config-2.6.30 @@ -75,6 +75,10 @@ CONFIG_GENERIC_CMOS_UPDATE=y CONFIG_GENERIC_FIND_FIRST_BIT=y CONFIG_GENERIC_FIND_LAST_BIT=y CONFIG_GENERIC_FIND_NEXT_BIT=y +CONFIG_GENERIC_GPIO=y +CONFIG_GPIOLIB=y +CONFIG_GPIO_SYSFS=y +CONFIG_LEDS_GPIO=y CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y CONFIG_GENERIC_IOMAP=y CONFIG_GENERIC_ISA_DMA=y diff --git a/target/linux/rdc/files-2.6.30/arch/x86/include/asm/rdc321x_gpio.h b/target/linux/rdc/files-2.6.30/arch/x86/include/asm/rdc321x_gpio.h index 873bffe30..adb75aff2 100644 --- a/target/linux/rdc/files-2.6.30/arch/x86/include/asm/rdc321x_gpio.h +++ b/target/linux/rdc/files-2.6.30/arch/x86/include/asm/rdc321x_gpio.h @@ -3,55 +3,12 @@ #include -extern int rdc_gpio_get_value(unsigned gpio); -extern void rdc_gpio_set_value(unsigned gpio, int value); -extern int rdc_gpio_direction_input(unsigned gpio); -extern int rdc_gpio_direction_output(unsigned gpio, int value); -extern int rdc_gpio_request(unsigned gpio, const char *label); -extern void rdc_gpio_free(unsigned gpio); +#define gpio_to_irq(gpio) NULL -/* Wrappers for the arch-neutral GPIO API */ +#define gpio_get_value __gpio_get_value +#define gpio_set_value __gpio_set_value -static inline int gpio_request(unsigned gpio, const char *label) -{ - return rdc_gpio_request(gpio, label); -} - -static inline void gpio_free(unsigned gpio) -{ - might_sleep(); - rdc_gpio_free(gpio); -} - -static inline int gpio_direction_input(unsigned gpio) -{ - return rdc_gpio_direction_input(gpio); -} - -static inline int gpio_direction_output(unsigned gpio, int value) -{ - return rdc_gpio_direction_output(gpio, value); -} - -static inline int gpio_get_value(unsigned gpio) -{ - return rdc_gpio_get_value(gpio); -} - -static inline void gpio_set_value(unsigned gpio, int value) -{ - rdc_gpio_set_value(gpio, value); -} - -static inline int gpio_to_irq(unsigned gpio) -{ - return gpio; -} - -static inline int irq_to_gpio(unsigned irq) -{ - return irq; -} +#define gpio_cansleep __gpio_cansleep /* For cansleep */ #include diff --git a/target/linux/rdc/files-2.6.30/arch/x86/mach-rdc321x/gpio.c b/target/linux/rdc/files-2.6.30/arch/x86/mach-rdc321x/gpio.c index 92df2201d..c99b3b223 100644 --- a/target/linux/rdc/files-2.6.30/arch/x86/mach-rdc321x/gpio.c +++ b/target/linux/rdc/files-2.6.30/arch/x86/mach-rdc321x/gpio.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include @@ -38,9 +39,6 @@ static DEFINE_SPINLOCK(gpio_lock); static u32 gpio_data_reg1; static u32 gpio_data_reg2; -static u32 gpio_request_data[2]; - - static inline void rdc321x_conf_write(unsigned addr, u32 value) { outl((1 << 31) | (7 << 11) | addr, RDC3210_CFGREG_ADDR); @@ -73,63 +71,8 @@ static void rdc321x_configure_gpio(unsigned gpio) spin_unlock_irqrestore(&gpio_lock, flags); } -/* initially setup the 2 copies of the gpio data registers. - This function is called before the platform setup code. */ -static int __init rdc321x_gpio_setup(void) -{ - /* this might not be, what others (BIOS, bootloader, etc.) - wrote to these registers before, but it's a good guess. Still - better than just using 0xffffffff. */ - - gpio_data_reg1 = rdc321x_conf_read(RDC321X_GPIO_DATA_REG1); - gpio_data_reg2 = rdc321x_conf_read(RDC321X_GPIO_DATA_REG2); - - return 0; -} - -/* determine, if gpio number is valid */ -static inline int rdc321x_is_gpio(unsigned gpio) -{ - return gpio <= RDC321X_MAX_GPIO; -} - -/* request GPIO */ -int rdc_gpio_request(unsigned gpio, const char *label) -{ - unsigned long flags; - - if (!rdc321x_is_gpio(gpio)) - return -EINVAL; - - spin_lock_irqsave(&gpio_lock, flags); - if (gpio_request_data[(gpio & 0x20) ? 1 : 0] & (1 << (gpio & 0x1f))) - goto inuse; - gpio_request_data[(gpio & 0x20) ? 1 : 0] |= (1 << (gpio & 0x1f)); - spin_unlock_irqrestore(&gpio_lock, flags); - - return 0; -inuse: - spin_unlock_irqrestore(&gpio_lock, flags); - return -EINVAL; -} -EXPORT_SYMBOL(rdc_gpio_request); - -/* release previously-claimed GPIO */ -void rdc_gpio_free(unsigned gpio) -{ - unsigned long flags; - - if (!rdc321x_is_gpio(gpio)) - return; - - spin_lock_irqsave(&gpio_lock, flags); - gpio_request_data[(gpio & 0x20) ? 1 : 0] &= ~(1 << (gpio & 0x1f)); - spin_unlock_irqrestore(&gpio_lock, flags); -} -EXPORT_SYMBOL(rdc_gpio_free); - /* read GPIO pin */ -int rdc_gpio_get_value(unsigned gpio) +static int rdc_gpio_get_value(struct gpio_chip *chip, unsigned gpio) { u32 reg; unsigned long flags; @@ -141,10 +84,10 @@ int rdc_gpio_get_value(unsigned gpio) return (1 << (gpio & 0x1f)) & reg ? 1 : 0; } -EXPORT_SYMBOL(rdc_gpio_get_value); /* set GPIO pin to value */ -void rdc_gpio_set_value(unsigned gpio, int value) +static void rdc_gpio_set_value(struct gpio_chip *chip, + unsigned gpio, int value) { unsigned long flags; u32 reg; @@ -168,31 +111,48 @@ void rdc_gpio_set_value(unsigned gpio, int value) spin_unlock_irqrestore(&gpio_lock, flags); } } -EXPORT_SYMBOL(rdc_gpio_set_value); /* configure GPIO pin as input */ -int rdc_gpio_direction_input(unsigned gpio) +static int rdc_gpio_direction_input(struct gpio_chip *chip, unsigned gpio) { - if (!rdc321x_is_gpio(gpio)) - return -EINVAL; - rdc321x_configure_gpio(gpio); return 0; } -EXPORT_SYMBOL(rdc_gpio_direction_input); /* configure GPIO pin as output and set value */ -int rdc_gpio_direction_output(unsigned gpio, int value) +static int rdc_gpio_direction_output(struct gpio_chip *chip, + unsigned gpio, int value) { - if (!rdc321x_is_gpio(gpio)) - return -EINVAL; - - gpio_set_value(gpio, value); rdc321x_configure_gpio(gpio); + gpio_set_value(gpio, value); return 0; } -EXPORT_SYMBOL(rdc_gpio_direction_output); + +static struct gpio_chip rdc321x_gpio_chip = { + .label = "rdc321x-gpio", + .direction_input = rdc_gpio_direction_input, + .direction_output = rdc_gpio_direction_output, + .get = rdc_gpio_get_value, + .set = rdc_gpio_set_value, + .base = 0, + .ngpio = RDC321X_MAX_GPIO, +}; + +/* initially setup the 2 copies of the gpio data registers. + This function is called before the platform setup code. */ +static int __init rdc321x_gpio_setup(void) +{ + /* this might not be, what others (BIOS, bootloader, etc.) + wrote to these registers before, but it's a good guess. Still + better than just using 0xffffffff. */ + + gpio_data_reg1 = rdc321x_conf_read(RDC321X_GPIO_DATA_REG1); + gpio_data_reg2 = rdc321x_conf_read(RDC321X_GPIO_DATA_REG2); + + printk(KERN_INFO "rdc321x: registering %d GPIOs\n", rdc321x_gpio_chip.ngpio); + return gpiochip_add(&rdc321x_gpio_chip); +} arch_initcall(rdc321x_gpio_setup); diff --git a/target/linux/rdc/files-2.6.30/arch/x86/mach-rdc321x/platform.c b/target/linux/rdc/files-2.6.30/arch/x86/mach-rdc321x/platform.c index e319c02b3..3c2cec721 100644 --- a/target/linux/rdc/files-2.6.30/arch/x86/mach-rdc321x/platform.c +++ b/target/linux/rdc/files-2.6.30/arch/x86/mach-rdc321x/platform.c @@ -79,7 +79,7 @@ static struct platform_device rdc_flash_device = { /* LEDS */ static struct gpio_led default_leds[] = { - { .name = "rdc321x:dmz", .gpio = 1, }, + { .name = "rdc321x:dmz", .gpio = 1, .active_low = 1}, }; static struct gpio_led_platform_data rdc321x_led_data = { @@ -161,15 +161,15 @@ static int __init rdc_board_setup(void) ROOT_DEV = 0; rdc_map_info.name = rdc_flash_device.name; - rdc_map_info.phys = 0xff000000; - rdc_map_info.size = 0x1000000; + rdc_map_info.size = 0x800000; //8MB + rdc_map_info.phys = (u32) -rdc_map_info.size; rdc_map_info.bankwidth = 2; rdc_map_info.set_vpp = NULL; simple_map_init(&rdc_map_info); while (probe_flash_start(&rdc_map_info)) { - rdc_map_info.phys++; - if (--rdc_map_info.size) + if (rdc_map_info.size /= 2 < 0x100000) //1MB panic("Could not find start of flash!"); + rdc_map_info.phys = (u32) -rdc_map_info.size; } rdc_flash_resource.start = rdc_map_info.phys; rdc_flash_data.width = rdc_map_info.bankwidth; diff --git a/target/linux/rdc/files/drivers/mtd/maps/bifferboard-flash.c b/target/linux/rdc/files/drivers/mtd/maps/bifferboard-flash.c new file mode 100644 index 000000000..e732334e9 --- /dev/null +++ b/target/linux/rdc/files/drivers/mtd/maps/bifferboard-flash.c @@ -0,0 +1,243 @@ +/* Flash mapping for Bifferboard, (c) bifferos@yahoo.co.uk + * Works with 1, 4 and 8MB flash versions + */ + +#include +#include +#include +#include + +#define DRV "bifferboard-flash: " + +static struct mtd_info *bb_mtd = NULL; + +#define SIZE_BIFFBOOT 0x10000 +#define SIZE_SECTOR 0x10000 +#define SIZE_CONFIG 0x02000 +#define SIZE_1MB 0x00100000 +#define SIZE_4MB 0x00400000 +#define SIZE_8MB 0x00800000 + +#define BASE_1MB 0xfff00000 +#define BASE_4MB 0xffc00000 +#define BASE_8MB 0xff800000 + +#define OFFS_KERNEL 0x6000 +#define OFFS_CONFIG 0x4000 + +/* + * Flash detection code. This is needed because the cfi_probe doesn't probe + * for the size correctly. You actually have to know the flash size before you + * call it, or so it seems. It does work correctly if you map the entire flash + * chip, but unsure of the implications for mapping more mem than exists. + */ + +static unsigned char ReadFlash(void* base, u32 addr) +{ + unsigned char val = *(volatile unsigned char *)(base+addr); + udelay(1); + return val; +} + +static void WriteFlash(void* base, u32 addr, unsigned short data) +{ + *(volatile unsigned short *)(base+addr) = data; +} + +static DEFINE_SPINLOCK(flash_lock); + +static u32 bb_detect(void) +{ + u32 ret = 0; + ulong flags; + + /* for detection, map in just the 1MB device, 1st 64k is enough */ + void* base = ioremap_nocache(BASE_1MB, 0x10000); + + if (!base) + { + pr_err(DRV "Failed to map flash for probing\n"); + return 0; + } + + spin_lock_irqsave(&flash_lock, flags); + + /* put flash in auto-detect mode */ + WriteFlash(base, 0xaaaa, 0xaaaa); + WriteFlash(base, 0x5554, 0x5555); + WriteFlash(base, 0xaaaa, 0x9090); + + /* Read the auto-config data - 4 values in total */ + ret = ReadFlash(base, 0x0000); ret <<= 8; + ret |= ReadFlash(base, 0x0200); ret <<= 8; + ret |= ReadFlash(base, 0x0003); ret <<= 8; + ret |= ReadFlash(base, 0x0002); + + /* exit the autodetect state */ + WriteFlash(base, 0x0000, 0xf0f0); + + spin_unlock_irqrestore(&flash_lock, flags); + + /* unmap it, it'll be re-mapped based on the detection */ + iounmap(base); + + return ret; +} + + +static struct map_info bb_map; + +/* Update the map, using the detected flash signature. */ +static int bb_adjust_map(unsigned long sig, struct map_info* m) +{ + m->bankwidth = 2; + switch (sig) + { + case 0x7f1c225b : + m->name = "ENLV800B"; + m->phys = BASE_1MB; + m->size = SIZE_1MB; + break; + case 0x7f1c22f9 : + m->name = "ENLV320B"; + m->phys = BASE_4MB; + m->size = SIZE_4MB; + break; + case 0x7f1c22cb : + m->name = "ENLV640B"; + m->phys = BASE_8MB; + m->size = SIZE_8MB; + break; + default: + return -ENXIO; + } + return 0; +} + + +/* adjust partition sizes, prior to adding the partition + * Values not specified by defines here are subject to replacement based on + * the real flash size. (0x00000000 being the exception, of course) */ + +static struct mtd_partition bb_parts[] = +{ +/* 0 */ { name: "kernel", offset: 0x00000000, size: 0x000fa000 }, +/* 1 */ { name: "rootfs", offset: MTDPART_OFS_APPEND, size: 0x002F0000 }, +/* 2 */ { name: "biffboot", offset: MTDPART_OFS_APPEND, size: MTDPART_SIZ_FULL, mask_flags: MTD_WRITEABLE }, +}; + + +/* returns the count of partitions to be used */ +static ulong bb_adjust_partitions(struct map_info* m) +{ + /* Read the kernel offset value, 1036 bytes into the config block. */ + u16 km_units = *((u16*)(m->virt + OFFS_CONFIG + 1036)); + u32 kernelmax = 0x200000; /* Biffboot 2.7 or earlier default */ + + /* special-case 1MB devices, because there are fewer partitions */ + if (m->size == SIZE_1MB) + { + bb_parts[0].size = SIZE_1MB - SIZE_BIFFBOOT; /* kernel */ + bb_parts[1].name = "biffboot"; /* biffboot */ + bb_parts[1].offset = MTDPART_OFS_APPEND; /* biffboot */ + bb_parts[1].size = MTDPART_SIZ_FULL; /* biffboot */ + bb_parts[1].mask_flags = MTD_WRITEABLE; + return 2; /* because there's no rootfs now */ + } + + /* sanity check */ + if (km_units > ((m->size-SIZE_BIFFBOOT)/SIZE_SECTOR)) + { + pr_err(DRV "config block has invalid kernelmax\n"); + return 0; + } + + kernelmax = km_units * SIZE_SECTOR; + + /* Kernel */ + bb_parts[0].size = kernelmax; + + /* rootfs */ + bb_parts[1].size = m->size - kernelmax - SIZE_BIFFBOOT; + + return 3; /* 3 partitions */ +} + + +static int __init init_bb_map(void) +{ + int ret; + ulong signature = bb_detect(); + ulong part_len; + + if (!signature) + { + pr_err(DRV "Undetected flash chip"); + return -ENXIO; + } + + ret = bb_adjust_map(signature, &bb_map); + + if (ret) + { + pr_err(DRV "Unrecognised flash chip (signature: 0x%lx)\n", signature); + return ret; + } + + bb_map.virt = ioremap_nocache(bb_map.phys, bb_map.size); + if (!bb_map.virt) + { + pr_err(DRV "ioremap\n"); + return -EIO; + } + + bb_mtd = do_map_probe("cfi_probe", &bb_map); + if (!bb_mtd) + { + /* cfi_probe fails here for 1MB devices */ + pr_err(DRV "cfi_probe\n"); + ret = -ENXIO; + goto err; + } + + part_len = bb_adjust_partitions(&bb_map); + if (!part_len) + { + pr_err(DRV "no partitions established"); + ret = -ENXIO; + goto err2; + } + + bb_mtd->owner = THIS_MODULE; + ret = add_mtd_partitions(bb_mtd, bb_parts, part_len); + if (ret) + { + pr_err(DRV "add_mtd_partitions\n"); + ret = -ENXIO; + goto err2; + } + + return 0; + +err2: + map_destroy(bb_mtd); +err: + iounmap(bb_map.virt); + + return ret; +} + +static void __exit exit_bb_map(void) +{ + del_mtd_partitions(bb_mtd); + map_destroy(bb_mtd); + iounmap(bb_map.virt); +} + +module_init(init_bb_map); +module_exit(exit_bb_map); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Bifferos "); +MODULE_DESCRIPTION("MTD map driver for Bifferboard"); + diff --git a/target/linux/rdc/image/Makefile b/target/linux/rdc/image/Makefile index 0de6dbc25..9b4c13508 100644 --- a/target/linux/rdc/image/Makefile +++ b/target/linux/rdc/image/Makefile @@ -34,26 +34,18 @@ define Image/Build/ar525w $(STAGING_DIR_HOST)/bin/airlink -e -b 1 -j $(shell bash -c 'echo $$[$(3)]') $(KDIR)/bzImage $(KDIR)/root.$(1) $(BIN_DIR)/openwrt-$(BOARD)-$(1)-$(2)-web.img endef -define Image/Prepare/sitecom/squashfs - dd if=/dev/null of=$(KDIR)/root.tmp seek=1 bs=32k - echo -n "0123456789abcdef0123" >> $(KDIR)/root.tmp - cat $(KDIR)/bzImage $(KDIR)/root.squashfs >> $(KDIR)/root.tmp - dd if=$(KDIR)/root.tmp of=$(KDIR)/root2.tmp bs=64k conv=sync - dd if=$(KDIR)/root2.tmp of=$(KDIR)/root.squashfs bs=1 skip=$$$$(perl -we 'print((-s"$(KDIR)/bzImage")+0x8014)') - $(RM) $(KDIR)/root.tmp $(KDIR)/root2.tmp - $(call add_jffs2_mark,$(KDIR)/root.squashfs) +define Image/Postprocess/sitecom/squashfs + dd if=/dev/zero of=$(KDIR)/tmp2.img count=1 bs=32k #32k config data a start of flash + cat $(KDIR)/tmp.img >> $(KDIR)/tmp2.img + $(call prepare_generic_squashfs,$(KDIR)/tmp2.img) + dd if=$(KDIR)/tmp2.img of=$(KDIR)/tmp.img bs=32k skip=1 endef define Image/Build/sitecom - echo -ne "\0\0" >> $(KDIR)/bzImage - dd if=$(KDIR)/bzImage of=$(KDIR)/bzImage.tmp bs=4 conv=sync - dd if=$(KDIR)/bzImage.tmp of=$(KDIR)/bzImage bs=1 count=$$$$(perl -we 'print((-s"$(KDIR)/bzImage.tmp")-2)') - perl -we 'while(<>){$$$$i.=$$$$_}print pack"v",-(unpack"%v*",$$$$i)' < $(KDIR)/bzImage.tmp >> $(KDIR)/bzImage - $(RM) $(KDIR)/bzImage.tmp - $(call Image/Prepare/sitecom/$(1)) - perl -we 'print "CSYS",pack("V",-s"$(KDIR)/bzImage"),pack("V",-s"$(KDIR)/root.$(1)"),"WRRM",pack("V",-s"$(KDIR)/bzImage")' > $(BIN_DIR)/openwrt-$(BOARD)-$(1)-$(2).img - cat $(KDIR)/bzImage $(KDIR)/root.$(1) >> $(BIN_DIR)/openwrt-$(BOARD)-$(1)-$(2).img - if [ `perl -we 'print -s"$(BIN_DIR)/openwrt-$(BOARD)-$(1)-$(2).img"'` -gt $$$$((0xffff0000-0xffe08000)) ]; then mv $(BIN_DIR)/openwrt-$(BOARD)-$(1)-$(2).img $(BIN_DIR)/openwrt-$(BOARD)-$(1)-$(2).img.too_big; echo "#ERR image too big"; fi + $(TOPDIR)/target/linux/rdc/image/mkimg_sitecom.pl $(KDIR)/bzImage > $(KDIR)/tmp.img + cat $(KDIR)/root.$(1) >> $(KDIR)/tmp.img + $(call Image/Postprocess/sitecom/$(1)) + cp $(KDIR)/tmp.img $(BIN_DIR)/openwrt-$(BOARD)-$(1)-$(2).img endef define Image/Build/dir450 @@ -92,6 +84,11 @@ define Image/Build/amit $(STAGING_DIR_HOST)/bin/makeamitbin -o $(BIN_DIR)/openwrt-$(BOARD)-$(1)-ar360w3g.bin -1 ALK_ATG001 -2 Atropos linux3g $(KDIR)/bzImage ramdisk3g $(KDIR)/root.$(1) endef +define Image/Build/bifferboard + $(TOPDIR)/target/linux/rdc/image/mkimg_bifferboard.py $(KDIR)/bzImage $(KDIR)/root.$(1) $(KDIR)/tmp.img + $(CP) $(KDIR)/tmp.img $(BIN_DIR)/openwrt-$(BOARD)-$(1)-$(2).img +endef + define Image/Build/Initramfs $(CP) $(KDIR)/bzImage $(BIN_DIR)/openwrt-$(BOARD)-ramfs.bzImage endef diff --git a/target/linux/rdc/image/mkimg_bifferboard.py b/target/linux/rdc/image/mkimg_bifferboard.py new file mode 100755 index 000000000..040c46274 --- /dev/null +++ b/target/linux/rdc/image/mkimg_bifferboard.py @@ -0,0 +1,40 @@ +#!/usr/bin/env python + +""" + Create firmware for 8MB Bifferboards + Firmware does not include the config blocks + Firmware starts just after config +""" + +import struct, sys + +kernel_extent = 0x200000 +config = 0x6000 + +if __name__ == "__main__": + + if len(sys.argv) != 4: + print "usage: mkimg_bifferboard.py <64k JFFS> " + sys.exit(0) + + bzimage = sys.argv[1] + rootfs = sys.argv[2] + target = sys.argv[3] + + # Kernel first + fw = file(bzimage).read() + if len(fw) > (kernel_extent - config): + raise IOError("Kernel too large") + + # Pad up to 0x200000 + while len(fw) < (kernel_extent - config): + fw += "\xff" + + fw += file(rootfs).read() + + # Check length of total + if len(fw) > (0x800000 - 0x10000 - 0x6000): + raise IOError("Rootfs too large") + + file(target,"wb").write(fw) + print "Firmware written to '%s'" % target diff --git a/target/linux/rdc/image/mkimg_sitecom.pl b/target/linux/rdc/image/mkimg_sitecom.pl new file mode 100755 index 000000000..4dd4a398c --- /dev/null +++ b/target/linux/rdc/image/mkimg_sitecom.pl @@ -0,0 +1,17 @@ +#!/usr/bin/perl + +$bzimgsize = -s @ARGV[0]; +$padding = 4 - ($bzimgsize + 2) % 4; +if ($padding == 4) { + $padding = 0; } +open (bzimg, @ARGV[0]); +while () { $i .= $_; } +$i .= "\0"x$padding; +$i .= pack "v", -(unpack "%v*", $i); +print "CSYS"; +print pack("V", length($i)); +print pack("V", 0); +#-s @ARGV[1] +print "WRRM"; +print pack("V", length($i)); +print $i; diff --git a/target/linux/rdc/patches-2.6.28/001-rdc3210_flash_map.patch b/target/linux/rdc/patches-2.6.28/001-rdc3210_flash_map.patch deleted file mode 100644 index 2c35b841a..000000000 --- a/target/linux/rdc/patches-2.6.28/001-rdc3210_flash_map.patch +++ /dev/null @@ -1,63 +0,0 @@ ---- a/drivers/mtd/maps/Kconfig -+++ b/drivers/mtd/maps/Kconfig -@@ -112,6 +112,50 @@ config MTD_SUN_UFLASH - Sun Microsystems boardsets. This driver will require CFI support - in the kernel, so if you did not enable CFI previously, do that now. - -+config MTD_RDC3210 -+ tristate "CFI Flash device mapped on RDC3210" -+ depends on X86 && MTD_CFI && MTD_PARTITIONS -+ help -+ RDC-3210 is the flash device we find on Ralink reference board. -+ -+config MTD_RDC3210_STATIC_MAP -+ bool "Partitions on RDC3210 mapped statically" if MTD_RDC3210 -+ select MTD_RDC3210_FACTORY_PRESENT -+ help -+ The mapping driver will use the static partition map for the -+ RDC-3210 flash device. -+ -+config MTD_RDC3210_FACTORY_PRESENT -+ bool "Reserve a partition on RDC3210 for factory presets" -+ depends on MTD_RDC3210 -+ default y -+ help -+ The mapping driver will reserve a partition on the RDC-3210 flash -+ device for resetting flash contents to factory defaults. -+ -+config MTD_RDC3210_ALLOW_JFFS2 -+ bool "JFFS2 filesystem usable in a partition on RDC3210" -+ depends on MTD_RDC3210 && !MTD_RDC3210_STATIC_MAP -+ help -+ The mapping driver will align a partition on the RDC-3210 flash -+ device to an erase-block boundary so that a JFFS2 filesystem may -+ reside on it. -+ -+config MTD_RDC3210_SIZE -+ hex "Amount of flash memory on RDC3210" -+ depends on MTD_RDC3210 -+ default "0x400000" -+ help -+ Total size in bytes of the RDC-3210 flash device -+ -+config MTD_RDC3210_BUSWIDTH -+ int "Width of CFI Flash device mapped on RDC3210" -+ depends on MTD_RDC3210 -+ default "2" -+ help -+ Number of bytes addressed on the RDC-3210 flash device before -+ addressing the same chip again -+ - config MTD_SC520CDP - tristate "CFI Flash device mapped on AMD SC520 CDP" - depends on X86 && MTD_CFI && MTD_CONCAT ---- a/drivers/mtd/maps/Makefile -+++ b/drivers/mtd/maps/Makefile -@@ -27,6 +27,7 @@ obj-$(CONFIG_MTD_PHYSMAP_OF) += physmap_ - obj-$(CONFIG_MTD_PMC_MSP_EVM) += pmcmsp-flash.o - obj-$(CONFIG_MTD_PMC_MSP_RAMROOT)+= pmcmsp-ramroot.o - obj-$(CONFIG_MTD_PCMCIA) += pcmciamtd.o -+obj-$(CONFIG_MTD_RDC3210) += rdc3210.o - obj-$(CONFIG_MTD_RPXLITE) += rpxlite.o - obj-$(CONFIG_MTD_TQM8XXL) += tqm8xxl.o - obj-$(CONFIG_MTD_SA1100) += sa1100-flash.o diff --git a/target/linux/rdc/patches-2.6.28/002-platform_support.patch b/target/linux/rdc/patches-2.6.28/002-platform_support.patch deleted file mode 100644 index bb2c7cb3a..000000000 --- a/target/linux/rdc/patches-2.6.28/002-platform_support.patch +++ /dev/null @@ -1,334 +0,0 @@ -Index: linux-2.6.28.10/arch/x86/mach-rdc321x/gpio.c -=================================================================== ---- linux-2.6.28.10.orig/arch/x86/mach-rdc321x/gpio.c 2009-11-03 21:01:29.800401126 -0800 -+++ linux-2.6.28.10/arch/x86/mach-rdc321x/gpio.c 2009-11-03 21:01:32.164401226 -0800 -@@ -26,7 +26,7 @@ - #include - #include - --#include -+#include - #include - - -@@ -74,8 +74,8 @@ - } - - /* initially setup the 2 copies of the gpio data registers. -- This function must be called by the platform setup code. */ --void __init rdc321x_gpio_setup() -+ This function is called before the platform setup code. */ -+static int __init rdc321x_gpio_setup(void) - { - /* this might not be, what others (BIOS, bootloader, etc.) - wrote to these registers before, but it's a good guess. Still -@@ -83,6 +83,8 @@ - - gpio_data_reg1 = rdc321x_conf_read(RDC321X_GPIO_DATA_REG1); - gpio_data_reg2 = rdc321x_conf_read(RDC321X_GPIO_DATA_REG2); -+ -+ return 0; - } - - /* determine, if gpio number is valid */ -@@ -192,3 +194,5 @@ - return 0; - } - EXPORT_SYMBOL(rdc_gpio_direction_output); -+ -+arch_initcall(rdc321x_gpio_setup); -Index: linux-2.6.28.10/arch/x86/mach-rdc321x/platform.c -=================================================================== ---- linux-2.6.28.10.orig/arch/x86/mach-rdc321x/platform.c 2009-11-03 21:01:29.836402559 -0800 -+++ linux-2.6.28.10/arch/x86/mach-rdc321x/platform.c 2009-11-03 21:13:27.212398945 -0800 -@@ -1,7 +1,9 @@ - /* - * Generic RDC321x platform devices - * -+ * Copyright (C) 2007-2008 OpenWrt.org - * Copyright (C) 2007 Florian Fainelli -+ * Copyright (C) 2008 Daniel Gimpelevich - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License -@@ -25,13 +27,59 @@ - #include - #include - #include -+#include - #include -+#include -+#include -+#include -+#include -+#include -+#include - --#include -+#include -+ -+/* Flash */ -+#ifdef CONFIG_MTD_R8610 -+#define CONFIG_MTD_RDC3210 1 -+#elif defined CONFIG_MTD_RDC3210 -+static struct resource rdc_flash_resource[] = { -+ [0] = { -+ .start = (u32)-CONFIG_MTD_RDC3210_SIZE, -+ .end = (u32)-1, -+ .flags = IORESOURCE_MEM, -+ }, -+}; -+ -+static struct platform_device rdc_flash_device = { -+ .name = "rdc321x-flash", -+ .id = -1, -+ .num_resources = ARRAY_SIZE(rdc_flash_resource), -+ .resource = rdc_flash_resource, -+}; -+#else -+static struct mtd_partition rdc_flash_parts[15]; -+ -+static struct resource rdc_flash_resource = { -+ .end = (u32)-1, -+ .flags = IORESOURCE_MEM, -+}; -+ -+static struct physmap_flash_data rdc_flash_data = { -+ .parts = rdc_flash_parts, -+}; -+ -+static struct platform_device rdc_flash_device = { -+ .name = "physmap-flash", -+ .id = -1, -+ .resource = &rdc_flash_resource, -+ .num_resources = 1, -+ .dev.platform_data = &rdc_flash_data, -+}; -+#endif - - /* LEDS */ - static struct gpio_led default_leds[] = { -- { .name = "rdc:dmz", .gpio = 1, }, -+ { .name = "rdc321x:dmz", .gpio = 1, }, - }; - - static struct gpio_led_platform_data rdc321x_led_data = { -@@ -54,16 +102,189 @@ - .num_resources = 0, - }; - -+/* Button */ -+static struct gpio_keys_button rdc321x_gpio_btn[] = { -+ { -+ .gpio = 0, -+ .code = BTN_0, -+ .desc = "Reset", -+ .active_low = 1, -+ } -+}; -+ -+static struct gpio_keys_platform_data rdc321x_gpio_btn_data = { -+ .buttons = rdc321x_gpio_btn, -+ .nbuttons = ARRAY_SIZE(rdc321x_gpio_btn), -+}; -+ -+static struct platform_device rdc321x_button = { -+ .name = "gpio-keys", -+ .id = -1, -+ .dev = { -+ .platform_data = &rdc321x_gpio_btn_data, -+ } -+}; -+ - static struct platform_device *rdc321x_devs[] = { -+ &rdc_flash_device, - &rdc321x_leds, -- &rdc321x_wdt -+ &rdc321x_wdt, -+ &rdc321x_button, - }; - -+static int probe_flash_start(struct map_info *the_map) -+{ -+ struct mtd_info *res; -+ -+ the_map->virt = ioremap(the_map->phys, the_map->size); -+ if (the_map->virt == NULL) -+ return 1; -+ for (the_map->bankwidth = 32; the_map->bankwidth; the_map->bankwidth -+ >>= 1) { -+ res = do_map_probe("cfi_probe", the_map); -+ if (res == NULL) -+ res = do_map_probe("jedec_probe", the_map); -+ if (res != NULL) -+ break; -+ } -+ iounmap(the_map->virt); -+ if (res != NULL) -+ the_map->phys = (u32)-(s32)(the_map->size = res->size); -+ return res == NULL; -+} -+ - static int __init rdc_board_setup(void) - { -- rdc321x_gpio_setup(); -+#ifndef CONFIG_MTD_RDC3210 -+ struct map_info rdc_map_info; -+ u32 the_header[8]; - -+ ROOT_DEV = 0; -+ rdc_map_info.name = rdc_flash_device.name; -+ rdc_map_info.phys = 0xff000000; -+ rdc_map_info.size = 0x1000000; -+ rdc_map_info.bankwidth = 2; -+ rdc_map_info.set_vpp = NULL; -+ simple_map_init(&rdc_map_info); -+ while (probe_flash_start(&rdc_map_info)) { -+ rdc_map_info.phys++; -+ if (--rdc_map_info.size) -+ panic("Could not find start of flash!"); -+ } -+ rdc_flash_resource.start = rdc_map_info.phys; -+ rdc_flash_data.width = rdc_map_info.bankwidth; -+ rdc_map_info.virt = ioremap_nocache(rdc_map_info.phys, 0x10); -+ if (rdc_map_info.virt == NULL) -+ panic("Could not ioremap to read device magic!"); -+ the_header[0] = ((u32 *)rdc_map_info.virt)[0]; -+ the_header[1] = ((u32 *)rdc_map_info.virt)[1]; -+ the_header[2] = ((u32 *)rdc_map_info.virt)[2]; -+ the_header[3] = ((u32 *)rdc_map_info.virt)[3]; -+ iounmap(rdc_map_info.virt); -+ rdc_map_info.virt = ioremap_nocache(rdc_map_info.phys + 0x8000, 0x10); -+ if (rdc_map_info.virt == NULL) -+ panic("Could not ioremap to read device magic!"); -+ the_header[4] = ((u32 *)rdc_map_info.virt)[0]; -+ the_header[5] = ((u32 *)rdc_map_info.virt)[1]; -+ the_header[6] = ((u32 *)rdc_map_info.virt)[2]; -+ the_header[7] = ((u32 *)rdc_map_info.virt)[3]; -+ iounmap(rdc_map_info.virt); -+ if (!memcmp(the_header, "GMTK", 4)) { /* Gemtek */ -+ /* TODO */ -+ } else if (!memcmp(the_header + 4, "CSYS", 4)) { /* Sitecom */ -+ rdc_flash_parts[0].name = "system"; -+ rdc_flash_parts[0].offset = 0; -+ rdc_flash_parts[0].size = rdc_map_info.size - 0x10000; -+ rdc_flash_parts[1].name = "config"; -+ rdc_flash_parts[1].offset = 0; -+ rdc_flash_parts[1].size = 0x8000; -+ rdc_flash_parts[2].name = "magic"; -+ rdc_flash_parts[2].offset = 0x8000; -+ rdc_flash_parts[2].size = 0x14; -+ rdc_flash_parts[3].name = "kernel"; -+ rdc_flash_parts[3].offset = 0x8014; -+ rdc_flash_parts[3].size = the_header[5]; -+ rdc_flash_parts[4].name = "rootfs"; -+ rdc_flash_parts[4].offset = 0x8014 + the_header[5]; -+ rdc_flash_parts[4].size = rdc_flash_parts[0].size - rdc_flash_parts[4].offset; -+ rdc_flash_parts[5].name = "bootloader"; -+ rdc_flash_parts[5].offset = rdc_flash_parts[0].size; -+ rdc_flash_parts[5].size = 0x10000; -+ rdc_flash_data.nr_parts = 6; -+ } else if (!memcmp(((u8 *)the_header) + 14, "Li", 2)) { /* AMIT */ -+ rdc_flash_parts[0].name = "kernel_parthdr"; -+ rdc_flash_parts[0].offset = 0; -+ rdc_flash_parts[0].size = 0x10; -+ rdc_flash_parts[1].name = "kernel"; -+ rdc_flash_parts[1].offset = 0x10; -+ rdc_flash_parts[1].size = 0xffff0; -+ rdc_flash_parts[2].name = "rootfs_parthdr"; -+ rdc_flash_parts[2].offset = 0x100000; -+ rdc_flash_parts[2].size = 0x10; -+ rdc_flash_parts[3].name = "rootfs"; -+ rdc_flash_parts[3].offset = 0x100010; -+ rdc_flash_parts[3].size = rdc_map_info.size - 0x160010; -+ rdc_flash_parts[4].name = "config_parthdr"; -+ rdc_flash_parts[4].offset = rdc_map_info.size - 0x60000; -+ rdc_flash_parts[4].size = 0x10; -+ rdc_flash_parts[5].name = "config"; -+ rdc_flash_parts[5].offset = rdc_map_info.size - 0x5fff0; -+ rdc_flash_parts[5].size = 0xfff0; -+ rdc_flash_parts[6].name = "recoveryfs_parthdr"; -+ rdc_flash_parts[6].offset = rdc_map_info.size - 0x50000; -+ rdc_flash_parts[6].size = 0x10; -+ rdc_flash_parts[7].name = "recoveryfs"; -+ rdc_flash_parts[7].offset = rdc_map_info.size - 0x4fff0; -+ rdc_flash_parts[7].size = 0x3fff0; -+ rdc_flash_parts[8].name = "recovery_parthdr"; -+ rdc_flash_parts[8].offset = rdc_map_info.size - 0x10000; -+ rdc_flash_parts[8].size = 0x10; -+ rdc_flash_parts[9].name = "recovery"; -+ rdc_flash_parts[9].offset = rdc_map_info.size - 0xfff0; -+ rdc_flash_parts[9].size = 0x7ff0; -+ rdc_flash_parts[10].name = "productinfo_parthdr"; -+ rdc_flash_parts[10].offset = rdc_map_info.size - 0x8000; -+ rdc_flash_parts[10].size = 0x10; -+ rdc_flash_parts[11].name = "productinfo"; -+ rdc_flash_parts[11].offset = rdc_map_info.size - 0x7ff0; -+ rdc_flash_parts[11].size = 0x1ff0; -+ rdc_flash_parts[12].name = "bootloader_parthdr"; -+ rdc_flash_parts[12].offset = rdc_map_info.size - 0x6000; -+ rdc_flash_parts[12].size = 0x10; -+ rdc_flash_parts[13].name = "bootloader"; -+ rdc_flash_parts[13].offset = rdc_map_info.size - 0x5ff0; -+ rdc_flash_parts[13].size = 0x5ff0; -+ rdc_flash_parts[14].name = "everything"; -+ rdc_flash_parts[14].offset = 0; -+ rdc_flash_parts[14].size = rdc_map_info.size; -+ rdc_flash_data.nr_parts = 15; -+ } else { /* ZyXEL */ -+ rdc_flash_parts[0].name = "kernel"; -+ rdc_flash_parts[0].offset = 0; -+ rdc_flash_parts[0].size = 0x100000; -+ rdc_flash_parts[1].name = "rootfs"; -+ rdc_flash_parts[1].offset = 0x100000; -+ rdc_flash_parts[1].size = rdc_map_info.size - 0x140000; -+ rdc_flash_parts[2].name = "linux"; -+ rdc_flash_parts[2].offset = 0; -+ rdc_flash_parts[2].size = rdc_map_info.size - 0x40000; -+ rdc_flash_parts[3].name = "config"; -+ rdc_flash_parts[3].offset = rdc_map_info.size - 0x40000; -+ rdc_flash_parts[3].size = 0x10000; -+ rdc_flash_parts[4].name = "productinfo"; -+ rdc_flash_parts[4].offset = rdc_map_info.size - 0x30000; -+ rdc_flash_parts[4].size = 0x10000; -+ rdc_flash_parts[5].name = "bootloader"; -+ rdc_flash_parts[5].offset = rdc_map_info.size - 0x20000; -+ rdc_flash_parts[5].size = 0x20000; -+ rdc_flash_data.nr_parts = 6; -+ } -+#endif - return platform_add_devices(rdc321x_devs, ARRAY_SIZE(rdc321x_devs)); - } - -+#ifdef CONFIG_MTD_RDC3210 - arch_initcall(rdc_board_setup); -+#else -+late_initcall(rdc_board_setup); -+#endif -Index: linux-2.6.28.10/arch/x86/Makefile -=================================================================== ---- linux-2.6.28.10.orig/arch/x86/Makefile 2009-11-03 21:01:29.756400281 -0800 -+++ linux-2.6.28.10/arch/x86/Makefile 2009-11-03 21:01:32.164401226 -0800 -@@ -113,6 +113,10 @@ - mflags-$(CONFIG_X86_VOYAGER) := -Iarch/x86/include/asm/mach-voyager - mcore-$(CONFIG_X86_VOYAGER) := arch/x86/mach-voyager/ - -+# RDC subarch support -+mflags-$(CONFIG_X86_RDC321X) := -Iarch/x86/include/asm/mach-rdc321x -+mcore-$(CONFIG_X86_RDC321X) += arch/x86/mach-rdc321x/ -+ - # generic subarchitecture - mflags-$(CONFIG_X86_GENERICARCH):= -Iarch/x86/include/asm/mach-generic - fcore-$(CONFIG_X86_GENERICARCH) += arch/x86/mach-generic/ -Index: linux-2.6.28.10/arch/x86/include/asm/mach-rdc321x/gpio.h -=================================================================== ---- linux-2.6.28.10.orig/arch/x86/include/asm/mach-rdc321x/gpio.h 2009-11-03 21:01:29.784401606 -0800 -+++ linux-2.6.28.10/arch/x86/include/asm/mach-rdc321x/gpio.h 2009-11-03 21:01:32.164401226 -0800 -@@ -9,7 +9,6 @@ - extern int rdc_gpio_direction_output(unsigned gpio, int value); - extern int rdc_gpio_request(unsigned gpio, const char *label); - extern void rdc_gpio_free(unsigned gpio); --extern void __init rdc321x_gpio_setup(void); - - /* Wrappers for the arch-neutral GPIO API */ - diff --git a/target/linux/rdc/patches-2.6.28/004-yenta_mystery.patch b/target/linux/rdc/patches-2.6.28/004-yenta_mystery.patch deleted file mode 100644 index 4c2e2face..000000000 --- a/target/linux/rdc/patches-2.6.28/004-yenta_mystery.patch +++ /dev/null @@ -1,20 +0,0 @@ ---- a/drivers/pcmcia/yenta_socket.c -+++ b/drivers/pcmcia/yenta_socket.c -@@ -1174,6 +1174,17 @@ static int __devinit yenta_probe (struct - - /* We must finish initialization here */ - -+#ifdef CONFIG_X86_RDC -+/* #define YO_TI1510_DATASHEET_GUY_EXPLAIN_THIS_JUNK 0x0044f044 */ -+#define YO_TI1510_DATASHEET_GUY_EXPLAIN_THIS_JUNK 0x0844b060 -+/* #define YO_TI1510_DATASHEET_GUY_EXPLAIN_THIS_JUNK 0x0044d044 */ -+ -+ config_writel(socket, 32*4, YO_TI1510_DATASHEET_GUY_EXPLAIN_THIS_JUNK); -+ config_writel(socket, 35*4, 0x00000022); -+ config_writel(socket, 36*4, 0x60200000); -+ config_writel(socket, 40*4, 0x7e020000); -+#endif -+ - if (!socket->cb_irq || request_irq(socket->cb_irq, yenta_interrupt, IRQF_SHARED, "yenta", socket)) { - /* No IRQ or request_irq failed. Poll */ - socket->cb_irq = 0; /* But zero is a valid IRQ number. */ diff --git a/target/linux/rdc/patches-2.6.28/005-fix_amit_breakage.patch b/target/linux/rdc/patches-2.6.28/005-fix_amit_breakage.patch deleted file mode 100644 index 8103e841d..000000000 --- a/target/linux/rdc/patches-2.6.28/005-fix_amit_breakage.patch +++ /dev/null @@ -1,40 +0,0 @@ ---- a/arch/x86/boot/boot.h -+++ b/arch/x86/boot/boot.h -@@ -62,7 +62,7 @@ static inline void outl(u32 v, u16 port) - { - asm volatile("outl %0,%1" : : "a" (v), "dN" (port)); - } --static inline u32 inl(u32 port) -+static inline u32 inl(u16 port) - { - u32 v; - asm volatile("inl %1,%0" : "=a" (v) : "dN" (port)); ---- a/arch/x86/boot/pm.c -+++ b/arch/x86/boot/pm.c -@@ -14,6 +14,9 @@ - - #include "boot.h" - #include -+#ifdef CONFIG_X86_RDC -+#include -+#endif - - /* - * Invoke the realmode switch hook if present; otherwise -@@ -156,6 +159,16 @@ void go_to_protected_mode(void) - die(); - } - -+#ifdef CONFIG_X86_RDC -+ { -+ u32 bootctl; -+ -+ outl(0x80003840, RDC3210_CFGREG_ADDR); -+ bootctl = inl(RDC3210_CFGREG_DATA) | 0x07ff0000; -+ outl(bootctl, RDC3210_CFGREG_DATA); -+ } -+#endif -+ - /* Reset coprocessor (IGNNE#) */ - reset_coprocessor(); - diff --git a/target/linux/rdc/patches-2.6.28/006-bzip2_lzma_x86.patch b/target/linux/rdc/patches-2.6.28/006-bzip2_lzma_x86.patch deleted file mode 100644 index c1865a86b..000000000 --- a/target/linux/rdc/patches-2.6.28/006-bzip2_lzma_x86.patch +++ /dev/null @@ -1,2898 +0,0 @@ ---- a/arch/x86/boot/compressed/Makefile -+++ b/arch/x86/boot/compressed/Makefile -@@ -4,7 +4,7 @@ - # create a compressed vmlinux image from the original vmlinux - # - --targets := vmlinux vmlinux.bin vmlinux.bin.gz head_$(BITS).o misc.o piggy.o -+targets := vmlinux vmlinux.bin vmlinux.bin.gz vmlinux.bin.bz2 vmlinux.bin.lzma head_$(BITS).o misc.o piggy.o - - KBUILD_CFLAGS := -m$(BITS) -D__KERNEL__ $(LINUX_INCLUDE) -O2 - KBUILD_CFLAGS += -fno-strict-aliasing -fPIC -@@ -47,9 +47,17 @@ ifeq ($(CONFIG_X86_32),y) - ifdef CONFIG_RELOCATABLE - $(obj)/vmlinux.bin.gz: $(obj)/vmlinux.bin.all FORCE - $(call if_changed,gzip) -+$(obj)/vmlinux.bin.bz2: $(obj)/vmlinux.bin.all FORCE -+ $(call if_changed,bzip2) -+$(obj)/vmlinux.bin.lzma: $(obj)/vmlinux.bin.all FORCE -+ $(call if_changed,lzma) - else - $(obj)/vmlinux.bin.gz: $(obj)/vmlinux.bin FORCE - $(call if_changed,gzip) -+$(obj)/vmlinux.bin.bz2: $(obj)/vmlinux.bin FORCE -+ $(call if_changed,bzip2) -+$(obj)/vmlinux.bin.lzma: $(obj)/vmlinux.bin FORCE -+ $(call if_changed,lzma) - endif - LDFLAGS_piggy.o := -r --format binary --oformat elf32-i386 -T - -@@ -60,5 +68,9 @@ $(obj)/vmlinux.bin.gz: $(obj)/vmlinux.bi - LDFLAGS_piggy.o := -r --format binary --oformat elf64-x86-64 -T - endif - --$(obj)/piggy.o: $(obj)/vmlinux.scr $(obj)/vmlinux.bin.gz FORCE -+suffix_$(CONFIG_KERNEL_GZIP) = gz -+suffix_$(CONFIG_KERNEL_BZIP2) = bz2 -+suffix_$(CONFIG_KERNEL_LZMA) = lzma -+ -+$(obj)/piggy.o: $(obj)/vmlinux.scr $(obj)/vmlinux.bin.$(suffix_y) FORCE - $(call if_changed,ld) ---- a/arch/x86/boot/compressed/misc.c -+++ b/arch/x86/boot/compressed/misc.c -@@ -116,71 +116,13 @@ - /* - * gzip declarations - */ -- --#define OF(args) args - #define STATIC static - - #undef memset - #undef memcpy - #define memzero(s, n) memset((s), 0, (n)) - --typedef unsigned char uch; --typedef unsigned short ush; --typedef unsigned long ulg; -- --/* -- * Window size must be at least 32k, and a power of two. -- * We don't actually have a window just a huge output buffer, -- * so we report a 2G window size, as that should always be -- * larger than our output buffer: -- */ --#define WSIZE 0x80000000 - --/* Input buffer: */ --static unsigned char *inbuf; -- --/* Sliding window buffer (and final output buffer): */ --static unsigned char *window; -- --/* Valid bytes in inbuf: */ --static unsigned insize; -- --/* Index of next byte to be processed in inbuf: */ --static unsigned inptr; -- --/* Bytes in output buffer: */ --static unsigned outcnt; -- --/* gzip flag byte */ --#define ASCII_FLAG 0x01 /* bit 0 set: file probably ASCII text */ --#define CONTINUATION 0x02 /* bit 1 set: continuation of multi-part gz file */ --#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */ --#define ORIG_NAM 0x08 /* bit 3 set: original file name present */ --#define COMMENT 0x10 /* bit 4 set: file comment present */ --#define ENCRYPTED 0x20 /* bit 5 set: file is encrypted */ --#define RESERVED 0xC0 /* bit 6, 7: reserved */ -- --#define get_byte() (inptr < insize ? inbuf[inptr++] : fill_inbuf()) -- --/* Diagnostic functions */ --#ifdef DEBUG --# define Assert(cond, msg) do { if (!(cond)) error(msg); } while (0) --# define Trace(x) do { fprintf x; } while (0) --# define Tracev(x) do { if (verbose) fprintf x ; } while (0) --# define Tracevv(x) do { if (verbose > 1) fprintf x ; } while (0) --# define Tracec(c, x) do { if (verbose && (c)) fprintf x ; } while (0) --# define Tracecv(c, x) do { if (verbose > 1 && (c)) fprintf x ; } while (0) --#else --# define Assert(cond, msg) --# define Trace(x) --# define Tracev(x) --# define Tracevv(x) --# define Tracec(c, x) --# define Tracecv(c, x) --#endif -- --static int fill_inbuf(void); --static void flush_window(void); - static void error(char *m); - - /* -@@ -189,11 +131,6 @@ static void error(char *m); - static struct boot_params *real_mode; /* Pointer to real-mode data */ - static int quiet; - --extern unsigned char input_data[]; --extern int input_len; -- --static long bytes_out; -- - static void *memset(void *s, int c, unsigned n); - static void *memcpy(void *dest, const void *src, unsigned n); - -@@ -213,7 +150,19 @@ static char *vidmem; - static int vidport; - static int lines, cols; - -+#define NEW_CODE -+ -+#ifdef CONFIG_KERNEL_GZIP - #include "../../../../lib/inflate.c" -+#endif -+ -+#ifdef CONFIG_KERNEL_BZIP2 -+#include "../../../../lib/decompress_bunzip2.c" -+#endif -+ -+#ifdef CONFIG_KERNEL_LZMA -+#include "../../../../lib/decompress_unlzma.c" -+#endif - - static void scroll(void) - { -@@ -293,38 +242,6 @@ static void *memcpy(void *dest, const vo - return dest; - } - --/* =========================================================================== -- * Fill the input buffer. This is called only when the buffer is empty -- * and at least one byte is really needed. -- */ --static int fill_inbuf(void) --{ -- error("ran out of input data"); -- return 0; --} -- --/* =========================================================================== -- * Write the output window window[0..outcnt-1] and update crc and bytes_out. -- * (Used for the decompressed data only.) -- */ --static void flush_window(void) --{ -- /* With my window equal to my output buffer -- * I only need to compute the crc here. -- */ -- unsigned long c = crc; /* temporary variable */ -- unsigned n; -- unsigned char *in, ch; -- -- in = window; -- for (n = 0; n < outcnt; n++) { -- ch = *in++; -- c = crc_32_tab[((int)c ^ ch) & 0xff] ^ (c >> 8); -- } -- crc = c; -- bytes_out += (unsigned long)outcnt; -- outcnt = 0; --} - - static void error(char *x) - { -@@ -407,12 +324,8 @@ asmlinkage void decompress_kernel(void * - lines = real_mode->screen_info.orig_video_lines; - cols = real_mode->screen_info.orig_video_cols; - -- window = output; /* Output buffer (Normally at 1M) */ - free_mem_ptr = heap; /* Heap */ - free_mem_end_ptr = heap + BOOT_HEAP_SIZE; -- inbuf = input_data; /* Input buffer */ -- insize = input_len; -- inptr = 0; - - #ifdef CONFIG_X86_64 - if ((unsigned long)output & (__KERNEL_ALIGN - 1)) -@@ -430,10 +343,9 @@ asmlinkage void decompress_kernel(void * - #endif - #endif - -- makecrc(); - if (!quiet) - putstr("\nDecompressing Linux... "); -- gunzip(); -+ decompress(input_data, input_len, NULL, NULL, output, NULL, error); - parse_elf(output); - if (!quiet) - putstr("done.\nBooting the kernel.\n"); ---- a/arch/x86/include/asm/boot.h -+++ b/arch/x86/include/asm/boot.h -@@ -15,11 +15,21 @@ - + (CONFIG_PHYSICAL_ALIGN - 1)) \ - & ~(CONFIG_PHYSICAL_ALIGN - 1)) - -+#if (defined CONFIG_KERNEL_BZIP2) -+#define BOOT_HEAP_SIZE 0x400000 -+#else -+ - #ifdef CONFIG_X86_64 - #define BOOT_HEAP_SIZE 0x7000 --#define BOOT_STACK_SIZE 0x4000 - #else - #define BOOT_HEAP_SIZE 0x4000 -+#endif -+ -+#endif -+ -+#ifdef CONFIG_X86_64 -+#define BOOT_STACK_SIZE 0x4000 -+#else - #define BOOT_STACK_SIZE 0x1000 - #endif - ---- a/drivers/block/Kconfig -+++ b/drivers/block/Kconfig -@@ -358,6 +358,30 @@ config BLK_DEV_XIP - will prevent RAM block device backing store memory from being - allocated from highmem (only a problem for highmem systems). - -+config RD_BZIP2 -+ bool "Initial ramdisk compressed using bzip2" -+ default n -+ depends on BLK_DEV_INITRD=y -+ help -+ Support loading of a bzip2 encoded initial ramdisk or cpio buffer -+ If unsure, say N. -+ -+config RD_LZMA -+ bool "Initial ramdisk compressed using lzma" -+ default n -+ depends on BLK_DEV_INITRD=y -+ help -+ Support loading of a lzma encoded initial ramdisk or cpio buffer -+ If unsure, say N. -+ -+config RD_GZIP -+ bool "Initial ramdisk compressed using gzip" -+ default y -+ depends on BLK_DEV_INITRD=y -+ help -+ Support loading of a gzip encoded initial ramdisk or cpio buffer. -+ If unsure, say Y. -+ - config CDROM_PKTCDVD - tristate "Packet writing on CD/DVD media" - depends on !UML ---- /dev/null -+++ b/include/linux/decompress/bunzip2.h -@@ -0,0 +1,10 @@ -+#ifndef DECOMPRESS_BUNZIP2_H -+#define DECOMPRESS_BUNZIP2_H -+ -+int bunzip2(unsigned char *inbuf, int len, -+ int(*fill)(void*, unsigned int), -+ int(*flush)(void*, unsigned int), -+ unsigned char *output, -+ int *pos, -+ void(*error)(char *x)); -+#endif ---- /dev/null -+++ b/include/linux/decompress/generic.h -@@ -0,0 +1,30 @@ -+#ifndef DECOMPRESS_GENERIC_H -+#define DECOMPRESS_GENERIC_H -+ -+/* Minimal chunksize to be read. -+ *Bzip2 prefers at least 4096 -+ *Lzma prefers 0x10000 */ -+#define COMPR_IOBUF_SIZE 4096 -+ -+typedef int (*decompress_fn) (unsigned char *inbuf, int len, -+ int(*fill)(void*, unsigned int), -+ int(*writebb)(void*, unsigned int), -+ unsigned char *output, -+ int *posp, -+ void(*error)(char *x)); -+ -+/* inbuf - input buffer -+ *len - len of pre-read data in inbuf -+ *fill - function to fill inbuf if empty -+ *writebb - function to write out outbug -+ *posp - if non-null, input position (number of bytes read) will be -+ * returned here -+ * -+ *If len != 0, the inbuf is initialized (with as much data), and fill -+ *should not be called -+ *If len = 0, the inbuf is allocated, but empty. Its size is IOBUF_SIZE -+ *fill should be called (repeatedly...) to read data, at most IOBUF_SIZE -+ */ -+ -+ -+#endif ---- /dev/null -+++ b/include/linux/decompress/inflate.h -@@ -0,0 +1,13 @@ -+#ifndef INFLATE_H -+#define INFLATE_H -+ -+/* Other housekeeping constants */ -+#define INBUFSIZ 4096 -+ -+int gunzip(unsigned char *inbuf, int len, -+ int(*fill)(void*, unsigned int), -+ int(*flush)(void*, unsigned int), -+ unsigned char *output, -+ int *pos, -+ void(*error_fn)(char *x)); -+#endif ---- /dev/null -+++ b/include/linux/decompress/mm.h -@@ -0,0 +1,89 @@ -+/* -+ * linux/compr_mm.h -+ * -+ * Memory management for pre-boot and ramdisk uncompressors -+ * -+ * Authors: Alain Knaff -+ * -+ */ -+ -+#ifndef DECOMPR_MM_H -+#define DECOMPR_MM_H -+ -+#ifdef STATIC -+ -+/* Code active when included from pre-boot environment: */ -+ -+/* A trivial malloc implementation, adapted from -+ * malloc by Hannu Savolainen 1993 and Matthias Urlichs 1994 -+ */ -+static unsigned long malloc_ptr; -+static int malloc_count; -+ -+static void *malloc(int size) -+{ -+ void *p; -+ -+ if (size < 0) -+ error("Malloc error"); -+ if (!malloc_ptr) -+ malloc_ptr = free_mem_ptr; -+ -+ malloc_ptr = (malloc_ptr + 3) & ~3; /* Align */ -+ -+ p = (void *)malloc_ptr; -+ malloc_ptr += size; -+ -+ if (free_mem_end_ptr && malloc_ptr >= free_mem_end_ptr) -+ error("Out of memory"); -+ -+ malloc_count++; -+ return p; -+} -+ -+static void free(void *where) -+{ -+ malloc_count--; -+ if (!malloc_count) -+ malloc_ptr = free_mem_ptr; -+} -+ -+#define large_malloc(a) malloc(a) -+#define large_free(a) free(a) -+ -+#define set_error_fn(x) -+#define panic error -+ -+#define INIT -+ -+#else /* STATIC */ -+ -+/* Code active when compiled standalone for use when loading ramdisk: */ -+ -+#include -+#include -+#include -+#include -+ -+/* Use defines rather than static inline in order to avoid spurious -+ * warnings when not needed (indeed large_malloc / large_free are not -+ * needed by inflate */ -+ -+#define malloc(a) kmalloc(a, GFP_KERNEL) -+#define free(a) kfree(a) -+ -+#define large_malloc(a) vmalloc(a) -+#define large_free(a) vfree(a) -+ -+static void(*error)(char *m); -+#define set_error_fn(x) error = x; -+#define NEW_CODE -+ -+#define INIT __init -+#define STATIC -+ -+#include -+ -+#endif /* STATIC */ -+ -+#endif /* DECOMPR_MM_H */ ---- /dev/null -+++ b/include/linux/decompress/unlzma.h -@@ -0,0 +1,12 @@ -+#ifndef DECOMPRESS_UNLZMA_H -+#define DECOMPRESS_UNLZMA_H -+ -+int unlzma(unsigned char *, int, -+ int(*fill)(void*, unsigned int), -+ int(*flush)(void*, unsigned int), -+ unsigned char *output, -+ int *posp, -+ void(*error)(char *x) -+ ); -+ -+#endif ---- a/init/Kconfig -+++ b/init/Kconfig -@@ -101,6 +101,56 @@ config LOCALVERSION_AUTO - - which is done within the script "scripts/setlocalversion".) - -+choice -+ prompt "Kernel compression mode" -+ default KERNEL_GZIP -+ help -+ The linux kernel is a kind of self-extracting executable. -+ Several compression algorithms are available, which differ -+ in efficiency, compression and decompression speed. -+ Compression speed is only relevant when building a kernel. -+ Decompression speed is relevant at each boot. -+ -+ If you have any problems with bzip2 or lzma compressed -+ kernels, mail me (Alain Knaff) . (An older -+ version of this functionality (bzip2 only), for 2.4, was -+ supplied by Christian Ludwig) -+ -+ High compression options are mostly useful for users, who -+ are low on disk space (embedded systems), but for whom ram -+ size matters less. -+ -+ If in doubt, select 'gzip' -+ -+config KERNEL_GZIP -+ bool "Gzip" -+ help -+ The old and tried gzip compression. Its compression ratio is -+ the poorest among the 3 choices; however its speed (both -+ compression and decompression) is the fastest. -+ -+config KERNEL_BZIP2 -+ bool "Bzip2" -+ help -+ Its compression ratio and speed is intermediate. -+ Decompression speed is slowest among the 3. -+ The kernel size is about 10 per cent smaller with bzip2, -+ in comparison to gzip. -+ Bzip2 uses a large amount of memory. For modern kernels -+ you will need at least 8MB RAM or more for booting. -+ -+config KERNEL_LZMA -+ bool "LZMA" -+ help -+ The most recent compression algorithm. -+ Its ratio is best, decompression speed is between the other -+ 2. Compression is slowest. -+ The kernel size is about 33 per cent smaller with lzma, -+ in comparison to gzip. -+ -+endchoice -+ -+ - config SWAP - bool "Support for paging of anonymous memory (swap)" - depends on MMU && BLOCK ---- a/init/do_mounts_rd.c -+++ b/init/do_mounts_rd.c -@@ -11,6 +11,12 @@ - - #include "do_mounts.h" - -+#include -+ -+#include -+#include -+#include -+ - int __initdata rd_prompt = 1;/* 1 = prompt for RAM disk, 0 = don't prompt */ - - static int __init prompt_ramdisk(char *str) -@@ -29,7 +35,7 @@ static int __init ramdisk_start_setup(ch - } - __setup("ramdisk_start=", ramdisk_start_setup); - --static int __init crd_load(int in_fd, int out_fd); -+static int __init crd_load(int in_fd, int out_fd, decompress_fn deco); - - /* - * This routine tries to find a RAM disk image to load, and returns the -@@ -46,7 +52,7 @@ static int __init crd_load(int in_fd, in - * gzip - */ - static int __init --identify_ramdisk_image(int fd, int start_block) -+identify_ramdisk_image(int fd, int start_block, decompress_fn *decompressor) - { - const int size = 512; - struct minix_super_block *minixsb; -@@ -74,6 +80,7 @@ identify_ramdisk_image(int fd, int start - sys_lseek(fd, start_block * BLOCK_SIZE, 0); - sys_read(fd, buf, size); - -+#ifdef CONFIG_RD_GZIP - /* - * If it matches the gzip magic numbers, return 0 - */ -@@ -81,9 +88,39 @@ identify_ramdisk_image(int fd, int start - printk(KERN_NOTICE - "RAMDISK: Compressed image found at block %d\n", - start_block); -+ *decompressor = gunzip; -+ nblocks = 0; -+ goto done; -+ } -+#endif -+ -+#ifdef CONFIG_RD_BZIP2 -+ /* -+ * If it matches the bzip2 magic numbers, return -1 -+ */ -+ if (buf[0] == 0x42 && (buf[1] == 0x5a)) { -+ printk(KERN_NOTICE -+ "RAMDISK: Bzipped image found at block %d\n", -+ start_block); -+ *decompressor = bunzip2; - nblocks = 0; - goto done; - } -+#endif -+ -+#ifdef CONFIG_RD_LZMA -+ /* -+ * If it matches the lzma magic numbers, return -1 -+ */ -+ if (buf[0] == 0x5d && (buf[1] == 0x00)) { -+ printk(KERN_NOTICE -+ "RAMDISK: Lzma image found at block %d\n", -+ start_block); -+ *decompressor = unlzma; -+ nblocks = 0; -+ goto done; -+ } -+#endif - - /* romfs is at block zero too */ - if (romfsb->word0 == ROMSB_WORD0 && -@@ -156,6 +193,7 @@ int __init rd_load_image(char *from) - int nblocks, i, disk; - char *buf = NULL; - unsigned short rotate = 0; -+ decompress_fn decompressor = NULL; - #if !defined(CONFIG_S390) && !defined(CONFIG_PPC_ISERIES) - char rotator[4] = { '|' , '/' , '-' , '\\' }; - #endif -@@ -168,12 +206,12 @@ int __init rd_load_image(char *from) - if (in_fd < 0) - goto noclose_input; - -- nblocks = identify_ramdisk_image(in_fd, rd_image_start); -+ nblocks = identify_ramdisk_image(in_fd, rd_image_start, &decompressor); - if (nblocks < 0) - goto done; - - if (nblocks == 0) { -- if (crd_load(in_fd, out_fd) == 0) -+ if (crd_load(in_fd, out_fd, decompressor) == 0) - goto successful_load; - goto done; - } -@@ -272,138 +310,48 @@ int __init rd_load_disk(int n) - return rd_load_image("/dev/root"); - } - --/* -- * gzip declarations -- */ -- --#define OF(args) args -- --#ifndef memzero --#define memzero(s, n) memset ((s), 0, (n)) --#endif -- --typedef unsigned char uch; --typedef unsigned short ush; --typedef unsigned long ulg; -- --#define INBUFSIZ 4096 --#define WSIZE 0x8000 /* window size--must be a power of two, and */ -- /* at least 32K for zip's deflate method */ -- --static uch *inbuf; --static uch *window; -- --static unsigned insize; /* valid bytes in inbuf */ --static unsigned inptr; /* index of next byte to be processed in inbuf */ --static unsigned outcnt; /* bytes in output buffer */ - static int exit_code; --static int unzip_error; --static long bytes_out; -+static int decompress_error; - static int crd_infd, crd_outfd; - --#define get_byte() (inptr < insize ? inbuf[inptr++] : fill_inbuf()) -- --/* Diagnostic functions (stubbed out) */ --#define Assert(cond,msg) --#define Trace(x) --#define Tracev(x) --#define Tracevv(x) --#define Tracec(c,x) --#define Tracecv(c,x) -- --#define STATIC static --#define INIT __init -- --static int __init fill_inbuf(void); --static void __init flush_window(void); --static void __init error(char *m); -- --#define NO_INFLATE_MALLOC -- --#include "../lib/inflate.c" -- --/* =========================================================================== -- * Fill the input buffer. This is called only when the buffer is empty -- * and at least one byte is really needed. -- * Returning -1 does not guarantee that gunzip() will ever return. -- */ --static int __init fill_inbuf(void) -+static int __init compr_fill(void *buf, unsigned int len) - { -- if (exit_code) return -1; -- -- insize = sys_read(crd_infd, inbuf, INBUFSIZ); -- if (insize == 0) { -- error("RAMDISK: ran out of compressed data"); -- return -1; -- } -- -- inptr = 1; -- -- return inbuf[0]; -+ int r = sys_read(crd_infd, buf, len); -+ if (r < 0) -+ printk(KERN_ERR "RAMDISK: error while reading compressed data"); -+ else if (r == 0) -+ printk(KERN_ERR "RAMDISK: EOF while reading compressed data"); -+ return r; - } - --/* =========================================================================== -- * Write the output window window[0..outcnt-1] and update crc and bytes_out. -- * (Used for the decompressed data only.) -- */ --static void __init flush_window(void) -+static int __init compr_flush(void *window, unsigned int outcnt) - { -- ulg c = crc; /* temporary variable */ -- unsigned n, written; -- uch *in, ch; -- -- written = sys_write(crd_outfd, window, outcnt); -- if (written != outcnt && unzip_error == 0) { -- printk(KERN_ERR "RAMDISK: incomplete write (%d != %d) %ld\n", -- written, outcnt, bytes_out); -- unzip_error = 1; -- } -- in = window; -- for (n = 0; n < outcnt; n++) { -- ch = *in++; -- c = crc_32_tab[((int)c ^ ch) & 0xff] ^ (c >> 8); -- } -- crc = c; -- bytes_out += (ulg)outcnt; -- outcnt = 0; -+ int written = sys_write(crd_outfd, window, outcnt); -+ if (written != outcnt) { -+ if (decompress_error == 0) -+ printk(KERN_ERR -+ "RAMDISK: incomplete write (%d != %d)\n", -+ written, outcnt); -+ decompress_error = 1; -+ return -1; -+ } -+ return outcnt; - } - - static void __init error(char *x) - { - printk(KERN_ERR "%s\n", x); - exit_code = 1; -- unzip_error = 1; -+ decompress_error = 1; - } - --static int __init crd_load(int in_fd, int out_fd) -+static int __init crd_load(int in_fd, int out_fd, decompress_fn deco) - { - int result; -- -- insize = 0; /* valid bytes in inbuf */ -- inptr = 0; /* index of next byte to be processed in inbuf */ -- outcnt = 0; /* bytes in output buffer */ -- exit_code = 0; -- bytes_out = 0; -- crc = (ulg)0xffffffffL; /* shift register contents */ -- - crd_infd = in_fd; - crd_outfd = out_fd; -- inbuf = kmalloc(INBUFSIZ, GFP_KERNEL); -- if (!inbuf) { -- printk(KERN_ERR "RAMDISK: Couldn't allocate gzip buffer\n"); -- return -1; -- } -- window = kmalloc(WSIZE, GFP_KERNEL); -- if (!window) { -- printk(KERN_ERR "RAMDISK: Couldn't allocate gzip window\n"); -- kfree(inbuf); -- return -1; -- } -- makecrc(); -- result = gunzip(); -- if (unzip_error) -+ result = deco(NULL, 0, compr_fill, compr_flush, NULL, NULL, error); -+ if (decompress_error) - result = 1; -- kfree(inbuf); -- kfree(window); - return result; - } ---- a/init/initramfs.c -+++ b/init/initramfs.c -@@ -389,11 +389,14 @@ static int __init write_buffer(char *buf - return len - count; - } - --static void __init flush_buffer(char *buf, unsigned len) -+ -+static int __init flush_buffer(void *bufv, unsigned len) - { -+ char *buf = (char *) bufv; - int written; -+ int origLen = len; - if (message) -- return; -+ return -1; - while ((written = write_buffer(buf, len)) < len && !message) { - char c = buf[written]; - if (c == '0') { -@@ -407,73 +410,14 @@ static void __init flush_buffer(char *bu - } else - error("junk in compressed archive"); - } -+ return origLen; - } - --/* -- * gzip declarations -- */ -- --#define OF(args) args -- --#ifndef memzero --#define memzero(s, n) memset ((s), 0, (n)) --#endif -+static unsigned my_inptr; /* index of next byte to be processed in inbuf */ - --typedef unsigned char uch; --typedef unsigned short ush; --typedef unsigned long ulg; -- --#define WSIZE 0x8000 /* window size--must be a power of two, and */ -- /* at least 32K for zip's deflate method */ -- --static uch *inbuf; --static uch *window; -- --static unsigned insize; /* valid bytes in inbuf */ --static unsigned inptr; /* index of next byte to be processed in inbuf */ --static unsigned outcnt; /* bytes in output buffer */ --static long bytes_out; -- --#define get_byte() (inptr < insize ? inbuf[inptr++] : -1) -- --/* Diagnostic functions (stubbed out) */ --#define Assert(cond,msg) --#define Trace(x) --#define Tracev(x) --#define Tracevv(x) --#define Tracec(c,x) --#define Tracecv(c,x) -- --#define STATIC static --#define INIT __init -- --static void __init flush_window(void); --static void __init error(char *m); -- --#define NO_INFLATE_MALLOC -- --#include "../lib/inflate.c" -- --/* =========================================================================== -- * Write the output window window[0..outcnt-1] and update crc and bytes_out. -- * (Used for the decompressed data only.) -- */ --static void __init flush_window(void) --{ -- ulg c = crc; /* temporary variable */ -- unsigned n; -- uch *in, ch; -- -- flush_buffer(window, outcnt); -- in = window; -- for (n = 0; n < outcnt; n++) { -- ch = *in++; -- c = crc_32_tab[((int)c ^ ch) & 0xff] ^ (c >> 8); -- } -- crc = c; -- bytes_out += (ulg)outcnt; -- outcnt = 0; --} -+#include -+#include -+#include - - static char * __init unpack_to_rootfs(char *buf, unsigned len, int check_only) - { -@@ -482,9 +426,10 @@ static char * __init unpack_to_rootfs(ch - header_buf = kmalloc(110, GFP_KERNEL); - symlink_buf = kmalloc(PATH_MAX + N_ALIGN(PATH_MAX) + 1, GFP_KERNEL); - name_buf = kmalloc(N_ALIGN(PATH_MAX), GFP_KERNEL); -- window = kmalloc(WSIZE, GFP_KERNEL); -- if (!window || !header_buf || !symlink_buf || !name_buf) -+ -+ if (!header_buf || !symlink_buf || !name_buf) - panic("can't allocate buffers"); -+ - state = Start; - this_header = 0; - message = NULL; -@@ -504,22 +449,38 @@ static char * __init unpack_to_rootfs(ch - continue; - } - this_header = 0; -- insize = len; -- inbuf = buf; -- inptr = 0; -- outcnt = 0; /* bytes in output buffer */ -- bytes_out = 0; -- crc = (ulg)0xffffffffL; /* shift register contents */ -- makecrc(); -- gunzip(); -+ if (!gunzip(buf, len, NULL, flush_buffer, NULL, -+ &my_inptr, error) && -+ message == NULL) -+ goto ok; -+ -+#ifdef CONFIG_RD_BZIP2 -+ message = NULL; /* Zero out message, or else cpio will think an error has already occured */ -+ if (!bunzip2(buf, len, NULL, flush_buffer, NULL, -+ &my_inptr, error) < 0 -+ && -+ message == NULL) { -+ goto ok; -+ } -+#endif -+ -+#ifdef CONFIG_RD_LZMA -+ message = NULL; /* Zero out message, or else cpio will think an error has already occured */ -+ if (!unlzma(buf, len, NULL, flush_buffer, NULL, -+ &my_inptr, error) < 0 -+ && -+ message == NULL) { -+ goto ok; -+ } -+#endif -+ok: - if (state != Reset) -- error("junk in gzipped archive"); -- this_header = saved_offset + inptr; -- buf += inptr; -- len -= inptr; -+ error("junk in compressed archive"); -+ this_header = saved_offset + my_inptr; -+ buf += my_inptr; -+ len -= my_inptr; - } - dir_utime(); -- kfree(window); - kfree(name_buf); - kfree(symlink_buf); - kfree(header_buf); ---- a/lib/Makefile -+++ b/lib/Makefile -@@ -11,7 +11,8 @@ lib-y := ctype.o string.o vsprintf.o cmd - rbtree.o radix-tree.o dump_stack.o \ - idr.o int_sqrt.o extable.o prio_tree.o \ - sha1.o irq_regs.o reciprocal_div.o argv_split.o \ -- proportions.o prio_heap.o ratelimit.o show_mem.o -+ proportions.o prio_heap.o ratelimit.o show_mem.o \ -+ inflate.o decompress_bunzip2.o decompress_unlzma.o - - lib-$(CONFIG_MMU) += ioremap.o - lib-$(CONFIG_SMP) += cpumask.o ---- /dev/null -+++ b/lib/decompress_bunzip2.c -@@ -0,0 +1,735 @@ -+/* vi: set sw = 4 ts = 4: */ -+/* Small bzip2 deflate implementation, by Rob Landley (rob@landley.net). -+ -+ Based on bzip2 decompression code by Julian R Seward (jseward@acm.org), -+ which also acknowledges contributions by Mike Burrows, David Wheeler, -+ Peter Fenwick, Alistair Moffat, Radford Neal, Ian H. Witten, -+ Robert Sedgewick, and Jon L. Bentley. -+ -+ This code is licensed under the LGPLv2: -+ LGPL (http://www.gnu.org/copyleft/lgpl.html -+*/ -+ -+/* -+ Size and speed optimizations by Manuel Novoa III (mjn3@codepoet.org). -+ -+ More efficient reading of Huffman codes, a streamlined read_bunzip() -+ function, and various other tweaks. In (limited) tests, approximately -+ 20% faster than bzcat on x86 and about 10% faster on arm. -+ -+ Note that about 2/3 of the time is spent in read_unzip() reversing -+ the Burrows-Wheeler transformation. Much of that time is delay -+ resulting from cache misses. -+ -+ I would ask that anyone benefiting from this work, especially those -+ using it in commercial products, consider making a donation to my local -+ non-profit hospice organization in the name of the woman I loved, who -+ passed away Feb. 12, 2003. -+ -+ In memory of Toni W. Hagan -+ -+ Hospice of Acadiana, Inc. -+ 2600 Johnston St., Suite 200 -+ Lafayette, LA 70503-3240 -+ -+ Phone (337) 232-1234 or 1-800-738-2226 -+ Fax (337) 232-1297 -+ -+ http://www.hospiceacadiana.com/ -+ -+ Manuel -+ */ -+ -+/* -+ Made it fit for running in Linux Kernel by Alain Knaff (alain@knaff.lu) -+*/ -+ -+ -+#ifndef STATIC -+#include -+#endif /* !STATIC */ -+ -+#include -+ -+#ifndef INT_MAX -+#define INT_MAX 0x7fffffff -+#endif -+ -+/* Constants for Huffman coding */ -+#define MAX_GROUPS 6 -+#define GROUP_SIZE 50 /* 64 would have been more efficient */ -+#define MAX_HUFCODE_BITS 20 /* Longest Huffman code allowed */ -+#define MAX_SYMBOLS 258 /* 256 literals + RUNA + RUNB */ -+#define SYMBOL_RUNA 0 -+#define SYMBOL_RUNB 1 -+ -+/* Status return values */ -+#define RETVAL_OK 0 -+#define RETVAL_LAST_BLOCK (-1) -+#define RETVAL_NOT_BZIP_DATA (-2) -+#define RETVAL_UNEXPECTED_INPUT_EOF (-3) -+#define RETVAL_UNEXPECTED_OUTPUT_EOF (-4) -+#define RETVAL_DATA_ERROR (-5) -+#define RETVAL_OUT_OF_MEMORY (-6) -+#define RETVAL_OBSOLETE_INPUT (-7) -+ -+/* Other housekeeping constants */ -+#define BZIP2_IOBUF_SIZE 4096 -+ -+/* This is what we know about each Huffman coding group */ -+struct group_data { -+ /* We have an extra slot at the end of limit[] for a sentinal value. */ -+ int limit[MAX_HUFCODE_BITS+1]; -+ int base[MAX_HUFCODE_BITS]; -+ int permute[MAX_SYMBOLS]; -+ int minLen, maxLen; -+}; -+ -+/* Structure holding all the housekeeping data, including IO buffers and -+ memory that persists between calls to bunzip */ -+struct bunzip_data { -+ /* State for interrupting output loop */ -+ int writeCopies, writePos, writeRunCountdown, writeCount, writeCurrent; -+ /* I/O tracking data (file handles, buffers, positions, etc.) */ -+ int (*fill)(void*, unsigned int); -+ int inbufCount, inbufPos /*, outbufPos*/; -+ unsigned char *inbuf /*,*outbuf*/; -+ unsigned int inbufBitCount, inbufBits; -+ /* The CRC values stored in the block header and calculated from the -+ data */ -+ unsigned int crc32Table[256], headerCRC, totalCRC, writeCRC; -+ /* Intermediate buffer and its size (in bytes) */ -+ unsigned int *dbuf, dbufSize; -+ /* These things are a bit too big to go on the stack */ -+ unsigned char selectors[32768]; /* nSelectors = 15 bits */ -+ struct group_data groups[MAX_GROUPS]; /* Huffman coding tables */ -+ int io_error; /* non-zero if we have IO error */ -+}; -+ -+ -+/* Return the next nnn bits of input. All reads from the compressed input -+ are done through this function. All reads are big endian */ -+static unsigned int INIT get_bits(struct bunzip_data *bd, char bits_wanted) -+{ -+ unsigned int bits = 0; -+ -+ /* If we need to get more data from the byte buffer, do so. -+ (Loop getting one byte at a time to enforce endianness and avoid -+ unaligned access.) */ -+ while (bd->inbufBitCount < bits_wanted) { -+ /* If we need to read more data from file into byte buffer, do -+ so */ -+ if (bd->inbufPos == bd->inbufCount) { -+ if (bd->io_error) -+ return 0; -+ bd->inbufCount = bd->fill(bd->inbuf, BZIP2_IOBUF_SIZE); -+ if (bd->inbufCount <= 0) { -+ bd->io_error = RETVAL_UNEXPECTED_INPUT_EOF; -+ return 0; -+ } -+ bd->inbufPos = 0; -+ } -+ /* Avoid 32-bit overflow (dump bit buffer to top of output) */ -+ if (bd->inbufBitCount >= 24) { -+ bits = bd->inbufBits&((1 << bd->inbufBitCount)-1); -+ bits_wanted -= bd->inbufBitCount; -+ bits <<= bits_wanted; -+ bd->inbufBitCount = 0; -+ } -+ /* Grab next 8 bits of input from buffer. */ -+ bd->inbufBits = (bd->inbufBits << 8)|bd->inbuf[bd->inbufPos++]; -+ bd->inbufBitCount += 8; -+ } -+ /* Calculate result */ -+ bd->inbufBitCount -= bits_wanted; -+ bits |= (bd->inbufBits >> bd->inbufBitCount)&((1 << bits_wanted)-1); -+ -+ return bits; -+} -+ -+/* Unpacks the next block and sets up for the inverse burrows-wheeler step. */ -+ -+static int INIT get_next_block(struct bunzip_data *bd) -+{ -+ struct group_data *hufGroup = NULL; -+ int *base = NULL; -+ int *limit = NULL; -+ int dbufCount, nextSym, dbufSize, groupCount, selector, -+ i, j, k, t, runPos, symCount, symTotal, nSelectors, -+ byteCount[256]; -+ unsigned char uc, symToByte[256], mtfSymbol[256], *selectors; -+ unsigned int *dbuf, origPtr; -+ -+ dbuf = bd->dbuf; -+ dbufSize = bd->dbufSize; -+ selectors = bd->selectors; -+ -+ /* Read in header signature and CRC, then validate signature. -+ (last block signature means CRC is for whole file, return now) */ -+ i = get_bits(bd, 24); -+ j = get_bits(bd, 24); -+ bd->headerCRC = get_bits(bd, 32); -+ if ((i == 0x177245) && (j == 0x385090)) -+ return RETVAL_LAST_BLOCK; -+ if ((i != 0x314159) || (j != 0x265359)) -+ return RETVAL_NOT_BZIP_DATA; -+ /* We can add support for blockRandomised if anybody complains. -+ There was some code for this in busybox 1.0.0-pre3, but nobody ever -+ noticed that it didn't actually work. */ -+ if (get_bits(bd, 1)) -+ return RETVAL_OBSOLETE_INPUT; -+ origPtr = get_bits(bd, 24); -+ if (origPtr > dbufSize) -+ return RETVAL_DATA_ERROR; -+ /* mapping table: if some byte values are never used (encoding things -+ like ascii text), the compression code removes the gaps to have fewer -+ symbols to deal with, and writes a sparse bitfield indicating which -+ values were present. We make a translation table to convert the -+ symbols back to the corresponding bytes. */ -+ t = get_bits(bd, 16); -+ symTotal = 0; -+ for (i = 0; i < 16; i++) { -+ if (t&(1 << (15-i))) { -+ k = get_bits(bd, 16); -+ for (j = 0; j < 16; j++) -+ if (k&(1 << (15-j))) -+ symToByte[symTotal++] = (16*i)+j; -+ } -+ } -+ /* How many different Huffman coding groups does this block use? */ -+ groupCount = get_bits(bd, 3); -+ if (groupCount < 2 || groupCount > MAX_GROUPS) -+ return RETVAL_DATA_ERROR; -+ /* nSelectors: Every GROUP_SIZE many symbols we select a new -+ Huffman coding group. Read in the group selector list, -+ which is stored as MTF encoded bit runs. (MTF = Move To -+ Front, as each value is used it's moved to the start of the -+ list.) */ -+ nSelectors = get_bits(bd, 15); -+ if (!nSelectors) -+ return RETVAL_DATA_ERROR; -+ for (i = 0; i < groupCount; i++) -+ mtfSymbol[i] = i; -+ for (i = 0; i < nSelectors; i++) { -+ /* Get next value */ -+ for (j = 0; get_bits(bd, 1); j++) -+ if (j >= groupCount) -+ return RETVAL_DATA_ERROR; -+ /* Decode MTF to get the next selector */ -+ uc = mtfSymbol[j]; -+ for (; j; j--) -+ mtfSymbol[j] = mtfSymbol[j-1]; -+ mtfSymbol[0] = selectors[i] = uc; -+ } -+ /* Read the Huffman coding tables for each group, which code -+ for symTotal literal symbols, plus two run symbols (RUNA, -+ RUNB) */ -+ symCount = symTotal+2; -+ for (j = 0; j < groupCount; j++) { -+ unsigned char length[MAX_SYMBOLS], temp[MAX_HUFCODE_BITS+1]; -+ int minLen, maxLen, pp; -+ /* Read Huffman code lengths for each symbol. They're -+ stored in a way similar to mtf; record a starting -+ value for the first symbol, and an offset from the -+ previous value for everys symbol after that. -+ (Subtracting 1 before the loop and then adding it -+ back at the end is an optimization that makes the -+ test inside the loop simpler: symbol length 0 -+ becomes negative, so an unsigned inequality catches -+ it.) */ -+ t = get_bits(bd, 5)-1; -+ for (i = 0; i < symCount; i++) { -+ for (;;) { -+ if (((unsigned)t) > (MAX_HUFCODE_BITS-1)) -+ return RETVAL_DATA_ERROR; -+ -+ /* If first bit is 0, stop. Else -+ second bit indicates whether to -+ increment or decrement the value. -+ Optimization: grab 2 bits and unget -+ the second if the first was 0. */ -+ -+ k = get_bits(bd, 2); -+ if (k < 2) { -+ bd->inbufBitCount++; -+ break; -+ } -+ /* Add one if second bit 1, else -+ * subtract 1. Avoids if/else */ -+ t += (((k+1)&2)-1); -+ } -+ /* Correct for the initial -1, to get the -+ * final symbol length */ -+ length[i] = t+1; -+ } -+ /* Find largest and smallest lengths in this group */ -+ minLen = maxLen = length[0]; -+ -+ for (i = 1; i < symCount; i++) { -+ if (length[i] > maxLen) -+ maxLen = length[i]; -+ else if (length[i] < minLen) -+ minLen = length[i]; -+ } -+ -+ /* Calculate permute[], base[], and limit[] tables from -+ * length[]. -+ * -+ * permute[] is the lookup table for converting -+ * Huffman coded symbols into decoded symbols. base[] -+ * is the amount to subtract from the value of a -+ * Huffman symbol of a given length when using -+ * permute[]. -+ * -+ * limit[] indicates the largest numerical value a -+ * symbol with a given number of bits can have. This -+ * is how the Huffman codes can vary in length: each -+ * code with a value > limit[length] needs another -+ * bit. -+ */ -+ hufGroup = bd->groups+j; -+ hufGroup->minLen = minLen; -+ hufGroup->maxLen = maxLen; -+ /* Note that minLen can't be smaller than 1, so we -+ adjust the base and limit array pointers so we're -+ not always wasting the first entry. We do this -+ again when using them (during symbol decoding).*/ -+ base = hufGroup->base-1; -+ limit = hufGroup->limit-1; -+ /* Calculate permute[]. Concurently, initialize -+ * temp[] and limit[]. */ -+ pp = 0; -+ for (i = minLen; i <= maxLen; i++) { -+ temp[i] = limit[i] = 0; -+ for (t = 0; t < symCount; t++) -+ if (length[t] == i) -+ hufGroup->permute[pp++] = t; -+ } -+ /* Count symbols coded for at each bit length */ -+ for (i = 0; i < symCount; i++) -+ temp[length[i]]++; -+ /* Calculate limit[] (the largest symbol-coding value -+ *at each bit length, which is (previous limit << -+ *1)+symbols at this level), and base[] (number of -+ *symbols to ignore at each bit length, which is limit -+ *minus the cumulative count of symbols coded for -+ *already). */ -+ pp = t = 0; -+ for (i = minLen; i < maxLen; i++) { -+ pp += temp[i]; -+ /* We read the largest possible symbol size -+ and then unget bits after determining how -+ many we need, and those extra bits could be -+ set to anything. (They're noise from -+ future symbols.) At each level we're -+ really only interested in the first few -+ bits, so here we set all the trailing -+ to-be-ignored bits to 1 so they don't -+ affect the value > limit[length] -+ comparison. */ -+ limit[i] = (pp << (maxLen - i)) - 1; -+ pp <<= 1; -+ base[i+1] = pp-(t += temp[i]); -+ } -+ limit[maxLen+1] = INT_MAX; /* Sentinal value for -+ * reading next sym. */ -+ limit[maxLen] = pp+temp[maxLen]-1; -+ base[minLen] = 0; -+ } -+ /* We've finished reading and digesting the block header. Now -+ read this block's Huffman coded symbols from the file and -+ undo the Huffman coding and run length encoding, saving the -+ result into dbuf[dbufCount++] = uc */ -+ -+ /* Initialize symbol occurrence counters and symbol Move To -+ * Front table */ -+ for (i = 0; i < 256; i++) { -+ byteCount[i] = 0; -+ mtfSymbol[i] = (unsigned char)i; -+ } -+ /* Loop through compressed symbols. */ -+ runPos = dbufCount = symCount = selector = 0; -+ for (;;) { -+ /* Determine which Huffman coding group to use. */ -+ if (!(symCount--)) { -+ symCount = GROUP_SIZE-1; -+ if (selector >= nSelectors) -+ return RETVAL_DATA_ERROR; -+ hufGroup = bd->groups+selectors[selector++]; -+ base = hufGroup->base-1; -+ limit = hufGroup->limit-1; -+ } -+ /* Read next Huffman-coded symbol. */ -+ /* Note: It is far cheaper to read maxLen bits and -+ back up than it is to read minLen bits and then an -+ additional bit at a time, testing as we go. -+ Because there is a trailing last block (with file -+ CRC), there is no danger of the overread causing an -+ unexpected EOF for a valid compressed file. As a -+ further optimization, we do the read inline -+ (falling back to a call to get_bits if the buffer -+ runs dry). The following (up to got_huff_bits:) is -+ equivalent to j = get_bits(bd, hufGroup->maxLen); -+ */ -+ while (bd->inbufBitCount < hufGroup->maxLen) { -+ if (bd->inbufPos == bd->inbufCount) { -+ j = get_bits(bd, hufGroup->maxLen); -+ goto got_huff_bits; -+ } -+ bd->inbufBits = -+ (bd->inbufBits << 8)|bd->inbuf[bd->inbufPos++]; -+ bd->inbufBitCount += 8; -+ }; -+ bd->inbufBitCount -= hufGroup->maxLen; -+ j = (bd->inbufBits >> bd->inbufBitCount)& -+ ((1 << hufGroup->maxLen)-1); -+got_huff_bits: -+ /* Figure how how many bits are in next symbol and -+ * unget extras */ -+ i = hufGroup->minLen; -+ while (j > limit[i]) -+ ++i; -+ bd->inbufBitCount += (hufGroup->maxLen - i); -+ /* Huffman decode value to get nextSym (with bounds checking) */ -+ if ((i > hufGroup->maxLen) -+ || (((unsigned)(j = (j>>(hufGroup->maxLen-i))-base[i])) -+ >= MAX_SYMBOLS)) -+ return RETVAL_DATA_ERROR; -+ nextSym = hufGroup->permute[j]; -+ /* We have now decoded the symbol, which indicates -+ either a new literal byte, or a repeated run of the -+ most recent literal byte. First, check if nextSym -+ indicates a repeated run, and if so loop collecting -+ how many times to repeat the last literal. */ -+ if (((unsigned)nextSym) <= SYMBOL_RUNB) { /* RUNA or RUNB */ -+ /* If this is the start of a new run, zero out -+ * counter */ -+ if (!runPos) { -+ runPos = 1; -+ t = 0; -+ } -+ /* Neat trick that saves 1 symbol: instead of -+ or-ing 0 or 1 at each bit position, add 1 -+ or 2 instead. For example, 1011 is 1 << 0 -+ + 1 << 1 + 2 << 2. 1010 is 2 << 0 + 2 << 1 -+ + 1 << 2. You can make any bit pattern -+ that way using 1 less symbol than the basic -+ or 0/1 method (except all bits 0, which -+ would use no symbols, but a run of length 0 -+ doesn't mean anything in this context). -+ Thus space is saved. */ -+ t += (runPos << nextSym); -+ /* +runPos if RUNA; +2*runPos if RUNB */ -+ -+ runPos <<= 1; -+ continue; -+ } -+ /* When we hit the first non-run symbol after a run, -+ we now know how many times to repeat the last -+ literal, so append that many copies to our buffer -+ of decoded symbols (dbuf) now. (The last literal -+ used is the one at the head of the mtfSymbol -+ array.) */ -+ if (runPos) { -+ runPos = 0; -+ if (dbufCount+t >= dbufSize) -+ return RETVAL_DATA_ERROR; -+ -+ uc = symToByte[mtfSymbol[0]]; -+ byteCount[uc] += t; -+ while (t--) -+ dbuf[dbufCount++] = uc; -+ } -+ /* Is this the terminating symbol? */ -+ if (nextSym > symTotal) -+ break; -+ /* At this point, nextSym indicates a new literal -+ character. Subtract one to get the position in the -+ MTF array at which this literal is currently to be -+ found. (Note that the result can't be -1 or 0, -+ because 0 and 1 are RUNA and RUNB. But another -+ instance of the first symbol in the mtf array, -+ position 0, would have been handled as part of a -+ run above. Therefore 1 unused mtf position minus 2 -+ non-literal nextSym values equals -1.) */ -+ if (dbufCount >= dbufSize) -+ return RETVAL_DATA_ERROR; -+ i = nextSym - 1; -+ uc = mtfSymbol[i]; -+ /* Adjust the MTF array. Since we typically expect to -+ *move only a small number of symbols, and are bound -+ *by 256 in any case, using memmove here would -+ *typically be bigger and slower due to function call -+ *overhead and other assorted setup costs. */ -+ do { -+ mtfSymbol[i] = mtfSymbol[i-1]; -+ } while (--i); -+ mtfSymbol[0] = uc; -+ uc = symToByte[uc]; -+ /* We have our literal byte. Save it into dbuf. */ -+ byteCount[uc]++; -+ dbuf[dbufCount++] = (unsigned int)uc; -+ } -+ /* At this point, we've read all the Huffman-coded symbols -+ (and repeated runs) for this block from the input stream, -+ and decoded them into the intermediate buffer. There are -+ dbufCount many decoded bytes in dbuf[]. Now undo the -+ Burrows-Wheeler transform on dbuf. See -+ http://dogma.net/markn/articles/bwt/bwt.htm -+ */ -+ /* Turn byteCount into cumulative occurrence counts of 0 to n-1. */ -+ j = 0; -+ for (i = 0; i < 256; i++) { -+ k = j+byteCount[i]; -+ byteCount[i] = j; -+ j = k; -+ } -+ /* Figure out what order dbuf would be in if we sorted it. */ -+ for (i = 0; i < dbufCount; i++) { -+ uc = (unsigned char)(dbuf[i] & 0xff); -+ dbuf[byteCount[uc]] |= (i << 8); -+ byteCount[uc]++; -+ } -+ /* Decode first byte by hand to initialize "previous" byte. -+ Note that it doesn't get output, and if the first three -+ characters are identical it doesn't qualify as a run (hence -+ writeRunCountdown = 5). */ -+ if (dbufCount) { -+ if (origPtr >= dbufCount) -+ return RETVAL_DATA_ERROR; -+ bd->writePos = dbuf[origPtr]; -+ bd->writeCurrent = (unsigned char)(bd->writePos&0xff); -+ bd->writePos >>= 8; -+ bd->writeRunCountdown = 5; -+ } -+ bd->writeCount = dbufCount; -+ -+ return RETVAL_OK; -+} -+ -+/* Undo burrows-wheeler transform on intermediate buffer to produce output. -+ If start_bunzip was initialized with out_fd =-1, then up to len bytes of -+ data are written to outbuf. Return value is number of bytes written or -+ error (all errors are negative numbers). If out_fd!=-1, outbuf and len -+ are ignored, data is written to out_fd and return is RETVAL_OK or error. -+*/ -+ -+static int INIT read_bunzip(struct bunzip_data *bd, char *outbuf, int len) -+{ -+ const unsigned int *dbuf; -+ int pos, xcurrent, previous, gotcount; -+ -+ /* If last read was short due to end of file, return last block now */ -+ if (bd->writeCount < 0) -+ return bd->writeCount; -+ -+ gotcount = 0; -+ dbuf = bd->dbuf; -+ pos = bd->writePos; -+ xcurrent = bd->writeCurrent; -+ -+ /* We will always have pending decoded data to write into the output -+ buffer unless this is the very first call (in which case we haven't -+ Huffman-decoded a block into the intermediate buffer yet). */ -+ -+ if (bd->writeCopies) { -+ /* Inside the loop, writeCopies means extra copies (beyond 1) */ -+ --bd->writeCopies; -+ /* Loop outputting bytes */ -+ for (;;) { -+ /* If the output buffer is full, snapshot -+ * state and return */ -+ if (gotcount >= len) { -+ bd->writePos = pos; -+ bd->writeCurrent = xcurrent; -+ bd->writeCopies++; -+ return len; -+ } -+ /* Write next byte into output buffer, updating CRC */ -+ outbuf[gotcount++] = xcurrent; -+ bd->writeCRC = (((bd->writeCRC) << 8) -+ ^bd->crc32Table[((bd->writeCRC) >> 24) -+ ^xcurrent]); -+ /* Loop now if we're outputting multiple -+ * copies of this byte */ -+ if (bd->writeCopies) { -+ --bd->writeCopies; -+ continue; -+ } -+decode_next_byte: -+ if (!bd->writeCount--) -+ break; -+ /* Follow sequence vector to undo -+ * Burrows-Wheeler transform */ -+ previous = xcurrent; -+ pos = dbuf[pos]; -+ xcurrent = pos&0xff; -+ pos >>= 8; -+ /* After 3 consecutive copies of the same -+ byte, the 4th is a repeat count. We count -+ down from 4 instead *of counting up because -+ testing for non-zero is faster */ -+ if (--bd->writeRunCountdown) { -+ if (xcurrent != previous) -+ bd->writeRunCountdown = 4; -+ } else { -+ /* We have a repeated run, this byte -+ * indicates the count */ -+ bd->writeCopies = xcurrent; -+ xcurrent = previous; -+ bd->writeRunCountdown = 5; -+ /* Sometimes there are just 3 bytes -+ * (run length 0) */ -+ if (!bd->writeCopies) -+ goto decode_next_byte; -+ /* Subtract the 1 copy we'd output -+ * anyway to get extras */ -+ --bd->writeCopies; -+ } -+ } -+ /* Decompression of this block completed successfully */ -+ bd->writeCRC = ~bd->writeCRC; -+ bd->totalCRC = ((bd->totalCRC << 1) | -+ (bd->totalCRC >> 31)) ^ bd->writeCRC; -+ /* If this block had a CRC error, force file level CRC error. */ -+ if (bd->writeCRC != bd->headerCRC) { -+ bd->totalCRC = bd->headerCRC+1; -+ return RETVAL_LAST_BLOCK; -+ } -+ } -+ -+ /* Refill the intermediate buffer by Huffman-decoding next -+ * block of input */ -+ /* (previous is just a convenient unused temp variable here) */ -+ previous = get_next_block(bd); -+ if (previous) { -+ bd->writeCount = previous; -+ return (previous != RETVAL_LAST_BLOCK) ? previous : gotcount; -+ } -+ bd->writeCRC = 0xffffffffUL; -+ pos = bd->writePos; -+ xcurrent = bd->writeCurrent; -+ goto decode_next_byte; -+} -+ -+static int INIT nofill(void *buf, unsigned int len) -+{ -+ return -1; -+} -+ -+/* Allocate the structure, read file header. If in_fd ==-1, inbuf must contain -+ a complete bunzip file (len bytes long). If in_fd!=-1, inbuf and len are -+ ignored, and data is read from file handle into temporary buffer. */ -+static int INIT start_bunzip(struct bunzip_data **bdp, void *inbuf, int len, -+ int (*fill)(void*, unsigned int)) -+{ -+ struct bunzip_data *bd; -+ unsigned int i, j, c; -+ const unsigned int BZh0 = -+ (((unsigned int)'B') << 24)+(((unsigned int)'Z') << 16) -+ +(((unsigned int)'h') << 8)+(unsigned int)'0'; -+ -+ /* Figure out how much data to allocate */ -+ i = sizeof(struct bunzip_data); -+ -+ /* Allocate bunzip_data. Most fields initialize to zero. */ -+ bd = *bdp = malloc(i); -+ memset(bd, 0, sizeof(struct bunzip_data)); -+ /* Setup input buffer */ -+ bd->inbuf = inbuf; -+ bd->inbufCount = len; -+ if (fill != NULL) -+ bd->fill = fill; -+ else -+ bd->fill = nofill; -+ -+ /* Init the CRC32 table (big endian) */ -+ for (i = 0; i < 256; i++) { -+ c = i << 24; -+ for (j = 8; j; j--) -+ c = c&0x80000000 ? (c << 1)^0x04c11db7 : (c << 1); -+ bd->crc32Table[i] = c; -+ } -+ -+ /* Ensure that file starts with "BZh['1'-'9']." */ -+ i = get_bits(bd, 32); -+ if (((unsigned int)(i-BZh0-1)) >= 9) -+ return RETVAL_NOT_BZIP_DATA; -+ -+ /* Fourth byte (ascii '1'-'9'), indicates block size in units of 100k of -+ uncompressed data. Allocate intermediate buffer for block. */ -+ bd->dbufSize = 100000*(i-BZh0); -+ -+ bd->dbuf = large_malloc(bd->dbufSize * sizeof(int)); -+ return RETVAL_OK; -+} -+ -+/* Example usage: decompress src_fd to dst_fd. (Stops at end of bzip2 data, -+ not end of file.) */ -+STATIC int INIT bunzip2(unsigned char *buf, int len, -+ int(*fill)(void*, unsigned int), -+ int(*flush)(void*, unsigned int), -+ unsigned char *outbuf, -+ int *pos, -+ void(*error_fn)(char *x)) -+{ -+ struct bunzip_data *bd; -+ int i = -1; -+ unsigned char *inbuf; -+ -+ set_error_fn(error_fn); -+ if (flush) -+ outbuf = malloc(BZIP2_IOBUF_SIZE); -+ else -+ len -= 4; /* Uncompressed size hack active in pre-boot -+ environment */ -+ if (!outbuf) { -+ error("Could not allocate output bufer"); -+ return -1; -+ } -+ if (buf) -+ inbuf = buf; -+ else -+ inbuf = malloc(BZIP2_IOBUF_SIZE); -+ if (!inbuf) { -+ error("Could not allocate input bufer"); -+ goto exit_0; -+ } -+ i = start_bunzip(&bd, inbuf, len, fill); -+ if (!i) { -+ for (;;) { -+ i = read_bunzip(bd, outbuf, BZIP2_IOBUF_SIZE); -+ if (i <= 0) -+ break; -+ if (!flush) -+ outbuf += i; -+ else -+ if (i != flush(outbuf, i)) { -+ i = RETVAL_UNEXPECTED_OUTPUT_EOF; -+ break; -+ } -+ } -+ } -+ /* Check CRC and release memory */ -+ if (i == RETVAL_LAST_BLOCK) { -+ if (bd->headerCRC != bd->totalCRC) -+ error("Data integrity error when decompressing."); -+ else -+ i = RETVAL_OK; -+ } else if (i == RETVAL_UNEXPECTED_OUTPUT_EOF) { -+ error("Compressed file ends unexpectedly"); -+ } -+ if (bd->dbuf) -+ large_free(bd->dbuf); -+ if (pos) -+ *pos = bd->inbufPos; -+ free(bd); -+ if (!buf) -+ free(inbuf); -+exit_0: -+ if (flush) -+ free(outbuf); -+ return i; -+} -+ -+#define decompress bunzip2 ---- /dev/null -+++ b/lib/decompress_unlzma.c -@@ -0,0 +1,647 @@ -+/* Lzma decompressor for Linux kernel. Shamelessly snarfed -+ *from busybox 1.1.1 -+ * -+ *Linux kernel adaptation -+ *Copyright (C) 2006 Alain < alain@knaff.lu > -+ * -+ *Based on small lzma deflate implementation/Small range coder -+ *implementation for lzma. -+ *Copyright (C) 2006 Aurelien Jacobs < aurel@gnuage.org > -+ * -+ *Based on LzmaDecode.c from the LZMA SDK 4.22 (http://www.7-zip.org/) -+ *Copyright (C) 1999-2005 Igor Pavlov -+ * -+ *Copyrights of the parts, see headers below. -+ * -+ * -+ *This program is free software; you can redistribute it and/or -+ *modify it under the terms of the GNU Lesser General Public -+ *License as published by the Free Software Foundation; either -+ *version 2.1 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 -+ *Lesser General Public License for more details. -+ * -+ *You should have received a copy of the GNU Lesser General Public -+ *License along with this library; if not, write to the Free Software -+ *Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -+ */ -+ -+#ifndef STATIC -+#include -+#endif /* STATIC */ -+ -+#include -+ -+#define MIN(a, b) (((a) < (b)) ? (a) : (b)) -+ -+static long long INIT read_int(unsigned char *ptr, int size) -+{ -+ int i; -+ long long ret = 0; -+ -+ for (i = 0; i < size; i++) -+ ret = (ret << 8) | ptr[size-i-1]; -+ return ret; -+} -+ -+#define ENDIAN_CONVERT(x) \ -+ x = (typeof(x))read_int((unsigned char *)&x, sizeof(x)) -+ -+ -+/* Small range coder implementation for lzma. -+ *Copyright (C) 2006 Aurelien Jacobs < aurel@gnuage.org > -+ * -+ *Based on LzmaDecode.c from the LZMA SDK 4.22 (http://www.7-zip.org/) -+ *Copyright (c) 1999-2005 Igor Pavlov -+ */ -+ -+#include -+ -+#define LZMA_IOBUF_SIZE 0x10000 -+ -+struct rc { -+ int (*fill)(void*, unsigned int); -+ uint8_t *ptr; -+ uint8_t *buffer; -+ uint8_t *buffer_end; -+ int buffer_size; -+ uint32_t code; -+ uint32_t range; -+ uint32_t bound; -+}; -+ -+ -+#define RC_TOP_BITS 24 -+#define RC_MOVE_BITS 5 -+#define RC_MODEL_TOTAL_BITS 11 -+ -+ -+/* Called twice: once at startup and once in rc_normalize() */ -+static void INIT rc_read(struct rc *rc) -+{ -+ rc->buffer_size = rc->fill((char *)rc->buffer, LZMA_IOBUF_SIZE); -+ if (rc->buffer_size <= 0) -+ error("unexpected EOF"); -+ rc->ptr = rc->buffer; -+ rc->buffer_end = rc->buffer + rc->buffer_size; -+} -+ -+/* Called once */ -+static inline void INIT rc_init(struct rc *rc, -+ int (*fill)(void*, unsigned int), -+ char *buffer, int buffer_size) -+{ -+ rc->fill = fill; -+ rc->buffer = (uint8_t *)buffer; -+ rc->buffer_size = buffer_size; -+ rc->buffer_end = rc->buffer + rc->buffer_size; -+ rc->ptr = rc->buffer; -+ -+ rc->code = 0; -+ rc->range = 0xFFFFFFFF; -+} -+ -+static inline void INIT rc_init_code(struct rc *rc) -+{ -+ int i; -+ -+ for (i = 0; i < 5; i++) { -+ if (rc->ptr >= rc->buffer_end) -+ rc_read(rc); -+ rc->code = (rc->code << 8) | *rc->ptr++; -+ } -+} -+ -+ -+/* Called once. TODO: bb_maybe_free() */ -+static inline void INIT rc_free(struct rc *rc) -+{ -+ free(rc->buffer); -+} -+ -+/* Called twice, but one callsite is in inline'd rc_is_bit_0_helper() */ -+static void INIT rc_do_normalize(struct rc *rc) -+{ -+ if (rc->ptr >= rc->buffer_end) -+ rc_read(rc); -+ rc->range <<= 8; -+ rc->code = (rc->code << 8) | *rc->ptr++; -+} -+static inline void INIT rc_normalize(struct rc *rc) -+{ -+ if (rc->range < (1 << RC_TOP_BITS)) -+ rc_do_normalize(rc); -+} -+ -+/* Called 9 times */ -+/* Why rc_is_bit_0_helper exists? -+ *Because we want to always expose (rc->code < rc->bound) to optimizer -+ */ -+static inline uint32_t INIT rc_is_bit_0_helper(struct rc *rc, uint16_t *p) -+{ -+ rc_normalize(rc); -+ rc->bound = *p * (rc->range >> RC_MODEL_TOTAL_BITS); -+ return rc->bound; -+} -+static inline int INIT rc_is_bit_0(struct rc *rc, uint16_t *p) -+{ -+ uint32_t t = rc_is_bit_0_helper(rc, p); -+ return rc->code < t; -+} -+ -+/* Called ~10 times, but very small, thus inlined */ -+static inline void INIT rc_update_bit_0(struct rc *rc, uint16_t *p) -+{ -+ rc->range = rc->bound; -+ *p += ((1 << RC_MODEL_TOTAL_BITS) - *p) >> RC_MOVE_BITS; -+} -+static inline void rc_update_bit_1(struct rc *rc, uint16_t *p) -+{ -+ rc->range -= rc->bound; -+ rc->code -= rc->bound; -+ *p -= *p >> RC_MOVE_BITS; -+} -+ -+/* Called 4 times in unlzma loop */ -+static int INIT rc_get_bit(struct rc *rc, uint16_t *p, int *symbol) -+{ -+ if (rc_is_bit_0(rc, p)) { -+ rc_update_bit_0(rc, p); -+ *symbol *= 2; -+ return 0; -+ } else { -+ rc_update_bit_1(rc, p); -+ *symbol = *symbol * 2 + 1; -+ return 1; -+ } -+} -+ -+/* Called once */ -+static inline int INIT rc_direct_bit(struct rc *rc) -+{ -+ rc_normalize(rc); -+ rc->range >>= 1; -+ if (rc->code >= rc->range) { -+ rc->code -= rc->range; -+ return 1; -+ } -+ return 0; -+} -+ -+/* Called twice */ -+static inline void INIT -+rc_bit_tree_decode(struct rc *rc, uint16_t *p, int num_levels, int *symbol) -+{ -+ int i = num_levels; -+ -+ *symbol = 1; -+ while (i--) -+ rc_get_bit(rc, p + *symbol, symbol); -+ *symbol -= 1 << num_levels; -+} -+ -+ -+/* -+ * Small lzma deflate implementation. -+ * Copyright (C) 2006 Aurelien Jacobs < aurel@gnuage.org > -+ * -+ * Based on LzmaDecode.c from the LZMA SDK 4.22 (http://www.7-zip.org/) -+ * Copyright (C) 1999-2005 Igor Pavlov -+ */ -+ -+ -+struct lzma_header { -+ uint8_t pos; -+ uint32_t dict_size; -+ uint64_t dst_size; -+} __attribute__ ((packed)) ; -+ -+ -+#define LZMA_BASE_SIZE 1846 -+#define LZMA_LIT_SIZE 768 -+ -+#define LZMA_NUM_POS_BITS_MAX 4 -+ -+#define LZMA_LEN_NUM_LOW_BITS 3 -+#define LZMA_LEN_NUM_MID_BITS 3 -+#define LZMA_LEN_NUM_HIGH_BITS 8 -+ -+#define LZMA_LEN_CHOICE 0 -+#define LZMA_LEN_CHOICE_2 (LZMA_LEN_CHOICE + 1) -+#define LZMA_LEN_LOW (LZMA_LEN_CHOICE_2 + 1) -+#define LZMA_LEN_MID (LZMA_LEN_LOW \ -+ + (1 << (LZMA_NUM_POS_BITS_MAX + LZMA_LEN_NUM_LOW_BITS))) -+#define LZMA_LEN_HIGH (LZMA_LEN_MID \ -+ +(1 << (LZMA_NUM_POS_BITS_MAX + LZMA_LEN_NUM_MID_BITS))) -+#define LZMA_NUM_LEN_PROBS (LZMA_LEN_HIGH + (1 << LZMA_LEN_NUM_HIGH_BITS)) -+ -+#define LZMA_NUM_STATES 12 -+#define LZMA_NUM_LIT_STATES 7 -+ -+#define LZMA_START_POS_MODEL_INDEX 4 -+#define LZMA_END_POS_MODEL_INDEX 14 -+#define LZMA_NUM_FULL_DISTANCES (1 << (LZMA_END_POS_MODEL_INDEX >> 1)) -+ -+#define LZMA_NUM_POS_SLOT_BITS 6 -+#define LZMA_NUM_LEN_TO_POS_STATES 4 -+ -+#define LZMA_NUM_ALIGN_BITS 4 -+ -+#define LZMA_MATCH_MIN_LEN 2 -+ -+#define LZMA_IS_MATCH 0 -+#define LZMA_IS_REP (LZMA_IS_MATCH + (LZMA_NUM_STATES << LZMA_NUM_POS_BITS_MAX)) -+#define LZMA_IS_REP_G0 (LZMA_IS_REP + LZMA_NUM_STATES) -+#define LZMA_IS_REP_G1 (LZMA_IS_REP_G0 + LZMA_NUM_STATES) -+#define LZMA_IS_REP_G2 (LZMA_IS_REP_G1 + LZMA_NUM_STATES) -+#define LZMA_IS_REP_0_LONG (LZMA_IS_REP_G2 + LZMA_NUM_STATES) -+#define LZMA_POS_SLOT (LZMA_IS_REP_0_LONG \ -+ + (LZMA_NUM_STATES << LZMA_NUM_POS_BITS_MAX)) -+#define LZMA_SPEC_POS (LZMA_POS_SLOT \ -+ +(LZMA_NUM_LEN_TO_POS_STATES << LZMA_NUM_POS_SLOT_BITS)) -+#define LZMA_ALIGN (LZMA_SPEC_POS \ -+ + LZMA_NUM_FULL_DISTANCES - LZMA_END_POS_MODEL_INDEX) -+#define LZMA_LEN_CODER (LZMA_ALIGN + (1 << LZMA_NUM_ALIGN_BITS)) -+#define LZMA_REP_LEN_CODER (LZMA_LEN_CODER + LZMA_NUM_LEN_PROBS) -+#define LZMA_LITERAL (LZMA_REP_LEN_CODER + LZMA_NUM_LEN_PROBS) -+ -+ -+struct writer { -+ uint8_t *buffer; -+ uint8_t previous_byte; -+ size_t buffer_pos; -+ int bufsize; -+ size_t global_pos; -+ int(*flush)(void*, unsigned int); -+ struct lzma_header *header; -+}; -+ -+struct cstate { -+ int state; -+ uint32_t rep0, rep1, rep2, rep3; -+}; -+ -+static inline size_t INIT get_pos(struct writer *wr) -+{ -+ return -+ wr->global_pos + wr->buffer_pos; -+} -+ -+static inline uint8_t INIT peek_old_byte(struct writer *wr, -+ uint32_t offs) -+{ -+ if (!wr->flush) { -+ int32_t pos; -+ while (offs > wr->header->dict_size) -+ offs -= wr->header->dict_size; -+ pos = wr->buffer_pos - offs; -+ return wr->buffer[pos]; -+ } else { -+ uint32_t pos = wr->buffer_pos - offs; -+ while (pos >= wr->header->dict_size) -+ pos += wr->header->dict_size; -+ return wr->buffer[pos]; -+ } -+ -+} -+ -+static inline void INIT write_byte(struct writer *wr, uint8_t byte) -+{ -+ wr->buffer[wr->buffer_pos++] = wr->previous_byte = byte; -+ if (wr->flush && wr->buffer_pos == wr->header->dict_size) { -+ wr->buffer_pos = 0; -+ wr->global_pos += wr->header->dict_size; -+ wr->flush((char *)wr->buffer, wr->header->dict_size); -+ } -+} -+ -+ -+static inline void INIT copy_byte(struct writer *wr, uint32_t offs) -+{ -+ write_byte(wr, peek_old_byte(wr, offs)); -+} -+ -+static inline void INIT copy_bytes(struct writer *wr, -+ uint32_t rep0, int len) -+{ -+ do { -+ copy_byte(wr, rep0); -+ len--; -+ } while (len != 0 && wr->buffer_pos < wr->header->dst_size); -+} -+ -+static inline void INIT process_bit0(struct writer *wr, struct rc *rc, -+ struct cstate *cst, uint16_t *p, -+ int pos_state, uint16_t *prob, -+ int lc, uint32_t literal_pos_mask) { -+ int mi = 1; -+ rc_update_bit_0(rc, prob); -+ prob = (p + LZMA_LITERAL + -+ (LZMA_LIT_SIZE -+ * (((get_pos(wr) & literal_pos_mask) << lc) -+ + (wr->previous_byte >> (8 - lc)))) -+ ); -+ -+ if (cst->state >= LZMA_NUM_LIT_STATES) { -+ int match_byte = peek_old_byte(wr, cst->rep0); -+ do { -+ int bit; -+ uint16_t *prob_lit; -+ -+ match_byte <<= 1; -+ bit = match_byte & 0x100; -+ prob_lit = prob + 0x100 + bit + mi; -+ if (rc_get_bit(rc, prob_lit, &mi)) { -+ if (!bit) -+ break; -+ } else { -+ if (bit) -+ break; -+ } -+ } while (mi < 0x100); -+ } -+ while (mi < 0x100) { -+ uint16_t *prob_lit = prob + mi; -+ rc_get_bit(rc, prob_lit, &mi); -+ } -+ write_byte(wr, mi); -+ if (cst->state < 4) -+ cst->state = 0; -+ else if (cst->state < 10) -+ cst->state -= 3; -+ else -+ cst->state -= 6; -+} -+ -+static inline void INIT process_bit1(struct writer *wr, struct rc *rc, -+ struct cstate *cst, uint16_t *p, -+ int pos_state, uint16_t *prob) { -+ int offset; -+ uint16_t *prob_len; -+ int num_bits; -+ int len; -+ -+ rc_update_bit_1(rc, prob); -+ prob = p + LZMA_IS_REP + cst->state; -+ if (rc_is_bit_0(rc, prob)) { -+ rc_update_bit_0(rc, prob); -+ cst->rep3 = cst->rep2; -+ cst->rep2 = cst->rep1; -+ cst->rep1 = cst->rep0; -+ cst->state = cst->state < LZMA_NUM_LIT_STATES ? 0 : 3; -+ prob = p + LZMA_LEN_CODER; -+ } else { -+ rc_update_bit_1(rc, prob); -+ prob = p + LZMA_IS_REP_G0 + cst->state; -+ if (rc_is_bit_0(rc, prob)) { -+ rc_update_bit_0(rc, prob); -+ prob = (p + LZMA_IS_REP_0_LONG -+ + (cst->state << -+ LZMA_NUM_POS_BITS_MAX) + -+ pos_state); -+ if (rc_is_bit_0(rc, prob)) { -+ rc_update_bit_0(rc, prob); -+ -+ cst->state = cst->state < LZMA_NUM_LIT_STATES ? -+ 9 : 11; -+ copy_byte(wr, cst->rep0); -+ return; -+ } else { -+ rc_update_bit_1(rc, prob); -+ } -+ } else { -+ uint32_t distance; -+ -+ rc_update_bit_1(rc, prob); -+ prob = p + LZMA_IS_REP_G1 + cst->state; -+ if (rc_is_bit_0(rc, prob)) { -+ rc_update_bit_0(rc, prob); -+ distance = cst->rep1; -+ } else { -+ rc_update_bit_1(rc, prob); -+ prob = p + LZMA_IS_REP_G2 + cst->state; -+ if (rc_is_bit_0(rc, prob)) { -+ rc_update_bit_0(rc, prob); -+ distance = cst->rep2; -+ } else { -+ rc_update_bit_1(rc, prob); -+ distance = cst->rep3; -+ cst->rep3 = cst->rep2; -+ } -+ cst->rep2 = cst->rep1; -+ } -+ cst->rep1 = cst->rep0; -+ cst->rep0 = distance; -+ } -+ cst->state = cst->state < LZMA_NUM_LIT_STATES ? 8 : 11; -+ prob = p + LZMA_REP_LEN_CODER; -+ } -+ -+ prob_len = prob + LZMA_LEN_CHOICE; -+ if (rc_is_bit_0(rc, prob_len)) { -+ rc_update_bit_0(rc, prob_len); -+ prob_len = (prob + LZMA_LEN_LOW -+ + (pos_state << -+ LZMA_LEN_NUM_LOW_BITS)); -+ offset = 0; -+ num_bits = LZMA_LEN_NUM_LOW_BITS; -+ } else { -+ rc_update_bit_1(rc, prob_len); -+ prob_len = prob + LZMA_LEN_CHOICE_2; -+ if (rc_is_bit_0(rc, prob_len)) { -+ rc_update_bit_0(rc, prob_len); -+ prob_len = (prob + LZMA_LEN_MID -+ + (pos_state << -+ LZMA_LEN_NUM_MID_BITS)); -+ offset = 1 << LZMA_LEN_NUM_LOW_BITS; -+ num_bits = LZMA_LEN_NUM_MID_BITS; -+ } else { -+ rc_update_bit_1(rc, prob_len); -+ prob_len = prob + LZMA_LEN_HIGH; -+ offset = ((1 << LZMA_LEN_NUM_LOW_BITS) -+ + (1 << LZMA_LEN_NUM_MID_BITS)); -+ num_bits = LZMA_LEN_NUM_HIGH_BITS; -+ } -+ } -+ -+ rc_bit_tree_decode(rc, prob_len, num_bits, &len); -+ len += offset; -+ -+ if (cst->state < 4) { -+ int pos_slot; -+ -+ cst->state += LZMA_NUM_LIT_STATES; -+ prob = -+ p + LZMA_POS_SLOT + -+ ((len < -+ LZMA_NUM_LEN_TO_POS_STATES ? len : -+ LZMA_NUM_LEN_TO_POS_STATES - 1) -+ << LZMA_NUM_POS_SLOT_BITS); -+ rc_bit_tree_decode(rc, prob, -+ LZMA_NUM_POS_SLOT_BITS, -+ &pos_slot); -+ if (pos_slot >= LZMA_START_POS_MODEL_INDEX) { -+ int i, mi; -+ num_bits = (pos_slot >> 1) - 1; -+ cst->rep0 = 2 | (pos_slot & 1); -+ if (pos_slot < LZMA_END_POS_MODEL_INDEX) { -+ cst->rep0 <<= num_bits; -+ prob = p + LZMA_SPEC_POS + -+ cst->rep0 - pos_slot - 1; -+ } else { -+ num_bits -= LZMA_NUM_ALIGN_BITS; -+ while (num_bits--) -+ cst->rep0 = (cst->rep0 << 1) | -+ rc_direct_bit(rc); -+ prob = p + LZMA_ALIGN; -+ cst->rep0 <<= LZMA_NUM_ALIGN_BITS; -+ num_bits = LZMA_NUM_ALIGN_BITS; -+ } -+ i = 1; -+ mi = 1; -+ while (num_bits--) { -+ if (rc_get_bit(rc, prob + mi, &mi)) -+ cst->rep0 |= i; -+ i <<= 1; -+ } -+ } else -+ cst->rep0 = pos_slot; -+ if (++(cst->rep0) == 0) -+ return; -+ } -+ -+ len += LZMA_MATCH_MIN_LEN; -+ -+ copy_bytes(wr, cst->rep0, len); -+} -+ -+ -+ -+STATIC inline int INIT unlzma(unsigned char *buf, int in_len, -+ int(*fill)(void*, unsigned int), -+ int(*flush)(void*, unsigned int), -+ unsigned char *output, -+ int *posp, -+ void(*error_fn)(char *x) -+ ) -+{ -+ struct lzma_header header; -+ int lc, pb, lp; -+ uint32_t pos_state_mask; -+ uint32_t literal_pos_mask; -+ uint16_t *p; -+ int num_probs; -+ struct rc rc; -+ int i, mi; -+ struct writer wr; -+ struct cstate cst; -+ unsigned char *inbuf; -+ int ret = -1; -+ -+ set_error_fn(error_fn); -+ if (!flush) -+ in_len -= 4; /* Uncompressed size hack active in pre-boot -+ environment */ -+ if (buf) -+ inbuf = buf; -+ else -+ inbuf = malloc(LZMA_IOBUF_SIZE); -+ if (!inbuf) { -+ error("Could not allocate input bufer"); -+ goto exit_0; -+ } -+ -+ cst.state = 0; -+ cst.rep0 = cst.rep1 = cst.rep2 = cst.rep3 = 1; -+ -+ wr.header = &header; -+ wr.flush = flush; -+ wr.global_pos = 0; -+ wr.previous_byte = 0; -+ wr.buffer_pos = 0; -+ -+ rc_init(&rc, fill, inbuf, in_len); -+ -+ for (i = 0; i < sizeof(header); i++) { -+ if (rc.ptr >= rc.buffer_end) -+ rc_read(&rc); -+ ((unsigned char *)&header)[i] = *rc.ptr++; -+ } -+ -+ if (header.pos >= (9 * 5 * 5)) -+ error("bad header"); -+ -+ mi = 0; -+ lc = header.pos; -+ while (lc >= 9) { -+ mi++; -+ lc -= 9; -+ } -+ pb = 0; -+ lp = mi; -+ while (lp >= 5) { -+ pb++; -+ lp -= 5; -+ } -+ pos_state_mask = (1 << pb) - 1; -+ literal_pos_mask = (1 << lp) - 1; -+ -+ ENDIAN_CONVERT(header.dict_size); -+ ENDIAN_CONVERT(header.dst_size); -+ -+ if (header.dict_size == 0) -+ header.dict_size = 1; -+ -+ if (output) -+ wr.buffer = output; -+ else { -+ wr.bufsize = MIN(header.dst_size, header.dict_size); -+ wr.buffer = large_malloc(wr.bufsize); -+ } -+ if (wr.buffer == NULL) -+ goto exit_1; -+ -+ num_probs = LZMA_BASE_SIZE + (LZMA_LIT_SIZE << (lc + lp)); -+ p = (uint16_t *) large_malloc(num_probs * sizeof(*p)); -+ if (p == 0) -+ goto exit_2; -+ num_probs = LZMA_LITERAL + (LZMA_LIT_SIZE << (lc + lp)); -+ for (i = 0; i < num_probs; i++) -+ p[i] = (1 << RC_MODEL_TOTAL_BITS) >> 1; -+ -+ rc_init_code(&rc); -+ -+ while (get_pos(&wr) < header.dst_size) { -+ int pos_state = get_pos(&wr) & pos_state_mask; -+ uint16_t *prob = p + LZMA_IS_MATCH + -+ (cst.state << LZMA_NUM_POS_BITS_MAX) + pos_state; -+ if (rc_is_bit_0(&rc, prob)) -+ process_bit0(&wr, &rc, &cst, p, pos_state, prob, -+ lc, literal_pos_mask); -+ else { -+ process_bit1(&wr, &rc, &cst, p, pos_state, prob); -+ if (cst.rep0 == 0) -+ break; -+ } -+ } -+ -+ if (posp) -+ *posp = rc.ptr-rc.buffer; -+ if (wr.flush) -+ wr.flush(wr.buffer, wr.buffer_pos); -+ ret = 0; -+ large_free(p); -+exit_2: -+ if (!output) -+ large_free(wr.buffer); -+exit_1: -+ if (!buf) -+ free(inbuf); -+exit_0: -+ return ret; -+} -+ -+#define decompress unlzma ---- a/lib/inflate.c -+++ b/lib/inflate.c -@@ -109,20 +109,78 @@ static char rcsid[] = "#Id: inflate.c,v - #endif - - #ifndef STATIC -+#include -+#endif /* ! STATIC */ - --#if defined(STDC_HEADERS) || defined(HAVE_STDLIB_H) --# include --# include -+#include -+ -+#include -+ -+#ifdef NEW_CODE -+static int(*flush_cb)(void*, unsigned int); -+static int(*fill_cb)(void*, unsigned int); -+ -+/* Begin stuff copied from initramfs */ -+/* -+ * gzip declarations -+ */ -+ -+#define OF(args) args -+ -+#ifndef memzero -+#define memzero(s, n) memset((s), 0, (n)) - #endif - --#include "gzip.h" --#define STATIC --#endif /* !STATIC */ -+#define INBUFSIZ 4096 -+ -+#define WSIZE 0x8000 /* window size--must be a power of two, and */ -+ /* at least 32K for zip's deflate method */ -+ -+static uint8_t *inbuf; -+static uint8_t *window; -+ -+static unsigned insize; /* valid bytes in inbuf */ -+static unsigned outcnt; /* bytes in output buffer */ -+static long bytes_out; -+ -+/* --- */ -+ -+static unsigned inptr; /* index of next byte to be processed in inbuf */ -+ -+/* --- */ -+ -+/* =========================================================================== -+ * Fill the input buffer. This is called only when the buffer is empty -+ * and at least one byte is really needed. -+ * Returning -1 does not guarantee that gunzip() will ever return. -+ */ -+static int INIT fill_inbuf(void) -+{ -+ insize = fill_cb(inbuf, INBUFSIZ); -+ if (insize <= 0) { -+ error("RAMDISK: ran out of compressed data"); -+ return -1; -+ } -+ -+ inptr = 1; -+ -+ return inbuf[0]; -+} -+ -+#define get_byte() (inptr < insize ? inbuf[inptr++] : fill_inbuf()) -+ -+/* Diagnostic functions (stubbed out) */ -+#define Assert(cond, msg) -+#define Trace(x) -+#define Tracev(x) -+#define Tracevv(x) -+#define Tracec(c, x) -+#define Tracecv(c, x) - --#ifndef INIT --#define INIT -+static void flush_window(void); -+/* End stuff copied from initramfs */ - #endif -- -+ - #define slide window - - /* Huffman code lookup table entry--this entry is four bytes for machines -@@ -133,10 +191,10 @@ static char rcsid[] = "#Id: inflate.c,v - an unused code. If a code with e == 99 is looked up, this implies an - error in the data. */ - struct huft { -- uch e; /* number of extra bits or operation */ -- uch b; /* number of bits in this code or subcode */ -+ uint8_t e; /* number of extra bits or operation */ -+ uint8_t b; /* number of bits in this code or subcode */ - union { -- ush n; /* literal, length base, or distance base */ -+ uint16_t n; /* literal, length base, or distance base */ - struct huft *t; /* pointer to next level of table */ - } v; - }; -@@ -144,7 +202,7 @@ struct huft { - - /* Function prototypes */ - STATIC int INIT huft_build OF((unsigned *, unsigned, unsigned, -- const ush *, const ush *, struct huft **, int *)); -+ const uint16_t *, const uint16_t *, struct huft **, int *)); - STATIC int INIT huft_free OF((struct huft *)); - STATIC int INIT inflate_codes OF((struct huft *, struct huft *, int, int)); - STATIC int INIT inflate_stored OF((void)); -@@ -159,28 +217,28 @@ STATIC int INIT inflate OF((void)); - circular buffer. The index is updated simply by incrementing and then - ANDing with 0x7fff (32K-1). */ - /* It is left to other modules to supply the 32 K area. It is assumed -- to be usable as if it were declared "uch slide[32768];" or as just -- "uch *slide;" and then malloc'ed in the latter case. The definition -+ to be usable as if it were declared "uint8_t slide[32768];" or as just -+ "uint8_t *slide;" and then malloc'ed in the latter case. The definition - must be in unzip.h, included above. */ - /* unsigned wp; current position in slide */ - #define wp outcnt - #define flush_output(w) (wp=(w),flush_window()) - - /* Tables for deflate from PKZIP's appnote.txt. */ --static const unsigned border[] = { /* Order of the bit length code lengths */ -+static const unsigned border[] = { /* Order of the bit length code lengths */ - 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; --static const ush cplens[] = { /* Copy lengths for literal codes 257..285 */ -+static const uint16_t cplens[] = { /* Copy lengths for literal codes 257..285 */ - 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, - 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0}; - /* note: see note #13 above about the 258 in this list. */ --static const ush cplext[] = { /* Extra bits for literal codes 257..285 */ -+static const uint16_t cplext[] = { /* Extra bits for literal codes 257..285 */ - 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, - 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 99, 99}; /* 99==invalid */ --static const ush cpdist[] = { /* Copy offsets for distance codes 0..29 */ -+static const uint16_t cpdist[] = { /* Copy offsets for distance codes 0..29 */ - 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, - 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, - 8193, 12289, 16385, 24577}; --static const ush cpdext[] = { /* Extra bits for distance codes */ -+static const uint16_t cpdext[] = { /* Extra bits for distance codes */ - 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, - 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, - 12, 12, 13, 13}; -@@ -217,59 +275,21 @@ static const ush cpdext[] = { /* - the stream. - */ - --STATIC ulg bb; /* bit buffer */ -+STATIC uint32_t bb; /* bit buffer */ - STATIC unsigned bk; /* bits in bit buffer */ - --STATIC const ush mask_bits[] = { -+STATIC const uint16_t mask_bits[] = { - 0x0000, - 0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff, - 0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff - }; - --#define NEXTBYTE() ({ int v = get_byte(); if (v < 0) goto underrun; (uch)v; }) --#define NEEDBITS(n) {while(k<(n)){b|=((ulg)NEXTBYTE())<>=(n);k-=(n);} - --#ifndef NO_INFLATE_MALLOC --/* A trivial malloc implementation, adapted from -- * malloc by Hannu Savolainen 1993 and Matthias Urlichs 1994 -- */ -- --static unsigned long malloc_ptr; --static int malloc_count; -- --static void *malloc(int size) --{ -- void *p; -- -- if (size < 0) -- error("Malloc error"); -- if (!malloc_ptr) -- malloc_ptr = free_mem_ptr; -- -- malloc_ptr = (malloc_ptr + 3) & ~3; /* Align */ -- -- p = (void *)malloc_ptr; -- malloc_ptr += size; -- -- if (free_mem_end_ptr && malloc_ptr >= free_mem_end_ptr) -- error("Out of memory"); -- -- malloc_count++; -- return p; --} -- --static void free(void *where) --{ -- malloc_count--; -- if (!malloc_count) -- malloc_ptr = free_mem_ptr; --} --#else --#define malloc(a) kmalloc(a, GFP_KERNEL) --#define free(a) kfree(a) --#endif -- - /* - Huffman code decoding is performed using a multi-level table lookup. - The fastest way to decode is to simply build a lookup table whose -@@ -307,7 +327,7 @@ STATIC const int lbits = 9; /* - STATIC const int dbits = 6; /* bits in base distance lookup table */ - - --/* If BMAX needs to be larger than 16, then h and x[] should be ulg. */ -+/* If BMAX needs to be larger than 16, then h and x[] should be uint32_t. */ - #define BMAX 16 /* maximum bit length of any code (16 for explode) */ - #define N_MAX 288 /* maximum number of codes in any set */ - -@@ -319,8 +339,8 @@ STATIC int INIT huft_build( - unsigned *b, /* code lengths in bits (all assumed <= BMAX) */ - unsigned n, /* number of codes (assumed <= N_MAX) */ - unsigned s, /* number of simple-valued codes (0..s-1) */ -- const ush *d, /* list of base values for non-simple codes */ -- const ush *e, /* list of extra bits for non-simple codes */ -+ const uint16_t *d, /* list of base values for non-simple codes */ -+ const uint16_t *e, /* list of extra bits for non-simple codes */ - struct huft **t, /* result: starting table */ - int *m /* maximum lookup bits, returns actual */ - ) -@@ -500,8 +520,8 @@ DEBG1("5 "); - if (h) - { - x[h] = i; /* save pattern for backing up */ -- r.b = (uch)l; /* bits to dump before this table */ -- r.e = (uch)(16 + j); /* bits in this table */ -+ r.b = (uint8_t)l; /* bits to dump before this table */ -+ r.e = (uint8_t)(16 + j); /* bits in this table */ - r.v.t = q; /* pointer to this table */ - j = i >> (w - l); /* (get around Turbo C bug) */ - u[h-1][j] = r; /* connect to last table */ -@@ -511,18 +531,18 @@ DEBG1("6 "); - DEBG("h6c "); - - /* set up table entry in r */ -- r.b = (uch)(k - w); -+ r.b = (uint8_t)(k - w); - if (p >= v + n) - r.e = 99; /* out of values--invalid code */ - else if (*p < s) - { -- r.e = (uch)(*p < 256 ? 16 : 15); /* 256 is end-of-block code */ -- r.v.n = (ush)(*p); /* simple code is just the value */ -+ r.e = (uint8_t)(*p < 256 ? 16 : 15); /* 256 is end-of-block code */ -+ r.v.n = (uint16_t)(*p); /* simple code is just the value */ - p++; /* one compiler does not like *p++ */ - } - else - { -- r.e = (uch)e[*p - s]; /* non-simple--look up in lists */ -+ r.e = (uint8_t)e[*p - s]; /* non-simple--look up in lists */ - r.v.n = d[*p++ - s]; - } - DEBG("h6d "); -@@ -592,11 +612,12 @@ STATIC int INIT inflate_codes( - Return an error code or zero if it all goes ok. */ - { - register unsigned e; /* table entry flag/number of extra bits */ -- unsigned n, d; /* length and index for copy */ -+ unsigned n; -+ int d; /* source index for copy */ - unsigned w; /* current window position */ - struct huft *t; /* pointer to table entry */ - unsigned ml, md; /* masks for bl and bd bits */ -- register ulg b; /* bit buffer */ -+ register uint32_t b; /* bit buffer */ - register unsigned k; /* number of bits in bit buffer */ - - -@@ -622,7 +643,7 @@ STATIC int INIT inflate_codes( - DUMPBITS(t->b) - if (e == 16) /* then it's a literal */ - { -- slide[w++] = (uch)t->v.n; -+ slide[w++] = (uint8_t)t->v.n; - Tracevv((stderr, "%c", slide[w-1])); - if (w == WSIZE) - { -@@ -659,11 +680,25 @@ STATIC int INIT inflate_codes( - - /* do the copy */ - do { -- n -= (e = (e = WSIZE - ((d &= WSIZE-1) > w ? d : w)) > n ? n : e); -+#ifdef NEW_CODE -+ if (flush_cb) { -+#endif -+ /* Sliding window emulated using circular buffer: -+ * manage wrap-around */ -+ e = WSIZE - ((d &= WSIZE-1) > w ? d : w); -+ if (e > n) -+ e = n; -+#ifdef NEW_CODE -+ } else { -+ e = n; -+ } -+#endif -+ n -= e; -+ - #if !defined(NOMEMCPY) && !defined(DEBUG) - if (w - d >= e) /* (this test assumes unsigned comparison) */ - { -- memcpy(slide + w, slide + d, e); -+ memcpy(slide + w, slide + d, e); - w += e; - d += e; - } -@@ -673,9 +708,8 @@ STATIC int INIT inflate_codes( - slide[w++] = slide[d++]; - Tracevv((stderr, "%c", slide[w-1])); - } while (--e); -- if (w == WSIZE) -- { -- flush_output(w); -+ if (w == WSIZE) { -+ flush_output(w); - w = 0; - } - } while (n); -@@ -702,7 +736,7 @@ STATIC int INIT inflate_stored(void) - { - unsigned n; /* number of bytes in block */ - unsigned w; /* current window position */ -- register ulg b; /* bit buffer */ -+ register uint32_t b; /* bit buffer */ - register unsigned k; /* number of bits in bit buffer */ - - DEBG("> 8); -+ } -+ crc = c; -+ bytes_out += (uint32_t)outcnt; -+ if (flush_cb != NULL) -+ flush_cb(window, outcnt); /* TODO: handle unzip_error */ -+ else -+ window += outcnt; -+ outcnt = 0; -+} -+ -+static int empty_fill(void *buf, unsigned int len) -+{ -+ return 0; -+} -+#endif -+ -+ - /* - * Do the uncompression! - */ --static int INIT gunzip(void) -+STATIC int INIT gunzip( -+#ifdef NEW_CODE -+ unsigned char *buf, int len, -+ int(*fill)(void*, unsigned int), -+ int(*flush)(void*, unsigned int), -+ unsigned char *output, -+ int *posp, -+ void(*error_fn)(char *x) -+#else -+ void -+#endif -+ ) - { -- uch flags; -+ uint8_t flags; - unsigned char magic[2]; /* magic header */ - char method; -- ulg orig_crc = 0; /* original crc */ -- ulg orig_len = 0; /* original uncompressed length */ -+ uint32_t orig_crc = 0; /* original crc */ -+ uint32_t orig_len = 0; /* original uncompressed length */ - int res; - -+#ifdef NEW_CODE -+ set_error_fn(error_fn); -+ if (fill == NULL) -+ fill_cb = empty_fill; -+ else -+ fill_cb = fill; -+ if (output) -+ window = output; -+ else { -+ window = malloc(0x8000); -+ if (!window) -+ panic("can't allocate buffers"); -+ flush_cb = flush; -+ } -+ -+ insize = len; -+ if (buf) -+ inbuf = buf; -+ else -+ inbuf = malloc(INBUFSIZ); -+#endif -+ -+ inptr = 0; -+ outcnt = 0; /* bytes in output buffer */ -+ bytes_out = 0; -+ crc = (uint32_t)0xffffffffL; /* shift register contents */ -+ makecrc(); -+ - magic[0] = NEXTBYTE(); - magic[1] = NEXTBYTE(); - method = NEXTBYTE(); -@@ -1212,7 +1317,7 @@ static int INIT gunzip(void) - return -1; - } - -- flags = (uch)get_byte(); -+ flags = (uint8_t)get_byte(); - if ((flags & ENCRYPTED) != 0) { - error("Input is encrypted"); - return -1; -@@ -1277,15 +1382,15 @@ static int INIT gunzip(void) - /* crc32 (see algorithm.doc) - * uncompressed input size modulo 2^32 - */ -- orig_crc = (ulg) NEXTBYTE(); -- orig_crc |= (ulg) NEXTBYTE() << 8; -- orig_crc |= (ulg) NEXTBYTE() << 16; -- orig_crc |= (ulg) NEXTBYTE() << 24; -+ orig_crc = (uint32_t) NEXTBYTE(); -+ orig_crc |= (uint32_t) NEXTBYTE() << 8; -+ orig_crc |= (uint32_t) NEXTBYTE() << 16; -+ orig_crc |= (uint32_t) NEXTBYTE() << 24; - -- orig_len = (ulg) NEXTBYTE(); -- orig_len |= (ulg) NEXTBYTE() << 8; -- orig_len |= (ulg) NEXTBYTE() << 16; -- orig_len |= (ulg) NEXTBYTE() << 24; -+ orig_len = (uint32_t) NEXTBYTE(); -+ orig_len |= (uint32_t) NEXTBYTE() << 8; -+ orig_len |= (uint32_t) NEXTBYTE() << 16; -+ orig_len |= (uint32_t) NEXTBYTE() << 24; - - /* Validate decompression */ - if (orig_crc != CRC_VALUE) { -@@ -1296,11 +1401,22 @@ static int INIT gunzip(void) - error("length error"); - return -1; - } -+#ifdef NEW_CODE -+ if (!output) -+ free(window); -+ if (posp) -+ *posp = inptr; -+#endif - return 0; - - underrun: /* NEXTBYTE() goto's here if needed */ -+ free(window); -+#ifdef NEW_CODE -+ if (!buf) -+ free(inbuf); -+#endif - error("out of input data"); - return -1; - } - -- -+#define decompress gunzip ---- a/scripts/Makefile.lib -+++ b/scripts/Makefile.lib -@@ -183,3 +183,17 @@ quiet_cmd_gzip = GZIP $@ - cmd_gzip = gzip -f -9 < $< > $@ - - -+# Bzip2 -+# --------------------------------------------------------------------------- -+ -+# Bzip2 does not include size in file... so we have to fake that -+size_append=$(CONFIG_SHELL) $(srctree)/scripts/bin_size -+ -+quiet_cmd_bzip2 = BZIP2 $@ -+cmd_bzip2 = (bzip2 -9 < $< ; $(size_append) $<) > $@ || (rm -f $@ ; false) -+ -+# Lzma -+# --------------------------------------------------------------------------- -+ -+quiet_cmd_lzma = LZMA $@ -+cmd_lzma = (/usr/bin/lzma -9 -c $< ; $(size_append) $<) >$@ || (rm -f $@ ; false) ---- /dev/null -+++ b/scripts/bin_size -@@ -0,0 +1,10 @@ -+#!/bin/sh -+ -+if [ $# = 0 ] ; then -+ echo Usage: $0 file -+fi -+ -+size_dec=`stat -c "%s" $1` -+size_hex_echo_string=`printf "%08x" $size_dec | -+ sed 's/\(..\)\(..\)\(..\)\(..\)/\\\\x\4\\\\x\3\\\\x\2\\\\x\1/g'` -+/bin/echo -ne $size_hex_echo_string diff --git a/target/linux/rdc/patches-2.6.28/007-r6040_git_updates.patch b/target/linux/rdc/patches-2.6.28/007-r6040_git_updates.patch deleted file mode 100644 index 704786ae7..000000000 --- a/target/linux/rdc/patches-2.6.28/007-r6040_git_updates.patch +++ /dev/null @@ -1,241 +0,0 @@ ---- a/drivers/net/r6040.c -+++ b/drivers/net/r6040.c -@@ -49,12 +49,12 @@ - #include - - #define DRV_NAME "r6040" --#define DRV_VERSION "0.19" --#define DRV_RELDATE "18Dec2008" -+#define DRV_VERSION "0.22" -+#define DRV_RELDATE "25Mar2009" - - /* PHY CHIP Address */ - #define PHY1_ADDR 1 /* For MAC1 */ --#define PHY2_ADDR 2 /* For MAC2 */ -+#define PHY2_ADDR 3 /* For MAC2 */ - #define PHY_MODE 0x3100 /* PHY CHIP Register 0 */ - #define PHY_CAP 0x01E1 /* PHY CHIP Register 4 */ - -@@ -160,6 +160,7 @@ MODULE_AUTHOR("Sten Wang "); - MODULE_LICENSE("GPL"); - MODULE_DESCRIPTION("RDC R6040 NAPI PCI FastEthernet driver"); -+MODULE_VERSION(DRV_VERSION " " DRV_RELDATE); - - /* RX and TX interrupts that we handle */ - #define RX_INTS (RX_FIFO_FULL | RX_NO_DESC | RX_FINISH) -@@ -200,7 +201,7 @@ struct r6040_private { - - static char version[] __devinitdata = KERN_INFO DRV_NAME - ": RDC R6040 NAPI net driver," -- "version "DRV_VERSION " (" DRV_RELDATE ")\n"; -+ "version "DRV_VERSION " (" DRV_RELDATE ")"; - - static int phy_table[] = { PHY1_ADDR, PHY2_ADDR }; - -@@ -330,7 +331,7 @@ static int r6040_alloc_rxbufs(struct net - do { - skb = netdev_alloc_skb(dev, MAX_BUF_SIZE); - if (!skb) { -- printk(KERN_ERR "%s: failed to alloc skb for rx\n", dev->name); -+ printk(KERN_ERR DRV_NAME "%s: failed to alloc skb for rx\n", dev->name); - rc = -ENOMEM; - goto err_exit; - } -@@ -438,7 +439,6 @@ static void r6040_down(struct net_device - { - struct r6040_private *lp = netdev_priv(dev); - void __iomem *ioaddr = lp->base; -- struct pci_dev *pdev = lp->pdev; - int limit = 2048; - u16 *adrp; - u16 cmd; -@@ -457,22 +457,12 @@ static void r6040_down(struct net_device - iowrite16(adrp[0], ioaddr + MID_0L); - iowrite16(adrp[1], ioaddr + MID_0M); - iowrite16(adrp[2], ioaddr + MID_0H); -- free_irq(dev->irq, dev); -- -- /* Free RX buffer */ -- r6040_free_rxbufs(dev); -- -- /* Free TX buffer */ -- r6040_free_txbufs(dev); -- -- /* Free Descriptor memory */ -- pci_free_consistent(pdev, RX_DESC_SIZE, lp->rx_ring, lp->rx_ring_dma); -- pci_free_consistent(pdev, TX_DESC_SIZE, lp->tx_ring, lp->tx_ring_dma); - } - - static int r6040_close(struct net_device *dev) - { - struct r6040_private *lp = netdev_priv(dev); -+ struct pci_dev *pdev = lp->pdev; - - /* deleted timer */ - del_timer_sync(&lp->timer); -@@ -481,8 +471,28 @@ static int r6040_close(struct net_device - napi_disable(&lp->napi); - netif_stop_queue(dev); - r6040_down(dev); -+ -+ free_irq(dev->irq, dev); -+ -+ /* Free RX buffer */ -+ r6040_free_rxbufs(dev); -+ -+ /* Free TX buffer */ -+ r6040_free_txbufs(dev); -+ - spin_unlock_irq(&lp->lock); - -+ /* Free Descriptor memory */ -+ if (lp->rx_ring) { -+ pci_free_consistent(pdev, RX_DESC_SIZE, lp->rx_ring, lp->rx_ring_dma); -+ lp->rx_ring = NULL; -+ } -+ -+ if (lp->tx_ring) { -+ pci_free_consistent(pdev, TX_DESC_SIZE, lp->tx_ring, lp->tx_ring_dma); -+ lp->tx_ring = NULL; -+ } -+ - return 0; - } - -@@ -598,7 +608,6 @@ static int r6040_rx(struct net_device *d - - /* Send to upper layer */ - netif_receive_skb(skb_ptr); -- dev->last_rx = jiffies; - dev->stats.rx_packets++; - dev->stats.rx_bytes += descptr->len - 4; - -@@ -668,7 +677,7 @@ static int r6040_poll(struct napi_struct - work_done = r6040_rx(dev, budget); - - if (work_done < budget) { -- netif_rx_complete(dev, napi); -+ napi_complete(napi); - /* Enable RX interrupt */ - iowrite16(ioread16(ioaddr + MIER) | RX_INTS, ioaddr + MIER); - } -@@ -705,7 +714,7 @@ static irqreturn_t r6040_interrupt(int i - - /* Mask off RX interrupt */ - misr &= ~RX_INTS; -- netif_rx_schedule(dev, &lp->napi); -+ napi_schedule(&lp->napi); - } - - /* TX interrupt request */ -@@ -1063,20 +1072,20 @@ static int __devinit r6040_init_one(stru - /* this should always be supported */ - err = pci_set_dma_mask(pdev, DMA_32BIT_MASK); - if (err) { -- printk(KERN_ERR DRV_NAME "32-bit PCI DMA addresses" -+ printk(KERN_ERR DRV_NAME ": 32-bit PCI DMA addresses" - "not supported by the card\n"); - goto err_out; - } - err = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK); - if (err) { -- printk(KERN_ERR DRV_NAME "32-bit PCI DMA addresses" -+ printk(KERN_ERR DRV_NAME ": 32-bit PCI DMA addresses" - "not supported by the card\n"); - goto err_out; - } - - /* IO Size check */ - if (pci_resource_len(pdev, 0) < io_size) { -- printk(KERN_ERR DRV_NAME "Insufficient PCI resources, aborting\n"); -+ printk(KERN_ERR DRV_NAME ": Insufficient PCI resources, aborting\n"); - err = -EIO; - goto err_out; - } -@@ -1086,7 +1095,7 @@ static int __devinit r6040_init_one(stru - - dev = alloc_etherdev(sizeof(struct r6040_private)); - if (!dev) { -- printk(KERN_ERR DRV_NAME "Failed to allocate etherdev\n"); -+ printk(KERN_ERR DRV_NAME ": Failed to allocate etherdev\n"); - err = -ENOMEM; - goto err_out; - } -@@ -1102,11 +1111,15 @@ static int __devinit r6040_init_one(stru - - ioaddr = pci_iomap(pdev, bar, io_size); - if (!ioaddr) { -- printk(KERN_ERR "ioremap failed for device %s\n", -+ printk(KERN_ERR DRV_NAME ": ioremap failed for device %s\n", - pci_name(pdev)); - err = -EIO; - goto err_out_free_res; - } -+ /* If PHY status change register is still set to zero it means the -+ * bootloader didn't initialize it */ -+ if (ioread16(ioaddr + PHY_CC) == 0) -+ iowrite16(0x9f07, ioaddr + PHY_CC); - - /* Init system & device */ - lp->base = ioaddr; -@@ -1123,6 +1136,13 @@ static int __devinit r6040_init_one(stru - adrp[1] = ioread16(ioaddr + MID_0M); - adrp[2] = ioread16(ioaddr + MID_0H); - -+ /* Some bootloader/BIOSes do not initialize -+ * MAC address, warn about that */ -+ if (!(adrp[0] || adrp[1] || adrp[2])) { -+ printk(KERN_WARNING DRV_NAME ": MAC address not initialized, generating random\n"); -+ random_ether_addr(dev->dev_addr); -+ } -+ - /* Link new device into r6040_root_dev */ - lp->pdev = pdev; - lp->dev = dev; ---- a/drivers/net/r6040.c -+++ b/drivers/net/r6040.c -@@ -742,6 +742,14 @@ static int r6040_up(struct net_device *d - struct r6040_private *lp = netdev_priv(dev); - void __iomem *ioaddr = lp->base; - int ret; -+ u16 val; -+ -+ /* Check presence of a second PHY */ -+ val = r6040_phy_read(ioaddr, lp->phy_addr, 2); -+ if (val == 0xFFFF) { -+ printk(KERN_ERR DRV_NAME " no second PHY attached\n"); -+ return -EIO; -+ } - - /* Initialise and alloc RX/TX buffers */ - r6040_init_txbufs(dev); ---- a/drivers/net/r6040.c -+++ b/drivers/net/r6040.c -@@ -401,6 +401,9 @@ static void r6040_init_mac_regs(struct n - * we may got called by r6040_tx_timeout which has left - * some unsent tx buffers */ - iowrite16(0x01, ioaddr + MTPR); -+ -+ /* Check media */ -+ mii_check_media(&lp->mii_if, 1, 1); - } - - static void r6040_tx_timeout(struct net_device *dev) -@@ -528,6 +531,8 @@ static int r6040_phy_mode_chk(struct net - phy_dat = 0x0000; - } - -+ mii_check_media(&lp->mii_if, 0, 1); -+ - return phy_dat; - }; - -@@ -810,7 +815,6 @@ static void r6040_timer(unsigned long da - lp->phy_mode = phy_mode; - lp->mcr0 = (lp->mcr0 & 0x7fff) | phy_mode; - iowrite16(lp->mcr0, ioaddr); -- printk(KERN_INFO "Link Change %x \n", ioread16(ioaddr)); - } - - /* Timer active again */ diff --git a/target/linux/rdc/patches-2.6.28/008-r8610_flash_map.patch b/target/linux/rdc/patches-2.6.28/008-r8610_flash_map.patch deleted file mode 100644 index 755522cbc..000000000 --- a/target/linux/rdc/patches-2.6.28/008-r8610_flash_map.patch +++ /dev/null @@ -1,25 +0,0 @@ ---- a/drivers/mtd/maps/Kconfig -+++ b/drivers/mtd/maps/Kconfig -@@ -156,6 +156,12 @@ config MTD_RDC3210_BUSWIDTH - Number of bytes addressed on the RDC-3210 flash device before - addressing the same chip again - -+config MTD_R8610 -+ tristate "CFI flash device mapped on R8610" -+ depends on X86 && MTD_CFI && MTD_PARTITIONS -+ help -+ Flash support for the RDC R8610 evaluation board. -+ - config MTD_SC520CDP - tristate "CFI Flash device mapped on AMD SC520 CDP" - depends on X86 && MTD_CFI && MTD_CONCAT ---- a/drivers/mtd/maps/Makefile -+++ b/drivers/mtd/maps/Makefile -@@ -28,6 +28,7 @@ obj-$(CONFIG_MTD_PMC_MSP_EVM) += pmcms - obj-$(CONFIG_MTD_PMC_MSP_RAMROOT)+= pmcmsp-ramroot.o - obj-$(CONFIG_MTD_PCMCIA) += pcmciamtd.o - obj-$(CONFIG_MTD_RDC3210) += rdc3210.o -+obj-$(CONFIG_MTD_R8610) += r8610.o - obj-$(CONFIG_MTD_RPXLITE) += rpxlite.o - obj-$(CONFIG_MTD_TQM8XXL) += tqm8xxl.o - obj-$(CONFIG_MTD_SA1100) += sa1100-flash.o diff --git a/target/linux/rdc/patches-2.6.30/009-rdc321x_select_embedded.patch b/target/linux/rdc/patches-2.6.30/009-rdc321x_select_embedded.patch index 0e0e1192b..f92fd6108 100644 --- a/target/linux/rdc/patches-2.6.30/009-rdc321x_select_embedded.patch +++ b/target/linux/rdc/patches-2.6.30/009-rdc321x_select_embedded.patch @@ -1,10 +1,11 @@ --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig -@@ -380,6 +380,7 @@ config X86_RDC321X +@@ -380,6 +380,8 @@ config X86_RDC321X depends on X86_EXTENDED_PLATFORM select M486 select X86_REBOOTFIXUPS + select EMBEDDED ++ select ARCH_REQUIRE_GPIOLIB ---help--- This option is needed for RDC R-321x system-on-chip, also known as R-8610-(G). diff --git a/target/linux/rdc/sitecom/config-2.6.30 b/target/linux/rdc/sitecom/config-2.6.30 index e6bfa8886..d756e8795 100644 --- a/target/linux/rdc/sitecom/config-2.6.30 +++ b/target/linux/rdc/sitecom/config-2.6.30 @@ -1,3 +1,2 @@ -# CONFIG_MTD_PHYSMAP is not set # CONFIG_MTD_R8610 is not set # CONFIG_MTD_RDC3210 is not set diff --git a/target/linux/s3c24xx/Makefile b/target/linux/s3c24xx/Makefile index 67fab6ccc..a0c186a86 100644 --- a/target/linux/s3c24xx/Makefile +++ b/target/linux/s3c24xx/Makefile @@ -12,7 +12,7 @@ BOARDNAME:=Samsung S3C24xx FEATURES:=jffs2 CFLAGS:=-O2 -pipe -march=armv4t -mtune=arm920t -funit-at-a-time -LINUX_VERSION:=2.6.30.9 +LINUX_VERSION:=2.6.30.10 DEVICE_TYPE=phone diff --git a/target/linux/s3c24xx/config-2.6.31 b/target/linux/s3c24xx/config-2.6.31 deleted file mode 100644 index 9ab52c96e..000000000 --- a/target/linux/s3c24xx/config-2.6.31 +++ /dev/null @@ -1,440 +0,0 @@ -# CONFIG_AEABI is not set -CONFIG_ALIGNMENT_TRAP=y -# CONFIG_APM_EMULATION is not set -# CONFIG_AR6000_WLAN is not set -# CONFIG_ARCH_BAST is not set -# CONFIG_ARCH_H1940 is not set -CONFIG_ARCH_REQUIRE_GPIOLIB=y -CONFIG_ARCH_S3C2410=y -# CONFIG_ARCH_S3C2440 is not set -# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set -# CONFIG_ARCH_SMDK2410 is not set -# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set -# CONFIG_ARCH_STMP3XXX is not set -# CONFIG_ARCH_SUPPORTS_MSI is not set -CONFIG_ARCH_SUSPEND_POSSIBLE=y -# CONFIG_ARCH_U300 is not set -CONFIG_ARM_THUMB=y -CONFIG_ARM=y -# CONFIG_ARPD is not set -CONFIG_BACKLIGHT_CLASS_DEVICE=y -CONFIG_BACKLIGHT_GENERIC=y -CONFIG_BACKLIGHT_LCD_SUPPORT=y -# CONFIG_BACKLIGHT_PWM is not set -CONFIG_BATTERY_BQ27000_HDQ=y -# CONFIG_BINARY_PRINTF is not set -CONFIG_BITREVERSE=y -CONFIG_BLK_DEV_RAM_COUNT=16 -CONFIG_BLK_DEV_RAM_SIZE=4096 -CONFIG_BLK_DEV_RAM=y -CONFIG_BRIDGE_NETFILTER=y -# CONFIG_BSD_PROCESS_ACCT is not set -CONFIG_CHARGER_PCF50633=y -CONFIG_CMDLINE="unused -- bootloader passes ATAG list" -CONFIG_COMPAT_BRK=y -CONFIG_CONSOLE_TRANSLATIONS=y -CONFIG_CONSTRUCTORS=y -CONFIG_CPU_32v4T=y -CONFIG_CPU_32=y -CONFIG_CPU_ABRT_EV4T=y -CONFIG_CPU_ARM920T=y -CONFIG_CPU_CACHE_V4WT=y -CONFIG_CPU_CACHE_VIVT=y -CONFIG_CPU_COPY_V4WB=y -CONFIG_CPU_CP15_MMU=y -CONFIG_CPU_CP15=y -# CONFIG_CPU_DCACHE_WRITETHROUGH is not set -# CONFIG_CPU_ICACHE_DISABLE is not set -CONFIG_CPU_IDLE_GOV_LADDER=y -CONFIG_CPU_IDLE=y -CONFIG_CPU_LLSERIAL_S3C2440_ONLY=y -CONFIG_CPU_LLSERIAL_S3C2440=y -CONFIG_CPU_PABRT_NOIFAR=y -CONFIG_CPU_S3C2410_DMA=y -CONFIG_CPU_S3C2442=y -CONFIG_CPU_S3C244X=y -CONFIG_CPU_TLB_V4WBI=y -CONFIG_CRC16=y -CONFIG_CRC7=y -CONFIG_CRC_CCITT=y -CONFIG_CRC_ITU_T=y -CONFIG_CRC_T10DIF=y -CONFIG_CRYPTO_HASH2=y -CONFIG_CRYPTO_HASH=y -CONFIG_CRYPTO_MD5=y -CONFIG_DEBUG_BUGVERBOSE=y -# CONFIG_DEBUG_FS is not set -CONFIG_DEBUG_MEMORY_INIT=y -CONFIG_DEBUG_S3C_UART=2 -# CONFIG_DEBUG_USER is not set -CONFIG_DECOMPRESS_BZIP2=y -CONFIG_DECOMPRESS_GZIP=y -CONFIG_DECOMPRESS_LZMA=y -CONFIG_DISPLAY_JBT6K74=y -CONFIG_DUMMY_CONSOLE=y -CONFIG_ELF_CORE=y -# CONFIG_EMBEDDED is not set -# CONFIG_ENABLE_WARN_DEPRECATED is not set -CONFIG_FB_CFB_COPYAREA=y -CONFIG_FB_CFB_FILLRECT=y -CONFIG_FB_CFB_IMAGEBLIT=y -CONFIG_FB=y -CONFIG_FIQ=y -# CONFIG_FIRMWARE_EDID is not set -# CONFIG_FONT_10x18 is not set -CONFIG_FONT_6x11=y -# CONFIG_FONT_7x14 is not set -# CONFIG_FONT_8x16 is not set -# CONFIG_FONT_8x8 is not set -# CONFIG_FONT_ACORN_8x8 is not set -# CONFIG_FONT_MINI_4x6 is not set -# CONFIG_FONT_PEARL_8x8 is not set -# CONFIG_FONT_SUN12x22 is not set -# CONFIG_FONT_SUN8x16 is not set -CONFIG_FONTS=y -# CONFIG_FPE_FASTFPE is not set -# CONFIG_FPE_NWFPE_XP is not set -CONFIG_FPE_NWFPE=y -# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set -# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set -CONFIG_FRAMEBUFFER_CONSOLE=y -CONFIG_FRAME_POINTER=y -CONFIG_FREEZER=y -# CONFIG_FSNOTIFY is not set -CONFIG_GENERIC_FIND_LAST_BIT=y -CONFIG_GENERIC_GPIO=y -CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y -CONFIG_GPIOLIB=y -CONFIG_GPIO_SYSFS=y -# CONFIG_HAMRADIO is not set -CONFIG_HARDIRQS_SW_RESEND=y -CONFIG_HAS_DMA=y -CONFIG_HAS_IOMEM=y -CONFIG_HAVE_AOUT=y -CONFIG_HAVE_ARCH_KGDB=y -CONFIG_HAVE_CLK=y -CONFIG_HAVE_FUNCTION_TRACER=y -CONFIG_HAVE_GENERIC_DMA_COHERENT=y -CONFIG_HAVE_IDE=y -CONFIG_HAVE_KPROBES=y -CONFIG_HAVE_KRETPROBES=y -CONFIG_HAVE_LATENCYTOP_SUPPORT=y -CONFIG_HAVE_MLOCKED_PAGE_BIT=y -CONFIG_HAVE_MLOCK=y -CONFIG_HAVE_OPROFILE=y -CONFIG_HAVE_PWM=y -CONFIG_HDQ_GPIO_BITBANG=y -CONFIG_HID_A4TECH=y -CONFIG_HID_APPLE=y -CONFIG_HID_BELKIN=y -CONFIG_HID_CHERRY=y -CONFIG_HID_CHICONY=y -CONFIG_HID_CYPRESS=y -CONFIG_HID_DRAGONRISE=y -CONFIG_HID_EZKEY=y -CONFIG_HID_GREENASIA=y -CONFIG_HID_GYRATION=y -CONFIG_HID_KENSINGTON=y -CONFIG_HID_KYE=y -CONFIG_HID_LOGITECH=y -CONFIG_HID_MICROSOFT=y -CONFIG_HID_MONTEREY=y -CONFIG_HID_NTRIG=y -CONFIG_HID_PANTHERLORD=y -CONFIG_HID_PETALYNX=y -CONFIG_HID_SAMSUNG=y -CONFIG_HID_SMARTJOYPLUS=y -CONFIG_HID_SONY=y -CONFIG_HID_SUNPLUS=y -CONFIG_HID_SUPPORT=y -CONFIG_HID_THRUSTMASTER=y -CONFIG_HID_TOPSEED=y -CONFIG_HID=y -CONFIG_HID_ZEROPLUS=y -CONFIG_HW_CONSOLE=y -# CONFIG_HW_RANDOM is not set -CONFIG_HZ=200 -CONFIG_I2C_BOARDINFO=y -CONFIG_I2C_CHARDEV=y -# CONFIG_I2C_DESIGNWARE is not set -CONFIG_I2C_S3C2410=y -CONFIG_I2C=y -CONFIG_INET_DIAG=y -CONFIG_INET_TCP_DIAG=y -CONFIG_INITRAMFS_SOURCE="" -CONFIG_INOTIFY=y -CONFIG_INPUT_EVDEV=y -# CONFIG_INPUT_GPIO_BUTTONS is not set -CONFIG_INPUT_KEYBOARD=y -CONFIG_INPUT_LIS302DL=y -# CONFIG_INPUT_MOUSEDEV_PSAUX is not set -CONFIG_INPUT_MOUSEDEV_SCREEN_X=480 -CONFIG_INPUT_MOUSEDEV_SCREEN_Y=640 -CONFIG_INPUT_MOUSEDEV=y -CONFIG_INPUT_PCF50633_PMU=y -CONFIG_INPUT_TOUCHSCREEN=y -CONFIG_INPUT=y -# CONFIG_INPUT_YEALINK is not set -# CONFIG_IP_PNP_BOOTP is not set -# CONFIG_IP_PNP_DHCP is not set -# CONFIG_IP_PNP_RARP is not set -CONFIG_IP_PNP=y -# CONFIG_IP_ROUTE_MULTIPATH is not set -# CONFIG_IP_ROUTE_VERBOSE is not set -# CONFIG_ISDN is not set -# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set -CONFIG_KALLSYMS=y -# CONFIG_KEYBOARD_ATKBD is not set -# CONFIG_KEYBOARD_GPIO is not set -# CONFIG_KEYBOARD_LKKBD is not set -# CONFIG_KEYBOARD_LM8323 is not set -# CONFIG_KEYBOARD_MATRIX is not set -# CONFIG_KEYBOARD_NEWTON is not set -# CONFIG_KEYBOARD_STOWAWAY is not set -# CONFIG_KEYBOARD_SUNKBD is not set -# CONFIG_KEYBOARD_XTKBD is not set -CONFIG_LCD_CLASS_DEVICE=y -# CONFIG_LCD_ILI9320 is not set -# CONFIG_LCD_LTV350QV is not set -# CONFIG_LCD_PLATFORM is not set -# CONFIG_LCD_TDO24M is not set -# CONFIG_LCD_VGG2432A4 is not set -# CONFIG_LEDS_GPIO is not set -CONFIG_LEDS_GTA02_VIBRATOR=y -# CONFIG_LEDS_PWM is not set -# CONFIG_LEDS_S3C24XX is not set -# CONFIG_LEDS_TRIGGER_DEFAULT_ON is not set -CONFIG_LOCK_KERNEL=y -CONFIG_LOG_BUF_SHIFT=18 -# CONFIG_LOGO_LINUX_CLUT224 is not set -# CONFIG_LOGO_LINUX_MONO is not set -# CONFIG_LOGO_LINUX_VGA16 is not set -CONFIG_LOGO=y -CONFIG_MAC80211_DEFAULT_PS_VALUE=0 -# CONFIG_MACH_AML_M5900 is not set -# CONFIG_MACH_ANUBIS is not set -# CONFIG_MACH_AT2440EVB is not set -# CONFIG_MACH_JIVE is not set -# CONFIG_MACH_MINI2440 is not set -# CONFIG_MACH_N30 is not set -CONFIG_MACH_NEO1973_GTA02=y -CONFIG_MACH_NEO1973=y -# CONFIG_MACH_NEXCODER_2440 is not set -# CONFIG_MACH_OSIRIS is not set -# CONFIG_MACH_OTOM is not set -# CONFIG_MACH_QT2410 is not set -# CONFIG_MACH_RX3715 is not set -# CONFIG_MACH_SMDK2412 is not set -# CONFIG_MACH_SMDK2413 is not set -# CONFIG_MACH_SMDK2443 is not set -# CONFIG_MACH_TCT_HAMMER is not set -# CONFIG_MACH_VR1000 is not set -# CONFIG_MACH_VSTMS is not set -CONFIG_MFD_CORE=y -CONFIG_MFD_GLAMO_FB=y -CONFIG_MFD_GLAMO_GPIO=y -# CONFIG_MFD_GLAMO_MCI is not set -CONFIG_MFD_GLAMO=y -CONFIG_MFD_PCF50633=y -# CONFIG_MFD_T7L66XB is not set -# CONFIG_MG_DISK is not set -# CONFIG_MISC_DEVICES is not set -CONFIG_MMC_BLOCK=y -CONFIG_MMC=y -CONFIG_MODULE_FORCE_UNLOAD=y -CONFIG_MTD_ABSENT=y -# CONFIG_MTD_CFI_AMDSTD is not set -CONFIG_MTD_CMDLINE_PARTS=y -# CONFIG_MTD_COMPLEX_MAPPINGS is not set -CONFIG_MTD_CONCAT=y -# CONFIG_MTD_NAND_S3C2410_CLKSTOP is not set -# CONFIG_MTD_NAND_S3C2410_DEBUG is not set -CONFIG_MTD_NAND_S3C2410_HWECC=y -CONFIG_MTD_NAND_S3C2410=y -CONFIG_MTD_NAND_VERIFY_WRITE=y -CONFIG_MTD_NAND=y -CONFIG_MTD_PHYSMAP=y -CONFIG_MTD_ROM=y -CONFIG_NAMESPACES=y -# CONFIG_NET_CLS_ACT is not set -# CONFIG_NETDEV_1000 is not set -# CONFIG_NET_ETHERNET is not set -# CONFIG_NET_NS is not set -# CONFIG_NETWORK_FILESYSTEMS is not set -CONFIG_NLS=y -CONFIG_NO_IOPORT=y -CONFIG_NR_TTY_DEVICES=6 -CONFIG_PAGEFLAGS_EXTENDED=y -CONFIG_PAGE_OFFSET=0xC0000000 -CONFIG_PCF50633_ADC=y -CONFIG_PCF50633_GPIO=y -# CONFIG_PCI is not set -# CONFIG_PCI_SYSCALL is not set -# CONFIG_PDA_POWER is not set -CONFIG_PLAT_S3C24XX=y -CONFIG_PLAT_S3C=y -# CONFIG_PM_DEBUG is not set -CONFIG_PM_SLEEP=y -CONFIG_PM=y -# CONFIG_POWER_SUPPLY_DEBUG is not set -CONFIG_POWER_SUPPLY=y -CONFIG_PREEMPT=y -CONFIG_PROC_PAGE_MONITOR=y -CONFIG_RD_BZIP2=y -CONFIG_RD_GZIP=y -# CONFIG_REGULATOR_DEBUG is not set -# CONFIG_REGULATOR_LP3971 is not set -# CONFIG_REGULATOR_MAX1586 is not set -CONFIG_REGULATOR_PCF50633=y -# CONFIG_REGULATOR_USERSPACE_CONSUMER is not set -CONFIG_REGULATOR=y -CONFIG_RFKILL_INPUT=y -CONFIG_RFKILL_LEDS=y -CONFIG_RFKILL=y -CONFIG_RTC_CLASS=y -# CONFIG_RTC_DRV_CMOS is not set -CONFIG_RTC_DRV_PCF50633=y -# CONFIG_RTC_DRV_RX8025 is not set -CONFIG_RTC_DRV_S3C=y -CONFIG_S3C2410_CLOCK=y -# CONFIG_S3C2410_DMA_DEBUG is not set -CONFIG_S3C2410_DMA=y -CONFIG_S3C2410_GPIO=y -# CONFIG_S3C2410_PM_CHECK is not set -# CONFIG_S3C2410_PM_DEBUG is not set -CONFIG_S3C2410_PM=y -CONFIG_S3C2410_WATCHDOG=y -# CONFIG_S3C24XX_ADC is not set -CONFIG_S3C24XX_GPIO_EXTRA=64 -CONFIG_S3C24XX_GPIO_EXTRA64=y -CONFIG_S3C24XX_PWM=y -# CONFIG_S3C_BOOT_ERROR_RESET is not set -CONFIG_S3C_BOOT_UART_FORCE_FIFO=y -# CONFIG_S3C_BOOT_WATCHDOG is not set -CONFIG_S3C_DEV_USB_HOST=y -CONFIG_S3C_DMA=y -CONFIG_S3C_GPIO_SPACE=0 -CONFIG_S3C_LOWLEVEL_UART_PORT=2 -CONFIG_S3C_PWM=y -# CONFIG_SCSI_DMA is not set -# CONFIG_SDIO_UART is not set -# CONFIG_SERIAL_8250 is not set -CONFIG_SERIAL_S3C2440=y -CONFIG_SERIAL_SAMSUNG_CONSOLE=y -CONFIG_SERIAL_SAMSUNG_UARTS=3 -CONFIG_SERIAL_SAMSUNG=y -# CONFIG_SERIO_RAW is not set -# CONFIG_SERIO_SERPORT is not set -CONFIG_SERIO=y -# CONFIG_SLOW_WORK is not set -# CONFIG_SMARTJOYPLUS_FF is not set -# CONFIG_SND_DRIVERS is not set -# CONFIG_SND_EMU10K1_SEQ is not set -CONFIG_SND_JACK=y -CONFIG_SND=m -# CONFIG_SND_OPL3_LIB_SEQ is not set -# CONFIG_SND_OPL4_LIB_SEQ is not set -CONFIG_SND_PCM=m -# CONFIG_SND_RAWMIDI_SEQ is not set -CONFIG_SND_S3C24XX_SOC_I2S=m -# CONFIG_SND_S3C24XX_SOC_LN2440SBC_ALC650 is not set -CONFIG_SND_S3C24XX_SOC=m -CONFIG_SND_S3C24XX_SOC_NEO1973_GTA02_WM8753=m -# CONFIG_SND_S3C24XX_SOC_S3C24XX_UDA134X is not set -# CONFIG_SND_SBAWE_SEQ is not set -# CONFIG_SND_SOC_ALL_CODECS is not set -CONFIG_SND_SOC_I2C_AND_SPI=m -CONFIG_SND_SOC=m -CONFIG_SND_SOC_WM8753=m -CONFIG_SND_TIMER=m -# CONFIG_SND_USB is not set -# CONFIG_SND_VERBOSE_PROCFS is not set -CONFIG_SOUND=m -# CONFIG_SOUND_OSS_CORE is not set -CONFIG_SPI_BITBANG=y -CONFIG_SPI_GPIO=y -CONFIG_SPI_MASTER=y -CONFIG_SPI_S3C24XX_GPIO=y -CONFIG_SPI_S3C24XX=y -# CONFIG_SPI_SPIDEV is not set -CONFIG_SPI=y -CONFIG_SPLIT_PTLOCK_CPUS=4096 -# CONFIG_SQUASHFS is not set -CONFIG_SUSPEND_FREEZER=y -CONFIG_SUSPEND=y -# CONFIG_SYSCTL_SYSCALL_CHECK is not set -CONFIG_SYSFS_DEPRECATED_V2=y -CONFIG_SYSFS_DEPRECATED=y -CONFIG_SYS_SUPPORTS_APM_EMULATION=y -CONFIG_TCP_MD5SIG=y -CONFIG_TOUCHSCREEN_FILTER_GROUP=y -CONFIG_TOUCHSCREEN_FILTER_LINEAR=y -CONFIG_TOUCHSCREEN_FILTER_MEAN=y -CONFIG_TOUCHSCREEN_FILTER_MEDIAN=y -CONFIG_TOUCHSCREEN_FILTER=y -# CONFIG_TOUCHSCREEN_S3C2410_DEBUG is not set -CONFIG_TOUCHSCREEN_S3C2410=y -CONFIG_TRACING_SUPPORT=y -# CONFIG_UACCESS_WITH_MEMCPY is not set -CONFIG_UID16=y -CONFIG_USB_ANNOUNCE_NEW_DEVICES=y -# CONFIG_USB_ARCH_HAS_EHCI is not set -# CONFIG_USB_AUDIO is not set -# CONFIG_USB_CDC_COMPOSITE is not set -# CONFIG_USB_DEVICEFS is not set -CONFIG_USB_ETH_RNDIS=y -CONFIG_USB_ETH=y -# CONFIG_USB_FILE_STORAGE is not set -# CONFIG_USB_GADGET_AMD5536UDC is not set -# CONFIG_USB_GADGET_AT91 is not set -# CONFIG_USB_GADGET_ATMEL_USBA is not set -# CONFIG_USB_GADGET_CI13XXX is not set -# CONFIG_USB_GADGET_DEBUG_FILES is not set -# CONFIG_USB_GADGET_DUALSPEED is not set -# CONFIG_USB_GADGET_DUMMY_HCD is not set -# CONFIG_USB_GADGETFS is not set -# CONFIG_USB_GADGET_FSL_QE is not set -# CONFIG_USB_GADGET_FSL_USB2 is not set -# CONFIG_USB_GADGET_GOKU is not set -# CONFIG_USB_GADGET_IMX is not set -# CONFIG_USB_GADGET_LANGWELL is not set -# CONFIG_USB_GADGET_LH7A40X is not set -# CONFIG_USB_GADGET_M66592 is not set -# CONFIG_USB_GADGET_MUSB_HDRC is not set -# CONFIG_USB_GADGET_NET2280 is not set -# CONFIG_USB_GADGET_OMAP is not set -# CONFIG_USB_GADGET_PXA25X is not set -# CONFIG_USB_GADGET_PXA27X is not set -CONFIG_USB_GADGET_S3C2410=y -# CONFIG_USB_GADGET_S3C_HSOTG is not set -CONFIG_USB_GADGET_SELECTED=y -CONFIG_USB_GADGET_VBUS_DRAW=500 -CONFIG_USB_GADGET=y -# CONFIG_USB_G_PRINTER is not set -# CONFIG_USB_G_SERIAL is not set -CONFIG_USB_HID=y -# CONFIG_USB_MIDI_GADGET is not set -# CONFIG_USB_MUSB_HDRC is not set -# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set -# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set -CONFIG_USB_OHCI_HCD=y -# CONFIG_USB_S3C2410_DEBUG is not set -CONFIG_USB_S3C2410=y -CONFIG_USB_SUPPORT=y -CONFIG_USB_SUSPEND=y -CONFIG_USB=y -# CONFIG_USB_ZERO is not set -# CONFIG_USER_NS is not set -CONFIG_VECTORS_BASE=0xffff0000 -# CONFIG_VGA_CONSOLE is not set -CONFIG_VIDEO_OUTPUT_CONTROL=y -# CONFIG_VLAN_8021Q is not set -CONFIG_VM_EVENT_COUNTERS=y -CONFIG_VT_CONSOLE=y -CONFIG_VT_HW_CONSOLE_BINDING=y -CONFIG_VT=y -CONFIG_W1=m -# CONFIG_WLAN_80211 is not set -CONFIG_ZBOOT_ROM_BSS=0x0 -CONFIG_ZBOOT_ROM_TEXT=0x0 -CONFIG_ZONE_DMA_FLAG=0 diff --git a/target/linux/s3c24xx/files-2.6.31/arch/arm/mach-s3c2442/gta02-pm-bt.c b/target/linux/s3c24xx/files-2.6.31/arch/arm/mach-s3c2442/gta02-pm-bt.c deleted file mode 100644 index 29a6b9ef3..000000000 --- a/target/linux/s3c24xx/files-2.6.31/arch/arm/mach-s3c2442/gta02-pm-bt.c +++ /dev/null @@ -1,258 +0,0 @@ -/* - * Bluetooth PM code for the Openmoko Freerunner GSM Phone - * - * (C) 2007 by Openmoko Inc. - * Author: Harald Welte - * All rights reserved. - * - * 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 -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include - -#include - -#define DRVMSG "Openmoko Freerunner Bluetooth Power Management" - -struct gta02_pm_bt_data { - struct regulator *regulator; - struct rfkill *rfkill; - int pre_resume_state; -}; - -static ssize_t bt_read(struct device *dev, struct device_attribute *attr, - char *buf) -{ - int ret = 0; - if (!strcmp(attr->attr.name, "power_on")) { - if (s3c2410_gpio_getpin(GTA02_GPIO_BT_EN)) - ret = 1; - } else if (!strcmp(attr->attr.name, "reset")) { - if (s3c2410_gpio_getpin(GTA02_GPIO_BT_EN) == 0) - ret = 1; - } - - if (!ret) { - return strlcpy(buf, "0\n", 3); - } else { - return strlcpy(buf, "1\n", 3); - } -} - -static void __gta02_pm_bt_toggle_radio(struct device *dev, unsigned int on) -{ - struct gta02_pm_bt_data *bt_data = dev_get_drvdata(dev); - - dev_info(dev, "__gta02_pm_bt_toggle_radio %d\n", on); - - bt_data = dev_get_drvdata(dev); - - s3c2410_gpio_setpin(GTA02_GPIO_BT_EN, !on); - - if (on) { - if (!regulator_is_enabled(bt_data->regulator)) - regulator_enable(bt_data->regulator); - } else { - if (regulator_is_enabled(bt_data->regulator)) - regulator_disable(bt_data->regulator); - } - - s3c2410_gpio_setpin(GTA02_GPIO_BT_EN, on); -} - - -static int bt_rfkill_set_block(void *data, bool blocked) -{ - struct device *dev = data; - - __gta02_pm_bt_toggle_radio(dev, !blocked); - - return 0; -} - -static const struct rfkill_ops gta02_bt_rfkill_ops = { - .set_block = bt_rfkill_set_block, -}; - - -static ssize_t bt_write(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - unsigned long on = simple_strtoul(buf, NULL, 10); - struct gta02_pm_bt_data *bt_data = dev_get_drvdata(dev); - - if (!strcmp(attr->attr.name, "power_on")) { - rfkill_set_sw_state(bt_data->rfkill, on ? 1 : 0); - - __gta02_pm_bt_toggle_radio(dev, on); - } else if (!strcmp(attr->attr.name, "reset")) { - /* reset is low-active, so we need to invert */ - s3c2410_gpio_setpin(GTA02_GPIO_BT_EN, on ? 0 : 1); - } - - return count; -} - -static DEVICE_ATTR(power_on, 0644, bt_read, bt_write); -static DEVICE_ATTR(reset, 0644, bt_read, bt_write); - -#ifdef CONFIG_PM -static int gta02_bt_suspend(struct platform_device *pdev, pm_message_t state) -{ - struct gta02_pm_bt_data *bt_data = dev_get_drvdata(&pdev->dev); - - dev_dbg(&pdev->dev, DRVMSG ": suspending\n"); - - bt_data->pre_resume_state = s3c2410_gpio_getpin(GTA02_GPIO_BT_EN); - __gta02_pm_bt_toggle_radio(&pdev->dev, 0); - - return 0; -} - -static int gta02_bt_resume(struct platform_device *pdev) -{ - struct gta02_pm_bt_data *bt_data = dev_get_drvdata(&pdev->dev); - dev_dbg(&pdev->dev, DRVMSG ": resuming\n"); - - __gta02_pm_bt_toggle_radio(&pdev->dev, bt_data->pre_resume_state); - return 0; -} -#else -#define gta02_bt_suspend NULL -#define gta02_bt_resume NULL -#endif - -static struct attribute *gta02_bt_sysfs_entries[] = { - &dev_attr_power_on.attr, - &dev_attr_reset.attr, - NULL -}; - -static struct attribute_group gta02_bt_attr_group = { - .name = NULL, - .attrs = gta02_bt_sysfs_entries, -}; - -static int __init gta02_bt_probe(struct platform_device *pdev) -{ - struct rfkill *rfkill; - struct regulator *regulator; - struct gta02_pm_bt_data *bt_data; - int ret; - - dev_info(&pdev->dev, DRVMSG ": starting\n"); - - bt_data = kzalloc(sizeof(*bt_data), GFP_KERNEL); - dev_set_drvdata(&pdev->dev, bt_data); - - regulator = regulator_get(&pdev->dev, "BT_3V2"); - if (IS_ERR(regulator)) - return -ENODEV; - - bt_data->regulator = regulator; - - /* this tests the true physical state of the regulator... */ - if (regulator_is_enabled(regulator)) { - /* - * but these only operate on the logical state of the - * regulator... so we need to logicaly "adopt" it on - * to turn it off - */ - regulator_enable(regulator); - regulator_disable(regulator); - } - - /* we pull reset to low to make sure that the chip doesn't - * drain power through the reset line */ - s3c2410_gpio_setpin(GTA02_GPIO_BT_EN, 0); - - rfkill = rfkill_alloc(pdev->name, &pdev->dev, RFKILL_TYPE_BLUETOOTH, - >a02_bt_rfkill_ops, &pdev->dev); - - if (!rfkill) { - dev_err(&pdev->dev, "Failed to allocate rfkill\n"); - return -ENOMEM; - } - - rfkill_init_sw_state(rfkill, 0); - - ret = rfkill_register(rfkill); - if (ret) { - rfkill_destroy(rfkill); - dev_err(&pdev->dev, "Failed to register rfkill\n"); - return ret; - } - - bt_data->rfkill = rfkill; - - return sysfs_create_group(&pdev->dev.kobj, >a02_bt_attr_group); -} - -static int gta02_bt_remove(struct platform_device *pdev) -{ - struct gta02_pm_bt_data *bt_data = dev_get_drvdata(&pdev->dev); - struct regulator *regulator; - - sysfs_remove_group(&pdev->dev.kobj, >a02_bt_attr_group); - - if (bt_data->rfkill) { - rfkill_destroy(bt_data->rfkill); - } - - if (!bt_data || !bt_data->regulator) - return 0; - - regulator = bt_data->regulator; - - /* Make sure regulator is disabled before calling regulator_put */ - if (regulator_is_enabled(regulator)) - regulator_disable(regulator); - - regulator_put(regulator); - - kfree(bt_data); - - return 0; -} - -static struct platform_driver gta02_bt_driver = { - .probe = gta02_bt_probe, - .remove = gta02_bt_remove, - .suspend = gta02_bt_suspend, - .resume = gta02_bt_resume, - .driver = { - .name = "gta02-pm-bt", - }, -}; - -static int __devinit gta02_bt_init(void) -{ - return platform_driver_register(>a02_bt_driver); -} - -static void gta02_bt_exit(void) -{ - platform_driver_unregister(>a02_bt_driver); -} - -module_init(gta02_bt_init); -module_exit(gta02_bt_exit); - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Harald Welte "); -MODULE_DESCRIPTION(DRVMSG); diff --git a/target/linux/s3c24xx/files-2.6.31/arch/arm/mach-s3c2442/gta02-pm-gps.c b/target/linux/s3c24xx/files-2.6.31/arch/arm/mach-s3c2442/gta02-pm-gps.c deleted file mode 100644 index f617d73f3..000000000 --- a/target/linux/s3c24xx/files-2.6.31/arch/arm/mach-s3c2442/gta02-pm-gps.c +++ /dev/null @@ -1,243 +0,0 @@ -/* - * GPS Power Management code for the Openmoko Freerunner GSM Phone - * - * (C) 2007-2009 by Openmoko Inc. - * Author: Harald Welte - * All rights reserved. - * - * 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 -#include -#include -#include -#include - -#include -#include -#include - -#include - -#include -#include -#include - -#include -#include - -struct gta02_pm_gps_data { -#ifdef CONFIG_PM - int keep_on_in_suspend; -#endif - int power_was_on; - struct regulator *regulator; -}; - -static struct gta02_pm_gps_data gta02_gps; - -int gta02_pm_gps_is_on(void) -{ - return gta02_gps.power_was_on; -} -EXPORT_SYMBOL_GPL(gta02_pm_gps_is_on); - -/* This is the POWERON pin */ -static void gps_pwron_set(int on) -{ - if (on) { - /* return UART pins to being UART pins */ - s3c2410_gpio_cfgpin(S3C2410_GPH(4), S3C2410_GPH4_TXD1); - /* remove pulldown now it won't be floating any more */ - s3c2410_gpio_pullup(S3C2410_GPH(5), 0); - - if (!gta02_gps.power_was_on) - regulator_enable(gta02_gps.regulator); - } else { - /* - * take care not to power unpowered GPS from UART TX - * return them to GPIO and force low - */ - s3c2410_gpio_cfgpin(S3C2410_GPH(4), S3C2410_GPIO_OUTPUT); - s3c2410_gpio_setpin(S3C2410_GPH(4), 0); - /* don't let RX from unpowered GPS float */ - s3c2410_gpio_pullup(S3C2410_GPH(5), 1); - if (gta02_gps.power_was_on) - regulator_disable(gta02_gps.regulator); - } -} - -static int gps_pwron_get(void) -{ - return regulator_is_enabled(gta02_gps.regulator); -} - -#ifdef CONFIG_PM -/* This is the flag for keeping gps ON during suspend */ -static void gps_keep_on_in_suspend_set(int on) -{ - gta02_gps.keep_on_in_suspend = on; -} - -static int gps_keep_on_in_suspend_get(void) -{ - return gta02_gps.keep_on_in_suspend; -} -#endif - -static ssize_t power_gps_read(struct device *dev, - struct device_attribute *attr, char *buf) -{ - int ret = 0; - - if (!strcmp(attr->attr.name, "power_on") || - !strcmp(attr->attr.name, "pwron")) { - ret = gps_pwron_get(); -#ifdef CONFIG_PM - } else if (!strcmp(attr->attr.name, "keep_on_in_suspend")) { - ret = gps_keep_on_in_suspend_get(); -#endif - } - if (ret) - return strlcpy(buf, "1\n", 3); - else - return strlcpy(buf, "0\n", 3); -} - -static ssize_t power_gps_write(struct device *dev, - struct device_attribute *attr, const char *buf, - size_t count) -{ - unsigned long on = simple_strtoul(buf, NULL, 10); - - if (!strcmp(attr->attr.name, "power_on") || - !strcmp(attr->attr.name, "pwron")) { - gps_pwron_set(on); - gta02_gps.power_was_on = !!on; -#ifdef CONFIG_PM - } else if (!strcmp(attr->attr.name, "keep_on_in_suspend")) { - gps_keep_on_in_suspend_set(on); -#endif - } - return count; -} - -#ifdef CONFIG_PM -static int gta02_pm_gps_suspend(struct platform_device *pdev, - pm_message_t state) -{ - if (!gta02_gps.keep_on_in_suspend || - !gta02_gps.power_was_on) - gps_pwron_set(0); - else - dev_warn(&pdev->dev, "GTA02: keeping gps ON " - "during suspend\n"); - return 0; -} - -static int gta02_pm_gps_resume(struct platform_device *pdev) -{ - if (!gta02_gps.keep_on_in_suspend && gta02_gps.power_was_on) - gps_pwron_set(1); - - return 0; -} - -static DEVICE_ATTR(keep_on_in_suspend, 0644, power_gps_read, power_gps_write); -#else -#define gta02_pm_gps_suspend NULL -#define gta02_pm_gps_resume NULL -#endif - -static DEVICE_ATTR(power_on, 0644, power_gps_read, power_gps_write); - -static struct attribute *gta02_gps_sysfs_entries[] = { - &dev_attr_power_on.attr, -#ifdef CONFIG_PM - &dev_attr_keep_on_in_suspend.attr, -#endif - NULL -}; - -static struct attribute_group gta02_gps_attr_group = { - .name = NULL, - .attrs = gta02_gps_sysfs_entries, -}; - -static int __init gta02_pm_gps_probe(struct platform_device *pdev) -{ - gta02_gps.regulator = regulator_get(&pdev->dev, "RF_3V"); - if (IS_ERR(gta02_gps.regulator)) { - dev_err(&pdev->dev, "probe failed %ld\n", - PTR_ERR(gta02_gps.regulator)); - - return PTR_ERR(gta02_gps.regulator); - } - - dev_info(&pdev->dev, "starting\n"); - - /* - * Here we should call the code that handles the set GPS power - * off action. But, the regulator API does not allow us to - * reassert regulator state, and when we read the regulator API - * logical state, it can differ from the actual state, So - * a workaround for this is to just set the regulator off in the - * PMU directly. Because that's different from normal flow, we - * have to reproduce other things from the OFF action here too. - */ - - /* - * u-boot enables LDO5 (GPS), which doesn't make sense and - * causes confusion. We therefore disable the regulator here. - */ - pcf50633_reg_write(gta02_pcf, PCF50633_REG_LDO5ENA, 0); - - /* - * take care not to power unpowered GPS from UART TX - * return them to GPIO and force low - */ - s3c2410_gpio_cfgpin(S3C2410_GPH(4), S3C2410_GPIO_OUTPUT); - s3c2410_gpio_setpin(S3C2410_GPH(4), 0); - /* don't let RX from unpowered GPS float */ - s3c2410_gpio_pullup(S3C2410_GPH(5), 1); - - return sysfs_create_group(&pdev->dev.kobj, - >a02_gps_attr_group); -} - -static int gta02_pm_gps_remove(struct platform_device *pdev) -{ - regulator_put(gta02_gps.regulator); - sysfs_remove_group(&pdev->dev.kobj, >a02_gps_attr_group); - return 0; -} - -static struct platform_driver gta02_pm_gps_driver = { - .probe = gta02_pm_gps_probe, - .remove = gta02_pm_gps_remove, - .suspend = gta02_pm_gps_suspend, - .resume = gta02_pm_gps_resume, - .driver = { - .name = "gta02-pm-gps", - }, -}; - -static int __devinit gta02_pm_gps_init(void) -{ - return platform_driver_register(>a02_pm_gps_driver); -} - -static void gta02_pm_gps_exit(void) -{ - platform_driver_unregister(>a02_pm_gps_driver); -} - -module_init(gta02_pm_gps_init); -module_exit(gta02_pm_gps_exit); - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Harald Welte "); diff --git a/target/linux/s3c24xx/files-2.6.31/arch/arm/mach-s3c2442/gta02-pm-gsm.c b/target/linux/s3c24xx/files-2.6.31/arch/arm/mach-s3c2442/gta02-pm-gsm.c deleted file mode 100644 index f80b7516e..000000000 --- a/target/linux/s3c24xx/files-2.6.31/arch/arm/mach-s3c2442/gta02-pm-gsm.c +++ /dev/null @@ -1,317 +0,0 @@ -/* - * GSM Management code for the Openmoko Freerunner GSM Phone - * - * (C) 2007 by Openmoko Inc. - * Author: Harald Welte - * All rights reserved. - * - * 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 -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include - -#include -#include -#include -#include - -int gta_gsm_interrupts; -EXPORT_SYMBOL(gta_gsm_interrupts); - -extern void s3c24xx_serial_console_set_silence(int); - -struct gta02pm_priv { - int gpio_ndl_gsm; - struct console *con; -}; - -static struct gta02pm_priv gta02_gsm; - -static struct console *find_s3c24xx_console(void) -{ - struct console *con; - - acquire_console_sem(); - - for (con = console_drivers; con; con = con->next) { - if (!strcmp(con->name, "ttySAC")) - break; - } - - release_console_sem(); - - return con; -} - -static ssize_t gsm_read(struct device *dev, struct device_attribute *attr, - char *buf) -{ - if (!strcmp(attr->attr.name, "power_on")) { - if (pcf50633_gpio_get(gta02_pcf, PCF50633_GPIO2)) - goto out_1; - } else if (!strcmp(attr->attr.name, "download")) { - if (!s3c2410_gpio_getpin(GTA02_GPIO_nDL_GSM)) - goto out_1; - } else if (!strcmp(attr->attr.name, "flowcontrolled")) { - if (s3c2410_gpio_getcfg(S3C2410_GPH(1)) == S3C2410_GPIO_OUTPUT) - goto out_1; - } - - return strlcpy(buf, "0\n", 3); -out_1: - return strlcpy(buf, "1\n", 3); -} - -static void gsm_on_off(struct device *dev, int on) -{ - if (!on) { - s3c2410_gpio_cfgpin(S3C2410_GPH(1), S3C2410_GPIO_INPUT); - s3c2410_gpio_cfgpin(S3C2410_GPH(2), S3C2410_GPIO_INPUT); - - pcf50633_gpio_set(gta02_pcf, PCF50633_GPIO2, 0); - - if (gta02_gsm.con) { - s3c24xx_serial_console_set_silence(0); - console_start(gta02_gsm.con); - - dev_dbg(dev, "powered down gta02 GSM, enabling " - "serial console\n"); - } - - return; - } - - if (gta02_gsm.con) { - dev_dbg(dev, "powering up GSM, thus " - "disconnecting serial console\n"); - - console_stop(gta02_gsm.con); - s3c24xx_serial_console_set_silence(1); - } - - /* allow UART to talk to GSM side now we will power it */ - s3c2410_gpio_cfgpin(S3C2410_GPH(1), S3C2410_GPH1_nRTS0); - s3c2410_gpio_cfgpin(S3C2410_GPH(2), S3C2410_GPH2_TXD0); - - pcf50633_gpio_set(gta02_pcf, PCF50633_GPIO2, 7); - - msleep(100); - - s3c2410_gpio_setpin(GTA02_GPIO_MODEM_ON, 1); - msleep(500); - s3c2410_gpio_setpin(GTA02_GPIO_MODEM_ON, 0); - - /* - * workaround for calypso firmware moko10 and earlier, - * without this it will leave IRQ line high after - * booting - */ - s3c2410_gpio_setpin(S3C2410_GPH(1), 1); - s3c2410_gpio_cfgpin(S3C2410_GPH(1), S3C2410_GPIO_OUTPUT); - msleep(1000); - s3c2410_gpio_cfgpin(S3C2410_GPH(1), S3C2410_GPH1_nRTS0); - -} - -static ssize_t gsm_write(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - unsigned long on = simple_strtoul(buf, NULL, 10); - - if (!strcmp(attr->attr.name, "power_on")) { - gsm_on_off(dev, on); - - return count; - } - - if (!strcmp(attr->attr.name, "download")) { - /* - * the keyboard / buttons driver requests and enables - * the JACK_INSERT IRQ. We have to take care about - * not enabling and disabling the IRQ when it was - * already in that state or we get "unblanaced IRQ" - * kernel warnings and stack dumps. So we use the - * copy of the ndl_gsm state to figure out if we should - * enable or disable the jack interrupt - */ - if (on) { - if (gta02_gsm.gpio_ndl_gsm) - disable_irq(gpio_to_irq( - GTA02_GPIO_JACK_INSERT)); - } else { - if (!gta02_gsm.gpio_ndl_gsm) - enable_irq(gpio_to_irq( - GTA02_GPIO_JACK_INSERT)); - } - - gta02_gsm.gpio_ndl_gsm = !on; - s3c2410_gpio_setpin(GTA02_GPIO_nDL_GSM, !on); - - return count; - } - - if (!strcmp(attr->attr.name, "flowcontrolled")) { - if (on) { - gta_gsm_interrupts = 0; - s3c2410_gpio_setpin(S3C2410_GPH(1), 1); - s3c2410_gpio_cfgpin(S3C2410_GPH(1), S3C2410_GPIO_OUTPUT); - } else - s3c2410_gpio_cfgpin(S3C2410_GPH(1), S3C2410_GPH1_nRTS0); - } - - return count; -} - -static DEVICE_ATTR(power_on, 0644, gsm_read, gsm_write); -static DEVICE_ATTR(reset, 0644, gsm_read, gsm_write); -static DEVICE_ATTR(download, 0644, gsm_read, gsm_write); -static DEVICE_ATTR(flowcontrolled, 0644, gsm_read, gsm_write); - -#ifdef CONFIG_PM - -static int gta02_gsm_resume(struct platform_device *pdev); -static int gta02_gsm_suspend(struct platform_device *pdev, pm_message_t state) -{ - /* GPIO state is saved/restored by S3C2410 core GPIO driver, so we - * don't need to do much here. */ - - /* If flowcontrol asserted, abort if GSM already interrupted */ - if (s3c2410_gpio_getcfg(S3C2410_GPH(1)) == S3C2410_GPIO_OUTPUT) { - if (gta_gsm_interrupts) - goto busy; - } - - /* disable DL GSM to prevent jack_insert becoming 'floating' */ - s3c2410_gpio_setpin(GTA02_GPIO_nDL_GSM, 1); - return 0; - -busy: - return -EBUSY; -} - -static int -gta02_gsm_suspend_late(struct platform_device *pdev, pm_message_t state) -{ - /* Last chance: abort if GSM already interrupted */ - if (s3c2410_gpio_getcfg(S3C2410_GPH(1)) == S3C2410_GPIO_OUTPUT) { - if (gta_gsm_interrupts) - return -EBUSY; - } - return 0; -} - -static int gta02_gsm_resume(struct platform_device *pdev) -{ - /* GPIO state is saved/restored by S3C2410 core GPIO driver, so we - * don't need to do much here. */ - - /* Make sure that the kernel console on the serial port is still - * disabled. FIXME: resume ordering race with serial driver! */ - if (gta02_gsm.con && s3c2410_gpio_getpin(GTA02_GPIO_MODEM_ON)) - console_stop(gta02_gsm.con); - - s3c2410_gpio_setpin(GTA02_GPIO_nDL_GSM, gta02_gsm.gpio_ndl_gsm); - - return 0; -} -#else -#define gta02_gsm_suspend NULL -#define gta02_gsm_suspend_late NULL -#define gta02_gsm_resume NULL -#endif /* CONFIG_PM */ - -static struct attribute *gta02_gsm_sysfs_entries[] = { - &dev_attr_power_on.attr, - &dev_attr_reset.attr, - &dev_attr_download.attr, - &dev_attr_flowcontrolled.attr, - NULL -}; - -static struct attribute_group gta02_gsm_attr_group = { - .name = NULL, - .attrs = gta02_gsm_sysfs_entries, -}; - -static int __init gta02_gsm_probe(struct platform_device *pdev) -{ - switch (S3C_SYSTEM_REV_ATAG) { - case GTA02v1_SYSTEM_REV: - case GTA02v2_SYSTEM_REV: - case GTA02v3_SYSTEM_REV: - case GTA02v4_SYSTEM_REV: - case GTA02v5_SYSTEM_REV: - case GTA02v6_SYSTEM_REV: - break; - default: - dev_warn(&pdev->dev, "Unknown Freerunner Revision 0x%x, " - "some PM features not available!!!\n", - system_rev); - break; - } - - gta02_gsm.con = find_s3c24xx_console(); - if (!gta02_gsm.con) - dev_warn(&pdev->dev, - "cannot find S3C24xx console driver\n"); - - /* note that download initially disabled, and enforce that */ - gta02_gsm.gpio_ndl_gsm = 1; - s3c2410_gpio_setpin(GTA02_GPIO_nDL_GSM, 1); - - /* GSM is to be initially off (at boot, or if this module inserted) */ - gsm_on_off(&pdev->dev, 0); - - return sysfs_create_group(&pdev->dev.kobj, >a02_gsm_attr_group); -} - -static int gta02_gsm_remove(struct platform_device *pdev) -{ - sysfs_remove_group(&pdev->dev.kobj, >a02_gsm_attr_group); - - return 0; -} - -static struct platform_driver gta02_gsm_driver = { - .probe = gta02_gsm_probe, - .remove = gta02_gsm_remove, - .suspend = gta02_gsm_suspend, - .suspend_late = gta02_gsm_suspend_late, - .resume = gta02_gsm_resume, - .driver = { - .name = "gta02-pm-gsm", - }, -}; - -static int __devinit gta02_gsm_init(void) -{ - return platform_driver_register(>a02_gsm_driver); -} - -static void gta02_gsm_exit(void) -{ - platform_driver_unregister(>a02_gsm_driver); -} - -module_init(gta02_gsm_init); -module_exit(gta02_gsm_exit); - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Harald Welte "); -MODULE_DESCRIPTION("Openmoko Freerunner GSM Power Management"); diff --git a/target/linux/s3c24xx/files-2.6.31/arch/arm/mach-s3c2442/gta02-pm-wlan.c b/target/linux/s3c24xx/files-2.6.31/arch/arm/mach-s3c2442/gta02-pm-wlan.c deleted file mode 100644 index f663b8002..000000000 --- a/target/linux/s3c24xx/files-2.6.31/arch/arm/mach-s3c2442/gta02-pm-wlan.c +++ /dev/null @@ -1,202 +0,0 @@ -/* - * GTA02 WLAN power management - * - * (C) 2008, 2009 by Openmoko Inc. - * Author: Andy Green - * All rights reserved. - * - * 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 -#include -#include -#include -#include - -#include -#include - -#include -#include -#include -#include -#include - -#include -#include - - -/* ----- Module hardware reset ("power") ----------------------------------- */ - - -void gta02_wlan_reset(int assert_reset) -{ - if (assert_reset) { - s3c2410_gpio_setpin(GTA02_GPIO_nWLAN_RESET, 0); - msleep(200); /* probably excessive but we don't have specs */ - } else { - s3c2410_gpio_setpin(GTA02_GPIO_nWLAN_RESET, 1); - } -} - -/* ----- rfkill ------------------------------------------------------------ */ - -/* - * S3C MCI handles suspend/resume through device removal/insertion. In order to - * preserve rfkill state, as required in clause 7 of section 3.1 in rfkill.txt, - * we therefore need to maintain rfkill state outside the driver. - * - * This platform driver is as good a place as any other. - */ - -static int (*gta02_wlan_rfkill_cb)(void *user, int on); -static void *gta02_wlan_rfkill_user; -static DEFINE_MUTEX(gta02_wlan_rfkill_lock); -static int gta02_wlan_rfkill_on; - -/* - * gta02_wlan_query_rfkill_lock is used to obtain the rfkill state before the - * driver is ready to process rfkill callbacks. To prevent the state from - * changing until the driver has completed its initialization, we grab and hold - * the rfkill lock. - * - * A call to gta02_wlan_query_rfkill_lock must be followed by either - * - a call to gta02_wlan_set_rfkill_cb, to complete the setup, or - * - a call to gta02_wlan_query_rfkill_unlock to abort the setup process. - */ - -int gta02_wlan_query_rfkill_lock(void) -{ - mutex_lock(>a02_wlan_rfkill_lock); - return gta02_wlan_rfkill_on; -} -EXPORT_SYMBOL_GPL(gta02_wlan_query_rfkill_lock); - -void gta02_wlan_query_rfkill_unlock(void) -{ - mutex_unlock(>a02_wlan_rfkill_lock); -} -EXPORT_SYMBOL_GPL(gta02_wlan_query_rfkill_unlock); - -void gta02_wlan_set_rfkill_cb(int (*cb)(void *user, int on), void *user) -{ - BUG_ON(!mutex_is_locked(>a02_wlan_rfkill_lock)); - BUG_ON(gta02_wlan_rfkill_cb); - gta02_wlan_rfkill_cb = cb; - gta02_wlan_rfkill_user = user; - mutex_unlock(>a02_wlan_rfkill_lock); -} -EXPORT_SYMBOL_GPL(gta02_wlan_set_rfkill_cb); - -void gta02_wlan_clear_rfkill_cb(void) -{ - mutex_lock(>a02_wlan_rfkill_lock); - BUG_ON(!gta02_wlan_rfkill_cb); - gta02_wlan_rfkill_cb = NULL; - mutex_unlock(>a02_wlan_rfkill_lock); -} -EXPORT_SYMBOL_GPL(gta02_wlan_clear_rfkill_cb); - -static int gta02_wlan_set_radio_block(void *data, bool blocked) -{ - struct device *dev = data; - int res = 0; - - dev_dbg(dev, "gta02_wlan_toggle_radio: blocked %d (%p)\n", - blocked, gta02_wlan_rfkill_cb); - mutex_lock(>a02_wlan_rfkill_lock); - if (gta02_wlan_rfkill_cb) - res = gta02_wlan_rfkill_cb(gta02_wlan_rfkill_user, !blocked); - if (!res) - gta02_wlan_rfkill_on = !blocked; - mutex_unlock(>a02_wlan_rfkill_lock); - return res; -} - -static const struct rfkill_ops gta02_wlan_rfkill_ops = { - .set_block = gta02_wlan_set_radio_block, -}; - -/* ----- Initialization/removal -------------------------------------------- */ - - -static int __init gta02_wlan_probe(struct platform_device *pdev) -{ - /* default-on for now */ - const int default_state = 1; - struct rfkill *rfkill; - int ret; - - dev_info(&pdev->dev, "starting\n"); - - s3c2410_gpio_cfgpin(GTA02_GPIO_nWLAN_RESET, S3C2410_GPIO_OUTPUT); - gta02_wlan_reset(1); - gta02_wlan_reset(0); - - rfkill = rfkill_alloc("ar6000", &pdev->dev, RFKILL_TYPE_WLAN, - >a02_wlan_rfkill_ops, &pdev->dev); - - - if (!rfkill) { - dev_err(&pdev->dev, "Failed to allocate rfkill\n"); - return -ENOMEM; - } - - rfkill_init_sw_state(rfkill, default_state); - /* - * If the WLAN driver somehow managed to get activated before we're - * ready, the driver is now in an unknown state, which isn't something - * we're prepared to handle. This can't happen, so just fail hard. - */ - BUG_ON(gta02_wlan_rfkill_cb); - gta02_wlan_rfkill_on = default_state; - - ret = rfkill_register(rfkill); - if (ret) { - rfkill_destroy(rfkill); - dev_err(&pdev->dev, "Failed to register rfkill\n"); - return ret; - } - - dev_set_drvdata(&pdev->dev, rfkill); - - return 0; -} - -static int gta02_wlan_remove(struct platform_device *pdev) -{ - struct rfkill *rfkill = dev_get_drvdata(&pdev->dev); - - rfkill_destroy(rfkill); - - return 0; -} - -static struct platform_driver gta02_wlan_driver = { - .probe = gta02_wlan_probe, - .remove = gta02_wlan_remove, - .driver = { - .name = "gta02-pm-wlan", - }, -}; - -static int __devinit gta02_wlan_init(void) -{ - return platform_driver_register(>a02_wlan_driver); -} - -static void gta02_wlan_exit(void) -{ - platform_driver_unregister(>a02_wlan_driver); -} - -module_init(gta02_wlan_init); -module_exit(gta02_wlan_exit); - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Andy Green "); -MODULE_DESCRIPTION("Openmoko GTA02 WLAN power management"); diff --git a/target/linux/s3c24xx/files-2.6.31/arch/arm/mach-s3c2442/include/mach/gta02-pm-gps.h b/target/linux/s3c24xx/files-2.6.31/arch/arm/mach-s3c2442/include/mach/gta02-pm-gps.h deleted file mode 100644 index f15180ac0..000000000 --- a/target/linux/s3c24xx/files-2.6.31/arch/arm/mach-s3c2442/include/mach/gta02-pm-gps.h +++ /dev/null @@ -1 +0,0 @@ -extern int gta02_pm_gps_is_on(void); diff --git a/target/linux/s3c24xx/files-2.6.31/arch/arm/mach-s3c2442/include/mach/gta02-pm-gsm.h b/target/linux/s3c24xx/files-2.6.31/arch/arm/mach-s3c2442/include/mach/gta02-pm-gsm.h deleted file mode 100644 index 07c072803..000000000 --- a/target/linux/s3c24xx/files-2.6.31/arch/arm/mach-s3c2442/include/mach/gta02-pm-gsm.h +++ /dev/null @@ -1 +0,0 @@ -extern int gta_gsm_interrupts; diff --git a/target/linux/s3c24xx/files-2.6.31/arch/arm/mach-s3c2442/include/mach/gta02-pm-wlan.h b/target/linux/s3c24xx/files-2.6.31/arch/arm/mach-s3c2442/include/mach/gta02-pm-wlan.h deleted file mode 100644 index 483697897..000000000 --- a/target/linux/s3c24xx/files-2.6.31/arch/arm/mach-s3c2442/include/mach/gta02-pm-wlan.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef __MACH_GTA02_PM_WLAN_H -#define __MACH_GTA02_PM_WLAN_H - -void gta02_wlan_reset(int assert_reset); -int gta02_wlan_query_rfkill_lock(void); -void gta02_wlan_query_rfkill_unlock(void); -void gta02_wlan_set_rfkill_cb(int (*cb)(void *user, int on), void *user); -void gta02_wlan_clear_rfkill_cb(void); - -#endif /* __MACH_GTA02_PM_WLAN_H */ diff --git a/target/linux/s3c24xx/files-2.6.31/arch/arm/mach-s3c2442/include/mach/gta02.h b/target/linux/s3c24xx/files-2.6.31/arch/arm/mach-s3c2442/include/mach/gta02.h deleted file mode 100644 index dec9b0bd2..000000000 --- a/target/linux/s3c24xx/files-2.6.31/arch/arm/mach-s3c2442/include/mach/gta02.h +++ /dev/null @@ -1,90 +0,0 @@ -#ifndef _GTA02_H -#define _GTA02_H - -#include -#include -#include -#include - -/* Different hardware revisions, passed in ATAG_REVISION by u-boot */ -#define GTA02v1_SYSTEM_REV 0x00000310 -#define GTA02v2_SYSTEM_REV 0x00000320 -#define GTA02v3_SYSTEM_REV 0x00000330 -#define GTA02v4_SYSTEM_REV 0x00000340 -#define GTA02v5_SYSTEM_REV 0x00000350 -#define GTA02v6_SYSTEM_REV 0x00000360 - -#define GTA02_GPIO_n3DL_GSM S3C2410_GPA(13) /* v1 + v2 + v3 only */ - -#define GTA02_GPIO_PWR_LED1 S3C2410_GPB(0) -#define GTA02_GPIO_PWR_LED2 S3C2410_GPB(1) -#define GTA02_GPIO_AUX_LED S3C2410_GPB(2) -#define GTA02_GPIO_VIBRATOR_ON S3C2410_GPB(3) -#define GTA02_GPIO_MODEM_RST S3C2410_GPB(5) -#define GTA02_GPIO_BT_EN S3C2410_GPB(6) -#define GTA02_GPIO_MODEM_ON S3C2410_GPB(7) -#define GTA02_GPIO_EXTINT8 S3C2410_GPB(8) -#define GTA02_GPIO_USB_PULLUP S3C2410_GPB(9) - -#define GTA02_GPIO_PIO5 S3C2410_GPC(5) /* v3 + v4 only */ -#define GTA02v3_GPIO_nG1_CS S3C2410_GPD(12) /* v3 + v4 only */ -#define GTA02v3_GPIO_nG2_CS S3C2410_GPD(13) /* v3 + v4 only */ -#define GTA02v5_GPIO_HDQ S3C2410_GPD(14) /* v5 + */ - -#define GTA02_GPIO_nG1_INT S3C2410_GPF(0) -#define GTA02_GPIO_IO1 S3C2410_GPF(1) -#define GTA02_GPIO_PIO_2 S3C2410_GPF(2) /* v2 + v3 + v4 only */ -#define GTA02_GPIO_JACK_INSERT S3C2410_GPF(4) -#define GTA02_GPIO_WLAN_GPIO1 S3C2410_GPF(5) /* v2 + v3 + v4 only */ -#define GTA02_GPIO_AUX_KEY S3C2410_GPF(6) -#define GTA02_GPIO_HOLD_KEY S3C2410_GPF(7) - -#define GTA02_GPIO_3D_IRQ S3C2410_GPG(4) -#define GTA02v2_GPIO_nG2_INT S3C2410_GPG(8) /* v2 + v3 + v4 only */ -#define GTA02v3_GPIO_nUSB_OC S3C2410_GPG(9) /* v3 + v4 only */ -#define GTA02v3_GPIO_nUSB_FLT S3C2410_GPG(10) /* v3 + v4 only */ -#define GTA02v3_GPIO_nGSM_OC S3C2410_GPG(11) /* v3 + v4 only */ - -#define GTA02_GPIO_AMP_SHUT S3C2440_GPJ1 /* v2 + v3 + v4 only */ -#define GTA02v1_GPIO_WLAN_GPIO10 S3C2440_GPJ2 -#define GTA02_GPIO_HP_IN S3C2440_GPJ2 /* v2 + v3 + v4 only */ -#define GTA02_GPIO_INT0 S3C2440_GPJ3 /* v2 + v3 + v4 only */ -#define GTA02_GPIO_nGSM_EN S3C2440_GPJ4 -#define GTA02_GPIO_3D_RESET S3C2440_GPJ5 -#define GTA02_GPIO_nDL_GSM S3C2440_GPJ6 /* v4 + v5 only */ -#define GTA02_GPIO_WLAN_GPIO0 S3C2440_GPJ7 -#define GTA02v1_GPIO_BAT_ID S3C2440_GPJ8 -#define GTA02_GPIO_KEEPACT S3C2440_GPJ8 -#define GTA02v1_GPIO_HP_IN S3C2440_GPJ10 -#define GTA02_CHIP_PWD S3C2440_GPJ11 /* v2 + v3 + v4 only */ -#define GTA02_GPIO_nWLAN_RESET S3C2440_GPJ12 /* v2 + v3 + v4 only */ - -#define GTA02_IRQ_GSENSOR_1 IRQ_EINT0 -#define GTA02_IRQ_MODEM IRQ_EINT1 -#define GTA02_IRQ_PIO_2 IRQ_EINT2 /* v2 + v3 + v4 only */ -#define GTA02_IRQ_nJACK_INSERT IRQ_EINT4 -#define GTA02_IRQ_WLAN_GPIO1 IRQ_EINT5 -#define GTA02_IRQ_AUX IRQ_EINT6 -#define GTA02_IRQ_nHOLD IRQ_EINT7 -#define GTA02_IRQ_PCF50633 IRQ_EINT9 -#define GTA02_IRQ_3D IRQ_EINT12 -#define GTA02_IRQ_GSENSOR_2 IRQ_EINT16 /* v2 + v3 + v4 only */ -#define GTA02v3_IRQ_nUSB_OC IRQ_EINT17 /* v3 + v4 only */ -#define GTA02v3_IRQ_nUSB_FLT IRQ_EINT18 /* v3 + v4 only */ -#define GTA02v3_IRQ_nGSM_OC IRQ_EINT19 /* v3 + v4 only */ - -/* returns 00 000 on GTA02 A5 and earlier, A6 returns 01 001 */ -#define GTA02_PCB_ID1_0 S3C2410_GPC(13) -#define GTA02_PCB_ID1_1 S3C2410_GPC(15) -#define GTA02_PCB_ID1_2 S3C2410_GPD(0) -#define GTA02_PCB_ID2_0 S3C2410_GPD(3) -#define GTA02_PCB_ID2_1 S3C2410_GPD(4) - -#define GTA02_GPIO_GLAMO_BASE S3C_GPIO_END -#define GTA02_GPIO_GLAMO(x) (GTA02_GPIO_GLAMO_BASE + x) - -int gta02_get_pcb_revision(void); - -extern struct pcf50633 *gta02_pcf; - -#endif /* _GTA02_H */ diff --git a/target/linux/s3c24xx/files-2.6.31/arch/arm/mach-s3c2442/mach-gta02.c b/target/linux/s3c24xx/files-2.6.31/arch/arm/mach-s3c2442/mach-gta02.c deleted file mode 100644 index 2b2e5ad70..000000000 --- a/target/linux/s3c24xx/files-2.6.31/arch/arm/mach-s3c2442/mach-gta02.c +++ /dev/null @@ -1,1686 +0,0 @@ -/* - * linux/arch/arm/mach-s3c2442/mach-gta02.c - * - * S3C2442 Machine Support for the Openmoko Freerunner (GTA02) - * - * Copyright (C) 2006-2007 by Openmoko, Inc. - * Author: Harald Welte - * All rights reserved. - * - * 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, - * MA 02111-1307 USA - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include -#include -#include - -#include -#include -#include -#include -#include - -#include - -#include -#include -#include - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include -#include -#include - -#include -#include - -#include -#ifdef CONFIG_TOUCHSCREEN_FILTER -#include -#include -#include -#include -#endif - -#include - -#include - -/* ------------------------------------------------------------------------------- - * GTA02 FIQ related - * - * Calls into vibrator and hdq and based on the return values - * determines if we the FIQ source be kept alive - */ - -#define DIVISOR_FROM_US(x) ((x) << 3) - -#ifdef CONFIG_HDQ_GPIO_BITBANG -#define FIQ_DIVISOR_HDQ DIVISOR_FROM_US(HDQ_SAMPLE_PERIOD_US) -extern int hdq_fiq_handler(void); -#endif - -#ifdef CONFIG_LEDS_GTA02_VIBRATOR -#define FIQ_DIVISOR_VIBRATOR DIVISOR_FROM_US(100) -extern int gta02_vibrator_fiq_handler(void); -#endif - -#if defined(CONFIG_LEDS_GTA02_VIBRATOR) || defined(CONFIG_HDQ_GPIO_BITBANG) - -/* Global data related to our fiq source */ -static u32 gta02_fiq_ack_mask; -static struct s3c2410_pwm gta02_fiq_pwm_timer; -static u16 gta02_fiq_timer_index; -static int gta02_fiq_irq; - -static void gta02_fiq_handler(void) -{ - u16 divisor = 0xffff; - - /* Vibrator servicing */ - - /* disable further timer interrupts if nobody has any work - * or adjust rate according to who still has work - * - * CAUTION: it means forground code must disable FIQ around - * its own non-atomic S3C2410_INTMSK changes... not common - * thankfully and taken care of by the fiq-basis patch - */ - -#ifdef CONFIG_LEDS_GTA02_VIBRATOR - if (gta02_vibrator_fiq_handler()) - divisor = FIQ_DIVISOR_VIBRATOR; -#endif - -#ifdef CONFIG_HDQ_GPIO_BITBANG - if (hdq_fiq_handler()) - divisor = FIQ_DIVISOR_HDQ; -#endif - - if (divisor == 0xffff) /* mask the fiq irq source */ - __raw_writel(__raw_readl(S3C2410_INTMSK) | gta02_fiq_ack_mask, - S3C2410_INTMSK); - else /* still working, maybe at a different rate */ - __raw_writel(divisor, S3C2410_TCNTB(gta02_fiq_timer_index)); - - __raw_writel(gta02_fiq_ack_mask, S3C2410_SRCPND); -} - -static void gta02_fiq_kick(void) -{ - unsigned long flags; - u32 tcon; - - /* we have to take care about FIQ because this modification is - * non-atomic, FIQ could come in after the read and before the - * writeback and its changes to the register would be lost - * (platform INTMSK mod code is taken care of already) - */ - local_save_flags(flags); - local_fiq_disable(); - /* allow FIQs to resume */ - __raw_writel(__raw_readl(S3C2410_INTMSK) & - ~(1 << (gta02_fiq_irq - S3C2410_CPUIRQ_OFFSET)), - S3C2410_INTMSK); - tcon = __raw_readl(S3C2410_TCON) & ~S3C2410_TCON_T3START; - /* fake the timer to a count of 1 */ - __raw_writel(1, S3C2410_TCNTB(gta02_fiq_timer_index)); - __raw_writel(tcon | S3C2410_TCON_T3MANUALUPD, S3C2410_TCON); - __raw_writel(tcon | S3C2410_TCON_T3MANUALUPD | S3C2410_TCON_T3START, - S3C2410_TCON); - __raw_writel(tcon | S3C2410_TCON_T3START, S3C2410_TCON); - local_irq_restore(flags); -} - -static int gta02_fiq_enable(void) -{ - int irq_index_fiq = IRQ_TIMER3; - int rc = 0; - - local_fiq_disable(); - - gta02_fiq_irq = irq_index_fiq; - gta02_fiq_ack_mask = 1 << (irq_index_fiq - S3C2410_CPUIRQ_OFFSET); - gta02_fiq_timer_index = (irq_index_fiq - IRQ_TIMER0); - - /* set up the timer to operate as a pwm device */ - - rc = s3c2410_pwm_init(>a02_fiq_pwm_timer); - if (rc) - goto bail; - - gta02_fiq_pwm_timer.timerid = PWM0 + gta02_fiq_timer_index; - gta02_fiq_pwm_timer.prescaler = (6 - 1) / 2; - gta02_fiq_pwm_timer.divider = S3C2410_TCFG1_MUX3_DIV2; - /* default rate == ~32us */ - gta02_fiq_pwm_timer.counter = gta02_fiq_pwm_timer.comparer = 3000; - - rc = s3c2410_pwm_enable(>a02_fiq_pwm_timer); - if (rc) - goto bail; - - s3c2410_pwm_start(>a02_fiq_pwm_timer); - - /* let our selected interrupt be a magic FIQ interrupt */ - __raw_writel(gta02_fiq_ack_mask, S3C2410_INTMOD); - - /* it's ready to go as soon as we unmask the source in S3C2410_INTMSK */ - local_fiq_enable(); - - set_fiq_c_handler(gta02_fiq_handler); - - return 0; - -bail: - printk(KERN_ERR "Could not initialize FIQ for GTA02: %d\n", rc); - - return rc; -} - -static void gta02_fiq_disable(void) -{ - __raw_writel(0, S3C2410_INTMOD); - local_fiq_disable(); - gta02_fiq_irq = 0; /* no active source interrupt now either */ - -} -/* -------------------- /GTA02 FIQ Handler ------------------------------------- */ - -#endif - -/* - * this gets called every 1ms when we paniced. - */ - -static long gta02_panic_blink(long count) -{ - long delay = 0; - static long last_blink; - static char led; - - if (count - last_blink < 100) /* 200ms period, fast blink */ - return 0; - - led ^= 1; - s3c2410_gpio_cfgpin(GTA02_GPIO_AUX_LED, S3C2410_GPIO_OUTPUT); - s3c2410_gpio_setpin(GTA02_GPIO_AUX_LED, led); - - last_blink = count; - return delay; -} - - -/** - * returns PCB revision information in b9,b8 and b2,b1,b0 - * Pre-GTA02 A6 returns 0x000 - * GTA02 A6 returns 0x101 - * ... - */ - -int gta02_get_pcb_revision(void) -{ - int n; - int u = 0; - static unsigned long pinlist[] = { - GTA02_PCB_ID1_0, - GTA02_PCB_ID1_1, - GTA02_PCB_ID1_2, - GTA02_PCB_ID2_0, - GTA02_PCB_ID2_1, - }; - static int pin_offset[] = { - 0, 1, 2, 8, 9 - }; - - for (n = 0 ; n < ARRAY_SIZE(pinlist); n++) { - /* - * set the PCB version GPIO to be pulled-down input - * force low briefly first - */ - s3c2410_gpio_cfgpin(pinlist[n], S3C2410_GPIO_OUTPUT); - s3c2410_gpio_setpin(pinlist[n], 0); - /* misnomer: it is a pullDOWN in 2442 */ - s3c2410_gpio_pullup(pinlist[n], 1); - s3c2410_gpio_cfgpin(pinlist[n], S3C2410_GPIO_INPUT); - - udelay(10); - - if (s3c2410_gpio_getpin(pinlist[n])) - u |= 1 << pin_offset[n]; - - /* - * when not being interrogated, all of the revision GPIO - * are set to output HIGH without pulldown so no current flows - * if they are NC or pulled up. - */ - s3c2410_gpio_setpin(pinlist[n], 1); - s3c2410_gpio_cfgpin(pinlist[n], S3C2410_GPIO_OUTPUT); - /* misnomer: it is a pullDOWN in 2442 */ - s3c2410_gpio_pullup(pinlist[n], 0); - } - - return u; -} - -struct platform_device gta02_resume_reason_device = { - .name = "gta02-resume", - .num_resources = 0, -}; - -static struct map_desc gta02_iodesc[] __initdata = { - { - .virtual = 0xe0000000, - .pfn = __phys_to_pfn(S3C2410_CS3+0x01000000), - .length = SZ_1M, - .type = MT_DEVICE - }, -}; - -#define UCON (S3C2410_UCON_DEFAULT | S3C2443_UCON_RXERR_IRQEN) -#define ULCON S3C2410_LCON_CS8 | S3C2410_LCON_PNONE | S3C2410_LCON_STOPB -#define UFCON S3C2410_UFCON_RXTRIG8 | S3C2410_UFCON_FIFOMODE - -static struct s3c2410_uartcfg gta02_uartcfgs[] = { - [0] = { - .hwport = 0, - .flags = 0, - .ucon = UCON, - .ulcon = ULCON, - .ufcon = UFCON, - }, - [1] = { - .hwport = 1, - .flags = 0, - .ucon = UCON, - .ulcon = ULCON, - .ufcon = UFCON, - }, - [2] = { - .hwport = 2, - .flags = 0, - .ucon = UCON, - .ulcon = ULCON, - .ufcon = UFCON, - }, - -}; - -struct pcf50633 *gta02_pcf; - -#ifdef CONFIG_CHARGER_PCF50633 -#ifdef CONFIG_HDQ_GPIO_BITBANG -static int gta02_get_charger_online_status(void) -{ - struct pcf50633 *pcf = gta02_pcf; - - return pcf50633_mbc_get_status(pcf) & PCF50633_MBC_USB_ONLINE; -} - -static int gta02_get_charger_active_status(void) -{ - struct pcf50633 *pcf = gta02_pcf; - - return pcf50633_mbc_get_status(pcf) & PCF50633_MBC_USB_ACTIVE; -} -#endif - -#define ADC_NOM_CHG_DETECT_1A 6 -#define ADC_NOM_CHG_DETECT_USB 43 - -static void -gta02_configure_pmu_for_charger(struct pcf50633 *pcf, void *unused, int res) -{ - int ma; - - /* Interpret charger type */ - if (res < ((ADC_NOM_CHG_DETECT_USB + ADC_NOM_CHG_DETECT_1A) / 2)) { - - /* Stop GPO driving out now that we have a IA charger */ - pcf50633_gpio_set(pcf, PCF50633_GPO, 0); - - ma = 1000; - } else - ma = 100; - - pcf50633_mbc_usb_curlim_set(pcf, ma); -} - -static struct delayed_work gta02_charger_work; -static int gta02_usb_vbus_draw; - -static void gta02_charger_worker(struct work_struct *work) -{ - struct pcf50633 *pcf = gta02_pcf; - - if (gta02_usb_vbus_draw) { - pcf50633_mbc_usb_curlim_set(pcf, gta02_usb_vbus_draw); - return; - } else { -#ifdef CONFIG_PCF50633_ADC - pcf50633_adc_async_read(pcf, - PCF50633_ADCC1_MUX_ADCIN1, - PCF50633_ADCC1_AVERAGE_16, - gta02_configure_pmu_for_charger, NULL); -#else - /* If the PCF50633 ADC is disabled we fallback to a 100mA limit for safety. */ - pcf50633_mbc_usb_curlim_set(pcf, 100); -#endif - return; - } -} - -#define GTA02_CHARGER_CONFIGURE_TIMEOUT ((3000 * HZ) / 1000) -static void gta02_pmu_event_callback(struct pcf50633 *pcf, int irq) -{ - if (irq == PCF50633_IRQ_USBINS) { - schedule_delayed_work(>a02_charger_work, - GTA02_CHARGER_CONFIGURE_TIMEOUT); - return; - } else if (irq == PCF50633_IRQ_USBREM) { - cancel_delayed_work_sync(>a02_charger_work); - gta02_usb_vbus_draw = 0; - } -} - -static void gta02_pmu_force_shutdown(struct pcf50633 *pcf) -{ - pcf50633_reg_set_bit_mask(pcf, PCF50633_REG_OOCSHDWN, - PCF50633_OOCSHDWN_GOSTDBY, PCF50633_OOCSHDWN_GOSTDBY); -} - - -static void gta02_udc_vbus_draw(unsigned int ma) -{ - if (!gta02_pcf) - return; - - gta02_usb_vbus_draw = ma; - - schedule_delayed_work(>a02_charger_work, - GTA02_CHARGER_CONFIGURE_TIMEOUT); -} - -static int gta02_udc_vbus_status(void) -{ - struct pcf50633 *pcf = gta02_pcf; - if (!gta02_pcf) - return -ENODEV; - - return !!(pcf50633_mbc_get_status(pcf) & PCF50633_MBC_USB_ONLINE); -} - -#else /* !CONFIG_CHARGER_PCF50633 */ -#ifdef CONFIG_HDQ_GPIO_BITBANG -#define gta02_get_charger_online_status NULL -#define gta02_get_charger_active_status NULL -#endif -#define gta02_pmu_event_callback NULL -#define gta02_udc_vbus_draw NULL -#define gta02_udc_vbus_status NULL -#endif - - -static struct platform_device gta02_pm_gps_dev = { - .name = "gta02-pm-gps", -}; - -static struct platform_device gta02_pm_bt_dev = { - .name = "gta02-pm-bt", -}; - -static struct platform_device gta02_pm_gsm_dev = { - .name = "gta02-pm-gsm", -}; - -static struct platform_device gta02_pm_wlan_dev = { - .name = "gta02-pm-wlan", -}; - -/* this is called when pc50633 is probed, unfortunately quite late in the - * day since it is an I2C bus device. Here we can belatedly define some - * platform devices with the advantage that we can mark the pcf50633 as the - * parent. This makes them get suspended and resumed with their parent - * the pcf50633 still around. - */ - -static struct platform_device gta02_glamo_dev; - -static void gta02_pmu_attach_child_devices(struct pcf50633 *pcf); -static void gta02_pmu_regulator_registered(struct pcf50633 *pcf, int id); - -static struct regulator_consumer_supply ldo4_consumers[] = { - { - .dev = >a02_pm_bt_dev.dev, - .supply = "BT_3V2", - }, -}; - -static struct regulator_consumer_supply ldo5_consumers[] = { - { - .dev = >a02_pm_gps_dev.dev, - .supply = "RF_3V", - }, -}; - -static struct regulator_consumer_supply hcldo_consumers[] = { - { - .dev = >a02_glamo_dev.dev, - .supply = "SD_3V3", - }, -}; - -static struct regulator_consumer_supply ldo6_consumers[] = { - { .supply = "VDC" }, - { .supply = "VDDIO" }, -}; - -static char *gta02_batteries[] = { - "battery", -}; - -#ifdef CONFIG_CHARGER_PCF50633 - -struct pcf50633_platform_data gta02_pcf_pdata = { - .resumers = { - [0] = PCF50633_INT1_USBINS | - PCF50633_INT1_USBREM | - PCF50633_INT1_ALARM, - [1] = PCF50633_INT2_ONKEYF, - [2] = PCF50633_INT3_ONKEY1S, - [3] = PCF50633_INT4_LOWSYS | - PCF50633_INT4_LOWBAT | - PCF50633_INT4_HIGHTMP, - }, - - .batteries = gta02_batteries, - .num_batteries = ARRAY_SIZE(gta02_batteries), - .charging_restart_interval = (900 * HZ), - .chg_ref_current_ma = 1000, - - .reg_init_data = { - [PCF50633_REGULATOR_AUTO] = { - .constraints = { - .name = "IO_3V3", - .min_uV = 3300000, - .max_uV = 3300000, - .valid_modes_mask = REGULATOR_MODE_NORMAL, - .boot_on = 1, - .always_on = 1, - .apply_uV = 1, - .state_mem = { - .enabled = 1, - }, - }, - .num_consumer_supplies = 0, - }, - [PCF50633_REGULATOR_DOWN1] = { - .constraints = { - .name = "CORE_1V3", - .min_uV = 1300000, - .max_uV = 1600000, - .valid_modes_mask = REGULATOR_MODE_NORMAL, - .boot_on = 1, - .always_on = 1, - .apply_uV = 1, - }, - .num_consumer_supplies = 0, - }, - [PCF50633_REGULATOR_DOWN2] = { - .constraints = { - .name = "IO_1V8", - .min_uV = 1800000, - .max_uV = 1800000, - .valid_modes_mask = REGULATOR_MODE_NORMAL, - .apply_uV = 1, - .boot_on = 1, - .always_on = 1, - .state_mem = { - .enabled = 1, - }, - }, - .num_consumer_supplies = 0, - }, - [PCF50633_REGULATOR_HCLDO] = { - .constraints = { - .name = "SD_3V3", - .min_uV = 2000000, - .max_uV = 3300000, - .valid_modes_mask = REGULATOR_MODE_NORMAL, - .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE, - .boot_on = 1, - }, - .num_consumer_supplies = ARRAY_SIZE(hcldo_consumers), - .consumer_supplies = hcldo_consumers, - }, - [PCF50633_REGULATOR_LDO1] = { - .constraints = { - .name = "GSENSOR_3V3", - .min_uV = 3300000, - .max_uV = 3300000, - .valid_modes_mask = REGULATOR_MODE_NORMAL, - .apply_uV = 1, - .always_on = 1, - }, - .num_consumer_supplies = 0, - }, - [PCF50633_REGULATOR_LDO2] = { - .constraints = { - .name = "CODEC_3V3", - .min_uV = 3300000, - .max_uV = 3300000, - .valid_modes_mask = REGULATOR_MODE_NORMAL, - .apply_uV = 1, - .always_on = 1, - }, - .num_consumer_supplies = 0, - }, - [PCF50633_REGULATOR_LDO3] = { - .constraints = { - .min_uV = 3000000, - .max_uV = 3000000, - .valid_modes_mask = REGULATOR_MODE_NORMAL, - .apply_uV = 1, - .always_on = 1, - }, - .num_consumer_supplies = 0, - }, - [PCF50633_REGULATOR_LDO4] = { - .constraints = { - .name = "BT_3V2", - .min_uV = 3200000, - .max_uV = 3200000, - .valid_modes_mask = REGULATOR_MODE_NORMAL, - .always_on = 1, - .apply_uV = 1, - }, - .num_consumer_supplies = ARRAY_SIZE(ldo4_consumers), - .consumer_supplies = ldo4_consumers, - }, - [PCF50633_REGULATOR_LDO5] = { - .constraints = { - .name = "RF_3V", - .min_uV = 3000000, - .max_uV = 3000000, - .valid_modes_mask = REGULATOR_MODE_NORMAL, - .apply_uV = 1, - .state_mem = { - .enabled = 1, - }, - }, - .num_consumer_supplies = ARRAY_SIZE(ldo5_consumers), - .consumer_supplies = ldo5_consumers, - }, - [PCF50633_REGULATOR_LDO6] = { - .constraints = { - .name = "LCM_3V", - .min_uV = 3000000, - .max_uV = 3000000, - .always_on = 0, - .valid_modes_mask = REGULATOR_MODE_NORMAL, - .apply_uV = 1, - }, - .num_consumer_supplies = ARRAY_SIZE(ldo6_consumers), - .consumer_supplies = ldo6_consumers, - }, - }, - .probe_done = gta02_pmu_attach_child_devices, - .regulator_registered = gta02_pmu_regulator_registered, - .mbc_event_callback = gta02_pmu_event_callback, - .force_shutdown = gta02_pmu_force_shutdown, -}; - -#endif - -#ifdef CONFIG_HDQ_GPIO_BITBANG -/* BQ27000 Battery */ - -struct bq27000_platform_data bq27000_pdata = { - .name = "battery", - .rsense_mohms = 20, - .hdq_read = hdq_read, - .hdq_write = hdq_write, - .hdq_initialized = hdq_initialized, - .get_charger_online_status = gta02_get_charger_online_status, - .get_charger_active_status = gta02_get_charger_active_status -}; - -struct platform_device bq27000_battery_device = { - .name = "bq27000-battery", - .dev = { - .platform_data = &bq27000_pdata, - }, -}; - -/* HDQ */ - -static void gta02_hdq_attach_child_devices(struct device *parent_device) -{ - switch (S3C_SYSTEM_REV_ATAG) { - case GTA02v5_SYSTEM_REV: - case GTA02v6_SYSTEM_REV: - bq27000_battery_device.dev.parent = parent_device; - platform_device_register(&bq27000_battery_device); - break; - default: - break; - } -} - -static void gta02_hdq_gpio_direction_out(void) -{ - s3c2410_gpio_cfgpin(GTA02v5_GPIO_HDQ, S3C2410_GPIO_OUTPUT); -} - -static void gta02_hdq_gpio_direction_in(void) -{ - s3c2410_gpio_cfgpin(GTA02v5_GPIO_HDQ, S3C2410_GPIO_INPUT); -} - -static void gta02_hdq_gpio_set_value(int val) -{ - - s3c2410_gpio_setpin(GTA02v5_GPIO_HDQ, val); -} - -static int gta02_hdq_gpio_get_value(void) -{ - return s3c2410_gpio_getpin(GTA02v5_GPIO_HDQ); -} - -static struct resource gta02_hdq_resources[] = { - [0] = { - .start = GTA02v5_GPIO_HDQ, - .end = GTA02v5_GPIO_HDQ, - }, -}; - -struct hdq_platform_data gta02_hdq_platform_data = { - .attach_child_devices = gta02_hdq_attach_child_devices, - .gpio_dir_out = gta02_hdq_gpio_direction_out, - .gpio_dir_in = gta02_hdq_gpio_direction_in, - .gpio_set = gta02_hdq_gpio_set_value, - .gpio_get = gta02_hdq_gpio_get_value, - - .enable_fiq = gta02_fiq_enable, - .disable_fiq = gta02_fiq_disable, - .kick_fiq = gta02_fiq_kick, - -}; - -struct platform_device gta02_hdq_device = { - .name = "hdq", - .num_resources = 1, - .resource = gta02_hdq_resources, - .dev = { - .platform_data = >a02_hdq_platform_data, - }, -}; -#endif - - -/* vibrator (child of FIQ) */ - -static struct resource gta02_vibrator_resources[] = { - [0] = { - .start = GTA02_GPIO_VIBRATOR_ON, - .end = GTA02_GPIO_VIBRATOR_ON, - }, -}; -struct gta02_vib_platform_data gta02_vib_pdata = { - .enable_fiq = gta02_fiq_enable, - .disable_fiq = gta02_fiq_disable, - .kick_fiq = gta02_fiq_kick, -}; - -static struct platform_device gta02_vibrator_dev = { - .name = "gta02-vibrator", - .num_resources = ARRAY_SIZE(gta02_vibrator_resources), - .resource = gta02_vibrator_resources, - .dev = { - .platform_data = >a02_vib_pdata, - }, -}; - -/* NOR Flash */ - -#define GTA02_FLASH_BASE S3C2410_CS3 /* GCS3 */ -#define GTA02_FLASH_SIZE 0x200000 /* 2MBytes */ - -static struct physmap_flash_data gta02_nor_flash_data = { - .width = 2, -}; - -static struct resource gta02_nor_flash_resource = { - .start = GTA02_FLASH_BASE, - .end = GTA02_FLASH_BASE + GTA02_FLASH_SIZE - 1, - .flags = IORESOURCE_MEM, -}; - -static struct platform_device gta02_nor_flash = { - .name = "physmap-flash", - .id = 0, - .dev = { - .platform_data = >a02_nor_flash_data, - }, - .resource = >a02_nor_flash_resource, - .num_resources = 1, -}; - - -struct platform_device s3c24xx_pwm_device = { - .name = "s3c24xx_pwm", - .num_resources = 0, -}; - -static struct i2c_board_info gta02_i2c_devs[] __initdata = { - { - I2C_BOARD_INFO("pcf50633", 0x73), - .irq = GTA02_IRQ_PCF50633, - .platform_data = >a02_pcf_pdata, - }, - { - I2C_BOARD_INFO("wm8753", 0x1a), - }, -}; - -static struct s3c2410_nand_set gta02_nand_sets[] = { - [0] = { - .name = "neo1973-nand", - .nr_chips = 1, - .flags = S3C2410_NAND_BBT, - }, -}; - -/* choose a set of timings derived from S3C@2442B MCP54 - * data sheet (K5D2G13ACM-D075 MCP Memory) - */ - -static struct s3c2410_platform_nand gta02_nand_info = { - .tacls = 0, - .twrph0 = 25, - .twrph1 = 15, - .nr_sets = ARRAY_SIZE(gta02_nand_sets), - .sets = gta02_nand_sets, - .software_ecc = 1, -}; - - -static void gta02_s3c_mmc_set_power(unsigned char power_mode, - unsigned short vdd) -{ - static int is_on = -1; - int on; - - on = power_mode == MMC_POWER_ON || power_mode == MMC_POWER_UP; - if (is_on != on) - gta02_wlan_reset(!on); - is_on = on; -} - - -static struct s3c24xx_mci_pdata gta02_s3c_mmc_cfg = { - .set_power = gta02_s3c_mmc_set_power, -}; - -static void gta02_udc_command(enum s3c2410_udc_cmd_e cmd) -{ - switch (cmd) { - case S3C2410_UDC_P_ENABLE: - printk(KERN_DEBUG "%s S3C2410_UDC_P_ENABLE\n", __func__); - s3c2410_gpio_setpin(GTA02_GPIO_USB_PULLUP, 1); - break; - case S3C2410_UDC_P_DISABLE: - printk(KERN_DEBUG "%s S3C2410_UDC_P_DISABLE\n", __func__); - s3c2410_gpio_setpin(GTA02_GPIO_USB_PULLUP, 0); - break; - case S3C2410_UDC_P_RESET: - printk(KERN_DEBUG "%s S3C2410_UDC_P_RESET\n", __func__); - /* FIXME! */ - break; - default: - break; - } -} - -/* get PMU to set USB current limit accordingly */ - -static struct s3c2410_udc_mach_info gta02_udc_cfg = { - .vbus_draw = gta02_udc_vbus_draw, - .udc_command = gta02_udc_command, -/* .get_vbus_status = gta02_udc_vbus_status,*/ -}; - - -/* Touchscreen configuration. */ - -#ifdef CONFIG_TOUCHSCREEN_FILTER -const static struct ts_filter_group_configuration gta02_ts_group = { - .length = 12, - .close_enough = 10, - .threshold = 6, /* At least half of the points in a group. */ - .attempts = 10, -}; - -const static struct ts_filter_median_configuration gta02_ts_median = { - .extent = 20, - .decimation_below = 3, - .decimation_threshold = 8 * 3, - .decimation_above = 4, -}; - -const static struct ts_filter_mean_configuration gta02_ts_mean = { - .length = 4, -}; - -const static struct ts_filter_linear_configuration gta02_ts_linear = { - .constants = {1, 0, 0, 0, 1, 0, 1}, /* Don't modify coords. */ - .coord0 = 0, - .coord1 = 1, -}; -#endif - -const static struct ts_filter_chain_configuration gta02_filter_configuration[] = -{ -#ifdef CONFIG_TOUCHSCREEN_FILTER - {&ts_filter_group_api, >a02_ts_group.config}, - {&ts_filter_median_api, >a02_ts_median.config}, - {&ts_filter_mean_api, >a02_ts_mean.config}, - {&ts_filter_linear_api, >a02_ts_linear.config}, -#endif - {NULL, NULL}, -}; - -const static struct s3c2410_ts_mach_info gta02_ts_cfg = { - .delay = 10000, - .presc = 0xff, /* slow as we can go */ - .filter_config = gta02_filter_configuration, -}; - - - -static void gta02_bl_set_intensity(int intensity) -{ - struct pcf50633 *pcf = gta02_pcf; - int old_intensity = pcf50633_reg_read(pcf, PCF50633_REG_LEDOUT); - int ret; - - /* - * One code path that leads here is from a kernel panic. Trying to turn - * the backlight on just gives us a nearly endless stream of complaints - * and accomplishes nothing. We can't win. Just give up. - * - * In the unlikely event that there's another path leading here while - * we're atomic, we print at least a warning. - */ - if (in_atomic()) { - printk(KERN_ERR - "gta02_bl_set_intensity called while atomic\n"); - return; - } - - if (!(pcf50633_reg_read(pcf, PCF50633_REG_LEDENA) & 3)) - old_intensity = 0; - else - old_intensity = pcf50633_reg_read(pcf, PCF50633_REG_LEDOUT); - - if (intensity == old_intensity) - return; - - /* We can't do this anywhere else */ - pcf50633_reg_write(pcf, PCF50633_REG_LEDDIM, 5); - - /* - * The PCF50633 cannot handle LEDOUT = 0 (datasheet p60) - * if seen, you have to re-enable the LED unit - */ - if (!intensity || !old_intensity) - pcf50633_reg_write(pcf, PCF50633_REG_LEDENA, 0); - - if (!intensity) /* illegal to set LEDOUT to 0 */ - ret = pcf50633_reg_set_bit_mask(pcf, PCF50633_REG_LEDOUT, 0x3f, - 2); - else - ret = pcf50633_reg_set_bit_mask(pcf, PCF50633_REG_LEDOUT, 0x3f, - intensity); - - if (intensity) - pcf50633_reg_write(pcf, PCF50633_REG_LEDENA, 2); - -} - -static struct generic_bl_info gta02_bl_info = { - .name = "gta02-bl", - .max_intensity = 0x3f, - .default_intensity = 0x3f, - .set_bl_intensity = gta02_bl_set_intensity, -}; - -static struct platform_device gta02_bl_dev = { - .name = "generic-bl", - .id = 1, - .dev = { - .platform_data = >a02_bl_info, - }, -}; - -/* SPI: LCM control interface attached to Glamo3362 */ - -static void gta02_jbt6k74_reset(int devidx, int level) -{ - gpio_set_value(GTA02_GPIO_GLAMO(4), level); -} - -static int jbt_probed = 0; - -static void gta02_jbt6k74_probe_completed(struct device *dev) -{ - struct pcf50633 *pcf = gta02_pcf; - if (!jbt_probed) { - /* Switch on backlight. Qi does not do it for us */ - pcf50633_reg_write(pcf, PCF50633_REG_LEDOUT, 0x01); - pcf50633_reg_write(pcf, PCF50633_REG_LEDENA, 0x00); - pcf50633_reg_write(pcf, PCF50633_REG_LEDDIM, 0x01); - pcf50633_reg_write(pcf, PCF50633_REG_LEDENA, 0x01); - - gta02_bl_dev.dev.parent = dev; - platform_device_register(>a02_bl_dev); - jbt_probed = 1; - } -} - -const struct jbt6k74_platform_data jbt6k74_pdata = { - .reset = gta02_jbt6k74_reset, - .probe_completed = gta02_jbt6k74_probe_completed, -}; - -/*----------- SPI: Accelerometers attached to SPI of s3c244x ----------------- */ - -void gta02_lis302dl_suspend_io(struct lis302dl_info *lis, int resume) -{ - struct lis302dl_platform_data *pdata = lis->pdata; - - if (!resume) { - /* - * we don't want to power them with a high level - * because GSENSOR_3V3 is not up during suspend - */ - s3c2410_gpio_setpin(pdata->pin_chip_select, 0); - s3c2410_gpio_setpin(pdata->pin_clk, 0); - s3c2410_gpio_setpin(pdata->pin_mosi, 0); - /* misnomer: it is a pullDOWN in 2442 */ - s3c2410_gpio_pullup(pdata->pin_miso, 1); - return; - } - - /* back to normal */ - s3c2410_gpio_setpin(pdata->pin_chip_select, 1); - s3c2410_gpio_setpin(pdata->pin_clk, 1); - /* misnomer: it is a pullDOWN in 2442 */ - s3c2410_gpio_pullup(pdata->pin_miso, 0); - - s3c2410_gpio_cfgpin(pdata->pin_chip_select, S3C2410_GPIO_OUTPUT); - s3c2410_gpio_cfgpin(pdata->pin_clk, S3C2410_GPIO_OUTPUT); - s3c2410_gpio_cfgpin(pdata->pin_mosi, S3C2410_GPIO_OUTPUT); - s3c2410_gpio_cfgpin(pdata->pin_miso, S3C2410_GPIO_INPUT); - -} - -struct lis302dl_platform_data lis302_pdata_top = { - .name = "lis302-1 (top)", - .pin_chip_select= S3C2410_GPD(12), - .pin_clk = S3C2410_GPG(7), - .pin_mosi = S3C2410_GPG(6), - .pin_miso = S3C2410_GPG(5), - .interrupt = GTA02_IRQ_GSENSOR_1, - .open_drain = 1, /* altered at runtime by PCB rev */ - .lis302dl_suspend_io = gta02_lis302dl_suspend_io, -}; - -struct lis302dl_platform_data lis302_pdata_bottom = { - .name = "lis302-2 (bottom)", - .pin_chip_select= S3C2410_GPD(13), - .pin_clk = S3C2410_GPG(7), - .pin_mosi = S3C2410_GPG(6), - .pin_miso = S3C2410_GPG(5), - .interrupt = GTA02_IRQ_GSENSOR_2, - .open_drain = 1, /* altered at runtime by PCB rev */ - .lis302dl_suspend_io = gta02_lis302dl_suspend_io, -}; - -static struct spi_board_info gta02_spi_board_info[] = { - { - .modalias = "jbt6k74", - .platform_data = &jbt6k74_pdata, - .controller_data = (void*)GTA02_GPIO_GLAMO(12), - /* irq */ - .max_speed_hz = 100 * 1000, - .bus_num = 2, - .chip_select = 0 - }, - { - .modalias = "lis302dl", - /* platform_data */ - .platform_data = &lis302_pdata_top, - /* controller_data */ - /* irq */ - .max_speed_hz = 100 * 1000, - .bus_num = 3, - .chip_select = 0, - }, - - { - .modalias = "lis302dl", - /* platform_data */ - .platform_data = &lis302_pdata_bottom, - /* controller_data */ - /* irq */ - .max_speed_hz = 100 * 1000, - .bus_num = 3, - .chip_select = 1, - }, - -}; - -static void gta02_lis302_chip_select(struct s3c2410_spigpio_info *info, int csid, int cs) -{ - - /* - * Huh... "quirk"... CS on this device is not really "CS" like you can - * expect. - * - * When it is 0 it selects SPI interface mode. - * When it is 1 it selects I2C interface mode. - * - * Because we have 2 devices on one interface we have to make sure - * that the "disabled" device (actually in I2C mode) don't think we're - * talking to it. - * - * When we talk to the "enabled" device, the "disabled" device sees - * the clocks as I2C clocks, creating havoc. - * - * I2C sees MOSI going LOW while CLK HIGH as a START action, thus we - * must ensure this is never issued. - */ - - int cs_gpio, other_cs_gpio; - - cs_gpio = csid ? S3C2410_GPD(13) : S3C2410_GPD(12); - other_cs_gpio = csid ? S3C2410_GPD(12) : S3C2410_GPD(13); - - - if (cs == BITBANG_CS_ACTIVE) { - s3c2410_gpio_setpin(other_cs_gpio, 1); - s3c2410_gpio_setpin(cs_gpio, 1); - s3c2410_gpio_setpin(info->pin_clk, 1); - s3c2410_gpio_setpin(cs_gpio, 0); - } else { - s3c2410_gpio_setpin(cs_gpio, 1); - s3c2410_gpio_setpin(other_cs_gpio, 1); - } -} - -static struct s3c2410_spigpio_info gta02_spigpio_cfg = { - .pin_clk = S3C2410_GPG(7), - .pin_mosi = S3C2410_GPG(6), - .pin_miso = S3C2410_GPG(5), - .bus_num = 3, - .num_chipselect = 2, - .chip_select = gta02_lis302_chip_select, -}; - -static struct platform_device gta02_spi_gpio_dev = { - .name = "spi_s3c24xx_gpio", - .dev = { - .platform_data = >a02_spigpio_cfg, - }, -}; - -/*----------- / SPI: Accelerometers attached to SPI of s3c244x ----------------- */ - -static struct gpio_led gta02_gpio_leds[] = { - { - .name = "gta02-power:orange", - .gpio = GTA02_GPIO_PWR_LED1, - }, { - .name = "gta02-power:blue", - .gpio = GTA02_GPIO_PWR_LED2, - }, { - .name = "gta02-aux:red", - .gpio = GTA02_GPIO_AUX_LED, - }, -}; - -static struct gpio_led_platform_data gta02_gpio_leds_pdata = { - .leds = gta02_gpio_leds, - .num_leds = ARRAY_SIZE(gta02_gpio_leds), -}; - -struct platform_device gta02_led_dev = { - .name = "leds-gpio", - .id = -1, - .dev = { - .platform_data = >a02_gpio_leds_pdata, - }, -}; - -static struct gpio_keys_button gta02_buttons[] = { - { - .gpio = GTA02_GPIO_AUX_KEY, - .code = KEY_PHONE, - .desc = "Aux", - .type = EV_KEY, - .debounce_interval = 100, - }, - { - .gpio = GTA02_GPIO_HOLD_KEY, - .code = KEY_PAUSE, - .desc = "Hold", - .type = EV_KEY, - .debounce_interval = 100, - }, -}; - -static struct gpio_keys_platform_data gta02_buttons_pdata = { - .buttons = gta02_buttons, - .nbuttons = ARRAY_SIZE(gta02_buttons), -}; - -static struct platform_device gta02_button_dev = { - .name = "gpio-keys", - .id = -1, - .dev = { - .platform_data = >a02_buttons_pdata, - }, -}; - -static struct platform_device gta02_pm_usbhost_dev = { - .name = "gta02-pm-host", -}; - -/* USB */ -static struct s3c2410_hcd_info gta02_usb_info = { - .port[0] = { - .flags = S3C_HCDFLG_USED, - }, - .port[1] = { - .flags = 0, - }, -}; - -/* - * we crank down SD Card clock dynamically when GPS is powered - */ - -static int gta02_glamo_mci_use_slow(void) -{ - return gta02_pm_gps_is_on(); -} - -static void gta02_glamo_external_reset(int level) -{ - s3c2410_gpio_setpin(GTA02_GPIO_3D_RESET, level); - s3c2410_gpio_cfgpin(GTA02_GPIO_3D_RESET, S3C2410_GPIO_OUTPUT); -} - -/* -static struct fb_videomode gta02_glamo_modes[] = { - { - .name = "480x640", - .xres = 480, - .yres = 640, - .pixclock = 40816, - .left_margin = 8, - .right_margin = 63, - .upper_margin = 2, - .lower_margin = 4, - .hsync_len = 8, - .vsync_len = 2, - .vmode = FB_VMODE_NONINTERLACED, - }, { - .name = "240x320", - .xres = 240, - .yres = 320, - .pixclock = 40816, - .left_margin = 8, - .right_margin = 88, - .upper_margin = 2, - .lower_margin = 2, - .hsync_len = 8, - .vsync_len = 2, - .vmode = FB_VMODE_NONINTERLACED, - } -};*/ - -struct spi_gpio_platform_data spigpio_platform_data = { - .sck = GTA02_GPIO_GLAMO(10), - .mosi = GTA02_GPIO_GLAMO(11), - .miso = GTA02_GPIO_GLAMO(5), - .num_chipselect = 1, -}; - -static struct platform_device spigpio_device = { - .name = "spi_gpio", - .id = 2, - .dev = { - .platform_data = &spigpio_platform_data, - }, -}; - -static void gta02_glamo_registered(struct device *dev) -{ - if (gpio_request(GTA02_GPIO_GLAMO(4), "jbt6k74 reset")) - printk("gta02: Failed to request jbt6k74 reset pin\n"); - if (gpio_direction_output(GTA02_GPIO_GLAMO(4), 1)) - printk("gta02: Failed to configure jbt6k74 reset pin\n"); - spigpio_device.dev.parent = dev; - platform_device_register(&spigpio_device); -} - -static struct fb_videomode gta02_glamo_modes[] = { - { - .name = "480x640", - .xres = 480, - .yres = 640, - .pixclock = 40816, - .left_margin = 8, - .right_margin = 16, - .upper_margin = 2, - .lower_margin = 16, - .hsync_len = 8, - .vsync_len = 2, - .vmode = FB_VMODE_NONINTERLACED, - }, { - .name = "240x320", - .xres = 240, - .yres = 320, - .pixclock = 40816, - .left_margin = 8, - .right_margin = 16, - .upper_margin = 2, - .lower_margin = 16, - .hsync_len = 8, - .vsync_len = 2, - .vmode = FB_VMODE_NONINTERLACED, - } -}; - - -static struct glamo_fb_platform_data gta02_glamo_fb_pdata = { - .width = 43, - .height = 58, - - .num_modes = ARRAY_SIZE(gta02_glamo_modes), - .modes = gta02_glamo_modes, -}; - -static struct glamo_mmc_platform_data gta02_glamo_mmc_pdata = { - .glamo_mmc_use_slow = gta02_glamo_mci_use_slow, -}; - -static struct glamo_platform_data gta02_glamo_pdata = { - .fb_data = >a02_glamo_fb_pdata, - .mmc_data = >a02_glamo_mmc_pdata, - .gpio_base = GTA02_GPIO_GLAMO_BASE, - - .osci_clock_rate = 32768, - - .glamo_external_reset = gta02_glamo_external_reset, - .registered = gta02_glamo_registered, -}; - -static struct resource gta02_glamo_resources[] = { - [0] = { - .start = S3C2410_CS1, - .end = S3C2410_CS1 + 0x1000000 - 1, - .flags = IORESOURCE_MEM, - }, - [1] = { - .start = GTA02_IRQ_3D, - .end = GTA02_IRQ_3D, - .flags = IORESOURCE_IRQ, - }, - [2] = { - .start = GTA02_GPIO_3D_RESET, - .end = GTA02_GPIO_3D_RESET, - }, -}; - -static struct platform_device gta02_glamo_dev = { - .name = "glamo3362", - .num_resources = ARRAY_SIZE(gta02_glamo_resources), - .resource = gta02_glamo_resources, - .dev = { - .platform_data = >a02_glamo_pdata, - }, -}; - -static void __init gta02_map_io(void) -{ - s3c24xx_init_io(gta02_iodesc, ARRAY_SIZE(gta02_iodesc)); - s3c24xx_init_clocks(12000000); - s3c24xx_init_uarts(gta02_uartcfgs, ARRAY_SIZE(gta02_uartcfgs)); -} - -static irqreturn_t gta02_modem_irq(int irq, void *param) -{ -/* printk(KERN_DEBUG "modem wakeup interrupt\n");*/ - gta_gsm_interrupts++; - return IRQ_HANDLED; -} - -static irqreturn_t ar6000_wow_irq(int irq, void *param) -{ -/* printk(KERN_DEBUG "ar6000_wow interrupt\n");*/ - return IRQ_HANDLED; -} - -/* - * hardware_ecc=1|0 - */ -static char hardware_ecc_str[4] __initdata = ""; - -static int __init hardware_ecc_setup(char *str) -{ - if (str) - strlcpy(hardware_ecc_str, str, sizeof(hardware_ecc_str)); - return 1; -} - -__setup("hardware_ecc=", hardware_ecc_setup); - -/* these are the guys that don't need to be children of PMU */ - -static struct platform_device *gta02_devices[] __initdata = { - &s3c_device_i2c0, - &s3c_device_usb, - &s3c_device_wdt, - &s3c_device_sdi, - &s3c_device_usbgadget, - &s3c_device_nand, - >a02_nor_flash, - - &s3c24xx_pwm_device, - >a02_led_dev, - >a02_pm_wlan_dev, /* not dependent on PMU */ - &s3c_device_iis, -}; - -/* these guys DO need to be children of PMU */ - -static struct platform_device *gta02_devices_pmu_children[] = { - &s3c_device_ts, /* input 1 */ - >a02_pm_gsm_dev, - >a02_pm_usbhost_dev, - >a02_spi_gpio_dev, /* input 2 and 3 */ - >a02_button_dev, /* input 4 */ - >a02_resume_reason_device, -}; - -static void gta02_register_glamo(void) -{ - platform_device_register(>a02_glamo_dev); -} - -static void gta02_pmu_regulator_registered(struct pcf50633 *pcf, int id) -{ - struct platform_device *regulator, *pdev; - - gta02_pcf = pcf; - - regulator = pcf->regulator_pdev[id]; - - switch(id) { - case PCF50633_REGULATOR_LDO4: - pdev = >a02_pm_bt_dev; - break; - case PCF50633_REGULATOR_LDO5: - pdev = >a02_pm_gps_dev; - break; - case PCF50633_REGULATOR_HCLDO: - gta02_register_glamo(); - return; - default: - return; - } - - pdev->dev.parent = ®ulator->dev; - platform_device_register(pdev); -} - -/* this is called when pc50633 is probed, unfortunately quite late in the - * day since it is an I2C bus device. Here we can belatedly define some - * platform devices with the advantage that we can mark the pcf50633 as the - * parent. This makes them get suspended and resumed with their parent - * the pcf50633 still around. - */ - -static void gta02_pmu_attach_child_devices(struct pcf50633 *pcf) -{ - int n; - - for (n = 0; n < ARRAY_SIZE(gta02_devices_pmu_children); n++) - gta02_devices_pmu_children[n]->dev.parent = pcf->dev; - - platform_add_devices(gta02_devices_pmu_children, - ARRAY_SIZE(gta02_devices_pmu_children)); - - regulator_has_full_constraints(); -} - -static void gta02_poweroff(void) -{ - pcf50633_reg_set_bit_mask(gta02_pcf, PCF50633_REG_OOCSHDWN, - PCF50633_OOCSHDWN_GOSTDBY, PCF50633_OOCSHDWN_GOSTDBY); -} - - -/* On hardware rev 5 and earlier the leds are missing a resistor and reading - * from their gpio pins will always return 0, so we have to shadow the - * led states software */ -static unsigned long gpb_shadow; -extern struct s3c_gpio_chip s3c24xx_gpios[]; - -static void gta02_gpb_set(struct gpio_chip *chip, - unsigned offset, int value) -{ - void __iomem *base = S3C24XX_GPIO_BASE(S3C2410_GPB(0)); - unsigned long flags; - unsigned long dat; - - local_irq_save(flags); - - dat = __raw_readl(base + 0x04) | gpb_shadow; - dat &= ~(1 << offset); - gpb_shadow &= ~(1 << offset); - if (value) { - dat |= 1 << offset; - switch (offset) { - case 0 ... 2: - gpb_shadow |= 1 << offset; - break; - default: - break; - } - } - __raw_writel(dat, base + 0x04); - - local_irq_restore(flags); -} - -static int gta02_gpb_get(struct gpio_chip *chip, unsigned offset) -{ - void __iomem *base = S3C24XX_GPIO_BASE(S3C2410_GPB(0)); - unsigned long val; - - val = __raw_readl(base + 0x04) | gpb_shadow; - val >>= offset; - val &= 1; - - return val; -} - -static void gta02_hijack_gpb(void) { - s3c24xx_gpios[1].chip.set = gta02_gpb_set; - s3c24xx_gpios[1].chip.get = gta02_gpb_get; -} - -static void __init gta02_machine_init(void) -{ - int rc; - - /* set the panic callback to make AUX blink fast */ - panic_blink = gta02_panic_blink; - - switch (S3C_SYSTEM_REV_ATAG) { - case GTA02v6_SYSTEM_REV: - /* we need push-pull interrupt from motion sensors */ - lis302_pdata_top.open_drain = 0; - lis302_pdata_bottom.open_drain = 0; - break; - default: - break; - } - if (S3C_SYSTEM_REV_ATAG <= GTA02v5_SYSTEM_REV) - gta02_hijack_gpb(); - -#ifdef CONFIG_CHARGER_PCF50633 - INIT_DELAYED_WORK(>a02_charger_work, gta02_charger_worker); -#endif - - /* Glamo chip select optimization */ -/* *((u32 *)(S3C2410_MEMREG(((1 + 1) << 2)))) = 0x1280; */ - - /* do not force soft ecc if we are asked to use hardware_ecc */ - if (hardware_ecc_str[0] == '1') - gta02_nand_info.software_ecc = 0; - - s3c_device_usb.dev.platform_data = >a02_usb_info; - s3c_device_nand.dev.platform_data = >a02_nand_info; - s3c_device_sdi.dev.platform_data = >a02_s3c_mmc_cfg; - - /* acc sensor chip selects */ - s3c2410_gpio_setpin(S3C2410_GPD(12), 1); - s3c2410_gpio_cfgpin(S3C2410_GPD(12), S3C2410_GPIO_OUTPUT); - s3c2410_gpio_setpin(S3C2410_GPD(13), 1); - s3c2410_gpio_cfgpin(S3C2410_GPD(13), S3C2410_GPIO_OUTPUT); - - - s3c24xx_udc_set_platdata(>a02_udc_cfg); - s3c_i2c0_set_platdata(NULL); - set_s3c2410ts_info(>a02_ts_cfg); - - i2c_register_board_info(0, gta02_i2c_devs, ARRAY_SIZE(gta02_i2c_devs)); - spi_register_board_info(gta02_spi_board_info, - ARRAY_SIZE(gta02_spi_board_info)); - - platform_add_devices(gta02_devices, ARRAY_SIZE(gta02_devices)); - - s3c_pm_init(); - - /* Make sure the modem can wake us up */ - set_irq_type(GTA02_IRQ_MODEM, IRQ_TYPE_EDGE_RISING); - rc = request_irq(GTA02_IRQ_MODEM, gta02_modem_irq, IRQF_DISABLED, - "modem", NULL); - if (rc < 0) - printk(KERN_ERR "GTA02: can't request GSM modem wakeup IRQ\n"); - enable_irq_wake(GTA02_IRQ_MODEM); - - /* Make sure the wifi module can wake us up*/ - set_irq_type(GTA02_IRQ_WLAN_GPIO1, IRQ_TYPE_EDGE_RISING); - rc = request_irq(GTA02_IRQ_WLAN_GPIO1, ar6000_wow_irq, IRQF_DISABLED, - "ar6000", NULL); - - if (rc < 0) - printk(KERN_ERR "GTA02: can't request ar6k wakeup IRQ\n"); - enable_irq_wake(GTA02_IRQ_WLAN_GPIO1); - - pm_power_off = gta02_poweroff; - - /* Register the HDQ and vibrator as children of pwm device */ -#ifdef CONFIG_HDQ_GPIO_BITBANG - gta02_hdq_device.dev.parent = &s3c24xx_pwm_device.dev; - platform_device_register(>a02_hdq_device); -#endif - gta02_vibrator_dev.dev.parent = &s3c24xx_pwm_device.dev; - platform_device_register(>a02_vibrator_dev); -} - -MACHINE_START(NEO1973_GTA02, "GTA02") - .phys_io = S3C2410_PA_UART, - .io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc, - .boot_params = S3C2410_SDRAM_PA + 0x100, - .map_io = gta02_map_io, - .init_irq = s3c24xx_init_irq, - .init_machine = gta02_machine_init, - .timer = &s3c24xx_timer, -MACHINE_END diff --git a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/Kconfig b/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/Kconfig deleted file mode 100644 index a422cb0ee..000000000 --- a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/Kconfig +++ /dev/null @@ -1,31 +0,0 @@ -config AR6000_WLAN - tristate "AR6000 wireless networking over SDIO" - depends on MMC - select WIRELESS_EXT - default m - help - good luck. - -config AR6000_WLAN_DEBUG - bool "Enable retrieval of firmware debugging information" - depends on AR6000_WLAN - default n - help - The AR6k firmware maintains a log of debugging events that - gets flushed to the host on various occasions. Retrieval of - this data is very slow, taking several seconds. - - If in doubt, say N. - -config AR6000_WLAN_RESET - bool "Soft-reset when shutting down" - depends on AR6000_WLAN - default n - help - The AR6k module can be explicitly reset when shutting down - the device. This adds a delay of about two seconds to suspend, - module removal, and so on. Since the WLAN SDIO function is - generally disabled soon thereafter anyway, this reset seems - superfluous. - - If in doubt, say N. diff --git a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/Makefile b/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/Makefile deleted file mode 100644 index f8f443172..000000000 --- a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/Makefile +++ /dev/null @@ -1,38 +0,0 @@ -REV ?= 2 - -PWD := $(shell pwd) - -EXTRA_CFLAGS += -I$(src)/include - -EXTRA_CFLAGS += -DLINUX -D__KERNEL__ -DHTC_RAW_INTERFACE\ - -DTCMD -DUSER_KEYS \ - -DNO_SYNC_FLUSH #\ - -DMULTIPLE_FRAMES_PER_INTERRUPT -DAR6000REV$(REV) \ - -DBLOCK_TX_PATH_FLAG \ - -DSDIO \ - -EXTRA_CFLAGS += -DKERNEL_2_6 - -obj-$(CONFIG_AR6000_WLAN) += ar6000.o - -ar6000-objs += htc/ar6k.o \ - htc/ar6k_events.o \ - htc/htc_send.o \ - htc/htc_recv.o \ - htc/htc_services.o \ - htc/htc.o \ - hif/hif2.o \ - bmi/bmi.o \ - ar6000/ar6000_drv.o \ - ar6000/ar6000_raw_if.o \ - ar6000/netbuf.o \ - ar6000/wireless_ext.o \ - ar6000/ioctl.o \ - miscdrv/common_drv.o \ - miscdrv/credit_dist.o \ - wmi/wmi.o \ - wlan/wlan_node.o \ - wlan/wlan_recv_beacon.o \ - wlan/wlan_utils.o - - diff --git a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/ar6000/ar6000_drv.c b/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/ar6000/ar6000_drv.c deleted file mode 100644 index 90533ab96..000000000 --- a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/ar6000/ar6000_drv.c +++ /dev/null @@ -1,3129 +0,0 @@ -/* - * - * Copyright (c) 2004-2007 Atheros Communications Inc. - * All rights reserved. - * - * - * 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; - * - * Software distributed under the License is distributed on an "AS - * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or - * implied. See the License for the specific language governing - * rights and limitations under the License. - * - * - * - */ - -/* - * This driver is a pseudo ethernet driver to access the Atheros AR6000 - * WLAN Device - */ -static const char athId[] __attribute__ ((unused)) = "$Id: //depot/sw/releases/olca2.0-GPL/host/os/linux/ar6000_drv.c#2 $"; - -#include "ar6000_drv.h" -#include "htc.h" - -MODULE_LICENSE("GPL and additional rights"); - -#ifndef REORG_APTC_HEURISTICS -#undef ADAPTIVE_POWER_THROUGHPUT_CONTROL -#endif /* REORG_APTC_HEURISTICS */ - -#ifdef ADAPTIVE_POWER_THROUGHPUT_CONTROL -#define APTC_TRAFFIC_SAMPLING_INTERVAL 100 /* msec */ -#define APTC_UPPER_THROUGHPUT_THRESHOLD 3000 /* Kbps */ -#define APTC_LOWER_THROUGHPUT_THRESHOLD 2000 /* Kbps */ - -typedef struct aptc_traffic_record { - A_BOOL timerScheduled; - struct timeval samplingTS; - unsigned long bytesReceived; - unsigned long bytesTransmitted; -} APTC_TRAFFIC_RECORD; - -A_TIMER aptcTimer; -APTC_TRAFFIC_RECORD aptcTR; -#endif /* ADAPTIVE_POWER_THROUGHPUT_CONTROL */ - -unsigned int bypasswmi = 0; -unsigned int debuglevel = 0; -int tspecCompliance = 1; -unsigned int busspeedlow = 0; -unsigned int onebitmode = 0; -unsigned int skipflash = 0; -unsigned int wmitimeout = 2; -unsigned int wlanNodeCaching = 1; -unsigned int enableuartprint = 0; -unsigned int logWmiRawMsgs = 0; -unsigned int enabletimerwar = 0; -unsigned int mbox_yield_limit = 99; -int reduce_credit_dribble = 1 + HTC_CONNECT_FLAGS_THRESHOLD_LEVEL_ONE_HALF; -int allow_trace_signal = 0; -#ifdef CONFIG_HOST_TCMD_SUPPORT -unsigned int testmode =0; -#endif - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) -module_param(bypasswmi, int, 0644); -module_param(debuglevel, int, 0644); -module_param(tspecCompliance, int, 0644); -module_param(onebitmode, int, 0644); -module_param(busspeedlow, int, 0644); -module_param(skipflash, int, 0644); -module_param(wmitimeout, int, 0644); -module_param(wlanNodeCaching, int, 0644); -module_param(logWmiRawMsgs, int, 0644); -module_param(enableuartprint, int, 0644); -module_param(enabletimerwar, int, 0644); -module_param(mbox_yield_limit, int, 0644); -module_param(reduce_credit_dribble, int, 0644); -module_param(allow_trace_signal, int, 0644); -#ifdef CONFIG_HOST_TCMD_SUPPORT -module_param(testmode, int, 0644); -#endif -#else - -#define __user -/* for linux 2.4 and lower */ -MODULE_PARM(bypasswmi,"i"); -MODULE_PARM(debuglevel, "i"); -MODULE_PARM(onebitmode,"i"); -MODULE_PARM(busspeedlow, "i"); -MODULE_PARM(skipflash, "i"); -MODULE_PARM(wmitimeout, "i"); -MODULE_PARM(wlanNodeCaching, "i"); -MODULE_PARM(enableuartprint,"i"); -MODULE_PARM(logWmiRawMsgs, "i"); -MODULE_PARM(enabletimerwar,"i"); -MODULE_PARM(mbox_yield_limit,"i"); -MODULE_PARM(reduce_credit_dribble,"i"); -MODULE_PARM(allow_trace_signal,"i"); -#ifdef CONFIG_HOST_TCMD_SUPPORT -MODULE_PARM(testmode, "i"); -#endif -#endif - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,10) -/* in 2.6.10 and later this is now a pointer to a uint */ -unsigned int _mboxnum = HTC_MAILBOX_NUM_MAX; -#define mboxnum &_mboxnum -#else -unsigned int mboxnum = HTC_MAILBOX_NUM_MAX; -#endif - -#ifdef CONFIG_AR6000_WLAN_RESET -unsigned int resetok = 1; -#else -unsigned int resetok = 0; -#endif - -#ifdef DEBUG -A_UINT32 g_dbg_flags = DBG_DEFAULTS; -unsigned int debugflags = 0; -int debugdriver = 1; -unsigned int debughtc = 128; -unsigned int debugbmi = 1; -unsigned int debughif = 2; -unsigned int txcreditsavailable[HTC_MAILBOX_NUM_MAX] = {0}; -unsigned int txcreditsconsumed[HTC_MAILBOX_NUM_MAX] = {0}; -unsigned int txcreditintrenable[HTC_MAILBOX_NUM_MAX] = {0}; -unsigned int txcreditintrenableaggregate[HTC_MAILBOX_NUM_MAX] = {0}; - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) -module_param(debugflags, int, 0644); -module_param(debugdriver, int, 0644); -module_param(debughtc, int, 0644); -module_param(debugbmi, int, 0644); -module_param(debughif, int, 0644); -module_param(resetok, int, 0644); -module_param_array(txcreditsavailable, int, mboxnum, 0644); -module_param_array(txcreditsconsumed, int, mboxnum, 0644); -module_param_array(txcreditintrenable, int, mboxnum, 0644); -module_param_array(txcreditintrenableaggregate, int, mboxnum, 0644); -#else -/* linux 2.4 and lower */ -MODULE_PARM(debugflags,"i"); -MODULE_PARM(debugdriver, "i"); -MODULE_PARM(debughtc, "i"); -MODULE_PARM(debugbmi, "i"); -MODULE_PARM(debughif, "i"); -MODULE_PARM(resetok, "i"); -MODULE_PARM(txcreditsavailable, "0-3i"); -MODULE_PARM(txcreditsconsumed, "0-3i"); -MODULE_PARM(txcreditintrenable, "0-3i"); -MODULE_PARM(txcreditintrenableaggregate, "0-3i"); -#endif - -#endif /* DEBUG */ - -unsigned int tx_attempt[HTC_MAILBOX_NUM_MAX] = {0}; -unsigned int tx_post[HTC_MAILBOX_NUM_MAX] = {0}; -unsigned int tx_complete[HTC_MAILBOX_NUM_MAX] = {0}; -unsigned int hifBusRequestNumMax = 40; -unsigned int war23838_disabled = 0; -#ifdef ADAPTIVE_POWER_THROUGHPUT_CONTROL -unsigned int enableAPTCHeuristics = 1; -#endif /* ADAPTIVE_POWER_THROUGHPUT_CONTROL */ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) -module_param_array(tx_attempt, int, mboxnum, 0644); -module_param_array(tx_post, int, mboxnum, 0644); -module_param_array(tx_complete, int, mboxnum, 0644); -module_param(hifBusRequestNumMax, int, 0644); -module_param(war23838_disabled, int, 0644); -#ifdef ADAPTIVE_POWER_THROUGHPUT_CONTROL -module_param(enableAPTCHeuristics, int, 0644); -#endif /* ADAPTIVE_POWER_THROUGHPUT_CONTROL */ -#else -MODULE_PARM(tx_attempt, "0-3i"); -MODULE_PARM(tx_post, "0-3i"); -MODULE_PARM(tx_complete, "0-3i"); -MODULE_PARM(hifBusRequestNumMax, "i"); -MODULE_PARM(war23838_disabled, "i"); -#ifdef ADAPTIVE_POWER_THROUGHPUT_CONTROL -MODULE_PARM(enableAPTCHeuristics, "i"); -#endif /* ADAPTIVE_POWER_THROUGHPUT_CONTROL */ -#endif - -#ifdef BLOCK_TX_PATH_FLAG -int blocktx = 0; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) -module_param(blocktx, int, 0644); -#else -MODULE_PARM(blocktx, "i"); -#endif -#endif /* BLOCK_TX_PATH_FLAG */ - -// TODO move to arsoft_c -USER_RSSI_THOLD rssi_map[12]; - -int reconnect_flag = 0; - -DECLARE_WAIT_QUEUE_HEAD(ar6000_scan_queue); - -/* Function declarations */ -static int ar6000_init_module(void); -static void ar6000_cleanup_module(void); - -int ar6000_init(struct net_device *dev); -static int ar6000_open(struct net_device *dev); -static int ar6000_close(struct net_device *dev); -static int ar6000_cleanup(struct net_device *dev); -static void ar6000_init_control_info(AR_SOFTC_T *ar); -static int ar6000_data_tx(struct sk_buff *skb, struct net_device *dev); - -static void ar6000_destroy(struct net_device *dev, unsigned int unregister); -static void ar6000_detect_error(unsigned long ptr); -static struct net_device_stats *ar6000_get_stats(struct net_device *dev); -static struct iw_statistics *ar6000_get_iwstats(struct net_device * dev); - -/* - * HTC service connection handlers - */ -static void ar6000_avail_ev(HTC_HANDLE HTCHandle); - -static void ar6000_unavail_ev(void *Instance); - -static void ar6000_target_failure(void *Instance, A_STATUS Status); - -static void ar6000_rx(void *Context, HTC_PACKET *pPacket); - -static void ar6000_rx_refill(void *Context,HTC_ENDPOINT_ID Endpoint); - -static void ar6000_tx_complete(void *Context, HTC_PACKET *pPacket); - -static void ar6000_tx_queue_full(void *Context, HTC_ENDPOINT_ID Endpoint); - -static void ar6000_tx_queue_avail(void *Context, HTC_ENDPOINT_ID Endpoint); - -/* - * Static variables - */ - -static struct net_device *ar6000_devices[MAX_AR6000]; -extern struct iw_handler_def ath_iw_handler_def; -DECLARE_WAIT_QUEUE_HEAD(arEvent); -static void ar6000_cookie_init(AR_SOFTC_T *ar); -static void ar6000_cookie_cleanup(AR_SOFTC_T *ar); -static void ar6000_free_cookie(AR_SOFTC_T *ar, struct ar_cookie * cookie); -static struct ar_cookie *ar6000_alloc_cookie(AR_SOFTC_T *ar); -static void ar6000_TxDataCleanup(AR_SOFTC_T *ar); - -#ifdef USER_KEYS -static A_STATUS ar6000_reinstall_keys(AR_SOFTC_T *ar,A_UINT8 key_op_ctrl); -#endif - - -static struct ar_cookie s_ar_cookie_mem[MAX_COOKIE_NUM]; - -#define HOST_INTEREST_ITEM_ADDRESS(ar, item) \ -((ar->arTargetType == TARGET_TYPE_AR6001) ? \ - AR6001_HOST_INTEREST_ITEM_ADDRESS(item) : \ - AR6002_HOST_INTEREST_ITEM_ADDRESS(item)) - - -/* Debug log support */ - -/* - * Flag to govern whether the debug logs should be parsed in the kernel - * or reported to the application. - */ -#ifdef DEBUG -#define REPORT_DEBUG_LOGS_TO_APP -#endif - -A_STATUS -ar6000_set_host_app_area(AR_SOFTC_T *ar) -{ - A_UINT32 address, data; - struct host_app_area_s host_app_area; - - /* Fetch the address of the host_app_area_s instance in the host interest area */ - address = HOST_INTEREST_ITEM_ADDRESS(ar, hi_app_host_interest); - if (ar6000_ReadRegDiag(ar->arHifDevice, &address, &data) != A_OK) { - return A_ERROR; - } - address = data; - host_app_area.wmi_protocol_ver = WMI_PROTOCOL_VERSION; - if (ar6000_WriteDataDiag(ar->arHifDevice, address, - (A_UCHAR *)&host_app_area, - sizeof(struct host_app_area_s)) != A_OK) - { - return A_ERROR; - } - - return A_OK; -} - -A_UINT32 -dbglog_get_debug_hdr_ptr(AR_SOFTC_T *ar) -{ - A_UINT32 param; - A_UINT32 address; - A_STATUS status; - - address = HOST_INTEREST_ITEM_ADDRESS(ar, hi_dbglog_hdr); - if ((status = ar6000_ReadDataDiag(ar->arHifDevice, address, - (A_UCHAR *)¶m, 4)) != A_OK) - { - param = 0; - } - - return param; -} - -/* - * The dbglog module has been initialized. Its ok to access the relevant - * data stuctures over the diagnostic window. - */ -void -ar6000_dbglog_init_done(AR_SOFTC_T *ar) -{ - ar->dbglog_init_done = TRUE; -} - -A_UINT32 -dbglog_get_debug_fragment(A_INT8 *datap, A_UINT32 len, A_UINT32 limit) -{ - A_INT32 *buffer; - A_UINT32 count; - A_UINT32 numargs; - A_UINT32 length; - A_UINT32 fraglen; - - count = fraglen = 0; - buffer = (A_INT32 *)datap; - length = (limit >> 2); - - if (len <= limit) { - fraglen = len; - } else { - while (count < length) { - numargs = DBGLOG_GET_NUMARGS(buffer[count]); - fraglen = (count << 2); - count += numargs + 1; - } - } - - return fraglen; -} - -void -dbglog_parse_debug_logs(A_INT8 *datap, A_UINT32 len) -{ - A_INT32 *buffer; - A_UINT32 count; - A_UINT32 timestamp; - A_UINT32 debugid; - A_UINT32 moduleid; - A_UINT32 numargs; - A_UINT32 length; - - count = 0; - buffer = (A_INT32 *)datap; - length = (len >> 2); - while (count < length) { - debugid = DBGLOG_GET_DBGID(buffer[count]); - moduleid = DBGLOG_GET_MODULEID(buffer[count]); - numargs = DBGLOG_GET_NUMARGS(buffer[count]); - timestamp = DBGLOG_GET_TIMESTAMP(buffer[count]); - switch (numargs) { - case 0: - AR_DEBUG_PRINTF("%d %d (%d)\n", moduleid, debugid, timestamp); - break; - - case 1: - AR_DEBUG_PRINTF("%d %d (%d): 0x%x\n", moduleid, debugid, - timestamp, buffer[count+1]); - break; - - case 2: - AR_DEBUG_PRINTF("%d %d (%d): 0x%x, 0x%x\n", moduleid, debugid, - timestamp, buffer[count+1], buffer[count+2]); - break; - - default: - AR_DEBUG_PRINTF("Invalid args: %d\n", numargs); - } - count += numargs + 1; - } -} - -int -ar6000_dbglog_get_debug_logs(AR_SOFTC_T *ar) -{ - struct dbglog_hdr_s debug_hdr; - struct dbglog_buf_s debug_buf; - A_UINT32 address; - A_UINT32 length; - A_UINT32 dropped; - A_UINT32 firstbuf; - A_UINT32 debug_hdr_ptr; - - if (!ar->dbglog_init_done) return A_ERROR; - -#ifndef CONFIG_AR6000_WLAN_DEBUG - return 0; -#endif - - AR6000_SPIN_LOCK(&ar->arLock, 0); - - if (ar->dbgLogFetchInProgress) { - AR6000_SPIN_UNLOCK(&ar->arLock, 0); - return A_EBUSY; - } - - /* block out others */ - ar->dbgLogFetchInProgress = TRUE; - - AR6000_SPIN_UNLOCK(&ar->arLock, 0); - - debug_hdr_ptr = dbglog_get_debug_hdr_ptr(ar); - printk("debug_hdr_ptr: 0x%x\n", debug_hdr_ptr); - - /* Get the contents of the ring buffer */ - if (debug_hdr_ptr) { - address = debug_hdr_ptr; - length = sizeof(struct dbglog_hdr_s); - ar6000_ReadDataDiag(ar->arHifDevice, address, - (A_UCHAR *)&debug_hdr, length); - address = (A_UINT32)debug_hdr.dbuf; - firstbuf = address; - dropped = debug_hdr.dropped; - length = sizeof(struct dbglog_buf_s); - ar6000_ReadDataDiag(ar->arHifDevice, address, - (A_UCHAR *)&debug_buf, length); - - do { - address = (A_UINT32)debug_buf.buffer; - length = debug_buf.length; - if ((length) && (debug_buf.length <= debug_buf.bufsize)) { - /* Rewind the index if it is about to overrun the buffer */ - if (ar->log_cnt > (DBGLOG_HOST_LOG_BUFFER_SIZE - length)) { - ar->log_cnt = 0; - } - if(A_OK != ar6000_ReadDataDiag(ar->arHifDevice, address, - (A_UCHAR *)&ar->log_buffer[ar->log_cnt], length)) - { - break; - } - ar6000_dbglog_event(ar, dropped, &ar->log_buffer[ar->log_cnt], length); - ar->log_cnt += length; - } else { - AR_DEBUG_PRINTF("Length: %d (Total size: %d)\n", - debug_buf.length, debug_buf.bufsize); - } - - address = (A_UINT32)debug_buf.next; - length = sizeof(struct dbglog_buf_s); - if(A_OK != ar6000_ReadDataDiag(ar->arHifDevice, address, - (A_UCHAR *)&debug_buf, length)) - { - break; - } - - } while (address != firstbuf); - } - - ar->dbgLogFetchInProgress = FALSE; - - return A_OK; -} - -void -ar6000_dbglog_event(AR_SOFTC_T *ar, A_UINT32 dropped, - A_INT8 *buffer, A_UINT32 length) -{ -#ifdef REPORT_DEBUG_LOGS_TO_APP - #define MAX_WIRELESS_EVENT_SIZE 252 - /* - * Break it up into chunks of MAX_WIRELESS_EVENT_SIZE bytes of messages. - * There seems to be a limitation on the length of message that could be - * transmitted to the user app via this mechanism. - */ - A_UINT32 send, sent; - - sent = 0; - send = dbglog_get_debug_fragment(&buffer[sent], length - sent, - MAX_WIRELESS_EVENT_SIZE); - while (send) { - ar6000_send_event_to_app(ar, WMIX_DBGLOG_EVENTID, &buffer[sent], send); - sent += send; - send = dbglog_get_debug_fragment(&buffer[sent], length - sent, - MAX_WIRELESS_EVENT_SIZE); - } -#else - AR_DEBUG_PRINTF("Dropped logs: 0x%x\nDebug info length: %d\n", - dropped, length); - - /* Interpret the debug logs */ - dbglog_parse_debug_logs(buffer, length); -#endif /* REPORT_DEBUG_LOGS_TO_APP */ -} - - - -static int __init -ar6000_init_module(void) -{ - static int probed = 0; - A_STATUS status; - HTC_INIT_INFO initInfo; - - A_MEMZERO(&initInfo,sizeof(initInfo)); - initInfo.AddInstance = ar6000_avail_ev; - initInfo.DeleteInstance = ar6000_unavail_ev; - initInfo.TargetFailure = ar6000_target_failure; - - -#ifdef DEBUG - /* Set the debug flags if specified at load time */ - if(debugflags != 0) - { - g_dbg_flags = debugflags; - } -#endif - - if (probed) { - return -ENODEV; - } - probed++; - -#ifdef ADAPTIVE_POWER_THROUGHPUT_CONTROL - memset(&aptcTR, 0, sizeof(APTC_TRAFFIC_RECORD)); -#endif /* ADAPTIVE_POWER_THROUGHPUT_CONTROL */ - -#ifdef CONFIG_HOST_GPIO_SUPPORT - ar6000_gpio_init(); -#endif /* CONFIG_HOST_GPIO_SUPPORT */ - - status = HTCInit(&initInfo); - if(status != A_OK) - return -ENODEV; - - return 0; -} - -static void __exit -ar6000_cleanup_module(void) -{ - int i = 0; - struct net_device *ar6000_netdev; - -#ifdef ADAPTIVE_POWER_THROUGHPUT_CONTROL - /* Delete the Adaptive Power Control timer */ - if (timer_pending(&aptcTimer)) { - del_timer_sync(&aptcTimer); - } -#endif /* ADAPTIVE_POWER_THROUGHPUT_CONTROL */ - - for (i=0; i < MAX_AR6000; i++) { - if (ar6000_devices[i] != NULL) { - ar6000_netdev = ar6000_devices[i]; - ar6000_devices[i] = NULL; - ar6000_destroy(ar6000_netdev, 1); - } - } - - /* shutting down HTC will cause the HIF layer to detach from the - * underlying bus driver which will cause the subsequent deletion of - * all HIF and HTC instances */ - HTCShutDown(); - - AR_DEBUG_PRINTF("ar6000_cleanup: success\n"); -} - -#ifdef ADAPTIVE_POWER_THROUGHPUT_CONTROL -void -aptcTimerHandler(unsigned long arg) -{ - A_UINT32 numbytes; - A_UINT32 throughput; - AR_SOFTC_T *ar; - A_STATUS status; - - ar = (AR_SOFTC_T *)arg; - A_ASSERT(ar != NULL); - A_ASSERT(!timer_pending(&aptcTimer)); - - AR6000_SPIN_LOCK(&ar->arLock, 0); - - /* Get the number of bytes transferred */ - numbytes = aptcTR.bytesTransmitted + aptcTR.bytesReceived; - aptcTR.bytesTransmitted = aptcTR.bytesReceived = 0; - - /* Calculate and decide based on throughput thresholds */ - throughput = ((numbytes * 8)/APTC_TRAFFIC_SAMPLING_INTERVAL); /* Kbps */ - if (throughput < APTC_LOWER_THROUGHPUT_THRESHOLD) { - /* Enable Sleep and delete the timer */ - A_ASSERT(ar->arWmiReady == TRUE); - AR6000_SPIN_UNLOCK(&ar->arLock, 0); - status = wmi_powermode_cmd(ar->arWmi, REC_POWER); - AR6000_SPIN_LOCK(&ar->arLock, 0); - A_ASSERT(status == A_OK); - aptcTR.timerScheduled = FALSE; - } else { - A_TIMEOUT_MS(&aptcTimer, APTC_TRAFFIC_SAMPLING_INTERVAL, 0); - } - - AR6000_SPIN_UNLOCK(&ar->arLock, 0); -} -#endif /* ADAPTIVE_POWER_THROUGHPUT_CONTROL */ - - - -/* set HTC block size, assume BMI is already initialized */ -A_STATUS ar6000_SetHTCBlockSize(AR_SOFTC_T *ar) -{ - A_STATUS status; - A_UINT32 blocksizes[HTC_MAILBOX_NUM_MAX]; - - do { - /* get the block sizes */ - status = HIFConfigureDevice(ar->arHifDevice, HIF_DEVICE_GET_MBOX_BLOCK_SIZE, - blocksizes, sizeof(blocksizes)); - - if (A_FAILED(status)) { - AR_DEBUG_PRINTF("Failed to get block size info from HIF layer...\n"); - break; - } - /* note: we actually get the block size for mailbox 1, for SDIO the block - * size on mailbox 0 is artificially set to 1 */ - /* must be a power of 2 */ - A_ASSERT((blocksizes[1] & (blocksizes[1] - 1)) == 0); - - /* set the host interest area for the block size */ - status = BMIWriteMemory(ar->arHifDevice, - HOST_INTEREST_ITEM_ADDRESS(ar, hi_mbox_io_block_sz), - (A_UCHAR *)&blocksizes[1], - 4); - - if (A_FAILED(status)) { - AR_DEBUG_PRINTF("BMIWriteMemory for IO block size failed \n"); - break; - } - - AR_DEBUG_PRINTF("Block Size Set: %d (target address:0x%X)\n", - blocksizes[1], HOST_INTEREST_ITEM_ADDRESS(ar, hi_mbox_io_block_sz)); - - /* set the host interest area for the mbox ISR yield limit */ - status = BMIWriteMemory(ar->arHifDevice, - HOST_INTEREST_ITEM_ADDRESS(ar, hi_mbox_isr_yield_limit), - (A_UCHAR *)&mbox_yield_limit, - 4); - - if (A_FAILED(status)) { - AR_DEBUG_PRINTF("BMIWriteMemory for yield limit failed \n"); - break; - } - - } while (FALSE); - - return status; -} - -static void free_raw_buffers(AR_SOFTC_T *ar) -{ - int i, j; - - for (i = 0; i != HTC_RAW_STREAM_NUM_MAX; i++) { - for (j = 0; j != RAW_HTC_READ_BUFFERS_NUM; j++) - kfree(ar->raw_htc_read_buffer[i][j]); - for (j = 0; j != RAW_HTC_WRITE_BUFFERS_NUM; j++) - kfree(ar->raw_htc_write_buffer[i][j]); - } -} - -static int alloc_raw_buffers(AR_SOFTC_T *ar) -{ - int i, j; - raw_htc_buffer *b; - - for (i = 0; i != HTC_RAW_STREAM_NUM_MAX; i++) { - for (j = 0; j != RAW_HTC_READ_BUFFERS_NUM; j++) { - b = kzalloc(sizeof(*b), GFP_KERNEL); - if (!b) - return -ENOMEM; - ar->raw_htc_read_buffer[i][j] = b; - } - for (j = 0; j != RAW_HTC_WRITE_BUFFERS_NUM; j++) { - b = kzalloc(sizeof(*b), GFP_KERNEL); - if (!b) - return -ENOMEM; - ar->raw_htc_write_buffer[i][j] = b; - } - } - return 0; -} - -static const struct net_device_ops ar6000_netdev_ops = { - .ndo_init = &ar6000_init, - .ndo_open = &ar6000_open, - .ndo_stop = &ar6000_close, - .ndo_start_xmit = &ar6000_data_tx, - .ndo_get_stats = &ar6000_get_stats, - .ndo_do_ioctl = &ar6000_ioctl, -}; -/* - * HTC Event handlers - */ -static void -ar6000_avail_ev(HTC_HANDLE HTCHandle) -{ - int i; - struct net_device *dev; - AR_SOFTC_T *ar; - int device_index = 0; - - AR_DEBUG_PRINTF("ar6000_available\n"); - - for (i=0; i < MAX_AR6000; i++) { - if (ar6000_devices[i] == NULL) { - break; - } - } - - if (i == MAX_AR6000) { - AR_DEBUG_PRINTF("ar6000_available: max devices reached\n"); - return; - } - - /* Save this. It gives a bit better readability especially since */ - /* we use another local "i" variable below. */ - device_index = i; - - A_ASSERT(HTCHandle != NULL); - - dev = alloc_etherdev(sizeof(AR_SOFTC_T)); - if (dev == NULL) { - AR_DEBUG_PRINTF("ar6000_available: can't alloc etherdev\n"); - return; - } - - ether_setup(dev); - - if (netdev_priv(dev) == NULL) { - printk(KERN_CRIT "ar6000_available: Could not allocate memory\n"); - return; - } - - A_MEMZERO(netdev_priv(dev), sizeof(AR_SOFTC_T)); - - ar = (AR_SOFTC_T *)netdev_priv(dev); - ar->arNetDev = dev; - ar->arHtcTarget = HTCHandle; - ar->arHifDevice = HTCGetHifDevice(HTCHandle); - ar->arWlanState = WLAN_ENABLED; - ar->arRadioSwitch = WLAN_ENABLED; - ar->arDeviceIndex = device_index; - - A_INIT_TIMER(&ar->arHBChallengeResp.timer, ar6000_detect_error, dev); - ar->arHBChallengeResp.seqNum = 0; - ar->arHBChallengeResp.outstanding = FALSE; - ar->arHBChallengeResp.missCnt = 0; - ar->arHBChallengeResp.frequency = AR6000_HB_CHALLENGE_RESP_FREQ_DEFAULT; - ar->arHBChallengeResp.missThres = AR6000_HB_CHALLENGE_RESP_MISS_THRES_DEFAULT; - - ar6000_init_control_info(ar); - init_waitqueue_head(&arEvent); - sema_init(&ar->arSem, 1); - - if (alloc_raw_buffers(ar)) { - free_raw_buffers(ar); - /* - * @@@ Clean up our own mess, but for anything else, cheerfully mimick - * the beautiful error non-handling of the rest of this function. - */ - return; - } - -#ifdef ADAPTIVE_POWER_THROUGHPUT_CONTROL - A_INIT_TIMER(&aptcTimer, aptcTimerHandler, ar); -#endif /* ADAPTIVE_POWER_THROUGHPUT_CONTROL */ - - /* - * If requested, perform some magic which requires no cooperation from - * the Target. It causes the Target to ignore flash and execute to the - * OS from ROM. - * - * This is intended to support recovery from a corrupted flash on Targets - * that support flash. - */ - if (skipflash) - { - ar6000_reset_device_skipflash(ar->arHifDevice); - } - - BMIInit(); - { - struct bmi_target_info targ_info; - - if (BMIGetTargetInfo(ar->arHifDevice, &targ_info) != A_OK) { - return; - } - - ar->arVersion.target_ver = targ_info.target_ver; - ar->arTargetType = targ_info.target_type; - } - - if (enableuartprint) { - A_UINT32 param; - param = 1; - if (BMIWriteMemory(ar->arHifDevice, - HOST_INTEREST_ITEM_ADDRESS(ar, hi_serial_enable), - (A_UCHAR *)¶m, - 4)!= A_OK) - { - AR_DEBUG_PRINTF("BMIWriteMemory for enableuartprint failed \n"); - return ; - } - AR_DEBUG_PRINTF("Serial console prints enabled\n"); - } -#ifdef CONFIG_HOST_TCMD_SUPPORT - if(testmode) { - ar->arTargetMode = AR6000_TCMD_MODE; - }else { - ar->arTargetMode = AR6000_WLAN_MODE; - } -#endif - if (enabletimerwar) { - A_UINT32 param; - - if (BMIReadMemory(ar->arHifDevice, - HOST_INTEREST_ITEM_ADDRESS(ar, hi_option_flag), - (A_UCHAR *)¶m, - 4)!= A_OK) - { - AR_DEBUG_PRINTF("BMIReadMemory for enabletimerwar failed \n"); - return; - } - - param |= HI_OPTION_TIMER_WAR; - - if (BMIWriteMemory(ar->arHifDevice, - HOST_INTEREST_ITEM_ADDRESS(ar, hi_option_flag), - (A_UCHAR *)¶m, - 4) != A_OK) - { - AR_DEBUG_PRINTF("BMIWriteMemory for enabletimerwar failed \n"); - return; - } - AR_DEBUG_PRINTF("Timer WAR enabled\n"); - } - - - /* since BMIInit is called in the driver layer, we have to set the block - * size here for the target */ - - if (A_FAILED(ar6000_SetHTCBlockSize(ar))) { - return; - } - - spin_lock_init(&ar->arLock); - - dev->netdev_ops = &ar6000_netdev_ops; - dev->watchdog_timeo = AR6000_TX_TIMEOUT; - ar6000_ioctl_iwsetup(&ath_iw_handler_def); - dev->wireless_handlers = &ath_iw_handler_def; - ath_iw_handler_def.get_wireless_stats = ar6000_get_iwstats; /*Displayed via proc fs */ - - /* - * We need the OS to provide us with more headroom in order to - * perform dix to 802.3, WMI header encap, and the HTC header - */ - dev->hard_header_len = ETH_HLEN + sizeof(ATH_LLC_SNAP_HDR) + - sizeof(WMI_DATA_HDR) + HTC_HEADER_LEN; - - /* This runs the init function */ - SET_NETDEV_DEV(dev, HIFGetOSDevice(ar->arHifDevice)); - if (register_netdev(dev)) { - AR_DEBUG_PRINTF("ar6000_avail: register_netdev failed\n"); - ar6000_destroy(dev, 0); - return; - } - - HTCSetInstance(ar->arHtcTarget, ar); - - /* We only register the device in the global list if we succeed. */ - /* If the device is in the global list, it will be destroyed */ - /* when the module is unloaded. */ - ar6000_devices[device_index] = dev; - - AR_DEBUG_PRINTF("ar6000_avail: name=%s htcTarget=0x%x, dev=0x%x (%d), ar=0x%x\n", - dev->name, (A_UINT32)HTCHandle, (A_UINT32)dev, device_index, - (A_UINT32)ar); -} - -static void ar6000_target_failure(void *Instance, A_STATUS Status) -{ - AR_SOFTC_T *ar = (AR_SOFTC_T *)Instance; - WMI_TARGET_ERROR_REPORT_EVENT errEvent; - static A_BOOL sip = FALSE; - - if (Status != A_OK) { - if (timer_pending(&ar->arHBChallengeResp.timer)) { - A_UNTIMEOUT(&ar->arHBChallengeResp.timer); - } - - /* try dumping target assertion information (if any) */ - ar6000_dump_target_assert_info(ar->arHifDevice,ar->arTargetType); - - /* - * Fetch the logs from the target via the diagnostic - * window. - */ - ar6000_dbglog_get_debug_logs(ar); - - /* Report the error only once */ - if (!sip) { - sip = TRUE; - errEvent.errorVal = WMI_TARGET_COM_ERR | - WMI_TARGET_FATAL_ERR; -#ifdef SEND_EVENT_TO_APP - ar6000_send_event_to_app(ar, WMI_ERROR_REPORT_EVENTID, - (A_UINT8 *)&errEvent, - sizeof(WMI_TARGET_ERROR_REPORT_EVENT)); -#endif - } - } -} - -static void -ar6000_unavail_ev(void *Instance) -{ - AR_SOFTC_T *ar = (AR_SOFTC_T *)Instance; - /* NULL out it's entry in the global list */ - ar6000_devices[ar->arDeviceIndex] = NULL; - ar6000_destroy(ar->arNetDev, 1); -} - -/* - * We need to differentiate between the surprise and planned removal of the - * device because of the following consideration: - * - In case of surprise removal, the hcd already frees up the pending - * for the device and hence there is no need to unregister the function - * driver inorder to get these requests. For planned removal, the function - * driver has to explictly unregister itself to have the hcd return all the - * pending requests before the data structures for the devices are freed up. - * Note that as per the current implementation, the function driver will - * end up releasing all the devices since there is no API to selectively - * release a particular device. - * - Certain commands issued to the target can be skipped for surprise - * removal since they will anyway not go through. - */ -static void -ar6000_destroy(struct net_device *dev, unsigned int unregister) -{ - AR_SOFTC_T *ar; - - AR_DEBUG_PRINTF("+ar6000_destroy \n"); - - if((dev == NULL) || ((ar = netdev_priv(dev)) == NULL)) - { - AR_DEBUG_PRINTF("%s(): Failed to get device structure.\n", __func__); - return; - } - - /* Clear the tx counters */ - memset(tx_attempt, 0, sizeof(tx_attempt)); - memset(tx_post, 0, sizeof(tx_post)); - memset(tx_complete, 0, sizeof(tx_complete)); - - /* Free up the device data structure */ - if (unregister) { - unregister_netdev(dev); - } else { - ar6000_close(dev); - ar6000_cleanup(dev); - } - - free_raw_buffers(ar); - -#ifndef free_netdev - kfree(dev); -#else - free_netdev(dev); -#endif - - AR_DEBUG_PRINTF("-ar6000_destroy \n"); -} - -static void ar6000_detect_error(unsigned long ptr) -{ - struct net_device *dev = (struct net_device *)ptr; - AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev); - WMI_TARGET_ERROR_REPORT_EVENT errEvent; - - AR6000_SPIN_LOCK(&ar->arLock, 0); - - if (ar->arHBChallengeResp.outstanding) { - ar->arHBChallengeResp.missCnt++; - } else { - ar->arHBChallengeResp.missCnt = 0; - } - - if (ar->arHBChallengeResp.missCnt > ar->arHBChallengeResp.missThres) { - /* Send Error Detect event to the application layer and do not reschedule the error detection module timer */ - ar->arHBChallengeResp.missCnt = 0; - ar->arHBChallengeResp.seqNum = 0; - errEvent.errorVal = WMI_TARGET_COM_ERR | WMI_TARGET_FATAL_ERR; - AR6000_SPIN_UNLOCK(&ar->arLock, 0); -#ifdef SEND_EVENT_TO_APP - ar6000_send_event_to_app(ar, WMI_ERROR_REPORT_EVENTID, - (A_UINT8 *)&errEvent, - sizeof(WMI_TARGET_ERROR_REPORT_EVENT)); -#endif - return; - } - - /* Generate the sequence number for the next challenge */ - ar->arHBChallengeResp.seqNum++; - ar->arHBChallengeResp.outstanding = TRUE; - - AR6000_SPIN_UNLOCK(&ar->arLock, 0); - - /* Send the challenge on the control channel */ - if (wmi_get_challenge_resp_cmd(ar->arWmi, ar->arHBChallengeResp.seqNum, DRV_HB_CHALLENGE) != A_OK) { - AR_DEBUG_PRINTF("Unable to send heart beat challenge\n"); - } - - - /* Reschedule the timer for the next challenge */ - A_TIMEOUT_MS(&ar->arHBChallengeResp.timer, ar->arHBChallengeResp.frequency * 1000, 0); -} - -void ar6000_init_profile_info(AR_SOFTC_T *ar) -{ - ar->arSsidLen = 0; - A_MEMZERO(ar->arSsid, sizeof(ar->arSsid)); - ar->arNetworkType = INFRA_NETWORK; - ar->arDot11AuthMode = OPEN_AUTH; - ar->arAuthMode = NONE_AUTH; - ar->arPairwiseCrypto = NONE_CRYPT; - ar->arPairwiseCryptoLen = 0; - ar->arGroupCrypto = NONE_CRYPT; - ar->arGroupCryptoLen = 0; - A_MEMZERO(ar->arWepKeyList, sizeof(ar->arWepKeyList)); - A_MEMZERO(ar->arReqBssid, sizeof(ar->arReqBssid)); - A_MEMZERO(ar->arBssid, sizeof(ar->arBssid)); - ar->arBssChannel = 0; -} - -static void -ar6000_init_control_info(AR_SOFTC_T *ar) -{ - ar->arWmiEnabled = FALSE; - ar6000_init_profile_info(ar); - ar->arDefTxKeyIndex = 0; - A_MEMZERO(ar->arWepKeyList, sizeof(ar->arWepKeyList)); - ar->arChannelHint = 0; - ar->arListenInterval = MAX_LISTEN_INTERVAL; - ar->arVersion.host_ver = AR6K_SW_VERSION; - ar->arRssi = 0; - ar->arTxPwr = 0; - ar->arTxPwrSet = FALSE; - ar->arSkipScan = 0; - ar->arBeaconInterval = 0; - ar->arBitRate = 0; - ar->arMaxRetries = 0; - ar->arWmmEnabled = TRUE; -} - -static int -ar6000_open(struct net_device *dev) -{ - /* Wake up the queues */ - netif_start_queue(dev); - - return 0; -} - -static int -ar6000_close(struct net_device *dev) -{ - /* Stop the transmit queues */ - netif_stop_queue(dev); - return 0; -} - -static int -ar6000_cleanup(struct net_device *dev) -{ - AR_SOFTC_T *ar = netdev_priv(dev); - - /* Stop the transmit queues */ - netif_stop_queue(dev); - - /* Disable the target and the interrupts associated with it */ - if (ar->arWmiReady == TRUE) - { - if (!bypasswmi) - { - if (ar->arConnected == TRUE || ar->arConnectPending == TRUE) - { - AR_DEBUG_PRINTF("%s(): Disconnect\n", __func__); - AR6000_SPIN_LOCK(&ar->arLock, 0); - ar6000_init_profile_info(ar); - AR6000_SPIN_UNLOCK(&ar->arLock, 0); - wmi_disconnect_cmd(ar->arWmi); - } - - ar6000_dbglog_get_debug_logs(ar); - ar->arWmiReady = FALSE; - ar->arConnected = FALSE; - ar->arConnectPending = FALSE; - wmi_shutdown(ar->arWmi); - ar->arWmiEnabled = FALSE; - ar->arWmi = NULL; - ar->arWlanState = WLAN_ENABLED; -#ifdef USER_KEYS - ar->user_savedkeys_stat = USER_SAVEDKEYS_STAT_INIT; - ar->user_key_ctrl = 0; -#endif - } - - AR_DEBUG_PRINTF("%s(): WMI stopped\n", __func__); - } - else - { - AR_DEBUG_PRINTF("%s(): WMI not ready 0x%08x 0x%08x\n", - __func__, (unsigned int) ar, (unsigned int) ar->arWmi); - - /* Shut down WMI if we have started it */ - if(ar->arWmiEnabled == TRUE) - { - AR_DEBUG_PRINTF("%s(): Shut down WMI\n", __func__); - wmi_shutdown(ar->arWmi); - ar->arWmiEnabled = FALSE; - ar->arWmi = NULL; - } - } - - /* stop HTC */ - HTCStop(ar->arHtcTarget); - - /* set the instance to NULL so we do not get called back on remove incase we - * we're explicity destroyed by module unload */ - HTCSetInstance(ar->arHtcTarget, NULL); - - if (resetok) { - /* try to reset the device if we can - * The driver may have been configure NOT to reset the target during - * a debug session */ - AR_DEBUG_PRINTF(" Attempting to reset target on instance destroy.... \n"); - ar6000_reset_device(ar->arHifDevice, ar->arTargetType); - } else { - AR_DEBUG_PRINTF(" Host does not want target reset. \n"); - } - - /* Done with cookies */ - ar6000_cookie_cleanup(ar); - - /* Cleanup BMI */ - BMIInit(); - - return 0; -} - -/* connect to a service */ -static A_STATUS ar6000_connectservice(AR_SOFTC_T *ar, - HTC_SERVICE_CONNECT_REQ *pConnect, - WMI_PRI_STREAM_ID WmiStreamID, - char *pDesc) -{ - A_STATUS status; - HTC_SERVICE_CONNECT_RESP response; - - do { - - A_MEMZERO(&response,sizeof(response)); - - status = HTCConnectService(ar->arHtcTarget, - pConnect, - &response); - - if (A_FAILED(status)) { - AR_DEBUG_PRINTF(" Failed to connect to %s service status:%d \n", pDesc, status); - break; - } - - if (WmiStreamID == WMI_NOT_MAPPED) { - /* done */ - break; - } - - /* set endpoint mapping for the WMI stream in the driver layer */ - arSetWMIStream2EndpointIDMap(ar,WmiStreamID,response.Endpoint); - - } while (FALSE); - - return status; -} - -static void ar6000_TxDataCleanup(AR_SOFTC_T *ar) -{ - /* flush all the data (non-control) streams - * we only flush packets that are tagged as data, we leave any control packets that - * were in the TX queues alone */ - HTCFlushEndpoint(ar->arHtcTarget, - arWMIStream2EndpointID(ar,WMI_BEST_EFFORT_PRI), - AR6K_DATA_PKT_TAG); - HTCFlushEndpoint(ar->arHtcTarget, - arWMIStream2EndpointID(ar,WMI_LOW_PRI), - AR6K_DATA_PKT_TAG); - HTCFlushEndpoint(ar->arHtcTarget, - arWMIStream2EndpointID(ar,WMI_HIGH_PRI), - AR6K_DATA_PKT_TAG); - HTCFlushEndpoint(ar->arHtcTarget, - arWMIStream2EndpointID(ar,WMI_HIGHEST_PRI), - AR6K_DATA_PKT_TAG); -} - -/* This function does one time initialization for the lifetime of the device */ -int ar6000_init(struct net_device *dev) -{ - AR_SOFTC_T *ar; - A_STATUS status; - A_INT32 timeleft; - - if((ar = netdev_priv(dev)) == NULL) - { - return(-EIO); - } - - /* Do we need to finish the BMI phase */ - if(BMIDone(ar->arHifDevice) != A_OK) - { - return -EIO; - } - - if (!bypasswmi) - { -#if 0 /* TBDXXX */ - if (ar->arVersion.host_ver != ar->arVersion.target_ver) { - A_PRINTF("WARNING: Host version 0x%x does not match Target " - " version 0x%x!\n", - ar->arVersion.host_ver, ar->arVersion.target_ver); - } -#endif - - /* Indicate that WMI is enabled (although not ready yet) */ - ar->arWmiEnabled = TRUE; - if ((ar->arWmi = wmi_init((void *) ar)) == NULL) - { - AR_DEBUG_PRINTF("%s() Failed to initialize WMI.\n", __func__); - return(-EIO); - } - - AR_DEBUG_PRINTF("%s() Got WMI @ 0x%08x.\n", __func__, - (unsigned int) ar->arWmi); - } - - do { - HTC_SERVICE_CONNECT_REQ connect; - - /* the reason we have to wait for the target here is that the driver layer - * has to init BMI in order to set the host block size, - */ - status = HTCWaitTarget(ar->arHtcTarget); - - if (A_FAILED(status)) { - break; - } - - A_MEMZERO(&connect,sizeof(connect)); - /* meta data is unused for now */ - connect.pMetaData = NULL; - connect.MetaDataLength = 0; - /* these fields are the same for all service endpoints */ - connect.EpCallbacks.pContext = ar; - connect.EpCallbacks.EpTxComplete = ar6000_tx_complete; - connect.EpCallbacks.EpRecv = ar6000_rx; - connect.EpCallbacks.EpRecvRefill = ar6000_rx_refill; - connect.EpCallbacks.EpSendFull = ar6000_tx_queue_full; - connect.EpCallbacks.EpSendAvail = ar6000_tx_queue_avail; - /* set the max queue depth so that our ar6000_tx_queue_full handler gets called. - * Linux has the peculiarity of not providing flow control between the - * NIC and the network stack. There is no API to indicate that a TX packet - * was sent which could provide some back pressure to the network stack. - * Under linux you would have to wait till the network stack consumed all sk_buffs - * before any back-flow kicked in. Which isn't very friendly. - * So we have to manage this ourselves */ - connect.MaxSendQueueDepth = 32; - - /* connect to control service */ - connect.ServiceID = WMI_CONTROL_SVC; - status = ar6000_connectservice(ar, - &connect, - WMI_CONTROL_PRI, - "WMI CONTROL"); - if (A_FAILED(status)) { - break; - } - - /* for the remaining data services set the connection flag to reduce dribbling, - * if configured to do so */ - if (reduce_credit_dribble) { - connect.ConnectionFlags |= HTC_CONNECT_FLAGS_REDUCE_CREDIT_DRIBBLE; - /* the credit dribble trigger threshold is (reduce_credit_dribble - 1) for a value - * of 0-3 */ - connect.ConnectionFlags &= ~HTC_CONNECT_FLAGS_THRESHOLD_LEVEL_MASK; - connect.ConnectionFlags |= - ((A_UINT16)reduce_credit_dribble - 1) & HTC_CONNECT_FLAGS_THRESHOLD_LEVEL_MASK; - } - /* connect to best-effort service */ - connect.ServiceID = WMI_DATA_BE_SVC; - - status = ar6000_connectservice(ar, - &connect, - WMI_BEST_EFFORT_PRI, - "WMI DATA BE"); - if (A_FAILED(status)) { - break; - } - - /* connect to back-ground - * map this to WMI LOW_PRI */ - connect.ServiceID = WMI_DATA_BK_SVC; - status = ar6000_connectservice(ar, - &connect, - WMI_LOW_PRI, - "WMI DATA BK"); - if (A_FAILED(status)) { - break; - } - - /* connect to Video service, map this to - * to HI PRI */ - connect.ServiceID = WMI_DATA_VI_SVC; - status = ar6000_connectservice(ar, - &connect, - WMI_HIGH_PRI, - "WMI DATA VI"); - if (A_FAILED(status)) { - break; - } - - /* connect to VO service, this is currently not - * mapped to a WMI priority stream due to historical reasons. - * WMI originally defined 3 priorities over 3 mailboxes - * We can change this when WMI is reworked so that priorities are not - * dependent on mailboxes */ - connect.ServiceID = WMI_DATA_VO_SVC; - status = ar6000_connectservice(ar, - &connect, - WMI_HIGHEST_PRI, - "WMI DATA VO"); - if (A_FAILED(status)) { - break; - } - - A_ASSERT(arWMIStream2EndpointID(ar,WMI_CONTROL_PRI) != 0); - A_ASSERT(arWMIStream2EndpointID(ar,WMI_BEST_EFFORT_PRI) != 0); - A_ASSERT(arWMIStream2EndpointID(ar,WMI_LOW_PRI) != 0); - A_ASSERT(arWMIStream2EndpointID(ar,WMI_HIGH_PRI) != 0); - A_ASSERT(arWMIStream2EndpointID(ar,WMI_HIGHEST_PRI) != 0); - } while (FALSE); - - if (A_FAILED(status)) { - return (-EIO); - } - - /* - * give our connected endpoints some buffers - */ - ar6000_rx_refill(ar, arWMIStream2EndpointID(ar,WMI_CONTROL_PRI)); - - ar6000_rx_refill(ar, arWMIStream2EndpointID(ar,WMI_BEST_EFFORT_PRI)); - - /* - * We will post the receive buffers only for SPE testing and so we are - * making it conditional on the 'bypasswmi' flag. - */ - if (bypasswmi) { - ar6000_rx_refill(ar,arWMIStream2EndpointID(ar,WMI_LOW_PRI)); - ar6000_rx_refill(ar,arWMIStream2EndpointID(ar,WMI_HIGH_PRI)); - } - - /* setup credit distribution */ - ar6000_setup_credit_dist(ar->arHtcTarget, &ar->arCreditStateInfo); - - /* Since cookies are used for HTC transports, they should be */ - /* initialized prior to enabling HTC. */ - ar6000_cookie_init(ar); - - /* start HTC */ - status = HTCStart(ar->arHtcTarget); - - if (status != A_OK) { - if (ar->arWmiEnabled == TRUE) { - wmi_shutdown(ar->arWmi); - ar->arWmiEnabled = FALSE; - ar->arWmi = NULL; - } - ar6000_cookie_cleanup(ar); - return -EIO; - } - - if (!bypasswmi) { - /* Wait for Wmi event to be ready */ - timeleft = wait_event_interruptible_timeout(arEvent, - (ar->arWmiReady == TRUE), wmitimeout * HZ); - - if(!timeleft || signal_pending(current)) - { - AR_DEBUG_PRINTF("WMI is not ready or wait was interrupted\n"); -#if defined(DWSIM) /* TBDXXX */ - AR_DEBUG_PRINTF(".....but proceed anyway.\n"); -#else - return -EIO; -#endif - } - - AR_DEBUG_PRINTF("%s() WMI is ready\n", __func__); - - /* Communicate the wmi protocol verision to the target */ - if ((ar6000_set_host_app_area(ar)) != A_OK) { - AR_DEBUG_PRINTF("Unable to set the host app area\n"); - } - } - - ar->arNumDataEndPts = 1; - - return(0); -} - - -void -ar6000_bitrate_rx(void *devt, A_INT32 rateKbps) -{ - AR_SOFTC_T *ar = (AR_SOFTC_T *)devt; - - ar->arBitRate = rateKbps; - wake_up(&arEvent); -} - -void -ar6000_ratemask_rx(void *devt, A_UINT16 ratemask) -{ - AR_SOFTC_T *ar = (AR_SOFTC_T *)devt; - - ar->arRateMask = ratemask; - wake_up(&arEvent); -} - -void -ar6000_txPwr_rx(void *devt, A_UINT8 txPwr) -{ - AR_SOFTC_T *ar = (AR_SOFTC_T *)devt; - - ar->arTxPwr = txPwr; - wake_up(&arEvent); -} - - -void -ar6000_channelList_rx(void *devt, A_INT8 numChan, A_UINT16 *chanList) -{ - AR_SOFTC_T *ar = (AR_SOFTC_T *)devt; - - A_MEMCPY(ar->arChannelList, chanList, numChan * sizeof (A_UINT16)); - ar->arNumChannels = numChan; - - wake_up(&arEvent); -} - -A_UINT8 -ar6000_ibss_map_epid(struct sk_buff *skb, struct net_device *dev, A_UINT32 * mapNo) -{ - AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev); - A_UINT8 *datap; - ATH_MAC_HDR *macHdr; - A_UINT32 i, eptMap; - - (*mapNo) = 0; - datap = A_NETBUF_DATA(skb); - macHdr = (ATH_MAC_HDR *)(datap + sizeof(WMI_DATA_HDR)); - if (IEEE80211_IS_MULTICAST(macHdr->dstMac)) { - return ENDPOINT_2; - } - - eptMap = -1; - for (i = 0; i < ar->arNodeNum; i ++) { - if (IEEE80211_ADDR_EQ(macHdr->dstMac, ar->arNodeMap[i].macAddress)) { - (*mapNo) = i + 1; - ar->arNodeMap[i].txPending ++; - return ar->arNodeMap[i].epId; - } - - if ((eptMap == -1) && !ar->arNodeMap[i].txPending) { - eptMap = i; - } - } - - if (eptMap == -1) { - eptMap = ar->arNodeNum; - ar->arNodeNum ++; - A_ASSERT(ar->arNodeNum <= MAX_NODE_NUM); - } - - A_MEMCPY(ar->arNodeMap[eptMap].macAddress, macHdr->dstMac, IEEE80211_ADDR_LEN); - - for (i = ENDPOINT_2; i <= ENDPOINT_5; i ++) { - if (!ar->arTxPending[i]) { - ar->arNodeMap[eptMap].epId = i; - break; - } - // No free endpoint is available, start redistribution on the inuse endpoints. - if (i == ENDPOINT_5) { - ar->arNodeMap[eptMap].epId = ar->arNexEpId; - ar->arNexEpId ++; - if (ar->arNexEpId > ENDPOINT_5) { - ar->arNexEpId = ENDPOINT_2; - } - } - } - - (*mapNo) = eptMap + 1; - ar->arNodeMap[eptMap].txPending ++; - - return ar->arNodeMap[eptMap].epId; -} - -#ifdef DEBUG -static void ar6000_dump_skb(struct sk_buff *skb) -{ - u_char *ch; - for (ch = A_NETBUF_DATA(skb); - (A_UINT32)ch < ((A_UINT32)A_NETBUF_DATA(skb) + - A_NETBUF_LEN(skb)); ch++) - { - AR_DEBUG_PRINTF("%2.2x ", *ch); - } - AR_DEBUG_PRINTF("\n"); -} -#endif - -static int -ar6000_data_tx(struct sk_buff *skb, struct net_device *dev) -{ - AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev); - WMI_PRI_STREAM_ID streamID = WMI_NOT_MAPPED; - A_UINT32 mapNo = 0; - int len; - struct ar_cookie *cookie; - A_BOOL checkAdHocPsMapping = FALSE; - -#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,13) - skb->list = NULL; -#endif - - AR_DEBUG2_PRINTF("ar6000_data_tx start - skb=0x%x, data=0x%x, len=0x%x\n", - (A_UINT32)skb, (A_UINT32)A_NETBUF_DATA(skb), - A_NETBUF_LEN(skb)); -#ifdef CONFIG_HOST_TCMD_SUPPORT - /* TCMD doesnt support any data, free the buf and return */ - if(ar->arTargetMode == AR6000_TCMD_MODE) { - A_NETBUF_FREE(skb); - return 0; - } -#endif - do { - - if (ar->arWmiReady == FALSE && bypasswmi == 0) { - break; - } - -#ifdef BLOCK_TX_PATH_FLAG - if (blocktx) { - break; - } -#endif /* BLOCK_TX_PATH_FLAG */ - - if (ar->arWmiEnabled) { - if (A_NETBUF_HEADROOM(skb) < dev->hard_header_len) { - struct sk_buff *newbuf; - /* - * We really should have gotten enough headroom but sometimes - * we still get packets with not enough headroom. Copy the packet. - */ - len = A_NETBUF_LEN(skb); - newbuf = A_NETBUF_ALLOC(len); - if (newbuf == NULL) { - break; - } - A_NETBUF_PUT(newbuf, len); - A_MEMCPY(A_NETBUF_DATA(newbuf), A_NETBUF_DATA(skb), len); - A_NETBUF_FREE(skb); - skb = newbuf; - /* fall through and assemble header */ - } - - if (wmi_dix_2_dot3(ar->arWmi, skb) != A_OK) { - AR_DEBUG_PRINTF("ar6000_data_tx - wmi_dix_2_dot3 failed\n"); - break; - } - - if (wmi_data_hdr_add(ar->arWmi, skb, DATA_MSGTYPE) != A_OK) { - AR_DEBUG_PRINTF("ar6000_data_tx - wmi_data_hdr_add failed\n"); - break; - } - - if ((ar->arNetworkType == ADHOC_NETWORK) && - ar->arIbssPsEnable && ar->arConnected) { - /* flag to check adhoc mapping once we take the lock below: */ - checkAdHocPsMapping = TRUE; - - } else { - /* get the stream mapping */ - if (ar->arWmmEnabled) { - streamID = wmi_get_stream_id(ar->arWmi, - wmi_implicit_create_pstream(ar->arWmi, skb, UPLINK_TRAFFIC, UNDEFINED_PRI)); - } else { - streamID = WMI_BEST_EFFORT_PRI; - } - } - - } else { - struct iphdr *ipHdr; - /* - * the endpoint is directly based on the TOS field in the IP - * header **** only for testing ****** - */ - ipHdr = A_NETBUF_DATA(skb) + sizeof(ATH_MAC_HDR); - /* here we map the TOS field to an endpoint number, this is for - * the endpointping test application */ - streamID = IP_TOS_TO_WMI_PRI(ipHdr->tos); - } - - } while (FALSE); - - /* did we succeed ? */ - if ((streamID == WMI_NOT_MAPPED) && !checkAdHocPsMapping) { - /* cleanup and exit */ - A_NETBUF_FREE(skb); - AR6000_STAT_INC(ar, tx_dropped); - AR6000_STAT_INC(ar, tx_aborted_errors); - return 0; - } - - cookie = NULL; - - /* take the lock to protect driver data */ - AR6000_SPIN_LOCK(&ar->arLock, 0); - - do { - - if (checkAdHocPsMapping) { - streamID = ar6000_ibss_map_epid(skb, dev, &mapNo); - } - - A_ASSERT(streamID != WMI_NOT_MAPPED); - - /* validate that the endpoint is connected */ - if (arWMIStream2EndpointID(ar,streamID) == 0) { - AR_DEBUG_PRINTF("Stream %d is NOT mapped!\n",streamID); - break; - } - /* allocate resource for this packet */ - cookie = ar6000_alloc_cookie(ar); - - if (cookie != NULL) { - /* update counts while the lock is held */ - ar->arTxPending[streamID]++; - ar->arTotalTxDataPending++; - } - - } while (FALSE); - - AR6000_SPIN_UNLOCK(&ar->arLock, 0); - - if (cookie != NULL) { - cookie->arc_bp[0] = (A_UINT32)skb; - cookie->arc_bp[1] = mapNo; - SET_HTC_PACKET_INFO_TX(&cookie->HtcPkt, - cookie, - A_NETBUF_DATA(skb), - A_NETBUF_LEN(skb), - arWMIStream2EndpointID(ar,streamID), - AR6K_DATA_PKT_TAG); - -#ifdef DEBUG - if (debugdriver >= 3) { - ar6000_dump_skb(skb); - } -#endif - /* HTC interface is asynchronous, if this fails, cleanup will happen in - * the ar6000_tx_complete callback */ - HTCSendPkt(ar->arHtcTarget, &cookie->HtcPkt); - } else { - /* no packet to send, cleanup */ - A_NETBUF_FREE(skb); - AR6000_STAT_INC(ar, tx_dropped); - AR6000_STAT_INC(ar, tx_aborted_errors); - } - - return 0; -} - -#ifdef ADAPTIVE_POWER_THROUGHPUT_CONTROL -static void -tvsub(register struct timeval *out, register struct timeval *in) -{ - if((out->tv_usec -= in->tv_usec) < 0) { - out->tv_sec--; - out->tv_usec += 1000000; - } - out->tv_sec -= in->tv_sec; -} - -void -applyAPTCHeuristics(AR_SOFTC_T *ar) -{ - A_UINT32 duration; - A_UINT32 numbytes; - A_UINT32 throughput; - struct timeval ts; - A_STATUS status; - - AR6000_SPIN_LOCK(&ar->arLock, 0); - - if ((enableAPTCHeuristics) && (!aptcTR.timerScheduled)) { - do_gettimeofday(&ts); - tvsub(&ts, &aptcTR.samplingTS); - duration = ts.tv_sec * 1000 + ts.tv_usec / 1000; /* ms */ - numbytes = aptcTR.bytesTransmitted + aptcTR.bytesReceived; - - if (duration > APTC_TRAFFIC_SAMPLING_INTERVAL) { - /* Initialize the time stamp and byte count */ - aptcTR.bytesTransmitted = aptcTR.bytesReceived = 0; - do_gettimeofday(&aptcTR.samplingTS); - - /* Calculate and decide based on throughput thresholds */ - throughput = ((numbytes * 8) / duration); - if (throughput > APTC_UPPER_THROUGHPUT_THRESHOLD) { - /* Disable Sleep and schedule a timer */ - A_ASSERT(ar->arWmiReady == TRUE); - AR6000_SPIN_UNLOCK(&ar->arLock, 0); - status = wmi_powermode_cmd(ar->arWmi, MAX_PERF_POWER); - AR6000_SPIN_LOCK(&ar->arLock, 0); - A_TIMEOUT_MS(&aptcTimer, APTC_TRAFFIC_SAMPLING_INTERVAL, 0); - aptcTR.timerScheduled = TRUE; - } - } - } - - AR6000_SPIN_UNLOCK(&ar->arLock, 0); -} -#endif /* ADAPTIVE_POWER_THROUGHPUT_CONTROL */ - -static void -ar6000_tx_queue_full(void *Context, HTC_ENDPOINT_ID Endpoint) -{ - AR_SOFTC_T *ar = (AR_SOFTC_T *) Context; - - if (Endpoint == arWMIStream2EndpointID(ar,WMI_CONTROL_PRI)) { - if (!bypasswmi) { - /* under normal WMI if this is getting full, then something is running rampant - * the host should not be exhausting the WMI queue with too many commands - * the only exception to this is during testing using endpointping */ - - AR6000_SPIN_LOCK(&ar->arLock, 0); - /* set flag to handle subsequent messages */ - ar->arWMIControlEpFull = TRUE; - AR6000_SPIN_UNLOCK(&ar->arLock, 0); - AR_DEBUG_PRINTF("WMI Control Endpoint is FULL!!! \n"); - } - } else { - /* one of the data endpoints queues is getting full..need to stop network stack - * the queue will resume after credits received */ - netif_stop_queue(ar->arNetDev); - } -} - -static void -ar6000_tx_queue_avail(void *Context, HTC_ENDPOINT_ID Endpoint) -{ - AR_SOFTC_T *ar = (AR_SOFTC_T *)Context; - - if (Endpoint == arWMIStream2EndpointID(ar,WMI_CONTROL_PRI)) { - /* FIXME: what do for it? */ - } else { - /* Wake up interface, rescheduling prevented. */ - if (ar->arConnected == TRUE || bypasswmi) - netif_wake_queue(ar->arNetDev); - } -} - -static void -ar6000_tx_complete(void *Context, HTC_PACKET *pPacket) -{ - AR_SOFTC_T *ar = (AR_SOFTC_T *)Context; - void *cookie = (void *)pPacket->pPktContext; - struct sk_buff *skb = NULL; - A_UINT32 mapNo = 0; - A_STATUS status; - struct ar_cookie * ar_cookie; - WMI_PRI_STREAM_ID streamID; - A_BOOL wakeEvent = FALSE; - - status = pPacket->Status; - ar_cookie = (struct ar_cookie *)cookie; - skb = (struct sk_buff *)ar_cookie->arc_bp[0]; - streamID = arEndpoint2WMIStreamID(ar,pPacket->Endpoint); - mapNo = ar_cookie->arc_bp[1]; - - A_ASSERT(skb); - A_ASSERT(pPacket->pBuffer == A_NETBUF_DATA(skb)); - - if (A_SUCCESS(status)) { - A_ASSERT(pPacket->ActualLength == A_NETBUF_LEN(skb)); - } - - AR_DEBUG2_PRINTF("ar6000_tx_complete skb=0x%x data=0x%x len=0x%x sid=%d ", - (A_UINT32)skb, (A_UINT32)pPacket->pBuffer, - pPacket->ActualLength, - streamID); - - /* lock the driver as we update internal state */ - AR6000_SPIN_LOCK(&ar->arLock, 0); - - ar->arTxPending[streamID]--; - - if ((streamID != WMI_CONTROL_PRI) || bypasswmi) { - ar->arTotalTxDataPending--; - } - - if (streamID == WMI_CONTROL_PRI) - { - if (ar->arWMIControlEpFull) { - /* since this packet completed, the WMI EP is no longer full */ - ar->arWMIControlEpFull = FALSE; - } - - if (ar->arTxPending[streamID] == 0) { - wakeEvent = TRUE; - } - } - - if (A_FAILED(status)) { - AR_DEBUG_PRINTF("%s() -TX ERROR, status: 0x%x\n", __func__, - status); - AR6000_STAT_INC(ar, tx_errors); - } else { - AR_DEBUG2_PRINTF("OK\n"); - AR6000_STAT_INC(ar, tx_packets); - ar->arNetStats.tx_bytes += A_NETBUF_LEN(skb); -#ifdef ADAPTIVE_POWER_THROUGHPUT_CONTROL - aptcTR.bytesTransmitted += a_netbuf_to_len(skb); - applyAPTCHeuristics(ar); -#endif /* ADAPTIVE_POWER_THROUGHPUT_CONTROL */ - } - - // TODO this needs to be looked at - if ((ar->arNetworkType == ADHOC_NETWORK) && ar->arIbssPsEnable - && (streamID != WMI_CONTROL_PRI) && mapNo) - { - mapNo --; - ar->arNodeMap[mapNo].txPending --; - - if (!ar->arNodeMap[mapNo].txPending && (mapNo == (ar->arNodeNum - 1))) { - A_UINT32 i; - for (i = ar->arNodeNum; i > 0; i --) { - if (!ar->arNodeMap[i - 1].txPending) { - A_MEMZERO(&ar->arNodeMap[i - 1], sizeof(struct ar_node_mapping)); - ar->arNodeNum --; - } else { - break; - } - } - } - } - - /* Freeing a cookie should not be contingent on either of */ - /* these flags, just if we have a cookie or not. */ - /* Can we even get here without a cookie? Fix later. */ - if (ar->arWmiReady == TRUE || (bypasswmi)) - { - ar6000_free_cookie(ar, cookie); - } - - AR6000_SPIN_UNLOCK(&ar->arLock, 0); - - /* lock is released, we can freely call other kernel APIs */ - - /* this indirectly frees the HTC_PACKET */ - A_NETBUF_FREE(skb); - - if (wakeEvent) { - wake_up(&arEvent); - } -} - -/* - * Receive event handler. This is called by HTC when a packet is received - */ -int pktcount; -static void -ar6000_rx(void *Context, HTC_PACKET *pPacket) -{ - AR_SOFTC_T *ar = (AR_SOFTC_T *)Context; - struct sk_buff *skb = (struct sk_buff *)pPacket->pPktContext; - int minHdrLen; - A_STATUS status = pPacket->Status; - WMI_PRI_STREAM_ID streamID = arEndpoint2WMIStreamID(ar,pPacket->Endpoint); - HTC_ENDPOINT_ID ept = pPacket->Endpoint; - - A_ASSERT((status != A_OK) || (pPacket->pBuffer == (A_NETBUF_DATA(skb) + HTC_HEADER_LEN))); - - AR_DEBUG2_PRINTF("ar6000_rx ar=0x%x sid=%d, skb=0x%x, data=0x%x, len=0x%x ", - (A_UINT32)ar, streamID, (A_UINT32)skb, (A_UINT32)pPacket->pBuffer, - pPacket->ActualLength); - if (status != A_OK) { - AR_DEBUG2_PRINTF("ERR\n"); - } else { - AR_DEBUG2_PRINTF("OK\n"); - } - - /* take lock to protect buffer counts - * and adaptive power throughput state */ - AR6000_SPIN_LOCK(&ar->arLock, 0); - - ar->arRxBuffers[streamID]--; - - if (A_SUCCESS(status)) { - AR6000_STAT_INC(ar, rx_packets); - ar->arNetStats.rx_bytes += pPacket->ActualLength; -#ifdef ADAPTIVE_POWER_THROUGHPUT_CONTROL - aptcTR.bytesReceived += a_netbuf_to_len(skb); - applyAPTCHeuristics(ar); -#endif /* ADAPTIVE_POWER_THROUGHPUT_CONTROL */ - - A_NETBUF_PUT(skb, pPacket->ActualLength + HTC_HEADER_LEN); - A_NETBUF_PULL(skb, HTC_HEADER_LEN); - -#ifdef DEBUG - if (debugdriver >= 2) { - ar6000_dump_skb(skb); - } -#endif /* DEBUG */ - } - - AR6000_SPIN_UNLOCK(&ar->arLock, 0); - - if (status != A_OK) { - AR6000_STAT_INC(ar, rx_errors); - A_NETBUF_FREE(skb); - } else if (ar->arWmiEnabled == TRUE) { - if (streamID == WMI_CONTROL_PRI) { - /* - * this is a wmi control msg - */ - wmi_control_rx(ar->arWmi, skb); - } else { - WMI_DATA_HDR *dhdr = (WMI_DATA_HDR *)A_NETBUF_DATA(skb); - if (WMI_DATA_HDR_IS_MSG_TYPE(dhdr, CNTL_MSGTYPE)) { - /* - * this is a wmi control msg - */ - /* strip off WMI hdr */ - wmi_data_hdr_remove(ar->arWmi, skb); - wmi_control_rx(ar->arWmi, skb); - } else { - /* - * this is a wmi data packet - */ - minHdrLen = sizeof (WMI_DATA_HDR) + sizeof(ATH_MAC_HDR) + - sizeof(ATH_LLC_SNAP_HDR); - - if ((pPacket->ActualLength < minHdrLen) || - (pPacket->ActualLength > AR6000_BUFFER_SIZE)) - { - /* - * packet is too short or too long - */ - AR_DEBUG_PRINTF("TOO SHORT or TOO LONG\n"); - AR6000_STAT_INC(ar, rx_errors); - AR6000_STAT_INC(ar, rx_length_errors); - A_NETBUF_FREE(skb); - } else { - if (ar->arWmmEnabled) { - wmi_implicit_create_pstream(ar->arWmi, skb, - DNLINK_TRAFFIC, UNDEFINED_PRI); - } -#if 0 - /* Access RSSI values here */ - AR_DEBUG_PRINTF("RSSI %d\n", - ((WMI_DATA_HDR *) A_NETBUF_DATA(skb))->rssi); -#endif - wmi_data_hdr_remove(ar->arWmi, skb); - wmi_dot3_2_dix(ar->arWmi, skb); - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) - /* - * extra push and memcpy, for eth_type_trans() of 2.4 kernel - * will pull out hard_header_len bytes of the skb. - */ - A_NETBUF_PUSH(skb, sizeof(WMI_DATA_HDR) + sizeof(ATH_LLC_SNAP_HDR) + HTC_HEADER_LEN); - A_MEMCPY(A_NETBUF_DATA(skb), A_NETBUF_DATA(skb) + sizeof(WMI_DATA_HDR) + - sizeof(ATH_LLC_SNAP_HDR) + HTC_HEADER_LEN, sizeof(ATH_MAC_HDR)); -#endif - if ((ar->arNetDev->flags & IFF_UP) == IFF_UP) - { - skb->dev = ar->arNetDev; - skb->protocol = eth_type_trans(skb, ar->arNetDev); - netif_rx(skb); - } - else - { - A_NETBUF_FREE(skb); - } - } - } - } - } else { - if ((ar->arNetDev->flags & IFF_UP) == IFF_UP) - { - skb->dev = ar->arNetDev; - skb->protocol = eth_type_trans(skb, ar->arNetDev); - netif_rx(skb); - } - else - { - A_NETBUF_FREE(skb); - } - } - - if (status != A_ECANCELED) { - /* - * HTC provides A_ECANCELED status when it doesn't want to be refilled - * (probably due to a shutdown) - */ - ar6000_rx_refill(Context, ept); - } - - -} - -static void -ar6000_rx_refill(void *Context, HTC_ENDPOINT_ID Endpoint) -{ - AR_SOFTC_T *ar = (AR_SOFTC_T *)Context; - void *osBuf; - int RxBuffers; - int buffersToRefill; - HTC_PACKET *pPacket; - WMI_PRI_STREAM_ID streamId = arEndpoint2WMIStreamID(ar,Endpoint); - - buffersToRefill = (int)AR6000_MAX_RX_BUFFERS - - (int)ar->arRxBuffers[streamId]; - - if (buffersToRefill <= 0) { - /* fast return, nothing to fill */ - return; - } - - AR_DEBUG2_PRINTF("ar6000_rx_refill: providing htc with %d buffers at eid=%d\n", - buffersToRefill, Endpoint); - - for (RxBuffers = 0; RxBuffers < buffersToRefill; RxBuffers++) { - osBuf = A_NETBUF_ALLOC(AR6000_BUFFER_SIZE); - if (NULL == osBuf) { - break; - } - /* the HTC packet wrapper is at the head of the reserved area - * in the skb */ - pPacket = (HTC_PACKET *)(A_NETBUF_HEAD(osBuf)); - /* set re-fill info */ - SET_HTC_PACKET_INFO_RX_REFILL(pPacket,osBuf,A_NETBUF_DATA(osBuf),AR6000_BUFFER_SIZE,Endpoint); - /* add this packet */ - HTCAddReceivePkt(ar->arHtcTarget, pPacket); - } - - /* update count */ - AR6000_SPIN_LOCK(&ar->arLock, 0); - ar->arRxBuffers[streamId] += RxBuffers; - AR6000_SPIN_UNLOCK(&ar->arLock, 0); -} - -static struct net_device_stats * -ar6000_get_stats(struct net_device *dev) -{ - AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev); - return &ar->arNetStats; -} - -static struct iw_statistics * -ar6000_get_iwstats(struct net_device * dev) -{ - AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev); - TARGET_STATS *pStats = &ar->arTargetStats; - struct iw_statistics * pIwStats = &ar->arIwStats; - - if ((ar->arWmiReady == FALSE) - /* - * The in_atomic function is used to determine if the scheduling is - * allowed in the current context or not. This was introduced in 2.6 - * From what I have read on the differences between 2.4 and 2.6, the - * 2.4 kernel did not support preemption and so this check might not - * be required for 2.4 kernels. - */ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) - || (in_atomic()) -#endif - ) - { - pIwStats->status = 0; - pIwStats->qual.qual = 0; - pIwStats->qual.level =0; - pIwStats->qual.noise = 0; - pIwStats->discard.code =0; - pIwStats->discard.retries=0; - pIwStats->miss.beacon =0; - return pIwStats; - } - if (down_interruptible(&ar->arSem)) { - pIwStats->status = 0; - return pIwStats; - } - - - ar->statsUpdatePending = TRUE; - - if(wmi_get_stats_cmd(ar->arWmi) != A_OK) { - up(&ar->arSem); - pIwStats->status = 0; - return pIwStats; - } - - wait_event_interruptible_timeout(arEvent, ar->statsUpdatePending == FALSE, wmitimeout * HZ); - - if (signal_pending(current)) { - AR_DEBUG_PRINTF("ar6000 : WMI get stats timeout \n"); - up(&ar->arSem); - pIwStats->status = 0; - return pIwStats; - } - pIwStats->status = 1 ; - pIwStats->qual.qual = pStats->cs_aveBeacon_rssi; - pIwStats->qual.level =pStats->cs_aveBeacon_rssi + 161; /* noise is -95 dBm */ - pIwStats->qual.noise = pStats->noise_floor_calibation; - pIwStats->discard.code = pStats->rx_decrypt_err; - pIwStats->discard.retries = pStats->tx_retry_cnt; - pIwStats->miss.beacon = pStats->cs_bmiss_cnt; - up(&ar->arSem); - return pIwStats; -} - -void -ar6000_ready_event(void *devt, A_UINT8 *datap, A_UINT8 phyCap) -{ - AR_SOFTC_T *ar = (AR_SOFTC_T *)devt; - struct net_device *dev = ar->arNetDev; - - ar->arWmiReady = TRUE; - wake_up(&arEvent); - A_MEMCPY(dev->dev_addr, datap, AR6000_ETH_ADDR_LEN); - AR_DEBUG_PRINTF("mac address = %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x\n", - dev->dev_addr[0], dev->dev_addr[1], - dev->dev_addr[2], dev->dev_addr[3], - dev->dev_addr[4], dev->dev_addr[5]); - - ar->arPhyCapability = phyCap; -} - -A_UINT8 -ar6000_iptos_to_userPriority(A_UINT8 *pkt) -{ - struct iphdr *ipHdr = (struct iphdr *)pkt; - A_UINT8 userPriority; - - /* - * IP Tos format : - * (Refer Pg 57 WMM-test-plan-v1.2) - * IP-TOS - 8bits - * : DSCP(6-bits) ECN(2-bits) - * : DSCP - P2 P1 P0 X X X - * where (P2 P1 P0) form 802.1D - */ - userPriority = ipHdr->tos >> 5; - return (userPriority & 0x7); -} - -void -ar6000_connect_event(AR_SOFTC_T *ar, A_UINT16 channel, A_UINT8 *bssid, - A_UINT16 listenInterval, A_UINT16 beaconInterval, - NETWORK_TYPE networkType, A_UINT8 beaconIeLen, - A_UINT8 assocReqLen, A_UINT8 assocRespLen, - A_UINT8 *assocInfo) -{ - union iwreq_data wrqu; - int i, beacon_ie_pos, assoc_resp_ie_pos, assoc_req_ie_pos; - static const char *tag1 = "ASSOCINFO(ReqIEs="; - static const char *tag2 = "ASSOCRESPIE="; - static const char *beaconIetag = "BEACONIE="; - char buf[WMI_CONTROL_MSG_MAX_LEN * 2 + sizeof(tag1)]; - char *pos; - A_UINT8 key_op_ctrl; - - A_MEMCPY(ar->arBssid, bssid, sizeof(ar->arBssid)); - ar->arBssChannel = channel; - - A_PRINTF("AR6000 connected event on freq %d ", channel); - A_PRINTF("with bssid %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x " - " listenInterval=%d, beaconInterval = %d, beaconIeLen = %d assocReqLen=%d" - " assocRespLen =%d\n", - bssid[0], bssid[1], bssid[2], - bssid[3], bssid[4], bssid[5], - listenInterval, beaconInterval, - beaconIeLen, assocReqLen, assocRespLen); - if (networkType & ADHOC_NETWORK) { - if (networkType & ADHOC_CREATOR) { - A_PRINTF("Network: Adhoc (Creator)\n"); - } else { - A_PRINTF("Network: Adhoc (Joiner)\n"); - } - } else { - A_PRINTF("Network: Infrastructure\n"); - } - - if (beaconIeLen && (sizeof(buf) > (9 + beaconIeLen * 2))) { - AR_DEBUG_PRINTF("\nBeaconIEs= "); - - beacon_ie_pos = 0; - A_MEMZERO(buf, sizeof(buf)); - sprintf(buf, "%s", beaconIetag); - pos = buf + 9; - for (i = beacon_ie_pos; i < beacon_ie_pos + beaconIeLen; i++) { - AR_DEBUG_PRINTF("%2.2x ", assocInfo[i]); - sprintf(pos, "%2.2x", assocInfo[i]); - pos += 2; - } - AR_DEBUG_PRINTF("\n"); - - A_MEMZERO(&wrqu, sizeof(wrqu)); - wrqu.data.length = strlen(buf); - wireless_send_event(ar->arNetDev, IWEVCUSTOM, &wrqu, buf); - } - - if (assocRespLen && (sizeof(buf) > (12 + (assocRespLen * 2)))) - { - assoc_resp_ie_pos = beaconIeLen + assocReqLen + - sizeof(A_UINT16) + /* capinfo*/ - sizeof(A_UINT16) + /* status Code */ - sizeof(A_UINT16) ; /* associd */ - A_MEMZERO(buf, sizeof(buf)); - sprintf(buf, "%s", tag2); - pos = buf + 12; - AR_DEBUG_PRINTF("\nAssocRespIEs= "); - /* - * The Association Response Frame w.o. the WLAN header is delivered to - * the host, so skip over to the IEs - */ - for (i = assoc_resp_ie_pos; i < assoc_resp_ie_pos + assocRespLen - 6; i++) - { - AR_DEBUG_PRINTF("%2.2x ", assocInfo[i]); - sprintf(pos, "%2.2x", assocInfo[i]); - pos += 2; - } - AR_DEBUG_PRINTF("\n"); - - A_MEMZERO(&wrqu, sizeof(wrqu)); - wrqu.data.length = strlen(buf); - wireless_send_event(ar->arNetDev, IWEVCUSTOM, &wrqu, buf); - } - - if (assocReqLen && (sizeof(buf) > (17 + (assocReqLen * 2)))) { - /* - * assoc Request includes capability and listen interval. Skip these. - */ - assoc_req_ie_pos = beaconIeLen + - sizeof(A_UINT16) + /* capinfo*/ - sizeof(A_UINT16); /* listen interval */ - - A_MEMZERO(buf, sizeof(buf)); - sprintf(buf, "%s", tag1); - pos = buf + 17; - AR_DEBUG_PRINTF("AssocReqIEs= "); - for (i = assoc_req_ie_pos; i < assoc_req_ie_pos + assocReqLen - 4; i++) { - AR_DEBUG_PRINTF("%2.2x ", assocInfo[i]); - sprintf(pos, "%2.2x", assocInfo[i]); - pos += 2;; - } - AR_DEBUG_PRINTF("\n"); - - A_MEMZERO(&wrqu, sizeof(wrqu)); - wrqu.data.length = strlen(buf); - wireless_send_event(ar->arNetDev, IWEVCUSTOM, &wrqu, buf); - } - -#ifdef USER_KEYS - if (ar->user_savedkeys_stat == USER_SAVEDKEYS_STAT_RUN && - ar->user_saved_keys.keyOk == TRUE) - { - - key_op_ctrl = KEY_OP_VALID_MASK & ~KEY_OP_INIT_TSC; - if (ar->user_key_ctrl & AR6000_USER_SETKEYS_RSC_UNCHANGED) { - key_op_ctrl &= ~KEY_OP_INIT_RSC; - } else { - key_op_ctrl |= KEY_OP_INIT_RSC; - } - ar6000_reinstall_keys(ar, key_op_ctrl); - } -#endif /* USER_KEYS */ - - /* flush data queues */ - ar6000_TxDataCleanup(ar); - - netif_start_queue(ar->arNetDev); - - if ((OPEN_AUTH == ar->arDot11AuthMode) && - (NONE_AUTH == ar->arAuthMode) && - (WEP_CRYPT == ar->arPairwiseCrypto)) - { - if (!ar->arConnected) { - ar6000_install_static_wep_keys(ar); - } - } - - ar->arConnected = TRUE; - ar->arConnectPending = FALSE; - - reconnect_flag = 0; - - A_MEMZERO(&wrqu, sizeof(wrqu)); - A_MEMCPY(wrqu.addr.sa_data, bssid, IEEE80211_ADDR_LEN); - wrqu.addr.sa_family = ARPHRD_ETHER; - wireless_send_event(ar->arNetDev, SIOCGIWAP, &wrqu, NULL); - if ((ar->arNetworkType == ADHOC_NETWORK) && ar->arIbssPsEnable) { - A_MEMZERO(ar->arNodeMap, sizeof(ar->arNodeMap)); - ar->arNodeNum = 0; - ar->arNexEpId = ENDPOINT_2; - } - -} - -void ar6000_set_numdataendpts(AR_SOFTC_T *ar, A_UINT32 num) -{ - A_ASSERT(num <= (HTC_MAILBOX_NUM_MAX - 1)); - ar->arNumDataEndPts = num; -} - -void -ar6000_disconnect_event(AR_SOFTC_T *ar, A_UINT8 reason, A_UINT8 *bssid, - A_UINT8 assocRespLen, A_UINT8 *assocInfo, A_UINT16 protocolReasonStatus) -{ - A_UINT8 i; - - A_PRINTF("AR6000 disconnected"); - if (bssid[0] || bssid[1] || bssid[2] || bssid[3] || bssid[4] || bssid[5]) { - A_PRINTF(" from %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x ", - bssid[0], bssid[1], bssid[2], bssid[3], bssid[4], bssid[5]); - } - A_PRINTF("\n"); - - AR_DEBUG_PRINTF("\nDisconnect Reason is %d", reason); - AR_DEBUG_PRINTF("\nProtocol Reason/Status Code is %d", protocolReasonStatus); - AR_DEBUG_PRINTF("\nAssocResp Frame = %s", - assocRespLen ? " " : "NULL"); - for (i = 0; i < assocRespLen; i++) { - if (!(i % 0x10)) { - AR_DEBUG_PRINTF("\n"); - } - AR_DEBUG_PRINTF("%2.2x ", assocInfo[i]); - } - AR_DEBUG_PRINTF("\n"); - /* - * If the event is due to disconnect cmd from the host, only they the target - * would stop trying to connect. Under any other condition, target would - * keep trying to connect. - * - */ - if( reason == DISCONNECT_CMD) - { - ar->arConnectPending = FALSE; - } else { - ar->arConnectPending = TRUE; - if (((reason == ASSOC_FAILED) && (protocolReasonStatus == 0x11)) || - ((reason == ASSOC_FAILED) && (protocolReasonStatus == 0x0) && (reconnect_flag == 1))) { - ar->arConnected = TRUE; - return; - } - } - ar->arConnected = FALSE; - - if( (reason != CSERV_DISCONNECT) || (reconnect_flag != 1) ) { - reconnect_flag = 0; - } - -#ifdef USER_KEYS - if (reason != CSERV_DISCONNECT) - { - ar->user_savedkeys_stat = USER_SAVEDKEYS_STAT_INIT; - ar->user_key_ctrl = 0; - } -#endif /* USER_KEYS */ - - netif_stop_queue(ar->arNetDev); - A_MEMZERO(ar->arBssid, sizeof(ar->arBssid)); - ar->arBssChannel = 0; - ar->arBeaconInterval = 0; - - ar6000_TxDataCleanup(ar); -} - -void -ar6000_regDomain_event(AR_SOFTC_T *ar, A_UINT32 regCode) -{ - A_PRINTF("AR6000 Reg Code = 0x%x\n", regCode); - ar->arRegCode = regCode; -} - -void -ar6000_neighborReport_event(AR_SOFTC_T *ar, int numAps, WMI_NEIGHBOR_INFO *info) -{ - static const char *tag = "PRE-AUTH"; - char buf[128]; - union iwreq_data wrqu; - int i; - - AR_DEBUG_PRINTF("AR6000 Neighbor Report Event\n"); - for (i=0; i < numAps; info++, i++) { - AR_DEBUG_PRINTF("bssid %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x ", - info->bssid[0], info->bssid[1], info->bssid[2], - info->bssid[3], info->bssid[4], info->bssid[5]); - if (info->bssFlags & WMI_PREAUTH_CAPABLE_BSS) { - AR_DEBUG_PRINTF("preauth-cap"); - } - if (info->bssFlags & WMI_PMKID_VALID_BSS) { - AR_DEBUG_PRINTF(" pmkid-valid\n"); - continue; /* we skip bss if the pmkid is already valid */ - } - AR_DEBUG_PRINTF("\n"); - snprintf(buf, sizeof(buf), "%s%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x", - tag, - info->bssid[0], info->bssid[1], info->bssid[2], - info->bssid[3], info->bssid[4], info->bssid[5], - i, info->bssFlags); - A_MEMZERO(&wrqu, sizeof(wrqu)); - wrqu.data.length = strlen(buf); - wireless_send_event(ar->arNetDev, IWEVCUSTOM, &wrqu, buf); - } -} - -void -ar6000_tkip_micerr_event(AR_SOFTC_T *ar, A_UINT8 keyid, A_BOOL ismcast) -{ - static const char *tag = "MLME-MICHAELMICFAILURE.indication"; - char buf[128]; - union iwreq_data wrqu; - - A_PRINTF("AR6000 TKIP MIC error received for keyid %d %scast\n", - keyid, ismcast ? "multi": "uni"); - snprintf(buf, sizeof(buf), "%s(keyid=%d %scat)", tag, keyid, - ismcast ? "multi" : "uni"); - memset(&wrqu, 0, sizeof(wrqu)); - wrqu.data.length = strlen(buf); - wireless_send_event(ar->arNetDev, IWEVCUSTOM, &wrqu, buf); -} - -void -ar6000_scanComplete_event(AR_SOFTC_T *ar, A_STATUS status) -{ - AR_DEBUG_PRINTF("AR6000 scan complete: %d\n", status); - - ar->scan_complete = 1; - wake_up_interruptible(&ar6000_scan_queue); -} - -void -ar6000_targetStats_event(AR_SOFTC_T *ar, WMI_TARGET_STATS *pTarget) -{ - TARGET_STATS *pStats = &ar->arTargetStats; - A_UINT8 ac; - - /*A_PRINTF("AR6000 updating target stats\n");*/ - pStats->tx_packets += pTarget->txrxStats.tx_stats.tx_packets; - pStats->tx_bytes += pTarget->txrxStats.tx_stats.tx_bytes; - pStats->tx_unicast_pkts += pTarget->txrxStats.tx_stats.tx_unicast_pkts; - pStats->tx_unicast_bytes += pTarget->txrxStats.tx_stats.tx_unicast_bytes; - pStats->tx_multicast_pkts += pTarget->txrxStats.tx_stats.tx_multicast_pkts; - pStats->tx_multicast_bytes += pTarget->txrxStats.tx_stats.tx_multicast_bytes; - pStats->tx_broadcast_pkts += pTarget->txrxStats.tx_stats.tx_broadcast_pkts; - pStats->tx_broadcast_bytes += pTarget->txrxStats.tx_stats.tx_broadcast_bytes; - pStats->tx_rts_success_cnt += pTarget->txrxStats.tx_stats.tx_rts_success_cnt; - for(ac = 0; ac < WMM_NUM_AC; ac++) - pStats->tx_packet_per_ac[ac] += pTarget->txrxStats.tx_stats.tx_packet_per_ac[ac]; - pStats->tx_errors += pTarget->txrxStats.tx_stats.tx_errors; - pStats->tx_failed_cnt += pTarget->txrxStats.tx_stats.tx_failed_cnt; - pStats->tx_retry_cnt += pTarget->txrxStats.tx_stats.tx_retry_cnt; - pStats->tx_rts_fail_cnt += pTarget->txrxStats.tx_stats.tx_rts_fail_cnt; - pStats->tx_unicast_rate = wmi_get_rate(pTarget->txrxStats.tx_stats.tx_unicast_rate); - - pStats->rx_packets += pTarget->txrxStats.rx_stats.rx_packets; - pStats->rx_bytes += pTarget->txrxStats.rx_stats.rx_bytes; - pStats->rx_unicast_pkts += pTarget->txrxStats.rx_stats.rx_unicast_pkts; - pStats->rx_unicast_bytes += pTarget->txrxStats.rx_stats.rx_unicast_bytes; - pStats->rx_multicast_pkts += pTarget->txrxStats.rx_stats.rx_multicast_pkts; - pStats->rx_multicast_bytes += pTarget->txrxStats.rx_stats.rx_multicast_bytes; - pStats->rx_broadcast_pkts += pTarget->txrxStats.rx_stats.rx_broadcast_pkts; - pStats->rx_broadcast_bytes += pTarget->txrxStats.rx_stats.rx_broadcast_bytes; - pStats->rx_fragment_pkt += pTarget->txrxStats.rx_stats.rx_fragment_pkt; - pStats->rx_errors += pTarget->txrxStats.rx_stats.rx_errors; - pStats->rx_crcerr += pTarget->txrxStats.rx_stats.rx_crcerr; - pStats->rx_key_cache_miss += pTarget->txrxStats.rx_stats.rx_key_cache_miss; - pStats->rx_decrypt_err += pTarget->txrxStats.rx_stats.rx_decrypt_err; - pStats->rx_duplicate_frames += pTarget->txrxStats.rx_stats.rx_duplicate_frames; - pStats->rx_unicast_rate = wmi_get_rate(pTarget->txrxStats.rx_stats.rx_unicast_rate); - - - pStats->tkip_local_mic_failure - += pTarget->txrxStats.tkipCcmpStats.tkip_local_mic_failure; - pStats->tkip_counter_measures_invoked - += pTarget->txrxStats.tkipCcmpStats.tkip_counter_measures_invoked; - pStats->tkip_replays += pTarget->txrxStats.tkipCcmpStats.tkip_replays; - pStats->tkip_format_errors += pTarget->txrxStats.tkipCcmpStats.tkip_format_errors; - pStats->ccmp_format_errors += pTarget->txrxStats.tkipCcmpStats.ccmp_format_errors; - pStats->ccmp_replays += pTarget->txrxStats.tkipCcmpStats.ccmp_replays; - - - pStats->power_save_failure_cnt += pTarget->pmStats.power_save_failure_cnt; - pStats->noise_floor_calibation = pTarget->noise_floor_calibation; - - pStats->cs_bmiss_cnt += pTarget->cservStats.cs_bmiss_cnt; - pStats->cs_lowRssi_cnt += pTarget->cservStats.cs_lowRssi_cnt; - pStats->cs_connect_cnt += pTarget->cservStats.cs_connect_cnt; - pStats->cs_disconnect_cnt += pTarget->cservStats.cs_disconnect_cnt; - pStats->cs_aveBeacon_snr = pTarget->cservStats.cs_aveBeacon_snr; - pStats->cs_aveBeacon_rssi = pTarget->cservStats.cs_aveBeacon_rssi; - pStats->cs_lastRoam_msec = pTarget->cservStats.cs_lastRoam_msec; - pStats->cs_snr = pTarget->cservStats.cs_snr; - pStats->cs_rssi = pTarget->cservStats.cs_rssi; - - pStats->lq_val = pTarget->lqVal; - - pStats->wow_num_pkts_dropped += pTarget->wowStats.wow_num_pkts_dropped; - pStats->wow_num_host_pkt_wakeups += pTarget->wowStats.wow_num_host_pkt_wakeups; - pStats->wow_num_host_event_wakeups += pTarget->wowStats.wow_num_host_event_wakeups; - pStats->wow_num_events_discarded += pTarget->wowStats.wow_num_events_discarded; - - ar->statsUpdatePending = FALSE; - wake_up(&arEvent); -} - -void -ar6000_rssiThreshold_event(AR_SOFTC_T *ar, WMI_RSSI_THRESHOLD_VAL newThreshold, A_INT16 rssi) -{ - USER_RSSI_THOLD userRssiThold; - - userRssiThold.tag = rssi_map[newThreshold].tag; - userRssiThold.rssi = rssi; - AR_DEBUG2_PRINTF("rssi Threshold range = %d tag = %d rssi = %d\n", newThreshold, userRssiThold.tag, rssi); -#ifdef SEND_EVENT_TO_APP - ar6000_send_event_to_app(ar, WMI_RSSI_THRESHOLD_EVENTID,(A_UINT8 *)&userRssiThold, sizeof(USER_RSSI_THOLD)); -#endif -} - - -void -ar6000_hbChallengeResp_event(AR_SOFTC_T *ar, A_UINT32 cookie, A_UINT32 source) -{ - if (source == APP_HB_CHALLENGE) { - /* Report it to the app in case it wants a positive acknowledgement */ -#ifdef SEND_EVENT_TO_APP - ar6000_send_event_to_app(ar, WMIX_HB_CHALLENGE_RESP_EVENTID, - (A_UINT8 *)&cookie, sizeof(cookie)); -#endif - } else { - /* This would ignore the replys that come in after their due time */ - if (cookie == ar->arHBChallengeResp.seqNum) { - ar->arHBChallengeResp.outstanding = FALSE; - } - } -} - - -void -ar6000_reportError_event(AR_SOFTC_T *ar, WMI_TARGET_ERROR_VAL errorVal) -{ - char *errString[] = { - [WMI_TARGET_PM_ERR_FAIL] "WMI_TARGET_PM_ERR_FAIL", - [WMI_TARGET_KEY_NOT_FOUND] "WMI_TARGET_KEY_NOT_FOUND", - [WMI_TARGET_DECRYPTION_ERR] "WMI_TARGET_DECRYPTION_ERR", - [WMI_TARGET_BMISS] "WMI_TARGET_BMISS", - [WMI_PSDISABLE_NODE_JOIN] "WMI_PSDISABLE_NODE_JOIN" - }; - - A_PRINTF("AR6000 Error on Target. Error = 0x%x\n", errorVal); - - /* One error is reported at a time, and errorval is a bitmask */ - if(errorVal & (errorVal - 1)) - return; - - A_PRINTF("AR6000 Error type = "); - switch(errorVal) - { - case WMI_TARGET_PM_ERR_FAIL: - case WMI_TARGET_KEY_NOT_FOUND: - case WMI_TARGET_DECRYPTION_ERR: - case WMI_TARGET_BMISS: - case WMI_PSDISABLE_NODE_JOIN: - A_PRINTF("%s\n", errString[errorVal]); - break; - default: - A_PRINTF("INVALID\n"); - break; - } - -} - - -void -ar6000_cac_event(AR_SOFTC_T *ar, A_UINT8 ac, A_UINT8 cacIndication, - A_UINT8 statusCode, A_UINT8 *tspecSuggestion) -{ - WMM_TSPEC_IE *tspecIe; - - /* - * This is the TSPEC IE suggestion from AP. - * Suggestion provided by AP under some error - * cases, could be helpful for the host app. - * Check documentation. - */ - tspecIe = (WMM_TSPEC_IE *)tspecSuggestion; - - /* - * What do we do, if we get TSPEC rejection? One thought - * that comes to mind is implictly delete the pstream... - */ - A_PRINTF("AR6000 CAC notification. " - "AC = %d, cacIndication = 0x%x, statusCode = 0x%x\n", - ac, cacIndication, statusCode); -} - -#define AR6000_PRINT_BSSID(_pBss) do { \ - A_PRINTF("%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x ",\ - (_pBss)[0],(_pBss)[1],(_pBss)[2],(_pBss)[3],\ - (_pBss)[4],(_pBss)[5]); \ -} while(0) - -void -ar6000_roam_tbl_event(AR_SOFTC_T *ar, WMI_TARGET_ROAM_TBL *pTbl) -{ - A_UINT8 i; - - A_PRINTF("ROAM TABLE NO OF ENTRIES is %d ROAM MODE is %d\n", - pTbl->numEntries, pTbl->roamMode); - for (i= 0; i < pTbl->numEntries; i++) { - A_PRINTF("[%d]bssid %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x ", i, - pTbl->bssRoamInfo[i].bssid[0], pTbl->bssRoamInfo[i].bssid[1], - pTbl->bssRoamInfo[i].bssid[2], - pTbl->bssRoamInfo[i].bssid[3], - pTbl->bssRoamInfo[i].bssid[4], - pTbl->bssRoamInfo[i].bssid[5]); - A_PRINTF("RSSI %d RSSIDT %d LAST RSSI %d UTIL %d ROAM_UTIL %d" - " BIAS %d\n", - pTbl->bssRoamInfo[i].rssi, - pTbl->bssRoamInfo[i].rssidt, - pTbl->bssRoamInfo[i].last_rssi, - pTbl->bssRoamInfo[i].util, - pTbl->bssRoamInfo[i].roam_util, - pTbl->bssRoamInfo[i].bias); - } -} - -void -ar6000_wow_list_event(struct ar6_softc *ar, A_UINT8 num_filters, WMI_GET_WOW_LIST_REPLY *wow_reply) -{ - A_UINT8 i,j; - - /*Each event now contains exactly one filter, see bug 26613*/ - A_PRINTF("WOW pattern %d of %d patterns\n", wow_reply->this_filter_num, wow_reply->num_filters); - A_PRINTF("wow mode = %s host mode = %s\n", - (wow_reply->wow_mode == 0? "disabled":"enabled"), - (wow_reply->host_mode == 1 ? "awake":"asleep")); - - - /*If there are no patterns, the reply will only contain generic - WoW information. Pattern information will exist only if there are - patterns present. Bug 26716*/ - - /* If this event contains pattern information, display it*/ - if (wow_reply->this_filter_num) { - i=0; - A_PRINTF("id=%d size=%d offset=%d\n", - wow_reply->wow_filters[i].wow_filter_id, - wow_reply->wow_filters[i].wow_filter_size, - wow_reply->wow_filters[i].wow_filter_offset); - A_PRINTF("wow pattern = "); - for (j=0; j< wow_reply->wow_filters[i].wow_filter_size; j++) { - A_PRINTF("%2.2x",wow_reply->wow_filters[i].wow_filter_pattern[j]); - } - - A_PRINTF("\nwow mask = "); - for (j=0; j< wow_reply->wow_filters[i].wow_filter_size; j++) { - A_PRINTF("%2.2x",wow_reply->wow_filters[i].wow_filter_mask[j]); - } - A_PRINTF("\n"); - } -} - -/* - * Report the Roaming related data collected on the target - */ -void -ar6000_display_roam_time(WMI_TARGET_ROAM_TIME *p) -{ - A_PRINTF("Disconnect Data : BSSID: "); - AR6000_PRINT_BSSID(p->disassoc_bssid); - A_PRINTF(" RSSI %d DISASSOC Time %d NO_TXRX_TIME %d\n", - p->disassoc_bss_rssi,p->disassoc_time, - p->no_txrx_time); - A_PRINTF("Connect Data: BSSID: "); - AR6000_PRINT_BSSID(p->assoc_bssid); - A_PRINTF(" RSSI %d ASSOC Time %d TXRX_TIME %d\n", - p->assoc_bss_rssi,p->assoc_time, - p->allow_txrx_time); - A_PRINTF("Last Data Tx Time (b4 Disassoc) %d "\ - "First Data Tx Time (after Assoc) %d\n", - p->last_data_txrx_time, p->first_data_txrx_time); -} - -void -ar6000_roam_data_event(AR_SOFTC_T *ar, WMI_TARGET_ROAM_DATA *p) -{ - switch (p->roamDataType) { - case ROAM_DATA_TIME: - ar6000_display_roam_time(&p->u.roamTime); - break; - default: - break; - } -} - -void -ar6000_bssInfo_event_rx(AR_SOFTC_T *ar, A_UINT8 *datap, int len) -{ - struct sk_buff *skb; - WMI_BSS_INFO_HDR *bih = (WMI_BSS_INFO_HDR *)datap; - - - if (!ar->arMgmtFilter) { - return; - } - if (((ar->arMgmtFilter & IEEE80211_FILTER_TYPE_BEACON) && - (bih->frameType != BEACON_FTYPE)) || - ((ar->arMgmtFilter & IEEE80211_FILTER_TYPE_PROBE_RESP) && - (bih->frameType != PROBERESP_FTYPE))) - { - return; - } - - if ((skb = A_NETBUF_ALLOC_RAW(len)) != NULL) { - - A_NETBUF_PUT(skb, len); - A_MEMCPY(A_NETBUF_DATA(skb), datap, len); - skb->dev = ar->arNetDev; - printk("MAC RAW...\n"); -// skb->mac.raw = A_NETBUF_DATA(skb); - skb->ip_summed = CHECKSUM_NONE; - skb->pkt_type = PACKET_OTHERHOST; - skb->protocol = __constant_htons(0x0019); - netif_rx(skb); - } -} - -A_UINT32 wmiSendCmdNum; - -A_STATUS -ar6000_control_tx(void *devt, void *osbuf, WMI_PRI_STREAM_ID streamID) -{ - AR_SOFTC_T *ar = (AR_SOFTC_T *)devt; - A_STATUS status = A_OK; - struct ar_cookie *cookie = NULL; - int i; - - /* take lock to protect ar6000_alloc_cookie() */ - AR6000_SPIN_LOCK(&ar->arLock, 0); - - do { - - AR_DEBUG2_PRINTF("ar_contrstatus = ol_tx: skb=0x%x, len=0x%x, sid=%d\n", - (A_UINT32)osbuf, A_NETBUF_LEN(osbuf), streamID); - - if ((streamID == WMI_CONTROL_PRI) && (ar->arWMIControlEpFull)) { - /* control endpoint is full, don't allocate resources, we - * are just going to drop this packet */ - cookie = NULL; - AR_DEBUG_PRINTF(" WMI Control EP full, dropping packet : 0x%X, len:%d \n", - (A_UINT32)osbuf, A_NETBUF_LEN(osbuf)); - } else { - cookie = ar6000_alloc_cookie(ar); - } - - if (cookie == NULL) { - status = A_NO_MEMORY; - break; - } - - if(logWmiRawMsgs) { - A_PRINTF("WMI cmd send, msgNo %d :", wmiSendCmdNum); - for(i = 0; i < a_netbuf_to_len(osbuf); i++) - A_PRINTF("%x ", ((A_UINT8 *)a_netbuf_to_data(osbuf))[i]); - A_PRINTF("\n"); - } - - wmiSendCmdNum++; - - } while (FALSE); - - if (cookie != NULL) { - /* got a structure to send it out on */ - ar->arTxPending[streamID]++; - - if (streamID != WMI_CONTROL_PRI) { - ar->arTotalTxDataPending++; - } - } - - AR6000_SPIN_UNLOCK(&ar->arLock, 0); - - if (cookie != NULL) { - cookie->arc_bp[0] = (A_UINT32)osbuf; - cookie->arc_bp[1] = 0; - SET_HTC_PACKET_INFO_TX(&cookie->HtcPkt, - cookie, - A_NETBUF_DATA(osbuf), - A_NETBUF_LEN(osbuf), - arWMIStream2EndpointID(ar,streamID), - AR6K_CONTROL_PKT_TAG); - /* this interface is asynchronous, if there is an error, cleanup will happen in the - * TX completion callback */ - HTCSendPkt(ar->arHtcTarget, &cookie->HtcPkt); - status = A_OK; - } - - return status; -} - -/* indicate tx activity or inactivity on a WMI stream */ -void ar6000_indicate_tx_activity(void *devt, A_UINT8 TrafficClass, A_BOOL Active) -{ - AR_SOFTC_T *ar = (AR_SOFTC_T *)devt; - WMI_PRI_STREAM_ID streamid; - - if (ar->arWmiEnabled) { - streamid = wmi_get_stream_id(ar->arWmi, TrafficClass); - } else { - /* for mbox ping testing, the traffic class is mapped directly as a stream ID, - * see handling of AR6000_XIOCTL_TRAFFIC_ACTIVITY_CHANGE in ioctl.c */ - streamid = (WMI_PRI_STREAM_ID)TrafficClass; - } - - /* notify HTC, this may cause credit distribution changes */ - - HTCIndicateActivityChange(ar->arHtcTarget, - arWMIStream2EndpointID(ar,streamid), - Active); - -} - -module_init(ar6000_init_module); -module_exit(ar6000_cleanup_module); - -/* Init cookie queue */ -static void -ar6000_cookie_init(AR_SOFTC_T *ar) -{ - A_UINT32 i; - - ar->arCookieList = NULL; - A_MEMZERO(s_ar_cookie_mem, sizeof(s_ar_cookie_mem)); - - for (i = 0; i < MAX_COOKIE_NUM; i++) { - ar6000_free_cookie(ar, &s_ar_cookie_mem[i]); - } -} - -/* cleanup cookie queue */ -static void -ar6000_cookie_cleanup(AR_SOFTC_T *ar) -{ - /* It is gone .... */ - ar->arCookieList = NULL; -} - -/* Init cookie queue */ -static void -ar6000_free_cookie(AR_SOFTC_T *ar, struct ar_cookie * cookie) -{ - /* Insert first */ - A_ASSERT(ar != NULL); - A_ASSERT(cookie != NULL); - cookie->arc_list_next = ar->arCookieList; - ar->arCookieList = cookie; -} - -/* cleanup cookie queue */ -static struct ar_cookie * -ar6000_alloc_cookie(AR_SOFTC_T *ar) -{ - struct ar_cookie *cookie; - - cookie = ar->arCookieList; - if(cookie != NULL) - { - ar->arCookieList = cookie->arc_list_next; - } - - return cookie; -} - -#ifdef SEND_EVENT_TO_APP -/* - * This function is used to send event which come from taget to - * the application. The buf which send to application is include - * the event ID and event content. - */ -#define EVENT_ID_LEN 2 -void ar6000_send_event_to_app(AR_SOFTC_T *ar, A_UINT16 eventId, - A_UINT8 *datap, int len) -{ - -#if (WIRELESS_EXT >= 15) - -/* note: IWEVCUSTOM only exists in wireless extensions after version 15 */ - - char *buf; - A_UINT16 size; - union iwreq_data wrqu; - - size = len + EVENT_ID_LEN; - - if (size > IW_CUSTOM_MAX) { - AR_DEBUG_PRINTF("WMI event ID : 0x%4.4X, len = %d too big for IWEVCUSTOM (max=%d) \n", - eventId, size, IW_CUSTOM_MAX); - return; - } - - buf = A_MALLOC_NOWAIT(size); - A_MEMZERO(buf, size); - A_MEMCPY(buf, &eventId, EVENT_ID_LEN); - A_MEMCPY(buf+EVENT_ID_LEN, datap, len); - - //AR_DEBUG_PRINTF("event ID = %d,len = %d\n",*(A_UINT16*)buf, size); - A_MEMZERO(&wrqu, sizeof(wrqu)); - wrqu.data.length = size; - wireless_send_event(ar->arNetDev, IWEVCUSTOM, &wrqu, buf); - - A_FREE(buf); -#endif - - -} -#endif - - -void -ar6000_tx_retry_err_event(void *devt) -{ - AR_DEBUG2_PRINTF("Tx retries reach maximum!\n"); -} - -void -ar6000_snrThresholdEvent_rx(void *devt, WMI_SNR_THRESHOLD_VAL newThreshold, A_UINT8 snr) -{ - AR_DEBUG2_PRINTF("snr threshold range %d, snr %d\n", newThreshold, snr); -} - -void -ar6000_lqThresholdEvent_rx(void *devt, WMI_LQ_THRESHOLD_VAL newThreshold, A_UINT8 lq) -{ - AR_DEBUG2_PRINTF("lq threshold range %d, lq %d\n", newThreshold, lq); -} - - - -A_UINT32 -a_copy_to_user(void *to, const void *from, A_UINT32 n) -{ - return(copy_to_user(to, from, n)); -} - -A_UINT32 -a_copy_from_user(void *to, const void *from, A_UINT32 n) -{ - return(copy_from_user(to, from, n)); -} - - -A_STATUS -ar6000_get_driver_cfg(struct net_device *dev, - A_UINT16 cfgParam, - void *result) -{ - - A_STATUS ret = 0; - - switch(cfgParam) - { - case AR6000_DRIVER_CFG_GET_WLANNODECACHING: - *((A_UINT32 *)result) = wlanNodeCaching; - break; - case AR6000_DRIVER_CFG_LOG_RAW_WMI_MSGS: - *((A_UINT32 *)result) = logWmiRawMsgs; - break; - default: - ret = EINVAL; - break; - } - - return ret; -} - -void -ar6000_keepalive_rx(void *devt, A_UINT8 configured) -{ - AR_SOFTC_T *ar = (AR_SOFTC_T *)devt; - - ar->arKeepaliveConfigured = configured; - wake_up(&arEvent); -} - -void -ar6000_pmkid_list_event(void *devt, A_UINT8 numPMKID, WMI_PMKID *pmkidList) -{ - A_UINT8 i, j; - - A_PRINTF("Number of Cached PMKIDs is %d\n", numPMKID); - - for (i = 0; i < numPMKID; i++) { - A_PRINTF("\nPMKID %d ", i); - for (j = 0; j < WMI_PMKID_LEN; j++) { - A_PRINTF("%2.2x", pmkidList->pmkid[j]); - } - pmkidList++; - } -} - -#ifdef USER_KEYS -static A_STATUS - -ar6000_reinstall_keys(AR_SOFTC_T *ar, A_UINT8 key_op_ctrl) -{ - A_STATUS status = A_OK; - struct ieee80211req_key *uik = &ar->user_saved_keys.ucast_ik; - struct ieee80211req_key *bik = &ar->user_saved_keys.bcast_ik; - CRYPTO_TYPE keyType = ar->user_saved_keys.keyType; - - if (IEEE80211_CIPHER_CCKM_KRK != uik->ik_type) { - if (NONE_CRYPT == keyType) { - goto _reinstall_keys_out; - } - - if (uik->ik_keylen) { - status = wmi_addKey_cmd(ar->arWmi, uik->ik_keyix, - ar->user_saved_keys.keyType, PAIRWISE_USAGE, - uik->ik_keylen, (A_UINT8 *)&uik->ik_keyrsc, - uik->ik_keydata, key_op_ctrl, SYNC_BEFORE_WMIFLAG); - } - - } else { - status = wmi_add_krk_cmd(ar->arWmi, uik->ik_keydata); - } - - if (IEEE80211_CIPHER_CCKM_KRK != bik->ik_type) { - if (NONE_CRYPT == keyType) { - goto _reinstall_keys_out; - } - - if (bik->ik_keylen) { - status = wmi_addKey_cmd(ar->arWmi, bik->ik_keyix, - ar->user_saved_keys.keyType, GROUP_USAGE, - bik->ik_keylen, (A_UINT8 *)&bik->ik_keyrsc, - bik->ik_keydata, key_op_ctrl, NO_SYNC_WMIFLAG); - } - } else { - status = wmi_add_krk_cmd(ar->arWmi, bik->ik_keydata); - } - -_reinstall_keys_out: - ar->user_savedkeys_stat = USER_SAVEDKEYS_STAT_INIT; - ar->user_key_ctrl = 0; - - return status; -} -#endif /* USER_KEYS */ - - -void -ar6000_dset_open_req( - void *context, - A_UINT32 id, - A_UINT32 targHandle, - A_UINT32 targReplyFn, - A_UINT32 targReplyArg) -{ -} - -void -ar6000_dset_close( - void *context, - A_UINT32 access_cookie) -{ - return; -} - -void -ar6000_dset_data_req( - void *context, - A_UINT32 accessCookie, - A_UINT32 offset, - A_UINT32 length, - A_UINT32 targBuf, - A_UINT32 targReplyFn, - A_UINT32 targReplyArg) -{ -} diff --git a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/ar6000/ar6000_drv.h b/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/ar6000/ar6000_drv.h deleted file mode 100644 index 784f158d9..000000000 --- a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/ar6000/ar6000_drv.h +++ /dev/null @@ -1,360 +0,0 @@ -/* - * - * Copyright (c) 2004-2007 Atheros Communications Inc. - * All rights reserved. - * - * - * 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; - * - * Software distributed under the License is distributed on an "AS - * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or - * implied. See the License for the specific language governing - * rights and limitations under the License. - * - * - * - */ - -#ifndef _AR6000_H_ -#define _AR6000_H_ - -#include - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include "a_types.h" -#include "a_osapi.h" -#include "htc_api.h" -#include "wmi.h" -#include "a_drv.h" -#include "bmi.h" -#include -#include -#include -#include -#include "gpio_api.h" -#include "gpio.h" -#include -#include -#include -#include -#include "AR6Khwreg.h" -#include "ar6000_api.h" -#ifdef CONFIG_HOST_TCMD_SUPPORT -#include -#endif - -#include "targaddrs.h" -#include "dbglog_api.h" -#include "ar6000_diag.h" -#include "common_drv.h" - -#ifndef __dev_put -#define __dev_put(dev) dev_put(dev) -#endif - -#ifdef USER_KEYS - -#define USER_SAVEDKEYS_STAT_INIT 0 -#define USER_SAVEDKEYS_STAT_RUN 1 - -// TODO this needs to move into the AR_SOFTC struct -struct USER_SAVEDKEYS { - struct ieee80211req_key ucast_ik; - struct ieee80211req_key bcast_ik; - CRYPTO_TYPE keyType; - A_BOOL keyOk; -}; -#endif - -#define DBG_INFO 0x00000001 -#define DBG_ERROR 0x00000002 -#define DBG_WARNING 0x00000004 -#define DBG_SDIO 0x00000008 -#define DBG_HIF 0x00000010 -#define DBG_HTC 0x00000020 -#define DBG_WMI 0x00000040 -#define DBG_WMI2 0x00000080 -#define DBG_DRIVER 0x00000100 - -#define DBG_DEFAULTS (DBG_ERROR|DBG_WARNING) - - -#ifdef DEBUG -#define AR_DEBUG_PRINTF(args...) if (debugdriver) A_PRINTF(args); -#define AR_DEBUG2_PRINTF(args...) if (debugdriver >= 2) A_PRINTF(args); -extern int debugdriver; -#else -#define AR_DEBUG_PRINTF(args...) -#define AR_DEBUG2_PRINTF(args...) -#endif - -A_STATUS ar6000_ReadRegDiag(HIF_DEVICE *hifDevice, A_UINT32 *address, A_UINT32 *data); -A_STATUS ar6000_WriteRegDiag(HIF_DEVICE *hifDevice, A_UINT32 *address, A_UINT32 *data); - -#ifdef __cplusplus -extern "C" { -#endif - -#define MAX_AR6000 1 -#define AR6000_MAX_RX_BUFFERS 16 -#define AR6000_BUFFER_SIZE 1664 -#define AR6000_TX_TIMEOUT 10 -#define AR6000_ETH_ADDR_LEN 6 -#define AR6000_MAX_ENDPOINTS 4 -#define MAX_NODE_NUM 15 -#define MAX_COOKIE_NUM 150 -#define AR6000_HB_CHALLENGE_RESP_FREQ_DEFAULT 1 -#define AR6000_HB_CHALLENGE_RESP_MISS_THRES_DEFAULT 1 - -enum { - DRV_HB_CHALLENGE = 0, - APP_HB_CHALLENGE -}; - -/* HTC RAW streams */ -typedef enum _HTC_RAW_STREAM_ID { - HTC_RAW_STREAM_NOT_MAPPED = -1, - HTC_RAW_STREAM_0 = 0, - HTC_RAW_STREAM_1 = 1, - HTC_RAW_STREAM_2 = 2, - HTC_RAW_STREAM_3 = 3, - HTC_RAW_STREAM_NUM_MAX -} HTC_RAW_STREAM_ID; - -#define RAW_HTC_READ_BUFFERS_NUM 4 -#define RAW_HTC_WRITE_BUFFERS_NUM 4 - -typedef struct { - int currPtr; - int length; - unsigned char data[AR6000_BUFFER_SIZE]; - HTC_PACKET HTCPacket; -} raw_htc_buffer; - -#ifdef CONFIG_HOST_TCMD_SUPPORT -/* - * add TCMD_MODE besides wmi and bypasswmi - * in TCMD_MODE, only few TCMD releated wmi commands - * counld be hanlder - */ -enum { - AR6000_WMI_MODE = 0, - AR6000_BYPASS_MODE, - AR6000_TCMD_MODE, - AR6000_WLAN_MODE -}; -#endif /* CONFIG_HOST_TCMD_SUPPORT */ - -struct ar_wep_key { - A_UINT8 arKeyIndex; - A_UINT8 arKeyLen; - A_UINT8 arKey[64]; -} ; - -struct ar_node_mapping { - A_UINT8 macAddress[6]; - A_UINT8 epId; - A_UINT8 txPending; -}; - -struct ar_cookie { - A_UINT32 arc_bp[2]; /* Must be first field */ - HTC_PACKET HtcPkt; /* HTC packet wrapper */ - struct ar_cookie *arc_list_next; -}; - -struct ar_hb_chlng_resp { - A_TIMER timer; - A_UINT32 frequency; - A_UINT32 seqNum; - A_BOOL outstanding; - A_UINT8 missCnt; - A_UINT8 missThres; -}; - -typedef struct ar6_softc { - struct net_device *arNetDev; /* net_device pointer */ - void *arWmi; - int arTxPending[WMI_PRI_MAX_COUNT]; - int arTotalTxDataPending; - A_UINT8 arNumDataEndPts; - A_BOOL arWmiEnabled; - A_BOOL arWmiReady; - A_BOOL arConnected; - A_BOOL arRadioSwitch; - HTC_HANDLE arHtcTarget; - void *arHifDevice; - spinlock_t arLock; - struct semaphore arSem; - int arRxBuffers[WMI_PRI_MAX_COUNT]; - int arSsidLen; - u_char arSsid[32]; - A_UINT8 arNetworkType; - A_UINT8 arDot11AuthMode; - A_UINT8 arAuthMode; - A_UINT8 arPairwiseCrypto; - A_UINT8 arPairwiseCryptoLen; - A_UINT8 arGroupCrypto; - A_UINT8 arGroupCryptoLen; - A_UINT8 arDefTxKeyIndex; - struct ar_wep_key arWepKeyList[WMI_MAX_KEY_INDEX + 1]; - A_UINT8 arBssid[6]; - A_UINT8 arReqBssid[6]; - A_UINT16 arChannelHint; - A_UINT16 arBssChannel; - A_UINT16 arListenInterval; - struct ar6000_version arVersion; - A_UINT32 arTargetType; - A_INT8 arRssi; - A_UINT8 arTxPwr; - A_BOOL arTxPwrSet; - A_INT32 arBitRate; - struct net_device_stats arNetStats; - struct iw_statistics arIwStats; - A_INT8 arNumChannels; - A_UINT16 arChannelList[32]; - A_UINT32 arRegCode; - A_BOOL statsUpdatePending; - TARGET_STATS arTargetStats; - A_INT8 arMaxRetries; - A_UINT8 arPhyCapability; -#ifdef CONFIG_HOST_TCMD_SUPPORT - A_UINT8 tcmdRxReport; - A_UINT32 tcmdRxTotalPkt; - A_INT32 tcmdRxRssi; - A_UINT32 tcmdPm; - A_UINT32 arTargetMode; -#endif - AR6000_WLAN_STATE arWlanState; - struct ar_node_mapping arNodeMap[MAX_NODE_NUM]; - A_UINT8 arIbssPsEnable; - A_UINT8 arNodeNum; - A_UINT8 arNexEpId; - struct ar_cookie *arCookieList; - A_UINT16 arRateMask; - A_UINT8 arSkipScan; - A_UINT16 arBeaconInterval; - A_BOOL arConnectPending; - A_BOOL arWmmEnabled; - struct ar_hb_chlng_resp arHBChallengeResp; - A_UINT8 arKeepaliveConfigured; - A_UINT32 arMgmtFilter; - HTC_ENDPOINT_ID arWmi2EpMapping[WMI_PRI_MAX_COUNT]; - WMI_PRI_STREAM_ID arEp2WmiMapping[ENDPOINT_MAX]; -#ifdef HTC_RAW_INTERFACE - HTC_ENDPOINT_ID arRaw2EpMapping[HTC_RAW_STREAM_NUM_MAX]; - HTC_RAW_STREAM_ID arEp2RawMapping[ENDPOINT_MAX]; - struct semaphore raw_htc_read_sem[HTC_RAW_STREAM_NUM_MAX]; - struct semaphore raw_htc_write_sem[HTC_RAW_STREAM_NUM_MAX]; - wait_queue_head_t raw_htc_read_queue[HTC_RAW_STREAM_NUM_MAX]; - wait_queue_head_t raw_htc_write_queue[HTC_RAW_STREAM_NUM_MAX]; - raw_htc_buffer *raw_htc_read_buffer[HTC_RAW_STREAM_NUM_MAX][RAW_HTC_READ_BUFFERS_NUM]; - raw_htc_buffer *raw_htc_write_buffer[HTC_RAW_STREAM_NUM_MAX][RAW_HTC_WRITE_BUFFERS_NUM]; - A_BOOL write_buffer_available[HTC_RAW_STREAM_NUM_MAX]; - A_BOOL read_buffer_available[HTC_RAW_STREAM_NUM_MAX]; -#endif - A_BOOL arRawIfInit; - int arDeviceIndex; - COMMON_CREDIT_STATE_INFO arCreditStateInfo; - A_BOOL arWMIControlEpFull; - A_BOOL dbgLogFetchInProgress; - A_UCHAR log_buffer[DBGLOG_HOST_LOG_BUFFER_SIZE]; - A_UINT32 log_cnt; - A_UINT32 dbglog_init_done; - A_UINT32 arConnectCtrlFlags; - A_UINT32 scan_complete; -#ifdef USER_KEYS - A_INT32 user_savedkeys_stat; - A_UINT32 user_key_ctrl; - struct USER_SAVEDKEYS user_saved_keys; -#endif -} AR_SOFTC_T; - - -#define arWMIStream2EndpointID(ar,wmi) (ar)->arWmi2EpMapping[(wmi)] -#define arSetWMIStream2EndpointIDMap(ar,wmi,ep) \ -{ (ar)->arWmi2EpMapping[(wmi)] = (ep); \ - (ar)->arEp2WmiMapping[(ep)] = (wmi); } -#define arEndpoint2WMIStreamID(ar,ep) (ar)->arEp2WmiMapping[(ep)] - -#define arRawIfEnabled(ar) (ar)->arRawIfInit -#define arRawStream2EndpointID(ar,raw) (ar)->arRaw2EpMapping[(raw)] -#define arSetRawStream2EndpointIDMap(ar,raw,ep) \ -{ (ar)->arRaw2EpMapping[(raw)] = (ep); \ - (ar)->arEp2RawMapping[(ep)] = (raw); } -#define arEndpoint2RawStreamID(ar,ep) (ar)->arEp2RawMapping[(ep)] - -struct ar_giwscan_param { - char *current_ev; - char *end_buf; - A_BOOL firstPass; -}; - -#define AR6000_STAT_INC(ar, stat) (ar->arNetStats.stat++) - -#define AR6000_SPIN_LOCK(lock, param) do { \ - if (irqs_disabled()) { \ - AR_DEBUG_PRINTF("IRQs disabled:AR6000_LOCK\n"); \ - } \ - spin_lock_bh(lock); \ -} while (0) - -#define AR6000_SPIN_UNLOCK(lock, param) do { \ - if (irqs_disabled()) { \ - AR_DEBUG_PRINTF("IRQs disabled: AR6000_UNLOCK\n"); \ - } \ - spin_unlock_bh(lock); \ -} while (0) - -int ar6000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); -int ar6000_ioctl_dispatcher(struct net_device *dev, struct ifreq *rq, int cmd); -void ar6000_ioctl_iwsetup(struct iw_handler_def *def); -void ar6000_gpio_init(void); -void ar6000_init_profile_info(AR_SOFTC_T *ar); -void ar6000_install_static_wep_keys(AR_SOFTC_T *ar); -int ar6000_init(struct net_device *dev); -int ar6000_dbglog_get_debug_logs(AR_SOFTC_T *ar); -A_STATUS ar6000_SetHTCBlockSize(AR_SOFTC_T *ar); - -#ifdef HTC_RAW_INTERFACE - -#ifndef __user -#define __user -#endif - -int ar6000_htc_raw_open(AR_SOFTC_T *ar); -int ar6000_htc_raw_close(AR_SOFTC_T *ar); -ssize_t ar6000_htc_raw_read(AR_SOFTC_T *ar, - HTC_RAW_STREAM_ID StreamID, - char __user *buffer, size_t count); -ssize_t ar6000_htc_raw_write(AR_SOFTC_T *ar, - HTC_RAW_STREAM_ID StreamID, - char __user *buffer, size_t count); - -#endif /* HTC_RAW_INTERFACE */ - -#ifdef __cplusplus -} -#endif - -#endif /* _AR6000_H_ */ diff --git a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/ar6000/ar6000_raw_if.c b/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/ar6000/ar6000_raw_if.c deleted file mode 100644 index 4443bb267..000000000 --- a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/ar6000/ar6000_raw_if.c +++ /dev/null @@ -1,440 +0,0 @@ -/* - * - * Copyright (c) 2004-2007 Atheros Communications Inc. - * All rights reserved. - * - * - * 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; - * - * Software distributed under the License is distributed on an "AS - * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or - * implied. See the License for the specific language governing - * rights and limitations under the License. - * - * - * - */ - -#include "ar6000_drv.h" - -#ifdef HTC_RAW_INTERFACE - -static void -ar6000_htc_raw_read_cb(void *Context, HTC_PACKET *pPacket) -{ - AR_SOFTC_T *ar = (AR_SOFTC_T *)Context; - raw_htc_buffer *busy; - HTC_RAW_STREAM_ID streamID; - - busy = (raw_htc_buffer *)pPacket->pPktContext; - A_ASSERT(busy != NULL); - - if (pPacket->Status == A_ECANCELED) { - /* - * HTC provides A_ECANCELED status when it doesn't want to be refilled - * (probably due to a shutdown) - */ - return; - } - - streamID = arEndpoint2RawStreamID(ar,pPacket->Endpoint); - A_ASSERT(streamID != HTC_RAW_STREAM_NOT_MAPPED); - -#ifdef CF - if (down_trylock(&ar->raw_htc_read_sem[streamID])) { -#else - if (down_interruptible(&ar->raw_htc_read_sem[streamID])) { -#endif /* CF */ - AR_DEBUG2_PRINTF("Unable to down the semaphore\n"); - } - - A_ASSERT((pPacket->Status != A_OK) || - (pPacket->pBuffer == (busy->data + HTC_HEADER_LEN))); - - busy->length = pPacket->ActualLength + HTC_HEADER_LEN; - busy->currPtr = HTC_HEADER_LEN; - ar->read_buffer_available[streamID] = TRUE; - //AR_DEBUG_PRINTF("raw read cb: 0x%X 0x%X \n", busy->currPtr,busy->length); - up(&ar->raw_htc_read_sem[streamID]); - - /* Signal the waiting process */ - AR_DEBUG2_PRINTF("Waking up the StreamID(%d) read process\n", streamID); - wake_up_interruptible(&ar->raw_htc_read_queue[streamID]); -} - -static void -ar6000_htc_raw_write_cb(void *Context, HTC_PACKET *pPacket) -{ - AR_SOFTC_T *ar = (AR_SOFTC_T *)Context; - raw_htc_buffer *free; - HTC_RAW_STREAM_ID streamID; - - free = (raw_htc_buffer *)pPacket->pPktContext; - A_ASSERT(free != NULL); - - if (pPacket->Status == A_ECANCELED) { - /* - * HTC provides A_ECANCELED status when it doesn't want to be refilled - * (probably due to a shutdown) - */ - return; - } - - streamID = arEndpoint2RawStreamID(ar,pPacket->Endpoint); - A_ASSERT(streamID != HTC_RAW_STREAM_NOT_MAPPED); - -#ifdef CF - if (down_trylock(&ar->raw_htc_write_sem[streamID])) { -#else - if (down_interruptible(&ar->raw_htc_write_sem[streamID])) { -#endif - AR_DEBUG2_PRINTF("Unable to down the semaphore\n"); - } - - A_ASSERT(pPacket->pBuffer == (free->data + HTC_HEADER_LEN)); - - free->length = 0; - ar->write_buffer_available[streamID] = TRUE; - up(&ar->raw_htc_write_sem[streamID]); - - /* Signal the waiting process */ - AR_DEBUG2_PRINTF("Waking up the StreamID(%d) write process\n", streamID); - wake_up_interruptible(&ar->raw_htc_write_queue[streamID]); -} - -/* connect to a service */ -static A_STATUS ar6000_connect_raw_service(AR_SOFTC_T *ar, - HTC_RAW_STREAM_ID StreamID) -{ - A_STATUS status; - HTC_SERVICE_CONNECT_RESP response; - A_UINT8 streamNo; - HTC_SERVICE_CONNECT_REQ connect; - - do { - - A_MEMZERO(&connect,sizeof(connect)); - /* pass the stream ID as meta data to the RAW streams service */ - streamNo = (A_UINT8)StreamID; - connect.pMetaData = &streamNo; - connect.MetaDataLength = sizeof(A_UINT8); - /* these fields are the same for all endpoints */ - connect.EpCallbacks.pContext = ar; - connect.EpCallbacks.EpTxComplete = ar6000_htc_raw_write_cb; - connect.EpCallbacks.EpRecv = ar6000_htc_raw_read_cb; - /* simple interface, we don't need these optional callbacks */ - connect.EpCallbacks.EpRecvRefill = NULL; - connect.EpCallbacks.EpSendFull = NULL; - connect.EpCallbacks.EpSendAvail = NULL; - connect.MaxSendQueueDepth = RAW_HTC_WRITE_BUFFERS_NUM; - - /* connect to the raw streams service, we may be able to get 1 or more - * connections, depending on WHAT is running on the target */ - connect.ServiceID = HTC_RAW_STREAMS_SVC; - - A_MEMZERO(&response,sizeof(response)); - - /* try to connect to the raw stream, it is okay if this fails with - * status HTC_SERVICE_NO_MORE_EP */ - status = HTCConnectService(ar->arHtcTarget, - &connect, - &response); - - if (A_FAILED(status)) { - if (response.ConnectRespCode == HTC_SERVICE_NO_MORE_EP) { - AR_DEBUG_PRINTF("HTC RAW , No more streams allowed \n"); - status = A_OK; - } - break; - } - - /* set endpoint mapping for the RAW HTC streams */ - arSetRawStream2EndpointIDMap(ar,StreamID,response.Endpoint); - - AR_DEBUG_PRINTF("HTC RAW : stream ID: %d, endpoint: %d\n", - StreamID, arRawStream2EndpointID(ar,StreamID)); - - } while (FALSE); - - return status; -} - -int ar6000_htc_raw_open(AR_SOFTC_T *ar) -{ - A_STATUS status; - int streamID, endPt, count2; - raw_htc_buffer *buffer; - HTC_SERVICE_ID servicepriority; - - A_ASSERT(ar->arHtcTarget != NULL); - - /* wait for target */ - status = HTCWaitTarget(ar->arHtcTarget); - - if (A_FAILED(status)) { - AR_DEBUG_PRINTF("HTCWaitTarget failed (%d)\n", status); - return -ENODEV; - } - - for (endPt = 0; endPt < ENDPOINT_MAX; endPt++) { - ar->arEp2RawMapping[endPt] = HTC_RAW_STREAM_NOT_MAPPED; - } - - for (streamID = HTC_RAW_STREAM_0; streamID < HTC_RAW_STREAM_NUM_MAX; streamID++) { - /* Initialize the data structures */ - init_MUTEX(&ar->raw_htc_read_sem[streamID]); - init_MUTEX(&ar->raw_htc_write_sem[streamID]); - init_waitqueue_head(&ar->raw_htc_read_queue[streamID]); - init_waitqueue_head(&ar->raw_htc_write_queue[streamID]); - - /* try to connect to the raw service */ - status = ar6000_connect_raw_service(ar,streamID); - - if (A_FAILED(status)) { - break; - } - - if (arRawStream2EndpointID(ar,streamID) == 0) { - break; - } - - for (count2 = 0; count2 < RAW_HTC_READ_BUFFERS_NUM; count2 ++) { - /* Initialize the receive buffers */ - buffer = ar->raw_htc_write_buffer[streamID][count2]; - memset(buffer, 0, sizeof(raw_htc_buffer)); - buffer = ar->raw_htc_read_buffer[streamID][count2]; - memset(buffer, 0, sizeof(raw_htc_buffer)); - - SET_HTC_PACKET_INFO_RX_REFILL(&buffer->HTCPacket, - buffer, - buffer->data, - AR6000_BUFFER_SIZE, - arRawStream2EndpointID(ar,streamID)); - - /* Queue buffers to HTC for receive */ - if ((status = HTCAddReceivePkt(ar->arHtcTarget, &buffer->HTCPacket)) != A_OK) - { - BMIInit(); - return -EIO; - } - } - - for (count2 = 0; count2 < RAW_HTC_WRITE_BUFFERS_NUM; count2 ++) { - /* Initialize the receive buffers */ - buffer = ar->raw_htc_write_buffer[streamID][count2]; - memset(buffer, 0, sizeof(raw_htc_buffer)); - } - - ar->read_buffer_available[streamID] = FALSE; - ar->write_buffer_available[streamID] = TRUE; - } - - if (A_FAILED(status)) { - return -EIO; - } - - AR_DEBUG_PRINTF("HTC RAW, number of streams the target supports: %d \n", streamID); - - servicepriority = HTC_RAW_STREAMS_SVC; /* only 1 */ - - /* set callbacks and priority list */ - HTCSetCreditDistribution(ar->arHtcTarget, - ar, - NULL, /* use default */ - NULL, /* use default */ - &servicepriority, - 1); - - /* Start the HTC component */ - if ((status = HTCStart(ar->arHtcTarget)) != A_OK) { - BMIInit(); - return -EIO; - } - - (ar)->arRawIfInit = TRUE; - - return 0; -} - -int ar6000_htc_raw_close(AR_SOFTC_T *ar) -{ - A_PRINTF("ar6000_htc_raw_close called \n"); - HTCStop(ar->arHtcTarget); - - /* reset the device */ - ar6000_reset_device(ar->arHifDevice, ar->arTargetType); - /* Initialize the BMI component */ - BMIInit(); - - return 0; -} - -raw_htc_buffer * -get_filled_buffer(AR_SOFTC_T *ar, HTC_RAW_STREAM_ID StreamID) -{ - int count; - raw_htc_buffer *busy; - - /* Check for data */ - for (count = 0; count < RAW_HTC_READ_BUFFERS_NUM; count ++) { - busy = ar->raw_htc_read_buffer[StreamID][count]; - if (busy->length) { - break; - } - } - if (busy->length) { - ar->read_buffer_available[StreamID] = TRUE; - } else { - ar->read_buffer_available[StreamID] = FALSE; - } - - return busy; -} - -ssize_t ar6000_htc_raw_read(AR_SOFTC_T *ar, HTC_RAW_STREAM_ID StreamID, - char __user *buffer, size_t length) -{ - int readPtr; - raw_htc_buffer *busy; - - if (arRawStream2EndpointID(ar,StreamID) == 0) { - AR_DEBUG_PRINTF("StreamID(%d) not connected! \n", StreamID); - return -EFAULT; - } - - if (down_interruptible(&ar->raw_htc_read_sem[StreamID])) { - return -ERESTARTSYS; - } - - busy = get_filled_buffer(ar,StreamID); - while (!ar->read_buffer_available[StreamID]) { - up(&ar->raw_htc_read_sem[StreamID]); - - /* Wait for the data */ - AR_DEBUG2_PRINTF("Sleeping StreamID(%d) read process\n", StreamID); - if (wait_event_interruptible(ar->raw_htc_read_queue[StreamID], - ar->read_buffer_available[StreamID])) - { - return -EINTR; - } - if (down_interruptible(&ar->raw_htc_read_sem[StreamID])) { - return -ERESTARTSYS; - } - busy = get_filled_buffer(ar,StreamID); - } - - /* Read the data */ - readPtr = busy->currPtr; - if (length > busy->length - HTC_HEADER_LEN) { - length = busy->length - HTC_HEADER_LEN; - } - if (copy_to_user(buffer, &busy->data[readPtr], length)) { - up(&ar->raw_htc_read_sem[StreamID]); - return -EFAULT; - } - - busy->currPtr += length; - - //AR_DEBUG_PRINTF("raw read ioctl: currPTR : 0x%X 0x%X \n", busy->currPtr,busy->length); - - if (busy->currPtr == busy->length) - { - busy->currPtr = 0; - busy->length = 0; - HTC_PACKET_RESET_RX(&busy->HTCPacket); - //AR_DEBUG_PRINTF("raw read ioctl: ep for packet:%d \n", busy->HTCPacket.Endpoint); - HTCAddReceivePkt(ar->arHtcTarget, &busy->HTCPacket); - } - ar->read_buffer_available[StreamID] = FALSE; - up(&ar->raw_htc_read_sem[StreamID]); - - return length; -} - -static raw_htc_buffer * -get_free_buffer(AR_SOFTC_T *ar, HTC_ENDPOINT_ID StreamID) -{ - int count; - raw_htc_buffer *free; - - free = NULL; - for (count = 0; count < RAW_HTC_WRITE_BUFFERS_NUM; count ++) { - free = ar->raw_htc_write_buffer[StreamID][count]; - if (free->length == 0) { - break; - } - } - if (!free->length) { - ar->write_buffer_available[StreamID] = TRUE; - } else { - ar->write_buffer_available[StreamID] = FALSE; - } - - return free; -} - -ssize_t ar6000_htc_raw_write(AR_SOFTC_T *ar, HTC_RAW_STREAM_ID StreamID, - char __user *buffer, size_t length) -{ - int writePtr; - raw_htc_buffer *free; - - if (arRawStream2EndpointID(ar,StreamID) == 0) { - AR_DEBUG_PRINTF("StreamID(%d) not connected! \n", StreamID); - return -EFAULT; - } - - if (down_interruptible(&ar->raw_htc_write_sem[StreamID])) { - return -ERESTARTSYS; - } - - /* Search for a free buffer */ - free = get_free_buffer(ar,StreamID); - - /* Check if there is space to write else wait */ - while (!ar->write_buffer_available[StreamID]) { - up(&ar->raw_htc_write_sem[StreamID]); - - /* Wait for buffer to become free */ - AR_DEBUG2_PRINTF("Sleeping StreamID(%d) write process\n", StreamID); - if (wait_event_interruptible(ar->raw_htc_write_queue[StreamID], - ar->write_buffer_available[StreamID])) - { - return -EINTR; - } - if (down_interruptible(&ar->raw_htc_write_sem[StreamID])) { - return -ERESTARTSYS; - } - free = get_free_buffer(ar,StreamID); - } - - /* Send the data */ - writePtr = HTC_HEADER_LEN; - if (length > (AR6000_BUFFER_SIZE - HTC_HEADER_LEN)) { - length = AR6000_BUFFER_SIZE - HTC_HEADER_LEN; - } - - if (copy_from_user(&free->data[writePtr], buffer, length)) { - up(&ar->raw_htc_read_sem[StreamID]); - return -EFAULT; - } - - free->length = length; - - SET_HTC_PACKET_INFO_TX(&free->HTCPacket, - free, - &free->data[writePtr], - length, - arRawStream2EndpointID(ar,StreamID), - AR6K_DATA_PKT_TAG); - - HTCSendPkt(ar->arHtcTarget,&free->HTCPacket); - - ar->write_buffer_available[StreamID] = FALSE; - up(&ar->raw_htc_write_sem[StreamID]); - - return length; -} -#endif /* HTC_RAW_INTERFACE */ diff --git a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/ar6000/ar6xapi_linux.h b/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/ar6000/ar6xapi_linux.h deleted file mode 100644 index b8e6e0961..000000000 --- a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/ar6000/ar6xapi_linux.h +++ /dev/null @@ -1,128 +0,0 @@ -#ifndef _AR6XAPI_LINUX_H -#define _AR6XAPI_LINUX_H -/* - * - * Copyright (c) 2004-2007 Atheros Communications Inc. - * All rights reserved. - * - * - * 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; - * - * Software distributed under the License is distributed on an "AS - * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or - * implied. See the License for the specific language governing - * rights and limitations under the License. - * - * - * - */ - -#ifdef __cplusplus -extern "C" { -#endif - -struct ar6_softc; - -void ar6000_ready_event(void *devt, A_UINT8 *datap, A_UINT8 phyCap); -A_UINT8 ar6000_iptos_to_userPriority(A_UINT8 *pkt); -A_STATUS ar6000_control_tx(void *devt, void *osbuf, WMI_PRI_STREAM_ID streamID); -void ar6000_connect_event(struct ar6_softc *ar, A_UINT16 channel, - A_UINT8 *bssid, A_UINT16 listenInterval, - A_UINT16 beaconInterval, NETWORK_TYPE networkType, - A_UINT8 beaconIeLen, A_UINT8 assocReqLen, - A_UINT8 assocRespLen,A_UINT8 *assocInfo); -void ar6000_disconnect_event(struct ar6_softc *ar, A_UINT8 reason, - A_UINT8 *bssid, A_UINT8 assocRespLen, - A_UINT8 *assocInfo, A_UINT16 protocolReasonStatus); -void ar6000_tkip_micerr_event(struct ar6_softc *ar, A_UINT8 keyid, - A_BOOL ismcast); -void ar6000_bitrate_rx(void *devt, A_INT32 rateKbps); -void ar6000_channelList_rx(void *devt, A_INT8 numChan, A_UINT16 *chanList); -void ar6000_regDomain_event(struct ar6_softc *ar, A_UINT32 regCode); -void ar6000_txPwr_rx(void *devt, A_UINT8 txPwr); -void ar6000_keepalive_rx(void *devt, A_UINT8 configured); -void ar6000_neighborReport_event(struct ar6_softc *ar, int numAps, - WMI_NEIGHBOR_INFO *info); -void ar6000_set_numdataendpts(struct ar6_softc *ar, A_UINT32 num); -void ar6000_scanComplete_event(struct ar6_softc *ar, A_STATUS status); -void ar6000_targetStats_event(struct ar6_softc *ar, WMI_TARGET_STATS *pStats); -void ar6000_rssiThreshold_event(struct ar6_softc *ar, - WMI_RSSI_THRESHOLD_VAL newThreshold, - A_INT16 rssi); -void ar6000_reportError_event(struct ar6_softc *, WMI_TARGET_ERROR_VAL errorVal); -void ar6000_cac_event(struct ar6_softc *ar, A_UINT8 ac, A_UINT8 cac_indication, - A_UINT8 statusCode, A_UINT8 *tspecSuggestion); -void ar6000_hbChallengeResp_event(struct ar6_softc *, A_UINT32 cookie, A_UINT32 source); -void -ar6000_roam_tbl_event(struct ar6_softc *ar, WMI_TARGET_ROAM_TBL *pTbl); - -void -ar6000_roam_data_event(struct ar6_softc *ar, WMI_TARGET_ROAM_DATA *p); - -void -ar6000_wow_list_event(struct ar6_softc *ar, A_UINT8 num_filters, - WMI_GET_WOW_LIST_REPLY *wow_reply); - -void ar6000_pmkid_list_event(void *devt, A_UINT8 numPMKID, - WMI_PMKID *pmkidList); - -void ar6000_gpio_intr_rx(A_UINT32 intr_mask, A_UINT32 input_values); -void ar6000_gpio_data_rx(A_UINT32 reg_id, A_UINT32 value); -void ar6000_gpio_ack_rx(void); - -void ar6000_dbglog_init_done(struct ar6_softc *ar); - -#ifdef SEND_EVENT_TO_APP -void ar6000_send_event_to_app(struct ar6_softc *ar, A_UINT16 eventId, A_UINT8 *datap, int len); -#endif - -#ifdef CONFIG_HOST_TCMD_SUPPORT -void ar6000_tcmd_rx_report_event(void *devt, A_UINT8 * results, int len); -#endif - -void ar6000_tx_retry_err_event(void *devt); - -void ar6000_snrThresholdEvent_rx(void *devt, - WMI_SNR_THRESHOLD_VAL newThreshold, - A_UINT8 snr); - -void ar6000_lqThresholdEvent_rx(void *devt, WMI_LQ_THRESHOLD_VAL range, A_UINT8 lqVal); - - -void ar6000_ratemask_rx(void *devt, A_UINT16 ratemask); - -A_STATUS ar6000_get_driver_cfg(struct net_device *dev, - A_UINT16 cfgParam, - void *result); -void ar6000_bssInfo_event_rx(struct ar6_softc *ar, A_UINT8 *data, int len); - -void ar6000_dbglog_event(struct ar6_softc *ar, A_UINT32 dropped, - A_INT8 *buffer, A_UINT32 length); - -int ar6000_dbglog_get_debug_logs(struct ar6_softc *ar); - -void ar6000_indicate_tx_activity(void *devt, A_UINT8 trafficClass, A_BOOL Active); - -void ar6000_dset_open_req(void *devt, - A_UINT32 id, - A_UINT32 targ_handle, - A_UINT32 targ_reply_fn, - A_UINT32 targ_reply_arg); -void ar6000_dset_close(void *devt, A_UINT32 access_cookie); -void ar6000_dset_data_req(void *devt, - A_UINT32 access_cookie, - A_UINT32 offset, - A_UINT32 length, - A_UINT32 targ_buf, - A_UINT32 targ_reply_fn, - A_UINT32 targ_reply_arg); - - - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/ar6000/athdrv_linux.h b/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/ar6000/athdrv_linux.h deleted file mode 100644 index 9c3e44973..000000000 --- a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/ar6000/athdrv_linux.h +++ /dev/null @@ -1,993 +0,0 @@ -/* - * Copyright (c) 2004-2006 Atheros Communications Inc. - * All rights reserved. - * - * - * - * 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; - * - * Software distributed under the License is distributed on an "AS - * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or - * implied. See the License for the specific language governing - * rights and limitations under the License. - * - * - * - */ - -#ifndef _ATHDRV_LINUX_H -#define _ATHDRV_LINUX_H - -#ifdef __cplusplus -extern "C" { -#endif - - -/* - * There are two types of ioctl's here: Standard ioctls and - * eXtended ioctls. All extended ioctls (XIOCTL) are multiplexed - * off of the single ioctl command, AR6000_IOCTL_EXTENDED. The - * arguments for every XIOCTL starts with a 32-bit command word - * that is used to select which extended ioctl is in use. After - * the command word are command-specific arguments. - */ - -/* Linux standard Wireless Extensions, private ioctl interfaces */ -#define IEEE80211_IOCTL_SETPARAM (SIOCIWFIRSTPRIV+0) -#define IEEE80211_IOCTL_GETPARAM (SIOCIWFIRSTPRIV+1) -#define IEEE80211_IOCTL_SETKEY (SIOCIWFIRSTPRIV+2) -#define IEEE80211_IOCTL_SETWMMPARAMS (SIOCIWFIRSTPRIV+3) -#define IEEE80211_IOCTL_DELKEY (SIOCIWFIRSTPRIV+4) -#define IEEE80211_IOCTL_GETWMMPARAMS (SIOCIWFIRSTPRIV+5) -#define IEEE80211_IOCTL_SETOPTIE (SIOCIWFIRSTPRIV+6) -#define IEEE80211_IOCTL_SETMLME (SIOCIWFIRSTPRIV+7) -//#define IEEE80211_IOCTL_GETOPTIE (SIOCIWFIRSTPRIV+7) -#define IEEE80211_IOCTL_ADDPMKID (SIOCIWFIRSTPRIV+8) -//#define IEEE80211_IOCTL_SETAUTHALG (SIOCIWFIRSTPRIV+10) -#define IEEE80211_IOCTL_LASTONE (SIOCIWFIRSTPRIV+9) - - - -/* ====WMI Ioctls==== */ -/* - * - * Many ioctls simply provide WMI services to application code: - * an application makes such an ioctl call with a set of arguments - * that are packaged into the corresponding WMI message, and sent - * to the Target. - */ - -#define AR6000_IOCTL_WMI_GETREV (SIOCIWFIRSTPRIV+10) -/* - * arguments: - * ar6000_version *revision - */ - -#define AR6000_IOCTL_WMI_SETPWR (SIOCIWFIRSTPRIV+11) -/* - * arguments: - * WMI_POWER_MODE_CMD pwrModeCmd (see include/wmi.h) - * uses: WMI_SET_POWER_MODE_CMDID - */ - -#define AR6000_IOCTL_WMI_SETSCAN (SIOCIWFIRSTPRIV+12) -/* - * arguments: - * WMI_SCAN_PARAMS_CMD scanParams (see include/wmi.h) - * uses: WMI_SET_SCAN_PARAMS_CMDID - */ - -#define AR6000_IOCTL_WMI_SETLISTENINT (SIOCIWFIRSTPRIV+13) -/* - * arguments: - * UINT32 listenInterval - * uses: WMI_SET_LISTEN_INT_CMDID - */ - -#define AR6000_IOCTL_WMI_SETBSSFILTER (SIOCIWFIRSTPRIV+14) -/* - * arguments: - * WMI_BSS_FILTER filter (see include/wmi.h) - * uses: WMI_SET_BSS_FILTER_CMDID - */ - -#define AR6000_IOCTL_WMI_SET_CHANNELPARAMS (SIOCIWFIRSTPRIV+16) -/* - * arguments: - * WMI_CHANNEL_PARAMS_CMD chParams - * uses: WMI_SET_CHANNEL_PARAMS_CMDID - */ - -#define AR6000_IOCTL_WMI_SET_PROBEDSSID (SIOCIWFIRSTPRIV+17) -/* - * arguments: - * WMI_PROBED_SSID_CMD probedSsids (see include/wmi.h) - * uses: WMI_SETPROBED_SSID_CMDID - */ - -#define AR6000_IOCTL_WMI_SET_PMPARAMS (SIOCIWFIRSTPRIV+18) -/* - * arguments: - * WMI_POWER_PARAMS_CMD powerParams (see include/wmi.h) - * uses: WMI_SET_POWER_PARAMS_CMDID - */ - -#define AR6000_IOCTL_WMI_SET_BADAP (SIOCIWFIRSTPRIV+19) -/* - * arguments: - * WMI_ADD_BAD_AP_CMD badAPs (see include/wmi.h) - * uses: WMI_ADD_BAD_AP_CMDID - */ - -#define AR6000_IOCTL_WMI_GET_QOS_QUEUE (SIOCIWFIRSTPRIV+20) -/* - * arguments: - * ar6000_queuereq queueRequest (see below) - */ - -#define AR6000_IOCTL_WMI_CREATE_QOS (SIOCIWFIRSTPRIV+21) -/* - * arguments: - * WMI_CREATE_PSTREAM createPstreamCmd (see include/wmi.h) - * uses: WMI_CREATE_PSTREAM_CMDID - */ - -#define AR6000_IOCTL_WMI_DELETE_QOS (SIOCIWFIRSTPRIV+22) -/* - * arguments: - * WMI_DELETE_PSTREAM_CMD deletePstreamCmd (see include/wmi.h) - * uses: WMI_DELETE_PSTREAM_CMDID - */ - -#define AR6000_IOCTL_WMI_SET_SNRTHRESHOLD (SIOCIWFIRSTPRIV+23) -/* - * arguments: - * WMI_SNR_THRESHOLD_PARAMS_CMD thresholdParams (see include/wmi.h) - * uses: WMI_SNR_THRESHOLD_PARAMS_CMDID - */ - -#define AR6000_IOCTL_WMI_SET_ERROR_REPORT_BITMASK (SIOCIWFIRSTPRIV+24) -/* - * arguments: - * WMI_TARGET_ERROR_REPORT_BITMASK errorReportBitMask (see include/wmi.h) - * uses: WMI_TARGET_ERROR_REPORT_BITMASK_CMDID - */ - -#define AR6000_IOCTL_WMI_GET_TARGET_STATS (SIOCIWFIRSTPRIV+25) -/* - * arguments: - * TARGET_STATS *targetStats (see below) - * uses: WMI_GET_STATISTICS_CMDID - */ - -#define AR6000_IOCTL_WMI_SET_ASSOC_INFO (SIOCIWFIRSTPRIV+26) -/* - * arguments: - * WMI_SET_ASSOC_INFO_CMD setAssocInfoCmd - * uses: WMI_SET_ASSOC_INFO_CMDID - */ - -#define AR6000_IOCTL_WMI_SET_ACCESS_PARAMS (SIOCIWFIRSTPRIV+27) -/* - * arguments: - * WMI_SET_ACCESS_PARAMS_CMD setAccessParams (see include/wmi.h) - * uses: WMI_SET_ACCESS_PARAMS_CMDID - */ - -#define AR6000_IOCTL_WMI_SET_BMISS_TIME (SIOCIWFIRSTPRIV+28) -/* - * arguments: - * UINT32 beaconMissTime - * uses: WMI_SET_BMISS_TIME_CMDID - */ - -#define AR6000_IOCTL_WMI_SET_DISC_TIMEOUT (SIOCIWFIRSTPRIV+29) -/* - * arguments: - * WMI_DISC_TIMEOUT_CMD disconnectTimeoutCmd (see include/wmi.h) - * uses: WMI_SET_DISC_TIMEOUT_CMDID - */ - -#define AR6000_IOCTL_WMI_SET_IBSS_PM_CAPS (SIOCIWFIRSTPRIV+30) -/* - * arguments: - * WMI_IBSS_PM_CAPS_CMD ibssPowerMgmtCapsCmd - * uses: WMI_SET_IBSS_PM_CAPS_CMDID - */ - -/* - * There is a very small space available for driver-private - * wireless ioctls. In order to circumvent this limitation, - * we multiplex a bunch of ioctls (XIOCTLs) on top of a - * single AR6000_IOCTL_EXTENDED ioctl. - */ -#define AR6000_IOCTL_EXTENDED (SIOCIWFIRSTPRIV+31) - - -/* ====BMI Extended Ioctls==== */ - -#define AR6000_XIOCTL_BMI_DONE 1 -/* - * arguments: - * UINT32 cmd (AR6000_XIOCTL_BMI_DONE) - * uses: BMI_DONE - */ - -#define AR6000_XIOCTL_BMI_READ_MEMORY 2 -/* - * arguments: - * union { - * struct { - * UINT32 cmd (AR6000_XIOCTL_BMI_READ_MEMORY) - * UINT32 address - * UINT32 length - * } - * char results[length] - * } - * uses: BMI_READ_MEMORY - */ - -#define AR6000_XIOCTL_BMI_WRITE_MEMORY 3 -/* - * arguments: - * UINT32 cmd (AR6000_XIOCTL_BMI_WRITE_MEMORY) - * UINT32 address - * UINT32 length - * char data[length] - * uses: BMI_WRITE_MEMORY - */ - -#define AR6000_XIOCTL_BMI_EXECUTE 4 -/* - * arguments: - * UINT32 cmd (AR6000_XIOCTL_BMI_EXECUTE) - * UINT32 TargetAddress - * UINT32 parameter - * uses: BMI_EXECUTE - */ - -#define AR6000_XIOCTL_BMI_SET_APP_START 5 -/* - * arguments: - * UINT32 cmd (AR6000_XIOCTL_BMI_SET_APP_START) - * UINT32 TargetAddress - * uses: BMI_SET_APP_START - */ - -#define AR6000_XIOCTL_BMI_READ_SOC_REGISTER 6 -/* - * arguments: - * union { - * struct { - * UINT32 cmd (AR6000_XIOCTL_BMI_READ_SOC_REGISTER) - * UINT32 TargetAddress, 32-bit aligned - * } - * UINT32 result - * } - * uses: BMI_READ_SOC_REGISTER - */ - -#define AR6000_XIOCTL_BMI_WRITE_SOC_REGISTER 7 -/* - * arguments: - * struct { - * UINT32 cmd (AR6000_XIOCTL_BMI_WRITE_SOC_REGISTER) - * UINT32 TargetAddress, 32-bit aligned - * UINT32 newValue - * } - * uses: BMI_WRITE_SOC_REGISTER - */ - -#define AR6000_XIOCTL_BMI_TEST 8 -/* - * arguments: - * UINT32 cmd (AR6000_XIOCTL_BMI_TEST) - * UINT32 address - * UINT32 length - * UINT32 count - */ - - - -/* Historical Host-side DataSet support */ -#define AR6000_XIOCTL_UNUSED9 9 -#define AR6000_XIOCTL_UNUSED10 10 -#define AR6000_XIOCTL_UNUSED11 11 - -/* ====Misc Extended Ioctls==== */ - -#define AR6000_XIOCTL_FORCE_TARGET_RESET 12 -/* - * arguments: - * UINT32 cmd (AR6000_XIOCTL_FORCE_TARGET_RESET) - */ - - -#ifdef HTC_RAW_INTERFACE -/* HTC Raw Interface Ioctls */ -#define AR6000_XIOCTL_HTC_RAW_OPEN 13 -/* - * arguments: - * UINT32 cmd (AR6000_XIOCTL_HTC_RAW_OPEN) - */ - -#define AR6000_XIOCTL_HTC_RAW_CLOSE 14 -/* - * arguments: - * UINT32 cmd (AR6000_XIOCTL_HTC_RAW_CLOSE) - */ - -#define AR6000_XIOCTL_HTC_RAW_READ 15 -/* - * arguments: - * union { - * struct { - * UINT32 cmd (AR6000_XIOCTL_HTC_RAW_READ) - * UINT32 mailboxID - * UINT32 length - * } - * results[length] - * } - */ - -#define AR6000_XIOCTL_HTC_RAW_WRITE 16 -/* - * arguments: - * UINT32 cmd (AR6000_XIOCTL_HTC_RAW_WRITE) - * UINT32 mailboxID - * UINT32 length - * char buffer[length] - */ -#endif /* HTC_RAW_INTERFACE */ - -#define AR6000_XIOCTL_CHECK_TARGET_READY 17 -/* - * arguments: - * UINT32 cmd (AR6000_XIOCTL_CHECK_TARGET_READY) - */ - - - -/* ====GPIO (General Purpose I/O) Extended Ioctls==== */ - -#define AR6000_XIOCTL_GPIO_OUTPUT_SET 18 -/* - * arguments: - * UINT32 cmd (AR6000_XIOCTL_GPIO_OUTPUT_SET) - * ar6000_gpio_output_set_cmd_s (see below) - * uses: WMIX_GPIO_OUTPUT_SET_CMDID - */ - -#define AR6000_XIOCTL_GPIO_INPUT_GET 19 -/* - * arguments: - * UINT32 cmd (AR6000_XIOCTL_GPIO_INPUT_GET) - * uses: WMIX_GPIO_INPUT_GET_CMDID - */ - -#define AR6000_XIOCTL_GPIO_REGISTER_SET 20 -/* - * arguments: - * UINT32 cmd (AR6000_XIOCTL_GPIO_REGISTER_SET) - * ar6000_gpio_register_cmd_s (see below) - * uses: WMIX_GPIO_REGISTER_SET_CMDID - */ - -#define AR6000_XIOCTL_GPIO_REGISTER_GET 21 -/* - * arguments: - * UINT32 cmd (AR6000_XIOCTL_GPIO_REGISTER_GET) - * ar6000_gpio_register_cmd_s (see below) - * uses: WMIX_GPIO_REGISTER_GET_CMDID - */ - -#define AR6000_XIOCTL_GPIO_INTR_ACK 22 -/* - * arguments: - * UINT32 cmd (AR6000_XIOCTL_GPIO_INTR_ACK) - * ar6000_cpio_intr_ack_cmd_s (see below) - * uses: WMIX_GPIO_INTR_ACK_CMDID - */ - -#define AR6000_XIOCTL_GPIO_INTR_WAIT 23 -/* - * arguments: - * UINT32 cmd (AR6000_XIOCTL_GPIO_INTR_WAIT) - */ - - - -/* ====more wireless commands==== */ - -#define AR6000_XIOCTL_SET_ADHOC_BSSID 24 -/* - * arguments: - * UINT32 cmd (AR6000_XIOCTL_SET_ADHOC_BSSID) - * WMI_SET_ADHOC_BSSID_CMD setAdHocBssidCmd (see include/wmi.h) - */ - -#define AR6000_XIOCTL_SET_OPT_MODE 25 -/* - * arguments: - * UINT32 cmd (AR6000_XIOCTL_SET_OPT_MODE) - * WMI_SET_OPT_MODE_CMD setOptModeCmd (see include/wmi.h) - * uses: WMI_SET_OPT_MODE_CMDID - */ - -#define AR6000_XIOCTL_OPT_SEND_FRAME 26 -/* - * arguments: - * UINT32 cmd (AR6000_XIOCTL_OPT_SEND_FRAME) - * WMI_OPT_TX_FRAME_CMD optTxFrameCmd (see include/wmi.h) - * uses: WMI_OPT_TX_FRAME_CMDID - */ - -#define AR6000_XIOCTL_SET_ADHOC_BEACON_INTVAL 27 -/* - * arguments: - * UINT32 cmd (AR6000_XIOCTL_SET_ADHOC_BEACON_INTVAL) - * WMI_BEACON_INT_CMD beaconIntCmd (see include/wmi.h) - * uses: WMI_SET_BEACON_INT_CMDID - */ - - -#define IEEE80211_IOCTL_SETAUTHALG 28 - - -#define AR6000_XIOCTL_SET_VOICE_PKT_SIZE 29 -/* - * arguments: - * UINT32 cmd (AR6000_XIOCTL_SET_VOICE_PKT_SIZE) - * WMI_SET_VOICE_PKT_SIZE_CMD setVoicePktSizeCmd (see include/wmi.h) - * uses: WMI_SET_VOICE_PKT_SIZE_CMDID - */ - - -#define AR6000_XIOCTL_SET_MAX_SP 30 -/* - * arguments: - * UINT32 cmd (AR6000_XIOCTL_SET_MAX_SP) - * WMI_SET_MAX_SP_LEN_CMD maxSPLen(see include/wmi.h) - * uses: WMI_SET_MAX_SP_LEN_CMDID - */ - -#define AR6000_XIOCTL_WMI_GET_ROAM_TBL 31 - -#define AR6000_XIOCTL_WMI_SET_ROAM_CTRL 32 - -#define AR6000_XIOCTRL_WMI_SET_POWERSAVE_TIMERS 33 - - -/* - * arguments: - * UINT32 cmd (AR6000_XIOCTRL_WMI_SET_POWERSAVE_TIMERS) - * WMI_SET_POWERSAVE_TIMERS_CMD powerSaveTimers(see include/wmi.h) - * WMI_SET_POWERSAVE_TIMERS_CMDID - */ - -#define AR6000_XIOCTRL_WMI_GET_POWER_MODE 34 -/* - * arguments: - * UINT32 cmd (AR6000_XIOCTRL_WMI_GET_POWER_MODE) - */ - -#define AR6000_XIOCTRL_WMI_SET_WLAN_STATE 35 -typedef enum { - WLAN_DISABLED, - WLAN_ENABLED -} AR6000_WLAN_STATE; -/* - * arguments: - * enable/disable - */ - -#define AR6000_XIOCTL_WMI_GET_ROAM_DATA 36 - -#define AR6000_XIOCTL_WMI_SETRETRYLIMITS 37 -/* - * arguments: - * WMI_SET_RETRY_LIMITS_CMD ibssSetRetryLimitsCmd - * uses: WMI_SET_RETRY_LIMITS_CMDID - */ - -#ifdef CONFIG_HOST_TCMD_SUPPORT -/* ====extended commands for radio test ==== */ - -#define AR6000_XIOCTL_TCMD_CONT_TX 38 -/* - * arguments: - * UINT32 cmd (AR6000_XIOCTL_TCMD_CONT_TX) - * WMI_TCMD_CONT_TX_CMD contTxCmd (see include/wmi.h) - * uses: WMI_TCMD_CONT_TX_CMDID - */ - -#define AR6000_XIOCTL_TCMD_CONT_RX 39 -/* - * arguments: - * UINT32 cmd (AR6000_XIOCTL_TCMD_CONT_RX) - * WMI_TCMD_CONT_RX_CMD rxCmd (see include/wmi.h) - * uses: WMI_TCMD_CONT_RX_CMDID - */ - -#define AR6000_XIOCTL_TCMD_PM 40 -/* - * arguments: - * UINT32 cmd (AR6000_XIOCTL_TCMD_PM) - * WMI_TCMD_PM_CMD pmCmd (see include/wmi.h) - * uses: WMI_TCMD_PM_CMDID - */ - -#endif /* CONFIG_HOST_TCMD_SUPPORT */ - -#define AR6000_XIOCTL_WMI_STARTSCAN 41 -/* - * arguments: - * UINT32 cmd (AR6000_XIOCTL_WMI_STARTSCAN) - * UINT8 scanType - * UINT8 scanConnected - * A_BOOL forceFgScan - * uses: WMI_START_SCAN_CMDID - */ - -#define AR6000_XIOCTL_WMI_SETFIXRATES 42 - -#define AR6000_XIOCTL_WMI_GETFIXRATES 43 - - -#define AR6000_XIOCTL_WMI_SET_RSSITHRESHOLD 44 -/* - * arguments: - * WMI_RSSI_THRESHOLD_PARAMS_CMD thresholdParams (see include/wmi.h) - * uses: WMI_RSSI_THRESHOLD_PARAMS_CMDID - */ - -#define AR6000_XIOCTL_WMI_CLR_RSSISNR 45 -/* - * arguments: - * WMI_CLR_RSSISNR_CMD thresholdParams (see include/wmi.h) - * uses: WMI_CLR_RSSISNR_CMDID - */ - -#define AR6000_XIOCTL_WMI_SET_LQTHRESHOLD 46 -/* - * arguments: - * WMI_LQ_THRESHOLD_PARAMS_CMD thresholdParams (see include/wmi.h) - * uses: WMI_LQ_THRESHOLD_PARAMS_CMDID - */ - -#define AR6000_XIOCTL_WMI_SET_RTS 47 -/* - * arguments: - * WMI_SET_RTS_MODE_CMD (see include/wmi.h) - * uses: WMI_SET_RTS_MODE_CMDID - */ - -#define AR6000_XIOCTL_WMI_SET_LPREAMBLE 48 - -#define AR6000_XIOCTL_WMI_SET_AUTHMODE 49 -/* - * arguments: - * UINT32 cmd (AR6000_XIOCTL_WMI_SET_AUTHMODE) - * UINT8 mode - * uses: WMI_SET_RECONNECT_AUTH_MODE_CMDID - */ - -#define AR6000_XIOCTL_WMI_SET_REASSOCMODE 50 - -/* - * arguments: - * UINT32 cmd (AR6000_XIOCTL_WMI_SET_WMM) - * UINT8 mode - * uses: WMI_SET_WMM_CMDID - */ -#define AR6000_XIOCTL_WMI_SET_WMM 51 - -/* - * arguments: - * UINT32 cmd (AR6000_XIOCTL_WMI_SET_HB_CHALLENGE_RESP_PARAMS) - * UINT32 frequency - * UINT8 threshold - */ -#define AR6000_XIOCTL_WMI_SET_HB_CHALLENGE_RESP_PARAMS 52 - -/* - * arguments: - * UINT32 cmd (AR6000_XIOCTL_WMI_GET_HB_CHALLENGE_RESP) - * UINT32 cookie - */ -#define AR6000_XIOCTL_WMI_GET_HB_CHALLENGE_RESP 53 - -/* - * arguments: - * UINT32 cmd (AR6000_XIOCTL_WMI_GET_RD) - * UINT32 regDomain - */ -#define AR6000_XIOCTL_WMI_GET_RD 54 - -#define AR6000_XIOCTL_DIAG_READ 55 - -#define AR6000_XIOCTL_DIAG_WRITE 56 - -/* - * arguments cmd (AR6000_XIOCTL_SET_TXOP) - * WMI_TXOP_CFG txopEnable - */ -#define AR6000_XIOCTL_WMI_SET_TXOP 57 - -#ifdef USER_KEYS -/* - * arguments: - * UINT32 cmd (AR6000_XIOCTL_USER_SETKEYS) - * UINT32 keyOpCtrl - * uses AR6000_USER_SETKEYS_INFO - */ -#define AR6000_XIOCTL_USER_SETKEYS 58 -#endif /* USER_KEYS */ - -#define AR6000_XIOCTL_WMI_SET_KEEPALIVE 59 -/* - * arguments: - * UINT8 cmd (AR6000_XIOCTL_WMI_SET_KEEPALIVE) - * UINT8 keepaliveInterval - * uses: WMI_SET_KEEPALIVE_CMDID - */ - -#define AR6000_XIOCTL_WMI_GET_KEEPALIVE 60 -/* - * arguments: - * UINT8 cmd (AR6000_XIOCTL_WMI_GET_KEEPALIVE) - * UINT8 keepaliveInterval - * A_BOOL configured - * uses: WMI_GET_KEEPALIVE_CMDID - */ - -/* ====ROM Patching Extended Ioctls==== */ - -#define AR6000_XIOCTL_BMI_ROMPATCH_INSTALL 61 -/* - * arguments: - * union { - * struct { - * UINT32 cmd (AR6000_XIOCTL_BMI_ROMPATCH_INSTALL) - * UINT32 ROM Address - * UINT32 RAM Address - * UINT32 number of bytes - * UINT32 activate? (0 or 1) - * } - * A_UINT32 resulting rompatch ID - * } - * uses: BMI_ROMPATCH_INSTALL - */ - -#define AR6000_XIOCTL_BMI_ROMPATCH_UNINSTALL 62 -/* - * arguments: - * struct { - * UINT32 cmd (AR6000_XIOCTL_BMI_ROMPATCH_UNINSTALL) - * UINT32 rompatch ID - * } - * uses: BMI_ROMPATCH_UNINSTALL - */ - -#define AR6000_XIOCTL_BMI_ROMPATCH_ACTIVATE 63 -/* - * arguments: - * struct { - * UINT32 cmd (AR6000_XIOCTL_BMI_ROMPATCH_ACTIVATE) - * UINT32 rompatch count - * UINT32 rompatch IDs[rompatch count] - * } - * uses: BMI_ROMPATCH_ACTIVATE - */ - -#define AR6000_XIOCTL_BMI_ROMPATCH_DEACTIVATE 64 -/* - * arguments: - * struct { - * UINT32 cmd (AR6000_XIOCTL_BMI_ROMPATCH_DEACTIVATE) - * UINT32 rompatch count - * UINT32 rompatch IDs[rompatch count] - * } - * uses: BMI_ROMPATCH_DEACTIVATE - */ - -#define AR6000_XIOCTL_WMI_SET_APPIE 65 -/* - * arguments: - * struct { - * UINT32 cmd (AR6000_XIOCTL_WMI_SET_APPIE) - * UINT32 app_frmtype; - * UINT32 app_buflen; - * UINT8 app_buf[]; - * } - */ -#define AR6000_XIOCTL_WMI_SET_MGMT_FRM_RX_FILTER 66 -/* - * arguments: - * A_UINT32 filter_type; - */ - -#define AR6000_XIOCTL_DBGLOG_CFG_MODULE 67 - -#define AR6000_XIOCTL_DBGLOG_GET_DEBUG_LOGS 68 - -#define AR6000_XIOCTL_WMI_SET_WSC_STATUS 70 -/* - * arguments: - * A_UINT32 wsc_status; - * (WSC_REG_INACTIVE or WSC_REG_ACTIVE) - */ - -/* - * arguments: - * struct { - * A_UINT8 streamType; - * A_UINT8 status; - * } - * uses: WMI_SET_BT_STATUS_CMDID - */ -#define AR6000_XIOCTL_WMI_SET_BT_STATUS 71 - -/* - * arguments: - * struct { - * A_UINT8 paramType; - * union { - * A_UINT8 noSCOPkts; - * BT_PARAMS_A2DP a2dpParams; - * BT_COEX_REGS regs; - * }; - * } - * uses: WMI_SET_BT_PARAM_CMDID - */ -#define AR6000_XIOCTL_WMI_SET_BT_PARAMS 72 - -#define AR6000_XIOCTL_WMI_SET_HOST_SLEEP_MODE 73 -#define AR6000_XIOCTL_WMI_SET_WOW_MODE 74 -#define AR6000_XIOCTL_WMI_GET_WOW_LIST 75 -#define AR6000_XIOCTL_WMI_ADD_WOW_PATTERN 76 -#define AR6000_XIOCTL_WMI_DEL_WOW_PATTERN 77 - - - -#define AR6000_XIOCTL_TARGET_INFO 78 -/* - * arguments: - * UINT32 cmd (AR6000_XIOCTL_TARGET_INFO) - * A_UINT32 TargetVersion (returned) - * A_UINT32 TargetType (returned) - * (See also bmi_msg.h target_ver and target_type) - */ - -#define AR6000_XIOCTL_DUMP_HTC_CREDIT_STATE 79 -/* - * arguments: - * none - */ - -#define AR6000_XIOCTL_TRAFFIC_ACTIVITY_CHANGE 80 -/* - * This ioctl is used to emulate traffic activity - * timeouts. Activity/inactivity will trigger the driver - * to re-balance credits. - * - * arguments: - * ar6000_traffic_activity_change - */ - -#define AR6000_XIOCTL_WMI_SET_CONNECT_CTRL_FLAGS 81 -/* - * This ioctl is used to set the connect control flags - * - * arguments: - * A_UINT32 connectCtrlFlags - */ - -#define AR6000_XIOCTL_WMI_SET_AKMP_PARAMS 82 -/* - * This IOCTL sets any Authentication,Key Management and Protection - * related parameters. This is used along with the information set in - * Connect Command. - * Currently this enables Multiple PMKIDs to an AP. - * - * arguments: - * struct { - * A_UINT32 akmpInfo; - * } - * uses: WMI_SET_AKMP_PARAMS_CMD - */ - -#define AR6000_XIOCTL_WMI_GET_PMKID_LIST 83 - -#define AR6000_XIOCTL_WMI_SET_PMKID_LIST 84 -/* - * This IOCTL is used to set a list of PMKIDs. This list of - * PMKIDs is used in the [Re]AssocReq Frame. This list is used - * only if the MultiPMKID option is enabled via the - * AR6000_XIOCTL_WMI_SET_AKMP_PARAMS IOCTL. - * - * arguments: - * struct { - * A_UINT32 numPMKID; - * WMI_PMKID pmkidList[WMI_MAX_PMKID_CACHE]; - * } - * uses: WMI_SET_PMKIDLIST_CMD - */ - -/* Historical DSETPATCH support for INI patches */ -#define AR6000_XIOCTL_UNUSED90 90 - - - -/* used by AR6000_IOCTL_WMI_GETREV */ -struct ar6000_version { - A_UINT32 host_ver; - A_UINT32 target_ver; -}; - -/* used by AR6000_IOCTL_WMI_GET_QOS_QUEUE */ -struct ar6000_queuereq { - A_UINT8 trafficClass; - A_UINT16 activeTsids; -}; - -/* used by AR6000_IOCTL_WMI_GET_TARGET_STATS */ -typedef struct targetStats_t { - A_UINT64 tx_packets; - A_UINT64 tx_bytes; - A_UINT64 tx_unicast_pkts; - A_UINT64 tx_unicast_bytes; - A_UINT64 tx_multicast_pkts; - A_UINT64 tx_multicast_bytes; - A_UINT64 tx_broadcast_pkts; - A_UINT64 tx_broadcast_bytes; - A_UINT64 tx_rts_success_cnt; - A_UINT64 tx_packet_per_ac[4]; - - A_UINT64 tx_errors; - A_UINT64 tx_failed_cnt; - A_UINT64 tx_retry_cnt; - A_UINT64 tx_rts_fail_cnt; - A_INT32 tx_unicast_rate; - A_UINT64 rx_packets; - A_UINT64 rx_bytes; - A_UINT64 rx_unicast_pkts; - A_UINT64 rx_unicast_bytes; - A_UINT64 rx_multicast_pkts; - A_UINT64 rx_multicast_bytes; - A_UINT64 rx_broadcast_pkts; - A_UINT64 rx_broadcast_bytes; - A_UINT64 rx_fragment_pkt; - - A_UINT64 rx_errors; - A_UINT64 rx_crcerr; - A_UINT64 rx_key_cache_miss; - A_UINT64 rx_decrypt_err; - A_UINT64 rx_duplicate_frames; - A_INT32 rx_unicast_rate; - - A_UINT64 tkip_local_mic_failure; - A_UINT64 tkip_counter_measures_invoked; - A_UINT64 tkip_replays; - A_UINT64 tkip_format_errors; - A_UINT64 ccmp_format_errors; - A_UINT64 ccmp_replays; - - A_UINT64 power_save_failure_cnt; - A_INT16 noise_floor_calibation; - - A_UINT64 cs_bmiss_cnt; - A_UINT64 cs_lowRssi_cnt; - A_UINT64 cs_connect_cnt; - A_UINT64 cs_disconnect_cnt; - A_UINT8 cs_aveBeacon_snr; - A_INT16 cs_aveBeacon_rssi; - A_UINT8 cs_lastRoam_msec; - A_UINT8 cs_snr; - A_INT16 cs_rssi; - - A_UINT32 lq_val; - - A_UINT32 wow_num_pkts_dropped; - A_UINT8 wow_num_host_pkt_wakeups; - A_UINT8 wow_num_host_event_wakeups; - A_UINT16 wow_num_events_discarded; - -}TARGET_STATS; - -typedef struct targetStats_cmd_t { - TARGET_STATS targetStats; - int clearStats; -} TARGET_STATS_CMD; - -/* used by AR6000_XIOCTL_USER_SETKEYS */ - -/* - * Setting this bit to 1 doesnot initialize the RSC on the firmware - */ -#define AR6000_XIOCTL_USER_SETKEYS_RSC_CTRL 1 -#define AR6000_USER_SETKEYS_RSC_UNCHANGED 0x00000002 - -typedef struct { - A_UINT32 keyOpCtrl; /* Bit Map of Key Mgmt Ctrl Flags */ -} AR6000_USER_SETKEYS_INFO; - - -/* used by AR6000_XIOCTL_GPIO_OUTPUT_SET */ -struct ar6000_gpio_output_set_cmd_s { - A_UINT32 set_mask; - A_UINT32 clear_mask; - A_UINT32 enable_mask; - A_UINT32 disable_mask; -}; - -/* - * used by AR6000_XIOCTL_GPIO_REGISTER_GET and AR6000_XIOCTL_GPIO_REGISTER_SET - */ -struct ar6000_gpio_register_cmd_s { - A_UINT32 gpioreg_id; - A_UINT32 value; -}; - -/* used by AR6000_XIOCTL_GPIO_INTR_ACK */ -struct ar6000_gpio_intr_ack_cmd_s { - A_UINT32 ack_mask; -}; - -/* used by AR6000_XIOCTL_GPIO_INTR_WAIT */ -struct ar6000_gpio_intr_wait_cmd_s { - A_UINT32 intr_mask; - A_UINT32 input_values; -}; - -/* used by the AR6000_XIOCTL_DBGLOG_CFG_MODULE */ -typedef struct ar6000_dbglog_module_config_s { - A_UINT32 valid; - A_UINT16 mmask; - A_UINT16 tsr; - A_BOOL rep; - A_UINT16 size; -} DBGLOG_MODULE_CONFIG; - -typedef struct user_rssi_thold_t { - A_INT16 tag; - A_INT16 rssi; -} USER_RSSI_THOLD; - -typedef struct user_rssi_params_t { - A_UINT8 weight; - A_UINT32 pollTime; - USER_RSSI_THOLD tholds[12]; -} USER_RSSI_PARAMS; - -/* - * Host driver may have some config parameters. Typically, these - * config params are one time config parameters. These could - * correspond to any of the underlying modules. Host driver exposes - * an api for the underlying modules to get this config. - */ -#define AR6000_DRIVER_CFG_BASE 0x8000 - -/* Should driver perform wlan node caching? */ -#define AR6000_DRIVER_CFG_GET_WLANNODECACHING 0x8001 -/*Should we log raw WMI msgs */ -#define AR6000_DRIVER_CFG_LOG_RAW_WMI_MSGS 0x8002 - -/* used by AR6000_XIOCTL_DIAG_READ & AR6000_XIOCTL_DIAG_WRITE */ -struct ar6000_diag_window_cmd_s { - unsigned int addr; - unsigned int value; -}; - - -struct ar6000_traffic_activity_change { - A_UINT32 StreamID; /* stream ID to indicate activity change */ - A_UINT32 Active; /* active (1) or inactive (0) */ -}; - -#ifdef __cplusplus -} -#endif -#endif diff --git a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/ar6000/athtypes_linux.h b/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/ar6000/athtypes_linux.h deleted file mode 100644 index 3e91de331..000000000 --- a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/ar6000/athtypes_linux.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * $Id: //depot/sw/releases/olca2.0-GPL/host/os/linux/include/athtypes_linux.h#1 $ - * - * This file contains the definitions of the basic atheros data types. - * It is used to map the data types in atheros files to a platform specific - * type. - * - * Copyright 2003-2005 Atheros Communications, Inc., All Rights Reserved. - * - * - * 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; - * - * Software distributed under the License is distributed on an "AS - * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or - * implied. See the License for the specific language governing - * rights and limitations under the License. - * - * - * - */ - -#ifndef _ATHTYPES_LINUX_H_ -#define _ATHTYPES_LINUX_H_ - -#ifdef __KERNEL__ -#include -#endif - -typedef int8_t A_INT8; -typedef int16_t A_INT16; -typedef int32_t A_INT32; -typedef int64_t A_INT64; - -typedef u_int8_t A_UINT8; -typedef u_int16_t A_UINT16; -typedef u_int32_t A_UINT32; -typedef u_int64_t A_UINT64; - -typedef int A_BOOL; -typedef char A_CHAR; -typedef unsigned char A_UCHAR; -typedef unsigned long A_ATH_TIMER; - - -#endif /* _ATHTYPES_LINUX_H_ */ diff --git a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/ar6000/config_linux.h b/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/ar6000/config_linux.h deleted file mode 100644 index 11a691d0c..000000000 --- a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/ar6000/config_linux.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (c) 2004-2007 Atheros Communications Inc. - * All rights reserved. - * - * - * 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; - * - * Software distributed under the License is distributed on an "AS - * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or - * implied. See the License for the specific language governing - * rights and limitations under the License. - * - * - * - */ - -#ifndef _CONFIG_LINUX_H_ -#define _CONFIG_LINUX_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * Host-side GPIO support is optional. - * If run-time access to GPIO pins is not required, then - * this should be changed to #undef. - */ -#define CONFIG_HOST_GPIO_SUPPORT - -/* - * Host side Test Command support - */ -#define CONFIG_HOST_TCMD_SUPPORT - -#define USE_4BYTE_REGISTER_ACCESS - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/ar6000/debug_linux.h b/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/ar6000/debug_linux.h deleted file mode 100644 index c74e1df9f..000000000 --- a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/ar6000/debug_linux.h +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright (c) 2004-2006 Atheros Communications Inc. - * All rights reserved. - * - * - * 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; - * - * Software distributed under the License is distributed on an "AS - * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or - * implied. See the License for the specific language governing - * rights and limitations under the License. - * - * - * - */ - -#ifndef _DEBUG_LINUX_H_ -#define _DEBUG_LINUX_H_ - -#define DBG_DEFAULTS (DBG_ERROR|DBG_WARNING) - -extern A_UINT32 g_dbg_flags; - -#define DBGFMT "%s() : " -#define DBGARG __func__ -#define DBGFN A_PRINTF - -/* ------- Debug related stuff ------- */ -enum { - ATH_DEBUG_SEND = 0x0001, - ATH_DEBUG_RECV = 0x0002, - ATH_DEBUG_SYNC = 0x0004, - ATH_DEBUG_DUMP = 0x0008, - ATH_DEBUG_IRQ = 0x0010, - ATH_DEBUG_TRC = 0x0020, - ATH_DEBUG_WARN = 0x0040, - ATH_DEBUG_ERR = 0x0080, - ATH_LOG_INF = 0x0100, - ATH_DEBUG_BMI = 0x0110, - ATH_DEBUG_WMI = 0x0120, - ATH_DEBUG_HIF = 0x0140, - ATH_DEBUG_HTC = 0x0180, - ATH_DEBUG_WLAN = 0x1000, - ATH_LOG_ERR = 0x1010, - ATH_DEBUG_ANY = 0xFFFF, -}; - -#ifdef DEBUG - -#define A_DPRINTF(f, a) \ - if(g_dbg_flags & (f)) \ - { \ - DBGFN a ; \ - } - - -// TODO FIX usage of A_PRINTF! -#define AR_DEBUG_LVL_CHECK(lvl) (debughtc & (lvl)) -#define AR_DEBUG_PRINTBUF(buffer, length, desc) do { \ - if (debughtc & ATH_DEBUG_DUMP) { \ - DebugDumpBytes(buffer, length,desc); \ - } \ -} while(0) -#define PRINTX_ARG(arg...) arg -#define AR_DEBUG_PRINTF(flags, args) do { \ - if (debughtc & (flags)) { \ - A_PRINTF(KERN_ALERT PRINTX_ARG args); \ - } \ -} while (0) -#define AR_DEBUG_ASSERT(test) do { \ - if (!(test)) { \ - AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Debug Assert Caught, File %s, Line: %d, Test:%s \n",__FILE__, __LINE__,#test)); \ - } \ -} while(0) -extern int debughtc; -#else -#define AR_DEBUG_PRINTF(flags, args) -#define AR_DEBUG_PRINTBUF(buffer, length, desc) -#define AR_DEBUG_ASSERT(test) -#define AR_DEBUG_LVL_CHECK(lvl) 0 -#define A_DPRINTF(f, a) -#endif - -#endif /* _DEBUG_LINUX_H_ */ diff --git a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/ar6000/ioctl.c b/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/ar6000/ioctl.c deleted file mode 100644 index 04aa911f3..000000000 --- a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/ar6000/ioctl.c +++ /dev/null @@ -1,2532 +0,0 @@ -/* - * - * Copyright (c) 2004-2007 Atheros Communications Inc. - * All rights reserved. - * - * - * 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; - * - * Software distributed under the License is distributed on an "AS - * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or - * implied. See the License for the specific language governing - * rights and limitations under the License. - * - * - * - */ - -#include "ar6000_drv.h" - -static A_UINT8 bcast_mac[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; -static A_UINT8 null_mac[] = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0}; -extern USER_RSSI_THOLD rssi_map[12]; -extern unsigned int wmitimeout; -extern A_WAITQUEUE_HEAD arEvent; -extern int tspecCompliance; -extern int bypasswmi; - -static int -ar6000_ioctl_get_roam_tbl(struct net_device *dev, struct ifreq *rq) -{ - AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev); - - if (ar->arWmiReady == FALSE) { - return -EIO; - } - - if(wmi_get_roam_tbl_cmd(ar->arWmi) != A_OK) { - return -EIO; - } - - return 0; -} - -static int -ar6000_ioctl_get_roam_data(struct net_device *dev, struct ifreq *rq) -{ - AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev); - - if (ar->arWmiReady == FALSE) { - return -EIO; - } - - - /* currently assume only roam times are required */ - if(wmi_get_roam_data_cmd(ar->arWmi, ROAM_DATA_TIME) != A_OK) { - return -EIO; - } - - - return 0; -} - -static int -ar6000_ioctl_set_roam_ctrl(struct net_device *dev, char *userdata) -{ - AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev); - WMI_SET_ROAM_CTRL_CMD cmd; - A_UINT8 size = sizeof(cmd); - - if (ar->arWmiReady == FALSE) { - return -EIO; - } - - - if (copy_from_user(&cmd, userdata, size)) { - return -EFAULT; - } - - if (cmd.roamCtrlType == WMI_SET_HOST_BIAS) { - if (cmd.info.bssBiasInfo.numBss > 1) { - size += (cmd.info.bssBiasInfo.numBss - 1) * sizeof(WMI_BSS_BIAS); - } - } - - if (copy_from_user(&cmd, userdata, size)) { - return -EFAULT; - } - - if(wmi_set_roam_ctrl_cmd(ar->arWmi, &cmd, size) != A_OK) { - return -EIO; - } - - return 0; -} - -static int -ar6000_ioctl_set_powersave_timers(struct net_device *dev, char *userdata) -{ - AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev); - WMI_POWERSAVE_TIMERS_POLICY_CMD cmd; - A_UINT8 size = sizeof(cmd); - - if (ar->arWmiReady == FALSE) { - return -EIO; - } - - if (copy_from_user(&cmd, userdata, size)) { - return -EFAULT; - } - - if (copy_from_user(&cmd, userdata, size)) { - return -EFAULT; - } - - if(wmi_set_powersave_timers_cmd(ar->arWmi, &cmd, size) != A_OK) { - return -EIO; - } - - return 0; -} - -static int -ar6000_ioctl_set_wmm(struct net_device *dev, struct ifreq *rq) -{ - AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev); - WMI_SET_WMM_CMD cmd; - A_STATUS ret; - - if ((dev->flags & IFF_UP) != IFF_UP) { - return -EIO; - } - if (ar->arWmiReady == FALSE) { - return -EIO; - } - - if (copy_from_user(&cmd, (char *)((unsigned int*)rq->ifr_data + 1), - sizeof(cmd))) - { - return -EFAULT; - } - - if (cmd.status == WMI_WMM_ENABLED) { - ar->arWmmEnabled = TRUE; - } else { - ar->arWmmEnabled = FALSE; - } - - ret = wmi_set_wmm_cmd(ar->arWmi, cmd.status); - - switch (ret) { - case A_OK: - return 0; - case A_EBUSY : - return -EBUSY; - case A_NO_MEMORY: - return -ENOMEM; - case A_EINVAL: - default: - return -EFAULT; - } -} - -static int -ar6000_ioctl_set_txop(struct net_device *dev, struct ifreq *rq) -{ - AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev); - WMI_SET_WMM_TXOP_CMD cmd; - A_STATUS ret; - - if ((dev->flags & IFF_UP) != IFF_UP) { - return -EIO; - } - if (ar->arWmiReady == FALSE) { - return -EIO; - } - - if (copy_from_user(&cmd, (char *)((unsigned int*)rq->ifr_data + 1), - sizeof(cmd))) - { - return -EFAULT; - } - - ret = wmi_set_wmm_txop(ar->arWmi, cmd.txopEnable); - - switch (ret) { - case A_OK: - return 0; - case A_EBUSY : - return -EBUSY; - case A_NO_MEMORY: - return -ENOMEM; - case A_EINVAL: - default: - return -EFAULT; - } -} - -static int -ar6000_ioctl_get_rd(struct net_device *dev, struct ifreq *rq) -{ - AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev); - A_STATUS ret = 0; - - if ((dev->flags & IFF_UP) != IFF_UP || ar->arWmiReady == FALSE) { - return -EIO; - } - - if(copy_to_user((char *)((unsigned int*)rq->ifr_data + 1), - &ar->arRegCode, sizeof(ar->arRegCode))) - ret = -EFAULT; - - return ret; -} - - -/* Get power mode command */ -static int -ar6000_ioctl_get_power_mode(struct net_device *dev, struct ifreq *rq) -{ - AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev); - WMI_POWER_MODE_CMD power_mode; - int ret = 0; - - if (ar->arWmiReady == FALSE) { - return -EIO; - } - - power_mode.powerMode = wmi_get_power_mode_cmd(ar->arWmi); - if (copy_to_user(rq->ifr_data, &power_mode, sizeof(WMI_POWER_MODE_CMD))) { - ret = -EFAULT; - } - - return ret; -} - - -static int -ar6000_ioctl_set_channelParams(struct net_device *dev, struct ifreq *rq) -{ - AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev); - WMI_CHANNEL_PARAMS_CMD cmd, *cmdp; - int ret = 0; - - if (ar->arWmiReady == FALSE) { - return -EIO; - } - - - if (copy_from_user(&cmd, rq->ifr_data, sizeof(cmd))) { - return -EFAULT; - } - - if (cmd.numChannels > 1) { - cmdp = A_MALLOC(130); - if (copy_from_user(cmdp, rq->ifr_data, - sizeof (*cmdp) + - ((cmd.numChannels - 1) * sizeof(A_UINT16)))) - { - kfree(cmdp); - return -EFAULT; - } - } else { - cmdp = &cmd; - } - - if ((ar->arPhyCapability == WMI_11G_CAPABILITY) && - ((cmdp->phyMode == WMI_11A_MODE) || (cmdp->phyMode == WMI_11AG_MODE))) - { - ret = -EINVAL; - } - - if (!ret && - (wmi_set_channelParams_cmd(ar->arWmi, cmdp->scanParam, cmdp->phyMode, - cmdp->numChannels, cmdp->channelList) - != A_OK)) - { - ret = -EIO; - } - - if (cmd.numChannels > 1) { - kfree(cmdp); - } - - return ret; -} - -static int -ar6000_ioctl_set_snr_threshold(struct net_device *dev, struct ifreq *rq) -{ - - AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev); - WMI_SNR_THRESHOLD_PARAMS_CMD cmd; - int ret = 0; - - if (ar->arWmiReady == FALSE) { - return -EIO; - } - - if (copy_from_user(&cmd, rq->ifr_data, sizeof(cmd))) { - return -EFAULT; - } - - if( wmi_set_snr_threshold_params(ar->arWmi, &cmd) != A_OK ) { - ret = -EIO; - } - - return ret; -} - -static int -ar6000_ioctl_set_rssi_threshold(struct net_device *dev, struct ifreq *rq) -{ -#define SWAP_THOLD(thold1, thold2) do { \ - USER_RSSI_THOLD tmpThold; \ - tmpThold.tag = thold1.tag; \ - tmpThold.rssi = thold1.rssi; \ - thold1.tag = thold2.tag; \ - thold1.rssi = thold2.rssi; \ - thold2.tag = tmpThold.tag; \ - thold2.rssi = tmpThold.rssi; \ -} while (0) - - AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev); - WMI_RSSI_THRESHOLD_PARAMS_CMD cmd; - USER_RSSI_PARAMS rssiParams; - A_INT32 i, j; - - int ret = 0; - - if (ar->arWmiReady == FALSE) { - return -EIO; - } - - if (copy_from_user((char *)&rssiParams, (char *)((unsigned int *)rq->ifr_data + 1), sizeof(USER_RSSI_PARAMS))) { - return -EFAULT; - } - cmd.weight = rssiParams.weight; - cmd.pollTime = rssiParams.pollTime; - - A_MEMCPY(rssi_map, &rssiParams.tholds, sizeof(rssi_map)); - /* - * only 6 elements, so use bubble sorting, in ascending order - */ - for (i = 5; i > 0; i--) { - for (j = 0; j < i; j++) { /* above tholds */ - if (rssi_map[j+1].rssi < rssi_map[j].rssi) { - SWAP_THOLD(rssi_map[j+1], rssi_map[j]); - } else if (rssi_map[j+1].rssi == rssi_map[j].rssi) { - return EFAULT; - } - } - } - for (i = 11; i > 6; i--) { - for (j = 6; j < i; j++) { /* below tholds */ - if (rssi_map[j+1].rssi < rssi_map[j].rssi) { - SWAP_THOLD(rssi_map[j+1], rssi_map[j]); - } else if (rssi_map[j+1].rssi == rssi_map[j].rssi) { - return EFAULT; - } - } - } - -#ifdef DEBUG - for (i = 0; i < 12; i++) { - AR_DEBUG2_PRINTF("thold[%d].tag: %d, thold[%d].rssi: %d \n", - i, rssi_map[i].tag, i, rssi_map[i].rssi); - } -#endif - cmd.thresholdAbove1_Val = rssi_map[0].rssi; - cmd.thresholdAbove2_Val = rssi_map[1].rssi; - cmd.thresholdAbove3_Val = rssi_map[2].rssi; - cmd.thresholdAbove4_Val = rssi_map[3].rssi; - cmd.thresholdAbove5_Val = rssi_map[4].rssi; - cmd.thresholdAbove6_Val = rssi_map[5].rssi; - cmd.thresholdBelow1_Val = rssi_map[6].rssi; - cmd.thresholdBelow2_Val = rssi_map[7].rssi; - cmd.thresholdBelow3_Val = rssi_map[8].rssi; - cmd.thresholdBelow4_Val = rssi_map[9].rssi; - cmd.thresholdBelow5_Val = rssi_map[10].rssi; - cmd.thresholdBelow6_Val = rssi_map[11].rssi; - - if( wmi_set_rssi_threshold_params(ar->arWmi, &cmd) != A_OK ) { - ret = -EIO; - } - - return ret; -} - -static int -ar6000_ioctl_set_lq_threshold(struct net_device *dev, struct ifreq *rq) -{ - - AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev); - WMI_LQ_THRESHOLD_PARAMS_CMD cmd; - int ret = 0; - - if (ar->arWmiReady == FALSE) { - return -EIO; - } - - if (copy_from_user(&cmd, (char *)((unsigned int *)rq->ifr_data + 1), sizeof(cmd))) { - return -EFAULT; - } - - if( wmi_set_lq_threshold_params(ar->arWmi, &cmd) != A_OK ) { - ret = -EIO; - } - - return ret; -} - - -static int -ar6000_ioctl_set_probedSsid(struct net_device *dev, struct ifreq *rq) -{ - AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev); - WMI_PROBED_SSID_CMD cmd; - int ret = 0; - - if (ar->arWmiReady == FALSE) { - return -EIO; - } - - if (copy_from_user(&cmd, rq->ifr_data, sizeof(cmd))) { - return -EFAULT; - } - - if (wmi_probedSsid_cmd(ar->arWmi, cmd.entryIndex, cmd.flag, cmd.ssidLength, - cmd.ssid) != A_OK) - { - ret = -EIO; - } - - return ret; -} - -static int -ar6000_ioctl_set_badAp(struct net_device *dev, struct ifreq *rq) -{ - AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev); - WMI_ADD_BAD_AP_CMD cmd; - int ret = 0; - - if (ar->arWmiReady == FALSE) { - return -EIO; - } - - - if (copy_from_user(&cmd, rq->ifr_data, sizeof(cmd))) { - return -EFAULT; - } - - if (cmd.badApIndex > WMI_MAX_BAD_AP_INDEX) { - return -EIO; - } - - if (A_MEMCMP(cmd.bssid, null_mac, AR6000_ETH_ADDR_LEN) == 0) { - /* - * This is a delete badAP. - */ - if (wmi_deleteBadAp_cmd(ar->arWmi, cmd.badApIndex) != A_OK) { - ret = -EIO; - } - } else { - if (wmi_addBadAp_cmd(ar->arWmi, cmd.badApIndex, cmd.bssid) != A_OK) { - ret = -EIO; - } - } - - return ret; -} - -static int -ar6000_ioctl_create_qos(struct net_device *dev, struct ifreq *rq) -{ - AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev); - WMI_CREATE_PSTREAM_CMD cmd; - A_STATUS ret; - - if (ar->arWmiReady == FALSE) { - return -EIO; - } - - - if (copy_from_user(&cmd, rq->ifr_data, sizeof(cmd))) { - return -EFAULT; - } - - ret = wmi_verify_tspec_params(&cmd, tspecCompliance); - if (ret == A_OK) - ret = wmi_create_pstream_cmd(ar->arWmi, &cmd); - - switch (ret) { - case A_OK: - return 0; - case A_EBUSY : - return -EBUSY; - case A_NO_MEMORY: - return -ENOMEM; - case A_EINVAL: - default: - return -EFAULT; - } -} - -static int -ar6000_ioctl_delete_qos(struct net_device *dev, struct ifreq *rq) -{ - AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev); - WMI_DELETE_PSTREAM_CMD cmd; - int ret = 0; - - if (ar->arWmiReady == FALSE) { - return -EIO; - } - - if (copy_from_user(&cmd, rq->ifr_data, sizeof(cmd))) { - return -EFAULT; - } - - ret = wmi_delete_pstream_cmd(ar->arWmi, cmd.trafficClass, cmd.tsid); - - switch (ret) { - case A_OK: - return 0; - case A_EBUSY : - return -EBUSY; - case A_NO_MEMORY: - return -ENOMEM; - case A_EINVAL: - default: - return -EFAULT; - } -} - -static int -ar6000_ioctl_get_qos_queue(struct net_device *dev, struct ifreq *rq) -{ - AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev); - struct ar6000_queuereq qreq; - int ret = 0; - - if (ar->arWmiReady == FALSE) { - return -EIO; - } - - if( copy_from_user(&qreq, rq->ifr_data, - sizeof(struct ar6000_queuereq))) - return -EFAULT; - - qreq.activeTsids = wmi_get_mapped_qos_queue(ar->arWmi, qreq.trafficClass); - - if (copy_to_user(rq->ifr_data, &qreq, - sizeof(struct ar6000_queuereq))) - { - ret = -EFAULT; - } - - return ret; -} - -#ifdef CONFIG_HOST_TCMD_SUPPORT -static A_STATUS -ar6000_ioctl_tcmd_get_rx_report(struct net_device *dev, - struct ifreq *rq, A_UINT8 *data, A_UINT32 len) -{ - AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev); - A_UINT32 buf[2]; - int ret = 0; - - if (ar->arWmiReady == FALSE) { - return -EIO; - } - - if (down_interruptible(&ar->arSem)) { - return -ERESTARTSYS; - } - ar->tcmdRxReport = 0; - if (wmi_test_cmd(ar->arWmi, data, len) != A_OK) { - up(&ar->arSem); - return -EIO; - } - - wait_event_interruptible_timeout(arEvent, ar->tcmdRxReport != 0, wmitimeout * HZ); - - if (signal_pending(current)) { - ret = -EINTR; - } - - buf[0] = ar->tcmdRxTotalPkt; - buf[1] = ar->tcmdRxRssi; - if (!ret && copy_to_user(rq->ifr_data, buf, sizeof(buf))) { - ret = -EFAULT; - } - - up(&ar->arSem); - - return ret; -} - -void -ar6000_tcmd_rx_report_event(void *devt, A_UINT8 * results, int len) -{ - AR_SOFTC_T *ar = (AR_SOFTC_T *)devt; - TCMD_CONT_RX * rx_rep = (TCMD_CONT_RX *)results; - - ar->tcmdRxTotalPkt = rx_rep->u.report.totalPkt; - ar->tcmdRxRssi = rx_rep->u.report.rssiInDBm; - ar->tcmdRxReport = 1; - - wake_up(&arEvent); -} -#endif /* CONFIG_HOST_TCMD_SUPPORT*/ - -static int -ar6000_ioctl_set_error_report_bitmask(struct net_device *dev, struct ifreq *rq) -{ - AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev); - WMI_TARGET_ERROR_REPORT_BITMASK cmd; - int ret = 0; - - if (ar->arWmiReady == FALSE) { - return -EIO; - } - - if (copy_from_user(&cmd, rq->ifr_data, sizeof(cmd))) { - return -EFAULT; - } - - ret = wmi_set_error_report_bitmask(ar->arWmi, cmd.bitmask); - - return (ret==0 ? ret : -EINVAL); -} - -static int -ar6000_clear_target_stats(struct net_device *dev) -{ - AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev); - TARGET_STATS *pStats = &ar->arTargetStats; - int ret = 0; - - if (ar->arWmiReady == FALSE) { - return -EIO; - } - AR6000_SPIN_LOCK(&ar->arLock, 0); - A_MEMZERO(pStats, sizeof(TARGET_STATS)); - AR6000_SPIN_UNLOCK(&ar->arLock, 0); - return ret; -} - -static int -ar6000_ioctl_get_target_stats(struct net_device *dev, struct ifreq *rq) -{ - AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev); - TARGET_STATS_CMD cmd; - TARGET_STATS *pStats = &ar->arTargetStats; - int ret = 0; - - if (ar->arWmiReady == FALSE) { - return -EIO; - } - if (copy_from_user(&cmd, rq->ifr_data, sizeof(cmd))) { - return -EFAULT; - } - if (down_interruptible(&ar->arSem)) { - return -ERESTARTSYS; - } - - ar->statsUpdatePending = TRUE; - - if(wmi_get_stats_cmd(ar->arWmi) != A_OK) { - up(&ar->arSem); - return -EIO; - } - - wait_event_interruptible_timeout(arEvent, ar->statsUpdatePending == FALSE, wmitimeout * HZ); - - if (signal_pending(current)) { - ret = -EINTR; - } - - if (!ret && copy_to_user(rq->ifr_data, pStats, sizeof(*pStats))) { - ret = -EFAULT; - } - - if (cmd.clearStats == 1) { - ret = ar6000_clear_target_stats(dev); - } - - up(&ar->arSem); - - return ret; -} - -static int -ar6000_ioctl_set_access_params(struct net_device *dev, struct ifreq *rq) -{ - AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev); - WMI_SET_ACCESS_PARAMS_CMD cmd; - int ret = 0; - - if (ar->arWmiReady == FALSE) { - return -EIO; - } - - if (copy_from_user(&cmd, rq->ifr_data, sizeof(cmd))) { - return -EFAULT; - } - - if (wmi_set_access_params_cmd(ar->arWmi, cmd.txop, cmd.eCWmin, cmd.eCWmax, - cmd.aifsn) == A_OK) - { - ret = 0; - } else { - ret = -EINVAL; - } - - return (ret); -} - -static int -ar6000_ioctl_set_disconnect_timeout(struct net_device *dev, struct ifreq *rq) -{ - AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev); - WMI_DISC_TIMEOUT_CMD cmd; - int ret = 0; - - if (ar->arWmiReady == FALSE) { - return -EIO; - } - - if (copy_from_user(&cmd, rq->ifr_data, sizeof(cmd))) { - return -EFAULT; - } - - if (wmi_disctimeout_cmd(ar->arWmi, cmd.disconnectTimeout) == A_OK) - { - ret = 0; - } else { - ret = -EINVAL; - } - - return (ret); -} - -static int -ar6000_xioctl_set_voice_pkt_size(struct net_device *dev, char * userdata) -{ - AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev); - WMI_SET_VOICE_PKT_SIZE_CMD cmd; - int ret = 0; - - if (ar->arWmiReady == FALSE) { - return -EIO; - } - - if (copy_from_user(&cmd, userdata, sizeof(cmd))) { - return -EFAULT; - } - - if (wmi_set_voice_pkt_size_cmd(ar->arWmi, cmd.voicePktSize) == A_OK) - { - ret = 0; - } else { - ret = -EINVAL; - } - - - return (ret); -} - -static int -ar6000_xioctl_set_max_sp_len(struct net_device *dev, char * userdata) -{ - AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev); - WMI_SET_MAX_SP_LEN_CMD cmd; - int ret = 0; - - if (ar->arWmiReady == FALSE) { - return -EIO; - } - - if (copy_from_user(&cmd, userdata, sizeof(cmd))) { - return -EFAULT; - } - - if (wmi_set_max_sp_len_cmd(ar->arWmi, cmd.maxSPLen) == A_OK) - { - ret = 0; - } else { - ret = -EINVAL; - } - - return (ret); -} - - -static int -ar6000_xioctl_set_bt_status_cmd(struct net_device *dev, char * userdata) -{ - AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev); - WMI_SET_BT_STATUS_CMD cmd; - int ret = 0; - - if (ar->arWmiReady == FALSE) { - return -EIO; - } - - if (copy_from_user(&cmd, userdata, sizeof(cmd))) { - return -EFAULT; - } - - if (wmi_set_bt_status_cmd(ar->arWmi, cmd.streamType, cmd.status) == A_OK) - { - ret = 0; - } else { - ret = -EINVAL; - } - - return (ret); -} - -static int -ar6000_xioctl_set_bt_params_cmd(struct net_device *dev, char * userdata) -{ - AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev); - WMI_SET_BT_PARAMS_CMD cmd; - int ret = 0; - - if (ar->arWmiReady == FALSE) { - return -EIO; - } - - if (copy_from_user(&cmd, userdata, sizeof(cmd))) { - return -EFAULT; - } - - if (wmi_set_bt_params_cmd(ar->arWmi, &cmd) == A_OK) - { - ret = 0; - } else { - ret = -EINVAL; - } - - return (ret); -} - -#ifdef CONFIG_HOST_GPIO_SUPPORT -struct ar6000_gpio_intr_wait_cmd_s gpio_intr_results; -/* gpio_reg_results and gpio_data_available are protected by arSem */ -static struct ar6000_gpio_register_cmd_s gpio_reg_results; -static A_BOOL gpio_data_available; /* Requested GPIO data available */ -static A_BOOL gpio_intr_available; /* GPIO interrupt info available */ -static A_BOOL gpio_ack_received; /* GPIO ack was received */ - -/* Host-side initialization for General Purpose I/O support */ -void ar6000_gpio_init(void) -{ - gpio_intr_available = FALSE; - gpio_data_available = FALSE; - gpio_ack_received = FALSE; -} - -/* - * Called when a GPIO interrupt is received from the Target. - * intr_values shows which GPIO pins have interrupted. - * input_values shows a recent value of GPIO pins. - */ -void -ar6000_gpio_intr_rx(A_UINT32 intr_mask, A_UINT32 input_values) -{ - gpio_intr_results.intr_mask = intr_mask; - gpio_intr_results.input_values = input_values; - *((volatile A_BOOL *)&gpio_intr_available) = TRUE; - wake_up(&arEvent); -} - -/* - * This is called when a response is received from the Target - * for a previous or ar6000_gpio_input_get or ar6000_gpio_register_get - * call. - */ -void -ar6000_gpio_data_rx(A_UINT32 reg_id, A_UINT32 value) -{ - gpio_reg_results.gpioreg_id = reg_id; - gpio_reg_results.value = value; - *((volatile A_BOOL *)&gpio_data_available) = TRUE; - wake_up(&arEvent); -} - -/* - * This is called when an acknowledgement is received from the Target - * for a previous or ar6000_gpio_output_set or ar6000_gpio_register_set - * call. - */ -void -ar6000_gpio_ack_rx(void) -{ - gpio_ack_received = TRUE; - wake_up(&arEvent); -} - -A_STATUS -ar6000_gpio_output_set(struct net_device *dev, - A_UINT32 set_mask, - A_UINT32 clear_mask, - A_UINT32 enable_mask, - A_UINT32 disable_mask) -{ - AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev); - - gpio_ack_received = FALSE; - return wmi_gpio_output_set(ar->arWmi, - set_mask, clear_mask, enable_mask, disable_mask); -} - -static A_STATUS -ar6000_gpio_input_get(struct net_device *dev) -{ - AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev); - - *((volatile A_BOOL *)&gpio_data_available) = FALSE; - return wmi_gpio_input_get(ar->arWmi); -} - -static A_STATUS -ar6000_gpio_register_set(struct net_device *dev, - A_UINT32 gpioreg_id, - A_UINT32 value) -{ - AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev); - - gpio_ack_received = FALSE; - return wmi_gpio_register_set(ar->arWmi, gpioreg_id, value); -} - -static A_STATUS -ar6000_gpio_register_get(struct net_device *dev, - A_UINT32 gpioreg_id) -{ - AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev); - - *((volatile A_BOOL *)&gpio_data_available) = FALSE; - return wmi_gpio_register_get(ar->arWmi, gpioreg_id); -} - -static A_STATUS -ar6000_gpio_intr_ack(struct net_device *dev, - A_UINT32 ack_mask) -{ - AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev); - - gpio_intr_available = FALSE; - return wmi_gpio_intr_ack(ar->arWmi, ack_mask); -} -#endif /* CONFIG_HOST_GPIO_SUPPORT */ - -int ar6000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) -{ - AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev); - HIF_DEVICE *hifDevice = ar->arHifDevice; - int ret, param, param2; - unsigned int address = 0; - unsigned int length = 0; - unsigned char *buffer; - char *userdata; - A_UINT32 connectCtrlFlags; - - - static WMI_SCAN_PARAMS_CMD scParams = {0, 0, 0, 0, 0, - WMI_SHORTSCANRATIO_DEFAULT, - DEFAULT_SCAN_CTRL_FLAGS, - 0}; - WMI_SET_AKMP_PARAMS_CMD akmpParams; - WMI_SET_PMKID_LIST_CMD pmkidInfo; - - if (cmd == AR6000_IOCTL_EXTENDED) - { - /* - * This allows for many more wireless ioctls than would otherwise - * be available. Applications embed the actual ioctl command in - * the first word of the parameter block, and use the command - * AR6000_IOCTL_EXTENDED_CMD on the ioctl call. - */ - get_user(cmd, (int *)rq->ifr_data); - userdata = (char *)(((unsigned int *)rq->ifr_data)+1); - } - else - { - userdata = (char *)rq->ifr_data; - } - - if ((ar->arWlanState == WLAN_DISABLED) && - ((cmd != AR6000_XIOCTRL_WMI_SET_WLAN_STATE) && - (cmd != AR6000_XIOCTL_DIAG_READ) && - (cmd != AR6000_XIOCTL_DIAG_WRITE))) - { - return -EIO; - } - - ret = 0; - switch(cmd) - { -#ifdef CONFIG_HOST_TCMD_SUPPORT - case AR6000_XIOCTL_TCMD_CONT_TX: - { - TCMD_CONT_TX txCmd; - - if (ar->tcmdPm == TCMD_PM_SLEEP) { - A_PRINTF("Can NOT send tx tcmd when target is asleep! \n"); - return -EFAULT; - } - - if(copy_from_user(&txCmd, userdata, sizeof(TCMD_CONT_TX))) - return -EFAULT; - wmi_test_cmd(ar->arWmi,(A_UINT8 *)&txCmd, sizeof(TCMD_CONT_TX)); - } - break; - case AR6000_XIOCTL_TCMD_CONT_RX: - { - TCMD_CONT_RX rxCmd; - - if (ar->tcmdPm == TCMD_PM_SLEEP) { - A_PRINTF("Can NOT send rx tcmd when target is asleep! \n"); - return -EFAULT; - } - if(copy_from_user(&rxCmd, userdata, sizeof(TCMD_CONT_RX))) - return -EFAULT; - switch(rxCmd.act) - { - case TCMD_CONT_RX_PROMIS: - case TCMD_CONT_RX_FILTER: - case TCMD_CONT_RX_SETMAC: - wmi_test_cmd(ar->arWmi,(A_UINT8 *)&rxCmd, - sizeof(TCMD_CONT_RX)); - break; - case TCMD_CONT_RX_REPORT: - ar6000_ioctl_tcmd_get_rx_report(dev, rq, - (A_UINT8 *)&rxCmd, sizeof(TCMD_CONT_RX)); - break; - default: - A_PRINTF("Unknown Cont Rx mode: %d\n",rxCmd.act); - return -EINVAL; - } - } - break; - case AR6000_XIOCTL_TCMD_PM: - { - TCMD_PM pmCmd; - - if(copy_from_user(&pmCmd, userdata, sizeof(TCMD_PM))) - return -EFAULT; - ar->tcmdPm = pmCmd.mode; - wmi_test_cmd(ar->arWmi, (A_UINT8*)&pmCmd, sizeof(TCMD_PM)); - } - break; -#endif /* CONFIG_HOST_TCMD_SUPPORT */ - - case AR6000_XIOCTL_BMI_DONE: - ret = BMIDone(hifDevice); - break; - - case AR6000_XIOCTL_BMI_READ_MEMORY: - get_user(address, (unsigned int *)userdata); - get_user(length, (unsigned int *)userdata + 1); - AR_DEBUG_PRINTF("Read Memory (address: 0x%x, length: %d)\n", - address, length); - if ((buffer = (unsigned char *)A_MALLOC(length)) != NULL) { - A_MEMZERO(buffer, length); - ret = BMIReadMemory(hifDevice, address, buffer, length); - if (copy_to_user(rq->ifr_data, buffer, length)) { - ret = -EFAULT; - } - A_FREE(buffer); - } else { - ret = -ENOMEM; - } - break; - - case AR6000_XIOCTL_BMI_WRITE_MEMORY: - get_user(address, (unsigned int *)userdata); - get_user(length, (unsigned int *)userdata + 1); - AR_DEBUG_PRINTF("Write Memory (address: 0x%x, length: %d)\n", - address, length); - if ((buffer = (unsigned char *)A_MALLOC(length)) != NULL) { - A_MEMZERO(buffer, length); - if (copy_from_user(buffer, &userdata[sizeof(address) + - sizeof(length)], length)) - { - ret = -EFAULT; - } else { - ret = BMIWriteMemory(hifDevice, address, buffer, length); - } - A_FREE(buffer); - } else { - ret = -ENOMEM; - } - break; - - case AR6000_XIOCTL_BMI_TEST: - AR_DEBUG_PRINTF("No longer supported\n"); - ret = -EOPNOTSUPP; - break; - - case AR6000_XIOCTL_BMI_EXECUTE: - get_user(address, (unsigned int *)userdata); - get_user(param, (unsigned int *)userdata + 1); - AR_DEBUG_PRINTF("Execute (address: 0x%x, param: %d)\n", - address, param); - ret = BMIExecute(hifDevice, address, ¶m); - put_user(param, (unsigned int *)rq->ifr_data); /* return value */ - break; - - case AR6000_XIOCTL_BMI_SET_APP_START: - get_user(address, (unsigned int *)userdata); - AR_DEBUG_PRINTF("Set App Start (address: 0x%x)\n", address); - ret = BMISetAppStart(hifDevice, address); - break; - - case AR6000_XIOCTL_BMI_READ_SOC_REGISTER: - get_user(address, (unsigned int *)userdata); - ret = BMIReadSOCRegister(hifDevice, address, ¶m); - put_user(param, (unsigned int *)rq->ifr_data); /* return value */ - break; - - case AR6000_XIOCTL_BMI_WRITE_SOC_REGISTER: - get_user(address, (unsigned int *)userdata); - get_user(param, (unsigned int *)userdata + 1); - ret = BMIWriteSOCRegister(hifDevice, address, param); - break; - -#ifdef HTC_RAW_INTERFACE - case AR6000_XIOCTL_HTC_RAW_OPEN: - ret = A_OK; - if (!arRawIfEnabled(ar)) { - /* make sure block size is set in case the target was reset since last - * BMI phase (i.e. flashup downloads) */ - ret = ar6000_SetHTCBlockSize(ar); - if (A_FAILED(ret)) { - break; - } - /* Terminate the BMI phase */ - ret = BMIDone(hifDevice); - if (ret == A_OK) { - ret = ar6000_htc_raw_open(ar); - } - } - break; - - case AR6000_XIOCTL_HTC_RAW_CLOSE: - if (arRawIfEnabled(ar)) { - ret = ar6000_htc_raw_close(ar); - arRawIfEnabled(ar) = FALSE; - } else { - ret = A_ERROR; - } - break; - - case AR6000_XIOCTL_HTC_RAW_READ: - if (arRawIfEnabled(ar)) { - unsigned int streamID; - get_user(streamID, (unsigned int *)userdata); - get_user(length, (unsigned int *)userdata + 1); - buffer = rq->ifr_data + sizeof(length); - ret = ar6000_htc_raw_read(ar, (HTC_RAW_STREAM_ID)streamID, - buffer, length); - put_user(ret, (unsigned int *)rq->ifr_data); - } else { - ret = A_ERROR; - } - break; - - case AR6000_XIOCTL_HTC_RAW_WRITE: - if (arRawIfEnabled(ar)) { - unsigned int streamID; - get_user(streamID, (unsigned int *)userdata); - get_user(length, (unsigned int *)userdata + 1); - buffer = userdata + sizeof(streamID) + sizeof(length); - ret = ar6000_htc_raw_write(ar, (HTC_RAW_STREAM_ID)streamID, - buffer, length); - put_user(ret, (unsigned int *)rq->ifr_data); - } else { - ret = A_ERROR; - } - break; -#endif /* HTC_RAW_INTERFACE */ - - case AR6000_IOCTL_WMI_GETREV: - { - if (copy_to_user(rq->ifr_data, &ar->arVersion, - sizeof(ar->arVersion))) - { - ret = -EFAULT; - } - break; - } - case AR6000_IOCTL_WMI_SETPWR: - { - WMI_POWER_MODE_CMD pwrModeCmd; - - if (ar->arWmiReady == FALSE) { - ret = -EIO; - } else if (copy_from_user(&pwrModeCmd, userdata, - sizeof(pwrModeCmd))) - { - ret = -EFAULT; - } else { - if (wmi_powermode_cmd(ar->arWmi, pwrModeCmd.powerMode) - != A_OK) - { - ret = -EIO; - } - } - break; - } - case AR6000_IOCTL_WMI_SET_IBSS_PM_CAPS: - { - WMI_IBSS_PM_CAPS_CMD ibssPmCaps; - - if (ar->arWmiReady == FALSE) { - ret = -EIO; - } else if (copy_from_user(&ibssPmCaps, userdata, - sizeof(ibssPmCaps))) - { - ret = -EFAULT; - } else { - if (wmi_ibsspmcaps_cmd(ar->arWmi, ibssPmCaps.power_saving, ibssPmCaps.ttl, - ibssPmCaps.atim_windows, ibssPmCaps.timeout_value) != A_OK) - { - ret = -EIO; - } - AR6000_SPIN_LOCK(&ar->arLock, 0); - ar->arIbssPsEnable = ibssPmCaps.power_saving; - AR6000_SPIN_UNLOCK(&ar->arLock, 0); - } - break; - } - case AR6000_IOCTL_WMI_SET_PMPARAMS: - { - WMI_POWER_PARAMS_CMD pmParams; - - if (ar->arWmiReady == FALSE) { - ret = -EIO; - } else if (copy_from_user(&pmParams, userdata, - sizeof(pmParams))) - { - ret = -EFAULT; - } else { - if (wmi_pmparams_cmd(ar->arWmi, pmParams.idle_period, - pmParams.pspoll_number, - pmParams.dtim_policy) != A_OK) - { - ret = -EIO; - } - } - break; - } - case AR6000_IOCTL_WMI_SETSCAN: - { - if (ar->arWmiReady == FALSE) { - ret = -EIO; - } else if (copy_from_user(&scParams, userdata, - sizeof(scParams))) - { - ret = -EFAULT; - } else { - if (CAN_SCAN_IN_CONNECT(scParams.scanCtrlFlags)) { - ar->arSkipScan = FALSE; - } else { - ar->arSkipScan = TRUE; - } - - if (wmi_scanparams_cmd(ar->arWmi, scParams.fg_start_period, - scParams.fg_end_period, - scParams.bg_period, - scParams.minact_chdwell_time, - scParams.maxact_chdwell_time, - scParams.pas_chdwell_time, - scParams.shortScanRatio, - scParams.scanCtrlFlags, - scParams.max_dfsch_act_time) != A_OK) - { - ret = -EIO; - } - } - break; - } - case AR6000_IOCTL_WMI_SETLISTENINT: - { - WMI_LISTEN_INT_CMD listenCmd; - - if (ar->arWmiReady == FALSE) { - ret = -EIO; - } else if (copy_from_user(&listenCmd, userdata, - sizeof(listenCmd))) - { - ret = -EFAULT; - } else { - if (wmi_listeninterval_cmd(ar->arWmi, listenCmd.listenInterval, listenCmd.numBeacons) != A_OK) { - ret = -EIO; - } else { - AR6000_SPIN_LOCK(&ar->arLock, 0); - ar->arListenInterval = param; - AR6000_SPIN_UNLOCK(&ar->arLock, 0); - } - - } - break; - } - case AR6000_IOCTL_WMI_SET_BMISS_TIME: - { - WMI_BMISS_TIME_CMD bmissCmd; - - if (ar->arWmiReady == FALSE) { - ret = -EIO; - } else if (copy_from_user(&bmissCmd, userdata, - sizeof(bmissCmd))) - { - ret = -EFAULT; - } else { - if (wmi_bmisstime_cmd(ar->arWmi, bmissCmd.bmissTime, bmissCmd.numBeacons) != A_OK) { - ret = -EIO; - } - } - break; - } - case AR6000_IOCTL_WMI_SETBSSFILTER: - { - if (ar->arWmiReady == FALSE) { - ret = -EIO; - } else { - - get_user(param, (unsigned char *)userdata); - get_user(param2, (unsigned int *)(userdata + 1)); - printk("SETBSSFILTER: filter 0x%x, mask: 0x%x\n", param, param2); - if (wmi_bssfilter_cmd(ar->arWmi, param, param2) != A_OK) { - ret = -EIO; - } - } - break; - } - case AR6000_IOCTL_WMI_SET_SNRTHRESHOLD: - { - ret = ar6000_ioctl_set_snr_threshold(dev, rq); - break; - } - case AR6000_XIOCTL_WMI_SET_RSSITHRESHOLD: - { - ret = ar6000_ioctl_set_rssi_threshold(dev, rq); - break; - } - case AR6000_XIOCTL_WMI_CLR_RSSISNR: - { - if (ar->arWmiReady == FALSE) { - ret = -EIO; - } - ret = wmi_clr_rssi_snr(ar->arWmi); - break; - } - case AR6000_XIOCTL_WMI_SET_LQTHRESHOLD: - { - ret = ar6000_ioctl_set_lq_threshold(dev, rq); - break; - } - case AR6000_XIOCTL_WMI_SET_LPREAMBLE: - { - WMI_SET_LPREAMBLE_CMD setLpreambleCmd; - - if (ar->arWmiReady == FALSE) { - ret = -EIO; - } else if (copy_from_user(&setLpreambleCmd, userdata, - sizeof(setLpreambleCmd))) - { - ret = -EFAULT; - } else { - if (wmi_set_lpreamble_cmd(ar->arWmi, setLpreambleCmd.status) - != A_OK) - { - ret = -EIO; - } - } - - break; - } - case AR6000_XIOCTL_WMI_SET_RTS: - { - WMI_SET_RTS_CMD rtsCmd; - - if (ar->arWmiReady == FALSE) { - ret = -EIO; - } else if (copy_from_user(&rtsCmd, userdata, - sizeof(rtsCmd))) - { - ret = -EFAULT; - } else { - if (wmi_set_rts_cmd(ar->arWmi, rtsCmd.threshold) - != A_OK) - { - ret = -EIO; - } - } - - break; - } - case AR6000_XIOCTL_WMI_SET_WMM: - { - ret = ar6000_ioctl_set_wmm(dev, rq); - break; - } - case AR6000_XIOCTL_WMI_SET_TXOP: - { - ret = ar6000_ioctl_set_txop(dev, rq); - break; - } - case AR6000_XIOCTL_WMI_GET_RD: - { - ret = ar6000_ioctl_get_rd(dev, rq); - break; - } - case AR6000_IOCTL_WMI_SET_CHANNELPARAMS: - { - ret = ar6000_ioctl_set_channelParams(dev, rq); - break; - } - case AR6000_IOCTL_WMI_SET_PROBEDSSID: - { - ret = ar6000_ioctl_set_probedSsid(dev, rq); - break; - } - case AR6000_IOCTL_WMI_SET_BADAP: - { - ret = ar6000_ioctl_set_badAp(dev, rq); - break; - } - case AR6000_IOCTL_WMI_CREATE_QOS: - { - ret = ar6000_ioctl_create_qos(dev, rq); - break; - } - case AR6000_IOCTL_WMI_DELETE_QOS: - { - ret = ar6000_ioctl_delete_qos(dev, rq); - break; - } - case AR6000_IOCTL_WMI_GET_QOS_QUEUE: - { - ret = ar6000_ioctl_get_qos_queue(dev, rq); - break; - } - case AR6000_IOCTL_WMI_GET_TARGET_STATS: - { - ret = ar6000_ioctl_get_target_stats(dev, rq); - break; - } - case AR6000_IOCTL_WMI_SET_ERROR_REPORT_BITMASK: - { - ret = ar6000_ioctl_set_error_report_bitmask(dev, rq); - break; - } - case AR6000_IOCTL_WMI_SET_ASSOC_INFO: - { - WMI_SET_ASSOC_INFO_CMD cmd; - A_UINT8 assocInfo[WMI_MAX_ASSOC_INFO_LEN]; - - if (ar->arWmiReady == FALSE) { - ret = -EIO; - } else { - get_user(cmd.ieType, userdata); - if (cmd.ieType >= WMI_MAX_ASSOC_INFO_TYPE) { - ret = -EIO; - } else { - get_user(cmd.bufferSize, userdata + 1); - if (cmd.bufferSize > WMI_MAX_ASSOC_INFO_LEN) { - ret = -EFAULT; - break; - } - if (copy_from_user(assocInfo, userdata + 2, - cmd.bufferSize)) - { - ret = -EFAULT; - } else { - if (wmi_associnfo_cmd(ar->arWmi, cmd.ieType, - cmd.bufferSize, - assocInfo) != A_OK) - { - ret = -EIO; - } - } - } - } - break; - } - case AR6000_IOCTL_WMI_SET_ACCESS_PARAMS: - { - ret = ar6000_ioctl_set_access_params(dev, rq); - break; - } - case AR6000_IOCTL_WMI_SET_DISC_TIMEOUT: - { - ret = ar6000_ioctl_set_disconnect_timeout(dev, rq); - break; - } - case AR6000_XIOCTL_FORCE_TARGET_RESET: - { - if (ar->arHtcTarget) - { -// HTCForceReset(htcTarget); - } - else - { - AR_DEBUG_PRINTF("ar6000_ioctl cannot attempt reset.\n"); - } - break; - } - case AR6000_XIOCTL_TARGET_INFO: - case AR6000_XIOCTL_CHECK_TARGET_READY: /* backwards compatibility */ - { - /* If we made it to here, then the Target exists and is ready. */ - - if (cmd == AR6000_XIOCTL_TARGET_INFO) { - if (copy_to_user((A_UINT32 *)rq->ifr_data, &ar->arVersion.target_ver, - sizeof(ar->arVersion.target_ver))) - { - ret = -EFAULT; - } - if (copy_to_user(((A_UINT32 *)rq->ifr_data)+1, &ar->arTargetType, - sizeof(ar->arTargetType))) - { - ret = -EFAULT; - } - } - break; - } - case AR6000_XIOCTL_WMI_SET_HB_CHALLENGE_RESP_PARAMS: - { - WMI_SET_HB_CHALLENGE_RESP_PARAMS_CMD hbparam; - - if (copy_from_user(&hbparam, userdata, sizeof(hbparam))) - { - ret = -EFAULT; - } else { - AR6000_SPIN_LOCK(&ar->arLock, 0); - /* Start a cyclic timer with the parameters provided. */ - if (hbparam.frequency) { - ar->arHBChallengeResp.frequency = hbparam.frequency; - } - if (hbparam.threshold) { - ar->arHBChallengeResp.missThres = hbparam.threshold; - } - - /* Delete the pending timer and start a new one */ - if (timer_pending(&ar->arHBChallengeResp.timer)) { - A_UNTIMEOUT(&ar->arHBChallengeResp.timer); - } - A_TIMEOUT_MS(&ar->arHBChallengeResp.timer, ar->arHBChallengeResp.frequency * 1000, 0); - AR6000_SPIN_UNLOCK(&ar->arLock, 0); - } - break; - } - case AR6000_XIOCTL_WMI_GET_HB_CHALLENGE_RESP: - { - A_UINT32 cookie; - - if (copy_from_user(&cookie, userdata, sizeof(cookie))) { - return -EFAULT; - } - - /* Send the challenge on the control channel */ - if (wmi_get_challenge_resp_cmd(ar->arWmi, cookie, APP_HB_CHALLENGE) != A_OK) { - return -EIO; - } - break; - } -#ifdef USER_KEYS - case AR6000_XIOCTL_USER_SETKEYS: - { - - ar->user_savedkeys_stat = USER_SAVEDKEYS_STAT_RUN; - - if (copy_from_user(&ar->user_key_ctrl, userdata, - sizeof(ar->user_key_ctrl))) - { - return -EFAULT; - } - - A_PRINTF("ar6000 USER set key %x\n", ar->user_key_ctrl); - break; - } -#endif /* USER_KEYS */ - -#ifdef CONFIG_HOST_GPIO_SUPPORT - case AR6000_XIOCTL_GPIO_OUTPUT_SET: - { - struct ar6000_gpio_output_set_cmd_s gpio_output_set_cmd; - - if (ar->arWmiReady == FALSE) { - return -EIO; - } - if (down_interruptible(&ar->arSem)) { - return -ERESTARTSYS; - } - - if (copy_from_user(&gpio_output_set_cmd, userdata, - sizeof(gpio_output_set_cmd))) - { - ret = -EFAULT; - } else { - ret = ar6000_gpio_output_set(dev, - gpio_output_set_cmd.set_mask, - gpio_output_set_cmd.clear_mask, - gpio_output_set_cmd.enable_mask, - gpio_output_set_cmd.disable_mask); - if (ret != A_OK) { - ret = EIO; - } - } - up(&ar->arSem); - break; - } - case AR6000_XIOCTL_GPIO_INPUT_GET: - { - if (ar->arWmiReady == FALSE) { - return -EIO; - } - if (down_interruptible(&ar->arSem)) { - return -ERESTARTSYS; - } - - ret = ar6000_gpio_input_get(dev); - if (ret != A_OK) { - up(&ar->arSem); - return -EIO; - } - - /* Wait for Target to respond. */ - wait_event_interruptible(arEvent, gpio_data_available); - if (signal_pending(current)) { - ret = -EINTR; - } else { - A_ASSERT(gpio_reg_results.gpioreg_id == GPIO_ID_NONE); - - if (copy_to_user(userdata, &gpio_reg_results.value, - sizeof(gpio_reg_results.value))) - { - ret = -EFAULT; - } - } - up(&ar->arSem); - break; - } - case AR6000_XIOCTL_GPIO_REGISTER_SET: - { - struct ar6000_gpio_register_cmd_s gpio_register_cmd; - - if (ar->arWmiReady == FALSE) { - return -EIO; - } - if (down_interruptible(&ar->arSem)) { - return -ERESTARTSYS; - } - - if (copy_from_user(&gpio_register_cmd, userdata, - sizeof(gpio_register_cmd))) - { - ret = -EFAULT; - } else { - ret = ar6000_gpio_register_set(dev, - gpio_register_cmd.gpioreg_id, - gpio_register_cmd.value); - if (ret != A_OK) { - ret = EIO; - } - - /* Wait for acknowledgement from Target */ - wait_event_interruptible(arEvent, gpio_ack_received); - if (signal_pending(current)) { - ret = -EINTR; - } - } - up(&ar->arSem); - break; - } - case AR6000_XIOCTL_GPIO_REGISTER_GET: - { - struct ar6000_gpio_register_cmd_s gpio_register_cmd; - - if (ar->arWmiReady == FALSE) { - return -EIO; - } - if (down_interruptible(&ar->arSem)) { - return -ERESTARTSYS; - } - - if (copy_from_user(&gpio_register_cmd, userdata, - sizeof(gpio_register_cmd))) - { - ret = -EFAULT; - } else { - ret = ar6000_gpio_register_get(dev, gpio_register_cmd.gpioreg_id); - if (ret != A_OK) { - up(&ar->arSem); - return -EIO; - } - - /* Wait for Target to respond. */ - wait_event_interruptible(arEvent, gpio_data_available); - if (signal_pending(current)) { - ret = -EINTR; - } else { - A_ASSERT(gpio_register_cmd.gpioreg_id == gpio_reg_results.gpioreg_id); - if (copy_to_user(userdata, &gpio_reg_results, - sizeof(gpio_reg_results))) - { - ret = -EFAULT; - } - } - } - up(&ar->arSem); - break; - } - case AR6000_XIOCTL_GPIO_INTR_ACK: - { - struct ar6000_gpio_intr_ack_cmd_s gpio_intr_ack_cmd; - - if (ar->arWmiReady == FALSE) { - return -EIO; - } - if (down_interruptible(&ar->arSem)) { - return -ERESTARTSYS; - } - - if (copy_from_user(&gpio_intr_ack_cmd, userdata, - sizeof(gpio_intr_ack_cmd))) - { - ret = -EFAULT; - } else { - ret = ar6000_gpio_intr_ack(dev, gpio_intr_ack_cmd.ack_mask); - if (ret != A_OK) { - ret = EIO; - } - } - up(&ar->arSem); - break; - } - case AR6000_XIOCTL_GPIO_INTR_WAIT: - { - /* Wait for Target to report an interrupt. */ - dev_hold(dev); - rtnl_unlock(); - wait_event_interruptible(arEvent, gpio_intr_available); - rtnl_lock(); - __dev_put(dev); - - if (signal_pending(current)) { - ret = -EINTR; - } else { - if (copy_to_user(userdata, &gpio_intr_results, - sizeof(gpio_intr_results))) - { - ret = -EFAULT; - } - } - break; - } -#endif /* CONFIG_HOST_GPIO_SUPPORT */ - - case AR6000_XIOCTL_DBGLOG_CFG_MODULE: - { - struct ar6000_dbglog_module_config_s config; - - if (copy_from_user(&config, userdata, sizeof(config))) { - return -EFAULT; - } - - /* Send the challenge on the control channel */ - if (wmi_config_debug_module_cmd(ar->arWmi, config.mmask, - config.tsr, config.rep, - config.size, config.valid) != A_OK) - { - return -EIO; - } - break; - } - - case AR6000_XIOCTL_DBGLOG_GET_DEBUG_LOGS: - { - /* Send the challenge on the control channel */ - if (ar6000_dbglog_get_debug_logs(ar) != A_OK) - { - return -EIO; - } - break; - } - - case AR6000_XIOCTL_SET_ADHOC_BSSID: - { - WMI_SET_ADHOC_BSSID_CMD adhocBssid; - - if (ar->arWmiReady == FALSE) { - ret = -EIO; - } else if (copy_from_user(&adhocBssid, userdata, - sizeof(adhocBssid))) - { - ret = -EFAULT; - } else if (A_MEMCMP(adhocBssid.bssid, bcast_mac, - AR6000_ETH_ADDR_LEN) == 0) - { - ret = -EFAULT; - } else { - - A_MEMCPY(ar->arReqBssid, adhocBssid.bssid, sizeof(ar->arReqBssid)); - } - break; - } - - case AR6000_XIOCTL_SET_OPT_MODE: - { - WMI_SET_OPT_MODE_CMD optModeCmd; - AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev); - - if (ar->arWmiReady == FALSE) { - ret = -EIO; - } else if (copy_from_user(&optModeCmd, userdata, - sizeof(optModeCmd))) - { - ret = -EFAULT; - } else if (ar->arConnected && optModeCmd.optMode == SPECIAL_ON) { - ret = -EFAULT; - - } else if (wmi_set_opt_mode_cmd(ar->arWmi, optModeCmd.optMode) - != A_OK) - { - ret = -EIO; - } - break; - } - - case AR6000_XIOCTL_OPT_SEND_FRAME: - { - WMI_OPT_TX_FRAME_CMD optTxFrmCmd; - A_UINT8 data[MAX_OPT_DATA_LEN]; - - if (ar->arWmiReady == FALSE) { - ret = -EIO; - } else if (copy_from_user(&optTxFrmCmd, userdata, - sizeof(optTxFrmCmd))) - { - ret = -EFAULT; - } else if (copy_from_user(data, - userdata+sizeof(WMI_OPT_TX_FRAME_CMD)-1, - optTxFrmCmd.optIEDataLen)) - { - ret = -EFAULT; - } else { - ret = wmi_opt_tx_frame_cmd(ar->arWmi, - optTxFrmCmd.frmType, - optTxFrmCmd.dstAddr, - optTxFrmCmd.bssid, - optTxFrmCmd.optIEDataLen, - data); - } - - break; - } - case AR6000_XIOCTL_WMI_SETRETRYLIMITS: - { - WMI_SET_RETRY_LIMITS_CMD setRetryParams; - - if (ar->arWmiReady == FALSE) { - ret = -EIO; - } else if (copy_from_user(&setRetryParams, userdata, - sizeof(setRetryParams))) - { - ret = -EFAULT; - } else { - if (wmi_set_retry_limits_cmd(ar->arWmi, setRetryParams.frameType, - setRetryParams.trafficClass, - setRetryParams.maxRetries, - setRetryParams.enableNotify) != A_OK) - { - ret = -EIO; - } - AR6000_SPIN_LOCK(&ar->arLock, 0); - ar->arMaxRetries = setRetryParams.maxRetries; - AR6000_SPIN_UNLOCK(&ar->arLock, 0); - } - break; - } - - case AR6000_XIOCTL_SET_ADHOC_BEACON_INTVAL: - { - WMI_BEACON_INT_CMD bIntvlCmd; - - if (ar->arWmiReady == FALSE) { - ret = -EIO; - } else if (copy_from_user(&bIntvlCmd, userdata, - sizeof(bIntvlCmd))) - { - ret = -EFAULT; - } else if (wmi_set_adhoc_bconIntvl_cmd(ar->arWmi, bIntvlCmd.beaconInterval) - != A_OK) - { - ret = -EIO; - } - break; - } - case IEEE80211_IOCTL_SETAUTHALG: - { - AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev); - struct ieee80211req_authalg req; - - if (ar->arWmiReady == FALSE) { - ret = -EIO; - } else if (copy_from_user(&req, userdata, - sizeof(struct ieee80211req_authalg))) - { - ret = -EFAULT; - } else if (req.auth_alg == AUTH_ALG_OPEN_SYSTEM) { - ar->arDot11AuthMode = OPEN_AUTH; - ar->arPairwiseCrypto = NONE_CRYPT; - ar->arGroupCrypto = NONE_CRYPT; - } else if (req.auth_alg == AUTH_ALG_LEAP) { - ar->arDot11AuthMode = LEAP_AUTH; - } else { - ret = -EIO; - } - break; - } - - case AR6000_XIOCTL_SET_VOICE_PKT_SIZE: - ret = ar6000_xioctl_set_voice_pkt_size(dev, userdata); - break; - - case AR6000_XIOCTL_SET_MAX_SP: - ret = ar6000_xioctl_set_max_sp_len(dev, userdata); - break; - - case AR6000_XIOCTL_WMI_GET_ROAM_TBL: - ret = ar6000_ioctl_get_roam_tbl(dev, rq); - break; - case AR6000_XIOCTL_WMI_SET_ROAM_CTRL: - ret = ar6000_ioctl_set_roam_ctrl(dev, userdata); - break; - case AR6000_XIOCTRL_WMI_SET_POWERSAVE_TIMERS: - ret = ar6000_ioctl_set_powersave_timers(dev, userdata); - break; - case AR6000_XIOCTRL_WMI_GET_POWER_MODE: - ret = ar6000_ioctl_get_power_mode(dev, rq); - break; - case AR6000_XIOCTRL_WMI_SET_WLAN_STATE: - get_user(ar->arWlanState, (unsigned int *)userdata); - if (ar->arWmiReady == FALSE) { - ret = -EIO; - break; - } - - if (ar->arWlanState == WLAN_ENABLED) { - /* Enable foreground scanning */ - if (wmi_scanparams_cmd(ar->arWmi, scParams.fg_start_period, - scParams.fg_end_period, - scParams.bg_period, - scParams.minact_chdwell_time, - scParams.maxact_chdwell_time, - scParams.pas_chdwell_time, - scParams.shortScanRatio, - scParams.scanCtrlFlags, - scParams.max_dfsch_act_time) != A_OK) - { - ret = -EIO; - } - if (ar->arSsidLen) { - ar->arConnectPending = TRUE; - if (wmi_connect_cmd(ar->arWmi, ar->arNetworkType, - ar->arDot11AuthMode, ar->arAuthMode, - ar->arPairwiseCrypto, - ar->arPairwiseCryptoLen, - ar->arGroupCrypto, ar->arGroupCryptoLen, - ar->arSsidLen, ar->arSsid, - ar->arReqBssid, ar->arChannelHint, - ar->arConnectCtrlFlags) != A_OK) - { - ret = -EIO; - ar->arConnectPending = FALSE; - } - } - } else { - /* Disconnect from the AP and disable foreground scanning */ - AR6000_SPIN_LOCK(&ar->arLock, 0); - if (ar->arConnected == TRUE || ar->arConnectPending == TRUE) { - AR6000_SPIN_UNLOCK(&ar->arLock, 0); - wmi_disconnect_cmd(ar->arWmi); - } else { - AR6000_SPIN_UNLOCK(&ar->arLock, 0); - } - - if (wmi_scanparams_cmd(ar->arWmi, 0xFFFF, 0, 0, 0, 0, 0, 0, 0xFF, 0) != A_OK) - { - ret = -EIO; - } - } - break; - case AR6000_XIOCTL_WMI_GET_ROAM_DATA: - ret = ar6000_ioctl_get_roam_data(dev, rq); - break; - case AR6000_XIOCTL_WMI_SET_BT_STATUS: - ret = ar6000_xioctl_set_bt_status_cmd(dev, userdata); - break; - case AR6000_XIOCTL_WMI_SET_BT_PARAMS: - ret = ar6000_xioctl_set_bt_params_cmd(dev, userdata); - break; - case AR6000_XIOCTL_WMI_STARTSCAN: - { - WMI_START_SCAN_CMD setStartScanCmd; - - if (ar->arWmiReady == FALSE) { - ret = -EIO; - } else if (copy_from_user(&setStartScanCmd, userdata, - sizeof(setStartScanCmd))) - { - ret = -EFAULT; - } else { - if (wmi_startscan_cmd(ar->arWmi, setStartScanCmd.scanType, - setStartScanCmd.forceFgScan, - setStartScanCmd.isLegacy, - setStartScanCmd.homeDwellTime, - setStartScanCmd.forceScanInterval) != A_OK) - { - ret = -EIO; - } - } - break; - } - case AR6000_XIOCTL_WMI_SETFIXRATES: - { - WMI_FIX_RATES_CMD setFixRatesCmd; - A_STATUS returnStatus; - - if (ar->arWmiReady == FALSE) { - ret = -EIO; - } else if (copy_from_user(&setFixRatesCmd, userdata, - sizeof(setFixRatesCmd))) - { - ret = -EFAULT; - } else { - returnStatus = wmi_set_fixrates_cmd(ar->arWmi, setFixRatesCmd.fixRateMask); - if (returnStatus == A_EINVAL) - { - ret = -EINVAL; - } - else if(returnStatus != A_OK) { - ret = -EIO; - } - } - break; - } - - case AR6000_XIOCTL_WMI_GETFIXRATES: - { - WMI_FIX_RATES_CMD getFixRatesCmd; - AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev); - int ret = 0; - - if (ar->arWmiReady == FALSE) { - return -EIO; - } - - if (down_interruptible(&ar->arSem)) { - return -ERESTARTSYS; - } - /* Used copy_from_user/copy_to_user to access user space data */ - if (copy_from_user(&getFixRatesCmd, userdata, sizeof(getFixRatesCmd))) { - ret = -EFAULT; - } else { - ar->arRateMask = 0xFFFF; - - if (wmi_get_ratemask_cmd(ar->arWmi) != A_OK) { - up(&ar->arSem); - return -EIO; - } - - wait_event_interruptible_timeout(arEvent, ar->arRateMask != 0xFFFF, wmitimeout * HZ); - - if (signal_pending(current)) { - ret = -EINTR; - } - - if (!ret) { - getFixRatesCmd.fixRateMask = ar->arRateMask; - } - - if(copy_to_user(userdata, &getFixRatesCmd, sizeof(getFixRatesCmd))) { - ret = -EFAULT; - } - - up(&ar->arSem); - } - break; - } - case AR6000_XIOCTL_WMI_SET_AUTHMODE: - { - WMI_SET_AUTH_MODE_CMD setAuthMode; - - if (ar->arWmiReady == FALSE) { - ret = -EIO; - } else if (copy_from_user(&setAuthMode, userdata, - sizeof(setAuthMode))) - { - ret = -EFAULT; - } else { - if (wmi_set_authmode_cmd(ar->arWmi, setAuthMode.mode) != A_OK) - { - ret = -EIO; - } - } - break; - } - case AR6000_XIOCTL_WMI_SET_REASSOCMODE: - { - WMI_SET_REASSOC_MODE_CMD setReassocMode; - - if (ar->arWmiReady == FALSE) { - ret = -EIO; - } else if (copy_from_user(&setReassocMode, userdata, - sizeof(setReassocMode))) - { - ret = -EFAULT; - } else { - if (wmi_set_reassocmode_cmd(ar->arWmi, setReassocMode.mode) != A_OK) - { - ret = -EIO; - } - } - break; - } - case AR6000_XIOCTL_DIAG_READ: - { - A_UINT32 addr, data; - get_user(addr, (unsigned int *)userdata); - if (ar6000_ReadRegDiag(ar->arHifDevice, &addr, &data) != A_OK) { - ret = -EIO; - } - put_user(data, (unsigned int *)userdata + 1); - break; - } - case AR6000_XIOCTL_DIAG_WRITE: - { - A_UINT32 addr, data; - get_user(addr, (unsigned int *)userdata); - get_user(data, (unsigned int *)userdata + 1); - if (ar6000_WriteRegDiag(ar->arHifDevice, &addr, &data) != A_OK) { - ret = -EIO; - } - break; - } - case AR6000_XIOCTL_WMI_SET_KEEPALIVE: - { - WMI_SET_KEEPALIVE_CMD setKeepAlive; - if (ar->arWmiReady == FALSE) { - return -EIO; - } else if (copy_from_user(&setKeepAlive, userdata, - sizeof(setKeepAlive))){ - ret = -EFAULT; - } else { - if (wmi_set_keepalive_cmd(ar->arWmi, setKeepAlive.keepaliveInterval) != A_OK) { - ret = -EIO; - } - } - break; - } - case AR6000_XIOCTL_WMI_GET_KEEPALIVE: - { - AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev); - WMI_GET_KEEPALIVE_CMD getKeepAlive; - int ret = 0; - if (ar->arWmiReady == FALSE) { - return -EIO; - } - if (down_interruptible(&ar->arSem)) { - return -ERESTARTSYS; - } - if (copy_from_user(&getKeepAlive, userdata,sizeof(getKeepAlive))) { - ret = -EFAULT; - } else { - getKeepAlive.keepaliveInterval = wmi_get_keepalive_cmd(ar->arWmi); - ar->arKeepaliveConfigured = 0xFF; - if (wmi_get_keepalive_configured(ar->arWmi) != A_OK){ - up(&ar->arSem); - return -EIO; - } - wait_event_interruptible_timeout(arEvent, ar->arKeepaliveConfigured != 0xFF, wmitimeout * HZ); - if (signal_pending(current)) { - ret = -EINTR; - } - - if (!ret) { - getKeepAlive.configured = ar->arKeepaliveConfigured; - } - if (copy_to_user(userdata, &getKeepAlive, sizeof(getKeepAlive))) { - ret = -EFAULT; - } - up(&ar->arSem); - } - break; - } - case AR6000_XIOCTL_WMI_SET_APPIE: - { - WMI_SET_APPIE_CMD appIEcmd; - A_UINT8 appIeInfo[IEEE80211_APPIE_FRAME_MAX_LEN]; - A_UINT32 fType,ieLen; - - if (ar->arWmiReady == FALSE) { - return -EIO; - } - get_user(fType, (A_UINT32 *)userdata); - appIEcmd.mgmtFrmType = fType; - if (appIEcmd.mgmtFrmType >= IEEE80211_APPIE_NUM_OF_FRAME) { - ret = -EIO; - } else { - get_user(ieLen, (A_UINT32 *)(userdata + 4)); - appIEcmd.ieLen = ieLen; - if (appIEcmd.ieLen > IEEE80211_APPIE_FRAME_MAX_LEN) { - ret = -EIO; - break; - } - if (copy_from_user(appIeInfo, userdata + 8, appIEcmd.ieLen)) { - ret = -EFAULT; - } else { - if (wmi_set_appie_cmd(ar->arWmi, appIEcmd.mgmtFrmType, - appIEcmd.ieLen, appIeInfo) != A_OK) - { - ret = -EIO; - } - } - } - break; - } - case AR6000_XIOCTL_WMI_SET_MGMT_FRM_RX_FILTER: - { - WMI_BSS_FILTER_CMD cmd; - A_UINT32 filterType; - - if (copy_from_user(&filterType, userdata, sizeof(A_UINT32))) - { - return -EFAULT; - } - if (filterType & (IEEE80211_FILTER_TYPE_BEACON | - IEEE80211_FILTER_TYPE_PROBE_RESP)) - { - cmd.bssFilter = ALL_BSS_FILTER; - } else { - cmd.bssFilter = NONE_BSS_FILTER; - } - if (wmi_bssfilter_cmd(ar->arWmi, cmd.bssFilter, 0) != A_OK) { - ret = -EIO; - } - - AR6000_SPIN_LOCK(&ar->arLock, 0); - ar->arMgmtFilter = filterType; - AR6000_SPIN_UNLOCK(&ar->arLock, 0); - break; - } - case AR6000_XIOCTL_WMI_SET_WSC_STATUS: - { - A_UINT32 wsc_status; - - if (copy_from_user(&wsc_status, userdata, sizeof(A_UINT32))) - { - return -EFAULT; - } - if (wmi_set_wsc_status_cmd(ar->arWmi, wsc_status) != A_OK) { - ret = -EIO; - } - break; - } - case AR6000_XIOCTL_BMI_ROMPATCH_INSTALL: - { - A_UINT32 ROM_addr; - A_UINT32 RAM_addr; - A_UINT32 nbytes; - A_UINT32 do_activate; - A_UINT32 rompatch_id; - - get_user(ROM_addr, (A_UINT32 *)userdata); - get_user(RAM_addr, (A_UINT32 *)userdata + 1); - get_user(nbytes, (A_UINT32 *)userdata + 2); - get_user(do_activate, (A_UINT32 *)userdata + 3); - AR_DEBUG_PRINTF("Install rompatch from ROM: 0x%x to RAM: 0x%x length: %d\n", - ROM_addr, RAM_addr, nbytes); - ret = BMIrompatchInstall(hifDevice, ROM_addr, RAM_addr, - nbytes, do_activate, &rompatch_id); - if (ret == A_OK) { - put_user(rompatch_id, (unsigned int *)rq->ifr_data); /* return value */ - } - break; - } - - case AR6000_XIOCTL_BMI_ROMPATCH_UNINSTALL: - { - A_UINT32 rompatch_id; - - get_user(rompatch_id, (A_UINT32 *)userdata); - AR_DEBUG_PRINTF("UNinstall rompatch_id %d\n", rompatch_id); - ret = BMIrompatchUninstall(hifDevice, rompatch_id); - break; - } - - case AR6000_XIOCTL_BMI_ROMPATCH_ACTIVATE: - case AR6000_XIOCTL_BMI_ROMPATCH_DEACTIVATE: - { - A_UINT32 rompatch_count; - - get_user(rompatch_count, (A_UINT32 *)userdata); - AR_DEBUG_PRINTF("Change rompatch activation count=%d\n", rompatch_count); - length = sizeof(A_UINT32) * rompatch_count; - if ((buffer = (unsigned char *)A_MALLOC(length)) != NULL) { - A_MEMZERO(buffer, length); - if (copy_from_user(buffer, &userdata[sizeof(rompatch_count)], length)) - { - ret = -EFAULT; - } else { - if (cmd == AR6000_XIOCTL_BMI_ROMPATCH_ACTIVATE) { - ret = BMIrompatchActivate(hifDevice, rompatch_count, (A_UINT32 *)buffer); - } else { - ret = BMIrompatchDeactivate(hifDevice, rompatch_count, (A_UINT32 *)buffer); - } - } - A_FREE(buffer); - } else { - ret = -ENOMEM; - } - - break; - } - - case AR6000_XIOCTL_WMI_SET_HOST_SLEEP_MODE: - { - WMI_SET_HOST_SLEEP_MODE_CMD setHostSleepMode; - - if (ar->arWmiReady == FALSE) { - ret = -EIO; - } else if (copy_from_user(&setHostSleepMode, userdata, - sizeof(setHostSleepMode))) - { - ret = -EFAULT; - } else { - if (wmi_set_host_sleep_mode_cmd(ar->arWmi, - &setHostSleepMode) != A_OK) - { - ret = -EIO; - } - } - break; - } - case AR6000_XIOCTL_WMI_SET_WOW_MODE: - { - WMI_SET_WOW_MODE_CMD setWowMode; - - if (ar->arWmiReady == FALSE) { - ret = -EIO; - } else if (copy_from_user(&setWowMode, userdata, - sizeof(setWowMode))) - { - ret = -EFAULT; - } else { - if (wmi_set_wow_mode_cmd(ar->arWmi, - &setWowMode) != A_OK) - { - ret = -EIO; - } - } - break; - } - case AR6000_XIOCTL_WMI_GET_WOW_LIST: - { - WMI_GET_WOW_LIST_CMD getWowList; - - if (ar->arWmiReady == FALSE) { - ret = -EIO; - } else if (copy_from_user(&getWowList, userdata, - sizeof(getWowList))) - { - ret = -EFAULT; - } else { - if (wmi_get_wow_list_cmd(ar->arWmi, - &getWowList) != A_OK) - { - ret = -EIO; - } - } - break; - } - case AR6000_XIOCTL_WMI_ADD_WOW_PATTERN: - { -#define WOW_PATTERN_SIZE 64 -#define WOW_MASK_SIZE 64 - - WMI_ADD_WOW_PATTERN_CMD cmd; - A_UINT8 mask_data[WOW_PATTERN_SIZE]={0}; - A_UINT8 pattern_data[WOW_PATTERN_SIZE]={0}; - - if (ar->arWmiReady == FALSE) { - ret = -EIO; - } else { - - if(copy_from_user(&cmd, userdata, - sizeof(WMI_ADD_WOW_PATTERN_CMD))) - return -EFAULT; - if (copy_from_user(pattern_data, - userdata + 3, - cmd.filter_size)){ - ret = -EFAULT; - break; - } - if (copy_from_user(mask_data, - (userdata + 3 + cmd.filter_size), - cmd.filter_size)){ - ret = -EFAULT; - break; - } else { - if (wmi_add_wow_pattern_cmd(ar->arWmi, - &cmd, pattern_data, mask_data, cmd.filter_size) != A_OK){ - ret = -EIO; - } - } - } -#undef WOW_PATTERN_SIZE -#undef WOW_MASK_SIZE - break; - } - case AR6000_XIOCTL_WMI_DEL_WOW_PATTERN: - { - WMI_DEL_WOW_PATTERN_CMD delWowPattern; - - if (ar->arWmiReady == FALSE) { - ret = -EIO; - } else if (copy_from_user(&delWowPattern, userdata, - sizeof(delWowPattern))) - { - ret = -EFAULT; - } else { - if (wmi_del_wow_pattern_cmd(ar->arWmi, - &delWowPattern) != A_OK) - { - ret = -EIO; - } - } - break; - } - case AR6000_XIOCTL_DUMP_HTC_CREDIT_STATE: - if (ar->arHtcTarget != NULL) { - HTCDumpCreditStates(ar->arHtcTarget); - } - break; - case AR6000_XIOCTL_TRAFFIC_ACTIVITY_CHANGE: - if (ar->arHtcTarget != NULL) { - struct ar6000_traffic_activity_change data; - - if (copy_from_user(&data, userdata, sizeof(data))) - { - return -EFAULT; - } - /* note, this is used for testing (mbox ping testing), indicate activity - * change using the stream ID as the traffic class */ - ar6000_indicate_tx_activity(ar, - (A_UINT8)data.StreamID, - data.Active ? TRUE : FALSE); - } - break; - case AR6000_XIOCTL_WMI_SET_CONNECT_CTRL_FLAGS: - if (ar->arWmiReady == FALSE) { - ret = -EIO; - } else if (copy_from_user(&connectCtrlFlags, userdata, - sizeof(connectCtrlFlags))) - { - ret = -EFAULT; - } else { - ar->arConnectCtrlFlags = connectCtrlFlags; - } - break; - case AR6000_XIOCTL_WMI_SET_AKMP_PARAMS: - if (ar->arWmiReady == FALSE) { - ret = -EIO; - } else if (copy_from_user(&akmpParams, userdata, - sizeof(WMI_SET_AKMP_PARAMS_CMD))) - { - ret = -EFAULT; - } else { - if (wmi_set_akmp_params_cmd(ar->arWmi, &akmpParams) != A_OK) { - ret = -EIO; - } - } - break; - case AR6000_XIOCTL_WMI_SET_PMKID_LIST: - if (ar->arWmiReady == FALSE) { - ret = -EIO; - } else { - if (copy_from_user(&pmkidInfo.numPMKID, userdata, - sizeof(pmkidInfo.numPMKID))) - { - ret = -EFAULT; - break; - } - if (copy_from_user(&pmkidInfo.pmkidList, - userdata + sizeof(pmkidInfo.numPMKID), - pmkidInfo.numPMKID * sizeof(WMI_PMKID))) - { - ret = -EFAULT; - break; - } - if (wmi_set_pmkid_list_cmd(ar->arWmi, &pmkidInfo) != A_OK) { - ret = -EIO; - } - } - break; - case AR6000_XIOCTL_WMI_GET_PMKID_LIST: - if (ar->arWmiReady == FALSE) { - ret = -EIO; - } else { - if (wmi_get_pmkid_list_cmd(ar->arWmi) != A_OK) { - ret = -EIO; - } - } - break; - default: - ret = -EOPNOTSUPP; - } - return ret; -} - diff --git a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/ar6000/netbuf.c b/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/ar6000/netbuf.c deleted file mode 100644 index 97b273b3a..000000000 --- a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/ar6000/netbuf.c +++ /dev/null @@ -1,225 +0,0 @@ - -/* - * - * Copyright (c) 2004-2007 Atheros Communications Inc. - * All rights reserved. - * - * - * 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; - * - * Software distributed under the License is distributed on an "AS - * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or - * implied. See the License for the specific language governing - * rights and limitations under the License. - * - * - * - */ -#include -#include -#include -#include "athdefs.h" -#include "a_types.h" -#include "a_osapi.h" -#include "htc_packet.h" - -#define AR6000_DATA_OFFSET 64 - -void a_netbuf_enqueue(A_NETBUF_QUEUE_T *q, void *pkt) -{ - skb_queue_tail((struct sk_buff_head *) q, (struct sk_buff *) pkt); -} - -void a_netbuf_prequeue(A_NETBUF_QUEUE_T *q, void *pkt) -{ - skb_queue_head((struct sk_buff_head *) q, (struct sk_buff *) pkt); -} - -void *a_netbuf_dequeue(A_NETBUF_QUEUE_T *q) -{ - return((void *) skb_dequeue((struct sk_buff_head *) q)); -} - -int a_netbuf_queue_size(A_NETBUF_QUEUE_T *q) -{ - return(skb_queue_len((struct sk_buff_head *) q)); -} - -int a_netbuf_queue_empty(A_NETBUF_QUEUE_T *q) -{ - return(skb_queue_empty((struct sk_buff_head *) q)); -} - -void a_netbuf_queue_init(A_NETBUF_QUEUE_T *q) -{ - skb_queue_head_init((struct sk_buff_head *) q); -} - -void * -a_netbuf_alloc(int size) -{ - struct sk_buff *skb; - skb = dev_alloc_skb(AR6000_DATA_OFFSET + sizeof(HTC_PACKET) + size); - skb_reserve(skb, AR6000_DATA_OFFSET + sizeof(HTC_PACKET)); - return ((void *)skb); -} - -/* - * Allocate an SKB w.o. any encapsulation requirement. - */ -void * -a_netbuf_alloc_raw(int size) -{ - struct sk_buff *skb; - - skb = dev_alloc_skb(size); - - return ((void *)skb); -} - -void -a_netbuf_free(void *bufPtr) -{ - struct sk_buff *skb = (struct sk_buff *)bufPtr; - - dev_kfree_skb(skb); -} - -A_UINT32 -a_netbuf_to_len(void *bufPtr) -{ - return (((struct sk_buff *)bufPtr)->len); -} - -void * -a_netbuf_to_data(void *bufPtr) -{ - return (((struct sk_buff *)bufPtr)->data); -} - -/* - * Add len # of bytes to the beginning of the network buffer - * pointed to by bufPtr - */ -A_STATUS -a_netbuf_push(void *bufPtr, A_INT32 len) -{ - skb_push((struct sk_buff *)bufPtr, len); - - return A_OK; -} - -/* - * Add len # of bytes to the beginning of the network buffer - * pointed to by bufPtr and also fill with data - */ -A_STATUS -a_netbuf_push_data(void *bufPtr, char *srcPtr, A_INT32 len) -{ - skb_push((struct sk_buff *) bufPtr, len); - A_MEMCPY(((struct sk_buff *)bufPtr)->data, srcPtr, len); - - return A_OK; -} - -/* - * Add len # of bytes to the end of the network buffer - * pointed to by bufPtr - */ -A_STATUS -a_netbuf_put(void *bufPtr, A_INT32 len) -{ - skb_put((struct sk_buff *)bufPtr, len); - - return A_OK; -} - -/* - * Add len # of bytes to the end of the network buffer - * pointed to by bufPtr and also fill with data - */ -A_STATUS -a_netbuf_put_data(void *bufPtr, char *srcPtr, A_INT32 len) -{ - char *start = ((struct sk_buff *)bufPtr)->data + - ((struct sk_buff *)bufPtr)->len; - skb_put((struct sk_buff *)bufPtr, len); - A_MEMCPY(start, srcPtr, len); - - return A_OK; -} - - -/* - * Trim the network buffer pointed to by bufPtr to len # of bytes - */ -A_STATUS -a_netbuf_setlen(void *bufPtr, A_INT32 len) -{ - skb_trim((struct sk_buff *)bufPtr, len); - - return A_OK; -} - -/* - * Chop of len # of bytes from the end of the buffer. - */ -A_STATUS -a_netbuf_trim(void *bufPtr, A_INT32 len) -{ - skb_trim((struct sk_buff *)bufPtr, ((struct sk_buff *)bufPtr)->len - len); - - return A_OK; -} - -/* - * Chop of len # of bytes from the end of the buffer and return the data. - */ -A_STATUS -a_netbuf_trim_data(void *bufPtr, char *dstPtr, A_INT32 len) -{ - char *start = ((struct sk_buff *)bufPtr)->data + - (((struct sk_buff *)bufPtr)->len - len); - - A_MEMCPY(dstPtr, start, len); - skb_trim((struct sk_buff *)bufPtr, ((struct sk_buff *)bufPtr)->len - len); - - return A_OK; -} - - -/* - * Returns the number of bytes available to a a_netbuf_push() - */ -A_INT32 -a_netbuf_headroom(void *bufPtr) -{ - return (skb_headroom((struct sk_buff *)bufPtr)); -} - -/* - * Removes specified number of bytes from the beginning of the buffer - */ -A_STATUS -a_netbuf_pull(void *bufPtr, A_INT32 len) -{ - skb_pull((struct sk_buff *)bufPtr, len); - - return A_OK; -} - -/* - * Removes specified number of bytes from the beginning of the buffer - * and return the data - */ -A_STATUS -a_netbuf_pull_data(void *bufPtr, char *dstPtr, A_INT32 len) -{ - A_MEMCPY(dstPtr, ((struct sk_buff *)bufPtr)->data, len); - skb_pull((struct sk_buff *)bufPtr, len); - - return A_OK; -} - diff --git a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/ar6000/osapi_linux.h b/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/ar6000/osapi_linux.h deleted file mode 100644 index 5b64212a2..000000000 --- a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/ar6000/osapi_linux.h +++ /dev/null @@ -1,319 +0,0 @@ -/* - * $Id: //depot/sw/releases/olca2.0-GPL/host/os/linux/include/osapi_linux.h#1 $ - * - * This file contains the definitions of the basic atheros data types. - * It is used to map the data types in atheros files to a platform specific - * type. - * - * Copyright 2003-2005 Atheros Communications, Inc., All Rights Reserved. - * - * - * 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; - * - * Software distributed under the License is distributed on an "AS - * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or - * implied. See the License for the specific language governing - * rights and limitations under the License. - * - * - * - */ - -#ifndef _OSAPI_LINUX_H_ -#define _OSAPI_LINUX_H_ - -#ifdef __KERNEL__ - -#include -#include -#include -#include -#include -#include -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) -#include -#endif -#include -#include -#include -#ifdef KERNEL_2_4 -#include -#include -#endif - -#ifdef __GNUC__ -#define __ATTRIB_PACK __attribute__ ((packed)) -#define __ATTRIB_PRINTF __attribute__ ((format (printf, 1, 2))) -#define __ATTRIB_NORETURN __attribute__ ((noreturn)) -#ifndef INLINE -#define INLINE __inline__ -#endif -#else /* Not GCC */ -#define __ATTRIB_PACK -#define __ATTRIB_PRINTF -#define __ATTRIB_NORETURN -#ifndef INLINE -#define INLINE __inline -#endif -#endif /* End __GNUC__ */ - -#define PREPACK -#define POSTPACK __ATTRIB_PACK - -/* - * Endianes macros - */ -#define A_BE2CPU8(x) ntohb(x) -#define A_BE2CPU16(x) ntohs(x) -#define A_BE2CPU32(x) ntohl(x) - -#define A_LE2CPU8(x) (x) -#define A_LE2CPU16(x) (x) -#define A_LE2CPU32(x) (x) - -#define A_CPU2BE8(x) htonb(x) -#define A_CPU2BE16(x) htons(x) -#define A_CPU2BE32(x) htonl(x) - -#define A_MEMCPY(dst, src, len) memcpy((A_UINT8 *)(dst), (src), (len)) -#define A_MEMZERO(addr, len) memset(addr, 0, len) -#define A_MEMCMP(addr1, addr2, len) memcmp((addr1), (addr2), (len)) -#define A_MALLOC(size) kmalloc((size), GFP_KERNEL) -#define A_MALLOC_NOWAIT(size) kmalloc((size), GFP_ATOMIC) -#define A_FREE(addr) kfree(addr) -#define A_PRINTF(args...) printk(args) - -/* Mutual Exclusion */ -typedef spinlock_t A_MUTEX_T; -#define A_MUTEX_INIT(mutex) spin_lock_init(mutex) -#define A_MUTEX_LOCK(mutex) spin_lock_bh(mutex) -#define A_MUTEX_UNLOCK(mutex) spin_unlock_bh(mutex) -#define A_IS_MUTEX_VALID(mutex) TRUE /* okay to return true, since A_MUTEX_DELETE does nothing */ -#define A_MUTEX_DELETE(mutex) /* spin locks are not kernel resources so nothing to free.. */ - -/* Get current time in ms adding a constant offset (in ms) */ -#define A_GET_MS(offset) \ - (jiffies + ((offset) / 1000) * HZ) - -/* - * Timer Functions - */ -#define A_MDELAY(msecs) mdelay(msecs) -typedef struct timer_list A_TIMER; - -#define A_INIT_TIMER(pTimer, pFunction, pArg) do { \ - init_timer(pTimer); \ - (pTimer)->function = (pFunction); \ - (pTimer)->data = (unsigned long)(pArg); \ -} while (0) - -/* - * Start a Timer that elapses after 'periodMSec' milli-seconds - * Support is provided for a one-shot timer. The 'repeatFlag' is - * ignored. - */ -#define A_TIMEOUT_MS(pTimer, periodMSec, repeatFlag) do { \ - if (repeatFlag) { \ - printk("\n" __FILE__ ":%d: Timer Repeat requested\n",__LINE__); \ - panic("Timer Repeat"); \ - } \ - mod_timer((pTimer), jiffies + HZ * (periodMSec) / 1000); \ -} while (0) - -/* - * Cancel the Timer. - */ -#define A_UNTIMEOUT(pTimer) do { \ - del_timer((pTimer)); \ -} while (0) - -#define A_DELETE_TIMER(pTimer) do { \ -} while (0) - -/* - * Wait Queue related functions - */ -typedef wait_queue_head_t A_WAITQUEUE_HEAD; -#define A_INIT_WAITQUEUE_HEAD(head) init_waitqueue_head(head) -#ifndef wait_event_interruptible_timeout -#define __wait_event_interruptible_timeout(wq, condition, ret) \ -do { \ - wait_queue_t __wait; \ - init_waitqueue_entry(&__wait, current); \ - \ - add_wait_queue(&wq, &__wait); \ - for (;;) { \ - set_current_state(TASK_INTERRUPTIBLE); \ - if (condition) \ - break; \ - if (!signal_pending(current)) { \ - ret = schedule_timeout(ret); \ - if (!ret) \ - break; \ - continue; \ - } \ - ret = -ERESTARTSYS; \ - break; \ - } \ - current->state = TASK_RUNNING; \ - remove_wait_queue(&wq, &__wait); \ -} while (0) - -#define wait_event_interruptible_timeout(wq, condition, timeout) \ -({ \ - long __ret = timeout; \ - if (!(condition)) \ - __wait_event_interruptible_timeout(wq, condition, __ret); \ - __ret; \ -}) -#endif /* wait_event_interruptible_timeout */ - -#define A_WAIT_EVENT_INTERRUPTIBLE_TIMEOUT(head, condition, timeout) do { \ - wait_event_interruptible_timeout(head, condition, timeout); \ -} while (0) - -#define A_WAKE_UP(head) wake_up(head) - -#ifdef DEBUG -#define A_ASSERT(expr) \ - if (!(expr)) { \ - printk(KERN_ALERT "\n" __FILE__ ":%d: Assertion " #expr " failed!\n",__LINE__); \ - panic(#expr); \ - } - -#else -#define A_ASSERT(expr) -#endif /* DEBUG */ - -/* - * Initialization of the network buffer subsystem - */ -#define A_NETBUF_INIT() - -/* - * Network buffer queue support - */ -typedef struct sk_buff_head A_NETBUF_QUEUE_T; - -#define A_NETBUF_QUEUE_INIT(q) \ - a_netbuf_queue_init(q) - -#define A_NETBUF_ENQUEUE(q, pkt) \ - a_netbuf_enqueue((q), (pkt)) -#define A_NETBUF_PREQUEUE(q, pkt) \ - a_netbuf_prequeue((q), (pkt)) -#define A_NETBUF_DEQUEUE(q) \ - (a_netbuf_dequeue(q)) -#define A_NETBUF_QUEUE_SIZE(q) \ - a_netbuf_queue_size(q) -#define A_NETBUF_QUEUE_EMPTY(q) \ - a_netbuf_queue_empty(q) - -/* - * Network buffer support - */ -#define A_NETBUF_ALLOC(size) \ - a_netbuf_alloc(size) -#define A_NETBUF_ALLOC_RAW(size) \ - a_netbuf_alloc_raw(size) -#define A_NETBUF_FREE(bufPtr) \ - a_netbuf_free(bufPtr) -#define A_NETBUF_DATA(bufPtr) \ - a_netbuf_to_data(bufPtr) -#define A_NETBUF_LEN(bufPtr) \ - a_netbuf_to_len(bufPtr) -#define A_NETBUF_PUSH(bufPtr, len) \ - a_netbuf_push(bufPtr, len) -#define A_NETBUF_PUT(bufPtr, len) \ - a_netbuf_put(bufPtr, len) -#define A_NETBUF_TRIM(bufPtr,len) \ - a_netbuf_trim(bufPtr, len) -#define A_NETBUF_PULL(bufPtr, len) \ - a_netbuf_pull(bufPtr, len) -#define A_NETBUF_HEADROOM(bufPtr)\ - a_netbuf_headroom(bufPtr) -#define A_NETBUF_SETLEN(bufPtr,len) \ - a_netbuf_setlen(bufPtr, len) - -/* Add data to end of a buffer */ -#define A_NETBUF_PUT_DATA(bufPtr, srcPtr, len) \ - a_netbuf_put_data(bufPtr, srcPtr, len) - -/* Add data to start of the buffer */ -#define A_NETBUF_PUSH_DATA(bufPtr, srcPtr, len) \ - a_netbuf_push_data(bufPtr, srcPtr, len) - -/* Remove data at start of the buffer */ -#define A_NETBUF_PULL_DATA(bufPtr, dstPtr, len) \ - a_netbuf_pull_data(bufPtr, dstPtr, len) - -/* Remove data from the end of the buffer */ -#define A_NETBUF_TRIM_DATA(bufPtr, dstPtr, len) \ - a_netbuf_trim_data(bufPtr, dstPtr, len) - -/* View data as "size" contiguous bytes of type "t" */ -#define A_NETBUF_VIEW_DATA(bufPtr, t, size) \ - (t )( ((struct skbuf *)(bufPtr))->data) - -/* return the beginning of the headroom for the buffer */ -#define A_NETBUF_HEAD(bufPtr) \ - ((((struct sk_buff *)(bufPtr))->head)) - -/* - * OS specific network buffer access routines - */ -void *a_netbuf_alloc(int size); -void *a_netbuf_alloc_raw(int size); -void a_netbuf_free(void *bufPtr); -void *a_netbuf_to_data(void *bufPtr); -A_UINT32 a_netbuf_to_len(void *bufPtr); -A_STATUS a_netbuf_push(void *bufPtr, A_INT32 len); -A_STATUS a_netbuf_push_data(void *bufPtr, char *srcPtr, A_INT32 len); -A_STATUS a_netbuf_put(void *bufPtr, A_INT32 len); -A_STATUS a_netbuf_put_data(void *bufPtr, char *srcPtr, A_INT32 len); -A_STATUS a_netbuf_pull(void *bufPtr, A_INT32 len); -A_STATUS a_netbuf_pull_data(void *bufPtr, char *dstPtr, A_INT32 len); -A_STATUS a_netbuf_trim(void *bufPtr, A_INT32 len); -A_STATUS a_netbuf_trim_data(void *bufPtr, char *dstPtr, A_INT32 len); -A_STATUS a_netbuf_setlen(void *bufPtr, A_INT32 len); -A_INT32 a_netbuf_headroom(void *bufPtr); -void a_netbuf_enqueue(A_NETBUF_QUEUE_T *q, void *pkt); -void a_netbuf_prequeue(A_NETBUF_QUEUE_T *q, void *pkt); -void *a_netbuf_dequeue(A_NETBUF_QUEUE_T *q); -int a_netbuf_queue_size(A_NETBUF_QUEUE_T *q); -int a_netbuf_queue_empty(A_NETBUF_QUEUE_T *q); -int a_netbuf_queue_empty(A_NETBUF_QUEUE_T *q); -void a_netbuf_queue_init(A_NETBUF_QUEUE_T *q); - -/* - * Kernel v.s User space functions - */ -A_UINT32 a_copy_to_user(void *to, const void *from, A_UINT32 n); -A_UINT32 a_copy_from_user(void *to, const void *from, A_UINT32 n); - -#else /* __KERNEL__ */ - -#ifdef __GNUC__ -#define __ATTRIB_PACK __attribute__ ((packed)) -#define __ATTRIB_PRINTF __attribute__ ((format (printf, 1, 2))) -#define __ATTRIB_NORETURN __attribute__ ((noreturn)) -#ifndef INLINE -#define INLINE __inline__ -#endif -#else /* Not GCC */ -#define __ATTRIB_PACK -#define __ATTRIB_PRINTF -#define __ATTRIB_NORETURN -#ifndef INLINE -#define INLINE __inline -#endif -#endif /* End __GNUC__ */ - -#define PREPACK -#define POSTPACK __ATTRIB_PACK - -#endif /* __KERNEL__ */ - -#endif /* _OSAPI_LINUX_H_ */ diff --git a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/ar6000/wireless_ext.c b/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/ar6000/wireless_ext.c deleted file mode 100644 index af78ae05f..000000000 --- a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/ar6000/wireless_ext.c +++ /dev/null @@ -1,1979 +0,0 @@ -/* - * - * Copyright (c) 2004-2007 Atheros Communications Inc. - * All rights reserved. - * - * - * 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; - * - * Software distributed under the License is distributed on an "AS - * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or - * implied. See the License for the specific language governing - * rights and limitations under the License. - * - * - * - */ - -#include "ar6000_drv.h" - -static A_UINT8 bcast_mac[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; -static void ar6000_set_quality(struct iw_quality *iq, A_INT8 rssi); -extern unsigned int wmitimeout; -extern A_WAITQUEUE_HEAD arEvent; -extern wait_queue_head_t ar6000_scan_queue; - -/* - * Encode a WPA or RSN information element as a custom - * element using the hostap format. - */ -static u_int -encode_ie(void *buf, size_t bufsize, - const u_int8_t *ie, size_t ielen, - const char *leader, size_t leader_len) -{ - u_int8_t *p; - int i; - - if (bufsize < leader_len) - return 0; - p = buf; - memcpy(p, leader, leader_len); - bufsize -= leader_len; - p += leader_len; - for (i = 0; i < ielen && bufsize > 2; i++) - p += sprintf(p, "%02x", ie[i]); - return (i == ielen ? p - (u_int8_t *)buf : 0); -} - -void -ar6000_scan_node(void *arg, bss_t *ni) -{ - struct iw_event iwe; -#if WIRELESS_EXT > 14 - char buf[64*2 + 30]; -#endif - struct ar_giwscan_param *param; - A_CHAR *current_ev; - A_CHAR *end_buf; - struct ieee80211_common_ie *cie; - struct iw_request_info info; - - info.cmd = 0; - info.flags = 0; - - param = (struct ar_giwscan_param *)arg; - - if (param->current_ev >= param->end_buf) { - return; - } - if ((param->firstPass == TRUE) && - ((ni->ni_cie.ie_wpa == NULL) && (ni->ni_cie.ie_rsn == NULL))) { - /* - * Only forward wpa bss's in first pass - */ - return; - } - - if ((param->firstPass == FALSE) && - ((ni->ni_cie.ie_wpa != NULL) || (ni->ni_cie.ie_rsn != NULL))) { - /* - * Only forward non-wpa bss's in 2nd pass - */ - return; - } - - current_ev = param->current_ev; - end_buf = param->end_buf; - - cie = &ni->ni_cie; - - A_MEMZERO(&iwe, sizeof(iwe)); - iwe.cmd = SIOCGIWAP; - iwe.u.ap_addr.sa_family = ARPHRD_ETHER; - A_MEMCPY(iwe.u.ap_addr.sa_data, ni->ni_macaddr, 6); - current_ev = iwe_stream_add_event(&info, current_ev, end_buf, &iwe, - IW_EV_ADDR_LEN); - - A_MEMZERO(&iwe, sizeof(iwe)); - iwe.cmd = SIOCGIWESSID; - iwe.u.data.flags = 1; - iwe.u.data.length = cie->ie_ssid[1]; - current_ev = iwe_stream_add_point(&info, current_ev, end_buf, &iwe, - &cie->ie_ssid[2]); - - if (cie->ie_capInfo & (IEEE80211_CAPINFO_ESS|IEEE80211_CAPINFO_IBSS)) { - A_MEMZERO(&iwe, sizeof(iwe)); - iwe.cmd = SIOCGIWMODE; - iwe.u.mode = cie->ie_capInfo & IEEE80211_CAPINFO_ESS ? - IW_MODE_MASTER : IW_MODE_ADHOC; - current_ev = iwe_stream_add_event(&info, current_ev, end_buf, &iwe, - IW_EV_UINT_LEN); - } - - A_MEMZERO(&iwe, sizeof(iwe)); - iwe.cmd = SIOCGIWFREQ; - iwe.u.freq.m = cie->ie_chan * 100000; - iwe.u.freq.e = 1; - current_ev = iwe_stream_add_event(&info, current_ev, end_buf, &iwe, - IW_EV_FREQ_LEN); - - A_MEMZERO(&iwe, sizeof(iwe)); - iwe.cmd = IWEVQUAL; - ar6000_set_quality(&iwe.u.qual, ni->ni_snr); - current_ev = iwe_stream_add_event(&info, current_ev, end_buf, &iwe, - IW_EV_QUAL_LEN); - - A_MEMZERO(&iwe, sizeof(iwe)); - iwe.cmd = SIOCGIWENCODE; - if (cie->ie_capInfo & IEEE80211_CAPINFO_PRIVACY) { - iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY; - } else { - iwe.u.data.flags = IW_ENCODE_DISABLED; - } - iwe.u.data.length = 0; - current_ev = iwe_stream_add_point(&info, current_ev, end_buf, &iwe, ""); - - A_MEMZERO(&iwe, sizeof(iwe)); - iwe.cmd = IWEVCUSTOM; - snprintf(buf, sizeof(buf), "bcn_int=%d", cie->ie_beaconInt); - iwe.u.data.length = strlen(buf); - current_ev = iwe_stream_add_point(&info, current_ev, end_buf, &iwe, buf); - - if (cie->ie_wpa != NULL) { - static const char wpa_leader[] = "wpa_ie="; - - A_MEMZERO(&iwe, sizeof(iwe)); - iwe.cmd = IWEVCUSTOM; - iwe.u.data.length = encode_ie(buf, sizeof(buf), cie->ie_wpa, - cie->ie_wpa[1]+2, - wpa_leader, sizeof(wpa_leader)-1); - - if (iwe.u.data.length != 0) { - current_ev = iwe_stream_add_point(&info, current_ev, end_buf, &iwe, - buf); - } - } - - if (cie->ie_rsn != NULL && cie->ie_rsn[0] == IEEE80211_ELEMID_RSN) { - static const char rsn_leader[] = "rsn_ie="; - - A_MEMZERO(&iwe, sizeof(iwe)); - iwe.cmd = IWEVCUSTOM; - iwe.u.data.length = encode_ie(buf, sizeof(buf), cie->ie_rsn, - cie->ie_rsn[1]+2, - rsn_leader, sizeof(rsn_leader)-1); - - if (iwe.u.data.length != 0) { - current_ev = iwe_stream_add_point(&info, current_ev, end_buf, &iwe, - buf); - } - } - - if (cie->ie_wmm != NULL) { - static const char wmm_leader[] = "wmm_ie="; - - A_MEMZERO(&iwe, sizeof(iwe)); - iwe.cmd = IWEVCUSTOM; - iwe.u.data.length = encode_ie(buf, sizeof(buf), cie->ie_wmm, - cie->ie_wmm[1]+2, - wmm_leader, sizeof(wmm_leader)-1); - if (iwe.u.data.length != 0) { - current_ev = iwe_stream_add_point(&info, current_ev, end_buf, &iwe, - buf); - } - } - - if (cie->ie_ath != NULL) { - static const char ath_leader[] = "ath_ie="; - - A_MEMZERO(&iwe, sizeof(iwe)); - iwe.cmd = IWEVCUSTOM; - iwe.u.data.length = encode_ie(buf, sizeof(buf), cie->ie_ath, - cie->ie_ath[1]+2, - ath_leader, sizeof(ath_leader)-1); - if (iwe.u.data.length != 0) { - current_ev = iwe_stream_add_point(&info, current_ev, end_buf, &iwe, - buf); - } - } - - param->current_ev = current_ev; -} - -int -ar6000_ioctl_giwscan(struct net_device *dev, - struct iw_request_info *info, - struct iw_point *data, char *extra) -{ - AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev); - struct ar_giwscan_param param; - int i; - - if (ar->arWlanState == WLAN_DISABLED) { - return -EIO; - } - - if (ar->arWmiReady == FALSE) { - return -EIO; - } - - param.current_ev = extra; - param.end_buf = extra + IW_SCAN_MAX_DATA; - param.firstPass = TRUE; - - /* - * Do two passes to insure WPA scan candidates - * are sorted to the front. This is a hack to deal with - * the wireless extensions capping scan results at - * IW_SCAN_MAX_DATA bytes. In densely populated environments - * it's easy to overflow this buffer (especially with WPA/RSN - * information elements). Note this sorting hack does not - * guarantee we won't overflow anyway. - */ - for (i = 0; i < 2; i++) { - /* - * Translate data to WE format. - */ - wmi_iterate_nodes(ar->arWmi, ar6000_scan_node, ¶m); - param.firstPass = FALSE; - if (param.current_ev >= param.end_buf) { - data->length = param.current_ev - extra; - return -E2BIG; - } - } - - data->length = param.current_ev - extra; - return 0; -} - -extern int reconnect_flag; -/* SIOCSIWESSID */ -static int -ar6000_ioctl_siwessid(struct net_device *dev, - struct iw_request_info *info, - struct iw_point *data, char *ssid) -{ - AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev); - A_STATUS status; - A_UINT8 arNetworkType; - - if (ar->arWlanState == WLAN_DISABLED) { - return -EIO; - } - - if (ar->arWmiReady == FALSE) { - return -EIO; - } - - /* - * iwconfig passes a string with length excluding any trailing NUL. - * FIXME: we should be able to set an ESSID of 32 bytes, yet things fall - * over badly if we do. So we limit the ESSID to 31 bytes. - */ - if (data->flags && (!data->length || data->length >= sizeof(ar->arSsid))) { - /* - * ssid is invalid - */ - return -EINVAL; - } - /* Added for bug 25178, return an IOCTL error instead of target returning - Illegal parameter error when either the BSSID or channel is missing - and we cannot scan during connect. - */ - if (data->flags) { - if (ar->arSkipScan == TRUE && - (ar->arChannelHint == 0 || - (!ar->arReqBssid[0] && !ar->arReqBssid[1] && !ar->arReqBssid[2] && - !ar->arReqBssid[3] && !ar->arReqBssid[4] && !ar->arReqBssid[5]))) - { - return -EINVAL; - } - } - - if (down_interruptible(&ar->arSem)) { - return -ERESTARTSYS; - } - - if (ar->arTxPending[WMI_CONTROL_PRI]) { - /* - * sleep until the command queue drains - */ - wait_event_interruptible_timeout(arEvent, - ar->arTxPending[WMI_CONTROL_PRI] == 0, wmitimeout * HZ); - if (signal_pending(current)) { - return -EINTR; - } - } - - if (!data->flags) { - arNetworkType = ar->arNetworkType; - ar6000_init_profile_info(ar); - ar->arNetworkType = arNetworkType; - } - - /* - * The original logic here prevented a disconnect if issuing an "essid off" - * if no ESSID was set, presumably to prevent sending multiple disconnects - * to the WMI. - * - * Unfortunately, this also meant that no disconnect was sent when we were - * already connected, but the profile has been changed since (which also - * clears the ESSID as a reminder that the WMI needs updating.) - * - * The "1 ||" makes sure we always disconnect or reconnect. The WMI doesn't - * seem to mind being sent multiple disconnects. - */ - if (1 || (ar->arSsidLen) || (!data->flags)) - { - if ((!data->flags) || - (A_MEMCMP(ar->arSsid, ssid, ar->arSsidLen) != 0) || - (ar->arSsidLen != (data->length))) - { - /* - * SSID set previously or essid off has been issued. - * - * Disconnect Command is issued in two cases after wmi is ready - * (1) ssid is different from the previous setting - * (2) essid off has been issued - * - */ - if (ar->arWmiReady == TRUE) { - reconnect_flag = 0; - status = wmi_disconnect_cmd(ar->arWmi); - A_MEMZERO(ar->arSsid, sizeof(ar->arSsid)); - ar->arSsidLen = 0; - if (ar->arSkipScan == FALSE) { - A_MEMZERO(ar->arReqBssid, sizeof(ar->arReqBssid)); - } - if (!data->flags) { - up(&ar->arSem); - return 0; - } - } else { - up(&ar->arSem); - } - } - else - { - /* - * SSID is same, so we assume profile hasn't changed. - * If the interface is up and wmi is ready, we issue - * a reconnect cmd. Issue a reconnect only we are already - * connected. - */ - if((ar->arConnected == TRUE) && (ar->arWmiReady == TRUE)) - { - reconnect_flag = TRUE; - status = wmi_reconnect_cmd(ar->arWmi,ar->arReqBssid, - ar->arChannelHint); - up(&ar->arSem); - if (status != A_OK) { - return -EIO; - } - return 0; - } - else{ - /* - * Dont return if connect is pending. - */ - if(!(ar->arConnectPending)) { - up(&ar->arSem); - return 0; - } - } - } - } - - ar->arSsidLen = data->length; - A_MEMCPY(ar->arSsid, ssid, ar->arSsidLen); - - /* The ssid length check prevents second "essid off" from the user, - to be treated as a connect cmd. The second "essid off" is ignored. - */ - if((ar->arWmiReady == TRUE) && (ar->arSsidLen > 0) ) - { - AR6000_SPIN_LOCK(&ar->arLock, 0); - if (SHARED_AUTH == ar->arDot11AuthMode) { - ar6000_install_static_wep_keys(ar); - } - AR_DEBUG_PRINTF("Connect called with authmode %d dot11 auth %d"\ - " PW crypto %d PW crypto Len %d GRP crypto %d"\ - " GRP crypto Len %d\n", - ar->arAuthMode, ar->arDot11AuthMode, - ar->arPairwiseCrypto, ar->arPairwiseCryptoLen, - ar->arGroupCrypto, ar->arGroupCryptoLen); - reconnect_flag = 0; - AR6000_SPIN_UNLOCK(&ar->arLock, 0); - status = wmi_connect_cmd(ar->arWmi, ar->arNetworkType, - ar->arDot11AuthMode, ar->arAuthMode, - ar->arPairwiseCrypto, ar->arPairwiseCryptoLen, - ar->arGroupCrypto,ar->arGroupCryptoLen, - ar->arSsidLen, ar->arSsid, - ar->arReqBssid, ar->arChannelHint, - ar->arConnectCtrlFlags); - - - up(&ar->arSem); - - if (status != A_OK) { - return -EIO; - } - ar->arConnectPending = TRUE; - }else{ - up(&ar->arSem); - } - return 0; -} - -/* SIOCGIWESSID */ -static int -ar6000_ioctl_giwessid(struct net_device *dev, - struct iw_request_info *info, - struct iw_point *data, char *essid) -{ - AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev); - - if (ar->arWlanState == WLAN_DISABLED) { - return -EIO; - } - - data->flags = 1; - data->length = ar->arSsidLen; - A_MEMCPY(essid, ar->arSsid, ar->arSsidLen); - - return 0; -} - - -void ar6000_install_static_wep_keys(AR_SOFTC_T *ar) -{ - A_UINT8 index; - A_UINT8 keyUsage; - - for (index = WMI_MIN_KEY_INDEX; index <= WMI_MAX_KEY_INDEX; index++) { - if (ar->arWepKeyList[index].arKeyLen) { - keyUsage = GROUP_USAGE; - if (index == ar->arDefTxKeyIndex) { - keyUsage |= TX_USAGE; - } - wmi_addKey_cmd(ar->arWmi, - index, - WEP_CRYPT, - keyUsage, - ar->arWepKeyList[index].arKeyLen, - NULL, - ar->arWepKeyList[index].arKey, KEY_OP_INIT_VAL, - NO_SYNC_WMIFLAG); - } - } -} - -int -ar6000_ioctl_delkey(struct net_device *dev, struct iw_request_info *info, - void *w, char *extra) -{ - return 0; -} - -int -ar6000_ioctl_setmlme(struct net_device *dev, struct iw_request_info *info, - void *w, char *extra) -{ - AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev); - struct ieee80211req_mlme *mlme = (struct ieee80211req_mlme *)extra; - - if ((ar->arWmiReady == FALSE) || (ar->arConnected != TRUE)) - return -EIO; - - switch (mlme->im_op) { - case IEEE80211_MLME_DISASSOC: - case IEEE80211_MLME_DEAUTH: - /* Not Supported */ - break; - default: - break; - } - return 0; -} - - -int -ar6000_ioctl_setwmmparams(struct net_device *dev, struct iw_request_info *info, - void *w, char *extra) -{ - return -EIO; /* for now */ -} - -int -ar6000_ioctl_getwmmparams(struct net_device *dev, struct iw_request_info *info, - void *w, char *extra) -{ - return -EIO; /* for now */ -} - -int ar6000_ioctl_setoptie(struct net_device *dev, struct iw_request_info *info, - struct iw_point *data, char *extra) -{ - /* The target generates the WPA/RSN IE */ - return 0; -} - -int -ar6000_ioctl_setauthalg(struct net_device *dev, struct iw_request_info *info, - void *w, char *extra) -{ - AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev); - struct ieee80211req_authalg *req = (struct ieee80211req_authalg *)extra; - int ret = 0; - - - AR6000_SPIN_LOCK(&ar->arLock, 0); - - if (req->auth_alg == AUTH_ALG_OPEN_SYSTEM) { - ar->arDot11AuthMode = OPEN_AUTH; - } else if (req->auth_alg == AUTH_ALG_LEAP) { - ar->arDot11AuthMode = LEAP_AUTH; - ar->arPairwiseCrypto = WEP_CRYPT; - ar->arGroupCrypto = WEP_CRYPT; - } else { - ret = -EIO; - } - - AR6000_SPIN_UNLOCK(&ar->arLock, 0); - - return ret; -} -static int -ar6000_ioctl_addpmkid(struct net_device *dev, struct iw_request_info *info, - void *w, char *extra) -{ - AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev); - struct ieee80211req_addpmkid *req = (struct ieee80211req_addpmkid *)extra; - A_STATUS status; - - if (ar->arWlanState == WLAN_DISABLED) { - return -EIO; - } - - AR_DEBUG_PRINTF("Add pmkid for %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x en=%d\n", - req->pi_bssid[0], req->pi_bssid[1], req->pi_bssid[2], - req->pi_bssid[3], req->pi_bssid[4], req->pi_bssid[5], - req->pi_enable); - - status = wmi_setPmkid_cmd(ar->arWmi, req->pi_bssid, req->pi_pmkid, - req->pi_enable); - - if (status != A_OK) { - return -EIO; - } - - return 0; -} - -/* - * SIOCSIWRATE - */ -int -ar6000_ioctl_siwrate(struct net_device *dev, - struct iw_request_info *info, - struct iw_param *rrq, char *extra) -{ - AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev); - A_UINT32 kbps; - - if (rrq->fixed) { - kbps = rrq->value / 1000; /* rrq->value is in bps */ - } else { - kbps = -1; /* -1 indicates auto rate */ - } - if(kbps != -1 && wmi_validate_bitrate(ar->arWmi, kbps) == A_EINVAL) - { - AR_DEBUG_PRINTF("BitRate is not Valid %d\n", kbps); - return -EINVAL; - } - ar->arBitRate = kbps; - if(ar->arWmiReady == TRUE) - { - if (wmi_set_bitrate_cmd(ar->arWmi, kbps) != A_OK) { - return -EINVAL; - } - } - return 0; -} - -/* - * SIOCGIWRATE - */ -int -ar6000_ioctl_giwrate(struct net_device *dev, - struct iw_request_info *info, - struct iw_param *rrq, char *extra) -{ - AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev); - int ret = 0; - - if (down_interruptible(&ar->arSem)) { - return -ERESTARTSYS; - } - if(ar->arWmiReady == TRUE) - { - ar->arBitRate = 0xFFFF; - if (wmi_get_bitrate_cmd(ar->arWmi) != A_OK) { - up(&ar->arSem); - return -EIO; - } - wait_event_interruptible_timeout(arEvent, ar->arBitRate != 0xFFFF, wmitimeout * HZ); - if (signal_pending(current)) { - ret = -EINTR; - } - } - /* If the interface is down or wmi is not ready or the target is not - connected - return the value stored in the device structure */ - if (!ret) { - if (ar->arBitRate == -1) { - rrq->fixed = TRUE; - rrq->value = 0; - } else { - rrq->value = ar->arBitRate * 1000; - } - } - - up(&ar->arSem); - - return ret; -} - -/* - * SIOCSIWTXPOW - */ -static int -ar6000_ioctl_siwtxpow(struct net_device *dev, - struct iw_request_info *info, - struct iw_param *rrq, char *extra) -{ - AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev); - A_UINT8 dbM; - - if (ar->arWlanState == WLAN_DISABLED) { - return -EIO; - } - - if (ar->arRadioSwitch == WLAN_ENABLED - && rrq->disabled) { - if (wmi_switch_radio(ar->arWmi, WLAN_DISABLED) < 0) - return -EIO; - ar->arRadioSwitch = WLAN_DISABLED; - } else if (ar->arRadioSwitch == WLAN_DISABLED - && !rrq->disabled) { - if (wmi_switch_radio(ar->arWmi, WLAN_ENABLED) < 0) - return -EIO; - ar->arRadioSwitch = WLAN_ENABLED; - } - - if (rrq->fixed) { - if (rrq->flags != IW_TXPOW_DBM) { - return -EOPNOTSUPP; - } - ar->arTxPwr= dbM = rrq->value; - ar->arTxPwrSet = TRUE; - } else { - ar->arTxPwr = dbM = 0; - ar->arTxPwrSet = FALSE; - } - if(ar->arWmiReady == TRUE) - { - AR_DEBUG_PRINTF("Set tx pwr cmd %d dbM\n", dbM); - wmi_set_txPwr_cmd(ar->arWmi, dbM); - } - return 0; -} - -/* - * SIOCGIWTXPOW - */ -int -ar6000_ioctl_giwtxpow(struct net_device *dev, - struct iw_request_info *info, - struct iw_param *rrq, char *extra) -{ - AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev); - int ret = 0; - - if (ar->arWlanState == WLAN_DISABLED) { - return -EIO; - } - - if (ar->arRadioSwitch == WLAN_DISABLED) { - rrq->disabled = 1; - return 0; - } - - if (down_interruptible(&ar->arSem)) { - return -ERESTARTSYS; - } - if((ar->arWmiReady == TRUE) && (ar->arConnected == TRUE)) - { - ar->arTxPwr = 0; - - if (wmi_get_txPwr_cmd(ar->arWmi) != A_OK) { - up(&ar->arSem); - return -EIO; - } - - wait_event_interruptible_timeout(arEvent, ar->arTxPwr != 0, wmitimeout * HZ); - - if (signal_pending(current)) { - ret = -EINTR; - } - } - /* If the interace is down or wmi is not ready or target is not connected - then return value stored in the device structure */ - - if (!ret) { - if (ar->arTxPwrSet == TRUE) { - rrq->fixed = TRUE; - } - rrq->value = ar->arTxPwr; - rrq->flags = IW_TXPOW_DBM; - } - - up(&ar->arSem); - - return ret; -} - -/* - * SIOCSIWRETRY - * since iwconfig only provides us with one max retry value, we use it - * to apply to data frames of the BE traffic class. - */ -static int -ar6000_ioctl_siwretry(struct net_device *dev, - struct iw_request_info *info, - struct iw_param *rrq, char *extra) -{ - AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev); - - if (ar->arWlanState == WLAN_DISABLED) { - return -EIO; - } - - if (rrq->disabled) { - return -EOPNOTSUPP; - } - - if ((rrq->flags & IW_RETRY_TYPE) != IW_RETRY_LIMIT) { - return -EOPNOTSUPP; - } - - if ( !(rrq->value >= WMI_MIN_RETRIES) || !(rrq->value <= WMI_MAX_RETRIES)) { - return - EINVAL; - } - if(ar->arWmiReady == TRUE) - { - if (wmi_set_retry_limits_cmd(ar->arWmi, DATA_FRAMETYPE, WMM_AC_BE, - rrq->value, 0) != A_OK){ - return -EINVAL; - } - } - ar->arMaxRetries = rrq->value; - return 0; -} - -/* - * SIOCGIWRETRY - */ -static int -ar6000_ioctl_giwretry(struct net_device *dev, - struct iw_request_info *info, - struct iw_param *rrq, char *extra) -{ - AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev); - - if (ar->arWlanState == WLAN_DISABLED) { - return -EIO; - } - - rrq->disabled = 0; - switch (rrq->flags & IW_RETRY_TYPE) { - case IW_RETRY_LIFETIME: - return -EOPNOTSUPP; - break; - case IW_RETRY_LIMIT: - rrq->flags = IW_RETRY_LIMIT; - switch (rrq->flags & IW_RETRY_MODIFIER) { - case IW_RETRY_MIN: - rrq->flags |= IW_RETRY_MIN; - rrq->value = WMI_MIN_RETRIES; - break; - case IW_RETRY_MAX: - rrq->flags |= IW_RETRY_MAX; - rrq->value = ar->arMaxRetries; - break; - } - break; - } - return 0; -} - -/* - * SIOCSIWENCODE - */ -static int -ar6000_ioctl_siwencode(struct net_device *dev, - struct iw_request_info *info, - struct iw_point *erq, char *keybuf) -{ - AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev); - int index; - A_INT32 auth = ar->arDot11AuthMode; - - if (ar->arWlanState == WLAN_DISABLED) { - return -EIO; - } - - index = erq->flags & IW_ENCODE_INDEX; - - if (index && (((index - 1) < WMI_MIN_KEY_INDEX) || - ((index - 1) > WMI_MAX_KEY_INDEX))) - { - return -EIO; - } - - if (erq->flags & IW_ENCODE_DISABLED) { - /* - * Encryption disabled - */ - if (index) { - /* - * If key index was specified then clear the specified key - */ - index--; - A_MEMZERO(ar->arWepKeyList[index].arKey, - sizeof(ar->arWepKeyList[index].arKey)); - ar->arWepKeyList[index].arKeyLen = 0; - } - ar->arDot11AuthMode = OPEN_AUTH; - ar->arPairwiseCrypto = NONE_CRYPT; - ar->arGroupCrypto = NONE_CRYPT; - ar->arAuthMode = NONE_AUTH; - } else { - /* - * Enabling WEP encryption - */ - if (index) { - index--; /* keyindex is off base 1 in iwconfig */ - } - - if (erq->flags & IW_ENCODE_OPEN) { - auth = OPEN_AUTH; - } else if (erq->flags & IW_ENCODE_RESTRICTED) { - auth = SHARED_AUTH; - } - - if (erq->length) { - if (!IEEE80211_IS_VALID_WEP_CIPHER_LEN(erq->length)) { - return -EIO; - } - - A_MEMZERO(ar->arWepKeyList[index].arKey, - sizeof(ar->arWepKeyList[index].arKey)); - A_MEMCPY(ar->arWepKeyList[index].arKey, keybuf, erq->length); - ar->arWepKeyList[index].arKeyLen = erq->length; - } else { - if (ar->arWepKeyList[index].arKeyLen == 0) { - return -EIO; - } - ar->arDefTxKeyIndex = index; - } - - ar->arPairwiseCrypto = WEP_CRYPT; - ar->arGroupCrypto = WEP_CRYPT; - ar->arDot11AuthMode = auth; - ar->arAuthMode = NONE_AUTH; - } - - /* - * profile has changed. Erase ssid to signal change - */ - A_MEMZERO(ar->arSsid, sizeof(ar->arSsid)); - ar->arSsidLen = 0; - - return 0; -} - -static int -ar6000_ioctl_giwencode(struct net_device *dev, - struct iw_request_info *info, - struct iw_point *erq, char *key) -{ - AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev); - A_UINT8 keyIndex; - struct ar_wep_key *wk; - - if (ar->arWlanState == WLAN_DISABLED) { - return -EIO; - } - - if (ar->arPairwiseCrypto == NONE_CRYPT) { - erq->length = 0; - erq->flags = IW_ENCODE_DISABLED; - } else { - /* get the keyIndex */ - keyIndex = erq->flags & IW_ENCODE_INDEX; - if (0 == keyIndex) { - keyIndex = ar->arDefTxKeyIndex; - } else if ((keyIndex - 1 < WMI_MIN_KEY_INDEX) || - (keyIndex - 1 > WMI_MAX_KEY_INDEX)) - { - keyIndex = WMI_MIN_KEY_INDEX; - } else { - keyIndex--; - } - erq->flags = keyIndex + 1; - erq->flags |= IW_ENCODE_ENABLED; - wk = &ar->arWepKeyList[keyIndex]; - if (erq->length > wk->arKeyLen) { - erq->length = wk->arKeyLen; - } - if (wk->arKeyLen) { - A_MEMCPY(key, wk->arKey, erq->length); - } - if (ar->arDot11AuthMode == OPEN_AUTH) { - erq->flags |= IW_ENCODE_OPEN; - } else if (ar->arDot11AuthMode == SHARED_AUTH) { - erq->flags |= IW_ENCODE_RESTRICTED; - } - } - - return 0; -} - -static int ar6000_ioctl_siwpower(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev); - WMI_POWER_MODE power_mode; - - if (wrqu->power.disabled) - power_mode = MAX_PERF_POWER; - else - power_mode = REC_POWER; - - if (wmi_powermode_cmd(ar->arWmi, power_mode) < 0) - return -EIO; - - return 0; -} - -static int ar6000_ioctl_giwpower(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev); - - /* - * FIXME: - * https://docs.openmoko.org/trac/ticket/2267 - * When starting wpa_supplicant the kernel oopses. - * The following condition avoids the oops. - * Remove this comment to bless this solution. - */ - if (ar->arWlanState == WLAN_DISABLED || ar->arWmiReady == FALSE) - return -EIO; - - return wmi_get_power_mode_cmd(ar->arWmi); -} - -static int ar6000_ioctl_siwgenie(struct net_device *dev, - struct iw_request_info *info, - struct iw_point *dwrq, - char *extra) -{ - /* The target does that for us */ - return 0; -} - -static int ar6000_ioctl_giwgenie(struct net_device *dev, - struct iw_request_info *info, - struct iw_point *dwrq, - char *extra) -{ - return 0; -} - -static int ar6000_ioctl_siwauth(struct net_device *dev, - struct iw_request_info *info, - struct iw_param *param, - char *extra) -{ - AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev); - int reset = 0; - - switch (param->flags & IW_AUTH_INDEX) { - case IW_AUTH_WPA_VERSION: - if (param->value & IW_AUTH_WPA_VERSION_DISABLED) { - ar->arAuthMode = NONE_AUTH; - } - if (param->value & IW_AUTH_WPA_VERSION_WPA) { - ar->arAuthMode = WPA_AUTH; - } - if (param->value & IW_AUTH_WPA_VERSION_WPA2) { - ar->arAuthMode = WPA2_AUTH; - } - - reset = 1; - break; - case IW_AUTH_CIPHER_PAIRWISE: - if (param->value & IW_AUTH_CIPHER_NONE) { - ar->arPairwiseCrypto = NONE_CRYPT; - } - if (param->value & IW_AUTH_CIPHER_WEP40) { - ar->arPairwiseCrypto = WEP_CRYPT; - } - if (param->value & IW_AUTH_CIPHER_TKIP) { - ar->arPairwiseCrypto = TKIP_CRYPT; - } - if (param->value & IW_AUTH_CIPHER_CCMP) { - ar->arPairwiseCrypto = AES_CRYPT; - } - - reset = 1; - break; - case IW_AUTH_CIPHER_GROUP: - if (param->value & IW_AUTH_CIPHER_NONE) { - ar->arGroupCrypto = NONE_CRYPT; - } - if (param->value & IW_AUTH_CIPHER_WEP40) { - ar->arGroupCrypto = WEP_CRYPT; - } - if (param->value & IW_AUTH_CIPHER_TKIP) { - ar->arGroupCrypto = TKIP_CRYPT; - } - if (param->value & IW_AUTH_CIPHER_CCMP) { - ar->arGroupCrypto = AES_CRYPT; - } - - reset = 1; - break; - case IW_AUTH_KEY_MGMT: - if (param->value & IW_AUTH_KEY_MGMT_PSK) { - if (ar->arAuthMode == WPA_AUTH) { - ar->arAuthMode = WPA_PSK_AUTH; - } else if (ar->arAuthMode == WPA2_AUTH) { - ar->arAuthMode = WPA2_PSK_AUTH; - } - - reset = 1; - } - break; - - case IW_AUTH_TKIP_COUNTERMEASURES: - if (ar->arWmiReady == FALSE) { - return -EIO; - } - wmi_set_tkip_countermeasures_cmd(ar->arWmi, param->value); - break; - - case IW_AUTH_DROP_UNENCRYPTED: - break; - - case IW_AUTH_80211_AUTH_ALG: - if (param->value & IW_AUTH_ALG_OPEN_SYSTEM) { - ar->arDot11AuthMode = OPEN_AUTH; - } - if (param->value & IW_AUTH_ALG_SHARED_KEY) { - ar->arDot11AuthMode = SHARED_AUTH; - } - if (param->value & IW_AUTH_ALG_LEAP) { - ar->arDot11AuthMode = LEAP_AUTH; - ar->arPairwiseCrypto = WEP_CRYPT; - ar->arGroupCrypto = WEP_CRYPT; - } - - reset = 1; - break; - - case IW_AUTH_WPA_ENABLED: - reset = 1; - break; - - case IW_AUTH_RX_UNENCRYPTED_EAPOL: - break; - - case IW_AUTH_PRIVACY_INVOKED: - break; - - default: - printk("%s(): Unknown flag 0x%x\n", __FUNCTION__, param->flags); - return -EOPNOTSUPP; - } - - if (reset) { - A_MEMZERO(ar->arSsid, sizeof(ar->arSsid)); - ar->arSsidLen = 0; - } - - return 0; -} - -static int ar6000_ioctl_giwauth(struct net_device *dev, - struct iw_request_info *info, - struct iw_param *dwrq, - char *extra) -{ - return 0; -} - -static int ar6000_ioctl_siwencodeext(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, - char *extra) -{ - AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev); - struct iw_point *encoding = &wrqu->encoding; - struct iw_encode_ext *ext = (struct iw_encode_ext *)extra; - int alg = ext->alg, idx; - - if (ar->arWlanState == WLAN_DISABLED) { - return -EIO; - } - - /* Determine and validate the key index */ - idx = (encoding->flags & IW_ENCODE_INDEX) - 1; - if (idx) { - if (idx < 0 || idx > 3) - return -EINVAL; - } - - if ((alg == IW_ENCODE_ALG_TKIP) || (alg == IW_ENCODE_ALG_CCMP)) { - struct ieee80211req_key ik; - KEY_USAGE key_usage; - CRYPTO_TYPE key_type = NONE_CRYPT; - int status; - - ar->user_saved_keys.keyOk = FALSE; - - if (alg == IW_ENCODE_ALG_TKIP) { - key_type = TKIP_CRYPT; - ik.ik_type = IEEE80211_CIPHER_TKIP; - } else { - key_type = AES_CRYPT; - ik.ik_type = IEEE80211_CIPHER_AES_CCM; - } - - ik.ik_keyix = idx; - ik.ik_keylen = ext->key_len; - ik.ik_flags = IEEE80211_KEY_RECV; - if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) { - ik.ik_flags |= IEEE80211_KEY_XMIT - | IEEE80211_KEY_DEFAULT; - } - - if (ext->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID) { - memcpy(&ik.ik_keyrsc, ext->rx_seq, 8); - } - - memcpy(ik.ik_keydata, ext->key, ext->key_len); - - ar->user_saved_keys.keyType = key_type; - if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) { - key_usage = GROUP_USAGE; - memset(ik.ik_macaddr, 0, ETH_ALEN); - memcpy(&ar->user_saved_keys.bcast_ik, &ik, - sizeof(struct ieee80211req_key)); - } else { - key_usage = PAIRWISE_USAGE; - memcpy(ik.ik_macaddr, ext->addr.sa_data, ETH_ALEN); - memcpy(&ar->user_saved_keys.ucast_ik, &ik, - sizeof(struct ieee80211req_key)); - } - - status = wmi_addKey_cmd(ar->arWmi, ik.ik_keyix, key_type, - key_usage, ik.ik_keylen, - (A_UINT8 *)&ik.ik_keyrsc, - ik.ik_keydata, - KEY_OP_INIT_VAL, SYNC_BEFORE_WMIFLAG); - - if (status < 0) - return -EIO; - - ar->user_saved_keys.keyOk = TRUE; - - return 0; - - } else { - /* WEP falls back to SIWENCODE */ - return -EOPNOTSUPP; - } - - return 0; -} - - -static int ar6000_ioctl_giwencodeext(struct net_device *dev, - struct iw_request_info *info, - struct iw_point *dwrq, - char *extra) -{ - return 0; -} - - -static int -ar6000_ioctl_setparam(struct net_device *dev, - struct iw_request_info *info, - void *erq, char *extra) -{ - AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev); - int *i = (int *)extra; - int param = i[0]; - int value = i[1]; - int ret = 0; - A_BOOL profChanged = FALSE; - - if (ar->arWlanState == WLAN_DISABLED) { - return -EIO; - } - - switch (param) { - case IEEE80211_PARAM_WPA: - switch (value) { - case WPA_MODE_WPA1: - ar->arAuthMode = WPA_AUTH; - profChanged = TRUE; - break; - case WPA_MODE_WPA2: - ar->arAuthMode = WPA2_AUTH; - profChanged = TRUE; - break; - case WPA_MODE_NONE: - ar->arAuthMode = NONE_AUTH; - profChanged = TRUE; - break; - default: - printk("IEEE80211_PARAM_WPA: Unknown value %d\n", value); - } - break; - case IEEE80211_PARAM_AUTHMODE: - switch(value) { - case IEEE80211_AUTH_WPA_PSK: - if (WPA_AUTH == ar->arAuthMode) { - ar->arAuthMode = WPA_PSK_AUTH; - profChanged = TRUE; - } else if (WPA2_AUTH == ar->arAuthMode) { - ar->arAuthMode = WPA2_PSK_AUTH; - profChanged = TRUE; - } else { - AR_DEBUG_PRINTF("Error - Setting PSK mode when WPA "\ - "param was set to %d\n", - ar->arAuthMode); - ret = -1; - } - break; - case IEEE80211_AUTH_WPA_CCKM: - if (WPA2_AUTH == ar->arAuthMode) { - ar->arAuthMode = WPA2_AUTH_CCKM; - } else { - ar->arAuthMode = WPA_AUTH_CCKM; - } - break; - default: - break; - } - break; - case IEEE80211_PARAM_UCASTCIPHER: - switch (value) { - case IEEE80211_CIPHER_AES_CCM: - ar->arPairwiseCrypto = AES_CRYPT; - profChanged = TRUE; - break; - case IEEE80211_CIPHER_TKIP: - ar->arPairwiseCrypto = TKIP_CRYPT; - profChanged = TRUE; - break; - case IEEE80211_CIPHER_WEP: - ar->arPairwiseCrypto = WEP_CRYPT; - profChanged = TRUE; - break; - case IEEE80211_CIPHER_NONE: - ar->arPairwiseCrypto = NONE_CRYPT; - profChanged = TRUE; - break; - } - break; - case IEEE80211_PARAM_UCASTKEYLEN: - if (!IEEE80211_IS_VALID_WEP_CIPHER_LEN(value)) { - ret = -EIO; - } else { - ar->arPairwiseCryptoLen = value; - } - break; - case IEEE80211_PARAM_MCASTCIPHER: - switch (value) { - case IEEE80211_CIPHER_AES_CCM: - ar->arGroupCrypto = AES_CRYPT; - profChanged = TRUE; - break; - case IEEE80211_CIPHER_TKIP: - ar->arGroupCrypto = TKIP_CRYPT; - profChanged = TRUE; - break; - case IEEE80211_CIPHER_WEP: - ar->arGroupCrypto = WEP_CRYPT; - profChanged = TRUE; - break; - case IEEE80211_CIPHER_NONE: - ar->arGroupCrypto = NONE_CRYPT; - profChanged = TRUE; - break; - } - break; - case IEEE80211_PARAM_MCASTKEYLEN: - if (!IEEE80211_IS_VALID_WEP_CIPHER_LEN(value)) { - ret = -EIO; - } else { - ar->arGroupCryptoLen = value; - } - break; - case IEEE80211_PARAM_COUNTERMEASURES: - if (ar->arWmiReady == FALSE) { - return -EIO; - } - wmi_set_tkip_countermeasures_cmd(ar->arWmi, value); - break; - default: - break; - } - - if (profChanged == TRUE) { - /* - * profile has changed. Erase ssid to signal change - */ - A_MEMZERO(ar->arSsid, sizeof(ar->arSsid)); - ar->arSsidLen = 0; - } - - return ret; -} - -int -ar6000_ioctl_getparam(struct net_device *dev, struct iw_request_info *info, - void *w, char *extra) -{ - return -EIO; /* for now */ -} - -int -ar6000_ioctl_setkey(struct net_device *dev, struct iw_request_info *info, - void *w, char *extra) -{ - AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev); - struct ieee80211req_key *ik = (struct ieee80211req_key *)extra; - KEY_USAGE keyUsage; - A_STATUS status; - CRYPTO_TYPE keyType = NONE_CRYPT; - - if (ar->arWlanState == WLAN_DISABLED) { - return -EIO; - } - - ar->user_saved_keys.keyOk = FALSE; - - if ( 0 == memcmp(ik->ik_macaddr, "\x00\x00\x00\x00\x00\x00", - IEEE80211_ADDR_LEN)) { - keyUsage = GROUP_USAGE; - A_MEMCPY(&ar->user_saved_keys.bcast_ik, ik, - sizeof(struct ieee80211req_key)); - } else { - keyUsage = PAIRWISE_USAGE; - A_MEMCPY(&ar->user_saved_keys.ucast_ik, ik, - sizeof(struct ieee80211req_key)); - } - - switch (ik->ik_type) { - case IEEE80211_CIPHER_WEP: - keyType = WEP_CRYPT; - break; - case IEEE80211_CIPHER_TKIP: - keyType = TKIP_CRYPT; - break; - case IEEE80211_CIPHER_AES_CCM: - keyType = AES_CRYPT; - break; - default: - break; - } - ar->user_saved_keys.keyType = keyType; - - if (IEEE80211_CIPHER_CCKM_KRK != ik->ik_type) { - if (NONE_CRYPT == keyType) { - return -EIO; - } - - status = wmi_addKey_cmd(ar->arWmi, ik->ik_keyix, keyType, keyUsage, - ik->ik_keylen, (A_UINT8 *)&ik->ik_keyrsc, - ik->ik_keydata, KEY_OP_INIT_VAL, - SYNC_BEFORE_WMIFLAG); - - if (status != A_OK) { - return -EIO; - } - } else { - status = wmi_add_krk_cmd(ar->arWmi, ik->ik_keydata); - } - - ar->user_saved_keys.keyOk = TRUE; - - return 0; -} - - -/* - * SIOCGIWNAME - */ -int -ar6000_ioctl_giwname(struct net_device *dev, - struct iw_request_info *info, - char *name, char *extra) -{ - AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev); - - if (ar->arWlanState == WLAN_DISABLED) { - return -EIO; - } - - switch (ar->arPhyCapability) { - case (WMI_11A_CAPABILITY): - strncpy(name, "AR6000 802.11a", IFNAMSIZ); - break; - case (WMI_11G_CAPABILITY): - strncpy(name, "AR6000 802.11g", IFNAMSIZ); - break; - case (WMI_11AG_CAPABILITY): - strncpy(name, "AR6000 802.11ag", IFNAMSIZ); - break; - default: - strncpy(name, "AR6000 802.11", IFNAMSIZ); - break; - } - - return 0; -} - -/* - * SIOCSIWFREQ - */ -int -ar6000_ioctl_siwfreq(struct net_device *dev, - struct iw_request_info *info, - struct iw_freq *freq, char *extra) -{ - AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev); - - if (ar->arWlanState == WLAN_DISABLED) { - return -EIO; - } - - /* - * We support limiting the channels via wmiconfig. - * - * We use this command to configure the channel hint for the connect cmd - * so it is possible the target will end up connecting to a different - * channel. - */ - if (freq->e > 1) { - return -EINVAL; - } else if (freq->e == 1) { - ar->arChannelHint = freq->m / 100000; - } else { - ar->arChannelHint = wlan_ieee2freq(freq->m); - } - - A_PRINTF("channel hint set to %d\n", ar->arChannelHint); - return 0; -} - -/* - * SIOCGIWFREQ - */ -int -ar6000_ioctl_giwfreq(struct net_device *dev, - struct iw_request_info *info, - struct iw_freq *freq, char *extra) -{ - AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev); - - if (ar->arWlanState == WLAN_DISABLED) { - return -EIO; - } - - if (ar->arConnected != TRUE) { - return -EINVAL; - } - - freq->m = ar->arBssChannel * 100000; - freq->e = 1; - - return 0; -} - -/* - * SIOCSIWMODE - */ -int -ar6000_ioctl_siwmode(struct net_device *dev, - struct iw_request_info *info, - __u32 *mode, char *extra) -{ - AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev); - - if (ar->arWlanState == WLAN_DISABLED) { - return -EIO; - } - - switch (*mode) { - case IW_MODE_INFRA: - ar->arNetworkType = INFRA_NETWORK; - break; - case IW_MODE_ADHOC: - ar->arNetworkType = ADHOC_NETWORK; - break; - default: - return -EINVAL; - } - - return 0; -} - -/* - * SIOCGIWMODE - */ -int -ar6000_ioctl_giwmode(struct net_device *dev, - struct iw_request_info *info, - __u32 *mode, char *extra) -{ - AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev); - - if (ar->arWlanState == WLAN_DISABLED) { - return -EIO; - } - - switch (ar->arNetworkType) { - case INFRA_NETWORK: - *mode = IW_MODE_INFRA; - break; - case ADHOC_NETWORK: - *mode = IW_MODE_ADHOC; - break; - default: - return -EIO; - } - return 0; -} - -/* - * SIOCSIWSENS - */ -int -ar6000_ioctl_siwsens(struct net_device *dev, - struct iw_request_info *info, - struct iw_param *sens, char *extra) -{ - return 0; -} - -/* - * SIOCGIWSENS - */ -int -ar6000_ioctl_giwsens(struct net_device *dev, - struct iw_request_info *info, - struct iw_param *sens, char *extra) -{ - sens->value = 0; - sens->fixed = 1; - - return 0; -} - -/* - * SIOCGIWRANGE - */ -int -ar6000_ioctl_giwrange(struct net_device *dev, - struct iw_request_info *info, - struct iw_point *data, char *extra) -{ - AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev); - struct iw_range *range = (struct iw_range *) extra; - int i, ret = 0; - - if (ar->arWmiReady == FALSE) { - return -EIO; - } - - if (ar->arWlanState == WLAN_DISABLED) { - return -EIO; - } - - if (down_interruptible(&ar->arSem)) { - return -ERESTARTSYS; - } - ar->arNumChannels = -1; - A_MEMZERO(ar->arChannelList, sizeof (ar->arChannelList)); - - if (wmi_get_channelList_cmd(ar->arWmi) != A_OK) { - up(&ar->arSem); - return -EIO; - } - - wait_event_interruptible_timeout(arEvent, ar->arNumChannels != -1, wmitimeout * HZ); - - if (signal_pending(current)) { - up(&ar->arSem); - return -EINTR; - } - - data->length = sizeof(struct iw_range); - A_MEMZERO(range, sizeof(struct iw_range)); - - range->txpower_capa = IW_TXPOW_DBM; - - range->min_pmp = 1 * 1024; - range->max_pmp = 65535 * 1024; - range->min_pmt = 1 * 1024; - range->max_pmt = 1000 * 1024; - range->pmp_flags = IW_POWER_PERIOD; - range->pmt_flags = IW_POWER_TIMEOUT; - range->pm_capa = 0; - - range->we_version_compiled = WIRELESS_EXT; - range->we_version_source = 13; - - range->retry_capa = IW_RETRY_LIMIT; - range->retry_flags = IW_RETRY_LIMIT; - range->min_retry = 0; - range->max_retry = 255; - - range->num_frequency = range->num_channels = ar->arNumChannels; - for (i = 0; i < ar->arNumChannels; i++) { - range->freq[i].i = wlan_freq2ieee(ar->arChannelList[i]); - range->freq[i].m = ar->arChannelList[i] * 100000; - range->freq[i].e = 1; - /* - * Linux supports max of 32 channels, bail out once you - * reach the max. - */ - if (i == IW_MAX_FREQUENCIES) { - break; - } - } - - /* Max quality is max field value minus noise floor */ - range->max_qual.qual = 0xff - 161; - - /* - * In order to use dBm measurements, 'level' must be lower - * than any possible measurement (see iw_print_stats() in - * wireless tools). It's unclear how this is meant to be - * done, but setting zero in these values forces dBm and - * the actual numbers are not used. - */ - range->max_qual.level = 0; - range->max_qual.noise = 0; - - range->sensitivity = 3; - - range->max_encoding_tokens = 4; - /* XXX query driver to find out supported key sizes */ - range->num_encoding_sizes = 3; - range->encoding_size[0] = 5; /* 40-bit */ - range->encoding_size[1] = 13; /* 104-bit */ - range->encoding_size[2] = 16; /* 128-bit */ - - range->num_bitrates = 0; - - /* estimated maximum TCP throughput values (bps) */ - range->throughput = 22000000; - - range->min_rts = 0; - range->max_rts = 2347; - range->min_frag = 256; - range->max_frag = 2346; - - up(&ar->arSem); - - return ret; -} - - -/* - * SIOCSIWAP - * This ioctl is used to set the desired bssid for the connect command. - */ -int -ar6000_ioctl_siwap(struct net_device *dev, - struct iw_request_info *info, - struct sockaddr *ap_addr, char *extra) -{ - AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev); - - if (ar->arWlanState == WLAN_DISABLED) { - return -EIO; - } - - if (ap_addr->sa_family != ARPHRD_ETHER) { - return -EIO; - } - - if (A_MEMCMP(&ap_addr->sa_data, bcast_mac, AR6000_ETH_ADDR_LEN) == 0) { - A_MEMZERO(ar->arReqBssid, sizeof(ar->arReqBssid)); - } else { - A_MEMCPY(ar->arReqBssid, &ap_addr->sa_data, sizeof(ar->arReqBssid)); - } - - return 0; -} - -/* - * SIOCGIWAP - */ -int -ar6000_ioctl_giwap(struct net_device *dev, - struct iw_request_info *info, - struct sockaddr *ap_addr, char *extra) -{ - AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev); - - if (ar->arWlanState == WLAN_DISABLED) { - return -EIO; - } - - if (ar->arConnected != TRUE) { - return -EINVAL; - } - - A_MEMCPY(&ap_addr->sa_data, ar->arBssid, sizeof(ar->arBssid)); - ap_addr->sa_family = ARPHRD_ETHER; - - return 0; -} - -/* - * SIOCGIWAPLIST - */ -int -ar6000_ioctl_iwaplist(struct net_device *dev, - struct iw_request_info *info, - struct iw_point *data, char *extra) -{ - return -EIO; /* for now */ -} - -/* - * SIOCSIWSCAN - */ -int -ar6000_ioctl_siwscan(struct net_device *dev, - struct iw_request_info *info, - struct iw_point *data, char *extra) -{ -#define ACT_DWELLTIME_DEFAULT 105 -#define HOME_TXDRAIN_TIME 100 -#define SCAN_INT HOME_TXDRAIN_TIME + ACT_DWELLTIME_DEFAULT - AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev); - int ret = 0; - - if (ar->arWmiReady == FALSE) { - return -EIO; - } - - if (ar->arWlanState == WLAN_DISABLED) { - return -EIO; - } - - /* We ask for everything from the target */ - if (wmi_bssfilter_cmd(ar->arWmi, ALL_BSS_FILTER, 0) != A_OK) { - printk("Couldn't set filtering\n"); - ret = -EIO; - } - - if (wmi_startscan_cmd(ar->arWmi, WMI_LONG_SCAN, FALSE, FALSE, \ - HOME_TXDRAIN_TIME, SCAN_INT) != A_OK) { - ret = -EIO; - } - - ar->scan_complete = 0; - wait_event_interruptible_timeout(ar6000_scan_queue, ar->scan_complete, - 5 * HZ); - - if (wmi_bssfilter_cmd(ar->arWmi, NONE_BSS_FILTER, 0) != A_OK) { - printk("Couldn't set filtering\n"); - ret = -EIO; - } - - return ret; -#undef ACT_DWELLTIME_DEFAULT -#undef HOME_TXDRAIN_TIME -#undef SCAN_INT -} - - -/* - * Units are in db above the noise floor. That means the - * rssi values reported in the tx/rx descriptors in the - * driver are the SNR expressed in db. - * - * If you assume that the noise floor is -95, which is an - * excellent assumption 99.5 % of the time, then you can - * derive the absolute signal level (i.e. -95 + rssi). - * There are some other slight factors to take into account - * depending on whether the rssi measurement is from 11b, - * 11g, or 11a. These differences are at most 2db and - * can be documented. - * - * NB: various calculations are based on the orinoco/wavelan - * drivers for compatibility - */ -static void -ar6000_set_quality(struct iw_quality *iq, A_INT8 rssi) -{ - if (rssi < 0) { - iq->qual = 0; - } else { - iq->qual = rssi; - } - - /* NB: max is 94 because noise is hardcoded to 161 */ - if (iq->qual > 94) - iq->qual = 94; - - iq->noise = 161; /* -95dBm */ - iq->level = iq->noise + iq->qual; - iq->updated = 7; -} - - -/* Structures to export the Wireless Handlers */ -static const iw_handler ath_handlers[] = { - (iw_handler) NULL, /* SIOCSIWCOMMIT */ - (iw_handler) ar6000_ioctl_giwname, /* SIOCGIWNAME */ - (iw_handler) NULL, /* SIOCSIWNWID */ - (iw_handler) NULL, /* SIOCGIWNWID */ - (iw_handler) ar6000_ioctl_siwfreq, /* SIOCSIWFREQ */ - (iw_handler) ar6000_ioctl_giwfreq, /* SIOCGIWFREQ */ - (iw_handler) ar6000_ioctl_siwmode, /* SIOCSIWMODE */ - (iw_handler) ar6000_ioctl_giwmode, /* SIOCGIWMODE */ - (iw_handler) ar6000_ioctl_siwsens, /* SIOCSIWSENS */ - (iw_handler) ar6000_ioctl_giwsens, /* SIOCGIWSENS */ - (iw_handler) NULL /* not _used */, /* SIOCSIWRANGE */ - (iw_handler) ar6000_ioctl_giwrange, /* SIOCGIWRANGE */ - (iw_handler) NULL /* not used */, /* SIOCSIWPRIV */ - (iw_handler) NULL /* kernel code */, /* SIOCGIWPRIV */ - (iw_handler) NULL /* not used */, /* SIOCSIWSTATS */ - (iw_handler) NULL /* kernel code */, /* SIOCGIWSTATS */ - (iw_handler) NULL, /* SIOCSIWSPY */ - (iw_handler) NULL, /* SIOCGIWSPY */ - (iw_handler) NULL, /* SIOCSIWTHRSPY */ - (iw_handler) NULL, /* SIOCGIWTHRSPY */ - (iw_handler) ar6000_ioctl_siwap, /* SIOCSIWAP */ - (iw_handler) ar6000_ioctl_giwap, /* SIOCGIWAP */ - (iw_handler) NULL, /* -- hole -- */ - (iw_handler) ar6000_ioctl_iwaplist, /* SIOCGIWAPLIST */ - (iw_handler) ar6000_ioctl_siwscan, /* SIOCSIWSCAN */ - (iw_handler) ar6000_ioctl_giwscan, /* SIOCGIWSCAN */ - (iw_handler) ar6000_ioctl_siwessid, /* SIOCSIWESSID */ - (iw_handler) ar6000_ioctl_giwessid, /* SIOCGIWESSID */ - (iw_handler) NULL, /* SIOCSIWNICKN */ - (iw_handler) NULL, /* SIOCGIWNICKN */ - (iw_handler) NULL, /* -- hole -- */ - (iw_handler) NULL, /* -- hole -- */ - (iw_handler) ar6000_ioctl_siwrate, /* SIOCSIWRATE */ - (iw_handler) ar6000_ioctl_giwrate, /* SIOCGIWRATE */ - (iw_handler) NULL, /* SIOCSIWRTS */ - (iw_handler) NULL, /* SIOCGIWRTS */ - (iw_handler) NULL, /* SIOCSIWFRAG */ - (iw_handler) NULL, /* SIOCGIWFRAG */ - (iw_handler) ar6000_ioctl_siwtxpow, /* SIOCSIWTXPOW */ - (iw_handler) ar6000_ioctl_giwtxpow, /* SIOCGIWTXPOW */ - (iw_handler) ar6000_ioctl_siwretry, /* SIOCSIWRETRY */ - (iw_handler) ar6000_ioctl_giwretry, /* SIOCGIWRETRY */ - (iw_handler) ar6000_ioctl_siwencode, /* SIOCSIWENCODE */ - (iw_handler) ar6000_ioctl_giwencode, /* SIOCGIWENCODE */ - (iw_handler) ar6000_ioctl_siwpower, /* SIOCSIWPOWER */ - (iw_handler) ar6000_ioctl_giwpower, /* SIOCGIWPOWER */ - (iw_handler) NULL, /* -- hole -- */ - (iw_handler) NULL, /* -- hole -- */ - (iw_handler) ar6000_ioctl_siwgenie, /* SIOCSIWGENIE */ - (iw_handler) ar6000_ioctl_giwgenie, /* SIOCGIWGENIE */ - (iw_handler) ar6000_ioctl_siwauth, /* SIOCSIWAUTH */ - (iw_handler) ar6000_ioctl_giwauth, /* SIOCGIWAUTH */ - (iw_handler) ar6000_ioctl_siwencodeext,/* SIOCSIWENCODEEXT */ - (iw_handler) ar6000_ioctl_giwencodeext,/* SIOCGIWENCODEEXT */ - (iw_handler) NULL, /* SIOCSIWPMKSA */ -}; - -static const iw_handler ath_priv_handlers[] = { - (iw_handler) ar6000_ioctl_setparam, /* SIOCWFIRSTPRIV+0 */ - (iw_handler) ar6000_ioctl_getparam, /* SIOCWFIRSTPRIV+1 */ - (iw_handler) ar6000_ioctl_setkey, /* SIOCWFIRSTPRIV+2 */ - (iw_handler) ar6000_ioctl_setwmmparams, /* SIOCWFIRSTPRIV+3 */ - (iw_handler) ar6000_ioctl_delkey, /* SIOCWFIRSTPRIV+4 */ - (iw_handler) ar6000_ioctl_getwmmparams, /* SIOCWFIRSTPRIV+5 */ - (iw_handler) ar6000_ioctl_setoptie, /* SIOCWFIRSTPRIV+6 */ - (iw_handler) ar6000_ioctl_setmlme, /* SIOCWFIRSTPRIV+7 */ - (iw_handler) ar6000_ioctl_addpmkid, /* SIOCWFIRSTPRIV+8 */ -}; - -#define IW_PRIV_TYPE_KEY \ - (IW_PRIV_TYPE_BYTE | sizeof(struct ieee80211req_key)) -#define IW_PRIV_TYPE_DELKEY \ - (IW_PRIV_TYPE_BYTE | sizeof(struct ieee80211req_del_key)) -#define IW_PRIV_TYPE_MLME \ - (IW_PRIV_TYPE_BYTE | sizeof(struct ieee80211req_mlme)) -#define IW_PRIV_TYPE_ADDPMKID \ - (IW_PRIV_TYPE_BYTE | sizeof(struct ieee80211req_addpmkid)) - -static const struct iw_priv_args ar6000_priv_args[] = { - { IEEE80211_IOCTL_SETKEY, - IW_PRIV_TYPE_KEY | IW_PRIV_SIZE_FIXED, 0, "setkey"}, - { IEEE80211_IOCTL_DELKEY, - IW_PRIV_TYPE_DELKEY | IW_PRIV_SIZE_FIXED, 0, "delkey"}, - { IEEE80211_IOCTL_SETPARAM, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, 0, "setparam"}, - { IEEE80211_IOCTL_GETPARAM, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getparam"}, - { IEEE80211_IOCTL_SETWMMPARAMS, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 4, 0, "setwmmparams"}, - { IEEE80211_IOCTL_GETWMMPARAMS, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 3, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getwmmparams"}, - { IEEE80211_IOCTL_SETOPTIE, - IW_PRIV_TYPE_BYTE, 0, "setie"}, - { IEEE80211_IOCTL_SETMLME, - IW_PRIV_TYPE_MLME, 0, "setmlme"}, - { IEEE80211_IOCTL_ADDPMKID, - IW_PRIV_TYPE_ADDPMKID | IW_PRIV_SIZE_FIXED, 0, "addpmkid"}, -}; - -void ar6000_ioctl_iwsetup(struct iw_handler_def *def) -{ - def->private_args = (struct iw_priv_args *)ar6000_priv_args; - def->num_private_args = ARRAY_SIZE(ar6000_priv_args); -} - -struct iw_handler_def ath_iw_handler_def = { - .standard = (iw_handler *)ath_handlers, - .num_standard = ARRAY_SIZE(ath_handlers), - .private = (iw_handler *)ath_priv_handlers, - .num_private = ARRAY_SIZE(ath_priv_handlers), -}; - - diff --git a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/bmi/bmi.c b/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/bmi/bmi.c deleted file mode 100644 index d7b610c15..000000000 --- a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/bmi/bmi.c +++ /dev/null @@ -1,657 +0,0 @@ -/* - * Copyright (c) 2004-2007 Atheros Communications Inc. - * All rights reserved. - * - * - * 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; - * - * Software distributed under the License is distributed on an "AS - * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or - * implied. See the License for the specific language governing - * rights and limitations under the License. - * - * - * - */ - -#include "hif.h" -#include "bmi.h" -#include "htc_api.h" -#include "bmi_internal.h" - -/* -Although we had envisioned BMI to run on top of HTC, this is not what the -final implementation boiled down to on dragon. Its a part of BSP and does -not use the HTC protocol either. On the host side, however, we were still -living with the original idea. I think the time has come to accept the truth -and separate it from HTC which has been carrying BMI's burden all this while. -It shall make HTC state machine relatively simpler -*/ - -/* APIs visible to the driver */ -void -BMIInit(void) -{ - bmiDone = FALSE; -} - -A_STATUS -BMIDone(HIF_DEVICE *device) -{ - A_STATUS status; - A_UINT32 cid; - - if (bmiDone) { - AR_DEBUG_PRINTF (ATH_DEBUG_BMI, ("BMIDone skipped\n")); - return A_OK; - } - - AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Done: Enter (device: 0x%p)\n", device)); - bmiDone = TRUE; - cid = BMI_DONE; - - status = bmiBufferSend(device, (A_UCHAR *)&cid, sizeof(cid)); - if (status != A_OK) { - AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n")); - return A_ERROR; - } - AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Done: Exit\n")); - - return A_OK; -} - -A_STATUS -BMIGetTargetInfo(HIF_DEVICE *device, struct bmi_target_info *targ_info) -{ - A_STATUS status; - A_UINT32 cid; - - if (bmiDone) { - AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Command disallowed\n")); - return A_ERROR; - } - - AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Get Target Info: Enter (device: 0x%p)\n", device)); - cid = BMI_GET_TARGET_INFO; - - status = bmiBufferSend(device, (A_UCHAR *)&cid, sizeof(cid)); - if (status != A_OK) { - AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n")); - return A_ERROR; - } - - status = bmiBufferReceive(device, (A_UCHAR *)&targ_info->target_ver, - sizeof(targ_info->target_ver)); - if (status != A_OK) { - AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to read Target Version from the device\n")); - return A_ERROR; - } - - if (targ_info->target_ver == TARGET_VERSION_SENTINAL) { - /* Determine how many bytes are in the Target's targ_info */ - status = bmiBufferReceive(device, (A_UCHAR *)&targ_info->target_info_byte_count, - sizeof(targ_info->target_info_byte_count)); - if (status != A_OK) { - AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to read Target Info Byte Count from the device\n")); - return A_ERROR; - } - - /* - * The Target's targ_info doesn't match the Host's targ_info. - * We need to do some backwards compatibility work to make this OK. - */ - A_ASSERT(targ_info->target_info_byte_count == sizeof(*targ_info)); - - /* Read the remainder of the targ_info */ - status = bmiBufferReceive(device, - ((A_UCHAR *)targ_info)+sizeof(targ_info->target_info_byte_count), - sizeof(*targ_info)-sizeof(targ_info->target_info_byte_count)); - if (status != A_OK) { - AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to read Target Info (%d bytes) from the device\n", - targ_info->target_info_byte_count)); - return A_ERROR; - } - } else { - /* - * Target must be an AR6001 whose firmware does not - * support BMI_GET_TARGET_INFO. Construct the data - * that it would have sent. - */ - targ_info->target_info_byte_count = sizeof(targ_info); - targ_info->target_type = TARGET_TYPE_AR6001; - } - - AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Get Target Info: Exit (ver: 0x%x type: 0x%x)\n", - targ_info->target_ver, targ_info->target_type)); - printk("BMI Get Target Info: Exit (ver: 0x%x type: 0x%x)\n", - targ_info->target_ver, targ_info->target_type); - - return A_OK; -} - -A_STATUS -BMIReadMemory(HIF_DEVICE *device, - A_UINT32 address, - A_UCHAR *buffer, - A_UINT32 length) -{ - A_UINT32 cid; - A_STATUS status; - A_UINT32 offset; - A_UINT32 remaining, rxlen; - static A_UCHAR data[BMI_DATASZ_MAX + sizeof(cid) + sizeof(address) + sizeof(length)]; - memset (&data, 0, BMI_DATASZ_MAX + sizeof(cid) + sizeof(address) + sizeof(length)); - - if (bmiDone) { - AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Command disallowed\n")); - return A_ERROR; - } - - AR_DEBUG_PRINTF(ATH_DEBUG_BMI, - ("BMI Read Memory: Enter (device: 0x%p, address: 0x%x, length: %d)\n", - device, address, length)); - - cid = BMI_READ_MEMORY; - - remaining = length; - - while (remaining) - { - rxlen = (remaining < BMI_DATASZ_MAX) ? remaining : BMI_DATASZ_MAX; - offset = 0; - A_MEMCPY(&data[offset], &cid, sizeof(cid)); - offset += sizeof(cid); - A_MEMCPY(&data[offset], &address, sizeof(address)); - offset += sizeof(address); - A_MEMCPY(&data[offset], &rxlen, sizeof(rxlen)); - offset += sizeof(length); - - status = bmiBufferSend(device, data, offset); - if (status != A_OK) { - AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n")); - return A_ERROR; - } - status = bmiBufferReceive(device, data, rxlen); - if (status != A_OK) { - AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to read from the device\n")); - return A_ERROR; - } - A_MEMCPY(&buffer[length - remaining], data, rxlen); - remaining -= rxlen; address += rxlen; - } - - AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Read Memory: Exit\n")); - return A_OK; -} - -A_STATUS -BMIWriteMemory(HIF_DEVICE *device, - A_UINT32 address, - A_UCHAR *buffer, - A_UINT32 length) -{ - A_UINT32 cid; - A_STATUS status; - A_UINT32 offset; - A_UINT32 remaining, txlen; - const A_UINT32 header = sizeof(cid) + sizeof(address) + sizeof(length); - static A_UCHAR data[BMI_DATASZ_MAX + sizeof(cid) + sizeof(address) + sizeof(length)]; - memset (&data, 0, header); - - if (bmiDone) { - AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Command disallowed\n")); - return A_ERROR; - } - - AR_DEBUG_PRINTF(ATH_DEBUG_BMI, - ("BMI Write Memory: Enter (device: 0x%p, address: 0x%x, length: %d)\n", - device, address, length)); - - cid = BMI_WRITE_MEMORY; - - remaining = length; - while (remaining) - { - txlen = (remaining < (BMI_DATASZ_MAX - header)) ? - remaining : (BMI_DATASZ_MAX - header); - offset = 0; - A_MEMCPY(&data[offset], &cid, sizeof(cid)); - offset += sizeof(cid); - A_MEMCPY(&data[offset], &address, sizeof(address)); - offset += sizeof(address); - A_MEMCPY(&data[offset], &txlen, sizeof(txlen)); - offset += sizeof(txlen); - A_MEMCPY(&data[offset], &buffer[length - remaining], txlen); - offset += txlen; - status = bmiBufferSend(device, data, offset); - if (status != A_OK) { - AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n")); - return A_ERROR; - } - remaining -= txlen; address += txlen; - } - - AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Write Memory: Exit\n")); - - return A_OK; -} - -A_STATUS -BMIExecute(HIF_DEVICE *device, - A_UINT32 address, - A_UINT32 *param) -{ - A_UINT32 cid; - A_STATUS status; - A_UINT32 offset; - static A_UCHAR data[sizeof(cid) + sizeof(address) + sizeof(*param)]; - memset (&data, 0, sizeof(cid) + sizeof(address) + sizeof(*param)); - - if (bmiDone) { - AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Command disallowed\n")); - return A_ERROR; - } - - AR_DEBUG_PRINTF(ATH_DEBUG_BMI, - ("BMI Execute: Enter (device: 0x%p, address: 0x%x, param: %d)\n", - device, address, *param)); - - cid = BMI_EXECUTE; - - offset = 0; - A_MEMCPY(&data[offset], &cid, sizeof(cid)); - offset += sizeof(cid); - A_MEMCPY(&data[offset], &address, sizeof(address)); - offset += sizeof(address); - A_MEMCPY(&data[offset], param, sizeof(*param)); - offset += sizeof(*param); - status = bmiBufferSend(device, data, offset); - if (status != A_OK) { - AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n")); - return A_ERROR; - } - - status = bmiBufferReceive(device, data, sizeof(*param)); - if (status != A_OK) { - AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to read from the device\n")); - return A_ERROR; - } - - A_MEMCPY(param, data, sizeof(*param)); - - AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Execute: Exit (param: %d)\n", *param)); - return A_OK; -} - -A_STATUS -BMISetAppStart(HIF_DEVICE *device, - A_UINT32 address) -{ - A_UINT32 cid; - A_STATUS status; - A_UINT32 offset; - static A_UCHAR data[sizeof(cid) + sizeof(address)]; - memset (&data, 0, sizeof(cid) + sizeof(address)); - - if (bmiDone) { - AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Command disallowed\n")); - return A_ERROR; - } - - AR_DEBUG_PRINTF(ATH_DEBUG_BMI, - ("BMI Set App Start: Enter (device: 0x%p, address: 0x%x)\n", - device, address)); - - cid = BMI_SET_APP_START; - - offset = 0; - A_MEMCPY(&data[offset], &cid, sizeof(cid)); - offset += sizeof(cid); - A_MEMCPY(&data[offset], &address, sizeof(address)); - offset += sizeof(address); - status = bmiBufferSend(device, data, offset); - if (status != A_OK) { - AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n")); - return A_ERROR; - } - - AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Set App Start: Exit\n")); - return A_OK; -} - -A_STATUS -BMIReadSOCRegister(HIF_DEVICE *device, - A_UINT32 address, - A_UINT32 *param) -{ - A_UINT32 cid; - A_STATUS status; - A_UINT32 offset; - static A_UCHAR data[sizeof(cid) + sizeof(address)]; - memset (&data, 0, sizeof(cid) + sizeof(address)); - - if (bmiDone) { - AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Command disallowed\n")); - return A_ERROR; - } - - AR_DEBUG_PRINTF(ATH_DEBUG_BMI, - ("BMI Read SOC Register: Enter (device: 0x%p, address: 0x%x)\n", - device, address)); - - cid = BMI_READ_SOC_REGISTER; - - offset = 0; - A_MEMCPY(&data[offset], &cid, sizeof(cid)); - offset += sizeof(cid); - A_MEMCPY(&data[offset], &address, sizeof(address)); - offset += sizeof(address); - - status = bmiBufferSend(device, data, offset); - if (status != A_OK) { - AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n")); - return A_ERROR; - } - - status = bmiBufferReceive(device, data, sizeof(*param)); - if (status != A_OK) { - AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to read from the device\n")); - return A_ERROR; - } - A_MEMCPY(param, data, sizeof(*param)); - - AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Read SOC Register: Exit (value: %d)\n", *param)); - return A_OK; -} - -A_STATUS -BMIWriteSOCRegister(HIF_DEVICE *device, - A_UINT32 address, - A_UINT32 param) -{ - A_UINT32 cid; - A_STATUS status; - A_UINT32 offset; - static A_UCHAR data[sizeof(cid) + sizeof(address) + sizeof(param)]; - - memset (&data, 0, sizeof(cid) + sizeof(address) + sizeof(param)); - - if (bmiDone) { - AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Command disallowed\n")); - return A_ERROR; - } - - AR_DEBUG_PRINTF(ATH_DEBUG_BMI, - ("BMI Write SOC Register: Enter (device: 0x%p, address: 0x%x, param: %d)\n", - device, address, param)); - - cid = BMI_WRITE_SOC_REGISTER; - - offset = 0; - A_MEMCPY(&data[offset], &cid, sizeof(cid)); - offset += sizeof(cid); - A_MEMCPY(&data[offset], &address, sizeof(address)); - offset += sizeof(address); - A_MEMCPY(&data[offset], ¶m, sizeof(param)); - offset += sizeof(param); - status = bmiBufferSend(device, data, offset); - if (status != A_OK) { - AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n")); - return A_ERROR; - } - - AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Read SOC Register: Exit\n")); - return A_OK; -} - -A_STATUS -BMIrompatchInstall(HIF_DEVICE *device, - A_UINT32 ROM_addr, - A_UINT32 RAM_addr, - A_UINT32 nbytes, - A_UINT32 do_activate, - A_UINT32 *rompatch_id) -{ - A_UINT32 cid; - A_STATUS status; - A_UINT32 offset; - static A_UCHAR data[sizeof(cid) + sizeof(ROM_addr) + sizeof(RAM_addr) + - sizeof(nbytes) + sizeof(do_activate)]; - - memset (&data, 0, sizeof(cid) + sizeof(ROM_addr) + sizeof(RAM_addr) + - sizeof(nbytes) + sizeof(do_activate)); - - if (bmiDone) { - AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Command disallowed\n")); - return A_ERROR; - } - - AR_DEBUG_PRINTF(ATH_DEBUG_BMI, - ("BMI rompatch Install: Enter (device: 0x%p, ROMaddr: 0x%x, RAMaddr: 0x%x length: %d activate: %d)\n", - device, ROM_addr, RAM_addr, nbytes, do_activate)); - - cid = BMI_ROMPATCH_INSTALL; - - offset = 0; - A_MEMCPY(&data[offset], &cid, sizeof(cid)); - offset += sizeof(cid); - A_MEMCPY(&data[offset], &ROM_addr, sizeof(ROM_addr)); - offset += sizeof(ROM_addr); - A_MEMCPY(&data[offset], &RAM_addr, sizeof(RAM_addr)); - offset += sizeof(RAM_addr); - A_MEMCPY(&data[offset], &nbytes, sizeof(nbytes)); - offset += sizeof(nbytes); - A_MEMCPY(&data[offset], &do_activate, sizeof(do_activate)); - offset += sizeof(do_activate); - status = bmiBufferSend(device, data, offset); - if (status != A_OK) { - AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n")); - return A_ERROR; - } - - status = bmiBufferReceive(device, (A_UCHAR *)rompatch_id, sizeof(*rompatch_id)); - if (status != A_OK) { - AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to read from the device\n")); - return A_ERROR; - } - - AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI rompatch Install: (rompatch_id=%d)\n", *rompatch_id)); - return A_OK; -} - -A_STATUS -BMIrompatchUninstall(HIF_DEVICE *device, - A_UINT32 rompatch_id) -{ - A_UINT32 cid; - A_STATUS status; - A_UINT32 offset; - static A_UCHAR data[sizeof(cid) + sizeof(rompatch_id)]; - memset (&data, 0, sizeof(cid) + sizeof(rompatch_id)); - - if (bmiDone) { - AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Command disallowed\n")); - return A_ERROR; - } - - AR_DEBUG_PRINTF(ATH_DEBUG_BMI, - ("BMI rompatch Uninstall: Enter (device: 0x%p, rompatch_id: %d)\n", - device, rompatch_id)); - - cid = BMI_ROMPATCH_UNINSTALL; - - offset = 0; - A_MEMCPY(&data[offset], &cid, sizeof(cid)); - offset += sizeof(cid); - A_MEMCPY(&data[offset], &rompatch_id, sizeof(rompatch_id)); - offset += sizeof(rompatch_id); - status = bmiBufferSend(device, data, offset); - if (status != A_OK) { - AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n")); - return A_ERROR; - } - - AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI rompatch UNinstall: (rompatch_id=0x%x)\n", rompatch_id)); - return A_OK; -} - -static A_STATUS -_BMIrompatchChangeActivation(HIF_DEVICE *device, - A_UINT32 rompatch_count, - A_UINT32 *rompatch_list, - A_UINT32 do_activate) -{ - A_UINT32 cid; - A_STATUS status; - A_UINT32 offset; - static A_UCHAR data[BMI_DATASZ_MAX + sizeof(cid) + sizeof(rompatch_count)]; - A_UINT32 length; - - memset (&data, 0, BMI_DATASZ_MAX + sizeof(cid) + sizeof(rompatch_count)); - - if (bmiDone) { - AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Command disallowed\n")); - return A_ERROR; - } - - AR_DEBUG_PRINTF(ATH_DEBUG_BMI, - ("BMI Change rompatch Activation: Enter (device: 0x%p, count: %d)\n", - device, rompatch_count)); - - cid = do_activate ? BMI_ROMPATCH_ACTIVATE : BMI_ROMPATCH_DEACTIVATE; - - offset = 0; - A_MEMCPY(&data[offset], &cid, sizeof(cid)); - offset += sizeof(cid); - A_MEMCPY(&data[offset], &rompatch_count, sizeof(rompatch_count)); - offset += sizeof(rompatch_count); - length = rompatch_count * sizeof(*rompatch_list); - A_MEMCPY(&data[offset], rompatch_list, length); - offset += length; - status = bmiBufferSend(device, data, offset); - if (status != A_OK) { - AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n")); - return A_ERROR; - } - - AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Change rompatch Activation: Exit\n")); - - return A_OK; -} - -A_STATUS -BMIrompatchActivate(HIF_DEVICE *device, - A_UINT32 rompatch_count, - A_UINT32 *rompatch_list) -{ - return _BMIrompatchChangeActivation(device, rompatch_count, rompatch_list, 1); -} - -A_STATUS -BMIrompatchDeactivate(HIF_DEVICE *device, - A_UINT32 rompatch_count, - A_UINT32 *rompatch_list) -{ - return _BMIrompatchChangeActivation(device, rompatch_count, rompatch_list, 0); -} - -/* BMI Access routines */ -A_STATUS -bmiBufferSend(HIF_DEVICE *device, - A_UCHAR *buffer, - A_UINT32 length) -{ - A_STATUS status; - A_UINT32 timeout; - A_UINT32 address; - static A_UINT32 cmdCredits; - A_UINT32 mboxAddress[HTC_MAILBOX_NUM_MAX]; - - HIFConfigureDevice(device, HIF_DEVICE_GET_MBOX_ADDR, - &mboxAddress, sizeof(mboxAddress)); - - cmdCredits = 0; - timeout = BMI_COMMUNICATION_TIMEOUT; - - while(timeout-- && !cmdCredits) { - /* Read the counter register to get the command credits */ - address = COUNT_DEC_ADDRESS + (HTC_MAILBOX_NUM_MAX + ENDPOINT1) * 4; - /* hit the credit counter with a 4-byte access, the first byte read will hit the counter and cause - * a decrement, while the remaining 3 bytes has no effect. The rationale behind this is to - * make all HIF accesses 4-byte aligned */ - status = HIFReadWrite(device, address, (A_UINT8 *)&cmdCredits, 4, - HIF_RD_SYNC_BYTE_INC, NULL); - if (status != A_OK) { - AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to decrement the command credit count register\n")); - return A_ERROR; - } - /* the counter is only 8=bits, ignore anything in the upper 3 bytes */ - cmdCredits &= 0xFF; - } - - if (cmdCredits) { - address = mboxAddress[ENDPOINT1]; - status = HIFReadWrite(device, address, buffer, length, - HIF_WR_SYNC_BYTE_INC, NULL); - if (status != A_OK) { - AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to send the BMI data to the device\n")); - return A_ERROR; - } - } else { - AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("BMI Communication timeout\n")); - return A_ERROR; - } - - return status; -} - -A_STATUS -bmiBufferReceive(HIF_DEVICE *device, - A_UCHAR *buffer, - A_UINT32 length) -{ - A_STATUS status; - A_UINT32 address; - A_UINT32 timeout; - static A_UINT32 cmdCredits; - A_UINT32 mboxAddress[HTC_MAILBOX_NUM_MAX]; - - HIFConfigureDevice(device, HIF_DEVICE_GET_MBOX_ADDR, - &mboxAddress, sizeof(mboxAddress)); - - cmdCredits = 0; - timeout = BMI_COMMUNICATION_TIMEOUT; - while(timeout-- && !cmdCredits) { - /* Read the counter register to get the command credits */ - address = COUNT_ADDRESS + (HTC_MAILBOX_NUM_MAX + ENDPOINT1) * 1; - /* read the counter using a 4-byte read. Since the counter is NOT auto-decrementing, - * we can read this counter multiple times using a non-incrementing address mode. - * The rationale here is to make all HIF accesses a multiple of 4 bytes */ - status = HIFReadWrite(device, address, (A_UINT8 *)&cmdCredits, sizeof(cmdCredits), - HIF_RD_SYNC_BYTE_FIX, NULL); - if (status != A_OK) { - AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to read the command credit count register\n")); - return A_ERROR; - } - /* we did a 4-byte read to the same count register so mask off upper bytes */ - cmdCredits &= 0xFF; - status = A_ERROR; - } - - if (cmdCredits) { - address = mboxAddress[ENDPOINT1]; - status = HIFReadWrite(device, address, buffer, length, - HIF_RD_SYNC_BYTE_INC, NULL); - if (status != A_OK) { - AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to read the BMI data from the device\n")); - return A_ERROR; - } - } else { - AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Communication timeout\n")); - return A_ERROR; - } - - return status; -} diff --git a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/bmi/bmi_internal.h b/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/bmi/bmi_internal.h deleted file mode 100644 index 1e213540c..000000000 --- a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/bmi/bmi_internal.h +++ /dev/null @@ -1,45 +0,0 @@ -#ifndef BMI_INTERNAL_H -#define BMI_INTERNAL_H -/* - * - * Copyright (c) 2004-2007 Atheros Communications Inc. - * All rights reserved. - * - * - * 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; - * - * Software distributed under the License is distributed on an "AS - * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or - * implied. See the License for the specific language governing - * rights and limitations under the License. - * - * - * - */ - -#include "a_config.h" -#include "athdefs.h" -#include "a_types.h" -#include "a_osapi.h" -#include "a_debug.h" -#include "AR6Khwreg.h" -#include "bmi_msg.h" - -#define BMI_COMMUNICATION_TIMEOUT 100000 - -/* ------ Global Variable Declarations ------- */ -A_BOOL bmiDone; - -A_STATUS -bmiBufferSend(HIF_DEVICE *device, - A_UCHAR *buffer, - A_UINT32 length); - -A_STATUS -bmiBufferReceive(HIF_DEVICE *device, - A_UCHAR *buffer, - A_UINT32 length); - -#endif diff --git a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/hif/hif.c b/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/hif/hif.c deleted file mode 100644 index d04486c35..000000000 --- a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/hif/hif.c +++ /dev/null @@ -1,824 +0,0 @@ -/* - * @file: hif.c - * - * @abstract: HIF layer reference implementation for Atheros SDIO stack - * - * @notice: Copyright (c) 2004-2006 Atheros Communications Inc. - * - * - * 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; - * - * Software distributed under the License is distributed on an "AS - * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or - * implied. See the License for the specific language governing - * rights and limitations under the License. - * - * - * - */ - -#include "hif_internal.h" - -/* ------ Static Variables ------ */ - -/* ------ Global Variable Declarations ------- */ -SD_PNP_INFO Ids[] = { - { - .SDIO_ManufacturerID = MANUFACTURER_ID_AR6001_BASE | 0xB, - .SDIO_ManufacturerCode = MANUFACTURER_CODE, - .SDIO_FunctionClass = FUNCTION_CLASS, - .SDIO_FunctionNo = 1 - }, - { - .SDIO_ManufacturerID = MANUFACTURER_ID_AR6001_BASE | 0xA, - .SDIO_ManufacturerCode = MANUFACTURER_CODE, - .SDIO_FunctionClass = FUNCTION_CLASS, - .SDIO_FunctionNo = 1 - }, - { - .SDIO_ManufacturerID = MANUFACTURER_ID_AR6001_BASE | 0x9, - .SDIO_ManufacturerCode = MANUFACTURER_CODE, - .SDIO_FunctionClass = FUNCTION_CLASS, - .SDIO_FunctionNo = 1 - }, - { - .SDIO_ManufacturerID = MANUFACTURER_ID_AR6001_BASE | 0x8, - .SDIO_ManufacturerCode = MANUFACTURER_CODE, - .SDIO_FunctionClass = FUNCTION_CLASS, - .SDIO_FunctionNo = 1 - }, - { - .SDIO_ManufacturerID = MANUFACTURER_ID_AR6002_BASE | 0x0, - .SDIO_ManufacturerCode = MANUFACTURER_CODE, - .SDIO_FunctionClass = FUNCTION_CLASS, - .SDIO_FunctionNo = 1 - }, - { - .SDIO_ManufacturerID = MANUFACTURER_ID_AR6002_BASE | 0x1, - .SDIO_ManufacturerCode = MANUFACTURER_CODE, - .SDIO_FunctionClass = FUNCTION_CLASS, - .SDIO_FunctionNo = 1 - }, - { - } //list is null termintaed -}; - -TARGET_FUNCTION_CONTEXT FunctionContext = { - .function.Version = CT_SDIO_STACK_VERSION_CODE, - .function.pName = "sdio_wlan", - .function.MaxDevices = 1, - .function.NumDevices = 0, - .function.pIds = Ids, - .function.pProbe = hifDeviceInserted, - .function.pRemove = hifDeviceRemoved, - .function.pSuspend = NULL, - .function.pResume = NULL, - .function.pWake = NULL, - .function.pContext = &FunctionContext, -}; - -HIF_DEVICE hifDevice[HIF_MAX_DEVICES]; -HTC_CALLBACKS htcCallbacks; -BUS_REQUEST busRequest[BUS_REQUEST_MAX_NUM]; -static BUS_REQUEST *s_busRequestFreeQueue = NULL; -OS_CRITICALSECTION lock; -extern A_UINT32 onebitmode; -extern A_UINT32 busspeedlow; - -#ifdef DEBUG -extern A_UINT32 debughif; -#define ATH_DEBUG_ERROR 1 -#define ATH_DEBUG_WARN 2 -#define ATH_DEBUG_TRACE 3 -#define _AR_DEBUG_PRINTX_ARG(arg...) arg -#define AR_DEBUG_PRINTF(lvl, args)\ - {if (lvl <= debughif)\ - A_PRINTF(KERN_ALERT _AR_DEBUG_PRINTX_ARG args);\ - } -#else -#define AR_DEBUG_PRINTF(lvl, args) -#endif - -static BUS_REQUEST *hifAllocateBusRequest(void); -static void hifFreeBusRequest(BUS_REQUEST *busrequest); -static THREAD_RETURN insert_helper_func(POSKERNEL_HELPER pHelper); -static void ResetAllCards(void); - -/* ------ Functions ------ */ -int HIFInit(HTC_CALLBACKS *callbacks) -{ - SDIO_STATUS status; - DBG_ASSERT(callbacks != NULL); - - /* Store the callback and event handlers */ - htcCallbacks.deviceInsertedHandler = callbacks->deviceInsertedHandler; - htcCallbacks.deviceRemovedHandler = callbacks->deviceRemovedHandler; - htcCallbacks.deviceSuspendHandler = callbacks->deviceSuspendHandler; - htcCallbacks.deviceResumeHandler = callbacks->deviceResumeHandler; - htcCallbacks.deviceWakeupHandler = callbacks->deviceWakeupHandler; - htcCallbacks.rwCompletionHandler = callbacks->rwCompletionHandler; - htcCallbacks.dsrHandler = callbacks->dsrHandler; - - CriticalSectionInit(&lock); - - /* Register with bus driver core */ - status = SDIO_RegisterFunction(&FunctionContext.function); - DBG_ASSERT(SDIO_SUCCESS(status)); - - return(0); -} - -A_STATUS -HIFReadWrite(HIF_DEVICE *device, - A_UINT32 address, - A_UCHAR *buffer, - A_UINT32 length, - A_UINT32 request, - void *context) -{ - A_UINT8 rw; - A_UINT8 mode; - A_UINT8 funcNo; - A_UINT8 opcode; - A_UINT16 count; - SDREQUEST *sdrequest; - SDIO_STATUS sdiostatus; - BUS_REQUEST *busrequest; - A_STATUS status = A_OK; - - DBG_ASSERT(device != NULL); - DBG_ASSERT(device->handle != NULL); - - AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("Device: %p\n", device)); - - do { - busrequest = hifAllocateBusRequest(); - if (busrequest == NULL) { - AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("HIF Unable to allocate bus request\n")); - status = A_NO_RESOURCE; - break; - } - - sdrequest = busrequest->request; - busrequest->context = context; - - sdrequest->pDataBuffer = buffer; - if (request & HIF_SYNCHRONOUS) { - sdrequest->Flags = SDREQ_FLAGS_RESP_SDIO_R5 | SDREQ_FLAGS_DATA_TRANS; - sdrequest->pCompleteContext = NULL; - sdrequest->pCompletion = NULL; - AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("Execution mode: Synchronous\n")); - } else if (request & HIF_ASYNCHRONOUS) { - sdrequest->Flags = SDREQ_FLAGS_RESP_SDIO_R5 | SDREQ_FLAGS_DATA_TRANS | - SDREQ_FLAGS_TRANS_ASYNC; - sdrequest->pCompleteContext = busrequest; - sdrequest->pCompletion = hifRWCompletionHandler; - AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("Execution mode: Asynchronous\n")); - } else { - AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, - ("Invalid execution mode: 0x%08x\n", request)); - status = A_EINVAL; - break; - } - - if (request & HIF_EXTENDED_IO) { - AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("Command type: CMD53\n")); - sdrequest->Command = CMD53; - } else { - AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, - ("Invalid command type: 0x%08x\n", request)); - status = A_EINVAL; - break; - } - - if (request & HIF_BLOCK_BASIS) { - mode = CMD53_BLOCK_BASIS; - sdrequest->BlockLen = HIF_MBOX_BLOCK_SIZE; - sdrequest->BlockCount = length / HIF_MBOX_BLOCK_SIZE; - count = sdrequest->BlockCount; - AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, - ("Block mode (BlockLen: %d, BlockCount: %d)\n", - sdrequest->BlockLen, sdrequest->BlockCount)); - } else if (request & HIF_BYTE_BASIS) { - mode = CMD53_BYTE_BASIS; - sdrequest->BlockLen = length; - sdrequest->BlockCount = 1; - count = sdrequest->BlockLen; - AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, - ("Byte mode (BlockLen: %d, BlockCount: %d)\n", - sdrequest->BlockLen, sdrequest->BlockCount)); - } else { - AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, - ("Invalid data mode: 0x%08x\n", request)); - status = A_EINVAL; - break; - } - -#if 0 - /* useful for checking register accesses */ - if (length & 0x3) { - A_PRINTF(KERN_ALERT"HIF (%s) is not a multiple of 4 bytes, addr:0x%X, len:%d\n", - request & HIF_WRITE ? "write":"read", address, length); - } -#endif - - if ((address >= HIF_MBOX_START_ADDR(0)) && - (address <= HIF_MBOX_END_ADDR(3))) - { - - DBG_ASSERT(length <= HIF_MBOX_WIDTH); - - /* - * Mailbox write. Adjust the address so that the last byte - * falls on the EOM address. - */ - address += (HIF_MBOX_WIDTH - length); - } - - - - if (request & HIF_WRITE) { - rw = CMD53_WRITE; - sdrequest->Flags |= SDREQ_FLAGS_DATA_WRITE; - AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("Direction: Write\n")); - } else if (request & HIF_READ) { - rw = CMD53_READ; - AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("Direction: Read\n")); - } else { - AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, - ("Invalid direction: 0x%08x\n", request)); - status = A_EINVAL; - break; - } - - if (request & HIF_FIXED_ADDRESS) { - opcode = CMD53_FIXED_ADDRESS; - AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("Address mode: Fixed\n")); - } else if (request & HIF_INCREMENTAL_ADDRESS) { - opcode = CMD53_INCR_ADDRESS; - AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("Address mode: Incremental\n")); - } else { - AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, - ("Invalid address mode: 0x%08x\n", request)); - status = A_EINVAL; - break; - } - - funcNo = SDDEVICE_GET_SDIO_FUNCNO(device->handle); - AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("Function number: %d\n", funcNo)); - SDIO_SET_CMD53_ARG(sdrequest->Argument, rw, funcNo, - mode, opcode, address, count); - - /* Send the command out */ - sdiostatus = SDDEVICE_CALL_REQUEST_FUNC(device->handle, sdrequest); - - if (!SDIO_SUCCESS(sdiostatus)) { - status = A_ERROR; - } - - } while (FALSE); - - if (A_FAILED(status) || (request & HIF_SYNCHRONOUS)) { - if (busrequest != NULL) { - hifFreeBusRequest(busrequest); - } - } - - if (A_FAILED(status) && (request & HIF_ASYNCHRONOUS)) { - /* call back async handler on failure */ - htcCallbacks.rwCompletionHandler(context, status); - } - - return status; -} - -A_STATUS -HIFConfigureDevice(HIF_DEVICE *device, HIF_DEVICE_CONFIG_OPCODE opcode, - void *config, A_UINT32 configLen) -{ - A_UINT32 count; - - switch(opcode) { - case HIF_DEVICE_GET_MBOX_BLOCK_SIZE: - ((A_UINT32 *)config)[0] = HIF_MBOX0_BLOCK_SIZE; - ((A_UINT32 *)config)[1] = HIF_MBOX1_BLOCK_SIZE; - ((A_UINT32 *)config)[2] = HIF_MBOX2_BLOCK_SIZE; - ((A_UINT32 *)config)[3] = HIF_MBOX3_BLOCK_SIZE; - break; - - case HIF_DEVICE_GET_MBOX_ADDR: - for (count = 0; count < 4; count ++) { - ((A_UINT32 *)config)[count] = HIF_MBOX_START_ADDR(count); - } - break; - case HIF_DEVICE_GET_IRQ_PROC_MODE: - /* the SDIO stack allows the interrupts to be processed either way, ASYNC or SYNC */ - *((HIF_DEVICE_IRQ_PROCESSING_MODE *)config) = HIF_DEVICE_IRQ_ASYNC_SYNC; - break; - default: - AR_DEBUG_PRINTF(ATH_DEBUG_WARN, - ("Unsupported configuration opcode: %d\n", opcode)); - return A_ERROR; - } - - return A_OK; -} - -void -HIFShutDownDevice(HIF_DEVICE *device) -{ - A_UINT8 data; - A_UINT32 count; - SDIO_STATUS status; - SDCONFIG_BUS_MODE_DATA busSettings; - SDCONFIG_FUNC_ENABLE_DISABLE_DATA fData; - - if (device != NULL) { - DBG_ASSERT(device->handle != NULL); - - /* Remove the allocated current if any */ - status = SDLIB_IssueConfig(device->handle, - SDCONFIG_FUNC_FREE_SLOT_CURRENT, NULL, 0); - DBG_ASSERT(SDIO_SUCCESS(status)); - - /* Disable the card */ - fData.EnableFlags = SDCONFIG_DISABLE_FUNC; - fData.TimeOut = 1; - status = SDLIB_IssueConfig(device->handle, SDCONFIG_FUNC_ENABLE_DISABLE, - &fData, sizeof(fData)); - DBG_ASSERT(SDIO_SUCCESS(status)); - - /* Perform a soft I/O reset */ - data = SDIO_IO_RESET; - status = SDLIB_IssueCMD52(device->handle, 0, SDIO_IO_ABORT_REG, - &data, 1, 1); - DBG_ASSERT(SDIO_SUCCESS(status)); - - /* - * WAR - Codetelligence driver does not seem to shutdown correctly in 1 - * bit mode. By default it configures the HC in the 4 bit. Its later in - * our driver that we switch to 1 bit mode. If we try to shutdown, the - * driver hangs so we revert to 4 bit mode, to be transparent to the - * underlying bus driver. - */ - if (onebitmode) { - ZERO_OBJECT(busSettings); - busSettings.BusModeFlags = SDDEVICE_GET_BUSMODE_FLAGS(device->handle); - SDCONFIG_SET_BUS_WIDTH(busSettings.BusModeFlags, - SDCONFIG_BUS_WIDTH_4_BIT); - - /* Issue config request to change the bus width to 4 bit */ - status = SDLIB_IssueConfig(device->handle, SDCONFIG_BUS_MODE_CTRL, - &busSettings, - sizeof(SDCONFIG_BUS_MODE_DATA)); - DBG_ASSERT(SDIO_SUCCESS(status)); - } - - /* Free the bus requests */ - for (count = 0; count < BUS_REQUEST_MAX_NUM; count ++) { - SDDeviceFreeRequest(device->handle, busRequest[count].request); - } - /* Clean up the queue */ - s_busRequestFreeQueue = NULL; - } else { - /* since we are unloading the driver anyways, reset all cards in case the SDIO card - * is externally powered and we are unloading the SDIO stack. This avoids the problem when - * the SDIO stack is reloaded and attempts are made to re-enumerate a card that is already - * enumerated */ - ResetAllCards(); - /* Unregister with bus driver core */ - AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, - ("Unregistering with the bus driver\n")); - status = SDIO_UnregisterFunction(&FunctionContext.function); - DBG_ASSERT(SDIO_SUCCESS(status)); - } -} - -void -hifRWCompletionHandler(SDREQUEST *request) -{ - A_STATUS status; - void *context; - BUS_REQUEST *busrequest; - - if (SDIO_SUCCESS(request->Status)) { - status = A_OK; - } else { - status = A_ERROR; - } - - DBG_ASSERT(status == A_OK); - busrequest = (BUS_REQUEST *) request->pCompleteContext; - context = (void *) busrequest->context; - /* free the request before calling the callback, in case the - * callback submits another request, this guarantees that - * there is at least 1 free request available everytime the callback - * is invoked */ - hifFreeBusRequest(busrequest); - htcCallbacks.rwCompletionHandler(context, status); -} - -void -hifIRQHandler(void *context) -{ - A_STATUS status; - HIF_DEVICE *device; - - device = (HIF_DEVICE *)context; - AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("Device: %p\n", device)); - status = htcCallbacks.dsrHandler(device->htc_handle); - DBG_ASSERT(status == A_OK); -} - -BOOL -hifDeviceInserted(SDFUNCTION *function, SDDEVICE *handle) -{ - BOOL enabled; - A_UINT8 data; - A_UINT32 count; - HIF_DEVICE *device; - SDIO_STATUS status; - A_UINT16 maxBlocks; - A_UINT16 maxBlockSize; - SDCONFIG_BUS_MODE_DATA busSettings; - SDCONFIG_FUNC_ENABLE_DISABLE_DATA fData; - TARGET_FUNCTION_CONTEXT *functionContext; - SDCONFIG_FUNC_SLOT_CURRENT_DATA slotCurrent; - SD_BUSCLOCK_RATE currentBusClock; - - DBG_ASSERT(function != NULL); - DBG_ASSERT(handle != NULL); - - device = addHifDevice(handle); - AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("Device: %p\n", device)); - functionContext = (TARGET_FUNCTION_CONTEXT *)function->pContext; - - /* - * Issue commands to get the manufacturer ID and stuff and compare it - * against the rev Id derived from the ID registered during the - * initialization process. Report the device only in the case there - * is a match. In the case od SDIO, the bus driver has already queried - * these details so we just need to use their data structures to get the - * relevant values. Infact, the driver has already matched it against - * the Ids that we registered with it so we dont need to the step here. - */ - - /* Configure the SDIO Bus Width */ - if (onebitmode) { - data = SDIO_BUS_WIDTH_1_BIT; - status = SDLIB_IssueCMD52(handle, 0, SDIO_BUS_IF_REG, &data, 1, 1); - if (!SDIO_SUCCESS(status)) { - AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, - ("Unable to set the bus width to 1 bit\n")); - return FALSE; - } - } - - /* Get current bus flags */ - ZERO_OBJECT(busSettings); - - busSettings.BusModeFlags = SDDEVICE_GET_BUSMODE_FLAGS(handle); - if (onebitmode) { - SDCONFIG_SET_BUS_WIDTH(busSettings.BusModeFlags, - SDCONFIG_BUS_WIDTH_1_BIT); - } - - /* get the current operating clock, the bus driver sets us up based - * on what our CIS reports and what the host controller can handle - * we can use this to determine whether we want to drop our clock rate - * down */ - currentBusClock = SDDEVICE_GET_OPER_CLOCK(handle); - busSettings.ClockRate = currentBusClock; - - AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, - ("HIF currently running at: %d \n",currentBusClock)); - - /* see if HIF wants to run at a lower clock speed, we may already be - * at that lower clock speed */ - if (currentBusClock > (SDIO_CLOCK_FREQUENCY_DEFAULT >> busspeedlow)) { - busSettings.ClockRate = SDIO_CLOCK_FREQUENCY_DEFAULT >> busspeedlow; - AR_DEBUG_PRINTF(ATH_DEBUG_WARN, - ("HIF overriding clock to %d \n",busSettings.ClockRate)); - } - - /* Issue config request to override clock rate */ - status = SDLIB_IssueConfig(handle, SDCONFIG_FUNC_CHANGE_BUS_MODE, &busSettings, - sizeof(SDCONFIG_BUS_MODE_DATA)); - if (!SDIO_SUCCESS(status)) { - AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, - ("Unable to configure the host clock\n")); - return FALSE; - } else { - AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, - ("Configured clock: %d, Maximum clock: %d\n", - busSettings.ActualClockRate, - SDDEVICE_GET_MAX_CLOCK(handle))); - } - - /* - * Check if the target supports block mode. This result of this check - * can be used to implement the HIFReadWrite API. - */ - if (SDDEVICE_GET_SDIO_FUNC_MAXBLKSIZE(handle)) { - /* Limit block size to operational block limit or card function - capability */ - maxBlockSize = min(SDDEVICE_GET_OPER_BLOCK_LEN(handle), - SDDEVICE_GET_SDIO_FUNC_MAXBLKSIZE(handle)); - - /* check if the card support multi-block transfers */ - if (!(SDDEVICE_GET_SDIOCARD_CAPS(handle) & SDIO_CAPS_MULTI_BLOCK)) { - AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("Byte basis only\n")); - - /* Limit block size to max byte basis */ - maxBlockSize = min(maxBlockSize, - (A_UINT16)SDIO_MAX_LENGTH_BYTE_BASIS); - maxBlocks = 1; - } else { - AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("Multi-block capable\n")); - maxBlocks = SDDEVICE_GET_OPER_BLOCKS(handle); - status = SDLIB_SetFunctionBlockSize(handle, HIF_MBOX_BLOCK_SIZE); - if (!SDIO_SUCCESS(status)) { - AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, - ("Failed to set block size. Err:%d\n", status)); - return FALSE; - } - } - - AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, - ("Bytes Per Block: %d bytes, Block Count:%d \n", - maxBlockSize, maxBlocks)); - } else { - AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, - ("Function does not support Block Mode!\n")); - return FALSE; - } - - /* Allocate the slot current */ - status = SDLIB_GetDefaultOpCurrent(handle, &slotCurrent.SlotCurrent); - if (SDIO_SUCCESS(status)) { - AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("Allocating Slot current: %d mA\n", - slotCurrent.SlotCurrent)); - status = SDLIB_IssueConfig(handle, SDCONFIG_FUNC_ALLOC_SLOT_CURRENT, - &slotCurrent, sizeof(slotCurrent)); - if (!SDIO_SUCCESS(status)) { - AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, - ("Failed to allocate slot current %d\n", status)); - return FALSE; - } - } - - /* Enable the dragon function */ - count = 0; - enabled = FALSE; - fData.TimeOut = 1; - fData.EnableFlags = SDCONFIG_ENABLE_FUNC; - while ((count++ < SDWLAN_ENABLE_DISABLE_TIMEOUT) && !enabled) - { - /* Enable dragon */ - status = SDLIB_IssueConfig(handle, SDCONFIG_FUNC_ENABLE_DISABLE, - &fData, sizeof(fData)); - if (!SDIO_SUCCESS(status)) { - AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, - ("Attempting to enable the card again\n")); - continue; - } - - /* Mark the status as enabled */ - enabled = TRUE; - } - - /* Check if we were succesful in enabling the target */ - if (!enabled) { - AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, - ("Failed to communicate with the target\n")); - return FALSE; - } - - /* Allocate the bus requests to be used later */ - A_MEMZERO(busRequest, sizeof(busRequest)); - for (count = 0; count < BUS_REQUEST_MAX_NUM; count ++) { - if ((busRequest[count].request = SDDeviceAllocRequest(handle)) == NULL){ - AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("Unable to allocate memory\n")); - /* TODO: Free the memory that has already been allocated */ - return FALSE; - } - hifFreeBusRequest(&busRequest[count]); - - AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, - ("0x%08x = busRequest[%d].request = 0x%08x\n", - (unsigned int) &busRequest[count], count, - (unsigned int) busRequest[count].request)); - } - - /* Schedule a worker to handle device inserted, this is a temporary workaround - * to fix a deadlock if the device fails to intialize in the insertion handler - * The failure causes the instance to shutdown the HIF layer and unregister the - * function driver within the busdriver probe context which can deadlock - * - * NOTE: we cannot use the default work queue because that would block - * SD bus request processing for all synchronous I/O. We must use a kernel - * thread that is creating using the helper library. - * */ - - if (SDIO_SUCCESS(SDLIB_OSCreateHelper(&device->insert_helper, - insert_helper_func, - device))) { - device->helper_started = TRUE; - } - - return TRUE; -} - -static THREAD_RETURN insert_helper_func(POSKERNEL_HELPER pHelper) -{ - - /* - * Adding a wait of around a second before we issue the very first - * command to dragon. During the process of loading/unloading the - * driver repeatedly it was observed that we get a data timeout - * while accessing function 1 registers in the chip. The theory at - * this point is that some initialization delay in dragon is - * causing the SDIO state in dragon core to be not ready even after - * the ready bit indicates that function 1 is ready. Accomodating - * for this behavior by adding some delay in the driver before it - * issues the first command after switching on dragon. Need to - * investigate this a bit more - TODO - */ - - A_MDELAY(1000); - /* Inform HTC */ - if ((htcCallbacks.deviceInsertedHandler(SD_GET_OS_HELPER_CONTEXT(pHelper))) != A_OK) { - AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("Device rejected\n")); - } - - return 0; -} - -void -HIFAckInterrupt(HIF_DEVICE *device) -{ - SDIO_STATUS status; - DBG_ASSERT(device != NULL); - DBG_ASSERT(device->handle != NULL); - - /* Acknowledge our function IRQ */ - status = SDLIB_IssueConfig(device->handle, SDCONFIG_FUNC_ACK_IRQ, - NULL, 0); - DBG_ASSERT(SDIO_SUCCESS(status)); -} - -void -HIFUnMaskInterrupt(HIF_DEVICE *device) -{ - SDIO_STATUS status; - - DBG_ASSERT(device != NULL); - DBG_ASSERT(device->handle != NULL); - - /* Register the IRQ Handler */ - SDDEVICE_SET_IRQ_HANDLER(device->handle, hifIRQHandler, device); - - /* Unmask our function IRQ */ - status = SDLIB_IssueConfig(device->handle, SDCONFIG_FUNC_UNMASK_IRQ, - NULL, 0); - DBG_ASSERT(SDIO_SUCCESS(status)); -} - -void HIFMaskInterrupt(HIF_DEVICE *device) -{ - SDIO_STATUS status; - DBG_ASSERT(device != NULL); - DBG_ASSERT(device->handle != NULL); - - /* Mask our function IRQ */ - status = SDLIB_IssueConfig(device->handle, SDCONFIG_FUNC_MASK_IRQ, - NULL, 0); - DBG_ASSERT(SDIO_SUCCESS(status)); - - /* Unregister the IRQ Handler */ - SDDEVICE_SET_IRQ_HANDLER(device->handle, NULL, NULL); -} - -static BUS_REQUEST *hifAllocateBusRequest(void) -{ - BUS_REQUEST *busrequest; - - /* Acquire lock */ - CriticalSectionAcquire(&lock); - - /* Remove first in list */ - if((busrequest = s_busRequestFreeQueue) != NULL) - { - s_busRequestFreeQueue = busrequest->next; - } - - /* Release lock */ - CriticalSectionRelease(&lock); - - return busrequest; -} - -static void -hifFreeBusRequest(BUS_REQUEST *busrequest) -{ - DBG_ASSERT(busrequest != NULL); - - /* Acquire lock */ - CriticalSectionAcquire(&lock); - - /* Insert first in list */ - busrequest->next = s_busRequestFreeQueue; - s_busRequestFreeQueue = busrequest; - - /* Release lock */ - CriticalSectionRelease(&lock); -} - -void -hifDeviceRemoved(SDFUNCTION *function, SDDEVICE *handle) -{ - A_STATUS status; - HIF_DEVICE *device; - DBG_ASSERT(function != NULL); - DBG_ASSERT(handle != NULL); - - device = getHifDevice(handle); - status = htcCallbacks.deviceRemovedHandler(device->htc_handle, A_OK); - - /* cleanup the helper thread */ - if (device->helper_started) { - SDLIB_OSDeleteHelper(&device->insert_helper); - device->helper_started = FALSE; - } - - delHifDevice(handle); - DBG_ASSERT(status == A_OK); -} - -HIF_DEVICE * -addHifDevice(SDDEVICE *handle) -{ - DBG_ASSERT(handle != NULL); - hifDevice[0].handle = handle; - return &hifDevice[0]; -} - -HIF_DEVICE * -getHifDevice(SDDEVICE *handle) -{ - DBG_ASSERT(handle != NULL); - return &hifDevice[0]; -} - -void -delHifDevice(SDDEVICE *handle) -{ - DBG_ASSERT(handle != NULL); - hifDevice[0].handle = NULL; -} - -struct device* -HIFGetOSDevice(HIF_DEVICE *device) -{ - return &device->handle->Device->dev; -} - -static void ResetAllCards(void) -{ - UINT8 data; - SDIO_STATUS status; - int i; - - data = SDIO_IO_RESET; - - /* set the I/O CARD reset bit: - * NOTE: we are exploiting a "feature" of the SDIO core that resets the core when you - * set the RES bit in the SDIO_IO_ABORT register. This bit however "normally" resets the - * I/O functions leaving the SDIO core in the same state (as per SDIO spec). - * In this design, this reset can be used to reset the SDIO core itself */ - for (i = 0; i < HIF_MAX_DEVICES; i++) { - if (hifDevice[i].handle != NULL) { - AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, - ("Issuing I/O Card reset for instance: %d \n",i)); - /* set the I/O Card reset bit */ - status = SDLIB_IssueCMD52(hifDevice[i].handle, - 0, /* function 0 space */ - SDIO_IO_ABORT_REG, - &data, - 1, /* 1 byte */ - TRUE); /* write */ - } - } - -} - -void HIFSetHandle(void *hif_handle, void *handle) -{ - HIF_DEVICE *device = (HIF_DEVICE *) hif_handle; - - device->htc_handle = handle; - - return; -} diff --git a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/hif/hif2.c b/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/hif/hif2.c deleted file mode 100644 index 386d96e66..000000000 --- a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/hif/hif2.c +++ /dev/null @@ -1,768 +0,0 @@ -/* - * hif2.c - HIF layer re-implementation for the Linux SDIO stack - * - * Copyright (C) 2008, 2009 by OpenMoko, Inc. - * Written by Werner Almesberger - * All Rights Reserved - * - * 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; - * - * Based on: - * - * @abstract: HIF layer reference implementation for Atheros SDIO stack - * @notice: Copyright (c) 2004-2006 Atheros Communications Inc. - */ - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "athdefs.h" -#include "a_types.h" -#include "hif.h" - - -/* @@@ Hack - this wants cleaning up */ - -#ifdef CONFIG_MACH_NEO1973_GTA02 - -#include - -#else /* CONFIG_MACH_NEO1973_GTA02 */ - -#define gta02_wlan_query_rfkill_lock() 1 -#define gta02_wlan_set_rfkill_cb(cb, hif) ((void) cb) -#define gta02_wlan_query_rfkill_unlock() -#define gta02_wlan_clear_rfkill_cb() - -#endif /* !CONFIG_MACH_NEO1973_GTA02 */ - - -/* - * KNOWN BUGS: - * - * - HIF_DEVICE_IRQ_ASYNC_SYNC doesn't work yet (gets MMC errors) - * - latency can reach hundreds of ms, probably because of scheduling delays - * - packets go through about three queues before finally hitting the network - */ - -/* - * Differences from Atheros' HIFs: - * - * - synchronous and asynchronous requests may get reordered with respect to - * each other, e.g., if HIFReadWrite returns for an asynchronous request and - * then HIFReadWrite is called for a synchronous request, the synchronous - * request may be executed before the asynchronous request. - * - * - request queue locking seems unnecessarily complex in the Atheros HIFs. - * - * - Atheros mask interrupts by calling sdio_claim_irq/sdio_release_irq, which - * can cause quite a bit of overhead. This HIF has its own light-weight - * interrupt masking. - * - * - Atheros call deviceInsertedHandler from a thread spawned off the probe or - * device insertion function. The original explanation for the Atheros SDIO - * stack said that this is done because a delay is needed to let the chip - * complete initialization. There is indeed a one second delay in the thread. - * - * The Atheros Linux SDIO HIF removes the delay and only retains the thread. - * Experimentally removing the thread didn't show any conflicts, so let's get - * rid of it for good. - * - * - The Atheros SDIO stack with Samuel's driver sets SDIO_CCCR_POWER in - * SDIO_POWER_EMPC. Atheros' Linux SDIO code apparently doesn't. We don't - * either, and this seems to work fine. - * @@@ Need to check this with Atheros. - */ - - -#define MBOXES 4 - -#define HIF_MBOX_BLOCK_SIZE 128 -#define HIF_MBOX_BASE_ADDR 0x800 -#define HIF_MBOX_WIDTH 0x800 -#define HIF_MBOX_START_ADDR(mbox) \ - (HIF_MBOX_BASE_ADDR+(mbox)*HIF_MBOX_WIDTH) - - -struct hif_device { - void *htc_handle; - struct sdio_func *func; - - /* - * @@@ our sweet little bit of bogosity - the mechanism that lets us - * use the SDIO stack from softirqs. This really wants to use skbs. - */ - struct list_head queue; - spinlock_t queue_lock; - struct task_struct *io_task; - wait_queue_head_t wait; - - /* - * activate_lock protects "active" and the activation/deactivation - * process itself. - * - * Relation to other locks: The SDIO function can be claimed while - * activate_lock is being held, but trying to acquire activate_lock - * while having ownership of the SDIO function could cause a deadlock. - */ - int active; - struct mutex activate_lock; -}; - -struct hif_request { - struct list_head list; - struct sdio_func *func; - int (*read)(struct sdio_func *func, - void *dst, unsigned int addr, int count); - int (*write)(struct sdio_func *func, - unsigned int addr, void *src, int count); - void *buf; - unsigned long addr; - int len; - A_STATUS (*completion)(void *context, A_STATUS status); - void *context; -}; - - -static HTC_CALLBACKS htcCallbacks; - -/* - * shutdown_lock prevents recursion through HIFShutDownDevice - */ -static DEFINE_MUTEX(shutdown_lock); - - -/* ----- Request processing ------------------------------------------------ */ - - -static A_STATUS process_request(struct hif_request *req) -{ - int ret; - A_STATUS status; - - dev_dbg(&req->func->dev, "process_request(req %p)\n", req); - sdio_claim_host(req->func); - if (req->read) { - ret = req->read(req->func, req->buf, req->addr, req->len); - } else { - ret = req->write(req->func, req->addr, req->buf, req->len); - } - sdio_release_host(req->func); - status = ret ? A_ERROR : A_OK; - if (req->completion) - req->completion(req->context, status); - kfree(req); - return status; -} - - -static void enqueue_request(struct hif_device *hif, struct hif_request *req) -{ - unsigned long flags; - - dev_dbg(&req->func->dev, "enqueue_request(req %p)\n", req); - spin_lock_irqsave(&hif->queue_lock, flags); - list_add_tail(&req->list, &hif->queue); - spin_unlock_irqrestore(&hif->queue_lock, flags); - wake_up(&hif->wait); -} - - -static struct hif_request *dequeue_request(struct hif_device *hif) -{ - struct hif_request *req; - unsigned long flags; - - spin_lock_irqsave(&hif->queue_lock, flags); - if (list_empty(&hif->queue)) - req = NULL; - else { - req = list_first_entry(&hif->queue, - struct hif_request, list); - list_del(&req->list); - } - spin_unlock_irqrestore(&hif->queue_lock, flags); - return req; -} - - -static void wait_queue_empty(struct hif_device *hif) -{ - unsigned long flags; - int empty; - - while (1) { - spin_lock_irqsave(&hif->queue_lock, flags); - empty = list_empty(&hif->queue); - spin_unlock_irqrestore(&hif->queue_lock, flags); - if (empty) - break; - else - yield(); - } -} - - -static int io(void *data) -{ - struct hif_device *hif = data; - struct sched_param param = { .sched_priority = 2 }; - /* one priority level slower than ksdioirqd (which is at 1) */ - DEFINE_WAIT(wait); - struct hif_request *req; - - sched_setscheduler(current, SCHED_FIFO, ¶m); - - while (1) { - while (1) { - /* - * Since we never use signals here, one might think - * that this ought to be TASK_UNINTERRUPTIBLE. However, - * such a task would increase the load average and, - * worse, it would trigger the softlockup check. - */ - prepare_to_wait(&hif->wait, &wait, TASK_INTERRUPTIBLE); - if (kthread_should_stop()) { - finish_wait(&hif->wait, &wait); - return 0; - } - req = dequeue_request(hif); - if (req) - break; - schedule(); - } - finish_wait(&hif->wait, &wait); - - (void) process_request(req); - } - return 0; -} - - -A_STATUS HIFReadWrite(HIF_DEVICE *hif, A_UINT32 address, A_UCHAR *buffer, - A_UINT32 length, A_UINT32 request, void *context) -{ - struct device *dev = HIFGetOSDevice(hif); - struct hif_request *req; - - dev_dbg(dev, "HIFReadWrite(device %p, address 0x%x, buffer %p, " - "length %d, request 0x%x, context %p)\n", - hif, address, buffer, length, request, context); - - BUG_ON(!(request & (HIF_SYNCHRONOUS | HIF_ASYNCHRONOUS))); - BUG_ON(!(request & (HIF_BYTE_BASIS | HIF_BLOCK_BASIS))); - BUG_ON(!(request & (HIF_READ | HIF_WRITE))); - BUG_ON(!(request & HIF_EXTENDED_IO)); - - if (address >= HIF_MBOX_START_ADDR(0) && - address < HIF_MBOX_START_ADDR(MBOXES+1)) { - BUG_ON(length > HIF_MBOX_WIDTH); - /* Adjust the address so that the last byte falls on the EOM - address. */ - address += HIF_MBOX_WIDTH-length; - } - - req = kzalloc(sizeof(*req), GFP_ATOMIC); - if (!req) { - if (request & HIF_ASYNCHRONOUS) - htcCallbacks.rwCompletionHandler(context, A_ERROR); - return A_ERROR; - } - - req->func = hif->func; - req->addr = address; - req->buf = buffer; - req->len = length; - - if (request & HIF_READ) { - if (request & HIF_FIXED_ADDRESS) - req->read = sdio_readsb; - else - req->read = sdio_memcpy_fromio; - } else { - if (request & HIF_FIXED_ADDRESS) - req->write = sdio_writesb; - else - req->write = sdio_memcpy_toio; - } - - if (!(request & HIF_ASYNCHRONOUS)) - return process_request(req); - - req->completion = htcCallbacks.rwCompletionHandler; - req->context = context; - enqueue_request(hif, req); - - return A_OK; -} - - -/* ----- Interrupt handling ------------------------------------------------ */ - -/* - * Volatile ought to be good enough to make gcc do the right thing on S3C24xx. - * No need to use atomic or put barriers, keeping the code more readable. - * - * Warning: this story changes if going SMP/SMT. - */ - -static volatile int masked = 1; -static volatile int pending; -static volatile int in_interrupt; - - -static void ar6000_do_irq(struct sdio_func *func) -{ - HIF_DEVICE *hif = sdio_get_drvdata(func); - struct device *dev = HIFGetOSDevice(hif); - A_STATUS status; - - dev_dbg(dev, "ar6000_do_irq -> %p\n", htcCallbacks.dsrHandler); - - status = htcCallbacks.dsrHandler(hif->htc_handle); - BUG_ON(status != A_OK); -} - - -static void sdio_ar6000_irq(struct sdio_func *func) -{ - HIF_DEVICE *hif = sdio_get_drvdata(func); - struct device *dev = HIFGetOSDevice(hif); - - dev_dbg(dev, "sdio_ar6000_irq\n"); - - in_interrupt = 1; - if (masked) { - in_interrupt = 0; - pending++; - return; - } - /* - * @@@ This is ugly. If we don't drop the lock, we'll deadlock when - * the handler tries to do SDIO. So there are four choices: - * - * 1) Break the call chain by calling the callback from a workqueue. - * Ugh. - * 2) Make process_request aware that we already have the lock. - * 3) Drop the lock. Which is ugly but should be safe as long as we're - * making sure the device doesn't go away. - * 4) Change the AR6k driver such that it only issues asynchronous - * quests when called from an interrupt. - * - * Solution 2) is probably the best for now. Will try it later. - */ - sdio_release_host(func); - ar6000_do_irq(func); - sdio_claim_host(func); - in_interrupt = 0; -} - - -void HIFAckInterrupt(HIF_DEVICE *hif) -{ - struct device *dev = HIFGetOSDevice(hif); - - dev_dbg(dev, "HIFAckInterrupt\n"); - /* do nothing */ -} - - -void HIFUnMaskInterrupt(HIF_DEVICE *hif) -{ - struct device *dev = HIFGetOSDevice(hif); - - dev_dbg(dev, "HIFUnMaskInterrupt\n"); - do { - masked = 1; - if (pending) { - pending = 0; - ar6000_do_irq(hif->func); - /* We may take an interrupt before unmasking and thus - get it pending. In this case, we just loop back. */ - } - masked = 0; - } - while (pending); -} - - -void HIFMaskInterrupt(HIF_DEVICE *hif) -{ - struct device *dev = HIFGetOSDevice(hif); - - dev_dbg(dev, "HIFMaskInterrupt\n"); - /* - * Since sdio_ar6000_irq can also be called from a process context, we - * may conceivably end up racing with it. Thus, we need to wait until - * we can be sure that no concurrent interrupt processing is going on - * before we return. - * - * Note: this may be a bit on the paranoid side - the callers may - * actually be nice enough to disable scheduling. Check later. - */ - masked = 1; - while (in_interrupt) - yield(); -} - - -/* ----- HIF API glue functions -------------------------------------------- */ - - -struct device *HIFGetOSDevice(HIF_DEVICE *hif) -{ - return &hif->func->dev; -} - - -void HIFSetHandle(void *hif_handle, void *handle) -{ - HIF_DEVICE *hif = (HIF_DEVICE *) hif_handle; - - hif->htc_handle = handle; -} - - -/* ----- Device configuration (HIF side) ----------------------------------- */ - - -A_STATUS HIFConfigureDevice(HIF_DEVICE *hif, - HIF_DEVICE_CONFIG_OPCODE opcode, void *config, A_UINT32 configLen) -{ - struct device *dev = HIFGetOSDevice(hif); - HIF_DEVICE_IRQ_PROCESSING_MODE *ipm_cfg = config; - A_UINT32 *mbs_cfg = config; - int i; - - dev_dbg(dev, "HIFConfigureDevice\n"); - - switch (opcode) { - case HIF_DEVICE_GET_MBOX_BLOCK_SIZE: - for (i = 0; i != MBOXES; i++) - mbs_cfg[i] = HIF_MBOX_BLOCK_SIZE; - break; - case HIF_DEVICE_GET_MBOX_ADDR: - for (i = 0; i != MBOXES; i++) - mbs_cfg[i] = HIF_MBOX_START_ADDR(i); - break; - case HIF_DEVICE_GET_IRQ_PROC_MODE: - *ipm_cfg = HIF_DEVICE_IRQ_SYNC_ONLY; -// *ipm_cfg = HIF_DEVICE_IRQ_ASYNC_SYNC; - break; - default: - return A_ERROR; - } - return A_OK; -} - - -/* ----- Device probe and removal (Linux side) ----------------------------- */ - - -static int ar6000_do_activate(struct hif_device *hif) -{ - struct sdio_func *func = hif->func; - struct device *dev = &func->dev; - int ret; - - dev_dbg(dev, "ar6000_do_activate\n"); - - sdio_claim_host(func); - sdio_enable_func(func); - - INIT_LIST_HEAD(&hif->queue); - init_waitqueue_head(&hif->wait); - spin_lock_init(&hif->queue_lock); - - ret = sdio_set_block_size(func, HIF_MBOX_BLOCK_SIZE); - if (ret < 0) { - dev_err(dev, "sdio_set_block_size returns %d\n", ret); - goto out_enabled; - } - ret = sdio_claim_irq(func, sdio_ar6000_irq); - if (ret) { - dev_err(dev, "sdio_claim_irq returns %d\n", ret); - goto out_enabled; - } - /* Set SDIO_BUS_CD_DISABLE in SDIO_CCCR_IF ? */ -#if 0 - sdio_f0_writeb(func, SDIO_CCCR_CAP_E4MI, SDIO_CCCR_CAPS, &ret); - if (ret) { - dev_err(dev, "sdio_f0_writeb(SDIO_CCCR_CAPS) returns %d\n", - ret); - goto out_got_irq; - } -#else - if (0) /* avoid warning */ - goto out_got_irq; -#endif - - sdio_release_host(func); - - hif->io_task = kthread_run(io, hif, "ar6000_io"); - ret = IS_ERR(hif->io_task); - if (ret) { - dev_err(dev, "kthread_run(ar6000_io): %d\n", ret); - goto out_func_ready; - } - - ret = htcCallbacks.deviceInsertedHandler(hif); - if (ret == A_OK) - return 0; - - dev_err(dev, "deviceInsertedHandler: %d\n", ret); - - ret = kthread_stop(hif->io_task); - if (ret) - dev_err(dev, "kthread_stop (ar6000_io): %d\n", ret); - -out_func_ready: - sdio_claim_host(func); - -out_got_irq: - sdio_release_irq(func); - -out_enabled: - sdio_disable_func(func); - sdio_release_host(func); - - return ret; -} - - -static void ar6000_do_deactivate(struct hif_device *hif) -{ - struct sdio_func *func = hif->func; - struct device *dev = &func->dev; - int ret; - - dev_dbg(dev, "ar6000_do_deactivate\n"); - if (!hif->active) - return; - - if (mutex_trylock(&shutdown_lock)) { - /* - * Funny, Atheros' HIF does this call, but this just puts us in - * a recursion through HTCShutDown/HIFShutDown if unloading the - * module. - * - * However, we need it for suspend/resume. See the comment at - * HIFShutDown, below. - */ - ret = htcCallbacks.deviceRemovedHandler(hif->htc_handle, A_OK); - if (ret != A_OK) - dev_err(dev, "deviceRemovedHandler: %d\n", ret); - mutex_unlock(&shutdown_lock); - } - wait_queue_empty(hif); - ret = kthread_stop(hif->io_task); - if (ret) - dev_err(dev, "kthread_stop (ar6000_io): %d\n", ret); - sdio_claim_host(func); - sdio_release_irq(func); - sdio_disable_func(func); - sdio_release_host(func); -} - - -static int ar6000_activate(struct hif_device *hif) -{ - int ret = 0; - - dev_dbg(&hif->func->dev, "ar6000_activate\n"); - mutex_lock(&hif->activate_lock); - if (!hif->active) { - ret = ar6000_do_activate(hif); - if (ret) { - printk(KERN_ERR "%s: Failed to activate %d\n", - __func__, ret); - goto out; - } - hif->active = 1; - } -out: - mutex_unlock(&hif->activate_lock); - return ret; -} - - -static void ar6000_deactivate(struct hif_device *hif) -{ - dev_dbg(&hif->func->dev, "ar6000_deactivate\n"); - mutex_lock(&hif->activate_lock); - if (hif->active) { - ar6000_do_deactivate(hif); - hif->active = 0; - } - mutex_unlock(&hif->activate_lock); -} - - -static int ar6000_rfkill_cb(void *data, int on) -{ - struct hif_device *hif = data; - struct sdio_func *func = hif->func; - struct device *dev = &func->dev; - - dev_dbg(dev, "ar6000_rfkill_cb: on %d\n", on); - if (on) - return ar6000_activate(hif); - ar6000_deactivate(hif); - return 0; -} - - -static int sdio_ar6000_probe(struct sdio_func *func, - const struct sdio_device_id *id) -{ - struct device *dev = &func->dev; - struct hif_device *hif; - int ret = 0; - - dev_dbg(dev, "sdio_ar6000_probe\n"); - BUG_ON(!htcCallbacks.deviceInsertedHandler); - - hif = kzalloc(sizeof(*hif), GFP_KERNEL); - if (!hif) - return -ENOMEM; - - sdio_set_drvdata(func, hif); - hif->func = func; - mutex_init(&hif->activate_lock); - hif->active = 0; - - if (gta02_wlan_query_rfkill_lock()) - ret = ar6000_activate(hif); - if (!ret) { - gta02_wlan_set_rfkill_cb(ar6000_rfkill_cb, hif); - return 0; - } - gta02_wlan_query_rfkill_unlock(); - sdio_set_drvdata(func, NULL); - kfree(hif); - return ret; -} - - -static void sdio_ar6000_remove(struct sdio_func *func) -{ - struct device *dev = &func->dev; - HIF_DEVICE *hif = sdio_get_drvdata(func); - - dev_dbg(dev, "sdio_ar6000_remove\n"); - gta02_wlan_clear_rfkill_cb(); - ar6000_deactivate(hif); - sdio_set_drvdata(func, NULL); - kfree(hif); -} - - -/* ----- Device registration/unregistration (called by HIF) ---------------- */ - - -#define ATHEROS_SDIO_DEVICE(id, offset) \ - SDIO_DEVICE(SDIO_VENDOR_ID_ATHEROS, SDIO_DEVICE_ID_ATHEROS_##id | (offset)) - -static const struct sdio_device_id sdio_ar6000_ids[] = { - { ATHEROS_SDIO_DEVICE(AR6002, 0) }, - { ATHEROS_SDIO_DEVICE(AR6002, 0x1) }, - { ATHEROS_SDIO_DEVICE(AR6001, 0x8) }, - { ATHEROS_SDIO_DEVICE(AR6001, 0x9) }, - { ATHEROS_SDIO_DEVICE(AR6001, 0xa) }, - { ATHEROS_SDIO_DEVICE(AR6001, 0xb) }, - { /* end: all zeroes */ }, -}; - -MODULE_DEVICE_TABLE(sdio, sdio_ar6000_ids); - - -static struct sdio_driver sdio_ar6000_driver = { - .probe = sdio_ar6000_probe, - .remove = sdio_ar6000_remove, - .name = "sdio_ar6000", - .id_table = sdio_ar6000_ids, -}; - - -int HIFInit(HTC_CALLBACKS *callbacks) -{ - int ret; - - BUG_ON(!callbacks); - - printk(KERN_DEBUG "HIFInit\n"); - htcCallbacks = *callbacks; - - ret = sdio_register_driver(&sdio_ar6000_driver); - if (ret) { - printk(KERN_ERR - "sdio_register_driver(sdio_ar6000_driver): %d\n", ret); - return A_ERROR; - } - - return 0; -} - - -/* - * We have four possible call chains here: - * - * System shutdown/reboot: - * - * kernel_restart_prepare ...> device_shutdown ... > s3cmci_shutdown -> - * mmc_remove_host ..> sdio_bus_remove -> sdio_ar6000_remove -> - * ar6000_deactivate -> ar6000_do_deactivate -> - * deviceRemovedHandler (HTCTargetRemovedHandler) -> HIFShutDownDevice - * - * This is roughly the same sequence as suspend, described below. - * - * Module removal: - * - * sys_delete_module -> ar6000_cleanup_module -> HTCShutDown -> - * HIFShutDownDevice -> sdio_unregister_driver ...> sdio_bus_remove -> - * sdio_ar6000_remove -> ar6000_deactivate -> ar6000_do_deactivate - * - * In this case, HIFShutDownDevice must call sdio_unregister_driver to - * notify the driver about its removal. ar6000_do_deactivate must not call - * deviceRemovedHandler, because that would loop back into HIFShutDownDevice. - * - * Suspend: - * - * device_suspend ...> s3cmci_suspend ...> sdio_bus_remove -> - * sdio_ar6000_remove -> ar6000_deactivate -> ar6000_do_deactivate -> - * deviceRemovedHandler (HTCTargetRemovedHandler) -> HIFShutDownDevice - * - * We must call deviceRemovedHandler to inform the ar6k stack that the device - * has been removed. Since HTCTargetRemovedHandler calls back into - * HIFShutDownDevice, we must also prevent the call to - * sdio_unregister_driver, or we'd end up recursing into the SDIO stack, - * eventually deadlocking somewhere. - * - * rfkill: - * - * rfkill_state_store -> rfkill_toggle_radio -> gta02_wlan_toggle_radio -> - * ar6000_rfkill_cb -> ar6000_deactivate -> ar6000_do_deactivate -> - * deviceRemovedHandler (HTCTargetRemovedHandler) -> HIFShutDownDevice - * - * This is similar to suspend - only the entry point changes. - */ - -void HIFShutDownDevice(HIF_DEVICE *hif) -{ - /* Beware, HTCShutDown calls us with hif == NULL ! */ - if (mutex_trylock(&shutdown_lock)) { - sdio_unregister_driver(&sdio_ar6000_driver); - mutex_unlock(&shutdown_lock); - } -} diff --git a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/hif/hif_internal.h b/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/hif/hif_internal.h deleted file mode 100644 index d8fc10132..000000000 --- a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/hif/hif_internal.h +++ /dev/null @@ -1,102 +0,0 @@ -/* - * @file: hif_internal.h - * - * @abstract: internal header file for hif layer - * - * @notice: Copyright (c) 2004-2006 Atheros Communications Inc. - * - * - * 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; - * - * Software distributed under the License is distributed on an "AS - * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or - * implied. See the License for the specific language governing - * rights and limitations under the License. - * - * - * - */ - -#include -#include -#include -#include -#include "a_config.h" -#include "athdefs.h" -#include "a_types.h" -#include "a_osapi.h" -#include "hif.h" - -#define MANUFACTURER_ID_AR6001_BASE 0x100 -#define MANUFACTURER_ID_AR6002_BASE 0x200 -#define FUNCTION_CLASS 0x0 -#define MANUFACTURER_CODE 0x271 - -#define BUS_REQUEST_MAX_NUM 64 - -#define SDIO_CLOCK_FREQUENCY_DEFAULT 25000000 -#define SDWLAN_ENABLE_DISABLE_TIMEOUT 20 -#define FLAGS_CARD_ENAB 0x02 -#define FLAGS_CARD_IRQ_UNMSK 0x04 - -#define HIF_MBOX_BLOCK_SIZE 128 -#define HIF_MBOX_BASE_ADDR 0x800 -#define HIF_MBOX_WIDTH 0x800 -#define HIF_MBOX0_BLOCK_SIZE 1 -#define HIF_MBOX1_BLOCK_SIZE HIF_MBOX_BLOCK_SIZE -#define HIF_MBOX2_BLOCK_SIZE HIF_MBOX_BLOCK_SIZE -#define HIF_MBOX3_BLOCK_SIZE HIF_MBOX_BLOCK_SIZE - -#define HIF_MBOX_START_ADDR(mbox) \ - HIF_MBOX_BASE_ADDR + mbox * HIF_MBOX_WIDTH - -#define HIF_MBOX_END_ADDR(mbox) \ - HIF_MBOX_START_ADDR(mbox) + HIF_MBOX_WIDTH - 1 - -struct hif_device { - SDDEVICE *handle; - void *htc_handle; - OSKERNEL_HELPER insert_helper; - BOOL helper_started; -}; - -typedef struct target_function_context { - SDFUNCTION function; /* function description of the bus driver */ - OS_SEMAPHORE instanceSem; /* instance lock. Unused */ - SDLIST instanceList; /* list of instances. Unused */ -} TARGET_FUNCTION_CONTEXT; - -typedef struct bus_request { - struct bus_request *next; - SDREQUEST *request; - void *context; -} BUS_REQUEST; - -BOOL -hifDeviceInserted(SDFUNCTION *function, SDDEVICE *device); - -void -hifDeviceRemoved(SDFUNCTION *function, SDDEVICE *device); - -SDREQUEST * -hifAllocateDeviceRequest(SDDEVICE *device); - -void -hifFreeDeviceRequest(SDREQUEST *request); - -void -hifRWCompletionHandler(SDREQUEST *request); - -void -hifIRQHandler(void *context); - -HIF_DEVICE * -addHifDevice(SDDEVICE *handle); - -HIF_DEVICE * -getHifDevice(SDDEVICE *handle); - -void -delHifDevice(SDDEVICE *handle); diff --git a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/htc/ar6k.c b/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/htc/ar6k.c deleted file mode 100644 index 72472abb0..000000000 --- a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/htc/ar6k.c +++ /dev/null @@ -1,991 +0,0 @@ -/* - * AR6K device layer that handles register level I/O - * - * Copyright (c) 2007 Atheros Communications Inc. - * All rights reserved. - * - * - * 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; - * - * Software distributed under the License is distributed on an "AS - * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or - * implied. See the License for the specific language governing - * rights and limitations under the License. - * - * - * - */ -#include "a_config.h" -#include "athdefs.h" -#include "a_types.h" -#include "AR6Khwreg.h" -#include "a_osapi.h" -#include "a_debug.h" -#include "hif.h" -#include "htc_packet.h" -#include "ar6k.h" - -#define MAILBOX_FOR_BLOCK_SIZE 1 - -extern A_UINT32 resetok; - -static A_STATUS DevEnableInterrupts(AR6K_DEVICE *pDev); -static A_STATUS DevDisableInterrupts(AR6K_DEVICE *pDev); - -#define LOCK_AR6K(p) A_MUTEX_LOCK(&(p)->Lock); -#define UNLOCK_AR6K(p) A_MUTEX_UNLOCK(&(p)->Lock); - -void AR6KFreeIOPacket(AR6K_DEVICE *pDev, HTC_PACKET *pPacket) -{ - LOCK_AR6K(pDev); - HTC_PACKET_ENQUEUE(&pDev->RegisterIOList,pPacket); - UNLOCK_AR6K(pDev); -} - -HTC_PACKET *AR6KAllocIOPacket(AR6K_DEVICE *pDev) -{ - HTC_PACKET *pPacket; - - LOCK_AR6K(pDev); - pPacket = HTC_PACKET_DEQUEUE(&pDev->RegisterIOList); - UNLOCK_AR6K(pDev); - - return pPacket; -} - -A_STATUS DevSetup(AR6K_DEVICE *pDev) -{ - A_UINT32 mailboxaddrs[AR6K_MAILBOXES]; - A_UINT32 blocksizes[AR6K_MAILBOXES]; - A_STATUS status = A_OK; - int i; - - AR_DEBUG_ASSERT(AR6K_IRQ_PROC_REGS_SIZE == 16); - AR_DEBUG_ASSERT(AR6K_IRQ_ENABLE_REGS_SIZE == 4); - - do { - /* give a handle to HIF for this target */ - HIFSetHandle(pDev->HIFDevice, (void *)pDev); - /* initialize our free list of IO packets */ - INIT_HTC_PACKET_QUEUE(&pDev->RegisterIOList); - A_MUTEX_INIT(&pDev->Lock); - - /* get the addresses for all 4 mailboxes */ - status = HIFConfigureDevice(pDev->HIFDevice, HIF_DEVICE_GET_MBOX_ADDR, - mailboxaddrs, sizeof(mailboxaddrs)); - - if (status != A_OK) { - AR_DEBUG_ASSERT(FALSE); - break; - } - - /* carve up register I/O packets (these are for ASYNC register I/O ) */ - for (i = 0; i < AR6K_MAX_REG_IO_BUFFERS; i++) { - HTC_PACKET *pIOPacket; - pIOPacket = &pDev->RegIOBuffers[i].HtcPacket; - SET_HTC_PACKET_INFO_RX_REFILL(pIOPacket, - pDev, - pDev->RegIOBuffers[i].Buffer, - AR6K_REG_IO_BUFFER_SIZE, - 0); /* don't care */ - AR6KFreeIOPacket(pDev,pIOPacket); - } - - /* get the address of the mailbox we are using */ - pDev->MailboxAddress = mailboxaddrs[HTC_MAILBOX]; - - /* get the block sizes */ - status = HIFConfigureDevice(pDev->HIFDevice, HIF_DEVICE_GET_MBOX_BLOCK_SIZE, - blocksizes, sizeof(blocksizes)); - - if (status != A_OK) { - AR_DEBUG_ASSERT(FALSE); - break; - } - - /* note: we actually get the block size of a mailbox other than 0, for SDIO the block - * size on mailbox 0 is artificially set to 1. So we use the block size that is set - * for the other 3 mailboxes */ - pDev->BlockSize = blocksizes[MAILBOX_FOR_BLOCK_SIZE]; - /* must be a power of 2 */ - AR_DEBUG_ASSERT((pDev->BlockSize & (pDev->BlockSize - 1)) == 0); - - /* assemble mask, used for padding to a block */ - pDev->BlockMask = pDev->BlockSize - 1; - - AR_DEBUG_PRINTF(ATH_DEBUG_TRC,("BlockSize: %d, MailboxAddress:0x%X \n", - pDev->BlockSize, pDev->MailboxAddress)); - - pDev->GetPendingEventsFunc = NULL; - /* see if the HIF layer implements the get pending events function */ - HIFConfigureDevice(pDev->HIFDevice, - HIF_DEVICE_GET_PENDING_EVENTS_FUNC, - &pDev->GetPendingEventsFunc, - sizeof(pDev->GetPendingEventsFunc)); - - /* assume we can process HIF interrupt events asynchronously */ - pDev->HifIRQProcessingMode = HIF_DEVICE_IRQ_ASYNC_SYNC; - - /* see if the HIF layer overrides this assumption */ - HIFConfigureDevice(pDev->HIFDevice, - HIF_DEVICE_GET_IRQ_PROC_MODE, - &pDev->HifIRQProcessingMode, - sizeof(pDev->HifIRQProcessingMode)); - - switch (pDev->HifIRQProcessingMode) { - case HIF_DEVICE_IRQ_SYNC_ONLY: - AR_DEBUG_PRINTF(ATH_DEBUG_TRC,("HIF Interrupt processing is SYNC ONLY\n")); - break; - case HIF_DEVICE_IRQ_ASYNC_SYNC: - AR_DEBUG_PRINTF(ATH_DEBUG_TRC,("HIF Interrupt processing is ASYNC and SYNC\n")); - break; - default: - AR_DEBUG_ASSERT(FALSE); - } - - pDev->HifMaskUmaskRecvEvent = NULL; - - /* see if the HIF layer implements the mask/unmask recv events function */ - HIFConfigureDevice(pDev->HIFDevice, - HIF_DEVICE_GET_RECV_EVENT_MASK_UNMASK_FUNC, - &pDev->HifMaskUmaskRecvEvent, - sizeof(pDev->HifMaskUmaskRecvEvent)); - - AR_DEBUG_PRINTF(ATH_DEBUG_TRC,("HIF special overrides : 0x%X , 0x%X\n", - (A_UINT32)pDev->GetPendingEventsFunc, (A_UINT32)pDev->HifMaskUmaskRecvEvent)); - - status = DevDisableInterrupts(pDev); - - } while (FALSE); - - if (A_FAILED(status)) { - /* make sure handle is cleared */ - HIFSetHandle(pDev->HIFDevice, NULL); - } - - return status; - -} - -static A_STATUS DevEnableInterrupts(AR6K_DEVICE *pDev) -{ - A_STATUS status; - AR6K_IRQ_ENABLE_REGISTERS regs; - - LOCK_AR6K(pDev); - - /* Enable all the interrupts except for the dragon interrupt */ - pDev->IrqEnableRegisters.int_status_enable = INT_STATUS_ENABLE_ERROR_SET(0x01) | - INT_STATUS_ENABLE_CPU_SET(0x01) | - INT_STATUS_ENABLE_COUNTER_SET(0x01); - - if (NULL == pDev->GetPendingEventsFunc) { - pDev->IrqEnableRegisters.int_status_enable |= INT_STATUS_ENABLE_MBOX_DATA_SET(0x01); - } else { - /* The HIF layer provided us with a pending events function which means that - * the detection of pending mbox messages is handled in the HIF layer. - * This is the case for the SPI2 interface. - * In the normal case we enable MBOX interrupts, for the case - * with HIFs that offer this mechanism, we keep these interrupts - * masked */ - pDev->IrqEnableRegisters.int_status_enable &= ~INT_STATUS_ENABLE_MBOX_DATA_SET(0x01); - } - - - /* Set up the CPU Interrupt Status Register */ - pDev->IrqEnableRegisters.cpu_int_status_enable = CPU_INT_STATUS_ENABLE_BIT_SET(0x00); - - /* Set up the Error Interrupt Status Register */ - pDev->IrqEnableRegisters.error_status_enable = - ERROR_STATUS_ENABLE_RX_UNDERFLOW_SET(0x01) | - ERROR_STATUS_ENABLE_TX_OVERFLOW_SET(0x01); - - /* Set up the Counter Interrupt Status Register (only for debug interrupt to catch fatal errors) */ - pDev->IrqEnableRegisters.counter_int_status_enable = - COUNTER_INT_STATUS_ENABLE_BIT_SET(AR6K_TARGET_DEBUG_INTR_MASK); - - /* copy into our temp area */ - A_MEMCPY(®s,&pDev->IrqEnableRegisters,AR6K_IRQ_ENABLE_REGS_SIZE); - - UNLOCK_AR6K(pDev); - - /* always synchronous */ - status = HIFReadWrite(pDev->HIFDevice, - INT_STATUS_ENABLE_ADDRESS, - ®s.int_status_enable, - AR6K_IRQ_ENABLE_REGS_SIZE, - HIF_WR_SYNC_BYTE_INC, - NULL); - - if (status != A_OK) { - /* Can't write it for some reason */ - AR_DEBUG_PRINTF(ATH_DEBUG_ERR, - ("Failed to update interrupt control registers err: %d\n", status)); - - } - - return status; -} - -static A_STATUS DevDisableInterrupts(AR6K_DEVICE *pDev) -{ - AR6K_IRQ_ENABLE_REGISTERS regs; - - LOCK_AR6K(pDev); - /* Disable all interrupts */ - pDev->IrqEnableRegisters.int_status_enable = 0; - pDev->IrqEnableRegisters.cpu_int_status_enable = 0; - pDev->IrqEnableRegisters.error_status_enable = 0; - pDev->IrqEnableRegisters.counter_int_status_enable = 0; - /* copy into our temp area */ - A_MEMCPY(®s,&pDev->IrqEnableRegisters,AR6K_IRQ_ENABLE_REGS_SIZE); - - UNLOCK_AR6K(pDev); - - /* always synchronous */ - return HIFReadWrite(pDev->HIFDevice, - INT_STATUS_ENABLE_ADDRESS, - ®s.int_status_enable, - AR6K_IRQ_ENABLE_REGS_SIZE, - HIF_WR_SYNC_BYTE_INC, - NULL); -} - -/* enable device interrupts */ -A_STATUS DevUnmaskInterrupts(AR6K_DEVICE *pDev) -{ - /* Unmask the host controller interrupts */ - HIFUnMaskInterrupt(pDev->HIFDevice); - - return DevEnableInterrupts(pDev); -} - -/* disable all device interrupts */ -A_STATUS DevMaskInterrupts(AR6K_DEVICE *pDev) -{ - A_STATUS status; - - status = DevDisableInterrupts(pDev); - - if (A_SUCCESS(status)) { - /* Disable the interrupt at the HIF layer */ - HIFMaskInterrupt(pDev->HIFDevice); - } - - return status; -} - -/* callback when our fetch to enable/disable completes */ -static void DevDoEnableDisableRecvAsyncHandler(void *Context, HTC_PACKET *pPacket) -{ - AR6K_DEVICE *pDev = (AR6K_DEVICE *)Context; - - AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("+DevDoEnableDisableRecvAsyncHandler: (dev: 0x%X)\n", (A_UINT32)pDev)); - - if (A_FAILED(pPacket->Status)) { - AR_DEBUG_PRINTF(ATH_DEBUG_ERR, - (" Failed to disable receiver, status:%d \n", pPacket->Status)); - } - /* free this IO packet */ - AR6KFreeIOPacket(pDev,pPacket); - AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("-DevDoEnableDisableRecvAsyncHandler \n")); -} - -/* disable packet reception (used in case the host runs out of buffers) - * this is the "override" method when the HIF reports another methods to - * disable recv events */ -static A_STATUS DevDoEnableDisableRecvOverride(AR6K_DEVICE *pDev, A_BOOL EnableRecv, A_BOOL AsyncMode) -{ - A_STATUS status = A_OK; - HTC_PACKET *pIOPacket = NULL; - - AR_DEBUG_PRINTF(ATH_DEBUG_TRC,("DevDoEnableDisableRecvOverride: Enable:%d Mode:%d\n", - EnableRecv,AsyncMode)); - - do { - - if (AsyncMode) { - - pIOPacket = AR6KAllocIOPacket(pDev); - - if (NULL == pIOPacket) { - status = A_NO_MEMORY; - AR_DEBUG_ASSERT(FALSE); - break; - } - - /* stick in our completion routine when the I/O operation completes */ - pIOPacket->Completion = DevDoEnableDisableRecvAsyncHandler; - pIOPacket->pContext = pDev; - - /* call the HIF layer override and do this asynchronously */ - status = pDev->HifMaskUmaskRecvEvent(pDev->HIFDevice, - EnableRecv ? HIF_UNMASK_RECV : HIF_MASK_RECV, - pIOPacket); - break; - } - - /* if we get here we are doing it synchronously */ - status = pDev->HifMaskUmaskRecvEvent(pDev->HIFDevice, - EnableRecv ? HIF_UNMASK_RECV : HIF_MASK_RECV, - NULL); - - } while (FALSE); - - if (A_FAILED(status) && (pIOPacket != NULL)) { - AR6KFreeIOPacket(pDev,pIOPacket); - } - - return status; -} - -/* disable packet reception (used in case the host runs out of buffers) - * this is the "normal" method using the interrupt enable registers through - * the host I/F */ -static A_STATUS DevDoEnableDisableRecvNormal(AR6K_DEVICE *pDev, A_BOOL EnableRecv, A_BOOL AsyncMode) -{ - A_STATUS status = A_OK; - HTC_PACKET *pIOPacket = NULL; - AR6K_IRQ_ENABLE_REGISTERS regs; - - /* take the lock to protect interrupt enable shadows */ - LOCK_AR6K(pDev); - - if (EnableRecv) { - pDev->IrqEnableRegisters.int_status_enable |= INT_STATUS_ENABLE_MBOX_DATA_SET(0x01); - } else { - pDev->IrqEnableRegisters.int_status_enable &= ~INT_STATUS_ENABLE_MBOX_DATA_SET(0x01); - } - - /* copy into our temp area */ - A_MEMCPY(®s,&pDev->IrqEnableRegisters,AR6K_IRQ_ENABLE_REGS_SIZE); - UNLOCK_AR6K(pDev); - - do { - - if (AsyncMode) { - - pIOPacket = AR6KAllocIOPacket(pDev); - - if (NULL == pIOPacket) { - status = A_NO_MEMORY; - AR_DEBUG_ASSERT(FALSE); - break; - } - - /* copy values to write to our async I/O buffer */ - A_MEMCPY(pIOPacket->pBuffer,®s,AR6K_IRQ_ENABLE_REGS_SIZE); - - /* stick in our completion routine when the I/O operation completes */ - pIOPacket->Completion = DevDoEnableDisableRecvAsyncHandler; - pIOPacket->pContext = pDev; - - /* write it out asynchronously */ - HIFReadWrite(pDev->HIFDevice, - INT_STATUS_ENABLE_ADDRESS, - pIOPacket->pBuffer, - AR6K_IRQ_ENABLE_REGS_SIZE, - HIF_WR_ASYNC_BYTE_INC, - pIOPacket); - break; - } - - /* if we get here we are doing it synchronously */ - - status = HIFReadWrite(pDev->HIFDevice, - INT_STATUS_ENABLE_ADDRESS, - ®s.int_status_enable, - AR6K_IRQ_ENABLE_REGS_SIZE, - HIF_WR_SYNC_BYTE_INC, - NULL); - - } while (FALSE); - - if (A_FAILED(status) && (pIOPacket != NULL)) { - AR6KFreeIOPacket(pDev,pIOPacket); - } - - return status; -} - - -A_STATUS DevStopRecv(AR6K_DEVICE *pDev, A_BOOL AsyncMode) -{ - if (NULL == pDev->HifMaskUmaskRecvEvent) { - return DevDoEnableDisableRecvNormal(pDev,FALSE,AsyncMode); - } else { - return DevDoEnableDisableRecvOverride(pDev,FALSE,AsyncMode); - } -} - -A_STATUS DevEnableRecv(AR6K_DEVICE *pDev, A_BOOL AsyncMode) -{ - if (NULL == pDev->HifMaskUmaskRecvEvent) { - return DevDoEnableDisableRecvNormal(pDev,TRUE,AsyncMode); - } else { - return DevDoEnableDisableRecvOverride(pDev,TRUE,AsyncMode); - } -} - -void DevDumpRegisters(AR6K_IRQ_PROC_REGISTERS *pIrqProcRegs, - AR6K_IRQ_ENABLE_REGISTERS *pIrqEnableRegs) -{ - - AR_DEBUG_PRINTF(ATH_DEBUG_DUMP, ("\n<------- Register Table -------->\n")); - - if (pIrqProcRegs != NULL) { - AR_DEBUG_PRINTF(ATH_DEBUG_DUMP, - ("Int Status: 0x%x\n",pIrqProcRegs->host_int_status)); - AR_DEBUG_PRINTF(ATH_DEBUG_DUMP, - ("CPU Int Status: 0x%x\n",pIrqProcRegs->cpu_int_status)); - AR_DEBUG_PRINTF(ATH_DEBUG_DUMP, - ("Error Int Status: 0x%x\n",pIrqProcRegs->error_int_status)); - AR_DEBUG_PRINTF(ATH_DEBUG_DUMP, - ("Counter Int Status: 0x%x\n",pIrqProcRegs->counter_int_status)); - AR_DEBUG_PRINTF(ATH_DEBUG_DUMP, - ("Mbox Frame: 0x%x\n",pIrqProcRegs->mbox_frame)); - AR_DEBUG_PRINTF(ATH_DEBUG_DUMP, - ("Rx Lookahead Valid: 0x%x\n",pIrqProcRegs->rx_lookahead_valid)); - AR_DEBUG_PRINTF(ATH_DEBUG_DUMP, - ("Rx Lookahead 0: 0x%x\n",pIrqProcRegs->rx_lookahead[0])); - AR_DEBUG_PRINTF(ATH_DEBUG_DUMP, - ("Rx Lookahead 1: 0x%x\n",pIrqProcRegs->rx_lookahead[1])); - } - - if (pIrqEnableRegs != NULL) { - AR_DEBUG_PRINTF(ATH_DEBUG_DUMP, - ("Int Status Enable: 0x%x\n",pIrqEnableRegs->int_status_enable)); - AR_DEBUG_PRINTF(ATH_DEBUG_DUMP, - ("Counter Int Status Enable: 0x%x\n",pIrqEnableRegs->counter_int_status_enable)); - AR_DEBUG_PRINTF(ATH_DEBUG_DUMP, ("<------------------------------->\n")); - } -} - - -#ifdef MBOXHW_UNIT_TEST - - -/* This is a mailbox hardware unit test that must be called in a schedulable context - * This test is very simple, it will send a list of buffers with a counting pattern - * and the target will invert the data and send the message back - * - * the unit test has the following constraints: - * - * The target has at least 8 buffers of 256 bytes each. The host will send - * the following pattern of buffers in rapid succession : - * - * 1 buffer - 128 bytes - * 1 buffer - 256 bytes - * 1 buffer - 512 bytes - * 1 buffer - 1024 bytes - * - * The host will send the buffers to one mailbox and wait for buffers to be reflected - * back from the same mailbox. The target sends the buffers FIFO order. - * Once the final buffer has been received for a mailbox, the next mailbox is tested. - * - * - * Note: To simplifythe test , we assume that the chosen buffer sizes - * will fall on a nice block pad - * - * It is expected that higher-order tests will be written to stress the mailboxes using - * a message-based protocol (with some performance timming) that can create more - * randomness in the packets sent over mailboxes. - * - * */ - -#define A_ROUND_UP_PWR2(x, align) (((int) (x) + ((align)-1)) & ~((align)-1)) - -#define BUFFER_BLOCK_PAD 128 - -#if 0 -#define BUFFER1 128 -#define BUFFER2 256 -#define BUFFER3 512 -#define BUFFER4 1024 -#endif - -#if 1 -#define BUFFER1 80 -#define BUFFER2 200 -#define BUFFER3 444 -#define BUFFER4 800 -#endif - -#define TOTAL_BYTES (A_ROUND_UP_PWR2(BUFFER1,BUFFER_BLOCK_PAD) + \ - A_ROUND_UP_PWR2(BUFFER2,BUFFER_BLOCK_PAD) + \ - A_ROUND_UP_PWR2(BUFFER3,BUFFER_BLOCK_PAD) + \ - A_ROUND_UP_PWR2(BUFFER4,BUFFER_BLOCK_PAD) ) - -#define TEST_BYTES (BUFFER1 + BUFFER2 + BUFFER3 + BUFFER4) - -#define TEST_CREDITS_RECV_TIMEOUT 100 - -static A_UINT8 g_Buffer[TOTAL_BYTES]; -static A_UINT32 g_MailboxAddrs[AR6K_MAILBOXES]; -static A_UINT32 g_BlockSizes[AR6K_MAILBOXES]; - -#define BUFFER_PROC_LIST_DEPTH 4 - -typedef struct _BUFFER_PROC_LIST{ - A_UINT8 *pBuffer; - A_UINT32 length; -}BUFFER_PROC_LIST; - - -#define PUSH_BUFF_PROC_ENTRY(pList,len,pCurrpos) \ -{ \ - (pList)->pBuffer = (pCurrpos); \ - (pList)->length = (len); \ - (pCurrpos) += (len); \ - (pList)++; \ -} - -/* a simple and crude way to send different "message" sizes */ -static void AssembleBufferList(BUFFER_PROC_LIST *pList) -{ - A_UINT8 *pBuffer = g_Buffer; - -#if BUFFER_PROC_LIST_DEPTH < 4 -#error "Buffer processing list depth is not deep enough!!" -#endif - - PUSH_BUFF_PROC_ENTRY(pList,BUFFER1,pBuffer); - PUSH_BUFF_PROC_ENTRY(pList,BUFFER2,pBuffer); - PUSH_BUFF_PROC_ENTRY(pList,BUFFER3,pBuffer); - PUSH_BUFF_PROC_ENTRY(pList,BUFFER4,pBuffer); - -} - -#define FILL_ZERO TRUE -#define FILL_COUNTING FALSE -static void InitBuffers(A_BOOL Zero) -{ - A_UINT16 *pBuffer16 = (A_UINT16 *)g_Buffer; - int i; - - /* fill buffer with 16 bit counting pattern or zeros */ - for (i = 0; i < (TOTAL_BYTES / 2) ; i++) { - if (!Zero) { - pBuffer16[i] = (A_UINT16)i; - } else { - pBuffer16[i] = 0; - } - } -} - - -static A_BOOL CheckOneBuffer(A_UINT16 *pBuffer16, int Length) -{ - int i; - A_UINT16 startCount; - A_BOOL success = TRUE; - - /* get the starting count */ - startCount = pBuffer16[0]; - /* invert it, this is the expected value */ - startCount = ~startCount; - /* scan the buffer and verify */ - for (i = 0; i < (Length / 2) ; i++,startCount++) { - /* target will invert all the data */ - if ((A_UINT16)pBuffer16[i] != (A_UINT16)~startCount) { - success = FALSE; - AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Invalid Data Got:0x%X, Expecting:0x%X (offset:%d, total:%d) \n", - pBuffer16[i], ((A_UINT16)~startCount), i, Length)); - AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("0x%X 0x%X 0x%X 0x%X \n", - pBuffer16[i], pBuffer16[i + 1], pBuffer16[i + 2],pBuffer16[i+3])); - break; - } - } - - return success; -} - -static A_BOOL CheckBuffers(void) -{ - int i; - A_BOOL success = TRUE; - BUFFER_PROC_LIST checkList[BUFFER_PROC_LIST_DEPTH]; - - /* assemble the list */ - AssembleBufferList(checkList); - - /* scan the buffers and verify */ - for (i = 0; i < BUFFER_PROC_LIST_DEPTH ; i++) { - success = CheckOneBuffer((A_UINT16 *)checkList[i].pBuffer, checkList[i].length); - if (!success) { - AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Buffer : 0x%X, Length:%d failed verify \n", - (A_UINT32)checkList[i].pBuffer, checkList[i].length)); - break; - } - } - - return success; -} - - /* find the end marker for the last buffer we will be sending */ -static A_UINT16 GetEndMarker(void) -{ - A_UINT8 *pBuffer; - BUFFER_PROC_LIST checkList[BUFFER_PROC_LIST_DEPTH]; - - /* fill up buffers with the normal counting pattern */ - InitBuffers(FILL_COUNTING); - - /* assemble the list we will be sending down */ - AssembleBufferList(checkList); - /* point to the last 2 bytes of the last buffer */ - pBuffer = &(checkList[BUFFER_PROC_LIST_DEPTH - 1].pBuffer[(checkList[BUFFER_PROC_LIST_DEPTH - 1].length) - 2]); - - /* the last count in the last buffer is the marker */ - return (A_UINT16)pBuffer[0] | ((A_UINT16)pBuffer[1] << 8); -} - -#define ATH_PRINT_OUT_ZONE ATH_DEBUG_ERR - -/* send the ordered buffers to the target */ -static A_STATUS SendBuffers(AR6K_DEVICE *pDev, int mbox) -{ - A_STATUS status = A_OK; - A_UINT32 request = HIF_WR_SYNC_BLOCK_INC; - BUFFER_PROC_LIST sendList[BUFFER_PROC_LIST_DEPTH]; - int i; - int totalBytes = 0; - int paddedLength; - int totalwPadding = 0; - - AR_DEBUG_PRINTF(ATH_PRINT_OUT_ZONE, ("Sending buffers on mailbox : %d \n",mbox)); - - /* fill buffer with counting pattern */ - InitBuffers(FILL_COUNTING); - - /* assemble the order in which we send */ - AssembleBufferList(sendList); - - for (i = 0; i < BUFFER_PROC_LIST_DEPTH; i++) { - - /* we are doing block transfers, so we need to pad everything to a block size */ - paddedLength = (sendList[i].length + (g_BlockSizes[mbox] - 1)) & - (~(g_BlockSizes[mbox] - 1)); - - /* send each buffer synchronously */ - status = HIFReadWrite(pDev->HIFDevice, - g_MailboxAddrs[mbox], - sendList[i].pBuffer, - paddedLength, - request, - NULL); - if (status != A_OK) { - break; - } - totalBytes += sendList[i].length; - totalwPadding += paddedLength; - } - - AR_DEBUG_PRINTF(ATH_PRINT_OUT_ZONE, ("Sent %d bytes (%d padded bytes) to mailbox : %d \n",totalBytes,totalwPadding,mbox)); - - return status; -} - -/* poll the mailbox credit counter until we get a credit or timeout */ -static A_STATUS GetCredits(AR6K_DEVICE *pDev, int mbox, int *pCredits) -{ - A_STATUS status = A_OK; - int timeout = TEST_CREDITS_RECV_TIMEOUT; - A_UINT8 credits = 0; - A_UINT32 address; - - while (TRUE) { - - /* Read the counter register to get credits, this auto-decrements */ - address = COUNT_DEC_ADDRESS + (AR6K_MAILBOXES + mbox) * 4; - status = HIFReadWrite(pDev->HIFDevice, address, &credits, sizeof(credits), - HIF_RD_SYNC_BYTE_FIX, NULL); - if (status != A_OK) { - AR_DEBUG_PRINTF(ATH_DEBUG_ERR, - ("Unable to decrement the command credit count register (mbox=%d)\n",mbox)); - status = A_ERROR; - break; - } - - if (credits) { - break; - } - - timeout--; - - if (timeout <= 0) { - AR_DEBUG_PRINTF(ATH_DEBUG_ERR, - (" Timeout reading credit registers (mbox=%d, address:0x%X) \n",mbox,address)); - status = A_ERROR; - break; - } - - /* delay a little, target may not be ready */ - msleep(1000); - - } - - if (status == A_OK) { - *pCredits = credits; - } - - return status; -} - - -/* wait for the buffers to come back */ -static A_STATUS RecvBuffers(AR6K_DEVICE *pDev, int mbox) -{ - A_STATUS status = A_OK; - A_UINT32 request = HIF_RD_SYNC_BLOCK_INC; - BUFFER_PROC_LIST recvList[BUFFER_PROC_LIST_DEPTH]; - int curBuffer; - int credits; - int i; - int totalBytes = 0; - int paddedLength; - int totalwPadding = 0; - - AR_DEBUG_PRINTF(ATH_PRINT_OUT_ZONE, ("Waiting for buffers on mailbox : %d \n",mbox)); - - /* zero the buffers */ - InitBuffers(FILL_ZERO); - - /* assemble the order in which we should receive */ - AssembleBufferList(recvList); - - curBuffer = 0; - - while (curBuffer < BUFFER_PROC_LIST_DEPTH) { - - /* get number of buffers that have been completed, this blocks - * until we get at least 1 credit or it times out */ - status = GetCredits(pDev, mbox, &credits); - - if (status != A_OK) { - break; - } - - AR_DEBUG_PRINTF(ATH_PRINT_OUT_ZONE, ("Got %d messages on mailbox : %d \n",credits, mbox)); - - /* get all the buffers that are sitting on the queue */ - for (i = 0; i < credits; i++) { - AR_DEBUG_ASSERT(curBuffer < BUFFER_PROC_LIST_DEPTH); - /* recv the current buffer synchronously, the buffers should come back in - * order... with padding applied by the target */ - paddedLength = (recvList[curBuffer].length + (g_BlockSizes[mbox] - 1)) & - (~(g_BlockSizes[mbox] - 1)); - - status = HIFReadWrite(pDev->HIFDevice, - g_MailboxAddrs[mbox], - recvList[curBuffer].pBuffer, - paddedLength, - request, - NULL); - if (status != A_OK) { - AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Failed to read %d bytes on mailbox:%d : address:0x%X \n", - recvList[curBuffer].length, mbox, g_MailboxAddrs[mbox])); - break; - } - - totalwPadding += paddedLength; - totalBytes += recvList[curBuffer].length; - curBuffer++; - } - - if (status != A_OK) { - break; - } - /* go back and get some more */ - credits = 0; - } - - if (totalBytes != TEST_BYTES) { - AR_DEBUG_ASSERT(FALSE); - } else { - AR_DEBUG_PRINTF(ATH_PRINT_OUT_ZONE, ("Got all buffers on mbox:%d total recv :%d (w/Padding : %d) \n", - mbox, totalBytes, totalwPadding)); - } - - return status; - - -} - -static A_STATUS DoOneMboxHWTest(AR6K_DEVICE *pDev, int mbox) -{ - A_STATUS status; - - do { - /* send out buffers */ - status = SendBuffers(pDev,mbox); - - if (status != A_OK) { - AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Sending buffers Failed : %d mbox:%d\n",status,mbox)); - break; - } - - /* go get them, this will block */ - status = RecvBuffers(pDev, mbox); - - if (status != A_OK) { - AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Recv buffers Failed : %d mbox:%d\n",status,mbox)); - break; - } - - /* check the returned data patterns */ - if (!CheckBuffers()) { - AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Buffer Verify Failed : mbox:%d\n",mbox)); - status = A_ERROR; - break; - } - - AR_DEBUG_PRINTF(ATH_PRINT_OUT_ZONE, (" Send/Recv success! mailbox : %d \n",mbox)); - - } while (FALSE); - - return status; -} - -/* here is where the test starts */ -A_STATUS DoMboxHWTest(AR6K_DEVICE *pDev) -{ - int i; - A_STATUS status; - int credits = 0; - A_UINT8 params[4]; - int numBufs; - int bufferSize; - A_UINT16 temp; - - - AR_DEBUG_PRINTF(ATH_PRINT_OUT_ZONE, (" DoMboxHWTest START - \n")); - - do { - /* get the addresses for all 4 mailboxes */ - status = HIFConfigureDevice(pDev->HIFDevice, HIF_DEVICE_GET_MBOX_ADDR, - g_MailboxAddrs, sizeof(g_MailboxAddrs)); - - if (status != A_OK) { - AR_DEBUG_ASSERT(FALSE); - break; - } - - /* get the block sizes */ - status = HIFConfigureDevice(pDev->HIFDevice, HIF_DEVICE_GET_MBOX_BLOCK_SIZE, - g_BlockSizes, sizeof(g_BlockSizes)); - - if (status != A_OK) { - AR_DEBUG_ASSERT(FALSE); - break; - } - - /* note, the HIF layer usually reports mbox 0 to have a block size of - * 1, but our test wants to run in block-mode for all mailboxes, so we treat all mailboxes - * the same. */ - g_BlockSizes[0] = g_BlockSizes[1]; - AR_DEBUG_PRINTF(ATH_PRINT_OUT_ZONE, ("Block Size to use: %d \n",g_BlockSizes[0])); - - if (g_BlockSizes[1] > BUFFER_BLOCK_PAD) { - AR_DEBUG_PRINTF(ATH_PRINT_OUT_ZONE, ("%d Block size is too large for buffer pad %d\n", - g_BlockSizes[1], BUFFER_BLOCK_PAD)); - break; - } - - AR_DEBUG_PRINTF(ATH_PRINT_OUT_ZONE, ("Waiting for target.... \n")); - - /* the target lets us know it is ready by giving us 1 credit on - * mailbox 0 */ - status = GetCredits(pDev, 0, &credits); - - if (status != A_OK) { - AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Failed to wait for target ready \n")); - break; - } - - AR_DEBUG_PRINTF(ATH_PRINT_OUT_ZONE, ("Target is ready ...\n")); - - /* read the first 4 scratch registers */ - status = HIFReadWrite(pDev->HIFDevice, - SCRATCH_ADDRESS, - params, - 4, - HIF_RD_SYNC_BYTE_INC, - NULL); - - if (status != A_OK) { - AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Failed to wait get parameters \n")); - break; - } - - numBufs = params[0]; - bufferSize = (int)(((A_UINT16)params[2] << 8) | (A_UINT16)params[1]); - - AR_DEBUG_PRINTF(ATH_PRINT_OUT_ZONE, - ("Target parameters: bufs per mailbox:%d, buffer size:%d bytes (total space: %d, minimum required space (w/padding): %d) \n", - numBufs, bufferSize, (numBufs * bufferSize), TOTAL_BYTES)); - - if ((numBufs * bufferSize) < TOTAL_BYTES) { - AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Not Enough buffer space to run test! need:%d, got:%d \n", - TOTAL_BYTES, (numBufs*bufferSize))); - status = A_ERROR; - break; - } - - temp = GetEndMarker(); - - status = HIFReadWrite(pDev->HIFDevice, - SCRATCH_ADDRESS + 4, - (A_UINT8 *)&temp, - 2, - HIF_WR_SYNC_BYTE_INC, - NULL); - - if (status != A_OK) { - AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Failed to write end marker \n")); - break; - } - - AR_DEBUG_PRINTF(ATH_PRINT_OUT_ZONE, ("End Marker: 0x%X \n",temp)); - - temp = (A_UINT16)g_BlockSizes[1]; - /* convert to a mask */ - temp = temp - 1; - status = HIFReadWrite(pDev->HIFDevice, - SCRATCH_ADDRESS + 6, - (A_UINT8 *)&temp, - 2, - HIF_WR_SYNC_BYTE_INC, - NULL); - - if (status != A_OK) { - AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Failed to write block mask \n")); - break; - } - - AR_DEBUG_PRINTF(ATH_PRINT_OUT_ZONE, ("Set Block Mask: 0x%X \n",temp)); - - /* execute the test on each mailbox */ - for (i = 0; i < AR6K_MAILBOXES; i++) { - status = DoOneMboxHWTest(pDev, i); - if (status != A_OK) { - break; - } - } - - } while (FALSE); - - if (status == A_OK) { - AR_DEBUG_PRINTF(ATH_PRINT_OUT_ZONE, (" DoMboxHWTest DONE - SUCCESS! - \n")); - } else { - AR_DEBUG_PRINTF(ATH_PRINT_OUT_ZONE, (" DoMboxHWTest DONE - FAILED! - \n")); - } - /* don't let HTC_Start continue, the target is actually not running any HTC code */ - return A_ERROR; -} -#endif - - - diff --git a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/htc/ar6k.h b/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/htc/ar6k.h deleted file mode 100644 index 301ab34a3..000000000 --- a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/htc/ar6k.h +++ /dev/null @@ -1,191 +0,0 @@ -/* - * - * Copyright (c) 2007 Atheros Communications Inc. - * All rights reserved. - * - * - * 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; - * - * Software distributed under the License is distributed on an "AS - * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or - * implied. See the License for the specific language governing - * rights and limitations under the License. - * - * - * - */ - -#ifndef AR6K_H_ -#define AR6K_H_ - -#define AR6K_MAILBOXES 4 - -/* HTC runs over mailbox 0 */ -#define HTC_MAILBOX 0 - -#define AR6K_TARGET_DEBUG_INTR_MASK 0x01 - -#define OTHER_INTS_ENABLED (INT_STATUS_ENABLE_ERROR_MASK | \ - INT_STATUS_ENABLE_CPU_MASK | \ - INT_STATUS_ENABLE_COUNTER_MASK) - -//#define MBOXHW_UNIT_TEST 1 - -#include "athstartpack.h" -typedef PREPACK struct _AR6K_IRQ_PROC_REGISTERS { - A_UINT8 host_int_status; - A_UINT8 cpu_int_status; - A_UINT8 error_int_status; - A_UINT8 counter_int_status; - A_UINT8 mbox_frame; - A_UINT8 rx_lookahead_valid; - A_UINT8 hole[2]; - A_UINT32 rx_lookahead[2]; -} POSTPACK AR6K_IRQ_PROC_REGISTERS; - -#define AR6K_IRQ_PROC_REGS_SIZE sizeof(AR6K_IRQ_PROC_REGISTERS) - - - -typedef PREPACK struct _AR6K_IRQ_ENABLE_REGISTERS { - A_UINT8 int_status_enable; - A_UINT8 cpu_int_status_enable; - A_UINT8 error_status_enable; - A_UINT8 counter_int_status_enable; -} POSTPACK AR6K_IRQ_ENABLE_REGISTERS; - -#include "athendpack.h" - -#define AR6K_IRQ_ENABLE_REGS_SIZE sizeof(AR6K_IRQ_ENABLE_REGISTERS) - -#define AR6K_REG_IO_BUFFER_SIZE 32 -#define AR6K_MAX_REG_IO_BUFFERS 8 - -/* buffers for ASYNC I/O */ -typedef struct AR6K_ASYNC_REG_IO_BUFFER { - HTC_PACKET HtcPacket; /* we use an HTC packet as a wrapper for our async register-based I/O */ - A_UINT8 Buffer[AR6K_REG_IO_BUFFER_SIZE]; -} AR6K_ASYNC_REG_IO_BUFFER; - -typedef struct _AR6K_DEVICE { - A_MUTEX_T Lock; - AR6K_IRQ_PROC_REGISTERS IrqProcRegisters; - AR6K_IRQ_ENABLE_REGISTERS IrqEnableRegisters; - void *HIFDevice; - A_UINT32 BlockSize; - A_UINT32 BlockMask; - A_UINT32 MailboxAddress; - HIF_PENDING_EVENTS_FUNC GetPendingEventsFunc; - void *HTCContext; - HTC_PACKET_QUEUE RegisterIOList; - AR6K_ASYNC_REG_IO_BUFFER RegIOBuffers[AR6K_MAX_REG_IO_BUFFERS]; - void (*TargetFailureCallback)(void *Context); - A_STATUS (*MessagePendingCallback)(void *Context, A_UINT32 LookAhead, A_BOOL *pAsyncProc); - HIF_DEVICE_IRQ_PROCESSING_MODE HifIRQProcessingMode; - HIF_MASK_UNMASK_RECV_EVENT HifMaskUmaskRecvEvent; -} AR6K_DEVICE; - -#define IS_DEV_IRQ_PROCESSING_ASYNC_ALLOWED(pDev) ((pDev)->HifIRQProcessingMode != HIF_DEVICE_IRQ_SYNC_ONLY) - -A_STATUS DevSetup(AR6K_DEVICE *pDev); -A_STATUS DevUnmaskInterrupts(AR6K_DEVICE *pDev); -A_STATUS DevMaskInterrupts(AR6K_DEVICE *pDev); -A_STATUS DevPollMboxMsgRecv(AR6K_DEVICE *pDev, - A_UINT32 *pLookAhead, - int TimeoutMS); -A_STATUS DevRWCompletionHandler(void *context, A_STATUS status); -A_STATUS DevDsrHandler(void *context); -A_STATUS DevCheckPendingRecvMsgsAsync(void *context); -void DevDumpRegisters(AR6K_IRQ_PROC_REGISTERS *pIrqProcRegs, - AR6K_IRQ_ENABLE_REGISTERS *pIrqEnableRegs); - -#define DEV_STOP_RECV_ASYNC TRUE -#define DEV_STOP_RECV_SYNC FALSE -#define DEV_ENABLE_RECV_ASYNC TRUE -#define DEV_ENABLE_RECV_SYNC FALSE -A_STATUS DevStopRecv(AR6K_DEVICE *pDev, A_BOOL ASyncMode); -A_STATUS DevEnableRecv(AR6K_DEVICE *pDev, A_BOOL ASyncMode); - -static INLINE A_STATUS DevSendPacket(AR6K_DEVICE *pDev, HTC_PACKET *pPacket, A_UINT32 SendLength) { - A_UINT32 paddedLength; - A_BOOL sync = (pPacket->Completion == NULL) ? TRUE : FALSE; - A_STATUS status; - - /* adjust the length to be a multiple of block size if appropriate */ - paddedLength = (SendLength + (pDev->BlockMask)) & - (~(pDev->BlockMask)); -#if 0 // BufferLength may not be set in , fix this... - if (paddedLength > pPacket->BufferLength) { - AR_DEBUG_ASSERT(FALSE); - if (pPacket->Completion != NULL) { - COMPLETE_HTC_PACKET(pPacket,A_EINVAL); - } - return A_EINVAL; - } -#endif - AR_DEBUG_PRINTF(ATH_DEBUG_SEND, - ("DevSendPacket, Padded Length: %d Mbox:0x%X (mode:%s)\n", - paddedLength, - pDev->MailboxAddress, - sync ? "SYNC" : "ASYNC")); - - status = HIFReadWrite(pDev->HIFDevice, - pDev->MailboxAddress, - pPacket->pBuffer, - paddedLength, /* the padded length */ - sync ? HIF_WR_SYNC_BLOCK_INC : HIF_WR_ASYNC_BLOCK_INC, - sync ? NULL : pPacket); /* pass the packet as the context to the HIF request */ - - if (sync) { - pPacket->Status = status; - } - - return status; -} - -static INLINE A_STATUS DevRecvPacket(AR6K_DEVICE *pDev, HTC_PACKET *pPacket, A_UINT32 RecvLength) { - A_UINT32 paddedLength; - A_STATUS status; - A_BOOL sync = (pPacket->Completion == NULL) ? TRUE : FALSE; - - /* adjust the length to be a multiple of block size if appropriate */ - paddedLength = (RecvLength + (pDev->BlockMask)) & - (~(pDev->BlockMask)); - if (paddedLength > pPacket->BufferLength) { - AR_DEBUG_ASSERT(FALSE); - AR_DEBUG_PRINTF(ATH_DEBUG_ERR, - ("DevRecvPacket, Not enough space for padlen:%d recvlen:%d bufferlen:%d \n", - paddedLength,RecvLength,pPacket->BufferLength)); - if (pPacket->Completion != NULL) { - COMPLETE_HTC_PACKET(pPacket,A_EINVAL); - } - return A_EINVAL; - } - - AR_DEBUG_PRINTF(ATH_DEBUG_RECV, - ("DevRecvPacket, Padded Length: %d Mbox:0x%X (mode:%s)\n", - paddedLength, - pDev->MailboxAddress, - sync ? "SYNC" : "ASYNC")); - - status = HIFReadWrite(pDev->HIFDevice, - pDev->MailboxAddress, - pPacket->pBuffer, - paddedLength, - sync ? HIF_RD_SYNC_BLOCK_INC : HIF_RD_ASYNC_BLOCK_INC, - sync ? NULL : pPacket); /* pass the packet as the context to the HIF request */ - - if (sync) { - pPacket->Status = status; - } - - return status; -} - -#ifdef MBOXHW_UNIT_TEST -A_STATUS DoMboxHWTest(AR6K_DEVICE *pDev); -#endif - -#endif /*AR6K_H_*/ diff --git a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/htc/ar6k_events.c b/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/htc/ar6k_events.c deleted file mode 100644 index 91b29af37..000000000 --- a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/htc/ar6k_events.c +++ /dev/null @@ -1,638 +0,0 @@ -/* - * AR6K Driver layer event handling (i.e. interrupts, message polling) - * - * Copyright (c) 2007 Atheros Communications Inc. - * All rights reserved. - * - * - * 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; - * - * Software distributed under the License is distributed on an "AS - * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or - * implied. See the License for the specific language governing - * rights and limitations under the License. - * - * - * - */ -#include "a_config.h" -#include "athdefs.h" -#include "a_types.h" -#include "AR6Khwreg.h" -#include "a_osapi.h" -#include "a_debug.h" -#include "hif.h" -#include "htc_packet.h" -#include "ar6k.h" - -extern void AR6KFreeIOPacket(AR6K_DEVICE *pDev, HTC_PACKET *pPacket); -extern HTC_PACKET *AR6KAllocIOPacket(AR6K_DEVICE *pDev); - -static A_STATUS DevServiceDebugInterrupt(AR6K_DEVICE *pDev); - -#define DELAY_PER_INTERVAL_MS 10 /* 10 MS delay per polling interval */ - -/* completion routine for ALL HIF layer async I/O */ -A_STATUS DevRWCompletionHandler(void *context, A_STATUS status) -{ - HTC_PACKET *pPacket = (HTC_PACKET *)context; - - COMPLETE_HTC_PACKET(pPacket,status); - - return A_OK; -} - -/* mailbox recv message polling */ -A_STATUS DevPollMboxMsgRecv(AR6K_DEVICE *pDev, - A_UINT32 *pLookAhead, - int TimeoutMS) -{ - A_STATUS status = A_OK; - int timeout = TimeoutMS/DELAY_PER_INTERVAL_MS; - - AR_DEBUG_ASSERT(timeout > 0); - - AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("+DevPollMboxMsgRecv \n")); - - while (TRUE) { - - if (pDev->GetPendingEventsFunc != NULL) - { - - HIF_PENDING_EVENTS_INFO events; - - /* the HIF layer uses a special mechanism to get events, do this - * synchronously */ - status = pDev->GetPendingEventsFunc(pDev->HIFDevice, - &events, - NULL); - if (A_FAILED(status)) - { - AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Failed to get pending events \n")); - break; - } - - if (events.Events & HIF_RECV_MSG_AVAIL) - { - /* there is a message available, the lookahead should be valid now */ - *pLookAhead = events.LookAhead; - - break; - } - } - else - { - - /* this is the standard HIF way.... */ - /* load the register table */ - status = HIFReadWrite(pDev->HIFDevice, - HOST_INT_STATUS_ADDRESS, - (A_UINT8 *)&pDev->IrqProcRegisters, - AR6K_IRQ_PROC_REGS_SIZE, - HIF_RD_SYNC_BYTE_INC, - NULL); - - if (A_FAILED(status)) - { - AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Failed to read register table \n")); - break; - } - - /* check for MBOX data and valid lookahead */ - if (pDev->IrqProcRegisters.host_int_status & (1 << HTC_MAILBOX)) - { - if (pDev->IrqProcRegisters.rx_lookahead_valid & (1 << HTC_MAILBOX)) - { - /* mailbox has a message and the look ahead is valid */ - *pLookAhead = pDev->IrqProcRegisters.rx_lookahead[HTC_MAILBOX]; - break; - } - } - - } - - timeout--; - - if (timeout <= 0) - { - AR_DEBUG_PRINTF(ATH_DEBUG_ERR, (" Timeout waiting for recv message \n")); - status = A_ERROR; - - /* check if the target asserted */ - if ( pDev->IrqProcRegisters.counter_int_status & AR6K_TARGET_DEBUG_INTR_MASK) { - /* target signaled an assert, process this pending interrupt - * this will call the target failure handler */ - DevServiceDebugInterrupt(pDev); - } - - break; - } - - /* delay a little */ - msleep(DELAY_PER_INTERVAL_MS); - AR_DEBUG_PRINTF(ATH_DEBUG_RECV,(" Retry Mbox Poll : %d \n",timeout)); - } - - AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("-DevPollMboxMsgRecv \n")); - - return status; -} - -static A_STATUS DevServiceCPUInterrupt(AR6K_DEVICE *pDev) -{ - A_STATUS status; - A_UINT8 cpu_int_status; - A_UINT8 regBuffer[4]; - - AR_DEBUG_PRINTF(ATH_DEBUG_IRQ, ("CPU Interrupt\n")); - cpu_int_status = pDev->IrqProcRegisters.cpu_int_status & - pDev->IrqEnableRegisters.cpu_int_status_enable; - AR_DEBUG_ASSERT(cpu_int_status); - AR_DEBUG_PRINTF(ATH_DEBUG_IRQ, - ("Valid interrupt source(s) in CPU_INT_STATUS: 0x%x\n", - cpu_int_status)); - - /* Clear the interrupt */ - pDev->IrqProcRegisters.cpu_int_status &= ~cpu_int_status; /* W1C */ - - /* set up the register transfer buffer to hit the register 4 times , this is done - * to make the access 4-byte aligned to mitigate issues with host bus interconnects that - * restrict bus transfer lengths to be a multiple of 4-bytes */ - - /* set W1C value to clear the interrupt, this hits the register first */ - regBuffer[0] = cpu_int_status; - /* the remaining 4 values are set to zero which have no-effect */ - regBuffer[1] = 0; - regBuffer[2] = 0; - regBuffer[3] = 0; - - status = HIFReadWrite(pDev->HIFDevice, - CPU_INT_STATUS_ADDRESS, - regBuffer, - 4, - HIF_WR_SYNC_BYTE_FIX, - NULL); - - AR_DEBUG_ASSERT(status == A_OK); - return status; -} - - -static A_STATUS DevServiceErrorInterrupt(AR6K_DEVICE *pDev) -{ - A_STATUS status; - A_UINT8 error_int_status; - A_UINT8 regBuffer[4]; - - AR_DEBUG_PRINTF(ATH_DEBUG_IRQ, ("Error Interrupt\n")); - error_int_status = pDev->IrqProcRegisters.error_int_status & 0x0F; - AR_DEBUG_ASSERT(error_int_status); - AR_DEBUG_PRINTF(ATH_DEBUG_IRQ, - ("Valid interrupt source(s) in ERROR_INT_STATUS: 0x%x\n", - error_int_status)); - - if (ERROR_INT_STATUS_WAKEUP_GET(error_int_status)) { - /* Wakeup */ - AR_DEBUG_PRINTF(ATH_DEBUG_IRQ, ("Error : Wakeup\n")); - } - - if (ERROR_INT_STATUS_RX_UNDERFLOW_GET(error_int_status)) { - /* Rx Underflow */ - AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Error : Rx Underflow\n")); - } - - if (ERROR_INT_STATUS_TX_OVERFLOW_GET(error_int_status)) { - /* Tx Overflow */ - AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Error : Tx Overflow\n")); - } - - /* Clear the interrupt */ - pDev->IrqProcRegisters.error_int_status &= ~error_int_status; /* W1C */ - - /* set up the register transfer buffer to hit the register 4 times , this is done - * to make the access 4-byte aligned to mitigate issues with host bus interconnects that - * restrict bus transfer lengths to be a multiple of 4-bytes */ - - /* set W1C value to clear the interrupt, this hits the register first */ - regBuffer[0] = error_int_status; - /* the remaining 4 values are set to zero which have no-effect */ - regBuffer[1] = 0; - regBuffer[2] = 0; - regBuffer[3] = 0; - - status = HIFReadWrite(pDev->HIFDevice, - ERROR_INT_STATUS_ADDRESS, - regBuffer, - 4, - HIF_WR_SYNC_BYTE_FIX, - NULL); - - AR_DEBUG_ASSERT(status == A_OK); - return status; -} - -static A_STATUS DevServiceDebugInterrupt(AR6K_DEVICE *pDev) -{ - A_UINT32 dummy; - A_STATUS status; - - /* Send a target failure event to the application */ - AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Target debug interrupt\n")); - - if (pDev->TargetFailureCallback != NULL) { - pDev->TargetFailureCallback(pDev->HTCContext); - } - - /* clear the interrupt , the debug error interrupt is - * counter 0 */ - /* read counter to clear interrupt */ - status = HIFReadWrite(pDev->HIFDevice, - COUNT_DEC_ADDRESS, - (A_UINT8 *)&dummy, - 4, - HIF_RD_SYNC_BYTE_INC, - NULL); - - AR_DEBUG_ASSERT(status == A_OK); - return status; -} - -static A_STATUS DevServiceCounterInterrupt(AR6K_DEVICE *pDev) -{ - A_UINT8 counter_int_status; - - AR_DEBUG_PRINTF(ATH_DEBUG_IRQ, ("Counter Interrupt\n")); - - counter_int_status = pDev->IrqProcRegisters.counter_int_status & - pDev->IrqEnableRegisters.counter_int_status_enable; - - AR_DEBUG_ASSERT(counter_int_status); - AR_DEBUG_PRINTF(ATH_DEBUG_IRQ, - ("Valid interrupt source(s) in COUNTER_INT_STATUS: 0x%x\n", - counter_int_status)); - - /* Check if the debug interrupt is pending */ - if (counter_int_status & AR6K_TARGET_DEBUG_INTR_MASK) { - return DevServiceDebugInterrupt(pDev); - } - - return A_OK; -} - -/* callback when our fetch to get interrupt status registers completes */ -static void DevGetEventAsyncHandler(void *Context, HTC_PACKET *pPacket) -{ - AR6K_DEVICE *pDev = (AR6K_DEVICE *)Context; - A_UINT32 lookAhead = 0; - A_BOOL otherInts = FALSE; - - AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("+DevGetEventAsyncHandler: (dev: 0x%X)\n", (A_UINT32)pDev)); - - do { - - if (A_FAILED(pPacket->Status)) { - AR_DEBUG_PRINTF(ATH_DEBUG_ERR, - (" GetEvents I/O request failed, status:%d \n", pPacket->Status)); - /* bail out, don't unmask HIF interrupt */ - break; - } - - if (pDev->GetPendingEventsFunc != NULL) { - /* the HIF layer collected the information for us */ - HIF_PENDING_EVENTS_INFO *pEvents = (HIF_PENDING_EVENTS_INFO *)pPacket->pBuffer; - if (pEvents->Events & HIF_RECV_MSG_AVAIL) { - lookAhead = pEvents->LookAhead; - if (0 == lookAhead) { - AR_DEBUG_PRINTF(ATH_DEBUG_ERR,(" DevGetEventAsyncHandler1, lookAhead is zero! \n")); - } - } - if (pEvents->Events & HIF_OTHER_EVENTS) { - otherInts = TRUE; - } - } else { - /* standard interrupt table handling.... */ - AR6K_IRQ_PROC_REGISTERS *pReg = (AR6K_IRQ_PROC_REGISTERS *)pPacket->pBuffer; - A_UINT8 host_int_status; - - host_int_status = pReg->host_int_status & pDev->IrqEnableRegisters.int_status_enable; - - if (host_int_status & (1 << HTC_MAILBOX)) { - host_int_status &= ~(1 << HTC_MAILBOX); - if (pReg->rx_lookahead_valid & (1 << HTC_MAILBOX)) { - /* mailbox has a message and the look ahead is valid */ - lookAhead = pReg->rx_lookahead[HTC_MAILBOX]; - if (0 == lookAhead) { - AR_DEBUG_PRINTF(ATH_DEBUG_ERR,(" DevGetEventAsyncHandler2, lookAhead is zero! \n")); - } - } - } - - if (host_int_status) { - /* there are other interrupts to handle */ - otherInts = TRUE; - } - } - - if (otherInts || (lookAhead == 0)) { - /* if there are other interrupts to process, we cannot do this in the async handler so - * ack the interrupt which will cause our sync handler to run again - * if however there are no more messages, we can now ack the interrupt */ - AR_DEBUG_PRINTF(ATH_DEBUG_IRQ, - (" Acking interrupt from DevGetEventAsyncHandler (otherints:%d, lookahead:0x%X)\n", - otherInts, lookAhead)); - HIFAckInterrupt(pDev->HIFDevice); - } else { - AR_DEBUG_PRINTF(ATH_DEBUG_IRQ, - (" DevGetEventAsyncHandler : detected another message, lookahead :0x%X \n", - lookAhead)); - /* lookahead is non-zero and there are no other interrupts to service, - * go get the next message */ - pDev->MessagePendingCallback(pDev->HTCContext, lookAhead, NULL); - } - - } while (FALSE); - - /* free this IO packet */ - AR6KFreeIOPacket(pDev,pPacket); - AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("-DevGetEventAsyncHandler \n")); -} - -/* called by the HTC layer when it wants us to check if the device has any more pending - * recv messages, this starts off a series of async requests to read interrupt registers */ -A_STATUS DevCheckPendingRecvMsgsAsync(void *context) -{ - AR6K_DEVICE *pDev = (AR6K_DEVICE *)context; - A_STATUS status = A_OK; - HTC_PACKET *pIOPacket; - - /* this is called in an ASYNC only context, we may NOT block, sleep or call any apis that can - * cause us to switch contexts */ - - AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("+DevCheckPendingRecvMsgsAsync: (dev: 0x%X)\n", (A_UINT32)pDev)); - - do { - - if (HIF_DEVICE_IRQ_SYNC_ONLY == pDev->HifIRQProcessingMode) { - /* break the async processing chain right here, no need to continue. - * The DevDsrHandler() will handle things in a loop when things are driven - * synchronously */ - break; - } - /* first allocate one of our HTC packets we created for async I/O - * we reuse HTC packet definitions so that we can use the completion mechanism - * in DevRWCompletionHandler() */ - pIOPacket = AR6KAllocIOPacket(pDev); - - if (NULL == pIOPacket) { - /* there should be only 1 asynchronous request out at a time to read these registers - * so this should actually never happen */ - status = A_NO_MEMORY; - AR_DEBUG_ASSERT(FALSE); - break; - } - - /* stick in our completion routine when the I/O operation completes */ - pIOPacket->Completion = DevGetEventAsyncHandler; - pIOPacket->pContext = pDev; - - if (pDev->GetPendingEventsFunc) { - /* HIF layer has it's own mechanism, pass the IO to it.. */ - status = pDev->GetPendingEventsFunc(pDev->HIFDevice, - (HIF_PENDING_EVENTS_INFO *)pIOPacket->pBuffer, - pIOPacket); - - } else { - /* standard way, read the interrupt register table asynchronously again */ - status = HIFReadWrite(pDev->HIFDevice, - HOST_INT_STATUS_ADDRESS, - pIOPacket->pBuffer, - AR6K_IRQ_PROC_REGS_SIZE, - HIF_RD_ASYNC_BYTE_INC, - pIOPacket); - } - - AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,(" Async IO issued to get interrupt status...\n")); - } while (FALSE); - - AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("-DevCheckPendingRecvMsgsAsync \n")); - - return status; -} - -/* process pending interrupts synchronously */ -static A_STATUS ProcessPendingIRQs(AR6K_DEVICE *pDev, A_BOOL *pDone, A_BOOL *pASyncProcessing) -{ - A_STATUS status = A_OK; - A_UINT8 host_int_status = 0; - A_UINT32 lookAhead = 0; - - AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("+ProcessPendingIRQs: (dev: 0x%X)\n", (A_UINT32)pDev)); - - /*** NOTE: the HIF implementation guarantees that the context of this call allows - * us to perform SYNCHRONOUS I/O, that is we can block, sleep or call any API that - * can block or switch thread/task ontexts. - * This is a fully schedulable context. - * */ - do { - - if (pDev->GetPendingEventsFunc != NULL) { - HIF_PENDING_EVENTS_INFO events; - - /* the HIF layer uses a special mechanism to get events - * get this synchronously */ - status = pDev->GetPendingEventsFunc(pDev->HIFDevice, - &events, - NULL); - - if (A_FAILED(status)) { - break; - } - - if (events.Events & HIF_RECV_MSG_AVAIL) { - lookAhead = events.LookAhead; - if (0 == lookAhead) { - AR_DEBUG_PRINTF(ATH_DEBUG_ERR,(" ProcessPendingIRQs1 lookAhead is zero! \n")); - } - } - - if (!(events.Events & HIF_OTHER_EVENTS) || - !(pDev->IrqEnableRegisters.int_status_enable & OTHER_INTS_ENABLED)) { - /* no need to read the register table, no other interesting interrupts. - * Some interfaces (like SPI) can shadow interrupt sources without - * requiring the host to do a full table read */ - break; - } - - /* otherwise fall through and read the register table */ - } - - /* - * Read the first 28 bytes of the HTC register table. This will yield us - * the value of different int status registers and the lookahead - * registers. - * length = sizeof(int_status) + sizeof(cpu_int_status) + - * sizeof(error_int_status) + sizeof(counter_int_status) + - * sizeof(mbox_frame) + sizeof(rx_lookahead_valid) + - * sizeof(hole) + sizeof(rx_lookahead) + - * sizeof(int_status_enable) + sizeof(cpu_int_status_enable) + - * sizeof(error_status_enable) + - * sizeof(counter_int_status_enable); - * - */ - status = HIFReadWrite(pDev->HIFDevice, - HOST_INT_STATUS_ADDRESS, - (A_UINT8 *)&pDev->IrqProcRegisters, - AR6K_IRQ_PROC_REGS_SIZE, - HIF_RD_SYNC_BYTE_INC, - NULL); - - if (A_FAILED(status)) { - break; - } - - if (AR_DEBUG_LVL_CHECK(ATH_DEBUG_IRQ)) { - DevDumpRegisters(&pDev->IrqProcRegisters, - &pDev->IrqEnableRegisters); - } - - /* Update only those registers that are enabled */ - host_int_status = pDev->IrqProcRegisters.host_int_status & - pDev->IrqEnableRegisters.int_status_enable; - - if (NULL == pDev->GetPendingEventsFunc) { - /* only look at mailbox status if the HIF layer did not provide this function, - * on some HIF interfaces reading the RX lookahead is not valid to do */ - if (host_int_status & (1 << HTC_MAILBOX)) { - /* mask out pending mailbox value, we use "lookAhead" as the real flag for - * mailbox processing below */ - host_int_status &= ~(1 << HTC_MAILBOX); - if (pDev->IrqProcRegisters.rx_lookahead_valid & (1 << HTC_MAILBOX)) { - /* mailbox has a message and the look ahead is valid */ - lookAhead = pDev->IrqProcRegisters.rx_lookahead[HTC_MAILBOX]; - if (0 == lookAhead) { - AR_DEBUG_PRINTF(ATH_DEBUG_ERR,(" ProcessPendingIRQs2, lookAhead is zero! \n")); - } - } - } - } else { - /* not valid to check if the HIF has another mechanism for reading mailbox pending status*/ - host_int_status &= ~(1 << HTC_MAILBOX); - } - - } while (FALSE); - - - do { - - /* did the interrupt status fetches succeed? */ - if (A_FAILED(status)) { - break; - } - - if ((0 == host_int_status) && (0 == lookAhead)) { - /* nothing to process, the caller can use this to break out of a loop */ - *pDone = TRUE; - break; - } - - if (lookAhead != 0) { - AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("Pending mailbox message, LookAhead: 0x%X\n",lookAhead)); - /* Mailbox Interrupt, the HTC layer may issue async requests to empty the - * mailbox... - * When emptying the recv mailbox we use the async handler above called from the - * completion routine of the callers read request. This can improve performance - * by reducing context switching when we rapidly pull packets */ - status = pDev->MessagePendingCallback(pDev->HTCContext, lookAhead, pASyncProcessing); - if (A_FAILED(status)) { - break; - } - } - - /* now handle the rest of them */ - AR_DEBUG_PRINTF(ATH_DEBUG_IRQ, - (" Valid interrupt source(s) for OTHER interrupts: 0x%x\n", - host_int_status)); - - if (HOST_INT_STATUS_CPU_GET(host_int_status)) { - /* CPU Interrupt */ - status = DevServiceCPUInterrupt(pDev); - if (A_FAILED(status)){ - break; - } - } - - if (HOST_INT_STATUS_ERROR_GET(host_int_status)) { - /* Error Interrupt */ - status = DevServiceErrorInterrupt(pDev); - if (A_FAILED(status)){ - break; - } - } - - if (HOST_INT_STATUS_COUNTER_GET(host_int_status)) { - /* Counter Interrupt */ - status = DevServiceCounterInterrupt(pDev); - if (A_FAILED(status)){ - break; - } - } - - } while (FALSE); - - AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("-ProcessPendingIRQs: (done:%d, async:%d) status=%d \n", - *pDone, *pASyncProcessing, status)); - - return status; -} - - -/* Synchronousinterrupt handler, this handler kicks off all interrupt processing.*/ -A_STATUS DevDsrHandler(void *context) -{ - AR6K_DEVICE *pDev = (AR6K_DEVICE *)context; - A_STATUS status = A_OK; - A_BOOL done = FALSE; - A_BOOL asyncProc = FALSE; - - AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("+DevDsrHandler: (dev: 0x%X)\n", (A_UINT32)pDev)); - - - while (!done) { - status = ProcessPendingIRQs(pDev, &done, &asyncProc); - if (A_FAILED(status)) { - break; - } - - if (HIF_DEVICE_IRQ_SYNC_ONLY == pDev->HifIRQProcessingMode) { - /* the HIF layer does not allow async IRQ processing, override the asyncProc flag */ - asyncProc = FALSE; - /* this will cause us to re-enter ProcessPendingIRQ() and re-read interrupt status registers. - * this has a nice side effect of blocking us until all async read requests are completed. - * This behavior is required on some HIF implementations that do not allow ASYNC - * processing in interrupt handlers (like Windows CE) */ - } - - if (asyncProc) { - /* the function performed some async I/O for performance, we - need to exit the ISR immediately, the check below will prevent the interrupt from being - Ack'd while we handle it asynchronously */ - break; - } - - } - - if (A_SUCCESS(status) && !asyncProc) { - /* Ack the interrupt only if : - * 1. we did not get any errors in processing interrupts - * 2. there are no outstanding async processing requests */ - AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,(" Acking interrupt from DevDsrHandler \n")); - HIFAckInterrupt(pDev->HIFDevice); - } - - AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("-DevDsrHandler \n")); - return A_OK; -} - - diff --git a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/htc/htc.c b/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/htc/htc.c deleted file mode 100644 index d52ed944e..000000000 --- a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/htc/htc.c +++ /dev/null @@ -1,508 +0,0 @@ -/* - * - * Copyright (c) 2007 Atheros Communications Inc. - * All rights reserved. - * - * - * 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; - * - * Software distributed under the License is distributed on an "AS - * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or - * implied. See the License for the specific language governing - * rights and limitations under the License. - * - * - * - */ - -#include "htc_internal.h" - - -static HTC_INIT_INFO HTCInitInfo = {NULL,NULL,NULL}; -static A_BOOL HTCInitialized = FALSE; - -static A_STATUS HTCTargetInsertedHandler(void *hif_handle); -static A_STATUS HTCTargetRemovedHandler(void *handle, A_STATUS status); -static void HTCReportFailure(void *Context); - -/* Initializes the HTC layer */ -A_STATUS HTCInit(HTC_INIT_INFO *pInitInfo) -{ - HTC_CALLBACKS htcCallbacks; - - AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("HTCInit: Enter\n")); - if (HTCInitialized) { - AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("HTCInit: Exit\n")); - return A_OK; - } - - A_MEMCPY(&HTCInitInfo,pInitInfo,sizeof(HTC_INIT_INFO)); - - A_MEMZERO(&htcCallbacks, sizeof(HTC_CALLBACKS)); - - /* setup HIF layer callbacks */ - htcCallbacks.deviceInsertedHandler = HTCTargetInsertedHandler; - htcCallbacks.deviceRemovedHandler = HTCTargetRemovedHandler; - /* the device layer handles these */ - htcCallbacks.rwCompletionHandler = DevRWCompletionHandler; - htcCallbacks.dsrHandler = DevDsrHandler; - HIFInit(&htcCallbacks); - HTCInitialized = TRUE; - - AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("HTCInit: Exit\n")); - return A_OK; -} - -void HTCFreeControlBuffer(HTC_TARGET *target, HTC_PACKET *pPacket, HTC_PACKET_QUEUE *pList) -{ - LOCK_HTC(target); - HTC_PACKET_ENQUEUE(pList,pPacket); - UNLOCK_HTC(target); -} - -HTC_PACKET *HTCAllocControlBuffer(HTC_TARGET *target, HTC_PACKET_QUEUE *pList) -{ - HTC_PACKET *pPacket; - - LOCK_HTC(target); - pPacket = HTC_PACKET_DEQUEUE(pList); - UNLOCK_HTC(target); - - return pPacket; -} - -/* cleanup the HTC instance */ -static void HTCCleanup(HTC_TARGET *target) -{ - if (A_IS_MUTEX_VALID(&target->HTCLock)) { - A_MUTEX_DELETE(&target->HTCLock); - } - - if (A_IS_MUTEX_VALID(&target->HTCRxLock)) { - A_MUTEX_DELETE(&target->HTCRxLock); - } - - if (A_IS_MUTEX_VALID(&target->HTCTxLock)) { - A_MUTEX_DELETE(&target->HTCTxLock); - } - /* free our instance */ - A_FREE(target); -} - -/* registered target arrival callback from the HIF layer */ -static A_STATUS HTCTargetInsertedHandler(void *hif_handle) -{ - HTC_TARGET *target = NULL; - A_STATUS status; - int i; - - AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("htcTargetInserted - Enter\n")); - - do { - - /* allocate target memory */ - if ((target = (HTC_TARGET *)A_MALLOC(sizeof(HTC_TARGET))) == NULL) { - AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to allocate memory\n")); - status = A_ERROR; - break; - } - - A_MEMZERO(target, sizeof(HTC_TARGET)); - A_MUTEX_INIT(&target->HTCLock); - A_MUTEX_INIT(&target->HTCRxLock); - A_MUTEX_INIT(&target->HTCTxLock); - INIT_HTC_PACKET_QUEUE(&target->ControlBufferTXFreeList); - INIT_HTC_PACKET_QUEUE(&target->ControlBufferRXFreeList); - - /* give device layer the hif device handle */ - target->Device.HIFDevice = hif_handle; - /* give the device layer our context (for event processing) - * the device layer will register it's own context with HIF - * so we need to set this so we can fetch it in the target remove handler */ - target->Device.HTCContext = target; - /* set device layer target failure callback */ - target->Device.TargetFailureCallback = HTCReportFailure; - /* set device layer recv message pending callback */ - target->Device.MessagePendingCallback = HTCRecvMessagePendingHandler; - target->EpWaitingForBuffers = ENDPOINT_MAX; - - /* setup device layer */ - status = DevSetup(&target->Device); - - if (A_FAILED(status)) { - break; - } - - /* carve up buffers/packets for control messages */ - for (i = 0; i < NUM_CONTROL_RX_BUFFERS; i++) { - HTC_PACKET *pControlPacket; - pControlPacket = &target->HTCControlBuffers[i].HtcPacket; - SET_HTC_PACKET_INFO_RX_REFILL(pControlPacket, - target, - target->HTCControlBuffers[i].Buffer, - HTC_CONTROL_BUFFER_SIZE, - ENDPOINT_0); - HTC_FREE_CONTROL_RX(target,pControlPacket); - } - - for (;i < NUM_CONTROL_BUFFERS;i++) { - HTC_PACKET *pControlPacket; - pControlPacket = &target->HTCControlBuffers[i].HtcPacket; - INIT_HTC_PACKET_INFO(pControlPacket, - target->HTCControlBuffers[i].Buffer, - HTC_CONTROL_BUFFER_SIZE); - HTC_FREE_CONTROL_TX(target,pControlPacket); - } - - } while (FALSE); - - if (A_SUCCESS(status)) { - AR_DEBUG_PRINTF(ATH_DEBUG_TRC, (" calling AddInstance callback \n")); - /* announce ourselves */ - HTCInitInfo.AddInstance((HTC_HANDLE)target); - } else { - if (target != NULL) { - HTCCleanup(target); - } - } - - AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("htcTargetInserted - Exit\n")); - - return status; -} - -/* registered removal callback from the HIF layer */ -static A_STATUS HTCTargetRemovedHandler(void *handle, A_STATUS status) -{ - HTC_TARGET *target; - - AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("+HTCTargetRemovedHandler handle:0x%X \n",(A_UINT32)handle)); - - if (NULL == handle) { - /* this could be NULL in the event that target initialization failed */ - return A_OK; - } - - target = ((AR6K_DEVICE *)handle)->HTCContext; - - AR_DEBUG_PRINTF(ATH_DEBUG_TRC, (" removing target:0x%X instance:0x%X ... \n", - (A_UINT32)target, (A_UINT32)target->pInstanceContext)); - - if (target->pInstanceContext != NULL) { - /* let upper layer know, it needs to call HTCStop() */ - HTCInitInfo.DeleteInstance(target->pInstanceContext); - } - - HIFShutDownDevice(target->Device.HIFDevice); - - HTCCleanup(target); - AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("-HTCTargetRemovedHandler \n")); - return A_OK; -} - -/* get the low level HIF device for the caller , the caller may wish to do low level - * HIF requests */ -void *HTCGetHifDevice(HTC_HANDLE HTCHandle) -{ - HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle); - return target->Device.HIFDevice; -} - -/* set the instance block for this HTC handle, so that on removal, the blob can be - * returned to the caller */ -void HTCSetInstance(HTC_HANDLE HTCHandle, void *Instance) -{ - HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle); - - target->pInstanceContext = Instance; -} - -/* wait for the target to arrive (sends HTC Ready message) - * this operation is fully synchronous and the message is polled for */ -A_STATUS HTCWaitTarget(HTC_HANDLE HTCHandle) -{ - HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle); - A_STATUS status; - HTC_PACKET *pPacket = NULL; - HTC_READY_MSG *pRdyMsg; - HTC_SERVICE_CONNECT_REQ connect; - HTC_SERVICE_CONNECT_RESP resp; - - AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("HTCWaitTarget - Enter (target:0x%X) \n", (A_UINT32)target)); - - do { - -#ifdef MBOXHW_UNIT_TEST - - status = DoMboxHWTest(&target->Device); - - if (status != A_OK) { - break; - } - -#endif - - /* we should be getting 1 control message that the target is ready */ - status = HTCWaitforControlMessage(target, &pPacket); - - if (A_FAILED(status)) { - AR_DEBUG_PRINTF(ATH_DEBUG_ERR, (" Target Not Available!!\n")); - break; - } - - /* we controlled the buffer creation so it has to be properly aligned */ - pRdyMsg = (HTC_READY_MSG *)pPacket->pBuffer; - - if ((pRdyMsg->MessageID != HTC_MSG_READY_ID) || - (pPacket->ActualLength < sizeof(HTC_READY_MSG))) { - /* this message is not valid */ - AR_DEBUG_ASSERT(FALSE); - status = A_EPROTO; - break; - } - - if (pRdyMsg->CreditCount == 0 || pRdyMsg->CreditSize == 0) { - /* this message is not valid */ - AR_DEBUG_ASSERT(FALSE); - status = A_EPROTO; - break; - } - - target->TargetCredits = pRdyMsg->CreditCount; - target->TargetCreditSize = pRdyMsg->CreditSize; - - AR_DEBUG_PRINTF(ATH_DEBUG_TRC, (" Target Ready: credits: %d credit size: %d\n", - target->TargetCredits, target->TargetCreditSize)); - - /* setup our pseudo HTC control endpoint connection */ - A_MEMZERO(&connect,sizeof(connect)); - A_MEMZERO(&resp,sizeof(resp)); - connect.EpCallbacks.pContext = target; - connect.EpCallbacks.EpTxComplete = HTCControlTxComplete; - connect.EpCallbacks.EpRecv = HTCControlRecv; - connect.EpCallbacks.EpRecvRefill = NULL; /* not needed */ - connect.EpCallbacks.EpSendFull = NULL; /* not needed */ - connect.EpCallbacks.EpSendAvail = NULL; /* not needed */ - connect.MaxSendQueueDepth = NUM_CONTROL_BUFFERS; - connect.ServiceID = HTC_CTRL_RSVD_SVC; - - /* connect fake service */ - status = HTCConnectService((HTC_HANDLE)target, - &connect, - &resp); - - if (!A_FAILED(status)) { - break; - } - - } while (FALSE); - - if (pPacket != NULL) { - HTC_FREE_CONTROL_RX(target,pPacket); - } - - AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("HTCWaitTarget - Exit\n")); - - return status; -} - - - -/* Start HTC, enable interrupts and let the target know host has finished setup */ -A_STATUS HTCStart(HTC_HANDLE HTCHandle) -{ - HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle); - HTC_PACKET *pPacket; - A_STATUS status; - - AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("HTCStart Enter\n")); - - /* now that we are starting, push control receive buffers into the - * HTC control endpoint */ - - while (1) { - pPacket = HTC_ALLOC_CONTROL_RX(target); - if (NULL == pPacket) { - break; - } - HTCAddReceivePkt((HTC_HANDLE)target,pPacket); - } - - do { - - AR_DEBUG_ASSERT(target->InitCredits != NULL); - AR_DEBUG_ASSERT(target->EpCreditDistributionListHead != NULL); - AR_DEBUG_ASSERT(target->EpCreditDistributionListHead->pNext != NULL); - - /* call init credits callback to do the distribution , - * NOTE: the first entry in the distribution list is ENDPOINT_0, so - * we pass the start of the list after this one. */ - target->InitCredits(target->pCredDistContext, - target->EpCreditDistributionListHead->pNext, - target->TargetCredits); - - if (AR_DEBUG_LVL_CHECK(ATH_DEBUG_TRC)) { - DumpCreditDistStates(target); - } - - /* the caller is done connecting to services, so we can indicate to the - * target that the setup phase is complete */ - status = HTCSendSetupComplete(target); - - if (A_FAILED(status)) { - break; - } - - /* unmask interrupts */ - status = DevUnmaskInterrupts(&target->Device); - - if (A_FAILED(status)) { - HTCStop(target); - } - - } while (FALSE); - - AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("HTCStart Exit\n")); - return status; -} - - -/* stop HTC communications, i.e. stop interrupt reception, and flush all queued buffers */ -void HTCStop(HTC_HANDLE HTCHandle) -{ - HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle); - AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("+HTCStop \n")); - - /* mark that we are shutting down .. */ - target->HTCStateFlags |= HTC_STATE_STOPPING; - - /* Masking interrupts is a synchronous operation, when this function returns - * all pending HIF I/O has completed, we can safely flush the queues */ - DevMaskInterrupts(&target->Device); - - /* flush all send packets */ - HTCFlushSendPkts(target); - /* flush all recv buffers */ - HTCFlushRecvBuffers(target); - - AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("-HTCStop \n")); -} - -/* undo what was done in HTCInit() */ -void HTCShutDown(void) -{ - AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("+HTCShutDown: \n")); - HTCInitialized = FALSE; - /* undo HTCInit */ - HIFShutDownDevice(NULL); - AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("-HTCShutDown: \n")); -} - -void HTCDumpCreditStates(HTC_HANDLE HTCHandle) -{ - HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle); - - LOCK_HTC_TX(target); - - DumpCreditDistStates(target); - - UNLOCK_HTC_TX(target); -} - -/* report a target failure from the device, this is a callback from the device layer - * which uses a mechanism to report errors from the target (i.e. special interrupts) */ -static void HTCReportFailure(void *Context) -{ - HTC_TARGET *target = (HTC_TARGET *)Context; - - target->TargetFailure = TRUE; - - if ((target->pInstanceContext != NULL) && (HTCInitInfo.TargetFailure != NULL)) { - /* let upper layer know, it needs to call HTCStop() */ - HTCInitInfo.TargetFailure(target->pInstanceContext, A_ERROR); - } -} - -void DebugDumpBytes(A_UCHAR *buffer, A_UINT16 length, char *pDescription) -{ - A_CHAR stream[60]; - A_UINT32 i; - A_UINT16 offset, count; - - AR_DEBUG_PRINTF(ATH_DEBUG_ANY, ("<---------Dumping %d Bytes : %s ------>\n", length, pDescription)); - - count = 0; - offset = 0; - for(i = 0; i < length; i++) { - sprintf(stream + offset, "%2.2X ", buffer[i]); - count ++; - offset += 3; - - if(count == 16) { - count = 0; - offset = 0; - AR_DEBUG_PRINTF(ATH_DEBUG_ANY, ("[H]: %s\n", stream)); - A_MEMZERO(stream, 60); - } - } - - if(offset != 0) { - AR_DEBUG_PRINTF(ATH_DEBUG_ANY, ("[H]: %s\n", stream)); - } - - AR_DEBUG_PRINTF(ATH_DEBUG_ANY, ("<------------------------------------------------->\n")); -} - -A_BOOL HTCGetEndpointStatistics(HTC_HANDLE HTCHandle, - HTC_ENDPOINT_ID Endpoint, - HTC_ENDPOINT_STAT_ACTION Action, - HTC_ENDPOINT_STATS *pStats) -{ - -#ifdef HTC_EP_STAT_PROFILING - HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle); - A_BOOL clearStats = FALSE; - A_BOOL sample = FALSE; - - switch (Action) { - case HTC_EP_STAT_SAMPLE : - sample = TRUE; - break; - case HTC_EP_STAT_SAMPLE_AND_CLEAR : - sample = TRUE; - clearStats = TRUE; - break; - case HTC_EP_STAT_CLEAR : - clearStats = TRUE; - break; - default: - break; - } - - A_ASSERT(Endpoint < ENDPOINT_MAX); - - /* lock out TX and RX while we sample and/or clear */ - LOCK_HTC_TX(target); - LOCK_HTC_RX(target); - - if (sample) { - A_ASSERT(pStats != NULL); - /* return the stats to the caller */ - A_MEMCPY(pStats, &target->EndPoint[Endpoint].EndPointStats, sizeof(HTC_ENDPOINT_STATS)); - } - - if (clearStats) { - /* reset stats */ - A_MEMZERO(&target->EndPoint[Endpoint].EndPointStats, sizeof(HTC_ENDPOINT_STATS)); - } - - UNLOCK_HTC_RX(target); - UNLOCK_HTC_TX(target); - - return TRUE; -#else - return FALSE; -#endif -} diff --git a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/htc/htc_debug.h b/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/htc/htc_debug.h deleted file mode 100644 index 08080be51..000000000 --- a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/htc/htc_debug.h +++ /dev/null @@ -1,65 +0,0 @@ -#ifndef HTC_DEBUG_H_ -#define HTC_DEBUG_H_ -/* - * - * Copyright (c) 2004-2007 Atheros Communications Inc. - * All rights reserved. - * - * - * 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; - * - * Software distributed under the License is distributed on an "AS - * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or - * implied. See the License for the specific language governing - * rights and limitations under the License. - * - * - * - */ - -/* ------- Debug related stuff ------- */ -enum { - ATH_DEBUG_SEND = 0x0001, - ATH_DEBUG_RECV = 0x0002, - ATH_DEBUG_SYNC = 0x0004, - ATH_DEBUG_DUMP = 0x0008, - ATH_DEBUG_IRQ = 0x0010, - ATH_DEBUG_TRC = 0x0020, - ATH_DEBUG_WARN = 0x0040, - ATH_DEBUG_ERR = 0x0080, - ATH_DEBUG_ANY = 0xFFFF, -}; - -#ifdef DEBUG - -// TODO FIX usage of A_PRINTF! -#define AR_DEBUG_LVL_CHECK(lvl) (debughtc & (lvl)) -#define AR_DEBUG_PRINTBUF(buffer, length, desc) do { \ - if (debughtc & ATH_DEBUG_DUMP) { \ - DebugDumpBytes(buffer, length,desc); \ - } \ -} while(0) -#define PRINTX_ARG(arg...) arg -#define AR_DEBUG_PRINTF(flags, args) do { \ - if (debughtc & (flags)) { \ - A_PRINTF(KERN_ALERT PRINTX_ARG args); \ - } \ -} while (0) -#define AR_DEBUG_ASSERT(test) do { \ - if (!(test)) { \ - AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Debug Assert Caught, File %s, Line: %d, Test:%s \n",__FILE__, __LINE__,#test)); \ - } \ -} while(0) -extern int debughtc; -#else -#define AR_DEBUG_PRINTF(flags, args) -#define AR_DEBUG_PRINTBUF(buffer, length, desc) -#define AR_DEBUG_ASSERT(test) -#define AR_DEBUG_LVL_CHECK(lvl) 0 -#endif - -void DebugDumpBytes(A_UCHAR *buffer, A_UINT16 length, char *pDescription); - -#endif /*HTC_DEBUG_H_*/ diff --git a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/htc/htc_internal.h b/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/htc/htc_internal.h deleted file mode 100644 index ebb8ac16e..000000000 --- a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/htc/htc_internal.h +++ /dev/null @@ -1,168 +0,0 @@ -/* - * - * Copyright (c) 2007 Atheros Communications Inc. - * All rights reserved. - * - * - * 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; - * - * Software distributed under the License is distributed on an "AS - * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or - * implied. See the License for the specific language governing - * rights and limitations under the License. - * - * - * - */ - -#ifndef _HTC_INTERNAL_H_ -#define _HTC_INTERNAL_H_ - -/* for debugging, uncomment this to capture the last frame header, on frame header - * processing errors, the last frame header is dump for comparison */ -//#define HTC_CAPTURE_LAST_FRAME - -//#define HTC_EP_STAT_PROFILING - -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ - -/* Header files */ -#include "a_config.h" -#include "athdefs.h" -#include "a_types.h" -#include "a_osapi.h" -#include "a_debug.h" -#include "htc.h" -#include "htc_api.h" -#include "bmi_msg.h" -#include "hif.h" -#include "ar6k.h" - -/* HTC operational parameters */ -#define HTC_TARGET_RESPONSE_TIMEOUT 2000 /* in ms */ -#define HTC_TARGET_DEBUG_INTR_MASK 0x01 -#define HTC_TARGET_CREDIT_INTR_MASK 0xF0 - -typedef struct _HTC_ENDPOINT { - HTC_SERVICE_ID ServiceID; /* service ID this endpoint is bound to - non-zero value means this endpoint is in use */ - HTC_PACKET_QUEUE TxQueue; /* HTC frame buffer TX queue */ - HTC_PACKET_QUEUE RxBuffers; /* HTC frame buffer RX list */ - HTC_ENDPOINT_CREDIT_DIST CreditDist; /* credit distribution structure (exposed to driver layer) */ - HTC_EP_CALLBACKS EpCallBacks; /* callbacks associated with this endpoint */ - int MaxTxQueueDepth; /* max depth of the TX queue before we need to - call driver's full handler */ - int CurrentTxQueueDepth; /* current TX queue depth */ - int MaxMsgLength; /* max length of endpoint message */ -#ifdef HTC_EP_STAT_PROFILING - HTC_ENDPOINT_STATS EndPointStats; /* endpoint statistics */ -#endif -} HTC_ENDPOINT; - -#ifdef HTC_EP_STAT_PROFILING -#define INC_HTC_EP_STAT(p,stat,count) (p)->EndPointStats.stat += (count); -#else -#define INC_HTC_EP_STAT(p,stat,count) -#endif - -#define HTC_SERVICE_TX_PACKET_TAG HTC_TX_PACKET_TAG_INTERNAL - -#define NUM_CONTROL_BUFFERS 8 -#define NUM_CONTROL_TX_BUFFERS 2 -#define NUM_CONTROL_RX_BUFFERS (NUM_CONTROL_BUFFERS - NUM_CONTROL_TX_BUFFERS) - -#define HTC_CONTROL_BUFFER_SIZE (HTC_MAX_CONTROL_MESSAGE_LENGTH + HTC_HDR_LENGTH) - -typedef struct HTC_CONTROL_BUFFER { - HTC_PACKET HtcPacket; - A_UINT8 Buffer[HTC_CONTROL_BUFFER_SIZE]; -} HTC_CONTROL_BUFFER; - -/* our HTC target state */ -typedef struct _HTC_TARGET { - HTC_ENDPOINT EndPoint[ENDPOINT_MAX]; - HTC_CONTROL_BUFFER HTCControlBuffers[NUM_CONTROL_BUFFERS]; - HTC_ENDPOINT_CREDIT_DIST *EpCreditDistributionListHead; - HTC_PACKET_QUEUE ControlBufferTXFreeList; - HTC_PACKET_QUEUE ControlBufferRXFreeList; - HTC_CREDIT_DIST_CALLBACK DistributeCredits; - HTC_CREDIT_INIT_CALLBACK InitCredits; - void *pCredDistContext; - int TargetCredits; - int TargetCreditSize; - A_MUTEX_T HTCLock; - A_MUTEX_T HTCRxLock; - A_MUTEX_T HTCTxLock; - AR6K_DEVICE Device; /* AR6K - specific state */ - A_UINT32 HTCStateFlags; - HTC_ENDPOINT_ID EpWaitingForBuffers; - A_BOOL TargetFailure; - void *pInstanceContext; -#define HTC_STATE_WAIT_BUFFERS (1 << 0) -#define HTC_STATE_STOPPING (1 << 1) -#ifdef HTC_CAPTURE_LAST_FRAME - HTC_FRAME_HDR LastFrameHdr; /* useful for debugging */ - A_UINT8 LastTrailer[256]; - A_UINT8 LastTrailerLength; -#endif -} HTC_TARGET; - -#define HTC_STOPPING(t) ((t)->HTCStateFlags & HTC_STATE_STOPPING) -#define LOCK_HTC(t) A_MUTEX_LOCK(&(t)->HTCLock); -#define UNLOCK_HTC(t) A_MUTEX_UNLOCK(&(t)->HTCLock); -#define LOCK_HTC_RX(t) A_MUTEX_LOCK(&(t)->HTCRxLock); -#define UNLOCK_HTC_RX(t) A_MUTEX_UNLOCK(&(t)->HTCRxLock); -#define LOCK_HTC_TX(t) A_MUTEX_LOCK(&(t)->HTCTxLock); -#define UNLOCK_HTC_TX(t) A_MUTEX_UNLOCK(&(t)->HTCTxLock); - -#define GET_HTC_TARGET_FROM_HANDLE(hnd) ((HTC_TARGET *)(hnd)) -#define HTC_RECYCLE_RX_PKT(target,p) \ -{ \ - HTC_PACKET_RESET_RX(pPacket); \ - HTCAddReceivePkt((HTC_HANDLE)(target),(p)); \ -} - -/* internal HTC functions */ -void HTCControlTxComplete(void *Context, HTC_PACKET *pPacket); -void HTCControlRecv(void *Context, HTC_PACKET *pPacket); -A_STATUS HTCWaitforControlMessage(HTC_TARGET *target, HTC_PACKET **ppControlPacket); -HTC_PACKET *HTCAllocControlBuffer(HTC_TARGET *target, HTC_PACKET_QUEUE *pList); -void HTCFreeControlBuffer(HTC_TARGET *target, HTC_PACKET *pPacket, HTC_PACKET_QUEUE *pList); -A_STATUS HTCIssueSend(HTC_TARGET *target, HTC_PACKET *pPacket, A_UINT8 Flags); -A_STATUS HTCIssueRecv(HTC_TARGET *target, HTC_PACKET *pPacket); -void HTCRecvCompleteHandler(void *Context, HTC_PACKET *pPacket); -A_STATUS HTCRecvMessagePendingHandler(void *Context, A_UINT32 LookAhead, A_BOOL *pAsyncProc); -void HTCProcessCreditRpt(HTC_TARGET *target, HTC_CREDIT_REPORT *pRpt, int NumEntries, HTC_ENDPOINT_ID FromEndpoint); -A_STATUS HTCSendSetupComplete(HTC_TARGET *target); -void HTCFlushRecvBuffers(HTC_TARGET *target); -void HTCFlushSendPkts(HTC_TARGET *target); -void DumpCreditDist(HTC_ENDPOINT_CREDIT_DIST *pEPDist); -void DumpCreditDistStates(HTC_TARGET *target); -void DebugDumpBytes(A_UCHAR *buffer, A_UINT16 length, char *pDescription); - -static INLINE HTC_PACKET *HTC_ALLOC_CONTROL_TX(HTC_TARGET *target) { - HTC_PACKET *pPacket = HTCAllocControlBuffer(target,&target->ControlBufferTXFreeList); - if (pPacket != NULL) { - /* set payload pointer area with some headroom */ - pPacket->pBuffer = pPacket->pBufferStart + HTC_HDR_LENGTH; - } - return pPacket; -} - -#define HTC_FREE_CONTROL_TX(t,p) HTCFreeControlBuffer((t),(p),&(t)->ControlBufferTXFreeList) -#define HTC_ALLOC_CONTROL_RX(t) HTCAllocControlBuffer((t),&(t)->ControlBufferRXFreeList) -#define HTC_FREE_CONTROL_RX(t,p) \ -{ \ - HTC_PACKET_RESET_RX(p); \ - HTCFreeControlBuffer((t),(p),&(t)->ControlBufferRXFreeList); \ -} - -#ifdef __cplusplus -} -#endif - -#endif /* _HTC_INTERNAL_H_ */ diff --git a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/htc/htc_recv.c b/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/htc/htc_recv.c deleted file mode 100644 index 4be2b0833..000000000 --- a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/htc/htc_recv.c +++ /dev/null @@ -1,703 +0,0 @@ -/* - * - * Copyright (c) 2007 Atheros Communications Inc. - * All rights reserved. - * - * - * 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; - * - * Software distributed under the License is distributed on an "AS - * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or - * implied. See the License for the specific language governing - * rights and limitations under the License. - * - * - * - */ - -#include "htc_internal.h" - -#define HTCIssueRecv(t, p) \ - DevRecvPacket(&(t)->Device, \ - (p), \ - (p)->ActualLength) - -#define DO_RCV_COMPLETION(t,p,e) \ -{ \ - if ((p)->ActualLength > 0) { \ - AR_DEBUG_PRINTF(ATH_DEBUG_RECV, (" completing packet 0x%X (%d bytes) on ep : %d \n", \ - (A_UINT32)(p), (p)->ActualLength, (p)->Endpoint)); \ - (e)->EpCallBacks.EpRecv((e)->EpCallBacks.pContext, \ - (p)); \ - } else { \ - AR_DEBUG_PRINTF(ATH_DEBUG_RECV, (" recycling empty packet \n")); \ - HTC_RECYCLE_RX_PKT((t), (p)); \ - } \ -} - -#ifdef HTC_EP_STAT_PROFILING -#define HTC_RX_STAT_PROFILE(t,ep,lookAhead) \ -{ \ - LOCK_HTC_RX((t)); \ - INC_HTC_EP_STAT((ep), RxReceived, 1); \ - if ((lookAhead) != 0) { \ - INC_HTC_EP_STAT((ep), RxLookAheads, 1); \ - } \ - UNLOCK_HTC_RX((t)); \ -} -#else -#define HTC_RX_STAT_PROFILE(t,ep,lookAhead) -#endif - -static INLINE A_STATUS HTCProcessTrailer(HTC_TARGET *target, - A_UINT8 *pBuffer, - int Length, - A_UINT32 *pNextLookAhead, - HTC_ENDPOINT_ID FromEndpoint) -{ - HTC_RECORD_HDR *pRecord; - A_UINT8 *pRecordBuf; - HTC_LOOKAHEAD_REPORT *pLookAhead; - A_UINT8 *pOrigBuffer; - int origLength; - A_STATUS status; - - AR_DEBUG_PRINTF(ATH_DEBUG_RECV, ("+HTCProcessTrailer (length:%d) \n", Length)); - - if (AR_DEBUG_LVL_CHECK(ATH_DEBUG_RECV)) { - AR_DEBUG_PRINTBUF(pBuffer,Length,"Recv Trailer"); - } - - pOrigBuffer = pBuffer; - origLength = Length; - status = A_OK; - - while (Length > 0) { - - if (Length < sizeof(HTC_RECORD_HDR)) { - status = A_EPROTO; - break; - } - /* these are byte aligned structs */ - pRecord = (HTC_RECORD_HDR *)pBuffer; - Length -= sizeof(HTC_RECORD_HDR); - pBuffer += sizeof(HTC_RECORD_HDR); - - if (pRecord->Length > Length) { - /* no room left in buffer for record */ - AR_DEBUG_PRINTF(ATH_DEBUG_ERR, - (" invalid record length: %d (id:%d) buffer has: %d bytes left \n", - pRecord->Length, pRecord->RecordID, Length)); - status = A_EPROTO; - break; - } - /* start of record follows the header */ - pRecordBuf = pBuffer; - - switch (pRecord->RecordID) { - case HTC_RECORD_CREDITS: - AR_DEBUG_ASSERT(pRecord->Length >= sizeof(HTC_CREDIT_REPORT)); - HTCProcessCreditRpt(target, - (HTC_CREDIT_REPORT *)pRecordBuf, - pRecord->Length / (sizeof(HTC_CREDIT_REPORT)), - FromEndpoint); - break; - case HTC_RECORD_LOOKAHEAD: - AR_DEBUG_ASSERT(pRecord->Length >= sizeof(HTC_LOOKAHEAD_REPORT)); - pLookAhead = (HTC_LOOKAHEAD_REPORT *)pRecordBuf; - if ((pLookAhead->PreValid == ((~pLookAhead->PostValid) & 0xFF)) && - (pNextLookAhead != NULL)) { - - AR_DEBUG_PRINTF(ATH_DEBUG_RECV, - (" LookAhead Report Found (pre valid:0x%X, post valid:0x%X) \n", - pLookAhead->PreValid, - pLookAhead->PostValid)); - - /* look ahead bytes are valid, copy them over */ - ((A_UINT8 *)pNextLookAhead)[0] = pLookAhead->LookAhead[0]; - ((A_UINT8 *)pNextLookAhead)[1] = pLookAhead->LookAhead[1]; - ((A_UINT8 *)pNextLookAhead)[2] = pLookAhead->LookAhead[2]; - ((A_UINT8 *)pNextLookAhead)[3] = pLookAhead->LookAhead[3]; - - if (AR_DEBUG_LVL_CHECK(ATH_DEBUG_RECV)) { - DebugDumpBytes((A_UINT8 *)pNextLookAhead,4,"Next Look Ahead"); - } - } - break; - default: - AR_DEBUG_PRINTF(ATH_DEBUG_ERR, (" unhandled record: id:%d length:%d \n", - pRecord->RecordID, pRecord->Length)); - break; - } - - if (A_FAILED(status)) { - break; - } - - /* advance buffer past this record for next time around */ - pBuffer += pRecord->Length; - Length -= pRecord->Length; - } - - if (A_FAILED(status)) { - DebugDumpBytes(pOrigBuffer,origLength,"BAD Recv Trailer"); - } - - AR_DEBUG_PRINTF(ATH_DEBUG_RECV, ("-HTCProcessTrailer \n")); - return status; - -} - -/* process a received message (i.e. strip off header, process any trailer data) - * note : locks must be released when this function is called */ -static A_STATUS HTCProcessRecvHeader(HTC_TARGET *target, HTC_PACKET *pPacket, A_UINT32 *pNextLookAhead) -{ - A_UINT8 temp; - A_UINT8 *pBuf; - A_STATUS status = A_OK; - A_UINT16 payloadLen; - A_UINT32 lookAhead; - - pBuf = pPacket->pBuffer; - - AR_DEBUG_PRINTF(ATH_DEBUG_RECV, ("+HTCProcessRecvHeader \n")); - - if (AR_DEBUG_LVL_CHECK(ATH_DEBUG_RECV)) { - AR_DEBUG_PRINTBUF(pBuf,pPacket->ActualLength,"HTC Recv PKT"); - } - - do { - /* note, we cannot assume the alignment of pBuffer, so we use the safe macros to - * retrieve 16 bit fields */ - payloadLen = A_GET_UINT16_FIELD(pBuf, HTC_FRAME_HDR, PayloadLen); - - ((A_UINT8 *)&lookAhead)[0] = pBuf[0]; - ((A_UINT8 *)&lookAhead)[1] = pBuf[1]; - ((A_UINT8 *)&lookAhead)[2] = pBuf[2]; - ((A_UINT8 *)&lookAhead)[3] = pBuf[3]; - - if (lookAhead != pPacket->HTCReserved) { - /* somehow the lookahead that gave us the full read length did not - * reflect the actual header in the pending message */ - AR_DEBUG_PRINTF(ATH_DEBUG_ERR, - ("HTCProcessRecvHeader, lookahead mismatch! \n")); - DebugDumpBytes((A_UINT8 *)&pPacket->HTCReserved,4,"Expected Message LookAhead"); - DebugDumpBytes(pBuf,sizeof(HTC_FRAME_HDR),"Current Frame Header"); -#ifdef HTC_CAPTURE_LAST_FRAME - DebugDumpBytes((A_UINT8 *)&target->LastFrameHdr,sizeof(HTC_FRAME_HDR),"Last Frame Header"); - if (target->LastTrailerLength != 0) { - DebugDumpBytes(target->LastTrailer, - target->LastTrailerLength, - "Last trailer"); - } -#endif - status = A_EPROTO; - break; - } - - /* get flags */ - temp = A_GET_UINT8_FIELD(pBuf, HTC_FRAME_HDR, Flags); - - if (temp & HTC_FLAGS_RECV_TRAILER) { - /* this packet has a trailer */ - - /* extract the trailer length in control byte 0 */ - temp = A_GET_UINT8_FIELD(pBuf, HTC_FRAME_HDR, ControlBytes[0]); - - if ((temp < sizeof(HTC_RECORD_HDR)) || (temp > payloadLen)) { - AR_DEBUG_PRINTF(ATH_DEBUG_ERR, - ("HTCProcessRecvHeader, invalid header (payloadlength should be :%d, CB[0] is:%d) \n", - payloadLen, temp)); - status = A_EPROTO; - break; - } - - /* process trailer data that follows HDR + application payload */ - status = HTCProcessTrailer(target, - (pBuf + HTC_HDR_LENGTH + payloadLen - temp), - temp, - pNextLookAhead, - pPacket->Endpoint); - - if (A_FAILED(status)) { - break; - } - -#ifdef HTC_CAPTURE_LAST_FRAME - A_MEMCPY(target->LastTrailer, (pBuf + HTC_HDR_LENGTH + payloadLen - temp), temp); - target->LastTrailerLength = temp; -#endif - /* trim length by trailer bytes */ - pPacket->ActualLength -= temp; - } -#ifdef HTC_CAPTURE_LAST_FRAME - else { - target->LastTrailerLength = 0; - } -#endif - - /* if we get to this point, the packet is good */ - /* remove header and adjust length */ - pPacket->pBuffer += HTC_HDR_LENGTH; - pPacket->ActualLength -= HTC_HDR_LENGTH; - - } while (FALSE); - - if (A_FAILED(status)) { - /* dump the whole packet */ - DebugDumpBytes(pBuf,pPacket->ActualLength,"BAD HTC Recv PKT"); - } else { -#ifdef HTC_CAPTURE_LAST_FRAME - A_MEMCPY(&target->LastFrameHdr,pBuf,sizeof(HTC_FRAME_HDR)); -#endif - if (AR_DEBUG_LVL_CHECK(ATH_DEBUG_RECV)) { - if (pPacket->ActualLength > 0) { - AR_DEBUG_PRINTBUF(pPacket->pBuffer,pPacket->ActualLength,"HTC - Application Msg"); - } - } - } - - AR_DEBUG_PRINTF(ATH_DEBUG_RECV, ("-HTCProcessRecvHeader \n")); - return status; -} - -/* asynchronous completion handler for recv packet fetching, when the device layer - * completes a read request, it will call this completion handler */ -void HTCRecvCompleteHandler(void *Context, HTC_PACKET *pPacket) -{ - HTC_TARGET *target = (HTC_TARGET *)Context; - HTC_ENDPOINT *pEndpoint; - A_UINT32 nextLookAhead = 0; - A_STATUS status; - - AR_DEBUG_PRINTF(ATH_DEBUG_RECV, ("+HTCRecvCompleteHandler (status:%d, ep:%d) \n", - pPacket->Status, pPacket->Endpoint)); - - AR_DEBUG_ASSERT(pPacket->Endpoint < ENDPOINT_MAX); - pEndpoint = &target->EndPoint[pPacket->Endpoint]; - pPacket->Completion = NULL; - - /* get completion status */ - status = pPacket->Status; - - do { - if (A_FAILED(status)) { - AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("HTCRecvCompleteHandler: request failed (status:%d, ep:%d) \n", - pPacket->Status, pPacket->Endpoint)); - break; - } - /* process the header for any trailer data */ - status = HTCProcessRecvHeader(target,pPacket,&nextLookAhead); - - if (A_FAILED(status)) { - break; - } - /* was there a lookahead for the next packet? */ - if (nextLookAhead != 0) { - A_STATUS nextStatus; - AR_DEBUG_PRINTF(ATH_DEBUG_RECV, - ("HTCRecvCompleteHandler - next look ahead was non-zero : 0x%X \n", - nextLookAhead)); - /* we have another packet, get the next packet fetch started (pipelined) before - * we call into the endpoint's callback, this will start another async request */ - nextStatus = HTCRecvMessagePendingHandler(target,nextLookAhead,NULL); - if (A_EPROTO == nextStatus) { - AR_DEBUG_PRINTF(ATH_DEBUG_ERR, - ("Next look ahead from recv header was INVALID\n")); - DebugDumpBytes((A_UINT8 *)&nextLookAhead, - 4, - "BAD lookahead from lookahead report"); - } - } else { - AR_DEBUG_PRINTF(ATH_DEBUG_RECV, - ("HTCRecvCompleteHandler - rechecking for more messages...\n")); - /* if we did not get anything on the look-ahead, - * call device layer to asynchronously re-check for messages. If we can keep the async - * processing going we get better performance. If there is a pending message we will keep processing - * messages asynchronously which should pipeline things nicely */ - DevCheckPendingRecvMsgsAsync(&target->Device); - } - - HTC_RX_STAT_PROFILE(target,pEndpoint,nextLookAhead); - DO_RCV_COMPLETION(target,pPacket,pEndpoint); - - } while (FALSE); - - if (A_FAILED(status)) { - AR_DEBUG_PRINTF(ATH_DEBUG_ERR, - ("HTCRecvCompleteHandler , message fetch failed (status = %d) \n", - status)); - /* recyle this packet */ - HTC_RECYCLE_RX_PKT(target, pPacket); - } - - AR_DEBUG_PRINTF(ATH_DEBUG_RECV, ("-HTCRecvCompleteHandler\n")); -} - -/* synchronously wait for a control message from the target, - * This function is used at initialization time ONLY. At init messages - * on ENDPOINT 0 are expected. */ -A_STATUS HTCWaitforControlMessage(HTC_TARGET *target, HTC_PACKET **ppControlPacket) -{ - A_STATUS status; - A_UINT32 lookAhead; - HTC_PACKET *pPacket = NULL; - HTC_FRAME_HDR *pHdr; - - AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("+HTCWaitforControlMessage \n")); - - do { - - *ppControlPacket = NULL; - - /* call the polling function to see if we have a message */ - status = DevPollMboxMsgRecv(&target->Device, - &lookAhead, - HTC_TARGET_RESPONSE_TIMEOUT); - - if (A_FAILED(status)) { - break; - } - - AR_DEBUG_PRINTF(ATH_DEBUG_RECV, - ("HTCWaitforControlMessage : lookAhead : 0x%X \n", lookAhead)); - - /* check the lookahead */ - pHdr = (HTC_FRAME_HDR *)&lookAhead; - - if (pHdr->EndpointID != ENDPOINT_0) { - /* unexpected endpoint number, should be zero */ - AR_DEBUG_ASSERT(FALSE); - status = A_EPROTO; - break; - } - - if (A_FAILED(status)) { - /* bad message */ - AR_DEBUG_ASSERT(FALSE); - status = A_EPROTO; - break; - } - - pPacket = HTC_ALLOC_CONTROL_RX(target); - - if (pPacket == NULL) { - AR_DEBUG_ASSERT(FALSE); - status = A_NO_MEMORY; - break; - } - - pPacket->HTCReserved = lookAhead; - pPacket->ActualLength = pHdr->PayloadLen + HTC_HDR_LENGTH; - - if (pPacket->ActualLength > pPacket->BufferLength) { - AR_DEBUG_ASSERT(FALSE); - status = A_EPROTO; - break; - } - - /* we want synchronous operation */ - pPacket->Completion = NULL; - - /* get the message from the device, this will block */ - status = HTCIssueRecv(target, pPacket); - - if (A_FAILED(status)) { - break; - } - - /* process receive header */ - status = HTCProcessRecvHeader(target,pPacket,NULL); - - pPacket->Status = status; - - if (A_FAILED(status)) { - AR_DEBUG_PRINTF(ATH_DEBUG_ERR, - ("HTCWaitforControlMessage, HTCProcessRecvHeader failed (status = %d) \n", - status)); - break; - } - - /* give the caller this control message packet, they are responsible to free */ - *ppControlPacket = pPacket; - - } while (FALSE); - - if (A_FAILED(status)) { - if (pPacket != NULL) { - /* cleanup buffer on error */ - HTC_FREE_CONTROL_RX(target,pPacket); - } - } - - AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("-HTCWaitforControlMessage \n")); - - return status; -} - -/* callback when device layer or lookahead report parsing detects a pending message */ -A_STATUS HTCRecvMessagePendingHandler(void *Context, A_UINT32 LookAhead, A_BOOL *pAsyncProc) -{ - HTC_TARGET *target = (HTC_TARGET *)Context; - A_STATUS status = A_OK; - HTC_PACKET *pPacket = NULL; - HTC_FRAME_HDR *pHdr; - HTC_ENDPOINT *pEndpoint; - A_BOOL asyncProc = FALSE; - - AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("+HTCRecvMessagePendingHandler LookAhead:0x%X \n",LookAhead)); - - if (IS_DEV_IRQ_PROCESSING_ASYNC_ALLOWED(&target->Device)) { - /* We use async mode to get the packets if the device layer supports it. - * The device layer interfaces with HIF in which HIF may have restrictions on - * how interrupts are processed */ - asyncProc = TRUE; - } - - if (pAsyncProc != NULL) { - /* indicate to caller how we decided to process this */ - *pAsyncProc = asyncProc; - } - - while (TRUE) { - - pHdr = (HTC_FRAME_HDR *)&LookAhead; - - if (pHdr->EndpointID >= ENDPOINT_MAX) { - AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Invalid Endpoint in look-ahead: %d \n",pHdr->EndpointID)); - /* invalid endpoint */ - status = A_EPROTO; - break; - } - - if (pHdr->PayloadLen > HTC_MAX_PAYLOAD_LENGTH) { - AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Payload length %d exceeds max HTC : %d !\n", - pHdr->PayloadLen, HTC_MAX_PAYLOAD_LENGTH)); - status = A_EPROTO; - break; - } - - pEndpoint = &target->EndPoint[pHdr->EndpointID]; - - if (0 == pEndpoint->ServiceID) { - AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Endpoint %d is not connected !\n",pHdr->EndpointID)); - /* endpoint isn't even connected */ - status = A_EPROTO; - break; - } - - /* lock RX to get a buffer */ - LOCK_HTC_RX(target); - - /* get a packet from the endpoint recv queue */ - pPacket = HTC_PACKET_DEQUEUE(&pEndpoint->RxBuffers); - - if (NULL == pPacket) { - /* check for refill handler */ - if (pEndpoint->EpCallBacks.EpRecvRefill != NULL) { - UNLOCK_HTC_RX(target); - /* call the re-fill handler */ - pEndpoint->EpCallBacks.EpRecvRefill(pEndpoint->EpCallBacks.pContext, - pHdr->EndpointID); - LOCK_HTC_RX(target); - /* check if we have more buffers */ - pPacket = HTC_PACKET_DEQUEUE(&pEndpoint->RxBuffers); - /* fall through */ - } - } - - if (NULL == pPacket) { - /* this is not an error, we simply need to mark that we are waiting for buffers.*/ - target->HTCStateFlags |= HTC_STATE_WAIT_BUFFERS; - target->EpWaitingForBuffers = pHdr->EndpointID; - status = A_NO_MEMORY; - } - - UNLOCK_HTC_RX(target); - - if (A_FAILED(status)) { - /* no buffers */ - break; - } - - AR_DEBUG_ASSERT(pPacket->Endpoint == pHdr->EndpointID); - - /* make sure this message can fit in the endpoint buffer */ - if ((pHdr->PayloadLen + HTC_HDR_LENGTH) > pPacket->BufferLength) { - AR_DEBUG_PRINTF(ATH_DEBUG_ERR, - ("Payload Length Error : header reports payload of: %d, endpoint buffer size: %d \n", - pHdr->PayloadLen, pPacket->BufferLength)); - status = A_EPROTO; - break; - } - - pPacket->HTCReserved = LookAhead; /* set expected look ahead */ - /* set the amount of data to fetch */ - pPacket->ActualLength = pHdr->PayloadLen + HTC_HDR_LENGTH; - - if (asyncProc) { - /* we use async mode to get the packet if the device layer supports it - * set our callback and context */ - pPacket->Completion = HTCRecvCompleteHandler; - pPacket->pContext = target; - } else { - /* fully synchronous */ - pPacket->Completion = NULL; - } - - /* go fetch the packet */ - status = HTCIssueRecv(target, pPacket); - - if (A_FAILED(status)) { - break; - } - - if (asyncProc) { - /* we did this asynchronously so we can get out of the loop, the asynch processing - * creates a chain of requests to continue processing pending messages in the - * context of callbacks */ - break; - } - - /* in the sync case, we process the packet, check lookaheads and then repeat */ - - LookAhead = 0; - status = HTCProcessRecvHeader(target,pPacket,&LookAhead); - - if (A_FAILED(status)) { - break; - } - - HTC_RX_STAT_PROFILE(target,pEndpoint,LookAhead); - DO_RCV_COMPLETION(target,pPacket,pEndpoint); - - pPacket = NULL; - - if (0 == LookAhead) { - break; - } - - } - - if (A_NO_MEMORY == status) { - AR_DEBUG_PRINTF(ATH_DEBUG_ERR, - (" Endpoint :%d has no buffers, blocking receiver to prevent overrun.. \n", - pHdr->EndpointID)); - /* try to stop receive at the device layer */ - DevStopRecv(&target->Device, asyncProc ? DEV_STOP_RECV_ASYNC : DEV_STOP_RECV_SYNC); - status = A_OK; - } else if (A_FAILED(status)) { - AR_DEBUG_PRINTF(ATH_DEBUG_ERR, - ("Failed to get pending message : LookAhead Value: 0x%X (status = %d) \n", - LookAhead, status)); - if (pPacket != NULL) { - /* clean up packet on error */ - HTC_RECYCLE_RX_PKT(target, pPacket); - } - } - - AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("-HTCRecvMessagePendingHandler \n")); - - return status; -} - -/* Makes a buffer available to the HTC module */ -A_STATUS HTCAddReceivePkt(HTC_HANDLE HTCHandle, HTC_PACKET *pPacket) -{ - HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle); - HTC_ENDPOINT *pEndpoint; - A_BOOL unblockRecv = FALSE; - A_STATUS status = A_OK; - - AR_DEBUG_PRINTF(ATH_DEBUG_SEND, - ("+- HTCAddReceivePkt: endPointId: %d, buffer: 0x%X, length: %d\n", - pPacket->Endpoint, (A_UINT32)pPacket->pBuffer, pPacket->BufferLength)); - - do { - - if (HTC_STOPPING(target)) { - status = A_ECANCELED; - break; - } - - AR_DEBUG_ASSERT(pPacket->Endpoint < ENDPOINT_MAX); - - pEndpoint = &target->EndPoint[pPacket->Endpoint]; - - LOCK_HTC_RX(target); - - /* store receive packet */ - HTC_PACKET_ENQUEUE(&pEndpoint->RxBuffers, pPacket); - - /* check if we are blocked waiting for a new buffer */ - if (target->HTCStateFlags & HTC_STATE_WAIT_BUFFERS) { - if (target->EpWaitingForBuffers == pPacket->Endpoint) { - AR_DEBUG_PRINTF(ATH_DEBUG_RECV,(" receiver was blocked on ep:%d, unblocking.. \n", - target->EpWaitingForBuffers)); - target->HTCStateFlags &= ~HTC_STATE_WAIT_BUFFERS; - target->EpWaitingForBuffers = ENDPOINT_MAX; - unblockRecv = TRUE; - } - } - - UNLOCK_HTC_RX(target); - - if (unblockRecv && !HTC_STOPPING(target)) { - /* TODO : implement a buffer threshold count? */ - DevEnableRecv(&target->Device,DEV_ENABLE_RECV_SYNC); - } - - } while (FALSE); - - return status; -} - -static void HTCFlushEndpointRX(HTC_TARGET *target, HTC_ENDPOINT *pEndpoint) -{ - HTC_PACKET *pPacket; - - LOCK_HTC_RX(target); - - while (1) { - pPacket = HTC_PACKET_DEQUEUE(&pEndpoint->RxBuffers); - if (NULL == pPacket) { - break; - } - UNLOCK_HTC_RX(target); - pPacket->Status = A_ECANCELED; - pPacket->ActualLength = 0; - AR_DEBUG_PRINTF(ATH_DEBUG_RECV, (" Flushing RX packet:0x%X, length:%d, ep:%d \n", - (A_UINT32)pPacket, pPacket->BufferLength, pPacket->Endpoint)); - /* give the packet back */ - pEndpoint->EpCallBacks.EpRecv(pEndpoint->EpCallBacks.pContext, - pPacket); - LOCK_HTC_RX(target); - } - - UNLOCK_HTC_RX(target); - - -} - -void HTCFlushRecvBuffers(HTC_TARGET *target) -{ - HTC_ENDPOINT *pEndpoint; - int i; - - /* NOTE: no need to flush endpoint 0, these buffers were - * allocated as part of the HTC struct */ - for (i = ENDPOINT_1; i < ENDPOINT_MAX; i++) { - pEndpoint = &target->EndPoint[i]; - if (pEndpoint->ServiceID == 0) { - /* not in use.. */ - continue; - } - HTCFlushEndpointRX(target,pEndpoint); - } - - -} - - diff --git a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/htc/htc_send.c b/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/htc/htc_send.c deleted file mode 100644 index cf0dabef4..000000000 --- a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/htc/htc_send.c +++ /dev/null @@ -1,538 +0,0 @@ -/* - * - * Copyright (c) 2007 Atheros Communications Inc. - * All rights reserved. - * - * - * 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; - * - * Software distributed under the License is distributed on an "AS - * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or - * implied. See the License for the specific language governing - * rights and limitations under the License. - * - * - * - */ - -#include "htc_internal.h" - -#define DO_EP_TX_COMPLETION(ep,p) \ -{ \ - (p)->Completion = NULL; \ - (ep)->EpCallBacks.EpTxComplete((ep)->EpCallBacks.pContext,(p)); \ -} - - -/* call the distribute credits callback with the distribution */ -#define DO_DISTRIBUTION(t,reason,description,pList) \ -{ \ - AR_DEBUG_PRINTF(ATH_DEBUG_SEND, \ - (" calling distribute function (%s) (dfn:0x%X, ctxt:0x%X, dist:0x%X) \n", \ - (description), \ - (A_UINT32)(t)->DistributeCredits, \ - (A_UINT32)(t)->pCredDistContext, \ - (A_UINT32)pList)); \ - (t)->DistributeCredits((t)->pCredDistContext, \ - (pList), \ - (reason)); \ -} - -/* our internal send packet completion handler when packets are submited to the AR6K device - * layer */ -static void HTCSendPktCompletionHandler(void *Context, HTC_PACKET *pPacket) -{ - HTC_TARGET *target = (HTC_TARGET *)Context; - HTC_ENDPOINT *pEndpoint = &target->EndPoint[pPacket->Endpoint]; - - - if (A_FAILED(pPacket->Status)) { - AR_DEBUG_PRINTF(ATH_DEBUG_ERR, - ("HTCSendPktCompletionHandler: request failed (status:%d, ep:%d) \n", - pPacket->Status, pPacket->Endpoint)); - } - /* first, fixup the head room we allocated */ - pPacket->pBuffer += HTC_HDR_LENGTH; - /* do completion */ - DO_EP_TX_COMPLETION(pEndpoint,pPacket); -} - -A_STATUS HTCIssueSend(HTC_TARGET *target, HTC_PACKET *pPacket, A_UINT8 SendFlags) -{ - A_STATUS status; - A_UINT8 *pHdrBuf; - A_BOOL sync = FALSE; - - /* caller always provides headrooom */ - pPacket->pBuffer -= HTC_HDR_LENGTH; - pHdrBuf = pPacket->pBuffer; - /* setup frame header */ - A_SET_UINT16_FIELD(pHdrBuf,HTC_FRAME_HDR,PayloadLen,(A_UINT16)pPacket->ActualLength); - A_SET_UINT8_FIELD(pHdrBuf,HTC_FRAME_HDR,Flags,SendFlags); - A_SET_UINT8_FIELD(pHdrBuf,HTC_FRAME_HDR,EndpointID, (A_UINT8)pPacket->Endpoint); - - if (pPacket->Completion == NULL) { - /* mark that this request was synchronously issued */ - sync = TRUE; - } - - AR_DEBUG_PRINTF(ATH_DEBUG_SEND, - ("+-HTCIssueSend: transmit length : %d (%s) \n", - pPacket->ActualLength + HTC_HDR_LENGTH, - sync ? "SYNC" : "ASYNC" )); - - /* send message to device */ - status = DevSendPacket(&target->Device, - pPacket, - pPacket->ActualLength + HTC_HDR_LENGTH); - - if (sync) { - /* use local sync variable. If this was issued asynchronously, pPacket is no longer - * safe to access. */ - pPacket->pBuffer += HTC_HDR_LENGTH; - } - - /* if this request was asynchronous, the packet completion routine will be invoked by - * the device layer when the HIF layer completes the request */ - - return status; -} - -/* try to send the current packet or a packet at the head of the TX queue, - * if there are no credits, the packet remains in the queue. */ -static void HTCTrySend(HTC_TARGET *target, - HTC_PACKET *pPacketToSend, - HTC_ENDPOINT_ID ep) -{ - HTC_PACKET *pPacket; - HTC_ENDPOINT *pEndpoint; - int creditsRequired; - A_UINT8 sendFlags; - - AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("+HTCTrySend (pPkt:0x%X)\n",(A_UINT32)pPacketToSend)); - - pEndpoint = &target->EndPoint[ep]; - - LOCK_HTC_TX(target); - - if (pPacketToSend != NULL) { - /* caller supplied us a packet to queue to the tail of the HTC TX queue before - * we check the tx queue */ - HTC_PACKET_ENQUEUE(&pEndpoint->TxQueue,pPacketToSend); - pEndpoint->CurrentTxQueueDepth++; - } - - /* now drain the TX queue for transmission as long as we have enough - * credits */ - - while (1) { - - if (HTC_QUEUE_EMPTY(&pEndpoint->TxQueue)) { - /* nothing in the queue */ - break; - } - - sendFlags = 0; - - /* get packet at head, but don't remove it */ - pPacket = HTC_GET_PKT_AT_HEAD(&pEndpoint->TxQueue); - AR_DEBUG_PRINTF(ATH_DEBUG_SEND,(" Got head packet:0x%X , Queue Depth: %d\n", - (A_UINT32)pPacket, pEndpoint->CurrentTxQueueDepth)); - - /* figure out how many credits this message requires */ - creditsRequired = pPacket->ActualLength + HTC_HDR_LENGTH; - creditsRequired += target->TargetCreditSize - 1; - creditsRequired /= target->TargetCreditSize; - - AR_DEBUG_PRINTF(ATH_DEBUG_SEND,(" Creds Required:%d Got:%d\n", - creditsRequired, pEndpoint->CreditDist.TxCredits)); - - if (pEndpoint->CreditDist.TxCredits < creditsRequired) { - - /* not enough credits */ - - if (pPacket->Endpoint == ENDPOINT_0) { - /* leave it in the queue */ - break; - } - /* invoke the registered distribution function only if this is not - * endpoint 0, we let the driver layer provide more credits if it can. - * We pass the credit distribution list starting at the endpoint in question - * */ - - /* set how many credits we need */ - pEndpoint->CreditDist.TxCreditsSeek = - creditsRequired - pEndpoint->CreditDist.TxCredits; - DO_DISTRIBUTION(target, - HTC_CREDIT_DIST_SEEK_CREDITS, - "Seek Credits", - &pEndpoint->CreditDist); - - pEndpoint->CreditDist.TxCreditsSeek = 0; - - if (pEndpoint->CreditDist.TxCredits < creditsRequired) { - /* still not enough credits to send, leave packet in the queue */ - AR_DEBUG_PRINTF(ATH_DEBUG_SEND, - (" Not enough credits for ep %d leaving packet in queue..\n", - pPacket->Endpoint)); - break; - } - - } - - pEndpoint->CreditDist.TxCredits -= creditsRequired; - INC_HTC_EP_STAT(pEndpoint, TxCreditsConsummed, creditsRequired); - - /* check if we need credits */ - if (pEndpoint->CreditDist.TxCredits < pEndpoint->CreditDist.TxCreditsPerMaxMsg) { - sendFlags |= HTC_FLAGS_NEED_CREDIT_UPDATE; - INC_HTC_EP_STAT(pEndpoint, TxCreditLowIndications, 1); - AR_DEBUG_PRINTF(ATH_DEBUG_SEND,(" Host Needs Credits \n")); - } - - /* now we can fully dequeue */ - pPacket = HTC_PACKET_DEQUEUE(&pEndpoint->TxQueue); - pEndpoint->CurrentTxQueueDepth--; - - INC_HTC_EP_STAT(pEndpoint, TxIssued, 1); - - UNLOCK_HTC_TX(target); - - HTCIssueSend(target, pPacket, sendFlags); - - LOCK_HTC_TX(target); - - /* go back and check for more messages */ - } - - if (pEndpoint->CurrentTxQueueDepth >= pEndpoint->MaxTxQueueDepth) { - AR_DEBUG_PRINTF(ATH_DEBUG_SEND, (" Endpoint %d, TX queue is full, Depth:%d, Max:%d \n", - ep, pEndpoint->CurrentTxQueueDepth, pEndpoint->MaxTxQueueDepth)); - UNLOCK_HTC_TX(target); - /* queue is now full, let caller know */ - if (pEndpoint->EpCallBacks.EpSendFull != NULL) { - AR_DEBUG_PRINTF(ATH_DEBUG_SEND, (" Calling driver's send full callback.... \n")); - pEndpoint->EpCallBacks.EpSendFull(pEndpoint->EpCallBacks.pContext, ep); - } - } else { - UNLOCK_HTC_TX(target); - /* queue is now available for new packet, let caller know */ - if (pEndpoint->EpCallBacks.EpSendAvail) - pEndpoint->EpCallBacks.EpSendAvail(pEndpoint->EpCallBacks.pContext, ep); - } - - AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("-HTCTrySend: \n")); -} - -/* HTC API - HTCSendPkt */ -A_STATUS HTCSendPkt(HTC_HANDLE HTCHandle, HTC_PACKET *pPacket) -{ - HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle); - HTC_ENDPOINT *pEndpoint; - HTC_ENDPOINT_ID ep; - A_STATUS status = A_OK; - - AR_DEBUG_PRINTF(ATH_DEBUG_SEND, - ("+HTCSendPkt: Enter endPointId: %d, buffer: 0x%X, length: %d \n", - pPacket->Endpoint, (A_UINT32)pPacket->pBuffer, pPacket->ActualLength)); - - ep = pPacket->Endpoint; - AR_DEBUG_ASSERT(ep < ENDPOINT_MAX); - pEndpoint = &target->EndPoint[ep]; - - do { - - if (HTC_STOPPING(target)) { - status = A_ECANCELED; - pPacket->Status = status; - DO_EP_TX_COMPLETION(pEndpoint,pPacket); - break; - } - /* everything sent through this interface is asynchronous */ - /* fill in HTC completion routines */ - pPacket->Completion = HTCSendPktCompletionHandler; - pPacket->pContext = target; - - HTCTrySend(target, pPacket, ep); - - } while (FALSE); - - AR_DEBUG_PRINTF(ATH_DEBUG_SEND, ("-HTCSendPkt \n")); - - return status; -} - - -/* check TX queues to drain because of credit distribution update */ -static INLINE void HTCCheckEndpointTxQueues(HTC_TARGET *target) -{ - HTC_ENDPOINT *pEndpoint; - HTC_ENDPOINT_CREDIT_DIST *pDistItem; - - AR_DEBUG_PRINTF(ATH_DEBUG_SEND, ("+HTCCheckEndpointTxQueues \n")); - pDistItem = target->EpCreditDistributionListHead; - - /* run through the credit distribution list to see - * if there are packets queued - * NOTE: no locks need to be taken since the distribution list - * is not dynamic (cannot be re-ordered) and we are not modifying any state */ - while (pDistItem != NULL) { - pEndpoint = (HTC_ENDPOINT *)pDistItem->pHTCReserved; - - if (pEndpoint->CurrentTxQueueDepth > 0) { - AR_DEBUG_PRINTF(ATH_DEBUG_SEND, (" Ep %d has %d credits and %d Packets in TX Queue \n", - pDistItem->Endpoint, pEndpoint->CreditDist.TxCredits, pEndpoint->CurrentTxQueueDepth)); - /* try to start the stalled queue, this list is ordered by priority. - * Highest priority queue get's processed first, if there are credits available the - * highest priority queue will get a chance to reclaim credits from lower priority - * ones */ - HTCTrySend(target, NULL, pDistItem->Endpoint); - } - - pDistItem = pDistItem->pNext; - } - - AR_DEBUG_PRINTF(ATH_DEBUG_SEND, ("-HTCCheckEndpointTxQueues \n")); -} - -/* process credit reports and call distribution function */ -void HTCProcessCreditRpt(HTC_TARGET *target, HTC_CREDIT_REPORT *pRpt, int NumEntries, HTC_ENDPOINT_ID FromEndpoint) -{ - int i; - HTC_ENDPOINT *pEndpoint; - int totalCredits = 0; - A_BOOL doDist = FALSE; - - AR_DEBUG_PRINTF(ATH_DEBUG_SEND, ("+HTCProcessCreditRpt, Credit Report Entries:%d \n", NumEntries)); - - /* lock out TX while we update credits */ - LOCK_HTC_TX(target); - - for (i = 0; i < NumEntries; i++, pRpt++) { - if (pRpt->EndpointID >= ENDPOINT_MAX) { - AR_DEBUG_ASSERT(FALSE); - break; - } - - pEndpoint = &target->EndPoint[pRpt->EndpointID]; - - AR_DEBUG_PRINTF(ATH_DEBUG_SEND, (" Endpoint %d got %d credits \n", - pRpt->EndpointID, pRpt->Credits)); - - -#ifdef HTC_EP_STAT_PROFILING - - INC_HTC_EP_STAT(pEndpoint, TxCreditRpts, 1); - INC_HTC_EP_STAT(pEndpoint, TxCreditsReturned, pRpt->Credits); - - if (FromEndpoint == pRpt->EndpointID) { - /* this credit report arrived on the same endpoint indicating it arrived in an RX - * packet */ - INC_HTC_EP_STAT(pEndpoint, TxCreditsFromRx, pRpt->Credits); - INC_HTC_EP_STAT(pEndpoint, TxCreditRptsFromRx, 1); - } else if (FromEndpoint == ENDPOINT_0) { - /* this credit arrived on endpoint 0 as a NULL message */ - INC_HTC_EP_STAT(pEndpoint, TxCreditsFromEp0, pRpt->Credits); - INC_HTC_EP_STAT(pEndpoint, TxCreditRptsFromEp0, 1); - } else { - /* arrived on another endpoint */ - INC_HTC_EP_STAT(pEndpoint, TxCreditsFromOther, pRpt->Credits); - INC_HTC_EP_STAT(pEndpoint, TxCreditRptsFromOther, 1); - } - -#endif - - if (ENDPOINT_0 == pRpt->EndpointID) { - /* always give endpoint 0 credits back */ - pEndpoint->CreditDist.TxCredits += pRpt->Credits; - } else { - /* for all other endpoints, update credits to distribute, the distribution function - * will handle giving out credits back to the endpoints */ - pEndpoint->CreditDist.TxCreditsToDist += pRpt->Credits; - /* flag that we have to do the distribution */ - doDist = TRUE; - } - - totalCredits += pRpt->Credits; - } - - AR_DEBUG_PRINTF(ATH_DEBUG_SEND, (" Report indicated %d credits to distribute \n", totalCredits)); - - if (doDist) { - /* this was a credit return based on a completed send operations - * note, this is done with the lock held */ - DO_DISTRIBUTION(target, - HTC_CREDIT_DIST_SEND_COMPLETE, - "Send Complete", - target->EpCreditDistributionListHead->pNext); - } - - UNLOCK_HTC_TX(target); - - if (totalCredits) { - HTCCheckEndpointTxQueues(target); - } - - AR_DEBUG_PRINTF(ATH_DEBUG_SEND, ("-HTCProcessCreditRpt \n")); -} - -/* flush endpoint TX queue */ -static void HTCFlushEndpointTX(HTC_TARGET *target, HTC_ENDPOINT *pEndpoint, HTC_TX_TAG Tag) -{ - HTC_PACKET *pPacket; - HTC_PACKET_QUEUE discardQueue; - - /* initialize the discard queue */ - INIT_HTC_PACKET_QUEUE(&discardQueue); - - LOCK_HTC_TX(target); - - /* interate from the front of the TX queue and flush out packets */ - ITERATE_OVER_LIST_ALLOW_REMOVE(&pEndpoint->TxQueue, pPacket, HTC_PACKET, ListLink) { - - /* check for removal */ - if ((HTC_TX_PACKET_TAG_ALL == Tag) || (Tag == pPacket->PktInfo.AsTx.Tag)) { - /* remove from queue */ - HTC_PACKET_REMOVE(pPacket); - /* add it to the discard pile */ - HTC_PACKET_ENQUEUE(&discardQueue, pPacket); - pEndpoint->CurrentTxQueueDepth--; - } - - } ITERATE_END; - - UNLOCK_HTC_TX(target); - - /* empty the discard queue */ - while (1) { - pPacket = HTC_PACKET_DEQUEUE(&discardQueue); - if (NULL == pPacket) { - break; - } - pPacket->Status = A_ECANCELED; - AR_DEBUG_PRINTF(ATH_DEBUG_TRC, (" Flushing TX packet:0x%X, length:%d, ep:%d tag:0x%X \n", - (A_UINT32)pPacket, pPacket->ActualLength, pPacket->Endpoint, pPacket->PktInfo.AsTx.Tag)); - DO_EP_TX_COMPLETION(pEndpoint,pPacket); - } - -} - -void DumpCreditDist(HTC_ENDPOINT_CREDIT_DIST *pEPDist) -{ -#ifdef DEBUG - HTC_ENDPOINT *pEndpoint = (HTC_ENDPOINT *)pEPDist->pHTCReserved; -#endif - - AR_DEBUG_PRINTF(ATH_DEBUG_ANY, ("--- EP : %d ServiceID: 0x%X --------------\n", - pEPDist->Endpoint, pEPDist->ServiceID)); - AR_DEBUG_PRINTF(ATH_DEBUG_ANY, (" this:0x%X next:0x%X prev:0x%X\n", - (A_UINT32)pEPDist, (A_UINT32)pEPDist->pNext, (A_UINT32)pEPDist->pPrev)); - AR_DEBUG_PRINTF(ATH_DEBUG_ANY, (" DistFlags : 0x%X \n", pEPDist->DistFlags)); - AR_DEBUG_PRINTF(ATH_DEBUG_ANY, (" TxCreditsNorm : %d \n", pEPDist->TxCreditsNorm)); - AR_DEBUG_PRINTF(ATH_DEBUG_ANY, (" TxCreditsMin : %d \n", pEPDist->TxCreditsMin)); - AR_DEBUG_PRINTF(ATH_DEBUG_ANY, (" TxCredits : %d \n", pEPDist->TxCredits)); - AR_DEBUG_PRINTF(ATH_DEBUG_ANY, (" TxCreditsAssigned : %d \n", pEPDist->TxCreditsAssigned)); - AR_DEBUG_PRINTF(ATH_DEBUG_ANY, (" TxCreditsSeek : %d \n", pEPDist->TxCreditsSeek)); - AR_DEBUG_PRINTF(ATH_DEBUG_ANY, (" TxCreditSize : %d \n", pEPDist->TxCreditSize)); - AR_DEBUG_PRINTF(ATH_DEBUG_ANY, (" TxCreditsPerMaxMsg : %d \n", pEPDist->TxCreditsPerMaxMsg)); - AR_DEBUG_PRINTF(ATH_DEBUG_ANY, (" TxCreditsToDist : %d \n", pEPDist->TxCreditsToDist)); - AR_DEBUG_PRINTF(ATH_DEBUG_ANY, (" TxQueueDepth : %d \n", pEndpoint->CurrentTxQueueDepth)); - AR_DEBUG_PRINTF(ATH_DEBUG_ANY, ("----------------------------------------------------\n")); -} - -void DumpCreditDistStates(HTC_TARGET *target) -{ - HTC_ENDPOINT_CREDIT_DIST *pEPList = target->EpCreditDistributionListHead; - - while (pEPList != NULL) { - DumpCreditDist(pEPList); - pEPList = pEPList->pNext; - } - - if (target->DistributeCredits != NULL) { - DO_DISTRIBUTION(target, - HTC_DUMP_CREDIT_STATE, - "Dump State", - NULL); - } -} - -/* flush all send packets from all endpoint queues */ -void HTCFlushSendPkts(HTC_TARGET *target) -{ - HTC_ENDPOINT *pEndpoint; - int i; - - DumpCreditDistStates(target); - - for (i = ENDPOINT_0; i < ENDPOINT_MAX; i++) { - pEndpoint = &target->EndPoint[i]; - if (pEndpoint->ServiceID == 0) { - /* not in use.. */ - continue; - } - HTCFlushEndpointTX(target,pEndpoint,HTC_TX_PACKET_TAG_ALL); - } - -} - -/* HTC API to flush an endpoint's TX queue*/ -void HTCFlushEndpoint(HTC_HANDLE HTCHandle, HTC_ENDPOINT_ID Endpoint, HTC_TX_TAG Tag) -{ - HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle); - HTC_ENDPOINT *pEndpoint = &target->EndPoint[Endpoint]; - - if (pEndpoint->ServiceID == 0) { - AR_DEBUG_ASSERT(FALSE); - /* not in use.. */ - return; - } - - HTCFlushEndpointTX(target, pEndpoint, Tag); -} - -/* HTC API to indicate activity to the credit distribution function */ -void HTCIndicateActivityChange(HTC_HANDLE HTCHandle, - HTC_ENDPOINT_ID Endpoint, - A_BOOL Active) -{ - HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle); - HTC_ENDPOINT *pEndpoint = &target->EndPoint[Endpoint]; - A_BOOL doDist = FALSE; - - if (pEndpoint->ServiceID == 0) { - AR_DEBUG_ASSERT(FALSE); - /* not in use.. */ - return; - } - - LOCK_HTC_TX(target); - - if (Active) { - if (!(pEndpoint->CreditDist.DistFlags & HTC_EP_ACTIVE)) { - /* mark active now */ - pEndpoint->CreditDist.DistFlags |= HTC_EP_ACTIVE; - doDist = TRUE; - } - } else { - if (pEndpoint->CreditDist.DistFlags & HTC_EP_ACTIVE) { - /* mark inactive now */ - pEndpoint->CreditDist.DistFlags &= ~HTC_EP_ACTIVE; - doDist = TRUE; - } - } - - if (doDist) { - /* do distribution again based on activity change - * note, this is done with the lock held */ - DO_DISTRIBUTION(target, - HTC_CREDIT_DIST_ACTIVITY_CHANGE, - "Activity Change", - target->EpCreditDistributionListHead->pNext); - } - - UNLOCK_HTC_TX(target); - -} diff --git a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/htc/htc_services.c b/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/htc/htc_services.c deleted file mode 100644 index e5d50d16d..000000000 --- a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/htc/htc_services.c +++ /dev/null @@ -1,403 +0,0 @@ -/* - * - * Copyright (c) 2007 Atheros Communications Inc. - * All rights reserved. - * - * - * 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; - * - * Software distributed under the License is distributed on an "AS - * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or - * implied. See the License for the specific language governing - * rights and limitations under the License. - * - * - * - */ - -#include "htc_internal.h" - -void HTCControlTxComplete(void *Context, HTC_PACKET *pPacket) -{ - /* not implemented - * we do not send control TX frames during normal runtime, only during setup */ - AR_DEBUG_ASSERT(FALSE); -} - - /* callback when a control message arrives on this endpoint */ -void HTCControlRecv(void *Context, HTC_PACKET *pPacket) -{ - AR_DEBUG_ASSERT(pPacket->Endpoint == ENDPOINT_0); - - /* the only control messages we are expecting are NULL messages (credit resports), which should - * never get here */ - AR_DEBUG_PRINTF(ATH_DEBUG_ERR, - ("HTCControlRecv, got message with length:%d \n", - pPacket->ActualLength + HTC_HDR_LENGTH)); - - /* dump header and message */ - DebugDumpBytes(pPacket->pBuffer - HTC_HDR_LENGTH, - pPacket->ActualLength + HTC_HDR_LENGTH, - "Unexpected ENDPOINT 0 Message"); - - HTC_RECYCLE_RX_PKT((HTC_TARGET*)Context,pPacket); -} - -A_STATUS HTCSendSetupComplete(HTC_TARGET *target) -{ - HTC_PACKET *pSendPacket = NULL; - A_STATUS status; - HTC_SETUP_COMPLETE_MSG *pSetupComplete; - - do { - /* allocate a packet to send to the target */ - pSendPacket = HTC_ALLOC_CONTROL_TX(target); - - if (NULL == pSendPacket) { - status = A_NO_MEMORY; - break; - } - - /* assemble setup complete message */ - pSetupComplete = (HTC_SETUP_COMPLETE_MSG *)pSendPacket->pBuffer; - A_MEMZERO(pSetupComplete,sizeof(HTC_SETUP_COMPLETE_MSG)); - pSetupComplete->MessageID = HTC_MSG_SETUP_COMPLETE_ID; - - SET_HTC_PACKET_INFO_TX(pSendPacket, - NULL, - (A_UINT8 *)pSetupComplete, - sizeof(HTC_SETUP_COMPLETE_MSG), - ENDPOINT_0, - HTC_SERVICE_TX_PACKET_TAG); - - /* we want synchronous operation */ - pSendPacket->Completion = NULL; - /* send the message */ - status = HTCIssueSend(target,pSendPacket,0); - - } while (FALSE); - - if (pSendPacket != NULL) { - HTC_FREE_CONTROL_TX(target,pSendPacket); - } - - return status; -} - - -A_STATUS HTCConnectService(HTC_HANDLE HTCHandle, - HTC_SERVICE_CONNECT_REQ *pConnectReq, - HTC_SERVICE_CONNECT_RESP *pConnectResp) -{ - HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle); - A_STATUS status = A_OK; - HTC_PACKET *pRecvPacket = NULL; - HTC_PACKET *pSendPacket = NULL; - HTC_CONNECT_SERVICE_RESPONSE_MSG *pResponseMsg; - HTC_CONNECT_SERVICE_MSG *pConnectMsg; - HTC_ENDPOINT_ID assignedEndpoint = ENDPOINT_MAX; - HTC_ENDPOINT *pEndpoint; - int maxMsgSize = 0; - - AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("+HTCConnectService, target:0x%X SvcID:0x%X \n", - (A_UINT32)target, pConnectReq->ServiceID)); - - do { - - AR_DEBUG_ASSERT(pConnectReq->ServiceID != 0); - - if (HTC_CTRL_RSVD_SVC == pConnectReq->ServiceID) { - /* special case for pseudo control service */ - assignedEndpoint = ENDPOINT_0; - maxMsgSize = HTC_MAX_CONTROL_MESSAGE_LENGTH; - } else { - /* allocate a packet to send to the target */ - pSendPacket = HTC_ALLOC_CONTROL_TX(target); - - if (NULL == pSendPacket) { - AR_DEBUG_ASSERT(FALSE); - status = A_NO_MEMORY; - break; - } - /* assemble connect service message */ - pConnectMsg = (HTC_CONNECT_SERVICE_MSG *)pSendPacket->pBuffer; - AR_DEBUG_ASSERT(pConnectMsg != NULL); - A_MEMZERO(pConnectMsg,sizeof(HTC_CONNECT_SERVICE_MSG)); - pConnectMsg->MessageID = HTC_MSG_CONNECT_SERVICE_ID; - pConnectMsg->ServiceID = pConnectReq->ServiceID; - pConnectMsg->ConnectionFlags = pConnectReq->ConnectionFlags; - /* check caller if it wants to transfer meta data */ - if ((pConnectReq->pMetaData != NULL) && - (pConnectReq->MetaDataLength <= HTC_SERVICE_META_DATA_MAX_LENGTH)) { - /* copy meta data into message buffer (after header ) */ - A_MEMCPY((A_UINT8 *)pConnectMsg + sizeof(HTC_CONNECT_SERVICE_MSG), - pConnectReq->pMetaData, - pConnectReq->MetaDataLength); - pConnectMsg->ServiceMetaLength = pConnectReq->MetaDataLength; - } - - SET_HTC_PACKET_INFO_TX(pSendPacket, - NULL, - (A_UINT8 *)pConnectMsg, - sizeof(HTC_CONNECT_SERVICE_MSG) + pConnectMsg->ServiceMetaLength, - ENDPOINT_0, - HTC_SERVICE_TX_PACKET_TAG); - - /* we want synchronous operation */ - pSendPacket->Completion = NULL; - - status = HTCIssueSend(target,pSendPacket,0); - - if (A_FAILED(status)) { - break; - } - - /* wait for response */ - status = HTCWaitforControlMessage(target, &pRecvPacket); - - if (A_FAILED(status)) { - break; - } - /* we controlled the buffer creation so it has to be properly aligned */ - pResponseMsg = (HTC_CONNECT_SERVICE_RESPONSE_MSG *)pRecvPacket->pBuffer; - - if ((pResponseMsg->MessageID != HTC_MSG_CONNECT_SERVICE_RESPONSE_ID) || - (pRecvPacket->ActualLength < sizeof(HTC_CONNECT_SERVICE_RESPONSE_MSG))) { - /* this message is not valid */ - AR_DEBUG_ASSERT(FALSE); - status = A_EPROTO; - break; - } - - pConnectResp->ConnectRespCode = pResponseMsg->Status; - /* check response status */ - if (pResponseMsg->Status != HTC_SERVICE_SUCCESS) { - AR_DEBUG_PRINTF(ATH_DEBUG_ERR, - (" Target failed service 0x%X connect request (status:%d)\n", - pResponseMsg->ServiceID, pResponseMsg->Status)); - status = A_EPROTO; - break; - } - - assignedEndpoint = pResponseMsg->EndpointID; - maxMsgSize = pResponseMsg->MaxMsgSize; - - if ((pConnectResp->pMetaData != NULL) && - (pResponseMsg->ServiceMetaLength > 0) && - (pResponseMsg->ServiceMetaLength <= HTC_SERVICE_META_DATA_MAX_LENGTH)) { - /* caller supplied a buffer and the target responded with data */ - int copyLength = min((int)pConnectResp->BufferLength, (int)pResponseMsg->ServiceMetaLength); - /* copy the meta data */ - A_MEMCPY(pConnectResp->pMetaData, - ((A_UINT8 *)pResponseMsg) + sizeof(HTC_CONNECT_SERVICE_RESPONSE_MSG), - copyLength); - pConnectResp->ActualLength = copyLength; - } - - } - - /* the rest of these are parameter checks so set the error status */ - status = A_EPROTO; - - if (assignedEndpoint >= ENDPOINT_MAX) { - AR_DEBUG_ASSERT(FALSE); - break; - } - - if (0 == maxMsgSize) { - AR_DEBUG_ASSERT(FALSE); - break; - } - - pEndpoint = &target->EndPoint[assignedEndpoint]; - - if (pEndpoint->ServiceID != 0) { - /* endpoint already in use! */ - AR_DEBUG_ASSERT(FALSE); - break; - } - - /* return assigned endpoint to caller */ - pConnectResp->Endpoint = assignedEndpoint; - pConnectResp->MaxMsgLength = maxMsgSize; - - /* setup the endpoint */ - pEndpoint->ServiceID = pConnectReq->ServiceID; /* this marks the endpoint in use */ - pEndpoint->MaxTxQueueDepth = pConnectReq->MaxSendQueueDepth; - pEndpoint->MaxMsgLength = maxMsgSize; - /* copy all the callbacks */ - pEndpoint->EpCallBacks = pConnectReq->EpCallbacks; - INIT_HTC_PACKET_QUEUE(&pEndpoint->RxBuffers); - INIT_HTC_PACKET_QUEUE(&pEndpoint->TxQueue); - /* set the credit distribution info for this endpoint, this information is - * passed back to the credit distribution callback function */ - pEndpoint->CreditDist.ServiceID = pConnectReq->ServiceID; - pEndpoint->CreditDist.pHTCReserved = pEndpoint; - pEndpoint->CreditDist.Endpoint = assignedEndpoint; - pEndpoint->CreditDist.TxCreditSize = target->TargetCreditSize; - pEndpoint->CreditDist.TxCreditsPerMaxMsg = maxMsgSize / target->TargetCreditSize; - - if (0 == pEndpoint->CreditDist.TxCreditsPerMaxMsg) { - pEndpoint->CreditDist.TxCreditsPerMaxMsg = 1; - } - - status = A_OK; - - } while (FALSE); - - if (pSendPacket != NULL) { - HTC_FREE_CONTROL_TX(target,pSendPacket); - } - - if (pRecvPacket != NULL) { - HTC_FREE_CONTROL_RX(target,pRecvPacket); - } - - AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("-HTCConnectService \n")); - - return status; -} - -static void AddToEndpointDistList(HTC_TARGET *target, HTC_ENDPOINT_CREDIT_DIST *pEpDist) -{ - HTC_ENDPOINT_CREDIT_DIST *pCurEntry,*pLastEntry; - - if (NULL == target->EpCreditDistributionListHead) { - target->EpCreditDistributionListHead = pEpDist; - pEpDist->pNext = NULL; - pEpDist->pPrev = NULL; - return; - } - - /* queue to the end of the list, this does not have to be very - * fast since this list is built at startup time */ - pCurEntry = target->EpCreditDistributionListHead; - - while (pCurEntry) { - pLastEntry = pCurEntry; - pCurEntry = pCurEntry->pNext; - } - - pLastEntry->pNext = pEpDist; - pEpDist->pPrev = pLastEntry; - pEpDist->pNext = NULL; -} - - - -/* default credit init callback */ -static void HTCDefaultCreditInit(void *Context, - HTC_ENDPOINT_CREDIT_DIST *pEPList, - int TotalCredits) -{ - HTC_ENDPOINT_CREDIT_DIST *pCurEpDist; - int totalEps = 0; - int creditsPerEndpoint; - - pCurEpDist = pEPList; - /* first run through the list and figure out how many endpoints we are dealing with */ - while (pCurEpDist != NULL) { - pCurEpDist = pCurEpDist->pNext; - totalEps++; - } - - /* even distribution */ - creditsPerEndpoint = TotalCredits/totalEps; - - pCurEpDist = pEPList; - /* run through the list and set minimum and normal credits and - * provide the endpoint with some credits to start */ - while (pCurEpDist != NULL) { - - if (creditsPerEndpoint < pCurEpDist->TxCreditsPerMaxMsg) { - /* too many endpoints and not enough credits */ - AR_DEBUG_ASSERT(FALSE); - break; - } - /* our minimum is set for at least 1 max message */ - pCurEpDist->TxCreditsMin = pCurEpDist->TxCreditsPerMaxMsg; - /* this value is ignored by our credit alg, since we do - * not dynamically adjust credits, this is the policy of - * the "default" credit distribution, something simple and easy */ - pCurEpDist->TxCreditsNorm = 0xFFFF; - /* give the endpoint minimum credits */ - pCurEpDist->TxCredits = creditsPerEndpoint; - pCurEpDist->TxCreditsAssigned = creditsPerEndpoint; - pCurEpDist = pCurEpDist->pNext; - } - -} - -/* default credit distribution callback, NOTE, this callback holds the TX lock */ -void HTCDefaultCreditDist(void *Context, - HTC_ENDPOINT_CREDIT_DIST *pEPDistList, - HTC_CREDIT_DIST_REASON Reason) -{ - HTC_ENDPOINT_CREDIT_DIST *pCurEpDist; - - if (Reason == HTC_CREDIT_DIST_SEND_COMPLETE) { - pCurEpDist = pEPDistList; - /* simple distribution */ - while (pCurEpDist != NULL) { - if (pCurEpDist->TxCreditsToDist > 0) { - /* just give the endpoint back the credits */ - pCurEpDist->TxCredits += pCurEpDist->TxCreditsToDist; - pCurEpDist->TxCreditsToDist = 0; - } - pCurEpDist = pCurEpDist->pNext; - } - } - - /* note we do not need to handle the other reason codes as this is a very - * simple distribution scheme, no need to seek for more credits or handle inactivity */ -} - -void HTCSetCreditDistribution(HTC_HANDLE HTCHandle, - void *pCreditDistContext, - HTC_CREDIT_DIST_CALLBACK CreditDistFunc, - HTC_CREDIT_INIT_CALLBACK CreditInitFunc, - HTC_SERVICE_ID ServicePriorityOrder[], - int ListLength) -{ - HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle); - int i; - int ep; - - if (CreditInitFunc != NULL) { - /* caller has supplied their own distribution functions */ - target->InitCredits = CreditInitFunc; - AR_DEBUG_ASSERT(CreditDistFunc != NULL); - target->DistributeCredits = CreditDistFunc; - target->pCredDistContext = pCreditDistContext; - } else { - /* caller wants HTC to do distribution */ - /* if caller wants service to handle distributions then - * it must set both of these to NULL! */ - AR_DEBUG_ASSERT(CreditDistFunc == NULL); - target->InitCredits = HTCDefaultCreditInit; - target->DistributeCredits = HTCDefaultCreditDist; - target->pCredDistContext = target; - } - - /* always add HTC control endpoint first, we only expose the list after the - * first one, this is added for TX queue checking */ - AddToEndpointDistList(target, &target->EndPoint[ENDPOINT_0].CreditDist); - - /* build the list of credit distribution structures in priority order - * supplied by the caller, these will follow endpoint 0 */ - for (i = 0; i < ListLength; i++) { - /* match services with endpoints and add the endpoints to the distribution list - * in FIFO order */ - for (ep = ENDPOINT_1; ep < ENDPOINT_MAX; ep++) { - if (target->EndPoint[ep].ServiceID == ServicePriorityOrder[i]) { - /* queue this one to the list */ - AddToEndpointDistList(target, &target->EndPoint[ep].CreditDist); - break; - } - } - AR_DEBUG_ASSERT(ep < ENDPOINT_MAX); - } - -} diff --git a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/include/AR6001_regdump.h b/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/include/AR6001_regdump.h deleted file mode 100644 index c1bcadea3..000000000 --- a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/include/AR6001_regdump.h +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright (c) 2006 Atheros Communications Inc. - * All rights reserved. - * - * $ATH_LICENSE_HOSTSDK0_C$ - * - */ - -#ifndef __AR6000_REGDUMP_H__ -#define __AR6000_REGDUMP_H__ - -#if !defined(__ASSEMBLER__) -/* - * Target CPU state at the time of failure is reflected - * in a register dump, which the Host can fetch through - * the diagnostic window. - */ - -struct MIPS_exception_frame_s { - A_UINT32 pc; /* Program Counter */ - A_UINT32 at; /* MIPS General Purpose registers */ - A_UINT32 v0; - A_UINT32 v1; - A_UINT32 a0; - A_UINT32 a1; - A_UINT32 a2; - A_UINT32 a3; - A_UINT32 t0; - A_UINT32 t1; - A_UINT32 t2; - A_UINT32 t3; - A_UINT32 t4; - A_UINT32 t5; - A_UINT32 t6; - A_UINT32 t7; - A_UINT32 s0; - A_UINT32 s1; - A_UINT32 s2; - A_UINT32 s3; - A_UINT32 s4; - A_UINT32 s5; - A_UINT32 s6; - A_UINT32 s7; - A_UINT32 t8; - A_UINT32 t9; - A_UINT32 k0; - A_UINT32 k1; - A_UINT32 gp; - A_UINT32 sp; - A_UINT32 s8; - A_UINT32 ra; - A_UINT32 cause; /* Selected coprocessor regs */ - A_UINT32 status; -}; -typedef struct MIPS_exception_frame_s CPU_exception_frame_t; - -#endif - -/* - * Offsets into MIPS_exception_frame structure, for use in assembler code - * MUST MATCH C STRUCTURE ABOVE - */ -#define RD_pc 0 -#define RD_at 1 -#define RD_v0 2 -#define RD_v1 3 -#define RD_a0 4 -#define RD_a1 5 -#define RD_a2 6 -#define RD_a3 7 -#define RD_t0 8 -#define RD_t1 9 -#define RD_t2 10 -#define RD_t3 11 -#define RD_t4 12 -#define RD_t5 13 -#define RD_t6 14 -#define RD_t7 15 -#define RD_s0 16 -#define RD_s1 17 -#define RD_s2 18 -#define RD_s3 19 -#define RD_s4 20 -#define RD_s5 21 -#define RD_s6 22 -#define RD_s7 23 -#define RD_t8 24 -#define RD_t9 25 -#define RD_k0 26 -#define RD_k1 27 -#define RD_gp 28 -#define RD_sp 29 -#define RD_s8 30 -#define RD_ra 31 -#define RD_cause 32 -#define RD_status 33 - -#define RD_SIZE (34*4) /* Space for this number of words */ - -#endif /* __AR6000_REGDUMP_H__ */ diff --git a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/include/AR6K_version.h b/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/include/AR6K_version.h deleted file mode 100644 index d5b2a20b0..000000000 --- a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/include/AR6K_version.h +++ /dev/null @@ -1,36 +0,0 @@ -#define __VER_MAJOR_ 2 -#define __VER_MINOR_ 0 -#define __VER_PATCH_ 0 - - -/* - * Copyright (c) 2004-2007 Atheros Communications Inc. - * All rights reserved. - * - * $ATH_LICENSE_HOSTSDK0_C$ - * - * The makear6ksdk script (used for release builds) modifies the following line. - */ -#define __BUILD_NUMBER_ 18 - - -/* Format of the version number. */ -#define VER_MAJOR_BIT_OFFSET 28 -#define VER_MINOR_BIT_OFFSET 24 -#define VER_PATCH_BIT_OFFSET 16 -#define VER_BUILD_NUM_BIT_OFFSET 0 - - -/* - * The version has the following format: - * Bits 28-31: Major version - * Bits 24-27: Minor version - * Bits 16-23: Patch version - * Bits 0-15: Build number (automatically generated during build process ) - * E.g. Build 1.1.3.7 would be represented as 0x11030007. - * - * DO NOT split the following macro into multiple lines as this may confuse the build scripts. - */ -#define AR6K_SW_VERSION ( ( __VER_MAJOR_ << VER_MAJOR_BIT_OFFSET ) + ( __VER_MINOR_ << VER_MINOR_BIT_OFFSET ) + ( __VER_PATCH_ << VER_PATCH_BIT_OFFSET ) + ( __BUILD_NUMBER_ << VER_BUILD_NUM_BIT_OFFSET ) ) - - diff --git a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/include/AR6K_version.h.NEW b/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/include/AR6K_version.h.NEW deleted file mode 100644 index d5b2a20b0..000000000 --- a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/include/AR6K_version.h.NEW +++ /dev/null @@ -1,36 +0,0 @@ -#define __VER_MAJOR_ 2 -#define __VER_MINOR_ 0 -#define __VER_PATCH_ 0 - - -/* - * Copyright (c) 2004-2007 Atheros Communications Inc. - * All rights reserved. - * - * $ATH_LICENSE_HOSTSDK0_C$ - * - * The makear6ksdk script (used for release builds) modifies the following line. - */ -#define __BUILD_NUMBER_ 18 - - -/* Format of the version number. */ -#define VER_MAJOR_BIT_OFFSET 28 -#define VER_MINOR_BIT_OFFSET 24 -#define VER_PATCH_BIT_OFFSET 16 -#define VER_BUILD_NUM_BIT_OFFSET 0 - - -/* - * The version has the following format: - * Bits 28-31: Major version - * Bits 24-27: Minor version - * Bits 16-23: Patch version - * Bits 0-15: Build number (automatically generated during build process ) - * E.g. Build 1.1.3.7 would be represented as 0x11030007. - * - * DO NOT split the following macro into multiple lines as this may confuse the build scripts. - */ -#define AR6K_SW_VERSION ( ( __VER_MAJOR_ << VER_MAJOR_BIT_OFFSET ) + ( __VER_MINOR_ << VER_MINOR_BIT_OFFSET ) + ( __VER_PATCH_ << VER_PATCH_BIT_OFFSET ) + ( __BUILD_NUMBER_ << VER_BUILD_NUM_BIT_OFFSET ) ) - - diff --git a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/include/AR6Khwreg.h b/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/include/AR6Khwreg.h deleted file mode 100644 index ecfdf20a0..000000000 --- a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/include/AR6Khwreg.h +++ /dev/null @@ -1,147 +0,0 @@ -/* - * Copyright (c) 2004-2007 Atheros Communications Inc. - * All rights reserved. - * - * $ATH_LICENSE_HOSTSDK0_C$ - * - * This file contains the definitions for AR6001 registers - * that may be directly manipulated by Host software. - */ - -#ifndef __AR6KHWREG_H__ -#define __AR6KHWREG_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -/* Host registers */ -#define HOST_INT_STATUS_ADDRESS 0x00000400 -#define CPU_INT_STATUS_ADDRESS 0x00000401 -#define ERROR_INT_STATUS_ADDRESS 0x00000402 -#define INT_STATUS_ENABLE_ADDRESS 0x00000418 -#define CPU_INT_STATUS_ENABLE_ADDRESS 0x00000419 -#define COUNT_ADDRESS 0x00000420 -#define COUNT_DEC_ADDRESS 0x00000440 -#define WINDOW_DATA_ADDRESS 0x00000474 -#define WINDOW_WRITE_ADDR_ADDRESS 0x00000478 -#define WINDOW_READ_ADDR_ADDRESS 0x0000047c - -/* Target addresses */ -#define RESET_CONTROL_ADDRESS 0x0c000000 -#define MC_REMAP_VALID_ADDRESS 0x0c004080 -#define MC_REMAP_SIZE_ADDRESS 0x0c004100 -#define MC_REMAP_COMPARE_ADDRESS 0x0c004180 -#define MC_REMAP_TARGET_ADDRESS 0x0c004200 -#define LOCAL_COUNT_ADDRESS 0x0c014080 -#define LOCAL_SCRATCH_ADDRESS 0x0c0140c0 - - -#define INT_STATUS_ENABLE_ERROR_MSB 7 -#define INT_STATUS_ENABLE_ERROR_LSB 7 -#define INT_STATUS_ENABLE_ERROR_MASK 0x00000080 -#define INT_STATUS_ENABLE_ERROR_GET(x) (((x) & INT_STATUS_ENABLE_ERROR_MASK) >> INT_STATUS_ENABLE_ERROR_LSB) -#define INT_STATUS_ENABLE_ERROR_SET(x) (((x) << INT_STATUS_ENABLE_ERROR_LSB) & INT_STATUS_ENABLE_ERROR_MASK) - -#define INT_STATUS_ENABLE_CPU_MSB 6 -#define INT_STATUS_ENABLE_CPU_LSB 6 -#define INT_STATUS_ENABLE_CPU_MASK 0x00000040 -#define INT_STATUS_ENABLE_CPU_GET(x) (((x) & INT_STATUS_ENABLE_CPU_MASK) >> INT_STATUS_ENABLE_CPU_LSB) -#define INT_STATUS_ENABLE_CPU_SET(x) (((x) << INT_STATUS_ENABLE_CPU_LSB) & INT_STATUS_ENABLE_CPU_MASK) - -#define INT_STATUS_ENABLE_COUNTER_MSB 4 -#define INT_STATUS_ENABLE_COUNTER_LSB 4 -#define INT_STATUS_ENABLE_COUNTER_MASK 0x00000010 -#define INT_STATUS_ENABLE_COUNTER_GET(x) (((x) & INT_STATUS_ENABLE_COUNTER_MASK) >> INT_STATUS_ENABLE_COUNTER_LSB) -#define INT_STATUS_ENABLE_COUNTER_SET(x) (((x) << INT_STATUS_ENABLE_COUNTER_LSB) & INT_STATUS_ENABLE_COUNTER_MASK) - -#define INT_STATUS_ENABLE_MBOX_DATA_MSB 3 -#define INT_STATUS_ENABLE_MBOX_DATA_LSB 0 -#define INT_STATUS_ENABLE_MBOX_DATA_MASK 0x0000000f -#define INT_STATUS_ENABLE_MBOX_DATA_GET(x) (((x) & INT_STATUS_ENABLE_MBOX_DATA_MASK) >> INT_STATUS_ENABLE_MBOX_DATA_LSB) -#define INT_STATUS_ENABLE_MBOX_DATA_SET(x) (((x) << INT_STATUS_ENABLE_MBOX_DATA_LSB) & INT_STATUS_ENABLE_MBOX_DATA_MASK) - -#define ERROR_STATUS_ENABLE_RX_UNDERFLOW_MSB 1 -#define ERROR_STATUS_ENABLE_RX_UNDERFLOW_LSB 1 -#define ERROR_STATUS_ENABLE_RX_UNDERFLOW_MASK 0x00000002 -#define ERROR_STATUS_ENABLE_RX_UNDERFLOW_GET(x) (((x) & ERROR_STATUS_ENABLE_RX_UNDERFLOW_MASK) >> ERROR_STATUS_ENABLE_RX_UNDERFLOW_LSB) -#define ERROR_STATUS_ENABLE_RX_UNDERFLOW_SET(x) (((x) << ERROR_STATUS_ENABLE_RX_UNDERFLOW_LSB) & ERROR_STATUS_ENABLE_RX_UNDERFLOW_MASK) - -#define ERROR_STATUS_ENABLE_TX_OVERFLOW_MSB 0 -#define ERROR_STATUS_ENABLE_TX_OVERFLOW_LSB 0 -#define ERROR_STATUS_ENABLE_TX_OVERFLOW_MASK 0x00000001 -#define ERROR_STATUS_ENABLE_TX_OVERFLOW_GET(x) (((x) & ERROR_STATUS_ENABLE_TX_OVERFLOW_MASK) >> ERROR_STATUS_ENABLE_TX_OVERFLOW_LSB) -#define ERROR_STATUS_ENABLE_TX_OVERFLOW_SET(x) (((x) << ERROR_STATUS_ENABLE_TX_OVERFLOW_LSB) & ERROR_STATUS_ENABLE_TX_OVERFLOW_MASK) - - -#define CPU_INT_STATUS_ENABLE_BIT_MSB 7 -#define CPU_INT_STATUS_ENABLE_BIT_LSB 0 -#define CPU_INT_STATUS_ENABLE_BIT_MASK 0x000000ff -#define CPU_INT_STATUS_ENABLE_BIT_GET(x) (((x) & CPU_INT_STATUS_ENABLE_BIT_MASK) >> CPU_INT_STATUS_ENABLE_BIT_LSB) -#define CPU_INT_STATUS_ENABLE_BIT_SET(x) (((x) << CPU_INT_STATUS_ENABLE_BIT_LSB) & CPU_INT_STATUS_ENABLE_BIT_MASK) - -#define COUNTER_INT_STATUS_ENABLE_BIT_MSB 7 -#define COUNTER_INT_STATUS_ENABLE_BIT_LSB 0 -#define COUNTER_INT_STATUS_ENABLE_BIT_MASK 0x000000ff -#define COUNTER_INT_STATUS_ENABLE_BIT_GET(x) (((x) & COUNTER_INT_STATUS_ENABLE_BIT_MASK) >> COUNTER_INT_STATUS_ENABLE_BIT_LSB) -#define COUNTER_INT_STATUS_ENABLE_BIT_SET(x) (((x) << COUNTER_INT_STATUS_ENABLE_BIT_LSB) & COUNTER_INT_STATUS_ENABLE_BIT_MASK) - -#define ERROR_INT_STATUS_WAKEUP_MSB 2 -#define ERROR_INT_STATUS_WAKEUP_LSB 2 -#define ERROR_INT_STATUS_WAKEUP_MASK 0x00000004 -#define ERROR_INT_STATUS_WAKEUP_GET(x) (((x) & ERROR_INT_STATUS_WAKEUP_MASK) >> ERROR_INT_STATUS_WAKEUP_LSB) -#define ERROR_INT_STATUS_WAKEUP_SET(x) (((x) << ERROR_INT_STATUS_WAKEUP_LSB) & ERROR_INT_STATUS_WAKEUP_MASK) - -#define ERROR_INT_STATUS_RX_UNDERFLOW_MSB 1 -#define ERROR_INT_STATUS_RX_UNDERFLOW_LSB 1 -#define ERROR_INT_STATUS_RX_UNDERFLOW_MASK 0x00000002 -#define ERROR_INT_STATUS_RX_UNDERFLOW_GET(x) (((x) & ERROR_INT_STATUS_RX_UNDERFLOW_MASK) >> ERROR_INT_STATUS_RX_UNDERFLOW_LSB) -#define ERROR_INT_STATUS_RX_UNDERFLOW_SET(x) (((x) << ERROR_INT_STATUS_RX_UNDERFLOW_LSB) & ERROR_INT_STATUS_RX_UNDERFLOW_MASK) - -#define ERROR_INT_STATUS_TX_OVERFLOW_MSB 0 -#define ERROR_INT_STATUS_TX_OVERFLOW_LSB 0 -#define ERROR_INT_STATUS_TX_OVERFLOW_MASK 0x00000001 -#define ERROR_INT_STATUS_TX_OVERFLOW_GET(x) (((x) & ERROR_INT_STATUS_TX_OVERFLOW_MASK) >> ERROR_INT_STATUS_TX_OVERFLOW_LSB) -#define ERROR_INT_STATUS_TX_OVERFLOW_SET(x) (((x) << ERROR_INT_STATUS_TX_OVERFLOW_LSB) & ERROR_INT_STATUS_TX_OVERFLOW_MASK) - -#define HOST_INT_STATUS_ERROR_MSB 7 -#define HOST_INT_STATUS_ERROR_LSB 7 -#define HOST_INT_STATUS_ERROR_MASK 0x00000080 -#define HOST_INT_STATUS_ERROR_GET(x) (((x) & HOST_INT_STATUS_ERROR_MASK) >> HOST_INT_STATUS_ERROR_LSB) -#define HOST_INT_STATUS_ERROR_SET(x) (((x) << HOST_INT_STATUS_ERROR_LSB) & HOST_INT_STATUS_ERROR_MASK) - -#define HOST_INT_STATUS_CPU_MSB 6 -#define HOST_INT_STATUS_CPU_LSB 6 -#define HOST_INT_STATUS_CPU_MASK 0x00000040 -#define HOST_INT_STATUS_CPU_GET(x) (((x) & HOST_INT_STATUS_CPU_MASK) >> HOST_INT_STATUS_CPU_LSB) -#define HOST_INT_STATUS_CPU_SET(x) (((x) << HOST_INT_STATUS_CPU_LSB) & HOST_INT_STATUS_CPU_MASK) - -#define HOST_INT_STATUS_COUNTER_MSB 4 -#define HOST_INT_STATUS_COUNTER_LSB 4 -#define HOST_INT_STATUS_COUNTER_MASK 0x00000010 -#define HOST_INT_STATUS_COUNTER_GET(x) (((x) & HOST_INT_STATUS_COUNTER_MASK) >> HOST_INT_STATUS_COUNTER_LSB) -#define HOST_INT_STATUS_COUNTER_SET(x) (((x) << HOST_INT_STATUS_COUNTER_LSB) & HOST_INT_STATUS_COUNTER_MASK) - -#define RESET_CONTROL_WARM_RST_MSB 7 -#define RESET_CONTROL_WARM_RST_LSB 7 -#define RESET_CONTROL_WARM_RST_MASK 0x00000080 -#define RESET_CONTROL_WARM_RST_GET(x) (((x) & RESET_CONTROL_WARM_RST_MASK) >> RESET_CONTROL_WARM_RST_LSB) -#define RESET_CONTROL_WARM_RST_SET(x) (((x) << RESET_CONTROL_WARM_RST_LSB) & RESET_CONTROL_WARM_RST_MASK) - -#define RESET_CONTROL_COLD_RST_MSB 8 -#define RESET_CONTROL_COLD_RST_LSB 8 -#define RESET_CONTROL_COLD_RST_MASK 0x00000100 -#define RESET_CONTROL_COLD_RST_GET(x) (((x) & RESET_CONTROL_COLD_RST_MASK) >> RESET_CONTROL_COLD_RST_LSB) -#define RESET_CONTROL_COLD_RST_SET(x) (((x) << RESET_CONTROL_COLD_RST_LSB) & RESET_CONTROL_COLD_RST_MASK) - -#define RESET_CAUSE_LAST_MSB 2 -#define RESET_CAUSE_LAST_LSB 0 -#define RESET_CAUSE_LAST_MASK 0x00000007 -#define RESET_CAUSE_LAST_GET(x) (((x) & RESET_CAUSE_LAST_MASK) >> RESET_CAUSE_LAST_LSB) -#define RESET_CAUSE_LAST_SET(x) (((x) << RESET_CAUSE_LAST_LSB) & RESET_CAUSE_LAST_MASK) - -#ifdef __cplusplus -} -#endif - -#endif /* __AR6KHWREG_H__ */ diff --git a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/include/a_config.h b/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/include/a_config.h deleted file mode 100644 index 627b2984d..000000000 --- a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/include/a_config.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef _A_CONFIG_H_ -#define _A_CONFIG_H_ -/* - * Copyright (c) 2004-2005 Atheros Communications Inc. - * All rights reserved. - * - * - * 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; - * - * Software distributed under the License is distributed on an "AS - * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or - * implied. See the License for the specific language governing - * rights and limitations under the License. - * - * - * - */ - -/* - * This file contains software configuration options that enables - * specific software "features" - */ -#include "../ar6000/config_linux.h" - -#endif diff --git a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/include/a_debug.h b/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/include/a_debug.h deleted file mode 100644 index 4b0b35155..000000000 --- a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/include/a_debug.h +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef _A_DEBUG_H_ -#define _A_DEBUG_H_ -/* - * Copyright (c) 2004-2006 Atheros Communications Inc. - * All rights reserved. - * - * Copyright (c) 2004-2007 Atheros Communications Inc. - * All rights reserved. - * - * - * 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; - * - * Software distributed under the License is distributed on an "AS - * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or - * implied. See the License for the specific language governing - * rights and limitations under the License. - * - * - * - */ - -#include -#include - -#define DBG_INFO 0x00000001 -#define DBG_ERROR 0x00000002 -#define DBG_WARNING 0x00000004 -#define DBG_SDIO 0x00000008 -#define DBG_HIF 0x00000010 -#define DBG_HTC 0x00000020 -#define DBG_WMI 0x00000040 -#define DBG_WMI2 0x00000080 -#define DBG_DRIVER 0x00000100 - -#define DBG_DEFAULTS (DBG_ERROR|DBG_WARNING) - -#include "../ar6000/debug_linux.h" - -#endif diff --git a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/include/a_drv.h b/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/include/a_drv.h deleted file mode 100644 index 07e52d179..000000000 --- a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/include/a_drv.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef _A_DRV_H_ -#define _A_DRV_H_ -/* - * $Id: //depot/sw/releases/olca2.0-GPL/host/include/a_drv.h#1 $ - * - * This file contains the definitions of the basic atheros data types. - * It is used to map the data types in atheros files to a platform specific - * type. - * - * Copyright 2003-2005 Atheros Communications, Inc., All Rights Reserved. - * - * - * 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; - * - * Software distributed under the License is distributed on an "AS - * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or - * implied. See the License for the specific language governing - * rights and limitations under the License. - * - * - * - */ - -#include "../ar6000/athdrv_linux.h" - -#endif /* _ADRV_H_ */ diff --git a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/include/a_drv_api.h b/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/include/a_drv_api.h deleted file mode 100644 index 75317260c..000000000 --- a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/include/a_drv_api.h +++ /dev/null @@ -1,185 +0,0 @@ -#ifndef _A_DRV_API_H_ -#define _A_DRV_API_H_ -/* - * Copyright (c) 2004-2006 Atheros Communications Inc. - * All rights reserved. - * - * - * 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; - * - * Software distributed under the License is distributed on an "AS - * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or - * implied. See the License for the specific language governing - * rights and limitations under the License. - * - * - * - */ - -#ifdef __cplusplus -extern "C" { -#endif - -/****************************************************************************/ -/****************************************************************************/ -/** **/ -/** WMI related hooks **/ -/** **/ -/****************************************************************************/ -/****************************************************************************/ - -#include - -#define A_WMI_CHANNELLIST_RX(devt, numChan, chanList) \ - ar6000_channelList_rx((devt), (numChan), (chanList)) - -#define A_WMI_SET_NUMDATAENDPTS(devt, num) \ - ar6000_set_numdataendpts((devt), (num)) - -#define A_WMI_CONTROL_TX(devt, osbuf, streamID) \ - ar6000_control_tx((devt), (osbuf), (streamID)) - -#define A_WMI_TARGETSTATS_EVENT(devt, pStats) \ - ar6000_targetStats_event((devt), (pStats)) - -#define A_WMI_SCANCOMPLETE_EVENT(devt, status) \ - ar6000_scanComplete_event((devt), (status)) - -#ifdef CONFIG_HOST_DSET_SUPPORT - -#define A_WMI_DSET_DATA_REQ(devt, access_cookie, offset, length, targ_buf, targ_reply_fn, targ_reply_arg) \ - ar6000_dset_data_req((devt), (access_cookie), (offset), (length), (targ_buf), (targ_reply_fn), (targ_reply_arg)) - -#define A_WMI_DSET_CLOSE(devt, access_cookie) \ - ar6000_dset_close((devt), (access_cookie)) - -#endif - -#define A_WMI_DSET_OPEN_REQ(devt, id, targ_handle, targ_reply_fn, targ_reply_arg) \ - ar6000_dset_open_req((devt), (id), (targ_handle), (targ_reply_fn), (targ_reply_arg)) - -#define A_WMI_CONNECT_EVENT(devt, channel, bssid, listenInterval, beaconInterval, networkType, beaconIeLen, assocReqLen, assocRespLen, assocInfo) \ - ar6000_connect_event((devt), (channel), (bssid), (listenInterval), (beaconInterval), (networkType), (beaconIeLen), (assocReqLen), (assocRespLen), (assocInfo)) - -#define A_WMI_REGDOMAIN_EVENT(devt, regCode) \ - ar6000_regDomain_event((devt), (regCode)) - -#define A_WMI_NEIGHBORREPORT_EVENT(devt, numAps, info) \ - ar6000_neighborReport_event((devt), (numAps), (info)) - -#define A_WMI_DISCONNECT_EVENT(devt, reason, bssid, assocRespLen, assocInfo, protocolReasonStatus) \ - ar6000_disconnect_event((devt), (reason), (bssid), (assocRespLen), (assocInfo), (protocolReasonStatus)) - -#define A_WMI_TKIP_MICERR_EVENT(devt, keyid, ismcast) \ - ar6000_tkip_micerr_event((devt), (keyid), (ismcast)) - -#define A_WMI_BITRATE_RX(devt, rateKbps) \ - ar6000_bitrate_rx((devt), (rateKbps)) - -#define A_WMI_TXPWR_RX(devt, txPwr) \ - ar6000_txPwr_rx((devt), (txPwr)) - -#define A_WMI_READY_EVENT(devt, datap, phyCap) \ - ar6000_ready_event((devt), (datap), (phyCap)) - -#define A_WMI_DBGLOG_INIT_DONE(ar) \ - ar6000_dbglog_init_done(ar); - -#define A_WMI_RSSI_THRESHOLD_EVENT(devt, newThreshold, rssi) \ - ar6000_rssiThreshold_event((devt), (newThreshold), (rssi)) - -#define A_WMI_REPORT_ERROR_EVENT(devt, errorVal) \ - ar6000_reportError_event((devt), (errorVal)) - -#define A_WMI_ROAM_TABLE_EVENT(devt, pTbl) \ - ar6000_roam_tbl_event((devt), (pTbl)) - -#define A_WMI_ROAM_DATA_EVENT(devt, p) \ - ar6000_roam_data_event((devt), (p)) - -#define A_WMI_WOW_LIST_EVENT(devt, num_filters, wow_filters) \ - ar6000_wow_list_event((devt), (num_filters), (wow_filters)) - -#define A_WMI_CAC_EVENT(devt, ac, cac_indication, statusCode, tspecSuggestion) \ - ar6000_cac_event((devt), (ac), (cac_indication), (statusCode), (tspecSuggestion)) - -#define A_WMI_IPTOS_TO_USERPRIORITY(pkt) \ - ar6000_iptos_to_userPriority((pkt)) - -#define A_WMI_PMKID_LIST_EVENT(devt, num_pmkid, pmkid_list) \ - ar6000_pmkid_list_event((devt), (num_pmkid), (pmkid_list)) - -#ifdef CONFIG_HOST_GPIO_SUPPORT - -#define A_WMI_GPIO_INTR_RX(intr_mask, input_values) \ - ar6000_gpio_intr_rx((intr_mask), (input_values)) - -#define A_WMI_GPIO_DATA_RX(reg_id, value) \ - ar6000_gpio_data_rx((reg_id), (value)) - -#define A_WMI_GPIO_ACK_RX() \ - ar6000_gpio_ack_rx() - -#endif - -#ifdef SEND_EVENT_TO_APP - -#define A_WMI_SEND_EVENT_TO_APP(ar, eventId, datap, len) \ - ar6000_send_event_to_app((ar), (eventId), (datap), (len)) - -#else - -#define A_WMI_SEND_EVENT_TO_APP(ar, eventId, datap, len) - -#endif - -#ifdef CONFIG_HOST_TCMD_SUPPORT -#define A_WMI_TCMD_RX_REPORT_EVENT(devt, results, len) \ - ar6000_tcmd_rx_report_event((devt), (results), (len)) -#endif - -#define A_WMI_HBCHALLENGERESP_EVENT(devt, cookie, source) \ - ar6000_hbChallengeResp_event((devt), (cookie), (source)) - -#define A_WMI_TX_RETRY_ERR_EVENT(devt) \ - ar6000_tx_retry_err_event((devt)) - -#define A_WMI_SNR_THRESHOLD_EVENT_RX(devt, newThreshold, snr) \ - ar6000_snrThresholdEvent_rx((devt), (newThreshold), (snr)) - -#define A_WMI_LQ_THRESHOLD_EVENT_RX(devt, range, lqVal) \ - ar6000_lqThresholdEvent_rx((devt), (range), (lqVal)) - -#define A_WMI_RATEMASK_RX(devt, ratemask) \ - ar6000_ratemask_rx((devt), (ratemask)) - -#define A_WMI_KEEPALIVE_RX(devt, configured) \ - ar6000_keepalive_rx((devt), (configured)) - -#define A_WMI_BSSINFO_EVENT_RX(ar, datp, len) \ - ar6000_bssInfo_event_rx((ar), (datap), (len)) - -#define A_WMI_DBGLOG_EVENT(ar, dropped, buffer, length) \ - ar6000_dbglog_event((ar), (dropped), (buffer), (length)); - -#define A_WMI_STREAM_TX_ACTIVE(devt,trafficClass) \ - ar6000_indicate_tx_activity((devt),(trafficClass), TRUE) - -#define A_WMI_STREAM_TX_INACTIVE(devt,trafficClass) \ - ar6000_indicate_tx_activity((devt),(trafficClass), FALSE) - -/****************************************************************************/ -/****************************************************************************/ -/** **/ -/** HTC related hooks **/ -/** **/ -/****************************************************************************/ -/****************************************************************************/ - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/include/a_osapi.h b/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/include/a_osapi.h deleted file mode 100644 index 7d6086712..000000000 --- a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/include/a_osapi.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef _A_OSAPI_H_ -#define _A_OSAPI_H_ -/* - * $Id: //depot/sw/releases/olca2.0-GPL/host/include/a_osapi.h#1 $ - * - * This file contains the definitions of the basic atheros data types. - * It is used to map the data types in atheros files to a platform specific - * type. - * - * Copyright 2003-2005 Atheros Communications, Inc., All Rights Reserved. - * - * - * 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; - * - * Software distributed under the License is distributed on an "AS - * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or - * implied. See the License for the specific language governing - * rights and limitations under the License. - * - * - * - */ - -#include "../ar6000/osapi_linux.h" - -#endif /* _OSAPI_H_ */ diff --git a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/include/a_types.h b/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/include/a_types.h deleted file mode 100644 index e2ed09076..000000000 --- a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/include/a_types.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef _A_TYPES_H_ -#define _A_TYPES_H_ -/* - * $Id: //depot/sw/releases/olca2.0-GPL/host/include/a_types.h#1 $ - * - * This file contains the definitions of the basic atheros data types. - * It is used to map the data types in atheros files to a platform specific - * type. - * - * Copyright 2003-2005 Atheros Communications, Inc., All Rights Reserved. - * - * - * 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; - * - * Software distributed under the License is distributed on an "AS - * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or - * implied. See the License for the specific language governing - * rights and limitations under the License. - * - * - * - */ - -#include "../ar6000/athtypes_linux.h" - -#endif /* _ATHTYPES_H_ */ diff --git a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/include/ar6000_api.h b/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/include/ar6000_api.h deleted file mode 100644 index abe5de79a..000000000 --- a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/include/ar6000_api.h +++ /dev/null @@ -1,29 +0,0 @@ -#ifndef _AR6000_API_H_ -#define _AR6000_API_H_ -/* - * Copyright (c) 2004-2005 Atheros Communications Inc. - * All rights reserved. - * - * This file contains the API to access the OS dependent atheros host driver - * by the WMI or WLAN generic modules. - * - * $Id: //depot/sw/releases/olca2.0-GPL/host/include/ar6000_api.h#1 $ - * - * - * 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; - * - * Software distributed under the License is distributed on an "AS - * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or - * implied. See the License for the specific language governing - * rights and limitations under the License. - * - * - * - */ - -#include "../ar6000/ar6xapi_linux.h" - -#endif /* _AR6000_API_H */ - diff --git a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/include/ar6000_diag.h b/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/include/ar6000_diag.h deleted file mode 100644 index 2df131df2..000000000 --- a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/include/ar6000_diag.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * - * Copyright (c) 2004-2007 Atheros Communications Inc. - * All rights reserved. - * - * - * 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; - * - * Software distributed under the License is distributed on an "AS - * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or - * implied. See the License for the specific language governing - * rights and limitations under the License. - * - * - * - */ - -#ifndef AR6000_DIAG_H_ -#define AR6000_DIAG_H_ - - -A_STATUS -ar6000_ReadRegDiag(HIF_DEVICE *hifDevice, A_UINT32 *address, A_UINT32 *data); - -A_STATUS -ar6000_WriteRegDiag(HIF_DEVICE *hifDevice, A_UINT32 *address, A_UINT32 *data); - -A_STATUS -ar6000_ReadDataDiag(HIF_DEVICE *hifDevice, A_UINT32 address, - A_UCHAR *data, A_UINT32 length); - -A_STATUS -ar6000_WriteDataDiag(HIF_DEVICE *hifDevice, A_UINT32 address, - A_UCHAR *data, A_UINT32 length); - -#endif /*AR6000_DIAG_H_*/ diff --git a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/include/athdefs.h b/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/include/athdefs.h deleted file mode 100644 index c28c871c5..000000000 --- a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/include/athdefs.h +++ /dev/null @@ -1,85 +0,0 @@ -#ifndef __ATHDEFS_H__ -#define __ATHDEFS_H__ - -/* - * Copyright (c) 2004-2007 Atheros Communications Inc. - * All rights reserved. - * - * $ATH_LICENSE_HOSTSDK0_C$ - * - * This file contains definitions that may be used across both - * Host and Target software. Nothing here is module-dependent - * or platform-dependent. - */ - -/* - * Generic error codes that can be used by hw, sta, ap, sim, dk - * and any other environments. Since these are enums, feel free to - * add any more codes that you need. - */ - -typedef enum { - A_ERROR = -1, /* Generic error return */ - A_OK = 0, /* success */ - /* Following values start at 1 */ - A_DEVICE_NOT_FOUND, /* not able to find PCI device */ - A_NO_MEMORY, /* not able to allocate memory, not available */ - A_MEMORY_NOT_AVAIL, /* memory region is not free for mapping */ - A_NO_FREE_DESC, /* no free descriptors available */ - A_BAD_ADDRESS, /* address does not match descriptor */ - A_WIN_DRIVER_ERROR, /* used in NT_HW version, if problem at init */ - A_REGS_NOT_MAPPED, /* registers not correctly mapped */ - A_EPERM, /* Not superuser */ - A_EACCES, /* Access denied */ - A_ENOENT, /* No such entry, search failed, etc. */ - A_EEXIST, /* The object already exists (can't create) */ - A_EFAULT, /* Bad address fault */ - A_EBUSY, /* Object is busy */ - A_EINVAL, /* Invalid parameter */ - A_EMSGSIZE, /* Inappropriate message buffer length */ - A_ECANCELED, /* Operation canceled */ - A_ENOTSUP, /* Operation not supported */ - A_ECOMM, /* Communication error on send */ - A_EPROTO, /* Protocol error */ - A_ENODEV, /* No such device */ - A_EDEVNOTUP, /* device is not UP */ - A_NO_RESOURCE, /* No resources for requested operation */ - A_HARDWARE, /* Hardware failure */ - A_PENDING, /* Asynchronous routine; will send up results la -ter (typically in callback) */ - A_EBADCHANNEL, /* The channel cannot be used */ - A_DECRYPT_ERROR, /* Decryption error */ - A_PHY_ERROR, /* RX PHY error */ - A_CONSUMED /* Object was consumed */ -} A_STATUS; - -#define A_SUCCESS(x) (x == A_OK) -#define A_FAILED(x) (!A_SUCCESS(x)) - -#ifndef TRUE -#define TRUE 1 -#endif - -#ifndef FALSE -#define FALSE 0 -#endif - -/* - * The following definition is WLAN specific definition - */ -typedef enum { - MODE_11A = 0, /* 11a Mode */ - MODE_11G = 1, /* 11g + 11b Mode */ - MODE_11B = 2, /* 11b Mode */ - MODE_11GONLY = 3, /* 11g only Mode */ - MODE_UNKNOWN = 4, - MODE_MAX = 4 -} WLAN_PHY_MODE; - -typedef enum { - WLAN_11A_CAPABILITY = 1, - WLAN_11G_CAPABILITY = 2, - WLAN_11AG_CAPABILITY = 3, -}WLAN_CAPABILITY; - -#endif /* __ATHDEFS_H__ */ diff --git a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/include/athdrv.h b/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/include/athdrv.h deleted file mode 100644 index 19da97e4b..000000000 --- a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/include/athdrv.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (c) 2004-2006 Atheros Communications Inc. - * All rights reserved. - * - * - * - * 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; - * - * Software distributed under the License is distributed on an "AS - * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or - * implied. See the License for the specific language governing - * rights and limitations under the License. - * - * - * - */ - -#ifndef _ATHDRV_H_ -#define _ATHDRV_H_ - -#ifdef __cplusplus -extern "C" { -#endif - - -#ifdef __cplusplus -} -#endif - -#endif /* _ATHDRV_H_ */ diff --git a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/include/athendpack.h b/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/include/athendpack.h deleted file mode 100644 index 42921ae7f..000000000 --- a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/include/athendpack.h +++ /dev/null @@ -1,41 +0,0 @@ -/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - * @file: athendpack.h - * - * @abstract: end compiler-specific structure packing - * - * Copyright (c) 2004-2007 Atheros Communications Inc. - * All rights reserved. - * - * - * 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; - * - * Software distributed under the License is distributed on an "AS - * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or - * implied. See the License for the specific language governing - * rights and limitations under the License. - * - * - * - */ -#ifdef VXWORKS -#endif /* VXWORKS */ - -#ifdef LINUX -#endif /* LINUX */ - -#ifdef QNX -#endif /* QNX */ - -#ifdef INTEGRITY -#include "integrity/athendpack_integrity.h" -#endif /* INTEGRITY */ - -#ifdef NUCLEUS -#endif /* NUCLEUS */ - -#ifdef UNDER_CE -#include "../os/wince/include/athendpack_wince.h" -#endif /* WINCE */ - diff --git a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/include/athstartpack.h b/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/include/athstartpack.h deleted file mode 100644 index 6632cc2cb..000000000 --- a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/include/athstartpack.h +++ /dev/null @@ -1,42 +0,0 @@ -/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - * @file: athstartpack.h - * - * @abstract: start compiler-specific structure packing - * - * Copyright (c) 2004-2007 Atheros Communications Inc. - * All rights reserved. - * - * - * 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; - * - * Software distributed under the License is distributed on an "AS - * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or - * implied. See the License for the specific language governing - * rights and limitations under the License. - * - * - * - */ - -#ifdef VXWORKS -#endif /* VXWORKS */ - -#ifdef LINUX -#endif /* LINUX */ - -#ifdef QNX -#endif /* QNX */ - -#ifdef INTEGRITY -#include "integrity/athstartpack_integrity.h" -#endif /* INTEGRITY */ - -#ifdef NUCLEUS -#endif /* NUCLEUS */ - -#ifdef UNDER_CE -#include "../os/wince/include/athstartpack_wince.h" -#endif /* WINCE */ - diff --git a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/include/bmi.h b/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/include/bmi.h deleted file mode 100644 index 2eb7134c7..000000000 --- a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/include/bmi.h +++ /dev/null @@ -1,100 +0,0 @@ -#ifndef _BMI_H_ -#define _BMI_H_ -/* - * Copyright (c) 2004-2005 Atheros Communications Inc. - * All rights reserved. - * - * - * 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; - * - * Software distributed under the License is distributed on an "AS - * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or - * implied. See the License for the specific language governing - * rights and limitations under the License. - * - * - * - * BMI declarations and prototypes - */ - -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ - -/* Header files */ -#include "a_config.h" -#include "athdefs.h" -#include "a_types.h" -#include "hif.h" -#include "a_osapi.h" -#include "bmi_msg.h" - -void -BMIInit(void); - -A_STATUS -BMIDone(HIF_DEVICE *device); - -A_STATUS -BMIGetTargetInfo(HIF_DEVICE *device, struct bmi_target_info *targ_info); - -A_STATUS -BMIReadMemory(HIF_DEVICE *device, - A_UINT32 address, - A_UCHAR *buffer, - A_UINT32 length); - -A_STATUS -BMIWriteMemory(HIF_DEVICE *device, - A_UINT32 address, - A_UCHAR *buffer, - A_UINT32 length); - -A_STATUS -BMIExecute(HIF_DEVICE *device, - A_UINT32 address, - A_UINT32 *param); - -A_STATUS -BMISetAppStart(HIF_DEVICE *device, - A_UINT32 address); - -A_STATUS -BMIReadSOCRegister(HIF_DEVICE *device, - A_UINT32 address, - A_UINT32 *param); - -A_STATUS -BMIWriteSOCRegister(HIF_DEVICE *device, - A_UINT32 address, - A_UINT32 param); - -A_STATUS -BMIrompatchInstall(HIF_DEVICE *device, - A_UINT32 ROM_addr, - A_UINT32 RAM_addr, - A_UINT32 nbytes, - A_UINT32 do_activate, - A_UINT32 *patch_id); - -A_STATUS -BMIrompatchUninstall(HIF_DEVICE *device, - A_UINT32 rompatch_id); - -A_STATUS -BMIrompatchActivate(HIF_DEVICE *device, - A_UINT32 rompatch_count, - A_UINT32 *rompatch_list); - -A_STATUS -BMIrompatchDeactivate(HIF_DEVICE *device, - A_UINT32 rompatch_count, - A_UINT32 *rompatch_list); - -#ifdef __cplusplus -} -#endif - -#endif /* _BMI_H_ */ diff --git a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/include/bmi_msg.h b/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/include/bmi_msg.h deleted file mode 100644 index 7c91ef473..000000000 --- a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/include/bmi_msg.h +++ /dev/null @@ -1,199 +0,0 @@ -#ifndef __BMI_MSG_H__ -#define __BMI_MSG_H__ -/* - * - * Copyright (c) 2004-2007 Atheros Communications Inc. - * All rights reserved. - * - * - * 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; - * - * Software distributed under the License is distributed on an "AS - * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or - * implied. See the License for the specific language governing - * rights and limitations under the License. - * - * - * - */ - -/* - * Bootloader Messaging Interface (BMI) - * - * BMI is a very simple messaging interface used during initialization - * to read memory, write memory, execute code, and to define an - * application entry PC. - * - * It is used to download an application to AR6K, to provide - * patches to code that is already resident on AR6K, and generally - * to examine and modify state. The Host has an opportunity to use - * BMI only once during bootup. Once the Host issues a BMI_DONE - * command, this opportunity ends. - * - * The Host writes BMI requests to mailbox0, and reads BMI responses - * from mailbox0. BMI requests all begin with a command - * (see below for specific commands), and are followed by - * command-specific data. - * - * Flow control: - * The Host can only issue a command once the Target gives it a - * "BMI Command Credit", using AR6K Counter #4. As soon as the - * Target has completed a command, it issues another BMI Command - * Credit (so the Host can issue the next command). - * - * BMI handles all required Target-side cache flushing. - */ - - -/* Maximum data size used for BMI transfers */ -#define BMI_DATASZ_MAX 32 - -/* BMI Commands */ - -#define BMI_NO_COMMAND 0 - -#define BMI_DONE 1 - /* - * Semantics: Host is done using BMI - * Request format: - * A_UINT32 command (BMI_DONE) - * Response format: none - */ - -#define BMI_READ_MEMORY 2 - /* - * Semantics: Host reads AR6K memory - * Request format: - * A_UINT32 command (BMI_READ_MEMORY) - * A_UINT32 address - * A_UINT32 length, at most BMI_DATASZ_MAX - * Response format: - * A_UINT8 data[length] - */ - -#define BMI_WRITE_MEMORY 3 - /* - * Semantics: Host writes AR6K memory - * Request format: - * A_UINT32 command (BMI_WRITE_MEMORY) - * A_UINT32 address - * A_UINT32 length, at most BMI_DATASZ_MAX - * A_UINT8 data[length] - * Response format: none - */ - -#define BMI_EXECUTE 4 - /* - * Semantics: Causes AR6K to execute code - * Request format: - * A_UINT32 command (BMI_EXECUTE) - * A_UINT32 address - * A_UINT32 parameter - * Response format: - * A_UINT32 return value - */ - -#define BMI_SET_APP_START 5 - /* - * Semantics: Set Target application starting address - * Request format: - * A_UINT32 command (BMI_SET_APP_START) - * A_UINT32 address - * Response format: none - */ - -#define BMI_READ_SOC_REGISTER 6 - /* - * Semantics: Read a 32-bit Target SOC register. - * Request format: - * A_UINT32 command (BMI_READ_REGISTER) - * A_UINT32 address - * Response format: - * A_UINT32 value - */ - -#define BMI_WRITE_SOC_REGISTER 7 - /* - * Semantics: Write a 32-bit Target SOC register. - * Request format: - * A_UINT32 command (BMI_WRITE_REGISTER) - * A_UINT32 address - * A_UINT32 value - * - * Response format: none - */ - -#define BMI_GET_TARGET_ID 8 -#define BMI_GET_TARGET_INFO 8 - /* - * Semantics: Fetch the 4-byte Target information - * Request format: - * A_UINT32 command (BMI_GET_TARGET_ID/INFO) - * Response format1 (old firmware): - * A_UINT32 TargetVersionID - * Response format2 (newer firmware): - * A_UINT32 TARGET_VERSION_SENTINAL - * struct bmi_target_info; - */ - -struct bmi_target_info { - A_UINT32 target_info_byte_count; /* size of this structure */ - A_UINT32 target_ver; /* Target Version ID */ - A_UINT32 target_type; /* Target type */ -}; -#define TARGET_VERSION_SENTINAL 0xffffffff -#define TARGET_TYPE_AR6001 1 -#define TARGET_TYPE_AR6002 2 - - -#define BMI_ROMPATCH_INSTALL 9 - /* - * Semantics: Install a ROM Patch. - * Request format: - * A_UINT32 command (BMI_ROMPATCH_INSTALL) - * A_UINT32 Target ROM Address - * A_UINT32 Target RAM Address - * A_UINT32 Size, in bytes - * A_UINT32 Activate? 1-->activate; - * 0-->install but do not activate - * Response format: - * A_UINT32 PatchID - */ - -#define BMI_ROMPATCH_UNINSTALL 10 - /* - * Semantics: Uninstall a previously-installed ROM Patch, - * automatically deactivating, if necessary. - * Request format: - * A_UINT32 command (BMI_ROMPATCH_UNINSTALL) - * A_UINT32 PatchID - * - * Response format: none - */ - -#define BMI_ROMPATCH_ACTIVATE 11 - /* - * Semantics: Activate a list of previously-installed ROM Patches. - * Request format: - * A_UINT32 command (BMI_ROMPATCH_ACTIVATE) - * A_UINT32 rompatch_count - * A_UINT32 PatchID[rompatch_count] - * - * Response format: none - */ - -#define BMI_ROMPATCH_DEACTIVATE 12 - /* - * Semantics: Deactivate a list of active ROM Patches. - * Request format: - * A_UINT32 command (BMI_ROMPATCH_DEACTIVATE) - * A_UINT32 rompatch_count - * A_UINT32 PatchID[rompatch_count] - * - * Response format: none - */ - - -#endif /* __BMI_MSG_H__ */ diff --git a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/include/common_drv.h b/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/include/common_drv.h deleted file mode 100644 index 1bdc3dae5..000000000 --- a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/include/common_drv.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - * - * Copyright (c) 2004-2007 Atheros Communications Inc. - * All rights reserved. - * - * - * 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; - * - * Software distributed under the License is distributed on an "AS - * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or - * implied. See the License for the specific language governing - * rights and limitations under the License. - * - * - * - */ - - -#ifndef COMMON_DRV_H_ -#define COMMON_DRV_H_ - -#include "hif.h" -#include "htc_packet.h" - - - -/* structure that is the state information for the default credit distribution callback - * drivers should instantiate (zero-init as well) this structure in their driver instance - * and pass it as a context to the HTC credit distribution functions */ -typedef struct _COMMON_CREDIT_STATE_INFO { - int TotalAvailableCredits; /* total credits in the system at startup */ - int CurrentFreeCredits; /* credits available in the pool that have not been - given out to endpoints */ - HTC_ENDPOINT_CREDIT_DIST *pLowestPriEpDist; /* pointer to the lowest priority endpoint dist struct */ -} COMMON_CREDIT_STATE_INFO; - - -/* HTC TX packet tagging definitions */ -#define AR6K_CONTROL_PKT_TAG HTC_TX_PACKET_TAG_USER_DEFINED -#define AR6K_DATA_PKT_TAG (AR6K_CONTROL_PKT_TAG + 1) - -#ifdef __cplusplus -extern "C" { -#endif - -/* OS-independent APIs */ -A_STATUS ar6000_setup_credit_dist(HTC_HANDLE HTCHandle, COMMON_CREDIT_STATE_INFO *pCredInfo); -A_STATUS ar6000_ReadRegDiag(HIF_DEVICE *hifDevice, A_UINT32 *address, A_UINT32 *data); -A_STATUS ar6000_WriteRegDiag(HIF_DEVICE *hifDevice, A_UINT32 *address, A_UINT32 *data); -A_STATUS ar6000_ReadDataDiag(HIF_DEVICE *hifDevice, A_UINT32 address, A_UCHAR *data, A_UINT32 length); -A_STATUS ar6000_reset_device(HIF_DEVICE *hifDevice, A_UINT32 TargetType); -void ar6000_dump_target_assert_info(HIF_DEVICE *hifDevice, A_UINT32 TargetType); -A_STATUS ar6000_reset_device_skipflash(HIF_DEVICE *hifDevice); - -#ifdef __cplusplus -} -#endif - -#endif /*COMMON_DRV_H_*/ diff --git a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/include/dbglog.h b/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/include/dbglog.h deleted file mode 100644 index 3d1e528f7..000000000 --- a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/include/dbglog.h +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright (c) 2004-2007 Atheros Communications Inc. - * All rights reserved. - * - * $ATH_LICENSE_HOSTSDK0_C$ - * - * This file contains the definitions and data structures associated with - * the log based debug mechanism. - * - */ - -#ifndef _DBGLOG_H_ -#define _DBGLOG_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -#define DBGLOG_TIMESTAMP_OFFSET 0 -#define DBGLOG_TIMESTAMP_MASK 0x0000FFFF /* Bit 0-15. Contains bit - 8-23 of the LF0 timer */ -#define DBGLOG_DBGID_OFFSET 16 -#define DBGLOG_DBGID_MASK 0x03FF0000 /* Bit 16-25 */ -#define DBGLOG_DBGID_NUM_MAX 256 /* Upper limit is width of mask */ - -#define DBGLOG_MODULEID_OFFSET 26 -#define DBGLOG_MODULEID_MASK 0x3C000000 /* Bit 26-29 */ -#define DBGLOG_MODULEID_NUM_MAX 16 /* Upper limit is width of mask */ - -/* - * Please ensure that the definition of any new module intrduced is captured - * between the DBGLOG_MODULEID_START and DBGLOG_MODULEID_END defines. The - * structure is required for the parser to correctly pick up the values for - * different modules. - */ -#define DBGLOG_MODULEID_START -#define DBGLOG_MODULEID_INF 0 -#define DBGLOG_MODULEID_WMI 1 -#define DBGLOG_MODULEID_CSERV 2 -#define DBGLOG_MODULEID_PM 3 -#define DBGLOG_MODULEID_TXRX_MGMTBUF 4 -#define DBGLOG_MODULEID_TXRX_TXBUF 5 -#define DBGLOG_MODULEID_TXRX_RXBUF 6 -#define DBGLOG_MODULEID_WOW 7 -#define DBGLOG_MODULEID_WHAL 8 -#define DBGLOG_MODULEID_END - -#define DBGLOG_NUM_ARGS_OFFSET 30 -#define DBGLOG_NUM_ARGS_MASK 0xC0000000 /* Bit 30-31 */ -#define DBGLOG_NUM_ARGS_MAX 2 /* Upper limit is width of mask */ - -#define DBGLOG_MODULE_LOG_ENABLE_OFFSET 0 -#define DBGLOG_MODULE_LOG_ENABLE_MASK 0x0000FFFF - -#define DBGLOG_REPORTING_ENABLED_OFFSET 16 -#define DBGLOG_REPORTING_ENABLED_MASK 0x00010000 - -#define DBGLOG_TIMESTAMP_RESOLUTION_OFFSET 17 -#define DBGLOG_TIMESTAMP_RESOLUTION_MASK 0x000E0000 - -#define DBGLOG_REPORT_SIZE_OFFSET 20 -#define DBGLOG_REPORT_SIZE_MASK 0x3FF00000 - -#define DBGLOG_LOG_BUFFER_SIZE 1500 -#define DBGLOG_DBGID_DEFINITION_LEN_MAX 64 - -struct dbglog_buf_s { - struct dbglog_buf_s *next; - A_INT8 *buffer; - A_UINT32 bufsize; - A_UINT32 length; - A_UINT32 count; - A_UINT32 free; -}; - -struct dbglog_hdr_s { - struct dbglog_buf_s *dbuf; - A_UINT32 dropped; -}; - -struct dbglog_config_s { - A_UINT32 cfgvalid; /* Mask with valid config bits */ - union { - /* TODO: Take care of endianness */ - struct { - A_UINT32 mmask:16; /* Mask of modules with logging on */ - A_UINT32 rep:1; /* Reporting enabled or not */ - A_UINT32 tsr:3; /* Time stamp resolution. Def: 1 ms */ - A_UINT32 size:10; /* Report size in number of messages */ - A_UINT32 reserved:2; - } dbglog_config; - - A_UINT32 value; - } u; -}; - -#define cfgmmask u.dbglog_config.mmask -#define cfgrep u.dbglog_config.rep -#define cfgtsr u.dbglog_config.tsr -#define cfgsize u.dbglog_config.size -#define cfgvalue u.value - -#ifdef __cplusplus -} -#endif - -#endif /* _DBGLOG_H_ */ diff --git a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/include/dbglog_api.h b/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/include/dbglog_api.h deleted file mode 100644 index 06c8102e1..000000000 --- a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/include/dbglog_api.h +++ /dev/null @@ -1,46 +0,0 @@ -#ifndef _DBGLOG_API_H_ -#define _DBGLOG_API_H_ -/* - * Copyright (c) 2004-2006 Atheros Communications Inc. - * All rights reserved. - * - * - * 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; - * - * Software distributed under the License is distributed on an "AS - * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or - * implied. See the License for the specific language governing - * rights and limitations under the License. - * - * - * - * This file contains host side debug primitives. - */ - -#ifdef __cplusplus -extern "C" { -#endif - -#include "dbglog.h" - -#define DBGLOG_HOST_LOG_BUFFER_SIZE DBGLOG_LOG_BUFFER_SIZE - -#define DBGLOG_GET_DBGID(arg) \ - ((arg & DBGLOG_DBGID_MASK) >> DBGLOG_DBGID_OFFSET) - -#define DBGLOG_GET_MODULEID(arg) \ - ((arg & DBGLOG_MODULEID_MASK) >> DBGLOG_MODULEID_OFFSET) - -#define DBGLOG_GET_NUMARGS(arg) \ - ((arg & DBGLOG_NUM_ARGS_MASK) >> DBGLOG_NUM_ARGS_OFFSET) - -#define DBGLOG_GET_TIMESTAMP(arg) \ - ((arg & DBGLOG_TIMESTAMP_MASK) >> DBGLOG_TIMESTAMP_OFFSET) - -#ifdef __cplusplus -} -#endif - -#endif /* _DBGLOG_API_H_ */ diff --git a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/include/dbglog_id.h b/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/include/dbglog_id.h deleted file mode 100644 index ce22b1682..000000000 --- a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/include/dbglog_id.h +++ /dev/null @@ -1,307 +0,0 @@ -/* - * - * Copyright (c) 2004-2007 Atheros Communications Inc. - * All rights reserved. - * - * $ATH_LICENSE_HOSTSDK0_C$ - * - * This file contains the definitions of the debug identifiers for different - * modules. - * - */ - -#ifndef _DBGLOG_ID_H_ -#define _DBGLOG_ID_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * The nomenclature for the debug identifiers is MODULE_DESCRIPTION. - * Please ensure that the definition of any new debugid introduced is captured - * between the _DBGID_DEFINITION_START and - * _DBGID_DEFINITION_END defines. The structure is required for the - * parser to correctly pick up the values for different debug identifiers. - */ - -/* INF debug identifier definitions */ -#define INF_DBGID_DEFINITION_START -#define INF_ASSERTION_FAILED 1 -#define INF_TARGET_ID 2 -#define INF_DBGID_DEFINITION_END - -/* WMI debug identifier definitions */ -#define WMI_DBGID_DEFINITION_START -#define WMI_CMD_RX_XTND_PKT_TOO_SHORT 1 -#define WMI_EXTENDED_CMD_NOT_HANDLED 2 -#define WMI_CMD_RX_PKT_TOO_SHORT 3 -#define WMI_CALLING_WMI_EXTENSION_FN 4 -#define WMI_CMD_NOT_HANDLED 5 -#define WMI_IN_SYNC 6 -#define WMI_TARGET_WMI_SYNC_CMD 7 -#define WMI_SET_SNR_THRESHOLD_PARAMS 8 -#define WMI_SET_RSSI_THRESHOLD_PARAMS 9 -#define WMI_SET_LQ_TRESHOLD_PARAMS 10 -#define WMI_TARGET_CREATE_PSTREAM_CMD 11 -#define WMI_WI_DTM_INUSE 12 -#define WMI_TARGET_DELETE_PSTREAM_CMD 13 -#define WMI_TARGET_IMPLICIT_DELETE_PSTREAM_CMD 14 -#define WMI_TARGET_GET_BIT_RATE_CMD 15 -#define WMI_GET_RATE_MASK_CMD_FIX_RATE_MASK_IS 16 -#define WMI_TARGET_GET_AVAILABLE_CHANNELS_CMD 17 -#define WMI_TARGET_GET_TX_PWR_CMD 18 -#define WMI_FREE_EVBUF_WMIBUF 19 -#define WMI_FREE_EVBUF_DATABUF 20 -#define WMI_FREE_EVBUF_BADFLAG 21 -#define WMI_HTC_RX_ERROR_DATA_PACKET 22 -#define WMI_HTC_RX_SYNC_PAUSING_FOR_MBOX 23 -#define WMI_INCORRECT_WMI_DATA_HDR_DROPPING_PKT 24 -#define WMI_SENDING_READY_EVENT 25 -#define WMI_SETPOWER_MDOE_TO_MAXPERF 26 -#define WMI_SETPOWER_MDOE_TO_REC 27 -#define WMI_BSSINFO_EVENT_FROM 28 -#define WMI_TARGET_GET_STATS_CMD 29 -#define WMI_SENDING_SCAN_COMPLETE_EVENT 30 -#define WMI_SENDING_RSSI_INDB_THRESHOLD_EVENT 31 -#define WMI_SENDING_RSSI_INDBM_THRESHOLD_EVENT 32 -#define WMI_SENDING_LINK_QUALITY_THRESHOLD_EVENT 33 -#define WMI_SENDING_ERROR_REPORT_EVENT 34 -#define WMI_SENDING_CAC_EVENT 35 -#define WMI_TARGET_GET_ROAM_TABLE_CMD 36 -#define WMI_TARGET_GET_ROAM_DATA_CMD 37 -#define WMI_SENDING_GPIO_INTR_EVENT 38 -#define WMI_SENDING_GPIO_ACK_EVENT 39 -#define WMI_SENDING_GPIO_DATA_EVENT 40 -#define WMI_CMD_RX 41 -#define WMI_CMD_RX_XTND 42 -#define WMI_EVENT_SEND 43 -#define WMI_EVENT_SEND_XTND 44 -#define WMI_DBGID_DEFINITION_END - -/* CSERV debug identifier definitions */ -#define CSERV_DBGID_DEFINITION_START -#define CSERV_BEGIN_SCAN1 1 -#define CSERV_BEGIN_SCAN2 2 -#define CSERV_END_SCAN1 3 -#define CSERV_END_SCAN2 4 -#define CSERV_CHAN_SCAN_START 5 -#define CSERV_CHAN_SCAN_STOP 6 -#define CSERV_CHANNEL_OPPPORTUNITY 7 -#define CSERV_NC_TIMEOUT 8 -#define CSERV_BACK_HOME 10 -#define CSERV_CHMGR_CH_CALLBACK1 11 -#define CSERV_CHMGR_CH_CALLBACK2 12 -#define CSERV_CHMGR_CH_CALLBACK3 13 -#define CSERV_SET_SCAN_PARAMS1 14 -#define CSERV_SET_SCAN_PARAMS2 15 -#define CSERV_SET_SCAN_PARAMS3 16 -#define CSERV_SET_SCAN_PARAMS4 17 -#define CSERV_ABORT_SCAN 18 -#define CSERV_NEWSTATE 19 -#define CSERV_MINCHMGR_OP_END 20 -#define CSERV_CHMGR_OP_END 21 -#define CSERV_DISCONNECT_TIMEOUT 22 -#define CSERV_ROAM_TIMEOUT 23 -#define CSERV_FORCE_SCAN1 24 -#define CSERV_FORCE_SCAN2 25 -#define CSERV_FORCE_SCAN3 26 -#define CSERV_UTIL_TIMEOUT 27 -#define CSERV_RSSIPOLLER 28 -#define CSERV_RETRY_CONNECT_TIMEOUT 29 -#define CSERV_RSSIINDBMPOLLER 30 -#define CSERV_BGSCAN_ENABLE 31 -#define CSERV_BGSCAN_DISABLE 32 -#define CSERV_WLAN_START_SCAN_CMD1 33 -#define CSERV_WLAN_START_SCAN_CMD2 34 -#define CSERV_WLAN_START_SCAN_CMD3 35 -#define CSERV_START_SCAN_CMD 36 -#define CSERV_START_FORCE_SCAN 37 -#define CSERV_NEXT_CHAN 38 -#define CSERV_SET_REGCODE 39 -#define CSERV_START_ADHOC 40 -#define CSERV_ADHOC_AT_HOME 41 -#define CSERV_OPT_AT_HOME 42 -#define CSERV_WLAN_CONNECT_CMD 43 -#define CSERV_WLAN_RECONNECT_CMD 44 -#define CSERV_WLAN_DISCONNECT_CMD 45 -#define CSERV_BSS_CHANGE_CHANNEL 46 -#define CSERV_BEACON_RX 47 -#define CSERV_KEEPALIVE_CHECK 48 -#define CSERV_RC_BEGIN_SCAN 49 -#define CSERV_RC_SCAN_START 50 -#define CSERV_RC_SCAN_STOP 51 -#define CSERV_RC_NEXT 52 -#define CSERV_RC_SCAN_END 53 -#define CSERV_PROBE_CALLBACK 54 -#define CSERV_ROAM1 55 -#define CSERV_ROAM2 56 -#define CSERV_ROAM3 57 -#define CSERV_CONNECT_EVENT 58 -#define CSERV_DISCONNECT_EVENT 59 -#define CSERV_BMISS_HANDLER1 60 -#define CSERV_BMISS_HANDLER2 61 -#define CSERV_BMISS_HANDLER3 62 -#define CSERV_LOWRSSI_HANDLER 63 -#define CSERV_WLAN_SET_PMKID_CMD 64 -#define CSERV_RECONNECT_REQUEST 65 -#define CSERV_KEYSPLUMBED_EVENT 66 -#define CSERV_NEW_REG 67 -#define CSERV_SET_RSSI_THOLD 68 -#define CSERV_RSSITHRESHOLDCHECK 69 -#define CSERV_RSSIINDBMTHRESHOLDCHECK 70 -#define CSERV_WLAN_SET_OPT_CMD1 71 -#define CSERV_WLAN_SET_OPT_CMD2 72 -#define CSERV_WLAN_SET_OPT_CMD3 73 -#define CSERV_WLAN_SET_OPT_CMD4 74 -#define CSERV_SCAN_CONNECT_STOP 75 -#define CSERV_BMISS_HANDLER4 76 -#define CSERV_INITIALIZE_TIMER 77 -#define CSERV_ARM_TIMER 78 -#define CSERV_DISARM_TIMER 79 -#define CSERV_UNINITIALIZE_TIMER 80 -#define CSERV_DISCONNECT_EVENT2 81 -#define CSERV_SCAN_CONNECT_START 82 -#define CSERV_BSSINFO_MEMORY_ALLOC_FAILED 83 -#define CSERV_SET_SCAN_PARAMS5 84 -#define CSERV_DBGID_DEFINITION_END - -/* TXRX debug identifier definitions */ -#define TXRX_TXBUF_DBGID_DEFINITION_START -#define TXRX_TXBUF_ALLOCATE_BUF 1 -#define TXRX_TXBUF_QUEUE_BUF_TO_MBOX 2 -#define TXRX_TXBUF_QUEUE_BUF_TO_TXQ 3 -#define TXRX_TXBUF_TXQ_DEPTH 4 -#define TXRX_TXBUF_IBSS_QUEUE_TO_SFQ 5 -#define TXRX_TXBUF_IBSS_QUEUE_TO_TXQ_FRM_SFQ 6 -#define TXRX_TXBUF_INITIALIZE_TIMER 7 -#define TXRX_TXBUF_ARM_TIMER 8 -#define TXRX_TXBUF_DISARM_TIMER 9 -#define TXRX_TXBUF_UNINITIALIZE_TIMER 10 -#define TXRX_TXBUF_DBGID_DEFINITION_END - -#define TXRX_RXBUF_DBGID_DEFINITION_START -#define TXRX_RXBUF_ALLOCATE_BUF 1 -#define TXRX_RXBUF_QUEUE_TO_HOST 2 -#define TXRX_RXBUF_QUEUE_TO_WLAN 3 -#define TXRX_RXBUF_ZERO_LEN_BUF 4 -#define TXRX_RXBUF_QUEUE_TO_HOST_LASTBUF_IN_RXCHAIN 5 -#define TXRX_RXBUF_LASTBUF_IN_RXCHAIN_ZEROBUF 6 -#define TXRX_RXBUF_QUEUE_EMPTY_QUEUE_TO_WLAN 7 -#define TXRX_RXBUF_SEND_TO_RECV_MGMT 8 -#define TXRX_RXBUF_SEND_TO_IEEE_LAYER 9 -#define TXRX_RXBUF_DBGID_DEFINITION_END - -#define TXRX_MGMTBUF_DBGID_DEFINITION_START -#define TXRX_MGMTBUF_ALLOCATE_BUF 1 -#define TXRX_MGMTBUF_ALLOCATE_SM_BUF 2 -#define TXRX_MGMTBUF_ALLOCATE_RMBUF 3 -#define TXRX_MGMTBUF_GET_BUF 4 -#define TXRX_MGMTBUF_GET_SM_BUF 5 -#define TXRX_MGMTBUF_QUEUE_BUF_TO_TXQ 6 -#define TXRX_MGMTBUF_REAPED_BUF 7 -#define TXRX_MGMTBUF_REAPED_SM_BUF 8 -#define TXRX_MGMTBUF_WAIT_FOR_TXQ_DRAIN 9 -#define TXRX_MGMTBUF_WAIT_FOR_TXQ_SFQ_DRAIN 10 -#define TXRX_MGMTBUF_ENQUEUE_INTO_SFQ 11 -#define TXRX_MGMTBUF_DEQUEUE_FROM_SFQ 12 -#define TXRX_MGMTBUF_PAUSE_TXQ 13 -#define TXRX_MGMTBUF_RESUME_TXQ 14 -#define TXRX_MGMTBUF_WAIT_FORTXQ_DRAIN_TIMEOUT 15 -#define TXRX_MGMTBUF_DRAINQ 16 -#define TXRX_MGMTBUF_INDICATE_Q_DRAINED 17 -#define TXRX_MGMTBUF_DBGID_DEFINITION_END - -/* PM (Power Module) debug identifier definitions */ -#define PM_DBGID_DEFINITION_START -#define PM_INIT 1 -#define PM_ENABLE 2 -#define PM_SET_STATE 3 -#define PM_SET_POWERMODE 4 -#define PM_CONN_NOTIFY 5 -#define PM_REF_COUNT_NEGATIVE 6 -#define PM_APSD_ENABLE 7 -#define PM_UPDATE_APSD_STATE 8 -#define PM_CHAN_OP_REQ 9 -#define PM_SET_MY_BEACON_POLICY 10 -#define PM_SET_ALL_BEACON_POLICY 11 -#define PM_SET_PM_PARAMS1 12 -#define PM_SET_PM_PARAMS2 13 -#define PM_ADHOC_SET_PM_CAPS_FAIL 14 -#define PM_ADHOC_UNKNOWN_IBSS_ATTRIB_ID 15 -#define PM_DBGID_DEFINITION_END - -/* Wake on Wireless debug identifier definitions */ -#define WOW_DBGID_DEFINITION_START -#define WOW_INIT 1 -#define WOW_GET_CONFIG_DSET 2 -#define WOW_NO_CONFIG_DSET 3 -#define WOW_INVALID_CONFIG_DSET 4 -#define WOW_USE_DEFAULT_CONFIG 5 -#define WOW_SETUP_GPIO 6 -#define WOW_INIT_DONE 7 -#define WOW_SET_GPIO_PIN 8 -#define WOW_CLEAR_GPIO_PIN 9 -#define WOW_SET_WOW_MODE_CMD 10 -#define WOW_SET_HOST_MODE_CMD 11 -#define WOW_ADD_WOW_PATTERN_CMD 12 -#define WOW_NEW_WOW_PATTERN_AT_INDEX 13 -#define WOW_DEL_WOW_PATTERN_CMD 14 -#define WOW_LIST_CONTAINS_PATTERNS 15 -#define WOW_GET_WOW_LIST_CMD 16 -#define WOW_INVALID_FILTER_ID 17 -#define WOW_INVALID_FILTER_LISTID 18 -#define WOW_NO_VALID_FILTER_AT_ID 19 -#define WOW_NO_VALID_LIST_AT_ID 20 -#define WOW_NUM_PATTERNS_EXCEEDED 21 -#define WOW_NUM_LISTS_EXCEEDED 22 -#define WOW_GET_WOW_STATS 23 -#define WOW_CLEAR_WOW_STATS 24 -#define WOW_WAKEUP_HOST 25 -#define WOW_EVENT_WAKEUP_HOST 26 -#define WOW_EVENT_DISCARD 27 -#define WOW_PATTERN_MATCH 28 -#define WOW_PATTERN_NOT_MATCH 29 -#define WOW_PATTERN_NOT_MATCH_OFFSET 30 -#define WOW_DISABLED_HOST_ASLEEP 31 -#define WOW_ENABLED_HOST_ASLEEP_NO_PATTERNS 32 -#define WOW_ENABLED_HOST_ASLEEP_NO_MATCH_FOUND 33 -#define WOW_DBGID_DEFINITION_END - -/* WHAL debug identifier definitions */ -#define WHAL_DBGID_DEFINITION_START -#define WHAL_ERROR_ANI_CONTROL 1 -#define WHAL_ERROR_CHIP_TEST1 2 -#define WHAL_ERROR_CHIP_TEST2 3 -#define WHAL_ERROR_EEPROM_CHECKSUM 4 -#define WHAL_ERROR_EEPROM_MACADDR 5 -#define WHAL_ERROR_INTERRUPT_HIU 6 -#define WHAL_ERROR_KEYCACHE_RESET 7 -#define WHAL_ERROR_KEYCACHE_SET 8 -#define WHAL_ERROR_KEYCACHE_TYPE 9 -#define WHAL_ERROR_KEYCACHE_TKIPENTRY 10 -#define WHAL_ERROR_KEYCACHE_WEPLENGTH 11 -#define WHAL_ERROR_PHY_INVALID_CHANNEL 12 -#define WHAL_ERROR_POWER_AWAKE 13 -#define WHAL_ERROR_POWER_SET 14 -#define WHAL_ERROR_RECV_STOPDMA 15 -#define WHAL_ERROR_RECV_STOPPCU 16 -#define WHAL_ERROR_RESET_CHANNF1 17 -#define WHAL_ERROR_RESET_CHANNF2 18 -#define WHAL_ERROR_RESET_PM 19 -#define WHAL_ERROR_RESET_OFFSETCAL 20 -#define WHAL_ERROR_RESET_RFGRANT 21 -#define WHAL_ERROR_RESET_RXFRAME 22 -#define WHAL_ERROR_RESET_STOPDMA 23 -#define WHAL_ERROR_RESET_RECOVER 24 -#define WHAL_ERROR_XMIT_COMPUTE 25 -#define WHAL_ERROR_XMIT_NOQUEUE 26 -#define WHAL_ERROR_XMIT_ACTIVEQUEUE 27 -#define WHAL_ERROR_XMIT_BADTYPE 28 -#define WHAL_DBGID_DEFINITION_END - -#ifdef __cplusplus -} -#endif - -#endif /* _DBGLOG_ID_H_ */ diff --git a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/include/dl_list.h b/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/include/dl_list.h deleted file mode 100644 index 4b9c58198..000000000 --- a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/include/dl_list.h +++ /dev/null @@ -1,114 +0,0 @@ -/* - * - * Double-link list definitions (adapted from Atheros SDIO stack) - * - * Copyright (c) 2007 Atheros Communications Inc. - * All rights reserved. - * - * - * 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; - * - * Software distributed under the License is distributed on an "AS - * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or - * implied. See the License for the specific language governing - * rights and limitations under the License. - * - * - * - */ -#ifndef __DL_LIST_H___ -#define __DL_LIST_H___ - -#define A_CONTAINING_STRUCT(address, struct_type, field_name)\ - ((struct_type *)((A_UINT32)(address) - (A_UINT32)(&((struct_type *)0)->field_name))) - -/* list functions */ -/* pointers for the list */ -typedef struct _DL_LIST { - struct _DL_LIST *pPrev; - struct _DL_LIST *pNext; -}DL_LIST, *PDL_LIST; -/* - * DL_LIST_INIT , initialize doubly linked list -*/ -#define DL_LIST_INIT(pList)\ - {(pList)->pPrev = pList; (pList)->pNext = pList;} - -#define DL_LIST_IS_EMPTY(pList) (((pList)->pPrev == (pList)) && ((pList)->pNext == (pList))) -#define DL_LIST_GET_ITEM_AT_HEAD(pList) (pList)->pNext -#define DL_LIST_GET_ITEM_AT_TAIL(pList) (pList)->pPrev -/* - * ITERATE_OVER_LIST pStart is the list, pTemp is a temp list member - * NOT: do not use this function if the items in the list are deleted inside the - * iteration loop -*/ -#define ITERATE_OVER_LIST(pStart, pTemp) \ - for((pTemp) =(pStart)->pNext; pTemp != (pStart); (pTemp) = (pTemp)->pNext) - - -/* safe iterate macro that allows the item to be removed from the list - * the iteration continues to the next item in the list - */ -#define ITERATE_OVER_LIST_ALLOW_REMOVE(pStart,pItem,st,offset) \ -{ \ - PDL_LIST pTemp; \ - pTemp = (pStart)->pNext; \ - while (pTemp != (pStart)) { \ - (pItem) = A_CONTAINING_STRUCT(pTemp,st,offset); \ - pTemp = pTemp->pNext; \ - -#define ITERATE_END }} - -/* - * DL_ListInsertTail - insert pAdd to the end of the list -*/ -static INLINE PDL_LIST DL_ListInsertTail(PDL_LIST pList, PDL_LIST pAdd) { - /* insert at tail */ - pAdd->pPrev = pList->pPrev; - pAdd->pNext = pList; - pList->pPrev->pNext = pAdd; - pList->pPrev = pAdd; - return pAdd; -} - -/* - * DL_ListInsertHead - insert pAdd into the head of the list -*/ -static INLINE PDL_LIST DL_ListInsertHead(PDL_LIST pList, PDL_LIST pAdd) { - /* insert at head */ - pAdd->pPrev = pList; - pAdd->pNext = pList->pNext; - pList->pNext->pPrev = pAdd; - pList->pNext = pAdd; - return pAdd; -} - -#define DL_ListAdd(pList,pItem) DL_ListInsertHead((pList),(pItem)) -/* - * DL_ListRemove - remove pDel from list -*/ -static INLINE PDL_LIST DL_ListRemove(PDL_LIST pDel) { - pDel->pNext->pPrev = pDel->pPrev; - pDel->pPrev->pNext = pDel->pNext; - /* point back to itself just to be safe, incase remove is called again */ - pDel->pNext = pDel; - pDel->pPrev = pDel; - return pDel; -} - -/* - * DL_ListRemoveItemFromHead - get a list item from the head -*/ -static INLINE PDL_LIST DL_ListRemoveItemFromHead(PDL_LIST pList) { - PDL_LIST pItem = NULL; - if (pList->pNext != pList) { - pItem = pList->pNext; - /* remove the first item from head */ - DL_ListRemove(pItem); - } - return pItem; -} - -#endif /* __DL_LIST_H___ */ diff --git a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/include/dset_api.h b/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/include/dset_api.h deleted file mode 100644 index de5cc6a66..000000000 --- a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/include/dset_api.h +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (c) 2004-2006 Atheros Communications Inc. - * All rights reserved. - * - * - * 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; - * - * Software distributed under the License is distributed on an "AS - * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or - * implied. See the License for the specific language governing - * rights and limitations under the License. - * - * - * - * $Id: //depot/sw/releases/olca2.0-GPL/host/include/dset_api.h#1 $ - * - * Host-side DataSet API. - * - */ - -#ifndef _DSET_API_H_ -#define _DSET_API_H_ - -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ - -/* - * Host-side DataSet support is optional, and is not - * currently required for correct operation. To disable - * Host-side DataSet support, set this to 0. - */ -#ifndef CONFIG_HOST_DSET_SUPPORT -#define CONFIG_HOST_DSET_SUPPORT 1 -#endif - -/* Called to send a DataSet Open Reply back to the Target. */ -A_STATUS wmi_dset_open_reply(struct wmi_t *wmip, - A_UINT32 status, - A_UINT32 access_cookie, - A_UINT32 size, - A_UINT32 version, - A_UINT32 targ_handle, - A_UINT32 targ_reply_fn, - A_UINT32 targ_reply_arg); - -/* Called to send a DataSet Data Reply back to the Target. */ -A_STATUS wmi_dset_data_reply(struct wmi_t *wmip, - A_UINT32 status, - A_UINT8 *host_buf, - A_UINT32 length, - A_UINT32 targ_buf, - A_UINT32 targ_reply_fn, - A_UINT32 targ_reply_arg); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - - -#endif /* _DSET_API_H_ */ diff --git a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/include/dset_internal.h b/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/include/dset_internal.h deleted file mode 100644 index f0be380e6..000000000 --- a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/include/dset_internal.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (c) 2007 Atheros Communications Inc. - * All rights reserved. - * - * $ATH_LICENSE_HOSTSDK0_C$ - * - */ - -#ifndef __DSET_INTERNAL_H__ -#define __DSET_INTERNAL_H__ - -/* - * Internal dset definitions, common for DataSet layer. - */ - -#define DSET_TYPE_STANDARD 0 -#define DSET_TYPE_BPATCHED 1 -#define DSET_TYPE_COMPRESSED 2 - -/* Dataset descriptor */ - -typedef struct dset_descriptor_s { - struct dset_descriptor_s *next; /* List link. NULL only at the last - descriptor */ - A_UINT16 id; /* Dset ID */ - A_UINT16 size; /* Dset size. */ - void *DataPtr; /* Pointer to raw data for standard - DataSet or pointer to original - dset_descriptor for patched - DataSet */ - A_UINT32 data_type; /* DSET_TYPE_*, above */ - - void *AuxPtr; /* Additional data that might - needed for data_type. For - example, pointer to patch - Dataset descriptor for BPatch. */ -} dset_descriptor_t; - -#endif /* __DSET_INTERNAL_H__ */ diff --git a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/include/dsetid.h b/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/include/dsetid.h deleted file mode 100644 index 85729f8b3..000000000 --- a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/include/dsetid.h +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Copyright (c) 2004-2007 Atheros Communications Inc. - * All rights reserved. - * - * $ATH_LICENSE_HOSTSDK0_C$ - * - */ - -#ifndef __DSETID_H__ -#define __DSETID_H__ - -/* Well-known DataSet IDs */ -#define DSETID_UNUSED 0x00000000 -#define DSETID_BOARD_DATA 0x00000001 /* Cal and board data */ -#define DSETID_REGDB 0x00000002 /* Regulatory Database */ -#define DSETID_POWER_CONTROL 0x00000003 /* TX Pwr Lim & Ant Gain */ -#define DSETID_USER_CONFIG 0x00000004 /* User Configuration */ - -#define DSETID_ANALOG_CONTROL_DATA_START 0x00000005 -#define DSETID_ANALOG_CONTROL_DATA_END 0x00000025 -/* - * Get DSETID for various reference clock speeds. - * For each speed there are three DataSets that correspond - * to the three columns of bank6 data (addr, 11a, 11b/g). - * This macro returns the dsetid of the first of those - * three DataSets. - */ -#define ANALOG_CONTROL_DATA_DSETID(refclk) \ - (DSETID_ANALOG_CONTROL_DATA_START + 3*refclk) - -/* - * There are TWO STARTUP_PATCH DataSets. - * DSETID_STARTUP_PATCH is historical, and was applied before BMI on - * earlier systems. On AR6002, it is applied after BMI, just like - * DSETID_STARTUP_PATCH2. - */ -#define DSETID_STARTUP_PATCH 0x00000026 -#define DSETID_GPIO_CONFIG_PATCH 0x00000027 -#define DSETID_WLANREGS 0x00000028 /* override wlan regs */ -#define DSETID_STARTUP_PATCH2 0x00000029 - -#define DSETID_WOW_CONFIG 0x00000090 /* WoW Configuration */ - -/* Add WHAL_INI_DATA_ID to DSETID_INI_DATA for a specific WHAL INI table. */ -#define DSETID_INI_DATA 0x00000100 -/* Reserved for WHAL INI Tables: 0x100..0x11f */ -#define DSETID_INI_DATA_END 0x0000011f - -#define DSETID_VENDOR_START 0x00010000 /* Vendor-defined DataSets */ - -#define DSETID_INDEX_END 0xfffffffe /* Reserved to indicate the - end of a memory-based - DataSet Index */ -#define DSETID_INDEX_FREE 0xffffffff /* An unused index entry */ - -/* - * PATCH DataSet format: - * A list of patches, terminated by a patch with - * address=PATCH_END. - * - * This allows for patches to be stored in flash. - */ -struct patch_s { - A_UINT32 *address; - A_UINT32 data; -}; - -/* - * Skip some patches. Can be used to erase a single patch in a - * patch DataSet without having to re-write the DataSet. May - * also be used to embed information for use by subsequent - * patch code. The "data" in a PATCH_SKIP tells how many - * bytes of length "patch_s" to skip. - */ -#define PATCH_SKIP ((A_UINT32 *)0x00000000) - -/* - * Execute code at the address specified by "data". - * The address of the patch structure is passed as - * the one parameter. - */ -#define PATCH_CODE_ABS ((A_UINT32 *)0x00000001) - -/* - * Same as PATCH_CODE_ABS, but treat "data" as an - * offset from the start of the patch word. - */ -#define PATCH_CODE_REL ((A_UINT32 *)0x00000002) - -/* Mark the end of this patch DataSet. */ -#define PATCH_END ((A_UINT32 *)0xffffffff) - -/* - * A DataSet which contains a Binary Patch to some other DataSet - * uses the original dsetid with the DSETID_BPATCH_FLAG bit set. - * Such a BPatch DataSet consists of BPatch metadata followed by - * the bdiff bytes. BPatch metadata consists of a single 32-bit - * word that contains the size of the BPatched final image. - * - * To create a suitable bdiff DataSet, use bdiff in host/tools/bdiff - * to create "diffs": - * bdiff -q -O -nooldmd5 -nonewmd5 -d ORIGfile NEWfile diffs - * Then add BPatch metadata to the start of "diffs". - * - * NB: There are some implementation-induced restrictions - * on which DataSets can be BPatched. - */ -#define DSETID_BPATCH_FLAG 0x80000000 - -#endif /* __DSETID_H__ */ diff --git a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/include/gpio.h b/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/include/gpio.h deleted file mode 100644 index 2203c7e01..000000000 --- a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/include/gpio.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (c) 2005 Atheros Communications Inc. - * All rights reserved. - * - * $ATH_LICENSE_HOSTSDK0_C$ - * - */ - -#if defined(AR6001) -#define GPIO_PIN_COUNT 18 -#else -#define GPIO_PIN_COUNT 18 -#endif - -/* - * Possible values for WMIX_GPIO_SET_REGISTER_CMDID. - * NB: These match hardware order, so that addresses can - * easily be computed. - */ -#define GPIO_ID_OUT 0x00000000 -#define GPIO_ID_OUT_W1TS 0x00000001 -#define GPIO_ID_OUT_W1TC 0x00000002 -#define GPIO_ID_ENABLE 0x00000003 -#define GPIO_ID_ENABLE_W1TS 0x00000004 -#define GPIO_ID_ENABLE_W1TC 0x00000005 -#define GPIO_ID_IN 0x00000006 -#define GPIO_ID_STATUS 0x00000007 -#define GPIO_ID_STATUS_W1TS 0x00000008 -#define GPIO_ID_STATUS_W1TC 0x00000009 -#define GPIO_ID_PIN0 0x0000000a -#define GPIO_ID_PIN(n) (GPIO_ID_PIN0+(n)) - -#define GPIO_LAST_REGISTER_ID GPIO_ID_PIN(17) -#define GPIO_ID_NONE 0xffffffff diff --git a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/include/gpio_api.h b/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/include/gpio_api.h deleted file mode 100644 index 8078aa57f..000000000 --- a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/include/gpio_api.h +++ /dev/null @@ -1,57 +0,0 @@ -#ifndef _GPIO_API_H_ -#define _GPIO_API_H_ -/* - * Copyright 2005 Atheros Communications, Inc., All Rights Reserved. - * - * - * 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; - * - * Software distributed under the License is distributed on an "AS - * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or - * implied. See the License for the specific language governing - * rights and limitations under the License. - * - * - * - */ - -/* - * Host-side General Purpose I/O API. - * - * $Id: //depot/sw/releases/olca2.0-GPL/host/include/gpio_api.h#1 $ - */ - -/* - * Send a command to the Target in order to change output on GPIO pins. - */ -A_STATUS wmi_gpio_output_set(struct wmi_t *wmip, - A_UINT32 set_mask, - A_UINT32 clear_mask, - A_UINT32 enable_mask, - A_UINT32 disable_mask); - -/* - * Send a command to the Target requesting input state of GPIO pins. - */ -A_STATUS wmi_gpio_input_get(struct wmi_t *wmip); - -/* - * Send a command to the Target to change the value of a GPIO register. - */ -A_STATUS wmi_gpio_register_set(struct wmi_t *wmip, - A_UINT32 gpioreg_id, - A_UINT32 value); - -/* - * Send a command to the Target to fetch the value of a GPIO register. - */ -A_STATUS wmi_gpio_register_get(struct wmi_t *wmip, A_UINT32 gpioreg_id); - -/* - * Send a command to the Target, acknowledging some GPIO interrupts. - */ -A_STATUS wmi_gpio_intr_ack(struct wmi_t *wmip, A_UINT32 ack_mask); - -#endif /* _GPIO_API_H_ */ diff --git a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/include/hif.h b/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/include/hif.h deleted file mode 100644 index 846a69f36..000000000 --- a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/include/hif.h +++ /dev/null @@ -1,296 +0,0 @@ -/* - * Copyright (c) 2004-2007 Atheros Communications Inc. - * All rights reserved. - * - * - * 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; - * - * Software distributed under the License is distributed on an "AS - * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or - * implied. See the License for the specific language governing - * rights and limitations under the License. - * - * - * - * HIF specific declarations and prototypes - */ - -#ifndef _HIF_H_ -#define _HIF_H_ - -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ - -/* Header files */ -#include "a_config.h" -#include "athdefs.h" -#include "a_types.h" -#include "a_osapi.h" - -typedef struct htc_callbacks HTC_CALLBACKS; -typedef struct hif_device HIF_DEVICE; - -/* - * direction - Direction of transfer (HIF_READ/HIF_WRITE). - */ -#define HIF_READ 0x00000001 -#define HIF_WRITE 0x00000002 -#define HIF_DIR_MASK (HIF_READ | HIF_WRITE) - -/* - * type - An interface may support different kind of read/write commands. - * The command type is divided into a basic and an extended command - * and can be specified using HIF_BASIC_IO/HIF_EXTENDED_IO. - */ -#define HIF_BASIC_IO 0x00000004 -#define HIF_EXTENDED_IO 0x00000008 -#define HIF_TYPE_MASK (HIF_BASIC_IO | HIF_EXTENDED_IO) - -/* - * emode - This indicates the whether the command is to be executed in a - * blocking or non-blocking fashion (HIF_SYNCHRONOUS/ - * HIF_ASYNCHRONOUS). The read/write data paths in HTC have been - * implemented using the asynchronous mode allowing the the bus - * driver to indicate the completion of operation through the - * registered callback routine. The requirement primarily comes - * from the contexts these operations get called from (a driver's - * transmit context or the ISR context in case of receive). - * Support for both of these modes is essential. - */ -#define HIF_SYNCHRONOUS 0x00000010 -#define HIF_ASYNCHRONOUS 0x00000020 -#define HIF_EMODE_MASK (HIF_SYNCHRONOUS | HIF_ASYNCHRONOUS) - -/* - * dmode - An interface may support different kinds of commands based on - * the tradeoff between the amount of data it can carry and the - * setup time. Byte and Block modes are supported (HIF_BYTE_BASIS/ - * HIF_BLOCK_BASIS). In case of latter, the data is rounded off - * to the nearest block size by padding. The size of the block is - * configurable at compile time using the HIF_BLOCK_SIZE and is - * negotiated with the target during initialization after the - * dragon interrupts are enabled. - */ -#define HIF_BYTE_BASIS 0x00000040 -#define HIF_BLOCK_BASIS 0x00000080 -#define HIF_DMODE_MASK (HIF_BYTE_BASIS | HIF_BLOCK_BASIS) - -/* - * amode - This indicates if the address has to be incremented on dragon - * after every read/write operation (HIF?FIXED_ADDRESS/ - * HIF_INCREMENTAL_ADDRESS). - */ -#define HIF_FIXED_ADDRESS 0x00000100 -#define HIF_INCREMENTAL_ADDRESS 0x00000200 -#define HIF_AMODE_MASK (HIF_FIXED_ADDRESS | HIF_INCREMENTAL_ADDRESS) - -#define HIF_WR_ASYNC_BYTE_FIX \ - (HIF_WRITE | HIF_ASYNCHRONOUS | HIF_EXTENDED_IO | HIF_BYTE_BASIS | HIF_FIXED_ADDRESS) -#define HIF_WR_ASYNC_BYTE_INC \ - (HIF_WRITE | HIF_ASYNCHRONOUS | HIF_EXTENDED_IO | HIF_BYTE_BASIS | HIF_INCREMENTAL_ADDRESS) -#define HIF_WR_ASYNC_BLOCK_INC \ - (HIF_WRITE | HIF_ASYNCHRONOUS | HIF_EXTENDED_IO | HIF_BLOCK_BASIS | HIF_INCREMENTAL_ADDRESS) -#define HIF_WR_SYNC_BYTE_FIX \ - (HIF_WRITE | HIF_SYNCHRONOUS | HIF_EXTENDED_IO | HIF_BYTE_BASIS | HIF_FIXED_ADDRESS) -#define HIF_WR_SYNC_BYTE_INC \ - (HIF_WRITE | HIF_SYNCHRONOUS | HIF_EXTENDED_IO | HIF_BYTE_BASIS | HIF_INCREMENTAL_ADDRESS) -#define HIF_WR_SYNC_BLOCK_INC \ - (HIF_WRITE | HIF_SYNCHRONOUS | HIF_EXTENDED_IO | HIF_BLOCK_BASIS | HIF_INCREMENTAL_ADDRESS) -#define HIF_RD_SYNC_BYTE_INC \ - (HIF_READ | HIF_SYNCHRONOUS | HIF_EXTENDED_IO | HIF_BYTE_BASIS | HIF_INCREMENTAL_ADDRESS) -#define HIF_RD_SYNC_BYTE_FIX \ - (HIF_READ | HIF_SYNCHRONOUS | HIF_EXTENDED_IO | HIF_BYTE_BASIS | HIF_FIXED_ADDRESS) -#define HIF_RD_ASYNC_BYTE_FIX \ - (HIF_READ | HIF_ASYNCHRONOUS | HIF_EXTENDED_IO | HIF_BYTE_BASIS | HIF_FIXED_ADDRESS) -#define HIF_RD_ASYNC_BLOCK_FIX \ - (HIF_READ | HIF_ASYNCHRONOUS | HIF_EXTENDED_IO | HIF_BLOCK_BASIS | HIF_FIXED_ADDRESS) -#define HIF_RD_ASYNC_BYTE_INC \ - (HIF_READ | HIF_ASYNCHRONOUS | HIF_EXTENDED_IO | HIF_BYTE_BASIS | HIF_INCREMENTAL_ADDRESS) -#define HIF_RD_ASYNC_BLOCK_INC \ - (HIF_READ | HIF_ASYNCHRONOUS | HIF_EXTENDED_IO | HIF_BLOCK_BASIS | HIF_INCREMENTAL_ADDRESS) -#define HIF_RD_SYNC_BLOCK_INC \ - (HIF_READ | HIF_SYNCHRONOUS | HIF_EXTENDED_IO | HIF_BLOCK_BASIS | HIF_INCREMENTAL_ADDRESS) - - -typedef enum { - HIF_DEVICE_POWER_STATE = 0, - HIF_DEVICE_GET_MBOX_BLOCK_SIZE, - HIF_DEVICE_GET_MBOX_ADDR, - HIF_DEVICE_GET_PENDING_EVENTS_FUNC, - HIF_DEVICE_GET_IRQ_PROC_MODE, - HIF_DEVICE_GET_RECV_EVENT_MASK_UNMASK_FUNC, -} HIF_DEVICE_CONFIG_OPCODE; - -/* - * HIF CONFIGURE definitions: - * - * HIF_DEVICE_GET_MBOX_BLOCK_SIZE - * input : none - * output : array of 4 A_UINT32s - * notes: block size is returned for each mailbox (4) - * - * HIF_DEVICE_GET_MBOX_ADDR - * input : none - * output : array of 4 A_UINT32 - * notes: address is returned for each mailbox (4) in the array - * - * HIF_DEVICE_GET_PENDING_EVENTS_FUNC - * input : none - * output: HIF_PENDING_EVENTS_FUNC function pointer - * notes: this is optional for the HIF layer, if the request is - * not handled then it indicates that the upper layer can use - * the standard device methods to get pending events (IRQs, mailbox messages etc..) - * otherwise it can call the function pointer to check pending events. - * - * HIF_DEVICE_GET_IRQ_PROC_MODE - * input : none - * output : HIF_DEVICE_IRQ_PROCESSING_MODE (interrupt processing mode) - * note: the hif layer interfaces with the underlying OS-specific bus driver. The HIF - * layer can report whether IRQ processing is requires synchronous behavior or - * can be processed using asynchronous bus requests (typically faster). - * - * HIF_DEVICE_GET_RECV_EVENT_MASK_UNMASK_FUNC - * input : - * output : HIF_MASK_UNMASK_RECV_EVENT function pointer - * notes: this is optional for the HIF layer. The HIF layer may require a special mechanism - * to mask receive message events. The upper layer can call this pointer when it needs - * to mask/unmask receive events (in case it runs out of buffers). - * - * - */ - -typedef enum { - HIF_DEVICE_IRQ_SYNC_ONLY, /* for HIF implementations that require the DSR to process all - interrupts before returning */ - HIF_DEVICE_IRQ_ASYNC_SYNC, /* for HIF implementations that allow DSR to process interrupts - using ASYNC I/O (that is HIFAckInterrupt can be called at a - later time */ -} HIF_DEVICE_IRQ_PROCESSING_MODE; - -#define HIF_MAX_DEVICES 1 - -struct htc_callbacks { - A_UCHAR *name; - A_UINT32 id; - A_STATUS (* deviceInsertedHandler)(void *hif_handle); - A_STATUS (* deviceRemovedHandler)(void *htc_handle, A_STATUS status); - A_STATUS (* deviceSuspendHandler)(void *htc_handle); - A_STATUS (* deviceResumeHandler)(void *htc_handle); - A_STATUS (* deviceWakeupHandler)(void *htc_handle); - A_STATUS (* rwCompletionHandler)(void *context, A_STATUS status); - A_STATUS (* dsrHandler)(void *htc_handle); -}; - - -#define HIF_OTHER_EVENTS (1 << 0) /* other interrupts (non-Recv) are pending, host - needs to read the register table to figure out what */ -#define HIF_RECV_MSG_AVAIL (1 << 1) /* pending recv packet */ - -typedef struct _HIF_PENDING_EVENTS_INFO { - A_UINT32 Events; - A_UINT32 LookAhead; -} HIF_PENDING_EVENTS_INFO; - - /* function to get pending events , some HIF modules use special mechanisms - * to detect packet available and other interrupts */ -typedef A_STATUS ( *HIF_PENDING_EVENTS_FUNC)(HIF_DEVICE *device, - HIF_PENDING_EVENTS_INFO *pEvents, - void *AsyncContext); - -#define HIF_MASK_RECV TRUE -#define HIF_UNMASK_RECV FALSE - /* function to mask recv events */ -typedef A_STATUS ( *HIF_MASK_UNMASK_RECV_EVENT)(HIF_DEVICE *device, - A_BOOL Mask, - void *AsyncContext); - - -/* - * This API is used by the HTC layer to initialize the HIF layer and to - * register different callback routines. Support for following events has - * been captured - DSR, Read/Write completion, Device insertion/removal, - * Device suspension/resumption/wakeup. In addition to this, the API is - * also used to register the name and the revision of the chip. The latter - * can be used to verify the revision of the chip read from the device - * before reporting it to HTC. - */ -int HIFInit(HTC_CALLBACKS *callbacks); - -/* - * This API is used to provide the read/write interface over the specific bus - * interface. - * address - Starting address in the dragon's address space. For mailbox - * writes, it refers to the start of the mbox boundary. It should - * be ensured that the last byte falls on the mailbox's EOM. For - * mailbox reads, it refers to the end of the mbox boundary. - * buffer - Pointer to the buffer containg the data to be transmitted or - * received. - * length - Amount of data to be transmitted or received. - * request - Characterizes the attributes of the command. - */ -A_STATUS -HIFReadWrite(HIF_DEVICE *device, - A_UINT32 address, - A_UCHAR *buffer, - A_UINT32 length, - A_UINT32 request, - void *context); - -/* - * This can be initiated from the unload driver context ie when the HTCShutdown - * routine is called. - */ -void HIFShutDownDevice(HIF_DEVICE *device); - -/* - * This should translate to an acknowledgment to the bus driver indicating that - * the previous interrupt request has been serviced and the all the relevant - * sources have been cleared. HTC is ready to process more interrupts. - * This should prevent the bus driver from raising an interrupt unless the - * previous one has been serviced and acknowledged using the previous API. - */ -void HIFAckInterrupt(HIF_DEVICE *device); - -void HIFMaskInterrupt(HIF_DEVICE *device); - -void HIFUnMaskInterrupt(HIF_DEVICE *device); - -/* - * This set of functions are to be used by the bus driver to notify - * the HIF module about various events. - * These are not implemented if the bus driver provides an alternative - * way for this notification though callbacks for instance. - */ -int HIFInsertEventNotify(void); - -int HIFRemoveEventNotify(void); - -int HIFIRQEventNotify(void); - -int HIFRWCompleteEventNotify(void); - -/* - * This function associates a opaque handle with the HIF layer - * to be used in communication with upper layer i.e. HTC. - * This would normaly be a pointer to htc_target data structure. - */ -void HIFSetHandle(void *hif_handle, void *handle); - -A_STATUS -HIFConfigureDevice(HIF_DEVICE *device, HIF_DEVICE_CONFIG_OPCODE opcode, - void *config, A_UINT32 configLen); - - -struct device; -struct device* -HIFGetOSDevice(HIF_DEVICE *device); - - -#ifdef __cplusplus -} -#endif - -#endif /* _HIF_H_ */ diff --git a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/include/host_version.h b/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/include/host_version.h deleted file mode 100644 index c090115bc..000000000 --- a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/include/host_version.h +++ /dev/null @@ -1,49 +0,0 @@ -#ifndef _HOST_VERSION_H_ -#define _HOST_VERSION_H_ -/* - * Copyright (c) 2004-2005 Atheros Communications Inc. - * All rights reserved. - * - * This file contains version information for the sample host driver for the - * AR6000 chip - * - * $Id: //depot/sw/releases/olca2.0-GPL/host/include/host_version.h#2 $ - * - * - * 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; - * - * Software distributed under the License is distributed on an "AS - * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or - * implied. See the License for the specific language governing - * rights and limitations under the License. - * - * - * - */ - -#ifdef __cplusplus -extern "C" { -#endif - -#include - -/* - * The version number is made up of major, minor, patch and build - * numbers. These are 16 bit numbers. The build and release script will - * set the build number using a Perforce counter. Here the build number is - * set to 9999 so that builds done without the build-release script are easily - * identifiable. - */ - -#define ATH_SW_VER_MAJOR __VER_MAJOR_ -#define ATH_SW_VER_MINOR __VER_MINOR_ -#define ATH_SW_VER_PATCH __VER_PATCH_ -#define ATH_SW_VER_BUILD 9999 - -#ifdef __cplusplus -} -#endif - -#endif /* _HOST_VERSION_H_ */ diff --git a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/include/htc.h b/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/include/htc.h deleted file mode 100644 index 152d867b7..000000000 --- a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/include/htc.h +++ /dev/null @@ -1,190 +0,0 @@ -/* - * Copyright (c) 2007 Atheros Communications Inc. - * All rights reserved. - * - * $ATH_LICENSE_HOSTSDK0_C$ - * - */ - - -#ifndef __HTC_H__ -#define __HTC_H__ - -#ifndef ATH_TARGET -#include "athstartpack.h" -#endif - -#define A_OFFSETOF(type,field) (int)(&(((type *)NULL)->field)) - -#define ASSEMBLE_UNALIGNED_UINT16(p,highbyte,lowbyte) \ - (((A_UINT16)(((A_UINT8 *)(p))[(highbyte)])) << 8 | (A_UINT16)(((A_UINT8 *)(p))[(lowbyte)])) - -/* alignment independent macros (little-endian) to fetch UINT16s or UINT8s from a - * structure using only the type and field name. - * Use these macros if there is the potential for unaligned buffer accesses. */ -#define A_GET_UINT16_FIELD(p,type,field) \ - ASSEMBLE_UNALIGNED_UINT16(p,\ - A_OFFSETOF(type,field) + 1, \ - A_OFFSETOF(type,field)) - -#define A_SET_UINT16_FIELD(p,type,field,value) \ -{ \ - ((A_UINT8 *)(p))[A_OFFSETOF(type,field)] = (A_UINT8)(value); \ - ((A_UINT8 *)(p))[A_OFFSETOF(type,field) + 1] = (A_UINT8)((value) >> 8); \ -} - -#define A_GET_UINT8_FIELD(p,type,field) \ - ((A_UINT8 *)(p))[A_OFFSETOF(type,field)] - -#define A_SET_UINT8_FIELD(p,type,field,value) \ - ((A_UINT8 *)(p))[A_OFFSETOF(type,field)] = (value) - -/****** DANGER DANGER *************** - * - * The frame header length and message formats defined herein were - * selected to accommodate optimal alignment for target processing. This reduces code - * size and improves performance. - * - * Any changes to the header length may alter the alignment and cause exceptions - * on the target. When adding to the message structures insure that fields are - * properly aligned. - * - */ - -/* HTC frame header */ -typedef PREPACK struct _HTC_FRAME_HDR{ - /* do not remove or re-arrange these fields, these are minimally required - * to take advantage of 4-byte lookaheads in some hardware implementations */ - A_UINT8 EndpointID; - A_UINT8 Flags; - A_UINT16 PayloadLen; /* length of data (including trailer) that follows the header */ - - /***** end of 4-byte lookahead ****/ - - A_UINT8 ControlBytes[2]; - - /* message payload starts after the header */ - -} POSTPACK HTC_FRAME_HDR; - -/* frame header flags */ -#define HTC_FLAGS_NEED_CREDIT_UPDATE (1 << 0) -#define HTC_FLAGS_RECV_TRAILER (1 << 1) - - -#define HTC_HDR_LENGTH (sizeof(HTC_FRAME_HDR)) -#define HTC_MAX_TRAILER_LENGTH 255 -#define HTC_MAX_PAYLOAD_LENGTH (2048 - sizeof(HTC_FRAME_HDR)) - -/* HTC control message IDs */ -typedef enum { - HTC_MSG_READY_ID = 1, - HTC_MSG_CONNECT_SERVICE_ID = 2, - HTC_MSG_CONNECT_SERVICE_RESPONSE_ID = 3, - HTC_MSG_SETUP_COMPLETE_ID = 4, -} HTC_MSG_IDS; - -#define HTC_MAX_CONTROL_MESSAGE_LENGTH 256 - -/* base message ID header */ -typedef PREPACK struct { - A_UINT16 MessageID; -} POSTPACK HTC_UNKNOWN_MSG; - -/* HTC ready message - * direction : target-to-host */ -typedef PREPACK struct { - A_UINT16 MessageID; /* ID */ - A_UINT16 CreditCount; /* number of credits the target can offer */ - A_UINT16 CreditSize; /* size of each credit */ - A_UINT8 MaxEndpoints; /* maximum number of endpoints the target has resources for */ - A_UINT8 _Pad1; -} POSTPACK HTC_READY_MSG; - -#define HTC_SERVICE_META_DATA_MAX_LENGTH 128 - -/* connect service - * direction : host-to-target */ -typedef PREPACK struct { - A_UINT16 MessageID; - A_UINT16 ServiceID; /* service ID of the service to connect to */ - A_UINT16 ConnectionFlags; /* connection flags */ - -#define HTC_CONNECT_FLAGS_REDUCE_CREDIT_DRIBBLE (1 << 2) /* reduce credit dribbling when - the host needs credits */ -#define HTC_CONNECT_FLAGS_THRESHOLD_LEVEL_MASK (0x3) -#define HTC_CONNECT_FLAGS_THRESHOLD_LEVEL_ONE_FOURTH 0x0 -#define HTC_CONNECT_FLAGS_THRESHOLD_LEVEL_ONE_HALF 0x1 -#define HTC_CONNECT_FLAGS_THRESHOLD_LEVEL_THREE_FOURTHS 0x2 -#define HTC_CONNECT_FLAGS_THRESHOLD_LEVEL_UNITY 0x3 - - A_UINT8 ServiceMetaLength; /* length of meta data that follows */ - A_UINT8 _Pad1; - - /* service-specific meta data starts after the header */ - -} POSTPACK HTC_CONNECT_SERVICE_MSG; - -/* connect response - * direction : target-to-host */ -typedef PREPACK struct { - A_UINT16 MessageID; - A_UINT16 ServiceID; /* service ID that the connection request was made */ - A_UINT8 Status; /* service connection status */ - A_UINT8 EndpointID; /* assigned endpoint ID */ - A_UINT16 MaxMsgSize; /* maximum expected message size on this endpoint */ - A_UINT8 ServiceMetaLength; /* length of meta data that follows */ - A_UINT8 _Pad1; - - /* service-specific meta data starts after the header */ - -} POSTPACK HTC_CONNECT_SERVICE_RESPONSE_MSG; - -typedef PREPACK struct { - A_UINT16 MessageID; - /* currently, no other fields */ -} POSTPACK HTC_SETUP_COMPLETE_MSG; - - -/* connect response status codes */ -#define HTC_SERVICE_SUCCESS 0 /* success */ -#define HTC_SERVICE_NOT_FOUND 1 /* service could not be found */ -#define HTC_SERVICE_FAILED 2 /* specific service failed the connect */ -#define HTC_SERVICE_NO_RESOURCES 3 /* no resources (i.e. no more endpoints) */ -#define HTC_SERVICE_NO_MORE_EP 4 /* specific service is not allowing any more - endpoints */ - -/* report record IDs */ -typedef enum { - HTC_RECORD_NULL = 0, - HTC_RECORD_CREDITS = 1, - HTC_RECORD_LOOKAHEAD = 2, -} HTC_RPT_IDS; - -typedef PREPACK struct { - A_UINT8 RecordID; /* Record ID */ - A_UINT8 Length; /* Length of record */ -} POSTPACK HTC_RECORD_HDR; - -typedef PREPACK struct { - A_UINT8 EndpointID; /* Endpoint that owns these credits */ - A_UINT8 Credits; /* credits to report since last report */ -} POSTPACK HTC_CREDIT_REPORT; - -typedef PREPACK struct { - A_UINT8 PreValid; /* pre valid guard */ - A_UINT8 LookAhead[4]; /* 4 byte lookahead */ - A_UINT8 PostValid; /* post valid guard */ - - /* NOTE: the LookAhead array is guarded by a PreValid and Post Valid guard bytes. - * The PreValid bytes must equal the inverse of the PostValid byte */ - -} POSTPACK HTC_LOOKAHEAD_REPORT; - -#ifndef ATH_TARGET -#include "athendpack.h" -#endif - - -#endif /* __HTC_H__ */ - diff --git a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/include/htc_api.h b/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/include/htc_api.h deleted file mode 100644 index e75692d7e..000000000 --- a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/include/htc_api.h +++ /dev/null @@ -1,439 +0,0 @@ -/* - * - * Copyright (c) 2007 Atheros Communications Inc. - * All rights reserved. - * - * - * 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; - * - * Software distributed under the License is distributed on an "AS - * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or - * implied. See the License for the specific language governing - * rights and limitations under the License. - * - * - * - */ - -#ifndef _HTC_API_H_ -#define _HTC_API_H_ - -#include -#include -#include "htc_packet.h" - -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ - -/* TODO.. for BMI */ -#define ENDPOINT1 0 -// TODO -remove me, but we have to fix BMI first -#define HTC_MAILBOX_NUM_MAX 4 - - -/* ------ Endpoint IDS ------ */ -typedef enum -{ - ENDPOINT_UNUSED = -1, - ENDPOINT_0 = 0, - ENDPOINT_1 = 1, - ENDPOINT_2 = 2, - ENDPOINT_3, - ENDPOINT_4, - ENDPOINT_5, - ENDPOINT_6, - ENDPOINT_7, - ENDPOINT_8, - ENDPOINT_MAX, -} HTC_ENDPOINT_ID; - -/* this is the amount of header room required by users of HTC */ -#define HTC_HEADER_LEN HTC_HDR_LENGTH - -typedef void *HTC_HANDLE; - -typedef A_UINT16 HTC_SERVICE_ID; - -typedef struct _HTC_INIT_INFO { - void (*AddInstance)(HTC_HANDLE); - void (*DeleteInstance)(void *Instance); - void (*TargetFailure)(void *Instance, A_STATUS Status); -} HTC_INIT_INFO; - -/* per service connection send completion */ -typedef void (*HTC_EP_SEND_PKT_COMPLETE)(void *,HTC_PACKET *); -/* per service connection pkt received */ -typedef void (*HTC_EP_RECV_PKT)(void *,HTC_PACKET *); - -/* Optional per service connection receive buffer re-fill callback, - * On some OSes (like Linux) packets are allocated from a global pool and indicated up - * to the network stack. The driver never gets the packets back from the OS. For these OSes - * a refill callback can be used to allocate and re-queue buffers into HTC. - * - * On other OSes, the network stack can call into the driver's OS-specifc "return_packet" handler and - * the driver can re-queue these buffers into HTC. In this regard a refill callback is - * unnecessary */ -typedef void (*HTC_EP_RECV_REFILL)(void *, HTC_ENDPOINT_ID Endpoint); - -/* Optional per service connection callback when a send queue is full. This can occur if the - * host continues queueing up TX packets faster than credits can arrive - * To prevent the host (on some Oses like Linux) from continuously queueing packets - * and consuming resources, this callback is provided so that that the host - * can disable TX in the subsystem (i.e. network stack) - * Other OSes require a "per-packet" indication_RAW_STREAM_NUM_MAX for each completed TX packet, this - * closed loop mechanism will prevent the network stack from overunning the NIC */ -typedef void (*HTC_EP_SEND_QUEUE_FULL)(void *, HTC_ENDPOINT_ID Endpoint); -/* Optional per service connection callback when a send queue is available for receive new packet. */ -typedef void (*HTC_EP_SEND_QUEUE_AVAIL)(void *, HTC_ENDPOINT_ID Endpoint); - -typedef struct _HTC_EP_CALLBACKS { - void *pContext; /* context for each callback */ - HTC_EP_SEND_PKT_COMPLETE EpTxComplete; /* tx completion callback for connected endpoint */ - HTC_EP_RECV_PKT EpRecv; /* receive callback for connected endpoint */ - HTC_EP_RECV_REFILL EpRecvRefill; /* OPTIONAL receive re-fill callback for connected endpoint */ - HTC_EP_SEND_QUEUE_FULL EpSendFull; /* OPTIONAL send full callback */ - HTC_EP_SEND_QUEUE_AVAIL EpSendAvail; /* OPTIONAL send available callback */ -} HTC_EP_CALLBACKS; - -/* service connection information */ -typedef struct _HTC_SERVICE_CONNECT_REQ { - HTC_SERVICE_ID ServiceID; /* service ID to connect to */ - A_UINT16 ConnectionFlags; /* connection flags, see htc protocol definition */ - A_UINT8 *pMetaData; /* ptr to optional service-specific meta-data */ - A_UINT8 MetaDataLength; /* optional meta data length */ - HTC_EP_CALLBACKS EpCallbacks; /* endpoint callbacks */ - int MaxSendQueueDepth; /* maximum depth of any send queue */ -} HTC_SERVICE_CONNECT_REQ; - -/* service connection response information */ -typedef struct _HTC_SERVICE_CONNECT_RESP { - A_UINT8 *pMetaData; /* caller supplied buffer to optional meta-data */ - A_UINT8 BufferLength; /* length of caller supplied buffer */ - A_UINT8 ActualLength; /* actual length of meta data */ - HTC_ENDPOINT_ID Endpoint; /* endpoint to communicate over */ - int MaxMsgLength; /* max length of all messages over this endpoint */ - A_UINT8 ConnectRespCode; /* connect response code from target */ -} HTC_SERVICE_CONNECT_RESP; - -/* endpoint distribution structure */ -typedef struct _HTC_ENDPOINT_CREDIT_DIST { - struct _HTC_ENDPOINT_CREDIT_DIST *pNext; - struct _HTC_ENDPOINT_CREDIT_DIST *pPrev; - HTC_SERVICE_ID ServiceID; /* Service ID (set by HTC) */ - HTC_ENDPOINT_ID Endpoint; /* endpoint for this distribution struct (set by HTC) */ - A_UINT32 DistFlags; /* distribution flags, distribution function can - set default activity using SET_EP_ACTIVE() macro */ - int TxCreditsNorm; /* credits for normal operation, anything above this - indicates the endpoint is over-subscribed, this field - is only relevant to the credit distribution function */ - int TxCreditsMin; /* floor for credit distribution, this field is - only relevant to the credit distribution function */ - int TxCreditsAssigned; /* number of credits assigned to this EP, this field - is only relevant to the credit dist function */ - int TxCredits; /* current credits available, this field is used by - HTC to determine whether a message can be sent or - must be queued */ - int TxCreditsToDist; /* pending credits to distribute on this endpoint, this - is set by HTC when credit reports arrive. - The credit distribution functions sets this to zero - when it distributes the credits */ - int TxCreditsSeek; /* this is the number of credits that the current pending TX - packet needs to transmit. This is set by HTC when - and endpoint needs credits in order to transmit */ - int TxCreditSize; /* size in bytes of each credit (set by HTC) */ - int TxCreditsPerMaxMsg; /* credits required for a maximum sized messages (set by HTC) */ - void *pHTCReserved; /* reserved for HTC use */ -} HTC_ENDPOINT_CREDIT_DIST; - -#define HTC_EP_ACTIVE (1 << 31) - -/* macro to check if an endpoint has gone active, useful for credit - * distributions */ -#define IS_EP_ACTIVE(epDist) ((epDist)->DistFlags & HTC_EP_ACTIVE) -#define SET_EP_ACTIVE(epDist) (epDist)->DistFlags |= HTC_EP_ACTIVE - - /* credit distibution code that is passed into the distrbution function, - * there are mandatory and optional codes that must be handled */ -typedef enum _HTC_CREDIT_DIST_REASON { - HTC_CREDIT_DIST_SEND_COMPLETE = 0, /* credits available as a result of completed - send operations (MANDATORY) resulting in credit reports */ - HTC_CREDIT_DIST_ACTIVITY_CHANGE = 1, /* a change in endpoint activity occured (OPTIONAL) */ - HTC_CREDIT_DIST_SEEK_CREDITS, /* an endpoint needs to "seek" credits (OPTIONAL) */ - HTC_DUMP_CREDIT_STATE /* for debugging, dump any state information that is kept by - the distribution function */ -} HTC_CREDIT_DIST_REASON; - -typedef void (*HTC_CREDIT_DIST_CALLBACK)(void *Context, - HTC_ENDPOINT_CREDIT_DIST *pEPList, - HTC_CREDIT_DIST_REASON Reason); - -typedef void (*HTC_CREDIT_INIT_CALLBACK)(void *Context, - HTC_ENDPOINT_CREDIT_DIST *pEPList, - int TotalCredits); - - /* endpoint statistics action */ -typedef enum _HTC_ENDPOINT_STAT_ACTION { - HTC_EP_STAT_SAMPLE = 0, /* only read statistics */ - HTC_EP_STAT_SAMPLE_AND_CLEAR = 1, /* sample and immediately clear statistics */ - HTC_EP_STAT_CLEAR /* clear only */ -} HTC_ENDPOINT_STAT_ACTION; - - /* endpoint statistics */ -typedef struct _HTC_ENDPOINT_STATS { - A_UINT32 TxCreditLowIndications; /* number of times the host set the credit-low flag in a send message on - this endpoint */ - A_UINT32 TxIssued; /* running count of TX packets issued */ - A_UINT32 TxCreditRpts; /* running count of total credit reports received for this endpoint */ - A_UINT32 TxCreditRptsFromRx; - A_UINT32 TxCreditRptsFromOther; - A_UINT32 TxCreditRptsFromEp0; - A_UINT32 TxCreditsFromRx; /* count of credits received via Rx packets on this endpoint */ - A_UINT32 TxCreditsFromOther; /* count of credits received via another endpoint */ - A_UINT32 TxCreditsFromEp0; /* count of credits received via another endpoint */ - A_UINT32 TxCreditsConsummed; /* count of consummed credits */ - A_UINT32 TxCreditsReturned; /* count of credits returned */ - A_UINT32 RxReceived; /* count of RX packets received */ - A_UINT32 RxLookAheads; /* count of lookahead records - found in messages received on this endpoint */ -} HTC_ENDPOINT_STATS; - -/* ------ Function Prototypes ------ */ -/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - @desc: Initialize HTC - @function name: HTCInit - @input: pInfo - initialization information - @output: - @return: A_OK on success - @notes: The caller initializes global HTC state and registers various instance - notification callbacks (see HTC_INIT_INFO). - - @example: - @see also: HTCShutdown -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -A_STATUS HTCInit(HTC_INIT_INFO *pInfo); -/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - @desc: Get the underlying HIF device handle - @function name: HTCGetHifDevice - @input: HTCHandle - handle passed into the AddInstance callback - @output: - @return: opaque HIF device handle usable in HIF API calls. - @notes: - @example: - @see also: -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -void *HTCGetHifDevice(HTC_HANDLE HTCHandle); -/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - @desc: Set the associated instance for the HTC handle - @function name: HTCSetInstance - @input: HTCHandle - handle passed into the AddInstance callback - Instance - caller supplied instance object - @output: - @return: - @notes: Caller must set the instance information for the HTC handle in order to receive - notifications for instance deletion (DeleteInstance callback is called) and for target - failure notification. - @example: - @see also: -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -void HTCSetInstance(HTC_HANDLE HTCHandle, void *Instance); -/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - @desc: Set credit distribution parameters - @function name: HTCSetCreditDistribution - @input: HTCHandle - HTC handle - pCreditDistCont - caller supplied context to pass into distribution functions - CreditDistFunc - Distribution function callback - CreditDistInit - Credit Distribution initialization callback - ServicePriorityOrder - Array containing list of service IDs, lowest index is highest - priority - ListLength - number of elements in ServicePriorityOrder - @output: - @return: - @notes: The user can set a custom credit distribution function to handle special requirements - for each endpoint. A default credit distribution routine can be used by setting - CreditInitFunc to NULL. The default credit distribution is only provided for simple - "fair" credit distribution without regard to any prioritization. - - @example: - @see also: -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -void HTCSetCreditDistribution(HTC_HANDLE HTCHandle, - void *pCreditDistContext, - HTC_CREDIT_DIST_CALLBACK CreditDistFunc, - HTC_CREDIT_INIT_CALLBACK CreditInitFunc, - HTC_SERVICE_ID ServicePriorityOrder[], - int ListLength); -/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - @desc: Wait for the target to indicate the HTC layer is ready - @function name: HTCWaitTarget - @input: HTCHandle - HTC handle - @output: - @return: - @notes: This API blocks until the target responds with an HTC ready message. - The caller should not connect services until the target has indicated it is - ready. - @example: - @see also: HTCConnectService -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -A_STATUS HTCWaitTarget(HTC_HANDLE HTCHandle); -/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - @desc: Start target service communications - @function name: HTCStart - @input: HTCHandle - HTC handle - @output: - @return: - @notes: This API indicates to the target that the service connection phase is complete - and the target can freely start all connected services. This API should only be - called AFTER all service connections have been made. TCStart will issue a - SETUP_COMPLETE message to the target to indicate that all service connections - have been made and the target can start communicating over the endpoints. - @example: - @see also: HTCConnectService -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -A_STATUS HTCStart(HTC_HANDLE HTCHandle); -/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - @desc: Add receive packet to HTC - @function name: HTCAddReceivePkt - @input: HTCHandle - HTC handle - pPacket - HTC receive packet to add - @output: - @return: A_OK on success - @notes: user must supply HTC packets for capturing incomming HTC frames. The caller - must initialize each HTC packet using the SET_HTC_PACKET_INFO_RX_REFILL() - macro. - @example: - @see also: -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -A_STATUS HTCAddReceivePkt(HTC_HANDLE HTCHandle, HTC_PACKET *pPacket); -/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - @desc: Connect to an HTC service - @function name: HTCConnectService - @input: HTCHandle - HTC handle - pReq - connection details - @output: pResp - connection response - @return: - @notes: Service connections must be performed before HTCStart. User provides callback handlers - for various endpoint events. - @example: - @see also: HTCStart -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -A_STATUS HTCConnectService(HTC_HANDLE HTCHandle, - HTC_SERVICE_CONNECT_REQ *pReq, - HTC_SERVICE_CONNECT_RESP *pResp); -/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - @desc: Send an HTC packet - @function name: HTCSendPkt - @input: HTCHandle - HTC handle - pPacket - packet to send - @output: - @return: A_OK - @notes: Caller must initialize packet using SET_HTC_PACKET_INFO_TX() macro. - This interface is fully asynchronous. On error, HTC SendPkt will - call the registered Endpoint callback to cleanup the packet. - @example: - @see also: HTCFlushEndpoint -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -A_STATUS HTCSendPkt(HTC_HANDLE HTCHandle, HTC_PACKET *pPacket); -/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - @desc: Stop HTC service communications - @function name: HTCStop - @input: HTCHandle - HTC handle - @output: - @return: - @notes: HTC communications is halted. All receive and pending TX packets will - be flushed. - @example: - @see also: -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -void HTCStop(HTC_HANDLE HTCHandle); -/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - @desc: Shutdown HTC - @function name: HTCShutdown - @input: - @output: - @return: - @notes: This cleans up all resources allocated by HTCInit(). - @example: - @see also: HTCInit -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -void HTCShutDown(void); -/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - @desc: Flush pending TX packets - @function name: HTCFlushEndpoint - @input: HTCHandle - HTC handle - Endpoint - Endpoint to flush - Tag - flush tag - @output: - @return: - @notes: The Tag parameter is used to selectively flush packets with matching tags. - The value of 0 forces all packets to be flush regardless of tag. - @example: - @see also: HTCSendPkt -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -void HTCFlushEndpoint(HTC_HANDLE HTCHandle, HTC_ENDPOINT_ID Endpoint, HTC_TX_TAG Tag); -/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - @desc: Dump credit distribution state - @function name: HTCDumpCreditStates - @input: HTCHandle - HTC handle - @output: - @return: - @notes: This dumps all credit distribution information to the debugger - @example: - @see also: -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -void HTCDumpCreditStates(HTC_HANDLE HTCHandle); -/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - @desc: Indicate a traffic activity change on an endpoint - @function name: HTCIndicateActivityChange - @input: HTCHandle - HTC handle - Endpoint - endpoint in which activity has changed - Active - TRUE if active, FALSE if it has become inactive - @output: - @return: - @notes: This triggers the registered credit distribution function to - re-adjust credits for active/inactive endpoints. - @example: - @see also: -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -void HTCIndicateActivityChange(HTC_HANDLE HTCHandle, - HTC_ENDPOINT_ID Endpoint, - A_BOOL Active); - -/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - @desc: Get endpoint statistics - @function name: HTCGetEndpointStatistics - @input: HTCHandle - HTC handle - Endpoint - Endpoint identifier - Action - action to take with statistics - @output: - pStats - statistics that were sampled (can be NULL if Action is HTC_EP_STAT_CLEAR) - - @return: TRUE if statistics profiling is enabled, otherwise FALSE. - - @notes: Statistics is a compile-time option and this function may return FALSE - if HTC is not compiled with profiling. - - The caller can specify the statistic "action" to take when sampling - the statistics. This includes: - - HTC_EP_STAT_SAMPLE: The pStats structure is filled with the current values. - HTC_EP_STAT_SAMPLE_AND_CLEAR: The structure is filled and the current statistics - are cleared. - HTC_EP_STAT_CLEA : the statistics are cleared, the called can pass a NULL value for - pStats - - @example: - @see also: -+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ -A_BOOL HTCGetEndpointStatistics(HTC_HANDLE HTCHandle, - HTC_ENDPOINT_ID Endpoint, - HTC_ENDPOINT_STAT_ACTION Action, - HTC_ENDPOINT_STATS *pStats); - -#ifdef __cplusplus -} -#endif - -#endif /* _HTC_API_H_ */ diff --git a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/include/htc_packet.h b/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/include/htc_packet.h deleted file mode 100644 index 9ce871817..000000000 --- a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/include/htc_packet.h +++ /dev/null @@ -1,138 +0,0 @@ -/* - * - * Copyright (c) 2007 Atheros Communications Inc. - * All rights reserved. - * - * - * 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; - * - * Software distributed under the License is distributed on an "AS - * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or - * implied. See the License for the specific language governing - * rights and limitations under the License. - * - * - * - */ - -#ifndef HTC_PACKET_H_ -#define HTC_PACKET_H_ - - -#include "dl_list.h" - -struct _HTC_PACKET; - -typedef void (* HTC_PACKET_COMPLETION)(void *,struct _HTC_PACKET *); - -typedef A_UINT16 HTC_TX_TAG; - -typedef struct _HTC_TX_PACKET_INFO { - HTC_TX_TAG Tag; /* tag used to selective flush packets */ -} HTC_TX_PACKET_INFO; - -#define HTC_TX_PACKET_TAG_ALL 0 /* a tag of zero is reserved and used to flush ALL packets */ -#define HTC_TX_PACKET_TAG_INTERNAL 1 /* internal tags start here */ -#define HTC_TX_PACKET_TAG_USER_DEFINED (HTC_TX_PACKET_TAG_INTERNAL + 9) /* user-defined tags start here */ - -typedef struct _HTC_RX_PACKET_INFO { - A_UINT32 Unused; /* for future use and to make compilers happy */ -} HTC_RX_PACKET_INFO; - -/* wrapper around endpoint-specific packets */ -typedef struct _HTC_PACKET { - DL_LIST ListLink; /* double link */ - void *pPktContext; /* caller's per packet specific context */ - - A_UINT8 *pBufferStart; /* the true buffer start , the caller can - store the real buffer start here. In - receive callbacks, the HTC layer sets pBuffer - to the start of the payload past the header. This - field allows the caller to reset pBuffer when it - recycles receive packets back to HTC */ - /* - * Pointer to the start of the buffer. In the transmit - * direction this points to the start of the payload. In the - * receive direction, however, the buffer when queued up - * points to the start of the HTC header but when returned - * to the caller points to the start of the payload - */ - A_UINT8 *pBuffer; /* payload start (RX/TX) */ - A_UINT32 BufferLength; /* length of buffer */ - A_UINT32 ActualLength; /* actual length of payload */ - int Endpoint; /* endpoint that this packet was sent/recv'd from */ - A_STATUS Status; /* completion status */ - union { - HTC_TX_PACKET_INFO AsTx; /* Tx Packet specific info */ - HTC_RX_PACKET_INFO AsRx; /* Rx Packet specific info */ - } PktInfo; - - /* the following fields are for internal HTC use */ - HTC_PACKET_COMPLETION Completion; /* completion */ - void *pContext; /* HTC private completion context */ - A_UINT32 HTCReserved; /* reserved */ -} HTC_PACKET; - - - -#define COMPLETE_HTC_PACKET(p,status) \ -{ \ - (p)->Status = (status); \ - (p)->Completion((p)->pContext,(p)); \ -} - -#define INIT_HTC_PACKET_INFO(p,b,len) \ -{ \ - (p)->pBufferStart = (b); \ - (p)->BufferLength = (len); \ -} - -/* macro to set an initial RX packet for refilling HTC */ -#define SET_HTC_PACKET_INFO_RX_REFILL(p,c,b,len,ep) \ -{ \ - (p)->pPktContext = (c); \ - (p)->pBuffer = (b); \ - (p)->pBufferStart = (b); \ - (p)->BufferLength = (len); \ - (p)->Endpoint = (ep); \ -} - -/* fast macro to recycle an RX packet that will be re-queued to HTC */ -#define HTC_PACKET_RESET_RX(p) \ - (p)->pBuffer = (p)->pBufferStart - -/* macro to set packet parameters for TX */ -#define SET_HTC_PACKET_INFO_TX(p,c,b,len,ep,tag) \ -{ \ - (p)->pPktContext = (c); \ - (p)->pBuffer = (b); \ - (p)->ActualLength = (len); \ - (p)->Endpoint = (ep); \ - (p)->PktInfo.AsTx.Tag = (tag); \ -} - -/* HTC Packet Queueing Macros */ -typedef DL_LIST HTC_PACKET_QUEUE; -/* initialize queue */ -#define INIT_HTC_PACKET_QUEUE(pQ) DL_LIST_INIT((pQ)) -/* enqueue HTC packet to the tail of the queue */ -#define HTC_PACKET_ENQUEUE(pQ,p) DL_ListInsertTail((pQ),&(p)->ListLink) -/* test if a queue is empty */ -#define HTC_QUEUE_EMPTY(pQ) DL_LIST_IS_EMPTY((pQ)) -/* get packet at head without removing it */ -#define HTC_GET_PKT_AT_HEAD(pQ) A_CONTAINING_STRUCT((DL_LIST_GET_ITEM_AT_HEAD(pQ)),HTC_PACKET,ListLink); -/* remove a packet from the current list it is linked to */ -#define HTC_PACKET_REMOVE(p) DL_ListRemove(&(p)->ListLink) - -/* dequeue an HTC packet from the head of the queue */ -static INLINE HTC_PACKET *HTC_PACKET_DEQUEUE(HTC_PACKET_QUEUE *queue) { - DL_LIST *pItem = DL_ListRemoveItemFromHead(queue); - if (pItem != NULL) { - return A_CONTAINING_STRUCT(pItem, HTC_PACKET, ListLink); - } - return NULL; -} - -#endif /*HTC_PACKET_H_*/ diff --git a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/include/htc_services.h b/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/include/htc_services.h deleted file mode 100644 index fc6fc2966..000000000 --- a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/include/htc_services.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (c) 2007 Atheros Communications Inc. - * All rights reserved. - * - * $ATH_LICENSE_HOSTSDK0_C$ - * - */ - -#ifndef __HTC_SERVICES_H__ -#define __HTC_SERVICES_H__ - -/* Current service IDs */ - -typedef enum { - RSVD_SERVICE_GROUP = 0, - WMI_SERVICE_GROUP = 1, - - HTC_TEST_GROUP = 254, - HTC_SERVICE_GROUP_LAST = 255 -}HTC_SERVICE_GROUP_IDS; - -#define MAKE_SERVICE_ID(group,index) \ - (int)(((int)group << 8) | (int)(index)) - -/* NOTE: service ID of 0x0000 is reserved and should never be used */ -#define HTC_CTRL_RSVD_SVC MAKE_SERVICE_ID(RSVD_SERVICE_GROUP,1) -#define WMI_CONTROL_SVC MAKE_SERVICE_ID(WMI_SERVICE_GROUP,0) -#define WMI_DATA_BE_SVC MAKE_SERVICE_ID(WMI_SERVICE_GROUP,1) -#define WMI_DATA_BK_SVC MAKE_SERVICE_ID(WMI_SERVICE_GROUP,2) -#define WMI_DATA_VI_SVC MAKE_SERVICE_ID(WMI_SERVICE_GROUP,3) -#define WMI_DATA_VO_SVC MAKE_SERVICE_ID(WMI_SERVICE_GROUP,4) -#define WMI_MAX_SERVICES 5 - -/* raw stream service (i.e. flash, tcmd, calibration apps) */ -#define HTC_RAW_STREAMS_SVC MAKE_SERVICE_ID(HTC_TEST_GROUP,0) - -#endif /*HTC_SERVICES_H_*/ diff --git a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/include/ieee80211.h b/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/include/ieee80211.h deleted file mode 100644 index 709004024..000000000 --- a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/include/ieee80211.h +++ /dev/null @@ -1,342 +0,0 @@ -/*- - * Copyright (c) 2001 Atsushi Onoe - * Copyright (c) 2002-2004 Sam Leffler, Errno Consulting - * Copyright (c) 2006 Atheros Communications, Inc. - * - * Wireless Network driver for Atheros AR6001 - * All rights reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ -#ifndef _NET80211_IEEE80211_H_ -#define _NET80211_IEEE80211_H_ - -#include "athstartpack.h" - -/* - * 802.11 protocol definitions. - */ - -#define IEEE80211_ADDR_LEN 6 /* size of 802.11 address */ -/* is 802.11 address multicast/broadcast? */ -#define IEEE80211_IS_MULTICAST(_a) (*(_a) & 0x01) -#define IEEE80211_ADDR_EQ(addr1, addr2) \ - (A_MEMCMP(addr1, addr2, IEEE80211_ADDR_LEN) == 0) - -#define IEEE80211_KEYBUF_SIZE 16 -#define IEEE80211_MICBUF_SIZE (8+8) /* space for both tx and rx */ - -/* - * NB: these values are ordered carefully; there are lots of - * of implications in any reordering. In particular beware - * that 4 is not used to avoid conflicting with IEEE80211_F_PRIVACY. - */ -#define IEEE80211_CIPHER_WEP 0 -#define IEEE80211_CIPHER_TKIP 1 -#define IEEE80211_CIPHER_AES_OCB 2 -#define IEEE80211_CIPHER_AES_CCM 3 -#define IEEE80211_CIPHER_CKIP 5 -#define IEEE80211_CIPHER_CCKM_KRK 6 -#define IEEE80211_CIPHER_NONE 7 /* pseudo value */ - -#define IEEE80211_CIPHER_MAX (IEEE80211_CIPHER_NONE+1) - -#define IEEE80211_IS_VALID_WEP_CIPHER_LEN(len) \ - (((len) == 5) || ((len) == 13) || ((len) == 16)) - - - -/* - * generic definitions for IEEE 802.11 frames - */ -PREPACK struct ieee80211_frame { - A_UINT8 i_fc[2]; - A_UINT8 i_dur[2]; - A_UINT8 i_addr1[IEEE80211_ADDR_LEN]; - A_UINT8 i_addr2[IEEE80211_ADDR_LEN]; - A_UINT8 i_addr3[IEEE80211_ADDR_LEN]; - A_UINT8 i_seq[2]; - /* possibly followed by addr4[IEEE80211_ADDR_LEN]; */ - /* see below */ -} POSTPACK; - -#define IEEE80211_FC0_VERSION_MASK 0x03 -#define IEEE80211_FC0_VERSION_SHIFT 0 -#define IEEE80211_FC0_VERSION_0 0x00 -#define IEEE80211_FC0_TYPE_MASK 0x0c -#define IEEE80211_FC0_TYPE_SHIFT 2 -#define IEEE80211_FC0_TYPE_MGT 0x00 -#define IEEE80211_FC0_TYPE_CTL 0x04 -#define IEEE80211_FC0_TYPE_DATA 0x08 - -#define IEEE80211_FC0_SUBTYPE_MASK 0xf0 -#define IEEE80211_FC0_SUBTYPE_SHIFT 4 -/* for TYPE_MGT */ -#define IEEE80211_FC0_SUBTYPE_ASSOC_REQ 0x00 -#define IEEE80211_FC0_SUBTYPE_ASSOC_RESP 0x10 -#define IEEE80211_FC0_SUBTYPE_REASSOC_REQ 0x20 -#define IEEE80211_FC0_SUBTYPE_REASSOC_RESP 0x30 -#define IEEE80211_FC0_SUBTYPE_PROBE_REQ 0x40 -#define IEEE80211_FC0_SUBTYPE_PROBE_RESP 0x50 -#define IEEE80211_FC0_SUBTYPE_BEACON 0x80 -#define IEEE80211_FC0_SUBTYPE_ATIM 0x90 -#define IEEE80211_FC0_SUBTYPE_DISASSOC 0xa0 -#define IEEE80211_FC0_SUBTYPE_AUTH 0xb0 -#define IEEE80211_FC0_SUBTYPE_DEAUTH 0xc0 -/* for TYPE_CTL */ -#define IEEE80211_FC0_SUBTYPE_PS_POLL 0xa0 -#define IEEE80211_FC0_SUBTYPE_RTS 0xb0 -#define IEEE80211_FC0_SUBTYPE_CTS 0xc0 -#define IEEE80211_FC0_SUBTYPE_ACK 0xd0 -#define IEEE80211_FC0_SUBTYPE_CF_END 0xe0 -#define IEEE80211_FC0_SUBTYPE_CF_END_ACK 0xf0 -/* for TYPE_DATA (bit combination) */ -#define IEEE80211_FC0_SUBTYPE_DATA 0x00 -#define IEEE80211_FC0_SUBTYPE_CF_ACK 0x10 -#define IEEE80211_FC0_SUBTYPE_CF_POLL 0x20 -#define IEEE80211_FC0_SUBTYPE_CF_ACPL 0x30 -#define IEEE80211_FC0_SUBTYPE_NODATA 0x40 -#define IEEE80211_FC0_SUBTYPE_CFACK 0x50 -#define IEEE80211_FC0_SUBTYPE_CFPOLL 0x60 -#define IEEE80211_FC0_SUBTYPE_CF_ACK_CF_ACK 0x70 -#define IEEE80211_FC0_SUBTYPE_QOS 0x80 -#define IEEE80211_FC0_SUBTYPE_QOS_NULL 0xc0 - -#define IEEE80211_FC1_DIR_MASK 0x03 -#define IEEE80211_FC1_DIR_NODS 0x00 /* STA->STA */ -#define IEEE80211_FC1_DIR_TODS 0x01 /* STA->AP */ -#define IEEE80211_FC1_DIR_FROMDS 0x02 /* AP ->STA */ -#define IEEE80211_FC1_DIR_DSTODS 0x03 /* AP ->AP */ - -#define IEEE80211_FC1_MORE_FRAG 0x04 -#define IEEE80211_FC1_RETRY 0x08 -#define IEEE80211_FC1_PWR_MGT 0x10 -#define IEEE80211_FC1_MORE_DATA 0x20 -#define IEEE80211_FC1_WEP 0x40 -#define IEEE80211_FC1_ORDER 0x80 - -#define IEEE80211_SEQ_FRAG_MASK 0x000f -#define IEEE80211_SEQ_FRAG_SHIFT 0 -#define IEEE80211_SEQ_SEQ_MASK 0xfff0 -#define IEEE80211_SEQ_SEQ_SHIFT 4 - -#define IEEE80211_NWID_LEN 32 - -/* - * 802.11 rate set. - */ -#define IEEE80211_RATE_SIZE 8 /* 802.11 standard */ -#define IEEE80211_RATE_MAXSIZE 15 /* max rates we'll handle */ - -#define WMM_NUM_AC 4 /* 4 AC categories */ - -#define WMM_PARAM_ACI_M 0x60 /* Mask for ACI field */ -#define WMM_PARAM_ACI_S 5 /* Shift for ACI field */ -#define WMM_PARAM_ACM_M 0x10 /* Mask for ACM bit */ -#define WMM_PARAM_ACM_S 4 /* Shift for ACM bit */ -#define WMM_PARAM_AIFSN_M 0x0f /* Mask for aifsn field */ -#define WMM_PARAM_LOGCWMIN_M 0x0f /* Mask for CwMin field (in log) */ -#define WMM_PARAM_LOGCWMAX_M 0xf0 /* Mask for CwMax field (in log) */ -#define WMM_PARAM_LOGCWMAX_S 4 /* Shift for CwMax field */ - -#define WMM_AC_TO_TID(_ac) ( \ - ((_ac) == WMM_AC_VO) ? 6 : \ - ((_ac) == WMM_AC_VI) ? 5 : \ - ((_ac) == WMM_AC_BK) ? 1 : \ - 0) - -#define TID_TO_WMM_AC(_tid) ( \ - ((_tid) < 1) ? WMM_AC_BE : \ - ((_tid) < 3) ? WMM_AC_BK : \ - ((_tid) < 6) ? WMM_AC_VI : \ - WMM_AC_VO) -/* - * Management information element payloads. - */ - -enum { - IEEE80211_ELEMID_SSID = 0, - IEEE80211_ELEMID_RATES = 1, - IEEE80211_ELEMID_FHPARMS = 2, - IEEE80211_ELEMID_DSPARMS = 3, - IEEE80211_ELEMID_CFPARMS = 4, - IEEE80211_ELEMID_TIM = 5, - IEEE80211_ELEMID_IBSSPARMS = 6, - IEEE80211_ELEMID_COUNTRY = 7, - IEEE80211_ELEMID_CHALLENGE = 16, - /* 17-31 reserved for challenge text extension */ - IEEE80211_ELEMID_PWRCNSTR = 32, - IEEE80211_ELEMID_PWRCAP = 33, - IEEE80211_ELEMID_TPCREQ = 34, - IEEE80211_ELEMID_TPCREP = 35, - IEEE80211_ELEMID_SUPPCHAN = 36, - IEEE80211_ELEMID_CHANSWITCH = 37, - IEEE80211_ELEMID_MEASREQ = 38, - IEEE80211_ELEMID_MEASREP = 39, - IEEE80211_ELEMID_QUIET = 40, - IEEE80211_ELEMID_IBSSDFS = 41, - IEEE80211_ELEMID_ERP = 42, - IEEE80211_ELEMID_RSN = 48, - IEEE80211_ELEMID_XRATES = 50, - IEEE80211_ELEMID_TPC = 150, - IEEE80211_ELEMID_CCKM = 156, - IEEE80211_ELEMID_VENDOR = 221, /* vendor private */ -}; - -#define ATH_OUI 0x7f0300 /* Atheros OUI */ -#define ATH_OUI_TYPE 0x01 -#define ATH_OUI_SUBTYPE 0x01 -#define ATH_OUI_VERSION 0x00 - -#define WPA_OUI 0xf25000 -#define WPA_OUI_TYPE 0x01 -#define WPA_VERSION 1 /* current supported version */ - -#define WPA_CSE_NULL 0x00 -#define WPA_CSE_WEP40 0x01 -#define WPA_CSE_TKIP 0x02 -#define WPA_CSE_CCMP 0x04 -#define WPA_CSE_WEP104 0x05 - -#define WPA_ASE_NONE 0x00 -#define WPA_ASE_8021X_UNSPEC 0x01 -#define WPA_ASE_8021X_PSK 0x02 - -#define RSN_OUI 0xac0f00 -#define RSN_VERSION 1 /* current supported version */ - -#define RSN_CSE_NULL 0x00 -#define RSN_CSE_WEP40 0x01 -#define RSN_CSE_TKIP 0x02 -#define RSN_CSE_WRAP 0x03 -#define RSN_CSE_CCMP 0x04 -#define RSN_CSE_WEP104 0x05 - -#define RSN_ASE_NONE 0x00 -#define RSN_ASE_8021X_UNSPEC 0x01 -#define RSN_ASE_8021X_PSK 0x02 - -#define RSN_CAP_PREAUTH 0x01 - -#define WMM_OUI 0xf25000 -#define WMM_OUI_TYPE 0x02 -#define WMM_INFO_OUI_SUBTYPE 0x00 -#define WMM_PARAM_OUI_SUBTYPE 0x01 -#define WMM_VERSION 1 - -/* WMM stream classes */ -#define WMM_NUM_AC 4 -#define WMM_AC_BE 0 /* best effort */ -#define WMM_AC_BK 1 /* background */ -#define WMM_AC_VI 2 /* video */ -#define WMM_AC_VO 3 /* voice */ - -/* TSPEC related */ -#define ACTION_CATEGORY_CODE_TSPEC 17 -#define ACTION_CODE_TSPEC_ADDTS 0 -#define ACTION_CODE_TSPEC_ADDTS_RESP 1 -#define ACTION_CODE_TSPEC_DELTS 2 - -typedef enum { - TSPEC_STATUS_CODE_ADMISSION_ACCEPTED = 0, - TSPEC_STATUS_CODE_ADDTS_INVALID_PARAMS = 0x1, - TSPEC_STATUS_CODE_ADDTS_REQUEST_REFUSED = 0x3, - TSPEC_STATUS_CODE_UNSPECIFIED_QOS_RELATED_FAILURE = 0xC8, - TSPEC_STATUS_CODE_REQUESTED_REFUSED_POLICY_CONFIGURATION = 0xC9, - TSPEC_STATUS_CODE_INSUFFCIENT_BANDWIDTH = 0xCA, - TSPEC_STATUS_CODE_INVALID_PARAMS = 0xCB, - TSPEC_STATUS_CODE_DELTS_SENT = 0x30, - TSPEC_STATUS_CODE_DELTS_RECV = 0x31, -} TSPEC_STATUS_CODE; - -/* - * WMM/802.11e Tspec Element - */ -typedef PREPACK struct wmm_tspec_ie_t { - A_UINT8 elementId; - A_UINT8 len; - A_UINT8 oui[3]; - A_UINT8 ouiType; - A_UINT8 ouiSubType; - A_UINT8 version; - A_UINT16 tsInfo_info; - A_UINT8 tsInfo_reserved; - A_UINT16 nominalMSDU; - A_UINT16 maxMSDU; - A_UINT32 minServiceInt; - A_UINT32 maxServiceInt; - A_UINT32 inactivityInt; - A_UINT32 suspensionInt; - A_UINT32 serviceStartTime; - A_UINT32 minDataRate; - A_UINT32 meanDataRate; - A_UINT32 peakDataRate; - A_UINT32 maxBurstSize; - A_UINT32 delayBound; - A_UINT32 minPhyRate; - A_UINT16 sba; - A_UINT16 mediumTime; -} POSTPACK WMM_TSPEC_IE; - - -/* - * BEACON management packets - * - * octet timestamp[8] - * octet beacon interval[2] - * octet capability information[2] - * information element - * octet elemid - * octet length - * octet information[length] - */ - -#define IEEE80211_BEACON_INTERVAL(beacon) \ - ((beacon)[8] | ((beacon)[9] << 8)) -#define IEEE80211_BEACON_CAPABILITY(beacon) \ - ((beacon)[10] | ((beacon)[11] << 8)) - -#define IEEE80211_CAPINFO_ESS 0x0001 -#define IEEE80211_CAPINFO_IBSS 0x0002 -#define IEEE80211_CAPINFO_CF_POLLABLE 0x0004 -#define IEEE80211_CAPINFO_CF_POLLREQ 0x0008 -#define IEEE80211_CAPINFO_PRIVACY 0x0010 -#define IEEE80211_CAPINFO_SHORT_PREAMBLE 0x0020 -#define IEEE80211_CAPINFO_PBCC 0x0040 -#define IEEE80211_CAPINFO_CHNL_AGILITY 0x0080 -/* bits 8-9 are reserved */ -#define IEEE80211_CAPINFO_SHORT_SLOTTIME 0x0400 -#define IEEE80211_CAPINFO_APSD 0x0800 -/* bit 12 is reserved */ -#define IEEE80211_CAPINFO_DSSSOFDM 0x2000 -/* bits 14-15 are reserved */ - -/* - * Authentication Modes - */ - -enum ieee80211_authmode { - IEEE80211_AUTH_NONE = 0, - IEEE80211_AUTH_OPEN = 1, - IEEE80211_AUTH_SHARED = 2, - IEEE80211_AUTH_8021X = 3, - IEEE80211_AUTH_AUTO = 4, /* auto-select/accept */ - /* NB: these are used only for ioctls */ - IEEE80211_AUTH_WPA = 5, /* WPA/RSN w/ 802.1x */ - IEEE80211_AUTH_WPA_PSK = 6, /* WPA/RSN w/ PSK */ - IEEE80211_AUTH_WPA_CCKM = 7, /* WPA/RSN IE w/ CCKM */ -}; - -#include "athendpack.h" - -#endif /* _NET80211_IEEE80211_H_ */ diff --git a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/include/ieee80211_ioctl.h b/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/include/ieee80211_ioctl.h deleted file mode 100644 index dab6747c4..000000000 --- a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/include/ieee80211_ioctl.h +++ /dev/null @@ -1,163 +0,0 @@ -/* - * Copyright (c) 2004-2005 Atheros Communications Inc. - * All rights reserved. - * - * - * 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; - * - * Software distributed under the License is distributed on an "AS - * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or - * implied. See the License for the specific language governing - * rights and limitations under the License. - * - * - * - * - * $Id: //depot/sw/releases/olca2.0-GPL/host/os/linux/include/ieee80211_ioctl.h#1 $ - */ - -#ifndef _IEEE80211_IOCTL_H_ -#define _IEEE80211_IOCTL_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * Extracted from the MADWIFI net80211/ieee80211_ioctl.h - */ - -/* - * WPA/RSN get/set key request. Specify the key/cipher - * type and whether the key is to be used for sending and/or - * receiving. The key index should be set only when working - * with global keys (use IEEE80211_KEYIX_NONE for ``no index''). - * Otherwise a unicast/pairwise key is specified by the bssid - * (on a station) or mac address (on an ap). They key length - * must include any MIC key data; otherwise it should be no - more than IEEE80211_KEYBUF_SIZE. - */ -struct ieee80211req_key { - u_int8_t ik_type; /* key/cipher type */ - u_int8_t ik_pad; - u_int16_t ik_keyix; /* key index */ - u_int8_t ik_keylen; /* key length in bytes */ - u_int8_t ik_flags; -#define IEEE80211_KEY_XMIT 0x01 -#define IEEE80211_KEY_RECV 0x02 -#define IEEE80211_KEY_DEFAULT 0x80 /* default xmit key */ - u_int8_t ik_macaddr[IEEE80211_ADDR_LEN]; - u_int64_t ik_keyrsc; /* key receive sequence counter */ - u_int64_t ik_keytsc; /* key transmit sequence counter */ - u_int8_t ik_keydata[IEEE80211_KEYBUF_SIZE+IEEE80211_MICBUF_SIZE]; -}; -/* - * Delete a key either by index or address. Set the index - * to IEEE80211_KEYIX_NONE when deleting a unicast key. - */ -struct ieee80211req_del_key { - u_int8_t idk_keyix; /* key index */ - u_int8_t idk_macaddr[IEEE80211_ADDR_LEN]; -}; -/* - * MLME state manipulation request. IEEE80211_MLME_ASSOC - * only makes sense when operating as a station. The other - * requests can be used when operating as a station or an - * ap (to effect a station). - */ -struct ieee80211req_mlme { - u_int8_t im_op; /* operation to perform */ -#define IEEE80211_MLME_ASSOC 1 /* associate station */ -#define IEEE80211_MLME_DISASSOC 2 /* disassociate station */ -#define IEEE80211_MLME_DEAUTH 3 /* deauthenticate station */ -#define IEEE80211_MLME_AUTHORIZE 4 /* authorize station */ -#define IEEE80211_MLME_UNAUTHORIZE 5 /* unauthorize station */ - u_int16_t im_reason; /* 802.11 reason code */ - u_int8_t im_macaddr[IEEE80211_ADDR_LEN]; -}; - -struct ieee80211req_addpmkid { - u_int8_t pi_bssid[IEEE80211_ADDR_LEN]; - u_int8_t pi_enable; - u_int8_t pi_pmkid[16]; -}; - -#define AUTH_ALG_OPEN_SYSTEM 0x01 -#define AUTH_ALG_SHARED_KEY 0x02 -#define AUTH_ALG_LEAP 0x04 - -struct ieee80211req_authalg { - u_int8_t auth_alg; -}; - -/* - * Request to add an IE to a Management Frame - */ -enum{ - IEEE80211_APPIE_FRAME_BEACON = 0, - IEEE80211_APPIE_FRAME_PROBE_REQ = 1, - IEEE80211_APPIE_FRAME_PROBE_RESP = 2, - IEEE80211_APPIE_FRAME_ASSOC_REQ = 3, - IEEE80211_APPIE_FRAME_ASSOC_RESP = 4, - IEEE80211_APPIE_NUM_OF_FRAME = 5 -}; - -/* - * The Maximum length of the IE that can be added to a Management frame - */ -#define IEEE80211_APPIE_FRAME_MAX_LEN 78 - -struct ieee80211req_getset_appiebuf { - u_int32_t app_frmtype; /* management frame type for which buffer is added */ - u_int32_t app_buflen; /*application supplied buffer length */ - u_int8_t app_buf[]; -}; - -/* - * The following definitions are used by an application to set filter - * for receiving management frames - */ -enum { - IEEE80211_FILTER_TYPE_BEACON = 0x1, - IEEE80211_FILTER_TYPE_PROBE_REQ = 0x2, - IEEE80211_FILTER_TYPE_PROBE_RESP = 0x4, - IEEE80211_FILTER_TYPE_ASSOC_REQ = 0x8, - IEEE80211_FILTER_TYPE_ASSOC_RESP = 0x10, - IEEE80211_FILTER_TYPE_AUTH = 0x20, - IEEE80211_FILTER_TYPE_DEAUTH = 0x40, - IEEE80211_FILTER_TYPE_DISASSOC = 0x80, - IEEE80211_FILTER_TYPE_ALL = 0xFF /* used to check the valid filter bits */ -}; - -struct ieee80211req_set_filter { - u_int32_t app_filterype; /* management frame filter type */ -}; - -enum { - IEEE80211_PARAM_AUTHMODE = 3, /* Authentication Mode */ - IEEE80211_PARAM_MCASTCIPHER = 5, - IEEE80211_PARAM_MCASTKEYLEN = 6, /* multicast key length */ - IEEE80211_PARAM_UCASTCIPHER = 8, - IEEE80211_PARAM_UCASTKEYLEN = 9, /* unicast key length */ - IEEE80211_PARAM_WPA = 10, /* WPA mode (0,1,2) */ - IEEE80211_PARAM_ROAMING = 12, /* roaming mode */ - IEEE80211_PARAM_PRIVACY = 13, /* privacy invoked */ - IEEE80211_PARAM_COUNTERMEASURES = 14, /* WPA/TKIP countermeasures */ - IEEE80211_PARAM_DROPUNENCRYPTED = 15, /* discard unencrypted frames */ -}; - -/* - * Values for IEEE80211_PARAM_WPA - */ -#define WPA_MODE_WPA1 1 -#define WPA_MODE_WPA2 2 -#define WPA_MODE_AUTO 3 -#define WPA_MODE_NONE 4 - -#ifdef __cplusplus -} -#endif - -#endif /* _IEEE80211_IOCTL_H_ */ diff --git a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/include/ieee80211_node.h b/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/include/ieee80211_node.h deleted file mode 100644 index 46b613c09..000000000 --- a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/include/ieee80211_node.h +++ /dev/null @@ -1,77 +0,0 @@ -/*- - * Copyright (c) 2001 Atsushi Onoe - * Copyright (c) 2002-2004 Sam Leffler, Errno Consulting - * Copyright (c) 2006 Atheros Communications, Inc. - * - * Wireless Network driver for Atheros AR6001 - * All rights reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ -#ifndef _IEEE80211_NODE_H_ -#define _IEEE80211_NODE_H_ - -/* - * Node locking definitions. - */ -#define IEEE80211_NODE_LOCK_INIT(_nt) A_MUTEX_INIT(&(_nt)->nt_nodelock) -#define IEEE80211_NODE_LOCK_DESTROY(_nt) -#define IEEE80211_NODE_LOCK(_nt) A_MUTEX_LOCK(&(_nt)->nt_nodelock) -#define IEEE80211_NODE_UNLOCK(_nt) A_MUTEX_UNLOCK(&(_nt)->nt_nodelock) -#define IEEE80211_NODE_LOCK_BH(_nt) A_MUTEX_LOCK(&(_nt)->nt_nodelock) -#define IEEE80211_NODE_UNLOCK_BH(_nt) A_MUTEX_UNLOCK(&(_nt)->nt_nodelock) -#define IEEE80211_NODE_LOCK_ASSERT(_nt) - -/* - * Node reference counting definitions. - * - * ieee80211_node_initref initialize the reference count to 1 - * ieee80211_node_incref add a reference - * ieee80211_node_decref remove a reference - * ieee80211_node_dectestref remove a reference and return 1 if this - * is the last reference, otherwise 0 - * ieee80211_node_refcnt reference count for printing (only) - */ -#define ieee80211_node_initref(_ni) ((_ni)->ni_refcnt = 1) -#define ieee80211_node_incref(_ni) ((_ni)->ni_refcnt++) -#define ieee80211_node_decref(_ni) ((_ni)->ni_refcnt--) -#define ieee80211_node_dectestref(_ni) (((_ni)->ni_refcnt--) == 0) -#define ieee80211_node_refcnt(_ni) ((_ni)->ni_refcnt) - -#define IEEE80211_NODE_HASHSIZE 32 -/* simple hash is enough for variation of macaddr */ -#define IEEE80211_NODE_HASH(addr) \ - (((const A_UINT8 *)(addr))[IEEE80211_ADDR_LEN - 1] % \ - IEEE80211_NODE_HASHSIZE) - -/* - * Table of ieee80211_node instances. Each ieee80211com - * has at least one for holding the scan candidates. - * When operating as an access point or in ibss mode there - * is a second table for associated stations or neighbors. - */ -struct ieee80211_node_table { - void *nt_wmip; /* back reference */ - A_MUTEX_T nt_nodelock; /* on node table */ - struct bss *nt_node_first; /* information of all nodes */ - struct bss *nt_node_last; /* information of all nodes */ - struct bss *nt_hash[IEEE80211_NODE_HASHSIZE]; - const char *nt_name; /* for debugging */ - A_UINT32 nt_scangen; /* gen# for timeout scan */ - A_TIMER nt_inact_timer; - A_UINT8 isTimerArmed; /* is the node timer armed */ -}; - -#define WLAN_NODE_INACT_TIMEOUT_MSEC 10000 - -#endif /* _IEEE80211_NODE_H_ */ diff --git a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/include/ini_dset.h b/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/include/ini_dset.h deleted file mode 100644 index 410f2b525..000000000 --- a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/include/ini_dset.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (c) 2004-2007 Atheros Communications Inc. - * All rights reserved. - * - * $ATH_LICENSE_HOSTSDK0_C$ - * - */ -#ifndef _INI_DSET_H_ -#define _INI_DSET_H_ - -/* - * Each of these represents a WHAL INI table, which consists - * of an "address column" followed by 1 or more "value columns". - * - * Software uses the base WHAL_INI_DATA_ID+column to access a - * DataSet that holds a particular column of data. - */ -typedef enum { - WHAL_INI_DATA_ID_NULL =0, - WHAL_INI_DATA_ID_MODE_SPECIFIC =1, /* 2,3 */ - WHAL_INI_DATA_ID_COMMON =4, /* 5 */ - WHAL_INI_DATA_ID_BB_RFGAIN =6, /* 7,8 */ - WHAL_INI_DATA_ID_ANALOG_BANK1 =9, /* 10 */ - WHAL_INI_DATA_ID_ANALOG_BANK2 =11, /* 12 */ - WHAL_INI_DATA_ID_ANALOG_BANK3 =13, /* 14, 15 */ - WHAL_INI_DATA_ID_ANALOG_BANK6 =16, /* 17, 18 */ - WHAL_INI_DATA_ID_ANALOG_BANK7 =19, /* 20 */ - WHAL_INI_DATA_ID_MODE_OVERRIDES =21, /* 22,23 */ - WHAL_INI_DATA_ID_COMMON_OVERRIDES =24, /* 25 */ - - WHAL_INI_DATA_ID_MAX =25 -} WHAL_INI_DATA_ID; - -typedef PREPACK struct { - A_UINT16 freqIndex; // 1 - A mode 2 - B or G mode 0 - common - A_UINT16 offset; - A_UINT32 newValue; -} POSTPACK INI_DSET_REG_OVERRIDE; - -#endif diff --git a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/include/regDb.h b/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/include/regDb.h deleted file mode 100644 index b3f665ff5..000000000 --- a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/include/regDb.h +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright (c) 2005 Atheros Communications, Inc. - * All rights reserved. - * - * - * $ATH_LICENSE_HOSTSDK0_C$ - * - * This module contains the header files for regulatory module, - * which include the DB schema and DB values. - * $Id: - */ - -#ifndef __REG_DB_H__ -#define __REG_DB_H__ - -#include "./regulatory/reg_dbschema.h" -#include "./regulatory/reg_dbvalues.h" - -#endif /* __REG_DB_H__ */ diff --git a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/include/regdump.h b/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/include/regdump.h deleted file mode 100644 index 0106825ce..000000000 --- a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/include/regdump.h +++ /dev/null @@ -1,33 +0,0 @@ -#ifndef __REGDUMP_H__ -#define __REGDUMP_H__ -/* - * Copyright (c) 2004-2007 Atheros Communications Inc. - * All rights reserved. - * - * $ATH_LICENSE_HOSTSDK0_C$ - * - */ -#if defined(AR6001) -#include "AR6001/AR6001_regdump.h" -#endif -#if defined(AR6002) -#include "AR6002/AR6002_regdump.h" -#endif - -#if !defined(__ASSEMBLER__) -/* - * Target CPU state at the time of failure is reflected - * in a register dump, which the Host can fetch through - * the diagnostic window. - */ -struct register_dump_s { - A_UINT32 target_id; /* Target ID */ - A_UINT32 assline; /* Line number (if assertion failure) */ - A_UINT32 pc; /* Program Counter at time of exception */ - A_UINT32 badvaddr; /* Virtual address causing exception */ - CPU_exception_frame_t exc_frame; /* CPU-specific exception info */ - - /* Could copy top of stack here, too.... */ -}; -#endif /* __ASSEMBLER__ */ -#endif /* __REGDUMP_H__ */ diff --git a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/include/targaddrs.h b/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/include/targaddrs.h deleted file mode 100644 index da2a65090..000000000 --- a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/include/targaddrs.h +++ /dev/null @@ -1,158 +0,0 @@ -/* - * Copyright (c) 2004-2007 Atheros Communications Inc. - * All rights reserved. - * - * $ATH_LICENSE_HOSTSDK0_C$ - * - */ - -#ifndef __TARGADDRS_H__ -#define __TARGADDRS_H__ -#if defined(AR6001) -#include "AR6001/addrs.h" -#endif -#if defined(AR6002) -#include "AR6002/addrs.h" -#endif - -/* - * AR6K option bits, to enable/disable various features. - * By default, all option bits are 0. - * These bits can be set in LOCAL_SCRATCH register 0. - */ -#define AR6K_OPTION_BMI_DISABLE 0x01 /* Disable BMI comm with Host */ -#define AR6K_OPTION_SERIAL_ENABLE 0x02 /* Enable serial port msgs */ -#define AR6K_OPTION_WDT_DISABLE 0x04 /* WatchDog Timer override */ -#define AR6K_OPTION_SLEEP_DISABLE 0x08 /* Disable system sleep */ -#define AR6K_OPTION_STOP_BOOT 0x10 /* Stop boot processes (for ATE) */ -#define AR6K_OPTION_ENABLE_NOANI 0x20 /* Operate without ANI */ -#define AR6K_OPTION_DSET_DISABLE 0x40 /* Ignore DataSets */ -#define AR6K_OPTION_IGNORE_FLASH 0x80 /* Ignore flash during bootup */ - -/* - * xxx_HOST_INTEREST_ADDRESS is the address in Target RAM of the - * host_interest structure. It must match the address of the _host_interest - * symbol (see linker script). - * - * Host Interest is shared between Host and Target in order to coordinate - * between the two, and is intended to remain constant (with additions only - * at the end) across software releases. - */ -#define AR6001_HOST_INTEREST_ADDRESS 0x80000600 -#define AR6002_HOST_INTEREST_ADDRESS 0x00500400 - -#define HOST_INTEREST_MAX_SIZE 0x100 - -#if !defined(__ASSEMBLER__) -struct register_dump_s; -struct dbglog_hdr_s; - -/* - * These are items that the Host may need to access - * via BMI or via the Diagnostic Window. The position - * of items in this structure must remain constant - * across firmware revisions! - * - * Types for each item must be fixed size across - * target and host platforms. - * - * More items may be added at the end. - */ -struct host_interest_s { - /* - * Pointer to application-defined area, if any. - * Set by Target application during startup. - */ - A_UINT32 hi_app_host_interest; /* 0x00 */ - - /* Pointer to register dump area, valid after Target crash. */ - A_UINT32 hi_failure_state; /* 0x04 */ - - /* Pointer to debug logging header */ - A_UINT32 hi_dbglog_hdr; /* 0x08 */ - - /* Indicates whether or not flash is present on Target. - * NB: flash_is_present indicator is here not just - * because it might be of interest to the Host; but - * also because it's set early on by Target's startup - * asm code and we need it to have a special RAM address - * so that it doesn't get reinitialized with the rest - * of data. - */ - A_UINT32 hi_flash_is_present; /* 0x0c */ - - /* - * General-purpose flag bits, similar to AR6000_OPTION_* flags. - * Can be used by application rather than by OS. - */ - A_UINT32 hi_option_flag; /* 0x10 */ - - /* - * Boolean that determines whether or not to - * display messages on the serial port. - */ - A_UINT32 hi_serial_enable; /* 0x14 */ - - /* Start address of Flash DataSet index, if any */ - A_UINT32 hi_dset_list_head; /* 0x18 */ - - /* Override Target application start address */ - A_UINT32 hi_app_start; /* 0x1c */ - - /* Clock and voltage tuning */ - A_UINT32 hi_skip_clock_init; /* 0x20 */ - A_UINT32 hi_core_clock_setting; /* 0x24 */ - A_UINT32 hi_cpu_clock_setting; /* 0x28 */ - A_UINT32 hi_system_sleep_setting; /* 0x2c */ - A_UINT32 hi_xtal_control_setting; /* 0x30 */ - A_UINT32 hi_pll_ctrl_setting_24ghz; /* 0x34 */ - A_UINT32 hi_pll_ctrl_setting_5ghz; /* 0x38 */ - A_UINT32 hi_ref_voltage_trim_setting; /* 0x3c */ - A_UINT32 hi_clock_info; /* 0x40 */ - - /* - * Flash configuration overrides, used only - * when firmware is not executing from flash. - * (When using flash, modify the global variables - * with equivalent names.) - */ - A_UINT32 hi_bank0_addr_value; /* 0x44 */ - A_UINT32 hi_bank0_read_value; /* 0x48 */ - A_UINT32 hi_bank0_write_value; /* 0x4c */ - A_UINT32 hi_bank0_config_value; /* 0x50 */ - - /* Pointer to Board Data */ - A_UINT32 hi_board_data; /* 0x54 */ - A_UINT32 hi_board_data_initialized; /* 0x58 */ - - A_UINT32 hi_dset_RAM_index_table; /* 0x5c */ - - A_UINT32 hi_desired_baud_rate; /* 0x60 */ - A_UINT32 hi_dbglog_config; /* 0x64 */ - A_UINT32 hi_end_RAM_reserve_sz; /* 0x68 */ - A_UINT32 hi_mbox_io_block_sz; /* 0x6c */ - - A_UINT32 hi_num_bpatch_streams; /* 0x70 */ - A_UINT32 hi_mbox_isr_yield_limit; /* 0x74 */ - - A_UINT32 hi_refclk_hz; /* 0x78 */ -}; - -/* Bits defined in hi_option_flag */ -#define HI_OPTION_TIMER_WAR 1 /* not really used */ - -/* - * Intended for use by Host software, this macro returns the Target RAM - * address of any item in the host_interest structure. - * Example: target_addr = AR6001_HOST_INTEREST_ITEM_ADDRESS(hi_board_data); - */ -#define AR6001_HOST_INTEREST_ITEM_ADDRESS(item) \ - ((A_UINT32)&((((struct host_interest_s *)(AR6001_HOST_INTEREST_ADDRESS))->item))) - -#define AR6002_HOST_INTEREST_ITEM_ADDRESS(item) \ - ((A_UINT32)&((((struct host_interest_s *)(AR6002_HOST_INTEREST_ADDRESS))->item))) - - -#endif /* !__ASSEMBLER__ */ - -#endif /* __TARGADDRS_H__ */ diff --git a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/include/testcmd.h b/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/include/testcmd.h deleted file mode 100644 index 737533adb..000000000 --- a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/include/testcmd.h +++ /dev/null @@ -1,144 +0,0 @@ -/* - * Copyright (c) 2004-2005 Atheros Communications Inc. - * All rights reserved. - * - * - * $ATH_LICENSE_HOSTSDK0_C$ - * - */ - -#ifndef TESTCMD_H_ -#define TESTCMD_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -typedef enum { - ZEROES_PATTERN = 0, - ONES_PATTERN, - REPEATING_10, - PN7_PATTERN, - PN9_PATTERN, - PN15_PATTERN -}TX_DATA_PATTERN; - -/* Continous tx - mode : TCMD_CONT_TX_OFF - Disabling continous tx - TCMD_CONT_TX_SINE - Enable continuous unmodulated tx - TCMD_CONT_TX_FRAME- Enable continuous modulated tx - freq : Channel freq in Mhz. (e.g 2412 for channel 1 in 11 g) -dataRate: 0 - 1 Mbps - 1 - 2 Mbps - 2 - 5.5 Mbps - 3 - 11 Mbps - 4 - 6 Mbps - 5 - 9 Mbps - 6 - 12 Mbps - 7 - 18 Mbps - 8 - 24 Mbps - 9 - 36 Mbps - 10 - 28 Mbps - 11 - 54 Mbps - txPwr: Tx power in dBm[5 -11] for unmod Tx, [5-14] for mod Tx -antenna: 1 - one antenna - 2 - two antenna -Note : Enable/disable continuous tx test cmd works only when target is awake. -*/ - -typedef enum { - TCMD_CONT_TX_OFF = 0, - TCMD_CONT_TX_SINE, - TCMD_CONT_TX_FRAME, - TCMD_CONT_TX_TX99, - TCMD_CONT_TX_TX100 -} TCMD_CONT_TX_MODE; - -typedef PREPACK struct { - A_UINT32 testCmdId; - A_UINT32 mode; - A_UINT32 freq; - A_UINT32 dataRate; - A_INT32 txPwr; - A_UINT32 antenna; - A_UINT32 enANI; - A_UINT32 scramblerOff; - A_UINT32 aifsn; - A_UINT16 pktSz; - A_UINT16 txPattern; -} POSTPACK TCMD_CONT_TX; - -#define TCMD_TXPATTERN_ZERONE 0x1 -#define TCMD_TXPATTERN_ZERONE_DIS_SCRAMBLE 0x2 - -/* Continuous Rx - act: TCMD_CONT_RX_PROMIS - promiscuous mode (accept all incoming frames) - TCMD_CONT_RX_FILTER - filter mode (accept only frames with dest - address equal specified - mac address (set via act =3) - TCMD_CONT_RX_REPORT off mode (disable cont rx mode and get the - report from the last cont - Rx test) - - TCMD_CONT_RX_SETMAC - set MacAddr mode (sets the MAC address for the - target. This Overrides - the default MAC address.) - -*/ -typedef enum { - TCMD_CONT_RX_PROMIS =0, - TCMD_CONT_RX_FILTER, - TCMD_CONT_RX_REPORT, - TCMD_CONT_RX_SETMAC -} TCMD_CONT_RX_ACT; - -typedef PREPACK struct { - A_UINT32 testCmdId; - A_UINT32 act; - A_UINT32 enANI; - PREPACK union { - struct PREPACK TCMD_CONT_RX_PARA { - A_UINT32 freq; - A_UINT32 antenna; - } POSTPACK para; - struct PREPACK TCMD_CONT_RX_REPORT { - A_UINT32 totalPkt; - A_INT32 rssiInDBm; - } POSTPACK report; - struct PREPACK TCMD_CONT_RX_MAC { - A_UCHAR addr[ATH_MAC_LEN]; - } POSTPACK mac; - } POSTPACK u; -} POSTPACK TCMD_CONT_RX; - -/* Force sleep/wake test cmd - mode: TCMD_PM_WAKEUP - Wakeup the target - TCMD_PM_SLEEP - Force the target to sleep. - */ -typedef enum { - TCMD_PM_WAKEUP = 1, /* be consistent with target */ - TCMD_PM_SLEEP -} TCMD_PM_MODE; - -typedef PREPACK struct { - A_UINT32 testCmdId; - A_UINT32 mode; -} POSTPACK TCMD_PM; - -typedef enum{ - TCMD_CONT_TX_ID, - TCMD_CONT_RX_ID, - TCMD_PM_ID - } TCMD_ID; - -typedef PREPACK union { - TCMD_CONT_TX contTx; - TCMD_CONT_RX contRx; - TCMD_PM pm ; -} POSTPACK TEST_CMD; - -#ifdef __cplusplus -} -#endif - -#endif /* TESTCMD_H_ */ diff --git a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/include/wlan_api.h b/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/include/wlan_api.h deleted file mode 100644 index aabca4b7b..000000000 --- a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/include/wlan_api.h +++ /dev/null @@ -1,101 +0,0 @@ -#ifndef _HOST_WLAN_API_H_ -#define _HOST_WLAN_API_H_ -/* - * Copyright (c) 2004-2005 Atheros Communications Inc. - * All rights reserved. - * - * This file contains the API for the host wlan module - * - * $Id: //depot/sw/releases/olca2.0-GPL/host/include/wlan_api.h#1 $ - * - * - * 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; - * - * Software distributed under the License is distributed on an "AS - * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or - * implied. See the License for the specific language governing - * rights and limitations under the License. - * - * - * - */ - -#ifdef __cplusplus -extern "C" { -#endif - -struct ieee80211_node_table; -struct ieee80211_frame; - -struct ieee80211_common_ie { - A_UINT16 ie_chan; - A_UINT8 *ie_tstamp; - A_UINT8 *ie_ssid; - A_UINT8 *ie_rates; - A_UINT8 *ie_xrates; - A_UINT8 *ie_country; - A_UINT8 *ie_wpa; - A_UINT8 *ie_rsn; - A_UINT8 *ie_wmm; - A_UINT8 *ie_ath; - A_UINT16 ie_capInfo; - A_UINT16 ie_beaconInt; - A_UINT8 *ie_tim; - A_UINT8 *ie_chswitch; - A_UINT8 ie_erp; - A_UINT8 *ie_wsc; -}; - -typedef struct bss { - A_UINT8 ni_macaddr[6]; - A_UINT8 ni_snr; - A_INT16 ni_rssi; - struct bss *ni_list_next; - struct bss *ni_list_prev; - struct bss *ni_hash_next; - struct bss *ni_hash_prev; - struct ieee80211_common_ie ni_cie; - A_UINT8 *ni_buf; - struct ieee80211_node_table *ni_table; - A_UINT32 ni_refcnt; - int ni_scangen; - A_UINT32 ni_tstamp; -} bss_t; - -typedef void wlan_node_iter_func(void *arg, bss_t *); - -bss_t *wlan_node_alloc(struct ieee80211_node_table *nt, int wh_size); -void wlan_node_free(bss_t *ni); -void wlan_setup_node(struct ieee80211_node_table *nt, bss_t *ni, - const A_UINT8 *macaddr); -bss_t *wlan_find_node(struct ieee80211_node_table *nt, const A_UINT8 *macaddr); -void wlan_node_reclaim(struct ieee80211_node_table *nt, bss_t *ni); -void wlan_free_allnodes(struct ieee80211_node_table *nt); -void wlan_iterate_nodes(struct ieee80211_node_table *nt, wlan_node_iter_func *f, - void *arg); - -void wlan_node_table_init(void *wmip, struct ieee80211_node_table *nt); -void wlan_node_table_reset(struct ieee80211_node_table *nt); -void wlan_node_table_cleanup(struct ieee80211_node_table *nt); - -A_STATUS wlan_parse_beacon(A_UINT8 *buf, int framelen, - struct ieee80211_common_ie *cie); - -A_UINT16 wlan_ieee2freq(int chan); -A_UINT32 wlan_freq2ieee(A_UINT16 freq); - - -bss_t * -wlan_find_Ssidnode (struct ieee80211_node_table *nt, A_UCHAR *pSsid, - A_UINT32 ssidLength, A_BOOL bIsWPA2); - -void -wlan_node_return (struct ieee80211_node_table *nt, bss_t *ni); - -#ifdef __cplusplus -} -#endif - -#endif /* _HOST_WLAN_API_H_ */ diff --git a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/include/wlan_dset.h b/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/include/wlan_dset.h deleted file mode 100644 index 8a876d647..000000000 --- a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/include/wlan_dset.h +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright (c) 2007 Atheros Communications, Inc. - * All rights reserved. - * - * - * $ATH_LICENSE_HOSTSDK0_C$ - * - */ - -#ifndef __WLAN_DSET_H__ -#define __WKAN_DSET_H__ - -typedef PREPACK struct wow_config_dset { - - A_UINT8 valid_dset; - A_UINT8 gpio_enable; - A_UINT16 gpio_pin; -} POSTPACK WOW_CONFIG_DSET; - -#endif diff --git a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/include/wmi.h b/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/include/wmi.h deleted file mode 100644 index 045acd4d3..000000000 --- a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/include/wmi.h +++ /dev/null @@ -1,1743 +0,0 @@ -/* - * Copyright (c) 2004-2006 Atheros Communications Inc. - * All rights reserved. - * - * - * $ATH_LICENSE_HOSTSDK0_C$ - * - * This file contains the definitions of the WMI protocol specified in the - * Wireless Module Interface (WMI). It includes definitions of all the - * commands and events. Commands are messages from the host to the WM. - * Events and Replies are messages from the WM to the host. - * - * Ownership of correctness in regards to WMI commands - * belongs to the host driver and the WM is not required to validate - * parameters for value, proper range, or any other checking. - * - */ - -#ifndef _WMI_H_ -#define _WMI_H_ - -#ifndef ATH_TARGET -#include "athstartpack.h" -#endif - -#include "wmix.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#define WMI_PROTOCOL_VERSION 0x0002 -#define WMI_PROTOCOL_REVISION 0x0000 - -#define ATH_MAC_LEN 6 /* length of mac in bytes */ -#define WMI_CMD_MAX_LEN 100 -#define WMI_CONTROL_MSG_MAX_LEN 256 -#define WMI_OPT_CONTROL_MSG_MAX_LEN 1536 -#define IS_ETHERTYPE(_typeOrLen) ((_typeOrLen) >= 0x0600) -#define RFC1042OUI {0x00, 0x00, 0x00} - -#define IP_ETHERTYPE 0x0800 - -#define WMI_IMPLICIT_PSTREAM 0xFF -#define WMI_MAX_THINSTREAM 15 - -struct host_app_area_s { - A_UINT32 wmi_protocol_ver; -}; - -/* - * Data Path - */ -typedef PREPACK struct { - A_UINT8 dstMac[ATH_MAC_LEN]; - A_UINT8 srcMac[ATH_MAC_LEN]; - A_UINT16 typeOrLen; -} POSTPACK ATH_MAC_HDR; - -typedef PREPACK struct { - A_UINT8 dsap; - A_UINT8 ssap; - A_UINT8 cntl; - A_UINT8 orgCode[3]; - A_UINT16 etherType; -} POSTPACK ATH_LLC_SNAP_HDR; - -typedef enum { - DATA_MSGTYPE = 0x0, - CNTL_MSGTYPE, - SYNC_MSGTYPE -} WMI_MSG_TYPE; - - -typedef PREPACK struct { - A_INT8 rssi; - A_UINT8 info; /* WMI_MSG_TYPE in lower 2 bits - b1b0 */ - /* UP in next 3 bits - b4b3b2 */ -#define WMI_DATA_HDR_MSG_TYPE_MASK 0x03 -#define WMI_DATA_HDR_MSG_TYPE_SHIFT 0 -#define WMI_DATA_HDR_UP_MASK 0x07 -#define WMI_DATA_HDR_UP_SHIFT 2 -#define WMI_DATA_HDR_IS_MSG_TYPE(h, t) (((h)->info & (WMI_DATA_HDR_MSG_TYPE_MASK)) == (t)) -} POSTPACK WMI_DATA_HDR; - - -#define WMI_DATA_HDR_SET_MSG_TYPE(h, t) (h)->info = (((h)->info & ~(WMI_DATA_HDR_MSG_TYPE_MASK << WMI_DATA_HDR_MSG_TYPE_SHIFT)) | (t << WMI_DATA_HDR_MSG_TYPE_SHIFT)) -#define WMI_DATA_HDR_SET_UP(h, p) (h)->info = (((h)->info & ~(WMI_DATA_HDR_UP_MASK << WMI_DATA_HDR_UP_SHIFT)) | (p << WMI_DATA_HDR_UP_SHIFT)) - -/* - * Control Path - */ -typedef PREPACK struct { - A_UINT16 commandId; -} POSTPACK WMI_CMD_HDR; /* used for commands and events */ - -/* - * List of Commnands - */ -typedef enum { - WMI_CONNECT_CMDID = 0x0001, - WMI_RECONNECT_CMDID, - WMI_DISCONNECT_CMDID, - WMI_SYNCHRONIZE_CMDID, - WMI_CREATE_PSTREAM_CMDID, - WMI_DELETE_PSTREAM_CMDID, - WMI_START_SCAN_CMDID, - WMI_SET_SCAN_PARAMS_CMDID, - WMI_SET_BSS_FILTER_CMDID, - WMI_SET_PROBED_SSID_CMDID, - WMI_SET_LISTEN_INT_CMDID, - WMI_SET_BMISS_TIME_CMDID, - WMI_SET_DISC_TIMEOUT_CMDID, - WMI_GET_CHANNEL_LIST_CMDID, - WMI_SET_BEACON_INT_CMDID, - WMI_GET_STATISTICS_CMDID, - WMI_SET_CHANNEL_PARAMS_CMDID, - WMI_SET_POWER_MODE_CMDID, - WMI_SET_IBSS_PM_CAPS_CMDID, - WMI_SET_POWER_PARAMS_CMDID, - WMI_SET_POWERSAVE_TIMERS_POLICY_CMDID, - WMI_ADD_CIPHER_KEY_CMDID, - WMI_DELETE_CIPHER_KEY_CMDID, - WMI_ADD_KRK_CMDID, - WMI_DELETE_KRK_CMDID, - WMI_SET_PMKID_CMDID, - WMI_SET_TX_PWR_CMDID, - WMI_GET_TX_PWR_CMDID, - WMI_SET_ASSOC_INFO_CMDID, - WMI_ADD_BAD_AP_CMDID, - WMI_DELETE_BAD_AP_CMDID, - WMI_SET_TKIP_COUNTERMEASURES_CMDID, - WMI_RSSI_THRESHOLD_PARAMS_CMDID, - WMI_TARGET_ERROR_REPORT_BITMASK_CMDID, - WMI_SET_ACCESS_PARAMS_CMDID, - WMI_SET_RETRY_LIMITS_CMDID, - WMI_SET_OPT_MODE_CMDID, - WMI_OPT_TX_FRAME_CMDID, - WMI_SET_VOICE_PKT_SIZE_CMDID, - WMI_SET_MAX_SP_LEN_CMDID, - WMI_SET_ROAM_CTRL_CMDID, - WMI_GET_ROAM_TBL_CMDID, - WMI_GET_ROAM_DATA_CMDID, - WMI_ENABLE_RM_CMDID, - WMI_SET_MAX_OFFHOME_DURATION_CMDID, - WMI_EXTENSION_CMDID, /* Non-wireless extensions */ - WMI_SNR_THRESHOLD_PARAMS_CMDID, - WMI_LQ_THRESHOLD_PARAMS_CMDID, - WMI_SET_LPREAMBLE_CMDID, - WMI_SET_RTS_CMDID, - WMI_CLR_RSSI_SNR_CMDID, - WMI_SET_FIXRATES_CMDID, - WMI_GET_FIXRATES_CMDID, - WMI_SET_AUTH_MODE_CMDID, - WMI_SET_REASSOC_MODE_CMDID, - WMI_SET_WMM_CMDID, - WMI_SET_WMM_TXOP_CMDID, - WMI_TEST_CMDID, - WMI_SET_BT_STATUS_CMDID, - WMI_SET_BT_PARAMS_CMDID, - - WMI_SET_KEEPALIVE_CMDID, - WMI_GET_KEEPALIVE_CMDID, - WMI_SET_APPIE_CMDID, - WMI_GET_APPIE_CMDID, - WMI_SET_WSC_STATUS_CMDID, - - /* Wake on Wireless */ - WMI_SET_HOST_SLEEP_MODE_CMDID, - WMI_SET_WOW_MODE_CMDID, - WMI_GET_WOW_LIST_CMDID, - WMI_ADD_WOW_PATTERN_CMDID, - WMI_DEL_WOW_PATTERN_CMDID, - WMI_SET_MAC_ADDRESS_CMDID, - WMI_SET_AKMP_PARAMS_CMDID, - WMI_SET_PMKID_LIST_CMDID, - WMI_GET_PMKID_LIST_CMDID, - - /* - * Developer commands starts at 0xF000 - */ - WMI_SET_BITRATE_CMDID = 0xF000, - WMI_GET_BITRATE_CMDID, - WMI_SET_WHALPARAM_CMDID, - -} WMI_COMMAND_ID; - -/* - * Frame Types - */ -typedef enum { - WMI_FRAME_BEACON = 0, - WMI_FRAME_PROBE_REQ, - WMI_FRAME_PROBE_RESP, - WMI_FRAME_ASSOC_REQ, - WMI_FRAME_ASSOC_RESP, - WMI_NUM_MGMT_FRAME -} WMI_MGMT_FRAME_TYPE; - -/* - * Connect Command - */ -typedef enum { - INFRA_NETWORK = 0x01, - ADHOC_NETWORK = 0x02, - ADHOC_CREATOR = 0x04, -} NETWORK_TYPE; - -typedef enum { - OPEN_AUTH = 0x01, - SHARED_AUTH = 0x02, - LEAP_AUTH = 0x04, /* different from IEEE_AUTH_MODE definitions */ -} DOT11_AUTH_MODE; - -typedef enum { - NONE_AUTH = 0x01, - WPA_AUTH = 0x02, - WPA_PSK_AUTH = 0x03, - WPA2_AUTH = 0x04, - WPA2_PSK_AUTH = 0x05, - WPA_AUTH_CCKM = 0x06, - WPA2_AUTH_CCKM = 0x07, -} AUTH_MODE; - -typedef enum { - NONE_CRYPT = 0x01, - WEP_CRYPT = 0x02, - TKIP_CRYPT = 0x03, - AES_CRYPT = 0x04, -} CRYPTO_TYPE; - -#define WMI_MIN_CRYPTO_TYPE NONE_CRYPT -#define WMI_MAX_CRYPTO_TYPE (AES_CRYPT + 1) - -#define WMI_MIN_KEY_INDEX 0 -#define WMI_MAX_KEY_INDEX 3 - -#define WMI_MAX_KEY_LEN 32 - -#define WMI_MAX_SSID_LEN 32 - -typedef enum { - CONNECT_ASSOC_POLICY_USER = 0x0001, - CONNECT_SEND_REASSOC = 0x0002, - CONNECT_IGNORE_WPAx_GROUP_CIPHER = 0x0004, - CONNECT_PROFILE_MATCH_DONE = 0x0008, - CONNECT_IGNORE_AAC_BEACON = 0x0010, - CONNECT_CSA_FOLLOW_BSS = 0x0020, -} WMI_CONNECT_CTRL_FLAGS_BITS; - -#define DEFAULT_CONNECT_CTRL_FLAGS (CONNECT_CSA_FOLLOW_BSS) - -typedef PREPACK struct { - A_UINT8 networkType; - A_UINT8 dot11AuthMode; - A_UINT8 authMode; - A_UINT8 pairwiseCryptoType; - A_UINT8 pairwiseCryptoLen; - A_UINT8 groupCryptoType; - A_UINT8 groupCryptoLen; - A_UINT8 ssidLength; - A_UCHAR ssid[WMI_MAX_SSID_LEN]; - A_UINT16 channel; - A_UINT8 bssid[ATH_MAC_LEN]; - A_UINT32 ctrl_flags; -} POSTPACK WMI_CONNECT_CMD; - -/* - * WMI_RECONNECT_CMDID - */ -typedef PREPACK struct { - A_UINT16 channel; /* hint */ - A_UINT8 bssid[ATH_MAC_LEN]; /* mandatory if set */ -} POSTPACK WMI_RECONNECT_CMD; - -/* - * WMI_ADD_CIPHER_KEY_CMDID - */ -typedef enum { - PAIRWISE_USAGE = 0x00, - GROUP_USAGE = 0x01, - TX_USAGE = 0x02, /* default Tx Key - Static WEP only */ -} KEY_USAGE; - -/* - * Bit Flag - * Bit 0 - Initialise TSC - default is Initialize - */ -#define KEY_OP_INIT_TSC 0x01 -#define KEY_OP_INIT_RSC 0x02 - -#define KEY_OP_INIT_VAL 0x03 /* Default Initialise the TSC & RSC */ -#define KEY_OP_VALID_MASK 0x03 - -typedef PREPACK struct { - A_UINT8 keyIndex; - A_UINT8 keyType; - A_UINT8 keyUsage; /* KEY_USAGE */ - A_UINT8 keyLength; - A_UINT8 keyRSC[8]; /* key replay sequence counter */ - A_UINT8 key[WMI_MAX_KEY_LEN]; - A_UINT8 key_op_ctrl; /* Additional Key Control information */ -} POSTPACK WMI_ADD_CIPHER_KEY_CMD; - -/* - * WMI_DELETE_CIPHER_KEY_CMDID - */ -typedef PREPACK struct { - A_UINT8 keyIndex; -} POSTPACK WMI_DELETE_CIPHER_KEY_CMD; - -#define WMI_KRK_LEN 16 -/* - * WMI_ADD_KRK_CMDID - */ -typedef PREPACK struct { - A_UINT8 krk[WMI_KRK_LEN]; -} POSTPACK WMI_ADD_KRK_CMD; - -/* - * WMI_SET_TKIP_COUNTERMEASURES_CMDID - */ -typedef enum { - WMI_TKIP_CM_DISABLE = 0x0, - WMI_TKIP_CM_ENABLE = 0x1, -} WMI_TKIP_CM_CONTROL; - -typedef PREPACK struct { - A_UINT8 cm_en; /* WMI_TKIP_CM_CONTROL */ -} POSTPACK WMI_SET_TKIP_COUNTERMEASURES_CMD; - -/* - * WMI_SET_PMKID_CMDID - */ - -#define WMI_PMKID_LEN 16 - -typedef enum { - PMKID_DISABLE = 0, - PMKID_ENABLE = 1, -} PMKID_ENABLE_FLG; - -typedef PREPACK struct { - A_UINT8 bssid[ATH_MAC_LEN]; - A_UINT8 enable; /* PMKID_ENABLE_FLG */ - A_UINT8 pmkid[WMI_PMKID_LEN]; -} POSTPACK WMI_SET_PMKID_CMD; - -/* - * WMI_START_SCAN_CMD - */ -typedef enum { - WMI_LONG_SCAN = 0, - WMI_SHORT_SCAN = 1, -} WMI_SCAN_TYPE; - -typedef PREPACK struct { - A_BOOL forceFgScan; - A_BOOL isLegacy; /* For Legacy Cisco AP compatibility */ - A_UINT32 homeDwellTime; /* Maximum duration in the home channel(milliseconds) */ - A_UINT32 forceScanInterval; /* Time interval between scans (milliseconds)*/ - A_UINT8 scanType; /* WMI_SCAN_TYPE */ -} POSTPACK WMI_START_SCAN_CMD; - -/* - * WMI_SET_SCAN_PARAMS_CMDID - */ -#define WMI_SHORTSCANRATIO_DEFAULT 3 -typedef enum { - CONNECT_SCAN_CTRL_FLAGS = 0x01, /* set if can scan in the Connect cmd */ - SCAN_CONNECTED_CTRL_FLAGS = 0x02, /* set if scan for the SSID it is */ - /* already connected to */ - ACTIVE_SCAN_CTRL_FLAGS = 0x04, /* set if enable active scan */ - ROAM_SCAN_CTRL_FLAGS = 0x08, /* set if enable roam scan when bmiss and lowrssi */ - REPORT_BSSINFO_CTRL_FLAGS = 0x10, /* set if follows customer BSSINFO reporting rule */ - ENABLE_AUTO_CTRL_FLAGS = 0x20, /* if disabled, target doesn't - scan after a disconnect event */ - ENABLE_SCAN_ABORT_EVENT = 0x40 /* Scan complete event with canceled status will be generated when a scan is prempted before it gets completed */ - -} WMI_SCAN_CTRL_FLAGS_BITS; - -#define CAN_SCAN_IN_CONNECT(flags) (flags & CONNECT_SCAN_CTRL_FLAGS) -#define CAN_SCAN_CONNECTED(flags) (flags & SCAN_CONNECTED_CTRL_FLAGS) -#define ENABLE_ACTIVE_SCAN(flags) (flags & ACTIVE_SCAN_CTRL_FLAGS) -#define ENABLE_ROAM_SCAN(flags) (flags & ROAM_SCAN_CTRL_FLAGS) -#define CONFIG_REPORT_BSSINFO(flags) (flags & REPORT_BSSINFO_CTRL_FLAGS) -#define IS_AUTO_SCAN_ENABLED(flags) (flags & ENABLE_AUTO_CTRL_FLAGS) -#define SCAN_ABORT_EVENT_ENABLED(flags) (flags & ENABLE_SCAN_ABORT_EVENT) - -#define DEFAULT_SCAN_CTRL_FLAGS (CONNECT_SCAN_CTRL_FLAGS| SCAN_CONNECTED_CTRL_FLAGS| ACTIVE_SCAN_CTRL_FLAGS| ROAM_SCAN_CTRL_FLAGS | ENABLE_AUTO_CTRL_FLAGS) - - -typedef PREPACK struct { - A_UINT16 fg_start_period; /* seconds */ - A_UINT16 fg_end_period; /* seconds */ - A_UINT16 bg_period; /* seconds */ - A_UINT16 maxact_chdwell_time; /* msec */ - A_UINT16 pas_chdwell_time; /* msec */ - A_UINT8 shortScanRatio; /* how many shorts scan for one long */ - A_UINT8 scanCtrlFlags; - A_UINT16 minact_chdwell_time; /* msec */ - A_UINT32 max_dfsch_act_time; /* msecs */ -} POSTPACK WMI_SCAN_PARAMS_CMD; - -/* - * WMI_SET_BSS_FILTER_CMDID - */ -typedef enum { - NONE_BSS_FILTER = 0x0, /* no beacons forwarded */ - ALL_BSS_FILTER, /* all beacons forwarded */ - PROFILE_FILTER, /* only beacons matching profile */ - ALL_BUT_PROFILE_FILTER, /* all but beacons matching profile */ - CURRENT_BSS_FILTER, /* only beacons matching current BSS */ - ALL_BUT_BSS_FILTER, /* all but beacons matching BSS */ - PROBED_SSID_FILTER, /* beacons matching probed ssid */ - LAST_BSS_FILTER, /* marker only */ -} WMI_BSS_FILTER; - -typedef PREPACK struct { - A_UINT8 bssFilter; /* see WMI_BSS_FILTER */ - A_UINT32 ieMask; -} POSTPACK WMI_BSS_FILTER_CMD; - -/* - * WMI_SET_PROBED_SSID_CMDID - */ -#define MAX_PROBED_SSID_INDEX 5 - -typedef enum { - DISABLE_SSID_FLAG = 0, /* disables entry */ - SPECIFIC_SSID_FLAG = 0x01, /* probes specified ssid */ - ANY_SSID_FLAG = 0x02, /* probes for any ssid */ -} WMI_SSID_FLAG; - -typedef PREPACK struct { - A_UINT8 entryIndex; /* 0 to MAX_PROBED_SSID_INDEX */ - A_UINT8 flag; /* WMI_SSID_FLG */ - A_UINT8 ssidLength; - A_UINT8 ssid[32]; -} POSTPACK WMI_PROBED_SSID_CMD; - -/* - * WMI_SET_LISTEN_INT_CMDID - * The Listen interval is between 15 and 3000 TUs - */ -#define MIN_LISTEN_INTERVAL 15 -#define MAX_LISTEN_INTERVAL 5000 -#define MIN_LISTEN_BEACONS 1 -#define MAX_LISTEN_BEACONS 50 - -typedef PREPACK struct { - A_UINT16 listenInterval; - A_UINT16 numBeacons; -} POSTPACK WMI_LISTEN_INT_CMD; - -/* - * WMI_SET_BEACON_INT_CMDID - */ -typedef PREPACK struct { - A_UINT16 beaconInterval; -} POSTPACK WMI_BEACON_INT_CMD; - -/* - * WMI_SET_BMISS_TIME_CMDID - * valid values are between 1000 and 5000 TUs - */ - -#define MIN_BMISS_TIME 1000 -#define MAX_BMISS_TIME 5000 -#define MIN_BMISS_BEACONS 1 -#define MAX_BMISS_BEACONS 50 - -typedef PREPACK struct { - A_UINT16 bmissTime; - A_UINT16 numBeacons; -} POSTPACK WMI_BMISS_TIME_CMD; - -/* - * WMI_SET_POWER_MODE_CMDID - */ -typedef enum { - REC_POWER = 0x01, - MAX_PERF_POWER, -} WMI_POWER_MODE; - -typedef PREPACK struct { - A_UINT8 powerMode; /* WMI_POWER_MODE */ -} POSTPACK WMI_POWER_MODE_CMD; - -/* - * WMI_SET_POWER_PARAMS_CMDID - */ -typedef enum { - IGNORE_DTIM = 0x01, - NORMAL_DTIM = 0x02, - STICK_DTIM = 0x03, -} WMI_DTIM_POLICY; - -typedef PREPACK struct { - A_UINT16 idle_period; /* msec */ - A_UINT16 pspoll_number; - A_UINT16 dtim_policy; -} POSTPACK WMI_POWER_PARAMS_CMD; - -typedef PREPACK struct { - A_UINT8 power_saving; - A_UINT8 ttl; /* number of beacon periods */ - A_UINT16 atim_windows; /* msec */ - A_UINT16 timeout_value; /* msec */ -} POSTPACK WMI_IBSS_PM_CAPS_CMD; - -/* - * WMI_SET_POWERSAVE_TIMERS_POLICY_CMDID - */ -typedef enum { - IGNORE_TIM_ALL_QUEUES_APSD = 0, - PROCESS_TIM_ALL_QUEUES_APSD = 1, - IGNORE_TIM_SIMULATED_APSD = 2, - PROCESS_TIM_SIMULATED_APSD = 3, -} APSD_TIM_POLICY; - -typedef PREPACK struct { - A_UINT16 psPollTimeout; /* msec */ - A_UINT16 triggerTimeout; /* msec */ - A_UINT32 apsdTimPolicy; /* TIM behavior with ques APSD enabled. Default is IGNORE_TIM_ALL_QUEUES_APSD */ - A_UINT32 simulatedAPSDTimPolicy; /* TIM behavior with simulated APSD enabled. Default is PROCESS_TIM_SIMULATED_APSD */ -} POSTPACK WMI_POWERSAVE_TIMERS_POLICY_CMD; - -/* - * WMI_SET_VOICE_PKT_SIZE_CMDID - */ -typedef PREPACK struct { - A_UINT16 voicePktSize; -} POSTPACK WMI_SET_VOICE_PKT_SIZE_CMD; - -/* - * WMI_SET_MAX_SP_LEN_CMDID - */ -typedef enum { - DELIVER_ALL_PKT = 0x0, - DELIVER_2_PKT = 0x1, - DELIVER_4_PKT = 0x2, - DELIVER_6_PKT = 0x3, -} APSD_SP_LEN_TYPE; - -typedef PREPACK struct { - A_UINT8 maxSPLen; -} POSTPACK WMI_SET_MAX_SP_LEN_CMD; - -/* - * WMI_SET_DISC_TIMEOUT_CMDID - */ -typedef PREPACK struct { - A_UINT8 disconnectTimeout; /* seconds */ -} POSTPACK WMI_DISC_TIMEOUT_CMD; - -typedef enum { - UPLINK_TRAFFIC = 0, - DNLINK_TRAFFIC = 1, - BIDIR_TRAFFIC = 2, -} DIR_TYPE; - -typedef enum { - DISABLE_FOR_THIS_AC = 0, - ENABLE_FOR_THIS_AC = 1, - ENABLE_FOR_ALL_AC = 2, -} VOICEPS_CAP_TYPE; - -typedef enum { - TRAFFIC_TYPE_APERIODIC = 0, - TRAFFIC_TYPE_PERIODIC = 1, -}TRAFFIC_TYPE; - -/* - * WMI_CREATE_PSTREAM_CMDID - */ -typedef PREPACK struct { - A_UINT32 minServiceInt; /* in milli-sec */ - A_UINT32 maxServiceInt; /* in milli-sec */ - A_UINT32 inactivityInt; /* in milli-sec */ - A_UINT32 suspensionInt; /* in milli-sec */ - A_UINT32 serviceStartTime; - A_UINT32 minDataRate; /* in bps */ - A_UINT32 meanDataRate; /* in bps */ - A_UINT32 peakDataRate; /* in bps */ - A_UINT32 maxBurstSize; - A_UINT32 delayBound; - A_UINT32 minPhyRate; /* in bps */ - A_UINT32 sba; - A_UINT32 mediumTime; - A_UINT16 nominalMSDU; /* in octects */ - A_UINT16 maxMSDU; /* in octects */ - A_UINT8 trafficClass; - A_UINT8 trafficType; /* TRAFFIC_TYPE */ - A_UINT8 trafficDirection; /* TRAFFIC_DIR */ - A_UINT8 voicePSCapability; /* VOICEPS_CAP_TYPE */ - A_UINT8 tsid; - A_UINT8 userPriority; /* 802.1D user priority */ -} POSTPACK WMI_CREATE_PSTREAM_CMD; - -/* - * WMI_DELETE_PSTREAM_CMDID - */ -typedef PREPACK struct { - A_UINT8 trafficClass; - A_UINT8 tsid; -} POSTPACK WMI_DELETE_PSTREAM_CMD; - -/* - * WMI_SET_CHANNEL_PARAMS_CMDID - */ -typedef enum { - WMI_11A_MODE = 0x1, - WMI_11G_MODE = 0x2, - WMI_11AG_MODE = 0x3, - WMI_11B_MODE = 0x4, - WMI_11GONLY_MODE = 0x5, -} WMI_PHY_MODE; - -#define WMI_MAX_CHANNELS 32 - -typedef PREPACK struct { - A_UINT8 reserved1; - A_UINT8 scanParam; /* set if enable scan */ - A_UINT8 phyMode; /* see WMI_PHY_MODE */ - A_UINT8 numChannels; /* how many channels follow */ - A_UINT16 channelList[1]; /* channels in Mhz */ -} POSTPACK WMI_CHANNEL_PARAMS_CMD; - - -/* - * WMI_RSSI_THRESHOLD_PARAMS_CMDID - * Setting the polltime to 0 would disable polling. - * Threshold values are in the ascending order, and should agree to: - * (lowThreshold_lowerVal < lowThreshold_upperVal < highThreshold_lowerVal - * < highThreshold_upperVal) - */ - -typedef PREPACK struct WMI_RSSI_THRESHOLD_PARAMS{ - A_UINT32 pollTime; /* Polling time as a factor of LI */ - A_INT16 thresholdAbove1_Val; /* lowest of upper */ - A_INT16 thresholdAbove2_Val; - A_INT16 thresholdAbove3_Val; - A_INT16 thresholdAbove4_Val; - A_INT16 thresholdAbove5_Val; - A_INT16 thresholdAbove6_Val; /* highest of upper */ - A_INT16 thresholdBelow1_Val; /* lowest of bellow */ - A_INT16 thresholdBelow2_Val; - A_INT16 thresholdBelow3_Val; - A_INT16 thresholdBelow4_Val; - A_INT16 thresholdBelow5_Val; - A_INT16 thresholdBelow6_Val; /* highest of bellow */ - A_UINT8 weight; /* "alpha" */ - A_UINT8 reserved[3]; -} POSTPACK WMI_RSSI_THRESHOLD_PARAMS_CMD; - -/* - * WMI_SNR_THRESHOLD_PARAMS_CMDID - * Setting the polltime to 0 would disable polling. - */ - -typedef PREPACK struct WMI_SNR_THRESHOLD_PARAMS{ - A_UINT32 pollTime; /* Polling time as a factor of LI */ - A_UINT8 weight; /* "alpha" */ - A_UINT8 thresholdAbove1_Val; /* lowest of uppper*/ - A_UINT8 thresholdAbove2_Val; - A_UINT8 thresholdAbove3_Val; - A_UINT8 thresholdAbove4_Val; /* highest of upper */ - A_UINT8 thresholdBelow1_Val; /* lowest of bellow */ - A_UINT8 thresholdBelow2_Val; - A_UINT8 thresholdBelow3_Val; - A_UINT8 thresholdBelow4_Val; /* highest of bellow */ - A_UINT8 reserved[3]; -} POSTPACK WMI_SNR_THRESHOLD_PARAMS_CMD; - -/* - * WMI_LQ_THRESHOLD_PARAMS_CMDID - */ -typedef PREPACK struct WMI_LQ_THRESHOLD_PARAMS { - A_UINT8 enable; - A_UINT8 thresholdAbove1_Val; - A_UINT8 thresholdAbove2_Val; - A_UINT8 thresholdAbove3_Val; - A_UINT8 thresholdAbove4_Val; - A_UINT8 thresholdBelow1_Val; - A_UINT8 thresholdBelow2_Val; - A_UINT8 thresholdBelow3_Val; - A_UINT8 thresholdBelow4_Val; - A_UINT8 reserved[3]; -} POSTPACK WMI_LQ_THRESHOLD_PARAMS_CMD; - -typedef enum { - WMI_LPREAMBLE_DISABLED = 0, - WMI_LPREAMBLE_ENABLED -} WMI_LPREAMBLE_STATUS; - -typedef PREPACK struct { - A_UINT8 status; -}POSTPACK WMI_SET_LPREAMBLE_CMD; - -typedef PREPACK struct { - A_UINT16 threshold; -}POSTPACK WMI_SET_RTS_CMD; - -/* - * WMI_TARGET_ERROR_REPORT_BITMASK_CMDID - * Sets the error reporting event bitmask in target. Target clears it - * upon an error. Subsequent errors are counted, but not reported - * via event, unless the bitmask is set again. - */ -typedef PREPACK struct { - A_UINT32 bitmask; -} POSTPACK WMI_TARGET_ERROR_REPORT_BITMASK; - -/* - * WMI_SET_TX_PWR_CMDID - */ -typedef PREPACK struct { - A_UINT8 dbM; /* in dbM units */ -} POSTPACK WMI_SET_TX_PWR_CMD, WMI_TX_PWR_REPLY; - -/* - * WMI_SET_ASSOC_INFO_CMDID - * - * A maximum of 2 private IEs can be sent in the [Re]Assoc request. - * A 3rd one, the CCX version IE can also be set from the host. - */ -#define WMI_MAX_ASSOC_INFO_TYPE 2 -#define WMI_CCX_VER_IE 2 /* ieType to set CCX Version IE */ - -#define WMI_MAX_ASSOC_INFO_LEN 240 - -typedef PREPACK struct { - A_UINT8 ieType; - A_UINT8 bufferSize; - A_UINT8 assocInfo[1]; /* up to WMI_MAX_ASSOC_INFO_LEN */ -} POSTPACK WMI_SET_ASSOC_INFO_CMD; - - -/* - * WMI_GET_TX_PWR_CMDID does not take any parameters - */ - -/* - * WMI_ADD_BAD_AP_CMDID - */ -#define WMI_MAX_BAD_AP_INDEX 1 - -typedef PREPACK struct { - A_UINT8 badApIndex; /* 0 to WMI_MAX_BAD_AP_INDEX */ - A_UINT8 bssid[ATH_MAC_LEN]; -} POSTPACK WMI_ADD_BAD_AP_CMD; - -/* - * WMI_DELETE_BAD_AP_CMDID - */ -typedef PREPACK struct { - A_UINT8 badApIndex; /* 0 to WMI_MAX_BAD_AP_INDEX */ -} POSTPACK WMI_DELETE_BAD_AP_CMD; - -/* - * WMI_SET_ACCESS_PARAMS_CMDID - */ -#define WMI_DEFAULT_TXOP_ACPARAM 0 /* implies one MSDU */ -#define WMI_DEFAULT_ECWMIN_ACPARAM 4 /* corresponds to CWmin of 15 */ -#define WMI_DEFAULT_ECWMAX_ACPARAM 10 /* corresponds to CWmax of 1023 */ -#define WMI_MAX_CW_ACPARAM 15 /* maximum eCWmin or eCWmax */ -#define WMI_DEFAULT_AIFSN_ACPARAM 2 -#define WMI_MAX_AIFSN_ACPARAM 15 -typedef PREPACK struct { - A_UINT16 txop; /* in units of 32 usec */ - A_UINT8 eCWmin; - A_UINT8 eCWmax; - A_UINT8 aifsn; -} POSTPACK WMI_SET_ACCESS_PARAMS_CMD; - - -/* - * WMI_SET_RETRY_LIMITS_CMDID - * - * This command is used to customize the number of retries the - * wlan device will perform on a given frame. - */ -#define WMI_MIN_RETRIES 2 -#define WMI_MAX_RETRIES 13 -typedef enum { - MGMT_FRAMETYPE = 0, - CONTROL_FRAMETYPE = 1, - DATA_FRAMETYPE = 2 -} WMI_FRAMETYPE; - -typedef PREPACK struct { - A_UINT8 frameType; /* WMI_FRAMETYPE */ - A_UINT8 trafficClass; /* applies only to DATA_FRAMETYPE */ - A_UINT8 maxRetries; - A_UINT8 enableNotify; -} POSTPACK WMI_SET_RETRY_LIMITS_CMD; - -/* - * WMI_SET_ROAM_CTRL_CMDID - * - * This command is used to influence the Roaming behaviour - * Set the host biases of the BSSs before setting the roam mode as bias - * based. - */ - -/* - * Different types of Roam Control - */ - -typedef enum { - WMI_FORCE_ROAM = 1, /* Roam to the specified BSSID */ - WMI_SET_ROAM_MODE = 2, /* default ,progd bias, no roam */ - WMI_SET_HOST_BIAS = 3, /* Set the Host Bias */ - WMI_SET_LOWRSSI_SCAN_PARAMS = 4, /* Set lowrssi Scan parameters */ -} WMI_ROAM_CTRL_TYPE; - -#define WMI_MIN_ROAM_CTRL_TYPE WMI_FORCE_ROAM -#define WMI_MAX_ROAM_CTRL_TYPE WMI_SET_LOWRSSI_SCAN_PARAMS - -/* - * ROAM MODES - */ - -typedef enum { - WMI_DEFAULT_ROAM_MODE = 1, /* RSSI based ROAM */ - WMI_HOST_BIAS_ROAM_MODE = 2, /* HOST BIAS based ROAM */ - WMI_LOCK_BSS_MODE = 3 /* Lock to the Current BSS - no Roam */ -} WMI_ROAM_MODE; - -/* - * BSS HOST BIAS INFO - */ - -typedef PREPACK struct { - A_UINT8 bssid[ATH_MAC_LEN]; - A_INT8 bias; -} POSTPACK WMI_BSS_BIAS; - -typedef PREPACK struct { - A_UINT8 numBss; - WMI_BSS_BIAS bssBias[1]; -} POSTPACK WMI_BSS_BIAS_INFO; - -typedef PREPACK struct WMI_LOWRSSI_SCAN_PARAMS { - A_UINT16 lowrssi_scan_period; - A_INT16 lowrssi_scan_threshold; - A_INT16 lowrssi_roam_threshold; - A_UINT8 roam_rssi_floor; - A_UINT8 reserved[1]; /* For alignment */ -} POSTPACK WMI_LOWRSSI_SCAN_PARAMS; - -typedef PREPACK struct { - PREPACK union { - A_UINT8 bssid[ATH_MAC_LEN]; /* WMI_FORCE_ROAM */ - A_UINT8 roamMode; /* WMI_SET_ROAM_MODE */ - WMI_BSS_BIAS_INFO bssBiasInfo; /* WMI_SET_HOST_BIAS */ - WMI_LOWRSSI_SCAN_PARAMS lrScanParams; - } POSTPACK info; - A_UINT8 roamCtrlType ; -} POSTPACK WMI_SET_ROAM_CTRL_CMD; - -/* - * WMI_ENABLE_RM_CMDID - */ -typedef PREPACK struct { - A_BOOL enable_radio_measurements; -} POSTPACK WMI_ENABLE_RM_CMD; - -/* - * WMI_SET_MAX_OFFHOME_DURATION_CMDID - */ -typedef PREPACK struct { - A_UINT8 max_offhome_duration; -} POSTPACK WMI_SET_MAX_OFFHOME_DURATION_CMD; - -typedef PREPACK struct { - A_UINT32 frequency; - A_UINT8 threshold; -} POSTPACK WMI_SET_HB_CHALLENGE_RESP_PARAMS_CMD; - -typedef enum { - BT_STREAM_UNDEF = 0, - BT_STREAM_SCO, /* SCO stream */ - BT_STREAM_A2DP, /* A2DP stream */ - BT_STREAM_MAX -} BT_STREAM_TYPE; - -typedef enum { - BT_PARAM_SCO = 1, /* SCO stream parameters */ - BT_PARAM_A2DP, /* A2DP stream parameters */ - BT_PARAM_MISC, /* miscellaneous parameters */ - BT_PARAM_REGS, /* co-existence register parameters */ - BT_PARAM_MAX -} BT_PARAM_TYPE; - -typedef enum { - BT_STATUS_UNDEF = 0, - BT_STATUS_START, - BT_STATUS_STOP, - BT_STATUS_RESUME, - BT_STATUS_SUSPEND, - BT_STATUS_MAX -} BT_STREAM_STATUS; - -typedef PREPACK struct { - A_UINT8 streamType; - A_UINT8 status; -} POSTPACK WMI_SET_BT_STATUS_CMD; - -typedef PREPACK struct { - A_UINT8 noSCOPkts; - A_UINT8 pspollTimeout; - A_UINT8 stompbt; -} POSTPACK BT_PARAMS_SCO; - -typedef PREPACK struct { - A_UINT32 period; - A_UINT32 dutycycle; - A_UINT8 stompbt; -} POSTPACK BT_PARAMS_A2DP; - -typedef PREPACK struct { - A_UINT32 mode; - A_UINT32 scoWghts; - A_UINT32 a2dpWghts; - A_UINT32 genWghts; - A_UINT32 mode2; - A_UINT8 setVal; -} POSTPACK BT_COEX_REGS; - -typedef enum { - WLAN_PROTECT_POLICY = 1, - WLAN_COEX_CTRL_FLAGS -} BT_PARAMS_MISC_TYPE; - -typedef enum { - WLAN_PROTECT_PER_STREAM = 0x01, /* default */ - WLAN_PROTECT_ANY_TX = 0x02 -} WLAN_PROTECT_FLAGS; - - -#define WLAN_DISABLE_COEX_IN_DISCONNECT 0x01 /* default */ -#define WLAN_KEEP_COEX_IN_DISCONNECT 0x02 -#define WLAN_STOMPBT_IN_DISCONNECT 0x04 - -#define WLAN_DISABLE_COEX_IN_ROAM 0x10 /* default */ -#define WLAN_KEEP_COEX_IN_ROAM 0x20 -#define WLAN_STOMPBT_IN_ROAM 0x40 - -#define WLAN_DISABLE_COEX_IN_SCAN 0x100 /* default */ -#define WLAN_KEEP_COEX_IN_SCAN 0x200 -#define WLAN_STOMPBT_IN_SCAN 0x400 - -#define WLAN_DISABLE_COEX_BT_OFF 0x1000 /* default */ -#define WLAN_KEEP_COEX_BT_OFF 0x2000 -#define WLAN_STOMPBT_BT_OFF 0x4000 - -typedef PREPACK struct { - A_UINT32 period; - A_UINT32 dutycycle; - A_UINT8 stompbt; - A_UINT8 policy; -} POSTPACK WLAN_PROTECT_POLICY_TYPE; - -typedef PREPACK struct { - PREPACK union { - WLAN_PROTECT_POLICY_TYPE protectParams; - A_UINT16 wlanCtrlFlags; - } POSTPACK info; - A_UINT8 paramType; -} POSTPACK BT_PARAMS_MISC; - -typedef PREPACK struct { - PREPACK union { - BT_PARAMS_SCO scoParams; - BT_PARAMS_A2DP a2dpParams; - BT_PARAMS_MISC miscParams; - BT_COEX_REGS regs; - } POSTPACK info; - A_UINT8 paramType; -} POSTPACK WMI_SET_BT_PARAMS_CMD; - -/* - * Command Replies - */ - -/* - * WMI_GET_CHANNEL_LIST_CMDID reply - */ -typedef PREPACK struct { - A_UINT8 reserved1; - A_UINT8 numChannels; /* number of channels in reply */ - A_UINT16 channelList[1]; /* channel in Mhz */ -} POSTPACK WMI_CHANNEL_LIST_REPLY; - -typedef enum { - A_SUCCEEDED = A_OK, - A_FAILED_DELETE_STREAM_DOESNOT_EXIST=250, - A_SUCCEEDED_MODIFY_STREAM=251, - A_FAILED_INVALID_STREAM = 252, - A_FAILED_MAX_THINSTREAMS = 253, - A_FAILED_CREATE_REMOVE_PSTREAM_FIRST = 254, -} PSTREAM_REPLY_STATUS; - -/* - * List of Events (target to host) - */ -typedef enum { - WMI_READY_EVENTID = 0x1001, - WMI_CONNECT_EVENTID, - WMI_DISCONNECT_EVENTID, - WMI_BSSINFO_EVENTID, - WMI_CMDERROR_EVENTID, - WMI_REGDOMAIN_EVENTID, - WMI_PSTREAM_TIMEOUT_EVENTID, - WMI_NEIGHBOR_REPORT_EVENTID, - WMI_TKIP_MICERR_EVENTID, - WMI_SCAN_COMPLETE_EVENTID, - WMI_REPORT_STATISTICS_EVENTID, - WMI_RSSI_THRESHOLD_EVENTID, - WMI_ERROR_REPORT_EVENTID, - WMI_OPT_RX_FRAME_EVENTID, - WMI_REPORT_ROAM_TBL_EVENTID, - WMI_EXTENSION_EVENTID, - WMI_CAC_EVENTID, - WMI_SNR_THRESHOLD_EVENTID, - WMI_LQ_THRESHOLD_EVENTID, - WMI_TX_RETRY_ERR_EVENTID, - WMI_REPORT_ROAM_DATA_EVENTID, - WMI_TEST_EVENTID, - WMI_APLIST_EVENTID, - WMI_GET_WOW_LIST_EVENTID, - WMI_GET_PMKID_LIST_EVENTID -} WMI_EVENT_ID; - -typedef enum { - WMI_11A_CAPABILITY = 1, - WMI_11G_CAPABILITY = 2, - WMI_11AG_CAPABILITY = 3, -} WMI_PHY_CAPABILITY; - -typedef PREPACK struct { - A_UINT8 macaddr[ATH_MAC_LEN]; - A_UINT8 phyCapability; /* WMI_PHY_CAPABILITY */ -} POSTPACK WMI_READY_EVENT; - -/* - * Connect Event - */ -typedef PREPACK struct { - A_UINT16 channel; - A_UINT8 bssid[ATH_MAC_LEN]; - A_UINT16 listenInterval; - A_UINT16 beaconInterval; - A_UINT32 networkType; - A_UINT8 beaconIeLen; - A_UINT8 assocReqLen; - A_UINT8 assocRespLen; - A_UINT8 assocInfo[1]; -} POSTPACK WMI_CONNECT_EVENT; - -/* - * Disconnect Event - */ -typedef enum { - NO_NETWORK_AVAIL = 0x01, - LOST_LINK = 0x02, /* bmiss */ - DISCONNECT_CMD = 0x03, - BSS_DISCONNECTED = 0x04, - AUTH_FAILED = 0x05, - ASSOC_FAILED = 0x06, - NO_RESOURCES_AVAIL = 0x07, - CSERV_DISCONNECT = 0x08, - INVALID_PROFILE = 0x0a, - DOT11H_CHANNEL_SWITCH = 0x0b, -} WMI_DISCONNECT_REASON; - -typedef PREPACK struct { - A_UINT16 protocolReasonStatus; /* reason code, see 802.11 spec. */ - A_UINT8 bssid[ATH_MAC_LEN]; /* set if known */ - A_UINT8 disconnectReason ; /* see WMI_DISCONNECT_REASON */ - A_UINT8 assocRespLen; - A_UINT8 assocInfo[1]; -} POSTPACK WMI_DISCONNECT_EVENT; - -/* - * BSS Info Event. - * Mechanism used to inform host of the presence and characteristic of - * wireless networks present. Consists of bss info header followed by - * the beacon or probe-response frame body. The 802.11 header is not included. - */ -typedef enum { - BEACON_FTYPE = 0x1, - PROBERESP_FTYPE, - ACTION_MGMT_FTYPE, -} WMI_BI_FTYPE; - -enum { - BSS_ELEMID_CHANSWITCH = 0x01, - BSS_ELEMID_ATHEROS = 0x02, -}; - -typedef PREPACK struct { - A_UINT16 channel; - A_UINT8 frameType; /* see WMI_BI_FTYPE */ - A_UINT8 snr; - A_INT16 rssi; - A_UINT8 bssid[ATH_MAC_LEN]; - A_UINT32 ieMask; -} POSTPACK WMI_BSS_INFO_HDR; - -/* - * Command Error Event - */ -typedef enum { - INVALID_PARAM = 0x01, - ILLEGAL_STATE = 0x02, - INTERNAL_ERROR = 0x03, -} WMI_ERROR_CODE; - -typedef PREPACK struct { - A_UINT16 commandId; - A_UINT8 errorCode; -} POSTPACK WMI_CMD_ERROR_EVENT; - -/* - * New Regulatory Domain Event - */ -typedef PREPACK struct { - A_UINT32 regDomain; -} POSTPACK WMI_REG_DOMAIN_EVENT; - -typedef PREPACK struct { - A_UINT8 trafficClass; -} POSTPACK WMI_PSTREAM_TIMEOUT_EVENT; - -/* - * The WMI_NEIGHBOR_REPORT Event is generated by the target to inform - * the host of BSS's it has found that matches the current profile. - * It can be used by the host to cache PMKs and/to initiate pre-authentication - * if the BSS supports it. The first bssid is always the current associated - * BSS. - * The bssid and bssFlags information repeats according to the number - * or APs reported. - */ -typedef enum { - WMI_DEFAULT_BSS_FLAGS = 0x00, - WMI_PREAUTH_CAPABLE_BSS = 0x01, - WMI_PMKID_VALID_BSS = 0x02, -} WMI_BSS_FLAGS; - -typedef PREPACK struct { - A_UINT8 bssid[ATH_MAC_LEN]; - A_UINT8 bssFlags; /* see WMI_BSS_FLAGS */ -} POSTPACK WMI_NEIGHBOR_INFO; - -typedef PREPACK struct { - A_INT8 numberOfAps; - WMI_NEIGHBOR_INFO neighbor[1]; -} POSTPACK WMI_NEIGHBOR_REPORT_EVENT; - -/* - * TKIP MIC Error Event - */ -typedef PREPACK struct { - A_UINT8 keyid; - A_UINT8 ismcast; -} POSTPACK WMI_TKIP_MICERR_EVENT; - -/* - * WMI_SCAN_COMPLETE_EVENTID - no parameters (old), staus parameter (new) - */ -typedef PREPACK struct { - A_STATUS status; -} POSTPACK WMI_SCAN_COMPLETE_EVENT; - -#define MAX_OPT_DATA_LEN 1400 - -/* - * WMI_SET_ADHOC_BSSID_CMDID - */ -typedef PREPACK struct { - A_UINT8 bssid[ATH_MAC_LEN]; -} POSTPACK WMI_SET_ADHOC_BSSID_CMD; - -/* - * WMI_SET_OPT_MODE_CMDID - */ -typedef enum { - SPECIAL_OFF, - SPECIAL_ON, -} OPT_MODE_TYPE; - -typedef PREPACK struct { - A_UINT8 optMode; -} POSTPACK WMI_SET_OPT_MODE_CMD; - -/* - * WMI_TX_OPT_FRAME_CMDID - */ -typedef enum { - OPT_PROBE_REQ = 0x01, - OPT_PROBE_RESP = 0x02, - OPT_CPPP_START = 0x03, - OPT_CPPP_STOP = 0x04, -} WMI_OPT_FTYPE; - -typedef PREPACK struct { - A_UINT16 optIEDataLen; - A_UINT8 frmType; - A_UINT8 dstAddr[ATH_MAC_LEN]; - A_UINT8 bssid[ATH_MAC_LEN]; - A_UINT8 reserved; /* For alignment */ - A_UINT8 optIEData[1]; -} POSTPACK WMI_OPT_TX_FRAME_CMD; - -/* - * Special frame receive Event. - * Mechanism used to inform host of the receiption of the special frames. - * Consists of special frame info header followed by special frame body. - * The 802.11 header is not included. - */ -typedef PREPACK struct { - A_UINT16 channel; - A_UINT8 frameType; /* see WMI_OPT_FTYPE */ - A_INT8 snr; - A_UINT8 srcAddr[ATH_MAC_LEN]; - A_UINT8 bssid[ATH_MAC_LEN]; -} POSTPACK WMI_OPT_RX_INFO_HDR; - -/* - * Reporting statistics. - */ -typedef PREPACK struct { - A_UINT32 tx_packets; - A_UINT32 tx_bytes; - A_UINT32 tx_unicast_pkts; - A_UINT32 tx_unicast_bytes; - A_UINT32 tx_multicast_pkts; - A_UINT32 tx_multicast_bytes; - A_UINT32 tx_broadcast_pkts; - A_UINT32 tx_broadcast_bytes; - A_UINT32 tx_rts_success_cnt; - A_UINT32 tx_packet_per_ac[4]; - A_UINT32 tx_errors_per_ac[4]; - - A_UINT32 tx_errors; - A_UINT32 tx_failed_cnt; - A_UINT32 tx_retry_cnt; - A_UINT32 tx_rts_fail_cnt; - A_INT32 tx_unicast_rate; -}POSTPACK tx_stats_t; - -typedef PREPACK struct { - A_UINT32 rx_packets; - A_UINT32 rx_bytes; - A_UINT32 rx_unicast_pkts; - A_UINT32 rx_unicast_bytes; - A_UINT32 rx_multicast_pkts; - A_UINT32 rx_multicast_bytes; - A_UINT32 rx_broadcast_pkts; - A_UINT32 rx_broadcast_bytes; - A_UINT32 rx_fragment_pkt; - - A_UINT32 rx_errors; - A_UINT32 rx_crcerr; - A_UINT32 rx_key_cache_miss; - A_UINT32 rx_decrypt_err; - A_UINT32 rx_duplicate_frames; - A_INT32 rx_unicast_rate; -}POSTPACK rx_stats_t; - -typedef PREPACK struct { - A_UINT32 tkip_local_mic_failure; - A_UINT32 tkip_counter_measures_invoked; - A_UINT32 tkip_replays; - A_UINT32 tkip_format_errors; - A_UINT32 ccmp_format_errors; - A_UINT32 ccmp_replays; -}POSTPACK tkip_ccmp_stats_t; - -typedef PREPACK struct { - A_UINT32 power_save_failure_cnt; -}POSTPACK pm_stats_t; - -typedef PREPACK struct { - A_UINT32 cs_bmiss_cnt; - A_UINT32 cs_lowRssi_cnt; - A_UINT16 cs_connect_cnt; - A_UINT16 cs_disconnect_cnt; - A_INT16 cs_aveBeacon_rssi; - A_UINT16 cs_roam_count; - A_UINT16 cs_rssi; - A_UINT8 cs_snr; - A_UINT8 cs_aveBeacon_snr; - A_UINT8 cs_lastRoam_msec; -} POSTPACK cserv_stats_t; - -typedef PREPACK struct { - tx_stats_t tx_stats; - rx_stats_t rx_stats; - tkip_ccmp_stats_t tkipCcmpStats; -}POSTPACK wlan_net_stats_t; - -typedef PREPACK struct { - A_UINT32 wow_num_pkts_dropped; - A_UINT16 wow_num_events_discarded; - A_UINT8 wow_num_host_pkt_wakeups; - A_UINT8 wow_num_host_event_wakeups; -} POSTPACK wlan_wow_stats_t; - -typedef PREPACK struct { - A_UINT32 lqVal; - A_INT32 noise_floor_calibation; - pm_stats_t pmStats; - wlan_net_stats_t txrxStats; - wlan_wow_stats_t wowStats; - cserv_stats_t cservStats; -} POSTPACK WMI_TARGET_STATS; - -/* - * WMI_RSSI_THRESHOLD_EVENTID. - * Indicate the RSSI events to host. Events are indicated when we breach a - * thresold value. - */ -typedef enum{ - WMI_RSSI_THRESHOLD1_ABOVE = 0, - WMI_RSSI_THRESHOLD2_ABOVE, - WMI_RSSI_THRESHOLD3_ABOVE, - WMI_RSSI_THRESHOLD4_ABOVE, - WMI_RSSI_THRESHOLD5_ABOVE, - WMI_RSSI_THRESHOLD6_ABOVE, - WMI_RSSI_THRESHOLD1_BELOW, - WMI_RSSI_THRESHOLD2_BELOW, - WMI_RSSI_THRESHOLD3_BELOW, - WMI_RSSI_THRESHOLD4_BELOW, - WMI_RSSI_THRESHOLD5_BELOW, - WMI_RSSI_THRESHOLD6_BELOW -}WMI_RSSI_THRESHOLD_VAL; - -typedef PREPACK struct { - A_INT16 rssi; - A_UINT8 range; -}POSTPACK WMI_RSSI_THRESHOLD_EVENT; - -/* - * WMI_ERROR_REPORT_EVENTID - */ -typedef enum{ - WMI_TARGET_PM_ERR_FAIL = 0x00000001, - WMI_TARGET_KEY_NOT_FOUND = 0x00000002, - WMI_TARGET_DECRYPTION_ERR = 0x00000004, - WMI_TARGET_BMISS = 0x00000008, - WMI_PSDISABLE_NODE_JOIN = 0x00000010, - WMI_TARGET_COM_ERR = 0x00000020, - WMI_TARGET_FATAL_ERR = 0x00000040 -} WMI_TARGET_ERROR_VAL; - -typedef PREPACK struct { - A_UINT32 errorVal; -}POSTPACK WMI_TARGET_ERROR_REPORT_EVENT; - -typedef PREPACK struct { - A_UINT8 retrys; -}POSTPACK WMI_TX_RETRY_ERR_EVENT; - -typedef enum{ - WMI_SNR_THRESHOLD1_ABOVE = 1, - WMI_SNR_THRESHOLD1_BELOW, - WMI_SNR_THRESHOLD2_ABOVE, - WMI_SNR_THRESHOLD2_BELOW, - WMI_SNR_THRESHOLD3_ABOVE, - WMI_SNR_THRESHOLD3_BELOW, - WMI_SNR_THRESHOLD4_ABOVE, - WMI_SNR_THRESHOLD4_BELOW -} WMI_SNR_THRESHOLD_VAL; - -typedef PREPACK struct { - A_UINT8 range; /* WMI_SNR_THRESHOLD_VAL */ - A_UINT8 snr; -}POSTPACK WMI_SNR_THRESHOLD_EVENT; - -typedef enum{ - WMI_LQ_THRESHOLD1_ABOVE = 1, - WMI_LQ_THRESHOLD1_BELOW, - WMI_LQ_THRESHOLD2_ABOVE, - WMI_LQ_THRESHOLD2_BELOW, - WMI_LQ_THRESHOLD3_ABOVE, - WMI_LQ_THRESHOLD3_BELOW, - WMI_LQ_THRESHOLD4_ABOVE, - WMI_LQ_THRESHOLD4_BELOW -} WMI_LQ_THRESHOLD_VAL; - -typedef PREPACK struct { - A_INT32 lq; - A_UINT8 range; /* WMI_LQ_THRESHOLD_VAL */ -}POSTPACK WMI_LQ_THRESHOLD_EVENT; -/* - * WMI_REPORT_ROAM_TBL_EVENTID - */ -#define MAX_ROAM_TBL_CAND 5 - -typedef PREPACK struct { - A_INT32 roam_util; - A_UINT8 bssid[ATH_MAC_LEN]; - A_INT8 rssi; - A_INT8 rssidt; - A_INT8 last_rssi; - A_INT8 util; - A_INT8 bias; - A_UINT8 reserved; /* For alignment */ -} POSTPACK WMI_BSS_ROAM_INFO; - - -typedef PREPACK struct { - A_UINT16 roamMode; - A_UINT16 numEntries; - WMI_BSS_ROAM_INFO bssRoamInfo[1]; -} POSTPACK WMI_TARGET_ROAM_TBL; - -/* - * WMI_CAC_EVENTID - */ -typedef enum { - CAC_INDICATION_ADMISSION = 0x00, - CAC_INDICATION_ADMISSION_RESP = 0x01, - CAC_INDICATION_DELETE = 0x02, - CAC_INDICATION_NO_RESP = 0x03, -}CAC_INDICATION; - -#define WMM_TSPEC_IE_LEN 63 - -typedef PREPACK struct { - A_UINT8 ac; - A_UINT8 cac_indication; - A_UINT8 statusCode; - A_UINT8 tspecSuggestion[WMM_TSPEC_IE_LEN]; -}POSTPACK WMI_CAC_EVENT; - -/* - * WMI_APLIST_EVENTID - */ - -typedef enum { - APLIST_VER1 = 1, -} APLIST_VER; - -typedef PREPACK struct { - A_UINT8 bssid[ATH_MAC_LEN]; - A_UINT16 channel; -} POSTPACK WMI_AP_INFO_V1; - -typedef PREPACK union { - WMI_AP_INFO_V1 apInfoV1; -} POSTPACK WMI_AP_INFO; - -typedef PREPACK struct { - A_UINT8 apListVer; - A_UINT8 numAP; - WMI_AP_INFO apList[1]; -} POSTPACK WMI_APLIST_EVENT; - -/* - * developer commands - */ - -/* - * WMI_SET_BITRATE_CMDID - * - * Get bit rate cmd uses same definition as set bit rate cmd - */ -typedef enum { - RATE_AUTO = -1, - RATE_1Mb = 0, - RATE_2Mb = 1, - RATE_5_5Mb = 2, - RATE_11Mb = 3, - RATE_6Mb = 4, - RATE_9Mb = 5, - RATE_12Mb = 6, - RATE_18Mb = 7, - RATE_24Mb = 8, - RATE_36Mb = 9, - RATE_48Mb = 10, - RATE_54Mb = 11, -} WMI_BIT_RATE; - -typedef PREPACK struct { - A_INT8 rateIndex; /* see WMI_BIT_RATE */ -} POSTPACK WMI_BIT_RATE_CMD, WMI_BIT_RATE_REPLY; - -/* - * WMI_SET_FIXRATES_CMDID - * - * Get fix rates cmd uses same definition as set fix rates cmd - */ -typedef enum { - FIX_RATE_1Mb = 0x1, - FIX_RATE_2Mb = 0x2, - FIX_RATE_5_5Mb = 0x4, - FIX_RATE_11Mb = 0x8, - FIX_RATE_6Mb = 0x10, - FIX_RATE_9Mb = 0x20, - FIX_RATE_12Mb = 0x40, - FIX_RATE_18Mb = 0x80, - FIX_RATE_24Mb = 0x100, - FIX_RATE_36Mb = 0x200, - FIX_RATE_48Mb = 0x400, - FIX_RATE_54Mb = 0x800, -} WMI_FIX_RATES_MASK; - -typedef PREPACK struct { - A_UINT16 fixRateMask; /* see WMI_BIT_RATE */ -} POSTPACK WMI_FIX_RATES_CMD, WMI_FIX_RATES_REPLY; - -/* - * WMI_SET_RECONNECT_AUTH_MODE_CMDID - * - * Set authentication mode - */ -typedef enum { - RECONN_DO_AUTH = 0x00, - RECONN_NOT_AUTH = 0x01 -} WMI_AUTH_MODE; - -typedef PREPACK struct { - A_UINT8 mode; -} POSTPACK WMI_SET_AUTH_MODE_CMD; - -/* - * WMI_SET_REASSOC_MODE_CMDID - * - * Set authentication mode - */ -typedef enum { - REASSOC_DO_DISASSOC = 0x00, - REASSOC_DONOT_DISASSOC = 0x01 -} WMI_REASSOC_MODE; - -typedef PREPACK struct { - A_UINT8 mode; -}POSTPACK WMI_SET_REASSOC_MODE_CMD; - -typedef enum { - ROAM_DATA_TIME = 1, /* Get The Roam Time Data */ -} ROAM_DATA_TYPE; - -typedef PREPACK struct { - A_UINT32 disassoc_time; - A_UINT32 no_txrx_time; - A_UINT32 assoc_time; - A_UINT32 allow_txrx_time; - A_UINT32 last_data_txrx_time; - A_UINT32 first_data_txrx_time; - A_UINT8 disassoc_bssid[ATH_MAC_LEN]; - A_INT8 disassoc_bss_rssi; - A_UINT8 assoc_bssid[ATH_MAC_LEN]; - A_INT8 assoc_bss_rssi; -} POSTPACK WMI_TARGET_ROAM_TIME; - -typedef PREPACK struct { - PREPACK union { - WMI_TARGET_ROAM_TIME roamTime; - } POSTPACK u; - A_UINT8 roamDataType ; -} POSTPACK WMI_TARGET_ROAM_DATA; - -typedef enum { - WMI_WMM_DISABLED = 0, - WMI_WMM_ENABLED -} WMI_WMM_STATUS; - -typedef PREPACK struct { - A_UINT8 status; -}POSTPACK WMI_SET_WMM_CMD; - -typedef enum { - WMI_TXOP_DISABLED = 0, - WMI_TXOP_ENABLED -} WMI_TXOP_CFG; - -typedef PREPACK struct { - A_UINT8 txopEnable; -}POSTPACK WMI_SET_WMM_TXOP_CMD; - -typedef PREPACK struct { - A_UINT8 keepaliveInterval; -} POSTPACK WMI_SET_KEEPALIVE_CMD; - -typedef PREPACK struct { - A_BOOL configured; - A_UINT8 keepaliveInterval; -} POSTPACK WMI_GET_KEEPALIVE_CMD; - -/* - * Add Application specified IE to a management frame - */ -#define WMI_MAX_IE_LEN 78 - -typedef PREPACK struct { - A_UINT8 mgmtFrmType; /* one of WMI_MGMT_FRAME_TYPE */ - A_UINT8 ieLen; /* Length of the IE that should be added to the MGMT frame */ - A_UINT8 ieInfo[1]; -} POSTPACK WMI_SET_APPIE_CMD; - -/* - * Notify the WSC registration status to the target - */ -#define WSC_REG_ACTIVE 1 -#define WSC_REG_INACTIVE 0 -/* Generic Hal Interface for setting hal paramters. */ -/* Add new Set HAL Param cmdIds here for newer params */ -typedef enum { - WHAL_SETCABTO_CMDID = 1, -}WHAL_CMDID; - -typedef PREPACK struct { - A_UINT8 cabTimeOut; -} POSTPACK WHAL_SETCABTO_PARAM; - -typedef PREPACK struct { - A_UINT8 whalCmdId; - A_UINT8 data[1]; -} POSTPACK WHAL_PARAMCMD; - - -#define WOW_MAX_FILTER_LISTS 1 /*4*/ -#define WOW_MAX_FILTERS_PER_LIST 4 -#define WOW_PATTERN_SIZE 64 -#define WOW_MASK_SIZE 64 - -typedef PREPACK struct { - A_UINT8 wow_valid_filter; - A_UINT8 wow_filter_id; - A_UINT8 wow_filter_size; - A_UINT8 wow_filter_offset; - A_UINT8 wow_filter_mask[WOW_MASK_SIZE]; - A_UINT8 wow_filter_pattern[WOW_PATTERN_SIZE]; -} POSTPACK WOW_FILTER; - - -typedef PREPACK struct { - A_UINT8 wow_valid_list; - A_UINT8 wow_list_id; - A_UINT8 wow_num_filters; - A_UINT8 wow_total_list_size; - WOW_FILTER list[WOW_MAX_FILTERS_PER_LIST]; -} POSTPACK WOW_FILTER_LIST; - -typedef PREPACK struct { - A_BOOL awake; - A_BOOL asleep; -} POSTPACK WMI_SET_HOST_SLEEP_MODE_CMD; - -typedef PREPACK struct { - A_BOOL enable_wow; -} POSTPACK WMI_SET_WOW_MODE_CMD; - -typedef PREPACK struct { - A_UINT8 filter_list_id; -} POSTPACK WMI_GET_WOW_LIST_CMD; - -/* - * WMI_GET_WOW_LIST_CMD reply - */ -typedef PREPACK struct { - A_UINT8 num_filters; /* number of patterns in reply */ - A_UINT8 this_filter_num; /* this is filter # x of total num_filters */ - A_UINT8 wow_mode; - A_UINT8 host_mode; - WOW_FILTER wow_filters[1]; -} POSTPACK WMI_GET_WOW_LIST_REPLY; - -typedef PREPACK struct { - A_UINT8 filter_list_id; - A_UINT8 filter_size; - A_UINT8 filter_offset; - A_UINT8 filter[1]; -} POSTPACK WMI_ADD_WOW_PATTERN_CMD; - -typedef PREPACK struct { - A_UINT16 filter_list_id; - A_UINT16 filter_id; -} POSTPACK WMI_DEL_WOW_PATTERN_CMD; - -typedef PREPACK struct { - A_UINT8 macaddr[ATH_MAC_LEN]; -} POSTPACK WMI_SET_MAC_ADDRESS_CMD; - -/* - * WMI_SET_AKMP_PARAMS_CMD - */ - -#define WMI_AKMP_MULTI_PMKID_EN 0x000001 - -typedef PREPACK struct { - A_UINT32 akmpInfo; -} POSTPACK WMI_SET_AKMP_PARAMS_CMD; - -typedef PREPACK struct { - A_UINT8 pmkid[WMI_PMKID_LEN]; -} POSTPACK WMI_PMKID; - -/* - * WMI_SET_PMKID_LIST_CMD - */ -#define WMI_MAX_PMKID_CACHE 8 - -typedef PREPACK struct { - A_UINT32 numPMKID; - WMI_PMKID pmkidList[WMI_MAX_PMKID_CACHE]; -} POSTPACK WMI_SET_PMKID_LIST_CMD; - -/* - * WMI_GET_PMKID_LIST_CMD Reply - * Following the Number of PMKIDs is the list of PMKIDs - */ -typedef PREPACK struct { - A_UINT32 numPMKID; - WMI_PMKID pmkidList[1]; -} POSTPACK WMI_PMKID_LIST_REPLY; - -/* index used for priority streams */ -typedef enum { - WMI_NOT_MAPPED = -1, - WMI_CONTROL_PRI = 0, - WMI_BEST_EFFORT_PRI = 1, - WMI_LOW_PRI = 2, - WMI_HIGH_PRI = 3, - WMI_HIGHEST_PRI, - WMI_PRI_MAX_COUNT -} WMI_PRI_STREAM_ID; - -#ifndef ATH_TARGET -#include "athendpack.h" -#endif - -#ifdef __cplusplus -} -#endif - -#endif /* _WMI_H_ */ diff --git a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/include/wmi_api.h b/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/include/wmi_api.h deleted file mode 100644 index 267edfd0a..000000000 --- a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/include/wmi_api.h +++ /dev/null @@ -1,260 +0,0 @@ -#ifndef _WMI_API_H_ -#define _WMI_API_H_ -/* - * Copyright (c) 2004-2006 Atheros Communications Inc. - * All rights reserved. - * - * This file contains the definitions for the Wireless Module Interface (WMI). - * - * $Id: //depot/sw/releases/olca2.0-GPL/host/include/wmi_api.h#2 $ - * - * - * 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; - * - * Software distributed under the License is distributed on an "AS - * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or - * implied. See the License for the specific language governing - * rights and limitations under the License. - * - * - * - */ - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * IP QoS Field definitions according to 802.1p - */ -#define BEST_EFFORT_PRI 0 -#define BACKGROUND_PRI 1 -#define EXCELLENT_EFFORT_PRI 3 -#define CONTROLLED_LOAD_PRI 4 -#define VIDEO_PRI 5 -#define VOICE_PRI 6 -#define NETWORK_CONTROL_PRI 7 -#define MAX_NUM_PRI 8 - -#define UNDEFINED_PRI (0xff) - -/* simple mapping of IP TOS field to a WMI priority stream - * this mapping was taken from the original linux driver implementation - * The operation maps the following - * - * */ -#define IP_TOS_TO_WMI_PRI(tos) \ - ((WMI_PRI_STREAM_ID)(((tos) >> 1) & 0x03)) - -#define WMI_IMPLICIT_PSTREAM_INACTIVITY_INT 5000 /* 5 seconds */ - - -struct wmi_t; - -void *wmi_init(void *devt); - -void wmi_qos_state_init(struct wmi_t *wmip); -void wmi_shutdown(struct wmi_t *wmip); -A_UINT16 wmi_get_mapped_qos_queue(struct wmi_t *, A_UINT8); -A_STATUS wmi_dix_2_dot3(struct wmi_t *wmip, void *osbuf); -A_STATUS wmi_data_hdr_add(struct wmi_t *wmip, void *osbuf, A_UINT8 msgType); -A_STATUS wmi_dot3_2_dix(struct wmi_t *wmip, void *osbuf); -A_STATUS wmi_data_hdr_remove(struct wmi_t *wmip, void *osbuf); -A_STATUS wmi_syncpoint(struct wmi_t *wmip); -A_STATUS wmi_syncpoint_reset(struct wmi_t *wmip); -WMI_PRI_STREAM_ID wmi_get_stream_id(struct wmi_t *wmip, A_UINT8 trafficClass); -A_UINT8 wmi_implicit_create_pstream(struct wmi_t *wmip, void *osbuf, A_UINT8 dir, A_UINT8 up); - -A_STATUS wmi_control_rx(struct wmi_t *wmip, void *osbuf); -void wmi_iterate_nodes(struct wmi_t *wmip, wlan_node_iter_func *f, void *arg); -void wmi_free_allnodes(struct wmi_t *wmip); -bss_t *wmi_find_node(struct wmi_t *wmip, const A_UINT8 *macaddr); - - -typedef enum { - NO_SYNC_WMIFLAG = 0, - SYNC_BEFORE_WMIFLAG, /* transmit all queued data before cmd */ - SYNC_AFTER_WMIFLAG, /* any new data waits until cmd execs */ - SYNC_BOTH_WMIFLAG, - END_WMIFLAG /* end marker */ -} WMI_SYNC_FLAG; - -A_STATUS wmi_cmd_send(struct wmi_t *wmip, void *osbuf, WMI_COMMAND_ID cmdId, - WMI_SYNC_FLAG flag); -A_STATUS wmi_connect_cmd(struct wmi_t *wmip, - NETWORK_TYPE netType, - DOT11_AUTH_MODE dot11AuthMode, - AUTH_MODE authMode, - CRYPTO_TYPE pairwiseCrypto, - A_UINT8 pairwiseCryptoLen, - CRYPTO_TYPE groupCrypto, - A_UINT8 groupCryptoLen, - int ssidLength, - A_UCHAR *ssid, - A_UINT8 *bssid, - A_UINT16 channel, - A_UINT32 ctrl_flags); -A_STATUS wmi_reconnect_cmd(struct wmi_t *wmip, - A_UINT8 *bssid, - A_UINT16 channel); -A_STATUS wmi_disconnect_cmd(struct wmi_t *wmip); -A_STATUS wmi_getrev_cmd(struct wmi_t *wmip); -A_STATUS wmi_startscan_cmd(struct wmi_t *wmip, WMI_SCAN_TYPE scanType, - A_BOOL forceFgScan, A_BOOL isLegacy, - A_UINT32 homeDwellTime, A_UINT32 forceScanInterval); -A_STATUS wmi_scanparams_cmd(struct wmi_t *wmip, A_UINT16 fg_start_sec, - A_UINT16 fg_end_sec, A_UINT16 bg_sec, - A_UINT16 minact_chdw_msec, - A_UINT16 maxact_chdw_msec, A_UINT16 pas_chdw_msec, - A_UINT8 shScanRatio, A_UINT8 scanCtrlFlags, - A_UINT32 max_dfsch_act_time); -A_STATUS wmi_bssfilter_cmd(struct wmi_t *wmip, A_UINT8 filter, A_UINT32 ieMask); -A_STATUS wmi_probedSsid_cmd(struct wmi_t *wmip, A_UINT8 index, A_UINT8 flag, - A_UINT8 ssidLength, A_UCHAR *ssid); -A_STATUS wmi_listeninterval_cmd(struct wmi_t *wmip, A_UINT16 listenInterval, A_UINT16 listenBeacons); -A_STATUS wmi_bmisstime_cmd(struct wmi_t *wmip, A_UINT16 bmisstime, A_UINT16 bmissbeacons); -A_STATUS wmi_associnfo_cmd(struct wmi_t *wmip, A_UINT8 ieType, - A_UINT8 ieLen, A_UINT8 *ieInfo); -A_STATUS wmi_powermode_cmd(struct wmi_t *wmip, A_UINT8 powerMode); -A_STATUS wmi_ibsspmcaps_cmd(struct wmi_t *wmip, A_UINT8 pmEnable, A_UINT8 ttl, - A_UINT16 atim_windows, A_UINT16 timeout_value); -A_STATUS wmi_pmparams_cmd(struct wmi_t *wmip, A_UINT16 idlePeriod, - A_UINT16 psPollNum, A_UINT16 dtimPolicy); -A_STATUS wmi_disctimeout_cmd(struct wmi_t *wmip, A_UINT8 timeout); -A_STATUS wmi_sync_cmd(struct wmi_t *wmip, A_UINT8 syncNumber); -A_STATUS wmi_create_pstream_cmd(struct wmi_t *wmip, WMI_CREATE_PSTREAM_CMD *pstream); -A_STATUS wmi_delete_pstream_cmd(struct wmi_t *wmip, A_UINT8 trafficClass, A_UINT8 streamID); -A_STATUS wmi_set_bitrate_cmd(struct wmi_t *wmip, A_INT32 rate); -A_STATUS wmi_get_bitrate_cmd(struct wmi_t *wmip); -A_INT8 wmi_validate_bitrate(struct wmi_t *wmip, A_INT32 rate); -A_STATUS wmi_get_regDomain_cmd(struct wmi_t *wmip); -A_STATUS wmi_get_channelList_cmd(struct wmi_t *wmip); -A_STATUS wmi_set_channelParams_cmd(struct wmi_t *wmip, A_UINT8 scanParam, - WMI_PHY_MODE mode, A_INT8 numChan, - A_UINT16 *channelList); - -A_STATUS wmi_set_snr_threshold_params(struct wmi_t *wmip, - WMI_SNR_THRESHOLD_PARAMS_CMD *snrCmd); -A_STATUS wmi_set_rssi_threshold_params(struct wmi_t *wmip, - WMI_RSSI_THRESHOLD_PARAMS_CMD *rssiCmd); -A_STATUS wmi_clr_rssi_snr(struct wmi_t *wmip); -A_STATUS wmi_set_lq_threshold_params(struct wmi_t *wmip, - WMI_LQ_THRESHOLD_PARAMS_CMD *lqCmd); -A_STATUS wmi_set_rts_cmd(struct wmi_t *wmip, A_UINT16 threshold); -A_STATUS wmi_set_lpreamble_cmd(struct wmi_t *wmip, A_UINT8 status); - -A_STATUS wmi_set_error_report_bitmask(struct wmi_t *wmip, A_UINT32 bitmask); - -A_STATUS wmi_get_challenge_resp_cmd(struct wmi_t *wmip, A_UINT32 cookie, - A_UINT32 source); -A_STATUS wmi_config_debug_module_cmd(struct wmi_t *wmip, A_UINT16 mmask, - A_UINT16 tsr, A_BOOL rep, A_UINT16 size, - A_UINT32 valid); -A_STATUS wmi_get_stats_cmd(struct wmi_t *wmip); -A_STATUS wmi_addKey_cmd(struct wmi_t *wmip, A_UINT8 keyIndex, - CRYPTO_TYPE keyType, A_UINT8 keyUsage, - A_UINT8 keyLength,A_UINT8 *keyRSC, - A_UINT8 *keyMaterial, A_UINT8 key_op_ctrl, - WMI_SYNC_FLAG sync_flag); -A_STATUS wmi_add_krk_cmd(struct wmi_t *wmip, A_UINT8 *krk); -A_STATUS wmi_delete_krk_cmd(struct wmi_t *wmip); -A_STATUS wmi_deleteKey_cmd(struct wmi_t *wmip, A_UINT8 keyIndex); -A_STATUS wmi_set_akmp_params_cmd(struct wmi_t *wmip, - WMI_SET_AKMP_PARAMS_CMD *akmpParams); -A_STATUS wmi_get_pmkid_list_cmd(struct wmi_t *wmip); -A_STATUS wmi_set_pmkid_list_cmd(struct wmi_t *wmip, - WMI_SET_PMKID_LIST_CMD *pmkInfo); -A_STATUS wmi_set_txPwr_cmd(struct wmi_t *wmip, A_UINT8 dbM); -A_STATUS wmi_get_txPwr_cmd(struct wmi_t *wmip); -A_STATUS wmi_switch_radio(struct wmi_t *wmip, A_UINT8 on); -A_STATUS wmi_addBadAp_cmd(struct wmi_t *wmip, A_UINT8 apIndex, A_UINT8 *bssid); -A_STATUS wmi_deleteBadAp_cmd(struct wmi_t *wmip, A_UINT8 apIndex); -A_STATUS wmi_set_tkip_countermeasures_cmd(struct wmi_t *wmip, A_BOOL en); -A_STATUS wmi_setPmkid_cmd(struct wmi_t *wmip, A_UINT8 *bssid, A_UINT8 *pmkId, - A_BOOL set); -A_STATUS wmi_set_access_params_cmd(struct wmi_t *wmip, A_UINT16 txop, - A_UINT8 eCWmin, A_UINT8 eCWmax, - A_UINT8 aifsn); -A_STATUS wmi_set_retry_limits_cmd(struct wmi_t *wmip, A_UINT8 frameType, - A_UINT8 trafficClass, A_UINT8 maxRetries, - A_UINT8 enableNotify); - -void wmi_get_current_bssid(struct wmi_t *wmip, A_UINT8 *bssid); - -A_STATUS wmi_get_roam_tbl_cmd(struct wmi_t *wmip); -A_STATUS wmi_get_roam_data_cmd(struct wmi_t *wmip, A_UINT8 roamDataType); -A_STATUS wmi_set_roam_ctrl_cmd(struct wmi_t *wmip, WMI_SET_ROAM_CTRL_CMD *p, - A_UINT8 size); -A_STATUS wmi_set_powersave_timers_cmd(struct wmi_t *wmip, - WMI_POWERSAVE_TIMERS_POLICY_CMD *pCmd, - A_UINT8 size); - -A_STATUS wmi_set_opt_mode_cmd(struct wmi_t *wmip, A_UINT8 optMode); -A_STATUS wmi_opt_tx_frame_cmd(struct wmi_t *wmip, - A_UINT8 frmType, - A_UINT8 *dstMacAddr, - A_UINT8 *bssid, - A_UINT16 optIEDataLen, - A_UINT8 *optIEData); - -A_STATUS wmi_set_adhoc_bconIntvl_cmd(struct wmi_t *wmip, A_UINT16 intvl); -A_STATUS wmi_set_voice_pkt_size_cmd(struct wmi_t *wmip, A_UINT16 voicePktSize); -A_STATUS wmi_set_max_sp_len_cmd(struct wmi_t *wmip, A_UINT8 maxSpLen); -A_UINT8 convert_userPriority_to_trafficClass(A_UINT8 userPriority); -A_UINT8 wmi_get_power_mode_cmd(struct wmi_t *wmip); -A_STATUS wmi_verify_tspec_params(WMI_CREATE_PSTREAM_CMD *pCmd, A_BOOL tspecCompliance); - -#ifdef CONFIG_HOST_TCMD_SUPPORT -A_STATUS wmi_test_cmd(struct wmi_t *wmip, A_UINT8 *buf, A_UINT32 len); -#endif - -A_STATUS wmi_set_bt_status_cmd(struct wmi_t *wmip, A_UINT8 streamType, A_UINT8 status); -A_STATUS wmi_set_bt_params_cmd(struct wmi_t *wmip, WMI_SET_BT_PARAMS_CMD* cmd); - - -/* - * This function is used to configure the fix rates mask to the target. - */ -A_STATUS wmi_set_fixrates_cmd(struct wmi_t *wmip, A_INT16 fixRatesMask); -A_STATUS wmi_get_ratemask_cmd(struct wmi_t *wmip); - -A_STATUS wmi_set_authmode_cmd(struct wmi_t *wmip, A_UINT8 mode); - -A_STATUS wmi_set_reassocmode_cmd(struct wmi_t *wmip, A_UINT8 mode); - -A_STATUS wmi_set_wmm_cmd(struct wmi_t *wmip, WMI_WMM_STATUS status); -A_STATUS wmi_set_wmm_txop(struct wmi_t *wmip, WMI_TXOP_CFG txEnable); - -A_STATUS wmi_get_keepalive_configured(struct wmi_t *wmip); -A_UINT8 wmi_get_keepalive_cmd(struct wmi_t *wmip); -A_STATUS wmi_set_keepalive_cmd(struct wmi_t *wmip, A_UINT8 keepaliveInterval); - -A_STATUS wmi_set_appie_cmd(struct wmi_t *wmip, A_UINT8 mgmtFrmType, - A_UINT8 ieLen,A_UINT8 *ieInfo); - -A_STATUS wmi_set_halparam_cmd(struct wmi_t *wmip, A_UINT8 *cmd, A_UINT16 dataLen); -A_INT32 wmi_get_rate(A_INT8 rateindex); - -/*Wake on Wireless WMI commands*/ -A_STATUS wmi_set_host_sleep_mode_cmd(struct wmi_t *wmip, WMI_SET_HOST_SLEEP_MODE_CMD *cmd); -A_STATUS wmi_set_wow_mode_cmd(struct wmi_t *wmip, WMI_SET_WOW_MODE_CMD *cmd); -A_STATUS wmi_get_wow_list_cmd(struct wmi_t *wmip, WMI_GET_WOW_LIST_CMD *cmd); -A_STATUS wmi_add_wow_pattern_cmd(struct wmi_t *wmip, - WMI_ADD_WOW_PATTERN_CMD *cmd, A_UINT8* pattern, A_UINT8* mask, A_UINT8 pattern_size); -A_STATUS wmi_del_wow_pattern_cmd(struct wmi_t *wmip, - WMI_DEL_WOW_PATTERN_CMD *cmd); -A_STATUS wmi_set_wsc_status_cmd(struct wmi_t *wmip, A_UINT32 status); - -bss_t * -wmi_find_Ssidnode (struct wmi_t *wmip, A_UCHAR *pSsid, - A_UINT32 ssidLength, A_BOOL bIsWPA2); - -void -wmi_node_return (struct wmi_t *wmip, bss_t *bss); -#ifdef __cplusplus -} -#endif - -#endif /* _WMI_API_H_ */ diff --git a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/include/wmix.h b/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/include/wmix.h deleted file mode 100644 index 8f12b5e55..000000000 --- a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/include/wmix.h +++ /dev/null @@ -1,233 +0,0 @@ -/* - * Copyright (c) 2004-2005 Atheros Communications Inc. - * All rights reserved. - * - * - * $ATH_LICENSE_HOSTSDK0_C$ - * - * This file contains extensions of the WMI protocol specified in the - * Wireless Module Interface (WMI). It includes definitions of all - * extended commands and events. Extensions include useful commands - * that are not directly related to wireless activities. They may - * be hardware-specific, and they might not be supported on all - * implementations. - * - * Extended WMIX commands are encapsulated in a WMI message with - * cmd=WMI_EXTENSION_CMD. - * - */ - -#ifndef _WMIX_H_ -#define _WMIX_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -#ifndef ATH_TARGET -#include "athstartpack.h" -#endif - -#include "dbglog.h" - -/* - * Extended WMI commands are those that are needed during wireless - * operation, but which are not really wireless commands. This allows, - * for instance, platform-specific commands. Extended WMI commands are - * embedded in a WMI command message with WMI_COMMAND_ID=WMI_EXTENSION_CMDID. - * Extended WMI events are similarly embedded in a WMI event message with - * WMI_EVENT_ID=WMI_EXTENSION_EVENTID. - */ -typedef PREPACK struct { - A_UINT32 commandId; -} POSTPACK WMIX_CMD_HDR; - -typedef enum { - WMIX_DSETOPEN_REPLY_CMDID = 0x2001, - WMIX_DSETDATA_REPLY_CMDID, - WMIX_GPIO_OUTPUT_SET_CMDID, - WMIX_GPIO_INPUT_GET_CMDID, - WMIX_GPIO_REGISTER_SET_CMDID, - WMIX_GPIO_REGISTER_GET_CMDID, - WMIX_GPIO_INTR_ACK_CMDID, - WMIX_HB_CHALLENGE_RESP_CMDID, - WMIX_DBGLOG_CFG_MODULE_CMDID, -} WMIX_COMMAND_ID; - -typedef enum { - WMIX_DSETOPENREQ_EVENTID = 0x3001, - WMIX_DSETCLOSE_EVENTID, - WMIX_DSETDATAREQ_EVENTID, - WMIX_GPIO_INTR_EVENTID, - WMIX_GPIO_DATA_EVENTID, - WMIX_GPIO_ACK_EVENTID, - WMIX_HB_CHALLENGE_RESP_EVENTID, - WMIX_DBGLOG_EVENTID, -} WMIX_EVENT_ID; - -/* - * =============DataSet support================= - */ - -/* - * WMIX_DSETOPENREQ_EVENTID - * DataSet Open Request Event - */ -typedef PREPACK struct { - A_UINT32 dset_id; - A_UINT32 targ_dset_handle; /* echo'ed, not used by Host, */ - A_UINT32 targ_reply_fn; /* echo'ed, not used by Host, */ - A_UINT32 targ_reply_arg; /* echo'ed, not used by Host, */ -} POSTPACK WMIX_DSETOPENREQ_EVENT; - -/* - * WMIX_DSETCLOSE_EVENTID - * DataSet Close Event - */ -typedef PREPACK struct { - A_UINT32 access_cookie; -} POSTPACK WMIX_DSETCLOSE_EVENT; - -/* - * WMIX_DSETDATAREQ_EVENTID - * DataSet Data Request Event - */ -typedef PREPACK struct { - A_UINT32 access_cookie; - A_UINT32 offset; - A_UINT32 length; - A_UINT32 targ_buf; /* echo'ed, not used by Host, */ - A_UINT32 targ_reply_fn; /* echo'ed, not used by Host, */ - A_UINT32 targ_reply_arg; /* echo'ed, not used by Host, */ -} POSTPACK WMIX_DSETDATAREQ_EVENT; - -typedef PREPACK struct { - A_UINT32 status; - A_UINT32 targ_dset_handle; - A_UINT32 targ_reply_fn; - A_UINT32 targ_reply_arg; - A_UINT32 access_cookie; - A_UINT32 size; - A_UINT32 version; -} POSTPACK WMIX_DSETOPEN_REPLY_CMD; - -typedef PREPACK struct { - A_UINT32 status; - A_UINT32 targ_buf; - A_UINT32 targ_reply_fn; - A_UINT32 targ_reply_arg; - A_UINT32 length; - A_UINT8 buf[1]; -} POSTPACK WMIX_DSETDATA_REPLY_CMD; - - -/* - * =============GPIO support================= - * All masks are 18-bit masks with bit N operating on GPIO pin N. - */ - -#include "gpio.h" - -/* - * Set GPIO pin output state. - * In order for output to be driven, a pin must be enabled for output. - * This can be done during initialization through the GPIO Configuration - * DataSet, or during operation with the enable_mask. - * - * If a request is made to simultaneously set/clear or set/disable or - * clear/disable or disable/enable, results are undefined. - */ -typedef PREPACK struct { - A_UINT32 set_mask; /* pins to set */ - A_UINT32 clear_mask; /* pins to clear */ - A_UINT32 enable_mask; /* pins to enable for output */ - A_UINT32 disable_mask; /* pins to disable/tristate */ -} POSTPACK WMIX_GPIO_OUTPUT_SET_CMD; - -/* - * Set a GPIO register. For debug/exceptional cases. - * Values for gpioreg_id are GPIO_REGISTER_IDs, defined in a - * platform-dependent header. - */ -typedef PREPACK struct { - A_UINT32 gpioreg_id; /* GPIO register ID */ - A_UINT32 value; /* value to write */ -} POSTPACK WMIX_GPIO_REGISTER_SET_CMD; - -/* Get a GPIO register. For debug/exceptional cases. */ -typedef PREPACK struct { - A_UINT32 gpioreg_id; /* GPIO register to read */ -} POSTPACK WMIX_GPIO_REGISTER_GET_CMD; - -/* - * Host acknowledges and re-arms GPIO interrupts. A single - * message should be used to acknowledge all interrupts that - * were delivered in an earlier WMIX_GPIO_INTR_EVENT message. - */ -typedef PREPACK struct { - A_UINT32 ack_mask; /* interrupts to acknowledge */ -} POSTPACK WMIX_GPIO_INTR_ACK_CMD; - -/* - * Target informs Host of GPIO interrupts that have ocurred since the - * last WMIX_GIPO_INTR_ACK_CMD was received. Additional information -- - * the current GPIO input values is provided -- in order to support - * use of a GPIO interrupt as a Data Valid signal for other GPIO pins. - */ -typedef PREPACK struct { - A_UINT32 intr_mask; /* pending GPIO interrupts */ - A_UINT32 input_values; /* recent GPIO input values */ -} POSTPACK WMIX_GPIO_INTR_EVENT; - -/* - * Target responds to Host's earlier WMIX_GPIO_INPUT_GET_CMDID request - * using a GPIO_DATA_EVENT with - * value set to the mask of GPIO pin inputs and - * reg_id set to GPIO_ID_NONE - * - * - * Target responds to Hosts's earlier WMIX_GPIO_REGISTER_GET_CMDID request - * using a GPIO_DATA_EVENT with - * value set to the value of the requested register and - * reg_id identifying the register (reflects the original request) - * NB: reg_id supports the future possibility of unsolicited - * WMIX_GPIO_DATA_EVENTs (for polling GPIO input), and it may - * simplify Host GPIO support. - */ -typedef PREPACK struct { - A_UINT32 value; - A_UINT32 reg_id; -} POSTPACK WMIX_GPIO_DATA_EVENT; - -/* - * =============Error Detection support================= - */ - -/* - * WMIX_HB_CHALLENGE_RESP_CMDID - * Heartbeat Challenge Response command - */ -typedef PREPACK struct { - A_UINT32 cookie; - A_UINT32 source; -} POSTPACK WMIX_HB_CHALLENGE_RESP_CMD; - -/* - * WMIX_HB_CHALLENGE_RESP_EVENTID - * Heartbeat Challenge Response Event - */ -#define WMIX_HB_CHALLENGE_RESP_EVENT WMIX_HB_CHALLENGE_RESP_CMD - -typedef PREPACK struct { - struct dbglog_config_s config; -} POSTPACK WMIX_DBGLOG_CFG_MODULE_CMD; - -#ifndef ATH_TARGET -#include "athendpack.h" -#endif - -#ifdef __cplusplus -} -#endif - -#endif /* _WMIX_H_ */ diff --git a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/miscdrv/common_drv.c b/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/miscdrv/common_drv.c deleted file mode 100644 index 4f1273466..000000000 --- a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/miscdrv/common_drv.c +++ /dev/null @@ -1,467 +0,0 @@ - -/* - * - * Copyright (c) 2004-2007 Atheros Communications Inc. - * All rights reserved. - * - * - * 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; - * - * Software distributed under the License is distributed on an "AS - * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or - * implied. See the License for the specific language governing - * rights and limitations under the License. - * - * - * - */ - -#include "a_config.h" -#include "athdefs.h" -#include "a_types.h" -#include "AR6Khwreg.h" -#include "targaddrs.h" -#include "a_osapi.h" -#include "hif.h" -#include "htc_api.h" -#include "bmi.h" -#include "bmi_msg.h" -#include "common_drv.h" -#include "a_debug.h" -#include "targaddrs.h" - -#define HOST_INTEREST_ITEM_ADDRESS(target, item) \ -(((TargetType) == TARGET_TYPE_AR6001) ? \ - AR6001_HOST_INTEREST_ITEM_ADDRESS(item) : \ - AR6002_HOST_INTEREST_ITEM_ADDRESS(item)) - - -/* Compile the 4BYTE version of the window register setup routine, - * This mitigates host interconnect issues with non-4byte aligned bus requests, some - * interconnects use bus adapters that impose strict limitations. - * Since diag window access is not intended for performance critical operations, the 4byte mode should - * be satisfactory even though it generates 4X the bus activity. */ - -#ifdef USE_4BYTE_REGISTER_ACCESS - - /* set the window address register (using 4-byte register access ). */ -A_STATUS ar6000_SetAddressWindowRegister(HIF_DEVICE *hifDevice, A_UINT32 RegisterAddr, A_UINT32 Address) -{ - A_STATUS status; - A_UINT8 addrValue[4]; - int i; - - /* write bytes 1,2,3 of the register to set the upper address bytes, the LSB is written - * last to initiate the access cycle */ - - for (i = 1; i <= 3; i++) { - /* fill the buffer with the address byte value we want to hit 4 times*/ - addrValue[0] = ((A_UINT8 *)&Address)[i]; - addrValue[1] = addrValue[0]; - addrValue[2] = addrValue[0]; - addrValue[3] = addrValue[0]; - - /* hit each byte of the register address with a 4-byte write operation to the same address, - * this is a harmless operation */ - status = HIFReadWrite(hifDevice, - RegisterAddr+i, - addrValue, - 4, - HIF_WR_SYNC_BYTE_FIX, - NULL); - if (status != A_OK) { - break; - } - } - - if (status != A_OK) { - AR_DEBUG_PRINTF(ATH_LOG_ERR, ("Cannot write initial bytes of 0x%x to window reg: 0x%X \n", - RegisterAddr, Address)); - return status; - } - - /* write the address register again, this time write the whole 4-byte value. - * The effect here is that the LSB write causes the cycle to start, the extra - * 3 byte write to bytes 1,2,3 has no effect since we are writing the same values again */ - status = HIFReadWrite(hifDevice, - RegisterAddr, - (A_UCHAR *)(&Address), - 4, - HIF_WR_SYNC_BYTE_INC, - NULL); - - if (status != A_OK) { - AR_DEBUG_PRINTF(ATH_LOG_ERR, ("Cannot write 0x%x to window reg: 0x%X \n", - RegisterAddr, Address)); - return status; - } - - return A_OK; - - - -} - - -#else - - /* set the window address register */ -A_STATUS ar6000_SetAddressWindowRegister(HIF_DEVICE *hifDevice, A_UINT32 RegisterAddr, A_UINT32 Address) -{ - A_STATUS status; - - /* write bytes 1,2,3 of the register to set the upper address bytes, the LSB is written - * last to initiate the access cycle */ - status = HIFReadWrite(hifDevice, - RegisterAddr+1, /* write upper 3 bytes */ - ((A_UCHAR *)(&Address))+1, - sizeof(A_UINT32)-1, - HIF_WR_SYNC_BYTE_INC, - NULL); - - if (status != A_OK) { - AR_DEBUG_PRINTF(ATH_LOG_ERR, ("Cannot write initial bytes of 0x%x to window reg: 0x%X \n", - RegisterAddr, Address)); - return status; - } - - /* write the LSB of the register, this initiates the operation */ - status = HIFReadWrite(hifDevice, - RegisterAddr, - (A_UCHAR *)(&Address), - sizeof(A_UINT8), - HIF_WR_SYNC_BYTE_INC, - NULL); - - if (status != A_OK) { - AR_DEBUG_PRINTF(ATH_LOG_ERR, ("Cannot write 0x%x to window reg: 0x%X \n", - RegisterAddr, Address)); - return status; - } - - return A_OK; -} - -#endif - -/* - * Read from the AR6000 through its diagnostic window. - * No cooperation from the Target is required for this. - */ -A_STATUS -ar6000_ReadRegDiag(HIF_DEVICE *hifDevice, A_UINT32 *address, A_UINT32 *data) -{ - A_STATUS status; - - /* set window register to start read cycle */ - status = ar6000_SetAddressWindowRegister(hifDevice, - WINDOW_READ_ADDR_ADDRESS, - *address); - - if (status != A_OK) { - return status; - } - - /* read the data */ - status = HIFReadWrite(hifDevice, - WINDOW_DATA_ADDRESS, - (A_UCHAR *)data, - sizeof(A_UINT32), - HIF_RD_SYNC_BYTE_INC, - NULL); - if (status != A_OK) { - AR_DEBUG_PRINTF(ATH_LOG_ERR, ("Cannot read from WINDOW_DATA_ADDRESS\n")); - return status; - } - - return status; -} - - -/* - * Write to the AR6000 through its diagnostic window. - * No cooperation from the Target is required for this. - */ -A_STATUS -ar6000_WriteRegDiag(HIF_DEVICE *hifDevice, A_UINT32 *address, A_UINT32 *data) -{ - A_STATUS status; - - /* set write data */ - status = HIFReadWrite(hifDevice, - WINDOW_DATA_ADDRESS, - (A_UCHAR *)data, - sizeof(A_UINT32), - HIF_WR_SYNC_BYTE_INC, - NULL); - if (status != A_OK) { - AR_DEBUG_PRINTF(ATH_LOG_ERR, ("Cannot write 0x%x to WINDOW_DATA_ADDRESS\n", *data)); - return status; - } - - /* set window register, which starts the write cycle */ - return ar6000_SetAddressWindowRegister(hifDevice, - WINDOW_WRITE_ADDR_ADDRESS, - *address); -} - -A_STATUS -ar6000_ReadDataDiag(HIF_DEVICE *hifDevice, A_UINT32 address, - A_UCHAR *data, A_UINT32 length) -{ - A_UINT32 count; - A_STATUS status = A_OK; - - for (count = 0; count < length; count += 4, address += 4) { - if ((status = ar6000_ReadRegDiag(hifDevice, &address, - (A_UINT32 *)&data[count])) != A_OK) - { - break; - } - } - - return status; -} - -A_STATUS -ar6000_WriteDataDiag(HIF_DEVICE *hifDevice, A_UINT32 address, - A_UCHAR *data, A_UINT32 length) -{ - A_UINT32 count; - A_STATUS status = A_OK; - - for (count = 0; count < length; count += 4, address += 4) { - if ((status = ar6000_WriteRegDiag(hifDevice, &address, - (A_UINT32 *)&data[count])) != A_OK) - { - break; - } - } - - return status; -} - -A_STATUS -ar6000_reset_device_skipflash(HIF_DEVICE *hifDevice) -{ - int i; - struct forceROM_s { - A_UINT32 addr; - A_UINT32 data; - }; - struct forceROM_s *ForceROM; - int szForceROM; - A_UINT32 instruction; - - static struct forceROM_s ForceROM_REV2[] = { - /* NB: This works for old REV2 ROM (old). */ - {0x00001ff0, 0x175b0027}, /* jump instruction at 0xa0001ff0 */ - {0x00001ff4, 0x00000000}, /* nop instruction at 0xa0001ff4 */ - - {MC_REMAP_TARGET_ADDRESS, 0x00001ff0}, /* remap to 0xa0001ff0 */ - {MC_REMAP_COMPARE_ADDRESS, 0x01000040},/* ...from 0xbfc00040 */ - {MC_REMAP_SIZE_ADDRESS, 0x00000000}, /* ...1 cache line */ - {MC_REMAP_VALID_ADDRESS, 0x00000001}, /* ...remap is valid */ - - {LOCAL_COUNT_ADDRESS+0x10, 0}, /* clear BMI credit counter */ - - {RESET_CONTROL_ADDRESS, RESET_CONTROL_WARM_RST_MASK}, - }; - - static struct forceROM_s ForceROM_NEW[] = { - /* NB: This works for AR6000 ROM REV3 and beyond. */ - {LOCAL_SCRATCH_ADDRESS, AR6K_OPTION_IGNORE_FLASH}, - {LOCAL_COUNT_ADDRESS+0x10, 0}, /* clear BMI credit counter */ - {RESET_CONTROL_ADDRESS, RESET_CONTROL_WARM_RST_MASK}, - }; - - /* - * Examine a semi-arbitrary instruction that's different - * in REV2 and other revisions. - * NB: If a Host port does not require simultaneous support - * for multiple revisions of Target ROM, this code can be elided. - */ - (void)ar6000_ReadDataDiag(hifDevice, 0x01000040, - (A_UCHAR *)&instruction, 4); - - AR_DEBUG_PRINTF(ATH_LOG_ERR, ("instruction=0x%x\n", instruction)); - - if (instruction == 0x3c1aa200) { - /* It's an old ROM */ - ForceROM = ForceROM_REV2; - szForceROM = sizeof(ForceROM_REV2)/sizeof(*ForceROM); - AR_DEBUG_PRINTF(ATH_LOG_ERR, ("Using OLD method\n")); - } else { - ForceROM = ForceROM_NEW; - szForceROM = sizeof(ForceROM_NEW)/sizeof(*ForceROM); - AR_DEBUG_PRINTF(ATH_LOG_ERR, ("Using NEW method\n")); - } - - AR_DEBUG_PRINTF(ATH_LOG_ERR, ("Force Target to execute from ROM....\n")); - for (i = 0; i < szForceROM; i++) - { - if (ar6000_WriteRegDiag(hifDevice, - &ForceROM[i].addr, - &ForceROM[i].data) != A_OK) - { - AR_DEBUG_PRINTF(ATH_LOG_ERR, ("Cannot force Target to execute ROM!\n")); - return A_ERROR; - } - } - - msleep(50); /* delay to allow dragon to come to BMI phase */ - return A_OK; -} - -/* reset device */ -A_STATUS ar6000_reset_device(HIF_DEVICE *hifDevice, A_UINT32 TargetType) -{ - -#if !defined(DWSIM) - A_STATUS status = A_OK; - A_UINT32 address; - A_UINT32 data; - - do { - - // address = RESET_CONTROL_ADDRESS; - data = RESET_CONTROL_COLD_RST_MASK; - - /* Hardcode the address of RESET_CONTROL_ADDRESS based on the target type */ - if (TargetType == TARGET_TYPE_AR6001) { - address = 0x0C000000; - } else { - if (TargetType == TARGET_TYPE_AR6002) { - address = 0x00004000; - } else { - A_ASSERT(0); - } - } - - status = ar6000_WriteRegDiag(hifDevice, &address, &data); - - if (A_FAILED(status)) { - break; - } - - /* - * Read back the RESET CAUSE register to ensure that the cold reset - * went through. - */ - msleep(2000); /* 2 second delay to allow things to settle down */ - - - // address = RESET_CAUSE_ADDRESS; - /* Hardcode the address of RESET_CAUSE_ADDRESS based on the target type */ - if (TargetType == TARGET_TYPE_AR6001) { - address = 0x0C0000CC; - } else { - if (TargetType == TARGET_TYPE_AR6002) { - address = 0x000040C0; - } else { - A_ASSERT(0); - } - } - - data = 0; - status = ar6000_ReadRegDiag(hifDevice, &address, &data); - - if (A_FAILED(status)) { - break; - } - - AR_DEBUG_PRINTF(ATH_LOG_ERR, ("Reset Cause readback: 0x%X \n",data)); - data &= RESET_CAUSE_LAST_MASK; - if (data != 2) { - AR_DEBUG_PRINTF(ATH_LOG_ERR, ("Unable to cold reset the target \n")); - } - - } while (FALSE); - - if (A_FAILED(status)) { - AR_DEBUG_PRINTF(ATH_LOG_ERR, ("Failed to reset target \n")); - } -#endif - return A_OK; -} - -#define REG_DUMP_COUNT_AR6001 38 /* WORDs, derived from AR6001_regdump.h */ -#define REG_DUMP_COUNT_AR6002 32 /* WORDs, derived from AR6002_regdump.h */ - - -#if REG_DUMP_COUNT_AR6001 <= REG_DUMP_COUNT_AR6002 -#define REGISTER_DUMP_LEN_MAX REG_DUMP_COUNT_AR6002 -#else -#define REGISTER_DUMP_LEN_MAX REG_DUMP_COUNT_AR6001 -#endif - -void ar6000_dump_target_assert_info(HIF_DEVICE *hifDevice, A_UINT32 TargetType) -{ - A_UINT32 address; - A_UINT32 regDumpArea = 0; - A_STATUS status; - A_UINT32 regDumpValues[REGISTER_DUMP_LEN_MAX]; - A_UINT32 regDumpCount = 0; - A_UINT32 i; - - do { - - /* the reg dump pointer is copied to the host interest area */ - address = HOST_INTEREST_ITEM_ADDRESS(TargetType, hi_failure_state); - - if (TargetType == TARGET_TYPE_AR6001) { - /* for AR6001, this is a fixed location because the ptr is actually stuck in cache, - * this may be fixed in later firmware versions */ - address = 0x18a0; - regDumpCount = REG_DUMP_COUNT_AR6001; - - } else if (TargetType == TARGET_TYPE_AR6002) { - - regDumpCount = REG_DUMP_COUNT_AR6002; - - } else { - A_ASSERT(0); - } - - /* read RAM location through diagnostic window */ - status = ar6000_ReadRegDiag(hifDevice, &address, ®DumpArea); - - if (A_FAILED(status)) { - AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("AR6K: Failed to get ptr to register dump area \n")); - break; - } - - AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("AR6K: Location of register dump data: 0x%X \n",regDumpArea)); - - if (regDumpArea == 0) { - /* no reg dump */ - break; - } - - if (TargetType == TARGET_TYPE_AR6001) { - regDumpArea &= 0x0FFFFFFF; /* convert to physical address in target memory */ - } - - /* fetch register dump data */ - status = ar6000_ReadDataDiag(hifDevice, - regDumpArea, - (A_UCHAR *)®DumpValues[0], - regDumpCount * (sizeof(A_UINT32))); - - if (A_FAILED(status)) { - AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("AR6K: Failed to get register dump \n")); - break; - } - - AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("AR6K: Register Dump: \n")); - - for (i = 0; i < regDumpCount; i++) { - AR_DEBUG_PRINTF(ATH_DEBUG_ERR,(" %d : 0x%8.8X \n",i, regDumpValues[i])); - } - - } while (FALSE); - -} - diff --git a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/miscdrv/credit_dist.c b/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/miscdrv/credit_dist.c deleted file mode 100644 index 8d37d6272..000000000 --- a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/miscdrv/credit_dist.c +++ /dev/null @@ -1,346 +0,0 @@ - -/* - * - * Copyright (c) 2004-2007 Atheros Communications Inc. - * All rights reserved. - * - * - * 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; - * - * Software distributed under the License is distributed on an "AS - * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or - * implied. See the License for the specific language governing - * rights and limitations under the License. - * - * - * - */ - -#include "a_config.h" -#include "athdefs.h" -#include "a_types.h" -#include "a_osapi.h" -#include "a_debug.h" -#include "htc_api.h" -#include "common_drv.h" - -/********* CREDIT DISTRIBUTION FUNCTIONS ******************************************/ - -#define NO_VO_SERVICE 1 /* currently WMI only uses 3 data streams, so we leave VO service inactive */ - -#ifdef NO_VO_SERVICE -#define DATA_SVCS_USED 3 -#else -#define DATA_SVCS_USED 4 -#endif - -static void RedistributeCredits(COMMON_CREDIT_STATE_INFO *pCredInfo, - HTC_ENDPOINT_CREDIT_DIST *pEPDistList); - -static void SeekCredits(COMMON_CREDIT_STATE_INFO *pCredInfo, - HTC_ENDPOINT_CREDIT_DIST *pEPDistList); - -/* reduce an ep's credits back to a set limit */ -static INLINE void ReduceCredits(COMMON_CREDIT_STATE_INFO *pCredInfo, - HTC_ENDPOINT_CREDIT_DIST *pEpDist, - int Limit) -{ - int credits; - - /* set the new limit */ - pEpDist->TxCreditsAssigned = Limit; - - if (pEpDist->TxCredits <= Limit) { - return; - } - - /* figure out how much to take away */ - credits = pEpDist->TxCredits - Limit; - /* take them away */ - pEpDist->TxCredits -= credits; - pCredInfo->CurrentFreeCredits += credits; -} - -/* give an endpoint some credits from the free credit pool */ -#define GiveCredits(pCredInfo,pEpDist,credits) \ -{ \ - (pEpDist)->TxCredits += (credits); \ - (pEpDist)->TxCreditsAssigned += (credits); \ - (pCredInfo)->CurrentFreeCredits -= (credits); \ -} - - -/* default credit init callback. - * This function is called in the context of HTCStart() to setup initial (application-specific) - * credit distributions */ -static void ar6000_credit_init(void *Context, - HTC_ENDPOINT_CREDIT_DIST *pEPList, - int TotalCredits) -{ - HTC_ENDPOINT_CREDIT_DIST *pCurEpDist; - int count; - COMMON_CREDIT_STATE_INFO *pCredInfo = (COMMON_CREDIT_STATE_INFO *)Context; - - pCredInfo->CurrentFreeCredits = TotalCredits; - pCredInfo->TotalAvailableCredits = TotalCredits; - - pCurEpDist = pEPList; - - /* run through the list and initialize */ - while (pCurEpDist != NULL) { - - /* set minimums for each endpoint */ - pCurEpDist->TxCreditsMin = pCurEpDist->TxCreditsPerMaxMsg; - - if (pCurEpDist->ServiceID == WMI_CONTROL_SVC) { - /* give control service some credits */ - GiveCredits(pCredInfo,pCurEpDist,pCurEpDist->TxCreditsMin); - /* control service is always marked active, it never goes inactive EVER */ - SET_EP_ACTIVE(pCurEpDist); - } else if (pCurEpDist->ServiceID == WMI_DATA_BK_SVC) { - /* this is the lowest priority data endpoint, save this off for easy access */ - pCredInfo->pLowestPriEpDist = pCurEpDist; - } - - /* Streams have to be created (explicit | implicit)for all kinds - * of traffic. BE endpoints are also inactive in the beginning. - * When BE traffic starts it creates implicit streams that - * redistributes credits. - */ - - /* note, all other endpoints have minimums set but are initially given NO credits. - * Credits will be distributed as traffic activity demands */ - pCurEpDist = pCurEpDist->pNext; - } - - if (pCredInfo->CurrentFreeCredits <= 0) { - AR_DEBUG_PRINTF(ATH_LOG_INF, ("Not enough credits (%d) to do credit distributions \n", TotalCredits)); - A_ASSERT(FALSE); - return; - } - - /* reset list */ - pCurEpDist = pEPList; - /* now run through the list and set max operating credit limits for everyone */ - while (pCurEpDist != NULL) { - if (pCurEpDist->ServiceID == WMI_CONTROL_SVC) { - /* control service max is just 1 max message */ - pCurEpDist->TxCreditsNorm = pCurEpDist->TxCreditsPerMaxMsg; - } else { - /* for the remaining data endpoints, we assume that each TxCreditsPerMaxMsg are - * the same. - * We use a simple calculation here, we take the remaining credits and - * determine how many max messages this can cover and then set each endpoint's - * normal value equal to half this amount. - * */ - count = (pCredInfo->CurrentFreeCredits/pCurEpDist->TxCreditsPerMaxMsg) * pCurEpDist->TxCreditsPerMaxMsg; - count = count >> 1; - count = max(count,pCurEpDist->TxCreditsPerMaxMsg); - /* set normal */ - pCurEpDist->TxCreditsNorm = count; - - } - pCurEpDist = pCurEpDist->pNext; - } - -} - - -/* default credit distribution callback - * This callback is invoked whenever endpoints require credit distributions. - * A lock is held while this function is invoked, this function shall NOT block. - * The pEPDistList is a list of distribution structures in prioritized order as - * defined by the call to the HTCSetCreditDistribution() api. - * - */ -static void ar6000_credit_distribute(void *Context, - HTC_ENDPOINT_CREDIT_DIST *pEPDistList, - HTC_CREDIT_DIST_REASON Reason) -{ - HTC_ENDPOINT_CREDIT_DIST *pCurEpDist; - COMMON_CREDIT_STATE_INFO *pCredInfo = (COMMON_CREDIT_STATE_INFO *)Context; - - switch (Reason) { - case HTC_CREDIT_DIST_SEND_COMPLETE : - pCurEpDist = pEPDistList; - /* we are given the start of the endpoint distribution list. - * There may be one or more endpoints to service. - * Run through the list and distribute credits */ - while (pCurEpDist != NULL) { - - if (pCurEpDist->TxCreditsToDist > 0) { - /* return the credits back to the endpoint */ - pCurEpDist->TxCredits += pCurEpDist->TxCreditsToDist; - /* always zero out when we are done */ - pCurEpDist->TxCreditsToDist = 0; - - if (pCurEpDist->TxCredits > pCurEpDist->TxCreditsAssigned) { - /* reduce to the assigned limit, previous credit reductions - * could have caused the limit to change */ - ReduceCredits(pCredInfo, pCurEpDist, pCurEpDist->TxCreditsAssigned); - } - - if (pCurEpDist->TxCredits > pCurEpDist->TxCreditsNorm) { - /* oversubscribed endpoints need to reduce back to normal */ - ReduceCredits(pCredInfo, pCurEpDist, pCurEpDist->TxCreditsNorm); - } - } - - pCurEpDist = pCurEpDist->pNext; - } - - A_ASSERT(pCredInfo->CurrentFreeCredits <= pCredInfo->TotalAvailableCredits); - - break; - - case HTC_CREDIT_DIST_ACTIVITY_CHANGE : - RedistributeCredits(pCredInfo,pEPDistList); - break; - case HTC_CREDIT_DIST_SEEK_CREDITS : - SeekCredits(pCredInfo,pEPDistList); - break; - case HTC_DUMP_CREDIT_STATE : - AR_DEBUG_PRINTF(ATH_LOG_INF, ("Credit Distribution, total : %d, free : %d\n", - pCredInfo->TotalAvailableCredits, pCredInfo->CurrentFreeCredits)); - break; - default: - break; - - } - -} - -/* redistribute credits based on activity change */ -static void RedistributeCredits(COMMON_CREDIT_STATE_INFO *pCredInfo, - HTC_ENDPOINT_CREDIT_DIST *pEPDistList) -{ - HTC_ENDPOINT_CREDIT_DIST *pCurEpDist = pEPDistList; - - /* walk through the list and remove credits from inactive endpoints */ - while (pCurEpDist != NULL) { - - if (pCurEpDist->ServiceID != WMI_CONTROL_SVC) { - if (!IS_EP_ACTIVE(pCurEpDist)) { - /* EP is inactive, reduce credits back to zero */ - ReduceCredits(pCredInfo, pCurEpDist, 0); - } - } - - /* NOTE in the active case, we do not need to do anything further, - * when an EP goes active and needs credits, HTC will call into - * our distribution function using a reason code of HTC_CREDIT_DIST_SEEK_CREDITS */ - - pCurEpDist = pCurEpDist->pNext; - } - - A_ASSERT(pCredInfo->CurrentFreeCredits <= pCredInfo->TotalAvailableCredits); - -} - -/* HTC has an endpoint that needs credits, pEPDist is the endpoint in question */ -static void SeekCredits(COMMON_CREDIT_STATE_INFO *pCredInfo, - HTC_ENDPOINT_CREDIT_DIST *pEPDist) -{ - HTC_ENDPOINT_CREDIT_DIST *pCurEpDist; - int credits = 0; - int need; - - do { - - if (pEPDist->ServiceID == WMI_CONTROL_SVC) { - /* we never oversubscribe on the control service, this is not - * a high performance path and the target never holds onto control - * credits for too long */ - break; - } - - /* for all other services, we follow a simple algorithm of - * 1. checking the free pool for credits - * 2. checking lower priority endpoints for credits to take */ - - if (pCredInfo->CurrentFreeCredits >= 2 * pEPDist->TxCreditsSeek) { - /* try to give more credits than it needs */ - credits = 2 * pEPDist->TxCreditsSeek; - } else { - /* give what we can */ - credits = min(pCredInfo->CurrentFreeCredits,pEPDist->TxCreditsSeek); - } - - if (credits >= pEPDist->TxCreditsSeek) { - /* we found some to fullfill the seek request */ - break; - } - - /* we don't have enough in the free pool, try taking away from lower priority services - * - * The rule for taking away credits: - * 1. Only take from lower priority endpoints - * 2. Only take what is allocated above the minimum (never starve an endpoint completely) - * 3. Only take what you need. - * - * */ - - /* starting at the lowest priority */ - pCurEpDist = pCredInfo->pLowestPriEpDist; - - /* work backwards until we hit the endpoint again */ - while (pCurEpDist != pEPDist) { - /* calculate how many we need so far */ - need = pEPDist->TxCreditsSeek - pCredInfo->CurrentFreeCredits; - - if ((pCurEpDist->TxCreditsAssigned - need) > pCurEpDist->TxCreditsMin) { - /* the current one has been allocated more than it's minimum and it - * has enough credits assigned above it's minimum to fullfill our need - * try to take away just enough to fullfill our need */ - ReduceCredits(pCredInfo, - pCurEpDist, - pCurEpDist->TxCreditsAssigned - need); - - if (pCredInfo->CurrentFreeCredits >= pEPDist->TxCreditsSeek) { - /* we have enough */ - break; - } - } - - pCurEpDist = pCurEpDist->pPrev; - } - - /* return what we can get */ - credits = min(pCredInfo->CurrentFreeCredits,pEPDist->TxCreditsSeek); - - } while (FALSE); - - /* did we find some credits? */ - if (credits) { - /* give what we can */ - GiveCredits(pCredInfo, pEPDist, credits); - } - -} - -/* initialize and setup credit distribution */ -A_STATUS ar6000_setup_credit_dist(HTC_HANDLE HTCHandle, COMMON_CREDIT_STATE_INFO *pCredInfo) -{ - HTC_SERVICE_ID servicepriority[5]; - - A_MEMZERO(pCredInfo,sizeof(COMMON_CREDIT_STATE_INFO)); - - servicepriority[0] = WMI_CONTROL_SVC; /* highest */ - servicepriority[1] = WMI_DATA_VO_SVC; - servicepriority[2] = WMI_DATA_VI_SVC; - servicepriority[3] = WMI_DATA_BE_SVC; - servicepriority[4] = WMI_DATA_BK_SVC; /* lowest */ - - /* set callbacks and priority list */ - HTCSetCreditDistribution(HTCHandle, - pCredInfo, - ar6000_credit_distribute, - ar6000_credit_init, - servicepriority, - 5); - - return A_OK; -} - diff --git a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/wlan/wlan_node.c b/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/wlan/wlan_node.c deleted file mode 100644 index b12484597..000000000 --- a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/wlan/wlan_node.c +++ /dev/null @@ -1,371 +0,0 @@ -/*- - * Copyright (c) 2001 Atsushi Onoe - * Copyright (c) 2002-2004 Sam Leffler, Errno Consulting - * Copyright (c) 2004-2005 Atheros Communications - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $Id: //depot/sw/releases/olca2.0-GPL/host/wlan/src/wlan_node.c#1 $ - */ -/* - * IEEE 802.11 node handling support. - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -static void wlan_node_timeout(A_ATH_TIMER arg); -static bss_t * _ieee80211_find_node(struct ieee80211_node_table *nt, - const A_UINT8 *macaddr); - -bss_t * -wlan_node_alloc(struct ieee80211_node_table *nt, int wh_size) -{ - bss_t *ni; - - ni = A_MALLOC_NOWAIT(sizeof(bss_t)); - - if (ni != NULL) { - ni->ni_buf = A_MALLOC_NOWAIT(wh_size); - if (ni->ni_buf == NULL) { - A_FREE(ni); - ni = NULL; - return ni; - } - } else { - return ni; - } - - /* Make sure our lists are clean */ - ni->ni_list_next = NULL; - ni->ni_list_prev = NULL; - ni->ni_hash_next = NULL; - ni->ni_hash_prev = NULL; - - // - // ni_scangen never initialized before and during suspend/resume of winmobile, customer (LG/SEMCO) identified - // that some junk has been stored in this, due to this scan list didn't properly updated - // - ni->ni_scangen = 0; - - return ni; -} - -void -wlan_node_free(bss_t *ni) -{ - if (ni->ni_buf != NULL) { - A_FREE(ni->ni_buf); - } - A_FREE(ni); -} - -void -wlan_setup_node(struct ieee80211_node_table *nt, bss_t *ni, - const A_UINT8 *macaddr) -{ - int hash; - - A_MEMCPY(ni->ni_macaddr, macaddr, IEEE80211_ADDR_LEN); - hash = IEEE80211_NODE_HASH(macaddr); - ieee80211_node_initref(ni); /* mark referenced */ - - ni->ni_tstamp = A_GET_MS(WLAN_NODE_INACT_TIMEOUT_MSEC); - IEEE80211_NODE_LOCK_BH(nt); - - /* Insert at the end of the node list */ - ni->ni_list_next = NULL; - ni->ni_list_prev = nt->nt_node_last; - if(nt->nt_node_last != NULL) - { - nt->nt_node_last->ni_list_next = ni; - } - nt->nt_node_last = ni; - if(nt->nt_node_first == NULL) - { - nt->nt_node_first = ni; - } - - /* Insert into the hash list i.e. the bucket */ - if((ni->ni_hash_next = nt->nt_hash[hash]) != NULL) - { - nt->nt_hash[hash]->ni_hash_prev = ni; - } - ni->ni_hash_prev = NULL; - nt->nt_hash[hash] = ni; - - if (!nt->isTimerArmed) { - A_TIMEOUT_MS(&nt->nt_inact_timer, WLAN_NODE_INACT_TIMEOUT_MSEC, 0); - nt->isTimerArmed = TRUE; - } - - IEEE80211_NODE_UNLOCK_BH(nt); -} - -static bss_t * -_ieee80211_find_node(struct ieee80211_node_table *nt, - const A_UINT8 *macaddr) -{ - bss_t *ni; - int hash; - - IEEE80211_NODE_LOCK_ASSERT(nt); - - hash = IEEE80211_NODE_HASH(macaddr); - for(ni = nt->nt_hash[hash]; ni; ni = ni->ni_hash_next) { - if (IEEE80211_ADDR_EQ(ni->ni_macaddr, macaddr)) { - ieee80211_node_incref(ni); /* mark referenced */ - return ni; - } - } - return NULL; -} - -bss_t * -wlan_find_node(struct ieee80211_node_table *nt, const A_UINT8 *macaddr) -{ - bss_t *ni; - - IEEE80211_NODE_LOCK(nt); - ni = _ieee80211_find_node(nt, macaddr); - IEEE80211_NODE_UNLOCK(nt); - return ni; -} - -/* - * Reclaim a node. If this is the last reference count then - * do the normal free work. Otherwise remove it from the node - * table and mark it gone by clearing the back-reference. - */ -void -wlan_node_reclaim(struct ieee80211_node_table *nt, bss_t *ni) -{ - IEEE80211_NODE_LOCK(nt); - - if(ni->ni_list_prev == NULL) - { - /* First in list so fix the list head */ - nt->nt_node_first = ni->ni_list_next; - } - else - { - ni->ni_list_prev->ni_list_next = ni->ni_list_next; - } - - if(ni->ni_list_next == NULL) - { - /* Last in list so fix list tail */ - nt->nt_node_last = ni->ni_list_prev; - } - else - { - ni->ni_list_next->ni_list_prev = ni->ni_list_prev; - } - - if(ni->ni_hash_prev == NULL) - { - /* First in list so fix the list head */ - int hash; - hash = IEEE80211_NODE_HASH(ni->ni_macaddr); - nt->nt_hash[hash] = ni->ni_hash_next; - } - else - { - ni->ni_hash_prev->ni_hash_next = ni->ni_hash_next; - } - - if(ni->ni_hash_next != NULL) - { - ni->ni_hash_next->ni_hash_prev = ni->ni_hash_prev; - } - wlan_node_free(ni); - - IEEE80211_NODE_UNLOCK(nt); -} - -static void -wlan_node_dec_free(bss_t *ni) -{ - if (ieee80211_node_dectestref(ni)) { - wlan_node_free(ni); - } -} - -void -wlan_free_allnodes(struct ieee80211_node_table *nt) -{ - bss_t *ni; - - while ((ni = nt->nt_node_first) != NULL) { - wlan_node_reclaim(nt, ni); - } -} - -void -wlan_iterate_nodes(struct ieee80211_node_table *nt, wlan_node_iter_func *f, - void *arg) -{ - bss_t *ni; - A_UINT32 gen; - - gen = ++nt->nt_scangen; - - IEEE80211_NODE_LOCK(nt); - for (ni = nt->nt_node_first; ni; ni = ni->ni_list_next) { - if (ni->ni_scangen != gen) { - ni->ni_scangen = gen; - (void) ieee80211_node_incref(ni); - (*f)(arg, ni); - wlan_node_dec_free(ni); - } - } - IEEE80211_NODE_UNLOCK(nt); -} - -/* - * Node table support. - */ -void -wlan_node_table_init(void *wmip, struct ieee80211_node_table *nt) -{ - int i; - - AR_DEBUG_PRINTF(ATH_DEBUG_WLAN, ("node table = 0x%x\n", (A_UINT32)nt)); - IEEE80211_NODE_LOCK_INIT(nt); - - nt->nt_node_first = nt->nt_node_last = NULL; - for(i = 0; i < IEEE80211_NODE_HASHSIZE; i++) - { - nt->nt_hash[i] = NULL; - } - A_INIT_TIMER(&nt->nt_inact_timer, wlan_node_timeout, nt); - nt->isTimerArmed = FALSE; - nt->nt_wmip = wmip; -} - -static void -wlan_node_timeout(A_ATH_TIMER arg) -{ - struct ieee80211_node_table *nt = (struct ieee80211_node_table *)arg; - bss_t *bss, *nextBss; - A_UINT8 myBssid[IEEE80211_ADDR_LEN], reArmTimer = FALSE; - - wmi_get_current_bssid(nt->nt_wmip, myBssid); - - bss = nt->nt_node_first; - while (bss != NULL) - { - nextBss = bss->ni_list_next; - if (A_MEMCMP(myBssid, bss->ni_macaddr, sizeof(myBssid)) != 0) - { - - if (bss->ni_tstamp <= A_GET_MS(0)) - { - /* - * free up all but the current bss - if set - */ - wlan_node_reclaim(nt, bss); - } - else - { - /* - * Re-arm timer, only when we have a bss other than - * current bss AND it is not aged-out. - */ - reArmTimer = TRUE; - } - } - bss = nextBss; - } - - if(reArmTimer) - A_TIMEOUT_MS(&nt->nt_inact_timer, WLAN_NODE_INACT_TIMEOUT_MSEC, 0); - - nt->isTimerArmed = reArmTimer; -} - -void -wlan_node_table_cleanup(struct ieee80211_node_table *nt) -{ - A_UNTIMEOUT(&nt->nt_inact_timer); - A_DELETE_TIMER(&nt->nt_inact_timer); - wlan_free_allnodes(nt); - IEEE80211_NODE_LOCK_DESTROY(nt); -} - -bss_t * -wlan_find_Ssidnode (struct ieee80211_node_table *nt, A_UCHAR *pSsid, - A_UINT32 ssidLength, A_BOOL bIsWPA2) -{ - bss_t *ni = NULL; - A_UCHAR *pIESsid = NULL; - - IEEE80211_NODE_LOCK (nt); - - for (ni = nt->nt_node_first; ni; ni = ni->ni_list_next) { - pIESsid = ni->ni_cie.ie_ssid; - if (pIESsid[1] <= 32) { - - // Step 1 : Check SSID - if (0x00 == memcmp (pSsid, &pIESsid[2], ssidLength)) { - - // Step 2 : if SSID matches, check WPA or WPA2 - if (TRUE == bIsWPA2 && NULL != ni->ni_cie.ie_rsn) { - ieee80211_node_incref (ni); /* mark referenced */ - IEEE80211_NODE_UNLOCK (nt); - return ni; - } - if (FALSE == bIsWPA2 && NULL != ni->ni_cie.ie_wpa) { - ieee80211_node_incref(ni); /* mark referenced */ - IEEE80211_NODE_UNLOCK (nt); - return ni; - } - } - } - } - - IEEE80211_NODE_UNLOCK (nt); - - return NULL; -} - -void -wlan_node_return (struct ieee80211_node_table *nt, bss_t *ni) -{ - IEEE80211_NODE_LOCK (nt); - wlan_node_dec_free (ni); - IEEE80211_NODE_UNLOCK (nt); -} diff --git a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/wlan/wlan_recv_beacon.c b/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/wlan/wlan_recv_beacon.c deleted file mode 100644 index 15beabb65..000000000 --- a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/wlan/wlan_recv_beacon.c +++ /dev/null @@ -1,192 +0,0 @@ -/*- - * Copyright (c) 2001 Atsushi Onoe - * Copyright (c) 2002-2004 Sam Leffler, Errno Consulting - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* - * IEEE 802.11 input handling. - */ - -#include "a_config.h" -#include "athdefs.h" -#include "a_types.h" -#include "a_osapi.h" -#include -#include -#include - -#define IEEE80211_VERIFY_LENGTH(_len, _minlen) do { \ - if ((_len) < (_minlen)) { \ - return A_EINVAL; \ - } \ -} while (0) - -#define IEEE80211_VERIFY_ELEMENT(__elem, __maxlen) do { \ - if ((__elem) == NULL) { \ - return A_EINVAL; \ - } \ - if ((__elem)[1] > (__maxlen)) { \ - return A_EINVAL; \ - } \ -} while (0) - - -/* unaligned little endian access */ -#define LE_READ_2(p) \ - ((A_UINT16) \ - ((((A_UINT8 *)(p))[0] ) | (((A_UINT8 *)(p))[1] << 8))) - -#define LE_READ_4(p) \ - ((A_UINT32) \ - ((((A_UINT8 *)(p))[0] ) | (((A_UINT8 *)(p))[1] << 8) | \ - (((A_UINT8 *)(p))[2] << 16) | (((A_UINT8 *)(p))[3] << 24))) - - -static int __inline -iswpaoui(const A_UINT8 *frm) -{ - return frm[1] > 3 && LE_READ_4(frm+2) == ((WPA_OUI_TYPE<<24)|WPA_OUI); -} - -static int __inline -iswmmoui(const A_UINT8 *frm) -{ - return frm[1] > 3 && LE_READ_4(frm+2) == ((WMM_OUI_TYPE<<24)|WMM_OUI); -} - -static int __inline -iswmmparam(const A_UINT8 *frm) -{ - return frm[1] > 5 && frm[6] == WMM_PARAM_OUI_SUBTYPE; -} - -static int __inline -iswmminfo(const A_UINT8 *frm) -{ - return frm[1] > 5 && frm[6] == WMM_INFO_OUI_SUBTYPE; -} - -static int __inline -isatherosoui(const A_UINT8 *frm) -{ - return frm[1] > 3 && LE_READ_4(frm+2) == ((ATH_OUI_TYPE<<24)|ATH_OUI); -} - -static int __inline -iswscoui(const A_UINT8 *frm) -{ - return frm[1] > 3 && LE_READ_4(frm+2) == ((0x04<<24)|WPA_OUI); -} - -A_STATUS -wlan_parse_beacon(A_UINT8 *buf, int framelen, struct ieee80211_common_ie *cie) -{ - A_UINT8 *frm, *efrm; - - frm = buf; - efrm = (A_UINT8 *) (frm + framelen); - - /* - * beacon/probe response frame format - * [8] time stamp - * [2] beacon interval - * [2] capability information - * [tlv] ssid - * [tlv] supported rates - * [tlv] country information - * [tlv] parameter set (FH/DS) - * [tlv] erp information - * [tlv] extended supported rates - * [tlv] WMM - * [tlv] WPA or RSN - * [tlv] Atheros Advanced Capabilities - */ - IEEE80211_VERIFY_LENGTH(efrm - frm, 12); - A_MEMZERO(cie, sizeof(*cie)); - - cie->ie_tstamp = frm; frm += 8; - cie->ie_beaconInt = A_LE2CPU16(*(A_UINT16 *)frm); frm += 2; - cie->ie_capInfo = A_LE2CPU16(*(A_UINT16 *)frm); frm += 2; - cie->ie_chan = 0; - - while (frm < efrm) { - switch (*frm) { - case IEEE80211_ELEMID_SSID: - cie->ie_ssid = frm; - break; - case IEEE80211_ELEMID_RATES: - cie->ie_rates = frm; - break; - case IEEE80211_ELEMID_COUNTRY: - cie->ie_country = frm; - break; - case IEEE80211_ELEMID_FHPARMS: - break; - case IEEE80211_ELEMID_DSPARMS: - cie->ie_chan = frm[2]; - break; - case IEEE80211_ELEMID_TIM: - cie->ie_tim = frm; - break; - case IEEE80211_ELEMID_IBSSPARMS: - break; - case IEEE80211_ELEMID_XRATES: - cie->ie_xrates = frm; - break; - case IEEE80211_ELEMID_ERP: - if (frm[1] != 1) { - //A_PRINTF("Discarding ERP Element - Bad Len\n"); - return A_EINVAL; - } - cie->ie_erp = frm[2]; - break; - case IEEE80211_ELEMID_RSN: - cie->ie_rsn = frm; - break; - case IEEE80211_ELEMID_VENDOR: - if (iswpaoui(frm)) { - cie->ie_wpa = frm; - } else if (iswmmoui(frm)) { - cie->ie_wmm = frm; - } else if (isatherosoui(frm)) { - cie->ie_ath = frm; - } else if(iswscoui(frm)) { - cie->ie_wsc = frm; - } - break; - default: - break; - } - frm += frm[1] + 2; - } - IEEE80211_VERIFY_ELEMENT(cie->ie_rates, IEEE80211_RATE_MAXSIZE); - IEEE80211_VERIFY_ELEMENT(cie->ie_ssid, IEEE80211_NWID_LEN); - - return A_OK; -} diff --git a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/wlan/wlan_utils.c b/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/wlan/wlan_utils.c deleted file mode 100644 index fd5aac90e..000000000 --- a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/wlan/wlan_utils.c +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (c) 2004-2005 Atheros Communications Inc. - * All rights reserved. - * - * This module implements frequently used wlan utilies - * - * $Id: //depot/sw/releases/olca2.0-GPL/host/wlan/src/wlan_utils.c#1 $ - * - * - * 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; - * - * Software distributed under the License is distributed on an "AS - * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or - * implied. See the License for the specific language governing - * rights and limitations under the License. - * - * - * - */ - -#include -#include -#include -#include - -/* - * converts ieee channel number to frequency - */ -A_UINT16 -wlan_ieee2freq(int chan) -{ - if (chan == 14) { - return 2484; - } - if (chan < 14) { /* 0-13 */ - return (2407 + (chan*5)); - } - if (chan < 27) { /* 15-26 */ - return (2512 + ((chan-15)*20)); - } - return (5000 + (chan*5)); -} - -/* - * Converts MHz frequency to IEEE channel number. - */ -A_UINT32 -wlan_freq2ieee(A_UINT16 freq) -{ - if (freq == 2484) - return 14; - if (freq < 2484) - return (freq - 2407) / 5; - if (freq < 5000) - return 15 + ((freq - 2512) / 20); - return (freq - 5000) / 5; -} diff --git a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/wmi/wmi.c b/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/wmi/wmi.c deleted file mode 100644 index d322cf3f5..000000000 --- a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/wmi/wmi.c +++ /dev/null @@ -1,3954 +0,0 @@ -/* - * Copyright (c) 2004-2007 Atheros Communications Inc. - * All rights reserved. - * - * This module implements the hardware independent layer of the - * Wireless Module Interface (WMI) protocol. - * - * $Id: //depot/sw/releases/olca2.0-GPL/host/wmi/wmi.c#3 $ - * - * - * 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; - * - * Software distributed under the License is distributed on an "AS - * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or - * implied. See the License for the specific language governing - * rights and limitations under the License. - * - * - * - */ - -#include -#include -#include -#include -#include "htc.h" -#include "htc_api.h" -#include "wmi.h" -#include -#include -#include -#include -#include "dset_api.h" -#include "gpio_api.h" -#include "wmi_host.h" -#include "a_drv.h" -#include "a_drv_api.h" -#include "a_debug.h" -#include "dbglog_api.h" - -static A_STATUS wmi_ready_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len); - -static A_STATUS wmi_connect_event_rx(struct wmi_t *wmip, A_UINT8 *datap, - int len); -static A_STATUS wmi_disconnect_event_rx(struct wmi_t *wmip, A_UINT8 *datap, - int len); -static A_STATUS wmi_tkip_micerr_event_rx(struct wmi_t *wmip, A_UINT8 *datap, - int len); -static A_STATUS wmi_bssInfo_event_rx(struct wmi_t *wmip, A_UINT8 *datap, - int len); -static A_STATUS wmi_opt_frame_event_rx(struct wmi_t *wmip, A_UINT8 *datap, - int len); -static A_STATUS wmi_pstream_timeout_event_rx(struct wmi_t *wmip, A_UINT8 *datap, - int len); -static A_STATUS wmi_sync_point(struct wmi_t *wmip); - -static A_STATUS wmi_bitrate_reply_rx(struct wmi_t *wmip, A_UINT8 *datap, - int len); -static A_STATUS wmi_ratemask_reply_rx(struct wmi_t *wmip, A_UINT8 *datap, - int len); -static A_STATUS wmi_channelList_reply_rx(struct wmi_t *wmip, A_UINT8 *datap, - int len); -static A_STATUS wmi_regDomain_event_rx(struct wmi_t *wmip, A_UINT8 *datap, - int len); -static A_STATUS wmi_txPwr_reply_rx(struct wmi_t *wmip, A_UINT8 *datap, int len); -static A_STATUS wmi_neighborReport_event_rx(struct wmi_t *wmip, A_UINT8 *datap, - int len); - -static A_STATUS wmi_dset_open_req_rx(struct wmi_t *wmip, A_UINT8 *datap, - int len); -#ifdef CONFIG_HOST_DSET_SUPPORT -static A_STATUS wmi_dset_close_rx(struct wmi_t *wmip, A_UINT8 *datap, int len); -static A_STATUS wmi_dset_data_req_rx(struct wmi_t *wmip, A_UINT8 *datap, - int len); -#endif /* CONFIG_HOST_DSET_SUPPORT */ - - -static A_STATUS wmi_scanComplete_rx(struct wmi_t *wmip, A_UINT8 *datap, - int len); -static A_STATUS wmi_errorEvent_rx(struct wmi_t *wmip, A_UINT8 *datap, int len); -static A_STATUS wmi_statsEvent_rx(struct wmi_t *wmip, A_UINT8 *datap, int len); -static A_STATUS wmi_rssiThresholdEvent_rx(struct wmi_t *wmip, A_UINT8 *datap, int len); -static A_STATUS wmi_hbChallengeResp_rx(struct wmi_t *wmip, A_UINT8 *datap, int len); -static A_STATUS wmi_reportErrorEvent_rx(struct wmi_t *wmip, A_UINT8 *datap, int len); -static A_STATUS wmi_cac_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len); -static A_STATUS wmi_roam_tbl_event_rx(struct wmi_t *wmip, A_UINT8 *datap, - int len); -static A_STATUS wmi_roam_data_event_rx(struct wmi_t *wmip, A_UINT8 *datap, - int len); -static A_STATUS wmi_get_wow_list_event_rx(struct wmi_t *wmip, A_UINT8 *datap, - int len); -static A_STATUS -wmi_get_pmkid_list_event_rx(struct wmi_t *wmip, A_UINT8 *datap, A_UINT32 len); - -#ifdef CONFIG_HOST_GPIO_SUPPORT -static A_STATUS wmi_gpio_intr_rx(struct wmi_t *wmip, A_UINT8 *datap, int len); -static A_STATUS wmi_gpio_data_rx(struct wmi_t *wmip, A_UINT8 *datap, int len); -static A_STATUS wmi_gpio_ack_rx(struct wmi_t *wmip, A_UINT8 *datap, int len); -#endif /* CONFIG_HOST_GPIO_SUPPORT */ - -#ifdef CONFIG_HOST_TCMD_SUPPORT -static A_STATUS -wmi_tcmd_test_report_rx(struct wmi_t *wmip, A_UINT8 *datap, int len); -#endif - -static A_STATUS -wmi_txRetryErrEvent_rx(struct wmi_t *wmip, A_UINT8 *datap, int len); - -static A_STATUS -wmi_snrThresholdEvent_rx(struct wmi_t *wmip, A_UINT8 *datap, int len); - -static A_STATUS -wmi_lqThresholdEvent_rx(struct wmi_t *wmip, A_UINT8 *datap, int len); - -static A_BOOL -wmi_is_bitrate_index_valid(struct wmi_t *wmip, A_UINT32 rateIndex); - -static A_STATUS -wmi_aplistEvent_rx(struct wmi_t *wmip, A_UINT8 *datap, int len); - -static A_STATUS -wmi_dbglog_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len); - -static A_STATUS wmi_keepalive_reply_rx(struct wmi_t *wmip, A_UINT8 *datap, int len); - -int wps_enable; -static const A_INT32 wmi_rateTable[] = { - 1000, - 2000, - 5500, - 11000, - 6000, - 9000, - 12000, - 18000, - 24000, - 36000, - 48000, - 54000, - 0}; - -#define MODE_A_SUPPORT_RATE_START 4 -#define MODE_A_SUPPORT_RATE_STOP 11 - -#define MODE_GONLY_SUPPORT_RATE_START MODE_A_SUPPORT_RATE_START -#define MODE_GONLY_SUPPORT_RATE_STOP MODE_A_SUPPORT_RATE_STOP - -#define MODE_B_SUPPORT_RATE_START 0 -#define MODE_B_SUPPORT_RATE_STOP 3 - -#define MODE_G_SUPPORT_RATE_START 0 -#define MODE_G_SUPPORT_RATE_STOP 11 - -#define MAX_NUMBER_OF_SUPPORT_RATES (MODE_G_SUPPORT_RATE_STOP + 1) - -/* 802.1d to AC mapping. Refer pg 57 of WMM-test-plan-v1.2 */ -const A_UINT8 up_to_ac[]= { - WMM_AC_BE, - WMM_AC_BK, - WMM_AC_BK, - WMM_AC_BE, - WMM_AC_VI, - WMM_AC_VI, - WMM_AC_VO, - WMM_AC_VO, - }; - -void * -wmi_init(void *devt) -{ - struct wmi_t *wmip; - - wmip = A_MALLOC(sizeof(struct wmi_t)); - if (wmip == NULL) { - return (NULL); - } - A_MEMZERO(wmip, sizeof(*wmip)); - A_MUTEX_INIT(&wmip->wmi_lock); - wmip->wmi_devt = devt; - wlan_node_table_init(wmip, &wmip->wmi_scan_table); - wmi_qos_state_init(wmip); - wmip->wmi_powerMode = REC_POWER; - wmip->wmi_phyMode = WMI_11G_MODE; - - return (wmip); -} - -void -wmi_qos_state_init(struct wmi_t *wmip) -{ - A_UINT8 i; - - if (wmip == NULL) { - return; - } - LOCK_WMI(wmip); - - /* Initialize QoS States */ - wmip->wmi_numQoSStream = 0; - - wmip->wmi_fatPipeExists = 0; - - for (i=0; i < WMM_NUM_AC; i++) { - wmip->wmi_streamExistsForAC[i]=0; - } - - /* Initialize the static Wmi stream Pri to WMM AC mappings Arrays */ - WMI_INIT_WMISTREAM_AC_MAP(wmip); - - UNLOCK_WMI(wmip); - - A_WMI_SET_NUMDATAENDPTS(wmip->wmi_devt, 1); -} - -void -wmi_shutdown(struct wmi_t *wmip) -{ - if (wmip != NULL) { - wlan_node_table_cleanup(&wmip->wmi_scan_table); - if (A_IS_MUTEX_VALID(&wmip->wmi_lock)) { - A_MUTEX_DELETE(&wmip->wmi_lock); - } - A_FREE(wmip); - } -} - -/* - * performs DIX to 802.3 encapsulation for transmit packets. - * uses passed in buffer. Returns buffer or NULL if failed. - * Assumes the entire DIX header is contigous and that there is - * enough room in the buffer for a 802.3 mac header and LLC+SNAP headers. - */ -A_STATUS -wmi_dix_2_dot3(struct wmi_t *wmip, void *osbuf) -{ - A_UINT8 *datap; - A_UINT16 typeorlen; - ATH_MAC_HDR macHdr; - ATH_LLC_SNAP_HDR *llcHdr; - - A_ASSERT(osbuf != NULL); - - if (A_NETBUF_HEADROOM(osbuf) < - (sizeof(ATH_LLC_SNAP_HDR) + sizeof(WMI_DATA_HDR))) - { - return A_NO_MEMORY; - } - - datap = A_NETBUF_DATA(osbuf); - - typeorlen = *(A_UINT16 *)(datap + ATH_MAC_LEN + ATH_MAC_LEN); - - if (!IS_ETHERTYPE(A_BE2CPU16(typeorlen))) { - /* - * packet is already in 802.3 format - return success - */ - A_DPRINTF(DBG_WMI, (DBGFMT "packet already 802.3\n", DBGARG)); - return (A_OK); - } - - /* - * Save mac fields and length to be inserted later - */ - A_MEMCPY(macHdr.dstMac, datap, ATH_MAC_LEN); - A_MEMCPY(macHdr.srcMac, datap + ATH_MAC_LEN, ATH_MAC_LEN); - macHdr.typeOrLen = A_CPU2BE16(A_NETBUF_LEN(osbuf) - sizeof(ATH_MAC_HDR) + - sizeof(ATH_LLC_SNAP_HDR)); - - /* - * Make room for LLC+SNAP headers - */ - if (A_NETBUF_PUSH(osbuf, sizeof(ATH_LLC_SNAP_HDR)) != A_OK) { - return A_NO_MEMORY; - } - - datap = A_NETBUF_DATA(osbuf); - - A_MEMCPY(datap, &macHdr, sizeof (ATH_MAC_HDR)); - - llcHdr = (ATH_LLC_SNAP_HDR *)(datap + sizeof(ATH_MAC_HDR)); - llcHdr->dsap = 0xAA; - llcHdr->ssap = 0xAA; - llcHdr->cntl = 0x03; - llcHdr->orgCode[0] = 0x0; - llcHdr->orgCode[1] = 0x0; - llcHdr->orgCode[2] = 0x0; - llcHdr->etherType = typeorlen; - - return (A_OK); -} - -/* - * Adds a WMI data header - * Assumes there is enough room in the buffer to add header. - */ -A_STATUS -wmi_data_hdr_add(struct wmi_t *wmip, void *osbuf, A_UINT8 msgType) -{ - WMI_DATA_HDR *dtHdr; - - A_ASSERT(osbuf != NULL); - - if (A_NETBUF_PUSH(osbuf, sizeof(WMI_DATA_HDR)) != A_OK) { - return A_NO_MEMORY; - } - - dtHdr = (WMI_DATA_HDR *)A_NETBUF_DATA(osbuf); - dtHdr->info = msgType; - dtHdr->rssi = 0; - - return (A_OK); -} - -A_UINT8 wmi_implicit_create_pstream(struct wmi_t *wmip, void *osbuf, A_UINT8 dir, A_UINT8 up) -{ - A_UINT8 *datap; - A_UINT8 trafficClass = WMM_AC_BE, userPriority = up; - ATH_LLC_SNAP_HDR *llcHdr; - A_UINT16 ipType = IP_ETHERTYPE; - WMI_DATA_HDR *dtHdr; - WMI_CREATE_PSTREAM_CMD cmd; - A_BOOL streamExists = FALSE; - - A_ASSERT(osbuf != NULL); - - datap = A_NETBUF_DATA(osbuf); - - if (up == UNDEFINED_PRI) { - llcHdr = (ATH_LLC_SNAP_HDR *)(datap + sizeof(WMI_DATA_HDR) + - sizeof(ATH_MAC_HDR)); - - if (llcHdr->etherType == A_CPU2BE16(ipType)) { - /* Extract the endpoint info from the TOS field in the IP header */ - userPriority = A_WMI_IPTOS_TO_USERPRIORITY(((A_UINT8 *)llcHdr) + sizeof(ATH_LLC_SNAP_HDR)); - } - } - - if (userPriority < MAX_NUM_PRI) { - trafficClass = convert_userPriority_to_trafficClass(userPriority); - } - - dtHdr = (WMI_DATA_HDR *)datap; - if(dir==UPLINK_TRAFFIC) - dtHdr->info |= (userPriority & WMI_DATA_HDR_UP_MASK) << WMI_DATA_HDR_UP_SHIFT; /* lower 3-bits are 802.1d priority */ - - LOCK_WMI(wmip); - streamExists = wmip->wmi_fatPipeExists; - UNLOCK_WMI(wmip); - - if (!(streamExists & (1 << trafficClass))) { - - A_MEMZERO(&cmd, sizeof(cmd)); - cmd.trafficClass = trafficClass; - cmd.userPriority = userPriority; - cmd.inactivityInt = WMI_IMPLICIT_PSTREAM_INACTIVITY_INT; - /* Implicit streams are created with TSID 0xFF */ - cmd.tsid = WMI_IMPLICIT_PSTREAM; - wmi_create_pstream_cmd(wmip, &cmd); - } - - return trafficClass; -} - -WMI_PRI_STREAM_ID -wmi_get_stream_id(struct wmi_t *wmip, A_UINT8 trafficClass) -{ - return WMI_ACCESSCATEGORY_WMISTREAM(wmip, trafficClass); -} - -/* - * performs 802.3 to DIX encapsulation for received packets. - * Assumes the entire 802.3 header is contigous. - */ -A_STATUS -wmi_dot3_2_dix(struct wmi_t *wmip, void *osbuf) -{ - A_UINT8 *datap; - ATH_MAC_HDR macHdr; - ATH_LLC_SNAP_HDR *llcHdr; - - A_ASSERT(osbuf != NULL); - datap = A_NETBUF_DATA(osbuf); - - A_MEMCPY(&macHdr, datap, sizeof(ATH_MAC_HDR)); - llcHdr = (ATH_LLC_SNAP_HDR *)(datap + sizeof(ATH_MAC_HDR)); - macHdr.typeOrLen = llcHdr->etherType; - - if (A_NETBUF_PULL(osbuf, sizeof(ATH_LLC_SNAP_HDR)) != A_OK) { - return A_NO_MEMORY; - } - - datap = A_NETBUF_DATA(osbuf); - - A_MEMCPY(datap, &macHdr, sizeof (ATH_MAC_HDR)); - - return (A_OK); -} - -/* - * Removes a WMI data header - */ -A_STATUS -wmi_data_hdr_remove(struct wmi_t *wmip, void *osbuf) -{ - A_ASSERT(osbuf != NULL); - - return (A_NETBUF_PULL(osbuf, sizeof(WMI_DATA_HDR))); -} - -void -wmi_iterate_nodes(struct wmi_t *wmip, wlan_node_iter_func *f, void *arg) -{ - wlan_iterate_nodes(&wmip->wmi_scan_table, f, arg); -} - -/* - * WMI Extended Event received from Target. - */ -A_STATUS -wmi_control_rx_xtnd(struct wmi_t *wmip, void *osbuf) -{ - WMIX_CMD_HDR *cmd; - A_UINT16 id; - A_UINT8 *datap; - A_UINT32 len; - A_STATUS status = A_OK; - - if (A_NETBUF_LEN(osbuf) < sizeof(WMIX_CMD_HDR)) { - A_DPRINTF(DBG_WMI, (DBGFMT "bad packet 1\n", DBGARG)); - wmip->wmi_stats.cmd_len_err++; - A_NETBUF_FREE(osbuf); - return A_ERROR; - } - - cmd = (WMIX_CMD_HDR *)A_NETBUF_DATA(osbuf); - id = cmd->commandId; - - if (A_NETBUF_PULL(osbuf, sizeof(WMIX_CMD_HDR)) != A_OK) { - A_DPRINTF(DBG_WMI, (DBGFMT "bad packet 2\n", DBGARG)); - wmip->wmi_stats.cmd_len_err++; - A_NETBUF_FREE(osbuf); - return A_ERROR; - } - - datap = A_NETBUF_DATA(osbuf); - len = A_NETBUF_LEN(osbuf); - - switch (id) { - case (WMIX_DSETOPENREQ_EVENTID): - status = wmi_dset_open_req_rx(wmip, datap, len); - break; -#ifdef CONFIG_HOST_DSET_SUPPORT - case (WMIX_DSETCLOSE_EVENTID): - status = wmi_dset_close_rx(wmip, datap, len); - break; - case (WMIX_DSETDATAREQ_EVENTID): - status = wmi_dset_data_req_rx(wmip, datap, len); - break; -#endif /* CONFIG_HOST_DSET_SUPPORT */ -#ifdef CONFIG_HOST_GPIO_SUPPORT - case (WMIX_GPIO_INTR_EVENTID): - wmi_gpio_intr_rx(wmip, datap, len); - break; - case (WMIX_GPIO_DATA_EVENTID): - wmi_gpio_data_rx(wmip, datap, len); - break; - case (WMIX_GPIO_ACK_EVENTID): - wmi_gpio_ack_rx(wmip, datap, len); - break; -#endif /* CONFIG_HOST_GPIO_SUPPORT */ - case (WMIX_HB_CHALLENGE_RESP_EVENTID): - wmi_hbChallengeResp_rx(wmip, datap, len); - break; - case (WMIX_DBGLOG_EVENTID): - wmi_dbglog_event_rx(wmip, datap, len); - break; - default: - A_DPRINTF(DBG_WMI|DBG_ERROR, - (DBGFMT "Unknown id 0x%x\n", DBGARG, id)); - wmip->wmi_stats.cmd_id_err++; - status = A_ERROR; - break; - } - - return status; -} - -/* - * Control Path - */ -A_UINT32 cmdRecvNum; - -A_STATUS -wmi_control_rx(struct wmi_t *wmip, void *osbuf) -{ - WMI_CMD_HDR *cmd; - A_UINT16 id; - A_UINT8 *datap; - A_UINT32 len, i, loggingReq; - A_STATUS status = A_OK; - - A_ASSERT(osbuf != NULL); - if (A_NETBUF_LEN(osbuf) < sizeof(WMI_CMD_HDR)) { - A_DPRINTF(DBG_WMI, (DBGFMT "bad packet 1\n", DBGARG)); - wmip->wmi_stats.cmd_len_err++; - A_NETBUF_FREE(osbuf); - return A_ERROR; - } - - cmd = (WMI_CMD_HDR *)A_NETBUF_DATA(osbuf); - id = cmd->commandId; - - if (A_NETBUF_PULL(osbuf, sizeof(WMI_CMD_HDR)) != A_OK) { - A_DPRINTF(DBG_WMI, (DBGFMT "bad packet 2\n", DBGARG)); - wmip->wmi_stats.cmd_len_err++; - A_NETBUF_FREE(osbuf); - return A_ERROR; - } - - datap = A_NETBUF_DATA(osbuf); - len = A_NETBUF_LEN(osbuf); - - ar6000_get_driver_cfg(wmip->wmi_devt, - AR6000_DRIVER_CFG_LOG_RAW_WMI_MSGS, - &loggingReq); - - if(loggingReq) { - AR_DEBUG_PRINTF(ATH_DEBUG_WMI, ("WMI %d \n",id)); - AR_DEBUG_PRINTF(ATH_DEBUG_WMI, ("WMI recv, MsgNo %d : ", cmdRecvNum)); - for(i = 0; i < len; i++) - AR_DEBUG_PRINTF(ATH_DEBUG_WMI, ("%x ", datap[i])); - AR_DEBUG_PRINTF(ATH_DEBUG_WMI, ("\n")); - } - - LOCK_WMI(wmip); - cmdRecvNum++; - UNLOCK_WMI(wmip); - - switch (id) { - case (WMI_GET_BITRATE_CMDID): - A_DPRINTF(DBG_WMI, (DBGFMT "WMI_GET_BITRATE_CMDID\n", DBGARG)); - status = wmi_bitrate_reply_rx(wmip, datap, len); - break; - case (WMI_GET_CHANNEL_LIST_CMDID): - A_DPRINTF(DBG_WMI, (DBGFMT "WMI_GET_CHANNEL_LIST_CMDID\n", DBGARG)); - status = wmi_channelList_reply_rx(wmip, datap, len); - break; - case (WMI_GET_TX_PWR_CMDID): - A_DPRINTF(DBG_WMI, (DBGFMT "WMI_GET_TX_PWR_CMDID\n", DBGARG)); - status = wmi_txPwr_reply_rx(wmip, datap, len); - break; - case (WMI_READY_EVENTID): - A_DPRINTF(DBG_WMI, (DBGFMT "WMI_READY_EVENTID\n", DBGARG)); - status = wmi_ready_event_rx(wmip, datap, len); - A_WMI_SEND_EVENT_TO_APP(wmip->wmi_devt, id, datap, len); - A_WMI_DBGLOG_INIT_DONE(wmip->wmi_devt); - break; - case (WMI_CONNECT_EVENTID): - A_DPRINTF(DBG_WMI, (DBGFMT "WMI_CONNECT_EVENTID\n", DBGARG)); - status = wmi_connect_event_rx(wmip, datap, len); - A_WMI_SEND_EVENT_TO_APP(wmip->wmi_devt, id, datap, len); - break; - case (WMI_DISCONNECT_EVENTID): - A_DPRINTF(DBG_WMI, (DBGFMT "WMI_DISCONNECT_EVENTID\n", DBGARG)); - status = wmi_disconnect_event_rx(wmip, datap, len); - A_WMI_SEND_EVENT_TO_APP(wmip->wmi_devt, id, datap, len); - break; - case (WMI_TKIP_MICERR_EVENTID): - A_DPRINTF(DBG_WMI, (DBGFMT "WMI_TKIP_MICERR_EVENTID\n", DBGARG)); - status = wmi_tkip_micerr_event_rx(wmip, datap, len); - break; - case (WMI_BSSINFO_EVENTID): - A_DPRINTF(DBG_WMI, (DBGFMT "WMI_BSSINFO_EVENTID\n", DBGARG)); - status = wmi_bssInfo_event_rx(wmip, datap, len); - A_WMI_SEND_EVENT_TO_APP(wmip->wmi_devt, id, datap, len); - break; - case (WMI_REGDOMAIN_EVENTID): - A_DPRINTF(DBG_WMI, (DBGFMT "WMI_REGDOMAIN_EVENTID\n", DBGARG)); - status = wmi_regDomain_event_rx(wmip, datap, len); - break; - case (WMI_PSTREAM_TIMEOUT_EVENTID): - A_DPRINTF(DBG_WMI, (DBGFMT "WMI_PSTREAM_TIMEOUT_EVENTID\n", DBGARG)); - status = wmi_pstream_timeout_event_rx(wmip, datap, len); - /* pstreams are fatpipe abstractions that get implicitly created. - * User apps only deal with thinstreams. creation of a thinstream - * by the user or data traffic flow in an AC triggers implicit - * pstream creation. Do we need to send this event to App..? - * no harm in sending it. - */ - A_WMI_SEND_EVENT_TO_APP(wmip->wmi_devt, id, datap, len); - break; - case (WMI_NEIGHBOR_REPORT_EVENTID): - A_DPRINTF(DBG_WMI, (DBGFMT "WMI_NEIGHBOR_REPORT_EVENTID\n", DBGARG)); - status = wmi_neighborReport_event_rx(wmip, datap, len); - break; - case (WMI_SCAN_COMPLETE_EVENTID): - A_DPRINTF(DBG_WMI, (DBGFMT "WMI_SCAN_COMPLETE_EVENTID\n", DBGARG)); - status = wmi_scanComplete_rx(wmip, datap, len); - A_WMI_SEND_EVENT_TO_APP(wmip->wmi_devt, id, datap, len); - break; - case (WMI_CMDERROR_EVENTID): - A_DPRINTF(DBG_WMI, (DBGFMT "WMI_CMDERROR_EVENTID\n", DBGARG)); - status = wmi_errorEvent_rx(wmip, datap, len); - break; - case (WMI_REPORT_STATISTICS_EVENTID): - A_DPRINTF(DBG_WMI, (DBGFMT "WMI_REPORT_STATISTICS_EVENTID\n", DBGARG)); - status = wmi_statsEvent_rx(wmip, datap, len); - break; - case (WMI_RSSI_THRESHOLD_EVENTID): - A_DPRINTF(DBG_WMI, (DBGFMT "WMI_RSSI_THRESHOLD_EVENTID\n", DBGARG)); - status = wmi_rssiThresholdEvent_rx(wmip, datap, len); - break; - case (WMI_ERROR_REPORT_EVENTID): - A_DPRINTF(DBG_WMI, (DBGFMT "WMI_ERROR_REPORT_EVENTID\n", DBGARG)); - status = wmi_reportErrorEvent_rx(wmip, datap, len); - A_WMI_SEND_EVENT_TO_APP(wmip->wmi_devt, id, datap, len); - break; - case (WMI_OPT_RX_FRAME_EVENTID): - A_DPRINTF(DBG_WMI, (DBGFMT "WMI_OPT_RX_FRAME_EVENTID\n", DBGARG)); - status = wmi_opt_frame_event_rx(wmip, datap, len); - break; - case (WMI_REPORT_ROAM_TBL_EVENTID): - A_DPRINTF(DBG_WMI, (DBGFMT "WMI_REPORT_ROAM_TBL_EVENTID\n", DBGARG)); - status = wmi_roam_tbl_event_rx(wmip, datap, len); - break; - case (WMI_EXTENSION_EVENTID): - A_DPRINTF(DBG_WMI, (DBGFMT "WMI_EXTENSION_EVENTID\n", DBGARG)); - status = wmi_control_rx_xtnd(wmip, osbuf); - break; - case (WMI_CAC_EVENTID): - A_DPRINTF(DBG_WMI, (DBGFMT "WMI_CAC_EVENTID\n", DBGARG)); - status = wmi_cac_event_rx(wmip, datap, len); - break; - case (WMI_REPORT_ROAM_DATA_EVENTID): - A_DPRINTF(DBG_WMI, (DBGFMT "WMI_REPORT_ROAM_DATA_EVENTID\n", DBGARG)); - status = wmi_roam_data_event_rx(wmip, datap, len); - break; -#ifdef CONFIG_HOST_TCMD_SUPPORT - case (WMI_TEST_EVENTID): - A_DPRINTF(DBG_WMI, (DBGFMT "WMI_TEST_EVENTID\n", DBGARG)); - status = wmi_tcmd_test_report_rx(wmip, datap, len); - break; -#endif - case (WMI_GET_FIXRATES_CMDID): - A_DPRINTF(DBG_WMI, (DBGFMT "WMI_GET_FIXRATES_CMDID\n", DBGARG)); - status = wmi_ratemask_reply_rx(wmip, datap, len); - break; - case (WMI_TX_RETRY_ERR_EVENTID): - A_DPRINTF(DBG_WMI, (DBGFMT "WMI_TX_RETRY_ERR_EVENTID\n", DBGARG)); - status = wmi_txRetryErrEvent_rx(wmip, datap, len); - A_WMI_SEND_EVENT_TO_APP(wmip->wmi_devt, id, datap, len); - break; - case (WMI_SNR_THRESHOLD_EVENTID): - A_DPRINTF(DBG_WMI, (DBGFMT "WMI_SNR_THRESHOLD_EVENTID\n", DBGARG)); - status = wmi_snrThresholdEvent_rx(wmip, datap, len); - A_WMI_SEND_EVENT_TO_APP(wmip->wmi_devt, id, datap, len); - break; - case (WMI_LQ_THRESHOLD_EVENTID): - A_DPRINTF(DBG_WMI, (DBGFMT "WMI_LQ_THRESHOLD_EVENTID\n", DBGARG)); - status = wmi_lqThresholdEvent_rx(wmip, datap, len); - A_WMI_SEND_EVENT_TO_APP(wmip->wmi_devt, id, datap, len); - break; - case (WMI_APLIST_EVENTID): - AR_DEBUG_PRINTF(ATH_DEBUG_WMI, ("Received APLIST Event\n")); - status = wmi_aplistEvent_rx(wmip, datap, len); - break; - case (WMI_GET_KEEPALIVE_CMDID): - A_DPRINTF(DBG_WMI, (DBGFMT "WMI_GET_KEEPALIVE_CMDID\n", DBGARG)); - status = wmi_keepalive_reply_rx(wmip, datap, len); - break; - case (WMI_GET_WOW_LIST_EVENTID): - status = wmi_get_wow_list_event_rx(wmip, datap, len); - break; - case (WMI_GET_PMKID_LIST_EVENTID): - A_DPRINTF(DBG_WMI, (DBGFMT "WMI_GET_PMKID_LIST Event\n", DBGARG)); - status = wmi_get_pmkid_list_event_rx(wmip, datap, len); - break; - default: - A_DPRINTF(DBG_WMI|DBG_ERROR, - (DBGFMT "Unknown id 0x%x\n", DBGARG, id)); - wmip->wmi_stats.cmd_id_err++; - status = A_ERROR; - break; - } - - A_NETBUF_FREE(osbuf); - - return status; -} - -static A_STATUS -wmi_ready_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len) -{ - WMI_READY_EVENT *ev = (WMI_READY_EVENT *)datap; - - if (len < sizeof(WMI_READY_EVENT)) { - return A_EINVAL; - } - A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG)); - wmip->wmi_ready = TRUE; - A_WMI_READY_EVENT(wmip->wmi_devt, ev->macaddr, ev->phyCapability); - - return A_OK; -} - -static A_STATUS -wmi_connect_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len) -{ - WMI_CONNECT_EVENT *ev; - - if (len < sizeof(WMI_CONNECT_EVENT)) { - return A_EINVAL; - } - ev = (WMI_CONNECT_EVENT *)datap; - A_DPRINTF(DBG_WMI, - (DBGFMT "freq %d bssid %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x\n", - DBGARG, ev->channel, - ev->bssid[0], ev->bssid[1], ev->bssid[2], - ev->bssid[3], ev->bssid[4], ev->bssid[5])); - - A_MEMCPY(wmip->wmi_bssid, ev->bssid, ATH_MAC_LEN); - - A_WMI_CONNECT_EVENT(wmip->wmi_devt, ev->channel, ev->bssid, - ev->listenInterval, ev->beaconInterval, - ev->networkType, ev->beaconIeLen, - ev->assocReqLen, ev->assocRespLen, - ev->assocInfo); - - return A_OK; -} - -static A_STATUS -wmi_regDomain_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len) -{ - WMI_REG_DOMAIN_EVENT *ev; - - if (len < sizeof(*ev)) { - return A_EINVAL; - } - ev = (WMI_REG_DOMAIN_EVENT *)datap; - - A_WMI_REGDOMAIN_EVENT(wmip->wmi_devt, ev->regDomain); - - return A_OK; -} - -static A_STATUS -wmi_neighborReport_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len) -{ - WMI_NEIGHBOR_REPORT_EVENT *ev; - int numAps; - - if (len < sizeof(*ev)) { - return A_EINVAL; - } - ev = (WMI_NEIGHBOR_REPORT_EVENT *)datap; - numAps = ev->numberOfAps; - - if (len < (int)(sizeof(*ev) + ((numAps - 1) * sizeof(WMI_NEIGHBOR_INFO)))) { - return A_EINVAL; - } - - A_WMI_NEIGHBORREPORT_EVENT(wmip->wmi_devt, numAps, ev->neighbor); - - return A_OK; -} - -static A_STATUS -wmi_disconnect_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len) -{ - WMI_DISCONNECT_EVENT *ev; - - if (len < sizeof(WMI_DISCONNECT_EVENT)) { - return A_EINVAL; - } - A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG)); - - ev = (WMI_DISCONNECT_EVENT *)datap; - - A_MEMZERO(wmip->wmi_bssid, sizeof(wmip->wmi_bssid)); - - A_WMI_DISCONNECT_EVENT(wmip->wmi_devt, ev->disconnectReason, ev->bssid, - ev->assocRespLen, ev->assocInfo, ev->protocolReasonStatus); - - return A_OK; -} - -static A_STATUS -wmi_tkip_micerr_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len) -{ - WMI_TKIP_MICERR_EVENT *ev; - - if (len < sizeof(*ev)) { - return A_EINVAL; - } - A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG)); - - ev = (WMI_TKIP_MICERR_EVENT *)datap; - A_WMI_TKIP_MICERR_EVENT(wmip->wmi_devt, ev->keyid, ev->ismcast); - - return A_OK; -} - -static A_STATUS -wmi_bssInfo_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len) -{ - bss_t *bss; - WMI_BSS_INFO_HDR *bih; - A_UINT8 *buf; - A_UINT32 nodeCachingAllowed; - - if (len <= sizeof(WMI_BSS_INFO_HDR)) { - return A_EINVAL; - } - - A_WMI_BSSINFO_EVENT_RX(wmip->wmi_devt, datap, len); - /* What is driver config for wlan node caching? */ - if(ar6000_get_driver_cfg(wmip->wmi_devt, - AR6000_DRIVER_CFG_GET_WLANNODECACHING, - &nodeCachingAllowed) != A_OK) { - return A_EINVAL; - } - - if(!nodeCachingAllowed) { - return A_OK; - } - - - bih = (WMI_BSS_INFO_HDR *)datap; - buf = datap + sizeof(WMI_BSS_INFO_HDR); - len -= sizeof(WMI_BSS_INFO_HDR); - - A_DPRINTF(DBG_WMI2, (DBGFMT "bssInfo event - ch %u, rssi %02x, " - "bssid \"%02x:%02x:%02x:%02x:%02x:%02x\"\n", DBGARG, - bih->channel, (unsigned char) bih->rssi, bih->bssid[0], - bih->bssid[1], bih->bssid[2], bih->bssid[3], bih->bssid[4], - bih->bssid[5])); - - if(wps_enable && (bih->frameType == PROBERESP_FTYPE) ) { - printk("%s() A_OK 2\n", __FUNCTION__); - return A_OK; - } - - bss = wlan_find_node(&wmip->wmi_scan_table, bih->bssid); - if (bss != NULL) { - /* - * Free up the node. Not the most efficient process given - * we are about to allocate a new node but it is simple and should be - * adequate. - */ - wlan_node_reclaim(&wmip->wmi_scan_table, bss); - } - - bss = wlan_node_alloc(&wmip->wmi_scan_table, len); - if (bss == NULL) { - return A_NO_MEMORY; - } - - bss->ni_snr = bih->snr; - bss->ni_rssi = bih->rssi; - A_ASSERT(bss->ni_buf != NULL); - A_MEMCPY(bss->ni_buf, buf, len); - - if (wlan_parse_beacon(bss->ni_buf, len, &bss->ni_cie) != A_OK) { - wlan_node_free(bss); - return A_EINVAL; - } - - /* - * Update the frequency in ie_chan, overwriting of channel number - * which is done in wlan_parse_beacon - */ - bss->ni_cie.ie_chan = bih->channel; - wlan_setup_node(&wmip->wmi_scan_table, bss, bih->bssid); - - return A_OK; -} - -static A_STATUS -wmi_opt_frame_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len) -{ - bss_t *bss; - WMI_OPT_RX_INFO_HDR *bih; - A_UINT8 *buf; - - if (len <= sizeof(WMI_OPT_RX_INFO_HDR)) { - return A_EINVAL; - } - - bih = (WMI_OPT_RX_INFO_HDR *)datap; - buf = datap + sizeof(WMI_OPT_RX_INFO_HDR); - len -= sizeof(WMI_OPT_RX_INFO_HDR); - - A_DPRINTF(DBG_WMI2, (DBGFMT "opt frame event %2.2x:%2.2x\n", DBGARG, - bih->bssid[4], bih->bssid[5])); - - bss = wlan_find_node(&wmip->wmi_scan_table, bih->bssid); - if (bss != NULL) { - /* - * Free up the node. Not the most efficient process given - * we are about to allocate a new node but it is simple and should be - * adequate. - */ - wlan_node_reclaim(&wmip->wmi_scan_table, bss); - } - - bss = wlan_node_alloc(&wmip->wmi_scan_table, len); - if (bss == NULL) { - return A_NO_MEMORY; - } - - bss->ni_snr = bih->snr; - bss->ni_cie.ie_chan = bih->channel; - A_ASSERT(bss->ni_buf != NULL); - A_MEMCPY(bss->ni_buf, buf, len); - wlan_setup_node(&wmip->wmi_scan_table, bss, bih->bssid); - - return A_OK; -} - - /* This event indicates inactivity timeout of a fatpipe(pstream) - * at the target - */ -static A_STATUS -wmi_pstream_timeout_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len) -{ - WMI_PSTREAM_TIMEOUT_EVENT *ev; - - if (len < sizeof(WMI_PSTREAM_TIMEOUT_EVENT)) { - return A_EINVAL; - } - - A_DPRINTF(DBG_WMI, (DBGFMT "wmi_pstream_timeout_event_rx\n", DBGARG)); - - ev = (WMI_PSTREAM_TIMEOUT_EVENT *)datap; - - /* When the pstream (fat pipe == AC) timesout, it means there were no - * thinStreams within this pstream & it got implicitly created due to - * data flow on this AC. We start the inactivity timer only for - * implicitly created pstream. Just reset the host state. - */ - /* Set the activeTsids for this AC to 0 */ - LOCK_WMI(wmip); - wmip->wmi_streamExistsForAC[ev->trafficClass]=0; - wmip->wmi_fatPipeExists &= ~(1 << ev->trafficClass); - UNLOCK_WMI(wmip); - - /*Indicate inactivity to driver layer for this fatpipe (pstream)*/ - A_WMI_STREAM_TX_INACTIVE(wmip->wmi_devt, ev->trafficClass); - - return A_OK; -} - -static A_STATUS -wmi_bitrate_reply_rx(struct wmi_t *wmip, A_UINT8 *datap, int len) -{ - WMI_BIT_RATE_CMD *reply; - A_INT32 rate; - - if (len < sizeof(WMI_BIT_RATE_CMD)) { - return A_EINVAL; - } - reply = (WMI_BIT_RATE_CMD *)datap; - A_DPRINTF(DBG_WMI, - (DBGFMT "Enter - rateindex %d\n", DBGARG, reply->rateIndex)); - - if (reply->rateIndex == RATE_AUTO) { - rate = RATE_AUTO; - } else { - rate = wmi_rateTable[(A_UINT32) reply->rateIndex]; - } - - A_WMI_BITRATE_RX(wmip->wmi_devt, rate); - - return A_OK; -} - -static A_STATUS -wmi_ratemask_reply_rx(struct wmi_t *wmip, A_UINT8 *datap, int len) -{ - WMI_FIX_RATES_CMD *reply; - - if (len < sizeof(WMI_BIT_RATE_CMD)) { - return A_EINVAL; - } - reply = (WMI_FIX_RATES_CMD *)datap; - A_DPRINTF(DBG_WMI, - (DBGFMT "Enter - fixed rate mask %x\n", DBGARG, reply->fixRateMask)); - - A_WMI_RATEMASK_RX(wmip->wmi_devt, reply->fixRateMask); - - return A_OK; -} - -static A_STATUS -wmi_channelList_reply_rx(struct wmi_t *wmip, A_UINT8 *datap, int len) -{ - WMI_CHANNEL_LIST_REPLY *reply; - - if (len < sizeof(WMI_CHANNEL_LIST_REPLY)) { - return A_EINVAL; - } - reply = (WMI_CHANNEL_LIST_REPLY *)datap; - A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG)); - - A_WMI_CHANNELLIST_RX(wmip->wmi_devt, reply->numChannels, - reply->channelList); - - return A_OK; -} - -static A_STATUS -wmi_txPwr_reply_rx(struct wmi_t *wmip, A_UINT8 *datap, int len) -{ - WMI_TX_PWR_REPLY *reply; - - if (len < sizeof(*reply)) { - return A_EINVAL; - } - reply = (WMI_TX_PWR_REPLY *)datap; - A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG)); - - A_WMI_TXPWR_RX(wmip->wmi_devt, reply->dbM); - - return A_OK; -} -static A_STATUS -wmi_keepalive_reply_rx(struct wmi_t *wmip, A_UINT8 *datap, int len) -{ - WMI_GET_KEEPALIVE_CMD *reply; - - if (len < sizeof(*reply)) { - return A_EINVAL; - } - reply = (WMI_GET_KEEPALIVE_CMD *)datap; - A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG)); - - A_WMI_KEEPALIVE_RX(wmip->wmi_devt, reply->configured); - - return A_OK; -} - - -static A_STATUS -wmi_dset_open_req_rx(struct wmi_t *wmip, A_UINT8 *datap, int len) -{ - WMIX_DSETOPENREQ_EVENT *dsetopenreq; - - if (len < sizeof(WMIX_DSETOPENREQ_EVENT)) { - return A_EINVAL; - } - dsetopenreq = (WMIX_DSETOPENREQ_EVENT *)datap; - A_DPRINTF(DBG_WMI, - (DBGFMT "Enter - dset_id=0x%x\n", DBGARG, dsetopenreq->dset_id)); - A_WMI_DSET_OPEN_REQ(wmip->wmi_devt, - dsetopenreq->dset_id, - dsetopenreq->targ_dset_handle, - dsetopenreq->targ_reply_fn, - dsetopenreq->targ_reply_arg); - - return A_OK; -} - -#ifdef CONFIG_HOST_DSET_SUPPORT -static A_STATUS -wmi_dset_close_rx(struct wmi_t *wmip, A_UINT8 *datap, int len) -{ - WMIX_DSETCLOSE_EVENT *dsetclose; - - if (len < sizeof(WMIX_DSETCLOSE_EVENT)) { - return A_EINVAL; - } - A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG)); - - dsetclose = (WMIX_DSETCLOSE_EVENT *)datap; - A_WMI_DSET_CLOSE(wmip->wmi_devt, dsetclose->access_cookie); - - return A_OK; -} - -static A_STATUS -wmi_dset_data_req_rx(struct wmi_t *wmip, A_UINT8 *datap, int len) -{ - WMIX_DSETDATAREQ_EVENT *dsetdatareq; - - if (len < sizeof(WMIX_DSETDATAREQ_EVENT)) { - return A_EINVAL; - } - A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG)); - - dsetdatareq = (WMIX_DSETDATAREQ_EVENT *)datap; - A_WMI_DSET_DATA_REQ(wmip->wmi_devt, - dsetdatareq->access_cookie, - dsetdatareq->offset, - dsetdatareq->length, - dsetdatareq->targ_buf, - dsetdatareq->targ_reply_fn, - dsetdatareq->targ_reply_arg); - - return A_OK; -} -#endif /* CONFIG_HOST_DSET_SUPPORT */ - -static A_STATUS -wmi_scanComplete_rx(struct wmi_t *wmip, A_UINT8 *datap, int len) -{ - WMI_SCAN_COMPLETE_EVENT *ev; - - ev = (WMI_SCAN_COMPLETE_EVENT *)datap; - A_WMI_SCANCOMPLETE_EVENT(wmip->wmi_devt, ev->status); - - return A_OK; -} - -/* - * Target is reporting a programming error. This is for - * developer aid only. Target only checks a few common violations - * and it is responsibility of host to do all error checking. - * Behavior of target after wmi error event is undefined. - * A reset is recommended. - */ -static A_STATUS -wmi_errorEvent_rx(struct wmi_t *wmip, A_UINT8 *datap, int len) -{ - WMI_CMD_ERROR_EVENT *ev; - - ev = (WMI_CMD_ERROR_EVENT *)datap; - AR_DEBUG_PRINTF(ATH_DEBUG_WMI, ("Programming Error: cmd=%d ", ev->commandId)); - switch (ev->errorCode) { - case (INVALID_PARAM): - AR_DEBUG_PRINTF(ATH_DEBUG_WMI, ("Illegal Parameter\n")); - break; - case (ILLEGAL_STATE): - AR_DEBUG_PRINTF(ATH_DEBUG_WMI, ("Illegal State\n")); - break; - case (INTERNAL_ERROR): - AR_DEBUG_PRINTF(ATH_DEBUG_WMI, ("Internal Error\n")); - break; - } - - return A_OK; -} - - -static A_STATUS -wmi_statsEvent_rx(struct wmi_t *wmip, A_UINT8 *datap, int len) -{ - WMI_TARGET_STATS *reply; - - if (len < sizeof(*reply)) { - return A_EINVAL; - } - reply = (WMI_TARGET_STATS *)datap; - A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG)); - - A_WMI_TARGETSTATS_EVENT(wmip->wmi_devt, reply); - - return A_OK; -} - -static A_STATUS -wmi_rssiThresholdEvent_rx(struct wmi_t *wmip, A_UINT8 *datap, int len) -{ - WMI_RSSI_THRESHOLD_EVENT *reply; - - if (len < sizeof(*reply)) { - return A_EINVAL; - } - reply = (WMI_RSSI_THRESHOLD_EVENT *)datap; - A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG)); - - A_WMI_RSSI_THRESHOLD_EVENT(wmip->wmi_devt, reply->range, reply->rssi); - - return A_OK; -} - - -static A_STATUS -wmi_reportErrorEvent_rx(struct wmi_t *wmip, A_UINT8 *datap, int len) -{ - WMI_TARGET_ERROR_REPORT_EVENT *reply; - - if (len < sizeof(*reply)) { - return A_EINVAL; - } - reply = (WMI_TARGET_ERROR_REPORT_EVENT *)datap; - A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG)); - - A_WMI_REPORT_ERROR_EVENT(wmip->wmi_devt, reply->errorVal); - - return A_OK; -} - -static A_STATUS -wmi_cac_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len) -{ - WMI_CAC_EVENT *reply; - - if (len < sizeof(*reply)) { - return A_EINVAL; - } - reply = (WMI_CAC_EVENT *)datap; - A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG)); - - A_WMI_CAC_EVENT(wmip->wmi_devt, reply->ac, - reply->cac_indication, reply->statusCode, - reply->tspecSuggestion); - - return A_OK; -} - -static A_STATUS -wmi_hbChallengeResp_rx(struct wmi_t *wmip, A_UINT8 *datap, int len) -{ - WMIX_HB_CHALLENGE_RESP_EVENT *reply; - - if (len < sizeof(*reply)) { - return A_EINVAL; - } - reply = (WMIX_HB_CHALLENGE_RESP_EVENT *)datap; - A_DPRINTF(DBG_WMI, (DBGFMT "wmi: challenge response event\n", DBGARG)); - - A_WMI_HBCHALLENGERESP_EVENT(wmip->wmi_devt, reply->cookie, reply->source); - - return A_OK; -} - -static A_STATUS -wmi_roam_tbl_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len) -{ - WMI_TARGET_ROAM_TBL *reply; - - if (len < sizeof(*reply)) { - return A_EINVAL; - } - reply = (WMI_TARGET_ROAM_TBL *)datap; - A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG)); - - A_WMI_ROAM_TABLE_EVENT(wmip->wmi_devt, reply); - - return A_OK; -} - -static A_STATUS -wmi_roam_data_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len) -{ - WMI_TARGET_ROAM_DATA *reply; - - if (len < sizeof(*reply)) { - return A_EINVAL; - } - reply = (WMI_TARGET_ROAM_DATA *)datap; - A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG)); - - A_WMI_ROAM_DATA_EVENT(wmip->wmi_devt, reply); - - return A_OK; -} - -static A_STATUS -wmi_txRetryErrEvent_rx(struct wmi_t *wmip, A_UINT8 *datap, int len) -{ - WMI_TX_RETRY_ERR_EVENT *reply; - - if (len < sizeof(*reply)) { - return A_EINVAL; - } - reply = (WMI_TX_RETRY_ERR_EVENT *)datap; - A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG)); - - A_WMI_TX_RETRY_ERR_EVENT(wmip->wmi_devt); - - return A_OK; -} - -static A_STATUS -wmi_snrThresholdEvent_rx(struct wmi_t *wmip, A_UINT8 *datap, int len) -{ - WMI_SNR_THRESHOLD_EVENT *reply; - - if (len < sizeof(*reply)) { - return A_EINVAL; - } - reply = (WMI_SNR_THRESHOLD_EVENT *)datap; - A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG)); - - A_WMI_SNR_THRESHOLD_EVENT_RX(wmip->wmi_devt, reply->range, reply->snr); - - return A_OK; -} - -static A_STATUS -wmi_lqThresholdEvent_rx(struct wmi_t *wmip, A_UINT8 *datap, int len) -{ - WMI_LQ_THRESHOLD_EVENT *reply; - - if (len < sizeof(*reply)) { - return A_EINVAL; - } - reply = (WMI_LQ_THRESHOLD_EVENT *)datap; - A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG)); - - A_WMI_LQ_THRESHOLD_EVENT_RX(wmip->wmi_devt, reply->range, reply->lq); - - return A_OK; -} - -static A_STATUS -wmi_aplistEvent_rx(struct wmi_t *wmip, A_UINT8 *datap, int len) -{ - A_UINT16 ap_info_entry_size; - WMI_APLIST_EVENT *ev = (WMI_APLIST_EVENT *)datap; - WMI_AP_INFO_V1 *ap_info_v1; - A_UINT8 i; - - if (len < sizeof(WMI_APLIST_EVENT)) { - return A_EINVAL; - } - - if (ev->apListVer == APLIST_VER1) { - ap_info_entry_size = sizeof(WMI_AP_INFO_V1); - ap_info_v1 = (WMI_AP_INFO_V1 *)ev->apList; - } else { - return A_EINVAL; - } - - AR_DEBUG_PRINTF(ATH_DEBUG_WMI, ("Number of APs in APLIST Event is %d\n", ev->numAP)); - if (len < (int)(sizeof(WMI_APLIST_EVENT) + - (ev->numAP - 1) * ap_info_entry_size)) - { - return A_EINVAL; - } - - /* - * AP List Ver1 Contents - */ - for (i = 0; i < ev->numAP; i++) { - AR_DEBUG_PRINTF(ATH_DEBUG_WMI, ("AP#%d BSSID %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x "\ - "Channel %d\n", i, - ap_info_v1->bssid[0], ap_info_v1->bssid[1], - ap_info_v1->bssid[2], ap_info_v1->bssid[3], - ap_info_v1->bssid[4], ap_info_v1->bssid[5], - ap_info_v1->channel)); - ap_info_v1++; - } - return A_OK; -} - -static A_STATUS -wmi_dbglog_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len) -{ - A_UINT32 dropped; - - dropped = *((A_UINT32 *)datap); - datap += sizeof(dropped); - len -= sizeof(dropped); - A_WMI_DBGLOG_EVENT(wmip->wmi_devt, dropped, datap, len); - return A_OK; -} - -#ifdef CONFIG_HOST_GPIO_SUPPORT -static A_STATUS -wmi_gpio_intr_rx(struct wmi_t *wmip, A_UINT8 *datap, int len) -{ - WMIX_GPIO_INTR_EVENT *gpio_intr = (WMIX_GPIO_INTR_EVENT *)datap; - - A_DPRINTF(DBG_WMI, - (DBGFMT "Enter - intrmask=0x%x input=0x%x.\n", DBGARG, - gpio_intr->intr_mask, gpio_intr->input_values)); - - A_WMI_GPIO_INTR_RX(gpio_intr->intr_mask, gpio_intr->input_values); - - return A_OK; -} - -static A_STATUS -wmi_gpio_data_rx(struct wmi_t *wmip, A_UINT8 *datap, int len) -{ - WMIX_GPIO_DATA_EVENT *gpio_data = (WMIX_GPIO_DATA_EVENT *)datap; - - A_DPRINTF(DBG_WMI, - (DBGFMT "Enter - reg=%d value=0x%x\n", DBGARG, - gpio_data->reg_id, gpio_data->value)); - - A_WMI_GPIO_DATA_RX(gpio_data->reg_id, gpio_data->value); - - return A_OK; -} - -static A_STATUS -wmi_gpio_ack_rx(struct wmi_t *wmip, A_UINT8 *datap, int len) -{ - A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG)); - - A_WMI_GPIO_ACK_RX(); - - return A_OK; -} -#endif /* CONFIG_HOST_GPIO_SUPPORT */ - -/* - * Called to send a wmi command. Command specific data is already built - * on osbuf and current osbuf->data points to it. - */ -A_STATUS -wmi_cmd_send(struct wmi_t *wmip, void *osbuf, WMI_COMMAND_ID cmdId, - WMI_SYNC_FLAG syncflag) -{ -#define IS_LONG_CMD(cmdId) ((cmdId == WMI_OPT_TX_FRAME_CMDID) || (cmdId == WMI_ADD_WOW_PATTERN_CMDID)) - WMI_CMD_HDR *cHdr; - WMI_PRI_STREAM_ID streamID = WMI_CONTROL_PRI; - - A_ASSERT(osbuf != NULL); - - if (syncflag >= END_WMIFLAG) { - return A_EINVAL; - } - - if ((syncflag == SYNC_BEFORE_WMIFLAG) || (syncflag == SYNC_BOTH_WMIFLAG)) { - /* - * We want to make sure all data currently queued is transmitted before - * the cmd execution. Establish a new sync point. - */ - wmi_sync_point(wmip); - } - - if (A_NETBUF_PUSH(osbuf, sizeof(WMI_CMD_HDR)) != A_OK) { - return A_NO_MEMORY; - } - - cHdr = (WMI_CMD_HDR *)A_NETBUF_DATA(osbuf); - cHdr->commandId = cmdId; - - /* - * Send cmd, some via control pipe, others via data pipe - */ - if (IS_LONG_CMD(cmdId)) { - wmi_data_hdr_add(wmip, osbuf, CNTL_MSGTYPE); - // TODO ... these can now go through the control endpoint via HTC 2.0 - streamID = WMI_BEST_EFFORT_PRI; - } - A_WMI_CONTROL_TX(wmip->wmi_devt, osbuf, streamID); - - if ((syncflag == SYNC_AFTER_WMIFLAG) || (syncflag == SYNC_BOTH_WMIFLAG)) { - /* - * We want to make sure all new data queued waits for the command to - * execute. Establish a new sync point. - */ - wmi_sync_point(wmip); - } - return (A_OK); -#undef IS_LONG_CMD -} - -A_STATUS -wmi_cmd_send_xtnd(struct wmi_t *wmip, void *osbuf, WMI_COMMAND_ID cmdId, - WMI_SYNC_FLAG syncflag) -{ - WMIX_CMD_HDR *cHdr; - - if (A_NETBUF_PUSH(osbuf, sizeof(WMIX_CMD_HDR)) != A_OK) { - return A_NO_MEMORY; - } - - cHdr = (WMIX_CMD_HDR *)A_NETBUF_DATA(osbuf); - cHdr->commandId = cmdId; - - return wmi_cmd_send(wmip, osbuf, WMI_EXTENSION_CMDID, syncflag); -} - -A_STATUS -wmi_connect_cmd(struct wmi_t *wmip, NETWORK_TYPE netType, - DOT11_AUTH_MODE dot11AuthMode, AUTH_MODE authMode, - CRYPTO_TYPE pairwiseCrypto, A_UINT8 pairwiseCryptoLen, - CRYPTO_TYPE groupCrypto,A_UINT8 groupCryptoLen, - int ssidLength, A_UCHAR *ssid, - A_UINT8 *bssid, A_UINT16 channel, A_UINT32 ctrl_flags) -{ - void *osbuf; - WMI_CONNECT_CMD *cc; - - if ((pairwiseCrypto == NONE_CRYPT) && (groupCrypto != NONE_CRYPT)) { - return A_EINVAL; - } - if ((pairwiseCrypto != NONE_CRYPT) && (groupCrypto == NONE_CRYPT)) { - return A_EINVAL; - } - - osbuf = A_NETBUF_ALLOC(sizeof(WMI_CONNECT_CMD)); - if (osbuf == NULL) { - return A_NO_MEMORY; - } - - A_NETBUF_PUT(osbuf, sizeof(WMI_CONNECT_CMD)); - - cc = (WMI_CONNECT_CMD *)(A_NETBUF_DATA(osbuf)); - A_MEMZERO(cc, sizeof(*cc)); - - A_MEMCPY(cc->ssid, ssid, ssidLength); - cc->ssidLength = ssidLength; - cc->networkType = netType; - cc->dot11AuthMode = dot11AuthMode; - cc->authMode = authMode; - cc->pairwiseCryptoType = pairwiseCrypto; - cc->pairwiseCryptoLen = pairwiseCryptoLen; - cc->groupCryptoType = groupCrypto; - cc->groupCryptoLen = groupCryptoLen; - cc->channel = channel; - cc->ctrl_flags = ctrl_flags; - - if (bssid != NULL) { - A_MEMCPY(cc->bssid, bssid, ATH_MAC_LEN); - } - if (wmi_set_keepalive_cmd(wmip, wmip->wmi_keepaliveInterval) != A_OK) { - return(A_ERROR); - } - - return (wmi_cmd_send(wmip, osbuf, WMI_CONNECT_CMDID, NO_SYNC_WMIFLAG)); -} - -A_STATUS -wmi_reconnect_cmd(struct wmi_t *wmip, A_UINT8 *bssid, A_UINT16 channel) -{ - void *osbuf; - WMI_RECONNECT_CMD *cc; - - osbuf = A_NETBUF_ALLOC(sizeof(WMI_RECONNECT_CMD)); - if (osbuf == NULL) { - return A_NO_MEMORY; - } - - A_NETBUF_PUT(osbuf, sizeof(WMI_RECONNECT_CMD)); - - cc = (WMI_RECONNECT_CMD *)(A_NETBUF_DATA(osbuf)); - A_MEMZERO(cc, sizeof(*cc)); - - cc->channel = channel; - - if (bssid != NULL) { - A_MEMCPY(cc->bssid, bssid, ATH_MAC_LEN); - } - - return (wmi_cmd_send(wmip, osbuf, WMI_RECONNECT_CMDID, NO_SYNC_WMIFLAG)); -} - -A_STATUS -wmi_disconnect_cmd(struct wmi_t *wmip) -{ - void *osbuf; - A_STATUS status; - - osbuf = A_NETBUF_ALLOC(0); /* no payload */ - if (osbuf == NULL) { - return A_NO_MEMORY; - } - - /* Bug fix for 24817(elevator bug) - the disconnect command does not - need to do a SYNC before.*/ - status = (wmi_cmd_send(wmip, osbuf, WMI_DISCONNECT_CMDID, - NO_SYNC_WMIFLAG)); - - return status; -} - -A_STATUS -wmi_startscan_cmd(struct wmi_t *wmip, WMI_SCAN_TYPE scanType, - A_BOOL forceFgScan, A_BOOL isLegacy, - A_UINT32 homeDwellTime, A_UINT32 forceScanInterval) -{ - void *osbuf; - WMI_START_SCAN_CMD *sc; - - if ((scanType != WMI_LONG_SCAN) && (scanType != WMI_SHORT_SCAN)) { - return A_EINVAL; - } - - osbuf = A_NETBUF_ALLOC(sizeof(*sc)); - if (osbuf == NULL) { - return A_NO_MEMORY; - } - - A_NETBUF_PUT(osbuf, sizeof(*sc)); - - sc = (WMI_START_SCAN_CMD *)(A_NETBUF_DATA(osbuf)); - sc->scanType = scanType; - sc->forceFgScan = forceFgScan; - sc->isLegacy = isLegacy; - sc->homeDwellTime = homeDwellTime; - sc->forceScanInterval = forceScanInterval; - - return (wmi_cmd_send(wmip, osbuf, WMI_START_SCAN_CMDID, NO_SYNC_WMIFLAG)); -} - -A_STATUS -wmi_scanparams_cmd(struct wmi_t *wmip, A_UINT16 fg_start_sec, - A_UINT16 fg_end_sec, A_UINT16 bg_sec, - A_UINT16 minact_chdw_msec, A_UINT16 maxact_chdw_msec, - A_UINT16 pas_chdw_msec, - A_UINT8 shScanRatio, A_UINT8 scanCtrlFlags, - A_UINT32 max_dfsch_act_time) -{ - void *osbuf; - WMI_SCAN_PARAMS_CMD *sc; - - osbuf = A_NETBUF_ALLOC(sizeof(*sc)); - if (osbuf == NULL) { - return A_NO_MEMORY; - } - - A_NETBUF_PUT(osbuf, sizeof(*sc)); - - sc = (WMI_SCAN_PARAMS_CMD *)(A_NETBUF_DATA(osbuf)); - A_MEMZERO(sc, sizeof(*sc)); - sc->fg_start_period = fg_start_sec; - sc->fg_end_period = fg_end_sec; - sc->bg_period = bg_sec; - sc->minact_chdwell_time = minact_chdw_msec; - sc->maxact_chdwell_time = maxact_chdw_msec; - sc->pas_chdwell_time = pas_chdw_msec; - sc->shortScanRatio = shScanRatio; - sc->scanCtrlFlags = scanCtrlFlags; - sc->max_dfsch_act_time = max_dfsch_act_time; - - return (wmi_cmd_send(wmip, osbuf, WMI_SET_SCAN_PARAMS_CMDID, - NO_SYNC_WMIFLAG)); -} - -A_STATUS -wmi_bssfilter_cmd(struct wmi_t *wmip, A_UINT8 filter, A_UINT32 ieMask) -{ - void *osbuf; - WMI_BSS_FILTER_CMD *cmd; - - if (filter >= LAST_BSS_FILTER) { - return A_EINVAL; - } - - osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); - if (osbuf == NULL) { - return A_NO_MEMORY; - } - - A_NETBUF_PUT(osbuf, sizeof(*cmd)); - - cmd = (WMI_BSS_FILTER_CMD *)(A_NETBUF_DATA(osbuf)); - A_MEMZERO(cmd, sizeof(*cmd)); - cmd->bssFilter = filter; - cmd->ieMask = ieMask; - - return (wmi_cmd_send(wmip, osbuf, WMI_SET_BSS_FILTER_CMDID, - NO_SYNC_WMIFLAG)); -} - -A_STATUS -wmi_probedSsid_cmd(struct wmi_t *wmip, A_UINT8 index, A_UINT8 flag, - A_UINT8 ssidLength, A_UCHAR *ssid) -{ - void *osbuf; - WMI_PROBED_SSID_CMD *cmd; - - if (index > MAX_PROBED_SSID_INDEX) { - return A_EINVAL; - } - if (ssidLength > sizeof(cmd->ssid)) { - return A_EINVAL; - } - if ((flag & (DISABLE_SSID_FLAG | ANY_SSID_FLAG)) && (ssidLength > 0)) { - return A_EINVAL; - } - if ((flag & SPECIFIC_SSID_FLAG) && !ssidLength) { - return A_EINVAL; - } - - osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); - if (osbuf == NULL) { - return A_NO_MEMORY; - } - - A_NETBUF_PUT(osbuf, sizeof(*cmd)); - - cmd = (WMI_PROBED_SSID_CMD *)(A_NETBUF_DATA(osbuf)); - A_MEMZERO(cmd, sizeof(*cmd)); - cmd->entryIndex = index; - cmd->flag = flag; - cmd->ssidLength = ssidLength; - A_MEMCPY(cmd->ssid, ssid, ssidLength); - - return (wmi_cmd_send(wmip, osbuf, WMI_SET_PROBED_SSID_CMDID, - NO_SYNC_WMIFLAG)); -} - -A_STATUS -wmi_listeninterval_cmd(struct wmi_t *wmip, A_UINT16 listenInterval, A_UINT16 listenBeacons) -{ - void *osbuf; - WMI_LISTEN_INT_CMD *cmd; - - osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); - if (osbuf == NULL) { - return A_NO_MEMORY; - } - - A_NETBUF_PUT(osbuf, sizeof(*cmd)); - - cmd = (WMI_LISTEN_INT_CMD *)(A_NETBUF_DATA(osbuf)); - A_MEMZERO(cmd, sizeof(*cmd)); - cmd->listenInterval = listenInterval; - cmd->numBeacons = listenBeacons; - - return (wmi_cmd_send(wmip, osbuf, WMI_SET_LISTEN_INT_CMDID, - NO_SYNC_WMIFLAG)); -} - -A_STATUS -wmi_bmisstime_cmd(struct wmi_t *wmip, A_UINT16 bmissTime, A_UINT16 bmissBeacons) -{ - void *osbuf; - WMI_BMISS_TIME_CMD *cmd; - - osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); - if (osbuf == NULL) { - return A_NO_MEMORY; - } - - A_NETBUF_PUT(osbuf, sizeof(*cmd)); - - cmd = (WMI_BMISS_TIME_CMD *)(A_NETBUF_DATA(osbuf)); - A_MEMZERO(cmd, sizeof(*cmd)); - cmd->bmissTime = bmissTime; - cmd->numBeacons = bmissBeacons; - - return (wmi_cmd_send(wmip, osbuf, WMI_SET_BMISS_TIME_CMDID, - NO_SYNC_WMIFLAG)); -} - -A_STATUS -wmi_associnfo_cmd(struct wmi_t *wmip, A_UINT8 ieType, - A_UINT8 ieLen, A_UINT8 *ieInfo) -{ - void *osbuf; - WMI_SET_ASSOC_INFO_CMD *cmd; - A_UINT16 cmdLen; - - cmdLen = sizeof(*cmd) + ieLen - 1; - osbuf = A_NETBUF_ALLOC(cmdLen); - if (osbuf == NULL) { - return A_NO_MEMORY; - } - - A_NETBUF_PUT(osbuf, cmdLen); - - cmd = (WMI_SET_ASSOC_INFO_CMD *)(A_NETBUF_DATA(osbuf)); - A_MEMZERO(cmd, cmdLen); - cmd->ieType = ieType; - cmd->bufferSize = ieLen; - A_MEMCPY(cmd->assocInfo, ieInfo, ieLen); - - return (wmi_cmd_send(wmip, osbuf, WMI_SET_ASSOC_INFO_CMDID, - NO_SYNC_WMIFLAG)); -} - -A_STATUS -wmi_powermode_cmd(struct wmi_t *wmip, A_UINT8 powerMode) -{ - void *osbuf; - WMI_POWER_MODE_CMD *cmd; - - osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); - if (osbuf == NULL) { - return A_NO_MEMORY; - } - - A_NETBUF_PUT(osbuf, sizeof(*cmd)); - - cmd = (WMI_POWER_MODE_CMD *)(A_NETBUF_DATA(osbuf)); - A_MEMZERO(cmd, sizeof(*cmd)); - cmd->powerMode = powerMode; - wmip->wmi_powerMode = powerMode; - - return (wmi_cmd_send(wmip, osbuf, WMI_SET_POWER_MODE_CMDID, - NO_SYNC_WMIFLAG)); -} - -A_STATUS -wmi_ibsspmcaps_cmd(struct wmi_t *wmip, A_UINT8 pmEnable, A_UINT8 ttl, - A_UINT16 atim_windows, A_UINT16 timeout_value) -{ - void *osbuf; - WMI_IBSS_PM_CAPS_CMD *cmd; - - osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); - if (osbuf == NULL) { - return A_NO_MEMORY; - } - - A_NETBUF_PUT(osbuf, sizeof(*cmd)); - - cmd = (WMI_IBSS_PM_CAPS_CMD *)(A_NETBUF_DATA(osbuf)); - A_MEMZERO(cmd, sizeof(*cmd)); - cmd->power_saving = pmEnable; - cmd->ttl = ttl; - cmd->atim_windows = atim_windows; - cmd->timeout_value = timeout_value; - - return (wmi_cmd_send(wmip, osbuf, WMI_SET_IBSS_PM_CAPS_CMDID, - NO_SYNC_WMIFLAG)); -} - -A_STATUS -wmi_pmparams_cmd(struct wmi_t *wmip, A_UINT16 idlePeriod, - A_UINT16 psPollNum, A_UINT16 dtimPolicy) -{ - void *osbuf; - WMI_POWER_PARAMS_CMD *pm; - - osbuf = A_NETBUF_ALLOC(sizeof(*pm)); - if (osbuf == NULL) { - return A_NO_MEMORY; - } - - A_NETBUF_PUT(osbuf, sizeof(*pm)); - - pm = (WMI_POWER_PARAMS_CMD *)(A_NETBUF_DATA(osbuf)); - A_MEMZERO(pm, sizeof(*pm)); - pm->idle_period = idlePeriod; - pm->pspoll_number = psPollNum; - pm->dtim_policy = dtimPolicy; - - return (wmi_cmd_send(wmip, osbuf, WMI_SET_POWER_PARAMS_CMDID, - NO_SYNC_WMIFLAG)); -} - -A_STATUS -wmi_disctimeout_cmd(struct wmi_t *wmip, A_UINT8 timeout) -{ - void *osbuf; - WMI_DISC_TIMEOUT_CMD *cmd; - - osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); - if (osbuf == NULL) { - return A_NO_MEMORY; - } - - A_NETBUF_PUT(osbuf, sizeof(*cmd)); - - cmd = (WMI_DISC_TIMEOUT_CMD *)(A_NETBUF_DATA(osbuf)); - A_MEMZERO(cmd, sizeof(*cmd)); - cmd->disconnectTimeout = timeout; - - return (wmi_cmd_send(wmip, osbuf, WMI_SET_DISC_TIMEOUT_CMDID, - NO_SYNC_WMIFLAG)); -} - -A_STATUS -wmi_addKey_cmd(struct wmi_t *wmip, A_UINT8 keyIndex, CRYPTO_TYPE keyType, - A_UINT8 keyUsage, A_UINT8 keyLength, A_UINT8 *keyRSC, - A_UINT8 *keyMaterial, A_UINT8 key_op_ctrl, - WMI_SYNC_FLAG sync_flag) -{ - void *osbuf; - WMI_ADD_CIPHER_KEY_CMD *cmd; - - if ((keyIndex > WMI_MAX_KEY_INDEX) || (keyLength > WMI_MAX_KEY_LEN) || - (keyMaterial == NULL)) - { - return A_EINVAL; - } - - if ((WEP_CRYPT != keyType) && (NULL == keyRSC)) { - return A_EINVAL; - } - - osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); - if (osbuf == NULL) { - return A_NO_MEMORY; - } - - A_NETBUF_PUT(osbuf, sizeof(*cmd)); - - cmd = (WMI_ADD_CIPHER_KEY_CMD *)(A_NETBUF_DATA(osbuf)); - A_MEMZERO(cmd, sizeof(*cmd)); - cmd->keyIndex = keyIndex; - cmd->keyType = keyType; - cmd->keyUsage = keyUsage; - cmd->keyLength = keyLength; - A_MEMCPY(cmd->key, keyMaterial, keyLength); - if (NULL != keyRSC) { - A_MEMCPY(cmd->keyRSC, keyRSC, sizeof(cmd->keyRSC)); - } - cmd->key_op_ctrl = key_op_ctrl; - - return (wmi_cmd_send(wmip, osbuf, WMI_ADD_CIPHER_KEY_CMDID, sync_flag)); -} - -A_STATUS -wmi_add_krk_cmd(struct wmi_t *wmip, A_UINT8 *krk) -{ - void *osbuf; - WMI_ADD_KRK_CMD *cmd; - - osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); - - if (osbuf == NULL) { - return A_NO_MEMORY; - } - - A_NETBUF_PUT(osbuf, sizeof(*cmd)); - - cmd = (WMI_ADD_KRK_CMD *)(A_NETBUF_DATA(osbuf)); - A_MEMZERO(cmd, sizeof(*cmd)); - A_MEMCPY(cmd->krk, krk, WMI_KRK_LEN); - - return (wmi_cmd_send(wmip, osbuf, WMI_ADD_KRK_CMDID, NO_SYNC_WMIFLAG)); -} - -A_STATUS -wmi_delete_krk_cmd(struct wmi_t *wmip) -{ - void *osbuf; - - osbuf = A_NETBUF_ALLOC(0); - - if (osbuf == NULL) { - return A_NO_MEMORY; - } - - return (wmi_cmd_send(wmip, osbuf, WMI_DELETE_KRK_CMDID, NO_SYNC_WMIFLAG)); -} - -A_STATUS -wmi_deleteKey_cmd(struct wmi_t *wmip, A_UINT8 keyIndex) -{ - void *osbuf; - WMI_DELETE_CIPHER_KEY_CMD *cmd; - - if (keyIndex > WMI_MAX_KEY_INDEX) { - return A_EINVAL; - } - - osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); - if (osbuf == NULL) { - return A_NO_MEMORY; - } - - A_NETBUF_PUT(osbuf, sizeof(*cmd)); - - cmd = (WMI_DELETE_CIPHER_KEY_CMD *)(A_NETBUF_DATA(osbuf)); - A_MEMZERO(cmd, sizeof(*cmd)); - cmd->keyIndex = keyIndex; - - return (wmi_cmd_send(wmip, osbuf, WMI_DELETE_CIPHER_KEY_CMDID, - NO_SYNC_WMIFLAG)); -} - -A_STATUS -wmi_setPmkid_cmd(struct wmi_t *wmip, A_UINT8 *bssid, A_UINT8 *pmkId, - A_BOOL set) -{ - void *osbuf; - WMI_SET_PMKID_CMD *cmd; - - if (bssid == NULL) { - return A_EINVAL; - } - - if ((set == TRUE) && (pmkId == NULL)) { - return A_EINVAL; - } - - osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); - if (osbuf == NULL) { - return A_NO_MEMORY; - } - - A_NETBUF_PUT(osbuf, sizeof(*cmd)); - - cmd = (WMI_SET_PMKID_CMD *)(A_NETBUF_DATA(osbuf)); - A_MEMCPY(cmd->bssid, bssid, sizeof(cmd->bssid)); - if (set == TRUE) { - A_MEMCPY(cmd->pmkid, pmkId, sizeof(cmd->pmkid)); - cmd->enable = PMKID_ENABLE; - } else { - A_MEMZERO(cmd->pmkid, sizeof(cmd->pmkid)); - cmd->enable = PMKID_DISABLE; - } - - return (wmi_cmd_send(wmip, osbuf, WMI_SET_PMKID_CMDID, NO_SYNC_WMIFLAG)); -} - -A_STATUS -wmi_set_tkip_countermeasures_cmd(struct wmi_t *wmip, A_BOOL en) -{ - void *osbuf; - WMI_SET_TKIP_COUNTERMEASURES_CMD *cmd; - - osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); - if (osbuf == NULL) { - return A_NO_MEMORY; - } - - A_NETBUF_PUT(osbuf, sizeof(*cmd)); - - cmd = (WMI_SET_TKIP_COUNTERMEASURES_CMD *)(A_NETBUF_DATA(osbuf)); - cmd->cm_en = (en == TRUE)? WMI_TKIP_CM_ENABLE : WMI_TKIP_CM_DISABLE; - - return (wmi_cmd_send(wmip, osbuf, WMI_SET_TKIP_COUNTERMEASURES_CMDID, - NO_SYNC_WMIFLAG)); -} - -A_STATUS -wmi_set_akmp_params_cmd(struct wmi_t *wmip, - WMI_SET_AKMP_PARAMS_CMD *akmpParams) -{ - void *osbuf; - WMI_SET_AKMP_PARAMS_CMD *cmd; - - osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); - if (osbuf == NULL) { - return A_NO_MEMORY; - } - - A_NETBUF_PUT(osbuf, sizeof(*cmd)); - cmd = (WMI_SET_AKMP_PARAMS_CMD *)(A_NETBUF_DATA(osbuf)); - cmd->akmpInfo = akmpParams->akmpInfo; - - return (wmi_cmd_send(wmip, osbuf, WMI_SET_AKMP_PARAMS_CMDID, - NO_SYNC_WMIFLAG)); -} - -A_STATUS -wmi_set_pmkid_list_cmd(struct wmi_t *wmip, - WMI_SET_PMKID_LIST_CMD *pmkInfo) -{ - void *osbuf; - WMI_SET_PMKID_LIST_CMD *cmd; - A_UINT16 cmdLen; - A_UINT8 i; - - cmdLen = sizeof(pmkInfo->numPMKID) + - pmkInfo->numPMKID * sizeof(WMI_PMKID); - - osbuf = A_NETBUF_ALLOC(cmdLen); - - if (osbuf == NULL) { - return A_NO_MEMORY; - } - - A_NETBUF_PUT(osbuf, cmdLen); - cmd = (WMI_SET_PMKID_LIST_CMD *)(A_NETBUF_DATA(osbuf)); - cmd->numPMKID = pmkInfo->numPMKID; - - for (i = 0; i < cmd->numPMKID; i++) { - A_MEMCPY(&cmd->pmkidList[i], &pmkInfo->pmkidList[i], - WMI_PMKID_LEN); - } - - return (wmi_cmd_send(wmip, osbuf, WMI_SET_PMKID_LIST_CMDID, - NO_SYNC_WMIFLAG)); -} - -A_STATUS -wmi_get_pmkid_list_cmd(struct wmi_t *wmip) -{ - void *osbuf; - - osbuf = A_NETBUF_ALLOC(0); /* no payload */ - if (osbuf == NULL) { - return A_NO_MEMORY; - } - - return (wmi_cmd_send(wmip, osbuf, WMI_GET_PMKID_LIST_CMDID, - NO_SYNC_WMIFLAG)); -} - -A_STATUS -wmi_dataSync_send(struct wmi_t *wmip, void *osbuf, WMI_PRI_STREAM_ID streamID) -{ - WMI_DATA_HDR *dtHdr; - - A_ASSERT(streamID != WMI_CONTROL_PRI); - A_ASSERT(osbuf != NULL); - - if (A_NETBUF_PUSH(osbuf, sizeof(WMI_DATA_HDR)) != A_OK) { - return A_NO_MEMORY; - } - - dtHdr = (WMI_DATA_HDR *)A_NETBUF_DATA(osbuf); - dtHdr->info = - (SYNC_MSGTYPE & WMI_DATA_HDR_MSG_TYPE_MASK) << WMI_DATA_HDR_MSG_TYPE_SHIFT; - - A_DPRINTF(DBG_WMI, (DBGFMT "Enter - streamID %d\n", DBGARG, streamID)); - - return (A_WMI_CONTROL_TX(wmip->wmi_devt, osbuf, streamID)); -} - -typedef struct _WMI_DATA_SYNC_BUFS { - A_UINT8 trafficClass; - void *osbuf; -}WMI_DATA_SYNC_BUFS; - -static A_STATUS -wmi_sync_point(struct wmi_t *wmip) -{ - void *cmd_osbuf; - WMI_DATA_SYNC_BUFS dataSyncBufs[WMM_NUM_AC]; - A_UINT8 i,numPriStreams=0; - A_STATUS status; - - A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG)); - - memset(dataSyncBufs,0,sizeof(dataSyncBufs)); - - /* lock out while we walk through the priority list and assemble our local array */ - LOCK_WMI(wmip); - - for (i=0; i < WMM_NUM_AC ; i++) { - if (wmip->wmi_fatPipeExists & (1 << i)) { - numPriStreams++; - dataSyncBufs[numPriStreams-1].trafficClass = i; - } - } - - UNLOCK_WMI(wmip); - - /* dataSyncBufs is now filled with entries (starting at index 0) containing valid streamIDs */ - - do { - /* - * We allocate all network buffers needed so we will be able to - * send all required frames. - */ - cmd_osbuf = A_NETBUF_ALLOC(0); /* no payload */ - if (cmd_osbuf == NULL) { - status = A_NO_MEMORY; - break; - } - - for (i=0; i < numPriStreams ; i++) { - dataSyncBufs[i].osbuf = A_NETBUF_ALLOC(0); - if (dataSyncBufs[i].osbuf == NULL) { - status = A_NO_MEMORY; - break; - } - } //end for - - /* - * Send sync cmd followed by sync data messages on all endpoints being - * used - */ - status = wmi_cmd_send(wmip, cmd_osbuf, WMI_SYNCHRONIZE_CMDID, - NO_SYNC_WMIFLAG); - - if (A_FAILED(status)) { - break; - } - /* cmd buffer sent, we no longer own it */ - cmd_osbuf = NULL; - - for(i=0; i < numPriStreams; i++) { - A_ASSERT(dataSyncBufs[i].osbuf != NULL); - - status = wmi_dataSync_send(wmip, dataSyncBufs[i].osbuf, - WMI_ACCESSCATEGORY_WMISTREAM(wmip,dataSyncBufs[i].trafficClass)); - - if (A_FAILED(status)) { - break; - } - /* we don't own this buffer anymore, NULL it out of the array so it - * won't get cleaned up */ - dataSyncBufs[i].osbuf = NULL; - } //end for - - } while(FALSE); - - /* free up any resources left over (possibly due to an error) */ - - if (cmd_osbuf != NULL) { - A_NETBUF_FREE(cmd_osbuf); - } - - for (i = 0; i < numPriStreams; i++) { - if (dataSyncBufs[i].osbuf != NULL) { - A_NETBUF_FREE(dataSyncBufs[i].osbuf); - } - } - - return (status); -} - -A_STATUS -wmi_create_pstream_cmd(struct wmi_t *wmip, WMI_CREATE_PSTREAM_CMD *params) -{ - void *osbuf; - WMI_CREATE_PSTREAM_CMD *cmd; - A_UINT16 activeTsids=0; - A_UINT8 fatPipeExistsForAC=0; - - /* Validate all the parameters. */ - if( !((params->userPriority < 8) && - (params->userPriority <= 0x7) && - (convert_userPriority_to_trafficClass(params->userPriority) == params->trafficClass) && - (params->trafficDirection == UPLINK_TRAFFIC || - params->trafficDirection == DNLINK_TRAFFIC || - params->trafficDirection == BIDIR_TRAFFIC) && - (params->trafficType == TRAFFIC_TYPE_APERIODIC || - params->trafficType == TRAFFIC_TYPE_PERIODIC ) && - (params->voicePSCapability == DISABLE_FOR_THIS_AC || - params->voicePSCapability == ENABLE_FOR_THIS_AC || - params->voicePSCapability == ENABLE_FOR_ALL_AC) && - (params->tsid == WMI_IMPLICIT_PSTREAM || params->tsid <= WMI_MAX_THINSTREAM)) ) - { - return A_EINVAL; - } - - osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); - if (osbuf == NULL) { - return A_NO_MEMORY; - } - - A_NETBUF_PUT(osbuf, sizeof(*cmd)); - - A_DPRINTF(DBG_WMI, - (DBGFMT "Sending create_pstream_cmd: ac=%d tsid:%d\n", DBGARG, - params->trafficClass, params->tsid)); - - cmd = (WMI_CREATE_PSTREAM_CMD *)(A_NETBUF_DATA(osbuf)); - A_MEMZERO(cmd, sizeof(*cmd)); - A_MEMCPY(cmd, params, sizeof(*cmd)); - - /* this is an implicitly created Fat pipe */ - if (params->tsid == WMI_IMPLICIT_PSTREAM) { - LOCK_WMI(wmip); - fatPipeExistsForAC = (wmip->wmi_fatPipeExists & (1 << params->trafficClass)); - wmip->wmi_fatPipeExists |= (1<trafficClass); - UNLOCK_WMI(wmip); - } else { - /* this is an explicitly created thin stream within a fat pipe */ - LOCK_WMI(wmip); - fatPipeExistsForAC = (wmip->wmi_fatPipeExists & (1 << params->trafficClass)); - activeTsids = wmip->wmi_streamExistsForAC[params->trafficClass]; - wmip->wmi_streamExistsForAC[params->trafficClass] |= (1<tsid); - /* if a thinstream becomes active, the fat pipe automatically - * becomes active - */ - wmip->wmi_fatPipeExists |= (1<trafficClass); - UNLOCK_WMI(wmip); - } - - /* Indicate activty change to driver layer only if this is the - * first TSID to get created in this AC explicitly or an implicit - * fat pipe is getting created. - */ - if (!fatPipeExistsForAC) { - A_WMI_STREAM_TX_ACTIVE(wmip->wmi_devt, params->trafficClass); - } - - /* mike: should be SYNC_BEFORE_WMIFLAG */ - return (wmi_cmd_send(wmip, osbuf, WMI_CREATE_PSTREAM_CMDID, - NO_SYNC_WMIFLAG)); -} - -A_STATUS -wmi_delete_pstream_cmd(struct wmi_t *wmip, A_UINT8 trafficClass, A_UINT8 tsid) -{ - void *osbuf; - WMI_DELETE_PSTREAM_CMD *cmd; - A_STATUS status; - A_UINT16 activeTsids=0; - - osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); - if (osbuf == NULL) { - return A_NO_MEMORY; - } - - A_NETBUF_PUT(osbuf, sizeof(*cmd)); - - cmd = (WMI_DELETE_PSTREAM_CMD *)(A_NETBUF_DATA(osbuf)); - A_MEMZERO(cmd, sizeof(*cmd)); - - cmd->trafficClass = trafficClass; - cmd->tsid = tsid; - - LOCK_WMI(wmip); - activeTsids = wmip->wmi_streamExistsForAC[trafficClass]; - UNLOCK_WMI(wmip); - - /* Check if the tsid was created & exists */ - if (!(activeTsids & (1<wmi_streamExistsForAC[trafficClass] &= ~(1<wmi_streamExistsForAC[trafficClass]; - UNLOCK_WMI(wmip); - - - /* Indicate stream inactivity to driver layer only if all tsids - * within this AC are deleted. - */ - if(!activeTsids) { - A_WMI_STREAM_TX_INACTIVE(wmip->wmi_devt, trafficClass); - wmip->wmi_fatPipeExists &= ~(1<rateIndex = index; - - return (wmi_cmd_send(wmip, osbuf, WMI_SET_BITRATE_CMDID, NO_SYNC_WMIFLAG)); -} - -A_STATUS -wmi_get_bitrate_cmd(struct wmi_t *wmip) -{ - void *osbuf; - - osbuf = A_NETBUF_ALLOC(0); /* no payload */ - if (osbuf == NULL) { - return A_NO_MEMORY; - } - - return (wmi_cmd_send(wmip, osbuf, WMI_GET_BITRATE_CMDID, NO_SYNC_WMIFLAG)); -} - -/* - * Returns TRUE iff the given rate index is legal in the current PHY mode. - */ -A_BOOL -wmi_is_bitrate_index_valid(struct wmi_t *wmip, A_UINT32 rateIndex) -{ - WMI_PHY_MODE phyMode = wmip->wmi_phyMode; - A_BOOL isValid = TRUE; - switch(phyMode) { - case WMI_11A_MODE: - if ((rateIndex < MODE_A_SUPPORT_RATE_START) || (rateIndex > MODE_A_SUPPORT_RATE_STOP)) { - isValid = FALSE; - } - break; - - case WMI_11B_MODE: - if ((rateIndex < MODE_B_SUPPORT_RATE_START) || (rateIndex > MODE_B_SUPPORT_RATE_STOP)) { - isValid = FALSE; - } - break; - - case WMI_11GONLY_MODE: - if ((rateIndex < MODE_GONLY_SUPPORT_RATE_START) || (rateIndex > MODE_GONLY_SUPPORT_RATE_STOP)) { - isValid = FALSE; - } - break; - - case WMI_11G_MODE: - case WMI_11AG_MODE: - if ((rateIndex < MODE_G_SUPPORT_RATE_START) || (rateIndex > MODE_G_SUPPORT_RATE_STOP)) { - isValid = FALSE; - } - break; - - default: - A_ASSERT(FALSE); - break; - } - - return isValid; -} - -A_INT8 -wmi_validate_bitrate(struct wmi_t *wmip, A_INT32 rate) -{ - A_INT8 i; - if (rate != -1) - { - for (i=0;;i++) - { - if (wmi_rateTable[(A_UINT32) i] == 0) { - return A_EINVAL; - } - if (wmi_rateTable[(A_UINT32) i] == rate) { - break; - } - } - } - else{ - i = -1; - } - - if(wmi_is_bitrate_index_valid(wmip, i) != TRUE) { - return A_EINVAL; - } - - return i; -} - -A_STATUS -wmi_set_fixrates_cmd(struct wmi_t *wmip, A_INT16 fixRatesMask) -{ - void *osbuf; - WMI_FIX_RATES_CMD *cmd; - A_UINT32 rateIndex; - - /* Make sure all rates in the mask are valid in the current PHY mode */ - for(rateIndex = 0; rateIndex < MAX_NUMBER_OF_SUPPORT_RATES; rateIndex++) { - if((1 << rateIndex) & (A_UINT32)fixRatesMask) { - if(wmi_is_bitrate_index_valid(wmip, rateIndex) != TRUE) { - A_DPRINTF(DBG_WMI, (DBGFMT "Set Fix Rates command failed: Given rate is illegal in current PHY mode\n", DBGARG)); - return A_EINVAL; - } - } - } - - - osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); - if (osbuf == NULL) { - return A_NO_MEMORY; - } - - A_NETBUF_PUT(osbuf, sizeof(*cmd)); - - cmd = (WMI_FIX_RATES_CMD *)(A_NETBUF_DATA(osbuf)); - A_MEMZERO(cmd, sizeof(*cmd)); - - cmd->fixRateMask = fixRatesMask; - - return (wmi_cmd_send(wmip, osbuf, WMI_SET_FIXRATES_CMDID, NO_SYNC_WMIFLAG)); -} - -A_STATUS -wmi_get_ratemask_cmd(struct wmi_t *wmip) -{ - void *osbuf; - - osbuf = A_NETBUF_ALLOC(0); /* no payload */ - if (osbuf == NULL) { - return A_NO_MEMORY; - } - - return (wmi_cmd_send(wmip, osbuf, WMI_GET_FIXRATES_CMDID, NO_SYNC_WMIFLAG)); -} - -A_STATUS -wmi_get_channelList_cmd(struct wmi_t *wmip) -{ - void *osbuf; - - osbuf = A_NETBUF_ALLOC(0); /* no payload */ - if (osbuf == NULL) { - return A_NO_MEMORY; - } - - return (wmi_cmd_send(wmip, osbuf, WMI_GET_CHANNEL_LIST_CMDID, - NO_SYNC_WMIFLAG)); -} - -/* - * used to generate a wmi sey channel Parameters cmd. - * mode should always be specified and corresponds to the phy mode of the - * wlan. - * numChan should alway sbe specified. If zero indicates that all available - * channels should be used. - * channelList is an array of channel frequencies (in Mhz) which the radio - * should limit its operation to. It should be NULL if numChan == 0. Size of - * array should correspond to numChan entries. - */ -A_STATUS -wmi_set_channelParams_cmd(struct wmi_t *wmip, A_UINT8 scanParam, - WMI_PHY_MODE mode, A_INT8 numChan, - A_UINT16 *channelList) -{ - void *osbuf; - WMI_CHANNEL_PARAMS_CMD *cmd; - A_INT8 size; - - size = sizeof (*cmd); - - if (numChan) { - if (numChan > WMI_MAX_CHANNELS) { - return A_EINVAL; - } - size += sizeof(A_UINT16) * (numChan - 1); - } - - osbuf = A_NETBUF_ALLOC(size); - if (osbuf == NULL) { - return A_NO_MEMORY; - } - - A_NETBUF_PUT(osbuf, size); - - cmd = (WMI_CHANNEL_PARAMS_CMD *)(A_NETBUF_DATA(osbuf)); - A_MEMZERO(cmd, size); - - wmip->wmi_phyMode = mode; - cmd->scanParam = scanParam; - cmd->phyMode = mode; - cmd->numChannels = numChan; - A_MEMCPY(cmd->channelList, channelList, numChan * sizeof(A_UINT16)); - - return (wmi_cmd_send(wmip, osbuf, WMI_SET_CHANNEL_PARAMS_CMDID, - NO_SYNC_WMIFLAG)); -} - -A_STATUS -wmi_set_rssi_threshold_params(struct wmi_t *wmip, - WMI_RSSI_THRESHOLD_PARAMS_CMD *rssiCmd) -{ - void *osbuf; - A_INT8 size; - WMI_RSSI_THRESHOLD_PARAMS_CMD *cmd; - /* These values are in ascending order */ - if( rssiCmd->thresholdAbove6_Val <= rssiCmd->thresholdAbove5_Val || - rssiCmd->thresholdAbove5_Val <= rssiCmd->thresholdAbove4_Val || - rssiCmd->thresholdAbove4_Val <= rssiCmd->thresholdAbove3_Val || - rssiCmd->thresholdAbove3_Val <= rssiCmd->thresholdAbove2_Val || - rssiCmd->thresholdAbove2_Val <= rssiCmd->thresholdAbove1_Val || - rssiCmd->thresholdBelow6_Val <= rssiCmd->thresholdBelow5_Val || - rssiCmd->thresholdBelow5_Val <= rssiCmd->thresholdBelow4_Val || - rssiCmd->thresholdBelow4_Val <= rssiCmd->thresholdBelow3_Val || - rssiCmd->thresholdBelow3_Val <= rssiCmd->thresholdBelow2_Val || - rssiCmd->thresholdBelow2_Val <= rssiCmd->thresholdBelow1_Val) { - - return A_EINVAL; - } - - size = sizeof (*cmd); - - osbuf = A_NETBUF_ALLOC(size); - if (osbuf == NULL) { - return A_NO_MEMORY; - } - - A_NETBUF_PUT(osbuf, size); - - cmd = (WMI_RSSI_THRESHOLD_PARAMS_CMD *)(A_NETBUF_DATA(osbuf)); - A_MEMZERO(cmd, size); - A_MEMCPY(cmd, rssiCmd, sizeof(WMI_RSSI_THRESHOLD_PARAMS_CMD)); - - return (wmi_cmd_send(wmip, osbuf, WMI_RSSI_THRESHOLD_PARAMS_CMDID, - NO_SYNC_WMIFLAG)); -} - -A_STATUS -wmi_set_host_sleep_mode_cmd(struct wmi_t *wmip, - WMI_SET_HOST_SLEEP_MODE_CMD *hostModeCmd) -{ - void *osbuf; - A_INT8 size; - WMI_SET_HOST_SLEEP_MODE_CMD *cmd; - - if( hostModeCmd->awake == hostModeCmd->asleep) { - return A_EINVAL; - } - - size = sizeof (*cmd); - - osbuf = A_NETBUF_ALLOC(size); - if (osbuf == NULL) { - return A_NO_MEMORY; - } - - A_NETBUF_PUT(osbuf, size); - - cmd = (WMI_SET_HOST_SLEEP_MODE_CMD *)(A_NETBUF_DATA(osbuf)); - A_MEMZERO(cmd, size); - A_MEMCPY(cmd, hostModeCmd, sizeof(WMI_SET_HOST_SLEEP_MODE_CMD)); - - return (wmi_cmd_send(wmip, osbuf, WMI_SET_HOST_SLEEP_MODE_CMDID, - NO_SYNC_WMIFLAG)); -} - -A_STATUS -wmi_set_wow_mode_cmd(struct wmi_t *wmip, - WMI_SET_WOW_MODE_CMD *wowModeCmd) -{ - void *osbuf; - A_INT8 size; - WMI_SET_WOW_MODE_CMD *cmd; - - size = sizeof (*cmd); - - osbuf = A_NETBUF_ALLOC(size); - if (osbuf == NULL) { - return A_NO_MEMORY; - } - - A_NETBUF_PUT(osbuf, size); - - cmd = (WMI_SET_WOW_MODE_CMD *)(A_NETBUF_DATA(osbuf)); - A_MEMZERO(cmd, size); - A_MEMCPY(cmd, wowModeCmd, sizeof(WMI_SET_WOW_MODE_CMD)); - - return (wmi_cmd_send(wmip, osbuf, WMI_SET_WOW_MODE_CMDID, - NO_SYNC_WMIFLAG)); - -} - -A_STATUS -wmi_get_wow_list_cmd(struct wmi_t *wmip, - WMI_GET_WOW_LIST_CMD *wowListCmd) -{ - void *osbuf; - A_INT8 size; - WMI_GET_WOW_LIST_CMD *cmd; - - size = sizeof (*cmd); - - osbuf = A_NETBUF_ALLOC(size); - if (osbuf == NULL) { - return A_NO_MEMORY; - } - - A_NETBUF_PUT(osbuf, size); - - cmd = (WMI_GET_WOW_LIST_CMD *)(A_NETBUF_DATA(osbuf)); - A_MEMZERO(cmd, size); - A_MEMCPY(cmd, wowListCmd, sizeof(WMI_GET_WOW_LIST_CMD)); - - return (wmi_cmd_send(wmip, osbuf, WMI_GET_WOW_LIST_CMDID, - NO_SYNC_WMIFLAG)); - -} - -static A_STATUS -wmi_get_wow_list_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len) -{ - WMI_GET_WOW_LIST_REPLY *reply; - - if (len < sizeof(WMI_GET_WOW_LIST_REPLY)) { - return A_EINVAL; - } - reply = (WMI_GET_WOW_LIST_REPLY *)datap; - - A_WMI_WOW_LIST_EVENT(wmip->wmi_devt, reply->num_filters, - reply); - - return A_OK; -} - -A_STATUS wmi_add_wow_pattern_cmd(struct wmi_t *wmip, - WMI_ADD_WOW_PATTERN_CMD *addWowCmd, - A_UINT8* pattern, A_UINT8* mask, - A_UINT8 pattern_size) -{ - void *osbuf; - A_INT8 size; - WMI_ADD_WOW_PATTERN_CMD *cmd; - A_UINT8 *filter_mask = NULL; - - size = sizeof (*cmd); - - size += ((2 * addWowCmd->filter_size)* sizeof(A_UINT8)); - osbuf = A_NETBUF_ALLOC(size); - if (osbuf == NULL) { - return A_NO_MEMORY; - } - - A_NETBUF_PUT(osbuf, size); - - cmd = (WMI_ADD_WOW_PATTERN_CMD *)(A_NETBUF_DATA(osbuf)); - cmd->filter_list_id = addWowCmd->filter_list_id; - cmd->filter_offset = addWowCmd->filter_offset; - cmd->filter_size = addWowCmd->filter_size; - - A_MEMCPY(cmd->filter, pattern, addWowCmd->filter_size); - - filter_mask = (A_UINT8*)(cmd->filter + cmd->filter_size); - A_MEMCPY(filter_mask, mask, addWowCmd->filter_size); - - - return (wmi_cmd_send(wmip, osbuf, WMI_ADD_WOW_PATTERN_CMDID, - NO_SYNC_WMIFLAG)); -} - -A_STATUS -wmi_del_wow_pattern_cmd(struct wmi_t *wmip, - WMI_DEL_WOW_PATTERN_CMD *delWowCmd) -{ - void *osbuf; - A_INT8 size; - WMI_DEL_WOW_PATTERN_CMD *cmd; - - size = sizeof (*cmd); - - osbuf = A_NETBUF_ALLOC(size); - if (osbuf == NULL) { - return A_NO_MEMORY; - } - - A_NETBUF_PUT(osbuf, size); - - cmd = (WMI_DEL_WOW_PATTERN_CMD *)(A_NETBUF_DATA(osbuf)); - A_MEMZERO(cmd, size); - A_MEMCPY(cmd, delWowCmd, sizeof(WMI_DEL_WOW_PATTERN_CMD)); - - return (wmi_cmd_send(wmip, osbuf, WMI_DEL_WOW_PATTERN_CMDID, - NO_SYNC_WMIFLAG)); - -} - -A_STATUS -wmi_set_snr_threshold_params(struct wmi_t *wmip, - WMI_SNR_THRESHOLD_PARAMS_CMD *snrCmd) -{ - void *osbuf; - A_INT8 size; - WMI_SNR_THRESHOLD_PARAMS_CMD *cmd; - /* These values are in ascending order */ - if( snrCmd->thresholdAbove4_Val <= snrCmd->thresholdAbove3_Val || - snrCmd->thresholdAbove3_Val <= snrCmd->thresholdAbove2_Val || - snrCmd->thresholdAbove2_Val <= snrCmd->thresholdAbove1_Val || - snrCmd->thresholdBelow4_Val <= snrCmd->thresholdBelow3_Val || - snrCmd->thresholdBelow3_Val <= snrCmd->thresholdBelow2_Val || - snrCmd->thresholdBelow2_Val <= snrCmd->thresholdBelow1_Val) { - - return A_EINVAL; - } - - size = sizeof (*cmd); - - osbuf = A_NETBUF_ALLOC(size); - if (osbuf == NULL) { - return A_NO_MEMORY; - } - - A_NETBUF_PUT(osbuf, size); - - cmd = (WMI_SNR_THRESHOLD_PARAMS_CMD *)(A_NETBUF_DATA(osbuf)); - A_MEMZERO(cmd, size); - A_MEMCPY(cmd, snrCmd, sizeof(WMI_SNR_THRESHOLD_PARAMS_CMD)); - - return (wmi_cmd_send(wmip, osbuf, WMI_SNR_THRESHOLD_PARAMS_CMDID, - NO_SYNC_WMIFLAG)); -} - -A_STATUS -wmi_clr_rssi_snr(struct wmi_t *wmip) -{ - void *osbuf; - - osbuf = A_NETBUF_ALLOC(sizeof(int)); - if (osbuf == NULL) { - return A_NO_MEMORY; - } - - return (wmi_cmd_send(wmip, osbuf, WMI_CLR_RSSI_SNR_CMDID, - NO_SYNC_WMIFLAG)); -} - -A_STATUS -wmi_set_lq_threshold_params(struct wmi_t *wmip, - WMI_LQ_THRESHOLD_PARAMS_CMD *lqCmd) -{ - void *osbuf; - A_INT8 size; - WMI_LQ_THRESHOLD_PARAMS_CMD *cmd; - /* These values are in ascending order */ - if( lqCmd->thresholdAbove4_Val <= lqCmd->thresholdAbove3_Val || - lqCmd->thresholdAbove3_Val <= lqCmd->thresholdAbove2_Val || - lqCmd->thresholdAbove2_Val <= lqCmd->thresholdAbove1_Val || - lqCmd->thresholdBelow4_Val <= lqCmd->thresholdBelow3_Val || - lqCmd->thresholdBelow3_Val <= lqCmd->thresholdBelow2_Val || - lqCmd->thresholdBelow2_Val <= lqCmd->thresholdBelow1_Val ) { - - return A_EINVAL; - } - - size = sizeof (*cmd); - - osbuf = A_NETBUF_ALLOC(size); - if (osbuf == NULL) { - return A_NO_MEMORY; - } - - A_NETBUF_PUT(osbuf, size); - - cmd = (WMI_LQ_THRESHOLD_PARAMS_CMD *)(A_NETBUF_DATA(osbuf)); - A_MEMZERO(cmd, size); - A_MEMCPY(cmd, lqCmd, sizeof(WMI_LQ_THRESHOLD_PARAMS_CMD)); - - return (wmi_cmd_send(wmip, osbuf, WMI_LQ_THRESHOLD_PARAMS_CMDID, - NO_SYNC_WMIFLAG)); -} - -A_STATUS -wmi_set_error_report_bitmask(struct wmi_t *wmip, A_UINT32 mask) -{ - void *osbuf; - A_INT8 size; - WMI_TARGET_ERROR_REPORT_BITMASK *cmd; - - size = sizeof (*cmd); - - osbuf = A_NETBUF_ALLOC(size); - if (osbuf == NULL) { - return A_NO_MEMORY; - } - - A_NETBUF_PUT(osbuf, size); - - cmd = (WMI_TARGET_ERROR_REPORT_BITMASK *)(A_NETBUF_DATA(osbuf)); - A_MEMZERO(cmd, size); - - cmd->bitmask = mask; - - return (wmi_cmd_send(wmip, osbuf, WMI_TARGET_ERROR_REPORT_BITMASK_CMDID, - NO_SYNC_WMIFLAG)); -} - -A_STATUS -wmi_get_challenge_resp_cmd(struct wmi_t *wmip, A_UINT32 cookie, A_UINT32 source) -{ - void *osbuf; - WMIX_HB_CHALLENGE_RESP_CMD *cmd; - - osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); - if (osbuf == NULL) { - return A_NO_MEMORY; - } - - A_NETBUF_PUT(osbuf, sizeof(*cmd)); - - cmd = (WMIX_HB_CHALLENGE_RESP_CMD *)(A_NETBUF_DATA(osbuf)); - cmd->cookie = cookie; - cmd->source = source; - - return (wmi_cmd_send_xtnd(wmip, osbuf, WMIX_HB_CHALLENGE_RESP_CMDID, - NO_SYNC_WMIFLAG)); -} - -A_STATUS -wmi_config_debug_module_cmd(struct wmi_t *wmip, A_UINT16 mmask, - A_UINT16 tsr, A_BOOL rep, A_UINT16 size, - A_UINT32 valid) -{ - void *osbuf; - WMIX_DBGLOG_CFG_MODULE_CMD *cmd; - - osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); - if (osbuf == NULL) { - return A_NO_MEMORY; - } - - A_NETBUF_PUT(osbuf, sizeof(*cmd)); - - cmd = (WMIX_DBGLOG_CFG_MODULE_CMD *)(A_NETBUF_DATA(osbuf)); - cmd->config.cfgmmask = mmask; - cmd->config.cfgtsr = tsr; - cmd->config.cfgrep = rep; - cmd->config.cfgsize = size; - cmd->config.cfgvalid = valid; - - return (wmi_cmd_send_xtnd(wmip, osbuf, WMIX_DBGLOG_CFG_MODULE_CMDID, - NO_SYNC_WMIFLAG)); -} - -A_STATUS -wmi_get_stats_cmd(struct wmi_t *wmip) -{ - void *osbuf; - - osbuf = A_NETBUF_ALLOC(0); /* no payload */ - if (osbuf == NULL) { - return A_NO_MEMORY; - } - - return (wmi_cmd_send(wmip, osbuf, WMI_GET_STATISTICS_CMDID, - NO_SYNC_WMIFLAG)); -} - -A_STATUS -wmi_addBadAp_cmd(struct wmi_t *wmip, A_UINT8 apIndex, A_UINT8 *bssid) -{ - void *osbuf; - WMI_ADD_BAD_AP_CMD *cmd; - - if ((bssid == NULL) || (apIndex > WMI_MAX_BAD_AP_INDEX)) { - return A_EINVAL; - } - - osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); - if (osbuf == NULL) { - return A_NO_MEMORY; - } - - A_NETBUF_PUT(osbuf, sizeof(*cmd)); - - cmd = (WMI_ADD_BAD_AP_CMD *)(A_NETBUF_DATA(osbuf)); - cmd->badApIndex = apIndex; - A_MEMCPY(cmd->bssid, bssid, sizeof(cmd->bssid)); - - return (wmi_cmd_send(wmip, osbuf, WMI_ADD_BAD_AP_CMDID, NO_SYNC_WMIFLAG)); -} - -A_STATUS -wmi_deleteBadAp_cmd(struct wmi_t *wmip, A_UINT8 apIndex) -{ - void *osbuf; - WMI_DELETE_BAD_AP_CMD *cmd; - - if (apIndex > WMI_MAX_BAD_AP_INDEX) { - return A_EINVAL; - } - - osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); - if (osbuf == NULL) { - return A_NO_MEMORY; - } - - A_NETBUF_PUT(osbuf, sizeof(*cmd)); - - cmd = (WMI_DELETE_BAD_AP_CMD *)(A_NETBUF_DATA(osbuf)); - cmd->badApIndex = apIndex; - - return (wmi_cmd_send(wmip, osbuf, WMI_DELETE_BAD_AP_CMDID, - NO_SYNC_WMIFLAG)); -} - -A_STATUS -wmi_set_txPwr_cmd(struct wmi_t *wmip, A_UINT8 dbM) -{ - void *osbuf; - WMI_SET_TX_PWR_CMD *cmd; - - osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); - if (osbuf == NULL) { - return A_NO_MEMORY; - } - - A_NETBUF_PUT(osbuf, sizeof(*cmd)); - - cmd = (WMI_SET_TX_PWR_CMD *)(A_NETBUF_DATA(osbuf)); - cmd->dbM = dbM; - - return (wmi_cmd_send(wmip, osbuf, WMI_SET_TX_PWR_CMDID, NO_SYNC_WMIFLAG)); -} - -A_STATUS -wmi_get_txPwr_cmd(struct wmi_t *wmip) -{ - void *osbuf; - - osbuf = A_NETBUF_ALLOC(0); /* no payload */ - if (osbuf == NULL) { - return A_NO_MEMORY; - } - - return (wmi_cmd_send(wmip, osbuf, WMI_GET_TX_PWR_CMDID, NO_SYNC_WMIFLAG)); -} - -A_STATUS -wmi_switch_radio(struct wmi_t *wmip, A_UINT8 on) -{ - WMI_SCAN_PARAMS_CMD scParams = {0, 0, 0, 0, 0, - WMI_SHORTSCANRATIO_DEFAULT, - DEFAULT_SCAN_CTRL_FLAGS, - 0}; - - if (on) { - /* Enable foreground scanning */ - if (wmi_scanparams_cmd(wmip, scParams.fg_start_period, - scParams.fg_end_period, - scParams.bg_period, - scParams.minact_chdwell_time, - scParams.maxact_chdwell_time, - scParams.pas_chdwell_time, - scParams.shortScanRatio, - scParams.scanCtrlFlags, - scParams.max_dfsch_act_time) != A_OK) { - return -EIO; - } - } else { - wmi_disconnect_cmd(wmip); - if (wmi_scanparams_cmd(wmip, 0xFFFF, 0, 0, 0, - 0, 0, 0, 0xFF, 0) != A_OK) { - return -EIO; - } - } - - return A_OK; -} - - -A_UINT16 -wmi_get_mapped_qos_queue(struct wmi_t *wmip, A_UINT8 trafficClass) -{ - A_UINT16 activeTsids=0; - - LOCK_WMI(wmip); - activeTsids = wmip->wmi_streamExistsForAC[trafficClass]; - UNLOCK_WMI(wmip); - - return activeTsids; -} - -A_STATUS -wmi_get_roam_tbl_cmd(struct wmi_t *wmip) -{ - void *osbuf; - - osbuf = A_NETBUF_ALLOC(0); /* no payload */ - if (osbuf == NULL) { - return A_NO_MEMORY; - } - - return (wmi_cmd_send(wmip, osbuf, WMI_GET_ROAM_TBL_CMDID, - NO_SYNC_WMIFLAG)); -} - -A_STATUS -wmi_get_roam_data_cmd(struct wmi_t *wmip, A_UINT8 roamDataType) -{ - void *osbuf; - A_UINT32 size = sizeof(A_UINT8); - WMI_TARGET_ROAM_DATA *cmd; - - osbuf = A_NETBUF_ALLOC(size); /* no payload */ - if (osbuf == NULL) { - return A_NO_MEMORY; - } - - A_NETBUF_PUT(osbuf, size); - - cmd = (WMI_TARGET_ROAM_DATA *)(A_NETBUF_DATA(osbuf)); - cmd->roamDataType = roamDataType; - - return (wmi_cmd_send(wmip, osbuf, WMI_GET_ROAM_DATA_CMDID, - NO_SYNC_WMIFLAG)); -} - -A_STATUS -wmi_set_roam_ctrl_cmd(struct wmi_t *wmip, WMI_SET_ROAM_CTRL_CMD *p, - A_UINT8 size) -{ - void *osbuf; - WMI_SET_ROAM_CTRL_CMD *cmd; - - osbuf = A_NETBUF_ALLOC(size); - if (osbuf == NULL) { - return A_NO_MEMORY; - } - - A_NETBUF_PUT(osbuf, size); - - cmd = (WMI_SET_ROAM_CTRL_CMD *)(A_NETBUF_DATA(osbuf)); - A_MEMZERO(cmd, size); - - A_MEMCPY(cmd, p, size); - - return (wmi_cmd_send(wmip, osbuf, WMI_SET_ROAM_CTRL_CMDID, - NO_SYNC_WMIFLAG)); -} - -A_STATUS -wmi_set_powersave_timers_cmd(struct wmi_t *wmip, - WMI_POWERSAVE_TIMERS_POLICY_CMD *pCmd, - A_UINT8 size) -{ - void *osbuf; - WMI_POWERSAVE_TIMERS_POLICY_CMD *cmd; - - /* These timers can't be zero */ - if(!pCmd->psPollTimeout || !pCmd->triggerTimeout || - !(pCmd->apsdTimPolicy == IGNORE_TIM_ALL_QUEUES_APSD || - pCmd->apsdTimPolicy == PROCESS_TIM_ALL_QUEUES_APSD) || - !(pCmd->simulatedAPSDTimPolicy == IGNORE_TIM_SIMULATED_APSD || - pCmd->simulatedAPSDTimPolicy == PROCESS_TIM_SIMULATED_APSD)) - return A_EINVAL; - - osbuf = A_NETBUF_ALLOC(size); - if (osbuf == NULL) { - return A_NO_MEMORY; - } - - A_NETBUF_PUT(osbuf, size); - - cmd = (WMI_POWERSAVE_TIMERS_POLICY_CMD *)(A_NETBUF_DATA(osbuf)); - A_MEMZERO(cmd, size); - - A_MEMCPY(cmd, pCmd, size); - - return (wmi_cmd_send(wmip, osbuf, WMI_SET_POWERSAVE_TIMERS_POLICY_CMDID, - NO_SYNC_WMIFLAG)); -} - -#ifdef CONFIG_HOST_GPIO_SUPPORT -/* Send a command to Target to change GPIO output pins. */ -A_STATUS -wmi_gpio_output_set(struct wmi_t *wmip, - A_UINT32 set_mask, - A_UINT32 clear_mask, - A_UINT32 enable_mask, - A_UINT32 disable_mask) -{ - void *osbuf; - WMIX_GPIO_OUTPUT_SET_CMD *output_set; - int size; - - size = sizeof(*output_set); - - A_DPRINTF(DBG_WMI, - (DBGFMT "Enter - set=0x%x clear=0x%x enb=0x%x dis=0x%x\n", DBGARG, - set_mask, clear_mask, enable_mask, disable_mask)); - - osbuf = A_NETBUF_ALLOC(size); - if (osbuf == NULL) { - return A_NO_MEMORY; - } - A_NETBUF_PUT(osbuf, size); - output_set = (WMIX_GPIO_OUTPUT_SET_CMD *)(A_NETBUF_DATA(osbuf)); - - output_set->set_mask = set_mask; - output_set->clear_mask = clear_mask; - output_set->enable_mask = enable_mask; - output_set->disable_mask = disable_mask; - - return (wmi_cmd_send_xtnd(wmip, osbuf, WMIX_GPIO_OUTPUT_SET_CMDID, - NO_SYNC_WMIFLAG)); -} - -/* Send a command to the Target requesting state of the GPIO input pins */ -A_STATUS -wmi_gpio_input_get(struct wmi_t *wmip) -{ - void *osbuf; - - A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG)); - - osbuf = A_NETBUF_ALLOC(0); - if (osbuf == NULL) { - return A_NO_MEMORY; - } - - return (wmi_cmd_send_xtnd(wmip, osbuf, WMIX_GPIO_INPUT_GET_CMDID, - NO_SYNC_WMIFLAG)); -} - -/* Send a command to the Target that changes the value of a GPIO register. */ -A_STATUS -wmi_gpio_register_set(struct wmi_t *wmip, - A_UINT32 gpioreg_id, - A_UINT32 value) -{ - void *osbuf; - WMIX_GPIO_REGISTER_SET_CMD *register_set; - int size; - - size = sizeof(*register_set); - - A_DPRINTF(DBG_WMI, - (DBGFMT "Enter - reg=%d value=0x%x\n", DBGARG, gpioreg_id, value)); - - osbuf = A_NETBUF_ALLOC(size); - if (osbuf == NULL) { - return A_NO_MEMORY; - } - A_NETBUF_PUT(osbuf, size); - register_set = (WMIX_GPIO_REGISTER_SET_CMD *)(A_NETBUF_DATA(osbuf)); - - register_set->gpioreg_id = gpioreg_id; - register_set->value = value; - - return (wmi_cmd_send_xtnd(wmip, osbuf, WMIX_GPIO_REGISTER_SET_CMDID, - NO_SYNC_WMIFLAG)); -} - -/* Send a command to the Target to fetch the value of a GPIO register. */ -A_STATUS -wmi_gpio_register_get(struct wmi_t *wmip, - A_UINT32 gpioreg_id) -{ - void *osbuf; - WMIX_GPIO_REGISTER_GET_CMD *register_get; - int size; - - size = sizeof(*register_get); - - A_DPRINTF(DBG_WMI, (DBGFMT "Enter - reg=%d\n", DBGARG, gpioreg_id)); - - osbuf = A_NETBUF_ALLOC(size); - if (osbuf == NULL) { - return A_NO_MEMORY; - } - A_NETBUF_PUT(osbuf, size); - register_get = (WMIX_GPIO_REGISTER_GET_CMD *)(A_NETBUF_DATA(osbuf)); - - register_get->gpioreg_id = gpioreg_id; - - return (wmi_cmd_send_xtnd(wmip, osbuf, WMIX_GPIO_REGISTER_GET_CMDID, - NO_SYNC_WMIFLAG)); -} - -/* Send a command to the Target acknowledging some GPIO interrupts. */ -A_STATUS -wmi_gpio_intr_ack(struct wmi_t *wmip, - A_UINT32 ack_mask) -{ - void *osbuf; - WMIX_GPIO_INTR_ACK_CMD *intr_ack; - int size; - - size = sizeof(*intr_ack); - - A_DPRINTF(DBG_WMI, (DBGFMT "Enter ack_mask=0x%x\n", DBGARG, ack_mask)); - - osbuf = A_NETBUF_ALLOC(size); - if (osbuf == NULL) { - return A_NO_MEMORY; - } - A_NETBUF_PUT(osbuf, size); - intr_ack = (WMIX_GPIO_INTR_ACK_CMD *)(A_NETBUF_DATA(osbuf)); - - intr_ack->ack_mask = ack_mask; - - return (wmi_cmd_send_xtnd(wmip, osbuf, WMIX_GPIO_INTR_ACK_CMDID, - NO_SYNC_WMIFLAG)); -} -#endif /* CONFIG_HOST_GPIO_SUPPORT */ - -A_STATUS -wmi_set_access_params_cmd(struct wmi_t *wmip, A_UINT16 txop, A_UINT8 eCWmin, - A_UINT8 eCWmax, A_UINT8 aifsn) -{ - void *osbuf; - WMI_SET_ACCESS_PARAMS_CMD *cmd; - - if ((eCWmin > WMI_MAX_CW_ACPARAM) || (eCWmax > WMI_MAX_CW_ACPARAM) || - (aifsn > WMI_MAX_AIFSN_ACPARAM)) - { - return A_EINVAL; - } - - osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); - if (osbuf == NULL) { - return A_NO_MEMORY; - } - - A_NETBUF_PUT(osbuf, sizeof(*cmd)); - - cmd = (WMI_SET_ACCESS_PARAMS_CMD *)(A_NETBUF_DATA(osbuf)); - cmd->txop = txop; - cmd->eCWmin = eCWmin; - cmd->eCWmax = eCWmax; - cmd->aifsn = aifsn; - - return (wmi_cmd_send(wmip, osbuf, WMI_SET_ACCESS_PARAMS_CMDID, - NO_SYNC_WMIFLAG)); -} - -A_STATUS -wmi_set_retry_limits_cmd(struct wmi_t *wmip, A_UINT8 frameType, - A_UINT8 trafficClass, A_UINT8 maxRetries, - A_UINT8 enableNotify) -{ - void *osbuf; - WMI_SET_RETRY_LIMITS_CMD *cmd; - - if ((frameType != MGMT_FRAMETYPE) && (frameType != CONTROL_FRAMETYPE) && - (frameType != DATA_FRAMETYPE)) - { - return A_EINVAL; - } - - if (maxRetries > WMI_MAX_RETRIES) { - return A_EINVAL; - } - - if (frameType != DATA_FRAMETYPE) { - trafficClass = 0; - } - - osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); - if (osbuf == NULL) { - return A_NO_MEMORY; - } - - A_NETBUF_PUT(osbuf, sizeof(*cmd)); - - cmd = (WMI_SET_RETRY_LIMITS_CMD *)(A_NETBUF_DATA(osbuf)); - cmd->frameType = frameType; - cmd->trafficClass = trafficClass; - cmd->maxRetries = maxRetries; - cmd->enableNotify = enableNotify; - - return (wmi_cmd_send(wmip, osbuf, WMI_SET_RETRY_LIMITS_CMDID, - NO_SYNC_WMIFLAG)); -} - -void -wmi_get_current_bssid(struct wmi_t *wmip, A_UINT8 *bssid) -{ - if (bssid != NULL) { - A_MEMCPY(bssid, wmip->wmi_bssid, ATH_MAC_LEN); - } -} - -A_STATUS -wmi_set_opt_mode_cmd(struct wmi_t *wmip, A_UINT8 optMode) -{ - void *osbuf; - WMI_SET_OPT_MODE_CMD *cmd; - - osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); - if (osbuf == NULL) { - return A_NO_MEMORY; - } - - A_NETBUF_PUT(osbuf, sizeof(*cmd)); - - cmd = (WMI_SET_OPT_MODE_CMD *)(A_NETBUF_DATA(osbuf)); - A_MEMZERO(cmd, sizeof(*cmd)); - cmd->optMode = optMode; - - return (wmi_cmd_send(wmip, osbuf, WMI_SET_OPT_MODE_CMDID, - SYNC_BOTH_WMIFLAG)); -} - -A_STATUS -wmi_opt_tx_frame_cmd(struct wmi_t *wmip, - A_UINT8 frmType, - A_UINT8 *dstMacAddr, - A_UINT8 *bssid, - A_UINT16 optIEDataLen, - A_UINT8 *optIEData) -{ - void *osbuf; - WMI_OPT_TX_FRAME_CMD *cmd; - osbuf = A_NETBUF_ALLOC(optIEDataLen + sizeof(*cmd)); - if (osbuf == NULL) { - return A_NO_MEMORY; - } - - A_NETBUF_PUT(osbuf, (optIEDataLen + sizeof(*cmd))); - - cmd = (WMI_OPT_TX_FRAME_CMD *)(A_NETBUF_DATA(osbuf)); - A_MEMZERO(cmd, (optIEDataLen + sizeof(*cmd)-1)); - - cmd->frmType = frmType; - cmd->optIEDataLen = optIEDataLen; - //cmd->optIEData = (A_UINT8 *)((int)cmd + sizeof(*cmd)); - A_MEMCPY(cmd->bssid, bssid, sizeof(cmd->bssid)); - A_MEMCPY(cmd->dstAddr, dstMacAddr, sizeof(cmd->dstAddr)); - A_MEMCPY(&cmd->optIEData[0], optIEData, optIEDataLen); - - return (wmi_cmd_send(wmip, osbuf, WMI_OPT_TX_FRAME_CMDID, - NO_SYNC_WMIFLAG)); -} - -A_STATUS -wmi_set_adhoc_bconIntvl_cmd(struct wmi_t *wmip, A_UINT16 intvl) -{ - void *osbuf; - WMI_BEACON_INT_CMD *cmd; - - osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); - if (osbuf == NULL) { - return A_NO_MEMORY; - } - - A_NETBUF_PUT(osbuf, sizeof(*cmd)); - - cmd = (WMI_BEACON_INT_CMD *)(A_NETBUF_DATA(osbuf)); - A_MEMZERO(cmd, sizeof(*cmd)); - cmd->beaconInterval = intvl; - - return (wmi_cmd_send(wmip, osbuf, WMI_SET_BEACON_INT_CMDID, - NO_SYNC_WMIFLAG)); -} - - -A_STATUS -wmi_set_voice_pkt_size_cmd(struct wmi_t *wmip, A_UINT16 voicePktSize) -{ - void *osbuf; - WMI_SET_VOICE_PKT_SIZE_CMD *cmd; - - osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); - if (osbuf == NULL) { - return A_NO_MEMORY; - } - - A_NETBUF_PUT(osbuf, sizeof(*cmd)); - - cmd = (WMI_SET_VOICE_PKT_SIZE_CMD *)(A_NETBUF_DATA(osbuf)); - A_MEMZERO(cmd, sizeof(*cmd)); - cmd->voicePktSize = voicePktSize; - - return (wmi_cmd_send(wmip, osbuf, WMI_SET_VOICE_PKT_SIZE_CMDID, - NO_SYNC_WMIFLAG)); -} - - -A_STATUS -wmi_set_max_sp_len_cmd(struct wmi_t *wmip, A_UINT8 maxSPLen) -{ - void *osbuf; - WMI_SET_MAX_SP_LEN_CMD *cmd; - - /* maxSPLen is a two-bit value. If user trys to set anything - * other than this, then its invalid - */ - if(maxSPLen & ~0x03) - return A_EINVAL; - - osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); - if (osbuf == NULL) { - return A_NO_MEMORY; - } - - A_NETBUF_PUT(osbuf, sizeof(*cmd)); - - cmd = (WMI_SET_MAX_SP_LEN_CMD *)(A_NETBUF_DATA(osbuf)); - A_MEMZERO(cmd, sizeof(*cmd)); - cmd->maxSPLen = maxSPLen; - - return (wmi_cmd_send(wmip, osbuf, WMI_SET_MAX_SP_LEN_CMDID, - NO_SYNC_WMIFLAG)); -} - -A_UINT8 -convert_userPriority_to_trafficClass(A_UINT8 userPriority) -{ - return (up_to_ac[userPriority & 0x7]); -} - -A_UINT8 -wmi_get_power_mode_cmd(struct wmi_t *wmip) -{ - return wmip->wmi_powerMode; -} - -A_STATUS -wmi_verify_tspec_params(WMI_CREATE_PSTREAM_CMD *pCmd, A_BOOL tspecCompliance) -{ - return A_OK; -} - -#ifdef CONFIG_HOST_TCMD_SUPPORT -static A_STATUS -wmi_tcmd_test_report_rx(struct wmi_t *wmip, A_UINT8 *datap, int len) -{ - - A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG)); - - A_WMI_TCMD_RX_REPORT_EVENT(wmip->wmi_devt, datap, len); - - return A_OK; -} - -#endif /* CONFIG_HOST_TCMD_SUPPORT*/ - -A_STATUS -wmi_set_authmode_cmd(struct wmi_t *wmip, A_UINT8 mode) -{ - void *osbuf; - WMI_SET_AUTH_MODE_CMD *cmd; - - osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); - if (osbuf == NULL) { - return A_NO_MEMORY; - } - - A_NETBUF_PUT(osbuf, sizeof(*cmd)); - - cmd = (WMI_SET_AUTH_MODE_CMD *)(A_NETBUF_DATA(osbuf)); - A_MEMZERO(cmd, sizeof(*cmd)); - cmd->mode = mode; - - return (wmi_cmd_send(wmip, osbuf, WMI_SET_AUTH_MODE_CMDID, - NO_SYNC_WMIFLAG)); -} - -A_STATUS -wmi_set_reassocmode_cmd(struct wmi_t *wmip, A_UINT8 mode) -{ - void *osbuf; - WMI_SET_REASSOC_MODE_CMD *cmd; - - osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); - if (osbuf == NULL) { - return A_NO_MEMORY; - } - - A_NETBUF_PUT(osbuf, sizeof(*cmd)); - - cmd = (WMI_SET_REASSOC_MODE_CMD *)(A_NETBUF_DATA(osbuf)); - A_MEMZERO(cmd, sizeof(*cmd)); - cmd->mode = mode; - - return (wmi_cmd_send(wmip, osbuf, WMI_SET_REASSOC_MODE_CMDID, - NO_SYNC_WMIFLAG)); -} - -A_STATUS -wmi_set_lpreamble_cmd(struct wmi_t *wmip, A_UINT8 status) -{ - void *osbuf; - WMI_SET_LPREAMBLE_CMD *cmd; - - osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); - if (osbuf == NULL) { - return A_NO_MEMORY; - } - - A_NETBUF_PUT(osbuf, sizeof(*cmd)); - - cmd = (WMI_SET_LPREAMBLE_CMD *)(A_NETBUF_DATA(osbuf)); - A_MEMZERO(cmd, sizeof(*cmd)); - cmd->status = status; - - return (wmi_cmd_send(wmip, osbuf, WMI_SET_LPREAMBLE_CMDID, - NO_SYNC_WMIFLAG)); -} - -A_STATUS -wmi_set_rts_cmd(struct wmi_t *wmip, A_UINT16 threshold) -{ - void *osbuf; - WMI_SET_RTS_CMD *cmd; - - osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); - if (osbuf == NULL) { - return A_NO_MEMORY; - } - - A_NETBUF_PUT(osbuf, sizeof(*cmd)); - - cmd = (WMI_SET_RTS_CMD*)(A_NETBUF_DATA(osbuf)); - A_MEMZERO(cmd, sizeof(*cmd)); - cmd->threshold = threshold; - - return (wmi_cmd_send(wmip, osbuf, WMI_SET_RTS_CMDID, - NO_SYNC_WMIFLAG)); -} - -A_STATUS -wmi_set_wmm_cmd(struct wmi_t *wmip, WMI_WMM_STATUS status) -{ - void *osbuf; - WMI_SET_WMM_CMD *cmd; - - osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); - if (osbuf == NULL) { - return A_NO_MEMORY; - } - - A_NETBUF_PUT(osbuf, sizeof(*cmd)); - - cmd = (WMI_SET_WMM_CMD*)(A_NETBUF_DATA(osbuf)); - A_MEMZERO(cmd, sizeof(*cmd)); - cmd->status = status; - - return (wmi_cmd_send(wmip, osbuf, WMI_SET_WMM_CMDID, - NO_SYNC_WMIFLAG)); - -} - -A_STATUS -wmi_set_wmm_txop(struct wmi_t *wmip, WMI_TXOP_CFG cfg) -{ - void *osbuf; - WMI_SET_WMM_TXOP_CMD *cmd; - - if( !((cfg == WMI_TXOP_DISABLED) || (cfg == WMI_TXOP_ENABLED)) ) - return A_EINVAL; - - osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); - if (osbuf == NULL) { - return A_NO_MEMORY; - } - - A_NETBUF_PUT(osbuf, sizeof(*cmd)); - - cmd = (WMI_SET_WMM_TXOP_CMD *)(A_NETBUF_DATA(osbuf)); - A_MEMZERO(cmd, sizeof(*cmd)); - cmd->txopEnable = cfg; - - return (wmi_cmd_send(wmip, osbuf, WMI_SET_WMM_TXOP_CMDID, - NO_SYNC_WMIFLAG)); - -} - -#ifdef CONFIG_HOST_TCMD_SUPPORT -/* WMI layer doesn't need to know the data type of the test cmd. - This would be beneficial for customers like Qualcomm, who might - have different test command requirements from differnt manufacturers - */ -A_STATUS -wmi_test_cmd(struct wmi_t *wmip, A_UINT8 *buf, A_UINT32 len) -{ - void *osbuf; - char *data; - - A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG)); - - osbuf= A_NETBUF_ALLOC(len); - if(osbuf == NULL) - { - return A_NO_MEMORY; - } - A_NETBUF_PUT(osbuf, len); - data = A_NETBUF_DATA(osbuf); - A_MEMCPY(data, buf, len); - - return(wmi_cmd_send(wmip, osbuf, WMI_TEST_CMDID, - NO_SYNC_WMIFLAG)); -} - -#endif - -A_STATUS -wmi_set_bt_status_cmd(struct wmi_t *wmip, A_UINT8 streamType, A_UINT8 status) -{ - void *osbuf; - WMI_SET_BT_STATUS_CMD *cmd; - - osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); - if (osbuf == NULL) { - return A_NO_MEMORY; - } - - A_NETBUF_PUT(osbuf, sizeof(*cmd)); - - cmd = (WMI_SET_BT_STATUS_CMD *)(A_NETBUF_DATA(osbuf)); - A_MEMZERO(cmd, sizeof(*cmd)); - cmd->streamType = streamType; - cmd->status = status; - - return (wmi_cmd_send(wmip, osbuf, WMI_SET_BT_STATUS_CMDID, - NO_SYNC_WMIFLAG)); -} - -A_STATUS -wmi_set_bt_params_cmd(struct wmi_t *wmip, WMI_SET_BT_PARAMS_CMD* cmd) -{ - void *osbuf; - WMI_SET_BT_PARAMS_CMD* alloc_cmd; - - osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); - if (osbuf == NULL) { - return A_NO_MEMORY; - } - - A_NETBUF_PUT(osbuf, sizeof(*cmd)); - - alloc_cmd = (WMI_SET_BT_PARAMS_CMD *)(A_NETBUF_DATA(osbuf)); - A_MEMZERO(alloc_cmd, sizeof(*cmd)); - A_MEMCPY(alloc_cmd, cmd, sizeof(*cmd)); - - return (wmi_cmd_send(wmip, osbuf, WMI_SET_BT_PARAMS_CMDID, - NO_SYNC_WMIFLAG)); -} - -A_STATUS -wmi_get_keepalive_configured(struct wmi_t *wmip) -{ - void *osbuf; - WMI_GET_KEEPALIVE_CMD *cmd; - osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); - if (osbuf == NULL) { - return A_NO_MEMORY; - } - A_NETBUF_PUT(osbuf, sizeof(*cmd)); - cmd = (WMI_GET_KEEPALIVE_CMD *)(A_NETBUF_DATA(osbuf)); - A_MEMZERO(cmd, sizeof(*cmd)); - return (wmi_cmd_send(wmip, osbuf, WMI_GET_KEEPALIVE_CMDID, - NO_SYNC_WMIFLAG)); -} - -A_UINT8 -wmi_get_keepalive_cmd(struct wmi_t *wmip) -{ - return wmip->wmi_keepaliveInterval; -} - -A_STATUS -wmi_set_keepalive_cmd(struct wmi_t *wmip, A_UINT8 keepaliveInterval) -{ - void *osbuf; - WMI_SET_KEEPALIVE_CMD *cmd; - - osbuf = A_NETBUF_ALLOC(sizeof(*cmd)); - if (osbuf == NULL) { - return A_NO_MEMORY; - } - - A_NETBUF_PUT(osbuf, sizeof(*cmd)); - - cmd = (WMI_SET_KEEPALIVE_CMD *)(A_NETBUF_DATA(osbuf)); - A_MEMZERO(cmd, sizeof(*cmd)); - cmd->keepaliveInterval = keepaliveInterval; - wmip->wmi_keepaliveInterval = keepaliveInterval; - - return (wmi_cmd_send(wmip, osbuf, WMI_SET_KEEPALIVE_CMDID, - NO_SYNC_WMIFLAG)); -} - -A_STATUS -wmi_set_appie_cmd(struct wmi_t *wmip, A_UINT8 mgmtFrmType, A_UINT8 ieLen, - A_UINT8 *ieInfo) -{ - void *osbuf; - WMI_SET_APPIE_CMD *cmd; - A_UINT16 cmdLen; - - if (ieLen > WMI_MAX_IE_LEN) { - return A_ERROR; - } - cmdLen = sizeof(*cmd) + ieLen - 1; - osbuf = A_NETBUF_ALLOC(cmdLen); - if (osbuf == NULL) { - return A_NO_MEMORY; - } - - A_NETBUF_PUT(osbuf, cmdLen); - - cmd = (WMI_SET_APPIE_CMD *)(A_NETBUF_DATA(osbuf)); - A_MEMZERO(cmd, cmdLen); - - cmd->mgmtFrmType = mgmtFrmType; - cmd->ieLen = ieLen; - A_MEMCPY(cmd->ieInfo, ieInfo, ieLen); - - return (wmi_cmd_send(wmip, osbuf, WMI_SET_APPIE_CMDID, NO_SYNC_WMIFLAG)); -} - -A_STATUS -wmi_set_halparam_cmd(struct wmi_t *wmip, A_UINT8 *cmd, A_UINT16 dataLen) -{ - void *osbuf; - A_UINT8 *data; - - osbuf = A_NETBUF_ALLOC(dataLen); - if (osbuf == NULL) { - return A_NO_MEMORY; - } - - A_NETBUF_PUT(osbuf, dataLen); - - data = A_NETBUF_DATA(osbuf); - - A_MEMCPY(data, cmd, dataLen); - - return (wmi_cmd_send(wmip, osbuf, WMI_SET_WHALPARAM_CMDID, NO_SYNC_WMIFLAG)); -} - -A_INT32 -wmi_get_rate(A_INT8 rateindex) -{ - if (rateindex == RATE_AUTO) { - return 0; - } else { - return(wmi_rateTable[(A_UINT32) rateindex]); - } -} - -void -wmi_node_return (struct wmi_t *wmip, bss_t *bss) -{ - if (NULL != bss) - { - wlan_node_return (&wmip->wmi_scan_table, bss); - } -} - -bss_t * -wmi_find_Ssidnode (struct wmi_t *wmip, A_UCHAR *pSsid, - A_UINT32 ssidLength, A_BOOL bIsWPA2) -{ - bss_t *node = NULL; - node = wlan_find_Ssidnode (&wmip->wmi_scan_table, pSsid, - ssidLength, bIsWPA2); - return node; -} - -void -wmi_free_allnodes(struct wmi_t *wmip) -{ - wlan_free_allnodes(&wmip->wmi_scan_table); -} - -bss_t * -wmi_find_node(struct wmi_t *wmip, const A_UINT8 *macaddr) -{ - bss_t *ni=NULL; - ni=wlan_find_node(&wmip->wmi_scan_table,macaddr); - return ni; -} - -A_STATUS -wmi_dset_open_reply(struct wmi_t *wmip, - A_UINT32 status, - A_UINT32 access_cookie, - A_UINT32 dset_size, - A_UINT32 dset_version, - A_UINT32 targ_handle, - A_UINT32 targ_reply_fn, - A_UINT32 targ_reply_arg) -{ - void *osbuf; - WMIX_DSETOPEN_REPLY_CMD *open_reply; - - A_DPRINTF(DBG_WMI, (DBGFMT "Enter - wmip=0x%x\n", DBGARG, (int)wmip)); - - osbuf = A_NETBUF_ALLOC(sizeof(*open_reply)); - if (osbuf == NULL) { - return A_NO_MEMORY; - } - - A_NETBUF_PUT(osbuf, sizeof(*open_reply)); - open_reply = (WMIX_DSETOPEN_REPLY_CMD *)(A_NETBUF_DATA(osbuf)); - - open_reply->status = status; - open_reply->targ_dset_handle = targ_handle; - open_reply->targ_reply_fn = targ_reply_fn; - open_reply->targ_reply_arg = targ_reply_arg; - open_reply->access_cookie = access_cookie; - open_reply->size = dset_size; - open_reply->version = dset_version; - - return (wmi_cmd_send_xtnd(wmip, osbuf, WMIX_DSETOPEN_REPLY_CMDID, - NO_SYNC_WMIFLAG)); -} - -static A_STATUS -wmi_get_pmkid_list_event_rx(struct wmi_t *wmip, A_UINT8 *datap, A_UINT32 len) -{ - WMI_PMKID_LIST_REPLY *reply; - A_UINT32 expected_len; - - if (len < sizeof(WMI_PMKID_LIST_REPLY)) { - return A_EINVAL; - } - reply = (WMI_PMKID_LIST_REPLY *)datap; - expected_len = sizeof(reply->numPMKID) + reply->numPMKID * WMI_PMKID_LEN; - - if (len < expected_len) { - return A_EINVAL; - } - - A_WMI_PMKID_LIST_EVENT(wmip->wmi_devt, reply->numPMKID, - reply->pmkidList); - - return A_OK; -} - -#ifdef CONFIG_HOST_DSET_SUPPORT -A_STATUS -wmi_dset_data_reply(struct wmi_t *wmip, - A_UINT32 status, - A_UINT8 *user_buf, - A_UINT32 length, - A_UINT32 targ_buf, - A_UINT32 targ_reply_fn, - A_UINT32 targ_reply_arg) -{ - void *osbuf; - WMIX_DSETDATA_REPLY_CMD *data_reply; - int size; - - size = sizeof(*data_reply) + length; - - A_DPRINTF(DBG_WMI, - (DBGFMT "Enter - length=%d status=%d\n", DBGARG, length, status)); - - osbuf = A_NETBUF_ALLOC(size); - if (osbuf == NULL) { - return A_NO_MEMORY; - } - A_NETBUF_PUT(osbuf, size); - data_reply = (WMIX_DSETDATA_REPLY_CMD *)(A_NETBUF_DATA(osbuf)); - - data_reply->status = status; - data_reply->targ_buf = targ_buf; - data_reply->targ_reply_fn = targ_reply_fn; - data_reply->targ_reply_arg = targ_reply_arg; - data_reply->length = length; - - if (status == A_OK) { - if (a_copy_from_user(data_reply->buf, user_buf, length)) { - return A_ERROR; - } - } - - return (wmi_cmd_send_xtnd(wmip, osbuf, WMIX_DSETDATA_REPLY_CMDID, - NO_SYNC_WMIFLAG)); -} -#endif /* CONFIG_HOST_DSET_SUPPORT */ - -A_STATUS -wmi_set_wsc_status_cmd(struct wmi_t *wmip, A_UINT32 status) -{ - void *osbuf; - char *cmd; - - wps_enable = status; - - osbuf = a_netbuf_alloc(sizeof(1)); - if (osbuf == NULL) { - return A_NO_MEMORY; - } - - a_netbuf_put(osbuf, sizeof(1)); - - cmd = (char *)(a_netbuf_to_data(osbuf)); - - A_MEMZERO(cmd, sizeof(*cmd)); - cmd[0] = (status?1:0); - return (wmi_cmd_send(wmip, osbuf, WMI_SET_WSC_STATUS_CMDID, - NO_SYNC_WMIFLAG)); -} - diff --git a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/wmi/wmi_doc.h b/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/wmi/wmi_doc.h deleted file mode 100644 index 19cd9386c..000000000 --- a/target/linux/s3c24xx/files-2.6.31/drivers/ar6000/wmi/wmi_doc.h +++ /dev/null @@ -1,4421 +0,0 @@ -/* - * - * Copyright (c) 2004-2007 Atheros Communications Inc. - * All rights reserved. - * - * - * 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; - * - * Software distributed under the License is distributed on an "AS - * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or - * implied. See the License for the specific language governing - * rights and limitations under the License. - * - * - * - */ - - -#if 0 -Wireless Module Interface (WMI) Documentaion - - This section describes the format and the usage model for WMI control and - data messages between the host and the AR6000-based targets. The header - file include/wmi.h contains all command and event manifest constants as - well as structure typedefs for each set of command and reply parameters. - -Data Frames - - The data payload transmitted and received by the target follows RFC-1042 - encapsulation and thus starts with an 802.2-style LLC-SNAP header. The - WLAN module completes 802.11 encapsulation of the payload, including the - MAC header, FCS, and WLAN security related fields. At the interface to the - message transport (HTC), a data frame is encapsulated in a WMI message. - -WMI Message Structure - - The WMI protocol leverages an 802.3-style Ethernet header in communicating - the source and destination information between the host and the AR6000 - modules using a 14-byte 802.3 header ahead of the 802.2-style payload. In - addition, the WMI protocol adds a header to all data messages: - - { - INT8 rssi - The RSSI of the received packet and its units are shown in db above the - noise floor, and the noise floor is shown in dbm. - UINT8 info - Contains information on message type and user priority. Message type - differentiates between a data packet and a synchronization message. - } WMI_DATA_HDR - - User priority contains the 802.1d user priority info from host to target. Host - software translates the host Ethernet format to 802.3 format prior to Tx and - 802.3 format to host format in the Rx direction. The host does not transmit the - FCS that follows the data. MsgType differentiates between a regular data - packet (msgType=0) and a synchronization message (msgType=1). - -Data Endpoints - - The AR6000 chipset provides several data endpoints to support quality of - service (QoS) and maintains separate queues and separate DMA engines for - each data endpoint. A data endpoint can be bi-directional. - - Best effort (BE) class traffic uses the default data endpoint (2). The host can - establish up to two additional data endpoints for other traffic classes. Once - such a data endpoint is established, it sends and receives corresponding QoS - traffic in a manner similar to the default data endpoint. - - If QoS is desired over the interconnect, host software must classify each data - packet and place it on the appropriate data endpoint. The information - required to classify data is generally available in-band as an 802.1p/q style - tag or as the ToS field in the IP header. The information may also be available - out-of-band depending on the host DDI. - -Connection States - - Table B-1 describes the AR6000 WLAN connection states: - - Table B-1. AR6000 Connection States - -Connection State - Description - - DISCONNECTED - In this state, the AR6000 device is not connected to a wireless - network. The device is in this state after reset when it sends the - WIRELESS MODULE “READY” EVENT, after it processes a - DISCONNECT command, and when it loses its link with the - access point (AP) that it was connected to. The device signals a - transition to the DISCONNECTED state with a “DISCONNECT” - event. - -CONNECTED - In this state, the AR6000 device is connected to wireless networks. - The device enters this state after successfully processing a - CONNECT, which establishes a connection with a wireless - network. The device signals a transition to the CONNECTED state - with a “CONNECT” event. - - -Message Types - - WMI uses commands, replies, and events for the control and configuration of - the AR6000 device. The control protocol is asynchronous. Table B-2 describes - AR6000 message types: - -Table B-2. AR6000 Message Types - -Message Type - Description - -Commands - Control messages that flow from the host to the device - -Replies/Events - Control messages that flow from the device to the host. - - The device issues a reply to some WMI commands, but not to others. - The payload in a reply is command-specific, and some commands do - not trigger a reply message at all. Events are control messages issued - by the device to signal the occurrence of an asynchronous event. - - -WMI Message Format - - All WMI control commands, replies and events use the header format: - - WMI_CMD_HDR Header Format - { - UINT16 id - This 16-bit constant identifies which WMI command the host is issuing, - which command the target is replying to, or which event has occurred. - WMI_CMD_HDR - } - - - A variable-size command-, reply-, or event-specific payload follows the - header. Over the interconnect, all fields in control messages (including - WMI_CMD_HDR and the command specific payload) use 32-bit little Endian - byte ordering and fields are packed. The AR6000 device always executes - commands in order, and the host may send multiple commands without - waiting for previous commands to complete. A majority of commands are - processed to completion once received. Other commands trigger a longer - duration activity whose completion is signaled to the host through an event. - -Command Restrictions - - Some commands may only be issued when the AR6000 device is in a certain - state. The host is required to wait for an event signaling a state transition - before such a command can be issued. For example, if a command requires - the device to be in the CONNECTED state, then the host is required to wait - for a “CONNECT” event before it issues that command. - - The device ignores any commands inappropriate for its current state. If the - command triggers a reply, the device generates an error reply. Otherwise, the - device silently ignores the inappropriate command. - -Command and Data Synchronization - - WMI provides a mechanism for a host to advise the device of necessary - synchronization between commands and data. The device implements - synchronization; no implicit synchronization exists between endpoints. - - The host controls synchronization using the “SYNCHRONIZE” command - over the control channel and synchronization messages over data channels. - The device stops each data channel upon receiving a synchronization message - on that channel, processing all data packets received prior to that message. - After the device receives synchronization messages for each data endpoint - and the “SYNCHRONIZE” command, it resumes all channels. - - When the host must guarantee a command executes before processing new - data packets, it first issues the command, then issues the “SYNCHRONIZE” - command and sends synchronization messages on data channels. When the - host must guarantee the device has processed all old data packets before a - processing a new command, it issues a “SYNCHRONIZE” command and - synchronization messages on all data channels, then issues the desired - command. - - - -WMI Commands - - ADD_BAD_AP - Cause the AR6000 device to avoid a particular AP - ADD_CIPHER_KEY - Add or replace any of the four AR6000 encryption keys - ADD_WOW_PATTERN - Used to add a pattern to the WoW pattern list - CLR_RSSI_SNR - Clear the current calculated RSSI and SNR value - CONNECT_CMD - Request that the AR6000 device establish a wireless connection - with the specified SSID - CREATE_PSTREAM - Create prioritized data endpoint between the host and device - DELETE_BAD_AP - Clear an entry in the bad AP table - DELETE_CIPHER_KEY - Delete a previously added cipher key - DELETE_PSTREAM - Delete a prioritized data endpoint - DELETE_WOW_PATTERN - Remove a pre-specified pattern from the WoW pattern list - EXTENSION - WMI message interface command - GET_BIT_RATE - Retrieve rate most recently used by the AR6000 - GET_CHANNEL_LIST - Retrieve list of channels used by the AR6000 - GET_FIXRATES - Retrieves the rate-mask set via the SET_FIXRATES command. - GET_PMKID_LIST_CMD - Retrieve the firmware list of PMKIDs - GET_ROAM_DATA - Internal use for data collection; available in special build only - GET_ROAM_TBL - Retrieve the roaming table maintained on the target - GET_TARGET_STATS - Request that the target send the statistics it maintains - GET_TX_PWR - Retrieve the current AR6000 device Tx power levels - GET_WOW_LIST - Retrieve the current list of WoW patterns - LQ_THRESHOLD_PARAMS - Set the link quality thresholds - OPT_TX_FRAME - Send a special frame (special feature) - RECONNECT - Request a reconnection to a BSS - RSSI_THRESHOLD_PARAMS - Configure how the AR6000 device monitors and reports signal - strength (RSSI) of the connected BSS - SCAN_PARAMS - Determine dwell time and changes scanned channels - SET_ACCESS_PARAMS - Set access parameters for the wireless network - SET_ADHOC_BSSID - Set the BSSID for an ad hoc network - SET_AKMP_PARAMS - Set multiPMKID mode - SET_APPIE - Add application-specified IE to a management frame - SET_ASSOC_INFO - Specify the IEs the device should add to association or - reassociation requests - SET_AUTH_MODE - Set 802.11 authentication mode of reconnection - SET_BEACON_INT - Set the beacon interval for an ad hoc network - SET_BIT_RATE - Set the AR6000 to a specific fixed bit rate - SET_BMISS_TIME - Set the beacon miss time - SET_BSS_FILTER - Inform the AR6000 of network types about which it wants to - receive information using a “BSSINFO” event - SET_BT_PARAMS - Set the status of a Bluetooth stream (SCO or A2DP) or set - Bluetooth coexistence register parameters - SET_BT_STATUS - Set the status of a Bluetooth stream (SCO or A2DP) - SET_CHANNEL_PARAMETERS - Configure WLAN channel parameters - SET_DISC_TIMEOUT - Set the amount of time the AR6000 spends attempting to - reestablish a connection - SET_FIXRATES - Set the device to a specific fixed PHY rate (supported subset) - SET_HALPARAM - Internal AR6000 command to set certain hardware parameters - SET_HOST_SLEEP_MODE - Set the host mode to asleep or awake - SET_IBSS_PM_CAPS - Support a non-standard power management scheme for an - ad hoc network - SET_LISTEN_INT - Request a listen interval - SET_LPREAMBLE - Override the short preamble capability of the AR6000 device - SET_MAX_SP_LEN - Set the maximum service period - SET_OPT_MODE - Set the special mode on/off (special feature) - SET_PMKID - Set the pairwise master key ID (PMKID) - SET_PMKID_LIST_CMD - Configure the firmware list of PMKIDs - SET_POWER_MODE - Set guidelines on trade-off between power utilization - SET_POWER_PARAMS - Configure power parameters - SET_POWERSAVE_PARAMS - Set the two AR6000 power save timers - SET_PROBED_SSID - Provide list of SSIDs the device should seek - SET_REASSOC_MODE - Specify whether the disassociated frame should be sent upon - reassociation - SET_RETRY_LIMITS - Limit how many times the device tries to send a frame - SET_ROAM_CTRL - Control roaming behavior - SET_RTS - Determine when RTS should be sent - SET_SCAN_PARAMS - Set the AR6000 scan parameters - SET_TKIP_COUNTERMEASURES - Enable/disable reports of TKIP MIC errors - SET_TX_PWR - Specify the AR6000 device Tx power levels - SET_VOICE_PKT_SIZE - Set voice packet size - SET_WMM - Override the AR6000 WMM capability - SET_WMM_TXOP - Configure TxOP bursting when sending traffic to a WMM- - capable AP - SET_WOW_MODE - Enable/disable WoW mode - SET_WSC_STATUS - Enable/disable profile check in cserv when the WPS protocol - is in progress - SNR_THRESHOLD_PARAMS - Configure how the device monitors and reports SNR of BSS - START_SCAN - Start a long or short channel scan - SYNCHRONIZE - Force a synchronization point between command and data - paths - TARGET_REPORT_ERROR_BITMASK - Control “ERROR_REPORT” events from the AR6000 - - - - -Name - ADD_BAD_AP - -Synopsis - The host uses this command to cause the AR6000 to avoid a particular AP. The - AR6000 maintain a table with up to two APs to avoid. An ADD_BAD_AP command - adds or replaces the specified entry in this bad AP table. - - If the AR6000 are currently connected to the AP specified in this command, they - disassociate. - -Command - wmiconfig eth1 --badap - -Command Parameters - UINT8 badApIndex Index [0...1] that identifies which entry in the - bad AP table to use - - - UINT8 bssid[6] MAC address of the AP to avoid - -Command Values - badApIndex = 0, 1 Entry in the bad AP table to use - -Reset Value - The bad AP table is cleared - -Restrictions - None - -See Also - “DELETE_BAD_AP” on page B-13 - -===================================================================== -Name - ADD_CIPHER_KEY - -Synopsis - The host uses this command to add/replace any of four encryption keys on the - AR6000. The ADD_CIPHER_KEY command is issued after the CONNECT event - has been received by the host for all dot11Auth modes except for SHARED_AUTH. - When the dot11AuthMode is SHARED_AUTH, then the ADD_CIPHER_KEY - command should be issued before the “CONNECT” command. - -Command - wmiconfig eth1 --cipherkey - - -Command Parameters - UINT8 keyIndex Index (0...3) of the key to add/replace; - uniquely identifies the key - UINT8 keyType CRYPTO_TYPE - UINT8 keyUsage Specifies usage parameters of the key when - keyType = WEP_CRYPT - UINT8 keyLength Length of the key in bytes - UINT8 keyOpCtrl bit[0] = Initialize TSC (default), - bit[1] = Initialize RSC - UINT8 keyRSC[8] Key replay sequence counter (RSC) initial - value the device should use - UINT8 key[32] Key material used for this connection - Command Values - { - NONE_CRYPT = 1 - WEP_CRYPT = 2 - TKIP_CRYPT = 3 - AES_CRYPT = 4 - KEY_OP_INIT_TSC 0x01 - KEY_OP_INIT_RSC 0x02 - KEY_OP_INIT_VAL 0x03 - Default is to Initialize the TSC - KEY_OP_VALID_MASK 0x04 - Two operations defined - } CRYPTO_TYPE - - { - PAIRWISE_USAGE = 0 Set if the key is used for unicast traffic only - GROUP_USAGE = 1 Set if the key is used to receive multicast - traffic (also set for static WEP keys) - TX_USAGE = 2 Set for the GROUP key used to transmit frames - All others are reserved - } KEY_USAGE - -Reset Value - The four available keys are disabled. - -Restrictions - The cipher should correspond to the encryption mode specified in the “CONNECT” - command. - -See Also - “DELETE_CIPHER_KEY” - -===================================================================== - - -Name - ADD_WOW_PATTERN - -Synopsis - The host uses this command to add a pattern to the WoW pattern list; used for - pattern-matching for host wakeups by the WoW module. If the host mode is asleep - and WoW is enabled, all packets are matched against the existing WoW patterns. If a - packet matches any of the patterns specified, the target will wake up the host. All - non-matching packets are discarded by the target without being sent up to the host. - -Command - wmiconfig –addwowpattern - - -Command Parameters - A_UINT8 filter_list_id ID of the list that is to include the new pattern - A_UINT8 filter_size Size of the new pattern - A_UINT8 filter_offset Offset at which the pattern matching for this - new pattern should begin at - A_UINT8 filter[1] Byte stream that contains both the pattern and - the mask of the new WoW wake-up pattern - -Reply Parameters - None - -Reset Value - None defined (default host mode is awake) - -Restrictions - None - -See Also - “DELETE_WOW_PATTERN” - -===================================================================== - - -Name - CLR_RSSI_SNR - -Synopsis - Clears the current calculated RSSI and SNR value. RSSI and SNR are reported by - running-average value. This command will clear the history and have a fresh start - for the running-average mechanism. - -Command - wmiconfig eth1 --cleanRssiSnr - -Command Parameters - None - -Reply Parameters - None - -Reset Value - None defined - -Restrictions - None - -===================================================================== - -Name - CONNECT_CMD - -Synopsis - New connect control information (connectCtrl) is added, with 32 possible modifiers. - - CONNECT_SEND_REASSOC - Valid only for a host-controlled connection to a - particular AP. If this bit is set, a reassociation frame is - sent. If this bit is clear, an association request frame is - sent to the AP. - - CONNECT_IGNORE_WPAx_GROUP_CIPHER - No group key is issued in the CONNECT command, - so use the group key advertised by the AP. In a target- - initiated roaming situation this allows a STA to roam - between APs that support different multicast ciphers. - - CONNECT_PROFILE_MATCH_DONE - In a host-controlled connection case, it is possible that - during connect, firmware may not have the - information for a profile match (e.g, when the AP - supports hidden SSIDs and the device may not - transmit probe requests during connect). By setting - this bit in the connection control information, the - firmware waits for a beacon from the AP with the - BSSID supplied in the CONNECT command. No - additional profile checks are done. - - CONNECT_IGNORE_AAC_BEACON - Ignore the Admission Capacity information in the - beacon of the AP - - CONNECT_ASSOC_POLICY_USER - When set, the CONNECT_SEND_REASSOC setting - determines if an Assoc or Reassoc is sent to an AP - -Command - wmiconfig --setconnectctrl - -Command Parameters - typedef struct{ - A_UINT8 networktype; - A_UINT8 dot11authmode; - A_UINT8 authmode; - A_UINT8 pairwiseCryptoType; /*CRYPTO_TYPE*/ - A_UINT8 pairwiseCryptoLen; - A_UINT8 groupCryptoType; /*CRYPTO_TYPE*/ - A_UINT8 groupCryptoLen; - A_UINT8 ssidLength; - A_UCHAR ssid[WMI_MAX_SSID_LEN]; - A_UINT16 channel; - A_UINT8 bssid[AUTH_MAC_LEN]; - A_UINT8 ctrl_flags; /*WMI_CONNECT_CTRL_FLAGS_BITS*/ - } WMI_CONNECT_CMD; - - ctrl flags bitmask - = 0x0001 CONNECT_ASSOC_POLICY_USER - Assoc frames are sent using the policy specified by - the flag - = 0x0002 CONNECT_SEND_REASSOC - Send Reassoc frame while connecting, otherwise send - assoc frames - = 0x0004 CONNECT_IGNORE_WPAx_GROUP_CIPHER - Ignore WPAx group cipher for WPA/WPA2 - = 0x0008 CONNECT_PROFILE_MATCH_DONE - Ignore any profile check - = 0x0010 CONNECT_IGNORE_AAC_BEACON - Ignore the admission control information in the - beacon - ... CONNECT_CMD, continued - Command Values - typedef enum { - INFRA_NETWORK = 0x01, - ADHOC_NETWORK = 0x02, - ADHOC_CREATOR = 0x04, - } NETWORK_TYPE; - - typedef enum { - OPEN_AUTH = 0x01, - SHARED_AUTH = 0x02, - LEAP_AUTH = 0x04, - } DOT11_AUTH_MODE; - typedef enum { - NONE_AUTH = 0x01, - WPA_AUTH = 0x02, - WPA_PSK_AUTH = 0x03, - WPA2_AUTH = 0x04, - WPA2_PSK_AUTH = 0x05, - WPA_AUTH_CCKM = 0x06, - WPA2_AUTH_CCKM = 0x07, - } AUTH_MODE; - typedef enum { - NONE_CRYPT = 0x01, - WEP_CRYPT = 0x02, - TKIP_CRYPT = 0x03, - AES_CRYPT = 0x04, - } CRYPTO_TYPE; - typedef enum { - CONNECT_ASSOC_POLICY_USER = 0x0001, - CONNECT_SEND_REASSOC = 0x0002, - CONNECT_IGNORE_WPAx_GROUP_CIPHER = 0x0004, - CONNECT_PROFILE_MATCH_DONE = 0x0008, - CONNECT_IGNORE_AAC_BEACON = 0x0010, - } WMI_CONNECT_CTRL_FLAGS_BITS; - - pairwiseCryptoLen and groupCryptoLen are valid when the respective - CryptoTypesis WEP_CRYPT, otherwise this value should be 0. This is the length in - bytes. - -Reset Value - None defined - -Restrictions - None - -===================================================================== - - -Name - CREATE_PSTREAM - -Synopsis - The host uses this command to create a new prioritized data endpoint between the - host and the AR6000 device that carries a prioritized stream of data. If the AP that the - device connects to requires TSPEC stream establishment, the device requests the - corresponding TSPEC with the AP. The maximum and minimum service interval - ranges from 0 – 0x7FFFFFFF (ms), where 0 = disabled. The device does not send a - reply event for this command, as it is always assumed the command has succeeded. - An AP admission control response comes to the host via a WMI_CAC_INDICATION - event, once the response for the ADDTS frame comes. - - Examples of cases where reassociation is generated (when WMM) and cases where - ADDTS is generated (when WMM and enabling ACM) are when: - Changing UAPSD flags in WMM mode, reassociation is generated - Changing the interval of sending auto QoS Null frame in WMM mode; - reassociation is not generated - Issuing a command with same previous parameters in WMM mode and enabling - ACM, an ADDTS request is generated - Changing the interval of a QoS null frame sending in WMM mode and enabling - ACM, an ADDTS request is generated - Issuing the command in disconnected state, reassociation or ADDTS is not - generated but the parameters are available after (re)association - -Command - --createqos - - where: - - - 802.1D user priority range (0–7) - - = 0 Tx (uplink) traffic - = 1 Rx (downlink) traffic - = 2 Bi-directional traffic - - = 1 BK - = 2 VI - = 3 VO - - = 0 Aperiodic - = 1 Periodic - - Specifies whether the voice power save mechanism - (APSD if AP supports it or legacy/simulated APSD - [using PS-Poll]) should be used - = 0 Disable voice power save for traffic class - = 1 Enable APSD voice power save for traffic class - = 2 Enable voice power save for all traffic classes - - (In ms) - - Inactivity interval (in ms) (0 = Infinite) - - (In ms) - - Service start time - - TSID range (0–15) - - Nominal MAC SDU size - - Maximum MAC SDU size - - Minimum data rate (in bps) - - Mean data rate (in bps) - - Peak data rate (in bps) - - Maximum burst size (in bps) - - Delay bound - - Minimum PHY rate (in bps) - - Surplus bandwidth allowance - - Medium time in TU of 32-ms periods per sec - ... CREATE_PSTREAM (continued) - -Command Parameters - UINT8 trafficClass TRAFFIC_CLASS value - UINT8 traffic - Direction - DIR_TYPE value - UINT8 rxQueueNum - AR6000 device mailbox index (2 or 3) - corresponding to the endpoint the host - wishes to use to receive packets for the - prioritized stream - UINT8 trafficType TRAFFIC_TYPE value - UINT8 voicePS -Capability - VOICEPS_CAP_TYPE value - UINT8 tsid Traffic stream ID - UINT8 userPriority 802.1D user priority - UINT16 nominalMSDU Nominal MSDU in octets - UINT16 maxMSDU Maximum MSDU in octets - UINT32 minServiceInt Minimum service interval: the min. - period of traffic specified (in ms) - UINT32 maxServiceInt Maximum service interval: the max. - period of traffic specified (in ms) - UINT32 inactivityInt Indicates how many ms an established - stream is inactive before the prioritized - data endpoint is taken down and the - corresponding T-SPEC deleted - UINT32 suspensionInt Suspension interval (in ms) - UINT32 service StartTime Service start time - UINT32 minDataRate Minimum data rate (in bps) - UINT32 meanDataRate Mean data rate (in bps) - UINT32 peakDataRate Peak data rate (in bps) - UINT32 maxBurstSize - UINT32 delayBound - UINT32 minPhyRate Minimum PHY rate for TSPEC (in bps) - UINT32 sba Surplus bandwidth allowance - UINT32 mediumTime Medium TSPEC time (in units of 32 ms) -Command Values - { - WMM_AC_BE = 0 Best Effort - WMM_AC_BK = 1 Background - WMM_AC_VI = 2 Video - WMM_AC_VO = 3 Voice - All other values reserved - } TRAFFIC_CLASS - { - UPLINK_TRAFFIC = 0 From the AR6000 device to the AP - DOWNLINK_TRAFFIC = 1 From the AP to the AR6000 device - BIDIR_TRAFFIC = 2 Bi-directional traffic - All other values reserved - } DIR_TYPE - { - DISABLE_FOR_THIS_AC = 0 - ENABLE_FOR_THIS_AC = 1 - ENABLE_FOR_ALL_AC = 2 - All other values reserved - } VOICEPS_CAP_TYPE - - ... CREATE_PSTREAM (continued) - - - VI BE BK Supported, Y/N? - 0 0 0 0 Y - 0 0 0 1 Y - 0 0 1 0 N - 0 0 1 1 N - 0 1 0 0 Y - 0 1 0 1 Y - 0 1 1 0 N - 0 1 1 1 N - 1 0 0 0 Y - 1 0 0 1 Y - 1 0 1 0 N - 1 1 0 0 N - 1 1 0 1 Y - 1 1 0 0 N - 1 1 1 0 N - 1 1 1 1 Y - -Reset Value - No pstream is present after reset; each of the BE, BK, VI,VO pstreams must be created - (either implicitly by data flow or explicitly by user) - -Restrictions - This command can only be issued when the device is in the CONNECTED state. If - the device receives the command while in DISCONNECTED state, it replies with a - failure indication. At most four prioritized data endpoints can be created, one for - each AC. - -See Also - “DELETE_PSTREAM” -===================================================================== - -Name - DELETE_BAD_AP - -Synopsis - The host uses this command to clear a particular entry in the bad AP table - -Command - wmiconfig eth1 --rmAP [--num=] // used to clear a badAP - entry. num is index from 0-3 - -Command Parameters - UINT8 badApIndex Index [0...n] that identifies the entry in the bad - AP table to delete - -Command Values - badApIndex = 0, 1, 2, 3 - Entry in the bad AP table - -Reset Value - None defined - -Restrictions - None - -See Also - “ADD_BAD_AP” - -===================================================================== - - -Name - DELETE_CIPHER_KEY - -Synopsis - The host uses this command to delete a key that was previously added with the - “ADD_CIPHER_KEY” command. - -Command - TBD - -Command Parameters - UINT8 keyIndex Index (0...3) of the key to be deleted - -Command Values - keyIndex = 0, 1,2, 3 Key to delete - -Reset Value - None - -Restrictions - The host should not delete a key that is currently in use by the AR6000. - -See Also - “ADD_CIPHER_KEY” - -===================================================================== - -Name - DELETE_PSTREAM - -Synopsis - The host uses this command to delete a prioritized data endpoint created by a - previous “CREATE_PSTREAM” command - -Command - --deleteqos , where: - - - = 0 BE - = 1 BK - = 2 VI - = 3 VO - - The TSpec ID; use the -qosqueue option - to get the active TSpec IDs for each traffic class - -Command Parameters - A_UINT8 trafficClass Indicate the traffic class of the stream - being deleted - -Command Values - { - WMM_AC_BE = 0 Best effort - WMM_AC_BK = 1 Background - WMM_AC_VI = 2 Video - WMM_AC_VO = 3 Voice - } TRAFFIC CLASS - - 0-15 for TSID - -Reply Values - N/A - -Restrictions - This command should only be issued after a “CREATE_PSTREAM” command has - successfully created a prioritized stream - -See Also - “CREATE_PSTREAM” - -===================================================================== - - -Name - DELETE_WOW_PATTERN - -Synopsis - The host uses this command to remove a pre-specified pattern from the - WoW pattern list. - -Command - wmiconfig –delwowpattern - -Command Parameters - A_UINT8 filter_list_id ID of the list that contains the WoW filter - pattern to delete - A_UINT8 filter_id ID of the WoW filter pattern to delete - -Reply Parameters - None - - - -Reset Value - None defined - -Restrictions - None - -See Also - “ADD_WOW_PATTERN” - -===================================================================== - - -Name - EXTENSION - -Synopsis - The WMI message interface is used mostly for wireless control messages to a wireless - module applicable to wireless module management regardless of the target platform - implementation. However, some commands only peripherally related to wireless - management are desired during operation. These wireless extension commands may - be platform-specific or implementation-dependent. - -Command - N/A - -Command Parameters - Command-specific - -Command Values - Command-specific - -Reply Parameters - Command-specific - -Reset Values - None defined - -Restrictions - None defined - -===================================================================== - - -Name - GET_BIT_RATE - -Synopsis - Used by the host to obtain the rate most recently used by the AR6000 device - -Command - wmiconfig eth1 --getfixrates - -Command Parameters - None - - - -Reply Parameters - INT8 - rateIndex - See the “SET_BIT_RATE” command - -Reset Values - None - -Restrictions - This command should only be used during development/debug; it is not intended -for use in production. It is only valid when the device is in the CONNECTED state - -See Also - “SET_BIT_RATE” - -===================================================================== - - -Name - GET_CHANNEL_LIST - -Synopsis - Used by the host uses to retrieve the list of channels that can be used by the device - while in the current wireless mode and in the current regulatory domain. - -Command - TBD - -Command Parameters - None - -Reply Parameters - UINT8 reserved Reserved - UINT8 numberOfChannels Number of channels the reply contains - UINT16 channelList[numberOfChannels] Array of channel frequencies (in MHz) - -Reset Values - None defined - -Restrictions - The maximum number of channels that can be reported are 32 - -===================================================================== - - -Name - GET_FIXRATES - -Synopsis - Clears the current calculated RSSI and SNR value. RSSI and SNR are reported by - running-average value. This command will clear the history and have a fresh start for - the running-average mechanism. - -Synopsis - This returns rate-mask set via WMI_SET_FIXRATES to retrieve the current fixed rate - that the AR6001 or AR6001 is using. See “SET_FIXRATES”. - -Command - wmiconfig eth1 --getfixrates - -Command Parameters - A_UINT16 fixRateMask; Note: if this command is used prior to - using WMI_SET_FIXRATES, AR6000 - returns 0xffff as fixRateMask, indicating - all the rates are enabled - -Reply Parameters - None - -Reset Value - None defined - -Restrictions - None - -See Also - “SET_FIXRATES” - -===================================================================== - - - -Name - GET_PMKID_LIST_CMD - -Synopsis - Retrieves the list of PMKIDs on the firmware. The - WMI_GET_PMKID_LIST_EVENT is generated by the firmware. - -Command - TBD - -Command Parameters - -Reset Values - None - -Restrictions - None - -See Also - SET_PMKID_LIST_CMD GET_PMKID_LIST_EVENT - -===================================================================== - - -Name - GET_ROAM_TBL - -Synopsis - Retrieve the roaming table maintained on the target. The response is reported - asynchronously through the ROAM_TBL_EVENT. - -Command - wmiconfig --getroamtable - -Command Parameters - A_UINT8 roamCtrlType; - A_UINT16 roamMode - A_UINT16 numEntries - WMI_BSS_ROAM_INFO bssRoamInfo[1] - -Reply Value - Reported asynchronously through the ROAM_TBL_EVENT - -Reset Value - None defined - -Restrictions - None - -See Also - SET_KEEPALIVE - -===================================================================== - - -Name - GET_TARGET_STATS - -Synopsis - The host uses this command to request that the target send the statistics that it - maintains. The statistics obtained from the target are accrued in the host every time - the GET_TARGET_STATS command is issued. The --clearStats option is added to - clear the target statistics maintained in the host. - -Command - wmiconfig --getTargetStats --clearStats - -Command Parameters - TARGET_STATS targetStats - WMI_TARGET_STATS - UINT8 clearStats - - -Reply Value - RSSI return value (0–100) - -Reset Values - All statistics are cleared (zeroed) - -Restrictions - The --getTargetStats option must be used; the --clearStats option is also available also - - -===================================================================== - -Name - GET_TX_PWR - -Synopsis - The host uses this command to retrieve the current Tx power level - -Command - wmiconfig -i eth1 --getpower - -Command Parameters - None - -Reply Parameters - UINT16 dbM The current Tx power level specified in dbM - -Reset Values - The maximum permitted by the regulatory domain - -Restrictions - None - -See Also - “SET_TX_PWR” - -===================================================================== - - -Name - GET_WOW_LIST - -Synopsis - The host uses this command to retrieve the current list of WoW patterns. - -Command - wmiconfig –getwowlist - -Command Parameters - A_UINT8 filter_list_id ID of the list of WoW patterns to retrieve - -Reply Value(s) - A_UINT16 num_filters Number of WoW patterns contained in the list - A_UINT8 wow_mode Current mode of WoW (enabled or disabled) - A_UINT8 host_mode Current host mode (asleep or awake) - WOW_FILTER wow_filters[1] - Contents of the WoW filter pattern list - (contains mask, pattern, offset and size - information for each of the patterns) - -Reset Value - None defined - -Restrictions - None - -See Also - “SET_WSC_STATUS” - -===================================================================== - - -Name - LQ_THRESHOLD_PARAMS - -Synopsis - Sets Link Quality thresholds, the sampling will happen at every unicast data frame - Tx if a certain threshold is met, and the corresponding event will be sent to the host. - -Command - --lqThreshold ... - ... - -Command Parameters - = 0 Disable link quality sampling - = 1 Enable link quality sampling - Above thresholds (value in [0,100]), in - ascending order - Below thresholds (value in [0,100]), in - ascending order - -Command Values - See command parameters - -Reset Value - None defined - -Restrictions - None - -===================================================================== - - -Name - OPT_TX_FRAME - -Synopsis - Special feature, sends a special frame. - -Command - wmiconfig --sendframe - - -Command Parameters - { - A_UINT16 optIEDataLen; - A_UINT8 frmType; - A_UINT8 dstAddr[ATH_MAC_LEN]; - A_UINT8 bssid[ATH_MAC_LEN]; - A_UINT8 optIEData[1]; - } WMI_OPT_TX_FRAME_CMD; - -Command Values - = 1 Probe request frame - = 2 Probe response frame - = 3 CPPP start - = 4 CPPP stop - -Reset Value - None defined - -Restrictions - Send a special frame only when special mode is on. - -===================================================================== - - -Name - RECONNECT - -Synopsis - This command requests a reconnection to a BSS to which the AR6000 device was - formerly connected - -Command - TBD - -Command Parameters - UINT16 channel Provides a hint as to which channel was - used for a previous connection - UINT8 bssid[6] If set, indicates which BSSID to connect to - -Command Values - None - -Reset Values - None - -Restrictions - None - -See Also - “CONNECT_CMD” - -===================================================================== - - -Name - RSSI_THRESHOLD_PARAMS - -Synopsis - Configures how the AR6000 device monitors and reports signal strength (RSSI) of the - connected BSS, which is used as a link quality metric. The four RSSI threshold sets (in - dbM) of the host specification divide the signal strength range into six segments. - When signal strength increases or decreases across one of the boundaries, an - RSSI_THRESHOLD event is signaled to the host. The host may then choose to take - action (such as influencing roaming). - -Command - wmiconfig eth1 --rssiThreshold - ... - - ... - - -Command Parameters - UINT8 weight Range in [1, 16] used to calculate average RSSI - UINT32 pollTime RSSI (signal strength) sampling frequency in - seconds (if pollTime = 0, single strength - sampling is disabled) - USER_RSS__THOLD tholds[12] Thresholds (6 x 2) - -Command Values - None defined - -Reset Values - pollTime is 0, and sampling is disabled - -Restrictions - Can only be issued if the AR6000 device is connected - - -===================================================================== - -Name - SCAN_PARAMS - -Synopsis - The minact parameter determines the minimum active channel dwell time, within - which if the STA receives any beacon, it remains on that channel until the maxact - channel dwell time. If the STA does not receive a beacon within the minact dwell - time, it switches to scan the next channel. - -Command - wmiconfig -scan -minact= --maxact= - -Command Parameters - UINT16 maxact Channel dwell time (in ms), default = 0 - UINT16 minact Channel dwell time (in ms), default = 105 - -Command Values - See channel parameters - -Reset Values - None defined - -Restrictions - The minact value should be greater than 0; maxact should be between 5–65535 ms - and greater than minact - -===================================================================== - - -Name - SET_ACCESS_PARAMS - -Synopsis - Allows the host to set access parameters for the wireless network. A thorough - understanding of IEEE 802.11 is required to properly manipulate these parameters. - -Command - wmiconfig eth1 --acparams --txop --cwmin <0-15> - --cwmax <0-15> --aifsn<0-15> - -Command Parameters - UINT16 txop The maximum time (expressed in units of - 32 ms) the device can spend transmitting - after acquiring the right to transmit - UINT8 eCWmin Minimum contention window - UINT8 eCWmax Maximum contention window - UINT8 aifsn The arbitration inter-frame space number - -Command Values - None - -Reset Values - Reasonable defaults that vary, between endpoints (prioritized streams) - -Restrictions - None - -===================================================================== - - -Name - SET_ADHOC_BSSID - -Synopsis - Allows the host to set the BSSID for an ad hoc network. If a network with this BSSID - is not found, the target creates an ad hoc network with this BSSID after the connect - WMI command is triggered (e.g., by the SIOCSIWESSID IOCTL). - -Command - wmiconfig eth1 --adhocbssid - -Command Parameters - A_UINT8 bssid[ATH_MAC_LEN] BSSID is specified in xx:xx:xx:xx:xx:xx format - -Command Values - None - -Reset Values - None - -Restrictions - None - -===================================================================== - - -Name - SET_AKMP_PARAMS - -Synopsis - Enables or disables multi PMKID mode. - -Command - wmiconfig eth1 --setakmp --multipmkid= - -Command Parameters - typedef struct { - A_UINT32 akmpInfo; - } WMI_SET_AKMP_PARAMS_CMD; - -Command Values - akmpInfo; - bit[0] = 0 - MultiPMKID mode is disabled and PMKIDs that - were set using the WMI_SET_PMKID_CMD are - used in the [Re]AssocRequest frame. - bit[0] = 1 - MultiPMKID mode is enabled and PMKIDs issued - by the WMI_SET_PMKID_LIST_CMD are used in - the next [Re]AssocRequest sent to the AP. - -Reset Values - MultiPMKID mode is disabled - -Restrictions - None - -===================================================================== - - -Name - SET_APPIE - -Synopsis - Add an application-specified IE to a management frame. The maximum length is - 76 bytes. Including the length and the element ID, this translates to 78 bytes. - -Command - wmiconfig --setappie , where: - - frame - One of beacon, probe, respon, assoc - - IE - A hex string beginning with DD (if = 0, no - IE is sent in the management frame) - -Command Parameters - mgmtFrmType; - A WMI_MGMT_FRAME_TYPE - - ieLen; - Length of the IE to add to the GMT frame - -Command Values - None - -Reset Value - None defined - -Restrictions - Supported only for the probe request and association request management frame -types. Also, only one IE can be added per management frame type. - -===================================================================== - - -Name - SET_ASSOC_INFO - -Synopsis - The host uses this command to specify any information elements (IEs) it wishes the - AR6000 device to add to all future association and reassociation requests. IEs must be - correct and are used as is by the device. IEs specified through this command are - cleared with a DISCONNECT. - -Command - wmiconfig eth1 --setAssocIe - -Command Parameters - UINT8 ieType Used directly in 802.11 frames - UINT8 bufferSize Size of assocInfo (in bytes) ranging from - 0–240. If = 0, previously set IEs are cleared. - UINT8 assocInfo[bufferSize] Used directly in 802.11 frames - -Command Values - None - -Reset Values - IEs are cleared - -Restrictions - This command can only be issued in the DISCONNECTED state - -===================================================================== - - -Name - SET_AUTHMODE - -Synopsis - Sets the 802.11 authentication mode of reconnection - -Command - wmiconfig eth1 --setauthmode - -Command Parameters - UINT8 mode - -Command Values - mode = 0x00 Proceed with authentication during reconnect - = 0x01 Do not proceed with authentication during reconnect - -Reset Values - Authentication - -Restrictions - None - -===================================================================== - - -Name - SET_BEACON_INT - -Synopsis - Sets the beacon interval for an ad hoc network. Beacon interval selection may have an - impact on power savings. To some degree, a longer interval reduces power - consumption but also decreases throughput. A thorough understanding of IEEE - 802.11 ad hoc networks is required to use this command effectively. - -Command - wmiconfig eth1 --ibssconintv - -Command Parameters - UINT16 beaconInterval Specifies the beacon interval in TU units (1024 ms) - -Command Values - None - -Reset Values - The default beacon interval is 100 TUs (102.4 ms) - -Restrictions - This command can only be issued before the AR6000 device starts an ad hoc network - -See Also - “SET_IBSS_PM_CAPS” - -===================================================================== - - -Name - SET_BIT_RATE - -Synopsis - The host uses this command to set the AR6000 device to a specific fixed rate. - -Command - wmiconfig eth1 --setfixrates ... - -Command Parameters - INT8 rateIndex - A WMI_BIT_RATE value - { - RATE_AUTO = -1 - RATE_1Mb = 0 - RATE_2Mb = 1 - RATE_5_5M = 2 - RATE_11Mb = 3 - RATE_6Mb = 4 - RATE_9Mb = 5 - RATE_12Mb = 6 - RATE_18Mb = 7 - RATE_24Mb = 8 - RATE_36Mb = 9 - RATE_48Mb = 10 - RATE_54Mb = 11 - } WMI_BIT_RATE - - -Command Values - See command parameters - -Reset Values - The dynamic rate is determined by the AR6000 device - -Restrictions - This command is intended for use only during development/debug; it is not -intended for use in production - -See Also - “GET_BIT_RATE” - -===================================================================== - - -Name - SET_BMISS_TIME - -Synopsis - This command sets the beacon miss (BMISS) time, which the AR6000 hardware use - to recognize missed beacons. When an excessive number (15) of consecutive beacons - are missed, the AR6000 consider switching to a different BSS. The time can be - specified in number of beacons or in TUs. - -Command(s) - wmiconfig eth1 --setbmissbeacons= - wmiconfig eth1 --setbmisstime= - -Command Parameters - UINT16 bmissTime Specifies the beacon miss time - [1000...5000] in TUs (1024 ms) - UINT16 bmissbeacons Specifies the number of beacons [5...50] - -Command Values - None - -Reset Values - bmissTime is 1500 TUs (1536 ms) - -Restrictions - None - -===================================================================== - - -Name - SET_BSS_FILTER - -Synopsis - The host uses this to inform the AR6000 device of the types of networks about which - it wants to receive information from the “BSSINFO” event. As the device performs - either foreground or background scans, it applies the filter and sends “BSSINFO” - events only for the networks that pass the filter. If any of the bssFilter or the ieMask - filter matches, a BSS Info is sent to the host. The ieMask currently is used as a match - for the IEs in the beacons, probe reponses and channel switch action management - frame. See also “Scan and Roam” on page C-1. - - The BSS filter command has been enhanced to support IE based filtering. The IEs can - be specified as a bitmask through this command using this enum. - -Command - wmiconfig eth1 –filter = --ieMask 0x - -Command Parameters - UINT8 BssFilter - - Command Values - typedef struct { - A_UINT8 bssFilter; See WMI_BSS_FILTER - A_UINT32 ieMask; - } __ATTRIB_PACK WMI_BSS_FILTER_CMD; - - The ieMask can take this combination of values: - - enum { - BSS_ELEMID_CHANSWITCH = 0x01 - BSS_ELEMID_ATHEROS = 0x02, - } - -Reply Value - None - -Reset Value - BssFilter = NONE_BSS_FILTER (0) - -Restrictions - None - -See Also - “CONNECT_CMD” - -===================================================================== - - -Name - SET_BT_PARAMS - -Synopsis - This command is used to set the status of a Bluetooth stream or set Bluetooth - coexistence register parameters. The stream may be an SCO or an A2DP stream and - its status can be started/stopped/suspended/resumed. - -Command - wmiconfig –setBTparams - -Command Parameters - struct { - union { - BT_PARAMS_SCO scoParams; - BT_PARAMS_A2DP a2dpParams; - BT_PARAMS_MISC miscParams; - BT_COEX_REGS regs; - } info; - A_UINT8 paramType; - struct { - A_UINT8 noSCOPkts; Number of SCO packets between consecutive PS-POLLs - A_UINT8 pspollTimeout; - A_UINT8 stompbt; - } BT_PARAMS_SCO; - struct { - A2DP BT stream parameters - A_UINT32 period; - A_UINT32 dutycycle; - A_UINT8 stompbt; - } BT_PARAMS_A2DP; - struct { - union { - WLAN_PROTECT_POLICY_TYPE protectParams; - A_UINT16 wlanCtrlFlags; - }info; - A_UINT8 paramType; - } BT_PARAMS_MISC; - struct { - BT coexistence registers values - A_UINT32 mode; Coexistence mode - A_UINT32 scoWghts; WLAN and BT weights - A_UINT32 a2dpWghts; - A_UINT32 genWghts; - A_UINT32 mode2; Coexistence mode2 - A_UINT8 setVal; - } BT_COEX_REGS; - -Command Values - None defined - -Reset Value - None - -Restrictions - None - -===================================================================== - - -Name - SET_BT_STATUS - -Synopsis - Sets the status of a Bluetooth stream. The stream may be a SCO or an A2DP stream - and its status can be started/stopped/suspended/resumed. - -Command - wmiconfig –setBTstatus - -Command Parameters - { - A_UINT8 streamType; Stream type - A_UINT8 status; Stream status - }WMI_SET_BT_STATUS_CMD; - -Command Values - { - BT_STREAM_UNDEF = 0 - BT_STREAM_SCO - SCO stream - BT_STREAM_A2DP - A2DP stream - BT_STREAM_MAX - } BT_STREAM_TYPE; - - { - BT_STATUS_UNDEF = 0 - BT_STATUS_START - BT_STATUS_STOP - BT_STATUS_RESUME - BT_STATUS_SUSPEND - BT_STATUS_MAX - } BT_STREAM_STATUS; - -Reset Value - None defined - -Restrictions - None - -===================================================================== - - -Name - SET_CHANNEL_PARAMETERS - -Synopsis - Configures various WLAN parameters related to channels, sets the wireless mode, - and can restrict the AR6000 device to a subset of available channels. The list of - available channels varies depending on the wireless mode and the regulatory - domain. The device never operates on a channel outside of its regulatory domain. The - device starts to scan the list of channels right after this command. - -Command - wmiconfig eth1 --wmode - -Command Parameters - UINT8 phyMode See Values below. - UINT8 numberOfChannels - Number of channels in the channel array that - follows. If = 0, then the device uses all of the - channels permitted by the regulatory domain - and by the specified phyMode. - UINT16 channel[numberOfChannels] - Array listing the subset of channels (expressed - as frequencies in MHz) the host wants the - device to use. Any channel not permitted by - the specified phyMode or by the specified - regulatory domain is ignored by the device. - -Command Values - phyMode = { - Wireless mode - 11a = 0x01 - 11g = 0x02 - 11ag = 0x03 - 11b = 0x04 - 11g only = 0x05 - } - -Reset Values - phyMode - 11ag - 802.11a/g modules - 11g - 802.11g module - channels - Defaults to all channels permitted by the - current regulatory domain. - -Restrictions - This command, if issued, should be issued soon after reset and prior to the first - connection. This command should only be issued in the DISCONNECTED state. - -===================================================================== - - -Name - SET_DISC_TIMEOUT - -Synopsis - The host uses this command to configure the amount of time that the AR6000 should - spend when it attempts to reestablish a connection after losing link with its current - BSS. If this time limit is exceeded, the AR6000 send a “DISCONNECT” event. After - sending the “DISCONNECT” event the AR6000 continues to attempt to reestablish a - connection, but they do so at the interval corresponding to a foreground scan as - established by the “SET_SCAN_PARAMS” command. - - A timeout value of 0 indicates that the AR6000 will disable all autonomous roaming, - so that the AR6000 will not perform any scans after sending a “DISCONNECT” - event to the host. The state is maintained until a shutdown or host sets different - timeout value from 0. - -Command - wmiconfig eth1 --disc= - -Command Parameters - UINT8 disconnectTimeout - Specifies the time limit (in seconds) after - which a failure to reestablish a connection - results in a “DISCONNECT” event - -Command Values - None - -Reset Values - disconnectTimeout is 10 seconds - -Restrictions - This command can only be issued while in a DISCONNECTED state - -===================================================================== - - -Name - SET_FIXRATES - -Synopsis - By default, the AR6000 device uses all PHY rates based on mode of operation. If the - host application requires the device to use subset of supported rates, it can set those - rates with this command. In 802.11g mode, the AR6000 device takes the entire - 802.11g basic rate set and the rates specified with this command and uses it as the - supported rate set. - - This rate set is advertised in the probe request and the assoc/re-assoc request as - supported rates. Upon successful association, the device modifies the rate set pool - using the: intersection of AP-supported rates with the union of the 802.11g basic rate - set and rates set using this command. The device picks transmission rates from this - pool based on a rate control algorithm. - -Command - TBD - -Command Parameters - A_UINT16 fixRateMask; - The individual bit is an index for rate table, - and setting the that index to 1 would set that - corresponding rate. E.g., fixRateMask = 9 - (1001) sets 1 Mbps and 11 Mbps. - -Command Values - None - -Reset Value - None defined - -Restrictions - None - -See Also - “GET_FIXRATES” - -===================================================================== - - -Name - SET_WHAL_PARAM - -Synopsis - An internal AR6000 command that is used to set certain hardware parameters. The - description of this command is in $WORKAREA/include/halapi.h. - -Command - TBD - -Command Parameters - ATH_HAL_SETCABTO_CMDID - Sets the timeout waiting for the multicast - traffic after a DTIM beacon (in TUs). - -Command Values - None - -Reset Value - Default = 10 TUs - -Restrictions - This command should be executed before issuing a connect command. - -===================================================================== - - -Name - SET_HOST_SLEEP_MODE - -Synopsis - The host uses this command to set the host mode to asleep or awake. All packets are - delivered to the host when the host mode is awake. When host mode is asleep, only if - WoW is enabled and the incoming packet matches one of the specified WoW - patterns, will the packet be delivered to the host. The host will also be woken up by - the target for pattern-matching packets and important events. - -Command - wmiconfig –sethostmode= - -Command Parameters - A_BOOL awake Set the host mode to awake - A_BOOL asleep Set the host mode to asleep - -Command Values - 1 = awake, 0 = asleep - -Reset Value - None defined (default host mode is awake) - -Restrictions - None - - -===================================================================== - -Name - SET_IBSS_PM_CAPS - -Synopsis - Used to support a non-standard power management scheme for an ad hoc wireless - network consisting of up to eight stations (STAs) that support this form of power - saving (e.g., Atheros-based STAs). A thorough understanding of IEEE 802.11 ad hoc - networks is required to use this command effectively. - -Command - wmiconfig eth1 --ibsspmcaps --ps= - --aw= - --ttl=