aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/powerpc/phyp-assisted-dump.txt127
-rw-r--r--arch/powerpc/Kconfig11
-rw-r--r--arch/powerpc/configs/maple_defconfig131
-rw-r--r--arch/powerpc/kernel/asm-offsets.c4
-rw-r--r--arch/powerpc/kernel/btext.c3
-rw-r--r--arch/powerpc/kernel/crash.c3
-rw-r--r--arch/powerpc/kernel/crash_dump.c3
-rw-r--r--arch/powerpc/kernel/head_32.S17
-rw-r--r--arch/powerpc/kernel/machine_kexec.c3
-rw-r--r--arch/powerpc/kernel/ppc_ksyms.c2
-rw-r--r--arch/powerpc/kernel/process.c5
-rw-r--r--arch/powerpc/kernel/prom.c59
-rw-r--r--arch/powerpc/kernel/rtas.c2
-rw-r--r--arch/powerpc/kernel/setup-common.c11
-rw-r--r--arch/powerpc/kernel/setup_64.c2
-rw-r--r--arch/powerpc/kernel/sys_ppc32.c5
-rw-r--r--arch/powerpc/kernel/vdso.c3
-rw-r--r--arch/powerpc/mm/Makefile2
-rw-r--r--arch/powerpc/mm/hash_utils_64.c26
-rw-r--r--arch/powerpc/mm/init_32.c2
-rw-r--r--arch/powerpc/mm/init_64.c2
-rw-r--r--arch/powerpc/mm/mem.c2
-rw-r--r--arch/powerpc/mm/numa.c3
-rw-r--r--arch/powerpc/mm/ppc_mmu_32.c2
-rw-r--r--arch/powerpc/mm/stab.c4
-rw-r--r--arch/powerpc/platforms/8xx/m8xx_setup.c7
-rw-r--r--arch/powerpc/platforms/cell/iommu.c2
-rw-r--r--arch/powerpc/platforms/iseries/pci.c3
-rw-r--r--arch/powerpc/platforms/maple/pci.c47
-rw-r--r--arch/powerpc/platforms/maple/setup.c4
-rw-r--r--arch/powerpc/platforms/pasemi/dma_lib.c144
-rw-r--r--arch/powerpc/platforms/powermac/setup.c2
-rw-r--r--arch/powerpc/platforms/ps3/htab.c3
-rw-r--r--arch/powerpc/platforms/ps3/mm.c3
-rw-r--r--arch/powerpc/platforms/ps3/os-area.c3
-rw-r--r--arch/powerpc/platforms/pseries/Makefile1
-rw-r--r--arch/powerpc/platforms/pseries/lpar.c15
-rw-r--r--arch/powerpc/platforms/pseries/phyp_dump.c498
-rw-r--r--arch/powerpc/platforms/pseries/scanlog.c37
-rw-r--r--arch/powerpc/platforms/pseries/setup.c4
-rw-r--r--arch/powerpc/sysdev/dart_iommu.c2
-rw-r--r--arch/powerpc/sysdev/mpic.c32
-rw-r--r--arch/ppc/8xx_io/commproc.c2
-rw-r--r--arch/ppc/kernel/head.S17
-rw-r--r--arch/sparc64/Kconfig1
-rw-r--r--drivers/net/Makefile3
-rw-r--r--drivers/net/pasemi_mac.c324
-rw-r--r--drivers/net/pasemi_mac.h35
-rw-r--r--drivers/net/pasemi_mac_ethtool.c159
-rw-r--r--include/asm-powerpc/Kbuild2
-rw-r--r--include/asm-powerpc/abs_addr.h3
-rw-r--r--include/asm-powerpc/cputhreads.h2
-rw-r--r--include/asm-powerpc/lmb.h82
-rw-r--r--include/asm-powerpc/machdep.h2
-rw-r--r--include/asm-powerpc/pasemi_dma.h77
-rw-r--r--include/asm-powerpc/phyp_dump.h45
-rw-r--r--include/asm-powerpc/sparsemem.h1
-rw-r--r--include/asm-sparc64/lmb.h10
-rw-r--r--include/linux/lmb.h83
-rw-r--r--lib/Kconfig3
-rw-r--r--lib/Makefile2
-rw-r--r--lib/lmb.c (renamed from arch/powerpc/mm/lmb.c)141
62 files changed, 1867 insertions, 368 deletions
diff --git a/Documentation/powerpc/phyp-assisted-dump.txt b/Documentation/powerpc/phyp-assisted-dump.txt
new file mode 100644
index 000000000000..c4682b982a2e
--- /dev/null
+++ b/Documentation/powerpc/phyp-assisted-dump.txt
@@ -0,0 +1,127 @@
1
2 Hypervisor-Assisted Dump
3 ------------------------
4 November 2007
5
6The goal of hypervisor-assisted dump is to enable the dump of
7a crashed system, and to do so from a fully-reset system, and
8to minimize the total elapsed time until the system is back
9in production use.
10
11As compared to kdump or other strategies, hypervisor-assisted
12dump offers several strong, practical advantages:
13
14-- Unlike kdump, the system has been reset, and loaded
15 with a fresh copy of the kernel. In particular,
16 PCI and I/O devices have been reinitialized and are
17 in a clean, consistent state.
18-- As the dump is performed, the dumped memory becomes
19 immediately available to the system for normal use.
20-- After the dump is completed, no further reboots are
21 required; the system will be fully usable, and running
22 in it's normal, production mode on it normal kernel.
23
24The above can only be accomplished by coordination with,
25and assistance from the hypervisor. The procedure is
26as follows:
27
28-- When a system crashes, the hypervisor will save
29 the low 256MB of RAM to a previously registered
30 save region. It will also save system state, system
31 registers, and hardware PTE's.
32
33-- After the low 256MB area has been saved, the
34 hypervisor will reset PCI and other hardware state.
35 It will *not* clear RAM. It will then launch the
36 bootloader, as normal.
37
38-- The freshly booted kernel will notice that there
39 is a new node (ibm,dump-kernel) in the device tree,
40 indicating that there is crash data available from
41 a previous boot. It will boot into only 256MB of RAM,
42 reserving the rest of system memory.
43
44-- Userspace tools will parse /sys/kernel/release_region
45 and read /proc/vmcore to obtain the contents of memory,
46 which holds the previous crashed kernel. The userspace
47 tools may copy this info to disk, or network, nas, san,
48 iscsi, etc. as desired.
49
50 For Example: the values in /sys/kernel/release-region
51 would look something like this (address-range pairs).
52 CPU:0x177fee000-0x10000: HPTE:0x177ffe020-0x1000: /
53 DUMP:0x177fff020-0x10000000, 0x10000000-0x16F1D370A
54
55-- As the userspace tools complete saving a portion of
56 dump, they echo an offset and size to
57 /sys/kernel/release_region to release the reserved
58 memory back to general use.
59
60 An example of this is:
61 "echo 0x40000000 0x10000000 > /sys/kernel/release_region"
62 which will release 256MB at the 1GB boundary.
63
64Please note that the hypervisor-assisted dump feature
65is only available on Power6-based systems with recent
66firmware versions.
67
68Implementation details:
69----------------------
70
71During boot, a check is made to see if firmware supports
72this feature on this particular machine. If it does, then
73we check to see if a active dump is waiting for us. If yes
74then everything but 256 MB of RAM is reserved during early
75boot. This area is released once we collect a dump from user
76land scripts that are run. If there is dump data, then
77the /sys/kernel/release_region file is created, and
78the reserved memory is held.
79
80If there is no waiting dump data, then only the highest
81256MB of the ram is reserved as a scratch area. This area
82is *not* released: this region will be kept permanently
83reserved, so that it can act as a receptacle for a copy
84of the low 256MB in the case a crash does occur. See,
85however, "open issues" below, as to whether
86such a reserved region is really needed.
87
88Currently the dump will be copied from /proc/vmcore to a
89a new file upon user intervention. The starting address
90to be read and the range for each data point in provided
91in /sys/kernel/release_region.
92
93The tools to examine the dump will be same as the ones
94used for kdump.
95
96General notes:
97--------------
98Security: please note that there are potential security issues
99with any sort of dump mechanism. In particular, plaintext
100(unencrypted) data, and possibly passwords, may be present in
101the dump data. Userspace tools must take adequate precautions to
102preserve security.
103
104Open issues/ToDo:
105------------
106 o The various code paths that tell the hypervisor that a crash
107 occurred, vs. it simply being a normal reboot, should be
108 reviewed, and possibly clarified/fixed.
109
110 o Instead of using /sys/kernel, should there be a /sys/dump
111 instead? There is a dump_subsys being created by the s390 code,
112 perhaps the pseries code should use a similar layout as well.
113
114 o Is reserving a 256MB region really required? The goal of
115 reserving a 256MB scratch area is to make sure that no
116 important crash data is clobbered when the hypervisor
117 save low mem to the scratch area. But, if one could assure
118 that nothing important is located in some 256MB area, then
119 it would not need to be reserved. Something that can be
120 improved in subsequent versions.
121
122 o Still working the kdump team to integrate this with kdump,
123 some work remains but this would not affect the current
124 patches.
125
126 o Still need to write a shell script, to copy the dump away.
127 Currently I am parsing it manually.
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 1189d8d6170d..3651355b6ad7 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -91,6 +91,7 @@ config PPC
91 select HAVE_OPROFILE 91 select HAVE_OPROFILE
92 select HAVE_KPROBES 92 select HAVE_KPROBES
93 select HAVE_KRETPROBES 93 select HAVE_KRETPROBES
94 select HAVE_LMB
94 95
95config EARLY_PRINTK 96config EARLY_PRINTK
96 bool 97 bool
@@ -307,6 +308,16 @@ config CRASH_DUMP
307 308
308 Don't change this unless you know what you are doing. 309 Don't change this unless you know what you are doing.
309 310
311config PHYP_DUMP
312 bool "Hypervisor-assisted dump (EXPERIMENTAL)"
313 depends on PPC_PSERIES && EXPERIMENTAL
314 help
315 Hypervisor-assisted dump is meant to be a kdump replacement
316 offering robustness and speed not possible without system
317 hypervisor assistence.
318
319 If unsure, say "N"
320
310config PPCBUG_NVRAM 321config PPCBUG_NVRAM
311 bool "Enable reading PPCBUG NVRAM during boot" if PPLUS || LOPEC 322 bool "Enable reading PPCBUG NVRAM during boot" if PPLUS || LOPEC
312 default y if PPC_PREP 323 default y if PPC_PREP
diff --git a/arch/powerpc/configs/maple_defconfig b/arch/powerpc/configs/maple_defconfig
index 8b810d056440..7a166a39d92d 100644
--- a/arch/powerpc/configs/maple_defconfig
+++ b/arch/powerpc/configs/maple_defconfig
@@ -333,7 +333,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
333CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" 333CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
334CONFIG_STANDALONE=y 334CONFIG_STANDALONE=y
335CONFIG_PREVENT_FIRMWARE_BUILD=y 335CONFIG_PREVENT_FIRMWARE_BUILD=y
336# CONFIG_FW_LOADER is not set 336CONFIG_FW_LOADER=y
337# CONFIG_DEBUG_DRIVER is not set 337# CONFIG_DEBUG_DRIVER is not set
338# CONFIG_DEBUG_DEVRES is not set 338# CONFIG_DEBUG_DEVRES is not set
339# CONFIG_SYS_HYPERVISOR is not set 339# CONFIG_SYS_HYPERVISOR is not set
@@ -374,6 +374,7 @@ CONFIG_BLK_DEV_IDEDISK=y
374CONFIG_BLK_DEV_IDECD=y 374CONFIG_BLK_DEV_IDECD=y
375# CONFIG_BLK_DEV_IDETAPE is not set 375# CONFIG_BLK_DEV_IDETAPE is not set
376# CONFIG_BLK_DEV_IDEFLOPPY is not set 376# CONFIG_BLK_DEV_IDEFLOPPY is not set
377# CONFIG_BLK_DEV_IDESCSI is not set
377CONFIG_IDE_TASK_IOCTL=y 378CONFIG_IDE_TASK_IOCTL=y
378CONFIG_IDE_PROC_FS=y 379CONFIG_IDE_PROC_FS=y
379 380
@@ -427,10 +428,129 @@ CONFIG_IDE_ARCH_OBSOLETE_INIT=y
427# SCSI device support 428# SCSI device support
428# 429#
429# CONFIG_RAID_ATTRS is not set 430# CONFIG_RAID_ATTRS is not set
430# CONFIG_SCSI is not set 431CONFIG_SCSI=y
431# CONFIG_SCSI_DMA is not set 432CONFIG_SCSI_DMA=y
433# CONFIG_SCSI_TGT is not set
432# CONFIG_SCSI_NETLINK is not set 434# CONFIG_SCSI_NETLINK is not set
433# CONFIG_ATA is not set 435# CONFIG_SCSI_PROC_FS is not set
436
437#
438# SCSI support type (disk, tape, CD-ROM)
439#
440CONFIG_BLK_DEV_SD=y
441# CONFIG_CHR_DEV_ST is not set
442# CONFIG_CHR_DEV_OSST is not set
443# CONFIG_BLK_DEV_SR is not set
444CONFIG_CHR_DEV_SG=y
445# CONFIG_CHR_DEV_SCH is not set
446
447#
448# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
449#
450# CONFIG_SCSI_MULTI_LUN is not set
451# CONFIG_SCSI_CONSTANTS is not set
452# CONFIG_SCSI_LOGGING is not set
453# CONFIG_SCSI_SCAN_ASYNC is not set
454CONFIG_SCSI_WAIT_SCAN=m
455
456#
457# SCSI Transports
458#
459# CONFIG_SCSI_SPI_ATTRS is not set
460# CONFIG_SCSI_FC_ATTRS is not set
461# CONFIG_SCSI_ISCSI_ATTRS is not set
462# CONFIG_SCSI_SAS_LIBSAS is not set
463# CONFIG_SCSI_SRP_ATTRS is not set
464CONFIG_SCSI_LOWLEVEL=y
465# CONFIG_ISCSI_TCP is not set
466# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
467# CONFIG_SCSI_3W_9XXX is not set
468# CONFIG_SCSI_ACARD is not set
469# CONFIG_SCSI_AACRAID is not set
470# CONFIG_SCSI_AIC7XXX is not set
471# CONFIG_SCSI_AIC7XXX_OLD is not set
472# CONFIG_SCSI_AIC79XX is not set
473# CONFIG_SCSI_AIC94XX is not set
474# CONFIG_SCSI_ARCMSR is not set
475# CONFIG_MEGARAID_NEWGEN is not set
476# CONFIG_MEGARAID_LEGACY is not set
477# CONFIG_MEGARAID_SAS is not set
478# CONFIG_SCSI_HPTIOP is not set
479# CONFIG_SCSI_DMX3191D is not set
480# CONFIG_SCSI_EATA is not set
481# CONFIG_SCSI_FUTURE_DOMAIN is not set
482# CONFIG_SCSI_GDTH is not set
483# CONFIG_SCSI_IPS is not set
484# CONFIG_SCSI_INITIO is not set
485# CONFIG_SCSI_INIA100 is not set
486# CONFIG_SCSI_STEX is not set
487# CONFIG_SCSI_SYM53C8XX_2 is not set
488CONFIG_SCSI_IPR=y
489CONFIG_SCSI_IPR_TRACE=y
490CONFIG_SCSI_IPR_DUMP=y
491# CONFIG_SCSI_QLOGIC_1280 is not set
492# CONFIG_SCSI_QLA_FC is not set
493# CONFIG_SCSI_QLA_ISCSI is not set
494# CONFIG_SCSI_LPFC is not set
495# CONFIG_SCSI_DC395x is not set
496# CONFIG_SCSI_DC390T is not set
497# CONFIG_SCSI_DEBUG is not set
498# CONFIG_SCSI_SRP is not set
499CONFIG_ATA=y
500CONFIG_ATA_NONSTANDARD=y
501# CONFIG_SATA_AHCI is not set
502# CONFIG_SATA_SVW is not set
503# CONFIG_ATA_PIIX is not set
504# CONFIG_SATA_MV is not set
505# CONFIG_SATA_NV is not set
506# CONFIG_PDC_ADMA is not set
507# CONFIG_SATA_QSTOR is not set
508# CONFIG_SATA_PROMISE is not set
509# CONFIG_SATA_SX4 is not set
510# CONFIG_SATA_SIL is not set
511# CONFIG_SATA_SIL24 is not set
512# CONFIG_SATA_SIS is not set
513# CONFIG_SATA_ULI is not set
514# CONFIG_SATA_VIA is not set
515# CONFIG_SATA_VITESSE is not set
516# CONFIG_SATA_INIC162X is not set
517# CONFIG_PATA_ALI is not set
518# CONFIG_PATA_AMD is not set
519# CONFIG_PATA_ARTOP is not set
520# CONFIG_PATA_ATIIXP is not set
521# CONFIG_PATA_CMD640_PCI is not set
522# CONFIG_PATA_CMD64X is not set
523# CONFIG_PATA_CS5520 is not set
524# CONFIG_PATA_CS5530 is not set
525# CONFIG_PATA_CYPRESS is not set
526# CONFIG_PATA_EFAR is not set
527# CONFIG_ATA_GENERIC is not set
528# CONFIG_PATA_HPT366 is not set
529# CONFIG_PATA_HPT37X is not set
530# CONFIG_PATA_HPT3X2N is not set
531# CONFIG_PATA_HPT3X3 is not set
532# CONFIG_PATA_IT821X is not set
533# CONFIG_PATA_IT8213 is not set
534# CONFIG_PATA_JMICRON is not set
535# CONFIG_PATA_TRIFLEX is not set
536# CONFIG_PATA_MARVELL is not set
537# CONFIG_PATA_MPIIX is not set
538# CONFIG_PATA_OLDPIIX is not set
539# CONFIG_PATA_NETCELL is not set
540# CONFIG_PATA_NS87410 is not set
541# CONFIG_PATA_NS87415 is not set
542# CONFIG_PATA_OPTI is not set
543# CONFIG_PATA_OPTIDMA is not set
544# CONFIG_PATA_PDC_OLD is not set
545# CONFIG_PATA_RADISYS is not set
546# CONFIG_PATA_RZ1000 is not set
547# CONFIG_PATA_SC1200 is not set
548# CONFIG_PATA_SERVERWORKS is not set
549# CONFIG_PATA_PDC2027X is not set
550# CONFIG_PATA_SIL680 is not set
551# CONFIG_PATA_SIS is not set
552# CONFIG_PATA_VIA is not set
553# CONFIG_PATA_WINBOND is not set
434# CONFIG_MD is not set 554# CONFIG_MD is not set
435# CONFIG_FUSION is not set 555# CONFIG_FUSION is not set
436 556
@@ -536,6 +656,7 @@ CONFIG_USB_PEGASUS=y
536# CONFIG_HIPPI is not set 656# CONFIG_HIPPI is not set
537# CONFIG_PPP is not set 657# CONFIG_PPP is not set
538# CONFIG_SLIP is not set 658# CONFIG_SLIP is not set
659# CONFIG_NET_FC is not set
539# CONFIG_SHAPER is not set 660# CONFIG_SHAPER is not set
540# CONFIG_NETCONSOLE is not set 661# CONFIG_NETCONSOLE is not set
541# CONFIG_NETPOLL is not set 662# CONFIG_NETPOLL is not set
@@ -783,12 +904,14 @@ CONFIG_USB_UHCI_HCD=y
783# 904#
784# may also be needed; see USB_STORAGE Help for more information 905# may also be needed; see USB_STORAGE Help for more information
785# 906#
907# CONFIG_USB_STORAGE is not set
786# CONFIG_USB_LIBUSUAL is not set 908# CONFIG_USB_LIBUSUAL is not set
787 909
788# 910#
789# USB Imaging devices 911# USB Imaging devices
790# 912#
791# CONFIG_USB_MDC800 is not set 913# CONFIG_USB_MDC800 is not set
914# CONFIG_USB_MICROTEK is not set
792CONFIG_USB_MON=y 915CONFIG_USB_MON=y
793 916
794# 917#
diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c
index 4b749c416464..e932b43bd82f 100644
--- a/arch/powerpc/kernel/asm-offsets.c
+++ b/arch/powerpc/kernel/asm-offsets.c
@@ -26,8 +26,6 @@
26#ifdef CONFIG_PPC64 26#ifdef CONFIG_PPC64
27#include <linux/time.h> 27#include <linux/time.h>
28#include <linux/hardirq.h> 28#include <linux/hardirq.h>
29#else
30#include <linux/ptrace.h>
31#endif 29#endif
32 30
33#include <asm/io.h> 31#include <asm/io.h>
@@ -60,7 +58,6 @@ int main(void)
60 DEFINE(AUDITCONTEXT, offsetof(struct task_struct, audit_context)); 58 DEFINE(AUDITCONTEXT, offsetof(struct task_struct, audit_context));
61#else 59#else
62 DEFINE(THREAD_INFO, offsetof(struct task_struct, stack)); 60 DEFINE(THREAD_INFO, offsetof(struct task_struct, stack));
63 DEFINE(PTRACE, offsetof(struct task_struct, ptrace));
64#endif /* CONFIG_PPC64 */ 61#endif /* CONFIG_PPC64 */
65 62
66 DEFINE(KSP, offsetof(struct thread_struct, ksp)); 63 DEFINE(KSP, offsetof(struct thread_struct, ksp));
@@ -80,7 +77,6 @@ int main(void)
80 DEFINE(PGDIR, offsetof(struct thread_struct, pgdir)); 77 DEFINE(PGDIR, offsetof(struct thread_struct, pgdir));
81#if defined(CONFIG_4xx) || defined(CONFIG_BOOKE) 78#if defined(CONFIG_4xx) || defined(CONFIG_BOOKE)
82 DEFINE(THREAD_DBCR0, offsetof(struct thread_struct, dbcr0)); 79 DEFINE(THREAD_DBCR0, offsetof(struct thread_struct, dbcr0));
83 DEFINE(PT_PTRACED, PT_PTRACED);
84#endif 80#endif
85#ifdef CONFIG_SPE 81#ifdef CONFIG_SPE
86 DEFINE(THREAD_EVR0, offsetof(struct thread_struct, evr[0])); 82 DEFINE(THREAD_EVR0, offsetof(struct thread_struct, evr[0]));
diff --git a/arch/powerpc/kernel/btext.c b/arch/powerpc/kernel/btext.c
index 80e2eef05b2e..9f9377745490 100644
--- a/arch/powerpc/kernel/btext.c
+++ b/arch/powerpc/kernel/btext.c
@@ -7,6 +7,7 @@
7#include <linux/string.h> 7#include <linux/string.h>
8#include <linux/init.h> 8#include <linux/init.h>
9#include <linux/module.h> 9#include <linux/module.h>
10#include <linux/lmb.h>
10 11
11#include <asm/sections.h> 12#include <asm/sections.h>
12#include <asm/prom.h> 13#include <asm/prom.h>
@@ -15,7 +16,7 @@
15#include <asm/mmu.h> 16#include <asm/mmu.h>
16#include <asm/pgtable.h> 17#include <asm/pgtable.h>
17#include <asm/io.h> 18#include <asm/io.h>
18#include <asm/lmb.h> 19#include <asm/prom.h>
19#include <asm/processor.h> 20#include <asm/processor.h>
20#include <asm/udbg.h> 21#include <asm/udbg.h>
21 22
diff --git a/arch/powerpc/kernel/crash.c b/arch/powerpc/kernel/crash.c
index 571132ed12c1..eae401de3f76 100644
--- a/arch/powerpc/kernel/crash.c
+++ b/arch/powerpc/kernel/crash.c
@@ -24,12 +24,13 @@
24#include <linux/init.h> 24#include <linux/init.h>
25#include <linux/irq.h> 25#include <linux/irq.h>
26#include <linux/types.h> 26#include <linux/types.h>
27#include <linux/lmb.h>
27 28
28#include <asm/processor.h> 29#include <asm/processor.h>
29#include <asm/machdep.h> 30#include <asm/machdep.h>
30#include <asm/kexec.h> 31#include <asm/kexec.h>
31#include <asm/kdump.h> 32#include <asm/kdump.h>
32#include <asm/lmb.h> 33#include <asm/prom.h>
33#include <asm/firmware.h> 34#include <asm/firmware.h>
34#include <asm/smp.h> 35#include <asm/smp.h>
35#include <asm/system.h> 36#include <asm/system.h>
diff --git a/arch/powerpc/kernel/crash_dump.c b/arch/powerpc/kernel/crash_dump.c
index 29ff77c468ac..9ee3c5278db0 100644
--- a/arch/powerpc/kernel/crash_dump.c
+++ b/arch/powerpc/kernel/crash_dump.c
@@ -13,8 +13,9 @@
13 13
14#include <linux/crash_dump.h> 14#include <linux/crash_dump.h>
15#include <linux/bootmem.h> 15#include <linux/bootmem.h>
16#include <linux/lmb.h>
16#include <asm/kdump.h> 17#include <asm/kdump.h>
17#include <asm/lmb.h> 18#include <asm/prom.h>
18#include <asm/firmware.h> 19#include <asm/firmware.h>
19#include <asm/uaccess.h> 20#include <asm/uaccess.h>
20 21
diff --git a/arch/powerpc/kernel/head_32.S b/arch/powerpc/kernel/head_32.S
index 0f4fac512020..c16d1354b19d 100644
--- a/arch/powerpc/kernel/head_32.S
+++ b/arch/powerpc/kernel/head_32.S
@@ -763,23 +763,6 @@ load_up_altivec:
763 b fast_exception_return 763 b fast_exception_return
764 764
765/* 765/*
766 * AltiVec unavailable trap from kernel - print a message, but let
767 * the task use AltiVec in the kernel until it returns to user mode.
768 */
769KernelAltiVec:
770 lwz r3,_MSR(r1)
771 oris r3,r3,MSR_VEC@h
772 stw r3,_MSR(r1) /* enable use of AltiVec after return */
773 lis r3,87f@h
774 ori r3,r3,87f@l
775 mr r4,r2 /* current */
776 lwz r5,_NIP(r1)
777 bl printk
778 b ret_from_except
77987: .string "AltiVec used in kernel (task=%p, pc=%x) \n"
780 .align 4,0
781
782/*
783 * giveup_altivec(tsk) 766 * giveup_altivec(tsk)
784 * Disable AltiVec for the task given as the argument, 767 * Disable AltiVec for the task given as the argument,
785 * and save the AltiVec registers in its thread_struct. 768 * and save the AltiVec registers in its thread_struct.
diff --git a/arch/powerpc/kernel/machine_kexec.c b/arch/powerpc/kernel/machine_kexec.c
index c0c8e8c3ced9..2d202f274e73 100644
--- a/arch/powerpc/kernel/machine_kexec.c
+++ b/arch/powerpc/kernel/machine_kexec.c
@@ -12,8 +12,9 @@
12#include <linux/kexec.h> 12#include <linux/kexec.h>
13#include <linux/reboot.h> 13#include <linux/reboot.h>
14#include <linux/threads.h> 14#include <linux/threads.h>
15#include <linux/lmb.h>
15#include <asm/machdep.h> 16#include <asm/machdep.h>
16#include <asm/lmb.h> 17#include <asm/prom.h>
17 18
18void machine_crash_shutdown(struct pt_regs *regs) 19void machine_crash_shutdown(struct pt_regs *regs)
19{ 20{
diff --git a/arch/powerpc/kernel/ppc_ksyms.c b/arch/powerpc/kernel/ppc_ksyms.c
index 9c98424277a8..a722ede726db 100644
--- a/arch/powerpc/kernel/ppc_ksyms.c
+++ b/arch/powerpc/kernel/ppc_ksyms.c
@@ -58,7 +58,6 @@ extern void program_check_exception(struct pt_regs *regs);
58extern void single_step_exception(struct pt_regs *regs); 58extern void single_step_exception(struct pt_regs *regs);
59extern int sys_sigreturn(struct pt_regs *regs); 59extern int sys_sigreturn(struct pt_regs *regs);
60 60
61EXPORT_SYMBOL(empty_zero_page);
62EXPORT_SYMBOL(clear_pages); 61EXPORT_SYMBOL(clear_pages);
63EXPORT_SYMBOL(copy_page); 62EXPORT_SYMBOL(copy_page);
64EXPORT_SYMBOL(ISA_DMA_THRESHOLD); 63EXPORT_SYMBOL(ISA_DMA_THRESHOLD);
@@ -192,3 +191,4 @@ EXPORT_SYMBOL(intercept_table);
192EXPORT_SYMBOL(__mtdcr); 191EXPORT_SYMBOL(__mtdcr);
193EXPORT_SYMBOL(__mfdcr); 192EXPORT_SYMBOL(__mfdcr);
194#endif 193#endif
194EXPORT_SYMBOL(empty_zero_page);
diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c
index 59311ec0d422..8d506d86e2df 100644
--- a/arch/powerpc/kernel/process.c
+++ b/arch/powerpc/kernel/process.c
@@ -868,11 +868,6 @@ int sys_execve(unsigned long a0, unsigned long a1, unsigned long a2,
868 flush_spe_to_thread(current); 868 flush_spe_to_thread(current);
869 error = do_execve(filename, (char __user * __user *) a1, 869 error = do_execve(filename, (char __user * __user *) a1,
870 (char __user * __user *) a2, regs); 870 (char __user * __user *) a2, regs);
871 if (error == 0) {
872 task_lock(current);
873 current->ptrace &= ~PT_DTRACE;
874 task_unlock(current);
875 }
876 putname(filename); 871 putname(filename);
877out: 872out:
878 return error; 873 return error;
diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c
index eac97f48b9b8..9330920265f3 100644
--- a/arch/powerpc/kernel/prom.c
+++ b/arch/powerpc/kernel/prom.c
@@ -31,10 +31,10 @@
31#include <linux/kexec.h> 31#include <linux/kexec.h>
32#include <linux/debugfs.h> 32#include <linux/debugfs.h>
33#include <linux/irq.h> 33#include <linux/irq.h>
34#include <linux/lmb.h>
34 35
35#include <asm/prom.h> 36#include <asm/prom.h>
36#include <asm/rtas.h> 37#include <asm/rtas.h>
37#include <asm/lmb.h>
38#include <asm/page.h> 38#include <asm/page.h>
39#include <asm/processor.h> 39#include <asm/processor.h>
40#include <asm/irq.h> 40#include <asm/irq.h>
@@ -51,6 +51,7 @@
51#include <asm/machdep.h> 51#include <asm/machdep.h>
52#include <asm/pSeries_reconfig.h> 52#include <asm/pSeries_reconfig.h>
53#include <asm/pci-bridge.h> 53#include <asm/pci-bridge.h>
54#include <asm/phyp_dump.h>
54#include <asm/kexec.h> 55#include <asm/kexec.h>
55 56
56#ifdef DEBUG 57#ifdef DEBUG
@@ -1040,6 +1041,56 @@ static void __init early_reserve_mem(void)
1040#endif 1041#endif
1041} 1042}
1042 1043
1044#ifdef CONFIG_PHYP_DUMP
1045/**
1046 * phyp_dump_reserve_mem() - reserve all not-yet-dumped mmemory
1047 *
1048 * This routine may reserve memory regions in the kernel only
1049 * if the system is supported and a dump was taken in last
1050 * boot instance or if the hardware is supported and the
1051 * scratch area needs to be setup. In other instances it returns
1052 * without reserving anything. The memory in case of dump being
1053 * active is freed when the dump is collected (by userland tools).
1054 */
1055static void __init phyp_dump_reserve_mem(void)
1056{
1057 unsigned long base, size;
1058 if (!phyp_dump_info->phyp_dump_configured) {
1059 printk(KERN_ERR "Phyp-dump not supported on this hardware\n");
1060 return;
1061 }
1062
1063 if (!phyp_dump_info->phyp_dump_at_boot) {
1064 printk(KERN_INFO "Phyp-dump disabled at boot time\n");
1065 return;
1066 }
1067
1068 if (phyp_dump_info->phyp_dump_is_active) {
1069 /* Reserve *everything* above RMR.Area freed by userland tools*/
1070 base = PHYP_DUMP_RMR_END;
1071 size = lmb_end_of_DRAM() - base;
1072
1073 /* XXX crashed_ram_end is wrong, since it may be beyond
1074 * the memory_limit, it will need to be adjusted. */
1075 lmb_reserve(base, size);
1076
1077 phyp_dump_info->init_reserve_start = base;
1078 phyp_dump_info->init_reserve_size = size;
1079 } else {
1080 size = phyp_dump_info->cpu_state_size +
1081 phyp_dump_info->hpte_region_size +
1082 PHYP_DUMP_RMR_END;
1083 base = lmb_end_of_DRAM() - size;
1084 lmb_reserve(base, size);
1085 phyp_dump_info->init_reserve_start = base;
1086 phyp_dump_info->init_reserve_size = size;
1087 }
1088}
1089#else
1090static inline void __init phyp_dump_reserve_mem(void) {}
1091#endif /* CONFIG_PHYP_DUMP && CONFIG_PPC_RTAS */
1092
1093
1043void __init early_init_devtree(void *params) 1094void __init early_init_devtree(void *params)
1044{ 1095{
1045 DBG(" -> early_init_devtree(%p)\n", params); 1096 DBG(" -> early_init_devtree(%p)\n", params);
@@ -1052,6 +1103,11 @@ void __init early_init_devtree(void *params)
1052 of_scan_flat_dt(early_init_dt_scan_rtas, NULL); 1103 of_scan_flat_dt(early_init_dt_scan_rtas, NULL);
1053#endif 1104#endif
1054 1105
1106#ifdef CONFIG_PHYP_DUMP
1107 /* scan tree to see if dump occured during last boot */
1108 of_scan_flat_dt(early_init_dt_scan_phyp_dump, NULL);
1109#endif
1110
1055 /* Retrieve various informations from the /chosen node of the 1111 /* Retrieve various informations from the /chosen node of the
1056 * device-tree, including the platform type, initrd location and 1112 * device-tree, including the platform type, initrd location and
1057 * size, TCE reserve, and more ... 1113 * size, TCE reserve, and more ...
@@ -1072,6 +1128,7 @@ void __init early_init_devtree(void *params)
1072 reserve_kdump_trampoline(); 1128 reserve_kdump_trampoline();
1073 reserve_crashkernel(); 1129 reserve_crashkernel();
1074 early_reserve_mem(); 1130 early_reserve_mem();
1131 phyp_dump_reserve_mem();
1075 1132
1076 lmb_enforce_memory_limit(memory_limit); 1133 lmb_enforce_memory_limit(memory_limit);
1077 lmb_analyze(); 1134 lmb_analyze();
diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c
index 52e95c2158c0..e2e78d967f31 100644
--- a/arch/powerpc/kernel/rtas.c
+++ b/arch/powerpc/kernel/rtas.c
@@ -22,6 +22,7 @@
22#include <linux/smp.h> 22#include <linux/smp.h>
23#include <linux/completion.h> 23#include <linux/completion.h>
24#include <linux/cpumask.h> 24#include <linux/cpumask.h>
25#include <linux/lmb.h>
25 26
26#include <asm/prom.h> 27#include <asm/prom.h>
27#include <asm/rtas.h> 28#include <asm/rtas.h>
@@ -34,7 +35,6 @@
34#include <asm/system.h> 35#include <asm/system.h>
35#include <asm/delay.h> 36#include <asm/delay.h>
36#include <asm/uaccess.h> 37#include <asm/uaccess.h>
37#include <asm/lmb.h>
38#include <asm/udbg.h> 38#include <asm/udbg.h>
39#include <asm/syscalls.h> 39#include <asm/syscalls.h>
40#include <asm/smp.h> 40#include <asm/smp.h>
diff --git a/arch/powerpc/kernel/setup-common.c b/arch/powerpc/kernel/setup-common.c
index 6adb5a1e98bb..db540eab09f4 100644
--- a/arch/powerpc/kernel/setup-common.c
+++ b/arch/powerpc/kernel/setup-common.c
@@ -34,6 +34,7 @@
34#include <linux/serial_8250.h> 34#include <linux/serial_8250.h>
35#include <linux/debugfs.h> 35#include <linux/debugfs.h>
36#include <linux/percpu.h> 36#include <linux/percpu.h>
37#include <linux/lmb.h>
37#include <asm/io.h> 38#include <asm/io.h>
38#include <asm/prom.h> 39#include <asm/prom.h>
39#include <asm/processor.h> 40#include <asm/processor.h>
@@ -56,7 +57,6 @@
56#include <asm/cache.h> 57#include <asm/cache.h>
57#include <asm/page.h> 58#include <asm/page.h>
58#include <asm/mmu.h> 59#include <asm/mmu.h>
59#include <asm/lmb.h>
60#include <asm/xmon.h> 60#include <asm/xmon.h>
61#include <asm/cputhreads.h> 61#include <asm/cputhreads.h>
62 62
@@ -167,6 +167,8 @@ static int show_cpuinfo(struct seq_file *m, void *v)
167 unsigned short min; 167 unsigned short min;
168 168
169 if (cpu_id == NR_CPUS) { 169 if (cpu_id == NR_CPUS) {
170 struct device_node *root;
171 const char *model = NULL;
170#if defined(CONFIG_SMP) && defined(CONFIG_PPC32) 172#if defined(CONFIG_SMP) && defined(CONFIG_PPC32)
171 unsigned long bogosum = 0; 173 unsigned long bogosum = 0;
172 int i; 174 int i;
@@ -178,6 +180,13 @@ static int show_cpuinfo(struct seq_file *m, void *v)
178 seq_printf(m, "timebase\t: %lu\n", ppc_tb_freq); 180 seq_printf(m, "timebase\t: %lu\n", ppc_tb_freq);
179 if (ppc_md.name) 181 if (ppc_md.name)
180 seq_printf(m, "platform\t: %s\n", ppc_md.name); 182 seq_printf(m, "platform\t: %s\n", ppc_md.name);
183 root = of_find_node_by_path("/");
184 if (root)
185 model = of_get_property(root, "model", NULL);
186 if (model)
187 seq_printf(m, "model\t\t: %s\n", model);
188 of_node_put(root);
189
181 if (ppc_md.show_cpuinfo != NULL) 190 if (ppc_md.show_cpuinfo != NULL)
182 ppc_md.show_cpuinfo(m); 191 ppc_md.show_cpuinfo(m);
183 192
diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c
index 3b1529c103ef..2c2d8315193c 100644
--- a/arch/powerpc/kernel/setup_64.c
+++ b/arch/powerpc/kernel/setup_64.c
@@ -33,6 +33,7 @@
33#include <linux/serial_8250.h> 33#include <linux/serial_8250.h>
34#include <linux/bootmem.h> 34#include <linux/bootmem.h>
35#include <linux/pci.h> 35#include <linux/pci.h>
36#include <linux/lmb.h>
36#include <asm/io.h> 37#include <asm/io.h>
37#include <asm/kdump.h> 38#include <asm/kdump.h>
38#include <asm/prom.h> 39#include <asm/prom.h>
@@ -55,7 +56,6 @@
55#include <asm/cache.h> 56#include <asm/cache.h>
56#include <asm/page.h> 57#include <asm/page.h>
57#include <asm/mmu.h> 58#include <asm/mmu.h>
58#include <asm/lmb.h>
59#include <asm/firmware.h> 59#include <asm/firmware.h>
60#include <asm/xmon.h> 60#include <asm/xmon.h>
61#include <asm/udbg.h> 61#include <asm/udbg.h>
diff --git a/arch/powerpc/kernel/sys_ppc32.c b/arch/powerpc/kernel/sys_ppc32.c
index 4a4f5c6b560b..9c3371e6958e 100644
--- a/arch/powerpc/kernel/sys_ppc32.c
+++ b/arch/powerpc/kernel/sys_ppc32.c
@@ -368,11 +368,6 @@ long compat_sys_execve(unsigned long a0, unsigned long a1, unsigned long a2,
368 368
369 error = compat_do_execve(filename, compat_ptr(a1), compat_ptr(a2), regs); 369 error = compat_do_execve(filename, compat_ptr(a1), compat_ptr(a2), regs);
370 370
371 if (error == 0) {
372 task_lock(current);
373 current->ptrace &= ~PT_DTRACE;
374 task_unlock(current);
375 }
376 putname(filename); 371 putname(filename);
377 372
378out: 373out:
diff --git a/arch/powerpc/kernel/vdso.c b/arch/powerpc/kernel/vdso.c
index d3437c4c4a6f..c21a626af676 100644
--- a/arch/powerpc/kernel/vdso.c
+++ b/arch/powerpc/kernel/vdso.c
@@ -21,13 +21,14 @@
21#include <linux/elf.h> 21#include <linux/elf.h>
22#include <linux/security.h> 22#include <linux/security.h>
23#include <linux/bootmem.h> 23#include <linux/bootmem.h>
24#include <linux/lmb.h>
24 25
25#include <asm/pgtable.h> 26#include <asm/pgtable.h>
26#include <asm/system.h> 27#include <asm/system.h>
27#include <asm/processor.h> 28#include <asm/processor.h>
28#include <asm/mmu.h> 29#include <asm/mmu.h>
29#include <asm/mmu_context.h> 30#include <asm/mmu_context.h>
30#include <asm/lmb.h> 31#include <asm/prom.h>
31#include <asm/machdep.h> 32#include <asm/machdep.h>
32#include <asm/cputable.h> 33#include <asm/cputable.h>
33#include <asm/sections.h> 34#include <asm/sections.h>
diff --git a/arch/powerpc/mm/Makefile b/arch/powerpc/mm/Makefile
index 41649a5d3602..1c00e0196f6c 100644
--- a/arch/powerpc/mm/Makefile
+++ b/arch/powerpc/mm/Makefile
@@ -6,7 +6,7 @@ ifeq ($(CONFIG_PPC64),y)
6EXTRA_CFLAGS += -mno-minimal-toc 6EXTRA_CFLAGS += -mno-minimal-toc
7endif 7endif
8 8
9obj-y := fault.o mem.o lmb.o \ 9obj-y := fault.o mem.o \
10 init_$(CONFIG_WORD_SIZE).o \ 10 init_$(CONFIG_WORD_SIZE).o \
11 pgtable_$(CONFIG_WORD_SIZE).o \ 11 pgtable_$(CONFIG_WORD_SIZE).o \
12 mmu_context_$(CONFIG_WORD_SIZE).o 12 mmu_context_$(CONFIG_WORD_SIZE).o
diff --git a/arch/powerpc/mm/hash_utils_64.c b/arch/powerpc/mm/hash_utils_64.c
index a83dfa3cf40c..c2e5f61788b0 100644
--- a/arch/powerpc/mm/hash_utils_64.c
+++ b/arch/powerpc/mm/hash_utils_64.c
@@ -31,6 +31,7 @@
31#include <linux/cache.h> 31#include <linux/cache.h>
32#include <linux/init.h> 32#include <linux/init.h>
33#include <linux/signal.h> 33#include <linux/signal.h>
34#include <linux/lmb.h>
34 35
35#include <asm/processor.h> 36#include <asm/processor.h>
36#include <asm/pgtable.h> 37#include <asm/pgtable.h>
@@ -41,7 +42,7 @@
41#include <asm/system.h> 42#include <asm/system.h>
42#include <asm/uaccess.h> 43#include <asm/uaccess.h>
43#include <asm/machdep.h> 44#include <asm/machdep.h>
44#include <asm/lmb.h> 45#include <asm/prom.h>
45#include <asm/abs_addr.h> 46#include <asm/abs_addr.h>
46#include <asm/tlbflush.h> 47#include <asm/tlbflush.h>
47#include <asm/io.h> 48#include <asm/io.h>
@@ -191,6 +192,24 @@ int htab_bolt_mapping(unsigned long vstart, unsigned long vend,
191 return ret < 0 ? ret : 0; 192 return ret < 0 ? ret : 0;
192} 193}
193 194
195static void htab_remove_mapping(unsigned long vstart, unsigned long vend,
196 int psize, int ssize)
197{
198 unsigned long vaddr;
199 unsigned int step, shift;
200
201 shift = mmu_psize_defs[psize].shift;
202 step = 1 << shift;
203
204 if (!ppc_md.hpte_removebolted) {
205 printk("Sub-arch doesn't implement hpte_removebolted\n");
206 return;
207 }
208
209 for (vaddr = vstart; vaddr < vend; vaddr += step)
210 ppc_md.hpte_removebolted(vaddr, psize, ssize);
211}
212
194static int __init htab_dt_scan_seg_sizes(unsigned long node, 213static int __init htab_dt_scan_seg_sizes(unsigned long node,
195 const char *uname, int depth, 214 const char *uname, int depth,
196 void *data) 215 void *data)
@@ -434,6 +453,11 @@ void create_section_mapping(unsigned long start, unsigned long end)
434 _PAGE_ACCESSED | _PAGE_DIRTY | _PAGE_COHERENT | PP_RWXX, 453 _PAGE_ACCESSED | _PAGE_DIRTY | _PAGE_COHERENT | PP_RWXX,
435 mmu_linear_psize, mmu_kernel_ssize)); 454 mmu_linear_psize, mmu_kernel_ssize));
436} 455}
456
457void remove_section_mapping(unsigned long start, unsigned long end)
458{
459 htab_remove_mapping(start, end, mmu_linear_psize, mmu_kernel_ssize);
460}
437#endif /* CONFIG_MEMORY_HOTPLUG */ 461#endif /* CONFIG_MEMORY_HOTPLUG */
438 462
439static inline void make_bl(unsigned int *insn_addr, void *func) 463static inline void make_bl(unsigned int *insn_addr, void *func)
diff --git a/arch/powerpc/mm/init_32.c b/arch/powerpc/mm/init_32.c
index 977cb1ee5e72..59a725b8ece9 100644
--- a/arch/powerpc/mm/init_32.c
+++ b/arch/powerpc/mm/init_32.c
@@ -30,6 +30,7 @@
30#include <linux/highmem.h> 30#include <linux/highmem.h>
31#include <linux/initrd.h> 31#include <linux/initrd.h>
32#include <linux/pagemap.h> 32#include <linux/pagemap.h>
33#include <linux/lmb.h>
33 34
34#include <asm/pgalloc.h> 35#include <asm/pgalloc.h>
35#include <asm/prom.h> 36#include <asm/prom.h>
@@ -41,7 +42,6 @@
41#include <asm/machdep.h> 42#include <asm/machdep.h>
42#include <asm/btext.h> 43#include <asm/btext.h>
43#include <asm/tlb.h> 44#include <asm/tlb.h>
44#include <asm/lmb.h>
45#include <asm/sections.h> 45#include <asm/sections.h>
46 46
47#include "mmu_decl.h" 47#include "mmu_decl.h"
diff --git a/arch/powerpc/mm/init_64.c b/arch/powerpc/mm/init_64.c
index c0f5cff77035..abeb0eb79313 100644
--- a/arch/powerpc/mm/init_64.c
+++ b/arch/powerpc/mm/init_64.c
@@ -38,11 +38,11 @@
38#include <linux/nodemask.h> 38#include <linux/nodemask.h>
39#include <linux/module.h> 39#include <linux/module.h>
40#include <linux/poison.h> 40#include <linux/poison.h>
41#include <linux/lmb.h>
41 42
42#include <asm/pgalloc.h> 43#include <asm/pgalloc.h>
43#include <asm/page.h> 44#include <asm/page.h>
44#include <asm/prom.h> 45#include <asm/prom.h>
45#include <asm/lmb.h>
46#include <asm/rtas.h> 46#include <asm/rtas.h>
47#include <asm/io.h> 47#include <asm/io.h>
48#include <asm/mmu_context.h> 48#include <asm/mmu_context.h>
diff --git a/arch/powerpc/mm/mem.c b/arch/powerpc/mm/mem.c
index be5c506779a7..60c019cdc69f 100644
--- a/arch/powerpc/mm/mem.c
+++ b/arch/powerpc/mm/mem.c
@@ -31,6 +31,7 @@
31#include <linux/initrd.h> 31#include <linux/initrd.h>
32#include <linux/pagemap.h> 32#include <linux/pagemap.h>
33#include <linux/suspend.h> 33#include <linux/suspend.h>
34#include <linux/lmb.h>
34 35
35#include <asm/pgalloc.h> 36#include <asm/pgalloc.h>
36#include <asm/prom.h> 37#include <asm/prom.h>
@@ -42,7 +43,6 @@
42#include <asm/machdep.h> 43#include <asm/machdep.h>
43#include <asm/btext.h> 44#include <asm/btext.h>
44#include <asm/tlb.h> 45#include <asm/tlb.h>
45#include <asm/lmb.h>
46#include <asm/sections.h> 46#include <asm/sections.h>
47#include <asm/vdso.h> 47#include <asm/vdso.h>
48 48
diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c
index a300d254aac6..1efd631211ef 100644
--- a/arch/powerpc/mm/numa.c
+++ b/arch/powerpc/mm/numa.c
@@ -17,8 +17,9 @@
17#include <linux/nodemask.h> 17#include <linux/nodemask.h>
18#include <linux/cpu.h> 18#include <linux/cpu.h>
19#include <linux/notifier.h> 19#include <linux/notifier.h>
20#include <linux/lmb.h>
20#include <asm/sparsemem.h> 21#include <asm/sparsemem.h>
21#include <asm/lmb.h> 22#include <asm/prom.h>
22#include <asm/system.h> 23#include <asm/system.h>
23#include <asm/smp.h> 24#include <asm/smp.h>
24 25
diff --git a/arch/powerpc/mm/ppc_mmu_32.c b/arch/powerpc/mm/ppc_mmu_32.c
index 5c45d474cfcc..72de3c79210a 100644
--- a/arch/powerpc/mm/ppc_mmu_32.c
+++ b/arch/powerpc/mm/ppc_mmu_32.c
@@ -26,11 +26,11 @@
26#include <linux/mm.h> 26#include <linux/mm.h>
27#include <linux/init.h> 27#include <linux/init.h>
28#include <linux/highmem.h> 28#include <linux/highmem.h>
29#include <linux/lmb.h>
29 30
30#include <asm/prom.h> 31#include <asm/prom.h>
31#include <asm/mmu.h> 32#include <asm/mmu.h>
32#include <asm/machdep.h> 33#include <asm/machdep.h>
33#include <asm/lmb.h>
34 34
35#include "mmu_decl.h" 35#include "mmu_decl.h"
36 36
diff --git a/arch/powerpc/mm/stab.c b/arch/powerpc/mm/stab.c
index 50448d5de9d2..efbbd13d93e5 100644
--- a/arch/powerpc/mm/stab.c
+++ b/arch/powerpc/mm/stab.c
@@ -12,12 +12,14 @@
12 * 2 of the License, or (at your option) any later version. 12 * 2 of the License, or (at your option) any later version.
13 */ 13 */
14 14
15#include <linux/lmb.h>
16
15#include <asm/pgtable.h> 17#include <asm/pgtable.h>
16#include <asm/mmu.h> 18#include <asm/mmu.h>
17#include <asm/mmu_context.h> 19#include <asm/mmu_context.h>
18#include <asm/paca.h> 20#include <asm/paca.h>
19#include <asm/cputable.h> 21#include <asm/cputable.h>
20#include <asm/lmb.h> 22#include <asm/prom.h>
21#include <asm/abs_addr.h> 23#include <asm/abs_addr.h>
22#include <asm/firmware.h> 24#include <asm/firmware.h>
23#include <asm/iseries/hv_call.h> 25#include <asm/iseries/hv_call.h>
diff --git a/arch/powerpc/platforms/8xx/m8xx_setup.c b/arch/powerpc/platforms/8xx/m8xx_setup.c
index 184f998d1be2..0d9f75c74f8c 100644
--- a/arch/powerpc/platforms/8xx/m8xx_setup.c
+++ b/arch/powerpc/platforms/8xx/m8xx_setup.c
@@ -111,17 +111,12 @@ void __init mpc8xx_calibrate_decr(void)
111 111
112 /* Processor frequency is MHz. 112 /* Processor frequency is MHz.
113 */ 113 */
114 ppc_tb_freq = 50000000;
115 if (!get_freq("bus-frequency", &ppc_tb_freq)) {
116 printk(KERN_ERR "WARNING: Estimating decrementer frequency "
117 "(not found)\n");
118 }
119 ppc_tb_freq /= 16;
120 ppc_proc_freq = 50000000; 114 ppc_proc_freq = 50000000;
121 if (!get_freq("clock-frequency", &ppc_proc_freq)) 115 if (!get_freq("clock-frequency", &ppc_proc_freq))
122 printk(KERN_ERR "WARNING: Estimating processor frequency " 116 printk(KERN_ERR "WARNING: Estimating processor frequency "
123 "(not found)\n"); 117 "(not found)\n");
124 118
119 ppc_tb_freq = ppc_proc_freq / 16;
125 printk("Decrementer Frequency = 0x%lx\n", ppc_tb_freq); 120 printk("Decrementer Frequency = 0x%lx\n", ppc_tb_freq);
126 121
127 /* Perform some more timer/timebase initialization. This used 122 /* Perform some more timer/timebase initialization. This used
diff --git a/arch/powerpc/platforms/cell/iommu.c b/arch/powerpc/platforms/cell/iommu.c
index d75ccded7f10..49fe641d4345 100644
--- a/arch/powerpc/platforms/cell/iommu.c
+++ b/arch/powerpc/platforms/cell/iommu.c
@@ -28,13 +28,13 @@
28#include <linux/notifier.h> 28#include <linux/notifier.h>
29#include <linux/of.h> 29#include <linux/of.h>
30#include <linux/of_platform.h> 30#include <linux/of_platform.h>
31#include <linux/lmb.h>
31 32
32#include <asm/prom.h> 33#include <asm/prom.h>
33#include <asm/iommu.h> 34#include <asm/iommu.h>
34#include <asm/machdep.h> 35#include <asm/machdep.h>
35#include <asm/pci-bridge.h> 36#include <asm/pci-bridge.h>
36#include <asm/udbg.h> 37#include <asm/udbg.h>
37#include <asm/lmb.h>
38#include <asm/firmware.h> 38#include <asm/firmware.h>
39#include <asm/cell-regs.h> 39#include <asm/cell-regs.h>
40 40
diff --git a/arch/powerpc/platforms/iseries/pci.c b/arch/powerpc/platforms/iseries/pci.c
index cc562e4c2f32..02a634faedbe 100644
--- a/arch/powerpc/platforms/iseries/pci.c
+++ b/arch/powerpc/platforms/iseries/pci.c
@@ -23,6 +23,7 @@
23 23
24#undef DEBUG 24#undef DEBUG
25 25
26#include <linux/jiffies.h>
26#include <linux/kernel.h> 27#include <linux/kernel.h>
27#include <linux/list.h> 28#include <linux/list.h>
28#include <linux/string.h> 29#include <linux/string.h>
@@ -586,7 +587,7 @@ static inline struct device_node *xlate_iomm_address(
586 static unsigned long last_jiffies; 587 static unsigned long last_jiffies;
587 static int num_printed; 588 static int num_printed;
588 589
589 if ((jiffies - last_jiffies) > 60 * HZ) { 590 if (time_after(jiffies, last_jiffies + 60 * HZ)) {
590 last_jiffies = jiffies; 591 last_jiffies = jiffies;
591 num_printed = 0; 592 num_printed = 0;
592 } 593 }
diff --git a/arch/powerpc/platforms/maple/pci.c b/arch/powerpc/platforms/maple/pci.c
index 3ffa0ac170ee..301855263b81 100644
--- a/arch/powerpc/platforms/maple/pci.c
+++ b/arch/powerpc/platforms/maple/pci.c
@@ -592,50 +592,3 @@ int maple_pci_get_legacy_ide_irq(struct pci_dev *pdev, int channel)
592 } 592 }
593 return irq; 593 return irq;
594} 594}
595
596/* XXX: To remove once all firmwares are ok */
597static void fixup_maple_ide(struct pci_dev* dev)
598{
599 if (!machine_is(maple))
600 return;
601
602#if 0 /* Enable this to enable IDE port 0 */
603 {
604 u8 v;
605
606 pci_read_config_byte(dev, 0x40, &v);
607 v |= 2;
608 pci_write_config_byte(dev, 0x40, v);
609 }
610#endif
611#if 0 /* fix bus master base */
612 pci_write_config_dword(dev, 0x20, 0xcc01);
613 printk("old ide resource: %lx -> %lx \n",
614 dev->resource[4].start, dev->resource[4].end);
615 dev->resource[4].start = 0xcc00;
616 dev->resource[4].end = 0xcc10;
617#endif
618#if 0 /* Enable this to fixup IDE sense/polarity of irqs in IO-APICs */
619 {
620 struct pci_dev *apicdev;
621 u32 v;
622
623 apicdev = pci_get_slot (dev->bus, PCI_DEVFN(5,0));
624 if (apicdev == NULL)
625 printk("IDE Fixup IRQ: Can't find IO-APIC !\n");
626 else {
627 pci_write_config_byte(apicdev, 0xf2, 0x10 + 2*14);
628 pci_read_config_dword(apicdev, 0xf4, &v);
629 v &= ~0x00000022;
630 pci_write_config_dword(apicdev, 0xf4, v);
631 pci_write_config_byte(apicdev, 0xf2, 0x10 + 2*15);
632 pci_read_config_dword(apicdev, 0xf4, &v);
633 v &= ~0x00000022;
634 pci_write_config_dword(apicdev, 0xf4, v);
635 pci_dev_put(apicdev);
636 }
637 }
638#endif
639}
640DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8111_IDE,
641 fixup_maple_ide);
diff --git a/arch/powerpc/platforms/maple/setup.c b/arch/powerpc/platforms/maple/setup.c
index 3ce2d73b4177..364714757cf1 100644
--- a/arch/powerpc/platforms/maple/setup.c
+++ b/arch/powerpc/platforms/maple/setup.c
@@ -43,6 +43,7 @@
43#include <linux/smp.h> 43#include <linux/smp.h>
44#include <linux/bitops.h> 44#include <linux/bitops.h>
45#include <linux/of_device.h> 45#include <linux/of_device.h>
46#include <linux/lmb.h>
46 47
47#include <asm/processor.h> 48#include <asm/processor.h>
48#include <asm/sections.h> 49#include <asm/sections.h>
@@ -57,7 +58,6 @@
57#include <asm/dma.h> 58#include <asm/dma.h>
58#include <asm/cputable.h> 59#include <asm/cputable.h>
59#include <asm/time.h> 60#include <asm/time.h>
60#include <asm/lmb.h>
61#include <asm/mpic.h> 61#include <asm/mpic.h>
62#include <asm/rtas.h> 62#include <asm/rtas.h>
63#include <asm/udbg.h> 63#include <asm/udbg.h>
@@ -319,7 +319,7 @@ static int __init maple_probe(void)
319 return 1; 319 return 1;
320} 320}
321 321
322define_machine(maple_md) { 322define_machine(maple) {
323 .name = "Maple", 323 .name = "Maple",
324 .probe = maple_probe, 324 .probe = maple_probe,
325 .setup_arch = maple_setup_arch, 325 .setup_arch = maple_setup_arch,
diff --git a/arch/powerpc/platforms/pasemi/dma_lib.c b/arch/powerpc/platforms/pasemi/dma_lib.c
index c529d8dff395..217af321b0ca 100644
--- a/arch/powerpc/platforms/pasemi/dma_lib.c
+++ b/arch/powerpc/platforms/pasemi/dma_lib.c
@@ -17,6 +17,7 @@
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */ 18 */
19 19
20#include <linux/kernel.h>
20#include <linux/init.h> 21#include <linux/init.h>
21#include <linux/module.h> 22#include <linux/module.h>
22#include <linux/pci.h> 23#include <linux/pci.h>
@@ -26,6 +27,8 @@
26 27
27#define MAX_TXCH 64 28#define MAX_TXCH 64
28#define MAX_RXCH 64 29#define MAX_RXCH 64
30#define MAX_FLAGS 64
31#define MAX_FUN 8
29 32
30static struct pasdma_status *dma_status; 33static struct pasdma_status *dma_status;
31 34
@@ -43,6 +46,8 @@ static struct pci_dev *dma_pdev;
43 46
44static DECLARE_BITMAP(txch_free, MAX_TXCH); 47static DECLARE_BITMAP(txch_free, MAX_TXCH);
45static DECLARE_BITMAP(rxch_free, MAX_RXCH); 48static DECLARE_BITMAP(rxch_free, MAX_RXCH);
49static DECLARE_BITMAP(flags_free, MAX_FLAGS);
50static DECLARE_BITMAP(fun_free, MAX_FUN);
46 51
47/* pasemi_read_iob_reg - read IOB register 52/* pasemi_read_iob_reg - read IOB register
48 * @reg: Register to read (offset into PCI CFG space) 53 * @reg: Register to read (offset into PCI CFG space)
@@ -373,6 +378,106 @@ void pasemi_dma_free_buf(struct pasemi_dmachan *chan, int size,
373} 378}
374EXPORT_SYMBOL(pasemi_dma_free_buf); 379EXPORT_SYMBOL(pasemi_dma_free_buf);
375 380
381/* pasemi_dma_alloc_flag - Allocate a flag (event) for channel syncronization
382 *
383 * Allocates a flag for use with channel syncronization (event descriptors).
384 * Returns allocated flag (0-63), < 0 on error.
385 */
386int pasemi_dma_alloc_flag(void)
387{
388 int bit;
389
390retry:
391 bit = find_next_bit(flags_free, MAX_FLAGS, 0);
392 if (bit >= MAX_FLAGS)
393 return -ENOSPC;
394 if (!test_and_clear_bit(bit, flags_free))
395 goto retry;
396
397 return bit;
398}
399EXPORT_SYMBOL(pasemi_dma_alloc_flag);
400
401
402/* pasemi_dma_free_flag - Deallocates a flag (event)
403 * @flag: Flag number to deallocate
404 *
405 * Frees up a flag so it can be reused for other purposes.
406 */
407void pasemi_dma_free_flag(int flag)
408{
409 BUG_ON(test_bit(flag, flags_free));
410 BUG_ON(flag >= MAX_FLAGS);
411 set_bit(flag, flags_free);
412}
413EXPORT_SYMBOL(pasemi_dma_free_flag);
414
415
416/* pasemi_dma_set_flag - Sets a flag (event) to 1
417 * @flag: Flag number to set active
418 *
419 * Sets the flag provided to 1.
420 */
421void pasemi_dma_set_flag(int flag)
422{
423 BUG_ON(flag >= MAX_FLAGS);
424 if (flag < 32)
425 pasemi_write_dma_reg(PAS_DMA_TXF_SFLG0, 1 << flag);
426 else
427 pasemi_write_dma_reg(PAS_DMA_TXF_SFLG1, 1 << flag);
428}
429EXPORT_SYMBOL(pasemi_dma_set_flag);
430
431/* pasemi_dma_clear_flag - Sets a flag (event) to 0
432 * @flag: Flag number to set inactive
433 *
434 * Sets the flag provided to 0.
435 */
436void pasemi_dma_clear_flag(int flag)
437{
438 BUG_ON(flag >= MAX_FLAGS);
439 if (flag < 32)
440 pasemi_write_dma_reg(PAS_DMA_TXF_CFLG0, 1 << flag);
441 else
442 pasemi_write_dma_reg(PAS_DMA_TXF_CFLG1, 1 << flag);
443}
444EXPORT_SYMBOL(pasemi_dma_clear_flag);
445
446/* pasemi_dma_alloc_fun - Allocate a function engine
447 *
448 * Allocates a function engine to use for crypto/checksum offload
449 * Returns allocated engine (0-8), < 0 on error.
450 */
451int pasemi_dma_alloc_fun(void)
452{
453 int bit;
454
455retry:
456 bit = find_next_bit(fun_free, MAX_FLAGS, 0);
457 if (bit >= MAX_FLAGS)
458 return -ENOSPC;
459 if (!test_and_clear_bit(bit, fun_free))
460 goto retry;
461
462 return bit;
463}
464EXPORT_SYMBOL(pasemi_dma_alloc_fun);
465
466
467/* pasemi_dma_free_fun - Deallocates a function engine
468 * @flag: Engine number to deallocate
469 *
470 * Frees up a function engine so it can be used for other purposes.
471 */
472void pasemi_dma_free_fun(int fun)
473{
474 BUG_ON(test_bit(fun, fun_free));
475 BUG_ON(fun >= MAX_FLAGS);
476 set_bit(fun, fun_free);
477}
478EXPORT_SYMBOL(pasemi_dma_free_fun);
479
480
376static void *map_onedev(struct pci_dev *p, int index) 481static void *map_onedev(struct pci_dev *p, int index)
377{ 482{
378 struct device_node *dn; 483 struct device_node *dn;
@@ -410,6 +515,7 @@ int pasemi_dma_init(void)
410 struct resource res; 515 struct resource res;
411 struct device_node *dn; 516 struct device_node *dn;
412 int i, intf, err = 0; 517 int i, intf, err = 0;
518 unsigned long timeout;
413 u32 tmp; 519 u32 tmp;
414 520
415 if (!machine_is(pasemi)) 521 if (!machine_is(pasemi))
@@ -478,6 +584,44 @@ int pasemi_dma_init(void)
478 for (i = 0; i < MAX_RXCH; i++) 584 for (i = 0; i < MAX_RXCH; i++)
479 __set_bit(i, rxch_free); 585 __set_bit(i, rxch_free);
480 586
587 timeout = jiffies + HZ;
588 pasemi_write_dma_reg(PAS_DMA_COM_RXCMD, 0);
589 while (pasemi_read_dma_reg(PAS_DMA_COM_RXSTA) & 1) {
590 if (time_after(jiffies, timeout)) {
591 pr_warning("Warning: Could not disable RX section\n");
592 break;
593 }
594 }
595
596 timeout = jiffies + HZ;
597 pasemi_write_dma_reg(PAS_DMA_COM_TXCMD, 0);
598 while (pasemi_read_dma_reg(PAS_DMA_COM_TXSTA) & 1) {
599 if (time_after(jiffies, timeout)) {
600 pr_warning("Warning: Could not disable TX section\n");
601 break;
602 }
603 }
604
605 /* setup resource allocations for the different DMA sections */
606 tmp = pasemi_read_dma_reg(PAS_DMA_COM_CFG);
607 pasemi_write_dma_reg(PAS_DMA_COM_CFG, tmp | 0x18000000);
608
609 /* enable tx section */
610 pasemi_write_dma_reg(PAS_DMA_COM_TXCMD, PAS_DMA_COM_TXCMD_EN);
611
612 /* enable rx section */
613 pasemi_write_dma_reg(PAS_DMA_COM_RXCMD, PAS_DMA_COM_RXCMD_EN);
614
615 for (i = 0; i < MAX_FLAGS; i++)
616 __set_bit(i, flags_free);
617
618 for (i = 0; i < MAX_FUN; i++)
619 __set_bit(i, fun_free);
620
621 /* clear all status flags */
622 pasemi_write_dma_reg(PAS_DMA_TXF_CFLG0, 0xffffffff);
623 pasemi_write_dma_reg(PAS_DMA_TXF_CFLG1, 0xffffffff);
624
481 printk(KERN_INFO "PA Semi PWRficient DMA library initialized " 625 printk(KERN_INFO "PA Semi PWRficient DMA library initialized "
482 "(%d tx, %d rx channels)\n", num_txch, num_rxch); 626 "(%d tx, %d rx channels)\n", num_txch, num_rxch);
483 627
diff --git a/arch/powerpc/platforms/powermac/setup.c b/arch/powerpc/platforms/powermac/setup.c
index 36ff1b6b7fac..59404baf911f 100644
--- a/arch/powerpc/platforms/powermac/setup.c
+++ b/arch/powerpc/platforms/powermac/setup.c
@@ -53,6 +53,7 @@
53#include <linux/suspend.h> 53#include <linux/suspend.h>
54#include <linux/of_device.h> 54#include <linux/of_device.h>
55#include <linux/of_platform.h> 55#include <linux/of_platform.h>
56#include <linux/lmb.h>
56 57
57#include <asm/reg.h> 58#include <asm/reg.h>
58#include <asm/sections.h> 59#include <asm/sections.h>
@@ -74,7 +75,6 @@
74#include <asm/iommu.h> 75#include <asm/iommu.h>
75#include <asm/smu.h> 76#include <asm/smu.h>
76#include <asm/pmc.h> 77#include <asm/pmc.h>
77#include <asm/lmb.h>
78#include <asm/udbg.h> 78#include <asm/udbg.h>
79 79
80#include "pmac.h" 80#include "pmac.h"
diff --git a/arch/powerpc/platforms/ps3/htab.c b/arch/powerpc/platforms/ps3/htab.c
index 7382f195c4f8..1cf901fa9031 100644
--- a/arch/powerpc/platforms/ps3/htab.c
+++ b/arch/powerpc/platforms/ps3/htab.c
@@ -19,9 +19,10 @@
19 */ 19 */
20 20
21#include <linux/kernel.h> 21#include <linux/kernel.h>
22#include <linux/lmb.h>
22 23
23#include <asm/machdep.h> 24#include <asm/machdep.h>
24#include <asm/lmb.h> 25#include <asm/prom.h>
25#include <asm/udbg.h> 26#include <asm/udbg.h>
26#include <asm/lv1call.h> 27#include <asm/lv1call.h>
27#include <asm/ps3fb.h> 28#include <asm/ps3fb.h>
diff --git a/arch/powerpc/platforms/ps3/mm.c b/arch/powerpc/platforms/ps3/mm.c
index 68900476c842..5b3fb2b321ab 100644
--- a/arch/powerpc/platforms/ps3/mm.c
+++ b/arch/powerpc/platforms/ps3/mm.c
@@ -21,9 +21,10 @@
21#include <linux/kernel.h> 21#include <linux/kernel.h>
22#include <linux/module.h> 22#include <linux/module.h>
23#include <linux/memory_hotplug.h> 23#include <linux/memory_hotplug.h>
24#include <linux/lmb.h>
24 25
25#include <asm/firmware.h> 26#include <asm/firmware.h>
26#include <asm/lmb.h> 27#include <asm/prom.h>
27#include <asm/udbg.h> 28#include <asm/udbg.h>
28#include <asm/lv1call.h> 29#include <asm/lv1call.h>
29 30
diff --git a/arch/powerpc/platforms/ps3/os-area.c b/arch/powerpc/platforms/ps3/os-area.c
index b9ea09d9d2fb..c73379ec9141 100644
--- a/arch/powerpc/platforms/ps3/os-area.c
+++ b/arch/powerpc/platforms/ps3/os-area.c
@@ -24,8 +24,9 @@
24#include <linux/fs.h> 24#include <linux/fs.h>
25#include <linux/syscalls.h> 25#include <linux/syscalls.h>
26#include <linux/ctype.h> 26#include <linux/ctype.h>
27#include <linux/lmb.h>
27 28
28#include <asm/lmb.h> 29#include <asm/prom.h>
29 30
30#include "platform.h" 31#include "platform.h"
31 32
diff --git a/arch/powerpc/platforms/pseries/Makefile b/arch/powerpc/platforms/pseries/Makefile
index 992ba6753cf2..bdae04bb7a01 100644
--- a/arch/powerpc/platforms/pseries/Makefile
+++ b/arch/powerpc/platforms/pseries/Makefile
@@ -18,3 +18,4 @@ obj-$(CONFIG_HOTPLUG_CPU) += hotplug-cpu.o
18obj-$(CONFIG_HVC_CONSOLE) += hvconsole.o 18obj-$(CONFIG_HVC_CONSOLE) += hvconsole.o
19obj-$(CONFIG_HVCS) += hvcserver.o 19obj-$(CONFIG_HVCS) += hvcserver.o
20obj-$(CONFIG_HCALL_STATS) += hvCall_inst.o 20obj-$(CONFIG_HCALL_STATS) += hvCall_inst.o
21obj-$(CONFIG_PHYP_DUMP) += phyp_dump.o
diff --git a/arch/powerpc/platforms/pseries/lpar.c b/arch/powerpc/platforms/pseries/lpar.c
index 9a455d46379d..233d9be25f49 100644
--- a/arch/powerpc/platforms/pseries/lpar.c
+++ b/arch/powerpc/platforms/pseries/lpar.c
@@ -520,6 +520,20 @@ static void pSeries_lpar_hpte_invalidate(unsigned long slot, unsigned long va,
520 BUG_ON(lpar_rc != H_SUCCESS); 520 BUG_ON(lpar_rc != H_SUCCESS);
521} 521}
522 522
523static void pSeries_lpar_hpte_removebolted(unsigned long ea,
524 int psize, int ssize)
525{
526 unsigned long slot, vsid, va;
527
528 vsid = get_kernel_vsid(ea, ssize);
529 va = hpt_va(ea, vsid, ssize);
530
531 slot = pSeries_lpar_hpte_find(va, psize, ssize);
532 BUG_ON(slot == -1);
533
534 pSeries_lpar_hpte_invalidate(slot, va, psize, ssize, 0);
535}
536
523/* Flag bits for H_BULK_REMOVE */ 537/* Flag bits for H_BULK_REMOVE */
524#define HBR_REQUEST 0x4000000000000000UL 538#define HBR_REQUEST 0x4000000000000000UL
525#define HBR_RESPONSE 0x8000000000000000UL 539#define HBR_RESPONSE 0x8000000000000000UL
@@ -597,6 +611,7 @@ void __init hpte_init_lpar(void)
597 ppc_md.hpte_updateboltedpp = pSeries_lpar_hpte_updateboltedpp; 611 ppc_md.hpte_updateboltedpp = pSeries_lpar_hpte_updateboltedpp;
598 ppc_md.hpte_insert = pSeries_lpar_hpte_insert; 612 ppc_md.hpte_insert = pSeries_lpar_hpte_insert;
599 ppc_md.hpte_remove = pSeries_lpar_hpte_remove; 613 ppc_md.hpte_remove = pSeries_lpar_hpte_remove;
614 ppc_md.hpte_removebolted = pSeries_lpar_hpte_removebolted;
600 ppc_md.flush_hash_range = pSeries_lpar_flush_hash_range; 615 ppc_md.flush_hash_range = pSeries_lpar_flush_hash_range;
601 ppc_md.hpte_clear_all = pSeries_lpar_hptab_clear; 616 ppc_md.hpte_clear_all = pSeries_lpar_hptab_clear;
602} 617}
diff --git a/arch/powerpc/platforms/pseries/phyp_dump.c b/arch/powerpc/platforms/pseries/phyp_dump.c
new file mode 100644
index 000000000000..7ddd10526cea
--- /dev/null
+++ b/arch/powerpc/platforms/pseries/phyp_dump.c
@@ -0,0 +1,498 @@
1/*
2 * Hypervisor-assisted dump
3 *
4 * Linas Vepstas, Manish Ahuja 2008
5 * Copyright 2008 IBM Corp.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version
10 * 2 of the License, or (at your option) any later version.
11 *
12 */
13
14#include <linux/init.h>
15#include <linux/kobject.h>
16#include <linux/mm.h>
17#include <linux/of.h>
18#include <linux/pfn.h>
19#include <linux/swap.h>
20#include <linux/sysfs.h>
21
22#include <asm/page.h>
23#include <asm/phyp_dump.h>
24#include <asm/machdep.h>
25#include <asm/prom.h>
26#include <asm/rtas.h>
27
28/* Variables, used to communicate data between early boot and late boot */
29static struct phyp_dump phyp_dump_vars;
30struct phyp_dump *phyp_dump_info = &phyp_dump_vars;
31
32static int ibm_configure_kernel_dump;
33/* ------------------------------------------------- */
34/* RTAS interfaces to declare the dump regions */
35
36struct dump_section {
37 u32 dump_flags;
38 u16 source_type;
39 u16 error_flags;
40 u64 source_address;
41 u64 source_length;
42 u64 length_copied;
43 u64 destination_address;
44};
45
46struct phyp_dump_header {
47 u32 version;
48 u16 num_of_sections;
49 u16 status;
50
51 u32 first_offset_section;
52 u32 dump_disk_section;
53 u64 block_num_dd;
54 u64 num_of_blocks_dd;
55 u32 offset_dd;
56 u32 maxtime_to_auto;
57 /* No dump disk path string used */
58
59 struct dump_section cpu_data;
60 struct dump_section hpte_data;
61 struct dump_section kernel_data;
62};
63
64/* The dump header *must be* in low memory, so .bss it */
65static struct phyp_dump_header phdr;
66
67#define NUM_DUMP_SECTIONS 3
68#define DUMP_HEADER_VERSION 0x1
69#define DUMP_REQUEST_FLAG 0x1
70#define DUMP_SOURCE_CPU 0x0001
71#define DUMP_SOURCE_HPTE 0x0002
72#define DUMP_SOURCE_RMO 0x0011
73#define DUMP_ERROR_FLAG 0x2000
74#define DUMP_TRIGGERED 0x4000
75#define DUMP_PERFORMED 0x8000
76
77
78/**
79 * init_dump_header() - initialize the header declaring a dump
80 * Returns: length of dump save area.
81 *
82 * When the hypervisor saves crashed state, it needs to put
83 * it somewhere. The dump header tells the hypervisor where
84 * the data can be saved.
85 */
86static unsigned long init_dump_header(struct phyp_dump_header *ph)
87{
88 unsigned long addr_offset = 0;
89
90 /* Set up the dump header */
91 ph->version = DUMP_HEADER_VERSION;
92 ph->num_of_sections = NUM_DUMP_SECTIONS;
93 ph->status = 0;
94
95 ph->first_offset_section =
96 (u32)offsetof(struct phyp_dump_header, cpu_data);
97 ph->dump_disk_section = 0;
98 ph->block_num_dd = 0;
99 ph->num_of_blocks_dd = 0;
100 ph->offset_dd = 0;
101
102 ph->maxtime_to_auto = 0; /* disabled */
103
104 /* The first two sections are mandatory */
105 ph->cpu_data.dump_flags = DUMP_REQUEST_FLAG;
106 ph->cpu_data.source_type = DUMP_SOURCE_CPU;
107 ph->cpu_data.source_address = 0;
108 ph->cpu_data.source_length = phyp_dump_info->cpu_state_size;
109 ph->cpu_data.destination_address = addr_offset;
110 addr_offset += phyp_dump_info->cpu_state_size;
111
112 ph->hpte_data.dump_flags = DUMP_REQUEST_FLAG;
113 ph->hpte_data.source_type = DUMP_SOURCE_HPTE;
114 ph->hpte_data.source_address = 0;
115 ph->hpte_data.source_length = phyp_dump_info->hpte_region_size;
116 ph->hpte_data.destination_address = addr_offset;
117 addr_offset += phyp_dump_info->hpte_region_size;
118
119 /* This section describes the low kernel region */
120 ph->kernel_data.dump_flags = DUMP_REQUEST_FLAG;
121 ph->kernel_data.source_type = DUMP_SOURCE_RMO;
122 ph->kernel_data.source_address = PHYP_DUMP_RMR_START;
123 ph->kernel_data.source_length = PHYP_DUMP_RMR_END;
124 ph->kernel_data.destination_address = addr_offset;
125 addr_offset += ph->kernel_data.source_length;
126
127 return addr_offset;
128}
129
130static void print_dump_header(const struct phyp_dump_header *ph)
131{
132#ifdef DEBUG
133 printk(KERN_INFO "dump header:\n");
134 /* setup some ph->sections required */
135 printk(KERN_INFO "version = %d\n", ph->version);
136 printk(KERN_INFO "Sections = %d\n", ph->num_of_sections);
137 printk(KERN_INFO "Status = 0x%x\n", ph->status);
138
139 /* No ph->disk, so all should be set to 0 */
140 printk(KERN_INFO "Offset to first section 0x%x\n",
141 ph->first_offset_section);
142 printk(KERN_INFO "dump disk sections should be zero\n");
143 printk(KERN_INFO "dump disk section = %d\n", ph->dump_disk_section);
144 printk(KERN_INFO "block num = %ld\n", ph->block_num_dd);
145 printk(KERN_INFO "number of blocks = %ld\n", ph->num_of_blocks_dd);
146 printk(KERN_INFO "dump disk offset = %d\n", ph->offset_dd);
147 printk(KERN_INFO "Max auto time= %d\n", ph->maxtime_to_auto);
148
149 /*set cpu state and hpte states as well scratch pad area */
150 printk(KERN_INFO " CPU AREA \n");
151 printk(KERN_INFO "cpu dump_flags =%d\n", ph->cpu_data.dump_flags);
152 printk(KERN_INFO "cpu source_type =%d\n", ph->cpu_data.source_type);
153 printk(KERN_INFO "cpu error_flags =%d\n", ph->cpu_data.error_flags);
154 printk(KERN_INFO "cpu source_address =%lx\n",
155 ph->cpu_data.source_address);
156 printk(KERN_INFO "cpu source_length =%lx\n",
157 ph->cpu_data.source_length);
158 printk(KERN_INFO "cpu length_copied =%lx\n",
159 ph->cpu_data.length_copied);
160
161 printk(KERN_INFO " HPTE AREA \n");
162 printk(KERN_INFO "HPTE dump_flags =%d\n", ph->hpte_data.dump_flags);
163 printk(KERN_INFO "HPTE source_type =%d\n", ph->hpte_data.source_type);
164 printk(KERN_INFO "HPTE error_flags =%d\n", ph->hpte_data.error_flags);
165 printk(KERN_INFO "HPTE source_address =%lx\n",
166 ph->hpte_data.source_address);
167 printk(KERN_INFO "HPTE source_length =%lx\n",
168 ph->hpte_data.source_length);
169 printk(KERN_INFO "HPTE length_copied =%lx\n",
170 ph->hpte_data.length_copied);
171
172 printk(KERN_INFO " SRSD AREA \n");
173 printk(KERN_INFO "SRSD dump_flags =%d\n", ph->kernel_data.dump_flags);
174 printk(KERN_INFO "SRSD source_type =%d\n", ph->kernel_data.source_type);
175 printk(KERN_INFO "SRSD error_flags =%d\n", ph->kernel_data.error_flags);
176 printk(KERN_INFO "SRSD source_address =%lx\n",
177 ph->kernel_data.source_address);
178 printk(KERN_INFO "SRSD source_length =%lx\n",
179 ph->kernel_data.source_length);
180 printk(KERN_INFO "SRSD length_copied =%lx\n",
181 ph->kernel_data.length_copied);
182#endif
183}
184
185static ssize_t show_phyp_dump_active(struct kobject *kobj,
186 struct kobj_attribute *attr, char *buf)
187{
188
189 /* create filesystem entry so kdump is phyp-dump aware */
190 return sprintf(buf, "%lx\n", phyp_dump_info->phyp_dump_at_boot);
191}
192
193static struct kobj_attribute pdl = __ATTR(phyp_dump_active, 0600,
194 show_phyp_dump_active,
195 NULL);
196
197static void register_dump_area(struct phyp_dump_header *ph, unsigned long addr)
198{
199 int rc;
200
201 /* Add addr value if not initialized before */
202 if (ph->cpu_data.destination_address == 0) {
203 ph->cpu_data.destination_address += addr;
204 ph->hpte_data.destination_address += addr;
205 ph->kernel_data.destination_address += addr;
206 }
207
208 /* ToDo Invalidate kdump and free memory range. */
209
210 do {
211 rc = rtas_call(ibm_configure_kernel_dump, 3, 1, NULL,
212 1, ph, sizeof(struct phyp_dump_header));
213 } while (rtas_busy_delay(rc));
214
215 if (rc) {
216 printk(KERN_ERR "phyp-dump: unexpected error (%d) on "
217 "register\n", rc);
218 print_dump_header(ph);
219 return;
220 }
221
222 rc = sysfs_create_file(kernel_kobj, &pdl.attr);
223 if (rc)
224 printk(KERN_ERR "phyp-dump: unable to create sysfs"
225 " file (%d)\n", rc);
226}
227
228static
229void invalidate_last_dump(struct phyp_dump_header *ph, unsigned long addr)
230{
231 int rc;
232
233 /* Add addr value if not initialized before */
234 if (ph->cpu_data.destination_address == 0) {
235 ph->cpu_data.destination_address += addr;
236 ph->hpte_data.destination_address += addr;
237 ph->kernel_data.destination_address += addr;
238 }
239
240 do {
241 rc = rtas_call(ibm_configure_kernel_dump, 3, 1, NULL,
242 2, ph, sizeof(struct phyp_dump_header));
243 } while (rtas_busy_delay(rc));
244
245 if (rc) {
246 printk(KERN_ERR "phyp-dump: unexpected error (%d) "
247 "on invalidate\n", rc);
248 print_dump_header(ph);
249 }
250}
251
252/* ------------------------------------------------- */
253/**
254 * release_memory_range -- release memory previously lmb_reserved
255 * @start_pfn: starting physical frame number
256 * @nr_pages: number of pages to free.
257 *
258 * This routine will release memory that had been previously
259 * lmb_reserved in early boot. The released memory becomes
260 * available for genreal use.
261 */
262static void release_memory_range(unsigned long start_pfn,
263 unsigned long nr_pages)
264{
265 struct page *rpage;
266 unsigned long end_pfn;
267 long i;
268
269 end_pfn = start_pfn + nr_pages;
270
271 for (i = start_pfn; i <= end_pfn; i++) {
272 rpage = pfn_to_page(i);
273 if (PageReserved(rpage)) {
274 ClearPageReserved(rpage);
275 init_page_count(rpage);
276 __free_page(rpage);
277 totalram_pages++;
278 }
279 }
280}
281
282/**
283 * track_freed_range -- Counts the range being freed.
284 * Once the counter goes to zero, it re-registers dump for
285 * future use.
286 */
287static void
288track_freed_range(unsigned long addr, unsigned long length)
289{
290 static unsigned long scratch_area_size, reserved_area_size;
291
292 if (addr < phyp_dump_info->init_reserve_start)
293 return;
294
295 if ((addr >= phyp_dump_info->init_reserve_start) &&
296 (addr <= phyp_dump_info->init_reserve_start +
297 phyp_dump_info->init_reserve_size))
298 reserved_area_size += length;
299
300 if ((addr >= phyp_dump_info->reserved_scratch_addr) &&
301 (addr <= phyp_dump_info->reserved_scratch_addr +
302 phyp_dump_info->reserved_scratch_size))
303 scratch_area_size += length;
304
305 if ((reserved_area_size == phyp_dump_info->init_reserve_size) &&
306 (scratch_area_size == phyp_dump_info->reserved_scratch_size)) {
307
308 invalidate_last_dump(&phdr,
309 phyp_dump_info->reserved_scratch_addr);
310 register_dump_area(&phdr,
311 phyp_dump_info->reserved_scratch_addr);
312 }
313}
314
315/* ------------------------------------------------- */
316/**
317 * sysfs_release_region -- sysfs interface to release memory range.
318 *
319 * Usage:
320 * "echo <start addr> <length> > /sys/kernel/release_region"
321 *
322 * Example:
323 * "echo 0x40000000 0x10000000 > /sys/kernel/release_region"
324 *
325 * will release 256MB starting at 1GB.
326 */
327static ssize_t store_release_region(struct kobject *kobj,
328 struct kobj_attribute *attr,
329 const char *buf, size_t count)
330{
331 unsigned long start_addr, length, end_addr;
332 unsigned long start_pfn, nr_pages;
333 ssize_t ret;
334
335 ret = sscanf(buf, "%lx %lx", &start_addr, &length);
336 if (ret != 2)
337 return -EINVAL;
338
339 track_freed_range(start_addr, length);
340
341 /* Range-check - don't free any reserved memory that
342 * wasn't reserved for phyp-dump */
343 if (start_addr < phyp_dump_info->init_reserve_start)
344 start_addr = phyp_dump_info->init_reserve_start;
345
346 end_addr = phyp_dump_info->init_reserve_start +
347 phyp_dump_info->init_reserve_size;
348 if (start_addr+length > end_addr)
349 length = end_addr - start_addr;
350
351 /* Release the region of memory assed in by user */
352 start_pfn = PFN_DOWN(start_addr);
353 nr_pages = PFN_DOWN(length);
354 release_memory_range(start_pfn, nr_pages);
355
356 return count;
357}
358
359static ssize_t show_release_region(struct kobject *kobj,
360 struct kobj_attribute *attr, char *buf)
361{
362 u64 second_addr_range;
363
364 /* total reserved size - start of scratch area */
365 second_addr_range = phyp_dump_info->init_reserve_size -
366 phyp_dump_info->reserved_scratch_size;
367 return sprintf(buf, "CPU:0x%lx-0x%lx: HPTE:0x%lx-0x%lx:"
368 " DUMP:0x%lx-0x%lx, 0x%lx-0x%lx:\n",
369 phdr.cpu_data.destination_address,
370 phdr.cpu_data.length_copied,
371 phdr.hpte_data.destination_address,
372 phdr.hpte_data.length_copied,
373 phdr.kernel_data.destination_address,
374 phdr.kernel_data.length_copied,
375 phyp_dump_info->init_reserve_start,
376 second_addr_range);
377}
378
379static struct kobj_attribute rr = __ATTR(release_region, 0600,
380 show_release_region,
381 store_release_region);
382
383static int __init phyp_dump_setup(void)
384{
385 struct device_node *rtas;
386 const struct phyp_dump_header *dump_header = NULL;
387 unsigned long dump_area_start;
388 unsigned long dump_area_length;
389 int header_len = 0;
390 int rc;
391
392 /* If no memory was reserved in early boot, there is nothing to do */
393 if (phyp_dump_info->init_reserve_size == 0)
394 return 0;
395
396 /* Return if phyp dump not supported */
397 if (!phyp_dump_info->phyp_dump_configured)
398 return -ENOSYS;
399
400 /* Is there dump data waiting for us? If there isn't,
401 * then register a new dump area, and release all of
402 * the rest of the reserved ram.
403 *
404 * The /rtas/ibm,kernel-dump rtas node is present only
405 * if there is dump data waiting for us.
406 */
407 rtas = of_find_node_by_path("/rtas");
408 if (rtas) {
409 dump_header = of_get_property(rtas, "ibm,kernel-dump",
410 &header_len);
411 of_node_put(rtas);
412 }
413
414 print_dump_header(dump_header);
415 dump_area_length = init_dump_header(&phdr);
416 /* align down */
417 dump_area_start = phyp_dump_info->init_reserve_start & PAGE_MASK;
418
419 if (dump_header == NULL) {
420 register_dump_area(&phdr, dump_area_start);
421 return 0;
422 }
423
424 /* re-register the dump area, if old dump was invalid */
425 if ((dump_header) && (dump_header->status & DUMP_ERROR_FLAG)) {
426 invalidate_last_dump(&phdr, dump_area_start);
427 register_dump_area(&phdr, dump_area_start);
428 return 0;
429 }
430
431 if (dump_header) {
432 phyp_dump_info->reserved_scratch_addr =
433 dump_header->cpu_data.destination_address;
434 phyp_dump_info->reserved_scratch_size =
435 dump_header->cpu_data.source_length +
436 dump_header->hpte_data.source_length +
437 dump_header->kernel_data.source_length;
438 }
439
440 /* Should we create a dump_subsys, analogous to s390/ipl.c ? */
441 rc = sysfs_create_file(kernel_kobj, &rr.attr);
442 if (rc)
443 printk(KERN_ERR "phyp-dump: unable to create sysfs file (%d)\n",
444 rc);
445
446 /* ToDo: re-register the dump area, for next time. */
447 return 0;
448}
449machine_subsys_initcall(pseries, phyp_dump_setup);
450
451int __init early_init_dt_scan_phyp_dump(unsigned long node,
452 const char *uname, int depth, void *data)
453{
454 const unsigned int *sizes;
455
456 phyp_dump_info->phyp_dump_configured = 0;
457 phyp_dump_info->phyp_dump_is_active = 0;
458
459 if (depth != 1 || strcmp(uname, "rtas") != 0)
460 return 0;
461
462 if (of_get_flat_dt_prop(node, "ibm,configure-kernel-dump", NULL))
463 phyp_dump_info->phyp_dump_configured++;
464
465 if (of_get_flat_dt_prop(node, "ibm,dump-kernel", NULL))
466 phyp_dump_info->phyp_dump_is_active++;
467
468 sizes = of_get_flat_dt_prop(node, "ibm,configure-kernel-dump-sizes",
469 NULL);
470 if (!sizes)
471 return 0;
472
473 if (sizes[0] == 1)
474 phyp_dump_info->cpu_state_size = *((unsigned long *)&sizes[1]);
475
476 if (sizes[3] == 2)
477 phyp_dump_info->hpte_region_size =
478 *((unsigned long *)&sizes[4]);
479 return 1;
480}
481
482/* Look for phyp_dump= cmdline option */
483static int __init early_phyp_dump_enabled(char *p)
484{
485 phyp_dump_info->phyp_dump_at_boot = 1;
486
487 if (!p)
488 return 0;
489
490 if (strncmp(p, "1", 1) == 0)
491 phyp_dump_info->phyp_dump_at_boot = 1;
492 else if (strncmp(p, "0", 1) == 0)
493 phyp_dump_info->phyp_dump_at_boot = 0;
494
495 return 0;
496}
497early_param("phyp_dump", early_phyp_dump_enabled);
498
diff --git a/arch/powerpc/platforms/pseries/scanlog.c b/arch/powerpc/platforms/pseries/scanlog.c
index 8e1ef168e2dd..e5b0ea870164 100644
--- a/arch/powerpc/platforms/pseries/scanlog.c
+++ b/arch/powerpc/platforms/pseries/scanlog.c
@@ -195,31 +195,30 @@ const struct file_operations scanlog_fops = {
195static int __init scanlog_init(void) 195static int __init scanlog_init(void)
196{ 196{
197 struct proc_dir_entry *ent; 197 struct proc_dir_entry *ent;
198 void *data;
199 int err = -ENOMEM;
198 200
199 ibm_scan_log_dump = rtas_token("ibm,scan-log-dump"); 201 ibm_scan_log_dump = rtas_token("ibm,scan-log-dump");
200 if (ibm_scan_log_dump == RTAS_UNKNOWN_SERVICE) { 202 if (ibm_scan_log_dump == RTAS_UNKNOWN_SERVICE)
201 printk(KERN_ERR "scan-log-dump not implemented on this system\n"); 203 return -ENODEV;
202 return -EIO;
203 }
204 204
205 ent = create_proc_entry("ppc64/rtas/scan-log-dump", S_IRUSR, NULL); 205 /* Ideally we could allocate a buffer < 4G */
206 if (ent) { 206 data = kzalloc(RTAS_DATA_BUF_SIZE, GFP_KERNEL);
207 ent->proc_fops = &scanlog_fops; 207 if (!data)
208 /* Ideally we could allocate a buffer < 4G */ 208 goto err;
209 ent->data = kmalloc(RTAS_DATA_BUF_SIZE, GFP_KERNEL); 209
210 if (!ent->data) { 210 ent = proc_create("ppc64/rtas/scan-log-dump", S_IRUSR, NULL,
211 printk(KERN_ERR "Failed to allocate a buffer\n"); 211 &scanlog_fops);
212 remove_proc_entry("scan-log-dump", ent->parent); 212 if (!ent)
213 return -ENOMEM; 213 goto err;
214 } 214
215 ((unsigned int *)ent->data)[0] = 0; 215 ent->data = data;
216 } else {
217 printk(KERN_ERR "Failed to create ppc64/scan-log-dump proc entry\n");
218 return -EIO;
219 }
220 proc_ppc64_scan_log_dump = ent; 216 proc_ppc64_scan_log_dump = ent;
221 217
222 return 0; 218 return 0;
219err:
220 kfree(data);
221 return err;
223} 222}
224 223
225static void __exit scanlog_cleanup(void) 224static void __exit scanlog_cleanup(void)
diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c
index fdb9b1c8f977..90555a39fe62 100644
--- a/arch/powerpc/platforms/pseries/setup.c
+++ b/arch/powerpc/platforms/pseries/setup.c
@@ -393,6 +393,7 @@ static void pseries_dedicated_idle_sleep(void)
393{ 393{
394 unsigned int cpu = smp_processor_id(); 394 unsigned int cpu = smp_processor_id();
395 unsigned long start_snooze; 395 unsigned long start_snooze;
396 unsigned long in_purr, out_purr;
396 397
397 /* 398 /*
398 * Indicate to the HV that we are idle. Now would be 399 * Indicate to the HV that we are idle. Now would be
@@ -400,6 +401,7 @@ static void pseries_dedicated_idle_sleep(void)
400 */ 401 */
401 get_lppaca()->idle = 1; 402 get_lppaca()->idle = 1;
402 get_lppaca()->donate_dedicated_cpu = 1; 403 get_lppaca()->donate_dedicated_cpu = 1;
404 in_purr = mfspr(SPRN_PURR);
403 405
404 /* 406 /*
405 * We come in with interrupts disabled, and need_resched() 407 * We come in with interrupts disabled, and need_resched()
@@ -432,6 +434,8 @@ static void pseries_dedicated_idle_sleep(void)
432 434
433out: 435out:
434 HMT_medium(); 436 HMT_medium();
437 out_purr = mfspr(SPRN_PURR);
438 get_lppaca()->wait_state_cycles += out_purr - in_purr;
435 get_lppaca()->donate_dedicated_cpu = 0; 439 get_lppaca()->donate_dedicated_cpu = 0;
436 get_lppaca()->idle = 0; 440 get_lppaca()->idle = 0;
437} 441}
diff --git a/arch/powerpc/sysdev/dart_iommu.c b/arch/powerpc/sysdev/dart_iommu.c
index e0e24b01e3a6..005c2ecf976f 100644
--- a/arch/powerpc/sysdev/dart_iommu.c
+++ b/arch/powerpc/sysdev/dart_iommu.c
@@ -37,6 +37,7 @@
37#include <linux/dma-mapping.h> 37#include <linux/dma-mapping.h>
38#include <linux/vmalloc.h> 38#include <linux/vmalloc.h>
39#include <linux/suspend.h> 39#include <linux/suspend.h>
40#include <linux/lmb.h>
40#include <asm/io.h> 41#include <asm/io.h>
41#include <asm/prom.h> 42#include <asm/prom.h>
42#include <asm/iommu.h> 43#include <asm/iommu.h>
@@ -44,7 +45,6 @@
44#include <asm/machdep.h> 45#include <asm/machdep.h>
45#include <asm/abs_addr.h> 46#include <asm/abs_addr.h>
46#include <asm/cacheflush.h> 47#include <asm/cacheflush.h>
47#include <asm/lmb.h>
48#include <asm/ppc-pci.h> 48#include <asm/ppc-pci.h>
49 49
50#include "dart.h" 50#include "dart.h"
diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c
index 6ffdda244bb1..6131fd2b6619 100644
--- a/arch/powerpc/sysdev/mpic.c
+++ b/arch/powerpc/sysdev/mpic.c
@@ -175,13 +175,16 @@ static inline void _mpic_write(enum mpic_reg_type type,
175 switch(type) { 175 switch(type) {
176#ifdef CONFIG_PPC_DCR 176#ifdef CONFIG_PPC_DCR
177 case mpic_access_dcr: 177 case mpic_access_dcr:
178 return dcr_write(rb->dhost, reg, value); 178 dcr_write(rb->dhost, reg, value);
179 break;
179#endif 180#endif
180 case mpic_access_mmio_be: 181 case mpic_access_mmio_be:
181 return out_be32(rb->base + (reg >> 2), value); 182 out_be32(rb->base + (reg >> 2), value);
183 break;
182 case mpic_access_mmio_le: 184 case mpic_access_mmio_le:
183 default: 185 default:
184 return out_le32(rb->base + (reg >> 2), value); 186 out_le32(rb->base + (reg >> 2), value);
187 break;
185 } 188 }
186} 189}
187 190
@@ -1000,7 +1003,7 @@ struct mpic * __init mpic_alloc(struct device_node *node,
1000 const char *name) 1003 const char *name)
1001{ 1004{
1002 struct mpic *mpic; 1005 struct mpic *mpic;
1003 u32 reg; 1006 u32 greg_feature;
1004 const char *vers; 1007 const char *vers;
1005 int i; 1008 int i;
1006 int intvec_top; 1009 int intvec_top;
@@ -1064,7 +1067,8 @@ struct mpic * __init mpic_alloc(struct device_node *node,
1064 1067
1065 /* Look for protected sources */ 1068 /* Look for protected sources */
1066 if (node) { 1069 if (node) {
1067 unsigned int psize, bits, mapsize; 1070 int psize;
1071 unsigned int bits, mapsize;
1068 const u32 *psrc = 1072 const u32 *psrc =
1069 of_get_property(node, "protected-sources", &psize); 1073 of_get_property(node, "protected-sources", &psize);
1070 if (psrc) { 1074 if (psrc) {
@@ -1107,8 +1111,7 @@ struct mpic * __init mpic_alloc(struct device_node *node,
1107 * in, try to obtain one 1111 * in, try to obtain one
1108 */ 1112 */
1109 if (paddr == 0 && !(mpic->flags & MPIC_USES_DCR)) { 1113 if (paddr == 0 && !(mpic->flags & MPIC_USES_DCR)) {
1110 const u32 *reg; 1114 const u32 *reg = of_get_property(node, "reg", NULL);
1111 reg = of_get_property(node, "reg", NULL);
1112 BUG_ON(reg == NULL); 1115 BUG_ON(reg == NULL);
1113 paddr = of_translate_address(node, reg); 1116 paddr = of_translate_address(node, reg);
1114 BUG_ON(paddr == OF_BAD_ADDR); 1117 BUG_ON(paddr == OF_BAD_ADDR);
@@ -1137,12 +1140,13 @@ struct mpic * __init mpic_alloc(struct device_node *node,
1137 * MPICs, num sources as well. On ISU MPICs, sources are counted 1140 * MPICs, num sources as well. On ISU MPICs, sources are counted
1138 * as ISUs are added 1141 * as ISUs are added
1139 */ 1142 */
1140 reg = mpic_read(mpic->gregs, MPIC_INFO(GREG_FEATURE_0)); 1143 greg_feature = mpic_read(mpic->gregs, MPIC_INFO(GREG_FEATURE_0));
1141 mpic->num_cpus = ((reg & MPIC_GREG_FEATURE_LAST_CPU_MASK) 1144 mpic->num_cpus = ((greg_feature & MPIC_GREG_FEATURE_LAST_CPU_MASK)
1142 >> MPIC_GREG_FEATURE_LAST_CPU_SHIFT) + 1; 1145 >> MPIC_GREG_FEATURE_LAST_CPU_SHIFT) + 1;
1143 if (isu_size == 0) 1146 if (isu_size == 0)
1144 mpic->num_sources = ((reg & MPIC_GREG_FEATURE_LAST_SRC_MASK) 1147 mpic->num_sources =
1145 >> MPIC_GREG_FEATURE_LAST_SRC_SHIFT) + 1; 1148 ((greg_feature & MPIC_GREG_FEATURE_LAST_SRC_MASK)
1149 >> MPIC_GREG_FEATURE_LAST_SRC_SHIFT) + 1;
1146 1150
1147 /* Map the per-CPU registers */ 1151 /* Map the per-CPU registers */
1148 for (i = 0; i < mpic->num_cpus; i++) { 1152 for (i = 0; i < mpic->num_cpus; i++) {
@@ -1161,7 +1165,7 @@ struct mpic * __init mpic_alloc(struct device_node *node,
1161 mpic->isu_mask = (1 << mpic->isu_shift) - 1; 1165 mpic->isu_mask = (1 << mpic->isu_shift) - 1;
1162 1166
1163 /* Display version */ 1167 /* Display version */
1164 switch (reg & MPIC_GREG_FEATURE_VERSION_MASK) { 1168 switch (greg_feature & MPIC_GREG_FEATURE_VERSION_MASK) {
1165 case 1: 1169 case 1:
1166 vers = "1.0"; 1170 vers = "1.0";
1167 break; 1171 break;
@@ -1321,7 +1325,7 @@ void __init mpic_set_serial_int(struct mpic *mpic, int enable)
1321 1325
1322void mpic_irq_set_priority(unsigned int irq, unsigned int pri) 1326void mpic_irq_set_priority(unsigned int irq, unsigned int pri)
1323{ 1327{
1324 int is_ipi; 1328 unsigned int is_ipi;
1325 struct mpic *mpic = mpic_find(irq, &is_ipi); 1329 struct mpic *mpic = mpic_find(irq, &is_ipi);
1326 unsigned int src = mpic_irq_to_hw(irq); 1330 unsigned int src = mpic_irq_to_hw(irq);
1327 unsigned long flags; 1331 unsigned long flags;
@@ -1344,7 +1348,7 @@ void mpic_irq_set_priority(unsigned int irq, unsigned int pri)
1344 1348
1345unsigned int mpic_irq_get_priority(unsigned int irq) 1349unsigned int mpic_irq_get_priority(unsigned int irq)
1346{ 1350{
1347 int is_ipi; 1351 unsigned int is_ipi;
1348 struct mpic *mpic = mpic_find(irq, &is_ipi); 1352 struct mpic *mpic = mpic_find(irq, &is_ipi);
1349 unsigned int src = mpic_irq_to_hw(irq); 1353 unsigned int src = mpic_irq_to_hw(irq);
1350 unsigned long flags; 1354 unsigned long flags;
diff --git a/arch/ppc/8xx_io/commproc.c b/arch/ppc/8xx_io/commproc.c
index 9d656de0f0f1..752443df5ecf 100644
--- a/arch/ppc/8xx_io/commproc.c
+++ b/arch/ppc/8xx_io/commproc.c
@@ -43,7 +43,7 @@
43({ \ 43({ \
44 u32 offset = offsetof(immap_t, member); \ 44 u32 offset = offsetof(immap_t, member); \
45 void *addr = ioremap (IMAP_ADDR + offset, \ 45 void *addr = ioremap (IMAP_ADDR + offset, \
46 sizeof( ((immap_t*)0)->member)); \ 46 FIELD_SIZEOF(immap_t, member)); \
47 addr; \ 47 addr; \
48}) 48})
49 49
diff --git a/arch/ppc/kernel/head.S b/arch/ppc/kernel/head.S
index 1b0ec7202dd5..e7e642b95138 100644
--- a/arch/ppc/kernel/head.S
+++ b/arch/ppc/kernel/head.S
@@ -701,23 +701,6 @@ load_up_altivec:
701 b fast_exception_return 701 b fast_exception_return
702 702
703/* 703/*
704 * AltiVec unavailable trap from kernel - print a message, but let
705 * the task use AltiVec in the kernel until it returns to user mode.
706 */
707KernelAltiVec:
708 lwz r3,_MSR(r1)
709 oris r3,r3,MSR_VEC@h
710 stw r3,_MSR(r1) /* enable use of AltiVec after return */
711 lis r3,87f@h
712 ori r3,r3,87f@l
713 mr r4,r2 /* current */
714 lwz r5,_NIP(r1)
715 bl printk
716 b ret_from_except
71787: .string "AltiVec used in kernel (task=%p, pc=%x) \n"
718 .align 4,0
719
720/*
721 * giveup_altivec(tsk) 704 * giveup_altivec(tsk)
722 * Disable AltiVec for the task given as the argument, 705 * Disable AltiVec for the task given as the argument,
723 * and save the AltiVec registers in its thread_struct. 706 * and save the AltiVec registers in its thread_struct.
diff --git a/arch/sparc64/Kconfig b/arch/sparc64/Kconfig
index 463d1be32c98..2667a9dee11d 100644
--- a/arch/sparc64/Kconfig
+++ b/arch/sparc64/Kconfig
@@ -16,6 +16,7 @@ config SPARC64
16 bool 16 bool
17 default y 17 default y
18 select HAVE_IDE 18 select HAVE_IDE
19 select HAVE_LMB
19 help 20 help
20 SPARC is a family of RISC microprocessors designed and marketed by 21 SPARC is a family of RISC microprocessors designed and marketed by
21 Sun Microsystems, incorporated. This port covers the newer 64-bit 22 Sun Microsystems, incorporated. This port covers the newer 64-bit
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index 3b1ea321dc05..4b442739e7bf 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -218,7 +218,8 @@ obj-$(CONFIG_SMC911X) += smc911x.o
218obj-$(CONFIG_BFIN_MAC) += bfin_mac.o 218obj-$(CONFIG_BFIN_MAC) += bfin_mac.o
219obj-$(CONFIG_DM9000) += dm9000.o 219obj-$(CONFIG_DM9000) += dm9000.o
220obj-$(CONFIG_FEC_8XX) += fec_8xx/ 220obj-$(CONFIG_FEC_8XX) += fec_8xx/
221obj-$(CONFIG_PASEMI_MAC) += pasemi_mac.o 221obj-$(CONFIG_PASEMI_MAC) += pasemi_mac_driver.o
222pasemi_mac_driver-objs := pasemi_mac.o pasemi_mac_ethtool.o
222obj-$(CONFIG_MLX4_CORE) += mlx4/ 223obj-$(CONFIG_MLX4_CORE) += mlx4/
223obj-$(CONFIG_ENC28J60) += enc28j60.o 224obj-$(CONFIG_ENC28J60) += enc28j60.o
224 225
diff --git a/drivers/net/pasemi_mac.c b/drivers/net/pasemi_mac.c
index 2e39e0285d8f..c50f0f4de6d8 100644
--- a/drivers/net/pasemi_mac.c
+++ b/drivers/net/pasemi_mac.c
@@ -55,15 +55,10 @@
55 * - Multiqueue RX/TX 55 * - Multiqueue RX/TX
56 */ 56 */
57 57
58
59/* Must be a power of two */
60#define RX_RING_SIZE 2048
61#define TX_RING_SIZE 4096
62
63#define LRO_MAX_AGGR 64 58#define LRO_MAX_AGGR 64
64 59
65#define PE_MIN_MTU 64 60#define PE_MIN_MTU 64
66#define PE_MAX_MTU 1500 61#define PE_MAX_MTU 9000
67#define PE_DEF_MTU ETH_DATA_LEN 62#define PE_DEF_MTU ETH_DATA_LEN
68 63
69#define DEFAULT_MSG_ENABLE \ 64#define DEFAULT_MSG_ENABLE \
@@ -76,16 +71,6 @@
76 NETIF_MSG_RX_ERR | \ 71 NETIF_MSG_RX_ERR | \
77 NETIF_MSG_TX_ERR) 72 NETIF_MSG_TX_ERR)
78 73
79#define TX_DESC(tx, num) ((tx)->chan.ring_virt[(num) & (TX_RING_SIZE-1)])
80#define TX_DESC_INFO(tx, num) ((tx)->ring_info[(num) & (TX_RING_SIZE-1)])
81#define RX_DESC(rx, num) ((rx)->chan.ring_virt[(num) & (RX_RING_SIZE-1)])
82#define RX_DESC_INFO(rx, num) ((rx)->ring_info[(num) & (RX_RING_SIZE-1)])
83#define RX_BUFF(rx, num) ((rx)->buffers[(num) & (RX_RING_SIZE-1)])
84
85#define RING_USED(ring) (((ring)->next_to_fill - (ring)->next_to_clean) \
86 & ((ring)->size - 1))
87#define RING_AVAIL(ring) ((ring->size) - RING_USED(ring))
88
89MODULE_LICENSE("GPL"); 74MODULE_LICENSE("GPL");
90MODULE_AUTHOR ("Olof Johansson <olof@lixom.net>"); 75MODULE_AUTHOR ("Olof Johansson <olof@lixom.net>");
91MODULE_DESCRIPTION("PA Semi PWRficient Ethernet driver"); 76MODULE_DESCRIPTION("PA Semi PWRficient Ethernet driver");
@@ -94,6 +79,8 @@ static int debug = -1; /* -1 == use DEFAULT_MSG_ENABLE as value */
94module_param(debug, int, 0); 79module_param(debug, int, 0);
95MODULE_PARM_DESC(debug, "PA Semi MAC bitmapped debugging message enable value"); 80MODULE_PARM_DESC(debug, "PA Semi MAC bitmapped debugging message enable value");
96 81
82extern const struct ethtool_ops pasemi_mac_ethtool_ops;
83
97static int translation_enabled(void) 84static int translation_enabled(void)
98{ 85{
99#if defined(CONFIG_PPC_PASEMI_IOMMU_DMA_FORCE) 86#if defined(CONFIG_PPC_PASEMI_IOMMU_DMA_FORCE)
@@ -322,6 +309,103 @@ static int pasemi_mac_unmap_tx_skb(struct pasemi_mac *mac,
322 return (nfrags + 3) & ~1; 309 return (nfrags + 3) & ~1;
323} 310}
324 311
312static struct pasemi_mac_csring *pasemi_mac_setup_csring(struct pasemi_mac *mac)
313{
314 struct pasemi_mac_csring *ring;
315 u32 val;
316 unsigned int cfg;
317 int chno;
318
319 ring = pasemi_dma_alloc_chan(TXCHAN, sizeof(struct pasemi_mac_csring),
320 offsetof(struct pasemi_mac_csring, chan));
321
322 if (!ring) {
323 dev_err(&mac->pdev->dev, "Can't allocate checksum channel\n");
324 goto out_chan;
325 }
326
327 chno = ring->chan.chno;
328
329 ring->size = CS_RING_SIZE;
330 ring->next_to_fill = 0;
331
332 /* Allocate descriptors */
333 if (pasemi_dma_alloc_ring(&ring->chan, CS_RING_SIZE))
334 goto out_ring_desc;
335
336 write_dma_reg(PAS_DMA_TXCHAN_BASEL(chno),
337 PAS_DMA_TXCHAN_BASEL_BRBL(ring->chan.ring_dma));
338 val = PAS_DMA_TXCHAN_BASEU_BRBH(ring->chan.ring_dma >> 32);
339 val |= PAS_DMA_TXCHAN_BASEU_SIZ(CS_RING_SIZE >> 3);
340
341 write_dma_reg(PAS_DMA_TXCHAN_BASEU(chno), val);
342
343 ring->events[0] = pasemi_dma_alloc_flag();
344 ring->events[1] = pasemi_dma_alloc_flag();
345 if (ring->events[0] < 0 || ring->events[1] < 0)
346 goto out_flags;
347
348 pasemi_dma_clear_flag(ring->events[0]);
349 pasemi_dma_clear_flag(ring->events[1]);
350
351 ring->fun = pasemi_dma_alloc_fun();
352 if (ring->fun < 0)
353 goto out_fun;
354
355 cfg = PAS_DMA_TXCHAN_CFG_TY_FUNC | PAS_DMA_TXCHAN_CFG_UP |
356 PAS_DMA_TXCHAN_CFG_TATTR(ring->fun) |
357 PAS_DMA_TXCHAN_CFG_LPSQ | PAS_DMA_TXCHAN_CFG_LPDQ;
358
359 if (translation_enabled())
360 cfg |= PAS_DMA_TXCHAN_CFG_TRD | PAS_DMA_TXCHAN_CFG_TRR;
361
362 write_dma_reg(PAS_DMA_TXCHAN_CFG(chno), cfg);
363
364 /* enable channel */
365 pasemi_dma_start_chan(&ring->chan, PAS_DMA_TXCHAN_TCMDSTA_SZ |
366 PAS_DMA_TXCHAN_TCMDSTA_DB |
367 PAS_DMA_TXCHAN_TCMDSTA_DE |
368 PAS_DMA_TXCHAN_TCMDSTA_DA);
369
370 return ring;
371
372out_fun:
373out_flags:
374 if (ring->events[0] >= 0)
375 pasemi_dma_free_flag(ring->events[0]);
376 if (ring->events[1] >= 0)
377 pasemi_dma_free_flag(ring->events[1]);
378 pasemi_dma_free_ring(&ring->chan);
379out_ring_desc:
380 pasemi_dma_free_chan(&ring->chan);
381out_chan:
382
383 return NULL;
384}
385
386static void pasemi_mac_setup_csrings(struct pasemi_mac *mac)
387{
388 int i;
389 mac->cs[0] = pasemi_mac_setup_csring(mac);
390 if (mac->type == MAC_TYPE_XAUI)
391 mac->cs[1] = pasemi_mac_setup_csring(mac);
392 else
393 mac->cs[1] = 0;
394
395 for (i = 0; i < MAX_CS; i++)
396 if (mac->cs[i])
397 mac->num_cs++;
398}
399
400static void pasemi_mac_free_csring(struct pasemi_mac_csring *csring)
401{
402 pasemi_dma_stop_chan(&csring->chan);
403 pasemi_dma_free_flag(csring->events[0]);
404 pasemi_dma_free_flag(csring->events[1]);
405 pasemi_dma_free_ring(&csring->chan);
406 pasemi_dma_free_chan(&csring->chan);
407}
408
325static int pasemi_mac_setup_rx_resources(const struct net_device *dev) 409static int pasemi_mac_setup_rx_resources(const struct net_device *dev)
326{ 410{
327 struct pasemi_mac_rxring *ring; 411 struct pasemi_mac_rxring *ring;
@@ -445,7 +529,7 @@ pasemi_mac_setup_tx_resources(const struct net_device *dev)
445 cfg = PAS_DMA_TXCHAN_CFG_TY_IFACE | 529 cfg = PAS_DMA_TXCHAN_CFG_TY_IFACE |
446 PAS_DMA_TXCHAN_CFG_TATTR(mac->dma_if) | 530 PAS_DMA_TXCHAN_CFG_TATTR(mac->dma_if) |
447 PAS_DMA_TXCHAN_CFG_UP | 531 PAS_DMA_TXCHAN_CFG_UP |
448 PAS_DMA_TXCHAN_CFG_WT(2); 532 PAS_DMA_TXCHAN_CFG_WT(4);
449 533
450 if (translation_enabled()) 534 if (translation_enabled())
451 cfg |= PAS_DMA_TXCHAN_CFG_TRD | PAS_DMA_TXCHAN_CFG_TRR; 535 cfg |= PAS_DMA_TXCHAN_CFG_TRD | PAS_DMA_TXCHAN_CFG_TRR;
@@ -810,13 +894,21 @@ restart:
810 u64 mactx = TX_DESC(txring, i); 894 u64 mactx = TX_DESC(txring, i);
811 struct sk_buff *skb; 895 struct sk_buff *skb;
812 896
813 skb = TX_DESC_INFO(txring, i+1).skb;
814 nr_frags = TX_DESC_INFO(txring, i).dma;
815
816 if ((mactx & XCT_MACTX_E) || 897 if ((mactx & XCT_MACTX_E) ||
817 (*chan->status & PAS_STATUS_ERROR)) 898 (*chan->status & PAS_STATUS_ERROR))
818 pasemi_mac_tx_error(mac, mactx); 899 pasemi_mac_tx_error(mac, mactx);
819 900
901 /* Skip over control descriptors */
902 if (!(mactx & XCT_MACTX_LLEN_M)) {
903 TX_DESC(txring, i) = 0;
904 TX_DESC(txring, i+1) = 0;
905 buf_count = 2;
906 continue;
907 }
908
909 skb = TX_DESC_INFO(txring, i+1).skb;
910 nr_frags = TX_DESC_INFO(txring, i).dma;
911
820 if (unlikely(mactx & XCT_MACTX_O)) 912 if (unlikely(mactx & XCT_MACTX_O))
821 /* Not yet transmitted */ 913 /* Not yet transmitted */
822 break; 914 break;
@@ -1041,13 +1133,7 @@ static int pasemi_mac_open(struct net_device *dev)
1041{ 1133{
1042 struct pasemi_mac *mac = netdev_priv(dev); 1134 struct pasemi_mac *mac = netdev_priv(dev);
1043 unsigned int flags; 1135 unsigned int flags;
1044 int ret; 1136 int i, ret;
1045
1046 /* enable rx section */
1047 write_dma_reg(PAS_DMA_COM_RXCMD, PAS_DMA_COM_RXCMD_EN);
1048
1049 /* enable tx section */
1050 write_dma_reg(PAS_DMA_COM_TXCMD, PAS_DMA_COM_TXCMD_EN);
1051 1137
1052 flags = PAS_MAC_CFG_TXP_FCE | PAS_MAC_CFG_TXP_FPC(3) | 1138 flags = PAS_MAC_CFG_TXP_FCE | PAS_MAC_CFG_TXP_FPC(3) |
1053 PAS_MAC_CFG_TXP_SL(3) | PAS_MAC_CFG_TXP_COB(0xf) | 1139 PAS_MAC_CFG_TXP_SL(3) | PAS_MAC_CFG_TXP_COB(0xf) |
@@ -1064,6 +1150,16 @@ static int pasemi_mac_open(struct net_device *dev)
1064 if (!mac->tx) 1150 if (!mac->tx)
1065 goto out_tx_ring; 1151 goto out_tx_ring;
1066 1152
1153 if (dev->mtu > 1500) {
1154 pasemi_mac_setup_csrings(mac);
1155 if (!mac->num_cs)
1156 goto out_tx_ring;
1157 }
1158
1159 /* Zero out rmon counters */
1160 for (i = 0; i < 32; i++)
1161 write_mac_reg(mac, PAS_MAC_RMON(i), 0);
1162
1067 /* 0x3ff with 33MHz clock is about 31us */ 1163 /* 0x3ff with 33MHz clock is about 31us */
1068 write_iob_reg(PAS_IOB_DMA_COM_TIMEOUTCFG, 1164 write_iob_reg(PAS_IOB_DMA_COM_TIMEOUTCFG,
1069 PAS_IOB_DMA_COM_TIMEOUTCFG_TCNT(0x3ff)); 1165 PAS_IOB_DMA_COM_TIMEOUTCFG_TCNT(0x3ff));
@@ -1247,7 +1343,7 @@ static int pasemi_mac_close(struct net_device *dev)
1247{ 1343{
1248 struct pasemi_mac *mac = netdev_priv(dev); 1344 struct pasemi_mac *mac = netdev_priv(dev);
1249 unsigned int sta; 1345 unsigned int sta;
1250 int rxch, txch; 1346 int rxch, txch, i;
1251 1347
1252 rxch = rx_ring(mac)->chan.chno; 1348 rxch = rx_ring(mac)->chan.chno;
1253 txch = tx_ring(mac)->chan.chno; 1349 txch = tx_ring(mac)->chan.chno;
@@ -1292,6 +1388,9 @@ static int pasemi_mac_close(struct net_device *dev)
1292 free_irq(mac->tx->chan.irq, mac->tx); 1388 free_irq(mac->tx->chan.irq, mac->tx);
1293 free_irq(mac->rx->chan.irq, mac->rx); 1389 free_irq(mac->rx->chan.irq, mac->rx);
1294 1390
1391 for (i = 0; i < mac->num_cs; i++)
1392 pasemi_mac_free_csring(mac->cs[i]);
1393
1295 /* Free resources */ 1394 /* Free resources */
1296 pasemi_mac_free_rx_resources(mac); 1395 pasemi_mac_free_rx_resources(mac);
1297 pasemi_mac_free_tx_resources(mac); 1396 pasemi_mac_free_tx_resources(mac);
@@ -1299,35 +1398,113 @@ static int pasemi_mac_close(struct net_device *dev)
1299 return 0; 1398 return 0;
1300} 1399}
1301 1400
1401static void pasemi_mac_queue_csdesc(const struct sk_buff *skb,
1402 const dma_addr_t *map,
1403 const unsigned int *map_size,
1404 struct pasemi_mac_txring *txring,
1405 struct pasemi_mac_csring *csring)
1406{
1407 u64 fund;
1408 dma_addr_t cs_dest;
1409 const int nh_off = skb_network_offset(skb);
1410 const int nh_len = skb_network_header_len(skb);
1411 const int nfrags = skb_shinfo(skb)->nr_frags;
1412 int cs_size, i, fill, hdr, cpyhdr, evt;
1413 dma_addr_t csdma;
1414
1415 fund = XCT_FUN_ST | XCT_FUN_RR_8BRES |
1416 XCT_FUN_O | XCT_FUN_FUN(csring->fun) |
1417 XCT_FUN_CRM_SIG | XCT_FUN_LLEN(skb->len - nh_off) |
1418 XCT_FUN_SHL(nh_len >> 2) | XCT_FUN_SE;
1419
1420 switch (ip_hdr(skb)->protocol) {
1421 case IPPROTO_TCP:
1422 fund |= XCT_FUN_SIG_TCP4;
1423 /* TCP checksum is 16 bytes into the header */
1424 cs_dest = map[0] + skb_transport_offset(skb) + 16;
1425 break;
1426 case IPPROTO_UDP:
1427 fund |= XCT_FUN_SIG_UDP4;
1428 /* UDP checksum is 6 bytes into the header */
1429 cs_dest = map[0] + skb_transport_offset(skb) + 6;
1430 break;
1431 default:
1432 BUG();
1433 }
1434
1435 /* Do the checksum offloaded */
1436 fill = csring->next_to_fill;
1437 hdr = fill;
1438
1439 CS_DESC(csring, fill++) = fund;
1440 /* Room for 8BRES. Checksum result is really 2 bytes into it */
1441 csdma = csring->chan.ring_dma + (fill & (CS_RING_SIZE-1)) * 8 + 2;
1442 CS_DESC(csring, fill++) = 0;
1443
1444 CS_DESC(csring, fill) = XCT_PTR_LEN(map_size[0]-nh_off) | XCT_PTR_ADDR(map[0]+nh_off);
1445 for (i = 1; i <= nfrags; i++)
1446 CS_DESC(csring, fill+i) = XCT_PTR_LEN(map_size[i]) | XCT_PTR_ADDR(map[i]);
1447
1448 fill += i;
1449 if (fill & 1)
1450 fill++;
1451
1452 /* Copy the result into the TCP packet */
1453 cpyhdr = fill;
1454 CS_DESC(csring, fill++) = XCT_FUN_O | XCT_FUN_FUN(csring->fun) |
1455 XCT_FUN_LLEN(2) | XCT_FUN_SE;
1456 CS_DESC(csring, fill++) = XCT_PTR_LEN(2) | XCT_PTR_ADDR(cs_dest) | XCT_PTR_T;
1457 CS_DESC(csring, fill++) = XCT_PTR_LEN(2) | XCT_PTR_ADDR(csdma);
1458 fill++;
1459
1460 evt = !csring->last_event;
1461 csring->last_event = evt;
1462
1463 /* Event handshaking with MAC TX */
1464 CS_DESC(csring, fill++) = CTRL_CMD_T | CTRL_CMD_META_EVT | CTRL_CMD_O |
1465 CTRL_CMD_ETYPE_SET | CTRL_CMD_REG(csring->events[evt]);
1466 CS_DESC(csring, fill++) = 0;
1467 CS_DESC(csring, fill++) = CTRL_CMD_T | CTRL_CMD_META_EVT | CTRL_CMD_O |
1468 CTRL_CMD_ETYPE_WCLR | CTRL_CMD_REG(csring->events[!evt]);
1469 CS_DESC(csring, fill++) = 0;
1470 csring->next_to_fill = fill & (CS_RING_SIZE-1);
1471
1472 cs_size = fill - hdr;
1473 write_dma_reg(PAS_DMA_TXCHAN_INCR(csring->chan.chno), (cs_size) >> 1);
1474
1475 /* TX-side event handshaking */
1476 fill = txring->next_to_fill;
1477 TX_DESC(txring, fill++) = CTRL_CMD_T | CTRL_CMD_META_EVT | CTRL_CMD_O |
1478 CTRL_CMD_ETYPE_WSET | CTRL_CMD_REG(csring->events[evt]);
1479 TX_DESC(txring, fill++) = 0;
1480 TX_DESC(txring, fill++) = CTRL_CMD_T | CTRL_CMD_META_EVT | CTRL_CMD_O |
1481 CTRL_CMD_ETYPE_CLR | CTRL_CMD_REG(csring->events[!evt]);
1482 TX_DESC(txring, fill++) = 0;
1483 txring->next_to_fill = fill;
1484
1485 write_dma_reg(PAS_DMA_TXCHAN_INCR(txring->chan.chno), 2);
1486
1487 return;
1488}
1489
1302static int pasemi_mac_start_tx(struct sk_buff *skb, struct net_device *dev) 1490static int pasemi_mac_start_tx(struct sk_buff *skb, struct net_device *dev)
1303{ 1491{
1304 struct pasemi_mac *mac = netdev_priv(dev); 1492 struct pasemi_mac * const mac = netdev_priv(dev);
1305 struct pasemi_mac_txring *txring; 1493 struct pasemi_mac_txring * const txring = tx_ring(mac);
1306 u64 dflags, mactx; 1494 struct pasemi_mac_csring *csring;
1495 u64 dflags = 0;
1496 u64 mactx;
1307 dma_addr_t map[MAX_SKB_FRAGS+1]; 1497 dma_addr_t map[MAX_SKB_FRAGS+1];
1308 unsigned int map_size[MAX_SKB_FRAGS+1]; 1498 unsigned int map_size[MAX_SKB_FRAGS+1];
1309 unsigned long flags; 1499 unsigned long flags;
1310 int i, nfrags; 1500 int i, nfrags;
1311 int fill; 1501 int fill;
1502 const int nh_off = skb_network_offset(skb);
1503 const int nh_len = skb_network_header_len(skb);
1312 1504
1313 dflags = XCT_MACTX_O | XCT_MACTX_ST | XCT_MACTX_CRC_PAD; 1505 prefetch(&txring->ring_info);
1314
1315 if (skb->ip_summed == CHECKSUM_PARTIAL) {
1316 const unsigned char *nh = skb_network_header(skb);
1317 1506
1318 switch (ip_hdr(skb)->protocol) { 1507 dflags = XCT_MACTX_O | XCT_MACTX_ST | XCT_MACTX_CRC_PAD;
1319 case IPPROTO_TCP:
1320 dflags |= XCT_MACTX_CSUM_TCP;
1321 dflags |= XCT_MACTX_IPH(skb_network_header_len(skb) >> 2);
1322 dflags |= XCT_MACTX_IPO(nh - skb->data);
1323 break;
1324 case IPPROTO_UDP:
1325 dflags |= XCT_MACTX_CSUM_UDP;
1326 dflags |= XCT_MACTX_IPH(skb_network_header_len(skb) >> 2);
1327 dflags |= XCT_MACTX_IPO(nh - skb->data);
1328 break;
1329 }
1330 }
1331 1508
1332 nfrags = skb_shinfo(skb)->nr_frags; 1509 nfrags = skb_shinfo(skb)->nr_frags;
1333 1510
@@ -1350,24 +1527,46 @@ static int pasemi_mac_start_tx(struct sk_buff *skb, struct net_device *dev)
1350 } 1527 }
1351 } 1528 }
1352 1529
1353 mactx = dflags | XCT_MACTX_LLEN(skb->len); 1530 if (skb->ip_summed == CHECKSUM_PARTIAL && skb->len <= 1540) {
1531 switch (ip_hdr(skb)->protocol) {
1532 case IPPROTO_TCP:
1533 dflags |= XCT_MACTX_CSUM_TCP;
1534 dflags |= XCT_MACTX_IPH(nh_len >> 2);
1535 dflags |= XCT_MACTX_IPO(nh_off);
1536 break;
1537 case IPPROTO_UDP:
1538 dflags |= XCT_MACTX_CSUM_UDP;
1539 dflags |= XCT_MACTX_IPH(nh_len >> 2);
1540 dflags |= XCT_MACTX_IPO(nh_off);
1541 break;
1542 default:
1543 WARN_ON(1);
1544 }
1545 }
1354 1546
1355 txring = tx_ring(mac); 1547 mactx = dflags | XCT_MACTX_LLEN(skb->len);
1356 1548
1357 spin_lock_irqsave(&txring->lock, flags); 1549 spin_lock_irqsave(&txring->lock, flags);
1358 1550
1359 fill = txring->next_to_fill;
1360
1361 /* Avoid stepping on the same cache line that the DMA controller 1551 /* Avoid stepping on the same cache line that the DMA controller
1362 * is currently about to send, so leave at least 8 words available. 1552 * is currently about to send, so leave at least 8 words available.
1363 * Total free space needed is mactx + fragments + 8 1553 * Total free space needed is mactx + fragments + 8
1364 */ 1554 */
1365 if (RING_AVAIL(txring) < nfrags + 10) { 1555 if (RING_AVAIL(txring) < nfrags + 14) {
1366 /* no room -- stop the queue and wait for tx intr */ 1556 /* no room -- stop the queue and wait for tx intr */
1367 netif_stop_queue(dev); 1557 netif_stop_queue(dev);
1368 goto out_err; 1558 goto out_err;
1369 } 1559 }
1370 1560
1561 /* Queue up checksum + event descriptors, if needed */
1562 if (mac->num_cs && skb->ip_summed == CHECKSUM_PARTIAL && skb->len > 1540) {
1563 csring = mac->cs[mac->last_cs];
1564 mac->last_cs = (mac->last_cs + 1) % mac->num_cs;
1565
1566 pasemi_mac_queue_csdesc(skb, map, map_size, txring, csring);
1567 }
1568
1569 fill = txring->next_to_fill;
1371 TX_DESC(txring, fill) = mactx; 1570 TX_DESC(txring, fill) = mactx;
1372 TX_DESC_INFO(txring, fill).dma = nfrags; 1571 TX_DESC_INFO(txring, fill).dma = nfrags;
1373 fill++; 1572 fill++;
@@ -1445,8 +1644,9 @@ static int pasemi_mac_change_mtu(struct net_device *dev, int new_mtu)
1445{ 1644{
1446 struct pasemi_mac *mac = netdev_priv(dev); 1645 struct pasemi_mac *mac = netdev_priv(dev);
1447 unsigned int reg; 1646 unsigned int reg;
1448 unsigned int rcmdsta; 1647 unsigned int rcmdsta = 0;
1449 int running; 1648 int running;
1649 int ret = 0;
1450 1650
1451 if (new_mtu < PE_MIN_MTU || new_mtu > PE_MAX_MTU) 1651 if (new_mtu < PE_MIN_MTU || new_mtu > PE_MAX_MTU)
1452 return -EINVAL; 1652 return -EINVAL;
@@ -1468,6 +1668,16 @@ static int pasemi_mac_change_mtu(struct net_device *dev, int new_mtu)
1468 pasemi_mac_pause_rxint(mac); 1668 pasemi_mac_pause_rxint(mac);
1469 pasemi_mac_clean_rx(rx_ring(mac), RX_RING_SIZE); 1669 pasemi_mac_clean_rx(rx_ring(mac), RX_RING_SIZE);
1470 pasemi_mac_free_rx_buffers(mac); 1670 pasemi_mac_free_rx_buffers(mac);
1671
1672 }
1673
1674 /* Setup checksum channels if large MTU and none already allocated */
1675 if (new_mtu > 1500 && !mac->num_cs) {
1676 pasemi_mac_setup_csrings(mac);
1677 if (!mac->num_cs) {
1678 ret = -ENOMEM;
1679 goto out;
1680 }
1471 } 1681 }
1472 1682
1473 /* Change maxf, i.e. what size frames are accepted. 1683 /* Change maxf, i.e. what size frames are accepted.
@@ -1482,6 +1692,7 @@ static int pasemi_mac_change_mtu(struct net_device *dev, int new_mtu)
1482 /* MTU + ETH_HLEN + VLAN_HLEN + 2 64B cachelines */ 1692 /* MTU + ETH_HLEN + VLAN_HLEN + 2 64B cachelines */
1483 mac->bufsz = new_mtu + ETH_HLEN + ETH_FCS_LEN + LOCAL_SKB_ALIGN + 128; 1693 mac->bufsz = new_mtu + ETH_HLEN + ETH_FCS_LEN + LOCAL_SKB_ALIGN + 128;
1484 1694
1695out:
1485 if (running) { 1696 if (running) {
1486 write_dma_reg(PAS_DMA_RXINT_RCMDSTA(mac->dma_if), 1697 write_dma_reg(PAS_DMA_RXINT_RCMDSTA(mac->dma_if),
1487 rcmdsta | PAS_DMA_RXINT_RCMDSTA_EN); 1698 rcmdsta | PAS_DMA_RXINT_RCMDSTA_EN);
@@ -1494,7 +1705,7 @@ static int pasemi_mac_change_mtu(struct net_device *dev, int new_mtu)
1494 pasemi_mac_intf_enable(mac); 1705 pasemi_mac_intf_enable(mac);
1495 } 1706 }
1496 1707
1497 return 0; 1708 return ret;
1498} 1709}
1499 1710
1500static int __devinit 1711static int __devinit
@@ -1528,7 +1739,7 @@ pasemi_mac_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
1528 netif_napi_add(dev, &mac->napi, pasemi_mac_poll, 64); 1739 netif_napi_add(dev, &mac->napi, pasemi_mac_poll, 64);
1529 1740
1530 dev->features = NETIF_F_IP_CSUM | NETIF_F_LLTX | NETIF_F_SG | 1741 dev->features = NETIF_F_IP_CSUM | NETIF_F_LLTX | NETIF_F_SG |
1531 NETIF_F_HIGHDMA; 1742 NETIF_F_HIGHDMA | NETIF_F_GSO;
1532 1743
1533 mac->lro_mgr.max_aggr = LRO_MAX_AGGR; 1744 mac->lro_mgr.max_aggr = LRO_MAX_AGGR;
1534 mac->lro_mgr.max_desc = MAX_LRO_DESCRIPTORS; 1745 mac->lro_mgr.max_desc = MAX_LRO_DESCRIPTORS;
@@ -1590,6 +1801,7 @@ pasemi_mac_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
1590 mac->bufsz = dev->mtu + ETH_HLEN + ETH_FCS_LEN + LOCAL_SKB_ALIGN + 128; 1801 mac->bufsz = dev->mtu + ETH_HLEN + ETH_FCS_LEN + LOCAL_SKB_ALIGN + 128;
1591 1802
1592 dev->change_mtu = pasemi_mac_change_mtu; 1803 dev->change_mtu = pasemi_mac_change_mtu;
1804 dev->ethtool_ops = &pasemi_mac_ethtool_ops;
1593 1805
1594 if (err) 1806 if (err)
1595 goto out; 1807 goto out;
diff --git a/drivers/net/pasemi_mac.h b/drivers/net/pasemi_mac.h
index 99e7b9329a6f..1a115ec60b53 100644
--- a/drivers/net/pasemi_mac.h
+++ b/drivers/net/pasemi_mac.h
@@ -26,7 +26,14 @@
26#include <linux/spinlock.h> 26#include <linux/spinlock.h>
27#include <linux/phy.h> 27#include <linux/phy.h>
28 28
29/* Must be a power of two */
30#define RX_RING_SIZE 2048
31#define TX_RING_SIZE 4096
32#define CS_RING_SIZE (TX_RING_SIZE*2)
33
34
29#define MAX_LRO_DESCRIPTORS 8 35#define MAX_LRO_DESCRIPTORS 8
36#define MAX_CS 2
30 37
31struct pasemi_mac_txring { 38struct pasemi_mac_txring {
32 struct pasemi_dmachan chan; /* Must be first */ 39 struct pasemi_dmachan chan; /* Must be first */
@@ -51,6 +58,15 @@ struct pasemi_mac_rxring {
51 struct pasemi_mac *mac; /* Needed in intr handler */ 58 struct pasemi_mac *mac; /* Needed in intr handler */
52}; 59};
53 60
61struct pasemi_mac_csring {
62 struct pasemi_dmachan chan;
63 unsigned int size;
64 unsigned int next_to_fill;
65 int events[2];
66 int last_event;
67 int fun;
68};
69
54struct pasemi_mac { 70struct pasemi_mac {
55 struct net_device *netdev; 71 struct net_device *netdev;
56 struct pci_dev *pdev; 72 struct pci_dev *pdev;
@@ -60,10 +76,12 @@ struct pasemi_mac {
60 struct napi_struct napi; 76 struct napi_struct napi;
61 77
62 int bufsz; /* RX ring buffer size */ 78 int bufsz; /* RX ring buffer size */
79 int last_cs;
80 int num_cs;
81 u32 dma_if;
63 u8 type; 82 u8 type;
64#define MAC_TYPE_GMAC 1 83#define MAC_TYPE_GMAC 1
65#define MAC_TYPE_XAUI 2 84#define MAC_TYPE_XAUI 2
66 u32 dma_if;
67 85
68 u8 mac_addr[6]; 86 u8 mac_addr[6];
69 87
@@ -74,6 +92,7 @@ struct pasemi_mac {
74 92
75 struct pasemi_mac_txring *tx; 93 struct pasemi_mac_txring *tx;
76 struct pasemi_mac_rxring *rx; 94 struct pasemi_mac_rxring *rx;
95 struct pasemi_mac_csring *cs[MAX_CS];
77 char tx_irq_name[10]; /* "eth%d tx" */ 96 char tx_irq_name[10]; /* "eth%d tx" */
78 char rx_irq_name[10]; /* "eth%d rx" */ 97 char rx_irq_name[10]; /* "eth%d rx" */
79 int link; 98 int link;
@@ -90,6 +109,16 @@ struct pasemi_mac_buffer {
90 dma_addr_t dma; 109 dma_addr_t dma;
91}; 110};
92 111
112#define TX_DESC(tx, num) ((tx)->chan.ring_virt[(num) & (TX_RING_SIZE-1)])
113#define TX_DESC_INFO(tx, num) ((tx)->ring_info[(num) & (TX_RING_SIZE-1)])
114#define RX_DESC(rx, num) ((rx)->chan.ring_virt[(num) & (RX_RING_SIZE-1)])
115#define RX_DESC_INFO(rx, num) ((rx)->ring_info[(num) & (RX_RING_SIZE-1)])
116#define RX_BUFF(rx, num) ((rx)->buffers[(num) & (RX_RING_SIZE-1)])
117#define CS_DESC(cs, num) ((cs)->chan.ring_virt[(num) & (CS_RING_SIZE-1)])
118
119#define RING_USED(ring) (((ring)->next_to_fill - (ring)->next_to_clean) \
120 & ((ring)->size - 1))
121#define RING_AVAIL(ring) ((ring->size) - RING_USED(ring))
93 122
94/* PCI register offsets and formats */ 123/* PCI register offsets and formats */
95 124
@@ -101,6 +130,7 @@ enum {
101 PAS_MAC_CFG_ADR0 = 0x8c, 130 PAS_MAC_CFG_ADR0 = 0x8c,
102 PAS_MAC_CFG_ADR1 = 0x90, 131 PAS_MAC_CFG_ADR1 = 0x90,
103 PAS_MAC_CFG_TXP = 0x98, 132 PAS_MAC_CFG_TXP = 0x98,
133 PAS_MAC_CFG_RMON = 0x100,
104 PAS_MAC_IPC_CHNL = 0x208, 134 PAS_MAC_IPC_CHNL = 0x208,
105}; 135};
106 136
@@ -172,6 +202,8 @@ enum {
172#define PAS_MAC_CFG_TXP_TIFG(x) (((x) << PAS_MAC_CFG_TXP_TIFG_S) & \ 202#define PAS_MAC_CFG_TXP_TIFG(x) (((x) << PAS_MAC_CFG_TXP_TIFG_S) & \
173 PAS_MAC_CFG_TXP_TIFG_M) 203 PAS_MAC_CFG_TXP_TIFG_M)
174 204
205#define PAS_MAC_RMON(r) (0x100+(r)*4)
206
175#define PAS_MAC_IPC_CHNL_DCHNO_M 0x003f0000 207#define PAS_MAC_IPC_CHNL_DCHNO_M 0x003f0000
176#define PAS_MAC_IPC_CHNL_DCHNO_S 16 208#define PAS_MAC_IPC_CHNL_DCHNO_S 16
177#define PAS_MAC_IPC_CHNL_DCHNO(x) (((x) << PAS_MAC_IPC_CHNL_DCHNO_S) & \ 209#define PAS_MAC_IPC_CHNL_DCHNO(x) (((x) << PAS_MAC_IPC_CHNL_DCHNO_S) & \
@@ -181,4 +213,5 @@ enum {
181#define PAS_MAC_IPC_CHNL_BCH(x) (((x) << PAS_MAC_IPC_CHNL_BCH_S) & \ 213#define PAS_MAC_IPC_CHNL_BCH(x) (((x) << PAS_MAC_IPC_CHNL_BCH_S) & \
182 PAS_MAC_IPC_CHNL_BCH_M) 214 PAS_MAC_IPC_CHNL_BCH_M)
183 215
216
184#endif /* PASEMI_MAC_H */ 217#endif /* PASEMI_MAC_H */
diff --git a/drivers/net/pasemi_mac_ethtool.c b/drivers/net/pasemi_mac_ethtool.c
new file mode 100644
index 000000000000..5e8df3afea64
--- /dev/null
+++ b/drivers/net/pasemi_mac_ethtool.c
@@ -0,0 +1,159 @@
1/*
2 * Copyright (C) 2006-2008 PA Semi, Inc
3 *
4 * Ethtool hooks for the PA Semi PWRficient onchip 1G/10G Ethernet MACs
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19
20
21#include <linux/netdevice.h>
22#include <linux/ethtool.h>
23#include <linux/pci.h>
24#include <linux/inet_lro.h>
25
26#include <asm/pasemi_dma.h>
27#include "pasemi_mac.h"
28
29static struct {
30 const char str[ETH_GSTRING_LEN];
31} ethtool_stats_keys[] = {
32 { "rx-drops" },
33 { "rx-bytes" },
34 { "rx-packets" },
35 { "rx-broadcast-packets" },
36 { "rx-multicast-packets" },
37 { "rx-crc-errors" },
38 { "rx-undersize-errors" },
39 { "rx-oversize-errors" },
40 { "rx-short-fragment-errors" },
41 { "rx-jabber-errors" },
42 { "rx-64-byte-packets" },
43 { "rx-65-127-byte-packets" },
44 { "rx-128-255-byte-packets" },
45 { "rx-256-511-byte-packets" },
46 { "rx-512-1023-byte-packets" },
47 { "rx-1024-1518-byte-packets" },
48 { "rx-pause-frames" },
49 { "tx-bytes" },
50 { "tx-packets" },
51 { "tx-broadcast-packets" },
52 { "tx-multicast-packets" },
53 { "tx-collisions" },
54 { "tx-late-collisions" },
55 { "tx-excessive-collisions" },
56 { "tx-crc-errors" },
57 { "tx-undersize-errors" },
58 { "tx-oversize-errors" },
59 { "tx-64-byte-packets" },
60 { "tx-65-127-byte-packets" },
61 { "tx-128-255-byte-packets" },
62 { "tx-256-511-byte-packets" },
63 { "tx-512-1023-byte-packets" },
64 { "tx-1024-1518-byte-packets" },
65};
66
67static int
68pasemi_mac_ethtool_get_settings(struct net_device *netdev,
69 struct ethtool_cmd *cmd)
70{
71 struct pasemi_mac *mac = netdev_priv(netdev);
72 struct phy_device *phydev = mac->phydev;
73
74 return phy_ethtool_gset(phydev, cmd);
75}
76
77static void
78pasemi_mac_ethtool_get_drvinfo(struct net_device *netdev,
79 struct ethtool_drvinfo *drvinfo)
80{
81 struct pasemi_mac *mac;
82 mac = netdev_priv(netdev);
83
84 /* clear and fill out info */
85 memset(drvinfo, 0, sizeof(struct ethtool_drvinfo));
86 strncpy(drvinfo->driver, "pasemi_mac", 12);
87 strcpy(drvinfo->version, "N/A");
88 strcpy(drvinfo->fw_version, "N/A");
89 strncpy(drvinfo->bus_info, pci_name(mac->pdev), 32);
90}
91
92static u32
93pasemi_mac_ethtool_get_msglevel(struct net_device *netdev)
94{
95 struct pasemi_mac *mac = netdev_priv(netdev);
96 return mac->msg_enable;
97}
98
99static void
100pasemi_mac_ethtool_set_msglevel(struct net_device *netdev,
101 u32 level)
102{
103 struct pasemi_mac *mac = netdev_priv(netdev);
104 mac->msg_enable = level;
105}
106
107
108static void
109pasemi_mac_ethtool_get_ringparam(struct net_device *netdev,
110 struct ethtool_ringparam *ering)
111{
112 struct pasemi_mac *mac = netdev->priv;
113
114 ering->tx_max_pending = TX_RING_SIZE/2;
115 ering->tx_pending = RING_USED(mac->tx)/2;
116 ering->rx_max_pending = RX_RING_SIZE/4;
117 ering->rx_pending = RING_USED(mac->rx)/4;
118}
119
120static int pasemi_mac_get_sset_count(struct net_device *netdev, int sset)
121{
122 switch (sset) {
123 case ETH_SS_STATS:
124 return ARRAY_SIZE(ethtool_stats_keys);
125 default:
126 return -EOPNOTSUPP;
127 }
128}
129
130static void pasemi_mac_get_ethtool_stats(struct net_device *netdev,
131 struct ethtool_stats *stats, u64 *data)
132{
133 struct pasemi_mac *mac = netdev->priv;
134 int i;
135
136 data[0] = pasemi_read_dma_reg(PAS_DMA_RXINT_RCMDSTA(mac->dma_if))
137 >> PAS_DMA_RXINT_RCMDSTA_DROPS_S;
138 for (i = 0; i < 32; i++)
139 data[1+i] = pasemi_read_mac_reg(mac->dma_if, PAS_MAC_RMON(i));
140}
141
142static void pasemi_mac_get_strings(struct net_device *netdev, u32 stringset,
143 u8 *data)
144{
145 memcpy(data, ethtool_stats_keys, sizeof(ethtool_stats_keys));
146}
147
148const struct ethtool_ops pasemi_mac_ethtool_ops = {
149 .get_settings = pasemi_mac_ethtool_get_settings,
150 .get_drvinfo = pasemi_mac_ethtool_get_drvinfo,
151 .get_msglevel = pasemi_mac_ethtool_get_msglevel,
152 .set_msglevel = pasemi_mac_ethtool_set_msglevel,
153 .get_link = ethtool_op_get_link,
154 .get_ringparam = pasemi_mac_ethtool_get_ringparam,
155 .get_strings = pasemi_mac_get_strings,
156 .get_sset_count = pasemi_mac_get_sset_count,
157 .get_ethtool_stats = pasemi_mac_get_ethtool_stats,
158};
159
diff --git a/include/asm-powerpc/Kbuild b/include/asm-powerpc/Kbuild
index 5f640e542475..7381916dfcbb 100644
--- a/include/asm-powerpc/Kbuild
+++ b/include/asm-powerpc/Kbuild
@@ -1,5 +1,6 @@
1include include/asm-generic/Kbuild.asm 1include include/asm-generic/Kbuild.asm
2 2
3header-y += a.out.h
3header-y += auxvec.h 4header-y += auxvec.h
4header-y += ioctls.h 5header-y += ioctls.h
5header-y += mman.h 6header-y += mman.h
@@ -23,7 +24,6 @@ header-y += sigcontext.h
23header-y += statfs.h 24header-y += statfs.h
24header-y += ps3fb.h 25header-y += ps3fb.h
25 26
26unifdef-y += a.out.h
27unifdef-y += asm-compat.h 27unifdef-y += asm-compat.h
28unifdef-y += bootx.h 28unifdef-y += bootx.h
29unifdef-y += byteorder.h 29unifdef-y += byteorder.h
diff --git a/include/asm-powerpc/abs_addr.h b/include/asm-powerpc/abs_addr.h
index 4aa220718b19..98324c5a8286 100644
--- a/include/asm-powerpc/abs_addr.h
+++ b/include/asm-powerpc/abs_addr.h
@@ -12,10 +12,11 @@
12 * 2 of the License, or (at your option) any later version. 12 * 2 of the License, or (at your option) any later version.
13 */ 13 */
14 14
15#include <linux/lmb.h>
16
15#include <asm/types.h> 17#include <asm/types.h>
16#include <asm/page.h> 18#include <asm/page.h>
17#include <asm/prom.h> 19#include <asm/prom.h>
18#include <asm/lmb.h>
19#include <asm/firmware.h> 20#include <asm/firmware.h>
20 21
21struct mschunks_map { 22struct mschunks_map {
diff --git a/include/asm-powerpc/cputhreads.h b/include/asm-powerpc/cputhreads.h
index 8485c28b5f47..fb11b0c459b8 100644
--- a/include/asm-powerpc/cputhreads.h
+++ b/include/asm-powerpc/cputhreads.h
@@ -35,7 +35,7 @@ static inline cpumask_t cpu_thread_mask_to_cores(cpumask_t threads)
35 35
36 res = CPU_MASK_NONE; 36 res = CPU_MASK_NONE;
37 for (i = 0; i < NR_CPUS; i += threads_per_core) { 37 for (i = 0; i < NR_CPUS; i += threads_per_core) {
38 cpus_shift_right(tmp, threads_core_mask, i); 38 cpus_shift_left(tmp, threads_core_mask, i);
39 if (cpus_intersects(threads, tmp)) 39 if (cpus_intersects(threads, tmp))
40 cpu_set(i, res); 40 cpu_set(i, res);
41 } 41 }
diff --git a/include/asm-powerpc/lmb.h b/include/asm-powerpc/lmb.h
index 5d1dc48a0bb8..028184b6a162 100644
--- a/include/asm-powerpc/lmb.h
+++ b/include/asm-powerpc/lmb.h
@@ -1,81 +1,15 @@
1#ifndef _ASM_POWERPC_LMB_H 1#ifndef _ASM_POWERPC_LMB_H
2#define _ASM_POWERPC_LMB_H 2#define _ASM_POWERPC_LMB_H
3#ifdef __KERNEL__
4 3
5/* 4#include <asm/udbg.h>
6 * Definitions for talking to the Open Firmware PROM on
7 * Power Macintosh computers.
8 *
9 * Copyright (C) 2001 Peter Bergner, IBM Corp.
10 *
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation; either version
14 * 2 of the License, or (at your option) any later version.
15 */
16 5
17#include <linux/init.h> 6#define LMB_DBG(fmt...) udbg_printf(fmt)
18#include <asm/prom.h>
19 7
20#define MAX_LMB_REGIONS 128 8#ifdef CONFIG_PPC32
9extern unsigned long __max_low_memory;
10#define LMB_REAL_LIMIT __max_low_memory
11#else
12#define LMB_REAL_LIMIT 0
13#endif
21 14
22struct lmb_property {
23 unsigned long base;
24 unsigned long size;
25};
26
27struct lmb_region {
28 unsigned long cnt;
29 unsigned long size;
30 struct lmb_property region[MAX_LMB_REGIONS+1];
31};
32
33struct lmb {
34 unsigned long debug;
35 unsigned long rmo_size;
36 struct lmb_region memory;
37 struct lmb_region reserved;
38};
39
40extern struct lmb lmb;
41
42extern void __init lmb_init(void);
43extern void __init lmb_analyze(void);
44extern long __init lmb_add(unsigned long base, unsigned long size);
45extern long __init lmb_reserve(unsigned long base, unsigned long size);
46extern unsigned long __init lmb_alloc(unsigned long size, unsigned long align);
47extern unsigned long __init lmb_alloc_base(unsigned long size,
48 unsigned long align, unsigned long max_addr);
49extern unsigned long __init __lmb_alloc_base(unsigned long size,
50 unsigned long align, unsigned long max_addr);
51extern unsigned long __init lmb_phys_mem_size(void);
52extern unsigned long __init lmb_end_of_DRAM(void);
53extern void __init lmb_enforce_memory_limit(unsigned long memory_limit);
54extern int __init lmb_is_reserved(unsigned long addr);
55
56extern void lmb_dump_all(void);
57
58static inline unsigned long
59lmb_size_bytes(struct lmb_region *type, unsigned long region_nr)
60{
61 return type->region[region_nr].size;
62}
63static inline unsigned long
64lmb_size_pages(struct lmb_region *type, unsigned long region_nr)
65{
66 return lmb_size_bytes(type, region_nr) >> PAGE_SHIFT;
67}
68static inline unsigned long
69lmb_start_pfn(struct lmb_region *type, unsigned long region_nr)
70{
71 return type->region[region_nr].base >> PAGE_SHIFT;
72}
73static inline unsigned long
74lmb_end_pfn(struct lmb_region *type, unsigned long region_nr)
75{
76 return lmb_start_pfn(type, region_nr) +
77 lmb_size_pages(type, region_nr);
78}
79
80#endif /* __KERNEL__ */
81#endif /* _ASM_POWERPC_LMB_H */ 15#endif /* _ASM_POWERPC_LMB_H */
diff --git a/include/asm-powerpc/machdep.h b/include/asm-powerpc/machdep.h
index 0872ec228c1e..b95386aed50d 100644
--- a/include/asm-powerpc/machdep.h
+++ b/include/asm-powerpc/machdep.h
@@ -68,6 +68,8 @@ struct machdep_calls {
68 unsigned long vflags, 68 unsigned long vflags,
69 int psize, int ssize); 69 int psize, int ssize);
70 long (*hpte_remove)(unsigned long hpte_group); 70 long (*hpte_remove)(unsigned long hpte_group);
71 void (*hpte_removebolted)(unsigned long ea,
72 int psize, int ssize);
71 void (*flush_hash_range)(unsigned long number, int local); 73 void (*flush_hash_range)(unsigned long number, int local);
72 74
73 /* special for kexec, to be called in real mode, linar mapping is 75 /* special for kexec, to be called in real mode, linar mapping is
diff --git a/include/asm-powerpc/pasemi_dma.h b/include/asm-powerpc/pasemi_dma.h
index b4526ff3a50d..19fd7933e2d9 100644
--- a/include/asm-powerpc/pasemi_dma.h
+++ b/include/asm-powerpc/pasemi_dma.h
@@ -1,5 +1,5 @@
1/* 1/*
2 * Copyright (C) 2006 PA Semi, Inc 2 * Copyright (C) 2006-2008 PA Semi, Inc
3 * 3 *
4 * Hardware register layout and descriptor formats for the on-board 4 * Hardware register layout and descriptor formats for the on-board
5 * DMA engine on PA Semi PWRficient. Used by ethernet, function and security 5 * DMA engine on PA Semi PWRficient. Used by ethernet, function and security
@@ -40,6 +40,11 @@ enum {
40 PAS_DMA_COM_TXSTA = 0x104, /* Transmit Status Register */ 40 PAS_DMA_COM_TXSTA = 0x104, /* Transmit Status Register */
41 PAS_DMA_COM_RXCMD = 0x108, /* Receive Command Register */ 41 PAS_DMA_COM_RXCMD = 0x108, /* Receive Command Register */
42 PAS_DMA_COM_RXSTA = 0x10c, /* Receive Status Register */ 42 PAS_DMA_COM_RXSTA = 0x10c, /* Receive Status Register */
43 PAS_DMA_COM_CFG = 0x114, /* Common config reg */
44 PAS_DMA_TXF_SFLG0 = 0x140, /* Set flags */
45 PAS_DMA_TXF_SFLG1 = 0x144, /* Set flags */
46 PAS_DMA_TXF_CFLG0 = 0x148, /* Set flags */
47 PAS_DMA_TXF_CFLG1 = 0x14c, /* Set flags */
43}; 48};
44 49
45 50
@@ -123,11 +128,16 @@ enum {
123#define PAS_DMA_TXCHAN_TCMDSTA_DA 0x00000100 128#define PAS_DMA_TXCHAN_TCMDSTA_DA 0x00000100
124#define PAS_DMA_TXCHAN_CFG(c) (0x304+(c)*_PAS_DMA_TXCHAN_STRIDE) 129#define PAS_DMA_TXCHAN_CFG(c) (0x304+(c)*_PAS_DMA_TXCHAN_STRIDE)
125#define PAS_DMA_TXCHAN_CFG_TY_IFACE 0x00000000 /* Type = interface */ 130#define PAS_DMA_TXCHAN_CFG_TY_IFACE 0x00000000 /* Type = interface */
131#define PAS_DMA_TXCHAN_CFG_TY_COPY 0x00000001 /* Type = copy only */
132#define PAS_DMA_TXCHAN_CFG_TY_FUNC 0x00000002 /* Type = function */
133#define PAS_DMA_TXCHAN_CFG_TY_XOR 0x00000003 /* Type = xor only */
126#define PAS_DMA_TXCHAN_CFG_TATTR_M 0x0000003c 134#define PAS_DMA_TXCHAN_CFG_TATTR_M 0x0000003c
127#define PAS_DMA_TXCHAN_CFG_TATTR_S 2 135#define PAS_DMA_TXCHAN_CFG_TATTR_S 2
128#define PAS_DMA_TXCHAN_CFG_TATTR(x) (((x) << PAS_DMA_TXCHAN_CFG_TATTR_S) & \ 136#define PAS_DMA_TXCHAN_CFG_TATTR(x) (((x) << PAS_DMA_TXCHAN_CFG_TATTR_S) & \
129 PAS_DMA_TXCHAN_CFG_TATTR_M) 137 PAS_DMA_TXCHAN_CFG_TATTR_M)
130#define PAS_DMA_TXCHAN_CFG_WT_M 0x000001c0 138#define PAS_DMA_TXCHAN_CFG_LPDQ 0x00000800
139#define PAS_DMA_TXCHAN_CFG_LPSQ 0x00000400
140#define PAS_DMA_TXCHAN_CFG_WT_M 0x000003c0
131#define PAS_DMA_TXCHAN_CFG_WT_S 6 141#define PAS_DMA_TXCHAN_CFG_WT_S 6
132#define PAS_DMA_TXCHAN_CFG_WT(x) (((x) << PAS_DMA_TXCHAN_CFG_WT_S) & \ 142#define PAS_DMA_TXCHAN_CFG_WT(x) (((x) << PAS_DMA_TXCHAN_CFG_WT_S) & \
133 PAS_DMA_TXCHAN_CFG_WT_M) 143 PAS_DMA_TXCHAN_CFG_WT_M)
@@ -394,11 +404,62 @@ enum {
394 XCT_COPY_LLEN_M) 404 XCT_COPY_LLEN_M)
395#define XCT_COPY_SE 0x0000000000000001ull 405#define XCT_COPY_SE 0x0000000000000001ull
396 406
407/* Function descriptor fields */
408#define XCT_FUN_T 0x8000000000000000ull
409#define XCT_FUN_ST 0x4000000000000000ull
410#define XCT_FUN_RR_M 0x3000000000000000ull
411#define XCT_FUN_RR_NORES 0x0000000000000000ull
412#define XCT_FUN_RR_8BRES 0x1000000000000000ull
413#define XCT_FUN_RR_24BRES 0x2000000000000000ull
414#define XCT_FUN_RR_40BRES 0x3000000000000000ull
415#define XCT_FUN_I 0x0800000000000000ull
416#define XCT_FUN_O 0x0400000000000000ull
417#define XCT_FUN_E 0x0200000000000000ull
418#define XCT_FUN_FUN_M 0x01c0000000000000ull
419#define XCT_FUN_FUN_S 54
420#define XCT_FUN_FUN(x) ((((long)(x)) << XCT_FUN_FUN_S) & XCT_FUN_FUN_M)
421#define XCT_FUN_CRM_M 0x0038000000000000ull
422#define XCT_FUN_CRM_NOP 0x0000000000000000ull
423#define XCT_FUN_CRM_SIG 0x0008000000000000ull
424#define XCT_FUN_LLEN_M 0x0007ffff00000000ull
425#define XCT_FUN_LLEN_S 32
426#define XCT_FUN_LLEN(x) ((((long)(x)) << XCT_FUN_LLEN_S) & XCT_FUN_LLEN_M)
427#define XCT_FUN_SHL_M 0x00000000f8000000ull
428#define XCT_FUN_SHL_S 27
429#define XCT_FUN_SHL(x) ((((long)(x)) << XCT_FUN_SHL_S) & XCT_FUN_SHL_M)
430#define XCT_FUN_CHL_M 0x0000000007c00000ull
431#define XCT_FUN_HSZ_M 0x00000000003c0000ull
432#define XCT_FUN_ALG_M 0x0000000000038000ull
433#define XCT_FUN_HP 0x0000000000004000ull
434#define XCT_FUN_BCM_M 0x0000000000003800ull
435#define XCT_FUN_BCP_M 0x0000000000000600ull
436#define XCT_FUN_SIG_M 0x00000000000001f0ull
437#define XCT_FUN_SIG_TCP4 0x0000000000000140ull
438#define XCT_FUN_SIG_TCP6 0x0000000000000150ull
439#define XCT_FUN_SIG_UDP4 0x0000000000000160ull
440#define XCT_FUN_SIG_UDP6 0x0000000000000170ull
441#define XCT_FUN_A 0x0000000000000008ull
442#define XCT_FUN_C 0x0000000000000004ull
443#define XCT_FUN_AL2 0x0000000000000002ull
444#define XCT_FUN_SE 0x0000000000000001ull
445
446/* Function descriptor 8byte result fields */
447#define XCT_FUNRES_8B_CS_M 0x0000ffff00000000ull
448#define XCT_FUNRES_8B_CS_S 32
449#define XCT_FUNRES_8B_CRC_M 0x00000000ffffffffull
450#define XCT_FUNRES_8B_CRC_S 0
451
397/* Control descriptor fields */ 452/* Control descriptor fields */
398#define CTRL_CMD_T 0x8000000000000000ull 453#define CTRL_CMD_T 0x8000000000000000ull
399#define CTRL_CMD_META_EVT 0x2000000000000000ull 454#define CTRL_CMD_META_EVT 0x2000000000000000ull
400#define CTRL_CMD_O 0x0400000000000000ull 455#define CTRL_CMD_O 0x0400000000000000ull
401#define CTRL_CMD_REG_M 0x000000000000000full 456#define CTRL_CMD_ETYPE_M 0x0038000000000000ull
457#define CTRL_CMD_ETYPE_EXT 0x0000000000000000ull
458#define CTRL_CMD_ETYPE_WSET 0x0020000000000000ull
459#define CTRL_CMD_ETYPE_WCLR 0x0028000000000000ull
460#define CTRL_CMD_ETYPE_SET 0x0030000000000000ull
461#define CTRL_CMD_ETYPE_CLR 0x0038000000000000ull
462#define CTRL_CMD_REG_M 0x000000000000007full
402#define CTRL_CMD_REG_S 0 463#define CTRL_CMD_REG_S 0
403#define CTRL_CMD_REG(x) ((((long)(x)) << CTRL_CMD_REG_S) & \ 464#define CTRL_CMD_REG(x) ((((long)(x)) << CTRL_CMD_REG_S) & \
404 CTRL_CMD_REG_M) 465 CTRL_CMD_REG_M)
@@ -461,6 +522,16 @@ extern void *pasemi_dma_alloc_buf(struct pasemi_dmachan *chan, int size,
461extern void pasemi_dma_free_buf(struct pasemi_dmachan *chan, int size, 522extern void pasemi_dma_free_buf(struct pasemi_dmachan *chan, int size,
462 dma_addr_t *handle); 523 dma_addr_t *handle);
463 524
525/* Routines to allocate flags (events) for channel syncronization */
526extern int pasemi_dma_alloc_flag(void);
527extern void pasemi_dma_free_flag(int flag);
528extern void pasemi_dma_set_flag(int flag);
529extern void pasemi_dma_clear_flag(int flag);
530
531/* Routines to allocate function engines */
532extern int pasemi_dma_alloc_fun(void);
533extern void pasemi_dma_free_fun(int fun);
534
464/* Initialize the library, must be called before any other functions */ 535/* Initialize the library, must be called before any other functions */
465extern int pasemi_dma_init(void); 536extern int pasemi_dma_init(void);
466 537
diff --git a/include/asm-powerpc/phyp_dump.h b/include/asm-powerpc/phyp_dump.h
new file mode 100644
index 000000000000..209a98913d9d
--- /dev/null
+++ b/include/asm-powerpc/phyp_dump.h
@@ -0,0 +1,45 @@
1/*
2 * Hypervisor-assisted dump
3 *
4 * Linas Vepstas, Manish Ahuja 2008
5 * Copyright 2008 IBM Corp.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version
10 * 2 of the License, or (at your option) any later version.
11 */
12
13#ifndef _PPC64_PHYP_DUMP_H
14#define _PPC64_PHYP_DUMP_H
15
16#ifdef CONFIG_PHYP_DUMP
17
18/* The RMR region will be saved for later dumping
19 * whenever the kernel crashes. Set this to 256MB. */
20#define PHYP_DUMP_RMR_START 0x0
21#define PHYP_DUMP_RMR_END (1UL<<28)
22
23struct phyp_dump {
24 /* Memory that is reserved during very early boot. */
25 unsigned long init_reserve_start;
26 unsigned long init_reserve_size;
27 /* Check status during boot if dump supported, active & present*/
28 unsigned long phyp_dump_at_boot;
29 unsigned long phyp_dump_configured;
30 unsigned long phyp_dump_is_active;
31 /* store cpu & hpte size */
32 unsigned long cpu_state_size;
33 unsigned long hpte_region_size;
34 /* previous scratch area values */
35 unsigned long reserved_scratch_addr;
36 unsigned long reserved_scratch_size;
37};
38
39extern struct phyp_dump *phyp_dump_info;
40
41int early_init_dt_scan_phyp_dump(unsigned long node,
42 const char *uname, int depth, void *data);
43
44#endif /* CONFIG_PHYP_DUMP */
45#endif /* _PPC64_PHYP_DUMP_H */
diff --git a/include/asm-powerpc/sparsemem.h b/include/asm-powerpc/sparsemem.h
index e8b493d52b4f..c5acf4ccf571 100644
--- a/include/asm-powerpc/sparsemem.h
+++ b/include/asm-powerpc/sparsemem.h
@@ -15,6 +15,7 @@
15 15
16#ifdef CONFIG_MEMORY_HOTPLUG 16#ifdef CONFIG_MEMORY_HOTPLUG
17extern void create_section_mapping(unsigned long start, unsigned long end); 17extern void create_section_mapping(unsigned long start, unsigned long end);
18extern void remove_section_mapping(unsigned long start, unsigned long end);
18#ifdef CONFIG_NUMA 19#ifdef CONFIG_NUMA
19extern int hot_add_scn_to_nid(unsigned long scn_addr); 20extern int hot_add_scn_to_nid(unsigned long scn_addr);
20#else 21#else
diff --git a/include/asm-sparc64/lmb.h b/include/asm-sparc64/lmb.h
new file mode 100644
index 000000000000..6a352cbcf520
--- /dev/null
+++ b/include/asm-sparc64/lmb.h
@@ -0,0 +1,10 @@
1#ifndef _SPARC64_LMB_H
2#define _SPARC64_LMB_H
3
4#include <asm/oplib.h>
5
6#define LMB_DBG(fmt...) prom_printf(fmt)
7
8#define LMB_REAL_LIMIT 0
9
10#endif /* !(_SPARC64_LMB_H) */
diff --git a/include/linux/lmb.h b/include/linux/lmb.h
new file mode 100644
index 000000000000..632717c6a2ba
--- /dev/null
+++ b/include/linux/lmb.h
@@ -0,0 +1,83 @@
1#ifndef _LINUX_LMB_H
2#define _LINUX_LMB_H
3#ifdef __KERNEL__
4
5/*
6 * Logical memory blocks.
7 *
8 * Copyright (C) 2001 Peter Bergner, IBM Corp.
9 *
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version
13 * 2 of the License, or (at your option) any later version.
14 */
15
16#include <linux/init.h>
17#include <linux/mm.h>
18
19#define MAX_LMB_REGIONS 128
20
21struct lmb_property {
22 u64 base;
23 u64 size;
24};
25
26struct lmb_region {
27 unsigned long cnt;
28 u64 size;
29 struct lmb_property region[MAX_LMB_REGIONS+1];
30};
31
32struct lmb {
33 unsigned long debug;
34 u64 rmo_size;
35 struct lmb_region memory;
36 struct lmb_region reserved;
37};
38
39extern struct lmb lmb;
40
41extern void __init lmb_init(void);
42extern void __init lmb_analyze(void);
43extern long __init lmb_add(u64 base, u64 size);
44extern long __init lmb_reserve(u64 base, u64 size);
45extern u64 __init lmb_alloc(u64 size, u64 align);
46extern u64 __init lmb_alloc_base(u64 size,
47 u64, u64 max_addr);
48extern u64 __init __lmb_alloc_base(u64 size,
49 u64 align, u64 max_addr);
50extern u64 __init lmb_phys_mem_size(void);
51extern u64 __init lmb_end_of_DRAM(void);
52extern void __init lmb_enforce_memory_limit(u64 memory_limit);
53extern int __init lmb_is_reserved(u64 addr);
54
55extern void lmb_dump_all(void);
56
57static inline u64
58lmb_size_bytes(struct lmb_region *type, unsigned long region_nr)
59{
60 return type->region[region_nr].size;
61}
62static inline u64
63lmb_size_pages(struct lmb_region *type, unsigned long region_nr)
64{
65 return lmb_size_bytes(type, region_nr) >> PAGE_SHIFT;
66}
67static inline u64
68lmb_start_pfn(struct lmb_region *type, unsigned long region_nr)
69{
70 return type->region[region_nr].base >> PAGE_SHIFT;
71}
72static inline u64
73lmb_end_pfn(struct lmb_region *type, unsigned long region_nr)
74{
75 return lmb_start_pfn(type, region_nr) +
76 lmb_size_pages(type, region_nr);
77}
78
79#include <asm/lmb.h>
80
81#endif /* __KERNEL__ */
82
83#endif /* _LINUX_LMB_H */
diff --git a/lib/Kconfig b/lib/Kconfig
index ba3d104994d9..2d53dc092e8b 100644
--- a/lib/Kconfig
+++ b/lib/Kconfig
@@ -141,4 +141,7 @@ config HAS_DMA
141config CHECK_SIGNATURE 141config CHECK_SIGNATURE
142 bool 142 bool
143 143
144config HAVE_LMB
145 boolean
146
144endmenu 147endmenu
diff --git a/lib/Makefile b/lib/Makefile
index 23de261a4c83..61bba16a0a2f 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -70,6 +70,8 @@ obj-$(CONFIG_FAULT_INJECTION) += fault-inject.o
70 70
71lib-$(CONFIG_GENERIC_BUG) += bug.o 71lib-$(CONFIG_GENERIC_BUG) += bug.o
72 72
73obj-$(CONFIG_HAVE_LMB) += lmb.o
74
73hostprogs-y := gen_crc32table 75hostprogs-y := gen_crc32table
74clean-files := crc32table.h 76clean-files := crc32table.h
75 77
diff --git a/arch/powerpc/mm/lmb.c b/lib/lmb.c
index 4ce23bcf8a57..3c43b95fef4a 100644
--- a/arch/powerpc/mm/lmb.c
+++ b/lib/lmb.c
@@ -3,7 +3,7 @@
3 * 3 *
4 * Peter Bergner, IBM Corp. June 2001. 4 * Peter Bergner, IBM Corp. June 2001.
5 * Copyright (C) 2001 Peter Bergner. 5 * Copyright (C) 2001 Peter Bergner.
6 * 6 *
7 * This program is free software; you can redistribute it and/or 7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License 8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 9 * as published by the Free Software Foundation; either version
@@ -13,19 +13,12 @@
13#include <linux/kernel.h> 13#include <linux/kernel.h>
14#include <linux/init.h> 14#include <linux/init.h>
15#include <linux/bitops.h> 15#include <linux/bitops.h>
16#include <asm/types.h> 16#include <linux/lmb.h>
17#include <asm/page.h>
18#include <asm/prom.h>
19#include <asm/lmb.h>
20#ifdef CONFIG_PPC32
21#include "mmu_decl.h" /* for __max_low_memory */
22#endif
23 17
24#undef DEBUG 18#undef DEBUG
25 19
26#ifdef DEBUG 20#ifdef DEBUG
27#include <asm/udbg.h> 21#define DBG(fmt...) LMB_DBG(fmt)
28#define DBG(fmt...) udbg_printf(fmt)
29#else 22#else
30#define DBG(fmt...) 23#define DBG(fmt...)
31#endif 24#endif
@@ -41,33 +34,34 @@ void lmb_dump_all(void)
41 34
42 DBG("lmb_dump_all:\n"); 35 DBG("lmb_dump_all:\n");
43 DBG(" memory.cnt = 0x%lx\n", lmb.memory.cnt); 36 DBG(" memory.cnt = 0x%lx\n", lmb.memory.cnt);
44 DBG(" memory.size = 0x%lx\n", lmb.memory.size); 37 DBG(" memory.size = 0x%llx\n",
38 (unsigned long long)lmb.memory.size);
45 for (i=0; i < lmb.memory.cnt ;i++) { 39 for (i=0; i < lmb.memory.cnt ;i++) {
46 DBG(" memory.region[0x%x].base = 0x%lx\n", 40 DBG(" memory.region[0x%x].base = 0x%llx\n",
47 i, lmb.memory.region[i].base); 41 i, (unsigned long long)lmb.memory.region[i].base);
48 DBG(" .size = 0x%lx\n", 42 DBG(" .size = 0x%llx\n",
49 lmb.memory.region[i].size); 43 (unsigned long long)lmb.memory.region[i].size);
50 } 44 }
51 45
52 DBG("\n reserved.cnt = 0x%lx\n", lmb.reserved.cnt); 46 DBG("\n reserved.cnt = 0x%lx\n", lmb.reserved.cnt);
53 DBG(" reserved.size = 0x%lx\n", lmb.reserved.size); 47 DBG(" reserved.size = 0x%lx\n", lmb.reserved.size);
54 for (i=0; i < lmb.reserved.cnt ;i++) { 48 for (i=0; i < lmb.reserved.cnt ;i++) {
55 DBG(" reserved.region[0x%x].base = 0x%lx\n", 49 DBG(" reserved.region[0x%x].base = 0x%llx\n",
56 i, lmb.reserved.region[i].base); 50 i, (unsigned long long)lmb.reserved.region[i].base);
57 DBG(" .size = 0x%lx\n", 51 DBG(" .size = 0x%llx\n",
58 lmb.reserved.region[i].size); 52 (unsigned long long)lmb.reserved.region[i].size);
59 } 53 }
60#endif /* DEBUG */ 54#endif /* DEBUG */
61} 55}
62 56
63static unsigned long __init lmb_addrs_overlap(unsigned long base1, 57static unsigned long __init lmb_addrs_overlap(u64 base1,
64 unsigned long size1, unsigned long base2, unsigned long size2) 58 u64 size1, u64 base2, u64 size2)
65{ 59{
66 return ((base1 < (base2+size2)) && (base2 < (base1+size1))); 60 return ((base1 < (base2+size2)) && (base2 < (base1+size1)));
67} 61}
68 62
69static long __init lmb_addrs_adjacent(unsigned long base1, unsigned long size1, 63static long __init lmb_addrs_adjacent(u64 base1, u64 size1,
70 unsigned long base2, unsigned long size2) 64 u64 base2, u64 size2)
71{ 65{
72 if (base2 == base1 + size1) 66 if (base2 == base1 + size1)
73 return 1; 67 return 1;
@@ -80,10 +74,10 @@ static long __init lmb_addrs_adjacent(unsigned long base1, unsigned long size1,
80static long __init lmb_regions_adjacent(struct lmb_region *rgn, 74static long __init lmb_regions_adjacent(struct lmb_region *rgn,
81 unsigned long r1, unsigned long r2) 75 unsigned long r1, unsigned long r2)
82{ 76{
83 unsigned long base1 = rgn->region[r1].base; 77 u64 base1 = rgn->region[r1].base;
84 unsigned long size1 = rgn->region[r1].size; 78 u64 size1 = rgn->region[r1].size;
85 unsigned long base2 = rgn->region[r2].base; 79 u64 base2 = rgn->region[r2].base;
86 unsigned long size2 = rgn->region[r2].size; 80 u64 size2 = rgn->region[r2].size;
87 81
88 return lmb_addrs_adjacent(base1, size1, base2, size2); 82 return lmb_addrs_adjacent(base1, size1, base2, size2);
89} 83}
@@ -135,16 +129,21 @@ void __init lmb_analyze(void)
135} 129}
136 130
137/* This routine called with relocation disabled. */ 131/* This routine called with relocation disabled. */
138static long __init lmb_add_region(struct lmb_region *rgn, unsigned long base, 132static long __init lmb_add_region(struct lmb_region *rgn, u64 base, u64 size)
139 unsigned long size)
140{ 133{
141 unsigned long coalesced = 0; 134 unsigned long coalesced = 0;
142 long adjacent, i; 135 long adjacent, i;
143 136
137 if ((rgn->cnt == 1) && (rgn->region[0].size == 0)) {
138 rgn->region[0].base = base;
139 rgn->region[0].size = size;
140 return 0;
141 }
142
144 /* First try and coalesce this LMB with another. */ 143 /* First try and coalesce this LMB with another. */
145 for (i=0; i < rgn->cnt; i++) { 144 for (i=0; i < rgn->cnt; i++) {
146 unsigned long rgnbase = rgn->region[i].base; 145 u64 rgnbase = rgn->region[i].base;
147 unsigned long rgnsize = rgn->region[i].size; 146 u64 rgnsize = rgn->region[i].size;
148 147
149 if ((rgnbase == base) && (rgnsize == size)) 148 if ((rgnbase == base) && (rgnsize == size))
150 /* Already have this region, so we're done */ 149 /* Already have this region, so we're done */
@@ -185,13 +184,18 @@ static long __init lmb_add_region(struct lmb_region *rgn, unsigned long base,
185 break; 184 break;
186 } 185 }
187 } 186 }
187
188 if (base < rgn->region[0].base) {
189 rgn->region[0].base = base;
190 rgn->region[0].size = size;
191 }
188 rgn->cnt++; 192 rgn->cnt++;
189 193
190 return 0; 194 return 0;
191} 195}
192 196
193/* This routine may be called with relocation disabled. */ 197/* This routine may be called with relocation disabled. */
194long __init lmb_add(unsigned long base, unsigned long size) 198long __init lmb_add(u64 base, u64 size)
195{ 199{
196 struct lmb_region *_rgn = &(lmb.memory); 200 struct lmb_region *_rgn = &(lmb.memory);
197 201
@@ -203,7 +207,7 @@ long __init lmb_add(unsigned long base, unsigned long size)
203 207
204} 208}
205 209
206long __init lmb_reserve(unsigned long base, unsigned long size) 210long __init lmb_reserve(u64 base, u64 size)
207{ 211{
208 struct lmb_region *_rgn = &(lmb.reserved); 212 struct lmb_region *_rgn = &(lmb.reserved);
209 213
@@ -212,14 +216,14 @@ long __init lmb_reserve(unsigned long base, unsigned long size)
212 return lmb_add_region(_rgn, base, size); 216 return lmb_add_region(_rgn, base, size);
213} 217}
214 218
215long __init lmb_overlaps_region(struct lmb_region *rgn, unsigned long base, 219long __init lmb_overlaps_region(struct lmb_region *rgn, u64 base,
216 unsigned long size) 220 u64 size)
217{ 221{
218 unsigned long i; 222 unsigned long i;
219 223
220 for (i=0; i < rgn->cnt; i++) { 224 for (i=0; i < rgn->cnt; i++) {
221 unsigned long rgnbase = rgn->region[i].base; 225 u64 rgnbase = rgn->region[i].base;
222 unsigned long rgnsize = rgn->region[i].size; 226 u64 rgnsize = rgn->region[i].size;
223 if ( lmb_addrs_overlap(base,size,rgnbase,rgnsize) ) { 227 if ( lmb_addrs_overlap(base,size,rgnbase,rgnsize) ) {
224 break; 228 break;
225 } 229 }
@@ -228,54 +232,61 @@ long __init lmb_overlaps_region(struct lmb_region *rgn, unsigned long base,
228 return (i < rgn->cnt) ? i : -1; 232 return (i < rgn->cnt) ? i : -1;
229} 233}
230 234
231unsigned long __init lmb_alloc(unsigned long size, unsigned long align) 235u64 __init lmb_alloc(u64 size, u64 align)
232{ 236{
233 return lmb_alloc_base(size, align, LMB_ALLOC_ANYWHERE); 237 return lmb_alloc_base(size, align, LMB_ALLOC_ANYWHERE);
234} 238}
235 239
236unsigned long __init lmb_alloc_base(unsigned long size, unsigned long align, 240u64 __init lmb_alloc_base(u64 size, u64 align, u64 max_addr)
237 unsigned long max_addr)
238{ 241{
239 unsigned long alloc; 242 u64 alloc;
240 243
241 alloc = __lmb_alloc_base(size, align, max_addr); 244 alloc = __lmb_alloc_base(size, align, max_addr);
242 245
243 if (alloc == 0) 246 if (alloc == 0)
244 panic("ERROR: Failed to allocate 0x%lx bytes below 0x%lx.\n", 247 panic("ERROR: Failed to allocate 0x%llx bytes below 0x%llx.\n",
245 size, max_addr); 248 (unsigned long long) size, (unsigned long long) max_addr);
246 249
247 return alloc; 250 return alloc;
248} 251}
249 252
250unsigned long __init __lmb_alloc_base(unsigned long size, unsigned long align, 253static u64 lmb_align_down(u64 addr, u64 size)
251 unsigned long max_addr) 254{
255 return addr & ~(size - 1);
256}
257
258static u64 lmb_align_up(u64 addr, u64 size)
259{
260 return (addr + (size - 1)) & ~(size - 1);
261}
262
263u64 __init __lmb_alloc_base(u64 size, u64 align, u64 max_addr)
252{ 264{
253 long i, j; 265 long i, j;
254 unsigned long base = 0; 266 u64 base = 0;
255 267
256 BUG_ON(0 == size); 268 BUG_ON(0 == size);
257 269
258#ifdef CONFIG_PPC32 270 /* On some platforms, make sure we allocate lowmem */
259 /* On 32-bit, make sure we allocate lowmem */
260 if (max_addr == LMB_ALLOC_ANYWHERE) 271 if (max_addr == LMB_ALLOC_ANYWHERE)
261 max_addr = __max_low_memory; 272 max_addr = LMB_REAL_LIMIT;
262#endif 273
263 for (i = lmb.memory.cnt-1; i >= 0; i--) { 274 for (i = lmb.memory.cnt-1; i >= 0; i--) {
264 unsigned long lmbbase = lmb.memory.region[i].base; 275 u64 lmbbase = lmb.memory.region[i].base;
265 unsigned long lmbsize = lmb.memory.region[i].size; 276 u64 lmbsize = lmb.memory.region[i].size;
266 277
267 if (max_addr == LMB_ALLOC_ANYWHERE) 278 if (max_addr == LMB_ALLOC_ANYWHERE)
268 base = _ALIGN_DOWN(lmbbase + lmbsize - size, align); 279 base = lmb_align_down(lmbbase + lmbsize - size, align);
269 else if (lmbbase < max_addr) { 280 else if (lmbbase < max_addr) {
270 base = min(lmbbase + lmbsize, max_addr); 281 base = min(lmbbase + lmbsize, max_addr);
271 base = _ALIGN_DOWN(base - size, align); 282 base = lmb_align_down(base - size, align);
272 } else 283 } else
273 continue; 284 continue;
274 285
275 while ((lmbbase <= base) && 286 while ((lmbbase <= base) &&
276 ((j = lmb_overlaps_region(&lmb.reserved, base, size)) >= 0) ) 287 ((j = lmb_overlaps_region(&lmb.reserved, base, size)) >= 0) )
277 base = _ALIGN_DOWN(lmb.reserved.region[j].base - size, 288 base = lmb_align_down(lmb.reserved.region[j].base - size,
278 align); 289 align);
279 290
280 if ((base != 0) && (lmbbase <= base)) 291 if ((base != 0) && (lmbbase <= base))
281 break; 292 break;
@@ -284,18 +295,19 @@ unsigned long __init __lmb_alloc_base(unsigned long size, unsigned long align,
284 if (i < 0) 295 if (i < 0)
285 return 0; 296 return 0;
286 297
287 lmb_add_region(&lmb.reserved, base, size); 298 if (lmb_add_region(&lmb.reserved, base, lmb_align_up(size, align)) < 0)
299 return 0;
288 300
289 return base; 301 return base;
290} 302}
291 303
292/* You must call lmb_analyze() before this. */ 304/* You must call lmb_analyze() before this. */
293unsigned long __init lmb_phys_mem_size(void) 305u64 __init lmb_phys_mem_size(void)
294{ 306{
295 return lmb.memory.size; 307 return lmb.memory.size;
296} 308}
297 309
298unsigned long __init lmb_end_of_DRAM(void) 310u64 __init lmb_end_of_DRAM(void)
299{ 311{
300 int idx = lmb.memory.cnt - 1; 312 int idx = lmb.memory.cnt - 1;
301 313
@@ -303,9 +315,10 @@ unsigned long __init lmb_end_of_DRAM(void)
303} 315}
304 316
305/* You must call lmb_analyze() after this. */ 317/* You must call lmb_analyze() after this. */
306void __init lmb_enforce_memory_limit(unsigned long memory_limit) 318void __init lmb_enforce_memory_limit(u64 memory_limit)
307{ 319{
308 unsigned long i, limit; 320 unsigned long i;
321 u64 limit;
309 struct lmb_property *p; 322 struct lmb_property *p;
310 323
311 if (! memory_limit) 324 if (! memory_limit)
@@ -343,13 +356,13 @@ void __init lmb_enforce_memory_limit(unsigned long memory_limit)
343 } 356 }
344} 357}
345 358
346int __init lmb_is_reserved(unsigned long addr) 359int __init lmb_is_reserved(u64 addr)
347{ 360{
348 int i; 361 int i;
349 362
350 for (i = 0; i < lmb.reserved.cnt; i++) { 363 for (i = 0; i < lmb.reserved.cnt; i++) {
351 unsigned long upper = lmb.reserved.region[i].base + 364 u64 upper = lmb.reserved.region[i].base +
352 lmb.reserved.region[i].size - 1; 365 lmb.reserved.region[i].size - 1;
353 if ((addr >= lmb.reserved.region[i].base) && (addr <= upper)) 366 if ((addr >= lmb.reserved.region[i].base) && (addr <= upper))
354 return 1; 367 return 1;
355 } 368 }