6194 lines
196 KiB
Diff
6194 lines
196 KiB
Diff
diff --git a/Makefile b/Makefile
|
|
index f124b18..794fa28 100644
|
|
diff --git a/arch/cris/arch-v10/drivers/sync_serial.c b/arch/cris/arch-v10/drivers/sync_serial.c
|
|
index 85026537..466af40 100644
|
|
--- a/arch/cris/arch-v10/drivers/sync_serial.c
|
|
+++ b/arch/cris/arch-v10/drivers/sync_serial.c
|
|
@@ -158,7 +158,7 @@ static int sync_serial_open(struct inode *inode, struct file *file);
|
|
static int sync_serial_release(struct inode *inode, struct file *file);
|
|
static unsigned int sync_serial_poll(struct file *filp, poll_table *wait);
|
|
|
|
-static int sync_serial_ioctl(struct file *file,
|
|
+static long sync_serial_ioctl(struct file *file,
|
|
unsigned int cmd, unsigned long arg);
|
|
static ssize_t sync_serial_write(struct file *file, const char *buf,
|
|
size_t count, loff_t *ppos);
|
|
@@ -625,11 +625,11 @@ static int sync_serial_open(struct inode *inode, struct file *file)
|
|
*R_IRQ_MASK1_SET = 1 << port->data_avail_bit;
|
|
DEBUG(printk(KERN_DEBUG "sser%d rec started\n", dev));
|
|
}
|
|
- ret = 0;
|
|
+ err = 0;
|
|
|
|
out:
|
|
mutex_unlock(&sync_serial_mutex);
|
|
- return ret;
|
|
+ return err;
|
|
}
|
|
|
|
static int sync_serial_release(struct inode *inode, struct file *file)
|
|
diff --git a/arch/cris/arch-v10/kernel/irq.c b/arch/cris/arch-v10/kernel/irq.c
|
|
index 907cfb5..ba0e596 100644
|
|
--- a/arch/cris/arch-v10/kernel/irq.c
|
|
+++ b/arch/cris/arch-v10/kernel/irq.c
|
|
@@ -20,6 +20,9 @@
|
|
#define crisv10_mask_irq(irq_nr) (*R_VECT_MASK_CLR = 1 << (irq_nr));
|
|
#define crisv10_unmask_irq(irq_nr) (*R_VECT_MASK_SET = 1 << (irq_nr));
|
|
|
|
+extern void kgdb_init(void);
|
|
+extern void breakpoint(void);
|
|
+
|
|
/* don't use set_int_vector, it bypasses the linux interrupt handlers. it is
|
|
* global just so that the kernel gdb can use it.
|
|
*/
|
|
diff --git a/arch/cris/include/asm/thread_info.h b/arch/cris/include/asm/thread_info.h
|
|
index 29b74a1..332f19c 100644
|
|
--- a/arch/cris/include/asm/thread_info.h
|
|
+++ b/arch/cris/include/asm/thread_info.h
|
|
@@ -11,8 +11,6 @@
|
|
|
|
#ifdef __KERNEL__
|
|
|
|
-#define __HAVE_ARCH_THREAD_INFO_ALLOCATOR
|
|
-
|
|
#ifndef __ASSEMBLY__
|
|
#include <asm/types.h>
|
|
#include <asm/processor.h>
|
|
@@ -67,8 +65,10 @@ struct thread_info {
|
|
|
|
#define init_thread_info (init_thread_union.thread_info)
|
|
|
|
+#define __HAVE_ARCH_THREAD_INFO_ALLOCATOR
|
|
/* thread information allocation */
|
|
-#define alloc_thread_info(tsk, node) ((struct thread_info *) __get_free_pages(GFP_KERNEL,1))
|
|
+#define alloc_thread_info_node(tsk, node) \
|
|
+ ((struct thread_info *) __get_free_pages(GFP_KERNEL, 1))
|
|
#define free_thread_info(ti) free_pages((unsigned long) (ti), 1)
|
|
|
|
#endif /* !__ASSEMBLY__ */
|
|
diff --git a/arch/parisc/include/asm/atomic.h b/arch/parisc/include/asm/atomic.h
|
|
index f819559..26fd114 100644
|
|
--- a/arch/parisc/include/asm/atomic.h
|
|
+++ b/arch/parisc/include/asm/atomic.h
|
|
@@ -259,10 +259,10 @@ static __inline__ int atomic_add_unless(atomic_t *v, int a, int u)
|
|
|
|
#define ATOMIC64_INIT(i) ((atomic64_t) { (i) })
|
|
|
|
-static __inline__ int
|
|
+static __inline__ s64
|
|
__atomic64_add_return(s64 i, atomic64_t *v)
|
|
{
|
|
- int ret;
|
|
+ s64 ret;
|
|
unsigned long flags;
|
|
_atomic_spin_lock_irqsave(v, flags);
|
|
|
|
diff --git a/arch/parisc/include/asm/futex.h b/arch/parisc/include/asm/futex.h
|
|
index 67a33cc..2388bdb 100644
|
|
--- a/arch/parisc/include/asm/futex.h
|
|
+++ b/arch/parisc/include/asm/futex.h
|
|
@@ -5,11 +5,14 @@
|
|
|
|
#include <linux/futex.h>
|
|
#include <linux/uaccess.h>
|
|
+#include <asm/atomic.h>
|
|
#include <asm/errno.h>
|
|
|
|
static inline int
|
|
futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr)
|
|
{
|
|
+ unsigned long int flags;
|
|
+ u32 val;
|
|
int op = (encoded_op >> 28) & 7;
|
|
int cmp = (encoded_op >> 24) & 15;
|
|
int oparg = (encoded_op << 8) >> 20;
|
|
@@ -18,21 +21,58 @@ futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr)
|
|
if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
|
|
oparg = 1 << oparg;
|
|
|
|
- if (! access_ok (VERIFY_WRITE, uaddr, sizeof(u32)))
|
|
+ if (!access_ok(VERIFY_WRITE, uaddr, sizeof(*uaddr)))
|
|
return -EFAULT;
|
|
|
|
pagefault_disable();
|
|
|
|
+ _atomic_spin_lock_irqsave(uaddr, flags);
|
|
+
|
|
switch (op) {
|
|
case FUTEX_OP_SET:
|
|
+ /* *(int *)UADDR2 = OPARG; */
|
|
+ ret = get_user(oldval, uaddr);
|
|
+ if (!ret)
|
|
+ ret = put_user(oparg, uaddr);
|
|
+ break;
|
|
case FUTEX_OP_ADD:
|
|
+ /* *(int *)UADDR2 += OPARG; */
|
|
+ ret = get_user(oldval, uaddr);
|
|
+ if (!ret) {
|
|
+ val = oldval + oparg;
|
|
+ ret = put_user(val, uaddr);
|
|
+ }
|
|
+ break;
|
|
case FUTEX_OP_OR:
|
|
+ /* *(int *)UADDR2 |= OPARG; */
|
|
+ ret = get_user(oldval, uaddr);
|
|
+ if (!ret) {
|
|
+ val = oldval | oparg;
|
|
+ ret = put_user(val, uaddr);
|
|
+ }
|
|
+ break;
|
|
case FUTEX_OP_ANDN:
|
|
+ /* *(int *)UADDR2 &= ~OPARG; */
|
|
+ ret = get_user(oldval, uaddr);
|
|
+ if (!ret) {
|
|
+ val = oldval & ~oparg;
|
|
+ ret = put_user(val, uaddr);
|
|
+ }
|
|
+ break;
|
|
case FUTEX_OP_XOR:
|
|
+ /* *(int *)UADDR2 ^= OPARG; */
|
|
+ ret = get_user(oldval, uaddr);
|
|
+ if (!ret) {
|
|
+ val = oldval ^ oparg;
|
|
+ ret = put_user(val, uaddr);
|
|
+ }
|
|
+ break;
|
|
default:
|
|
ret = -ENOSYS;
|
|
}
|
|
|
|
+ _atomic_spin_unlock_irqrestore(uaddr, flags);
|
|
+
|
|
pagefault_enable();
|
|
|
|
if (!ret) {
|
|
@@ -54,7 +94,9 @@ static inline int
|
|
futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
|
|
u32 oldval, u32 newval)
|
|
{
|
|
+ int ret;
|
|
u32 val;
|
|
+ unsigned long flags;
|
|
|
|
/* futex.c wants to do a cmpxchg_inatomic on kernel NULL, which is
|
|
* our gateway page, and causes no end of trouble...
|
|
@@ -65,12 +107,24 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
|
|
if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
|
|
return -EFAULT;
|
|
|
|
- if (get_user(val, uaddr))
|
|
- return -EFAULT;
|
|
- if (val == oldval && put_user(newval, uaddr))
|
|
- return -EFAULT;
|
|
+ /* HPPA has no cmpxchg in hardware and therefore the
|
|
+ * best we can do here is use an array of locks. The
|
|
+ * lock selected is based on a hash of the userspace
|
|
+ * address. This should scale to a couple of CPUs.
|
|
+ */
|
|
+
|
|
+ _atomic_spin_lock_irqsave(uaddr, flags);
|
|
+
|
|
+ ret = get_user(val, uaddr);
|
|
+
|
|
+ if (!ret && val == oldval)
|
|
+ ret = put_user(newval, uaddr);
|
|
+
|
|
*uval = val;
|
|
- return 0;
|
|
+
|
|
+ _atomic_spin_unlock_irqrestore(uaddr, flags);
|
|
+
|
|
+ return ret;
|
|
}
|
|
|
|
#endif /*__KERNEL__*/
|
|
diff --git a/arch/parisc/include/asm/unistd.h b/arch/parisc/include/asm/unistd.h
|
|
index 3392de3..d61de64 100644
|
|
--- a/arch/parisc/include/asm/unistd.h
|
|
+++ b/arch/parisc/include/asm/unistd.h
|
|
@@ -821,8 +821,9 @@
|
|
#define __NR_open_by_handle_at (__NR_Linux + 326)
|
|
#define __NR_syncfs (__NR_Linux + 327)
|
|
#define __NR_setns (__NR_Linux + 328)
|
|
+#define __NR_sendmmsg (__NR_Linux + 329)
|
|
|
|
-#define __NR_Linux_syscalls (__NR_setns + 1)
|
|
+#define __NR_Linux_syscalls (__NR_sendmmsg + 1)
|
|
|
|
|
|
#define __IGNORE_select /* newselect */
|
|
diff --git a/arch/parisc/kernel/syscall_table.S b/arch/parisc/kernel/syscall_table.S
|
|
index 34a4f5a..e66366f 100644
|
|
--- a/arch/parisc/kernel/syscall_table.S
|
|
+++ b/arch/parisc/kernel/syscall_table.S
|
|
@@ -427,6 +427,7 @@
|
|
ENTRY_COMP(open_by_handle_at)
|
|
ENTRY_SAME(syncfs)
|
|
ENTRY_SAME(setns)
|
|
+ ENTRY_COMP(sendmmsg)
|
|
|
|
/* Nothing yet */
|
|
|
|
diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c
|
|
index c016033..3b22142 100644
|
|
--- a/arch/powerpc/kernel/prom_init.c
|
|
+++ b/arch/powerpc/kernel/prom_init.c
|
|
@@ -1020,7 +1020,7 @@ static unsigned long __init alloc_up(unsigned long size, unsigned long align)
|
|
}
|
|
if (addr == 0)
|
|
return 0;
|
|
- RELOC(alloc_bottom) = addr;
|
|
+ RELOC(alloc_bottom) = addr + size;
|
|
|
|
prom_debug(" -> %x\n", addr);
|
|
prom_debug(" alloc_bottom : %x\n", RELOC(alloc_bottom));
|
|
@@ -1834,7 +1834,7 @@ static void __init *make_room(unsigned long *mem_start, unsigned long *mem_end,
|
|
chunk = alloc_up(room, 0);
|
|
if (chunk == 0)
|
|
prom_panic("No memory for flatten_device_tree (claim failed)");
|
|
- *mem_end = RELOC(alloc_top);
|
|
+ *mem_end = chunk + room;
|
|
}
|
|
|
|
ret = (void *)*mem_start;
|
|
@@ -2053,7 +2053,7 @@ static void __init flatten_device_tree(void)
|
|
mem_start = (unsigned long)alloc_up(room, PAGE_SIZE);
|
|
if (mem_start == 0)
|
|
prom_panic("Can't allocate initial device-tree chunk\n");
|
|
- mem_end = RELOC(alloc_top);
|
|
+ mem_end = mem_start + room;
|
|
|
|
/* Get root of tree */
|
|
root = call_prom("peer", 1, 1, (phandle)0);
|
|
diff --git a/arch/powerpc/platforms/pseries/dtl.c b/arch/powerpc/platforms/pseries/dtl.c
|
|
index e919007..0e86563 100644
|
|
--- a/arch/powerpc/platforms/pseries/dtl.c
|
|
+++ b/arch/powerpc/platforms/pseries/dtl.c
|
|
@@ -181,7 +181,7 @@ static void dtl_stop(struct dtl *dtl)
|
|
|
|
lppaca_of(dtl->cpu).dtl_enable_mask = 0x0;
|
|
|
|
- unregister_dtl(hwcpu, __pa(dtl->buf));
|
|
+ unregister_dtl(hwcpu);
|
|
}
|
|
|
|
static u64 dtl_current_index(struct dtl *dtl)
|
|
diff --git a/arch/powerpc/platforms/pseries/kexec.c b/arch/powerpc/platforms/pseries/kexec.c
|
|
index 54cf3a4..1118cb7 100644
|
|
--- a/arch/powerpc/platforms/pseries/kexec.c
|
|
+++ b/arch/powerpc/platforms/pseries/kexec.c
|
|
@@ -26,6 +26,17 @@ static void pseries_kexec_cpu_down(int crash_shutdown, int secondary)
|
|
/* Don't risk a hypervisor call if we're crashing */
|
|
if (firmware_has_feature(FW_FEATURE_SPLPAR) && !crash_shutdown) {
|
|
unsigned long addr;
|
|
+ int ret;
|
|
+
|
|
+ if (get_lppaca()->dtl_enable_mask) {
|
|
+ ret = unregister_dtl(hard_smp_processor_id());
|
|
+ if (ret) {
|
|
+ pr_err("WARNING: DTL deregistration for cpu "
|
|
+ "%d (hw %d) failed with %d\n",
|
|
+ smp_processor_id(),
|
|
+ hard_smp_processor_id(), ret);
|
|
+ }
|
|
+ }
|
|
|
|
addr = __pa(get_slb_shadow());
|
|
if (unregister_slb_shadow(hard_smp_processor_id(), addr))
|
|
diff --git a/arch/powerpc/platforms/pseries/lpar.c b/arch/powerpc/platforms/pseries/lpar.c
|
|
index 39e6e0a..ed96b37 100644
|
|
--- a/arch/powerpc/platforms/pseries/lpar.c
|
|
+++ b/arch/powerpc/platforms/pseries/lpar.c
|
|
@@ -395,7 +395,7 @@ static void pSeries_lpar_hptab_clear(void)
|
|
unsigned long ptel;
|
|
} ptes[4];
|
|
long lpar_rc;
|
|
- int i, j;
|
|
+ unsigned long i, j;
|
|
|
|
/* Read in batches of 4,
|
|
* invalidate only valid entries not in the VRMA
|
|
diff --git a/arch/powerpc/platforms/pseries/plpar_wrappers.h b/arch/powerpc/platforms/pseries/plpar_wrappers.h
|
|
index 4bf2120..a6921ae 100644
|
|
--- a/arch/powerpc/platforms/pseries/plpar_wrappers.h
|
|
+++ b/arch/powerpc/platforms/pseries/plpar_wrappers.h
|
|
@@ -73,9 +73,9 @@ static inline long register_slb_shadow(unsigned long cpu, unsigned long vpa)
|
|
return vpa_call(0x3, cpu, vpa);
|
|
}
|
|
|
|
-static inline long unregister_dtl(unsigned long cpu, unsigned long vpa)
|
|
+static inline long unregister_dtl(unsigned long cpu)
|
|
{
|
|
- return vpa_call(0x6, cpu, vpa);
|
|
+ return vpa_call(0x6, cpu, 0);
|
|
}
|
|
|
|
static inline long register_dtl(unsigned long cpu, unsigned long vpa)
|
|
diff --git a/arch/sparc/include/asm/bitops_64.h b/arch/sparc/include/asm/bitops_64.h
|
|
index 38e9aa1..3fc595a 100644
|
|
--- a/arch/sparc/include/asm/bitops_64.h
|
|
+++ b/arch/sparc/include/asm/bitops_64.h
|
|
@@ -26,61 +26,28 @@ extern void change_bit(unsigned long nr, volatile unsigned long *addr);
|
|
#define smp_mb__before_clear_bit() barrier()
|
|
#define smp_mb__after_clear_bit() barrier()
|
|
|
|
-#include <asm-generic/bitops/ffz.h>
|
|
-#include <asm-generic/bitops/__ffs.h>
|
|
#include <asm-generic/bitops/fls.h>
|
|
#include <asm-generic/bitops/__fls.h>
|
|
#include <asm-generic/bitops/fls64.h>
|
|
|
|
#ifdef __KERNEL__
|
|
|
|
+extern int ffs(int x);
|
|
+extern unsigned long __ffs(unsigned long);
|
|
+
|
|
+#include <asm-generic/bitops/ffz.h>
|
|
#include <asm-generic/bitops/sched.h>
|
|
-#include <asm-generic/bitops/ffs.h>
|
|
|
|
/*
|
|
* hweightN: returns the hamming weight (i.e. the number
|
|
* of bits set) of a N-bit word
|
|
*/
|
|
|
|
-#ifdef ULTRA_HAS_POPULATION_COUNT
|
|
-
|
|
-static inline unsigned int __arch_hweight64(unsigned long w)
|
|
-{
|
|
- unsigned int res;
|
|
-
|
|
- __asm__ ("popc %1,%0" : "=r" (res) : "r" (w));
|
|
- return res;
|
|
-}
|
|
-
|
|
-static inline unsigned int __arch_hweight32(unsigned int w)
|
|
-{
|
|
- unsigned int res;
|
|
-
|
|
- __asm__ ("popc %1,%0" : "=r" (res) : "r" (w & 0xffffffff));
|
|
- return res;
|
|
-}
|
|
+extern unsigned long __arch_hweight64(__u64 w);
|
|
+extern unsigned int __arch_hweight32(unsigned int w);
|
|
+extern unsigned int __arch_hweight16(unsigned int w);
|
|
+extern unsigned int __arch_hweight8(unsigned int w);
|
|
|
|
-static inline unsigned int __arch_hweight16(unsigned int w)
|
|
-{
|
|
- unsigned int res;
|
|
-
|
|
- __asm__ ("popc %1,%0" : "=r" (res) : "r" (w & 0xffff));
|
|
- return res;
|
|
-}
|
|
-
|
|
-static inline unsigned int __arch_hweight8(unsigned int w)
|
|
-{
|
|
- unsigned int res;
|
|
-
|
|
- __asm__ ("popc %1,%0" : "=r" (res) : "r" (w & 0xff));
|
|
- return res;
|
|
-}
|
|
-
|
|
-#else
|
|
-
|
|
-#include <asm-generic/bitops/arch_hweight.h>
|
|
-
|
|
-#endif
|
|
#include <asm-generic/bitops/const_hweight.h>
|
|
#include <asm-generic/bitops/lock.h>
|
|
#endif /* __KERNEL__ */
|
|
diff --git a/arch/sparc/include/asm/elf_64.h b/arch/sparc/include/asm/elf_64.h
|
|
index e678803..7df8b7f 100644
|
|
--- a/arch/sparc/include/asm/elf_64.h
|
|
+++ b/arch/sparc/include/asm/elf_64.h
|
|
@@ -59,15 +59,33 @@
|
|
#define R_SPARC_6 45
|
|
|
|
/* Bits present in AT_HWCAP, primarily for Sparc32. */
|
|
-
|
|
-#define HWCAP_SPARC_FLUSH 1 /* CPU supports flush instruction. */
|
|
-#define HWCAP_SPARC_STBAR 2
|
|
-#define HWCAP_SPARC_SWAP 4
|
|
-#define HWCAP_SPARC_MULDIV 8
|
|
-#define HWCAP_SPARC_V9 16
|
|
-#define HWCAP_SPARC_ULTRA3 32
|
|
-#define HWCAP_SPARC_BLKINIT 64
|
|
-#define HWCAP_SPARC_N2 128
|
|
+#define HWCAP_SPARC_FLUSH 0x00000001
|
|
+#define HWCAP_SPARC_STBAR 0x00000002
|
|
+#define HWCAP_SPARC_SWAP 0x00000004
|
|
+#define HWCAP_SPARC_MULDIV 0x00000008
|
|
+#define HWCAP_SPARC_V9 0x00000010
|
|
+#define HWCAP_SPARC_ULTRA3 0x00000020
|
|
+#define HWCAP_SPARC_BLKINIT 0x00000040
|
|
+#define HWCAP_SPARC_N2 0x00000080
|
|
+
|
|
+/* Solaris compatible AT_HWCAP bits. */
|
|
+#define AV_SPARC_MUL32 0x00000100 /* 32x32 multiply is efficient */
|
|
+#define AV_SPARC_DIV32 0x00000200 /* 32x32 divide is efficient */
|
|
+#define AV_SPARC_FSMULD 0x00000400 /* 'fsmuld' is efficient */
|
|
+#define AV_SPARC_V8PLUS 0x00000800 /* v9 insn available to 32bit */
|
|
+#define AV_SPARC_POPC 0x00001000 /* 'popc' is efficient */
|
|
+#define AV_SPARC_VIS 0x00002000 /* VIS insns available */
|
|
+#define AV_SPARC_VIS2 0x00004000 /* VIS2 insns available */
|
|
+#define AV_SPARC_ASI_BLK_INIT 0x00008000 /* block init ASIs available */
|
|
+#define AV_SPARC_FMAF 0x00010000 /* fused multiply-add */
|
|
+#define AV_SPARC_VIS3 0x00020000 /* VIS3 insns available */
|
|
+#define AV_SPARC_HPC 0x00040000 /* HPC insns available */
|
|
+#define AV_SPARC_RANDOM 0x00080000 /* 'random' insn available */
|
|
+#define AV_SPARC_TRANS 0x00100000 /* transaction insns available */
|
|
+#define AV_SPARC_FJFMAU 0x00200000 /* unfused multiply-add */
|
|
+#define AV_SPARC_IMA 0x00400000 /* integer multiply-add */
|
|
+#define AV_SPARC_ASI_CACHE_SPARING \
|
|
+ 0x00800000 /* cache sparing ASIs available */
|
|
|
|
#define CORE_DUMP_USE_REGSET
|
|
|
|
@@ -162,31 +180,8 @@ typedef struct {
|
|
#define ELF_ET_DYN_BASE 0x0000010000000000UL
|
|
#define COMPAT_ELF_ET_DYN_BASE 0x0000000070000000UL
|
|
|
|
-
|
|
-/* This yields a mask that user programs can use to figure out what
|
|
- instruction set this cpu supports. */
|
|
-
|
|
-/* On Ultra, we support all of the v8 capabilities. */
|
|
-static inline unsigned int sparc64_elf_hwcap(void)
|
|
-{
|
|
- unsigned int cap = (HWCAP_SPARC_FLUSH | HWCAP_SPARC_STBAR |
|
|
- HWCAP_SPARC_SWAP | HWCAP_SPARC_MULDIV |
|
|
- HWCAP_SPARC_V9);
|
|
-
|
|
- if (tlb_type == cheetah || tlb_type == cheetah_plus)
|
|
- cap |= HWCAP_SPARC_ULTRA3;
|
|
- else if (tlb_type == hypervisor) {
|
|
- if (sun4v_chip_type == SUN4V_CHIP_NIAGARA1 ||
|
|
- sun4v_chip_type == SUN4V_CHIP_NIAGARA2)
|
|
- cap |= HWCAP_SPARC_BLKINIT;
|
|
- if (sun4v_chip_type == SUN4V_CHIP_NIAGARA2)
|
|
- cap |= HWCAP_SPARC_N2;
|
|
- }
|
|
-
|
|
- return cap;
|
|
-}
|
|
-
|
|
-#define ELF_HWCAP sparc64_elf_hwcap();
|
|
+extern unsigned long sparc64_elf_hwcap;
|
|
+#define ELF_HWCAP sparc64_elf_hwcap
|
|
|
|
/* This yields a string that ld.so will use to load implementation
|
|
specific libraries for optimization. This is more specific in
|
|
diff --git a/arch/sparc/include/asm/hypervisor.h b/arch/sparc/include/asm/hypervisor.h
|
|
index 7568640..015a761 100644
|
|
--- a/arch/sparc/include/asm/hypervisor.h
|
|
+++ b/arch/sparc/include/asm/hypervisor.h
|
|
@@ -2927,6 +2927,13 @@ extern unsigned long sun4v_ncs_request(unsigned long request,
|
|
#define HV_FAST_FIRE_GET_PERFREG 0x120
|
|
#define HV_FAST_FIRE_SET_PERFREG 0x121
|
|
|
|
+#define HV_FAST_REBOOT_DATA_SET 0x172
|
|
+
|
|
+#ifndef __ASSEMBLY__
|
|
+extern unsigned long sun4v_reboot_data_set(unsigned long ra,
|
|
+ unsigned long len);
|
|
+#endif
|
|
+
|
|
/* Function numbers for HV_CORE_TRAP. */
|
|
#define HV_CORE_SET_VER 0x00
|
|
#define HV_CORE_PUTCHAR 0x01
|
|
@@ -2940,16 +2947,23 @@ extern unsigned long sun4v_ncs_request(unsigned long request,
|
|
#define HV_GRP_CORE 0x0001
|
|
#define HV_GRP_INTR 0x0002
|
|
#define HV_GRP_SOFT_STATE 0x0003
|
|
+#define HV_GRP_TM 0x0080
|
|
#define HV_GRP_PCI 0x0100
|
|
#define HV_GRP_LDOM 0x0101
|
|
#define HV_GRP_SVC_CHAN 0x0102
|
|
#define HV_GRP_NCS 0x0103
|
|
#define HV_GRP_RNG 0x0104
|
|
+#define HV_GRP_PBOOT 0x0105
|
|
+#define HV_GRP_TPM 0x0107
|
|
+#define HV_GRP_SDIO 0x0108
|
|
+#define HV_GRP_SDIO_ERR 0x0109
|
|
+#define HV_GRP_REBOOT_DATA 0x0110
|
|
#define HV_GRP_NIAG_PERF 0x0200
|
|
#define HV_GRP_FIRE_PERF 0x0201
|
|
#define HV_GRP_N2_CPU 0x0202
|
|
#define HV_GRP_NIU 0x0204
|
|
#define HV_GRP_VF_CPU 0x0205
|
|
+#define HV_GRP_KT_CPU 0x0209
|
|
#define HV_GRP_DIAG 0x0300
|
|
|
|
#ifndef __ASSEMBLY__
|
|
diff --git a/arch/sparc/include/asm/spitfire.h b/arch/sparc/include/asm/spitfire.h
|
|
index f0d0c40..55a17c6 100644
|
|
--- a/arch/sparc/include/asm/spitfire.h
|
|
+++ b/arch/sparc/include/asm/spitfire.h
|
|
@@ -42,6 +42,7 @@
|
|
#define SUN4V_CHIP_INVALID 0x00
|
|
#define SUN4V_CHIP_NIAGARA1 0x01
|
|
#define SUN4V_CHIP_NIAGARA2 0x02
|
|
+#define SUN4V_CHIP_NIAGARA3 0x03
|
|
#define SUN4V_CHIP_UNKNOWN 0xff
|
|
|
|
#ifndef __ASSEMBLY__
|
|
diff --git a/arch/sparc/include/asm/tsb.h b/arch/sparc/include/asm/tsb.h
|
|
index 83c571d..1a8afd1 100644
|
|
--- a/arch/sparc/include/asm/tsb.h
|
|
+++ b/arch/sparc/include/asm/tsb.h
|
|
@@ -133,29 +133,6 @@ extern struct tsb_phys_patch_entry __tsb_phys_patch, __tsb_phys_patch_end;
|
|
sub TSB, 0x8, TSB; \
|
|
TSB_STORE(TSB, TAG);
|
|
|
|
-#define KTSB_LOAD_QUAD(TSB, REG) \
|
|
- ldda [TSB] ASI_NUCLEUS_QUAD_LDD, REG;
|
|
-
|
|
-#define KTSB_STORE(ADDR, VAL) \
|
|
- stxa VAL, [ADDR] ASI_N;
|
|
-
|
|
-#define KTSB_LOCK_TAG(TSB, REG1, REG2) \
|
|
-99: lduwa [TSB] ASI_N, REG1; \
|
|
- sethi %hi(TSB_TAG_LOCK_HIGH), REG2;\
|
|
- andcc REG1, REG2, %g0; \
|
|
- bne,pn %icc, 99b; \
|
|
- nop; \
|
|
- casa [TSB] ASI_N, REG1, REG2;\
|
|
- cmp REG1, REG2; \
|
|
- bne,pn %icc, 99b; \
|
|
- nop; \
|
|
-
|
|
-#define KTSB_WRITE(TSB, TTE, TAG) \
|
|
- add TSB, 0x8, TSB; \
|
|
- stxa TTE, [TSB] ASI_N; \
|
|
- sub TSB, 0x8, TSB; \
|
|
- stxa TAG, [TSB] ASI_N;
|
|
-
|
|
/* Do a kernel page table walk. Leaves physical PTE pointer in
|
|
* REG1. Jumps to FAIL_LABEL on early page table walk termination.
|
|
* VADDR will not be clobbered, but REG2 will.
|
|
@@ -239,6 +216,8 @@ extern struct tsb_phys_patch_entry __tsb_phys_patch, __tsb_phys_patch_end;
|
|
(KERNEL_TSB_SIZE_BYTES / 16)
|
|
#define KERNEL_TSB4M_NENTRIES 4096
|
|
|
|
+#define KTSB_PHYS_SHIFT 15
|
|
+
|
|
/* Do a kernel TSB lookup at tl>0 on VADDR+TAG, branch to OK_LABEL
|
|
* on TSB hit. REG1, REG2, REG3, and REG4 are used as temporaries
|
|
* and the found TTE will be left in REG1. REG3 and REG4 must
|
|
@@ -247,13 +226,22 @@ extern struct tsb_phys_patch_entry __tsb_phys_patch, __tsb_phys_patch_end;
|
|
* VADDR and TAG will be preserved and not clobbered by this macro.
|
|
*/
|
|
#define KERN_TSB_LOOKUP_TL1(VADDR, TAG, REG1, REG2, REG3, REG4, OK_LABEL) \
|
|
- sethi %hi(swapper_tsb), REG1; \
|
|
+661: sethi %hi(swapper_tsb), REG1; \
|
|
or REG1, %lo(swapper_tsb), REG1; \
|
|
+ .section .swapper_tsb_phys_patch, "ax"; \
|
|
+ .word 661b; \
|
|
+ .previous; \
|
|
+661: nop; \
|
|
+ .section .tsb_ldquad_phys_patch, "ax"; \
|
|
+ .word 661b; \
|
|
+ sllx REG1, KTSB_PHYS_SHIFT, REG1; \
|
|
+ sllx REG1, KTSB_PHYS_SHIFT, REG1; \
|
|
+ .previous; \
|
|
srlx VADDR, PAGE_SHIFT, REG2; \
|
|
and REG2, (KERNEL_TSB_NENTRIES - 1), REG2; \
|
|
sllx REG2, 4, REG2; \
|
|
add REG1, REG2, REG2; \
|
|
- KTSB_LOAD_QUAD(REG2, REG3); \
|
|
+ TSB_LOAD_QUAD(REG2, REG3); \
|
|
cmp REG3, TAG; \
|
|
be,a,pt %xcc, OK_LABEL; \
|
|
mov REG4, REG1;
|
|
@@ -263,12 +251,21 @@ extern struct tsb_phys_patch_entry __tsb_phys_patch, __tsb_phys_patch_end;
|
|
* we can make use of that for the index computation.
|
|
*/
|
|
#define KERN_TSB4M_LOOKUP_TL1(TAG, REG1, REG2, REG3, REG4, OK_LABEL) \
|
|
- sethi %hi(swapper_4m_tsb), REG1; \
|
|
+661: sethi %hi(swapper_4m_tsb), REG1; \
|
|
or REG1, %lo(swapper_4m_tsb), REG1; \
|
|
+ .section .swapper_4m_tsb_phys_patch, "ax"; \
|
|
+ .word 661b; \
|
|
+ .previous; \
|
|
+661: nop; \
|
|
+ .section .tsb_ldquad_phys_patch, "ax"; \
|
|
+ .word 661b; \
|
|
+ sllx REG1, KTSB_PHYS_SHIFT, REG1; \
|
|
+ sllx REG1, KTSB_PHYS_SHIFT, REG1; \
|
|
+ .previous; \
|
|
and TAG, (KERNEL_TSB4M_NENTRIES - 1), REG2; \
|
|
sllx REG2, 4, REG2; \
|
|
add REG1, REG2, REG2; \
|
|
- KTSB_LOAD_QUAD(REG2, REG3); \
|
|
+ TSB_LOAD_QUAD(REG2, REG3); \
|
|
cmp REG3, TAG; \
|
|
be,a,pt %xcc, OK_LABEL; \
|
|
mov REG4, REG1;
|
|
diff --git a/arch/sparc/include/asm/xor_64.h b/arch/sparc/include/asm/xor_64.h
|
|
index bee4bf4..9ed6ff6 100644
|
|
--- a/arch/sparc/include/asm/xor_64.h
|
|
+++ b/arch/sparc/include/asm/xor_64.h
|
|
@@ -65,6 +65,7 @@ static struct xor_block_template xor_block_niagara = {
|
|
#define XOR_SELECT_TEMPLATE(FASTEST) \
|
|
((tlb_type == hypervisor && \
|
|
(sun4v_chip_type == SUN4V_CHIP_NIAGARA1 || \
|
|
- sun4v_chip_type == SUN4V_CHIP_NIAGARA2)) ? \
|
|
+ sun4v_chip_type == SUN4V_CHIP_NIAGARA2 || \
|
|
+ sun4v_chip_type == SUN4V_CHIP_NIAGARA3)) ? \
|
|
&xor_block_niagara : \
|
|
&xor_block_VIS)
|
|
diff --git a/arch/sparc/kernel/cpu.c b/arch/sparc/kernel/cpu.c
|
|
index 138dbbc..9810fd8 100644
|
|
--- a/arch/sparc/kernel/cpu.c
|
|
+++ b/arch/sparc/kernel/cpu.c
|
|
@@ -396,6 +396,7 @@ static int show_cpuinfo(struct seq_file *m, void *__unused)
|
|
, cpu_data(0).clock_tick
|
|
#endif
|
|
);
|
|
+ cpucap_info(m);
|
|
#ifdef CONFIG_SMP
|
|
smp_bogo(m);
|
|
#endif
|
|
@@ -474,11 +475,18 @@ static void __init sun4v_cpu_probe(void)
|
|
sparc_pmu_type = "niagara2";
|
|
break;
|
|
|
|
+ case SUN4V_CHIP_NIAGARA3:
|
|
+ sparc_cpu_type = "UltraSparc T3 (Niagara3)";
|
|
+ sparc_fpu_type = "UltraSparc T3 integrated FPU";
|
|
+ sparc_pmu_type = "niagara3";
|
|
+ break;
|
|
+
|
|
default:
|
|
printk(KERN_WARNING "CPU: Unknown sun4v cpu type [%s]\n",
|
|
prom_cpu_compatible);
|
|
sparc_cpu_type = "Unknown SUN4V CPU";
|
|
sparc_fpu_type = "Unknown SUN4V FPU";
|
|
+ sparc_pmu_type = "Unknown SUN4V PMU";
|
|
break;
|
|
}
|
|
}
|
|
diff --git a/arch/sparc/kernel/cpumap.c b/arch/sparc/kernel/cpumap.c
|
|
index d91fd78..4197e8d 100644
|
|
--- a/arch/sparc/kernel/cpumap.c
|
|
+++ b/arch/sparc/kernel/cpumap.c
|
|
@@ -324,6 +324,7 @@ static int iterate_cpu(struct cpuinfo_tree *t, unsigned int root_index)
|
|
switch (sun4v_chip_type) {
|
|
case SUN4V_CHIP_NIAGARA1:
|
|
case SUN4V_CHIP_NIAGARA2:
|
|
+ case SUN4V_CHIP_NIAGARA3:
|
|
rover_inc_table = niagara_iterate_method;
|
|
break;
|
|
default:
|
|
diff --git a/arch/sparc/kernel/ds.c b/arch/sparc/kernel/ds.c
|
|
index dd1342c..7429b47 100644
|
|
--- a/arch/sparc/kernel/ds.c
|
|
+++ b/arch/sparc/kernel/ds.c
|
|
@@ -15,12 +15,15 @@
|
|
#include <linux/reboot.h>
|
|
#include <linux/cpu.h>
|
|
|
|
+#include <asm/hypervisor.h>
|
|
#include <asm/ldc.h>
|
|
#include <asm/vio.h>
|
|
#include <asm/mdesc.h>
|
|
#include <asm/head.h>
|
|
#include <asm/irq.h>
|
|
|
|
+#include "kernel.h"
|
|
+
|
|
#define DRV_MODULE_NAME "ds"
|
|
#define PFX DRV_MODULE_NAME ": "
|
|
#define DRV_MODULE_VERSION "1.0"
|
|
@@ -828,18 +831,32 @@ void ldom_set_var(const char *var, const char *value)
|
|
}
|
|
}
|
|
|
|
+static char full_boot_str[256] __attribute__((aligned(32)));
|
|
+static int reboot_data_supported;
|
|
+
|
|
void ldom_reboot(const char *boot_command)
|
|
{
|
|
/* Don't bother with any of this if the boot_command
|
|
* is empty.
|
|
*/
|
|
if (boot_command && strlen(boot_command)) {
|
|
- char full_boot_str[256];
|
|
+ unsigned long len;
|
|
|
|
strcpy(full_boot_str, "boot ");
|
|
strcpy(full_boot_str + strlen("boot "), boot_command);
|
|
+ len = strlen(full_boot_str);
|
|
|
|
- ldom_set_var("reboot-command", full_boot_str);
|
|
+ if (reboot_data_supported) {
|
|
+ unsigned long ra = kimage_addr_to_ra(full_boot_str);
|
|
+ unsigned long hv_ret;
|
|
+
|
|
+ hv_ret = sun4v_reboot_data_set(ra, len);
|
|
+ if (hv_ret != HV_EOK)
|
|
+ pr_err("SUN4V: Unable to set reboot data "
|
|
+ "hv_ret=%lu\n", hv_ret);
|
|
+ } else {
|
|
+ ldom_set_var("reboot-command", full_boot_str);
|
|
+ }
|
|
}
|
|
sun4v_mach_sir();
|
|
}
|
|
@@ -1237,6 +1254,16 @@ static struct vio_driver ds_driver = {
|
|
|
|
static int __init ds_init(void)
|
|
{
|
|
+ unsigned long hv_ret, major, minor;
|
|
+
|
|
+ if (tlb_type == hypervisor) {
|
|
+ hv_ret = sun4v_get_version(HV_GRP_REBOOT_DATA, &major, &minor);
|
|
+ if (hv_ret == HV_EOK) {
|
|
+ pr_info("SUN4V: Reboot data supported (maj=%lu,min=%lu).\n",
|
|
+ major, minor);
|
|
+ reboot_data_supported = 1;
|
|
+ }
|
|
+ }
|
|
kthread_run(ds_thread, NULL, "kldomd");
|
|
|
|
return vio_register_driver(&ds_driver);
|
|
diff --git a/arch/sparc/kernel/entry.h b/arch/sparc/kernel/entry.h
|
|
index d1f1361..e27f8ea 100644
|
|
--- a/arch/sparc/kernel/entry.h
|
|
+++ b/arch/sparc/kernel/entry.h
|
|
@@ -42,6 +42,20 @@ extern void fpsave(unsigned long *fpregs, unsigned long *fsr,
|
|
extern void fpload(unsigned long *fpregs, unsigned long *fsr);
|
|
|
|
#else /* CONFIG_SPARC32 */
|
|
+struct popc_3insn_patch_entry {
|
|
+ unsigned int addr;
|
|
+ unsigned int insns[3];
|
|
+};
|
|
+extern struct popc_3insn_patch_entry __popc_3insn_patch,
|
|
+ __popc_3insn_patch_end;
|
|
+
|
|
+struct popc_6insn_patch_entry {
|
|
+ unsigned int addr;
|
|
+ unsigned int insns[6];
|
|
+};
|
|
+extern struct popc_6insn_patch_entry __popc_6insn_patch,
|
|
+ __popc_6insn_patch_end;
|
|
+
|
|
extern void __init per_cpu_patch(void);
|
|
extern void __init sun4v_patch(void);
|
|
extern void __init boot_cpu_id_too_large(int cpu);
|
|
diff --git a/arch/sparc/kernel/head_64.S b/arch/sparc/kernel/head_64.S
|
|
index aa594c7..0cbab31 100644
|
|
--- a/arch/sparc/kernel/head_64.S
|
|
+++ b/arch/sparc/kernel/head_64.S
|
|
@@ -132,6 +132,8 @@ prom_sun4v_name:
|
|
.asciz "sun4v"
|
|
prom_niagara_prefix:
|
|
.asciz "SUNW,UltraSPARC-T"
|
|
+prom_sparc_prefix:
|
|
+ .asciz "SPARC-T"
|
|
.align 4
|
|
prom_root_compatible:
|
|
.skip 64
|
|
@@ -382,6 +384,22 @@ sun4v_chip_type:
|
|
90: ldub [%g7], %g2
|
|
ldub [%g1], %g4
|
|
cmp %g2, %g4
|
|
+ bne,pn %icc, 89f
|
|
+ add %g7, 1, %g7
|
|
+ subcc %g3, 1, %g3
|
|
+ bne,pt %xcc, 90b
|
|
+ add %g1, 1, %g1
|
|
+ ba,pt %xcc, 91f
|
|
+ nop
|
|
+
|
|
+89: sethi %hi(prom_cpu_compatible), %g1
|
|
+ or %g1, %lo(prom_cpu_compatible), %g1
|
|
+ sethi %hi(prom_sparc_prefix), %g7
|
|
+ or %g7, %lo(prom_sparc_prefix), %g7
|
|
+ mov 7, %g3
|
|
+90: ldub [%g7], %g2
|
|
+ ldub [%g1], %g4
|
|
+ cmp %g2, %g4
|
|
bne,pn %icc, 4f
|
|
add %g7, 1, %g7
|
|
subcc %g3, 1, %g3
|
|
@@ -390,6 +408,15 @@ sun4v_chip_type:
|
|
|
|
sethi %hi(prom_cpu_compatible), %g1
|
|
or %g1, %lo(prom_cpu_compatible), %g1
|
|
+ ldub [%g1 + 7], %g2
|
|
+ cmp %g2, '3'
|
|
+ be,pt %xcc, 5f
|
|
+ mov SUN4V_CHIP_NIAGARA3, %g4
|
|
+ ba,pt %xcc, 4f
|
|
+ nop
|
|
+
|
|
+91: sethi %hi(prom_cpu_compatible), %g1
|
|
+ or %g1, %lo(prom_cpu_compatible), %g1
|
|
ldub [%g1 + 17], %g2
|
|
cmp %g2, '1'
|
|
be,pt %xcc, 5f
|
|
@@ -397,6 +424,7 @@ sun4v_chip_type:
|
|
cmp %g2, '2'
|
|
be,pt %xcc, 5f
|
|
mov SUN4V_CHIP_NIAGARA2, %g4
|
|
+
|
|
4:
|
|
mov SUN4V_CHIP_UNKNOWN, %g4
|
|
5: sethi %hi(sun4v_chip_type), %g2
|
|
@@ -514,6 +542,9 @@ niagara_tlb_fixup:
|
|
cmp %g1, SUN4V_CHIP_NIAGARA2
|
|
be,pt %xcc, niagara2_patch
|
|
nop
|
|
+ cmp %g1, SUN4V_CHIP_NIAGARA3
|
|
+ be,pt %xcc, niagara2_patch
|
|
+ nop
|
|
|
|
call generic_patch_copyops
|
|
nop
|
|
@@ -528,7 +559,7 @@ niagara2_patch:
|
|
nop
|
|
call niagara_patch_bzero
|
|
nop
|
|
- call niagara2_patch_pageops
|
|
+ call niagara_patch_pageops
|
|
nop
|
|
|
|
ba,a,pt %xcc, 80f
|
|
diff --git a/arch/sparc/kernel/hvapi.c b/arch/sparc/kernel/hvapi.c
|
|
index 7c60afb..c2d055d 100644
|
|
--- a/arch/sparc/kernel/hvapi.c
|
|
+++ b/arch/sparc/kernel/hvapi.c
|
|
@@ -28,16 +28,23 @@ static struct api_info api_table[] = {
|
|
{ .group = HV_GRP_CORE, .flags = FLAG_PRE_API },
|
|
{ .group = HV_GRP_INTR, },
|
|
{ .group = HV_GRP_SOFT_STATE, },
|
|
+ { .group = HV_GRP_TM, },
|
|
{ .group = HV_GRP_PCI, .flags = FLAG_PRE_API },
|
|
{ .group = HV_GRP_LDOM, },
|
|
{ .group = HV_GRP_SVC_CHAN, .flags = FLAG_PRE_API },
|
|
{ .group = HV_GRP_NCS, .flags = FLAG_PRE_API },
|
|
{ .group = HV_GRP_RNG, },
|
|
+ { .group = HV_GRP_PBOOT, },
|
|
+ { .group = HV_GRP_TPM, },
|
|
+ { .group = HV_GRP_SDIO, },
|
|
+ { .group = HV_GRP_SDIO_ERR, },
|
|
+ { .group = HV_GRP_REBOOT_DATA, },
|
|
{ .group = HV_GRP_NIAG_PERF, .flags = FLAG_PRE_API },
|
|
{ .group = HV_GRP_FIRE_PERF, },
|
|
{ .group = HV_GRP_N2_CPU, },
|
|
{ .group = HV_GRP_NIU, },
|
|
{ .group = HV_GRP_VF_CPU, },
|
|
+ { .group = HV_GRP_KT_CPU, },
|
|
{ .group = HV_GRP_DIAG, .flags = FLAG_PRE_API },
|
|
};
|
|
|
|
diff --git a/arch/sparc/kernel/hvcalls.S b/arch/sparc/kernel/hvcalls.S
|
|
index 8a5f35f..58d60de 100644
|
|
--- a/arch/sparc/kernel/hvcalls.S
|
|
+++ b/arch/sparc/kernel/hvcalls.S
|
|
@@ -798,3 +798,10 @@ ENTRY(sun4v_niagara2_setperf)
|
|
retl
|
|
nop
|
|
ENDPROC(sun4v_niagara2_setperf)
|
|
+
|
|
+ENTRY(sun4v_reboot_data_set)
|
|
+ mov HV_FAST_REBOOT_DATA_SET, %o5
|
|
+ ta HV_FAST_TRAP
|
|
+ retl
|
|
+ nop
|
|
+ENDPROC(sun4v_reboot_data_set)
|
|
diff --git a/arch/sparc/kernel/kernel.h b/arch/sparc/kernel/kernel.h
|
|
index 6f6544c..fd6c36b 100644
|
|
--- a/arch/sparc/kernel/kernel.h
|
|
+++ b/arch/sparc/kernel/kernel.h
|
|
@@ -4,12 +4,27 @@
|
|
#include <linux/interrupt.h>
|
|
|
|
#include <asm/traps.h>
|
|
+#include <asm/head.h>
|
|
+#include <asm/io.h>
|
|
|
|
/* cpu.c */
|
|
extern const char *sparc_pmu_type;
|
|
extern unsigned int fsr_storage;
|
|
extern int ncpus_probed;
|
|
|
|
+#ifdef CONFIG_SPARC64
|
|
+/* setup_64.c */
|
|
+struct seq_file;
|
|
+extern void cpucap_info(struct seq_file *);
|
|
+
|
|
+static inline unsigned long kimage_addr_to_ra(const char *p)
|
|
+{
|
|
+ unsigned long val = (unsigned long) p;
|
|
+
|
|
+ return kern_base + (val - KERNBASE);
|
|
+}
|
|
+#endif
|
|
+
|
|
#ifdef CONFIG_SPARC32
|
|
/* cpu.c */
|
|
extern void cpu_probe(void);
|
|
diff --git a/arch/sparc/kernel/ktlb.S b/arch/sparc/kernel/ktlb.S
|
|
index 1d36147..79f3103 100644
|
|
--- a/arch/sparc/kernel/ktlb.S
|
|
+++ b/arch/sparc/kernel/ktlb.S
|
|
@@ -47,16 +47,16 @@ kvmap_itlb_tsb_miss:
|
|
kvmap_itlb_vmalloc_addr:
|
|
KERN_PGTABLE_WALK(%g4, %g5, %g2, kvmap_itlb_longpath)
|
|
|
|
- KTSB_LOCK_TAG(%g1, %g2, %g7)
|
|
+ TSB_LOCK_TAG(%g1, %g2, %g7)
|
|
|
|
/* Load and check PTE. */
|
|
ldxa [%g5] ASI_PHYS_USE_EC, %g5
|
|
mov 1, %g7
|
|
sllx %g7, TSB_TAG_INVALID_BIT, %g7
|
|
brgez,a,pn %g5, kvmap_itlb_longpath
|
|
- KTSB_STORE(%g1, %g7)
|
|
+ TSB_STORE(%g1, %g7)
|
|
|
|
- KTSB_WRITE(%g1, %g5, %g6)
|
|
+ TSB_WRITE(%g1, %g5, %g6)
|
|
|
|
/* fallthrough to TLB load */
|
|
|
|
@@ -102,9 +102,9 @@ kvmap_itlb_longpath:
|
|
kvmap_itlb_obp:
|
|
OBP_TRANS_LOOKUP(%g4, %g5, %g2, %g3, kvmap_itlb_longpath)
|
|
|
|
- KTSB_LOCK_TAG(%g1, %g2, %g7)
|
|
+ TSB_LOCK_TAG(%g1, %g2, %g7)
|
|
|
|
- KTSB_WRITE(%g1, %g5, %g6)
|
|
+ TSB_WRITE(%g1, %g5, %g6)
|
|
|
|
ba,pt %xcc, kvmap_itlb_load
|
|
nop
|
|
@@ -112,17 +112,17 @@ kvmap_itlb_obp:
|
|
kvmap_dtlb_obp:
|
|
OBP_TRANS_LOOKUP(%g4, %g5, %g2, %g3, kvmap_dtlb_longpath)
|
|
|
|
- KTSB_LOCK_TAG(%g1, %g2, %g7)
|
|
+ TSB_LOCK_TAG(%g1, %g2, %g7)
|
|
|
|
- KTSB_WRITE(%g1, %g5, %g6)
|
|
+ TSB_WRITE(%g1, %g5, %g6)
|
|
|
|
ba,pt %xcc, kvmap_dtlb_load
|
|
nop
|
|
|
|
.align 32
|
|
kvmap_dtlb_tsb4m_load:
|
|
- KTSB_LOCK_TAG(%g1, %g2, %g7)
|
|
- KTSB_WRITE(%g1, %g5, %g6)
|
|
+ TSB_LOCK_TAG(%g1, %g2, %g7)
|
|
+ TSB_WRITE(%g1, %g5, %g6)
|
|
ba,pt %xcc, kvmap_dtlb_load
|
|
nop
|
|
|
|
@@ -222,16 +222,16 @@ kvmap_linear_patch:
|
|
kvmap_dtlb_vmalloc_addr:
|
|
KERN_PGTABLE_WALK(%g4, %g5, %g2, kvmap_dtlb_longpath)
|
|
|
|
- KTSB_LOCK_TAG(%g1, %g2, %g7)
|
|
+ TSB_LOCK_TAG(%g1, %g2, %g7)
|
|
|
|
/* Load and check PTE. */
|
|
ldxa [%g5] ASI_PHYS_USE_EC, %g5
|
|
mov 1, %g7
|
|
sllx %g7, TSB_TAG_INVALID_BIT, %g7
|
|
brgez,a,pn %g5, kvmap_dtlb_longpath
|
|
- KTSB_STORE(%g1, %g7)
|
|
+ TSB_STORE(%g1, %g7)
|
|
|
|
- KTSB_WRITE(%g1, %g5, %g6)
|
|
+ TSB_WRITE(%g1, %g5, %g6)
|
|
|
|
/* fallthrough to TLB load */
|
|
|
|
diff --git a/arch/sparc/kernel/mdesc.c b/arch/sparc/kernel/mdesc.c
|
|
index 42f28c7..acaebb6 100644
|
|
--- a/arch/sparc/kernel/mdesc.c
|
|
+++ b/arch/sparc/kernel/mdesc.c
|
|
@@ -508,6 +508,8 @@ const char *mdesc_node_name(struct mdesc_handle *hp, u64 node)
|
|
}
|
|
EXPORT_SYMBOL(mdesc_node_name);
|
|
|
|
+static u64 max_cpus = 64;
|
|
+
|
|
static void __init report_platform_properties(void)
|
|
{
|
|
struct mdesc_handle *hp = mdesc_grab();
|
|
@@ -543,8 +545,10 @@ static void __init report_platform_properties(void)
|
|
if (v)
|
|
printk("PLATFORM: watchdog-max-timeout [%llu ms]\n", *v);
|
|
v = mdesc_get_property(hp, pn, "max-cpus", NULL);
|
|
- if (v)
|
|
- printk("PLATFORM: max-cpus [%llu]\n", *v);
|
|
+ if (v) {
|
|
+ max_cpus = *v;
|
|
+ printk("PLATFORM: max-cpus [%llu]\n", max_cpus);
|
|
+ }
|
|
|
|
#ifdef CONFIG_SMP
|
|
{
|
|
@@ -715,7 +719,7 @@ static void __cpuinit set_proc_ids(struct mdesc_handle *hp)
|
|
}
|
|
|
|
static void __cpuinit get_one_mondo_bits(const u64 *p, unsigned int *mask,
|
|
- unsigned char def)
|
|
+ unsigned long def, unsigned long max)
|
|
{
|
|
u64 val;
|
|
|
|
@@ -726,6 +730,9 @@ static void __cpuinit get_one_mondo_bits(const u64 *p, unsigned int *mask,
|
|
if (!val || val >= 64)
|
|
goto use_default;
|
|
|
|
+ if (val > max)
|
|
+ val = max;
|
|
+
|
|
*mask = ((1U << val) * 64U) - 1U;
|
|
return;
|
|
|
|
@@ -736,19 +743,28 @@ use_default:
|
|
static void __cpuinit get_mondo_data(struct mdesc_handle *hp, u64 mp,
|
|
struct trap_per_cpu *tb)
|
|
{
|
|
+ static int printed;
|
|
const u64 *val;
|
|
|
|
val = mdesc_get_property(hp, mp, "q-cpu-mondo-#bits", NULL);
|
|
- get_one_mondo_bits(val, &tb->cpu_mondo_qmask, 7);
|
|
+ get_one_mondo_bits(val, &tb->cpu_mondo_qmask, 7, ilog2(max_cpus * 2));
|
|
|
|
val = mdesc_get_property(hp, mp, "q-dev-mondo-#bits", NULL);
|
|
- get_one_mondo_bits(val, &tb->dev_mondo_qmask, 7);
|
|
+ get_one_mondo_bits(val, &tb->dev_mondo_qmask, 7, 8);
|
|
|
|
val = mdesc_get_property(hp, mp, "q-resumable-#bits", NULL);
|
|
- get_one_mondo_bits(val, &tb->resum_qmask, 6);
|
|
+ get_one_mondo_bits(val, &tb->resum_qmask, 6, 7);
|
|
|
|
val = mdesc_get_property(hp, mp, "q-nonresumable-#bits", NULL);
|
|
- get_one_mondo_bits(val, &tb->nonresum_qmask, 2);
|
|
+ get_one_mondo_bits(val, &tb->nonresum_qmask, 2, 2);
|
|
+ if (!printed++) {
|
|
+ pr_info("SUN4V: Mondo queue sizes "
|
|
+ "[cpu(%u) dev(%u) r(%u) nr(%u)]\n",
|
|
+ tb->cpu_mondo_qmask + 1,
|
|
+ tb->dev_mondo_qmask + 1,
|
|
+ tb->resum_qmask + 1,
|
|
+ tb->nonresum_qmask + 1);
|
|
+ }
|
|
}
|
|
|
|
static void * __cpuinit mdesc_iterate_over_cpus(void *(*func)(struct mdesc_handle *, u64, int, void *), void *arg, cpumask_t *mask)
|
|
diff --git a/arch/sparc/kernel/pcr.c b/arch/sparc/kernel/pcr.c
|
|
index 8ac23e6..343b0f9 100644
|
|
--- a/arch/sparc/kernel/pcr.c
|
|
+++ b/arch/sparc/kernel/pcr.c
|
|
@@ -80,8 +80,11 @@ static void n2_pcr_write(u64 val)
|
|
{
|
|
unsigned long ret;
|
|
|
|
- ret = sun4v_niagara2_setperf(HV_N2_PERF_SPARC_CTL, val);
|
|
- if (ret != HV_EOK)
|
|
+ if (val & PCR_N2_HTRACE) {
|
|
+ ret = sun4v_niagara2_setperf(HV_N2_PERF_SPARC_CTL, val);
|
|
+ if (ret != HV_EOK)
|
|
+ write_pcr(val);
|
|
+ } else
|
|
write_pcr(val);
|
|
}
|
|
|
|
@@ -106,6 +109,10 @@ static int __init register_perf_hsvc(void)
|
|
perf_hsvc_group = HV_GRP_N2_CPU;
|
|
break;
|
|
|
|
+ case SUN4V_CHIP_NIAGARA3:
|
|
+ perf_hsvc_group = HV_GRP_KT_CPU;
|
|
+ break;
|
|
+
|
|
default:
|
|
return -ENODEV;
|
|
}
|
|
diff --git a/arch/sparc/kernel/perf_event.c b/arch/sparc/kernel/perf_event.c
|
|
index 2cb0e1c..6860d40 100644
|
|
--- a/arch/sparc/kernel/perf_event.c
|
|
+++ b/arch/sparc/kernel/perf_event.c
|
|
@@ -1301,7 +1301,8 @@ static bool __init supported_pmu(void)
|
|
sparc_pmu = &niagara1_pmu;
|
|
return true;
|
|
}
|
|
- if (!strcmp(sparc_pmu_type, "niagara2")) {
|
|
+ if (!strcmp(sparc_pmu_type, "niagara2") ||
|
|
+ !strcmp(sparc_pmu_type, "niagara3")) {
|
|
sparc_pmu = &niagara2_pmu;
|
|
return true;
|
|
}
|
|
diff --git a/arch/sparc/kernel/setup_64.c b/arch/sparc/kernel/setup_64.c
|
|
index c4dd099..3e9daea 100644
|
|
--- a/arch/sparc/kernel/setup_64.c
|
|
+++ b/arch/sparc/kernel/setup_64.c
|
|
@@ -29,6 +29,7 @@
|
|
#include <linux/interrupt.h>
|
|
#include <linux/cpu.h>
|
|
#include <linux/initrd.h>
|
|
+#include <linux/module.h>
|
|
|
|
#include <asm/system.h>
|
|
#include <asm/io.h>
|
|
@@ -46,6 +47,8 @@
|
|
#include <asm/mmu.h>
|
|
#include <asm/ns87303.h>
|
|
#include <asm/btext.h>
|
|
+#include <asm/elf.h>
|
|
+#include <asm/mdesc.h>
|
|
|
|
#ifdef CONFIG_IP_PNP
|
|
#include <net/ipconfig.h>
|
|
@@ -269,6 +272,40 @@ void __init sun4v_patch(void)
|
|
sun4v_hvapi_init();
|
|
}
|
|
|
|
+static void __init popc_patch(void)
|
|
+{
|
|
+ struct popc_3insn_patch_entry *p3;
|
|
+ struct popc_6insn_patch_entry *p6;
|
|
+
|
|
+ p3 = &__popc_3insn_patch;
|
|
+ while (p3 < &__popc_3insn_patch_end) {
|
|
+ unsigned long i, addr = p3->addr;
|
|
+
|
|
+ for (i = 0; i < 3; i++) {
|
|
+ *(unsigned int *) (addr + (i * 4)) = p3->insns[i];
|
|
+ wmb();
|
|
+ __asm__ __volatile__("flush %0"
|
|
+ : : "r" (addr + (i * 4)));
|
|
+ }
|
|
+
|
|
+ p3++;
|
|
+ }
|
|
+
|
|
+ p6 = &__popc_6insn_patch;
|
|
+ while (p6 < &__popc_6insn_patch_end) {
|
|
+ unsigned long i, addr = p6->addr;
|
|
+
|
|
+ for (i = 0; i < 6; i++) {
|
|
+ *(unsigned int *) (addr + (i * 4)) = p6->insns[i];
|
|
+ wmb();
|
|
+ __asm__ __volatile__("flush %0"
|
|
+ : : "r" (addr + (i * 4)));
|
|
+ }
|
|
+
|
|
+ p6++;
|
|
+ }
|
|
+}
|
|
+
|
|
#ifdef CONFIG_SMP
|
|
void __init boot_cpu_id_too_large(int cpu)
|
|
{
|
|
@@ -278,6 +315,154 @@ void __init boot_cpu_id_too_large(int cpu)
|
|
}
|
|
#endif
|
|
|
|
+/* On Ultra, we support all of the v8 capabilities. */
|
|
+unsigned long sparc64_elf_hwcap = (HWCAP_SPARC_FLUSH | HWCAP_SPARC_STBAR |
|
|
+ HWCAP_SPARC_SWAP | HWCAP_SPARC_MULDIV |
|
|
+ HWCAP_SPARC_V9);
|
|
+EXPORT_SYMBOL(sparc64_elf_hwcap);
|
|
+
|
|
+static const char *hwcaps[] = {
|
|
+ "flush", "stbar", "swap", "muldiv", "v9",
|
|
+ "ultra3", "blkinit", "n2",
|
|
+
|
|
+ /* These strings are as they appear in the machine description
|
|
+ * 'hwcap-list' property for cpu nodes.
|
|
+ */
|
|
+ "mul32", "div32", "fsmuld", "v8plus", "popc", "vis", "vis2",
|
|
+ "ASIBlkInit", "fmaf", "vis3", "hpc", "random", "trans", "fjfmau",
|
|
+ "ima", "cspare",
|
|
+};
|
|
+
|
|
+void cpucap_info(struct seq_file *m)
|
|
+{
|
|
+ unsigned long caps = sparc64_elf_hwcap;
|
|
+ int i, printed = 0;
|
|
+
|
|
+ seq_puts(m, "cpucaps\t\t: ");
|
|
+ for (i = 0; i < ARRAY_SIZE(hwcaps); i++) {
|
|
+ unsigned long bit = 1UL << i;
|
|
+ if (caps & bit) {
|
|
+ seq_printf(m, "%s%s",
|
|
+ printed ? "," : "", hwcaps[i]);
|
|
+ printed++;
|
|
+ }
|
|
+ }
|
|
+ seq_putc(m, '\n');
|
|
+}
|
|
+
|
|
+static void __init report_hwcaps(unsigned long caps)
|
|
+{
|
|
+ int i, printed = 0;
|
|
+
|
|
+ printk(KERN_INFO "CPU CAPS: [");
|
|
+ for (i = 0; i < ARRAY_SIZE(hwcaps); i++) {
|
|
+ unsigned long bit = 1UL << i;
|
|
+ if (caps & bit) {
|
|
+ printk(KERN_CONT "%s%s",
|
|
+ printed ? "," : "", hwcaps[i]);
|
|
+ if (++printed == 8) {
|
|
+ printk(KERN_CONT "]\n");
|
|
+ printk(KERN_INFO "CPU CAPS: [");
|
|
+ printed = 0;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ printk(KERN_CONT "]\n");
|
|
+}
|
|
+
|
|
+static unsigned long __init mdesc_cpu_hwcap_list(void)
|
|
+{
|
|
+ struct mdesc_handle *hp;
|
|
+ unsigned long caps = 0;
|
|
+ const char *prop;
|
|
+ int len;
|
|
+ u64 pn;
|
|
+
|
|
+ hp = mdesc_grab();
|
|
+ if (!hp)
|
|
+ return 0;
|
|
+
|
|
+ pn = mdesc_node_by_name(hp, MDESC_NODE_NULL, "cpu");
|
|
+ if (pn == MDESC_NODE_NULL)
|
|
+ goto out;
|
|
+
|
|
+ prop = mdesc_get_property(hp, pn, "hwcap-list", &len);
|
|
+ if (!prop)
|
|
+ goto out;
|
|
+
|
|
+ while (len) {
|
|
+ int i, plen;
|
|
+
|
|
+ for (i = 0; i < ARRAY_SIZE(hwcaps); i++) {
|
|
+ unsigned long bit = 1UL << i;
|
|
+
|
|
+ if (!strcmp(prop, hwcaps[i])) {
|
|
+ caps |= bit;
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ plen = strlen(prop) + 1;
|
|
+ prop += plen;
|
|
+ len -= plen;
|
|
+ }
|
|
+
|
|
+out:
|
|
+ mdesc_release(hp);
|
|
+ return caps;
|
|
+}
|
|
+
|
|
+/* This yields a mask that user programs can use to figure out what
|
|
+ * instruction set this cpu supports.
|
|
+ */
|
|
+static void __init init_sparc64_elf_hwcap(void)
|
|
+{
|
|
+ unsigned long cap = sparc64_elf_hwcap;
|
|
+ unsigned long mdesc_caps;
|
|
+
|
|
+ if (tlb_type == cheetah || tlb_type == cheetah_plus)
|
|
+ cap |= HWCAP_SPARC_ULTRA3;
|
|
+ else if (tlb_type == hypervisor) {
|
|
+ if (sun4v_chip_type == SUN4V_CHIP_NIAGARA1 ||
|
|
+ sun4v_chip_type == SUN4V_CHIP_NIAGARA2 ||
|
|
+ sun4v_chip_type == SUN4V_CHIP_NIAGARA3)
|
|
+ cap |= HWCAP_SPARC_BLKINIT;
|
|
+ if (sun4v_chip_type == SUN4V_CHIP_NIAGARA2 ||
|
|
+ sun4v_chip_type == SUN4V_CHIP_NIAGARA3)
|
|
+ cap |= HWCAP_SPARC_N2;
|
|
+ }
|
|
+
|
|
+ cap |= (AV_SPARC_MUL32 | AV_SPARC_DIV32 | AV_SPARC_V8PLUS);
|
|
+
|
|
+ mdesc_caps = mdesc_cpu_hwcap_list();
|
|
+ if (!mdesc_caps) {
|
|
+ if (tlb_type == spitfire)
|
|
+ cap |= AV_SPARC_VIS;
|
|
+ if (tlb_type == cheetah || tlb_type == cheetah_plus)
|
|
+ cap |= AV_SPARC_VIS | AV_SPARC_VIS2;
|
|
+ if (tlb_type == cheetah_plus)
|
|
+ cap |= AV_SPARC_POPC;
|
|
+ if (tlb_type == hypervisor) {
|
|
+ if (sun4v_chip_type == SUN4V_CHIP_NIAGARA1)
|
|
+ cap |= AV_SPARC_ASI_BLK_INIT;
|
|
+ if (sun4v_chip_type == SUN4V_CHIP_NIAGARA2 ||
|
|
+ sun4v_chip_type == SUN4V_CHIP_NIAGARA3)
|
|
+ cap |= (AV_SPARC_VIS | AV_SPARC_VIS2 |
|
|
+ AV_SPARC_ASI_BLK_INIT |
|
|
+ AV_SPARC_POPC);
|
|
+ if (sun4v_chip_type == SUN4V_CHIP_NIAGARA3)
|
|
+ cap |= (AV_SPARC_VIS3 | AV_SPARC_HPC |
|
|
+ AV_SPARC_FMAF);
|
|
+ }
|
|
+ }
|
|
+ sparc64_elf_hwcap = cap | mdesc_caps;
|
|
+
|
|
+ report_hwcaps(sparc64_elf_hwcap);
|
|
+
|
|
+ if (sparc64_elf_hwcap & AV_SPARC_POPC)
|
|
+ popc_patch();
|
|
+}
|
|
+
|
|
void __init setup_arch(char **cmdline_p)
|
|
{
|
|
/* Initialize PROM console and command line. */
|
|
@@ -337,6 +522,7 @@ void __init setup_arch(char **cmdline_p)
|
|
init_cur_cpu_trap(current_thread_info());
|
|
|
|
paging_init();
|
|
+ init_sparc64_elf_hwcap();
|
|
}
|
|
|
|
extern int stop_a_enabled;
|
|
diff --git a/arch/sparc/kernel/sparc_ksyms_64.c b/arch/sparc/kernel/sparc_ksyms_64.c
|
|
index 372ad59..83b47ab 100644
|
|
--- a/arch/sparc/kernel/sparc_ksyms_64.c
|
|
+++ b/arch/sparc/kernel/sparc_ksyms_64.c
|
|
@@ -8,6 +8,7 @@
|
|
#include <linux/module.h>
|
|
#include <linux/pci.h>
|
|
#include <linux/init.h>
|
|
+#include <linux/bitops.h>
|
|
|
|
#include <asm/system.h>
|
|
#include <asm/cpudata.h>
|
|
@@ -38,5 +39,15 @@ EXPORT_SYMBOL(sun4v_niagara_setperf);
|
|
EXPORT_SYMBOL(sun4v_niagara2_getperf);
|
|
EXPORT_SYMBOL(sun4v_niagara2_setperf);
|
|
|
|
+/* from hweight.S */
|
|
+EXPORT_SYMBOL(__arch_hweight8);
|
|
+EXPORT_SYMBOL(__arch_hweight16);
|
|
+EXPORT_SYMBOL(__arch_hweight32);
|
|
+EXPORT_SYMBOL(__arch_hweight64);
|
|
+
|
|
+/* from ffs_ffz.S */
|
|
+EXPORT_SYMBOL(ffs);
|
|
+EXPORT_SYMBOL(__ffs);
|
|
+
|
|
/* Exporting a symbol from /init/main.c */
|
|
EXPORT_SYMBOL(saved_command_line);
|
|
diff --git a/arch/sparc/kernel/sstate.c b/arch/sparc/kernel/sstate.c
|
|
index 8cdbe59..c59af54 100644
|
|
--- a/arch/sparc/kernel/sstate.c
|
|
+++ b/arch/sparc/kernel/sstate.c
|
|
@@ -14,14 +14,9 @@
|
|
#include <asm/head.h>
|
|
#include <asm/io.h>
|
|
|
|
-static int hv_supports_soft_state;
|
|
-
|
|
-static unsigned long kimage_addr_to_ra(const char *p)
|
|
-{
|
|
- unsigned long val = (unsigned long) p;
|
|
+#include "kernel.h"
|
|
|
|
- return kern_base + (val - KERNBASE);
|
|
-}
|
|
+static int hv_supports_soft_state;
|
|
|
|
static void do_set_sstate(unsigned long state, const char *msg)
|
|
{
|
|
diff --git a/arch/sparc/kernel/unaligned_64.c b/arch/sparc/kernel/unaligned_64.c
|
|
index b2b019e..9043106 100644
|
|
--- a/arch/sparc/kernel/unaligned_64.c
|
|
+++ b/arch/sparc/kernel/unaligned_64.c
|
|
@@ -22,6 +22,7 @@
|
|
#include <linux/bitops.h>
|
|
#include <linux/perf_event.h>
|
|
#include <linux/ratelimit.h>
|
|
+#include <linux/bitops.h>
|
|
#include <asm/fpumacro.h>
|
|
|
|
enum direction {
|
|
@@ -373,16 +374,11 @@ asmlinkage void kernel_unaligned_trap(struct pt_regs *regs, unsigned int insn)
|
|
}
|
|
}
|
|
|
|
-static char popc_helper[] = {
|
|
-0, 1, 1, 2, 1, 2, 2, 3,
|
|
-1, 2, 2, 3, 2, 3, 3, 4,
|
|
-};
|
|
-
|
|
int handle_popc(u32 insn, struct pt_regs *regs)
|
|
{
|
|
- u64 value;
|
|
- int ret, i, rd = ((insn >> 25) & 0x1f);
|
|
int from_kernel = (regs->tstate & TSTATE_PRIV) != 0;
|
|
+ int ret, rd = ((insn >> 25) & 0x1f);
|
|
+ u64 value;
|
|
|
|
perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS, 1, 0, regs, 0);
|
|
if (insn & 0x2000) {
|
|
@@ -392,10 +388,7 @@ int handle_popc(u32 insn, struct pt_regs *regs)
|
|
maybe_flush_windows(0, insn & 0x1f, rd, from_kernel);
|
|
value = fetch_reg(insn & 0x1f, regs);
|
|
}
|
|
- for (ret = 0, i = 0; i < 16; i++) {
|
|
- ret += popc_helper[value & 0xf];
|
|
- value >>= 4;
|
|
- }
|
|
+ ret = hweight64(value);
|
|
if (rd < 16) {
|
|
if (rd)
|
|
regs->u_regs[rd] = ret;
|
|
diff --git a/arch/sparc/kernel/vmlinux.lds.S b/arch/sparc/kernel/vmlinux.lds.S
|
|
index c022075..0e16056 100644
|
|
--- a/arch/sparc/kernel/vmlinux.lds.S
|
|
+++ b/arch/sparc/kernel/vmlinux.lds.S
|
|
@@ -107,7 +107,26 @@ SECTIONS
|
|
*(.sun4v_2insn_patch)
|
|
__sun4v_2insn_patch_end = .;
|
|
}
|
|
-
|
|
+ .swapper_tsb_phys_patch : {
|
|
+ __swapper_tsb_phys_patch = .;
|
|
+ *(.swapper_tsb_phys_patch)
|
|
+ __swapper_tsb_phys_patch_end = .;
|
|
+ }
|
|
+ .swapper_4m_tsb_phys_patch : {
|
|
+ __swapper_4m_tsb_phys_patch = .;
|
|
+ *(.swapper_4m_tsb_phys_patch)
|
|
+ __swapper_4m_tsb_phys_patch_end = .;
|
|
+ }
|
|
+ .popc_3insn_patch : {
|
|
+ __popc_3insn_patch = .;
|
|
+ *(.popc_3insn_patch)
|
|
+ __popc_3insn_patch_end = .;
|
|
+ }
|
|
+ .popc_6insn_patch : {
|
|
+ __popc_6insn_patch = .;
|
|
+ *(.popc_6insn_patch)
|
|
+ __popc_6insn_patch_end = .;
|
|
+ }
|
|
PERCPU_SECTION(SMP_CACHE_BYTES)
|
|
|
|
. = ALIGN(PAGE_SIZE);
|
|
diff --git a/arch/sparc/lib/Makefile b/arch/sparc/lib/Makefile
|
|
index 7f01b8f..a3fc437 100644
|
|
--- a/arch/sparc/lib/Makefile
|
|
+++ b/arch/sparc/lib/Makefile
|
|
@@ -31,13 +31,13 @@ lib-$(CONFIG_SPARC64) += NGmemcpy.o NGcopy_from_user.o NGcopy_to_user.o
|
|
lib-$(CONFIG_SPARC64) += NGpatch.o NGpage.o NGbzero.o
|
|
|
|
lib-$(CONFIG_SPARC64) += NG2memcpy.o NG2copy_from_user.o NG2copy_to_user.o
|
|
-lib-$(CONFIG_SPARC64) += NG2patch.o NG2page.o
|
|
+lib-$(CONFIG_SPARC64) += NG2patch.o
|
|
|
|
lib-$(CONFIG_SPARC64) += GENmemcpy.o GENcopy_from_user.o GENcopy_to_user.o
|
|
lib-$(CONFIG_SPARC64) += GENpatch.o GENpage.o GENbzero.o
|
|
|
|
lib-$(CONFIG_SPARC64) += copy_in_user.o user_fixup.o memmove.o
|
|
-lib-$(CONFIG_SPARC64) += mcount.o ipcsum.o xor.o
|
|
+lib-$(CONFIG_SPARC64) += mcount.o ipcsum.o xor.o hweight.o ffs.o
|
|
|
|
obj-y += iomap.o
|
|
obj-$(CONFIG_SPARC32) += atomic32.o
|
|
diff --git a/arch/sparc/lib/NG2page.S b/arch/sparc/lib/NG2page.S
|
|
deleted file mode 100644
|
|
index 73b6b7c..0000000
|
|
--- a/arch/sparc/lib/NG2page.S
|
|
+++ /dev/null
|
|
@@ -1,61 +0,0 @@
|
|
-/* NG2page.S: Niagara-2 optimized clear and copy page.
|
|
- *
|
|
- * Copyright (C) 2007 (davem@davemloft.net)
|
|
- */
|
|
-
|
|
-#include <asm/asi.h>
|
|
-#include <asm/page.h>
|
|
-#include <asm/visasm.h>
|
|
-
|
|
- .text
|
|
- .align 32
|
|
-
|
|
- /* This is heavily simplified from the sun4u variants
|
|
- * because Niagara-2 does not have any D-cache aliasing issues.
|
|
- */
|
|
-NG2copy_user_page: /* %o0=dest, %o1=src, %o2=vaddr */
|
|
- prefetch [%o1 + 0x00], #one_read
|
|
- prefetch [%o1 + 0x40], #one_read
|
|
- VISEntryHalf
|
|
- set PAGE_SIZE, %g7
|
|
- sub %o0, %o1, %g3
|
|
-1: stxa %g0, [%o1 + %g3] ASI_BLK_INIT_QUAD_LDD_P
|
|
- subcc %g7, 64, %g7
|
|
- ldda [%o1] ASI_BLK_P, %f0
|
|
- stda %f0, [%o1 + %g3] ASI_BLK_P
|
|
- add %o1, 64, %o1
|
|
- bne,pt %xcc, 1b
|
|
- prefetch [%o1 + 0x40], #one_read
|
|
- membar #Sync
|
|
- VISExitHalf
|
|
- retl
|
|
- nop
|
|
-
|
|
-#define BRANCH_ALWAYS 0x10680000
|
|
-#define NOP 0x01000000
|
|
-#define NG_DO_PATCH(OLD, NEW) \
|
|
- sethi %hi(NEW), %g1; \
|
|
- or %g1, %lo(NEW), %g1; \
|
|
- sethi %hi(OLD), %g2; \
|
|
- or %g2, %lo(OLD), %g2; \
|
|
- sub %g1, %g2, %g1; \
|
|
- sethi %hi(BRANCH_ALWAYS), %g3; \
|
|
- sll %g1, 11, %g1; \
|
|
- srl %g1, 11 + 2, %g1; \
|
|
- or %g3, %lo(BRANCH_ALWAYS), %g3; \
|
|
- or %g3, %g1, %g3; \
|
|
- stw %g3, [%g2]; \
|
|
- sethi %hi(NOP), %g3; \
|
|
- or %g3, %lo(NOP), %g3; \
|
|
- stw %g3, [%g2 + 0x4]; \
|
|
- flush %g2;
|
|
-
|
|
- .globl niagara2_patch_pageops
|
|
- .type niagara2_patch_pageops,#function
|
|
-niagara2_patch_pageops:
|
|
- NG_DO_PATCH(copy_user_page, NG2copy_user_page)
|
|
- NG_DO_PATCH(_clear_page, NGclear_page)
|
|
- NG_DO_PATCH(clear_user_page, NGclear_user_page)
|
|
- retl
|
|
- nop
|
|
- .size niagara2_patch_pageops,.-niagara2_patch_pageops
|
|
diff --git a/arch/sparc/lib/NGpage.S b/arch/sparc/lib/NGpage.S
|
|
index 428920d..b9e790b 100644
|
|
--- a/arch/sparc/lib/NGpage.S
|
|
+++ b/arch/sparc/lib/NGpage.S
|
|
@@ -16,55 +16,91 @@
|
|
*/
|
|
|
|
NGcopy_user_page: /* %o0=dest, %o1=src, %o2=vaddr */
|
|
- prefetch [%o1 + 0x00], #one_read
|
|
- mov 8, %g1
|
|
- mov 16, %g2
|
|
- mov 24, %g3
|
|
+ save %sp, -192, %sp
|
|
+ rd %asi, %g3
|
|
+ wr %g0, ASI_BLK_INIT_QUAD_LDD_P, %asi
|
|
set PAGE_SIZE, %g7
|
|
+ prefetch [%i1 + 0x00], #one_read
|
|
+ prefetch [%i1 + 0x40], #one_read
|
|
|
|
-1: ldda [%o1 + %g0] ASI_BLK_INIT_QUAD_LDD_P, %o2
|
|
- ldda [%o1 + %g2] ASI_BLK_INIT_QUAD_LDD_P, %o4
|
|
- prefetch [%o1 + 0x40], #one_read
|
|
- add %o1, 32, %o1
|
|
- stxa %o2, [%o0 + %g0] ASI_BLK_INIT_QUAD_LDD_P
|
|
- stxa %o3, [%o0 + %g1] ASI_BLK_INIT_QUAD_LDD_P
|
|
- ldda [%o1 + %g0] ASI_BLK_INIT_QUAD_LDD_P, %o2
|
|
- stxa %o4, [%o0 + %g2] ASI_BLK_INIT_QUAD_LDD_P
|
|
- stxa %o5, [%o0 + %g3] ASI_BLK_INIT_QUAD_LDD_P
|
|
- ldda [%o1 + %g2] ASI_BLK_INIT_QUAD_LDD_P, %o4
|
|
- add %o1, 32, %o1
|
|
- add %o0, 32, %o0
|
|
- stxa %o2, [%o0 + %g0] ASI_BLK_INIT_QUAD_LDD_P
|
|
- stxa %o3, [%o0 + %g1] ASI_BLK_INIT_QUAD_LDD_P
|
|
- stxa %o4, [%o0 + %g2] ASI_BLK_INIT_QUAD_LDD_P
|
|
- stxa %o5, [%o0 + %g3] ASI_BLK_INIT_QUAD_LDD_P
|
|
- subcc %g7, 64, %g7
|
|
+1: prefetch [%i1 + 0x80], #one_read
|
|
+ prefetch [%i1 + 0xc0], #one_read
|
|
+ ldda [%i1 + 0x00] %asi, %o2
|
|
+ ldda [%i1 + 0x10] %asi, %o4
|
|
+ ldda [%i1 + 0x20] %asi, %l2
|
|
+ ldda [%i1 + 0x30] %asi, %l4
|
|
+ stxa %o2, [%i0 + 0x00] %asi
|
|
+ stxa %o3, [%i0 + 0x08] %asi
|
|
+ stxa %o4, [%i0 + 0x10] %asi
|
|
+ stxa %o5, [%i0 + 0x18] %asi
|
|
+ stxa %l2, [%i0 + 0x20] %asi
|
|
+ stxa %l3, [%i0 + 0x28] %asi
|
|
+ stxa %l4, [%i0 + 0x30] %asi
|
|
+ stxa %l5, [%i0 + 0x38] %asi
|
|
+ ldda [%i1 + 0x40] %asi, %o2
|
|
+ ldda [%i1 + 0x50] %asi, %o4
|
|
+ ldda [%i1 + 0x60] %asi, %l2
|
|
+ ldda [%i1 + 0x70] %asi, %l4
|
|
+ stxa %o2, [%i0 + 0x40] %asi
|
|
+ stxa %o3, [%i0 + 0x48] %asi
|
|
+ stxa %o4, [%i0 + 0x50] %asi
|
|
+ stxa %o5, [%i0 + 0x58] %asi
|
|
+ stxa %l2, [%i0 + 0x60] %asi
|
|
+ stxa %l3, [%i0 + 0x68] %asi
|
|
+ stxa %l4, [%i0 + 0x70] %asi
|
|
+ stxa %l5, [%i0 + 0x78] %asi
|
|
+ add %i1, 128, %i1
|
|
+ subcc %g7, 128, %g7
|
|
bne,pt %xcc, 1b
|
|
- add %o0, 32, %o0
|
|
+ add %i0, 128, %i0
|
|
+ wr %g3, 0x0, %asi
|
|
membar #Sync
|
|
- retl
|
|
- nop
|
|
+ ret
|
|
+ restore
|
|
|
|
- .globl NGclear_page, NGclear_user_page
|
|
+ .align 32
|
|
NGclear_page: /* %o0=dest */
|
|
NGclear_user_page: /* %o0=dest, %o1=vaddr */
|
|
- mov 8, %g1
|
|
- mov 16, %g2
|
|
- mov 24, %g3
|
|
+ rd %asi, %g3
|
|
+ wr %g0, ASI_BLK_INIT_QUAD_LDD_P, %asi
|
|
set PAGE_SIZE, %g7
|
|
|
|
-1: stxa %g0, [%o0 + %g0] ASI_BLK_INIT_QUAD_LDD_P
|
|
- stxa %g0, [%o0 + %g1] ASI_BLK_INIT_QUAD_LDD_P
|
|
- stxa %g0, [%o0 + %g2] ASI_BLK_INIT_QUAD_LDD_P
|
|
- stxa %g0, [%o0 + %g3] ASI_BLK_INIT_QUAD_LDD_P
|
|
- add %o0, 32, %o0
|
|
- stxa %g0, [%o0 + %g0] ASI_BLK_INIT_QUAD_LDD_P
|
|
- stxa %g0, [%o0 + %g1] ASI_BLK_INIT_QUAD_LDD_P
|
|
- stxa %g0, [%o0 + %g2] ASI_BLK_INIT_QUAD_LDD_P
|
|
- stxa %g0, [%o0 + %g3] ASI_BLK_INIT_QUAD_LDD_P
|
|
- subcc %g7, 64, %g7
|
|
+1: stxa %g0, [%o0 + 0x00] %asi
|
|
+ stxa %g0, [%o0 + 0x08] %asi
|
|
+ stxa %g0, [%o0 + 0x10] %asi
|
|
+ stxa %g0, [%o0 + 0x18] %asi
|
|
+ stxa %g0, [%o0 + 0x20] %asi
|
|
+ stxa %g0, [%o0 + 0x28] %asi
|
|
+ stxa %g0, [%o0 + 0x30] %asi
|
|
+ stxa %g0, [%o0 + 0x38] %asi
|
|
+ stxa %g0, [%o0 + 0x40] %asi
|
|
+ stxa %g0, [%o0 + 0x48] %asi
|
|
+ stxa %g0, [%o0 + 0x50] %asi
|
|
+ stxa %g0, [%o0 + 0x58] %asi
|
|
+ stxa %g0, [%o0 + 0x60] %asi
|
|
+ stxa %g0, [%o0 + 0x68] %asi
|
|
+ stxa %g0, [%o0 + 0x70] %asi
|
|
+ stxa %g0, [%o0 + 0x78] %asi
|
|
+ stxa %g0, [%o0 + 0x80] %asi
|
|
+ stxa %g0, [%o0 + 0x88] %asi
|
|
+ stxa %g0, [%o0 + 0x90] %asi
|
|
+ stxa %g0, [%o0 + 0x98] %asi
|
|
+ stxa %g0, [%o0 + 0xa0] %asi
|
|
+ stxa %g0, [%o0 + 0xa8] %asi
|
|
+ stxa %g0, [%o0 + 0xb0] %asi
|
|
+ stxa %g0, [%o0 + 0xb8] %asi
|
|
+ stxa %g0, [%o0 + 0xc0] %asi
|
|
+ stxa %g0, [%o0 + 0xc8] %asi
|
|
+ stxa %g0, [%o0 + 0xd0] %asi
|
|
+ stxa %g0, [%o0 + 0xd8] %asi
|
|
+ stxa %g0, [%o0 + 0xe0] %asi
|
|
+ stxa %g0, [%o0 + 0xe8] %asi
|
|
+ stxa %g0, [%o0 + 0xf0] %asi
|
|
+ stxa %g0, [%o0 + 0xf8] %asi
|
|
+ subcc %g7, 256, %g7
|
|
bne,pt %xcc, 1b
|
|
- add %o0, 32, %o0
|
|
+ add %o0, 256, %o0
|
|
+ wr %g3, 0x0, %asi
|
|
membar #Sync
|
|
retl
|
|
nop
|
|
diff --git a/arch/sparc/lib/ffs.S b/arch/sparc/lib/ffs.S
|
|
new file mode 100644
|
|
index 0000000..b39389f
|
|
--- /dev/null
|
|
+++ b/arch/sparc/lib/ffs.S
|
|
@@ -0,0 +1,84 @@
|
|
+#include <linux/linkage.h>
|
|
+
|
|
+ .register %g2,#scratch
|
|
+
|
|
+ .text
|
|
+ .align 32
|
|
+
|
|
+ENTRY(ffs)
|
|
+ brnz,pt %o0, 1f
|
|
+ mov 1, %o1
|
|
+ retl
|
|
+ clr %o0
|
|
+ nop
|
|
+ nop
|
|
+ENTRY(__ffs)
|
|
+ sllx %o0, 32, %g1 /* 1 */
|
|
+ srlx %o0, 32, %g2
|
|
+
|
|
+ clr %o1 /* 2 */
|
|
+ movrz %g1, %g2, %o0
|
|
+
|
|
+ movrz %g1, 32, %o1 /* 3 */
|
|
+1: clr %o2
|
|
+
|
|
+ sllx %o0, (64 - 16), %g1 /* 4 */
|
|
+ srlx %o0, 16, %g2
|
|
+
|
|
+ movrz %g1, %g2, %o0 /* 5 */
|
|
+ clr %o3
|
|
+
|
|
+ movrz %g1, 16, %o2 /* 6 */
|
|
+ clr %o4
|
|
+
|
|
+ and %o0, 0xff, %g1 /* 7 */
|
|
+ srlx %o0, 8, %g2
|
|
+
|
|
+ movrz %g1, %g2, %o0 /* 8 */
|
|
+ clr %o5
|
|
+
|
|
+ movrz %g1, 8, %o3 /* 9 */
|
|
+ add %o2, %o1, %o2
|
|
+
|
|
+ and %o0, 0xf, %g1 /* 10 */
|
|
+ srlx %o0, 4, %g2
|
|
+
|
|
+ movrz %g1, %g2, %o0 /* 11 */
|
|
+ add %o2, %o3, %o2
|
|
+
|
|
+ movrz %g1, 4, %o4 /* 12 */
|
|
+
|
|
+ and %o0, 0x3, %g1 /* 13 */
|
|
+ srlx %o0, 2, %g2
|
|
+
|
|
+ movrz %g1, %g2, %o0 /* 14 */
|
|
+ add %o2, %o4, %o2
|
|
+
|
|
+ movrz %g1, 2, %o5 /* 15 */
|
|
+
|
|
+ and %o0, 0x1, %g1 /* 16 */
|
|
+
|
|
+ add %o2, %o5, %o2 /* 17 */
|
|
+ xor %g1, 0x1, %g1
|
|
+
|
|
+ retl /* 18 */
|
|
+ add %o2, %g1, %o0
|
|
+ENDPROC(ffs)
|
|
+ENDPROC(__ffs)
|
|
+
|
|
+ .section .popc_6insn_patch, "ax"
|
|
+ .word ffs
|
|
+ brz,pn %o0, 98f
|
|
+ neg %o0, %g1
|
|
+ xnor %o0, %g1, %o1
|
|
+ popc %o1, %o0
|
|
+98: retl
|
|
+ nop
|
|
+ .word __ffs
|
|
+ neg %o0, %g1
|
|
+ xnor %o0, %g1, %o1
|
|
+ popc %o1, %o0
|
|
+ retl
|
|
+ sub %o0, 1, %o0
|
|
+ nop
|
|
+ .previous
|
|
diff --git a/arch/sparc/lib/hweight.S b/arch/sparc/lib/hweight.S
|
|
new file mode 100644
|
|
index 0000000..95414e0
|
|
--- /dev/null
|
|
+++ b/arch/sparc/lib/hweight.S
|
|
@@ -0,0 +1,51 @@
|
|
+#include <linux/linkage.h>
|
|
+
|
|
+ .text
|
|
+ .align 32
|
|
+ENTRY(__arch_hweight8)
|
|
+ ba,pt %xcc, __sw_hweight8
|
|
+ nop
|
|
+ nop
|
|
+ENDPROC(__arch_hweight8)
|
|
+ .section .popc_3insn_patch, "ax"
|
|
+ .word __arch_hweight8
|
|
+ sllx %o0, 64-8, %g1
|
|
+ retl
|
|
+ popc %g1, %o0
|
|
+ .previous
|
|
+
|
|
+ENTRY(__arch_hweight16)
|
|
+ ba,pt %xcc, __sw_hweight16
|
|
+ nop
|
|
+ nop
|
|
+ENDPROC(__arch_hweight16)
|
|
+ .section .popc_3insn_patch, "ax"
|
|
+ .word __arch_hweight16
|
|
+ sllx %o0, 64-16, %g1
|
|
+ retl
|
|
+ popc %g1, %o0
|
|
+ .previous
|
|
+
|
|
+ENTRY(__arch_hweight32)
|
|
+ ba,pt %xcc, __sw_hweight32
|
|
+ nop
|
|
+ nop
|
|
+ENDPROC(__arch_hweight32)
|
|
+ .section .popc_3insn_patch, "ax"
|
|
+ .word __arch_hweight32
|
|
+ sllx %o0, 64-32, %g1
|
|
+ retl
|
|
+ popc %g1, %o0
|
|
+ .previous
|
|
+
|
|
+ENTRY(__arch_hweight64)
|
|
+ ba,pt %xcc, __sw_hweight64
|
|
+ nop
|
|
+ nop
|
|
+ENDPROC(__arch_hweight64)
|
|
+ .section .popc_3insn_patch, "ax"
|
|
+ .word __arch_hweight64
|
|
+ retl
|
|
+ popc %o0, %o0
|
|
+ nop
|
|
+ .previous
|
|
diff --git a/arch/sparc/mm/init_64.c b/arch/sparc/mm/init_64.c
|
|
index 3fd8e18..581531d 100644
|
|
--- a/arch/sparc/mm/init_64.c
|
|
+++ b/arch/sparc/mm/init_64.c
|
|
@@ -1597,6 +1597,44 @@ static void __init tsb_phys_patch(void)
|
|
static struct hv_tsb_descr ktsb_descr[NUM_KTSB_DESCR];
|
|
extern struct tsb swapper_tsb[KERNEL_TSB_NENTRIES];
|
|
|
|
+static void patch_one_ktsb_phys(unsigned int *start, unsigned int *end, unsigned long pa)
|
|
+{
|
|
+ pa >>= KTSB_PHYS_SHIFT;
|
|
+
|
|
+ while (start < end) {
|
|
+ unsigned int *ia = (unsigned int *)(unsigned long)*start;
|
|
+
|
|
+ ia[0] = (ia[0] & ~0x3fffff) | (pa >> 10);
|
|
+ __asm__ __volatile__("flush %0" : : "r" (ia));
|
|
+
|
|
+ ia[1] = (ia[1] & ~0x3ff) | (pa & 0x3ff);
|
|
+ __asm__ __volatile__("flush %0" : : "r" (ia + 1));
|
|
+
|
|
+ start++;
|
|
+ }
|
|
+}
|
|
+
|
|
+static void ktsb_phys_patch(void)
|
|
+{
|
|
+ extern unsigned int __swapper_tsb_phys_patch;
|
|
+ extern unsigned int __swapper_tsb_phys_patch_end;
|
|
+ unsigned long ktsb_pa;
|
|
+
|
|
+ ktsb_pa = kern_base + ((unsigned long)&swapper_tsb[0] - KERNBASE);
|
|
+ patch_one_ktsb_phys(&__swapper_tsb_phys_patch,
|
|
+ &__swapper_tsb_phys_patch_end, ktsb_pa);
|
|
+#ifndef CONFIG_DEBUG_PAGEALLOC
|
|
+ {
|
|
+ extern unsigned int __swapper_4m_tsb_phys_patch;
|
|
+ extern unsigned int __swapper_4m_tsb_phys_patch_end;
|
|
+ ktsb_pa = (kern_base +
|
|
+ ((unsigned long)&swapper_4m_tsb[0] - KERNBASE));
|
|
+ patch_one_ktsb_phys(&__swapper_4m_tsb_phys_patch,
|
|
+ &__swapper_4m_tsb_phys_patch_end, ktsb_pa);
|
|
+ }
|
|
+#endif
|
|
+}
|
|
+
|
|
static void __init sun4v_ktsb_init(void)
|
|
{
|
|
unsigned long ktsb_pa;
|
|
@@ -1716,8 +1754,10 @@ void __init paging_init(void)
|
|
sun4u_pgprot_init();
|
|
|
|
if (tlb_type == cheetah_plus ||
|
|
- tlb_type == hypervisor)
|
|
+ tlb_type == hypervisor) {
|
|
tsb_phys_patch();
|
|
+ ktsb_phys_patch();
|
|
+ }
|
|
|
|
if (tlb_type == hypervisor) {
|
|
sun4v_patch_tlb_handlers();
|
|
diff --git a/arch/x86/xen/Makefile b/arch/x86/xen/Makefile
|
|
index 17c565d..a6575b9 100644
|
|
--- a/arch/x86/xen/Makefile
|
|
+++ b/arch/x86/xen/Makefile
|
|
@@ -18,5 +18,5 @@ obj-y := enlighten.o setup.o multicalls.o mmu.o irq.o \
|
|
obj-$(CONFIG_SMP) += smp.o
|
|
obj-$(CONFIG_PARAVIRT_SPINLOCKS)+= spinlock.o
|
|
obj-$(CONFIG_XEN_DEBUG_FS) += debugfs.o
|
|
-
|
|
+obj-$(CONFIG_XEN_DOM0) += vga.o
|
|
obj-$(CONFIG_SWIOTLB_XEN) += pci-swiotlb-xen.o
|
|
diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c
|
|
index 5525163..5325742 100644
|
|
--- a/arch/x86/xen/enlighten.c
|
|
+++ b/arch/x86/xen/enlighten.c
|
|
@@ -1248,6 +1248,14 @@ asmlinkage void __init xen_start_kernel(void)
|
|
if (pci_xen)
|
|
x86_init.pci.arch_init = pci_xen_init;
|
|
} else {
|
|
+ const struct dom0_vga_console_info *info =
|
|
+ (void *)((char *)xen_start_info +
|
|
+ xen_start_info->console.dom0.info_off);
|
|
+
|
|
+ xen_init_vga(info, xen_start_info->console.dom0.info_size);
|
|
+ xen_start_info->console.domU.mfn = 0;
|
|
+ xen_start_info->console.domU.evtchn = 0;
|
|
+
|
|
/* Make sure ACS will be enabled */
|
|
pci_request_acs();
|
|
}
|
|
diff --git a/arch/x86/xen/vga.c b/arch/x86/xen/vga.c
|
|
new file mode 100644
|
|
index 0000000..1cd7f4d
|
|
--- /dev/null
|
|
+++ b/arch/x86/xen/vga.c
|
|
@@ -0,0 +1,67 @@
|
|
+#include <linux/screen_info.h>
|
|
+#include <linux/init.h>
|
|
+
|
|
+#include <asm/bootparam.h>
|
|
+#include <asm/setup.h>
|
|
+
|
|
+#include <xen/interface/xen.h>
|
|
+
|
|
+#include "xen-ops.h"
|
|
+
|
|
+void __init xen_init_vga(const struct dom0_vga_console_info *info, size_t size)
|
|
+{
|
|
+ struct screen_info *screen_info = &boot_params.screen_info;
|
|
+
|
|
+ /* This is drawn from a dump from vgacon:startup in
|
|
+ * standard Linux. */
|
|
+ screen_info->orig_video_mode = 3;
|
|
+ screen_info->orig_video_isVGA = 1;
|
|
+ screen_info->orig_video_lines = 25;
|
|
+ screen_info->orig_video_cols = 80;
|
|
+ screen_info->orig_video_ega_bx = 3;
|
|
+ screen_info->orig_video_points = 16;
|
|
+ screen_info->orig_y = screen_info->orig_video_lines - 1;
|
|
+
|
|
+ switch (info->video_type) {
|
|
+ case XEN_VGATYPE_TEXT_MODE_3:
|
|
+ if (size < offsetof(struct dom0_vga_console_info, u.text_mode_3)
|
|
+ + sizeof(info->u.text_mode_3))
|
|
+ break;
|
|
+ screen_info->orig_video_lines = info->u.text_mode_3.rows;
|
|
+ screen_info->orig_video_cols = info->u.text_mode_3.columns;
|
|
+ screen_info->orig_x = info->u.text_mode_3.cursor_x;
|
|
+ screen_info->orig_y = info->u.text_mode_3.cursor_y;
|
|
+ screen_info->orig_video_points =
|
|
+ info->u.text_mode_3.font_height;
|
|
+ break;
|
|
+
|
|
+ case XEN_VGATYPE_VESA_LFB:
|
|
+ if (size < offsetof(struct dom0_vga_console_info,
|
|
+ u.vesa_lfb.gbl_caps))
|
|
+ break;
|
|
+ screen_info->orig_video_isVGA = VIDEO_TYPE_VLFB;
|
|
+ screen_info->lfb_width = info->u.vesa_lfb.width;
|
|
+ screen_info->lfb_height = info->u.vesa_lfb.height;
|
|
+ screen_info->lfb_depth = info->u.vesa_lfb.bits_per_pixel;
|
|
+ screen_info->lfb_base = info->u.vesa_lfb.lfb_base;
|
|
+ screen_info->lfb_size = info->u.vesa_lfb.lfb_size;
|
|
+ screen_info->lfb_linelength = info->u.vesa_lfb.bytes_per_line;
|
|
+ screen_info->red_size = info->u.vesa_lfb.red_size;
|
|
+ screen_info->red_pos = info->u.vesa_lfb.red_pos;
|
|
+ screen_info->green_size = info->u.vesa_lfb.green_size;
|
|
+ screen_info->green_pos = info->u.vesa_lfb.green_pos;
|
|
+ screen_info->blue_size = info->u.vesa_lfb.blue_size;
|
|
+ screen_info->blue_pos = info->u.vesa_lfb.blue_pos;
|
|
+ screen_info->rsvd_size = info->u.vesa_lfb.rsvd_size;
|
|
+ screen_info->rsvd_pos = info->u.vesa_lfb.rsvd_pos;
|
|
+ if (size >= offsetof(struct dom0_vga_console_info,
|
|
+ u.vesa_lfb.gbl_caps)
|
|
+ + sizeof(info->u.vesa_lfb.gbl_caps))
|
|
+ screen_info->capabilities = info->u.vesa_lfb.gbl_caps;
|
|
+ if (size >= offsetof(struct dom0_vga_console_info,
|
|
+ u.vesa_lfb.mode_attrs)
|
|
+ + sizeof(info->u.vesa_lfb.mode_attrs))
|
|
+ screen_info->vesa_attributes = info->u.vesa_lfb.mode_attrs;
|
|
+ break;
|
|
+ }
|
|
+}
|
|
diff --git a/arch/x86/xen/xen-ops.h b/arch/x86/xen/xen-ops.h
|
|
index 97dfdc8..b095739 100644
|
|
--- a/arch/x86/xen/xen-ops.h
|
|
+++ b/arch/x86/xen/xen-ops.h
|
|
@@ -88,6 +88,17 @@ static inline void xen_uninit_lock_cpu(int cpu)
|
|
}
|
|
#endif
|
|
|
|
+struct dom0_vga_console_info;
|
|
+
|
|
+#ifdef CONFIG_XEN_DOM0
|
|
+void __init xen_init_vga(const struct dom0_vga_console_info *, size_t size);
|
|
+#else
|
|
+static inline void __init xen_init_vga(const struct dom0_vga_console_info *info,
|
|
+ size_t size)
|
|
+{
|
|
+}
|
|
+#endif
|
|
+
|
|
/* Declare an asm function, along with symbols needed to make it
|
|
inlineable */
|
|
#define DECL_ASM(ret, name, ...) \
|
|
diff --git a/crypto/md5.c b/crypto/md5.c
|
|
index 30efc7d..7febeaa 100644
|
|
--- a/crypto/md5.c
|
|
+++ b/crypto/md5.c
|
|
@@ -21,99 +21,9 @@
|
|
#include <linux/module.h>
|
|
#include <linux/string.h>
|
|
#include <linux/types.h>
|
|
+#include <linux/cryptohash.h>
|
|
#include <asm/byteorder.h>
|
|
|
|
-#define F1(x, y, z) (z ^ (x & (y ^ z)))
|
|
-#define F2(x, y, z) F1(z, x, y)
|
|
-#define F3(x, y, z) (x ^ y ^ z)
|
|
-#define F4(x, y, z) (y ^ (x | ~z))
|
|
-
|
|
-#define MD5STEP(f, w, x, y, z, in, s) \
|
|
- (w += f(x, y, z) + in, w = (w<<s | w>>(32-s)) + x)
|
|
-
|
|
-static void md5_transform(u32 *hash, u32 const *in)
|
|
-{
|
|
- u32 a, b, c, d;
|
|
-
|
|
- a = hash[0];
|
|
- b = hash[1];
|
|
- c = hash[2];
|
|
- d = hash[3];
|
|
-
|
|
- MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7);
|
|
- MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12);
|
|
- MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17);
|
|
- MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22);
|
|
- MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7);
|
|
- MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12);
|
|
- MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17);
|
|
- MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22);
|
|
- MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7);
|
|
- MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12);
|
|
- MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
|
|
- MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
|
|
- MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7);
|
|
- MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
|
|
- MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
|
|
- MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
|
|
-
|
|
- MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5);
|
|
- MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9);
|
|
- MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
|
|
- MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);
|
|
- MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5);
|
|
- MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);
|
|
- MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
|
|
- MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);
|
|
- MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5);
|
|
- MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
|
|
- MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14);
|
|
- MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20);
|
|
- MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
|
|
- MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);
|
|
- MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14);
|
|
- MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
|
|
-
|
|
- MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4);
|
|
- MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11);
|
|
- MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
|
|
- MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
|
|
- MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4);
|
|
- MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);
|
|
- MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);
|
|
- MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
|
|
- MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
|
|
- MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11);
|
|
- MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16);
|
|
- MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23);
|
|
- MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4);
|
|
- MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
|
|
- MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
|
|
- MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23);
|
|
-
|
|
- MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6);
|
|
- MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10);
|
|
- MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
|
|
- MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21);
|
|
- MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
|
|
- MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);
|
|
- MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
|
|
- MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21);
|
|
- MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);
|
|
- MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
|
|
- MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15);
|
|
- MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
|
|
- MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6);
|
|
- MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
|
|
- MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);
|
|
- MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21);
|
|
-
|
|
- hash[0] += a;
|
|
- hash[1] += b;
|
|
- hash[2] += c;
|
|
- hash[3] += d;
|
|
-}
|
|
-
|
|
/* XXX: this stuff can be optimized */
|
|
static inline void le32_to_cpu_array(u32 *buf, unsigned int words)
|
|
{
|
|
diff --git a/drivers/char/random.c b/drivers/char/random.c
|
|
index d4ddeba..c35a785 100644
|
|
--- a/drivers/char/random.c
|
|
+++ b/drivers/char/random.c
|
|
@@ -1300,330 +1300,14 @@ ctl_table random_table[] = {
|
|
};
|
|
#endif /* CONFIG_SYSCTL */
|
|
|
|
-/********************************************************************
|
|
- *
|
|
- * Random functions for networking
|
|
- *
|
|
- ********************************************************************/
|
|
-
|
|
-/*
|
|
- * TCP initial sequence number picking. This uses the random number
|
|
- * generator to pick an initial secret value. This value is hashed
|
|
- * along with the TCP endpoint information to provide a unique
|
|
- * starting point for each pair of TCP endpoints. This defeats
|
|
- * attacks which rely on guessing the initial TCP sequence number.
|
|
- * This algorithm was suggested by Steve Bellovin.
|
|
- *
|
|
- * Using a very strong hash was taking an appreciable amount of the total
|
|
- * TCP connection establishment time, so this is a weaker hash,
|
|
- * compensated for by changing the secret periodically.
|
|
- */
|
|
-
|
|
-/* F, G and H are basic MD4 functions: selection, majority, parity */
|
|
-#define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z))))
|
|
-#define G(x, y, z) (((x) & (y)) + (((x) ^ (y)) & (z)))
|
|
-#define H(x, y, z) ((x) ^ (y) ^ (z))
|
|
-
|
|
-/*
|
|
- * The generic round function. The application is so specific that
|
|
- * we don't bother protecting all the arguments with parens, as is generally
|
|
- * good macro practice, in favor of extra legibility.
|
|
- * Rotation is separate from addition to prevent recomputation
|
|
- */
|
|
-#define ROUND(f, a, b, c, d, x, s) \
|
|
- (a += f(b, c, d) + x, a = (a << s) | (a >> (32 - s)))
|
|
-#define K1 0
|
|
-#define K2 013240474631UL
|
|
-#define K3 015666365641UL
|
|
+static u32 random_int_secret[MD5_MESSAGE_BYTES / 4] ____cacheline_aligned;
|
|
|
|
-#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
|
|
-
|
|
-static __u32 twothirdsMD4Transform(__u32 const buf[4], __u32 const in[12])
|
|
+static int __init random_int_secret_init(void)
|
|
{
|
|
- __u32 a = buf[0], b = buf[1], c = buf[2], d = buf[3];
|
|
-
|
|
- /* Round 1 */
|
|
- ROUND(F, a, b, c, d, in[ 0] + K1, 3);
|
|
- ROUND(F, d, a, b, c, in[ 1] + K1, 7);
|
|
- ROUND(F, c, d, a, b, in[ 2] + K1, 11);
|
|
- ROUND(F, b, c, d, a, in[ 3] + K1, 19);
|
|
- ROUND(F, a, b, c, d, in[ 4] + K1, 3);
|
|
- ROUND(F, d, a, b, c, in[ 5] + K1, 7);
|
|
- ROUND(F, c, d, a, b, in[ 6] + K1, 11);
|
|
- ROUND(F, b, c, d, a, in[ 7] + K1, 19);
|
|
- ROUND(F, a, b, c, d, in[ 8] + K1, 3);
|
|
- ROUND(F, d, a, b, c, in[ 9] + K1, 7);
|
|
- ROUND(F, c, d, a, b, in[10] + K1, 11);
|
|
- ROUND(F, b, c, d, a, in[11] + K1, 19);
|
|
-
|
|
- /* Round 2 */
|
|
- ROUND(G, a, b, c, d, in[ 1] + K2, 3);
|
|
- ROUND(G, d, a, b, c, in[ 3] + K2, 5);
|
|
- ROUND(G, c, d, a, b, in[ 5] + K2, 9);
|
|
- ROUND(G, b, c, d, a, in[ 7] + K2, 13);
|
|
- ROUND(G, a, b, c, d, in[ 9] + K2, 3);
|
|
- ROUND(G, d, a, b, c, in[11] + K2, 5);
|
|
- ROUND(G, c, d, a, b, in[ 0] + K2, 9);
|
|
- ROUND(G, b, c, d, a, in[ 2] + K2, 13);
|
|
- ROUND(G, a, b, c, d, in[ 4] + K2, 3);
|
|
- ROUND(G, d, a, b, c, in[ 6] + K2, 5);
|
|
- ROUND(G, c, d, a, b, in[ 8] + K2, 9);
|
|
- ROUND(G, b, c, d, a, in[10] + K2, 13);
|
|
-
|
|
- /* Round 3 */
|
|
- ROUND(H, a, b, c, d, in[ 3] + K3, 3);
|
|
- ROUND(H, d, a, b, c, in[ 7] + K3, 9);
|
|
- ROUND(H, c, d, a, b, in[11] + K3, 11);
|
|
- ROUND(H, b, c, d, a, in[ 2] + K3, 15);
|
|
- ROUND(H, a, b, c, d, in[ 6] + K3, 3);
|
|
- ROUND(H, d, a, b, c, in[10] + K3, 9);
|
|
- ROUND(H, c, d, a, b, in[ 1] + K3, 11);
|
|
- ROUND(H, b, c, d, a, in[ 5] + K3, 15);
|
|
- ROUND(H, a, b, c, d, in[ 9] + K3, 3);
|
|
- ROUND(H, d, a, b, c, in[ 0] + K3, 9);
|
|
- ROUND(H, c, d, a, b, in[ 4] + K3, 11);
|
|
- ROUND(H, b, c, d, a, in[ 8] + K3, 15);
|
|
-
|
|
- return buf[1] + b; /* "most hashed" word */
|
|
- /* Alternative: return sum of all words? */
|
|
-}
|
|
-#endif
|
|
-
|
|
-#undef ROUND
|
|
-#undef F
|
|
-#undef G
|
|
-#undef H
|
|
-#undef K1
|
|
-#undef K2
|
|
-#undef K3
|
|
-
|
|
-/* This should not be decreased so low that ISNs wrap too fast. */
|
|
-#define REKEY_INTERVAL (300 * HZ)
|
|
-/*
|
|
- * Bit layout of the tcp sequence numbers (before adding current time):
|
|
- * bit 24-31: increased after every key exchange
|
|
- * bit 0-23: hash(source,dest)
|
|
- *
|
|
- * The implementation is similar to the algorithm described
|
|
- * in the Appendix of RFC 1185, except that
|
|
- * - it uses a 1 MHz clock instead of a 250 kHz clock
|
|
- * - it performs a rekey every 5 minutes, which is equivalent
|
|
- * to a (source,dest) tulple dependent forward jump of the
|
|
- * clock by 0..2^(HASH_BITS+1)
|
|
- *
|
|
- * Thus the average ISN wraparound time is 68 minutes instead of
|
|
- * 4.55 hours.
|
|
- *
|
|
- * SMP cleanup and lock avoidance with poor man's RCU.
|
|
- * Manfred Spraul <manfred@colorfullife.com>
|
|
- *
|
|
- */
|
|
-#define COUNT_BITS 8
|
|
-#define COUNT_MASK ((1 << COUNT_BITS) - 1)
|
|
-#define HASH_BITS 24
|
|
-#define HASH_MASK ((1 << HASH_BITS) - 1)
|
|
-
|
|
-static struct keydata {
|
|
- __u32 count; /* already shifted to the final position */
|
|
- __u32 secret[12];
|
|
-} ____cacheline_aligned ip_keydata[2];
|
|
-
|
|
-static unsigned int ip_cnt;
|
|
-
|
|
-static void rekey_seq_generator(struct work_struct *work);
|
|
-
|
|
-static DECLARE_DELAYED_WORK(rekey_work, rekey_seq_generator);
|
|
-
|
|
-/*
|
|
- * Lock avoidance:
|
|
- * The ISN generation runs lockless - it's just a hash over random data.
|
|
- * State changes happen every 5 minutes when the random key is replaced.
|
|
- * Synchronization is performed by having two copies of the hash function
|
|
- * state and rekey_seq_generator always updates the inactive copy.
|
|
- * The copy is then activated by updating ip_cnt.
|
|
- * The implementation breaks down if someone blocks the thread
|
|
- * that processes SYN requests for more than 5 minutes. Should never
|
|
- * happen, and even if that happens only a not perfectly compliant
|
|
- * ISN is generated, nothing fatal.
|
|
- */
|
|
-static void rekey_seq_generator(struct work_struct *work)
|
|
-{
|
|
- struct keydata *keyptr = &ip_keydata[1 ^ (ip_cnt & 1)];
|
|
-
|
|
- get_random_bytes(keyptr->secret, sizeof(keyptr->secret));
|
|
- keyptr->count = (ip_cnt & COUNT_MASK) << HASH_BITS;
|
|
- smp_wmb();
|
|
- ip_cnt++;
|
|
- schedule_delayed_work(&rekey_work,
|
|
- round_jiffies_relative(REKEY_INTERVAL));
|
|
-}
|
|
-
|
|
-static inline struct keydata *get_keyptr(void)
|
|
-{
|
|
- struct keydata *keyptr = &ip_keydata[ip_cnt & 1];
|
|
-
|
|
- smp_rmb();
|
|
-
|
|
- return keyptr;
|
|
-}
|
|
-
|
|
-static __init int seqgen_init(void)
|
|
-{
|
|
- rekey_seq_generator(NULL);
|
|
+ get_random_bytes(random_int_secret, sizeof(random_int_secret));
|
|
return 0;
|
|
}
|
|
-late_initcall(seqgen_init);
|
|
-
|
|
-#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
|
|
-__u32 secure_tcpv6_sequence_number(__be32 *saddr, __be32 *daddr,
|
|
- __be16 sport, __be16 dport)
|
|
-{
|
|
- __u32 seq;
|
|
- __u32 hash[12];
|
|
- struct keydata *keyptr = get_keyptr();
|
|
-
|
|
- /* The procedure is the same as for IPv4, but addresses are longer.
|
|
- * Thus we must use twothirdsMD4Transform.
|
|
- */
|
|
-
|
|
- memcpy(hash, saddr, 16);
|
|
- hash[4] = ((__force u16)sport << 16) + (__force u16)dport;
|
|
- memcpy(&hash[5], keyptr->secret, sizeof(__u32) * 7);
|
|
-
|
|
- seq = twothirdsMD4Transform((const __u32 *)daddr, hash) & HASH_MASK;
|
|
- seq += keyptr->count;
|
|
-
|
|
- seq += ktime_to_ns(ktime_get_real());
|
|
-
|
|
- return seq;
|
|
-}
|
|
-EXPORT_SYMBOL(secure_tcpv6_sequence_number);
|
|
-#endif
|
|
-
|
|
-/* The code below is shamelessly stolen from secure_tcp_sequence_number().
|
|
- * All blames to Andrey V. Savochkin <saw@msu.ru>.
|
|
- */
|
|
-__u32 secure_ip_id(__be32 daddr)
|
|
-{
|
|
- struct keydata *keyptr;
|
|
- __u32 hash[4];
|
|
-
|
|
- keyptr = get_keyptr();
|
|
-
|
|
- /*
|
|
- * Pick a unique starting offset for each IP destination.
|
|
- * The dest ip address is placed in the starting vector,
|
|
- * which is then hashed with random data.
|
|
- */
|
|
- hash[0] = (__force __u32)daddr;
|
|
- hash[1] = keyptr->secret[9];
|
|
- hash[2] = keyptr->secret[10];
|
|
- hash[3] = keyptr->secret[11];
|
|
-
|
|
- return half_md4_transform(hash, keyptr->secret);
|
|
-}
|
|
-
|
|
-#ifdef CONFIG_INET
|
|
-
|
|
-__u32 secure_tcp_sequence_number(__be32 saddr, __be32 daddr,
|
|
- __be16 sport, __be16 dport)
|
|
-{
|
|
- __u32 seq;
|
|
- __u32 hash[4];
|
|
- struct keydata *keyptr = get_keyptr();
|
|
-
|
|
- /*
|
|
- * Pick a unique starting offset for each TCP connection endpoints
|
|
- * (saddr, daddr, sport, dport).
|
|
- * Note that the words are placed into the starting vector, which is
|
|
- * then mixed with a partial MD4 over random data.
|
|
- */
|
|
- hash[0] = (__force u32)saddr;
|
|
- hash[1] = (__force u32)daddr;
|
|
- hash[2] = ((__force u16)sport << 16) + (__force u16)dport;
|
|
- hash[3] = keyptr->secret[11];
|
|
-
|
|
- seq = half_md4_transform(hash, keyptr->secret) & HASH_MASK;
|
|
- seq += keyptr->count;
|
|
- /*
|
|
- * As close as possible to RFC 793, which
|
|
- * suggests using a 250 kHz clock.
|
|
- * Further reading shows this assumes 2 Mb/s networks.
|
|
- * For 10 Mb/s Ethernet, a 1 MHz clock is appropriate.
|
|
- * For 10 Gb/s Ethernet, a 1 GHz clock should be ok, but
|
|
- * we also need to limit the resolution so that the u32 seq
|
|
- * overlaps less than one time per MSL (2 minutes).
|
|
- * Choosing a clock of 64 ns period is OK. (period of 274 s)
|
|
- */
|
|
- seq += ktime_to_ns(ktime_get_real()) >> 6;
|
|
-
|
|
- return seq;
|
|
-}
|
|
-
|
|
-/* Generate secure starting point for ephemeral IPV4 transport port search */
|
|
-u32 secure_ipv4_port_ephemeral(__be32 saddr, __be32 daddr, __be16 dport)
|
|
-{
|
|
- struct keydata *keyptr = get_keyptr();
|
|
- u32 hash[4];
|
|
-
|
|
- /*
|
|
- * Pick a unique starting offset for each ephemeral port search
|
|
- * (saddr, daddr, dport) and 48bits of random data.
|
|
- */
|
|
- hash[0] = (__force u32)saddr;
|
|
- hash[1] = (__force u32)daddr;
|
|
- hash[2] = (__force u32)dport ^ keyptr->secret[10];
|
|
- hash[3] = keyptr->secret[11];
|
|
-
|
|
- return half_md4_transform(hash, keyptr->secret);
|
|
-}
|
|
-EXPORT_SYMBOL_GPL(secure_ipv4_port_ephemeral);
|
|
-
|
|
-#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
|
|
-u32 secure_ipv6_port_ephemeral(const __be32 *saddr, const __be32 *daddr,
|
|
- __be16 dport)
|
|
-{
|
|
- struct keydata *keyptr = get_keyptr();
|
|
- u32 hash[12];
|
|
-
|
|
- memcpy(hash, saddr, 16);
|
|
- hash[4] = (__force u32)dport;
|
|
- memcpy(&hash[5], keyptr->secret, sizeof(__u32) * 7);
|
|
-
|
|
- return twothirdsMD4Transform((const __u32 *)daddr, hash);
|
|
-}
|
|
-#endif
|
|
-
|
|
-#if defined(CONFIG_IP_DCCP) || defined(CONFIG_IP_DCCP_MODULE)
|
|
-/* Similar to secure_tcp_sequence_number but generate a 48 bit value
|
|
- * bit's 32-47 increase every key exchange
|
|
- * 0-31 hash(source, dest)
|
|
- */
|
|
-u64 secure_dccp_sequence_number(__be32 saddr, __be32 daddr,
|
|
- __be16 sport, __be16 dport)
|
|
-{
|
|
- u64 seq;
|
|
- __u32 hash[4];
|
|
- struct keydata *keyptr = get_keyptr();
|
|
-
|
|
- hash[0] = (__force u32)saddr;
|
|
- hash[1] = (__force u32)daddr;
|
|
- hash[2] = ((__force u16)sport << 16) + (__force u16)dport;
|
|
- hash[3] = keyptr->secret[11];
|
|
-
|
|
- seq = half_md4_transform(hash, keyptr->secret);
|
|
- seq |= ((u64)keyptr->count) << (32 - HASH_BITS);
|
|
-
|
|
- seq += ktime_to_ns(ktime_get_real());
|
|
- seq &= (1ull << 48) - 1;
|
|
-
|
|
- return seq;
|
|
-}
|
|
-EXPORT_SYMBOL(secure_dccp_sequence_number);
|
|
-#endif
|
|
-
|
|
-#endif /* CONFIG_INET */
|
|
-
|
|
+late_initcall(random_int_secret_init);
|
|
|
|
/*
|
|
* Get a random word for internal kernel use only. Similar to urandom but
|
|
@@ -1631,17 +1315,15 @@ EXPORT_SYMBOL(secure_dccp_sequence_number);
|
|
* value is not cryptographically secure but for several uses the cost of
|
|
* depleting entropy is too high
|
|
*/
|
|
-DEFINE_PER_CPU(__u32 [4], get_random_int_hash);
|
|
+DEFINE_PER_CPU(__u32 [MD5_DIGEST_WORDS], get_random_int_hash);
|
|
unsigned int get_random_int(void)
|
|
{
|
|
- struct keydata *keyptr;
|
|
__u32 *hash = get_cpu_var(get_random_int_hash);
|
|
- int ret;
|
|
+ unsigned int ret;
|
|
|
|
- keyptr = get_keyptr();
|
|
hash[0] += current->pid + jiffies + get_cycles();
|
|
-
|
|
- ret = half_md4_transform(hash, keyptr->secret);
|
|
+ md5_transform(hash, random_int_secret);
|
|
+ ret = hash[0];
|
|
put_cpu_var(get_random_int_hash);
|
|
|
|
return ret;
|
|
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
|
|
index 0929219..1bbb85b 100644
|
|
--- a/drivers/gpu/drm/drm_edid.c
|
|
+++ b/drivers/gpu/drm/drm_edid.c
|
|
@@ -127,6 +127,23 @@ static const u8 edid_header[] = {
|
|
0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00
|
|
};
|
|
|
|
+ /*
|
|
+ * Sanity check the header of the base EDID block. Return 8 if the header
|
|
+ * is perfect, down to 0 if it's totally wrong.
|
|
+ */
|
|
+int drm_edid_header_is_valid(const u8 *raw_edid)
|
|
+{
|
|
+ int i, score = 0;
|
|
+
|
|
+ for (i = 0; i < sizeof(edid_header); i++)
|
|
+ if (raw_edid[i] == edid_header[i])
|
|
+ score++;
|
|
+
|
|
+ return score;
|
|
+}
|
|
+EXPORT_SYMBOL(drm_edid_header_is_valid);
|
|
+
|
|
+
|
|
/*
|
|
* Sanity check the EDID block (base or extension). Return 0 if the block
|
|
* doesn't check out, or 1 if it's valid.
|
|
@@ -139,12 +156,7 @@ drm_edid_block_valid(u8 *raw_edid)
|
|
struct edid *edid = (struct edid *)raw_edid;
|
|
|
|
if (raw_edid[0] == 0x00) {
|
|
- int score = 0;
|
|
-
|
|
- for (i = 0; i < sizeof(edid_header); i++)
|
|
- if (raw_edid[i] == edid_header[i])
|
|
- score++;
|
|
-
|
|
+ int score = drm_edid_header_is_valid(raw_edid);
|
|
if (score == 8) ;
|
|
else if (score >= 6) {
|
|
DRM_DEBUG("Fixing EDID header, your hardware may be failing\n");
|
|
diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
|
|
index 296fbd6..7eef6e1 100644
|
|
--- a/drivers/gpu/drm/i915/i915_dma.c
|
|
+++ b/drivers/gpu/drm/i915/i915_dma.c
|
|
@@ -61,7 +61,6 @@ static void i915_write_hws_pga(struct drm_device *dev)
|
|
static int i915_init_phys_hws(struct drm_device *dev)
|
|
{
|
|
drm_i915_private_t *dev_priv = dev->dev_private;
|
|
- struct intel_ring_buffer *ring = LP_RING(dev_priv);
|
|
|
|
/* Program Hardware Status Page */
|
|
dev_priv->status_page_dmah =
|
|
@@ -71,10 +70,9 @@ static int i915_init_phys_hws(struct drm_device *dev)
|
|
DRM_ERROR("Can not allocate hardware status page\n");
|
|
return -ENOMEM;
|
|
}
|
|
- ring->status_page.page_addr =
|
|
- (void __force __iomem *)dev_priv->status_page_dmah->vaddr;
|
|
|
|
- memset_io(ring->status_page.page_addr, 0, PAGE_SIZE);
|
|
+ memset_io((void __force __iomem *)dev_priv->status_page_dmah->vaddr,
|
|
+ 0, PAGE_SIZE);
|
|
|
|
i915_write_hws_pga(dev);
|
|
|
|
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
|
|
index 3b03f85..9b1d669 100644
|
|
--- a/drivers/gpu/drm/i915/i915_irq.c
|
|
+++ b/drivers/gpu/drm/i915/i915_irq.c
|
|
@@ -306,12 +306,15 @@ static void i915_hotplug_work_func(struct work_struct *work)
|
|
struct drm_mode_config *mode_config = &dev->mode_config;
|
|
struct intel_encoder *encoder;
|
|
|
|
+ mutex_lock(&mode_config->mutex);
|
|
DRM_DEBUG_KMS("running encoder hotplug functions\n");
|
|
|
|
list_for_each_entry(encoder, &mode_config->encoder_list, base.head)
|
|
if (encoder->hot_plug)
|
|
encoder->hot_plug(encoder);
|
|
|
|
+ mutex_unlock(&mode_config->mutex);
|
|
+
|
|
/* Just fire off a uevent and let userspace tell us what to do */
|
|
drm_helper_hpd_irq_event(dev);
|
|
}
|
|
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
|
|
index 0f1c799..5609c06 100644
|
|
--- a/drivers/gpu/drm/i915/intel_display.c
|
|
+++ b/drivers/gpu/drm/i915/intel_display.c
|
|
@@ -2699,14 +2699,18 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc)
|
|
I915_WRITE(PF_WIN_SZ(pipe), dev_priv->pch_pf_size);
|
|
}
|
|
|
|
+ /*
|
|
+ * On ILK+ LUT must be loaded before the pipe is running but with
|
|
+ * clocks enabled
|
|
+ */
|
|
+ intel_crtc_load_lut(crtc);
|
|
+
|
|
intel_enable_pipe(dev_priv, pipe, is_pch_port);
|
|
intel_enable_plane(dev_priv, plane, pipe);
|
|
|
|
if (is_pch_port)
|
|
ironlake_pch_enable(crtc);
|
|
|
|
- intel_crtc_load_lut(crtc);
|
|
-
|
|
mutex_lock(&dev->struct_mutex);
|
|
intel_update_fbc(dev);
|
|
mutex_unlock(&dev->struct_mutex);
|
|
diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c
|
|
index a06ff07..05f500c 100644
|
|
--- a/drivers/gpu/drm/i915/intel_panel.c
|
|
+++ b/drivers/gpu/drm/i915/intel_panel.c
|
|
@@ -83,11 +83,15 @@ intel_pch_panel_fitting(struct drm_device *dev,
|
|
u32 scaled_height = mode->hdisplay * adjusted_mode->vdisplay;
|
|
if (scaled_width > scaled_height) { /* pillar */
|
|
width = scaled_height / mode->vdisplay;
|
|
+ if (width & 1)
|
|
+ width++;
|
|
x = (adjusted_mode->hdisplay - width + 1) / 2;
|
|
y = 0;
|
|
height = adjusted_mode->vdisplay;
|
|
} else if (scaled_width < scaled_height) { /* letter */
|
|
height = scaled_width / mode->hdisplay;
|
|
+ if (height & 1)
|
|
+ height++;
|
|
y = (adjusted_mode->vdisplay - height + 1) / 2;
|
|
x = 0;
|
|
width = adjusted_mode->hdisplay;
|
|
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c
|
|
index 95c4b14..1f61fc7 100644
|
|
--- a/drivers/gpu/drm/i915/intel_ringbuffer.c
|
|
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.c
|
|
@@ -1319,6 +1319,9 @@ int intel_render_ring_init_dri(struct drm_device *dev, u64 start, u32 size)
|
|
ring->get_seqno = pc_render_get_seqno;
|
|
}
|
|
|
|
+ if (!I915_NEED_GFX_HWS(dev))
|
|
+ ring->status_page.page_addr = dev_priv->status_page_dmah->vaddr;
|
|
+
|
|
ring->dev = dev;
|
|
INIT_LIST_HEAD(&ring->active_list);
|
|
INIT_LIST_HEAD(&ring->request_list);
|
|
diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c
|
|
index 9792d4f..6d6b5f1 100644
|
|
--- a/drivers/gpu/drm/radeon/radeon_connectors.c
|
|
+++ b/drivers/gpu/drm/radeon/radeon_connectors.c
|
|
@@ -430,6 +430,45 @@ int radeon_connector_set_property(struct drm_connector *connector, struct drm_pr
|
|
return 0;
|
|
}
|
|
|
|
+/*
|
|
+ * Some integrated ATI Radeon chipset implementations (e. g.
|
|
+ * Asus M2A-VM HDMI) may indicate the availability of a DDC,
|
|
+ * even when there's no monitor connected. For these connectors
|
|
+ * following DDC probe extension will be applied: check also for the
|
|
+ * availability of EDID with at least a correct EDID header. Only then,
|
|
+ * DDC is assumed to be available. This prevents drm_get_edid() and
|
|
+ * drm_edid_block_valid() from periodically dumping data and kernel
|
|
+ * errors into the logs and onto the terminal.
|
|
+ */
|
|
+static bool radeon_connector_needs_extended_probe(struct radeon_device *dev,
|
|
+ uint32_t supported_device,
|
|
+ int connector_type)
|
|
+{
|
|
+ /* Asus M2A-VM HDMI board sends data to i2c bus even,
|
|
+ * if HDMI add-on card is not plugged in or HDMI is disabled in
|
|
+ * BIOS. Valid DDC can only be assumed, if also a valid EDID header
|
|
+ * can be retrieved via i2c bus during DDC probe */
|
|
+ if ((dev->pdev->device == 0x791e) &&
|
|
+ (dev->pdev->subsystem_vendor == 0x1043) &&
|
|
+ (dev->pdev->subsystem_device == 0x826d)) {
|
|
+ if ((connector_type == DRM_MODE_CONNECTOR_HDMIA) &&
|
|
+ (supported_device == ATOM_DEVICE_DFP2_SUPPORT))
|
|
+ return true;
|
|
+ }
|
|
+ /* ECS A740GM-M with ATI RADEON 2100 sends data to i2c bus
|
|
+ * for a DVI connector that is not implemented */
|
|
+ if ((dev->pdev->device == 0x796e) &&
|
|
+ (dev->pdev->subsystem_vendor == 0x1019) &&
|
|
+ (dev->pdev->subsystem_device == 0x2615)) {
|
|
+ if ((connector_type == DRM_MODE_CONNECTOR_DVID) &&
|
|
+ (supported_device == ATOM_DEVICE_DFP2_SUPPORT))
|
|
+ return true;
|
|
+ }
|
|
+
|
|
+ /* Default: no EDID header probe required for DDC probing */
|
|
+ return false;
|
|
+}
|
|
+
|
|
static void radeon_fixup_lvds_native_mode(struct drm_encoder *encoder,
|
|
struct drm_connector *connector)
|
|
{
|
|
@@ -661,7 +700,8 @@ radeon_vga_detect(struct drm_connector *connector, bool force)
|
|
ret = connector_status_disconnected;
|
|
|
|
if (radeon_connector->ddc_bus)
|
|
- dret = radeon_ddc_probe(radeon_connector);
|
|
+ dret = radeon_ddc_probe(radeon_connector,
|
|
+ radeon_connector->requires_extended_probe);
|
|
if (dret) {
|
|
if (radeon_connector->edid) {
|
|
kfree(radeon_connector->edid);
|
|
@@ -833,7 +873,8 @@ radeon_dvi_detect(struct drm_connector *connector, bool force)
|
|
bool dret = false;
|
|
|
|
if (radeon_connector->ddc_bus)
|
|
- dret = radeon_ddc_probe(radeon_connector);
|
|
+ dret = radeon_ddc_probe(radeon_connector,
|
|
+ radeon_connector->requires_extended_probe);
|
|
if (dret) {
|
|
if (radeon_connector->edid) {
|
|
kfree(radeon_connector->edid);
|
|
@@ -1251,7 +1292,8 @@ radeon_dp_detect(struct drm_connector *connector, bool force)
|
|
if (radeon_dp_getdpcd(radeon_connector))
|
|
ret = connector_status_connected;
|
|
} else {
|
|
- if (radeon_ddc_probe(radeon_connector))
|
|
+ if (radeon_ddc_probe(radeon_connector,
|
|
+ radeon_connector->requires_extended_probe))
|
|
ret = connector_status_connected;
|
|
}
|
|
}
|
|
@@ -1406,6 +1448,9 @@ radeon_add_atom_connector(struct drm_device *dev,
|
|
radeon_connector->shared_ddc = shared_ddc;
|
|
radeon_connector->connector_object_id = connector_object_id;
|
|
radeon_connector->hpd = *hpd;
|
|
+ radeon_connector->requires_extended_probe =
|
|
+ radeon_connector_needs_extended_probe(rdev, supported_device,
|
|
+ connector_type);
|
|
radeon_connector->router = *router;
|
|
if (router->ddc_valid || router->cd_valid) {
|
|
radeon_connector->router_bus = radeon_i2c_lookup(rdev, &router->i2c_info);
|
|
@@ -1752,6 +1797,9 @@ radeon_add_legacy_connector(struct drm_device *dev,
|
|
radeon_connector->devices = supported_device;
|
|
radeon_connector->connector_object_id = connector_object_id;
|
|
radeon_connector->hpd = *hpd;
|
|
+ radeon_connector->requires_extended_probe =
|
|
+ radeon_connector_needs_extended_probe(rdev, supported_device,
|
|
+ connector_type);
|
|
switch (connector_type) {
|
|
case DRM_MODE_CONNECTOR_VGA:
|
|
drm_connector_init(dev, &radeon_connector->base, &radeon_vga_connector_funcs, connector_type);
|
|
diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c
|
|
index 7cfaa7e..440e6ec 100644
|
|
--- a/drivers/gpu/drm/radeon/radeon_device.c
|
|
+++ b/drivers/gpu/drm/radeon/radeon_device.c
|
|
@@ -704,8 +704,9 @@ int radeon_device_init(struct radeon_device *rdev,
|
|
rdev->gpu_lockup = false;
|
|
rdev->accel_working = false;
|
|
|
|
- DRM_INFO("initializing kernel modesetting (%s 0x%04X:0x%04X).\n",
|
|
- radeon_family_name[rdev->family], pdev->vendor, pdev->device);
|
|
+ DRM_INFO("initializing kernel modesetting (%s 0x%04X:0x%04X 0x%04X:0x%04X).\n",
|
|
+ radeon_family_name[rdev->family], pdev->vendor, pdev->device,
|
|
+ pdev->subsystem_vendor, pdev->subsystem_device);
|
|
|
|
/* mutex initialization are all done here so we
|
|
* can recall function without having locking issues */
|
|
diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c
|
|
index 292f73f..ed085ce 100644
|
|
--- a/drivers/gpu/drm/radeon/radeon_display.c
|
|
+++ b/drivers/gpu/drm/radeon/radeon_display.c
|
|
@@ -777,8 +777,17 @@ static int radeon_ddc_dump(struct drm_connector *connector)
|
|
if (!radeon_connector->ddc_bus)
|
|
return -1;
|
|
edid = drm_get_edid(connector, &radeon_connector->ddc_bus->adapter);
|
|
+ /* Log EDID retrieval status here. In particular with regard to
|
|
+ * connectors with requires_extended_probe flag set, that will prevent
|
|
+ * function radeon_dvi_detect() to fetch EDID on this connector,
|
|
+ * as long as there is no valid EDID header found */
|
|
if (edid) {
|
|
+ DRM_INFO("Radeon display connector %s: Found valid EDID",
|
|
+ drm_get_connector_name(connector));
|
|
kfree(edid);
|
|
+ } else {
|
|
+ DRM_INFO("Radeon display connector %s: No monitor connected or invalid EDID",
|
|
+ drm_get_connector_name(connector));
|
|
}
|
|
return ret;
|
|
}
|
|
diff --git a/drivers/gpu/drm/radeon/radeon_i2c.c b/drivers/gpu/drm/radeon/radeon_i2c.c
|
|
index 781196d..6c111c1 100644
|
|
--- a/drivers/gpu/drm/radeon/radeon_i2c.c
|
|
+++ b/drivers/gpu/drm/radeon/radeon_i2c.c
|
|
@@ -32,17 +32,17 @@
|
|
* radeon_ddc_probe
|
|
*
|
|
*/
|
|
-bool radeon_ddc_probe(struct radeon_connector *radeon_connector)
|
|
+bool radeon_ddc_probe(struct radeon_connector *radeon_connector, bool requires_extended_probe)
|
|
{
|
|
- u8 out_buf[] = { 0x0, 0x0};
|
|
- u8 buf[2];
|
|
+ u8 out = 0x0;
|
|
+ u8 buf[8];
|
|
int ret;
|
|
struct i2c_msg msgs[] = {
|
|
{
|
|
.addr = 0x50,
|
|
.flags = 0,
|
|
.len = 1,
|
|
- .buf = out_buf,
|
|
+ .buf = &out,
|
|
},
|
|
{
|
|
.addr = 0x50,
|
|
@@ -52,15 +52,31 @@ bool radeon_ddc_probe(struct radeon_connector *radeon_connector)
|
|
}
|
|
};
|
|
|
|
+ /* Read 8 bytes from i2c for extended probe of EDID header */
|
|
+ if (requires_extended_probe)
|
|
+ msgs[1].len = 8;
|
|
+
|
|
/* on hw with routers, select right port */
|
|
if (radeon_connector->router.ddc_valid)
|
|
radeon_router_select_ddc_port(radeon_connector);
|
|
|
|
ret = i2c_transfer(&radeon_connector->ddc_bus->adapter, msgs, 2);
|
|
- if (ret == 2)
|
|
- return true;
|
|
-
|
|
- return false;
|
|
+ if (ret != 2)
|
|
+ /* Couldn't find an accessible DDC on this connector */
|
|
+ return false;
|
|
+ if (requires_extended_probe) {
|
|
+ /* Probe also for valid EDID header
|
|
+ * EDID header starts with:
|
|
+ * 0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00.
|
|
+ * Only the first 6 bytes must be valid as
|
|
+ * drm_edid_block_valid() can fix the last 2 bytes */
|
|
+ if (drm_edid_header_is_valid(buf) < 6) {
|
|
+ /* Couldn't find an accessible EDID on this
|
|
+ * connector */
|
|
+ return false;
|
|
+ }
|
|
+ }
|
|
+ return true;
|
|
}
|
|
|
|
/* bit banging i2c */
|
|
diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h
|
|
index 6df4e3c..d09031c 100644
|
|
--- a/drivers/gpu/drm/radeon/radeon_mode.h
|
|
+++ b/drivers/gpu/drm/radeon/radeon_mode.h
|
|
@@ -438,6 +438,9 @@ struct radeon_connector {
|
|
struct radeon_i2c_chan *ddc_bus;
|
|
/* some systems have an hdmi and vga port with a shared ddc line */
|
|
bool shared_ddc;
|
|
+ /* for some Radeon chip families we apply an additional EDID header
|
|
+ check as part of the DDC probe */
|
|
+ bool requires_extended_probe;
|
|
bool use_digital;
|
|
/* we need to mind the EDID between detect
|
|
and get modes due to analog/digital/tvencoder */
|
|
@@ -514,7 +517,8 @@ extern void radeon_i2c_put_byte(struct radeon_i2c_chan *i2c,
|
|
u8 val);
|
|
extern void radeon_router_select_ddc_port(struct radeon_connector *radeon_connector);
|
|
extern void radeon_router_select_cd_port(struct radeon_connector *radeon_connector);
|
|
-extern bool radeon_ddc_probe(struct radeon_connector *radeon_connector);
|
|
+extern bool radeon_ddc_probe(struct radeon_connector *radeon_connector,
|
|
+ bool requires_extended_probe);
|
|
extern int radeon_ddc_get_modes(struct radeon_connector *radeon_connector);
|
|
|
|
extern struct drm_encoder *radeon_best_encoder(struct drm_connector *connector);
|
|
diff --git a/drivers/isdn/i4l/isdn_net.c b/drivers/isdn/i4l/isdn_net.c
|
|
index 9798811..b145b5a 100644
|
|
--- a/drivers/isdn/i4l/isdn_net.c
|
|
+++ b/drivers/isdn/i4l/isdn_net.c
|
|
@@ -2531,6 +2531,9 @@ static void _isdn_setup(struct net_device *dev)
|
|
|
|
/* Setup the generic properties */
|
|
dev->flags = IFF_NOARP|IFF_POINTOPOINT;
|
|
+
|
|
+ /* isdn prepends a header in the tx path, can't share skbs */
|
|
+ dev->priv_flags &= ~IFF_TX_SKB_SHARING;
|
|
dev->header_ops = NULL;
|
|
dev->netdev_ops = &isdn_netdev_ops;
|
|
|
|
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
|
|
index 776a478..d5ce011 100644
|
|
--- a/drivers/net/Makefile
|
|
+++ b/drivers/net/Makefile
|
|
@@ -283,6 +283,7 @@ obj-$(CONFIG_USB_HSO) += usb/
|
|
obj-$(CONFIG_USB_USBNET) += usb/
|
|
obj-$(CONFIG_USB_ZD1201) += usb/
|
|
obj-$(CONFIG_USB_IPHETH) += usb/
|
|
+obj-$(CONFIG_USB_CDC_PHONET) += usb/
|
|
|
|
obj-$(CONFIG_WLAN) += wireless/
|
|
obj-$(CONFIG_NET_TULIP) += tulip/
|
|
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
|
|
index 63c22b0..9ea2f21 100644
|
|
--- a/drivers/net/bonding/bond_main.c
|
|
+++ b/drivers/net/bonding/bond_main.c
|
|
@@ -1625,8 +1625,10 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
|
|
|
|
if (slave_dev->type != ARPHRD_ETHER)
|
|
bond_setup_by_slave(bond_dev, slave_dev);
|
|
- else
|
|
+ else {
|
|
ether_setup(bond_dev);
|
|
+ bond_dev->priv_flags &= ~IFF_TX_SKB_SHARING;
|
|
+ }
|
|
|
|
netdev_bonding_change(bond_dev,
|
|
NETDEV_POST_TYPE_CHANGE);
|
|
@@ -4398,7 +4400,7 @@ static void bond_setup(struct net_device *bond_dev)
|
|
bond_dev->tx_queue_len = 0;
|
|
bond_dev->flags |= IFF_MASTER|IFF_MULTICAST;
|
|
bond_dev->priv_flags |= IFF_BONDING;
|
|
- bond_dev->priv_flags &= ~IFF_XMIT_DST_RELEASE;
|
|
+ bond_dev->priv_flags &= ~(IFF_XMIT_DST_RELEASE | IFF_TX_SKB_SHARING);
|
|
|
|
/* At first, we block adding VLANs. That's the only way to
|
|
* prevent problems that occur when adding VLANs over an
|
|
diff --git a/drivers/net/bonding/bond_sysfs.c b/drivers/net/bonding/bond_sysfs.c
|
|
index 88fcb25..0624610 100644
|
|
--- a/drivers/net/bonding/bond_sysfs.c
|
|
+++ b/drivers/net/bonding/bond_sysfs.c
|
|
@@ -992,6 +992,7 @@ static ssize_t bonding_store_primary(struct device *d,
|
|
int i;
|
|
struct slave *slave;
|
|
struct bonding *bond = to_bond(d);
|
|
+ char ifname[IFNAMSIZ];
|
|
|
|
if (!rtnl_trylock())
|
|
return restart_syscall();
|
|
@@ -1002,32 +1003,33 @@ static ssize_t bonding_store_primary(struct device *d,
|
|
if (!USES_PRIMARY(bond->params.mode)) {
|
|
pr_info("%s: Unable to set primary slave; %s is in mode %d\n",
|
|
bond->dev->name, bond->dev->name, bond->params.mode);
|
|
- } else {
|
|
- bond_for_each_slave(bond, slave, i) {
|
|
- if (strnicmp
|
|
- (slave->dev->name, buf,
|
|
- strlen(slave->dev->name)) == 0) {
|
|
- pr_info("%s: Setting %s as primary slave.\n",
|
|
- bond->dev->name, slave->dev->name);
|
|
- bond->primary_slave = slave;
|
|
- strcpy(bond->params.primary, slave->dev->name);
|
|
- bond_select_active_slave(bond);
|
|
- goto out;
|
|
- }
|
|
- }
|
|
+ goto out;
|
|
+ }
|
|
|
|
- /* if we got here, then we didn't match the name of any slave */
|
|
+ sscanf(buf, "%16s", ifname); /* IFNAMSIZ */
|
|
|
|
- if (strlen(buf) == 0 || buf[0] == '\n') {
|
|
- pr_info("%s: Setting primary slave to None.\n",
|
|
- bond->dev->name);
|
|
- bond->primary_slave = NULL;
|
|
- bond_select_active_slave(bond);
|
|
- } else {
|
|
- pr_info("%s: Unable to set %.*s as primary slave as it is not a slave.\n",
|
|
- bond->dev->name, (int)strlen(buf) - 1, buf);
|
|
+ /* check to see if we are clearing primary */
|
|
+ if (!strlen(ifname) || buf[0] == '\n') {
|
|
+ pr_info("%s: Setting primary slave to None.\n",
|
|
+ bond->dev->name);
|
|
+ bond->primary_slave = NULL;
|
|
+ bond_select_active_slave(bond);
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ bond_for_each_slave(bond, slave, i) {
|
|
+ if (strncmp(slave->dev->name, ifname, IFNAMSIZ) == 0) {
|
|
+ pr_info("%s: Setting %s as primary slave.\n",
|
|
+ bond->dev->name, slave->dev->name);
|
|
+ bond->primary_slave = slave;
|
|
+ strcpy(bond->params.primary, slave->dev->name);
|
|
+ bond_select_active_slave(bond);
|
|
+ goto out;
|
|
}
|
|
}
|
|
+
|
|
+ pr_info("%s: Unable to set %.*s as primary slave.\n",
|
|
+ bond->dev->name, (int)strlen(buf) - 1, buf);
|
|
out:
|
|
write_unlock_bh(&bond->curr_slave_lock);
|
|
read_unlock(&bond->lock);
|
|
@@ -1162,6 +1164,7 @@ static ssize_t bonding_store_active_slave(struct device *d,
|
|
struct slave *old_active = NULL;
|
|
struct slave *new_active = NULL;
|
|
struct bonding *bond = to_bond(d);
|
|
+ char ifname[IFNAMSIZ];
|
|
|
|
if (!rtnl_trylock())
|
|
return restart_syscall();
|
|
@@ -1170,56 +1173,62 @@ static ssize_t bonding_store_active_slave(struct device *d,
|
|
read_lock(&bond->lock);
|
|
write_lock_bh(&bond->curr_slave_lock);
|
|
|
|
- if (!USES_PRIMARY(bond->params.mode))
|
|
+ if (!USES_PRIMARY(bond->params.mode)) {
|
|
pr_info("%s: Unable to change active slave; %s is in mode %d\n",
|
|
bond->dev->name, bond->dev->name, bond->params.mode);
|
|
- else {
|
|
- bond_for_each_slave(bond, slave, i) {
|
|
- if (strnicmp
|
|
- (slave->dev->name, buf,
|
|
- strlen(slave->dev->name)) == 0) {
|
|
- old_active = bond->curr_active_slave;
|
|
- new_active = slave;
|
|
- if (new_active == old_active) {
|
|
- /* do nothing */
|
|
- pr_info("%s: %s is already the current active slave.\n",
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ sscanf(buf, "%16s", ifname); /* IFNAMSIZ */
|
|
+
|
|
+ /* check to see if we are clearing active */
|
|
+ if (!strlen(ifname) || buf[0] == '\n') {
|
|
+ pr_info("%s: Clearing current active slave.\n",
|
|
+ bond->dev->name);
|
|
+ bond->curr_active_slave = NULL;
|
|
+ bond_select_active_slave(bond);
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ bond_for_each_slave(bond, slave, i) {
|
|
+ if (strncmp(slave->dev->name, ifname, IFNAMSIZ) == 0) {
|
|
+ old_active = bond->curr_active_slave;
|
|
+ new_active = slave;
|
|
+ if (new_active == old_active) {
|
|
+ /* do nothing */
|
|
+ pr_info("%s: %s is already the current"
|
|
+ " active slave.\n",
|
|
+ bond->dev->name,
|
|
+ slave->dev->name);
|
|
+ goto out;
|
|
+ }
|
|
+ else {
|
|
+ if ((new_active) &&
|
|
+ (old_active) &&
|
|
+ (new_active->link == BOND_LINK_UP) &&
|
|
+ IS_UP(new_active->dev)) {
|
|
+ pr_info("%s: Setting %s as active"
|
|
+ " slave.\n",
|
|
bond->dev->name,
|
|
slave->dev->name);
|
|
- goto out;
|
|
+ bond_change_active_slave(bond,
|
|
+ new_active);
|
|
}
|
|
else {
|
|
- if ((new_active) &&
|
|
- (old_active) &&
|
|
- (new_active->link == BOND_LINK_UP) &&
|
|
- IS_UP(new_active->dev)) {
|
|
- pr_info("%s: Setting %s as active slave.\n",
|
|
- bond->dev->name,
|
|
- slave->dev->name);
|
|
- bond_change_active_slave(bond, new_active);
|
|
- }
|
|
- else {
|
|
- pr_info("%s: Could not set %s as active slave; either %s is down or the link is down.\n",
|
|
- bond->dev->name,
|
|
- slave->dev->name,
|
|
- slave->dev->name);
|
|
- }
|
|
- goto out;
|
|
+ pr_info("%s: Could not set %s as"
|
|
+ " active slave; either %s is"
|
|
+ " down or the link is down.\n",
|
|
+ bond->dev->name,
|
|
+ slave->dev->name,
|
|
+ slave->dev->name);
|
|
}
|
|
+ goto out;
|
|
}
|
|
}
|
|
-
|
|
- /* if we got here, then we didn't match the name of any slave */
|
|
-
|
|
- if (strlen(buf) == 0 || buf[0] == '\n') {
|
|
- pr_info("%s: Setting active slave to None.\n",
|
|
- bond->dev->name);
|
|
- bond->primary_slave = NULL;
|
|
- bond_select_active_slave(bond);
|
|
- } else {
|
|
- pr_info("%s: Unable to set %.*s as active slave as it is not a slave.\n",
|
|
- bond->dev->name, (int)strlen(buf) - 1, buf);
|
|
- }
|
|
}
|
|
+
|
|
+ pr_info("%s: Unable to set %.*s as active slave.\n",
|
|
+ bond->dev->name, (int)strlen(buf) - 1, buf);
|
|
out:
|
|
write_unlock_bh(&bond->curr_slave_lock);
|
|
read_unlock(&bond->lock);
|
|
diff --git a/drivers/net/e1000e/lib.c b/drivers/net/e1000e/lib.c
|
|
index dd8ab05..8d28602 100644
|
|
--- a/drivers/net/e1000e/lib.c
|
|
+++ b/drivers/net/e1000e/lib.c
|
|
@@ -190,7 +190,8 @@ s32 e1000_check_alt_mac_addr_generic(struct e1000_hw *hw)
|
|
/* Check for LOM (vs. NIC) or one of two valid mezzanine cards */
|
|
if (!((nvm_data & NVM_COMPAT_LOM) ||
|
|
(hw->adapter->pdev->device == E1000_DEV_ID_82571EB_SERDES_DUAL) ||
|
|
- (hw->adapter->pdev->device == E1000_DEV_ID_82571EB_SERDES_QUAD)))
|
|
+ (hw->adapter->pdev->device == E1000_DEV_ID_82571EB_SERDES_QUAD) ||
|
|
+ (hw->adapter->pdev->device == E1000_DEV_ID_82571EB_SERDES)))
|
|
goto out;
|
|
|
|
ret_val = e1000_read_nvm(hw, NVM_ALT_MAC_ADDR_PTR, 1,
|
|
diff --git a/drivers/net/gianfar_ptp.c b/drivers/net/gianfar_ptp.c
|
|
index d8e1753..c413479 100644
|
|
--- a/drivers/net/gianfar_ptp.c
|
|
+++ b/drivers/net/gianfar_ptp.c
|
|
@@ -193,14 +193,9 @@ static void set_alarm(struct etsects *etsects)
|
|
/* Caller must hold etsects->lock. */
|
|
static void set_fipers(struct etsects *etsects)
|
|
{
|
|
- u32 tmr_ctrl = gfar_read(&etsects->regs->tmr_ctrl);
|
|
-
|
|
- gfar_write(&etsects->regs->tmr_ctrl, tmr_ctrl & (~TE));
|
|
- gfar_write(&etsects->regs->tmr_prsc, etsects->tmr_prsc);
|
|
+ set_alarm(etsects);
|
|
gfar_write(&etsects->regs->tmr_fiper1, etsects->tmr_fiper1);
|
|
gfar_write(&etsects->regs->tmr_fiper2, etsects->tmr_fiper2);
|
|
- set_alarm(etsects);
|
|
- gfar_write(&etsects->regs->tmr_ctrl, tmr_ctrl|TE);
|
|
}
|
|
|
|
/*
|
|
@@ -511,7 +506,7 @@ static int gianfar_ptp_probe(struct platform_device *dev)
|
|
gfar_write(&etsects->regs->tmr_fiper1, etsects->tmr_fiper1);
|
|
gfar_write(&etsects->regs->tmr_fiper2, etsects->tmr_fiper2);
|
|
set_alarm(etsects);
|
|
- gfar_write(&etsects->regs->tmr_ctrl, tmr_ctrl|FS|RTPE|TE);
|
|
+ gfar_write(&etsects->regs->tmr_ctrl, tmr_ctrl|FS|RTPE|TE|FRD);
|
|
|
|
spin_unlock_irqrestore(&etsects->lock, flags);
|
|
|
|
diff --git a/drivers/net/ifb.c b/drivers/net/ifb.c
|
|
index 4fecaed..2b98461 100644
|
|
--- a/drivers/net/ifb.c
|
|
+++ b/drivers/net/ifb.c
|
|
@@ -145,7 +145,7 @@ static void ifb_setup(struct net_device *dev)
|
|
|
|
dev->flags |= IFF_NOARP;
|
|
dev->flags &= ~IFF_MULTICAST;
|
|
- dev->priv_flags &= ~IFF_XMIT_DST_RELEASE;
|
|
+ dev->priv_flags &= ~(IFF_XMIT_DST_RELEASE | IFF_TX_SKB_SHARING);
|
|
random_ether_addr(dev->dev_addr);
|
|
}
|
|
|
|
diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c
|
|
index d6aeaa5..2f3c48d 100644
|
|
--- a/drivers/net/macvlan.c
|
|
+++ b/drivers/net/macvlan.c
|
|
@@ -547,7 +547,7 @@ void macvlan_common_setup(struct net_device *dev)
|
|
{
|
|
ether_setup(dev);
|
|
|
|
- dev->priv_flags &= ~IFF_XMIT_DST_RELEASE;
|
|
+ dev->priv_flags &= ~(IFF_XMIT_DST_RELEASE | IFF_TX_SKB_SHARING);
|
|
dev->netdev_ops = &macvlan_netdev_ops;
|
|
dev->destructor = free_netdev;
|
|
dev->header_ops = &macvlan_hard_header_ops,
|
|
diff --git a/drivers/net/niu.c b/drivers/net/niu.c
|
|
index cc25bff..2f8c351 100644
|
|
--- a/drivers/net/niu.c
|
|
+++ b/drivers/net/niu.c
|
|
@@ -9196,7 +9196,7 @@ static int __devinit niu_ldg_init(struct niu *np)
|
|
|
|
first_chan = 0;
|
|
for (i = 0; i < port; i++)
|
|
- first_chan += parent->rxchan_per_port[port];
|
|
+ first_chan += parent->rxchan_per_port[i];
|
|
num_chan = parent->rxchan_per_port[port];
|
|
|
|
for (i = first_chan; i < (first_chan + num_chan); i++) {
|
|
@@ -9212,7 +9212,7 @@ static int __devinit niu_ldg_init(struct niu *np)
|
|
|
|
first_chan = 0;
|
|
for (i = 0; i < port; i++)
|
|
- first_chan += parent->txchan_per_port[port];
|
|
+ first_chan += parent->txchan_per_port[i];
|
|
num_chan = parent->txchan_per_port[port];
|
|
for (i = first_chan; i < (first_chan + num_chan); i++) {
|
|
err = niu_ldg_assign_ldn(np, parent,
|
|
diff --git a/drivers/net/phy/dp83640.c b/drivers/net/phy/dp83640.c
|
|
index 2cd8dc5..cb6e0b4 100644
|
|
--- a/drivers/net/phy/dp83640.c
|
|
+++ b/drivers/net/phy/dp83640.c
|
|
@@ -34,8 +34,7 @@
|
|
#define PAGESEL 0x13
|
|
#define LAYER4 0x02
|
|
#define LAYER2 0x01
|
|
-#define MAX_RXTS 4
|
|
-#define MAX_TXTS 4
|
|
+#define MAX_RXTS 64
|
|
#define N_EXT_TS 1
|
|
#define PSF_PTPVER 2
|
|
#define PSF_EVNT 0x4000
|
|
@@ -218,7 +217,7 @@ static void phy2rxts(struct phy_rxts *p, struct rxts *rxts)
|
|
rxts->seqid = p->seqid;
|
|
rxts->msgtype = (p->msgtype >> 12) & 0xf;
|
|
rxts->hash = p->msgtype & 0x0fff;
|
|
- rxts->tmo = jiffies + HZ;
|
|
+ rxts->tmo = jiffies + 2;
|
|
}
|
|
|
|
static u64 phy2txts(struct phy_txts *p)
|
|
diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c
|
|
index 5990621..5f838ef 100644
|
|
--- a/drivers/net/r8169.c
|
|
+++ b/drivers/net/r8169.c
|
|
@@ -236,6 +236,7 @@ static DEFINE_PCI_DEVICE_TABLE(rtl8169_pci_tbl) = {
|
|
{ PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8168), 0, 0, RTL_CFG_1 },
|
|
{ PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8169), 0, 0, RTL_CFG_0 },
|
|
{ PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4300), 0, 0, RTL_CFG_0 },
|
|
+ { PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4302), 0, 0, RTL_CFG_0 },
|
|
{ PCI_DEVICE(PCI_VENDOR_ID_AT, 0xc107), 0, 0, RTL_CFG_0 },
|
|
{ PCI_DEVICE(0x16ec, 0x0116), 0, 0, RTL_CFG_0 },
|
|
{ PCI_VENDOR_ID_LINKSYS, 0x1032,
|
|
diff --git a/drivers/net/sis190.c b/drivers/net/sis190.c
|
|
index b436e00..f6d26ab 100644
|
|
--- a/drivers/net/sis190.c
|
|
+++ b/drivers/net/sis190.c
|
|
@@ -1824,6 +1824,16 @@ static int sis190_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
|
|
generic_mii_ioctl(&tp->mii_if, if_mii(ifr), cmd, NULL);
|
|
}
|
|
|
|
+static int sis190_mac_addr(struct net_device *dev, void *p)
|
|
+{
|
|
+ int rc;
|
|
+
|
|
+ rc = eth_mac_addr(dev, p);
|
|
+ if (!rc)
|
|
+ sis190_init_rxfilter(dev);
|
|
+ return rc;
|
|
+}
|
|
+
|
|
static const struct net_device_ops sis190_netdev_ops = {
|
|
.ndo_open = sis190_open,
|
|
.ndo_stop = sis190_close,
|
|
@@ -1832,7 +1842,7 @@ static const struct net_device_ops sis190_netdev_ops = {
|
|
.ndo_tx_timeout = sis190_tx_timeout,
|
|
.ndo_set_multicast_list = sis190_set_rx_mode,
|
|
.ndo_change_mtu = eth_change_mtu,
|
|
- .ndo_set_mac_address = eth_mac_addr,
|
|
+ .ndo_set_mac_address = sis190_mac_addr,
|
|
.ndo_validate_addr = eth_validate_addr,
|
|
#ifdef CONFIG_NET_POLL_CONTROLLER
|
|
.ndo_poll_controller = sis190_netpoll,
|
|
diff --git a/drivers/net/tun.c b/drivers/net/tun.c
|
|
index 5235f48..fb50e5a 100644
|
|
--- a/drivers/net/tun.c
|
|
+++ b/drivers/net/tun.c
|
|
@@ -528,6 +528,7 @@ static void tun_net_init(struct net_device *dev)
|
|
dev->netdev_ops = &tap_netdev_ops;
|
|
/* Ethernet TAP Device */
|
|
ether_setup(dev);
|
|
+ dev->priv_flags &= ~IFF_TX_SKB_SHARING;
|
|
|
|
random_ether_addr(dev->dev_addr);
|
|
|
|
diff --git a/drivers/net/veth.c b/drivers/net/veth.c
|
|
index 8461576..4bf7c6d 100644
|
|
--- a/drivers/net/veth.c
|
|
+++ b/drivers/net/veth.c
|
|
@@ -262,6 +262,8 @@ static void veth_setup(struct net_device *dev)
|
|
{
|
|
ether_setup(dev);
|
|
|
|
+ dev->priv_flags &= ~IFF_TX_SKB_SHARING;
|
|
+
|
|
dev->netdev_ops = &veth_netdev_ops;
|
|
dev->ethtool_ops = &veth_ethtool_ops;
|
|
dev->features |= NETIF_F_LLTX;
|
|
diff --git a/drivers/net/wan/hdlc_fr.c b/drivers/net/wan/hdlc_fr.c
|
|
index fc433f2..13f9997 100644
|
|
--- a/drivers/net/wan/hdlc_fr.c
|
|
+++ b/drivers/net/wan/hdlc_fr.c
|
|
@@ -1083,9 +1083,10 @@ static int fr_add_pvc(struct net_device *frad, unsigned int dlci, int type)
|
|
|
|
used = pvc_is_used(pvc);
|
|
|
|
- if (type == ARPHRD_ETHER)
|
|
+ if (type == ARPHRD_ETHER) {
|
|
dev = alloc_netdev(0, "pvceth%d", ether_setup);
|
|
- else
|
|
+ dev->priv_flags &= ~IFF_TX_SKB_SHARING;
|
|
+ } else
|
|
dev = alloc_netdev(0, "pvc%d", pvc_setup);
|
|
|
|
if (!dev) {
|
|
diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c
|
|
index 55cf71f..e1b3e3c 100644
|
|
--- a/drivers/net/wireless/airo.c
|
|
+++ b/drivers/net/wireless/airo.c
|
|
@@ -2823,6 +2823,7 @@ static struct net_device *_init_airo_card( unsigned short irq, int port,
|
|
dev->wireless_data = &ai->wireless_data;
|
|
dev->irq = irq;
|
|
dev->base_addr = port;
|
|
+ dev->priv_flags &= ~IFF_TX_SKB_SHARING;
|
|
|
|
SET_NETDEV_DEV(dev, dmdev);
|
|
|
|
diff --git a/drivers/net/wireless/ath/ath9k/ar9002_hw.c b/drivers/net/wireless/ath/ath9k/ar9002_hw.c
|
|
index f344cc2..c32f9d1 100644
|
|
--- a/drivers/net/wireless/ath/ath9k/ar9002_hw.c
|
|
+++ b/drivers/net/wireless/ath/ath9k/ar9002_hw.c
|
|
@@ -309,11 +309,7 @@ static void ar9002_hw_configpcipowersave(struct ath_hw *ah,
|
|
u8 i;
|
|
u32 val;
|
|
|
|
- if (ah->is_pciexpress != true)
|
|
- return;
|
|
-
|
|
- /* Do not touch SerDes registers */
|
|
- if (ah->config.pcie_powersave_enable == 2)
|
|
+ if (ah->is_pciexpress != true || ah->aspm_enabled != true)
|
|
return;
|
|
|
|
/* Nothing to do on restore for 11N */
|
|
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
|
|
index ff8150e..7e07f0f 100644
|
|
--- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
|
|
+++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
|
|
@@ -306,7 +306,7 @@ static const struct ar9300_eeprom ar9300_default = {
|
|
{ { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
|
|
{ { CTL(60, 1), CTL(60, 0), CTL(60, 0), CTL(60, 1) } },
|
|
|
|
- { { CTL(60, 1), CTL(60, 0), CTL(0, 0), CTL(0, 0) } },
|
|
+ { { CTL(60, 1), CTL(60, 0), CTL(60, 0), CTL(60, 0) } },
|
|
{ { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
|
|
{ { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
|
|
|
|
@@ -883,7 +883,7 @@ static const struct ar9300_eeprom ar9300_x113 = {
|
|
{ { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
|
|
{ { CTL(60, 1), CTL(60, 0), CTL(60, 0), CTL(60, 1) } },
|
|
|
|
- { { CTL(60, 1), CTL(60, 0), CTL(0, 0), CTL(0, 0) } },
|
|
+ { { CTL(60, 1), CTL(60, 0), CTL(60, 0), CTL(60, 0) } },
|
|
{ { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
|
|
{ { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
|
|
|
|
@@ -2039,7 +2039,7 @@ static const struct ar9300_eeprom ar9300_x112 = {
|
|
{ { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
|
|
{ { CTL(60, 1), CTL(60, 0), CTL(60, 0), CTL(60, 1) } },
|
|
|
|
- { { CTL(60, 1), CTL(60, 0), CTL(0, 0), CTL(0, 0) } },
|
|
+ { { CTL(60, 1), CTL(60, 0), CTL(60, 0), CTL(60, 0) } },
|
|
{ { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
|
|
{ { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
|
|
|
|
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_hw.c b/drivers/net/wireless/ath/ath9k/ar9003_hw.c
|
|
index 392bf0f..7e02fb4 100644
|
|
--- a/drivers/net/wireless/ath/ath9k/ar9003_hw.c
|
|
+++ b/drivers/net/wireless/ath/ath9k/ar9003_hw.c
|
|
@@ -351,11 +351,7 @@ static void ar9003_hw_configpcipowersave(struct ath_hw *ah,
|
|
int restore,
|
|
int power_off)
|
|
{
|
|
- if (ah->is_pciexpress != true)
|
|
- return;
|
|
-
|
|
- /* Do not touch SerDes registers */
|
|
- if (ah->config.pcie_powersave_enable == 2)
|
|
+ if (ah->is_pciexpress != true || ah->aspm_enabled != true)
|
|
return;
|
|
|
|
/* Nothing to do on restore for 11N */
|
|
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.h b/drivers/net/wireless/ath/ath9k/ar9003_phy.h
|
|
index 443090d..efdbe98 100644
|
|
--- a/drivers/net/wireless/ath/ath9k/ar9003_phy.h
|
|
+++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.h
|
|
@@ -848,7 +848,7 @@
|
|
#define AR_PHY_TPC_11_B1 (AR_SM1_BASE + 0x220)
|
|
#define AR_PHY_PDADC_TAB_1 (AR_SM1_BASE + 0x240)
|
|
#define AR_PHY_TX_IQCAL_STATUS_B1 (AR_SM1_BASE + 0x48c)
|
|
-#define AR_PHY_TX_IQCAL_CORR_COEFF_B1(_i) (AR_SM_BASE + 0x450 + ((_i) << 2))
|
|
+#define AR_PHY_TX_IQCAL_CORR_COEFF_B1(_i) (AR_SM1_BASE + 0x450 + ((_i) << 2))
|
|
|
|
/*
|
|
* Channel 2 Register Map
|
|
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c
|
|
index 1be7c8b..03900ca 100644
|
|
--- a/drivers/net/wireless/ath/ath9k/hw.c
|
|
+++ b/drivers/net/wireless/ath/ath9k/hw.c
|
|
@@ -299,6 +299,14 @@ static void ath9k_hw_disablepcie(struct ath_hw *ah)
|
|
REG_WRITE(ah, AR_PCIE_SERDES2, 0x00000000);
|
|
}
|
|
|
|
+static void ath9k_hw_aspm_init(struct ath_hw *ah)
|
|
+{
|
|
+ struct ath_common *common = ath9k_hw_common(ah);
|
|
+
|
|
+ if (common->bus_ops->aspm_init)
|
|
+ common->bus_ops->aspm_init(common);
|
|
+}
|
|
+
|
|
/* This should work for all families including legacy */
|
|
static bool ath9k_hw_chip_test(struct ath_hw *ah)
|
|
{
|
|
@@ -359,7 +367,6 @@ static void ath9k_hw_init_config(struct ath_hw *ah)
|
|
ah->config.additional_swba_backoff = 0;
|
|
ah->config.ack_6mb = 0x0;
|
|
ah->config.cwm_ignore_extcca = 0;
|
|
- ah->config.pcie_powersave_enable = 0;
|
|
ah->config.pcie_clock_req = 0;
|
|
ah->config.pcie_waen = 0;
|
|
ah->config.analog_shiftreg = 1;
|
|
@@ -577,7 +584,7 @@ static int __ath9k_hw_init(struct ath_hw *ah)
|
|
|
|
|
|
if (ah->is_pciexpress)
|
|
- ath9k_hw_configpcipowersave(ah, 0, 0);
|
|
+ ath9k_hw_aspm_init(ah);
|
|
else
|
|
ath9k_hw_disablepcie(ah);
|
|
|
|
diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h
|
|
index 4b157c5..939cc9d 100644
|
|
--- a/drivers/net/wireless/ath/ath9k/hw.h
|
|
+++ b/drivers/net/wireless/ath/ath9k/hw.h
|
|
@@ -215,7 +215,6 @@ struct ath9k_ops_config {
|
|
int additional_swba_backoff;
|
|
int ack_6mb;
|
|
u32 cwm_ignore_extcca;
|
|
- u8 pcie_powersave_enable;
|
|
bool pcieSerDesWrite;
|
|
u8 pcie_clock_req;
|
|
u32 pcie_waen;
|
|
@@ -671,6 +670,7 @@ struct ath_hw {
|
|
|
|
bool sw_mgmt_crypto;
|
|
bool is_pciexpress;
|
|
+ bool aspm_enabled;
|
|
bool is_monitoring;
|
|
bool need_an_top2_fixup;
|
|
u16 tx_trig_level;
|
|
@@ -870,6 +870,7 @@ struct ath_bus_ops {
|
|
bool (*eeprom_read)(struct ath_common *common, u32 off, u16 *data);
|
|
void (*bt_coex_prep)(struct ath_common *common);
|
|
void (*extn_synch_en)(struct ath_common *common);
|
|
+ void (*aspm_init)(struct ath_common *common);
|
|
};
|
|
|
|
static inline struct ath_common *ath9k_hw_common(struct ath_hw *ah)
|
|
diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c
|
|
index 45c585a..5a9fd21 100644
|
|
--- a/drivers/net/wireless/ath/ath9k/init.c
|
|
+++ b/drivers/net/wireless/ath/ath9k/init.c
|
|
@@ -665,8 +665,10 @@ static void ath9k_init_band_txpower(struct ath_softc *sc, int band)
|
|
static void ath9k_init_txpower_limits(struct ath_softc *sc)
|
|
{
|
|
struct ath_hw *ah = sc->sc_ah;
|
|
+ struct ath_common *common = ath9k_hw_common(sc->sc_ah);
|
|
struct ath9k_channel *curchan = ah->curchan;
|
|
|
|
+ ah->txchainmask = common->tx_chainmask;
|
|
if (ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ)
|
|
ath9k_init_band_txpower(sc, IEEE80211_BAND_2GHZ);
|
|
if (ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ)
|
|
diff --git a/drivers/net/wireless/ath/ath9k/pci.c b/drivers/net/wireless/ath/ath9k/pci.c
|
|
index 3bad0b2..be4ea13 100644
|
|
--- a/drivers/net/wireless/ath/ath9k/pci.c
|
|
+++ b/drivers/net/wireless/ath/ath9k/pci.c
|
|
@@ -16,6 +16,7 @@
|
|
|
|
#include <linux/nl80211.h>
|
|
#include <linux/pci.h>
|
|
+#include <linux/pci-aspm.h>
|
|
#include <linux/ath9k_platform.h>
|
|
#include "ath9k.h"
|
|
|
|
@@ -115,12 +116,38 @@ static void ath_pci_extn_synch_enable(struct ath_common *common)
|
|
pci_write_config_byte(pdev, sc->sc_ah->caps.pcie_lcr_offset, lnkctl);
|
|
}
|
|
|
|
+static void ath_pci_aspm_init(struct ath_common *common)
|
|
+{
|
|
+ struct ath_softc *sc = (struct ath_softc *) common->priv;
|
|
+ struct ath_hw *ah = sc->sc_ah;
|
|
+ struct pci_dev *pdev = to_pci_dev(sc->dev);
|
|
+ struct pci_dev *parent;
|
|
+ int pos;
|
|
+ u8 aspm;
|
|
+
|
|
+ if (!pci_is_pcie(pdev))
|
|
+ return;
|
|
+
|
|
+ parent = pdev->bus->self;
|
|
+ if (WARN_ON(!parent))
|
|
+ return;
|
|
+
|
|
+ pos = pci_pcie_cap(parent);
|
|
+ pci_read_config_byte(parent, pos + PCI_EXP_LNKCTL, &aspm);
|
|
+ if (aspm & (PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1)) {
|
|
+ ah->aspm_enabled = true;
|
|
+ /* Initialize PCIe PM and SERDES registers. */
|
|
+ ath9k_hw_configpcipowersave(ah, 0, 0);
|
|
+ }
|
|
+}
|
|
+
|
|
static const struct ath_bus_ops ath_pci_bus_ops = {
|
|
.ath_bus_type = ATH_PCI,
|
|
.read_cachesize = ath_pci_read_cachesize,
|
|
.eeprom_read = ath_pci_eeprom_read,
|
|
.bt_coex_prep = ath_pci_bt_coex_prep,
|
|
.extn_synch_en = ath_pci_extn_synch_enable,
|
|
+ .aspm_init = ath_pci_aspm_init,
|
|
};
|
|
|
|
static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
|
|
diff --git a/drivers/net/wireless/hostap/hostap_main.c b/drivers/net/wireless/hostap/hostap_main.c
|
|
index d508482..89a116f 100644
|
|
--- a/drivers/net/wireless/hostap/hostap_main.c
|
|
+++ b/drivers/net/wireless/hostap/hostap_main.c
|
|
@@ -855,6 +855,7 @@ void hostap_setup_dev(struct net_device *dev, local_info_t *local,
|
|
|
|
iface = netdev_priv(dev);
|
|
ether_setup(dev);
|
|
+ dev->priv_flags &= ~IFF_TX_SKB_SHARING;
|
|
|
|
/* kernel callbacks */
|
|
if (iface) {
|
|
diff --git a/drivers/net/wireless/iwlegacy/iwl-3945.c b/drivers/net/wireless/iwlegacy/iwl-3945.c
|
|
index d096dc2..dcc1552 100644
|
|
--- a/drivers/net/wireless/iwlegacy/iwl-3945.c
|
|
+++ b/drivers/net/wireless/iwlegacy/iwl-3945.c
|
|
@@ -1747,7 +1747,11 @@ int iwl3945_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
|
|
}
|
|
|
|
memcpy(active_rxon, staging_rxon, sizeof(*active_rxon));
|
|
-
|
|
+ /*
|
|
+ * We do not commit tx power settings while channel changing,
|
|
+ * do it now if tx power changed.
|
|
+ */
|
|
+ iwl_legacy_set_tx_power(priv, priv->tx_power_next, false);
|
|
return 0;
|
|
}
|
|
|
|
diff --git a/drivers/net/wireless/iwlegacy/iwl-4965.c b/drivers/net/wireless/iwlegacy/iwl-4965.c
|
|
index facc94e..0a1babb 100644
|
|
--- a/drivers/net/wireless/iwlegacy/iwl-4965.c
|
|
+++ b/drivers/net/wireless/iwlegacy/iwl-4965.c
|
|
@@ -1237,7 +1237,12 @@ static int iwl4965_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *c
|
|
|
|
memcpy(active_rxon, &ctx->staging, sizeof(*active_rxon));
|
|
iwl_legacy_print_rx_config_cmd(priv, ctx);
|
|
- goto set_tx_power;
|
|
+ /*
|
|
+ * We do not commit tx power settings while channel changing,
|
|
+ * do it now if tx power changed.
|
|
+ */
|
|
+ iwl_legacy_set_tx_power(priv, priv->tx_power_next, false);
|
|
+ return 0;
|
|
}
|
|
|
|
/* If we are currently associated and the new config requires
|
|
@@ -1317,7 +1322,6 @@ static int iwl4965_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *c
|
|
|
|
iwl4965_init_sensitivity(priv);
|
|
|
|
-set_tx_power:
|
|
/* If we issue a new RXON command which required a tune then we must
|
|
* send a new TXPOWER command or we won't be able to Tx any frames */
|
|
ret = iwl_legacy_set_tx_power(priv, priv->tx_power_next, true);
|
|
diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c
|
|
index e816c27..f1c3f49 100644
|
|
--- a/drivers/net/wireless/iwlwifi/iwl-5000.c
|
|
+++ b/drivers/net/wireless/iwlwifi/iwl-5000.c
|
|
@@ -421,6 +421,7 @@ static struct iwl_base_params iwl5000_base_params = {
|
|
.chain_noise_scale = 1000,
|
|
.wd_timeout = IWL_LONG_WD_TIMEOUT,
|
|
.max_event_log_size = 512,
|
|
+ .no_idle_support = true,
|
|
};
|
|
static struct iwl_ht_params iwl5000_ht_params = {
|
|
.ht_greenfield_support = true,
|
|
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h
|
|
index a54d416..b76996a 100644
|
|
--- a/drivers/net/wireless/iwlwifi/iwl-core.h
|
|
+++ b/drivers/net/wireless/iwlwifi/iwl-core.h
|
|
@@ -195,6 +195,7 @@ struct iwl_mod_params {
|
|
* @temperature_kelvin: temperature report by uCode in kelvin
|
|
* @max_event_log_size: size of event log buffer size for ucode event logging
|
|
* @shadow_reg_enable: HW shadhow register bit
|
|
+ * @no_idle_support: do not support idle mode
|
|
*/
|
|
struct iwl_base_params {
|
|
int eeprom_size;
|
|
@@ -216,6 +217,7 @@ struct iwl_base_params {
|
|
bool temperature_kelvin;
|
|
u32 max_event_log_size;
|
|
const bool shadow_reg_enable;
|
|
+ const bool no_idle_support;
|
|
};
|
|
/*
|
|
* @advanced_bt_coexist: support advanced bt coexist
|
|
diff --git a/drivers/net/wireless/iwlwifi/iwl-power.c b/drivers/net/wireless/iwlwifi/iwl-power.c
|
|
index 595c930..4a05a6a 100644
|
|
--- a/drivers/net/wireless/iwlwifi/iwl-power.c
|
|
+++ b/drivers/net/wireless/iwlwifi/iwl-power.c
|
|
@@ -355,7 +355,8 @@ static void iwl_power_build_cmd(struct iwl_priv *priv,
|
|
|
|
dtimper = priv->hw->conf.ps_dtim_period ?: 1;
|
|
|
|
- if (priv->hw->conf.flags & IEEE80211_CONF_IDLE)
|
|
+ if (!priv->cfg->base_params->no_idle_support &&
|
|
+ priv->hw->conf.flags & IEEE80211_CONF_IDLE)
|
|
iwl_static_sleep_cmd(priv, cmd, IWL_POWER_INDEX_5, 20);
|
|
else if (iwl_tt_is_low_power_state(priv)) {
|
|
/* in thermal throttling low power state */
|
|
diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c
|
|
index 2a6aa85..5a45228 100644
|
|
--- a/drivers/net/wireless/rt2x00/rt2800lib.c
|
|
+++ b/drivers/net/wireless/rt2x00/rt2800lib.c
|
|
@@ -784,8 +784,7 @@ void rt2800_write_beacon(struct queue_entry *entry, struct txentry_desc *txdesc)
|
|
/*
|
|
* Add space for the TXWI in front of the skb.
|
|
*/
|
|
- skb_push(entry->skb, TXWI_DESC_SIZE);
|
|
- memset(entry->skb, 0, TXWI_DESC_SIZE);
|
|
+ memset(skb_push(entry->skb, TXWI_DESC_SIZE), 0, TXWI_DESC_SIZE);
|
|
|
|
/*
|
|
* Register descriptor details in skb frame descriptor.
|
|
diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c
|
|
index 93bec14..a76fdbe 100644
|
|
--- a/drivers/net/wireless/rt2x00/rt2x00mac.c
|
|
+++ b/drivers/net/wireless/rt2x00/rt2x00mac.c
|
|
@@ -113,7 +113,7 @@ void rt2x00mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
|
|
* due to possible race conditions in mac80211.
|
|
*/
|
|
if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags))
|
|
- goto exit_fail;
|
|
+ goto exit_free_skb;
|
|
|
|
/*
|
|
* Use the ATIM queue if appropriate and present.
|
|
@@ -127,7 +127,7 @@ void rt2x00mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
|
|
ERROR(rt2x00dev,
|
|
"Attempt to send packet over invalid queue %d.\n"
|
|
"Please file bug report to %s.\n", qid, DRV_PROJECT);
|
|
- goto exit_fail;
|
|
+ goto exit_free_skb;
|
|
}
|
|
|
|
/*
|
|
@@ -159,6 +159,7 @@ void rt2x00mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
|
|
|
|
exit_fail:
|
|
rt2x00queue_pause_queue(queue);
|
|
+ exit_free_skb:
|
|
dev_kfree_skb_any(skb);
|
|
}
|
|
EXPORT_SYMBOL_GPL(rt2x00mac_tx);
|
|
diff --git a/drivers/net/wireless/rtlwifi/pci.c b/drivers/net/wireless/rtlwifi/pci.c
|
|
index 254b64b..c872a23 100644
|
|
--- a/drivers/net/wireless/rtlwifi/pci.c
|
|
+++ b/drivers/net/wireless/rtlwifi/pci.c
|
|
@@ -1709,15 +1709,17 @@ static bool _rtl_pci_find_adapter(struct pci_dev *pdev,
|
|
pcipriv->ndis_adapter.devnumber = PCI_SLOT(pdev->devfn);
|
|
pcipriv->ndis_adapter.funcnumber = PCI_FUNC(pdev->devfn);
|
|
|
|
- /*find bridge info */
|
|
- pcipriv->ndis_adapter.pcibridge_vendorid = bridge_pdev->vendor;
|
|
- for (tmp = 0; tmp < PCI_BRIDGE_VENDOR_MAX; tmp++) {
|
|
- if (bridge_pdev->vendor == pcibridge_vendors[tmp]) {
|
|
- pcipriv->ndis_adapter.pcibridge_vendor = tmp;
|
|
- RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
|
|
- ("Pci Bridge Vendor is found index: %d\n",
|
|
- tmp));
|
|
- break;
|
|
+ if (bridge_pdev) {
|
|
+ /*find bridge info if available */
|
|
+ pcipriv->ndis_adapter.pcibridge_vendorid = bridge_pdev->vendor;
|
|
+ for (tmp = 0; tmp < PCI_BRIDGE_VENDOR_MAX; tmp++) {
|
|
+ if (bridge_pdev->vendor == pcibridge_vendors[tmp]) {
|
|
+ pcipriv->ndis_adapter.pcibridge_vendor = tmp;
|
|
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
|
|
+ ("Pci Bridge Vendor is found index:"
|
|
+ " %d\n", tmp));
|
|
+ break;
|
|
+ }
|
|
}
|
|
}
|
|
|
|
diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c
|
|
index 3c7857c..e1678b9 100644
|
|
--- a/drivers/platform/x86/asus-wmi.c
|
|
+++ b/drivers/platform/x86/asus-wmi.c
|
|
@@ -797,8 +797,8 @@ exit:
|
|
* Hwmon device
|
|
*/
|
|
static ssize_t asus_hwmon_pwm1(struct device *dev,
|
|
- struct device_attribute *attr,
|
|
- char *buf)
|
|
+ struct device_attribute *attr,
|
|
+ char *buf)
|
|
{
|
|
struct asus_wmi *asus = dev_get_drvdata(dev);
|
|
u32 value;
|
|
@@ -809,7 +809,7 @@ static ssize_t asus_hwmon_pwm1(struct device *dev,
|
|
if (err < 0)
|
|
return err;
|
|
|
|
- value |= 0xFF;
|
|
+ value &= 0xFF;
|
|
|
|
if (value == 1) /* Low Speed */
|
|
value = 85;
|
|
@@ -869,7 +869,7 @@ static mode_t asus_hwmon_sysfs_is_visible(struct kobject *kobj,
|
|
* - reverved bits are non-zero
|
|
* - sfun and presence bit are not set
|
|
*/
|
|
- if (value != ASUS_WMI_UNSUPPORTED_METHOD || value & 0xFFF80000
|
|
+ if (value == ASUS_WMI_UNSUPPORTED_METHOD || value & 0xFFF80000
|
|
|| (!asus->sfun && !(value & ASUS_WMI_DSTS_PRESENCE_BIT)))
|
|
ok = false;
|
|
}
|
|
@@ -904,6 +904,7 @@ static int asus_wmi_hwmon_init(struct asus_wmi *asus)
|
|
pr_err("Could not register asus hwmon device\n");
|
|
return PTR_ERR(hwmon);
|
|
}
|
|
+ dev_set_drvdata(hwmon, asus);
|
|
asus->hwmon_device = hwmon;
|
|
result = sysfs_create_group(&hwmon->kobj, &hwmon_attribute_group);
|
|
if (result)
|
|
@@ -1164,14 +1165,18 @@ ASUS_WMI_CREATE_DEVICE_ATTR(cardr, 0644, ASUS_WMI_DEVID_CARDREADER);
|
|
static ssize_t store_cpufv(struct device *dev, struct device_attribute *attr,
|
|
const char *buf, size_t count)
|
|
{
|
|
- int value;
|
|
+ int value, rv;
|
|
|
|
if (!count || sscanf(buf, "%i", &value) != 1)
|
|
return -EINVAL;
|
|
if (value < 0 || value > 2)
|
|
return -EINVAL;
|
|
|
|
- return asus_wmi_evaluate_method(ASUS_WMI_METHODID_CFVS, value, 0, NULL);
|
|
+ rv = asus_wmi_evaluate_method(ASUS_WMI_METHODID_CFVS, value, 0, NULL);
|
|
+ if (rv < 0)
|
|
+ return rv;
|
|
+
|
|
+ return count;
|
|
}
|
|
|
|
static DEVICE_ATTR(cpufv, S_IRUGO | S_IWUSR, NULL, store_cpufv);
|
|
diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.c b/drivers/scsi/mpt2sas/mpt2sas_base.c
|
|
index efa0255..1da606c 100644
|
|
--- a/drivers/scsi/mpt2sas/mpt2sas_base.c
|
|
+++ b/drivers/scsi/mpt2sas/mpt2sas_base.c
|
|
@@ -94,7 +94,7 @@ module_param(diag_buffer_enable, int, 0);
|
|
MODULE_PARM_DESC(diag_buffer_enable, " post diag buffers "
|
|
"(TRACE=1/SNAPSHOT=2/EXTENDED=4/default=0)");
|
|
|
|
-int mpt2sas_fwfault_debug;
|
|
+static int mpt2sas_fwfault_debug;
|
|
MODULE_PARM_DESC(mpt2sas_fwfault_debug, " enable detection of firmware fault "
|
|
"and halt firmware - (default=0)");
|
|
|
|
@@ -857,7 +857,7 @@ _base_interrupt(int irq, void *bus_id)
|
|
completed_cmds = 0;
|
|
cb_idx = 0xFF;
|
|
do {
|
|
- rd.word = rpf->Words;
|
|
+ rd.word = le64_to_cpu(rpf->Words);
|
|
if (rd.u.low == UINT_MAX || rd.u.high == UINT_MAX)
|
|
goto out;
|
|
reply = 0;
|
|
@@ -906,7 +906,7 @@ _base_interrupt(int irq, void *bus_id)
|
|
|
|
next:
|
|
|
|
- rpf->Words = ULLONG_MAX;
|
|
+ rpf->Words = cpu_to_le64(ULLONG_MAX);
|
|
ioc->reply_post_host_index = (ioc->reply_post_host_index ==
|
|
(ioc->reply_post_queue_depth - 1)) ? 0 :
|
|
ioc->reply_post_host_index + 1;
|
|
@@ -1817,7 +1817,9 @@ _base_display_ioc_capabilities(struct MPT2SAS_ADAPTER *ioc)
|
|
char desc[16];
|
|
u8 revision;
|
|
u32 iounit_pg1_flags;
|
|
+ u32 bios_version;
|
|
|
|
+ bios_version = le32_to_cpu(ioc->bios_pg3.BiosVersion);
|
|
pci_read_config_byte(ioc->pdev, PCI_CLASS_REVISION, &revision);
|
|
strncpy(desc, ioc->manu_pg0.ChipName, 16);
|
|
printk(MPT2SAS_INFO_FMT "%s: FWVersion(%02d.%02d.%02d.%02d), "
|
|
@@ -1828,10 +1830,10 @@ _base_display_ioc_capabilities(struct MPT2SAS_ADAPTER *ioc)
|
|
(ioc->facts.FWVersion.Word & 0x0000FF00) >> 8,
|
|
ioc->facts.FWVersion.Word & 0x000000FF,
|
|
revision,
|
|
- (ioc->bios_pg3.BiosVersion & 0xFF000000) >> 24,
|
|
- (ioc->bios_pg3.BiosVersion & 0x00FF0000) >> 16,
|
|
- (ioc->bios_pg3.BiosVersion & 0x0000FF00) >> 8,
|
|
- ioc->bios_pg3.BiosVersion & 0x000000FF);
|
|
+ (bios_version & 0xFF000000) >> 24,
|
|
+ (bios_version & 0x00FF0000) >> 16,
|
|
+ (bios_version & 0x0000FF00) >> 8,
|
|
+ bios_version & 0x000000FF);
|
|
|
|
_base_display_dell_branding(ioc);
|
|
_base_display_intel_branding(ioc);
|
|
@@ -2150,7 +2152,7 @@ _base_release_memory_pools(struct MPT2SAS_ADAPTER *ioc)
|
|
static int
|
|
_base_allocate_memory_pools(struct MPT2SAS_ADAPTER *ioc, int sleep_flag)
|
|
{
|
|
- Mpi2IOCFactsReply_t *facts;
|
|
+ struct mpt2sas_facts *facts;
|
|
u32 queue_size, queue_diff;
|
|
u16 max_sge_elements;
|
|
u16 num_of_reply_frames;
|
|
@@ -2783,7 +2785,7 @@ _base_handshake_req_reply_wait(struct MPT2SAS_ADAPTER *ioc, int request_bytes,
|
|
int i;
|
|
u8 failed;
|
|
u16 dummy;
|
|
- u32 *mfp;
|
|
+ __le32 *mfp;
|
|
|
|
/* make sure doorbell is not in use */
|
|
if ((readl(&ioc->chip->Doorbell) & MPI2_DOORBELL_USED)) {
|
|
@@ -2871,7 +2873,7 @@ _base_handshake_req_reply_wait(struct MPT2SAS_ADAPTER *ioc, int request_bytes,
|
|
writel(0, &ioc->chip->HostInterruptStatus);
|
|
|
|
if (ioc->logging_level & MPT_DEBUG_INIT) {
|
|
- mfp = (u32 *)reply;
|
|
+ mfp = (__le32 *)reply;
|
|
printk(KERN_INFO "\toffset:data\n");
|
|
for (i = 0; i < reply_bytes/4; i++)
|
|
printk(KERN_INFO "\t[0x%02x]:%08x\n", i*4,
|
|
@@ -3097,7 +3099,8 @@ static int
|
|
_base_get_port_facts(struct MPT2SAS_ADAPTER *ioc, int port, int sleep_flag)
|
|
{
|
|
Mpi2PortFactsRequest_t mpi_request;
|
|
- Mpi2PortFactsReply_t mpi_reply, *pfacts;
|
|
+ Mpi2PortFactsReply_t mpi_reply;
|
|
+ struct mpt2sas_port_facts *pfacts;
|
|
int mpi_reply_sz, mpi_request_sz, r;
|
|
|
|
dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
|
|
@@ -3139,7 +3142,8 @@ static int
|
|
_base_get_ioc_facts(struct MPT2SAS_ADAPTER *ioc, int sleep_flag)
|
|
{
|
|
Mpi2IOCFactsRequest_t mpi_request;
|
|
- Mpi2IOCFactsReply_t mpi_reply, *facts;
|
|
+ Mpi2IOCFactsReply_t mpi_reply;
|
|
+ struct mpt2sas_facts *facts;
|
|
int mpi_reply_sz, mpi_request_sz, r;
|
|
|
|
dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
|
|
@@ -3225,17 +3229,6 @@ _base_send_ioc_init(struct MPT2SAS_ADAPTER *ioc, int sleep_flag)
|
|
mpi_request.MsgVersion = cpu_to_le16(MPI2_VERSION);
|
|
mpi_request.HeaderVersion = cpu_to_le16(MPI2_HEADER_VERSION);
|
|
|
|
- /* In MPI Revision I (0xA), the SystemReplyFrameSize(offset 0x18) was
|
|
- * removed and made reserved. For those with older firmware will need
|
|
- * this fix. It was decided that the Reply and Request frame sizes are
|
|
- * the same.
|
|
- */
|
|
- if ((ioc->facts.HeaderVersion >> 8) < 0xA) {
|
|
- mpi_request.Reserved7 = cpu_to_le16(ioc->reply_sz);
|
|
-/* mpi_request.SystemReplyFrameSize =
|
|
- * cpu_to_le16(ioc->reply_sz);
|
|
- */
|
|
- }
|
|
|
|
mpi_request.SystemRequestFrameSize = cpu_to_le16(ioc->request_sz/4);
|
|
mpi_request.ReplyDescriptorPostQueueDepth =
|
|
@@ -3243,25 +3236,17 @@ _base_send_ioc_init(struct MPT2SAS_ADAPTER *ioc, int sleep_flag)
|
|
mpi_request.ReplyFreeQueueDepth =
|
|
cpu_to_le16(ioc->reply_free_queue_depth);
|
|
|
|
-#if BITS_PER_LONG > 32
|
|
mpi_request.SenseBufferAddressHigh =
|
|
- cpu_to_le32(ioc->sense_dma >> 32);
|
|
+ cpu_to_le32((u64)ioc->sense_dma >> 32);
|
|
mpi_request.SystemReplyAddressHigh =
|
|
- cpu_to_le32(ioc->reply_dma >> 32);
|
|
+ cpu_to_le32((u64)ioc->reply_dma >> 32);
|
|
mpi_request.SystemRequestFrameBaseAddress =
|
|
- cpu_to_le64(ioc->request_dma);
|
|
+ cpu_to_le64((u64)ioc->request_dma);
|
|
mpi_request.ReplyFreeQueueAddress =
|
|
- cpu_to_le64(ioc->reply_free_dma);
|
|
+ cpu_to_le64((u64)ioc->reply_free_dma);
|
|
mpi_request.ReplyDescriptorPostQueueAddress =
|
|
- cpu_to_le64(ioc->reply_post_free_dma);
|
|
-#else
|
|
- mpi_request.SystemRequestFrameBaseAddress =
|
|
- cpu_to_le32(ioc->request_dma);
|
|
- mpi_request.ReplyFreeQueueAddress =
|
|
- cpu_to_le32(ioc->reply_free_dma);
|
|
- mpi_request.ReplyDescriptorPostQueueAddress =
|
|
- cpu_to_le32(ioc->reply_post_free_dma);
|
|
-#endif
|
|
+ cpu_to_le64((u64)ioc->reply_post_free_dma);
|
|
+
|
|
|
|
/* This time stamp specifies number of milliseconds
|
|
* since epoch ~ midnight January 1, 1970.
|
|
@@ -3271,10 +3256,10 @@ _base_send_ioc_init(struct MPT2SAS_ADAPTER *ioc, int sleep_flag)
|
|
(current_time.tv_usec / 1000));
|
|
|
|
if (ioc->logging_level & MPT_DEBUG_INIT) {
|
|
- u32 *mfp;
|
|
+ __le32 *mfp;
|
|
int i;
|
|
|
|
- mfp = (u32 *)&mpi_request;
|
|
+ mfp = (__le32 *)&mpi_request;
|
|
printk(KERN_INFO "\toffset:data\n");
|
|
for (i = 0; i < sizeof(Mpi2IOCInitRequest_t)/4; i++)
|
|
printk(KERN_INFO "\t[0x%02x]:%08x\n", i*4,
|
|
@@ -3759,7 +3744,7 @@ _base_make_ioc_operational(struct MPT2SAS_ADAPTER *ioc, int sleep_flag)
|
|
|
|
/* initialize Reply Post Free Queue */
|
|
for (i = 0; i < ioc->reply_post_queue_depth; i++)
|
|
- ioc->reply_post_free[i].Words = ULLONG_MAX;
|
|
+ ioc->reply_post_free[i].Words = cpu_to_le64(ULLONG_MAX);
|
|
|
|
r = _base_send_ioc_init(ioc, sleep_flag);
|
|
if (r)
|
|
diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.h b/drivers/scsi/mpt2sas/mpt2sas_base.h
|
|
index dcc289c..451dc1c 100644
|
|
--- a/drivers/scsi/mpt2sas/mpt2sas_base.h
|
|
+++ b/drivers/scsi/mpt2sas/mpt2sas_base.h
|
|
@@ -541,6 +541,53 @@ struct _tr_list {
|
|
|
|
typedef void (*MPT_ADD_SGE)(void *paddr, u32 flags_length, dma_addr_t dma_addr);
|
|
|
|
+/* IOC Facts and Port Facts converted from little endian to cpu */
|
|
+union mpi2_version_union {
|
|
+ MPI2_VERSION_STRUCT Struct;
|
|
+ u32 Word;
|
|
+};
|
|
+
|
|
+struct mpt2sas_facts {
|
|
+ u16 MsgVersion;
|
|
+ u16 HeaderVersion;
|
|
+ u8 IOCNumber;
|
|
+ u8 VP_ID;
|
|
+ u8 VF_ID;
|
|
+ u16 IOCExceptions;
|
|
+ u16 IOCStatus;
|
|
+ u32 IOCLogInfo;
|
|
+ u8 MaxChainDepth;
|
|
+ u8 WhoInit;
|
|
+ u8 NumberOfPorts;
|
|
+ u8 MaxMSIxVectors;
|
|
+ u16 RequestCredit;
|
|
+ u16 ProductID;
|
|
+ u32 IOCCapabilities;
|
|
+ union mpi2_version_union FWVersion;
|
|
+ u16 IOCRequestFrameSize;
|
|
+ u16 Reserved3;
|
|
+ u16 MaxInitiators;
|
|
+ u16 MaxTargets;
|
|
+ u16 MaxSasExpanders;
|
|
+ u16 MaxEnclosures;
|
|
+ u16 ProtocolFlags;
|
|
+ u16 HighPriorityCredit;
|
|
+ u16 MaxReplyDescriptorPostQueueDepth;
|
|
+ u8 ReplyFrameSize;
|
|
+ u8 MaxVolumes;
|
|
+ u16 MaxDevHandle;
|
|
+ u16 MaxPersistentEntries;
|
|
+ u16 MinDevHandle;
|
|
+};
|
|
+
|
|
+struct mpt2sas_port_facts {
|
|
+ u8 PortNumber;
|
|
+ u8 VP_ID;
|
|
+ u8 VF_ID;
|
|
+ u8 PortType;
|
|
+ u16 MaxPostedCmdBuffers;
|
|
+};
|
|
+
|
|
/**
|
|
* struct MPT2SAS_ADAPTER - per adapter struct
|
|
* @list: ioc_list
|
|
@@ -749,8 +796,8 @@ struct MPT2SAS_ADAPTER {
|
|
u32 event_masks[MPI2_EVENT_NOTIFY_EVENTMASK_WORDS];
|
|
|
|
/* static config pages */
|
|
- Mpi2IOCFactsReply_t facts;
|
|
- Mpi2PortFactsReply_t *pfacts;
|
|
+ struct mpt2sas_facts facts;
|
|
+ struct mpt2sas_port_facts *pfacts;
|
|
Mpi2ManufacturingPage0_t manu_pg0;
|
|
Mpi2BiosPage2_t bios_pg2;
|
|
Mpi2BiosPage3_t bios_pg3;
|
|
@@ -840,7 +887,7 @@ struct MPT2SAS_ADAPTER {
|
|
|
|
/* reply free queue */
|
|
u16 reply_free_queue_depth;
|
|
- u32 *reply_free;
|
|
+ __le32 *reply_free;
|
|
dma_addr_t reply_free_dma;
|
|
struct dma_pool *reply_free_dma_pool;
|
|
u32 reply_free_host_index;
|
|
diff --git a/drivers/scsi/mpt2sas/mpt2sas_ctl.c b/drivers/scsi/mpt2sas/mpt2sas_ctl.c
|
|
index 437c2d9..d1c3bba 100644
|
|
--- a/drivers/scsi/mpt2sas/mpt2sas_ctl.c
|
|
+++ b/drivers/scsi/mpt2sas/mpt2sas_ctl.c
|
|
@@ -2706,13 +2706,13 @@ static DEVICE_ATTR(ioc_reset_count, S_IRUGO,
|
|
_ctl_ioc_reset_count_show, NULL);
|
|
|
|
struct DIAG_BUFFER_START {
|
|
- u32 Size;
|
|
- u32 DiagVersion;
|
|
+ __le32 Size;
|
|
+ __le32 DiagVersion;
|
|
u8 BufferType;
|
|
u8 Reserved[3];
|
|
- u32 Reserved1;
|
|
- u32 Reserved2;
|
|
- u32 Reserved3;
|
|
+ __le32 Reserved1;
|
|
+ __le32 Reserved2;
|
|
+ __le32 Reserved3;
|
|
};
|
|
/**
|
|
* _ctl_host_trace_buffer_size_show - host buffer size (trace only)
|
|
diff --git a/drivers/scsi/mpt2sas/mpt2sas_debug.h b/drivers/scsi/mpt2sas/mpt2sas_debug.h
|
|
index 3dcddfe..9731f8e 100644
|
|
--- a/drivers/scsi/mpt2sas/mpt2sas_debug.h
|
|
+++ b/drivers/scsi/mpt2sas/mpt2sas_debug.h
|
|
@@ -164,7 +164,7 @@ static inline void
|
|
_debug_dump_mf(void *mpi_request, int sz)
|
|
{
|
|
int i;
|
|
- u32 *mfp = (u32 *)mpi_request;
|
|
+ __le32 *mfp = (__le32 *)mpi_request;
|
|
|
|
printk(KERN_INFO "mf:\n\t");
|
|
for (i = 0; i < sz; i++) {
|
|
diff --git a/drivers/scsi/mpt2sas/mpt2sas_scsih.c b/drivers/scsi/mpt2sas/mpt2sas_scsih.c
|
|
index a7dbc68..e327a3c 100644
|
|
--- a/drivers/scsi/mpt2sas/mpt2sas_scsih.c
|
|
+++ b/drivers/scsi/mpt2sas/mpt2sas_scsih.c
|
|
@@ -1956,7 +1956,7 @@ _scsih_slave_configure(struct scsi_device *sdev)
|
|
case MPI2_RAID_VOL_TYPE_RAID1E:
|
|
qdepth = MPT2SAS_RAID_QUEUE_DEPTH;
|
|
if (ioc->manu_pg10.OEMIdentifier &&
|
|
- (ioc->manu_pg10.GenericFlags0 &
|
|
+ (le32_to_cpu(ioc->manu_pg10.GenericFlags0) &
|
|
MFG10_GF0_R10_DISPLAY) &&
|
|
!(raid_device->num_pds % 2))
|
|
r_level = "RAID10";
|
|
@@ -4598,7 +4598,7 @@ _scsih_expander_add(struct MPT2SAS_ADAPTER *ioc, u16 handle)
|
|
Mpi2SasEnclosurePage0_t enclosure_pg0;
|
|
u32 ioc_status;
|
|
u16 parent_handle;
|
|
- __le64 sas_address, sas_address_parent = 0;
|
|
+ u64 sas_address, sas_address_parent = 0;
|
|
int i;
|
|
unsigned long flags;
|
|
struct _sas_port *mpt2sas_port = NULL;
|
|
@@ -5404,7 +5404,7 @@ _scsih_sas_device_status_change_event(struct MPT2SAS_ADAPTER *ioc,
|
|
{
|
|
struct MPT2SAS_TARGET *target_priv_data;
|
|
struct _sas_device *sas_device;
|
|
- __le64 sas_address;
|
|
+ u64 sas_address;
|
|
unsigned long flags;
|
|
Mpi2EventDataSasDeviceStatusChange_t *event_data =
|
|
fw_event->event_data;
|
|
@@ -6566,7 +6566,7 @@ _scsih_search_responding_expanders(struct MPT2SAS_ADAPTER *ioc)
|
|
Mpi2ExpanderPage0_t expander_pg0;
|
|
Mpi2ConfigReply_t mpi_reply;
|
|
u16 ioc_status;
|
|
- __le64 sas_address;
|
|
+ u64 sas_address;
|
|
u16 handle;
|
|
|
|
printk(MPT2SAS_INFO_FMT "%s\n", ioc->name, __func__);
|
|
@@ -7505,7 +7505,7 @@ _scsih_suspend(struct pci_dev *pdev, pm_message_t state)
|
|
{
|
|
struct Scsi_Host *shost = pci_get_drvdata(pdev);
|
|
struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
|
|
- u32 device_state;
|
|
+ pci_power_t device_state;
|
|
|
|
mpt2sas_base_stop_watchdog(ioc);
|
|
scsi_block_requests(shost);
|
|
@@ -7532,7 +7532,7 @@ _scsih_resume(struct pci_dev *pdev)
|
|
{
|
|
struct Scsi_Host *shost = pci_get_drvdata(pdev);
|
|
struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
|
|
- u32 device_state = pdev->current_state;
|
|
+ pci_power_t device_state = pdev->current_state;
|
|
int r;
|
|
|
|
printk(MPT2SAS_INFO_FMT "pdev=0x%p, slot=%s, previous "
|
|
diff --git a/drivers/scsi/mpt2sas/mpt2sas_transport.c b/drivers/scsi/mpt2sas/mpt2sas_transport.c
|
|
index cb1cdec..15c7980 100644
|
|
--- a/drivers/scsi/mpt2sas/mpt2sas_transport.c
|
|
+++ b/drivers/scsi/mpt2sas/mpt2sas_transport.c
|
|
@@ -299,7 +299,6 @@ _transport_expander_report_manufacture(struct MPT2SAS_ADAPTER *ioc,
|
|
void *data_out = NULL;
|
|
dma_addr_t data_out_dma;
|
|
u32 sz;
|
|
- u64 *sas_address_le;
|
|
u16 wait_state_count;
|
|
|
|
if (ioc->shost_recovery || ioc->pci_error_recovery) {
|
|
@@ -372,8 +371,7 @@ _transport_expander_report_manufacture(struct MPT2SAS_ADAPTER *ioc,
|
|
mpi_request->PhysicalPort = 0xFF;
|
|
mpi_request->VF_ID = 0; /* TODO */
|
|
mpi_request->VP_ID = 0;
|
|
- sas_address_le = (u64 *)&mpi_request->SASAddress;
|
|
- *sas_address_le = cpu_to_le64(sas_address);
|
|
+ mpi_request->SASAddress = cpu_to_le64(sas_address);
|
|
mpi_request->RequestDataLength =
|
|
cpu_to_le16(sizeof(struct rep_manu_request));
|
|
psge = &mpi_request->SGL;
|
|
@@ -1049,14 +1047,14 @@ struct phy_error_log_reply{
|
|
u8 function; /* 0x11 */
|
|
u8 function_result;
|
|
u8 response_length;
|
|
- u16 expander_change_count;
|
|
+ __be16 expander_change_count;
|
|
u8 reserved_1[3];
|
|
u8 phy_identifier;
|
|
u8 reserved_2[2];
|
|
- u32 invalid_dword;
|
|
- u32 running_disparity_error;
|
|
- u32 loss_of_dword_sync;
|
|
- u32 phy_reset_problem;
|
|
+ __be32 invalid_dword;
|
|
+ __be32 running_disparity_error;
|
|
+ __be32 loss_of_dword_sync;
|
|
+ __be32 phy_reset_problem;
|
|
};
|
|
|
|
/**
|
|
@@ -1085,7 +1083,6 @@ _transport_get_expander_phy_error_log(struct MPT2SAS_ADAPTER *ioc,
|
|
void *data_out = NULL;
|
|
dma_addr_t data_out_dma;
|
|
u32 sz;
|
|
- u64 *sas_address_le;
|
|
u16 wait_state_count;
|
|
|
|
if (ioc->shost_recovery || ioc->pci_error_recovery) {
|
|
@@ -1160,8 +1157,7 @@ _transport_get_expander_phy_error_log(struct MPT2SAS_ADAPTER *ioc,
|
|
mpi_request->PhysicalPort = 0xFF;
|
|
mpi_request->VF_ID = 0; /* TODO */
|
|
mpi_request->VP_ID = 0;
|
|
- sas_address_le = (u64 *)&mpi_request->SASAddress;
|
|
- *sas_address_le = cpu_to_le64(phy->identify.sas_address);
|
|
+ mpi_request->SASAddress = cpu_to_le64(phy->identify.sas_address);
|
|
mpi_request->RequestDataLength =
|
|
cpu_to_le16(sizeof(struct phy_error_log_request));
|
|
psge = &mpi_request->SGL;
|
|
@@ -1406,7 +1402,6 @@ _transport_expander_phy_control(struct MPT2SAS_ADAPTER *ioc,
|
|
void *data_out = NULL;
|
|
dma_addr_t data_out_dma;
|
|
u32 sz;
|
|
- u64 *sas_address_le;
|
|
u16 wait_state_count;
|
|
|
|
if (ioc->shost_recovery) {
|
|
@@ -1486,8 +1481,7 @@ _transport_expander_phy_control(struct MPT2SAS_ADAPTER *ioc,
|
|
mpi_request->PhysicalPort = 0xFF;
|
|
mpi_request->VF_ID = 0; /* TODO */
|
|
mpi_request->VP_ID = 0;
|
|
- sas_address_le = (u64 *)&mpi_request->SASAddress;
|
|
- *sas_address_le = cpu_to_le64(phy->identify.sas_address);
|
|
+ mpi_request->SASAddress = cpu_to_le64(phy->identify.sas_address);
|
|
mpi_request->RequestDataLength =
|
|
cpu_to_le16(sizeof(struct phy_error_log_request));
|
|
psge = &mpi_request->SGL;
|
|
@@ -1914,7 +1908,7 @@ _transport_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy,
|
|
mpi_request->PhysicalPort = 0xFF;
|
|
mpi_request->VF_ID = 0; /* TODO */
|
|
mpi_request->VP_ID = 0;
|
|
- *((u64 *)&mpi_request->SASAddress) = (rphy) ?
|
|
+ mpi_request->SASAddress = (rphy) ?
|
|
cpu_to_le64(rphy->identify.sas_address) :
|
|
cpu_to_le64(ioc->sas_hba.sas_address);
|
|
mpi_request->RequestDataLength = cpu_to_le16(blk_rq_bytes(req) - 4);
|
|
diff --git a/drivers/staging/ath6kl/os/linux/ar6000_drv.c b/drivers/staging/ath6kl/os/linux/ar6000_drv.c
|
|
index aa97efc..62487a7 100644
|
|
--- a/drivers/staging/ath6kl/os/linux/ar6000_drv.c
|
|
+++ b/drivers/staging/ath6kl/os/linux/ar6000_drv.c
|
|
@@ -6198,6 +6198,7 @@ int ar6000_create_ap_interface(struct ar6_softc *ar, char *ap_ifname)
|
|
|
|
ether_setup(dev);
|
|
init_netdev(dev, ap_ifname);
|
|
+ dev->priv_flags &= ~IFF_TX_SKB_SHARING;
|
|
|
|
if (register_netdev(dev)) {
|
|
AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("ar6000_create_ap_interface: register_netdev failed\n"));
|
|
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
|
|
index bc4b12c..fc7e57b 100644
|
|
--- a/fs/cifs/cifsfs.c
|
|
+++ b/fs/cifs/cifsfs.c
|
|
@@ -581,6 +581,10 @@ cifs_get_root(struct smb_vol *vol, struct super_block *sb)
|
|
mutex_unlock(&dir->i_mutex);
|
|
dput(dentry);
|
|
dentry = child;
|
|
+ if (!dentry->d_inode) {
|
|
+ dput(dentry);
|
|
+ dentry = ERR_PTR(-ENOENT);
|
|
+ }
|
|
} while (!IS_ERR(dentry));
|
|
_FreeXid(xid);
|
|
kfree(full_path);
|
|
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
|
|
index 9b018c8..a7b2dcd 100644
|
|
--- a/fs/cifs/inode.c
|
|
+++ b/fs/cifs/inode.c
|
|
@@ -764,20 +764,10 @@ char *cifs_build_path_to_root(struct smb_vol *vol, struct cifs_sb_info *cifs_sb,
|
|
if (full_path == NULL)
|
|
return full_path;
|
|
|
|
- if (dfsplen) {
|
|
+ if (dfsplen)
|
|
strncpy(full_path, tcon->treeName, dfsplen);
|
|
- /* switch slash direction in prepath depending on whether
|
|
- * windows or posix style path names
|
|
- */
|
|
- if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS) {
|
|
- int i;
|
|
- for (i = 0; i < dfsplen; i++) {
|
|
- if (full_path[i] == '\\')
|
|
- full_path[i] = '/';
|
|
- }
|
|
- }
|
|
- }
|
|
strncpy(full_path + dfsplen, vol->prepath, pplen);
|
|
+ convert_delimiter(full_path, CIFS_DIR_SEP(cifs_sb));
|
|
full_path[dfsplen + pplen] = 0; /* add trailing null */
|
|
return full_path;
|
|
}
|
|
diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c
|
|
index 147aa22..c1b9c4b 100644
|
|
--- a/fs/cifs/transport.c
|
|
+++ b/fs/cifs/transport.c
|
|
@@ -362,6 +362,8 @@ cifs_call_async(struct TCP_Server_Info *server, struct kvec *iov,
|
|
mid = AllocMidQEntry(hdr, server);
|
|
if (mid == NULL) {
|
|
mutex_unlock(&server->srv_mutex);
|
|
+ atomic_dec(&server->inFlight);
|
|
+ wake_up(&server->request_q);
|
|
return -ENOMEM;
|
|
}
|
|
|
|
diff --git a/fs/ecryptfs/main.c b/fs/ecryptfs/main.c
|
|
index 9f1bb74..b4a6bef 100644
|
|
--- a/fs/ecryptfs/main.c
|
|
+++ b/fs/ecryptfs/main.c
|
|
@@ -175,6 +175,7 @@ enum { ecryptfs_opt_sig, ecryptfs_opt_ecryptfs_sig,
|
|
ecryptfs_opt_encrypted_view, ecryptfs_opt_fnek_sig,
|
|
ecryptfs_opt_fn_cipher, ecryptfs_opt_fn_cipher_key_bytes,
|
|
ecryptfs_opt_unlink_sigs, ecryptfs_opt_mount_auth_tok_only,
|
|
+ ecryptfs_opt_check_dev_ruid,
|
|
ecryptfs_opt_err };
|
|
|
|
static const match_table_t tokens = {
|
|
@@ -191,6 +192,7 @@ static const match_table_t tokens = {
|
|
{ecryptfs_opt_fn_cipher_key_bytes, "ecryptfs_fn_key_bytes=%u"},
|
|
{ecryptfs_opt_unlink_sigs, "ecryptfs_unlink_sigs"},
|
|
{ecryptfs_opt_mount_auth_tok_only, "ecryptfs_mount_auth_tok_only"},
|
|
+ {ecryptfs_opt_check_dev_ruid, "ecryptfs_check_dev_ruid"},
|
|
{ecryptfs_opt_err, NULL}
|
|
};
|
|
|
|
@@ -236,6 +238,7 @@ static void ecryptfs_init_mount_crypt_stat(
|
|
* ecryptfs_parse_options
|
|
* @sb: The ecryptfs super block
|
|
* @options: The options passed to the kernel
|
|
+ * @check_ruid: set to 1 if device uid should be checked against the ruid
|
|
*
|
|
* Parse mount options:
|
|
* debug=N - ecryptfs_verbosity level for debug output
|
|
@@ -251,7 +254,8 @@ static void ecryptfs_init_mount_crypt_stat(
|
|
*
|
|
* Returns zero on success; non-zero on error
|
|
*/
|
|
-static int ecryptfs_parse_options(struct ecryptfs_sb_info *sbi, char *options)
|
|
+static int ecryptfs_parse_options(struct ecryptfs_sb_info *sbi, char *options,
|
|
+ uid_t *check_ruid)
|
|
{
|
|
char *p;
|
|
int rc = 0;
|
|
@@ -276,6 +280,8 @@ static int ecryptfs_parse_options(struct ecryptfs_sb_info *sbi, char *options)
|
|
char *cipher_key_bytes_src;
|
|
char *fn_cipher_key_bytes_src;
|
|
|
|
+ *check_ruid = 0;
|
|
+
|
|
if (!options) {
|
|
rc = -EINVAL;
|
|
goto out;
|
|
@@ -380,6 +386,9 @@ static int ecryptfs_parse_options(struct ecryptfs_sb_info *sbi, char *options)
|
|
mount_crypt_stat->flags |=
|
|
ECRYPTFS_GLOBAL_MOUNT_AUTH_TOK_ONLY;
|
|
break;
|
|
+ case ecryptfs_opt_check_dev_ruid:
|
|
+ *check_ruid = 1;
|
|
+ break;
|
|
case ecryptfs_opt_err:
|
|
default:
|
|
printk(KERN_WARNING
|
|
@@ -475,6 +484,7 @@ static struct dentry *ecryptfs_mount(struct file_system_type *fs_type, int flags
|
|
const char *err = "Getting sb failed";
|
|
struct inode *inode;
|
|
struct path path;
|
|
+ uid_t check_ruid;
|
|
int rc;
|
|
|
|
sbi = kmem_cache_zalloc(ecryptfs_sb_info_cache, GFP_KERNEL);
|
|
@@ -483,7 +493,7 @@ static struct dentry *ecryptfs_mount(struct file_system_type *fs_type, int flags
|
|
goto out;
|
|
}
|
|
|
|
- rc = ecryptfs_parse_options(sbi, raw_data);
|
|
+ rc = ecryptfs_parse_options(sbi, raw_data, &check_ruid);
|
|
if (rc) {
|
|
err = "Error parsing options";
|
|
goto out;
|
|
@@ -521,6 +531,15 @@ static struct dentry *ecryptfs_mount(struct file_system_type *fs_type, int flags
|
|
"known incompatibilities\n");
|
|
goto out_free;
|
|
}
|
|
+
|
|
+ if (check_ruid && path.dentry->d_inode->i_uid != current_uid()) {
|
|
+ rc = -EPERM;
|
|
+ printk(KERN_ERR "Mount of device (uid: %d) not owned by "
|
|
+ "requested user (uid: %d)\n",
|
|
+ path.dentry->d_inode->i_uid, current_uid());
|
|
+ goto out_free;
|
|
+ }
|
|
+
|
|
ecryptfs_set_superblock_lower(s, path.dentry->d_sb);
|
|
s->s_maxbytes = path.dentry->d_sb->s_maxbytes;
|
|
s->s_blocksize = path.dentry->d_sb->s_blocksize;
|
|
diff --git a/fs/ecryptfs/read_write.c b/fs/ecryptfs/read_write.c
|
|
index 85d4309..3745f7c 100644
|
|
--- a/fs/ecryptfs/read_write.c
|
|
+++ b/fs/ecryptfs/read_write.c
|
|
@@ -39,15 +39,16 @@
|
|
int ecryptfs_write_lower(struct inode *ecryptfs_inode, char *data,
|
|
loff_t offset, size_t size)
|
|
{
|
|
- struct ecryptfs_inode_info *inode_info;
|
|
+ struct file *lower_file;
|
|
mm_segment_t fs_save;
|
|
ssize_t rc;
|
|
|
|
- inode_info = ecryptfs_inode_to_private(ecryptfs_inode);
|
|
- BUG_ON(!inode_info->lower_file);
|
|
+ lower_file = ecryptfs_inode_to_private(ecryptfs_inode)->lower_file;
|
|
+ if (!lower_file)
|
|
+ return -EIO;
|
|
fs_save = get_fs();
|
|
set_fs(get_ds());
|
|
- rc = vfs_write(inode_info->lower_file, data, size, &offset);
|
|
+ rc = vfs_write(lower_file, data, size, &offset);
|
|
set_fs(fs_save);
|
|
mark_inode_dirty_sync(ecryptfs_inode);
|
|
return rc;
|
|
@@ -225,15 +226,16 @@ out:
|
|
int ecryptfs_read_lower(char *data, loff_t offset, size_t size,
|
|
struct inode *ecryptfs_inode)
|
|
{
|
|
- struct ecryptfs_inode_info *inode_info =
|
|
- ecryptfs_inode_to_private(ecryptfs_inode);
|
|
+ struct file *lower_file;
|
|
mm_segment_t fs_save;
|
|
ssize_t rc;
|
|
|
|
- BUG_ON(!inode_info->lower_file);
|
|
+ lower_file = ecryptfs_inode_to_private(ecryptfs_inode)->lower_file;
|
|
+ if (!lower_file)
|
|
+ return -EIO;
|
|
fs_save = get_fs();
|
|
set_fs(get_ds());
|
|
- rc = vfs_read(inode_info->lower_file, data, size, &offset);
|
|
+ rc = vfs_read(lower_file, data, size, &offset);
|
|
set_fs(fs_save);
|
|
return rc;
|
|
}
|
|
diff --git a/fs/ext3/namei.c b/fs/ext3/namei.c
|
|
index 34b6d9b..e5a7111 100644
|
|
--- a/fs/ext3/namei.c
|
|
+++ b/fs/ext3/namei.c
|
|
@@ -2210,9 +2210,11 @@ static int ext3_symlink (struct inode * dir,
|
|
/*
|
|
* For non-fast symlinks, we just allocate inode and put it on
|
|
* orphan list in the first transaction => we need bitmap,
|
|
- * group descriptor, sb, inode block, quota blocks.
|
|
+ * group descriptor, sb, inode block, quota blocks, and
|
|
+ * possibly selinux xattr blocks.
|
|
*/
|
|
- credits = 4 + EXT3_MAXQUOTAS_INIT_BLOCKS(dir->i_sb);
|
|
+ credits = 4 + EXT3_MAXQUOTAS_INIT_BLOCKS(dir->i_sb) +
|
|
+ EXT3_XATTR_TRANS_BLOCKS;
|
|
} else {
|
|
/*
|
|
* Fast symlink. We have to add entry to directory
|
|
diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
|
|
index b754b77..458a394 100644
|
|
--- a/fs/ext4/namei.c
|
|
+++ b/fs/ext4/namei.c
|
|
@@ -2264,9 +2264,11 @@ static int ext4_symlink(struct inode *dir,
|
|
/*
|
|
* For non-fast symlinks, we just allocate inode and put it on
|
|
* orphan list in the first transaction => we need bitmap,
|
|
- * group descriptor, sb, inode block, quota blocks.
|
|
+ * group descriptor, sb, inode block, quota blocks, and
|
|
+ * possibly selinux xattr blocks.
|
|
*/
|
|
- credits = 4 + EXT4_MAXQUOTAS_INIT_BLOCKS(dir->i_sb);
|
|
+ credits = 4 + EXT4_MAXQUOTAS_INIT_BLOCKS(dir->i_sb) +
|
|
+ EXT4_XATTR_TRANS_BLOCKS;
|
|
} else {
|
|
/*
|
|
* Fast symlink. We have to add entry to directory
|
|
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
|
|
index 33d12f8..0ec3687 100644
|
|
--- a/include/drm/drm_crtc.h
|
|
+++ b/include/drm/drm_crtc.h
|
|
@@ -802,6 +802,7 @@ extern struct drm_display_mode *drm_gtf_mode_complex(struct drm_device *dev,
|
|
extern int drm_add_modes_noedid(struct drm_connector *connector,
|
|
int hdisplay, int vdisplay);
|
|
|
|
+extern int drm_edid_header_is_valid(const u8 *raw_edid);
|
|
extern bool drm_edid_is_valid(struct edid *edid);
|
|
struct drm_display_mode *drm_mode_find_dmt(struct drm_device *dev,
|
|
int hsize, int vsize, int fresh);
|
|
diff --git a/include/drm/i915_drm.h b/include/drm/i915_drm.h
|
|
index c4d6dbf..28c0d11 100644
|
|
--- a/include/drm/i915_drm.h
|
|
+++ b/include/drm/i915_drm.h
|
|
@@ -237,7 +237,7 @@ typedef struct _drm_i915_sarea {
|
|
#define DRM_IOCTL_I915_GEM_GET_APERTURE DRM_IOR (DRM_COMMAND_BASE + DRM_I915_GEM_GET_APERTURE, struct drm_i915_gem_get_aperture)
|
|
#define DRM_IOCTL_I915_GET_PIPE_FROM_CRTC_ID DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GET_PIPE_FROM_CRTC_ID, struct drm_i915_get_pipe_from_crtc_id)
|
|
#define DRM_IOCTL_I915_GEM_MADVISE DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_MADVISE, struct drm_i915_gem_madvise)
|
|
-#define DRM_IOCTL_I915_OVERLAY_PUT_IMAGE DRM_IOW(DRM_COMMAND_BASE + DRM_IOCTL_I915_OVERLAY_ATTRS, struct drm_intel_overlay_put_image)
|
|
+#define DRM_IOCTL_I915_OVERLAY_PUT_IMAGE DRM_IOW(DRM_COMMAND_BASE + DRM_I915_OVERLAY_PUT_IMAGE, struct drm_intel_overlay_put_image)
|
|
#define DRM_IOCTL_I915_OVERLAY_ATTRS DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_OVERLAY_ATTRS, struct drm_intel_overlay_attrs)
|
|
|
|
/* Allow drivers to submit batchbuffers directly to hardware, relying
|
|
diff --git a/include/linux/cryptohash.h b/include/linux/cryptohash.h
|
|
index ec78a4b..d2984fb 100644
|
|
--- a/include/linux/cryptohash.h
|
|
+++ b/include/linux/cryptohash.h
|
|
@@ -8,6 +8,11 @@
|
|
void sha_init(__u32 *buf);
|
|
void sha_transform(__u32 *digest, const char *data, __u32 *W);
|
|
|
|
+#define MD5_DIGEST_WORDS 4
|
|
+#define MD5_MESSAGE_BYTES 64
|
|
+
|
|
+void md5_transform(__u32 *hash, __u32 const *in);
|
|
+
|
|
__u32 half_md4_transform(__u32 buf[4], __u32 const in[8]);
|
|
|
|
#endif
|
|
diff --git a/include/linux/if.h b/include/linux/if.h
|
|
index 3bc63e6..03489ca 100644
|
|
--- a/include/linux/if.h
|
|
+++ b/include/linux/if.h
|
|
@@ -76,6 +76,8 @@
|
|
#define IFF_BRIDGE_PORT 0x4000 /* device used as bridge port */
|
|
#define IFF_OVS_DATAPATH 0x8000 /* device used as Open vSwitch
|
|
* datapath port */
|
|
+#define IFF_TX_SKB_SHARING 0x10000 /* The interface supports sharing
|
|
+ * skbs on transmit */
|
|
|
|
#define IF_GET_IFACE 0x0001 /* for querying only */
|
|
#define IF_GET_PROTO 0x0002
|
|
diff --git a/include/linux/mm.h b/include/linux/mm.h
|
|
index 1036614..ec6e33d 100644
|
|
--- a/include/linux/mm.h
|
|
+++ b/include/linux/mm.h
|
|
@@ -959,6 +959,8 @@ int invalidate_inode_page(struct page *page);
|
|
#ifdef CONFIG_MMU
|
|
extern int handle_mm_fault(struct mm_struct *mm, struct vm_area_struct *vma,
|
|
unsigned long address, unsigned int flags);
|
|
+extern int fixup_user_fault(struct task_struct *tsk, struct mm_struct *mm,
|
|
+ unsigned long address, unsigned int fault_flags);
|
|
#else
|
|
static inline int handle_mm_fault(struct mm_struct *mm,
|
|
struct vm_area_struct *vma, unsigned long address,
|
|
@@ -968,6 +970,14 @@ static inline int handle_mm_fault(struct mm_struct *mm,
|
|
BUG();
|
|
return VM_FAULT_SIGBUS;
|
|
}
|
|
+static inline int fixup_user_fault(struct task_struct *tsk,
|
|
+ struct mm_struct *mm, unsigned long address,
|
|
+ unsigned int fault_flags)
|
|
+{
|
|
+ /* should never happen if there's no MMU */
|
|
+ BUG();
|
|
+ return -EFAULT;
|
|
+}
|
|
#endif
|
|
|
|
extern int make_pages_present(unsigned long addr, unsigned long end);
|
|
@@ -985,8 +995,6 @@ int get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
|
|
int get_user_pages_fast(unsigned long start, int nr_pages, int write,
|
|
struct page **pages);
|
|
struct page *get_dump_page(unsigned long addr);
|
|
-extern int fixup_user_fault(struct task_struct *tsk, struct mm_struct *mm,
|
|
- unsigned long address, unsigned int fault_flags);
|
|
|
|
extern int try_to_release_page(struct page * page, gfp_t gfp_mask);
|
|
extern void do_invalidatepage(struct page *page, unsigned long offset);
|
|
diff --git a/include/linux/random.h b/include/linux/random.h
|
|
index fb7ab9d..d13059f 100644
|
|
--- a/include/linux/random.h
|
|
+++ b/include/linux/random.h
|
|
@@ -57,17 +57,6 @@ extern void add_interrupt_randomness(int irq);
|
|
extern void get_random_bytes(void *buf, int nbytes);
|
|
void generate_random_uuid(unsigned char uuid_out[16]);
|
|
|
|
-extern __u32 secure_ip_id(__be32 daddr);
|
|
-extern u32 secure_ipv4_port_ephemeral(__be32 saddr, __be32 daddr, __be16 dport);
|
|
-extern u32 secure_ipv6_port_ephemeral(const __be32 *saddr, const __be32 *daddr,
|
|
- __be16 dport);
|
|
-extern __u32 secure_tcp_sequence_number(__be32 saddr, __be32 daddr,
|
|
- __be16 sport, __be16 dport);
|
|
-extern __u32 secure_tcpv6_sequence_number(__be32 *saddr, __be32 *daddr,
|
|
- __be16 sport, __be16 dport);
|
|
-extern u64 secure_dccp_sequence_number(__be32 saddr, __be32 daddr,
|
|
- __be16 sport, __be16 dport);
|
|
-
|
|
#ifndef MODULE
|
|
extern const struct file_operations random_fops, urandom_fops;
|
|
#endif
|
|
diff --git a/include/net/ipv6.h b/include/net/ipv6.h
|
|
index c033ed0..3b5ac1f 100644
|
|
--- a/include/net/ipv6.h
|
|
+++ b/include/net/ipv6.h
|
|
@@ -463,17 +463,7 @@ static inline int ipv6_addr_diff(const struct in6_addr *a1, const struct in6_add
|
|
return __ipv6_addr_diff(a1, a2, sizeof(struct in6_addr));
|
|
}
|
|
|
|
-static __inline__ void ipv6_select_ident(struct frag_hdr *fhdr)
|
|
-{
|
|
- static u32 ipv6_fragmentation_id = 1;
|
|
- static DEFINE_SPINLOCK(ip6_id_lock);
|
|
-
|
|
- spin_lock_bh(&ip6_id_lock);
|
|
- fhdr->identification = htonl(ipv6_fragmentation_id);
|
|
- if (++ipv6_fragmentation_id == 0)
|
|
- ipv6_fragmentation_id = 1;
|
|
- spin_unlock_bh(&ip6_id_lock);
|
|
-}
|
|
+extern void ipv6_select_ident(struct frag_hdr *fhdr, struct rt6_info *rt);
|
|
|
|
/*
|
|
* Prototypes exported by ipv6
|
|
diff --git a/include/net/secure_seq.h b/include/net/secure_seq.h
|
|
new file mode 100644
|
|
index 0000000..d97f689
|
|
--- /dev/null
|
|
+++ b/include/net/secure_seq.h
|
|
@@ -0,0 +1,20 @@
|
|
+#ifndef _NET_SECURE_SEQ
|
|
+#define _NET_SECURE_SEQ
|
|
+
|
|
+#include <linux/types.h>
|
|
+
|
|
+extern __u32 secure_ip_id(__be32 daddr);
|
|
+extern __u32 secure_ipv6_id(const __be32 daddr[4]);
|
|
+extern u32 secure_ipv4_port_ephemeral(__be32 saddr, __be32 daddr, __be16 dport);
|
|
+extern u32 secure_ipv6_port_ephemeral(const __be32 *saddr, const __be32 *daddr,
|
|
+ __be16 dport);
|
|
+extern __u32 secure_tcp_sequence_number(__be32 saddr, __be32 daddr,
|
|
+ __be16 sport, __be16 dport);
|
|
+extern __u32 secure_tcpv6_sequence_number(__be32 *saddr, __be32 *daddr,
|
|
+ __be16 sport, __be16 dport);
|
|
+extern u64 secure_dccp_sequence_number(__be32 saddr, __be32 daddr,
|
|
+ __be16 sport, __be16 dport);
|
|
+extern u64 secure_dccpv6_sequence_number(__be32 *saddr, __be32 *daddr,
|
|
+ __be16 sport, __be16 dport);
|
|
+
|
|
+#endif /* _NET_SECURE_SEQ */
|
|
diff --git a/include/net/transp_v6.h b/include/net/transp_v6.h
|
|
index 5271a74..45ce307 100644
|
|
--- a/include/net/transp_v6.h
|
|
+++ b/include/net/transp_v6.h
|
|
@@ -14,6 +14,8 @@ extern struct proto tcpv6_prot;
|
|
|
|
struct flowi6;
|
|
|
|
+extern void initialize_hashidentrnd(void);
|
|
+
|
|
/* extension headers */
|
|
extern int ipv6_exthdrs_init(void);
|
|
extern void ipv6_exthdrs_exit(void);
|
|
diff --git a/include/xen/interface/xen.h b/include/xen/interface/xen.h
|
|
index 70213b4..6acd9ce 100644
|
|
--- a/include/xen/interface/xen.h
|
|
+++ b/include/xen/interface/xen.h
|
|
@@ -450,6 +450,45 @@ struct start_info {
|
|
int8_t cmd_line[MAX_GUEST_CMDLINE];
|
|
};
|
|
|
|
+struct dom0_vga_console_info {
|
|
+ uint8_t video_type;
|
|
+#define XEN_VGATYPE_TEXT_MODE_3 0x03
|
|
+#define XEN_VGATYPE_VESA_LFB 0x23
|
|
+
|
|
+ union {
|
|
+ struct {
|
|
+ /* Font height, in pixels. */
|
|
+ uint16_t font_height;
|
|
+ /* Cursor location (column, row). */
|
|
+ uint16_t cursor_x, cursor_y;
|
|
+ /* Number of rows and columns (dimensions in characters). */
|
|
+ uint16_t rows, columns;
|
|
+ } text_mode_3;
|
|
+
|
|
+ struct {
|
|
+ /* Width and height, in pixels. */
|
|
+ uint16_t width, height;
|
|
+ /* Bytes per scan line. */
|
|
+ uint16_t bytes_per_line;
|
|
+ /* Bits per pixel. */
|
|
+ uint16_t bits_per_pixel;
|
|
+ /* LFB physical address, and size (in units of 64kB). */
|
|
+ uint32_t lfb_base;
|
|
+ uint32_t lfb_size;
|
|
+ /* RGB mask offsets and sizes, as defined by VBE 1.2+ */
|
|
+ uint8_t red_pos, red_size;
|
|
+ uint8_t green_pos, green_size;
|
|
+ uint8_t blue_pos, blue_size;
|
|
+ uint8_t rsvd_pos, rsvd_size;
|
|
+
|
|
+ /* VESA capabilities (offset 0xa, VESA command 0x4f00). */
|
|
+ uint32_t gbl_caps;
|
|
+ /* Mode attributes (offset 0x0, VESA command 0x4f01). */
|
|
+ uint16_t mode_attrs;
|
|
+ } vesa_lfb;
|
|
+ } u;
|
|
+};
|
|
+
|
|
/* These flags are passed in the 'flags' field of start_info_t. */
|
|
#define SIF_PRIVILEGED (1<<0) /* Is the domain privileged? */
|
|
#define SIF_INITDOMAIN (1<<1) /* Is this the initial control domain? */
|
|
diff --git a/kernel/futex.c b/kernel/futex.c
|
|
index 7a0a4ed..8b6da25 100644
|
|
--- a/kernel/futex.c
|
|
+++ b/kernel/futex.c
|
|
@@ -218,6 +218,8 @@ static void drop_futex_key_refs(union futex_key *key)
|
|
* @uaddr: virtual address of the futex
|
|
* @fshared: 0 for a PROCESS_PRIVATE futex, 1 for PROCESS_SHARED
|
|
* @key: address where result is stored.
|
|
+ * @rw: mapping needs to be read/write (values: VERIFY_READ,
|
|
+ * VERIFY_WRITE)
|
|
*
|
|
* Returns a negative error code or 0
|
|
* The key words are stored in *key on success.
|
|
@@ -229,12 +231,12 @@ static void drop_futex_key_refs(union futex_key *key)
|
|
* lock_page() might sleep, the caller should not hold a spinlock.
|
|
*/
|
|
static int
|
|
-get_futex_key(u32 __user *uaddr, int fshared, union futex_key *key)
|
|
+get_futex_key(u32 __user *uaddr, int fshared, union futex_key *key, int rw)
|
|
{
|
|
unsigned long address = (unsigned long)uaddr;
|
|
struct mm_struct *mm = current->mm;
|
|
struct page *page, *page_head;
|
|
- int err;
|
|
+ int err, ro = 0;
|
|
|
|
/*
|
|
* The futex address must be "naturally" aligned.
|
|
@@ -262,8 +264,18 @@ get_futex_key(u32 __user *uaddr, int fshared, union futex_key *key)
|
|
|
|
again:
|
|
err = get_user_pages_fast(address, 1, 1, &page);
|
|
+ /*
|
|
+ * If write access is not required (eg. FUTEX_WAIT), try
|
|
+ * and get read-only access.
|
|
+ */
|
|
+ if (err == -EFAULT && rw == VERIFY_READ) {
|
|
+ err = get_user_pages_fast(address, 1, 0, &page);
|
|
+ ro = 1;
|
|
+ }
|
|
if (err < 0)
|
|
return err;
|
|
+ else
|
|
+ err = 0;
|
|
|
|
#ifdef CONFIG_TRANSPARENT_HUGEPAGE
|
|
page_head = page;
|
|
@@ -305,6 +317,13 @@ again:
|
|
if (!page_head->mapping) {
|
|
unlock_page(page_head);
|
|
put_page(page_head);
|
|
+ /*
|
|
+ * ZERO_PAGE pages don't have a mapping. Avoid a busy loop
|
|
+ * trying to find one. RW mapping would have COW'd (and thus
|
|
+ * have a mapping) so this page is RO and won't ever change.
|
|
+ */
|
|
+ if ((page_head == ZERO_PAGE(address)))
|
|
+ return -EFAULT;
|
|
goto again;
|
|
}
|
|
|
|
@@ -316,6 +335,15 @@ again:
|
|
* the object not the particular process.
|
|
*/
|
|
if (PageAnon(page_head)) {
|
|
+ /*
|
|
+ * A RO anonymous page will never change and thus doesn't make
|
|
+ * sense for futex operations.
|
|
+ */
|
|
+ if (ro) {
|
|
+ err = -EFAULT;
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
key->both.offset |= FUT_OFF_MMSHARED; /* ref taken on mm */
|
|
key->private.mm = mm;
|
|
key->private.address = address;
|
|
@@ -327,9 +355,10 @@ again:
|
|
|
|
get_futex_key_refs(key);
|
|
|
|
+out:
|
|
unlock_page(page_head);
|
|
put_page(page_head);
|
|
- return 0;
|
|
+ return err;
|
|
}
|
|
|
|
static inline void put_futex_key(union futex_key *key)
|
|
@@ -940,7 +969,7 @@ futex_wake(u32 __user *uaddr, unsigned int flags, int nr_wake, u32 bitset)
|
|
if (!bitset)
|
|
return -EINVAL;
|
|
|
|
- ret = get_futex_key(uaddr, flags & FLAGS_SHARED, &key);
|
|
+ ret = get_futex_key(uaddr, flags & FLAGS_SHARED, &key, VERIFY_READ);
|
|
if (unlikely(ret != 0))
|
|
goto out;
|
|
|
|
@@ -986,10 +1015,10 @@ futex_wake_op(u32 __user *uaddr1, unsigned int flags, u32 __user *uaddr2,
|
|
int ret, op_ret;
|
|
|
|
retry:
|
|
- ret = get_futex_key(uaddr1, flags & FLAGS_SHARED, &key1);
|
|
+ ret = get_futex_key(uaddr1, flags & FLAGS_SHARED, &key1, VERIFY_READ);
|
|
if (unlikely(ret != 0))
|
|
goto out;
|
|
- ret = get_futex_key(uaddr2, flags & FLAGS_SHARED, &key2);
|
|
+ ret = get_futex_key(uaddr2, flags & FLAGS_SHARED, &key2, VERIFY_WRITE);
|
|
if (unlikely(ret != 0))
|
|
goto out_put_key1;
|
|
|
|
@@ -1243,10 +1272,11 @@ retry:
|
|
pi_state = NULL;
|
|
}
|
|
|
|
- ret = get_futex_key(uaddr1, flags & FLAGS_SHARED, &key1);
|
|
+ ret = get_futex_key(uaddr1, flags & FLAGS_SHARED, &key1, VERIFY_READ);
|
|
if (unlikely(ret != 0))
|
|
goto out;
|
|
- ret = get_futex_key(uaddr2, flags & FLAGS_SHARED, &key2);
|
|
+ ret = get_futex_key(uaddr2, flags & FLAGS_SHARED, &key2,
|
|
+ requeue_pi ? VERIFY_WRITE : VERIFY_READ);
|
|
if (unlikely(ret != 0))
|
|
goto out_put_key1;
|
|
|
|
@@ -1790,7 +1820,7 @@ static int futex_wait_setup(u32 __user *uaddr, u32 val, unsigned int flags,
|
|
* while the syscall executes.
|
|
*/
|
|
retry:
|
|
- ret = get_futex_key(uaddr, flags & FLAGS_SHARED, &q->key);
|
|
+ ret = get_futex_key(uaddr, flags & FLAGS_SHARED, &q->key, VERIFY_READ);
|
|
if (unlikely(ret != 0))
|
|
return ret;
|
|
|
|
@@ -1941,7 +1971,7 @@ static int futex_lock_pi(u32 __user *uaddr, unsigned int flags, int detect,
|
|
}
|
|
|
|
retry:
|
|
- ret = get_futex_key(uaddr, flags & FLAGS_SHARED, &q.key);
|
|
+ ret = get_futex_key(uaddr, flags & FLAGS_SHARED, &q.key, VERIFY_WRITE);
|
|
if (unlikely(ret != 0))
|
|
goto out;
|
|
|
|
@@ -2060,7 +2090,7 @@ retry:
|
|
if ((uval & FUTEX_TID_MASK) != vpid)
|
|
return -EPERM;
|
|
|
|
- ret = get_futex_key(uaddr, flags & FLAGS_SHARED, &key);
|
|
+ ret = get_futex_key(uaddr, flags & FLAGS_SHARED, &key, VERIFY_WRITE);
|
|
if (unlikely(ret != 0))
|
|
goto out;
|
|
|
|
@@ -2249,7 +2279,7 @@ static int futex_wait_requeue_pi(u32 __user *uaddr, unsigned int flags,
|
|
debug_rt_mutex_init_waiter(&rt_waiter);
|
|
rt_waiter.task = NULL;
|
|
|
|
- ret = get_futex_key(uaddr2, flags & FLAGS_SHARED, &key2);
|
|
+ ret = get_futex_key(uaddr2, flags & FLAGS_SHARED, &key2, VERIFY_WRITE);
|
|
if (unlikely(ret != 0))
|
|
goto out;
|
|
|
|
diff --git a/lib/Makefile b/lib/Makefile
|
|
index 6b597fd..578414a 100644
|
|
--- a/lib/Makefile
|
|
+++ b/lib/Makefile
|
|
@@ -10,7 +10,7 @@ endif
|
|
lib-y := ctype.o string.o vsprintf.o cmdline.o \
|
|
rbtree.o radix-tree.o dump_stack.o timerqueue.o\
|
|
idr.o int_sqrt.o extable.o prio_tree.o \
|
|
- sha1.o irq_regs.o reciprocal_div.o argv_split.o \
|
|
+ sha1.o md5.o irq_regs.o reciprocal_div.o argv_split.o \
|
|
proportions.o prio_heap.o ratelimit.o show_mem.o \
|
|
is_single_threaded.o plist.o decompress.o find_next_bit.o
|
|
|
|
diff --git a/lib/md5.c b/lib/md5.c
|
|
new file mode 100644
|
|
index 0000000..c777180
|
|
--- /dev/null
|
|
+++ b/lib/md5.c
|
|
@@ -0,0 +1,95 @@
|
|
+#include <linux/kernel.h>
|
|
+#include <linux/module.h>
|
|
+#include <linux/cryptohash.h>
|
|
+
|
|
+#define F1(x, y, z) (z ^ (x & (y ^ z)))
|
|
+#define F2(x, y, z) F1(z, x, y)
|
|
+#define F3(x, y, z) (x ^ y ^ z)
|
|
+#define F4(x, y, z) (y ^ (x | ~z))
|
|
+
|
|
+#define MD5STEP(f, w, x, y, z, in, s) \
|
|
+ (w += f(x, y, z) + in, w = (w<<s | w>>(32-s)) + x)
|
|
+
|
|
+void md5_transform(__u32 *hash, __u32 const *in)
|
|
+{
|
|
+ u32 a, b, c, d;
|
|
+
|
|
+ a = hash[0];
|
|
+ b = hash[1];
|
|
+ c = hash[2];
|
|
+ d = hash[3];
|
|
+
|
|
+ MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7);
|
|
+ MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12);
|
|
+ MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17);
|
|
+ MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22);
|
|
+ MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7);
|
|
+ MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12);
|
|
+ MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17);
|
|
+ MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22);
|
|
+ MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7);
|
|
+ MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12);
|
|
+ MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
|
|
+ MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
|
|
+ MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7);
|
|
+ MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
|
|
+ MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
|
|
+ MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
|
|
+
|
|
+ MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5);
|
|
+ MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9);
|
|
+ MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
|
|
+ MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);
|
|
+ MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5);
|
|
+ MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);
|
|
+ MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
|
|
+ MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);
|
|
+ MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5);
|
|
+ MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
|
|
+ MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14);
|
|
+ MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20);
|
|
+ MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
|
|
+ MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);
|
|
+ MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14);
|
|
+ MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
|
|
+
|
|
+ MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4);
|
|
+ MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11);
|
|
+ MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
|
|
+ MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
|
|
+ MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4);
|
|
+ MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);
|
|
+ MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);
|
|
+ MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
|
|
+ MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
|
|
+ MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11);
|
|
+ MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16);
|
|
+ MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23);
|
|
+ MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4);
|
|
+ MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
|
|
+ MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
|
|
+ MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23);
|
|
+
|
|
+ MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6);
|
|
+ MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10);
|
|
+ MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
|
|
+ MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21);
|
|
+ MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
|
|
+ MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);
|
|
+ MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
|
|
+ MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21);
|
|
+ MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);
|
|
+ MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
|
|
+ MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15);
|
|
+ MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
|
|
+ MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6);
|
|
+ MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
|
|
+ MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);
|
|
+ MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21);
|
|
+
|
|
+ hash[0] += a;
|
|
+ hash[1] += b;
|
|
+ hash[2] += c;
|
|
+ hash[3] += d;
|
|
+}
|
|
+EXPORT_SYMBOL(md5_transform);
|
|
diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c
|
|
index 6e82148..5b4f51d 100644
|
|
--- a/net/8021q/vlan_dev.c
|
|
+++ b/net/8021q/vlan_dev.c
|
|
@@ -694,7 +694,7 @@ void vlan_setup(struct net_device *dev)
|
|
ether_setup(dev);
|
|
|
|
dev->priv_flags |= IFF_802_1Q_VLAN;
|
|
- dev->priv_flags &= ~IFF_XMIT_DST_RELEASE;
|
|
+ dev->priv_flags &= ~(IFF_XMIT_DST_RELEASE | IFF_TX_SKB_SHARING);
|
|
dev->tx_queue_len = 0;
|
|
|
|
dev->netdev_ops = &vlan_netdev_ops;
|
|
diff --git a/net/bluetooth/bnep/netdev.c b/net/bluetooth/bnep/netdev.c
|
|
index 8c100c9..d4f5dff 100644
|
|
--- a/net/bluetooth/bnep/netdev.c
|
|
+++ b/net/bluetooth/bnep/netdev.c
|
|
@@ -231,6 +231,7 @@ void bnep_net_setup(struct net_device *dev)
|
|
dev->addr_len = ETH_ALEN;
|
|
|
|
ether_setup(dev);
|
|
+ dev->priv_flags &= ~IFF_TX_SKB_SHARING;
|
|
dev->netdev_ops = &bnep_netdev_ops;
|
|
|
|
dev->watchdog_timeo = HZ * 2;
|
|
diff --git a/net/core/Makefile b/net/core/Makefile
|
|
index 8a04dd2..0d357b1 100644
|
|
--- a/net/core/Makefile
|
|
+++ b/net/core/Makefile
|
|
@@ -3,7 +3,7 @@
|
|
#
|
|
|
|
obj-y := sock.o request_sock.o skbuff.o iovec.o datagram.o stream.o scm.o \
|
|
- gen_stats.o gen_estimator.o net_namespace.o
|
|
+ gen_stats.o gen_estimator.o net_namespace.o secure_seq.o
|
|
|
|
obj-$(CONFIG_SYSCTL) += sysctl_net_core.o
|
|
|
|
diff --git a/net/core/link_watch.c b/net/core/link_watch.c
|
|
index a7b3421..357bd4e 100644
|
|
--- a/net/core/link_watch.c
|
|
+++ b/net/core/link_watch.c
|
|
@@ -126,7 +126,7 @@ static void linkwatch_schedule_work(int urgent)
|
|
return;
|
|
|
|
/* It's already running which is good enough. */
|
|
- if (!cancel_delayed_work(&linkwatch_work))
|
|
+ if (!__cancel_delayed_work(&linkwatch_work))
|
|
return;
|
|
|
|
/* Otherwise we reschedule it again for immediate execution. */
|
|
diff --git a/net/core/pktgen.c b/net/core/pktgen.c
|
|
index f76079c..e35a6fb 100644
|
|
--- a/net/core/pktgen.c
|
|
+++ b/net/core/pktgen.c
|
|
@@ -1070,7 +1070,9 @@ static ssize_t pktgen_if_write(struct file *file,
|
|
len = num_arg(&user_buffer[i], 10, &value);
|
|
if (len < 0)
|
|
return len;
|
|
-
|
|
+ if ((value > 0) &&
|
|
+ (!(pkt_dev->odev->priv_flags & IFF_TX_SKB_SHARING)))
|
|
+ return -ENOTSUPP;
|
|
i += len;
|
|
pkt_dev->clone_skb = value;
|
|
|
|
@@ -3555,7 +3557,6 @@ static int pktgen_add_device(struct pktgen_thread *t, const char *ifname)
|
|
pkt_dev->min_pkt_size = ETH_ZLEN;
|
|
pkt_dev->max_pkt_size = ETH_ZLEN;
|
|
pkt_dev->nfrags = 0;
|
|
- pkt_dev->clone_skb = pg_clone_skb_d;
|
|
pkt_dev->delay = pg_delay_d;
|
|
pkt_dev->count = pg_count_d;
|
|
pkt_dev->sofar = 0;
|
|
@@ -3563,7 +3564,6 @@ static int pktgen_add_device(struct pktgen_thread *t, const char *ifname)
|
|
pkt_dev->udp_src_max = 9;
|
|
pkt_dev->udp_dst_min = 9;
|
|
pkt_dev->udp_dst_max = 9;
|
|
-
|
|
pkt_dev->vlan_p = 0;
|
|
pkt_dev->vlan_cfi = 0;
|
|
pkt_dev->vlan_id = 0xffff;
|
|
@@ -3575,6 +3575,8 @@ static int pktgen_add_device(struct pktgen_thread *t, const char *ifname)
|
|
err = pktgen_setup_dev(pkt_dev, ifname);
|
|
if (err)
|
|
goto out1;
|
|
+ if (pkt_dev->odev->priv_flags & IFF_TX_SKB_SHARING)
|
|
+ pkt_dev->clone_skb = pg_clone_skb_d;
|
|
|
|
pkt_dev->entry = proc_create_data(ifname, 0600, pg_proc_dir,
|
|
&pktgen_if_fops, pkt_dev);
|
|
diff --git a/net/core/secure_seq.c b/net/core/secure_seq.c
|
|
new file mode 100644
|
|
index 0000000..45329d7
|
|
--- /dev/null
|
|
+++ b/net/core/secure_seq.c
|
|
@@ -0,0 +1,184 @@
|
|
+#include <linux/kernel.h>
|
|
+#include <linux/init.h>
|
|
+#include <linux/cryptohash.h>
|
|
+#include <linux/module.h>
|
|
+#include <linux/cache.h>
|
|
+#include <linux/random.h>
|
|
+#include <linux/hrtimer.h>
|
|
+#include <linux/ktime.h>
|
|
+#include <linux/string.h>
|
|
+
|
|
+#include <net/secure_seq.h>
|
|
+
|
|
+static u32 net_secret[MD5_MESSAGE_BYTES / 4] ____cacheline_aligned;
|
|
+
|
|
+static int __init net_secret_init(void)
|
|
+{
|
|
+ get_random_bytes(net_secret, sizeof(net_secret));
|
|
+ return 0;
|
|
+}
|
|
+late_initcall(net_secret_init);
|
|
+
|
|
+static u32 seq_scale(u32 seq)
|
|
+{
|
|
+ /*
|
|
+ * As close as possible to RFC 793, which
|
|
+ * suggests using a 250 kHz clock.
|
|
+ * Further reading shows this assumes 2 Mb/s networks.
|
|
+ * For 10 Mb/s Ethernet, a 1 MHz clock is appropriate.
|
|
+ * For 10 Gb/s Ethernet, a 1 GHz clock should be ok, but
|
|
+ * we also need to limit the resolution so that the u32 seq
|
|
+ * overlaps less than one time per MSL (2 minutes).
|
|
+ * Choosing a clock of 64 ns period is OK. (period of 274 s)
|
|
+ */
|
|
+ return seq + (ktime_to_ns(ktime_get_real()) >> 6);
|
|
+}
|
|
+
|
|
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
|
|
+__u32 secure_tcpv6_sequence_number(__be32 *saddr, __be32 *daddr,
|
|
+ __be16 sport, __be16 dport)
|
|
+{
|
|
+ u32 secret[MD5_MESSAGE_BYTES / 4];
|
|
+ u32 hash[MD5_DIGEST_WORDS];
|
|
+ u32 i;
|
|
+
|
|
+ memcpy(hash, saddr, 16);
|
|
+ for (i = 0; i < 4; i++)
|
|
+ secret[i] = net_secret[i] + daddr[i];
|
|
+ secret[4] = net_secret[4] +
|
|
+ (((__force u16)sport << 16) + (__force u16)dport);
|
|
+ for (i = 5; i < MD5_MESSAGE_BYTES / 4; i++)
|
|
+ secret[i] = net_secret[i];
|
|
+
|
|
+ md5_transform(hash, secret);
|
|
+
|
|
+ return seq_scale(hash[0]);
|
|
+}
|
|
+EXPORT_SYMBOL(secure_tcpv6_sequence_number);
|
|
+
|
|
+u32 secure_ipv6_port_ephemeral(const __be32 *saddr, const __be32 *daddr,
|
|
+ __be16 dport)
|
|
+{
|
|
+ u32 secret[MD5_MESSAGE_BYTES / 4];
|
|
+ u32 hash[MD5_DIGEST_WORDS];
|
|
+ u32 i;
|
|
+
|
|
+ memcpy(hash, saddr, 16);
|
|
+ for (i = 0; i < 4; i++)
|
|
+ secret[i] = net_secret[i] + (__force u32) daddr[i];
|
|
+ secret[4] = net_secret[4] + (__force u32)dport;
|
|
+ for (i = 5; i < MD5_MESSAGE_BYTES / 4; i++)
|
|
+ secret[i] = net_secret[i];
|
|
+
|
|
+ md5_transform(hash, secret);
|
|
+
|
|
+ return hash[0];
|
|
+}
|
|
+#endif
|
|
+
|
|
+#ifdef CONFIG_INET
|
|
+__u32 secure_ip_id(__be32 daddr)
|
|
+{
|
|
+ u32 hash[MD5_DIGEST_WORDS];
|
|
+
|
|
+ hash[0] = (__force __u32) daddr;
|
|
+ hash[1] = net_secret[13];
|
|
+ hash[2] = net_secret[14];
|
|
+ hash[3] = net_secret[15];
|
|
+
|
|
+ md5_transform(hash, net_secret);
|
|
+
|
|
+ return hash[0];
|
|
+}
|
|
+
|
|
+__u32 secure_ipv6_id(const __be32 daddr[4])
|
|
+{
|
|
+ __u32 hash[4];
|
|
+
|
|
+ memcpy(hash, daddr, 16);
|
|
+ md5_transform(hash, net_secret);
|
|
+
|
|
+ return hash[0];
|
|
+}
|
|
+
|
|
+__u32 secure_tcp_sequence_number(__be32 saddr, __be32 daddr,
|
|
+ __be16 sport, __be16 dport)
|
|
+{
|
|
+ u32 hash[MD5_DIGEST_WORDS];
|
|
+
|
|
+ hash[0] = (__force u32)saddr;
|
|
+ hash[1] = (__force u32)daddr;
|
|
+ hash[2] = ((__force u16)sport << 16) + (__force u16)dport;
|
|
+ hash[3] = net_secret[15];
|
|
+
|
|
+ md5_transform(hash, net_secret);
|
|
+
|
|
+ return seq_scale(hash[0]);
|
|
+}
|
|
+
|
|
+u32 secure_ipv4_port_ephemeral(__be32 saddr, __be32 daddr, __be16 dport)
|
|
+{
|
|
+ u32 hash[MD5_DIGEST_WORDS];
|
|
+
|
|
+ hash[0] = (__force u32)saddr;
|
|
+ hash[1] = (__force u32)daddr;
|
|
+ hash[2] = (__force u32)dport ^ net_secret[14];
|
|
+ hash[3] = net_secret[15];
|
|
+
|
|
+ md5_transform(hash, net_secret);
|
|
+
|
|
+ return hash[0];
|
|
+}
|
|
+EXPORT_SYMBOL_GPL(secure_ipv4_port_ephemeral);
|
|
+#endif
|
|
+
|
|
+#if defined(CONFIG_IP_DCCP) || defined(CONFIG_IP_DCCP_MODULE)
|
|
+u64 secure_dccp_sequence_number(__be32 saddr, __be32 daddr,
|
|
+ __be16 sport, __be16 dport)
|
|
+{
|
|
+ u32 hash[MD5_DIGEST_WORDS];
|
|
+ u64 seq;
|
|
+
|
|
+ hash[0] = (__force u32)saddr;
|
|
+ hash[1] = (__force u32)daddr;
|
|
+ hash[2] = ((__force u16)sport << 16) + (__force u16)dport;
|
|
+ hash[3] = net_secret[15];
|
|
+
|
|
+ md5_transform(hash, net_secret);
|
|
+
|
|
+ seq = hash[0] | (((u64)hash[1]) << 32);
|
|
+ seq += ktime_to_ns(ktime_get_real());
|
|
+ seq &= (1ull << 48) - 1;
|
|
+
|
|
+ return seq;
|
|
+}
|
|
+EXPORT_SYMBOL(secure_dccp_sequence_number);
|
|
+
|
|
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
|
|
+u64 secure_dccpv6_sequence_number(__be32 *saddr, __be32 *daddr,
|
|
+ __be16 sport, __be16 dport)
|
|
+{
|
|
+ u32 secret[MD5_MESSAGE_BYTES / 4];
|
|
+ u32 hash[MD5_DIGEST_WORDS];
|
|
+ u64 seq;
|
|
+ u32 i;
|
|
+
|
|
+ memcpy(hash, saddr, 16);
|
|
+ for (i = 0; i < 4; i++)
|
|
+ secret[i] = net_secret[i] + daddr[i];
|
|
+ secret[4] = net_secret[4] +
|
|
+ (((__force u16)sport << 16) + (__force u16)dport);
|
|
+ for (i = 5; i < MD5_MESSAGE_BYTES / 4; i++)
|
|
+ secret[i] = net_secret[i];
|
|
+
|
|
+ md5_transform(hash, secret);
|
|
+
|
|
+ seq = hash[0] | (((u64)hash[1]) << 32);
|
|
+ seq += ktime_to_ns(ktime_get_real());
|
|
+ seq &= (1ull << 48) - 1;
|
|
+
|
|
+ return seq;
|
|
+}
|
|
+EXPORT_SYMBOL(secure_dccpv6_sequence_number);
|
|
+#endif
|
|
+#endif
|
|
diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c
|
|
index 8c36adf..332639b 100644
|
|
--- a/net/dccp/ipv4.c
|
|
+++ b/net/dccp/ipv4.c
|
|
@@ -26,6 +26,7 @@
|
|
#include <net/timewait_sock.h>
|
|
#include <net/tcp_states.h>
|
|
#include <net/xfrm.h>
|
|
+#include <net/secure_seq.h>
|
|
|
|
#include "ackvec.h"
|
|
#include "ccid.h"
|
|
diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c
|
|
index 8dc4348..b74f761 100644
|
|
--- a/net/dccp/ipv6.c
|
|
+++ b/net/dccp/ipv6.c
|
|
@@ -29,6 +29,7 @@
|
|
#include <net/transp_v6.h>
|
|
#include <net/ip6_checksum.h>
|
|
#include <net/xfrm.h>
|
|
+#include <net/secure_seq.h>
|
|
|
|
#include "dccp.h"
|
|
#include "ipv6.h"
|
|
@@ -69,13 +70,7 @@ static inline void dccp_v6_send_check(struct sock *sk, struct sk_buff *skb)
|
|
dh->dccph_checksum = dccp_v6_csum_finish(skb, &np->saddr, &np->daddr);
|
|
}
|
|
|
|
-static inline __u32 secure_dccpv6_sequence_number(__be32 *saddr, __be32 *daddr,
|
|
- __be16 sport, __be16 dport )
|
|
-{
|
|
- return secure_tcpv6_sequence_number(saddr, daddr, sport, dport);
|
|
-}
|
|
-
|
|
-static inline __u32 dccp_v6_init_sequence(struct sk_buff *skb)
|
|
+static inline __u64 dccp_v6_init_sequence(struct sk_buff *skb)
|
|
{
|
|
return secure_dccpv6_sequence_number(ipv6_hdr(skb)->daddr.s6_addr32,
|
|
ipv6_hdr(skb)->saddr.s6_addr32,
|
|
diff --git a/net/ethernet/eth.c b/net/ethernet/eth.c
|
|
index 44d2b42..2780e9b 100644
|
|
--- a/net/ethernet/eth.c
|
|
+++ b/net/ethernet/eth.c
|
|
@@ -340,6 +340,7 @@ void ether_setup(struct net_device *dev)
|
|
dev->addr_len = ETH_ALEN;
|
|
dev->tx_queue_len = 1000; /* Ethernet wants good queues */
|
|
dev->flags = IFF_BROADCAST|IFF_MULTICAST;
|
|
+ dev->priv_flags = IFF_TX_SKB_SHARING;
|
|
|
|
memset(dev->broadcast, 0xFF, ETH_ALEN);
|
|
|
|
diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c
|
|
index 0d4a184..4155abc 100644
|
|
--- a/net/ipv4/devinet.c
|
|
+++ b/net/ipv4/devinet.c
|
|
@@ -1134,15 +1134,15 @@ static void inetdev_send_gratuitous_arp(struct net_device *dev,
|
|
struct in_device *in_dev)
|
|
|
|
{
|
|
- struct in_ifaddr *ifa = in_dev->ifa_list;
|
|
-
|
|
- if (!ifa)
|
|
- return;
|
|
+ struct in_ifaddr *ifa;
|
|
|
|
- arp_send(ARPOP_REQUEST, ETH_P_ARP,
|
|
- ifa->ifa_local, dev,
|
|
- ifa->ifa_local, NULL,
|
|
- dev->dev_addr, NULL);
|
|
+ for (ifa = in_dev->ifa_list; ifa;
|
|
+ ifa = ifa->ifa_next) {
|
|
+ arp_send(ARPOP_REQUEST, ETH_P_ARP,
|
|
+ ifa->ifa_local, dev,
|
|
+ ifa->ifa_local, NULL,
|
|
+ dev->dev_addr, NULL);
|
|
+ }
|
|
}
|
|
|
|
/* Called only under RTNL semaphore */
|
|
diff --git a/net/ipv4/gre.c b/net/ipv4/gre.c
|
|
index c6933f2..3e3f75d 100644
|
|
--- a/net/ipv4/gre.c
|
|
+++ b/net/ipv4/gre.c
|
|
@@ -15,6 +15,7 @@
|
|
#include <linux/kmod.h>
|
|
#include <linux/skbuff.h>
|
|
#include <linux/in.h>
|
|
+#include <linux/ip.h>
|
|
#include <linux/netdevice.h>
|
|
#include <linux/version.h>
|
|
#include <linux/spinlock.h>
|
|
@@ -97,27 +98,17 @@ drop:
|
|
static void gre_err(struct sk_buff *skb, u32 info)
|
|
{
|
|
const struct gre_protocol *proto;
|
|
- u8 ver;
|
|
-
|
|
- if (!pskb_may_pull(skb, 12))
|
|
- goto drop;
|
|
+ const struct iphdr *iph = (const struct iphdr *)skb->data;
|
|
+ u8 ver = skb->data[(iph->ihl<<2) + 1]&0x7f;
|
|
|
|
- ver = skb->data[1]&0x7f;
|
|
if (ver >= GREPROTO_MAX)
|
|
- goto drop;
|
|
+ return;
|
|
|
|
rcu_read_lock();
|
|
proto = rcu_dereference(gre_proto[ver]);
|
|
- if (!proto || !proto->err_handler)
|
|
- goto drop_unlock;
|
|
- proto->err_handler(skb, info);
|
|
- rcu_read_unlock();
|
|
- return;
|
|
-
|
|
-drop_unlock:
|
|
+ if (proto && proto->err_handler)
|
|
+ proto->err_handler(skb, info);
|
|
rcu_read_unlock();
|
|
-drop:
|
|
- kfree_skb(skb);
|
|
}
|
|
|
|
static const struct net_protocol net_gre_protocol = {
|
|
diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c
|
|
index 5395e45..23ef31b 100644
|
|
--- a/net/ipv4/icmp.c
|
|
+++ b/net/ipv4/icmp.c
|
|
@@ -380,6 +380,7 @@ static struct rtable *icmp_route_lookup(struct net *net,
|
|
struct icmp_bxm *param)
|
|
{
|
|
struct rtable *rt, *rt2;
|
|
+ struct flowi4 fl4_dec;
|
|
int err;
|
|
|
|
memset(fl4, 0, sizeof(*fl4));
|
|
@@ -408,19 +409,19 @@ static struct rtable *icmp_route_lookup(struct net *net,
|
|
} else
|
|
return rt;
|
|
|
|
- err = xfrm_decode_session_reverse(skb_in, flowi4_to_flowi(fl4), AF_INET);
|
|
+ err = xfrm_decode_session_reverse(skb_in, flowi4_to_flowi(&fl4_dec), AF_INET);
|
|
if (err)
|
|
goto relookup_failed;
|
|
|
|
- if (inet_addr_type(net, fl4->saddr) == RTN_LOCAL) {
|
|
- rt2 = __ip_route_output_key(net, fl4);
|
|
+ if (inet_addr_type(net, fl4_dec.saddr) == RTN_LOCAL) {
|
|
+ rt2 = __ip_route_output_key(net, &fl4_dec);
|
|
if (IS_ERR(rt2))
|
|
err = PTR_ERR(rt2);
|
|
} else {
|
|
struct flowi4 fl4_2 = {};
|
|
unsigned long orefdst;
|
|
|
|
- fl4_2.daddr = fl4->saddr;
|
|
+ fl4_2.daddr = fl4_dec.saddr;
|
|
rt2 = ip_route_output_key(net, &fl4_2);
|
|
if (IS_ERR(rt2)) {
|
|
err = PTR_ERR(rt2);
|
|
@@ -428,7 +429,7 @@ static struct rtable *icmp_route_lookup(struct net *net,
|
|
}
|
|
/* Ugh! */
|
|
orefdst = skb_in->_skb_refdst; /* save old refdst */
|
|
- err = ip_route_input(skb_in, fl4->daddr, fl4->saddr,
|
|
+ err = ip_route_input(skb_in, fl4_dec.daddr, fl4_dec.saddr,
|
|
RT_TOS(tos), rt2->dst.dev);
|
|
|
|
dst_release(&rt2->dst);
|
|
@@ -440,10 +441,11 @@ static struct rtable *icmp_route_lookup(struct net *net,
|
|
goto relookup_failed;
|
|
|
|
rt2 = (struct rtable *) xfrm_lookup(net, &rt2->dst,
|
|
- flowi4_to_flowi(fl4), NULL,
|
|
+ flowi4_to_flowi(&fl4_dec), NULL,
|
|
XFRM_LOOKUP_ICMP);
|
|
if (!IS_ERR(rt2)) {
|
|
dst_release(&rt->dst);
|
|
+ memcpy(fl4, &fl4_dec, sizeof(*fl4));
|
|
rt = rt2;
|
|
} else if (PTR_ERR(rt2) == -EPERM) {
|
|
if (rt)
|
|
diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c
|
|
index f1d27f6..283c0a2 100644
|
|
--- a/net/ipv4/igmp.c
|
|
+++ b/net/ipv4/igmp.c
|
|
@@ -1718,7 +1718,7 @@ static int ip_mc_add_src(struct in_device *in_dev, __be32 *pmca, int sfmode,
|
|
|
|
pmc->sfcount[sfmode]--;
|
|
for (j=0; j<i; j++)
|
|
- (void) ip_mc_del1_src(pmc, sfmode, &psfsrc[i]);
|
|
+ (void) ip_mc_del1_src(pmc, sfmode, &psfsrc[j]);
|
|
} else if (isexclude != (pmc->sfcount[MCAST_EXCLUDE] != 0)) {
|
|
#ifdef CONFIG_IP_MULTICAST
|
|
struct ip_sf_list *psf;
|
|
diff --git a/net/ipv4/inet_hashtables.c b/net/ipv4/inet_hashtables.c
|
|
index 3c0369a..984ec65 100644
|
|
--- a/net/ipv4/inet_hashtables.c
|
|
+++ b/net/ipv4/inet_hashtables.c
|
|
@@ -21,6 +21,7 @@
|
|
|
|
#include <net/inet_connection_sock.h>
|
|
#include <net/inet_hashtables.h>
|
|
+#include <net/secure_seq.h>
|
|
#include <net/ip.h>
|
|
|
|
/*
|
|
diff --git a/net/ipv4/inetpeer.c b/net/ipv4/inetpeer.c
|
|
index ce616d9..6877645 100644
|
|
--- a/net/ipv4/inetpeer.c
|
|
+++ b/net/ipv4/inetpeer.c
|
|
@@ -19,6 +19,7 @@
|
|
#include <linux/net.h>
|
|
#include <net/ip.h>
|
|
#include <net/inetpeer.h>
|
|
+#include <net/secure_seq.h>
|
|
|
|
/*
|
|
* Theory of operations.
|
|
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
|
|
index 84f26e8..0c99db4 100644
|
|
--- a/net/ipv4/ip_output.c
|
|
+++ b/net/ipv4/ip_output.c
|
|
@@ -734,7 +734,7 @@ static inline int ip_ufo_append_data(struct sock *sk,
|
|
int getfrag(void *from, char *to, int offset, int len,
|
|
int odd, struct sk_buff *skb),
|
|
void *from, int length, int hh_len, int fragheaderlen,
|
|
- int transhdrlen, int mtu, unsigned int flags)
|
|
+ int transhdrlen, int maxfraglen, unsigned int flags)
|
|
{
|
|
struct sk_buff *skb;
|
|
int err;
|
|
@@ -767,7 +767,7 @@ static inline int ip_ufo_append_data(struct sock *sk,
|
|
skb->csum = 0;
|
|
|
|
/* specify the length of each IP datagram fragment */
|
|
- skb_shinfo(skb)->gso_size = mtu - fragheaderlen;
|
|
+ skb_shinfo(skb)->gso_size = maxfraglen - fragheaderlen;
|
|
skb_shinfo(skb)->gso_type = SKB_GSO_UDP;
|
|
__skb_queue_tail(queue, skb);
|
|
}
|
|
@@ -831,7 +831,7 @@ static int __ip_append_data(struct sock *sk,
|
|
(rt->dst.dev->features & NETIF_F_UFO) && !rt->dst.header_len) {
|
|
err = ip_ufo_append_data(sk, queue, getfrag, from, length,
|
|
hh_len, fragheaderlen, transhdrlen,
|
|
- mtu, flags);
|
|
+ maxfraglen, flags);
|
|
if (err)
|
|
goto error;
|
|
return 0;
|
|
diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c
|
|
index 30a7763..f81af8d 100644
|
|
--- a/net/ipv4/ipmr.c
|
|
+++ b/net/ipv4/ipmr.c
|
|
@@ -1796,7 +1796,7 @@ static struct mr_table *ipmr_rt_fib_lookup(struct net *net, struct sk_buff *skb)
|
|
struct flowi4 fl4 = {
|
|
.daddr = iph->daddr,
|
|
.saddr = iph->saddr,
|
|
- .flowi4_tos = iph->tos,
|
|
+ .flowi4_tos = RT_TOS(iph->tos),
|
|
.flowi4_oif = rt->rt_oif,
|
|
.flowi4_iif = rt->rt_iif,
|
|
.flowi4_mark = rt->rt_mark,
|
|
diff --git a/net/ipv4/netfilter/nf_nat_proto_common.c b/net/ipv4/netfilter/nf_nat_proto_common.c
|
|
index 3e61faf..f52d41e 100644
|
|
--- a/net/ipv4/netfilter/nf_nat_proto_common.c
|
|
+++ b/net/ipv4/netfilter/nf_nat_proto_common.c
|
|
@@ -12,6 +12,7 @@
|
|
#include <linux/ip.h>
|
|
|
|
#include <linux/netfilter.h>
|
|
+#include <net/secure_seq.h>
|
|
#include <net/netfilter/nf_nat.h>
|
|
#include <net/netfilter/nf_nat_core.h>
|
|
#include <net/netfilter/nf_nat_rule.h>
|
|
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
|
|
index aa13ef1..cdabdbf 100644
|
|
--- a/net/ipv4/route.c
|
|
+++ b/net/ipv4/route.c
|
|
@@ -108,6 +108,7 @@
|
|
#ifdef CONFIG_SYSCTL
|
|
#include <linux/sysctl.h>
|
|
#endif
|
|
+#include <net/secure_seq.h>
|
|
|
|
#define RT_FL_TOS(oldflp4) \
|
|
((u32)(oldflp4->flowi4_tos & (IPTOS_RT_MASK | RTO_ONLINK)))
|
|
@@ -725,6 +726,7 @@ static inline int compare_keys(struct rtable *rt1, struct rtable *rt2)
|
|
((__force u32)rt1->rt_key_src ^ (__force u32)rt2->rt_key_src) |
|
|
(rt1->rt_mark ^ rt2->rt_mark) |
|
|
(rt1->rt_key_tos ^ rt2->rt_key_tos) |
|
|
+ (rt1->rt_route_iif ^ rt2->rt_route_iif) |
|
|
(rt1->rt_oif ^ rt2->rt_oif) |
|
|
(rt1->rt_iif ^ rt2->rt_iif)) == 0;
|
|
}
|
|
@@ -1703,7 +1705,7 @@ void ip_rt_get_source(u8 *addr, struct sk_buff *skb, struct rtable *rt)
|
|
memset(&fl4, 0, sizeof(fl4));
|
|
fl4.daddr = iph->daddr;
|
|
fl4.saddr = iph->saddr;
|
|
- fl4.flowi4_tos = iph->tos;
|
|
+ fl4.flowi4_tos = RT_TOS(iph->tos);
|
|
fl4.flowi4_oif = rt->dst.dev->ifindex;
|
|
fl4.flowi4_iif = skb->dev->ifindex;
|
|
fl4.flowi4_mark = skb->mark;
|
|
@@ -2281,8 +2283,8 @@ int ip_route_input_common(struct sk_buff *skb, __be32 daddr, __be32 saddr,
|
|
if ((((__force u32)rth->rt_key_dst ^ (__force u32)daddr) |
|
|
((__force u32)rth->rt_key_src ^ (__force u32)saddr) |
|
|
(rth->rt_iif ^ iif) |
|
|
- rth->rt_oif |
|
|
(rth->rt_key_tos ^ tos)) == 0 &&
|
|
+ rt_is_input_route(rth) &&
|
|
rth->rt_mark == skb->mark &&
|
|
net_eq(dev_net(rth->dst.dev), net) &&
|
|
!rt_is_expired(rth)) {
|
|
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
|
|
index 708dc20..b3e6956 100644
|
|
--- a/net/ipv4/tcp_ipv4.c
|
|
+++ b/net/ipv4/tcp_ipv4.c
|
|
@@ -72,6 +72,7 @@
|
|
#include <net/timewait_sock.h>
|
|
#include <net/xfrm.h>
|
|
#include <net/netdma.h>
|
|
+#include <net/secure_seq.h>
|
|
|
|
#include <linux/inet.h>
|
|
#include <linux/ipv6.h>
|
|
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c
|
|
index 3b5669a..5591236 100644
|
|
--- a/net/ipv6/af_inet6.c
|
|
+++ b/net/ipv6/af_inet6.c
|
|
@@ -1078,6 +1078,8 @@ static int __init inet6_init(void)
|
|
goto out;
|
|
}
|
|
|
|
+ initialize_hashidentrnd();
|
|
+
|
|
err = proto_register(&tcpv6_prot, 1);
|
|
if (err)
|
|
goto out;
|
|
diff --git a/net/ipv6/inet6_hashtables.c b/net/ipv6/inet6_hashtables.c
|
|
index b531972..73f1a00 100644
|
|
--- a/net/ipv6/inet6_hashtables.c
|
|
+++ b/net/ipv6/inet6_hashtables.c
|
|
@@ -20,6 +20,7 @@
|
|
#include <net/inet_connection_sock.h>
|
|
#include <net/inet_hashtables.h>
|
|
#include <net/inet6_hashtables.h>
|
|
+#include <net/secure_seq.h>
|
|
#include <net/ip.h>
|
|
|
|
int __inet6_hash(struct sock *sk, struct inet_timewait_sock *tw)
|
|
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
|
|
index 9d4b165..1661296 100644
|
|
--- a/net/ipv6/ip6_output.c
|
|
+++ b/net/ipv6/ip6_output.c
|
|
@@ -596,6 +596,35 @@ int ip6_find_1stfragopt(struct sk_buff *skb, u8 **nexthdr)
|
|
return offset;
|
|
}
|
|
|
|
+static u32 hashidentrnd __read_mostly;
|
|
+#define FID_HASH_SZ 16
|
|
+static u32 ipv6_fragmentation_id[FID_HASH_SZ];
|
|
+
|
|
+void __init initialize_hashidentrnd(void)
|
|
+{
|
|
+ get_random_bytes(&hashidentrnd, sizeof(hashidentrnd));
|
|
+}
|
|
+
|
|
+static u32 __ipv6_select_ident(const struct in6_addr *addr)
|
|
+{
|
|
+ u32 newid, oldid, hash = jhash2((u32 *)addr, 4, hashidentrnd);
|
|
+ u32 *pid = &ipv6_fragmentation_id[hash % FID_HASH_SZ];
|
|
+
|
|
+ do {
|
|
+ oldid = *pid;
|
|
+ newid = oldid + 1;
|
|
+ if (!(hash + newid))
|
|
+ newid++;
|
|
+ } while (cmpxchg(pid, oldid, newid) != oldid);
|
|
+
|
|
+ return hash + newid;
|
|
+}
|
|
+
|
|
+void ipv6_select_ident(struct frag_hdr *fhdr, struct rt6_info *rt)
|
|
+{
|
|
+ fhdr->identification = htonl(__ipv6_select_ident(&rt->rt6i_dst.addr));
|
|
+}
|
|
+
|
|
int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *))
|
|
{
|
|
struct sk_buff *frag;
|
|
@@ -680,7 +709,7 @@ int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *))
|
|
skb_reset_network_header(skb);
|
|
memcpy(skb_network_header(skb), tmp_hdr, hlen);
|
|
|
|
- ipv6_select_ident(fh);
|
|
+ ipv6_select_ident(fh, rt);
|
|
fh->nexthdr = nexthdr;
|
|
fh->reserved = 0;
|
|
fh->frag_off = htons(IP6_MF);
|
|
@@ -826,7 +855,7 @@ slow_path:
|
|
fh->nexthdr = nexthdr;
|
|
fh->reserved = 0;
|
|
if (!frag_id) {
|
|
- ipv6_select_ident(fh);
|
|
+ ipv6_select_ident(fh, rt);
|
|
frag_id = fh->identification;
|
|
} else
|
|
fh->identification = frag_id;
|
|
@@ -1072,7 +1101,8 @@ static inline int ip6_ufo_append_data(struct sock *sk,
|
|
int getfrag(void *from, char *to, int offset, int len,
|
|
int odd, struct sk_buff *skb),
|
|
void *from, int length, int hh_len, int fragheaderlen,
|
|
- int transhdrlen, int mtu,unsigned int flags)
|
|
+ int transhdrlen, int mtu,unsigned int flags,
|
|
+ struct rt6_info *rt)
|
|
|
|
{
|
|
struct sk_buff *skb;
|
|
@@ -1116,7 +1146,7 @@ static inline int ip6_ufo_append_data(struct sock *sk,
|
|
skb_shinfo(skb)->gso_size = (mtu - fragheaderlen -
|
|
sizeof(struct frag_hdr)) & ~7;
|
|
skb_shinfo(skb)->gso_type = SKB_GSO_UDP;
|
|
- ipv6_select_ident(&fhdr);
|
|
+ ipv6_select_ident(&fhdr, rt);
|
|
skb_shinfo(skb)->ip6_frag_id = fhdr.identification;
|
|
__skb_queue_tail(&sk->sk_write_queue, skb);
|
|
|
|
@@ -1282,7 +1312,7 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to,
|
|
|
|
err = ip6_ufo_append_data(sk, getfrag, from, length,
|
|
hh_len, fragheaderlen,
|
|
- transhdrlen, mtu, flags);
|
|
+ transhdrlen, mtu, flags, rt);
|
|
if (err)
|
|
goto error;
|
|
return 0;
|
|
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
|
|
index 87551ca..7c43e86 100644
|
|
--- a/net/ipv6/tcp_ipv6.c
|
|
+++ b/net/ipv6/tcp_ipv6.c
|
|
@@ -61,6 +61,7 @@
|
|
#include <net/timewait_sock.h>
|
|
#include <net/netdma.h>
|
|
#include <net/inet_common.h>
|
|
+#include <net/secure_seq.h>
|
|
|
|
#include <asm/uaccess.h>
|
|
|
|
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
|
|
index 328985c..29213b5 100644
|
|
--- a/net/ipv6/udp.c
|
|
+++ b/net/ipv6/udp.c
|
|
@@ -1359,7 +1359,7 @@ static struct sk_buff *udp6_ufo_fragment(struct sk_buff *skb, u32 features)
|
|
fptr = (struct frag_hdr *)(skb_network_header(skb) + unfrag_ip6hlen);
|
|
fptr->nexthdr = nexthdr;
|
|
fptr->reserved = 0;
|
|
- ipv6_select_ident(fptr);
|
|
+ ipv6_select_ident(fptr, (struct rt6_info *)skb_dst(skb));
|
|
|
|
/* Fragment the skb. ipv6 header and the remaining fields of the
|
|
* fragment header are updated in ipv6_gso_segment()
|
|
diff --git a/net/l2tp/l2tp_eth.c b/net/l2tp/l2tp_eth.c
|
|
index a8193f5..d2726a7 100644
|
|
--- a/net/l2tp/l2tp_eth.c
|
|
+++ b/net/l2tp/l2tp_eth.c
|
|
@@ -103,7 +103,7 @@ static struct net_device_ops l2tp_eth_netdev_ops = {
|
|
static void l2tp_eth_dev_setup(struct net_device *dev)
|
|
{
|
|
ether_setup(dev);
|
|
-
|
|
+ dev->priv_flags &= ~IFF_TX_SKB_SHARING;
|
|
dev->netdev_ops = &l2tp_eth_netdev_ops;
|
|
dev->destructor = free_netdev;
|
|
}
|
|
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
|
|
index dee30ae..895eec1 100644
|
|
--- a/net/mac80211/iface.c
|
|
+++ b/net/mac80211/iface.c
|
|
@@ -699,6 +699,7 @@ static const struct net_device_ops ieee80211_monitorif_ops = {
|
|
static void ieee80211_if_setup(struct net_device *dev)
|
|
{
|
|
ether_setup(dev);
|
|
+ dev->priv_flags &= ~IFF_TX_SKB_SHARING;
|
|
dev->netdev_ops = &ieee80211_dataif_ops;
|
|
dev->destructor = free_netdev;
|
|
}
|
|
diff --git a/net/netfilter/ipvs/ip_vs_ctl.c b/net/netfilter/ipvs/ip_vs_ctl.c
|
|
index 699c79a..a178cb3 100644
|
|
--- a/net/netfilter/ipvs/ip_vs_ctl.c
|
|
+++ b/net/netfilter/ipvs/ip_vs_ctl.c
|
|
@@ -3771,6 +3771,7 @@ err_sock:
|
|
void ip_vs_control_cleanup(void)
|
|
{
|
|
EnterFunction(2);
|
|
+ unregister_netdevice_notifier(&ip_vs_dst_notifier);
|
|
ip_vs_genl_unregister();
|
|
nf_unregister_sockopt(&ip_vs_sockopts);
|
|
LeaveFunction(2);
|
|
diff --git a/net/sched/sch_sfq.c b/net/sched/sch_sfq.c
|
|
index b6ea6af..69400e3 100644
|
|
--- a/net/sched/sch_sfq.c
|
|
+++ b/net/sched/sch_sfq.c
|
|
@@ -410,7 +410,12 @@ sfq_enqueue(struct sk_buff *skb, struct Qdisc *sch)
|
|
/* Return Congestion Notification only if we dropped a packet
|
|
* from this flow.
|
|
*/
|
|
- return (qlen != slot->qlen) ? NET_XMIT_CN : NET_XMIT_SUCCESS;
|
|
+ if (qlen != slot->qlen)
|
|
+ return NET_XMIT_CN;
|
|
+
|
|
+ /* As we dropped a packet, better let upper stack know this */
|
|
+ qdisc_tree_decrease_qlen(sch, 1);
|
|
+ return NET_XMIT_SUCCESS;
|
|
}
|
|
|
|
static struct sk_buff *
|
|
diff --git a/net/socket.c b/net/socket.c
|
|
index 02dc82d..ed46dbb 100644
|
|
--- a/net/socket.c
|
|
+++ b/net/socket.c
|
|
@@ -1871,8 +1871,14 @@ SYSCALL_DEFINE2(shutdown, int, fd, int, how)
|
|
#define COMPAT_NAMELEN(msg) COMPAT_MSG(msg, msg_namelen)
|
|
#define COMPAT_FLAGS(msg) COMPAT_MSG(msg, msg_flags)
|
|
|
|
+struct used_address {
|
|
+ struct sockaddr_storage name;
|
|
+ unsigned int name_len;
|
|
+};
|
|
+
|
|
static int __sys_sendmsg(struct socket *sock, struct msghdr __user *msg,
|
|
- struct msghdr *msg_sys, unsigned flags, int nosec)
|
|
+ struct msghdr *msg_sys, unsigned flags,
|
|
+ struct used_address *used_address)
|
|
{
|
|
struct compat_msghdr __user *msg_compat =
|
|
(struct compat_msghdr __user *)msg;
|
|
@@ -1953,8 +1959,28 @@ static int __sys_sendmsg(struct socket *sock, struct msghdr __user *msg,
|
|
|
|
if (sock->file->f_flags & O_NONBLOCK)
|
|
msg_sys->msg_flags |= MSG_DONTWAIT;
|
|
- err = (nosec ? sock_sendmsg_nosec : sock_sendmsg)(sock, msg_sys,
|
|
- total_len);
|
|
+ /*
|
|
+ * If this is sendmmsg() and current destination address is same as
|
|
+ * previously succeeded address, omit asking LSM's decision.
|
|
+ * used_address->name_len is initialized to UINT_MAX so that the first
|
|
+ * destination address never matches.
|
|
+ */
|
|
+ if (used_address && used_address->name_len == msg_sys->msg_namelen &&
|
|
+ !memcmp(&used_address->name, msg->msg_name,
|
|
+ used_address->name_len)) {
|
|
+ err = sock_sendmsg_nosec(sock, msg_sys, total_len);
|
|
+ goto out_freectl;
|
|
+ }
|
|
+ err = sock_sendmsg(sock, msg_sys, total_len);
|
|
+ /*
|
|
+ * If this is sendmmsg() and sending to current destination address was
|
|
+ * successful, remember it.
|
|
+ */
|
|
+ if (used_address && err >= 0) {
|
|
+ used_address->name_len = msg_sys->msg_namelen;
|
|
+ memcpy(&used_address->name, msg->msg_name,
|
|
+ used_address->name_len);
|
|
+ }
|
|
|
|
out_freectl:
|
|
if (ctl_buf != ctl)
|
|
@@ -1979,7 +2005,7 @@ SYSCALL_DEFINE3(sendmsg, int, fd, struct msghdr __user *, msg, unsigned, flags)
|
|
if (!sock)
|
|
goto out;
|
|
|
|
- err = __sys_sendmsg(sock, msg, &msg_sys, flags, 0);
|
|
+ err = __sys_sendmsg(sock, msg, &msg_sys, flags, NULL);
|
|
|
|
fput_light(sock->file, fput_needed);
|
|
out:
|
|
@@ -1998,6 +2024,10 @@ int __sys_sendmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen,
|
|
struct mmsghdr __user *entry;
|
|
struct compat_mmsghdr __user *compat_entry;
|
|
struct msghdr msg_sys;
|
|
+ struct used_address used_address;
|
|
+
|
|
+ if (vlen > UIO_MAXIOV)
|
|
+ vlen = UIO_MAXIOV;
|
|
|
|
datagrams = 0;
|
|
|
|
@@ -2005,27 +2035,22 @@ int __sys_sendmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen,
|
|
if (!sock)
|
|
return err;
|
|
|
|
- err = sock_error(sock->sk);
|
|
- if (err)
|
|
- goto out_put;
|
|
-
|
|
+ used_address.name_len = UINT_MAX;
|
|
entry = mmsg;
|
|
compat_entry = (struct compat_mmsghdr __user *)mmsg;
|
|
+ err = 0;
|
|
|
|
while (datagrams < vlen) {
|
|
- /*
|
|
- * No need to ask LSM for more than the first datagram.
|
|
- */
|
|
if (MSG_CMSG_COMPAT & flags) {
|
|
err = __sys_sendmsg(sock, (struct msghdr __user *)compat_entry,
|
|
- &msg_sys, flags, datagrams);
|
|
+ &msg_sys, flags, &used_address);
|
|
if (err < 0)
|
|
break;
|
|
err = __put_user(err, &compat_entry->msg_len);
|
|
++compat_entry;
|
|
} else {
|
|
err = __sys_sendmsg(sock, (struct msghdr __user *)entry,
|
|
- &msg_sys, flags, datagrams);
|
|
+ &msg_sys, flags, &used_address);
|
|
if (err < 0)
|
|
break;
|
|
err = put_user(err, &entry->msg_len);
|
|
@@ -2037,29 +2062,11 @@ int __sys_sendmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen,
|
|
++datagrams;
|
|
}
|
|
|
|
-out_put:
|
|
fput_light(sock->file, fput_needed);
|
|
|
|
- if (err == 0)
|
|
- return datagrams;
|
|
-
|
|
- if (datagrams != 0) {
|
|
- /*
|
|
- * We may send less entries than requested (vlen) if the
|
|
- * sock is non blocking...
|
|
- */
|
|
- if (err != -EAGAIN) {
|
|
- /*
|
|
- * ... or if sendmsg returns an error after we
|
|
- * send some datagrams, where we record the
|
|
- * error to return on the next call or if the
|
|
- * app asks about it using getsockopt(SO_ERROR).
|
|
- */
|
|
- sock->sk->sk_err = -err;
|
|
- }
|
|
-
|
|
+ /* We only return an error if no datagrams were able to be sent */
|
|
+ if (datagrams != 0)
|
|
return datagrams;
|
|
- }
|
|
|
|
return err;
|
|
}
|
|
diff --git a/net/xfrm/xfrm_algo.c b/net/xfrm/xfrm_algo.c
|
|
index 58064d9..791ab2e 100644
|
|
--- a/net/xfrm/xfrm_algo.c
|
|
+++ b/net/xfrm/xfrm_algo.c
|
|
@@ -462,8 +462,8 @@ static struct xfrm_algo_desc ealg_list[] = {
|
|
.desc = {
|
|
.sadb_alg_id = SADB_X_EALG_AESCTR,
|
|
.sadb_alg_ivlen = 8,
|
|
- .sadb_alg_minbits = 128,
|
|
- .sadb_alg_maxbits = 256
|
|
+ .sadb_alg_minbits = 160,
|
|
+ .sadb_alg_maxbits = 288
|
|
}
|
|
},
|
|
};
|
|
diff --git a/sound/core/timer.c b/sound/core/timer.c
|
|
index 7c1cbf0..950eed0 100644
|
|
--- a/sound/core/timer.c
|
|
+++ b/sound/core/timer.c
|
|
@@ -531,6 +531,8 @@ int snd_timer_stop(struct snd_timer_instance *timeri)
|
|
if (err < 0)
|
|
return err;
|
|
timer = timeri->timer;
|
|
+ if (!timer)
|
|
+ return -EINVAL;
|
|
spin_lock_irqsave(&timer->lock, flags);
|
|
timeri->cticks = timeri->ticks;
|
|
timeri->pticks = 0;
|
|
diff --git a/sound/soc/codecs/sgtl5000.c b/sound/soc/codecs/sgtl5000.c
|
|
index ff29380..c49317c 100644
|
|
--- a/sound/soc/codecs/sgtl5000.c
|
|
+++ b/sound/soc/codecs/sgtl5000.c
|
|
@@ -33,73 +33,31 @@
|
|
#define SGTL5000_DAP_REG_OFFSET 0x0100
|
|
#define SGTL5000_MAX_REG_OFFSET 0x013A
|
|
|
|
-/* default value of sgtl5000 registers except DAP */
|
|
-static const u16 sgtl5000_regs[SGTL5000_MAX_REG_OFFSET >> 1] = {
|
|
- 0xa011, /* 0x0000, CHIP_ID. 11 stand for revison 17 */
|
|
- 0x0000, /* 0x0002, CHIP_DIG_POWER. */
|
|
- 0x0008, /* 0x0004, CHIP_CKL_CTRL */
|
|
- 0x0010, /* 0x0006, CHIP_I2S_CTRL */
|
|
- 0x0000, /* 0x0008, reserved */
|
|
- 0x0008, /* 0x000A, CHIP_SSS_CTRL */
|
|
- 0x0000, /* 0x000C, reserved */
|
|
- 0x020c, /* 0x000E, CHIP_ADCDAC_CTRL */
|
|
- 0x3c3c, /* 0x0010, CHIP_DAC_VOL */
|
|
- 0x0000, /* 0x0012, reserved */
|
|
- 0x015f, /* 0x0014, CHIP_PAD_STRENGTH */
|
|
- 0x0000, /* 0x0016, reserved */
|
|
- 0x0000, /* 0x0018, reserved */
|
|
- 0x0000, /* 0x001A, reserved */
|
|
- 0x0000, /* 0x001E, reserved */
|
|
- 0x0000, /* 0x0020, CHIP_ANA_ADC_CTRL */
|
|
- 0x1818, /* 0x0022, CHIP_ANA_HP_CTRL */
|
|
- 0x0111, /* 0x0024, CHIP_ANN_CTRL */
|
|
- 0x0000, /* 0x0026, CHIP_LINREG_CTRL */
|
|
- 0x0000, /* 0x0028, CHIP_REF_CTRL */
|
|
- 0x0000, /* 0x002A, CHIP_MIC_CTRL */
|
|
- 0x0000, /* 0x002C, CHIP_LINE_OUT_CTRL */
|
|
- 0x0404, /* 0x002E, CHIP_LINE_OUT_VOL */
|
|
- 0x7060, /* 0x0030, CHIP_ANA_POWER */
|
|
- 0x5000, /* 0x0032, CHIP_PLL_CTRL */
|
|
- 0x0000, /* 0x0034, CHIP_CLK_TOP_CTRL */
|
|
- 0x0000, /* 0x0036, CHIP_ANA_STATUS */
|
|
- 0x0000, /* 0x0038, reserved */
|
|
- 0x0000, /* 0x003A, CHIP_ANA_TEST2 */
|
|
- 0x0000, /* 0x003C, CHIP_SHORT_CTRL */
|
|
- 0x0000, /* reserved */
|
|
-};
|
|
-
|
|
-/* default value of dap registers */
|
|
-static const u16 sgtl5000_dap_regs[] = {
|
|
- 0x0000, /* 0x0100, DAP_CONTROL */
|
|
- 0x0000, /* 0x0102, DAP_PEQ */
|
|
- 0x0040, /* 0x0104, DAP_BASS_ENHANCE */
|
|
- 0x051f, /* 0x0106, DAP_BASS_ENHANCE_CTRL */
|
|
- 0x0000, /* 0x0108, DAP_AUDIO_EQ */
|
|
- 0x0040, /* 0x010A, DAP_SGTL_SURROUND */
|
|
- 0x0000, /* 0x010C, DAP_FILTER_COEF_ACCESS */
|
|
- 0x0000, /* 0x010E, DAP_COEF_WR_B0_MSB */
|
|
- 0x0000, /* 0x0110, DAP_COEF_WR_B0_LSB */
|
|
- 0x0000, /* 0x0112, reserved */
|
|
- 0x0000, /* 0x0114, reserved */
|
|
- 0x002f, /* 0x0116, DAP_AUDIO_EQ_BASS_BAND0 */
|
|
- 0x002f, /* 0x0118, DAP_AUDIO_EQ_BAND0 */
|
|
- 0x002f, /* 0x011A, DAP_AUDIO_EQ_BAND2 */
|
|
- 0x002f, /* 0x011C, DAP_AUDIO_EQ_BAND3 */
|
|
- 0x002f, /* 0x011E, DAP_AUDIO_EQ_TREBLE_BAND4 */
|
|
- 0x8000, /* 0x0120, DAP_MAIN_CHAN */
|
|
- 0x0000, /* 0x0122, DAP_MIX_CHAN */
|
|
- 0x0510, /* 0x0124, DAP_AVC_CTRL */
|
|
- 0x1473, /* 0x0126, DAP_AVC_THRESHOLD */
|
|
- 0x0028, /* 0x0128, DAP_AVC_ATTACK */
|
|
- 0x0050, /* 0x012A, DAP_AVC_DECAY */
|
|
- 0x0000, /* 0x012C, DAP_COEF_WR_B1_MSB */
|
|
- 0x0000, /* 0x012E, DAP_COEF_WR_B1_LSB */
|
|
- 0x0000, /* 0x0130, DAP_COEF_WR_B2_MSB */
|
|
- 0x0000, /* 0x0132, DAP_COEF_WR_B2_LSB */
|
|
- 0x0000, /* 0x0134, DAP_COEF_WR_A1_MSB */
|
|
- 0x0000, /* 0x0136, DAP_COEF_WR_A1_LSB */
|
|
- 0x0000, /* 0x0138, DAP_COEF_WR_A2_MSB */
|
|
- 0x0000, /* 0x013A, DAP_COEF_WR_A2_LSB */
|
|
+/* default value of sgtl5000 registers */
|
|
+static const u16 sgtl5000_regs[SGTL5000_MAX_REG_OFFSET] = {
|
|
+ [SGTL5000_CHIP_CLK_CTRL] = 0x0008,
|
|
+ [SGTL5000_CHIP_I2S_CTRL] = 0x0010,
|
|
+ [SGTL5000_CHIP_SSS_CTRL] = 0x0008,
|
|
+ [SGTL5000_CHIP_DAC_VOL] = 0x3c3c,
|
|
+ [SGTL5000_CHIP_PAD_STRENGTH] = 0x015f,
|
|
+ [SGTL5000_CHIP_ANA_HP_CTRL] = 0x1818,
|
|
+ [SGTL5000_CHIP_ANA_CTRL] = 0x0111,
|
|
+ [SGTL5000_CHIP_LINE_OUT_VOL] = 0x0404,
|
|
+ [SGTL5000_CHIP_ANA_POWER] = 0x7060,
|
|
+ [SGTL5000_CHIP_PLL_CTRL] = 0x5000,
|
|
+ [SGTL5000_DAP_BASS_ENHANCE] = 0x0040,
|
|
+ [SGTL5000_DAP_BASS_ENHANCE_CTRL] = 0x051f,
|
|
+ [SGTL5000_DAP_SURROUND] = 0x0040,
|
|
+ [SGTL5000_DAP_EQ_BASS_BAND0] = 0x002f,
|
|
+ [SGTL5000_DAP_EQ_BASS_BAND1] = 0x002f,
|
|
+ [SGTL5000_DAP_EQ_BASS_BAND2] = 0x002f,
|
|
+ [SGTL5000_DAP_EQ_BASS_BAND3] = 0x002f,
|
|
+ [SGTL5000_DAP_EQ_BASS_BAND4] = 0x002f,
|
|
+ [SGTL5000_DAP_MAIN_CHAN] = 0x8000,
|
|
+ [SGTL5000_DAP_AVC_CTRL] = 0x0510,
|
|
+ [SGTL5000_DAP_AVC_THRESHOLD] = 0x1473,
|
|
+ [SGTL5000_DAP_AVC_ATTACK] = 0x0028,
|
|
+ [SGTL5000_DAP_AVC_DECAY] = 0x0050,
|
|
};
|
|
|
|
/* regulator supplies for sgtl5000, VDDD is an optional external supply */
|
|
@@ -1022,12 +980,10 @@ static int sgtl5000_suspend(struct snd_soc_codec *codec, pm_message_t state)
|
|
static int sgtl5000_restore_regs(struct snd_soc_codec *codec)
|
|
{
|
|
u16 *cache = codec->reg_cache;
|
|
- int i;
|
|
- int regular_regs = SGTL5000_CHIP_SHORT_CTRL >> 1;
|
|
+ u16 reg;
|
|
|
|
/* restore regular registers */
|
|
- for (i = 0; i < regular_regs; i++) {
|
|
- int reg = i << 1;
|
|
+ for (reg = 0; reg <= SGTL5000_CHIP_SHORT_CTRL; reg += 2) {
|
|
|
|
/* this regs depends on the others */
|
|
if (reg == SGTL5000_CHIP_ANA_POWER ||
|
|
@@ -1037,35 +993,31 @@ static int sgtl5000_restore_regs(struct snd_soc_codec *codec)
|
|
reg == SGTL5000_CHIP_CLK_CTRL)
|
|
continue;
|
|
|
|
- snd_soc_write(codec, reg, cache[i]);
|
|
+ snd_soc_write(codec, reg, cache[reg]);
|
|
}
|
|
|
|
/* restore dap registers */
|
|
- for (i = SGTL5000_DAP_REG_OFFSET >> 1;
|
|
- i < SGTL5000_MAX_REG_OFFSET >> 1; i++) {
|
|
- int reg = i << 1;
|
|
-
|
|
- snd_soc_write(codec, reg, cache[i]);
|
|
- }
|
|
+ for (reg = SGTL5000_DAP_REG_OFFSET; reg < SGTL5000_MAX_REG_OFFSET; reg += 2)
|
|
+ snd_soc_write(codec, reg, cache[reg]);
|
|
|
|
/*
|
|
* restore power and other regs according
|
|
* to set_power() and set_clock()
|
|
*/
|
|
snd_soc_write(codec, SGTL5000_CHIP_LINREG_CTRL,
|
|
- cache[SGTL5000_CHIP_LINREG_CTRL >> 1]);
|
|
+ cache[SGTL5000_CHIP_LINREG_CTRL]);
|
|
|
|
snd_soc_write(codec, SGTL5000_CHIP_ANA_POWER,
|
|
- cache[SGTL5000_CHIP_ANA_POWER >> 1]);
|
|
+ cache[SGTL5000_CHIP_ANA_POWER]);
|
|
|
|
snd_soc_write(codec, SGTL5000_CHIP_CLK_CTRL,
|
|
- cache[SGTL5000_CHIP_CLK_CTRL >> 1]);
|
|
+ cache[SGTL5000_CHIP_CLK_CTRL]);
|
|
|
|
snd_soc_write(codec, SGTL5000_CHIP_REF_CTRL,
|
|
- cache[SGTL5000_CHIP_REF_CTRL >> 1]);
|
|
+ cache[SGTL5000_CHIP_REF_CTRL]);
|
|
|
|
snd_soc_write(codec, SGTL5000_CHIP_LINE_OUT_CTRL,
|
|
- cache[SGTL5000_CHIP_LINE_OUT_CTRL >> 1]);
|
|
+ cache[SGTL5000_CHIP_LINE_OUT_CTRL]);
|
|
return 0;
|
|
}
|
|
|
|
@@ -1460,16 +1412,6 @@ static __devinit int sgtl5000_i2c_probe(struct i2c_client *client,
|
|
if (!sgtl5000)
|
|
return -ENOMEM;
|
|
|
|
- /*
|
|
- * copy DAP default values to default value array.
|
|
- * sgtl5000 register space has a big hole, merge it
|
|
- * at init phase makes life easy.
|
|
- * FIXME: should we drop 'const' of sgtl5000_regs?
|
|
- */
|
|
- memcpy((void *)(&sgtl5000_regs[0] + (SGTL5000_DAP_REG_OFFSET >> 1)),
|
|
- sgtl5000_dap_regs,
|
|
- SGTL5000_MAX_REG_OFFSET - SGTL5000_DAP_REG_OFFSET);
|
|
-
|
|
i2c_set_clientdata(client, sgtl5000);
|
|
|
|
ret = snd_soc_register_codec(&client->dev,
|
|
diff --git a/sound/usb/caiaq/input.c b/sound/usb/caiaq/input.c
|
|
index 4432ef7..a213813 100644
|
|
--- a/sound/usb/caiaq/input.c
|
|
+++ b/sound/usb/caiaq/input.c
|
|
@@ -30,7 +30,7 @@ static unsigned short keycode_ak1[] = { KEY_C, KEY_B, KEY_A };
|
|
static unsigned short keycode_rk2[] = { KEY_1, KEY_2, KEY_3, KEY_4,
|
|
KEY_5, KEY_6, KEY_7 };
|
|
static unsigned short keycode_rk3[] = { KEY_1, KEY_2, KEY_3, KEY_4,
|
|
- KEY_5, KEY_6, KEY_7, KEY_5, KEY_6 };
|
|
+ KEY_5, KEY_6, KEY_7, KEY_8, KEY_9 };
|
|
|
|
static unsigned short keycode_kore[] = {
|
|
KEY_FN_F1, /* "menu" */
|
|
diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c
|
|
index b0ef9f5..05842c8 100644
|
|
--- a/sound/usb/endpoint.c
|
|
+++ b/sound/usb/endpoint.c
|
|
@@ -352,7 +352,7 @@ int snd_usb_parse_audio_endpoints(struct snd_usb_audio *chip, int iface_no)
|
|
continue;
|
|
}
|
|
if (((protocol == UAC_VERSION_1) && (fmt->bLength < 8)) ||
|
|
- ((protocol == UAC_VERSION_2) && (fmt->bLength != 6))) {
|
|
+ ((protocol == UAC_VERSION_2) && (fmt->bLength < 6))) {
|
|
snd_printk(KERN_ERR "%d:%u:%d : invalid UAC_FORMAT_TYPE desc\n",
|
|
dev->devnum, iface_no, altno);
|
|
continue;
|
|
diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c
|
|
index c22fa76..c04d7c7 100644
|
|
--- a/sound/usb/mixer.c
|
|
+++ b/sound/usb/mixer.c
|
|
@@ -1191,6 +1191,11 @@ static int parse_audio_feature_unit(struct mixer_build *state, int unitid, void
|
|
|
|
if (state->mixer->protocol == UAC_VERSION_1) {
|
|
csize = hdr->bControlSize;
|
|
+ if (!csize) {
|
|
+ snd_printdd(KERN_ERR "usbaudio: unit %u: "
|
|
+ "invalid bControlSize == 0\n", unitid);
|
|
+ return -EINVAL;
|
|
+ }
|
|
channels = (hdr->bLength - 7) / csize - 1;
|
|
bmaControls = hdr->bmaControls;
|
|
} else {
|
|
@@ -1934,15 +1939,13 @@ static int snd_usb_mixer_controls(struct usb_mixer_interface *mixer)
|
|
struct mixer_build state;
|
|
int err;
|
|
const struct usbmix_ctl_map *map;
|
|
- struct usb_host_interface *hostif;
|
|
void *p;
|
|
|
|
- hostif = mixer->chip->ctrl_intf;
|
|
memset(&state, 0, sizeof(state));
|
|
state.chip = mixer->chip;
|
|
state.mixer = mixer;
|
|
- state.buffer = hostif->extra;
|
|
- state.buflen = hostif->extralen;
|
|
+ state.buffer = mixer->hostif->extra;
|
|
+ state.buflen = mixer->hostif->extralen;
|
|
|
|
/* check the mapping table */
|
|
for (map = usbmix_ctl_maps; map->id; map++) {
|
|
@@ -1955,7 +1958,8 @@ static int snd_usb_mixer_controls(struct usb_mixer_interface *mixer)
|
|
}
|
|
|
|
p = NULL;
|
|
- while ((p = snd_usb_find_csint_desc(hostif->extra, hostif->extralen, p, UAC_OUTPUT_TERMINAL)) != NULL) {
|
|
+ while ((p = snd_usb_find_csint_desc(mixer->hostif->extra, mixer->hostif->extralen,
|
|
+ p, UAC_OUTPUT_TERMINAL)) != NULL) {
|
|
if (mixer->protocol == UAC_VERSION_1) {
|
|
struct uac1_output_terminal_descriptor *desc = p;
|
|
|
|
@@ -2162,17 +2166,15 @@ int snd_usb_mixer_activate(struct usb_mixer_interface *mixer)
|
|
/* create the handler for the optional status interrupt endpoint */
|
|
static int snd_usb_mixer_status_create(struct usb_mixer_interface *mixer)
|
|
{
|
|
- struct usb_host_interface *hostif;
|
|
struct usb_endpoint_descriptor *ep;
|
|
void *transfer_buffer;
|
|
int buffer_length;
|
|
unsigned int epnum;
|
|
|
|
- hostif = mixer->chip->ctrl_intf;
|
|
/* we need one interrupt input endpoint */
|
|
- if (get_iface_desc(hostif)->bNumEndpoints < 1)
|
|
+ if (get_iface_desc(mixer->hostif)->bNumEndpoints < 1)
|
|
return 0;
|
|
- ep = get_endpoint(hostif, 0);
|
|
+ ep = get_endpoint(mixer->hostif, 0);
|
|
if (!usb_endpoint_dir_in(ep) || !usb_endpoint_xfer_int(ep))
|
|
return 0;
|
|
|
|
@@ -2202,7 +2204,6 @@ int snd_usb_create_mixer(struct snd_usb_audio *chip, int ctrlif,
|
|
};
|
|
struct usb_mixer_interface *mixer;
|
|
struct snd_info_entry *entry;
|
|
- struct usb_host_interface *host_iface;
|
|
int err;
|
|
|
|
strcpy(chip->card->mixername, "USB Mixer");
|
|
@@ -2219,8 +2220,8 @@ int snd_usb_create_mixer(struct snd_usb_audio *chip, int ctrlif,
|
|
return -ENOMEM;
|
|
}
|
|
|
|
- host_iface = &usb_ifnum_to_if(chip->dev, ctrlif)->altsetting[0];
|
|
- switch (get_iface_desc(host_iface)->bInterfaceProtocol) {
|
|
+ mixer->hostif = &usb_ifnum_to_if(chip->dev, ctrlif)->altsetting[0];
|
|
+ switch (get_iface_desc(mixer->hostif)->bInterfaceProtocol) {
|
|
case UAC_VERSION_1:
|
|
default:
|
|
mixer->protocol = UAC_VERSION_1;
|
|
diff --git a/sound/usb/mixer.h b/sound/usb/mixer.h
|
|
index ae1a14d..81b2d8a 100644
|
|
--- a/sound/usb/mixer.h
|
|
+++ b/sound/usb/mixer.h
|
|
@@ -3,6 +3,7 @@
|
|
|
|
struct usb_mixer_interface {
|
|
struct snd_usb_audio *chip;
|
|
+ struct usb_host_interface *hostif;
|
|
struct list_head list;
|
|
unsigned int ignore_ctl_error;
|
|
struct urb *urb;
|