]> err.no Git - linux-2.6/commitdiff
Merge branch 'linux-2.6'
authorPaul Mackerras <paulus@samba.org>
Thu, 13 Mar 2008 04:26:33 +0000 (15:26 +1100)
committerPaul Mackerras <paulus@samba.org>
Thu, 13 Mar 2008 04:26:33 +0000 (15:26 +1100)
48 files changed:
arch/powerpc/Kconfig
arch/powerpc/kernel/btext.c
arch/powerpc/kernel/crash.c
arch/powerpc/kernel/crash_dump.c
arch/powerpc/kernel/head_32.S
arch/powerpc/kernel/machine_kexec.c
arch/powerpc/kernel/prom.c
arch/powerpc/kernel/rtas.c
arch/powerpc/kernel/setup-common.c
arch/powerpc/kernel/setup_64.c
arch/powerpc/kernel/vdso.c
arch/powerpc/mm/Makefile
arch/powerpc/mm/hash_utils_64.c
arch/powerpc/mm/init_32.c
arch/powerpc/mm/init_64.c
arch/powerpc/mm/mem.c
arch/powerpc/mm/numa.c
arch/powerpc/mm/ppc_mmu_32.c
arch/powerpc/mm/stab.c
arch/powerpc/platforms/8xx/m8xx_setup.c
arch/powerpc/platforms/cell/iommu.c
arch/powerpc/platforms/maple/setup.c
arch/powerpc/platforms/pasemi/dma_lib.c
arch/powerpc/platforms/powermac/setup.c
arch/powerpc/platforms/ps3/htab.c
arch/powerpc/platforms/ps3/mm.c
arch/powerpc/platforms/ps3/os-area.c
arch/powerpc/platforms/pseries/lpar.c
arch/powerpc/sysdev/dart_iommu.c
arch/powerpc/sysdev/mpic.c
arch/ppc/8xx_io/commproc.c
arch/ppc/kernel/head.S
arch/sparc64/Kconfig
drivers/net/Makefile
drivers/net/pasemi_mac.c
drivers/net/pasemi_mac.h
drivers/net/pasemi_mac_ethtool.c [new file with mode: 0644]
include/asm-powerpc/abs_addr.h
include/asm-powerpc/cputhreads.h
include/asm-powerpc/lmb.h
include/asm-powerpc/machdep.h
include/asm-powerpc/pasemi_dma.h
include/asm-powerpc/sparsemem.h
include/asm-sparc64/lmb.h [new file with mode: 0644]
include/linux/lmb.h [new file with mode: 0644]
lib/Kconfig
lib/Makefile
lib/lmb.c [moved from arch/powerpc/mm/lmb.c with 68% similarity]

index 1189d8d6170d252013ddcf112903073297308da7..ef12db07b22f41362fc81d79d2168fee0c03ba22 100644 (file)
@@ -91,6 +91,7 @@ config PPC
        select HAVE_OPROFILE
        select HAVE_KPROBES
        select HAVE_KRETPROBES
+       select HAVE_LMB
 
 config EARLY_PRINTK
        bool
index 80e2eef05b2e6c5fd6e8fed925b8761e28a27d4d..9f9377745490d966ff434f728bc1e15581c3dace 100644 (file)
@@ -7,6 +7,7 @@
 #include <linux/string.h>
 #include <linux/init.h>
 #include <linux/module.h>
+#include <linux/lmb.h>
 
 #include <asm/sections.h>
 #include <asm/prom.h>
@@ -15,7 +16,7 @@
 #include <asm/mmu.h>
 #include <asm/pgtable.h>
 #include <asm/io.h>
-#include <asm/lmb.h>
+#include <asm/prom.h>
 #include <asm/processor.h>
 #include <asm/udbg.h>
 
index 571132ed12c1e4f74961eef16815533fa78c8351..eae401de3f769f08176838d9456a2e84c9ba786d 100644 (file)
 #include <linux/init.h>
 #include <linux/irq.h>
 #include <linux/types.h>
+#include <linux/lmb.h>
 
 #include <asm/processor.h>
 #include <asm/machdep.h>
 #include <asm/kexec.h>
 #include <asm/kdump.h>
-#include <asm/lmb.h>
+#include <asm/prom.h>
 #include <asm/firmware.h>
 #include <asm/smp.h>
 #include <asm/system.h>
index 29ff77c468ac77a3f8d3afdf81722aa46054673e..9ee3c5278db0a955425b4b1206a8e200ae01e6cc 100644 (file)
@@ -13,8 +13,9 @@
 
 #include <linux/crash_dump.h>
 #include <linux/bootmem.h>
+#include <linux/lmb.h>
 #include <asm/kdump.h>
-#include <asm/lmb.h>
+#include <asm/prom.h>
 #include <asm/firmware.h>
 #include <asm/uaccess.h>
 
index 0f4fac51202007492fdc219e99533d119bcc3339..c16d1354b19d7c7c9379eb2d386ee80d25b6156e 100644 (file)
@@ -762,23 +762,6 @@ load_up_altivec:
        /* we haven't used ctr or xer or lr */
        b       fast_exception_return
 
-/*
- * AltiVec unavailable trap from kernel - print a message, but let
- * the task use AltiVec in the kernel until it returns to user mode.
- */
-KernelAltiVec:
-       lwz     r3,_MSR(r1)
-       oris    r3,r3,MSR_VEC@h
-       stw     r3,_MSR(r1)     /* enable use of AltiVec after return */
-       lis     r3,87f@h
-       ori     r3,r3,87f@l
-       mr      r4,r2           /* current */
-       lwz     r5,_NIP(r1)
-       bl      printk
-       b       ret_from_except
-87:    .string "AltiVec used in kernel  (task=%p, pc=%x)  \n"
-       .align  4,0
-
 /*
  * giveup_altivec(tsk)
  * Disable AltiVec for the task given as the argument,
index c0c8e8c3ced90a62b8c5996dcd75bb1a6bae0001..2d202f274e7384722a0584a224b415420ee5ed11 100644 (file)
@@ -12,8 +12,9 @@
 #include <linux/kexec.h>
 #include <linux/reboot.h>
 #include <linux/threads.h>
+#include <linux/lmb.h>
 #include <asm/machdep.h>
-#include <asm/lmb.h>
+#include <asm/prom.h>
 
 void machine_crash_shutdown(struct pt_regs *regs)
 {
index eac97f48b9b8df29171e59476a95b50f01a6ef67..ff600ef0b4d6c2e82aed50476aca6774b770d93a 100644 (file)
 #include <linux/kexec.h>
 #include <linux/debugfs.h>
 #include <linux/irq.h>
+#include <linux/lmb.h>
 
 #include <asm/prom.h>
 #include <asm/rtas.h>
-#include <asm/lmb.h>
 #include <asm/page.h>
 #include <asm/processor.h>
 #include <asm/irq.h>
index 52e95c2158c02418789d3e238b96b31ee42aa9d1..e2e78d967f31b21fc7dbf70de92c46c4f43d457b 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/smp.h>
 #include <linux/completion.h>
 #include <linux/cpumask.h>
+#include <linux/lmb.h>
 
 #include <asm/prom.h>
 #include <asm/rtas.h>
@@ -34,7 +35,6 @@
 #include <asm/system.h>
 #include <asm/delay.h>
 #include <asm/uaccess.h>
-#include <asm/lmb.h>
 #include <asm/udbg.h>
 #include <asm/syscalls.h>
 #include <asm/smp.h>
index 6adb5a1e98bb8f2a46eac766b03288ac8e4b1f7e..12cc41c16b0dd9e5ee549c5e8aa37334141f6f34 100644 (file)
@@ -34,6 +34,7 @@
 #include <linux/serial_8250.h>
 #include <linux/debugfs.h>
 #include <linux/percpu.h>
+#include <linux/lmb.h>
 #include <asm/io.h>
 #include <asm/prom.h>
 #include <asm/processor.h>
@@ -56,7 +57,6 @@
 #include <asm/cache.h>
 #include <asm/page.h>
 #include <asm/mmu.h>
-#include <asm/lmb.h>
 #include <asm/xmon.h>
 #include <asm/cputhreads.h>
 
index 3b1529c103ef4a545da877bfe4d2de81cf41abe7..2c2d8315193ce438bdb83b9df07b4434e29f7ca4 100644 (file)
@@ -33,6 +33,7 @@
 #include <linux/serial_8250.h>
 #include <linux/bootmem.h>
 #include <linux/pci.h>
+#include <linux/lmb.h>
 #include <asm/io.h>
 #include <asm/kdump.h>
 #include <asm/prom.h>
@@ -55,7 +56,6 @@
 #include <asm/cache.h>
 #include <asm/page.h>
 #include <asm/mmu.h>
-#include <asm/lmb.h>
 #include <asm/firmware.h>
 #include <asm/xmon.h>
 #include <asm/udbg.h>
index d3437c4c4a6f9b81f99020353dceaff248a54a06..c21a626af676fde938922c25e110c203e892a24f 100644 (file)
 #include <linux/elf.h>
 #include <linux/security.h>
 #include <linux/bootmem.h>
+#include <linux/lmb.h>
 
 #include <asm/pgtable.h>
 #include <asm/system.h>
 #include <asm/processor.h>
 #include <asm/mmu.h>
 #include <asm/mmu_context.h>
-#include <asm/lmb.h>
+#include <asm/prom.h>
 #include <asm/machdep.h>
 #include <asm/cputable.h>
 #include <asm/sections.h>
index 41649a5d3602c97201021ff8ff35ec408d0e7515..1c00e0196f6c25bc99452ecdd6f04e47ee412b66 100644 (file)
@@ -6,7 +6,7 @@ ifeq ($(CONFIG_PPC64),y)
 EXTRA_CFLAGS   += -mno-minimal-toc
 endif
 
-obj-y                          := fault.o mem.o lmb.o \
+obj-y                          := fault.o mem.o \
                                   init_$(CONFIG_WORD_SIZE).o \
                                   pgtable_$(CONFIG_WORD_SIZE).o \
                                   mmu_context_$(CONFIG_WORD_SIZE).o
index 590f1f67c87403df6db3f878c800a7c37bf992b4..0b018b29cda84647dd6898a2808a6eb15477a32d 100644 (file)
@@ -31,6 +31,7 @@
 #include <linux/cache.h>
 #include <linux/init.h>
 #include <linux/signal.h>
+#include <linux/lmb.h>
 
 #include <asm/processor.h>
 #include <asm/pgtable.h>
@@ -41,7 +42,7 @@
 #include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/machdep.h>
-#include <asm/lmb.h>
+#include <asm/prom.h>
 #include <asm/abs_addr.h>
 #include <asm/tlbflush.h>
 #include <asm/io.h>
@@ -191,6 +192,24 @@ int htab_bolt_mapping(unsigned long vstart, unsigned long vend,
        return ret < 0 ? ret : 0;
 }
 
+static void htab_remove_mapping(unsigned long vstart, unsigned long vend,
+                     int psize, int ssize)
+{
+       unsigned long vaddr;
+       unsigned int step, shift;
+
+       shift = mmu_psize_defs[psize].shift;
+       step = 1 << shift;
+
+       if (!ppc_md.hpte_removebolted) {
+               printk("Sub-arch doesn't implement hpte_removebolted\n");
+               return;
+       }
+
+       for (vaddr = vstart; vaddr < vend; vaddr += step)
+               ppc_md.hpte_removebolted(vaddr, psize, ssize);
+}
+
 static int __init htab_dt_scan_seg_sizes(unsigned long node,
                                         const char *uname, int depth,
                                         void *data)
@@ -429,6 +448,11 @@ void create_section_mapping(unsigned long start, unsigned long end)
                        _PAGE_ACCESSED | _PAGE_DIRTY | _PAGE_COHERENT | PP_RWXX,
                        mmu_linear_psize, mmu_kernel_ssize));
 }
+
+void remove_section_mapping(unsigned long start, unsigned long end)
+{
+       htab_remove_mapping(start, end, mmu_linear_psize, mmu_kernel_ssize);
+}
 #endif /* CONFIG_MEMORY_HOTPLUG */
 
 static inline void make_bl(unsigned int *insn_addr, void *func)
index 977cb1ee5e7269e353755c190cf945931a51413c..59a725b8ece96a5e445cbd3e16ea9b169d49b3cc 100644 (file)
@@ -30,6 +30,7 @@
 #include <linux/highmem.h>
 #include <linux/initrd.h>
 #include <linux/pagemap.h>
+#include <linux/lmb.h>
 
 #include <asm/pgalloc.h>
 #include <asm/prom.h>
@@ -41,7 +42,6 @@
 #include <asm/machdep.h>
 #include <asm/btext.h>
 #include <asm/tlb.h>
-#include <asm/lmb.h>
 #include <asm/sections.h>
 
 #include "mmu_decl.h"
index c0f5cff77035e8d1abae6fe746e96af2cbcd6dd2..abeb0eb7931387e0bcb3aa3727d209a0f05cb525 100644 (file)
 #include <linux/nodemask.h>
 #include <linux/module.h>
 #include <linux/poison.h>
+#include <linux/lmb.h>
 
 #include <asm/pgalloc.h>
 #include <asm/page.h>
 #include <asm/prom.h>
-#include <asm/lmb.h>
 #include <asm/rtas.h>
 #include <asm/io.h>
 #include <asm/mmu_context.h>
index be5c506779a74595d8950cfece610f9a378ce220..60c019cdc69f629bd14b7f506208e1035b9a3d0e 100644 (file)
@@ -31,6 +31,7 @@
 #include <linux/initrd.h>
 #include <linux/pagemap.h>
 #include <linux/suspend.h>
+#include <linux/lmb.h>
 
 #include <asm/pgalloc.h>
 #include <asm/prom.h>
@@ -42,7 +43,6 @@
 #include <asm/machdep.h>
 #include <asm/btext.h>
 #include <asm/tlb.h>
-#include <asm/lmb.h>
 #include <asm/sections.h>
 #include <asm/vdso.h>
 
index a300d254aac6518dc473ecf405bebf6943b6bfeb..1efd631211ef3772532430129176286bb182fbbc 100644 (file)
@@ -17,8 +17,9 @@
 #include <linux/nodemask.h>
 #include <linux/cpu.h>
 #include <linux/notifier.h>
+#include <linux/lmb.h>
 #include <asm/sparsemem.h>
-#include <asm/lmb.h>
+#include <asm/prom.h>
 #include <asm/system.h>
 #include <asm/smp.h>
 
index 5c45d474cfcc91d2b09211974fad4508e3de3af0..72de3c79210aa455b58fc12303bd454415974c2d 100644 (file)
 #include <linux/mm.h>
 #include <linux/init.h>
 #include <linux/highmem.h>
+#include <linux/lmb.h>
 
 #include <asm/prom.h>
 #include <asm/mmu.h>
 #include <asm/machdep.h>
-#include <asm/lmb.h>
 
 #include "mmu_decl.h"
 
index 50448d5de9d247c9657c66a85e76f225483fc4f4..efbbd13d93e519bcfd30ebb5da48f0f87b2672f0 100644 (file)
  *      2 of the License, or (at your option) any later version.
  */
 
+#include <linux/lmb.h>
+
 #include <asm/pgtable.h>
 #include <asm/mmu.h>
 #include <asm/mmu_context.h>
 #include <asm/paca.h>
 #include <asm/cputable.h>
-#include <asm/lmb.h>
+#include <asm/prom.h>
 #include <asm/abs_addr.h>
 #include <asm/firmware.h>
 #include <asm/iseries/hv_call.h>
index 184f998d1be2e25da5f3d09c2d526683ded8741c..0d9f75c74f8cdf22e83f13ba342c45f5b12a0d66 100644 (file)
@@ -111,17 +111,12 @@ void __init mpc8xx_calibrate_decr(void)
 
        /* Processor frequency is MHz.
         */
-       ppc_tb_freq = 50000000;
-       if (!get_freq("bus-frequency", &ppc_tb_freq)) {
-               printk(KERN_ERR "WARNING: Estimating decrementer frequency "
-                               "(not found)\n");
-       }
-       ppc_tb_freq /= 16;
        ppc_proc_freq = 50000000;
        if (!get_freq("clock-frequency", &ppc_proc_freq))
                printk(KERN_ERR "WARNING: Estimating processor frequency "
                                "(not found)\n");
 
+       ppc_tb_freq = ppc_proc_freq / 16;
        printk("Decrementer Frequency = 0x%lx\n", ppc_tb_freq);
 
        /* Perform some more timer/timebase initialization.  This used
index 20ea0e118f246b21819b907d49c25e8c4d70e510..d6a732503ea61bb7455751e37d2ae9177e0a1e31 100644 (file)
 #include <linux/notifier.h>
 #include <linux/of.h>
 #include <linux/of_platform.h>
+#include <linux/lmb.h>
 
 #include <asm/prom.h>
 #include <asm/iommu.h>
 #include <asm/machdep.h>
 #include <asm/pci-bridge.h>
 #include <asm/udbg.h>
-#include <asm/lmb.h>
 #include <asm/firmware.h>
 #include <asm/cell-regs.h>
 
index 3ce2d73b4177791c1a61a7643bd6e1ff7def86aa..dadf33b5c09c4c60835d733802dd4d2da0b39f1a 100644 (file)
@@ -43,6 +43,7 @@
 #include <linux/smp.h>
 #include <linux/bitops.h>
 #include <linux/of_device.h>
+#include <linux/lmb.h>
 
 #include <asm/processor.h>
 #include <asm/sections.h>
@@ -57,7 +58,6 @@
 #include <asm/dma.h>
 #include <asm/cputable.h>
 #include <asm/time.h>
-#include <asm/lmb.h>
 #include <asm/mpic.h>
 #include <asm/rtas.h>
 #include <asm/udbg.h>
index c529d8dff395bdd5a6f3cfb316dbaafcb674ab1a..217af321b0ca4d95b1c9aa2a9a39afbe68d98c7f 100644 (file)
@@ -17,6 +17,7 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
  */
 
+#include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/pci.h>
@@ -26,6 +27,8 @@
 
 #define MAX_TXCH 64
 #define MAX_RXCH 64
+#define MAX_FLAGS 64
+#define MAX_FUN 8
 
 static struct pasdma_status *dma_status;
 
@@ -43,6 +46,8 @@ static struct pci_dev *dma_pdev;
 
 static DECLARE_BITMAP(txch_free, MAX_TXCH);
 static DECLARE_BITMAP(rxch_free, MAX_RXCH);
+static DECLARE_BITMAP(flags_free, MAX_FLAGS);
+static DECLARE_BITMAP(fun_free, MAX_FUN);
 
 /* pasemi_read_iob_reg - read IOB register
  * @reg: Register to read (offset into PCI CFG space)
@@ -373,6 +378,106 @@ void pasemi_dma_free_buf(struct pasemi_dmachan *chan, int size,
 }
 EXPORT_SYMBOL(pasemi_dma_free_buf);
 
+/* pasemi_dma_alloc_flag - Allocate a flag (event) for channel syncronization
+ *
+ * Allocates a flag for use with channel syncronization (event descriptors).
+ * Returns allocated flag (0-63), < 0 on error.
+ */
+int pasemi_dma_alloc_flag(void)
+{
+       int bit;
+
+retry:
+       bit = find_next_bit(flags_free, MAX_FLAGS, 0);
+       if (bit >= MAX_FLAGS)
+               return -ENOSPC;
+       if (!test_and_clear_bit(bit, flags_free))
+               goto retry;
+
+       return bit;
+}
+EXPORT_SYMBOL(pasemi_dma_alloc_flag);
+
+
+/* pasemi_dma_free_flag - Deallocates a flag (event)
+ * @flag: Flag number to deallocate
+ *
+ * Frees up a flag so it can be reused for other purposes.
+ */
+void pasemi_dma_free_flag(int flag)
+{
+       BUG_ON(test_bit(flag, flags_free));
+       BUG_ON(flag >= MAX_FLAGS);
+       set_bit(flag, flags_free);
+}
+EXPORT_SYMBOL(pasemi_dma_free_flag);
+
+
+/* pasemi_dma_set_flag - Sets a flag (event) to 1
+ * @flag: Flag number to set active
+ *
+ * Sets the flag provided to 1.
+ */
+void pasemi_dma_set_flag(int flag)
+{
+       BUG_ON(flag >= MAX_FLAGS);
+       if (flag < 32)
+               pasemi_write_dma_reg(PAS_DMA_TXF_SFLG0, 1 << flag);
+       else
+               pasemi_write_dma_reg(PAS_DMA_TXF_SFLG1, 1 << flag);
+}
+EXPORT_SYMBOL(pasemi_dma_set_flag);
+
+/* pasemi_dma_clear_flag - Sets a flag (event) to 0
+ * @flag: Flag number to set inactive
+ *
+ * Sets the flag provided to 0.
+ */
+void pasemi_dma_clear_flag(int flag)
+{
+       BUG_ON(flag >= MAX_FLAGS);
+       if (flag < 32)
+               pasemi_write_dma_reg(PAS_DMA_TXF_CFLG0, 1 << flag);
+       else
+               pasemi_write_dma_reg(PAS_DMA_TXF_CFLG1, 1 << flag);
+}
+EXPORT_SYMBOL(pasemi_dma_clear_flag);
+
+/* pasemi_dma_alloc_fun - Allocate a function engine
+ *
+ * Allocates a function engine to use for crypto/checksum offload
+ * Returns allocated engine (0-8), < 0 on error.
+ */
+int pasemi_dma_alloc_fun(void)
+{
+       int bit;
+
+retry:
+       bit = find_next_bit(fun_free, MAX_FLAGS, 0);
+       if (bit >= MAX_FLAGS)
+               return -ENOSPC;
+       if (!test_and_clear_bit(bit, fun_free))
+               goto retry;
+
+       return bit;
+}
+EXPORT_SYMBOL(pasemi_dma_alloc_fun);
+
+
+/* pasemi_dma_free_fun - Deallocates a function engine
+ * @flag: Engine number to deallocate
+ *
+ * Frees up a function engine so it can be used for other purposes.
+ */
+void pasemi_dma_free_fun(int fun)
+{
+       BUG_ON(test_bit(fun, fun_free));
+       BUG_ON(fun >= MAX_FLAGS);
+       set_bit(fun, fun_free);
+}
+EXPORT_SYMBOL(pasemi_dma_free_fun);
+
+
 static void *map_onedev(struct pci_dev *p, int index)
 {
        struct device_node *dn;
@@ -410,6 +515,7 @@ int pasemi_dma_init(void)
        struct resource res;
        struct device_node *dn;
        int i, intf, err = 0;
+       unsigned long timeout;
        u32 tmp;
 
        if (!machine_is(pasemi))
@@ -478,6 +584,44 @@ int pasemi_dma_init(void)
        for (i = 0; i < MAX_RXCH; i++)
                __set_bit(i, rxch_free);
 
+       timeout = jiffies + HZ;
+       pasemi_write_dma_reg(PAS_DMA_COM_RXCMD, 0);
+       while (pasemi_read_dma_reg(PAS_DMA_COM_RXSTA) & 1) {
+               if (time_after(jiffies, timeout)) {
+                       pr_warning("Warning: Could not disable RX section\n");
+                       break;
+               }
+       }
+
+       timeout = jiffies + HZ;
+       pasemi_write_dma_reg(PAS_DMA_COM_TXCMD, 0);
+       while (pasemi_read_dma_reg(PAS_DMA_COM_TXSTA) & 1) {
+               if (time_after(jiffies, timeout)) {
+                       pr_warning("Warning: Could not disable TX section\n");
+                       break;
+               }
+       }
+
+       /* setup resource allocations for the different DMA sections */
+       tmp = pasemi_read_dma_reg(PAS_DMA_COM_CFG);
+       pasemi_write_dma_reg(PAS_DMA_COM_CFG, tmp | 0x18000000);
+
+       /* enable tx section */
+       pasemi_write_dma_reg(PAS_DMA_COM_TXCMD, PAS_DMA_COM_TXCMD_EN);
+
+       /* enable rx section */
+       pasemi_write_dma_reg(PAS_DMA_COM_RXCMD, PAS_DMA_COM_RXCMD_EN);
+
+       for (i = 0; i < MAX_FLAGS; i++)
+               __set_bit(i, flags_free);
+
+       for (i = 0; i < MAX_FUN; i++)
+               __set_bit(i, fun_free);
+
+       /* clear all status flags */
+       pasemi_write_dma_reg(PAS_DMA_TXF_CFLG0, 0xffffffff);
+       pasemi_write_dma_reg(PAS_DMA_TXF_CFLG1, 0xffffffff);
+
        printk(KERN_INFO "PA Semi PWRficient DMA library initialized "
                "(%d tx, %d rx channels)\n", num_txch, num_rxch);
 
index 36ff1b6b7fac43f58a77778947809cdb5ae10014..59404baf911fa144baba6325c57765f141120d1d 100644 (file)
@@ -53,6 +53,7 @@
 #include <linux/suspend.h>
 #include <linux/of_device.h>
 #include <linux/of_platform.h>
+#include <linux/lmb.h>
 
 #include <asm/reg.h>
 #include <asm/sections.h>
@@ -74,7 +75,6 @@
 #include <asm/iommu.h>
 #include <asm/smu.h>
 #include <asm/pmc.h>
-#include <asm/lmb.h>
 #include <asm/udbg.h>
 
 #include "pmac.h"
index 7382f195c4f87689aac7f1e858e98c16e0dd687d..1cf901fa9031d51a86c97ed33b6b70b9bae196b6 100644 (file)
  */
 
 #include <linux/kernel.h>
+#include <linux/lmb.h>
 
 #include <asm/machdep.h>
-#include <asm/lmb.h>
+#include <asm/prom.h>
 #include <asm/udbg.h>
 #include <asm/lv1call.h>
 #include <asm/ps3fb.h>
index 68900476c8425881b0514f0f077e302ea4b10e88..5b3fb2b321abeffa98811e8570100ea49eb1f3da 100644 (file)
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/memory_hotplug.h>
+#include <linux/lmb.h>
 
 #include <asm/firmware.h>
-#include <asm/lmb.h>
+#include <asm/prom.h>
 #include <asm/udbg.h>
 #include <asm/lv1call.h>
 
index b9ea09d9d2fb130056f59d59640eec8554623fa0..c73379ec9141038c5a68e14f0233a64c9fb2601f 100644 (file)
@@ -24,8 +24,9 @@
 #include <linux/fs.h>
 #include <linux/syscalls.h>
 #include <linux/ctype.h>
+#include <linux/lmb.h>
 
-#include <asm/lmb.h>
+#include <asm/prom.h>
 
 #include "platform.h"
 
index 9a455d46379d525181a4278714e22304f72028db..233d9be25f49248958f93eb91d55a92c8d5ebde6 100644 (file)
@@ -520,6 +520,20 @@ static void pSeries_lpar_hpte_invalidate(unsigned long slot, unsigned long va,
        BUG_ON(lpar_rc != H_SUCCESS);
 }
 
+static void pSeries_lpar_hpte_removebolted(unsigned long ea,
+                                          int psize, int ssize)
+{
+       unsigned long slot, vsid, va;
+
+       vsid = get_kernel_vsid(ea, ssize);
+       va = hpt_va(ea, vsid, ssize);
+
+       slot = pSeries_lpar_hpte_find(va, psize, ssize);
+       BUG_ON(slot == -1);
+
+       pSeries_lpar_hpte_invalidate(slot, va, psize, ssize, 0);
+}
+
 /* Flag bits for H_BULK_REMOVE */
 #define HBR_REQUEST    0x4000000000000000UL
 #define HBR_RESPONSE   0x8000000000000000UL
@@ -597,6 +611,7 @@ void __init hpte_init_lpar(void)
        ppc_md.hpte_updateboltedpp = pSeries_lpar_hpte_updateboltedpp;
        ppc_md.hpte_insert      = pSeries_lpar_hpte_insert;
        ppc_md.hpte_remove      = pSeries_lpar_hpte_remove;
+       ppc_md.hpte_removebolted = pSeries_lpar_hpte_removebolted;
        ppc_md.flush_hash_range = pSeries_lpar_flush_hash_range;
        ppc_md.hpte_clear_all   = pSeries_lpar_hptab_clear;
 }
index e0e24b01e3a61c5138ff110e40c3a66c219ffa36..005c2ecf976fe810f2f02ddee3f78200d8d3f010 100644 (file)
@@ -37,6 +37,7 @@
 #include <linux/dma-mapping.h>
 #include <linux/vmalloc.h>
 #include <linux/suspend.h>
+#include <linux/lmb.h>
 #include <asm/io.h>
 #include <asm/prom.h>
 #include <asm/iommu.h>
@@ -44,7 +45,6 @@
 #include <asm/machdep.h>
 #include <asm/abs_addr.h>
 #include <asm/cacheflush.h>
-#include <asm/lmb.h>
 #include <asm/ppc-pci.h>
 
 #include "dart.h"
index 6ffdda244bb1525f2fcd64413385997cb85e1954..6131fd2b6619c0ea26e06e2dccea125d89e3486b 100644 (file)
@@ -175,13 +175,16 @@ static inline void _mpic_write(enum mpic_reg_type type,
        switch(type) {
 #ifdef CONFIG_PPC_DCR
        case mpic_access_dcr:
-               return dcr_write(rb->dhost, reg, value);
+               dcr_write(rb->dhost, reg, value);
+               break;
 #endif
        case mpic_access_mmio_be:
-               return out_be32(rb->base + (reg >> 2), value);
+               out_be32(rb->base + (reg >> 2), value);
+               break;
        case mpic_access_mmio_le:
        default:
-               return out_le32(rb->base + (reg >> 2), value);
+               out_le32(rb->base + (reg >> 2), value);
+               break;
        }
 }
 
@@ -1000,7 +1003,7 @@ struct mpic * __init mpic_alloc(struct device_node *node,
                                const char *name)
 {
        struct mpic     *mpic;
-       u32             reg;
+       u32             greg_feature;
        const char      *vers;
        int             i;
        int             intvec_top;
@@ -1064,7 +1067,8 @@ struct mpic * __init mpic_alloc(struct device_node *node,
 
        /* Look for protected sources */
        if (node) {
-               unsigned int psize, bits, mapsize;
+               int psize;
+               unsigned int bits, mapsize;
                const u32 *psrc =
                        of_get_property(node, "protected-sources", &psize);
                if (psrc) {
@@ -1107,8 +1111,7 @@ struct mpic * __init mpic_alloc(struct device_node *node,
         * in, try to obtain one
         */
        if (paddr == 0 && !(mpic->flags & MPIC_USES_DCR)) {
-               const u32 *reg;
-               reg = of_get_property(node, "reg", NULL);
+               const u32 *reg = of_get_property(node, "reg", NULL);
                BUG_ON(reg == NULL);
                paddr = of_translate_address(node, reg);
                BUG_ON(paddr == OF_BAD_ADDR);
@@ -1137,12 +1140,13 @@ struct mpic * __init mpic_alloc(struct device_node *node,
         * MPICs, num sources as well. On ISU MPICs, sources are counted
         * as ISUs are added
         */
-       reg = mpic_read(mpic->gregs, MPIC_INFO(GREG_FEATURE_0));
-       mpic->num_cpus = ((reg & MPIC_GREG_FEATURE_LAST_CPU_MASK)
+       greg_feature = mpic_read(mpic->gregs, MPIC_INFO(GREG_FEATURE_0));
+       mpic->num_cpus = ((greg_feature & MPIC_GREG_FEATURE_LAST_CPU_MASK)
                          >> MPIC_GREG_FEATURE_LAST_CPU_SHIFT) + 1;
        if (isu_size == 0)
-               mpic->num_sources = ((reg & MPIC_GREG_FEATURE_LAST_SRC_MASK)
-                                    >> MPIC_GREG_FEATURE_LAST_SRC_SHIFT) + 1;
+               mpic->num_sources =
+                       ((greg_feature & MPIC_GREG_FEATURE_LAST_SRC_MASK)
+                        >> MPIC_GREG_FEATURE_LAST_SRC_SHIFT) + 1;
 
        /* Map the per-CPU registers */
        for (i = 0; i < mpic->num_cpus; i++) {
@@ -1161,7 +1165,7 @@ struct mpic * __init mpic_alloc(struct device_node *node,
        mpic->isu_mask = (1 << mpic->isu_shift) - 1;
 
        /* Display version */
-       switch (reg & MPIC_GREG_FEATURE_VERSION_MASK) {
+       switch (greg_feature & MPIC_GREG_FEATURE_VERSION_MASK) {
        case 1:
                vers = "1.0";
                break;
@@ -1321,7 +1325,7 @@ void __init mpic_set_serial_int(struct mpic *mpic, int enable)
 
 void mpic_irq_set_priority(unsigned int irq, unsigned int pri)
 {
-       int is_ipi;
+       unsigned int is_ipi;
        struct mpic *mpic = mpic_find(irq, &is_ipi);
        unsigned int src = mpic_irq_to_hw(irq);
        unsigned long flags;
@@ -1344,7 +1348,7 @@ void mpic_irq_set_priority(unsigned int irq, unsigned int pri)
 
 unsigned int mpic_irq_get_priority(unsigned int irq)
 {
-       int is_ipi;
+       unsigned int is_ipi;
        struct mpic *mpic = mpic_find(irq, &is_ipi);
        unsigned int src = mpic_irq_to_hw(irq);
        unsigned long flags;
index 9d656de0f0f19357d7f48724743bb6945ef7ba93..752443df5ecf270ea67ca0e3c44dafd22d62a678 100644 (file)
@@ -43,7 +43,7 @@
 ({                                                                     \
        u32 offset = offsetof(immap_t, member);                         \
        void *addr = ioremap (IMAP_ADDR + offset,                       \
-                             sizeof( ((immap_t*)0)->member));          \
+                             FIELD_SIZEOF(immap_t, member));           \
        addr;                                                           \
 })
 
index 1b0ec7202dd5470a939b7c9d933618f8c2c425a4..e7e642b95138c32e796c18720027893497a86376 100644 (file)
@@ -700,23 +700,6 @@ load_up_altivec:
        /* we haven't used ctr or xer or lr */
        b       fast_exception_return
 
-/*
- * AltiVec unavailable trap from kernel - print a message, but let
- * the task use AltiVec in the kernel until it returns to user mode.
- */
-KernelAltiVec:
-       lwz     r3,_MSR(r1)
-       oris    r3,r3,MSR_VEC@h
-       stw     r3,_MSR(r1)     /* enable use of AltiVec after return */
-       lis     r3,87f@h
-       ori     r3,r3,87f@l
-       mr      r4,r2           /* current */
-       lwz     r5,_NIP(r1)
-       bl      printk
-       b       ret_from_except
-87:    .string "AltiVec used in kernel  (task=%p, pc=%x)  \n"
-       .align  4,0
-
 /*
  * giveup_altivec(tsk)
  * Disable AltiVec for the task given as the argument,
index 463d1be32c98614cea3fc98cb31154895a5858eb..2667a9dee11d943cd2f018a2eec489034c0fd07d 100644 (file)
@@ -16,6 +16,7 @@ config SPARC64
        bool
        default y
        select HAVE_IDE
+       select HAVE_LMB
        help
          SPARC is a family of RISC microprocessors designed and marketed by
          Sun Microsystems, incorporated.  This port covers the newer 64-bit
index 3b1ea321dc056624d924c20ec4a7375b4ede88a7..4b442739e7bfbff595c147c39b7c7ff05dc2d4ff 100644 (file)
@@ -218,7 +218,8 @@ obj-$(CONFIG_SMC911X) += smc911x.o
 obj-$(CONFIG_BFIN_MAC) += bfin_mac.o
 obj-$(CONFIG_DM9000) += dm9000.o
 obj-$(CONFIG_FEC_8XX) += fec_8xx/
-obj-$(CONFIG_PASEMI_MAC) += pasemi_mac.o
+obj-$(CONFIG_PASEMI_MAC) += pasemi_mac_driver.o
+pasemi_mac_driver-objs := pasemi_mac.o pasemi_mac_ethtool.o
 obj-$(CONFIG_MLX4_CORE) += mlx4/
 obj-$(CONFIG_ENC28J60) += enc28j60.o
 
index 2e39e0285d8f9d2a6a9712ce33249749ede49377..c50f0f4de6d843319c401d6e3104cbd843755a0a 100644 (file)
  * - Multiqueue RX/TX
  */
 
-
-/* Must be a power of two */
-#define RX_RING_SIZE 2048
-#define TX_RING_SIZE 4096
-
 #define LRO_MAX_AGGR 64
 
 #define PE_MIN_MTU     64
-#define PE_MAX_MTU     1500
+#define PE_MAX_MTU     9000
 #define PE_DEF_MTU     ETH_DATA_LEN
 
 #define DEFAULT_MSG_ENABLE       \
         NETIF_MSG_RX_ERR       | \
         NETIF_MSG_TX_ERR)
 
-#define TX_DESC(tx, num)       ((tx)->chan.ring_virt[(num) & (TX_RING_SIZE-1)])
-#define TX_DESC_INFO(tx, num)  ((tx)->ring_info[(num) & (TX_RING_SIZE-1)])
-#define RX_DESC(rx, num)       ((rx)->chan.ring_virt[(num) & (RX_RING_SIZE-1)])
-#define RX_DESC_INFO(rx, num)  ((rx)->ring_info[(num) & (RX_RING_SIZE-1)])
-#define RX_BUFF(rx, num)       ((rx)->buffers[(num) & (RX_RING_SIZE-1)])
-
-#define RING_USED(ring)                (((ring)->next_to_fill - (ring)->next_to_clean) \
-                                & ((ring)->size - 1))
-#define RING_AVAIL(ring)       ((ring->size) - RING_USED(ring))
-
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR ("Olof Johansson <olof@lixom.net>");
 MODULE_DESCRIPTION("PA Semi PWRficient Ethernet driver");
@@ -94,6 +79,8 @@ static int debug = -1;        /* -1 == use DEFAULT_MSG_ENABLE as value */
 module_param(debug, int, 0);
 MODULE_PARM_DESC(debug, "PA Semi MAC bitmapped debugging message enable value");
 
+extern const struct ethtool_ops pasemi_mac_ethtool_ops;
+
 static int translation_enabled(void)
 {
 #if defined(CONFIG_PPC_PASEMI_IOMMU_DMA_FORCE)
@@ -322,6 +309,103 @@ static int pasemi_mac_unmap_tx_skb(struct pasemi_mac *mac,
        return (nfrags + 3) & ~1;
 }
 
+static struct pasemi_mac_csring *pasemi_mac_setup_csring(struct pasemi_mac *mac)
+{
+       struct pasemi_mac_csring *ring;
+       u32 val;
+       unsigned int cfg;
+       int chno;
+
+       ring = pasemi_dma_alloc_chan(TXCHAN, sizeof(struct pasemi_mac_csring),
+                                      offsetof(struct pasemi_mac_csring, chan));
+
+       if (!ring) {
+               dev_err(&mac->pdev->dev, "Can't allocate checksum channel\n");
+               goto out_chan;
+       }
+
+       chno = ring->chan.chno;
+
+       ring->size = CS_RING_SIZE;
+       ring->next_to_fill = 0;
+
+       /* Allocate descriptors */
+       if (pasemi_dma_alloc_ring(&ring->chan, CS_RING_SIZE))
+               goto out_ring_desc;
+
+       write_dma_reg(PAS_DMA_TXCHAN_BASEL(chno),
+                     PAS_DMA_TXCHAN_BASEL_BRBL(ring->chan.ring_dma));
+       val = PAS_DMA_TXCHAN_BASEU_BRBH(ring->chan.ring_dma >> 32);
+       val |= PAS_DMA_TXCHAN_BASEU_SIZ(CS_RING_SIZE >> 3);
+
+       write_dma_reg(PAS_DMA_TXCHAN_BASEU(chno), val);
+
+       ring->events[0] = pasemi_dma_alloc_flag();
+       ring->events[1] = pasemi_dma_alloc_flag();
+       if (ring->events[0] < 0 || ring->events[1] < 0)
+               goto out_flags;
+
+       pasemi_dma_clear_flag(ring->events[0]);
+       pasemi_dma_clear_flag(ring->events[1]);
+
+       ring->fun = pasemi_dma_alloc_fun();
+       if (ring->fun < 0)
+               goto out_fun;
+
+       cfg = PAS_DMA_TXCHAN_CFG_TY_FUNC | PAS_DMA_TXCHAN_CFG_UP |
+             PAS_DMA_TXCHAN_CFG_TATTR(ring->fun) |
+             PAS_DMA_TXCHAN_CFG_LPSQ | PAS_DMA_TXCHAN_CFG_LPDQ;
+
+       if (translation_enabled())
+               cfg |= PAS_DMA_TXCHAN_CFG_TRD | PAS_DMA_TXCHAN_CFG_TRR;
+
+       write_dma_reg(PAS_DMA_TXCHAN_CFG(chno), cfg);
+
+       /* enable channel */
+       pasemi_dma_start_chan(&ring->chan, PAS_DMA_TXCHAN_TCMDSTA_SZ |
+                                          PAS_DMA_TXCHAN_TCMDSTA_DB |
+                                          PAS_DMA_TXCHAN_TCMDSTA_DE |
+                                          PAS_DMA_TXCHAN_TCMDSTA_DA);
+
+       return ring;
+
+out_fun:
+out_flags:
+       if (ring->events[0] >= 0)
+               pasemi_dma_free_flag(ring->events[0]);
+       if (ring->events[1] >= 0)
+               pasemi_dma_free_flag(ring->events[1]);
+       pasemi_dma_free_ring(&ring->chan);
+out_ring_desc:
+       pasemi_dma_free_chan(&ring->chan);
+out_chan:
+
+       return NULL;
+}
+
+static void pasemi_mac_setup_csrings(struct pasemi_mac *mac)
+{
+       int i;
+       mac->cs[0] = pasemi_mac_setup_csring(mac);
+       if (mac->type == MAC_TYPE_XAUI)
+               mac->cs[1] = pasemi_mac_setup_csring(mac);
+       else
+               mac->cs[1] = 0;
+
+       for (i = 0; i < MAX_CS; i++)
+               if (mac->cs[i])
+                       mac->num_cs++;
+}
+
+static void pasemi_mac_free_csring(struct pasemi_mac_csring *csring)
+{
+       pasemi_dma_stop_chan(&csring->chan);
+       pasemi_dma_free_flag(csring->events[0]);
+       pasemi_dma_free_flag(csring->events[1]);
+       pasemi_dma_free_ring(&csring->chan);
+       pasemi_dma_free_chan(&csring->chan);
+}
+
 static int pasemi_mac_setup_rx_resources(const struct net_device *dev)
 {
        struct pasemi_mac_rxring *ring;
@@ -445,7 +529,7 @@ pasemi_mac_setup_tx_resources(const struct net_device *dev)
        cfg = PAS_DMA_TXCHAN_CFG_TY_IFACE |
              PAS_DMA_TXCHAN_CFG_TATTR(mac->dma_if) |
              PAS_DMA_TXCHAN_CFG_UP |
-             PAS_DMA_TXCHAN_CFG_WT(2);
+             PAS_DMA_TXCHAN_CFG_WT(4);
 
        if (translation_enabled())
                cfg |= PAS_DMA_TXCHAN_CFG_TRD | PAS_DMA_TXCHAN_CFG_TRR;
@@ -810,13 +894,21 @@ restart:
                u64 mactx = TX_DESC(txring, i);
                struct sk_buff *skb;
 
-               skb = TX_DESC_INFO(txring, i+1).skb;
-               nr_frags = TX_DESC_INFO(txring, i).dma;
-
                if ((mactx  & XCT_MACTX_E) ||
                    (*chan->status & PAS_STATUS_ERROR))
                        pasemi_mac_tx_error(mac, mactx);
 
+               /* Skip over control descriptors */
+               if (!(mactx & XCT_MACTX_LLEN_M)) {
+                       TX_DESC(txring, i) = 0;
+                       TX_DESC(txring, i+1) = 0;
+                       buf_count = 2;
+                       continue;
+               }
+
+               skb = TX_DESC_INFO(txring, i+1).skb;
+               nr_frags = TX_DESC_INFO(txring, i).dma;
+
                if (unlikely(mactx & XCT_MACTX_O))
                        /* Not yet transmitted */
                        break;
@@ -1041,13 +1133,7 @@ static int pasemi_mac_open(struct net_device *dev)
 {
        struct pasemi_mac *mac = netdev_priv(dev);
        unsigned int flags;
-       int ret;
-
-       /* enable rx section */
-       write_dma_reg(PAS_DMA_COM_RXCMD, PAS_DMA_COM_RXCMD_EN);
-
-       /* enable tx section */
-       write_dma_reg(PAS_DMA_COM_TXCMD, PAS_DMA_COM_TXCMD_EN);
+       int i, ret;
 
        flags = PAS_MAC_CFG_TXP_FCE | PAS_MAC_CFG_TXP_FPC(3) |
                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)
        if (!mac->tx)
                goto out_tx_ring;
 
+       if (dev->mtu > 1500) {
+               pasemi_mac_setup_csrings(mac);
+               if (!mac->num_cs)
+                       goto out_tx_ring;
+       }
+
+       /* Zero out rmon counters */
+       for (i = 0; i < 32; i++)
+               write_mac_reg(mac, PAS_MAC_RMON(i), 0);
+
        /* 0x3ff with 33MHz clock is about 31us */
        write_iob_reg(PAS_IOB_DMA_COM_TIMEOUTCFG,
                      PAS_IOB_DMA_COM_TIMEOUTCFG_TCNT(0x3ff));
@@ -1247,7 +1343,7 @@ static int pasemi_mac_close(struct net_device *dev)
 {
        struct pasemi_mac *mac = netdev_priv(dev);
        unsigned int sta;
-       int rxch, txch;
+       int rxch, txch, i;
 
        rxch = rx_ring(mac)->chan.chno;
        txch = tx_ring(mac)->chan.chno;
@@ -1292,6 +1388,9 @@ static int pasemi_mac_close(struct net_device *dev)
        free_irq(mac->tx->chan.irq, mac->tx);
        free_irq(mac->rx->chan.irq, mac->rx);
 
+       for (i = 0; i < mac->num_cs; i++)
+               pasemi_mac_free_csring(mac->cs[i]);
+
        /* Free resources */
        pasemi_mac_free_rx_resources(mac);
        pasemi_mac_free_tx_resources(mac);
@@ -1299,35 +1398,113 @@ static int pasemi_mac_close(struct net_device *dev)
        return 0;
 }
 
+static void pasemi_mac_queue_csdesc(const struct sk_buff *skb,
+                                   const dma_addr_t *map,
+                                   const unsigned int *map_size,
+                                   struct pasemi_mac_txring *txring,
+                                   struct pasemi_mac_csring *csring)
+{
+       u64 fund;
+       dma_addr_t cs_dest;
+       const int nh_off = skb_network_offset(skb);
+       const int nh_len = skb_network_header_len(skb);
+       const int nfrags = skb_shinfo(skb)->nr_frags;
+       int cs_size, i, fill, hdr, cpyhdr, evt;
+       dma_addr_t csdma;
+
+       fund = XCT_FUN_ST | XCT_FUN_RR_8BRES |
+              XCT_FUN_O | XCT_FUN_FUN(csring->fun) |
+              XCT_FUN_CRM_SIG | XCT_FUN_LLEN(skb->len - nh_off) |
+              XCT_FUN_SHL(nh_len >> 2) | XCT_FUN_SE;
+
+       switch (ip_hdr(skb)->protocol) {
+       case IPPROTO_TCP:
+               fund |= XCT_FUN_SIG_TCP4;
+               /* TCP checksum is 16 bytes into the header */
+               cs_dest = map[0] + skb_transport_offset(skb) + 16;
+               break;
+       case IPPROTO_UDP:
+               fund |= XCT_FUN_SIG_UDP4;
+               /* UDP checksum is 6 bytes into the header */
+               cs_dest = map[0] + skb_transport_offset(skb) + 6;
+               break;
+       default:
+               BUG();
+       }
+
+       /* Do the checksum offloaded */
+       fill = csring->next_to_fill;
+       hdr = fill;
+
+       CS_DESC(csring, fill++) = fund;
+       /* Room for 8BRES. Checksum result is really 2 bytes into it */
+       csdma = csring->chan.ring_dma + (fill & (CS_RING_SIZE-1)) * 8 + 2;
+       CS_DESC(csring, fill++) = 0;
+
+       CS_DESC(csring, fill) = XCT_PTR_LEN(map_size[0]-nh_off) | XCT_PTR_ADDR(map[0]+nh_off);
+       for (i = 1; i <= nfrags; i++)
+               CS_DESC(csring, fill+i) = XCT_PTR_LEN(map_size[i]) | XCT_PTR_ADDR(map[i]);
+
+       fill += i;
+       if (fill & 1)
+               fill++;
+
+       /* Copy the result into the TCP packet */
+       cpyhdr = fill;
+       CS_DESC(csring, fill++) = XCT_FUN_O | XCT_FUN_FUN(csring->fun) |
+                                 XCT_FUN_LLEN(2) | XCT_FUN_SE;
+       CS_DESC(csring, fill++) = XCT_PTR_LEN(2) | XCT_PTR_ADDR(cs_dest) | XCT_PTR_T;
+       CS_DESC(csring, fill++) = XCT_PTR_LEN(2) | XCT_PTR_ADDR(csdma);
+       fill++;
+
+       evt = !csring->last_event;
+       csring->last_event = evt;
+
+       /* Event handshaking with MAC TX */
+       CS_DESC(csring, fill++) = CTRL_CMD_T | CTRL_CMD_META_EVT | CTRL_CMD_O |
+                                 CTRL_CMD_ETYPE_SET | CTRL_CMD_REG(csring->events[evt]);
+       CS_DESC(csring, fill++) = 0;
+       CS_DESC(csring, fill++) = CTRL_CMD_T | CTRL_CMD_META_EVT | CTRL_CMD_O |
+                                 CTRL_CMD_ETYPE_WCLR | CTRL_CMD_REG(csring->events[!evt]);
+       CS_DESC(csring, fill++) = 0;
+       csring->next_to_fill = fill & (CS_RING_SIZE-1);
+
+       cs_size = fill - hdr;
+       write_dma_reg(PAS_DMA_TXCHAN_INCR(csring->chan.chno), (cs_size) >> 1);
+
+       /* TX-side event handshaking */
+       fill = txring->next_to_fill;
+       TX_DESC(txring, fill++) = CTRL_CMD_T | CTRL_CMD_META_EVT | CTRL_CMD_O |
+                                 CTRL_CMD_ETYPE_WSET | CTRL_CMD_REG(csring->events[evt]);
+       TX_DESC(txring, fill++) = 0;
+       TX_DESC(txring, fill++) = CTRL_CMD_T | CTRL_CMD_META_EVT | CTRL_CMD_O |
+                                 CTRL_CMD_ETYPE_CLR | CTRL_CMD_REG(csring->events[!evt]);
+       TX_DESC(txring, fill++) = 0;
+       txring->next_to_fill = fill;
+
+       write_dma_reg(PAS_DMA_TXCHAN_INCR(txring->chan.chno), 2);
+
+       return;
+}
+
 static int pasemi_mac_start_tx(struct sk_buff *skb, struct net_device *dev)
 {
-       struct pasemi_mac *mac = netdev_priv(dev);
-       struct pasemi_mac_txring *txring;
-       u64 dflags, mactx;
+       struct pasemi_mac * const mac = netdev_priv(dev);
+       struct pasemi_mac_txring * const txring = tx_ring(mac);
+       struct pasemi_mac_csring *csring;
+       u64 dflags = 0;
+       u64 mactx;
        dma_addr_t map[MAX_SKB_FRAGS+1];
        unsigned int map_size[MAX_SKB_FRAGS+1];
        unsigned long flags;
        int i, nfrags;
        int fill;
+       const int nh_off = skb_network_offset(skb);
+       const int nh_len = skb_network_header_len(skb);
 
-       dflags = XCT_MACTX_O | XCT_MACTX_ST | XCT_MACTX_CRC_PAD;
-
-       if (skb->ip_summed == CHECKSUM_PARTIAL) {
-               const unsigned char *nh = skb_network_header(skb);
+       prefetch(&txring->ring_info);
 
-               switch (ip_hdr(skb)->protocol) {
-               case IPPROTO_TCP:
-                       dflags |= XCT_MACTX_CSUM_TCP;
-                       dflags |= XCT_MACTX_IPH(skb_network_header_len(skb) >> 2);
-                       dflags |= XCT_MACTX_IPO(nh - skb->data);
-                       break;
-               case IPPROTO_UDP:
-                       dflags |= XCT_MACTX_CSUM_UDP;
-                       dflags |= XCT_MACTX_IPH(skb_network_header_len(skb) >> 2);
-                       dflags |= XCT_MACTX_IPO(nh - skb->data);
-                       break;
-               }
-       }
+       dflags = XCT_MACTX_O | XCT_MACTX_ST | XCT_MACTX_CRC_PAD;
 
        nfrags = skb_shinfo(skb)->nr_frags;
 
@@ -1350,24 +1527,46 @@ static int pasemi_mac_start_tx(struct sk_buff *skb, struct net_device *dev)
                }
        }
 
-       mactx = dflags | XCT_MACTX_LLEN(skb->len);
+       if (skb->ip_summed == CHECKSUM_PARTIAL && skb->len <= 1540) {
+               switch (ip_hdr(skb)->protocol) {
+               case IPPROTO_TCP:
+                       dflags |= XCT_MACTX_CSUM_TCP;
+                       dflags |= XCT_MACTX_IPH(nh_len >> 2);
+                       dflags |= XCT_MACTX_IPO(nh_off);
+                       break;
+               case IPPROTO_UDP:
+                       dflags |= XCT_MACTX_CSUM_UDP;
+                       dflags |= XCT_MACTX_IPH(nh_len >> 2);
+                       dflags |= XCT_MACTX_IPO(nh_off);
+                       break;
+               default:
+                       WARN_ON(1);
+               }
+       }
 
-       txring = tx_ring(mac);
+       mactx = dflags | XCT_MACTX_LLEN(skb->len);
 
        spin_lock_irqsave(&txring->lock, flags);
 
-       fill = txring->next_to_fill;
-
        /* Avoid stepping on the same cache line that the DMA controller
         * is currently about to send, so leave at least 8 words available.
         * Total free space needed is mactx + fragments + 8
         */
-       if (RING_AVAIL(txring) < nfrags + 10) {
+       if (RING_AVAIL(txring) < nfrags + 14) {
                /* no room -- stop the queue and wait for tx intr */
                netif_stop_queue(dev);
                goto out_err;
        }
 
+       /* Queue up checksum + event descriptors, if needed */
+       if (mac->num_cs && skb->ip_summed == CHECKSUM_PARTIAL && skb->len > 1540) {
+               csring = mac->cs[mac->last_cs];
+               mac->last_cs = (mac->last_cs + 1) % mac->num_cs;
+
+               pasemi_mac_queue_csdesc(skb, map, map_size, txring, csring);
+       }
+
+       fill = txring->next_to_fill;
        TX_DESC(txring, fill) = mactx;
        TX_DESC_INFO(txring, fill).dma = nfrags;
        fill++;
@@ -1445,8 +1644,9 @@ static int pasemi_mac_change_mtu(struct net_device *dev, int new_mtu)
 {
        struct pasemi_mac *mac = netdev_priv(dev);
        unsigned int reg;
-       unsigned int rcmdsta;
+       unsigned int rcmdsta = 0;
        int running;
+       int ret = 0;
 
        if (new_mtu < PE_MIN_MTU || new_mtu > PE_MAX_MTU)
                return -EINVAL;
@@ -1468,6 +1668,16 @@ static int pasemi_mac_change_mtu(struct net_device *dev, int new_mtu)
                pasemi_mac_pause_rxint(mac);
                pasemi_mac_clean_rx(rx_ring(mac), RX_RING_SIZE);
                pasemi_mac_free_rx_buffers(mac);
+
+       }
+
+       /* Setup checksum channels if large MTU and none already allocated */
+       if (new_mtu > 1500 && !mac->num_cs) {
+               pasemi_mac_setup_csrings(mac);
+               if (!mac->num_cs) {
+                       ret = -ENOMEM;
+                       goto out;
+               }
        }
 
        /* 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)
        /* MTU + ETH_HLEN + VLAN_HLEN + 2 64B cachelines */
        mac->bufsz = new_mtu + ETH_HLEN + ETH_FCS_LEN + LOCAL_SKB_ALIGN + 128;
 
+out:
        if (running) {
                write_dma_reg(PAS_DMA_RXINT_RCMDSTA(mac->dma_if),
                              rcmdsta | PAS_DMA_RXINT_RCMDSTA_EN);
@@ -1494,7 +1705,7 @@ static int pasemi_mac_change_mtu(struct net_device *dev, int new_mtu)
                pasemi_mac_intf_enable(mac);
        }
 
-       return 0;
+       return ret;
 }
 
 static int __devinit
@@ -1528,7 +1739,7 @@ pasemi_mac_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        netif_napi_add(dev, &mac->napi, pasemi_mac_poll, 64);
 
        dev->features = NETIF_F_IP_CSUM | NETIF_F_LLTX | NETIF_F_SG |
-                       NETIF_F_HIGHDMA;
+                       NETIF_F_HIGHDMA | NETIF_F_GSO;
 
        mac->lro_mgr.max_aggr = LRO_MAX_AGGR;
        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)
        mac->bufsz = dev->mtu + ETH_HLEN + ETH_FCS_LEN + LOCAL_SKB_ALIGN + 128;
 
        dev->change_mtu = pasemi_mac_change_mtu;
+       dev->ethtool_ops = &pasemi_mac_ethtool_ops;
 
        if (err)
                goto out;
index 99e7b9329a6fb5366936d62f399b513a676b5897..1a115ec60b531d4bf407f406716fc8ccf9ac72f0 100644 (file)
 #include <linux/spinlock.h>
 #include <linux/phy.h>
 
+/* Must be a power of two */
+#define RX_RING_SIZE 2048
+#define TX_RING_SIZE 4096
+#define CS_RING_SIZE (TX_RING_SIZE*2)
+
+
 #define MAX_LRO_DESCRIPTORS 8
+#define MAX_CS 2
 
 struct pasemi_mac_txring {
        struct pasemi_dmachan chan; /* Must be first */
@@ -51,6 +58,15 @@ struct pasemi_mac_rxring {
        struct pasemi_mac *mac; /* Needed in intr handler */
 };
 
+struct pasemi_mac_csring {
+       struct pasemi_dmachan chan;
+       unsigned int    size;
+       unsigned int    next_to_fill;
+       int             events[2];
+       int             last_event;
+       int             fun;
+};
+
 struct pasemi_mac {
        struct net_device *netdev;
        struct pci_dev *pdev;
@@ -60,10 +76,12 @@ struct pasemi_mac {
        struct napi_struct napi;
 
        int             bufsz; /* RX ring buffer size */
+       int             last_cs;
+       int             num_cs;
+       u32             dma_if;
        u8              type;
 #define MAC_TYPE_GMAC  1
 #define MAC_TYPE_XAUI  2
-       u32     dma_if;
 
        u8              mac_addr[6];
 
@@ -74,6 +92,7 @@ struct pasemi_mac {
 
        struct pasemi_mac_txring *tx;
        struct pasemi_mac_rxring *rx;
+       struct pasemi_mac_csring *cs[MAX_CS];
        char            tx_irq_name[10];                /* "eth%d tx" */
        char            rx_irq_name[10];                /* "eth%d rx" */
        int     link;
@@ -90,6 +109,16 @@ struct pasemi_mac_buffer {
        dma_addr_t      dma;
 };
 
+#define TX_DESC(tx, num)       ((tx)->chan.ring_virt[(num) & (TX_RING_SIZE-1)])
+#define TX_DESC_INFO(tx, num)  ((tx)->ring_info[(num) & (TX_RING_SIZE-1)])
+#define RX_DESC(rx, num)       ((rx)->chan.ring_virt[(num) & (RX_RING_SIZE-1)])
+#define RX_DESC_INFO(rx, num)  ((rx)->ring_info[(num) & (RX_RING_SIZE-1)])
+#define RX_BUFF(rx, num)       ((rx)->buffers[(num) & (RX_RING_SIZE-1)])
+#define CS_DESC(cs, num)       ((cs)->chan.ring_virt[(num) & (CS_RING_SIZE-1)])
+
+#define RING_USED(ring)        (((ring)->next_to_fill - (ring)->next_to_clean) \
+                               & ((ring)->size - 1))
+#define RING_AVAIL(ring)       ((ring->size) - RING_USED(ring))
 
 /* PCI register offsets and formats */
 
@@ -101,6 +130,7 @@ enum {
        PAS_MAC_CFG_ADR0 = 0x8c,
        PAS_MAC_CFG_ADR1 = 0x90,
        PAS_MAC_CFG_TXP = 0x98,
+       PAS_MAC_CFG_RMON = 0x100,
        PAS_MAC_IPC_CHNL = 0x208,
 };
 
@@ -172,6 +202,8 @@ enum {
 #define PAS_MAC_CFG_TXP_TIFG(x)                (((x) << PAS_MAC_CFG_TXP_TIFG_S) & \
                                         PAS_MAC_CFG_TXP_TIFG_M)
 
+#define PAS_MAC_RMON(r)                        (0x100+(r)*4)
+
 #define PAS_MAC_IPC_CHNL_DCHNO_M       0x003f0000
 #define PAS_MAC_IPC_CHNL_DCHNO_S       16
 #define PAS_MAC_IPC_CHNL_DCHNO(x)      (((x) << PAS_MAC_IPC_CHNL_DCHNO_S) & \
@@ -181,4 +213,5 @@ enum {
 #define PAS_MAC_IPC_CHNL_BCH(x)                (((x) << PAS_MAC_IPC_CHNL_BCH_S) & \
                                         PAS_MAC_IPC_CHNL_BCH_M)
 
+
 #endif /* PASEMI_MAC_H */
diff --git a/drivers/net/pasemi_mac_ethtool.c b/drivers/net/pasemi_mac_ethtool.c
new file mode 100644 (file)
index 0000000..5e8df3a
--- /dev/null
@@ -0,0 +1,159 @@
+/*
+ * Copyright (C) 2006-2008 PA Semi, Inc
+ *
+ * Ethtool hooks for the PA Semi PWRficient onchip 1G/10G Ethernet MACs
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ */
+
+
+#include <linux/netdevice.h>
+#include <linux/ethtool.h>
+#include <linux/pci.h>
+#include <linux/inet_lro.h>
+
+#include <asm/pasemi_dma.h>
+#include "pasemi_mac.h"
+
+static struct {
+       const char str[ETH_GSTRING_LEN];
+} ethtool_stats_keys[] = {
+       { "rx-drops" },
+       { "rx-bytes" },
+       { "rx-packets" },
+       { "rx-broadcast-packets" },
+       { "rx-multicast-packets" },
+       { "rx-crc-errors" },
+       { "rx-undersize-errors" },
+       { "rx-oversize-errors" },
+       { "rx-short-fragment-errors" },
+       { "rx-jabber-errors" },
+       { "rx-64-byte-packets" },
+       { "rx-65-127-byte-packets" },
+       { "rx-128-255-byte-packets" },
+       { "rx-256-511-byte-packets" },
+       { "rx-512-1023-byte-packets" },
+       { "rx-1024-1518-byte-packets" },
+       { "rx-pause-frames" },
+       { "tx-bytes" },
+       { "tx-packets" },
+       { "tx-broadcast-packets" },
+       { "tx-multicast-packets" },
+       { "tx-collisions" },
+       { "tx-late-collisions" },
+       { "tx-excessive-collisions" },
+       { "tx-crc-errors" },
+       { "tx-undersize-errors" },
+       { "tx-oversize-errors" },
+       { "tx-64-byte-packets" },
+       { "tx-65-127-byte-packets" },
+       { "tx-128-255-byte-packets" },
+       { "tx-256-511-byte-packets" },
+       { "tx-512-1023-byte-packets" },
+       { "tx-1024-1518-byte-packets" },
+};
+
+static int
+pasemi_mac_ethtool_get_settings(struct net_device *netdev,
+                              struct ethtool_cmd *cmd)
+{
+       struct pasemi_mac *mac = netdev_priv(netdev);
+       struct phy_device *phydev = mac->phydev;
+
+       return phy_ethtool_gset(phydev, cmd);
+}
+
+static void
+pasemi_mac_ethtool_get_drvinfo(struct net_device *netdev,
+                              struct ethtool_drvinfo *drvinfo)
+{
+       struct pasemi_mac *mac;
+       mac = netdev_priv(netdev);
+
+       /* clear and fill out info */
+       memset(drvinfo, 0, sizeof(struct ethtool_drvinfo));
+       strncpy(drvinfo->driver, "pasemi_mac", 12);
+       strcpy(drvinfo->version, "N/A");
+       strcpy(drvinfo->fw_version, "N/A");
+       strncpy(drvinfo->bus_info, pci_name(mac->pdev), 32);
+}
+
+static u32
+pasemi_mac_ethtool_get_msglevel(struct net_device *netdev)
+{
+       struct pasemi_mac *mac = netdev_priv(netdev);
+       return mac->msg_enable;
+}
+
+static void
+pasemi_mac_ethtool_set_msglevel(struct net_device *netdev,
+                               u32 level)
+{
+       struct pasemi_mac *mac = netdev_priv(netdev);
+       mac->msg_enable = level;
+}
+
+
+static void
+pasemi_mac_ethtool_get_ringparam(struct net_device *netdev,
+                                struct ethtool_ringparam *ering)
+{
+       struct pasemi_mac *mac = netdev->priv;
+
+       ering->tx_max_pending = TX_RING_SIZE/2;
+       ering->tx_pending = RING_USED(mac->tx)/2;
+       ering->rx_max_pending = RX_RING_SIZE/4;
+       ering->rx_pending = RING_USED(mac->rx)/4;
+}
+
+static int pasemi_mac_get_sset_count(struct net_device *netdev, int sset)
+{
+       switch (sset) {
+       case ETH_SS_STATS:
+               return ARRAY_SIZE(ethtool_stats_keys);
+       default:
+               return -EOPNOTSUPP;
+       }
+}
+
+static void pasemi_mac_get_ethtool_stats(struct net_device *netdev,
+               struct ethtool_stats *stats, u64 *data)
+{
+       struct pasemi_mac *mac = netdev->priv;
+       int i;
+
+       data[0] = pasemi_read_dma_reg(PAS_DMA_RXINT_RCMDSTA(mac->dma_if))
+                       >> PAS_DMA_RXINT_RCMDSTA_DROPS_S;
+       for (i = 0; i < 32; i++)
+               data[1+i] = pasemi_read_mac_reg(mac->dma_if, PAS_MAC_RMON(i));
+}
+
+static void pasemi_mac_get_strings(struct net_device *netdev, u32 stringset,
+                                  u8 *data)
+{
+       memcpy(data, ethtool_stats_keys, sizeof(ethtool_stats_keys));
+}
+
+const struct ethtool_ops pasemi_mac_ethtool_ops = {
+       .get_settings           = pasemi_mac_ethtool_get_settings,
+       .get_drvinfo            = pasemi_mac_ethtool_get_drvinfo,
+       .get_msglevel           = pasemi_mac_ethtool_get_msglevel,
+       .set_msglevel           = pasemi_mac_ethtool_set_msglevel,
+       .get_link               = ethtool_op_get_link,
+       .get_ringparam          = pasemi_mac_ethtool_get_ringparam,
+       .get_strings            = pasemi_mac_get_strings,
+       .get_sset_count         = pasemi_mac_get_sset_count,
+       .get_ethtool_stats      = pasemi_mac_get_ethtool_stats,
+};
+
index 4aa220718b19a09b00cd137ca384bc4a7fa9f292..98324c5a82867cfa5ace5179de635220ab5d01a4 100644 (file)
  * 2 of the License, or (at your option) any later version.
  */
 
+#include <linux/lmb.h>
+
 #include <asm/types.h>
 #include <asm/page.h>
 #include <asm/prom.h>
-#include <asm/lmb.h>
 #include <asm/firmware.h>
 
 struct mschunks_map {
index 8485c28b5f47efa58d0eb752d45f2c5a3a483661..fb11b0c459b832912cabee81141517a38d136ba6 100644 (file)
@@ -35,7 +35,7 @@ static inline cpumask_t cpu_thread_mask_to_cores(cpumask_t threads)
 
        res = CPU_MASK_NONE;
        for (i = 0; i < NR_CPUS; i += threads_per_core) {
-               cpus_shift_right(tmp, threads_core_mask, i);
+               cpus_shift_left(tmp, threads_core_mask, i);
                if (cpus_intersects(threads, tmp))
                        cpu_set(i, res);
        }
index 5d1dc48a0bb830229f0dd90ae561ab71d6b769f1..028184b6a16244954dabcc45a256fe3bb0cf649e 100644 (file)
@@ -1,81 +1,15 @@
 #ifndef _ASM_POWERPC_LMB_H
 #define _ASM_POWERPC_LMB_H
-#ifdef __KERNEL__
 
-/*
- * Definitions for talking to the Open Firmware PROM on
- * Power Macintosh computers.
- *
- * Copyright (C) 2001 Peter Bergner, IBM Corp.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
- */
+#include <asm/udbg.h>
 
-#include <linux/init.h>
-#include <asm/prom.h>
+#define LMB_DBG(fmt...) udbg_printf(fmt)
 
-#define MAX_LMB_REGIONS 128
+#ifdef CONFIG_PPC32
+extern unsigned long __max_low_memory;
+#define LMB_REAL_LIMIT __max_low_memory
+#else
+#define LMB_REAL_LIMIT 0
+#endif
 
-struct lmb_property {
-       unsigned long base;
-       unsigned long size;
-};
-
-struct lmb_region {
-       unsigned long cnt;
-       unsigned long size;
-       struct lmb_property region[MAX_LMB_REGIONS+1];
-};
-
-struct lmb {
-       unsigned long debug;
-       unsigned long rmo_size;
-       struct lmb_region memory;
-       struct lmb_region reserved;
-};
-
-extern struct lmb lmb;
-
-extern void __init lmb_init(void);
-extern void __init lmb_analyze(void);
-extern long __init lmb_add(unsigned long base, unsigned long size);
-extern long __init lmb_reserve(unsigned long base, unsigned long size);
-extern unsigned long __init lmb_alloc(unsigned long size, unsigned long align);
-extern unsigned long __init lmb_alloc_base(unsigned long size,
-               unsigned long align, unsigned long max_addr);
-extern unsigned long __init __lmb_alloc_base(unsigned long size,
-               unsigned long align, unsigned long max_addr);
-extern unsigned long __init lmb_phys_mem_size(void);
-extern unsigned long __init lmb_end_of_DRAM(void);
-extern void __init lmb_enforce_memory_limit(unsigned long memory_limit);
-extern int __init lmb_is_reserved(unsigned long addr);
-
-extern void lmb_dump_all(void);
-
-static inline unsigned long
-lmb_size_bytes(struct lmb_region *type, unsigned long region_nr)
-{
-       return type->region[region_nr].size;
-}
-static inline unsigned long
-lmb_size_pages(struct lmb_region *type, unsigned long region_nr)
-{
-       return lmb_size_bytes(type, region_nr) >> PAGE_SHIFT;
-}
-static inline unsigned long
-lmb_start_pfn(struct lmb_region *type, unsigned long region_nr)
-{
-       return type->region[region_nr].base >> PAGE_SHIFT;
-}
-static inline unsigned long
-lmb_end_pfn(struct lmb_region *type, unsigned long region_nr)
-{
-       return lmb_start_pfn(type, region_nr) +
-              lmb_size_pages(type, region_nr);
-}
-
-#endif /* __KERNEL__ */
 #endif /* _ASM_POWERPC_LMB_H */
index 0872ec228c1e45d1e27c094f37a8c948823850bf..b95386aed50d15bd1063ea39d228e189d6df1491 100644 (file)
@@ -68,6 +68,8 @@ struct machdep_calls {
                                       unsigned long vflags,
                                       int psize, int ssize);
        long            (*hpte_remove)(unsigned long hpte_group);
+       void            (*hpte_removebolted)(unsigned long ea,
+                                            int psize, int ssize);
        void            (*flush_hash_range)(unsigned long number, int local);
 
        /* special for kexec, to be called in real mode, linar mapping is
index b4526ff3a50d4eb5bef209cf31dd1a98ad171f2f..19fd7933e2d91a682231428641b2fa5ee52ac559 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2006 PA Semi, Inc
+ * Copyright (C) 2006-2008 PA Semi, Inc
  *
  * Hardware register layout and descriptor formats for the on-board
  * DMA engine on PA Semi PWRficient. Used by ethernet, function and security
@@ -40,6 +40,11 @@ enum {
        PAS_DMA_COM_TXSTA = 0x104,      /* Transmit Status Register   */
        PAS_DMA_COM_RXCMD = 0x108,      /* Receive Command Register   */
        PAS_DMA_COM_RXSTA = 0x10c,      /* Receive Status Register    */
+       PAS_DMA_COM_CFG   = 0x114,      /* Common config reg          */
+       PAS_DMA_TXF_SFLG0 = 0x140,      /* Set flags                  */
+       PAS_DMA_TXF_SFLG1 = 0x144,      /* Set flags                  */
+       PAS_DMA_TXF_CFLG0 = 0x148,      /* Set flags                  */
+       PAS_DMA_TXF_CFLG1 = 0x14c,      /* Set flags                  */
 };
 
 
@@ -123,11 +128,16 @@ enum {
 #define    PAS_DMA_TXCHAN_TCMDSTA_DA   0x00000100
 #define PAS_DMA_TXCHAN_CFG(c)     (0x304+(c)*_PAS_DMA_TXCHAN_STRIDE)
 #define    PAS_DMA_TXCHAN_CFG_TY_IFACE 0x00000000      /* Type = interface */
+#define    PAS_DMA_TXCHAN_CFG_TY_COPY  0x00000001      /* Type = copy only */
+#define    PAS_DMA_TXCHAN_CFG_TY_FUNC  0x00000002      /* Type = function */
+#define    PAS_DMA_TXCHAN_CFG_TY_XOR   0x00000003      /* Type = xor only */
 #define    PAS_DMA_TXCHAN_CFG_TATTR_M  0x0000003c
 #define    PAS_DMA_TXCHAN_CFG_TATTR_S  2
 #define    PAS_DMA_TXCHAN_CFG_TATTR(x) (((x) << PAS_DMA_TXCHAN_CFG_TATTR_S) & \
                                         PAS_DMA_TXCHAN_CFG_TATTR_M)
-#define    PAS_DMA_TXCHAN_CFG_WT_M     0x000001c0
+#define    PAS_DMA_TXCHAN_CFG_LPDQ     0x00000800
+#define    PAS_DMA_TXCHAN_CFG_LPSQ     0x00000400
+#define    PAS_DMA_TXCHAN_CFG_WT_M     0x000003c0
 #define    PAS_DMA_TXCHAN_CFG_WT_S     6
 #define    PAS_DMA_TXCHAN_CFG_WT(x)    (((x) << PAS_DMA_TXCHAN_CFG_WT_S) & \
                                         PAS_DMA_TXCHAN_CFG_WT_M)
@@ -394,11 +404,62 @@ enum {
                                 XCT_COPY_LLEN_M)
 #define XCT_COPY_SE            0x0000000000000001ull
 
+/* Function descriptor fields */
+#define XCT_FUN_T              0x8000000000000000ull
+#define XCT_FUN_ST             0x4000000000000000ull
+#define XCT_FUN_RR_M           0x3000000000000000ull
+#define XCT_FUN_RR_NORES       0x0000000000000000ull
+#define XCT_FUN_RR_8BRES       0x1000000000000000ull
+#define XCT_FUN_RR_24BRES      0x2000000000000000ull
+#define XCT_FUN_RR_40BRES      0x3000000000000000ull
+#define XCT_FUN_I              0x0800000000000000ull
+#define XCT_FUN_O              0x0400000000000000ull
+#define XCT_FUN_E              0x0200000000000000ull
+#define XCT_FUN_FUN_M          0x01c0000000000000ull
+#define XCT_FUN_FUN_S          54
+#define XCT_FUN_FUN(x)         ((((long)(x)) << XCT_FUN_FUN_S) & XCT_FUN_FUN_M)
+#define XCT_FUN_CRM_M          0x0038000000000000ull
+#define XCT_FUN_CRM_NOP                0x0000000000000000ull
+#define XCT_FUN_CRM_SIG                0x0008000000000000ull
+#define XCT_FUN_LLEN_M         0x0007ffff00000000ull
+#define XCT_FUN_LLEN_S         32
+#define XCT_FUN_LLEN(x)                ((((long)(x)) << XCT_FUN_LLEN_S) & XCT_FUN_LLEN_M)
+#define XCT_FUN_SHL_M          0x00000000f8000000ull
+#define XCT_FUN_SHL_S          27
+#define XCT_FUN_SHL(x)         ((((long)(x)) << XCT_FUN_SHL_S) & XCT_FUN_SHL_M)
+#define XCT_FUN_CHL_M          0x0000000007c00000ull
+#define XCT_FUN_HSZ_M          0x00000000003c0000ull
+#define XCT_FUN_ALG_M          0x0000000000038000ull
+#define XCT_FUN_HP             0x0000000000004000ull
+#define XCT_FUN_BCM_M          0x0000000000003800ull
+#define XCT_FUN_BCP_M          0x0000000000000600ull
+#define XCT_FUN_SIG_M          0x00000000000001f0ull
+#define XCT_FUN_SIG_TCP4       0x0000000000000140ull
+#define XCT_FUN_SIG_TCP6       0x0000000000000150ull
+#define XCT_FUN_SIG_UDP4       0x0000000000000160ull
+#define XCT_FUN_SIG_UDP6       0x0000000000000170ull
+#define XCT_FUN_A              0x0000000000000008ull
+#define XCT_FUN_C              0x0000000000000004ull
+#define XCT_FUN_AL2            0x0000000000000002ull
+#define XCT_FUN_SE             0x0000000000000001ull
+
+/* Function descriptor 8byte result fields */
+#define XCT_FUNRES_8B_CS_M     0x0000ffff00000000ull
+#define XCT_FUNRES_8B_CS_S     32
+#define XCT_FUNRES_8B_CRC_M    0x00000000ffffffffull
+#define XCT_FUNRES_8B_CRC_S    0
+
 /* Control descriptor fields */
 #define CTRL_CMD_T             0x8000000000000000ull
 #define CTRL_CMD_META_EVT      0x2000000000000000ull
 #define CTRL_CMD_O             0x0400000000000000ull
-#define CTRL_CMD_REG_M         0x000000000000000full
+#define CTRL_CMD_ETYPE_M       0x0038000000000000ull
+#define CTRL_CMD_ETYPE_EXT     0x0000000000000000ull
+#define CTRL_CMD_ETYPE_WSET    0x0020000000000000ull
+#define CTRL_CMD_ETYPE_WCLR    0x0028000000000000ull
+#define CTRL_CMD_ETYPE_SET     0x0030000000000000ull
+#define CTRL_CMD_ETYPE_CLR     0x0038000000000000ull
+#define CTRL_CMD_REG_M         0x000000000000007full
 #define CTRL_CMD_REG_S         0
 #define CTRL_CMD_REG(x)                ((((long)(x)) << CTRL_CMD_REG_S) & \
                                 CTRL_CMD_REG_M)
@@ -461,6 +522,16 @@ extern void *pasemi_dma_alloc_buf(struct pasemi_dmachan *chan, int size,
 extern void pasemi_dma_free_buf(struct pasemi_dmachan *chan, int size,
                                dma_addr_t *handle);
 
+/* Routines to allocate flags (events) for channel syncronization */
+extern int  pasemi_dma_alloc_flag(void);
+extern void pasemi_dma_free_flag(int flag);
+extern void pasemi_dma_set_flag(int flag);
+extern void pasemi_dma_clear_flag(int flag);
+
+/* Routines to allocate function engines */
+extern int  pasemi_dma_alloc_fun(void);
+extern void pasemi_dma_free_fun(int fun);
+
 /* Initialize the library, must be called before any other functions */
 extern int pasemi_dma_init(void);
 
index e8b493d52b4f68a6807ed25475262b47e4defbd7..c5acf4ccf57198dba85e3ce895de6aefbb433609 100644 (file)
@@ -15,6 +15,7 @@
 
 #ifdef CONFIG_MEMORY_HOTPLUG
 extern void create_section_mapping(unsigned long start, unsigned long end);
+extern void remove_section_mapping(unsigned long start, unsigned long end);
 #ifdef CONFIG_NUMA
 extern int hot_add_scn_to_nid(unsigned long scn_addr);
 #else
diff --git a/include/asm-sparc64/lmb.h b/include/asm-sparc64/lmb.h
new file mode 100644 (file)
index 0000000..6a352cb
--- /dev/null
@@ -0,0 +1,10 @@
+#ifndef _SPARC64_LMB_H
+#define _SPARC64_LMB_H
+
+#include <asm/oplib.h>
+
+#define LMB_DBG(fmt...) prom_printf(fmt)
+
+#define LMB_REAL_LIMIT 0
+
+#endif /* !(_SPARC64_LMB_H) */
diff --git a/include/linux/lmb.h b/include/linux/lmb.h
new file mode 100644 (file)
index 0000000..632717c
--- /dev/null
@@ -0,0 +1,83 @@
+#ifndef _LINUX_LMB_H
+#define _LINUX_LMB_H
+#ifdef __KERNEL__
+
+/*
+ * Logical memory blocks.
+ *
+ * Copyright (C) 2001 Peter Bergner, IBM Corp.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/init.h>
+#include <linux/mm.h>
+
+#define MAX_LMB_REGIONS 128
+
+struct lmb_property {
+       u64 base;
+       u64 size;
+};
+
+struct lmb_region {
+       unsigned long cnt;
+       u64 size;
+       struct lmb_property region[MAX_LMB_REGIONS+1];
+};
+
+struct lmb {
+       unsigned long debug;
+       u64 rmo_size;
+       struct lmb_region memory;
+       struct lmb_region reserved;
+};
+
+extern struct lmb lmb;
+
+extern void __init lmb_init(void);
+extern void __init lmb_analyze(void);
+extern long __init lmb_add(u64 base, u64 size);
+extern long __init lmb_reserve(u64 base, u64 size);
+extern u64 __init lmb_alloc(u64 size, u64 align);
+extern u64 __init lmb_alloc_base(u64 size,
+               u64, u64 max_addr);
+extern u64 __init __lmb_alloc_base(u64 size,
+               u64 align, u64 max_addr);
+extern u64 __init lmb_phys_mem_size(void);
+extern u64 __init lmb_end_of_DRAM(void);
+extern void __init lmb_enforce_memory_limit(u64 memory_limit);
+extern int __init lmb_is_reserved(u64 addr);
+
+extern void lmb_dump_all(void);
+
+static inline u64
+lmb_size_bytes(struct lmb_region *type, unsigned long region_nr)
+{
+       return type->region[region_nr].size;
+}
+static inline u64
+lmb_size_pages(struct lmb_region *type, unsigned long region_nr)
+{
+       return lmb_size_bytes(type, region_nr) >> PAGE_SHIFT;
+}
+static inline u64
+lmb_start_pfn(struct lmb_region *type, unsigned long region_nr)
+{
+       return type->region[region_nr].base >> PAGE_SHIFT;
+}
+static inline u64
+lmb_end_pfn(struct lmb_region *type, unsigned long region_nr)
+{
+       return lmb_start_pfn(type, region_nr) +
+              lmb_size_pages(type, region_nr);
+}
+
+#include <asm/lmb.h>
+
+#endif /* __KERNEL__ */
+
+#endif /* _LINUX_LMB_H */
index ba3d104994d914643e4c673b1058e0c4a57cd813..2d53dc092e8b1670bd26e6e3c6210f01caa54a29 100644 (file)
@@ -141,4 +141,7 @@ config HAS_DMA
 config CHECK_SIGNATURE
        bool
 
+config HAVE_LMB
+       boolean
+
 endmenu
index 23de261a4c83cfdd040a81618f5f77bac630a38e..61bba16a0a2fb85ab34b7f1c96faac5115d37cb4 100644 (file)
@@ -70,6 +70,8 @@ obj-$(CONFIG_FAULT_INJECTION) += fault-inject.o
 
 lib-$(CONFIG_GENERIC_BUG) += bug.o
 
+obj-$(CONFIG_HAVE_LMB) += lmb.o
+
 hostprogs-y    := gen_crc32table
 clean-files    := crc32table.h
 
similarity index 68%
rename from arch/powerpc/mm/lmb.c
rename to lib/lmb.c
index 4ce23bcf8a57e8a641579b5fab466c7eaf3172e3..3c43b95fef4a332151918ca61769c47806b8c03f 100644 (file)
+++ b/lib/lmb.c
@@ -3,7 +3,7 @@
  *
  * Peter Bergner, IBM Corp.    June 2001.
  * Copyright (C) 2001 Peter Bergner.
- * 
+ *
  *      This program is free software; you can redistribute it and/or
  *      modify it under the terms of the GNU General Public License
  *      as published by the Free Software Foundation; either version
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/bitops.h>
-#include <asm/types.h>
-#include <asm/page.h>
-#include <asm/prom.h>
-#include <asm/lmb.h>
-#ifdef CONFIG_PPC32
-#include "mmu_decl.h"          /* for __max_low_memory */
-#endif
+#include <linux/lmb.h>
 
 #undef DEBUG
 
 #ifdef DEBUG
-#include <asm/udbg.h>
-#define DBG(fmt...) udbg_printf(fmt)
+#define DBG(fmt...) LMB_DBG(fmt)
 #else
 #define DBG(fmt...)
 #endif
@@ -41,33 +34,34 @@ void lmb_dump_all(void)
 
        DBG("lmb_dump_all:\n");
        DBG("    memory.cnt               = 0x%lx\n", lmb.memory.cnt);
-       DBG("    memory.size              = 0x%lx\n", lmb.memory.size);
+       DBG("    memory.size              = 0x%llx\n",
+           (unsigned long long)lmb.memory.size);
        for (i=0; i < lmb.memory.cnt ;i++) {
-               DBG("    memory.region[0x%x].base       = 0x%lx\n",
-                           i, lmb.memory.region[i].base);
-               DBG("                 .size     = 0x%lx\n",
-                           lmb.memory.region[i].size);
+               DBG("    memory.region[0x%x].base       = 0x%llx\n",
+                   i, (unsigned long long)lmb.memory.region[i].base);
+               DBG("                 .size     = 0x%llx\n",
+                   (unsigned long long)lmb.memory.region[i].size);
        }
 
        DBG("\n    reserved.cnt   = 0x%lx\n", lmb.reserved.cnt);
        DBG("    reserved.size    = 0x%lx\n", lmb.reserved.size);
        for (i=0; i < lmb.reserved.cnt ;i++) {
-               DBG("    reserved.region[0x%x].base       = 0x%lx\n",
-                           i, lmb.reserved.region[i].base);
-               DBG("                 .size     = 0x%lx\n",
-                           lmb.reserved.region[i].size);
+               DBG("    reserved.region[0x%x].base       = 0x%llx\n",
+                   i, (unsigned long long)lmb.reserved.region[i].base);
+               DBG("                 .size     = 0x%llx\n",
+                   (unsigned long long)lmb.reserved.region[i].size);
        }
 #endif /* DEBUG */
 }
 
-static unsigned long __init lmb_addrs_overlap(unsigned long base1,
-               unsigned long size1, unsigned long base2, unsigned long size2)
+static unsigned long __init lmb_addrs_overlap(u64 base1,
+               u64 size1, u64 base2, u64 size2)
 {
        return ((base1 < (base2+size2)) && (base2 < (base1+size1)));
 }
 
-static long __init lmb_addrs_adjacent(unsigned long base1, unsigned long size1,
-               unsigned long base2, unsigned long size2)
+static long __init lmb_addrs_adjacent(u64 base1, u64 size1,
+               u64 base2, u64 size2)
 {
        if (base2 == base1 + size1)
                return 1;
@@ -80,10 +74,10 @@ static long __init lmb_addrs_adjacent(unsigned long base1, unsigned long size1,
 static long __init lmb_regions_adjacent(struct lmb_region *rgn,
                unsigned long r1, unsigned long r2)
 {
-       unsigned long base1 = rgn->region[r1].base;
-       unsigned long size1 = rgn->region[r1].size;
-       unsigned long base2 = rgn->region[r2].base;
-       unsigned long size2 = rgn->region[r2].size;
+       u64 base1 = rgn->region[r1].base;
+       u64 size1 = rgn->region[r1].size;
+       u64 base2 = rgn->region[r2].base;
+       u64 size2 = rgn->region[r2].size;
 
        return lmb_addrs_adjacent(base1, size1, base2, size2);
 }
@@ -135,16 +129,21 @@ void __init lmb_analyze(void)
 }
 
 /* This routine called with relocation disabled. */
-static long __init lmb_add_region(struct lmb_region *rgn, unsigned long base,
-                                 unsigned long size)
+static long __init lmb_add_region(struct lmb_region *rgn, u64 base, u64 size)
 {
        unsigned long coalesced = 0;
        long adjacent, i;
 
+       if ((rgn->cnt == 1) && (rgn->region[0].size == 0)) {
+               rgn->region[0].base = base;
+               rgn->region[0].size = size;
+               return 0;
+       }
+
        /* First try and coalesce this LMB with another. */
        for (i=0; i < rgn->cnt; i++) {
-               unsigned long rgnbase = rgn->region[i].base;
-               unsigned long rgnsize = rgn->region[i].size;
+               u64 rgnbase = rgn->region[i].base;
+               u64 rgnsize = rgn->region[i].size;
 
                if ((rgnbase == base) && (rgnsize == size))
                        /* 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,
                        break;
                }
        }
+
+       if (base < rgn->region[0].base) {
+               rgn->region[0].base = base;
+               rgn->region[0].size = size;
+       }
        rgn->cnt++;
 
        return 0;
 }
 
 /* This routine may be called with relocation disabled. */
-long __init lmb_add(unsigned long base, unsigned long size)
+long __init lmb_add(u64 base, u64 size)
 {
        struct lmb_region *_rgn = &(lmb.memory);
 
@@ -203,7 +207,7 @@ long __init lmb_add(unsigned long base, unsigned long size)
 
 }
 
-long __init lmb_reserve(unsigned long base, unsigned long size)
+long __init lmb_reserve(u64 base, u64 size)
 {
        struct lmb_region *_rgn = &(lmb.reserved);
 
@@ -212,14 +216,14 @@ long __init lmb_reserve(unsigned long base, unsigned long size)
        return lmb_add_region(_rgn, base, size);
 }
 
-long __init lmb_overlaps_region(struct lmb_region *rgn, unsigned long base,
-                               unsigned long size)
+long __init lmb_overlaps_region(struct lmb_region *rgn, u64 base,
+                               u64 size)
 {
        unsigned long i;
 
        for (i=0; i < rgn->cnt; i++) {
-               unsigned long rgnbase = rgn->region[i].base;
-               unsigned long rgnsize = rgn->region[i].size;
+               u64 rgnbase = rgn->region[i].base;
+               u64 rgnsize = rgn->region[i].size;
                if ( lmb_addrs_overlap(base,size,rgnbase,rgnsize) ) {
                        break;
                }
@@ -228,54 +232,61 @@ long __init lmb_overlaps_region(struct lmb_region *rgn, unsigned long base,
        return (i < rgn->cnt) ? i : -1;
 }
 
-unsigned long __init lmb_alloc(unsigned long size, unsigned long align)
+u64 __init lmb_alloc(u64 size, u64 align)
 {
        return lmb_alloc_base(size, align, LMB_ALLOC_ANYWHERE);
 }
 
-unsigned long __init lmb_alloc_base(unsigned long size, unsigned long align,
-                                   unsigned long max_addr)
+u64 __init lmb_alloc_base(u64 size, u64 align, u64 max_addr)
 {
-       unsigned long alloc;
+       u64 alloc;
 
        alloc = __lmb_alloc_base(size, align, max_addr);
 
        if (alloc == 0)
-               panic("ERROR: Failed to allocate 0x%lx bytes below 0x%lx.\n",
-                               size, max_addr);
+               panic("ERROR: Failed to allocate 0x%llx bytes below 0x%llx.\n",
+                     (unsigned long long) size, (unsigned long long) max_addr);
 
        return alloc;
 }
 
-unsigned long __init __lmb_alloc_base(unsigned long size, unsigned long align,
-                                   unsigned long max_addr)
+static u64 lmb_align_down(u64 addr, u64 size)
+{
+       return addr & ~(size - 1);
+}
+
+static u64 lmb_align_up(u64 addr, u64 size)
+{
+       return (addr + (size - 1)) & ~(size - 1);
+}
+
+u64 __init __lmb_alloc_base(u64 size, u64 align, u64 max_addr)
 {
        long i, j;
-       unsigned long base = 0;
+       u64 base = 0;
 
        BUG_ON(0 == size);
 
-#ifdef CONFIG_PPC32
-       /* On 32-bit, make sure we allocate lowmem */
+       /* On some platforms, make sure we allocate lowmem */
        if (max_addr == LMB_ALLOC_ANYWHERE)
-               max_addr = __max_low_memory;
-#endif
+               max_addr = LMB_REAL_LIMIT;
+
        for (i = lmb.memory.cnt-1; i >= 0; i--) {
-               unsigned long lmbbase = lmb.memory.region[i].base;
-               unsigned long lmbsize = lmb.memory.region[i].size;
+               u64 lmbbase = lmb.memory.region[i].base;
+               u64 lmbsize = lmb.memory.region[i].size;
 
                if (max_addr == LMB_ALLOC_ANYWHERE)
-                       base = _ALIGN_DOWN(lmbbase + lmbsize - size, align);
+                       base = lmb_align_down(lmbbase + lmbsize - size, align);
                else if (lmbbase < max_addr) {
                        base = min(lmbbase + lmbsize, max_addr);
-                       base = _ALIGN_DOWN(base - size, align);
+                       base = lmb_align_down(base - size, align);
                } else
                        continue;
 
                while ((lmbbase <= base) &&
                       ((j = lmb_overlaps_region(&lmb.reserved, base, size)) >= 0) )
-                       base = _ALIGN_DOWN(lmb.reserved.region[j].base - size,
-                                          align);
+                       base = lmb_align_down(lmb.reserved.region[j].base - size,
+                                             align);
 
                if ((base != 0) && (lmbbase <= base))
                        break;
@@ -284,18 +295,19 @@ unsigned long __init __lmb_alloc_base(unsigned long size, unsigned long align,
        if (i < 0)
                return 0;
 
-       lmb_add_region(&lmb.reserved, base, size);
+       if (lmb_add_region(&lmb.reserved, base, lmb_align_up(size, align)) < 0)
+               return 0;
 
        return base;
 }
 
 /* You must call lmb_analyze() before this. */
-unsigned long __init lmb_phys_mem_size(void)
+u64 __init lmb_phys_mem_size(void)
 {
        return lmb.memory.size;
 }
 
-unsigned long __init lmb_end_of_DRAM(void)
+u64 __init lmb_end_of_DRAM(void)
 {
        int idx = lmb.memory.cnt - 1;
 
@@ -303,9 +315,10 @@ unsigned long __init lmb_end_of_DRAM(void)
 }
 
 /* You must call lmb_analyze() after this. */
-void __init lmb_enforce_memory_limit(unsigned long memory_limit)
+void __init lmb_enforce_memory_limit(u64 memory_limit)
 {
-       unsigned long i, limit;
+       unsigned long i;
+       u64 limit;
        struct lmb_property *p;
 
        if (! memory_limit)
@@ -343,13 +356,13 @@ void __init lmb_enforce_memory_limit(unsigned long memory_limit)
        }
 }
 
-int __init lmb_is_reserved(unsigned long addr)
+int __init lmb_is_reserved(u64 addr)
 {
        int i;
 
        for (i = 0; i < lmb.reserved.cnt; i++) {
-               unsigned long upper = lmb.reserved.region[i].base +
-                                     lmb.reserved.region[i].size - 1;
+               u64 upper = lmb.reserved.region[i].base +
+                       lmb.reserved.region[i].size - 1;
                if ((addr >= lmb.reserved.region[i].base) && (addr <= upper))
                        return 1;
        }