diff --git a/[refs] b/[refs] index 24e5d5c1e625..60ea2a028c29 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: a5fcaa210626a79465321e344c91a6a7dc3881fa +refs/heads/master: cca5307d178c931e70a642302b56fa2701d02253 diff --git a/trunk/Documentation/cachetlb.txt b/trunk/Documentation/cachetlb.txt index 866b76139420..debf6813934a 100644 --- a/trunk/Documentation/cachetlb.txt +++ b/trunk/Documentation/cachetlb.txt @@ -253,7 +253,7 @@ Here are the routines, one by one: The first of these two routines is invoked after map_vm_area() has installed the page table entries. The second is invoked - before unmap_kernel_range() deletes the page table entries. + before unmap_vm_area() deletes the page table entries. There exists another whole class of cpu cache issues which currently require a whole different set of interfaces to handle properly. diff --git a/trunk/Documentation/feature-removal-schedule.txt b/trunk/Documentation/feature-removal-schedule.txt index d05e6243b4df..18bd2ddccb15 100644 --- a/trunk/Documentation/feature-removal-schedule.txt +++ b/trunk/Documentation/feature-removal-schedule.txt @@ -297,16 +297,3 @@ Why: Obsolete for multiple years now, NAT core provides the same behaviour. Who: Patrick McHardy --------------------------- - -What: The arch/ppc and include/asm-ppc directories -When: Jun 2008 -Why: The arch/powerpc tree is the merged architecture for ppc32 and ppc64 - platforms. Currently there are efforts underway to port the remaining - arch/ppc platforms to the merged tree. New submissions to the arch/ppc - tree have been frozen with the 2.6.22 kernel release and that tree will - remain in bug-fix only mode until its scheduled removal. Platforms - that are not ported by June 2008 will be removed due to the lack of an - interested maintainer. -Who: linuxppc-dev@ozlabs.org - ---------------------------- diff --git a/trunk/Documentation/powerpc/booting-without-of.txt b/trunk/Documentation/powerpc/booting-without-of.txt index 0c2434822094..d42d98107d49 100644 --- a/trunk/Documentation/powerpc/booting-without-of.txt +++ b/trunk/Documentation/powerpc/booting-without-of.txt @@ -42,16 +42,15 @@ Table of Contents 1) Defining child nodes of an SOC 2) Representing devices without a current OF specification a) MDIO IO device - b) Gianfar-compatible ethernet nodes c) PHY nodes + b) Gianfar-compatible ethernet nodes d) Interrupt controllers e) I2C f) Freescale SOC USB controllers g) Freescale SOC SEC Security Engines h) Board Control and Status (BCSR) i) Freescale QUICC Engine module (QE) - j) Flash chip nodes - k) Global Utilities Block + g) Flash chip nodes VII - Specifying interrupt information for devices 1) interrupts property @@ -627,14 +626,6 @@ So the node content can be summarized as a start token, a full path, a list of properties, a list of child nodes, and an end token. Every child node is a full node structure itself as defined above. -NOTE: The above definition requires that all property definitions for -a particular node MUST precede any subnode definitions for that node. -Although the structure would not be ambiguous if properties and -subnodes were intermingled, the kernel parser requires that the -properties come first (up until at least 2.6.22). Any tools -manipulating a flattened tree must take care to preserve this -constraint. - 4) Device tree "strings" block In order to save space, property names, which are generally redundant, @@ -1791,33 +1782,6 @@ platforms are moved over to use the flattened-device-tree model. partition-names = "fs\0firmware"; }; - k) Global Utilities Block - - The global utilities block controls power management, I/O device - enabling, power-on-reset configuration monitoring, general-purpose - I/O signal configuration, alternate function selection for multiplexed - signals, and clock control. - - Required properties: - - - compatible : Should define the compatible device type for - global-utilities. - - reg : Offset and length of the register set for the device. - - Recommended properties: - - - fsl,has-rstcr : Indicates that the global utilities register set - contains a functioning "reset control register" (i.e. the board - is wired to reset upon setting the HRESET_REQ bit in this register). - - Example: - - global-utilities@e0000 { /* global utilities block */ - compatible = "fsl,mpc8548-guts"; - reg = ; - fsl,has-rstcr; - }; - More devices will be defined as this spec matures. VII - Specifying interrupt information for devices diff --git a/trunk/arch/powerpc/Kconfig b/trunk/arch/powerpc/Kconfig index e641bb68d871..6b8b83ebca75 100644 --- a/trunk/arch/powerpc/Kconfig +++ b/trunk/arch/powerpc/Kconfig @@ -4,7 +4,17 @@ mainmenu "Linux/PowerPC Kernel Configuration" -source "arch/powerpc/platforms/Kconfig.cputype" +config PPC64 + bool "64-bit kernel" + default n + help + This option selects whether a 32-bit or a 64-bit kernel + will be built. + +config PPC_PM_NEEDS_RTC_LIB + bool + select RTC_LIB + default y if PM config PPC32 bool @@ -125,6 +135,123 @@ config PPC64_SWSUSP depends on PPC64 && (BROKEN || (PPC_PMAC64 && EXPERIMENTAL)) default y +menu "Processor support" +choice + prompt "Processor Type" + depends on PPC32 + default 6xx + +config CLASSIC32 + bool "52xx/6xx/7xx/74xx" + select PPC_FPU + select 6xx + help + There are four families of PowerPC chips supported. The more common + types (601, 603, 604, 740, 750, 7400), the Motorola embedded + versions (821, 823, 850, 855, 860, 52xx, 82xx, 83xx), the AMCC + embedded versions (403 and 405) and the high end 64 bit Power + processors (POWER 3, POWER4, and IBM PPC970 also known as G5). + + This option is the catch-all for 6xx types, including some of the + embedded versions. Unless there is see an option for the specific + chip family you are using, you want this option. + + You do not want this if you are building a kernel for a 64 bit + IBM RS/6000 or an Apple G5, choose 6xx. + + If unsure, select this option + + Note that the kernel runs in 32-bit mode even on 64-bit chips. + +config PPC_82xx + bool "Freescale 82xx" + select 6xx + select PPC_FPU + +config PPC_83xx + bool "Freescale 83xx" + select 6xx + select FSL_SOC + select 83xx + select PPC_FPU + select WANT_DEVICE_TREE + +config PPC_85xx + bool "Freescale 85xx" + select E500 + select FSL_SOC + select 85xx + select WANT_DEVICE_TREE + +config PPC_86xx + bool "Freescale 86xx" + select 6xx + select FSL_SOC + select FSL_PCIE + select PPC_FPU + select ALTIVEC + help + The Freescale E600 SoCs have 74xx cores. + +config PPC_8xx + bool "Freescale 8xx" + select FSL_SOC + select 8xx + +config 40x + bool "AMCC 40x" + select PPC_DCR_NATIVE + +config 44x + bool "AMCC 44x" + select PPC_DCR_NATIVE + select WANT_DEVICE_TREE + +config E200 + bool "Freescale e200" + +endchoice + +config POWER4_ONLY + bool "Optimize for POWER4" + depends on PPC64 + default n + ---help--- + Cause the compiler to optimize for POWER4/POWER5/PPC970 processors. + The resulting binary will not work on POWER3 or RS64 processors + when compiled with binutils 2.15 or later. + +config POWER3 + bool + depends on PPC64 + default y if !POWER4_ONLY + +config POWER4 + depends on PPC64 + def_bool y + +config 6xx + bool + +# this is temp to handle compat with arch=ppc +config 8xx + bool + +# this is temp to handle compat with arch=ppc +config 83xx + bool + +# this is temp to handle compat with arch=ppc +config 85xx + bool + +config E500 + bool + +config PPC_FPU + bool + default y if PPC64 + config PPC_DCR_NATIVE bool default n @@ -143,6 +270,134 @@ config PPC_OF_PLATFORM_PCI depends on PPC64 # not supported on 32 bits yet default n +config 4xx + bool + depends on 40x || 44x + default y + +config BOOKE + bool + depends on E200 || E500 || 44x + default y + +config FSL_BOOKE + bool + depends on E200 || E500 + default y + +config PTE_64BIT + bool + depends on 44x || E500 + default y if 44x + default y if E500 && PHYS_64BIT + +config PHYS_64BIT + bool 'Large physical address support' if E500 + depends on 44x || E500 + select RESOURCES_64BIT + default y if 44x + ---help--- + This option enables kernel support for larger than 32-bit physical + addresses. This features is not be available on all e500 cores. + + If in doubt, say N here. + +config ALTIVEC + bool "AltiVec Support" + depends on CLASSIC32 || POWER4 + ---help--- + This option enables kernel support for the Altivec extensions to the + PowerPC processor. The kernel currently supports saving and restoring + altivec registers, and turning on the 'altivec enable' bit so user + processes can execute altivec instructions. + + This option is only usefully if you have a processor that supports + altivec (G4, otherwise known as 74xx series), but does not have + any affect on a non-altivec cpu (it does, however add code to the + kernel). + + If in doubt, say Y here. + +config SPE + bool "SPE Support" + depends on E200 || E500 + default y + ---help--- + This option enables kernel support for the Signal Processing + Extensions (SPE) to the PowerPC processor. The kernel currently + supports saving and restoring SPE registers, and turning on the + 'spe enable' bit so user processes can execute SPE instructions. + + This option is only useful if you have a processor that supports + SPE (e500, otherwise known as 85xx series), but does not have any + effect on a non-spe cpu (it does, however add code to the kernel). + + If in doubt, say Y here. + +config PPC_STD_MMU + bool + depends on 6xx || POWER3 || POWER4 || PPC64 + default y + +config PPC_STD_MMU_32 + def_bool y + depends on PPC_STD_MMU && PPC32 + +config PPC_MM_SLICES + bool + default y if HUGETLB_PAGE + default n + +config VIRT_CPU_ACCOUNTING + bool "Deterministic task and CPU time accounting" + depends on PPC64 + default y + help + Select this option to enable more accurate task and CPU time + accounting. This is done by reading a CPU counter on each + kernel entry and exit and on transitions within the kernel + between system, softirq and hardirq state, so there is a + small performance impact. This also enables accounting of + stolen time on logically-partitioned systems running on + IBM POWER5-based machines. + + If in doubt, say Y here. + +config SMP + depends on PPC_STD_MMU + bool "Symmetric multi-processing support" + ---help--- + This enables support for systems with more than one CPU. If you have + a system with only one CPU, say N. If you have a system with more + than one CPU, say Y. Note that the kernel does not currently + support SMP machines with 603/603e/603ev or PPC750 ("G3") processors + since they have inadequate hardware support for multiprocessor + operation. + + If you say N here, the kernel will run on single and multiprocessor + machines, but will use only one CPU of a multiprocessor machine. If + you say Y here, the kernel will run on single-processor machines. + On a single-processor machine, the kernel will run faster if you say + N here. + + If you don't know what to do here, say N. + +config NR_CPUS + int "Maximum number of CPUs (2-128)" + range 2 128 + depends on SMP + default "32" if PPC64 + default "4" + +config NOT_COHERENT_CACHE + bool + depends on 4xx || 8xx || E200 + default y + +config CONFIG_CHECK_CACHE_COHERENCY + bool +endmenu + source "init/Kconfig" source "arch/powerpc/platforms/Kconfig" @@ -422,6 +677,10 @@ config SBUS config FSL_SOC bool +config FSL_PCIE + bool + depends on PPC_86xx + # Yes MCA RS/6000s exist but Linux-PPC does not currently support any config MCA bool @@ -429,10 +688,10 @@ config MCA config PCI bool "PCI support" if 40x || CPM2 || PPC_83xx || PPC_85xx || PPC_86xx \ || PPC_MPC52xx || (EMBEDDED && (PPC_PSERIES || PPC_ISERIES)) \ - || PPC_PS3 - default y if !40x && !CPM2 && !8xx && !PPC_83xx \ + || MPC7448HPC2 || PPC_PS3 || PPC_HOLLY + default y if !40x && !CPM2 && !8xx && !APUS && !PPC_83xx \ && !PPC_85xx && !PPC_86xx - default PCI_PERMEDIA if !4xx && !CPM2 && !8xx + default PCI_PERMEDIA if !4xx && !CPM2 && !8xx && APUS default PCI_QSPAN if !4xx && !CPM2 && 8xx select ARCH_SUPPORTS_MSI help diff --git a/trunk/arch/powerpc/Makefile b/trunk/arch/powerpc/Makefile index 187a39af3e1c..fbafd965dcd2 100644 --- a/trunk/arch/powerpc/Makefile +++ b/trunk/arch/powerpc/Makefile @@ -148,7 +148,7 @@ all: $(KBUILD_IMAGE) CPPFLAGS_vmlinux.lds := -Upowerpc -BOOT_TARGETS = zImage zImage.initrd uImage +BOOT_TARGETS = zImage zImage.initrd zImage.dts zImage.dts_initrd uImage PHONY += $(BOOT_TARGETS) diff --git a/trunk/arch/powerpc/boot/44x.c b/trunk/arch/powerpc/boot/44x.c index 9f64e840bef6..d51377d9024f 100644 --- a/trunk/arch/powerpc/boot/44x.c +++ b/trunk/arch/powerpc/boot/44x.c @@ -38,48 +38,3 @@ void ibm44x_fixup_memsize(void) dt_fixup_memory(0, memsize); } - -#define SPRN_DBCR0 0x134 -#define DBCR0_RST_SYSTEM 0x30000000 - -void ibm44x_dbcr_reset(void) -{ - unsigned long tmp; - - asm volatile ( - "mfspr %0,%1\n" - "oris %0,%0,%2@h\n" - "mtspr %1,%0" - : "=&r"(tmp) : "i"(SPRN_DBCR0), "i"(DBCR0_RST_SYSTEM) - ); - -} - -/* Read 4xx EBC bus bridge registers to get mappings of the peripheral - * banks into the OPB address space */ -void ibm4xx_fixup_ebc_ranges(const char *ebc) -{ - void *devp; - u32 bxcr; - u32 ranges[EBC_NUM_BANKS*4]; - u32 *p = ranges; - int i; - - for (i = 0; i < EBC_NUM_BANKS; i++) { - mtdcr(DCRN_EBC0_CFGADDR, EBC_BXCR(i)); - bxcr = mfdcr(DCRN_EBC0_CFGDATA); - - if ((bxcr & EBC_BXCR_BU) != EBC_BXCR_BU_OFF) { - *p++ = i; - *p++ = 0; - *p++ = bxcr & EBC_BXCR_BAS; - *p++ = EBC_BXCR_BANK_SIZE(bxcr); - } - } - - devp = finddevice(ebc); - if (! devp) - fatal("Couldn't locate EBC node %s\n\r", ebc); - - setprop(devp, "ranges", ranges, (p - ranges) * sizeof(u32)); -} diff --git a/trunk/arch/powerpc/boot/44x.h b/trunk/arch/powerpc/boot/44x.h index 577982c9a3cd..7b129ad043e1 100644 --- a/trunk/arch/powerpc/boot/44x.h +++ b/trunk/arch/powerpc/boot/44x.h @@ -11,9 +11,6 @@ #define _PPC_BOOT_44X_H_ void ibm44x_fixup_memsize(void); -void ibm4xx_fixup_ebc_ranges(const char *ebc); - -void ibm44x_dbcr_reset(void); void ebony_init(void *mac0, void *mac1); #endif /* _PPC_BOOT_44X_H_ */ diff --git a/trunk/arch/powerpc/boot/Makefile b/trunk/arch/powerpc/boot/Makefile index 61a6f34ca5ed..ff2701949ee1 100644 --- a/trunk/arch/powerpc/boot/Makefile +++ b/trunk/arch/powerpc/boot/Makefile @@ -43,11 +43,10 @@ $(addprefix $(obj)/,$(zlib) gunzip_util.o main.o): \ src-wlib := string.S crt0.S stdio.c main.c flatdevtree.c flatdevtree_misc.c \ ns16550.c serial.c simple_alloc.c div64.S util.S \ - gunzip_util.c elf_util.c $(zlib) devtree.c oflib.c ofconsole.c \ - 44x.c ebony.c mv64x60.c mpsc.c mv64x60_i2c.c cuboot.c + gunzip_util.c elf_util.c $(zlib) devtree.c \ + 44x.c ebony.c mv64x60.c mpsc.c mv64x60_i2c.c src-plat := of.c cuboot-83xx.c cuboot-85xx.c holly.c \ - cuboot-ebony.c treeboot-ebony.c prpmc2800.c \ - ps3-head.S ps3-hvcall.S ps3.c + cuboot-ebony.c treeboot-ebony.c prpmc2800.c src-boot := $(src-wlib) $(src-plat) empty.c src-boot := $(addprefix $(obj)/, $(src-boot)) @@ -76,11 +75,11 @@ $(addprefix $(obj)/,$(zliblinuxheader)): $(obj)/%: $(srctree)/include/linux/% $(obj)/empty.c: @touch $@ -$(obj)/zImage.lds $(obj)/zImage.coff.lds $(obj)/zImage.ps3.lds: $(obj)/%: $(srctree)/$(src)/%.S +$(obj)/zImage.lds $(obj)/zImage.coff.lds: $(obj)/%: $(srctree)/$(src)/%.S @cp $< $@ clean-files := $(zlib) $(zlibheader) $(zliblinuxheader) \ - empty.c zImage zImage.coff.lds zImage.ps3.lds zImage.lds + empty.c zImage.coff.lds zImage.lds quiet_cmd_bootcc = BOOTCC $@ cmd_bootcc = $(CROSS32CC) -Wp,-MD,$(depfile) $(BOOTCFLAGS) -c -o $@ $< @@ -103,7 +102,7 @@ hostprogs-y := addnote addRamDisk hack-coff mktree targets += $(patsubst $(obj)/%,%,$(obj-boot) wrapper.a) extra-y := $(obj)/wrapper.a $(obj-plat) $(obj)/empty.o \ - $(obj)/zImage.lds $(obj)/zImage.coff.lds $(obj)/zImage.ps3.lds + $(obj)/zImage.lds $(obj)/zImage.coff.lds wrapper :=$(srctree)/$(src)/wrapper wrapperbits := $(extra-y) $(addprefix $(obj)/,addnote hack-coff mktree) \ @@ -133,7 +132,7 @@ image-$(CONFIG_PPC_CELLEB) += zImage.pseries image-$(CONFIG_PPC_CHRP) += zImage.chrp image-$(CONFIG_PPC_EFIKA) += zImage.chrp image-$(CONFIG_PPC_PMAC) += zImage.pmac -image-$(CONFIG_PPC_HOLLY) += zImage.holly +image-$(CONFIG_PPC_HOLLY) += zImage.holly-elf image-$(CONFIG_PPC_PRPMC2800) += zImage.prpmc2800 image-$(CONFIG_PPC_ISERIES) += zImage.iseries image-$(CONFIG_DEFAULT_UIMAGE) += uImage @@ -158,43 +157,55 @@ targets += $(image-y) $(initrd-y) $(addprefix $(obj)/, $(initrd-y)): $(obj)/ramdisk.image.gz -# If CONFIG_WANT_DEVICE_TREE is set and CONFIG_DEVICE_TREE isn't an -# empty string, define 'dts' to be path to the dts -# CONFIG_DEVICE_TREE will have "" around it, make sure to strip them -ifeq ($(CONFIG_WANT_DEVICE_TREE),y) -ifneq ($(CONFIG_DEVICE_TREE),"") -dts = $(if $(shell echo $(CONFIG_DEVICE_TREE) | grep '^/'),\ - ,$(srctree)/$(src)/dts/)$(CONFIG_DEVICE_TREE:"%"=%) -endif -endif +dts- := $(patsubst zImage%, zImage.dts%, $(image-n) $(image-)) +dts-y := $(patsubst zImage%, zImage.dts%, $(image-y)) +dts-y := $(filter-out $(image-y), $(dts-y)) +targets += $(image-y) $(dts-y) + +dts_initrd- := $(patsubst zImage%, zImage.dts_initrd%, $(image-n) $(image-)) +dts_initrd-y := $(patsubst zImage%, zImage.dts_initrd%, $(image-y)) +dts_initrd-y := $(filter-out $(image-y), $(dts_initrd-y)) +targets += $(image-y) $(dts_initrd-y) + +$(addprefix $(obj)/, $(dts_initrd-y)): $(obj)/ramdisk.image.gz # Don't put the ramdisk on the pattern rule; when its missing make will try # the pattern rule with less dependencies that also matches (even with the # hard dependency listed). -$(obj)/zImage.initrd.%: vmlinux $(wrapperbits) $(dts) +$(obj)/zImage.dts_initrd.%: vmlinux $(wrapperbits) $(dts) $(obj)/ramdisk.image.gz $(call if_changed,wrap,$*,$(dts),,$(obj)/ramdisk.image.gz) -$(obj)/zImage.%: vmlinux $(wrapperbits) $(dts) +$(obj)/zImage.dts.%: vmlinux $(wrapperbits) $(dts) $(call if_changed,wrap,$*,$(dts)) -# This cannot be in the root of $(src) as the zImage rule always adds a $(obj) -# prefix -$(obj)/vmlinux.strip: vmlinux - $(STRIP) -s -R .comment $< -o $@ +$(obj)/zImage.initrd.%: vmlinux $(wrapperbits) + $(call if_changed,wrap,$*,,,$(obj)/ramdisk.image.gz) + +$(obj)/zImage.%: vmlinux $(wrapperbits) + $(call if_changed,wrap,$*) $(obj)/zImage.iseries: vmlinux $(STRIP) -s -R .comment $< -o $@ -$(obj)/zImage.ps3: vmlinux $(wrapper) $(wrapperbits) $(srctree)/$(src)/dts/ps3.dts - $(STRIP) -s -R .comment $< -o vmlinux.strip - $(call cmd,wrap,ps3,$(srctree)/$(src)/dts/ps3.dts,,) +$(obj)/zImage.ps3: vmlinux + $(STRIP) -s -R .comment $< -o $@ + +$(obj)/zImage.initrd.ps3: vmlinux + @echo " WARNING zImage.initrd.ps3 not supported (yet)" + +$(obj)/zImage.holly-elf: vmlinux $(wrapperbits) + $(call if_changed,wrap,holly,$(obj)/dts/holly.dts,,) -$(obj)/zImage.initrd.ps3: vmlinux $(wrapper) $(wrapperbits) $(srctree)/$(src)/dts/ps3.dts $(obj)/ramdisk.image.gz - $(call cmd,wrap,ps3,$(srctree)/$(src)/dts/ps3.dts,,$(obj)/ramdisk.image.gz) +$(obj)/zImage.initrd.holly-elf: vmlinux $(wrapperbits) $(obj)/ramdisk.image.gz + $(call if_changed,wrap,holly,$(obj)/dts/holly.dts,,$(obj)/ramdisk.image.gz) $(obj)/uImage: vmlinux $(wrapperbits) $(call if_changed,wrap,uboot) +# CONFIG_DEVICE_TREE will have "" around it, make sure to strip them +dts = $(if $(shell echo $(CONFIG_DEVICE_TREE) | grep '^/'),\ + ,$(srctree)/$(src)/dts/)$(CONFIG_DEVICE_TREE:"%"=%) + $(obj)/cuImage.%: vmlinux $(dts) $(wrapperbits) $(call if_changed,wrap,cuboot-$*,$(dts)) @@ -204,22 +215,22 @@ $(obj)/treeImage.initrd.%: vmlinux $(dts) $(wrapperbits) $(obj)/treeImage.%: vmlinux $(dts) $(wrapperbits) $(call if_changed,wrap,treeboot-$*,$(dts)) -# If there isn't a platform selected then just strip the vmlinux. -ifeq (,$(image-y)) -image-y := vmlinux.strip -endif - $(obj)/zImage: $(addprefix $(obj)/, $(image-y)) @rm -f $@; ln $< $@ $(obj)/zImage.initrd: $(addprefix $(obj)/, $(initrd-y)) @rm -f $@; ln $< $@ +$(obj)/zImage.dts: $(addprefix $(obj)/, $(dts-y)) + @rm -f $@; ln $< $@ +$(obj)/zImage.dts_initrd: $(addprefix $(obj)/, $(dts_initrd-y)) + @rm -f $@; ln $< $@ + install: $(CONFIGURE) $(addprefix $(obj)/, $(image-y)) sh -x $(srctree)/$(src)/install.sh "$(KERNELRELEASE)" vmlinux System.map "$(INSTALL_PATH)" $< # anything not in $(targets) -clean-files += $(image-) $(initrd-) zImage zImage.initrd cuImage.* treeImage.* \ - otheros.bld +clean-files += $(image-) $(initrd-) zImage zImage.initrd cuImage.* \ + treeImage.* zImage.dts zImage.dts_initrd # clean up files cached by wrapper clean-kernel := vmlinux.strip vmlinux.bin diff --git a/trunk/arch/powerpc/boot/cuboot-83xx.c b/trunk/arch/powerpc/boot/cuboot-83xx.c index 296025d8b295..9af554eea54b 100644 --- a/trunk/arch/powerpc/boot/cuboot-83xx.c +++ b/trunk/arch/powerpc/boot/cuboot-83xx.c @@ -12,12 +12,12 @@ #include "ops.h" #include "stdio.h" -#include "cuboot.h" #define TARGET_83xx #include "ppcboot.h" static bd_t bd; +extern char _end[]; extern char _dtb_start[], _dtb_end[]; static void platform_fixups(void) @@ -52,7 +52,16 @@ static void platform_fixups(void) void platform_init(unsigned long r3, unsigned long r4, unsigned long r5, unsigned long r6, unsigned long r7) { - CUBOOT_INIT(); + unsigned long end_of_ram = bd.bi_memstart + bd.bi_memsize; + unsigned long avail_ram = end_of_ram - (unsigned long)_end; + + memcpy(&bd, (bd_t *)r3, sizeof(bd)); + loader_info.initrd_addr = r4; + loader_info.initrd_size = r4 ? r5 - r4 : 0; + loader_info.cmdline = (char *)r6; + loader_info.cmdline_len = r7 - r6; + + simple_alloc_init(_end, avail_ram - 1024*1024, 32, 64); ft_init(_dtb_start, _dtb_end - _dtb_start, 32); serial_console_init(); platform_ops.fixups = platform_fixups; diff --git a/trunk/arch/powerpc/boot/cuboot-85xx.c b/trunk/arch/powerpc/boot/cuboot-85xx.c index 10f0f697c935..e2560317f278 100644 --- a/trunk/arch/powerpc/boot/cuboot-85xx.c +++ b/trunk/arch/powerpc/boot/cuboot-85xx.c @@ -12,12 +12,12 @@ #include "ops.h" #include "stdio.h" -#include "cuboot.h" #define TARGET_85xx #include "ppcboot.h" static bd_t bd; +extern char _end[]; extern char _dtb_start[], _dtb_end[]; static void platform_fixups(void) @@ -53,7 +53,16 @@ static void platform_fixups(void) void platform_init(unsigned long r3, unsigned long r4, unsigned long r5, unsigned long r6, unsigned long r7) { - CUBOOT_INIT(); + unsigned long end_of_ram = bd.bi_memstart + bd.bi_memsize; + unsigned long avail_ram = end_of_ram - (unsigned long)_end; + + memcpy(&bd, (bd_t *)r3, sizeof(bd)); + loader_info.initrd_addr = r4; + loader_info.initrd_size = r4 ? r5 - r4 : 0; + loader_info.cmdline = (char *)r6; + loader_info.cmdline_len = r7 - r6; + + simple_alloc_init(_end, avail_ram - 1024*1024, 32, 64); ft_init(_dtb_start, _dtb_end - _dtb_start, 32); serial_console_init(); platform_ops.fixups = platform_fixups; diff --git a/trunk/arch/powerpc/boot/cuboot-ebony.c b/trunk/arch/powerpc/boot/cuboot-ebony.c index c5f37ce172ea..4464c5f67acb 100644 --- a/trunk/arch/powerpc/boot/cuboot-ebony.c +++ b/trunk/arch/powerpc/boot/cuboot-ebony.c @@ -15,16 +15,28 @@ #include "ops.h" #include "stdio.h" #include "44x.h" -#include "cuboot.h" #define TARGET_44x #include "ppcboot.h" static bd_t bd; +extern char _end[]; + +BSS_STACK(4096); void platform_init(unsigned long r3, unsigned long r4, unsigned long r5, unsigned long r6, unsigned long r7) { - CUBOOT_INIT(); + unsigned long end_of_ram = bd.bi_memstart + bd.bi_memsize; + unsigned long avail_ram = end_of_ram - (unsigned long)_end; + + memcpy(&bd, (bd_t *)r3, sizeof(bd)); + loader_info.initrd_addr = r4; + loader_info.initrd_size = r4 ? r5 : 0; + loader_info.cmdline = (char *)r6; + loader_info.cmdline_len = r7 - r6; + + simple_alloc_init(_end, avail_ram, 32, 64); + ebony_init(&bd.bi_enetaddr, &bd.bi_enet1addr); } diff --git a/trunk/arch/powerpc/boot/cuboot.c b/trunk/arch/powerpc/boot/cuboot.c deleted file mode 100644 index 65795468ad6f..000000000000 --- a/trunk/arch/powerpc/boot/cuboot.c +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Compatibility for old (not device tree aware) U-Boot versions - * - * Author: Scott Wood - * Consolidated using macros by David Gibson - * - * Copyright 2007 David Gibson, IBM Corporation. - * Copyright (c) 2007 Freescale Semiconductor, 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. - */ - -#include "ops.h" -#include "stdio.h" - -#include "ppcboot.h" - -extern char _end[]; -extern char _dtb_start[], _dtb_end[]; - -void cuboot_init(unsigned long r4, unsigned long r5, - unsigned long r6, unsigned long r7, - unsigned long end_of_ram) -{ - unsigned long avail_ram = end_of_ram - (unsigned long)_end; - - loader_info.initrd_addr = r4; - loader_info.initrd_size = r4 ? r5 - r4 : 0; - loader_info.cmdline = (char *)r6; - loader_info.cmdline_len = r7 - r6; - - simple_alloc_init(_end, avail_ram - 1024*1024, 32, 64); -} diff --git a/trunk/arch/powerpc/boot/cuboot.h b/trunk/arch/powerpc/boot/cuboot.h deleted file mode 100644 index cd2aa7f348f3..000000000000 --- a/trunk/arch/powerpc/boot/cuboot.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef _PPC_BOOT_CUBOOT_H_ -#define _PPC_BOOT_CUBOOT_H_ - -void cuboot_init(unsigned long r4, unsigned long r5, - unsigned long r6, unsigned long r7, - unsigned long end_of_ram); - -#define CUBOOT_INIT() \ - do { \ - memcpy(&bd, (bd_t *)r3, sizeof(bd)); \ - cuboot_init(r4, r5, r6, r7, bd.bi_memstart + bd.bi_memsize); \ - } while (0) - -#endif /* _PPC_BOOT_CUBOOT_H_ */ diff --git a/trunk/arch/powerpc/boot/dcr.h b/trunk/arch/powerpc/boot/dcr.h index 14b44aa96fea..877bc97b1e97 100644 --- a/trunk/arch/powerpc/boot/dcr.h +++ b/trunk/arch/powerpc/boot/dcr.h @@ -26,43 +26,6 @@ static const unsigned long sdram_bxcr[] = { SDRAM0_B0CR, SDRAM0_B1CR, SDRAM0_B2C #define SDRAM_CONFIG_BANK_SIZE(reg) \ (0x00400000 << ((reg & SDRAM_CONFIG_SIZE_MASK) >> 17)) -/* 440GP External Bus Controller (EBC) */ -#define DCRN_EBC0_CFGADDR 0x012 -#define DCRN_EBC0_CFGDATA 0x013 -#define EBC_NUM_BANKS 8 -#define EBC_B0CR 0x00 -#define EBC_B1CR 0x01 -#define EBC_B2CR 0x02 -#define EBC_B3CR 0x03 -#define EBC_B4CR 0x04 -#define EBC_B5CR 0x05 -#define EBC_B6CR 0x06 -#define EBC_B7CR 0x07 -#define EBC_BXCR(n) (n) -#define EBC_BXCR_BAS 0xfff00000 -#define EBC_BXCR_BS 0x000e0000 -#define EBC_BXCR_BANK_SIZE(reg) \ - (0x100000 << (((reg) & EBC_BXCR_BS) >> 17)) -#define EBC_BXCR_BU 0x00018000 -#define EBC_BXCR_BU_OFF 0x00000000 -#define EBC_BXCR_BU_RO 0x00008000 -#define EBC_BXCR_BU_WO 0x00010000 -#define EBC_BXCR_BU_RW 0x00018000 -#define EBC_BXCR_BW 0x00006000 -#define EBC_B0AP 0x10 -#define EBC_B1AP 0x11 -#define EBC_B2AP 0x12 -#define EBC_B3AP 0x13 -#define EBC_B4AP 0x14 -#define EBC_B5AP 0x15 -#define EBC_B6AP 0x16 -#define EBC_B7AP 0x17 -#define EBC_BXAP(n) (0x10+(n)) -#define EBC_BEAR 0x20 -#define EBC_BESR 0x21 -#define EBC_CFG 0x23 -#define EBC_CID 0x24 - /* 440GP Clock, PM, chip control */ #define DCRN_CPC0_SR 0x0b0 #define DCRN_CPC0_ER 0x0b1 diff --git a/trunk/arch/powerpc/boot/dts/ebony.dts b/trunk/arch/powerpc/boot/dts/ebony.dts index c5f99613fc7b..0ec02f4726b5 100644 --- a/trunk/arch/powerpc/boot/dts/ebony.dts +++ b/trunk/arch/powerpc/boot/dts/ebony.dts @@ -31,8 +31,8 @@ reg = <0>; clock-frequency = <0>; // Filled in by zImage timebase-frequency = <0>; // Filled in by zImage - i-cache-line-size = <20>; - d-cache-line-size = <20>; + i-cache-line-size = <32>; + d-cache-line-size = <32>; i-cache-size = <8000>; /* 32 kB */ d-cache-size = <8000>; /* 32 kB */ dcr-controller; @@ -135,9 +135,11 @@ #address-cells = <2>; #size-cells = <1>; clock-frequency = <0>; // Filled in by zImage - // ranges property is supplied by zImage - // based on firmware's configuration of the - // EBC bridge + ranges = <0 00000000 fff00000 100000 + 1 00000000 48000000 100000 + 2 00000000 ff800000 400000 + 3 00000000 48200000 100000 + 7 00000000 48300000 100000>; interrupts = <5 4>; interrupt-parent = <&UIC1>; diff --git a/trunk/arch/powerpc/boot/dts/holly.dts b/trunk/arch/powerpc/boot/dts/holly.dts index 80a4fab8ee37..254499b107f4 100644 --- a/trunk/arch/powerpc/boot/dts/holly.dts +++ b/trunk/arch/powerpc/boot/dts/holly.dts @@ -46,7 +46,7 @@ tsi109@c0000000 { device_type = "tsi-bridge"; - compatible = "tsi109-bridge", "tsi108-bridge"; + compatible = "tsi-bridge"; #address-cells = <1>; #size-cells = <1>; ranges = <00000000 c0000000 00010000>; @@ -54,55 +54,52 @@ i2c@7000 { device_type = "i2c"; - compatible = "tsi109-i2c", "tsi108-i2c"; - interrupt-parent = <&MPIC>; + compatible = "tsi-i2c"; + interrupt-parent = < &/tsi109@c0000000/pic@7400 >; interrupts = ; reg = <7000 400>; }; - MDIO: mdio@6000 { + mdio@6000 { device_type = "mdio"; - compatible = "tsi109-mdio", "tsi108-mdio"; - reg = <6000 50>; - #address-cells = <1>; - #size-cells = <0>; + compatible = "tsi-ethernet"; - PHY1: ethernet-phy@1 { - compatible = "bcm5461a"; - reg = <1>; - txc-rxc-delay-disable; + PHY1: ethernet-phy@6000 { + device_type = "ethernet-phy"; + compatible = "bcm54xx"; + reg = <6000 50>; + phy-id = <1>; }; - PHY2: ethernet-phy@2 { - compatible = "bcm5461a"; - reg = <2>; - txc-rxc-delay-disable; + PHY2: ethernet-phy@6400 { + device_type = "ethernet-phy"; + compatible = "bcm54xx"; + reg = <6000 50>; + phy-id = <2>; }; }; ethernet@6200 { device_type = "network"; - compatible = "tsi109-ethernet", "tsi108-ethernet"; + compatible = "tsi-ethernet"; #address-cells = <1>; #size-cells = <0>; reg = <6000 200>; local-mac-address = [ 00 00 00 00 00 00 ]; - interrupt-parent = <&MPIC>; + interrupt-parent = < &/tsi109@c0000000/pic@7400 >; interrupts = <10 2>; - mdio-handle = <&MDIO>; phy-handle = <&PHY1>; }; ethernet@6600 { device_type = "network"; - compatible = "tsi109-ethernet", "tsi108-ethernet"; + compatible = "tsi-ethernet"; #address-cells = <1>; #size-cells = <0>; reg = <6400 200>; local-mac-address = [ 00 00 00 00 00 00 ]; - interrupt-parent = <&MPIC>; + interrupt-parent = < &/tsi109@c0000000/pic@7400 >; interrupts = <11 2>; - mdio-handle = <&MDIO>; phy-handle = <&PHY2>; }; @@ -113,7 +110,7 @@ virtual-reg = ; clock-frequency = <3F9C6000>; current-speed = <1c200>; - interrupt-parent = <&MPIC>; + interrupt-parent = < &/tsi109@c0000000/pic@7400 >; interrupts = ; }; @@ -124,7 +121,7 @@ virtual-reg = ; clock-frequency = <3F9C6000>; current-speed = <1c200>; - interrupt-parent = <&MPIC>; + interrupt-parent = < &/tsi109@c0000000/pic@7400 >; interrupts = ; }; @@ -139,7 +136,7 @@ pci@1000 { device_type = "pci"; - compatible = "tsi109-pci", "tsi108-pci"; + compatible = "tsi109"; #interrupt-cells = <1>; #size-cells = <2>; #address-cells = <3>; @@ -153,7 +150,7 @@ ranges = <02000000 0 40000000 40000000 0 10000000 01000000 0 00000000 7e000000 0 00010000>; clock-frequency = <7f28154>; - interrupt-parent = <&MPIC>; + interrupt-parent = < &/tsi109@c0000000/pic@7400 >; interrupts = <17 2>; interrupt-map-mask = ; /*----------------------------------------------------+ @@ -189,12 +186,13 @@ #address-cells = <0>; #interrupt-cells = <2>; interrupts = <17 2>; - interrupt-parent = <&MPIC>; + interrupt-parent = < &/tsi109@c0000000/pic@7400 >; }; }; }; chosen { linux,stdout-path = "/tsi109@c0000000/serial@7808"; + bootargs = "console=ttyS0,115200"; }; }; diff --git a/trunk/arch/powerpc/boot/dts/mpc7448hpc2.dts b/trunk/arch/powerpc/boot/dts/mpc7448hpc2.dts index 0e3d314a7158..765c306ecf80 100644 --- a/trunk/arch/powerpc/boot/dts/mpc7448hpc2.dts +++ b/trunk/arch/powerpc/boot/dts/mpc7448hpc2.dts @@ -45,7 +45,7 @@ #address-cells = <1>; #size-cells = <1>; #interrupt-cells = <2>; - device_type = "tsi108-bridge"; + device_type = "tsi-bridge"; ranges = <00000000 c0000000 00010000>; reg = ; bus-frequency = <0>; @@ -55,26 +55,27 @@ interrupts = ; reg = <7000 400>; device_type = "i2c"; - compatible = "tsi108-i2c"; + compatible = "tsi-i2c"; }; - MDIO: mdio@6000 { + mdio@6000 { device_type = "mdio"; - compatible = "tsi108-mdio"; - reg = <6000 50>; - #address-cells = <1>; - #size-cells = <0>; + compatible = "tsi-ethernet"; - phy8: ethernet-phy@8 { + phy8: ethernet-phy@6000 { interrupt-parent = <&mpic>; interrupts = <2 1>; - reg = <8>; + reg = <6000 50>; + phy-id = <8>; + device_type = "ethernet-phy"; }; - phy9: ethernet-phy@9 { + phy9: ethernet-phy@6400 { interrupt-parent = <&mpic>; interrupts = <2 1>; - reg = <9>; + reg = <6000 50>; + phy-id = <9>; + device_type = "ethernet-phy"; }; }; @@ -82,12 +83,12 @@ ethernet@6200 { #size-cells = <0>; device_type = "network"; - compatible = "tsi108-ethernet"; + model = "TSI-ETH"; + compatible = "tsi-ethernet"; reg = <6000 200>; address = [ 00 06 D2 00 00 01 ]; interrupts = <10 2>; interrupt-parent = <&mpic>; - mdio-handle = <&MDIO>; phy-handle = <&phy8>; }; @@ -95,12 +96,12 @@ #address-cells = <1>; #size-cells = <0>; device_type = "network"; - compatible = "tsi108-ethernet"; + model = "TSI-ETH"; + compatible = "tsi-ethernet"; reg = <6400 200>; address = [ 00 06 D2 00 00 02 ]; interrupts = <11 2>; interrupt-parent = <&mpic>; - mdio-handle = <&MDIO>; phy-handle = <&phy9>; }; @@ -134,7 +135,7 @@ big-endian; }; pci@1000 { - compatible = "tsi108-pci"; + compatible = "tsi10x"; device_type = "pci"; #interrupt-cells = <1>; #size-cells = <2>; diff --git a/trunk/arch/powerpc/boot/dts/mpc8272ads.dts b/trunk/arch/powerpc/boot/dts/mpc8272ads.dts index 1934b800278e..423eedcf634f 100644 --- a/trunk/arch/powerpc/boot/dts/mpc8272ads.dts +++ b/trunk/arch/powerpc/boot/dts/mpc8272ads.dts @@ -14,10 +14,12 @@ compatible = "MPC8260ADS"; #address-cells = <1>; #size-cells = <1>; + linux,phandle = <100>; cpus { #address-cells = <1>; #size-cells = <0>; + linux,phandle = <200>; PowerPC,8272@0 { device_type = "cpu"; @@ -30,10 +32,12 @@ bus-frequency = <0>; clock-frequency = <0>; 32-bit; + linux,phandle = <201>; }; }; - pci_pic: interrupt-controller@f8200000 { + interrupt-controller@f8200000 { + linux,phandle = ; #address-cells = <0>; #interrupt-cells = <2>; interrupt-controller; @@ -43,13 +47,15 @@ }; memory { device_type = "memory"; + linux,phandle = <300>; reg = <00000000 4000000 f4500000 00000020>; }; chosen { name = "chosen"; linux,platform = <0>; - interrupt-controller = <&Cpm_pic>; + interrupt-controller = <10c00>; + linux,phandle = <400>; }; soc8272@f0000000 { @@ -64,17 +70,20 @@ device_type = "mdio"; compatible = "fs_enet"; reg = <0 0>; + linux,phandle = <24520>; #address-cells = <1>; #size-cells = <0>; - phy0:ethernet-phy@0 { - interrupt-parent = <&Cpm_pic>; + ethernet-phy@0 { + linux,phandle = <2452000>; + interrupt-parent = <10c00>; interrupts = <17 4>; reg = <0>; bitbang = [ 12 12 13 02 02 01 ]; device_type = "ethernet-phy"; }; - phy1:ethernet-phy@1 { - interrupt-parent = <&Cpm_pic>; + ethernet-phy@1 { + linux,phandle = <2452001>; + interrupt-parent = <10c00>; interrupts = <17 4>; bitbang = [ 12 12 13 02 02 01 ]; reg = <3>; @@ -92,8 +101,8 @@ reg = <11300 20 8400 100 11380 30>; mac-address = [ 00 11 2F 99 43 54 ]; interrupts = <20 2>; - interrupt-parent = <&Cpm_pic>; - phy-handle = <&Phy0>; + interrupt-parent = <10c00>; + phy-handle = <2452000>; rx-clock = <13>; tx-clock = <12>; }; @@ -106,13 +115,14 @@ reg = <11320 20 8500 100 113b0 30>; mac-address = [ 00 11 2F 99 44 54 ]; interrupts = <21 2>; - interrupt-parent = <&Cpm_pic>; - phy-handle = <&Phy1>; + interrupt-parent = <10c00>; + phy-handle = <2452001>; rx-clock = <17>; tx-clock = <18>; }; cpm@f0000000 { + linux,phandle = ; #address-cells = <1>; #size-cells = <1>; #interrupt-cells = <2>; @@ -132,7 +142,7 @@ reg = <11a00 20 8000 100>; current-speed = <1c200>; interrupts = <28 2>; - interrupt-parent = <&Cpm_pic>; + interrupt-parent = <10c00>; clock-setup = <0 00ffffff>; rx-clock = <1>; tx-clock = <1>; @@ -146,14 +156,15 @@ reg = <11a60 20 8300 100>; current-speed = <1c200>; interrupts = <2b 2>; - interrupt-parent = <&Cpm_pic>; + interrupt-parent = <10c00>; clock-setup = <1b ffffff00>; rx-clock = <4>; tx-clock = <4>; }; }; - cpm_pic:interrupt-controller@10c00 { + interrupt-controller@10c00 { + linux,phandle = <10c00>; #address-cells = <0>; #interrupt-cells = <2>; interrupt-controller; @@ -163,6 +174,7 @@ compatible = "CPM2"; }; pci@0500 { + linux,phandle = <0500>; #interrupt-cells = <1>; #size-cells = <2>; #address-cells = <3>; @@ -190,7 +202,7 @@ c000 0 0 2 f8200000 43 8 c000 0 0 3 f8200000 40 8 c000 0 0 4 f8200000 41 8>; - interrupt-parent = <&Cpm_pic>; + interrupt-parent = <10c00>; interrupts = <14 8>; bus-range = <0 0>; ranges = <02000000 0 80000000 80000000 0 40000000 @@ -204,7 +216,7 @@ compatible = "talitos"; reg = <30000 10000>; interrupts = ; - interrupt-parent = <&Cpm_pic>; + interrupt-parent = <10c00>; num-channels = <4>; channel-fifo-len = <18>; exec-units-mask = <0000007e>; diff --git a/trunk/arch/powerpc/boot/dts/mpc832x_mds.dts b/trunk/arch/powerpc/boot/dts/mpc832x_mds.dts index 4fc0c4d34aa8..112dd5198fe2 100644 --- a/trunk/arch/powerpc/boot/dts/mpc832x_mds.dts +++ b/trunk/arch/powerpc/boot/dts/mpc832x_mds.dts @@ -272,13 +272,7 @@ reg = <2200 200>; interrupts = <22>; interrupt-parent = < &qeic >; - /* - * mac-address is deprecated and will be removed - * in 2.6.25. Only recent versions of - * U-Boot support local-mac-address, however. - */ - mac-address = [ 00 00 00 00 00 00 ]; - local-mac-address = [ 00 00 00 00 00 00 ]; + mac-address = [ 00 04 9f 00 23 23 ]; rx-clock = <19>; tx-clock = <1a>; phy-handle = < &phy3 >; @@ -293,13 +287,7 @@ reg = <3000 200>; interrupts = <23>; interrupt-parent = < &qeic >; - /* - * mac-address is deprecated and will be removed - * in 2.6.25. Only recent versions of - * U-Boot support local-mac-address, however. - */ - mac-address = [ 00 00 00 00 00 00 ]; - local-mac-address = [ 00 00 00 00 00 00 ]; + mac-address = [ 00 11 22 33 44 55 ]; rx-clock = <17>; tx-clock = <18>; phy-handle = < &phy4 >; diff --git a/trunk/arch/powerpc/boot/dts/mpc832x_rdb.dts b/trunk/arch/powerpc/boot/dts/mpc832x_rdb.dts index 447c03ffabbc..be4c35784e49 100644 --- a/trunk/arch/powerpc/boot/dts/mpc832x_rdb.dts +++ b/trunk/arch/powerpc/boot/dts/mpc832x_rdb.dts @@ -231,13 +231,7 @@ reg = <3000 200>; interrupts = <21>; interrupt-parent = <&qeic>; - /* - * mac-address is deprecated and will be removed - * in 2.6.25. Only recent versions of - * U-Boot support local-mac-address, however. - */ - mac-address = [ 00 00 00 00 00 00 ]; - local-mac-address = [ 00 00 00 00 00 00 ]; + mac-address = [ 00 04 9f ef 03 02 ]; rx-clock = <20>; tx-clock = <13>; phy-handle = <&phy00>; @@ -252,13 +246,7 @@ reg = <2200 200>; interrupts = <22>; interrupt-parent = <&qeic>; - /* - * mac-address is deprecated and will be removed - * in 2.6.25. Only recent versions of - * U-Boot support local-mac-address, however. - */ - mac-address = [ 00 00 00 00 00 00 ]; - local-mac-address = [ 00 00 00 00 00 00 ]; + mac-address = [ 00 04 9f ef 03 01 ]; rx-clock = <19>; tx-clock = <1a>; phy-handle = <&phy04>; diff --git a/trunk/arch/powerpc/boot/dts/mpc8349emitx.dts b/trunk/arch/powerpc/boot/dts/mpc8349emitx.dts index ae9bca575453..db0d00303275 100644 --- a/trunk/arch/powerpc/boot/dts/mpc8349emitx.dts +++ b/trunk/arch/powerpc/boot/dts/mpc8349emitx.dts @@ -131,11 +131,6 @@ model = "TSEC"; compatible = "gianfar"; reg = <24000 1000>; - /* - * address is deprecated and will be removed - * in 2.6.25. Only recent versions of - * U-Boot support local-mac-address, however. - */ address = [ 00 00 00 00 00 00 ]; local-mac-address = [ 00 00 00 00 00 00 ]; interrupts = <20 8 21 8 22 8>; @@ -150,11 +145,6 @@ model = "TSEC"; compatible = "gianfar"; reg = <25000 1000>; - /* - * address is deprecated and will be removed - * in 2.6.25. Only recent versions of - * U-Boot support local-mac-address, however. - */ address = [ 00 00 00 00 00 00 ]; local-mac-address = [ 00 00 00 00 00 00 ]; interrupts = <23 8 24 8 25 8>; diff --git a/trunk/arch/powerpc/boot/dts/mpc834x_mds.dts b/trunk/arch/powerpc/boot/dts/mpc834x_mds.dts index 310e877826b4..df773fafe9d1 100644 --- a/trunk/arch/powerpc/boot/dts/mpc834x_mds.dts +++ b/trunk/arch/powerpc/boot/dts/mpc834x_mds.dts @@ -136,11 +136,6 @@ model = "TSEC"; compatible = "gianfar"; reg = <24000 1000>; - /* - * address is deprecated and will be removed - * in 2.6.25. Only recent versions of - * U-Boot support local-mac-address, however. - */ address = [ 00 00 00 00 00 00 ]; local-mac-address = [ 00 00 00 00 00 00 ]; interrupts = <20 8 21 8 22 8>; @@ -155,11 +150,6 @@ model = "TSEC"; compatible = "gianfar"; reg = <25000 1000>; - /* - * address is deprecated and will be removed - * in 2.6.25. Only recent versions of - * U-Boot support local-mac-address, however. - */ address = [ 00 00 00 00 00 00 ]; local-mac-address = [ 00 00 00 00 00 00 ]; interrupts = <23 8 24 8 25 8>; diff --git a/trunk/arch/powerpc/boot/dts/mpc836x_mds.dts b/trunk/arch/powerpc/boot/dts/mpc836x_mds.dts index 1e914f31dd92..38c8594df3a4 100644 --- a/trunk/arch/powerpc/boot/dts/mpc836x_mds.dts +++ b/trunk/arch/powerpc/boot/dts/mpc836x_mds.dts @@ -301,13 +301,7 @@ reg = <2000 200>; interrupts = <20>; interrupt-parent = < &qeic >; - /* - * mac-address is deprecated and will be removed - * in 2.6.25. Only recent versions of - * U-Boot support local-mac-address, however. - */ - mac-address = [ 00 00 00 00 00 00 ]; - local-mac-address = [ 00 00 00 00 00 00 ]; + mac-address = [ 00 04 9f 00 23 23 ]; rx-clock = <0>; tx-clock = <19>; phy-handle = < &phy0 >; @@ -323,13 +317,7 @@ reg = <3000 200>; interrupts = <21>; interrupt-parent = < &qeic >; - /* - * mac-address is deprecated and will be removed - * in 2.6.25. Only recent versions of - * U-Boot support local-mac-address, however. - */ - mac-address = [ 00 00 00 00 00 00 ]; - local-mac-address = [ 00 00 00 00 00 00 ]; + mac-address = [ 00 11 22 33 44 55 ]; rx-clock = <0>; tx-clock = <14>; phy-handle = < &phy1 >; diff --git a/trunk/arch/powerpc/boot/dts/mpc8540ads.dts b/trunk/arch/powerpc/boot/dts/mpc8540ads.dts index 364a969f5c2f..d91e81c009f5 100644 --- a/trunk/arch/powerpc/boot/dts/mpc8540ads.dts +++ b/trunk/arch/powerpc/boot/dts/mpc8540ads.dts @@ -52,7 +52,7 @@ compatible = "fsl,8540-memory-controller"; reg = <2000 1000>; interrupt-parent = <&mpic>; - interrupts = <12 2>; + interrupts = <2 2>; }; l2-cache-controller@20000 { @@ -61,14 +61,14 @@ cache-line-size = <20>; // 32 bytes cache-size = <40000>; // L2, 256K interrupt-parent = <&mpic>; - interrupts = <10 2>; + interrupts = <0 2>; }; i2c@3000 { device_type = "i2c"; compatible = "fsl-i2c"; reg = <3000 100>; - interrupts = <2b 2>; + interrupts = <1b 2>; interrupt-parent = <&mpic>; dfsrr; }; @@ -81,19 +81,19 @@ reg = <24520 20>; phy0: ethernet-phy@0 { interrupt-parent = <&mpic>; - interrupts = <5 1>; + interrupts = <35 1>; reg = <0>; device_type = "ethernet-phy"; }; phy1: ethernet-phy@1 { interrupt-parent = <&mpic>; - interrupts = <5 1>; + interrupts = <35 1>; reg = <1>; device_type = "ethernet-phy"; }; phy3: ethernet-phy@3 { interrupt-parent = <&mpic>; - interrupts = <7 1>; + interrupts = <37 1>; reg = <3>; device_type = "ethernet-phy"; }; @@ -106,14 +106,9 @@ model = "TSEC"; compatible = "gianfar"; reg = <24000 1000>; - /* - * address is deprecated and will be removed - * in 2.6.25. Only recent versions of - * U-Boot support local-mac-address, however. - */ - address = [ 00 00 00 00 00 00 ]; - local-mac-address = [ 00 00 00 00 00 00 ]; - interrupts = <1d 2 1e 2 22 2>; + address = [ 00 E0 0C 00 73 00 ]; + local-mac-address = [ 00 E0 0C 00 73 00 ]; + interrupts = ; interrupt-parent = <&mpic>; phy-handle = <&phy0>; }; @@ -125,14 +120,9 @@ model = "TSEC"; compatible = "gianfar"; reg = <25000 1000>; - /* - * address is deprecated and will be removed - * in 2.6.25. Only recent versions of - * U-Boot support local-mac-address, however. - */ - address = [ 00 00 00 00 00 00 ]; - local-mac-address = [ 00 00 00 00 00 00 ]; - interrupts = <23 2 24 2 28 2>; + address = [ 00 E0 0C 00 73 01 ]; + local-mac-address = [ 00 E0 0C 00 73 01 ]; + interrupts = <13 2 14 2 18 2>; interrupt-parent = <&mpic>; phy-handle = <&phy1>; }; @@ -144,14 +134,9 @@ model = "FEC"; compatible = "gianfar"; reg = <26000 1000>; - /* - * address is deprecated and will be removed - * in 2.6.25. Only recent versions of - * U-Boot support local-mac-address, however. - */ - address = [ 00 00 00 00 00 00 ]; - local-mac-address = [ 00 00 00 00 00 00 ]; - interrupts = <29 2>; + address = [ 00 E0 0C 00 73 02 ]; + local-mac-address = [ 00 E0 0C 00 73 02 ]; + interrupts = <19 2>; interrupt-parent = <&mpic>; phy-handle = <&phy3>; }; @@ -161,7 +146,7 @@ compatible = "ns16550"; reg = <4500 100>; // reg base, size clock-frequency = <0>; // should we fill in in uboot? - interrupts = <2a 2>; + interrupts = <1a 2>; interrupt-parent = <&mpic>; }; @@ -170,7 +155,7 @@ compatible = "ns16550"; reg = <4600 100>; // reg base, size clock-frequency = <0>; // should we fill in in uboot? - interrupts = <2a 2>; + interrupts = <1a 2>; interrupt-parent = <&mpic>; }; pci@8000 { @@ -178,78 +163,78 @@ interrupt-map = < /* IDSEL 0x02 */ - 1000 0 0 1 &mpic 1 1 - 1000 0 0 2 &mpic 2 1 - 1000 0 0 3 &mpic 3 1 - 1000 0 0 4 &mpic 4 1 + 1000 0 0 1 &mpic 31 1 + 1000 0 0 2 &mpic 32 1 + 1000 0 0 3 &mpic 33 1 + 1000 0 0 4 &mpic 34 1 /* IDSEL 0x03 */ - 1800 0 0 1 &mpic 4 1 - 1800 0 0 2 &mpic 1 1 - 1800 0 0 3 &mpic 2 1 - 1800 0 0 4 &mpic 3 1 + 1800 0 0 1 &mpic 34 1 + 1800 0 0 2 &mpic 31 1 + 1800 0 0 3 &mpic 32 1 + 1800 0 0 4 &mpic 33 1 /* IDSEL 0x04 */ - 2000 0 0 1 &mpic 3 1 - 2000 0 0 2 &mpic 4 1 - 2000 0 0 3 &mpic 1 1 - 2000 0 0 4 &mpic 2 1 + 2000 0 0 1 &mpic 33 1 + 2000 0 0 2 &mpic 34 1 + 2000 0 0 3 &mpic 31 1 + 2000 0 0 4 &mpic 32 1 /* IDSEL 0x05 */ - 2800 0 0 1 &mpic 2 1 - 2800 0 0 2 &mpic 3 1 - 2800 0 0 3 &mpic 4 1 - 2800 0 0 4 &mpic 1 1 + 2800 0 0 1 &mpic 32 1 + 2800 0 0 2 &mpic 33 1 + 2800 0 0 3 &mpic 34 1 + 2800 0 0 4 &mpic 31 1 /* IDSEL 0x0c */ - 6000 0 0 1 &mpic 1 1 - 6000 0 0 2 &mpic 2 1 - 6000 0 0 3 &mpic 3 1 - 6000 0 0 4 &mpic 4 1 + 6000 0 0 1 &mpic 31 1 + 6000 0 0 2 &mpic 32 1 + 6000 0 0 3 &mpic 33 1 + 6000 0 0 4 &mpic 34 1 /* IDSEL 0x0d */ - 6800 0 0 1 &mpic 4 1 - 6800 0 0 2 &mpic 1 1 - 6800 0 0 3 &mpic 2 1 - 6800 0 0 4 &mpic 3 1 + 6800 0 0 1 &mpic 34 1 + 6800 0 0 2 &mpic 31 1 + 6800 0 0 3 &mpic 32 1 + 6800 0 0 4 &mpic 33 1 /* IDSEL 0x0e */ - 7000 0 0 1 &mpic 3 1 - 7000 0 0 2 &mpic 4 1 - 7000 0 0 3 &mpic 1 1 - 7000 0 0 4 &mpic 2 1 + 7000 0 0 1 &mpic 33 1 + 7000 0 0 2 &mpic 34 1 + 7000 0 0 3 &mpic 31 1 + 7000 0 0 4 &mpic 32 1 /* IDSEL 0x0f */ - 7800 0 0 1 &mpic 2 1 - 7800 0 0 2 &mpic 3 1 - 7800 0 0 3 &mpic 4 1 - 7800 0 0 4 &mpic 1 1 + 7800 0 0 1 &mpic 32 1 + 7800 0 0 2 &mpic 33 1 + 7800 0 0 3 &mpic 34 1 + 7800 0 0 4 &mpic 31 1 /* IDSEL 0x12 */ - 9000 0 0 1 &mpic 1 1 - 9000 0 0 2 &mpic 2 1 - 9000 0 0 3 &mpic 3 1 - 9000 0 0 4 &mpic 4 1 + 9000 0 0 1 &mpic 31 1 + 9000 0 0 2 &mpic 32 1 + 9000 0 0 3 &mpic 33 1 + 9000 0 0 4 &mpic 34 1 /* IDSEL 0x13 */ - 9800 0 0 1 &mpic 4 1 - 9800 0 0 2 &mpic 1 1 - 9800 0 0 3 &mpic 2 1 - 9800 0 0 4 &mpic 3 1 + 9800 0 0 1 &mpic 34 1 + 9800 0 0 2 &mpic 31 1 + 9800 0 0 3 &mpic 32 1 + 9800 0 0 4 &mpic 33 1 /* IDSEL 0x14 */ - a000 0 0 1 &mpic 3 1 - a000 0 0 2 &mpic 4 1 - a000 0 0 3 &mpic 1 1 - a000 0 0 4 &mpic 2 1 + a000 0 0 1 &mpic 33 1 + a000 0 0 2 &mpic 34 1 + a000 0 0 3 &mpic 31 1 + a000 0 0 4 &mpic 32 1 /* IDSEL 0x15 */ - a800 0 0 1 &mpic 2 1 - a800 0 0 2 &mpic 3 1 - a800 0 0 3 &mpic 4 1 - a800 0 0 4 &mpic 1 1>; + a800 0 0 1 &mpic 32 1 + a800 0 0 2 &mpic 33 1 + a800 0 0 3 &mpic 34 1 + a800 0 0 4 &mpic 31 1>; interrupt-parent = <&mpic>; - interrupts = <18 2>; + interrupts = <08 2>; bus-range = <0 0>; ranges = <02000000 0 80000000 80000000 0 20000000 01000000 0 00000000 e2000000 0 00100000>; diff --git a/trunk/arch/powerpc/boot/dts/mpc8541cds.dts b/trunk/arch/powerpc/boot/dts/mpc8541cds.dts index 070206fffe88..4f2c3af2e052 100644 --- a/trunk/arch/powerpc/boot/dts/mpc8541cds.dts +++ b/trunk/arch/powerpc/boot/dts/mpc8541cds.dts @@ -52,7 +52,7 @@ compatible = "fsl,8541-memory-controller"; reg = <2000 1000>; interrupt-parent = <&mpic>; - interrupts = <12 2>; + interrupts = <2 2>; }; l2-cache-controller@20000 { @@ -61,14 +61,14 @@ cache-line-size = <20>; // 32 bytes cache-size = <40000>; // L2, 256K interrupt-parent = <&mpic>; - interrupts = <10 2>; + interrupts = <0 2>; }; i2c@3000 { device_type = "i2c"; compatible = "fsl-i2c"; reg = <3000 100>; - interrupts = <2b 2>; + interrupts = <1b 2>; interrupt-parent = <&mpic>; dfsrr; }; @@ -81,13 +81,13 @@ reg = <24520 20>; phy0: ethernet-phy@0 { interrupt-parent = <&mpic>; - interrupts = <5 1>; + interrupts = <35 0>; reg = <0>; device_type = "ethernet-phy"; }; phy1: ethernet-phy@1 { interrupt-parent = <&mpic>; - interrupts = <5 1>; + interrupts = <35 0>; reg = <1>; device_type = "ethernet-phy"; }; @@ -100,8 +100,8 @@ model = "TSEC"; compatible = "gianfar"; reg = <24000 1000>; - local-mac-address = [ 00 00 00 00 00 00 ]; - interrupts = <1d 2 1e 2 22 2>; + local-mac-address = [ 00 E0 0C 00 73 00 ]; + interrupts = ; interrupt-parent = <&mpic>; phy-handle = <&phy0>; }; @@ -113,8 +113,8 @@ model = "TSEC"; compatible = "gianfar"; reg = <25000 1000>; - local-mac-address = [ 00 00 00 00 00 00 ]; - interrupts = <23 2 24 2 28 2>; + local-mac-address = [ 00 E0 0C 00 73 01 ]; + interrupts = <13 2 14 2 18 2>; interrupt-parent = <&mpic>; phy-handle = <&phy1>; }; @@ -124,7 +124,7 @@ compatible = "ns16550"; reg = <4500 100>; // reg base, size clock-frequency = <0>; // should we fill in in uboot? - interrupts = <2a 2>; + interrupts = <1a 2>; interrupt-parent = <&mpic>; }; @@ -133,7 +133,7 @@ compatible = "ns16550"; reg = <4600 100>; // reg base, size clock-frequency = <0>; // should we fill in in uboot? - interrupts = <2a 2>; + interrupts = <1a 2>; interrupt-parent = <&mpic>; }; @@ -142,49 +142,49 @@ interrupt-map = < /* IDSEL 0x10 */ - 08000 0 0 1 &mpic 0 1 - 08000 0 0 2 &mpic 1 1 - 08000 0 0 3 &mpic 2 1 - 08000 0 0 4 &mpic 3 1 + 08000 0 0 1 &mpic 30 1 + 08000 0 0 2 &mpic 31 1 + 08000 0 0 3 &mpic 32 1 + 08000 0 0 4 &mpic 33 1 /* IDSEL 0x11 */ - 08800 0 0 1 &mpic 0 1 - 08800 0 0 2 &mpic 1 1 - 08800 0 0 3 &mpic 2 1 - 08800 0 0 4 &mpic 3 1 + 08800 0 0 1 &mpic 30 1 + 08800 0 0 2 &mpic 31 1 + 08800 0 0 3 &mpic 32 1 + 08800 0 0 4 &mpic 33 1 /* IDSEL 0x12 (Slot 1) */ - 09000 0 0 1 &mpic 0 1 - 09000 0 0 2 &mpic 1 1 - 09000 0 0 3 &mpic 2 1 - 09000 0 0 4 &mpic 3 1 + 09000 0 0 1 &mpic 30 1 + 09000 0 0 2 &mpic 31 1 + 09000 0 0 3 &mpic 32 1 + 09000 0 0 4 &mpic 33 1 /* IDSEL 0x13 (Slot 2) */ - 09800 0 0 1 &mpic 1 1 - 09800 0 0 2 &mpic 2 1 - 09800 0 0 3 &mpic 3 1 - 09800 0 0 4 &mpic 0 1 + 09800 0 0 1 &mpic 31 1 + 09800 0 0 2 &mpic 32 1 + 09800 0 0 3 &mpic 33 1 + 09800 0 0 4 &mpic 30 1 /* IDSEL 0x14 (Slot 3) */ - 0a000 0 0 1 &mpic 2 1 - 0a000 0 0 2 &mpic 3 1 - 0a000 0 0 3 &mpic 0 1 - 0a000 0 0 4 &mpic 1 1 + 0a000 0 0 1 &mpic 32 1 + 0a000 0 0 2 &mpic 33 1 + 0a000 0 0 3 &mpic 30 1 + 0a000 0 0 4 &mpic 31 1 /* IDSEL 0x15 (Slot 4) */ - 0a800 0 0 1 &mpic 3 1 - 0a800 0 0 2 &mpic 0 1 - 0a800 0 0 3 &mpic 1 1 - 0a800 0 0 4 &mpic 2 1 + 0a800 0 0 1 &mpic 33 1 + 0a800 0 0 2 &mpic 30 1 + 0a800 0 0 3 &mpic 31 1 + 0a800 0 0 4 &mpic 32 1 /* Bus 1 (Tundra Bridge) */ /* IDSEL 0x12 (ISA bridge) */ - 19000 0 0 1 &mpic 0 1 - 19000 0 0 2 &mpic 1 1 - 19000 0 0 3 &mpic 2 1 - 19000 0 0 4 &mpic 3 1>; + 19000 0 0 1 &mpic 30 1 + 19000 0 0 2 &mpic 31 1 + 19000 0 0 3 &mpic 32 1 + 19000 0 0 4 &mpic 33 1>; interrupt-parent = <&mpic>; - interrupts = <18 2>; + interrupts = <08 2>; bus-range = <0 0>; ranges = <02000000 0 80000000 80000000 0 20000000 01000000 0 00000000 e2000000 0 00100000>; @@ -216,12 +216,12 @@ interrupt-map = < /* IDSEL 0x15 */ - a800 0 0 1 &mpic b 1 - a800 0 0 2 &mpic b 1 - a800 0 0 3 &mpic b 1 - a800 0 0 4 &mpic b 1>; + a800 0 0 1 &mpic 3b 1 + a800 0 0 2 &mpic 3b 1 + a800 0 0 3 &mpic 3b 1 + a800 0 0 4 &mpic 3b 1>; interrupt-parent = <&mpic>; - interrupts = <19 2>; + interrupts = <09 2>; bus-range = <0 0>; ranges = <02000000 0 a0000000 a0000000 0 20000000 01000000 0 00000000 e3000000 0 00100000>; diff --git a/trunk/arch/powerpc/boot/dts/mpc8544ds.dts b/trunk/arch/powerpc/boot/dts/mpc8544ds.dts index 828592592460..3033599e74e8 100644 --- a/trunk/arch/powerpc/boot/dts/mpc8544ds.dts +++ b/trunk/arch/powerpc/boot/dts/mpc8544ds.dts @@ -52,7 +52,7 @@ compatible = "fsl,8544-memory-controller"; reg = <2000 1000>; interrupt-parent = <&mpic>; - interrupts = <12 2>; + interrupts = <2 2>; }; l2-cache-controller@20000 { @@ -61,14 +61,14 @@ cache-line-size = <20>; // 32 bytes cache-size = <40000>; // L2, 256K interrupt-parent = <&mpic>; - interrupts = <10 2>; + interrupts = <0 2>; }; i2c@3000 { device_type = "i2c"; compatible = "fsl-i2c"; reg = <3000 100>; - interrupts = <2b 2>; + interrupts = <1b 2>; interrupt-parent = <&mpic>; dfsrr; }; @@ -81,13 +81,13 @@ reg = <24520 20>; phy0: ethernet-phy@0 { interrupt-parent = <&mpic>; - interrupts = ; + interrupts = <3a 1>; reg = <0>; device_type = "ethernet-phy"; }; phy1: ethernet-phy@1 { interrupt-parent = <&mpic>; - interrupts = ; + interrupts = <3a 1>; reg = <1>; device_type = "ethernet-phy"; }; @@ -101,7 +101,7 @@ compatible = "gianfar"; reg = <24000 1000>; local-mac-address = [ 00 00 00 00 00 00 ]; - interrupts = <1d 2 1e 2 22 2>; + interrupts = ; interrupt-parent = <&mpic>; phy-handle = <&phy0>; }; @@ -114,7 +114,7 @@ compatible = "gianfar"; reg = <26000 1000>; local-mac-address = [ 00 00 00 00 00 00 ]; - interrupts = <1f 2 20 2 21 2>; + interrupts = ; interrupt-parent = <&mpic>; phy-handle = <&phy1>; }; @@ -124,7 +124,7 @@ compatible = "ns16550"; reg = <4500 100>; clock-frequency = <0>; - interrupts = <2a 2>; + interrupts = <1a 2>; interrupt-parent = <&mpic>; }; @@ -133,7 +133,7 @@ compatible = "ns16550"; reg = <4600 100>; clock-frequency = <0>; - interrupts = <2a 2>; + interrupts = <1a 2>; interrupt-parent = <&mpic>; }; diff --git a/trunk/arch/powerpc/boot/dts/mpc8548cds.dts b/trunk/arch/powerpc/boot/dts/mpc8548cds.dts index 9d0b84b66cd4..ad96381033c0 100644 --- a/trunk/arch/powerpc/boot/dts/mpc8548cds.dts +++ b/trunk/arch/powerpc/boot/dts/mpc8548cds.dts @@ -52,7 +52,7 @@ compatible = "fsl,8548-memory-controller"; reg = <2000 1000>; interrupt-parent = <&mpic>; - interrupts = <12 2>; + interrupts = <2 2>; }; l2-cache-controller@20000 { @@ -61,14 +61,14 @@ cache-line-size = <20>; // 32 bytes cache-size = <80000>; // L2, 512K interrupt-parent = <&mpic>; - interrupts = <10 2>; + interrupts = <0 2>; }; i2c@3000 { device_type = "i2c"; compatible = "fsl-i2c"; reg = <3000 100>; - interrupts = <2b 2>; + interrupts = <1b 2>; interrupt-parent = <&mpic>; dfsrr; }; @@ -81,25 +81,25 @@ reg = <24520 20>; phy0: ethernet-phy@0 { interrupt-parent = <&mpic>; - interrupts = <5 1>; + interrupts = <35 0>; reg = <0>; device_type = "ethernet-phy"; }; phy1: ethernet-phy@1 { interrupt-parent = <&mpic>; - interrupts = <5 1>; + interrupts = <35 0>; reg = <1>; device_type = "ethernet-phy"; }; phy2: ethernet-phy@2 { interrupt-parent = <&mpic>; - interrupts = <5 1>; + interrupts = <35 0>; reg = <2>; device_type = "ethernet-phy"; }; phy3: ethernet-phy@3 { interrupt-parent = <&mpic>; - interrupts = <5 1>; + interrupts = <35 0>; reg = <3>; device_type = "ethernet-phy"; }; @@ -112,8 +112,8 @@ model = "eTSEC"; compatible = "gianfar"; reg = <24000 1000>; - local-mac-address = [ 00 00 00 00 00 00 ]; - interrupts = <1d 2 1e 2 22 2>; + local-mac-address = [ 00 E0 0C 00 73 00 ]; + interrupts = ; interrupt-parent = <&mpic>; phy-handle = <&phy0>; }; @@ -125,8 +125,8 @@ model = "eTSEC"; compatible = "gianfar"; reg = <25000 1000>; - local-mac-address = [ 00 00 00 00 00 00 ]; - interrupts = <23 2 24 2 28 2>; + local-mac-address = [ 00 E0 0C 00 73 01 ]; + interrupts = <13 2 14 2 18 2>; interrupt-parent = <&mpic>; phy-handle = <&phy1>; }; @@ -139,8 +139,8 @@ model = "eTSEC"; compatible = "gianfar"; reg = <26000 1000>; - local-mac-address = [ 00 00 00 00 00 00 ]; - interrupts = <1f 2 20 2 21 2>; + local-mac-address = [ 00 E0 0C 00 73 02 ]; + interrupts = ; interrupt-parent = <&mpic>; phy-handle = <&phy2>; }; @@ -152,8 +152,8 @@ model = "eTSEC"; compatible = "gianfar"; reg = <27000 1000>; - local-mac-address = [ 00 00 00 00 00 00 ]; - interrupts = <25 2 26 2 27 2>; + local-mac-address = [ 00 E0 0C 00 73 03 ]; + interrupts = <15 2 16 2 17 2>; interrupt-parent = <&mpic>; phy-handle = <&phy3>; }; @@ -164,7 +164,7 @@ compatible = "ns16550"; reg = <4500 100>; // reg base, size clock-frequency = <0>; // should we fill in in uboot? - interrupts = <2a 2>; + interrupts = <1a 2>; interrupt-parent = <&mpic>; }; @@ -173,64 +173,58 @@ compatible = "ns16550"; reg = <4600 100>; // reg base, size clock-frequency = <0>; // should we fill in in uboot? - interrupts = <2a 2>; + interrupts = <1a 2>; interrupt-parent = <&mpic>; }; - global-utilities@e0000 { //global utilities reg - compatible = "fsl,mpc8548-guts"; - reg = ; - fsl,has-rstcr; - }; - pci1: pci@8000 { interrupt-map-mask = <1f800 0 0 7>; interrupt-map = < /* IDSEL 0x10 */ - 08000 0 0 1 &mpic 0 1 - 08000 0 0 2 &mpic 1 1 - 08000 0 0 3 &mpic 2 1 - 08000 0 0 4 &mpic 3 1 + 08000 0 0 1 &mpic 30 1 + 08000 0 0 2 &mpic 31 1 + 08000 0 0 3 &mpic 32 1 + 08000 0 0 4 &mpic 33 1 /* IDSEL 0x11 */ - 08800 0 0 1 &mpic 0 1 - 08800 0 0 2 &mpic 1 1 - 08800 0 0 3 &mpic 2 1 - 08800 0 0 4 &mpic 3 1 + 08800 0 0 1 &mpic 30 1 + 08800 0 0 2 &mpic 31 1 + 08800 0 0 3 &mpic 32 1 + 08800 0 0 4 &mpic 33 1 /* IDSEL 0x12 (Slot 1) */ - 09000 0 0 1 &mpic 0 1 - 09000 0 0 2 &mpic 1 1 - 09000 0 0 3 &mpic 2 1 - 09000 0 0 4 &mpic 3 1 + 09000 0 0 1 &mpic 30 1 + 09000 0 0 2 &mpic 31 1 + 09000 0 0 3 &mpic 32 1 + 09000 0 0 4 &mpic 33 1 /* IDSEL 0x13 (Slot 2) */ - 09800 0 0 1 &mpic 1 1 - 09800 0 0 2 &mpic 2 1 - 09800 0 0 3 &mpic 3 1 - 09800 0 0 4 &mpic 0 1 + 09800 0 0 1 &mpic 31 1 + 09800 0 0 2 &mpic 32 1 + 09800 0 0 3 &mpic 33 1 + 09800 0 0 4 &mpic 30 1 /* IDSEL 0x14 (Slot 3) */ - 0a000 0 0 1 &mpic 2 1 - 0a000 0 0 2 &mpic 3 1 - 0a000 0 0 3 &mpic 0 1 - 0a000 0 0 4 &mpic 1 1 + 0a000 0 0 1 &mpic 32 1 + 0a000 0 0 2 &mpic 33 1 + 0a000 0 0 3 &mpic 30 1 + 0a000 0 0 4 &mpic 31 1 /* IDSEL 0x15 (Slot 4) */ - 0a800 0 0 1 &mpic 3 1 - 0a800 0 0 2 &mpic 0 1 - 0a800 0 0 3 &mpic 1 1 - 0a800 0 0 4 &mpic 2 1 + 0a800 0 0 1 &mpic 33 1 + 0a800 0 0 2 &mpic 30 1 + 0a800 0 0 3 &mpic 31 1 + 0a800 0 0 4 &mpic 32 1 /* Bus 1 (Tundra Bridge) */ /* IDSEL 0x12 (ISA bridge) */ - 19000 0 0 1 &mpic 0 1 - 19000 0 0 2 &mpic 1 1 - 19000 0 0 3 &mpic 2 1 - 19000 0 0 4 &mpic 3 1>; + 19000 0 0 1 &mpic 30 1 + 19000 0 0 2 &mpic 31 1 + 19000 0 0 3 &mpic 32 1 + 19000 0 0 4 &mpic 33 1>; interrupt-parent = <&mpic>; - interrupts = <18 2>; + interrupts = <08 2>; bus-range = <0 0>; ranges = <02000000 0 80000000 80000000 0 20000000 01000000 0 00000000 e2000000 0 00100000>; @@ -262,12 +256,12 @@ interrupt-map = < /* IDSEL 0x15 */ - a800 0 0 1 &mpic b 1 - a800 0 0 2 &mpic b 1 - a800 0 0 3 &mpic b 1 - a800 0 0 4 &mpic b 1>; + a800 0 0 1 &mpic 3b 1 + a800 0 0 2 &mpic 3b 1 + a800 0 0 3 &mpic 3b 1 + a800 0 0 4 &mpic 3b 1>; interrupt-parent = <&mpic>; - interrupts = <19 2>; + interrupts = <09 2>; bus-range = <0 0>; ranges = <02000000 0 a0000000 a0000000 0 20000000 01000000 0 00000000 e3000000 0 00100000>; diff --git a/trunk/arch/powerpc/boot/dts/mpc8555cds.dts b/trunk/arch/powerpc/boot/dts/mpc8555cds.dts index 17e45d9a382a..951ed92f1154 100644 --- a/trunk/arch/powerpc/boot/dts/mpc8555cds.dts +++ b/trunk/arch/powerpc/boot/dts/mpc8555cds.dts @@ -52,7 +52,7 @@ compatible = "fsl,8555-memory-controller"; reg = <2000 1000>; interrupt-parent = <&mpic>; - interrupts = <12 2>; + interrupts = <2 2>; }; l2-cache-controller@20000 { @@ -61,14 +61,14 @@ cache-line-size = <20>; // 32 bytes cache-size = <40000>; // L2, 256K interrupt-parent = <&mpic>; - interrupts = <10 2>; + interrupts = <0 2>; }; i2c@3000 { device_type = "i2c"; compatible = "fsl-i2c"; reg = <3000 100>; - interrupts = <2b 2>; + interrupts = <1b 2>; interrupt-parent = <&mpic>; dfsrr; }; @@ -81,13 +81,13 @@ reg = <24520 20>; phy0: ethernet-phy@0 { interrupt-parent = <&mpic>; - interrupts = <5 1>; + interrupts = <35 0>; reg = <0>; device_type = "ethernet-phy"; }; phy1: ethernet-phy@1 { interrupt-parent = <&mpic>; - interrupts = <5 1>; + interrupts = <35 0>; reg = <1>; device_type = "ethernet-phy"; }; @@ -100,8 +100,8 @@ model = "TSEC"; compatible = "gianfar"; reg = <24000 1000>; - local-mac-address = [ 00 00 00 00 00 00 ]; - interrupts = <1d 2 1e 2 22 2>; + local-mac-address = [ 00 E0 0C 00 73 00 ]; + interrupts = <0d 2 0e 2 12 2>; interrupt-parent = <&mpic>; phy-handle = <&phy0>; }; @@ -113,8 +113,8 @@ model = "TSEC"; compatible = "gianfar"; reg = <25000 1000>; - local-mac-address = [ 00 00 00 00 00 00 ]; - interrupts = <23 2 24 2 28 2>; + local-mac-address = [ 00 E0 0C 00 73 01 ]; + interrupts = <13 2 14 2 18 2>; interrupt-parent = <&mpic>; phy-handle = <&phy1>; }; @@ -124,7 +124,7 @@ compatible = "ns16550"; reg = <4500 100>; // reg base, size clock-frequency = <0>; // should we fill in in uboot? - interrupts = <2a 2>; + interrupts = <1a 2>; interrupt-parent = <&mpic>; }; @@ -133,7 +133,7 @@ compatible = "ns16550"; reg = <4600 100>; // reg base, size clock-frequency = <0>; // should we fill in in uboot? - interrupts = <2a 2>; + interrupts = <1a 2>; interrupt-parent = <&mpic>; }; @@ -142,49 +142,49 @@ interrupt-map = < /* IDSEL 0x10 */ - 08000 0 0 1 &mpic 0 1 - 08000 0 0 2 &mpic 1 1 - 08000 0 0 3 &mpic 2 1 - 08000 0 0 4 &mpic 3 1 + 08000 0 0 1 &mpic 30 1 + 08000 0 0 2 &mpic 31 1 + 08000 0 0 3 &mpic 32 1 + 08000 0 0 4 &mpic 33 1 /* IDSEL 0x11 */ - 08800 0 0 1 &mpic 0 1 - 08800 0 0 2 &mpic 1 1 - 08800 0 0 3 &mpic 2 1 - 08800 0 0 4 &mpic 3 1 + 08800 0 0 1 &mpic 30 1 + 08800 0 0 2 &mpic 31 1 + 08800 0 0 3 &mpic 32 1 + 08800 0 0 4 &mpic 33 1 /* IDSEL 0x12 (Slot 1) */ - 09000 0 0 1 &mpic 0 1 - 09000 0 0 2 &mpic 1 1 - 09000 0 0 3 &mpic 2 1 - 09000 0 0 4 &mpic 3 1 + 09000 0 0 1 &mpic 30 1 + 09000 0 0 2 &mpic 31 1 + 09000 0 0 3 &mpic 32 1 + 09000 0 0 4 &mpic 33 1 /* IDSEL 0x13 (Slot 2) */ - 09800 0 0 1 &mpic 1 1 - 09800 0 0 2 &mpic 2 1 - 09800 0 0 3 &mpic 3 1 - 09800 0 0 4 &mpic 0 1 + 09800 0 0 1 &mpic 31 1 + 09800 0 0 2 &mpic 32 1 + 09800 0 0 3 &mpic 33 1 + 09800 0 0 4 &mpic 30 1 /* IDSEL 0x14 (Slot 3) */ - 0a000 0 0 1 &mpic 2 1 - 0a000 0 0 2 &mpic 3 1 - 0a000 0 0 3 &mpic 0 1 - 0a000 0 0 4 &mpic 1 1 + 0a000 0 0 1 &mpic 32 1 + 0a000 0 0 2 &mpic 33 1 + 0a000 0 0 3 &mpic 30 1 + 0a000 0 0 4 &mpic 31 1 /* IDSEL 0x15 (Slot 4) */ - 0a800 0 0 1 &mpic 3 1 - 0a800 0 0 2 &mpic 0 1 - 0a800 0 0 3 &mpic 1 1 - 0a800 0 0 4 &mpic 2 1 + 0a800 0 0 1 &mpic 33 1 + 0a800 0 0 2 &mpic 30 1 + 0a800 0 0 3 &mpic 31 1 + 0a800 0 0 4 &mpic 32 1 /* Bus 1 (Tundra Bridge) */ /* IDSEL 0x12 (ISA bridge) */ - 19000 0 0 1 &mpic 0 1 - 19000 0 0 2 &mpic 1 1 - 19000 0 0 3 &mpic 2 1 - 19000 0 0 4 &mpic 3 1>; + 19000 0 0 1 &mpic 30 1 + 19000 0 0 2 &mpic 31 1 + 19000 0 0 3 &mpic 32 1 + 19000 0 0 4 &mpic 33 1>; interrupt-parent = <&mpic>; - interrupts = <18 2>; + interrupts = <08 2>; bus-range = <0 0>; ranges = <02000000 0 80000000 80000000 0 20000000 01000000 0 00000000 e2000000 0 00100000>; @@ -216,12 +216,12 @@ interrupt-map = < /* IDSEL 0x15 */ - a800 0 0 1 &mpic b 1 - a800 0 0 2 &mpic b 1 - a800 0 0 3 &mpic b 1 - a800 0 0 4 &mpic b 1>; + a800 0 0 1 &mpic 3b 1 + a800 0 0 2 &mpic 3b 1 + a800 0 0 3 &mpic 3b 1 + a800 0 0 4 &mpic 3b 1>; interrupt-parent = <&mpic>; - interrupts = <19 2>; + interrupts = <09 2>; bus-range = <0 0>; ranges = <02000000 0 a0000000 a0000000 0 20000000 01000000 0 00000000 e3000000 0 00100000>; diff --git a/trunk/arch/powerpc/boot/dts/mpc8560ads.dts b/trunk/arch/powerpc/boot/dts/mpc8560ads.dts index 21ccaaa27993..80682152b0cf 100644 --- a/trunk/arch/powerpc/boot/dts/mpc8560ads.dts +++ b/trunk/arch/powerpc/boot/dts/mpc8560ads.dts @@ -52,7 +52,7 @@ compatible = "fsl,8540-memory-controller"; reg = <2000 1000>; interrupt-parent = <&mpic>; - interrupts = <12 2>; + interrupts = <2 2>; }; l2-cache-controller@20000 { @@ -61,7 +61,7 @@ cache-line-size = <20>; // 32 bytes cache-size = <40000>; // L2, 256K interrupt-parent = <&mpic>; - interrupts = <10 2>; + interrupts = <0 2>; }; mdio@24520 { @@ -72,25 +72,25 @@ #size-cells = <0>; phy0: ethernet-phy@0 { interrupt-parent = <&mpic>; - interrupts = <5 1>; + interrupts = <35 1>; reg = <0>; device_type = "ethernet-phy"; }; phy1: ethernet-phy@1 { interrupt-parent = <&mpic>; - interrupts = <5 1>; + interrupts = <35 1>; reg = <1>; device_type = "ethernet-phy"; }; phy2: ethernet-phy@2 { interrupt-parent = <&mpic>; - interrupts = <7 1>; + interrupts = <37 1>; reg = <2>; device_type = "ethernet-phy"; }; phy3: ethernet-phy@3 { interrupt-parent = <&mpic>; - interrupts = <7 1>; + interrupts = <37 1>; reg = <3>; device_type = "ethernet-phy"; }; @@ -101,14 +101,8 @@ model = "TSEC"; compatible = "gianfar"; reg = <24000 1000>; - /* - * address is deprecated and will be removed - * in 2.6.25. Only recent versions of - * U-Boot support local-mac-address, however. - */ - address = [ 00 00 00 00 00 00 ]; - local-mac-address = [ 00 00 00 00 00 00 ]; - interrupts = <1d 2 1e 2 22 2>; + address = [ 00 00 0C 00 00 FD ]; + interrupts = ; interrupt-parent = <&mpic>; phy-handle = <&phy0>; }; @@ -120,14 +114,8 @@ model = "TSEC"; compatible = "gianfar"; reg = <25000 1000>; - /* - * address is deprecated and will be removed - * in 2.6.25. Only recent versions of - * U-Boot support local-mac-address, however. - */ - address = [ 00 00 00 00 00 00 ]; - local-mac-address = [ 00 00 00 00 00 00 ]; - interrupts = <23 2 24 2 28 2>; + address = [ 00 00 0C 00 01 FD ]; + interrupts = <13 2 14 2 18 2>; interrupt-parent = <&mpic>; phy-handle = <&phy1>; }; @@ -144,79 +132,79 @@ interrupt-map = < /* IDSEL 0x2 */ - 1000 0 0 1 &mpic 1 1 - 1000 0 0 2 &mpic 2 1 - 1000 0 0 3 &mpic 3 1 - 1000 0 0 4 &mpic 4 1 + 1000 0 0 1 &mpic 31 1 + 1000 0 0 2 &mpic 32 1 + 1000 0 0 3 &mpic 33 1 + 1000 0 0 4 &mpic 34 1 /* IDSEL 0x3 */ - 1800 0 0 1 &mpic 4 1 - 1800 0 0 2 &mpic 1 1 - 1800 0 0 3 &mpic 2 1 - 1800 0 0 4 &mpic 3 1 + 1800 0 0 1 &mpic 34 1 + 1800 0 0 2 &mpic 31 1 + 1800 0 0 3 &mpic 32 1 + 1800 0 0 4 &mpic 33 1 /* IDSEL 0x4 */ - 2000 0 0 1 &mpic 3 1 - 2000 0 0 2 &mpic 4 1 - 2000 0 0 3 &mpic 1 1 - 2000 0 0 4 &mpic 2 1 + 2000 0 0 1 &mpic 33 1 + 2000 0 0 2 &mpic 34 1 + 2000 0 0 3 &mpic 31 1 + 2000 0 0 4 &mpic 32 1 /* IDSEL 0x5 */ - 2800 0 0 1 &mpic 2 1 - 2800 0 0 2 &mpic 3 1 - 2800 0 0 3 &mpic 4 1 - 2800 0 0 4 &mpic 1 1 + 2800 0 0 1 &mpic 32 1 + 2800 0 0 2 &mpic 33 1 + 2800 0 0 3 &mpic 34 1 + 2800 0 0 4 &mpic 31 1 /* IDSEL 12 */ - 6000 0 0 1 &mpic 1 1 - 6000 0 0 2 &mpic 2 1 - 6000 0 0 3 &mpic 3 1 - 6000 0 0 4 &mpic 4 1 + 6000 0 0 1 &mpic 31 1 + 6000 0 0 2 &mpic 32 1 + 6000 0 0 3 &mpic 33 1 + 6000 0 0 4 &mpic 34 1 /* IDSEL 13 */ - 6800 0 0 1 &mpic 4 1 - 6800 0 0 2 &mpic 1 1 - 6800 0 0 3 &mpic 2 1 - 6800 0 0 4 &mpic 3 1 + 6800 0 0 1 &mpic 34 1 + 6800 0 0 2 &mpic 31 1 + 6800 0 0 3 &mpic 32 1 + 6800 0 0 4 &mpic 33 1 /* IDSEL 14*/ - 7000 0 0 1 &mpic 3 1 - 7000 0 0 2 &mpic 4 1 - 7000 0 0 3 &mpic 1 1 - 7000 0 0 4 &mpic 2 1 + 7000 0 0 1 &mpic 33 1 + 7000 0 0 2 &mpic 34 1 + 7000 0 0 3 &mpic 31 1 + 7000 0 0 4 &mpic 32 1 /* IDSEL 15 */ - 7800 0 0 1 &mpic 2 1 - 7800 0 0 2 &mpic 3 1 - 7800 0 0 3 &mpic 4 1 - 7800 0 0 4 &mpic 1 1 + 7800 0 0 1 &mpic 32 1 + 7800 0 0 2 &mpic 33 1 + 7800 0 0 3 &mpic 34 1 + 7800 0 0 4 &mpic 31 1 /* IDSEL 18 */ - 9000 0 0 1 &mpic 1 1 - 9000 0 0 2 &mpic 2 1 - 9000 0 0 3 &mpic 3 1 - 9000 0 0 4 &mpic 4 1 + 9000 0 0 1 &mpic 31 1 + 9000 0 0 2 &mpic 32 1 + 9000 0 0 3 &mpic 33 1 + 9000 0 0 4 &mpic 34 1 /* IDSEL 19 */ - 9800 0 0 1 &mpic 4 1 - 9800 0 0 2 &mpic 1 1 - 9800 0 0 3 &mpic 2 1 - 9800 0 0 4 &mpic 3 1 + 9800 0 0 1 &mpic 34 1 + 9800 0 0 2 &mpic 31 1 + 9800 0 0 3 &mpic 32 1 + 9800 0 0 4 &mpic 33 1 /* IDSEL 20 */ - a000 0 0 1 &mpic 3 1 - a000 0 0 2 &mpic 4 1 - a000 0 0 3 &mpic 1 1 - a000 0 0 4 &mpic 2 1 + a000 0 0 1 &mpic 33 1 + a000 0 0 2 &mpic 34 1 + a000 0 0 3 &mpic 31 1 + a000 0 0 4 &mpic 32 1 /* IDSEL 21 */ - a800 0 0 1 &mpic 2 1 - a800 0 0 2 &mpic 3 1 - a800 0 0 3 &mpic 4 1 - a800 0 0 4 &mpic 1 1>; + a800 0 0 1 &mpic 32 1 + a800 0 0 2 &mpic 33 1 + a800 0 0 3 &mpic 34 1 + a800 0 0 4 &mpic 31 1>; interrupt-parent = <&mpic>; - interrupts = <18 2>; + interrupts = <8 0>; bus-range = <0 0>; ranges = <02000000 0 80000000 80000000 0 20000000 01000000 0 00000000 e2000000 0 01000000>; @@ -246,7 +234,7 @@ interrupt-controller; #address-cells = <0>; #interrupt-cells = <2>; - interrupts = <2e 2>; + interrupts = <1e 0>; interrupt-parent = <&mpic>; reg = <90c00 80>; built-in; @@ -287,13 +275,7 @@ model = "FCC"; device-id = <2>; reg = <91320 20 88500 100 913a0 30>; - /* - * mac-address is deprecated and will be removed - * in 2.6.25. Only recent versions of - * U-Boot support local-mac-address, however. - */ - mac-address = [ 00 00 00 00 00 00 ]; - local-mac-address = [ 00 00 00 00 00 00 ]; + mac-address = [ 00 00 0C 00 02 FD ]; clock-setup = ; rx-clock = <15>; tx-clock = <16>; @@ -308,13 +290,7 @@ model = "FCC"; device-id = <3>; reg = <91340 20 88600 100 913d0 30>; - /* - * mac-address is deprecated and will be removed - * in 2.6.25. Only recent versions of - * U-Boot support local-mac-address, however. - */ - mac-address = [ 00 00 00 00 00 00 ]; - local-mac-address = [ 00 00 00 00 00 00 ]; + mac-address = [ 00 00 0C 00 03 FD ]; clock-setup = ; rx-clock = <17>; tx-clock = <18>; diff --git a/trunk/arch/powerpc/boot/dts/mpc8568mds.dts b/trunk/arch/powerpc/boot/dts/mpc8568mds.dts index 6bb18f2807a8..a123ec9456bc 100644 --- a/trunk/arch/powerpc/boot/dts/mpc8568mds.dts +++ b/trunk/arch/powerpc/boot/dts/mpc8568mds.dts @@ -61,7 +61,7 @@ compatible = "fsl,8568-memory-controller"; reg = <2000 1000>; interrupt-parent = <&mpic>; - interrupts = <12 2>; + interrupts = <2 2>; }; l2-cache-controller@20000 { @@ -70,14 +70,14 @@ cache-line-size = <20>; // 32 bytes cache-size = <80000>; // L2, 512K interrupt-parent = <&mpic>; - interrupts = <10 2>; + interrupts = <0 2>; }; i2c@3000 { device_type = "i2c"; compatible = "fsl-i2c"; reg = <3000 100>; - interrupts = <2b 2>; + interrupts = <1b 2>; interrupt-parent = <&mpic>; dfsrr; }; @@ -86,7 +86,7 @@ device_type = "i2c"; compatible = "fsl-i2c"; reg = <3100 100>; - interrupts = <2b 2>; + interrupts = <1b 2>; interrupt-parent = <&mpic>; dfsrr; }; @@ -99,25 +99,25 @@ reg = <24520 20>; phy0: ethernet-phy@0 { interrupt-parent = <&mpic>; - interrupts = <1 1>; + interrupts = <31 1>; reg = <0>; device_type = "ethernet-phy"; }; phy1: ethernet-phy@1 { interrupt-parent = <&mpic>; - interrupts = <2 1>; + interrupts = <32 1>; reg = <1>; device_type = "ethernet-phy"; }; phy2: ethernet-phy@2 { interrupt-parent = <&mpic>; - interrupts = <1 1>; + interrupts = <31 1>; reg = <2>; device_type = "ethernet-phy"; }; phy3: ethernet-phy@3 { interrupt-parent = <&mpic>; - interrupts = <2 1>; + interrupts = <32 1>; reg = <3>; device_type = "ethernet-phy"; }; @@ -130,14 +130,8 @@ model = "eTSEC"; compatible = "gianfar"; reg = <24000 1000>; - /* - * mac-address is deprecated and will be removed - * in 2.6.25. Only recent versions of - * U-Boot support local-mac-address, however. - */ mac-address = [ 00 00 00 00 00 00 ]; - local-mac-address = [ 00 00 00 00 00 00 ]; - interrupts = <1d 2 1e 2 22 2>; + interrupts = ; interrupt-parent = <&mpic>; phy-handle = <&phy2>; }; @@ -149,14 +143,8 @@ model = "eTSEC"; compatible = "gianfar"; reg = <25000 1000>; - /* - * mac-address is deprecated and will be removed - * in 2.6.25. Only recent versions of - * U-Boot support local-mac-address, however. - */ - mac-address = [ 00 00 00 00 00 00 ]; - local-mac-address = [ 00 00 00 00 00 00 ]; - interrupts = <23 2 24 2 28 2>; + mac-address = [ 00 00 00 00 00 00]; + interrupts = <13 2 14 2 18 2>; interrupt-parent = <&mpic>; phy-handle = <&phy3>; }; @@ -166,7 +154,7 @@ compatible = "ns16550"; reg = <4500 100>; clock-frequency = <0>; - interrupts = <2a 2>; + interrupts = <1a 2>; interrupt-parent = <&mpic>; }; @@ -175,7 +163,7 @@ compatible = "ns16550"; reg = <4600 100>; clock-frequency = <0>; - interrupts = <2a 2>; + interrupts = <1a 2>; interrupt-parent = <&mpic>; }; @@ -184,7 +172,7 @@ model = "SEC2"; compatible = "talitos"; reg = <30000 f000>; - interrupts = <2d 2>; + interrupts = <1d 2>; interrupt-parent = <&mpic>; num-channels = <4>; channel-fifo-len = <18>; @@ -312,13 +300,7 @@ reg = <2000 200>; interrupts = <20>; interrupt-parent = <&qeic>; - /* - * mac-address is deprecated and will be removed - * in 2.6.25. Only recent versions of - * U-Boot support local-mac-address, however. - */ - mac-address = [ 00 00 00 00 00 00 ]; - local-mac-address = [ 00 00 00 00 00 00 ]; + mac-address = [ 00 04 9f 00 23 23 ]; rx-clock = <0>; tx-clock = <19>; phy-handle = <&qe_phy0>; @@ -334,13 +316,7 @@ reg = <3000 200>; interrupts = <21>; interrupt-parent = <&qeic>; - /* - * mac-address is deprecated and will be removed - * in 2.6.25. Only recent versions of - * U-Boot support local-mac-address, however. - */ - mac-address = [ 00 00 00 00 00 00 ]; - local-mac-address = [ 00 00 00 00 00 00 ]; + mac-address = [ 00 11 22 33 44 55 ]; rx-clock = <0>; tx-clock = <14>; phy-handle = <&qe_phy1>; @@ -359,25 +335,25 @@ * gianfar's MDIO bus */ qe_phy0: ethernet-phy@00 { interrupt-parent = <&mpic>; - interrupts = <1 1>; + interrupts = <31 1>; reg = <0>; device_type = "ethernet-phy"; }; qe_phy1: ethernet-phy@01 { interrupt-parent = <&mpic>; - interrupts = <2 1>; + interrupts = <32 1>; reg = <1>; device_type = "ethernet-phy"; }; qe_phy2: ethernet-phy@02 { interrupt-parent = <&mpic>; - interrupts = <1 1>; + interrupts = <31 1>; reg = <2>; device_type = "ethernet-phy"; }; qe_phy3: ethernet-phy@03 { interrupt-parent = <&mpic>; - interrupts = <2 1>; + interrupts = <32 1>; reg = <3>; device_type = "ethernet-phy"; }; @@ -391,7 +367,7 @@ reg = <80 80>; built-in; big-endian; - interrupts = <2e 2 2e 2>; //high:30 low:30 + interrupts = <1e 2 1e 2>; //high:30 low:30 interrupt-parent = <&mpic>; }; diff --git a/trunk/arch/powerpc/boot/dts/mpc8641_hpcn.dts b/trunk/arch/powerpc/boot/dts/mpc8641_hpcn.dts index db56a02b748f..260b264c869e 100644 --- a/trunk/arch/powerpc/boot/dts/mpc8641_hpcn.dts +++ b/trunk/arch/powerpc/boot/dts/mpc8641_hpcn.dts @@ -56,12 +56,8 @@ #size-cells = <1>; #interrupt-cells = <2>; device_type = "soc"; - ranges = <00001000 f8001000 000ff000 - 80000000 80000000 20000000 - e2000000 e2000000 00100000 - a0000000 a0000000 20000000 - e3000000 e3000000 00100000>; - reg = ; // CCSRBAR + ranges = <0 f8000000 00100000>; + reg = ; // CCSRBAR 1M bus-frequency = <0>; i2c@3000 { @@ -90,25 +86,25 @@ reg = <24520 20>; phy0: ethernet-phy@0 { interrupt-parent = <&mpic>; - interrupts = ; + interrupts = <4a 1>; reg = <0>; device_type = "ethernet-phy"; }; phy1: ethernet-phy@1 { interrupt-parent = <&mpic>; - interrupts = ; + interrupts = <4a 1>; reg = <1>; device_type = "ethernet-phy"; }; phy2: ethernet-phy@2 { interrupt-parent = <&mpic>; - interrupts = ; + interrupts = <4a 1>; reg = <2>; device_type = "ethernet-phy"; }; phy3: ethernet-phy@3 { interrupt-parent = <&mpic>; - interrupts = ; + interrupts = <4a 1>; reg = <3>; device_type = "ethernet-phy"; }; @@ -121,13 +117,7 @@ model = "TSEC"; compatible = "gianfar"; reg = <24000 1000>; - /* - * mac-address is deprecated and will be removed - * in 2.6.25. Only recent versions of - * U-Boot support local-mac-address, however. - */ - mac-address = [ 00 00 00 00 00 00 ]; - local-mac-address = [ 00 00 00 00 00 00 ]; + mac-address = [ 00 E0 0C 00 73 00 ]; interrupts = <1d 2 1e 2 22 2>; interrupt-parent = <&mpic>; phy-handle = <&phy0>; @@ -140,13 +130,7 @@ model = "TSEC"; compatible = "gianfar"; reg = <25000 1000>; - /* - * mac-address is deprecated and will be removed - * in 2.6.25. Only recent versions of - * U-Boot support local-mac-address, however. - */ - mac-address = [ 00 00 00 00 00 00 ]; - local-mac-address = [ 00 00 00 00 00 00 ]; + mac-address = [ 00 E0 0C 00 73 01 ]; interrupts = <23 2 24 2 28 2>; interrupt-parent = <&mpic>; phy-handle = <&phy1>; @@ -159,13 +143,7 @@ model = "TSEC"; compatible = "gianfar"; reg = <26000 1000>; - /* - * mac-address is deprecated and will be removed - * in 2.6.25. Only recent versions of - * U-Boot support local-mac-address, however. - */ - mac-address = [ 00 00 00 00 00 00 ]; - local-mac-address = [ 00 00 00 00 00 00 ]; + mac-address = [ 00 E0 0C 00 02 FD ]; interrupts = <1F 2 20 2 21 2>; interrupt-parent = <&mpic>; phy-handle = <&phy2>; @@ -178,13 +156,7 @@ model = "TSEC"; compatible = "gianfar"; reg = <27000 1000>; - /* - * mac-address is deprecated and will be removed - * in 2.6.25. Only recent versions of - * U-Boot support local-mac-address, however. - */ - mac-address = [ 00 00 00 00 00 00 ]; - local-mac-address = [ 00 00 00 00 00 00 ]; + mac-address = [ 00 E0 0C 00 03 FD ]; interrupts = <25 2 26 2 27 2>; interrupt-parent = <&mpic>; phy-handle = <&phy3>; @@ -214,7 +186,7 @@ #size-cells = <2>; #address-cells = <3>; reg = <8000 1000>; - bus-range = <0 ff>; + bus-range = <0 fe>; ranges = <02000000 0 80000000 80000000 0 20000000 01000000 0 00000000 e2000000 0 00100000>; clock-frequency = <1fca055>; @@ -313,84 +285,17 @@ f800 0 0 3 &i8259 0 0 f800 0 0 4 &i8259 0 0 >; - uli1575@0 { - reg = <0 0 0 0 0>; - #size-cells = <2>; - #address-cells = <3>; - ranges = <02000000 0 80000000 - 02000000 0 80000000 - 0 20000000 - 01000000 0 00000000 - 01000000 0 00000000 - 0 00100000>; - - pci_bridge@0 { - reg = <0 0 0 0 0>; - #size-cells = <2>; - #address-cells = <3>; - ranges = <02000000 0 80000000 - 02000000 0 80000000 - 0 20000000 - 01000000 0 00000000 - 01000000 0 00000000 - 0 00100000>; - - isa@1e { - device_type = "isa"; - #interrupt-cells = <2>; - #size-cells = <1>; - #address-cells = <2>; - reg = ; - ranges = <1 0 01000000 0 0 - 00001000>; - interrupt-parent = <&i8259>; - - i8259: interrupt-controller@20 { - reg = <1 20 2 - 1 a0 2 - 1 4d0 2>; - clock-frequency = <0>; - interrupt-controller; - device_type = "interrupt-controller"; - #address-cells = <0>; - #interrupt-cells = <2>; - built-in; - compatible = "chrp,iic"; - interrupts = <9 2>; - interrupt-parent = - <&mpic>; - }; - - i8042@60 { - #size-cells = <0>; - #address-cells = <1>; - reg = <1 60 1 1 64 1>; - interrupts = <1 3 c 3>; - interrupt-parent = - <&i8259>; - - keyboard@0 { - reg = <0>; - compatible = "pnpPNP,303"; - }; - - mouse@1 { - reg = <1>; - compatible = "pnpPNP,f03"; - }; - }; - - rtc@70 { - compatible = - "pnpPNP,b00"; - reg = <1 70 2>; - }; - - gpio@400 { - reg = <1 400 80>; - }; - }; - }; + i8259: i8259@4d0 { + clock-frequency = <0>; + interrupt-controller; + device_type = "interrupt-controller"; + #address-cells = <0>; + #interrupt-cells = <2>; + built-in; + compatible = "chrp,iic"; + big-endian; + interrupts = <49 2>; + interrupt-parent = <&mpic>; }; }; @@ -411,10 +316,10 @@ interrupt-map-mask = ; interrupt-map = < /* IDSEL 0x0 */ - 0000 0 0 1 &mpic 4 1 - 0000 0 0 2 &mpic 5 1 - 0000 0 0 3 &mpic 6 1 - 0000 0 0 4 &mpic 7 1 + 0000 0 0 1 &mpic 44 1 + 0000 0 0 2 &mpic 45 1 + 0000 0 0 3 &mpic 46 1 + 0000 0 0 4 &mpic 47 1 >; }; diff --git a/trunk/arch/powerpc/boot/dts/mpc866ads.dts b/trunk/arch/powerpc/boot/dts/mpc866ads.dts index e5e7726ddb03..c0d06fd12927 100644 --- a/trunk/arch/powerpc/boot/dts/mpc866ads.dts +++ b/trunk/arch/powerpc/boot/dts/mpc866ads.dts @@ -15,10 +15,12 @@ compatible = "mpc8xx"; #address-cells = <1>; #size-cells = <1>; + linux,phandle = <100>; cpus { #address-cells = <1>; #size-cells = <0>; + linux,phandle = <200>; PowerPC,866@0 { device_type = "cpu"; @@ -32,12 +34,14 @@ clock-frequency = <0>; 32-bit; interrupts = ; // decrementer interrupt - interrupt-parent = <&Mpc8xx_pic>; + interrupt-parent = ; + linux,phandle = <201>; }; }; memory { device_type = "memory"; + linux,phandle = <300>; reg = <00000000 800000>; }; @@ -53,9 +57,11 @@ device_type = "mdio"; compatible = "fs_enet"; reg = ; + linux,phandle = ; #address-cells = <1>; #size-cells = <0>; - phy: ethernet-phy@f { + ethernet-phy@f { + linux,phandle = ; reg = ; device_type = "ethernet-phy"; }; @@ -69,11 +75,12 @@ reg = ; mac-address = [ 00 00 0C 00 01 FD ]; interrupts = <3 1>; - interrupt-parent = <&Mpc8xx_pic>; - phy-handle = <&Phy>; + interrupt-parent = ; + phy-handle = ; }; - mpc8xx_pic: pic@ff000000 { + pic@ff000000 { + linux,phandle = ; interrupt-controller; #address-cells = <0>; #interrupt-cells = <2>; @@ -84,6 +91,7 @@ }; cpm@ff000000 { + linux,phandle = ; #address-cells = <1>; #size-cells = <1>; #interrupt-cells = <2>; @@ -94,14 +102,15 @@ command-proc = <9c0>; brg-frequency = <0>; interrupts = <0 2>; // cpm error interrupt - interrupt-parent = <&Cpm_pic>; + interrupt-parent = <930>; - cpm_pic: pic@930 { + pic@930 { + linux,phandle = <930>; interrupt-controller; #address-cells = <0>; #interrupt-cells = <2>; interrupts = <5 2 0 2>; - interrupt-parent = <&Mpc8xx_pic>; + interrupt-parent = ; reg = <930 20>; built-in; device_type = "cpm-pic"; @@ -119,7 +128,7 @@ tx-clock = <1>; current-speed = <0>; interrupts = <4 3>; - interrupt-parent = <&Cpm_pic>; + interrupt-parent = <930>; }; smc@a90 { @@ -133,7 +142,7 @@ tx-clock = <2>; current-speed = <0>; interrupts = <3 3>; - interrupt-parent = <&Cpm_pic>; + interrupt-parent = <930>; }; scc@a00 { @@ -144,7 +153,7 @@ reg = ; mac-address = [ 00 00 0C 00 03 FD ]; interrupts = <1e 3>; - interrupt-parent = <&Cpm_pic>; + interrupt-parent = <930>; }; }; }; diff --git a/trunk/arch/powerpc/boot/dts/mpc885ads.dts b/trunk/arch/powerpc/boot/dts/mpc885ads.dts index dc7ab9c80611..110bf6170603 100644 --- a/trunk/arch/powerpc/boot/dts/mpc885ads.dts +++ b/trunk/arch/powerpc/boot/dts/mpc885ads.dts @@ -15,10 +15,12 @@ compatible = "mpc8xx"; #address-cells = <1>; #size-cells = <1>; + linux,phandle = <100>; cpus { #address-cells = <1>; #size-cells = <0>; + linux,phandle = <200>; PowerPC,885@0 { device_type = "cpu"; @@ -32,12 +34,14 @@ clock-frequency = <0>; 32-bit; interrupts = ; // decrementer interrupt - interrupt-parent = <&Mpc8xx_pic>; + interrupt-parent = ; + linux,phandle = <201>; }; }; memory { device_type = "memory"; + linux,phandle = <300>; reg = <00000000 800000>; }; @@ -53,17 +57,21 @@ device_type = "mdio"; compatible = "fs_enet"; reg = ; + linux,phandle = ; #address-cells = <1>; #size-cells = <0>; - Phy0: ethernet-phy@0 { + ethernet-phy@0 { + linux,phandle = ; reg = <0>; device_type = "ethernet-phy"; }; - Phy1: ethernet-phy@1 { + ethernet-phy@1 { + linux,phandle = ; reg = <1>; device_type = "ethernet-phy"; }; - Phy2: ethernet-phy@2 { + ethernet-phy@2 { + linux,phandle = ; reg = <2>; device_type = "ethernet-phy"; }; @@ -77,8 +85,8 @@ reg = ; mac-address = [ 00 00 0C 00 01 FD ]; interrupts = <3 1>; - interrupt-parent = <&Mpc8xx_pic>; - phy-handle = <&Phy1>; + interrupt-parent = ; + phy-handle = ; }; fec@1e00 { @@ -89,11 +97,12 @@ reg = <1e00 188>; mac-address = [ 00 00 0C 00 02 FD ]; interrupts = <7 1>; - interrupt-parent = <&Mpc8xx_pic>; - phy-handle = <&Phy2>; + interrupt-parent = ; + phy-handle = ; }; - Mpc8xx_pic: pic@ff000000 { + pic@ff000000 { + linux,phandle = ; interrupt-controller; #address-cells = <0>; #interrupt-cells = <2>; @@ -103,18 +112,8 @@ compatible = "CPM"; }; - pcmcia@0080 { - #address-cells = <3>; - #interrupt-cells = <1>; - #size-cells = <2>; - compatible = "fsl,pq-pcmcia"; - device_type = "pcmcia"; - reg = <80 80>; - interrupt-parent = <&Mpc8xx_pic>; - interrupts = ; - }; - cpm@ff000000 { + linux,phandle = ; #address-cells = <1>; #size-cells = <1>; #interrupt-cells = <2>; @@ -125,14 +124,15 @@ command-proc = <9c0>; brg-frequency = <0>; interrupts = <0 2>; // cpm error interrupt - interrupt-parent = <&Cpm_pic>; + interrupt-parent = <930>; - Cpm_pic: pic@930 { + pic@930 { + linux,phandle = <930>; interrupt-controller; #address-cells = <0>; #interrupt-cells = <2>; interrupts = <5 2 0 2>; - interrupt-parent = <&Mpc8xx_pic>; + interrupt-parent = ; reg = <930 20>; built-in; device_type = "cpm-pic"; @@ -150,7 +150,7 @@ tx-clock = <1>; current-speed = <0>; interrupts = <4 3>; - interrupt-parent = <&Cpm_pic>; + interrupt-parent = <930>; }; smc@a90 { @@ -164,7 +164,7 @@ tx-clock = <2>; current-speed = <0>; interrupts = <3 3>; - interrupt-parent = <&Cpm_pic>; + interrupt-parent = <930>; }; scc@a40 { @@ -175,8 +175,8 @@ reg = ; mac-address = [ 00 00 0C 00 03 FD ]; interrupts = <1c 3>; - interrupt-parent = <&Cpm_pic>; - phy-handle = <&Phy2>; + interrupt-parent = <930>; + phy-handle = ; }; }; }; diff --git a/trunk/arch/powerpc/boot/dts/prpmc2800.dts b/trunk/arch/powerpc/boot/dts/prpmc2800.dts index 699d0df574d5..568965a022b9 100644 --- a/trunk/arch/powerpc/boot/dts/prpmc2800.dts +++ b/trunk/arch/powerpc/boot/dts/prpmc2800.dts @@ -309,7 +309,7 @@ }; chosen { - bootargs = "ip=on"; + bootargs = "ip=on console=ttyMM0"; linux,stdout-path = "/mv64x60@f1000000/mpsc@8000"; }; }; diff --git a/trunk/arch/powerpc/boot/dts/ps3.dts b/trunk/arch/powerpc/boot/dts/ps3.dts deleted file mode 100644 index 379ded282d5e..000000000000 --- a/trunk/arch/powerpc/boot/dts/ps3.dts +++ /dev/null @@ -1,68 +0,0 @@ -/* - * PS3 Game Console device tree. - * - * Copyright (C) 2007 Sony Computer Entertainment Inc. - * Copyright 2007 Sony Corp. - * - * 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; version 2 of the License. - * - * 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 - */ - -/ { - model = "SonyPS3"; - compatible = "sony,ps3"; - #size-cells = <2>; - #address-cells = <2>; - - chosen { - }; - - /* - * We'll get the size of the bootmem block from lv1 after startup, - * so we'll put a null entry here. - */ - - memory { - device_type = "memory"; - reg = <0 0 0 0>; - }; - - /* - * The boot cpu is always zero for PS3. - * - * dtc expects a clock-frequency and timebase-frequency entries, so - * we'll put a null entries here. These will be initialized after - * startup with data from lv1. - * - * Seems the only way currently to indicate a processor has multiple - * threads is with an ibm,ppc-interrupt-server#s entry. We'll put one - * here so we can bring up both of ours. See smp_setup_cpu_maps(). - */ - - cpus { - #size-cells = <0>; - #address-cells = <1>; - - cpu@0 { - device_type = "cpu"; - reg = <0>; - ibm,ppc-interrupt-server#s = <0 1>; - clock-frequency = <0>; - timebase-frequency = <0>; - i-cache-size = <8000>; - d-cache-size = <8000>; - i-cache-line-size = <80>; - d-cache-line-size = <80>; - }; - }; -}; diff --git a/trunk/arch/powerpc/boot/ebony.c b/trunk/arch/powerpc/boot/ebony.c index 75daedafd0a4..b1251ee7a102 100644 --- a/trunk/arch/powerpc/boot/ebony.c +++ b/trunk/arch/powerpc/boot/ebony.c @@ -100,13 +100,28 @@ static void ebony_fixups(void) ibm440gp_fixup_clocks(sysclk, 6 * 1843200); ibm44x_fixup_memsize(); dt_fixup_mac_addresses(ebony_mac0, ebony_mac1); - ibm4xx_fixup_ebc_ranges("/plb/opb/ebc"); +} + +#define SPRN_DBCR0 0x134 +#define DBCR0_RST_SYSTEM 0x30000000 + +static void ebony_exit(void) +{ + unsigned long tmp; + + asm volatile ( + "mfspr %0,%1\n" + "oris %0,%0,%2@h\n" + "mtspr %1,%0" + : "=&r"(tmp) : "i"(SPRN_DBCR0), "i"(DBCR0_RST_SYSTEM) + ); + } void ebony_init(void *mac0, void *mac1) { platform_ops.fixups = ebony_fixups; - platform_ops.exit = ibm44x_dbcr_reset; + platform_ops.exit = ebony_exit; ebony_mac0 = mac0; ebony_mac1 = mac1; ft_init(_dtb_start, _dtb_end - _dtb_start, 32); diff --git a/trunk/arch/powerpc/boot/main.c b/trunk/arch/powerpc/boot/main.c index 416dc3857bfe..56b56a8d4b23 100644 --- a/trunk/arch/powerpc/boot/main.c +++ b/trunk/arch/powerpc/boot/main.c @@ -36,6 +36,8 @@ struct addr_range { unsigned long size; }; +typedef void (*kernel_entry_t)(unsigned long, unsigned long, void *); + #undef DEBUG static struct addr_range prep_kernel(void) diff --git a/trunk/arch/powerpc/boot/of.c b/trunk/arch/powerpc/boot/of.c index 385e08b83b7e..d16ee3e3f868 100644 --- a/trunk/arch/powerpc/boot/of.c +++ b/trunk/arch/powerpc/boot/of.c @@ -15,7 +15,8 @@ #include "page.h" #include "ops.h" -#include "of.h" +typedef void *ihandle; +typedef void *phandle; extern char _end[]; @@ -24,10 +25,154 @@ extern char _end[]; #define RAM_END (512<<20) /* Fixme: use OF */ #define ONE_MB 0x100000 +int (*prom) (void *); static unsigned long claim_base; +static int call_prom(const char *service, int nargs, int nret, ...) +{ + int i; + struct prom_args { + const char *service; + int nargs; + int nret; + unsigned int args[12]; + } args; + va_list list; + + args.service = service; + args.nargs = nargs; + args.nret = nret; + + va_start(list, nret); + for (i = 0; i < nargs; i++) + args.args[i] = va_arg(list, unsigned int); + va_end(list); + + for (i = 0; i < nret; i++) + args.args[nargs+i] = 0; + + if (prom(&args) < 0) + return -1; + + return (nret > 0)? args.args[nargs]: 0; +} + +static int call_prom_ret(const char *service, int nargs, int nret, + unsigned int *rets, ...) +{ + int i; + struct prom_args { + const char *service; + int nargs; + int nret; + unsigned int args[12]; + } args; + va_list list; + + args.service = service; + args.nargs = nargs; + args.nret = nret; + + va_start(list, rets); + for (i = 0; i < nargs; i++) + args.args[i] = va_arg(list, unsigned int); + va_end(list); + + for (i = 0; i < nret; i++) + args.args[nargs+i] = 0; + + if (prom(&args) < 0) + return -1; + + if (rets != (void *) 0) + for (i = 1; i < nret; ++i) + rets[i-1] = args.args[nargs+i]; + + return (nret > 0)? args.args[nargs]: 0; +} + +/* + * Older OF's require that when claiming a specific range of addresses, + * we claim the physical space in the /memory node and the virtual + * space in the chosen mmu node, and then do a map operation to + * map virtual to physical. + */ +static int need_map = -1; +static ihandle chosen_mmu; +static phandle memory; + +/* returns true if s2 is a prefix of s1 */ +static int string_match(const char *s1, const char *s2) +{ + for (; *s2; ++s2) + if (*s1++ != *s2) + return 0; + return 1; +} + +static int check_of_version(void) +{ + phandle oprom, chosen; + char version[64]; + + oprom = finddevice("/openprom"); + if (oprom == (phandle) -1) + return 0; + if (getprop(oprom, "model", version, sizeof(version)) <= 0) + return 0; + version[sizeof(version)-1] = 0; + printf("OF version = '%s'\r\n", version); + if (!string_match(version, "Open Firmware, 1.") + && !string_match(version, "FirmWorks,3.")) + return 0; + chosen = finddevice("/chosen"); + if (chosen == (phandle) -1) { + chosen = finddevice("/chosen@0"); + if (chosen == (phandle) -1) { + printf("no chosen\n"); + return 0; + } + } + if (getprop(chosen, "mmu", &chosen_mmu, sizeof(chosen_mmu)) <= 0) { + printf("no mmu\n"); + return 0; + } + memory = (ihandle) call_prom("open", 1, 1, "/memory"); + if (memory == (ihandle) -1) { + memory = (ihandle) call_prom("open", 1, 1, "/memory@0"); + if (memory == (ihandle) -1) { + printf("no memory node\n"); + return 0; + } + } + printf("old OF detected\r\n"); + return 1; +} + +static void *claim(unsigned long virt, unsigned long size, unsigned long align) +{ + int ret; + unsigned int result; + + if (need_map < 0) + need_map = check_of_version(); + if (align || !need_map) + return (void *) call_prom("claim", 3, 1, virt, size, align); + + ret = call_prom_ret("call-method", 5, 2, &result, "claim", memory, + align, size, virt); + if (ret != 0 || result == -1) + return (void *) -1; + ret = call_prom_ret("call-method", 5, 2, &result, "claim", chosen_mmu, + align, size, virt); + /* 0x12 == coherent + read/write */ + ret = call_prom("call-method", 6, 1, "map", chosen_mmu, + 0x12, size, virt, virt); + return (void *) virt; +} + static void *of_try_claim(unsigned long size) { unsigned long addr = 0; @@ -39,7 +184,7 @@ static void *of_try_claim(unsigned long size) #ifdef DEBUG printf(" trying: 0x%08lx\n\r", claim_base); #endif - addr = (unsigned long)of_claim(claim_base, size, 0); + addr = (unsigned long)claim(claim_base, size, 0); if ((void *)addr != (void *)-1) break; } @@ -63,6 +208,64 @@ static void of_image_hdr(const void *hdr) } } +static void *of_vmlinux_alloc(unsigned long size) +{ + void *p = malloc(size); + + if (!p) + fatal("Can't allocate memory for kernel image!\n\r"); + + return p; +} + +static void of_exit(void) +{ + call_prom("exit", 0, 0); +} + +/* + * OF device tree routines + */ +static void *of_finddevice(const char *name) +{ + return (phandle) call_prom("finddevice", 1, 1, name); +} + +static int of_getprop(const void *phandle, const char *name, void *buf, + const int buflen) +{ + return call_prom("getprop", 4, 1, phandle, name, buf, buflen); +} + +static int of_setprop(const void *phandle, const char *name, const void *buf, + const int buflen) +{ + return call_prom("setprop", 4, 1, phandle, name, buf, buflen); +} + +/* + * OF console routines + */ +static void *of_stdout_handle; + +static int of_console_open(void) +{ + void *devp; + + if (((devp = finddevice("/chosen")) != NULL) + && (getprop(devp, "stdout", &of_stdout_handle, + sizeof(of_stdout_handle)) + == sizeof(of_stdout_handle))) + return 0; + + return -1; +} + +static void of_console_write(char *buf, int len) +{ + call_prom("write", 3, 1, of_stdout_handle, buf, len); +} + void platform_init(unsigned long a1, unsigned long a2, void *promptr) { platform_ops.image_hdr = of_image_hdr; @@ -74,9 +277,10 @@ void platform_init(unsigned long a1, unsigned long a2, void *promptr) dt_ops.getprop = of_getprop; dt_ops.setprop = of_setprop; - of_console_init(); + console_ops.open = of_console_open; + console_ops.write = of_console_write; - of_init(promptr); + prom = (int (*)(void *))promptr; loader_info.promptr = promptr; if (a1 && a2 && a2 != 0xdeadbeef) { loader_info.initrd_addr = a1; diff --git a/trunk/arch/powerpc/boot/of.h b/trunk/arch/powerpc/boot/of.h deleted file mode 100644 index e4c68f7391c5..000000000000 --- a/trunk/arch/powerpc/boot/of.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef _PPC_BOOT_OF_H_ -#define _PPC_BOOT_OF_H_ - -typedef void *phandle; -typedef void *ihandle; - -void of_init(void *promptr); -int of_call_prom(const char *service, int nargs, int nret, ...); -void *of_claim(unsigned long virt, unsigned long size, unsigned long align); -void *of_vmlinux_alloc(unsigned long size); -void of_exit(void); -void *of_finddevice(const char *name); -int of_getprop(const void *phandle, const char *name, void *buf, - const int buflen); -int of_setprop(const void *phandle, const char *name, const void *buf, - const int buflen); - -/* Console functions */ -void of_console_init(void); - -#endif /* _PPC_BOOT_OF_H_ */ diff --git a/trunk/arch/powerpc/boot/ofconsole.c b/trunk/arch/powerpc/boot/ofconsole.c deleted file mode 100644 index ce0e02424453..000000000000 --- a/trunk/arch/powerpc/boot/ofconsole.c +++ /dev/null @@ -1,45 +0,0 @@ -/* - * OF console routines - * - * Copyright (C) Paul Mackerras 1997. - * - * 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 "types.h" -#include "elf.h" -#include "string.h" -#include "stdio.h" -#include "page.h" -#include "ops.h" - -#include "of.h" - -static void *of_stdout_handle; - -static int of_console_open(void) -{ - void *devp; - - if (((devp = of_finddevice("/chosen")) != NULL) - && (of_getprop(devp, "stdout", &of_stdout_handle, - sizeof(of_stdout_handle)) - == sizeof(of_stdout_handle))) - return 0; - - return -1; -} - -static void of_console_write(const char *buf, int len) -{ - of_call_prom("write", 3, 1, of_stdout_handle, buf, len); -} - -void of_console_init(void) -{ - console_ops.open = of_console_open; - console_ops.write = of_console_write; -} diff --git a/trunk/arch/powerpc/boot/oflib.c b/trunk/arch/powerpc/boot/oflib.c deleted file mode 100644 index 95b8fd69a403..000000000000 --- a/trunk/arch/powerpc/boot/oflib.c +++ /dev/null @@ -1,202 +0,0 @@ -/* - * Copyright (C) Paul Mackerras 1997. - * - * 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 "types.h" -#include "elf.h" -#include "string.h" -#include "stdio.h" -#include "page.h" -#include "ops.h" - -#include "of.h" - -static int (*prom) (void *); - -void of_init(void *promptr) -{ - prom = (int (*)(void *))promptr; -} - -int of_call_prom(const char *service, int nargs, int nret, ...) -{ - int i; - struct prom_args { - const char *service; - int nargs; - int nret; - unsigned int args[12]; - } args; - va_list list; - - args.service = service; - args.nargs = nargs; - args.nret = nret; - - va_start(list, nret); - for (i = 0; i < nargs; i++) - args.args[i] = va_arg(list, unsigned int); - va_end(list); - - for (i = 0; i < nret; i++) - args.args[nargs+i] = 0; - - if (prom(&args) < 0) - return -1; - - return (nret > 0)? args.args[nargs]: 0; -} - -static int of_call_prom_ret(const char *service, int nargs, int nret, - unsigned int *rets, ...) -{ - int i; - struct prom_args { - const char *service; - int nargs; - int nret; - unsigned int args[12]; - } args; - va_list list; - - args.service = service; - args.nargs = nargs; - args.nret = nret; - - va_start(list, rets); - for (i = 0; i < nargs; i++) - args.args[i] = va_arg(list, unsigned int); - va_end(list); - - for (i = 0; i < nret; i++) - args.args[nargs+i] = 0; - - if (prom(&args) < 0) - return -1; - - if (rets != (void *) 0) - for (i = 1; i < nret; ++i) - rets[i-1] = args.args[nargs+i]; - - return (nret > 0)? args.args[nargs]: 0; -} - -/* returns true if s2 is a prefix of s1 */ -static int string_match(const char *s1, const char *s2) -{ - for (; *s2; ++s2) - if (*s1++ != *s2) - return 0; - return 1; -} - -/* - * Older OF's require that when claiming a specific range of addresses, - * we claim the physical space in the /memory node and the virtual - * space in the chosen mmu node, and then do a map operation to - * map virtual to physical. - */ -static int need_map = -1; -static ihandle chosen_mmu; -static phandle memory; - -static int check_of_version(void) -{ - phandle oprom, chosen; - char version[64]; - - oprom = of_finddevice("/openprom"); - if (oprom == (phandle) -1) - return 0; - if (of_getprop(oprom, "model", version, sizeof(version)) <= 0) - return 0; - version[sizeof(version)-1] = 0; - printf("OF version = '%s'\r\n", version); - if (!string_match(version, "Open Firmware, 1.") - && !string_match(version, "FirmWorks,3.")) - return 0; - chosen = of_finddevice("/chosen"); - if (chosen == (phandle) -1) { - chosen = of_finddevice("/chosen@0"); - if (chosen == (phandle) -1) { - printf("no chosen\n"); - return 0; - } - } - if (of_getprop(chosen, "mmu", &chosen_mmu, sizeof(chosen_mmu)) <= 0) { - printf("no mmu\n"); - return 0; - } - memory = (ihandle) of_call_prom("open", 1, 1, "/memory"); - if (memory == (ihandle) -1) { - memory = (ihandle) of_call_prom("open", 1, 1, "/memory@0"); - if (memory == (ihandle) -1) { - printf("no memory node\n"); - return 0; - } - } - printf("old OF detected\r\n"); - return 1; -} - -void *of_claim(unsigned long virt, unsigned long size, unsigned long align) -{ - int ret; - unsigned int result; - - if (need_map < 0) - need_map = check_of_version(); - if (align || !need_map) - return (void *) of_call_prom("claim", 3, 1, virt, size, align); - - ret = of_call_prom_ret("call-method", 5, 2, &result, "claim", memory, - align, size, virt); - if (ret != 0 || result == -1) - return (void *) -1; - ret = of_call_prom_ret("call-method", 5, 2, &result, "claim", chosen_mmu, - align, size, virt); - /* 0x12 == coherent + read/write */ - ret = of_call_prom("call-method", 6, 1, "map", chosen_mmu, - 0x12, size, virt, virt); - return (void *) virt; -} - -void *of_vmlinux_alloc(unsigned long size) -{ - void *p = malloc(size); - - if (!p) - fatal("Can't allocate memory for kernel image!\n\r"); - - return p; -} - -void of_exit(void) -{ - of_call_prom("exit", 0, 0); -} - -/* - * OF device tree routines - */ -void *of_finddevice(const char *name) -{ - return (phandle) of_call_prom("finddevice", 1, 1, name); -} - -int of_getprop(const void *phandle, const char *name, void *buf, - const int buflen) -{ - return of_call_prom("getprop", 4, 1, phandle, name, buf, buflen); -} - -int of_setprop(const void *phandle, const char *name, const void *buf, - const int buflen) -{ - return of_call_prom("setprop", 4, 1, phandle, name, buf, buflen); -} diff --git a/trunk/arch/powerpc/boot/ops.h b/trunk/arch/powerpc/boot/ops.h index 86077066cd7c..959124f3f9af 100644 --- a/trunk/arch/powerpc/boot/ops.h +++ b/trunk/arch/powerpc/boot/ops.h @@ -19,8 +19,6 @@ #define MAX_PATH_LEN 256 #define MAX_PROP_LEN 256 /* What should this be? */ -typedef void (*kernel_entry_t)(unsigned long r3, unsigned long r4, void *r5); - /* Platform specific operations */ struct platform_ops { void (*fixups)(void); @@ -53,7 +51,7 @@ extern struct dt_ops dt_ops; /* Console operations */ struct console_ops { int (*open)(void); - void (*write)(const char *buf, int len); + void (*write)(char *buf, int len); void (*edit_cmdline)(char *buf, int len); void (*close)(void); void *data; diff --git a/trunk/arch/powerpc/boot/ps3-head.S b/trunk/arch/powerpc/boot/ps3-head.S deleted file mode 100644 index 1a6d64a68df5..000000000000 --- a/trunk/arch/powerpc/boot/ps3-head.S +++ /dev/null @@ -1,80 +0,0 @@ -/* - * PS3 bootwrapper entry. - * - * Copyright (C) 2007 Sony Computer Entertainment Inc. - * Copyright 2007 Sony Corp. - * - * 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; version 2 of the License. - * - * 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 "ppc_asm.h" - - .text - -/* - * __system_reset_overlay - The PS3 first stage entry. - * - * The bootwraper build script copies the 0x100 bytes at symbol - * __system_reset_overlay to offset 0x100 of the rom image. - * - * The PS3 has a single processor with two threads. - */ - - .globl __system_reset_overlay -__system_reset_overlay: - - /* Switch to 32-bit mode. */ - - mfmsr r9 - clrldi r9,r9,1 - mtmsrd r9 - nop - - /* Get thread number in r3 and branch. */ - - mfspr r3, 0x88 - cntlzw. r3, r3 - li r4, 0 - li r5, 0 - beq 1f - - /* Secondary goes to __secondary_hold in kernel. */ - - li r4, 0x60 - mtctr r4 - bctr - - /* Primary delays then goes to _zimage_start in wrapper. */ -1: - or 31, 31, 31 /* db16cyc */ - or 31, 31, 31 /* db16cyc */ - - lis r4, _zimage_start@ha - addi r4, r4, _zimage_start@l - mtctr r4 - bctr - -/* - * __system_reset_kernel - Place holder for the kernel reset vector. - * - * The bootwrapper build script copies 0x100 bytes from offset 0x100 - * of the rom image to the symbol __system_reset_kernel. At runtime - * the bootwrapper program copies the 0x100 bytes at __system_reset_kernel - * to ram address 0x100. This symbol must occupy 0x100 bytes. - */ - - .globl __system_reset_kernel -__system_reset_kernel: - - . = __system_reset_kernel + 0x100 diff --git a/trunk/arch/powerpc/boot/ps3-hvcall.S b/trunk/arch/powerpc/boot/ps3-hvcall.S deleted file mode 100644 index c8b7df3210d1..000000000000 --- a/trunk/arch/powerpc/boot/ps3-hvcall.S +++ /dev/null @@ -1,184 +0,0 @@ -/* - * PS3 bootwrapper hvcalls. - * - * Copyright (C) 2007 Sony Computer Entertainment Inc. - * Copyright 2007 Sony Corp. - * - * 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; version 2 of the License. - * - * 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 "ppc_asm.h" - -/* - * The PS3 hypervisor uses a 64 bit "C" language calling convention. - * The routines here marshal arguments between the 32 bit wrapper - * program and the 64 bit hvcalls. - * - * wrapper lv1 - * 32-bit (h,l) 64-bit - * - * 1: r3,r4 <-> r3 - * 2: r5,r6 <-> r4 - * 3: r7,r8 <-> r5 - * 4: r9,r10 <-> r6 - * 5: 8(r1),12(r1) <-> r7 - * 6: 16(r1),20(r1) <-> r8 - * 7: 24(r1),28(r1) <-> r9 - * 8: 32(r1),36(r1) <-> r10 - * - */ - -.macro GLOBAL name - .section ".text" - .balign 4 - .globl \name -\name: -.endm - -.macro NO_SUPPORT name - GLOBAL \name - b ps3_no_support -.endm - -.macro HVCALL num - li r11, \num - .long 0x44000022 - extsw r3, r3 -.endm - -.macro SAVE_LR offset=4 - mflr r0 - stw r0, \offset(r1) -.endm - -.macro LOAD_LR offset=4 - lwz r0, \offset(r1) - mtlr r0 -.endm - -.macro LOAD_64_REG target,high,low - sldi r11, \high, 32 - or \target, r11, \low -.endm - -.macro LOAD_64_STACK target,offset - ld \target, \offset(r1) -.endm - -.macro LOAD_R3 - LOAD_64_REG r3,r3,r4 -.endm - -.macro LOAD_R4 - LOAD_64_REG r4,r5,r6 -.endm - -.macro LOAD_R5 - LOAD_64_REG r5,r7,r8 -.endm - -.macro LOAD_R6 - LOAD_64_REG r6,r9,r10 -.endm - -.macro LOAD_R7 - LOAD_64_STACK r7,8 -.endm - -.macro LOAD_R8 - LOAD_64_STACK r8,16 -.endm - -.macro LOAD_R9 - LOAD_64_STACK r9,24 -.endm - -.macro LOAD_R10 - LOAD_64_STACK r10,32 -.endm - -.macro LOAD_REGS_0 - stwu 1,-16(1) - stw 3, 8(1) -.endm - -.macro LOAD_REGS_5 - LOAD_R3 - LOAD_R4 - LOAD_R5 - LOAD_R6 - LOAD_R7 -.endm - -.macro LOAD_REGS_6 - LOAD_REGS_5 - LOAD_R8 -.endm - -.macro LOAD_REGS_8 - LOAD_REGS_6 - LOAD_R9 - LOAD_R10 -.endm - -.macro STORE_REGS_0_1 - lwz r11, 8(r1) - std r4, 0(r11) - mr r4, r3 - li r3, 0 - addi r1,r1,16 -.endm - -.macro STORE_REGS_5_2 - lwz r11, 16(r1) - std r4, 0(r11) - lwz r11, 24(r1) - std r5, 0(r11) -.endm - -.macro STORE_REGS_6_1 - lwz r11, 24(r1) - std r4, 0(r11) -.endm - -GLOBAL lv1_get_logical_ppe_id - SAVE_LR - LOAD_REGS_0 - HVCALL 69 - STORE_REGS_0_1 - LOAD_LR - blr - -GLOBAL lv1_get_logical_partition_id - SAVE_LR - LOAD_REGS_0 - HVCALL 74 - STORE_REGS_0_1 - LOAD_LR - blr - -GLOBAL lv1_get_repository_node_value - SAVE_LR - LOAD_REGS_5 - HVCALL 91 - STORE_REGS_5_2 - LOAD_LR - blr - -GLOBAL lv1_panic - SAVE_LR - LOAD_REGS_8 - HVCALL 255 - LOAD_LR - blr diff --git a/trunk/arch/powerpc/boot/ps3.c b/trunk/arch/powerpc/boot/ps3.c deleted file mode 100644 index 893d59339c26..000000000000 --- a/trunk/arch/powerpc/boot/ps3.c +++ /dev/null @@ -1,161 +0,0 @@ -/* - * PS3 bootwrapper support. - * - * Copyright (C) 2007 Sony Computer Entertainment Inc. - * Copyright 2007 Sony Corp. - * - * 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; version 2 of the License. - * - * 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 "types.h" -#include "elf.h" -#include "string.h" -#include "stdio.h" -#include "page.h" -#include "ops.h" - -extern s64 lv1_panic(u64 in_1); -extern s64 lv1_get_logical_partition_id(u64 *out_1); -extern s64 lv1_get_logical_ppe_id(u64 *out_1); -extern s64 lv1_get_repository_node_value(u64 in_1, u64 in_2, u64 in_3, - u64 in_4, u64 in_5, u64 *out_1, u64 *out_2); - -#ifdef DEBUG -#define DBG(fmt...) printf(fmt) -#else -static inline int __attribute__ ((format (printf, 1, 2))) DBG( - const char *fmt, ...) {return 0;} -#endif - -BSS_STACK(4096); - -/* A buffer that may be edited by tools operating on a zImage binary so as to - * edit the command line passed to vmlinux (by setting /chosen/bootargs). - * The buffer is put in it's own section so that tools may locate it easier. - */ -static char cmdline[COMMAND_LINE_SIZE] - __attribute__((__section__("__builtin_cmdline"))); - -static void prep_cmdline(void *chosen) -{ - if (cmdline[0] == '\0') - getprop(chosen, "bootargs", cmdline, COMMAND_LINE_SIZE-1); - else - setprop_str(chosen, "bootargs", cmdline); - - printf("cmdline: '%s'\n", cmdline); -} - -static void ps3_console_write(const char *buf, int len) -{ -} - -static void ps3_exit(void) -{ - printf("ps3_exit\n"); - - /* lv1_panic will shutdown the lpar. */ - - lv1_panic(0); /* zero = do not reboot */ - while (1); -} - -static int ps3_repository_read_rm_size(u64 *rm_size) -{ - s64 result; - u64 lpar_id; - u64 ppe_id; - u64 v2; - - result = lv1_get_logical_partition_id(&lpar_id); - - if (result) - return -1; - - result = lv1_get_logical_ppe_id(&ppe_id); - - if (result) - return -1; - - /* - * n1: 0000000062690000 : ....bi.. - * n2: 7075000000000000 : pu...... - * n3: 0000000000000001 : ........ - * n4: 726d5f73697a6500 : rm_size. - */ - - result = lv1_get_repository_node_value(lpar_id, 0x0000000062690000ULL, - 0x7075000000000000ULL, ppe_id, 0x726d5f73697a6500ULL, rm_size, - &v2); - - printf("%s:%d: ppe_id %lu \n", __func__, __LINE__, - (unsigned long)ppe_id); - printf("%s:%d: lpar_id %lu \n", __func__, __LINE__, - (unsigned long)lpar_id); - printf("%s:%d: rm_size %llxh \n", __func__, __LINE__, *rm_size); - - return result ? -1 : 0; -} - -void ps3_copy_vectors(void) -{ - extern char __system_reset_kernel[]; - - memcpy((void *)0x100, __system_reset_kernel, 0x100); - flush_cache((void *)0x100, 0x100); -} - -void platform_init(void) -{ - extern char _end[]; - extern char _dtb_start[]; - extern char _initrd_start[]; - extern char _initrd_end[]; - const u32 heapsize = 0x1000000 - (u32)_end; /* 16MiB */ - void *chosen; - unsigned long ft_addr; - u64 rm_size; - - console_ops.write = ps3_console_write; - platform_ops.exit = ps3_exit; - - printf("\n-- PS3 bootwrapper --\n"); - - simple_alloc_init(_end, heapsize, 32, 64); - ft_init(_dtb_start, 0, 4); - - chosen = finddevice("/chosen"); - - ps3_repository_read_rm_size(&rm_size); - dt_fixup_memory(0, rm_size); - - if (_initrd_end > _initrd_start) { - setprop_val(chosen, "linux,initrd-start", (u32)(_initrd_start)); - setprop_val(chosen, "linux,initrd-end", (u32)(_initrd_end)); - } - - prep_cmdline(chosen); - - ft_addr = dt_ops.finalize(); - - ps3_copy_vectors(); - - printf(" flat tree at 0x%lx\n\r", ft_addr); - - ((kernel_entry_t)0)(ft_addr, 0, NULL); - - ps3_exit(); -} diff --git a/trunk/arch/powerpc/boot/serial.c b/trunk/arch/powerpc/boot/serial.c index eaa0d3ae3518..7fd32330a9a5 100644 --- a/trunk/arch/powerpc/boot/serial.c +++ b/trunk/arch/powerpc/boot/serial.c @@ -27,7 +27,7 @@ static int serial_open(void) return scdp->open(); } -static void serial_write(const char *buf, int len) +static void serial_write(char *buf, int len) { struct serial_console_data *scdp = console_ops.data; diff --git a/trunk/arch/powerpc/boot/stdio.c b/trunk/arch/powerpc/boot/stdio.c index 5b57800bbc67..0a9feeb98342 100644 --- a/trunk/arch/powerpc/boot/stdio.c +++ b/trunk/arch/powerpc/boot/stdio.c @@ -190,11 +190,7 @@ int vsprintf(char *buf, const char *fmt, va_list args) /* get the conversion qualifier */ qualifier = -1; - if (*fmt == 'l' && *(fmt + 1) == 'l') { - qualifier = 'q'; - fmt += 2; - } else if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' - || *fmt == 'Z') { + if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' || *fmt =='Z') { qualifier = *fmt; ++fmt; } @@ -285,10 +281,6 @@ int vsprintf(char *buf, const char *fmt, va_list args) num = va_arg(args, unsigned long); if (flags & SIGN) num = (signed long) num; - } else if (qualifier == 'q') { - num = va_arg(args, unsigned long long); - if (flags & SIGN) - num = (signed long long) num; } else if (qualifier == 'Z') { num = va_arg(args, size_t); } else if (qualifier == 'h') { diff --git a/trunk/arch/powerpc/boot/types.h b/trunk/arch/powerpc/boot/types.h index 31393d17a9c1..79d26e708677 100644 --- a/trunk/arch/powerpc/boot/types.h +++ b/trunk/arch/powerpc/boot/types.h @@ -7,10 +7,6 @@ typedef unsigned char u8; typedef unsigned short u16; typedef unsigned int u32; typedef unsigned long long u64; -typedef signed char s8; -typedef short s16; -typedef int s32; -typedef long long s64; #define min(x,y) ({ \ typeof(x) _x = (x); \ diff --git a/trunk/arch/powerpc/boot/wrapper b/trunk/arch/powerpc/boot/wrapper index 65f685479175..da77adc73078 100755 --- a/trunk/arch/powerpc/boot/wrapper +++ b/trunk/arch/powerpc/boot/wrapper @@ -144,15 +144,6 @@ miboot|uboot) cuboot*) gzip= ;; -ps3) - platformo="$object/ps3-head.o $object/ps3-hvcall.o $object/ps3.o" - lds=$object/zImage.ps3.lds - gzip= - ext=bin - objflags="-O binary --set-section-flags=.bss=contents,alloc,load,data" - ksection=.kernel:vmlinux.bin - isection=.kernel:initrd - ;; esac vmz="$tmpdir/`basename \"$kernel\"`.$ext" @@ -248,50 +239,4 @@ treeboot*) fi exit 0 ;; -ps3) - # The ps3's loader supports loading gzipped binary images from flash - # rom to addr zero. The loader enters the image at addr 0x100. A - # bootwrapper overlay is use to arrange for the kernel to be loaded - # to addr zero and to have a suitable bootwrapper entry at 0x100. - # To construct the rom image, 0x100 bytes from offset 0x100 in the - # kernel is copied to the bootwrapper symbol __system_reset_kernel. - # The 0x100 bytes at the bootwrapper symbol __system_reset_overlay is - # then copied to offset 0x100. At runtime the bootwrapper program - # copies the 0x100 bytes at __system_reset_kernel to addr 0x100. - - system_reset_overlay=0x`${CROSS}nm "$ofile" \ - | grep ' __system_reset_overlay$' \ - | cut -d' ' -f1` - system_reset_overlay=`printf "%d" $system_reset_overlay` - system_reset_kernel=0x`${CROSS}nm "$ofile" \ - | grep ' __system_reset_kernel$' \ - | cut -d' ' -f1` - system_reset_kernel=`printf "%d" $system_reset_kernel` - overlay_dest="256" - overlay_size="256" - - rm -f "$object/otheros.bld" - - ${CROSS}objcopy -O binary "$ofile" "$ofile.bin" - - msg=$(dd if="$ofile.bin" of="$ofile.bin" conv=notrunc \ - skip=$overlay_dest seek=$system_reset_kernel \ - count=$overlay_size bs=1 2>&1) - - if [ $? -ne "0" ]; then - echo $msg - exit 1 - fi - - msg=$(dd if="$ofile.bin" of="$ofile.bin" conv=notrunc \ - skip=$system_reset_overlay seek=$overlay_dest \ - count=$overlay_size bs=1 2>&1) - - if [ $? -ne "0" ]; then - echo $msg - exit 2 - fi - - gzip --force -9 --stdout "$ofile.bin" > "$object/otheros.bld" - ;; esac diff --git a/trunk/arch/powerpc/boot/zImage.ps3.lds.S b/trunk/arch/powerpc/boot/zImage.ps3.lds.S deleted file mode 100644 index aaa469c1e60d..000000000000 --- a/trunk/arch/powerpc/boot/zImage.ps3.lds.S +++ /dev/null @@ -1,50 +0,0 @@ -OUTPUT_ARCH(powerpc:common) -ENTRY(_zimage_start) -EXTERN(_zimage_start) -SECTIONS -{ - _vmlinux_start = .; - .kernel:vmlinux.bin : { *(.kernel:vmlinux.bin) } - _vmlinux_end = .; - - . = ALIGN(4096); - _dtb_start = .; - .kernel:dtb : { *(.kernel:dtb) } - _dtb_end = .; - - . = ALIGN(4096); - _initrd_start = .; - .kernel:initrd : { *(.kernel:initrd) } - _initrd_end = .; - - _start = .; - .text : - { - *(.text) - *(.fixup) - } - _etext = .; - . = ALIGN(4096); - .data : - { - *(.rodata*) - *(.data*) - *(.sdata*) - __got2_start = .; - *(.got2) - __got2_end = .; - } - - . = ALIGN(4096); - _edata = .; - - . = ALIGN(4096); - __bss_start = .; - .bss : - { - *(.sbss) - *(.bss) - } - . = ALIGN(4096); - _end = . ; -} diff --git a/trunk/arch/powerpc/configs/holly_defconfig b/trunk/arch/powerpc/configs/holly_defconfig index 04b94f884aae..32781849ad4c 100644 --- a/trunk/arch/powerpc/configs/holly_defconfig +++ b/trunk/arch/powerpc/configs/holly_defconfig @@ -190,12 +190,10 @@ CONFIG_SPLIT_PTLOCK_CPUS=4 # CONFIG_RESOURCES_64BIT is not set CONFIG_ZONE_DMA_FLAG=1 CONFIG_PROC_DEVICETREE=y -CONFIG_CMDLINE_BOOL=y -CONFIG_CMDLINE="console=ttyS0,115200" +# CONFIG_CMDLINE_BOOL is not set # CONFIG_PM is not set # CONFIG_SECCOMP is not set -CONFIG_WANT_DEVICE_TREE=y -CONFIG_DEVICE_TREE="holly.dts" +# CONFIG_WANT_DEVICE_TREE is not set CONFIG_ISA_DMA_API=y # diff --git a/trunk/arch/powerpc/configs/ps3_defconfig b/trunk/arch/powerpc/configs/ps3_defconfig index d0b43df44426..956d1df61e0f 100644 --- a/trunk/arch/powerpc/configs/ps3_defconfig +++ b/trunk/arch/powerpc/configs/ps3_defconfig @@ -156,11 +156,7 @@ CONFIG_PS3_HTAB_SIZE=20 CONFIG_PS3_USE_LPAR_ADDR=y CONFIG_PS3_VUART=y CONFIG_PS3_PS3AV=y -CONFIG_PS3_SYS_MANAGER=m -CONFIG_PS3_STORAGE=y -CONFIG_PS3_DISK=y -CONFIG_PS3_ROM=y -CONFIG_PS3_FLASH=y +CONFIG_PS3_SYS_MANAGER=y CONFIG_PPC_CELL=y # CONFIG_PPC_CELL_NATIVE is not set # CONFIG_PPC_IBM_CELL_BLADE is not set @@ -339,7 +335,7 @@ CONFIG_BT=m CONFIG_BT_L2CAP=m CONFIG_BT_SCO=m CONFIG_BT_RFCOMM=m -CONFIG_BT_RFCOMM_TTY=y +# CONFIG_BT_RFCOMM_TTY is not set # CONFIG_BT_BNEP is not set CONFIG_BT_HIDP=m @@ -348,9 +344,7 @@ CONFIG_BT_HIDP=m # CONFIG_BT_HCIUSB=m CONFIG_BT_HCIUSB_SCO=y -CONFIG_BT_HCIUART=m -CONFIG_BT_HCIUART_H4=y -CONFIG_BT_HCIUART_BCSP=y +# CONFIG_BT_HCIUART is not set # CONFIG_BT_HCIBCM203X is not set # CONFIG_BT_HCIBPA10X is not set # CONFIG_BT_HCIBFUSB is not set @@ -441,7 +435,7 @@ CONFIG_CHR_DEV_SG=m # # Some SCSI devices (e.g. CD jukebox) support multiple LUNs # -CONFIG_SCSI_MULTI_LUN=y +# 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 @@ -485,7 +479,6 @@ CONFIG_NETDEVICES=y CONFIG_MII=m CONFIG_NETDEV_1000=y CONFIG_NETDEV_10000=y -CONFIG_GELIC_NET=y # # Wireless LAN @@ -553,27 +546,7 @@ CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 # # CONFIG_INPUT_KEYBOARD is not set # CONFIG_INPUT_MOUSE is not set -CONFIG_INPUT_JOYSTICK=y -# CONFIG_JOYSTICK_ANALOG is not set -# CONFIG_JOYSTICK_A3D is not set -# CONFIG_JOYSTICK_ADI is not set -# CONFIG_JOYSTICK_COBRA is not set -# CONFIG_JOYSTICK_GF2K is not set -# CONFIG_JOYSTICK_GRIP is not set -# CONFIG_JOYSTICK_GRIP_MP is not set -# CONFIG_JOYSTICK_GUILLEMOT is not set -# CONFIG_JOYSTICK_INTERACT is not set -# CONFIG_JOYSTICK_SIDEWINDER is not set -# CONFIG_JOYSTICK_TMDC is not set -# CONFIG_JOYSTICK_IFORCE is not set -# CONFIG_JOYSTICK_WARRIOR is not set -# CONFIG_JOYSTICK_MAGELLAN is not set -# CONFIG_JOYSTICK_SPACEORB is not set -# CONFIG_JOYSTICK_SPACEBALL is not set -# CONFIG_JOYSTICK_STINGER is not set -# CONFIG_JOYSTICK_TWIDJOY is not set -# CONFIG_JOYSTICK_JOYDUMP is not set -# CONFIG_JOYSTICK_XPAD 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 @@ -590,7 +563,7 @@ CONFIG_INPUT_JOYSTICK=y CONFIG_VT=y CONFIG_VT_CONSOLE=y CONFIG_HW_CONSOLE=y -CONFIG_VT_HW_CONSOLE_BINDING=y +# CONFIG_VT_HW_CONSOLE_BINDING is not set # CONFIG_SERIAL_NONSTANDARD is not set # @@ -1113,7 +1086,7 @@ CONFIG_HAS_DMA=y # # CONFIG_PRINTK_TIME is not set CONFIG_ENABLE_MUST_CHECK=y -CONFIG_MAGIC_SYSRQ=y +# CONFIG_MAGIC_SYSRQ is not set # CONFIG_UNUSED_SYMBOLS is not set # CONFIG_DEBUG_FS is not set # CONFIG_HEADERS_CHECK is not set @@ -1143,7 +1116,16 @@ CONFIG_DEBUG_STACKOVERFLOW=y # CONFIG_DEBUGGER is not set CONFIG_IRQSTACKS=y # CONFIG_BOOTX_TEXT is not set -# CONFIG_PPC_EARLY_DEBUG is not set +CONFIG_PPC_EARLY_DEBUG=y +# CONFIG_PPC_EARLY_DEBUG_LPAR is not set +# CONFIG_PPC_EARLY_DEBUG_G5 is not set +# CONFIG_PPC_EARLY_DEBUG_RTAS_PANEL is not set +# CONFIG_PPC_EARLY_DEBUG_RTAS_CONSOLE is not set +# CONFIG_PPC_EARLY_DEBUG_MAPLE is not set +# CONFIG_PPC_EARLY_DEBUG_ISERIES is not set +# CONFIG_PPC_EARLY_DEBUG_PAS_REALMODE is not set +# CONFIG_PPC_EARLY_DEBUG_BEAT is not set +# CONFIG_PPC_EARLY_DEBUG_44x is not set # # Security options diff --git a/trunk/arch/powerpc/kernel/Makefile b/trunk/arch/powerpc/kernel/Makefile index 42c42ecad00c..3e779f07f21b 100644 --- a/trunk/arch/powerpc/kernel/Makefile +++ b/trunk/arch/powerpc/kernel/Makefile @@ -12,8 +12,7 @@ endif obj-y := semaphore.o cputable.o ptrace.o syscalls.o \ irq.o align.o signal_32.o pmc.o vdso.o \ - init_task.o process.o systbl.o idle.o \ - signal.o + init_task.o process.o systbl.o idle.o obj-y += vdso32/ obj-$(CONFIG_PPC64) += setup_64.o binfmt_elf32.o sys_ppc32.o \ signal_64.o ptrace32.o \ @@ -66,9 +65,9 @@ obj-$(CONFIG_PPC_UDBG_16550) += legacy_serial.o udbg_16550.o module-$(CONFIG_PPC64) += module_64.o obj-$(CONFIG_MODULES) += $(module-y) -pci64-$(CONFIG_PPC64) += pci_64.o pci_dn.o isa-bridge.o +pci64-$(CONFIG_PPC64) += pci_64.o pci_dn.o pci32-$(CONFIG_PPC32) := pci_32.o -obj-$(CONFIG_PCI) += $(pci64-y) $(pci32-y) pci-common.o +obj-$(CONFIG_PCI) += $(pci64-y) $(pci32-y) obj-$(CONFIG_PCI_MSI) += msi.o kexec-$(CONFIG_PPC64) := machine_kexec_64.o kexec-$(CONFIG_PPC32) := machine_kexec_32.o diff --git a/trunk/arch/powerpc/kernel/cputable.c b/trunk/arch/powerpc/kernel/cputable.c index b1f8000952f3..b2b5d664d328 100644 --- a/trunk/arch/powerpc/kernel/cputable.c +++ b/trunk/arch/powerpc/kernel/cputable.c @@ -294,21 +294,6 @@ static struct cpu_spec cpu_specs[] = { .oprofile_mmcra_sipr = MMCRA_SIPR, .platform = "power5", }, - { /* Power5++ */ - .pvr_mask = 0xffffff00, - .pvr_value = 0x003b0300, - .cpu_name = "POWER5+ (gs)", - .cpu_features = CPU_FTRS_POWER5, - .cpu_user_features = COMMON_USER_POWER5_PLUS, - .icache_bsize = 128, - .dcache_bsize = 128, - .num_pmcs = 6, - .oprofile_cpu_type = "ppc64/power5++", - .oprofile_type = PPC_OPROFILE_POWER4, - .oprofile_mmcra_sihv = MMCRA_SIHV, - .oprofile_mmcra_sipr = MMCRA_SIPR, - .platform = "power5+", - }, { /* Power5 GS */ .pvr_mask = 0xffff0000, .pvr_value = 0x003b0000, @@ -1193,8 +1178,8 @@ static struct cpu_spec cpu_specs[] = { .platform = "ppc440", }, { /* 440SP Rev. A */ - .pvr_mask = 0xfff00fff, - .pvr_value = 0x53200891, + .pvr_mask = 0xff000fff, + .pvr_value = 0x53000891, .cpu_name = "440SP Rev. A", .cpu_features = CPU_FTRS_44X, .cpu_user_features = COMMON_USER_BOOKE, @@ -1203,19 +1188,9 @@ static struct cpu_spec cpu_specs[] = { .platform = "ppc440", }, { /* 440SPe Rev. A */ - .pvr_mask = 0xfff00fff, - .pvr_value = 0x53400890, - .cpu_name = "440SPe Rev. A", - .cpu_features = CPU_FTRS_44X, - .cpu_user_features = COMMON_USER_BOOKE, - .icache_bsize = 32, - .dcache_bsize = 32, - .platform = "ppc440", - }, - { /* 440SPe Rev. B */ - .pvr_mask = 0xfff00fff, - .pvr_value = 0x53400891, - .cpu_name = "440SPe Rev. B", + .pvr_mask = 0xff000fff, + .pvr_value = 0x53000890, + .cpu_name = "440SPe Rev. A", .cpu_features = CPU_FTRS_44X, .cpu_user_features = COMMON_USER_BOOKE, .icache_bsize = 32, diff --git a/trunk/arch/powerpc/kernel/head_32.S b/trunk/arch/powerpc/kernel/head_32.S index 7d73a13450b0..c897203198b1 100644 --- a/trunk/arch/powerpc/kernel/head_32.S +++ b/trunk/arch/powerpc/kernel/head_32.S @@ -9,6 +9,7 @@ * rewritten by Paul Mackerras. * Copyright (C) 1996 Paul Mackerras. * MPC8xx modifications Copyright (C) 1997 Dan Malek (dmalek@jlc.net). + * Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk). * * This file contains the low-level support and setup for the * PowerPC platform, including trap and interrupt dispatch. @@ -31,6 +32,10 @@ #include #include +#ifdef CONFIG_APUS +#include +#endif + /* 601 only have IBAT; cr0.eq is set on 601 when using this macro */ #define LOAD_BAT(n, reg, RA, RB) \ /* see the comment for clear_bats() -- Cort */ \ @@ -87,6 +92,11 @@ _start: * r4: virtual address of boot_infos_t * r5: 0 * + * APUS + * r3: 'APUS' + * r4: physical address of memory base + * Linux/m68k style BootInfo structure at &_end. + * * PREP * This is jumped to on prep systems right after the kernel is relocated * to its proper place in memory by the boot loader. The expected layout @@ -140,6 +150,14 @@ __start: */ bl early_init +#ifdef CONFIG_APUS +/* On APUS the __va/__pa constants need to be set to the correct + * values before continuing. + */ + mr r4,r30 + bl fix_mem_constants +#endif /* CONFIG_APUS */ + /* Switch MMU off, clear BATs and flush TLB. At this point, r3 contains * the physical address we are running at, returned by early_init() */ @@ -149,7 +167,7 @@ __after_mmu_off: bl flush_tlbs bl initial_bats -#if defined(CONFIG_BOOTX_TEXT) +#if !defined(CONFIG_APUS) && defined(CONFIG_BOOTX_TEXT) bl setup_disp_bat #endif @@ -165,6 +183,7 @@ __after_mmu_off: #endif /* CONFIG_6xx */ +#ifndef CONFIG_APUS /* * We need to run with _start at physical address 0. * On CHRP, we are loaded at 0x10000 since OF on CHRP uses @@ -177,6 +196,7 @@ __after_mmu_off: addis r4,r3,KERNELBASE@h /* current address of _start */ cmpwi 0,r4,0 /* are we already running at 0? */ bne relocate_kernel +#endif /* CONFIG_APUS */ /* * we now have the 1st 16M of ram mapped with the bats. * prep needs the mmu to be turned on here, but pmac already has it on. @@ -861,6 +881,85 @@ _GLOBAL(copy_and_flush) addi r6,r6,4 blr +#ifdef CONFIG_APUS +/* + * On APUS the physical base address of the kernel is not known at compile + * time, which means the __pa/__va constants used are incorrect. In the + * __init section is recorded the virtual addresses of instructions using + * these constants, so all that has to be done is fix these before + * continuing the kernel boot. + * + * r4 = The physical address of the kernel base. + */ +fix_mem_constants: + mr r10,r4 + addis r10,r10,-KERNELBASE@h /* virt_to_phys constant */ + neg r11,r10 /* phys_to_virt constant */ + + lis r12,__vtop_table_begin@h + ori r12,r12,__vtop_table_begin@l + add r12,r12,r10 /* table begin phys address */ + lis r13,__vtop_table_end@h + ori r13,r13,__vtop_table_end@l + add r13,r13,r10 /* table end phys address */ + subi r12,r12,4 + subi r13,r13,4 +1: lwzu r14,4(r12) /* virt address of instruction */ + add r14,r14,r10 /* phys address of instruction */ + lwz r15,0(r14) /* instruction, now insert top */ + rlwimi r15,r10,16,16,31 /* half of vp const in low half */ + stw r15,0(r14) /* of instruction and restore. */ + dcbst r0,r14 /* write it to memory */ + sync + icbi r0,r14 /* flush the icache line */ + cmpw r12,r13 + bne 1b + sync /* additional sync needed on g4 */ + isync + +/* + * Map the memory where the exception handlers will + * be copied to when hash constants have been patched. + */ +#ifdef CONFIG_APUS_FAST_EXCEPT + lis r8,0xfff0 +#else + lis r8,0 +#endif + ori r8,r8,0x2 /* 128KB, supervisor */ + mtspr SPRN_DBAT3U,r8 + mtspr SPRN_DBAT3L,r8 + + lis r12,__ptov_table_begin@h + ori r12,r12,__ptov_table_begin@l + add r12,r12,r10 /* table begin phys address */ + lis r13,__ptov_table_end@h + ori r13,r13,__ptov_table_end@l + add r13,r13,r10 /* table end phys address */ + subi r12,r12,4 + subi r13,r13,4 +1: lwzu r14,4(r12) /* virt address of instruction */ + add r14,r14,r10 /* phys address of instruction */ + lwz r15,0(r14) /* instruction, now insert top */ + rlwimi r15,r11,16,16,31 /* half of pv const in low half*/ + stw r15,0(r14) /* of instruction and restore. */ + dcbst r0,r14 /* write it to memory */ + sync + icbi r0,r14 /* flush the icache line */ + cmpw r12,r13 + bne 1b + + sync /* additional sync needed on g4 */ + isync /* No speculative loading until now */ + blr + +/*********************************************************************** + * Please note that on APUS the exception handlers are located at the + * physical address 0xfff0000. For this reason, the exception handlers + * cannot use relative branches to access the code below. + ***********************************************************************/ +#endif /* CONFIG_APUS */ + #ifdef CONFIG_SMP #ifdef CONFIG_GEMINI .globl __secondary_start_gemini @@ -1036,6 +1135,19 @@ start_here: bl __save_cpu_setup bl MMU_init +#ifdef CONFIG_APUS + /* Copy exception code to exception vector base on APUS. */ + lis r4,KERNELBASE@h +#ifdef CONFIG_APUS_FAST_EXCEPT + lis r3,0xfff0 /* Copy to 0xfff00000 */ +#else + lis r3,0 /* Copy to 0x00000000 */ +#endif + li r5,0x4000 /* # bytes of memory to copy */ + li r6,0 + bl copy_and_flush /* copy the first 0x4000 bytes */ +#endif /* CONFIG_APUS */ + /* * Go back to running unmapped so we can load up new values * for SDR1 (hash table pointer) and the segment registers @@ -1212,7 +1324,11 @@ initial_bats: #else ori r8,r8,2 /* R/W access */ #endif /* CONFIG_SMP */ +#ifdef CONFIG_APUS + ori r11,r11,BL_8M<<2|0x2 /* set up 8MB BAT registers for 604 */ +#else ori r11,r11,BL_256M<<2|0x2 /* set up BAT registers for 604 */ +#endif /* CONFIG_APUS */ mtspr SPRN_DBAT0L,r8 /* N.B. 6xx (not 601) have valid */ mtspr SPRN_DBAT0U,r11 /* bit in upper BAT register */ @@ -1222,7 +1338,7 @@ initial_bats: blr -#ifdef CONFIG_BOOTX_TEXT +#if !defined(CONFIG_APUS) && defined(CONFIG_BOOTX_TEXT) setup_disp_bat: /* * setup the display bat prepared for us in prom.c @@ -1246,7 +1362,7 @@ setup_disp_bat: 1: mtspr SPRN_IBAT3L,r8 mtspr SPRN_IBAT3U,r11 blr -#endif /* CONFIG_BOOTX_TEXT */ +#endif /* !defined(CONFIG_APUS) && defined(CONFIG_BOOTX_TEXT) */ #ifdef CONFIG_8260 /* Jump into the system reset for the rom. diff --git a/trunk/arch/powerpc/kernel/head_64.S b/trunk/arch/powerpc/kernel/head_64.S index 8cdd48ea4391..1111fcec7673 100644 --- a/trunk/arch/powerpc/kernel/head_64.S +++ b/trunk/arch/powerpc/kernel/head_64.S @@ -103,8 +103,8 @@ __secondary_hold_acknowledge: . = 0x60 /* - * The following code is used to hold secondary processors - * in a spin loop after they have entered the kernel, but + * The following code is used on pSeries to hold secondary processors + * in a spin loop after they have been freed from OpenFirmware, but * before the bulk of the kernel has been relocated. This code * is relocated to physical address 0x60 before prom_init is run. * All of it must fit below the first exception vector at 0x100. diff --git a/trunk/arch/powerpc/kernel/io.c b/trunk/arch/powerpc/kernel/io.c index e31aca9208eb..34ae11494ddc 100644 --- a/trunk/arch/powerpc/kernel/io.c +++ b/trunk/arch/powerpc/kernel/io.c @@ -35,7 +35,7 @@ void _insb(const volatile u8 __iomem *port, void *buf, long count) asm volatile("sync"); do { tmp = *port; - eieio(); + asm volatile("eieio"); *tbuf++ = tmp; } while (--count != 0); asm volatile("twi 0,%0,0; isync" : : "r" (tmp)); @@ -66,7 +66,7 @@ void _insw_ns(const volatile u16 __iomem *port, void *buf, long count) asm volatile("sync"); do { tmp = *port; - eieio(); + asm volatile("eieio"); *tbuf++ = tmp; } while (--count != 0); asm volatile("twi 0,%0,0; isync" : : "r" (tmp)); @@ -97,7 +97,7 @@ void _insl_ns(const volatile u32 __iomem *port, void *buf, long count) asm volatile("sync"); do { tmp = *port; - eieio(); + asm volatile("eieio"); *tbuf++ = tmp; } while (--count != 0); asm volatile("twi 0,%0,0; isync" : : "r" (tmp)); @@ -155,21 +155,21 @@ void _memcpy_fromio(void *dest, const volatile void __iomem *src, __asm__ __volatile__ ("sync" : : : "memory"); while(n && (!IO_CHECK_ALIGN(vsrc, 4) || !IO_CHECK_ALIGN(dest, 4))) { *((u8 *)dest) = *((volatile u8 *)vsrc); - eieio(); + __asm__ __volatile__ ("eieio" : : : "memory"); vsrc++; dest++; n--; } while(n > 4) { *((u32 *)dest) = *((volatile u32 *)vsrc); - eieio(); + __asm__ __volatile__ ("eieio" : : : "memory"); vsrc += 4; dest += 4; n -= 4; } while(n) { *((u8 *)dest) = *((volatile u8 *)vsrc); - eieio(); + __asm__ __volatile__ ("eieio" : : : "memory"); vsrc++; dest++; n--; diff --git a/trunk/arch/powerpc/kernel/irq.c b/trunk/arch/powerpc/kernel/irq.c index 2fc87862146c..c2b84c64db20 100644 --- a/trunk/arch/powerpc/kernel/irq.c +++ b/trunk/arch/powerpc/kernel/irq.c @@ -7,6 +7,7 @@ * Copyright (C) 1996-2001 Cort Dougan * Adapted for Power Macintosh by Paul Mackerras * Copyright (C) 1996 Paul Mackerras (paulus@cs.anu.edu.au) + * Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk). * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -336,8 +337,7 @@ void do_IRQ(struct pt_regs *regs) void __init init_IRQ(void) { - if (ppc_md.init_IRQ) - ppc_md.init_IRQ(); + ppc_md.init_IRQ(); #ifdef CONFIG_PPC64 irq_ctx_init(); #endif @@ -597,49 +597,6 @@ static void irq_radix_rdunlock(unsigned long flags) local_irq_restore(flags); } -static int irq_setup_virq(struct irq_host *host, unsigned int virq, - irq_hw_number_t hwirq) -{ - /* Clear IRQ_NOREQUEST flag */ - get_irq_desc(virq)->status &= ~IRQ_NOREQUEST; - - /* map it */ - smp_wmb(); - irq_map[virq].hwirq = hwirq; - smp_mb(); - - if (host->ops->map(host, virq, hwirq)) { - pr_debug("irq: -> mapping failed, freeing\n"); - irq_free_virt(virq, 1); - return -1; - } - - return 0; -} - -unsigned int irq_create_direct_mapping(struct irq_host *host) -{ - unsigned int virq; - - if (host == NULL) - host = irq_default_host; - - BUG_ON(host == NULL); - WARN_ON(host->revmap_type != IRQ_HOST_MAP_NOMAP); - - virq = irq_alloc_virt(host, 1, 0); - if (virq == NO_IRQ) { - pr_debug("irq: create_direct virq allocation failed\n"); - return NO_IRQ; - } - - pr_debug("irq: create_direct obtained virq %d\n", virq); - - if (irq_setup_virq(host, virq, virq)) - return NO_IRQ; - - return virq; -} unsigned int irq_create_mapping(struct irq_host *host, irq_hw_number_t hwirq) @@ -688,9 +645,18 @@ unsigned int irq_create_mapping(struct irq_host *host, } pr_debug("irq: -> obtained virq %d\n", virq); - if (irq_setup_virq(host, virq, hwirq)) - return NO_IRQ; + /* Clear IRQ_NOREQUEST flag */ + get_irq_desc(virq)->status &= ~IRQ_NOREQUEST; + /* map it */ + smp_wmb(); + irq_map[virq].hwirq = hwirq; + smp_mb(); + if (host->ops->map(host, virq, hwirq)) { + pr_debug("irq: -> mapping failed, freeing\n"); + irq_free_virt(virq, 1); + return NO_IRQ; + } return virq; } EXPORT_SYMBOL_GPL(irq_create_mapping); diff --git a/trunk/arch/powerpc/kernel/isa-bridge.c b/trunk/arch/powerpc/kernel/isa-bridge.c deleted file mode 100644 index f0f49d1be3d5..000000000000 --- a/trunk/arch/powerpc/kernel/isa-bridge.c +++ /dev/null @@ -1,271 +0,0 @@ -/* - * Routines for tracking a legacy ISA bridge - * - * Copyrigh 2007 Benjamin Herrenschmidt , IBM Corp. - * - * Some bits and pieces moved over from pci_64.c - * - * Copyrigh 2003 Anton Blanchard , IBM Corp. - * - * 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. - */ - -#define DEBUG - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -unsigned long isa_io_base; /* NULL if no ISA bus */ -EXPORT_SYMBOL(isa_io_base); - -/* Cached ISA bridge dev. */ -static struct device_node *isa_bridge_devnode; -struct pci_dev *isa_bridge_pcidev; -EXPORT_SYMBOL_GPL(isa_bridge_pcidev); - -#define ISA_SPACE_MASK 0x1 -#define ISA_SPACE_IO 0x1 - -static void __devinit pci_process_ISA_OF_ranges(struct device_node *isa_node, - unsigned long phb_io_base_phys) -{ - /* We should get some saner parsing here and remove these structs */ - struct pci_address { - u32 a_hi; - u32 a_mid; - u32 a_lo; - }; - - struct isa_address { - u32 a_hi; - u32 a_lo; - }; - - struct isa_range { - struct isa_address isa_addr; - struct pci_address pci_addr; - unsigned int size; - }; - - const struct isa_range *range; - unsigned long pci_addr; - unsigned int isa_addr; - unsigned int size; - int rlen = 0; - - range = of_get_property(isa_node, "ranges", &rlen); - if (range == NULL || (rlen < sizeof(struct isa_range))) - goto inval_range; - - /* From "ISA Binding to 1275" - * The ranges property is laid out as an array of elements, - * each of which comprises: - * cells 0 - 1: an ISA address - * cells 2 - 4: a PCI address - * (size depending on dev->n_addr_cells) - * cell 5: the size of the range - */ - if ((range->isa_addr.a_hi && ISA_SPACE_MASK) != ISA_SPACE_IO) { - range++; - rlen -= sizeof(struct isa_range); - if (rlen < sizeof(struct isa_range)) - goto inval_range; - } - if ((range->isa_addr.a_hi && ISA_SPACE_MASK) != ISA_SPACE_IO) - goto inval_range; - - isa_addr = range->isa_addr.a_lo; - pci_addr = (unsigned long) range->pci_addr.a_mid << 32 | - range->pci_addr.a_lo; - - /* Assume these are both zero. Note: We could fix that and - * do a proper parsing instead ... oh well, that will do for - * now as nobody uses fancy mappings for ISA bridges - */ - if ((pci_addr != 0) || (isa_addr != 0)) { - printk(KERN_ERR "unexpected isa to pci mapping: %s\n", - __FUNCTION__); - return; - } - - /* Align size and make sure it's cropped to 64K */ - size = PAGE_ALIGN(range->size); - if (size > 0x10000) - size = 0x10000; - - printk(KERN_ERR "no ISA IO ranges or unexpected isa range," - "mapping 64k\n"); - - __ioremap_at(phb_io_base_phys, (void *)ISA_IO_BASE, - size, _PAGE_NO_CACHE|_PAGE_GUARDED); - return; - -inval_range: - printk(KERN_ERR "no ISA IO ranges or unexpected isa range," - "mapping 64k\n"); - __ioremap_at(phb_io_base_phys, (void *)ISA_IO_BASE, - 0x10000, _PAGE_NO_CACHE|_PAGE_GUARDED); -} - - -/** - * isa_bridge_find_early - Find and map the ISA IO space early before - * main PCI discovery. This is optionally called by - * the arch code when adding PCI PHBs to get early - * access to ISA IO ports - */ -void __init isa_bridge_find_early(struct pci_controller *hose) -{ - struct device_node *np, *parent = NULL, *tmp; - - /* If we already have an ISA bridge, bail off */ - if (isa_bridge_devnode != NULL) - return; - - /* For each "isa" node in the system. Note : we do a search by - * type and not by name. It might be better to do by name but that's - * what the code used to do and I don't want to break too much at - * once. We can look into changing that separately - */ - for_each_node_by_type(np, "isa") { - /* Look for our hose being a parent */ - for (parent = of_get_parent(np); parent;) { - if (parent == hose->arch_data) { - of_node_put(parent); - break; - } - tmp = parent; - parent = of_get_parent(parent); - of_node_put(tmp); - } - if (parent != NULL) - break; - } - if (np == NULL) - return; - isa_bridge_devnode = np; - - /* Now parse the "ranges" property and setup the ISA mapping */ - pci_process_ISA_OF_ranges(np, hose->io_base_phys); - - /* Set the global ISA io base to indicate we have an ISA bridge */ - isa_io_base = ISA_IO_BASE; - - pr_debug("ISA bridge (early) is %s\n", np->full_name); -} - -/** - * isa_bridge_find_late - Find and map the ISA IO space upon discovery of - * a new ISA bridge - */ -static void __devinit isa_bridge_find_late(struct pci_dev *pdev, - struct device_node *devnode) -{ - struct pci_controller *hose = pci_bus_to_host(pdev->bus); - - /* Store ISA device node and PCI device */ - isa_bridge_devnode = of_node_get(devnode); - isa_bridge_pcidev = pdev; - - /* Now parse the "ranges" property and setup the ISA mapping */ - pci_process_ISA_OF_ranges(devnode, hose->io_base_phys); - - /* Set the global ISA io base to indicate we have an ISA bridge */ - isa_io_base = ISA_IO_BASE; - - pr_debug("ISA bridge (late) is %s on %s\n", - devnode->full_name, pci_name(pdev)); -} - -/** - * isa_bridge_remove - Remove/unmap an ISA bridge - */ -static void isa_bridge_remove(void) -{ - pr_debug("ISA bridge removed !\n"); - - /* Clear the global ISA io base to indicate that we have no more - * ISA bridge. Note that drivers don't quite handle that, though - * we should probably do something about it. But do we ever really - * have ISA bridges being removed on machines using legacy devices ? - */ - isa_io_base = ISA_IO_BASE; - - /* Clear references to the bridge */ - of_node_put(isa_bridge_devnode); - isa_bridge_devnode = NULL; - isa_bridge_pcidev = NULL; - - /* Unmap the ISA area */ - __iounmap_at((void *)ISA_IO_BASE, 0x10000); -} - -/** - * isa_bridge_notify - Get notified of PCI devices addition/removal - */ -static int __devinit isa_bridge_notify(struct notifier_block *nb, - unsigned long action, void *data) -{ - struct device *dev = data; - struct pci_dev *pdev = to_pci_dev(dev); - struct device_node *devnode = pci_device_to_OF_node(pdev); - - switch(action) { - case BUS_NOTIFY_ADD_DEVICE: - /* Check if we have an early ISA device, without PCI dev */ - if (isa_bridge_devnode && isa_bridge_devnode == devnode && - !isa_bridge_pcidev) { - pr_debug("ISA bridge PCI attached: %s\n", - pci_name(pdev)); - isa_bridge_pcidev = pdev; - } - - /* Check if we have no ISA device, and this happens to be one, - * register it as such if it has an OF device - */ - if (!isa_bridge_devnode && devnode && devnode->type && - !strcmp(devnode->type, "isa")) - isa_bridge_find_late(pdev, devnode); - - return 0; - case BUS_NOTIFY_DEL_DEVICE: - /* Check if this our existing ISA device */ - if (pdev == isa_bridge_pcidev || - (devnode && devnode == isa_bridge_devnode)) - isa_bridge_remove(); - return 0; - } - return 0; -} - -static struct notifier_block isa_bridge_notifier = { - .notifier_call = isa_bridge_notify -}; - -/** - * isa_bridge_init - register to be notified of ISA bridge addition/removal - * - */ -static int __init isa_bridge_init(void) -{ - if (firmware_has_feature(FW_FEATURE_ISERIES)) - return 0; - bus_register_notifier(&pci_bus_type, &isa_bridge_notifier); - return 0; -} -arch_initcall(isa_bridge_init); diff --git a/trunk/arch/powerpc/kernel/misc_32.S b/trunk/arch/powerpc/kernel/misc_32.S index e708ab7ca9e8..98decf8ebff4 100644 --- a/trunk/arch/powerpc/kernel/misc_32.S +++ b/trunk/arch/powerpc/kernel/misc_32.S @@ -392,7 +392,7 @@ BEGIN_FTR_SECTION mtspr SPRN_L1CSR0,r3 isync blr -END_FTR_SECTION_IFSET(CPU_FTR_UNIFIED_ID_CACHE) +END_FTR_SECTION_IFCLR(CPU_FTR_SPLIT_ID_CACHE) mfspr r3,SPRN_L1CSR1 ori r3,r3,L1CSR1_ICFI|L1CSR1_ICLFR mtspr SPRN_L1CSR1,r3 @@ -419,7 +419,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_UNIFIED_ID_CACHE) _GLOBAL(__flush_icache_range) BEGIN_FTR_SECTION blr /* for 601, do nothing */ -END_FTR_SECTION_IFSET(CPU_FTR_COHERENT_ICACHE) +END_FTR_SECTION_IFCLR(CPU_FTR_SPLIT_ID_CACHE) li r5,L1_CACHE_BYTES-1 andc r3,r3,r5 subf r4,r3,r4 @@ -514,8 +514,8 @@ _GLOBAL(invalidate_dcache_range) */ _GLOBAL(__flush_dcache_icache) BEGIN_FTR_SECTION - blr -END_FTR_SECTION_IFSET(CPU_FTR_COHERENT_ICACHE) + blr /* for 601, do nothing */ +END_FTR_SECTION_IFCLR(CPU_FTR_SPLIT_ID_CACHE) rlwinm r3,r3,0,0,19 /* Get page base address */ li r4,4096/L1_CACHE_BYTES /* Number of lines in a page */ mtctr r4 @@ -543,7 +543,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_COHERENT_ICACHE) _GLOBAL(__flush_dcache_icache_phys) BEGIN_FTR_SECTION blr /* for 601, do nothing */ -END_FTR_SECTION_IFSET(CPU_FTR_COHERENT_ICACHE) +END_FTR_SECTION_IFCLR(CPU_FTR_SPLIT_ID_CACHE) mfmsr r10 rlwinm r0,r10,0,28,26 /* clear DR */ mtmsr r0 diff --git a/trunk/arch/powerpc/kernel/misc_64.S b/trunk/arch/powerpc/kernel/misc_64.S index bbb3ba54c51c..519861da0423 100644 --- a/trunk/arch/powerpc/kernel/misc_64.S +++ b/trunk/arch/powerpc/kernel/misc_64.S @@ -646,19 +646,6 @@ _GLOBAL(kexec_sequence) /* turn off mmu */ bl real_mode - /* copy 0x100 bytes starting at start to 0 */ - li r3,0 - mr r4,r30 /* start, aka phys mem offset */ - li r5,0x100 - li r6,0 - bl .copy_and_flush /* (dest, src, copy limit, start offset) */ -1: /* assume normal blr return */ - - /* release other cpus to the new kernel secondary start at 0x60 */ - mflr r5 - li r6,1 - stw r6,kexec_flag-1b(5) - /* clear out hardware hash page table and tlb */ ld r5,0(r27) /* deref function descriptor */ mtctr r5 @@ -689,6 +676,19 @@ _GLOBAL(kexec_sequence) * are the boot cpu ????? * other device tree differences (prop sizes, va vs pa, etc)... */ + + /* copy 0x100 bytes starting at start to 0 */ + li r3,0 + mr r4,r30 + li r5,0x100 + li r6,0 + bl .copy_and_flush /* (dest, src, copy limit, start offset) */ +1: /* assume normal blr return */ + + /* release other cpus to the new kernel secondary start at 0x60 */ + mflr r5 + li r6,1 + stw r6,kexec_flag-1b(5) mr r3,r25 # my phys cpu mr r4,r30 # start, aka phys mem offset mtlr 4 diff --git a/trunk/arch/powerpc/kernel/of_platform.c b/trunk/arch/powerpc/kernel/of_platform.c index 9536ed7f247c..d454f61c9c7c 100644 --- a/trunk/arch/powerpc/kernel/of_platform.c +++ b/trunk/arch/powerpc/kernel/of_platform.c @@ -427,6 +427,14 @@ static int __devinit of_pci_phb_probe(struct of_device *dev, /* Process "ranges" property */ pci_process_bridge_OF_ranges(phb, dev->node, 0); + /* Setup IO space. We use the non-dynamic version of that code here, + * which doesn't quite support unplugging. Next kernel release will + * have a better fix for this. + * Note also that we don't do ISA, this will also be fixed with a + * more massive rework. + */ + pci_setup_phb_io(phb, pci_io_base == 0); + /* Init pci_dn data structures */ pci_devs_phb_init_dynamic(phb); diff --git a/trunk/arch/powerpc/kernel/pci-common.c b/trunk/arch/powerpc/kernel/pci-common.c deleted file mode 100644 index faf5ef3e90d0..000000000000 --- a/trunk/arch/powerpc/kernel/pci-common.c +++ /dev/null @@ -1,454 +0,0 @@ -/* - * Contains common pci routines for ALL ppc platform - * (based on pci_32.c and pci_64.c) - * - * Port for PPC64 David Engebretsen, IBM Corp. - * Contains common pci routines for ppc64 platform, pSeries and iSeries brands. - * - * Copyright (C) 2003 Anton Blanchard , IBM - * Rework, based on alpha PCI code. - * - * Common pmac/prep/chrp pci routines. -- Cort - * - * 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. - */ - -#undef DEBUG - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef DEBUG -#include -#define DBG(fmt...) printk(fmt) -#else -#define DBG(fmt...) -#endif - -static DEFINE_SPINLOCK(hose_spinlock); - -/* XXX kill that some day ... */ -int global_phb_number; /* Global phb counter */ - -extern struct list_head hose_list; - -/* - * pci_controller(phb) initialized common variables. - */ -static void __devinit pci_setup_pci_controller(struct pci_controller *hose) -{ - memset(hose, 0, sizeof(struct pci_controller)); - - spin_lock(&hose_spinlock); - hose->global_number = global_phb_number++; - list_add_tail(&hose->list_node, &hose_list); - spin_unlock(&hose_spinlock); -} - -struct pci_controller * pcibios_alloc_controller(struct device_node *dev) -{ - struct pci_controller *phb; - - if (mem_init_done) - phb = kmalloc(sizeof(struct pci_controller), GFP_KERNEL); - else - phb = alloc_bootmem(sizeof (struct pci_controller)); - if (phb == NULL) - return NULL; - pci_setup_pci_controller(phb); - phb->arch_data = dev; - phb->is_dynamic = mem_init_done; -#ifdef CONFIG_PPC64 - if (dev) { - int nid = of_node_to_nid(dev); - - if (nid < 0 || !node_online(nid)) - nid = -1; - - PHB_SET_NODE(phb, nid); - } -#endif - return phb; -} - -void pcibios_free_controller(struct pci_controller *phb) -{ - spin_lock(&hose_spinlock); - list_del(&phb->list_node); - spin_unlock(&hose_spinlock); - - if (phb->is_dynamic) - kfree(phb); -} - -/* - * Return the domain number for this bus. - */ -int pci_domain_nr(struct pci_bus *bus) -{ - if (firmware_has_feature(FW_FEATURE_ISERIES)) - return 0; - else { - struct pci_controller *hose = pci_bus_to_host(bus); - - return hose->global_number; - } -} - -EXPORT_SYMBOL(pci_domain_nr); - -#ifdef CONFIG_PPC_OF - -/* This routine is meant to be used early during boot, when the - * PCI bus numbers have not yet been assigned, and you need to - * issue PCI config cycles to an OF device. - * It could also be used to "fix" RTAS config cycles if you want - * to set pci_assign_all_buses to 1 and still use RTAS for PCI - * config cycles. - */ -struct pci_controller* pci_find_hose_for_OF_device(struct device_node* node) -{ - if (!have_of) - return NULL; - while(node) { - struct pci_controller *hose, *tmp; - list_for_each_entry_safe(hose, tmp, &hose_list, list_node) - if (hose->arch_data == node) - return hose; - node = node->parent; - } - return NULL; -} - -static ssize_t pci_show_devspec(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct pci_dev *pdev; - struct device_node *np; - - pdev = to_pci_dev (dev); - np = pci_device_to_OF_node(pdev); - if (np == NULL || np->full_name == NULL) - return 0; - return sprintf(buf, "%s", np->full_name); -} -static DEVICE_ATTR(devspec, S_IRUGO, pci_show_devspec, NULL); -#endif /* CONFIG_PPC_OF */ - -/* Add sysfs properties */ -void pcibios_add_platform_entries(struct pci_dev *pdev) -{ -#ifdef CONFIG_PPC_OF - device_create_file(&pdev->dev, &dev_attr_devspec); -#endif /* CONFIG_PPC_OF */ -} - -char __init *pcibios_setup(char *str) -{ - return str; -} - -/* - * Reads the interrupt pin to determine if interrupt is use by card. - * If the interrupt is used, then gets the interrupt line from the - * openfirmware and sets it in the pci_dev and pci_config line. - */ -int pci_read_irq_line(struct pci_dev *pci_dev) -{ - struct of_irq oirq; - unsigned int virq; - - DBG("Try to map irq for %s...\n", pci_name(pci_dev)); - -#ifdef DEBUG - memset(&oirq, 0xff, sizeof(oirq)); -#endif - /* Try to get a mapping from the device-tree */ - if (of_irq_map_pci(pci_dev, &oirq)) { - u8 line, pin; - - /* If that fails, lets fallback to what is in the config - * space and map that through the default controller. We - * also set the type to level low since that's what PCI - * interrupts are. If your platform does differently, then - * either provide a proper interrupt tree or don't use this - * function. - */ - if (pci_read_config_byte(pci_dev, PCI_INTERRUPT_PIN, &pin)) - return -1; - if (pin == 0) - return -1; - if (pci_read_config_byte(pci_dev, PCI_INTERRUPT_LINE, &line) || - line == 0xff) { - return -1; - } - DBG(" -> no map ! Using irq line %d from PCI config\n", line); - - virq = irq_create_mapping(NULL, line); - if (virq != NO_IRQ) - set_irq_type(virq, IRQ_TYPE_LEVEL_LOW); - } else { - DBG(" -> got one, spec %d cells (0x%08x 0x%08x...) on %s\n", - oirq.size, oirq.specifier[0], oirq.specifier[1], - oirq.controller->full_name); - - virq = irq_create_of_mapping(oirq.controller, oirq.specifier, - oirq.size); - } - if(virq == NO_IRQ) { - DBG(" -> failed to map !\n"); - return -1; - } - - DBG(" -> mapped to linux irq %d\n", virq); - - pci_dev->irq = virq; - - return 0; -} -EXPORT_SYMBOL(pci_read_irq_line); - -/* - * Platform support for /proc/bus/pci/X/Y mmap()s, - * modelled on the sparc64 implementation by Dave Miller. - * -- paulus. - */ - -/* - * Adjust vm_pgoff of VMA such that it is the physical page offset - * corresponding to the 32-bit pci bus offset for DEV requested by the user. - * - * Basically, the user finds the base address for his device which he wishes - * to mmap. They read the 32-bit value from the config space base register, - * add whatever PAGE_SIZE multiple offset they wish, and feed this into the - * offset parameter of mmap on /proc/bus/pci/XXX for that device. - * - * Returns negative error code on failure, zero on success. - */ -static struct resource *__pci_mmap_make_offset(struct pci_dev *dev, - resource_size_t *offset, - enum pci_mmap_state mmap_state) -{ - struct pci_controller *hose = pci_bus_to_host(dev->bus); - unsigned long io_offset = 0; - int i, res_bit; - - if (hose == 0) - return NULL; /* should never happen */ - - /* If memory, add on the PCI bridge address offset */ - if (mmap_state == pci_mmap_mem) { -#if 0 /* See comment in pci_resource_to_user() for why this is disabled */ - *offset += hose->pci_mem_offset; -#endif - res_bit = IORESOURCE_MEM; - } else { - io_offset = (unsigned long)hose->io_base_virt - _IO_BASE; - *offset += io_offset; - res_bit = IORESOURCE_IO; - } - - /* - * Check that the offset requested corresponds to one of the - * resources of the device. - */ - for (i = 0; i <= PCI_ROM_RESOURCE; i++) { - struct resource *rp = &dev->resource[i]; - int flags = rp->flags; - - /* treat ROM as memory (should be already) */ - if (i == PCI_ROM_RESOURCE) - flags |= IORESOURCE_MEM; - - /* Active and same type? */ - if ((flags & res_bit) == 0) - continue; - - /* In the range of this resource? */ - if (*offset < (rp->start & PAGE_MASK) || *offset > rp->end) - continue; - - /* found it! construct the final physical address */ - if (mmap_state == pci_mmap_io) - *offset += hose->io_base_phys - io_offset; - return rp; - } - - return NULL; -} - -/* - * Set vm_page_prot of VMA, as appropriate for this architecture, for a pci - * device mapping. - */ -static pgprot_t __pci_mmap_set_pgprot(struct pci_dev *dev, struct resource *rp, - pgprot_t protection, - enum pci_mmap_state mmap_state, - int write_combine) -{ - unsigned long prot = pgprot_val(protection); - - /* Write combine is always 0 on non-memory space mappings. On - * memory space, if the user didn't pass 1, we check for a - * "prefetchable" resource. This is a bit hackish, but we use - * this to workaround the inability of /sysfs to provide a write - * combine bit - */ - if (mmap_state != pci_mmap_mem) - write_combine = 0; - else if (write_combine == 0) { - if (rp->flags & IORESOURCE_PREFETCH) - write_combine = 1; - } - - /* XXX would be nice to have a way to ask for write-through */ - prot |= _PAGE_NO_CACHE; - if (write_combine) - prot &= ~_PAGE_GUARDED; - else - prot |= _PAGE_GUARDED; - - return __pgprot(prot); -} - -/* - * This one is used by /dev/mem and fbdev who have no clue about the - * PCI device, it tries to find the PCI device first and calls the - * above routine - */ -pgprot_t pci_phys_mem_access_prot(struct file *file, - unsigned long pfn, - unsigned long size, - pgprot_t protection) -{ - struct pci_dev *pdev = NULL; - struct resource *found = NULL; - unsigned long prot = pgprot_val(protection); - unsigned long offset = pfn << PAGE_SHIFT; - int i; - - if (page_is_ram(pfn)) - return __pgprot(prot); - - prot |= _PAGE_NO_CACHE | _PAGE_GUARDED; - - for_each_pci_dev(pdev) { - for (i = 0; i <= PCI_ROM_RESOURCE; i++) { - struct resource *rp = &pdev->resource[i]; - int flags = rp->flags; - - /* Active and same type? */ - if ((flags & IORESOURCE_MEM) == 0) - continue; - /* In the range of this resource? */ - if (offset < (rp->start & PAGE_MASK) || - offset > rp->end) - continue; - found = rp; - break; - } - if (found) - break; - } - if (found) { - if (found->flags & IORESOURCE_PREFETCH) - prot &= ~_PAGE_GUARDED; - pci_dev_put(pdev); - } - - DBG("non-PCI map for %lx, prot: %lx\n", offset, prot); - - return __pgprot(prot); -} - - -/* - * Perform the actual remap of the pages for a PCI device mapping, as - * appropriate for this architecture. The region in the process to map - * is described by vm_start and vm_end members of VMA, the base physical - * address is found in vm_pgoff. - * The pci device structure is provided so that architectures may make mapping - * decisions on a per-device or per-bus basis. - * - * Returns a negative error code on failure, zero on success. - */ -int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma, - enum pci_mmap_state mmap_state, int write_combine) -{ - resource_size_t offset = vma->vm_pgoff << PAGE_SHIFT; - struct resource *rp; - int ret; - - rp = __pci_mmap_make_offset(dev, &offset, mmap_state); - if (rp == NULL) - return -EINVAL; - - vma->vm_pgoff = offset >> PAGE_SHIFT; - vma->vm_page_prot = __pci_mmap_set_pgprot(dev, rp, - vma->vm_page_prot, - mmap_state, write_combine); - - ret = remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff, - vma->vm_end - vma->vm_start, vma->vm_page_prot); - - return ret; -} - -void pci_resource_to_user(const struct pci_dev *dev, int bar, - const struct resource *rsrc, - resource_size_t *start, resource_size_t *end) -{ - struct pci_controller *hose = pci_bus_to_host(dev->bus); - resource_size_t offset = 0; - - if (hose == NULL) - return; - - if (rsrc->flags & IORESOURCE_IO) - offset = (unsigned long)hose->io_base_virt - _IO_BASE; - - /* We pass a fully fixed up address to userland for MMIO instead of - * a BAR value because X is lame and expects to be able to use that - * to pass to /dev/mem ! - * - * That means that we'll have potentially 64 bits values where some - * userland apps only expect 32 (like X itself since it thinks only - * Sparc has 64 bits MMIO) but if we don't do that, we break it on - * 32 bits CHRPs :-( - * - * Hopefully, the sysfs insterface is immune to that gunk. Once X - * has been fixed (and the fix spread enough), we can re-enable the - * 2 lines below and pass down a BAR value to userland. In that case - * we'll also have to re-enable the matching code in - * __pci_mmap_make_offset(). - * - * BenH. - */ -#if 0 - else if (rsrc->flags & IORESOURCE_MEM) - offset = hose->pci_mem_offset; -#endif - - *start = rsrc->start - offset; - *end = rsrc->end - offset; -} diff --git a/trunk/arch/powerpc/kernel/pci_32.c b/trunk/arch/powerpc/kernel/pci_32.c index 0adf077f3f3a..86982112b0dd 100644 --- a/trunk/arch/powerpc/kernel/pci_32.c +++ b/trunk/arch/powerpc/kernel/pci_32.c @@ -55,7 +55,8 @@ static u8* pci_to_OF_bus_map; */ int pci_assign_all_buses; -LIST_HEAD(hose_list); +struct pci_controller* hose_head; +struct pci_controller** hose_tail = &hose_head; static int pci_bus_count; @@ -572,6 +573,58 @@ pcibios_assign_resources(void) } } + +int +pcibios_enable_resources(struct pci_dev *dev, int mask) +{ + u16 cmd, old_cmd; + int idx; + struct resource *r; + + pci_read_config_word(dev, PCI_COMMAND, &cmd); + old_cmd = cmd; + for (idx=0; idx<6; idx++) { + /* Only set up the requested stuff */ + if (!(mask & (1<resource[idx]; + if (r->flags & IORESOURCE_UNSET) { + printk(KERN_ERR "PCI: Device %s not available because of resource collisions\n", pci_name(dev)); + return -EINVAL; + } + if (r->flags & IORESOURCE_IO) + cmd |= PCI_COMMAND_IO; + if (r->flags & IORESOURCE_MEM) + cmd |= PCI_COMMAND_MEMORY; + } + if (dev->resource[PCI_ROM_RESOURCE].start) + cmd |= PCI_COMMAND_MEMORY; + if (cmd != old_cmd) { + printk("PCI: Enabling device %s (%04x -> %04x)\n", pci_name(dev), old_cmd, cmd); + pci_write_config_word(dev, PCI_COMMAND, cmd); + } + return 0; +} + +static int next_controller_index; + +struct pci_controller * __init +pcibios_alloc_controller(void) +{ + struct pci_controller *hose; + + hose = (struct pci_controller *)alloc_bootmem(sizeof(*hose)); + memset(hose, 0, sizeof(struct pci_controller)); + + *hose_tail = hose; + hose_tail = &hose->next; + + hose->index = next_controller_index++; + + return hose; +} + #ifdef CONFIG_PPC_OF /* * Functions below are used on OpenFirmware machines. @@ -617,7 +670,7 @@ void pcibios_make_OF_bus_map(void) { int i; - struct pci_controller *hose, *tmp; + struct pci_controller* hose; struct property *map_prop; struct device_node *dn; @@ -634,7 +687,7 @@ pcibios_make_OF_bus_map(void) pci_to_OF_bus_map[i] = 0xff; /* For each hose, we begin searching bridges */ - list_for_each_entry_safe(hose, tmp, &hose_list, list_node) { + for(hose=hose_head; hose; hose=hose->next) { struct device_node* node; node = (struct device_node *)hose->arch_data; if (!node) @@ -712,7 +765,7 @@ static struct device_node *scan_OF_for_pci_bus(struct pci_bus *bus) /* Are we a root bus ? */ if (bus->self == NULL || bus->parent == NULL) { - struct pci_controller *hose = pci_bus_to_host(bus); + struct pci_controller *hose = pci_bus_to_hose(bus->number); if (hose == NULL) return NULL; return of_node_get(hose->arch_data); @@ -765,6 +818,27 @@ pci_device_to_OF_node(struct pci_dev *dev) } EXPORT_SYMBOL(pci_device_to_OF_node); +/* This routine is meant to be used early during boot, when the + * PCI bus numbers have not yet been assigned, and you need to + * issue PCI config cycles to an OF device. + * It could also be used to "fix" RTAS config cycles if you want + * to set pci_assign_all_buses to 1 and still use RTAS for PCI + * config cycles. + */ +struct pci_controller* pci_find_hose_for_OF_device(struct device_node* node) +{ + if (!have_of) + return NULL; + while(node) { + struct pci_controller* hose; + for (hose=hose_head;hose;hose=hose->next) + if (hose->arch_data == node) + return hose; + node=node->parent; + } + return NULL; +} + static int find_OF_pci_device_filter(struct device_node* node, void* data) { @@ -953,12 +1027,34 @@ pci_create_OF_bus_map(void) } } +static ssize_t pci_show_devspec(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct pci_dev *pdev; + struct device_node *np; + + pdev = to_pci_dev (dev); + np = pci_device_to_OF_node(pdev); + if (np == NULL || np->full_name == NULL) + return 0; + return sprintf(buf, "%s", np->full_name); +} +static DEVICE_ATTR(devspec, S_IRUGO, pci_show_devspec, NULL); + #else /* CONFIG_PPC_OF */ void pcibios_make_OF_bus_map(void) { } #endif /* CONFIG_PPC_OF */ +/* Add sysfs properties */ +int pcibios_add_platform_entries(struct pci_dev *pdev) +{ +#ifdef CONFIG_PPC_OF + return device_create_file(&pdev->dev, &dev_attr_devspec); +#endif /* CONFIG_PPC_OF */ +} + + #ifdef CONFIG_PPC_PMAC /* * This set of routines checks for PCI<->PCI bridges that have closed @@ -1173,14 +1269,14 @@ pcibios_fixup_p2p_bridges(void) static int __init pcibios_init(void) { - struct pci_controller *hose, *tmp; + struct pci_controller *hose; struct pci_bus *bus; - int next_busno = 0; + int next_busno; printk(KERN_INFO "PCI: Probing PCI hardware\n"); /* Scan all of the recorded PCI controllers. */ - list_for_each_entry_safe(hose, tmp, &hose_list, list_node) { + for (next_busno = 0, hose = hose_head; hose; hose = hose->next) { if (pci_assign_all_buses) hose->first_busno = next_busno; hose->last_busno = 0xff; @@ -1223,6 +1319,12 @@ pcibios_init(void) subsys_initcall(pcibios_init); +unsigned long resource_fixup(struct pci_dev * dev, struct resource * res, + unsigned long start, unsigned long size) +{ + return start; +} + void __init pcibios_fixup_bus(struct pci_bus *bus) { struct pci_controller *hose = (struct pci_controller *) bus->sysdata; @@ -1240,7 +1342,7 @@ void __init pcibios_fixup_bus(struct pci_bus *bus) if (!res->flags) { if (io_offset) printk(KERN_ERR "I/O resource not set for host" - " bridge %d\n", hose->global_number); + " bridge %d\n", hose->index); res->start = 0; res->end = IO_SPACE_LIMIT; res->flags = IORESOURCE_IO; @@ -1254,7 +1356,7 @@ void __init pcibios_fixup_bus(struct pci_bus *bus) if (i > 0) continue; printk(KERN_ERR "Memory resource not set for " - "host bridge %d\n", hose->global_number); + "host bridge %d\n", hose->index); res->start = hose->pci_mem_offset; res->end = ~0U; res->flags = IORESOURCE_MEM; @@ -1268,7 +1370,7 @@ void __init pcibios_fixup_bus(struct pci_bus *bus) for (i = 0; i < 4; ++i) { if ((res = bus->resource[i]) == NULL) continue; - if (!res->flags || bus->self->transparent) + if (!res->flags) continue; if (io_offset && (res->flags & IORESOURCE_IO)) { res->start += io_offset; @@ -1293,6 +1395,11 @@ void __init pcibios_fixup_bus(struct pci_bus *bus) } } +char __init *pcibios_setup(char *str) +{ + return str; +} + /* the next one is stolen from the alpha port... */ void __init pcibios_update_irq(struct pci_dev *dev, int irq) @@ -1301,6 +1408,64 @@ pcibios_update_irq(struct pci_dev *dev, int irq) /* XXX FIXME - update OF device tree node interrupt property */ } +#ifdef CONFIG_PPC_MERGE +/* XXX This is a copy of the ppc64 version. This is temporary until we start + * merging the 2 PCI layers + */ +/* + * Reads the interrupt pin to determine if interrupt is use by card. + * If the interrupt is used, then gets the interrupt line from the + * openfirmware and sets it in the pci_dev and pci_config line. + */ +int pci_read_irq_line(struct pci_dev *pci_dev) +{ + struct of_irq oirq; + unsigned int virq; + + DBG("Try to map irq for %s...\n", pci_name(pci_dev)); + + /* Try to get a mapping from the device-tree */ + if (of_irq_map_pci(pci_dev, &oirq)) { + u8 line, pin; + + /* If that fails, lets fallback to what is in the config + * space and map that through the default controller. We + * also set the type to level low since that's what PCI + * interrupts are. If your platform does differently, then + * either provide a proper interrupt tree or don't use this + * function. + */ + if (pci_read_config_byte(pci_dev, PCI_INTERRUPT_PIN, &pin)) + return -1; + if (pin == 0) + return -1; + if (pci_read_config_byte(pci_dev, PCI_INTERRUPT_LINE, &line) || + line == 0xff) { + return -1; + } + DBG(" -> no map ! Using irq line %d from PCI config\n", line); + + virq = irq_create_mapping(NULL, line); + if (virq != NO_IRQ) + set_irq_type(virq, IRQ_TYPE_LEVEL_LOW); + } else { + DBG(" -> got one, spec %d cells (0x%08x...) on %s\n", + oirq.size, oirq.specifier[0], oirq.controller->full_name); + + virq = irq_create_of_mapping(oirq.controller, oirq.specifier, + oirq.size); + } + if(virq == NO_IRQ) { + DBG(" -> failed to map !\n"); + return -1; + } + pci_dev->irq = virq; + + return 0; +} +EXPORT_SYMBOL(pci_read_irq_line); +#endif /* CONFIG_PPC_MERGE */ + int pcibios_enable_device(struct pci_dev *dev, int mask) { u16 cmd, old_cmd; @@ -1332,17 +1497,281 @@ int pcibios_enable_device(struct pci_dev *dev, int mask) return 0; } -static struct pci_controller* +struct pci_controller* pci_bus_to_hose(int bus) { - struct pci_controller *hose, *tmp; + struct pci_controller* hose = hose_head; - list_for_each_entry_safe(hose, tmp, &hose_list, list_node) + for (; hose; hose = hose->next) if (bus >= hose->first_busno && bus <= hose->last_busno) return hose; return NULL; } +void __iomem * +pci_bus_io_base(unsigned int bus) +{ + struct pci_controller *hose; + + hose = pci_bus_to_hose(bus); + if (!hose) + return NULL; + return hose->io_base_virt; +} + +unsigned long +pci_bus_io_base_phys(unsigned int bus) +{ + struct pci_controller *hose; + + hose = pci_bus_to_hose(bus); + if (!hose) + return 0; + return hose->io_base_phys; +} + +unsigned long +pci_bus_mem_base_phys(unsigned int bus) +{ + struct pci_controller *hose; + + hose = pci_bus_to_hose(bus); + if (!hose) + return 0; + return hose->pci_mem_offset; +} + +unsigned long +pci_resource_to_bus(struct pci_dev *pdev, struct resource *res) +{ + /* Hack alert again ! See comments in chrp_pci.c + */ + struct pci_controller* hose = + (struct pci_controller *)pdev->sysdata; + if (hose && res->flags & IORESOURCE_MEM) + return res->start - hose->pci_mem_offset; + /* We may want to do something with IOs here... */ + return res->start; +} + + +static struct resource *__pci_mmap_make_offset(struct pci_dev *dev, + resource_size_t *offset, + enum pci_mmap_state mmap_state) +{ + struct pci_controller *hose = pci_bus_to_hose(dev->bus->number); + unsigned long io_offset = 0; + int i, res_bit; + + if (hose == 0) + return NULL; /* should never happen */ + + /* If memory, add on the PCI bridge address offset */ + if (mmap_state == pci_mmap_mem) { +#if 0 /* See comment in pci_resource_to_user() for why this is disabled */ + *offset += hose->pci_mem_offset; +#endif + res_bit = IORESOURCE_MEM; + } else { + io_offset = hose->io_base_virt - (void __iomem *)_IO_BASE; + *offset += io_offset; + res_bit = IORESOURCE_IO; + } + + /* + * Check that the offset requested corresponds to one of the + * resources of the device. + */ + for (i = 0; i <= PCI_ROM_RESOURCE; i++) { + struct resource *rp = &dev->resource[i]; + int flags = rp->flags; + + /* treat ROM as memory (should be already) */ + if (i == PCI_ROM_RESOURCE) + flags |= IORESOURCE_MEM; + + /* Active and same type? */ + if ((flags & res_bit) == 0) + continue; + + /* In the range of this resource? */ + if (*offset < (rp->start & PAGE_MASK) || *offset > rp->end) + continue; + + /* found it! construct the final physical address */ + if (mmap_state == pci_mmap_io) + *offset += hose->io_base_phys - io_offset; + return rp; + } + + return NULL; +} + +/* + * Set vm_page_prot of VMA, as appropriate for this architecture, for a pci + * device mapping. + */ +static pgprot_t __pci_mmap_set_pgprot(struct pci_dev *dev, struct resource *rp, + pgprot_t protection, + enum pci_mmap_state mmap_state, + int write_combine) +{ + unsigned long prot = pgprot_val(protection); + + /* Write combine is always 0 on non-memory space mappings. On + * memory space, if the user didn't pass 1, we check for a + * "prefetchable" resource. This is a bit hackish, but we use + * this to workaround the inability of /sysfs to provide a write + * combine bit + */ + if (mmap_state != pci_mmap_mem) + write_combine = 0; + else if (write_combine == 0) { + if (rp->flags & IORESOURCE_PREFETCH) + write_combine = 1; + } + + /* XXX would be nice to have a way to ask for write-through */ + prot |= _PAGE_NO_CACHE; + if (write_combine) + prot &= ~_PAGE_GUARDED; + else + prot |= _PAGE_GUARDED; + + return __pgprot(prot); +} + +/* + * This one is used by /dev/mem and fbdev who have no clue about the + * PCI device, it tries to find the PCI device first and calls the + * above routine + */ +pgprot_t pci_phys_mem_access_prot(struct file *file, + unsigned long pfn, + unsigned long size, + pgprot_t protection) +{ + struct pci_dev *pdev = NULL; + struct resource *found = NULL; + unsigned long prot = pgprot_val(protection); + unsigned long offset = pfn << PAGE_SHIFT; + int i; + + if (page_is_ram(pfn)) + return __pgprot(prot); + + prot |= _PAGE_NO_CACHE | _PAGE_GUARDED; + + for_each_pci_dev(pdev) { + for (i = 0; i <= PCI_ROM_RESOURCE; i++) { + struct resource *rp = &pdev->resource[i]; + int flags = rp->flags; + + /* Active and same type? */ + if ((flags & IORESOURCE_MEM) == 0) + continue; + /* In the range of this resource? */ + if (offset < (rp->start & PAGE_MASK) || + offset > rp->end) + continue; + found = rp; + break; + } + if (found) + break; + } + if (found) { + if (found->flags & IORESOURCE_PREFETCH) + prot &= ~_PAGE_GUARDED; + pci_dev_put(pdev); + } + + DBG("non-PCI map for %lx, prot: %lx\n", offset, prot); + + return __pgprot(prot); +} + + +/* + * Perform the actual remap of the pages for a PCI device mapping, as + * appropriate for this architecture. The region in the process to map + * is described by vm_start and vm_end members of VMA, the base physical + * address is found in vm_pgoff. + * The pci device structure is provided so that architectures may make mapping + * decisions on a per-device or per-bus basis. + * + * Returns a negative error code on failure, zero on success. + */ +int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma, + enum pci_mmap_state mmap_state, + int write_combine) +{ + resource_size_t offset = vma->vm_pgoff << PAGE_SHIFT; + struct resource *rp; + int ret; + + rp = __pci_mmap_make_offset(dev, &offset, mmap_state); + if (rp == NULL) + return -EINVAL; + + vma->vm_pgoff = offset >> PAGE_SHIFT; + vma->vm_page_prot = __pci_mmap_set_pgprot(dev, rp, + vma->vm_page_prot, + mmap_state, write_combine); + + ret = remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff, + vma->vm_end - vma->vm_start, vma->vm_page_prot); + + return ret; +} + +/* Obsolete functions. Should be removed once the symbios driver + * is fixed + */ +unsigned long +phys_to_bus(unsigned long pa) +{ + struct pci_controller *hose; + int i; + + for (hose = hose_head; hose; hose = hose->next) { + for (i = 0; i < 3; ++i) { + if (pa >= hose->mem_resources[i].start + && pa <= hose->mem_resources[i].end) { + /* + * XXX the hose->pci_mem_offset really + * only applies to mem_resources[0]. + * We need a way to store an offset for + * the others. -- paulus + */ + if (i == 0) + pa -= hose->pci_mem_offset; + return pa; + } + } + } + /* hmmm, didn't find it */ + return 0; +} + +unsigned long +pci_phys_to_bus(unsigned long pa, int busnr) +{ + struct pci_controller* hose = pci_bus_to_hose(busnr); + if (!hose) + return pa; + return pa - hose->pci_mem_offset; +} + +unsigned long +pci_bus_to_phys(unsigned int ba, int busnr) +{ + struct pci_controller* hose = pci_bus_to_hose(busnr); + if (!hose) + return ba; + return ba + hose->pci_mem_offset; +} + /* Provide information on locations of various I/O regions in physical * memory. Do this on a per-card basis so that we choose the right * root bridge. @@ -1385,11 +1814,62 @@ long sys_pciconfig_iobase(long which, unsigned long bus, unsigned long devfn) return result; } +void pci_resource_to_user(const struct pci_dev *dev, int bar, + const struct resource *rsrc, + resource_size_t *start, resource_size_t *end) +{ + struct pci_controller *hose = pci_bus_to_hose(dev->bus->number); + resource_size_t offset = 0; + + if (hose == NULL) + return; + + if (rsrc->flags & IORESOURCE_IO) + offset = (unsigned long)hose->io_base_virt - _IO_BASE; + + /* We pass a fully fixed up address to userland for MMIO instead of + * a BAR value because X is lame and expects to be able to use that + * to pass to /dev/mem ! + * + * That means that we'll have potentially 64 bits values where some + * userland apps only expect 32 (like X itself since it thinks only + * Sparc has 64 bits MMIO) but if we don't do that, we break it on + * 32 bits CHRPs :-( + * + * Hopefully, the sysfs insterface is immune to that gunk. Once X + * has been fixed (and the fix spread enough), we can re-enable the + * 2 lines below and pass down a BAR value to userland. In that case + * we'll also have to re-enable the matching code in + * __pci_mmap_make_offset(). + * + * BenH. + */ +#if 0 + else if (rsrc->flags & IORESOURCE_MEM) + offset = hose->pci_mem_offset; +#endif + + *start = rsrc->start - offset; + *end = rsrc->end - offset; +} + +void __init pci_init_resource(struct resource *res, resource_size_t start, + resource_size_t end, int flags, char *name) +{ + res->start = start; + res->end = end; + res->flags = flags; + res->name = name; + res->parent = NULL; + res->sibling = NULL; + res->child = NULL; +} + unsigned long pci_address_to_pio(phys_addr_t address) { - struct pci_controller *hose, *tmp; + struct pci_controller* hose = hose_head; - list_for_each_entry_safe(hose, tmp, &hose_list, list_node) { + for (; hose; hose = hose->next) { unsigned int size = hose->io_resource.end - hose->io_resource.start + 1; if (address >= hose->io_base_phys && diff --git a/trunk/arch/powerpc/kernel/pci_64.c b/trunk/arch/powerpc/kernel/pci_64.c index a97e23ac1976..e3009a43ac56 100644 --- a/trunk/arch/powerpc/kernel/pci_64.c +++ b/trunk/arch/powerpc/kernel/pci_64.c @@ -22,7 +22,6 @@ #include #include #include -#include #include #include @@ -42,23 +41,35 @@ unsigned long pci_probe_only = 1; int pci_assign_all_buses = 0; +static int pci_initial_scan_done; static void fixup_resource(struct resource *res, struct pci_dev *dev); static void do_bus_setup(struct pci_bus *bus); +static void phbs_remap_io(void); /* pci_io_base -- the base address from which io bars are offsets. * This is the lowest I/O base address (so bar values are always positive), * and it *must* be the start of ISA space if an ISA bus exists because - * ISA drivers use hard coded offsets. If no ISA bus exists nothing - * is mapped on the first 64K of IO space + * ISA drivers use hard coded offsets. If no ISA bus exists a dummy + * page is mapped and isa_io_limit prevents access to it. */ -unsigned long pci_io_base = ISA_IO_BASE; +unsigned long isa_io_base; /* NULL if no ISA bus */ +EXPORT_SYMBOL(isa_io_base); +unsigned long pci_io_base; EXPORT_SYMBOL(pci_io_base); +void iSeries_pcibios_init(void); + LIST_HEAD(hose_list); static struct dma_mapping_ops *pci_dma_ops; +int global_phb_number; /* Global phb counter */ + +/* Cached ISA bridge dev. */ +struct pci_dev *ppc64_isabridge_dev = NULL; +EXPORT_SYMBOL_GPL(ppc64_isabridge_dev); + void set_pci_dma_ops(struct dma_mapping_ops *dma_ops) { pci_dma_ops = dma_ops; @@ -89,7 +100,7 @@ void pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region return; if (res->flags & IORESOURCE_IO) - offset = (unsigned long)hose->io_base_virt - _IO_BASE; + offset = (unsigned long)hose->io_base_virt - pci_io_base; if (res->flags & IORESOURCE_MEM) offset = hose->pci_mem_offset; @@ -108,7 +119,7 @@ void pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res, return; if (res->flags & IORESOURCE_IO) - offset = (unsigned long)hose->io_base_virt - _IO_BASE; + offset = (unsigned long)hose->io_base_virt - pci_io_base; if (res->flags & IORESOURCE_MEM) offset = hose->pci_mem_offset; @@ -145,7 +156,7 @@ void pcibios_align_resource(void *data, struct resource *res, if (res->flags & IORESOURCE_IO) { unsigned long offset = (unsigned long)hose->io_base_virt - - _IO_BASE; + pci_io_base; /* Make sure we start at our min on all hoses */ if (start - offset < PCIBIOS_MIN_IO) start = PCIBIOS_MIN_IO + offset; @@ -169,6 +180,55 @@ void pcibios_align_resource(void *data, struct resource *res, res->start = start; } +static DEFINE_SPINLOCK(hose_spinlock); + +/* + * pci_controller(phb) initialized common variables. + */ +static void __devinit pci_setup_pci_controller(struct pci_controller *hose) +{ + memset(hose, 0, sizeof(struct pci_controller)); + + spin_lock(&hose_spinlock); + hose->global_number = global_phb_number++; + list_add_tail(&hose->list_node, &hose_list); + spin_unlock(&hose_spinlock); +} + +struct pci_controller * pcibios_alloc_controller(struct device_node *dev) +{ + struct pci_controller *phb; + + if (mem_init_done) + phb = kmalloc(sizeof(struct pci_controller), GFP_KERNEL); + else + phb = alloc_bootmem(sizeof (struct pci_controller)); + if (phb == NULL) + return NULL; + pci_setup_pci_controller(phb); + phb->arch_data = dev; + phb->is_dynamic = mem_init_done; + if (dev) { + int nid = of_node_to_nid(dev); + + if (nid < 0 || !node_online(nid)) + nid = -1; + + PHB_SET_NODE(phb, nid); + } + return phb; +} + +void pcibios_free_controller(struct pci_controller *phb) +{ + spin_lock(&hose_spinlock); + list_del(&phb->list_node); + spin_unlock(&hose_spinlock); + + if (phb->is_dynamic) + kfree(phb); +} + void __devinit pcibios_claim_one_bus(struct pci_bus *b) { struct pci_dev *dev; @@ -231,6 +291,7 @@ static unsigned int pci_parse_of_flags(u32 addr0) return flags; } +#define GET_64BIT(prop, i) ((((u64) (prop)[(i)]) << 32) | (prop)[(i)+1]) static void pci_parse_of_addrs(struct device_node *node, struct pci_dev *dev) { @@ -249,8 +310,8 @@ static void pci_parse_of_addrs(struct device_node *node, struct pci_dev *dev) flags = pci_parse_of_flags(addrs[0]); if (!flags) continue; - base = of_read_number(&addrs[1], 2); - size = of_read_number(&addrs[3], 2); + base = GET_64BIT(addrs, 1); + size = GET_64BIT(addrs, 3); if (!size) continue; i = addrs[0] & 0xff; @@ -418,7 +479,7 @@ void __devinit of_scan_pci_bridge(struct device_node *node, i = 1; for (; len >= 32; len -= 32, ranges += 8) { flags = pci_parse_of_flags(ranges[0]); - size = of_read_number(&ranges[6], 2); + size = GET_64BIT(ranges, 6); if (flags == 0 || size == 0) continue; if (flags & IORESOURCE_IO) { @@ -437,7 +498,7 @@ void __devinit of_scan_pci_bridge(struct device_node *node, res = bus->resource[i]; ++i; } - res->start = of_read_number(&ranges[1], 2); + res->start = GET_64BIT(ranges, 1); res->end = res->start + size - 1; res->flags = flags; fixup_resource(res, dev); @@ -476,16 +537,10 @@ void __devinit scan_phb(struct pci_controller *hose) bus->secondary = hose->first_busno; hose->bus = bus; - if (!firmware_has_feature(FW_FEATURE_ISERIES)) - pcibios_map_io_space(bus); - bus->resource[0] = res = &hose->io_resource; - if (res->flags && request_resource(&ioport_resource, res)) { + if (res->flags && request_resource(&ioport_resource, res)) printk(KERN_ERR "Failed to request PCI IO region " "on PCI domain %04x\n", hose->global_number); - DBG("res->start = 0x%016lx, res->end = 0x%016lx\n", - res->start, res->end); - } for (i = 0; i < 3; ++i) { res = &hose->mem_resources[i]; @@ -543,6 +598,17 @@ static int __init pcibios_init(void) if (ppc_md.pcibios_fixup) ppc_md.pcibios_fixup(); + /* Cache the location of the ISA bridge (if we have one) */ + ppc64_isabridge_dev = pci_get_class(PCI_CLASS_BRIDGE_ISA << 8, NULL); + if (ppc64_isabridge_dev != NULL) + printk(KERN_DEBUG "ISA bridge at %s\n", pci_name(ppc64_isabridge_dev)); + + if (!firmware_has_feature(FW_FEATURE_ISERIES)) + /* map in PCI I/O space */ + phbs_remap_io(); + + pci_initial_scan_done = 1; + printk(KERN_DEBUG "PCI: Probing PCI hardware done\n"); return 0; @@ -550,6 +616,11 @@ static int __init pcibios_init(void) subsys_initcall(pcibios_init); +char __init *pcibios_setup(char *str) +{ + return str; +} + int pcibios_enable_device(struct pci_dev *dev, int mask) { u16 cmd, oldcmd; @@ -580,6 +651,22 @@ int pcibios_enable_device(struct pci_dev *dev, int mask) return 0; } +/* + * Return the domain number for this bus. + */ +int pci_domain_nr(struct pci_bus *bus) +{ + if (firmware_has_feature(FW_FEATURE_ISERIES)) + return 0; + else { + struct pci_controller *hose = pci_bus_to_host(bus); + + return hose->global_number; + } +} + +EXPORT_SYMBOL(pci_domain_nr); + /* Decide whether to display the domain number in /proc */ int pci_proc_domain(struct pci_bus *bus) { @@ -591,6 +678,281 @@ int pci_proc_domain(struct pci_bus *bus) } } +/* + * Platform support for /proc/bus/pci/X/Y mmap()s, + * modelled on the sparc64 implementation by Dave Miller. + * -- paulus. + */ + +/* + * Adjust vm_pgoff of VMA such that it is the physical page offset + * corresponding to the 32-bit pci bus offset for DEV requested by the user. + * + * Basically, the user finds the base address for his device which he wishes + * to mmap. They read the 32-bit value from the config space base register, + * add whatever PAGE_SIZE multiple offset they wish, and feed this into the + * offset parameter of mmap on /proc/bus/pci/XXX for that device. + * + * Returns negative error code on failure, zero on success. + */ +static struct resource *__pci_mmap_make_offset(struct pci_dev *dev, + resource_size_t *offset, + enum pci_mmap_state mmap_state) +{ + struct pci_controller *hose = pci_bus_to_host(dev->bus); + unsigned long io_offset = 0; + int i, res_bit; + + if (hose == 0) + return NULL; /* should never happen */ + + /* If memory, add on the PCI bridge address offset */ + if (mmap_state == pci_mmap_mem) { +#if 0 /* See comment in pci_resource_to_user() for why this is disabled */ + *offset += hose->pci_mem_offset; +#endif + res_bit = IORESOURCE_MEM; + } else { + io_offset = (unsigned long)hose->io_base_virt - pci_io_base; + *offset += io_offset; + res_bit = IORESOURCE_IO; + } + + /* + * Check that the offset requested corresponds to one of the + * resources of the device. + */ + for (i = 0; i <= PCI_ROM_RESOURCE; i++) { + struct resource *rp = &dev->resource[i]; + int flags = rp->flags; + + /* treat ROM as memory (should be already) */ + if (i == PCI_ROM_RESOURCE) + flags |= IORESOURCE_MEM; + + /* Active and same type? */ + if ((flags & res_bit) == 0) + continue; + + /* In the range of this resource? */ + if (*offset < (rp->start & PAGE_MASK) || *offset > rp->end) + continue; + + /* found it! construct the final physical address */ + if (mmap_state == pci_mmap_io) + *offset += hose->io_base_phys - io_offset; + return rp; + } + + return NULL; +} + +/* + * Set vm_page_prot of VMA, as appropriate for this architecture, for a pci + * device mapping. + */ +static pgprot_t __pci_mmap_set_pgprot(struct pci_dev *dev, struct resource *rp, + pgprot_t protection, + enum pci_mmap_state mmap_state, + int write_combine) +{ + unsigned long prot = pgprot_val(protection); + + /* Write combine is always 0 on non-memory space mappings. On + * memory space, if the user didn't pass 1, we check for a + * "prefetchable" resource. This is a bit hackish, but we use + * this to workaround the inability of /sysfs to provide a write + * combine bit + */ + if (mmap_state != pci_mmap_mem) + write_combine = 0; + else if (write_combine == 0) { + if (rp->flags & IORESOURCE_PREFETCH) + write_combine = 1; + } + + /* XXX would be nice to have a way to ask for write-through */ + prot |= _PAGE_NO_CACHE; + if (write_combine) + prot &= ~_PAGE_GUARDED; + else + prot |= _PAGE_GUARDED; + + return __pgprot(prot); +} + +/* + * This one is used by /dev/mem and fbdev who have no clue about the + * PCI device, it tries to find the PCI device first and calls the + * above routine + */ +pgprot_t pci_phys_mem_access_prot(struct file *file, + unsigned long pfn, + unsigned long size, + pgprot_t protection) +{ + struct pci_dev *pdev = NULL; + struct resource *found = NULL; + unsigned long prot = pgprot_val(protection); + unsigned long offset = pfn << PAGE_SHIFT; + int i; + + if (page_is_ram(pfn)) + return __pgprot(prot); + + prot |= _PAGE_NO_CACHE | _PAGE_GUARDED; + + for_each_pci_dev(pdev) { + for (i = 0; i <= PCI_ROM_RESOURCE; i++) { + struct resource *rp = &pdev->resource[i]; + int flags = rp->flags; + + /* Active and same type? */ + if ((flags & IORESOURCE_MEM) == 0) + continue; + /* In the range of this resource? */ + if (offset < (rp->start & PAGE_MASK) || + offset > rp->end) + continue; + found = rp; + break; + } + if (found) + break; + } + if (found) { + if (found->flags & IORESOURCE_PREFETCH) + prot &= ~_PAGE_GUARDED; + pci_dev_put(pdev); + } + + DBG("non-PCI map for %lx, prot: %lx\n", offset, prot); + + return __pgprot(prot); +} + + +/* + * Perform the actual remap of the pages for a PCI device mapping, as + * appropriate for this architecture. The region in the process to map + * is described by vm_start and vm_end members of VMA, the base physical + * address is found in vm_pgoff. + * The pci device structure is provided so that architectures may make mapping + * decisions on a per-device or per-bus basis. + * + * Returns a negative error code on failure, zero on success. + */ +int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma, + enum pci_mmap_state mmap_state, int write_combine) +{ + resource_size_t offset = vma->vm_pgoff << PAGE_SHIFT; + struct resource *rp; + int ret; + + rp = __pci_mmap_make_offset(dev, &offset, mmap_state); + if (rp == NULL) + return -EINVAL; + + vma->vm_pgoff = offset >> PAGE_SHIFT; + vma->vm_page_prot = __pci_mmap_set_pgprot(dev, rp, + vma->vm_page_prot, + mmap_state, write_combine); + + ret = remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff, + vma->vm_end - vma->vm_start, vma->vm_page_prot); + + return ret; +} + +static ssize_t pci_show_devspec(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct pci_dev *pdev; + struct device_node *np; + + pdev = to_pci_dev (dev); + np = pci_device_to_OF_node(pdev); + if (np == NULL || np->full_name == NULL) + return 0; + return sprintf(buf, "%s", np->full_name); +} +static DEVICE_ATTR(devspec, S_IRUGO, pci_show_devspec, NULL); + +int pcibios_add_platform_entries(struct pci_dev *pdev) +{ + return device_create_file(&pdev->dev, &dev_attr_devspec); +} + +#define ISA_SPACE_MASK 0x1 +#define ISA_SPACE_IO 0x1 + +static void __devinit pci_process_ISA_OF_ranges(struct device_node *isa_node, + unsigned long phb_io_base_phys, + void __iomem * phb_io_base_virt) +{ + /* Remove these asap */ + + struct pci_address { + u32 a_hi; + u32 a_mid; + u32 a_lo; + }; + + struct isa_address { + u32 a_hi; + u32 a_lo; + }; + + struct isa_range { + struct isa_address isa_addr; + struct pci_address pci_addr; + unsigned int size; + }; + + const struct isa_range *range; + unsigned long pci_addr; + unsigned int isa_addr; + unsigned int size; + int rlen = 0; + + range = of_get_property(isa_node, "ranges", &rlen); + if (range == NULL || (rlen < sizeof(struct isa_range))) { + printk(KERN_ERR "no ISA ranges or unexpected isa range size," + "mapping 64k\n"); + __ioremap_explicit(phb_io_base_phys, + (unsigned long)phb_io_base_virt, + 0x10000, _PAGE_NO_CACHE | _PAGE_GUARDED); + return; + } + + /* From "ISA Binding to 1275" + * The ranges property is laid out as an array of elements, + * each of which comprises: + * cells 0 - 1: an ISA address + * cells 2 - 4: a PCI address + * (size depending on dev->n_addr_cells) + * cell 5: the size of the range + */ + if ((range->isa_addr.a_hi && ISA_SPACE_MASK) == ISA_SPACE_IO) { + isa_addr = range->isa_addr.a_lo; + pci_addr = (unsigned long) range->pci_addr.a_mid << 32 | + range->pci_addr.a_lo; + + /* Assume these are both zero */ + if ((pci_addr != 0) || (isa_addr != 0)) { + printk(KERN_ERR "unexpected isa to pci mapping: %s\n", + __FUNCTION__); + return; + } + + size = PAGE_ALIGN(range->size); + + __ioremap_explicit(phb_io_base_phys, + (unsigned long) phb_io_base_virt, + size, _PAGE_NO_CACHE | _PAGE_GUARDED); + } +} + void __devinit pci_process_bridge_OF_ranges(struct pci_controller *hose, struct device_node *dev, int prim) { @@ -685,122 +1047,155 @@ void __devinit pci_process_bridge_OF_ranges(struct pci_controller *hose, } } -#ifdef CONFIG_HOTPLUG - -int pcibios_unmap_io_space(struct pci_bus *bus) +void __devinit pci_setup_phb_io(struct pci_controller *hose, int primary) { - struct pci_controller *hose; + unsigned long size = hose->pci_io_size; + unsigned long io_virt_offset; + struct resource *res; + struct device_node *isa_dn; - WARN_ON(bus == NULL); + if (size == 0) + return; - /* If this is not a PHB, we only flush the hash table over - * the area mapped by this bridge. We don't play with the PTE - * mappings since we might have to deal with sub-page alignemnts - * so flushing the hash table is the only sane way to make sure - * that no hash entries are covering that removed bridge area - * while still allowing other busses overlapping those pages - */ - if (bus->self) { - struct resource *res = bus->resource[0]; + hose->io_base_virt = reserve_phb_iospace(size); + DBG("phb%d io_base_phys 0x%lx io_base_virt 0x%lx\n", + hose->global_number, hose->io_base_phys, + (unsigned long) hose->io_base_virt); + + if (primary) { + pci_io_base = (unsigned long)hose->io_base_virt; + isa_dn = of_find_node_by_type(NULL, "isa"); + if (isa_dn) { + isa_io_base = pci_io_base; + pci_process_ISA_OF_ranges(isa_dn, hose->io_base_phys, + hose->io_base_virt); + of_node_put(isa_dn); + } + } - DBG("IO unmapping for PCI-PCI bridge %s\n", - pci_name(bus->self)); + io_virt_offset = (unsigned long)hose->io_base_virt - pci_io_base; + res = &hose->io_resource; + res->start += io_virt_offset; + res->end += io_virt_offset; - __flush_hash_table_range(&init_mm, res->start + _IO_BASE, - res->end - res->start + 1); - return 0; - } + /* If this is called after the initial PCI scan, then we need to + * proceed to IO mappings now + */ + if (pci_initial_scan_done) + __ioremap_explicit(hose->io_base_phys, + (unsigned long)hose->io_base_virt, + hose->pci_io_size, + _PAGE_NO_CACHE | _PAGE_GUARDED); +} - /* Get the host bridge */ - hose = pci_bus_to_host(bus); +void __devinit pci_setup_phb_io_dynamic(struct pci_controller *hose, + int primary) +{ + unsigned long size = hose->pci_io_size; + unsigned long io_virt_offset; + struct resource *res; - /* Check if we have IOs allocated */ - if (hose->io_base_alloc == 0) - return 0; + if (size == 0) + return; - DBG("IO unmapping for PHB %s\n", - ((struct device_node *)hose->arch_data)->full_name); - DBG(" alloc=0x%p\n", hose->io_base_alloc); + hose->io_base_virt = __ioremap(hose->io_base_phys, size, + _PAGE_NO_CACHE | _PAGE_GUARDED); + DBG("phb%d io_base_phys 0x%lx io_base_virt 0x%lx\n", + hose->global_number, hose->io_base_phys, + (unsigned long) hose->io_base_virt); - /* This is a PHB, we fully unmap the IO area */ - vunmap(hose->io_base_alloc); + if (primary) + pci_io_base = (unsigned long)hose->io_base_virt; - return 0; + io_virt_offset = (unsigned long)hose->io_base_virt - pci_io_base; + res = &hose->io_resource; + res->start += io_virt_offset; + res->end += io_virt_offset; } -EXPORT_SYMBOL_GPL(pcibios_unmap_io_space); -#endif /* CONFIG_HOTPLUG */ -int __devinit pcibios_map_io_space(struct pci_bus *bus) +static int get_bus_io_range(struct pci_bus *bus, unsigned long *start_phys, + unsigned long *start_virt, unsigned long *size) { - struct vm_struct *area; - unsigned long phys_page; - unsigned long size_page; - unsigned long io_virt_offset; - struct pci_controller *hose; + struct pci_controller *hose = pci_bus_to_host(bus); + struct resource *res; - WARN_ON(bus == NULL); + if (bus->self) + res = bus->resource[0]; + else + /* Root Bus */ + res = &hose->io_resource; - /* If this not a PHB, nothing to do, page tables still exist and - * thus HPTEs will be faulted in when needed - */ - if (bus->self) { - DBG("IO mapping for PCI-PCI bridge %s\n", - pci_name(bus->self)); - DBG(" virt=0x%016lx...0x%016lx\n", - bus->resource[0]->start + _IO_BASE, - bus->resource[0]->end + _IO_BASE); - return 0; + if (res->end == 0 && res->start == 0) + return 1; + + *start_virt = pci_io_base + res->start; + *start_phys = *start_virt + hose->io_base_phys + - (unsigned long) hose->io_base_virt; + + if (res->end > res->start) + *size = res->end - res->start + 1; + else { + printk("%s(): unexpected region 0x%lx->0x%lx\n", + __FUNCTION__, res->start, res->end); + return 1; } - /* Get the host bridge */ - hose = pci_bus_to_host(bus); - phys_page = _ALIGN_DOWN(hose->io_base_phys, PAGE_SIZE); - size_page = _ALIGN_UP(hose->pci_io_size, PAGE_SIZE); + return 0; +} - /* Make sure IO area address is clear */ - hose->io_base_alloc = NULL; +int unmap_bus_range(struct pci_bus *bus) +{ + unsigned long start_phys; + unsigned long start_virt; + unsigned long size; - /* If there's no IO to map on that bus, get away too */ - if (hose->pci_io_size == 0 || hose->io_base_phys == 0) - return 0; + if (!bus) { + printk(KERN_ERR "%s() expected bus\n", __FUNCTION__); + return 1; + } + + if (get_bus_io_range(bus, &start_phys, &start_virt, &size)) + return 1; + if (__iounmap_explicit((void __iomem *) start_virt, size)) + return 1; - /* Let's allocate some IO space for that guy. We don't pass - * VM_IOREMAP because we don't care about alignment tricks that - * the core does in that case. Maybe we should due to stupid card - * with incomplete address decoding but I'd rather not deal with - * those outside of the reserved 64K legacy region. - */ - area = __get_vm_area(size_page, 0, PHB_IO_BASE, PHB_IO_END); - if (area == NULL) - return -ENOMEM; - hose->io_base_alloc = area->addr; - hose->io_base_virt = (void __iomem *)(area->addr + - hose->io_base_phys - phys_page); - - DBG("IO mapping for PHB %s\n", - ((struct device_node *)hose->arch_data)->full_name); - DBG(" phys=0x%016lx, virt=0x%p (alloc=0x%p)\n", - hose->io_base_phys, hose->io_base_virt, hose->io_base_alloc); - DBG(" size=0x%016lx (alloc=0x%016lx)\n", - hose->pci_io_size, size_page); - - /* Establish the mapping */ - if (__ioremap_at(phys_page, area->addr, size_page, - _PAGE_NO_CACHE | _PAGE_GUARDED) == NULL) - return -ENOMEM; - - /* Fixup hose IO resource */ - io_virt_offset = (unsigned long)hose->io_base_virt - _IO_BASE; - hose->io_resource.start += io_virt_offset; - hose->io_resource.end += io_virt_offset; - - DBG(" hose->io_resource=0x%016lx...0x%016lx\n", - hose->io_resource.start, hose->io_resource.end); + return 0; +} +EXPORT_SYMBOL(unmap_bus_range); + +int remap_bus_range(struct pci_bus *bus) +{ + unsigned long start_phys; + unsigned long start_virt; + unsigned long size; + + if (!bus) { + printk(KERN_ERR "%s() expected bus\n", __FUNCTION__); + return 1; + } + + + if (get_bus_io_range(bus, &start_phys, &start_virt, &size)) + return 1; + if (start_phys == 0) + return 1; + printk(KERN_DEBUG "mapping IO %lx -> %lx, size: %lx\n", start_phys, start_virt, size); + if (__ioremap_explicit(start_phys, start_virt, size, + _PAGE_NO_CACHE | _PAGE_GUARDED)) + return 1; return 0; } -EXPORT_SYMBOL_GPL(pcibios_map_io_space); +EXPORT_SYMBOL(remap_bus_range); + +static void phbs_remap_io(void) +{ + struct pci_controller *hose, *tmp; + + list_for_each_entry_safe(hose, tmp, &hose_list, list_node) + remap_bus_range(hose->bus); +} static void __devinit fixup_resource(struct resource *res, struct pci_dev *dev) { @@ -808,7 +1203,8 @@ static void __devinit fixup_resource(struct resource *res, struct pci_dev *dev) unsigned long offset; if (res->flags & IORESOURCE_IO) { - offset = (unsigned long)hose->io_base_virt - _IO_BASE; + offset = (unsigned long)hose->io_base_virt - pci_io_base; + res->start += offset; res->end += offset; } else if (res->flags & IORESOURCE_MEM) { @@ -823,20 +1219,9 @@ void __devinit pcibios_fixup_device_resources(struct pci_dev *dev, /* Update device resources. */ int i; - DBG("%s: Fixup resources:\n", pci_name(dev)); - for (i = 0; i < PCI_NUM_RESOURCES; i++) { - struct resource *res = &dev->resource[i]; - if (!res->flags) - continue; - - DBG(" 0x%02x < %08lx:0x%016lx...0x%016lx\n", - i, res->flags, res->start, res->end); - - fixup_resource(res, dev); - - DBG(" > %08lx:0x%016lx...0x%016lx\n", - res->flags, res->start, res->end); - } + for (i = 0; i < PCI_NUM_RESOURCES; i++) + if (dev->resource[i].flags) + fixup_resource(&dev->resource[i], dev); } EXPORT_SYMBOL(pcibios_fixup_device_resources); @@ -906,6 +1291,119 @@ void __devinit pcibios_fixup_bus(struct pci_bus *bus) } EXPORT_SYMBOL(pcibios_fixup_bus); +/* + * Reads the interrupt pin to determine if interrupt is use by card. + * If the interrupt is used, then gets the interrupt line from the + * openfirmware and sets it in the pci_dev and pci_config line. + */ +int pci_read_irq_line(struct pci_dev *pci_dev) +{ + struct of_irq oirq; + unsigned int virq; + + DBG("Try to map irq for %s...\n", pci_name(pci_dev)); + +#ifdef DEBUG + memset(&oirq, 0xff, sizeof(oirq)); +#endif + /* Try to get a mapping from the device-tree */ + if (of_irq_map_pci(pci_dev, &oirq)) { + u8 line, pin; + + /* If that fails, lets fallback to what is in the config + * space and map that through the default controller. We + * also set the type to level low since that's what PCI + * interrupts are. If your platform does differently, then + * either provide a proper interrupt tree or don't use this + * function. + */ + if (pci_read_config_byte(pci_dev, PCI_INTERRUPT_PIN, &pin)) + return -1; + if (pin == 0) + return -1; + if (pci_read_config_byte(pci_dev, PCI_INTERRUPT_LINE, &line) || + line == 0xff) { + return -1; + } + DBG(" -> no map ! Using irq line %d from PCI config\n", line); + + virq = irq_create_mapping(NULL, line); + if (virq != NO_IRQ) + set_irq_type(virq, IRQ_TYPE_LEVEL_LOW); + } else { + DBG(" -> got one, spec %d cells (0x%08x 0x%08x...) on %s\n", + oirq.size, oirq.specifier[0], oirq.specifier[1], + oirq.controller->full_name); + + virq = irq_create_of_mapping(oirq.controller, oirq.specifier, + oirq.size); + } + if(virq == NO_IRQ) { + DBG(" -> failed to map !\n"); + return -1; + } + + DBG(" -> mapped to linux irq %d\n", virq); + + pci_dev->irq = virq; + + return 0; +} +EXPORT_SYMBOL(pci_read_irq_line); + +void pci_resource_to_user(const struct pci_dev *dev, int bar, + const struct resource *rsrc, + resource_size_t *start, resource_size_t *end) +{ + struct pci_controller *hose = pci_bus_to_host(dev->bus); + resource_size_t offset = 0; + + if (hose == NULL) + return; + + if (rsrc->flags & IORESOURCE_IO) + offset = (unsigned long)hose->io_base_virt - pci_io_base; + + /* We pass a fully fixed up address to userland for MMIO instead of + * a BAR value because X is lame and expects to be able to use that + * to pass to /dev/mem ! + * + * That means that we'll have potentially 64 bits values where some + * userland apps only expect 32 (like X itself since it thinks only + * Sparc has 64 bits MMIO) but if we don't do that, we break it on + * 32 bits CHRPs :-( + * + * Hopefully, the sysfs insterface is immune to that gunk. Once X + * has been fixed (and the fix spread enough), we can re-enable the + * 2 lines below and pass down a BAR value to userland. In that case + * we'll also have to re-enable the matching code in + * __pci_mmap_make_offset(). + * + * BenH. + */ +#if 0 + else if (rsrc->flags & IORESOURCE_MEM) + offset = hose->pci_mem_offset; +#endif + + *start = rsrc->start - offset; + *end = rsrc->end - offset; +} + +struct pci_controller* pci_find_hose_for_OF_device(struct device_node* node) +{ + if (!have_of) + return NULL; + while(node) { + struct pci_controller *hose, *tmp; + list_for_each_entry_safe(hose, tmp, &hose_list, list_node) + if (hose->arch_data == node) + return hose; + node = node->parent; + } + return NULL; +} + unsigned long pci_address_to_pio(phys_addr_t address) { struct pci_controller *hose, *tmp; @@ -914,7 +1412,7 @@ unsigned long pci_address_to_pio(phys_addr_t address) if (address >= hose->io_base_phys && address < (hose->io_base_phys + hose->pci_io_size)) { unsigned long base = - (unsigned long)hose->io_base_virt - _IO_BASE; + (unsigned long)hose->io_base_virt - pci_io_base; return base + (address - hose->io_base_phys); } } diff --git a/trunk/arch/powerpc/kernel/ppc_ksyms.c b/trunk/arch/powerpc/kernel/ppc_ksyms.c index a20f1951a5ce..c96fa9bd35a4 100644 --- a/trunk/arch/powerpc/kernel/ppc_ksyms.c +++ b/trunk/arch/powerpc/kernel/ppc_ksyms.c @@ -67,6 +67,7 @@ EXPORT_SYMBOL(ISA_DMA_THRESHOLD); EXPORT_SYMBOL(DMA_MODE_READ); EXPORT_SYMBOL(DMA_MODE_WRITE); +EXPORT_SYMBOL(do_signal); EXPORT_SYMBOL(transfer_to_handler); EXPORT_SYMBOL(do_IRQ); EXPORT_SYMBOL(machine_check_exception); @@ -105,6 +106,10 @@ EXPORT_SYMBOL(isa_mem_base); EXPORT_SYMBOL(pci_dram_offset); EXPORT_SYMBOL(pci_alloc_consistent); EXPORT_SYMBOL(pci_free_consistent); +EXPORT_SYMBOL(pci_bus_io_base); +EXPORT_SYMBOL(pci_bus_io_base_phys); +EXPORT_SYMBOL(pci_bus_mem_base_phys); +EXPORT_SYMBOL(pci_bus_to_hose); #endif /* CONFIG_PCI */ EXPORT_SYMBOL(start_thread); diff --git a/trunk/arch/powerpc/kernel/process.c b/trunk/arch/powerpc/kernel/process.c index 84f000a45e36..6e2f03566b0d 100644 --- a/trunk/arch/powerpc/kernel/process.c +++ b/trunk/arch/powerpc/kernel/process.c @@ -219,25 +219,21 @@ void discard_lazy_cpu_state(void) } #endif /* CONFIG_SMP */ +#ifdef CONFIG_PPC_MERGE /* XXX for now */ int set_dabr(unsigned long dabr) { -#ifdef CONFIG_PPC_MERGE /* XXX for now */ if (ppc_md.set_dabr) return ppc_md.set_dabr(dabr); -#endif - /* XXX should we have a CPU_FTR_HAS_DABR ? */ -#if defined(CONFIG_PPC64) || defined(CONFIG_6xx) mtspr(SPRN_DABR, dabr); -#endif return 0; } +#endif #ifdef CONFIG_PPC64 DEFINE_PER_CPU(struct cpu_usage, cpu_usage_array); -#endif - static DEFINE_PER_CPU(unsigned long, current_dabr); +#endif struct task_struct *__switch_to(struct task_struct *prev, struct task_struct *new) @@ -303,10 +299,12 @@ struct task_struct *__switch_to(struct task_struct *prev, #endif /* CONFIG_SMP */ +#ifdef CONFIG_PPC64 /* for now */ if (unlikely(__get_cpu_var(current_dabr) != new->thread.dabr)) { set_dabr(new->thread.dabr); __get_cpu_var(current_dabr) = new->thread.dabr; } +#endif /* CONFIG_PPC64 */ new_thread = &new->thread; old_thread = ¤t->thread; @@ -475,10 +473,12 @@ void flush_thread(void) discard_lazy_cpu_state(); +#ifdef CONFIG_PPC64 /* for now */ if (current->thread.dabr) { current->thread.dabr = 0; set_dabr(0); } +#endif } void diff --git a/trunk/arch/powerpc/kernel/prom.c b/trunk/arch/powerpc/kernel/prom.c index 37ff99bd98b4..af42ddab3ab4 100644 --- a/trunk/arch/powerpc/kernel/prom.c +++ b/trunk/arch/powerpc/kernel/prom.c @@ -52,7 +52,6 @@ #include #include #include -#include #ifdef DEBUG #define DBG(fmt...) printk(KERN_ERR fmt) @@ -1006,7 +1005,7 @@ static void __init early_reserve_mem(void) void __init early_init_devtree(void *params) { - DBG(" -> early_init_devtree(%p)\n", params); + DBG(" -> early_init_devtree()\n"); /* Setup flat device-tree pointer */ initial_boot_params = params; @@ -1056,6 +1055,8 @@ void __init early_init_devtree(void *params) DBG(" <- early_init_devtree()\n"); } +#undef printk + int of_n_addr_cells(struct device_node* np) { const int *ip; @@ -1374,17 +1375,8 @@ static void of_node_release(struct kref *kref) struct device_node *node = kref_to_device_node(kref); struct property *prop = node->properties; - /* We should never be releasing nodes that haven't been detached. */ - if (!of_node_check_flag(node, OF_DETACHED)) { - printk("WARNING: Bad of_node_put() on %s\n", node->full_name); - dump_stack(); - kref_init(&node->kref); - return; - } - - if (!of_node_check_flag(node, OF_DYNAMIC)) + if (!OF_IS_DYNAMIC(node)) return; - while (prop) { struct property *next = prop->next; kfree(prop->name); @@ -1440,8 +1432,6 @@ void of_detach_node(const struct device_node *np) write_lock(&devtree_lock); parent = np->parent; - if (!parent) - goto out_unlock; if (allnodes == np) allnodes = np->allnext; @@ -1465,9 +1455,6 @@ void of_detach_node(const struct device_node *np) prevsib->sibling = np->sibling; } - of_node_set_flag(np, OF_DETACHED); - -out_unlock: write_unlock(&devtree_lock); } @@ -1729,18 +1716,22 @@ struct device_node *of_get_cpu_node(int cpu, unsigned int *thread) } EXPORT_SYMBOL(of_get_cpu_node); -#if defined(CONFIG_DEBUG_FS) && defined(DEBUG) +#ifdef DEBUG static struct debugfs_blob_wrapper flat_dt_blob; static int __init export_flat_device_tree(void) { struct dentry *d; + d = debugfs_create_dir("powerpc", NULL); + if (!d) + return 1; + flat_dt_blob.data = initial_boot_params; flat_dt_blob.size = initial_boot_params->totalsize; d = debugfs_create_blob("flat-device-tree", S_IFREG | S_IRUSR, - powerpc_debugfs_root, &flat_dt_blob); + d, &flat_dt_blob); if (!d) return 1; diff --git a/trunk/arch/powerpc/kernel/prom_init.c b/trunk/arch/powerpc/kernel/prom_init.c index a1d582e38627..d6047c441034 100644 --- a/trunk/arch/powerpc/kernel/prom_init.c +++ b/trunk/arch/powerpc/kernel/prom_init.c @@ -635,7 +635,6 @@ static void __init early_cmdline_parse(void) /* ibm,dynamic-reconfiguration-memory property supported */ #define OV5_DRCONF_MEMORY 0x20 #define OV5_LARGE_PAGES 0x10 /* large pages supported */ -#define OV5_DONATE_DEDICATE_CPU 0x02 /* donate dedicated CPU support */ /* PCIe/MSI support. Without MSI full PCIe is not supported */ #ifdef CONFIG_PCI_MSI #define OV5_MSI 0x01 /* PCIe/MSI support */ @@ -686,8 +685,7 @@ static unsigned char ibm_architecture_vec[] = { /* option vector 5: PAPR/OF options */ 3 - 2, /* length */ 0, /* don't ignore, don't halt */ - OV5_LPAR | OV5_SPLPAR | OV5_LARGE_PAGES | OV5_DRCONF_MEMORY | - OV5_DONATE_DEDICATE_CPU | OV5_MSI, + OV5_LPAR | OV5_SPLPAR | OV5_LARGE_PAGES | OV5_DRCONF_MEMORY | OV5_MSI, }; /* Old method - ELF header with PT_NOTE sections */ diff --git a/trunk/arch/powerpc/kernel/ptrace-common.h b/trunk/arch/powerpc/kernel/ptrace-common.h new file mode 100644 index 000000000000..8797ae737a7b --- /dev/null +++ b/trunk/arch/powerpc/kernel/ptrace-common.h @@ -0,0 +1,161 @@ +/* + * Copyright (c) 2002 Stephen Rothwell, IBM Coproration + * Extracted from ptrace.c and ptrace32.c + * + * This file is subject to the terms and conditions of the GNU General + * Public License. See the file README.legal in the main directory of + * this archive for more details. + */ + +#ifndef _PPC64_PTRACE_COMMON_H +#define _PPC64_PTRACE_COMMON_H + +#include + +/* + * Set of msr bits that gdb can change on behalf of a process. + */ +#define MSR_DEBUGCHANGE (MSR_FE0 | MSR_SE | MSR_BE | MSR_FE1) + +/* + * Get contents of register REGNO in task TASK. + */ +static inline unsigned long get_reg(struct task_struct *task, int regno) +{ + unsigned long tmp = 0; + + /* + * Put the correct FP bits in, they might be wrong as a result + * of our lazy FP restore. + */ + if (regno == PT_MSR) { + tmp = ((unsigned long *)task->thread.regs)[PT_MSR]; + tmp |= task->thread.fpexc_mode; + } else if (regno < (sizeof(struct pt_regs) / sizeof(unsigned long))) { + tmp = ((unsigned long *)task->thread.regs)[regno]; + } + + return tmp; +} + +/* + * Write contents of register REGNO in task TASK. + */ +static inline int put_reg(struct task_struct *task, int regno, + unsigned long data) +{ + if (regno < PT_SOFTE) { + if (regno == PT_MSR) + data = (data & MSR_DEBUGCHANGE) + | (task->thread.regs->msr & ~MSR_DEBUGCHANGE); + ((unsigned long *)task->thread.regs)[regno] = data; + return 0; + } + return -EIO; +} + +static inline void set_single_step(struct task_struct *task) +{ + struct pt_regs *regs = task->thread.regs; + if (regs != NULL) + regs->msr |= MSR_SE; + set_tsk_thread_flag(task, TIF_SINGLESTEP); +} + +static inline void clear_single_step(struct task_struct *task) +{ + struct pt_regs *regs = task->thread.regs; + if (regs != NULL) + regs->msr &= ~MSR_SE; + clear_tsk_thread_flag(task, TIF_SINGLESTEP); +} + +#ifdef CONFIG_ALTIVEC +/* + * Get/set all the altivec registers vr0..vr31, vscr, vrsave, in one go. + * The transfer totals 34 quadword. Quadwords 0-31 contain the + * corresponding vector registers. Quadword 32 contains the vscr as the + * last word (offset 12) within that quadword. Quadword 33 contains the + * vrsave as the first word (offset 0) within the quadword. + * + * This definition of the VMX state is compatible with the current PPC32 + * ptrace interface. This allows signal handling and ptrace to use the + * same structures. This also simplifies the implementation of a bi-arch + * (combined (32- and 64-bit) gdb. + */ + +/* + * Get contents of AltiVec register state in task TASK + */ +static inline int get_vrregs(unsigned long __user *data, + struct task_struct *task) +{ + unsigned long regsize; + + /* copy AltiVec registers VR[0] .. VR[31] */ + regsize = 32 * sizeof(vector128); + if (copy_to_user(data, task->thread.vr, regsize)) + return -EFAULT; + data += (regsize / sizeof(unsigned long)); + + /* copy VSCR */ + regsize = 1 * sizeof(vector128); + if (copy_to_user(data, &task->thread.vscr, regsize)) + return -EFAULT; + data += (regsize / sizeof(unsigned long)); + + /* copy VRSAVE */ + if (put_user(task->thread.vrsave, (u32 __user *)data)) + return -EFAULT; + + return 0; +} + +/* + * Write contents of AltiVec register state into task TASK. + */ +static inline int set_vrregs(struct task_struct *task, + unsigned long __user *data) +{ + unsigned long regsize; + + /* copy AltiVec registers VR[0] .. VR[31] */ + regsize = 32 * sizeof(vector128); + if (copy_from_user(task->thread.vr, data, regsize)) + return -EFAULT; + data += (regsize / sizeof(unsigned long)); + + /* copy VSCR */ + regsize = 1 * sizeof(vector128); + if (copy_from_user(&task->thread.vscr, data, regsize)) + return -EFAULT; + data += (regsize / sizeof(unsigned long)); + + /* copy VRSAVE */ + if (get_user(task->thread.vrsave, (u32 __user *)data)) + return -EFAULT; + + return 0; +} +#endif + +static inline int ptrace_set_debugreg(struct task_struct *task, + unsigned long addr, unsigned long data) +{ + /* We only support one DABR and no IABRS at the moment */ + if (addr > 0) + return -EINVAL; + + /* The bottom 3 bits are flags */ + if ((data & ~0x7UL) >= TASK_SIZE) + return -EIO; + + /* Ensure translation is on */ + if (data && !(data & DABR_TRANSLATION)) + return -EIO; + + task->thread.dabr = data; + return 0; +} + +#endif /* _PPC64_PTRACE_COMMON_H */ diff --git a/trunk/arch/powerpc/kernel/ptrace.c b/trunk/arch/powerpc/kernel/ptrace.c index 0fb53950da43..bf76562167c3 100644 --- a/trunk/arch/powerpc/kernel/ptrace.c +++ b/trunk/arch/powerpc/kernel/ptrace.c @@ -35,11 +35,11 @@ #include #include -/* - * does not yet catch signals sent when the child dies. - * in exit.c or in signal.c. - */ +#ifdef CONFIG_PPC64 +#include "ptrace-common.h" +#endif +#ifdef CONFIG_PPC32 /* * Set of msr bits that gdb can change on behalf of a process. */ @@ -48,117 +48,65 @@ #else #define MSR_DEBUGCHANGE (MSR_SE | MSR_BE) #endif +#endif /* CONFIG_PPC32 */ /* - * Max register writeable via put_reg + * does not yet catch signals sent when the child dies. + * in exit.c or in signal.c. */ -#ifdef CONFIG_PPC32 -#define PT_MAX_PUT_REG PT_MQ -#else -#define PT_MAX_PUT_REG PT_CCR -#endif +#ifdef CONFIG_PPC32 /* * Get contents of register REGNO in task TASK. */ -unsigned long ptrace_get_reg(struct task_struct *task, int regno) +static inline unsigned long get_reg(struct task_struct *task, int regno) { - unsigned long tmp = 0; - - if (task->thread.regs == NULL) - return -EIO; - - if (regno == PT_MSR) { - tmp = ((unsigned long *)task->thread.regs)[PT_MSR]; - return tmp | task->thread.fpexc_mode; - } - - if (regno < (sizeof(struct pt_regs) / sizeof(unsigned long))) + if (regno < sizeof(struct pt_regs) / sizeof(unsigned long) + && task->thread.regs != NULL) return ((unsigned long *)task->thread.regs)[regno]; - - return -EIO; + return (0); } /* * Write contents of register REGNO in task TASK. */ -int ptrace_put_reg(struct task_struct *task, int regno, unsigned long data) +static inline int put_reg(struct task_struct *task, int regno, + unsigned long data) { - if (task->thread.regs == NULL) - return -EIO; - - if (regno <= PT_MAX_PUT_REG || regno == PT_TRAP) { + if (regno <= PT_MQ && task->thread.regs != NULL) { if (regno == PT_MSR) data = (data & MSR_DEBUGCHANGE) | (task->thread.regs->msr & ~MSR_DEBUGCHANGE); - /* We prevent mucking around with the reserved area of trap - * which are used internally by the kernel - */ - if (regno == PT_TRAP) - data &= 0xfff0; ((unsigned long *)task->thread.regs)[regno] = data; return 0; } return -EIO; } - -static int get_fpregs(void __user *data, struct task_struct *task, - int has_fpscr) -{ - unsigned int count = has_fpscr ? 33 : 32; - - if (copy_to_user(data, task->thread.fpr, count * sizeof(double))) - return -EFAULT; - return 0; -} - -static int set_fpregs(void __user *data, struct task_struct *task, - int has_fpscr) -{ - unsigned int count = has_fpscr ? 33 : 32; - - if (copy_from_user(task->thread.fpr, data, count * sizeof(double))) - return -EFAULT; - return 0; -} - - #ifdef CONFIG_ALTIVEC -/* - * Get/set all the altivec registers vr0..vr31, vscr, vrsave, in one go. - * The transfer totals 34 quadword. Quadwords 0-31 contain the - * corresponding vector registers. Quadword 32 contains the vscr as the - * last word (offset 12) within that quadword. Quadword 33 contains the - * vrsave as the first word (offset 0) within the quadword. - * - * This definition of the VMX state is compatible with the current PPC32 - * ptrace interface. This allows signal handling and ptrace to use the - * same structures. This also simplifies the implementation of a bi-arch - * (combined (32- and 64-bit) gdb. - */ - /* * Get contents of AltiVec register state in task TASK */ -static int get_vrregs(unsigned long __user *data, struct task_struct *task) +static inline int get_vrregs(unsigned long __user *data, struct task_struct *task) { - unsigned long regsize; + int i, j; - /* copy AltiVec registers VR[0] .. VR[31] */ - regsize = 32 * sizeof(vector128); - if (copy_to_user(data, task->thread.vr, regsize)) + if (!access_ok(VERIFY_WRITE, data, 133 * sizeof(unsigned long))) return -EFAULT; - data += (regsize / sizeof(unsigned long)); + + /* copy AltiVec registers VR[0] .. VR[31] */ + for (i = 0; i < 32; i++) + for (j = 0; j < 4; j++, data++) + if (__put_user(task->thread.vr[i].u[j], data)) + return -EFAULT; /* copy VSCR */ - regsize = 1 * sizeof(vector128); - if (copy_to_user(data, &task->thread.vscr, regsize)) - return -EFAULT; - data += (regsize / sizeof(unsigned long)); + for (i = 0; i < 4; i++, data++) + if (__put_user(task->thread.vscr.u[i], data)) + return -EFAULT; - /* copy VRSAVE */ - if (put_user(task->thread.vrsave, (u32 __user *)data)) + /* copy VRSAVE */ + if (__put_user(task->thread.vrsave, data)) return -EFAULT; return 0; @@ -167,29 +115,31 @@ static int get_vrregs(unsigned long __user *data, struct task_struct *task) /* * Write contents of AltiVec register state into task TASK. */ -static int set_vrregs(struct task_struct *task, unsigned long __user *data) +static inline int set_vrregs(struct task_struct *task, unsigned long __user *data) { - unsigned long regsize; + int i, j; - /* copy AltiVec registers VR[0] .. VR[31] */ - regsize = 32 * sizeof(vector128); - if (copy_from_user(task->thread.vr, data, regsize)) + if (!access_ok(VERIFY_READ, data, 133 * sizeof(unsigned long))) return -EFAULT; - data += (regsize / sizeof(unsigned long)); + + /* copy AltiVec registers VR[0] .. VR[31] */ + for (i = 0; i < 32; i++) + for (j = 0; j < 4; j++, data++) + if (__get_user(task->thread.vr[i].u[j], data)) + return -EFAULT; /* copy VSCR */ - regsize = 1 * sizeof(vector128); - if (copy_from_user(&task->thread.vscr, data, regsize)) - return -EFAULT; - data += (regsize / sizeof(unsigned long)); + for (i = 0; i < 4; i++, data++) + if (__get_user(task->thread.vscr.u[i], data)) + return -EFAULT; /* copy VRSAVE */ - if (get_user(task->thread.vrsave, (u32 __user *)data)) + if (__get_user(task->thread.vrsave, data)) return -EFAULT; return 0; } -#endif /* CONFIG_ALTIVEC */ +#endif #ifdef CONFIG_SPE @@ -206,7 +156,7 @@ static int set_vrregs(struct task_struct *task, unsigned long __user *data) /* * Get contents of SPE register state in task TASK. */ -static int get_evrregs(unsigned long *data, struct task_struct *task) +static inline int get_evrregs(unsigned long *data, struct task_struct *task) { int i; @@ -232,7 +182,7 @@ static int get_evrregs(unsigned long *data, struct task_struct *task) /* * Write contents of SPE register state into task TASK. */ -static int set_evrregs(struct task_struct *task, unsigned long *data) +static inline int set_evrregs(struct task_struct *task, unsigned long *data) { int i; @@ -255,8 +205,8 @@ static int set_evrregs(struct task_struct *task, unsigned long *data) } #endif /* CONFIG_SPE */ - -static void set_single_step(struct task_struct *task) +static inline void +set_single_step(struct task_struct *task) { struct pt_regs *regs = task->thread.regs; @@ -271,7 +221,8 @@ static void set_single_step(struct task_struct *task) set_tsk_thread_flag(task, TIF_SINGLESTEP); } -static void clear_single_step(struct task_struct *task) +static inline void +clear_single_step(struct task_struct *task) { struct pt_regs *regs = task->thread.regs; @@ -285,25 +236,7 @@ static void clear_single_step(struct task_struct *task) } clear_tsk_thread_flag(task, TIF_SINGLESTEP); } - -static int ptrace_set_debugreg(struct task_struct *task, unsigned long addr, - unsigned long data) -{ - /* We only support one DABR and no IABRS at the moment */ - if (addr > 0) - return -EINVAL; - - /* The bottom 3 bits are flags */ - if ((data & ~0x7UL) >= TASK_SIZE) - return -EIO; - - /* Ensure translation is on */ - if (data && !(data & DABR_TRANSLATION)) - return -EIO; - - task->thread.dabr = data; - return 0; -} +#endif /* CONFIG_PPC32 */ /* * Called by kernel/ptrace.c when detaching.. @@ -316,62 +249,6 @@ void ptrace_disable(struct task_struct *child) clear_single_step(child); } -/* - * Here are the old "legacy" powerpc specific getregs/setregs ptrace calls, - * we mark them as obsolete now, they will be removed in a future version - */ -static long arch_ptrace_old(struct task_struct *child, long request, long addr, - long data) -{ - int ret = -EPERM; - - switch(request) { - case PPC_PTRACE_GETREGS: { /* Get GPRs 0 - 31. */ - int i; - unsigned long *reg = &((unsigned long *)child->thread.regs)[0]; - unsigned long __user *tmp = (unsigned long __user *)addr; - - for (i = 0; i < 32; i++) { - ret = put_user(*reg, tmp); - if (ret) - break; - reg++; - tmp++; - } - break; - } - - case PPC_PTRACE_SETREGS: { /* Set GPRs 0 - 31. */ - int i; - unsigned long *reg = &((unsigned long *)child->thread.regs)[0]; - unsigned long __user *tmp = (unsigned long __user *)addr; - - for (i = 0; i < 32; i++) { - ret = get_user(*reg, tmp); - if (ret) - break; - reg++; - tmp++; - } - break; - } - - case PPC_PTRACE_GETFPREGS: { /* Get FPRs 0 - 31. */ - flush_fp_to_thread(child); - ret = get_fpregs((void __user *)addr, child, 0); - break; - } - - case PPC_PTRACE_SETFPREGS: { /* Get FPRs 0 - 31. */ - flush_fp_to_thread(child); - ret = set_fpregs((void __user *)addr, child, 0); - break; - } - - } - return ret; -} - long arch_ptrace(struct task_struct *child, long request, long addr, long data) { int ret = -EPERM; @@ -407,9 +284,11 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) #endif break; +#ifdef CONFIG_PPC32 CHECK_FULL_REGS(child->thread.regs); +#endif if (index < PT_FPR0) { - tmp = ptrace_get_reg(child, (int) index); + tmp = get_reg(child, (int) index); } else { flush_fp_to_thread(child); tmp = ((unsigned long *)child->thread.fpr)[index - PT_FPR0]; @@ -444,9 +323,13 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) #endif break; +#ifdef CONFIG_PPC32 CHECK_FULL_REGS(child->thread.regs); +#endif + if (index == PT_ORIG_R3) + break; if (index < PT_FPR0) { - ret = ptrace_put_reg(child, index, data); + ret = put_reg(child, index, data); } else { flush_fp_to_thread(child); ((unsigned long *)child->thread.fpr)[index - PT_FPR0] = data; @@ -501,6 +384,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) break; } +#ifdef CONFIG_PPC64 case PTRACE_GET_DEBUGREG: { ret = -EINVAL; /* We only support one DABR and no IABRS at the moment */ @@ -514,61 +398,73 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) case PTRACE_SET_DEBUGREG: ret = ptrace_set_debugreg(child, addr, data); break; +#endif case PTRACE_DETACH: ret = ptrace_detach(child, data); break; -#ifdef CONFIG_PPC64 - case PTRACE_GETREGS64: -#endif - case PTRACE_GETREGS: { /* Get all pt_regs from the child. */ - int ui; - if (!access_ok(VERIFY_WRITE, (void __user *)data, - sizeof(struct pt_regs))) { - ret = -EIO; - break; - } - ret = 0; - for (ui = 0; ui < PT_REGS_COUNT; ui ++) { - ret |= __put_user(ptrace_get_reg(child, ui), - (unsigned long __user *) data); - data += sizeof(long); + case PPC_PTRACE_GETREGS: { /* Get GPRs 0 - 31. */ + int i; + unsigned long *reg = &((unsigned long *)child->thread.regs)[0]; + unsigned long __user *tmp = (unsigned long __user *)addr; + + for (i = 0; i < 32; i++) { + ret = put_user(*reg, tmp); + if (ret) + break; + reg++; + tmp++; } break; } -#ifdef CONFIG_PPC64 - case PTRACE_SETREGS64: -#endif - case PTRACE_SETREGS: { /* Set all gp regs in the child. */ - unsigned long tmp; - int ui; - if (!access_ok(VERIFY_READ, (void __user *)data, - sizeof(struct pt_regs))) { - ret = -EIO; - break; - } - ret = 0; - for (ui = 0; ui < PT_REGS_COUNT; ui ++) { - ret = __get_user(tmp, (unsigned long __user *) data); + case PPC_PTRACE_SETREGS: { /* Set GPRs 0 - 31. */ + int i; + unsigned long *reg = &((unsigned long *)child->thread.regs)[0]; + unsigned long __user *tmp = (unsigned long __user *)addr; + + for (i = 0; i < 32; i++) { + ret = get_user(*reg, tmp); if (ret) break; - ptrace_put_reg(child, ui, tmp); - data += sizeof(long); + reg++; + tmp++; } break; } - case PTRACE_GETFPREGS: { /* Get the child FPU state (FPR0...31 + FPSCR) */ + case PPC_PTRACE_GETFPREGS: { /* Get FPRs 0 - 31. */ + int i; + unsigned long *reg = &((unsigned long *)child->thread.fpr)[0]; + unsigned long __user *tmp = (unsigned long __user *)addr; + flush_fp_to_thread(child); - ret = get_fpregs((void __user *)data, child, 1); + + for (i = 0; i < 32; i++) { + ret = put_user(*reg, tmp); + if (ret) + break; + reg++; + tmp++; + } break; } - case PTRACE_SETFPREGS: { /* Set the child FPU state (FPR0...31 + FPSCR) */ + case PPC_PTRACE_SETFPREGS: { /* Get FPRs 0 - 31. */ + int i; + unsigned long *reg = &((unsigned long *)child->thread.fpr)[0]; + unsigned long __user *tmp = (unsigned long __user *)addr; + flush_fp_to_thread(child); - ret = set_fpregs((void __user *)data, child, 1); + + for (i = 0; i < 32; i++) { + ret = get_user(*reg, tmp); + if (ret) + break; + reg++; + tmp++; + } break; } @@ -603,18 +499,11 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) break; #endif - /* Old reverse args ptrace callss */ - case PPC_PTRACE_GETREGS: /* Get GPRs 0 - 31. */ - case PPC_PTRACE_SETREGS: /* Set GPRs 0 - 31. */ - case PPC_PTRACE_GETFPREGS: /* Get FPRs 0 - 31. */ - case PPC_PTRACE_SETFPREGS: /* Get FPRs 0 - 31. */ - ret = arch_ptrace_old(child, request, addr, data); - break; - default: ret = ptrace_request(child, request, addr, data); break; } + return ret; } diff --git a/trunk/arch/powerpc/kernel/ptrace32.c b/trunk/arch/powerpc/kernel/ptrace32.c index 9e6baeac0fb1..9b9a230349bc 100644 --- a/trunk/arch/powerpc/kernel/ptrace32.c +++ b/trunk/arch/powerpc/kernel/ptrace32.c @@ -33,55 +33,13 @@ #include #include +#include "ptrace-common.h" + /* * does not yet catch signals sent when the child dies. * in exit.c or in signal.c. */ -/* - * Here are the old "legacy" powerpc specific getregs/setregs ptrace calls, - * we mark them as obsolete now, they will be removed in a future version - */ -static long compat_ptrace_old(struct task_struct *child, long request, - long addr, long data) -{ - int ret = -EPERM; - - switch(request) { - case PPC_PTRACE_GETREGS: { /* Get GPRs 0 - 31. */ - int i; - unsigned long *reg = &((unsigned long *)child->thread.regs)[0]; - unsigned int __user *tmp = (unsigned int __user *)addr; - - for (i = 0; i < 32; i++) { - ret = put_user(*reg, tmp); - if (ret) - break; - reg++; - tmp++; - } - break; - } - - case PPC_PTRACE_SETREGS: { /* Set GPRs 0 - 31. */ - int i; - unsigned long *reg = &((unsigned long *)child->thread.regs)[0]; - unsigned int __user *tmp = (unsigned int __user *)addr; - - for (i = 0; i < 32; i++) { - ret = get_user(*reg, tmp); - if (ret) - break; - reg++; - tmp++; - } - break; - } - - } - return ret; -} - long compat_sys_ptrace(int request, int pid, unsigned long addr, unsigned long data) { @@ -165,7 +123,7 @@ long compat_sys_ptrace(int request, int pid, unsigned long addr, break; if (index < PT_FPR0) { - tmp = ptrace_get_reg(child, index); + tmp = get_reg(child, index); } else { flush_fp_to_thread(child); /* @@ -204,9 +162,7 @@ long compat_sys_ptrace(int request, int pid, unsigned long addr, else part = 0; /* want the 1st half of the register (left-most). */ - /* Validate the input - check to see if address is on the wrong boundary - * or beyond the end of the user area - */ + /* Validate the input - check to see if address is on the wrong boundary or beyond the end of the user area */ if ((addr & 3) || numReg > PT_FPSCR) break; @@ -214,7 +170,7 @@ long compat_sys_ptrace(int request, int pid, unsigned long addr, flush_fp_to_thread(child); tmp = ((unsigned long int *)child->thread.fpr)[numReg - PT_FPR0]; } else { /* register within PT_REGS struct */ - tmp = ptrace_get_reg(child, numReg); + tmp = get_reg(child, numReg); } reg32bits = ((u32*)&tmp)[part]; ret = put_user(reg32bits, (u32 __user *)data); @@ -270,8 +226,10 @@ long compat_sys_ptrace(int request, int pid, unsigned long addr, if ((addr & 3) || (index > PT_FPSCR32)) break; + if (index == PT_ORIG_R3) + break; if (index < PT_FPR0) { - ret = ptrace_put_reg(child, index, data); + ret = put_reg(child, index, data); } else { flush_fp_to_thread(child); /* @@ -300,25 +258,70 @@ long compat_sys_ptrace(int request, int pid, unsigned long addr, /* Determine which register the user wants */ index = (u64)addr >> 2; numReg = index / 2; - /* * Validate the input - check to see if address is on the * wrong boundary or beyond the end of the user area */ if ((addr & 3) || (numReg > PT_FPSCR)) break; - if (numReg < PT_FPR0) { - unsigned long freg = ptrace_get_reg(child, numReg); - if (index % 2) - freg = (freg & ~0xfffffffful) | (data & 0xfffffffful); - else - freg = (freg & 0xfffffffful) | (data << 32); - ret = ptrace_put_reg(child, numReg, freg); - } else { + /* Insure it is a register we let them change */ + if ((numReg == PT_ORIG_R3) + || ((numReg > PT_CCR) && (numReg < PT_FPR0))) + break; + if (numReg >= PT_FPR0) { flush_fp_to_thread(child); - ((unsigned int *)child->thread.regs)[index] = data; - ret = 0; } + if (numReg == PT_MSR) + data = (data & MSR_DEBUGCHANGE) + | (child->thread.regs->msr & ~MSR_DEBUGCHANGE); + ((u32*)child->thread.regs)[index] = data; + ret = 0; + break; + } + + case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */ + case PTRACE_CONT: { /* restart after signal. */ + ret = -EIO; + if (!valid_signal(data)) + break; + if (request == PTRACE_SYSCALL) + set_tsk_thread_flag(child, TIF_SYSCALL_TRACE); + else + clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); + child->exit_code = data; + /* make sure the single step bit is not set. */ + clear_single_step(child); + wake_up_process(child); + ret = 0; + break; + } + + /* + * make the child exit. Best I can do is send it a sigkill. + * perhaps it should be put in the status that it wants to + * exit. + */ + case PTRACE_KILL: { + ret = 0; + if (child->exit_state == EXIT_ZOMBIE) /* already dead */ + break; + child->exit_code = SIGKILL; + /* make sure the single step bit is not set. */ + clear_single_step(child); + wake_up_process(child); + break; + } + + case PTRACE_SINGLESTEP: { /* set the trap flag. */ + ret = -EIO; + if (!valid_signal(data)) + break; + clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); + set_single_step(child); + child->exit_code = data; + /* give it a chance to run. */ + wake_up_process(child); + ret = 0; break; } @@ -331,67 +334,95 @@ long compat_sys_ptrace(int request, int pid, unsigned long addr, break; } - case PTRACE_GETEVENTMSG: - ret = put_user(child->ptrace_message, (unsigned int __user *) data); + case PTRACE_SET_DEBUGREG: + ret = ptrace_set_debugreg(child, addr, data); break; - case PTRACE_GETREGS: { /* Get all pt_regs from the child. */ - int ui; - if (!access_ok(VERIFY_WRITE, (void __user *)data, - PT_REGS_COUNT * sizeof(int))) { - ret = -EIO; - break; + case PTRACE_DETACH: + ret = ptrace_detach(child, data); + break; + + case PPC_PTRACE_GETREGS: { /* Get GPRs 0 - 31. */ + int i; + unsigned long *reg = &((unsigned long *)child->thread.regs)[0]; + unsigned int __user *tmp = (unsigned int __user *)addr; + + for (i = 0; i < 32; i++) { + ret = put_user(*reg, tmp); + if (ret) + break; + reg++; + tmp++; } - ret = 0; - for (ui = 0; ui < PT_REGS_COUNT; ui ++) { - ret |= __put_user(ptrace_get_reg(child, ui), - (unsigned int __user *) data); - data += sizeof(int); + break; + } + + case PPC_PTRACE_SETREGS: { /* Set GPRs 0 - 31. */ + int i; + unsigned long *reg = &((unsigned long *)child->thread.regs)[0]; + unsigned int __user *tmp = (unsigned int __user *)addr; + + for (i = 0; i < 32; i++) { + ret = get_user(*reg, tmp); + if (ret) + break; + reg++; + tmp++; } break; } - case PTRACE_SETREGS: { /* Set all gp regs in the child. */ - unsigned long tmp; - int ui; - if (!access_ok(VERIFY_READ, (void __user *)data, - PT_REGS_COUNT * sizeof(int))) { - ret = -EIO; - break; + case PPC_PTRACE_GETFPREGS: { /* Get FPRs 0 - 31. */ + int i; + unsigned long *reg = &((unsigned long *)child->thread.fpr)[0]; + unsigned int __user *tmp = (unsigned int __user *)addr; + + flush_fp_to_thread(child); + + for (i = 0; i < 32; i++) { + ret = put_user(*reg, tmp); + if (ret) + break; + reg++; + tmp++; } - ret = 0; - for (ui = 0; ui < PT_REGS_COUNT; ui ++) { - ret = __get_user(tmp, (unsigned int __user *) data); + break; + } + + case PPC_PTRACE_SETFPREGS: { /* Get FPRs 0 - 31. */ + int i; + unsigned long *reg = &((unsigned long *)child->thread.fpr)[0]; + unsigned int __user *tmp = (unsigned int __user *)addr; + + flush_fp_to_thread(child); + + for (i = 0; i < 32; i++) { + ret = get_user(*reg, tmp); if (ret) break; - ptrace_put_reg(child, ui, tmp); - data += sizeof(int); + reg++; + tmp++; } break; } - case PTRACE_GETFPREGS: - case PTRACE_SETFPREGS: + case PTRACE_GETEVENTMSG: + ret = put_user(child->ptrace_message, (unsigned int __user *) data); + break; + +#ifdef CONFIG_ALTIVEC case PTRACE_GETVRREGS: - case PTRACE_SETVRREGS: - case PTRACE_GETREGS64: - case PTRACE_SETREGS64: - case PPC_PTRACE_GETFPREGS: - case PPC_PTRACE_SETFPREGS: - case PTRACE_KILL: - case PTRACE_SINGLESTEP: - case PTRACE_DETACH: - case PTRACE_SET_DEBUGREG: - case PTRACE_SYSCALL: - case PTRACE_CONT: - ret = arch_ptrace(child, request, addr, data); + /* Get the child altivec register state. */ + flush_altivec_to_thread(child); + ret = get_vrregs((unsigned long __user *)data, child); break; - /* Old reverse args ptrace callss */ - case PPC_PTRACE_GETREGS: /* Get GPRs 0 - 31. */ - case PPC_PTRACE_SETREGS: /* Set GPRs 0 - 31. */ - ret = compat_ptrace_old(child, request, addr, data); + case PTRACE_SETVRREGS: + /* Set the child altivec register state. */ + flush_altivec_to_thread(child); + ret = set_vrregs(child, (unsigned long __user *)data); break; +#endif default: ret = ptrace_request(child, request, addr, data); diff --git a/trunk/arch/powerpc/kernel/rtas_pci.c b/trunk/arch/powerpc/kernel/rtas_pci.c index a5de6211b97a..f2286822be09 100644 --- a/trunk/arch/powerpc/kernel/rtas_pci.c +++ b/trunk/arch/powerpc/kernel/rtas_pci.c @@ -278,8 +278,10 @@ void __init find_and_init_phbs(void) { struct device_node *node; struct pci_controller *phb; + unsigned int index; struct device_node *root = of_find_node_by_path("/"); + index = 0; for (node = of_get_next_child(root, NULL); node != NULL; node = of_get_next_child(root, node)) { @@ -293,7 +295,8 @@ void __init find_and_init_phbs(void) continue; rtas_setup_phb(phb); pci_process_bridge_OF_ranges(phb, node, 0); - isa_bridge_find_early(phb); + pci_setup_phb_io(phb, index == 0); + index++; } of_node_put(root); @@ -332,7 +335,7 @@ int pcibios_remove_root_bus(struct pci_controller *phb) return 1; } - rc = pcibios_unmap_io_space(b); + rc = unmap_bus_range(b); if (rc) { printk(KERN_ERR "%s: failed to unmap IO on bus %s\n", __FUNCTION__, b->name); diff --git a/trunk/arch/powerpc/kernel/setup-common.c b/trunk/arch/powerpc/kernel/setup-common.c index 4924c48cb1ff..ed07a198f8d6 100644 --- a/trunk/arch/powerpc/kernel/setup-common.c +++ b/trunk/arch/powerpc/kernel/setup-common.c @@ -32,7 +32,6 @@ #include #include #include -#include #include #include #include @@ -487,14 +486,6 @@ int check_legacy_ioport(unsigned long base_port) switch(base_port) { case I8042_DATA_REG: - if (!(np = of_find_compatible_node(NULL, NULL, "pnpPNP,303"))) - np = of_find_compatible_node(NULL, NULL, "pnpPNP,f03"); - if (np) { - parent = of_get_parent(np); - of_node_put(np); - np = parent; - break; - } np = of_find_node_by_type(NULL, "8042"); break; case FDC_BASE: /* FDC1 */ @@ -580,15 +571,3 @@ static int __init check_cache_coherency(void) late_initcall(check_cache_coherency); #endif /* CONFIG_CHECK_CACHE_COHERENCY */ - -#ifdef CONFIG_DEBUG_FS -struct dentry *powerpc_debugfs_root; - -static int powerpc_debugfs_init(void) -{ - powerpc_debugfs_root = debugfs_create_dir("powerpc", NULL); - - return powerpc_debugfs_root == NULL; -} -arch_initcall(powerpc_debugfs_init); -#endif diff --git a/trunk/arch/powerpc/kernel/setup_32.c b/trunk/arch/powerpc/kernel/setup_32.c index 7ec6ba56d83d..35f8f443c14f 100644 --- a/trunk/arch/powerpc/kernel/setup_32.c +++ b/trunk/arch/powerpc/kernel/setup_32.c @@ -262,11 +262,13 @@ void __init setup_arch(char **cmdline_p) * Systems with OF can look in the properties on the cpu node(s) * for a possibly more accurate value. */ - dcache_bsize = cur_cpu_spec->dcache_bsize; - icache_bsize = cur_cpu_spec->icache_bsize; - ucache_bsize = 0; - if (cpu_has_feature(CPU_FTR_UNIFIED_ID_CACHE)) - ucache_bsize = icache_bsize = dcache_bsize; + if (cpu_has_feature(CPU_FTR_SPLIT_ID_CACHE)) { + dcache_bsize = cur_cpu_spec->dcache_bsize; + icache_bsize = cur_cpu_spec->icache_bsize; + ucache_bsize = 0; + } else + ucache_bsize = dcache_bsize = icache_bsize + = cur_cpu_spec->dcache_bsize; /* reboot on panic */ panic_timeout = 180; diff --git a/trunk/arch/powerpc/kernel/setup_64.c b/trunk/arch/powerpc/kernel/setup_64.c index bc43bba05cf8..6018178708a5 100644 --- a/trunk/arch/powerpc/kernel/setup_64.c +++ b/trunk/arch/powerpc/kernel/setup_64.c @@ -350,11 +350,13 @@ void __init setup_system(void) { DBG(" -> setup_system()\n"); - /* Apply CPUs-specific fixups to kernel text (nop out sections - * not relevant to this CPU) + /* Apply the CPUs-specific and firmware specific fixups to kernel + * text (nop out sections not relevant to this CPU or this firmware) */ do_feature_fixups(cur_cpu_spec->cpu_features, &__start___ftr_fixup, &__stop___ftr_fixup); + do_feature_fixups(powerpc_firmware_features, + &__start___fw_ftr_fixup, &__stop___fw_ftr_fixup); /* * Unflatten the device-tree passed by prom_init or kexec @@ -392,12 +394,6 @@ void __init setup_system(void) if (ppc_md.init_early) ppc_md.init_early(); - /* Apply firmware specific fixups to kernel text (nop out - * sections not relevant to this firmware) - */ - do_feature_fixups(powerpc_firmware_features, - &__start___fw_ftr_fixup, &__stop___fw_ftr_fixup); - /* * We can discover serial ports now since the above did setup the * hash table management for us, thus ioremap works. We do that early diff --git a/trunk/arch/powerpc/kernel/signal.c b/trunk/arch/powerpc/kernel/signal.c deleted file mode 100644 index c434d6c4e4e6..000000000000 --- a/trunk/arch/powerpc/kernel/signal.c +++ /dev/null @@ -1,180 +0,0 @@ -/* - * Common signal handling code for both 32 and 64 bits - * - * Copyright (c) 2007 Benjamin Herrenschmidt, IBM Coproration - * Extracted from signal_32.c and signal_64.c - * - * This file is subject to the terms and conditions of the GNU General - * Public License. See the file README.legal in the main directory of - * this archive for more details. - */ - -#include -#include -#include -#include - -#include "signal.h" - -/* - * Allocate space for the signal frame - */ -void __user * get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, - size_t frame_size) -{ - unsigned long oldsp, newsp; - - /* Default to using normal stack */ - oldsp = regs->gpr[1]; - - /* Check for alt stack */ - if ((ka->sa.sa_flags & SA_ONSTACK) && - current->sas_ss_size && !on_sig_stack(oldsp)) - oldsp = (current->sas_ss_sp + current->sas_ss_size); - - /* Get aligned frame */ - newsp = (oldsp - frame_size) & ~0xFUL; - - /* Check access */ - if (!access_ok(VERIFY_WRITE, (void __user *)newsp, oldsp - newsp)) - return NULL; - - return (void __user *)newsp; -} - - -/* - * Restore the user process's signal mask - */ -void restore_sigmask(sigset_t *set) -{ - sigdelsetmask(set, ~_BLOCKABLE); - spin_lock_irq(¤t->sighand->siglock); - current->blocked = *set; - recalc_sigpending(); - spin_unlock_irq(¤t->sighand->siglock); -} - -static void check_syscall_restart(struct pt_regs *regs, struct k_sigaction *ka, - int has_handler) -{ - unsigned long ret = regs->gpr[3]; - int restart = 1; - - /* syscall ? */ - if (TRAP(regs) != 0x0C00) - return; - - /* error signalled ? */ - if (!(regs->ccr & 0x10000000)) - return; - - switch (ret) { - case ERESTART_RESTARTBLOCK: - case ERESTARTNOHAND: - /* ERESTARTNOHAND means that the syscall should only be - * restarted if there was no handler for the signal, and since - * we only get here if there is a handler, we dont restart. - */ - restart = !has_handler; - break; - case ERESTARTSYS: - /* ERESTARTSYS means to restart the syscall if there is no - * handler or the handler was registered with SA_RESTART - */ - restart = !has_handler || (ka->sa.sa_flags & SA_RESTART) != 0; - break; - case ERESTARTNOINTR: - /* ERESTARTNOINTR means that the syscall should be - * called again after the signal handler returns. - */ - break; - default: - return; - } - if (restart) { - if (ret == ERESTART_RESTARTBLOCK) - regs->gpr[0] = __NR_restart_syscall; - else - regs->gpr[3] = regs->orig_gpr3; - regs->nip -= 4; - regs->result = 0; - } else { - regs->result = -EINTR; - regs->gpr[3] = EINTR; - regs->ccr |= 0x10000000; - } -} - -int do_signal(sigset_t *oldset, struct pt_regs *regs) -{ - siginfo_t info; - int signr; - struct k_sigaction ka; - int ret; - int is32 = is_32bit_task(); - - if (test_thread_flag(TIF_RESTORE_SIGMASK)) - oldset = ¤t->saved_sigmask; - else if (!oldset) - oldset = ¤t->blocked; - - signr = get_signal_to_deliver(&info, &ka, regs, NULL); - - /* Is there any syscall restart business here ? */ - check_syscall_restart(regs, &ka, signr > 0); - - if (signr <= 0) { - /* No signal to deliver -- put the saved sigmask back */ - if (test_thread_flag(TIF_RESTORE_SIGMASK)) { - clear_thread_flag(TIF_RESTORE_SIGMASK); - sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); - } - return 0; /* no signals delivered */ - } - - /* - * Reenable the DABR before delivering the signal to - * user space. The DABR will have been cleared if it - * triggered inside the kernel. - */ - if (current->thread.dabr) - set_dabr(current->thread.dabr); - - if (is32) { - if (ka.sa.sa_flags & SA_SIGINFO) - ret = handle_rt_signal32(signr, &ka, &info, oldset, - regs); - else - ret = handle_signal32(signr, &ka, &info, oldset, - regs); - } else { - ret = handle_rt_signal64(signr, &ka, &info, oldset, regs); - } - - if (ret) { - spin_lock_irq(¤t->sighand->siglock); - sigorsets(¤t->blocked, ¤t->blocked, - &ka.sa.sa_mask); - if (!(ka.sa.sa_flags & SA_NODEFER)) - sigaddset(¤t->blocked, signr); - recalc_sigpending(); - spin_unlock_irq(¤t->sighand->siglock); - - /* - * A signal was successfully delivered; the saved sigmask is in - * its frame, and we can clear the TIF_RESTORE_SIGMASK flag. - */ - if (test_thread_flag(TIF_RESTORE_SIGMASK)) - clear_thread_flag(TIF_RESTORE_SIGMASK); - } - - return ret; -} - -long sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, - unsigned long r5, unsigned long r6, unsigned long r7, - unsigned long r8, struct pt_regs *regs) -{ - return do_sigaltstack(uss, uoss, regs->gpr[1]); -} diff --git a/trunk/arch/powerpc/kernel/signal.h b/trunk/arch/powerpc/kernel/signal.h deleted file mode 100644 index 77efb3d5465a..000000000000 --- a/trunk/arch/powerpc/kernel/signal.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (c) 2007 Benjamin Herrenschmidt, IBM Coproration - * Extracted from signal_32.c and signal_64.c - * - * This file is subject to the terms and conditions of the GNU General - * Public License. See the file README.legal in the main directory of - * this archive for more details. - */ - -#ifndef _POWERPC_ARCH_SIGNAL_H -#define _POWERPC_ARCH_SIGNAL_H - -#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) - -extern void __user * get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, - size_t frame_size); -extern void restore_sigmask(sigset_t *set); - -extern int handle_signal32(unsigned long sig, struct k_sigaction *ka, - siginfo_t *info, sigset_t *oldset, - struct pt_regs *regs); - -extern int handle_rt_signal32(unsigned long sig, struct k_sigaction *ka, - siginfo_t *info, sigset_t *oldset, - struct pt_regs *regs); - - -#ifdef CONFIG_PPC64 - -static inline int is_32bit_task(void) -{ - return test_thread_flag(TIF_32BIT); -} - -extern int handle_rt_signal64(int signr, struct k_sigaction *ka, - siginfo_t *info, sigset_t *set, - struct pt_regs *regs); - -#else /* CONFIG_PPC64 */ - -static inline int is_32bit_task(void) -{ - return 1; -} - -static inline int handle_rt_signal64(int signr, struct k_sigaction *ka, - siginfo_t *info, sigset_t *set, - struct pt_regs *regs) -{ - return -EFAULT; -} - -#endif /* !defined(CONFIG_PPC64) */ - -#endif /* _POWERPC_ARCH_SIGNAL_H */ diff --git a/trunk/arch/powerpc/kernel/signal_32.c b/trunk/arch/powerpc/kernel/signal_32.c index 590057e9e987..dd1dca5bfa81 100644 --- a/trunk/arch/powerpc/kernel/signal_32.c +++ b/trunk/arch/powerpc/kernel/signal_32.c @@ -51,11 +51,12 @@ #include #endif -#include "signal.h" - #undef DEBUG_SIG +#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) + #ifdef CONFIG_PPC64 +#define do_signal do_signal32 #define sys_sigsuspend compat_sys_sigsuspend #define sys_rt_sigsuspend compat_sys_rt_sigsuspend #define sys_rt_sigreturn compat_sys_rt_sigreturn @@ -230,6 +231,8 @@ static inline int restore_general_regs(struct pt_regs *regs, #endif /* CONFIG_PPC64 */ +int do_signal(sigset_t *oldset, struct pt_regs *regs); + /* * Atomically swap in the new signal mask, and wait for a signal. */ @@ -248,6 +251,14 @@ long sys_sigsuspend(old_sigset_t mask) return -ERESTARTNOHAND; } +#ifdef CONFIG_PPC32 +long sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, int r5, + int r6, int r7, int r8, struct pt_regs *regs) +{ + return do_sigaltstack(uss, uoss, regs->gpr[1]); +} +#endif + long sys_sigaction(int sig, struct old_sigaction __user *act, struct old_sigaction __user *oact) { @@ -282,17 +293,14 @@ long sys_sigaction(int sig, struct old_sigaction __user *act, /* * When we have signals to deliver, we set up on the * user stack, going down from the original stack pointer: - * an ABI gap of 56 words - * an mcontext struct + * a sigregs struct * a sigcontext struct * a gap of __SIGNAL_FRAMESIZE bytes * - * Each of these things must be a multiple of 16 bytes in size. The following - * structure represent all of this except the __SIGNAL_FRAMESIZE gap + * Each of these things must be a multiple of 16 bytes in size. * */ -struct sigframe { - struct sigcontext sctx; /* the sigcontext */ +struct sigregs { struct mcontext mctx; /* all the register values */ /* * Programs using the rs6000/xcoff abi can save up to 19 gp @@ -695,22 +703,44 @@ int compat_sys_sigaltstack(u32 __new, u32 __old, int r5, } #endif /* CONFIG_PPC64 */ + +/* + * Restore the user process's signal mask + */ +#ifdef CONFIG_PPC64 +extern void restore_sigmask(sigset_t *set); +#else /* CONFIG_PPC64 */ +static void restore_sigmask(sigset_t *set) +{ + sigdelsetmask(set, ~_BLOCKABLE); + spin_lock_irq(¤t->sighand->siglock); + current->blocked = *set; + recalc_sigpending(); + spin_unlock_irq(¤t->sighand->siglock); +} +#endif + /* * Set up a signal frame for a "real-time" signal handler * (one which gets siginfo). */ -int handle_rt_signal32(unsigned long sig, struct k_sigaction *ka, +static int handle_rt_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info, sigset_t *oldset, - struct pt_regs *regs) + struct pt_regs *regs, unsigned long newsp) { struct rt_sigframe __user *rt_sf; struct mcontext __user *frame; - unsigned long newsp = 0; + unsigned long origsp = newsp; /* Set up Signal Frame */ /* Put a Real Time Context onto stack */ - rt_sf = get_sigframe(ka, regs, sizeof(*rt_sf)); - if (unlikely(rt_sf == NULL)) + newsp -= sizeof(*rt_sf); + rt_sf = (struct rt_sigframe __user *)newsp; + + /* create a stack frame for the caller of the handler */ + newsp -= __SIGNAL_FRAMESIZE + 16; + + if (!access_ok(VERIFY_WRITE, (void __user *)newsp, origsp - newsp)) goto badframe; /* Put the siginfo & fill in most of the ucontext */ @@ -740,12 +770,8 @@ int handle_rt_signal32(unsigned long sig, struct k_sigaction *ka, current->thread.fpscr.val = 0; /* turn off all fp exceptions */ - /* create a stack frame for the caller of the handler */ - newsp = ((unsigned long)rt_sf) - (__SIGNAL_FRAMESIZE + 16); if (put_user(regs->gpr[1], (u32 __user *)newsp)) goto badframe; - - /* Fill registers for signal handler */ regs->gpr[1] = newsp; regs->gpr[3] = sig; regs->gpr[4] = (unsigned long) &rt_sf->info; @@ -989,18 +1015,27 @@ int sys_debug_setcontext(struct ucontext __user *ctx, /* * OK, we're invoking a handler */ -int handle_signal32(unsigned long sig, struct k_sigaction *ka, - siginfo_t *info, sigset_t *oldset, struct pt_regs *regs) +static int handle_signal(unsigned long sig, struct k_sigaction *ka, + siginfo_t *info, sigset_t *oldset, struct pt_regs *regs, + unsigned long newsp) { struct sigcontext __user *sc; - struct sigframe __user *frame; - unsigned long newsp = 0; + struct sigregs __user *frame; + unsigned long origsp = newsp; /* Set up Signal Frame */ - frame = get_sigframe(ka, regs, sizeof(*frame)); - if (unlikely(frame == NULL)) + newsp -= sizeof(struct sigregs); + frame = (struct sigregs __user *) newsp; + + /* Put a sigcontext on the stack */ + newsp -= sizeof(*sc); + sc = (struct sigcontext __user *) newsp; + + /* create a stack frame for the caller of the handler */ + newsp -= __SIGNAL_FRAMESIZE; + + if (!access_ok(VERIFY_WRITE, (void __user *) newsp, origsp - newsp)) goto badframe; - sc = (struct sigcontext __user *) &frame->sctx; #if _NSIG != 64 #error "Please adjust handle_signal()" @@ -1012,7 +1047,7 @@ int handle_signal32(unsigned long sig, struct k_sigaction *ka, #else || __put_user(oldset->sig[1], &sc->_unused[3]) #endif - || __put_user(to_user_ptr(&frame->mctx), &sc->regs) + || __put_user(to_user_ptr(frame), &sc->regs) || __put_user(sig, &sc->signal)) goto badframe; @@ -1028,11 +1063,8 @@ int handle_signal32(unsigned long sig, struct k_sigaction *ka, current->thread.fpscr.val = 0; /* turn off all fp exceptions */ - /* create a stack frame for the caller of the handler */ - newsp = ((unsigned long)frame) - __SIGNAL_FRAMESIZE; if (put_user(regs->gpr[1], (u32 __user *)newsp)) goto badframe; - regs->gpr[1] = newsp; regs->gpr[3] = sig; regs->gpr[4] = (unsigned long) sc; @@ -1094,3 +1126,106 @@ long sys_sigreturn(int r3, int r4, int r5, int r6, int r7, int r8, force_sig(SIGSEGV, current); return 0; } + +/* + * Note that 'init' is a special process: it doesn't get signals it doesn't + * want to handle. Thus you cannot kill init even with a SIGKILL even by + * mistake. + */ +int do_signal(sigset_t *oldset, struct pt_regs *regs) +{ + siginfo_t info; + struct k_sigaction ka; + unsigned int newsp; + int signr, ret; + +#ifdef CONFIG_PPC32 + if (try_to_freeze()) { + signr = 0; + if (!signal_pending(current)) + goto no_signal; + } +#endif + + if (test_thread_flag(TIF_RESTORE_SIGMASK)) + oldset = ¤t->saved_sigmask; + else if (!oldset) + oldset = ¤t->blocked; + + signr = get_signal_to_deliver(&info, &ka, regs, NULL); +#ifdef CONFIG_PPC32 +no_signal: +#endif + if (TRAP(regs) == 0x0C00 /* System Call! */ + && regs->ccr & 0x10000000 /* error signalled */ + && ((ret = regs->gpr[3]) == ERESTARTSYS + || ret == ERESTARTNOHAND || ret == ERESTARTNOINTR + || ret == ERESTART_RESTARTBLOCK)) { + + if (signr > 0 + && (ret == ERESTARTNOHAND || ret == ERESTART_RESTARTBLOCK + || (ret == ERESTARTSYS + && !(ka.sa.sa_flags & SA_RESTART)))) { + /* make the system call return an EINTR error */ + regs->result = -EINTR; + regs->gpr[3] = EINTR; + /* note that the cr0.SO bit is already set */ + } else { + regs->nip -= 4; /* Back up & retry system call */ + regs->result = 0; + regs->trap = 0; + if (ret == ERESTART_RESTARTBLOCK) + regs->gpr[0] = __NR_restart_syscall; + else + regs->gpr[3] = regs->orig_gpr3; + } + } + + if (signr == 0) { + /* No signal to deliver -- put the saved sigmask back */ + if (test_thread_flag(TIF_RESTORE_SIGMASK)) { + clear_thread_flag(TIF_RESTORE_SIGMASK); + sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); + } + return 0; /* no signals delivered */ + } + + if ((ka.sa.sa_flags & SA_ONSTACK) && current->sas_ss_size + && !on_sig_stack(regs->gpr[1])) + newsp = current->sas_ss_sp + current->sas_ss_size; + else + newsp = regs->gpr[1]; + newsp &= ~0xfUL; + +#ifdef CONFIG_PPC64 + /* + * Reenable the DABR before delivering the signal to + * user space. The DABR will have been cleared if it + * triggered inside the kernel. + */ + if (current->thread.dabr) + set_dabr(current->thread.dabr); +#endif + + /* Whee! Actually deliver the signal. */ + if (ka.sa.sa_flags & SA_SIGINFO) + ret = handle_rt_signal(signr, &ka, &info, oldset, regs, newsp); + else + ret = handle_signal(signr, &ka, &info, oldset, regs, newsp); + + if (ret) { + spin_lock_irq(¤t->sighand->siglock); + sigorsets(¤t->blocked, ¤t->blocked, + &ka.sa.sa_mask); + if (!(ka.sa.sa_flags & SA_NODEFER)) + sigaddset(¤t->blocked, signr); + recalc_sigpending(); + spin_unlock_irq(¤t->sighand->siglock); + /* A signal was successfully delivered; the saved sigmask is in + its frame, and we can clear the TIF_RESTORE_SIGMASK flag */ + if (test_thread_flag(TIF_RESTORE_SIGMASK)) + clear_thread_flag(TIF_RESTORE_SIGMASK); + } + + return ret; +} diff --git a/trunk/arch/powerpc/kernel/signal_64.c b/trunk/arch/powerpc/kernel/signal_64.c index de895e6d8c62..b27e26852fdb 100644 --- a/trunk/arch/powerpc/kernel/signal_64.c +++ b/trunk/arch/powerpc/kernel/signal_64.c @@ -34,10 +34,10 @@ #include #include -#include "signal.h" - #define DEBUG_SIG 0 +#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) + #define GP_REGS_SIZE min(sizeof(elf_gregset_t), sizeof(struct pt_regs)) #define FP_REGS_SIZE sizeof(elf_fpregset_t) @@ -64,6 +64,14 @@ struct rt_sigframe { char abigap[288]; } __attribute__ ((aligned (16))); +long sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, unsigned long r5, + unsigned long r6, unsigned long r7, unsigned long r8, + struct pt_regs *regs) +{ + return do_sigaltstack(uss, uoss, regs->gpr[1]); +} + + /* * Set up the sigcontext for the signal frame. */ @@ -199,6 +207,25 @@ static long restore_sigcontext(struct pt_regs *regs, sigset_t *set, int sig, return err; } +/* + * Allocate space for the signal frame + */ +static inline void __user * get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, + size_t frame_size) +{ + unsigned long newsp; + + /* Default to using normal stack */ + newsp = regs->gpr[1]; + + if ((ka->sa.sa_flags & SA_ONSTACK) && current->sas_ss_size) { + if (! on_sig_stack(regs->gpr[1])) + newsp = (current->sas_ss_sp + current->sas_ss_size); + } + + return (void __user *)((newsp - frame_size) & -16ul); +} + /* * Setup the trampoline code on the stack */ @@ -225,6 +252,19 @@ static long setup_trampoline(unsigned int syscall, unsigned int __user *tramp) return err; } +/* + * Restore the user process's signal mask (also used by signal32.c) + */ +void restore_sigmask(sigset_t *set) +{ + sigdelsetmask(set, ~_BLOCKABLE); + spin_lock_irq(¤t->sighand->siglock); + current->blocked = *set; + recalc_sigpending(); + spin_unlock_irq(¤t->sighand->siglock); +} + + /* * Handle {get,set,swap}_context operations */ @@ -319,7 +359,7 @@ int sys_rt_sigreturn(unsigned long r3, unsigned long r4, unsigned long r5, return 0; } -int handle_rt_signal64(int signr, struct k_sigaction *ka, siginfo_t *info, +static int setup_rt_frame(int signr, struct k_sigaction *ka, siginfo_t *info, sigset_t *set, struct pt_regs *regs) { /* Handler is *really* a pointer to the function descriptor for @@ -333,7 +373,8 @@ int handle_rt_signal64(int signr, struct k_sigaction *ka, siginfo_t *info, long err = 0; frame = get_sigframe(ka, regs, sizeof(*frame)); - if (unlikely(frame == NULL)) + + if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) goto badframe; err |= __put_user(&frame->info, &frame->pinfo); @@ -370,7 +411,7 @@ int handle_rt_signal64(int signr, struct k_sigaction *ka, siginfo_t *info, funct_desc_ptr = (func_descr_t __user *) ka->sa.sa_handler; /* Allocate a dummy caller frame for the signal handler. */ - newsp = ((unsigned long)frame) - __SIGNAL_FRAMESIZE; + newsp = (unsigned long)frame - __SIGNAL_FRAMESIZE; err |= put_user(regs->gpr[1], (unsigned long __user *)newsp); /* Set up "regs" so we "return" to the signal handler. */ @@ -401,3 +442,134 @@ int handle_rt_signal64(int signr, struct k_sigaction *ka, siginfo_t *info, force_sigsegv(signr, current); return 0; } + + +/* + * OK, we're invoking a handler + */ +static int handle_signal(unsigned long sig, struct k_sigaction *ka, + siginfo_t *info, sigset_t *oldset, struct pt_regs *regs) +{ + int ret; + + /* Set up Signal Frame */ + ret = setup_rt_frame(sig, ka, info, oldset, regs); + + if (ret) { + spin_lock_irq(¤t->sighand->siglock); + sigorsets(¤t->blocked, ¤t->blocked, &ka->sa.sa_mask); + if (!(ka->sa.sa_flags & SA_NODEFER)) + sigaddset(¤t->blocked,sig); + recalc_sigpending(); + spin_unlock_irq(¤t->sighand->siglock); + } + + return ret; +} + +static inline void syscall_restart(struct pt_regs *regs, struct k_sigaction *ka) +{ + switch ((int)regs->result) { + case -ERESTART_RESTARTBLOCK: + case -ERESTARTNOHAND: + /* ERESTARTNOHAND means that the syscall should only be + * restarted if there was no handler for the signal, and since + * we only get here if there is a handler, we dont restart. + */ + regs->result = -EINTR; + regs->gpr[3] = EINTR; + regs->ccr |= 0x10000000; + break; + case -ERESTARTSYS: + /* ERESTARTSYS means to restart the syscall if there is no + * handler or the handler was registered with SA_RESTART + */ + if (!(ka->sa.sa_flags & SA_RESTART)) { + regs->result = -EINTR; + regs->gpr[3] = EINTR; + regs->ccr |= 0x10000000; + break; + } + /* fallthrough */ + case -ERESTARTNOINTR: + /* ERESTARTNOINTR means that the syscall should be + * called again after the signal handler returns. + */ + regs->gpr[3] = regs->orig_gpr3; + regs->nip -= 4; + regs->result = 0; + break; + } +} + +/* + * Note that 'init' is a special process: it doesn't get signals it doesn't + * want to handle. Thus you cannot kill init even with a SIGKILL even by + * mistake. + */ +int do_signal(sigset_t *oldset, struct pt_regs *regs) +{ + siginfo_t info; + int signr; + struct k_sigaction ka; + + /* + * If the current thread is 32 bit - invoke the + * 32 bit signal handling code + */ + if (test_thread_flag(TIF_32BIT)) + return do_signal32(oldset, regs); + + if (test_thread_flag(TIF_RESTORE_SIGMASK)) + oldset = ¤t->saved_sigmask; + else if (!oldset) + oldset = ¤t->blocked; + + signr = get_signal_to_deliver(&info, &ka, regs, NULL); + if (signr > 0) { + int ret; + + /* Whee! Actually deliver the signal. */ + if (TRAP(regs) == 0x0C00) + syscall_restart(regs, &ka); + + /* + * Reenable the DABR before delivering the signal to + * user space. The DABR will have been cleared if it + * triggered inside the kernel. + */ + if (current->thread.dabr) + set_dabr(current->thread.dabr); + + ret = handle_signal(signr, &ka, &info, oldset, regs); + + /* If a signal was successfully delivered, the saved sigmask is in + its frame, and we can clear the TIF_RESTORE_SIGMASK flag */ + if (ret && test_thread_flag(TIF_RESTORE_SIGMASK)) + clear_thread_flag(TIF_RESTORE_SIGMASK); + + return ret; + } + + if (TRAP(regs) == 0x0C00) { /* System Call! */ + if ((int)regs->result == -ERESTARTNOHAND || + (int)regs->result == -ERESTARTSYS || + (int)regs->result == -ERESTARTNOINTR) { + regs->gpr[3] = regs->orig_gpr3; + regs->nip -= 4; /* Back up & retry system call */ + regs->result = 0; + } else if ((int)regs->result == -ERESTART_RESTARTBLOCK) { + regs->gpr[0] = __NR_restart_syscall; + regs->nip -= 4; + regs->result = 0; + } + } + /* No signal to deliver -- put the saved sigmask back */ + if (test_thread_flag(TIF_RESTORE_SIGMASK)) { + clear_thread_flag(TIF_RESTORE_SIGMASK); + sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); + } + + return 0; +} +EXPORT_SYMBOL(do_signal); diff --git a/trunk/arch/powerpc/kernel/sysfs.c b/trunk/arch/powerpc/kernel/sysfs.c index 55d29ed4b7a0..68991c2d4a1b 100644 --- a/trunk/arch/powerpc/kernel/sysfs.c +++ b/trunk/arch/powerpc/kernel/sysfs.c @@ -442,14 +442,12 @@ int sysfs_add_device_to_node(struct sys_device *dev, int nid) return sysfs_create_link(&node->sysdev.kobj, &dev->kobj, kobject_name(&dev->kobj)); } -EXPORT_SYMBOL_GPL(sysfs_add_device_to_node); void sysfs_remove_device_from_node(struct sys_device *dev, int nid) { struct node *node = &node_devices[nid]; sysfs_remove_link(&node->sysdev.kobj, kobject_name(&dev->kobj)); } -EXPORT_SYMBOL_GPL(sysfs_remove_device_from_node); #else static void register_nodes(void) @@ -459,6 +457,9 @@ static void register_nodes(void) #endif +EXPORT_SYMBOL_GPL(sysfs_add_device_to_node); +EXPORT_SYMBOL_GPL(sysfs_remove_device_from_node); + /* Only valid if CPU is present. */ static ssize_t show_physical_id(struct sys_device *dev, char *buf) { diff --git a/trunk/arch/powerpc/kernel/time.c b/trunk/arch/powerpc/kernel/time.c index e5df167f7824..2c8564d54e4d 100644 --- a/trunk/arch/powerpc/kernel/time.c +++ b/trunk/arch/powerpc/kernel/time.c @@ -77,8 +77,9 @@ /* keep track of when we need to update the rtc */ time_t last_rtc_update; #ifdef CONFIG_PPC_ISERIES -static unsigned long __initdata iSeries_recal_titan; -static signed long __initdata iSeries_recal_tb; +unsigned long iSeries_recal_titan = 0; +unsigned long iSeries_recal_tb = 0; +static unsigned long first_settimeofday = 1; #endif /* The decrementer counts down by 128 every 128ns on a 601. */ @@ -112,9 +113,8 @@ u64 ticklen_to_xs; /* 0.64 fraction */ DEFINE_SPINLOCK(rtc_lock); EXPORT_SYMBOL_GPL(rtc_lock); -static u64 tb_to_ns_scale __read_mostly; -static unsigned tb_to_ns_shift __read_mostly; -static unsigned long boot_tb __read_mostly; +u64 tb_to_ns_scale; +unsigned tb_to_ns_shift; struct gettimeofday_struct do_gtod; @@ -214,6 +214,7 @@ static void account_process_time(struct pt_regs *regs) run_posix_cpu_timers(current); } +#ifdef CONFIG_PPC_SPLPAR /* * Stuff for accounting stolen time. */ @@ -221,28 +222,19 @@ struct cpu_purr_data { int initialized; /* thread is running */ u64 tb; /* last TB value read */ u64 purr; /* last PURR value read */ + spinlock_t lock; }; -/* - * Each entry in the cpu_purr_data array is manipulated only by its - * "owner" cpu -- usually in the timer interrupt but also occasionally - * in process context for cpu online. As long as cpus do not touch - * each others' cpu_purr_data, disabling local interrupts is - * sufficient to serialize accesses. - */ static DEFINE_PER_CPU(struct cpu_purr_data, cpu_purr_data); static void snapshot_tb_and_purr(void *data) { - unsigned long flags; struct cpu_purr_data *p = &__get_cpu_var(cpu_purr_data); - local_irq_save(flags); p->tb = mftb(); p->purr = mfspr(SPRN_PURR); wmb(); p->initialized = 1; - local_irq_restore(flags); } /* @@ -250,14 +242,15 @@ static void snapshot_tb_and_purr(void *data) */ void snapshot_timebases(void) { + int cpu; + if (!cpu_has_feature(CPU_FTR_PURR)) return; + for_each_possible_cpu(cpu) + spin_lock_init(&per_cpu(cpu_purr_data, cpu).lock); on_each_cpu(snapshot_tb_and_purr, NULL, 0, 1); } -/* - * Must be called with interrupts disabled. - */ void calculate_steal_time(void) { u64 tb, purr; @@ -269,6 +262,7 @@ void calculate_steal_time(void) pme = &per_cpu(cpu_purr_data, smp_processor_id()); if (!pme->initialized) return; /* this can happen in early boot */ + spin_lock(&pme->lock); tb = mftb(); purr = mfspr(SPRN_PURR); stolen = (tb - pme->tb) - (purr - pme->purr); @@ -276,9 +270,9 @@ void calculate_steal_time(void) account_steal_time(current, stolen); pme->tb = tb; pme->purr = purr; + spin_unlock(&pme->lock); } -#ifdef CONFIG_PPC_SPLPAR /* * Must be called before the cpu is added to the online map when * a cpu is being brought up at runtime. @@ -290,12 +284,12 @@ static void snapshot_purr(void) if (!cpu_has_feature(CPU_FTR_PURR)) return; - local_irq_save(flags); pme = &per_cpu(cpu_purr_data, smp_processor_id()); + spin_lock_irqsave(&pme->lock, flags); pme->tb = mftb(); pme->purr = mfspr(SPRN_PURR); pme->initialized = 1; - local_irq_restore(flags); + spin_unlock_irqrestore(&pme->lock, flags); } #endif /* CONFIG_PPC_SPLPAR */ @@ -556,15 +550,10 @@ EXPORT_SYMBOL(profile_pc); * returned by the service processor for the timebase frequency. */ -static int __init iSeries_tb_recal(void) +static void iSeries_tb_recal(void) { struct div_result divres; unsigned long titan, tb; - - /* Make sure we only run on iSeries */ - if (!firmware_has_feature(FW_FEATURE_ISERIES)) - return -ENODEV; - tb = get_tb(); titan = HvCallXm_loadTod(); if ( iSeries_recal_titan ) { @@ -605,18 +594,8 @@ static int __init iSeries_tb_recal(void) } iSeries_recal_titan = titan; iSeries_recal_tb = tb; - - return 0; -} -late_initcall(iSeries_tb_recal); - -/* Called from platform early init */ -void __init iSeries_time_init_early(void) -{ - iSeries_recal_tb = get_tb(); - iSeries_recal_titan = HvCallXm_loadTod(); } -#endif /* CONFIG_PPC_ISERIES */ +#endif /* * For iSeries shared processors, we have to let the hypervisor @@ -756,7 +735,7 @@ unsigned long long sched_clock(void) { if (__USE_RTC()) return get_rtc(); - return mulhdu(get_tb() - boot_tb, tb_to_ns_scale) << tb_to_ns_shift; + return mulhdu(get_tb(), tb_to_ns_scale) << tb_to_ns_shift; } int do_settimeofday(struct timespec *tv) @@ -780,6 +759,12 @@ int do_settimeofday(struct timespec *tv) * to the RTC again, or write to the RTC but then they don't call * settimeofday to perform this operation. */ +#ifdef CONFIG_PPC_ISERIES + if (firmware_has_feature(FW_FEATURE_ISERIES) && first_settimeofday) { + iSeries_tb_recal(); + first_settimeofday = 0; + } +#endif /* Make userspace gettimeofday spin until we're done. */ ++vdso_data->tb_update_count; @@ -975,8 +960,6 @@ void __init time_init(void) } tb_to_ns_scale = scale; tb_to_ns_shift = shift; - /* Save the current timebase to pretty up CONFIG_PRINTK_TIME */ - boot_tb = get_tb(); tm = get_boot_time(); diff --git a/trunk/arch/powerpc/kernel/vdso.c b/trunk/arch/powerpc/kernel/vdso.c index cef01e4e8989..4245579edb4e 100644 --- a/trunk/arch/powerpc/kernel/vdso.c +++ b/trunk/arch/powerpc/kernel/vdso.c @@ -670,7 +670,7 @@ static int __init vdso_init(void) /* * Fill up the "systemcfg" stuff for backward compatiblity */ - strcpy((char *)vdso_data->eye_catcher, "SYSTEMCFG:PPC64"); + strcpy(vdso_data->eye_catcher, "SYSTEMCFG:PPC64"); vdso_data->version.major = SYSTEMCFG_MAJOR; vdso_data->version.minor = SYSTEMCFG_MINOR; vdso_data->processor = mfspr(SPRN_PVR); diff --git a/trunk/arch/powerpc/kernel/vmlinux.lds.S b/trunk/arch/powerpc/kernel/vmlinux.lds.S index ae4acd84143d..21c39ff2dc39 100644 --- a/trunk/arch/powerpc/kernel/vmlinux.lds.S +++ b/trunk/arch/powerpc/kernel/vmlinux.lds.S @@ -7,7 +7,6 @@ #define PROVIDE32(x) PROVIDE(x) #endif #include -#include ENTRY(_stext) @@ -212,11 +211,6 @@ SECTIONS *(.data.cacheline_aligned) } - . = ALIGN(L1_CACHE_BYTES); - .data.read_mostly : { - *(.data.read_mostly) - } - . = ALIGN(PAGE_SIZE); __data_nosave : { __nosave_begin = .; diff --git a/trunk/arch/powerpc/mm/44x_mmu.c b/trunk/arch/powerpc/mm/44x_mmu.c index c3df50476539..ca4dcb07a939 100644 --- a/trunk/arch/powerpc/mm/44x_mmu.c +++ b/trunk/arch/powerpc/mm/44x_mmu.c @@ -12,6 +12,7 @@ * Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au) * and Cort Dougan (PReP) (cort@cs.nmt.edu) * Copyright (C) 1996 Paul Mackerras + * Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk). * * Derived from "arch/i386/mm/init.c" * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds diff --git a/trunk/arch/powerpc/mm/4xx_mmu.c b/trunk/arch/powerpc/mm/4xx_mmu.c index 7ff2609b64d1..838e09db71d9 100644 --- a/trunk/arch/powerpc/mm/4xx_mmu.c +++ b/trunk/arch/powerpc/mm/4xx_mmu.c @@ -9,6 +9,7 @@ * Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au) * and Cort Dougan (PReP) (cort@cs.nmt.edu) * Copyright (C) 1996 Paul Mackerras + * Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk). * * Derived from "arch/i386/mm/init.c" * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds diff --git a/trunk/arch/powerpc/mm/Makefile b/trunk/arch/powerpc/mm/Makefile index 7e4d27ad3dee..4f839c6a9768 100644 --- a/trunk/arch/powerpc/mm/Makefile +++ b/trunk/arch/powerpc/mm/Makefile @@ -11,7 +11,8 @@ obj-$(CONFIG_PPC32) += init_32.o pgtable_32.o mmu_context_32.o hash-$(CONFIG_PPC_NATIVE) := hash_native_64.o obj-$(CONFIG_PPC64) += init_64.o pgtable_64.o mmu_context_64.o \ hash_utils_64.o hash_low_64.o tlb_64.o \ - slb_low.o slb.o stab.o mmap.o $(hash-y) + slb_low.o slb.o stab.o mmap.o imalloc.o \ + $(hash-y) obj-$(CONFIG_PPC_STD_MMU_32) += ppc_mmu_32.o hash_low_32.o tlb_32.o obj-$(CONFIG_40x) += 4xx_mmu.o obj-$(CONFIG_44x) += 44x_mmu.o diff --git a/trunk/arch/powerpc/mm/fault.c b/trunk/arch/powerpc/mm/fault.c index 0ece51310bfe..115b25f50bf8 100644 --- a/trunk/arch/powerpc/mm/fault.c +++ b/trunk/arch/powerpc/mm/fault.c @@ -380,7 +380,7 @@ int __kprobes do_page_fault(struct pt_regs *regs, unsigned long address, } printk("VM: killing process %s\n", current->comm); if (user_mode(regs)) - do_group_exit(SIGKILL); + do_exit(SIGKILL); return SIGKILL; do_sigbus: diff --git a/trunk/arch/powerpc/mm/fsl_booke_mmu.c b/trunk/arch/powerpc/mm/fsl_booke_mmu.c index afab247d472f..123da03ab118 100644 --- a/trunk/arch/powerpc/mm/fsl_booke_mmu.c +++ b/trunk/arch/powerpc/mm/fsl_booke_mmu.c @@ -14,6 +14,7 @@ * Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au) * and Cort Dougan (PReP) (cort@cs.nmt.edu) * Copyright (C) 1996 Paul Mackerras + * Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk). * * Derived from "arch/i386/mm/init.c" * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds diff --git a/trunk/arch/powerpc/mm/hash_native_64.c b/trunk/arch/powerpc/mm/hash_native_64.c index 6ba9b47e55af..4a20d890e2f4 100644 --- a/trunk/arch/powerpc/mm/hash_native_64.c +++ b/trunk/arch/powerpc/mm/hash_native_64.c @@ -104,7 +104,7 @@ static inline void tlbie(unsigned long va, int psize, int local) spin_unlock(&native_tlbie_lock); } -static inline void native_lock_hpte(struct hash_pte *hptep) +static inline void native_lock_hpte(hpte_t *hptep) { unsigned long *word = &hptep->v; @@ -116,7 +116,7 @@ static inline void native_lock_hpte(struct hash_pte *hptep) } } -static inline void native_unlock_hpte(struct hash_pte *hptep) +static inline void native_unlock_hpte(hpte_t *hptep) { unsigned long *word = &hptep->v; @@ -128,7 +128,7 @@ static long native_hpte_insert(unsigned long hpte_group, unsigned long va, unsigned long pa, unsigned long rflags, unsigned long vflags, int psize) { - struct hash_pte *hptep = htab_address + hpte_group; + hpte_t *hptep = htab_address + hpte_group; unsigned long hpte_v, hpte_r; int i; @@ -163,7 +163,7 @@ static long native_hpte_insert(unsigned long hpte_group, unsigned long va, hptep->r = hpte_r; /* Guarantee the second dword is visible before the valid bit */ - eieio(); + __asm__ __volatile__ ("eieio" : : : "memory"); /* * Now set the first dword including the valid bit * NOTE: this also unlocks the hpte @@ -177,7 +177,7 @@ static long native_hpte_insert(unsigned long hpte_group, unsigned long va, static long native_hpte_remove(unsigned long hpte_group) { - struct hash_pte *hptep; + hpte_t *hptep; int i; int slot_offset; unsigned long hpte_v; @@ -217,7 +217,7 @@ static long native_hpte_remove(unsigned long hpte_group) static long native_hpte_updatepp(unsigned long slot, unsigned long newpp, unsigned long va, int psize, int local) { - struct hash_pte *hptep = htab_address + slot; + hpte_t *hptep = htab_address + slot; unsigned long hpte_v, want_v; int ret = 0; @@ -233,14 +233,15 @@ static long native_hpte_updatepp(unsigned long slot, unsigned long newpp, /* Even if we miss, we need to invalidate the TLB */ if (!HPTE_V_COMPARE(hpte_v, want_v) || !(hpte_v & HPTE_V_VALID)) { DBG_LOW(" -> miss\n"); + native_unlock_hpte(hptep); ret = -1; } else { DBG_LOW(" -> hit\n"); /* Update the HPTE */ hptep->r = (hptep->r & ~(HPTE_R_PP | HPTE_R_N)) | (newpp & (HPTE_R_PP | HPTE_R_N | HPTE_R_C)); + native_unlock_hpte(hptep); } - native_unlock_hpte(hptep); /* Ensure it is out of the tlb too. */ tlbie(va, psize, local); @@ -250,7 +251,7 @@ static long native_hpte_updatepp(unsigned long slot, unsigned long newpp, static long native_hpte_find(unsigned long va, int psize) { - struct hash_pte *hptep; + hpte_t *hptep; unsigned long hash; unsigned long i, j; long slot; @@ -293,7 +294,7 @@ static void native_hpte_updateboltedpp(unsigned long newpp, unsigned long ea, { unsigned long vsid, va; long slot; - struct hash_pte *hptep; + hpte_t *hptep; vsid = get_kernel_vsid(ea); va = (vsid << 28) | (ea & 0x0fffffff); @@ -314,7 +315,7 @@ static void native_hpte_updateboltedpp(unsigned long newpp, unsigned long ea, static void native_hpte_invalidate(unsigned long slot, unsigned long va, int psize, int local) { - struct hash_pte *hptep = htab_address + slot; + hpte_t *hptep = htab_address + slot; unsigned long hpte_v; unsigned long want_v; unsigned long flags; @@ -344,7 +345,7 @@ static void native_hpte_invalidate(unsigned long slot, unsigned long va, #define LP_BITS 8 #define LP_MASK(i) ((0xFF >> (i)) << LP_SHIFT) -static void hpte_decode(struct hash_pte *hpte, unsigned long slot, +static void hpte_decode(hpte_t *hpte, unsigned long slot, int *psize, unsigned long *va) { unsigned long hpte_r = hpte->r; @@ -414,7 +415,7 @@ static void hpte_decode(struct hash_pte *hpte, unsigned long slot, static void native_hpte_clear(void) { unsigned long slot, slots, flags; - struct hash_pte *hptep = htab_address; + hpte_t *hptep = htab_address; unsigned long hpte_v, va; unsigned long pteg_count; int psize; @@ -461,7 +462,7 @@ static void native_hpte_clear(void) static void native_flush_hash_range(unsigned long number, int local) { unsigned long va, hash, index, hidx, shift, slot; - struct hash_pte *hptep; + hpte_t *hptep; unsigned long hpte_v; unsigned long want_v; unsigned long flags; diff --git a/trunk/arch/powerpc/mm/hash_utils_64.c b/trunk/arch/powerpc/mm/hash_utils_64.c index 2ce9491b48d4..4f2f4534a9d8 100644 --- a/trunk/arch/powerpc/mm/hash_utils_64.c +++ b/trunk/arch/powerpc/mm/hash_utils_64.c @@ -87,7 +87,7 @@ extern unsigned long dart_tablebase; static unsigned long _SDR1; struct mmu_psize_def mmu_psize_defs[MMU_PAGE_COUNT]; -struct hash_pte *htab_address; +hpte_t *htab_address; unsigned long htab_size_bytes; unsigned long htab_hash_mask; int mmu_linear_psize = MMU_PAGE_4K; diff --git a/trunk/arch/powerpc/mm/imalloc.c b/trunk/arch/powerpc/mm/imalloc.c new file mode 100644 index 000000000000..c831815c31f0 --- /dev/null +++ b/trunk/arch/powerpc/mm/imalloc.c @@ -0,0 +1,313 @@ +/* + * c 2001 PPC 64 Team, IBM Corp + * + * 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 "mmu_decl.h" + +static DEFINE_MUTEX(imlist_mutex); +struct vm_struct * imlist = NULL; + +static int get_free_im_addr(unsigned long size, unsigned long *im_addr) +{ + unsigned long addr; + struct vm_struct **p, *tmp; + + addr = ioremap_bot; + for (p = &imlist; (tmp = *p) ; p = &tmp->next) { + if (size + addr < (unsigned long) tmp->addr) + break; + if ((unsigned long)tmp->addr >= ioremap_bot) + addr = tmp->size + (unsigned long) tmp->addr; + if (addr >= IMALLOC_END-size) + return 1; + } + *im_addr = addr; + + return 0; +} + +/* Return whether the region described by v_addr and size is a subset + * of the region described by parent + */ +static inline int im_region_is_subset(unsigned long v_addr, unsigned long size, + struct vm_struct *parent) +{ + return (int) (v_addr >= (unsigned long) parent->addr && + v_addr < (unsigned long) parent->addr + parent->size && + size < parent->size); +} + +/* Return whether the region described by v_addr and size is a superset + * of the region described by child + */ +static int im_region_is_superset(unsigned long v_addr, unsigned long size, + struct vm_struct *child) +{ + struct vm_struct parent; + + parent.addr = (void *) v_addr; + parent.size = size; + + return im_region_is_subset((unsigned long) child->addr, child->size, + &parent); +} + +/* Return whether the region described by v_addr and size overlaps + * the region described by vm. Overlapping regions meet the + * following conditions: + * 1) The regions share some part of the address space + * 2) The regions aren't identical + * 3) Neither region is a subset of the other + */ +static int im_region_overlaps(unsigned long v_addr, unsigned long size, + struct vm_struct *vm) +{ + if (im_region_is_superset(v_addr, size, vm)) + return 0; + + return (v_addr + size > (unsigned long) vm->addr + vm->size && + v_addr < (unsigned long) vm->addr + vm->size) || + (v_addr < (unsigned long) vm->addr && + v_addr + size > (unsigned long) vm->addr); +} + +/* Determine imalloc status of region described by v_addr and size. + * Can return one of the following: + * IM_REGION_UNUSED - Entire region is unallocated in imalloc space. + * IM_REGION_SUBSET - Region is a subset of a region that is already + * allocated in imalloc space. + * vm will be assigned to a ptr to the parent region. + * IM_REGION_EXISTS - Exact region already allocated in imalloc space. + * vm will be assigned to a ptr to the existing imlist + * member. + * IM_REGION_OVERLAPS - Region overlaps an allocated region in imalloc space. + * IM_REGION_SUPERSET - Region is a superset of a region that is already + * allocated in imalloc space. + */ +static int im_region_status(unsigned long v_addr, unsigned long size, + struct vm_struct **vm) +{ + struct vm_struct *tmp; + + for (tmp = imlist; tmp; tmp = tmp->next) + if (v_addr < (unsigned long) tmp->addr + tmp->size) + break; + + *vm = NULL; + if (tmp) { + if (im_region_overlaps(v_addr, size, tmp)) + return IM_REGION_OVERLAP; + + *vm = tmp; + if (im_region_is_subset(v_addr, size, tmp)) { + /* Return with tmp pointing to superset */ + return IM_REGION_SUBSET; + } + if (im_region_is_superset(v_addr, size, tmp)) { + /* Return with tmp pointing to first subset */ + return IM_REGION_SUPERSET; + } + else if (v_addr == (unsigned long) tmp->addr && + size == tmp->size) { + /* Return with tmp pointing to exact region */ + return IM_REGION_EXISTS; + } + } + + return IM_REGION_UNUSED; +} + +static struct vm_struct * split_im_region(unsigned long v_addr, + unsigned long size, struct vm_struct *parent) +{ + struct vm_struct *vm1 = NULL; + struct vm_struct *vm2 = NULL; + struct vm_struct *new_vm = NULL; + + vm1 = kmalloc(sizeof(*vm1), GFP_KERNEL); + if (vm1 == NULL) { + printk(KERN_ERR "%s() out of memory\n", __FUNCTION__); + return NULL; + } + + if (v_addr == (unsigned long) parent->addr) { + /* Use existing parent vm_struct to represent child, allocate + * new one for the remainder of parent range + */ + vm1->size = parent->size - size; + vm1->addr = (void *) (v_addr + size); + vm1->next = parent->next; + + parent->size = size; + parent->next = vm1; + new_vm = parent; + } else if (v_addr + size == (unsigned long) parent->addr + + parent->size) { + /* Allocate new vm_struct to represent child, use existing + * parent one for remainder of parent range + */ + vm1->size = size; + vm1->addr = (void *) v_addr; + vm1->next = parent->next; + new_vm = vm1; + + parent->size -= size; + parent->next = vm1; + } else { + /* Allocate two new vm_structs for the new child and + * uppermost remainder, and use existing parent one for the + * lower remainder of parent range + */ + vm2 = kmalloc(sizeof(*vm2), GFP_KERNEL); + if (vm2 == NULL) { + printk(KERN_ERR "%s() out of memory\n", __FUNCTION__); + kfree(vm1); + return NULL; + } + + vm1->size = size; + vm1->addr = (void *) v_addr; + vm1->next = vm2; + new_vm = vm1; + + vm2->size = ((unsigned long) parent->addr + parent->size) - + (v_addr + size); + vm2->addr = (void *) v_addr + size; + vm2->next = parent->next; + + parent->size = v_addr - (unsigned long) parent->addr; + parent->next = vm1; + } + + return new_vm; +} + +static struct vm_struct * __add_new_im_area(unsigned long req_addr, + unsigned long size) +{ + struct vm_struct **p, *tmp, *area; + + for (p = &imlist; (tmp = *p) ; p = &tmp->next) { + if (req_addr + size <= (unsigned long)tmp->addr) + break; + } + + area = kmalloc(sizeof(*area), GFP_KERNEL); + if (!area) + return NULL; + area->flags = 0; + area->addr = (void *)req_addr; + area->size = size; + area->next = *p; + *p = area; + + return area; +} + +static struct vm_struct * __im_get_area(unsigned long req_addr, + unsigned long size, + int criteria) +{ + struct vm_struct *tmp; + int status; + + status = im_region_status(req_addr, size, &tmp); + if ((criteria & status) == 0) { + return NULL; + } + + switch (status) { + case IM_REGION_UNUSED: + tmp = __add_new_im_area(req_addr, size); + break; + case IM_REGION_SUBSET: + tmp = split_im_region(req_addr, size, tmp); + break; + case IM_REGION_EXISTS: + /* Return requested region */ + break; + case IM_REGION_SUPERSET: + /* Return first existing subset of requested region */ + break; + default: + printk(KERN_ERR "%s() unexpected imalloc region status\n", + __FUNCTION__); + tmp = NULL; + } + + return tmp; +} + +struct vm_struct * im_get_free_area(unsigned long size) +{ + struct vm_struct *area; + unsigned long addr; + + mutex_lock(&imlist_mutex); + if (get_free_im_addr(size, &addr)) { + printk(KERN_ERR "%s() cannot obtain addr for size 0x%lx\n", + __FUNCTION__, size); + area = NULL; + goto next_im_done; + } + + area = __im_get_area(addr, size, IM_REGION_UNUSED); + if (area == NULL) { + printk(KERN_ERR + "%s() cannot obtain area for addr 0x%lx size 0x%lx\n", + __FUNCTION__, addr, size); + } +next_im_done: + mutex_unlock(&imlist_mutex); + return area; +} + +struct vm_struct * im_get_area(unsigned long v_addr, unsigned long size, + int criteria) +{ + struct vm_struct *area; + + mutex_lock(&imlist_mutex); + area = __im_get_area(v_addr, size, criteria); + mutex_unlock(&imlist_mutex); + return area; +} + +void im_free(void * addr) +{ + struct vm_struct **p, *tmp; + + if (!addr) + return; + if ((unsigned long) addr & ~PAGE_MASK) { + printk(KERN_ERR "Trying to %s bad address (%p)\n", __FUNCTION__, addr); + return; + } + mutex_lock(&imlist_mutex); + for (p = &imlist ; (tmp = *p) ; p = &tmp->next) { + if (tmp->addr == addr) { + *p = tmp->next; + unmap_vm_area(tmp); + kfree(tmp); + mutex_unlock(&imlist_mutex); + return; + } + } + mutex_unlock(&imlist_mutex); + printk(KERN_ERR "Trying to %s nonexistent area (%p)\n", __FUNCTION__, + addr); +} diff --git a/trunk/arch/powerpc/mm/init_32.c b/trunk/arch/powerpc/mm/init_32.c index e1f5ded851f6..5fce6ccecb8d 100644 --- a/trunk/arch/powerpc/mm/init_32.c +++ b/trunk/arch/powerpc/mm/init_32.c @@ -5,6 +5,7 @@ * Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au) * and Cort Dougan (PReP) (cort@cs.nmt.edu) * Copyright (C) 1996 Paul Mackerras + * Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk). * PPC44x/36-bit changes by Matt Porter (mporter@mvista.com) * * Derived from "arch/i386/mm/init.c" diff --git a/trunk/arch/powerpc/mm/init_64.c b/trunk/arch/powerpc/mm/init_64.c index 1d6edf724c85..7312a265545f 100644 --- a/trunk/arch/powerpc/mm/init_64.c +++ b/trunk/arch/powerpc/mm/init_64.c @@ -5,6 +5,7 @@ * Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au) * and Cort Dougan (PReP) (cort@cs.nmt.edu) * Copyright (C) 1996 Paul Mackerras + * Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk). * * Derived from "arch/i386/mm/init.c" * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds diff --git a/trunk/arch/powerpc/mm/mem.c b/trunk/arch/powerpc/mm/mem.c index f0e7eedb1ba3..0266a94d83b6 100644 --- a/trunk/arch/powerpc/mm/mem.c +++ b/trunk/arch/powerpc/mm/mem.c @@ -5,6 +5,7 @@ * Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au) * and Cort Dougan (PReP) (cort@cs.nmt.edu) * Copyright (C) 1996 Paul Mackerras + * Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk). * PPC44x/36-bit changes by Matt Porter (mporter@mvista.com) * * Derived from "arch/i386/mm/init.c" @@ -128,6 +129,8 @@ int __devinit arch_add_memory(int nid, u64 start, u64 size) zone = pgdata->node_zones; return __add_pages(zone, start_pfn, nr_pages); + + return 0; } /* diff --git a/trunk/arch/powerpc/mm/mmu_context_32.c b/trunk/arch/powerpc/mm/mmu_context_32.c index cc32ba41d900..792086b01000 100644 --- a/trunk/arch/powerpc/mm/mmu_context_32.c +++ b/trunk/arch/powerpc/mm/mmu_context_32.c @@ -11,6 +11,7 @@ * Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au) * and Cort Dougan (PReP) (cort@cs.nmt.edu) * Copyright (C) 1996 Paul Mackerras + * Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk). * * Derived from "arch/i386/mm/init.c" * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds diff --git a/trunk/arch/powerpc/mm/mmu_decl.h b/trunk/arch/powerpc/mm/mmu_decl.h index c94a64fd3c01..2558c34eedaa 100644 --- a/trunk/arch/powerpc/mm/mmu_decl.h +++ b/trunk/arch/powerpc/mm/mmu_decl.h @@ -8,6 +8,7 @@ * Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au) * and Cort Dougan (PReP) (cort@cs.nmt.edu) * Copyright (C) 1996 Paul Mackerras + * Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk). * * Derived from "arch/i386/mm/init.c" * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds @@ -39,8 +40,8 @@ extern int __map_without_bats; extern unsigned long ioremap_base; extern unsigned int rtas_data, rtas_size; -struct hash_pte; -extern struct hash_pte *Hash, *Hash_end; +struct _PTE; +extern struct _PTE *Hash, *Hash_end; extern unsigned long Hash_size, Hash_mask; extern unsigned int num_tlbcam_entries; @@ -89,4 +90,16 @@ static inline void flush_HPTE(unsigned context, unsigned long va, else _tlbie(va); } +#else /* CONFIG_PPC64 */ +/* imalloc region types */ +#define IM_REGION_UNUSED 0x1 +#define IM_REGION_SUBSET 0x2 +#define IM_REGION_EXISTS 0x4 +#define IM_REGION_OVERLAP 0x8 +#define IM_REGION_SUPERSET 0x10 + +extern struct vm_struct * im_get_free_area(unsigned long size); +extern struct vm_struct * im_get_area(unsigned long v_addr, unsigned long size, + int region_type); +extern void im_free(void *addr); #endif diff --git a/trunk/arch/powerpc/mm/pgtable_32.c b/trunk/arch/powerpc/mm/pgtable_32.c index 64488723162a..f6ae1a57d652 100644 --- a/trunk/arch/powerpc/mm/pgtable_32.c +++ b/trunk/arch/powerpc/mm/pgtable_32.c @@ -8,6 +8,7 @@ * Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au) * and Cort Dougan (PReP) (cort@cs.nmt.edu) * Copyright (C) 1996 Paul Mackerras + * Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk). * * Derived from "arch/i386/mm/init.c" * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds @@ -36,6 +37,7 @@ unsigned long ioremap_base; unsigned long ioremap_bot; EXPORT_SYMBOL(ioremap_bot); /* aka VMALLOC_END */ +int io_bat_index; #if defined(CONFIG_6xx) || defined(CONFIG_POWER3) #define HAVE_BATS 1 @@ -298,6 +300,51 @@ void __init mapin_ram(void) } } +/* is x a power of 4? */ +#define is_power_of_4(x) is_power_of_2(x) && (ffs(x) & 1) + +/* + * Set up a mapping for a block of I/O. + * virt, phys, size must all be page-aligned. + * This should only be called before ioremap is called. + */ +void __init io_block_mapping(unsigned long virt, phys_addr_t phys, + unsigned int size, int flags) +{ + int i; + + if (virt > KERNELBASE && virt < ioremap_bot) + ioremap_bot = ioremap_base = virt; + +#ifdef HAVE_BATS + /* + * Use a BAT for this if possible... + */ + if (io_bat_index < 2 && is_power_of_2(size) + && (virt & (size - 1)) == 0 && (phys & (size - 1)) == 0) { + setbat(io_bat_index, virt, phys, size, flags); + ++io_bat_index; + return; + } +#endif /* HAVE_BATS */ + +#ifdef HAVE_TLBCAM + /* + * Use a CAM for this if possible... + */ + if (tlbcam_index < num_tlbcam_entries && is_power_of_4(size) + && (virt & (size - 1)) == 0 && (phys & (size - 1)) == 0) { + settlbcam(tlbcam_index, virt, phys, size, flags, 0); + ++tlbcam_index; + return; + } +#endif /* HAVE_TLBCAM */ + + /* No BATs available, put it in the page tables. */ + for (i = 0; i < size; i += PAGE_SIZE) + map_page(virt + i, phys + i, flags); +} + /* Scan the real Linux page tables and return a PTE pointer for * a virtual address in a context. * Returns true (1) if PTE was found, zero otherwise. The pointer to @@ -332,6 +379,82 @@ get_pteptr(struct mm_struct *mm, unsigned long addr, pte_t **ptep, pmd_t **pmdp) return(retval); } +/* Find physical address for this virtual address. Normally used by + * I/O functions, but anyone can call it. + */ +unsigned long iopa(unsigned long addr) +{ + unsigned long pa; + + /* I don't know why this won't work on PMacs or CHRP. It + * appears there is some bug, or there is some implicit + * mapping done not properly represented by BATs or in page + * tables.......I am actively working on resolving this, but + * can't hold up other stuff. -- Dan + */ + pte_t *pte; + struct mm_struct *mm; + + /* Check the BATs */ + pa = v_mapped_by_bats(addr); + if (pa) + return pa; + + /* Allow mapping of user addresses (within the thread) + * for DMA if necessary. + */ + if (addr < TASK_SIZE) + mm = current->mm; + else + mm = &init_mm; + + pa = 0; + if (get_pteptr(mm, addr, &pte, NULL)) { + pa = (pte_val(*pte) & PAGE_MASK) | (addr & ~PAGE_MASK); + pte_unmap(pte); + } + + return(pa); +} + +/* This is will find the virtual address for a physical one.... + * Swiped from APUS, could be dangerous :-). + * This is only a placeholder until I really find a way to make this + * work. -- Dan + */ +unsigned long +mm_ptov (unsigned long paddr) +{ + unsigned long ret; +#if 0 + if (paddr < 16*1024*1024) + ret = ZTWO_VADDR(paddr); + else { + int i; + + for (i = 0; i < kmap_chunk_count;){ + unsigned long phys = kmap_chunks[i++]; + unsigned long size = kmap_chunks[i++]; + unsigned long virt = kmap_chunks[i++]; + if (paddr >= phys + && paddr < (phys + size)){ + ret = virt + paddr - phys; + goto exit; + } + } + + ret = (unsigned long) __va(paddr); + } +exit: +#ifdef DEBUGPV + printk ("PTOV(%lx)=%lx\n", paddr, ret); +#endif +#else + ret = (unsigned long)paddr + KERNELBASE; +#endif + return ret; +} + #ifdef CONFIG_DEBUG_PAGEALLOC static int __change_page_attr(struct page *page, pgprot_t prot) diff --git a/trunk/arch/powerpc/mm/pgtable_64.c b/trunk/arch/powerpc/mm/pgtable_64.c index 3dfd10db931a..ad6e135bf212 100644 --- a/trunk/arch/powerpc/mm/pgtable_64.c +++ b/trunk/arch/powerpc/mm/pgtable_64.c @@ -7,6 +7,7 @@ * Modifications by Paul Mackerras (PowerMac) (paulus@samba.org) * and Cort Dougan (PReP) (cort@cs.nmt.edu) * Copyright (C) 1996 Paul Mackerras + * Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk). * * Derived from "arch/i386/mm/init.c" * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds @@ -33,27 +34,41 @@ #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 "mmu_decl.h" -unsigned long ioremap_bot = IOREMAP_BASE; +unsigned long ioremap_bot = IMALLOC_BASE; +static unsigned long phbs_io_bot = PHBS_IO_BASE; /* * map_io_page currently only called by __ioremap @@ -87,8 +102,8 @@ static int map_io_page(unsigned long ea, unsigned long pa, int flags) * entry in the hardware page table. * */ - if (htab_bolt_mapping(ea, (unsigned long)ea + PAGE_SIZE, - pa, flags, mmu_io_psize)) { + if (htab_bolt_mapping(ea, ea + PAGE_SIZE, pa, flags, + mmu_io_psize)) { printk(KERN_ERR "Failed to do bolted mapping IO " "memory at %016lx !\n", pa); return -ENOMEM; @@ -98,11 +113,8 @@ static int map_io_page(unsigned long ea, unsigned long pa, int flags) } -/** - * __ioremap_at - Low level function to establish the page tables - * for an IO mapping - */ -void __iomem * __ioremap_at(phys_addr_t pa, void *ea, unsigned long size, +static void __iomem * __ioremap_com(phys_addr_t addr, unsigned long pa, + unsigned long ea, unsigned long size, unsigned long flags) { unsigned long i; @@ -110,35 +122,17 @@ void __iomem * __ioremap_at(phys_addr_t pa, void *ea, unsigned long size, if ((flags & _PAGE_PRESENT) == 0) flags |= pgprot_val(PAGE_KERNEL); - WARN_ON(pa & ~PAGE_MASK); - WARN_ON(((unsigned long)ea) & ~PAGE_MASK); - WARN_ON(size & ~PAGE_MASK); - for (i = 0; i < size; i += PAGE_SIZE) - if (map_io_page((unsigned long)ea+i, pa+i, flags)) + if (map_io_page(ea+i, pa+i, flags)) return NULL; - return (void __iomem *)ea; -} - -/** - * __iounmap_from - Low level function to tear down the page tables - * for an IO mapping. This is used for mappings that - * are manipulated manually, like partial unmapping of - * PCI IOs or ISA space. - */ -void __iounmap_at(void *ea, unsigned long size) -{ - WARN_ON(((unsigned long)ea) & ~PAGE_MASK); - WARN_ON(size & ~PAGE_MASK); - - unmap_kernel_range((unsigned long)ea, size); + return (void __iomem *) (ea + (addr & ~PAGE_MASK)); } void __iomem * __ioremap(phys_addr_t addr, unsigned long size, unsigned long flags) { - phys_addr_t paligned; + unsigned long pa, ea; void __iomem *ret; /* @@ -150,30 +144,27 @@ void __iomem * __ioremap(phys_addr_t addr, unsigned long size, * IMALLOC_END * */ - paligned = addr & PAGE_MASK; - size = PAGE_ALIGN(addr + size) - paligned; + pa = addr & PAGE_MASK; + size = PAGE_ALIGN(addr + size) - pa; - if ((size == 0) || (paligned == 0)) + if ((size == 0) || (pa == 0)) return NULL; if (mem_init_done) { struct vm_struct *area; - - area = __get_vm_area(size, VM_IOREMAP, - ioremap_bot, IOREMAP_END); + area = im_get_free_area(size); if (area == NULL) return NULL; - ret = __ioremap_at(paligned, area->addr, size, flags); + ea = (unsigned long)(area->addr); + ret = __ioremap_com(addr, pa, ea, size, flags); if (!ret) - vunmap(area->addr); + im_free(area->addr); } else { - ret = __ioremap_at(paligned, (void *)ioremap_bot, size, flags); + ea = ioremap_bot; + ret = __ioremap_com(addr, pa, ea, size, flags); if (ret) ioremap_bot += size; } - - if (ret) - ret += addr & ~PAGE_MASK; return ret; } @@ -196,9 +187,62 @@ void __iomem * ioremap_flags(phys_addr_t addr, unsigned long size, } +#define IS_PAGE_ALIGNED(_val) ((_val) == ((_val) & PAGE_MASK)) + +int __ioremap_explicit(phys_addr_t pa, unsigned long ea, + unsigned long size, unsigned long flags) +{ + struct vm_struct *area; + void __iomem *ret; + + /* For now, require page-aligned values for pa, ea, and size */ + if (!IS_PAGE_ALIGNED(pa) || !IS_PAGE_ALIGNED(ea) || + !IS_PAGE_ALIGNED(size)) { + printk(KERN_ERR "unaligned value in %s\n", __FUNCTION__); + return 1; + } + + if (!mem_init_done) { + /* Two things to consider in this case: + * 1) No records will be kept (imalloc, etc) that the region + * has been remapped + * 2) It won't be easy to iounmap() the region later (because + * of 1) + */ + ; + } else { + area = im_get_area(ea, size, + IM_REGION_UNUSED|IM_REGION_SUBSET|IM_REGION_EXISTS); + if (area == NULL) { + /* Expected when PHB-dlpar is in play */ + return 1; + } + if (ea != (unsigned long) area->addr) { + printk(KERN_ERR "unexpected addr return from " + "im_get_area\n"); + return 1; + } + } + + ret = __ioremap_com(pa, pa, ea, size, flags); + if (ret == NULL) { + printk(KERN_ERR "ioremap_explicit() allocation failure !\n"); + return 1; + } + if (ret != (void *) ea) { + printk(KERN_ERR "__ioremap_com() returned unexpected addr\n"); + return 1; + } + + return 0; +} + /* * Unmap an IO region and remove it from imalloc'd list. * Access to IO memory should be serialized by driver. + * This code is modeled after vmalloc code - unmap_vm_area() + * + * XXX what about calls before mem_init_done (ie python_countermeasures()) */ void __iounmap(volatile void __iomem *token) { @@ -207,14 +251,9 @@ void __iounmap(volatile void __iomem *token) if (!mem_init_done) return; - addr = (void *) ((unsigned long __force) - PCI_FIX_ADDR(token) & PAGE_MASK); - if ((unsigned long)addr < ioremap_bot) { - printk(KERN_WARNING "Attempt to iounmap early bolted mapping" - " at 0x%p\n", addr); - return; - } - vunmap(addr); + addr = (void *) ((unsigned long __force) token & PAGE_MASK); + + im_free(addr); } void iounmap(volatile void __iomem *token) @@ -225,8 +264,77 @@ void iounmap(volatile void __iomem *token) __iounmap(token); } +static int iounmap_subset_regions(unsigned long addr, unsigned long size) +{ + struct vm_struct *area; + + /* Check whether subsets of this region exist */ + area = im_get_area(addr, size, IM_REGION_SUPERSET); + if (area == NULL) + return 1; + + while (area) { + iounmap((void __iomem *) area->addr); + area = im_get_area(addr, size, + IM_REGION_SUPERSET); + } + + return 0; +} + +int __iounmap_explicit(volatile void __iomem *start, unsigned long size) +{ + struct vm_struct *area; + unsigned long addr; + int rc; + + addr = (unsigned long __force) start & PAGE_MASK; + + /* Verify that the region either exists or is a subset of an existing + * region. In the latter case, split the parent region to create + * the exact region + */ + area = im_get_area(addr, size, + IM_REGION_EXISTS | IM_REGION_SUBSET); + if (area == NULL) { + /* Determine whether subset regions exist. If so, unmap */ + rc = iounmap_subset_regions(addr, size); + if (rc) { + printk(KERN_ERR + "%s() cannot unmap nonexistent range 0x%lx\n", + __FUNCTION__, addr); + return 1; + } + } else { + iounmap((void __iomem *) area->addr); + } + /* + * FIXME! This can't be right: + iounmap(area->addr); + * Maybe it should be "iounmap(area);" + */ + return 0; +} + EXPORT_SYMBOL(ioremap); EXPORT_SYMBOL(ioremap_flags); EXPORT_SYMBOL(__ioremap); EXPORT_SYMBOL(iounmap); EXPORT_SYMBOL(__iounmap); + +static DEFINE_SPINLOCK(phb_io_lock); + +void __iomem * reserve_phb_iospace(unsigned long size) +{ + void __iomem *virt_addr; + + if (phbs_io_bot >= IMALLOC_BASE) + panic("reserve_phb_iospace(): phb io space overflow\n"); + + spin_lock(&phb_io_lock); + virt_addr = (void __iomem *) phbs_io_bot; + phbs_io_bot += size; + spin_unlock(&phb_io_lock); + + return virt_addr; +} diff --git a/trunk/arch/powerpc/mm/ppc_mmu_32.c b/trunk/arch/powerpc/mm/ppc_mmu_32.c index 5c45d474cfcc..ec1421a20aaa 100644 --- a/trunk/arch/powerpc/mm/ppc_mmu_32.c +++ b/trunk/arch/powerpc/mm/ppc_mmu_32.c @@ -11,6 +11,7 @@ * Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au) * and Cort Dougan (PReP) (cort@cs.nmt.edu) * Copyright (C) 1996 Paul Mackerras + * Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk). * * Derived from "arch/i386/mm/init.c" * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds @@ -34,12 +35,12 @@ #include "mmu_decl.h" -struct hash_pte *Hash, *Hash_end; +PTE *Hash, *Hash_end; unsigned long Hash_size, Hash_mask; unsigned long _SDR1; union ubat { /* BAT register values to be loaded */ - struct ppc_bat bat; + BAT bat; u32 word[2]; } BATS[8][2]; /* 8 pairs of IBAT, DBAT */ @@ -244,7 +245,7 @@ void __init MMU_init_hw(void) cacheable_memzero(Hash, Hash_size); _SDR1 = __pa(Hash) | SDR1_LOW_BITS; - Hash_end = (struct hash_pte *) ((unsigned long)Hash + Hash_size); + Hash_end = (PTE *) ((unsigned long)Hash + Hash_size); printk("Total memory = %ldMB; using %ldkB for hash table (at %p)\n", total_memory >> 20, Hash_size >> 10, Hash); diff --git a/trunk/arch/powerpc/mm/stab.c b/trunk/arch/powerpc/mm/stab.c index 28492bbdee8e..132c6bc66ce1 100644 --- a/trunk/arch/powerpc/mm/stab.c +++ b/trunk/arch/powerpc/mm/stab.c @@ -55,7 +55,7 @@ static int make_ste(unsigned long stab, unsigned long esid, unsigned long vsid) for (entry = 0; entry < 8; entry++, ste++) { if (!(ste->esid_data & STE_ESID_V)) { ste->vsid_data = vsid_data; - eieio(); + asm volatile("eieio":::"memory"); ste->esid_data = esid_data; return (global_entry | entry); } @@ -101,7 +101,7 @@ static int make_ste(unsigned long stab, unsigned long esid, unsigned long vsid) asm volatile("sync" : : : "memory"); /* Order update */ castout_ste->vsid_data = vsid_data; - eieio(); /* Order update */ + asm volatile("eieio" : : : "memory"); /* Order update */ castout_ste->esid_data = esid_data; asm volatile("slbie %0" : : "r" (old_esid << SID_SHIFT)); diff --git a/trunk/arch/powerpc/mm/tlb_32.c b/trunk/arch/powerpc/mm/tlb_32.c index 06c7e77e097a..6a69417cbc0e 100644 --- a/trunk/arch/powerpc/mm/tlb_32.c +++ b/trunk/arch/powerpc/mm/tlb_32.c @@ -11,6 +11,7 @@ * Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au) * and Cort Dougan (PReP) (cort@cs.nmt.edu) * Copyright (C) 1996 Paul Mackerras + * Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk). * * Derived from "arch/i386/mm/init.c" * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds diff --git a/trunk/arch/powerpc/mm/tlb_64.c b/trunk/arch/powerpc/mm/tlb_64.c index cbd34fc813ee..2bfc4d7e1aa2 100644 --- a/trunk/arch/powerpc/mm/tlb_64.c +++ b/trunk/arch/powerpc/mm/tlb_64.c @@ -8,6 +8,7 @@ * Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au) * and Cort Dougan (PReP) (cort@cs.nmt.edu) * Copyright (C) 1996 Paul Mackerras + * Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk). * * Derived from "arch/i386/mm/init.c" * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds @@ -238,59 +239,3 @@ void pte_free_finish(void) pte_free_submit(*batchp); *batchp = NULL; } - -/** - * __flush_hash_table_range - Flush all HPTEs for a given address range - * from the hash table (and the TLB). But keeps - * the linux PTEs intact. - * - * @mm : mm_struct of the target address space (generally init_mm) - * @start : starting address - * @end : ending address (not included in the flush) - * - * This function is mostly to be used by some IO hotplug code in order - * to remove all hash entries from a given address range used to map IO - * space on a removed PCI-PCI bidge without tearing down the full mapping - * since 64K pages may overlap with other bridges when using 64K pages - * with 4K HW pages on IO space. - * - * Because of that usage pattern, it's only available with CONFIG_HOTPLUG - * and is implemented for small size rather than speed. - */ -#ifdef CONFIG_HOTPLUG - -void __flush_hash_table_range(struct mm_struct *mm, unsigned long start, - unsigned long end) -{ - unsigned long flags; - - start = _ALIGN_DOWN(start, PAGE_SIZE); - end = _ALIGN_UP(end, PAGE_SIZE); - - BUG_ON(!mm->pgd); - - /* Note: Normally, we should only ever use a batch within a - * PTE locked section. This violates the rule, but will work - * since we don't actually modify the PTEs, we just flush the - * hash while leaving the PTEs intact (including their reference - * to being hashed). This is not the most performance oriented - * way to do things but is fine for our needs here. - */ - local_irq_save(flags); - arch_enter_lazy_mmu_mode(); - for (; start < end; start += PAGE_SIZE) { - pte_t *ptep = find_linux_pte(mm->pgd, start); - unsigned long pte; - - if (ptep == NULL) - continue; - pte = pte_val(*ptep); - if (!(pte & _PAGE_HASHPTE)) - continue; - hpte_need_flush(mm, start, ptep, pte, 0); - } - arch_leave_lazy_mmu_mode(); - local_irq_restore(flags); -} - -#endif /* CONFIG_HOTPLUG */ diff --git a/trunk/arch/powerpc/oprofile/op_model_power4.c b/trunk/arch/powerpc/oprofile/op_model_power4.c index a7c206b665af..fe597a154d4f 100644 --- a/trunk/arch/powerpc/oprofile/op_model_power4.c +++ b/trunk/arch/powerpc/oprofile/op_model_power4.c @@ -1,7 +1,5 @@ /* * Copyright (C) 2004 Anton Blanchard , IBM - * Added mmcra[slot] support: - * Copyright (C) 2006-2007 Will Schmidt , IBM * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -183,17 +181,11 @@ static void __attribute_used__ kernel_unknown_bucket(void) * On GQ and newer the MMCRA stores the HV and PR bits at the time * the SIAR was sampled. We use that to work out if the SIAR was sampled in * the hypervisor, our exception vectors or RTAS. - * If the MMCRA_SAMPLE_ENABLE bit is set, we can use the MMCRA[slot] bits - * to more accurately identify the address of the sampled instruction. The - * mmcra[slot] bits represent the slot number of a sampled instruction - * within an instruction group. The slot will contain a value between 1 - * and 5 if MMCRA_SAMPLE_ENABLE is set, otherwise 0. */ static unsigned long get_pc(struct pt_regs *regs) { unsigned long pc = mfspr(SPRN_SIAR); unsigned long mmcra; - unsigned long slot; /* Cant do much about it */ if (!cur_cpu_spec->oprofile_mmcra_sihv) @@ -201,12 +193,6 @@ static unsigned long get_pc(struct pt_regs *regs) mmcra = mfspr(SPRN_MMCRA); - if (mmcra & MMCRA_SAMPLE_ENABLE) { - slot = ((mmcra & MMCRA_SLOT) >> MMCRA_SLOT_SHIFT); - if (slot > 1) - pc += 4 * (slot - 1); - } - /* Were we in the hypervisor? */ if (firmware_has_feature(FW_FEATURE_LPAR) && (mmcra & cur_cpu_spec->oprofile_mmcra_sihv)) diff --git a/trunk/arch/powerpc/platforms/52xx/efika.c b/trunk/arch/powerpc/platforms/52xx/efika.c index 4be6e7a17b66..f591a9fc19b9 100644 --- a/trunk/arch/powerpc/platforms/52xx/efika.c +++ b/trunk/arch/powerpc/platforms/52xx/efika.c @@ -54,7 +54,7 @@ static int rtas_read_config(struct pci_bus *bus, unsigned int devfn, int offset, struct pci_controller *hose = bus->sysdata; unsigned long addr = (offset & 0xff) | ((devfn & 0xff) << 8) | (((bus->number - hose->first_busno) & 0xff) << 16) - | (hose->global_number << 24); + | (hose->index << 24); int ret = -1; int rval; @@ -69,7 +69,7 @@ static int rtas_write_config(struct pci_bus *bus, unsigned int devfn, struct pci_controller *hose = bus->sysdata; unsigned long addr = (offset & 0xff) | ((devfn & 0xff) << 8) | (((bus->number - hose->first_busno) & 0xff) << 16) - | (hose->global_number << 24); + | (hose->index << 24); int rval; rval = rtas_call(rtas_token("write-pci-config"), 3, 1, NULL, @@ -83,7 +83,7 @@ static struct pci_ops rtas_pci_ops = { }; -static void __init efika_pcisetup(void) +void __init efika_pcisetup(void) { const int *bus_range; int len; @@ -128,7 +128,7 @@ static void __init efika_pcisetup(void) printk(" controlled by %s\n", pcictrl->full_name); printk("\n"); - hose = pcibios_alloc_controller(of_node_get(pcictrl)); + hose = pcibios_alloc_controller(); if (!hose) { printk(KERN_WARNING EFIKA_PLATFORM_NAME ": Can't allocate PCI controller structure for %s\n", @@ -136,6 +136,7 @@ static void __init efika_pcisetup(void) return; } + hose->arch_data = of_node_get(pcictrl); hose->first_busno = bus_range[0]; hose->last_busno = bus_range[1]; hose->ops = &rtas_pci_ops; @@ -144,7 +145,7 @@ static void __init efika_pcisetup(void) } #else -static void __init efika_pcisetup(void) +void __init efika_pcisetup(void) {} #endif @@ -251,8 +252,6 @@ define_machine(efika) .progress = rtas_progress, .get_boot_time = rtas_get_boot_time, .calibrate_decr = generic_calibrate_decr, -#ifdef CONFIG_PCI .phys_mem_access_prot = pci_phys_mem_access_prot, -#endif }; diff --git a/trunk/arch/powerpc/platforms/52xx/lite5200.c b/trunk/arch/powerpc/platforms/52xx/lite5200.c index 5c46e898fd45..1cfc00dfb99a 100644 --- a/trunk/arch/powerpc/platforms/52xx/lite5200.c +++ b/trunk/arch/powerpc/platforms/52xx/lite5200.c @@ -156,7 +156,7 @@ static void __init lite5200_setup_arch(void) } -static void lite5200_show_cpuinfo(struct seq_file *m) +void lite5200_show_cpuinfo(struct seq_file *m) { struct device_node* np = of_find_all_nodes(NULL); const char *model = NULL; diff --git a/trunk/arch/powerpc/platforms/52xx/mpc52xx_pci.c b/trunk/arch/powerpc/platforms/52xx/mpc52xx_pci.c index 4c6c82a684b1..34d34a26d305 100644 --- a/trunk/arch/powerpc/platforms/52xx/mpc52xx_pci.c +++ b/trunk/arch/powerpc/platforms/52xx/mpc52xx_pci.c @@ -112,18 +112,18 @@ mpc52xx_pci_read_config(struct pci_bus *bus, unsigned int devfn, u32 value; if (ppc_md.pci_exclude_device) - if (ppc_md.pci_exclude_device(hose, bus->number, devfn)) + if (ppc_md.pci_exclude_device(bus->number, devfn)) return PCIBIOS_DEVICE_NOT_FOUND; out_be32(hose->cfg_addr, (1 << 31) | - (bus->number << 16) | + ((bus->number - hose->bus_offset) << 16) | (devfn << 8) | (offset & 0xfc)); mb(); #if defined(CONFIG_PPC_MPC5200_BUGFIX) - if (bus->number) { + if (bus->number != hose->bus_offset) { /* workaround for the bug 435 of the MPC5200 (L25R); * Don't do 32 bits config access during type-1 cycles */ switch (len) { @@ -169,18 +169,18 @@ mpc52xx_pci_write_config(struct pci_bus *bus, unsigned int devfn, u32 value, mask; if (ppc_md.pci_exclude_device) - if (ppc_md.pci_exclude_device(hose, bus->number, devfn)) + if (ppc_md.pci_exclude_device(bus->number, devfn)) return PCIBIOS_DEVICE_NOT_FOUND; out_be32(hose->cfg_addr, (1 << 31) | - (bus->number << 16) | + ((bus->number - hose->bus_offset) << 16) | (devfn << 8) | (offset & 0xfc)); mb(); #if defined(CONFIG_PPC_MPC5200_BUGFIX) - if (bus->number) { + if (bus->number != hose->bus_offset) { /* workaround for the bug 435 of the MPC5200 (L25R); * Don't do 32 bits config access during type-1 cycles */ switch (len) { @@ -385,13 +385,17 @@ mpc52xx_add_bridge(struct device_node *node) * tree are needed to configure the 52xx PCI controller. Rather * than parse the tree here, let pci_process_bridge_OF_ranges() * do it for us and extract the values after the fact */ - hose = pcibios_alloc_controller(node); + hose = pcibios_alloc_controller(); if (!hose) return -ENOMEM; + hose->arch_data = node; + hose->set_cfg_type = 1; + hose->first_busno = bus_range ? bus_range[0] : 0; hose->last_busno = bus_range ? bus_range[1] : 0xff; + hose->bus_offset = 0; hose->ops = &mpc52xx_pci_ops; pci_regs = ioremap(rsrc.start, rsrc.end - rsrc.start + 1); diff --git a/trunk/arch/powerpc/platforms/52xx/mpc52xx_pm.c b/trunk/arch/powerpc/platforms/52xx/mpc52xx_pm.c index ee2e7639c63e..fd40044d16cd 100644 --- a/trunk/arch/powerpc/platforms/52xx/mpc52xx_pm.c +++ b/trunk/arch/powerpc/platforms/52xx/mpc52xx_pm.c @@ -9,8 +9,8 @@ /* these are defined in mpc52xx_sleep.S, and only used here */ -extern void mpc52xx_deep_sleep(void __iomem *sram, void __iomem *sdram_regs, - struct mpc52xx_cdm __iomem *, struct mpc52xx_intr __iomem*); +extern void mpc52xx_deep_sleep(void *sram, void *sdram_regs, + struct mpc52xx_cdm *, struct mpc52xx_intr *); extern void mpc52xx_ds_sram(void); extern const long mpc52xx_ds_sram_size; extern void mpc52xx_ds_cached(void); @@ -21,7 +21,7 @@ static void __iomem *sdram; static struct mpc52xx_cdm __iomem *cdm; static struct mpc52xx_intr __iomem *intr; static struct mpc52xx_gpio_wkup __iomem *gpiow; -static void __iomem *sram; +static void *sram; static int sram_size; struct mpc52xx_suspend mpc52xx_suspend; @@ -100,7 +100,7 @@ int mpc52xx_pm_enter(suspend_state_t state) u32 clk_enables; u32 msr, hid0; u32 intr_main_mask; - void __iomem * irq_0x500 = (void __iomem *)CONFIG_KERNEL_START + 0x500; + void __iomem * irq_0x500 = (void *)CONFIG_KERNEL_START + 0x500; unsigned long irq_0x500_stop = (unsigned long)irq_0x500 + mpc52xx_ds_cached_size; char saved_0x500[mpc52xx_ds_cached_size]; diff --git a/trunk/arch/powerpc/platforms/82xx/Kconfig b/trunk/arch/powerpc/platforms/82xx/Kconfig index 89fde43895c5..de7fce9cb6eb 100644 --- a/trunk/arch/powerpc/platforms/82xx/Kconfig +++ b/trunk/arch/powerpc/platforms/82xx/Kconfig @@ -1,5 +1,5 @@ choice - prompt "82xx Board Type" + prompt "Machine Type" depends on PPC_82xx default MPC82xx_ADS diff --git a/trunk/arch/powerpc/platforms/82xx/mpc82xx_ads.c b/trunk/arch/powerpc/platforms/82xx/mpc82xx_ads.c index da20832b27f1..47cb09f08052 100644 --- a/trunk/arch/powerpc/platforms/82xx/mpc82xx_ads.c +++ b/trunk/arch/powerpc/platforms/82xx/mpc82xx_ads.c @@ -49,7 +49,7 @@ #include #include -#include +#include <../sysdev/cpm2_pic.h> #include "pq2ads.h" @@ -507,8 +507,7 @@ void m82xx_pci_init_irq(void) return; } -static int m82xx_pci_exclude_device(struct pci_controller *hose, - u_char bus, u_char devfn) +static int m82xx_pci_exclude_device(u_char bus, u_char devfn) { if (bus == 0 && PCI_SLOT(devfn) == 0) return PCIBIOS_DEVICE_NOT_FOUND; @@ -516,7 +515,7 @@ static int m82xx_pci_exclude_device(struct pci_controller *hose, return PCIBIOS_SUCCESSFUL; } -static void __init mpc82xx_add_bridge(struct device_node *np) +void __init add_bridge(struct device_node *np) { int len; struct pci_controller *hose; @@ -543,13 +542,19 @@ static void __init mpc82xx_add_bridge(struct device_node *np) pci_assign_all_buses = 1; - hose = pcibios_alloc_controller(np); + hose = pcibios_alloc_controller(); if (!hose) return; + hose->arch_data = np; + hose->set_cfg_type = 1; + hose->first_busno = bus_range ? bus_range[0] : 0; hose->last_busno = bus_range ? bus_range[1] : 0xff; + hose->bus_offset = 0; + + hose->set_cfg_type = 1; setup_indirect_pci(hose, r.start + offsetof(pci_cpm2_t, pci_cfg_addr), @@ -579,7 +584,7 @@ static void __init mpc82xx_ads_setup_arch(void) #ifdef CONFIG_PCI ppc_md.pci_exclude_device = m82xx_pci_exclude_device; for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;) - mpc82xx_add_bridge(np); + add_bridge(np); of_node_put(np); #endif diff --git a/trunk/arch/powerpc/platforms/83xx/Kconfig b/trunk/arch/powerpc/platforms/83xx/Kconfig index ec305f18abd8..19cafdf6df93 100644 --- a/trunk/arch/powerpc/platforms/83xx/Kconfig +++ b/trunk/arch/powerpc/platforms/83xx/Kconfig @@ -1,5 +1,5 @@ choice - prompt "83xx Board Type" + prompt "Machine Type" depends on PPC_83xx default MPC834x_MDS diff --git a/trunk/arch/powerpc/platforms/83xx/Makefile b/trunk/arch/powerpc/platforms/83xx/Makefile index 5a98f885779f..31a91b53f528 100644 --- a/trunk/arch/powerpc/platforms/83xx/Makefile +++ b/trunk/arch/powerpc/platforms/83xx/Makefile @@ -1,7 +1,7 @@ # # Makefile for the PowerPC 83xx linux kernel. # -obj-y := misc.o usb.o +obj-y := misc.o obj-$(CONFIG_PCI) += pci.o obj-$(CONFIG_MPC8313_RDB) += mpc8313_rdb.o obj-$(CONFIG_MPC832x_RDB) += mpc832x_rdb.o diff --git a/trunk/arch/powerpc/platforms/83xx/mpc8313_rdb.c b/trunk/arch/powerpc/platforms/83xx/mpc8313_rdb.c index 3edfe170a03b..96970ac887ee 100644 --- a/trunk/arch/powerpc/platforms/83xx/mpc8313_rdb.c +++ b/trunk/arch/powerpc/platforms/83xx/mpc8313_rdb.c @@ -28,6 +28,11 @@ #define DBG(fmt...) #endif +#ifndef CONFIG_PCI +unsigned long isa_io_base = 0; +unsigned long isa_mem_base = 0; +#endif + /* ************************************************************************ * * Setup the architecture @@ -44,11 +49,10 @@ static void __init mpc8313_rdb_setup_arch(void) #ifdef CONFIG_PCI for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;) - mpc83xx_add_bridge(np); + add_bridge(np); ppc_md.pci_exclude_device = mpc83xx_exclude_device; #endif - mpc831x_usb_cfg(); } void __init mpc8313_rdb_init_IRQ(void) diff --git a/trunk/arch/powerpc/platforms/83xx/mpc832x_mds.c b/trunk/arch/powerpc/platforms/83xx/mpc832x_mds.c index b39cb52c6fb9..94843ed52a93 100644 --- a/trunk/arch/powerpc/platforms/83xx/mpc832x_mds.c +++ b/trunk/arch/powerpc/platforms/83xx/mpc832x_mds.c @@ -49,6 +49,11 @@ #define DBG(fmt...) #endif +#ifndef CONFIG_PCI +unsigned long isa_io_base = 0; +unsigned long isa_mem_base = 0; +#endif + static u8 *bcsr_regs = NULL; /* ************************************************************************ @@ -75,7 +80,7 @@ static void __init mpc832x_sys_setup_arch(void) #ifdef CONFIG_PCI for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;) - mpc83xx_add_bridge(np); + add_bridge(np); ppc_md.pci_exclude_device = mpc83xx_exclude_device; #endif diff --git a/trunk/arch/powerpc/platforms/83xx/mpc832x_rdb.c b/trunk/arch/powerpc/platforms/83xx/mpc832x_rdb.c index b2b28a44738c..3db68b73fc32 100644 --- a/trunk/arch/powerpc/platforms/83xx/mpc832x_rdb.c +++ b/trunk/arch/powerpc/platforms/83xx/mpc832x_rdb.c @@ -32,6 +32,11 @@ #define DBG(fmt...) #endif +#ifndef CONFIG_PCI +unsigned long isa_io_base = 0; +unsigned long isa_mem_base = 0; +#endif + /* ************************************************************************ * * Setup the architecture @@ -48,7 +53,7 @@ static void __init mpc832x_rdb_setup_arch(void) #ifdef CONFIG_PCI for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;) - mpc83xx_add_bridge(np); + add_bridge(np); ppc_md.pci_exclude_device = mpc83xx_exclude_device; #endif diff --git a/trunk/arch/powerpc/platforms/83xx/mpc834x_itx.c b/trunk/arch/powerpc/platforms/83xx/mpc834x_itx.c index 47ba5446f63c..40a01947d684 100644 --- a/trunk/arch/powerpc/platforms/83xx/mpc834x_itx.c +++ b/trunk/arch/powerpc/platforms/83xx/mpc834x_itx.c @@ -38,6 +38,11 @@ #include "mpc83xx.h" +#ifndef CONFIG_PCI +unsigned long isa_io_base = 0; +unsigned long isa_mem_base = 0; +#endif + /* ************************************************************************ * * Setup the architecture @@ -54,12 +59,10 @@ static void __init mpc834x_itx_setup_arch(void) #ifdef CONFIG_PCI for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;) - mpc83xx_add_bridge(np); + add_bridge(np); ppc_md.pci_exclude_device = mpc83xx_exclude_device; #endif - - mpc834x_usb_cfg(); } static void __init mpc834x_itx_init_IRQ(void) diff --git a/trunk/arch/powerpc/platforms/83xx/mpc834x_mds.c b/trunk/arch/powerpc/platforms/83xx/mpc834x_mds.c index 4c9ff9cadfe4..10394b2d7e7a 100644 --- a/trunk/arch/powerpc/platforms/83xx/mpc834x_mds.c +++ b/trunk/arch/powerpc/platforms/83xx/mpc834x_mds.c @@ -38,17 +38,61 @@ #include "mpc83xx.h" +#ifndef CONFIG_PCI +unsigned long isa_io_base = 0; +unsigned long isa_mem_base = 0; +#endif + #define BCSR5_INT_USB 0x02 -static int mpc834xemds_usb_cfg(void) +/* Note: This is only for PB, not for PB+PIB + * On PB only port0 is connected using ULPI */ +static int mpc834x_usb_cfg(void) { - struct device_node *np; + unsigned long sccr, sicrl; + void __iomem *immap; void __iomem *bcsr_regs = NULL; u8 bcsr5; + struct device_node *np = NULL; + int port0_is_dr = 0; + + if ((np = of_find_compatible_node(NULL, "usb", "fsl-usb2-dr")) != NULL) + port0_is_dr = 1; + if ((np = of_find_compatible_node(NULL, "usb", "fsl-usb2-mph")) != NULL){ + if (port0_is_dr) { + printk(KERN_WARNING + "There is only one USB port on PB board! \n"); + return -1; + } else if (!port0_is_dr) + /* No usb port enabled */ + return -1; + } + + immap = ioremap(get_immrbase(), 0x1000); + if (!immap) + return -1; + + /* Configure clock */ + sccr = in_be32(immap + MPC83XX_SCCR_OFFS); + if (port0_is_dr) + sccr |= MPC83XX_SCCR_USB_DRCM_11; /* 1:3 */ + else + sccr |= MPC83XX_SCCR_USB_MPHCM_11; /* 1:3 */ + out_be32(immap + MPC83XX_SCCR_OFFS, sccr); + + /* Configure Pin */ + sicrl = in_be32(immap + MPC83XX_SICRL_OFFS); + /* set port0 only */ + if (port0_is_dr) + sicrl |= MPC83XX_SICRL_USB0; + else + sicrl &= ~(MPC83XX_SICRL_USB0); + out_be32(immap + MPC83XX_SICRL_OFFS, sicrl); + + iounmap(immap); - mpc834x_usb_cfg(); /* Map BCSR area */ np = of_find_node_by_name(NULL, "bcsr"); - if (np) { + if (np != 0) { struct resource res; of_address_to_resource(np, 0, &res); @@ -85,12 +129,12 @@ static void __init mpc834x_mds_setup_arch(void) #ifdef CONFIG_PCI for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;) - mpc83xx_add_bridge(np); + add_bridge(np); ppc_md.pci_exclude_device = mpc83xx_exclude_device; #endif - mpc834xemds_usb_cfg(); + mpc834x_usb_cfg(); } static void __init mpc834x_mds_init_IRQ(void) diff --git a/trunk/arch/powerpc/platforms/83xx/mpc836x_mds.c b/trunk/arch/powerpc/platforms/83xx/mpc836x_mds.c index 0e615fd65c1f..bceeff8bbfd2 100644 --- a/trunk/arch/powerpc/platforms/83xx/mpc836x_mds.c +++ b/trunk/arch/powerpc/platforms/83xx/mpc836x_mds.c @@ -55,6 +55,11 @@ #define DBG(fmt...) #endif +#ifndef CONFIG_PCI +unsigned long isa_io_base = 0; +unsigned long isa_mem_base = 0; +#endif + static u8 *bcsr_regs = NULL; /* ************************************************************************ @@ -81,7 +86,7 @@ static void __init mpc836x_mds_setup_arch(void) #ifdef CONFIG_PCI for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;) - mpc83xx_add_bridge(np); + add_bridge(np); ppc_md.pci_exclude_device = mpc83xx_exclude_device; #endif diff --git a/trunk/arch/powerpc/platforms/83xx/mpc83xx.h b/trunk/arch/powerpc/platforms/83xx/mpc83xx.h index 589ee55730f3..9cd03b59c8f4 100644 --- a/trunk/arch/powerpc/platforms/83xx/mpc83xx.h +++ b/trunk/arch/powerpc/platforms/83xx/mpc83xx.h @@ -3,11 +3,9 @@ #include #include -#include /* System Clock Control Register */ #define MPC83XX_SCCR_OFFS 0xA08 -#define MPC83XX_SCCR_USB_MASK 0x00f00000 #define MPC83XX_SCCR_USB_MPHCM_11 0x00c00000 #define MPC83XX_SCCR_USB_MPHCM_01 0x00400000 #define MPC83XX_SCCR_USB_MPHCM_10 0x00800000 @@ -17,43 +15,21 @@ /* system i/o configuration register low */ #define MPC83XX_SICRL_OFFS 0x114 -#define MPC834X_SICRL_USB_MASK 0x60000000 -#define MPC834X_SICRL_USB0 0x40000000 -#define MPC834X_SICRL_USB1 0x20000000 -#define MPC831X_SICRL_USB_MASK 0x00000c00 -#define MPC831X_SICRL_USB_ULPI 0x00000800 +#define MPC83XX_SICRL_USB0 0x40000000 +#define MPC83XX_SICRL_USB1 0x20000000 /* system i/o configuration register high */ #define MPC83XX_SICRH_OFFS 0x118 -#define MPC834X_SICRH_USB_UTMI 0x00020000 -#define MPC831X_SICRH_USB_MASK 0x000000e0 -#define MPC831X_SICRH_USB_ULPI 0x000000a0 - -/* USB Control Register */ -#define FSL_USB2_CONTROL_OFFS 0x500 -#define CONTROL_UTMI_PHY_EN 0x00000200 -#define CONTROL_REFSEL_48MHZ 0x00000080 -#define CONTROL_PHY_CLK_SEL_ULPI 0x00000400 -#define CONTROL_OTG_PORT 0x00000020 - -/* USB PORTSC Registers */ -#define FSL_USB2_PORTSC1_OFFS 0x184 -#define FSL_USB2_PORTSC2_OFFS 0x188 -#define PORTSCX_PTW_16BIT 0x10000000 -#define PORTSCX_PTS_UTMI 0x00000000 -#define PORTSCX_PTS_ULPI 0x80000000 +#define MPC83XX_SICRH_USB_UTMI 0x00020000 /* * Declaration for the various functions exported by the * mpc83xx_* files. Mostly for use by mpc83xx_setup */ -extern int mpc83xx_add_bridge(struct device_node *dev); -extern int mpc83xx_exclude_device(struct pci_controller *hose, - u_char bus, u_char devfn); +extern int add_bridge(struct device_node *dev); +extern int mpc83xx_exclude_device(u_char bus, u_char devfn); extern void mpc83xx_restart(char *cmd); extern long mpc83xx_time_init(void); -extern int mpc834x_usb_cfg(void); -extern int mpc831x_usb_cfg(void); #endif /* __MPC83XX_H__ */ diff --git a/trunk/arch/powerpc/platforms/83xx/pci.c b/trunk/arch/powerpc/platforms/83xx/pci.c index c0e2b89154e5..774457d09e94 100644 --- a/trunk/arch/powerpc/platforms/83xx/pci.c +++ b/trunk/arch/powerpc/platforms/83xx/pci.c @@ -33,14 +33,19 @@ #define DBG(x...) #endif -int mpc83xx_exclude_device(struct pci_controller *hose, u_char bus, u_char devfn) +int mpc83xx_pci2_busno; + +int mpc83xx_exclude_device(u_char bus, u_char devfn) { - if ((bus == hose->first_busno) && PCI_SLOT(devfn) == 0) + if (bus == 0 && PCI_SLOT(devfn) == 0) return PCIBIOS_DEVICE_NOT_FOUND; + if (mpc83xx_pci2_busno) + if (bus == (mpc83xx_pci2_busno) && PCI_SLOT(devfn) == 0) + return PCIBIOS_DEVICE_NOT_FOUND; return PCIBIOS_SUCCESSFUL; } -int __init mpc83xx_add_bridge(struct device_node *dev) +int __init add_bridge(struct device_node *dev) { int len; struct pci_controller *hose; @@ -61,10 +66,11 @@ int __init mpc83xx_add_bridge(struct device_node *dev) " bus 0\n", dev->full_name); } - pci_assign_all_buses = 1; - hose = pcibios_alloc_controller(dev); + hose = pcibios_alloc_controller(); if (!hose) return -ENOMEM; + hose->arch_data = dev; + hose->set_cfg_type = 1; hose->first_busno = bus_range ? bus_range[0] : 0; hose->last_busno = bus_range ? bus_range[1] : 0xff; @@ -80,6 +86,8 @@ int __init mpc83xx_add_bridge(struct device_node *dev) if ((rsrc.start & 0xfffff) == 0x8600) { setup_indirect_pci(hose, immr + 0x8380, immr + 0x8384); primary = 0; + hose->bus_offset = hose->first_busno; + mpc83xx_pci2_busno = hose->first_busno; } printk(KERN_INFO "Found MPC83xx PCI host bridge at 0x%016llx. " diff --git a/trunk/arch/powerpc/platforms/83xx/usb.c b/trunk/arch/powerpc/platforms/83xx/usb.c deleted file mode 100644 index e7fdf013cd39..000000000000 --- a/trunk/arch/powerpc/platforms/83xx/usb.c +++ /dev/null @@ -1,181 +0,0 @@ -/* - * Freescale 83xx USB SOC setup code - * - * Copyright (C) 2007 Freescale Semiconductor, Inc. - * Author: Li Yang - * - * 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 "mpc83xx.h" - - -#ifdef CONFIG_MPC834x -int mpc834x_usb_cfg(void) -{ - unsigned long sccr, sicrl, sicrh; - void __iomem *immap; - struct device_node *np = NULL; - int port0_is_dr = 0, port1_is_dr = 0; - const void *prop, *dr_mode; - - immap = ioremap(get_immrbase(), 0x1000); - if (!immap) - return -ENOMEM; - - /* Read registers */ - /* Note: DR and MPH must use the same clock setting in SCCR */ - sccr = in_be32(immap + MPC83XX_SCCR_OFFS) & ~MPC83XX_SCCR_USB_MASK; - sicrl = in_be32(immap + MPC83XX_SICRL_OFFS) & ~MPC834X_SICRL_USB_MASK; - sicrh = in_be32(immap + MPC83XX_SICRH_OFFS) & ~MPC834X_SICRH_USB_UTMI; - - np = of_find_compatible_node(NULL, "usb", "fsl-usb2-dr"); - if (np) { - sccr |= MPC83XX_SCCR_USB_DRCM_11; /* 1:3 */ - - prop = of_get_property(np, "phy_type", NULL); - if (prop && (!strcmp(prop, "utmi") || - !strcmp(prop, "utmi_wide"))) { - sicrl |= MPC834X_SICRL_USB0 | MPC834X_SICRL_USB1; - sicrh |= MPC834X_SICRH_USB_UTMI; - port1_is_dr = 1; - } else if (prop && !strcmp(prop, "serial")) { - dr_mode = of_get_property(np, "dr_mode", NULL); - if (dr_mode && !strcmp(dr_mode, "otg")) { - sicrl |= MPC834X_SICRL_USB0 | MPC834X_SICRL_USB1; - port1_is_dr = 1; - } else { - sicrl |= MPC834X_SICRL_USB0; - } - } else if (prop && !strcmp(prop, "ulpi")) { - sicrl |= MPC834X_SICRL_USB0; - } else { - printk(KERN_WARNING "834x USB PHY type not supported\n"); - } - port0_is_dr = 1; - of_node_put(np); - } - np = of_find_compatible_node(NULL, "usb", "fsl-usb2-mph"); - if (np) { - sccr |= MPC83XX_SCCR_USB_MPHCM_11; /* 1:3 */ - - prop = of_get_property(np, "port0", NULL); - if (prop) { - if (port0_is_dr) - printk(KERN_WARNING - "834x USB port0 can't be used by both DR and MPH!\n"); - sicrl |= MPC834X_SICRL_USB0; - } - prop = of_get_property(np, "port1", NULL); - if (prop) { - if (port1_is_dr) - printk(KERN_WARNING - "834x USB port1 can't be used by both DR and MPH!\n"); - sicrl |= MPC834X_SICRL_USB1; - } - of_node_put(np); - } - - /* Write back */ - out_be32(immap + MPC83XX_SCCR_OFFS, sccr); - out_be32(immap + MPC83XX_SICRL_OFFS, sicrl); - out_be32(immap + MPC83XX_SICRH_OFFS, sicrh); - - iounmap(immap); - return 0; -} -#endif /* CONFIG_MPC834x */ - -#ifdef CONFIG_PPC_MPC831x -int mpc831x_usb_cfg(void) -{ - u32 temp; - void __iomem *immap, *usb_regs; - struct device_node *np = NULL; - const void *prop; - struct resource res; - int ret = 0; -#ifdef CONFIG_USB_OTG - const void *dr_mode; -#endif - - np = of_find_compatible_node(NULL, "usb", "fsl-usb2-dr"); - if (!np) - return -ENODEV; - prop = of_get_property(np, "phy_type", NULL); - - /* Map IMMR space for pin and clock settings */ - immap = ioremap(get_immrbase(), 0x1000); - if (!immap) { - of_node_put(np); - return -ENOMEM; - } - - /* Configure clock */ - temp = in_be32(immap + MPC83XX_SCCR_OFFS); - temp &= ~MPC83XX_SCCR_USB_MASK; - temp |= MPC83XX_SCCR_USB_DRCM_11; /* 1:3 */ - out_be32(immap + MPC83XX_SCCR_OFFS, temp); - - /* Configure pin mux for ULPI. There is no pin mux for UTMI */ - if (!strcmp(prop, "ulpi")) { - temp = in_be32(immap + MPC83XX_SICRL_OFFS); - temp &= ~MPC831X_SICRL_USB_MASK; - temp |= MPC831X_SICRL_USB_ULPI; - out_be32(immap + MPC83XX_SICRL_OFFS, temp); - - temp = in_be32(immap + MPC83XX_SICRH_OFFS); - temp &= ~MPC831X_SICRH_USB_MASK; - temp |= MPC831X_SICRH_USB_ULPI; - out_be32(immap + MPC83XX_SICRH_OFFS, temp); - } - - iounmap(immap); - - /* Map USB SOC space */ - ret = of_address_to_resource(np, 0, &res); - if (ret) { - of_node_put(np); - return ret; - } - usb_regs = ioremap(res.start, res.end - res.start + 1); - - /* Using on-chip PHY */ - if (!strcmp(prop, "utmi_wide") || - !strcmp(prop, "utmi")) { - /* Set UTMI_PHY_EN, REFSEL to 48MHZ */ - out_be32(usb_regs + FSL_USB2_CONTROL_OFFS, - CONTROL_UTMI_PHY_EN | CONTROL_REFSEL_48MHZ); - /* Using external UPLI PHY */ - } else if (!strcmp(prop, "ulpi")) { - /* Set PHY_CLK_SEL to ULPI */ - temp = CONTROL_PHY_CLK_SEL_ULPI; -#ifdef CONFIG_USB_OTG - /* Set OTG_PORT */ - dr_mode = of_get_property(np, "dr_mode", NULL); - if (dr_mode && !strcmp(dr_mode, "otg")) - temp |= CONTROL_OTG_PORT; -#endif /* CONFIG_USB_OTG */ - out_be32(usb_regs + FSL_USB2_CONTROL_OFFS, temp); - } else { - printk(KERN_WARNING "831x USB PHY type not supported\n"); - ret = -EINVAL; - } - - iounmap(usb_regs); - of_node_put(np); - return ret; -} -#endif /* CONFIG_PPC_MPC831x */ diff --git a/trunk/arch/powerpc/platforms/85xx/misc.c b/trunk/arch/powerpc/platforms/85xx/misc.c index 4fe376e9c3b6..3e62fcb04c1c 100644 --- a/trunk/arch/powerpc/platforms/85xx/misc.c +++ b/trunk/arch/powerpc/platforms/85xx/misc.c @@ -13,43 +13,11 @@ #include #include #include -#include -#include -#include - -static __be32 __iomem *rstcr; extern void abort(void); -static int __init mpc85xx_rstcr(void) -{ - struct device_node *np; - np = of_find_node_by_name(NULL, "global-utilities"); - if ((np && of_get_property(np, "fsl,has-rstcr", NULL))) { - const u32 *prop = of_get_property(np, "reg", NULL); - if (prop) { - /* map reset control register - * 0xE00B0 is offset of reset control register - */ - rstcr = ioremap(get_immrbase() + *prop + 0xB0, 0xff); - if (!rstcr) - printk (KERN_EMERG "Error: reset control " - "register not mapped!\n"); - } - } else - printk (KERN_INFO "rstcr compatible register does not exist!\n"); - if (np) - of_node_put(np); - return 0; -} - -arch_initcall(mpc85xx_rstcr); - void mpc85xx_restart(char *cmd) { local_irq_disable(); - if (rstcr) - /* set reset control register */ - out_be32(rstcr, 0x2); /* HRESET_REQ */ abort(); } diff --git a/trunk/arch/powerpc/platforms/85xx/mpc8544_ds.c b/trunk/arch/powerpc/platforms/85xx/mpc8544_ds.c index 6fb90aab879f..bec84ffe708e 100644 --- a/trunk/arch/powerpc/platforms/85xx/mpc8544_ds.c +++ b/trunk/arch/powerpc/platforms/85xx/mpc8544_ds.c @@ -61,11 +61,24 @@ void __init mpc8544_ds_pic_init(void) return; } + /* Alloc mpic structure and per isu has 16 INT entries. */ mpic = mpic_alloc(np, r.start, MPIC_PRIMARY | MPIC_WANTS_RESET | MPIC_BIG_ENDIAN, - 0, 256, " OpenPIC "); + 16, 64, " OPENPIC "); BUG_ON(mpic == NULL); + /* + * 48 Internal Interrupts + */ + mpic_assign_isu(mpic, 0, r.start + 0x10200); + mpic_assign_isu(mpic, 1, r.start + 0x10400); + mpic_assign_isu(mpic, 2, r.start + 0x10600); + + /* + * 16 External interrupts + */ + mpic_assign_isu(mpic, 3, r.start + 0x10000); + mpic_init(mpic); #ifdef CONFIG_PPC_I8259 diff --git a/trunk/arch/powerpc/platforms/85xx/mpc85xx.h b/trunk/arch/powerpc/platforms/85xx/mpc85xx.h index 7286ffac2c1d..83415db33378 100644 --- a/trunk/arch/powerpc/platforms/85xx/mpc85xx.h +++ b/trunk/arch/powerpc/platforms/85xx/mpc85xx.h @@ -15,4 +15,4 @@ */ extern void mpc85xx_restart(char *); -extern int mpc85xx_add_bridge(struct device_node *dev); +extern int add_bridge(struct device_node *dev); diff --git a/trunk/arch/powerpc/platforms/85xx/mpc85xx_ads.c b/trunk/arch/powerpc/platforms/85xx/mpc85xx_ads.c index 7235f702394c..5d27621f0927 100644 --- a/trunk/arch/powerpc/platforms/85xx/mpc85xx_ads.c +++ b/trunk/arch/powerpc/platforms/85xx/mpc85xx_ads.c @@ -38,9 +38,13 @@ #include #endif +#ifndef CONFIG_PCI +unsigned long isa_io_base = 0; +unsigned long isa_mem_base = 0; +#endif + #ifdef CONFIG_PCI -static int mpc85xx_exclude_device(struct pci_controller *hose, - u_char bus, u_char devfn) +static int mpc85xx_exclude_device(u_char bus, u_char devfn) { if (bus == 0 && PCI_SLOT(devfn) == 0) return PCIBIOS_DEVICE_NOT_FOUND; @@ -87,10 +91,30 @@ static void __init mpc85xx_ads_pic_init(void) mpic = mpic_alloc(np, r.start, MPIC_PRIMARY | MPIC_WANTS_RESET | MPIC_BIG_ENDIAN, - 0, 256, " OpenPIC "); + 4, 0, " OpenPIC "); BUG_ON(mpic == NULL); of_node_put(np); + mpic_assign_isu(mpic, 0, r.start + 0x10200); + mpic_assign_isu(mpic, 1, r.start + 0x10280); + mpic_assign_isu(mpic, 2, r.start + 0x10300); + mpic_assign_isu(mpic, 3, r.start + 0x10380); + mpic_assign_isu(mpic, 4, r.start + 0x10400); + mpic_assign_isu(mpic, 5, r.start + 0x10480); + mpic_assign_isu(mpic, 6, r.start + 0x10500); + mpic_assign_isu(mpic, 7, r.start + 0x10580); + + /* Unused on this platform (leave room for 8548) */ + mpic_assign_isu(mpic, 8, r.start + 0x10600); + mpic_assign_isu(mpic, 9, r.start + 0x10680); + mpic_assign_isu(mpic, 10, r.start + 0x10700); + mpic_assign_isu(mpic, 11, r.start + 0x10780); + + /* External Interrupts */ + mpic_assign_isu(mpic, 12, r.start + 0x10000); + mpic_assign_isu(mpic, 13, r.start + 0x10080); + mpic_assign_isu(mpic, 14, r.start + 0x10100); + mpic_init(mpic); #ifdef CONFIG_CPM2 @@ -217,7 +241,7 @@ static void __init mpc85xx_ads_setup_arch(void) #ifdef CONFIG_PCI for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;) - mpc85xx_add_bridge(np); + add_bridge(np); ppc_md.pci_exclude_device = mpc85xx_exclude_device; #endif } diff --git a/trunk/arch/powerpc/platforms/85xx/mpc85xx_cds.c b/trunk/arch/powerpc/platforms/85xx/mpc85xx_cds.c index 50c8d6458362..1490eb3ce0d3 100644 --- a/trunk/arch/powerpc/platforms/85xx/mpc85xx_cds.c +++ b/trunk/arch/powerpc/platforms/85xx/mpc85xx_cds.c @@ -47,6 +47,11 @@ #include #include "mpc85xx.h" +#ifndef CONFIG_PCI +unsigned long isa_io_base = 0; +unsigned long isa_mem_base = 0; +#endif + static int cds_pci_slot = 2; static volatile u8 *cadmus; @@ -55,11 +60,15 @@ static volatile u8 *cadmus; #define ARCADIA_HOST_BRIDGE_IDSEL 17 #define ARCADIA_2ND_BRIDGE_IDSEL 3 -static int mpc85xx_exclude_device(struct pci_controller *hose, - u_char bus, u_char devfn) +extern int mpc85xx_pci2_busno; + +static int mpc85xx_exclude_device(u_char bus, u_char devfn) { - if ((bus == hose->first_busno) && PCI_SLOT(devfn) == 0) + if (bus == 0 && PCI_SLOT(devfn) == 0) return PCIBIOS_DEVICE_NOT_FOUND; + if (mpc85xx_pci2_busno) + if (bus == (mpc85xx_pci2_busno) && PCI_SLOT(devfn) == 0) + return PCIBIOS_DEVICE_NOT_FOUND; /* We explicitly do not go past the Tundra 320 Bridge */ if ((bus == 1) && (PCI_SLOT(devfn) == ARCADIA_2ND_BRIDGE_IDSEL)) return PCIBIOS_DEVICE_NOT_FOUND; @@ -69,44 +78,52 @@ static int mpc85xx_exclude_device(struct pci_controller *hose, return PCIBIOS_SUCCESSFUL; } -static void __init mpc85xx_cds_pci_irq_fixup(struct pci_dev *dev) +static void __init mpc85xx_cds_pcibios_fixup(void) { - u_char c; - if (dev->vendor == PCI_VENDOR_ID_VIA) { - switch (dev->device) { - case PCI_DEVICE_ID_VIA_82C586_1: - /* - * U-Boot does not set the enable bits - * for the IDE device. Force them on here. - */ - pci_read_config_byte(dev, 0x40, &c); - c |= 0x03; /* IDE: Chip Enable Bits */ - pci_write_config_byte(dev, 0x40, c); - - /* - * Since only primary interface works, force the - * IDE function to standard primary IDE interrupt - * w/ 8259 offset - */ - dev->irq = 14; - pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq); - break; + struct pci_dev *dev; + u_char c; + + if ((dev = pci_get_device(PCI_VENDOR_ID_VIA, + PCI_DEVICE_ID_VIA_82C586_1, NULL))) { /* - * Force legacy USB interrupt routing + * U-Boot does not set the enable bits + * for the IDE device. Force them on here. */ - case PCI_DEVICE_ID_VIA_82C586_2: - /* There are two USB controllers. - * Identify them by functon number + pci_read_config_byte(dev, 0x40, &c); + c |= 0x03; /* IDE: Chip Enable Bits */ + pci_write_config_byte(dev, 0x40, c); + + /* + * Since only primary interface works, force the + * IDE function to standard primary IDE interrupt + * w/ 8259 offset */ - if (PCI_FUNC(dev->devfn)) - dev->irq = 11; - else - dev->irq = 10; - pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq); - default: - break; - } + dev->irq = 14; + pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq); + pci_dev_put(dev); + } + + /* + * Force legacy USB interrupt routing + */ + if ((dev = pci_get_device(PCI_VENDOR_ID_VIA, + PCI_DEVICE_ID_VIA_82C586_2, NULL))) { + dev->irq = 10; + pci_write_config_byte(dev, PCI_INTERRUPT_LINE, 10); + pci_dev_put(dev); } + + if ((dev = pci_get_device(PCI_VENDOR_ID_VIA, + PCI_DEVICE_ID_VIA_82C586_2, dev))) { + dev->irq = 11; + pci_write_config_byte(dev, PCI_INTERRUPT_LINE, 11); + pci_dev_put(dev); + } + + /* Now map all the PCI irqs */ + dev = NULL; + for_each_pci_dev(dev) + pci_read_irq_line(dev); } #ifdef CONFIG_PPC_I8259 @@ -148,12 +165,33 @@ static void __init mpc85xx_cds_pic_init(void) mpic = mpic_alloc(np, r.start, MPIC_PRIMARY | MPIC_WANTS_RESET | MPIC_BIG_ENDIAN, - 0, 256, " OpenPIC "); + 4, 0, " OpenPIC "); BUG_ON(mpic == NULL); /* Return the mpic node */ of_node_put(np); + mpic_assign_isu(mpic, 0, r.start + 0x10200); + mpic_assign_isu(mpic, 1, r.start + 0x10280); + mpic_assign_isu(mpic, 2, r.start + 0x10300); + mpic_assign_isu(mpic, 3, r.start + 0x10380); + mpic_assign_isu(mpic, 4, r.start + 0x10400); + mpic_assign_isu(mpic, 5, r.start + 0x10480); + mpic_assign_isu(mpic, 6, r.start + 0x10500); + mpic_assign_isu(mpic, 7, r.start + 0x10580); + + /* Used only for 8548 so far, but no harm in + * allocating them for everyone */ + mpic_assign_isu(mpic, 8, r.start + 0x10600); + mpic_assign_isu(mpic, 9, r.start + 0x10680); + mpic_assign_isu(mpic, 10, r.start + 0x10700); + mpic_assign_isu(mpic, 11, r.start + 0x10780); + + /* External Interrupts */ + mpic_assign_isu(mpic, 12, r.start + 0x10000); + mpic_assign_isu(mpic, 13, r.start + 0x10080); + mpic_assign_isu(mpic, 14, r.start + 0x10100); + mpic_init(mpic); #ifdef CONFIG_PPC_I8259 @@ -219,9 +257,9 @@ static void __init mpc85xx_cds_setup_arch(void) #ifdef CONFIG_PCI for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;) - mpc85xx_add_bridge(np); + add_bridge(np); - ppc_md.pci_irq_fixup = mpc85xx_cds_pci_irq_fixup; + ppc_md.pcibios_fixup = mpc85xx_cds_pcibios_fixup; ppc_md.pci_exclude_device = mpc85xx_exclude_device; #endif } diff --git a/trunk/arch/powerpc/platforms/85xx/mpc85xx_mds.c b/trunk/arch/powerpc/platforms/85xx/mpc85xx_mds.c index 004b80bd0b84..e3dddbfe66ff 100644 --- a/trunk/arch/powerpc/platforms/85xx/mpc85xx_mds.c +++ b/trunk/arch/powerpc/platforms/85xx/mpc85xx_mds.c @@ -59,6 +59,11 @@ #define DBG(fmt...) #endif +#ifndef CONFIG_PCI +unsigned long isa_io_base = 0; +unsigned long isa_mem_base = 0; +#endif + /* ************************************************************************ * * Setup the architecture @@ -95,7 +100,7 @@ static void __init mpc85xx_mds_setup_arch(void) #ifdef CONFIG_PCI for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;) { - mpc85xx_add_bridge(np); + add_bridge(np); } of_node_put(np); #endif @@ -176,10 +181,29 @@ static void __init mpc85xx_mds_pic_init(void) mpic = mpic_alloc(np, r.start, MPIC_PRIMARY | MPIC_WANTS_RESET | MPIC_BIG_ENDIAN, - 0, 256, " OpenPIC "); + 4, 0, " OpenPIC "); BUG_ON(mpic == NULL); of_node_put(np); + /* Internal Interrupts */ + mpic_assign_isu(mpic, 0, r.start + 0x10200); + mpic_assign_isu(mpic, 1, r.start + 0x10280); + mpic_assign_isu(mpic, 2, r.start + 0x10300); + mpic_assign_isu(mpic, 3, r.start + 0x10380); + mpic_assign_isu(mpic, 4, r.start + 0x10400); + mpic_assign_isu(mpic, 5, r.start + 0x10480); + mpic_assign_isu(mpic, 6, r.start + 0x10500); + mpic_assign_isu(mpic, 7, r.start + 0x10580); + mpic_assign_isu(mpic, 8, r.start + 0x10600); + mpic_assign_isu(mpic, 9, r.start + 0x10680); + mpic_assign_isu(mpic, 10, r.start + 0x10700); + mpic_assign_isu(mpic, 11, r.start + 0x10780); + + /* External Interrupts */ + mpic_assign_isu(mpic, 12, r.start + 0x10000); + mpic_assign_isu(mpic, 13, r.start + 0x10080); + mpic_assign_isu(mpic, 14, r.start + 0x10100); + mpic_init(mpic); #ifdef CONFIG_QUICC_ENGINE diff --git a/trunk/arch/powerpc/platforms/85xx/pci.c b/trunk/arch/powerpc/platforms/85xx/pci.c index 8118417b7364..48f17e23d771 100644 --- a/trunk/arch/powerpc/platforms/85xx/pci.c +++ b/trunk/arch/powerpc/platforms/85xx/pci.c @@ -33,8 +33,10 @@ #define DBG(x...) #endif +int mpc85xx_pci2_busno = 0; + #ifdef CONFIG_PCI -int __init mpc85xx_add_bridge(struct device_node *dev) +int __init add_bridge(struct device_node *dev) { int len; struct pci_controller *hose; @@ -55,10 +57,11 @@ int __init mpc85xx_add_bridge(struct device_node *dev) " bus 0\n", dev->full_name); } - pci_assign_all_buses = 1; - hose = pcibios_alloc_controller(dev); + hose = pcibios_alloc_controller(); if (!hose) return -ENOMEM; + hose->arch_data = dev; + hose->set_cfg_type = 1; hose->first_busno = bus_range ? bus_range[0] : 0; hose->last_busno = bus_range ? bus_range[1] : 0xff; @@ -71,6 +74,8 @@ int __init mpc85xx_add_bridge(struct device_node *dev) if ((rsrc.start & 0xfffff) == 0x9000) { setup_indirect_pci(hose, immr + 0x9000, immr + 0x9004); primary = 0; + hose->bus_offset = hose->first_busno; + mpc85xx_pci2_busno = hose->first_busno; } printk(KERN_INFO "Found MPC85xx PCI host bridge at 0x%016llx. " diff --git a/trunk/arch/powerpc/platforms/86xx/Kconfig b/trunk/arch/powerpc/platforms/86xx/Kconfig index 0faebfdc1596..d1bcff500464 100644 --- a/trunk/arch/powerpc/platforms/86xx/Kconfig +++ b/trunk/arch/powerpc/platforms/86xx/Kconfig @@ -1,5 +1,5 @@ choice - prompt "86xx Board Type" + prompt "Machine Type" depends on PPC_86xx default MPC8641_HPCN diff --git a/trunk/arch/powerpc/platforms/86xx/mpc86xx.h b/trunk/arch/powerpc/platforms/86xx/mpc86xx.h index 23f7ed2a7f88..2834462590b8 100644 --- a/trunk/arch/powerpc/platforms/86xx/mpc86xx.h +++ b/trunk/arch/powerpc/platforms/86xx/mpc86xx.h @@ -15,10 +15,15 @@ * mpc86xx_* files. Mostly for use by mpc86xx_setup(). */ -extern int mpc86xx_add_bridge(struct device_node *dev); +extern int add_bridge(struct device_node *dev); -extern int mpc86xx_exclude_device(struct pci_controller *hose, - u_char bus, u_char devfn); +extern int mpc86xx_exclude_device(u_char bus, u_char devfn); + +extern void setup_indirect_pcie(struct pci_controller *hose, + u32 cfg_addr, u32 cfg_data); +extern void setup_indirect_pcie_nomap(struct pci_controller *hose, + void __iomem *cfg_addr, + void __iomem *cfg_data); extern void __init mpc86xx_smp_init(void); diff --git a/trunk/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c b/trunk/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c index 5b01ec7c13dc..1051702c8d4f 100644 --- a/trunk/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c +++ b/trunk/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c @@ -44,6 +44,13 @@ #define DBG(fmt...) do { } while(0) #endif +#ifndef CONFIG_PCI +unsigned long isa_io_base = 0; +unsigned long isa_mem_base = 0; +unsigned long pci_dram_offset = 0; +#endif + + #ifdef CONFIG_PCI static void mpc86xx_8259_cascade(unsigned int irq, struct irq_desc *desc) { @@ -74,9 +81,22 @@ mpc86xx_hpcn_init_irq(void) /* Alloc mpic structure and per isu has 16 INT entries. */ mpic1 = mpic_alloc(np, res.start, MPIC_PRIMARY | MPIC_WANTS_RESET | MPIC_BIG_ENDIAN, - 0, 256, " MPIC "); + 16, NR_IRQS - 4, + " MPIC "); BUG_ON(mpic1 == NULL); + mpic_assign_isu(mpic1, 0, res.start + 0x10000); + + /* 48 Internal Interrupts */ + mpic_assign_isu(mpic1, 1, res.start + 0x10200); + mpic_assign_isu(mpic1, 2, res.start + 0x10400); + mpic_assign_isu(mpic1, 3, res.start + 0x10600); + + /* 16 External interrupts + * Moving them from [0 - 15] to [64 - 79] + */ + mpic_assign_isu(mpic1, 4, res.start + 0x10000); + mpic_init(mpic1); #ifdef CONFIG_PCI @@ -299,7 +319,6 @@ static void __devinit quirk_uli5229(struct pci_dev *dev) { unsigned short temp; pci_write_config_word(dev, 0x04, 0x0405); - dev->class &= ~0x5; pci_read_config_word(dev, 0x4a, &temp); temp |= 0x1000; pci_write_config_word(dev, 0x4a, temp); @@ -345,7 +364,9 @@ mpc86xx_hpcn_setup_arch(void) #ifdef CONFIG_PCI for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;) - mpc86xx_add_bridge(np); + add_bridge(np); + + ppc_md.pci_exclude_device = mpc86xx_exclude_device; #endif printk("MPC86xx HPCN board from Freescale Semiconductor\n"); diff --git a/trunk/arch/powerpc/platforms/86xx/pci.c b/trunk/arch/powerpc/platforms/86xx/pci.c index 73cd5b05a84e..8235c562661f 100644 --- a/trunk/arch/powerpc/platforms/86xx/pci.c +++ b/trunk/arch/powerpc/platforms/86xx/pci.c @@ -122,6 +122,7 @@ static void __init mpc86xx_setup_pcie(struct pci_controller *hose, u32 pcie_offset, u32 pcie_size) { u16 cmd; + unsigned int temps; DBG("PCIE host controller register offset 0x%08x, size 0x%08x.\n", pcie_offset, pcie_size); @@ -132,49 +133,22 @@ mpc86xx_setup_pcie(struct pci_controller *hose, u32 pcie_offset, u32 pcie_size) early_write_config_word(hose, 0, 0, PCI_COMMAND, cmd); early_write_config_byte(hose, 0, 0, PCI_LATENCY_TIMER, 0x80); + + /* PCIE Bus, Fix the MPC8641D host bridge's location to bus 0xFF. */ + early_read_config_dword(hose, 0, 0, PCI_PRIMARY_BUS, &temps); + temps = (temps & 0xff000000) | (0xff) | (0x0 << 8) | (0xfe << 16); + early_write_config_dword(hose, 0, 0, PCI_PRIMARY_BUS, temps); } -static void __devinit quirk_fsl_pcie_transparent(struct pci_dev *dev) +int mpc86xx_exclude_device(u_char bus, u_char devfn) { - struct resource *res; - int i, res_idx = PCI_BRIDGE_RESOURCES; - struct pci_controller *hose; + if (bus == 0 && PCI_SLOT(devfn) == 0) + return PCIBIOS_DEVICE_NOT_FOUND; - /* - * Make the bridge be transparent. - */ - dev->transparent = 1; - - hose = pci_bus_to_host(dev->bus); - if (!hose) { - printk(KERN_ERR "Can't find hose for bus %d\n", - dev->bus->number); - return; - } - - if (hose->io_resource.flags) { - res = &dev->resource[res_idx++]; - res->start = hose->io_resource.start; - res->end = hose->io_resource.end; - res->flags = hose->io_resource.flags; - } - - for (i = 0; i < 3; i++) { - res = &dev->resource[res_idx + i]; - res->start = hose->mem_resources[i].start; - res->end = hose->mem_resources[i].end; - res->flags = hose->mem_resources[i].flags; - } + return PCIBIOS_SUCCESSFUL; } - -DECLARE_PCI_FIXUP_EARLY(0x1957, 0x7010, quirk_fsl_pcie_transparent); -DECLARE_PCI_FIXUP_EARLY(0x1957, 0x7011, quirk_fsl_pcie_transparent); - -#define PCIE_LTSSM 0x404 /* PCIe Link Training and Status */ -#define PCIE_LTSSM_L0 0x16 /* L0 state */ - -int __init mpc86xx_add_bridge(struct device_node *dev) +int __init add_bridge(struct device_node *dev) { int len; struct pci_controller *hose; @@ -182,7 +156,6 @@ int __init mpc86xx_add_bridge(struct device_node *dev) const int *bus_range; int has_address = 0; int primary = 0; - u16 val; DBG("Adding PCIE host bridge %s\n", dev->full_name); @@ -195,23 +168,17 @@ int __init mpc86xx_add_bridge(struct device_node *dev) printk(KERN_WARNING "Can't get bus-range for %s, assume" " bus 0\n", dev->full_name); - pci_assign_all_buses = 1; - hose = pcibios_alloc_controller(dev); + hose = pcibios_alloc_controller(); if (!hose) return -ENOMEM; + hose->arch_data = dev; + hose->set_cfg_type = 1; - hose->indirect_type = PPC_INDIRECT_TYPE_EXT_REG | - PPC_INDIRECT_TYPE_SURPRESS_PRIMARY_BUS; - + /* last_busno = 0xfe cause by MPC8641 PCIE bug */ hose->first_busno = bus_range ? bus_range[0] : 0x0; - hose->last_busno = bus_range ? bus_range[1] : 0xff; - - setup_indirect_pci(hose, rsrc.start, rsrc.start + 0x4); + hose->last_busno = bus_range ? bus_range[1] : 0xfe; - /* Probe the hose link training status */ - early_read_config_word(hose, 0, 0, PCIE_LTSSM, &val); - if (val < PCIE_LTSSM_L0) - return -ENXIO; + setup_indirect_pcie(hose, rsrc.start, rsrc.start + 0x4); /* Setup the PCIE host controller. */ mpc86xx_setup_pcie(hose, rsrc.start, rsrc.end - rsrc.start + 1); diff --git a/trunk/arch/powerpc/platforms/8xx/m8xx_setup.c b/trunk/arch/powerpc/platforms/8xx/m8xx_setup.c index f1693550c70c..0901dbada350 100644 --- a/trunk/arch/powerpc/platforms/8xx/m8xx_setup.c +++ b/trunk/arch/powerpc/platforms/8xx/m8xx_setup.c @@ -32,7 +32,6 @@ #include #include #include -#include #include #include @@ -50,10 +49,6 @@ #include "sysdev/mpc8xx_pic.h" -#ifdef CONFIG_PCMCIA_M8XX -struct mpc8xx_pcmcia_ops m8xx_pcmcia_ops; -#endif - void m8xx_calibrate_decr(void); extern void m8xx_wdt_handler_install(bd_t *bp); extern int cpm_pic_init(void); diff --git a/trunk/arch/powerpc/platforms/8xx/mpc885ads_setup.c b/trunk/arch/powerpc/platforms/8xx/mpc885ads_setup.c index dc27dab48df0..c36e475d93dc 100644 --- a/trunk/arch/powerpc/platforms/8xx/mpc885ads_setup.c +++ b/trunk/arch/powerpc/platforms/8xx/mpc885ads_setup.c @@ -22,7 +22,6 @@ #include #include -#include #include #include @@ -52,70 +51,6 @@ static void init_smc1_uart_ioports(struct fs_uart_platform_info* fpi); static void init_smc2_uart_ioports(struct fs_uart_platform_info* fpi); static void init_scc3_ioports(struct fs_platform_info* ptr); -#ifdef CONFIG_PCMCIA_M8XX -static void pcmcia_hw_setup(int slot, int enable) -{ - unsigned *bcsr_io; - - bcsr_io = ioremap(BCSR1, sizeof(unsigned long)); - if (enable) - clrbits32(bcsr_io, BCSR1_PCCEN); - else - setbits32(bcsr_io, BCSR1_PCCEN); - - iounmap(bcsr_io); -} - -static int pcmcia_set_voltage(int slot, int vcc, int vpp) -{ - u32 reg = 0; - unsigned *bcsr_io; - - bcsr_io = ioremap(BCSR1, sizeof(unsigned long)); - - switch(vcc) { - case 0: - break; - case 33: - reg |= BCSR1_PCCVCC0; - break; - case 50: - reg |= BCSR1_PCCVCC1; - break; - default: - return 1; - } - - switch(vpp) { - case 0: - break; - case 33: - case 50: - if(vcc == vpp) - reg |= BCSR1_PCCVPP1; - else - return 1; - break; - case 120: - if ((vcc == 33) || (vcc == 50)) - reg |= BCSR1_PCCVPP0; - else - return 1; - default: - return 1; - } - - /* first, turn off all power */ - clrbits32(bcsr_io, 0x00610000); - - /* enable new powersettings */ - setbits32(bcsr_io, reg); - - iounmap(bcsr_io); - return 0; -} -#endif - void __init mpc885ads_board_setup(void) { cpm8xx_t *cp; @@ -180,12 +115,6 @@ void __init mpc885ads_board_setup(void) immr_unmap(io_port); #endif - -#ifdef CONFIG_PCMCIA_M8XX - /*Set up board specific hook-ups*/ - m8xx_pcmcia_ops.hw_ctrl = pcmcia_hw_setup; - m8xx_pcmcia_ops.voltage_set = pcmcia_set_voltage; -#endif } diff --git a/trunk/arch/powerpc/platforms/Kconfig b/trunk/arch/powerpc/platforms/Kconfig index 33545d352e92..361acfa2894c 100644 --- a/trunk/arch/powerpc/platforms/Kconfig +++ b/trunk/arch/powerpc/platforms/Kconfig @@ -2,7 +2,7 @@ menu "Platform support" choice prompt "Machine type" - depends on PPC64 || 6xx + depends on PPC64 || CLASSIC32 default PPC_MULTIPLATFORM config PPC_MULTIPLATFORM @@ -16,30 +16,15 @@ config EMBEDDED6xx bool "Embedded 6xx/7xx/7xxx-based board" depends on PPC32 && (BROKEN||BROKEN_ON_SMP) -config PPC_82xx - bool "Freescale 82xx" - depends on 6xx - -config PPC_83xx - bool "Freescale 83xx" - depends on 6xx - select FSL_SOC - select 83xx - select WANT_DEVICE_TREE - -config PPC_86xx - bool "Freescale 86xx" - depends on 6xx - select FSL_SOC - select ALTIVEC +config APUS + bool "Amiga-APUS" + depends on PPC32 && BROKEN help - The Freescale E600 SoCs have 74xx cores. + Select APUS if configuring for a PowerUP Amiga. + More information is available at: + . endchoice -config CLASSIC32 - def_bool y - depends on 6xx && PPC_MULTIPLATFORM - source "arch/powerpc/platforms/pseries/Kconfig" source "arch/powerpc/platforms/iseries/Kconfig" source "arch/powerpc/platforms/chrp/Kconfig" diff --git a/trunk/arch/powerpc/platforms/Kconfig.cputype b/trunk/arch/powerpc/platforms/Kconfig.cputype deleted file mode 100644 index b8b5fde94668..000000000000 --- a/trunk/arch/powerpc/platforms/Kconfig.cputype +++ /dev/null @@ -1,221 +0,0 @@ -config PPC64 - bool "64-bit kernel" - default n - help - This option selects whether a 32-bit or a 64-bit kernel - will be built. - -menu "Processor support" -choice - prompt "Processor Type" - depends on PPC32 - default 6xx - help - There are five families of 32 bit PowerPC chips supported. - The most common ones are the desktop and server CPUs (601, 603, - 604, 740, 750, 74xx) CPUs from Freescale and IBM, with their - embedded 52xx/82xx/83xx/86xx counterparts. - The other embeeded parts, namely 4xx, 8xx, e200 (55xx) and e500 - (85xx) each form a family of their own that is not compatible - with the others. - - If unsure, select 52xx/6xx/7xx/74xx/82xx/83xx/86xx. - -config 6xx - bool "52xx/6xx/7xx/74xx/82xx/83xx/86xx" - select PPC_FPU - -config PPC_85xx - bool "Freescale 85xx" - select E500 - select FSL_SOC - select 85xx - select WANT_DEVICE_TREE - -config PPC_8xx - bool "Freescale 8xx" - select FSL_SOC - select 8xx - -config 40x - bool "AMCC 40x" - select PPC_DCR_NATIVE - -config 44x - bool "AMCC 44x" - select PPC_DCR_NATIVE - select WANT_DEVICE_TREE - -config E200 - bool "Freescale e200" - -endchoice - -config POWER4_ONLY - bool "Optimize for POWER4" - depends on PPC64 - default n - ---help--- - Cause the compiler to optimize for POWER4/POWER5/PPC970 processors. - The resulting binary will not work on POWER3 or RS64 processors - when compiled with binutils 2.15 or later. - -config POWER3 - bool - depends on PPC64 - default y if !POWER4_ONLY - -config POWER4 - depends on PPC64 - def_bool y - -config 6xx - bool - -# this is temp to handle compat with arch=ppc -config 8xx - bool - -# this is temp to handle compat with arch=ppc -config 83xx - bool - -# this is temp to handle compat with arch=ppc -config 85xx - bool - -config E500 - bool - -config PPC_FPU - bool - default y if PPC64 - -config 4xx - bool - depends on 40x || 44x - default y - -config BOOKE - bool - depends on E200 || E500 || 44x - default y - -config FSL_BOOKE - bool - depends on E200 || E500 - default y - -config PTE_64BIT - bool - depends on 44x || E500 - default y if 44x - default y if E500 && PHYS_64BIT - -config PHYS_64BIT - bool 'Large physical address support' if E500 - depends on 44x || E500 - select RESOURCES_64BIT - default y if 44x - ---help--- - This option enables kernel support for larger than 32-bit physical - addresses. This features is not be available on all e500 cores. - - If in doubt, say N here. - -config ALTIVEC - bool "AltiVec Support" - depends on CLASSIC32 || POWER4 - ---help--- - This option enables kernel support for the Altivec extensions to the - PowerPC processor. The kernel currently supports saving and restoring - altivec registers, and turning on the 'altivec enable' bit so user - processes can execute altivec instructions. - - This option is only usefully if you have a processor that supports - altivec (G4, otherwise known as 74xx series), but does not have - any affect on a non-altivec cpu (it does, however add code to the - kernel). - - If in doubt, say Y here. - -config SPE - bool "SPE Support" - depends on E200 || E500 - default y - ---help--- - This option enables kernel support for the Signal Processing - Extensions (SPE) to the PowerPC processor. The kernel currently - supports saving and restoring SPE registers, and turning on the - 'spe enable' bit so user processes can execute SPE instructions. - - This option is only useful if you have a processor that supports - SPE (e500, otherwise known as 85xx series), but does not have any - effect on a non-spe cpu (it does, however add code to the kernel). - - If in doubt, say Y here. - -config PPC_STD_MMU - bool - depends on 6xx || POWER3 || POWER4 || PPC64 - default y - -config PPC_STD_MMU_32 - def_bool y - depends on PPC_STD_MMU && PPC32 - -config PPC_MM_SLICES - bool - default y if HUGETLB_PAGE - default n - -config VIRT_CPU_ACCOUNTING - bool "Deterministic task and CPU time accounting" - depends on PPC64 - default y - help - Select this option to enable more accurate task and CPU time - accounting. This is done by reading a CPU counter on each - kernel entry and exit and on transitions within the kernel - between system, softirq and hardirq state, so there is a - small performance impact. This also enables accounting of - stolen time on logically-partitioned systems running on - IBM POWER5-based machines. - - If in doubt, say Y here. - -config SMP - depends on PPC_STD_MMU - bool "Symmetric multi-processing support" - ---help--- - This enables support for systems with more than one CPU. If you have - a system with only one CPU, say N. If you have a system with more - than one CPU, say Y. Note that the kernel does not currently - support SMP machines with 603/603e/603ev or PPC750 ("G3") processors - since they have inadequate hardware support for multiprocessor - operation. - - If you say N here, the kernel will run on single and multiprocessor - machines, but will use only one CPU of a multiprocessor machine. If - you say Y here, the kernel will run on single-processor machines. - On a single-processor machine, the kernel will run faster if you say - N here. - - If you don't know what to do here, say N. - -config NR_CPUS - int "Maximum number of CPUs (2-128)" - range 2 128 - depends on SMP - default "32" if PPC64 - default "4" - -config NOT_COHERENT_CACHE - bool - depends on 4xx || 8xx || E200 - default y - -config CONFIG_CHECK_CACHE_COHERENCY - bool - -endmenu diff --git a/trunk/arch/powerpc/platforms/apus/Kconfig b/trunk/arch/powerpc/platforms/apus/Kconfig new file mode 100644 index 000000000000..6bde3bffed86 --- /dev/null +++ b/trunk/arch/powerpc/platforms/apus/Kconfig @@ -0,0 +1,130 @@ + +config AMIGA + bool + depends on APUS + default y + help + This option enables support for the Amiga series of computers. + +config ZORRO + bool + depends on APUS + default y + help + This enables support for the Zorro bus in the Amiga. If you have + expansion cards in your Amiga that conform to the Amiga + AutoConfig(tm) specification, say Y, otherwise N. Note that even + expansion cards that do not fit in the Zorro slots but fit in e.g. + the CPU slot may fall in this category, so you have to say Y to let + Linux use these. + +config ABSTRACT_CONSOLE + bool + depends on APUS + default y + +config APUS_FAST_EXCEPT + bool + depends on APUS + default y + +config AMIGA_PCMCIA + bool "Amiga 1200/600 PCMCIA support" + depends on APUS && EXPERIMENTAL + help + Include support in the kernel for pcmcia on Amiga 1200 and Amiga + 600. If you intend to use pcmcia cards say Y; otherwise say N. + +config AMIGA_BUILTIN_SERIAL + tristate "Amiga builtin serial support" + depends on APUS + help + If you want to use your Amiga's built-in serial port in Linux, + answer Y. + + To compile this driver as a module, choose M here. + +config GVPIOEXT + tristate "GVP IO-Extender support" + depends on APUS + help + If you want to use a GVP IO-Extender serial card in Linux, say Y. + Otherwise, say N. + +config GVPIOEXT_LP + tristate "GVP IO-Extender parallel printer support" + depends on GVPIOEXT + help + Say Y to enable driving a printer from the parallel port on your + GVP IO-Extender card, N otherwise. + +config GVPIOEXT_PLIP + tristate "GVP IO-Extender PLIP support" + depends on GVPIOEXT + help + Say Y to enable doing IP over the parallel port on your GVP + IO-Extender card, N otherwise. + +config MULTIFACE_III_TTY + tristate "Multiface Card III serial support" + depends on APUS + help + If you want to use a Multiface III card's serial port in Linux, + answer Y. + + To compile this driver as a module, choose M here. + +config A2232 + tristate "Commodore A2232 serial support (EXPERIMENTAL)" + depends on EXPERIMENTAL && APUS + ---help--- + This option supports the 2232 7-port serial card shipped with the + Amiga 2000 and other Zorro-bus machines, dating from 1989. At + a max of 19,200 bps, the ports are served by a 6551 ACIA UART chip + each, plus a 8520 CIA, and a master 6502 CPU and buffer as well. The + ports were connected with 8 pin DIN connectors on the card bracket, + for which 8 pin to DB25 adapters were supplied. The card also had + jumpers internally to toggle various pinning configurations. + + This driver can be built as a module; but then "generic_serial" + will also be built as a module. This has to be loaded before + "ser_a2232". If you want to do this, answer M here. + +config WHIPPET_SERIAL + tristate "Hisoft Whippet PCMCIA serial support" + depends on AMIGA_PCMCIA + help + HiSoft has a web page at , but there + is no listing for the Whippet in their Amiga section. + +config APNE + tristate "PCMCIA NE2000 support" + depends on AMIGA_PCMCIA + help + If you have a PCMCIA NE2000 compatible adapter, say Y. Otherwise, + say N. + + To compile this driver as a module, choose M here: the + module will be called apne. + +config SERIAL_CONSOLE + bool "Support for serial port console" + depends on APUS && (AMIGA_BUILTIN_SERIAL=y || GVPIOEXT=y || MULTIFACE_III_TTY=y) + +config HEARTBEAT + bool "Use power LED as a heartbeat" + depends on APUS + help + Use the power-on LED on your machine as a load meter. The exact + behavior is platform-dependent, but normally the flash frequency is + a hyperbolic function of the 5-minute load average. + +config PROC_HARDWARE + bool "/proc/hardware support" + depends on APUS + +source "drivers/zorro/Kconfig" + +config PCI_PERMEDIA + bool "PCI for Permedia2" + depends on !4xx && !8xx && APUS diff --git a/trunk/arch/powerpc/platforms/cell/io-workarounds.c b/trunk/arch/powerpc/platforms/cell/io-workarounds.c index 9d7c2ef940a8..7fb92f23f380 100644 --- a/trunk/arch/powerpc/platforms/cell/io-workarounds.c +++ b/trunk/arch/powerpc/platforms/cell/io-workarounds.c @@ -102,7 +102,7 @@ static void spider_io_flush(const volatile void __iomem *addr) vaddr = (unsigned long)PCI_FIX_ADDR(addr); /* Check if it's in allowed range for PIO */ - if (vaddr < PHB_IO_BASE || vaddr > PHB_IO_END) + if (vaddr < PHBS_IO_BASE || vaddr >= IMALLOC_BASE) return; /* Try to find a PTE. If not, clear the paddr, we'll do diff --git a/trunk/arch/powerpc/platforms/cell/spu_base.c b/trunk/arch/powerpc/platforms/cell/spu_base.c index e4d0c9f42abd..a7f5a7653c62 100644 --- a/trunk/arch/powerpc/platforms/cell/spu_base.c +++ b/trunk/arch/powerpc/platforms/cell/spu_base.c @@ -183,7 +183,7 @@ static int __spu_trap_data_seg(struct spu *spu, unsigned long ea) spu->slb_replace = 0; spu_restart_dma(spu); - spu->stats.slb_flt++; + return 0; } @@ -332,7 +332,6 @@ spu_irq_class_2(int irq, void *data) if (stat & 0x10) /* SPU mailbox threshold */ spu->wbox_callback(spu); - spu->stats.class2_intr++; return stat ? IRQ_HANDLED : IRQ_NONE; } @@ -463,18 +462,8 @@ void spu_free(struct spu *spu) } EXPORT_SYMBOL_GPL(spu_free); -static int spu_shutdown(struct sys_device *sysdev) -{ - struct spu *spu = container_of(sysdev, struct spu, sysdev); - - spu_free_irqs(spu); - spu_destroy_spu(spu); - return 0; -} - struct sysdev_class spu_sysdev_class = { - set_kset_name("spu"), - .shutdown = spu_shutdown, + set_kset_name("spu") }; int spu_add_sysdev_attr(struct sysdev_attribute *attr) @@ -585,9 +574,6 @@ static int __init create_spu(void *data) spin_unlock_irqrestore(&spu_list_lock, flags); mutex_unlock(&spu_mutex); - spu->stats.utilization_state = SPU_UTIL_IDLE; - spu->stats.tstamp = jiffies; - goto out; out_free_irqs: @@ -600,45 +586,6 @@ static int __init create_spu(void *data) return ret; } -static const char *spu_state_names[] = { - "user", "system", "iowait", "idle" -}; - -static unsigned long long spu_acct_time(struct spu *spu, - enum spu_utilization_state state) -{ - unsigned long long time = spu->stats.times[state]; - - if (spu->stats.utilization_state == state) - time += jiffies - spu->stats.tstamp; - - return jiffies_to_msecs(time); -} - - -static ssize_t spu_stat_show(struct sys_device *sysdev, char *buf) -{ - struct spu *spu = container_of(sysdev, struct spu, sysdev); - - return sprintf(buf, "%s %llu %llu %llu %llu " - "%llu %llu %llu %llu %llu %llu %llu %llu\n", - spu_state_names[spu->stats.utilization_state], - spu_acct_time(spu, SPU_UTIL_USER), - spu_acct_time(spu, SPU_UTIL_SYSTEM), - spu_acct_time(spu, SPU_UTIL_IOWAIT), - spu_acct_time(spu, SPU_UTIL_IDLE), - spu->stats.vol_ctx_switch, - spu->stats.invol_ctx_switch, - spu->stats.slb_flt, - spu->stats.hash_flt, - spu->stats.min_flt, - spu->stats.maj_flt, - spu->stats.class2_intr, - spu->stats.libassist); -} - -static SYSDEV_ATTR(stat, 0644, spu_stat_show, NULL); - static int __init init_spu_base(void) { int i, ret = 0; @@ -664,8 +611,6 @@ static int __init init_spu_base(void) xmon_register_spus(&spu_full_list); - spu_add_sysdev_attr(&attr_stat); - return 0; out_unregister_sysdev_class: diff --git a/trunk/arch/powerpc/platforms/cell/spufs/backing_ops.c b/trunk/arch/powerpc/platforms/cell/spufs/backing_ops.c index 07a0e815abf5..d32db9ffc6eb 100644 --- a/trunk/arch/powerpc/platforms/cell/spufs/backing_ops.c +++ b/trunk/arch/powerpc/platforms/cell/spufs/backing_ops.c @@ -320,12 +320,6 @@ static int spu_backing_set_mfc_query(struct spu_context * ctx, u32 mask, /* FIXME: what are the side-effects of this? */ prob->dma_querymask_RW = mask; prob->dma_querytype_RW = mode; - /* In the current implementation, the SPU context is always - * acquired in runnable state when new bits are added to the - * mask (tagwait), so it's sufficient just to mask - * dma_tagstatus_R with the 'mask' parameter here. - */ - ctx->csa.prob.dma_tagstatus_R &= mask; out: spin_unlock(&ctx->csa.register_lock); diff --git a/trunk/arch/powerpc/platforms/cell/spufs/context.c b/trunk/arch/powerpc/platforms/cell/spufs/context.c index 6d7bd60f5380..7c51cb54bca1 100644 --- a/trunk/arch/powerpc/platforms/cell/spufs/context.c +++ b/trunk/arch/powerpc/platforms/cell/spufs/context.c @@ -23,14 +23,10 @@ #include #include #include -#include #include #include #include "spufs.h" - -atomic_t nr_spu_contexts = ATOMIC_INIT(0); - struct spu_context *alloc_spu_context(struct spu_gang *gang) { struct spu_context *ctx; @@ -57,12 +53,10 @@ struct spu_context *alloc_spu_context(struct spu_gang *gang) INIT_LIST_HEAD(&ctx->rq); if (gang) spu_gang_add_ctx(gang, ctx); - ctx->cpus_allowed = current->cpus_allowed; - spu_set_timeslice(ctx); - ctx->stats.execution_state = SPUCTX_UTIL_USER; - ctx->stats.tstamp = jiffies; - - atomic_inc(&nr_spu_contexts); + ctx->rt_priority = current->rt_priority; + ctx->policy = current->policy; + ctx->prio = current->prio; + INIT_DELAYED_WORK(&ctx->sched_work, spu_sched_tick); goto out; out_free: kfree(ctx); @@ -82,7 +76,6 @@ void destroy_spu_context(struct kref *kref) if (ctx->gang) spu_gang_remove_ctx(ctx->gang, ctx); BUG_ON(!list_empty(&ctx->rq)); - atomic_dec(&nr_spu_contexts); kfree(ctx); } diff --git a/trunk/arch/powerpc/platforms/cell/spufs/fault.c b/trunk/arch/powerpc/platforms/cell/spufs/fault.c index e064d0c0d80e..0f75c07e29d8 100644 --- a/trunk/arch/powerpc/platforms/cell/spufs/fault.c +++ b/trunk/arch/powerpc/platforms/cell/spufs/fault.c @@ -33,8 +33,7 @@ * function. Currently, there are a few corner cases that we haven't had * to handle fortunately. */ -static int spu_handle_mm_fault(struct mm_struct *mm, unsigned long ea, - unsigned long dsisr, unsigned *flt) +static int spu_handle_mm_fault(struct mm_struct *mm, unsigned long ea, unsigned long dsisr) { struct vm_area_struct *vma; unsigned long is_write; @@ -74,8 +73,7 @@ static int spu_handle_mm_fault(struct mm_struct *mm, unsigned long ea, goto bad_area; } ret = 0; - *flt = handle_mm_fault(mm, vma, ea, is_write); - switch (*flt) { + switch (handle_mm_fault(mm, vma, ea, is_write)) { case VM_FAULT_MINOR: current->min_flt++; break; @@ -155,7 +153,6 @@ int spufs_handle_class1(struct spu_context *ctx) { u64 ea, dsisr, access; unsigned long flags; - unsigned flt = 0; int ret; /* @@ -181,17 +178,9 @@ int spufs_handle_class1(struct spu_context *ctx) if (!(dsisr & (MFC_DSISR_PTE_NOT_FOUND | MFC_DSISR_ACCESS_DENIED))) return 0; - spuctx_switch_state(ctx, SPUCTX_UTIL_IOWAIT); - pr_debug("ctx %p: ea %016lx, dsisr %016lx state %d\n", ctx, ea, dsisr, ctx->state); - ctx->stats.hash_flt++; - if (ctx->state == SPU_STATE_RUNNABLE) { - ctx->spu->stats.hash_flt++; - spu_switch_state(ctx->spu, SPU_UTIL_IOWAIT); - } - /* we must not hold the lock when entering spu_handle_mm_fault */ spu_release(ctx); @@ -203,7 +192,7 @@ int spufs_handle_class1(struct spu_context *ctx) /* hashing failed, so try the actual fault handler */ if (ret) - ret = spu_handle_mm_fault(current->mm, ea, dsisr, &flt); + ret = spu_handle_mm_fault(current->mm, ea, dsisr); spu_acquire(ctx); /* @@ -212,23 +201,11 @@ int spufs_handle_class1(struct spu_context *ctx) * In case of unhandled error report the problem to user space. */ if (!ret) { - if (flt == VM_FAULT_MINOR) - ctx->stats.min_flt++; - else - ctx->stats.maj_flt++; - if (ctx->state == SPU_STATE_RUNNABLE) { - if (flt == VM_FAULT_MINOR) - ctx->spu->stats.min_flt++; - else - ctx->spu->stats.maj_flt++; - } - if (ctx->spu) ctx->ops->restart_dma(ctx); } else spufs_handle_dma_error(ctx, ea, SPE_EVENT_SPE_DATA_STORAGE); - spuctx_switch_state(ctx, SPUCTX_UTIL_SYSTEM); return ret; } EXPORT_SYMBOL_GPL(spufs_handle_class1); diff --git a/trunk/arch/powerpc/platforms/cell/spufs/file.c b/trunk/arch/powerpc/platforms/cell/spufs/file.c index c2814ea96af2..b1e7e2f8a2e9 100644 --- a/trunk/arch/powerpc/platforms/cell/spufs/file.c +++ b/trunk/arch/powerpc/platforms/cell/spufs/file.c @@ -28,7 +28,6 @@ #include #include #include -#include #include #include @@ -40,7 +39,6 @@ #define SPUFS_MMAP_4K (PAGE_SIZE == 0x1000) - static int spufs_mem_open(struct inode *inode, struct file *file) { @@ -218,12 +216,12 @@ unsigned long spufs_get_unmapped_area(struct file *file, unsigned long addr, #endif /* CONFIG_SPU_FS_64K_LS */ static const struct file_operations spufs_mem_fops = { - .open = spufs_mem_open, - .release = spufs_mem_release, - .read = spufs_mem_read, - .write = spufs_mem_write, - .llseek = generic_file_llseek, - .mmap = spufs_mem_mmap, + .open = spufs_mem_open, + .release = spufs_mem_release, + .read = spufs_mem_read, + .write = spufs_mem_write, + .llseek = generic_file_llseek, + .mmap = spufs_mem_mmap, #ifdef CONFIG_SPU_FS_64K_LS .get_unmapped_area = spufs_get_unmapped_area, #endif @@ -1499,15 +1497,14 @@ static ssize_t spufs_mfc_write(struct file *file, const char __user *buffer, if (status) ret = status; } + spu_release(ctx); if (ret) - goto out_unlock; + goto out; ctx->tagwait |= 1 << cmd.tag; ret = size; -out_unlock: - spu_release(ctx); out: return ret; } @@ -1518,14 +1515,14 @@ static unsigned int spufs_mfc_poll(struct file *file,poll_table *wait) u32 free_elements, tagstatus; unsigned int mask; - poll_wait(file, &ctx->mfc_wq, wait); - spu_acquire(ctx); ctx->ops->set_mfc_query(ctx, ctx->tagwait, 2); free_elements = ctx->ops->get_mfc_free_elements(ctx); tagstatus = ctx->ops->read_mfc_tagstatus(ctx); spu_release(ctx); + poll_wait(file, &ctx->mfc_wq, wait); + mask = 0; if (free_elements & 0xffff) mask |= POLLOUT | POLLWRNORM; @@ -1800,29 +1797,6 @@ static int spufs_info_open(struct inode *inode, struct file *file) return 0; } -static int spufs_caps_show(struct seq_file *s, void *private) -{ - struct spu_context *ctx = s->private; - - if (!(ctx->flags & SPU_CREATE_NOSCHED)) - seq_puts(s, "sched\n"); - if (!(ctx->flags & SPU_CREATE_ISOLATE)) - seq_puts(s, "step\n"); - return 0; -} - -static int spufs_caps_open(struct inode *inode, struct file *file) -{ - return single_open(file, spufs_caps_show, SPUFS_I(inode)->i_ctx); -} - -static const struct file_operations spufs_caps_fops = { - .open = spufs_caps_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; - static ssize_t __spufs_mbox_info_read(struct spu_context *ctx, char __user *buf, size_t len, loff_t *pos) { @@ -2040,105 +2014,7 @@ static const struct file_operations spufs_proxydma_info_fops = { .read = spufs_proxydma_info_read, }; -static int spufs_show_tid(struct seq_file *s, void *private) -{ - struct spu_context *ctx = s->private; - - seq_printf(s, "%d\n", ctx->tid); - return 0; -} - -static int spufs_tid_open(struct inode *inode, struct file *file) -{ - return single_open(file, spufs_show_tid, SPUFS_I(inode)->i_ctx); -} - -static const struct file_operations spufs_tid_fops = { - .open = spufs_tid_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; - -static const char *ctx_state_names[] = { - "user", "system", "iowait", "loaded" -}; - -static unsigned long long spufs_acct_time(struct spu_context *ctx, - enum spuctx_execution_state state) -{ - unsigned long time = ctx->stats.times[state]; - - if (ctx->stats.execution_state == state) - time += jiffies - ctx->stats.tstamp; - - return jiffies_to_msecs(time); -} - -static unsigned long long spufs_slb_flts(struct spu_context *ctx) -{ - unsigned long long slb_flts = ctx->stats.slb_flt; - - if (ctx->state == SPU_STATE_RUNNABLE) { - slb_flts += (ctx->spu->stats.slb_flt - - ctx->stats.slb_flt_base); - } - - return slb_flts; -} - -static unsigned long long spufs_class2_intrs(struct spu_context *ctx) -{ - unsigned long long class2_intrs = ctx->stats.class2_intr; - - if (ctx->state == SPU_STATE_RUNNABLE) { - class2_intrs += (ctx->spu->stats.class2_intr - - ctx->stats.class2_intr_base); - } - - return class2_intrs; -} - - -static int spufs_show_stat(struct seq_file *s, void *private) -{ - struct spu_context *ctx = s->private; - - spu_acquire(ctx); - seq_printf(s, "%s %llu %llu %llu %llu " - "%llu %llu %llu %llu %llu %llu %llu %llu\n", - ctx_state_names[ctx->stats.execution_state], - spufs_acct_time(ctx, SPUCTX_UTIL_USER), - spufs_acct_time(ctx, SPUCTX_UTIL_SYSTEM), - spufs_acct_time(ctx, SPUCTX_UTIL_IOWAIT), - spufs_acct_time(ctx, SPUCTX_UTIL_LOADED), - ctx->stats.vol_ctx_switch, - ctx->stats.invol_ctx_switch, - spufs_slb_flts(ctx), - ctx->stats.hash_flt, - ctx->stats.min_flt, - ctx->stats.maj_flt, - spufs_class2_intrs(ctx), - ctx->stats.libassist); - spu_release(ctx); - return 0; -} - -static int spufs_stat_open(struct inode *inode, struct file *file) -{ - return single_open(file, spufs_show_stat, SPUFS_I(inode)->i_ctx); -} - -static const struct file_operations spufs_stat_fops = { - .open = spufs_stat_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; - - struct tree_descr spufs_dir_contents[] = { - { "capabilities", &spufs_caps_fops, 0444, }, { "mem", &spufs_mem_fops, 0666, }, { "regs", &spufs_regs_fops, 0666, }, { "mbox", &spufs_mbox_fops, 0444, }, @@ -2170,13 +2046,10 @@ struct tree_descr spufs_dir_contents[] = { { "wbox_info", &spufs_wbox_info_fops, 0444, }, { "dma_info", &spufs_dma_info_fops, 0444, }, { "proxydma_info", &spufs_proxydma_info_fops, 0444, }, - { "tid", &spufs_tid_fops, 0444, }, - { "stat", &spufs_stat_fops, 0444, }, {}, }; struct tree_descr spufs_dir_nosched_contents[] = { - { "capabilities", &spufs_caps_fops, 0444, }, { "mem", &spufs_mem_fops, 0666, }, { "mbox", &spufs_mbox_fops, 0444, }, { "ibox", &spufs_ibox_fops, 0444, }, @@ -2195,8 +2068,6 @@ struct tree_descr spufs_dir_nosched_contents[] = { { "psmap", &spufs_psmap_fops, 0666, }, { "phys-id", &spufs_id_ops, 0666, }, { "object-id", &spufs_object_id_ops, 0666, }, - { "tid", &spufs_tid_fops, 0444, }, - { "stat", &spufs_stat_fops, 0444, }, {}, }; diff --git a/trunk/arch/powerpc/platforms/cell/spufs/inode.c b/trunk/arch/powerpc/platforms/cell/spufs/inode.c index f37460e5bfd2..9807206e0219 100644 --- a/trunk/arch/powerpc/platforms/cell/spufs/inode.c +++ b/trunk/arch/powerpc/platforms/cell/spufs/inode.c @@ -232,6 +232,10 @@ static int spufs_dir_close(struct inode *inode, struct file *file) return dcache_dir_close(inode, file); } +const struct inode_operations spufs_dir_inode_operations = { + .lookup = simple_lookup, +}; + const struct file_operations spufs_context_fops = { .open = dcache_dir_open, .release = spufs_dir_close, @@ -265,7 +269,7 @@ spufs_mkdir(struct inode *dir, struct dentry *dentry, unsigned int flags, goto out_iput; ctx->flags = flags; - inode->i_op = &simple_dir_inode_operations; + inode->i_op = &spufs_dir_inode_operations; inode->i_fop = &simple_dir_operations; if (flags & SPU_CREATE_NOSCHED) ret = spufs_fill_dir(dentry, spufs_dir_nosched_contents, @@ -382,7 +386,7 @@ spufs_mkgang(struct inode *dir, struct dentry *dentry, int mode) if (!gang) goto out_iput; - inode->i_op = &simple_dir_inode_operations; + inode->i_op = &spufs_dir_inode_operations; inode->i_fop = &simple_dir_operations; d_instantiate(dentry, inode); @@ -589,7 +593,7 @@ spufs_create_root(struct super_block *sb, void *data) if (!inode) goto out; - inode->i_op = &simple_dir_inode_operations; + inode->i_op = &spufs_dir_inode_operations; inode->i_fop = &simple_dir_operations; SPUFS_I(inode)->i_ctx = NULL; diff --git a/trunk/arch/powerpc/platforms/cell/spufs/run.c b/trunk/arch/powerpc/platforms/cell/spufs/run.c index 58ae13b7de84..57626600b1a4 100644 --- a/trunk/arch/powerpc/platforms/cell/spufs/run.c +++ b/trunk/arch/powerpc/platforms/cell/spufs/run.c @@ -29,8 +29,7 @@ static inline int spu_stopped(struct spu_context *ctx, u32 * stat) spu = ctx->spu; pte_fault = spu->dsisr & (MFC_DSISR_PTE_NOT_FOUND | MFC_DSISR_ACCESS_DENIED); - return (!(*stat & SPU_STATUS_RUNNING) || pte_fault || spu->class_0_pending) ? - 1 : 0; + return (!(*stat & 0x1) || pte_fault || spu->class_0_pending) ? 1 : 0; } static int spu_setup_isolated(struct spu_context *ctx) @@ -143,11 +142,8 @@ static int spu_run_init(struct spu_context *ctx, u32 * npc) runcntl = SPU_RUNCNTL_RUNNABLE; ctx->ops->runcntl_write(ctx, runcntl); } else { - unsigned long mode = SPU_PRIVCNTL_MODE_NORMAL; + spu_start_tick(ctx); ctx->ops->npc_write(ctx, *npc); - if (test_thread_flag(TIF_SINGLESTEP)) - mode = SPU_PRIVCNTL_MODE_SINGLE_STEP; - out_be64(&ctx->spu->priv2->spu_privcntl_RW, mode); ctx->ops->runcntl_write(ctx, SPU_RUNCNTL_RUNNABLE); } @@ -159,6 +155,7 @@ static int spu_run_fini(struct spu_context *ctx, u32 * npc, { int ret = 0; + spu_stop_tick(ctx); *status = ctx->ops->status_read(ctx); *npc = ctx->ops->npc_read(ctx); spu_release(ctx); @@ -301,22 +298,9 @@ long spufs_run_spu(struct file *file, struct spu_context *ctx, ctx->ops->master_start(ctx); ctx->event_return = 0; - spu_acquire(ctx); - if (ctx->state == SPU_STATE_SAVED) { - __spu_update_sched_info(ctx); - - ret = spu_activate(ctx, 0); - if (ret) { - spu_release(ctx); - goto out; - } - } else { - /* - * We have to update the scheduling priority under active_mutex - * to protect against find_victim(). - */ - spu_update_sched_info(ctx); - } + ret = spu_acquire_runnable(ctx, 0); + if (ret) + return ret; ret = spu_run_init(ctx, npc); if (ret) { @@ -341,20 +325,16 @@ long spufs_run_spu(struct file *file, struct spu_context *ctx, if (unlikely(ctx->state != SPU_STATE_RUNNABLE)) { ret = spu_reacquire_runnable(ctx, npc, &status); - if (ret) + if (ret) { + spu_stop_tick(ctx); goto out2; + } continue; } ret = spu_process_events(ctx); } while (!ret && !(status & (SPU_STATUS_STOPPED_BY_STOP | - SPU_STATUS_STOPPED_BY_HALT | - SPU_STATUS_SINGLE_STEP))); - - if ((status & SPU_STATUS_STOPPED_BY_STOP) && - (((status >> SPU_STOP_STATUS_SHIFT) & 0x3f00) == 0x2100) && - (ctx->state == SPU_STATE_RUNNABLE)) - ctx->stats.libassist++; + SPU_STATUS_STOPPED_BY_HALT))); ctx->ops->master_stop(ctx); ret = spu_run_fini(ctx, npc, &status); @@ -364,15 +344,10 @@ long spufs_run_spu(struct file *file, struct spu_context *ctx, if ((ret == 0) || ((ret == -ERESTARTSYS) && ((status & SPU_STATUS_STOPPED_BY_HALT) || - (status & SPU_STATUS_SINGLE_STEP) || ((status & SPU_STATUS_STOPPED_BY_STOP) && (status >> SPU_STOP_STATUS_SHIFT != 0x2104))))) ret = status; - /* Note: we don't need to force_sig SIGTRAP on single-step - * since we have TIF_SINGLESTEP set, thus the kernel will do - * it upon return from the syscall anyawy - */ if ((status & SPU_STATUS_STOPPED_BY_STOP) && (status >> SPU_STOP_STATUS_SHIFT) == 0x3fff) { force_sig(SIGTRAP, current); diff --git a/trunk/arch/powerpc/platforms/cell/spufs/sched.c b/trunk/arch/powerpc/platforms/cell/spufs/sched.c index e5b4dd1db286..3b831e07f1ed 100644 --- a/trunk/arch/powerpc/platforms/cell/spufs/sched.c +++ b/trunk/arch/powerpc/platforms/cell/spufs/sched.c @@ -35,10 +35,6 @@ #include #include #include -#include -#include -#include -#include #include #include @@ -47,126 +43,54 @@ #include #include "spufs.h" +#define SPU_TIMESLICE (HZ) + struct spu_prio_array { DECLARE_BITMAP(bitmap, MAX_PRIO); struct list_head runq[MAX_PRIO]; spinlock_t runq_lock; struct list_head active_list[MAX_NUMNODES]; struct mutex active_mutex[MAX_NUMNODES]; - int nr_active[MAX_NUMNODES]; - int nr_waiting; }; -static unsigned long spu_avenrun[3]; static struct spu_prio_array *spu_prio; -static struct task_struct *spusched_task; -static struct timer_list spusched_timer; - -/* - * Priority of a normal, non-rt, non-niced'd process (aka nice level 0). - */ -#define NORMAL_PRIO 120 - -/* - * Frequency of the spu scheduler tick. By default we do one SPU scheduler - * tick for every 10 CPU scheduler ticks. - */ -#define SPUSCHED_TICK (10) +static struct workqueue_struct *spu_sched_wq; -/* - * These are the 'tuning knobs' of the scheduler: - * - * Minimum timeslice is 5 msecs (or 1 spu scheduler tick, whichever is - * larger), default timeslice is 100 msecs, maximum timeslice is 800 msecs. - */ -#define MIN_SPU_TIMESLICE max(5 * HZ / (1000 * SPUSCHED_TICK), 1) -#define DEF_SPU_TIMESLICE (100 * HZ / (1000 * SPUSCHED_TICK)) - -#define MAX_USER_PRIO (MAX_PRIO - MAX_RT_PRIO) -#define SCALE_PRIO(x, prio) \ - max(x * (MAX_PRIO - prio) / (MAX_USER_PRIO / 2), MIN_SPU_TIMESLICE) - -/* - * scale user-nice values [ -20 ... 0 ... 19 ] to time slice values: - * [800ms ... 100ms ... 5ms] - * - * The higher a thread's priority, the bigger timeslices - * it gets during one round of execution. But even the lowest - * priority thread gets MIN_TIMESLICE worth of execution time. - */ -void spu_set_timeslice(struct spu_context *ctx) +static inline int node_allowed(int node) { - if (ctx->prio < NORMAL_PRIO) - ctx->time_slice = SCALE_PRIO(DEF_SPU_TIMESLICE * 4, ctx->prio); - else - ctx->time_slice = SCALE_PRIO(DEF_SPU_TIMESLICE, ctx->prio); -} + cpumask_t mask; -/* - * Update scheduling information from the owning thread. - */ -void __spu_update_sched_info(struct spu_context *ctx) -{ - /* - * 32-Bit assignment are atomic on powerpc, and we don't care about - * memory ordering here because retriving the controlling thread is - * per defintion racy. - */ - ctx->tid = current->pid; - - /* - * We do our own priority calculations, so we normally want - * ->static_prio to start with. Unfortunately thies field - * contains junk for threads with a realtime scheduling - * policy so we have to look at ->prio in this case. - */ - if (rt_prio(current->prio)) - ctx->prio = current->prio; - else - ctx->prio = current->static_prio; - ctx->policy = current->policy; - - /* - * A lot of places that don't hold active_mutex poke into - * cpus_allowed, including grab_runnable_context which - * already holds the runq_lock. So abuse runq_lock - * to protect this field aswell. - */ - spin_lock(&spu_prio->runq_lock); - ctx->cpus_allowed = current->cpus_allowed; - spin_unlock(&spu_prio->runq_lock); -} - -void spu_update_sched_info(struct spu_context *ctx) -{ - int node = ctx->spu->node; - - mutex_lock(&spu_prio->active_mutex[node]); - __spu_update_sched_info(ctx); - mutex_unlock(&spu_prio->active_mutex[node]); + if (!nr_cpus_node(node)) + return 0; + mask = node_to_cpumask(node); + if (!cpus_intersects(mask, current->cpus_allowed)) + return 0; + return 1; } -static int __node_allowed(struct spu_context *ctx, int node) +void spu_start_tick(struct spu_context *ctx) { - if (nr_cpus_node(node)) { - cpumask_t mask = node_to_cpumask(node); - - if (cpus_intersects(mask, ctx->cpus_allowed)) - return 1; + if (ctx->policy == SCHED_RR) { + /* + * Make sure the exiting bit is cleared. + */ + clear_bit(SPU_SCHED_EXITING, &ctx->sched_flags); + mb(); + queue_delayed_work(spu_sched_wq, &ctx->sched_work, SPU_TIMESLICE); } - - return 0; } -static int node_allowed(struct spu_context *ctx, int node) +void spu_stop_tick(struct spu_context *ctx) { - int rval; - - spin_lock(&spu_prio->runq_lock); - rval = __node_allowed(ctx, node); - spin_unlock(&spu_prio->runq_lock); - - return rval; + if (ctx->policy == SCHED_RR) { + /* + * While the work can be rearming normally setting this flag + * makes sure it does not rearm itself anymore. + */ + set_bit(SPU_SCHED_EXITING, &ctx->sched_flags); + mb(); + cancel_delayed_work(&ctx->sched_work); + } } /** @@ -175,18 +99,9 @@ static int node_allowed(struct spu_context *ctx, int node) */ static void spu_add_to_active_list(struct spu *spu) { - int node = spu->node; - - mutex_lock(&spu_prio->active_mutex[node]); - spu_prio->nr_active[node]++; - list_add_tail(&spu->list, &spu_prio->active_list[node]); - mutex_unlock(&spu_prio->active_mutex[node]); -} - -static void __spu_remove_from_active_list(struct spu *spu) -{ - list_del_init(&spu->list); - spu_prio->nr_active[spu->node]--; + mutex_lock(&spu_prio->active_mutex[spu->node]); + list_add_tail(&spu->list, &spu_prio->active_list[spu->node]); + mutex_unlock(&spu_prio->active_mutex[spu->node]); } /** @@ -198,7 +113,7 @@ static void spu_remove_from_active_list(struct spu *spu) int node = spu->node; mutex_lock(&spu_prio->active_mutex[node]); - __spu_remove_from_active_list(spu); + list_del_init(&spu->list); mutex_unlock(&spu_prio->active_mutex[node]); } @@ -229,10 +144,6 @@ static void spu_bind_context(struct spu *spu, struct spu_context *ctx) { pr_debug("%s: pid=%d SPU=%d NODE=%d\n", __FUNCTION__, current->pid, spu->number, spu->node); - - ctx->stats.slb_flt_base = spu->stats.slb_flt; - ctx->stats.class2_intr_base = spu->stats.class2_intr; - spu->ctx = ctx; spu->flags = 0; ctx->spu = spu; @@ -250,8 +161,8 @@ static void spu_bind_context(struct spu *spu, struct spu_context *ctx) spu->timestamp = jiffies; spu_cpu_affinity_set(spu, raw_smp_processor_id()); spu_switch_notify(spu, ctx); + spu_add_to_active_list(spu); ctx->state = SPU_STATE_RUNNABLE; - spu_switch_state(spu, SPU_UTIL_SYSTEM); } /** @@ -264,8 +175,7 @@ static void spu_unbind_context(struct spu *spu, struct spu_context *ctx) pr_debug("%s: unbind pid=%d SPU=%d NODE=%d\n", __FUNCTION__, spu->pid, spu->number, spu->node); - spu_switch_state(spu, SPU_UTIL_IDLE); - + spu_remove_from_active_list(spu); spu_switch_notify(spu, NULL); spu_unmap_mappings(ctx); spu_save(&ctx->csa, spu); @@ -282,11 +192,6 @@ static void spu_unbind_context(struct spu *spu, struct spu_context *ctx) ctx->spu = NULL; spu->flags = 0; spu->ctx = NULL; - - ctx->stats.slb_flt += - (spu->stats.slb_flt - ctx->stats.slb_flt_base); - ctx->stats.class2_intr += - (spu->stats.class2_intr - ctx->stats.class2_intr_base); } /** @@ -295,39 +200,20 @@ static void spu_unbind_context(struct spu *spu, struct spu_context *ctx) */ static void __spu_add_to_rq(struct spu_context *ctx) { - /* - * Unfortunately this code path can be called from multiple threads - * on behalf of a single context due to the way the problem state - * mmap support works. - * - * Fortunately we need to wake up all these threads at the same time - * and can simply skip the runqueue addition for every but the first - * thread getting into this codepath. - * - * It's still quite hacky, and long-term we should proxy all other - * threads through the owner thread so that spu_run is in control - * of all the scheduling activity for a given context. - */ - if (list_empty(&ctx->rq)) { - list_add_tail(&ctx->rq, &spu_prio->runq[ctx->prio]); - set_bit(ctx->prio, spu_prio->bitmap); - if (!spu_prio->nr_waiting++) - __mod_timer(&spusched_timer, jiffies + SPUSCHED_TICK); - } + int prio = ctx->prio; + + list_add_tail(&ctx->rq, &spu_prio->runq[prio]); + set_bit(prio, spu_prio->bitmap); } static void __spu_del_from_rq(struct spu_context *ctx) { int prio = ctx->prio; - if (!list_empty(&ctx->rq)) { - if (!--spu_prio->nr_waiting) - del_timer(&spusched_timer); + if (!list_empty(&ctx->rq)) list_del_init(&ctx->rq); - - if (list_empty(&spu_prio->runq[prio])) - clear_bit(prio, spu_prio->bitmap); - } + if (list_empty(&spu_prio->runq[prio])) + clear_bit(prio, spu_prio->bitmap); } static void spu_prio_wait(struct spu_context *ctx) @@ -358,7 +244,7 @@ static struct spu *spu_get_idle(struct spu_context *ctx) for (n = 0; n < MAX_NUMNODES; n++, node++) { node = (node < MAX_NUMNODES) ? node : 0; - if (!node_allowed(ctx, node)) + if (!node_allowed(node)) continue; spu = spu_alloc_node(node); if (spu) @@ -390,15 +276,15 @@ static struct spu *find_victim(struct spu_context *ctx) node = cpu_to_node(raw_smp_processor_id()); for (n = 0; n < MAX_NUMNODES; n++, node++) { node = (node < MAX_NUMNODES) ? node : 0; - if (!node_allowed(ctx, node)) + if (!node_allowed(node)) continue; mutex_lock(&spu_prio->active_mutex[node]); list_for_each_entry(spu, &spu_prio->active_list[node], list) { struct spu_context *tmp = spu->ctx; - if (tmp->prio > ctx->prio && - (!victim || tmp->prio > victim->prio)) + if (tmp->rt_priority < ctx->rt_priority && + (!victim || tmp->rt_priority < victim->rt_priority)) victim = spu->ctx; } mutex_unlock(&spu_prio->active_mutex[node]); @@ -426,10 +312,7 @@ static struct spu *find_victim(struct spu_context *ctx) victim = NULL; goto restart; } - spu_remove_from_active_list(spu); spu_unbind_context(spu, victim); - victim->stats.invol_ctx_switch++; - spu->stats.invol_ctx_switch++; mutex_unlock(&victim->state_mutex); /* * We need to break out of the wait loop in spu_run @@ -455,30 +338,22 @@ static struct spu *find_victim(struct spu_context *ctx) */ int spu_activate(struct spu_context *ctx, unsigned long flags) { - spuctx_switch_state(ctx, SPUCTX_UTIL_SYSTEM); + + if (ctx->spu) + return 0; do { struct spu *spu; - /* - * If there are multiple threads waiting for a single context - * only one actually binds the context while the others will - * only be able to acquire the state_mutex once the context - * already is in runnable state. - */ - if (ctx->spu) - return 0; - spu = spu_get_idle(ctx); /* * If this is a realtime thread we try to get it running by * preempting a lower priority thread. */ - if (!spu && rt_prio(ctx->prio)) + if (!spu && ctx->rt_priority) spu = find_victim(ctx); if (spu) { spu_bind_context(spu, ctx); - spu_add_to_active_list(spu); return 0; } @@ -494,28 +369,23 @@ int spu_activate(struct spu_context *ctx, unsigned long flags) * Remove the highest priority context on the runqueue and return it * to the caller. Returns %NULL if no runnable context was found. */ -static struct spu_context *grab_runnable_context(int prio, int node) +static struct spu_context *grab_runnable_context(int prio) { - struct spu_context *ctx; + struct spu_context *ctx = NULL; int best; spin_lock(&spu_prio->runq_lock); best = sched_find_first_bit(spu_prio->bitmap); - while (best < prio) { + if (best < prio) { struct list_head *rq = &spu_prio->runq[best]; - list_for_each_entry(ctx, rq, rq) { - /* XXX(hch): check for affinity here aswell */ - if (__node_allowed(ctx, node)) { - __spu_del_from_rq(ctx); - goto found; - } - } - best++; + BUG_ON(list_empty(rq)); + + ctx = list_entry(rq->next, struct spu_context, rq); + __spu_del_from_rq(ctx); } - ctx = NULL; - found: spin_unlock(&spu_prio->runq_lock); + return ctx; } @@ -525,12 +395,9 @@ static int __spu_deactivate(struct spu_context *ctx, int force, int max_prio) struct spu_context *new = NULL; if (spu) { - new = grab_runnable_context(max_prio, spu->node); + new = grab_runnable_context(max_prio); if (new || force) { - spu_remove_from_active_list(spu); spu_unbind_context(spu, ctx); - ctx->stats.vol_ctx_switch++; - spu->stats.vol_ctx_switch++; spu_free(spu); if (new) wake_up(&new->stop_wq); @@ -550,17 +417,7 @@ static int __spu_deactivate(struct spu_context *ctx, int force, int max_prio) */ void spu_deactivate(struct spu_context *ctx) { - /* - * We must never reach this for a nosched context, - * but handle the case gracefull instead of panicing. - */ - if (ctx->flags & SPU_CREATE_NOSCHED) { - WARN_ON(1); - return; - } - __spu_deactivate(ctx, 1, MAX_PRIO); - spuctx_switch_state(ctx, SPUCTX_UTIL_USER); } /** @@ -575,178 +432,56 @@ void spu_yield(struct spu_context *ctx) { if (!(ctx->flags & SPU_CREATE_NOSCHED)) { mutex_lock(&ctx->state_mutex); - if (__spu_deactivate(ctx, 0, MAX_PRIO)) - spuctx_switch_state(ctx, SPUCTX_UTIL_USER); - else { - spuctx_switch_state(ctx, SPUCTX_UTIL_LOADED); - spu_switch_state(ctx->spu, SPU_UTIL_USER); - } + __spu_deactivate(ctx, 0, MAX_PRIO); mutex_unlock(&ctx->state_mutex); } } -static void spusched_tick(struct spu_context *ctx) +void spu_sched_tick(struct work_struct *work) { - if (ctx->flags & SPU_CREATE_NOSCHED) - return; - if (ctx->policy == SCHED_FIFO) - return; - - if (--ctx->time_slice) - return; + struct spu_context *ctx = + container_of(work, struct spu_context, sched_work.work); + int preempted; /* - * Unfortunately active_mutex ranks outside of state_mutex, so - * we have to trylock here. If we fail give the context another - * tick and try again. + * If this context is being stopped avoid rescheduling from the + * scheduler tick because we would block on the state_mutex. + * The caller will yield the spu later on anyway. */ - if (mutex_trylock(&ctx->state_mutex)) { - struct spu *spu = ctx->spu; - struct spu_context *new; + if (test_bit(SPU_SCHED_EXITING, &ctx->sched_flags)) + return; - new = grab_runnable_context(ctx->prio + 1, spu->node); - if (new) { + mutex_lock(&ctx->state_mutex); + preempted = __spu_deactivate(ctx, 0, ctx->prio + 1); + mutex_unlock(&ctx->state_mutex); - __spu_remove_from_active_list(spu); - spu_unbind_context(spu, ctx); - ctx->stats.invol_ctx_switch++; - spu->stats.invol_ctx_switch++; - spu_free(spu); - wake_up(&new->stop_wq); - /* - * We need to break out of the wait loop in - * spu_run manually to ensure this context - * gets put on the runqueue again ASAP. - */ - wake_up(&ctx->stop_wq); - } - spu_set_timeslice(ctx); - mutex_unlock(&ctx->state_mutex); + if (preempted) { + /* + * We need to break out of the wait loop in spu_run manually + * to ensure this context gets put on the runqueue again + * ASAP. + */ + wake_up(&ctx->stop_wq); } else { - ctx->time_slice++; + spu_start_tick(ctx); } } -/** - * count_active_contexts - count nr of active tasks - * - * Return the number of tasks currently running or waiting to run. - * - * Note that we don't take runq_lock / active_mutex here. Reading - * a single 32bit value is atomic on powerpc, and we don't care - * about memory ordering issues here. - */ -static unsigned long count_active_contexts(void) -{ - int nr_active = 0, node; - - for (node = 0; node < MAX_NUMNODES; node++) - nr_active += spu_prio->nr_active[node]; - nr_active += spu_prio->nr_waiting; - - return nr_active; -} - -/** - * spu_calc_load - given tick count, update the avenrun load estimates. - * @tick: tick count - * - * No locking against reading these values from userspace, as for - * the CPU loadavg code. - */ -static void spu_calc_load(unsigned long ticks) -{ - unsigned long active_tasks; /* fixed-point */ - static int count = LOAD_FREQ; - - count -= ticks; - - if (unlikely(count < 0)) { - active_tasks = count_active_contexts() * FIXED_1; - do { - CALC_LOAD(spu_avenrun[0], EXP_1, active_tasks); - CALC_LOAD(spu_avenrun[1], EXP_5, active_tasks); - CALC_LOAD(spu_avenrun[2], EXP_15, active_tasks); - count += LOAD_FREQ; - } while (count < 0); - } -} - -static void spusched_wake(unsigned long data) -{ - mod_timer(&spusched_timer, jiffies + SPUSCHED_TICK); - wake_up_process(spusched_task); - spu_calc_load(SPUSCHED_TICK); -} - -static int spusched_thread(void *unused) -{ - struct spu *spu, *next; - int node; - - while (!kthread_should_stop()) { - set_current_state(TASK_INTERRUPTIBLE); - schedule(); - for (node = 0; node < MAX_NUMNODES; node++) { - mutex_lock(&spu_prio->active_mutex[node]); - list_for_each_entry_safe(spu, next, - &spu_prio->active_list[node], - list) - spusched_tick(spu->ctx); - mutex_unlock(&spu_prio->active_mutex[node]); - } - } - - return 0; -} - -#define LOAD_INT(x) ((x) >> FSHIFT) -#define LOAD_FRAC(x) LOAD_INT(((x) & (FIXED_1-1)) * 100) - -static int show_spu_loadavg(struct seq_file *s, void *private) -{ - int a, b, c; - - a = spu_avenrun[0] + (FIXED_1/200); - b = spu_avenrun[1] + (FIXED_1/200); - c = spu_avenrun[2] + (FIXED_1/200); - - /* - * Note that last_pid doesn't really make much sense for the - * SPU loadavg (it even seems very odd on the CPU side..), - * but we include it here to have a 100% compatible interface. - */ - seq_printf(s, "%d.%02d %d.%02d %d.%02d %ld/%d %d\n", - LOAD_INT(a), LOAD_FRAC(a), - LOAD_INT(b), LOAD_FRAC(b), - LOAD_INT(c), LOAD_FRAC(c), - count_active_contexts(), - atomic_read(&nr_spu_contexts), - current->nsproxy->pid_ns->last_pid); - return 0; -} - -static int spu_loadavg_open(struct inode *inode, struct file *file) -{ - return single_open(file, show_spu_loadavg, NULL); -} - -static const struct file_operations spu_loadavg_fops = { - .open = spu_loadavg_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; - int __init spu_sched_init(void) { - struct proc_dir_entry *entry; - int err = -ENOMEM, i; + int i; - spu_prio = kzalloc(sizeof(struct spu_prio_array), GFP_KERNEL); - if (!spu_prio) - goto out; + spu_sched_wq = create_singlethread_workqueue("spusched"); + if (!spu_sched_wq) + return 1; + spu_prio = kzalloc(sizeof(struct spu_prio_array), GFP_KERNEL); + if (!spu_prio) { + printk(KERN_WARNING "%s: Unable to allocate priority queue.\n", + __FUNCTION__); + destroy_workqueue(spu_sched_wq); + return 1; + } for (i = 0; i < MAX_PRIO; i++) { INIT_LIST_HEAD(&spu_prio->runq[i]); __clear_bit(i, spu_prio->bitmap); @@ -757,30 +492,7 @@ int __init spu_sched_init(void) INIT_LIST_HEAD(&spu_prio->active_list[i]); } spin_lock_init(&spu_prio->runq_lock); - - setup_timer(&spusched_timer, spusched_wake, 0); - - spusched_task = kthread_run(spusched_thread, NULL, "spusched"); - if (IS_ERR(spusched_task)) { - err = PTR_ERR(spusched_task); - goto out_free_spu_prio; - } - - entry = create_proc_entry("spu_loadavg", 0, NULL); - if (!entry) - goto out_stop_kthread; - entry->proc_fops = &spu_loadavg_fops; - - pr_debug("spusched: tick: %d, min ticks: %d, default ticks: %d\n", - SPUSCHED_TICK, MIN_SPU_TIMESLICE, DEF_SPU_TIMESLICE); return 0; - - out_stop_kthread: - kthread_stop(spusched_task); - out_free_spu_prio: - kfree(spu_prio); - out: - return err; } void __exit spu_sched_exit(void) @@ -788,11 +500,6 @@ void __exit spu_sched_exit(void) struct spu *spu, *tmp; int node; - remove_proc_entry("spu_loadavg", NULL); - - del_timer_sync(&spusched_timer); - kthread_stop(spusched_task); - for (node = 0; node < MAX_NUMNODES; node++) { mutex_lock(&spu_prio->active_mutex[node]); list_for_each_entry_safe(spu, tmp, &spu_prio->active_list[node], @@ -803,4 +510,5 @@ void __exit spu_sched_exit(void) mutex_unlock(&spu_prio->active_mutex[node]); } kfree(spu_prio); + destroy_workqueue(spu_sched_wq); } diff --git a/trunk/arch/powerpc/platforms/cell/spufs/spu_restore.c b/trunk/arch/powerpc/platforms/cell/spufs/spu_restore.c index 4e19ed7a0756..0bf723dcd677 100644 --- a/trunk/arch/powerpc/platforms/cell/spufs/spu_restore.c +++ b/trunk/arch/powerpc/platforms/cell/spufs/spu_restore.c @@ -296,7 +296,7 @@ static inline void restore_complete(void) * This code deviates from the documented sequence in the * following aspects: * - * 1. The EA for LSCSA is passed from PPE in the + * 1. The EA for LSCSA is passed from PPE in the * signal notification channels. * 2. The register spill area is pulled by SPU * into LS, rather than pushed by PPE. diff --git a/trunk/arch/powerpc/platforms/cell/spufs/spu_save.c b/trunk/arch/powerpc/platforms/cell/spufs/spu_save.c index ae95cc1701e9..196033b8a579 100644 --- a/trunk/arch/powerpc/platforms/cell/spufs/spu_save.c +++ b/trunk/arch/powerpc/platforms/cell/spufs/spu_save.c @@ -44,7 +44,7 @@ static inline void save_event_mask(void) * Read the SPU_RdEventMsk channel and save to the LSCSA. */ offset = LSCSA_QW_OFFSET(event_mask); - regs_spill[offset].slot[0] = spu_readch(SPU_RdEventMask); + regs_spill[offset].slot[0] = spu_readch(SPU_RdEventStatMask); } static inline void save_tag_mask(void) diff --git a/trunk/arch/powerpc/platforms/cell/spufs/spufs.h b/trunk/arch/powerpc/platforms/cell/spufs/spufs.h index 08b3530288ac..47617e8014a5 100644 --- a/trunk/arch/powerpc/platforms/cell/spufs/spufs.h +++ b/trunk/arch/powerpc/platforms/cell/spufs/spufs.h @@ -26,7 +26,6 @@ #include #include #include -#include #include #include @@ -40,17 +39,9 @@ enum { struct spu_context_ops; struct spu_gang; -/* - * This is the state for spu utilization reporting to userspace. - * Because this state is visible to userspace it must never change and needs - * to be kept strictly separate from any internal state kept by the kernel. - */ -enum spuctx_execution_state { - SPUCTX_UTIL_USER = 0, - SPUCTX_UTIL_SYSTEM, - SPUCTX_UTIL_IOWAIT, - SPUCTX_UTIL_LOADED, - SPUCTX_UTIL_MAX +/* ctx->sched_flags */ +enum { + SPU_SCHED_EXITING = 0, }; struct spu_context { @@ -90,34 +81,13 @@ struct spu_context { struct list_head gang_list; struct spu_gang *gang; - /* owner thread */ - pid_t tid; - /* scheduler fields */ - struct list_head rq; - unsigned int time_slice; + struct list_head rq; + struct delayed_work sched_work; unsigned long sched_flags; - cpumask_t cpus_allowed; + unsigned long rt_priority; int policy; int prio; - - /* statistics */ - struct { - /* updates protected by ctx->state_mutex */ - enum spuctx_execution_state execution_state; - unsigned long tstamp; /* time of last ctx switch */ - unsigned long times[SPUCTX_UTIL_MAX]; - unsigned long long vol_ctx_switch; - unsigned long long invol_ctx_switch; - unsigned long long min_flt; - unsigned long long maj_flt; - unsigned long long hash_flt; - unsigned long long slb_flt; - unsigned long long slb_flt_base; /* # at last ctx switch */ - unsigned long long class2_intr; - unsigned long long class2_intr_base; /* # at last ctx switch */ - unsigned long long libassist; - } stats; }; struct spu_gang { @@ -207,7 +177,6 @@ void spu_gang_add_ctx(struct spu_gang *gang, struct spu_context *ctx); int spufs_handle_class1(struct spu_context *ctx); /* context management */ -extern atomic_t nr_spu_contexts; static inline void spu_acquire(struct spu_context *ctx) { mutex_lock(&ctx->state_mutex); @@ -231,9 +200,9 @@ void spu_acquire_saved(struct spu_context *ctx); int spu_activate(struct spu_context *ctx, unsigned long flags); void spu_deactivate(struct spu_context *ctx); void spu_yield(struct spu_context *ctx); -void spu_set_timeslice(struct spu_context *ctx); -void spu_update_sched_info(struct spu_context *ctx); -void __spu_update_sched_info(struct spu_context *ctx); +void spu_start_tick(struct spu_context *ctx); +void spu_stop_tick(struct spu_context *ctx); +void spu_sched_tick(struct work_struct *work); int __init spu_sched_init(void); void __exit spu_sched_exit(void); @@ -241,7 +210,7 @@ extern char *isolated_loader; /* * spufs_wait - * Same as wait_event_interruptible(), except that here + * Same as wait_event_interruptible(), except that here * we need to call spu_release(ctx) before sleeping, and * then spu_acquire(ctx) when awoken. */ @@ -287,37 +256,4 @@ struct spufs_coredump_reader { extern struct spufs_coredump_reader spufs_coredump_read[]; extern int spufs_coredump_num_notes; -/* - * This function is a little bit too large for an inline, but - * as fault.c is built into the kernel we can't move it out of - * line. - */ -static inline void spuctx_switch_state(struct spu_context *ctx, - enum spuctx_execution_state new_state) -{ - WARN_ON(!mutex_is_locked(&ctx->state_mutex)); - - if (ctx->stats.execution_state != new_state) { - unsigned long curtime = jiffies; - - ctx->stats.times[ctx->stats.execution_state] += - curtime - ctx->stats.tstamp; - ctx->stats.tstamp = curtime; - ctx->stats.execution_state = new_state; - } -} - -static inline void spu_switch_state(struct spu *spu, - enum spuctx_execution_state new_state) -{ - if (spu->stats.utilization_state != new_state) { - unsigned long curtime = jiffies; - - spu->stats.times[spu->stats.utilization_state] += - curtime - spu->stats.tstamp; - spu->stats.tstamp = curtime; - spu->stats.utilization_state = new_state; - } -} - #endif diff --git a/trunk/arch/powerpc/platforms/cell/spufs/switch.c b/trunk/arch/powerpc/platforms/cell/spufs/switch.c index 9c506ba08cdc..71a0b41adb8c 100644 --- a/trunk/arch/powerpc/platforms/cell/spufs/switch.c +++ b/trunk/arch/powerpc/platforms/cell/spufs/switch.c @@ -70,7 +70,7 @@ } #endif /* debug */ -#define POLL_WHILE_FALSE(_c) POLL_WHILE_TRUE(!(_c)) +#define POLL_WHILE_FALSE(_c) POLL_WHILE_TRUE(!(_c)) static inline void acquire_spu_lock(struct spu *spu) { @@ -387,19 +387,6 @@ static inline void save_ppu_querytype(struct spu_state *csa, struct spu *spu) csa->prob.dma_querytype_RW = in_be32(&prob->dma_querytype_RW); } -static inline void save_ppu_tagstatus(struct spu_state *csa, struct spu *spu) -{ - struct spu_problem __iomem *prob = spu->problem; - - /* Save the Prxy_TagStatus register in the CSA. - * - * It is unnecessary to restore dma_tagstatus_R, however, - * dma_tagstatus_R in the CSA is accessed via backing_ops, so - * we must save it. - */ - csa->prob.dma_tagstatus_R = in_be32(&prob->dma_tagstatus_R); -} - static inline void save_mfc_csr_tsq(struct spu_state *csa, struct spu *spu) { struct spu_priv2 __iomem *priv2 = spu->priv2; @@ -1825,7 +1812,6 @@ static void save_csa(struct spu_state *prev, struct spu *spu) save_mfc_queues(prev, spu); /* Step 19. */ save_ppu_querymask(prev, spu); /* Step 20. */ save_ppu_querytype(prev, spu); /* Step 21. */ - save_ppu_tagstatus(prev, spu); /* NEW. */ save_mfc_csr_tsq(prev, spu); /* Step 22. */ save_mfc_csr_cmd(prev, spu); /* Step 23. */ save_mfc_csr_ato(prev, spu); /* Step 24. */ @@ -1944,7 +1930,7 @@ static void harvest(struct spu_state *prev, struct spu *spu) reset_spu_privcntl(prev, spu); /* Step 16. */ reset_spu_lslr(prev, spu); /* Step 17. */ setup_mfc_sr1(prev, spu); /* Step 18. */ - spu_invalidate_slbs(spu); /* Step 19. */ + spu_invalidate_slbs(spu); /* Step 19. */ reset_ch_part1(prev, spu); /* Step 20. */ reset_ch_part2(prev, spu); /* Step 21. */ enable_interrupts(prev, spu); /* Step 22. */ diff --git a/trunk/arch/powerpc/platforms/chrp/Kconfig b/trunk/arch/powerpc/platforms/chrp/Kconfig index 22b4b4e3b6f0..d2c690531963 100644 --- a/trunk/arch/powerpc/platforms/chrp/Kconfig +++ b/trunk/arch/powerpc/platforms/chrp/Kconfig @@ -8,5 +8,4 @@ config PPC_CHRP select PPC_MPC106 select PPC_UDBG_16550 select PPC_NATIVE - select PCI default y diff --git a/trunk/arch/powerpc/platforms/chrp/Makefile b/trunk/arch/powerpc/platforms/chrp/Makefile index 4b3bfadc70fa..902feb1ac431 100644 --- a/trunk/arch/powerpc/platforms/chrp/Makefile +++ b/trunk/arch/powerpc/platforms/chrp/Makefile @@ -1,3 +1,4 @@ -obj-y += setup.o time.o pegasos_eth.o pci.o +obj-y += setup.o time.o pegasos_eth.o +obj-$(CONFIG_PCI) += pci.o obj-$(CONFIG_SMP) += smp.o obj-$(CONFIG_NVRAM) += nvram.o diff --git a/trunk/arch/powerpc/platforms/chrp/pci.c b/trunk/arch/powerpc/platforms/chrp/pci.c index 3690624e49d4..d32fedc991d3 100644 --- a/trunk/arch/powerpc/platforms/chrp/pci.c +++ b/trunk/arch/powerpc/platforms/chrp/pci.c @@ -99,7 +99,7 @@ int rtas_read_config(struct pci_bus *bus, unsigned int devfn, int offset, struct pci_controller *hose = bus->sysdata; unsigned long addr = (offset & 0xff) | ((devfn & 0xff) << 8) | (((bus->number - hose->first_busno) & 0xff) << 16) - | (hose->global_number << 24); + | (hose->index << 24); int ret = -1; int rval; @@ -114,7 +114,7 @@ int rtas_write_config(struct pci_bus *bus, unsigned int devfn, int offset, struct pci_controller *hose = bus->sysdata; unsigned long addr = (offset & 0xff) | ((devfn & 0xff) << 8) | (((bus->number - hose->first_busno) & 0xff) << 16) - | (hose->global_number << 24); + | (hose->index << 24); int rval; rval = rtas_call(rtas_token("write-pci-config"), 3, 1, NULL, @@ -254,12 +254,13 @@ chrp_find_bridges(void) printk(" at %llx", (unsigned long long)r.start); printk("\n"); - hose = pcibios_alloc_controller(dev); + hose = pcibios_alloc_controller(); if (!hose) { printk("Can't allocate PCI controller structure for %s\n", dev->full_name); continue; } + hose->arch_data = dev; hose->first_busno = bus_range[0]; hose->last_busno = bus_range[1]; diff --git a/trunk/arch/powerpc/platforms/embedded6xx/Kconfig b/trunk/arch/powerpc/platforms/embedded6xx/Kconfig index bec772674e40..f2d26268ca6f 100644 --- a/trunk/arch/powerpc/platforms/embedded6xx/Kconfig +++ b/trunk/arch/powerpc/platforms/embedded6xx/Kconfig @@ -28,7 +28,6 @@ config PPC_HOLLY bool "PPC750GX/CL with TSI10x bridge (Hickory/Holly)" select TSI108_BRIDGE select PPC_UDBG_16550 - select WANT_DEVICE_TREE help Select PPC_HOLLY if configuring for an IBM 750GX/CL Eval Board with TSI108/9 bridge (Hickory/Holly) @@ -45,7 +44,6 @@ endchoice config TSI108_BRIDGE bool depends on MPC7448HPC2 || PPC_HOLLY - select PCI select MPIC select MPIC_WEIRD default y diff --git a/trunk/arch/powerpc/platforms/embedded6xx/holly.c b/trunk/arch/powerpc/platforms/embedded6xx/holly.c index 6292e36dc577..3a0b4a01401c 100644 --- a/trunk/arch/powerpc/platforms/embedded6xx/holly.c +++ b/trunk/arch/powerpc/platforms/embedded6xx/holly.c @@ -45,7 +45,7 @@ #define HOLLY_PCI_CFG_PHYS 0x7c000000 -int holly_exclude_device(struct pci_controller *hose, u_char bus, u_char devfn) +int holly_exclude_device(u_char bus, u_char devfn) { if (bus == 0 && PCI_SLOT(devfn) == 0) return PCIBIOS_DEVICE_NOT_FOUND; diff --git a/trunk/arch/powerpc/platforms/embedded6xx/linkstation.c b/trunk/arch/powerpc/platforms/embedded6xx/linkstation.c index f4d0a7a603f5..b412f006a9c5 100644 --- a/trunk/arch/powerpc/platforms/embedded6xx/linkstation.c +++ b/trunk/arch/powerpc/platforms/embedded6xx/linkstation.c @@ -54,9 +54,8 @@ static struct mtd_partition linkstation_physmap_partitions[] = { }, }; -static int __init linkstation_add_bridge(struct device_node *dev) +static int __init add_bridge(struct device_node *dev) { -#ifdef CONFIG_PCI int len; struct pci_controller *hose; const int *bus_range; @@ -68,17 +67,18 @@ static int __init linkstation_add_bridge(struct device_node *dev) printk(KERN_WARNING "Can't get bus-range for %s, assume" " bus 0\n", dev->full_name); - hose = pcibios_alloc_controller(dev); + hose = pcibios_alloc_controller(); if (hose == NULL) return -ENOMEM; hose->first_busno = bus_range ? bus_range[0] : 0; hose->last_busno = bus_range ? bus_range[1] : 0xff; + hose->arch_data = dev; setup_indirect_pci(hose, 0xfec00000, 0xfee00000); /* Interpret the "ranges" property */ /* This also maps the I/O region and sets isa_io/mem_base */ pci_process_bridge_OF_ranges(hose, dev, 1); -#endif + return 0; } @@ -92,7 +92,7 @@ static void __init linkstation_setup_arch(void) /* Lookup PCI host bridges */ for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;) - linkstation_add_bridge(np); + add_bridge(np); printk(KERN_INFO "BUFFALO Network Attached Storage Series\n"); printk(KERN_INFO "(C) 2002-2005 BUFFALO INC.\n"); diff --git a/trunk/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c b/trunk/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c index 1e3cc69487b5..4542e0c837c0 100644 --- a/trunk/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c +++ b/trunk/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c @@ -54,10 +54,15 @@ #define MPC7448HPC2_PCI_CFG_PHYS 0xfb000000 +#ifndef CONFIG_PCI +isa_io_base = MPC7448_HPC2_ISA_IO_BASE; +isa_mem_base = MPC7448_HPC2_ISA_MEM_BASE; +pci_dram_offset = MPC7448_HPC2_PCI_MEM_OFFSET; +#endif + extern void _nmask_and_or_msr(unsigned long nmask, unsigned long or_val); -int mpc7448_hpc2_exclude_device(struct pci_controller *hose, - u_char bus, u_char devfn) +int mpc7448_hpc2_exclude_device(u_char bus, u_char devfn) { if (bus == 0 && PCI_SLOT(devfn) == 0) return PCIBIOS_DEVICE_NOT_FOUND; diff --git a/trunk/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.h b/trunk/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.h index f7e0e0c7f8d8..a543a5242e34 100644 --- a/trunk/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.h +++ b/trunk/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.h @@ -18,4 +18,9 @@ #include +/* Base Addresses for the PCI bus + */ +#define MPC7448_HPC2_PCI_MEM_OFFSET (0x00000000) +#define MPC7448_HPC2_ISA_IO_BASE (0x00000000) +#define MPC7448_HPC2_ISA_MEM_BASE (0x00000000) #endif /* __PPC_PLATFORMS_MPC7448_HPC2_H */ diff --git a/trunk/arch/powerpc/platforms/iseries/call_hpt.h b/trunk/arch/powerpc/platforms/iseries/call_hpt.h index 8d95fe4b554e..a843b0f87b72 100644 --- a/trunk/arch/powerpc/platforms/iseries/call_hpt.h +++ b/trunk/arch/powerpc/platforms/iseries/call_hpt.h @@ -76,25 +76,24 @@ static inline u64 HvCallHpt_invalidateSetSwBitsGet(u32 hpteIndex, u8 bitson, return compressedStatus; } -static inline u64 HvCallHpt_findValid(struct hash_pte *hpte, u64 vpn) +static inline u64 HvCallHpt_findValid(hpte_t *hpte, u64 vpn) { return HvCall3Ret16(HvCallHptFindValid, hpte, vpn, 0, 0); } -static inline u64 HvCallHpt_findNextValid(struct hash_pte *hpte, u32 hpteIndex, +static inline u64 HvCallHpt_findNextValid(hpte_t *hpte, u32 hpteIndex, u8 bitson, u8 bitsoff) { return HvCall3Ret16(HvCallHptFindNextValid, hpte, hpteIndex, bitson, bitsoff); } -static inline void HvCallHpt_get(struct hash_pte *hpte, u32 hpteIndex) +static inline void HvCallHpt_get(hpte_t *hpte, u32 hpteIndex) { HvCall2Ret16(HvCallHptGet, hpte, hpteIndex, 0); } -static inline void HvCallHpt_addValidate(u32 hpteIndex, u32 hBit, - struct hash_pte *hpte) +static inline void HvCallHpt_addValidate(u32 hpteIndex, u32 hBit, hpte_t *hpte) { HvCall4(HvCallHptAddValidate, hpteIndex, hBit, hpte->v, hpte->r); } diff --git a/trunk/arch/powerpc/platforms/iseries/htab.c b/trunk/arch/powerpc/platforms/iseries/htab.c index b4e2c7a038e1..ed44dfceaa45 100644 --- a/trunk/arch/powerpc/platforms/iseries/htab.c +++ b/trunk/arch/powerpc/platforms/iseries/htab.c @@ -44,7 +44,7 @@ long iSeries_hpte_insert(unsigned long hpte_group, unsigned long va, unsigned long vflags, int psize) { long slot; - struct hash_pte lhpte; + hpte_t lhpte; int secondary = 0; BUG_ON(psize != MMU_PAGE_4K); @@ -99,7 +99,7 @@ long iSeries_hpte_insert(unsigned long hpte_group, unsigned long va, static unsigned long iSeries_hpte_getword0(unsigned long slot) { - struct hash_pte hpte; + hpte_t hpte; HvCallHpt_get(&hpte, slot); return hpte.v; @@ -144,7 +144,7 @@ static long iSeries_hpte_remove(unsigned long hpte_group) static long iSeries_hpte_updatepp(unsigned long slot, unsigned long newpp, unsigned long va, int psize, int local) { - struct hash_pte hpte; + hpte_t hpte; unsigned long want_v; iSeries_hlock(slot); @@ -176,7 +176,7 @@ static long iSeries_hpte_updatepp(unsigned long slot, unsigned long newpp, */ static long iSeries_hpte_find(unsigned long vpn) { - struct hash_pte hpte; + hpte_t hpte; long slot; /* diff --git a/trunk/arch/powerpc/platforms/iseries/pci.c b/trunk/arch/powerpc/platforms/iseries/pci.c index da87162000f0..9c974227155e 100644 --- a/trunk/arch/powerpc/platforms/iseries/pci.c +++ b/trunk/arch/powerpc/platforms/iseries/pci.c @@ -742,11 +742,6 @@ void __init iSeries_pcibios_init(void) /* Install IO hooks */ ppc_pci_io = iseries_pci_io; - /* iSeries has no IO space in the common sense, it needs to set - * the IO base to 0 - */ - pci_io_base = 0; - if (root == NULL) { printk(KERN_CRIT "iSeries_pcibios_init: can't find root " "of device tree\n"); @@ -768,7 +763,7 @@ void __init iSeries_pcibios_init(void) if (phb == NULL) continue; - phb->pci_mem_offset = bus; + phb->pci_mem_offset = phb->local_number = bus; phb->first_busno = bus; phb->last_busno = bus; phb->ops = &iSeries_pci_ops; diff --git a/trunk/arch/powerpc/platforms/iseries/setup.c b/trunk/arch/powerpc/platforms/iseries/setup.c index 13a8b1908ded..7f5dcee814d4 100644 --- a/trunk/arch/powerpc/platforms/iseries/setup.c +++ b/trunk/arch/powerpc/platforms/iseries/setup.c @@ -79,6 +79,8 @@ extern void iSeries_pci_final_fixup(void); static void iSeries_pci_final_fixup(void) { } #endif +extern unsigned long iSeries_recal_tb; +extern unsigned long iSeries_recal_titan; struct MemoryBlock { unsigned long absStart; @@ -290,8 +292,8 @@ static void __init iSeries_init_early(void) { DBG(" -> iSeries_init_early()\n"); - /* Snapshot the timebase, for use in later recalibration */ - iSeries_time_init_early(); + iSeries_recal_tb = get_tb(); + iSeries_recal_titan = HvCallXm_loadTod(); /* * Initialize the DMA/TCE management diff --git a/trunk/arch/powerpc/platforms/maple/pci.c b/trunk/arch/powerpc/platforms/maple/pci.c index fceaae40fe70..7aaa5bbc9363 100644 --- a/trunk/arch/powerpc/platforms/maple/pci.c +++ b/trunk/arch/powerpc/platforms/maple/pci.c @@ -444,7 +444,7 @@ static void __init setup_u3_ht(struct pci_controller* hose) u3_ht = hose; } -static int __init maple_add_bridge(struct device_node *dev) +static int __init add_bridge(struct device_node *dev) { int len; struct pci_controller *hose; @@ -519,6 +519,23 @@ void __devinit maple_pci_irq_fixup(struct pci_dev *dev) DBG(" <- maple_pci_irq_fixup\n"); } +static void __init maple_fixup_phb_resources(void) +{ + struct pci_controller *hose, *tmp; + + list_for_each_entry_safe(hose, tmp, &hose_list, list_node) { + unsigned long offset = (unsigned long)hose->io_base_virt - pci_io_base; + + hose->io_resource.start += offset; + hose->io_resource.end += offset; + + printk(KERN_INFO "PCI Host %d, io start: %llx; io end: %llx\n", + hose->global_number, + (unsigned long long)hose->io_resource.start, + (unsigned long long)hose->io_resource.end); + } +} + void __init maple_pci_init(void) { struct device_node *np, *root; @@ -541,7 +558,7 @@ void __init maple_pci_init(void) continue; if ((of_device_is_compatible(np, "u4-pcie") || of_device_is_compatible(np, "u3-agp")) && - maple_add_bridge(np) == 0) + add_bridge(np) == 0) of_node_get(np); if (of_device_is_compatible(np, "u3-ht")) { @@ -553,9 +570,27 @@ void __init maple_pci_init(void) /* Now setup the HyperTransport host if we found any */ - if (ht && maple_add_bridge(ht) != 0) + if (ht && add_bridge(ht) != 0) of_node_put(ht); + /* + * We need to call pci_setup_phb_io for the HT bridge first + * so it gets the I/O port numbers starting at 0, and we + * need to call it for the AGP bridge after that so it gets + * small positive I/O port numbers. + */ + if (u3_ht) + pci_setup_phb_io(u3_ht, 1); + if (u3_agp) + pci_setup_phb_io(u3_agp, 0); + if (u4_pcie) + pci_setup_phb_io(u4_pcie, 0); + + /* Fixup the IO resources on our host bridges as the common code + * does it only for childs of the host bridges + */ + maple_fixup_phb_resources(); + /* Setup the linkage between OF nodes and PHBs */ pci_devs_phb_init(); diff --git a/trunk/arch/powerpc/platforms/pasemi/Kconfig b/trunk/arch/powerpc/platforms/pasemi/Kconfig index 95cd90fd81c7..7c5076e38ea1 100644 --- a/trunk/arch/powerpc/platforms/pasemi/Kconfig +++ b/trunk/arch/powerpc/platforms/pasemi/Kconfig @@ -25,13 +25,4 @@ config PPC_PASEMI_MDIO help Driver for MDIO via GPIO on PWRficient platforms -config ELECTRA_IDE - tristate "Electra IDE driver" - default y - depends on PPC_PASEMI && ATA - select PATA_PLATFORM - help - This includes driver support for the Electra on-board IDE - interface. - endmenu diff --git a/trunk/arch/powerpc/platforms/pasemi/Makefile b/trunk/arch/powerpc/platforms/pasemi/Makefile index f47fcac7e581..2cd2a4f26a48 100644 --- a/trunk/arch/powerpc/platforms/pasemi/Makefile +++ b/trunk/arch/powerpc/platforms/pasemi/Makefile @@ -1,4 +1,3 @@ obj-y += setup.o pci.o time.o idle.o powersave.o iommu.o obj-$(CONFIG_PPC_PASEMI_MDIO) += gpio_mdio.o -obj-$(CONFIG_ELECTRA_IDE) += electra_ide.o obj-$(CONFIG_PPC_PASEMI_CPUFREQ) += cpufreq.o diff --git a/trunk/arch/powerpc/platforms/pasemi/electra_ide.c b/trunk/arch/powerpc/platforms/pasemi/electra_ide.c deleted file mode 100644 index 12fb0c949263..000000000000 --- a/trunk/arch/powerpc/platforms/pasemi/electra_ide.c +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright (C) 2007 PA Semi, Inc - * - * Maintained by: Olof Johansson - * - * 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 - -/* The electra IDE interface is incredibly simple: Just a device on the localbus - * with interrupts hooked up to one of the GPIOs. The device tree contains the - * address window and interrupt mappings already, and the pata_platform driver handles - * the rest. We just need to hook the two up. - */ - -#define MAX_IFS 4 /* really, we have only one */ - -static struct platform_device *pdevs[MAX_IFS]; - -static int __devinit electra_ide_init(void) -{ - struct device_node *np; - struct resource r[3]; - int ret = 0; - int i; - - np = of_find_compatible_node(NULL, "ide", "electra-ide"); - i = 0; - - while (np && i < MAX_IFS) { - memset(r, 0, sizeof(r)); - - /* pata_platform wants two address ranges: one for the base registers, - * another for the control (altstatus). It's located at offset 0x3f6 in - * the window, but the device tree only has one large register window - * that covers both ranges. So we need to split it up by hand here: - */ - - ret = of_address_to_resource(np, 0, &r[0]); - if (ret) - goto out; - ret = of_address_to_resource(np, 0, &r[1]); - if (ret) - goto out; - - r[1].start += 0x3f6; - r[0].end = r[1].start-1; - - r[2].start = irq_of_parse_and_map(np, 0); - r[2].end = irq_of_parse_and_map(np, 0); - r[2].flags = IORESOURCE_IRQ; - - pr_debug("registering platform device at 0x%lx/0x%lx, irq is %ld\n", - r[0].start, r[1].start, r[2].start); - pdevs[i] = platform_device_register_simple("pata_platform", i, r, 3); - if (IS_ERR(pdevs[i])) { - ret = PTR_ERR(pdevs[i]); - pdevs[i] = NULL; - goto out; - } - np = of_find_compatible_node(np, "ide", "electra-ide"); - } -out: - return ret; -} -module_init(electra_ide_init); - -static void __devexit electra_ide_exit(void) -{ - int i; - - for (i = 0; i < MAX_IFS; i++) - if (pdevs[i]) - platform_device_unregister(pdevs[i]); -} -module_exit(electra_ide_exit); - - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR ("Olof Johansson "); -MODULE_DESCRIPTION("PA Semi Electra IDE driver"); diff --git a/trunk/arch/powerpc/platforms/pasemi/pci.c b/trunk/arch/powerpc/platforms/pasemi/pci.c index ab1f5f62bcd8..bbc6dfcfaa91 100644 --- a/trunk/arch/powerpc/platforms/pasemi/pci.c +++ b/trunk/arch/powerpc/platforms/pasemi/pci.c @@ -132,7 +132,7 @@ static void __init setup_pa_pxp(struct pci_controller *hose) hose->cfg_data = ioremap(0xe0000000, 0x10000000); } -static int __init pas_add_bridge(struct device_node *dev) +static int __init add_bridge(struct device_node *dev) { struct pci_controller *hose; @@ -150,11 +150,29 @@ static int __init pas_add_bridge(struct device_node *dev) printk(KERN_INFO "Found PA-PXP PCI host bridge.\n"); /* Interpret the "ranges" property */ + /* This also maps the I/O region and sets isa_io/mem_base */ pci_process_bridge_OF_ranges(hose, dev, 1); + pci_setup_phb_io(hose, 1); return 0; } + +static void __init pas_fixup_phb_resources(void) +{ + struct pci_controller *hose, *tmp; + + list_for_each_entry_safe(hose, tmp, &hose_list, list_node) { + unsigned long offset = (unsigned long)hose->io_base_virt - pci_io_base; + hose->io_resource.start += offset; + hose->io_resource.end += offset; + printk(KERN_INFO "PCI Host %d, io start: %lx; io end: %lx\n", + hose->global_number, + hose->io_resource.start, hose->io_resource.end); + } +} + + void __init pas_pci_init(void) { struct device_node *np, *root; @@ -167,11 +185,13 @@ void __init pas_pci_init(void) } for (np = NULL; (np = of_get_next_child(root, np)) != NULL;) - if (np->name && !strcmp(np->name, "pxp") && !pas_add_bridge(np)) + if (np->name && !strcmp(np->name, "pxp") && !add_bridge(np)) of_node_get(np); of_node_put(root); + pas_fixup_phb_resources(); + /* Setup the linkage between OF nodes and PHBs */ pci_devs_phb_init(); diff --git a/trunk/arch/powerpc/platforms/pasemi/setup.c b/trunk/arch/powerpc/platforms/pasemi/setup.c index ffe6528048b5..c5a3f61f8d85 100644 --- a/trunk/arch/powerpc/platforms/pasemi/setup.c +++ b/trunk/arch/powerpc/platforms/pasemi/setup.c @@ -239,7 +239,7 @@ static int __init pas_probe(void) return 1; } -define_machine(pasemi) { +define_machine(pas) { .name = "PA Semi PA6T-1682M", .probe = pas_probe, .setup_arch = pas_setup_arch, diff --git a/trunk/arch/powerpc/platforms/powermac/Kconfig b/trunk/arch/powerpc/platforms/powermac/Kconfig index 055990ca8ce6..5b7afe50039a 100644 --- a/trunk/arch/powerpc/platforms/powermac/Kconfig +++ b/trunk/arch/powerpc/platforms/powermac/Kconfig @@ -2,7 +2,6 @@ config PPC_PMAC bool "Apple PowerMac based machines" depends on PPC_MULTIPLATFORM select MPIC - select PCI select PPC_INDIRECT_PCI if PPC32 select PPC_MPC106 if PPC32 select PPC_NATIVE diff --git a/trunk/arch/powerpc/platforms/powermac/low_i2c.c b/trunk/arch/powerpc/platforms/powermac/low_i2c.c index efdf5eb81ecc..3f507ab9c5e5 100644 --- a/trunk/arch/powerpc/platforms/powermac/low_i2c.c +++ b/trunk/arch/powerpc/platforms/powermac/low_i2c.c @@ -42,7 +42,6 @@ #include #include #include -#include #include #include #include @@ -85,7 +84,7 @@ struct pmac_i2c_bus void *hostdata; int channel; /* some hosts have multiple */ int mode; /* current mode */ - struct mutex mutex; + struct semaphore sem; int opened; int polled; /* open mode */ struct platform_device *platform_dev; @@ -105,7 +104,7 @@ static LIST_HEAD(pmac_i2c_busses); struct pmac_i2c_host_kw { - struct mutex mutex; /* Access mutex for use by + struct semaphore mutex; /* Access mutex for use by * i2c-keywest */ void __iomem *base; /* register base address */ int bsteps; /* register stepping */ @@ -376,14 +375,14 @@ static void kw_i2c_timeout(unsigned long data) static int kw_i2c_open(struct pmac_i2c_bus *bus) { struct pmac_i2c_host_kw *host = bus->hostdata; - mutex_lock(&host->mutex); + down(&host->mutex); return 0; } static void kw_i2c_close(struct pmac_i2c_bus *bus) { struct pmac_i2c_host_kw *host = bus->hostdata; - mutex_unlock(&host->mutex); + up(&host->mutex); } static int kw_i2c_xfer(struct pmac_i2c_bus *bus, u8 addrdir, int subsize, @@ -499,7 +498,7 @@ static struct pmac_i2c_host_kw *__init kw_i2c_host_init(struct device_node *np) kfree(host); return NULL; } - mutex_init(&host->mutex); + init_MUTEX(&host->mutex); init_completion(&host->complete); spin_lock_init(&host->lock); init_timer(&host->timeout_timer); @@ -572,7 +571,7 @@ static void __init kw_i2c_add(struct pmac_i2c_host_kw *host, bus->open = kw_i2c_open; bus->close = kw_i2c_close; bus->xfer = kw_i2c_xfer; - mutex_init(&bus->mutex); + init_MUTEX(&bus->sem); if (controller == busnode) bus->flags = pmac_i2c_multibus; list_add(&bus->link, &pmac_i2c_busses); @@ -799,7 +798,7 @@ static void __init pmu_i2c_probe(void) bus->mode = pmac_i2c_mode_std; bus->hostdata = bus + 1; bus->xfer = pmu_i2c_xfer; - mutex_init(&bus->mutex); + init_MUTEX(&bus->sem); bus->flags = pmac_i2c_multibus; list_add(&bus->link, &pmac_i2c_busses); @@ -922,7 +921,7 @@ static void __init smu_i2c_probe(void) bus->mode = pmac_i2c_mode_std; bus->hostdata = bus + 1; bus->xfer = smu_i2c_xfer; - mutex_init(&bus->mutex); + init_MUTEX(&bus->sem); bus->flags = 0; list_add(&bus->link, &pmac_i2c_busses); @@ -1094,13 +1093,13 @@ int pmac_i2c_open(struct pmac_i2c_bus *bus, int polled) { int rc; - mutex_lock(&bus->mutex); + down(&bus->sem); bus->polled = polled || pmac_i2c_force_poll; bus->opened = 1; bus->mode = pmac_i2c_mode_std; if (bus->open && (rc = bus->open(bus)) != 0) { bus->opened = 0; - mutex_unlock(&bus->mutex); + up(&bus->sem); return rc; } return 0; @@ -1113,7 +1112,7 @@ void pmac_i2c_close(struct pmac_i2c_bus *bus) if (bus->close) bus->close(bus); bus->opened = 0; - mutex_unlock(&bus->mutex); + up(&bus->sem); } EXPORT_SYMBOL_GPL(pmac_i2c_close); diff --git a/trunk/arch/powerpc/platforms/powermac/pci.c b/trunk/arch/powerpc/platforms/powermac/pci.c index 92586db19754..c4af9e21ac93 100644 --- a/trunk/arch/powerpc/platforms/powermac/pci.c +++ b/trunk/arch/powerpc/platforms/powermac/pci.c @@ -35,6 +35,8 @@ #define DBG(x...) #endif +static int add_bridge(struct device_node *dev); + /* XXX Could be per-controller, but I don't think we risk anything by * assuming we won't have both UniNorth and Bandit */ static int has_uninorth; @@ -895,7 +897,7 @@ static void __init setup_u3_ht(struct pci_controller* hose) * "pci" (a MPC106) and no bandit or chaos bridges, and contrariwise, * if we have one or more bandit or chaos bridges, we don't have a MPC106. */ -static int __init pmac_add_bridge(struct device_node *dev) +static int __init add_bridge(struct device_node *dev) { int len; struct pci_controller *hose; @@ -916,9 +918,15 @@ static int __init pmac_add_bridge(struct device_node *dev) " bus 0\n", dev->full_name); } + /* XXX Different prototypes, to be merged */ +#ifdef CONFIG_PPC64 hose = pcibios_alloc_controller(dev); +#else + hose = pcibios_alloc_controller(); +#endif if (!hose) return -ENOMEM; + hose->arch_data = dev; hose->first_busno = bus_range ? bus_range[0] : 0; hose->last_busno = bus_range ? bus_range[1] : 0xff; @@ -998,6 +1006,19 @@ void __devinit pmac_pci_irq_fixup(struct pci_dev *dev) #endif /* CONFIG_PPC32 */ } +#ifdef CONFIG_PPC64 +static void __init pmac_fixup_phb_resources(void) +{ + struct pci_controller *hose, *tmp; + + list_for_each_entry_safe(hose, tmp, &hose_list, list_node) { + printk(KERN_INFO "PCI Host %d, io start: %lx; io end: %lx\n", + hose->global_number, + hose->io_resource.start, hose->io_resource.end); + } +} +#endif + void __init pmac_pci_init(void) { struct device_node *np, *root; @@ -1015,7 +1036,7 @@ void __init pmac_pci_init(void) if (strcmp(np->name, "bandit") == 0 || strcmp(np->name, "chaos") == 0 || strcmp(np->name, "pci") == 0) { - if (pmac_add_bridge(np) == 0) + if (add_bridge(np) == 0) of_node_get(np); } if (strcmp(np->name, "ht") == 0) { @@ -1029,9 +1050,28 @@ void __init pmac_pci_init(void) /* Probe HT last as it relies on the agp resources to be already * setup */ - if (ht && pmac_add_bridge(ht) != 0) + if (ht && add_bridge(ht) != 0) of_node_put(ht); + /* + * We need to call pci_setup_phb_io for the HT bridge first + * so it gets the I/O port numbers starting at 0, and we + * need to call it for the AGP bridge after that so it gets + * small positive I/O port numbers. + */ + if (u3_ht) + pci_setup_phb_io(u3_ht, 1); + if (u3_agp) + pci_setup_phb_io(u3_agp, 0); + if (u4_pcie) + pci_setup_phb_io(u4_pcie, 0); + + /* + * On ppc64, fixup the IO resources on our host bridges as + * the common code does it only for children of the host bridges + */ + pmac_fixup_phb_resources(); + /* Setup the linkage between OF nodes and PHBs */ pci_devs_phb_init(); diff --git a/trunk/arch/powerpc/platforms/ps3/Kconfig b/trunk/arch/powerpc/platforms/ps3/Kconfig index a05079b07696..40f0008af4d1 100644 --- a/trunk/arch/powerpc/platforms/ps3/Kconfig +++ b/trunk/arch/powerpc/platforms/ps3/Kconfig @@ -7,7 +7,6 @@ config PPC_PS3 select USB_OHCI_BIG_ENDIAN_MMIO select USB_ARCH_HAS_EHCI select USB_EHCI_BIG_ENDIAN_MMIO - select MEMORY_HOTPLUG help This option enables support for the Sony PS3 game console and other platforms using the PS3 hypervisor. @@ -74,12 +73,18 @@ config PS3_USE_LPAR_ADDR config PS3_VUART depends on PPC_PS3 - tristate + bool "PS3 Virtual UART support" if PS3_ADVANCED + default y + help + Include support for the PS3 Virtual UART. + + This support is required for several system services + including the System Manager and AV Settings. In + general, all users will say Y. config PS3_PS3AV - depends on PPC_PS3 tristate "PS3 AV settings driver" if PS3_ADVANCED - select PS3_VUART + depends on PS3_VUART default y help Include support for the PS3 AV Settings driver. @@ -88,18 +93,13 @@ config PS3_PS3AV general, all users will say Y or M. config PS3_SYS_MANAGER - depends on PPC_PS3 - tristate "PS3 System Manager driver" if PS3_ADVANCED - select PS3_VUART - default m + bool "PS3 System Manager driver" if PS3_ADVANCED + depends on PS3_VUART + default y help Include support for the PS3 System Manager. This support is required for system control. In - general, all users will say Y or M. - -config PS3_STORAGE - depends on PPC_PS3 - tristate + general, all users will say Y. endmenu diff --git a/trunk/arch/powerpc/platforms/ps3/Makefile b/trunk/arch/powerpc/platforms/ps3/Makefile index ac1bdf844eca..a0048fcf0866 100644 --- a/trunk/arch/powerpc/platforms/ps3/Makefile +++ b/trunk/arch/powerpc/platforms/ps3/Makefile @@ -4,4 +4,3 @@ obj-y += system-bus.o obj-$(CONFIG_SMP) += smp.o obj-$(CONFIG_SPU_BASE) += spu.o -obj-y += device-init.o diff --git a/trunk/arch/powerpc/platforms/ps3/device-init.c b/trunk/arch/powerpc/platforms/ps3/device-init.c deleted file mode 100644 index 825ebb2cbc2a..000000000000 --- a/trunk/arch/powerpc/platforms/ps3/device-init.c +++ /dev/null @@ -1,785 +0,0 @@ -/* - * PS3 device registration routines. - * - * Copyright (C) 2007 Sony Computer Entertainment Inc. - * Copyright 2007 Sony Corp. - * - * 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; version 2 of the License. - * - * 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 "platform.h" - -/** - * ps3_setup_gelic_device - Setup and register a gelic device instance. - * - * Allocates memory for a struct ps3_system_bus_device instance, initialises the - * structure members, and registers the device instance with the system bus. - */ - -static int __init ps3_setup_gelic_device( - const struct ps3_repository_device *repo) -{ - int result; - struct layout { - struct ps3_system_bus_device dev; - struct ps3_dma_region d_region; - } *p; - - pr_debug(" -> %s:%d\n", __func__, __LINE__); - - BUG_ON(repo->bus_type != PS3_BUS_TYPE_SB); - BUG_ON(repo->dev_type != PS3_DEV_TYPE_SB_GELIC); - - p = kzalloc(sizeof(struct layout), GFP_KERNEL); - - if (!p) { - result = -ENOMEM; - goto fail_malloc; - } - - p->dev.match_id = PS3_MATCH_ID_GELIC; - p->dev.dev_type = PS3_DEVICE_TYPE_SB; - p->dev.bus_id = repo->bus_id; - p->dev.dev_id = repo->dev_id; - p->dev.d_region = &p->d_region; - - result = ps3_repository_find_interrupt(repo, - PS3_INTERRUPT_TYPE_EVENT_PORT, &p->dev.interrupt_id); - - if (result) { - pr_debug("%s:%d ps3_repository_find_interrupt failed\n", - __func__, __LINE__); - goto fail_find_interrupt; - } - - BUG_ON(p->dev.interrupt_id != 0); - - result = ps3_dma_region_init(&p->dev, p->dev.d_region, PS3_DMA_64K, - PS3_DMA_OTHER, NULL, 0); - - if (result) { - pr_debug("%s:%d ps3_dma_region_init failed\n", - __func__, __LINE__); - goto fail_dma_init; - } - - result = ps3_system_bus_device_register(&p->dev); - - if (result) { - pr_debug("%s:%d ps3_system_bus_device_register failed\n", - __func__, __LINE__); - goto fail_device_register; - } - - pr_debug(" <- %s:%d\n", __func__, __LINE__); - return result; - -fail_device_register: -fail_dma_init: -fail_find_interrupt: - kfree(p); -fail_malloc: - pr_debug(" <- %s:%d: fail.\n", __func__, __LINE__); - return result; -} - -static int __init_refok ps3_setup_uhc_device( - const struct ps3_repository_device *repo, enum ps3_match_id match_id, - enum ps3_interrupt_type interrupt_type, enum ps3_reg_type reg_type) -{ - int result; - struct layout { - struct ps3_system_bus_device dev; - struct ps3_dma_region d_region; - struct ps3_mmio_region m_region; - } *p; - u64 bus_addr; - u64 len; - - pr_debug(" -> %s:%d\n", __func__, __LINE__); - - BUG_ON(repo->bus_type != PS3_BUS_TYPE_SB); - BUG_ON(repo->dev_type != PS3_DEV_TYPE_SB_USB); - - p = kzalloc(sizeof(struct layout), GFP_KERNEL); - - if (!p) { - result = -ENOMEM; - goto fail_malloc; - } - - p->dev.match_id = match_id; - p->dev.dev_type = PS3_DEVICE_TYPE_SB; - p->dev.bus_id = repo->bus_id; - p->dev.dev_id = repo->dev_id; - p->dev.d_region = &p->d_region; - p->dev.m_region = &p->m_region; - - result = ps3_repository_find_interrupt(repo, - interrupt_type, &p->dev.interrupt_id); - - if (result) { - pr_debug("%s:%d ps3_repository_find_interrupt failed\n", - __func__, __LINE__); - goto fail_find_interrupt; - } - - result = ps3_repository_find_reg(repo, reg_type, - &bus_addr, &len); - - if (result) { - pr_debug("%s:%d ps3_repository_find_reg failed\n", - __func__, __LINE__); - goto fail_find_reg; - } - - result = ps3_dma_region_init(&p->dev, p->dev.d_region, PS3_DMA_64K, - PS3_DMA_INTERNAL, NULL, 0); - - if (result) { - pr_debug("%s:%d ps3_dma_region_init failed\n", - __func__, __LINE__); - goto fail_dma_init; - } - - result = ps3_mmio_region_init(&p->dev, p->dev.m_region, bus_addr, len, - PS3_MMIO_4K); - - if (result) { - pr_debug("%s:%d ps3_mmio_region_init failed\n", - __func__, __LINE__); - goto fail_mmio_init; - } - - result = ps3_system_bus_device_register(&p->dev); - - if (result) { - pr_debug("%s:%d ps3_system_bus_device_register failed\n", - __func__, __LINE__); - goto fail_device_register; - } - - pr_debug(" <- %s:%d\n", __func__, __LINE__); - return result; - -fail_device_register: -fail_mmio_init: -fail_dma_init: -fail_find_reg: -fail_find_interrupt: - kfree(p); -fail_malloc: - pr_debug(" <- %s:%d: fail.\n", __func__, __LINE__); - return result; -} - -static int __init ps3_setup_ehci_device( - const struct ps3_repository_device *repo) -{ - return ps3_setup_uhc_device(repo, PS3_MATCH_ID_EHCI, - PS3_INTERRUPT_TYPE_SB_EHCI, PS3_REG_TYPE_SB_EHCI); -} - -static int __init ps3_setup_ohci_device( - const struct ps3_repository_device *repo) -{ - return ps3_setup_uhc_device(repo, PS3_MATCH_ID_OHCI, - PS3_INTERRUPT_TYPE_SB_OHCI, PS3_REG_TYPE_SB_OHCI); -} - -static int __init ps3_setup_vuart_device(enum ps3_match_id match_id, - unsigned int port_number) -{ - int result; - struct layout { - struct ps3_system_bus_device dev; - } *p; - - pr_debug(" -> %s:%d: match_id %u, port %u\n", __func__, __LINE__, - match_id, port_number); - - p = kzalloc(sizeof(struct layout), GFP_KERNEL); - - if (!p) - return -ENOMEM; - - p->dev.match_id = match_id; - p->dev.dev_type = PS3_DEVICE_TYPE_VUART; - p->dev.port_number = port_number; - - result = ps3_system_bus_device_register(&p->dev); - - if (result) - pr_debug("%s:%d ps3_system_bus_device_register failed\n", - __func__, __LINE__); - - pr_debug(" <- %s:%d\n", __func__, __LINE__); - return result; -} - -static int ps3stor_wait_for_completion(u64 dev_id, u64 tag, - unsigned int timeout) -{ - int result = -1; - unsigned int retries = 0; - u64 status; - - for (retries = 0; retries < timeout; retries++) { - result = lv1_storage_check_async_status(dev_id, tag, &status); - if (!result) - break; - - msleep(1); - } - - if (result) - pr_debug("%s:%u: check_async_status: %s, status %lx\n", - __func__, __LINE__, ps3_result(result), status); - - return result; -} - -/** - * ps3_storage_wait_for_device - Wait for a storage device to become ready. - * @repo: The repository device to wait for. - * - * Uses the hypervisor's storage device notification mechanism to wait until - * a storage device is ready. The device notification mechanism uses a - * psuedo device (id = -1) to asynchronously notify the guest when storage - * devices become ready. The notification device has a block size of 512 - * bytes. - */ - -static int ps3_storage_wait_for_device(const struct ps3_repository_device *repo) -{ - int result; - const u64 notification_dev_id = (u64)-1LL; - const unsigned int timeout = HZ; - u64 lpar; - u64 tag; - struct { - u64 operation_code; /* must be zero */ - u64 event_mask; /* 1 = device ready */ - } *notify_cmd; - struct { - u64 event_type; /* notify_device_ready */ - u64 bus_id; - u64 dev_id; - u64 dev_type; - u64 dev_port; - } *notify_event; - enum { - notify_device_ready = 1 - }; - - pr_debug(" -> %s:%u: bus_id %u, dev_id %u, dev_type %u\n", __func__, - __LINE__, repo->bus_id, repo->dev_id, repo->dev_type); - - notify_cmd = kzalloc(512, GFP_KERNEL); - notify_event = (void *)notify_cmd; - if (!notify_cmd) - return -ENOMEM; - - lpar = ps3_mm_phys_to_lpar(__pa(notify_cmd)); - - result = lv1_open_device(repo->bus_id, notification_dev_id, 0); - if (result) { - printk(KERN_ERR "%s:%u: lv1_open_device %s\n", __func__, - __LINE__, ps3_result(result)); - result = -ENODEV; - goto fail_free; - } - - /* Setup and write the request for device notification. */ - - notify_cmd->operation_code = 0; /* must be zero */ - notify_cmd->event_mask = 0x01; /* device ready */ - - result = lv1_storage_write(notification_dev_id, 0, 0, 1, 0, lpar, - &tag); - if (result) { - printk(KERN_ERR "%s:%u: write failed %s\n", __func__, __LINE__, - ps3_result(result)); - result = -ENODEV; - goto fail_close; - } - - /* Wait for the write completion */ - - result = ps3stor_wait_for_completion(notification_dev_id, tag, - timeout); - if (result) { - printk(KERN_ERR "%s:%u: write not completed %s\n", __func__, - __LINE__, ps3_result(result)); - result = -ENODEV; - goto fail_close; - } - - /* Loop here processing the requested notification events. */ - - result = -ENODEV; - while (1) { - memset(notify_event, 0, sizeof(*notify_event)); - - result = lv1_storage_read(notification_dev_id, 0, 0, 1, 0, - lpar, &tag); - if (result) { - printk(KERN_ERR "%s:%u: write failed %s\n", __func__, - __LINE__, ps3_result(result)); - break; - } - - result = ps3stor_wait_for_completion(notification_dev_id, tag, - timeout); - if (result) { - printk(KERN_ERR "%s:%u: read not completed %s\n", - __func__, __LINE__, ps3_result(result)); - break; - } - - if (notify_event->event_type != notify_device_ready || - notify_event->bus_id != repo->bus_id) { - pr_debug("%s:%u: bad notify_event: event %lu, " - "dev_id %lu, dev_type %lu\n", - __func__, __LINE__, notify_event->event_type, - notify_event->dev_id, notify_event->dev_type); - break; - } - - if (notify_event->dev_id == repo->dev_id && - notify_event->dev_type == repo->dev_type) { - pr_debug("%s:%u: device ready: dev_id %u\n", __func__, - __LINE__, repo->dev_id); - result = 0; - break; - } - - if (notify_event->dev_id == repo->dev_id && - notify_event->dev_type == PS3_DEV_TYPE_NOACCESS) { - pr_debug("%s:%u: no access: dev_id %u\n", __func__, - __LINE__, repo->dev_id); - break; - } - } - -fail_close: - lv1_close_device(repo->bus_id, notification_dev_id); -fail_free: - kfree(notify_cmd); - pr_debug(" <- %s:%u\n", __func__, __LINE__); - return result; -} - -static int ps3_setup_storage_dev(const struct ps3_repository_device *repo, - enum ps3_match_id match_id) -{ - int result; - struct ps3_storage_device *p; - u64 port, blk_size, num_blocks; - unsigned int num_regions, i; - - pr_debug(" -> %s:%u: match_id %u\n", __func__, __LINE__, match_id); - - result = ps3_repository_read_stor_dev_info(repo->bus_index, - repo->dev_index, &port, - &blk_size, &num_blocks, - &num_regions); - if (result) { - printk(KERN_ERR "%s:%u: _read_stor_dev_info failed %d\n", - __func__, __LINE__, result); - return -ENODEV; - } - - pr_debug("%s:%u: index %u:%u: port %lu blk_size %lu num_blocks %lu " - "num_regions %u\n", __func__, __LINE__, repo->bus_index, - repo->dev_index, port, blk_size, num_blocks, num_regions); - - p = kzalloc(sizeof(struct ps3_storage_device) + - num_regions * sizeof(struct ps3_storage_region), - GFP_KERNEL); - if (!p) { - result = -ENOMEM; - goto fail_malloc; - } - - p->sbd.match_id = match_id; - p->sbd.dev_type = PS3_DEVICE_TYPE_SB; - p->sbd.bus_id = repo->bus_id; - p->sbd.dev_id = repo->dev_id; - p->sbd.d_region = &p->dma_region; - p->blk_size = blk_size; - p->num_regions = num_regions; - - result = ps3_repository_find_interrupt(repo, - PS3_INTERRUPT_TYPE_EVENT_PORT, - &p->sbd.interrupt_id); - if (result) { - printk(KERN_ERR "%s:%u: find_interrupt failed %d\n", __func__, - __LINE__, result); - result = -ENODEV; - goto fail_find_interrupt; - } - - /* FIXME: Arrange to only do this on a 'cold' boot */ - - result = ps3_storage_wait_for_device(repo); - if (result) { - printk(KERN_ERR "%s:%u: storage_notification failed %d\n", - __func__, __LINE__, result); - result = -ENODEV; - goto fail_probe_notification; - } - - for (i = 0; i < num_regions; i++) { - unsigned int id; - u64 start, size; - - result = ps3_repository_read_stor_dev_region(repo->bus_index, - repo->dev_index, - i, &id, &start, - &size); - if (result) { - printk(KERN_ERR - "%s:%u: read_stor_dev_region failed %d\n", - __func__, __LINE__, result); - result = -ENODEV; - goto fail_read_region; - } - pr_debug("%s:%u: region %u: id %u start %lu size %lu\n", - __func__, __LINE__, i, id, start, size); - - p->regions[i].id = id; - p->regions[i].start = start; - p->regions[i].size = size; - } - - result = ps3_system_bus_device_register(&p->sbd); - if (result) { - pr_debug("%s:%u ps3_system_bus_device_register failed\n", - __func__, __LINE__); - goto fail_device_register; - } - - pr_debug(" <- %s:%u\n", __func__, __LINE__); - return 0; - -fail_device_register: -fail_read_region: -fail_probe_notification: -fail_find_interrupt: - kfree(p); -fail_malloc: - pr_debug(" <- %s:%u: fail.\n", __func__, __LINE__); - return result; -} - -static int __init ps3_register_vuart_devices(void) -{ - int result; - unsigned int port_number; - - pr_debug(" -> %s:%d\n", __func__, __LINE__); - - result = ps3_repository_read_vuart_av_port(&port_number); - if (result) - port_number = 0; /* av default */ - - result = ps3_setup_vuart_device(PS3_MATCH_ID_AV_SETTINGS, port_number); - WARN_ON(result); - - result = ps3_repository_read_vuart_sysmgr_port(&port_number); - if (result) - port_number = 2; /* sysmgr default */ - - result = ps3_setup_vuart_device(PS3_MATCH_ID_SYSTEM_MANAGER, - port_number); - WARN_ON(result); - - pr_debug(" <- %s:%d\n", __func__, __LINE__); - return result; -} - -static int __init ps3_register_sound_devices(void) -{ - int result; - struct layout { - struct ps3_system_bus_device dev; - struct ps3_dma_region d_region; - struct ps3_mmio_region m_region; - } *p; - - pr_debug(" -> %s:%d\n", __func__, __LINE__); - - p = kzalloc(sizeof(*p), GFP_KERNEL); - if (!p) - return -ENOMEM; - - p->dev.match_id = PS3_MATCH_ID_SOUND; - p->dev.dev_type = PS3_DEVICE_TYPE_IOC0; - p->dev.d_region = &p->d_region; - p->dev.m_region = &p->m_region; - - result = ps3_system_bus_device_register(&p->dev); - - if (result) - pr_debug("%s:%d ps3_system_bus_device_register failed\n", - __func__, __LINE__); - - pr_debug(" <- %s:%d\n", __func__, __LINE__); - return result; -} - -static int __init ps3_register_graphics_devices(void) -{ - int result; - struct layout { - struct ps3_system_bus_device dev; - } *p; - - pr_debug(" -> %s:%d\n", __func__, __LINE__); - - p = kzalloc(sizeof(struct layout), GFP_KERNEL); - - if (!p) - return -ENOMEM; - - p->dev.match_id = PS3_MATCH_ID_GRAPHICS; - p->dev.dev_type = PS3_DEVICE_TYPE_IOC0; - - result = ps3_system_bus_device_register(&p->dev); - - if (result) - pr_debug("%s:%d ps3_system_bus_device_register failed\n", - __func__, __LINE__); - - pr_debug(" <- %s:%d\n", __func__, __LINE__); - return result; -} - -/** - * ps3_register_repository_device - Register a device from the repositiory info. - * - */ - -static int ps3_register_repository_device( - const struct ps3_repository_device *repo) -{ - int result; - - switch (repo->dev_type) { - case PS3_DEV_TYPE_SB_GELIC: - result = ps3_setup_gelic_device(repo); - if (result) { - pr_debug("%s:%d ps3_setup_gelic_device failed\n", - __func__, __LINE__); - } - break; - case PS3_DEV_TYPE_SB_USB: - - /* Each USB device has both an EHCI and an OHCI HC */ - - result = ps3_setup_ehci_device(repo); - - if (result) { - pr_debug("%s:%d ps3_setup_ehci_device failed\n", - __func__, __LINE__); - } - - result = ps3_setup_ohci_device(repo); - - if (result) { - pr_debug("%s:%d ps3_setup_ohci_device failed\n", - __func__, __LINE__); - } - break; - case PS3_DEV_TYPE_STOR_DISK: - result = ps3_setup_storage_dev(repo, PS3_MATCH_ID_STOR_DISK); - - /* Some devices are not accessable from the Other OS lpar. */ - if (result == -ENODEV) { - result = 0; - pr_debug("%s:%u: not accessable\n", __func__, - __LINE__); - } - - if (result) - pr_debug("%s:%u ps3_setup_storage_dev failed\n", - __func__, __LINE__); - break; - - case PS3_DEV_TYPE_STOR_ROM: - result = ps3_setup_storage_dev(repo, PS3_MATCH_ID_STOR_ROM); - if (result) - pr_debug("%s:%u ps3_setup_storage_dev failed\n", - __func__, __LINE__); - break; - - case PS3_DEV_TYPE_STOR_FLASH: - result = ps3_setup_storage_dev(repo, PS3_MATCH_ID_STOR_FLASH); - if (result) - pr_debug("%s:%u ps3_setup_storage_dev failed\n", - __func__, __LINE__); - break; - - default: - result = 0; - pr_debug("%s:%u: unsupported dev_type %u\n", __func__, __LINE__, - repo->dev_type); - } - - return result; -} - -/** - * ps3_probe_thread - Background repository probing at system startup. - * - * This implementation only supports background probing on a single bus. - */ - -static int ps3_probe_thread(void *data) -{ - struct ps3_repository_device *repo = data; - int result; - unsigned int ms = 250; - - pr_debug(" -> %s:%u: kthread started\n", __func__, __LINE__); - - do { - try_to_freeze(); - - pr_debug("%s:%u: probing...\n", __func__, __LINE__); - - do { - result = ps3_repository_find_device(repo); - - if (result == -ENODEV) - pr_debug("%s:%u: nothing new\n", __func__, - __LINE__); - else if (result) - pr_debug("%s:%u: find device error.\n", - __func__, __LINE__); - else { - pr_debug("%s:%u: found device\n", __func__, - __LINE__); - ps3_register_repository_device(repo); - ps3_repository_bump_device(repo); - ms = 250; - } - } while (!result); - - pr_debug("%s:%u: ms %u\n", __func__, __LINE__, ms); - - if ( ms > 60000) - break; - - msleep_interruptible(ms); - - /* An exponential backoff. */ - ms <<= 1; - - } while (!kthread_should_stop()); - - pr_debug(" <- %s:%u: kthread finished\n", __func__, __LINE__); - - return 0; -} - -/** - * ps3_start_probe_thread - Starts the background probe thread. - * - */ - -static int __init ps3_start_probe_thread(enum ps3_bus_type bus_type) -{ - int result; - struct task_struct *task; - static struct ps3_repository_device repo; /* must be static */ - - pr_debug(" -> %s:%d\n", __func__, __LINE__); - - memset(&repo, 0, sizeof(repo)); - - repo.bus_type = bus_type; - - result = ps3_repository_find_bus(repo.bus_type, 0, &repo.bus_index); - - if (result) { - printk(KERN_ERR "%s: Cannot find bus (%d)\n", __func__, result); - return -ENODEV; - } - - result = ps3_repository_read_bus_id(repo.bus_index, &repo.bus_id); - - if (result) { - printk(KERN_ERR "%s: read_bus_id failed %d\n", __func__, - result); - return -ENODEV; - } - - task = kthread_run(ps3_probe_thread, &repo, "ps3-probe-%u", bus_type); - - if (IS_ERR(task)) { - result = PTR_ERR(task); - printk(KERN_ERR "%s: kthread_run failed %d\n", __func__, - result); - return result; - } - - pr_debug(" <- %s:%d\n", __func__, __LINE__); - return 0; -} - -/** - * ps3_register_devices - Probe the system and register devices found. - * - * A device_initcall() routine. - */ - -static int __init ps3_register_devices(void) -{ - int result; - - if (!firmware_has_feature(FW_FEATURE_PS3_LV1)) - return -ENODEV; - - pr_debug(" -> %s:%d\n", __func__, __LINE__); - - /* ps3_repository_dump_bus_info(); */ - - result = ps3_start_probe_thread(PS3_BUS_TYPE_STORAGE); - - ps3_register_vuart_devices(); - - ps3_register_graphics_devices(); - - ps3_repository_find_devices(PS3_BUS_TYPE_SB, - ps3_register_repository_device); - - ps3_register_sound_devices(); - - pr_debug(" <- %s:%d\n", __func__, __LINE__); - return 0; -} - -device_initcall(ps3_register_devices); diff --git a/trunk/arch/powerpc/platforms/ps3/htab.c b/trunk/arch/powerpc/platforms/ps3/htab.c index 5d2e176a1b18..a1409e450c70 100644 --- a/trunk/arch/powerpc/platforms/ps3/htab.c +++ b/trunk/arch/powerpc/platforms/ps3/htab.c @@ -29,12 +29,12 @@ #include "platform.h" #if defined(DEBUG) -#define DBG udbg_printf +#define DBG(fmt...) udbg_printf(fmt) #else -#define DBG pr_debug +#define DBG(fmt...) do{if(0)printk(fmt);}while(0) #endif -static struct hash_pte *htab; +static hpte_t *htab; static unsigned long htab_addr; static unsigned char *bolttab; static unsigned char *inusetab; @@ -44,8 +44,8 @@ static DEFINE_SPINLOCK(ps3_bolttab_lock); #define debug_dump_hpte(_a, _b, _c, _d, _e, _f, _g) \ _debug_dump_hpte(_a, _b, _c, _d, _e, _f, _g, __func__, __LINE__) static void _debug_dump_hpte(unsigned long pa, unsigned long va, - unsigned long group, unsigned long bitmap, struct hash_pte lhpte, - int psize, unsigned long slot, const char* func, int line) + unsigned long group, unsigned long bitmap, hpte_t lhpte, int psize, + unsigned long slot, const char* func, int line) { DBG("%s:%d: pa = %lxh\n", func, line, pa); DBG("%s:%d: lpar = %lxh\n", func, line, @@ -63,7 +63,7 @@ static long ps3_hpte_insert(unsigned long hpte_group, unsigned long va, unsigned long pa, unsigned long rflags, unsigned long vflags, int psize) { unsigned long slot; - struct hash_pte lhpte; + hpte_t lhpte; int secondary = 0; unsigned long result; unsigned long bitmap; @@ -234,17 +234,10 @@ static void ps3_hpte_invalidate(unsigned long slot, unsigned long va, static void ps3_hpte_clear(void) { - int result; + /* Make sure to clean up the frame buffer device first */ + ps3fb_cleanup(); - DBG(" -> %s:%d\n", __func__, __LINE__); - - result = lv1_unmap_htab(htab_addr); - BUG_ON(result); - - ps3_mm_shutdown(); - ps3_mm_vas_destroy(); - - DBG(" <- %s:%d\n", __func__, __LINE__); + lv1_unmap_htab(htab_addr); } void __init ps3_hpte_init(unsigned long htab_size) @@ -262,7 +255,7 @@ void __init ps3_hpte_init(unsigned long htab_size) ppc64_pft_size = __ilog2(htab_size); - bitmap_size = htab_size / sizeof(struct hash_pte) / 8; + bitmap_size = htab_size / sizeof(hpte_t) / 8; bolttab = __va(lmb_alloc(bitmap_size, 1)); inusetab = __va(lmb_alloc(bitmap_size, 1)); @@ -280,8 +273,8 @@ void __init ps3_map_htab(void) result = lv1_map_htab(0, &htab_addr); - htab = (__force struct hash_pte *)ioremap_flags(htab_addr, htab_size, - pgprot_val(PAGE_READONLY_X)); + htab = (hpte_t *)__ioremap(htab_addr, htab_size, + pgprot_val(PAGE_READONLY_X)); DBG("%s:%d: lpar %016lxh, virt %016lxh\n", __func__, __LINE__, htab_addr, (unsigned long)htab); diff --git a/trunk/arch/powerpc/platforms/ps3/interrupt.c b/trunk/arch/powerpc/platforms/ps3/interrupt.c index 67e32ec9b37e..ec9030dbb5f1 100644 --- a/trunk/arch/powerpc/platforms/ps3/interrupt.c +++ b/trunk/arch/powerpc/platforms/ps3/interrupt.c @@ -30,9 +30,9 @@ #include "platform.h" #if defined(DEBUG) -#define DBG udbg_printf +#define DBG(fmt...) udbg_printf(fmt) #else -#define DBG pr_debug +#define DBG(fmt...) do{if(0)printk(fmt);}while(0) #endif /** @@ -78,84 +78,18 @@ struct ps3_bmp { /** * struct ps3_private - a per cpu data structure * @bmp: ps3_bmp structure - * @ppe_id: HV logical_ppe_id - * @thread_id: HV thread_id + * @node: HV logical_ppe_id + * @cpu: HV thread_id */ struct ps3_private { struct ps3_bmp bmp __attribute__ ((aligned (PS3_BMP_MINALIGN))); - u64 ppe_id; - u64 thread_id; + u64 node; + unsigned int cpu; }; static DEFINE_PER_CPU(struct ps3_private, ps3_private); -/** - * ps3_chip_mask - Set an interrupt mask bit in ps3_bmp. - * @virq: The assigned Linux virq. - * - * Sets ps3_bmp.mask and calls lv1_did_update_interrupt_mask(). - */ - -static void ps3_chip_mask(unsigned int virq) -{ - struct ps3_private *pd = get_irq_chip_data(virq); - unsigned long flags; - - pr_debug("%s:%d: thread_id %lu, virq %d\n", __func__, __LINE__, - pd->thread_id, virq); - - local_irq_save(flags); - clear_bit(63 - virq, &pd->bmp.mask); - lv1_did_update_interrupt_mask(pd->ppe_id, pd->thread_id); - local_irq_restore(flags); -} - -/** - * ps3_chip_unmask - Clear an interrupt mask bit in ps3_bmp. - * @virq: The assigned Linux virq. - * - * Clears ps3_bmp.mask and calls lv1_did_update_interrupt_mask(). - */ - -static void ps3_chip_unmask(unsigned int virq) -{ - struct ps3_private *pd = get_irq_chip_data(virq); - unsigned long flags; - - pr_debug("%s:%d: thread_id %lu, virq %d\n", __func__, __LINE__, - pd->thread_id, virq); - - local_irq_save(flags); - set_bit(63 - virq, &pd->bmp.mask); - lv1_did_update_interrupt_mask(pd->ppe_id, pd->thread_id); - local_irq_restore(flags); -} - -/** - * ps3_chip_eoi - HV end-of-interrupt. - * @virq: The assigned Linux virq. - * - * Calls lv1_end_of_interrupt_ext(). - */ - -static void ps3_chip_eoi(unsigned int virq) -{ - const struct ps3_private *pd = get_irq_chip_data(virq); - lv1_end_of_interrupt_ext(pd->ppe_id, pd->thread_id, virq); -} - -/** - * ps3_irq_chip - Represents the ps3_bmp as a Linux struct irq_chip. - */ - -static struct irq_chip ps3_irq_chip = { - .typename = "ps3", - .mask = ps3_chip_mask, - .unmask = ps3_chip_unmask, - .eoi = ps3_chip_eoi, -}; - /** * ps3_virq_setup - virq related setup. * @cpu: enum ps3_cpu_binding indicating the cpu the interrupt should be @@ -200,8 +134,6 @@ int ps3_virq_setup(enum ps3_cpu_binding cpu, unsigned long outlet, goto fail_set; } - ps3_chip_mask(*virq); - return result; fail_set: @@ -221,8 +153,8 @@ int ps3_virq_destroy(unsigned int virq) { const struct ps3_private *pd = get_irq_chip_data(virq); - pr_debug("%s:%d: ppe_id %lu, thread_id %lu, virq %u\n", __func__, - __LINE__, pd->ppe_id, pd->thread_id, virq); + pr_debug("%s:%d: node %lu, cpu %d, virq %u\n", __func__, __LINE__, + pd->node, pd->cpu, virq); set_irq_chip_data(virq, NULL); irq_dispose_mapping(virq); @@ -258,8 +190,7 @@ int ps3_irq_plug_setup(enum ps3_cpu_binding cpu, unsigned long outlet, /* Binds outlet to cpu + virq. */ - result = lv1_connect_irq_plug_ext(pd->ppe_id, pd->thread_id, *virq, - outlet, 0); + result = lv1_connect_irq_plug_ext(pd->node, pd->cpu, *virq, outlet, 0); if (result) { pr_info("%s:%d: lv1_connect_irq_plug_ext failed: %s\n", @@ -291,12 +222,10 @@ int ps3_irq_plug_destroy(unsigned int virq) int result; const struct ps3_private *pd = get_irq_chip_data(virq); - pr_debug("%s:%d: ppe_id %lu, thread_id %lu, virq %u\n", __func__, - __LINE__, pd->ppe_id, pd->thread_id, virq); - - ps3_chip_mask(virq); + pr_debug("%s:%d: node %lu, cpu %d, virq %u\n", __func__, __LINE__, + pd->node, pd->cpu, virq); - result = lv1_disconnect_irq_plug_ext(pd->ppe_id, pd->thread_id, virq); + result = lv1_disconnect_irq_plug_ext(pd->node, pd->cpu, virq); if (result) pr_info("%s:%d: lv1_disconnect_irq_plug_ext failed: %s\n", @@ -353,9 +282,7 @@ int ps3_event_receive_port_destroy(unsigned int virq) { int result; - pr_debug(" -> %s:%d virq %u\n", __func__, __LINE__, virq); - - ps3_chip_mask(virq); + pr_debug(" -> %s:%d virq: %u\n", __func__, __LINE__, virq); result = lv1_destruct_event_receive_port(virq_to_hw(virq)); @@ -363,14 +290,17 @@ int ps3_event_receive_port_destroy(unsigned int virq) pr_debug("%s:%d: lv1_destruct_event_receive_port failed: %s\n", __func__, __LINE__, ps3_result(result)); - /* - * Don't call ps3_virq_destroy() here since ps3_smp_cleanup_cpu() - * calls from interrupt context (smp_call_function) when kexecing. + /* lv1_destruct_event_receive_port() destroys the IRQ plug, + * so don't call ps3_irq_plug_destroy() here. */ + result = ps3_virq_destroy(virq); + BUG_ON(result); + pr_debug(" <- %s:%d\n", __func__, __LINE__); return result; } +EXPORT_SYMBOL_GPL(ps3_event_receive_port_destroy); int ps3_send_event_locally(unsigned int virq) { @@ -381,15 +311,17 @@ int ps3_send_event_locally(unsigned int virq) * ps3_sb_event_receive_port_setup - Setup a system bus event receive port. * @cpu: enum ps3_cpu_binding indicating the cpu the interrupt should be * serviced on. - * @dev: The system bus device instance. + * @did: The HV device identifier read from the system repository. + * @interrupt_id: The device interrupt id read from the system repository. * @virq: The assigned Linux virq. * * An event irq represents a virtual device interrupt. The interrupt_id * coresponds to the software interrupt number. */ -int ps3_sb_event_receive_port_setup(struct ps3_system_bus_device *dev, - enum ps3_cpu_binding cpu, unsigned int *virq) +int ps3_sb_event_receive_port_setup(enum ps3_cpu_binding cpu, + const struct ps3_device_id *did, unsigned int interrupt_id, + unsigned int *virq) { /* this should go in system-bus.c */ @@ -400,8 +332,8 @@ int ps3_sb_event_receive_port_setup(struct ps3_system_bus_device *dev, if (result) return result; - result = lv1_connect_interrupt_event_receive_port(dev->bus_id, - dev->dev_id, virq_to_hw(*virq), dev->interrupt_id); + result = lv1_connect_interrupt_event_receive_port(did->bus_id, + did->dev_id, virq_to_hw(*virq), interrupt_id); if (result) { pr_debug("%s:%d: lv1_connect_interrupt_event_receive_port" @@ -413,24 +345,24 @@ int ps3_sb_event_receive_port_setup(struct ps3_system_bus_device *dev, } pr_debug("%s:%d: interrupt_id %u, virq %u\n", __func__, __LINE__, - dev->interrupt_id, *virq); + interrupt_id, *virq); return 0; } EXPORT_SYMBOL(ps3_sb_event_receive_port_setup); -int ps3_sb_event_receive_port_destroy(struct ps3_system_bus_device *dev, - unsigned int virq) +int ps3_sb_event_receive_port_destroy(const struct ps3_device_id *did, + unsigned int interrupt_id, unsigned int virq) { /* this should go in system-bus.c */ int result; pr_debug(" -> %s:%d: interrupt_id %u, virq %u\n", __func__, __LINE__, - dev->interrupt_id, virq); + interrupt_id, virq); - result = lv1_disconnect_interrupt_event_receive_port(dev->bus_id, - dev->dev_id, virq_to_hw(virq), dev->interrupt_id); + result = lv1_disconnect_interrupt_event_receive_port(did->bus_id, + did->dev_id, virq_to_hw(virq), interrupt_id); if (result) pr_debug("%s:%d: lv1_disconnect_interrupt_event_receive_port" @@ -440,14 +372,6 @@ int ps3_sb_event_receive_port_destroy(struct ps3_system_bus_device *dev, result = ps3_event_receive_port_destroy(virq); BUG_ON(result); - /* - * ps3_event_receive_port_destroy() destroys the IRQ plug, - * so don't call ps3_irq_plug_destroy() here. - */ - - result = ps3_virq_destroy(virq); - BUG_ON(result); - pr_debug(" <- %s:%d\n", __func__, __LINE__); return result; } @@ -488,24 +412,16 @@ EXPORT_SYMBOL_GPL(ps3_io_irq_setup); int ps3_io_irq_destroy(unsigned int virq) { int result; - unsigned long outlet = virq_to_hw(virq); - - ps3_chip_mask(virq); - /* - * lv1_destruct_io_irq_outlet() will destroy the IRQ plug, - * so call ps3_irq_plug_destroy() first. - */ - - result = ps3_irq_plug_destroy(virq); - BUG_ON(result); - - result = lv1_destruct_io_irq_outlet(outlet); + result = lv1_destruct_io_irq_outlet(virq_to_hw(virq)); if (result) pr_debug("%s:%d: lv1_destruct_io_irq_outlet failed: %s\n", __func__, __LINE__, ps3_result(result)); + result = ps3_irq_plug_destroy(virq); + BUG_ON(result); + return result; } EXPORT_SYMBOL_GPL(ps3_io_irq_destroy); @@ -545,13 +461,11 @@ int ps3_vuart_irq_setup(enum ps3_cpu_binding cpu, void* virt_addr_bmp, return result; } -EXPORT_SYMBOL_GPL(ps3_vuart_irq_setup); int ps3_vuart_irq_destroy(unsigned int virq) { int result; - ps3_chip_mask(virq); result = lv1_deconfigure_virtual_uart_irq(); if (result) { @@ -565,7 +479,6 @@ int ps3_vuart_irq_destroy(unsigned int virq) return result; } -EXPORT_SYMBOL_GPL(ps3_vuart_irq_destroy); /** * ps3_spe_irq_setup - Setup an spe virq. @@ -601,14 +514,9 @@ int ps3_spe_irq_setup(enum ps3_cpu_binding cpu, unsigned long spe_id, int ps3_spe_irq_destroy(unsigned int virq) { - int result; - - ps3_chip_mask(virq); - - result = ps3_irq_plug_destroy(virq); + int result = ps3_irq_plug_destroy(virq); BUG_ON(result); - - return result; + return 0; } @@ -625,7 +533,7 @@ static void _dump_64_bmp(const char *header, const u64 *p, unsigned cpu, *p & 0xffff); } -static void __maybe_unused _dump_256_bmp(const char *header, +static void __attribute__ ((unused)) _dump_256_bmp(const char *header, const u64 *p, unsigned cpu, const char* func, int line) { pr_debug("%s:%d: %s %u {%016lx:%016lx:%016lx:%016lx}\n", @@ -638,25 +546,86 @@ static void _dump_bmp(struct ps3_private* pd, const char* func, int line) unsigned long flags; spin_lock_irqsave(&pd->bmp.lock, flags); - _dump_64_bmp("stat", &pd->bmp.status, pd->thread_id, func, line); - _dump_64_bmp("mask", &pd->bmp.mask, pd->thread_id, func, line); + _dump_64_bmp("stat", &pd->bmp.status, pd->cpu, func, line); + _dump_64_bmp("mask", &pd->bmp.mask, pd->cpu, func, line); spin_unlock_irqrestore(&pd->bmp.lock, flags); } #define dump_mask(_x) _dump_mask(_x, __func__, __LINE__) -static void __maybe_unused _dump_mask(struct ps3_private *pd, +static void __attribute__ ((unused)) _dump_mask(struct ps3_private* pd, const char* func, int line) { unsigned long flags; spin_lock_irqsave(&pd->bmp.lock, flags); - _dump_64_bmp("mask", &pd->bmp.mask, pd->thread_id, func, line); + _dump_64_bmp("mask", &pd->bmp.mask, pd->cpu, func, line); spin_unlock_irqrestore(&pd->bmp.lock, flags); } #else static void dump_bmp(struct ps3_private* pd) {}; #endif /* defined(DEBUG) */ +static void ps3_chip_mask(unsigned int virq) +{ + struct ps3_private *pd = get_irq_chip_data(virq); + u64 bit = 0x8000000000000000UL >> virq; + u64 *p = &pd->bmp.mask; + u64 old; + unsigned long flags; + + pr_debug("%s:%d: cpu %u, virq %d\n", __func__, __LINE__, pd->cpu, virq); + + local_irq_save(flags); + asm volatile( + "1: ldarx %0,0,%3\n" + "andc %0,%0,%2\n" + "stdcx. %0,0,%3\n" + "bne- 1b" + : "=&r" (old), "+m" (*p) + : "r" (bit), "r" (p) + : "cc" ); + + lv1_did_update_interrupt_mask(pd->node, pd->cpu); + local_irq_restore(flags); +} + +static void ps3_chip_unmask(unsigned int virq) +{ + struct ps3_private *pd = get_irq_chip_data(virq); + u64 bit = 0x8000000000000000UL >> virq; + u64 *p = &pd->bmp.mask; + u64 old; + unsigned long flags; + + pr_debug("%s:%d: cpu %u, virq %d\n", __func__, __LINE__, pd->cpu, virq); + + local_irq_save(flags); + asm volatile( + "1: ldarx %0,0,%3\n" + "or %0,%0,%2\n" + "stdcx. %0,0,%3\n" + "bne- 1b" + : "=&r" (old), "+m" (*p) + : "r" (bit), "r" (p) + : "cc" ); + + lv1_did_update_interrupt_mask(pd->node, pd->cpu); + local_irq_restore(flags); +} + +static void ps3_chip_eoi(unsigned int virq) +{ + const struct ps3_private *pd = get_irq_chip_data(virq); + lv1_end_of_interrupt_ext(pd->node, pd->cpu, virq); +} + +static struct irq_chip irq_chip = { + .typename = "ps3", + .mask = ps3_chip_mask, + .unmask = ps3_chip_unmask, + .eoi = ps3_chip_eoi, +}; + static void ps3_host_unmap(struct irq_host *h, unsigned int virq) { set_irq_chip_data(virq, NULL); @@ -668,7 +637,7 @@ static int ps3_host_map(struct irq_host *h, unsigned int virq, pr_debug("%s:%d: hwirq %lu, virq %u\n", __func__, __LINE__, hwirq, virq); - set_irq_chip_and_handler(virq, &ps3_irq_chip, handle_fasteoi_irq); + set_irq_chip_and_handler(virq, &irq_chip, handle_fasteoi_irq); return 0; } @@ -688,7 +657,7 @@ void __init ps3_register_ipi_debug_brk(unsigned int cpu, unsigned int virq) cpu, virq, pd->bmp.ipi_debug_brk_mask); } -static unsigned int ps3_get_irq(void) +unsigned int ps3_get_irq(void) { struct ps3_private *pd = &__get_cpu_var(ps3_private); u64 x = (pd->bmp.status & pd->bmp.mask); @@ -703,8 +672,8 @@ static unsigned int ps3_get_irq(void) plug &= 0x3f; if (unlikely(plug) == NO_IRQ) { - pr_debug("%s:%d: no plug found: thread_id %lu\n", __func__, - __LINE__, pd->thread_id); + pr_debug("%s:%d: no plug found: cpu %u\n", __func__, __LINE__, + pd->cpu); dump_bmp(&per_cpu(ps3_private, 0)); dump_bmp(&per_cpu(ps3_private, 1)); return NO_IRQ; @@ -734,16 +703,16 @@ void __init ps3_init_IRQ(void) for_each_possible_cpu(cpu) { struct ps3_private *pd = &per_cpu(ps3_private, cpu); - lv1_get_logical_ppe_id(&pd->ppe_id); - pd->thread_id = get_hard_smp_processor_id(cpu); + lv1_get_logical_ppe_id(&pd->node); + pd->cpu = get_hard_smp_processor_id(cpu); spin_lock_init(&pd->bmp.lock); - pr_debug("%s:%d: ppe_id %lu, thread_id %lu, bmp %lxh\n", - __func__, __LINE__, pd->ppe_id, pd->thread_id, + pr_debug("%s:%d: node %lu, cpu %d, bmp %lxh\n", __func__, + __LINE__, pd->node, pd->cpu, ps3_mm_phys_to_lpar(__pa(&pd->bmp))); - result = lv1_configure_irq_state_bitmap(pd->ppe_id, - pd->thread_id, ps3_mm_phys_to_lpar(__pa(&pd->bmp))); + result = lv1_configure_irq_state_bitmap(pd->node, pd->cpu, + ps3_mm_phys_to_lpar(__pa(&pd->bmp))); if (result) pr_debug("%s:%d: lv1_configure_irq_state_bitmap failed:" @@ -753,16 +722,3 @@ void __init ps3_init_IRQ(void) ppc_md.get_irq = ps3_get_irq; } - -void ps3_shutdown_IRQ(int cpu) -{ - int result; - u64 ppe_id; - u64 thread_id = get_hard_smp_processor_id(cpu); - - lv1_get_logical_ppe_id(&ppe_id); - result = lv1_configure_irq_state_bitmap(ppe_id, thread_id, 0); - - DBG("%s:%d: lv1_configure_irq_state_bitmap (%lu:%lu/%d) %s\n", __func__, - __LINE__, ppe_id, thread_id, cpu, ps3_result(result)); -} diff --git a/trunk/arch/powerpc/platforms/ps3/mm.c b/trunk/arch/powerpc/platforms/ps3/mm.c index 7bb3e1620974..f8a3e206c584 100644 --- a/trunk/arch/powerpc/platforms/ps3/mm.c +++ b/trunk/arch/powerpc/platforms/ps3/mm.c @@ -30,9 +30,9 @@ #include "platform.h" #if defined(DEBUG) -#define DBG udbg_printf +#define DBG(fmt...) udbg_printf(fmt) #else -#define DBG pr_debug +#define DBG(fmt...) do{if(0)printk(fmt);}while(0) #endif enum { @@ -115,8 +115,7 @@ struct map { }; #define debug_dump_map(x) _debug_dump_map(x, __func__, __LINE__) -static void __maybe_unused _debug_dump_map(const struct map *m, - const char *func, int line) +static void _debug_dump_map(const struct map* m, const char* func, int line) { DBG("%s:%d: map.total = %lxh\n", func, line, m->total); DBG("%s:%d: map.rm.size = %lxh\n", func, line, m->rm.size); @@ -213,15 +212,9 @@ void __init ps3_mm_vas_create(unsigned long* htab_size) void ps3_mm_vas_destroy(void) { - int result; - - DBG("%s:%d: map.vas_id = %lu\n", __func__, __LINE__, map.vas_id); - if (map.vas_id) { - result = lv1_select_virtual_address_space(0); - BUG_ON(result); - result = lv1_destruct_virtual_address_space(map.vas_id); - BUG_ON(result); + lv1_select_virtual_address_space(0); + lv1_destruct_virtual_address_space(map.vas_id); map.vas_id = 0; } } @@ -239,7 +232,7 @@ void ps3_mm_vas_destroy(void) * @size is rounded down to a multiple of the vas large page size. */ -static int ps3_mm_region_create(struct mem_region *r, unsigned long size) +int ps3_mm_region_create(struct mem_region *r, unsigned long size) { int result; unsigned long muid; @@ -280,14 +273,10 @@ static int ps3_mm_region_create(struct mem_region *r, unsigned long size) * @r: pointer to struct mem_region */ -static void ps3_mm_region_destroy(struct mem_region *r) +void ps3_mm_region_destroy(struct mem_region *r) { - int result; - - DBG("%s:%d: r->base = %lxh\n", __func__, __LINE__, r->base); if (r->base) { - result = lv1_release_memory(r->base); - BUG_ON(result); + lv1_release_memory(r->base); r->size = r->base = r->offset = 0; map.total = map.rm.size; } @@ -340,34 +329,31 @@ core_initcall(ps3_mm_add_memory); /*============================================================================*/ /** - * dma_sb_lpar_to_bus - Translate an lpar address to ioc mapped bus address. + * dma_lpar_to_bus - Translate an lpar address to ioc mapped bus address. * @r: pointer to dma region structure * @lpar_addr: HV lpar address */ -static unsigned long dma_sb_lpar_to_bus(struct ps3_dma_region *r, +static unsigned long dma_lpar_to_bus(struct ps3_dma_region *r, unsigned long lpar_addr) { - if (lpar_addr >= map.rm.size) - lpar_addr -= map.r1.offset; - BUG_ON(lpar_addr < r->offset); - BUG_ON(lpar_addr >= r->offset + r->len); - return r->bus_addr + lpar_addr - r->offset; + BUG_ON(lpar_addr >= map.r1.base + map.r1.size); + return r->bus_addr + (lpar_addr <= map.rm.size ? lpar_addr + : lpar_addr - map.r1.offset); } #define dma_dump_region(_a) _dma_dump_region(_a, __func__, __LINE__) -static void __maybe_unused _dma_dump_region(const struct ps3_dma_region *r, - const char *func, int line) +static void _dma_dump_region(const struct ps3_dma_region *r, const char* func, + int line) { - DBG("%s:%d: dev %u:%u\n", func, line, r->dev->bus_id, - r->dev->dev_id); + DBG("%s:%d: dev %u:%u\n", func, line, r->did.bus_id, + r->did.dev_id); DBG("%s:%d: page_size %u\n", func, line, r->page_size); DBG("%s:%d: bus_addr %lxh\n", func, line, r->bus_addr); DBG("%s:%d: len %lxh\n", func, line, r->len); - DBG("%s:%d: offset %lxh\n", func, line, r->offset); } - /** +/** * dma_chunk - A chunk of dma pages mapped by the io controller. * @region - The dma region that owns this chunk. * @lpar_addr: Starting lpar address of the area to map. @@ -395,11 +381,10 @@ static void _dma_dump_chunk (const struct dma_chunk* c, const char* func, int line) { DBG("%s:%d: r.dev %u:%u\n", func, line, - c->region->dev->bus_id, c->region->dev->dev_id); + c->region->did.bus_id, c->region->did.dev_id); DBG("%s:%d: r.bus_addr %lxh\n", func, line, c->region->bus_addr); DBG("%s:%d: r.page_size %u\n", func, line, c->region->page_size); DBG("%s:%d: r.len %lxh\n", func, line, c->region->len); - DBG("%s:%d: r.offset %lxh\n", func, line, c->region->offset); DBG("%s:%d: c.lpar_addr %lxh\n", func, line, c->lpar_addr); DBG("%s:%d: c.bus_addr %lxh\n", func, line, c->bus_addr); DBG("%s:%d: c.len %lxh\n", func, line, c->len); @@ -410,68 +395,39 @@ static struct dma_chunk * dma_find_chunk(struct ps3_dma_region *r, { struct dma_chunk *c; unsigned long aligned_bus = _ALIGN_DOWN(bus_addr, 1 << r->page_size); - unsigned long aligned_len = _ALIGN_UP(len+bus_addr-aligned_bus, - 1 << r->page_size); + unsigned long aligned_len = _ALIGN_UP(len, 1 << r->page_size); list_for_each_entry(c, &r->chunk_list.head, link) { /* intersection */ - if (aligned_bus >= c->bus_addr && - aligned_bus + aligned_len <= c->bus_addr + c->len) + if (aligned_bus >= c->bus_addr + && aligned_bus < c->bus_addr + c->len + && aligned_bus + aligned_len <= c->bus_addr + c->len) { return c; - + } /* below */ - if (aligned_bus + aligned_len <= c->bus_addr) + if (aligned_bus + aligned_len <= c->bus_addr) { continue; - + } /* above */ - if (aligned_bus >= c->bus_addr + c->len) + if (aligned_bus >= c->bus_addr + c->len) { continue; + } /* we don't handle the multi-chunk case for now */ + dma_dump_chunk(c); BUG(); } return NULL; } -static struct dma_chunk *dma_find_chunk_lpar(struct ps3_dma_region *r, - unsigned long lpar_addr, unsigned long len) -{ - struct dma_chunk *c; - unsigned long aligned_lpar = _ALIGN_DOWN(lpar_addr, 1 << r->page_size); - unsigned long aligned_len = _ALIGN_UP(len + lpar_addr - aligned_lpar, - 1 << r->page_size); - - list_for_each_entry(c, &r->chunk_list.head, link) { - /* intersection */ - if (c->lpar_addr <= aligned_lpar && - aligned_lpar < c->lpar_addr + c->len) { - if (aligned_lpar + aligned_len <= c->lpar_addr + c->len) - return c; - else { - dma_dump_chunk(c); - BUG(); - } - } - /* below */ - if (aligned_lpar + aligned_len <= c->lpar_addr) { - continue; - } - /* above */ - if (c->lpar_addr + c->len <= aligned_lpar) { - continue; - } - } - return NULL; -} - -static int dma_sb_free_chunk(struct dma_chunk *c) +static int dma_free_chunk(struct dma_chunk *c) { int result = 0; if (c->bus_addr) { - result = lv1_unmap_device_dma_region(c->region->dev->bus_id, - c->region->dev->dev_id, c->bus_addr, c->len); + result = lv1_unmap_device_dma_region(c->region->did.bus_id, + c->region->did.dev_id, c->bus_addr, c->len); BUG_ON(result); } @@ -479,39 +435,8 @@ static int dma_sb_free_chunk(struct dma_chunk *c) return result; } -static int dma_ioc0_free_chunk(struct dma_chunk *c) -{ - int result = 0; - int iopage; - unsigned long offset; - struct ps3_dma_region *r = c->region; - - DBG("%s:start\n", __func__); - for (iopage = 0; iopage < (c->len >> r->page_size); iopage++) { - offset = (1 << r->page_size) * iopage; - /* put INVALID entry */ - result = lv1_put_iopte(0, - c->bus_addr + offset, - c->lpar_addr + offset, - r->ioid, - 0); - DBG("%s: bus=%#lx, lpar=%#lx, ioid=%d\n", __func__, - c->bus_addr + offset, - c->lpar_addr + offset, - r->ioid); - - if (result) { - DBG("%s:%d: lv1_put_iopte failed: %s\n", __func__, - __LINE__, ps3_result(result)); - } - } - kfree(c); - DBG("%s:end\n", __func__); - return result; -} - /** - * dma_sb_map_pages - Maps dma pages into the io controller bus address space. + * dma_map_pages - Maps dma pages into the io controller bus address space. * @r: Pointer to a struct ps3_dma_region. * @phys_addr: Starting physical address of the area to map. * @len: Length in bytes of the area to map. @@ -521,8 +446,8 @@ static int dma_ioc0_free_chunk(struct dma_chunk *c) * make the HV call to add the pages into the io controller address space. */ -static int dma_sb_map_pages(struct ps3_dma_region *r, unsigned long phys_addr, - unsigned long len, struct dma_chunk **c_out, u64 iopte_flag) +static int dma_map_pages(struct ps3_dma_region *r, unsigned long phys_addr, + unsigned long len, struct dma_chunk **c_out) { int result; struct dma_chunk *c; @@ -536,13 +461,13 @@ static int dma_sb_map_pages(struct ps3_dma_region *r, unsigned long phys_addr, c->region = r; c->lpar_addr = ps3_mm_phys_to_lpar(phys_addr); - c->bus_addr = dma_sb_lpar_to_bus(r, c->lpar_addr); + c->bus_addr = dma_lpar_to_bus(r, c->lpar_addr); c->len = len; - BUG_ON(iopte_flag != 0xf800000000000000UL); - result = lv1_map_device_dma_region(c->region->dev->bus_id, - c->region->dev->dev_id, c->lpar_addr, - c->bus_addr, c->len, iopte_flag); + result = lv1_map_device_dma_region(c->region->did.bus_id, + c->region->did.dev_id, c->lpar_addr, c->bus_addr, c->len, + 0xf800000000000000UL); + if (result) { DBG("%s:%d: lv1_map_device_dma_region failed: %s\n", __func__, __LINE__, ps3_result(result)); @@ -562,120 +487,26 @@ static int dma_sb_map_pages(struct ps3_dma_region *r, unsigned long phys_addr, return result; } -static int dma_ioc0_map_pages(struct ps3_dma_region *r, unsigned long phys_addr, - unsigned long len, struct dma_chunk **c_out, - u64 iopte_flag) -{ - int result; - struct dma_chunk *c, *last; - int iopage, pages; - unsigned long offset; - - DBG(KERN_ERR "%s: phy=%#lx, lpar%#lx, len=%#lx\n", __func__, - phys_addr, ps3_mm_phys_to_lpar(phys_addr), len); - c = kzalloc(sizeof(struct dma_chunk), GFP_ATOMIC); - - if (!c) { - result = -ENOMEM; - goto fail_alloc; - } - - c->region = r; - c->len = len; - c->lpar_addr = ps3_mm_phys_to_lpar(phys_addr); - /* allocate IO address */ - if (list_empty(&r->chunk_list.head)) { - /* first one */ - c->bus_addr = r->bus_addr; - } else { - /* derive from last bus addr*/ - last = list_entry(r->chunk_list.head.next, - struct dma_chunk, link); - c->bus_addr = last->bus_addr + last->len; - DBG("%s: last bus=%#lx, len=%#lx\n", __func__, - last->bus_addr, last->len); - } - - /* FIXME: check whether length exceeds region size */ - - /* build ioptes for the area */ - pages = len >> r->page_size; - DBG("%s: pgsize=%#x len=%#lx pages=%#x iopteflag=%#lx\n", __func__, - r->page_size, r->len, pages, iopte_flag); - for (iopage = 0; iopage < pages; iopage++) { - offset = (1 << r->page_size) * iopage; - result = lv1_put_iopte(0, - c->bus_addr + offset, - c->lpar_addr + offset, - r->ioid, - iopte_flag); - if (result) { - printk(KERN_WARNING "%s:%d: lv1_map_device_dma_region " - "failed: %s\n", __func__, __LINE__, - ps3_result(result)); - goto fail_map; - } - DBG("%s: pg=%d bus=%#lx, lpar=%#lx, ioid=%#x\n", __func__, - iopage, c->bus_addr + offset, c->lpar_addr + offset, - r->ioid); - } - - /* be sure that last allocated one is inserted at head */ - list_add(&c->link, &r->chunk_list.head); - - *c_out = c; - DBG("%s: end\n", __func__); - return 0; - -fail_map: - for (iopage--; 0 <= iopage; iopage--) { - lv1_put_iopte(0, - c->bus_addr + offset, - c->lpar_addr + offset, - r->ioid, - 0); - } - kfree(c); -fail_alloc: - *c_out = NULL; - return result; -} - /** - * dma_sb_region_create - Create a device dma region. + * dma_region_create - Create a device dma region. * @r: Pointer to a struct ps3_dma_region. * * This is the lowest level dma region create routine, and is the one that * will make the HV call to create the region. */ -static int dma_sb_region_create(struct ps3_dma_region *r) +static int dma_region_create(struct ps3_dma_region* r) { int result; - pr_info(" -> %s:%d:\n", __func__, __LINE__); - - BUG_ON(!r); - - if (!r->dev->bus_id) { - pr_info("%s:%d: %u:%u no dma\n", __func__, __LINE__, - r->dev->bus_id, r->dev->dev_id); - return 0; - } - - DBG("%s:%u: len = 0x%lx, page_size = %u, offset = 0x%lx\n", __func__, - __LINE__, r->len, r->page_size, r->offset); - - BUG_ON(!r->len); - BUG_ON(!r->page_size); - BUG_ON(!r->region_ops); - + r->len = _ALIGN_UP(map.total, 1 << r->page_size); INIT_LIST_HEAD(&r->chunk_list.head); spin_lock_init(&r->chunk_list.lock); - result = lv1_allocate_device_dma_region(r->dev->bus_id, r->dev->dev_id, - roundup_pow_of_two(r->len), r->page_size, r->region_type, - &r->bus_addr); + result = lv1_allocate_device_dma_region(r->did.bus_id, r->did.dev_id, + r->len, r->page_size, r->region_type, &r->bus_addr); + + dma_dump_region(r); if (result) { DBG("%s:%d: lv1_allocate_device_dma_region failed: %s\n", @@ -686,27 +517,6 @@ static int dma_sb_region_create(struct ps3_dma_region *r) return result; } -static int dma_ioc0_region_create(struct ps3_dma_region *r) -{ - int result; - - INIT_LIST_HEAD(&r->chunk_list.head); - spin_lock_init(&r->chunk_list.lock); - - result = lv1_allocate_io_segment(0, - r->len, - r->page_size, - &r->bus_addr); - if (result) { - DBG("%s:%d: lv1_allocate_io_segment failed: %s\n", - __func__, __LINE__, ps3_result(result)); - r->len = r->bus_addr = 0; - } - DBG("%s: len=%#lx, pg=%d, bus=%#lx\n", __func__, - r->len, r->page_size, r->bus_addr); - return result; -} - /** * dma_region_free - Free a device dma region. * @r: Pointer to a struct ps3_dma_region. @@ -715,62 +525,31 @@ static int dma_ioc0_region_create(struct ps3_dma_region *r) * will make the HV call to free the region. */ -static int dma_sb_region_free(struct ps3_dma_region *r) +static int dma_region_free(struct ps3_dma_region* r) { int result; struct dma_chunk *c; struct dma_chunk *tmp; - BUG_ON(!r); - - if (!r->dev->bus_id) { - pr_info("%s:%d: %u:%u no dma\n", __func__, __LINE__, - r->dev->bus_id, r->dev->dev_id); - return 0; - } - list_for_each_entry_safe(c, tmp, &r->chunk_list.head, link) { list_del(&c->link); - dma_sb_free_chunk(c); + dma_free_chunk(c); } - result = lv1_free_device_dma_region(r->dev->bus_id, r->dev->dev_id, + result = lv1_free_device_dma_region(r->did.bus_id, r->did.dev_id, r->bus_addr); if (result) DBG("%s:%d: lv1_free_device_dma_region failed: %s\n", __func__, __LINE__, ps3_result(result)); - r->bus_addr = 0; - - return result; -} - -static int dma_ioc0_region_free(struct ps3_dma_region *r) -{ - int result; - struct dma_chunk *c, *n; - - DBG("%s: start\n", __func__); - list_for_each_entry_safe(c, n, &r->chunk_list.head, link) { - list_del(&c->link); - dma_ioc0_free_chunk(c); - } - - result = lv1_release_io_segment(0, r->bus_addr); - - if (result) - DBG("%s:%d: lv1_free_device_dma_region failed: %s\n", - __func__, __LINE__, ps3_result(result)); - - r->bus_addr = 0; - DBG("%s: end\n", __func__); + r->len = r->bus_addr = 0; return result; } /** - * dma_sb_map_area - Map an area of memory into a device dma region. + * dma_map_area - Map an area of memory into a device dma region. * @r: Pointer to a struct ps3_dma_region. * @virt_addr: Starting virtual address of the area to map. * @len: Length in bytes of the area to map. @@ -780,19 +559,16 @@ static int dma_ioc0_region_free(struct ps3_dma_region *r) * This is the common dma mapping routine. */ -static int dma_sb_map_area(struct ps3_dma_region *r, unsigned long virt_addr, - unsigned long len, unsigned long *bus_addr, - u64 iopte_flag) +static int dma_map_area(struct ps3_dma_region *r, unsigned long virt_addr, + unsigned long len, unsigned long *bus_addr) { int result; unsigned long flags; struct dma_chunk *c; unsigned long phys_addr = is_kernel_addr(virt_addr) ? __pa(virt_addr) : virt_addr; - unsigned long aligned_phys = _ALIGN_DOWN(phys_addr, 1 << r->page_size); - unsigned long aligned_len = _ALIGN_UP(len + phys_addr - aligned_phys, - 1 << r->page_size); - *bus_addr = dma_sb_lpar_to_bus(r, ps3_mm_phys_to_lpar(phys_addr)); + + *bus_addr = dma_lpar_to_bus(r, ps3_mm_phys_to_lpar(phys_addr)); if (!USE_DYNAMIC_DMA) { unsigned long lpar_addr = ps3_mm_phys_to_lpar(phys_addr); @@ -812,18 +588,17 @@ static int dma_sb_map_area(struct ps3_dma_region *r, unsigned long virt_addr, c = dma_find_chunk(r, *bus_addr, len); if (c) { - DBG("%s:%d: reusing mapped chunk", __func__, __LINE__); - dma_dump_chunk(c); c->usage_count++; spin_unlock_irqrestore(&r->chunk_list.lock, flags); return 0; } - result = dma_sb_map_pages(r, aligned_phys, aligned_len, &c, iopte_flag); + result = dma_map_pages(r, _ALIGN_DOWN(phys_addr, 1 << r->page_size), + _ALIGN_UP(len, 1 << r->page_size), &c); if (result) { *bus_addr = 0; - DBG("%s:%d: dma_sb_map_pages failed (%d)\n", + DBG("%s:%d: dma_map_pages failed (%d)\n", __func__, __LINE__, result); spin_unlock_irqrestore(&r->chunk_list.lock, flags); return result; @@ -835,57 +610,8 @@ static int dma_sb_map_area(struct ps3_dma_region *r, unsigned long virt_addr, return result; } -static int dma_ioc0_map_area(struct ps3_dma_region *r, unsigned long virt_addr, - unsigned long len, unsigned long *bus_addr, - u64 iopte_flag) -{ - int result; - unsigned long flags; - struct dma_chunk *c; - unsigned long phys_addr = is_kernel_addr(virt_addr) ? __pa(virt_addr) - : virt_addr; - unsigned long aligned_phys = _ALIGN_DOWN(phys_addr, 1 << r->page_size); - unsigned long aligned_len = _ALIGN_UP(len + phys_addr - aligned_phys, - 1 << r->page_size); - - DBG(KERN_ERR "%s: vaddr=%#lx, len=%#lx\n", __func__, - virt_addr, len); - DBG(KERN_ERR "%s: ph=%#lx a_ph=%#lx a_l=%#lx\n", __func__, - phys_addr, aligned_phys, aligned_len); - - spin_lock_irqsave(&r->chunk_list.lock, flags); - c = dma_find_chunk_lpar(r, ps3_mm_phys_to_lpar(phys_addr), len); - - if (c) { - /* FIXME */ - BUG(); - *bus_addr = c->bus_addr + phys_addr - aligned_phys; - c->usage_count++; - spin_unlock_irqrestore(&r->chunk_list.lock, flags); - return 0; - } - - result = dma_ioc0_map_pages(r, aligned_phys, aligned_len, &c, - iopte_flag); - - if (result) { - *bus_addr = 0; - DBG("%s:%d: dma_ioc0_map_pages failed (%d)\n", - __func__, __LINE__, result); - spin_unlock_irqrestore(&r->chunk_list.lock, flags); - return result; - } - *bus_addr = c->bus_addr + phys_addr - aligned_phys; - DBG("%s: va=%#lx pa=%#lx a_pa=%#lx bus=%#lx\n", __func__, - virt_addr, phys_addr, aligned_phys, *bus_addr); - c->usage_count = 1; - - spin_unlock_irqrestore(&r->chunk_list.lock, flags); - return result; -} - /** - * dma_sb_unmap_area - Unmap an area of memory from a device dma region. + * dma_unmap_area - Unmap an area of memory from a device dma region. * @r: Pointer to a struct ps3_dma_region. * @bus_addr: The starting ioc bus address of the area to unmap. * @len: Length in bytes of the area to unmap. @@ -893,7 +619,7 @@ static int dma_ioc0_map_area(struct ps3_dma_region *r, unsigned long virt_addr, * This is the common dma unmap routine. */ -static int dma_sb_unmap_area(struct ps3_dma_region *r, unsigned long bus_addr, +int dma_unmap_area(struct ps3_dma_region *r, unsigned long bus_addr, unsigned long len) { unsigned long flags; @@ -905,8 +631,7 @@ static int dma_sb_unmap_area(struct ps3_dma_region *r, unsigned long bus_addr, if (!c) { unsigned long aligned_bus = _ALIGN_DOWN(bus_addr, 1 << r->page_size); - unsigned long aligned_len = _ALIGN_UP(len + bus_addr - - aligned_bus, 1 << r->page_size); + unsigned long aligned_len = _ALIGN_UP(len, 1 << r->page_size); DBG("%s:%d: not found: bus_addr %lxh\n", __func__, __LINE__, bus_addr); DBG("%s:%d: not found: len %lxh\n", @@ -922,166 +647,94 @@ static int dma_sb_unmap_area(struct ps3_dma_region *r, unsigned long bus_addr, if (!c->usage_count) { list_del(&c->link); - dma_sb_free_chunk(c); + dma_free_chunk(c); } spin_unlock_irqrestore(&r->chunk_list.lock, flags); return 0; } -static int dma_ioc0_unmap_area(struct ps3_dma_region *r, - unsigned long bus_addr, unsigned long len) -{ - unsigned long flags; - struct dma_chunk *c; - - DBG("%s: start a=%#lx l=%#lx\n", __func__, bus_addr, len); - spin_lock_irqsave(&r->chunk_list.lock, flags); - c = dma_find_chunk(r, bus_addr, len); - - if (!c) { - unsigned long aligned_bus = _ALIGN_DOWN(bus_addr, - 1 << r->page_size); - unsigned long aligned_len = _ALIGN_UP(len + bus_addr - - aligned_bus, - 1 << r->page_size); - DBG("%s:%d: not found: bus_addr %lxh\n", - __func__, __LINE__, bus_addr); - DBG("%s:%d: not found: len %lxh\n", - __func__, __LINE__, len); - DBG("%s:%d: not found: aligned_bus %lxh\n", - __func__, __LINE__, aligned_bus); - DBG("%s:%d: not found: aligned_len %lxh\n", - __func__, __LINE__, aligned_len); - BUG(); - } - - c->usage_count--; - - if (!c->usage_count) { - list_del(&c->link); - dma_ioc0_free_chunk(c); - } - - spin_unlock_irqrestore(&r->chunk_list.lock, flags); - DBG("%s: end\n", __func__); - return 0; -} - /** - * dma_sb_region_create_linear - Setup a linear dma mapping for a device. + * dma_region_create_linear - Setup a linear dma maping for a device. * @r: Pointer to a struct ps3_dma_region. * * This routine creates an HV dma region for the device and maps all available * ram into the io controller bus address space. */ -static int dma_sb_region_create_linear(struct ps3_dma_region *r) +static int dma_region_create_linear(struct ps3_dma_region *r) { int result; - unsigned long virt_addr, len, tmp; - - if (r->len > 16*1024*1024) { /* FIXME: need proper fix */ - /* force 16M dma pages for linear mapping */ - if (r->page_size != PS3_DMA_16M) { - pr_info("%s:%d: forcing 16M pages for linear map\n", - __func__, __LINE__); - r->page_size = PS3_DMA_16M; - r->len = _ALIGN_UP(r->len, 1 << r->page_size); - } + unsigned long tmp; + + /* force 16M dma pages for linear mapping */ + + if (r->page_size != PS3_DMA_16M) { + pr_info("%s:%d: forcing 16M pages for linear map\n", + __func__, __LINE__); + r->page_size = PS3_DMA_16M; } - result = dma_sb_region_create(r); + result = dma_region_create(r); BUG_ON(result); - if (r->offset < map.rm.size) { - /* Map (part of) 1st RAM chunk */ - virt_addr = map.rm.base + r->offset; - len = map.rm.size - r->offset; - if (len > r->len) - len = r->len; - result = dma_sb_map_area(r, virt_addr, len, &tmp, - IOPTE_PP_W | IOPTE_PP_R | IOPTE_SO_RW | IOPTE_M); - BUG_ON(result); - } + result = dma_map_area(r, map.rm.base, map.rm.size, &tmp); + BUG_ON(result); - if (r->offset + r->len > map.rm.size) { - /* Map (part of) 2nd RAM chunk */ - virt_addr = USE_LPAR_ADDR ? map.r1.base : map.rm.size; - len = r->len; - if (r->offset >= map.rm.size) - virt_addr += r->offset - map.rm.size; - else - len -= map.rm.size - r->offset; - result = dma_sb_map_area(r, virt_addr, len, &tmp, - IOPTE_PP_W | IOPTE_PP_R | IOPTE_SO_RW | IOPTE_M); - BUG_ON(result); - } + if (USE_LPAR_ADDR) + result = dma_map_area(r, map.r1.base, map.r1.size, + &tmp); + else + result = dma_map_area(r, map.rm.size, map.r1.size, + &tmp); + + BUG_ON(result); return result; } /** - * dma_sb_region_free_linear - Free a linear dma mapping for a device. + * dma_region_free_linear - Free a linear dma mapping for a device. * @r: Pointer to a struct ps3_dma_region. * * This routine will unmap all mapped areas and free the HV dma region. */ -static int dma_sb_region_free_linear(struct ps3_dma_region *r) +static int dma_region_free_linear(struct ps3_dma_region *r) { int result; - unsigned long bus_addr, len, lpar_addr; - - if (r->offset < map.rm.size) { - /* Unmap (part of) 1st RAM chunk */ - lpar_addr = map.rm.base + r->offset; - len = map.rm.size - r->offset; - if (len > r->len) - len = r->len; - bus_addr = dma_sb_lpar_to_bus(r, lpar_addr); - result = dma_sb_unmap_area(r, bus_addr, len); - BUG_ON(result); - } - if (r->offset + r->len > map.rm.size) { - /* Unmap (part of) 2nd RAM chunk */ - lpar_addr = map.r1.base; - len = r->len; - if (r->offset >= map.rm.size) - lpar_addr += r->offset - map.rm.size; - else - len -= map.rm.size - r->offset; - bus_addr = dma_sb_lpar_to_bus(r, lpar_addr); - result = dma_sb_unmap_area(r, bus_addr, len); - BUG_ON(result); - } + result = dma_unmap_area(r, dma_lpar_to_bus(r, 0), map.rm.size); + BUG_ON(result); + + result = dma_unmap_area(r, dma_lpar_to_bus(r, map.r1.base), + map.r1.size); + BUG_ON(result); - result = dma_sb_region_free(r); + result = dma_region_free(r); BUG_ON(result); return result; } /** - * dma_sb_map_area_linear - Map an area of memory into a device dma region. + * dma_map_area_linear - Map an area of memory into a device dma region. * @r: Pointer to a struct ps3_dma_region. * @virt_addr: Starting virtual address of the area to map. * @len: Length in bytes of the area to map. * @bus_addr: A pointer to return the starting ioc bus address of the area to * map. * - * This routine just returns the corresponding bus address. Actual mapping + * This routine just returns the coresponding bus address. Actual mapping * occurs in dma_region_create_linear(). */ -static int dma_sb_map_area_linear(struct ps3_dma_region *r, - unsigned long virt_addr, unsigned long len, unsigned long *bus_addr, - u64 iopte_flag) +static int dma_map_area_linear(struct ps3_dma_region *r, + unsigned long virt_addr, unsigned long len, unsigned long *bus_addr) { unsigned long phys_addr = is_kernel_addr(virt_addr) ? __pa(virt_addr) : virt_addr; - *bus_addr = dma_sb_lpar_to_bus(r, ps3_mm_phys_to_lpar(phys_addr)); + *bus_addr = dma_lpar_to_bus(r, ps3_mm_phys_to_lpar(phys_addr)); return 0; } @@ -1091,98 +744,42 @@ static int dma_sb_map_area_linear(struct ps3_dma_region *r, * @bus_addr: The starting ioc bus address of the area to unmap. * @len: Length in bytes of the area to unmap. * - * This routine does nothing. Unmapping occurs in dma_sb_region_free_linear(). + * This routine does nothing. Unmapping occurs in dma_region_free_linear(). */ -static int dma_sb_unmap_area_linear(struct ps3_dma_region *r, +static int dma_unmap_area_linear(struct ps3_dma_region *r, unsigned long bus_addr, unsigned long len) { return 0; -}; - -static const struct ps3_dma_region_ops ps3_dma_sb_region_ops = { - .create = dma_sb_region_create, - .free = dma_sb_region_free, - .map = dma_sb_map_area, - .unmap = dma_sb_unmap_area -}; - -static const struct ps3_dma_region_ops ps3_dma_sb_region_linear_ops = { - .create = dma_sb_region_create_linear, - .free = dma_sb_region_free_linear, - .map = dma_sb_map_area_linear, - .unmap = dma_sb_unmap_area_linear -}; - -static const struct ps3_dma_region_ops ps3_dma_ioc0_region_ops = { - .create = dma_ioc0_region_create, - .free = dma_ioc0_region_free, - .map = dma_ioc0_map_area, - .unmap = dma_ioc0_unmap_area -}; - -int ps3_dma_region_init(struct ps3_system_bus_device *dev, - struct ps3_dma_region *r, enum ps3_dma_page_size page_size, - enum ps3_dma_region_type region_type, void *addr, unsigned long len) -{ - unsigned long lpar_addr; - - lpar_addr = addr ? ps3_mm_phys_to_lpar(__pa(addr)) : 0; - - r->dev = dev; - r->page_size = page_size; - r->region_type = region_type; - r->offset = lpar_addr; - if (r->offset >= map.rm.size) - r->offset -= map.r1.offset; - r->len = len ? len : _ALIGN_UP(map.total, 1 << r->page_size); - - switch (dev->dev_type) { - case PS3_DEVICE_TYPE_SB: - r->region_ops = (USE_DYNAMIC_DMA) - ? &ps3_dma_sb_region_ops - : &ps3_dma_sb_region_linear_ops; - break; - case PS3_DEVICE_TYPE_IOC0: - r->region_ops = &ps3_dma_ioc0_region_ops; - break; - default: - BUG(); - return -EINVAL; - } - return 0; } -EXPORT_SYMBOL(ps3_dma_region_init); int ps3_dma_region_create(struct ps3_dma_region *r) { - BUG_ON(!r); - BUG_ON(!r->region_ops); - BUG_ON(!r->region_ops->create); - return r->region_ops->create(r); + return (USE_DYNAMIC_DMA) + ? dma_region_create(r) + : dma_region_create_linear(r); } -EXPORT_SYMBOL(ps3_dma_region_create); int ps3_dma_region_free(struct ps3_dma_region *r) { - BUG_ON(!r); - BUG_ON(!r->region_ops); - BUG_ON(!r->region_ops->free); - return r->region_ops->free(r); + return (USE_DYNAMIC_DMA) + ? dma_region_free(r) + : dma_region_free_linear(r); } -EXPORT_SYMBOL(ps3_dma_region_free); int ps3_dma_map(struct ps3_dma_region *r, unsigned long virt_addr, - unsigned long len, unsigned long *bus_addr, - u64 iopte_flag) + unsigned long len, unsigned long *bus_addr) { - return r->region_ops->map(r, virt_addr, len, bus_addr, iopte_flag); + return (USE_DYNAMIC_DMA) + ? dma_map_area(r, virt_addr, len, bus_addr) + : dma_map_area_linear(r, virt_addr, len, bus_addr); } int ps3_dma_unmap(struct ps3_dma_region *r, unsigned long bus_addr, unsigned long len) { - return r->region_ops->unmap(r, bus_addr, len); + return (USE_DYNAMIC_DMA) ? dma_unmap_area(r, bus_addr, len) + : dma_unmap_area_linear(r, bus_addr, len); } /*============================================================================*/ @@ -1213,13 +810,12 @@ void __init ps3_mm_init(void) BUG_ON(map.rm.base); BUG_ON(!map.rm.size); + lmb_add(map.rm.base, map.rm.size); + lmb_analyze(); /* arrange to do this in ps3_mm_add_memory */ ps3_mm_region_create(&map.r1, map.total - map.rm.size); - /* correct map.total for the real total amount of memory we use */ - map.total = map.rm.size + map.r1.size; - DBG(" <- %s:%d\n", __func__, __LINE__); } diff --git a/trunk/arch/powerpc/platforms/ps3/os-area.c b/trunk/arch/powerpc/platforms/ps3/os-area.c index b70e474014f0..5c3da08bc0c4 100644 --- a/trunk/arch/powerpc/platforms/ps3/os-area.c +++ b/trunk/arch/powerpc/platforms/ps3/os-area.c @@ -133,7 +133,7 @@ struct saved_params { } static saved_params; #define dump_header(_a) _dump_header(_a, __func__, __LINE__) -static void _dump_header(const struct os_area_header *h, const char *func, +static void _dump_header(const struct os_area_header __iomem *h, const char* func, int line) { pr_debug("%s:%d: h.magic_num: '%s'\n", func, line, @@ -151,7 +151,7 @@ static void _dump_header(const struct os_area_header *h, const char *func, } #define dump_params(_a) _dump_params(_a, __func__, __LINE__) -static void _dump_params(const struct os_area_params *p, const char *func, +static void _dump_params(const struct os_area_params __iomem *p, const char* func, int line) { pr_debug("%s:%d: p.boot_flag: %u\n", func, line, p->boot_flag); diff --git a/trunk/arch/powerpc/platforms/ps3/platform.h b/trunk/arch/powerpc/platforms/ps3/platform.h index 87d52060fec0..ca04f03305c7 100644 --- a/trunk/arch/powerpc/platforms/ps3/platform.h +++ b/trunk/arch/powerpc/platforms/ps3/platform.h @@ -41,7 +41,6 @@ void ps3_mm_shutdown(void); /* irq */ void ps3_init_IRQ(void); -void ps3_shutdown_IRQ(int cpu); void __init ps3_register_ipi_debug_brk(unsigned int cpu, unsigned int virq); /* smp */ @@ -83,7 +82,6 @@ enum ps3_dev_type { PS3_DEV_TYPE_STOR_ROM = TYPE_ROM, /* 5 */ PS3_DEV_TYPE_SB_GPIO = 6, PS3_DEV_TYPE_STOR_FLASH = TYPE_RBC, /* 14 */ - PS3_DEV_TYPE_NOACCESS = 255, }; int ps3_repository_read_bus_str(unsigned int bus_index, const char *bus_str, @@ -131,28 +129,24 @@ int ps3_repository_read_dev_reg(unsigned int bus_index, /* repository bus enumerators */ struct ps3_repository_device { - enum ps3_bus_type bus_type; unsigned int bus_index; - unsigned int bus_id; - enum ps3_dev_type dev_type; unsigned int dev_index; - unsigned int dev_id; + struct ps3_device_id did; }; -static inline struct ps3_repository_device *ps3_repository_bump_device( - struct ps3_repository_device *repo) +int ps3_repository_find_device(enum ps3_bus_type bus_type, + enum ps3_dev_type dev_type, + const struct ps3_repository_device *start_dev, + struct ps3_repository_device *dev); +static inline int ps3_repository_find_first_device( + enum ps3_bus_type bus_type, enum ps3_dev_type dev_type, + struct ps3_repository_device *dev) { - repo->dev_index++; - return repo; + return ps3_repository_find_device(bus_type, dev_type, NULL, dev); } -int ps3_repository_find_device(struct ps3_repository_device *repo); -int ps3_repository_find_devices(enum ps3_bus_type bus_type, - int (*callback)(const struct ps3_repository_device *repo)); -int ps3_repository_find_bus(enum ps3_bus_type bus_type, unsigned int from, - unsigned int *bus_index); -int ps3_repository_find_interrupt(const struct ps3_repository_device *repo, +int ps3_repository_find_interrupt(const struct ps3_repository_device *dev, enum ps3_interrupt_type intr_type, unsigned int *interrupt_id); -int ps3_repository_find_reg(const struct ps3_repository_device *repo, +int ps3_repository_find_reg(const struct ps3_repository_device *dev, enum ps3_reg_type reg_type, u64 *bus_addr, u64 *len); /* repository block device info */ @@ -222,19 +216,4 @@ int ps3_repository_read_num_spu_resource_id(unsigned int *num_resource_id); int ps3_repository_read_spu_resource_id(unsigned int res_index, enum ps3_spu_resource_type* resource_type, unsigned int *resource_id); -/* repository vuart info */ - -int ps3_repository_read_vuart_av_port(unsigned int *port); -int ps3_repository_read_vuart_sysmgr_port(unsigned int *port); - -/* Page table entries */ -#define IOPTE_PP_W 0x8000000000000000ul /* protection: write */ -#define IOPTE_PP_R 0x4000000000000000ul /* protection: read */ -#define IOPTE_M 0x2000000000000000ul /* coherency required */ -#define IOPTE_SO_R 0x1000000000000000ul /* ordering: writes */ -#define IOPTE_SO_RW 0x1800000000000000ul /* ordering: r & w */ -#define IOPTE_RPN_Mask 0x07fffffffffff000ul /* RPN */ -#define IOPTE_H 0x0000000000000800ul /* cache hint */ -#define IOPTE_IOID_Mask 0x00000000000007fful /* ioid */ - #endif diff --git a/trunk/arch/powerpc/platforms/ps3/repository.c b/trunk/arch/powerpc/platforms/ps3/repository.c index 8cc37cfea0f2..ae586a0e5d3f 100644 --- a/trunk/arch/powerpc/platforms/ps3/repository.c +++ b/trunk/arch/powerpc/platforms/ps3/repository.c @@ -138,7 +138,7 @@ static int read_node(unsigned int lpar_id, u64 n1, u64 n2, u64 n3, u64 n4, pr_debug("%s:%d: lv1_get_repository_node_value failed: %s\n", __func__, __LINE__, ps3_result(result)); dump_node_name(lpar_id, n1, n2, n3, n4); - return -ENOENT; + return result; } dump_node(lpar_id, n1, n2, n3, n4, v1, v2); @@ -155,7 +155,7 @@ static int read_node(unsigned int lpar_id, u64 n1, u64 n2, u64 n3, u64 n4, pr_debug("%s:%d: warning: discarding non-zero v2: %016lx\n", __func__, __LINE__, v2); - return 0; + return result; } int ps3_repository_read_bus_str(unsigned int bus_index, const char *bus_str, @@ -314,140 +314,324 @@ int ps3_repository_read_dev_reg(unsigned int bus_index, reg_index, bus_addr, len); } +#if defined(DEBUG) +int ps3_repository_dump_resource_info(unsigned int bus_index, + unsigned int dev_index) +{ + int result = 0; + unsigned int res_index; + pr_debug(" -> %s:%d: (%u:%u)\n", __func__, __LINE__, + bus_index, dev_index); -int ps3_repository_find_device(struct ps3_repository_device *repo) -{ - int result; - struct ps3_repository_device tmp = *repo; - unsigned int num_dev; + for (res_index = 0; res_index < 10; res_index++) { + enum ps3_interrupt_type intr_type; + unsigned int interrupt_id; - BUG_ON(repo->bus_index > 10); - BUG_ON(repo->dev_index > 10); + result = ps3_repository_read_dev_intr(bus_index, dev_index, + res_index, &intr_type, &interrupt_id); - result = ps3_repository_read_bus_num_dev(tmp.bus_index, &num_dev); + if (result) { + if (result != LV1_NO_ENTRY) + pr_debug("%s:%d ps3_repository_read_dev_intr" + " (%u:%u) failed\n", __func__, __LINE__, + bus_index, dev_index); + break; + } - if (result) { - pr_debug("%s:%d read_bus_num_dev failed\n", __func__, __LINE__); - return result; + pr_debug("%s:%d (%u:%u) intr_type %u, interrupt_id %u\n", + __func__, __LINE__, bus_index, dev_index, intr_type, + interrupt_id); } - pr_debug("%s:%d: bus_type %u, bus_index %u, bus_id %u, num_dev %u\n", - __func__, __LINE__, tmp.bus_type, tmp.bus_index, tmp.bus_id, - num_dev); + for (res_index = 0; res_index < 10; res_index++) { + enum ps3_reg_type reg_type; + u64 bus_addr; + u64 len; - if (tmp.dev_index >= num_dev) { - pr_debug("%s:%d: no device found\n", __func__, __LINE__); - return -ENODEV; + result = ps3_repository_read_dev_reg(bus_index, dev_index, + res_index, ®_type, &bus_addr, &len); + + if (result) { + if (result != LV1_NO_ENTRY) + pr_debug("%s:%d ps3_repository_read_dev_reg" + " (%u:%u) failed\n", __func__, __LINE__, + bus_index, dev_index); + break; + } + + pr_debug("%s:%d (%u:%u) reg_type %u, bus_addr %lxh, len %lxh\n", + __func__, __LINE__, bus_index, dev_index, reg_type, + bus_addr, len); } - result = ps3_repository_read_dev_type(tmp.bus_index, tmp.dev_index, - &tmp.dev_type); + pr_debug(" <- %s:%d\n", __func__, __LINE__); + return result; +} + +static int dump_stor_dev_info(unsigned int bus_index, unsigned int dev_index) +{ + int result = 0; + unsigned int num_regions, region_index; + u64 port, blk_size, num_blocks; + + pr_debug(" -> %s:%d: (%u:%u)\n", __func__, __LINE__, + bus_index, dev_index); + result = ps3_repository_read_stor_dev_info(bus_index, dev_index, &port, + &blk_size, &num_blocks, &num_regions); if (result) { - pr_debug("%s:%d read_dev_type failed\n", __func__, __LINE__); - return result; + pr_debug("%s:%d ps3_repository_read_stor_dev_info" + " (%u:%u) failed\n", __func__, __LINE__, + bus_index, dev_index); + goto out; } - result = ps3_repository_read_dev_id(tmp.bus_index, tmp.dev_index, - &tmp.dev_id); + pr_debug("%s:%d (%u:%u): port %lu, blk_size %lu, num_blocks " + "%lu, num_regions %u\n", + __func__, __LINE__, bus_index, dev_index, port, + blk_size, num_blocks, num_regions); - if (result) { - pr_debug("%s:%d ps3_repository_read_dev_id failed\n", __func__, - __LINE__); - return result; + for (region_index = 0; region_index < num_regions; region_index++) { + unsigned int region_id; + u64 region_start, region_size; + + result = ps3_repository_read_stor_dev_region(bus_index, + dev_index, region_index, ®ion_id, ®ion_start, + ®ion_size); + if (result) { + pr_debug("%s:%d ps3_repository_read_stor_dev_region" + " (%u:%u) failed\n", __func__, __LINE__, + bus_index, dev_index); + break; + } + + pr_debug("%s:%d (%u:%u) region_id %u, start %lxh, size %lxh\n", + __func__, __LINE__, bus_index, dev_index, region_id, + region_start, region_size); } - pr_debug("%s:%d: found: dev_type %u, dev_index %u, dev_id %u\n", - __func__, __LINE__, tmp.dev_type, tmp.dev_index, tmp.dev_id); +out: + pr_debug(" <- %s:%d\n", __func__, __LINE__); + return result; +} + +static int dump_device_info(unsigned int bus_index, enum ps3_bus_type bus_type, + unsigned int num_dev) +{ + int result = 0; + unsigned int dev_index; + + pr_debug(" -> %s:%d: bus_%u\n", __func__, __LINE__, bus_index); + + for (dev_index = 0; dev_index < num_dev; dev_index++) { + enum ps3_dev_type dev_type; + unsigned int dev_id; + + result = ps3_repository_read_dev_type(bus_index, dev_index, + &dev_type); + + if (result) { + pr_debug("%s:%d ps3_repository_read_dev_type" + " (%u:%u) failed\n", __func__, __LINE__, + bus_index, dev_index); + break; + } + + result = ps3_repository_read_dev_id(bus_index, dev_index, + &dev_id); + + if (result) { + pr_debug("%s:%d ps3_repository_read_dev_id" + " (%u:%u) failed\n", __func__, __LINE__, + bus_index, dev_index); + continue; + } - *repo = tmp; - return 0; + pr_debug("%s:%d (%u:%u): dev_type %u, dev_id %u\n", __func__, + __LINE__, bus_index, dev_index, dev_type, dev_id); + + ps3_repository_dump_resource_info(bus_index, dev_index); + + if (bus_type == PS3_BUS_TYPE_STORAGE) + dump_stor_dev_info(bus_index, dev_index); + } + + pr_debug(" <- %s:%d\n", __func__, __LINE__); + return result; } -int __devinit ps3_repository_find_devices(enum ps3_bus_type bus_type, - int (*callback)(const struct ps3_repository_device *repo)) +int ps3_repository_dump_bus_info(void) { int result = 0; - struct ps3_repository_device repo; + unsigned int bus_index; - pr_debug(" -> %s:%d: find bus_type %u\n", __func__, __LINE__, bus_type); + pr_debug(" -> %s:%d\n", __func__, __LINE__); - for (repo.bus_index = 0; repo.bus_index < 10; repo.bus_index++) { + for (bus_index = 0; bus_index < 10; bus_index++) { + enum ps3_bus_type bus_type; + unsigned int bus_id; + unsigned int num_dev; - result = ps3_repository_read_bus_type(repo.bus_index, - &repo.bus_type); + result = ps3_repository_read_bus_type(bus_index, &bus_type); if (result) { pr_debug("%s:%d read_bus_type(%u) failed\n", - __func__, __LINE__, repo.bus_index); + __func__, __LINE__, bus_index); break; } - if (repo.bus_type != bus_type) { - pr_debug("%s:%d: skip, bus_type %u\n", __func__, - __LINE__, repo.bus_type); + result = ps3_repository_read_bus_id(bus_index, &bus_id); + + if (result) { + pr_debug("%s:%d read_bus_id(%u) failed\n", + __func__, __LINE__, bus_index); continue; } - result = ps3_repository_read_bus_id(repo.bus_index, - &repo.bus_id); + if (bus_index != bus_id) + pr_debug("%s:%d bus_index != bus_id\n", + __func__, __LINE__); + + result = ps3_repository_read_bus_num_dev(bus_index, &num_dev); if (result) { - pr_debug("%s:%d read_bus_id(%u) failed\n", - __func__, __LINE__, repo.bus_index); + pr_debug("%s:%d read_bus_num_dev(%u) failed\n", + __func__, __LINE__, bus_index); continue; } - for (repo.dev_index = 0; ; repo.dev_index++) { - result = ps3_repository_find_device(&repo); + pr_debug("%s:%d bus_%u: bus_type %u, bus_id %u, num_dev %u\n", + __func__, __LINE__, bus_index, bus_type, bus_id, + num_dev); - if (result == -ENODEV) { - result = 0; - break; - } else if (result) - break; + dump_device_info(bus_index, bus_type, num_dev); + } - result = callback(&repo); + pr_debug(" <- %s:%d\n", __func__, __LINE__); + return result; +} +#endif /* defined(DEBUG) */ + +static int find_device(unsigned int bus_index, unsigned int num_dev, + unsigned int start_dev_index, enum ps3_dev_type dev_type, + struct ps3_repository_device *dev) +{ + int result = 0; + unsigned int dev_index; - if (result) { - pr_debug("%s:%d: abort at callback\n", __func__, - __LINE__); - break; - } + pr_debug("%s:%d: find dev_type %u\n", __func__, __LINE__, dev_type); + + dev->dev_index = UINT_MAX; + + for (dev_index = start_dev_index; dev_index < num_dev; dev_index++) { + enum ps3_dev_type x; + + result = ps3_repository_read_dev_type(bus_index, dev_index, + &x); + + if (result) { + pr_debug("%s:%d read_dev_type failed\n", + __func__, __LINE__); + return result; } - break; + + if (x == dev_type) + break; } - pr_debug(" <- %s:%d\n", __func__, __LINE__); + if (dev_index == num_dev) + return -1; + + pr_debug("%s:%d: found dev_type %u at dev_index %u\n", + __func__, __LINE__, dev_type, dev_index); + + result = ps3_repository_read_dev_id(bus_index, dev_index, + &dev->did.dev_id); + + if (result) { + pr_debug("%s:%d read_dev_id failed\n", + __func__, __LINE__); + return result; + } + + dev->dev_index = dev_index; + + pr_debug("%s:%d found: dev_id %u\n", __func__, __LINE__, + dev->did.dev_id); + return result; } -int ps3_repository_find_bus(enum ps3_bus_type bus_type, unsigned int from, - unsigned int *bus_index) +int ps3_repository_find_device (enum ps3_bus_type bus_type, + enum ps3_dev_type dev_type, + const struct ps3_repository_device *start_dev, + struct ps3_repository_device *dev) { - unsigned int i; - enum ps3_bus_type type; - int error; + int result = 0; + unsigned int bus_index; + unsigned int num_dev; + + pr_debug("%s:%d: find bus_type %u, dev_type %u\n", __func__, __LINE__, + bus_type, dev_type); + + BUG_ON(start_dev && start_dev->bus_index > 10); + + for (bus_index = start_dev ? start_dev->bus_index : 0; bus_index < 10; + bus_index++) { + enum ps3_bus_type x; + + result = ps3_repository_read_bus_type(bus_index, &x); - for (i = from; i < 10; i++) { - error = ps3_repository_read_bus_type(i, &type); - if (error) { + if (result) { pr_debug("%s:%d read_bus_type failed\n", __func__, __LINE__); - *bus_index = UINT_MAX; - return error; - } - if (type == bus_type) { - *bus_index = i; - return 0; + dev->bus_index = UINT_MAX; + return result; } + if (x == bus_type) + break; + } + + if (bus_index >= 10) + return -ENODEV; + + pr_debug("%s:%d: found bus_type %u at bus_index %u\n", + __func__, __LINE__, bus_type, bus_index); + + result = ps3_repository_read_bus_num_dev(bus_index, &num_dev); + + if (result) { + pr_debug("%s:%d read_bus_num_dev failed\n", + __func__, __LINE__); + return result; } - *bus_index = UINT_MAX; - return -ENODEV; + + result = find_device(bus_index, num_dev, start_dev + ? start_dev->dev_index + 1 : 0, dev_type, dev); + + if (result) { + pr_debug("%s:%d get_did failed\n", __func__, __LINE__); + return result; + } + + result = ps3_repository_read_bus_id(bus_index, &dev->did.bus_id); + + if (result) { + pr_debug("%s:%d read_bus_id failed\n", + __func__, __LINE__); + return result; + } + + dev->bus_index = bus_index; + + pr_debug("%s:%d found: bus_id %u, dev_id %u\n", + __func__, __LINE__, dev->did.bus_id, dev->did.dev_id); + + return result; } -int ps3_repository_find_interrupt(const struct ps3_repository_device *repo, +int ps3_repository_find_interrupt(const struct ps3_repository_device *dev, enum ps3_interrupt_type intr_type, unsigned int *interrupt_id) { int result = 0; @@ -461,8 +645,8 @@ int ps3_repository_find_interrupt(const struct ps3_repository_device *repo, enum ps3_interrupt_type t; unsigned int id; - result = ps3_repository_read_dev_intr(repo->bus_index, - repo->dev_index, res_index, &t, &id); + result = ps3_repository_read_dev_intr(dev->bus_index, + dev->dev_index, res_index, &t, &id); if (result) { pr_debug("%s:%d read_dev_intr failed\n", @@ -485,7 +669,7 @@ int ps3_repository_find_interrupt(const struct ps3_repository_device *repo, return result; } -int ps3_repository_find_reg(const struct ps3_repository_device *repo, +int ps3_repository_find_reg(const struct ps3_repository_device *dev, enum ps3_reg_type reg_type, u64 *bus_addr, u64 *len) { int result = 0; @@ -500,8 +684,8 @@ int ps3_repository_find_reg(const struct ps3_repository_device *repo, u64 a; u64 l; - result = ps3_repository_read_dev_reg(repo->bus_index, - repo->dev_index, res_index, &t, &a, &l); + result = ps3_repository_read_dev_reg(dev->bus_index, + dev->dev_index, res_index, &t, &a, &l); if (result) { pr_debug("%s:%d read_dev_reg failed\n", @@ -781,36 +965,6 @@ int ps3_repository_read_boot_dat_size(unsigned int *size) return result; } -int ps3_repository_read_vuart_av_port(unsigned int *port) -{ - int result; - u64 v1; - - result = read_node(PS3_LPAR_ID_CURRENT, - make_first_field("bi", 0), - make_field("vir_uart", 0), - make_field("port", 0), - make_field("avset", 0), - &v1, 0); - *port = v1; - return result; -} - -int ps3_repository_read_vuart_sysmgr_port(unsigned int *port) -{ - int result; - u64 v1; - - result = read_node(PS3_LPAR_ID_CURRENT, - make_first_field("bi", 0), - make_field("vir_uart", 0), - make_field("port", 0), - make_field("sysmgr", 0), - &v1, 0); - *port = v1; - return result; -} - /** * ps3_repository_read_boot_dat_info - Get address and size of cell_ext_os_area. * address: lpar address of cell_ext_os_area @@ -872,205 +1026,3 @@ int ps3_repository_read_be_tb_freq(unsigned int be_index, u64 *tb_freq) return result ? result : ps3_repository_read_tb_freq(node_id, tb_freq); } - -#if defined(DEBUG) - -int ps3_repository_dump_resource_info(const struct ps3_repository_device *repo) -{ - int result = 0; - unsigned int res_index; - - pr_debug(" -> %s:%d: (%u:%u)\n", __func__, __LINE__, - repo->bus_index, repo->dev_index); - - for (res_index = 0; res_index < 10; res_index++) { - enum ps3_interrupt_type intr_type; - unsigned int interrupt_id; - - result = ps3_repository_read_dev_intr(repo->bus_index, - repo->dev_index, res_index, &intr_type, &interrupt_id); - - if (result) { - if (result != LV1_NO_ENTRY) - pr_debug("%s:%d ps3_repository_read_dev_intr" - " (%u:%u) failed\n", __func__, __LINE__, - repo->bus_index, repo->dev_index); - break; - } - - pr_debug("%s:%d (%u:%u) intr_type %u, interrupt_id %u\n", - __func__, __LINE__, repo->bus_index, repo->dev_index, - intr_type, interrupt_id); - } - - for (res_index = 0; res_index < 10; res_index++) { - enum ps3_reg_type reg_type; - u64 bus_addr; - u64 len; - - result = ps3_repository_read_dev_reg(repo->bus_index, - repo->dev_index, res_index, ®_type, &bus_addr, &len); - - if (result) { - if (result != LV1_NO_ENTRY) - pr_debug("%s:%d ps3_repository_read_dev_reg" - " (%u:%u) failed\n", __func__, __LINE__, - repo->bus_index, repo->dev_index); - break; - } - - pr_debug("%s:%d (%u:%u) reg_type %u, bus_addr %lxh, len %lxh\n", - __func__, __LINE__, repo->bus_index, repo->dev_index, - reg_type, bus_addr, len); - } - - pr_debug(" <- %s:%d\n", __func__, __LINE__); - return result; -} - -static int dump_stor_dev_info(struct ps3_repository_device *repo) -{ - int result = 0; - unsigned int num_regions, region_index; - u64 port, blk_size, num_blocks; - - pr_debug(" -> %s:%d: (%u:%u)\n", __func__, __LINE__, - repo->bus_index, repo->dev_index); - - result = ps3_repository_read_stor_dev_info(repo->bus_index, - repo->dev_index, &port, &blk_size, &num_blocks, &num_regions); - if (result) { - pr_debug("%s:%d ps3_repository_read_stor_dev_info" - " (%u:%u) failed\n", __func__, __LINE__, - repo->bus_index, repo->dev_index); - goto out; - } - - pr_debug("%s:%d (%u:%u): port %lu, blk_size %lu, num_blocks " - "%lu, num_regions %u\n", - __func__, __LINE__, repo->bus_index, repo->dev_index, port, - blk_size, num_blocks, num_regions); - - for (region_index = 0; region_index < num_regions; region_index++) { - unsigned int region_id; - u64 region_start, region_size; - - result = ps3_repository_read_stor_dev_region(repo->bus_index, - repo->dev_index, region_index, ®ion_id, - ®ion_start, ®ion_size); - if (result) { - pr_debug("%s:%d ps3_repository_read_stor_dev_region" - " (%u:%u) failed\n", __func__, __LINE__, - repo->bus_index, repo->dev_index); - break; - } - - pr_debug("%s:%d (%u:%u) region_id %u, start %lxh, size %lxh\n", - __func__, __LINE__, repo->bus_index, repo->dev_index, - region_id, region_start, region_size); - } - -out: - pr_debug(" <- %s:%d\n", __func__, __LINE__); - return result; -} - -static int dump_device_info(struct ps3_repository_device *repo, - unsigned int num_dev) -{ - int result = 0; - - pr_debug(" -> %s:%d: bus_%u\n", __func__, __LINE__, repo->bus_index); - - for (repo->dev_index = 0; repo->dev_index < num_dev; - repo->dev_index++) { - - result = ps3_repository_read_dev_type(repo->bus_index, - repo->dev_index, &repo->dev_type); - - if (result) { - pr_debug("%s:%d ps3_repository_read_dev_type" - " (%u:%u) failed\n", __func__, __LINE__, - repo->bus_index, repo->dev_index); - break; - } - - result = ps3_repository_read_dev_id(repo->bus_index, - repo->dev_index, &repo->dev_id); - - if (result) { - pr_debug("%s:%d ps3_repository_read_dev_id" - " (%u:%u) failed\n", __func__, __LINE__, - repo->bus_index, repo->dev_index); - continue; - } - - pr_debug("%s:%d (%u:%u): dev_type %u, dev_id %u\n", __func__, - __LINE__, repo->bus_index, repo->dev_index, - repo->dev_type, repo->dev_id); - - ps3_repository_dump_resource_info(repo); - - if (repo->bus_type == PS3_BUS_TYPE_STORAGE) - dump_stor_dev_info(repo); - } - - pr_debug(" <- %s:%d\n", __func__, __LINE__); - return result; -} - -int ps3_repository_dump_bus_info(void) -{ - int result = 0; - struct ps3_repository_device repo; - - pr_debug(" -> %s:%d\n", __func__, __LINE__); - - memset(&repo, 0, sizeof(repo)); - - for (repo.bus_index = 0; repo.bus_index < 10; repo.bus_index++) { - unsigned int num_dev; - - result = ps3_repository_read_bus_type(repo.bus_index, - &repo.bus_type); - - if (result) { - pr_debug("%s:%d read_bus_type(%u) failed\n", - __func__, __LINE__, repo.bus_index); - break; - } - - result = ps3_repository_read_bus_id(repo.bus_index, - &repo.bus_id); - - if (result) { - pr_debug("%s:%d read_bus_id(%u) failed\n", - __func__, __LINE__, repo.bus_index); - continue; - } - - if (repo.bus_index != repo.bus_id) - pr_debug("%s:%d bus_index != bus_id\n", - __func__, __LINE__); - - result = ps3_repository_read_bus_num_dev(repo.bus_index, - &num_dev); - - if (result) { - pr_debug("%s:%d read_bus_num_dev(%u) failed\n", - __func__, __LINE__, repo.bus_index); - continue; - } - - pr_debug("%s:%d bus_%u: bus_type %u, bus_id %u, num_dev %u\n", - __func__, __LINE__, repo.bus_index, repo.bus_type, - repo.bus_id, num_dev); - - dump_device_info(&repo, num_dev); - } - - pr_debug(" <- %s:%d\n", __func__, __LINE__); - return result; -} - -#endif /* defined(DEBUG) */ diff --git a/trunk/arch/powerpc/platforms/ps3/setup.c b/trunk/arch/powerpc/platforms/ps3/setup.c index aa05288de64e..935396766621 100644 --- a/trunk/arch/powerpc/platforms/ps3/setup.c +++ b/trunk/arch/powerpc/platforms/ps3/setup.c @@ -37,35 +37,27 @@ #include "platform.h" #if defined(DEBUG) -#define DBG udbg_printf +#define DBG(fmt...) udbg_printf(fmt) #else -#define DBG pr_debug +#define DBG(fmt...) do{if(0)printk(fmt);}while(0) #endif #if !defined(CONFIG_SMP) static void smp_send_stop(void) {} #endif -static union ps3_firmware_version ps3_firmware_version; - -void ps3_get_firmware_version(union ps3_firmware_version *v) -{ - *v = ps3_firmware_version; -} -EXPORT_SYMBOL_GPL(ps3_get_firmware_version); - -int ps3_compare_firmware_version(u16 major, u16 minor, u16 rev) +int ps3_get_firmware_version(union ps3_firmware_version *v) { - union ps3_firmware_version x; + int result = lv1_get_version_info(&v->raw); - x.pad = 0; - x.major = major; - x.minor = minor; - x.rev = rev; + if (result) { + v->raw = 0; + return -1; + } - return (ps3_firmware_version.raw - x.raw); + return result; } -EXPORT_SYMBOL_GPL(ps3_compare_firmware_version); +EXPORT_SYMBOL_GPL(ps3_get_firmware_version); static void ps3_power_save(void) { @@ -107,8 +99,7 @@ static void ps3_panic(char *str) while(1); } -#if defined(CONFIG_FB_PS3) || defined(CONFIG_FB_PS3_MODULE) || \ - defined(CONFIG_PS3_FLASH) || defined(CONFIG_PS3_FLASH_MODULE) +#ifdef CONFIG_FB_PS3 static void prealloc(struct ps3_prealloc *p) { if (!p->size) @@ -124,15 +115,12 @@ static void prealloc(struct ps3_prealloc *p) printk(KERN_INFO "%s: %lu bytes at %p\n", p->name, p->size, p->address); } -#endif -#if defined(CONFIG_FB_PS3) || defined(CONFIG_FB_PS3_MODULE) struct ps3_prealloc ps3fb_videomemory = { - .name = "ps3fb videomemory", - .size = CONFIG_FB_PS3_DEFAULT_SIZE_M*1024*1024, - .align = 1024*1024 /* the GPU requires 1 MiB alignment */ + .name = "ps3fb videomemory", + .size = CONFIG_FB_PS3_DEFAULT_SIZE_M*1024*1024, + .align = 1024*1024 /* the GPU requires 1 MiB alignment */ }; -EXPORT_SYMBOL_GPL(ps3fb_videomemory); #define prealloc_ps3fb_videomemory() prealloc(&ps3fb_videomemory) static int __init early_parse_ps3fb(char *p) @@ -149,30 +137,6 @@ early_param("ps3fb", early_parse_ps3fb); #define prealloc_ps3fb_videomemory() do { } while (0) #endif -#if defined(CONFIG_PS3_FLASH) || defined(CONFIG_PS3_FLASH_MODULE) -struct ps3_prealloc ps3flash_bounce_buffer = { - .name = "ps3flash bounce buffer", - .size = 256*1024, - .align = 256*1024 -}; -EXPORT_SYMBOL_GPL(ps3flash_bounce_buffer); -#define prealloc_ps3flash_bounce_buffer() prealloc(&ps3flash_bounce_buffer) - -static int __init early_parse_ps3flash(char *p) -{ - if (!p) - return 1; - - if (!strcmp(p, "off")) - ps3flash_bounce_buffer.size = 0; - - return 0; -} -early_param("ps3flash", early_parse_ps3flash); -#else -#define prealloc_ps3flash_bounce_buffer() do { } while (0) -#endif - static int ps3_set_dabr(u64 dabr) { enum {DABR_USER = 1, DABR_KERNEL = 2,}; @@ -182,13 +146,13 @@ static int ps3_set_dabr(u64 dabr) static void __init ps3_setup_arch(void) { + union ps3_firmware_version v; DBG(" -> %s:%d\n", __func__, __LINE__); - lv1_get_version_info(&ps3_firmware_version.raw); - printk(KERN_INFO "PS3 firmware version %u.%u.%u\n", - ps3_firmware_version.major, ps3_firmware_version.minor, - ps3_firmware_version.rev); + ps3_get_firmware_version(&v); + printk(KERN_INFO "PS3 firmware version %u.%u.%u\n", v.major, v.minor, + v.rev); ps3_spu_set_platform(); ps3_map_htab(); @@ -202,8 +166,6 @@ static void __init ps3_setup_arch(void) #endif prealloc_ps3fb_videomemory(); - prealloc_ps3flash_bounce_buffer(); - ppc_md.power_save = ps3_power_save; DBG(" <- %s:%d\n", __func__, __LINE__); @@ -222,7 +184,7 @@ static int __init ps3_probe(void) DBG(" -> %s:%d\n", __func__, __LINE__); dt_root = of_get_flat_dt_root(); - if (!of_flat_dt_is_compatible(dt_root, "sony,ps3")) + if (!of_flat_dt_is_compatible(dt_root, "PS3")) return 0; powerpc_firmware_features |= FW_FEATURE_PS3_POSSIBLE; @@ -239,12 +201,31 @@ static int __init ps3_probe(void) #if defined(CONFIG_KEXEC) static void ps3_kexec_cpu_down(int crash_shutdown, int secondary) { - int cpu = smp_processor_id(); + DBG(" -> %s:%d\n", __func__, __LINE__); + + if (secondary) { + int cpu; + for_each_online_cpu(cpu) + if (cpu) + ps3_smp_cleanup_cpu(cpu); + } else + ps3_smp_cleanup_cpu(0); + + DBG(" <- %s:%d\n", __func__, __LINE__); +} + +static void ps3_machine_kexec(struct kimage *image) +{ + unsigned long ppe_id; + + DBG(" -> %s:%d\n", __func__, __LINE__); - DBG(" -> %s:%d: (%d)\n", __func__, __LINE__, cpu); + lv1_get_logical_ppe_id(&ppe_id); + lv1_configure_irq_state_bitmap(ppe_id, 0, 0); + ps3_mm_shutdown(); + ps3_mm_vas_destroy(); - ps3_smp_cleanup_cpu(cpu); - ps3_shutdown_IRQ(cpu); + default_machine_kexec(image); DBG(" <- %s:%d\n", __func__, __LINE__); } @@ -266,7 +247,7 @@ define_machine(ps3) { .power_off = ps3_power_off, #if defined(CONFIG_KEXEC) .kexec_cpu_down = ps3_kexec_cpu_down, - .machine_kexec = default_machine_kexec, + .machine_kexec = ps3_machine_kexec, .machine_kexec_prepare = default_machine_kexec_prepare, .machine_crash_shutdown = default_machine_crash_shutdown, #endif diff --git a/trunk/arch/powerpc/platforms/ps3/smp.c b/trunk/arch/powerpc/platforms/ps3/smp.c index f0b12f212363..53416ec5198b 100644 --- a/trunk/arch/powerpc/platforms/ps3/smp.c +++ b/trunk/arch/powerpc/platforms/ps3/smp.c @@ -27,9 +27,9 @@ #include "platform.h" #if defined(DEBUG) -#define DBG udbg_printf +#define DBG(fmt...) udbg_printf(fmt) #else -#define DBG pr_debug +#define DBG(fmt...) do{if(0)printk(fmt);}while(0) #endif static irqreturn_t ipi_function_handler(int irq, void *msg) @@ -39,11 +39,11 @@ static irqreturn_t ipi_function_handler(int irq, void *msg) } /** - * ps3_ipi_virqs - a per cpu array of virqs for ipi use + * virqs - a per cpu array of virqs for ipi use */ #define MSG_COUNT 4 -static DEFINE_PER_CPU(unsigned int, ps3_ipi_virqs[MSG_COUNT]); +static DEFINE_PER_CPU(unsigned int, virqs[MSG_COUNT]); static const char *names[MSG_COUNT] = { "ipi call", @@ -62,7 +62,7 @@ static void do_message_pass(int target, int msg) return; } - virq = per_cpu(ps3_ipi_virqs, target)[msg]; + virq = per_cpu(virqs, target)[msg]; result = ps3_send_event_locally(virq); if (result) @@ -94,13 +94,13 @@ static int ps3_smp_probe(void) static void __init ps3_smp_setup_cpu(int cpu) { int result; - unsigned int *virqs = per_cpu(ps3_ipi_virqs, cpu); + unsigned int *virqs = per_cpu(virqs, cpu); int i; DBG(" -> %s:%d: (%d)\n", __func__, __LINE__, cpu); /* - * Check assumptions on ps3_ipi_virqs[] indexing. If this + * Check assumptions on virqs[] indexing. If this * check fails, then a different mapping of PPC_MSG_ * to index needs to be setup. */ @@ -132,13 +132,13 @@ static void __init ps3_smp_setup_cpu(int cpu) void ps3_smp_cleanup_cpu(int cpu) { - unsigned int *virqs = per_cpu(ps3_ipi_virqs, cpu); + unsigned int *virqs = per_cpu(virqs, cpu); int i; DBG(" -> %s:%d: (%d)\n", __func__, __LINE__, cpu); for (i = 0; i < MSG_COUNT; i++) { - /* Can't call free_irq from interrupt context. */ + free_irq(virqs[i], (void*)(long)i); ps3_event_receive_port_destroy(virqs[i]); virqs[i] = NO_IRQ; } diff --git a/trunk/arch/powerpc/platforms/ps3/spu.c b/trunk/arch/powerpc/platforms/ps3/spu.c index c7f734c89462..651437cb2c18 100644 --- a/trunk/arch/powerpc/platforms/ps3/spu.c +++ b/trunk/arch/powerpc/platforms/ps3/spu.c @@ -182,18 +182,15 @@ static int __init setup_areas(struct spu *spu) { struct table {char* name; unsigned long addr; unsigned long size;}; - spu_pdata(spu)->shadow = ioremap_flags(spu_pdata(spu)->shadow_addr, - sizeof(struct spe_shadow), - pgprot_val(PAGE_READONLY) | - _PAGE_NO_CACHE); + spu_pdata(spu)->shadow = __ioremap( + spu_pdata(spu)->shadow_addr, sizeof(struct spe_shadow), + pgprot_val(PAGE_READONLY) | _PAGE_NO_CACHE | _PAGE_GUARDED); if (!spu_pdata(spu)->shadow) { pr_debug("%s:%d: ioremap shadow failed\n", __func__, __LINE__); goto fail_ioremap; } - spu->local_store = (__force void *)ioremap_flags(spu->local_store_phys, - LS_SIZE, _PAGE_NO_CACHE); - + spu->local_store = ioremap(spu->local_store_phys, LS_SIZE); if (!spu->local_store) { pr_debug("%s:%d: ioremap local_store failed\n", __func__, __LINE__); @@ -202,7 +199,6 @@ static int __init setup_areas(struct spu *spu) spu->problem = ioremap(spu->problem_phys, sizeof(struct spu_problem)); - if (!spu->problem) { pr_debug("%s:%d: ioremap problem failed\n", __func__, __LINE__); goto fail_ioremap; @@ -210,7 +206,6 @@ static int __init setup_areas(struct spu *spu) spu->priv2 = ioremap(spu_pdata(spu)->priv2_addr, sizeof(struct spu_priv2)); - if (!spu->priv2) { pr_debug("%s:%d: ioremap priv2 failed\n", __func__, __LINE__); goto fail_ioremap; diff --git a/trunk/arch/powerpc/platforms/ps3/system-bus.c b/trunk/arch/powerpc/platforms/ps3/system-bus.c index 4bb634a17e43..6bda51027cc6 100644 --- a/trunk/arch/powerpc/platforms/ps3/system-bus.c +++ b/trunk/arch/powerpc/platforms/ps3/system-bus.c @@ -30,228 +30,22 @@ #include "platform.h" -static struct device ps3_system_bus = { - .bus_id = "ps3_system", -}; - -/* FIXME: need device usage counters! */ -struct { - struct mutex mutex; - int sb_11; /* usb 0 */ - int sb_12; /* usb 0 */ - int gpu; -} static usage_hack; - -static int ps3_is_device(struct ps3_system_bus_device *dev, - unsigned int bus_id, unsigned int dev_id) -{ - return dev->bus_id == bus_id && dev->dev_id == dev_id; -} - -static int ps3_open_hv_device_sb(struct ps3_system_bus_device *dev) -{ - int result; - - BUG_ON(!dev->bus_id); - mutex_lock(&usage_hack.mutex); - - if (ps3_is_device(dev, 1, 1)) { - usage_hack.sb_11++; - if (usage_hack.sb_11 > 1) { - result = 0; - goto done; - } - } - - if (ps3_is_device(dev, 1, 2)) { - usage_hack.sb_12++; - if (usage_hack.sb_12 > 1) { - result = 0; - goto done; - } - } - - result = lv1_open_device(dev->bus_id, dev->dev_id, 0); - - if (result) { - pr_debug("%s:%d: lv1_open_device failed: %s\n", __func__, - __LINE__, ps3_result(result)); - result = -EPERM; - } - -done: - mutex_unlock(&usage_hack.mutex); - return result; -} - -static int ps3_close_hv_device_sb(struct ps3_system_bus_device *dev) -{ - int result; - - BUG_ON(!dev->bus_id); - mutex_lock(&usage_hack.mutex); - - if (ps3_is_device(dev, 1, 1)) { - usage_hack.sb_11--; - if (usage_hack.sb_11) { - result = 0; - goto done; - } - } - - if (ps3_is_device(dev, 1, 2)) { - usage_hack.sb_12--; - if (usage_hack.sb_12) { - result = 0; - goto done; - } - } - - result = lv1_close_device(dev->bus_id, dev->dev_id); - BUG_ON(result); - -done: - mutex_unlock(&usage_hack.mutex); - return result; -} - -static int ps3_open_hv_device_gpu(struct ps3_system_bus_device *dev) -{ - int result; - - mutex_lock(&usage_hack.mutex); - - usage_hack.gpu++; - if (usage_hack.gpu > 1) { - result = 0; - goto done; - } - - result = lv1_gpu_open(0); - - if (result) { - pr_debug("%s:%d: lv1_gpu_open failed: %s\n", __func__, - __LINE__, ps3_result(result)); - result = -EPERM; - } - -done: - mutex_unlock(&usage_hack.mutex); - return result; -} - -static int ps3_close_hv_device_gpu(struct ps3_system_bus_device *dev) -{ - int result; - - mutex_lock(&usage_hack.mutex); - - usage_hack.gpu--; - if (usage_hack.gpu) { - result = 0; - goto done; - } - - result = lv1_gpu_close(); - BUG_ON(result); - -done: - mutex_unlock(&usage_hack.mutex); - return result; -} - -int ps3_open_hv_device(struct ps3_system_bus_device *dev) -{ - BUG_ON(!dev); - pr_debug("%s:%d: match_id: %u\n", __func__, __LINE__, dev->match_id); - - switch (dev->match_id) { - case PS3_MATCH_ID_EHCI: - case PS3_MATCH_ID_OHCI: - case PS3_MATCH_ID_GELIC: - case PS3_MATCH_ID_STOR_DISK: - case PS3_MATCH_ID_STOR_ROM: - case PS3_MATCH_ID_STOR_FLASH: - return ps3_open_hv_device_sb(dev); - - case PS3_MATCH_ID_SOUND: - case PS3_MATCH_ID_GRAPHICS: - return ps3_open_hv_device_gpu(dev); - - case PS3_MATCH_ID_AV_SETTINGS: - case PS3_MATCH_ID_SYSTEM_MANAGER: - pr_debug("%s:%d: unsupported match_id: %u\n", __func__, - __LINE__, dev->match_id); - pr_debug("%s:%d: bus_id: %u\n", __func__, - __LINE__, dev->bus_id); - BUG(); - return -EINVAL; - - default: - break; - } - - pr_debug("%s:%d: unknown match_id: %u\n", __func__, __LINE__, - dev->match_id); - BUG(); - return -ENODEV; -} -EXPORT_SYMBOL_GPL(ps3_open_hv_device); - -int ps3_close_hv_device(struct ps3_system_bus_device *dev) -{ - BUG_ON(!dev); - pr_debug("%s:%d: match_id: %u\n", __func__, __LINE__, dev->match_id); - - switch (dev->match_id) { - case PS3_MATCH_ID_EHCI: - case PS3_MATCH_ID_OHCI: - case PS3_MATCH_ID_GELIC: - case PS3_MATCH_ID_STOR_DISK: - case PS3_MATCH_ID_STOR_ROM: - case PS3_MATCH_ID_STOR_FLASH: - return ps3_close_hv_device_sb(dev); - - case PS3_MATCH_ID_SOUND: - case PS3_MATCH_ID_GRAPHICS: - return ps3_close_hv_device_gpu(dev); - - case PS3_MATCH_ID_AV_SETTINGS: - case PS3_MATCH_ID_SYSTEM_MANAGER: - pr_debug("%s:%d: unsupported match_id: %u\n", __func__, - __LINE__, dev->match_id); - pr_debug("%s:%d: bus_id: %u\n", __func__, - __LINE__, dev->bus_id); - BUG(); - return -EINVAL; - - default: - break; - } - - pr_debug("%s:%d: unknown match_id: %u\n", __func__, __LINE__, - dev->match_id); - BUG(); - return -ENODEV; -} -EXPORT_SYMBOL_GPL(ps3_close_hv_device); - #define dump_mmio_region(_a) _dump_mmio_region(_a, __func__, __LINE__) static void _dump_mmio_region(const struct ps3_mmio_region* r, const char* func, int line) { - pr_debug("%s:%d: dev %u:%u\n", func, line, r->dev->bus_id, - r->dev->dev_id); + pr_debug("%s:%d: dev %u:%u\n", func, line, r->did.bus_id, + r->did.dev_id); pr_debug("%s:%d: bus_addr %lxh\n", func, line, r->bus_addr); pr_debug("%s:%d: len %lxh\n", func, line, r->len); pr_debug("%s:%d: lpar_addr %lxh\n", func, line, r->lpar_addr); } -static int ps3_sb_mmio_region_create(struct ps3_mmio_region *r) +int ps3_mmio_region_create(struct ps3_mmio_region *r) { int result; - result = lv1_map_device_mmio_region(r->dev->bus_id, r->dev->dev_id, + result = lv1_map_device_mmio_region(r->did.bus_id, r->did.dev_id, r->bus_addr, r->len, r->page_size, &r->lpar_addr); if (result) { @@ -263,26 +57,13 @@ static int ps3_sb_mmio_region_create(struct ps3_mmio_region *r) dump_mmio_region(r); return result; } - -static int ps3_ioc0_mmio_region_create(struct ps3_mmio_region *r) -{ - /* device specific; do nothing currently */ - return 0; -} - -int ps3_mmio_region_create(struct ps3_mmio_region *r) -{ - return r->mmio_ops->create(r); -} EXPORT_SYMBOL_GPL(ps3_mmio_region_create); -static int ps3_sb_free_mmio_region(struct ps3_mmio_region *r) +int ps3_free_mmio_region(struct ps3_mmio_region *r) { int result; - dump_mmio_region(r); -; - result = lv1_unmap_device_mmio_region(r->dev->bus_id, r->dev->dev_id, + result = lv1_unmap_device_mmio_region(r->did.bus_id, r->did.dev_id, r->lpar_addr); if (result) @@ -292,60 +73,14 @@ static int ps3_sb_free_mmio_region(struct ps3_mmio_region *r) r->lpar_addr = 0; return result; } - -static int ps3_ioc0_free_mmio_region(struct ps3_mmio_region *r) -{ - /* device specific; do nothing currently */ - return 0; -} - - -int ps3_free_mmio_region(struct ps3_mmio_region *r) -{ - return r->mmio_ops->free(r); -} - EXPORT_SYMBOL_GPL(ps3_free_mmio_region); -static const struct ps3_mmio_region_ops ps3_mmio_sb_region_ops = { - .create = ps3_sb_mmio_region_create, - .free = ps3_sb_free_mmio_region -}; - -static const struct ps3_mmio_region_ops ps3_mmio_ioc0_region_ops = { - .create = ps3_ioc0_mmio_region_create, - .free = ps3_ioc0_free_mmio_region -}; - -int ps3_mmio_region_init(struct ps3_system_bus_device *dev, - struct ps3_mmio_region *r, unsigned long bus_addr, unsigned long len, - enum ps3_mmio_page_size page_size) -{ - r->dev = dev; - r->bus_addr = bus_addr; - r->len = len; - r->page_size = page_size; - switch (dev->dev_type) { - case PS3_DEVICE_TYPE_SB: - r->mmio_ops = &ps3_mmio_sb_region_ops; - break; - case PS3_DEVICE_TYPE_IOC0: - r->mmio_ops = &ps3_mmio_ioc0_region_ops; - break; - default: - BUG(); - return -EINVAL; - } - return 0; -} -EXPORT_SYMBOL_GPL(ps3_mmio_region_init); - static int ps3_system_bus_match(struct device *_dev, struct device_driver *_drv) { int result; - struct ps3_system_bus_driver *drv = ps3_drv_to_system_bus_drv(_drv); - struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev); + struct ps3_system_bus_driver *drv = to_ps3_system_bus_driver(_drv); + struct ps3_system_bus_device *dev = to_ps3_system_bus_device(_dev); result = dev->match_id == drv->match_id; @@ -357,14 +92,32 @@ static int ps3_system_bus_match(struct device *_dev, static int ps3_system_bus_probe(struct device *_dev) { - int result = 0; - struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev); - struct ps3_system_bus_driver *drv; + int result; + struct ps3_system_bus_device *dev = to_ps3_system_bus_device(_dev); + struct ps3_system_bus_driver *drv = + to_ps3_system_bus_driver(_dev->driver); + + result = lv1_open_device(dev->did.bus_id, dev->did.dev_id, 0); + + if (result) { + pr_debug("%s:%d: lv1_open_device failed (%d)\n", + __func__, __LINE__, result); + result = -EACCES; + goto clean_none; + } + + if (dev->d_region->did.bus_id) { + result = ps3_dma_region_create(dev->d_region); - BUG_ON(!dev); - pr_info(" -> %s:%d: %s\n", __func__, __LINE__, _dev->bus_id); + if (result) { + pr_debug("%s:%d: ps3_dma_region_create failed (%d)\n", + __func__, __LINE__, result); + BUG_ON("check region type"); + result = -EINVAL; + goto clean_device; + } + } - drv = ps3_system_bus_dev_to_system_bus_drv(dev); BUG_ON(!drv); if (drv->probe) @@ -373,127 +126,56 @@ static int ps3_system_bus_probe(struct device *_dev) pr_info("%s:%d: %s no probe method\n", __func__, __LINE__, dev->core.bus_id); - pr_info(" <- %s:%d: %s\n", __func__, __LINE__, dev->core.bus_id); - return result; -} - -static int ps3_system_bus_remove(struct device *_dev) -{ - int result = 0; - struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev); - struct ps3_system_bus_driver *drv; - - BUG_ON(!dev); - pr_info(" -> %s:%d: %s\n", __func__, __LINE__, _dev->bus_id); - - drv = ps3_system_bus_dev_to_system_bus_drv(dev); - BUG_ON(!drv); + if (result) { + pr_debug("%s:%d: drv->probe failed\n", __func__, __LINE__); + goto clean_dma; + } - if (drv->remove) - result = drv->remove(dev); - else - dev_dbg(&dev->core, "%s:%d %s: no remove method\n", - __func__, __LINE__, drv->core.name); + return result; - pr_info(" <- %s:%d: %s\n", __func__, __LINE__, dev->core.bus_id); +clean_dma: + ps3_dma_region_free(dev->d_region); +clean_device: + lv1_close_device(dev->did.bus_id, dev->did.dev_id); +clean_none: return result; } -static void ps3_system_bus_shutdown(struct device *_dev) +static int ps3_system_bus_remove(struct device *_dev) { - struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev); - struct ps3_system_bus_driver *drv; - - BUG_ON(!dev); - - dev_dbg(&dev->core, " -> %s:%d: match_id %d\n", __func__, __LINE__, - dev->match_id); + struct ps3_system_bus_device *dev = to_ps3_system_bus_device(_dev); + struct ps3_system_bus_driver *drv = + to_ps3_system_bus_driver(_dev->driver); - if (!dev->core.driver) { - dev_dbg(&dev->core, "%s:%d: no driver bound\n", __func__, - __LINE__); - return; - } - - drv = ps3_system_bus_dev_to_system_bus_drv(dev); - - BUG_ON(!drv); - - dev_dbg(&dev->core, "%s:%d: %s -> %s\n", __func__, __LINE__, - dev->core.bus_id, drv->core.name); - - if (drv->shutdown) - drv->shutdown(dev); - else if (drv->remove) { - dev_dbg(&dev->core, "%s:%d %s: no shutdown, calling remove\n", - __func__, __LINE__, drv->core.name); + if (drv->remove) drv->remove(dev); - } else { - dev_dbg(&dev->core, "%s:%d %s: no shutdown method\n", - __func__, __LINE__, drv->core.name); - BUG(); - } - - dev_dbg(&dev->core, " <- %s:%d\n", __func__, __LINE__); -} - -static int ps3_system_bus_uevent(struct device *_dev, char **envp, - int num_envp, char *buffer, int buffer_size) -{ - struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev); - int i = 0, length = 0; + else + pr_info("%s:%d: %s no remove method\n", __func__, __LINE__, + dev->core.bus_id); - if (add_uevent_var(envp, num_envp, &i, buffer, buffer_size, - &length, "MODALIAS=ps3:%d", - dev->match_id)) - return -ENOMEM; + ps3_dma_region_free(dev->d_region); + ps3_free_mmio_region(dev->m_region); + lv1_close_device(dev->did.bus_id, dev->did.dev_id); - envp[i] = NULL; return 0; } -static ssize_t modalias_show(struct device *_dev, struct device_attribute *a, - char *buf) -{ - struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev); - int len = snprintf(buf, PAGE_SIZE, "ps3:%d\n", dev->match_id); - - return (len >= PAGE_SIZE) ? (PAGE_SIZE - 1) : len; -} - -static struct device_attribute ps3_system_bus_dev_attrs[] = { - __ATTR_RO(modalias), - __ATTR_NULL, -}; - struct bus_type ps3_system_bus_type = { .name = "ps3_system_bus", .match = ps3_system_bus_match, - .uevent = ps3_system_bus_uevent, .probe = ps3_system_bus_probe, .remove = ps3_system_bus_remove, - .shutdown = ps3_system_bus_shutdown, - .dev_attrs = ps3_system_bus_dev_attrs, }; -static int __init ps3_system_bus_init(void) +int __init ps3_system_bus_init(void) { int result; if (!firmware_has_feature(FW_FEATURE_PS3_LV1)) return -ENODEV; - pr_debug(" -> %s:%d\n", __func__, __LINE__); - - mutex_init(&usage_hack.mutex); - - result = device_register(&ps3_system_bus); - BUG_ON(result); - result = bus_register(&ps3_system_bus_type); BUG_ON(result); - - pr_debug(" <- %s:%d\n", __func__, __LINE__); return result; } @@ -503,13 +185,16 @@ core_initcall(ps3_system_bus_init); * Returns the virtual address of the buffer and sets dma_handle * to the dma address (mapping) of the first page. */ + static void * ps3_alloc_coherent(struct device *_dev, size_t size, - dma_addr_t *dma_handle, gfp_t flag) + dma_addr_t *dma_handle, gfp_t flag) { int result; - struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev); + struct ps3_system_bus_device *dev = to_ps3_system_bus_device(_dev); unsigned long virt_addr; + BUG_ON(!dev->d_region->bus_addr); + flag &= ~(__GFP_DMA | __GFP_HIGHMEM); flag |= __GFP_ZERO; @@ -520,8 +205,7 @@ static void * ps3_alloc_coherent(struct device *_dev, size_t size, goto clean_none; } - result = ps3_dma_map(dev->d_region, virt_addr, size, dma_handle, - IOPTE_PP_W | IOPTE_PP_R | IOPTE_SO_RW | IOPTE_M); + result = ps3_dma_map(dev->d_region, virt_addr, size, dma_handle); if (result) { pr_debug("%s:%d: ps3_dma_map failed (%d)\n", @@ -542,7 +226,7 @@ static void * ps3_alloc_coherent(struct device *_dev, size_t size, static void ps3_free_coherent(struct device *_dev, size_t size, void *vaddr, dma_addr_t dma_handle) { - struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev); + struct ps3_system_bus_device *dev = to_ps3_system_bus_device(_dev); ps3_dma_unmap(dev->d_region, dma_handle, size); free_pages((unsigned long)vaddr, get_order(size)); @@ -555,16 +239,15 @@ static void ps3_free_coherent(struct device *_dev, size_t size, void *vaddr, * byte within the page as vaddr. */ -static dma_addr_t ps3_sb_map_single(struct device *_dev, void *ptr, size_t size, +static dma_addr_t ps3_map_single(struct device *_dev, void *ptr, size_t size, enum dma_data_direction direction) { - struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev); + struct ps3_system_bus_device *dev = to_ps3_system_bus_device(_dev); int result; unsigned long bus_addr; result = ps3_dma_map(dev->d_region, (unsigned long)ptr, size, - &bus_addr, - IOPTE_PP_R | IOPTE_PP_W | IOPTE_SO_RW | IOPTE_M); + &bus_addr); if (result) { pr_debug("%s:%d: ps3_dma_map failed (%d)\n", @@ -574,44 +257,10 @@ static dma_addr_t ps3_sb_map_single(struct device *_dev, void *ptr, size_t size, return bus_addr; } -static dma_addr_t ps3_ioc0_map_single(struct device *_dev, void *ptr, - size_t size, - enum dma_data_direction direction) -{ - struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev); - int result; - unsigned long bus_addr; - u64 iopte_flag; - - iopte_flag = IOPTE_M; - switch (direction) { - case DMA_BIDIRECTIONAL: - iopte_flag |= IOPTE_PP_R | IOPTE_PP_W | IOPTE_SO_RW; - break; - case DMA_TO_DEVICE: - iopte_flag |= IOPTE_PP_R | IOPTE_SO_R; - break; - case DMA_FROM_DEVICE: - iopte_flag |= IOPTE_PP_W | IOPTE_SO_RW; - break; - default: - /* not happned */ - BUG(); - }; - result = ps3_dma_map(dev->d_region, (unsigned long)ptr, size, - &bus_addr, iopte_flag); - - if (result) { - pr_debug("%s:%d: ps3_dma_map failed (%d)\n", - __func__, __LINE__, result); - } - return bus_addr; -} - static void ps3_unmap_single(struct device *_dev, dma_addr_t dma_addr, size_t size, enum dma_data_direction direction) { - struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev); + struct ps3_system_bus_device *dev = to_ps3_system_bus_device(_dev); int result; result = ps3_dma_unmap(dev->d_region, dma_addr, size); @@ -622,20 +271,20 @@ static void ps3_unmap_single(struct device *_dev, dma_addr_t dma_addr, } } -static int ps3_sb_map_sg(struct device *_dev, struct scatterlist *sg, int nents, +static int ps3_map_sg(struct device *_dev, struct scatterlist *sg, int nents, enum dma_data_direction direction) { #if defined(CONFIG_PS3_DYNAMIC_DMA) BUG_ON("do"); return -EPERM; #else - struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev); + struct ps3_system_bus_device *dev = to_ps3_system_bus_device(_dev); int i; for (i = 0; i < nents; i++, sg++) { int result = ps3_dma_map(dev->d_region, page_to_phys(sg->page) + sg->offset, sg->length, - &sg->dma_address, 0); + &sg->dma_address); if (result) { pr_debug("%s:%d: ps3_dma_map failed (%d)\n", @@ -650,15 +299,7 @@ static int ps3_sb_map_sg(struct device *_dev, struct scatterlist *sg, int nents, #endif } -static int ps3_ioc0_map_sg(struct device *_dev, struct scatterlist *sg, - int nents, - enum dma_data_direction direction) -{ - BUG(); - return 0; -} - -static void ps3_sb_unmap_sg(struct device *_dev, struct scatterlist *sg, +static void ps3_unmap_sg(struct device *_dev, struct scatterlist *sg, int nents, enum dma_data_direction direction) { #if defined(CONFIG_PS3_DYNAMIC_DMA) @@ -666,34 +307,18 @@ static void ps3_sb_unmap_sg(struct device *_dev, struct scatterlist *sg, #endif } -static void ps3_ioc0_unmap_sg(struct device *_dev, struct scatterlist *sg, - int nents, enum dma_data_direction direction) -{ - BUG(); -} - static int ps3_dma_supported(struct device *_dev, u64 mask) { return mask >= DMA_32BIT_MASK; } -static struct dma_mapping_ops ps3_sb_dma_ops = { +static struct dma_mapping_ops ps3_dma_ops = { .alloc_coherent = ps3_alloc_coherent, .free_coherent = ps3_free_coherent, - .map_single = ps3_sb_map_single, + .map_single = ps3_map_single, .unmap_single = ps3_unmap_single, - .map_sg = ps3_sb_map_sg, - .unmap_sg = ps3_sb_unmap_sg, - .dma_supported = ps3_dma_supported -}; - -static struct dma_mapping_ops ps3_ioc0_dma_ops = { - .alloc_coherent = ps3_alloc_coherent, - .free_coherent = ps3_free_coherent, - .map_single = ps3_ioc0_map_single, - .unmap_single = ps3_unmap_single, - .map_sg = ps3_ioc0_map_sg, - .unmap_sg = ps3_ioc0_unmap_sg, + .map_sg = ps3_map_sg, + .unmap_sg = ps3_unmap_sg, .dma_supported = ps3_dma_supported }; @@ -703,7 +328,7 @@ static struct dma_mapping_ops ps3_ioc0_dma_ops = { static void ps3_system_bus_release_device(struct device *_dev) { - struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev); + struct ps3_system_bus_device *dev = to_ps3_system_bus_device(_dev); kfree(dev); } @@ -718,38 +343,19 @@ static void ps3_system_bus_release_device(struct device *_dev) int ps3_system_bus_device_register(struct ps3_system_bus_device *dev) { int result; - static unsigned int dev_ioc0_count; - static unsigned int dev_sb_count; - static unsigned int dev_vuart_count; + static unsigned int dev_count = 1; - if (!dev->core.parent) - dev->core.parent = &ps3_system_bus; + dev->core.parent = NULL; dev->core.bus = &ps3_system_bus_type; dev->core.release = ps3_system_bus_release_device; - switch (dev->dev_type) { - case PS3_DEVICE_TYPE_IOC0: - dev->core.archdata.dma_ops = &ps3_ioc0_dma_ops; - snprintf(dev->core.bus_id, sizeof(dev->core.bus_id), - "ioc0_%02x", ++dev_ioc0_count); - break; - case PS3_DEVICE_TYPE_SB: - dev->core.archdata.dma_ops = &ps3_sb_dma_ops; - snprintf(dev->core.bus_id, sizeof(dev->core.bus_id), - "sb_%02x", ++dev_sb_count); - - break; - case PS3_DEVICE_TYPE_VUART: - snprintf(dev->core.bus_id, sizeof(dev->core.bus_id), - "vuart_%02x", ++dev_vuart_count); - break; - default: - BUG(); - }; - dev->core.archdata.of_node = NULL; + dev->core.archdata.dma_ops = &ps3_dma_ops; dev->core.archdata.numa_node = 0; + snprintf(dev->core.bus_id, sizeof(dev->core.bus_id), "sb_%02x", + dev_count++); + pr_debug("%s:%d add %s\n", __func__, __LINE__, dev->core.bus_id); result = device_register(&dev->core); @@ -762,15 +368,9 @@ int ps3_system_bus_driver_register(struct ps3_system_bus_driver *drv) { int result; - pr_debug(" -> %s:%d: %s\n", __func__, __LINE__, drv->core.name); - - if (!firmware_has_feature(FW_FEATURE_PS3_LV1)) - return -ENODEV; - drv->core.bus = &ps3_system_bus_type; result = driver_register(&drv->core); - pr_debug(" <- %s:%d: %s\n", __func__, __LINE__, drv->core.name); return result; } @@ -778,9 +378,7 @@ EXPORT_SYMBOL_GPL(ps3_system_bus_driver_register); void ps3_system_bus_driver_unregister(struct ps3_system_bus_driver *drv) { - pr_debug(" -> %s:%d: %s\n", __func__, __LINE__, drv->core.name); driver_unregister(&drv->core); - pr_debug(" <- %s:%d: %s\n", __func__, __LINE__, drv->core.name); } EXPORT_SYMBOL_GPL(ps3_system_bus_driver_unregister); diff --git a/trunk/arch/powerpc/platforms/ps3/time.c b/trunk/arch/powerpc/platforms/ps3/time.c index 802a9ccacb5e..1bae8b19b363 100644 --- a/trunk/arch/powerpc/platforms/ps3/time.c +++ b/trunk/arch/powerpc/platforms/ps3/time.c @@ -39,7 +39,7 @@ static void _dump_tm(const struct rtc_time *tm, const char* func, int line) } #define dump_time(_a) _dump_time(_a, __func__, __LINE__) -static void __maybe_unused _dump_time(int time, const char *func, +static void __attribute__ ((unused)) _dump_time(int time, const char* func, int line) { struct rtc_time tm; diff --git a/trunk/arch/powerpc/platforms/pseries/Makefile b/trunk/arch/powerpc/platforms/pseries/Makefile index 992ba6753cf2..ae1fc92dc1c9 100644 --- a/trunk/arch/powerpc/platforms/pseries/Makefile +++ b/trunk/arch/powerpc/platforms/pseries/Makefile @@ -8,7 +8,7 @@ obj-y := lpar.o hvCall.o nvram.o reconfig.o \ obj-$(CONFIG_SMP) += smp.o obj-$(CONFIG_XICS) += xics.o obj-$(CONFIG_SCANLOG) += scanlog.o -obj-$(CONFIG_EEH) += eeh.o eeh_cache.o eeh_driver.o eeh_event.o eeh_sysfs.o +obj-$(CONFIG_EEH) += eeh.o eeh_cache.o eeh_driver.o eeh_event.o obj-$(CONFIG_KEXEC) += kexec.o obj-$(CONFIG_PCI) += pci.o pci_dlpar.o obj-$(CONFIG_PCI_MSI) += msi.o diff --git a/trunk/arch/powerpc/platforms/pseries/eeh.c b/trunk/arch/powerpc/platforms/pseries/eeh.c index b8770395013d..5f3e6d8659fe 100644 --- a/trunk/arch/powerpc/platforms/pseries/eeh.c +++ b/trunk/arch/powerpc/platforms/pseries/eeh.c @@ -1,8 +1,6 @@ /* * eeh.c - * Copyright IBM Corporation 2001, 2005, 2006 - * Copyright Dave Engebretsen & Todd Inglett 2001 - * Copyright Linas Vepstas 2005, 2006 + * Copyright (C) 2001 Dave Engebretsen & Todd Inglett IBM 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 @@ -17,8 +15,6 @@ * 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 - * - * Please address comments and feedback to Linas Vepstas */ #include @@ -121,6 +117,7 @@ static unsigned long no_cfg_addr; static unsigned long ignored_check; static unsigned long total_mmio_ffs; static unsigned long false_positives; +static unsigned long ignored_failures; static unsigned long slot_resets; #define IS_BRIDGE(class_code) (((class_code)<<16) == PCI_BASE_CLASS_BRIDGE) @@ -508,7 +505,6 @@ int eeh_dn_check_failure(struct device_node *dn, struct pci_dev *dev) printk(KERN_WARNING "EEH: read_slot_reset_state() failed; rc=%d dn=%s\n", ret, dn->full_name); false_positives++; - pdn->eeh_false_positives ++; rc = 0; goto dn_unlock; } @@ -517,7 +513,6 @@ int eeh_dn_check_failure(struct device_node *dn, struct pci_dev *dev) * they are empty when they don't have children. */ if ((rets[0] == 5) && (dn->child == NULL)) { false_positives++; - pdn->eeh_false_positives ++; rc = 0; goto dn_unlock; } @@ -527,7 +522,6 @@ int eeh_dn_check_failure(struct device_node *dn, struct pci_dev *dev) printk(KERN_WARNING "EEH: event on unsupported device, rc=%d dn=%s\n", ret, dn->full_name); false_positives++; - pdn->eeh_false_positives ++; rc = 0; goto dn_unlock; } @@ -535,7 +529,6 @@ int eeh_dn_check_failure(struct device_node *dn, struct pci_dev *dev) /* If not the kind of error we know about, punt. */ if (rets[0] != 1 && rets[0] != 2 && rets[0] != 4 && rets[0] != 5) { false_positives++; - pdn->eeh_false_positives ++; rc = 0; goto dn_unlock; } @@ -928,7 +921,6 @@ static void *early_enable_eeh(struct device_node *dn, void *data) pdn->eeh_mode = 0; pdn->eeh_check_count = 0; pdn->eeh_freeze_count = 0; - pdn->eeh_false_positives = 0; if (status && strcmp(status, "ok") != 0) return NULL; /* ignore devices with bad status */ @@ -1147,8 +1139,7 @@ static void eeh_add_device_late(struct pci_dev *dev) pdn = PCI_DN(dn); pdn->pcidev = dev; - pci_addr_cache_insert_device(dev); - eeh_sysfs_add_device(dev); + pci_addr_cache_insert_device (dev); } void eeh_add_device_tree_late(struct pci_bus *bus) @@ -1187,7 +1178,6 @@ static void eeh_remove_device(struct pci_dev *dev) printk(KERN_DEBUG "EEH: remove device %s\n", pci_name(dev)); #endif pci_addr_cache_remove_device(dev); - eeh_sysfs_remove_device(dev); dn = pci_device_to_OF_node(dev); if (PCI_DN(dn)->pcidev) { @@ -1224,10 +1214,11 @@ static int proc_eeh_show(struct seq_file *m, void *v) "check not wanted=%ld\n" "eeh_total_mmio_ffs=%ld\n" "eeh_false_positives=%ld\n" + "eeh_ignored_failures=%ld\n" "eeh_slot_resets=%ld\n", no_device, no_dn, no_cfg_addr, ignored_check, total_mmio_ffs, - false_positives, + false_positives, ignored_failures, slot_resets); } diff --git a/trunk/arch/powerpc/platforms/pseries/eeh_cache.c b/trunk/arch/powerpc/platforms/pseries/eeh_cache.c index e49c815eae23..f2bae04424f8 100644 --- a/trunk/arch/powerpc/platforms/pseries/eeh_cache.c +++ b/trunk/arch/powerpc/platforms/pseries/eeh_cache.c @@ -2,8 +2,7 @@ * eeh_cache.c * PCI address cache; allows the lookup of PCI devices based on I/O address * - * Copyright IBM Corporation 2004 - * Copyright Linas Vepstas 2004 + * Copyright (C) 2004 Linas Vepstas IBM 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 @@ -296,8 +295,6 @@ void __init pci_addr_cache_build(void) continue; pci_dev_get (dev); /* matching put is in eeh_remove_device() */ PCI_DN(dn)->pcidev = dev; - - eeh_sysfs_add_device(dev); } #ifdef DEBUG diff --git a/trunk/arch/powerpc/platforms/pseries/eeh_driver.c b/trunk/arch/powerpc/platforms/pseries/eeh_driver.c index 15e015ef6865..161a5844ab6c 100644 --- a/trunk/arch/powerpc/platforms/pseries/eeh_driver.c +++ b/trunk/arch/powerpc/platforms/pseries/eeh_driver.c @@ -1,7 +1,6 @@ /* * PCI Error Recovery Driver for RPA-compliant PPC64 platform. - * Copyright IBM Corp. 2004 2005 - * Copyright Linas Vepstas 2004, 2005 + * Copyright (C) 2004, 2005 Linas Vepstas * * All rights reserved. * @@ -20,7 +19,8 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * - * Send comments and feedback to Linas Vepstas + * Send feedback to + * */ #include #include diff --git a/trunk/arch/powerpc/platforms/pseries/eeh_sysfs.c b/trunk/arch/powerpc/platforms/pseries/eeh_sysfs.c deleted file mode 100644 index 15e13b568904..000000000000 --- a/trunk/arch/powerpc/platforms/pseries/eeh_sysfs.c +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Sysfs entries for PCI Error Recovery for PAPR-compliant platform. - * Copyright IBM Corporation 2007 - * Copyright Linas Vepstas 2007 - * - * 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, GOOD TITLE or - * NON INFRINGEMENT. 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. - * - * Send comments and feedback to Linas Vepstas - */ -#include -#include -#include -#include - -/** - * EEH_SHOW_ATTR -- create sysfs entry for eeh statistic - * @_name: name of file in sysfs directory - * @_memb: name of member in struct pci_dn to access - * @_format: printf format for display - * - * All of the attributes look very similar, so just - * auto-gen a cut-n-paste routine to display them. - */ -#define EEH_SHOW_ATTR(_name,_memb,_format) \ -static ssize_t eeh_show_##_name(struct device *dev, \ - struct device_attribute *attr, char *buf) \ -{ \ - struct pci_dev *pdev = to_pci_dev(dev); \ - struct device_node *dn = pci_device_to_OF_node(pdev); \ - struct pci_dn *pdn; \ - \ - if (!dn || PCI_DN(dn) == NULL) \ - return 0; \ - \ - pdn = PCI_DN(dn); \ - return sprintf(buf, _format "\n", pdn->_memb); \ -} \ -static DEVICE_ATTR(_name, S_IRUGO, eeh_show_##_name, NULL); - - -EEH_SHOW_ATTR(eeh_mode, eeh_mode, "0x%x"); -EEH_SHOW_ATTR(eeh_config_addr, eeh_config_addr, "0x%x"); -EEH_SHOW_ATTR(eeh_pe_config_addr, eeh_pe_config_addr, "0x%x"); -EEH_SHOW_ATTR(eeh_check_count, eeh_check_count, "%d"); -EEH_SHOW_ATTR(eeh_freeze_count, eeh_freeze_count, "%d"); -EEH_SHOW_ATTR(eeh_false_positives, eeh_false_positives, "%d"); - -void eeh_sysfs_add_device(struct pci_dev *pdev) -{ - int rc=0; - - rc += device_create_file(&pdev->dev, &dev_attr_eeh_mode); - rc += device_create_file(&pdev->dev, &dev_attr_eeh_config_addr); - rc += device_create_file(&pdev->dev, &dev_attr_eeh_pe_config_addr); - rc += device_create_file(&pdev->dev, &dev_attr_eeh_check_count); - rc += device_create_file(&pdev->dev, &dev_attr_eeh_false_positives); - rc += device_create_file(&pdev->dev, &dev_attr_eeh_freeze_count); - - if (rc) - printk(KERN_WARNING "EEH: Unable to create sysfs entries\n"); -} - -void eeh_sysfs_remove_device(struct pci_dev *pdev) -{ - device_remove_file(&pdev->dev, &dev_attr_eeh_mode); - device_remove_file(&pdev->dev, &dev_attr_eeh_config_addr); - device_remove_file(&pdev->dev, &dev_attr_eeh_pe_config_addr); - device_remove_file(&pdev->dev, &dev_attr_eeh_check_count); - device_remove_file(&pdev->dev, &dev_attr_eeh_false_positives); - device_remove_file(&pdev->dev, &dev_attr_eeh_freeze_count); -} - diff --git a/trunk/arch/powerpc/platforms/pseries/lpar.c b/trunk/arch/powerpc/platforms/pseries/lpar.c index 8cc6eeeaae2f..362dfbc260a6 100644 --- a/trunk/arch/powerpc/platforms/pseries/lpar.c +++ b/trunk/arch/powerpc/platforms/pseries/lpar.c @@ -373,23 +373,12 @@ static void pSeries_lpar_hptab_clear(void) { unsigned long size_bytes = 1UL << ppc64_pft_size; unsigned long hpte_count = size_bytes >> 4; - unsigned long dummy1, dummy2, dword0; - long lpar_rc; + unsigned long dummy1, dummy2; int i; /* TODO: Use bulk call */ - for (i = 0; i < hpte_count; i++) { - /* dont remove HPTEs with VRMA mappings */ - lpar_rc = plpar_pte_remove_raw(H_ANDCOND, i, HPTE_V_1TB_SEG, - &dummy1, &dummy2); - if (lpar_rc == H_NOT_FOUND) { - lpar_rc = plpar_pte_read_raw(0, i, &dword0, &dummy1); - if (!lpar_rc && ((dword0 & HPTE_V_VRMA_MASK) - != HPTE_V_VRMA_MASK)) - /* Can be hpte for 1TB Seg. So remove it */ - plpar_pte_remove_raw(0, i, 0, &dummy1, &dummy2); - } - } + for (i = 0; i < hpte_count; i++) + plpar_pte_remove_raw(0, i, 0, &dummy1, &dummy2); } /* diff --git a/trunk/arch/powerpc/platforms/pseries/pci_dlpar.c b/trunk/arch/powerpc/platforms/pseries/pci_dlpar.c index 47f0e0857f0e..ffaf6c5c517b 100644 --- a/trunk/arch/powerpc/platforms/pseries/pci_dlpar.c +++ b/trunk/arch/powerpc/platforms/pseries/pci_dlpar.c @@ -110,6 +110,8 @@ pcibios_fixup_new_pci_devices(struct pci_bus *bus, int fix_bus) } } } + + eeh_add_device_tree_late(bus); } EXPORT_SYMBOL_GPL(pcibios_fixup_new_pci_devices); @@ -137,8 +139,6 @@ pcibios_pci_config_bridge(struct pci_dev *dev) /* Make the discovered devices available */ pci_bus_add_devices(child_bus); - - eeh_add_device_tree_late(child_bus); return 0; } @@ -171,7 +171,6 @@ pcibios_add_pci_devices(struct pci_bus * bus) if (!list_empty(&bus->devices)) { pcibios_fixup_new_pci_devices(bus, 0); pci_bus_add_devices(bus); - eeh_add_device_tree_late(bus); } } else if (mode == PCI_PROBE_NORMAL) { /* use legacy probe */ @@ -180,7 +179,6 @@ pcibios_add_pci_devices(struct pci_bus * bus) if (num) { pcibios_fixup_new_pci_devices(bus, 1); pci_bus_add_devices(bus); - eeh_add_device_tree_late(bus); } list_for_each_entry(dev, &bus->devices, bus_list) @@ -202,6 +200,8 @@ struct pci_controller * __devinit init_phb_dynamic(struct device_node *dn) rtas_setup_phb(phb); pci_process_bridge_OF_ranges(phb, dn, 0); + pci_setup_phb_io_dynamic(phb, primary); + pci_devs_phb_init_dynamic(phb); if (dn->child) @@ -210,7 +210,6 @@ struct pci_controller * __devinit init_phb_dynamic(struct device_node *dn) scan_phb(phb); pcibios_fixup_new_pci_devices(phb->bus, 0); pci_bus_add_devices(phb->bus); - eeh_add_device_tree_late(phb->bus); return phb; } diff --git a/trunk/arch/powerpc/platforms/pseries/plpar_wrappers.h b/trunk/arch/powerpc/platforms/pseries/plpar_wrappers.h index d003c80fa31d..2e4d10c9eea8 100644 --- a/trunk/arch/powerpc/platforms/pseries/plpar_wrappers.h +++ b/trunk/arch/powerpc/platforms/pseries/plpar_wrappers.h @@ -108,21 +108,6 @@ static inline long plpar_pte_read(unsigned long flags, unsigned long ptex, return rc; } -/* plpar_pte_read_raw can be called in real mode. It calls plpar_hcall_raw */ -static inline long plpar_pte_read_raw(unsigned long flags, unsigned long ptex, - unsigned long *old_pteh_ret, unsigned long *old_ptel_ret) -{ - long rc; - unsigned long retbuf[PLPAR_HCALL_BUFSIZE]; - - rc = plpar_hcall_raw(H_READ, retbuf, flags, ptex); - - *old_pteh_ret = retbuf[0]; - *old_ptel_ret = retbuf[1]; - - return rc; -} - static inline long plpar_pte_protect(unsigned long flags, unsigned long ptex, unsigned long avpn) { diff --git a/trunk/arch/powerpc/platforms/pseries/pseries.h b/trunk/arch/powerpc/platforms/pseries/pseries.h index 61e19f78b923..2729d559fd91 100644 --- a/trunk/arch/powerpc/platforms/pseries/pseries.h +++ b/trunk/arch/powerpc/platforms/pseries/pseries.h @@ -33,8 +33,6 @@ static inline void setup_kexec_cpu_down_xics(void) { } static inline void setup_kexec_cpu_down_mpic(void) { } #endif -extern void pSeries_final_fixup(void); - /* Poweron flag used for enabling auto ups restart */ extern unsigned long rtas_poweron_auto; diff --git a/trunk/arch/powerpc/platforms/pseries/reconfig.c b/trunk/arch/powerpc/platforms/pseries/reconfig.c index c02f8742c54d..5aa97aff3391 100644 --- a/trunk/arch/powerpc/platforms/pseries/reconfig.c +++ b/trunk/arch/powerpc/platforms/pseries/reconfig.c @@ -123,7 +123,7 @@ static int pSeries_reconfig_add_node(const char *path, struct property *proplist strcpy(np->full_name, path); np->properties = proplist; - of_node_set_flag(np, OF_DYNAMIC); + OF_MARK_DYNAMIC(np); kref_init(&np->kref); np->parent = derive_parent(path); diff --git a/trunk/arch/powerpc/platforms/pseries/setup.c b/trunk/arch/powerpc/platforms/pseries/setup.c index 59e69f085cb4..a031d99becb7 100644 --- a/trunk/arch/powerpc/platforms/pseries/setup.c +++ b/trunk/arch/powerpc/platforms/pseries/setup.c @@ -399,7 +399,6 @@ static void pseries_dedicated_idle_sleep(void) * a good time to find other work to dispatch. */ get_lppaca()->idle = 1; - get_lppaca()->donate_dedicated_cpu = 1; /* * We come in with interrupts disabled, and need_resched() @@ -432,7 +431,6 @@ static void pseries_dedicated_idle_sleep(void) out: HMT_medium(); - get_lppaca()->donate_dedicated_cpu = 0; get_lppaca()->idle = 0; } diff --git a/trunk/arch/powerpc/platforms/pseries/xics.c b/trunk/arch/powerpc/platforms/pseries/xics.c index 5bd90a7eb763..f1df942072bb 100644 --- a/trunk/arch/powerpc/platforms/pseries/xics.c +++ b/trunk/arch/powerpc/platforms/pseries/xics.c @@ -156,9 +156,9 @@ static inline void lpar_qirr_info(int n_cpu , u8 value) #ifdef CONFIG_SMP -static int get_irq_server(unsigned int virq, unsigned int strict_check) +static int get_irq_server(unsigned int virq) { - int server; + unsigned int server; /* For the moment only implement delivery to all cpus or one cpu */ cpumask_t cpumask = irq_desc[virq].affinity; cpumask_t tmp = CPU_MASK_NONE; @@ -166,25 +166,22 @@ static int get_irq_server(unsigned int virq, unsigned int strict_check) if (!distribute_irqs) return default_server; - if (!cpus_equal(cpumask, CPU_MASK_ALL)) { + if (cpus_equal(cpumask, CPU_MASK_ALL)) { + server = default_distrib_server; + } else { cpus_and(tmp, cpu_online_map, cpumask); - server = first_cpu(tmp); - - if (server < NR_CPUS) - return get_hard_smp_processor_id(server); - - if (strict_check) - return -1; + if (cpus_empty(tmp)) + server = default_distrib_server; + else + server = get_hard_smp_processor_id(first_cpu(tmp)); } - if (cpus_equal(cpu_online_map, cpu_present_map)) - return default_distrib_server; + return server; - return default_server; } #else -static int get_irq_server(unsigned int virq, unsigned int strict_check) +static int get_irq_server(unsigned int virq) { return default_server; } @@ -195,7 +192,7 @@ static void xics_unmask_irq(unsigned int virq) { unsigned int irq; int call_status; - int server; + unsigned int server; pr_debug("xics: unmask virq %d\n", virq); @@ -204,7 +201,7 @@ static void xics_unmask_irq(unsigned int virq) if (irq == XICS_IPI || irq == XICS_IRQ_SPURIOUS) return; - server = get_irq_server(virq, 0); + server = get_irq_server(virq); call_status = rtas_call(ibm_set_xive, 3, 1, NULL, irq, server, DEFAULT_PRIORITY); @@ -401,7 +398,8 @@ static void xics_set_affinity(unsigned int virq, cpumask_t cpumask) unsigned int irq; int status; int xics_status[2]; - int irq_server; + unsigned long newmask; + cpumask_t tmp = CPU_MASK_NONE; irq = (unsigned int)irq_map[virq].hwirq; if (irq == XICS_IPI || irq == XICS_IRQ_SPURIOUS) @@ -415,21 +413,18 @@ static void xics_set_affinity(unsigned int virq, cpumask_t cpumask) return; } - /* - * For the moment only implement delivery to all cpus or one cpu. - * Get current irq_server for the given irq - */ - irq_server = get_irq_server(irq, 1); - if (irq_server == -1) { - char cpulist[128]; - cpumask_scnprintf(cpulist, sizeof(cpulist), cpumask); - printk(KERN_WARNING "xics_set_affinity: No online cpus in " - "the mask %s for irq %d\n", cpulist, virq); - return; + /* For the moment only implement delivery to all cpus or one cpu */ + if (cpus_equal(cpumask, CPU_MASK_ALL)) { + newmask = default_distrib_server; + } else { + cpus_and(tmp, cpu_online_map, cpumask); + if (cpus_empty(tmp)) + return; + newmask = get_hard_smp_processor_id(first_cpu(tmp)); } status = rtas_call(ibm_set_xive, 3, 1, NULL, - irq, irq_server, xics_status[1]); + irq, newmask, xics_status[1]); if (status) { printk(KERN_ERR "xics_set_affinity: irq=%u ibm,set-xive " diff --git a/trunk/arch/powerpc/sysdev/Makefile b/trunk/arch/powerpc/sysdev/Makefile index f65078c3d3b3..c3ce0bd12c0b 100644 --- a/trunk/arch/powerpc/sysdev/Makefile +++ b/trunk/arch/powerpc/sysdev/Makefile @@ -5,6 +5,7 @@ endif mpic-msi-obj-$(CONFIG_PCI_MSI) += mpic_msi.o mpic_u3msi.o obj-$(CONFIG_MPIC) += mpic.o $(mpic-msi-obj-y) +obj-$(CONFIG_PPC_INDIRECT_PCI) += indirect_pci.o obj-$(CONFIG_PPC_MPC106) += grackle.o obj-$(CONFIG_PPC_DCR) += dcr.o obj-$(CONFIG_PPC_DCR_NATIVE) += dcr-low.o @@ -12,19 +13,16 @@ obj-$(CONFIG_PPC_PMI) += pmi.o obj-$(CONFIG_U3_DART) += dart_iommu.o obj-$(CONFIG_MMIO_NVRAM) += mmio_nvram.o obj-$(CONFIG_FSL_SOC) += fsl_soc.o +obj-$(CONFIG_FSL_PCIE) += fsl_pcie.o obj-$(CONFIG_TSI108_BRIDGE) += tsi108_pci.o tsi108_dev.o obj-$(CONFIG_QUICC_ENGINE) += qe_lib/ mv64x60-$(CONFIG_PCI) += mv64x60_pci.o obj-$(CONFIG_MV64X60) += $(mv64x60-y) mv64x60_pic.o mv64x60_dev.o -obj-$(CONFIG_RTC_DRV_CMOS) += rtc_cmos_setup.o # contains only the suspend handler for time -ifeq ($(CONFIG_RTC_CLASS),) obj-$(CONFIG_PM) += timer.o -endif ifeq ($(CONFIG_PPC_MERGE),y) -obj-$(CONFIG_PPC_INDIRECT_PCI) += indirect_pci.o obj-$(CONFIG_PPC_I8259) += i8259.o obj-$(CONFIG_PPC_83xx) += ipic.o obj-$(CONFIG_4xx) += uic.o diff --git a/trunk/arch/powerpc/sysdev/fsl_pcie.c b/trunk/arch/powerpc/sysdev/fsl_pcie.c new file mode 100644 index 000000000000..041c07e8b665 --- /dev/null +++ b/trunk/arch/powerpc/sysdev/fsl_pcie.c @@ -0,0 +1,171 @@ +/* + * Support for indirect PCI bridges. + * + * Copyright (C) 1998 Gabriel Paubert. + * + * 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. + * + * "Temporary" MPC8548 Errata file - + * The standard indirect_pci code should work with future silicon versions. + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#define PCI_CFG_OUT out_be32 + +/* ERRATA PCI-Ex 14 PCIE Controller timeout */ +#define PCIE_FIX out_be32(hose->cfg_addr+0x4, 0x0400ffff) + + +static int +indirect_read_config_pcie(struct pci_bus *bus, unsigned int devfn, int offset, + int len, u32 *val) +{ + struct pci_controller *hose = bus->sysdata; + volatile void __iomem *cfg_data; + u32 temp; + + if (ppc_md.pci_exclude_device) + if (ppc_md.pci_exclude_device(bus->number, devfn)) + return PCIBIOS_DEVICE_NOT_FOUND; + + /* Possible artifact of CDCpp50937 needs further investigation */ + if (devfn != 0x0 && bus->number == 0xff) + return PCIBIOS_DEVICE_NOT_FOUND; + + PCIE_FIX; + if (bus->number == 0xff) { + PCI_CFG_OUT(hose->cfg_addr, + (0x80000000 | ((offset & 0xf00) << 16) | + ((bus->number - hose->bus_offset) << 16) + | (devfn << 8) | ((offset & 0xfc) ))); + } else { + PCI_CFG_OUT(hose->cfg_addr, + (0x80000001 | ((offset & 0xf00) << 16) | + ((bus->number - hose->bus_offset) << 16) + | (devfn << 8) | ((offset & 0xfc) ))); + } + + /* + * Note: the caller has already checked that offset is + * suitably aligned and that len is 1, 2 or 4. + */ + /* ERRATA PCI-Ex 12 - Configuration Address/Data Alignment */ + cfg_data = hose->cfg_data; + PCIE_FIX; + temp = in_le32(cfg_data); + switch (len) { + case 1: + *val = (temp >> (((offset & 3))*8)) & 0xff; + break; + case 2: + *val = (temp >> (((offset & 3))*8)) & 0xffff; + break; + default: + *val = temp; + break; + } + return PCIBIOS_SUCCESSFUL; +} + +static int +indirect_write_config_pcie(struct pci_bus *bus, unsigned int devfn, int offset, + int len, u32 val) +{ + struct pci_controller *hose = bus->sysdata; + volatile void __iomem *cfg_data; + u32 temp; + + if (ppc_md.pci_exclude_device) + if (ppc_md.pci_exclude_device(bus->number, devfn)) + return PCIBIOS_DEVICE_NOT_FOUND; + + /* Possible artifact of CDCpp50937 needs further investigation */ + if (devfn != 0x0 && bus->number == 0xff) + return PCIBIOS_DEVICE_NOT_FOUND; + + PCIE_FIX; + if (bus->number == 0xff) { + PCI_CFG_OUT(hose->cfg_addr, + (0x80000000 | ((offset & 0xf00) << 16) | + ((bus->number - hose->bus_offset) << 16) + | (devfn << 8) | ((offset & 0xfc) ))); + } else { + PCI_CFG_OUT(hose->cfg_addr, + (0x80000001 | ((offset & 0xf00) << 16) | + ((bus->number - hose->bus_offset) << 16) + | (devfn << 8) | ((offset & 0xfc) ))); + } + + /* + * Note: the caller has already checked that offset is + * suitably aligned and that len is 1, 2 or 4. + */ + /* ERRATA PCI-Ex 12 - Configuration Address/Data Alignment */ + cfg_data = hose->cfg_data; + switch (len) { + case 1: + PCIE_FIX; + temp = in_le32(cfg_data); + temp = (temp & ~(0xff << ((offset & 3) * 8))) | + (val << ((offset & 3) * 8)); + PCIE_FIX; + out_le32(cfg_data, temp); + break; + case 2: + PCIE_FIX; + temp = in_le32(cfg_data); + temp = (temp & ~(0xffff << ((offset & 3) * 8))); + temp |= (val << ((offset & 3) * 8)) ; + PCIE_FIX; + out_le32(cfg_data, temp); + break; + default: + PCIE_FIX; + out_le32(cfg_data, val); + break; + } + PCIE_FIX; + return PCIBIOS_SUCCESSFUL; +} + +static struct pci_ops indirect_pcie_ops = { + indirect_read_config_pcie, + indirect_write_config_pcie +}; + +void __init +setup_indirect_pcie_nomap(struct pci_controller* hose, void __iomem * cfg_addr, + void __iomem * cfg_data) +{ + hose->cfg_addr = cfg_addr; + hose->cfg_data = cfg_data; + hose->ops = &indirect_pcie_ops; +} + +void __init +setup_indirect_pcie(struct pci_controller* hose, u32 cfg_addr, u32 cfg_data) +{ + unsigned long base = cfg_addr & PAGE_MASK; + void __iomem *mbase, *addr, *data; + + mbase = ioremap(base, PAGE_SIZE); + addr = mbase + (cfg_addr & ~PAGE_MASK); + if ((cfg_data & PAGE_MASK) != base) + mbase = ioremap(cfg_data & PAGE_MASK, PAGE_SIZE); + data = mbase + (cfg_data & ~PAGE_MASK); + setup_indirect_pcie_nomap(hose, addr, data); +} diff --git a/trunk/arch/powerpc/sysdev/fsl_soc.c b/trunk/arch/powerpc/sysdev/fsl_soc.c index c0ddc80d8160..cad175724359 100644 --- a/trunk/arch/powerpc/sysdev/fsl_soc.c +++ b/trunk/arch/powerpc/sysdev/fsl_soc.c @@ -1028,19 +1028,6 @@ static int __init fs_enet_of_init(void) arch_initcall(fs_enet_of_init); -static int __init fsl_pcmcia_of_init(void) -{ - struct device_node *np = NULL; - /* - * Register all the devices which type is "pcmcia" - */ - while ((np = of_find_compatible_node(np, - "pcmcia", "fsl,pq-pcmcia")) != NULL) - of_platform_device_create(np, "m8xx-pcmcia", NULL); - return 0; -} - -arch_initcall(fsl_pcmcia_of_init); static const char *smc_regs = "regs"; static const char *smc_pram = "pram"; diff --git a/trunk/arch/powerpc/sysdev/indirect_pci.c b/trunk/arch/powerpc/sysdev/indirect_pci.c index c7e6e859b393..e71488469704 100644 --- a/trunk/arch/powerpc/sysdev/indirect_pci.c +++ b/trunk/arch/powerpc/sysdev/indirect_pci.c @@ -33,27 +33,18 @@ indirect_read_config(struct pci_bus *bus, unsigned int devfn, int offset, struct pci_controller *hose = bus->sysdata; volatile void __iomem *cfg_data; u8 cfg_type = 0; - u32 bus_no, reg; if (ppc_md.pci_exclude_device) - if (ppc_md.pci_exclude_device(hose, bus->number, devfn)) + if (ppc_md.pci_exclude_device(bus->number, devfn)) return PCIBIOS_DEVICE_NOT_FOUND; - if (hose->indirect_type & PPC_INDIRECT_TYPE_SET_CFG_TYPE) + if (hose->set_cfg_type) if (bus->number != hose->first_busno) cfg_type = 1; - bus_no = (bus->number == hose->first_busno) ? - hose->self_busno : bus->number; - - if (hose->indirect_type & PPC_INDIRECT_TYPE_EXT_REG) - reg = ((offset & 0xf00) << 16) | (offset & 0xfc); - else - reg = offset & 0xfc; - - PCI_CFG_OUT(hose->cfg_addr, - (0x80000000 | (bus_no << 16) - | (devfn << 8) | reg | cfg_type)); + PCI_CFG_OUT(hose->cfg_addr, + (0x80000000 | ((bus->number - hose->bus_offset) << 16) + | (devfn << 8) | ((offset & 0xfc) | cfg_type))); /* * Note: the caller has already checked that offset is @@ -81,33 +72,18 @@ indirect_write_config(struct pci_bus *bus, unsigned int devfn, int offset, struct pci_controller *hose = bus->sysdata; volatile void __iomem *cfg_data; u8 cfg_type = 0; - u32 bus_no, reg; if (ppc_md.pci_exclude_device) - if (ppc_md.pci_exclude_device(hose, bus->number, devfn)) + if (ppc_md.pci_exclude_device(bus->number, devfn)) return PCIBIOS_DEVICE_NOT_FOUND; - if (hose->indirect_type & PPC_INDIRECT_TYPE_SET_CFG_TYPE) + if (hose->set_cfg_type) if (bus->number != hose->first_busno) cfg_type = 1; - bus_no = (bus->number == hose->first_busno) ? - hose->self_busno : bus->number; - - if (hose->indirect_type & PPC_INDIRECT_TYPE_EXT_REG) - reg = ((offset & 0xf00) << 16) | (offset & 0xfc); - else - reg = offset & 0xfc; - - PCI_CFG_OUT(hose->cfg_addr, - (0x80000000 | (bus_no << 16) - | (devfn << 8) | reg | cfg_type)); - - /* surpress setting of PCI_PRIMARY_BUS */ - if (hose->indirect_type & PPC_INDIRECT_TYPE_SURPRESS_PRIMARY_BUS) - if ((offset == PCI_PRIMARY_BUS) && - (bus->number == hose->first_busno)) - val &= 0xffffff00; + PCI_CFG_OUT(hose->cfg_addr, + (0x80000000 | ((bus->number - hose->bus_offset) << 16) + | (devfn << 8) | ((offset & 0xfc) | cfg_type))); /* * Note: the caller has already checked that offset is diff --git a/trunk/arch/powerpc/sysdev/mpc8xx_pic.h b/trunk/arch/powerpc/sysdev/mpc8xx_pic.h index 9fe00eebdc8b..afa2ee6717c1 100644 --- a/trunk/arch/powerpc/sysdev/mpc8xx_pic.h +++ b/trunk/arch/powerpc/sysdev/mpc8xx_pic.h @@ -4,16 +4,9 @@ #include #include +extern struct hw_interrupt_type mpc8xx_pic; + int mpc8xx_pic_init(void); unsigned int mpc8xx_get_irq(void); -/* - * Some internal interrupt registers use an 8-bit mask for the interrupt - * level instead of a number. - */ -static inline uint mk_int_int_mask(uint mask) -{ - return (1 << (7 - (mask/2))); -} - #endif /* _PPC_KERNEL_PPC8xx_H */ diff --git a/trunk/arch/powerpc/sysdev/mv64x60_dev.c b/trunk/arch/powerpc/sysdev/mv64x60_dev.c index b618fa60aef3..4b0a9c88eeb3 100644 --- a/trunk/arch/powerpc/sysdev/mv64x60_dev.c +++ b/trunk/arch/powerpc/sysdev/mv64x60_dev.c @@ -12,7 +12,6 @@ #include #include #include -#include #include #include @@ -421,30 +420,3 @@ static int __init mv64x60_device_setup(void) return err; } arch_initcall(mv64x60_device_setup); - -static int __init mv64x60_add_mpsc_console(void) -{ - struct device_node *np = NULL; - const char *prop; - - prop = of_get_property(of_chosen, "linux,stdout-path", NULL); - if (prop == NULL) - goto not_mpsc; - - np = of_find_node_by_path(prop); - if (!np) - goto not_mpsc; - - if (!of_device_is_compatible(np, "marvell,mpsc")) - goto not_mpsc; - - prop = of_get_property(np, "block-index", NULL); - if (!prop) - goto not_mpsc; - - add_preferred_console("ttyMM", *(int *)prop, NULL); - -not_mpsc: - return 0; -} -console_initcall(mv64x60_add_mpsc_console); diff --git a/trunk/arch/powerpc/sysdev/mv64x60_pci.c b/trunk/arch/powerpc/sysdev/mv64x60_pci.c index 45db86c2363c..b5aef4cbc8d2 100644 --- a/trunk/arch/powerpc/sysdev/mv64x60_pci.c +++ b/trunk/arch/powerpc/sysdev/mv64x60_pci.c @@ -137,15 +137,18 @@ static int __init mv64x60_add_bridge(struct device_node *dev) printk(KERN_WARNING "Can't get bus-range for %s, assume" " bus 0\n", dev->full_name); - hose = pcibios_alloc_controller(dev); + hose = pcibios_alloc_controller(); if (!hose) return -ENOMEM; + hose->arch_data = dev; + hose->set_cfg_type = 1; + hose->first_busno = bus_range ? bus_range[0] : 0; hose->last_busno = bus_range ? bus_range[1] : 0xff; setup_indirect_pci(hose, rsrc.start, rsrc.start + 4); - hose->self_busno = hose->first_busno; + hose->bus_offset = hose->first_busno; printk(KERN_INFO "Found MV64x60 PCI host bridge at 0x%016llx. " "Firmware bus number: %d->%d\n", diff --git a/trunk/arch/powerpc/sysdev/qe_lib/ucc.c b/trunk/arch/powerpc/sysdev/qe_lib/ucc.c index f970e5415ac0..ac12a44d516f 100644 --- a/trunk/arch/powerpc/sysdev/qe_lib/ucc.c +++ b/trunk/arch/powerpc/sysdev/qe_lib/ucc.c @@ -18,7 +18,6 @@ #include #include #include -#include #include #include @@ -41,7 +40,6 @@ int ucc_set_qe_mux_mii_mng(int ucc_num) return 0; } -EXPORT_SYMBOL(ucc_set_qe_mux_mii_mng); int ucc_set_type(int ucc_num, struct ucc_common *regs, enum ucc_speed_type speed) diff --git a/trunk/arch/powerpc/sysdev/qe_lib/ucc_fast.c b/trunk/arch/powerpc/sysdev/qe_lib/ucc_fast.c index 3df202e8d332..9143236853fc 100644 --- a/trunk/arch/powerpc/sysdev/qe_lib/ucc_fast.c +++ b/trunk/arch/powerpc/sysdev/qe_lib/ucc_fast.c @@ -19,7 +19,6 @@ #include #include #include -#include #include #include @@ -71,7 +70,6 @@ void ucc_fast_dump_regs(struct ucc_fast_private * uccf) printk(KERN_INFO "guemr : addr - 0x%08x, val - 0x%02x", (u32) & uccf->uf_regs->guemr, uccf->uf_regs->guemr); } -EXPORT_SYMBOL(ucc_fast_dump_regs); u32 ucc_fast_get_qe_cr_subblock(int uccf_num) { @@ -87,13 +85,11 @@ u32 ucc_fast_get_qe_cr_subblock(int uccf_num) default: return QE_CR_SUBBLOCK_INVALID; } } -EXPORT_SYMBOL(ucc_fast_get_qe_cr_subblock); void ucc_fast_transmit_on_demand(struct ucc_fast_private * uccf) { out_be16(&uccf->uf_regs->utodr, UCC_FAST_TOD); } -EXPORT_SYMBOL(ucc_fast_transmit_on_demand); void ucc_fast_enable(struct ucc_fast_private * uccf, enum comm_dir mode) { @@ -114,7 +110,6 @@ void ucc_fast_enable(struct ucc_fast_private * uccf, enum comm_dir mode) } out_be32(&uf_regs->gumr, gumr); } -EXPORT_SYMBOL(ucc_fast_enable); void ucc_fast_disable(struct ucc_fast_private * uccf, enum comm_dir mode) { @@ -135,7 +130,6 @@ void ucc_fast_disable(struct ucc_fast_private * uccf, enum comm_dir mode) } out_be32(&uf_regs->gumr, gumr); } -EXPORT_SYMBOL(ucc_fast_disable); int ucc_fast_init(struct ucc_fast_info * uf_info, struct ucc_fast_private ** uccf_ret) { @@ -347,7 +341,6 @@ int ucc_fast_init(struct ucc_fast_info * uf_info, struct ucc_fast_private ** ucc *uccf_ret = uccf; return 0; } -EXPORT_SYMBOL(ucc_fast_init); void ucc_fast_free(struct ucc_fast_private * uccf) { @@ -362,4 +355,3 @@ void ucc_fast_free(struct ucc_fast_private * uccf) kfree(uccf); } -EXPORT_SYMBOL(ucc_fast_free); diff --git a/trunk/arch/powerpc/sysdev/rtc_cmos_setup.c b/trunk/arch/powerpc/sysdev/rtc_cmos_setup.c deleted file mode 100644 index e276048b8c5f..000000000000 --- a/trunk/arch/powerpc/sysdev/rtc_cmos_setup.c +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Setup code for PC-style Real-Time Clock. - * - * Author: Wade Farnsworth - * - * 2007 (c) MontaVista Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2. This program - * is licensed "as is" without any warranty of any kind, whether express - * or implied. - */ - -#include -#include -#include -#include - -#include - -static int __init add_rtc(void) -{ - struct device_node *np; - struct platform_device *pd; - struct resource res; - int ret; - - np = of_find_compatible_node(NULL, NULL, "pnpPNP,b00"); - if (!np) - return -ENODEV; - - ret = of_address_to_resource(np, 0, &res); - of_node_put(np); - if (ret) - return ret; - - /* - * RTC_PORT(x) is hardcoded in asm/mc146818rtc.h. Verify that the - * address provided by the device node matches. - */ - if (res.start != RTC_PORT(0)) - return -EINVAL; - - pd = platform_device_register_simple("rtc_cmos", -1, - &res, 1); - if (IS_ERR(pd)) - return PTR_ERR(pd); - - return 0; -} -fs_initcall(add_rtc); diff --git a/trunk/arch/powerpc/sysdev/timer.c b/trunk/arch/powerpc/sysdev/timer.c index e81e7ec2e799..4a01748b4217 100644 --- a/trunk/arch/powerpc/sysdev/timer.c +++ b/trunk/arch/powerpc/sysdev/timer.c @@ -24,12 +24,7 @@ static int timer_resume(struct sys_device *dev) /* get current RTC time and convert to seconds */ get_rtc_time(&cur_rtc_tm); - cur_rtc_time = mktime(cur_rtc_tm.tm_year + 1900, - cur_rtc_tm.tm_mon + 1, - cur_rtc_tm.tm_mday, - cur_rtc_tm.tm_hour, - cur_rtc_tm.tm_min, - cur_rtc_tm.tm_sec); + rtc_tm_to_time(&cur_rtc_tm, &cur_rtc_time); diff = cur_rtc_time - suspend_rtc_time; @@ -49,12 +44,7 @@ static int timer_suspend(struct sys_device *dev, pm_message_t state) WARN_ON(!ppc_md.get_rtc_time); get_rtc_time(&suspend_rtc_tm); - suspend_rtc_time = mktime(suspend_rtc_tm.tm_year + 1900, - suspend_rtc_tm.tm_mon + 1, - suspend_rtc_tm.tm_mday, - suspend_rtc_tm.tm_hour, - suspend_rtc_tm.tm_min, - suspend_rtc_tm.tm_sec); + rtc_tm_to_time(&suspend_rtc_tm, &suspend_rtc_time); return 0; } diff --git a/trunk/arch/powerpc/sysdev/tsi108_dev.c b/trunk/arch/powerpc/sysdev/tsi108_dev.c index a113d800cbf0..7d3b09b7d544 100644 --- a/trunk/arch/powerpc/sysdev/tsi108_dev.c +++ b/trunk/arch/powerpc/sysdev/tsi108_dev.c @@ -72,11 +72,12 @@ static int __init tsi108_eth_of_init(void) int ret; for (np = NULL, i = 0; - (np = of_find_compatible_node(np, "network", "tsi108-ethernet")) != NULL; + (np = of_find_compatible_node(np, "network", "tsi-ethernet")) != NULL; i++) { struct resource r[2]; - struct device_node *phy, *mdio; + struct device_node *phy; hw_info tsi_eth_data; + const unsigned int *id; const unsigned int *phy_id; const void *mac_addr; const phandle *ph; @@ -110,13 +111,6 @@ static int __init tsi108_eth_of_init(void) if (mac_addr) memcpy(tsi_eth_data.mac_addr, mac_addr, 6); - ph = of_get_property(np, "mdio-handle", NULL); - mdio = of_find_node_by_phandle(*ph); - ret = of_address_to_resource(mdio, 0, &res); - of_node_put(mdio); - if (ret) - goto unreg; - ph = of_get_property(np, "phy-handle", NULL); phy = of_find_node_by_phandle(*ph); @@ -125,25 +119,20 @@ static int __init tsi108_eth_of_init(void) goto unreg; } - phy_id = of_get_property(phy, "reg", NULL); - + id = of_get_property(phy, "reg", NULL); + phy_id = of_get_property(phy, "phy-id", NULL); + ret = of_address_to_resource(phy, 0, &res); + if (ret) { + of_node_put(phy); + goto unreg; + } tsi_eth_data.regs = r[0].start; tsi_eth_data.phyregs = res.start; tsi_eth_data.phy = *phy_id; tsi_eth_data.irq_num = irq_of_parse_and_map(np, 0); - - /* Some boards with the TSI108 bridge (e.g. Holly) - * have a miswiring of the ethernet PHYs which - * requires a workaround. The special - * "txc-rxc-delay-disable" property enables this - * workaround. FIXME: Need to port the tsi108_eth - * driver itself to phylib and use a non-misleading - * name for the workaround flag - it's not actually to - * do with the model of PHY in use */ - if (of_get_property(phy, "txc-rxc-delay-disable", NULL)) + if (of_device_is_compatible(phy, "bcm54xx")) tsi_eth_data.phy_type = TSI108_PHY_BCM54XX; of_node_put(phy); - ret = platform_device_add_data(tsi_eth_dev, &tsi_eth_data, sizeof(hw_info)); diff --git a/trunk/arch/powerpc/sysdev/tsi108_pci.c b/trunk/arch/powerpc/sysdev/tsi108_pci.c index 90db8a720fed..2153163fa593 100644 --- a/trunk/arch/powerpc/sysdev/tsi108_pci.c +++ b/trunk/arch/powerpc/sysdev/tsi108_pci.c @@ -64,10 +64,9 @@ tsi108_direct_write_config(struct pci_bus *bus, unsigned int devfunc, int offset, int len, u32 val) { volatile unsigned char *cfg_addr; - struct pci_controller *hose = bus->sysdata; if (ppc_md.pci_exclude_device) - if (ppc_md.pci_exclude_device(hose, bus->number, devfunc)) + if (ppc_md.pci_exclude_device(bus->number, devfunc)) return PCIBIOS_DEVICE_NOT_FOUND; cfg_addr = (unsigned char *)(tsi_mk_config_addr(bus->number, @@ -150,11 +149,10 @@ tsi108_direct_read_config(struct pci_bus *bus, unsigned int devfn, int offset, int len, u32 * val) { volatile unsigned char *cfg_addr; - struct pci_controller *hose = bus->sysdata; u32 temp; if (ppc_md.pci_exclude_device) - if (ppc_md.pci_exclude_device(hose, bus->number, devfn)) + if (ppc_md.pci_exclude_device(bus->number, devfn)) return PCIBIOS_DEVICE_NOT_FOUND; cfg_addr = (unsigned char *)(tsi_mk_config_addr(bus->number, @@ -221,12 +219,14 @@ int __init tsi108_setup_pci(struct device_node *dev, u32 cfg_phys, int primary) " bus 0\n", dev->full_name); } - hose = pcibios_alloc_controller(dev); + hose = pcibios_alloc_controller(); if (!hose) { printk("PCI Host bridge init failed\n"); return -ENOMEM; } + hose->arch_data = dev; + hose->set_cfg_type = 1; hose->first_busno = bus_range ? bus_range[0] : 0; hose->last_busno = bus_range ? bus_range[1] : 0xff; diff --git a/trunk/arch/powerpc/xmon/xmon.c b/trunk/arch/powerpc/xmon/xmon.c index 669e6566ad70..28fdf4f50c27 100644 --- a/trunk/arch/powerpc/xmon/xmon.c +++ b/trunk/arch/powerpc/xmon/xmon.c @@ -2634,7 +2634,7 @@ static int __init setup_xmon_sysrq(void) __initcall(setup_xmon_sysrq); #endif /* CONFIG_MAGIC_SYSRQ */ -static int __initdata xmon_early, xmon_off; +int __initdata xmon_early, xmon_off; static int __init early_parse_xmon(char *p) { diff --git a/trunk/arch/ppc/kernel/misc.S b/trunk/arch/ppc/kernel/misc.S index 0da55368655c..d319f9ba2379 100644 --- a/trunk/arch/ppc/kernel/misc.S +++ b/trunk/arch/ppc/kernel/misc.S @@ -328,7 +328,7 @@ BEGIN_FTR_SECTION mtspr SPRN_L1CSR0,r3 isync blr -END_FTR_SECTION_IFSET(CPU_FTR_UNIFIED_ID_CACHE) +END_FTR_SECTION_IFCLR(CPU_FTR_SPLIT_ID_CACHE) mfspr r3,SPRN_L1CSR1 ori r3,r3,L1CSR1_ICFI|L1CSR1_ICLFR mtspr SPRN_L1CSR1,r3 @@ -355,7 +355,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_UNIFIED_ID_CACHE) _GLOBAL(__flush_icache_range) BEGIN_FTR_SECTION blr /* for 601, do nothing */ -END_FTR_SECTION_IFSET(CPU_FTR_COHERENT_ICACHE) +END_FTR_SECTION_IFCLR(CPU_FTR_SPLIT_ID_CACHE) li r5,L1_CACHE_BYTES-1 andc r3,r3,r5 subf r4,r3,r4 @@ -472,7 +472,7 @@ _GLOBAL(flush_dcache_all) _GLOBAL(__flush_dcache_icache) BEGIN_FTR_SECTION blr /* for 601, do nothing */ -END_FTR_SECTION_IFSET(CPU_FTR_COHERENT_ICACHE) +END_FTR_SECTION_IFCLR(CPU_FTR_SPLIT_ID_CACHE) rlwinm r3,r3,0,0,19 /* Get page base address */ li r4,4096/L1_CACHE_BYTES /* Number of lines in a page */ mtctr r4 @@ -500,7 +500,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_COHERENT_ICACHE) _GLOBAL(__flush_dcache_icache_phys) BEGIN_FTR_SECTION blr /* for 601, do nothing */ -END_FTR_SECTION_IFSET(CPU_FTR_COHERENT_ICACHE) +END_FTR_SECTION_IFCLR(CPU_FTR_SPLIT_ID_CACHE) mfmsr r10 rlwinm r0,r10,0,28,26 /* clear DR */ mtmsr r0 diff --git a/trunk/arch/ppc/kernel/ppc_ksyms.c b/trunk/arch/ppc/kernel/ppc_ksyms.c index 63f0a987139b..a4165209ac7c 100644 --- a/trunk/arch/ppc/kernel/ppc_ksyms.c +++ b/trunk/arch/ppc/kernel/ppc_ksyms.c @@ -64,6 +64,7 @@ extern unsigned long mm_ptov (unsigned long paddr); EXPORT_SYMBOL(clear_pages); EXPORT_SYMBOL(clear_user_page); +EXPORT_SYMBOL(do_signal); EXPORT_SYMBOL(transfer_to_handler); EXPORT_SYMBOL(do_IRQ); EXPORT_SYMBOL(machine_check_exception); diff --git a/trunk/arch/ppc/kernel/setup.c b/trunk/arch/ppc/kernel/setup.c index 967c1ef59a6b..c79704f5409c 100644 --- a/trunk/arch/ppc/kernel/setup.c +++ b/trunk/arch/ppc/kernel/setup.c @@ -526,7 +526,7 @@ void __init setup_arch(char **cmdline_p) * Systems with OF can look in the properties on the cpu node(s) * for a possibly more accurate value. */ - if (! cpu_has_feature(CPU_FTR_UNIFIED_ID_CACHE)) { + if (cpu_has_feature(CPU_FTR_SPLIT_ID_CACHE)) { dcache_bsize = cur_cpu_spec->dcache_bsize; icache_bsize = cur_cpu_spec->icache_bsize; ucache_bsize = 0; diff --git a/trunk/arch/ppc/mm/tlb.c b/trunk/arch/ppc/mm/tlb.c index 4ff260bc9dd1..fa29740a28f5 100644 --- a/trunk/arch/ppc/mm/tlb.c +++ b/trunk/arch/ppc/mm/tlb.c @@ -27,7 +27,6 @@ #include #include #include -#include #include #include diff --git a/trunk/arch/ppc/platforms/prep_setup.c b/trunk/arch/ppc/platforms/prep_setup.c index 3c56654bfc6f..6f21110a9747 100644 --- a/trunk/arch/ppc/platforms/prep_setup.c +++ b/trunk/arch/ppc/platforms/prep_setup.c @@ -69,6 +69,9 @@ TODC_ALLOC(); +unsigned char ucBoardRev; +unsigned char ucBoardRevMaj, ucBoardRevMin; + extern unsigned char prep_nvram_read_val(int addr); extern void prep_nvram_write_val(int addr, unsigned char val); diff --git a/trunk/arch/ppc/syslib/Makefile b/trunk/arch/ppc/syslib/Makefile index 543795be58c8..95694159b226 100644 --- a/trunk/arch/ppc/syslib/Makefile +++ b/trunk/arch/ppc/syslib/Makefile @@ -7,7 +7,6 @@ CFLAGS_btext.o += -fPIC wdt-mpc8xx-$(CONFIG_8xx_WDT) += m8xx_wdt.o -obj-$(CONFIG_PPC_INDIRECT_PCI) += indirect_pci.o obj-$(CONFIG_PPCBUG_NVRAM) += prep_nvram.o obj-$(CONFIG_PPC_OCP) += ocp.o obj-$(CONFIG_IBM_OCP) += ibm_ocp.o diff --git a/trunk/arch/ppc/syslib/indirect_pci.c b/trunk/arch/ppc/syslib/indirect_pci.c deleted file mode 100644 index 83b323a7d029..000000000000 --- a/trunk/arch/ppc/syslib/indirect_pci.c +++ /dev/null @@ -1,134 +0,0 @@ -/* - * Support for indirect PCI bridges. - * - * Copyright (C) 1998 Gabriel Paubert. - * - * 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 - -#ifdef CONFIG_PPC_INDIRECT_PCI_BE -#define PCI_CFG_OUT out_be32 -#else -#define PCI_CFG_OUT out_le32 -#endif - -static int -indirect_read_config(struct pci_bus *bus, unsigned int devfn, int offset, - int len, u32 *val) -{ - struct pci_controller *hose = bus->sysdata; - volatile void __iomem *cfg_data; - u8 cfg_type = 0; - - if (ppc_md.pci_exclude_device) - if (ppc_md.pci_exclude_device(bus->number, devfn)) - return PCIBIOS_DEVICE_NOT_FOUND; - - if (hose->set_cfg_type) - if (bus->number != hose->first_busno) - cfg_type = 1; - - PCI_CFG_OUT(hose->cfg_addr, - (0x80000000 | ((bus->number - hose->bus_offset) << 16) - | (devfn << 8) | ((offset & 0xfc) | cfg_type))); - - /* - * Note: the caller has already checked that offset is - * suitably aligned and that len is 1, 2 or 4. - */ - cfg_data = hose->cfg_data + (offset & 3); - switch (len) { - case 1: - *val = in_8(cfg_data); - break; - case 2: - *val = in_le16(cfg_data); - break; - default: - *val = in_le32(cfg_data); - break; - } - return PCIBIOS_SUCCESSFUL; -} - -static int -indirect_write_config(struct pci_bus *bus, unsigned int devfn, int offset, - int len, u32 val) -{ - struct pci_controller *hose = bus->sysdata; - volatile void __iomem *cfg_data; - u8 cfg_type = 0; - - if (ppc_md.pci_exclude_device) - if (ppc_md.pci_exclude_device(bus->number, devfn)) - return PCIBIOS_DEVICE_NOT_FOUND; - - if (hose->set_cfg_type) - if (bus->number != hose->first_busno) - cfg_type = 1; - - PCI_CFG_OUT(hose->cfg_addr, - (0x80000000 | ((bus->number - hose->bus_offset) << 16) - | (devfn << 8) | ((offset & 0xfc) | cfg_type))); - - /* - * Note: the caller has already checked that offset is - * suitably aligned and that len is 1, 2 or 4. - */ - cfg_data = hose->cfg_data + (offset & 3); - switch (len) { - case 1: - out_8(cfg_data, val); - break; - case 2: - out_le16(cfg_data, val); - break; - default: - out_le32(cfg_data, val); - break; - } - return PCIBIOS_SUCCESSFUL; -} - -static struct pci_ops indirect_pci_ops = -{ - indirect_read_config, - indirect_write_config -}; - -void __init -setup_indirect_pci_nomap(struct pci_controller* hose, void __iomem * cfg_addr, - void __iomem * cfg_data) -{ - hose->cfg_addr = cfg_addr; - hose->cfg_data = cfg_data; - hose->ops = &indirect_pci_ops; -} - -void __init -setup_indirect_pci(struct pci_controller* hose, u32 cfg_addr, u32 cfg_data) -{ - unsigned long base = cfg_addr & PAGE_MASK; - void __iomem *mbase, *addr, *data; - - mbase = ioremap(base, PAGE_SIZE); - addr = mbase + (cfg_addr & ~PAGE_MASK); - if ((cfg_data & PAGE_MASK) != base) - mbase = ioremap(cfg_data & PAGE_MASK, PAGE_SIZE); - data = mbase + (cfg_data & ~PAGE_MASK); - setup_indirect_pci_nomap(hose, addr, data); -} diff --git a/trunk/arch/ppc/syslib/virtex_devices.c b/trunk/arch/ppc/syslib/virtex_devices.c index ace4ec08de51..16546788e23b 100644 --- a/trunk/arch/ppc/syslib/virtex_devices.c +++ b/trunk/arch/ppc/syslib/virtex_devices.c @@ -71,21 +71,6 @@ }, \ } -/* - * ML300/ML403 Video Device: shortcut macro for single instance - */ -#define XPAR_TFT(num) { \ - .name = "xilinxfb", \ - .id = num, \ - .num_resources = 1, \ - .resource = (struct resource[]) { \ - { \ - .start = XPAR_TFT_##num##_BASEADDR, \ - .end = XPAR_TFT_##num##_BASEADDR+7, \ - .flags = IORESOURCE_IO, \ - }, \ - }, \ -} /* UART 8250 driver platform data table */ struct plat_serial8250_port virtex_serial_platform_data[] = { @@ -161,17 +146,20 @@ struct platform_device virtex_platform_devices[] = { XPAR_SYSACE(1), #endif + /* ML300/403 reference design framebuffer */ #if defined(XPAR_TFT_0_BASEADDR) - XPAR_TFT(0), -#endif -#if defined(XPAR_TFT_1_BASEADDR) - XPAR_TFT(1), -#endif -#if defined(XPAR_TFT_2_BASEADDR) - XPAR_TFT(2), -#endif -#if defined(XPAR_TFT_3_BASEADDR) - XPAR_TFT(3), + { + .name = "xilinxfb", + .id = 0, + .num_resources = 1, + .resource = (struct resource[]) { + { + .start = XPAR_TFT_0_BASEADDR, + .end = XPAR_TFT_0_BASEADDR+7, + .flags = IORESOURCE_IO, + }, + }, + }, #endif }; diff --git a/trunk/drivers/block/viodasd.c b/trunk/drivers/block/viodasd.c index dae39911a11d..68592c336011 100644 --- a/trunk/drivers/block/viodasd.c +++ b/trunk/drivers/block/viodasd.c @@ -252,10 +252,10 @@ static int viodasd_getgeo(struct block_device *bdev, struct hd_geometry *geo) struct gendisk *disk = bdev->bd_disk; struct viodasd_device *d = disk->private_data; - geo->sectors = d->sectors ? d->sectors : 32; + geo->sectors = d->sectors ? d->sectors : 0; geo->heads = d->tracks ? d->tracks : 64; geo->cylinders = d->cylinders ? d->cylinders : - get_capacity(disk) / (geo->sectors * geo->heads); + get_capacity(disk) / (geo->cylinders * geo->heads); return 0; } diff --git a/trunk/drivers/char/briq_panel.c b/trunk/drivers/char/briq_panel.c index b6f2639f903d..ed53f541d9e8 100644 --- a/trunk/drivers/char/briq_panel.c +++ b/trunk/drivers/char/briq_panel.c @@ -91,6 +91,11 @@ static ssize_t briq_panel_read(struct file *file, char __user *buf, size_t count unsigned short c; unsigned char cp; +#if 0 /* Can't seek (pread) on this device */ + if (ppos != &file->f_pos) + return -ESPIPE; +#endif + if (!vfd_is_open) return -ENODEV; @@ -134,6 +139,11 @@ static ssize_t briq_panel_write(struct file *file, const char __user *buf, size_ size_t indx = len; int i, esc = 0; +#if 0 /* Can't seek (pwrite) on this device */ + if (ppos != &file->f_pos) + return -ESPIPE; +#endif + if (!vfd_is_open) return -EBUSY; diff --git a/trunk/drivers/char/drm/sis_mm.c b/trunk/drivers/char/drm/sis_mm.c index 0580fa33cb77..441bbdbf1510 100644 --- a/trunk/drivers/char/drm/sis_mm.c +++ b/trunk/drivers/char/drm/sis_mm.c @@ -94,7 +94,7 @@ static int sis_fb_init(DRM_IOCTL_ARGS) mutex_lock(&dev->struct_mutex); #if defined(CONFIG_FB_SIS) { - drm_sman_mm_t sman_mm; + struct drm_sman_mm sman_mm; sman_mm.private = (void *)0xFFFFFFFF; sman_mm.allocate = sis_sman_mm_allocate; sman_mm.free = sis_sman_mm_free; diff --git a/trunk/drivers/char/hvc_console.c b/trunk/drivers/char/hvc_console.c index b3ab42e0dd4a..322bc5f7d86b 100644 --- a/trunk/drivers/char/hvc_console.c +++ b/trunk/drivers/char/hvc_console.c @@ -674,7 +674,7 @@ static const cpumask_t cpus_in_xmon = CPU_MASK_NONE; * calling hvc_poll() who determines whether a console adapter support * interrupts. */ -static int khvcd(void *unused) +int khvcd(void *unused) { int poll_mask; struct hvc_struct *hp; diff --git a/trunk/drivers/char/viotape.c b/trunk/drivers/char/viotape.c index db57277117bb..13faf8d17482 100644 --- a/trunk/drivers/char/viotape.c +++ b/trunk/drivers/char/viotape.c @@ -873,12 +873,12 @@ static int viotap_release(struct inode *inode, struct file *file) } const struct file_operations viotap_fops = { - .owner = THIS_MODULE, - .read = viotap_read, - .write = viotap_write, - .ioctl = viotap_ioctl, - .open = viotap_open, - .release = viotap_release, + owner: THIS_MODULE, + read: viotap_read, + write: viotap_write, + ioctl: viotap_ioctl, + open: viotap_open, + release: viotap_release, }; /* Handle interrupt events for tape */ diff --git a/trunk/drivers/net/8139cp.c b/trunk/drivers/net/8139cp.c index e970e64bf966..807e6992e614 100644 --- a/trunk/drivers/net/8139cp.c +++ b/trunk/drivers/net/8139cp.c @@ -26,6 +26,7 @@ TODO: * Test Tx checksumming thoroughly + * Implement dev->tx_timeout Low priority TODO: * Complete reset on PciErr @@ -1217,30 +1218,6 @@ static int cp_close (struct net_device *dev) return 0; } -static void cp_tx_timeout(struct net_device *dev) -{ - struct cp_private *cp = netdev_priv(dev); - unsigned long flags; - int rc; - - printk(KERN_WARNING "%s: Transmit timeout, status %2x %4x %4x %4x\n", - dev->name, cpr8(Cmd), cpr16(CpCmd), - cpr16(IntrStatus), cpr16(IntrMask)); - - spin_lock_irqsave(&cp->lock, flags); - - cp_stop_hw(cp); - cp_clean_rings(cp); - rc = cp_init_rings(cp); - cp_start_hw(cp); - - netif_wake_queue(dev); - - spin_unlock_irqrestore(&cp->lock, flags); - - return; -} - #ifdef BROKEN static int cp_change_mtu(struct net_device *dev, int new_mtu) { @@ -1943,8 +1920,10 @@ static int cp_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) dev->change_mtu = cp_change_mtu; #endif dev->ethtool_ops = &cp_ethtool_ops; +#if 0 dev->tx_timeout = cp_tx_timeout; dev->watchdog_timeo = TX_TIMEOUT; +#endif #if CP_VLAN_TAG_USED dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; diff --git a/trunk/drivers/net/Kconfig b/trunk/drivers/net/Kconfig index 43d03178064d..713ab05a87c0 100644 --- a/trunk/drivers/net/Kconfig +++ b/trunk/drivers/net/Kconfig @@ -205,7 +205,7 @@ config MII config MACB tristate "Atmel MACB support" depends on AVR32 || ARCH_AT91SAM9260 || ARCH_AT91SAM9263 - select PHYLIB + select MII help The Atmel MACB ethernet interface is found on many AT32 and AT91 parts. Say Y to include support for the MACB chip. diff --git a/trunk/drivers/net/arm/Kconfig b/trunk/drivers/net/arm/Kconfig index f9cc2b621fe2..5bf2d33887ac 100644 --- a/trunk/drivers/net/arm/Kconfig +++ b/trunk/drivers/net/arm/Kconfig @@ -43,7 +43,6 @@ config ARM_AT91_ETHER config EP93XX_ETH tristate "EP93xx Ethernet support" depends on ARM && ARCH_EP93XX - select MII help This is a driver for the ethernet hardware included in EP93xx CPUs. Say Y if you are building a kernel for EP93xx based devices. diff --git a/trunk/drivers/net/atl1/atl1.h b/trunk/drivers/net/atl1/atl1.h index ff4765f6c3de..df4c1a0071aa 100644 --- a/trunk/drivers/net/atl1/atl1.h +++ b/trunk/drivers/net/atl1/atl1.h @@ -43,7 +43,6 @@ extern const struct ethtool_ops atl1_ethtool_ops; struct atl1_adapter; #define ATL1_MAX_INTR 3 -#define ATL1_MAX_TX_BUF_LEN 0x3000 /* 12288 bytes */ #define ATL1_DEFAULT_TPD 256 #define ATL1_MAX_TPD 1024 @@ -58,45 +57,29 @@ struct atl1_adapter; #define ATL1_RRD_DESC(R, i) ATL1_GET_DESC(R, i, struct rx_return_desc) /* - * This detached comment is preserved for documentation purposes only. - * It was originally attached to some code that got deleted, but seems - * important enough to keep around... - * - * * Some workarounds require millisecond delays and are run during interrupt * context. Most notably, when establishing link, the phy may need tweaking * but cannot process phy register reads/writes faster than millisecond * intervals...and we establish link due to a "link status change" interrupt. - * - */ - -/* - * atl1_ring_header represents a single, contiguous block of DMA space - * mapped for the three descriptor rings (tpd, rfd, rrd) and the two - * message blocks (cmb, smb) described below */ -struct atl1_ring_header { - void *desc; /* virtual address */ - dma_addr_t dma; /* physical address*/ - unsigned int size; /* length in bytes */ -}; /* - * atl1_buffer is wrapper around a pointer to a socket buffer - * so a DMA handle can be stored along with the skb + * wrapper around a pointer to a socket buffer, + * so a DMA handle can be stored along with the buffer */ struct atl1_buffer { - struct sk_buff *skb; /* socket buffer */ - u16 length; /* rx buffer length */ - u16 alloced; /* 1 if skb allocated */ + struct sk_buff *skb; + u16 length; + u16 alloced; dma_addr_t dma; }; -/* transmit packet descriptor (tpd) ring */ +#define MAX_TX_BUF_LEN 0x3000 /* 12KB */ + struct atl1_tpd_ring { - void *desc; /* descriptor ring virtual address */ - dma_addr_t dma; /* descriptor ring physical address */ - u16 size; /* descriptor ring length in bytes */ + void *desc; /* pointer to the descriptor ring memory */ + dma_addr_t dma; /* physical adress of the descriptor ring */ + u16 size; /* length of descriptor ring in bytes */ u16 count; /* number of descriptors in the ring */ u16 hw_idx; /* hardware index */ atomic_t next_to_clean; @@ -104,34 +87,36 @@ struct atl1_tpd_ring { struct atl1_buffer *buffer_info; }; -/* receive free descriptor (rfd) ring */ struct atl1_rfd_ring { - void *desc; /* descriptor ring virtual address */ - dma_addr_t dma; /* descriptor ring physical address */ - u16 size; /* descriptor ring length in bytes */ - u16 count; /* number of descriptors in the ring */ + void *desc; + dma_addr_t dma; + u16 size; + u16 count; atomic_t next_to_use; u16 next_to_clean; struct atl1_buffer *buffer_info; }; -/* receive return descriptor (rrd) ring */ struct atl1_rrd_ring { - void *desc; /* descriptor ring virtual address */ - dma_addr_t dma; /* descriptor ring physical address */ - unsigned int size; /* descriptor ring length in bytes */ - u16 count; /* number of descriptors in the ring */ + void *desc; + dma_addr_t dma; + unsigned int size; + u16 count; u16 next_to_use; atomic_t next_to_clean; }; -/* coalescing message block (cmb) */ +struct atl1_ring_header { + void *desc; /* pointer to the descriptor ring memory */ + dma_addr_t dma; /* physical adress of the descriptor ring */ + unsigned int size; /* length of descriptor ring in bytes */ +}; + struct atl1_cmb { struct coals_msg_block *cmb; dma_addr_t dma; }; -/* statistics message block (smb) */ struct atl1_smb { struct stats_msg_block *smb; dma_addr_t dma; @@ -156,26 +141,24 @@ struct atl1_sft_stats { u64 tx_aborted_errors; u64 tx_window_errors; u64 tx_carrier_errors; - u64 tx_pause; /* num pause packets transmitted. */ - u64 excecol; /* num tx packets w/ excessive collisions. */ - u64 deffer; /* num tx packets deferred */ - u64 scc; /* num packets subsequently transmitted - * successfully w/ single prior collision. */ - u64 mcc; /* num packets subsequently transmitted - * successfully w/ multiple prior collisions. */ + + u64 tx_pause; /* num Pause packet transmitted. */ + u64 excecol; /* num tx packets aborted due to excessive collisions. */ + u64 deffer; /* num deferred tx packets */ + u64 scc; /* num packets subsequently transmitted successfully w/ single prior collision. */ + u64 mcc; /* num packets subsequently transmitted successfully w/ multiple prior collisions. */ u64 latecol; /* num tx packets w/ late collisions. */ - u64 tx_underun; /* num tx packets aborted due to transmit - * FIFO underrun, or TRD FIFO underrun */ - u64 tx_trunc; /* num tx packets truncated due to size - * exceeding MTU, regardless whether truncated - * by the chip or not. (The name doesn't really - * reflect the meaning in this case.) */ + u64 tx_underun; /* num tx packets aborted due to transmit FIFO underrun, or TRD FIFO underrun */ + u64 tx_trunc; /* num tx packets truncated due to size exceeding MTU, regardless whether truncated by Selene or not. (The name doesn't really reflect the meaning in this case.) */ u64 rx_pause; /* num Pause packets received. */ u64 rx_rrd_ov; u64 rx_trunc; }; -/* hardware structure */ +/* board specific private data structure */ +#define ATL1_REGS_LEN 8 + +/* Structure containing variables used by the shared code */ struct atl1_hw { u8 __iomem *hw_addr; struct atl1_adapter *back; @@ -184,35 +167,24 @@ struct atl1_hw { enum atl1_dma_req_block dmar_block; enum atl1_dma_req_block dmaw_block; u8 preamble_len; - u8 max_retry; /* Retransmission maximum, after which the - * packet will be discarded */ - u8 jam_ipg; /* IPG to start JAM for collision based flow - * control in half-duplex mode. In units of - * 8-bit time */ - u8 ipgt; /* Desired back to back inter-packet gap. - * The default is 96-bit time */ - u8 min_ifg; /* Minimum number of IFG to enforce in between - * receive frames. Frame gap below such IFP - * is dropped */ + u8 max_retry; /* Retransmission maximum, after which the packet will be discarded */ + u8 jam_ipg; /* IPG to start JAM for collision based flow control in half-duplex mode. In units of 8-bit time */ + u8 ipgt; /* Desired back to back inter-packet gap. The default is 96-bit time */ + u8 min_ifg; /* Minimum number of IFG to enforce in between RX frames. Frame gap below such IFP is dropped */ u8 ipgr1; /* 64bit Carrier-Sense window */ u8 ipgr2; /* 96-bit IPG window */ - u8 tpd_burst; /* Number of TPD to prefetch in cache-aligned - * burst. Each TPD is 16 bytes long */ - u8 rfd_burst; /* Number of RFD to prefetch in cache-aligned - * burst. Each RFD is 12 bytes long */ + u8 tpd_burst; /* Number of TPD to prefetch in cache-aligned burst. Each TPD is 16 bytes long */ + u8 rfd_burst; /* Number of RFD to prefetch in cache-aligned burst. Each RFD is 12 bytes long */ u8 rfd_fetch_gap; - u8 rrd_burst; /* Threshold number of RRDs that can be retired - * in a burst. Each RRD is 16 bytes long */ + u8 rrd_burst; /* Threshold number of RRDs that can be retired in a burst. Each RRD is 16 bytes long */ u8 tpd_fetch_th; u8 tpd_fetch_gap; u16 tx_jumbo_task_th; - u16 txf_burst; /* Number of data bytes to read in a cache- - * aligned burst. Each SRAM entry is 8 bytes */ - u16 rx_jumbo_th; /* Jumbo packet size for non-VLAN packet. VLAN - * packets should add 4 bytes */ + u16 txf_burst; /* Number of data bytes to read in a cache-aligned burst. Each SRAM entry is + 8 bytes long */ + u16 rx_jumbo_th; /* Jumbo packet size for non-VLAN packet. VLAN packets should add 4 bytes */ u16 rx_jumbo_lkah; - u16 rrd_ret_timer; /* RRD retirement timer. Decrement by 1 after - * every 512ns passes. */ + u16 rrd_ret_timer; /* RRD retirement timer. Decrement by 1 after every 512ns passes. */ u16 lcol; /* Collision Window */ u16 cmb_tpd; @@ -222,35 +194,48 @@ struct atl1_hw { u32 smb_timer; u16 media_type; u16 autoneg_advertised; + u16 pci_cmd_word; u16 mii_autoneg_adv_reg; u16 mii_1000t_ctrl_reg; + u32 mem_rang; + u32 txcw; u32 max_frame_size; u32 min_frame_size; + u32 mc_filter_type; + u32 num_mc_addrs; + u32 collision_delta; + u32 tx_packet_delta; + u16 phy_spd_default; u16 dev_rev; /* spi flash */ u8 flash_vendor; + u8 dma_fairness; u8 mac_addr[ETH_ALEN]; u8 perm_mac_addr[ETH_ALEN]; + /* bool phy_preamble_sup; */ bool phy_configured; }; struct atl1_adapter { + /* OS defined structs */ struct net_device *netdev; struct pci_dev *pdev; struct net_device_stats net_stats; struct atl1_sft_stats soft_stats; + struct vlan_group *vlgrp; u32 rx_buffer_len; u32 wol; u16 link_speed; u16 link_duplex; spinlock_t lock; + atomic_t irq_sem; struct work_struct tx_timeout_task; struct work_struct link_chg_task; struct work_struct pcie_dma_to_rst_task; @@ -258,7 +243,9 @@ struct atl1_adapter { struct timer_list phy_config_timer; bool phy_timer_pending; - /* all descriptor rings' memory */ + bool mac_disabled; + + /* All descriptor rings' memory */ struct atl1_ring_header ring_header; /* TX */ @@ -271,16 +258,25 @@ struct atl1_adapter { u64 hw_csum_err; u64 hw_csum_good; - u16 imt; /* interrupt moderator timer (2us resolution */ - u16 ict; /* interrupt clear timer (2us resolution */ - struct mii_if_info mii; /* MII interface info */ + u32 gorcl; + u64 gorcl_old; + + /* Interrupt Moderator timer ( 2us resolution) */ + u16 imt; + /* Interrupt Clear timer (2us resolution) */ + u16 ict; + + /* MII interface info */ + struct mii_if_info mii; /* structs defined in atl1_hw.h */ - u32 bd_number; /* board number */ + u32 bd_number; /* board number */ bool pci_using_64; struct atl1_hw hw; struct atl1_smb smb; struct atl1_cmb cmb; + + u32 pci_state[16]; }; #endif /* _ATL1_H_ */ diff --git a/trunk/drivers/net/atl1/atl1_main.c b/trunk/drivers/net/atl1/atl1_main.c index 4a18b881ae9a..501919eb7f5e 100644 --- a/trunk/drivers/net/atl1/atl1_main.c +++ b/trunk/drivers/net/atl1/atl1_main.c @@ -38,7 +38,7 @@ * TODO: * Fix TSO; tx performance is horrible with TSO enabled. * Wake on LAN. - * Add more ethtool functions. + * Add more ethtool functions, including set ring parameters. * Fix abstruse irq enable/disable condition described here: * http://marc.theaimsgroup.com/?l=linux-netdev&m=116398508500553&w=2 * @@ -158,70 +158,13 @@ static int __devinit atl1_sw_init(struct atl1_adapter *adapter) hw->cmb_tx_timer = 1; /* about 2us */ hw->smb_timer = 100000; /* about 200ms */ + atomic_set(&adapter->irq_sem, 0); spin_lock_init(&adapter->lock); spin_lock_init(&adapter->mb_lock); return 0; } -static int mdio_read(struct net_device *netdev, int phy_id, int reg_num) -{ - struct atl1_adapter *adapter = netdev_priv(netdev); - u16 result; - - atl1_read_phy_reg(&adapter->hw, reg_num & 0x1f, &result); - - return result; -} - -static void mdio_write(struct net_device *netdev, int phy_id, int reg_num, - int val) -{ - struct atl1_adapter *adapter = netdev_priv(netdev); - - atl1_write_phy_reg(&adapter->hw, reg_num, val); -} - -/* - * atl1_mii_ioctl - - * @netdev: - * @ifreq: - * @cmd: - */ -static int atl1_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) -{ - struct atl1_adapter *adapter = netdev_priv(netdev); - unsigned long flags; - int retval; - - if (!netif_running(netdev)) - return -EINVAL; - - spin_lock_irqsave(&adapter->lock, flags); - retval = generic_mii_ioctl(&adapter->mii, if_mii(ifr), cmd, NULL); - spin_unlock_irqrestore(&adapter->lock, flags); - - return retval; -} - -/* - * atl1_ioctl - - * @netdev: - * @ifreq: - * @cmd: - */ -static int atl1_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) -{ - switch (cmd) { - case SIOCGMIIPHY: - case SIOCGMIIREG: - case SIOCSMIIREG: - return atl1_mii_ioctl(netdev, ifr, cmd); - default: - return -EOPNOTSUPP; - } -} - /* * atl1_setup_mem_resources - allocate Tx / RX descriptor resources * @adapter: board private structure @@ -245,22 +188,19 @@ s32 atl1_setup_ring_resources(struct atl1_adapter *adapter) goto err_nomem; } rfd_ring->buffer_info = - (struct atl1_buffer *)(tpd_ring->buffer_info + tpd_ring->count); + (struct atl1_buffer *)(tpd_ring->buffer_info + tpd_ring->count); - /* real ring DMA buffer - * each ring/block may need up to 8 bytes for alignment, hence the - * additional 40 bytes tacked onto the end. - */ - ring_header->size = size = - sizeof(struct tx_packet_desc) * tpd_ring->count - + sizeof(struct rx_free_desc) * rfd_ring->count - + sizeof(struct rx_return_desc) * rrd_ring->count - + sizeof(struct coals_msg_block) - + sizeof(struct stats_msg_block) - + 40; + /* real ring DMA buffer */ + ring_header->size = size = sizeof(struct tx_packet_desc) * + tpd_ring->count + + sizeof(struct rx_free_desc) * rfd_ring->count + + sizeof(struct rx_return_desc) * rrd_ring->count + + sizeof(struct coals_msg_block) + + sizeof(struct stats_msg_block) + + 40; /* "40: for 8 bytes align" huh? -- CHS */ ring_header->desc = pci_alloc_consistent(pdev, ring_header->size, - &ring_header->dma); + &ring_header->dma); if (unlikely(!ring_header->desc)) { dev_err(&pdev->dev, "pci_alloc_consistent failed\n"); goto err_nomem; @@ -274,6 +214,8 @@ s32 atl1_setup_ring_resources(struct atl1_adapter *adapter) tpd_ring->dma += offset; tpd_ring->desc = (u8 *) ring_header->desc + offset; tpd_ring->size = sizeof(struct tx_packet_desc) * tpd_ring->count; + atomic_set(&tpd_ring->next_to_use, 0); + atomic_set(&tpd_ring->next_to_clean, 0); /* init RFD ring */ rfd_ring->dma = tpd_ring->dma + tpd_ring->size; @@ -281,7 +223,9 @@ s32 atl1_setup_ring_resources(struct atl1_adapter *adapter) rfd_ring->dma += offset; rfd_ring->desc = (u8 *) tpd_ring->desc + (tpd_ring->size + offset); rfd_ring->size = sizeof(struct rx_free_desc) * rfd_ring->count; - + rfd_ring->next_to_clean = 0; + /* rfd_ring->next_to_use = rfd_ring->count - 1; */ + atomic_set(&rfd_ring->next_to_use, 0); /* init RRD ring */ rrd_ring->dma = rfd_ring->dma + rfd_ring->size; @@ -289,22 +233,23 @@ s32 atl1_setup_ring_resources(struct atl1_adapter *adapter) rrd_ring->dma += offset; rrd_ring->desc = (u8 *) rfd_ring->desc + (rfd_ring->size + offset); rrd_ring->size = sizeof(struct rx_return_desc) * rrd_ring->count; - + rrd_ring->next_to_use = 0; + atomic_set(&rrd_ring->next_to_clean, 0); /* init CMB */ adapter->cmb.dma = rrd_ring->dma + rrd_ring->size; offset = (adapter->cmb.dma & 0x7) ? (8 - (adapter->cmb.dma & 0x7)) : 0; adapter->cmb.dma += offset; - adapter->cmb.cmb = (struct coals_msg_block *) - ((u8 *) rrd_ring->desc + (rrd_ring->size + offset)); + adapter->cmb.cmb = + (struct coals_msg_block *) ((u8 *) rrd_ring->desc + + (rrd_ring->size + offset)); /* init SMB */ adapter->smb.dma = adapter->cmb.dma + sizeof(struct coals_msg_block); offset = (adapter->smb.dma & 0x7) ? (8 - (adapter->smb.dma & 0x7)) : 0; adapter->smb.dma += offset; adapter->smb.smb = (struct stats_msg_block *) - ((u8 *) adapter->cmb.cmb + - (sizeof(struct coals_msg_block) + offset)); + ((u8 *) adapter->cmb.cmb + (sizeof(struct coals_msg_block) + offset)); return ATL1_SUCCESS; @@ -313,1121 +258,984 @@ s32 atl1_setup_ring_resources(struct atl1_adapter *adapter) return -ENOMEM; } -void atl1_init_ring_ptrs(struct atl1_adapter *adapter) +/* + * atl1_irq_enable - Enable default interrupt generation settings + * @adapter: board private structure + */ +static void atl1_irq_enable(struct atl1_adapter *adapter) { - struct atl1_tpd_ring *tpd_ring = &adapter->tpd_ring; - struct atl1_rfd_ring *rfd_ring = &adapter->rfd_ring; - struct atl1_rrd_ring *rrd_ring = &adapter->rrd_ring; - - atomic_set(&tpd_ring->next_to_use, 0); - atomic_set(&tpd_ring->next_to_clean, 0); + if (likely(!atomic_dec_and_test(&adapter->irq_sem))) + iowrite32(IMR_NORMAL_MASK, adapter->hw.hw_addr + REG_IMR); +} - rfd_ring->next_to_clean = 0; - atomic_set(&rfd_ring->next_to_use, 0); +static void atl1_clear_phy_int(struct atl1_adapter *adapter) +{ + u16 phy_data; + unsigned long flags; - rrd_ring->next_to_use = 0; - atomic_set(&rrd_ring->next_to_clean, 0); + spin_lock_irqsave(&adapter->lock, flags); + atl1_read_phy_reg(&adapter->hw, 19, &phy_data); + spin_unlock_irqrestore(&adapter->lock, flags); } -/* - * atl1_clean_rx_ring - Free RFD Buffers - * @adapter: board private structure - */ -static void atl1_clean_rx_ring(struct atl1_adapter *adapter) +static void atl1_inc_smb(struct atl1_adapter *adapter) { - struct atl1_rfd_ring *rfd_ring = &adapter->rfd_ring; - struct atl1_rrd_ring *rrd_ring = &adapter->rrd_ring; - struct atl1_buffer *buffer_info; - struct pci_dev *pdev = adapter->pdev; - unsigned long size; - unsigned int i; + struct stats_msg_block *smb = adapter->smb.smb; - /* Free all the Rx ring sk_buffs */ - for (i = 0; i < rfd_ring->count; i++) { - buffer_info = &rfd_ring->buffer_info[i]; - if (buffer_info->dma) { - pci_unmap_page(pdev, buffer_info->dma, - buffer_info->length, PCI_DMA_FROMDEVICE); - buffer_info->dma = 0; - } - if (buffer_info->skb) { - dev_kfree_skb(buffer_info->skb); - buffer_info->skb = NULL; - } - } + /* Fill out the OS statistics structure */ + adapter->soft_stats.rx_packets += smb->rx_ok; + adapter->soft_stats.tx_packets += smb->tx_ok; + adapter->soft_stats.rx_bytes += smb->rx_byte_cnt; + adapter->soft_stats.tx_bytes += smb->tx_byte_cnt; + adapter->soft_stats.multicast += smb->rx_mcast; + adapter->soft_stats.collisions += (smb->tx_1_col + + smb->tx_2_col * 2 + + smb->tx_late_col + + smb->tx_abort_col * + adapter->hw.max_retry); - size = sizeof(struct atl1_buffer) * rfd_ring->count; - memset(rfd_ring->buffer_info, 0, size); + /* Rx Errors */ + adapter->soft_stats.rx_errors += (smb->rx_frag + + smb->rx_fcs_err + + smb->rx_len_err + + smb->rx_sz_ov + + smb->rx_rxf_ov + + smb->rx_rrd_ov + smb->rx_align_err); + adapter->soft_stats.rx_fifo_errors += smb->rx_rxf_ov; + adapter->soft_stats.rx_length_errors += smb->rx_len_err; + adapter->soft_stats.rx_crc_errors += smb->rx_fcs_err; + adapter->soft_stats.rx_frame_errors += smb->rx_align_err; + adapter->soft_stats.rx_missed_errors += (smb->rx_rrd_ov + + smb->rx_rxf_ov); - /* Zero out the descriptor ring */ - memset(rfd_ring->desc, 0, rfd_ring->size); + adapter->soft_stats.rx_pause += smb->rx_pause; + adapter->soft_stats.rx_rrd_ov += smb->rx_rrd_ov; + adapter->soft_stats.rx_trunc += smb->rx_sz_ov; - rfd_ring->next_to_clean = 0; - atomic_set(&rfd_ring->next_to_use, 0); + /* Tx Errors */ + adapter->soft_stats.tx_errors += (smb->tx_late_col + + smb->tx_abort_col + + smb->tx_underrun + smb->tx_trunc); + adapter->soft_stats.tx_fifo_errors += smb->tx_underrun; + adapter->soft_stats.tx_aborted_errors += smb->tx_abort_col; + adapter->soft_stats.tx_window_errors += smb->tx_late_col; - rrd_ring->next_to_use = 0; - atomic_set(&rrd_ring->next_to_clean, 0); + adapter->soft_stats.excecol += smb->tx_abort_col; + adapter->soft_stats.deffer += smb->tx_defer; + adapter->soft_stats.scc += smb->tx_1_col; + adapter->soft_stats.mcc += smb->tx_2_col; + adapter->soft_stats.latecol += smb->tx_late_col; + adapter->soft_stats.tx_underun += smb->tx_underrun; + adapter->soft_stats.tx_trunc += smb->tx_trunc; + adapter->soft_stats.tx_pause += smb->tx_pause; + + adapter->net_stats.rx_packets = adapter->soft_stats.rx_packets; + adapter->net_stats.tx_packets = adapter->soft_stats.tx_packets; + adapter->net_stats.rx_bytes = adapter->soft_stats.rx_bytes; + adapter->net_stats.tx_bytes = adapter->soft_stats.tx_bytes; + adapter->net_stats.multicast = adapter->soft_stats.multicast; + adapter->net_stats.collisions = adapter->soft_stats.collisions; + adapter->net_stats.rx_errors = adapter->soft_stats.rx_errors; + adapter->net_stats.rx_over_errors = + adapter->soft_stats.rx_missed_errors; + adapter->net_stats.rx_length_errors = + adapter->soft_stats.rx_length_errors; + adapter->net_stats.rx_crc_errors = adapter->soft_stats.rx_crc_errors; + adapter->net_stats.rx_frame_errors = + adapter->soft_stats.rx_frame_errors; + adapter->net_stats.rx_fifo_errors = adapter->soft_stats.rx_fifo_errors; + adapter->net_stats.rx_missed_errors = + adapter->soft_stats.rx_missed_errors; + adapter->net_stats.tx_errors = adapter->soft_stats.tx_errors; + adapter->net_stats.tx_fifo_errors = adapter->soft_stats.tx_fifo_errors; + adapter->net_stats.tx_aborted_errors = + adapter->soft_stats.tx_aborted_errors; + adapter->net_stats.tx_window_errors = + adapter->soft_stats.tx_window_errors; + adapter->net_stats.tx_carrier_errors = + adapter->soft_stats.tx_carrier_errors; } -/* - * atl1_clean_tx_ring - Free Tx Buffers - * @adapter: board private structure - */ -static void atl1_clean_tx_ring(struct atl1_adapter *adapter) +static void atl1_rx_checksum(struct atl1_adapter *adapter, + struct rx_return_desc *rrd, + struct sk_buff *skb) { - struct atl1_tpd_ring *tpd_ring = &adapter->tpd_ring; - struct atl1_buffer *buffer_info; - struct pci_dev *pdev = adapter->pdev; - unsigned long size; - unsigned int i; - - /* Free all the Tx ring sk_buffs */ - for (i = 0; i < tpd_ring->count; i++) { - buffer_info = &tpd_ring->buffer_info[i]; - if (buffer_info->dma) { - pci_unmap_page(pdev, buffer_info->dma, - buffer_info->length, PCI_DMA_TODEVICE); - buffer_info->dma = 0; - } - } + skb->ip_summed = CHECKSUM_NONE; - for (i = 0; i < tpd_ring->count; i++) { - buffer_info = &tpd_ring->buffer_info[i]; - if (buffer_info->skb) { - dev_kfree_skb_any(buffer_info->skb); - buffer_info->skb = NULL; + if (unlikely(rrd->pkt_flg & PACKET_FLAG_ERR)) { + if (rrd->err_flg & (ERR_FLAG_CRC | ERR_FLAG_TRUNC | + ERR_FLAG_CODE | ERR_FLAG_OV)) { + adapter->hw_csum_err++; + dev_dbg(&adapter->pdev->dev, "rx checksum error\n"); + return; } } - size = sizeof(struct atl1_buffer) * tpd_ring->count; - memset(tpd_ring->buffer_info, 0, size); + /* not IPv4 */ + if (!(rrd->pkt_flg & PACKET_FLAG_IPV4)) + /* checksum is invalid, but it's not an IPv4 pkt, so ok */ + return; - /* Zero out the descriptor ring */ - memset(tpd_ring->desc, 0, tpd_ring->size); + /* IPv4 packet */ + if (likely(!(rrd->err_flg & + (ERR_FLAG_IP_CHKSUM | ERR_FLAG_L4_CHKSUM)))) { + skb->ip_summed = CHECKSUM_UNNECESSARY; + adapter->hw_csum_good++; + return; + } - atomic_set(&tpd_ring->next_to_use, 0); - atomic_set(&tpd_ring->next_to_clean, 0); + /* IPv4, but hardware thinks its checksum is wrong */ + dev_dbg(&adapter->pdev->dev, + "hw csum wrong, pkt_flag:%x, err_flag:%x\n", + rrd->pkt_flg, rrd->err_flg); + skb->ip_summed = CHECKSUM_COMPLETE; + skb->csum = htons(rrd->xsz.xsum_sz.rx_chksum); + adapter->hw_csum_err++; + return; } /* - * atl1_free_ring_resources - Free Tx / RX descriptor Resources - * @adapter: board private structure - * - * Free all transmit software resources + * atl1_alloc_rx_buffers - Replace used receive buffers + * @adapter: address of board private structure */ -void atl1_free_ring_resources(struct atl1_adapter *adapter) +static u16 atl1_alloc_rx_buffers(struct atl1_adapter *adapter) { - struct pci_dev *pdev = adapter->pdev; - struct atl1_tpd_ring *tpd_ring = &adapter->tpd_ring; struct atl1_rfd_ring *rfd_ring = &adapter->rfd_ring; - struct atl1_rrd_ring *rrd_ring = &adapter->rrd_ring; - struct atl1_ring_header *ring_header = &adapter->ring_header; - - atl1_clean_tx_ring(adapter); - atl1_clean_rx_ring(adapter); + struct pci_dev *pdev = adapter->pdev; + struct page *page; + unsigned long offset; + struct atl1_buffer *buffer_info, *next_info; + struct sk_buff *skb; + u16 num_alloc = 0; + u16 rfd_next_to_use, next_next; + struct rx_free_desc *rfd_desc; - kfree(tpd_ring->buffer_info); - pci_free_consistent(pdev, ring_header->size, ring_header->desc, - ring_header->dma); + next_next = rfd_next_to_use = atomic_read(&rfd_ring->next_to_use); + if (++next_next == rfd_ring->count) + next_next = 0; + buffer_info = &rfd_ring->buffer_info[rfd_next_to_use]; + next_info = &rfd_ring->buffer_info[next_next]; - tpd_ring->buffer_info = NULL; - tpd_ring->desc = NULL; - tpd_ring->dma = 0; - - rfd_ring->buffer_info = NULL; - rfd_ring->desc = NULL; - rfd_ring->dma = 0; - - rrd_ring->desc = NULL; - rrd_ring->dma = 0; -} - -static void atl1_setup_mac_ctrl(struct atl1_adapter *adapter) -{ - u32 value; - struct atl1_hw *hw = &adapter->hw; - struct net_device *netdev = adapter->netdev; - /* Config MAC CTRL Register */ - value = MAC_CTRL_TX_EN | MAC_CTRL_RX_EN; - /* duplex */ - if (FULL_DUPLEX == adapter->link_duplex) - value |= MAC_CTRL_DUPLX; - /* speed */ - value |= ((u32) ((SPEED_1000 == adapter->link_speed) ? - MAC_CTRL_SPEED_1000 : MAC_CTRL_SPEED_10_100) << - MAC_CTRL_SPEED_SHIFT); - /* flow control */ - value |= (MAC_CTRL_TX_FLOW | MAC_CTRL_RX_FLOW); - /* PAD & CRC */ - value |= (MAC_CTRL_ADD_CRC | MAC_CTRL_PAD); - /* preamble length */ - value |= (((u32) adapter->hw.preamble_len - & MAC_CTRL_PRMLEN_MASK) << MAC_CTRL_PRMLEN_SHIFT); - /* vlan */ - if (adapter->vlgrp) - value |= MAC_CTRL_RMV_VLAN; - /* rx checksum - if (adapter->rx_csum) - value |= MAC_CTRL_RX_CHKSUM_EN; - */ - /* filter mode */ - value |= MAC_CTRL_BC_EN; - if (netdev->flags & IFF_PROMISC) - value |= MAC_CTRL_PROMIS_EN; - else if (netdev->flags & IFF_ALLMULTI) - value |= MAC_CTRL_MC_ALL_EN; - /* value |= MAC_CTRL_LOOPBACK; */ - iowrite32(value, hw->hw_addr + REG_MAC_CTRL); -} - -/* - * atl1_set_mac - Change the Ethernet Address of the NIC - * @netdev: network interface device structure - * @p: pointer to an address structure - * - * Returns 0 on success, negative on failure - */ -static int atl1_set_mac(struct net_device *netdev, void *p) -{ - struct atl1_adapter *adapter = netdev_priv(netdev); - struct sockaddr *addr = p; - - if (netif_running(netdev)) - return -EBUSY; - - if (!is_valid_ether_addr(addr->sa_data)) - return -EADDRNOTAVAIL; - - memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len); - memcpy(adapter->hw.mac_addr, addr->sa_data, netdev->addr_len); - - atl1_set_mac_addr(&adapter->hw); - return 0; -} - -static u32 atl1_check_link(struct atl1_adapter *adapter) -{ - struct atl1_hw *hw = &adapter->hw; - struct net_device *netdev = adapter->netdev; - u32 ret_val; - u16 speed, duplex, phy_data; - int reconfig = 0; - - /* MII_BMSR must read twice */ - atl1_read_phy_reg(hw, MII_BMSR, &phy_data); - atl1_read_phy_reg(hw, MII_BMSR, &phy_data); - if (!(phy_data & BMSR_LSTATUS)) { /* link down */ - if (netif_carrier_ok(netdev)) { /* old link state: Up */ - dev_info(&adapter->pdev->dev, "link is down\n"); - adapter->link_speed = SPEED_0; - netif_carrier_off(netdev); - netif_stop_queue(netdev); - } - return ATL1_SUCCESS; - } - - /* Link Up */ - ret_val = atl1_get_speed_and_duplex(hw, &speed, &duplex); - if (ret_val) - return ret_val; - - switch (hw->media_type) { - case MEDIA_TYPE_1000M_FULL: - if (speed != SPEED_1000 || duplex != FULL_DUPLEX) - reconfig = 1; - break; - case MEDIA_TYPE_100M_FULL: - if (speed != SPEED_100 || duplex != FULL_DUPLEX) - reconfig = 1; - break; - case MEDIA_TYPE_100M_HALF: - if (speed != SPEED_100 || duplex != HALF_DUPLEX) - reconfig = 1; - break; - case MEDIA_TYPE_10M_FULL: - if (speed != SPEED_10 || duplex != FULL_DUPLEX) - reconfig = 1; - break; - case MEDIA_TYPE_10M_HALF: - if (speed != SPEED_10 || duplex != HALF_DUPLEX) - reconfig = 1; - break; - } - - /* link result is our setting */ - if (!reconfig) { - if (adapter->link_speed != speed - || adapter->link_duplex != duplex) { - adapter->link_speed = speed; - adapter->link_duplex = duplex; - atl1_setup_mac_ctrl(adapter); - dev_info(&adapter->pdev->dev, - "%s link is up %d Mbps %s\n", - netdev->name, adapter->link_speed, - adapter->link_duplex == FULL_DUPLEX ? - "full duplex" : "half duplex"); - } - if (!netif_carrier_ok(netdev)) { /* Link down -> Up */ - netif_carrier_on(netdev); - netif_wake_queue(netdev); + while (!buffer_info->alloced && !next_info->alloced) { + if (buffer_info->skb) { + buffer_info->alloced = 1; + goto next; } - return ATL1_SUCCESS; - } - /* change orignal link status */ - if (netif_carrier_ok(netdev)) { - adapter->link_speed = SPEED_0; - netif_carrier_off(netdev); - netif_stop_queue(netdev); - } + rfd_desc = ATL1_RFD_DESC(rfd_ring, rfd_next_to_use); - if (hw->media_type != MEDIA_TYPE_AUTO_SENSOR && - hw->media_type != MEDIA_TYPE_1000M_FULL) { - switch (hw->media_type) { - case MEDIA_TYPE_100M_FULL: - phy_data = MII_CR_FULL_DUPLEX | MII_CR_SPEED_100 | - MII_CR_RESET; - break; - case MEDIA_TYPE_100M_HALF: - phy_data = MII_CR_SPEED_100 | MII_CR_RESET; - break; - case MEDIA_TYPE_10M_FULL: - phy_data = - MII_CR_FULL_DUPLEX | MII_CR_SPEED_10 | MII_CR_RESET; - break; - default: /* MEDIA_TYPE_10M_HALF: */ - phy_data = MII_CR_SPEED_10 | MII_CR_RESET; + skb = dev_alloc_skb(adapter->rx_buffer_len + NET_IP_ALIGN); + if (unlikely(!skb)) { /* Better luck next round */ + adapter->net_stats.rx_dropped++; break; } - atl1_write_phy_reg(hw, MII_BMCR, phy_data); - return ATL1_SUCCESS; - } - - /* auto-neg, insert timer to re-config phy */ - if (!adapter->phy_timer_pending) { - adapter->phy_timer_pending = true; - mod_timer(&adapter->phy_config_timer, jiffies + 3 * HZ); - } - - return ATL1_SUCCESS; -} - -static void atl1_check_for_link(struct atl1_adapter *adapter) -{ - struct net_device *netdev = adapter->netdev; - u16 phy_data = 0; - - spin_lock(&adapter->lock); - adapter->phy_timer_pending = false; - atl1_read_phy_reg(&adapter->hw, MII_BMSR, &phy_data); - atl1_read_phy_reg(&adapter->hw, MII_BMSR, &phy_data); - spin_unlock(&adapter->lock); - - /* notify upper layer link down ASAP */ - if (!(phy_data & BMSR_LSTATUS)) { /* Link Down */ - if (netif_carrier_ok(netdev)) { /* old link state: Up */ - dev_info(&adapter->pdev->dev, "%s link is down\n", - netdev->name); - adapter->link_speed = SPEED_0; - netif_carrier_off(netdev); - netif_stop_queue(netdev); - } - } - schedule_work(&adapter->link_chg_task); -} -/* - * atl1_set_multi - Multicast and Promiscuous mode set - * @netdev: network interface device structure - * - * The set_multi entry point is called whenever the multicast address - * list or the network interface flags are updated. This routine is - * responsible for configuring the hardware for proper multicast, - * promiscuous mode, and all-multi behavior. - */ -static void atl1_set_multi(struct net_device *netdev) -{ - struct atl1_adapter *adapter = netdev_priv(netdev); - struct atl1_hw *hw = &adapter->hw; - struct dev_mc_list *mc_ptr; - u32 rctl; - u32 hash_value; - - /* Check for Promiscuous and All Multicast modes */ - rctl = ioread32(hw->hw_addr + REG_MAC_CTRL); - if (netdev->flags & IFF_PROMISC) - rctl |= MAC_CTRL_PROMIS_EN; - else if (netdev->flags & IFF_ALLMULTI) { - rctl |= MAC_CTRL_MC_ALL_EN; - rctl &= ~MAC_CTRL_PROMIS_EN; - } else - rctl &= ~(MAC_CTRL_PROMIS_EN | MAC_CTRL_MC_ALL_EN); - - iowrite32(rctl, hw->hw_addr + REG_MAC_CTRL); - - /* clear the old settings from the multicast hash table */ - iowrite32(0, hw->hw_addr + REG_RX_HASH_TABLE); - iowrite32(0, (hw->hw_addr + REG_RX_HASH_TABLE) + (1 << 2)); - - /* compute mc addresses' hash value ,and put it into hash table */ - for (mc_ptr = netdev->mc_list; mc_ptr; mc_ptr = mc_ptr->next) { - hash_value = atl1_hash_mc_addr(hw, mc_ptr->dmi_addr); - atl1_hash_set(hw, hash_value); - } -} - -/* - * atl1_change_mtu - Change the Maximum Transfer Unit - * @netdev: network interface device structure - * @new_mtu: new value for maximum frame size - * - * Returns 0 on success, negative on failure - */ -static int atl1_change_mtu(struct net_device *netdev, int new_mtu) -{ - struct atl1_adapter *adapter = netdev_priv(netdev); - int old_mtu = netdev->mtu; - int max_frame = new_mtu + ENET_HEADER_SIZE + ETHERNET_FCS_SIZE; - - if ((max_frame < MINIMUM_ETHERNET_FRAME_SIZE) || - (max_frame > MAX_JUMBO_FRAME_SIZE)) { - dev_warn(&adapter->pdev->dev, "invalid MTU setting\n"); - return -EINVAL; - } - - adapter->hw.max_frame_size = max_frame; - adapter->hw.tx_jumbo_task_th = (max_frame + 7) >> 3; - adapter->rx_buffer_len = (max_frame + 7) & ~7; - adapter->hw.rx_jumbo_th = adapter->rx_buffer_len / 8; - - netdev->mtu = new_mtu; - if ((old_mtu != new_mtu) && netif_running(netdev)) { - atl1_down(adapter); - atl1_up(adapter); - } - - return 0; -} - -static void set_flow_ctrl_old(struct atl1_adapter *adapter) -{ - u32 hi, lo, value; - - /* RFD Flow Control */ - value = adapter->rfd_ring.count; - hi = value / 16; - if (hi < 2) - hi = 2; - lo = value * 7 / 8; - - value = ((hi & RXQ_RXF_PAUSE_TH_HI_MASK) << RXQ_RXF_PAUSE_TH_HI_SHIFT) | - ((lo & RXQ_RXF_PAUSE_TH_LO_MASK) << RXQ_RXF_PAUSE_TH_LO_SHIFT); - iowrite32(value, adapter->hw.hw_addr + REG_RXQ_RXF_PAUSE_THRESH); + /* + * Make buffer alignment 2 beyond a 16 byte boundary + * this will result in a 16 byte aligned IP header after + * the 14 byte MAC header is removed + */ + skb_reserve(skb, NET_IP_ALIGN); - /* RRD Flow Control */ - value = adapter->rrd_ring.count; - lo = value / 16; - hi = value * 7 / 8; - if (lo < 2) - lo = 2; - value = ((hi & RXQ_RRD_PAUSE_TH_HI_MASK) << RXQ_RRD_PAUSE_TH_HI_SHIFT) | - ((lo & RXQ_RRD_PAUSE_TH_LO_MASK) << RXQ_RRD_PAUSE_TH_LO_SHIFT); - iowrite32(value, adapter->hw.hw_addr + REG_RXQ_RRD_PAUSE_THRESH); -} + buffer_info->alloced = 1; + buffer_info->skb = skb; + buffer_info->length = (u16) adapter->rx_buffer_len; + page = virt_to_page(skb->data); + offset = (unsigned long)skb->data & ~PAGE_MASK; + buffer_info->dma = pci_map_page(pdev, page, offset, + adapter->rx_buffer_len, + PCI_DMA_FROMDEVICE); + rfd_desc->buffer_addr = cpu_to_le64(buffer_info->dma); + rfd_desc->buf_len = cpu_to_le16(adapter->rx_buffer_len); + rfd_desc->coalese = 0; -static void set_flow_ctrl_new(struct atl1_hw *hw) -{ - u32 hi, lo, value; +next: + rfd_next_to_use = next_next; + if (unlikely(++next_next == rfd_ring->count)) + next_next = 0; - /* RXF Flow Control */ - value = ioread32(hw->hw_addr + REG_SRAM_RXF_LEN); - lo = value / 16; - if (lo < 192) - lo = 192; - hi = value * 7 / 8; - if (hi < lo) - hi = lo + 16; - value = ((hi & RXQ_RXF_PAUSE_TH_HI_MASK) << RXQ_RXF_PAUSE_TH_HI_SHIFT) | - ((lo & RXQ_RXF_PAUSE_TH_LO_MASK) << RXQ_RXF_PAUSE_TH_LO_SHIFT); - iowrite32(value, hw->hw_addr + REG_RXQ_RXF_PAUSE_THRESH); + buffer_info = &rfd_ring->buffer_info[rfd_next_to_use]; + next_info = &rfd_ring->buffer_info[next_next]; + num_alloc++; + } - /* RRD Flow Control */ - value = ioread32(hw->hw_addr + REG_SRAM_RRD_LEN); - lo = value / 8; - hi = value * 7 / 8; - if (lo < 2) - lo = 2; - if (hi < lo) - hi = lo + 3; - value = ((hi & RXQ_RRD_PAUSE_TH_HI_MASK) << RXQ_RRD_PAUSE_TH_HI_SHIFT) | - ((lo & RXQ_RRD_PAUSE_TH_LO_MASK) << RXQ_RRD_PAUSE_TH_LO_SHIFT); - iowrite32(value, hw->hw_addr + REG_RXQ_RRD_PAUSE_THRESH); + if (num_alloc) { + /* + * Force memory writes to complete before letting h/w + * know there are new descriptors to fetch. (Only + * applicable for weak-ordered memory model archs, + * such as IA-64). + */ + wmb(); + atomic_set(&rfd_ring->next_to_use, (int)rfd_next_to_use); + } + return num_alloc; } -/* - * atl1_configure - Configure Transmit&Receive Unit after Reset - * @adapter: board private structure - * - * Configure the Tx /Rx unit of the MAC after a reset. - */ -static u32 atl1_configure(struct atl1_adapter *adapter) +static void atl1_intr_rx(struct atl1_adapter *adapter) { - struct atl1_hw *hw = &adapter->hw; + int i, count; + u16 length; + u16 rrd_next_to_clean; u32 value; + struct atl1_rfd_ring *rfd_ring = &adapter->rfd_ring; + struct atl1_rrd_ring *rrd_ring = &adapter->rrd_ring; + struct atl1_buffer *buffer_info; + struct rx_return_desc *rrd; + struct sk_buff *skb; - /* clear interrupt status */ - iowrite32(0xffffffff, adapter->hw.hw_addr + REG_ISR); + count = 0; - /* set MAC Address */ - value = (((u32) hw->mac_addr[2]) << 24) | - (((u32) hw->mac_addr[3]) << 16) | - (((u32) hw->mac_addr[4]) << 8) | - (((u32) hw->mac_addr[5])); - iowrite32(value, hw->hw_addr + REG_MAC_STA_ADDR); - value = (((u32) hw->mac_addr[0]) << 8) | (((u32) hw->mac_addr[1])); - iowrite32(value, hw->hw_addr + (REG_MAC_STA_ADDR + 4)); + rrd_next_to_clean = atomic_read(&rrd_ring->next_to_clean); - /* tx / rx ring */ + while (1) { + rrd = ATL1_RRD_DESC(rrd_ring, rrd_next_to_clean); + i = 1; + if (likely(rrd->xsz.valid)) { /* packet valid */ +chk_rrd: + /* check rrd status */ + if (likely(rrd->num_buf == 1)) + goto rrd_ok; - /* HI base address */ - iowrite32((u32) ((adapter->tpd_ring.dma & 0xffffffff00000000ULL) >> 32), - hw->hw_addr + REG_DESC_BASE_ADDR_HI); - /* LO base address */ - iowrite32((u32) (adapter->rfd_ring.dma & 0x00000000ffffffffULL), - hw->hw_addr + REG_DESC_RFD_ADDR_LO); - iowrite32((u32) (adapter->rrd_ring.dma & 0x00000000ffffffffULL), - hw->hw_addr + REG_DESC_RRD_ADDR_LO); - iowrite32((u32) (adapter->tpd_ring.dma & 0x00000000ffffffffULL), - hw->hw_addr + REG_DESC_TPD_ADDR_LO); - iowrite32((u32) (adapter->cmb.dma & 0x00000000ffffffffULL), - hw->hw_addr + REG_DESC_CMB_ADDR_LO); - iowrite32((u32) (adapter->smb.dma & 0x00000000ffffffffULL), - hw->hw_addr + REG_DESC_SMB_ADDR_LO); + /* rrd seems to be bad */ + if (unlikely(i-- > 0)) { + /* rrd may not be DMAed completely */ + dev_dbg(&adapter->pdev->dev, + "incomplete RRD DMA transfer\n"); + udelay(1); + goto chk_rrd; + } + /* bad rrd */ + dev_dbg(&adapter->pdev->dev, "bad RRD\n"); + /* see if update RFD index */ + if (rrd->num_buf > 1) { + u16 num_buf; + num_buf = + (rrd->xsz.xsum_sz.pkt_size + + adapter->rx_buffer_len - + 1) / adapter->rx_buffer_len; + if (rrd->num_buf == num_buf) { + /* clean alloc flag for bad rrd */ + while (rfd_ring->next_to_clean != + (rrd->buf_indx + num_buf)) { + rfd_ring->buffer_info[rfd_ring-> + next_to_clean].alloced = 0; + if (++rfd_ring->next_to_clean == + rfd_ring->count) { + rfd_ring-> + next_to_clean = 0; + } + } + } + } - /* element count */ - value = adapter->rrd_ring.count; - value <<= 16; - value += adapter->rfd_ring.count; - iowrite32(value, hw->hw_addr + REG_DESC_RFD_RRD_RING_SIZE); - iowrite32(adapter->tpd_ring.count, hw->hw_addr + - REG_DESC_TPD_RING_SIZE); + /* update rrd */ + rrd->xsz.valid = 0; + if (++rrd_next_to_clean == rrd_ring->count) + rrd_next_to_clean = 0; + count++; + continue; + } else { /* current rrd still not be updated */ - /* Load Ptr */ - iowrite32(1, hw->hw_addr + REG_LOAD_PTR); + break; + } +rrd_ok: + /* clean alloc flag for bad rrd */ + while (rfd_ring->next_to_clean != rrd->buf_indx) { + rfd_ring->buffer_info[rfd_ring->next_to_clean].alloced = + 0; + if (++rfd_ring->next_to_clean == rfd_ring->count) + rfd_ring->next_to_clean = 0; + } - /* config Mailbox */ - value = ((atomic_read(&adapter->tpd_ring.next_to_use) - & MB_TPD_PROD_INDX_MASK) << MB_TPD_PROD_INDX_SHIFT) | - ((atomic_read(&adapter->rrd_ring.next_to_clean) - & MB_RRD_CONS_INDX_MASK) << MB_RRD_CONS_INDX_SHIFT) | - ((atomic_read(&adapter->rfd_ring.next_to_use) - & MB_RFD_PROD_INDX_MASK) << MB_RFD_PROD_INDX_SHIFT); - iowrite32(value, hw->hw_addr + REG_MAILBOX); + buffer_info = &rfd_ring->buffer_info[rrd->buf_indx]; + if (++rfd_ring->next_to_clean == rfd_ring->count) + rfd_ring->next_to_clean = 0; - /* config IPG/IFG */ - value = (((u32) hw->ipgt & MAC_IPG_IFG_IPGT_MASK) - << MAC_IPG_IFG_IPGT_SHIFT) | - (((u32) hw->min_ifg & MAC_IPG_IFG_MIFG_MASK) - << MAC_IPG_IFG_MIFG_SHIFT) | - (((u32) hw->ipgr1 & MAC_IPG_IFG_IPGR1_MASK) - << MAC_IPG_IFG_IPGR1_SHIFT) | - (((u32) hw->ipgr2 & MAC_IPG_IFG_IPGR2_MASK) - << MAC_IPG_IFG_IPGR2_SHIFT); - iowrite32(value, hw->hw_addr + REG_MAC_IPG_IFG); + /* update rrd next to clean */ + if (++rrd_next_to_clean == rrd_ring->count) + rrd_next_to_clean = 0; + count++; - /* config Half-Duplex Control */ - value = ((u32) hw->lcol & MAC_HALF_DUPLX_CTRL_LCOL_MASK) | - (((u32) hw->max_retry & MAC_HALF_DUPLX_CTRL_RETRY_MASK) - << MAC_HALF_DUPLX_CTRL_RETRY_SHIFT) | - MAC_HALF_DUPLX_CTRL_EXC_DEF_EN | - (0xa << MAC_HALF_DUPLX_CTRL_ABEBT_SHIFT) | - (((u32) hw->jam_ipg & MAC_HALF_DUPLX_CTRL_JAMIPG_MASK) - << MAC_HALF_DUPLX_CTRL_JAMIPG_SHIFT); - iowrite32(value, hw->hw_addr + REG_MAC_HALF_DUPLX_CTRL); + if (unlikely(rrd->pkt_flg & PACKET_FLAG_ERR)) { + if (!(rrd->err_flg & + (ERR_FLAG_IP_CHKSUM | ERR_FLAG_L4_CHKSUM + | ERR_FLAG_LEN))) { + /* packet error, don't need upstream */ + buffer_info->alloced = 0; + rrd->xsz.valid = 0; + continue; + } + } - /* set Interrupt Moderator Timer */ - iowrite16(adapter->imt, hw->hw_addr + REG_IRQ_MODU_TIMER_INIT); - iowrite32(MASTER_CTRL_ITIMER_EN, hw->hw_addr + REG_MASTER_CTRL); + /* Good Receive */ + pci_unmap_page(adapter->pdev, buffer_info->dma, + buffer_info->length, PCI_DMA_FROMDEVICE); + skb = buffer_info->skb; + length = le16_to_cpu(rrd->xsz.xsum_sz.pkt_size); - /* set Interrupt Clear Timer */ - iowrite16(adapter->ict, hw->hw_addr + REG_CMBDISDMA_TIMER); + skb_put(skb, length - ETHERNET_FCS_SIZE); - /* set MTU, 4 : VLAN */ - iowrite32(hw->max_frame_size + 4, hw->hw_addr + REG_MTU); + /* Receive Checksum Offload */ + atl1_rx_checksum(adapter, rrd, skb); + skb->protocol = eth_type_trans(skb, adapter->netdev); - /* jumbo size & rrd retirement timer */ - value = (((u32) hw->rx_jumbo_th & RXQ_JMBOSZ_TH_MASK) - << RXQ_JMBOSZ_TH_SHIFT) | - (((u32) hw->rx_jumbo_lkah & RXQ_JMBO_LKAH_MASK) - << RXQ_JMBO_LKAH_SHIFT) | - (((u32) hw->rrd_ret_timer & RXQ_RRD_TIMER_MASK) - << RXQ_RRD_TIMER_SHIFT); - iowrite32(value, hw->hw_addr + REG_RXQ_JMBOSZ_RRDTIM); + if (adapter->vlgrp && (rrd->pkt_flg & PACKET_FLAG_VLAN_INS)) { + u16 vlan_tag = (rrd->vlan_tag >> 4) | + ((rrd->vlan_tag & 7) << 13) | + ((rrd->vlan_tag & 8) << 9); + vlan_hwaccel_rx(skb, adapter->vlgrp, vlan_tag); + } else + netif_rx(skb); - /* Flow Control */ - switch (hw->dev_rev) { - case 0x8001: - case 0x9001: - case 0x9002: - case 0x9003: - set_flow_ctrl_old(adapter); - break; - default: - set_flow_ctrl_new(hw); - break; + /* let protocol layer free skb */ + buffer_info->skb = NULL; + buffer_info->alloced = 0; + rrd->xsz.valid = 0; + + adapter->netdev->last_rx = jiffies; } - /* config TXQ */ - value = (((u32) hw->tpd_burst & TXQ_CTRL_TPD_BURST_NUM_MASK) - << TXQ_CTRL_TPD_BURST_NUM_SHIFT) | - (((u32) hw->txf_burst & TXQ_CTRL_TXF_BURST_NUM_MASK) - << TXQ_CTRL_TXF_BURST_NUM_SHIFT) | - (((u32) hw->tpd_fetch_th & TXQ_CTRL_TPD_FETCH_TH_MASK) - << TXQ_CTRL_TPD_FETCH_TH_SHIFT) | TXQ_CTRL_ENH_MODE | - TXQ_CTRL_EN; - iowrite32(value, hw->hw_addr + REG_TXQ_CTRL); + atomic_set(&rrd_ring->next_to_clean, rrd_next_to_clean); - /* min tpd fetch gap & tx jumbo packet size threshold for taskoffload */ - value = (((u32) hw->tx_jumbo_task_th & TX_JUMBO_TASK_TH_MASK) - << TX_JUMBO_TASK_TH_SHIFT) | - (((u32) hw->tpd_fetch_gap & TX_TPD_MIN_IPG_MASK) - << TX_TPD_MIN_IPG_SHIFT); - iowrite32(value, hw->hw_addr + REG_TX_JUMBO_TASK_TH_TPD_IPG); + atl1_alloc_rx_buffers(adapter); - /* config RXQ */ - value = (((u32) hw->rfd_burst & RXQ_CTRL_RFD_BURST_NUM_MASK) - << RXQ_CTRL_RFD_BURST_NUM_SHIFT) | - (((u32) hw->rrd_burst & RXQ_CTRL_RRD_BURST_THRESH_MASK) - << RXQ_CTRL_RRD_BURST_THRESH_SHIFT) | - (((u32) hw->rfd_fetch_gap & RXQ_CTRL_RFD_PREF_MIN_IPG_MASK) - << RXQ_CTRL_RFD_PREF_MIN_IPG_SHIFT) | RXQ_CTRL_CUT_THRU_EN | - RXQ_CTRL_EN; - iowrite32(value, hw->hw_addr + REG_RXQ_CTRL); + /* update mailbox ? */ + if (count) { + u32 tpd_next_to_use; + u32 rfd_next_to_use; + u32 rrd_next_to_clean; - /* config DMA Engine */ - value = ((((u32) hw->dmar_block) & DMA_CTRL_DMAR_BURST_LEN_MASK) - << DMA_CTRL_DMAR_BURST_LEN_SHIFT) | - ((((u32) hw->dmaw_block) & DMA_CTRL_DMAR_BURST_LEN_MASK) - << DMA_CTRL_DMAR_BURST_LEN_SHIFT) | DMA_CTRL_DMAR_EN | - DMA_CTRL_DMAW_EN; - value |= (u32) hw->dma_ord; - if (atl1_rcb_128 == hw->rcb_value) - value |= DMA_CTRL_RCB_VALUE; - iowrite32(value, hw->hw_addr + REG_DMA_CTRL); + spin_lock(&adapter->mb_lock); - /* config CMB / SMB */ - value = hw->cmb_rrd | ((u32) hw->cmb_tpd << 16); - iowrite32(value, hw->hw_addr + REG_CMB_WRITE_TH); - value = hw->cmb_rx_timer | ((u32) hw->cmb_tx_timer << 16); - iowrite32(value, hw->hw_addr + REG_CMB_WRITE_TIMER); - iowrite32(hw->smb_timer, hw->hw_addr + REG_SMB_TIMER); + tpd_next_to_use = atomic_read(&adapter->tpd_ring.next_to_use); + rfd_next_to_use = + atomic_read(&adapter->rfd_ring.next_to_use); + rrd_next_to_clean = + atomic_read(&adapter->rrd_ring.next_to_clean); + value = ((rfd_next_to_use & MB_RFD_PROD_INDX_MASK) << + MB_RFD_PROD_INDX_SHIFT) | + ((rrd_next_to_clean & MB_RRD_CONS_INDX_MASK) << + MB_RRD_CONS_INDX_SHIFT) | + ((tpd_next_to_use & MB_TPD_PROD_INDX_MASK) << + MB_TPD_PROD_INDX_SHIFT); + iowrite32(value, adapter->hw.hw_addr + REG_MAILBOX); + spin_unlock(&adapter->mb_lock); + } +} + +static void atl1_intr_tx(struct atl1_adapter *adapter) +{ + struct atl1_tpd_ring *tpd_ring = &adapter->tpd_ring; + struct atl1_buffer *buffer_info; + u16 sw_tpd_next_to_clean; + u16 cmb_tpd_next_to_clean; + + sw_tpd_next_to_clean = atomic_read(&tpd_ring->next_to_clean); + cmb_tpd_next_to_clean = le16_to_cpu(adapter->cmb.cmb->tpd_cons_idx); - /* --- enable CMB / SMB */ - value = CSMB_CTRL_CMB_EN | CSMB_CTRL_SMB_EN; - iowrite32(value, hw->hw_addr + REG_CSMB_CTRL); + while (cmb_tpd_next_to_clean != sw_tpd_next_to_clean) { + struct tx_packet_desc *tpd; - value = ioread32(adapter->hw.hw_addr + REG_ISR); - if (unlikely((value & ISR_PHY_LINKDOWN) != 0)) - value = 1; /* config failed */ - else - value = 0; + tpd = ATL1_TPD_DESC(tpd_ring, sw_tpd_next_to_clean); + buffer_info = &tpd_ring->buffer_info[sw_tpd_next_to_clean]; + if (buffer_info->dma) { + pci_unmap_page(adapter->pdev, buffer_info->dma, + buffer_info->length, PCI_DMA_TODEVICE); + buffer_info->dma = 0; + } - /* clear all interrupt status */ - iowrite32(0x3fffffff, adapter->hw.hw_addr + REG_ISR); - iowrite32(0, adapter->hw.hw_addr + REG_ISR); - return value; -} + if (buffer_info->skb) { + dev_kfree_skb_irq(buffer_info->skb); + buffer_info->skb = NULL; + } + tpd->buffer_addr = 0; + tpd->desc.data = 0; -/* - * atl1_pcie_patch - Patch for PCIE module - */ -static void atl1_pcie_patch(struct atl1_adapter *adapter) -{ - u32 value; + if (++sw_tpd_next_to_clean == tpd_ring->count) + sw_tpd_next_to_clean = 0; + } + atomic_set(&tpd_ring->next_to_clean, sw_tpd_next_to_clean); - /* much vendor magic here */ - value = 0x6500; - iowrite32(value, adapter->hw.hw_addr + 0x12FC); - /* pcie flow control mode change */ - value = ioread32(adapter->hw.hw_addr + 0x1008); - value |= 0x8000; - iowrite32(value, adapter->hw.hw_addr + 0x1008); + if (netif_queue_stopped(adapter->netdev) + && netif_carrier_ok(adapter->netdev)) + netif_wake_queue(adapter->netdev); } -/* - * When ACPI resume on some VIA MotherBoard, the Interrupt Disable bit/0x400 - * on PCI Command register is disable. - * The function enable this bit. - * Brackett, 2006/03/15 - */ -static void atl1_via_workaround(struct atl1_adapter *adapter) +static void atl1_check_for_link(struct atl1_adapter *adapter) { - unsigned long value; + struct net_device *netdev = adapter->netdev; + u16 phy_data = 0; - value = ioread16(adapter->hw.hw_addr + PCI_COMMAND); - if (value & PCI_COMMAND_INTX_DISABLE) - value &= ~PCI_COMMAND_INTX_DISABLE; - iowrite32(value, adapter->hw.hw_addr + PCI_COMMAND); -} + spin_lock(&adapter->lock); + adapter->phy_timer_pending = false; + atl1_read_phy_reg(&adapter->hw, MII_BMSR, &phy_data); + atl1_read_phy_reg(&adapter->hw, MII_BMSR, &phy_data); + spin_unlock(&adapter->lock); -/* - * atl1_irq_enable - Enable default interrupt generation settings - * @adapter: board private structure - */ -static void atl1_irq_enable(struct atl1_adapter *adapter) -{ - iowrite32(IMR_NORMAL_MASK, adapter->hw.hw_addr + REG_IMR); - ioread32(adapter->hw.hw_addr + REG_IMR); + /* notify upper layer link down ASAP */ + if (!(phy_data & BMSR_LSTATUS)) { /* Link Down */ + if (netif_carrier_ok(netdev)) { /* old link state: Up */ + dev_info(&adapter->pdev->dev, "%s link is down\n", + netdev->name); + adapter->link_speed = SPEED_0; + netif_carrier_off(netdev); + netif_stop_queue(netdev); + } + } + schedule_work(&adapter->link_chg_task); } /* - * atl1_irq_disable - Mask off interrupt generation on the NIC - * @adapter: board private structure + * atl1_intr - Interrupt Handler + * @irq: interrupt number + * @data: pointer to a network interface device structure + * @pt_regs: CPU registers structure */ -static void atl1_irq_disable(struct atl1_adapter *adapter) +static irqreturn_t atl1_intr(int irq, void *data) { - iowrite32(0, adapter->hw.hw_addr + REG_IMR); - ioread32(adapter->hw.hw_addr + REG_IMR); - synchronize_irq(adapter->pdev->irq); -} + /*struct atl1_adapter *adapter = ((struct net_device *)data)->priv;*/ + struct atl1_adapter *adapter = netdev_priv(data); + u32 status; + u8 update_rx; + int max_ints = 10; -static void atl1_clear_phy_int(struct atl1_adapter *adapter) -{ - u16 phy_data; - unsigned long flags; + status = adapter->cmb.cmb->int_stats; + if (!status) + return IRQ_NONE; - spin_lock_irqsave(&adapter->lock, flags); - atl1_read_phy_reg(&adapter->hw, 19, &phy_data); - spin_unlock_irqrestore(&adapter->lock, flags); -} + update_rx = 0; -static void atl1_inc_smb(struct atl1_adapter *adapter) -{ - struct stats_msg_block *smb = adapter->smb.smb; + do { + /* clear CMB interrupt status at once */ + adapter->cmb.cmb->int_stats = 0; - /* Fill out the OS statistics structure */ - adapter->soft_stats.rx_packets += smb->rx_ok; - adapter->soft_stats.tx_packets += smb->tx_ok; - adapter->soft_stats.rx_bytes += smb->rx_byte_cnt; - adapter->soft_stats.tx_bytes += smb->tx_byte_cnt; - adapter->soft_stats.multicast += smb->rx_mcast; - adapter->soft_stats.collisions += (smb->tx_1_col + smb->tx_2_col * 2 + - smb->tx_late_col + smb->tx_abort_col * adapter->hw.max_retry); + if (status & ISR_GPHY) /* clear phy status */ + atl1_clear_phy_int(adapter); - /* Rx Errors */ - adapter->soft_stats.rx_errors += (smb->rx_frag + smb->rx_fcs_err + - smb->rx_len_err + smb->rx_sz_ov + smb->rx_rxf_ov + - smb->rx_rrd_ov + smb->rx_align_err); - adapter->soft_stats.rx_fifo_errors += smb->rx_rxf_ov; - adapter->soft_stats.rx_length_errors += smb->rx_len_err; - adapter->soft_stats.rx_crc_errors += smb->rx_fcs_err; - adapter->soft_stats.rx_frame_errors += smb->rx_align_err; - adapter->soft_stats.rx_missed_errors += (smb->rx_rrd_ov + - smb->rx_rxf_ov); + /* clear ISR status, and Enable CMB DMA/Disable Interrupt */ + iowrite32(status | ISR_DIS_INT, adapter->hw.hw_addr + REG_ISR); - adapter->soft_stats.rx_pause += smb->rx_pause; - adapter->soft_stats.rx_rrd_ov += smb->rx_rrd_ov; - adapter->soft_stats.rx_trunc += smb->rx_sz_ov; + /* check if SMB intr */ + if (status & ISR_SMB) + atl1_inc_smb(adapter); - /* Tx Errors */ - adapter->soft_stats.tx_errors += (smb->tx_late_col + - smb->tx_abort_col + smb->tx_underrun + smb->tx_trunc); - adapter->soft_stats.tx_fifo_errors += smb->tx_underrun; - adapter->soft_stats.tx_aborted_errors += smb->tx_abort_col; - adapter->soft_stats.tx_window_errors += smb->tx_late_col; + /* check if PCIE PHY Link down */ + if (status & ISR_PHY_LINKDOWN) { + dev_dbg(&adapter->pdev->dev, "pcie phy link down %x\n", + status); + if (netif_running(adapter->netdev)) { /* reset MAC */ + iowrite32(0, adapter->hw.hw_addr + REG_IMR); + schedule_work(&adapter->pcie_dma_to_rst_task); + return IRQ_HANDLED; + } + } - adapter->soft_stats.excecol += smb->tx_abort_col; - adapter->soft_stats.deffer += smb->tx_defer; - adapter->soft_stats.scc += smb->tx_1_col; - adapter->soft_stats.mcc += smb->tx_2_col; - adapter->soft_stats.latecol += smb->tx_late_col; - adapter->soft_stats.tx_underun += smb->tx_underrun; - adapter->soft_stats.tx_trunc += smb->tx_trunc; - adapter->soft_stats.tx_pause += smb->tx_pause; + /* check if DMA read/write error ? */ + if (status & (ISR_DMAR_TO_RST | ISR_DMAW_TO_RST)) { + dev_dbg(&adapter->pdev->dev, + "pcie DMA r/w error (status = 0x%x)\n", + status); + iowrite32(0, adapter->hw.hw_addr + REG_IMR); + schedule_work(&adapter->pcie_dma_to_rst_task); + return IRQ_HANDLED; + } - adapter->net_stats.rx_packets = adapter->soft_stats.rx_packets; - adapter->net_stats.tx_packets = adapter->soft_stats.tx_packets; - adapter->net_stats.rx_bytes = adapter->soft_stats.rx_bytes; - adapter->net_stats.tx_bytes = adapter->soft_stats.tx_bytes; - adapter->net_stats.multicast = adapter->soft_stats.multicast; - adapter->net_stats.collisions = adapter->soft_stats.collisions; - adapter->net_stats.rx_errors = adapter->soft_stats.rx_errors; - adapter->net_stats.rx_over_errors = - adapter->soft_stats.rx_missed_errors; - adapter->net_stats.rx_length_errors = - adapter->soft_stats.rx_length_errors; - adapter->net_stats.rx_crc_errors = adapter->soft_stats.rx_crc_errors; - adapter->net_stats.rx_frame_errors = - adapter->soft_stats.rx_frame_errors; - adapter->net_stats.rx_fifo_errors = adapter->soft_stats.rx_fifo_errors; - adapter->net_stats.rx_missed_errors = - adapter->soft_stats.rx_missed_errors; - adapter->net_stats.tx_errors = adapter->soft_stats.tx_errors; - adapter->net_stats.tx_fifo_errors = adapter->soft_stats.tx_fifo_errors; - adapter->net_stats.tx_aborted_errors = - adapter->soft_stats.tx_aborted_errors; - adapter->net_stats.tx_window_errors = - adapter->soft_stats.tx_window_errors; - adapter->net_stats.tx_carrier_errors = - adapter->soft_stats.tx_carrier_errors; + /* link event */ + if (status & ISR_GPHY) { + adapter->soft_stats.tx_carrier_errors++; + atl1_check_for_link(adapter); + } + + /* transmit event */ + if (status & ISR_CMB_TX) + atl1_intr_tx(adapter); + + /* rx exception */ + if (unlikely(status & (ISR_RXF_OV | ISR_RFD_UNRUN | + ISR_RRD_OV | ISR_HOST_RFD_UNRUN | + ISR_HOST_RRD_OV | ISR_CMB_RX))) { + if (status & (ISR_RXF_OV | ISR_RFD_UNRUN | + ISR_RRD_OV | ISR_HOST_RFD_UNRUN | + ISR_HOST_RRD_OV)) + dev_dbg(&adapter->pdev->dev, + "rx exception, ISR = 0x%x\n", status); + atl1_intr_rx(adapter); + } + + if (--max_ints < 0) + break; + + } while ((status = adapter->cmb.cmb->int_stats)); + + /* re-enable Interrupt */ + iowrite32(ISR_DIS_SMB | ISR_DIS_DMA, adapter->hw.hw_addr + REG_ISR); + return IRQ_HANDLED; } /* - * atl1_get_stats - Get System Network Statistics + * atl1_set_multi - Multicast and Promiscuous mode set * @netdev: network interface device structure * - * Returns the address of the device statistics structure. - * The statistics are actually updated from the timer callback. + * The set_multi entry point is called whenever the multicast address + * list or the network interface flags are updated. This routine is + * responsible for configuring the hardware for proper multicast, + * promiscuous mode, and all-multi behavior. */ -static struct net_device_stats *atl1_get_stats(struct net_device *netdev) +static void atl1_set_multi(struct net_device *netdev) { struct atl1_adapter *adapter = netdev_priv(netdev); - return &adapter->net_stats; + struct atl1_hw *hw = &adapter->hw; + struct dev_mc_list *mc_ptr; + u32 rctl; + u32 hash_value; + + /* Check for Promiscuous and All Multicast modes */ + rctl = ioread32(hw->hw_addr + REG_MAC_CTRL); + if (netdev->flags & IFF_PROMISC) + rctl |= MAC_CTRL_PROMIS_EN; + else if (netdev->flags & IFF_ALLMULTI) { + rctl |= MAC_CTRL_MC_ALL_EN; + rctl &= ~MAC_CTRL_PROMIS_EN; + } else + rctl &= ~(MAC_CTRL_PROMIS_EN | MAC_CTRL_MC_ALL_EN); + + iowrite32(rctl, hw->hw_addr + REG_MAC_CTRL); + + /* clear the old settings from the multicast hash table */ + iowrite32(0, hw->hw_addr + REG_RX_HASH_TABLE); + iowrite32(0, (hw->hw_addr + REG_RX_HASH_TABLE) + (1 << 2)); + + /* compute mc addresses' hash value ,and put it into hash table */ + for (mc_ptr = netdev->mc_list; mc_ptr; mc_ptr = mc_ptr->next) { + hash_value = atl1_hash_mc_addr(hw, mc_ptr->dmi_addr); + atl1_hash_set(hw, hash_value); + } } -static void atl1_update_mailbox(struct atl1_adapter *adapter) +static void atl1_setup_mac_ctrl(struct atl1_adapter *adapter) { - unsigned long flags; - u32 tpd_next_to_use; - u32 rfd_next_to_use; - u32 rrd_next_to_clean; u32 value; - - spin_lock_irqsave(&adapter->mb_lock, flags); - - tpd_next_to_use = atomic_read(&adapter->tpd_ring.next_to_use); - rfd_next_to_use = atomic_read(&adapter->rfd_ring.next_to_use); - rrd_next_to_clean = atomic_read(&adapter->rrd_ring.next_to_clean); - - value = ((rfd_next_to_use & MB_RFD_PROD_INDX_MASK) << - MB_RFD_PROD_INDX_SHIFT) | - ((rrd_next_to_clean & MB_RRD_CONS_INDX_MASK) << - MB_RRD_CONS_INDX_SHIFT) | - ((tpd_next_to_use & MB_TPD_PROD_INDX_MASK) << - MB_TPD_PROD_INDX_SHIFT); - iowrite32(value, adapter->hw.hw_addr + REG_MAILBOX); - - spin_unlock_irqrestore(&adapter->mb_lock, flags); + struct atl1_hw *hw = &adapter->hw; + struct net_device *netdev = adapter->netdev; + /* Config MAC CTRL Register */ + value = MAC_CTRL_TX_EN | MAC_CTRL_RX_EN; + /* duplex */ + if (FULL_DUPLEX == adapter->link_duplex) + value |= MAC_CTRL_DUPLX; + /* speed */ + value |= ((u32) ((SPEED_1000 == adapter->link_speed) ? + MAC_CTRL_SPEED_1000 : MAC_CTRL_SPEED_10_100) << + MAC_CTRL_SPEED_SHIFT); + /* flow control */ + value |= (MAC_CTRL_TX_FLOW | MAC_CTRL_RX_FLOW); + /* PAD & CRC */ + value |= (MAC_CTRL_ADD_CRC | MAC_CTRL_PAD); + /* preamble length */ + value |= (((u32) adapter->hw.preamble_len + & MAC_CTRL_PRMLEN_MASK) << MAC_CTRL_PRMLEN_SHIFT); + /* vlan */ + if (adapter->vlgrp) + value |= MAC_CTRL_RMV_VLAN; + /* rx checksum + if (adapter->rx_csum) + value |= MAC_CTRL_RX_CHKSUM_EN; + */ + /* filter mode */ + value |= MAC_CTRL_BC_EN; + if (netdev->flags & IFF_PROMISC) + value |= MAC_CTRL_PROMIS_EN; + else if (netdev->flags & IFF_ALLMULTI) + value |= MAC_CTRL_MC_ALL_EN; + /* value |= MAC_CTRL_LOOPBACK; */ + iowrite32(value, hw->hw_addr + REG_MAC_CTRL); } -static void atl1_clean_alloc_flag(struct atl1_adapter *adapter, - struct rx_return_desc *rrd, u16 offset) +static u32 atl1_check_link(struct atl1_adapter *adapter) { - struct atl1_rfd_ring *rfd_ring = &adapter->rfd_ring; + struct atl1_hw *hw = &adapter->hw; + struct net_device *netdev = adapter->netdev; + u32 ret_val; + u16 speed, duplex, phy_data; + int reconfig = 0; - while (rfd_ring->next_to_clean != (rrd->buf_indx + offset)) { - rfd_ring->buffer_info[rfd_ring->next_to_clean].alloced = 0; - if (++rfd_ring->next_to_clean == rfd_ring->count) { - rfd_ring->next_to_clean = 0; + /* MII_BMSR must read twice */ + atl1_read_phy_reg(hw, MII_BMSR, &phy_data); + atl1_read_phy_reg(hw, MII_BMSR, &phy_data); + if (!(phy_data & BMSR_LSTATUS)) { /* link down */ + if (netif_carrier_ok(netdev)) { /* old link state: Up */ + dev_info(&adapter->pdev->dev, "link is down\n"); + adapter->link_speed = SPEED_0; + netif_carrier_off(netdev); + netif_stop_queue(netdev); } + return ATL1_SUCCESS; } -} -static void atl1_update_rfd_index(struct atl1_adapter *adapter, - struct rx_return_desc *rrd) -{ - u16 num_buf; + /* Link Up */ + ret_val = atl1_get_speed_and_duplex(hw, &speed, &duplex); + if (ret_val) + return ret_val; - num_buf = (rrd->xsz.xsum_sz.pkt_size + adapter->rx_buffer_len - 1) / - adapter->rx_buffer_len; - if (rrd->num_buf == num_buf) - /* clean alloc flag for bad rrd */ - atl1_clean_alloc_flag(adapter, rrd, num_buf); -} + switch (hw->media_type) { + case MEDIA_TYPE_1000M_FULL: + if (speed != SPEED_1000 || duplex != FULL_DUPLEX) + reconfig = 1; + break; + case MEDIA_TYPE_100M_FULL: + if (speed != SPEED_100 || duplex != FULL_DUPLEX) + reconfig = 1; + break; + case MEDIA_TYPE_100M_HALF: + if (speed != SPEED_100 || duplex != HALF_DUPLEX) + reconfig = 1; + break; + case MEDIA_TYPE_10M_FULL: + if (speed != SPEED_10 || duplex != FULL_DUPLEX) + reconfig = 1; + break; + case MEDIA_TYPE_10M_HALF: + if (speed != SPEED_10 || duplex != HALF_DUPLEX) + reconfig = 1; + break; + } -static void atl1_rx_checksum(struct atl1_adapter *adapter, - struct rx_return_desc *rrd, struct sk_buff *skb) -{ - struct pci_dev *pdev = adapter->pdev; + /* link result is our setting */ + if (!reconfig) { + if (adapter->link_speed != speed + || adapter->link_duplex != duplex) { + adapter->link_speed = speed; + adapter->link_duplex = duplex; + atl1_setup_mac_ctrl(adapter); + dev_info(&adapter->pdev->dev, + "%s link is up %d Mbps %s\n", + netdev->name, adapter->link_speed, + adapter->link_duplex == FULL_DUPLEX ? + "full duplex" : "half duplex"); + } + if (!netif_carrier_ok(netdev)) { /* Link down -> Up */ + netif_carrier_on(netdev); + netif_wake_queue(netdev); + } + return ATL1_SUCCESS; + } - skb->ip_summed = CHECKSUM_NONE; + /* change orignal link status */ + if (netif_carrier_ok(netdev)) { + adapter->link_speed = SPEED_0; + netif_carrier_off(netdev); + netif_stop_queue(netdev); + } - if (unlikely(rrd->pkt_flg & PACKET_FLAG_ERR)) { - if (rrd->err_flg & (ERR_FLAG_CRC | ERR_FLAG_TRUNC | - ERR_FLAG_CODE | ERR_FLAG_OV)) { - adapter->hw_csum_err++; - dev_printk(KERN_DEBUG, &pdev->dev, - "rx checksum error\n"); - return; + if (hw->media_type != MEDIA_TYPE_AUTO_SENSOR && + hw->media_type != MEDIA_TYPE_1000M_FULL) { + switch (hw->media_type) { + case MEDIA_TYPE_100M_FULL: + phy_data = MII_CR_FULL_DUPLEX | MII_CR_SPEED_100 | + MII_CR_RESET; + break; + case MEDIA_TYPE_100M_HALF: + phy_data = MII_CR_SPEED_100 | MII_CR_RESET; + break; + case MEDIA_TYPE_10M_FULL: + phy_data = + MII_CR_FULL_DUPLEX | MII_CR_SPEED_10 | MII_CR_RESET; + break; + default: /* MEDIA_TYPE_10M_HALF: */ + phy_data = MII_CR_SPEED_10 | MII_CR_RESET; + break; } + atl1_write_phy_reg(hw, MII_BMCR, phy_data); + return ATL1_SUCCESS; } - /* not IPv4 */ - if (!(rrd->pkt_flg & PACKET_FLAG_IPV4)) - /* checksum is invalid, but it's not an IPv4 pkt, so ok */ - return; - - /* IPv4 packet */ - if (likely(!(rrd->err_flg & - (ERR_FLAG_IP_CHKSUM | ERR_FLAG_L4_CHKSUM)))) { - skb->ip_summed = CHECKSUM_UNNECESSARY; - adapter->hw_csum_good++; - return; + /* auto-neg, insert timer to re-config phy */ + if (!adapter->phy_timer_pending) { + adapter->phy_timer_pending = true; + mod_timer(&adapter->phy_config_timer, jiffies + 3 * HZ); } - /* IPv4, but hardware thinks its checksum is wrong */ - dev_printk(KERN_DEBUG, &pdev->dev, - "hw csum wrong, pkt_flag:%x, err_flag:%x\n", - rrd->pkt_flg, rrd->err_flg); - skb->ip_summed = CHECKSUM_COMPLETE; - skb->csum = htons(rrd->xsz.xsum_sz.rx_chksum); - adapter->hw_csum_err++; - return; + return ATL1_SUCCESS; } -/* - * atl1_alloc_rx_buffers - Replace used receive buffers - * @adapter: address of board private structure - */ -static u16 atl1_alloc_rx_buffers(struct atl1_adapter *adapter) +static void set_flow_ctrl_old(struct atl1_adapter *adapter) { - struct atl1_rfd_ring *rfd_ring = &adapter->rfd_ring; - struct pci_dev *pdev = adapter->pdev; - struct page *page; - unsigned long offset; - struct atl1_buffer *buffer_info, *next_info; - struct sk_buff *skb; - u16 num_alloc = 0; - u16 rfd_next_to_use, next_next; - struct rx_free_desc *rfd_desc; - - next_next = rfd_next_to_use = atomic_read(&rfd_ring->next_to_use); - if (++next_next == rfd_ring->count) - next_next = 0; - buffer_info = &rfd_ring->buffer_info[rfd_next_to_use]; - next_info = &rfd_ring->buffer_info[next_next]; - - while (!buffer_info->alloced && !next_info->alloced) { - if (buffer_info->skb) { - buffer_info->alloced = 1; - goto next; - } - - rfd_desc = ATL1_RFD_DESC(rfd_ring, rfd_next_to_use); + u32 hi, lo, value; - skb = dev_alloc_skb(adapter->rx_buffer_len + NET_IP_ALIGN); - if (unlikely(!skb)) { /* Better luck next round */ - adapter->net_stats.rx_dropped++; - break; - } + /* RFD Flow Control */ + value = adapter->rfd_ring.count; + hi = value / 16; + if (hi < 2) + hi = 2; + lo = value * 7 / 8; - /* - * Make buffer alignment 2 beyond a 16 byte boundary - * this will result in a 16 byte aligned IP header after - * the 14 byte MAC header is removed - */ - skb_reserve(skb, NET_IP_ALIGN); + value = ((hi & RXQ_RXF_PAUSE_TH_HI_MASK) << RXQ_RXF_PAUSE_TH_HI_SHIFT) | + ((lo & RXQ_RXF_PAUSE_TH_LO_MASK) << RXQ_RXF_PAUSE_TH_LO_SHIFT); + iowrite32(value, adapter->hw.hw_addr + REG_RXQ_RXF_PAUSE_THRESH); - buffer_info->alloced = 1; - buffer_info->skb = skb; - buffer_info->length = (u16) adapter->rx_buffer_len; - page = virt_to_page(skb->data); - offset = (unsigned long)skb->data & ~PAGE_MASK; - buffer_info->dma = pci_map_page(pdev, page, offset, - adapter->rx_buffer_len, - PCI_DMA_FROMDEVICE); - rfd_desc->buffer_addr = cpu_to_le64(buffer_info->dma); - rfd_desc->buf_len = cpu_to_le16(adapter->rx_buffer_len); - rfd_desc->coalese = 0; + /* RRD Flow Control */ + value = adapter->rrd_ring.count; + lo = value / 16; + hi = value * 7 / 8; + if (lo < 2) + lo = 2; + value = ((hi & RXQ_RRD_PAUSE_TH_HI_MASK) << RXQ_RRD_PAUSE_TH_HI_SHIFT) | + ((lo & RXQ_RRD_PAUSE_TH_LO_MASK) << RXQ_RRD_PAUSE_TH_LO_SHIFT); + iowrite32(value, adapter->hw.hw_addr + REG_RXQ_RRD_PAUSE_THRESH); +} -next: - rfd_next_to_use = next_next; - if (unlikely(++next_next == rfd_ring->count)) - next_next = 0; +static void set_flow_ctrl_new(struct atl1_hw *hw) +{ + u32 hi, lo, value; - buffer_info = &rfd_ring->buffer_info[rfd_next_to_use]; - next_info = &rfd_ring->buffer_info[next_next]; - num_alloc++; - } + /* RXF Flow Control */ + value = ioread32(hw->hw_addr + REG_SRAM_RXF_LEN); + lo = value / 16; + if (lo < 192) + lo = 192; + hi = value * 7 / 8; + if (hi < lo) + hi = lo + 16; + value = ((hi & RXQ_RXF_PAUSE_TH_HI_MASK) << RXQ_RXF_PAUSE_TH_HI_SHIFT) | + ((lo & RXQ_RXF_PAUSE_TH_LO_MASK) << RXQ_RXF_PAUSE_TH_LO_SHIFT); + iowrite32(value, hw->hw_addr + REG_RXQ_RXF_PAUSE_THRESH); - if (num_alloc) { - /* - * Force memory writes to complete before letting h/w - * know there are new descriptors to fetch. (Only - * applicable for weak-ordered memory model archs, - * such as IA-64). - */ - wmb(); - atomic_set(&rfd_ring->next_to_use, (int)rfd_next_to_use); - } - return num_alloc; + /* RRD Flow Control */ + value = ioread32(hw->hw_addr + REG_SRAM_RRD_LEN); + lo = value / 8; + hi = value * 7 / 8; + if (lo < 2) + lo = 2; + if (hi < lo) + hi = lo + 3; + value = ((hi & RXQ_RRD_PAUSE_TH_HI_MASK) << RXQ_RRD_PAUSE_TH_HI_SHIFT) | + ((lo & RXQ_RRD_PAUSE_TH_LO_MASK) << RXQ_RRD_PAUSE_TH_LO_SHIFT); + iowrite32(value, hw->hw_addr + REG_RXQ_RRD_PAUSE_THRESH); } -static void atl1_intr_rx(struct atl1_adapter *adapter) +/* + * atl1_configure - Configure Transmit&Receive Unit after Reset + * @adapter: board private structure + * + * Configure the Tx /Rx unit of the MAC after a reset. + */ +static u32 atl1_configure(struct atl1_adapter *adapter) { - int i, count; - u16 length; - u16 rrd_next_to_clean; + struct atl1_hw *hw = &adapter->hw; u32 value; - struct atl1_rfd_ring *rfd_ring = &adapter->rfd_ring; - struct atl1_rrd_ring *rrd_ring = &adapter->rrd_ring; - struct atl1_buffer *buffer_info; - struct rx_return_desc *rrd; - struct sk_buff *skb; - count = 0; - - rrd_next_to_clean = atomic_read(&rrd_ring->next_to_clean); + /* clear interrupt status */ + iowrite32(0xffffffff, adapter->hw.hw_addr + REG_ISR); - while (1) { - rrd = ATL1_RRD_DESC(rrd_ring, rrd_next_to_clean); - i = 1; - if (likely(rrd->xsz.valid)) { /* packet valid */ -chk_rrd: - /* check rrd status */ - if (likely(rrd->num_buf == 1)) - goto rrd_ok; + /* set MAC Address */ + value = (((u32) hw->mac_addr[2]) << 24) | + (((u32) hw->mac_addr[3]) << 16) | + (((u32) hw->mac_addr[4]) << 8) | + (((u32) hw->mac_addr[5])); + iowrite32(value, hw->hw_addr + REG_MAC_STA_ADDR); + value = (((u32) hw->mac_addr[0]) << 8) | (((u32) hw->mac_addr[1])); + iowrite32(value, hw->hw_addr + (REG_MAC_STA_ADDR + 4)); - /* rrd seems to be bad */ - if (unlikely(i-- > 0)) { - /* rrd may not be DMAed completely */ - dev_printk(KERN_DEBUG, &adapter->pdev->dev, - "incomplete RRD DMA transfer\n"); - udelay(1); - goto chk_rrd; - } - /* bad rrd */ - dev_printk(KERN_DEBUG, &adapter->pdev->dev, - "bad RRD\n"); - /* see if update RFD index */ - if (rrd->num_buf > 1) - atl1_update_rfd_index(adapter, rrd); + /* tx / rx ring */ - /* update rrd */ - rrd->xsz.valid = 0; - if (++rrd_next_to_clean == rrd_ring->count) - rrd_next_to_clean = 0; - count++; - continue; - } else { /* current rrd still not be updated */ + /* HI base address */ + iowrite32((u32) ((adapter->tpd_ring.dma & 0xffffffff00000000ULL) >> 32), + hw->hw_addr + REG_DESC_BASE_ADDR_HI); + /* LO base address */ + iowrite32((u32) (adapter->rfd_ring.dma & 0x00000000ffffffffULL), + hw->hw_addr + REG_DESC_RFD_ADDR_LO); + iowrite32((u32) (adapter->rrd_ring.dma & 0x00000000ffffffffULL), + hw->hw_addr + REG_DESC_RRD_ADDR_LO); + iowrite32((u32) (adapter->tpd_ring.dma & 0x00000000ffffffffULL), + hw->hw_addr + REG_DESC_TPD_ADDR_LO); + iowrite32((u32) (adapter->cmb.dma & 0x00000000ffffffffULL), + hw->hw_addr + REG_DESC_CMB_ADDR_LO); + iowrite32((u32) (adapter->smb.dma & 0x00000000ffffffffULL), + hw->hw_addr + REG_DESC_SMB_ADDR_LO); - break; - } -rrd_ok: - /* clean alloc flag for bad rrd */ - atl1_clean_alloc_flag(adapter, rrd, 0); + /* element count */ + value = adapter->rrd_ring.count; + value <<= 16; + value += adapter->rfd_ring.count; + iowrite32(value, hw->hw_addr + REG_DESC_RFD_RRD_RING_SIZE); + iowrite32(adapter->tpd_ring.count, hw->hw_addr + REG_DESC_TPD_RING_SIZE); - buffer_info = &rfd_ring->buffer_info[rrd->buf_indx]; - if (++rfd_ring->next_to_clean == rfd_ring->count) - rfd_ring->next_to_clean = 0; + /* Load Ptr */ + iowrite32(1, hw->hw_addr + REG_LOAD_PTR); - /* update rrd next to clean */ - if (++rrd_next_to_clean == rrd_ring->count) - rrd_next_to_clean = 0; - count++; + /* config Mailbox */ + value = ((atomic_read(&adapter->tpd_ring.next_to_use) + & MB_TPD_PROD_INDX_MASK) << MB_TPD_PROD_INDX_SHIFT) | + ((atomic_read(&adapter->rrd_ring.next_to_clean) + & MB_RRD_CONS_INDX_MASK) << MB_RRD_CONS_INDX_SHIFT) | + ((atomic_read(&adapter->rfd_ring.next_to_use) + & MB_RFD_PROD_INDX_MASK) << MB_RFD_PROD_INDX_SHIFT); + iowrite32(value, hw->hw_addr + REG_MAILBOX); - if (unlikely(rrd->pkt_flg & PACKET_FLAG_ERR)) { - if (!(rrd->err_flg & - (ERR_FLAG_IP_CHKSUM | ERR_FLAG_L4_CHKSUM - | ERR_FLAG_LEN))) { - /* packet error, don't need upstream */ - buffer_info->alloced = 0; - rrd->xsz.valid = 0; - continue; - } - } + /* config IPG/IFG */ + value = (((u32) hw->ipgt & MAC_IPG_IFG_IPGT_MASK) + << MAC_IPG_IFG_IPGT_SHIFT) | + (((u32) hw->min_ifg & MAC_IPG_IFG_MIFG_MASK) + << MAC_IPG_IFG_MIFG_SHIFT) | + (((u32) hw->ipgr1 & MAC_IPG_IFG_IPGR1_MASK) + << MAC_IPG_IFG_IPGR1_SHIFT) | + (((u32) hw->ipgr2 & MAC_IPG_IFG_IPGR2_MASK) + << MAC_IPG_IFG_IPGR2_SHIFT); + iowrite32(value, hw->hw_addr + REG_MAC_IPG_IFG); - /* Good Receive */ - pci_unmap_page(adapter->pdev, buffer_info->dma, - buffer_info->length, PCI_DMA_FROMDEVICE); - skb = buffer_info->skb; - length = le16_to_cpu(rrd->xsz.xsum_sz.pkt_size); + /* config Half-Duplex Control */ + value = ((u32) hw->lcol & MAC_HALF_DUPLX_CTRL_LCOL_MASK) | + (((u32) hw->max_retry & MAC_HALF_DUPLX_CTRL_RETRY_MASK) + << MAC_HALF_DUPLX_CTRL_RETRY_SHIFT) | + MAC_HALF_DUPLX_CTRL_EXC_DEF_EN | + (0xa << MAC_HALF_DUPLX_CTRL_ABEBT_SHIFT) | + (((u32) hw->jam_ipg & MAC_HALF_DUPLX_CTRL_JAMIPG_MASK) + << MAC_HALF_DUPLX_CTRL_JAMIPG_SHIFT); + iowrite32(value, hw->hw_addr + REG_MAC_HALF_DUPLX_CTRL); - skb_put(skb, length - ETHERNET_FCS_SIZE); + /* set Interrupt Moderator Timer */ + iowrite16(adapter->imt, hw->hw_addr + REG_IRQ_MODU_TIMER_INIT); + iowrite32(MASTER_CTRL_ITIMER_EN, hw->hw_addr + REG_MASTER_CTRL); - /* Receive Checksum Offload */ - atl1_rx_checksum(adapter, rrd, skb); - skb->protocol = eth_type_trans(skb, adapter->netdev); + /* set Interrupt Clear Timer */ + iowrite16(adapter->ict, hw->hw_addr + REG_CMBDISDMA_TIMER); - if (adapter->vlgrp && (rrd->pkt_flg & PACKET_FLAG_VLAN_INS)) { - u16 vlan_tag = (rrd->vlan_tag >> 4) | - ((rrd->vlan_tag & 7) << 13) | - ((rrd->vlan_tag & 8) << 9); - vlan_hwaccel_rx(skb, adapter->vlgrp, vlan_tag); - } else - netif_rx(skb); + /* set MTU, 4 : VLAN */ + iowrite32(hw->max_frame_size + 4, hw->hw_addr + REG_MTU); - /* let protocol layer free skb */ - buffer_info->skb = NULL; - buffer_info->alloced = 0; - rrd->xsz.valid = 0; + /* jumbo size & rrd retirement timer */ + value = (((u32) hw->rx_jumbo_th & RXQ_JMBOSZ_TH_MASK) + << RXQ_JMBOSZ_TH_SHIFT) | + (((u32) hw->rx_jumbo_lkah & RXQ_JMBO_LKAH_MASK) + << RXQ_JMBO_LKAH_SHIFT) | + (((u32) hw->rrd_ret_timer & RXQ_RRD_TIMER_MASK) + << RXQ_RRD_TIMER_SHIFT); + iowrite32(value, hw->hw_addr + REG_RXQ_JMBOSZ_RRDTIM); - adapter->netdev->last_rx = jiffies; + /* Flow Control */ + switch (hw->dev_rev) { + case 0x8001: + case 0x9001: + case 0x9002: + case 0x9003: + set_flow_ctrl_old(adapter); + break; + default: + set_flow_ctrl_new(hw); + break; } - atomic_set(&rrd_ring->next_to_clean, rrd_next_to_clean); + /* config TXQ */ + value = (((u32) hw->tpd_burst & TXQ_CTRL_TPD_BURST_NUM_MASK) + << TXQ_CTRL_TPD_BURST_NUM_SHIFT) | + (((u32) hw->txf_burst & TXQ_CTRL_TXF_BURST_NUM_MASK) + << TXQ_CTRL_TXF_BURST_NUM_SHIFT) | + (((u32) hw->tpd_fetch_th & TXQ_CTRL_TPD_FETCH_TH_MASK) + << TXQ_CTRL_TPD_FETCH_TH_SHIFT) | TXQ_CTRL_ENH_MODE | TXQ_CTRL_EN; + iowrite32(value, hw->hw_addr + REG_TXQ_CTRL); - atl1_alloc_rx_buffers(adapter); + /* min tpd fetch gap & tx jumbo packet size threshold for taskoffload */ + value = (((u32) hw->tx_jumbo_task_th & TX_JUMBO_TASK_TH_MASK) + << TX_JUMBO_TASK_TH_SHIFT) | + (((u32) hw->tpd_fetch_gap & TX_TPD_MIN_IPG_MASK) + << TX_TPD_MIN_IPG_SHIFT); + iowrite32(value, hw->hw_addr + REG_TX_JUMBO_TASK_TH_TPD_IPG); - /* update mailbox ? */ - if (count) { - u32 tpd_next_to_use; - u32 rfd_next_to_use; - u32 rrd_next_to_clean; + /* config RXQ */ + value = (((u32) hw->rfd_burst & RXQ_CTRL_RFD_BURST_NUM_MASK) + << RXQ_CTRL_RFD_BURST_NUM_SHIFT) | + (((u32) hw->rrd_burst & RXQ_CTRL_RRD_BURST_THRESH_MASK) + << RXQ_CTRL_RRD_BURST_THRESH_SHIFT) | + (((u32) hw->rfd_fetch_gap & RXQ_CTRL_RFD_PREF_MIN_IPG_MASK) + << RXQ_CTRL_RFD_PREF_MIN_IPG_SHIFT) | + RXQ_CTRL_CUT_THRU_EN | RXQ_CTRL_EN; + iowrite32(value, hw->hw_addr + REG_RXQ_CTRL); - spin_lock(&adapter->mb_lock); + /* config DMA Engine */ + value = ((((u32) hw->dmar_block) & DMA_CTRL_DMAR_BURST_LEN_MASK) + << DMA_CTRL_DMAR_BURST_LEN_SHIFT) | + ((((u32) hw->dmaw_block) & DMA_CTRL_DMAR_BURST_LEN_MASK) + << DMA_CTRL_DMAR_BURST_LEN_SHIFT) | + DMA_CTRL_DMAR_EN | DMA_CTRL_DMAW_EN; + value |= (u32) hw->dma_ord; + if (atl1_rcb_128 == hw->rcb_value) + value |= DMA_CTRL_RCB_VALUE; + iowrite32(value, hw->hw_addr + REG_DMA_CTRL); - tpd_next_to_use = atomic_read(&adapter->tpd_ring.next_to_use); - rfd_next_to_use = - atomic_read(&adapter->rfd_ring.next_to_use); - rrd_next_to_clean = - atomic_read(&adapter->rrd_ring.next_to_clean); - value = ((rfd_next_to_use & MB_RFD_PROD_INDX_MASK) << - MB_RFD_PROD_INDX_SHIFT) | - ((rrd_next_to_clean & MB_RRD_CONS_INDX_MASK) << - MB_RRD_CONS_INDX_SHIFT) | - ((tpd_next_to_use & MB_TPD_PROD_INDX_MASK) << - MB_TPD_PROD_INDX_SHIFT); - iowrite32(value, adapter->hw.hw_addr + REG_MAILBOX); - spin_unlock(&adapter->mb_lock); - } + /* config CMB / SMB */ + value = hw->cmb_rrd | ((u32) hw->cmb_tpd << 16); + iowrite32(value, hw->hw_addr + REG_CMB_WRITE_TH); + value = hw->cmb_rx_timer | ((u32) hw->cmb_tx_timer << 16); + iowrite32(value, hw->hw_addr + REG_CMB_WRITE_TIMER); + iowrite32(hw->smb_timer, hw->hw_addr + REG_SMB_TIMER); + + /* --- enable CMB / SMB */ + value = CSMB_CTRL_CMB_EN | CSMB_CTRL_SMB_EN; + iowrite32(value, hw->hw_addr + REG_CSMB_CTRL); + + value = ioread32(adapter->hw.hw_addr + REG_ISR); + if (unlikely((value & ISR_PHY_LINKDOWN) != 0)) + value = 1; /* config failed */ + else + value = 0; + + /* clear all interrupt status */ + iowrite32(0x3fffffff, adapter->hw.hw_addr + REG_ISR); + iowrite32(0, adapter->hw.hw_addr + REG_ISR); + return value; +} + +/* + * atl1_irq_disable - Mask off interrupt generation on the NIC + * @adapter: board private structure + */ +static void atl1_irq_disable(struct atl1_adapter *adapter) +{ + atomic_inc(&adapter->irq_sem); + iowrite32(0, adapter->hw.hw_addr + REG_IMR); + ioread32(adapter->hw.hw_addr + REG_IMR); + synchronize_irq(adapter->pdev->irq); } -static void atl1_intr_tx(struct atl1_adapter *adapter) +static void atl1_vlan_rx_register(struct net_device *netdev, + struct vlan_group *grp) { - struct atl1_tpd_ring *tpd_ring = &adapter->tpd_ring; - struct atl1_buffer *buffer_info; - u16 sw_tpd_next_to_clean; - u16 cmb_tpd_next_to_clean; - - sw_tpd_next_to_clean = atomic_read(&tpd_ring->next_to_clean); - cmb_tpd_next_to_clean = le16_to_cpu(adapter->cmb.cmb->tpd_cons_idx); - - while (cmb_tpd_next_to_clean != sw_tpd_next_to_clean) { - struct tx_packet_desc *tpd; - - tpd = ATL1_TPD_DESC(tpd_ring, sw_tpd_next_to_clean); - buffer_info = &tpd_ring->buffer_info[sw_tpd_next_to_clean]; - if (buffer_info->dma) { - pci_unmap_page(adapter->pdev, buffer_info->dma, - buffer_info->length, PCI_DMA_TODEVICE); - buffer_info->dma = 0; - } + struct atl1_adapter *adapter = netdev_priv(netdev); + unsigned long flags; + u32 ctrl; - if (buffer_info->skb) { - dev_kfree_skb_irq(buffer_info->skb); - buffer_info->skb = NULL; - } - tpd->buffer_addr = 0; - tpd->desc.data = 0; + spin_lock_irqsave(&adapter->lock, flags); + /* atl1_irq_disable(adapter); */ + adapter->vlgrp = grp; - if (++sw_tpd_next_to_clean == tpd_ring->count) - sw_tpd_next_to_clean = 0; + if (grp) { + /* enable VLAN tag insert/strip */ + ctrl = ioread32(adapter->hw.hw_addr + REG_MAC_CTRL); + ctrl |= MAC_CTRL_RMV_VLAN; + iowrite32(ctrl, adapter->hw.hw_addr + REG_MAC_CTRL); + } else { + /* disable VLAN tag insert/strip */ + ctrl = ioread32(adapter->hw.hw_addr + REG_MAC_CTRL); + ctrl &= ~MAC_CTRL_RMV_VLAN; + iowrite32(ctrl, adapter->hw.hw_addr + REG_MAC_CTRL); } - atomic_set(&tpd_ring->next_to_clean, sw_tpd_next_to_clean); - if (netif_queue_stopped(adapter->netdev) - && netif_carrier_ok(adapter->netdev)) - netif_wake_queue(adapter->netdev); + /* atl1_irq_enable(adapter); */ + spin_unlock_irqrestore(&adapter->lock, flags); +} + +static void atl1_restore_vlan(struct atl1_adapter *adapter) +{ + atl1_vlan_rx_register(adapter->netdev, adapter->vlgrp); } static u16 tpd_avail(struct atl1_tpd_ring *tpd_ring) { u16 next_to_clean = atomic_read(&tpd_ring->next_to_clean); u16 next_to_use = atomic_read(&tpd_ring->next_to_use); - return ((next_to_clean > next_to_use) ? - next_to_clean - next_to_use - 1 : - tpd_ring->count + next_to_clean - next_to_use - 1); + return ((next_to_clean > + next_to_use) ? next_to_clean - next_to_use - + 1 : tpd_ring->count + next_to_clean - next_to_use - 1); } static int atl1_tso(struct atl1_adapter *adapter, struct sk_buff *skb, @@ -1450,7 +1258,9 @@ static int atl1_tso(struct atl1_adapter *adapter, struct sk_buff *skb, iph->tot_len = 0; iph->check = 0; tcp_hdr(skb)->check = ~csum_tcpudp_magic(iph->saddr, - iph->daddr, 0, IPPROTO_TCP, 0); + iph->daddr, 0, + IPPROTO_TCP, + 0); ipofst = skb_network_offset(skb); if (ipofst != ENET_HEADER_SIZE) /* 802.3 frame */ tso->tsopl |= 1 << TSO_PARAM_ETHTYPE_SHIFT; @@ -1458,8 +1268,7 @@ static int atl1_tso(struct atl1_adapter *adapter, struct sk_buff *skb, tso->tsopl |= (iph->ihl & CSUM_PARAM_IPHL_MASK) << CSUM_PARAM_IPHL_SHIFT; tso->tsopl |= (tcp_hdrlen(skb) & - TSO_PARAM_TCPHDRLEN_MASK) << - TSO_PARAM_TCPHDRLEN_SHIFT; + TSO_PARAM_TCPHDRLEN_MASK) << TSO_PARAM_TCPHDRLEN_SHIFT; tso->tsopl |= (skb_shinfo(skb)->gso_size & TSO_PARAM_MSS_MASK) << TSO_PARAM_MSS_SHIFT; tso->tsopl |= 1 << TSO_PARAM_IPCKSUM_SHIFT; @@ -1472,7 +1281,7 @@ static int atl1_tso(struct atl1_adapter *adapter, struct sk_buff *skb, } static int atl1_tx_csum(struct atl1_adapter *adapter, struct sk_buff *skb, - struct csum_param *csum) + struct csum_param *csum) { u8 css, cso; @@ -1480,7 +1289,7 @@ static int atl1_tx_csum(struct atl1_adapter *adapter, struct sk_buff *skb, cso = skb_transport_offset(skb); css = cso + skb->csum_offset; if (unlikely(cso & 0x1)) { - dev_printk(KERN_DEBUG, &adapter->pdev->dev, + dev_dbg(&adapter->pdev->dev, "payload offset not an even number\n"); return -1; } @@ -1495,8 +1304,8 @@ static int atl1_tx_csum(struct atl1_adapter *adapter, struct sk_buff *skb, return true; } -static void atl1_tx_map(struct atl1_adapter *adapter, struct sk_buff *skb, - bool tcp_seg) +static void atl1_tx_map(struct atl1_adapter *adapter, + struct sk_buff *skb, bool tcp_seg) { /* We enter this function holding a spinlock. */ struct atl1_tpd_ring *tpd_ring = &adapter->tpd_ring; @@ -1533,25 +1342,26 @@ static void atl1_tx_map(struct atl1_adapter *adapter, struct sk_buff *skb, if (first_buf_len > proto_hdr_len) { len12 = first_buf_len - proto_hdr_len; - m = (len12 + ATL1_MAX_TX_BUF_LEN - 1) / - ATL1_MAX_TX_BUF_LEN; + m = (len12 + MAX_TX_BUF_LEN - 1) / MAX_TX_BUF_LEN; for (i = 0; i < m; i++) { buffer_info = &tpd_ring->buffer_info[tpd_next_to_use]; buffer_info->skb = NULL; buffer_info->length = - (ATL1_MAX_TX_BUF_LEN >= - len12) ? ATL1_MAX_TX_BUF_LEN : len12; + (MAX_TX_BUF_LEN >= + len12) ? MAX_TX_BUF_LEN : len12; len12 -= buffer_info->length; page = virt_to_page(skb->data + - (proto_hdr_len + - i * ATL1_MAX_TX_BUF_LEN)); + (proto_hdr_len + + i * MAX_TX_BUF_LEN)); offset = (unsigned long)(skb->data + - (proto_hdr_len + - i * ATL1_MAX_TX_BUF_LEN)) & ~PAGE_MASK; - buffer_info->dma = pci_map_page(adapter->pdev, - page, offset, buffer_info->length, - PCI_DMA_TODEVICE); + (proto_hdr_len + + i * MAX_TX_BUF_LEN)) & + ~PAGE_MASK; + buffer_info->dma = + pci_map_page(adapter->pdev, page, offset, + buffer_info->length, + PCI_DMA_TODEVICE); if (++tpd_next_to_use == tpd_ring->count) tpd_next_to_use = 0; } @@ -1562,7 +1372,8 @@ static void atl1_tx_map(struct atl1_adapter *adapter, struct sk_buff *skb, page = virt_to_page(skb->data); offset = (unsigned long)skb->data & ~PAGE_MASK; buffer_info->dma = pci_map_page(adapter->pdev, page, - offset, first_buf_len, PCI_DMA_TODEVICE); + offset, first_buf_len, + PCI_DMA_TODEVICE); if (++tpd_next_to_use == tpd_ring->count) tpd_next_to_use = 0; } @@ -1574,19 +1385,19 @@ static void atl1_tx_map(struct atl1_adapter *adapter, struct sk_buff *skb, frag = &skb_shinfo(skb)->frags[f]; lenf = frag->size; - m = (lenf + ATL1_MAX_TX_BUF_LEN - 1) / ATL1_MAX_TX_BUF_LEN; + m = (lenf + MAX_TX_BUF_LEN - 1) / MAX_TX_BUF_LEN; for (i = 0; i < m; i++) { buffer_info = &tpd_ring->buffer_info[tpd_next_to_use]; if (unlikely(buffer_info->skb)) BUG(); buffer_info->skb = NULL; - buffer_info->length = (lenf > ATL1_MAX_TX_BUF_LEN) ? - ATL1_MAX_TX_BUF_LEN : lenf; + buffer_info->length = + (lenf > MAX_TX_BUF_LEN) ? MAX_TX_BUF_LEN : lenf; lenf -= buffer_info->length; - buffer_info->dma = pci_map_page(adapter->pdev, - frag->page, - frag->page_offset + (i * ATL1_MAX_TX_BUF_LEN), - buffer_info->length, PCI_DMA_TODEVICE); + buffer_info->dma = + pci_map_page(adapter->pdev, frag->page, + frag->page_offset + i * MAX_TX_BUF_LEN, + buffer_info->length, PCI_DMA_TODEVICE); if (++tpd_next_to_use == tpd_ring->count) tpd_next_to_use = 0; @@ -1598,7 +1409,7 @@ static void atl1_tx_map(struct atl1_adapter *adapter, struct sk_buff *skb, } static void atl1_tx_queue(struct atl1_adapter *adapter, int count, - union tpd_descr *descr) + union tpd_descr *descr) { /* We enter this function holding a spinlock. */ struct atl1_tpd_ring *tpd_ring = &adapter->tpd_ring; @@ -1642,6 +1453,31 @@ static void atl1_tx_queue(struct atl1_adapter *adapter, int count, atomic_set(&tpd_ring->next_to_use, (int)tpd_next_to_use); } +static void atl1_update_mailbox(struct atl1_adapter *adapter) +{ + unsigned long flags; + u32 tpd_next_to_use; + u32 rfd_next_to_use; + u32 rrd_next_to_clean; + u32 value; + + spin_lock_irqsave(&adapter->mb_lock, flags); + + tpd_next_to_use = atomic_read(&adapter->tpd_ring.next_to_use); + rfd_next_to_use = atomic_read(&adapter->rfd_ring.next_to_use); + rrd_next_to_clean = atomic_read(&adapter->rrd_ring.next_to_clean); + + value = ((rfd_next_to_use & MB_RFD_PROD_INDX_MASK) << + MB_RFD_PROD_INDX_SHIFT) | + ((rrd_next_to_clean & MB_RRD_CONS_INDX_MASK) << + MB_RRD_CONS_INDX_SHIFT) | + ((tpd_next_to_use & MB_TPD_PROD_INDX_MASK) << + MB_TPD_PROD_INDX_SHIFT); + iowrite32(value, adapter->hw.hw_addr + REG_MAILBOX); + + spin_unlock_irqrestore(&adapter->mb_lock, flags); +} + static int atl1_xmit_frame(struct sk_buff *skb, struct net_device *netdev) { struct atl1_adapter *adapter = netdev_priv(netdev); @@ -1677,8 +1513,8 @@ static int atl1_xmit_frame(struct sk_buff *skb, struct net_device *netdev) for (f = 0; f < nr_frags; f++) { frag_size = skb_shinfo(skb)->frags[f].size; if (frag_size) - count += (frag_size + ATL1_MAX_TX_BUF_LEN - 1) / - ATL1_MAX_TX_BUF_LEN; + count += + (frag_size + MAX_TX_BUF_LEN - 1) / MAX_TX_BUF_LEN; } /* mss will be nonzero if we're doing segment offload (TSO/GSO) */ @@ -1694,8 +1530,7 @@ static int atl1_xmit_frame(struct sk_buff *skb, struct net_device *netdev) /* need additional TPD ? */ if (proto_hdr_len != len) count += (len - proto_hdr_len + - ATL1_MAX_TX_BUF_LEN - 1) / - ATL1_MAX_TX_BUF_LEN; + MAX_TX_BUF_LEN - 1) / MAX_TX_BUF_LEN; } } @@ -1703,7 +1538,7 @@ static int atl1_xmit_frame(struct sk_buff *skb, struct net_device *netdev) if (!spin_trylock(&adapter->lock)) { /* Can't get lock - tell upper layer to requeue */ local_irq_restore(flags); - dev_printk(KERN_DEBUG, &adapter->pdev->dev, "tx locked\n"); + dev_dbg(&adapter->pdev->dev, "tx locked\n"); return NETDEV_TX_LOCKED; } @@ -1711,7 +1546,7 @@ static int atl1_xmit_frame(struct sk_buff *skb, struct net_device *netdev) /* not enough descriptors */ netif_stop_queue(netdev); spin_unlock_irqrestore(&adapter->lock, flags); - dev_printk(KERN_DEBUG, &adapter->pdev->dev, "tx busy\n"); + dev_dbg(&adapter->pdev->dev, "tx busy\n"); return NETDEV_TX_BUSY; } @@ -1753,208 +1588,131 @@ static int atl1_xmit_frame(struct sk_buff *skb, struct net_device *netdev) } /* - * atl1_intr - Interrupt Handler - * @irq: interrupt number - * @data: pointer to a network interface device structure - * @pt_regs: CPU registers structure - */ -static irqreturn_t atl1_intr(int irq, void *data) -{ - struct atl1_adapter *adapter = netdev_priv(data); - u32 status; - u8 update_rx; - int max_ints = 10; - - status = adapter->cmb.cmb->int_stats; - if (!status) - return IRQ_NONE; - - update_rx = 0; - - do { - /* clear CMB interrupt status at once */ - adapter->cmb.cmb->int_stats = 0; - - if (status & ISR_GPHY) /* clear phy status */ - atl1_clear_phy_int(adapter); - - /* clear ISR status, and Enable CMB DMA/Disable Interrupt */ - iowrite32(status | ISR_DIS_INT, adapter->hw.hw_addr + REG_ISR); - - /* check if SMB intr */ - if (status & ISR_SMB) - atl1_inc_smb(adapter); - - /* check if PCIE PHY Link down */ - if (status & ISR_PHY_LINKDOWN) { - dev_printk(KERN_DEBUG, &adapter->pdev->dev, - "pcie phy link down %x\n", status); - if (netif_running(adapter->netdev)) { /* reset MAC */ - iowrite32(0, adapter->hw.hw_addr + REG_IMR); - schedule_work(&adapter->pcie_dma_to_rst_task); - return IRQ_HANDLED; - } - } - - /* check if DMA read/write error ? */ - if (status & (ISR_DMAR_TO_RST | ISR_DMAW_TO_RST)) { - dev_printk(KERN_DEBUG, &adapter->pdev->dev, - "pcie DMA r/w error (status = 0x%x)\n", - status); - iowrite32(0, adapter->hw.hw_addr + REG_IMR); - schedule_work(&adapter->pcie_dma_to_rst_task); - return IRQ_HANDLED; - } - - /* link event */ - if (status & ISR_GPHY) { - adapter->soft_stats.tx_carrier_errors++; - atl1_check_for_link(adapter); - } - - /* transmit event */ - if (status & ISR_CMB_TX) - atl1_intr_tx(adapter); - - /* rx exception */ - if (unlikely(status & (ISR_RXF_OV | ISR_RFD_UNRUN | - ISR_RRD_OV | ISR_HOST_RFD_UNRUN | - ISR_HOST_RRD_OV | ISR_CMB_RX))) { - if (status & (ISR_RXF_OV | ISR_RFD_UNRUN | - ISR_RRD_OV | ISR_HOST_RFD_UNRUN | - ISR_HOST_RRD_OV)) - dev_printk(KERN_DEBUG, &adapter->pdev->dev, - "rx exception, ISR = 0x%x\n", status); - atl1_intr_rx(adapter); - } - - if (--max_ints < 0) - break; - - } while ((status = adapter->cmb.cmb->int_stats)); - - /* re-enable Interrupt */ - iowrite32(ISR_DIS_SMB | ISR_DIS_DMA, adapter->hw.hw_addr + REG_ISR); - return IRQ_HANDLED; -} - -/* - * atl1_watchdog - Timer Call-back - * @data: pointer to netdev cast into an unsigned long - */ -static void atl1_watchdog(unsigned long data) -{ - struct atl1_adapter *adapter = (struct atl1_adapter *)data; - - /* Reset the timer */ - mod_timer(&adapter->watchdog_timer, jiffies + 2 * HZ); -} - -/* - * atl1_phy_config - Timer Call-back - * @data: pointer to netdev cast into an unsigned long - */ -static void atl1_phy_config(unsigned long data) -{ - struct atl1_adapter *adapter = (struct atl1_adapter *)data; - struct atl1_hw *hw = &adapter->hw; - unsigned long flags; - - spin_lock_irqsave(&adapter->lock, flags); - adapter->phy_timer_pending = false; - atl1_write_phy_reg(hw, MII_ADVERTISE, hw->mii_autoneg_adv_reg); - atl1_write_phy_reg(hw, MII_AT001_CR, hw->mii_1000t_ctrl_reg); - atl1_write_phy_reg(hw, MII_BMCR, MII_CR_RESET | MII_CR_AUTO_NEG_EN); - spin_unlock_irqrestore(&adapter->lock, flags); -} - -/* - * atl1_tx_timeout - Respond to a Tx Hang + * atl1_get_stats - Get System Network Statistics * @netdev: network interface device structure + * + * Returns the address of the device statistics structure. + * The statistics are actually updated from the timer callback. */ -static void atl1_tx_timeout(struct net_device *netdev) +static struct net_device_stats *atl1_get_stats(struct net_device *netdev) { struct atl1_adapter *adapter = netdev_priv(netdev); - /* Do the reset outside of interrupt context */ - schedule_work(&adapter->tx_timeout_task); + return &adapter->net_stats; } /* - * Orphaned vendor comment left intact here: - * - * If TPD Buffer size equal to 0, PCIE DMAR_TO_INT - * will assert. We do soft reset <0x1400=1> according - * with the SPEC. BUT, it seemes that PCIE or DMA - * state-machine will not be reset. DMAR_TO_INT will - * assert again and again. - * + * atl1_clean_rx_ring - Free RFD Buffers + * @adapter: board private structure */ -static void atl1_tx_timeout_task(struct work_struct *work) +static void atl1_clean_rx_ring(struct atl1_adapter *adapter) { - struct atl1_adapter *adapter = - container_of(work, struct atl1_adapter, tx_timeout_task); - struct net_device *netdev = adapter->netdev; + struct atl1_rfd_ring *rfd_ring = &adapter->rfd_ring; + struct atl1_rrd_ring *rrd_ring = &adapter->rrd_ring; + struct atl1_buffer *buffer_info; + struct pci_dev *pdev = adapter->pdev; + unsigned long size; + unsigned int i; - netif_device_detach(netdev); - atl1_down(adapter); - atl1_up(adapter); - netif_device_attach(netdev); -} + /* Free all the Rx ring sk_buffs */ + for (i = 0; i < rfd_ring->count; i++) { + buffer_info = &rfd_ring->buffer_info[i]; + if (buffer_info->dma) { + pci_unmap_page(pdev, + buffer_info->dma, + buffer_info->length, + PCI_DMA_FROMDEVICE); + buffer_info->dma = 0; + } + if (buffer_info->skb) { + dev_kfree_skb(buffer_info->skb); + buffer_info->skb = NULL; + } + } -/* - * atl1_link_chg_task - deal with link change event Out of interrupt context - */ -static void atl1_link_chg_task(struct work_struct *work) -{ - struct atl1_adapter *adapter = - container_of(work, struct atl1_adapter, link_chg_task); - unsigned long flags; + size = sizeof(struct atl1_buffer) * rfd_ring->count; + memset(rfd_ring->buffer_info, 0, size); - spin_lock_irqsave(&adapter->lock, flags); - atl1_check_link(adapter); - spin_unlock_irqrestore(&adapter->lock, flags); + /* Zero out the descriptor ring */ + memset(rfd_ring->desc, 0, rfd_ring->size); + + rfd_ring->next_to_clean = 0; + atomic_set(&rfd_ring->next_to_use, 0); + + rrd_ring->next_to_use = 0; + atomic_set(&rrd_ring->next_to_clean, 0); } -static void atl1_vlan_rx_register(struct net_device *netdev, - struct vlan_group *grp) +/* + * atl1_clean_tx_ring - Free Tx Buffers + * @adapter: board private structure + */ +static void atl1_clean_tx_ring(struct atl1_adapter *adapter) { - struct atl1_adapter *adapter = netdev_priv(netdev); - unsigned long flags; - u32 ctrl; + struct atl1_tpd_ring *tpd_ring = &adapter->tpd_ring; + struct atl1_buffer *buffer_info; + struct pci_dev *pdev = adapter->pdev; + unsigned long size; + unsigned int i; - spin_lock_irqsave(&adapter->lock, flags); - /* atl1_irq_disable(adapter); */ - adapter->vlgrp = grp; + /* Free all the Tx ring sk_buffs */ + for (i = 0; i < tpd_ring->count; i++) { + buffer_info = &tpd_ring->buffer_info[i]; + if (buffer_info->dma) { + pci_unmap_page(pdev, buffer_info->dma, + buffer_info->length, PCI_DMA_TODEVICE); + buffer_info->dma = 0; + } + } - if (grp) { - /* enable VLAN tag insert/strip */ - ctrl = ioread32(adapter->hw.hw_addr + REG_MAC_CTRL); - ctrl |= MAC_CTRL_RMV_VLAN; - iowrite32(ctrl, adapter->hw.hw_addr + REG_MAC_CTRL); - } else { - /* disable VLAN tag insert/strip */ - ctrl = ioread32(adapter->hw.hw_addr + REG_MAC_CTRL); - ctrl &= ~MAC_CTRL_RMV_VLAN; - iowrite32(ctrl, adapter->hw.hw_addr + REG_MAC_CTRL); + for (i = 0; i < tpd_ring->count; i++) { + buffer_info = &tpd_ring->buffer_info[i]; + if (buffer_info->skb) { + dev_kfree_skb_any(buffer_info->skb); + buffer_info->skb = NULL; + } } - /* atl1_irq_enable(adapter); */ - spin_unlock_irqrestore(&adapter->lock, flags); -} + size = sizeof(struct atl1_buffer) * tpd_ring->count; + memset(tpd_ring->buffer_info, 0, size); -static void atl1_restore_vlan(struct atl1_adapter *adapter) -{ - atl1_vlan_rx_register(adapter->netdev, adapter->vlgrp); + /* Zero out the descriptor ring */ + memset(tpd_ring->desc, 0, tpd_ring->size); + + atomic_set(&tpd_ring->next_to_use, 0); + atomic_set(&tpd_ring->next_to_clean, 0); } -int atl1_reset(struct atl1_adapter *adapter) +/* + * atl1_free_ring_resources - Free Tx / RX descriptor Resources + * @adapter: board private structure + * + * Free all transmit software resources + */ +void atl1_free_ring_resources(struct atl1_adapter *adapter) { - int ret; + struct pci_dev *pdev = adapter->pdev; + struct atl1_tpd_ring *tpd_ring = &adapter->tpd_ring; + struct atl1_rfd_ring *rfd_ring = &adapter->rfd_ring; + struct atl1_rrd_ring *rrd_ring = &adapter->rrd_ring; + struct atl1_ring_header *ring_header = &adapter->ring_header; - ret = atl1_reset_hw(&adapter->hw); - if (ret != ATL1_SUCCESS) - return ret; - return atl1_init_hw(&adapter->hw); + atl1_clean_tx_ring(adapter); + atl1_clean_rx_ring(adapter); + + kfree(tpd_ring->buffer_info); + pci_free_consistent(pdev, ring_header->size, ring_header->desc, + ring_header->dma); + + tpd_ring->buffer_info = NULL; + tpd_ring->desc = NULL; + tpd_ring->dma = 0; + + rfd_ring->buffer_info = NULL; + rfd_ring->desc = NULL; + rfd_ring->dma = 0; + + rrd_ring->desc = NULL; + rrd_ring->dma = 0; } s32 atl1_up(struct atl1_adapter *adapter) @@ -1965,7 +1723,6 @@ s32 atl1_up(struct atl1_adapter *adapter) /* hardware has been reset, we need to reload some things */ atl1_set_multi(netdev); - atl1_init_ring_ptrs(adapter); atl1_restore_vlan(adapter); err = atl1_alloc_rx_buffers(adapter); if (unlikely(!err)) /* no RX BUFFER allocated */ @@ -1993,6 +1750,11 @@ s32 atl1_up(struct atl1_adapter *adapter) atl1_check_link(adapter); return 0; + /* FIXME: unreachable code! -- CHS */ + /* free irq disable any interrupt */ + iowrite32(0, adapter->hw.hw_addr + REG_IMR); + free_irq(adapter->pdev->irq, netdev); + err_up: pci_disable_msi(adapter->pdev); /* free rx_buffers */ @@ -2019,8 +1781,174 @@ void atl1_down(struct atl1_adapter *adapter) netif_carrier_off(netdev); netif_stop_queue(netdev); - atl1_clean_tx_ring(adapter); - atl1_clean_rx_ring(adapter); + atl1_clean_tx_ring(adapter); + atl1_clean_rx_ring(adapter); +} + +/* + * atl1_change_mtu - Change the Maximum Transfer Unit + * @netdev: network interface device structure + * @new_mtu: new value for maximum frame size + * + * Returns 0 on success, negative on failure + */ +static int atl1_change_mtu(struct net_device *netdev, int new_mtu) +{ + struct atl1_adapter *adapter = netdev_priv(netdev); + int old_mtu = netdev->mtu; + int max_frame = new_mtu + ENET_HEADER_SIZE + ETHERNET_FCS_SIZE; + + if ((max_frame < MINIMUM_ETHERNET_FRAME_SIZE) || + (max_frame > MAX_JUMBO_FRAME_SIZE)) { + dev_warn(&adapter->pdev->dev, "invalid MTU setting\n"); + return -EINVAL; + } + + adapter->hw.max_frame_size = max_frame; + adapter->hw.tx_jumbo_task_th = (max_frame + 7) >> 3; + adapter->rx_buffer_len = (max_frame + 7) & ~7; + adapter->hw.rx_jumbo_th = adapter->rx_buffer_len / 8; + + netdev->mtu = new_mtu; + if ((old_mtu != new_mtu) && netif_running(netdev)) { + atl1_down(adapter); + atl1_up(adapter); + } + + return 0; +} + +/* + * atl1_set_mac - Change the Ethernet Address of the NIC + * @netdev: network interface device structure + * @p: pointer to an address structure + * + * Returns 0 on success, negative on failure + */ +static int atl1_set_mac(struct net_device *netdev, void *p) +{ + struct atl1_adapter *adapter = netdev_priv(netdev); + struct sockaddr *addr = p; + + if (netif_running(netdev)) + return -EBUSY; + + if (!is_valid_ether_addr(addr->sa_data)) + return -EADDRNOTAVAIL; + + memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len); + memcpy(adapter->hw.mac_addr, addr->sa_data, netdev->addr_len); + + atl1_set_mac_addr(&adapter->hw); + return 0; +} + +/* + * atl1_watchdog - Timer Call-back + * @data: pointer to netdev cast into an unsigned long + */ +static void atl1_watchdog(unsigned long data) +{ + struct atl1_adapter *adapter = (struct atl1_adapter *)data; + + /* Reset the timer */ + mod_timer(&adapter->watchdog_timer, jiffies + 2 * HZ); +} + +static int mdio_read(struct net_device *netdev, int phy_id, int reg_num) +{ + struct atl1_adapter *adapter = netdev_priv(netdev); + u16 result; + + atl1_read_phy_reg(&adapter->hw, reg_num & 0x1f, &result); + + return result; +} + +static void mdio_write(struct net_device *netdev, int phy_id, int reg_num, int val) +{ + struct atl1_adapter *adapter = netdev_priv(netdev); + + atl1_write_phy_reg(&adapter->hw, reg_num, val); +} + +/* + * atl1_mii_ioctl - + * @netdev: + * @ifreq: + * @cmd: + */ +static int atl1_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) +{ + struct atl1_adapter *adapter = netdev_priv(netdev); + unsigned long flags; + int retval; + + if (!netif_running(netdev)) + return -EINVAL; + + spin_lock_irqsave(&adapter->lock, flags); + retval = generic_mii_ioctl(&adapter->mii, if_mii(ifr), cmd, NULL); + spin_unlock_irqrestore(&adapter->lock, flags); + + return retval; +} + +/* + * atl1_ioctl - + * @netdev: + * @ifreq: + * @cmd: + */ +static int atl1_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) +{ + switch (cmd) { + case SIOCGMIIPHY: + case SIOCGMIIREG: + case SIOCSMIIREG: + return atl1_mii_ioctl(netdev, ifr, cmd); + default: + return -EOPNOTSUPP; + } +} + +/* + * atl1_tx_timeout - Respond to a Tx Hang + * @netdev: network interface device structure + */ +static void atl1_tx_timeout(struct net_device *netdev) +{ + struct atl1_adapter *adapter = netdev_priv(netdev); + /* Do the reset outside of interrupt context */ + schedule_work(&adapter->tx_timeout_task); +} + +/* + * atl1_phy_config - Timer Call-back + * @data: pointer to netdev cast into an unsigned long + */ +static void atl1_phy_config(unsigned long data) +{ + struct atl1_adapter *adapter = (struct atl1_adapter *)data; + struct atl1_hw *hw = &adapter->hw; + unsigned long flags; + + spin_lock_irqsave(&adapter->lock, flags); + adapter->phy_timer_pending = false; + atl1_write_phy_reg(hw, MII_ADVERTISE, hw->mii_autoneg_adv_reg); + atl1_write_phy_reg(hw, MII_AT001_CR, hw->mii_1000t_ctrl_reg); + atl1_write_phy_reg(hw, MII_BMCR, MII_CR_RESET | MII_CR_AUTO_NEG_EN); + spin_unlock_irqrestore(&adapter->lock, flags); +} + +int atl1_reset(struct atl1_adapter *adapter) +{ + int ret; + + ret = atl1_reset_hw(&adapter->hw); + if (ret != ATL1_SUCCESS) + return ret; + return atl1_init_hw(&adapter->hw); } /* @@ -2075,113 +2003,77 @@ static int atl1_close(struct net_device *netdev) return 0; } -#ifdef CONFIG_PM -static int atl1_suspend(struct pci_dev *pdev, pm_message_t state) +#ifdef CONFIG_NET_POLL_CONTROLLER +static void atl1_poll_controller(struct net_device *netdev) { - struct net_device *netdev = pci_get_drvdata(pdev); - struct atl1_adapter *adapter = netdev_priv(netdev); - struct atl1_hw *hw = &adapter->hw; - u32 ctrl = 0; - u32 wufc = adapter->wol; - - netif_device_detach(netdev); - if (netif_running(netdev)) - atl1_down(adapter); - - atl1_read_phy_reg(hw, MII_BMSR, (u16 *) & ctrl); - atl1_read_phy_reg(hw, MII_BMSR, (u16 *) & ctrl); - if (ctrl & BMSR_LSTATUS) - wufc &= ~ATL1_WUFC_LNKC; - - /* reduce speed to 10/100M */ - if (wufc) { - atl1_phy_enter_power_saving(hw); - /* if resume, let driver to re- setup link */ - hw->phy_configured = false; - atl1_set_mac_addr(hw); - atl1_set_multi(netdev); - - ctrl = 0; - /* turn on magic packet wol */ - if (wufc & ATL1_WUFC_MAG) - ctrl = WOL_MAGIC_EN | WOL_MAGIC_PME_EN; - - /* turn on Link change WOL */ - if (wufc & ATL1_WUFC_LNKC) - ctrl |= (WOL_LINK_CHG_EN | WOL_LINK_CHG_PME_EN); - iowrite32(ctrl, hw->hw_addr + REG_WOL_CTRL); - - /* turn on all-multi mode if wake on multicast is enabled */ - ctrl = ioread32(hw->hw_addr + REG_MAC_CTRL); - ctrl &= ~MAC_CTRL_DBG; - ctrl &= ~MAC_CTRL_PROMIS_EN; - if (wufc & ATL1_WUFC_MC) - ctrl |= MAC_CTRL_MC_ALL_EN; - else - ctrl &= ~MAC_CTRL_MC_ALL_EN; - - /* turn on broadcast mode if wake on-BC is enabled */ - if (wufc & ATL1_WUFC_BC) - ctrl |= MAC_CTRL_BC_EN; - else - ctrl &= ~MAC_CTRL_BC_EN; - - /* enable RX */ - ctrl |= MAC_CTRL_RX_EN; - iowrite32(ctrl, hw->hw_addr + REG_MAC_CTRL); - pci_enable_wake(pdev, PCI_D3hot, 1); - pci_enable_wake(pdev, PCI_D3cold, 1); - } else { - iowrite32(0, hw->hw_addr + REG_WOL_CTRL); - pci_enable_wake(pdev, PCI_D3hot, 0); - pci_enable_wake(pdev, PCI_D3cold, 0); - } - - pci_save_state(pdev); - pci_disable_device(pdev); - - pci_set_power_state(pdev, PCI_D3hot); - - return 0; + disable_irq(netdev->irq); + atl1_intr(netdev->irq, netdev); + enable_irq(netdev->irq); } +#endif -static int atl1_resume(struct pci_dev *pdev) +/* + * If TPD Buffer size equal to 0, PCIE DMAR_TO_INT + * will assert. We do soft reset <0x1400=1> according + * with the SPEC. BUT, it seemes that PCIE or DMA + * state-machine will not be reset. DMAR_TO_INT will + * assert again and again. + */ +static void atl1_tx_timeout_task(struct work_struct *work) { - struct net_device *netdev = pci_get_drvdata(pdev); - struct atl1_adapter *adapter = netdev_priv(netdev); - u32 ret_val; - - pci_set_power_state(pdev, 0); - pci_restore_state(pdev); - - ret_val = pci_enable_device(pdev); - pci_enable_wake(pdev, PCI_D3hot, 0); - pci_enable_wake(pdev, PCI_D3cold, 0); - - iowrite32(0, adapter->hw.hw_addr + REG_WOL_CTRL); - atl1_reset(adapter); + struct atl1_adapter *adapter = + container_of(work, struct atl1_adapter, tx_timeout_task); + struct net_device *netdev = adapter->netdev; - if (netif_running(netdev)) - atl1_up(adapter); + netif_device_detach(netdev); + atl1_down(adapter); + atl1_up(adapter); netif_device_attach(netdev); +} - atl1_via_workaround(adapter); +/* + * atl1_link_chg_task - deal with link change event Out of interrupt context + */ +static void atl1_link_chg_task(struct work_struct *work) +{ + struct atl1_adapter *adapter = + container_of(work, struct atl1_adapter, link_chg_task); + unsigned long flags; - return 0; + spin_lock_irqsave(&adapter->lock, flags); + atl1_check_link(adapter); + spin_unlock_irqrestore(&adapter->lock, flags); } -#else -#define atl1_suspend NULL -#define atl1_resume NULL -#endif -#ifdef CONFIG_NET_POLL_CONTROLLER -static void atl1_poll_controller(struct net_device *netdev) +/* + * atl1_pcie_patch - Patch for PCIE module + */ +static void atl1_pcie_patch(struct atl1_adapter *adapter) { - disable_irq(netdev->irq); - atl1_intr(netdev->irq, netdev); - enable_irq(netdev->irq); + u32 value; + value = 0x6500; + iowrite32(value, adapter->hw.hw_addr + 0x12FC); + /* pcie flow control mode change */ + value = ioread32(adapter->hw.hw_addr + 0x1008); + value |= 0x8000; + iowrite32(value, adapter->hw.hw_addr + 0x1008); +} + +/* + * When ACPI resume on some VIA MotherBoard, the Interrupt Disable bit/0x400 + * on PCI Command register is disable. + * The function enable this bit. + * Brackett, 2006/03/15 + */ +static void atl1_via_workaround(struct atl1_adapter *adapter) +{ + unsigned long value; + + value = ioread16(adapter->hw.hw_addr + PCI_COMMAND); + if (value & PCI_COMMAND_INTX_DISABLE) + value &= ~PCI_COMMAND_INTX_DISABLE; + iowrite32(value, adapter->hw.hw_addr + PCI_COMMAND); } -#endif /* * atl1_probe - Device Initialization Routine @@ -2195,7 +2087,7 @@ static void atl1_poll_controller(struct net_device *netdev) * and a hardware reset occur. */ static int __devinit atl1_probe(struct pci_dev *pdev, - const struct pci_device_id *ent) + const struct pci_device_id *ent) { struct net_device *netdev; struct atl1_adapter *adapter; @@ -2249,7 +2141,7 @@ static int __devinit atl1_probe(struct pci_dev *pdev, } /* get device revision number */ adapter->hw.dev_rev = ioread16(adapter->hw.hw_addr + - (REG_MASTER_CTRL + 2)); + (REG_MASTER_CTRL + 2)); dev_info(&pdev->dev, "version %s\n", DRIVER_VERSION); /* set default ring resource counts */ @@ -2402,8 +2294,7 @@ static void __devexit atl1_remove(struct pci_dev *pdev) * address, we need to save the permanent one. */ if (memcmp(adapter->hw.mac_addr, adapter->hw.perm_mac_addr, ETH_ALEN)) { - memcpy(adapter->hw.mac_addr, adapter->hw.perm_mac_addr, - ETH_ALEN); + memcpy(adapter->hw.mac_addr, adapter->hw.perm_mac_addr, ETH_ALEN); atl1_set_mac_addr(&adapter->hw); } @@ -2415,11 +2306,112 @@ static void __devexit atl1_remove(struct pci_dev *pdev) pci_disable_device(pdev); } +#ifdef CONFIG_PM +static int atl1_suspend(struct pci_dev *pdev, pm_message_t state) +{ + struct net_device *netdev = pci_get_drvdata(pdev); + struct atl1_adapter *adapter = netdev_priv(netdev); + struct atl1_hw *hw = &adapter->hw; + u32 ctrl = 0; + u32 wufc = adapter->wol; + + netif_device_detach(netdev); + if (netif_running(netdev)) + atl1_down(adapter); + + atl1_read_phy_reg(hw, MII_BMSR, (u16 *) & ctrl); + atl1_read_phy_reg(hw, MII_BMSR, (u16 *) & ctrl); + if (ctrl & BMSR_LSTATUS) + wufc &= ~ATL1_WUFC_LNKC; + + /* reduce speed to 10/100M */ + if (wufc) { + atl1_phy_enter_power_saving(hw); + /* if resume, let driver to re- setup link */ + hw->phy_configured = false; + atl1_set_mac_addr(hw); + atl1_set_multi(netdev); + + ctrl = 0; + /* turn on magic packet wol */ + if (wufc & ATL1_WUFC_MAG) + ctrl = WOL_MAGIC_EN | WOL_MAGIC_PME_EN; + + /* turn on Link change WOL */ + if (wufc & ATL1_WUFC_LNKC) + ctrl |= (WOL_LINK_CHG_EN | WOL_LINK_CHG_PME_EN); + iowrite32(ctrl, hw->hw_addr + REG_WOL_CTRL); + + /* turn on all-multi mode if wake on multicast is enabled */ + ctrl = ioread32(hw->hw_addr + REG_MAC_CTRL); + ctrl &= ~MAC_CTRL_DBG; + ctrl &= ~MAC_CTRL_PROMIS_EN; + if (wufc & ATL1_WUFC_MC) + ctrl |= MAC_CTRL_MC_ALL_EN; + else + ctrl &= ~MAC_CTRL_MC_ALL_EN; + + /* turn on broadcast mode if wake on-BC is enabled */ + if (wufc & ATL1_WUFC_BC) + ctrl |= MAC_CTRL_BC_EN; + else + ctrl &= ~MAC_CTRL_BC_EN; + + /* enable RX */ + ctrl |= MAC_CTRL_RX_EN; + iowrite32(ctrl, hw->hw_addr + REG_MAC_CTRL); + pci_enable_wake(pdev, PCI_D3hot, 1); + pci_enable_wake(pdev, PCI_D3cold, 1); /* 4 == D3 cold */ + } else { + iowrite32(0, hw->hw_addr + REG_WOL_CTRL); + pci_enable_wake(pdev, PCI_D3hot, 0); + pci_enable_wake(pdev, PCI_D3cold, 0); /* 4 == D3 cold */ + } + + pci_save_state(pdev); + pci_disable_device(pdev); + + pci_set_power_state(pdev, PCI_D3hot); + + return 0; +} + +static int atl1_resume(struct pci_dev *pdev) +{ + struct net_device *netdev = pci_get_drvdata(pdev); + struct atl1_adapter *adapter = netdev_priv(netdev); + u32 ret_val; + + pci_set_power_state(pdev, 0); + pci_restore_state(pdev); + + ret_val = pci_enable_device(pdev); + pci_enable_wake(pdev, PCI_D3hot, 0); + pci_enable_wake(pdev, PCI_D3cold, 0); + + iowrite32(0, adapter->hw.hw_addr + REG_WOL_CTRL); + atl1_reset(adapter); + + if (netif_running(netdev)) + atl1_up(adapter); + netif_device_attach(netdev); + + atl1_via_workaround(adapter); + + return 0; +} +#else +#define atl1_suspend NULL +#define atl1_resume NULL +#endif + static struct pci_driver atl1_driver = { .name = atl1_driver_name, .id_table = atl1_pci_tbl, .probe = atl1_probe, .remove = __devexit_p(atl1_remove), + /* Power Managment Hooks */ + /* probably broken right now -- CHS */ .suspend = atl1_suspend, .resume = atl1_resume }; diff --git a/trunk/drivers/net/ehea/ehea.h b/trunk/drivers/net/ehea/ehea.h index 6628fa622e2c..f03f070451de 100644 --- a/trunk/drivers/net/ehea/ehea.h +++ b/trunk/drivers/net/ehea/ehea.h @@ -39,13 +39,13 @@ #include #define DRV_NAME "ehea" -#define DRV_VERSION "EHEA_0070" +#define DRV_VERSION "EHEA_0067" -/* eHEA capability flags */ +/* EHEA capability flags */ #define DLPAR_PORT_ADD_REM 1 -#define DLPAR_MEM_ADD 2 -#define DLPAR_MEM_REM 4 -#define EHEA_CAPABILITIES (DLPAR_PORT_ADD_REM) +#define DLPAR_MEM_ADD 2 +#define DLPAR_MEM_REM 4 +#define EHEA_CAPABILITIES (DLPAR_PORT_ADD_REM) #define EHEA_MSG_DEFAULT (NETIF_MSG_LINK | NETIF_MSG_TIMER \ | NETIF_MSG_RX_ERR | NETIF_MSG_TX_ERR) @@ -113,8 +113,6 @@ /* Memory Regions */ #define EHEA_MR_ACC_CTRL 0x00800000 -#define EHEA_BUSMAP_START 0x8000000000000000ULL - #define EHEA_WATCH_DOG_TIMEOUT 10*HZ /* utility functions */ @@ -188,12 +186,6 @@ struct h_epas { set to 0 if unused */ }; -struct ehea_busmap { - unsigned int entries; /* total number of entries */ - unsigned int valid_sections; /* number of valid sections */ - u64 *vaddr; -}; - struct ehea_qp; struct ehea_cq; struct ehea_eq; @@ -390,8 +382,6 @@ struct ehea_adapter { struct ehea_mr mr; u32 pd; /* protection domain */ u64 max_mc_mac; /* max number of multicast mac addresses */ - int active_ports; - struct list_head list; }; @@ -441,9 +431,6 @@ struct port_res_cfg { int max_entries_rq3; }; -enum ehea_flag_bits { - __EHEA_STOP_XFER -}; void ehea_set_ethtool_ops(struct net_device *netdev); int ehea_sense_port_attr(struct ehea_port *port); diff --git a/trunk/drivers/net/ehea/ehea_main.c b/trunk/drivers/net/ehea/ehea_main.c index 1d1571cf322e..383144db4d18 100644 --- a/trunk/drivers/net/ehea/ehea_main.c +++ b/trunk/drivers/net/ehea/ehea_main.c @@ -79,11 +79,6 @@ MODULE_PARM_DESC(sq_entries, " Number of entries for the Send Queue " MODULE_PARM_DESC(use_mcs, " 0:NAPI, 1:Multiple receive queues, Default = 1 "); static int port_name_cnt = 0; -static LIST_HEAD(adapter_list); -u64 ehea_driver_flags = 0; -struct workqueue_struct *ehea_driver_wq; -struct work_struct ehea_rereg_mr_task; - static int __devinit ehea_probe_adapter(struct ibmebus_dev *dev, const struct of_device_id *id); @@ -243,17 +238,13 @@ static int ehea_refill_rq_def(struct ehea_port_res *pr, rwqe->wr_id = EHEA_BMASK_SET(EHEA_WR_ID_TYPE, wqe_type) | EHEA_BMASK_SET(EHEA_WR_ID_INDEX, index); rwqe->sg_list[0].l_key = pr->recv_mr.lkey; - rwqe->sg_list[0].vaddr = ehea_map_vaddr(skb->data); + rwqe->sg_list[0].vaddr = (u64)skb->data; rwqe->sg_list[0].len = packet_size; rwqe->data_segments = 1; index++; index &= max_index_mask; - - if (unlikely(test_bit(__EHEA_STOP_XFER, &ehea_driver_flags))) - goto out; } - q_skba->index = index; /* Ring doorbell */ @@ -262,7 +253,7 @@ static int ehea_refill_rq_def(struct ehea_port_res *pr, ehea_update_rq2a(pr->qp, i); else ehea_update_rq3a(pr->qp, i); -out: + return ret; } @@ -1330,7 +1321,7 @@ static void write_swqe2_TSO(struct sk_buff *skb, sg1entry->len = skb_data_size - headersize; tmp_addr = (u64)(skb->data + headersize); - sg1entry->vaddr = ehea_map_vaddr(tmp_addr); + sg1entry->vaddr = tmp_addr; swqe->descriptors++; } } else @@ -1361,7 +1352,7 @@ static void write_swqe2_nonTSO(struct sk_buff *skb, sg1entry->l_key = lkey; sg1entry->len = skb_data_size - SWQE2_MAX_IMM; tmp_addr = (u64)(skb->data + SWQE2_MAX_IMM); - sg1entry->vaddr = ehea_map_vaddr(tmp_addr); + sg1entry->vaddr = tmp_addr; swqe->descriptors++; } } else { @@ -1400,7 +1391,7 @@ static inline void write_swqe2_data(struct sk_buff *skb, struct net_device *dev, sg1entry->len = frag->size; tmp_addr = (u64)(page_address(frag->page) + frag->page_offset); - sg1entry->vaddr = ehea_map_vaddr(tmp_addr); + sg1entry->vaddr = tmp_addr; swqe->descriptors++; sg1entry_contains_frag_data = 1; } @@ -1415,7 +1406,7 @@ static inline void write_swqe2_data(struct sk_buff *skb, struct net_device *dev, tmp_addr = (u64)(page_address(frag->page) + frag->page_offset); - sgentry->vaddr = ehea_map_vaddr(tmp_addr); + sgentry->vaddr = tmp_addr; swqe->descriptors++; } } @@ -1887,9 +1878,6 @@ static int ehea_start_xmit(struct sk_buff *skb, struct net_device *dev) ehea_dump(swqe, 512, "swqe"); } - if (unlikely(test_bit(__EHEA_STOP_XFER, &ehea_driver_flags))) - goto out; - ehea_post_swqe(pr->qp, swqe); pr->tx_packets++; @@ -1904,7 +1892,7 @@ static int ehea_start_xmit(struct sk_buff *skb, struct net_device *dev) } dev->trans_start = jiffies; spin_unlock(&pr->xmit_lock); -out: + return NETDEV_TX_OK; } @@ -2232,9 +2220,6 @@ static int ehea_up(struct net_device *dev) out_clean_pr: ehea_clean_all_portres(port); out: - if (ret) - ehea_info("Failed starting %s. ret=%i", dev->name, ret); - return ret; } @@ -2274,13 +2259,8 @@ static int ehea_down(struct net_device *dev) msleep(1); ehea_broadcast_reg_helper(port, H_DEREG_BCMC); - port->state = EHEA_PORT_DOWN; - ret = ehea_clean_all_portres(port); - if (ret) - ehea_info("Failed freeing resources for %s. ret=%i", - dev->name, ret); - + port->state = EHEA_PORT_DOWN; return ret; } @@ -2312,11 +2292,15 @@ static void ehea_reset_port(struct work_struct *work) netif_stop_queue(dev); netif_poll_disable(dev); - ehea_down(dev); + ret = ehea_down(dev); + if (ret) + ehea_error("ehea_down failed. not all resources are freed"); ret = ehea_up(dev); - if (ret) + if (ret) { + ehea_error("Reset device %s failed: ret=%d", dev->name, ret); goto out; + } if (netif_msg_timer(port)) ehea_info("Device %s resetted successfully", dev->name); @@ -2328,88 +2312,6 @@ static void ehea_reset_port(struct work_struct *work) return; } -static void ehea_rereg_mrs(struct work_struct *work) -{ - int ret, i; - struct ehea_adapter *adapter; - - ehea_info("LPAR memory enlarged - re-initializing driver"); - - list_for_each_entry(adapter, &adapter_list, list) - if (adapter->active_ports) { - /* Shutdown all ports */ - for (i = 0; i < EHEA_MAX_PORTS; i++) { - struct ehea_port *port = adapter->port[i]; - - if (port) { - struct net_device *dev = port->netdev; - - if (dev->flags & IFF_UP) { - ehea_info("stopping %s", - dev->name); - down(&port->port_lock); - netif_stop_queue(dev); - netif_poll_disable(dev); - ehea_down(dev); - up(&port->port_lock); - } - } - } - - /* Unregister old memory region */ - ret = ehea_rem_mr(&adapter->mr); - if (ret) { - ehea_error("unregister MR failed - driver" - " inoperable!"); - goto out; - } - } - - ehea_destroy_busmap(); - - ret = ehea_create_busmap(); - if (ret) - goto out; - - clear_bit(__EHEA_STOP_XFER, &ehea_driver_flags); - - list_for_each_entry(adapter, &adapter_list, list) - if (adapter->active_ports) { - /* Register new memory region */ - ret = ehea_reg_kernel_mr(adapter, &adapter->mr); - if (ret) { - ehea_error("register MR failed - driver" - " inoperable!"); - goto out; - } - - /* Restart all ports */ - for (i = 0; i < EHEA_MAX_PORTS; i++) { - struct ehea_port *port = adapter->port[i]; - - if (port) { - struct net_device *dev = port->netdev; - - if (dev->flags & IFF_UP) { - ehea_info("restarting %s", - dev->name); - down(&port->port_lock); - - ret = ehea_up(dev); - if (!ret) { - netif_poll_enable(dev); - netif_wake_queue(dev); - } - - up(&port->port_lock); - } - } - } - } -out: - return; -} - static void ehea_tx_watchdog(struct net_device *dev) { struct ehea_port *port = netdev_priv(dev); @@ -2671,8 +2573,6 @@ struct ehea_port *ehea_setup_single_port(struct ehea_adapter *adapter, ehea_info("%s: Jumbo frames are %sabled", dev->name, jumbo == 1 ? "en" : "dis"); - adapter->active_ports++; - return port; out_unreg_port: @@ -2696,7 +2596,6 @@ static void ehea_shutdown_single_port(struct ehea_port *port) ehea_unregister_port(port); kfree(port->mc_list); free_netdev(port->netdev); - port->adapter->active_ports--; } static int ehea_setup_ports(struct ehea_adapter *adapter) @@ -2889,8 +2788,6 @@ static int __devinit ehea_probe_adapter(struct ibmebus_dev *dev, goto out; } - list_add(&adapter->list, &adapter_list); - adapter->ebus_dev = dev; adapter_handle = of_get_property(dev->ofdev.node, "ibm,hea-handle", @@ -2994,10 +2891,7 @@ static int __devexit ehea_remove(struct ibmebus_dev *dev) ehea_destroy_eq(adapter->neq); ehea_remove_adapter_mr(adapter); - list_del(&adapter->list); - kfree(adapter); - return 0; } @@ -3045,18 +2939,9 @@ int __init ehea_module_init(void) printk(KERN_INFO "IBM eHEA ethernet device driver (Release %s)\n", DRV_VERSION); - ehea_driver_wq = create_workqueue("ehea_driver_wq"); - - INIT_WORK(&ehea_rereg_mr_task, ehea_rereg_mrs); - ret = check_module_parm(); if (ret) goto out; - - ret = ehea_create_busmap(); - if (ret) - goto out; - ret = ibmebus_register_driver(&ehea_driver); if (ret) { ehea_error("failed registering eHEA device driver on ebus"); @@ -3080,7 +2965,6 @@ static void __exit ehea_module_exit(void) { driver_remove_file(&ehea_driver.driver, &driver_attr_capabilities); ibmebus_unregister_driver(&ehea_driver); - ehea_destroy_busmap(); } module_init(ehea_module_init); diff --git a/trunk/drivers/net/ehea/ehea_phyp.h b/trunk/drivers/net/ehea/ehea_phyp.h index 89b63531ff26..d17a45a7e717 100644 --- a/trunk/drivers/net/ehea/ehea_phyp.h +++ b/trunk/drivers/net/ehea/ehea_phyp.h @@ -60,9 +60,6 @@ static inline u32 get_longbusy_msecs(int long_busy_ret_code) } } -/* Number of pages which can be registered at once by H_REGISTER_HEA_RPAGES */ -#define EHEA_MAX_RPAGE 512 - /* Notification Event Queue (NEQ) Entry bit masks */ #define NEQE_EVENT_CODE EHEA_BMASK_IBM(2, 7) #define NEQE_PORTNUM EHEA_BMASK_IBM(32, 47) diff --git a/trunk/drivers/net/ehea/ehea_qmr.c b/trunk/drivers/net/ehea/ehea_qmr.c index a36fa6c23fdf..29eaa46948b0 100644 --- a/trunk/drivers/net/ehea/ehea_qmr.c +++ b/trunk/drivers/net/ehea/ehea_qmr.c @@ -31,13 +31,6 @@ #include "ehea_phyp.h" #include "ehea_qmr.h" - -struct ehea_busmap ehea_bmap = { 0, 0, NULL }; -extern u64 ehea_driver_flags; -extern struct workqueue_struct *ehea_driver_wq; -extern struct work_struct ehea_rereg_mr_task; - - static void *hw_qpageit_get_inc(struct hw_queue *queue) { void *retvalue = hw_qeit_get(queue); @@ -554,84 +547,18 @@ int ehea_destroy_qp(struct ehea_qp *qp) return 0; } -int ehea_create_busmap( void ) -{ - u64 vaddr = EHEA_BUSMAP_START; - unsigned long abs_max_pfn = 0; - unsigned long sec_max_pfn; - int i; - - /* - * Sections are not in ascending order -> Loop over all sections and - * find the highest PFN to compute the required map size. - */ - ehea_bmap.valid_sections = 0; - - for (i = 0; i < NR_MEM_SECTIONS; i++) - if (valid_section_nr(i)) { - sec_max_pfn = section_nr_to_pfn(i); - if (sec_max_pfn > abs_max_pfn) - abs_max_pfn = sec_max_pfn; - ehea_bmap.valid_sections++; - } - - ehea_bmap.entries = abs_max_pfn / EHEA_PAGES_PER_SECTION + 1; - ehea_bmap.vaddr = vmalloc(ehea_bmap.entries * sizeof(*ehea_bmap.vaddr)); - - if (!ehea_bmap.vaddr) - return -ENOMEM; - - for (i = 0 ; i < ehea_bmap.entries; i++) { - unsigned long pfn = section_nr_to_pfn(i); - - if (pfn_valid(pfn)) { - ehea_bmap.vaddr[i] = vaddr; - vaddr += EHEA_SECTSIZE; - } else - ehea_bmap.vaddr[i] = 0; - } - - return 0; -} - -void ehea_destroy_busmap( void ) -{ - vfree(ehea_bmap.vaddr); -} - -u64 ehea_map_vaddr(void *caddr) -{ - u64 mapped_addr; - unsigned long index = __pa(caddr) >> SECTION_SIZE_BITS; - - if (likely(index < ehea_bmap.entries)) { - mapped_addr = ehea_bmap.vaddr[index]; - if (likely(mapped_addr)) - mapped_addr |= (((unsigned long)caddr) - & (EHEA_SECTSIZE - 1)); - else - mapped_addr = -1; - } else - mapped_addr = -1; - - if (unlikely(mapped_addr == -1)) - if (!test_and_set_bit(__EHEA_STOP_XFER, &ehea_driver_flags)) - queue_work(ehea_driver_wq, &ehea_rereg_mr_task); - - return mapped_addr; -} - int ehea_reg_kernel_mr(struct ehea_adapter *adapter, struct ehea_mr *mr) { - int ret; - u64 *pt; - void *pg; - u64 hret, pt_abs, i, j, m, mr_len; + int i, k, ret; + u64 hret, pt_abs, start, end, nr_pages; u32 acc_ctrl = EHEA_MR_ACC_CTRL; + u64 *pt; - mr_len = ehea_bmap.valid_sections * EHEA_SECTSIZE; + start = KERNELBASE; + end = (u64)high_memory; + nr_pages = (end - start) / EHEA_PAGESIZE; - pt = kzalloc(EHEA_MAX_RPAGE * sizeof(u64), GFP_KERNEL); + pt = kzalloc(PAGE_SIZE, GFP_KERNEL); if (!pt) { ehea_error("no mem"); ret = -ENOMEM; @@ -639,8 +566,7 @@ int ehea_reg_kernel_mr(struct ehea_adapter *adapter, struct ehea_mr *mr) } pt_abs = virt_to_abs(pt); - hret = ehea_h_alloc_resource_mr(adapter->handle, - EHEA_BUSMAP_START, mr_len, + hret = ehea_h_alloc_resource_mr(adapter->handle, start, end - start, acc_ctrl, adapter->pd, &mr->handle, &mr->lkey); if (hret != H_SUCCESS) { @@ -649,43 +575,49 @@ int ehea_reg_kernel_mr(struct ehea_adapter *adapter, struct ehea_mr *mr) goto out; } - for (i = 0 ; i < ehea_bmap.entries; i++) - if (ehea_bmap.vaddr[i]) { - void *sectbase = __va(i << SECTION_SIZE_BITS); - unsigned long k = 0; - - for (j = 0; j < (PAGES_PER_SECTION / EHEA_MAX_RPAGE); - j++) { - - for (m = 0; m < EHEA_MAX_RPAGE; m++) { - pg = sectbase + ((k++) * EHEA_PAGESIZE); - pt[m] = virt_to_abs(pg); - } - - hret = ehea_h_register_rpage_mr(adapter->handle, - mr->handle, - 0, 0, pt_abs, - EHEA_MAX_RPAGE); - if ((hret != H_SUCCESS) - && (hret != H_PAGE_REGISTERED)) { - ehea_h_free_resource(adapter->handle, - mr->handle, - FORCE_FREE); - ehea_error("register_rpage_mr failed"); - ret = -EIO; - goto out; - } - } + mr->vaddr = KERNELBASE; + k = 0; + + while (nr_pages > 0) { + if (nr_pages > 1) { + u64 num_pages = min(nr_pages, (u64)512); + for (i = 0; i < num_pages; i++) + pt[i] = virt_to_abs((void*)(((u64)start) + + ((k++) * + EHEA_PAGESIZE))); + + hret = ehea_h_register_rpage_mr(adapter->handle, + mr->handle, 0, + 0, (u64)pt_abs, + num_pages); + nr_pages -= num_pages; + } else { + u64 abs_adr = virt_to_abs((void*)(((u64)start) + + (k * EHEA_PAGESIZE))); + + hret = ehea_h_register_rpage_mr(adapter->handle, + mr->handle, 0, + 0, abs_adr,1); + nr_pages--; + } + + if ((hret != H_SUCCESS) && (hret != H_PAGE_REGISTERED)) { + ehea_h_free_resource(adapter->handle, + mr->handle, FORCE_FREE); + ehea_error("register_rpage_mr failed"); + ret = -EIO; + goto out; } + } if (hret != H_SUCCESS) { - ehea_h_free_resource(adapter->handle, mr->handle, FORCE_FREE); - ehea_error("registering mr failed"); + ehea_h_free_resource(adapter->handle, mr->handle, + FORCE_FREE); + ehea_error("register_rpage failed for last page"); ret = -EIO; goto out; } - mr->vaddr = EHEA_BUSMAP_START; mr->adapter = adapter; ret = 0; out: diff --git a/trunk/drivers/net/ehea/ehea_qmr.h b/trunk/drivers/net/ehea/ehea_qmr.h index b71f8452a5e3..c0eb3e03a102 100644 --- a/trunk/drivers/net/ehea/ehea_qmr.h +++ b/trunk/drivers/net/ehea/ehea_qmr.h @@ -36,14 +36,8 @@ * page size of ehea hardware queues */ -#define EHEA_PAGESHIFT 12 -#define EHEA_PAGESIZE (1UL << EHEA_PAGESHIFT) -#define EHEA_SECTSIZE (1UL << 24) -#define EHEA_PAGES_PER_SECTION (EHEA_SECTSIZE >> PAGE_SHIFT) - -#if (1UL << SECTION_SIZE_BITS) < EHEA_SECTSIZE -#error eHEA module can't work if kernel sectionsize < ehea sectionsize -#endif +#define EHEA_PAGESHIFT 12 +#define EHEA_PAGESIZE 4096UL /* Some abbreviations used here: * @@ -378,8 +372,4 @@ int ehea_rem_mr(struct ehea_mr *mr); void ehea_error_data(struct ehea_adapter *adapter, u64 res_handle); -int ehea_create_busmap( void ); -void ehea_destroy_busmap( void ); -u64 ehea_map_vaddr(void *caddr); - #endif /* __EHEA_QMR_H__ */ diff --git a/trunk/drivers/net/forcedeth.c b/trunk/drivers/net/forcedeth.c index 136827f8dc2e..67046e8c21eb 100644 --- a/trunk/drivers/net/forcedeth.c +++ b/trunk/drivers/net/forcedeth.c @@ -550,8 +550,6 @@ union ring_type { /* PHY defines */ #define PHY_OUI_MARVELL 0x5043 #define PHY_OUI_CICADA 0x03f1 -#define PHY_OUI_VITESSE 0x01c1 -#define PHY_OUI_REALTEK 0x01c1 #define PHYID1_OUI_MASK 0x03ff #define PHYID1_OUI_SHFT 6 #define PHYID2_OUI_MASK 0xfc00 @@ -559,36 +557,12 @@ union ring_type { #define PHYID2_MODEL_MASK 0x03f0 #define PHY_MODEL_MARVELL_E3016 0x220 #define PHY_MARVELL_E3016_INITMASK 0x0300 -#define PHY_CICADA_INIT1 0x0f000 -#define PHY_CICADA_INIT2 0x0e00 -#define PHY_CICADA_INIT3 0x01000 -#define PHY_CICADA_INIT4 0x0200 -#define PHY_CICADA_INIT5 0x0004 -#define PHY_CICADA_INIT6 0x02000 -#define PHY_VITESSE_INIT_REG1 0x1f -#define PHY_VITESSE_INIT_REG2 0x10 -#define PHY_VITESSE_INIT_REG3 0x11 -#define PHY_VITESSE_INIT_REG4 0x12 -#define PHY_VITESSE_INIT_MSK1 0xc -#define PHY_VITESSE_INIT_MSK2 0x0180 -#define PHY_VITESSE_INIT1 0x52b5 -#define PHY_VITESSE_INIT2 0xaf8a -#define PHY_VITESSE_INIT3 0x8 -#define PHY_VITESSE_INIT4 0x8f8a -#define PHY_VITESSE_INIT5 0xaf86 -#define PHY_VITESSE_INIT6 0x8f86 -#define PHY_VITESSE_INIT7 0xaf82 -#define PHY_VITESSE_INIT8 0x0100 -#define PHY_VITESSE_INIT9 0x8f82 -#define PHY_VITESSE_INIT10 0x0 -#define PHY_REALTEK_INIT_REG1 0x1f -#define PHY_REALTEK_INIT_REG2 0x19 -#define PHY_REALTEK_INIT_REG3 0x13 -#define PHY_REALTEK_INIT1 0x0000 -#define PHY_REALTEK_INIT2 0x8e00 -#define PHY_REALTEK_INIT3 0x0001 -#define PHY_REALTEK_INIT4 0xad17 - +#define PHY_INIT1 0x0f000 +#define PHY_INIT2 0x0e00 +#define PHY_INIT3 0x01000 +#define PHY_INIT4 0x0200 +#define PHY_INIT5 0x0004 +#define PHY_INIT6 0x02000 #define PHY_GIGABIT 0x0100 #define PHY_TIMEOUT 0x1 @@ -1122,28 +1096,6 @@ static int phy_init(struct net_device *dev) return PHY_ERROR; } } - if (np->phy_oui == PHY_OUI_REALTEK) { - if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT1)) { - printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev)); - return PHY_ERROR; - } - if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG2, PHY_REALTEK_INIT2)) { - printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev)); - return PHY_ERROR; - } - if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT3)) { - printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev)); - return PHY_ERROR; - } - if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG3, PHY_REALTEK_INIT4)) { - printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev)); - return PHY_ERROR; - } - if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT1)) { - printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev)); - return PHY_ERROR; - } - } /* set advertise register */ reg = mii_rw(dev, np->phyaddr, MII_ADVERTISE, MII_READ); @@ -1189,14 +1141,14 @@ static int phy_init(struct net_device *dev) /* phy vendor specific configuration */ if ((np->phy_oui == PHY_OUI_CICADA) && (phyinterface & PHY_RGMII) ) { phy_reserved = mii_rw(dev, np->phyaddr, MII_RESV1, MII_READ); - phy_reserved &= ~(PHY_CICADA_INIT1 | PHY_CICADA_INIT2); - phy_reserved |= (PHY_CICADA_INIT3 | PHY_CICADA_INIT4); + phy_reserved &= ~(PHY_INIT1 | PHY_INIT2); + phy_reserved |= (PHY_INIT3 | PHY_INIT4); if (mii_rw(dev, np->phyaddr, MII_RESV1, phy_reserved)) { printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev)); return PHY_ERROR; } phy_reserved = mii_rw(dev, np->phyaddr, MII_NCONFIG, MII_READ); - phy_reserved |= PHY_CICADA_INIT5; + phy_reserved |= PHY_INIT5; if (mii_rw(dev, np->phyaddr, MII_NCONFIG, phy_reserved)) { printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev)); return PHY_ERROR; @@ -1204,106 +1156,12 @@ static int phy_init(struct net_device *dev) } if (np->phy_oui == PHY_OUI_CICADA) { phy_reserved = mii_rw(dev, np->phyaddr, MII_SREVISION, MII_READ); - phy_reserved |= PHY_CICADA_INIT6; + phy_reserved |= PHY_INIT6; if (mii_rw(dev, np->phyaddr, MII_SREVISION, phy_reserved)) { printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev)); return PHY_ERROR; } } - if (np->phy_oui == PHY_OUI_VITESSE) { - if (mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG1, PHY_VITESSE_INIT1)) { - printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev)); - return PHY_ERROR; - } - if (mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG2, PHY_VITESSE_INIT2)) { - printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev)); - return PHY_ERROR; - } - phy_reserved = mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG4, MII_READ); - if (mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG4, phy_reserved)) { - printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev)); - return PHY_ERROR; - } - phy_reserved = mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG3, MII_READ); - phy_reserved &= ~PHY_VITESSE_INIT_MSK1; - phy_reserved |= PHY_VITESSE_INIT3; - if (mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG3, phy_reserved)) { - printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev)); - return PHY_ERROR; - } - if (mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG2, PHY_VITESSE_INIT4)) { - printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev)); - return PHY_ERROR; - } - if (mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG2, PHY_VITESSE_INIT5)) { - printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev)); - return PHY_ERROR; - } - phy_reserved = mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG4, MII_READ); - phy_reserved &= ~PHY_VITESSE_INIT_MSK1; - phy_reserved |= PHY_VITESSE_INIT3; - if (mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG4, phy_reserved)) { - printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev)); - return PHY_ERROR; - } - phy_reserved = mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG3, MII_READ); - if (mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG3, phy_reserved)) { - printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev)); - return PHY_ERROR; - } - if (mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG2, PHY_VITESSE_INIT6)) { - printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev)); - return PHY_ERROR; - } - if (mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG2, PHY_VITESSE_INIT7)) { - printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev)); - return PHY_ERROR; - } - phy_reserved = mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG4, MII_READ); - if (mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG4, phy_reserved)) { - printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev)); - return PHY_ERROR; - } - phy_reserved = mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG3, MII_READ); - phy_reserved &= ~PHY_VITESSE_INIT_MSK2; - phy_reserved |= PHY_VITESSE_INIT8; - if (mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG3, phy_reserved)) { - printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev)); - return PHY_ERROR; - } - if (mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG2, PHY_VITESSE_INIT9)) { - printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev)); - return PHY_ERROR; - } - if (mii_rw(dev, np->phyaddr, PHY_VITESSE_INIT_REG1, PHY_VITESSE_INIT10)) { - printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev)); - return PHY_ERROR; - } - } - if (np->phy_oui == PHY_OUI_REALTEK) { - /* reset could have cleared these out, set them back */ - if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT1)) { - printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev)); - return PHY_ERROR; - } - if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG2, PHY_REALTEK_INIT2)) { - printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev)); - return PHY_ERROR; - } - if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT3)) { - printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev)); - return PHY_ERROR; - } - if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG3, PHY_REALTEK_INIT4)) { - printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev)); - return PHY_ERROR; - } - if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT1)) { - printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev)); - return PHY_ERROR; - } - } - /* some phys clear out pause advertisment on reset, set it back */ mii_rw(dev, np->phyaddr, MII_ADVERTISE, reg); diff --git a/trunk/drivers/net/gianfar_mii.c b/trunk/drivers/net/gianfar_mii.c index ac3596f45dd8..5dd34a1a7b89 100644 --- a/trunk/drivers/net/gianfar_mii.c +++ b/trunk/drivers/net/gianfar_mii.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include diff --git a/trunk/drivers/net/macb.c b/trunk/drivers/net/macb.c index a4bb0264180a..0e04f7ac3f2e 100644 --- a/trunk/drivers/net/macb.c +++ b/trunk/drivers/net/macb.c @@ -17,12 +17,13 @@ #include #include #include +#include +#include #include +#include #include -#include #include -#include #include "macb.h" @@ -84,202 +85,172 @@ static void __init macb_get_hwaddr(struct macb *bp) memcpy(bp->dev->dev_addr, addr, sizeof(addr)); } -static int macb_mdio_read(struct mii_bus *bus, int mii_id, int regnum) +static void macb_enable_mdio(struct macb *bp) { - struct macb *bp = bus->priv; + unsigned long flags; + u32 reg; + + spin_lock_irqsave(&bp->lock, flags); + reg = macb_readl(bp, NCR); + reg |= MACB_BIT(MPE); + macb_writel(bp, NCR, reg); + macb_writel(bp, IER, MACB_BIT(MFD)); + spin_unlock_irqrestore(&bp->lock, flags); +} + +static void macb_disable_mdio(struct macb *bp) +{ + unsigned long flags; + u32 reg; + + spin_lock_irqsave(&bp->lock, flags); + reg = macb_readl(bp, NCR); + reg &= ~MACB_BIT(MPE); + macb_writel(bp, NCR, reg); + macb_writel(bp, IDR, MACB_BIT(MFD)); + spin_unlock_irqrestore(&bp->lock, flags); +} + +static int macb_mdio_read(struct net_device *dev, int phy_id, int location) +{ + struct macb *bp = netdev_priv(dev); int value; + mutex_lock(&bp->mdio_mutex); + + macb_enable_mdio(bp); macb_writel(bp, MAN, (MACB_BF(SOF, MACB_MAN_SOF) | MACB_BF(RW, MACB_MAN_READ) - | MACB_BF(PHYA, mii_id) - | MACB_BF(REGA, regnum) + | MACB_BF(PHYA, phy_id) + | MACB_BF(REGA, location) | MACB_BF(CODE, MACB_MAN_CODE))); - /* wait for end of transfer */ - while (!MACB_BFEXT(IDLE, macb_readl(bp, NSR))) - cpu_relax(); + wait_for_completion(&bp->mdio_complete); value = MACB_BFEXT(DATA, macb_readl(bp, MAN)); + macb_disable_mdio(bp); + mutex_unlock(&bp->mdio_mutex); return value; } -static int macb_mdio_write(struct mii_bus *bus, int mii_id, int regnum, - u16 value) +static void macb_mdio_write(struct net_device *dev, int phy_id, + int location, int val) { - struct macb *bp = bus->priv; + struct macb *bp = netdev_priv(dev); + + dev_dbg(&bp->pdev->dev, "mdio_write %02x:%02x <- %04x\n", + phy_id, location, val); + + mutex_lock(&bp->mdio_mutex); + macb_enable_mdio(bp); macb_writel(bp, MAN, (MACB_BF(SOF, MACB_MAN_SOF) | MACB_BF(RW, MACB_MAN_WRITE) - | MACB_BF(PHYA, mii_id) - | MACB_BF(REGA, regnum) + | MACB_BF(PHYA, phy_id) + | MACB_BF(REGA, location) | MACB_BF(CODE, MACB_MAN_CODE) - | MACB_BF(DATA, value))); + | MACB_BF(DATA, val))); - /* wait for end of transfer */ - while (!MACB_BFEXT(IDLE, macb_readl(bp, NSR))) - cpu_relax(); + wait_for_completion(&bp->mdio_complete); - return 0; + macb_disable_mdio(bp); + mutex_unlock(&bp->mdio_mutex); } -static int macb_mdio_reset(struct mii_bus *bus) +static int macb_phy_probe(struct macb *bp) { - return 0; -} - -static void macb_handle_link_change(struct net_device *dev) -{ - struct macb *bp = netdev_priv(dev); - struct phy_device *phydev = bp->phy_dev; - unsigned long flags; - - int status_change = 0; - - spin_lock_irqsave(&bp->lock, flags); - - if (phydev->link) { - if ((bp->speed != phydev->speed) || - (bp->duplex != phydev->duplex)) { - u32 reg; - - reg = macb_readl(bp, NCFGR); - reg &= ~(MACB_BIT(SPD) | MACB_BIT(FD)); + int phy_address; + u16 phyid1, phyid2; - if (phydev->duplex) - reg |= MACB_BIT(FD); - if (phydev->speed) - reg |= MACB_BIT(SPD); + for (phy_address = 0; phy_address < 32; phy_address++) { + phyid1 = macb_mdio_read(bp->dev, phy_address, MII_PHYSID1); + phyid2 = macb_mdio_read(bp->dev, phy_address, MII_PHYSID2); - macb_writel(bp, NCFGR, reg); - - bp->speed = phydev->speed; - bp->duplex = phydev->duplex; - status_change = 1; - } + if (phyid1 != 0xffff && phyid1 != 0x0000 + && phyid2 != 0xffff && phyid2 != 0x0000) + break; } - if (phydev->link != bp->link) { - if (phydev->link) - netif_schedule(dev); - else { - bp->speed = 0; - bp->duplex = -1; - } - bp->link = phydev->link; - - status_change = 1; - } + if (phy_address == 32) + return -ENODEV; - spin_unlock_irqrestore(&bp->lock, flags); + dev_info(&bp->pdev->dev, + "detected PHY at address %d (ID %04x:%04x)\n", + phy_address, phyid1, phyid2); - if (status_change) { - if (phydev->link) - printk(KERN_INFO "%s: link up (%d/%s)\n", - dev->name, phydev->speed, - DUPLEX_FULL == phydev->duplex ? "Full":"Half"); - else - printk(KERN_INFO "%s: link down\n", dev->name); - } + bp->mii.phy_id = phy_address; + return 0; } -/* based on au1000_eth. c*/ -static int macb_mii_probe(struct net_device *dev) +static void macb_set_media(struct macb *bp, int media) { - struct macb *bp = netdev_priv(dev); - struct phy_device *phydev = NULL; - struct eth_platform_data *pdata; - int phy_addr; - - /* find the first phy */ - for (phy_addr = 0; phy_addr < PHY_MAX_ADDR; phy_addr++) { - if (bp->mii_bus.phy_map[phy_addr]) { - phydev = bp->mii_bus.phy_map[phy_addr]; - break; - } - } + u32 reg; - if (!phydev) { - printk (KERN_ERR "%s: no PHY found\n", dev->name); - return -1; - } - - pdata = bp->pdev->dev.platform_data; - /* TODO : add pin_irq */ - - /* attach the mac to the phy */ - if (pdata && pdata->is_rmii) { - phydev = phy_connect(dev, phydev->dev.bus_id, - &macb_handle_link_change, 0, PHY_INTERFACE_MODE_RMII); - } else { - phydev = phy_connect(dev, phydev->dev.bus_id, - &macb_handle_link_change, 0, PHY_INTERFACE_MODE_MII); - } - - if (IS_ERR(phydev)) { - printk(KERN_ERR "%s: Could not attach to PHY\n", dev->name); - return PTR_ERR(phydev); - } - - /* mask with MAC supported features */ - phydev->supported &= PHY_BASIC_FEATURES; - - phydev->advertising = phydev->supported; - - bp->link = 0; - bp->speed = 0; - bp->duplex = -1; - bp->phy_dev = phydev; - - return 0; + spin_lock_irq(&bp->lock); + reg = macb_readl(bp, NCFGR); + reg &= ~(MACB_BIT(SPD) | MACB_BIT(FD)); + if (media & (ADVERTISE_100HALF | ADVERTISE_100FULL)) + reg |= MACB_BIT(SPD); + if (media & ADVERTISE_FULL) + reg |= MACB_BIT(FD); + macb_writel(bp, NCFGR, reg); + spin_unlock_irq(&bp->lock); } -static int macb_mii_init(struct macb *bp) +static void macb_check_media(struct macb *bp, int ok_to_print, int init_media) { - struct eth_platform_data *pdata; - int err = -ENXIO, i; + struct mii_if_info *mii = &bp->mii; + unsigned int old_carrier, new_carrier; + int advertise, lpa, media, duplex; - /* Enable managment port */ - macb_writel(bp, NCR, MACB_BIT(MPE)); + /* if forced media, go no further */ + if (mii->force_media) + return; - bp->mii_bus.name = "MACB_mii_bus", - bp->mii_bus.read = &macb_mdio_read, - bp->mii_bus.write = &macb_mdio_write, - bp->mii_bus.reset = &macb_mdio_reset, - bp->mii_bus.id = bp->pdev->id, - bp->mii_bus.priv = bp, - bp->mii_bus.dev = &bp->dev->dev; - pdata = bp->pdev->dev.platform_data; + /* check current and old link status */ + old_carrier = netif_carrier_ok(mii->dev) ? 1 : 0; + new_carrier = (unsigned int) mii_link_ok(mii); - if (pdata) - bp->mii_bus.phy_mask = pdata->phy_mask; + /* if carrier state did not change, assume nothing else did */ + if (!init_media && old_carrier == new_carrier) + return; - bp->mii_bus.irq = kmalloc(sizeof(int)*PHY_MAX_ADDR, GFP_KERNEL); - if (!bp->mii_bus.irq) { - err = -ENOMEM; - goto err_out; + /* no carrier, nothing much to do */ + if (!new_carrier) { + netif_carrier_off(mii->dev); + printk(KERN_INFO "%s: link down\n", mii->dev->name); + return; } - for (i = 0; i < PHY_MAX_ADDR; i++) - bp->mii_bus.irq[i] = PHY_POLL; + /* + * we have carrier, see who's on the other end + */ + netif_carrier_on(mii->dev); - platform_set_drvdata(bp->dev, &bp->mii_bus); + /* get MII advertise and LPA values */ + if (!init_media && mii->advertising) { + advertise = mii->advertising; + } else { + advertise = mii->mdio_read(mii->dev, mii->phy_id, MII_ADVERTISE); + mii->advertising = advertise; + } + lpa = mii->mdio_read(mii->dev, mii->phy_id, MII_LPA); - if (mdiobus_register(&bp->mii_bus)) - goto err_out_free_mdio_irq; + /* figure out media and duplex from advertise and LPA values */ + media = mii_nway_result(lpa & advertise); + duplex = (media & ADVERTISE_FULL) ? 1 : 0; - if (macb_mii_probe(bp->dev) != 0) { - goto err_out_unregister_bus; - } + if (ok_to_print) + printk(KERN_INFO "%s: link up, %sMbps, %s-duplex, lpa 0x%04X\n", + mii->dev->name, + media & (ADVERTISE_100FULL | ADVERTISE_100HALF) ? "100" : "10", + duplex ? "full" : "half", lpa); - return 0; + mii->full_duplex = duplex; -err_out_unregister_bus: - mdiobus_unregister(&bp->mii_bus); -err_out_free_mdio_irq: - kfree(bp->mii_bus.irq); -err_out: - return err; + /* Let the MAC know about the new link state */ + macb_set_media(bp, media); } static void macb_update_stats(struct macb *bp) @@ -294,6 +265,16 @@ static void macb_update_stats(struct macb *bp) *p += __raw_readl(reg); } +static void macb_periodic_task(struct work_struct *work) +{ + struct macb *bp = container_of(work, struct macb, periodic_task.work); + + macb_update_stats(bp); + macb_check_media(bp, 1, 0); + + schedule_delayed_work(&bp->periodic_task, HZ); +} + static void macb_tx(struct macb *bp) { unsigned int tail; @@ -538,6 +519,9 @@ static irqreturn_t macb_interrupt(int irq, void *dev_id) spin_lock(&bp->lock); while (status) { + if (status & MACB_BIT(MFD)) + complete(&bp->mdio_complete); + /* close possible race with dev_close */ if (unlikely(!netif_running(dev))) { macb_writel(bp, IDR, ~0UL); @@ -551,8 +535,7 @@ static irqreturn_t macb_interrupt(int irq, void *dev_id) * until we have processed the buffers */ macb_writel(bp, IDR, MACB_RX_INT_FLAGS); - dev_dbg(&bp->pdev->dev, - "scheduling RX softirq\n"); + dev_dbg(&bp->pdev->dev, "scheduling RX softirq\n"); __netif_rx_schedule(dev); } } @@ -782,7 +765,7 @@ static void macb_init_hw(struct macb *bp) macb_writel(bp, TBQP, bp->tx_ring_dma); /* Enable TX and RX */ - macb_writel(bp, NCR, MACB_BIT(RE) | MACB_BIT(TE) | MACB_BIT(MPE)); + macb_writel(bp, NCR, MACB_BIT(RE) | MACB_BIT(TE)); /* Enable interrupts */ macb_writel(bp, IER, (MACB_BIT(RCOMP) @@ -793,126 +776,18 @@ static void macb_init_hw(struct macb *bp) | MACB_BIT(TCOMP) | MACB_BIT(ISR_ROVR) | MACB_BIT(HRESP))); - } -/* - * The hash address register is 64 bits long and takes up two - * locations in the memory map. The least significant bits are stored - * in EMAC_HSL and the most significant bits in EMAC_HSH. - * - * The unicast hash enable and the multicast hash enable bits in the - * network configuration register enable the reception of hash matched - * frames. The destination address is reduced to a 6 bit index into - * the 64 bit hash register using the following hash function. The - * hash function is an exclusive or of every sixth bit of the - * destination address. - * - * hi[5] = da[5] ^ da[11] ^ da[17] ^ da[23] ^ da[29] ^ da[35] ^ da[41] ^ da[47] - * hi[4] = da[4] ^ da[10] ^ da[16] ^ da[22] ^ da[28] ^ da[34] ^ da[40] ^ da[46] - * hi[3] = da[3] ^ da[09] ^ da[15] ^ da[21] ^ da[27] ^ da[33] ^ da[39] ^ da[45] - * hi[2] = da[2] ^ da[08] ^ da[14] ^ da[20] ^ da[26] ^ da[32] ^ da[38] ^ da[44] - * hi[1] = da[1] ^ da[07] ^ da[13] ^ da[19] ^ da[25] ^ da[31] ^ da[37] ^ da[43] - * hi[0] = da[0] ^ da[06] ^ da[12] ^ da[18] ^ da[24] ^ da[30] ^ da[36] ^ da[42] - * - * da[0] represents the least significant bit of the first byte - * received, that is, the multicast/unicast indicator, and da[47] - * represents the most significant bit of the last byte received. If - * the hash index, hi[n], points to a bit that is set in the hash - * register then the frame will be matched according to whether the - * frame is multicast or unicast. A multicast match will be signalled - * if the multicast hash enable bit is set, da[0] is 1 and the hash - * index points to a bit set in the hash register. A unicast match - * will be signalled if the unicast hash enable bit is set, da[0] is 0 - * and the hash index points to a bit set in the hash register. To - * receive all multicast frames, the hash register should be set with - * all ones and the multicast hash enable bit should be set in the - * network configuration register. - */ - -static inline int hash_bit_value(int bitnr, __u8 *addr) +static void macb_init_phy(struct net_device *dev) { - if (addr[bitnr / 8] & (1 << (bitnr % 8))) - return 1; - return 0; -} - -/* - * Return the hash index value for the specified address. - */ -static int hash_get_index(__u8 *addr) -{ - int i, j, bitval; - int hash_index = 0; - - for (j = 0; j < 6; j++) { - for (i = 0, bitval = 0; i < 8; i++) - bitval ^= hash_bit_value(i*6 + j, addr); - - hash_index |= (bitval << j); - } - - return hash_index; -} - -/* - * Add multicast addresses to the internal multicast-hash table. - */ -static void macb_sethashtable(struct net_device *dev) -{ - struct dev_mc_list *curr; - unsigned long mc_filter[2]; - unsigned int i, bitnr; - struct macb *bp = netdev_priv(dev); - - mc_filter[0] = mc_filter[1] = 0; - - curr = dev->mc_list; - for (i = 0; i < dev->mc_count; i++, curr = curr->next) { - if (!curr) break; /* unexpected end of list */ - - bitnr = hash_get_index(curr->dmi_addr); - mc_filter[bitnr >> 5] |= 1 << (bitnr & 31); - } - - macb_writel(bp, HRB, mc_filter[0]); - macb_writel(bp, HRT, mc_filter[1]); -} - -/* - * Enable/Disable promiscuous and multicast modes. - */ -static void macb_set_rx_mode(struct net_device *dev) -{ - unsigned long cfg; struct macb *bp = netdev_priv(dev); - cfg = macb_readl(bp, NCFGR); - - if (dev->flags & IFF_PROMISC) - /* Enable promiscuous mode */ - cfg |= MACB_BIT(CAF); - else if (dev->flags & (~IFF_PROMISC)) - /* Disable promiscuous mode */ - cfg &= ~MACB_BIT(CAF); - - if (dev->flags & IFF_ALLMULTI) { - /* Enable all multicast mode */ - macb_writel(bp, HRB, -1); - macb_writel(bp, HRT, -1); - cfg |= MACB_BIT(NCFGR_MTI); - } else if (dev->mc_count > 0) { - /* Enable specific multicasts */ - macb_sethashtable(dev); - cfg |= MACB_BIT(NCFGR_MTI); - } else if (dev->flags & (~IFF_ALLMULTI)) { - /* Disable all multicast mode */ - macb_writel(bp, HRB, 0); - macb_writel(bp, HRT, 0); - cfg &= ~MACB_BIT(NCFGR_MTI); - } - - macb_writel(bp, NCFGR, cfg); + /* Set some reasonable default settings */ + macb_mdio_write(dev, bp->mii.phy_id, MII_ADVERTISE, + ADVERTISE_CSMA | ADVERTISE_ALL); + macb_mdio_write(dev, bp->mii.phy_id, MII_BMCR, + (BMCR_SPEED100 | BMCR_ANENABLE + | BMCR_ANRESTART | BMCR_FULLDPLX)); } static int macb_open(struct net_device *dev) @@ -922,10 +797,6 @@ static int macb_open(struct net_device *dev) dev_dbg(&bp->pdev->dev, "open\n"); - /* if the phy is not yet register, retry later*/ - if (!bp->phy_dev) - return -EAGAIN; - if (!is_valid_ether_addr(dev->dev_addr)) return -EADDRNOTAVAIL; @@ -939,12 +810,13 @@ static int macb_open(struct net_device *dev) macb_init_rings(bp); macb_init_hw(bp); + macb_init_phy(dev); - /* schedule a link state check */ - phy_start(bp->phy_dev); - + macb_check_media(bp, 1, 1); netif_start_queue(dev); + schedule_delayed_work(&bp->periodic_task, HZ); + return 0; } @@ -953,10 +825,9 @@ static int macb_close(struct net_device *dev) struct macb *bp = netdev_priv(dev); unsigned long flags; - netif_stop_queue(dev); + cancel_rearming_delayed_work(&bp->periodic_task); - if (bp->phy_dev) - phy_stop(bp->phy_dev); + netif_stop_queue(dev); spin_lock_irqsave(&bp->lock, flags); macb_reset_hw(bp); @@ -974,9 +845,6 @@ static struct net_device_stats *macb_get_stats(struct net_device *dev) struct net_device_stats *nstat = &bp->stats; struct macb_stats *hwstat = &bp->hw_stats; - /* read stats from hardware */ - macb_update_stats(bp); - /* Convert HW stats into netdevice stats */ nstat->rx_errors = (hwstat->rx_fcs_errors + hwstat->rx_align_errors + @@ -1014,27 +882,18 @@ static struct net_device_stats *macb_get_stats(struct net_device *dev) static int macb_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) { struct macb *bp = netdev_priv(dev); - struct phy_device *phydev = bp->phy_dev; - if (!phydev) - return -ENODEV; - - return phy_ethtool_gset(phydev, cmd); + return mii_ethtool_gset(&bp->mii, cmd); } static int macb_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) { struct macb *bp = netdev_priv(dev); - struct phy_device *phydev = bp->phy_dev; - - if (!phydev) - return -ENODEV; - return phy_ethtool_sset(phydev, cmd); + return mii_ethtool_sset(&bp->mii, cmd); } -static void macb_get_drvinfo(struct net_device *dev, - struct ethtool_drvinfo *info) +static void macb_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) { struct macb *bp = netdev_priv(dev); @@ -1043,34 +902,104 @@ static void macb_get_drvinfo(struct net_device *dev, strcpy(info->bus_info, bp->pdev->dev.bus_id); } +static int macb_nway_reset(struct net_device *dev) +{ + struct macb *bp = netdev_priv(dev); + return mii_nway_restart(&bp->mii); +} + static struct ethtool_ops macb_ethtool_ops = { .get_settings = macb_get_settings, .set_settings = macb_set_settings, .get_drvinfo = macb_get_drvinfo, + .nway_reset = macb_nway_reset, .get_link = ethtool_op_get_link, }; static int macb_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) { struct macb *bp = netdev_priv(dev); - struct phy_device *phydev = bp->phy_dev; if (!netif_running(dev)) return -EINVAL; - if (!phydev) - return -ENODEV; + return generic_mii_ioctl(&bp->mii, if_mii(rq), cmd, NULL); +} + +static ssize_t macb_mii_show(const struct device *_dev, char *buf, + unsigned long addr) +{ + struct net_device *dev = to_net_dev(_dev); + struct macb *bp = netdev_priv(dev); + ssize_t ret = -EINVAL; + + if (netif_running(dev)) { + int value; + value = macb_mdio_read(dev, bp->mii.phy_id, addr); + ret = sprintf(buf, "0x%04x\n", (uint16_t)value); + } + + return ret; +} + +#define MII_ENTRY(name, addr) \ +static ssize_t show_##name(struct device *_dev, \ + struct device_attribute *attr, \ + char *buf) \ +{ \ + return macb_mii_show(_dev, buf, addr); \ +} \ +static DEVICE_ATTR(name, S_IRUGO, show_##name, NULL) + +MII_ENTRY(bmcr, MII_BMCR); +MII_ENTRY(bmsr, MII_BMSR); +MII_ENTRY(physid1, MII_PHYSID1); +MII_ENTRY(physid2, MII_PHYSID2); +MII_ENTRY(advertise, MII_ADVERTISE); +MII_ENTRY(lpa, MII_LPA); +MII_ENTRY(expansion, MII_EXPANSION); + +static struct attribute *macb_mii_attrs[] = { + &dev_attr_bmcr.attr, + &dev_attr_bmsr.attr, + &dev_attr_physid1.attr, + &dev_attr_physid2.attr, + &dev_attr_advertise.attr, + &dev_attr_lpa.attr, + &dev_attr_expansion.attr, + NULL, +}; + +static struct attribute_group macb_mii_group = { + .name = "mii", + .attrs = macb_mii_attrs, +}; + +static void macb_unregister_sysfs(struct net_device *net) +{ + struct device *_dev = &net->dev; - return phy_mii_ioctl(phydev, if_mii(rq), cmd); + sysfs_remove_group(&_dev->kobj, &macb_mii_group); } +static int macb_register_sysfs(struct net_device *net) +{ + struct device *_dev = &net->dev; + int ret; + + ret = sysfs_create_group(&_dev->kobj, &macb_mii_group); + if (ret) + printk(KERN_WARNING + "%s: sysfs mii attribute registration failed: %d\n", + net->name, ret); + return ret; +} static int __devinit macb_probe(struct platform_device *pdev) { struct eth_platform_data *pdata; struct resource *regs; struct net_device *dev; struct macb *bp; - struct phy_device *phydev; unsigned long pclk_hz; u32 config; int err = -ENXIO; @@ -1144,7 +1073,6 @@ static int __devinit macb_probe(struct platform_device *pdev) dev->stop = macb_close; dev->hard_start_xmit = macb_start_xmit; dev->get_stats = macb_get_stats; - dev->set_multicast_list = macb_set_rx_mode; dev->do_ioctl = macb_ioctl; dev->poll = macb_poll; dev->weight = 64; @@ -1152,6 +1080,10 @@ static int __devinit macb_probe(struct platform_device *pdev) dev->base_addr = regs->start; + INIT_DELAYED_WORK(&bp->periodic_task, macb_periodic_task); + mutex_init(&bp->mdio_mutex); + init_completion(&bp->mdio_complete); + /* Set MII management clock divider */ pclk_hz = clk_get_rate(bp->pclk); if (pclk_hz <= 20000000) @@ -1164,9 +1096,20 @@ static int __devinit macb_probe(struct platform_device *pdev) config = MACB_BF(CLK, MACB_CLK_DIV64); macb_writel(bp, NCFGR, config); + bp->mii.dev = dev; + bp->mii.mdio_read = macb_mdio_read; + bp->mii.mdio_write = macb_mdio_write; + bp->mii.phy_id_mask = 0x1f; + bp->mii.reg_num_mask = 0x1f; + macb_get_hwaddr(bp); - pdata = pdev->dev.platform_data; + err = macb_phy_probe(bp); + if (err) { + dev_err(&pdev->dev, "Failed to detect PHY, aborting.\n"); + goto err_out_free_irq; + } + pdata = pdev->dev.platform_data; if (pdata && pdata->is_rmii) #if defined(CONFIG_ARCH_AT91) macb_writel(bp, USRIO, (MACB_BIT(RMII) | MACB_BIT(CLKEN)) ); @@ -1188,27 +1131,18 @@ static int __devinit macb_probe(struct platform_device *pdev) goto err_out_free_irq; } - if (macb_mii_init(bp) != 0) { - goto err_out_unregister_netdev; - } - platform_set_drvdata(pdev, dev); + macb_register_sysfs(dev); + printk(KERN_INFO "%s: Atmel MACB at 0x%08lx irq %d " "(%02x:%02x:%02x:%02x:%02x:%02x)\n", dev->name, dev->base_addr, dev->irq, dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2], dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5]); - phydev = bp->phy_dev; - 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); - return 0; -err_out_unregister_netdev: - unregister_netdev(dev); err_out_free_irq: free_irq(dev->irq, dev); err_out_iounmap: @@ -1219,9 +1153,7 @@ static int __devinit macb_probe(struct platform_device *pdev) clk_put(bp->hclk); #endif clk_disable(bp->pclk); -#ifndef CONFIG_ARCH_AT91 err_out_put_pclk: -#endif clk_put(bp->pclk); err_out_free_dev: free_netdev(dev); @@ -1239,8 +1171,7 @@ static int __devexit macb_remove(struct platform_device *pdev) if (dev) { bp = netdev_priv(dev); - mdiobus_unregister(&bp->mii_bus); - kfree(bp->mii_bus.irq); + macb_unregister_sysfs(dev); unregister_netdev(dev); free_irq(dev->irq, dev); iounmap(bp->regs); diff --git a/trunk/drivers/net/macb.h b/trunk/drivers/net/macb.h index 4e3283ebd97c..b3bb2182edd1 100644 --- a/trunk/drivers/net/macb.h +++ b/trunk/drivers/net/macb.h @@ -383,11 +383,11 @@ struct macb { unsigned int rx_pending, tx_pending; - struct mii_bus mii_bus; - struct phy_device *phy_dev; - unsigned int link; - unsigned int speed; - unsigned int duplex; + struct delayed_work periodic_task; + + struct mutex mdio_mutex; + struct completion mdio_complete; + struct mii_if_info mii; }; #endif /* _MACB_H */ diff --git a/trunk/drivers/net/myri10ge/myri10ge.c b/trunk/drivers/net/myri10ge/myri10ge.c index deca65330b0f..e1732c164a40 100644 --- a/trunk/drivers/net/myri10ge/myri10ge.c +++ b/trunk/drivers/net/myri10ge/myri10ge.c @@ -1060,6 +1060,7 @@ static inline void myri10ge_tx_done(struct myri10ge_priv *mgp, int mcp_index) struct myri10ge_tx_buf *tx = &mgp->tx; struct sk_buff *skb; int idx, len; + int limit = 0; while (tx->pkt_done != mcp_index) { idx = tx->done & tx->mask; @@ -1090,6 +1091,11 @@ static inline void myri10ge_tx_done(struct myri10ge_priv *mgp, int mcp_index) bus), len, PCI_DMA_TODEVICE); } + + /* limit potential for livelock by only handling + * 2 full tx rings per call */ + if (unlikely(++limit > 2 * tx->mask)) + break; } /* start the queue if we've stopped it */ if (netif_queue_stopped(mgp->dev) diff --git a/trunk/drivers/net/s2io.c b/trunk/drivers/net/s2io.c index afef6c0c59fe..58bbfdd4f901 100644 --- a/trunk/drivers/net/s2io.c +++ b/trunk/drivers/net/s2io.c @@ -796,14 +796,12 @@ static void free_shared_mem(struct s2io_nic *nic) struct mac_info *mac_control; struct config_param *config; int lst_size, lst_per_page; - struct net_device *dev; + struct net_device *dev = nic->dev; int page_num = 0; if (!nic) return; - dev = nic->dev; - mac_control = &nic->mac_control; config = &nic->config; diff --git a/trunk/drivers/net/usb/cdc_subset.c b/trunk/drivers/net/usb/cdc_subset.c index 943988ed01d8..bc62b012602b 100644 --- a/trunk/drivers/net/usb/cdc_subset.c +++ b/trunk/drivers/net/usb/cdc_subset.c @@ -304,9 +304,6 @@ static const struct usb_device_id products [] = { }, { USB_DEVICE (0x8086, 0x07d3), // "blob" bootloader .driver_info = (unsigned long) &blob_info, -}, { - USB_DEVICE (0x1286, 0x8001), // "blob" bootloader - .driver_info = (unsigned long) &blob_info, }, { // Linux Ethernet/RNDIS gadget on pxa210/25x/26x, second config // e.g. Gumstix, current OpenZaurus, ... diff --git a/trunk/drivers/net/wireless/airo.c b/trunk/drivers/net/wireless/airo.c index 1c54908fdc4c..2d3a180dada0 100644 --- a/trunk/drivers/net/wireless/airo.c +++ b/trunk/drivers/net/wireless/airo.c @@ -52,8 +52,6 @@ #include "airo.h" -#define DRV_NAME "airo" - #ifdef CONFIG_PCI static struct pci_device_id card_ids[] = { { 0x14b9, 1, PCI_ANY_ID, PCI_ANY_ID, }, @@ -73,7 +71,7 @@ static int airo_pci_suspend(struct pci_dev *pdev, pm_message_t state); static int airo_pci_resume(struct pci_dev *pdev); static struct pci_driver airo_driver = { - .name = DRV_NAME, + .name = "airo", .id_table = card_ids, .probe = airo_pci_probe, .remove = __devexit_p(airo_pci_remove), @@ -1094,7 +1092,7 @@ static int get_dec_u16( char *buffer, int *start, int limit ); static void OUT4500( struct airo_info *, u16 register, u16 value ); static unsigned short IN4500( struct airo_info *, u16 register ); static u16 setup_card(struct airo_info*, u8 *mac, int lock); -static int enable_MAC(struct airo_info *ai, int lock); +static int enable_MAC( struct airo_info *ai, Resp *rsp, int lock ); static void disable_MAC(struct airo_info *ai, int lock); static void enable_interrupts(struct airo_info*); static void disable_interrupts(struct airo_info*); @@ -1252,7 +1250,7 @@ static int flashputbuf(struct airo_info *ai); static int flashrestart(struct airo_info *ai,struct net_device *dev); #define airo_print(type, name, fmt, args...) \ - printk(type DRV_NAME "(%s): " fmt "\n", name, ##args) + { printk(type "airo(%s): " fmt "\n", name, ##args); } #define airo_print_info(name, fmt, args...) \ airo_print(KERN_INFO, name, fmt, ##args) @@ -1928,54 +1926,28 @@ static int readStatsRid(struct airo_info*ai, StatsRid *sr, int rid, int lock) { return rc; } -static void try_auto_wep(struct airo_info *ai) -{ - if (auto_wep && !(ai->flags & FLAG_RADIO_DOWN)) { - ai->expires = RUN_AT(3*HZ); - wake_up_interruptible(&ai->thr_wait); - } -} - static int airo_open(struct net_device *dev) { - struct airo_info *ai = dev->priv; - int rc = 0; + struct airo_info *info = dev->priv; + Resp rsp; - if (test_bit(FLAG_FLASHING, &ai->flags)) + if (test_bit(FLAG_FLASHING, &info->flags)) return -EIO; /* Make sure the card is configured. * Wireless Extensions may postpone config changes until the card * is open (to pipeline changes and speed-up card setup). If * those changes are not yet commited, do it now - Jean II */ - if (test_bit(FLAG_COMMIT, &ai->flags)) { - disable_MAC(ai, 1); - writeConfigRid(ai, 1); + if (test_bit (FLAG_COMMIT, &info->flags)) { + disable_MAC(info, 1); + writeConfigRid(info, 1); } - if (ai->wifidev != dev) { - clear_bit(JOB_DIE, &ai->jobs); - ai->airo_thread_task = kthread_run(airo_thread, dev, dev->name); - if (IS_ERR(ai->airo_thread_task)) - return (int)PTR_ERR(ai->airo_thread_task); - - rc = request_irq(dev->irq, airo_interrupt, IRQF_SHARED, - dev->name, dev); - if (rc) { - airo_print_err(dev->name, - "register interrupt %d failed, rc %d", - dev->irq, rc); - set_bit(JOB_DIE, &ai->jobs); - kthread_stop(ai->airo_thread_task); - return rc; - } - + if (info->wifidev != dev) { /* Power on the MAC controller (which may have been disabled) */ - clear_bit(FLAG_RADIO_DOWN, &ai->flags); - enable_interrupts(ai); - - try_auto_wep(ai); + clear_bit(FLAG_RADIO_DOWN, &info->flags); + enable_interrupts(info); } - enable_MAC(ai, 1); + enable_MAC(info, &rsp, 1); netif_start_queue(dev); return 0; @@ -2366,13 +2338,14 @@ static int airo_set_mac_address(struct net_device *dev, void *p) { struct airo_info *ai = dev->priv; struct sockaddr *addr = p; + Resp rsp; readConfigRid(ai, 1); memcpy (ai->config.macAddr, addr->sa_data, dev->addr_len); set_bit (FLAG_COMMIT, &ai->flags); disable_MAC(ai, 1); writeConfigRid (ai, 1); - enable_MAC(ai, 1); + enable_MAC(ai, &rsp, 1); memcpy (ai->dev->dev_addr, addr->sa_data, dev->addr_len); if (ai->wifidev) memcpy (ai->wifidev->dev_addr, addr->sa_data, dev->addr_len); @@ -2419,11 +2392,6 @@ static int airo_close(struct net_device *dev) { disable_MAC(ai, 1); #endif disable_interrupts( ai ); - - free_irq(dev->irq, dev); - - set_bit(JOB_DIE, &ai->jobs); - kthread_stop(ai->airo_thread_task); } return 0; } @@ -2435,6 +2403,7 @@ void stop_airo_card( struct net_device *dev, int freeres ) set_bit(FLAG_RADIO_DOWN, &ai->flags); disable_MAC(ai, 1); disable_interrupts(ai); + free_irq( dev->irq, dev ); takedown_proc_entry( dev, ai ); if (test_bit(FLAG_REGISTERED, &ai->flags)) { unregister_netdev( dev ); @@ -2445,6 +2414,9 @@ void stop_airo_card( struct net_device *dev, int freeres ) } clear_bit(FLAG_REGISTERED, &ai->flags); } + set_bit(JOB_DIE, &ai->jobs); + kthread_stop(ai->airo_thread_task); + /* * Clean out tx queue */ @@ -2582,7 +2554,8 @@ static int mpi_init_descriptors (struct airo_info *ai) * 2) Map PCI memory for issueing commands. * 3) Allocate memory (shared) to send and receive ethernet frames. */ -static int mpi_map_card(struct airo_info *ai, struct pci_dev *pci) +static int mpi_map_card(struct airo_info *ai, struct pci_dev *pci, + const char *name) { unsigned long mem_start, mem_len, aux_start, aux_len; int rc = -1; @@ -2596,35 +2569,35 @@ static int mpi_map_card(struct airo_info *ai, struct pci_dev *pci) aux_start = pci_resource_start(pci, 2); aux_len = AUXMEMSIZE; - if (!request_mem_region(mem_start, mem_len, DRV_NAME)) { - airo_print_err("", "Couldn't get region %x[%x]", - (int)mem_start, (int)mem_len); + if (!request_mem_region(mem_start, mem_len, name)) { + airo_print_err(ai->dev->name, "Couldn't get region %x[%x] for %s", + (int)mem_start, (int)mem_len, name); goto out; } - if (!request_mem_region(aux_start, aux_len, DRV_NAME)) { - airo_print_err("", "Couldn't get region %x[%x]", - (int)aux_start, (int)aux_len); + if (!request_mem_region(aux_start, aux_len, name)) { + airo_print_err(ai->dev->name, "Couldn't get region %x[%x] for %s", + (int)aux_start, (int)aux_len, name); goto free_region1; } ai->pcimem = ioremap(mem_start, mem_len); if (!ai->pcimem) { - airo_print_err("", "Couldn't map region %x[%x]", - (int)mem_start, (int)mem_len); + airo_print_err(ai->dev->name, "Couldn't map region %x[%x] for %s", + (int)mem_start, (int)mem_len, name); goto free_region2; } ai->pciaux = ioremap(aux_start, aux_len); if (!ai->pciaux) { - airo_print_err("", "Couldn't map region %x[%x]", - (int)aux_start, (int)aux_len); + airo_print_err(ai->dev->name, "Couldn't map region %x[%x] for %s", + (int)aux_start, (int)aux_len, name); goto free_memmap; } /* Reserve PKTSIZE for each fid and 2K for the Rids */ ai->shared = pci_alloc_consistent(pci, PCI_SHARED_LEN, &ai->shared_dma); if (!ai->shared) { - airo_print_err("", "Couldn't alloc_consistent %d", - PCI_SHARED_LEN); + airo_print_err(ai->dev->name, "Couldn't alloc_consistent %d", + PCI_SHARED_LEN); goto free_auxmap; } @@ -2769,7 +2742,7 @@ static int airo_networks_allocate(struct airo_info *ai) kzalloc(AIRO_MAX_NETWORK_COUNT * sizeof(BSSListElement), GFP_KERNEL); if (!ai->networks) { - airo_print_warn("", "Out of memory allocating beacons"); + airo_print_warn(ai->dev->name, "Out of memory allocating beacons"); return -ENOMEM; } @@ -2797,6 +2770,7 @@ static int airo_test_wpa_capable(struct airo_info *ai) { int status; CapabilityRid cap_rid; + const char *name = ai->dev->name; status = readCapabilityRid(ai, &cap_rid, 1); if (status != SUCCESS) return 0; @@ -2804,12 +2778,12 @@ static int airo_test_wpa_capable(struct airo_info *ai) /* Only firmware versions 5.30.17 or better can do WPA */ if ((cap_rid.softVer > 0x530) || ((cap_rid.softVer == 0x530) && (cap_rid.softSubVer >= 17))) { - airo_print_info("", "WPA is supported."); + airo_print_info(name, "WPA is supported."); return 1; } /* No WPA support */ - airo_print_info("", "WPA unsupported (only firmware versions 5.30.17" + airo_print_info(name, "WPA unsupported (only firmware versions 5.30.17" " and greater support WPA. Detected %s)", cap_rid.prodVer); return 0; } @@ -2823,19 +2797,23 @@ static struct net_device *_init_airo_card( unsigned short irq, int port, int i, rc; /* Create the network device object. */ - dev = alloc_netdev(sizeof(*ai), "", ether_setup); - if (!dev) { + dev = alloc_etherdev(sizeof(*ai)); + if (!dev) { airo_print_err("", "Couldn't alloc_etherdev"); return NULL; + } + if (dev_alloc_name(dev, dev->name) < 0) { + airo_print_err("", "Couldn't get name!"); + goto err_out_free; } ai = dev->priv; ai->wifidev = NULL; - ai->flags = 1 << FLAG_RADIO_DOWN; + ai->flags = 0; ai->jobs = 0; ai->dev = dev; if (pci && (pci->device == 0x5000 || pci->device == 0xa504)) { - airo_print_dbg("", "Found an MPI350 card"); + airo_print_dbg(dev->name, "Found an MPI350 card"); set_bit(FLAG_MPI, &ai->flags); } spin_lock_init(&ai->aux_lock); @@ -2843,11 +2821,14 @@ static struct net_device *_init_airo_card( unsigned short irq, int port, ai->config.len = 0; ai->pci = pci; init_waitqueue_head (&ai->thr_wait); + ai->airo_thread_task = kthread_run(airo_thread, dev, dev->name); + if (IS_ERR(ai->airo_thread_task)) + goto err_out_free; ai->tfm = NULL; add_airo_dev(ai); if (airo_networks_allocate (ai)) - goto err_out_free; + goto err_out_thr; airo_networks_initialize (ai); /* The Airo-specific entries in the device structure. */ @@ -2870,22 +2851,27 @@ static struct net_device *_init_airo_card( unsigned short irq, int port, dev->base_addr = port; SET_NETDEV_DEV(dev, dmdev); - SET_MODULE_OWNER(dev); reset_card (dev, 1); msleep(400); + rc = request_irq( dev->irq, airo_interrupt, IRQF_SHARED, dev->name, dev ); + if (rc) { + airo_print_err(dev->name, "register interrupt %d failed, rc %d", + irq, rc); + goto err_out_nets; + } if (!is_pcmcia) { - if (!request_region(dev->base_addr, 64, DRV_NAME)) { + if (!request_region( dev->base_addr, 64, dev->name )) { rc = -EBUSY; airo_print_err(dev->name, "Couldn't request region"); - goto err_out_nets; + goto err_out_irq; } } if (test_bit(FLAG_MPI,&ai->flags)) { - if (mpi_map_card(ai, pci)) { - airo_print_err("", "Could not map memory"); + if (mpi_map_card(ai, pci, dev->name)) { + airo_print_err(dev->name, "Could not map memory"); goto err_out_res; } } @@ -2913,7 +2899,6 @@ static struct net_device *_init_airo_card( unsigned short irq, int port, ai->bssListRidLen = sizeof(BSSListRid) - sizeof(BSSListRidExtra); } - strcpy(dev->name, "eth%d"); rc = register_netdev(dev); if (rc) { airo_print_err(dev->name, "Couldn't register_netdev"); @@ -2936,6 +2921,8 @@ static struct net_device *_init_airo_card( unsigned short irq, int port, if (setup_proc_entry(dev, dev->priv) < 0) goto err_out_wifi; + netif_start_queue(dev); + SET_MODULE_OWNER(dev); return dev; err_out_wifi: @@ -2953,9 +2940,14 @@ static struct net_device *_init_airo_card( unsigned short irq, int port, err_out_res: if (!is_pcmcia) release_region( dev->base_addr, 64 ); +err_out_irq: + free_irq(dev->irq, dev); err_out_nets: airo_networks_free(ai); +err_out_thr: del_airo_dev(ai); + set_bit(JOB_DIE, &ai->jobs); + kthread_stop(ai->airo_thread_task); err_out_free: free_netdev(dev); return NULL; @@ -3537,11 +3529,9 @@ static u16 IN4500( struct airo_info *ai, u16 reg ) { return rc; } -static int enable_MAC(struct airo_info *ai, int lock) -{ +static int enable_MAC( struct airo_info *ai, Resp *rsp, int lock ) { int rc; - Cmd cmd; - Resp rsp; + Cmd cmd; /* FLAG_RADIO_OFF : Radio disabled via /proc or Wireless Extensions * FLAG_RADIO_DOWN : Radio disabled via "ifconfig ethX down" @@ -3557,7 +3547,7 @@ static int enable_MAC(struct airo_info *ai, int lock) if (!test_bit(FLAG_ENABLED, &ai->flags)) { memset(&cmd, 0, sizeof(cmd)); cmd.cmd = MAC_ENABLE; - rc = issuecommand(ai, &cmd, &rsp); + rc = issuecommand(ai, &cmd, rsp); if (rc == SUCCESS) set_bit(FLAG_ENABLED, &ai->flags); } else @@ -3567,12 +3557,8 @@ static int enable_MAC(struct airo_info *ai, int lock) up(&ai->sem); if (rc) - airo_print_err(ai->dev->name, "Cannot enable MAC"); - else if ((rsp.status & 0xFF00) != 0) { - airo_print_err(ai->dev->name, "Bad MAC enable reason=%x, " - "rid=%x, offset=%d", rsp.rsp0, rsp.rsp1, rsp.rsp2); - rc = ERROR; - } + airo_print_err(ai->dev->name, "%s: Cannot enable MAC, err=%d", + __FUNCTION__, rc); return rc; } @@ -3916,9 +3902,12 @@ static u16 setup_card(struct airo_info *ai, u8 *mac, int lock) if ( status != SUCCESS ) return ERROR; } - status = enable_MAC(ai, lock); - if (status != SUCCESS) + status = enable_MAC(ai, &rsp, lock); + if ( status != SUCCESS || (rsp.status & 0xFF00) != 0) { + airo_print_err(ai->dev->name, "Bad MAC enable reason = %x, rid = %x," + " offset = %d", rsp.rsp0, rsp.rsp1, rsp.rsp2 ); return ERROR; + } /* Grab the initial wep key, we gotta save it for auto_wep */ rc = readWepKeyRid(ai, &wkr, 1, lock); @@ -3930,7 +3919,10 @@ static u16 setup_card(struct airo_info *ai, u8 *mac, int lock) rc = readWepKeyRid(ai, &wkr, 0, lock); } while(lastindex != wkr.kindex); - try_auto_wep(ai); + if (auto_wep) { + ai->expires = RUN_AT(3*HZ); + wake_up_interruptible(&ai->thr_wait); + } return SUCCESS; } @@ -4012,7 +4004,7 @@ static int bap_setup(struct airo_info *ai, u16 rid, u16 offset, int whichbap ) } if ( !(max_tries--) ) { airo_print_err(ai->dev->name, - "BAP setup error too many retries\n"); + "airo: BAP setup error too many retries\n"); return ERROR; } // -- PC4500 missed it, try again @@ -5160,6 +5152,7 @@ static void proc_SSID_on_close( struct inode *inode, struct file *file ) { struct net_device *dev = dp->data; struct airo_info *ai = dev->priv; SsidRid SSID_rid; + Resp rsp; int i; int offset = 0; @@ -5184,7 +5177,7 @@ static void proc_SSID_on_close( struct inode *inode, struct file *file ) { SSID_rid.len = sizeof(SSID_rid); disable_MAC(ai, 1); writeSsidRid(ai, &SSID_rid, 1); - enable_MAC(ai, 1); + enable_MAC(ai, &rsp, 1); } static inline u8 hexVal(char c) { @@ -5200,6 +5193,7 @@ static void proc_APList_on_close( struct inode *inode, struct file *file ) { struct net_device *dev = dp->data; struct airo_info *ai = dev->priv; APListRid APList_rid; + Resp rsp; int i; if ( !data->writelen ) return; @@ -5224,17 +5218,18 @@ static void proc_APList_on_close( struct inode *inode, struct file *file ) { } disable_MAC(ai, 1); writeAPListRid(ai, &APList_rid, 1); - enable_MAC(ai, 1); + enable_MAC(ai, &rsp, 1); } /* This function wraps PC4500_writerid with a MAC disable */ static int do_writerid( struct airo_info *ai, u16 rid, const void *rid_data, int len, int dummy ) { int rc; + Resp rsp; disable_MAC(ai, 1); rc = PC4500_writerid(ai, rid, rid_data, len, 1); - enable_MAC(ai, 1); + enable_MAC(ai, &rsp, 1); return rc; } @@ -5265,6 +5260,7 @@ static int set_wep_key(struct airo_info *ai, u16 index, const char *key, u16 keylen, int perm, int lock ) { static const unsigned char macaddr[ETH_ALEN] = { 0x01, 0, 0, 0, 0, 0 }; WepKeyRid wkr; + Resp rsp; memset(&wkr, 0, sizeof(wkr)); if (keylen == 0) { @@ -5284,7 +5280,7 @@ static int set_wep_key(struct airo_info *ai, u16 index, if (perm) disable_MAC(ai, lock); writeWepKeyRid(ai, &wkr, perm, lock); - if (perm) enable_MAC(ai, lock); + if (perm) enable_MAC(ai, &rsp, lock); return 0; } @@ -5552,6 +5548,7 @@ static int proc_close( struct inode *inode, struct file *file ) changed. */ static void timer_func( struct net_device *dev ) { struct airo_info *apriv = dev->priv; + Resp rsp; /* We don't have a link so try changing the authtype */ readConfigRid(apriv, 0); @@ -5578,7 +5575,7 @@ static void timer_func( struct net_device *dev ) { } set_bit (FLAG_COMMIT, &apriv->flags); writeConfigRid(apriv, 0); - enable_MAC(apriv, 0); + enable_MAC(apriv, &rsp, 0); up(&apriv->sem); /* Schedule check to see if the change worked */ @@ -5600,10 +5597,8 @@ static int __devinit airo_pci_probe(struct pci_dev *pdev, dev = _init_airo_card(pdev->irq, pdev->resource[0].start, 0, pdev, &pdev->dev); else dev = _init_airo_card(pdev->irq, pdev->resource[2].start, 0, pdev, &pdev->dev); - if (!dev) { - pci_disable_device(pdev); + if (!dev) return -ENODEV; - } pci_set_drvdata(pdev, dev); return 0; @@ -5615,8 +5610,6 @@ static void __devexit airo_pci_remove(struct pci_dev *pdev) airo_print_info(dev->name, "Unregistering..."); stop_airo_card(dev, 1); - pci_disable_device(pdev); - pci_set_drvdata(pdev, NULL); } static int airo_pci_suspend(struct pci_dev *pdev, pm_message_t state) @@ -5653,6 +5646,7 @@ static int airo_pci_resume(struct pci_dev *pdev) { struct net_device *dev = pci_get_drvdata(pdev); struct airo_info *ai = dev->priv; + Resp rsp; pci_power_t prev_state = pdev->current_state; pci_set_power_state(pdev, PCI_D0); @@ -5685,7 +5679,7 @@ static int airo_pci_resume(struct pci_dev *pdev) ai->APList = NULL; } writeConfigRid(ai, 0); - enable_MAC(ai, 0); + enable_MAC(ai, &rsp, 0); ai->power = PMSG_ON; netif_device_attach(dev); netif_wake_queue(dev); @@ -5909,6 +5903,7 @@ static int airo_set_essid(struct net_device *dev, char *extra) { struct airo_info *local = dev->priv; + Resp rsp; SsidRid SSID_rid; /* SSIDs */ /* Reload the list of current SSID */ @@ -5940,7 +5935,7 @@ static int airo_set_essid(struct net_device *dev, /* Write it to the card */ disable_MAC(local, 1); writeSsidRid(local, &SSID_rid, 1); - enable_MAC(local, 1); + enable_MAC(local, &rsp, 1); return 0; } @@ -6005,7 +6000,7 @@ static int airo_set_wap(struct net_device *dev, memcpy(APList_rid.ap[0], awrq->sa_data, ETH_ALEN); disable_MAC(local, 1); writeAPListRid(local, &APList_rid, 1); - enable_MAC(local, 1); + enable_MAC(local, &rsp, 1); } return 0; } @@ -7459,6 +7454,7 @@ static int airo_config_commit(struct net_device *dev, char *extra) /* NULL */ { struct airo_info *local = dev->priv; + Resp rsp; if (!test_bit (FLAG_COMMIT, &local->flags)) return 0; @@ -7483,7 +7479,7 @@ static int airo_config_commit(struct net_device *dev, if (down_interruptible(&local->sem)) return -ERESTARTSYS; writeConfigRid(local, 0); - enable_MAC(local, 0); + enable_MAC(local, &rsp, 0); if (test_bit (FLAG_RESET, &local->flags)) airo_set_promisc(local); else @@ -7750,6 +7746,7 @@ static int readrids(struct net_device *dev, aironet_ioctl *comp) { unsigned char *iobuf; int len; struct airo_info *ai = dev->priv; + Resp rsp; if (test_bit(FLAG_FLASHING, &ai->flags)) return -EIO; @@ -7761,7 +7758,7 @@ static int readrids(struct net_device *dev, aironet_ioctl *comp) { if (test_bit(FLAG_COMMIT, &ai->flags)) { disable_MAC (ai, 1); writeConfigRid (ai, 1); - enable_MAC(ai, 1); + enable_MAC (ai, &rsp, 1); } break; case AIROGSLIST: ridcode = RID_SSID; break; @@ -7818,6 +7815,7 @@ static int writerids(struct net_device *dev, aironet_ioctl *comp) { struct airo_info *ai = dev->priv; int ridcode; int enabled; + Resp rsp; static int (* writer)(struct airo_info *, u16 rid, const void *, int, int); unsigned char *iobuf; @@ -7851,7 +7849,7 @@ static int writerids(struct net_device *dev, aironet_ioctl *comp) { * same with MAC off */ case AIROPMACON: - if (enable_MAC(ai, 1) != 0) + if (enable_MAC(ai, &rsp, 1) != 0) return -EIO; return 0; diff --git a/trunk/drivers/net/wireless/ipw2100.c b/trunk/drivers/net/wireless/ipw2100.c index 072ede71e575..d51daf87450f 100644 --- a/trunk/drivers/net/wireless/ipw2100.c +++ b/trunk/drivers/net/wireless/ipw2100.c @@ -1768,8 +1768,7 @@ static int ipw2100_up(struct ipw2100_priv *priv, int deferred) if (priv->stop_rf_kill) { priv->stop_rf_kill = 0; - queue_delayed_work(priv->workqueue, &priv->rf_kill, - round_jiffies(HZ)); + queue_delayed_work(priv->workqueue, &priv->rf_kill, HZ); } deferred = 1; @@ -2099,7 +2098,7 @@ static void isr_indicate_rf_kill(struct ipw2100_priv *priv, u32 status) /* Make sure the RF Kill check timer is running */ priv->stop_rf_kill = 0; cancel_delayed_work(&priv->rf_kill); - queue_delayed_work(priv->workqueue, &priv->rf_kill, round_jiffies(HZ)); + queue_delayed_work(priv->workqueue, &priv->rf_kill, HZ); } static void isr_scan_complete(struct ipw2100_priv *priv, u32 status) @@ -4234,8 +4233,7 @@ static int ipw_radio_kill_sw(struct ipw2100_priv *priv, int disable_radio) /* Make sure the RF_KILL check timer is running */ priv->stop_rf_kill = 0; cancel_delayed_work(&priv->rf_kill); - queue_delayed_work(priv->workqueue, &priv->rf_kill, - round_jiffies(HZ)); + queue_delayed_work(priv->workqueue, &priv->rf_kill, HZ); } else schedule_reset(priv); } @@ -5971,8 +5969,7 @@ static void ipw2100_rf_kill(struct work_struct *work) if (rf_kill_active(priv)) { IPW_DEBUG_RF_KILL("RF Kill active, rescheduling GPIO check\n"); if (!priv->stop_rf_kill) - queue_delayed_work(priv->workqueue, &priv->rf_kill, - round_jiffies(HZ)); + queue_delayed_work(priv->workqueue, &priv->rf_kill, HZ); goto exit_unlock; } diff --git a/trunk/drivers/net/wireless/ipw2200.c b/trunk/drivers/net/wireless/ipw2200.c index aa32a97380ec..7cb2052a55a5 100644 --- a/trunk/drivers/net/wireless/ipw2200.c +++ b/trunk/drivers/net/wireless/ipw2200.c @@ -1751,7 +1751,7 @@ static int ipw_radio_kill_sw(struct ipw_priv *priv, int disable_radio) /* Make sure the RF_KILL check timer is running */ cancel_delayed_work(&priv->rf_kill); queue_delayed_work(priv->workqueue, &priv->rf_kill, - round_jiffies(2 * HZ)); + 2 * HZ); } else queue_work(priv->workqueue, &priv->up); } @@ -4690,8 +4690,7 @@ static void ipw_rx_notification(struct ipw_priv *priv, else if (priv->config & CFG_BACKGROUND_SCAN && priv->status & STATUS_ASSOCIATED) queue_delayed_work(priv->workqueue, - &priv->request_scan, - round_jiffies(HZ)); + &priv->request_scan, HZ); /* Send an empty event to user space. * We don't send the received data on the event because diff --git a/trunk/drivers/net/wireless/libertas/cmd.c b/trunk/drivers/net/wireless/libertas/cmd.c index 4a8f5dc70239..13f6528abb00 100644 --- a/trunk/drivers/net/wireless/libertas/cmd.c +++ b/trunk/drivers/net/wireless/libertas/cmd.c @@ -240,7 +240,7 @@ static int wlan_cmd_802_11_enable_rsn(wlan_private * priv, if (*enable) penableRSN->enable = cpu_to_le16(cmd_enable_rsn); else - penableRSN->enable = cpu_to_le16(cmd_disable_rsn); + penableRSN->enable = cpu_to_le16(cmd_enable_rsn); } lbs_deb_leave(LBS_DEB_CMD); diff --git a/trunk/drivers/net/wireless/libertas/rx.c b/trunk/drivers/net/wireless/libertas/rx.c index 769c86fb9509..88d9d2d787d5 100644 --- a/trunk/drivers/net/wireless/libertas/rx.c +++ b/trunk/drivers/net/wireless/libertas/rx.c @@ -439,6 +439,7 @@ static int process_rxed_802_11_packet(wlan_private * priv, struct sk_buff *skb) ret = 0; done: + skb->protocol = __constant_htons(0x0019); /* ETH_P_80211_RAW */ lbs_deb_leave_args(LBS_DEB_RX, "ret %d", ret); return ret; } diff --git a/trunk/drivers/net/wireless/libertas/version.h b/trunk/drivers/net/wireless/libertas/version.h new file mode 100644 index 000000000000..8b137891791f --- /dev/null +++ b/trunk/drivers/net/wireless/libertas/version.h @@ -0,0 +1 @@ + diff --git a/trunk/drivers/net/wireless/libertas/wext.c b/trunk/drivers/net/wireless/libertas/wext.c index 2fcc3bf21081..f42b796b5e47 100644 --- a/trunk/drivers/net/wireless/libertas/wext.c +++ b/trunk/drivers/net/wireless/libertas/wext.c @@ -1719,6 +1719,9 @@ static int wlan_set_encodeext(struct net_device *dev, pkey->type = KEY_TYPE_ID_TKIP; } else if (alg == IW_ENCODE_ALG_CCMP) { pkey->type = KEY_TYPE_ID_AES; + } else { + ret = -EINVAL; + goto out; } /* If WPA isn't enabled yet, do that now */ diff --git a/trunk/drivers/net/wireless/prism54/isl_ioctl.c b/trunk/drivers/net/wireless/prism54/isl_ioctl.c index 585f5996d292..283be4a70524 100644 --- a/trunk/drivers/net/wireless/prism54/isl_ioctl.c +++ b/trunk/drivers/net/wireless/prism54/isl_ioctl.c @@ -1853,6 +1853,7 @@ prism54_del_mac(struct net_device *ndev, struct iw_request_info *info, islpci_private *priv = netdev_priv(ndev); struct islpci_acl *acl = &priv->acl; struct mac_entry *entry; + struct list_head *ptr; struct sockaddr *addr = (struct sockaddr *) extra; if (addr->sa_family != ARPHRD_ETHER) @@ -1860,9 +1861,11 @@ prism54_del_mac(struct net_device *ndev, struct iw_request_info *info, if (down_interruptible(&acl->sem)) return -ERESTARTSYS; - list_for_each_entry(entry, &acl->mac_list, _list) { + for (ptr = acl->mac_list.next; ptr != &acl->mac_list; ptr = ptr->next) { + entry = list_entry(ptr, struct mac_entry, _list); + if (memcmp(entry->addr, addr->sa_data, ETH_ALEN) == 0) { - list_del(&entry->_list); + list_del(ptr); acl->size--; kfree(entry); up(&acl->sem); @@ -1880,6 +1883,7 @@ prism54_get_mac(struct net_device *ndev, struct iw_request_info *info, islpci_private *priv = netdev_priv(ndev); struct islpci_acl *acl = &priv->acl; struct mac_entry *entry; + struct list_head *ptr; struct sockaddr *dst = (struct sockaddr *) extra; dwrq->length = 0; @@ -1887,7 +1891,9 @@ prism54_get_mac(struct net_device *ndev, struct iw_request_info *info, if (down_interruptible(&acl->sem)) return -ERESTARTSYS; - list_for_each_entry(entry, &acl->mac_list, _list) { + for (ptr = acl->mac_list.next; ptr != &acl->mac_list; ptr = ptr->next) { + entry = list_entry(ptr, struct mac_entry, _list); + memcpy(dst->sa_data, entry->addr, ETH_ALEN); dst->sa_family = ARPHRD_ETHER; dwrq->length++; @@ -1954,6 +1960,7 @@ prism54_get_policy(struct net_device *ndev, struct iw_request_info *info, static int prism54_mac_accept(struct islpci_acl *acl, char *mac) { + struct list_head *ptr; struct mac_entry *entry; int res = 0; @@ -1965,7 +1972,8 @@ prism54_mac_accept(struct islpci_acl *acl, char *mac) return 1; } - list_for_each_entry(entry, &acl->mac_list, _list) { + for (ptr = acl->mac_list.next; ptr != &acl->mac_list; ptr = ptr->next) { + entry = list_entry(ptr, struct mac_entry, _list); if (memcmp(entry->addr, mac, ETH_ALEN) == 0) { res = 1; break; @@ -2208,9 +2216,11 @@ prism54_wpa_bss_ie_init(islpci_private *priv) void prism54_wpa_bss_ie_clean(islpci_private *priv) { - struct islpci_bss_wpa_ie *bss, *n; + struct list_head *ptr, *n; - list_for_each_entry_safe(bss, n, &priv->bss_wpa_list, list) { + list_for_each_safe(ptr, n, &priv->bss_wpa_list) { + struct islpci_bss_wpa_ie *bss; + bss = list_entry(ptr, struct islpci_bss_wpa_ie, list); kfree(bss); } } diff --git a/trunk/drivers/net/wireless/rtl8187_rtl8225.c b/trunk/drivers/net/wireless/rtl8187_rtl8225.c index efc41207780e..e25a09f1b068 100644 --- a/trunk/drivers/net/wireless/rtl8187_rtl8225.c +++ b/trunk/drivers/net/wireless/rtl8187_rtl8225.c @@ -67,7 +67,7 @@ static void rtl8225_write_bitbang(struct ieee80211_hw *dev, u8 addr, u16 data) msleep(2); } -static void rtl8225_write_8051(struct ieee80211_hw *dev, u8 addr, __le16 data) +static void rtl8225_write_8051(struct ieee80211_hw *dev, u8 addr, u16 data) { struct rtl8187_priv *priv = dev->priv; u16 reg80, reg82, reg84; @@ -106,7 +106,7 @@ void rtl8225_write(struct ieee80211_hw *dev, u8 addr, u16 data) struct rtl8187_priv *priv = dev->priv; if (priv->asic_rev) - rtl8225_write_8051(dev, addr, cpu_to_le16(data)); + rtl8225_write_8051(dev, addr, data); else rtl8225_write_bitbang(dev, addr, data); } diff --git a/trunk/drivers/net/wireless/zd1211rw/zd_chip.c b/trunk/drivers/net/wireless/zd1211rw/zd_chip.c index c39f1984b84d..5b624bfc01a6 100644 --- a/trunk/drivers/net/wireless/zd1211rw/zd_chip.c +++ b/trunk/drivers/net/wireless/zd1211rw/zd_chip.c @@ -49,9 +49,8 @@ void zd_chip_clear(struct zd_chip *chip) ZD_MEMCLEAR(chip, sizeof(*chip)); } -static int scnprint_mac_oui(struct zd_chip *chip, char *buffer, size_t size) +static int scnprint_mac_oui(const u8 *addr, char *buffer, size_t size) { - u8 *addr = zd_usb_to_netdev(&chip->usb)->dev_addr; return scnprintf(buffer, size, "%02x-%02x-%02x", addr[0], addr[1], addr[2]); } @@ -62,10 +61,10 @@ static int scnprint_id(struct zd_chip *chip, char *buffer, size_t size) int i = 0; i = scnprintf(buffer, size, "zd1211%s chip ", - zd_chip_is_zd1211b(chip) ? "b" : ""); + chip->is_zd1211b ? "b" : ""); i += zd_usb_scnprint_id(&chip->usb, buffer+i, size-i); i += scnprintf(buffer+i, size-i, " "); - i += scnprint_mac_oui(chip, buffer+i, size-i); + i += scnprint_mac_oui(chip->e2p_mac, buffer+i, size-i); i += scnprintf(buffer+i, size-i, " "); i += zd_rf_scnprint_id(&chip->rf, buffer+i, size-i); i += scnprintf(buffer+i, size-i, " pa%1x %c%c%c%c%c", chip->pa_type, @@ -367,9 +366,64 @@ static int read_pod(struct zd_chip *chip, u8 *rf_type) return r; } +static int _read_mac_addr(struct zd_chip *chip, u8 *mac_addr, + const zd_addr_t *addr) +{ + int r; + u32 parts[2]; + + r = zd_ioread32v_locked(chip, parts, (const zd_addr_t *)addr, 2); + if (r) { + dev_dbg_f(zd_chip_dev(chip), + "error: couldn't read e2p macs. Error number %d\n", r); + return r; + } + + mac_addr[0] = parts[0]; + mac_addr[1] = parts[0] >> 8; + mac_addr[2] = parts[0] >> 16; + mac_addr[3] = parts[0] >> 24; + mac_addr[4] = parts[1]; + mac_addr[5] = parts[1] >> 8; + + return 0; +} + +static int read_e2p_mac_addr(struct zd_chip *chip) +{ + static const zd_addr_t addr[2] = { E2P_MAC_ADDR_P1, E2P_MAC_ADDR_P2 }; + + ZD_ASSERT(mutex_is_locked(&chip->mutex)); + return _read_mac_addr(chip, chip->e2p_mac, (const zd_addr_t *)addr); +} + /* MAC address: if custom mac addresses are to to be used CR_MAC_ADDR_P1 and * CR_MAC_ADDR_P2 must be overwritten */ +void zd_get_e2p_mac_addr(struct zd_chip *chip, u8 *mac_addr) +{ + mutex_lock(&chip->mutex); + memcpy(mac_addr, chip->e2p_mac, ETH_ALEN); + mutex_unlock(&chip->mutex); +} + +static int read_mac_addr(struct zd_chip *chip, u8 *mac_addr) +{ + static const zd_addr_t addr[2] = { CR_MAC_ADDR_P1, CR_MAC_ADDR_P2 }; + return _read_mac_addr(chip, mac_addr, (const zd_addr_t *)addr); +} + +int zd_read_mac_addr(struct zd_chip *chip, u8 *mac_addr) +{ + int r; + + dev_dbg_f(zd_chip_dev(chip), "\n"); + mutex_lock(&chip->mutex); + r = read_mac_addr(chip, mac_addr); + mutex_unlock(&chip->mutex); + return r; +} + int zd_write_mac_addr(struct zd_chip *chip, const u8 *mac_addr) { int r; @@ -390,6 +444,12 @@ int zd_write_mac_addr(struct zd_chip *chip, const u8 *mac_addr) mutex_lock(&chip->mutex); r = zd_iowrite32a_locked(chip, reqs, ARRAY_SIZE(reqs)); +#ifdef DEBUG + { + u8 tmp[ETH_ALEN]; + read_mac_addr(chip, tmp); + } +#endif /* DEBUG */ mutex_unlock(&chip->mutex); return r; } @@ -749,7 +809,7 @@ static int zd1211b_hw_reset_phy(struct zd_chip *chip) static int hw_reset_phy(struct zd_chip *chip) { - return zd_chip_is_zd1211b(chip) ? zd1211b_hw_reset_phy(chip) : + return chip->is_zd1211b ? zd1211b_hw_reset_phy(chip) : zd1211_hw_reset_phy(chip); } @@ -814,7 +874,7 @@ static int hw_init_hmac(struct zd_chip *chip) if (r) return r; - return zd_chip_is_zd1211b(chip) ? + return chip->is_zd1211b ? zd1211b_hw_init_hmac(chip) : zd1211_hw_init_hmac(chip); } @@ -1076,15 +1136,8 @@ static int read_fw_regs_offset(struct zd_chip *chip) return 0; } -/* Read mac address using pre-firmware interface */ -int zd_chip_read_mac_addr_fw(struct zd_chip *chip, u8 *addr) -{ - dev_dbg_f(zd_chip_dev(chip), "\n"); - return zd_usb_read_fw(&chip->usb, E2P_MAC_ADDR_P1, addr, - ETH_ALEN); -} -int zd_chip_init_hw(struct zd_chip *chip) +int zd_chip_init_hw(struct zd_chip *chip, u8 device_type) { int r; u8 rf_type; @@ -1092,6 +1145,7 @@ int zd_chip_init_hw(struct zd_chip *chip) dev_dbg_f(zd_chip_dev(chip), "\n"); mutex_lock(&chip->mutex); + chip->is_zd1211b = (device_type == DEVICE_ZD1211B) != 0; #ifdef DEBUG r = test_init(chip); @@ -1147,6 +1201,10 @@ int zd_chip_init_hw(struct zd_chip *chip) goto out; #endif /* DEBUG */ + r = read_e2p_mac_addr(chip); + if (r) + goto out; + r = read_cal_int_tables(chip); if (r) goto out; @@ -1201,7 +1259,7 @@ static int update_channel_integration_and_calibration(struct zd_chip *chip, r = update_pwr_int(chip, channel); if (r) return r; - if (zd_chip_is_zd1211b(chip)) { + if (chip->is_zd1211b) { static const struct zd_ioreq16 ioreqs[] = { { CR69, 0x28 }, {}, diff --git a/trunk/drivers/net/wireless/zd1211rw/zd_chip.h b/trunk/drivers/net/wireless/zd1211rw/zd_chip.h index f4698576ab71..79d0288c193a 100644 --- a/trunk/drivers/net/wireless/zd1211rw/zd_chip.h +++ b/trunk/drivers/net/wireless/zd1211rw/zd_chip.h @@ -704,6 +704,7 @@ struct zd_chip { struct mutex mutex; /* Base address of FW_REG_ registers */ zd_addr_t fw_regs_base; + u8 e2p_mac[ETH_ALEN]; /* EepSetPoint in the vendor driver */ u8 pwr_cal_values[E2P_CHANNEL_COUNT]; /* integration values in the vendor driver */ @@ -714,7 +715,7 @@ struct zd_chip { unsigned int pa_type:4, patch_cck_gain:1, patch_cr157:1, patch_6m_band_edge:1, new_phy_layout:1, al2230s_bit:1, - supports_tx_led:1; + is_zd1211b:1, supports_tx_led:1; }; static inline struct zd_chip *zd_usb_to_chip(struct zd_usb *usb) @@ -733,15 +734,9 @@ void zd_chip_init(struct zd_chip *chip, struct net_device *netdev, struct usb_interface *intf); void zd_chip_clear(struct zd_chip *chip); -int zd_chip_read_mac_addr_fw(struct zd_chip *chip, u8 *addr); -int zd_chip_init_hw(struct zd_chip *chip); +int zd_chip_init_hw(struct zd_chip *chip, u8 device_type); int zd_chip_reset(struct zd_chip *chip); -static inline int zd_chip_is_zd1211b(struct zd_chip *chip) -{ - return chip->usb.is_zd1211b; -} - static inline int zd_ioread16v_locked(struct zd_chip *chip, u16 *values, const zd_addr_t *addresses, unsigned int count) @@ -830,6 +825,8 @@ static inline u8 _zd_chip_get_channel(struct zd_chip *chip) } u8 zd_chip_get_channel(struct zd_chip *chip); int zd_read_regdomain(struct zd_chip *chip, u8 *regdomain); +void zd_get_e2p_mac_addr(struct zd_chip *chip, u8 *mac_addr); +int zd_read_mac_addr(struct zd_chip *chip, u8 *mac_addr); int zd_write_mac_addr(struct zd_chip *chip, const u8 *mac_addr); int zd_chip_switch_radio_on(struct zd_chip *chip); int zd_chip_switch_radio_off(struct zd_chip *chip); diff --git a/trunk/drivers/net/wireless/zd1211rw/zd_mac.c b/trunk/drivers/net/wireless/zd1211rw/zd_mac.c index f6c487aa8246..6753d240c168 100644 --- a/trunk/drivers/net/wireless/zd1211rw/zd_mac.c +++ b/trunk/drivers/net/wireless/zd1211rw/zd_mac.c @@ -86,46 +86,38 @@ static int reset_channel(struct zd_mac *mac) return r; } -int zd_mac_preinit_hw(struct zd_mac *mac) -{ - int r; - u8 addr[ETH_ALEN]; - - r = zd_chip_read_mac_addr_fw(&mac->chip, addr); - if (r) - return r; - - memcpy(mac->netdev->dev_addr, addr, ETH_ALEN); - return 0; -} - -int zd_mac_init_hw(struct zd_mac *mac) +int zd_mac_init_hw(struct zd_mac *mac, u8 device_type) { int r; struct zd_chip *chip = &mac->chip; + u8 addr[ETH_ALEN]; u8 default_regdomain; r = zd_chip_enable_int(chip); if (r) goto out; - r = zd_chip_init_hw(chip); + r = zd_chip_init_hw(chip, device_type); if (r) goto disable_int; + zd_get_e2p_mac_addr(chip, addr); + r = zd_write_mac_addr(chip, addr); + if (r) + goto disable_int; ZD_ASSERT(!irqs_disabled()); + spin_lock_irq(&mac->lock); + memcpy(mac->netdev->dev_addr, addr, ETH_ALEN); + spin_unlock_irq(&mac->lock); r = zd_read_regdomain(chip, &default_regdomain); if (r) goto disable_int; if (!zd_regdomain_supported(default_regdomain)) { - /* The vendor driver overrides the regulatory domain and - * allowed channel registers and unconditionally restricts - * available channels to 1-11 everywhere. Match their - * questionable behaviour only for regdomains which we don't - * recognise. */ - dev_warn(zd_mac_dev(mac), "Unrecognised regulatory domain: " - "%#04x. Defaulting to FCC.\n", default_regdomain); - default_regdomain = ZD_REGDOMAIN_FCC; + dev_dbg_f(zd_mac_dev(mac), + "Regulatory Domain %#04x is not supported.\n", + default_regdomain); + r = -EINVAL; + goto disable_int; } spin_lock_irq(&mac->lock); mac->regdomain = mac->default_regdomain = default_regdomain; @@ -172,25 +164,14 @@ int zd_mac_open(struct net_device *netdev) { struct zd_mac *mac = zd_netdev_mac(netdev); struct zd_chip *chip = &mac->chip; - struct zd_usb *usb = &chip->usb; int r; - if (!usb->initialized) { - r = zd_usb_init_hw(usb); - if (r) - goto out; - } - tasklet_enable(&mac->rx_tasklet); r = zd_chip_enable_int(chip); if (r < 0) goto out; - r = zd_write_mac_addr(chip, netdev->dev_addr); - if (r) - goto disable_int; - r = zd_chip_set_basic_rates(chip, CR_RATES_80211B | CR_RATES_80211G); if (r < 0) goto disable_int; @@ -270,11 +251,9 @@ int zd_mac_set_mac_address(struct net_device *netdev, void *p) dev_dbg_f(zd_mac_dev(mac), "Setting MAC to " MAC_FMT "\n", MAC_ARG(addr->sa_data)); - if (netdev->flags & IFF_UP) { - r = zd_write_mac_addr(chip, addr->sa_data); - if (r) - return r; - } + r = zd_write_mac_addr(chip, addr->sa_data); + if (r) + return r; spin_lock_irqsave(&mac->lock, flags); memcpy(netdev->dev_addr, addr->sa_data, ETH_ALEN); @@ -876,7 +855,7 @@ static int fill_ctrlset(struct zd_mac *mac, /* ZD1211B: Computing the length difference this way, gives us * flexibility to compute the packet length. */ - cs->packet_length = cpu_to_le16(zd_chip_is_zd1211b(&mac->chip) ? + cs->packet_length = cpu_to_le16(mac->chip.is_zd1211b ? packet_length - frag_len : packet_length); /* diff --git a/trunk/drivers/net/wireless/zd1211rw/zd_mac.h b/trunk/drivers/net/wireless/zd1211rw/zd_mac.h index 9f9344eb50f9..faf4c7828d4e 100644 --- a/trunk/drivers/net/wireless/zd1211rw/zd_mac.h +++ b/trunk/drivers/net/wireless/zd1211rw/zd_mac.h @@ -189,8 +189,7 @@ int zd_mac_init(struct zd_mac *mac, struct usb_interface *intf); void zd_mac_clear(struct zd_mac *mac); -int zd_mac_preinit_hw(struct zd_mac *mac); -int zd_mac_init_hw(struct zd_mac *mac); +int zd_mac_init_hw(struct zd_mac *mac, u8 device_type); int zd_mac_open(struct net_device *netdev); int zd_mac_stop(struct net_device *netdev); diff --git a/trunk/drivers/net/wireless/zd1211rw/zd_rf.c b/trunk/drivers/net/wireless/zd1211rw/zd_rf.c index abe5d38f7f4d..7407409b60b1 100644 --- a/trunk/drivers/net/wireless/zd1211rw/zd_rf.c +++ b/trunk/drivers/net/wireless/zd1211rw/zd_rf.c @@ -34,7 +34,7 @@ static const char * const rfs[] = { [AL2210_RF] = "AL2210_RF", [MAXIM_NEW_RF] = "MAXIM_NEW_RF", [UW2453_RF] = "UW2453_RF", - [AL2230S_RF] = "AL2230S_RF", + [UNKNOWN_A_RF] = "UNKNOWN_A_RF", [RALINK_RF] = "RALINK_RF", [INTERSIL_RF] = "INTERSIL_RF", [RF2959_RF] = "RF2959_RF", @@ -77,7 +77,6 @@ int zd_rf_init_hw(struct zd_rf *rf, u8 type) r = zd_rf_init_rf2959(rf); break; case AL2230_RF: - case AL2230S_RF: r = zd_rf_init_al2230(rf); break; case AL7230B_RF: diff --git a/trunk/drivers/net/wireless/zd1211rw/zd_rf.h b/trunk/drivers/net/wireless/zd1211rw/zd_rf.h index 30502f26b71c..c6dfd8227f6e 100644 --- a/trunk/drivers/net/wireless/zd1211rw/zd_rf.h +++ b/trunk/drivers/net/wireless/zd1211rw/zd_rf.h @@ -26,7 +26,7 @@ #define AL2210_RF 0x7 #define MAXIM_NEW_RF 0x8 #define UW2453_RF 0x9 -#define AL2230S_RF 0xa +#define UNKNOWN_A_RF 0xa #define RALINK_RF 0xb #define INTERSIL_RF 0xc #define RF2959_RF 0xd diff --git a/trunk/drivers/net/wireless/zd1211rw/zd_rf_al2230.c b/trunk/drivers/net/wireless/zd1211rw/zd_rf_al2230.c index 006774de3202..e7a4ecf7b6e2 100644 --- a/trunk/drivers/net/wireless/zd1211rw/zd_rf_al2230.c +++ b/trunk/drivers/net/wireless/zd1211rw/zd_rf_al2230.c @@ -21,8 +21,6 @@ #include "zd_usb.h" #include "zd_chip.h" -#define IS_AL2230S(chip) ((chip)->al2230s_bit || (chip)->rf.type == AL2230S_RF) - static const u32 zd1211_al2230_table[][3] = { RF_CHANNEL( 1) = { 0x03f790, 0x033331, 0x00000d, }, RF_CHANNEL( 2) = { 0x03f790, 0x0b3331, 0x00000d, }, @@ -178,7 +176,7 @@ static int zd1211_al2230_init_hw(struct zd_rf *rf) if (r) return r; - if (IS_AL2230S(chip)) { + if (chip->al2230s_bit) { r = zd_iowrite16a_locked(chip, ioreqs_init_al2230s, ARRAY_SIZE(ioreqs_init_al2230s)); if (r) @@ -190,7 +188,7 @@ static int zd1211_al2230_init_hw(struct zd_rf *rf) return r; /* improve band edge for AL2230S */ - if (IS_AL2230S(chip)) + if (chip->al2230s_bit) r = zd_rfwrite_locked(chip, 0x000824, RF_RV_BITS); else r = zd_rfwrite_locked(chip, 0x0005a4, RF_RV_BITS); @@ -316,7 +314,7 @@ static int zd1211b_al2230_init_hw(struct zd_rf *rf) if (r) return r; - if (IS_AL2230S(chip)) { + if (chip->al2230s_bit) { r = zd_iowrite16a_locked(chip, ioreqs_init_al2230s, ARRAY_SIZE(ioreqs_init_al2230s)); if (r) @@ -330,7 +328,7 @@ static int zd1211b_al2230_init_hw(struct zd_rf *rf) if (r) return r; - if (IS_AL2230S(chip)) + if (chip->al2230s_bit) r = zd_rfwrite_locked(chip, 0x241000, RF_RV_BITS); else r = zd_rfwrite_locked(chip, 0x25a000, RF_RV_BITS); @@ -424,7 +422,7 @@ int zd_rf_init_al2230(struct zd_rf *rf) struct zd_chip *chip = zd_rf_to_chip(rf); rf->switch_radio_off = al2230_switch_radio_off; - if (zd_chip_is_zd1211b(chip)) { + if (chip->is_zd1211b) { rf->init_hw = zd1211b_al2230_init_hw; rf->set_channel = zd1211b_al2230_set_channel; rf->switch_radio_on = zd1211b_al2230_switch_radio_on; diff --git a/trunk/drivers/net/wireless/zd1211rw/zd_rf_al7230b.c b/trunk/drivers/net/wireless/zd1211rw/zd_rf_al7230b.c index 73d0bb26f810..f4e8b6ada854 100644 --- a/trunk/drivers/net/wireless/zd1211rw/zd_rf_al7230b.c +++ b/trunk/drivers/net/wireless/zd1211rw/zd_rf_al7230b.c @@ -473,7 +473,7 @@ int zd_rf_init_al7230b(struct zd_rf *rf) { struct zd_chip *chip = zd_rf_to_chip(rf); - if (zd_chip_is_zd1211b(chip)) { + if (chip->is_zd1211b) { rf->init_hw = zd1211b_al7230b_init_hw; rf->switch_radio_on = zd1211b_al7230b_switch_radio_on; rf->set_channel = zd1211b_al7230b_set_channel; diff --git a/trunk/drivers/net/wireless/zd1211rw/zd_rf_rf2959.c b/trunk/drivers/net/wireless/zd1211rw/zd_rf_rf2959.c index cc70d40684ea..2d736bdf707c 100644 --- a/trunk/drivers/net/wireless/zd1211rw/zd_rf_rf2959.c +++ b/trunk/drivers/net/wireless/zd1211rw/zd_rf_rf2959.c @@ -265,7 +265,7 @@ int zd_rf_init_rf2959(struct zd_rf *rf) { struct zd_chip *chip = zd_rf_to_chip(rf); - if (zd_chip_is_zd1211b(chip)) { + if (chip->is_zd1211b) { dev_err(zd_chip_dev(chip), "RF2959 is currently not supported for ZD1211B" " devices\n"); diff --git a/trunk/drivers/net/wireless/zd1211rw/zd_rf_uw2453.c b/trunk/drivers/net/wireless/zd1211rw/zd_rf_uw2453.c index 857dcf3eae61..414e40d571ab 100644 --- a/trunk/drivers/net/wireless/zd1211rw/zd_rf_uw2453.c +++ b/trunk/drivers/net/wireless/zd1211rw/zd_rf_uw2453.c @@ -486,7 +486,7 @@ static int uw2453_switch_radio_on(struct zd_rf *rf) if (r) return r; - if (zd_chip_is_zd1211b(chip)) + if (chip->is_zd1211b) ioreqs[1].value = 0x7f; return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs)); diff --git a/trunk/drivers/net/wireless/zd1211rw/zd_usb.c b/trunk/drivers/net/wireless/zd1211rw/zd_usb.c index 28d41a29d7b1..ca24299a26c6 100644 --- a/trunk/drivers/net/wireless/zd1211rw/zd_usb.c +++ b/trunk/drivers/net/wireless/zd1211rw/zd_usb.c @@ -71,7 +71,6 @@ static struct usb_device_id usb_ids[] = { { USB_DEVICE(0x0586, 0x3412), .driver_info = DEVICE_ZD1211B }, { USB_DEVICE(0x0586, 0x3413), .driver_info = DEVICE_ZD1211B }, { USB_DEVICE(0x0053, 0x5301), .driver_info = DEVICE_ZD1211B }, - { USB_DEVICE(0x0411, 0x00da), .driver_info = DEVICE_ZD1211B }, /* "Driverless" devices that need ejecting */ { USB_DEVICE(0x0ace, 0x2011), .driver_info = DEVICE_INSTALLER }, { USB_DEVICE(0x0ace, 0x20ff), .driver_info = DEVICE_INSTALLER }, @@ -196,27 +195,26 @@ static u16 get_word(const void *data, u16 offset) return le16_to_cpu(p[offset]); } -static char *get_fw_name(struct zd_usb *usb, char *buffer, size_t size, +static char *get_fw_name(char *buffer, size_t size, u8 device_type, const char* postfix) { scnprintf(buffer, size, "%s%s", - usb->is_zd1211b ? + device_type == DEVICE_ZD1211B ? FW_ZD1211B_PREFIX : FW_ZD1211_PREFIX, postfix); return buffer; } -static int handle_version_mismatch(struct zd_usb *usb, +static int handle_version_mismatch(struct usb_device *udev, u8 device_type, const struct firmware *ub_fw) { - struct usb_device *udev = zd_usb_to_usbdev(usb); const struct firmware *ur_fw = NULL; int offset; int r = 0; char fw_name[128]; r = request_fw_file(&ur_fw, - get_fw_name(usb, fw_name, sizeof(fw_name), "ur"), + get_fw_name(fw_name, sizeof(fw_name), device_type, "ur"), &udev->dev); if (r) goto error; @@ -239,12 +237,11 @@ static int handle_version_mismatch(struct zd_usb *usb, return r; } -static int upload_firmware(struct zd_usb *usb) +static int upload_firmware(struct usb_device *udev, u8 device_type) { int r; u16 fw_bcdDevice; u16 bcdDevice; - struct usb_device *udev = zd_usb_to_usbdev(usb); const struct firmware *ub_fw = NULL; const struct firmware *uph_fw = NULL; char fw_name[128]; @@ -252,7 +249,7 @@ static int upload_firmware(struct zd_usb *usb) bcdDevice = get_bcdDevice(udev); r = request_fw_file(&ub_fw, - get_fw_name(usb, fw_name, sizeof(fw_name), "ub"), + get_fw_name(fw_name, sizeof(fw_name), device_type, "ub"), &udev->dev); if (r) goto error; @@ -267,7 +264,7 @@ static int upload_firmware(struct zd_usb *usb) dev_warn(&udev->dev, "device has old bootcode, please " "report success or failure\n"); - r = handle_version_mismatch(usb, ub_fw); + r = handle_version_mismatch(udev, device_type, ub_fw); if (r) goto error; } else { @@ -278,7 +275,7 @@ static int upload_firmware(struct zd_usb *usb) r = request_fw_file(&uph_fw, - get_fw_name(usb, fw_name, sizeof(fw_name), "uphr"), + get_fw_name(fw_name, sizeof(fw_name), device_type, "uphr"), &udev->dev); if (r) goto error; @@ -297,30 +294,6 @@ static int upload_firmware(struct zd_usb *usb) return r; } -/* Read data from device address space using "firmware interface" which does - * not require firmware to be loaded. */ -int zd_usb_read_fw(struct zd_usb *usb, zd_addr_t addr, u8 *data, u16 len) -{ - int r; - struct usb_device *udev = zd_usb_to_usbdev(usb); - - r = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), - USB_REQ_FIRMWARE_READ_DATA, USB_DIR_IN | 0x40, addr, 0, - data, len, 5000); - if (r < 0) { - dev_err(&udev->dev, - "read over firmware interface failed: %d\n", r); - return r; - } else if (r != len) { - dev_err(&udev->dev, - "incomplete read over firmware interface: %d/%d\n", - r, len); - return -EIO; - } - - return 0; -} - #define urb_dev(urb) (&(urb)->dev->dev) static inline void handle_regs_int(struct urb *urb) @@ -947,42 +920,9 @@ static int eject_installer(struct usb_interface *intf) return 0; } -int zd_usb_init_hw(struct zd_usb *usb) -{ - int r; - struct zd_mac *mac = zd_usb_to_mac(usb); - - dev_dbg_f(zd_usb_dev(usb), "\n"); - - r = upload_firmware(usb); - if (r) { - dev_err(zd_usb_dev(usb), - "couldn't load firmware. Error number %d\n", r); - return r; - } - - r = usb_reset_configuration(zd_usb_to_usbdev(usb)); - if (r) { - dev_dbg_f(zd_usb_dev(usb), - "couldn't reset configuration. Error number %d\n", r); - return r; - } - - r = zd_mac_init_hw(mac); - if (r) { - dev_dbg_f(zd_usb_dev(usb), - "couldn't initialize mac. Error number %d\n", r); - return r; - } - - usb->initialized = 1; - return 0; -} - static int probe(struct usb_interface *intf, const struct usb_device_id *id) { int r; - struct zd_usb *usb; struct usb_device *udev = interface_to_usbdev(intf); struct net_device *netdev = NULL; @@ -1010,10 +950,26 @@ static int probe(struct usb_interface *intf, const struct usb_device_id *id) goto error; } - usb = &zd_netdev_mac(netdev)->chip.usb; - usb->is_zd1211b = (id->driver_info == DEVICE_ZD1211B) != 0; + r = upload_firmware(udev, id->driver_info); + if (r) { + dev_err(&intf->dev, + "couldn't load firmware. Error number %d\n", r); + goto error; + } - r = zd_mac_preinit_hw(zd_netdev_mac(netdev)); + r = usb_reset_configuration(udev); + if (r) { + dev_dbg_f(&intf->dev, + "couldn't reset configuration. Error number %d\n", r); + goto error; + } + + /* At this point the interrupt endpoint is not generally enabled. We + * save the USB bandwidth until the network device is opened. But + * notify that the initialization of the MAC will require the + * interrupts to be temporary enabled. + */ + r = zd_mac_init_hw(zd_netdev_mac(netdev), id->driver_info); if (r) { dev_dbg_f(&intf->dev, "couldn't initialize mac. Error number %d\n", r); diff --git a/trunk/drivers/net/wireless/zd1211rw/zd_usb.h b/trunk/drivers/net/wireless/zd1211rw/zd_usb.h index 961a7a12ad68..506ea6a74393 100644 --- a/trunk/drivers/net/wireless/zd1211rw/zd_usb.h +++ b/trunk/drivers/net/wireless/zd1211rw/zd_usb.h @@ -188,7 +188,6 @@ struct zd_usb { struct zd_usb_rx rx; struct zd_usb_tx tx; struct usb_interface *intf; - u8 is_zd1211b:1, initialized:1; }; #define zd_usb_dev(usb) (&usb->intf->dev) @@ -237,8 +236,6 @@ int zd_usb_iowrite16v(struct zd_usb *usb, const struct zd_ioreq16 *ioreqs, int zd_usb_rfwrite(struct zd_usb *usb, u32 value, u8 bits); -int zd_usb_read_fw(struct zd_usb *usb, zd_addr_t addr, u8 *data, u16 len); - extern struct workqueue_struct *zd_workqueue; #endif /* _ZD_USB_H */ diff --git a/trunk/drivers/pci/hotplug/rpadlpar_core.c b/trunk/drivers/pci/hotplug/rpadlpar_core.c index deb6b5e35feb..bb3c101c2c5a 100644 --- a/trunk/drivers/pci/hotplug/rpadlpar_core.c +++ b/trunk/drivers/pci/hotplug/rpadlpar_core.c @@ -159,8 +159,8 @@ static void dlpar_pci_add_bus(struct device_node *dn) /* Claim new bus resources */ pcibios_claim_one_bus(dev->bus); - /* Map IO space for child bus, which may or may not succeed */ - pcibios_map_io_space(dev->subordinate); + /* ioremap() for child bus, which may or may not succeed */ + remap_bus_range(dev->subordinate); /* Add new devices to global lists. Register in proc, sysfs. */ pci_bus_add_devices(phb->bus); @@ -390,7 +390,7 @@ int dlpar_remove_pci_slot(char *drc_name, struct device_node *dn) } else pcibios_remove_pci_devices(bus); - if (pcibios_unmap_io_space(bus)) { + if (unmap_bus_range(bus)) { printk(KERN_ERR "%s: failed to unmap bus range\n", __FUNCTION__); return -ERANGE; diff --git a/trunk/drivers/pcmcia/Kconfig b/trunk/drivers/pcmcia/Kconfig index c0c77f82d051..35f88649d3b7 100644 --- a/trunk/drivers/pcmcia/Kconfig +++ b/trunk/drivers/pcmcia/Kconfig @@ -180,15 +180,14 @@ config TCIC PCMCIA cards are plugged into. If unsure, say N. config PCMCIA_M8XX - tristate "MPC8xx PCMCIA support" - depends on PCMCIA && PPC && 8xx - select PCCARD_IODYN - select PCCARD_NONSTATIC - help - Say Y here to include support for PowerPC 8xx series PCMCIA - controller. - - This driver is also available as a module called m8xx_pcmcia. + tristate "MPC8xx PCMCIA support" + depends on PCMCIA && PPC && 8xx + select PCCARD_IODYN + help + Say Y here to include support for PowerPC 8xx series PCMCIA + controller. + + This driver is also available as a module called m8xx_pcmcia. config HD64465_PCMCIA tristate "HD64465 host bridge support" diff --git a/trunk/drivers/pcmcia/m8xx_pcmcia.c b/trunk/drivers/pcmcia/m8xx_pcmcia.c index 3b40f9623cc9..9721ed7bf502 100644 --- a/trunk/drivers/pcmcia/m8xx_pcmcia.c +++ b/trunk/drivers/pcmcia/m8xx_pcmcia.c @@ -10,7 +10,7 @@ * Further fixes, v2.6 kernel port * * - * Some fixes, additions (C) 2005-2007 Montavista Software, Inc. + * Some fixes, additions (C) 2005 Montavista Software, Inc. * * * "The ExCA standard specifies that socket controllers should provide @@ -40,6 +40,10 @@ #include #include +#include +#include +#include + #include #include #include @@ -47,18 +51,11 @@ #include #include #include -#include +#include -#include -#include -#include -#include #include #include #include -#include -#include -#include #include #include @@ -149,17 +146,27 @@ MODULE_LICENSE("Dual MPL/GPL"); #define PCMCIA_MEM_WIN_BASE 0xe0000000 /* base address for memory window 0 */ #define PCMCIA_MEM_WIN_SIZE 0x04000000 /* each memory window is 64 MByte */ #define PCMCIA_IO_WIN_BASE _IO_BASE /* base address for io window 0 */ + +#define PCMCIA_SCHLVL PCMCIA_INTERRUPT /* Status Change Interrupt Level */ + /* ------------------------------------------------------------------------- */ -static int pcmcia_schlvl; +/* 2.4.x and newer has this always in HZ */ +#define M8XX_BUSFREQ ((((bd_t *)&(__res))->bi_busfreq)) + +static int pcmcia_schlvl = PCMCIA_SCHLVL; static DEFINE_SPINLOCK(events_lock); + #define PCMCIA_SOCKET_KEY_5V 1 #define PCMCIA_SOCKET_KEY_LV 2 /* look up table for pgcrx registers */ -static u32 *m8xx_pgcrx[2]; +static u32 *m8xx_pgcrx[2] = { + &((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pgcra, + &((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pgcrb +}; /* * This structure is used to address each window in the PCMCIA controller. @@ -221,16 +228,11 @@ struct event_table { u32 eventbit; }; -static const char driver_name[] = "m8xx-pcmcia"; - struct socket_info { void (*handler)(void *info, u32 events); void *info; u32 slot; - pcmconf8xx_t *pcmcia; - u32 bus_freq; - int hwirq; socket_state_t state; struct pccard_mem_map mem_win[PCMCIA_MEM_WIN_NO]; @@ -406,21 +408,78 @@ static void hardware_disable(int slot) #if defined(CONFIG_MPC885ADS) #define PCMCIA_BOARD_MSG "MPC885ADS" -#define socket_get(_slot_) PCMCIA_SOCKET_KEY_5V -static inline void hardware_enable(int slot) +static int voltage_set(int slot, int vcc, int vpp) { - m8xx_pcmcia_ops.hw_ctrl(slot, 1); + u32 reg = 0; + unsigned *bcsr_io; + + bcsr_io = ioremap(BCSR1, sizeof(unsigned long)); + + switch(vcc) { + case 0: + break; + case 33: + reg |= BCSR1_PCCVCC0; + break; + case 50: + reg |= BCSR1_PCCVCC1; + break; + default: + goto out_unmap; + } + + switch(vpp) { + case 0: + break; + case 33: + case 50: + if(vcc == vpp) + reg |= BCSR1_PCCVPP1; + else + goto out_unmap; + break; + case 120: + if ((vcc == 33) || (vcc == 50)) + reg |= BCSR1_PCCVPP0; + else + goto out_unmap; + default: + goto out_unmap; + } + + /* first, turn off all power */ + out_be32(bcsr_io, in_be32(bcsr_io) & ~(BCSR1_PCCVCC_MASK | BCSR1_PCCVPP_MASK)); + + /* enable new powersettings */ + out_be32(bcsr_io, in_be32(bcsr_io) | reg); + + iounmap(bcsr_io); + return 0; + +out_unmap: + iounmap(bcsr_io); + return 1; } -static inline void hardware_disable(int slot) +#define socket_get(_slot_) PCMCIA_SOCKET_KEY_5V + +static void hardware_enable(int slot) { - m8xx_pcmcia_ops.hw_ctrl(slot, 0); + unsigned *bcsr_io; + + bcsr_io = ioremap(BCSR1, sizeof(unsigned long)); + out_be32(bcsr_io, in_be32(bcsr_io) & ~BCSR1_PCCEN); + iounmap(bcsr_io); } -static inline int voltage_set(int slot, int vcc, int vpp) +static void hardware_disable(int slot) { - return m8xx_pcmcia_ops.voltage_set(slot, vcc, vpp); + unsigned *bcsr_io; + + bcsr_io = ioremap(BCSR1, sizeof(unsigned long)); + out_be32(bcsr_io, in_be32(bcsr_io) | BCSR1_PCCEN); + iounmap(bcsr_io); } #endif @@ -545,6 +604,48 @@ static int voltage_set(int slot, int vcc, int vpp) #endif /* CONFIG_PRxK */ +static void m8xx_shutdown(void) +{ + u32 m, i; + struct pcmcia_win *w; + + for(i = 0; i < PCMCIA_SOCKETS_NO; i++){ + w = (void *) &((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pbr0; + + out_be32(&((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pscr, M8XX_PCMCIA_MASK(i)); + out_be32(&((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_per, in_be32(&((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_per) & ~M8XX_PCMCIA_MASK(i)); + + /* turn off interrupt and disable CxOE */ + out_be32(M8XX_PGCRX(i), M8XX_PGCRX_CXOE); + + /* turn off memory windows */ + for(m = 0; m < PCMCIA_MEM_WIN_NO; m++) { + out_be32(&w->or, 0); /* set to not valid */ + w++; + } + + /* turn off voltage */ + voltage_set(i, 0, 0); + + /* disable external hardware */ + hardware_disable(i); + } + + free_irq(pcmcia_schlvl, NULL); +} + +static struct device_driver m8xx_driver = { + .name = "m8xx-pcmcia", + .bus = &platform_bus_type, + .suspend = pcmcia_socket_dev_suspend, + .resume = pcmcia_socket_dev_resume, +}; + +static struct platform_device m8xx_device = { + .name = "m8xx-pcmcia", + .id = 0, +}; + static u32 pending_events[PCMCIA_SOCKETS_NO]; static DEFINE_SPINLOCK(pending_event_lock); @@ -553,14 +654,13 @@ static irqreturn_t m8xx_interrupt(int irq, void *dev) struct socket_info *s; struct event_table *e; unsigned int i, events, pscr, pipr, per; - pcmconf8xx_t *pcmcia = socket[0].pcmcia; dprintk("Interrupt!\n"); /* get interrupt sources */ - pscr = in_be32(&pcmcia->pcmc_pscr); - pipr = in_be32(&pcmcia->pcmc_pipr); - per = in_be32(&pcmcia->pcmc_per); + pscr = in_be32(&((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pscr); + pipr = in_be32(&((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pipr); + per = in_be32(&((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_per); for(i = 0; i < PCMCIA_SOCKETS_NO; i++) { s = &socket[i]; @@ -624,7 +724,7 @@ static irqreturn_t m8xx_interrupt(int irq, void *dev) per &= ~M8XX_PCMCIA_RDY_L(0); per &= ~M8XX_PCMCIA_RDY_L(1); - out_be32(&pcmcia->pcmc_per, per); + out_be32(&((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_per, per); if (events) pcmcia_parse_events(&socket[i].socket, events); @@ -632,7 +732,7 @@ static irqreturn_t m8xx_interrupt(int irq, void *dev) } /* clear the interrupt sources */ - out_be32(&pcmcia->pcmc_pscr, pscr); + out_be32(&((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pscr, pscr); dprintk("Interrupt done.\n"); @@ -653,7 +753,7 @@ static u32 m8xx_get_graycode(u32 size) return k; } -static u32 m8xx_get_speed(u32 ns, u32 is_io, u32 bus_freq) +static u32 m8xx_get_speed(u32 ns, u32 is_io) { u32 reg, clocks, psst, psl, psht; @@ -681,7 +781,7 @@ static u32 m8xx_get_speed(u32 ns, u32 is_io, u32 bus_freq) #define ADJ 180 /* 80 % longer accesstime - to be sure */ - clocks = ((bus_freq / 1000) * ns) / 1000; + clocks = ((M8XX_BUSFREQ / 1000) * ns) / 1000; clocks = (clocks * ADJ) / (100*1000); if(clocks >= PCMCIA_BMT_LIMIT) { printk( "Max access time limit reached\n"); @@ -706,9 +806,8 @@ static int m8xx_get_status(struct pcmcia_socket *sock, unsigned int *value) int lsock = container_of(sock, struct socket_info, socket)->slot; struct socket_info *s = &socket[lsock]; unsigned int pipr, reg; - pcmconf8xx_t *pcmcia = s->pcmcia; - pipr = in_be32(&pcmcia->pcmc_pipr); + pipr = in_be32(&((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pipr); *value = ((pipr & (M8XX_PCMCIA_CD1(lsock) | M8XX_PCMCIA_CD2(lsock))) == 0) ? SS_DETECT : 0; @@ -819,7 +918,6 @@ static int m8xx_set_socket(struct pcmcia_socket *sock, socket_state_t *state) struct event_table *e; unsigned int reg; unsigned long flags; - pcmconf8xx_t *pcmcia = socket[0].pcmcia; dprintk( "SetSocket(%d, flags %#3.3x, Vcc %d, Vpp %d, " "io_irq %d, csc_mask %#2.2x)\n", lsock, state->flags, @@ -829,7 +927,6 @@ static int m8xx_set_socket(struct pcmcia_socket *sock, socket_state_t *state) if(voltage_set(lsock, state->Vcc, state->Vpp)) return -EINVAL; - /* Take care of reset... */ if(state->flags & SS_RESET) out_be32(M8XX_PGCRX(lsock), in_be32(M8XX_PGCRX(lsock)) | M8XX_PGCRX_CXRESET); /* active high */ @@ -885,8 +982,7 @@ static int m8xx_set_socket(struct pcmcia_socket *sock, socket_state_t *state) * If io_irq is non-zero we should enable irq. */ if(state->io_irq) { - out_be32(M8XX_PGCRX(lsock), - in_be32(M8XX_PGCRX(lsock)) | mk_int_int_mask(s->hwirq) << 24); + out_be32(M8XX_PGCRX(lsock), in_be32(M8XX_PGCRX(lsock)) | mk_int_int_mask(state->io_irq) << 24); /* * Strange thing here: * The manual does not tell us which interrupt @@ -931,7 +1027,7 @@ static int m8xx_set_socket(struct pcmcia_socket *sock, socket_state_t *state) * Writing ones will clear the bits. */ - out_be32(&pcmcia->pcmc_pscr, reg); + out_be32(&((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pscr, reg); /* * Write the mask. @@ -940,8 +1036,15 @@ static int m8xx_set_socket(struct pcmcia_socket *sock, socket_state_t *state) * Ones will enable the interrupt. */ - reg |= in_be32(&pcmcia->pcmc_per) & (M8XX_PCMCIA_MASK(0) | M8XX_PCMCIA_MASK(1)); - out_be32(&pcmcia->pcmc_per, reg); + /* + reg |= ((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_per + & M8XX_PCMCIA_MASK(lsock); + */ + + reg |= in_be32(&((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_per) & + (M8XX_PCMCIA_MASK(0) | M8XX_PCMCIA_MASK(1)); + + out_be32(&((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_per, reg); spin_unlock_irqrestore(&events_lock, flags); @@ -959,8 +1062,6 @@ static int m8xx_set_io_map(struct pcmcia_socket *sock, struct pccard_io_map *io) struct socket_info *s = &socket[lsock]; struct pcmcia_win *w; unsigned int reg, winnr; - pcmconf8xx_t *pcmcia = s->pcmcia; - #define M8XX_SIZE (io->stop - io->start + 1) #define M8XX_BASE (PCMCIA_IO_WIN_BASE + io->start) @@ -985,7 +1086,7 @@ static int m8xx_set_io_map(struct pcmcia_socket *sock, struct pccard_io_map *io) /* setup registers */ - w = (void *) &pcmcia->pcmc_pbr0; + w = (void *) &((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pbr0; w += winnr; out_be32(&w->or, 0); /* turn off window first */ @@ -994,13 +1095,12 @@ static int m8xx_set_io_map(struct pcmcia_socket *sock, struct pccard_io_map *io) reg <<= 27; reg |= M8XX_PCMCIA_POR_IO |(lsock << 2); - reg |= m8xx_get_speed(io->speed, 1, s->bus_freq); + reg |= m8xx_get_speed(io->speed, 1); if(io->flags & MAP_WRPROT) reg |= M8XX_PCMCIA_POR_WRPROT; - /*if(io->flags & (MAP_16BIT | MAP_AUTOSZ))*/ - if(io->flags & MAP_16BIT) + if(io->flags & (MAP_16BIT | MAP_AUTOSZ)) reg |= M8XX_PCMCIA_POR_16BIT; if(io->flags & MAP_ACTIVE) @@ -1017,7 +1117,7 @@ static int m8xx_set_io_map(struct pcmcia_socket *sock, struct pccard_io_map *io) /* setup registers */ - w = (void *) &pcmcia->pcmc_pbr0; + w = (void *) &((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pbr0; w += winnr; out_be32(&w->or, 0); /* turn off window */ @@ -1044,7 +1144,6 @@ static int m8xx_set_mem_map(struct pcmcia_socket *sock, struct pccard_mem_map *m struct pcmcia_win *w; struct pccard_mem_map *old; unsigned int reg, winnr; - pcmconf8xx_t *pcmcia = s->pcmcia; dprintk( "SetMemMap(%d, %d, %#2.2x, %d ns, " "%#5.5lx, %#5.5x)\n", lsock, mem->map, mem->flags, @@ -1067,12 +1166,12 @@ static int m8xx_set_mem_map(struct pcmcia_socket *sock, struct pccard_mem_map *m /* Setup the window in the pcmcia controller */ - w = (void *) &pcmcia->pcmc_pbr0; + w = (void *) &((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pbr0; w += winnr; reg |= lsock << 2; - reg |= m8xx_get_speed(mem->speed, 0, s->bus_freq); + reg |= m8xx_get_speed(mem->speed, 0); if(mem->flags & MAP_ATTRIB) reg |= M8XX_PCMCIA_POR_ATTRMEM; @@ -1137,69 +1236,60 @@ static int m8xx_sock_init(struct pcmcia_socket *sock) } -static int m8xx_sock_suspend(struct pcmcia_socket *sock) +static int m8xx_suspend(struct pcmcia_socket *sock) { return m8xx_set_socket(sock, &dead_socket); } static struct pccard_operations m8xx_services = { .init = m8xx_sock_init, - .suspend = m8xx_sock_suspend, + .suspend = m8xx_suspend, .get_status = m8xx_get_status, .set_socket = m8xx_set_socket, .set_io_map = m8xx_set_io_map, .set_mem_map = m8xx_set_mem_map, }; -static int __init m8xx_probe(struct of_device *ofdev, const struct of_device_id *match) +static int __init m8xx_init(void) { struct pcmcia_win *w; - unsigned int i, m, hwirq; - pcmconf8xx_t *pcmcia; - int status; - struct device_node *np = ofdev->node; + unsigned int i,m; pcmcia_info("%s\n", version); - pcmcia = of_iomap(np, 0); - if(pcmcia == NULL) - return -EINVAL; - - pcmcia_schlvl = irq_of_parse_and_map(np, 0); - hwirq = irq_map[pcmcia_schlvl].hwirq; - if (pcmcia_schlvl < 0) - return -EINVAL; - - m8xx_pgcrx[0] = &pcmcia->pcmc_pgcra; - m8xx_pgcrx[1] = &pcmcia->pcmc_pgcrb; - + if (driver_register(&m8xx_driver)) + return -1; pcmcia_info(PCMCIA_BOARD_MSG " using " PCMCIA_SLOT_MSG - " with IRQ %u (%d). \n", pcmcia_schlvl, hwirq); + " with IRQ %u.\n", pcmcia_schlvl); /* Configure Status change interrupt */ - if(request_irq(pcmcia_schlvl, m8xx_interrupt, IRQF_SHARED, - driver_name, socket)) { + if(request_irq(pcmcia_schlvl, m8xx_interrupt, 0, + "m8xx_pcmcia", NULL)) { pcmcia_error("Cannot allocate IRQ %u for SCHLVL!\n", pcmcia_schlvl); return -1; } - w = (void *) &pcmcia->pcmc_pbr0; + w = (void *) &((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pbr0; + + out_be32(&((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pscr, + M8XX_PCMCIA_MASK(0)| M8XX_PCMCIA_MASK(1)); - out_be32(&pcmcia->pcmc_pscr, M8XX_PCMCIA_MASK(0)| M8XX_PCMCIA_MASK(1)); - clrbits32(&pcmcia->pcmc_per, M8XX_PCMCIA_MASK(0) | M8XX_PCMCIA_MASK(1)); + out_be32(&((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_per, + in_be32(&((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_per) & + ~(M8XX_PCMCIA_MASK(0)| M8XX_PCMCIA_MASK(1))); - /* connect interrupt and disable CxOE */ +/* connect interrupt and disable CxOE */ - out_be32(M8XX_PGCRX(0), M8XX_PGCRX_CXOE | (mk_int_int_mask(hwirq) << 16)); - out_be32(M8XX_PGCRX(1), M8XX_PGCRX_CXOE | (mk_int_int_mask(hwirq) << 16)); + out_be32(M8XX_PGCRX(0), M8XX_PGCRX_CXOE | (mk_int_int_mask(pcmcia_schlvl) << 16)); + out_be32(M8XX_PGCRX(1), M8XX_PGCRX_CXOE | (mk_int_int_mask(pcmcia_schlvl) << 16)); - /* intialize the fixed memory windows */ +/* intialize the fixed memory windows */ for(i = 0; i < PCMCIA_SOCKETS_NO; i++){ - for (m = 0; m < PCMCIA_MEM_WIN_NO; m++) { + for(m = 0; m < PCMCIA_MEM_WIN_NO; m++) { out_be32(&w->br, PCMCIA_MEM_WIN_BASE + (PCMCIA_MEM_WIN_SIZE * (m + i * PCMCIA_MEM_WIN_NO))); @@ -1210,14 +1300,16 @@ static int __init m8xx_probe(struct of_device *ofdev, const struct of_device_id } } - /* turn off voltage */ +/* turn off voltage */ voltage_set(0, 0, 0); voltage_set(1, 0, 0); - /* Enable external hardware */ +/* Enable external hardware */ hardware_enable(0); hardware_enable(1); + platform_device_register(&m8xx_device); + for (i = 0 ; i < PCMCIA_SOCKETS_NO; i++) { socket[i].slot = i; socket[i].socket.owner = THIS_MODULE; @@ -1225,105 +1317,30 @@ static int __init m8xx_probe(struct of_device *ofdev, const struct of_device_id socket[i].socket.irq_mask = 0x000; socket[i].socket.map_size = 0x1000; socket[i].socket.io_offset = 0; - socket[i].socket.pci_irq = pcmcia_schlvl; + socket[i].socket.pci_irq = i ? 7 : 9; socket[i].socket.ops = &m8xx_services; - socket[i].socket.resource_ops = &pccard_nonstatic_ops; + socket[i].socket.resource_ops = &pccard_iodyn_ops; socket[i].socket.cb_dev = NULL; - socket[i].socket.dev.parent = &ofdev->dev; - socket[i].pcmcia = pcmcia; - socket[i].bus_freq = ppc_proc_freq; - socket[i].hwirq = hwirq; - - + socket[i].socket.dev.parent = &m8xx_device.dev; } - for (i = 0; i < PCMCIA_SOCKETS_NO; i++) { - status = pcmcia_register_socket(&socket[i].socket); - if (status < 0) - pcmcia_error("Socket register failed\n"); - } + for (i = 0; i < PCMCIA_SOCKETS_NO; i++) + pcmcia_register_socket(&socket[i].socket); return 0; } -static int m8xx_remove(struct of_device* ofdev) +static void __exit m8xx_exit(void) { - u32 m, i; - struct pcmcia_win *w; - pcmconf8xx_t *pcmcia = socket[0].pcmcia; - - for (i = 0; i < PCMCIA_SOCKETS_NO; i++) { - w = (void *) &pcmcia->pcmc_pbr0; - - out_be32(&pcmcia->pcmc_pscr, M8XX_PCMCIA_MASK(i)); - out_be32(&pcmcia->pcmc_per, - in_be32(&pcmcia->pcmc_per) & ~M8XX_PCMCIA_MASK(i)); - - /* turn off interrupt and disable CxOE */ - out_be32(M8XX_PGCRX(i), M8XX_PGCRX_CXOE); - - /* turn off memory windows */ - for (m = 0; m < PCMCIA_MEM_WIN_NO; m++) { - out_be32(&w->or, 0); /* set to not valid */ - w++; - } - - /* turn off voltage */ - voltage_set(i, 0, 0); + int i; - /* disable external hardware */ - hardware_disable(i); - } for (i = 0; i < PCMCIA_SOCKETS_NO; i++) pcmcia_unregister_socket(&socket[i].socket); - free_irq(pcmcia_schlvl, NULL); + m8xx_shutdown(); - return 0; -} - -#ifdef CONFIG_PM -static int m8xx_suspend(struct platform_device *pdev, pm_message_t state) -{ - return pcmcia_socket_dev_suspend(&pdev->dev, state); -} - -static int m8xx_resume(struct platform_device *pdev) -{ - return pcmcia_socket_dev_resume(&pdev->dev); -} -#else -#define m8xx_suspend NULL -#define m8xx_resume NULL -#endif - -static struct of_device_id m8xx_pcmcia_match[] = { - { - .type = "pcmcia", - .compatible = "fsl,pq-pcmcia", - }, - {}, -}; - -MODULE_DEVICE_TABLE(of, m8xx_pcmcia_match); - -static struct of_platform_driver m8xx_pcmcia_driver = { - .name = (char *) driver_name, - .match_table = m8xx_pcmcia_match, - .probe = m8xx_probe, - .remove = m8xx_remove, - .suspend = m8xx_suspend, - .resume = m8xx_resume, -}; - -static int __init m8xx_init(void) -{ - return of_register_platform_driver(&m8xx_pcmcia_driver); -} - -static void __exit m8xx_exit(void) -{ - of_unregister_platform_driver(&m8xx_pcmcia_driver); + platform_device_unregister(&m8xx_device); + driver_unregister(&m8xx_driver); } module_init(m8xx_init); diff --git a/trunk/drivers/ps3/Makefile b/trunk/drivers/ps3/Makefile index 746031de2195..e251d1c1171c 100644 --- a/trunk/drivers/ps3/Makefile +++ b/trunk/drivers/ps3/Makefile @@ -1,6 +1,3 @@ obj-$(CONFIG_PS3_VUART) += vuart.o -obj-$(CONFIG_PS3_PS3AV) += ps3av_mod.o -ps3av_mod-objs += ps3av.o ps3av_cmd.o -obj-$(CONFIG_PPC_PS3) += sys-manager-core.o +obj-$(CONFIG_PS3_PS3AV) += ps3av.o ps3av_cmd.o obj-$(CONFIG_PS3_SYS_MANAGER) += sys-manager.o -obj-$(CONFIG_PS3_STORAGE) += ps3stor_lib.o diff --git a/trunk/drivers/ps3/ps3av.c b/trunk/drivers/ps3/ps3av.c index 85e21614f868..1393e64335f9 100644 --- a/trunk/drivers/ps3/ps3av.c +++ b/trunk/drivers/ps3/ps3av.c @@ -1,30 +1,32 @@ /* - * PS3 AV backend support. + * Copyright (C) 2006 Sony Computer Entertainment Inc. + * Copyright 2006, 2007 Sony Corporation * - * Copyright (C) 2007 Sony Computer Entertainment Inc. - * Copyright 2007 Sony Corp. + * AV backend support for PS3 * - * 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; version 2 of the License. + * 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; version 2 of the License. * - * 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. + * 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 + * 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 Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#include #include #include #include +#include +#include #include #include +#include #include #include @@ -37,12 +39,13 @@ static int timeout = 5000; /* in msec ( 5 sec ) */ module_param(timeout, int, 0644); static struct ps3av { + int available; struct mutex mutex; struct work_struct work; struct completion done; struct workqueue_struct *wq; int open_count; - struct ps3_system_bus_device *dev; + struct ps3_vuart_port_device *dev; int region; struct ps3av_pkt_av_get_hw_conf av_hw_conf; @@ -52,13 +55,11 @@ static struct ps3av { u32 audio_port; int ps3av_mode; int ps3av_mode_old; - union { - struct ps3av_reply_hdr reply_hdr; - u8 raw[PS3AV_BUF_SIZE]; - } recv_buf; - void (*flip_ctl)(int on, void *data); - void *flip_data; -} *ps3av; +} ps3av; + +static struct ps3_vuart_port_device ps3av_dev = { + .match_id = PS3_MATCH_ID_AV_SETTINGS +}; /* color space */ #define YUV444 PS3AV_CMD_VIDEO_CS_YUV444_8 @@ -168,7 +169,7 @@ static int ps3av_parse_event_packet(const struct ps3av_reply_hdr *hdr) if (hdr->cid & PS3AV_EVENT_CMD_MASK) { table = ps3av_search_cmd_table(hdr->cid, PS3AV_EVENT_CMD_MASK); if (table) - dev_dbg(&ps3av->dev->core, + dev_dbg(&ps3av_dev.core, "recv event packet cid:%08x port:0x%x size:%d\n", hdr->cid, ps3av_event_get_port_id(hdr->cid), hdr->size); @@ -181,41 +182,6 @@ static int ps3av_parse_event_packet(const struct ps3av_reply_hdr *hdr) return 0; } - -#define POLLING_INTERVAL 25 /* in msec */ - -static int ps3av_vuart_write(struct ps3_system_bus_device *dev, - const void *buf, unsigned long size) -{ - int error; - dev_dbg(&dev->core, " -> %s:%d\n", __func__, __LINE__); - error = ps3_vuart_write(dev, buf, size); - dev_dbg(&dev->core, " <- %s:%d\n", __func__, __LINE__); - return error ? error : size; -} - -static int ps3av_vuart_read(struct ps3_system_bus_device *dev, void *buf, - unsigned long size, int timeout) -{ - int error; - int loopcnt = 0; - - dev_dbg(&dev->core, " -> %s:%d\n", __func__, __LINE__); - timeout = (timeout + POLLING_INTERVAL - 1) / POLLING_INTERVAL; - while (loopcnt++ <= timeout) { - error = ps3_vuart_read(dev, buf, size); - if (!error) - return size; - if (error != -EAGAIN) { - printk(KERN_ERR "%s: ps3_vuart_read failed %d\n", - __func__, error); - return error; - } - msleep(POLLING_INTERVAL); - } - return -EWOULDBLOCK; -} - static int ps3av_send_cmd_pkt(const struct ps3av_send_hdr *send_buf, struct ps3av_reply_hdr *recv_buf, int write_len, int read_len) @@ -224,13 +190,13 @@ static int ps3av_send_cmd_pkt(const struct ps3av_send_hdr *send_buf, u32 cmd; int event; - if (!ps3av) + if (!ps3av.available) return -ENODEV; /* send pkt */ - res = ps3av_vuart_write(ps3av->dev, send_buf, write_len); + res = ps3av_vuart_write(ps3av.dev, send_buf, write_len); if (res < 0) { - dev_dbg(&ps3av->dev->core, + dev_dbg(&ps3av_dev.core, "%s: ps3av_vuart_write() failed (result=%d)\n", __func__, res); return res; @@ -240,20 +206,20 @@ static int ps3av_send_cmd_pkt(const struct ps3av_send_hdr *send_buf, cmd = send_buf->cid; do { /* read header */ - res = ps3av_vuart_read(ps3av->dev, recv_buf, PS3AV_HDR_SIZE, + res = ps3av_vuart_read(ps3av.dev, recv_buf, PS3AV_HDR_SIZE, timeout); if (res != PS3AV_HDR_SIZE) { - dev_dbg(&ps3av->dev->core, + dev_dbg(&ps3av_dev.core, "%s: ps3av_vuart_read() failed (result=%d)\n", __func__, res); return res; } /* read body */ - res = ps3av_vuart_read(ps3av->dev, &recv_buf->cid, + res = ps3av_vuart_read(ps3av.dev, &recv_buf->cid, recv_buf->size, timeout); if (res < 0) { - dev_dbg(&ps3av->dev->core, + dev_dbg(&ps3av_dev.core, "%s: ps3av_vuart_read() failed (result=%d)\n", __func__, res); return res; @@ -264,7 +230,7 @@ static int ps3av_send_cmd_pkt(const struct ps3av_send_hdr *send_buf, } while (event); if ((cmd | PS3AV_REPLY_BIT) != recv_buf->cid) { - dev_dbg(&ps3av->dev->core, "%s: reply err (result=%x)\n", + dev_dbg(&ps3av_dev.core, "%s: reply err (result=%x)\n", __func__, recv_buf->cid); return -EINVAL; } @@ -279,7 +245,7 @@ static int ps3av_process_reply_packet(struct ps3av_send_hdr *cmd_buf, int return_len; if (recv_buf->version != PS3AV_VERSION) { - dev_dbg(&ps3av->dev->core, "reply_packet invalid version:%x\n", + dev_dbg(&ps3av_dev.core, "reply_packet invalid version:%x\n", recv_buf->version); return -EFAULT; } @@ -301,11 +267,16 @@ int ps3av_do_pkt(u32 cid, u16 send_len, size_t usr_buf_size, struct ps3av_send_hdr *buf) { int res = 0; + static union { + struct ps3av_reply_hdr reply_hdr; + u8 raw[PS3AV_BUF_SIZE]; + } recv_buf; + u32 *table; - BUG_ON(!ps3av); + BUG_ON(!ps3av.available); - mutex_lock(&ps3av->mutex); + mutex_lock(&ps3av.mutex); table = ps3av_search_cmd_table(cid, PS3AV_CID_MASK); BUG_ON(!table); @@ -317,7 +288,7 @@ int ps3av_do_pkt(u32 cid, u16 send_len, size_t usr_buf_size, ps3av_set_hdr(cid, send_len, buf); /* send packet via vuart */ - res = ps3av_send_cmd_pkt(buf, &ps3av->recv_buf.reply_hdr, send_len, + res = ps3av_send_cmd_pkt(buf, &recv_buf.reply_hdr, send_len, usr_buf_size); if (res < 0) { printk(KERN_ERR @@ -327,7 +298,7 @@ int ps3av_do_pkt(u32 cid, u16 send_len, size_t usr_buf_size, } /* process reply packet */ - res = ps3av_process_reply_packet(buf, &ps3av->recv_buf.reply_hdr, + res = ps3av_process_reply_packet(buf, &recv_buf.reply_hdr, usr_buf_size); if (res < 0) { printk(KERN_ERR "%s: put_return_status() failed (result=%d)\n", @@ -335,11 +306,11 @@ int ps3av_do_pkt(u32 cid, u16 send_len, size_t usr_buf_size, goto err; } - mutex_unlock(&ps3av->mutex); + mutex_unlock(&ps3av.mutex); return 0; err: - mutex_unlock(&ps3av->mutex); + mutex_unlock(&ps3av.mutex); printk(KERN_ERR "%s: failed cid:%x res:%d\n", __func__, cid, res); return res; } @@ -348,11 +319,11 @@ static int ps3av_set_av_video_mute(u32 mute) { int i, num_of_av_port, res; - num_of_av_port = ps3av->av_hw_conf.num_of_hdmi + - ps3av->av_hw_conf.num_of_avmulti; + num_of_av_port = ps3av.av_hw_conf.num_of_hdmi + + ps3av.av_hw_conf.num_of_avmulti; /* video mute on */ for (i = 0; i < num_of_av_port; i++) { - res = ps3av_cmd_av_video_mute(1, &ps3av->av_port[i], mute); + res = ps3av_cmd_av_video_mute(1, &ps3av.av_port[i], mute); if (res < 0) return -1; } @@ -364,13 +335,13 @@ static int ps3av_set_video_disable_sig(void) { int i, num_of_hdmi_port, num_of_av_port, res; - num_of_hdmi_port = ps3av->av_hw_conf.num_of_hdmi; - num_of_av_port = ps3av->av_hw_conf.num_of_hdmi + - ps3av->av_hw_conf.num_of_avmulti; + num_of_hdmi_port = ps3av.av_hw_conf.num_of_hdmi; + num_of_av_port = ps3av.av_hw_conf.num_of_hdmi + + ps3av.av_hw_conf.num_of_avmulti; /* tv mute */ for (i = 0; i < num_of_hdmi_port; i++) { - res = ps3av_cmd_av_tv_mute(ps3av->av_port[i], + res = ps3av_cmd_av_tv_mute(ps3av.av_port[i], PS3AV_CMD_MUTE_ON); if (res < 0) return -1; @@ -379,11 +350,11 @@ static int ps3av_set_video_disable_sig(void) /* video mute on */ for (i = 0; i < num_of_av_port; i++) { - res = ps3av_cmd_av_video_disable_sig(ps3av->av_port[i]); + res = ps3av_cmd_av_video_disable_sig(ps3av.av_port[i]); if (res < 0) return -1; if (i < num_of_hdmi_port) { - res = ps3av_cmd_av_tv_mute(ps3av->av_port[i], + res = ps3av_cmd_av_tv_mute(ps3av.av_port[i], PS3AV_CMD_MUTE_OFF); if (res < 0) return -1; @@ -398,17 +369,17 @@ static int ps3av_set_audio_mute(u32 mute) { int i, num_of_av_port, num_of_opt_port, res; - num_of_av_port = ps3av->av_hw_conf.num_of_hdmi + - ps3av->av_hw_conf.num_of_avmulti; - num_of_opt_port = ps3av->av_hw_conf.num_of_spdif; + num_of_av_port = ps3av.av_hw_conf.num_of_hdmi + + ps3av.av_hw_conf.num_of_avmulti; + num_of_opt_port = ps3av.av_hw_conf.num_of_spdif; for (i = 0; i < num_of_av_port; i++) { - res = ps3av_cmd_av_audio_mute(1, &ps3av->av_port[i], mute); + res = ps3av_cmd_av_audio_mute(1, &ps3av.av_port[i], mute); if (res < 0) return -1; } for (i = 0; i < num_of_opt_port; i++) { - res = ps3av_cmd_audio_mute(1, &ps3av->opt_port[i], mute); + res = ps3av_cmd_audio_mute(1, &ps3av.opt_port[i], mute); if (res < 0) return -1; } @@ -423,40 +394,40 @@ int ps3av_set_audio_mode(u32 ch, u32 fs, u32 word_bits, u32 format, u32 source) struct ps3av_pkt_audio_mode audio_mode; u32 len = 0; - num_of_audio = ps3av->av_hw_conf.num_of_hdmi + - ps3av->av_hw_conf.num_of_avmulti + - ps3av->av_hw_conf.num_of_spdif; + num_of_audio = ps3av.av_hw_conf.num_of_hdmi + + ps3av.av_hw_conf.num_of_avmulti + + ps3av.av_hw_conf.num_of_spdif; avb_param.num_of_video_pkt = 0; avb_param.num_of_audio_pkt = PS3AV_AVB_NUM_AUDIO; /* always 0 */ avb_param.num_of_av_video_pkt = 0; - avb_param.num_of_av_audio_pkt = ps3av->av_hw_conf.num_of_hdmi; + avb_param.num_of_av_audio_pkt = ps3av.av_hw_conf.num_of_hdmi; - vid = video_mode_table[ps3av->ps3av_mode].vid; + vid = video_mode_table[ps3av.ps3av_mode].vid; /* audio mute */ ps3av_set_audio_mute(PS3AV_CMD_MUTE_ON); /* audio inactive */ - res = ps3av_cmd_audio_active(0, ps3av->audio_port); + res = ps3av_cmd_audio_active(0, ps3av.audio_port); if (res < 0) - dev_dbg(&ps3av->dev->core, + dev_dbg(&ps3av_dev.core, "ps3av_cmd_audio_active OFF failed\n"); /* audio_pkt */ for (i = 0; i < num_of_audio; i++) { - ps3av_cmd_set_audio_mode(&audio_mode, ps3av->av_port[i], ch, - fs, word_bits, format, source); - if (i < ps3av->av_hw_conf.num_of_hdmi) { + ps3av_cmd_set_audio_mode(&audio_mode, ps3av.av_port[i], ch, fs, + word_bits, format, source); + if (i < ps3av.av_hw_conf.num_of_hdmi) { /* hdmi only */ len += ps3av_cmd_set_av_audio_param(&avb_param.buf[len], - ps3av->av_port[i], + ps3av.av_port[i], &audio_mode, vid); } /* audio_mode pkt should be sent separately */ res = ps3av_cmd_audio_mode(&audio_mode); if (res < 0) - dev_dbg(&ps3av->dev->core, + dev_dbg(&ps3av_dev.core, "ps3av_cmd_audio_mode failed, port:%x\n", i); } @@ -464,16 +435,15 @@ int ps3av_set_audio_mode(u32 ch, u32 fs, u32 word_bits, u32 format, u32 source) len += offsetof(struct ps3av_pkt_avb_param, buf); res = ps3av_cmd_avb_param(&avb_param, len); if (res < 0) - dev_dbg(&ps3av->dev->core, "ps3av_cmd_avb_param failed\n"); + dev_dbg(&ps3av_dev.core, "ps3av_cmd_avb_param failed\n"); /* audio mute */ ps3av_set_audio_mute(PS3AV_CMD_MUTE_OFF); /* audio active */ - res = ps3av_cmd_audio_active(1, ps3av->audio_port); + res = ps3av_cmd_audio_active(1, ps3av.audio_port); if (res < 0) - dev_dbg(&ps3av->dev->core, - "ps3av_cmd_audio_active ON failed\n"); + dev_dbg(&ps3av_dev.core, "ps3av_cmd_audio_active ON failed\n"); return 0; } @@ -486,7 +456,7 @@ static int ps3av_set_videomode(void) ps3av_set_av_video_mute(PS3AV_CMD_MUTE_ON); /* wake up ps3avd to do the actual video mode setting */ - queue_work(ps3av->wq, &ps3av->work); + queue_work(ps3av.wq, &ps3av.work); return 0; } @@ -503,8 +473,8 @@ static void ps3av_set_videomode_cont(u32 id, u32 old_id) avb_param.num_of_video_pkt = PS3AV_AVB_NUM_VIDEO; /* num of head */ avb_param.num_of_audio_pkt = 0; - avb_param.num_of_av_video_pkt = ps3av->av_hw_conf.num_of_hdmi + - ps3av->av_hw_conf.num_of_avmulti; + avb_param.num_of_av_video_pkt = ps3av.av_hw_conf.num_of_hdmi + + ps3av.av_hw_conf.num_of_avmulti; avb_param.num_of_av_audio_pkt = 0; /* video signal off */ @@ -514,21 +484,21 @@ static void ps3av_set_videomode_cont(u32 id, u32 old_id) if (id & PS3AV_MODE_HDCP_OFF) { res = ps3av_cmd_av_hdmi_mode(PS3AV_CMD_AV_HDMI_HDCP_OFF); if (res == PS3AV_STATUS_UNSUPPORTED_HDMI_MODE) - dev_dbg(&ps3av->dev->core, "Not supported\n"); + dev_dbg(&ps3av_dev.core, "Not supported\n"); else if (res) - dev_dbg(&ps3av->dev->core, + dev_dbg(&ps3av_dev.core, "ps3av_cmd_av_hdmi_mode failed\n"); } else if (old_id & PS3AV_MODE_HDCP_OFF) { res = ps3av_cmd_av_hdmi_mode(PS3AV_CMD_AV_HDMI_MODE_NORMAL); if (res < 0 && res != PS3AV_STATUS_UNSUPPORTED_HDMI_MODE) - dev_dbg(&ps3av->dev->core, + dev_dbg(&ps3av_dev.core, "ps3av_cmd_av_hdmi_mode failed\n"); } /* video_pkt */ for (i = 0; i < avb_param.num_of_video_pkt; i++) len += ps3av_cmd_set_video_mode(&avb_param.buf[len], - ps3av->head[i], video_mode->vid, + ps3av.head[i], video_mode->vid, video_mode->fmt, id); /* av_video_pkt */ for (i = 0; i < avb_param.num_of_av_video_pkt; i++) { @@ -537,12 +507,12 @@ static void ps3av_set_videomode_cont(u32 id, u32 old_id) else av_video_cs = video_mode->cs; #ifndef PS3AV_HDMI_YUV - if (ps3av->av_port[i] == PS3AV_CMD_AVPORT_HDMI_0 || - ps3av->av_port[i] == PS3AV_CMD_AVPORT_HDMI_1) + if (ps3av.av_port[i] == PS3AV_CMD_AVPORT_HDMI_0 || + ps3av.av_port[i] == PS3AV_CMD_AVPORT_HDMI_1) av_video_cs = RGB8; /* use RGB for HDMI */ #endif len += ps3av_cmd_set_av_video_cs(&avb_param.buf[len], - ps3av->av_port[i], + ps3av.av_port[i], video_mode->vid, av_video_cs, video_mode->aspect, id); } @@ -554,7 +524,7 @@ static void ps3av_set_videomode_cont(u32 id, u32 old_id) "%s: Command failed. Please try your request again. \n", __func__); else if (res) - dev_dbg(&ps3av->dev->core, "ps3av_cmd_avb_param failed\n"); + dev_dbg(&ps3av_dev.core, "ps3av_cmd_avb_param failed\n"); msleep(1500); /* av video mute */ @@ -563,8 +533,8 @@ static void ps3av_set_videomode_cont(u32 id, u32 old_id) static void ps3avd(struct work_struct *work) { - ps3av_set_videomode_cont(ps3av->ps3av_mode, ps3av->ps3av_mode_old); - complete(&ps3av->done); + ps3av_set_videomode_cont(ps3av.ps3av_mode, ps3av.ps3av_mode_old); + complete(&ps3av.done); } static int ps3av_vid2table_id(int vid) @@ -631,7 +601,7 @@ static int ps3av_hdmi_get_vid(struct ps3av_info_monitor *info) return vid; } - if (ps3av->region & PS3AV_REGION_60) + if (ps3av.region & PS3AV_REGION_60) vid = PS3AV_DEFAULT_HDMI_VID_REG_60; else vid = PS3AV_DEFAULT_HDMI_VID_REG_50; @@ -673,16 +643,16 @@ static int ps3av_auto_videomode(struct ps3av_pkt_av_get_hw_conf *av_hw_conf, vid = PS3AV_DEFAULT_DVI_VID; } else if (vid == -1) { /* no HDMI interface or HDMI is off */ - if (ps3av->region & PS3AV_REGION_60) + if (ps3av.region & PS3AV_REGION_60) vid = PS3AV_DEFAULT_AVMULTI_VID_REG_60; else vid = PS3AV_DEFAULT_AVMULTI_VID_REG_50; - if (ps3av->region & PS3AV_REGION_RGB) + if (ps3av.region & PS3AV_REGION_RGB) rgb = PS3AV_MODE_RGB; } else if (boot) { /* HDMI: using DEFAULT HDMI_VID while booting up */ info = &monitor_info.info; - if (ps3av->region & PS3AV_REGION_60) { + if (ps3av.region & PS3AV_REGION_60) { if (info->res_60.res_bits & PS3AV_RESBIT_720x480P) vid = PS3AV_DEFAULT_HDMI_VID_REG_60; else if (info->res_50.res_bits & PS3AV_RESBIT_720x576P) @@ -745,14 +715,14 @@ int ps3av_set_video_mode(u32 id, int boot) size = ARRAY_SIZE(video_mode_table); if ((id & PS3AV_MODE_MASK) > size - 1 || id < 0) { - dev_dbg(&ps3av->dev->core, "%s: error id :%d\n", __func__, id); + dev_dbg(&ps3av_dev.core, "%s: error id :%d\n", __func__, id); return -EINVAL; } /* auto mode */ option = id & ~PS3AV_MODE_MASK; if ((id & PS3AV_MODE_MASK) == 0) { - id = ps3av_auto_videomode(&ps3av->av_hw_conf, boot); + id = ps3av_auto_videomode(&ps3av.av_hw_conf, boot); if (id < 1) { printk(KERN_ERR "%s: invalid id :%d\n", __func__, id); return -EINVAL; @@ -761,11 +731,11 @@ int ps3av_set_video_mode(u32 id, int boot) } /* set videomode */ - wait_for_completion(&ps3av->done); - ps3av->ps3av_mode_old = ps3av->ps3av_mode; - ps3av->ps3av_mode = id; + wait_for_completion(&ps3av.done); + ps3av.ps3av_mode_old = ps3av.ps3av_mode; + ps3av.ps3av_mode = id; if (ps3av_set_videomode()) - ps3av->ps3av_mode = ps3av->ps3av_mode_old; + ps3av.ps3av_mode = ps3av.ps3av_mode_old; return 0; } @@ -774,7 +744,7 @@ EXPORT_SYMBOL_GPL(ps3av_set_video_mode); int ps3av_get_auto_mode(int boot) { - return ps3av_auto_videomode(&ps3av->av_hw_conf, boot); + return ps3av_auto_videomode(&ps3av.av_hw_conf, boot); } EXPORT_SYMBOL_GPL(ps3av_get_auto_mode); @@ -802,7 +772,7 @@ EXPORT_SYMBOL_GPL(ps3av_set_mode); int ps3av_get_mode(void) { - return ps3av ? ps3av->ps3av_mode : 0; + return ps3av.ps3av_mode; } EXPORT_SYMBOL_GPL(ps3av_get_mode); @@ -872,65 +842,82 @@ int ps3av_audio_mute(int mute) EXPORT_SYMBOL_GPL(ps3av_audio_mute); -void ps3av_register_flip_ctl(void (*flip_ctl)(int on, void *data), - void *flip_data) +int ps3av_dev_open(void) { - mutex_lock(&ps3av->mutex); - ps3av->flip_ctl = flip_ctl; - ps3av->flip_data = flip_data; - mutex_unlock(&ps3av->mutex); + int status = 0; + + mutex_lock(&ps3av.mutex); + if (!ps3av.open_count++) { + status = lv1_gpu_open(0); + if (status) { + printk(KERN_ERR "%s: lv1_gpu_open failed %d\n", + __func__, status); + ps3av.open_count--; + } + } + mutex_unlock(&ps3av.mutex); + + return status; } -EXPORT_SYMBOL_GPL(ps3av_register_flip_ctl); -void ps3av_flip_ctl(int on) +EXPORT_SYMBOL_GPL(ps3av_dev_open); + +int ps3av_dev_close(void) { - mutex_lock(&ps3av->mutex); - if (ps3av->flip_ctl) - ps3av->flip_ctl(on, ps3av->flip_data); - mutex_unlock(&ps3av->mutex); + int status = 0; + + mutex_lock(&ps3av.mutex); + if (ps3av.open_count <= 0) { + printk(KERN_ERR "%s: GPU already closed\n", __func__); + status = -1; + } else if (!--ps3av.open_count) { + status = lv1_gpu_close(); + if (status) + printk(KERN_WARNING "%s: lv1_gpu_close failed %d\n", + __func__, status); + } + mutex_unlock(&ps3av.mutex); + + return status; } -static int ps3av_probe(struct ps3_system_bus_device *dev) +EXPORT_SYMBOL_GPL(ps3av_dev_close); + +static int ps3av_probe(struct ps3_vuart_port_device *dev) { int res; u32 id; - dev_dbg(&dev->core, " -> %s:%d\n", __func__, __LINE__); - dev_dbg(&dev->core, " timeout=%d\n", timeout); + dev_dbg(&ps3av_dev.core, "init ...\n"); + dev_dbg(&ps3av_dev.core, " timeout=%d\n", timeout); - if (ps3av) { - dev_err(&dev->core, "Only one ps3av device is supported\n"); - return -EBUSY; - } - - ps3av = kzalloc(sizeof(*ps3av), GFP_KERNEL); - if (!ps3av) - return -ENOMEM; + memset(&ps3av, 0, sizeof(ps3av)); - mutex_init(&ps3av->mutex); - ps3av->ps3av_mode = 0; - ps3av->dev = dev; + mutex_init(&ps3av.mutex); + ps3av.ps3av_mode = 0; + ps3av.dev = dev; - INIT_WORK(&ps3av->work, ps3avd); - init_completion(&ps3av->done); - complete(&ps3av->done); - ps3av->wq = create_singlethread_workqueue("ps3avd"); - if (!ps3av->wq) - goto fail; + INIT_WORK(&ps3av.work, ps3avd); + init_completion(&ps3av.done); + complete(&ps3av.done); + ps3av.wq = create_singlethread_workqueue("ps3avd"); + if (!ps3av.wq) + return -ENOMEM; + ps3av.available = 1; switch (ps3_os_area_get_av_multi_out()) { case PS3_PARAM_AV_MULTI_OUT_NTSC: - ps3av->region = PS3AV_REGION_60; + ps3av.region = PS3AV_REGION_60; break; case PS3_PARAM_AV_MULTI_OUT_PAL_YCBCR: case PS3_PARAM_AV_MULTI_OUT_SECAM: - ps3av->region = PS3AV_REGION_50; + ps3av.region = PS3AV_REGION_50; break; case PS3_PARAM_AV_MULTI_OUT_PAL_RGB: - ps3av->region = PS3AV_REGION_50 | PS3AV_REGION_RGB; + ps3av.region = PS3AV_REGION_50 | PS3AV_REGION_RGB; break; default: - ps3av->region = PS3AV_REGION_60; + ps3av.region = PS3AV_REGION_60; break; } @@ -940,47 +927,39 @@ static int ps3av_probe(struct ps3_system_bus_device *dev) printk(KERN_ERR "%s: ps3av_cmd_init failed %d\n", __func__, res); - ps3av_get_hw_conf(ps3av); - id = ps3av_auto_videomode(&ps3av->av_hw_conf, 1); - mutex_lock(&ps3av->mutex); - ps3av->ps3av_mode = id; - mutex_unlock(&ps3av->mutex); + ps3av_get_hw_conf(&ps3av); + id = ps3av_auto_videomode(&ps3av.av_hw_conf, 1); + mutex_lock(&ps3av.mutex); + ps3av.ps3av_mode = id; + mutex_unlock(&ps3av.mutex); - dev_dbg(&dev->core, " <- %s:%d\n", __func__, __LINE__); + dev_dbg(&ps3av_dev.core, "init...done\n"); return 0; - -fail: - kfree(ps3av); - ps3av = NULL; - return -ENOMEM; } -static int ps3av_remove(struct ps3_system_bus_device *dev) +static int ps3av_remove(struct ps3_vuart_port_device *dev) { - dev_dbg(&dev->core, " -> %s:%d\n", __func__, __LINE__); - if (ps3av) { + if (ps3av.available) { ps3av_cmd_fin(); - if (ps3av->wq) - destroy_workqueue(ps3av->wq); - kfree(ps3av); - ps3av = NULL; + if (ps3av.wq) + destroy_workqueue(ps3av.wq); + ps3av.available = 0; } - dev_dbg(&dev->core, " <- %s:%d\n", __func__, __LINE__); return 0; } -static void ps3av_shutdown(struct ps3_system_bus_device *dev) +static void ps3av_shutdown(struct ps3_vuart_port_device *dev) { - dev_dbg(&dev->core, " -> %s:%d\n", __func__, __LINE__); ps3av_remove(dev); - dev_dbg(&dev->core, " <- %s:%d\n", __func__, __LINE__); } static struct ps3_vuart_port_driver ps3av_driver = { - .core.match_id = PS3_MATCH_ID_AV_SETTINGS, - .core.core.name = "ps3_av", + .match_id = PS3_MATCH_ID_AV_SETTINGS, + .core = { + .name = "ps3_av", + }, .probe = ps3av_probe, .remove = ps3av_remove, .shutdown = ps3av_shutdown, @@ -993,8 +972,6 @@ static int ps3av_module_init(void) if (!firmware_has_feature(FW_FEATURE_PS3_LV1)) return -ENODEV; - pr_debug(" -> %s:%d\n", __func__, __LINE__); - error = ps3_vuart_port_driver_register(&ps3av_driver); if (error) { printk(KERN_ERR @@ -1003,21 +980,20 @@ static int ps3av_module_init(void) return error; } - pr_debug(" <- %s:%d\n", __func__, __LINE__); + error = ps3_vuart_port_device_register(&ps3av_dev); + if (error) + printk(KERN_ERR + "%s: ps3_vuart_port_device_register failed %d\n", + __func__, error); + return error; } static void __exit ps3av_module_exit(void) { - pr_debug(" -> %s:%d\n", __func__, __LINE__); + device_unregister(&ps3av_dev.core); ps3_vuart_port_driver_unregister(&ps3av_driver); - pr_debug(" <- %s:%d\n", __func__, __LINE__); } subsys_initcall(ps3av_module_init); module_exit(ps3av_module_exit); - -MODULE_LICENSE("GPL v2"); -MODULE_DESCRIPTION("PS3 AV Settings Driver"); -MODULE_AUTHOR("Sony Computer Entertainment Inc."); -MODULE_ALIAS(PS3_MODULE_ALIAS_AV_SETTINGS); diff --git a/trunk/drivers/ps3/ps3av_cmd.c b/trunk/drivers/ps3/ps3av_cmd.c index f72f5ddf18e4..0145ea173c42 100644 --- a/trunk/drivers/ps3/ps3av_cmd.c +++ b/trunk/drivers/ps3/ps3av_cmd.c @@ -143,14 +143,6 @@ static u32 ps3av_vid_video2av(int vid) return PS3AV_CMD_AV_VID_480P; } -static int ps3av_hdmi_range(void) -{ - if (ps3_compare_firmware_version(1, 8, 0) < 0) - return 0; - else - return 1; /* supported */ -} - int ps3av_cmd_init(void) { int res; @@ -358,10 +350,6 @@ u32 ps3av_cmd_set_av_video_cs(void *p, u32 avport, int video_vid, int cs_out, /* should be same as video_mode.video_cs_out */ av_video_cs->av_cs_in = ps3av_cs_video2av(PS3AV_CMD_VIDEO_CS_RGB_8); av_video_cs->bitlen_out = ps3av_cs_video2av_bitlen(cs_out); - if ((id & PS3AV_MODE_WHITE) && ps3av_hdmi_range()) - av_video_cs->super_white = PS3AV_CMD_AV_SUPER_WHITE_ON; - else /* default off */ - av_video_cs->super_white = PS3AV_CMD_AV_SUPER_WHITE_OFF; av_video_cs->aspect = aspect; if (id & PS3AV_MODE_DITHER) { av_video_cs->dither = PS3AV_CMD_AV_DITHER_ON @@ -404,10 +392,6 @@ u32 ps3av_cmd_set_video_mode(void *p, u32 head, int video_vid, int video_fmt, video_mode->pitch = video_mode->width * 4; /* line_length */ video_mode->video_out_format = PS3AV_CMD_VIDEO_OUT_FORMAT_RGB_12BIT; video_mode->video_format = ps3av_video_fmt_table[video_fmt].format; - if ((id & PS3AV_MODE_COLOR) && ps3av_hdmi_range()) - video_mode->video_cl_cnv = PS3AV_CMD_VIDEO_CL_CNV_DISABLE_LUT; - else /* default enable */ - video_mode->video_cl_cnv = PS3AV_CMD_VIDEO_CL_CNV_ENABLE_LUT; video_mode->video_order = ps3av_video_fmt_table[video_fmt].order; pr_debug("%s: video_mode:vid:%x width:%d height:%d pitch:%d out_format:%d format:%x order:%x\n", @@ -868,7 +852,7 @@ int ps3av_cmd_avb_param(struct ps3av_pkt_avb_param *avb, u32 send_len) { int res; - ps3av_flip_ctl(0); /* flip off */ + ps3fb_flip_ctl(0); /* flip off */ /* avb packet */ res = ps3av_do_pkt(PS3AV_CID_AVB_PARAM, send_len, sizeof(*avb), @@ -882,7 +866,7 @@ int ps3av_cmd_avb_param(struct ps3av_pkt_avb_param *avb, u32 send_len) res); out: - ps3av_flip_ctl(1); /* flip on */ + ps3fb_flip_ctl(1); /* flip on */ return res; } @@ -1003,3 +987,34 @@ void ps3av_cmd_av_monitor_info_dump(const struct ps3av_pkt_av_get_monitor_info * | PS3AV_CMD_AV_LAYOUT_176 \ | PS3AV_CMD_AV_LAYOUT_192) +/************************* vuart ***************************/ + +#define POLLING_INTERVAL 25 /* in msec */ + +int ps3av_vuart_write(struct ps3_vuart_port_device *dev, const void *buf, + unsigned long size) +{ + int error = ps3_vuart_write(dev, buf, size); + return error ? error : size; +} + +int ps3av_vuart_read(struct ps3_vuart_port_device *dev, void *buf, + unsigned long size, int timeout) +{ + int error; + int loopcnt = 0; + + timeout = (timeout + POLLING_INTERVAL - 1) / POLLING_INTERVAL; + while (loopcnt++ <= timeout) { + error = ps3_vuart_read(dev, buf, size); + if (!error) + return size; + if (error != -EAGAIN) { + printk(KERN_ERR "%s: ps3_vuart_read failed %d\n", + __func__, error); + return error; + } + msleep(POLLING_INTERVAL); + } + return -EWOULDBLOCK; +} diff --git a/trunk/drivers/ps3/ps3stor_lib.c b/trunk/drivers/ps3/ps3stor_lib.c deleted file mode 100644 index 3a9824e3b251..000000000000 --- a/trunk/drivers/ps3/ps3stor_lib.c +++ /dev/null @@ -1,302 +0,0 @@ -/* - * PS3 Storage Library - * - * Copyright (C) 2007 Sony Computer Entertainment Inc. - * Copyright 2007 Sony Corp. - * - * 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; version 2 of the License. - * - * 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 Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include - -#include -#include - - -static int ps3stor_probe_access(struct ps3_storage_device *dev) -{ - int res, error; - unsigned int i; - unsigned long n; - - if (dev->sbd.match_id == PS3_MATCH_ID_STOR_ROM) { - /* special case: CD-ROM is assumed always accessible */ - dev->accessible_regions = 1; - return 0; - } - - error = -EPERM; - for (i = 0; i < dev->num_regions; i++) { - dev_dbg(&dev->sbd.core, - "%s:%u: checking accessibility of region %u\n", - __func__, __LINE__, i); - - dev->region_idx = i; - res = ps3stor_read_write_sectors(dev, dev->bounce_lpar, 0, 1, - 0); - if (res) { - dev_dbg(&dev->sbd.core, "%s:%u: read failed, " - "region %u is not accessible\n", __func__, - __LINE__, i); - continue; - } - - dev_dbg(&dev->sbd.core, "%s:%u: region %u is accessible\n", - __func__, __LINE__, i); - set_bit(i, &dev->accessible_regions); - - /* We can access at least one region */ - error = 0; - } - if (error) - return error; - - n = hweight_long(dev->accessible_regions); - if (n > 1) - dev_info(&dev->sbd.core, - "%s:%u: %lu accessible regions found. Only the first " - "one will be used", - __func__, __LINE__, n); - dev->region_idx = __ffs(dev->accessible_regions); - dev_info(&dev->sbd.core, - "First accessible region has index %u start %lu size %lu\n", - dev->region_idx, dev->regions[dev->region_idx].start, - dev->regions[dev->region_idx].size); - - return 0; -} - - -/** - * ps3stor_setup - Setup a storage device before use - * @dev: Pointer to a struct ps3_storage_device - * @handler: Pointer to an interrupt handler - * - * Returns 0 for success, or an error code - */ -int ps3stor_setup(struct ps3_storage_device *dev, irq_handler_t handler) -{ - int error, res, alignment; - enum ps3_dma_page_size page_size; - - error = ps3_open_hv_device(&dev->sbd); - if (error) { - dev_err(&dev->sbd.core, - "%s:%u: ps3_open_hv_device failed %d\n", __func__, - __LINE__, error); - goto fail; - } - - error = ps3_sb_event_receive_port_setup(&dev->sbd, PS3_BINDING_CPU_ANY, - &dev->irq); - if (error) { - dev_err(&dev->sbd.core, - "%s:%u: ps3_sb_event_receive_port_setup failed %d\n", - __func__, __LINE__, error); - goto fail_close_device; - } - - error = request_irq(dev->irq, handler, IRQF_DISABLED, - dev->sbd.core.driver->name, dev); - if (error) { - dev_err(&dev->sbd.core, "%s:%u: request_irq failed %d\n", - __func__, __LINE__, error); - goto fail_sb_event_receive_port_destroy; - } - - alignment = min(__ffs(dev->bounce_size), - __ffs((unsigned long)dev->bounce_buf)); - if (alignment < 12) { - dev_err(&dev->sbd.core, - "%s:%u: bounce buffer not aligned (%lx at 0x%p)\n", - __func__, __LINE__, dev->bounce_size, dev->bounce_buf); - error = -EINVAL; - goto fail_free_irq; - } else if (alignment < 16) - page_size = PS3_DMA_4K; - else - page_size = PS3_DMA_64K; - dev->sbd.d_region = &dev->dma_region; - ps3_dma_region_init(&dev->sbd, &dev->dma_region, page_size, - PS3_DMA_OTHER, dev->bounce_buf, dev->bounce_size); - res = ps3_dma_region_create(&dev->dma_region); - if (res) { - dev_err(&dev->sbd.core, "%s:%u: cannot create DMA region\n", - __func__, __LINE__); - error = -ENOMEM; - goto fail_free_irq; - } - - dev->bounce_lpar = ps3_mm_phys_to_lpar(__pa(dev->bounce_buf)); - dev->bounce_dma = dma_map_single(&dev->sbd.core, dev->bounce_buf, - dev->bounce_size, DMA_BIDIRECTIONAL); - if (!dev->bounce_dma) { - dev_err(&dev->sbd.core, "%s:%u: map DMA region failed\n", - __func__, __LINE__); - error = -ENODEV; - goto fail_free_dma; - } - - error = ps3stor_probe_access(dev); - if (error) { - dev_err(&dev->sbd.core, "%s:%u: No accessible regions found\n", - __func__, __LINE__); - goto fail_unmap_dma; - } - return 0; - -fail_unmap_dma: - dma_unmap_single(&dev->sbd.core, dev->bounce_dma, dev->bounce_size, - DMA_BIDIRECTIONAL); -fail_free_dma: - ps3_dma_region_free(&dev->dma_region); -fail_free_irq: - free_irq(dev->irq, dev); -fail_sb_event_receive_port_destroy: - ps3_sb_event_receive_port_destroy(&dev->sbd, dev->irq); -fail_close_device: - ps3_close_hv_device(&dev->sbd); -fail: - return error; -} -EXPORT_SYMBOL_GPL(ps3stor_setup); - - -/** - * ps3stor_teardown - Tear down a storage device after use - * @dev: Pointer to a struct ps3_storage_device - */ -void ps3stor_teardown(struct ps3_storage_device *dev) -{ - int error; - - dma_unmap_single(&dev->sbd.core, dev->bounce_dma, dev->bounce_size, - DMA_BIDIRECTIONAL); - ps3_dma_region_free(&dev->dma_region); - - free_irq(dev->irq, dev); - - error = ps3_sb_event_receive_port_destroy(&dev->sbd, dev->irq); - if (error) - dev_err(&dev->sbd.core, - "%s:%u: destroy event receive port failed %d\n", - __func__, __LINE__, error); - - error = ps3_close_hv_device(&dev->sbd); - if (error) - dev_err(&dev->sbd.core, - "%s:%u: ps3_close_hv_device failed %d\n", __func__, - __LINE__, error); -} -EXPORT_SYMBOL_GPL(ps3stor_teardown); - - -/** - * ps3stor_read_write_sectors - read/write from/to a storage device - * @dev: Pointer to a struct ps3_storage_device - * @lpar: HV logical partition address - * @start_sector: First sector to read/write - * @sectors: Number of sectors to read/write - * @write: Flag indicating write (non-zero) or read (zero) - * - * Returns 0 for success, -1 in case of failure to submit the command, or - * an LV1 status value in case of other errors - */ -u64 ps3stor_read_write_sectors(struct ps3_storage_device *dev, u64 lpar, - u64 start_sector, u64 sectors, int write) -{ - unsigned int region_id = dev->regions[dev->region_idx].id; - const char *op = write ? "write" : "read"; - int res; - - dev_dbg(&dev->sbd.core, "%s:%u: %s %lu sectors starting at %lu\n", - __func__, __LINE__, op, sectors, start_sector); - - init_completion(&dev->done); - res = write ? lv1_storage_write(dev->sbd.dev_id, region_id, - start_sector, sectors, 0, lpar, - &dev->tag) - : lv1_storage_read(dev->sbd.dev_id, region_id, - start_sector, sectors, 0, lpar, - &dev->tag); - if (res) { - dev_dbg(&dev->sbd.core, "%s:%u: %s failed %d\n", __func__, - __LINE__, op, res); - return -1; - } - - wait_for_completion(&dev->done); - if (dev->lv1_status) { - dev_dbg(&dev->sbd.core, "%s:%u: %s failed 0x%lx\n", __func__, - __LINE__, op, dev->lv1_status); - return dev->lv1_status; - } - - dev_dbg(&dev->sbd.core, "%s:%u: %s completed\n", __func__, __LINE__, - op); - - return 0; -} -EXPORT_SYMBOL_GPL(ps3stor_read_write_sectors); - - -/** - * ps3stor_send_command - send a device command to a storage device - * @dev: Pointer to a struct ps3_storage_device - * @cmd: Command number - * @arg1: First command argument - * @arg2: Second command argument - * @arg3: Third command argument - * @arg4: Fourth command argument - * - * Returns 0 for success, -1 in case of failure to submit the command, or - * an LV1 status value in case of other errors - */ -u64 ps3stor_send_command(struct ps3_storage_device *dev, u64 cmd, u64 arg1, - u64 arg2, u64 arg3, u64 arg4) -{ - int res; - - dev_dbg(&dev->sbd.core, "%s:%u: send device command 0x%lx\n", __func__, - __LINE__, cmd); - - init_completion(&dev->done); - - res = lv1_storage_send_device_command(dev->sbd.dev_id, cmd, arg1, - arg2, arg3, arg4, &dev->tag); - if (res) { - dev_err(&dev->sbd.core, - "%s:%u: send_device_command 0x%lx failed %d\n", - __func__, __LINE__, cmd, res); - return -1; - } - - wait_for_completion(&dev->done); - if (dev->lv1_status) { - dev_dbg(&dev->sbd.core, "%s:%u: command 0x%lx failed 0x%lx\n", - __func__, __LINE__, cmd, dev->lv1_status); - return dev->lv1_status; - } - - dev_dbg(&dev->sbd.core, "%s:%u: command 0x%lx completed\n", __func__, - __LINE__, cmd); - - return 0; -} -EXPORT_SYMBOL_GPL(ps3stor_send_command); - - -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("PS3 Storage Bus Library"); -MODULE_AUTHOR("Sony Corporation"); diff --git a/trunk/drivers/ps3/sys-manager-core.c b/trunk/drivers/ps3/sys-manager-core.c deleted file mode 100644 index 31648f7d9ae1..000000000000 --- a/trunk/drivers/ps3/sys-manager-core.c +++ /dev/null @@ -1,68 +0,0 @@ -/* - * PS3 System Manager core. - * - * Copyright (C) 2007 Sony Computer Entertainment Inc. - * Copyright 2007 Sony Corp. - * - * 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; version 2 of the License. - * - * 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 - -/** - * Staticly linked routines that allow late binding of a loaded sys-manager - * module. - */ - -static struct ps3_sys_manager_ops ps3_sys_manager_ops; - -/** - * ps3_register_sys_manager_ops - Bind ps3_sys_manager_ops to a module. - * @ops: struct ps3_sys_manager_ops. - * - * To be called from ps3_sys_manager_probe() and ps3_sys_manager_remove() to - * register call back ops for power control. Copies data to the static - * variable ps3_sys_manager_ops. - */ - -void ps3_sys_manager_register_ops(const struct ps3_sys_manager_ops *ops) -{ - BUG_ON(!ops); - BUG_ON(!ops->dev); - ps3_sys_manager_ops = ops ? *ops : ps3_sys_manager_ops; -} -EXPORT_SYMBOL_GPL(ps3_sys_manager_register_ops); - -void ps3_sys_manager_power_off(void) -{ - if (ps3_sys_manager_ops.power_off) - ps3_sys_manager_ops.power_off(ps3_sys_manager_ops.dev); - - printk(KERN_EMERG "System Halted, OK to turn off power\n"); - local_irq_disable(); - while (1) - (void)0; -} - -void ps3_sys_manager_restart(void) -{ - if (ps3_sys_manager_ops.restart) - ps3_sys_manager_ops.restart(ps3_sys_manager_ops.dev); - - printk(KERN_EMERG "System Halted, OK to turn off power\n"); - local_irq_disable(); - while (1) - (void)0; -} diff --git a/trunk/drivers/ps3/sys-manager.c b/trunk/drivers/ps3/sys-manager.c index 8461b08ab9fb..3aa2b0dcc369 100644 --- a/trunk/drivers/ps3/sys-manager.c +++ b/trunk/drivers/ps3/sys-manager.c @@ -35,7 +35,7 @@ MODULE_DESCRIPTION("PS3 System Manager"); /** * ps3_sys_manager - PS3 system manager driver. * - * The system manager provides an asynchronous system event notification + * The system manager provides an asyncronous system event notification * mechanism for reporting events like thermal alert and button presses to * guests. It also provides support to control system shutdown and startup. * @@ -52,7 +52,6 @@ MODULE_DESCRIPTION("PS3 System Manager"); * @size: Header size in bytes, curently 16. * @payload_size: Message payload size in bytes. * @service_id: Message type, one of enum ps3_sys_manager_service_id. - * @request_tag: Unique number to identify reply. */ struct ps3_sys_manager_header { @@ -62,49 +61,29 @@ struct ps3_sys_manager_header { u16 reserved_1; u32 payload_size; u16 service_id; - u16 reserved_2; - u32 request_tag; + u16 reserved_2[3]; }; -#define dump_sm_header(_h) _dump_sm_header(_h, __func__, __LINE__) -static void __maybe_unused _dump_sm_header( - const struct ps3_sys_manager_header *h, const char *func, int line) -{ - pr_debug("%s:%d: version: %xh\n", func, line, h->version); - pr_debug("%s:%d: size: %xh\n", func, line, h->size); - pr_debug("%s:%d: payload_size: %xh\n", func, line, h->payload_size); - pr_debug("%s:%d: service_id: %xh\n", func, line, h->service_id); - pr_debug("%s:%d: request_tag: %xh\n", func, line, h->request_tag); -} - /** - * @PS3_SM_RX_MSG_LEN_MIN - Shortest received message length. - * @PS3_SM_RX_MSG_LEN_MAX - Longest received message length. + * @PS3_SM_RX_MSG_LEN - System manager received message length. * - * Currently all messages received from the system manager are either - * (16 bytes header + 8 bytes payload = 24 bytes) or (16 bytes header - * + 16 bytes payload = 32 bytes). This knowlege is used to simplify - * the logic. + * Currently all messages received from the system manager are the same length + * (16 bytes header + 16 bytes payload = 32 bytes). This knowlege is used to + * simplify the logic. */ enum { - PS3_SM_RX_MSG_LEN_MIN = 24, - PS3_SM_RX_MSG_LEN_MAX = 32, + PS3_SM_RX_MSG_LEN = 32, }; /** * enum ps3_sys_manager_service_id - Message header service_id. - * @PS3_SM_SERVICE_ID_REQUEST: guest --> sys_manager. - * @PS3_SM_SERVICE_ID_REQUEST_ERROR: guest <-- sys_manager. - * @PS3_SM_SERVICE_ID_COMMAND: guest <-- sys_manager. - * @PS3_SM_SERVICE_ID_RESPONSE: guest --> sys_manager. - * @PS3_SM_SERVICE_ID_SET_ATTR: guest --> sys_manager. - * @PS3_SM_SERVICE_ID_EXTERN_EVENT: guest <-- sys_manager. - * @PS3_SM_SERVICE_ID_SET_NEXT_OP: guest --> sys_manager. - * - * PS3_SM_SERVICE_ID_REQUEST_ERROR is returned for invalid data values in a - * a PS3_SM_SERVICE_ID_REQUEST message. It also seems to be returned when - * a REQUEST message is sent at the wrong time. + * @PS3_SM_SERVICE_ID_REQUEST: guest --> sys_manager. + * @PS3_SM_SERVICE_ID_COMMAND: guest <-- sys_manager. + * @PS3_SM_SERVICE_ID_RESPONSE: guest --> sys_manager. + * @PS3_SM_SERVICE_ID_SET_ATTR: guest --> sys_manager. + * @PS3_SM_SERVICE_ID_EXTERN_EVENT: guest <-- sys_manager. + * @PS3_SM_SERVICE_ID_SET_NEXT_OP: guest --> sys_manager. */ enum ps3_sys_manager_service_id { @@ -114,7 +93,6 @@ enum ps3_sys_manager_service_id { PS3_SM_SERVICE_ID_COMMAND = 3, PS3_SM_SERVICE_ID_EXTERN_EVENT = 4, PS3_SM_SERVICE_ID_SET_NEXT_OP = 5, - PS3_SM_SERVICE_ID_REQUEST_ERROR = 6, PS3_SM_SERVICE_ID_SET_ATTR = 8, }; @@ -206,22 +184,12 @@ enum ps3_sys_manager_cmd { PS3_SM_CMD_SHUTDOWN = 1, /* shutdown guest OS */ }; -/** - * ps3_sm_force_power_off - Poweroff helper. - * - * A global variable used to force a poweroff when the power button has - * been pressed irrespective of how init handles the ctrl_alt_del signal. - * - */ - -static unsigned int ps3_sm_force_power_off; - /** * ps3_sys_manager_write - Helper to write a two part message to the vuart. * */ -static int ps3_sys_manager_write(struct ps3_system_bus_device *dev, +static int ps3_sys_manager_write(struct ps3_vuart_port_device *dev, const struct ps3_sys_manager_header *header, const void *payload) { int result; @@ -245,10 +213,15 @@ static int ps3_sys_manager_write(struct ps3_system_bus_device *dev, * */ -static int ps3_sys_manager_send_attr(struct ps3_system_bus_device *dev, +static int ps3_sys_manager_send_attr(struct ps3_vuart_port_device *dev, enum ps3_sys_manager_attr attr) { - struct ps3_sys_manager_header header; + static const struct ps3_sys_manager_header header = { + .version = 1, + .size = 16, + .payload_size = 16, + .service_id = PS3_SM_SERVICE_ID_SET_ATTR, + }; struct { u8 version; u8 reserved_1[3]; @@ -259,12 +232,6 @@ static int ps3_sys_manager_send_attr(struct ps3_system_bus_device *dev, dev_dbg(&dev->core, "%s:%d: %xh\n", __func__, __LINE__, attr); - memset(&header, 0, sizeof(header)); - header.version = 1; - header.size = 16; - header.payload_size = 16; - header.service_id = PS3_SM_SERVICE_ID_SET_ATTR; - memset(&payload, 0, sizeof(payload)); payload.version = 1; payload.attribute = attr; @@ -278,11 +245,16 @@ static int ps3_sys_manager_send_attr(struct ps3_system_bus_device *dev, * Tell the system manager what to do after this lpar is destroyed. */ -static int ps3_sys_manager_send_next_op(struct ps3_system_bus_device *dev, +static int ps3_sys_manager_send_next_op(struct ps3_vuart_port_device *dev, enum ps3_sys_manager_next_op op, enum ps3_sys_manager_wake_source wake_source) { - struct ps3_sys_manager_header header; + static const struct ps3_sys_manager_header header = { + .version = 1, + .size = 16, + .payload_size = 16, + .service_id = PS3_SM_SERVICE_ID_SET_NEXT_OP, + }; struct { u8 version; u8 type; @@ -296,12 +268,6 @@ static int ps3_sys_manager_send_next_op(struct ps3_system_bus_device *dev, dev_dbg(&dev->core, "%s:%d: (%xh)\n", __func__, __LINE__, op); - memset(&header, 0, sizeof(header)); - header.version = 1; - header.size = 16; - header.payload_size = 16; - header.service_id = PS3_SM_SERVICE_ID_SET_NEXT_OP; - memset(&payload, 0, sizeof(payload)); payload.version = 3; payload.type = op; @@ -320,35 +286,32 @@ static int ps3_sys_manager_send_next_op(struct ps3_system_bus_device *dev, * the command is then communicated back to the system manager with a response * message. * - * Currently, the only supported request is the 'shutdown self' request. + * Currently, the only supported request it the 'shutdown self' request. */ -static int ps3_sys_manager_send_request_shutdown( - struct ps3_system_bus_device *dev) +static int ps3_sys_manager_send_request_shutdown(struct ps3_vuart_port_device *dev) { - struct ps3_sys_manager_header header; + static const struct ps3_sys_manager_header header = { + .version = 1, + .size = 16, + .payload_size = 16, + .service_id = PS3_SM_SERVICE_ID_REQUEST, + }; struct { u8 version; u8 type; u8 gos_id; u8 reserved_1[13]; - } payload; + } static const payload = { + .version = 1, + .type = 1, /* shutdown */ + .gos_id = 0, /* self */ + }; BUILD_BUG_ON(sizeof(payload) != 16); dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__); - memset(&header, 0, sizeof(header)); - header.version = 1; - header.size = 16; - header.payload_size = 16; - header.service_id = PS3_SM_SERVICE_ID_REQUEST; - - memset(&payload, 0, sizeof(payload)); - payload.version = 1; - payload.type = 1; /* shutdown */ - payload.gos_id = 0; /* self */ - return ps3_sys_manager_write(dev, &header, &payload); } @@ -360,10 +323,15 @@ static int ps3_sys_manager_send_request_shutdown( * failure of a command sent by the system manager. */ -static int ps3_sys_manager_send_response(struct ps3_system_bus_device *dev, +static int ps3_sys_manager_send_response(struct ps3_vuart_port_device *dev, u64 status) { - struct ps3_sys_manager_header header; + static const struct ps3_sys_manager_header header = { + .version = 1, + .size = 16, + .payload_size = 16, + .service_id = PS3_SM_SERVICE_ID_RESPONSE, + }; struct { u8 version; u8 reserved_1[3]; @@ -376,12 +344,6 @@ static int ps3_sys_manager_send_response(struct ps3_system_bus_device *dev, dev_dbg(&dev->core, "%s:%d: (%s)\n", __func__, __LINE__, (status ? "nak" : "ack")); - memset(&header, 0, sizeof(header)); - header.version = 1; - header.size = 16; - header.payload_size = 16; - header.service_id = PS3_SM_SERVICE_ID_RESPONSE; - memset(&payload, 0, sizeof(payload)); payload.version = 1; payload.status = status; @@ -394,7 +356,7 @@ static int ps3_sys_manager_send_response(struct ps3_system_bus_device *dev, * */ -static int ps3_sys_manager_handle_event(struct ps3_system_bus_device *dev) +static int ps3_sys_manager_handle_event(struct ps3_vuart_port_device *dev) { int result; struct { @@ -408,7 +370,7 @@ static int ps3_sys_manager_handle_event(struct ps3_system_bus_device *dev) BUILD_BUG_ON(sizeof(event) != 16); result = ps3_vuart_read(dev, &event, sizeof(event)); - BUG_ON(result && "need to retry here"); + BUG_ON(result); if (event.version != 1) { dev_dbg(&dev->core, "%s:%d: unsupported event version (%u)\n", @@ -420,34 +382,11 @@ static int ps3_sys_manager_handle_event(struct ps3_system_bus_device *dev) case PS3_SM_EVENT_POWER_PRESSED: dev_dbg(&dev->core, "%s:%d: POWER_PRESSED\n", __func__, __LINE__); - ps3_sm_force_power_off = 1; - /* - * A memory barrier is use here to sync memory since - * ps3_sys_manager_final_restart() could be called on - * another cpu. - */ - wmb(); - kill_cad_pid(SIGINT, 1); /* ctrl_alt_del */ break; case PS3_SM_EVENT_POWER_RELEASED: dev_dbg(&dev->core, "%s:%d: POWER_RELEASED (%u ms)\n", __func__, __LINE__, event.value); - break; - case PS3_SM_EVENT_RESET_PRESSED: - dev_dbg(&dev->core, "%s:%d: RESET_PRESSED\n", - __func__, __LINE__); - ps3_sm_force_power_off = 0; - /* - * A memory barrier is use here to sync memory since - * ps3_sys_manager_final_restart() could be called on - * another cpu. - */ - wmb(); - kill_cad_pid(SIGINT, 1); /* ctrl_alt_del */ - break; - case PS3_SM_EVENT_RESET_RELEASED: - dev_dbg(&dev->core, "%s:%d: RESET_RELEASED (%u ms)\n", - __func__, __LINE__, event.value); + kill_cad_pid(SIGINT, 1); break; case PS3_SM_EVENT_THERMAL_ALERT: dev_dbg(&dev->core, "%s:%d: THERMAL_ALERT (zone %u)\n", @@ -472,7 +411,7 @@ static int ps3_sys_manager_handle_event(struct ps3_system_bus_device *dev) * The system manager sends this in reply to a 'request' message from the guest. */ -static int ps3_sys_manager_handle_cmd(struct ps3_system_bus_device *dev) +static int ps3_sys_manager_handle_cmd(struct ps3_vuart_port_device *dev) { int result; struct { @@ -486,7 +425,6 @@ static int ps3_sys_manager_handle_cmd(struct ps3_system_bus_device *dev) dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__); result = ps3_vuart_read(dev, &cmd, sizeof(cmd)); - BUG_ON(result && "need to retry here"); if(result) return result; @@ -510,10 +448,9 @@ static int ps3_sys_manager_handle_cmd(struct ps3_system_bus_device *dev) /** * ps3_sys_manager_handle_msg - First stage msg handler. * - * Can be called directly to manually poll vuart and pump message handler. */ -static int ps3_sys_manager_handle_msg(struct ps3_system_bus_device *dev) +static int ps3_sys_manager_handle_msg(struct ps3_vuart_port_device *dev) { int result; struct ps3_sys_manager_header header; @@ -527,17 +464,12 @@ static int ps3_sys_manager_handle_msg(struct ps3_system_bus_device *dev) if (header.version != 1) { dev_dbg(&dev->core, "%s:%d: unsupported header version (%u)\n", __func__, __LINE__, header.version); - dump_sm_header(&header); goto fail_header; } BUILD_BUG_ON(sizeof(header) != 16); - - if (header.size != 16 || (header.payload_size != 8 - && header.payload_size != 16)) { - dump_sm_header(&header); - BUG(); - } + BUG_ON(header.size != 16); + BUG_ON(header.payload_size != 16); switch (header.service_id) { case PS3_SM_SERVICE_ID_EXTERN_EVENT: @@ -546,11 +478,6 @@ static int ps3_sys_manager_handle_msg(struct ps3_system_bus_device *dev) case PS3_SM_SERVICE_ID_COMMAND: dev_dbg(&dev->core, "%s:%d: COMMAND\n", __func__, __LINE__); return ps3_sys_manager_handle_cmd(dev); - case PS3_SM_SERVICE_ID_REQUEST_ERROR: - dev_dbg(&dev->core, "%s:%d: REQUEST_ERROR\n", __func__, - __LINE__); - dump_sm_header(&header); - break; default: dev_dbg(&dev->core, "%s:%d: unknown service_id (%u)\n", __func__, __LINE__, header.service_id); @@ -567,25 +494,45 @@ static int ps3_sys_manager_handle_msg(struct ps3_system_bus_device *dev) } /** - * ps3_sys_manager_final_power_off - The final platform machine_power_off routine. + * ps3_sys_manager_work - Asyncronous read handler. + * + * Signaled when a complete message arrives at the vuart port. + */ + +static void ps3_sys_manager_work(struct work_struct *work) +{ + struct ps3_vuart_port_device *dev = ps3_vuart_work_to_port_device(work); + + ps3_sys_manager_handle_msg(dev); + ps3_vuart_read_async(dev, ps3_sys_manager_work, PS3_SM_RX_MSG_LEN); +} + +struct { + struct ps3_vuart_port_device *dev; +} static drv_priv; + +/** + * ps3_sys_manager_restart - The final platform machine_restart routine. * - * This routine never returns. The routine disables asynchronous vuart reads + * This routine never returns. The routine disables asyncronous vuart reads * then spins calling ps3_sys_manager_handle_msg() to receive and acknowledge * the shutdown command sent from the system manager. Soon after the * acknowledgement is sent the lpar is destroyed by the HV. This routine - * should only be called from ps3_power_off() through - * ps3_sys_manager_ops.power_off. + * should only be called from ps3_restart(). */ -static void ps3_sys_manager_final_power_off(struct ps3_system_bus_device *dev) +void ps3_sys_manager_restart(void) { - BUG_ON(!dev); + struct ps3_vuart_port_device *dev = drv_priv.dev; + + BUG_ON(!drv_priv.dev); dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__); ps3_vuart_cancel_async(dev); - ps3_sys_manager_send_next_op(dev, PS3_SM_NEXT_OP_SYS_SHUTDOWN, + ps3_sys_manager_send_attr(dev, 0); + ps3_sys_manager_send_next_op(dev, PS3_SM_NEXT_OP_LPAR_REBOOT, PS3_SM_WAKE_DEFAULT); ps3_sys_manager_send_request_shutdown(dev); @@ -596,33 +543,26 @@ static void ps3_sys_manager_final_power_off(struct ps3_system_bus_device *dev) } /** - * ps3_sys_manager_final_restart - The final platform machine_restart routine. + * ps3_sys_manager_power_off - The final platform machine_power_off routine. * - * This routine never returns. The routine disables asynchronous vuart reads + * This routine never returns. The routine disables asyncronous vuart reads * then spins calling ps3_sys_manager_handle_msg() to receive and acknowledge * the shutdown command sent from the system manager. Soon after the * acknowledgement is sent the lpar is destroyed by the HV. This routine - * should only be called from ps3_restart() through ps3_sys_manager_ops.restart. + * should only be called from ps3_power_off(). */ -static void ps3_sys_manager_final_restart(struct ps3_system_bus_device *dev) +void ps3_sys_manager_power_off(void) { - BUG_ON(!dev); - - dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__); + struct ps3_vuart_port_device *dev = drv_priv.dev; - /* Check if we got here via a power button event. */ + BUG_ON(!drv_priv.dev); - if (ps3_sm_force_power_off) { - dev_dbg(&dev->core, "%s:%d: forcing poweroff\n", - __func__, __LINE__); - ps3_sys_manager_final_power_off(dev); - } + dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__); ps3_vuart_cancel_async(dev); - ps3_sys_manager_send_attr(dev, 0); - ps3_sys_manager_send_next_op(dev, PS3_SM_NEXT_OP_LPAR_REBOOT, + ps3_sys_manager_send_next_op(dev, PS3_SM_NEXT_OP_SYS_SHUTDOWN, PS3_SM_WAKE_DEFAULT); ps3_sys_manager_send_request_shutdown(dev); @@ -632,60 +572,31 @@ static void ps3_sys_manager_final_restart(struct ps3_system_bus_device *dev) ps3_sys_manager_handle_msg(dev); } -/** - * ps3_sys_manager_work - Asynchronous read handler. - * - * Signaled when PS3_SM_RX_MSG_LEN_MIN bytes arrive at the vuart port. - */ - -static void ps3_sys_manager_work(struct ps3_system_bus_device *dev) -{ - ps3_sys_manager_handle_msg(dev); - ps3_vuart_read_async(dev, PS3_SM_RX_MSG_LEN_MIN); -} - -static int ps3_sys_manager_probe(struct ps3_system_bus_device *dev) +static int ps3_sys_manager_probe(struct ps3_vuart_port_device *dev) { int result; - struct ps3_sys_manager_ops ops; dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__); - ops.power_off = ps3_sys_manager_final_power_off; - ops.restart = ps3_sys_manager_final_restart; - ops.dev = dev; - - /* ps3_sys_manager_register_ops copies ops. */ - - ps3_sys_manager_register_ops(&ops); + BUG_ON(drv_priv.dev); + drv_priv.dev = dev; result = ps3_sys_manager_send_attr(dev, PS3_SM_ATTR_ALL); BUG_ON(result); - result = ps3_vuart_read_async(dev, PS3_SM_RX_MSG_LEN_MIN); + result = ps3_vuart_read_async(dev, ps3_sys_manager_work, + PS3_SM_RX_MSG_LEN); BUG_ON(result); return result; } -static int ps3_sys_manager_remove(struct ps3_system_bus_device *dev) -{ - dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__); - return 0; -} - -static void ps3_sys_manager_shutdown(struct ps3_system_bus_device *dev) -{ - dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__); -} - static struct ps3_vuart_port_driver ps3_sys_manager = { - .core.match_id = PS3_MATCH_ID_SYSTEM_MANAGER, - .core.core.name = "ps3_sys_manager", + .match_id = PS3_MATCH_ID_SYSTEM_MANAGER, + .core = { + .name = "ps3_sys_manager", + }, .probe = ps3_sys_manager_probe, - .remove = ps3_sys_manager_remove, - .shutdown = ps3_sys_manager_shutdown, - .work = ps3_sys_manager_work, }; static int __init ps3_sys_manager_init(void) @@ -697,6 +608,3 @@ static int __init ps3_sys_manager_init(void) } module_init(ps3_sys_manager_init); -/* Module remove not supported. */ - -MODULE_ALIAS(PS3_MODULE_ALIAS_SYSTEM_MANAGER); diff --git a/trunk/drivers/ps3/vuart.c b/trunk/drivers/ps3/vuart.c index bea25a1391ee..ec2d36a1bc67 100644 --- a/trunk/drivers/ps3/vuart.c +++ b/trunk/drivers/ps3/vuart.c @@ -70,34 +70,6 @@ enum vuart_interrupt_mask { INTERRUPT_MASK_DISCONNECT = 4, }; -/** - * struct ps3_vuart_port_priv - private vuart device data. - */ - -struct ps3_vuart_port_priv { - u64 interrupt_mask; - - struct { - spinlock_t lock; - struct list_head head; - } tx_list; - struct { - struct ps3_vuart_work work; - unsigned long bytes_held; - spinlock_t lock; - struct list_head head; - } rx_list; - struct ps3_vuart_stats stats; -}; - -static struct ps3_vuart_port_priv *to_port_priv( - struct ps3_system_bus_device *dev) -{ - BUG_ON(!dev); - BUG_ON(!dev->driver_priv); - return (struct ps3_vuart_port_priv *)dev->driver_priv; -} - /** * struct ports_bmp - bitmap indicating ports needing service. * @@ -111,14 +83,31 @@ struct ports_bmp { } __attribute__ ((aligned (32))); #define dump_ports_bmp(_b) _dump_ports_bmp(_b, __func__, __LINE__) -static void __maybe_unused _dump_ports_bmp( +static void __attribute__ ((unused)) _dump_ports_bmp( const struct ports_bmp* bmp, const char* func, int line) { pr_debug("%s:%d: ports_bmp: %016lxh\n", func, line, bmp->status); } +static int ps3_vuart_match_id_to_port(enum ps3_match_id match_id, + unsigned int *port_number) +{ + switch(match_id) { + case PS3_MATCH_ID_AV_SETTINGS: + *port_number = 0; + return 0; + case PS3_MATCH_ID_SYSTEM_MANAGER: + *port_number = 2; + return 0; + default: + WARN_ON(1); + *port_number = UINT_MAX; + return -EINVAL; + }; +} + #define dump_port_params(_b) _dump_port_params(_b, __func__, __LINE__) -static void __maybe_unused _dump_port_params(unsigned int port_number, +static void __attribute__ ((unused)) _dump_port_params(unsigned int port_number, const char* func, int line) { #if defined(DEBUG) @@ -155,14 +144,14 @@ struct vuart_triggers { unsigned long tx; }; -int ps3_vuart_get_triggers(struct ps3_system_bus_device *dev, +int ps3_vuart_get_triggers(struct ps3_vuart_port_device *dev, struct vuart_triggers *trig) { int result; unsigned long size; unsigned long val; - result = lv1_get_virtual_uart_param(dev->port_number, + result = lv1_get_virtual_uart_param(dev->priv->port_number, PARAM_TX_TRIGGER, &trig->tx); if (result) { @@ -171,7 +160,7 @@ int ps3_vuart_get_triggers(struct ps3_system_bus_device *dev, return result; } - result = lv1_get_virtual_uart_param(dev->port_number, + result = lv1_get_virtual_uart_param(dev->priv->port_number, PARAM_RX_BUF_SIZE, &size); if (result) { @@ -180,7 +169,7 @@ int ps3_vuart_get_triggers(struct ps3_system_bus_device *dev, return result; } - result = lv1_get_virtual_uart_param(dev->port_number, + result = lv1_get_virtual_uart_param(dev->priv->port_number, PARAM_RX_TRIGGER, &val); if (result) { @@ -197,13 +186,13 @@ int ps3_vuart_get_triggers(struct ps3_system_bus_device *dev, return result; } -int ps3_vuart_set_triggers(struct ps3_system_bus_device *dev, unsigned int tx, +int ps3_vuart_set_triggers(struct ps3_vuart_port_device *dev, unsigned int tx, unsigned int rx) { int result; unsigned long size; - result = lv1_set_virtual_uart_param(dev->port_number, + result = lv1_set_virtual_uart_param(dev->priv->port_number, PARAM_TX_TRIGGER, tx); if (result) { @@ -212,7 +201,7 @@ int ps3_vuart_set_triggers(struct ps3_system_bus_device *dev, unsigned int tx, return result; } - result = lv1_get_virtual_uart_param(dev->port_number, + result = lv1_get_virtual_uart_param(dev->priv->port_number, PARAM_RX_BUF_SIZE, &size); if (result) { @@ -221,7 +210,7 @@ int ps3_vuart_set_triggers(struct ps3_system_bus_device *dev, unsigned int tx, return result; } - result = lv1_set_virtual_uart_param(dev->port_number, + result = lv1_set_virtual_uart_param(dev->priv->port_number, PARAM_RX_TRIGGER, size - rx); if (result) { @@ -236,12 +225,10 @@ int ps3_vuart_set_triggers(struct ps3_system_bus_device *dev, unsigned int tx, return result; } -static int ps3_vuart_get_rx_bytes_waiting(struct ps3_system_bus_device *dev, +static int ps3_vuart_get_rx_bytes_waiting(struct ps3_vuart_port_device *dev, u64 *bytes_waiting) { - int result; - - result = lv1_get_virtual_uart_param(dev->port_number, + int result = lv1_get_virtual_uart_param(dev->priv->port_number, PARAM_RX_BYTES, bytes_waiting); if (result) @@ -253,24 +240,17 @@ static int ps3_vuart_get_rx_bytes_waiting(struct ps3_system_bus_device *dev, return result; } -/** - * ps3_vuart_set_interrupt_mask - Enable/disable the port interrupt sources. - * @dev: The struct ps3_system_bus_device instance. - * @bmp: Logical OR of enum vuart_interrupt_mask values. A zero bit disables. - */ - -static int ps3_vuart_set_interrupt_mask(struct ps3_system_bus_device *dev, +static int ps3_vuart_set_interrupt_mask(struct ps3_vuart_port_device *dev, unsigned long mask) { int result; - struct ps3_vuart_port_priv *priv = to_port_priv(dev); dev_dbg(&dev->core, "%s:%d: %lxh\n", __func__, __LINE__, mask); - priv->interrupt_mask = mask; + dev->priv->interrupt_mask = mask; - result = lv1_set_virtual_uart_param(dev->port_number, - PARAM_INTERRUPT_MASK, priv->interrupt_mask); + result = lv1_set_virtual_uart_param(dev->priv->port_number, + PARAM_INTERRUPT_MASK, dev->priv->interrupt_mask); if (result) dev_dbg(&dev->core, "%s:%d: interrupt_mask failed: %s\n", @@ -279,96 +259,79 @@ static int ps3_vuart_set_interrupt_mask(struct ps3_system_bus_device *dev, return result; } -static int ps3_vuart_get_interrupt_status(struct ps3_system_bus_device *dev, +static int ps3_vuart_get_interrupt_status(struct ps3_vuart_port_device *dev, unsigned long *status) { - int result; - struct ps3_vuart_port_priv *priv = to_port_priv(dev); u64 tmp; - - result = lv1_get_virtual_uart_param(dev->port_number, + int result = lv1_get_virtual_uart_param(dev->priv->port_number, PARAM_INTERRUPT_STATUS, &tmp); if (result) dev_dbg(&dev->core, "%s:%d: interrupt_status failed: %s\n", __func__, __LINE__, ps3_result(result)); - *status = tmp & priv->interrupt_mask; + *status = tmp & dev->priv->interrupt_mask; dev_dbg(&dev->core, "%s:%d: m %lxh, s %lxh, m&s %lxh\n", - __func__, __LINE__, priv->interrupt_mask, tmp, *status); + __func__, __LINE__, dev->priv->interrupt_mask, tmp, *status); return result; } -int ps3_vuart_enable_interrupt_tx(struct ps3_system_bus_device *dev) +int ps3_vuart_enable_interrupt_tx(struct ps3_vuart_port_device *dev) { - struct ps3_vuart_port_priv *priv = to_port_priv(dev); - - return (priv->interrupt_mask & INTERRUPT_MASK_TX) ? 0 - : ps3_vuart_set_interrupt_mask(dev, priv->interrupt_mask + return (dev->priv->interrupt_mask & INTERRUPT_MASK_TX) ? 0 + : ps3_vuart_set_interrupt_mask(dev, dev->priv->interrupt_mask | INTERRUPT_MASK_TX); } -int ps3_vuart_enable_interrupt_rx(struct ps3_system_bus_device *dev) +int ps3_vuart_enable_interrupt_rx(struct ps3_vuart_port_device *dev) { - struct ps3_vuart_port_priv *priv = to_port_priv(dev); - - return (priv->interrupt_mask & INTERRUPT_MASK_RX) ? 0 - : ps3_vuart_set_interrupt_mask(dev, priv->interrupt_mask + return (dev->priv->interrupt_mask & INTERRUPT_MASK_RX) ? 0 + : ps3_vuart_set_interrupt_mask(dev, dev->priv->interrupt_mask | INTERRUPT_MASK_RX); } -int ps3_vuart_enable_interrupt_disconnect(struct ps3_system_bus_device *dev) +int ps3_vuart_enable_interrupt_disconnect(struct ps3_vuart_port_device *dev) { - struct ps3_vuart_port_priv *priv = to_port_priv(dev); - - return (priv->interrupt_mask & INTERRUPT_MASK_DISCONNECT) ? 0 - : ps3_vuart_set_interrupt_mask(dev, priv->interrupt_mask + return (dev->priv->interrupt_mask & INTERRUPT_MASK_DISCONNECT) ? 0 + : ps3_vuart_set_interrupt_mask(dev, dev->priv->interrupt_mask | INTERRUPT_MASK_DISCONNECT); } -int ps3_vuart_disable_interrupt_tx(struct ps3_system_bus_device *dev) +int ps3_vuart_disable_interrupt_tx(struct ps3_vuart_port_device *dev) { - struct ps3_vuart_port_priv *priv = to_port_priv(dev); - - return (priv->interrupt_mask & INTERRUPT_MASK_TX) - ? ps3_vuart_set_interrupt_mask(dev, priv->interrupt_mask + return (dev->priv->interrupt_mask & INTERRUPT_MASK_TX) + ? ps3_vuart_set_interrupt_mask(dev, dev->priv->interrupt_mask & ~INTERRUPT_MASK_TX) : 0; } -int ps3_vuart_disable_interrupt_rx(struct ps3_system_bus_device *dev) +int ps3_vuart_disable_interrupt_rx(struct ps3_vuart_port_device *dev) { - struct ps3_vuart_port_priv *priv = to_port_priv(dev); - - return (priv->interrupt_mask & INTERRUPT_MASK_RX) - ? ps3_vuart_set_interrupt_mask(dev, priv->interrupt_mask + return (dev->priv->interrupt_mask & INTERRUPT_MASK_RX) + ? ps3_vuart_set_interrupt_mask(dev, dev->priv->interrupt_mask & ~INTERRUPT_MASK_RX) : 0; } -int ps3_vuart_disable_interrupt_disconnect(struct ps3_system_bus_device *dev) +int ps3_vuart_disable_interrupt_disconnect(struct ps3_vuart_port_device *dev) { - struct ps3_vuart_port_priv *priv = to_port_priv(dev); - - return (priv->interrupt_mask & INTERRUPT_MASK_DISCONNECT) - ? ps3_vuart_set_interrupt_mask(dev, priv->interrupt_mask + return (dev->priv->interrupt_mask & INTERRUPT_MASK_DISCONNECT) + ? ps3_vuart_set_interrupt_mask(dev, dev->priv->interrupt_mask & ~INTERRUPT_MASK_DISCONNECT) : 0; } /** * ps3_vuart_raw_write - Low level write helper. - * @dev: The struct ps3_system_bus_device instance. * * Do not call ps3_vuart_raw_write directly, use ps3_vuart_write. */ -static int ps3_vuart_raw_write(struct ps3_system_bus_device *dev, +static int ps3_vuart_raw_write(struct ps3_vuart_port_device *dev, const void* buf, unsigned int bytes, unsigned long *bytes_written) { int result; - struct ps3_vuart_port_priv *priv = to_port_priv(dev); - result = lv1_write_virtual_uart(dev->port_number, + result = lv1_write_virtual_uart(dev->priv->port_number, ps3_mm_phys_to_lpar(__pa(buf)), bytes, bytes_written); if (result) { @@ -377,30 +340,28 @@ static int ps3_vuart_raw_write(struct ps3_system_bus_device *dev, return result; } - priv->stats.bytes_written += *bytes_written; + dev->priv->stats.bytes_written += *bytes_written; dev_dbg(&dev->core, "%s:%d: wrote %lxh/%xh=>%lxh\n", __func__, __LINE__, - *bytes_written, bytes, priv->stats.bytes_written); + *bytes_written, bytes, dev->priv->stats.bytes_written); return result; } /** * ps3_vuart_raw_read - Low level read helper. - * @dev: The struct ps3_system_bus_device instance. * * Do not call ps3_vuart_raw_read directly, use ps3_vuart_read. */ -static int ps3_vuart_raw_read(struct ps3_system_bus_device *dev, void *buf, +static int ps3_vuart_raw_read(struct ps3_vuart_port_device *dev, void* buf, unsigned int bytes, unsigned long *bytes_read) { int result; - struct ps3_vuart_port_priv *priv = to_port_priv(dev); dev_dbg(&dev->core, "%s:%d: %xh\n", __func__, __LINE__, bytes); - result = lv1_read_virtual_uart(dev->port_number, + result = lv1_read_virtual_uart(dev->priv->port_number, ps3_mm_phys_to_lpar(__pa(buf)), bytes, bytes_read); if (result) { @@ -409,27 +370,25 @@ static int ps3_vuart_raw_read(struct ps3_system_bus_device *dev, void *buf, return result; } - priv->stats.bytes_read += *bytes_read; + dev->priv->stats.bytes_read += *bytes_read; dev_dbg(&dev->core, "%s:%d: read %lxh/%xh=>%lxh\n", __func__, __LINE__, - *bytes_read, bytes, priv->stats.bytes_read); + *bytes_read, bytes, dev->priv->stats.bytes_read); return result; } /** * ps3_vuart_clear_rx_bytes - Discard bytes received. - * @dev: The struct ps3_system_bus_device instance. * @bytes: Max byte count to discard, zero = all pending. * * Used to clear pending rx interrupt source. Will not block. */ -void ps3_vuart_clear_rx_bytes(struct ps3_system_bus_device *dev, +void ps3_vuart_clear_rx_bytes(struct ps3_vuart_port_device *dev, unsigned int bytes) { int result; - struct ps3_vuart_port_priv *priv = to_port_priv(dev); u64 bytes_waiting; void* tmp; @@ -459,9 +418,8 @@ void ps3_vuart_clear_rx_bytes(struct ps3_system_bus_device *dev, /* Don't include these bytes in the stats. */ - priv->stats.bytes_read -= bytes_waiting; + dev->priv->stats.bytes_read -= bytes_waiting; } -EXPORT_SYMBOL_GPL(ps3_vuart_clear_rx_bytes); /** * struct list_buffer - An element for a port device fifo buffer list. @@ -477,7 +435,6 @@ struct list_buffer { /** * ps3_vuart_write - the entry point for writing data to a port - * @dev: The struct ps3_system_bus_device instance. * * If the port is idle on entry as much of the incoming data is written to * the port as the port will accept. Otherwise a list buffer is created @@ -485,26 +442,25 @@ struct list_buffer { * then enqueued for transmision via the transmit interrupt. */ -int ps3_vuart_write(struct ps3_system_bus_device *dev, const void *buf, +int ps3_vuart_write(struct ps3_vuart_port_device *dev, const void* buf, unsigned int bytes) { static unsigned long dbg_number; int result; - struct ps3_vuart_port_priv *priv = to_port_priv(dev); unsigned long flags; struct list_buffer *lb; dev_dbg(&dev->core, "%s:%d: %u(%xh) bytes\n", __func__, __LINE__, bytes, bytes); - spin_lock_irqsave(&priv->tx_list.lock, flags); + spin_lock_irqsave(&dev->priv->tx_list.lock, flags); - if (list_empty(&priv->tx_list.head)) { + if (list_empty(&dev->priv->tx_list.head)) { unsigned long bytes_written; result = ps3_vuart_raw_write(dev, buf, bytes, &bytes_written); - spin_unlock_irqrestore(&priv->tx_list.lock, flags); + spin_unlock_irqrestore(&dev->priv->tx_list.lock, flags); if (result) { dev_dbg(&dev->core, @@ -522,7 +478,7 @@ int ps3_vuart_write(struct ps3_system_bus_device *dev, const void *buf, bytes -= bytes_written; buf += bytes_written; } else - spin_unlock_irqrestore(&priv->tx_list.lock, flags); + spin_unlock_irqrestore(&dev->priv->tx_list.lock, flags); lb = kmalloc(sizeof(struct list_buffer) + bytes, GFP_KERNEL); @@ -535,86 +491,29 @@ int ps3_vuart_write(struct ps3_system_bus_device *dev, const void *buf, lb->tail = lb->data + bytes; lb->dbg_number = ++dbg_number; - spin_lock_irqsave(&priv->tx_list.lock, flags); - list_add_tail(&lb->link, &priv->tx_list.head); + spin_lock_irqsave(&dev->priv->tx_list.lock, flags); + list_add_tail(&lb->link, &dev->priv->tx_list.head); ps3_vuart_enable_interrupt_tx(dev); - spin_unlock_irqrestore(&priv->tx_list.lock, flags); + spin_unlock_irqrestore(&dev->priv->tx_list.lock, flags); dev_dbg(&dev->core, "%s:%d: queued buf_%lu, %xh bytes\n", __func__, __LINE__, lb->dbg_number, bytes); return 0; } -EXPORT_SYMBOL_GPL(ps3_vuart_write); - -/** - * ps3_vuart_queue_rx_bytes - Queue waiting bytes into the buffer list. - * @dev: The struct ps3_system_bus_device instance. - * @bytes_queued: Number of bytes queued to the buffer list. - * - * Must be called with priv->rx_list.lock held. - */ - -static int ps3_vuart_queue_rx_bytes(struct ps3_system_bus_device *dev, - u64 *bytes_queued) -{ - static unsigned long dbg_number; - int result; - struct ps3_vuart_port_priv *priv = to_port_priv(dev); - struct list_buffer *lb; - u64 bytes; - - *bytes_queued = 0; - - result = ps3_vuart_get_rx_bytes_waiting(dev, &bytes); - BUG_ON(result); - - if (result) - return -EIO; - - if (!bytes) - return 0; - - /* Add some extra space for recently arrived data. */ - - bytes += 128; - - lb = kmalloc(sizeof(struct list_buffer) + bytes, GFP_ATOMIC); - - if (!lb) - return -ENOMEM; - - ps3_vuart_raw_read(dev, lb->data, bytes, &bytes); - - lb->head = lb->data; - lb->tail = lb->data + bytes; - lb->dbg_number = ++dbg_number; - - list_add_tail(&lb->link, &priv->rx_list.head); - priv->rx_list.bytes_held += bytes; - - dev_dbg(&dev->core, "%s:%d: buf_%lu: queued %lxh bytes\n", - __func__, __LINE__, lb->dbg_number, bytes); - - *bytes_queued = bytes; - - return 0; -} /** - * ps3_vuart_read - The entry point for reading data from a port. + * ps3_vuart_read - the entry point for reading data from a port * - * Queue data waiting at the port, and if enough bytes to satisfy the request - * are held in the buffer list those bytes are dequeued and copied to the - * caller's buffer. Emptied list buffers are retiered. If the request cannot - * be statified by bytes held in the list buffers -EAGAIN is returned. + * If enough bytes to satisfy the request are held in the buffer list those + * bytes are dequeued and copied to the caller's buffer. Emptied list buffers + * are retiered. If the request cannot be statified by bytes held in the list + * buffers -EAGAIN is returned. */ -int ps3_vuart_read(struct ps3_system_bus_device *dev, void *buf, +int ps3_vuart_read(struct ps3_vuart_port_device *dev, void* buf, unsigned int bytes) { - int result; - struct ps3_vuart_port_priv *priv = to_port_priv(dev); unsigned long flags; struct list_buffer *lb, *n; unsigned long bytes_read; @@ -622,37 +521,30 @@ int ps3_vuart_read(struct ps3_system_bus_device *dev, void *buf, dev_dbg(&dev->core, "%s:%d: %u(%xh) bytes\n", __func__, __LINE__, bytes, bytes); - spin_lock_irqsave(&priv->rx_list.lock, flags); - - /* Queue rx bytes here for polled reads. */ + spin_lock_irqsave(&dev->priv->rx_list.lock, flags); - while (priv->rx_list.bytes_held < bytes) { - u64 tmp; - - result = ps3_vuart_queue_rx_bytes(dev, &tmp); - if (result || !tmp) { - dev_dbg(&dev->core, "%s:%d: starved for %lxh bytes\n", - __func__, __LINE__, - bytes - priv->rx_list.bytes_held); - spin_unlock_irqrestore(&priv->rx_list.lock, flags); - return -EAGAIN; - } + if (dev->priv->rx_list.bytes_held < bytes) { + spin_unlock_irqrestore(&dev->priv->rx_list.lock, flags); + dev_dbg(&dev->core, "%s:%d: starved for %lxh bytes\n", + __func__, __LINE__, + bytes - dev->priv->rx_list.bytes_held); + return -EAGAIN; } - list_for_each_entry_safe(lb, n, &priv->rx_list.head, link) { + list_for_each_entry_safe(lb, n, &dev->priv->rx_list.head, link) { bytes_read = min((unsigned int)(lb->tail - lb->head), bytes); memcpy(buf, lb->head, bytes_read); buf += bytes_read; bytes -= bytes_read; - priv->rx_list.bytes_held -= bytes_read; + dev->priv->rx_list.bytes_held -= bytes_read; if (bytes_read < lb->tail - lb->head) { lb->head += bytes_read; dev_dbg(&dev->core, "%s:%d: buf_%lu: dequeued %lxh " "bytes\n", __func__, __LINE__, lb->dbg_number, bytes_read); - spin_unlock_irqrestore(&priv->rx_list.lock, flags); + spin_unlock_irqrestore(&dev->priv->rx_list.lock, flags); return 0; } @@ -664,32 +556,16 @@ int ps3_vuart_read(struct ps3_system_bus_device *dev, void *buf, kfree(lb); } - spin_unlock_irqrestore(&priv->rx_list.lock, flags); + spin_unlock_irqrestore(&dev->priv->rx_list.lock, flags); return 0; } -EXPORT_SYMBOL_GPL(ps3_vuart_read); - -/** - * ps3_vuart_work - Asynchronous read handler. - */ - -static void ps3_vuart_work(struct work_struct *work) -{ - struct ps3_system_bus_device *dev = - ps3_vuart_work_to_system_bus_dev(work); - struct ps3_vuart_port_driver *drv = - ps3_system_bus_dev_to_vuart_drv(dev); - - BUG_ON(!drv); - drv->work(dev); -} -int ps3_vuart_read_async(struct ps3_system_bus_device *dev, unsigned int bytes) +int ps3_vuart_read_async(struct ps3_vuart_port_device *dev, work_func_t func, + unsigned int bytes) { - struct ps3_vuart_port_priv *priv = to_port_priv(dev); unsigned long flags; - if (priv->rx_list.work.trigger) { + if(dev->priv->work.trigger) { dev_dbg(&dev->core, "%s:%d: warning, multiple calls\n", __func__, __LINE__); return -EAGAIN; @@ -697,32 +573,30 @@ int ps3_vuart_read_async(struct ps3_system_bus_device *dev, unsigned int bytes) BUG_ON(!bytes); - PREPARE_WORK(&priv->rx_list.work.work, ps3_vuart_work); + PREPARE_WORK(&dev->priv->work.work, func); - spin_lock_irqsave(&priv->rx_list.lock, flags); - if (priv->rx_list.bytes_held >= bytes) { + spin_lock_irqsave(&dev->priv->work.lock, flags); + if(dev->priv->rx_list.bytes_held >= bytes) { dev_dbg(&dev->core, "%s:%d: schedule_work %xh bytes\n", __func__, __LINE__, bytes); - schedule_work(&priv->rx_list.work.work); - spin_unlock_irqrestore(&priv->rx_list.lock, flags); + schedule_work(&dev->priv->work.work); + spin_unlock_irqrestore(&dev->priv->work.lock, flags); return 0; } - priv->rx_list.work.trigger = bytes; - spin_unlock_irqrestore(&priv->rx_list.lock, flags); + dev->priv->work.trigger = bytes; + spin_unlock_irqrestore(&dev->priv->work.lock, flags); dev_dbg(&dev->core, "%s:%d: waiting for %u(%xh) bytes\n", __func__, __LINE__, bytes, bytes); return 0; } -EXPORT_SYMBOL_GPL(ps3_vuart_read_async); -void ps3_vuart_cancel_async(struct ps3_system_bus_device *dev) +void ps3_vuart_cancel_async(struct ps3_vuart_port_device *dev) { - to_port_priv(dev)->rx_list.work.trigger = 0; + dev->priv->work.trigger = 0; } -EXPORT_SYMBOL_GPL(ps3_vuart_cancel_async); /** * ps3_vuart_handle_interrupt_tx - third stage transmit interrupt handler @@ -732,19 +606,18 @@ EXPORT_SYMBOL_GPL(ps3_vuart_cancel_async); * adjusts the final list buffer state for a partial write. */ -static int ps3_vuart_handle_interrupt_tx(struct ps3_system_bus_device *dev) +static int ps3_vuart_handle_interrupt_tx(struct ps3_vuart_port_device *dev) { int result = 0; - struct ps3_vuart_port_priv *priv = to_port_priv(dev); unsigned long flags; struct list_buffer *lb, *n; unsigned long bytes_total = 0; dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__); - spin_lock_irqsave(&priv->tx_list.lock, flags); + spin_lock_irqsave(&dev->priv->tx_list.lock, flags); - list_for_each_entry_safe(lb, n, &priv->tx_list.head, link) { + list_for_each_entry_safe(lb, n, &dev->priv->tx_list.head, link) { unsigned long bytes_written; @@ -778,7 +651,7 @@ static int ps3_vuart_handle_interrupt_tx(struct ps3_system_bus_device *dev) ps3_vuart_disable_interrupt_tx(dev); port_full: - spin_unlock_irqrestore(&priv->tx_list.lock, flags); + spin_unlock_irqrestore(&dev->priv->tx_list.lock, flags); dev_dbg(&dev->core, "%s:%d wrote %lxh bytes total\n", __func__, __LINE__, bytes_total); return result; @@ -792,37 +665,60 @@ static int ps3_vuart_handle_interrupt_tx(struct ps3_system_bus_device *dev) * buffer list. Buffer list data is dequeued via ps3_vuart_read. */ -static int ps3_vuart_handle_interrupt_rx(struct ps3_system_bus_device *dev) +static int ps3_vuart_handle_interrupt_rx(struct ps3_vuart_port_device *dev) { - int result; - struct ps3_vuart_port_priv *priv = to_port_priv(dev); + static unsigned long dbg_number; + int result = 0; unsigned long flags; - u64 bytes; + struct list_buffer *lb; + unsigned long bytes; dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__); - spin_lock_irqsave(&priv->rx_list.lock, flags); - result = ps3_vuart_queue_rx_bytes(dev, &bytes); + result = ps3_vuart_get_rx_bytes_waiting(dev, &bytes); - if (result) { - spin_unlock_irqrestore(&priv->rx_list.lock, flags); - return result; - } + if (result) + return -EIO; + + BUG_ON(!bytes); + + /* Add some extra space for recently arrived data. */ + + bytes += 128; - if (priv->rx_list.work.trigger && priv->rx_list.bytes_held - >= priv->rx_list.work.trigger) { + lb = kmalloc(sizeof(struct list_buffer) + bytes, GFP_ATOMIC); + + if (!lb) + return -ENOMEM; + + ps3_vuart_raw_read(dev, lb->data, bytes, &bytes); + + lb->head = lb->data; + lb->tail = lb->data + bytes; + lb->dbg_number = ++dbg_number; + + spin_lock_irqsave(&dev->priv->rx_list.lock, flags); + list_add_tail(&lb->link, &dev->priv->rx_list.head); + dev->priv->rx_list.bytes_held += bytes; + spin_unlock_irqrestore(&dev->priv->rx_list.lock, flags); + + dev_dbg(&dev->core, "%s:%d: buf_%lu: queued %lxh bytes\n", + __func__, __LINE__, lb->dbg_number, bytes); + + spin_lock_irqsave(&dev->priv->work.lock, flags); + if(dev->priv->work.trigger + && dev->priv->rx_list.bytes_held >= dev->priv->work.trigger) { dev_dbg(&dev->core, "%s:%d: schedule_work %lxh bytes\n", - __func__, __LINE__, priv->rx_list.work.trigger); - priv->rx_list.work.trigger = 0; - schedule_work(&priv->rx_list.work.work); + __func__, __LINE__, dev->priv->work.trigger); + dev->priv->work.trigger = 0; + schedule_work(&dev->priv->work.work); } - - spin_unlock_irqrestore(&priv->rx_list.lock, flags); - return result; + spin_unlock_irqrestore(&dev->priv->work.lock, flags); + return 0; } static int ps3_vuart_handle_interrupt_disconnect( - struct ps3_system_bus_device *dev) + struct ps3_vuart_port_device *dev) { dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__); BUG_ON("no support"); @@ -837,10 +733,9 @@ static int ps3_vuart_handle_interrupt_disconnect( * stage handler after one iteration. */ -static int ps3_vuart_handle_port_interrupt(struct ps3_system_bus_device *dev) +static int ps3_vuart_handle_port_interrupt(struct ps3_vuart_port_device *dev) { int result; - struct ps3_vuart_port_priv *priv = to_port_priv(dev); unsigned long status; result = ps3_vuart_get_interrupt_status(dev, &status); @@ -852,21 +747,21 @@ static int ps3_vuart_handle_port_interrupt(struct ps3_system_bus_device *dev) status); if (status & INTERRUPT_MASK_DISCONNECT) { - priv->stats.disconnect_interrupts++; + dev->priv->stats.disconnect_interrupts++; result = ps3_vuart_handle_interrupt_disconnect(dev); if (result) ps3_vuart_disable_interrupt_disconnect(dev); } if (status & INTERRUPT_MASK_TX) { - priv->stats.tx_interrupts++; + dev->priv->stats.tx_interrupts++; result = ps3_vuart_handle_interrupt_tx(dev); if (result) ps3_vuart_disable_interrupt_tx(dev); } if (status & INTERRUPT_MASK_RX) { - priv->stats.rx_interrupts++; + dev->priv->stats.rx_interrupts++; result = ps3_vuart_handle_interrupt_rx(dev); if (result) ps3_vuart_disable_interrupt_rx(dev); @@ -876,11 +771,11 @@ static int ps3_vuart_handle_port_interrupt(struct ps3_system_bus_device *dev) } struct vuart_bus_priv { - struct ports_bmp *bmp; + const struct ports_bmp bmp; unsigned int virq; struct semaphore probe_mutex; int use_count; - struct ps3_system_bus_device *devices[PORT_COUNT]; + struct ps3_vuart_port_device *devices[PORT_COUNT]; } static vuart_bus_priv; /** @@ -893,16 +788,17 @@ struct vuart_bus_priv { static irqreturn_t ps3_vuart_irq_handler(int irq, void *_private) { - struct vuart_bus_priv *bus_priv = _private; + struct vuart_bus_priv *bus_priv; - BUG_ON(!bus_priv); + BUG_ON(!_private); + bus_priv = (struct vuart_bus_priv *)_private; while (1) { unsigned int port; - dump_ports_bmp(bus_priv->bmp); + dump_ports_bmp(&bus_priv->bmp); - port = (BITS_PER_LONG - 1) - __ilog2(bus_priv->bmp->status); + port = (BITS_PER_LONG - 1) - __ilog2(bus_priv->bmp.status); if (port == BITS_PER_LONG) break; @@ -916,144 +812,100 @@ static irqreturn_t ps3_vuart_irq_handler(int irq, void *_private) return IRQ_HANDLED; } -static int ps3_vuart_bus_interrupt_get(void) +static int ps3_vuart_match(struct device *_dev, struct device_driver *_drv) { int result; + struct ps3_vuart_port_driver *drv = to_ps3_vuart_port_driver(_drv); + struct ps3_vuart_port_device *dev = to_ps3_vuart_port_device(_dev); - pr_debug(" -> %s:%d\n", __func__, __LINE__); - - vuart_bus_priv.use_count++; - - BUG_ON(vuart_bus_priv.use_count > 2); - - if (vuart_bus_priv.use_count != 1) { - return 0; - } - - BUG_ON(vuart_bus_priv.bmp); - - vuart_bus_priv.bmp = kzalloc(sizeof(struct ports_bmp), GFP_KERNEL); - - if (!vuart_bus_priv.bmp) { - pr_debug("%s:%d: kzalloc failed.\n", __func__, __LINE__); - result = -ENOMEM; - goto fail_bmp_malloc; - } - - result = ps3_vuart_irq_setup(PS3_BINDING_CPU_ANY, vuart_bus_priv.bmp, - &vuart_bus_priv.virq); - - if (result) { - pr_debug("%s:%d: ps3_vuart_irq_setup failed (%d)\n", - __func__, __LINE__, result); - result = -EPERM; - goto fail_alloc_irq; - } - - result = request_irq(vuart_bus_priv.virq, ps3_vuart_irq_handler, - IRQF_DISABLED, "vuart", &vuart_bus_priv); + result = dev->match_id == drv->match_id; - if (result) { - pr_debug("%s:%d: request_irq failed (%d)\n", - __func__, __LINE__, result); - goto fail_request_irq; - } + dev_info(&dev->core, "%s:%d: dev=%u(%s), drv=%u(%s): %s\n", __func__, + __LINE__, dev->match_id, dev->core.bus_id, drv->match_id, + drv->core.name, (result ? "match" : "miss")); - pr_debug(" <- %s:%d: ok\n", __func__, __LINE__); return result; - -fail_request_irq: - ps3_vuart_irq_destroy(vuart_bus_priv.virq); - vuart_bus_priv.virq = NO_IRQ; -fail_alloc_irq: - kfree(vuart_bus_priv.bmp); - vuart_bus_priv.bmp = NULL; -fail_bmp_malloc: - vuart_bus_priv.use_count--; - pr_debug(" <- %s:%d: failed\n", __func__, __LINE__); - return result; -} - -static int ps3_vuart_bus_interrupt_put(void) -{ - pr_debug(" -> %s:%d\n", __func__, __LINE__); - - vuart_bus_priv.use_count--; - - BUG_ON(vuart_bus_priv.use_count < 0); - - if (vuart_bus_priv.use_count != 0) - return 0; - - free_irq(vuart_bus_priv.virq, &vuart_bus_priv); - - ps3_vuart_irq_destroy(vuart_bus_priv.virq); - vuart_bus_priv.virq = NO_IRQ; - - kfree(vuart_bus_priv.bmp); - vuart_bus_priv.bmp = NULL; - - pr_debug(" <- %s:%d\n", __func__, __LINE__); - return 0; } -static int ps3_vuart_probe(struct ps3_system_bus_device *dev) +static int ps3_vuart_probe(struct device *_dev) { int result; - struct ps3_vuart_port_driver *drv; - struct ps3_vuart_port_priv *priv = NULL; + unsigned int port_number; + struct ps3_vuart_port_device *dev = to_ps3_vuart_port_device(_dev); + struct ps3_vuart_port_driver *drv = + to_ps3_vuart_port_driver(_dev->driver); dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__); - drv = ps3_system_bus_dev_to_vuart_drv(dev); - - dev_dbg(&dev->core, "%s:%d: (%s)\n", __func__, __LINE__, - drv->core.core.name); - BUG_ON(!drv); - if (dev->port_number >= PORT_COUNT) { - BUG(); - return -EINVAL; - } - down(&vuart_bus_priv.probe_mutex); - result = ps3_vuart_bus_interrupt_get(); + /* Setup vuart_bus_priv.devices[]. */ - if (result) - goto fail_setup_interrupt; + result = ps3_vuart_match_id_to_port(dev->match_id, + &port_number); - if (vuart_bus_priv.devices[dev->port_number]) { + if (result) { + dev_dbg(&dev->core, "%s:%d: unknown match_id (%d)\n", + __func__, __LINE__, dev->match_id); + result = -EINVAL; + goto fail_match; + } + + if (vuart_bus_priv.devices[port_number]) { dev_dbg(&dev->core, "%s:%d: port busy (%d)\n", __func__, - __LINE__, dev->port_number); + __LINE__, port_number); result = -EBUSY; - goto fail_busy; + goto fail_match; } - vuart_bus_priv.devices[dev->port_number] = dev; + vuart_bus_priv.devices[port_number] = dev; - /* Setup dev->driver_priv. */ + /* Setup dev->priv. */ - dev->driver_priv = kzalloc(sizeof(struct ps3_vuart_port_priv), - GFP_KERNEL); + dev->priv = kzalloc(sizeof(struct ps3_vuart_port_priv), GFP_KERNEL); - if (!dev->driver_priv) { + if (!dev->priv) { result = -ENOMEM; - goto fail_dev_malloc; + goto fail_alloc; } - priv = to_port_priv(dev); + dev->priv->port_number = port_number; + + INIT_LIST_HEAD(&dev->priv->tx_list.head); + spin_lock_init(&dev->priv->tx_list.lock); - INIT_LIST_HEAD(&priv->tx_list.head); - spin_lock_init(&priv->tx_list.lock); + INIT_LIST_HEAD(&dev->priv->rx_list.head); + spin_lock_init(&dev->priv->rx_list.lock); - INIT_LIST_HEAD(&priv->rx_list.head); - spin_lock_init(&priv->rx_list.lock); + INIT_WORK(&dev->priv->work.work, NULL); + spin_lock_init(&dev->priv->work.lock); + dev->priv->work.trigger = 0; + dev->priv->work.dev = dev; - INIT_WORK(&priv->rx_list.work.work, NULL); - priv->rx_list.work.trigger = 0; - priv->rx_list.work.dev = dev; + if (++vuart_bus_priv.use_count == 1) { + + result = ps3_vuart_irq_setup(PS3_BINDING_CPU_ANY, + (void*)&vuart_bus_priv.bmp.status, &vuart_bus_priv.virq); + + if (result) { + dev_dbg(&dev->core, + "%s:%d: ps3_vuart_irq_setup failed (%d)\n", + __func__, __LINE__, result); + result = -EPERM; + goto fail_alloc_irq; + } + + result = request_irq(vuart_bus_priv.virq, ps3_vuart_irq_handler, + IRQF_DISABLED, "vuart", &vuart_bus_priv); + + if (result) { + dev_info(&dev->core, "%s:%d: request_irq failed (%d)\n", + __func__, __LINE__, result); + goto fail_request_irq; + } + } /* clear stale pending interrupts */ @@ -1084,179 +936,165 @@ static int ps3_vuart_probe(struct ps3_system_bus_device *dev) fail_probe: ps3_vuart_set_interrupt_mask(dev, 0); - kfree(dev->driver_priv); - dev->driver_priv = NULL; -fail_dev_malloc: - vuart_bus_priv.devices[dev->port_number] = NULL; -fail_busy: - ps3_vuart_bus_interrupt_put(); -fail_setup_interrupt: +fail_request_irq: + ps3_vuart_irq_destroy(vuart_bus_priv.virq); + vuart_bus_priv.virq = NO_IRQ; +fail_alloc_irq: + --vuart_bus_priv.use_count; + kfree(dev->priv); + dev->priv = NULL; +fail_alloc: + vuart_bus_priv.devices[port_number] = NULL; +fail_match: up(&vuart_bus_priv.probe_mutex); - dev_dbg(&dev->core, "%s:%d: failed\n", __func__, __LINE__); + dev_dbg(&dev->core, "%s:%d failed\n", __func__, __LINE__); return result; } -/** - * ps3_vuart_cleanup - common cleanup helper. - * @dev: The struct ps3_system_bus_device instance. - * - * Cleans interrupts and HV resources. Must be called with - * vuart_bus_priv.probe_mutex held. Used by ps3_vuart_remove and - * ps3_vuart_shutdown. After this call, polled reading will still work. - */ - -static int ps3_vuart_cleanup(struct ps3_system_bus_device *dev) -{ - dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__); - - ps3_vuart_cancel_async(dev); - ps3_vuart_set_interrupt_mask(dev, 0); - ps3_vuart_bus_interrupt_put(); - return 0; -} - -/** - * ps3_vuart_remove - Completely clean the device instance. - * @dev: The struct ps3_system_bus_device instance. - * - * Cleans all memory, interrupts and HV resources. After this call the - * device can no longer be used. - */ - -static int ps3_vuart_remove(struct ps3_system_bus_device *dev) +static int ps3_vuart_remove(struct device *_dev) { - struct ps3_vuart_port_priv *priv = to_port_priv(dev); - struct ps3_vuart_port_driver *drv; - - BUG_ON(!dev); + struct ps3_vuart_port_device *dev = to_ps3_vuart_port_device(_dev); + struct ps3_vuart_port_driver *drv = + to_ps3_vuart_port_driver(_dev->driver); down(&vuart_bus_priv.probe_mutex); - dev_dbg(&dev->core, " -> %s:%d: match_id %d\n", __func__, __LINE__, - dev->match_id); + dev_dbg(&dev->core, "%s:%d: %s\n", __func__, __LINE__, + dev->core.bus_id); - if (!dev->core.driver) { - dev_dbg(&dev->core, "%s:%d: no driver bound\n", __func__, - __LINE__); - up(&vuart_bus_priv.probe_mutex); - return 0; - } + BUG_ON(vuart_bus_priv.use_count < 1); - drv = ps3_system_bus_dev_to_vuart_drv(dev); + if (drv->remove) + drv->remove(dev); + else + dev_dbg(&dev->core, "%s:%d: %s no remove method\n", __func__, + __LINE__, dev->core.bus_id); - BUG_ON(!drv); + vuart_bus_priv.devices[dev->priv->port_number] = NULL; - if (drv->remove) { - drv->remove(dev); - } else { - dev_dbg(&dev->core, "%s:%d: no remove method\n", __func__, - __LINE__); + if (--vuart_bus_priv.use_count == 0) { BUG(); + free_irq(vuart_bus_priv.virq, &vuart_bus_priv); + ps3_vuart_irq_destroy(vuart_bus_priv.virq); + vuart_bus_priv.virq = NO_IRQ; } - ps3_vuart_cleanup(dev); - - vuart_bus_priv.devices[dev->port_number] = NULL; - kfree(priv); - priv = NULL; + kfree(dev->priv); + dev->priv = NULL; - dev_dbg(&dev->core, " <- %s:%d\n", __func__, __LINE__); up(&vuart_bus_priv.probe_mutex); return 0; } -/** - * ps3_vuart_shutdown - Cleans interrupts and HV resources. - * @dev: The struct ps3_system_bus_device instance. - * - * Cleans interrupts and HV resources. After this call the - * device can still be used in polling mode. This behavior required - * by sys-manager to be able to complete the device power operation - * sequence. - */ - -static int ps3_vuart_shutdown(struct ps3_system_bus_device *dev) +static void ps3_vuart_shutdown(struct device *_dev) { - struct ps3_vuart_port_driver *drv; - - BUG_ON(!dev); - - down(&vuart_bus_priv.probe_mutex); - - dev_dbg(&dev->core, " -> %s:%d: match_id %d\n", __func__, __LINE__, - dev->match_id); - - if (!dev->core.driver) { - dev_dbg(&dev->core, "%s:%d: no driver bound\n", __func__, - __LINE__); - up(&vuart_bus_priv.probe_mutex); - return 0; - } - - drv = ps3_system_bus_dev_to_vuart_drv(dev); + struct ps3_vuart_port_device *dev = to_ps3_vuart_port_device(_dev); + struct ps3_vuart_port_driver *drv = + to_ps3_vuart_port_driver(_dev->driver); - BUG_ON(!drv); + dev_dbg(&dev->core, "%s:%d: %s\n", __func__, __LINE__, + dev->core.bus_id); if (drv->shutdown) drv->shutdown(dev); - else if (drv->remove) { - dev_dbg(&dev->core, "%s:%d: no shutdown, calling remove\n", - __func__, __LINE__); - drv->remove(dev); - } else { - dev_dbg(&dev->core, "%s:%d: no shutdown method\n", __func__, - __LINE__); - BUG(); - } - - ps3_vuart_cleanup(dev); + else + dev_dbg(&dev->core, "%s:%d: %s no shutdown method\n", __func__, + __LINE__, dev->core.bus_id); +} - dev_dbg(&dev->core, " <- %s:%d\n", __func__, __LINE__); +/** + * ps3_vuart_bus - The vuart bus instance. + * + * The vuart is managed as a bus that port devices connect to. + */ - up(&vuart_bus_priv.probe_mutex); - return 0; -} +struct bus_type ps3_vuart_bus = { + .name = "ps3_vuart", + .match = ps3_vuart_match, + .probe = ps3_vuart_probe, + .remove = ps3_vuart_remove, + .shutdown = ps3_vuart_shutdown, +}; -static int __init ps3_vuart_bus_init(void) +int __init ps3_vuart_bus_init(void) { + int result; + pr_debug("%s:%d:\n", __func__, __LINE__); if (!firmware_has_feature(FW_FEATURE_PS3_LV1)) return -ENODEV; init_MUTEX(&vuart_bus_priv.probe_mutex); + result = bus_register(&ps3_vuart_bus); + BUG_ON(result); - return 0; + return result; } -static void __exit ps3_vuart_bus_exit(void) +void __exit ps3_vuart_bus_exit(void) { pr_debug("%s:%d:\n", __func__, __LINE__); + bus_unregister(&ps3_vuart_bus); } core_initcall(ps3_vuart_bus_init); module_exit(ps3_vuart_bus_exit); /** - * ps3_vuart_port_driver_register - Add a vuart port device driver. + * ps3_vuart_port_release_device - Remove a vuart port device. */ -int ps3_vuart_port_driver_register(struct ps3_vuart_port_driver *drv) +static void ps3_vuart_port_release_device(struct device *_dev) { - int result; +#if defined(DEBUG) + struct ps3_vuart_port_device *dev = to_ps3_vuart_port_device(_dev); - pr_debug("%s:%d: (%s)\n", __func__, __LINE__, drv->core.core.name); + dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__); + + BUG_ON(dev->priv && "forgot to free"); + memset(&dev->core, 0, sizeof(dev->core)); +#endif +} - BUG_ON(!drv->core.match_id); - BUG_ON(!drv->core.core.name); +/** + * ps3_vuart_port_device_register - Add a vuart port device. + */ + +int ps3_vuart_port_device_register(struct ps3_vuart_port_device *dev) +{ + static unsigned int dev_count = 1; - drv->core.probe = ps3_vuart_probe; - drv->core.remove = ps3_vuart_remove; - drv->core.shutdown = ps3_vuart_shutdown; + BUG_ON(dev->priv && "forgot to free"); - result = ps3_system_bus_driver_register(&drv->core); + dev->core.parent = NULL; + dev->core.bus = &ps3_vuart_bus; + dev->core.release = ps3_vuart_port_release_device; + + snprintf(dev->core.bus_id, sizeof(dev->core.bus_id), "vuart_%02x", + dev_count++); + + dev_dbg(&dev->core, "%s:%d register\n", __func__, __LINE__); + + return device_register(&dev->core); +} + +EXPORT_SYMBOL_GPL(ps3_vuart_port_device_register); + +/** + * ps3_vuart_port_driver_register - Add a vuart port device driver. + */ + +int ps3_vuart_port_driver_register(struct ps3_vuart_port_driver *drv) +{ + int result; + + pr_debug("%s:%d: (%s)\n", __func__, __LINE__, drv->core.name); + drv->core.bus = &ps3_vuart_bus; + result = driver_register(&drv->core); return result; } + EXPORT_SYMBOL_GPL(ps3_vuart_port_driver_register); /** @@ -1265,7 +1103,8 @@ EXPORT_SYMBOL_GPL(ps3_vuart_port_driver_register); void ps3_vuart_port_driver_unregister(struct ps3_vuart_port_driver *drv) { - pr_debug("%s:%d: (%s)\n", __func__, __LINE__, drv->core.core.name); - ps3_system_bus_driver_unregister(&drv->core); + pr_debug("%s:%d: (%s)\n", __func__, __LINE__, drv->core.name); + driver_unregister(&drv->core); } + EXPORT_SYMBOL_GPL(ps3_vuart_port_driver_unregister); diff --git a/trunk/drivers/ps3/vuart.h b/trunk/drivers/ps3/vuart.h index eb7f6d94a890..1be992d568c8 100644 --- a/trunk/drivers/ps3/vuart.h +++ b/trunk/drivers/ps3/vuart.h @@ -34,7 +34,29 @@ struct ps3_vuart_stats { struct ps3_vuart_work { struct work_struct work; unsigned long trigger; - struct ps3_system_bus_device *dev; /* to convert work to device */ + spinlock_t lock; + struct ps3_vuart_port_device* dev; /* to convert work to device */ +}; + +/** + * struct ps3_vuart_port_priv - private vuart device data. + */ + +struct ps3_vuart_port_priv { + unsigned int port_number; + u64 interrupt_mask; + + struct { + spinlock_t lock; + struct list_head head; + } tx_list; + struct { + unsigned long bytes_held; + spinlock_t lock; + struct list_head head; + } rx_list; + struct ps3_vuart_stats stats; + struct ps3_vuart_work work; }; /** @@ -42,30 +64,32 @@ struct ps3_vuart_work { */ struct ps3_vuart_port_driver { - struct ps3_system_bus_driver core; - int (*probe)(struct ps3_system_bus_device *); - int (*remove)(struct ps3_system_bus_device *); - void (*shutdown)(struct ps3_system_bus_device *); - void (*work)(struct ps3_system_bus_device *); - /* int (*tx_event)(struct ps3_system_bus_device *dev); */ - /* int (*rx_event)(struct ps3_system_bus_device *dev); */ - /* int (*disconnect_event)(struct ps3_system_bus_device *dev); */ - /* int (*suspend)(struct ps3_system_bus_device *, pm_message_t); */ - /* int (*resume)(struct ps3_system_bus_device *); */ + enum ps3_match_id match_id; + struct device_driver core; + int (*probe)(struct ps3_vuart_port_device *); + int (*remove)(struct ps3_vuart_port_device *); + void (*shutdown)(struct ps3_vuart_port_device *); + int (*tx_event)(struct ps3_vuart_port_device *dev); + int (*rx_event)(struct ps3_vuart_port_device *dev); + int (*disconnect_event)(struct ps3_vuart_port_device *dev); + /* int (*suspend)(struct ps3_vuart_port_device *, pm_message_t); */ + /* int (*resume)(struct ps3_vuart_port_device *); */ }; int ps3_vuart_port_driver_register(struct ps3_vuart_port_driver *drv); void ps3_vuart_port_driver_unregister(struct ps3_vuart_port_driver *drv); -static inline struct ps3_vuart_port_driver * - ps3_system_bus_dev_to_vuart_drv(struct ps3_system_bus_device *_dev) +static inline struct ps3_vuart_port_driver *to_ps3_vuart_port_driver( + struct device_driver *_drv) +{ + return container_of(_drv, struct ps3_vuart_port_driver, core); +} +static inline struct ps3_vuart_port_device *to_ps3_vuart_port_device( + struct device *_dev) { - struct ps3_system_bus_driver *sbd = - ps3_system_bus_dev_to_system_bus_drv(_dev); - BUG_ON(!sbd); - return container_of(sbd, struct ps3_vuart_port_driver, core); + return container_of(_dev, struct ps3_vuart_port_device, core); } -static inline struct ps3_system_bus_device *ps3_vuart_work_to_system_bus_dev( +static inline struct ps3_vuart_port_device *ps3_vuart_work_to_port_device( struct work_struct *_work) { struct ps3_vuart_work *vw = container_of(_work, struct ps3_vuart_work, @@ -73,13 +97,14 @@ static inline struct ps3_system_bus_device *ps3_vuart_work_to_system_bus_dev( return vw->dev; } -int ps3_vuart_write(struct ps3_system_bus_device *dev, const void *buf, +int ps3_vuart_write(struct ps3_vuart_port_device *dev, const void* buf, + unsigned int bytes); +int ps3_vuart_read(struct ps3_vuart_port_device *dev, void* buf, unsigned int bytes); -int ps3_vuart_read(struct ps3_system_bus_device *dev, void *buf, +int ps3_vuart_read_async(struct ps3_vuart_port_device *dev, work_func_t func, unsigned int bytes); -int ps3_vuart_read_async(struct ps3_system_bus_device *dev, unsigned int bytes); -void ps3_vuart_cancel_async(struct ps3_system_bus_device *dev); -void ps3_vuart_clear_rx_bytes(struct ps3_system_bus_device *dev, +void ps3_vuart_cancel_async(struct ps3_vuart_port_device *dev); +void ps3_vuart_clear_rx_bytes(struct ps3_vuart_port_device *dev, unsigned int bytes); #endif diff --git a/trunk/drivers/rtc/Kconfig b/trunk/drivers/rtc/Kconfig index 83b071b6ece4..4e4c10a7fd3a 100644 --- a/trunk/drivers/rtc/Kconfig +++ b/trunk/drivers/rtc/Kconfig @@ -246,7 +246,7 @@ comment "Platform RTC drivers" config RTC_DRV_CMOS tristate "PC-style 'CMOS'" depends on RTC_CLASS && (X86 || ALPHA || ARM26 || ARM \ - || M32R || ATARI || PPC || MIPS) + || M32R || ATARI || POWERPC || MIPS) help Say "yes" here to get direct support for the real time clock found in every PC or ACPI-based system, and some other boards. diff --git a/trunk/drivers/s390/net/qeth.h b/trunk/drivers/s390/net/qeth.h index ec18bae05df0..b34eb82edd98 100644 --- a/trunk/drivers/s390/net/qeth.h +++ b/trunk/drivers/s390/net/qeth.h @@ -211,10 +211,6 @@ struct qeth_perf_stats { /* initial values when measuring starts */ unsigned long initial_rx_packets; unsigned long initial_tx_packets; - /* inbound scatter gather data */ - unsigned int sg_skbs_rx; - unsigned int sg_frags_rx; - unsigned int sg_alloc_page_rx; }; /* Routing stuff */ @@ -345,9 +341,6 @@ qeth_is_ipa_enabled(struct qeth_ipa_info *ipa, enum qeth_ipa_funcs func) #define QETH_IP_HEADER_SIZE 40 -/* large receive scatter gather copy break */ -#define QETH_RX_SG_CB (PAGE_SIZE >> 1) - struct qeth_hdr_layer3 { __u8 id; __u8 flags; @@ -778,7 +771,6 @@ struct qeth_card_options { int layer2; enum qeth_large_send_types large_send; int performance_stats; - int rx_sg_cb; }; /* @@ -836,7 +828,6 @@ struct qeth_card { int (*orig_hard_header)(struct sk_buff *,struct net_device *, unsigned short,void *,void *,unsigned); struct qeth_osn_info osn_info; - atomic_t force_alloc_skb; }; struct qeth_card_list_struct { diff --git a/trunk/drivers/s390/net/qeth_main.c b/trunk/drivers/s390/net/qeth_main.c index 57f69434fbf9..86b0c44165c1 100644 --- a/trunk/drivers/s390/net/qeth_main.c +++ b/trunk/drivers/s390/net/qeth_main.c @@ -1054,7 +1054,6 @@ qeth_set_intial_options(struct qeth_card *card) else card->options.layer2 = 0; card->options.performance_stats = 0; - card->options.rx_sg_cb = QETH_RX_SG_CB; } /** @@ -1935,7 +1934,6 @@ qeth_send_control_data(struct qeth_card *card, int len, atomic_inc(&reply->received); wake_up(&reply->wait_q); } - cpu_relax(); }; rc = reply->rc; qeth_put_reply(reply); @@ -2260,89 +2258,6 @@ qeth_get_skb(unsigned int length, struct qeth_hdr *hdr) return skb; } -static inline int -qeth_create_skb_frag(struct qdio_buffer_element *element, - struct sk_buff **pskb, - int offset, int *pfrag, int data_len) -{ - struct page *page = virt_to_page(element->addr); - if (*pfrag == 0) { - /* the upper protocol layers assume that there is data in the - * skb itself. Copy a small amount (64 bytes) to make them - * happy. */ - *pskb = dev_alloc_skb(64 + QETH_FAKE_LL_LEN_ETH); - if (!(*pskb)) - return -ENOMEM; - skb_reserve(*pskb, QETH_FAKE_LL_LEN_ETH); - if (data_len <= 64) { - memcpy(skb_put(*pskb, data_len), element->addr + offset, - data_len); - } else { - get_page(page); - memcpy(skb_put(*pskb, 64), element->addr + offset, 64); - skb_fill_page_desc(*pskb, *pfrag, page, offset + 64, - data_len - 64); - (*pskb)->data_len += data_len - 64; - (*pskb)->len += data_len - 64; - (*pskb)->truesize += data_len - 64; - } - } else { - get_page(page); - skb_fill_page_desc(*pskb, *pfrag, page, offset, data_len); - (*pskb)->data_len += data_len; - (*pskb)->len += data_len; - (*pskb)->truesize += data_len; - } - (*pfrag)++; - return 0; -} - -static inline struct qeth_buffer_pool_entry * -qeth_find_free_buffer_pool_entry(struct qeth_card *card) -{ - struct list_head *plh; - struct qeth_buffer_pool_entry *entry; - int i, free; - struct page *page; - - if (list_empty(&card->qdio.in_buf_pool.entry_list)) - return NULL; - - list_for_each(plh, &card->qdio.in_buf_pool.entry_list) { - entry = list_entry(plh, struct qeth_buffer_pool_entry, list); - free = 1; - for (i = 0; i < QETH_MAX_BUFFER_ELEMENTS(card); ++i) { - if (page_count(virt_to_page(entry->elements[i])) > 1) { - free = 0; - break; - } - } - if (free) { - list_del_init(&entry->list); - return entry; - } - } - - /* no free buffer in pool so take first one and swap pages */ - entry = list_entry(card->qdio.in_buf_pool.entry_list.next, - struct qeth_buffer_pool_entry, list); - for (i = 0; i < QETH_MAX_BUFFER_ELEMENTS(card); ++i) { - if (page_count(virt_to_page(entry->elements[i])) > 1) { - page = alloc_page(GFP_ATOMIC|GFP_DMA); - if (!page) { - return NULL; - } else { - free_page((unsigned long)entry->elements[i]); - entry->elements[i] = page_address(page); - if (card->options.performance_stats) - card->perf_stats.sg_alloc_page_rx++; - } - } - } - list_del_init(&entry->list); - return entry; -} - static struct sk_buff * qeth_get_next_skb(struct qeth_card *card, struct qdio_buffer *buffer, struct qdio_buffer_element **__element, int *__offset, @@ -2354,8 +2269,6 @@ qeth_get_next_skb(struct qeth_card *card, struct qdio_buffer *buffer, int skb_len; void *data_ptr; int data_len; - int use_rx_sg = 0; - int frag = 0; QETH_DBF_TEXT(trace,6,"nextskb"); /* qeth_hdr must not cross element boundaries */ @@ -2380,43 +2293,23 @@ qeth_get_next_skb(struct qeth_card *card, struct qdio_buffer *buffer, if (!skb_len) return NULL; - if ((skb_len >= card->options.rx_sg_cb) && - (!(card->info.type == QETH_CARD_TYPE_OSN)) && - (!atomic_read(&card->force_alloc_skb))) { - use_rx_sg = 1; - } else { - if (card->options.fake_ll) { - if (card->dev->type == ARPHRD_IEEE802_TR) { - if (!(skb = qeth_get_skb(skb_len + - QETH_FAKE_LL_LEN_TR, *hdr))) - goto no_mem; - skb_reserve(skb, QETH_FAKE_LL_LEN_TR); - } else { - if (!(skb = qeth_get_skb(skb_len + - QETH_FAKE_LL_LEN_ETH, *hdr))) - goto no_mem; - skb_reserve(skb, QETH_FAKE_LL_LEN_ETH); - } + if (card->options.fake_ll){ + if(card->dev->type == ARPHRD_IEEE802_TR){ + if (!(skb = qeth_get_skb(skb_len+QETH_FAKE_LL_LEN_TR, *hdr))) + goto no_mem; + skb_reserve(skb,QETH_FAKE_LL_LEN_TR); } else { - skb = qeth_get_skb(skb_len, *hdr); - if (!skb) + if (!(skb = qeth_get_skb(skb_len+QETH_FAKE_LL_LEN_ETH, *hdr))) goto no_mem; + skb_reserve(skb,QETH_FAKE_LL_LEN_ETH); } - } - + } else if (!(skb = qeth_get_skb(skb_len, *hdr))) + goto no_mem; data_ptr = element->addr + offset; while (skb_len) { data_len = min(skb_len, (int)(element->length - offset)); - if (data_len) { - if (use_rx_sg) { - if (qeth_create_skb_frag(element, &skb, offset, - &frag, data_len)) - goto no_mem; - } else { - memcpy(skb_put(skb, data_len), data_ptr, - data_len); - } - } + if (data_len) + memcpy(skb_put(skb, data_len), data_ptr, data_len); skb_len -= data_len; if (skb_len){ if (qeth_is_last_sbale(element)){ @@ -2438,10 +2331,6 @@ qeth_get_next_skb(struct qeth_card *card, struct qdio_buffer *buffer, } *__element = element; *__offset = offset; - if (use_rx_sg && card->options.performance_stats) { - card->perf_stats.sg_skbs_rx++; - card->perf_stats.sg_frags_rx += skb_shinfo(skb)->nr_frags; - } return skb; no_mem: if (net_ratelimit()){ @@ -2719,15 +2608,28 @@ qeth_process_inbound_buffer(struct qeth_card *card, } } -static int +static struct qeth_buffer_pool_entry * +qeth_get_buffer_pool_entry(struct qeth_card *card) +{ + struct qeth_buffer_pool_entry *entry; + + QETH_DBF_TEXT(trace, 6, "gtbfplen"); + if (!list_empty(&card->qdio.in_buf_pool.entry_list)) { + entry = list_entry(card->qdio.in_buf_pool.entry_list.next, + struct qeth_buffer_pool_entry, list); + list_del_init(&entry->list); + return entry; + } + return NULL; +} + +static void qeth_init_input_buffer(struct qeth_card *card, struct qeth_qdio_buffer *buf) { struct qeth_buffer_pool_entry *pool_entry; int i; - - pool_entry = qeth_find_free_buffer_pool_entry(card); - if (!pool_entry) - return 1; + + pool_entry = qeth_get_buffer_pool_entry(card); /* * since the buffer is accessed only from the input_tasklet * there shouldn't be a need to synchronize; also, since we use @@ -2746,7 +2648,6 @@ qeth_init_input_buffer(struct qeth_card *card, struct qeth_qdio_buffer *buf) buf->buffer->element[i].flags = 0; } buf->state = QETH_QDIO_BUF_EMPTY; - return 0; } static void @@ -2781,7 +2682,6 @@ qeth_queue_input_buffer(struct qeth_card *card, int index) int count; int i; int rc; - int newcount = 0; QETH_DBF_TEXT(trace,6,"queinbuf"); count = (index < queue->next_buf_to_init)? @@ -2792,27 +2692,9 @@ qeth_queue_input_buffer(struct qeth_card *card, int index) /* only requeue at a certain threshold to avoid SIGAs */ if (count >= QETH_IN_BUF_REQUEUE_THRESHOLD(card)){ for (i = queue->next_buf_to_init; - i < queue->next_buf_to_init + count; ++i) { - if (qeth_init_input_buffer(card, - &queue->bufs[i % QDIO_MAX_BUFFERS_PER_Q])) { - break; - } else { - newcount++; - } - } - - if (newcount < count) { - /* we are in memory shortage so we switch back to - traditional skb allocation and drop packages */ - if (atomic_cmpxchg(&card->force_alloc_skb, 0, 1)) - printk(KERN_WARNING - "qeth: switch to alloc skb\n"); - count = newcount; - } else { - if (atomic_cmpxchg(&card->force_alloc_skb, 1, 0)) - printk(KERN_WARNING "qeth: switch to sg\n"); - } - + i < queue->next_buf_to_init + count; ++i) + qeth_init_input_buffer(card, + &queue->bufs[i % QDIO_MAX_BUFFERS_PER_Q]); /* * according to old code it should be avoided to requeue all * 128 buffers in order to benefit from PCI avoidance. @@ -6612,7 +6494,6 @@ qeth_hardsetup_card(struct qeth_card *card) QETH_DBF_TEXT(setup, 2, "hrdsetup"); - atomic_set(&card->force_alloc_skb, 0); retry: if (retries < 3){ PRINT_WARN("Retrying to do IDX activates.\n"); diff --git a/trunk/drivers/s390/net/qeth_proc.c b/trunk/drivers/s390/net/qeth_proc.c index f1ff165a5e05..89d56c8ecdd2 100644 --- a/trunk/drivers/s390/net/qeth_proc.c +++ b/trunk/drivers/s390/net/qeth_proc.c @@ -212,12 +212,6 @@ qeth_perf_procfile_seq_show(struct seq_file *s, void *it) " Skb fragments sent in SG mode : %u\n\n", card->perf_stats.sg_skbs_sent, card->perf_stats.sg_frags_sent); - seq_printf(s, " Skbs received in SG mode : %u\n" - " Skb fragments received in SG mode : %u\n" - " Page allocations for rx SG mode : %u\n\n", - card->perf_stats.sg_skbs_rx, - card->perf_stats.sg_frags_rx, - card->perf_stats.sg_alloc_page_rx); seq_printf(s, " large_send tx (in Kbytes) : %u\n" " large_send count : %u\n\n", card->perf_stats.large_send_bytes >> 10, diff --git a/trunk/drivers/serial/cpm_uart/cpm_uart_core.c b/trunk/drivers/serial/cpm_uart/cpm_uart_core.c index cefde58dbad2..b63ff8dd7304 100644 --- a/trunk/drivers/serial/cpm_uart/cpm_uart_core.c +++ b/trunk/drivers/serial/cpm_uart/cpm_uart_core.c @@ -678,7 +678,7 @@ static int cpm_uart_tx_pump(struct uart_port *port) } bdp->cbd_datlen = count; bdp->cbd_sc |= BD_SC_READY; - eieio(); + __asm__("eieio"); /* Get next BD. */ if (bdp->cbd_sc & BD_SC_WRAP) bdp = pinfo->tx_bd_base; diff --git a/trunk/drivers/serial/of_serial.c b/trunk/drivers/serial/of_serial.c index a64d85821996..7ffdaeaf0545 100644 --- a/trunk/drivers/serial/of_serial.c +++ b/trunk/drivers/serial/of_serial.c @@ -17,11 +17,6 @@ #include #include -struct of_serial_info { - int type; - int line; -}; - /* * Fill a struct uart_port for a given device node */ @@ -67,7 +62,6 @@ static int __devinit of_platform_serial_setup(struct of_device *ofdev, static int __devinit of_platform_serial_probe(struct of_device *ofdev, const struct of_device_id *id) { - struct of_serial_info *info; struct uart_port port; int port_type; int ret; @@ -75,35 +69,30 @@ static int __devinit of_platform_serial_probe(struct of_device *ofdev, if (of_find_property(ofdev->node, "used-by-rtas", NULL)) return -EBUSY; - info = kmalloc(sizeof(*info), GFP_KERNEL); - if (info == NULL) - return -ENOMEM; - port_type = (unsigned long)id->data; ret = of_platform_serial_setup(ofdev, port_type, &port); if (ret) goto out; switch (port_type) { + case PORT_UNKNOWN: + dev_info(&ofdev->dev, "Unknown serial port found, " + "attempting to use 8250 driver\n"); + /* fallthrough */ case PORT_8250 ... PORT_MAX_8250: ret = serial8250_register_port(&port); break; default: /* need to add code for these */ - case PORT_UNKNOWN: - dev_info(&ofdev->dev, "Unknown serial port found, ignored\n"); ret = -ENODEV; break; } if (ret < 0) goto out; - info->type = port_type; - info->line = ret; - ofdev->dev.driver_data = info; + ofdev->dev.driver_data = (void *)(unsigned long)ret; return 0; out: - kfree(info); irq_dispose_mapping(port.irq); return ret; } @@ -113,16 +102,8 @@ static int __devinit of_platform_serial_probe(struct of_device *ofdev, */ static int of_platform_serial_remove(struct of_device *ofdev) { - struct of_serial_info *info = ofdev->dev.driver_data; - switch (info->type) { - case PORT_8250 ... PORT_MAX_8250: - serial8250_unregister_port(info->line); - break; - default: - /* need to add code for these */ - break; - } - kfree(info); + int line = (unsigned long)ofdev->dev.driver_data; + serial8250_unregister_port(line); return 0; } diff --git a/trunk/drivers/video/Kconfig b/trunk/drivers/video/Kconfig index 9b7a76be36a0..403dac787ebf 100644 --- a/trunk/drivers/video/Kconfig +++ b/trunk/drivers/video/Kconfig @@ -1790,8 +1790,8 @@ config FB_IBM_GXT4500 adaptor, found on some IBM System P (pSeries) machines. config FB_PS3 - tristate "PS3 GPU framebuffer driver" - depends on FB && PS3_PS3AV + bool "PS3 GPU framebuffer driver" + depends on (FB = y) && PS3_PS3AV select FB_SYS_FILLRECT select FB_SYS_COPYAREA select FB_SYS_IMAGEBLIT diff --git a/trunk/drivers/video/ps3fb.c b/trunk/drivers/video/ps3fb.c index 08b7ffbbbbd8..9cf92ba5d6e3 100644 --- a/trunk/drivers/video/ps3fb.c +++ b/trunk/drivers/video/ps3fb.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -45,9 +46,6 @@ #include #include - -#define DEVICE_NAME "ps3fb" - #ifdef PS3FB_DEBUG #define DPRINTK(fmt, args...) printk("%s: " fmt, __func__ , ##args) #else @@ -128,6 +126,7 @@ struct gpu_driver_info { struct ps3fb_priv { unsigned int irq_no; + void *dev; u64 context_handle, memory_handle; void *xdr_ea; @@ -172,7 +171,7 @@ static const struct ps3fb_res_table ps3fb_res[] = { { 0, 0, 0, 0 , 0} }; /* default resolution */ -#define GPU_RES_INDEX 0 /* 720 x 480 */ +#define GPU_RES_INDEX 0 /* 720 x 480 */ static const struct fb_videomode ps3fb_modedb[] = { /* 60 Hz broadcast modes (modes "1" to "5") */ @@ -299,9 +298,10 @@ static const struct fb_videomode ps3fb_modedb[] = { #define FB_OFF(i) (GPU_OFFSET - VP_OFF(i) % GPU_OFFSET) static int ps3fb_mode; -module_param(ps3fb_mode, int, 0); +module_param(ps3fb_mode, bool, 0); + +static char *mode_option __initdata; -static char *mode_option __devinitdata; static int ps3fb_get_res_table(u32 xres, u32 yres) { @@ -681,15 +681,15 @@ int ps3fb_wait_for_vsync(u32 crtc) EXPORT_SYMBOL_GPL(ps3fb_wait_for_vsync); -void ps3fb_flip_ctl(int on, void *data) +void ps3fb_flip_ctl(int on) { - struct ps3fb_priv *priv = data; if (on) - atomic_dec_if_positive(&priv->ext_flip); + atomic_dec_if_positive(&ps3fb.ext_flip); else - atomic_inc(&priv->ext_flip); + atomic_inc(&ps3fb.ext_flip); } +EXPORT_SYMBOL_GPL(ps3fb_flip_ctl); /* * ioctl @@ -851,9 +851,37 @@ static irqreturn_t ps3fb_vsync_interrupt(int irq, void *ptr) return IRQ_HANDLED; } +#ifndef MODULE +static int __init ps3fb_setup(char *options) +{ + char *this_opt; + int mode = 0; + + if (!options || !*options) + return 0; /* no options */ + + while ((this_opt = strsep(&options, ",")) != NULL) { + if (!*this_opt) + continue; + if (!strncmp(this_opt, "mode:", 5)) + mode = simple_strtoul(this_opt + 5, NULL, 0); + else + mode_option = this_opt; + } + return mode; +} +#endif /* MODULE */ + + /* + * Initialisation + */ -static int ps3fb_vsync_settings(struct gpu_driver_info *dinfo, - struct ps3_system_bus_device *dev) +static void ps3fb_platform_release(struct device *device) +{ + /* This is called when the reference count goes to zero. */ +} + +static int ps3fb_vsync_settings(struct gpu_driver_info *dinfo, void *dev) { int error; @@ -869,6 +897,7 @@ static int ps3fb_vsync_settings(struct gpu_driver_info *dinfo, return -EINVAL; } + ps3fb.dev = dev; error = ps3_irq_plug_setup(PS3_BINDING_CPU_ANY, dinfo->irq.irq_outlet, &ps3fb.irq_no); if (error) { @@ -878,7 +907,7 @@ static int ps3fb_vsync_settings(struct gpu_driver_info *dinfo, } error = request_irq(ps3fb.irq_no, ps3fb_vsync_interrupt, IRQF_DISABLED, - DEVICE_NAME, dev); + "ps3fb vsync", ps3fb.dev); if (error) { printk(KERN_ERR "%s: request_irq failed %d\n", __func__, error); @@ -937,45 +966,16 @@ static struct fb_ops ps3fb_ops = { }; static struct fb_fix_screeninfo ps3fb_fix __initdata = { - .id = DEVICE_NAME, + .id = "PS3 FB", .type = FB_TYPE_PACKED_PIXELS, .visual = FB_VISUAL_TRUECOLOR, .accel = FB_ACCEL_NONE, }; -static int ps3fb_set_sync(void) -{ - int status; - -#ifdef HEAD_A - status = lv1_gpu_context_attribute(0x0, - L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_SYNC, - 0, L1GPU_DISPLAY_SYNC_VSYNC, 0, 0); - if (status) { - printk(KERN_ERR "%s: lv1_gpu_context_attribute DISPLAY_SYNC " - "failed: %d\n", __func__, status); - return -1; - } -#endif -#ifdef HEAD_B - status = lv1_gpu_context_attribute(0x0, - L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_SYNC, - 1, L1GPU_DISPLAY_SYNC_VSYNC, 0, 0); - - if (status) { - printk(KERN_ERR "%s: lv1_gpu_context_attribute DISPLAY_MODE " - "failed: %d\n", __func__, status); - return -1; - } -#endif - return 0; -} - -static int __devinit ps3fb_probe(struct ps3_system_bus_device *dev) +static int __init ps3fb_probe(struct platform_device *dev) { struct fb_info *info; int retval = -ENOMEM; - u32 xres, yres; u64 ddr_lpar = 0; u64 lpar_dma_control = 0; u64 lpar_driver_info = 0; @@ -986,30 +986,6 @@ static int __devinit ps3fb_probe(struct ps3_system_bus_device *dev) unsigned long offset; struct task_struct *task; - status = ps3_open_hv_device(dev); - if (status) { - printk(KERN_ERR "%s: ps3_open_hv_device failed\n", __func__); - goto err; - } - - if (!ps3fb_mode) - ps3fb_mode = ps3av_get_mode(); - DPRINTK("ps3av_mode:%d\n", ps3fb_mode); - - if (ps3fb_mode > 0 && - !ps3av_video_mode2res(ps3fb_mode, &xres, &yres)) { - ps3fb.res_index = ps3fb_get_res_table(xres, yres); - DPRINTK("res_index:%d\n", ps3fb.res_index); - } else - ps3fb.res_index = GPU_RES_INDEX; - - atomic_set(&ps3fb.f_count, -1); /* fbcon opens ps3fb */ - atomic_set(&ps3fb.ext_flip, 0); /* for flip with vsync */ - init_waitqueue_head(&ps3fb.wait_vsync); - ps3fb.num_frames = 1; - - ps3fb_set_sync(); - /* get gpu context handle */ status = lv1_gpu_memory_allocate(DDR_SIZE, 0, 0, 0, 0, &ps3fb.memory_handle, &ddr_lpar); @@ -1053,7 +1029,7 @@ static int __devinit ps3fb_probe(struct ps3_system_bus_device *dev) * leakage into userspace */ memset(ps3fb.xdr_ea, 0, ps3fb_videomemory.size); - info = framebuffer_alloc(sizeof(u32) * 16, &dev->core); + info = framebuffer_alloc(sizeof(u32) * 16, &dev->dev); if (!info) goto err_free_irq; @@ -1085,20 +1061,19 @@ static int __devinit ps3fb_probe(struct ps3_system_bus_device *dev) if (retval < 0) goto err_fb_dealloc; - dev->core.driver_data = info; + platform_set_drvdata(dev, info); printk(KERN_INFO "fb%d: PS3 frame buffer device, using %ld KiB of video memory\n", info->node, ps3fb_videomemory.size >> 10); - task = kthread_run(ps3fbd, info, DEVICE_NAME); + task = kthread_run(ps3fbd, info, "ps3fbd"); if (IS_ERR(task)) { retval = PTR_ERR(task); goto err_unregister_framebuffer; } ps3fb.task = task; - ps3av_register_flip_ctl(ps3fb_flip_ctl, &ps3fb); return 0; @@ -1109,7 +1084,7 @@ static int __devinit ps3fb_probe(struct ps3_system_bus_device *dev) err_framebuffer_release: framebuffer_release(info); err_free_irq: - free_irq(ps3fb.irq_no, dev); + free_irq(ps3fb.irq_no, ps3fb.dev); ps3_irq_plug_destroy(ps3fb.irq_no); err_iounmap_dinfo: iounmap((u8 __iomem *)ps3fb.dinfo); @@ -1121,30 +1096,26 @@ static int __devinit ps3fb_probe(struct ps3_system_bus_device *dev) return retval; } -static int ps3fb_shutdown(struct ps3_system_bus_device *dev) +static void ps3fb_shutdown(struct platform_device *dev) { - int status; - struct fb_info *info = dev->core.driver_data; - - DPRINTK(" -> %s:%d\n", __func__, __LINE__); - - ps3fb_flip_ctl(0, &ps3fb); /* flip off */ + ps3fb_flip_ctl(0); /* flip off */ ps3fb.dinfo->irq.mask = 0; + free_irq(ps3fb.irq_no, ps3fb.dev); + ps3_irq_plug_destroy(ps3fb.irq_no); + iounmap((u8 __iomem *)ps3fb.dinfo); +} - if (info) { - unregister_framebuffer(info); - fb_dealloc_cmap(&info->cmap); - framebuffer_release(info); - } +void ps3fb_cleanup(void) +{ + int status; - ps3av_register_flip_ctl(NULL, NULL); if (ps3fb.task) { struct task_struct *task = ps3fb.task; ps3fb.task = NULL; kthread_stop(task); } if (ps3fb.irq_no) { - free_irq(ps3fb.irq_no, dev); + free_irq(ps3fb.irq_no, ps3fb.dev); ps3_irq_plug_destroy(ps3fb.irq_no); } iounmap((u8 __iomem *)ps3fb.dinfo); @@ -1157,69 +1128,134 @@ static int ps3fb_shutdown(struct ps3_system_bus_device *dev) if (status) DPRINTK("lv1_gpu_memory_free failed: %d\n", status); - ps3_close_hv_device(dev); - DPRINTK(" <- %s:%d\n", __func__, __LINE__); - - return 0; + ps3av_dev_close(); } -static struct ps3_system_bus_driver ps3fb_driver = { - .match_id = PS3_MATCH_ID_GRAPHICS, - .core.name = DEVICE_NAME, - .core.owner = THIS_MODULE, - .probe = ps3fb_probe, - .remove = ps3fb_shutdown, - .shutdown = ps3fb_shutdown, -}; +EXPORT_SYMBOL_GPL(ps3fb_cleanup); -static int __init ps3fb_setup(void) +static int ps3fb_remove(struct platform_device *dev) { - char *options; + struct fb_info *info = platform_get_drvdata(dev); -#ifdef MODULE + if (info) { + unregister_framebuffer(info); + fb_dealloc_cmap(&info->cmap); + framebuffer_release(info); + } + ps3fb_cleanup(); return 0; -#endif +} - if (fb_get_options(DEVICE_NAME, &options)) - return -ENXIO; +static struct platform_driver ps3fb_driver = { + .probe = ps3fb_probe, + .remove = ps3fb_remove, + .shutdown = ps3fb_shutdown, + .driver = { .name = "ps3fb" } +}; - if (!options || !*options) - return 0; +static struct platform_device ps3fb_device = { + .name = "ps3fb", + .id = 0, + .dev = { .release = ps3fb_platform_release } +}; - while (1) { - char *this_opt = strsep(&options, ","); +int ps3fb_set_sync(void) +{ + int status; - if (!this_opt) - break; - if (!*this_opt) - continue; - if (!strncmp(this_opt, "mode:", 5)) - ps3fb_mode = simple_strtoul(this_opt + 5, NULL, 0); - else - mode_option = this_opt; +#ifdef HEAD_A + status = lv1_gpu_context_attribute(0x0, + L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_SYNC, + 0, L1GPU_DISPLAY_SYNC_VSYNC, 0, 0); + if (status) { + printk(KERN_ERR + "%s: lv1_gpu_context_attribute DISPLAY_SYNC failed: %d\n", + __func__, status); + return -1; } +#endif +#ifdef HEAD_B + status = lv1_gpu_context_attribute(0x0, + L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_SYNC, + 1, L1GPU_DISPLAY_SYNC_VSYNC, 0, 0); + + if (status) { + printk(KERN_ERR + "%s: lv1_gpu_context_attribute DISPLAY_MODE failed: %d\n", + __func__, status); + return -1; + } +#endif return 0; } +EXPORT_SYMBOL_GPL(ps3fb_set_sync); + static int __init ps3fb_init(void) { - if (!ps3fb_videomemory.address || ps3fb_setup()) - return -ENXIO; + int error; +#ifndef MODULE + int mode; + char *option = NULL; + + if (fb_get_options("ps3fb", &option)) + goto err; +#endif + + if (!ps3fb_videomemory.address) + goto err; + + error = ps3av_dev_open(); + if (error) { + printk(KERN_ERR "%s: ps3av_dev_open failed\n", __func__); + goto err; + } + + ps3fb_mode = ps3av_get_mode(); + DPRINTK("ps3av_mode:%d\n", ps3fb_mode); +#ifndef MODULE + mode = ps3fb_setup(option); /* check boot option */ + if (mode) + ps3fb_mode = mode; +#endif + if (ps3fb_mode > 0) { + u32 xres, yres; + ps3av_video_mode2res(ps3fb_mode, &xres, &yres); + ps3fb.res_index = ps3fb_get_res_table(xres, yres); + DPRINTK("res_index:%d\n", ps3fb.res_index); + } else + ps3fb.res_index = GPU_RES_INDEX; + + atomic_set(&ps3fb.f_count, -1); /* fbcon opens ps3fb */ + atomic_set(&ps3fb.ext_flip, 0); /* for flip with vsync */ + init_waitqueue_head(&ps3fb.wait_vsync); + ps3fb.num_frames = 1; - return ps3_system_bus_driver_register(&ps3fb_driver); + error = platform_driver_register(&ps3fb_driver); + if (!error) { + error = platform_device_register(&ps3fb_device); + if (error) + platform_driver_unregister(&ps3fb_driver); + } + + ps3fb_set_sync(); + + return error; + +err: + return -ENXIO; } +module_init(ps3fb_init); + +#ifdef MODULE static void __exit ps3fb_exit(void) { - DPRINTK(" -> %s:%d\n", __func__, __LINE__); - ps3_system_bus_driver_unregister(&ps3fb_driver); - DPRINTK(" <- %s:%d\n", __func__, __LINE__); + platform_device_unregister(&ps3fb_device); + platform_driver_unregister(&ps3fb_driver); } -module_init(ps3fb_init); module_exit(ps3fb_exit); MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("PS3 GPU Frame Buffer Driver"); -MODULE_AUTHOR("Sony Computer Entertainment Inc."); -MODULE_ALIAS(PS3_MODULE_ALIAS_GRAPHICS); +#endif /* MODULE */ diff --git a/trunk/include/asm-arm/arch-at91/board.h b/trunk/include/asm-arm/arch-at91/board.h index d96b10fd449f..0ce6ee98ed0b 100644 --- a/trunk/include/asm-arm/arch-at91/board.h +++ b/trunk/include/asm-arm/arch-at91/board.h @@ -64,7 +64,6 @@ extern void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data) /* Ethernet (EMAC & MACB) */ struct at91_eth_data { - u32 phy_mask; u8 phy_irq_pin; /* PHY IRQ */ u8 is_rmii; /* using RMII interface? */ }; diff --git a/trunk/include/asm-avr32/arch-at32ap/board.h b/trunk/include/asm-avr32/arch-at32ap/board.h index 974480438849..9fd2e32f84b8 100644 --- a/trunk/include/asm-avr32/arch-at32ap/board.h +++ b/trunk/include/asm-avr32/arch-at32ap/board.h @@ -21,7 +21,6 @@ void at32_map_usart(unsigned int hw_id, unsigned int line); struct platform_device *at32_add_device_usart(unsigned int id); struct eth_platform_data { - u32 phy_mask; u8 is_rmii; }; struct platform_device * diff --git a/trunk/include/asm-powerpc/cache.h b/trunk/include/asm-powerpc/cache.h index 53507046a1b1..642be62cf393 100644 --- a/trunk/include/asm-powerpc/cache.h +++ b/trunk/include/asm-powerpc/cache.h @@ -34,9 +34,5 @@ struct ppc64_caches { extern struct ppc64_caches ppc64_caches; #endif /* __powerpc64__ && ! __ASSEMBLY__ */ -#if !defined(__ASSEMBLY__) -#define __read_mostly __attribute__((__section__(".data.read_mostly"))) -#endif - #endif /* __KERNEL__ */ #endif /* _ASM_POWERPC_CACHE_H */ diff --git a/trunk/include/asm-powerpc/cputable.h b/trunk/include/asm-powerpc/cputable.h index 3dc8e2dfca84..82d595a52109 100644 --- a/trunk/include/asm-powerpc/cputable.h +++ b/trunk/include/asm-powerpc/cputable.h @@ -111,7 +111,7 @@ extern void do_feature_fixups(unsigned long value, void *fixup_start, /* CPU kernel features */ /* Retain the 32b definitions all use bottom half of word */ -#define CPU_FTR_COHERENT_ICACHE ASM_CONST(0x0000000000000001) +#define CPU_FTR_SPLIT_ID_CACHE ASM_CONST(0x0000000000000001) #define CPU_FTR_L2CR ASM_CONST(0x0000000000000002) #define CPU_FTR_SPEC7450 ASM_CONST(0x0000000000000004) #define CPU_FTR_ALTIVEC ASM_CONST(0x0000000000000008) @@ -135,7 +135,6 @@ extern void do_feature_fixups(unsigned long value, void *fixup_start, #define CPU_FTR_PPC_LE ASM_CONST(0x0000000000200000) #define CPU_FTR_REAL_LE ASM_CONST(0x0000000000400000) #define CPU_FTR_FPU_UNAVAILABLE ASM_CONST(0x0000000000800000) -#define CPU_FTR_UNIFIED_ID_CACHE ASM_CONST(0x0000000001000000) /* * Add the 64-bit processor unique features in the top half of the word; @@ -155,6 +154,7 @@ extern void do_feature_fixups(unsigned long value, void *fixup_start, #define CPU_FTR_MMCRA LONG_ASM_CONST(0x0000004000000000) #define CPU_FTR_CTRL LONG_ASM_CONST(0x0000008000000000) #define CPU_FTR_SMT LONG_ASM_CONST(0x0000010000000000) +#define CPU_FTR_COHERENT_ICACHE LONG_ASM_CONST(0x0000020000000000) #define CPU_FTR_LOCKLESS_TLBIE LONG_ASM_CONST(0x0000040000000000) #define CPU_FTR_CI_LARGE_PAGE LONG_ASM_CONST(0x0000100000000000) #define CPU_FTR_PAUSE_ZERO LONG_ASM_CONST(0x0000200000000000) @@ -206,149 +206,164 @@ extern void do_feature_fixups(unsigned long value, void *fixup_start, !defined(CONFIG_POWER3) && !defined(CONFIG_POWER4) && \ !defined(CONFIG_BOOKE)) -#define CPU_FTRS_PPC601 (CPU_FTR_COMMON | CPU_FTR_601 | CPU_FTR_HPTE_TABLE | \ - CPU_FTR_COHERENT_ICACHE | CPU_FTR_UNIFIED_ID_CACHE) -#define CPU_FTRS_603 (CPU_FTR_COMMON | \ +#define CPU_FTRS_PPC601 (CPU_FTR_COMMON | CPU_FTR_601 | CPU_FTR_HPTE_TABLE) +#define CPU_FTRS_603 (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \ CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | \ CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_PPC_LE) -#define CPU_FTRS_604 (CPU_FTR_COMMON | \ +#define CPU_FTRS_604 (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \ CPU_FTR_USE_TB | CPU_FTR_604_PERF_MON | CPU_FTR_HPTE_TABLE | \ CPU_FTR_PPC_LE) -#define CPU_FTRS_740_NOTAU (CPU_FTR_COMMON | \ +#define CPU_FTRS_740_NOTAU (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \ CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | \ CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_PPC_LE) -#define CPU_FTRS_740 (CPU_FTR_COMMON | \ +#define CPU_FTRS_740 (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \ CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | \ CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP | \ CPU_FTR_PPC_LE) -#define CPU_FTRS_750 (CPU_FTR_COMMON | \ +#define CPU_FTRS_750 (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \ CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | \ CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP | \ CPU_FTR_PPC_LE) -#define CPU_FTRS_750CL (CPU_FTRS_750 | CPU_FTR_HAS_HIGH_BATS) -#define CPU_FTRS_750FX1 (CPU_FTRS_750 | CPU_FTR_DUAL_PLL_750FX | CPU_FTR_NO_DPM) -#define CPU_FTRS_750FX2 (CPU_FTRS_750 | CPU_FTR_NO_DPM) -#define CPU_FTRS_750FX (CPU_FTRS_750 | CPU_FTR_DUAL_PLL_750FX | \ - CPU_FTR_HAS_HIGH_BATS) -#define CPU_FTRS_750GX (CPU_FTRS_750FX) -#define CPU_FTRS_7400_NOTAU (CPU_FTR_COMMON | \ +#define CPU_FTRS_750CL (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \ + CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | \ + CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP | \ + CPU_FTR_HAS_HIGH_BATS | CPU_FTR_PPC_LE) +#define CPU_FTRS_750FX1 (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \ + CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | \ + CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP | \ + CPU_FTR_DUAL_PLL_750FX | CPU_FTR_NO_DPM | CPU_FTR_PPC_LE) +#define CPU_FTRS_750FX2 (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \ + CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | \ + CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP | \ + CPU_FTR_NO_DPM | CPU_FTR_PPC_LE) +#define CPU_FTRS_750FX (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \ + CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | \ + CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP | \ + CPU_FTR_DUAL_PLL_750FX | CPU_FTR_HAS_HIGH_BATS | CPU_FTR_PPC_LE) +#define CPU_FTRS_750GX (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \ + CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | \ + CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP | \ + CPU_FTR_DUAL_PLL_750FX | CPU_FTR_HAS_HIGH_BATS | CPU_FTR_PPC_LE) +#define CPU_FTRS_7400_NOTAU (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \ CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | \ CPU_FTR_ALTIVEC_COMP | CPU_FTR_HPTE_TABLE | \ CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_PPC_LE) -#define CPU_FTRS_7400 (CPU_FTR_COMMON | \ +#define CPU_FTRS_7400 (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \ CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | \ CPU_FTR_TAU | CPU_FTR_ALTIVEC_COMP | CPU_FTR_HPTE_TABLE | \ CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_PPC_LE) -#define CPU_FTRS_7450_20 (CPU_FTR_COMMON | \ +#define CPU_FTRS_7450_20 (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \ CPU_FTR_USE_TB | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | \ CPU_FTR_L3CR | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | \ CPU_FTR_NEED_COHERENT | CPU_FTR_PPC_LE) -#define CPU_FTRS_7450_21 (CPU_FTR_COMMON | \ +#define CPU_FTRS_7450_21 (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \ CPU_FTR_USE_TB | \ CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | \ CPU_FTR_L3CR | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | \ CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_L3_DISABLE_NAP | \ CPU_FTR_NEED_COHERENT | CPU_FTR_PPC_LE) -#define CPU_FTRS_7450_23 (CPU_FTR_COMMON | \ +#define CPU_FTRS_7450_23 (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \ CPU_FTR_USE_TB | \ CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | \ CPU_FTR_L3CR | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | \ CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_NEED_COHERENT | CPU_FTR_PPC_LE) -#define CPU_FTRS_7455_1 (CPU_FTR_COMMON | \ +#define CPU_FTRS_7455_1 (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \ CPU_FTR_USE_TB | \ CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | CPU_FTR_L3CR | \ CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | CPU_FTR_HAS_HIGH_BATS | \ CPU_FTR_NEED_COHERENT | CPU_FTR_PPC_LE) -#define CPU_FTRS_7455_20 (CPU_FTR_COMMON | \ +#define CPU_FTRS_7455_20 (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \ CPU_FTR_USE_TB | \ CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | \ CPU_FTR_L3CR | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | \ CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_L3_DISABLE_NAP | \ CPU_FTR_NEED_COHERENT | CPU_FTR_HAS_HIGH_BATS | CPU_FTR_PPC_LE) -#define CPU_FTRS_7455 (CPU_FTR_COMMON | \ +#define CPU_FTRS_7455 (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \ CPU_FTR_USE_TB | \ CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | \ CPU_FTR_L3CR | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | \ CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_HAS_HIGH_BATS | \ CPU_FTR_NEED_COHERENT | CPU_FTR_PPC_LE) -#define CPU_FTRS_7447_10 (CPU_FTR_COMMON | \ +#define CPU_FTRS_7447_10 (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \ CPU_FTR_USE_TB | \ CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | \ CPU_FTR_L3CR | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | \ CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_HAS_HIGH_BATS | \ CPU_FTR_NEED_COHERENT | CPU_FTR_NO_BTIC | CPU_FTR_PPC_LE) -#define CPU_FTRS_7447 (CPU_FTR_COMMON | \ +#define CPU_FTRS_7447 (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \ CPU_FTR_USE_TB | \ CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | \ CPU_FTR_L3CR | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | \ CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_HAS_HIGH_BATS | \ CPU_FTR_NEED_COHERENT | CPU_FTR_PPC_LE) -#define CPU_FTRS_7447A (CPU_FTR_COMMON | \ +#define CPU_FTRS_7447A (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \ CPU_FTR_USE_TB | \ CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | \ CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | \ CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_HAS_HIGH_BATS | \ CPU_FTR_NEED_COHERENT | CPU_FTR_PPC_LE) -#define CPU_FTRS_7448 (CPU_FTR_COMMON | \ +#define CPU_FTRS_7448 (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \ CPU_FTR_USE_TB | \ CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | \ CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | \ CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_HAS_HIGH_BATS | \ CPU_FTR_PPC_LE) -#define CPU_FTRS_82XX (CPU_FTR_COMMON | \ +#define CPU_FTRS_82XX (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \ CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB) -#define CPU_FTRS_G2_LE (CPU_FTR_MAYBE_CAN_DOZE | \ +#define CPU_FTRS_G2_LE (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE | \ CPU_FTR_USE_TB | CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_HAS_HIGH_BATS) -#define CPU_FTRS_E300 (CPU_FTR_MAYBE_CAN_DOZE | \ +#define CPU_FTRS_E300 (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE | \ CPU_FTR_USE_TB | CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_HAS_HIGH_BATS | \ CPU_FTR_COMMON) -#define CPU_FTRS_E300C2 (CPU_FTR_MAYBE_CAN_DOZE | \ +#define CPU_FTRS_E300C2 (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE | \ CPU_FTR_USE_TB | CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_HAS_HIGH_BATS | \ CPU_FTR_COMMON | CPU_FTR_FPU_UNAVAILABLE) -#define CPU_FTRS_CLASSIC32 (CPU_FTR_COMMON | \ +#define CPU_FTRS_CLASSIC32 (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \ CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE) -#define CPU_FTRS_8XX (CPU_FTR_USE_TB) -#define CPU_FTRS_40X (CPU_FTR_USE_TB | CPU_FTR_NODSISRALIGN) -#define CPU_FTRS_44X (CPU_FTR_USE_TB | CPU_FTR_NODSISRALIGN) -#define CPU_FTRS_E200 (CPU_FTR_USE_TB | CPU_FTR_NODSISRALIGN | \ - CPU_FTR_COHERENT_ICACHE | CPU_FTR_UNIFIED_ID_CACHE) -#define CPU_FTRS_E500 (CPU_FTR_USE_TB | CPU_FTR_NODSISRALIGN) -#define CPU_FTRS_E500_2 (CPU_FTR_USE_TB | \ +#define CPU_FTRS_8XX (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB) +#define CPU_FTRS_40X (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \ + CPU_FTR_NODSISRALIGN) +#define CPU_FTRS_44X (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \ + CPU_FTR_NODSISRALIGN) +#define CPU_FTRS_E200 (CPU_FTR_USE_TB | CPU_FTR_NODSISRALIGN) +#define CPU_FTRS_E500 (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \ + CPU_FTR_NODSISRALIGN) +#define CPU_FTRS_E500_2 (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \ CPU_FTR_BIG_PHYS | CPU_FTR_NODSISRALIGN) #define CPU_FTRS_GENERIC_32 (CPU_FTR_COMMON | CPU_FTR_NODSISRALIGN) /* 64-bit CPUs */ -#define CPU_FTRS_POWER3 (CPU_FTR_USE_TB | \ +#define CPU_FTRS_POWER3 (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \ CPU_FTR_HPTE_TABLE | CPU_FTR_IABR | CPU_FTR_PPC_LE) -#define CPU_FTRS_RS64 (CPU_FTR_USE_TB | \ +#define CPU_FTRS_RS64 (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \ CPU_FTR_HPTE_TABLE | CPU_FTR_IABR | \ CPU_FTR_MMCRA | CPU_FTR_CTRL) -#define CPU_FTRS_POWER4 (CPU_FTR_USE_TB | \ +#define CPU_FTRS_POWER4 (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \ CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \ CPU_FTR_MMCRA) -#define CPU_FTRS_PPC970 (CPU_FTR_USE_TB | \ +#define CPU_FTRS_PPC970 (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \ CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \ CPU_FTR_ALTIVEC_COMP | CPU_FTR_CAN_NAP | CPU_FTR_MMCRA) -#define CPU_FTRS_POWER5 (CPU_FTR_USE_TB | \ +#define CPU_FTRS_POWER5 (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \ CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \ CPU_FTR_MMCRA | CPU_FTR_SMT | \ CPU_FTR_COHERENT_ICACHE | CPU_FTR_LOCKLESS_TLBIE | \ CPU_FTR_PURR) -#define CPU_FTRS_POWER6 (CPU_FTR_USE_TB | \ +#define CPU_FTRS_POWER6 (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \ CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \ CPU_FTR_MMCRA | CPU_FTR_SMT | \ CPU_FTR_COHERENT_ICACHE | CPU_FTR_LOCKLESS_TLBIE | \ CPU_FTR_PURR | CPU_FTR_SPURR | CPU_FTR_REAL_LE | \ CPU_FTR_DSCR) -#define CPU_FTRS_CELL (CPU_FTR_USE_TB | \ +#define CPU_FTRS_CELL (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \ CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \ CPU_FTR_ALTIVEC_COMP | CPU_FTR_MMCRA | CPU_FTR_SMT | \ CPU_FTR_PAUSE_ZERO | CPU_FTR_CI_LARGE_PAGE | CPU_FTR_CELL_TB_BUG) -#define CPU_FTRS_PA6T (CPU_FTR_USE_TB | \ +#define CPU_FTRS_PA6T (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \ CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | \ CPU_FTR_ALTIVEC_COMP | CPU_FTR_CI_LARGE_PAGE | \ CPU_FTR_PURR | CPU_FTR_REAL_LE) -#define CPU_FTRS_COMPATIBLE (CPU_FTR_USE_TB | \ +#define CPU_FTRS_COMPATIBLE (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \ CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2) #ifdef __powerpc64__ diff --git a/trunk/include/asm-powerpc/floppy.h b/trunk/include/asm-powerpc/floppy.h index 34146f0eea63..afa700ded877 100644 --- a/trunk/include/asm-powerpc/floppy.h +++ b/trunk/include/asm-powerpc/floppy.h @@ -29,7 +29,7 @@ #define fd_free_irq() free_irq(FLOPPY_IRQ, NULL); #include -#include /* for isa_bridge_pcidev */ +#include /* for ppc64_isabridge_dev */ #define fd_dma_setup(addr,size,mode,io) fd_ops->_dma_setup(addr,size,mode,io) @@ -139,12 +139,12 @@ static int hard_dma_setup(char *addr, unsigned long size, int mode, int io) if (bus_addr && (addr != prev_addr || size != prev_size || dir != prev_dir)) { /* different from last time -- unmap prev */ - pci_unmap_single(isa_bridge_pcidev, bus_addr, prev_size, prev_dir); + pci_unmap_single(ppc64_isabridge_dev, bus_addr, prev_size, prev_dir); bus_addr = 0; } if (!bus_addr) /* need to map it */ - bus_addr = pci_map_single(isa_bridge_pcidev, addr, size, dir); + bus_addr = pci_map_single(ppc64_isabridge_dev, addr, size, dir); /* remember this one as prev */ prev_addr = addr; diff --git a/trunk/include/asm-powerpc/hvcall.h b/trunk/include/asm-powerpc/hvcall.h index bf6cd7cb996c..62efd9d7a43d 100644 --- a/trunk/include/asm-powerpc/hvcall.h +++ b/trunk/include/asm-powerpc/hvcall.h @@ -206,7 +206,6 @@ #define H_FREE_LOGICAL_LAN_BUFFER 0x1D4 #define H_QUERY_INT_STATE 0x1E4 #define H_POLL_PENDING 0x1D8 -#define H_ILLAN_ATTRIBUTES 0x244 #define H_JOIN 0x298 #define H_VASI_STATE 0x2A4 #define H_ENABLE_CRQ 0x2B0 diff --git a/trunk/include/asm-powerpc/io.h b/trunk/include/asm-powerpc/io.h index bb8d965f96c6..350c9bdb31dc 100644 --- a/trunk/include/asm-powerpc/io.h +++ b/trunk/include/asm-powerpc/io.h @@ -607,9 +607,9 @@ static inline void iosync(void) * * * iounmap undoes such a mapping and can be hooked * - * * __ioremap_at (and the pending __iounmap_at) are low level functions to - * create hand-made mappings for use only by the PCI code and cannot - * currently be hooked. Must be page aligned. + * * __ioremap_explicit (and the pending __iounmap_explicit) are low level + * functions to create hand-made mappings for use only by the PCI code + * and cannot currently be hooked. * * * __ioremap is the low level implementation used by ioremap and * ioremap_flags and cannot be hooked (but can be used by a hook on one @@ -629,9 +629,19 @@ extern void __iomem *__ioremap(phys_addr_t, unsigned long size, unsigned long flags); extern void __iounmap(volatile void __iomem *addr); -extern void __iomem * __ioremap_at(phys_addr_t pa, void *ea, - unsigned long size, unsigned long flags); -extern void __iounmap_at(void *ea, unsigned long size); +extern int __ioremap_explicit(phys_addr_t p_addr, unsigned long v_addr, + unsigned long size, unsigned long flags); +extern int __iounmap_explicit(volatile void __iomem *start, + unsigned long size); + +extern void __iomem * reserve_phb_iospace(unsigned long size); + +/* Those are more 32 bits only functions */ +extern unsigned long iopa(unsigned long addr); +extern unsigned long mm_ptov(unsigned long addr) __attribute_const__; +extern void io_block_mapping(unsigned long virt, phys_addr_t phys, + unsigned int size, int flags); + /* * When CONFIG_PPC_INDIRECT_IO is set, we use the generic iomap implementation @@ -641,8 +651,8 @@ extern void __iounmap_at(void *ea, unsigned long size); */ #define HAVE_ARCH_PIO_SIZE 1 #define PIO_OFFSET 0x00000000UL -#define PIO_MASK (FULL_IO_SIZE - 1) -#define PIO_RESERVED (FULL_IO_SIZE) +#define PIO_MASK 0x3fffffffUL +#define PIO_RESERVED 0x40000000UL #define mmio_read16be(addr) readw_be(addr) #define mmio_read32be(addr) readl_be(addr) diff --git a/trunk/include/asm-powerpc/irq.h b/trunk/include/asm-powerpc/irq.h index 0485c53db2b5..05dd5a3eb3aa 100644 --- a/trunk/include/asm-powerpc/irq.h +++ b/trunk/include/asm-powerpc/irq.h @@ -223,15 +223,6 @@ extern void irq_dispose_mapping(unsigned int virq); extern unsigned int irq_find_mapping(struct irq_host *host, irq_hw_number_t hwirq); -/** - * irq_create_direct_mapping - Allocate a virq for direct mapping - * @host: host to allocate the virq for or NULL for default host - * - * This routine is used for irq controllers which can choose the hardware - * interrupt numbers they generate. In such a case it's simplest to use - * the linux virq as the hardware interrupt number. - */ -extern unsigned int irq_create_direct_mapping(struct irq_host *host); /** * irq_radix_revmap - Find a linux virq from a hw irq number. diff --git a/trunk/include/asm-powerpc/lppaca.h b/trunk/include/asm-powerpc/lppaca.h index 567ed92cd91f..821ea0c512b4 100644 --- a/trunk/include/asm-powerpc/lppaca.h +++ b/trunk/include/asm-powerpc/lppaca.h @@ -98,7 +98,7 @@ struct lppaca { u64 saved_gpr5; // Saved GPR5 x30-x37 u8 reserved4; // Reserved x38-x38 - u8 donate_dedicated_cpu; // Donate dedicated CPU cycles x39-x39 + u8 cpuctls_task_attrs; // Task attributes for cpuctls x39-x39 u8 fpregs_in_use; // FP regs in use x3A-x3A u8 pmcregs_in_use; // PMC regs in use x3B-x3B volatile u32 saved_decr; // Saved Decr Value x3C-x3F diff --git a/trunk/include/asm-powerpc/lv1call.h b/trunk/include/asm-powerpc/lv1call.h index 81713acf7529..f733beeea63a 100644 --- a/trunk/include/asm-powerpc/lv1call.h +++ b/trunk/include/asm-powerpc/lv1call.h @@ -238,7 +238,6 @@ LV1_CALL(destruct_virtual_address_space, 1, 0, 10 ) LV1_CALL(configure_irq_state_bitmap, 3, 0, 11 ) LV1_CALL(connect_irq_plug_ext, 5, 0, 12 ) LV1_CALL(release_memory, 1, 0, 13 ) -LV1_CALL(put_iopte, 5, 0, 15 ) LV1_CALL(disconnect_irq_plug_ext, 3, 0, 17 ) LV1_CALL(construct_event_receive_port, 0, 1, 18 ) LV1_CALL(destruct_event_receive_port, 1, 0, 19 ) @@ -269,8 +268,6 @@ LV1_CALL(remove_repository_node, 4, 0, 93 ) LV1_CALL(read_htab_entries, 2, 5, 95 ) LV1_CALL(set_dabr, 2, 0, 96 ) LV1_CALL(get_total_execution_time, 2, 1, 103 ) -LV1_CALL(allocate_io_segment, 3, 1, 116 ) -LV1_CALL(release_io_segment, 2, 0, 117 ) LV1_CALL(construct_io_irq_outlet, 1, 1, 120 ) LV1_CALL(destruct_io_irq_outlet, 1, 0, 121 ) LV1_CALL(map_htab, 1, 1, 122 ) diff --git a/trunk/include/asm-powerpc/machdep.h b/trunk/include/asm-powerpc/machdep.h index 71c6e7eb2a26..6cf1a831f550 100644 --- a/trunk/include/asm-powerpc/machdep.h +++ b/trunk/include/asm-powerpc/machdep.h @@ -218,7 +218,7 @@ struct machdep_calls { int (*pcibios_enable_device_hook)(struct pci_dev *, int initial); /* Called in indirect_* to avoid touching devices */ - int (*pci_exclude_device)(struct pci_controller *, unsigned char, unsigned char); + int (*pci_exclude_device)(unsigned char, unsigned char); /* Called at then very end of pcibios_init() */ void (*pcibios_after_init)(void); diff --git a/trunk/include/asm-powerpc/mmu-8xx.h b/trunk/include/asm-powerpc/mmu-8xx.h deleted file mode 100644 index 952bd8899f2f..000000000000 --- a/trunk/include/asm-powerpc/mmu-8xx.h +++ /dev/null @@ -1,147 +0,0 @@ -#ifndef _ASM_POWERPC_MMU_8XX_H_ -#define _ASM_POWERPC_MMU_8XX_H_ -/* - * PPC8xx support - */ - -/* Control/status registers for the MPC8xx. - * A write operation to these registers causes serialized access. - * During software tablewalk, the registers used perform mask/shift-add - * operations when written/read. A TLB entry is created when the Mx_RPN - * is written, and the contents of several registers are used to - * create the entry. - */ -#define SPRN_MI_CTR 784 /* Instruction TLB control register */ -#define MI_GPM 0x80000000 /* Set domain manager mode */ -#define MI_PPM 0x40000000 /* Set subpage protection */ -#define MI_CIDEF 0x20000000 /* Set cache inhibit when MMU dis */ -#define MI_RSV4I 0x08000000 /* Reserve 4 TLB entries */ -#define MI_PPCS 0x02000000 /* Use MI_RPN prob/priv state */ -#define MI_IDXMASK 0x00001f00 /* TLB index to be loaded */ -#define MI_RESETVAL 0x00000000 /* Value of register at reset */ - -/* These are the Ks and Kp from the PowerPC books. For proper operation, - * Ks = 0, Kp = 1. - */ -#define SPRN_MI_AP 786 -#define MI_Ks 0x80000000 /* Should not be set */ -#define MI_Kp 0x40000000 /* Should always be set */ - -/* The effective page number register. When read, contains the information - * about the last instruction TLB miss. When MI_RPN is written, bits in - * this register are used to create the TLB entry. - */ -#define SPRN_MI_EPN 787 -#define MI_EPNMASK 0xfffff000 /* Effective page number for entry */ -#define MI_EVALID 0x00000200 /* Entry is valid */ -#define MI_ASIDMASK 0x0000000f /* ASID match value */ - /* Reset value is undefined */ - -/* A "level 1" or "segment" or whatever you want to call it register. - * For the instruction TLB, it contains bits that get loaded into the - * TLB entry when the MI_RPN is written. - */ -#define SPRN_MI_TWC 789 -#define MI_APG 0x000001e0 /* Access protection group (0) */ -#define MI_GUARDED 0x00000010 /* Guarded storage */ -#define MI_PSMASK 0x0000000c /* Mask of page size bits */ -#define MI_PS8MEG 0x0000000c /* 8M page size */ -#define MI_PS512K 0x00000004 /* 512K page size */ -#define MI_PS4K_16K 0x00000000 /* 4K or 16K page size */ -#define MI_SVALID 0x00000001 /* Segment entry is valid */ - /* Reset value is undefined */ - -/* Real page number. Defined by the pte. Writing this register - * causes a TLB entry to be created for the instruction TLB, using - * additional information from the MI_EPN, and MI_TWC registers. - */ -#define SPRN_MI_RPN 790 - -/* Define an RPN value for mapping kernel memory to large virtual - * pages for boot initialization. This has real page number of 0, - * large page size, shared page, cache enabled, and valid. - * Also mark all subpages valid and write access. - */ -#define MI_BOOTINIT 0x000001fd - -#define SPRN_MD_CTR 792 /* Data TLB control register */ -#define MD_GPM 0x80000000 /* Set domain manager mode */ -#define MD_PPM 0x40000000 /* Set subpage protection */ -#define MD_CIDEF 0x20000000 /* Set cache inhibit when MMU dis */ -#define MD_WTDEF 0x10000000 /* Set writethrough when MMU dis */ -#define MD_RSV4I 0x08000000 /* Reserve 4 TLB entries */ -#define MD_TWAM 0x04000000 /* Use 4K page hardware assist */ -#define MD_PPCS 0x02000000 /* Use MI_RPN prob/priv state */ -#define MD_IDXMASK 0x00001f00 /* TLB index to be loaded */ -#define MD_RESETVAL 0x04000000 /* Value of register at reset */ - -#define SPRN_M_CASID 793 /* Address space ID (context) to match */ -#define MC_ASIDMASK 0x0000000f /* Bits used for ASID value */ - - -/* These are the Ks and Kp from the PowerPC books. For proper operation, - * Ks = 0, Kp = 1. - */ -#define SPRN_MD_AP 794 -#define MD_Ks 0x80000000 /* Should not be set */ -#define MD_Kp 0x40000000 /* Should always be set */ - -/* The effective page number register. When read, contains the information - * about the last instruction TLB miss. When MD_RPN is written, bits in - * this register are used to create the TLB entry. - */ -#define SPRN_MD_EPN 795 -#define MD_EPNMASK 0xfffff000 /* Effective page number for entry */ -#define MD_EVALID 0x00000200 /* Entry is valid */ -#define MD_ASIDMASK 0x0000000f /* ASID match value */ - /* Reset value is undefined */ - -/* The pointer to the base address of the first level page table. - * During a software tablewalk, reading this register provides the address - * of the entry associated with MD_EPN. - */ -#define SPRN_M_TWB 796 -#define M_L1TB 0xfffff000 /* Level 1 table base address */ -#define M_L1INDX 0x00000ffc /* Level 1 index, when read */ - /* Reset value is undefined */ - -/* A "level 1" or "segment" or whatever you want to call it register. - * For the data TLB, it contains bits that get loaded into the TLB entry - * when the MD_RPN is written. It is also provides the hardware assist - * for finding the PTE address during software tablewalk. - */ -#define SPRN_MD_TWC 797 -#define MD_L2TB 0xfffff000 /* Level 2 table base address */ -#define MD_L2INDX 0xfffffe00 /* Level 2 index (*pte), when read */ -#define MD_APG 0x000001e0 /* Access protection group (0) */ -#define MD_GUARDED 0x00000010 /* Guarded storage */ -#define MD_PSMASK 0x0000000c /* Mask of page size bits */ -#define MD_PS8MEG 0x0000000c /* 8M page size */ -#define MD_PS512K 0x00000004 /* 512K page size */ -#define MD_PS4K_16K 0x00000000 /* 4K or 16K page size */ -#define MD_WT 0x00000002 /* Use writethrough page attribute */ -#define MD_SVALID 0x00000001 /* Segment entry is valid */ - /* Reset value is undefined */ - - -/* Real page number. Defined by the pte. Writing this register - * causes a TLB entry to be created for the data TLB, using - * additional information from the MD_EPN, and MD_TWC registers. - */ -#define SPRN_MD_RPN 798 - -/* This is a temporary storage register that could be used to save - * a processor working register during a tablewalk. - */ -#define SPRN_M_TW 799 - -#ifndef __ASSEMBLY__ -typedef unsigned long phys_addr_t; - -typedef struct { - unsigned long id; - unsigned long vdso_base; -} mm_context_t; -#endif /* !__ASSEMBLY__ */ - -#endif /* _ASM_POWERPC_MMU_8XX_H_ */ diff --git a/trunk/include/asm-powerpc/mmu-fsl-booke.h b/trunk/include/asm-powerpc/mmu-fsl-booke.h deleted file mode 100644 index 37580004cd7a..000000000000 --- a/trunk/include/asm-powerpc/mmu-fsl-booke.h +++ /dev/null @@ -1,88 +0,0 @@ -#ifndef _ASM_POWERPC_MMU_FSL_BOOKE_H_ -#define _ASM_POWERPC_MMU_FSL_BOOKE_H_ -/* - * Freescale Book-E MMU support - */ - -/* Book-E defined page sizes */ -#define BOOKE_PAGESZ_1K 0 -#define BOOKE_PAGESZ_4K 1 -#define BOOKE_PAGESZ_16K 2 -#define BOOKE_PAGESZ_64K 3 -#define BOOKE_PAGESZ_256K 4 -#define BOOKE_PAGESZ_1M 5 -#define BOOKE_PAGESZ_4M 6 -#define BOOKE_PAGESZ_16M 7 -#define BOOKE_PAGESZ_64M 8 -#define BOOKE_PAGESZ_256M 9 -#define BOOKE_PAGESZ_1GB 10 -#define BOOKE_PAGESZ_4GB 11 -#define BOOKE_PAGESZ_16GB 12 -#define BOOKE_PAGESZ_64GB 13 -#define BOOKE_PAGESZ_256GB 14 -#define BOOKE_PAGESZ_1TB 15 - -#define MAS0_TLBSEL(x) ((x << 28) & 0x30000000) -#define MAS0_ESEL(x) ((x << 16) & 0x0FFF0000) -#define MAS0_NV(x) ((x) & 0x00000FFF) - -#define MAS1_VALID 0x80000000 -#define MAS1_IPROT 0x40000000 -#define MAS1_TID(x) ((x << 16) & 0x3FFF0000) -#define MAS1_TS 0x00001000 -#define MAS1_TSIZE(x) ((x << 8) & 0x00000F00) - -#define MAS2_EPN 0xFFFFF000 -#define MAS2_X0 0x00000040 -#define MAS2_X1 0x00000020 -#define MAS2_W 0x00000010 -#define MAS2_I 0x00000008 -#define MAS2_M 0x00000004 -#define MAS2_G 0x00000002 -#define MAS2_E 0x00000001 - -#define MAS3_RPN 0xFFFFF000 -#define MAS3_U0 0x00000200 -#define MAS3_U1 0x00000100 -#define MAS3_U2 0x00000080 -#define MAS3_U3 0x00000040 -#define MAS3_UX 0x00000020 -#define MAS3_SX 0x00000010 -#define MAS3_UW 0x00000008 -#define MAS3_SW 0x00000004 -#define MAS3_UR 0x00000002 -#define MAS3_SR 0x00000001 - -#define MAS4_TLBSELD(x) MAS0_TLBSEL(x) -#define MAS4_TIDDSEL 0x000F0000 -#define MAS4_TSIZED(x) MAS1_TSIZE(x) -#define MAS4_X0D 0x00000040 -#define MAS4_X1D 0x00000020 -#define MAS4_WD 0x00000010 -#define MAS4_ID 0x00000008 -#define MAS4_MD 0x00000004 -#define MAS4_GD 0x00000002 -#define MAS4_ED 0x00000001 - -#define MAS6_SPID0 0x3FFF0000 -#define MAS6_SPID1 0x00007FFE -#define MAS6_SAS 0x00000001 -#define MAS6_SPID MAS6_SPID0 - -#define MAS7_RPN 0xFFFFFFFF - -#ifndef __ASSEMBLY__ - -#ifndef CONFIG_PHYS_64BIT -typedef unsigned long phys_addr_t; -#else -typedef unsigned long long phys_addr_t; -#endif - -typedef struct { - unsigned long id; - unsigned long vdso_base; -} mm_context_t; -#endif /* !__ASSEMBLY__ */ - -#endif /* _ASM_POWERPC_MMU_FSL_BOOKE_H_ */ diff --git a/trunk/include/asm-powerpc/mmu-hash32.h b/trunk/include/asm-powerpc/mmu-hash32.h deleted file mode 100644 index 4bd735be3833..000000000000 --- a/trunk/include/asm-powerpc/mmu-hash32.h +++ /dev/null @@ -1,91 +0,0 @@ -#ifndef _ASM_POWERPC_MMU_HASH32_H_ -#define _ASM_POWERPC_MMU_HASH32_H_ -/* - * 32-bit hash table MMU support - */ - -/* - * BATs - */ - -/* Block size masks */ -#define BL_128K 0x000 -#define BL_256K 0x001 -#define BL_512K 0x003 -#define BL_1M 0x007 -#define BL_2M 0x00F -#define BL_4M 0x01F -#define BL_8M 0x03F -#define BL_16M 0x07F -#define BL_32M 0x0FF -#define BL_64M 0x1FF -#define BL_128M 0x3FF -#define BL_256M 0x7FF - -/* BAT Access Protection */ -#define BPP_XX 0x00 /* No access */ -#define BPP_RX 0x01 /* Read only */ -#define BPP_RW 0x02 /* Read/write */ - -#ifndef __ASSEMBLY__ -struct ppc_bat { - struct { - unsigned long bepi:15; /* Effective page index (virtual address) */ - unsigned long :4; /* Unused */ - unsigned long bl:11; /* Block size mask */ - unsigned long vs:1; /* Supervisor valid */ - unsigned long vp:1; /* User valid */ - } batu; /* Upper register */ - struct { - unsigned long brpn:15; /* Real page index (physical address) */ - unsigned long :10; /* Unused */ - unsigned long w:1; /* Write-thru cache */ - unsigned long i:1; /* Cache inhibit */ - unsigned long m:1; /* Memory coherence */ - unsigned long g:1; /* Guarded (MBZ in IBAT) */ - unsigned long :1; /* Unused */ - unsigned long pp:2; /* Page access protections */ - } batl; /* Lower register */ -}; -#endif /* !__ASSEMBLY__ */ - -/* - * Hash table - */ - -/* Values for PP (assumes Ks=0, Kp=1) */ -#define PP_RWXX 0 /* Supervisor read/write, User none */ -#define PP_RWRX 1 /* Supervisor read/write, User read */ -#define PP_RWRW 2 /* Supervisor read/write, User read/write */ -#define PP_RXRX 3 /* Supervisor read, User read */ - -#ifndef __ASSEMBLY__ - -/* Hardware Page Table Entry */ -struct hash_pte { - unsigned long v:1; /* Entry is valid */ - unsigned long vsid:24; /* Virtual segment identifier */ - unsigned long h:1; /* Hash algorithm indicator */ - unsigned long api:6; /* Abbreviated page index */ - unsigned long rpn:20; /* Real (physical) page number */ - unsigned long :3; /* Unused */ - unsigned long r:1; /* Referenced */ - unsigned long c:1; /* Changed */ - unsigned long w:1; /* Write-thru cache mode */ - unsigned long i:1; /* Cache inhibited */ - unsigned long m:1; /* Memory coherence */ - unsigned long g:1; /* Guarded */ - unsigned long :1; /* Unused */ - unsigned long pp:2; /* Page protection */ -}; - -typedef struct { - unsigned long id; - unsigned long vdso_base; -} mm_context_t; - -typedef unsigned long phys_addr_t; - -#endif /* !__ASSEMBLY__ */ - -#endif /* _ASM_POWERPC_MMU_HASH32_H_ */ diff --git a/trunk/include/asm-powerpc/mmu-hash64.h b/trunk/include/asm-powerpc/mmu-hash64.h index 695962f02059..b8dca30bd0b5 100644 --- a/trunk/include/asm-powerpc/mmu-hash64.h +++ b/trunk/include/asm-powerpc/mmu-hash64.h @@ -94,9 +94,6 @@ extern char initial_stab[]; #define HPTE_R_C ASM_CONST(0x0000000000000080) #define HPTE_R_R ASM_CONST(0x0000000000000100) -#define HPTE_V_1TB_SEG ASM_CONST(0x4000000000000000) -#define HPTE_V_VRMA_MASK ASM_CONST(0x4001ffffff000000) - /* Values for PP (assumes Ks=0, Kp=1) */ /* pp0 will always be 0 for linux */ #define PP_RWXX 0 /* Supervisor read/write, User none */ @@ -106,12 +103,12 @@ extern char initial_stab[]; #ifndef __ASSEMBLY__ -struct hash_pte { +typedef struct { unsigned long v; unsigned long r; -}; +} hpte_t; -extern struct hash_pte *htab_address; +extern hpte_t *htab_address; extern unsigned long htab_size_bytes; extern unsigned long htab_hash_mask; diff --git a/trunk/include/asm-powerpc/mmu.h b/trunk/include/asm-powerpc/mmu.h index d44d211e7588..fe510fff8907 100644 --- a/trunk/include/asm-powerpc/mmu.h +++ b/trunk/include/asm-powerpc/mmu.h @@ -5,18 +5,13 @@ #ifdef CONFIG_PPC64 /* 64-bit classic hash table MMU */ # include -#elif defined(CONFIG_PPC_STD_MMU) -/* 32-bit classic hash table MMU */ -# include #elif defined(CONFIG_44x) /* 44x-style software loaded TLB */ # include -#elif defined(CONFIG_FSL_BOOKE) -/* Freescale Book-E software loaded TLB */ -# include -#elif defined (CONFIG_PPC_8xx) -/* Motorola/Freescale 8xx software loaded TLB */ -# include +#else +/* Other 32-bit. FIXME: split up the other 32-bit MMU types, and + * revise for arch/powerpc */ +# include #endif #endif /* __KERNEL__ */ diff --git a/trunk/include/asm-powerpc/mmu_context.h b/trunk/include/asm-powerpc/mmu_context.h index f863ac21409e..40c9e5a13ff1 100644 --- a/trunk/include/asm-powerpc/mmu_context.h +++ b/trunk/include/asm-powerpc/mmu_context.h @@ -2,210 +2,16 @@ #define __ASM_POWERPC_MMU_CONTEXT_H #ifdef __KERNEL__ -#include -#include -#include - #ifndef CONFIG_PPC64 -#include -#include - -/* - * On 32-bit PowerPC 6xx/7xx/7xxx CPUs, we use a set of 16 VSIDs - * (virtual segment identifiers) for each context. Although the - * hardware supports 24-bit VSIDs, and thus >1 million contexts, - * we only use 32,768 of them. That is ample, since there can be - * at most around 30,000 tasks in the system anyway, and it means - * that we can use a bitmap to indicate which contexts are in use. - * Using a bitmap means that we entirely avoid all of the problems - * that we used to have when the context number overflowed, - * particularly on SMP systems. - * -- paulus. - */ - -/* - * This function defines the mapping from contexts to VSIDs (virtual - * segment IDs). We use a skew on both the context and the high 4 bits - * of the 32-bit virtual address (the "effective segment ID") in order - * to spread out the entries in the MMU hash table. Note, if this - * function is changed then arch/ppc/mm/hashtable.S will have to be - * changed to correspond. - */ -#define CTX_TO_VSID(ctx, va) (((ctx) * (897 * 16) + ((va) >> 28) * 0x111) \ - & 0xffffff) - -/* - The MPC8xx has only 16 contexts. We rotate through them on each - task switch. A better way would be to keep track of tasks that - own contexts, and implement an LRU usage. That way very active - tasks don't always have to pay the TLB reload overhead. The - kernel pages are mapped shared, so the kernel can run on behalf - of any task that makes a kernel entry. Shared does not mean they - are not protected, just that the ASID comparison is not performed. - -- Dan - - The IBM4xx has 256 contexts, so we can just rotate through these - as a way of "switching" contexts. If the TID of the TLB is zero, - the PID/TID comparison is disabled, so we can use a TID of zero - to represent all kernel pages as shared among all contexts. - -- Dan - */ - -static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk) -{ -} - -#ifdef CONFIG_8xx -#define NO_CONTEXT 16 -#define LAST_CONTEXT 15 -#define FIRST_CONTEXT 0 - -#elif defined(CONFIG_4xx) -#define NO_CONTEXT 256 -#define LAST_CONTEXT 255 -#define FIRST_CONTEXT 1 - -#elif defined(CONFIG_E200) || defined(CONFIG_E500) -#define NO_CONTEXT 256 -#define LAST_CONTEXT 255 -#define FIRST_CONTEXT 1 - -#else - -/* PPC 6xx, 7xx CPUs */ -#define NO_CONTEXT ((unsigned long) -1) -#define LAST_CONTEXT 32767 -#define FIRST_CONTEXT 1 -#endif - -/* - * Set the current MMU context. - * On 32-bit PowerPCs (other than the 8xx embedded chips), this is done by - * loading up the segment registers for the user part of the address space. - * - * Since the PGD is immediately available, it is much faster to simply - * pass this along as a second parameter, which is required for 8xx and - * can be used for debugging on all processors (if you happen to have - * an Abatron). - */ -extern void set_context(unsigned long contextid, pgd_t *pgd); - -/* - * Bitmap of contexts in use. - * The size of this bitmap is LAST_CONTEXT + 1 bits. - */ -extern unsigned long context_map[]; - -/* - * This caches the next context number that we expect to be free. - * Its use is an optimization only, we can't rely on this context - * number to be free, but it usually will be. - */ -extern unsigned long next_mmu_context; - -/* - * If we don't have sufficient contexts to give one to every task - * that could be in the system, we need to be able to steal contexts. - * These variables support that. - */ -#if LAST_CONTEXT < 30000 -#define FEW_CONTEXTS 1 -extern atomic_t nr_free_contexts; -extern struct mm_struct *context_mm[LAST_CONTEXT+1]; -extern void steal_context(void); -#endif - -/* - * Get a new mmu context for the address space described by `mm'. - */ -static inline void get_mmu_context(struct mm_struct *mm) -{ - unsigned long ctx; - - if (mm->context.id != NO_CONTEXT) - return; -#ifdef FEW_CONTEXTS - while (atomic_dec_if_positive(&nr_free_contexts) < 0) - steal_context(); -#endif - ctx = next_mmu_context; - while (test_and_set_bit(ctx, context_map)) { - ctx = find_next_zero_bit(context_map, LAST_CONTEXT+1, ctx); - if (ctx > LAST_CONTEXT) - ctx = 0; - } - next_mmu_context = (ctx + 1) & LAST_CONTEXT; - mm->context.id = ctx; -#ifdef FEW_CONTEXTS - context_mm[ctx] = mm; -#endif -} - -/* - * Set up the context for a new address space. - */ -static inline int init_new_context(struct task_struct *t, struct mm_struct *mm) -{ - mm->context.id = NO_CONTEXT; - mm->context.vdso_base = 0; - return 0; -} - -/* - * We're finished using the context for an address space. - */ -static inline void destroy_context(struct mm_struct *mm) -{ - preempt_disable(); - if (mm->context.id != NO_CONTEXT) { - clear_bit(mm->context.id, context_map); - mm->context.id = NO_CONTEXT; -#ifdef FEW_CONTEXTS - atomic_inc(&nr_free_contexts); -#endif - } - preempt_enable(); -} - -static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, - struct task_struct *tsk) -{ -#ifdef CONFIG_ALTIVEC - if (cpu_has_feature(CPU_FTR_ALTIVEC)) - asm volatile ("dssall;\n" -#ifndef CONFIG_POWER4 - "sync;\n" /* G4 needs a sync here, G5 apparently not */ -#endif - : : ); -#endif /* CONFIG_ALTIVEC */ - - tsk->thread.pgdir = next->pgd; - - /* No need to flush userspace segments if the mm doesnt change */ - if (prev == next) - return; - - /* Setup new userspace context */ - get_mmu_context(next); - set_context(next->context.id, next->pgd); -} - -#define deactivate_mm(tsk,mm) do { } while (0) - -/* - * After we have set current->mm to a new value, this activates - * the context for the new mm so we see the new mappings. - */ -#define activate_mm(active_mm, mm) switch_mm(active_mm, mm, current) - -extern void mmu_context_init(void); - - +#include #else #include #include #include +#include +#include +#include /* * Copyright (C) 2001 PPC 64 Team, IBM Corp diff --git a/trunk/include/asm-powerpc/mpc86xx.h b/trunk/include/asm-powerpc/mpc86xx.h index 15f650f987e7..b85df45b1a84 100644 --- a/trunk/include/asm-powerpc/mpc86xx.h +++ b/trunk/include/asm-powerpc/mpc86xx.h @@ -19,6 +19,12 @@ #ifdef CONFIG_PPC_86xx +#define _IO_BASE isa_io_base +#define _ISA_MEM_BASE isa_mem_base +#ifdef CONFIG_PCI +#define PCI_DRAM_OFFSET pci_dram_offset +#endif + #define CPU0_BOOT_RELEASE 0x01000000 #define CPU1_BOOT_RELEASE 0x02000000 #define CPU_ALL_RELEASED (CPU0_BOOT_RELEASE | CPU1_BOOT_RELEASE) diff --git a/trunk/include/asm-powerpc/mpc8xx.h b/trunk/include/asm-powerpc/mpc8xx.h index 2be014b6f57c..580371120e1a 100644 --- a/trunk/include/asm-powerpc/mpc8xx.h +++ b/trunk/include/asm-powerpc/mpc8xx.h @@ -23,10 +23,6 @@ #include #endif -#ifdef CONFIG_PCMCIA_M8XX -extern struct mpc8xx_pcmcia_ops m8xx_pcmcia_ops; -#endif - #endif /* CONFIG_8xx */ #endif /* __CONFIG_8xx_DEFS */ #endif /* __KERNEL__ */ diff --git a/trunk/include/asm-powerpc/pci-bridge.h b/trunk/include/asm-powerpc/pci-bridge.h index e72c2a60853c..d9bf5aba96cb 100644 --- a/trunk/include/asm-powerpc/pci-bridge.h +++ b/trunk/include/asm-powerpc/pci-bridge.h @@ -2,91 +2,12 @@ #define _ASM_POWERPC_PCI_BRIDGE_H #ifdef __KERNEL__ -#include -#include -#include - #ifndef CONFIG_PPC64 - -struct device_node; -struct pci_controller; - -/* - * Structure of a PCI controller (host bridge) - */ -struct pci_controller { - struct pci_bus *bus; - char is_dynamic; - void *arch_data; - struct list_head list_node; - struct device *parent; - - int first_busno; - int last_busno; - int self_busno; - - void __iomem *io_base_virt; - resource_size_t io_base_phys; - - /* Some machines (PReP) have a non 1:1 mapping of - * the PCI memory space in the CPU bus space - */ - resource_size_t pci_mem_offset; - - struct pci_ops *ops; - volatile unsigned int __iomem *cfg_addr; - volatile void __iomem *cfg_data; - - /* - * Used for variants of PCI indirect handling and possible quirks: - * SET_CFG_TYPE - used on 4xx or any PHB that does explicit type0/1 - * EXT_REG - provides access to PCI-e extended registers - * SURPRESS_PRIMARY_BUS - we surpress the setting of PCI_PRIMARY_BUS - * on Freescale PCI-e controllers since they used the PCI_PRIMARY_BUS - * to determine which bus number to match on when generating type0 - * config cycles - */ -#define PPC_INDIRECT_TYPE_SET_CFG_TYPE (0x00000001) -#define PPC_INDIRECT_TYPE_EXT_REG (0x00000002) -#define PPC_INDIRECT_TYPE_SURPRESS_PRIMARY_BUS (0x00000004) - u32 indirect_type; - - /* Currently, we limit ourselves to 1 IO range and 3 mem - * ranges since the common pci_bus structure can't handle more - */ - struct resource io_resource; - struct resource mem_resources[3]; - int global_number; /* PCI domain number */ -}; - -static inline struct pci_controller *pci_bus_to_host(struct pci_bus *bus) -{ - return bus->sysdata; -} - -/* These are used for config access before all the PCI probing - has been done. */ -int early_read_config_byte(struct pci_controller *hose, int bus, int dev_fn, - int where, u8 *val); -int early_read_config_word(struct pci_controller *hose, int bus, int dev_fn, - int where, u16 *val); -int early_read_config_dword(struct pci_controller *hose, int bus, int dev_fn, - int where, u32 *val); -int early_write_config_byte(struct pci_controller *hose, int bus, int dev_fn, - int where, u8 val); -int early_write_config_word(struct pci_controller *hose, int bus, int dev_fn, - int where, u16 val); -int early_write_config_dword(struct pci_controller *hose, int bus, int dev_fn, - int where, u32 val); - -extern void setup_indirect_pci_nomap(struct pci_controller* hose, - void __iomem *cfg_addr, void __iomem *cfg_data); -extern void setup_indirect_pci(struct pci_controller* hose, - u32 cfg_addr, u32 cfg_data); -extern void setup_grackle(struct pci_controller *hose); - +#include #else +#include +#include /* * This program is free software; you can redistribute it and/or @@ -110,7 +31,6 @@ struct pci_controller { int last_busno; void __iomem *io_base_virt; - void *io_base_alloc; resource_size_t io_base_phys; /* Some machines have a non 1:1 mapping of @@ -128,7 +48,8 @@ struct pci_controller { */ struct resource io_resource; struct resource mem_resources[3]; - int global_number; + int global_number; + int local_number; unsigned long buid; unsigned long dma_window_base_cur; unsigned long dma_window_size; @@ -149,22 +70,19 @@ struct pci_dn { int devfn; /* pci device and function number */ int class_code; /* pci device class */ - struct pci_controller *phb; /* for pci devices */ - struct iommu_table *iommu_table; /* for phb's or bridges */ - struct pci_dev *pcidev; /* back-pointer to the pci device */ - struct device_node *node; /* back-pointer to the device_node */ - - int pci_ext_config_space; /* for pci devices */ - -#ifdef CONFIG_EEH +#ifdef CONFIG_PPC_PSERIES int eeh_mode; /* See eeh.h for possible EEH_MODEs */ int eeh_config_addr; int eeh_pe_config_addr; /* new-style partition endpoint address */ int eeh_check_count; /* # times driver ignored error */ int eeh_freeze_count; /* # times this device froze up. */ - int eeh_false_positives; /* # times this device reported #ff's */ - u32 config_space[16]; /* saved PCI config space */ #endif + int pci_ext_config_space; /* for pci devices */ + struct pci_controller *phb; /* for pci devices */ + struct iommu_table *iommu_table; /* for phb's or bridges */ + struct pci_dev *pcidev; /* back-pointer to the pci device */ + struct device_node *node; /* back-pointer to the device_node */ + u32 config_space[16]; /* saved PCI config space */ }; /* Get the pointer to a device_node's pci_dn */ @@ -210,6 +128,9 @@ static inline struct device_node *pci_bus_to_OF_node(struct pci_bus *bus) /** Find the bus corresponding to the indicated device node */ struct pci_bus * pcibios_find_pci_bus(struct device_node *dn); +extern void pci_process_bridge_OF_ranges(struct pci_controller *hose, + struct device_node *dev, int primary); + /** Remove all of the PCI devices under this bus */ void pcibios_remove_pci_devices(struct pci_bus *bus); @@ -227,38 +148,13 @@ static inline struct pci_controller *pci_bus_to_host(struct pci_bus *bus) return PCI_DN(busdn)->phb; } -extern void pcibios_free_controller(struct pci_controller *phb); - -extern void isa_bridge_find_early(struct pci_controller *hose); - -extern int pcibios_unmap_io_space(struct pci_bus *bus); -extern int pcibios_map_io_space(struct pci_bus *bus); - -/* Return values for ppc_md.pci_probe_mode function */ -#define PCI_PROBE_NONE -1 /* Don't look at this bus at all */ -#define PCI_PROBE_NORMAL 0 /* Do normal PCI probing */ -#define PCI_PROBE_DEVTREE 1 /* Instantiate from device tree */ - -#ifdef CONFIG_NUMA -#define PHB_SET_NODE(PHB, NODE) ((PHB)->node = (NODE)) -#else -#define PHB_SET_NODE(PHB, NODE) ((PHB)->node = -1) -#endif - -#endif /* CONFIG_PPC64 */ - -/* Get the PCI host controller for an OF device */ extern struct pci_controller* pci_find_hose_for_OF_device(struct device_node* node); -/* Fill up host controller resources from the OF node */ -extern void -pci_process_bridge_OF_ranges(struct pci_controller *hose, - struct device_node *dev, int primary); - -/* Allocate a new PCI host bridge structure */ extern struct pci_controller * pcibios_alloc_controller(struct device_node *dev); +extern void pcibios_free_controller(struct pci_controller *phb); + #ifdef CONFIG_PCI extern unsigned long pci_address_to_pio(phys_addr_t address); #else @@ -268,7 +164,17 @@ static inline unsigned long pci_address_to_pio(phys_addr_t address) } #endif +/* Return values for ppc_md.pci_probe_mode function */ +#define PCI_PROBE_NONE -1 /* Don't look at this bus at all */ +#define PCI_PROBE_NORMAL 0 /* Do normal PCI probing */ +#define PCI_PROBE_DEVTREE 1 /* Instantiate from device tree */ +#ifdef CONFIG_NUMA +#define PHB_SET_NODE(PHB, NODE) ((PHB)->node = (NODE)) +#else +#define PHB_SET_NODE(PHB, NODE) ((PHB)->node = -1) +#endif +#endif /* CONFIG_PPC64 */ #endif /* __KERNEL__ */ #endif diff --git a/trunk/include/asm-powerpc/pci.h b/trunk/include/asm-powerpc/pci.h index 7b11765c6865..e16e7bc9ab5c 100644 --- a/trunk/include/asm-powerpc/pci.h +++ b/trunk/include/asm-powerpc/pci.h @@ -95,6 +95,8 @@ static inline void pci_dma_burst_advice(struct pci_dev *pdev, #define get_pci_dma_ops() NULL #endif +extern int pci_domain_nr(struct pci_bus *bus); + /* Decide whether to display the domain number in /proc */ extern int pci_proc_domain(struct pci_bus *bus); @@ -110,6 +112,9 @@ static inline void pci_dma_burst_advice(struct pci_dev *pdev, } #endif +/* Return the index of the PCI controller for device PDEV. */ +#define pci_domain_nr(bus) ((struct pci_controller *)(bus)->sysdata)->index + /* Set the name of the bus as it appears in /proc/bus/pci */ static inline int pci_proc_domain(struct pci_bus *bus) { @@ -118,8 +123,6 @@ static inline int pci_proc_domain(struct pci_bus *bus) #endif /* CONFIG_PPC64 */ -extern int pci_domain_nr(struct pci_bus *bus); - struct vm_area_struct; /* Map a range of PCI memory or I/O space for a device into user space */ int pci_mmap_page_range(struct pci_dev *pdev, struct vm_area_struct *vma, @@ -199,6 +202,10 @@ static inline struct resource *pcibios_select_root(struct pci_dev *pdev, return root; } +extern int unmap_bus_range(struct pci_bus *bus); + +extern int remap_bus_range(struct pci_bus *bus); + extern void pcibios_fixup_device_resources(struct pci_dev *dev, struct pci_bus *bus); diff --git a/trunk/include/asm-powerpc/pgtable-ppc32.h b/trunk/include/asm-powerpc/pgtable-ppc32.h index 6c236d4d6262..973c1c13bdc0 100644 --- a/trunk/include/asm-powerpc/pgtable-ppc32.h +++ b/trunk/include/asm-powerpc/pgtable-ppc32.h @@ -6,7 +6,11 @@ #ifndef __ASSEMBLY__ #include #include +#include /* For TASK_SIZE */ +#include +#include #include /* For sub-arch specific PPC_PIN_SIZE */ +struct mm_struct; extern unsigned long va_to_phys(unsigned long address); extern pte_t *va_to_pte(unsigned long address); @@ -484,6 +488,14 @@ extern unsigned long bad_call_to_PMD_PAGE_SIZE(void); #define pfn_pte(pfn, prot) __pte(((pte_basic_t)(pfn) << PFN_SHIFT_OFFSET) |\ pgprot_val(prot)) #define mk_pte(page, prot) pfn_pte(page_to_pfn(page), prot) + +/* + * ZERO_PAGE is a global shared page that is always zero: used + * for zero-mapped memory areas etc.. + */ +extern unsigned long empty_zero_page[1024]; +#define ZERO_PAGE(vaddr) (virt_to_page(empty_zero_page)) + #endif /* __ASSEMBLY__ */ #define pte_none(pte) ((pte_val(pte) & ~_PTE_NONE_MASK) == 0) @@ -712,6 +724,10 @@ extern pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn, #define pte_unmap(pte) kunmap_atomic(pte, KM_PTE0) #define pte_unmap_nested(pte) kunmap_atomic(pte, KM_PTE1) +extern pgd_t swapper_pg_dir[PTRS_PER_PGD]; + +extern void paging_init(void); + /* * Encode and decode a swap entry. * Note that the bits we use in a PTE for representing a swap entry @@ -729,6 +745,40 @@ extern pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn, #define pte_to_pgoff(pte) (pte_val(pte) >> 3) #define pgoff_to_pte(off) ((pte_t) { ((off) << 3) | _PAGE_FILE }) +/* CONFIG_APUS */ +/* For virtual address to physical address conversion */ +extern void cache_clear(__u32 addr, int length); +extern void cache_push(__u32 addr, int length); +extern int mm_end_of_chunk (unsigned long addr, int len); +extern unsigned long iopa(unsigned long addr); +extern unsigned long mm_ptov(unsigned long addr) __attribute_const__; + +/* Values for nocacheflag and cmode */ +/* These are not used by the APUS kernel_map, but prevents + compilation errors. */ +#define KERNELMAP_FULL_CACHING 0 +#define KERNELMAP_NOCACHE_SER 1 +#define KERNELMAP_NOCACHE_NONSER 2 +#define KERNELMAP_NO_COPYBACK 3 + +/* + * Map some physical address range into the kernel address space. + */ +extern unsigned long kernel_map(unsigned long paddr, unsigned long size, + int nocacheflag, unsigned long *memavailp ); + +/* + * Set cache mode of (kernel space) address range. + */ +extern void kernel_set_cachemode (unsigned long address, unsigned long size, + unsigned int cmode); + +/* Needs to be defined here and not in linux/mm.h, as it is arch dependent */ +#define kern_addr_valid(addr) (1) + +#define io_remap_pfn_range(vma, vaddr, pfn, size, prot) \ + remap_pfn_range(vma, vaddr, pfn, size, prot) + /* * No page table caches to initialise */ diff --git a/trunk/include/asm-powerpc/pgtable-ppc64.h b/trunk/include/asm-powerpc/pgtable-ppc64.h index 7ca8b5c10019..0c879121c8fc 100644 --- a/trunk/include/asm-powerpc/pgtable-ppc64.h +++ b/trunk/include/asm-powerpc/pgtable-ppc64.h @@ -7,7 +7,11 @@ #ifndef __ASSEMBLY__ #include +#include /* For TASK_SIZE */ +#include +#include #include +struct mm_struct; #endif /* __ASSEMBLY__ */ #ifdef CONFIG_PPC_64K_PAGES @@ -23,7 +27,7 @@ */ #define PGTABLE_EADDR_SIZE (PTE_INDEX_SIZE + PMD_INDEX_SIZE + \ PUD_INDEX_SIZE + PGD_INDEX_SIZE + PAGE_SHIFT) -#define PGTABLE_RANGE (ASM_CONST(1) << PGTABLE_EADDR_SIZE) +#define PGTABLE_RANGE (1UL << PGTABLE_EADDR_SIZE) #if TASK_SIZE_USER64 > PGTABLE_RANGE #error TASK_SIZE_USER64 exceeds pagetable range @@ -33,28 +37,19 @@ #error TASK_SIZE_USER64 exceeds user VSID range #endif - /* * Define the address range of the vmalloc VM area. */ #define VMALLOC_START ASM_CONST(0xD000000000000000) -#define VMALLOC_SIZE (PGTABLE_RANGE >> 1) +#define VMALLOC_SIZE ASM_CONST(0x80000000000) #define VMALLOC_END (VMALLOC_START + VMALLOC_SIZE) /* - * Define the address ranges for MMIO and IO space : - * - * ISA_IO_BASE = VMALLOC_END, 64K reserved area - * PHB_IO_BASE = ISA_IO_BASE + 64K to ISA_IO_BASE + 2G, PHB IO spaces - * IOREMAP_BASE = ISA_IO_BASE + 2G to VMALLOC_START + PGTABLE_RANGE + * Define the address range of the imalloc VM area. */ -#define FULL_IO_SIZE 0x80000000ul -#define ISA_IO_BASE (VMALLOC_END) -#define ISA_IO_END (VMALLOC_END + 0x10000ul) -#define PHB_IO_BASE (ISA_IO_END) -#define PHB_IO_END (VMALLOC_END + FULL_IO_SIZE) -#define IOREMAP_BASE (PHB_IO_END) -#define IOREMAP_END (VMALLOC_START + PGTABLE_RANGE) +#define PHBS_IO_BASE VMALLOC_END +#define IMALLOC_BASE (PHBS_IO_BASE + 0x80000000ul) /* Reserve 2 gigs for PHBs */ +#define IMALLOC_END (VMALLOC_START + PGTABLE_RANGE) /* * Region IDs @@ -139,6 +134,16 @@ #define __S110 PAGE_SHARED_X #define __S111 PAGE_SHARED_X +#ifndef __ASSEMBLY__ + +/* + * ZERO_PAGE is a global shared page that is always zero: used + * for zero-mapped memory areas etc.. + */ +extern unsigned long empty_zero_page[PAGE_SIZE/sizeof(unsigned long)]; +#define ZERO_PAGE(vaddr) (virt_to_page(empty_zero_page)) +#endif /* __ASSEMBLY__ */ + #ifdef CONFIG_HUGETLB_PAGE #define HAVE_ARCH_UNMAPPED_AREA @@ -427,6 +432,10 @@ extern pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn, #define pgd_ERROR(e) \ printk("%s:%d: bad pgd %08lx.\n", __FILE__, __LINE__, pgd_val(e)) +extern pgd_t swapper_pg_dir[]; + +extern void paging_init(void); + /* Encode and de-code a swap entry */ #define __swp_type(entry) (((entry).val >> 1) & 0x3f) #define __swp_offset(entry) ((entry).val >> 8) @@ -437,6 +446,17 @@ extern pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn, #define pgoff_to_pte(off) ((pte_t) {((off) << PTE_RPN_SHIFT)|_PAGE_FILE}) #define PTE_FILE_MAX_BITS (BITS_PER_LONG - PTE_RPN_SHIFT) +/* + * kern_addr_valid is intended to indicate whether an address is a valid + * kernel address. Most 32-bit archs define it as always true (like this) + * but most 64-bit archs actually perform a test. What should we do here? + * The only use is in fs/ncpfs/dir.c + */ +#define kern_addr_valid(addr) (1) + +#define io_remap_pfn_range(vma, vaddr, pfn, size, prot) \ + remap_pfn_range(vma, vaddr, pfn, size, prot) + void pgtable_cache_init(void); /* diff --git a/trunk/include/asm-powerpc/pgtable.h b/trunk/include/asm-powerpc/pgtable.h index d18ffe7bc7c4..78bf4ae712a6 100644 --- a/trunk/include/asm-powerpc/pgtable.h +++ b/trunk/include/asm-powerpc/pgtable.h @@ -2,13 +2,6 @@ #define _ASM_POWERPC_PGTABLE_H #ifdef __KERNEL__ -#ifndef __ASSEMBLY__ -#include /* For TASK_SIZE */ -#include -#include -struct mm_struct; -#endif /* !__ASSEMBLY__ */ - #if defined(CONFIG_PPC64) # include #else @@ -16,27 +9,6 @@ struct mm_struct; #endif #ifndef __ASSEMBLY__ -/* - * ZERO_PAGE is a global shared page that is always zero: used - * for zero-mapped memory areas etc.. - */ -extern unsigned long empty_zero_page[]; -#define ZERO_PAGE(vaddr) (virt_to_page(empty_zero_page)) - -extern pgd_t swapper_pg_dir[]; - -extern void paging_init(void); - -/* - * kern_addr_valid is intended to indicate whether an address is a valid - * kernel address. Most 32-bit archs define it as always true (like this) - * but most 64-bit archs actually perform a test. What should we do here? - */ -#define kern_addr_valid(addr) (1) - -#define io_remap_pfn_range(vma, vaddr, pfn, size, prot) \ - remap_pfn_range(vma, vaddr, pfn, size, prot) - #include #endif /* __ASSEMBLY__ */ diff --git a/trunk/include/asm-powerpc/ppc-pci.h b/trunk/include/asm-powerpc/ppc-pci.h index b847aa10074b..8e2005159ffd 100644 --- a/trunk/include/asm-powerpc/ppc-pci.h +++ b/trunk/include/asm-powerpc/ppc-pci.h @@ -26,7 +26,7 @@ extern int global_phb_number; extern void find_and_init_phbs(void); -extern struct pci_dev *isa_bridge_pcidev; /* may be NULL if no ISA bus */ +extern struct pci_dev *ppc64_isabridge_dev; /* may be NULL if no ISA bus */ /** Bus Unit ID macros; get low and hi 32-bits of the 64-bit BUID */ #define BUID_HI(buid) ((buid) >> 32) @@ -47,8 +47,8 @@ extern void init_pci_config_tokens (void); extern unsigned long get_phb_buid (struct device_node *); extern int rtas_setup_phb(struct pci_controller *phb); -/* From iSeries PCI */ -extern void iSeries_pcibios_init(void); +/* From pSeries_pci.h */ +extern void pSeries_final_fixup(void); extern unsigned long pci_probe_only; @@ -139,9 +139,6 @@ void eeh_clear_slot (struct device_node *dn, int mode_flag); */ struct device_node * find_device_pe(struct device_node *dn); -void eeh_sysfs_add_device(struct pci_dev *pdev); -void eeh_sysfs_remove_device(struct pci_dev *pdev); - #endif /* CONFIG_EEH */ #else /* CONFIG_PCI */ diff --git a/trunk/include/asm-powerpc/processor.h b/trunk/include/asm-powerpc/processor.h index e28b10805159..d947b1609491 100644 --- a/trunk/include/asm-powerpc/processor.h +++ b/trunk/include/asm-powerpc/processor.h @@ -43,6 +43,14 @@ extern int _chrp_type; /* what kind of prep workstation we are */ extern int _prep_type; +/* + * This is used to identify the board type from a given PReP board + * vendor. Board revision is also made available. This will be moved + * elsewhere soon + */ +extern unsigned char ucBoardRev; +extern unsigned char ucBoardRevMaj, ucBoardRevMin; + #endif /* CONFIG_PPC_PREP */ #endif /* defined(__KERNEL__) && defined(CONFIG_PPC32) */ diff --git a/trunk/include/asm-powerpc/prom.h b/trunk/include/asm-powerpc/prom.h index 1632baa17dc6..6845af93ba91 100644 --- a/trunk/include/asm-powerpc/prom.h +++ b/trunk/include/asm-powerpc/prom.h @@ -98,19 +98,10 @@ struct device_node { extern struct device_node *of_chosen; /* flag descriptions */ -#define OF_DYNAMIC 1 /* node and properties were allocated via kmalloc */ -#define OF_DETACHED 2 /* node has been detached from the device tree */ - -static inline int of_node_check_flag(struct device_node *n, unsigned long flag) -{ - return test_bit(flag, &n->_flags); -} - -static inline void of_node_set_flag(struct device_node *n, unsigned long flag) -{ - set_bit(flag, &n->_flags); -} +#define OF_DYNAMIC 1 /* node and properties were allocated via kmalloc */ +#define OF_IS_DYNAMIC(x) test_bit(OF_DYNAMIC, &x->_flags) +#define OF_MARK_DYNAMIC(x) set_bit(OF_DYNAMIC, &x->_flags) #define HAVE_ARCH_DEVTREE_FIXUPS @@ -133,9 +124,6 @@ extern struct device_node *of_find_node_by_type(struct device_node *from, dn = of_find_node_by_type(dn, type)) extern struct device_node *of_find_compatible_node(struct device_node *from, const char *type, const char *compat); -#define for_each_compatible_node(dn, type, compatible) \ - for (dn = of_find_compatible_node(NULL, type, compatible); dn; \ - dn = of_find_compatible_node(dn, type, compatible)) extern struct device_node *of_find_node_by_path(const char *path); extern struct device_node *of_find_node_by_phandle(phandle handle); extern struct device_node *of_find_all_nodes(struct device_node *prev); diff --git a/trunk/include/asm-powerpc/ps3.h b/trunk/include/asm-powerpc/ps3.h index a6f3f5ee7ca7..1e04651eedc4 100644 --- a/trunk/include/asm-powerpc/ps3.h +++ b/trunk/include/asm-powerpc/ps3.h @@ -35,8 +35,7 @@ union ps3_firmware_version { }; }; -void ps3_get_firmware_version(union ps3_firmware_version *v); -int ps3_compare_firmware_version(u16 major, u16 minor, u16 rev); +int ps3_get_firmware_version(union ps3_firmware_version *v); /* 'Other OS' area */ @@ -49,6 +48,18 @@ enum ps3_param_av_multi_out { enum ps3_param_av_multi_out ps3_os_area_get_av_multi_out(void); +/** + * struct ps3_device_id - HV bus device identifier from the system repository + * @bus_id: HV bus id, {1..} (zero invalid) + * @dev_id: HV device id, {0..} + */ + +struct ps3_device_id { + unsigned int bus_id; + unsigned int dev_id; +}; + + /* dma routines */ enum ps3_dma_page_size { @@ -63,8 +74,6 @@ enum ps3_dma_region_type { PS3_DMA_INTERNAL = 2, }; -struct ps3_dma_region_ops; - /** * struct ps3_dma_region - A per device dma state variables structure * @did: The HV device id. @@ -72,42 +81,21 @@ struct ps3_dma_region_ops; * @region_type: The HV region type. * @bus_addr: The 'translated' bus address of the region. * @len: The length in bytes of the region. - * @offset: The offset from the start of memory of the region. - * @ioid: The IOID of the device who owns this region * @chunk_list: Opaque variable used by the ioc page manager. - * @region_ops: struct ps3_dma_region_ops - dma region operations */ struct ps3_dma_region { - struct ps3_system_bus_device *dev; - /* device variables */ - const struct ps3_dma_region_ops *region_ops; - unsigned char ioid; + struct ps3_device_id did; enum ps3_dma_page_size page_size; enum ps3_dma_region_type region_type; - unsigned long len; - unsigned long offset; - - /* driver variables (set by ps3_dma_region_create) */ unsigned long bus_addr; + unsigned long len; struct { spinlock_t lock; struct list_head head; } chunk_list; }; -struct ps3_dma_region_ops { - int (*create)(struct ps3_dma_region *); - int (*free)(struct ps3_dma_region *); - int (*map)(struct ps3_dma_region *, - unsigned long virt_addr, - unsigned long len, - unsigned long *bus_addr, - u64 iopte_pp); - int (*unmap)(struct ps3_dma_region *, - unsigned long bus_addr, - unsigned long len); -}; /** * struct ps3_dma_region_init - Helper to initialize structure variables * @@ -115,16 +103,18 @@ struct ps3_dma_region_ops { * ps3_system_bus_device_register. */ -struct ps3_system_bus_device; - -int ps3_dma_region_init(struct ps3_system_bus_device *dev, - struct ps3_dma_region *r, enum ps3_dma_page_size page_size, - enum ps3_dma_region_type region_type, void *addr, unsigned long len); +static inline void ps3_dma_region_init(struct ps3_dma_region *r, + const struct ps3_device_id* did, enum ps3_dma_page_size page_size, + enum ps3_dma_region_type region_type) +{ + r->did = *did; + r->page_size = page_size; + r->region_type = region_type; +} int ps3_dma_region_create(struct ps3_dma_region *r); int ps3_dma_region_free(struct ps3_dma_region *r); int ps3_dma_map(struct ps3_dma_region *r, unsigned long virt_addr, - unsigned long len, unsigned long *bus_addr, - u64 iopte_pp); + unsigned long len, unsigned long *bus_addr); int ps3_dma_unmap(struct ps3_dma_region *r, unsigned long bus_addr, unsigned long len); @@ -135,7 +125,6 @@ enum ps3_mmio_page_size { PS3_MMIO_64K = 16U }; -struct ps3_mmio_region_ops; /** * struct ps3_mmio_region - a per device mmio state variables structure * @@ -143,18 +132,13 @@ struct ps3_mmio_region_ops; */ struct ps3_mmio_region { - struct ps3_system_bus_device *dev; - const struct ps3_mmio_region_ops *mmio_ops; + struct ps3_device_id did; unsigned long bus_addr; unsigned long len; enum ps3_mmio_page_size page_size; unsigned long lpar_addr; }; -struct ps3_mmio_region_ops { - int (*create)(struct ps3_mmio_region *); - int (*free)(struct ps3_mmio_region *); -}; /** * struct ps3_mmio_region_init - Helper to initialize structure variables * @@ -162,9 +146,15 @@ struct ps3_mmio_region_ops { * ps3_system_bus_device_register. */ -int ps3_mmio_region_init(struct ps3_system_bus_device *dev, - struct ps3_mmio_region *r, unsigned long bus_addr, unsigned long len, - enum ps3_mmio_page_size page_size); +static inline void ps3_mmio_region_init(struct ps3_mmio_region *r, + const struct ps3_device_id* did, unsigned long bus_addr, + unsigned long len, enum ps3_mmio_page_size page_size) +{ + r->did = *did; + r->bus_addr = bus_addr; + r->len = len; + r->page_size = page_size; +} int ps3_mmio_region_create(struct ps3_mmio_region *r); int ps3_free_mmio_region(struct ps3_mmio_region *r); unsigned long ps3_mm_phys_to_lpar(unsigned long phys_addr); @@ -197,10 +187,11 @@ int ps3_spe_irq_setup(enum ps3_cpu_binding cpu, unsigned long spe_id, unsigned int class, unsigned int *virq); int ps3_spe_irq_destroy(unsigned int virq); -int ps3_sb_event_receive_port_setup(struct ps3_system_bus_device *dev, - enum ps3_cpu_binding cpu, unsigned int *virq); -int ps3_sb_event_receive_port_destroy(struct ps3_system_bus_device *dev, - unsigned int virq); +int ps3_sb_event_receive_port_setup(enum ps3_cpu_binding cpu, + const struct ps3_device_id *did, unsigned int interrupt_id, + unsigned int *virq); +int ps3_sb_event_receive_port_destroy(const struct ps3_device_id *did, + unsigned int interrupt_id, unsigned int virq); /* lv1 result codes */ @@ -298,33 +289,11 @@ static inline const char* ps3_result(int result) /* system bus routines */ enum ps3_match_id { - PS3_MATCH_ID_EHCI = 1, - PS3_MATCH_ID_OHCI = 2, - PS3_MATCH_ID_GELIC = 3, - PS3_MATCH_ID_AV_SETTINGS = 4, - PS3_MATCH_ID_SYSTEM_MANAGER = 5, - PS3_MATCH_ID_STOR_DISK = 6, - PS3_MATCH_ID_STOR_ROM = 7, - PS3_MATCH_ID_STOR_FLASH = 8, - PS3_MATCH_ID_SOUND = 9, - PS3_MATCH_ID_GRAPHICS = 10, -}; - -#define PS3_MODULE_ALIAS_EHCI "ps3:1" -#define PS3_MODULE_ALIAS_OHCI "ps3:2" -#define PS3_MODULE_ALIAS_GELIC "ps3:3" -#define PS3_MODULE_ALIAS_AV_SETTINGS "ps3:4" -#define PS3_MODULE_ALIAS_SYSTEM_MANAGER "ps3:5" -#define PS3_MODULE_ALIAS_STOR_DISK "ps3:6" -#define PS3_MODULE_ALIAS_STOR_ROM "ps3:7" -#define PS3_MODULE_ALIAS_STOR_FLASH "ps3:8" -#define PS3_MODULE_ALIAS_SOUND "ps3:9" -#define PS3_MODULE_ALIAS_GRAPHICS "ps3:10" - -enum ps3_system_bus_device_type { - PS3_DEVICE_TYPE_IOC0 = 1, - PS3_DEVICE_TYPE_SB, - PS3_DEVICE_TYPE_VUART, + PS3_MATCH_ID_EHCI = 1, + PS3_MATCH_ID_OHCI, + PS3_MATCH_ID_GELIC, + PS3_MATCH_ID_AV_SETTINGS, + PS3_MATCH_ID_SYSTEM_MANAGER, }; /** @@ -333,23 +302,14 @@ enum ps3_system_bus_device_type { struct ps3_system_bus_device { enum ps3_match_id match_id; - enum ps3_system_bus_device_type dev_type; - - unsigned int bus_id; /* SB */ - unsigned int dev_id; /* SB */ - unsigned int interrupt_id; /* SB */ - struct ps3_dma_region *d_region; /* SB, IOC0 */ - struct ps3_mmio_region *m_region; /* SB, IOC0*/ - unsigned int port_number; /* VUART */ - -/* struct iommu_table *iommu_table; -- waiting for BenH's cleanups */ + struct ps3_device_id did; + unsigned int interrupt_id; +/* struct iommu_table *iommu_table; -- waiting for Ben's cleanups */ + struct ps3_dma_region *d_region; + struct ps3_mmio_region *m_region; struct device core; - void *driver_priv; /* private driver variables */ }; -int ps3_open_hv_device(struct ps3_system_bus_device *dev); -int ps3_close_hv_device(struct ps3_system_bus_device *dev); - /** * struct ps3_system_bus_driver - a driver for a device on the system bus */ @@ -359,7 +319,6 @@ struct ps3_system_bus_driver { struct device_driver core; int (*probe)(struct ps3_system_bus_device *); int (*remove)(struct ps3_system_bus_device *); - int (*shutdown)(struct ps3_system_bus_device *); /* int (*suspend)(struct ps3_system_bus_device *, pm_message_t); */ /* int (*resume)(struct ps3_system_bus_device *); */ }; @@ -367,24 +326,16 @@ struct ps3_system_bus_driver { int ps3_system_bus_device_register(struct ps3_system_bus_device *dev); int ps3_system_bus_driver_register(struct ps3_system_bus_driver *drv); void ps3_system_bus_driver_unregister(struct ps3_system_bus_driver *drv); - -static inline struct ps3_system_bus_driver *ps3_drv_to_system_bus_drv( +static inline struct ps3_system_bus_driver *to_ps3_system_bus_driver( struct device_driver *_drv) { return container_of(_drv, struct ps3_system_bus_driver, core); } -static inline struct ps3_system_bus_device *ps3_dev_to_system_bus_dev( +static inline struct ps3_system_bus_device *to_ps3_system_bus_device( struct device *_dev) { return container_of(_dev, struct ps3_system_bus_device, core); } -static inline struct ps3_system_bus_driver * - ps3_system_bus_dev_to_system_bus_drv(struct ps3_system_bus_device *_dev) -{ - BUG_ON(!_dev); - BUG_ON(!_dev->core.driver); - return ps3_drv_to_system_bus_drv(_dev->core.driver); -} /** * ps3_system_bus_set_drvdata - @@ -407,17 +358,32 @@ static inline void *ps3_system_bus_get_driver_data( extern struct bus_type ps3_system_bus_type; -/* system manager */ +/* vuart routines */ + +struct ps3_vuart_port_priv; + +/** + * struct ps3_vuart_port_device - a device on a vuart port + */ + +struct ps3_vuart_port_device { + enum ps3_match_id match_id; + struct device core; + struct ps3_vuart_port_priv* priv; /* private driver variables */ -struct ps3_sys_manager_ops { - struct ps3_system_bus_device *dev; - void (*power_off)(struct ps3_system_bus_device *dev); - void (*restart)(struct ps3_system_bus_device *dev); }; -void ps3_sys_manager_register_ops(const struct ps3_sys_manager_ops *ops); -void ps3_sys_manager_power_off(void); +int ps3_vuart_port_device_register(struct ps3_vuart_port_device *dev); + +/* system manager */ + +#ifdef CONFIG_PS3_SYS_MANAGER void ps3_sys_manager_restart(void); +void ps3_sys_manager_power_off(void); +#else +static inline void ps3_sys_manager_restart(void) {} +static inline void ps3_sys_manager_power_off(void) {} +#endif struct ps3_prealloc { const char *name; @@ -427,7 +393,5 @@ struct ps3_prealloc { }; extern struct ps3_prealloc ps3fb_videomemory; -extern struct ps3_prealloc ps3flash_bounce_buffer; - #endif diff --git a/trunk/include/asm-powerpc/ps3av.h b/trunk/include/asm-powerpc/ps3av.h index 7df4250802de..9efc40f1c778 100644 --- a/trunk/include/asm-powerpc/ps3av.h +++ b/trunk/include/asm-powerpc/ps3av.h @@ -1,23 +1,20 @@ /* - * PS3 AV backend support. + * Copyright (C) 2006 Sony Computer Entertainment Inc. + * Copyright 2006, 2007 Sony Corporation * - * Copyright (C) 2007 Sony Computer Entertainment Inc. - * Copyright 2007 Sony Corp. + * 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; version 2 of the License. * - * 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; version 2 of the License. + * 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. * - * 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 + * 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 Street, Fifth Floor, Boston, MA 02110-1301 USA. */ - #ifndef _ASM_POWERPC_PS3AV_H_ #define _ASM_POWERPC_PS3AV_H_ @@ -162,9 +159,6 @@ #define PS3AV_CMD_VIDEO_FMT_X8R8G8B8 0x0000 /* video_out_format */ #define PS3AV_CMD_VIDEO_OUT_FORMAT_RGB_12BIT 0x0000 -/* video_cl_cnv */ -#define PS3AV_CMD_VIDEO_CL_CNV_ENABLE_LUT 0x0000 -#define PS3AV_CMD_VIDEO_CL_CNV_DISABLE_LUT 0x0010 /* video_sync */ #define PS3AV_CMD_VIDEO_SYNC_VSYNC 0x0001 #define PS3AV_CMD_VIDEO_SYNC_CSYNC 0x0004 @@ -317,8 +311,6 @@ #define PS3AV_MODE_MASK 0x000F #define PS3AV_MODE_HDCP_OFF 0x1000 /* Retail PS3 product doesn't support this */ #define PS3AV_MODE_DITHER 0x0800 -#define PS3AV_MODE_COLOR 0x0400 -#define PS3AV_MODE_WHITE 0x0200 #define PS3AV_MODE_FULL 0x0080 #define PS3AV_MODE_DVI 0x0040 #define PS3AV_MODE_RGB 0x0020 @@ -537,9 +529,9 @@ struct ps3av_pkt_video_mode { u32 video_out_format; /* in: out format */ u32 video_format; /* in: input frame buffer format */ u8 reserved3; - u8 video_cl_cnv; /* in: color conversion */ + u8 reserved4; u16 video_order; /* in: input RGB order */ - u32 reserved4; + u32 reserved5; }; /* video: format */ @@ -547,8 +539,7 @@ struct ps3av_pkt_video_format { struct ps3av_send_hdr send_hdr; u32 video_head; /* in: head */ u32 video_format; /* in: frame buffer format */ - u8 reserved; - u8 video_cl_cnv; /* in: color conversion */ + u16 reserved; u16 video_order; /* in: input RGB order */ }; @@ -707,6 +698,12 @@ static inline void ps3av_cmd_av_monitor_info_dump(const struct ps3av_pkt_av_get_ extern int ps3av_cmd_video_get_monitor_info(struct ps3av_pkt_av_get_monitor_info *, u32); +struct ps3_vuart_port_device; +extern int ps3av_vuart_write(struct ps3_vuart_port_device *dev, + const void *buf, unsigned long size); +extern int ps3av_vuart_read(struct ps3_vuart_port_device *dev, void *buf, + unsigned long size, int timeout); + extern int ps3av_set_video_mode(u32, int); extern int ps3av_set_audio_mode(u32, u32, u32, u32, u32); extern int ps3av_get_auto_mode(int); @@ -719,8 +716,5 @@ extern int ps3av_video_mute(int); extern int ps3av_audio_mute(int); extern int ps3av_dev_open(void); extern int ps3av_dev_close(void); -extern void ps3av_register_flip_ctl(void (*flip_ctl)(int on, void *data), - void *flip_data); -extern void ps3av_flip_ctl(int on); #endif /* _ASM_POWERPC_PS3AV_H_ */ diff --git a/trunk/include/asm-powerpc/ps3fb.h b/trunk/include/asm-powerpc/ps3fb.h index 3f121fe4010d..ad81cf431964 100644 --- a/trunk/include/asm-powerpc/ps3fb.h +++ b/trunk/include/asm-powerpc/ps3fb.h @@ -41,4 +41,16 @@ struct ps3fb_ioctl_res { __u32 num_frames; /* num of frame buffers */ }; +#ifdef __KERNEL__ + +#ifdef CONFIG_FB_PS3 +extern void ps3fb_flip_ctl(int on); +extern void ps3fb_cleanup(void); +#else +static inline void ps3fb_flip_ctl(int on) {} +static inline void ps3fb_cleanup(void) {} +#endif + +#endif /* __KERNEL__ */ + #endif /* _ASM_POWERPC_PS3FB_H_ */ diff --git a/trunk/include/asm-powerpc/ps3stor.h b/trunk/include/asm-powerpc/ps3stor.h deleted file mode 100644 index 6fcaf714fa50..000000000000 --- a/trunk/include/asm-powerpc/ps3stor.h +++ /dev/null @@ -1,71 +0,0 @@ -/* - * PS3 Storage Devices - * - * Copyright (C) 2007 Sony Computer Entertainment Inc. - * Copyright 2007 Sony Corp. - * - * 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; version 2 of the License. - * - * 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 Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#ifndef _ASM_POWERPC_PS3STOR_H_ -#define _ASM_POWERPC_PS3STOR_H_ - -#include - -#include - - -struct ps3_storage_region { - unsigned int id; - u64 start; - u64 size; -}; - -struct ps3_storage_device { - struct ps3_system_bus_device sbd; - - struct ps3_dma_region dma_region; - unsigned int irq; - u64 blk_size; - - u64 tag; - u64 lv1_status; - struct completion done; - - unsigned long bounce_size; - void *bounce_buf; - u64 bounce_lpar; - dma_addr_t bounce_dma; - - unsigned int num_regions; - unsigned long accessible_regions; - unsigned int region_idx; /* first accessible region */ - struct ps3_storage_region regions[0]; /* Must be last */ -}; - -static inline struct ps3_storage_device *to_ps3_storage_device(struct device *dev) -{ - return container_of(dev, struct ps3_storage_device, sbd.core); -} - -extern int ps3stor_setup(struct ps3_storage_device *dev, - irq_handler_t handler); -extern void ps3stor_teardown(struct ps3_storage_device *dev); -extern u64 ps3stor_read_write_sectors(struct ps3_storage_device *dev, u64 lpar, - u64 start_sector, u64 sectors, - int write); -extern u64 ps3stor_send_command(struct ps3_storage_device *dev, u64 cmd, - u64 arg1, u64 arg2, u64 arg3, u64 arg4); - -#endif /* _ASM_POWERPC_PS3STOR_H_ */ diff --git a/trunk/include/asm-powerpc/ptrace.h b/trunk/include/asm-powerpc/ptrace.h index 13fccc5a4119..4ad77a13f865 100644 --- a/trunk/include/asm-powerpc/ptrace.h +++ b/trunk/include/asm-powerpc/ptrace.h @@ -92,11 +92,6 @@ extern unsigned long profile_pc(struct pt_regs *regs); set_thread_flag(TIF_NOERROR); \ } while(0) -struct task_struct; -extern unsigned long ptrace_get_reg(struct task_struct *task, int regno); -extern int ptrace_put_reg(struct task_struct *task, int regno, - unsigned long data); - /* * We use the least-significant bit of the trap field to indicate * whether we have saved the full set of registers, or only a @@ -163,7 +158,9 @@ do { \ #define PT_NIP 32 #define PT_MSR 33 +#ifdef __KERNEL__ #define PT_ORIG_R3 34 +#endif #define PT_CTR 35 #define PT_LNK 36 #define PT_XER 37 @@ -172,12 +169,11 @@ do { \ #define PT_MQ 39 #else #define PT_SOFTE 39 -#endif #define PT_TRAP 40 #define PT_DAR 41 #define PT_DSISR 42 #define PT_RESULT 43 -#define PT_REGS_COUNT 44 +#endif #define PT_FPR0 48 /* each FP reg occupies 2 slots in this space */ @@ -233,17 +229,7 @@ do { \ #define PTRACE_GET_DEBUGREG 25 #define PTRACE_SET_DEBUGREG 26 -/* (new) PTRACE requests using the same numbers as x86 and the same - * argument ordering. Additionally, they support more registers too - */ -#define PTRACE_GETREGS 12 -#define PTRACE_SETREGS 13 -#define PTRACE_GETFPREGS 14 -#define PTRACE_SETFPREGS 15 -#define PTRACE_GETREGS64 22 -#define PTRACE_SETREGS64 23 - -/* (old) PTRACE requests with inverted arguments */ +/* Additional PTRACE requests implemented on PowerPC. */ #define PPC_PTRACE_GETREGS 0x99 /* Get GPRs 0 - 31 */ #define PPC_PTRACE_SETREGS 0x98 /* Set GPRs 0 - 31 */ #define PPC_PTRACE_GETFPREGS 0x97 /* Get FPRs 0 - 31 */ diff --git a/trunk/include/asm-powerpc/reg.h b/trunk/include/asm-powerpc/reg.h index 281011e953ec..749c7f953b58 100644 --- a/trunk/include/asm-powerpc/reg.h +++ b/trunk/include/asm-powerpc/reg.h @@ -453,8 +453,6 @@ #define SPRN_MMCRA 0x312 #define MMCRA_SIHV 0x10000000UL /* state of MSR HV when SIAR set */ #define MMCRA_SIPR 0x08000000UL /* state of MSR PR when SIAR set */ -#define MMCRA_SLOT 0x07000000UL /* SLOT bits (37-39) */ -#define MMCRA_SLOT_SHIFT 24 #define MMCRA_SAMPLE_ENABLE 0x00000001UL /* enable sampling */ #define POWER6_MMCRA_SIHV 0x0000040000000000ULL #define POWER6_MMCRA_SIPR 0x0000020000000000ULL diff --git a/trunk/include/asm-powerpc/spu.h b/trunk/include/asm-powerpc/spu.h index eedc828cef2d..31d5054be20f 100644 --- a/trunk/include/asm-powerpc/spu.h +++ b/trunk/include/asm-powerpc/spu.h @@ -106,14 +106,6 @@ struct spu_context; struct spu_runqueue; struct device_node; -enum spu_utilization_state { - SPU_UTIL_SYSTEM, - SPU_UTIL_USER, - SPU_UTIL_IOWAIT, - SPU_UTIL_IDLE, - SPU_UTIL_MAX -}; - struct spu { const char *name; unsigned long local_store_phys; @@ -164,21 +156,6 @@ struct spu { u64 shadow_int_mask_RW[3]; struct sys_device sysdev; - - struct { - /* protected by interrupt reentrancy */ - enum spu_utilization_state utilization_state; - unsigned long tstamp; /* time of last ctx switch */ - unsigned long times[SPU_UTIL_MAX]; - unsigned long long vol_ctx_switch; - unsigned long long invol_ctx_switch; - unsigned long long min_flt; - unsigned long long maj_flt; - unsigned long long hash_flt; - unsigned long long slb_flt; - unsigned long long class2_intr; - unsigned long long libassist; - } stats; }; struct spu *spu_alloc(void); @@ -471,7 +448,6 @@ struct spu_priv1 { #define MFC_STATE1_PROBLEM_STATE_MASK 0x08ull #define MFC_STATE1_RELOCATE_MASK 0x10ull #define MFC_STATE1_MASTER_RUN_CONTROL_MASK 0x20ull -#define MFC_STATE1_TABLE_SEARCH_MASK 0x40ull u64 mfc_lpid_RW; /* 0x008 */ u64 spu_idr_RW; /* 0x010 */ u64 mfc_vr_RO; /* 0x018 */ diff --git a/trunk/include/asm-powerpc/syscalls.h b/trunk/include/asm-powerpc/syscalls.h index b3ca41fc8bb1..c2fe79d4f90f 100644 --- a/trunk/include/asm-powerpc/syscalls.h +++ b/trunk/include/asm-powerpc/syscalls.h @@ -43,9 +43,16 @@ asmlinkage long ppc_newuname(struct new_utsname __user * name); asmlinkage long sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize); + +#ifndef __powerpc64__ +asmlinkage long sys_sigaltstack(const stack_t __user *uss, + stack_t __user *uoss, int r5, int r6, int r7, int r8, + struct pt_regs *regs); +#else /* __powerpc64__ */ asmlinkage long sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, unsigned long r5, unsigned long r6, unsigned long r7, unsigned long r8, struct pt_regs *regs); +#endif /* __powerpc64__ */ #endif /* __KERNEL__ */ #endif /* __ASM_POWERPC_SYSCALLS_H */ diff --git a/trunk/include/asm-powerpc/system.h b/trunk/include/asm-powerpc/system.h index 32aa42b748be..09621f611dbc 100644 --- a/trunk/include/asm-powerpc/system.h +++ b/trunk/include/asm-powerpc/system.h @@ -43,7 +43,7 @@ #ifdef CONFIG_SMP #define smp_mb() mb() #define smp_rmb() rmb() -#define smp_wmb() eieio() +#define smp_wmb() __asm__ __volatile__ ("eieio" : : : "memory") #define smp_read_barrier_depends() read_barrier_depends() #else #define smp_mb() barrier() @@ -559,7 +559,5 @@ static inline void create_function_call(unsigned long addr, void * func) extern void account_system_vtime(struct task_struct *); #endif -extern struct dentry *powerpc_debugfs_root; - #endif /* __KERNEL__ */ #endif /* _ASM_POWERPC_SYSTEM_H */ diff --git a/trunk/include/asm-powerpc/termbits.h b/trunk/include/asm-powerpc/termbits.h index 6698188ca550..5e79198f7d18 100644 --- a/trunk/include/asm-powerpc/termbits.h +++ b/trunk/include/asm-powerpc/termbits.h @@ -152,10 +152,6 @@ struct ktermios { #define B3000000 00034 #define B3500000 00035 #define B4000000 00036 -#define BOTHER 00037 - -#define CIBAUD 077600000 -#define IBSHIFT 16 /* Shift from CBAUD to CIBAUD */ #define CSIZE 00001400 #define CS5 00000000 diff --git a/trunk/include/asm-powerpc/thread_info.h b/trunk/include/asm-powerpc/thread_info.h index 9d9aeca8ad22..3f32ca8bfec9 100644 --- a/trunk/include/asm-powerpc/thread_info.h +++ b/trunk/include/asm-powerpc/thread_info.h @@ -113,8 +113,8 @@ static inline struct thread_info *current_thread_info(void) #define TIF_POLLING_NRFLAG 4 /* true if poll_idle() is polling TIF_NEED_RESCHED */ #define TIF_32BIT 5 /* 32 bit binary */ -#define TIF_PERFMON_WORK 6 /* work for pfm_handle_work() */ -#define TIF_PERFMON_CTXSW 7 /* perfmon needs ctxsw calls */ +#define TIF_RUNLATCH 6 /* Is the runlatch enabled? */ +#define TIF_ABI_PENDING 7 /* 32/64 bit switch needed */ #define TIF_SYSCALL_AUDIT 8 /* syscall auditing active */ #define TIF_SINGLESTEP 9 /* singlestepping active */ #define TIF_MEMDIE 10 @@ -123,8 +123,6 @@ static inline struct thread_info *current_thread_info(void) #define TIF_NOERROR 14 /* Force successful syscall return */ #define TIF_RESTORE_SIGMASK 15 /* Restore signal mask in do_signal */ #define TIF_FREEZE 16 /* Freezing for suspend */ -#define TIF_RUNLATCH 17 /* Is the runlatch enabled? */ -#define TIF_ABI_PENDING 18 /* 32/64 bit switch needed */ /* as above, but as bit values */ #define _TIF_SYSCALL_TRACE (1<addr; + unsigned long end = addr + area->size; BUG_ON(addr >= end); pgd = pgd_offset_k(addr); @@ -84,12 +84,7 @@ void unmap_kernel_range(unsigned long addr, unsigned long size) continue; vunmap_pud_range(pgd, addr, next); } while (pgd++, addr = next, addr != end); - flush_tlb_kernel_range(start, end); -} - -static void unmap_vm_area(struct vm_struct *area) -{ - unmap_kernel_range((unsigned long)area->addr, area->size); + flush_tlb_kernel_range((unsigned long) area->addr, end); } static int vmap_pte_range(pmd_t *pmd, unsigned long addr, diff --git a/trunk/net/ieee80211/softmac/ieee80211softmac_assoc.c b/trunk/net/ieee80211/softmac/ieee80211softmac_assoc.c index afb6c6698b27..cc8110bdd579 100644 --- a/trunk/net/ieee80211/softmac/ieee80211softmac_assoc.c +++ b/trunk/net/ieee80211/softmac/ieee80211softmac_assoc.c @@ -271,11 +271,8 @@ ieee80211softmac_assoc_work(struct work_struct *work) */ dprintk(KERN_INFO PFX "Associate: Scanning for networks first.\n"); ieee80211softmac_notify(mac->dev, IEEE80211SOFTMAC_EVENT_SCAN_FINISHED, ieee80211softmac_assoc_notify_scan, NULL); - if (ieee80211softmac_start_scan(mac)) { + if (ieee80211softmac_start_scan(mac)) dprintk(KERN_INFO PFX "Associate: failed to initiate scan. Is device up?\n"); - mac->associnfo.associating = 0; - mac->associnfo.associated = 0; - } goto out; } else { mac->associnfo.associating = 0;