Merge tag 'fscache-fixes-for-ceph' into wip-fscache
Patches for Ceph FS-Cache support
This commit is contained in:
@@ -299,6 +299,15 @@ performed on the denizens of the cache. These are held in a structure of type:
|
|||||||
enough space in the cache to permit this.
|
enough space in the cache to permit this.
|
||||||
|
|
||||||
|
|
||||||
|
(*) Check coherency state of an object [mandatory]:
|
||||||
|
|
||||||
|
int (*check_consistency)(struct fscache_object *object)
|
||||||
|
|
||||||
|
This method is called to have the cache check the saved auxiliary data of
|
||||||
|
the object against the netfs's idea of the state. 0 should be returned
|
||||||
|
if they're consistent and -ESTALE otherwise. -ENOMEM and -ERESTARTSYS
|
||||||
|
may also be returned.
|
||||||
|
|
||||||
(*) Update object [mandatory]:
|
(*) Update object [mandatory]:
|
||||||
|
|
||||||
int (*update_object)(struct fscache_object *object)
|
int (*update_object)(struct fscache_object *object)
|
||||||
|
@@ -32,7 +32,7 @@ This document contains the following sections:
|
|||||||
(9) Setting the data file size
|
(9) Setting the data file size
|
||||||
(10) Page alloc/read/write
|
(10) Page alloc/read/write
|
||||||
(11) Page uncaching
|
(11) Page uncaching
|
||||||
(12) Index and data file update
|
(12) Index and data file consistency
|
||||||
(13) Miscellaneous cookie operations
|
(13) Miscellaneous cookie operations
|
||||||
(14) Cookie unregistration
|
(14) Cookie unregistration
|
||||||
(15) Index invalidation
|
(15) Index invalidation
|
||||||
@@ -433,7 +433,7 @@ to the caller. The attribute adjustment excludes read and write operations.
|
|||||||
|
|
||||||
|
|
||||||
=====================
|
=====================
|
||||||
PAGE READ/ALLOC/WRITE
|
PAGE ALLOC/READ/WRITE
|
||||||
=====================
|
=====================
|
||||||
|
|
||||||
And the sixth step is to store and retrieve pages in the cache. There are
|
And the sixth step is to store and retrieve pages in the cache. There are
|
||||||
@@ -499,7 +499,7 @@ Else if there's a copy of the page resident in the cache:
|
|||||||
(*) An argument that's 0 on success or negative for an error code.
|
(*) An argument that's 0 on success or negative for an error code.
|
||||||
|
|
||||||
If an error occurs, it should be assumed that the page contains no usable
|
If an error occurs, it should be assumed that the page contains no usable
|
||||||
data.
|
data. fscache_readpages_cancel() may need to be called.
|
||||||
|
|
||||||
end_io_func() will be called in process context if the read is results in
|
end_io_func() will be called in process context if the read is results in
|
||||||
an error, but it might be called in interrupt context if the read is
|
an error, but it might be called in interrupt context if the read is
|
||||||
@@ -623,6 +623,22 @@ some of the pages being read and some being allocated. Those pages will have
|
|||||||
been marked appropriately and will need uncaching.
|
been marked appropriately and will need uncaching.
|
||||||
|
|
||||||
|
|
||||||
|
CANCELLATION OF UNREAD PAGES
|
||||||
|
----------------------------
|
||||||
|
|
||||||
|
If one or more pages are passed to fscache_read_or_alloc_pages() but not then
|
||||||
|
read from the cache and also not read from the underlying filesystem then
|
||||||
|
those pages will need to have any marks and reservations removed. This can be
|
||||||
|
done by calling:
|
||||||
|
|
||||||
|
void fscache_readpages_cancel(struct fscache_cookie *cookie,
|
||||||
|
struct list_head *pages);
|
||||||
|
|
||||||
|
prior to returning to the caller. The cookie argument should be as passed to
|
||||||
|
fscache_read_or_alloc_pages(). Every page in the pages list will be examined
|
||||||
|
and any that have PG_fscache set will be uncached.
|
||||||
|
|
||||||
|
|
||||||
==============
|
==============
|
||||||
PAGE UNCACHING
|
PAGE UNCACHING
|
||||||
==============
|
==============
|
||||||
@@ -690,9 +706,18 @@ written to the cache and for the cache to finish with the page generally. No
|
|||||||
error is returned.
|
error is returned.
|
||||||
|
|
||||||
|
|
||||||
==========================
|
===============================
|
||||||
INDEX AND DATA FILE UPDATE
|
INDEX AND DATA FILE CONSISTENCY
|
||||||
==========================
|
===============================
|
||||||
|
|
||||||
|
To find out whether auxiliary data for an object is up to data within the
|
||||||
|
cache, the following function can be called:
|
||||||
|
|
||||||
|
int fscache_check_consistency(struct fscache_cookie *cookie)
|
||||||
|
|
||||||
|
This will call back to the netfs to check whether the auxiliary data associated
|
||||||
|
with a cookie is correct. It returns 0 if it is and -ESTALE if it isn't; it
|
||||||
|
may also return -ENOMEM and -ERESTARTSYS.
|
||||||
|
|
||||||
To request an update of the index data for an index or other object, the
|
To request an update of the index data for an index or other object, the
|
||||||
following function should be called:
|
following function should be called:
|
||||||
|
@@ -2953,7 +2953,7 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
|
|||||||
improve throughput, but will also increase the
|
improve throughput, but will also increase the
|
||||||
amount of memory reserved for use by the client.
|
amount of memory reserved for use by the client.
|
||||||
|
|
||||||
swapaccount[=0|1]
|
swapaccount=[0|1]
|
||||||
[KNL] Enable accounting of swap in memory resource
|
[KNL] Enable accounting of swap in memory resource
|
||||||
controller if no parameter or 1 is given or disable
|
controller if no parameter or 1 is given or disable
|
||||||
it if 0 is given (See Documentation/cgroups/memory.txt)
|
it if 0 is given (See Documentation/cgroups/memory.txt)
|
||||||
|
16
MAINTAINERS
16
MAINTAINERS
@@ -5581,9 +5581,9 @@ S: Maintained
|
|||||||
F: drivers/media/tuners/mxl5007t.*
|
F: drivers/media/tuners/mxl5007t.*
|
||||||
|
|
||||||
MYRICOM MYRI-10G 10GbE DRIVER (MYRI10GE)
|
MYRICOM MYRI-10G 10GbE DRIVER (MYRI10GE)
|
||||||
M: Andrew Gallatin <gallatin@myri.com>
|
M: Hyong-Youb Kim <hykim@myri.com>
|
||||||
L: netdev@vger.kernel.org
|
L: netdev@vger.kernel.org
|
||||||
W: http://www.myri.com/scs/download-Myri10GE.html
|
W: https://www.myricom.com/support/downloads/myri10ge.html
|
||||||
S: Supported
|
S: Supported
|
||||||
F: drivers/net/ethernet/myricom/myri10ge/
|
F: drivers/net/ethernet/myricom/myri10ge/
|
||||||
|
|
||||||
@@ -5884,7 +5884,7 @@ F: drivers/i2c/busses/i2c-omap.c
|
|||||||
F: include/linux/i2c-omap.h
|
F: include/linux/i2c-omap.h
|
||||||
|
|
||||||
OMAP DEVICE TREE SUPPORT
|
OMAP DEVICE TREE SUPPORT
|
||||||
M: Benoît Cousson <b-cousson@ti.com>
|
M: Benoît Cousson <bcousson@baylibre.com>
|
||||||
M: Tony Lindgren <tony@atomide.com>
|
M: Tony Lindgren <tony@atomide.com>
|
||||||
L: linux-omap@vger.kernel.org
|
L: linux-omap@vger.kernel.org
|
||||||
L: devicetree@vger.kernel.org
|
L: devicetree@vger.kernel.org
|
||||||
@@ -5964,14 +5964,14 @@ S: Maintained
|
|||||||
F: drivers/char/hw_random/omap-rng.c
|
F: drivers/char/hw_random/omap-rng.c
|
||||||
|
|
||||||
OMAP HWMOD SUPPORT
|
OMAP HWMOD SUPPORT
|
||||||
M: Benoît Cousson <b-cousson@ti.com>
|
M: Benoît Cousson <bcousson@baylibre.com>
|
||||||
M: Paul Walmsley <paul@pwsan.com>
|
M: Paul Walmsley <paul@pwsan.com>
|
||||||
L: linux-omap@vger.kernel.org
|
L: linux-omap@vger.kernel.org
|
||||||
S: Maintained
|
S: Maintained
|
||||||
F: arch/arm/mach-omap2/omap_hwmod.*
|
F: arch/arm/mach-omap2/omap_hwmod.*
|
||||||
|
|
||||||
OMAP HWMOD DATA FOR OMAP4-BASED DEVICES
|
OMAP HWMOD DATA FOR OMAP4-BASED DEVICES
|
||||||
M: Benoît Cousson <b-cousson@ti.com>
|
M: Benoît Cousson <bcousson@baylibre.com>
|
||||||
L: linux-omap@vger.kernel.org
|
L: linux-omap@vger.kernel.org
|
||||||
S: Maintained
|
S: Maintained
|
||||||
F: arch/arm/mach-omap2/omap_hwmod_44xx_data.c
|
F: arch/arm/mach-omap2/omap_hwmod_44xx_data.c
|
||||||
@@ -6066,7 +6066,7 @@ M: Rob Herring <rob.herring@calxeda.com>
|
|||||||
M: Pawel Moll <pawel.moll@arm.com>
|
M: Pawel Moll <pawel.moll@arm.com>
|
||||||
M: Mark Rutland <mark.rutland@arm.com>
|
M: Mark Rutland <mark.rutland@arm.com>
|
||||||
M: Stephen Warren <swarren@wwwdotorg.org>
|
M: Stephen Warren <swarren@wwwdotorg.org>
|
||||||
M: Ian Campbell <ian.campbell@citrix.com>
|
M: Ian Campbell <ijc+devicetree@hellion.org.uk>
|
||||||
L: devicetree@vger.kernel.org
|
L: devicetree@vger.kernel.org
|
||||||
S: Maintained
|
S: Maintained
|
||||||
F: Documentation/devicetree/
|
F: Documentation/devicetree/
|
||||||
@@ -7366,7 +7366,6 @@ F: drivers/net/ethernet/sfc/
|
|||||||
|
|
||||||
SGI GRU DRIVER
|
SGI GRU DRIVER
|
||||||
M: Dimitri Sivanich <sivanich@sgi.com>
|
M: Dimitri Sivanich <sivanich@sgi.com>
|
||||||
M: Robin Holt <holt@sgi.com>
|
|
||||||
S: Maintained
|
S: Maintained
|
||||||
F: drivers/misc/sgi-gru/
|
F: drivers/misc/sgi-gru/
|
||||||
|
|
||||||
@@ -7386,7 +7385,8 @@ S: Maintained for 2.6.
|
|||||||
F: Documentation/sgi-visws.txt
|
F: Documentation/sgi-visws.txt
|
||||||
|
|
||||||
SGI XP/XPC/XPNET DRIVER
|
SGI XP/XPC/XPNET DRIVER
|
||||||
M: Robin Holt <holt@sgi.com>
|
M: Cliff Whickman <cpw@sgi.com>
|
||||||
|
M: Robin Holt <robinmholt@gmail.com>
|
||||||
S: Maintained
|
S: Maintained
|
||||||
F: drivers/misc/sgi-xp/
|
F: drivers/misc/sgi-xp/
|
||||||
|
|
||||||
|
2
Makefile
2
Makefile
@@ -1,7 +1,7 @@
|
|||||||
VERSION = 3
|
VERSION = 3
|
||||||
PATCHLEVEL = 11
|
PATCHLEVEL = 11
|
||||||
SUBLEVEL = 0
|
SUBLEVEL = 0
|
||||||
EXTRAVERSION = -rc5
|
EXTRAVERSION =
|
||||||
NAME = Linux for Workgroups
|
NAME = Linux for Workgroups
|
||||||
|
|
||||||
# *DOCUMENTATION*
|
# *DOCUMENTATION*
|
||||||
|
@@ -39,9 +39,18 @@ ARC_ENTRY strchr
|
|||||||
ld.a r2,[r0,4]
|
ld.a r2,[r0,4]
|
||||||
sub r12,r6,r7
|
sub r12,r6,r7
|
||||||
bic r12,r12,r6
|
bic r12,r12,r6
|
||||||
|
#ifdef __LITTLE_ENDIAN__
|
||||||
and r7,r12,r4
|
and r7,r12,r4
|
||||||
breq r7,0,.Loop ; For speed, we want this branch to be unaligned.
|
breq r7,0,.Loop ; For speed, we want this branch to be unaligned.
|
||||||
b .Lfound_char ; Likewise this one.
|
b .Lfound_char ; Likewise this one.
|
||||||
|
#else
|
||||||
|
and r12,r12,r4
|
||||||
|
breq r12,0,.Loop ; For speed, we want this branch to be unaligned.
|
||||||
|
lsr_s r12,r12,7
|
||||||
|
bic r2,r7,r6
|
||||||
|
b.d .Lfound_char_b
|
||||||
|
and_s r2,r2,r12
|
||||||
|
#endif
|
||||||
; /* We require this code address to be unaligned for speed... */
|
; /* We require this code address to be unaligned for speed... */
|
||||||
.Laligned:
|
.Laligned:
|
||||||
ld_s r2,[r0]
|
ld_s r2,[r0]
|
||||||
@@ -95,6 +104,7 @@ ARC_ENTRY strchr
|
|||||||
lsr r7,r7,7
|
lsr r7,r7,7
|
||||||
|
|
||||||
bic r2,r7,r6
|
bic r2,r7,r6
|
||||||
|
.Lfound_char_b:
|
||||||
norm r2,r2
|
norm r2,r2
|
||||||
sub_s r0,r0,4
|
sub_s r0,r0,4
|
||||||
asr_s r2,r2,3
|
asr_s r2,r2,3
|
||||||
|
@@ -14,11 +14,11 @@
|
|||||||
compatible = "atmel,at91sam9n12ek", "atmel,at91sam9n12", "atmel,at91sam9";
|
compatible = "atmel,at91sam9n12ek", "atmel,at91sam9n12", "atmel,at91sam9";
|
||||||
|
|
||||||
chosen {
|
chosen {
|
||||||
bootargs = "mem=128M console=ttyS0,115200 root=/dev/mtdblock1 rw rootfstype=jffs2";
|
bootargs = "console=ttyS0,115200 root=/dev/mtdblock1 rw rootfstype=jffs2";
|
||||||
};
|
};
|
||||||
|
|
||||||
memory {
|
memory {
|
||||||
reg = <0x20000000 0x10000000>;
|
reg = <0x20000000 0x8000000>;
|
||||||
};
|
};
|
||||||
|
|
||||||
clocks {
|
clocks {
|
||||||
|
@@ -94,8 +94,9 @@
|
|||||||
|
|
||||||
usb0: ohci@00600000 {
|
usb0: ohci@00600000 {
|
||||||
status = "okay";
|
status = "okay";
|
||||||
num-ports = <2>;
|
num-ports = <3>;
|
||||||
atmel,vbus-gpio = <&pioD 19 GPIO_ACTIVE_LOW
|
atmel,vbus-gpio = <0 /* &pioD 18 GPIO_ACTIVE_LOW *//* Activate to have access to port A */
|
||||||
|
&pioD 19 GPIO_ACTIVE_LOW
|
||||||
&pioD 20 GPIO_ACTIVE_LOW
|
&pioD 20 GPIO_ACTIVE_LOW
|
||||||
>;
|
>;
|
||||||
};
|
};
|
||||||
|
@@ -830,6 +830,8 @@
|
|||||||
regulator-max-microvolt = <5000000>;
|
regulator-max-microvolt = <5000000>;
|
||||||
enable-active-high;
|
enable-active-high;
|
||||||
gpio = <&gpio 24 0>; /* PD0 */
|
gpio = <&gpio 24 0>; /* PD0 */
|
||||||
|
regulator-always-on;
|
||||||
|
regulator-boot-on;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -412,6 +412,8 @@
|
|||||||
regulator-max-microvolt = <5000000>;
|
regulator-max-microvolt = <5000000>;
|
||||||
enable-active-high;
|
enable-active-high;
|
||||||
gpio = <&gpio 170 0>; /* PV2 */
|
gpio = <&gpio 170 0>; /* PV2 */
|
||||||
|
regulator-always-on;
|
||||||
|
regulator-boot-on;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -588,6 +588,8 @@
|
|||||||
regulator-max-microvolt = <5000000>;
|
regulator-max-microvolt = <5000000>;
|
||||||
enable-active-high;
|
enable-active-high;
|
||||||
gpio = <&tca6416 0 0>; /* GPIO_PMU0 */
|
gpio = <&tca6416 0 0>; /* GPIO_PMU0 */
|
||||||
|
regulator-always-on;
|
||||||
|
regulator-boot-on;
|
||||||
};
|
};
|
||||||
|
|
||||||
vbus3_reg: regulator@3 {
|
vbus3_reg: regulator@3 {
|
||||||
@@ -598,6 +600,8 @@
|
|||||||
regulator-max-microvolt = <5000000>;
|
regulator-max-microvolt = <5000000>;
|
||||||
enable-active-high;
|
enable-active-high;
|
||||||
gpio = <&tca6416 1 0>; /* GPIO_PMU1 */
|
gpio = <&tca6416 1 0>; /* GPIO_PMU1 */
|
||||||
|
regulator-always-on;
|
||||||
|
regulator-boot-on;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -88,4 +88,7 @@ static inline u32 mpidr_hash_size(void)
|
|||||||
{
|
{
|
||||||
return 1 << mpidr_hash.bits;
|
return 1 << mpidr_hash.bits;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern int platform_can_cpu_hotplug(void);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@@ -107,7 +107,7 @@ static inline int arch_spin_trylock(arch_spinlock_t *lock)
|
|||||||
" subs %1, %0, %0, ror #16\n"
|
" subs %1, %0, %0, ror #16\n"
|
||||||
" addeq %0, %0, %4\n"
|
" addeq %0, %0, %4\n"
|
||||||
" strexeq %2, %0, [%3]"
|
" strexeq %2, %0, [%3]"
|
||||||
: "=&r" (slock), "=&r" (contended), "=r" (res)
|
: "=&r" (slock), "=&r" (contended), "=&r" (res)
|
||||||
: "r" (&lock->slock), "I" (1 << TICKET_SHIFT)
|
: "r" (&lock->slock), "I" (1 << TICKET_SHIFT)
|
||||||
: "cc");
|
: "cc");
|
||||||
} while (res);
|
} while (res);
|
||||||
@@ -168,17 +168,20 @@ static inline void arch_write_lock(arch_rwlock_t *rw)
|
|||||||
|
|
||||||
static inline int arch_write_trylock(arch_rwlock_t *rw)
|
static inline int arch_write_trylock(arch_rwlock_t *rw)
|
||||||
{
|
{
|
||||||
unsigned long tmp;
|
unsigned long contended, res;
|
||||||
|
|
||||||
__asm__ __volatile__(
|
do {
|
||||||
" ldrex %0, [%1]\n"
|
__asm__ __volatile__(
|
||||||
" teq %0, #0\n"
|
" ldrex %0, [%2]\n"
|
||||||
" strexeq %0, %2, [%1]"
|
" mov %1, #0\n"
|
||||||
: "=&r" (tmp)
|
" teq %0, #0\n"
|
||||||
: "r" (&rw->lock), "r" (0x80000000)
|
" strexeq %1, %3, [%2]"
|
||||||
: "cc");
|
: "=&r" (contended), "=&r" (res)
|
||||||
|
: "r" (&rw->lock), "r" (0x80000000)
|
||||||
|
: "cc");
|
||||||
|
} while (res);
|
||||||
|
|
||||||
if (tmp == 0) {
|
if (!contended) {
|
||||||
smp_mb();
|
smp_mb();
|
||||||
return 1;
|
return 1;
|
||||||
} else {
|
} else {
|
||||||
@@ -254,18 +257,26 @@ static inline void arch_read_unlock(arch_rwlock_t *rw)
|
|||||||
|
|
||||||
static inline int arch_read_trylock(arch_rwlock_t *rw)
|
static inline int arch_read_trylock(arch_rwlock_t *rw)
|
||||||
{
|
{
|
||||||
unsigned long tmp, tmp2 = 1;
|
unsigned long contended, res;
|
||||||
|
|
||||||
__asm__ __volatile__(
|
do {
|
||||||
" ldrex %0, [%2]\n"
|
__asm__ __volatile__(
|
||||||
" adds %0, %0, #1\n"
|
" ldrex %0, [%2]\n"
|
||||||
" strexpl %1, %0, [%2]\n"
|
" mov %1, #0\n"
|
||||||
: "=&r" (tmp), "+r" (tmp2)
|
" adds %0, %0, #1\n"
|
||||||
: "r" (&rw->lock)
|
" strexpl %1, %0, [%2]"
|
||||||
: "cc");
|
: "=&r" (contended), "=&r" (res)
|
||||||
|
: "r" (&rw->lock)
|
||||||
|
: "cc");
|
||||||
|
} while (res);
|
||||||
|
|
||||||
smp_mb();
|
/* If the lock is negative, then it is already held for write. */
|
||||||
return tmp2 == 0;
|
if (contended < 0x80000000) {
|
||||||
|
smp_mb();
|
||||||
|
return 1;
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* read_can_lock - would read_trylock() succeed? */
|
/* read_can_lock - would read_trylock() succeed? */
|
||||||
|
@@ -43,6 +43,7 @@ struct mmu_gather {
|
|||||||
struct mm_struct *mm;
|
struct mm_struct *mm;
|
||||||
unsigned int fullmm;
|
unsigned int fullmm;
|
||||||
struct vm_area_struct *vma;
|
struct vm_area_struct *vma;
|
||||||
|
unsigned long start, end;
|
||||||
unsigned long range_start;
|
unsigned long range_start;
|
||||||
unsigned long range_end;
|
unsigned long range_end;
|
||||||
unsigned int nr;
|
unsigned int nr;
|
||||||
@@ -107,10 +108,12 @@ static inline void tlb_flush_mmu(struct mmu_gather *tlb)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
tlb_gather_mmu(struct mmu_gather *tlb, struct mm_struct *mm, unsigned int fullmm)
|
tlb_gather_mmu(struct mmu_gather *tlb, struct mm_struct *mm, unsigned long start, unsigned long end)
|
||||||
{
|
{
|
||||||
tlb->mm = mm;
|
tlb->mm = mm;
|
||||||
tlb->fullmm = fullmm;
|
tlb->fullmm = !(start | (end+1));
|
||||||
|
tlb->start = start;
|
||||||
|
tlb->end = end;
|
||||||
tlb->vma = NULL;
|
tlb->vma = NULL;
|
||||||
tlb->max = ARRAY_SIZE(tlb->local);
|
tlb->max = ARRAY_SIZE(tlb->local);
|
||||||
tlb->pages = tlb->local;
|
tlb->pages = tlb->local;
|
||||||
|
@@ -357,7 +357,8 @@ ENDPROC(__pabt_svc)
|
|||||||
.endm
|
.endm
|
||||||
|
|
||||||
.macro kuser_cmpxchg_check
|
.macro kuser_cmpxchg_check
|
||||||
#if !defined(CONFIG_CPU_32v6K) && !defined(CONFIG_NEEDS_SYSCALL_FOR_CMPXCHG)
|
#if !defined(CONFIG_CPU_32v6K) && defined(CONFIG_KUSER_HELPERS) && \
|
||||||
|
!defined(CONFIG_NEEDS_SYSCALL_FOR_CMPXCHG)
|
||||||
#ifndef CONFIG_MMU
|
#ifndef CONFIG_MMU
|
||||||
#warning "NPTL on non MMU needs fixing"
|
#warning "NPTL on non MMU needs fixing"
|
||||||
#else
|
#else
|
||||||
|
@@ -84,17 +84,14 @@ int show_fiq_list(struct seq_file *p, int prec)
|
|||||||
|
|
||||||
void set_fiq_handler(void *start, unsigned int length)
|
void set_fiq_handler(void *start, unsigned int length)
|
||||||
{
|
{
|
||||||
#if defined(CONFIG_CPU_USE_DOMAINS)
|
|
||||||
void *base = (void *)0xffff0000;
|
|
||||||
#else
|
|
||||||
void *base = vectors_page;
|
void *base = vectors_page;
|
||||||
#endif
|
|
||||||
unsigned offset = FIQ_OFFSET;
|
unsigned offset = FIQ_OFFSET;
|
||||||
|
|
||||||
memcpy(base + offset, start, length);
|
memcpy(base + offset, start, length);
|
||||||
|
if (!cache_is_vipt_nonaliasing())
|
||||||
|
flush_icache_range((unsigned long)base + offset, offset +
|
||||||
|
length);
|
||||||
flush_icache_range(0xffff0000 + offset, 0xffff0000 + offset + length);
|
flush_icache_range(0xffff0000 + offset, 0xffff0000 + offset + length);
|
||||||
if (!vectors_high())
|
|
||||||
flush_icache_range(offset, offset + length);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int claim_fiq(struct fiq_handler *f)
|
int claim_fiq(struct fiq_handler *f)
|
||||||
|
@@ -15,6 +15,7 @@
|
|||||||
#include <asm/mmu_context.h>
|
#include <asm/mmu_context.h>
|
||||||
#include <asm/cacheflush.h>
|
#include <asm/cacheflush.h>
|
||||||
#include <asm/mach-types.h>
|
#include <asm/mach-types.h>
|
||||||
|
#include <asm/smp_plat.h>
|
||||||
#include <asm/system_misc.h>
|
#include <asm/system_misc.h>
|
||||||
|
|
||||||
extern const unsigned char relocate_new_kernel[];
|
extern const unsigned char relocate_new_kernel[];
|
||||||
@@ -38,6 +39,14 @@ int machine_kexec_prepare(struct kimage *image)
|
|||||||
__be32 header;
|
__be32 header;
|
||||||
int i, err;
|
int i, err;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Validate that if the current HW supports SMP, then the SW supports
|
||||||
|
* and implements CPU hotplug for the current HW. If not, we won't be
|
||||||
|
* able to kexec reliably, so fail the prepare operation.
|
||||||
|
*/
|
||||||
|
if (num_possible_cpus() > 1 && !platform_can_cpu_hotplug())
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* No segment at default ATAGs address. try to locate
|
* No segment at default ATAGs address. try to locate
|
||||||
* a dtb using magic.
|
* a dtb using magic.
|
||||||
@@ -73,6 +82,7 @@ void machine_crash_nonpanic_core(void *unused)
|
|||||||
crash_save_cpu(®s, smp_processor_id());
|
crash_save_cpu(®s, smp_processor_id());
|
||||||
flush_cache_all();
|
flush_cache_all();
|
||||||
|
|
||||||
|
set_cpu_online(smp_processor_id(), false);
|
||||||
atomic_dec(&waiting_for_crash_ipi);
|
atomic_dec(&waiting_for_crash_ipi);
|
||||||
while (1)
|
while (1)
|
||||||
cpu_relax();
|
cpu_relax();
|
||||||
@@ -134,10 +144,13 @@ void machine_kexec(struct kimage *image)
|
|||||||
unsigned long reboot_code_buffer_phys;
|
unsigned long reboot_code_buffer_phys;
|
||||||
void *reboot_code_buffer;
|
void *reboot_code_buffer;
|
||||||
|
|
||||||
if (num_online_cpus() > 1) {
|
/*
|
||||||
pr_err("kexec: error: multiple CPUs still online\n");
|
* This can only happen if machine_shutdown() failed to disable some
|
||||||
return;
|
* CPU, and that can only happen if the checks in
|
||||||
}
|
* machine_kexec_prepare() were not correct. If this fails, we can't
|
||||||
|
* reliably kexec anyway, so BUG_ON is appropriate.
|
||||||
|
*/
|
||||||
|
BUG_ON(num_online_cpus() > 1);
|
||||||
|
|
||||||
page_list = image->head & PAGE_MASK;
|
page_list = image->head & PAGE_MASK;
|
||||||
|
|
||||||
|
@@ -56,7 +56,7 @@ armpmu_map_hw_event(const unsigned (*event_map)[PERF_COUNT_HW_MAX], u64 config)
|
|||||||
int mapping;
|
int mapping;
|
||||||
|
|
||||||
if (config >= PERF_COUNT_HW_MAX)
|
if (config >= PERF_COUNT_HW_MAX)
|
||||||
return -ENOENT;
|
return -EINVAL;
|
||||||
|
|
||||||
mapping = (*event_map)[config];
|
mapping = (*event_map)[config];
|
||||||
return mapping == HW_OP_UNSUPPORTED ? -ENOENT : mapping;
|
return mapping == HW_OP_UNSUPPORTED ? -ENOENT : mapping;
|
||||||
@@ -258,6 +258,9 @@ validate_event(struct pmu_hw_events *hw_events,
|
|||||||
struct arm_pmu *armpmu = to_arm_pmu(event->pmu);
|
struct arm_pmu *armpmu = to_arm_pmu(event->pmu);
|
||||||
struct pmu *leader_pmu = event->group_leader->pmu;
|
struct pmu *leader_pmu = event->group_leader->pmu;
|
||||||
|
|
||||||
|
if (is_software_event(event))
|
||||||
|
return 1;
|
||||||
|
|
||||||
if (event->pmu != leader_pmu || event->state < PERF_EVENT_STATE_OFF)
|
if (event->pmu != leader_pmu || event->state < PERF_EVENT_STATE_OFF)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
|
@@ -462,7 +462,7 @@ int in_gate_area_no_mm(unsigned long addr)
|
|||||||
{
|
{
|
||||||
return in_gate_area(NULL, addr);
|
return in_gate_area(NULL, addr);
|
||||||
}
|
}
|
||||||
#define is_gate_vma(vma) ((vma) = &gate_vma)
|
#define is_gate_vma(vma) ((vma) == &gate_vma)
|
||||||
#else
|
#else
|
||||||
#define is_gate_vma(vma) 0
|
#define is_gate_vma(vma) 0
|
||||||
#endif
|
#endif
|
||||||
|
@@ -145,6 +145,16 @@ int boot_secondary(unsigned int cpu, struct task_struct *idle)
|
|||||||
return -ENOSYS;
|
return -ENOSYS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int platform_can_cpu_hotplug(void)
|
||||||
|
{
|
||||||
|
#ifdef CONFIG_HOTPLUG_CPU
|
||||||
|
if (smp_ops.cpu_kill)
|
||||||
|
return 1;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_HOTPLUG_CPU
|
#ifdef CONFIG_HOTPLUG_CPU
|
||||||
static void percpu_timer_stop(void);
|
static void percpu_timer_stop(void);
|
||||||
|
|
||||||
|
@@ -146,7 +146,11 @@ static bool pm_fake(struct kvm_vcpu *vcpu,
|
|||||||
#define access_pmintenclr pm_fake
|
#define access_pmintenclr pm_fake
|
||||||
|
|
||||||
/* Architected CP15 registers.
|
/* Architected CP15 registers.
|
||||||
* Important: Must be sorted ascending by CRn, CRM, Op1, Op2
|
* CRn denotes the primary register number, but is copied to the CRm in the
|
||||||
|
* user space API for 64-bit register access in line with the terminology used
|
||||||
|
* in the ARM ARM.
|
||||||
|
* Important: Must be sorted ascending by CRn, CRM, Op1, Op2 and with 64-bit
|
||||||
|
* registers preceding 32-bit ones.
|
||||||
*/
|
*/
|
||||||
static const struct coproc_reg cp15_regs[] = {
|
static const struct coproc_reg cp15_regs[] = {
|
||||||
/* CSSELR: swapped by interrupt.S. */
|
/* CSSELR: swapped by interrupt.S. */
|
||||||
@@ -154,8 +158,8 @@ static const struct coproc_reg cp15_regs[] = {
|
|||||||
NULL, reset_unknown, c0_CSSELR },
|
NULL, reset_unknown, c0_CSSELR },
|
||||||
|
|
||||||
/* TTBR0/TTBR1: swapped by interrupt.S. */
|
/* TTBR0/TTBR1: swapped by interrupt.S. */
|
||||||
{ CRm( 2), Op1( 0), is64, NULL, reset_unknown64, c2_TTBR0 },
|
{ CRm64( 2), Op1( 0), is64, NULL, reset_unknown64, c2_TTBR0 },
|
||||||
{ CRm( 2), Op1( 1), is64, NULL, reset_unknown64, c2_TTBR1 },
|
{ CRm64( 2), Op1( 1), is64, NULL, reset_unknown64, c2_TTBR1 },
|
||||||
|
|
||||||
/* TTBCR: swapped by interrupt.S. */
|
/* TTBCR: swapped by interrupt.S. */
|
||||||
{ CRn( 2), CRm( 0), Op1( 0), Op2( 2), is32,
|
{ CRn( 2), CRm( 0), Op1( 0), Op2( 2), is32,
|
||||||
@@ -182,7 +186,7 @@ static const struct coproc_reg cp15_regs[] = {
|
|||||||
NULL, reset_unknown, c6_IFAR },
|
NULL, reset_unknown, c6_IFAR },
|
||||||
|
|
||||||
/* PAR swapped by interrupt.S */
|
/* PAR swapped by interrupt.S */
|
||||||
{ CRn( 7), Op1( 0), is64, NULL, reset_unknown64, c7_PAR },
|
{ CRm64( 7), Op1( 0), is64, NULL, reset_unknown64, c7_PAR },
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* DC{C,I,CI}SW operations:
|
* DC{C,I,CI}SW operations:
|
||||||
@@ -399,12 +403,13 @@ static bool index_to_params(u64 id, struct coproc_params *params)
|
|||||||
| KVM_REG_ARM_OPC1_MASK))
|
| KVM_REG_ARM_OPC1_MASK))
|
||||||
return false;
|
return false;
|
||||||
params->is_64bit = true;
|
params->is_64bit = true;
|
||||||
params->CRm = ((id & KVM_REG_ARM_CRM_MASK)
|
/* CRm to CRn: see cp15_to_index for details */
|
||||||
|
params->CRn = ((id & KVM_REG_ARM_CRM_MASK)
|
||||||
>> KVM_REG_ARM_CRM_SHIFT);
|
>> KVM_REG_ARM_CRM_SHIFT);
|
||||||
params->Op1 = ((id & KVM_REG_ARM_OPC1_MASK)
|
params->Op1 = ((id & KVM_REG_ARM_OPC1_MASK)
|
||||||
>> KVM_REG_ARM_OPC1_SHIFT);
|
>> KVM_REG_ARM_OPC1_SHIFT);
|
||||||
params->Op2 = 0;
|
params->Op2 = 0;
|
||||||
params->CRn = 0;
|
params->CRm = 0;
|
||||||
return true;
|
return true;
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
@@ -898,7 +903,14 @@ static u64 cp15_to_index(const struct coproc_reg *reg)
|
|||||||
if (reg->is_64) {
|
if (reg->is_64) {
|
||||||
val |= KVM_REG_SIZE_U64;
|
val |= KVM_REG_SIZE_U64;
|
||||||
val |= (reg->Op1 << KVM_REG_ARM_OPC1_SHIFT);
|
val |= (reg->Op1 << KVM_REG_ARM_OPC1_SHIFT);
|
||||||
val |= (reg->CRm << KVM_REG_ARM_CRM_SHIFT);
|
/*
|
||||||
|
* CRn always denotes the primary coproc. reg. nr. for the
|
||||||
|
* in-kernel representation, but the user space API uses the
|
||||||
|
* CRm for the encoding, because it is modelled after the
|
||||||
|
* MRRC/MCRR instructions: see the ARM ARM rev. c page
|
||||||
|
* B3-1445
|
||||||
|
*/
|
||||||
|
val |= (reg->CRn << KVM_REG_ARM_CRM_SHIFT);
|
||||||
} else {
|
} else {
|
||||||
val |= KVM_REG_SIZE_U32;
|
val |= KVM_REG_SIZE_U32;
|
||||||
val |= (reg->Op1 << KVM_REG_ARM_OPC1_SHIFT);
|
val |= (reg->Op1 << KVM_REG_ARM_OPC1_SHIFT);
|
||||||
|
@@ -135,6 +135,8 @@ static inline int cmp_reg(const struct coproc_reg *i1,
|
|||||||
return -1;
|
return -1;
|
||||||
if (i1->CRn != i2->CRn)
|
if (i1->CRn != i2->CRn)
|
||||||
return i1->CRn - i2->CRn;
|
return i1->CRn - i2->CRn;
|
||||||
|
if (i1->is_64 != i2->is_64)
|
||||||
|
return i2->is_64 - i1->is_64;
|
||||||
if (i1->CRm != i2->CRm)
|
if (i1->CRm != i2->CRm)
|
||||||
return i1->CRm - i2->CRm;
|
return i1->CRm - i2->CRm;
|
||||||
if (i1->Op1 != i2->Op1)
|
if (i1->Op1 != i2->Op1)
|
||||||
@@ -145,6 +147,7 @@ static inline int cmp_reg(const struct coproc_reg *i1,
|
|||||||
|
|
||||||
#define CRn(_x) .CRn = _x
|
#define CRn(_x) .CRn = _x
|
||||||
#define CRm(_x) .CRm = _x
|
#define CRm(_x) .CRm = _x
|
||||||
|
#define CRm64(_x) .CRn = _x, .CRm = 0
|
||||||
#define Op1(_x) .Op1 = _x
|
#define Op1(_x) .Op1 = _x
|
||||||
#define Op2(_x) .Op2 = _x
|
#define Op2(_x) .Op2 = _x
|
||||||
#define is64 .is_64 = true
|
#define is64 .is_64 = true
|
||||||
|
@@ -114,7 +114,11 @@ static bool access_l2ectlr(struct kvm_vcpu *vcpu,
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* A15-specific CP15 registers.
|
* A15-specific CP15 registers.
|
||||||
* Important: Must be sorted ascending by CRn, CRM, Op1, Op2
|
* CRn denotes the primary register number, but is copied to the CRm in the
|
||||||
|
* user space API for 64-bit register access in line with the terminology used
|
||||||
|
* in the ARM ARM.
|
||||||
|
* Important: Must be sorted ascending by CRn, CRM, Op1, Op2 and with 64-bit
|
||||||
|
* registers preceding 32-bit ones.
|
||||||
*/
|
*/
|
||||||
static const struct coproc_reg a15_regs[] = {
|
static const struct coproc_reg a15_regs[] = {
|
||||||
/* MPIDR: we use VMPIDR for guest access. */
|
/* MPIDR: we use VMPIDR for guest access. */
|
||||||
|
@@ -63,7 +63,8 @@ int kvm_handle_mmio_return(struct kvm_vcpu *vcpu, struct kvm_run *run)
|
|||||||
static int decode_hsr(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa,
|
static int decode_hsr(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa,
|
||||||
struct kvm_exit_mmio *mmio)
|
struct kvm_exit_mmio *mmio)
|
||||||
{
|
{
|
||||||
unsigned long rt, len;
|
unsigned long rt;
|
||||||
|
int len;
|
||||||
bool is_write, sign_extend;
|
bool is_write, sign_extend;
|
||||||
|
|
||||||
if (kvm_vcpu_dabt_isextabt(vcpu)) {
|
if (kvm_vcpu_dabt_isextabt(vcpu)) {
|
||||||
|
@@ -85,6 +85,12 @@ static void *mmu_memory_cache_alloc(struct kvm_mmu_memory_cache *mc)
|
|||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool page_empty(void *ptr)
|
||||||
|
{
|
||||||
|
struct page *ptr_page = virt_to_page(ptr);
|
||||||
|
return page_count(ptr_page) == 1;
|
||||||
|
}
|
||||||
|
|
||||||
static void clear_pud_entry(struct kvm *kvm, pud_t *pud, phys_addr_t addr)
|
static void clear_pud_entry(struct kvm *kvm, pud_t *pud, phys_addr_t addr)
|
||||||
{
|
{
|
||||||
pmd_t *pmd_table = pmd_offset(pud, 0);
|
pmd_t *pmd_table = pmd_offset(pud, 0);
|
||||||
@@ -103,12 +109,6 @@ static void clear_pmd_entry(struct kvm *kvm, pmd_t *pmd, phys_addr_t addr)
|
|||||||
put_page(virt_to_page(pmd));
|
put_page(virt_to_page(pmd));
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool pmd_empty(pmd_t *pmd)
|
|
||||||
{
|
|
||||||
struct page *pmd_page = virt_to_page(pmd);
|
|
||||||
return page_count(pmd_page) == 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void clear_pte_entry(struct kvm *kvm, pte_t *pte, phys_addr_t addr)
|
static void clear_pte_entry(struct kvm *kvm, pte_t *pte, phys_addr_t addr)
|
||||||
{
|
{
|
||||||
if (pte_present(*pte)) {
|
if (pte_present(*pte)) {
|
||||||
@@ -118,12 +118,6 @@ static void clear_pte_entry(struct kvm *kvm, pte_t *pte, phys_addr_t addr)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool pte_empty(pte_t *pte)
|
|
||||||
{
|
|
||||||
struct page *pte_page = virt_to_page(pte);
|
|
||||||
return page_count(pte_page) == 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void unmap_range(struct kvm *kvm, pgd_t *pgdp,
|
static void unmap_range(struct kvm *kvm, pgd_t *pgdp,
|
||||||
unsigned long long start, u64 size)
|
unsigned long long start, u64 size)
|
||||||
{
|
{
|
||||||
@@ -132,37 +126,37 @@ static void unmap_range(struct kvm *kvm, pgd_t *pgdp,
|
|||||||
pmd_t *pmd;
|
pmd_t *pmd;
|
||||||
pte_t *pte;
|
pte_t *pte;
|
||||||
unsigned long long addr = start, end = start + size;
|
unsigned long long addr = start, end = start + size;
|
||||||
u64 range;
|
u64 next;
|
||||||
|
|
||||||
while (addr < end) {
|
while (addr < end) {
|
||||||
pgd = pgdp + pgd_index(addr);
|
pgd = pgdp + pgd_index(addr);
|
||||||
pud = pud_offset(pgd, addr);
|
pud = pud_offset(pgd, addr);
|
||||||
if (pud_none(*pud)) {
|
if (pud_none(*pud)) {
|
||||||
addr += PUD_SIZE;
|
addr = pud_addr_end(addr, end);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
pmd = pmd_offset(pud, addr);
|
pmd = pmd_offset(pud, addr);
|
||||||
if (pmd_none(*pmd)) {
|
if (pmd_none(*pmd)) {
|
||||||
addr += PMD_SIZE;
|
addr = pmd_addr_end(addr, end);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
pte = pte_offset_kernel(pmd, addr);
|
pte = pte_offset_kernel(pmd, addr);
|
||||||
clear_pte_entry(kvm, pte, addr);
|
clear_pte_entry(kvm, pte, addr);
|
||||||
range = PAGE_SIZE;
|
next = addr + PAGE_SIZE;
|
||||||
|
|
||||||
/* If we emptied the pte, walk back up the ladder */
|
/* If we emptied the pte, walk back up the ladder */
|
||||||
if (pte_empty(pte)) {
|
if (page_empty(pte)) {
|
||||||
clear_pmd_entry(kvm, pmd, addr);
|
clear_pmd_entry(kvm, pmd, addr);
|
||||||
range = PMD_SIZE;
|
next = pmd_addr_end(addr, end);
|
||||||
if (pmd_empty(pmd)) {
|
if (page_empty(pmd) && !page_empty(pud)) {
|
||||||
clear_pud_entry(kvm, pud, addr);
|
clear_pud_entry(kvm, pud, addr);
|
||||||
range = PUD_SIZE;
|
next = pud_addr_end(addr, end);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
addr += range;
|
addr = next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -227,6 +227,8 @@ static struct clk_lookup periph_clocks_lookups[] = {
|
|||||||
CLKDEV_CON_DEV_ID("usart", "f8020000.serial", &usart1_clk),
|
CLKDEV_CON_DEV_ID("usart", "f8020000.serial", &usart1_clk),
|
||||||
CLKDEV_CON_DEV_ID("usart", "f8024000.serial", &usart2_clk),
|
CLKDEV_CON_DEV_ID("usart", "f8024000.serial", &usart2_clk),
|
||||||
CLKDEV_CON_DEV_ID("usart", "f8028000.serial", &usart3_clk),
|
CLKDEV_CON_DEV_ID("usart", "f8028000.serial", &usart3_clk),
|
||||||
|
CLKDEV_CON_DEV_ID("usart", "f8040000.serial", &uart0_clk),
|
||||||
|
CLKDEV_CON_DEV_ID("usart", "f8044000.serial", &uart1_clk),
|
||||||
CLKDEV_CON_DEV_ID("t0_clk", "f8008000.timer", &tcb0_clk),
|
CLKDEV_CON_DEV_ID("t0_clk", "f8008000.timer", &tcb0_clk),
|
||||||
CLKDEV_CON_DEV_ID("t0_clk", "f800c000.timer", &tcb0_clk),
|
CLKDEV_CON_DEV_ID("t0_clk", "f800c000.timer", &tcb0_clk),
|
||||||
CLKDEV_CON_DEV_ID("mci_clk", "f0008000.mmc", &mmc0_clk),
|
CLKDEV_CON_DEV_ID("mci_clk", "f0008000.mmc", &mmc0_clk),
|
||||||
|
@@ -75,6 +75,7 @@ static struct davinci_nand_pdata davinci_nand_data = {
|
|||||||
.parts = davinci_nand_partitions,
|
.parts = davinci_nand_partitions,
|
||||||
.nr_parts = ARRAY_SIZE(davinci_nand_partitions),
|
.nr_parts = ARRAY_SIZE(davinci_nand_partitions),
|
||||||
.ecc_mode = NAND_ECC_HW_SYNDROME,
|
.ecc_mode = NAND_ECC_HW_SYNDROME,
|
||||||
|
.ecc_bits = 4,
|
||||||
.bbt_options = NAND_BBT_USE_FLASH,
|
.bbt_options = NAND_BBT_USE_FLASH,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -153,6 +153,7 @@ static struct davinci_nand_pdata davinci_evm_nandflash_data = {
|
|||||||
.parts = davinci_evm_nandflash_partition,
|
.parts = davinci_evm_nandflash_partition,
|
||||||
.nr_parts = ARRAY_SIZE(davinci_evm_nandflash_partition),
|
.nr_parts = ARRAY_SIZE(davinci_evm_nandflash_partition),
|
||||||
.ecc_mode = NAND_ECC_HW,
|
.ecc_mode = NAND_ECC_HW,
|
||||||
|
.ecc_bits = 1,
|
||||||
.bbt_options = NAND_BBT_USE_FLASH,
|
.bbt_options = NAND_BBT_USE_FLASH,
|
||||||
.timing = &davinci_evm_nandflash_timing,
|
.timing = &davinci_evm_nandflash_timing,
|
||||||
};
|
};
|
||||||
|
@@ -90,6 +90,7 @@ static struct davinci_nand_pdata davinci_nand_data = {
|
|||||||
.parts = davinci_nand_partitions,
|
.parts = davinci_nand_partitions,
|
||||||
.nr_parts = ARRAY_SIZE(davinci_nand_partitions),
|
.nr_parts = ARRAY_SIZE(davinci_nand_partitions),
|
||||||
.ecc_mode = NAND_ECC_HW,
|
.ecc_mode = NAND_ECC_HW,
|
||||||
|
.ecc_bits = 1,
|
||||||
.options = 0,
|
.options = 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -88,6 +88,7 @@ static struct davinci_nand_pdata davinci_ntosd2_nandflash_data = {
|
|||||||
.parts = davinci_ntosd2_nandflash_partition,
|
.parts = davinci_ntosd2_nandflash_partition,
|
||||||
.nr_parts = ARRAY_SIZE(davinci_ntosd2_nandflash_partition),
|
.nr_parts = ARRAY_SIZE(davinci_ntosd2_nandflash_partition),
|
||||||
.ecc_mode = NAND_ECC_HW,
|
.ecc_mode = NAND_ECC_HW,
|
||||||
|
.ecc_bits = 1,
|
||||||
.bbt_options = NAND_BBT_USE_FLASH,
|
.bbt_options = NAND_BBT_USE_FLASH,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -122,11 +122,7 @@ static struct musb_hdrc_config musb_config = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static struct musb_hdrc_platform_data tusb_data = {
|
static struct musb_hdrc_platform_data tusb_data = {
|
||||||
#ifdef CONFIG_USB_GADGET_MUSB_HDRC
|
|
||||||
.mode = MUSB_OTG,
|
.mode = MUSB_OTG,
|
||||||
#else
|
|
||||||
.mode = MUSB_HOST,
|
|
||||||
#endif
|
|
||||||
.set_power = tusb_set_power,
|
.set_power = tusb_set_power,
|
||||||
.min_power = 25, /* x2 = 50 mA drawn from VBUS as peripheral */
|
.min_power = 25, /* x2 = 50 mA drawn from VBUS as peripheral */
|
||||||
.power = 100, /* Max 100 mA VBUS for host mode */
|
.power = 100, /* Max 100 mA VBUS for host mode */
|
||||||
|
@@ -85,7 +85,7 @@ static struct omap_board_mux board_mux[] __initdata = {
|
|||||||
|
|
||||||
static struct omap_musb_board_data musb_board_data = {
|
static struct omap_musb_board_data musb_board_data = {
|
||||||
.interface_type = MUSB_INTERFACE_ULPI,
|
.interface_type = MUSB_INTERFACE_ULPI,
|
||||||
.mode = MUSB_PERIPHERAL,
|
.mode = MUSB_OTG,
|
||||||
.power = 0,
|
.power = 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -38,11 +38,8 @@ static struct musb_hdrc_config musb_config = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static struct musb_hdrc_platform_data musb_plat = {
|
static struct musb_hdrc_platform_data musb_plat = {
|
||||||
#ifdef CONFIG_USB_GADGET_MUSB_HDRC
|
|
||||||
.mode = MUSB_OTG,
|
.mode = MUSB_OTG,
|
||||||
#else
|
|
||||||
.mode = MUSB_HOST,
|
|
||||||
#endif
|
|
||||||
/* .clock is set dynamically */
|
/* .clock is set dynamically */
|
||||||
.config = &musb_config,
|
.config = &musb_config,
|
||||||
|
|
||||||
|
@@ -42,7 +42,6 @@ static const char *atlas6_dt_match[] __initdata = {
|
|||||||
|
|
||||||
DT_MACHINE_START(ATLAS6_DT, "Generic ATLAS6 (Flattened Device Tree)")
|
DT_MACHINE_START(ATLAS6_DT, "Generic ATLAS6 (Flattened Device Tree)")
|
||||||
/* Maintainer: Barry Song <baohua.song@csr.com> */
|
/* Maintainer: Barry Song <baohua.song@csr.com> */
|
||||||
.nr_irqs = 128,
|
|
||||||
.map_io = sirfsoc_map_io,
|
.map_io = sirfsoc_map_io,
|
||||||
.init_time = sirfsoc_init_time,
|
.init_time = sirfsoc_init_time,
|
||||||
.init_late = sirfsoc_init_late,
|
.init_late = sirfsoc_init_late,
|
||||||
@@ -59,7 +58,6 @@ static const char *prima2_dt_match[] __initdata = {
|
|||||||
|
|
||||||
DT_MACHINE_START(PRIMA2_DT, "Generic PRIMA2 (Flattened Device Tree)")
|
DT_MACHINE_START(PRIMA2_DT, "Generic PRIMA2 (Flattened Device Tree)")
|
||||||
/* Maintainer: Barry Song <baohua.song@csr.com> */
|
/* Maintainer: Barry Song <baohua.song@csr.com> */
|
||||||
.nr_irqs = 128,
|
|
||||||
.map_io = sirfsoc_map_io,
|
.map_io = sirfsoc_map_io,
|
||||||
.init_time = sirfsoc_init_time,
|
.init_time = sirfsoc_init_time,
|
||||||
.dma_zone_size = SZ_256M,
|
.dma_zone_size = SZ_256M,
|
||||||
|
@@ -809,15 +809,18 @@ config KUSER_HELPERS
|
|||||||
the CPU type fitted to the system. This permits binaries to be
|
the CPU type fitted to the system. This permits binaries to be
|
||||||
run on ARMv4 through to ARMv7 without modification.
|
run on ARMv4 through to ARMv7 without modification.
|
||||||
|
|
||||||
|
See Documentation/arm/kernel_user_helpers.txt for details.
|
||||||
|
|
||||||
However, the fixed address nature of these helpers can be used
|
However, the fixed address nature of these helpers can be used
|
||||||
by ROP (return orientated programming) authors when creating
|
by ROP (return orientated programming) authors when creating
|
||||||
exploits.
|
exploits.
|
||||||
|
|
||||||
If all of the binaries and libraries which run on your platform
|
If all of the binaries and libraries which run on your platform
|
||||||
are built specifically for your platform, and make no use of
|
are built specifically for your platform, and make no use of
|
||||||
these helpers, then you can turn this option off. However,
|
these helpers, then you can turn this option off to hinder
|
||||||
when such an binary or library is run, it will receive a SIGILL
|
such exploits. However, in that case, if a binary or library
|
||||||
signal, which will terminate the program.
|
relying on those helpers is run, it will receive a SIGILL signal,
|
||||||
|
which will terminate the program.
|
||||||
|
|
||||||
Say N here only if you are absolutely certain that you do not
|
Say N here only if you are absolutely certain that you do not
|
||||||
need these helpers; otherwise, the safe option is to say Y.
|
need these helpers; otherwise, the safe option is to say Y.
|
||||||
|
@@ -55,12 +55,13 @@ void __init s3c_init_cpu(unsigned long idcode,
|
|||||||
|
|
||||||
printk("CPU %s (id 0x%08lx)\n", cpu->name, idcode);
|
printk("CPU %s (id 0x%08lx)\n", cpu->name, idcode);
|
||||||
|
|
||||||
if (cpu->map_io == NULL || cpu->init == NULL) {
|
if (cpu->init == NULL) {
|
||||||
printk(KERN_ERR "CPU %s support not enabled\n", cpu->name);
|
printk(KERN_ERR "CPU %s support not enabled\n", cpu->name);
|
||||||
panic("Unsupported Samsung CPU");
|
panic("Unsupported Samsung CPU");
|
||||||
}
|
}
|
||||||
|
|
||||||
cpu->map_io();
|
if (cpu->map_io)
|
||||||
|
cpu->map_io();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* s3c24xx_init_clocks
|
/* s3c24xx_init_clocks
|
||||||
|
@@ -170,6 +170,7 @@ static void __init xen_percpu_init(void *unused)
|
|||||||
per_cpu(xen_vcpu, cpu) = vcpup;
|
per_cpu(xen_vcpu, cpu) = vcpup;
|
||||||
|
|
||||||
enable_percpu_irq(xen_events_irq, 0);
|
enable_percpu_irq(xen_events_irq, 0);
|
||||||
|
put_cpu();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void xen_restart(enum reboot_mode reboot_mode, const char *cmd)
|
static void xen_restart(enum reboot_mode reboot_mode, const char *cmd)
|
||||||
|
@@ -42,14 +42,15 @@
|
|||||||
#define TPIDR_EL1 18 /* Thread ID, Privileged */
|
#define TPIDR_EL1 18 /* Thread ID, Privileged */
|
||||||
#define AMAIR_EL1 19 /* Aux Memory Attribute Indirection Register */
|
#define AMAIR_EL1 19 /* Aux Memory Attribute Indirection Register */
|
||||||
#define CNTKCTL_EL1 20 /* Timer Control Register (EL1) */
|
#define CNTKCTL_EL1 20 /* Timer Control Register (EL1) */
|
||||||
|
#define PAR_EL1 21 /* Physical Address Register */
|
||||||
/* 32bit specific registers. Keep them at the end of the range */
|
/* 32bit specific registers. Keep them at the end of the range */
|
||||||
#define DACR32_EL2 21 /* Domain Access Control Register */
|
#define DACR32_EL2 22 /* Domain Access Control Register */
|
||||||
#define IFSR32_EL2 22 /* Instruction Fault Status Register */
|
#define IFSR32_EL2 23 /* Instruction Fault Status Register */
|
||||||
#define FPEXC32_EL2 23 /* Floating-Point Exception Control Register */
|
#define FPEXC32_EL2 24 /* Floating-Point Exception Control Register */
|
||||||
#define DBGVCR32_EL2 24 /* Debug Vector Catch Register */
|
#define DBGVCR32_EL2 25 /* Debug Vector Catch Register */
|
||||||
#define TEECR32_EL1 25 /* ThumbEE Configuration Register */
|
#define TEECR32_EL1 26 /* ThumbEE Configuration Register */
|
||||||
#define TEEHBR32_EL1 26 /* ThumbEE Handler Base Register */
|
#define TEEHBR32_EL1 27 /* ThumbEE Handler Base Register */
|
||||||
#define NR_SYS_REGS 27
|
#define NR_SYS_REGS 28
|
||||||
|
|
||||||
/* 32bit mapping */
|
/* 32bit mapping */
|
||||||
#define c0_MPIDR (MPIDR_EL1 * 2) /* MultiProcessor ID Register */
|
#define c0_MPIDR (MPIDR_EL1 * 2) /* MultiProcessor ID Register */
|
||||||
@@ -69,6 +70,8 @@
|
|||||||
#define c5_AIFSR (AFSR1_EL1 * 2) /* Auxiliary Instr Fault Status R */
|
#define c5_AIFSR (AFSR1_EL1 * 2) /* Auxiliary Instr Fault Status R */
|
||||||
#define c6_DFAR (FAR_EL1 * 2) /* Data Fault Address Register */
|
#define c6_DFAR (FAR_EL1 * 2) /* Data Fault Address Register */
|
||||||
#define c6_IFAR (c6_DFAR + 1) /* Instruction Fault Address Register */
|
#define c6_IFAR (c6_DFAR + 1) /* Instruction Fault Address Register */
|
||||||
|
#define c7_PAR (PAR_EL1 * 2) /* Physical Address Register */
|
||||||
|
#define c7_PAR_high (c7_PAR + 1) /* PAR top 32 bits */
|
||||||
#define c10_PRRR (MAIR_EL1 * 2) /* Primary Region Remap Register */
|
#define c10_PRRR (MAIR_EL1 * 2) /* Primary Region Remap Register */
|
||||||
#define c10_NMRR (c10_PRRR + 1) /* Normal Memory Remap Register */
|
#define c10_NMRR (c10_PRRR + 1) /* Normal Memory Remap Register */
|
||||||
#define c12_VBAR (VBAR_EL1 * 2) /* Vector Base Address Register */
|
#define c12_VBAR (VBAR_EL1 * 2) /* Vector Base Address Register */
|
||||||
|
@@ -129,7 +129,7 @@ struct kvm_vcpu_arch {
|
|||||||
struct kvm_mmu_memory_cache mmu_page_cache;
|
struct kvm_mmu_memory_cache mmu_page_cache;
|
||||||
|
|
||||||
/* Target CPU and feature flags */
|
/* Target CPU and feature flags */
|
||||||
u32 target;
|
int target;
|
||||||
DECLARE_BITMAP(features, KVM_VCPU_MAX_FEATURES);
|
DECLARE_BITMAP(features, KVM_VCPU_MAX_FEATURES);
|
||||||
|
|
||||||
/* Detect first run of a vcpu */
|
/* Detect first run of a vcpu */
|
||||||
|
@@ -35,6 +35,7 @@ struct mmu_gather {
|
|||||||
struct mm_struct *mm;
|
struct mm_struct *mm;
|
||||||
unsigned int fullmm;
|
unsigned int fullmm;
|
||||||
struct vm_area_struct *vma;
|
struct vm_area_struct *vma;
|
||||||
|
unsigned long start, end;
|
||||||
unsigned long range_start;
|
unsigned long range_start;
|
||||||
unsigned long range_end;
|
unsigned long range_end;
|
||||||
unsigned int nr;
|
unsigned int nr;
|
||||||
@@ -97,10 +98,12 @@ static inline void tlb_flush_mmu(struct mmu_gather *tlb)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
tlb_gather_mmu(struct mmu_gather *tlb, struct mm_struct *mm, unsigned int fullmm)
|
tlb_gather_mmu(struct mmu_gather *tlb, struct mm_struct *mm, unsigned long start, unsigned long end)
|
||||||
{
|
{
|
||||||
tlb->mm = mm;
|
tlb->mm = mm;
|
||||||
tlb->fullmm = fullmm;
|
tlb->fullmm = !(start | (end+1));
|
||||||
|
tlb->start = start;
|
||||||
|
tlb->end = end;
|
||||||
tlb->vma = NULL;
|
tlb->vma = NULL;
|
||||||
tlb->max = ARRAY_SIZE(tlb->local);
|
tlb->max = ARRAY_SIZE(tlb->local);
|
||||||
tlb->pages = tlb->local;
|
tlb->pages = tlb->local;
|
||||||
|
@@ -107,7 +107,12 @@ armpmu_map_cache_event(const unsigned (*cache_map)
|
|||||||
static int
|
static int
|
||||||
armpmu_map_event(const unsigned (*event_map)[PERF_COUNT_HW_MAX], u64 config)
|
armpmu_map_event(const unsigned (*event_map)[PERF_COUNT_HW_MAX], u64 config)
|
||||||
{
|
{
|
||||||
int mapping = (*event_map)[config];
|
int mapping;
|
||||||
|
|
||||||
|
if (config >= PERF_COUNT_HW_MAX)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
mapping = (*event_map)[config];
|
||||||
return mapping == HW_OP_UNSUPPORTED ? -ENOENT : mapping;
|
return mapping == HW_OP_UNSUPPORTED ? -ENOENT : mapping;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -317,6 +322,9 @@ validate_event(struct pmu_hw_events *hw_events,
|
|||||||
struct hw_perf_event fake_event = event->hw;
|
struct hw_perf_event fake_event = event->hw;
|
||||||
struct pmu *leader_pmu = event->group_leader->pmu;
|
struct pmu *leader_pmu = event->group_leader->pmu;
|
||||||
|
|
||||||
|
if (is_software_event(event))
|
||||||
|
return 1;
|
||||||
|
|
||||||
if (event->pmu != leader_pmu || event->state <= PERF_EVENT_STATE_OFF)
|
if (event->pmu != leader_pmu || event->state <= PERF_EVENT_STATE_OFF)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
|
@@ -214,6 +214,7 @@ __kvm_hyp_code_start:
|
|||||||
mrs x21, tpidr_el1
|
mrs x21, tpidr_el1
|
||||||
mrs x22, amair_el1
|
mrs x22, amair_el1
|
||||||
mrs x23, cntkctl_el1
|
mrs x23, cntkctl_el1
|
||||||
|
mrs x24, par_el1
|
||||||
|
|
||||||
stp x4, x5, [x3]
|
stp x4, x5, [x3]
|
||||||
stp x6, x7, [x3, #16]
|
stp x6, x7, [x3, #16]
|
||||||
@@ -225,6 +226,7 @@ __kvm_hyp_code_start:
|
|||||||
stp x18, x19, [x3, #112]
|
stp x18, x19, [x3, #112]
|
||||||
stp x20, x21, [x3, #128]
|
stp x20, x21, [x3, #128]
|
||||||
stp x22, x23, [x3, #144]
|
stp x22, x23, [x3, #144]
|
||||||
|
str x24, [x3, #160]
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
.macro restore_sysregs
|
.macro restore_sysregs
|
||||||
@@ -243,6 +245,7 @@ __kvm_hyp_code_start:
|
|||||||
ldp x18, x19, [x3, #112]
|
ldp x18, x19, [x3, #112]
|
||||||
ldp x20, x21, [x3, #128]
|
ldp x20, x21, [x3, #128]
|
||||||
ldp x22, x23, [x3, #144]
|
ldp x22, x23, [x3, #144]
|
||||||
|
ldr x24, [x3, #160]
|
||||||
|
|
||||||
msr vmpidr_el2, x4
|
msr vmpidr_el2, x4
|
||||||
msr csselr_el1, x5
|
msr csselr_el1, x5
|
||||||
@@ -264,6 +267,7 @@ __kvm_hyp_code_start:
|
|||||||
msr tpidr_el1, x21
|
msr tpidr_el1, x21
|
||||||
msr amair_el1, x22
|
msr amair_el1, x22
|
||||||
msr cntkctl_el1, x23
|
msr cntkctl_el1, x23
|
||||||
|
msr par_el1, x24
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
.macro skip_32bit_state tmp, target
|
.macro skip_32bit_state tmp, target
|
||||||
@@ -600,6 +604,8 @@ END(__kvm_vcpu_run)
|
|||||||
|
|
||||||
// void __kvm_tlb_flush_vmid_ipa(struct kvm *kvm, phys_addr_t ipa);
|
// void __kvm_tlb_flush_vmid_ipa(struct kvm *kvm, phys_addr_t ipa);
|
||||||
ENTRY(__kvm_tlb_flush_vmid_ipa)
|
ENTRY(__kvm_tlb_flush_vmid_ipa)
|
||||||
|
dsb ishst
|
||||||
|
|
||||||
kern_hyp_va x0
|
kern_hyp_va x0
|
||||||
ldr x2, [x0, #KVM_VTTBR]
|
ldr x2, [x0, #KVM_VTTBR]
|
||||||
msr vttbr_el2, x2
|
msr vttbr_el2, x2
|
||||||
@@ -621,6 +627,7 @@ ENTRY(__kvm_tlb_flush_vmid_ipa)
|
|||||||
ENDPROC(__kvm_tlb_flush_vmid_ipa)
|
ENDPROC(__kvm_tlb_flush_vmid_ipa)
|
||||||
|
|
||||||
ENTRY(__kvm_flush_vm_context)
|
ENTRY(__kvm_flush_vm_context)
|
||||||
|
dsb ishst
|
||||||
tlbi alle1is
|
tlbi alle1is
|
||||||
ic ialluis
|
ic ialluis
|
||||||
dsb sy
|
dsb sy
|
||||||
@@ -753,6 +760,10 @@ el1_trap:
|
|||||||
*/
|
*/
|
||||||
tbnz x1, #7, 1f // S1PTW is set
|
tbnz x1, #7, 1f // S1PTW is set
|
||||||
|
|
||||||
|
/* Preserve PAR_EL1 */
|
||||||
|
mrs x3, par_el1
|
||||||
|
push x3, xzr
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Permission fault, HPFAR_EL2 is invalid.
|
* Permission fault, HPFAR_EL2 is invalid.
|
||||||
* Resolve the IPA the hard way using the guest VA.
|
* Resolve the IPA the hard way using the guest VA.
|
||||||
@@ -766,6 +777,8 @@ el1_trap:
|
|||||||
|
|
||||||
/* Read result */
|
/* Read result */
|
||||||
mrs x3, par_el1
|
mrs x3, par_el1
|
||||||
|
pop x0, xzr // Restore PAR_EL1 from the stack
|
||||||
|
msr par_el1, x0
|
||||||
tbnz x3, #0, 3f // Bail out if we failed the translation
|
tbnz x3, #0, 3f // Bail out if we failed the translation
|
||||||
ubfx x3, x3, #12, #36 // Extract IPA
|
ubfx x3, x3, #12, #36 // Extract IPA
|
||||||
lsl x3, x3, #4 // and present it like HPFAR
|
lsl x3, x3, #4 // and present it like HPFAR
|
||||||
|
@@ -211,6 +211,9 @@ static const struct sys_reg_desc sys_reg_descs[] = {
|
|||||||
/* FAR_EL1 */
|
/* FAR_EL1 */
|
||||||
{ Op0(0b11), Op1(0b000), CRn(0b0110), CRm(0b0000), Op2(0b000),
|
{ Op0(0b11), Op1(0b000), CRn(0b0110), CRm(0b0000), Op2(0b000),
|
||||||
NULL, reset_unknown, FAR_EL1 },
|
NULL, reset_unknown, FAR_EL1 },
|
||||||
|
/* PAR_EL1 */
|
||||||
|
{ Op0(0b11), Op1(0b000), CRn(0b0111), CRm(0b0100), Op2(0b000),
|
||||||
|
NULL, reset_unknown, PAR_EL1 },
|
||||||
|
|
||||||
/* PMINTENSET_EL1 */
|
/* PMINTENSET_EL1 */
|
||||||
{ Op0(0b11), Op1(0b000), CRn(0b1001), CRm(0b1110), Op2(0b001),
|
{ Op0(0b11), Op1(0b000), CRn(0b1001), CRm(0b1110), Op2(0b001),
|
||||||
|
@@ -22,7 +22,7 @@
|
|||||||
* unmapping a portion of the virtual address space, these hooks are called according to
|
* unmapping a portion of the virtual address space, these hooks are called according to
|
||||||
* the following template:
|
* the following template:
|
||||||
*
|
*
|
||||||
* tlb <- tlb_gather_mmu(mm, full_mm_flush); // start unmap for address space MM
|
* tlb <- tlb_gather_mmu(mm, start, end); // start unmap for address space MM
|
||||||
* {
|
* {
|
||||||
* for each vma that needs a shootdown do {
|
* for each vma that needs a shootdown do {
|
||||||
* tlb_start_vma(tlb, vma);
|
* tlb_start_vma(tlb, vma);
|
||||||
@@ -58,6 +58,7 @@ struct mmu_gather {
|
|||||||
unsigned int max;
|
unsigned int max;
|
||||||
unsigned char fullmm; /* non-zero means full mm flush */
|
unsigned char fullmm; /* non-zero means full mm flush */
|
||||||
unsigned char need_flush; /* really unmapped some PTEs? */
|
unsigned char need_flush; /* really unmapped some PTEs? */
|
||||||
|
unsigned long start, end;
|
||||||
unsigned long start_addr;
|
unsigned long start_addr;
|
||||||
unsigned long end_addr;
|
unsigned long end_addr;
|
||||||
struct page **pages;
|
struct page **pages;
|
||||||
@@ -155,13 +156,15 @@ static inline void __tlb_alloc_page(struct mmu_gather *tlb)
|
|||||||
|
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
tlb_gather_mmu(struct mmu_gather *tlb, struct mm_struct *mm, unsigned int full_mm_flush)
|
tlb_gather_mmu(struct mmu_gather *tlb, struct mm_struct *mm, unsigned long start, unsigned long end)
|
||||||
{
|
{
|
||||||
tlb->mm = mm;
|
tlb->mm = mm;
|
||||||
tlb->max = ARRAY_SIZE(tlb->local);
|
tlb->max = ARRAY_SIZE(tlb->local);
|
||||||
tlb->pages = tlb->local;
|
tlb->pages = tlb->local;
|
||||||
tlb->nr = 0;
|
tlb->nr = 0;
|
||||||
tlb->fullmm = full_mm_flush;
|
tlb->fullmm = !(start | (end+1));
|
||||||
|
tlb->start = start;
|
||||||
|
tlb->end = end;
|
||||||
tlb->start_addr = ~0UL;
|
tlb->start_addr = ~0UL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -18,9 +18,11 @@
|
|||||||
#include <asm/machdep.h>
|
#include <asm/machdep.h>
|
||||||
#include <asm/natfeat.h>
|
#include <asm/natfeat.h>
|
||||||
|
|
||||||
|
extern long nf_get_id2(const char *feature_name);
|
||||||
|
|
||||||
asm("\n"
|
asm("\n"
|
||||||
" .global nf_get_id,nf_call\n"
|
" .global nf_get_id2,nf_call\n"
|
||||||
"nf_get_id:\n"
|
"nf_get_id2:\n"
|
||||||
" .short 0x7300\n"
|
" .short 0x7300\n"
|
||||||
" rts\n"
|
" rts\n"
|
||||||
"nf_call:\n"
|
"nf_call:\n"
|
||||||
@@ -29,12 +31,25 @@ asm("\n"
|
|||||||
"1: moveq.l #0,%d0\n"
|
"1: moveq.l #0,%d0\n"
|
||||||
" rts\n"
|
" rts\n"
|
||||||
" .section __ex_table,\"a\"\n"
|
" .section __ex_table,\"a\"\n"
|
||||||
" .long nf_get_id,1b\n"
|
" .long nf_get_id2,1b\n"
|
||||||
" .long nf_call,1b\n"
|
" .long nf_call,1b\n"
|
||||||
" .previous");
|
" .previous");
|
||||||
EXPORT_SYMBOL_GPL(nf_get_id);
|
|
||||||
EXPORT_SYMBOL_GPL(nf_call);
|
EXPORT_SYMBOL_GPL(nf_call);
|
||||||
|
|
||||||
|
long nf_get_id(const char *feature_name)
|
||||||
|
{
|
||||||
|
/* feature_name may be in vmalloc()ed memory, so make a copy */
|
||||||
|
char name_copy[32];
|
||||||
|
size_t n;
|
||||||
|
|
||||||
|
n = strlcpy(name_copy, feature_name, sizeof(name_copy));
|
||||||
|
if (n >= sizeof(name_copy))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return nf_get_id2(name_copy);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(nf_get_id);
|
||||||
|
|
||||||
void nfprint(const char *fmt, ...)
|
void nfprint(const char *fmt, ...)
|
||||||
{
|
{
|
||||||
static char buf[256];
|
static char buf[256];
|
||||||
|
@@ -15,16 +15,17 @@
|
|||||||
unsigned long long n64; \
|
unsigned long long n64; \
|
||||||
} __n; \
|
} __n; \
|
||||||
unsigned long __rem, __upper; \
|
unsigned long __rem, __upper; \
|
||||||
|
unsigned long __base = (base); \
|
||||||
\
|
\
|
||||||
__n.n64 = (n); \
|
__n.n64 = (n); \
|
||||||
if ((__upper = __n.n32[0])) { \
|
if ((__upper = __n.n32[0])) { \
|
||||||
asm ("divul.l %2,%1:%0" \
|
asm ("divul.l %2,%1:%0" \
|
||||||
: "=d" (__n.n32[0]), "=d" (__upper) \
|
: "=d" (__n.n32[0]), "=d" (__upper) \
|
||||||
: "d" (base), "0" (__n.n32[0])); \
|
: "d" (__base), "0" (__n.n32[0])); \
|
||||||
} \
|
} \
|
||||||
asm ("divu.l %2,%1:%0" \
|
asm ("divu.l %2,%1:%0" \
|
||||||
: "=d" (__n.n32[1]), "=d" (__rem) \
|
: "=d" (__n.n32[1]), "=d" (__rem) \
|
||||||
: "d" (base), "1" (__upper), "0" (__n.n32[1])); \
|
: "d" (__base), "1" (__upper), "0" (__n.n32[1])); \
|
||||||
(n) = __n.n64; \
|
(n) = __n.n64; \
|
||||||
__rem; \
|
__rem; \
|
||||||
})
|
})
|
||||||
|
@@ -803,6 +803,32 @@ static int isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn,
|
|||||||
dec_insn.next_pc_inc;
|
dec_insn.next_pc_inc;
|
||||||
return 1;
|
return 1;
|
||||||
break;
|
break;
|
||||||
|
#ifdef CONFIG_CPU_CAVIUM_OCTEON
|
||||||
|
case lwc2_op: /* This is bbit0 on Octeon */
|
||||||
|
if ((regs->regs[insn.i_format.rs] & (1ull<<insn.i_format.rt)) == 0)
|
||||||
|
*contpc = regs->cp0_epc + 4 + (insn.i_format.simmediate << 2);
|
||||||
|
else
|
||||||
|
*contpc = regs->cp0_epc + 8;
|
||||||
|
return 1;
|
||||||
|
case ldc2_op: /* This is bbit032 on Octeon */
|
||||||
|
if ((regs->regs[insn.i_format.rs] & (1ull<<(insn.i_format.rt + 32))) == 0)
|
||||||
|
*contpc = regs->cp0_epc + 4 + (insn.i_format.simmediate << 2);
|
||||||
|
else
|
||||||
|
*contpc = regs->cp0_epc + 8;
|
||||||
|
return 1;
|
||||||
|
case swc2_op: /* This is bbit1 on Octeon */
|
||||||
|
if (regs->regs[insn.i_format.rs] & (1ull<<insn.i_format.rt))
|
||||||
|
*contpc = regs->cp0_epc + 4 + (insn.i_format.simmediate << 2);
|
||||||
|
else
|
||||||
|
*contpc = regs->cp0_epc + 8;
|
||||||
|
return 1;
|
||||||
|
case sdc2_op: /* This is bbit132 on Octeon */
|
||||||
|
if (regs->regs[insn.i_format.rs] & (1ull<<(insn.i_format.rt + 32)))
|
||||||
|
*contpc = regs->cp0_epc + 4 + (insn.i_format.simmediate << 2);
|
||||||
|
else
|
||||||
|
*contpc = regs->cp0_epc + 8;
|
||||||
|
return 1;
|
||||||
|
#endif
|
||||||
case cop0_op:
|
case cop0_op:
|
||||||
case cop1_op:
|
case cop1_op:
|
||||||
case cop2_op:
|
case cop2_op:
|
||||||
|
@@ -979,6 +979,7 @@ config RELOCATABLE
|
|||||||
must live at a different physical address than the primary
|
must live at a different physical address than the primary
|
||||||
kernel.
|
kernel.
|
||||||
|
|
||||||
|
# This value must have zeroes in the bottom 60 bits otherwise lots will break
|
||||||
config PAGE_OFFSET
|
config PAGE_OFFSET
|
||||||
hex
|
hex
|
||||||
default "0xc000000000000000"
|
default "0xc000000000000000"
|
||||||
|
@@ -211,9 +211,19 @@ extern long long virt_phys_offset;
|
|||||||
#define __va(x) ((void *)(unsigned long)((phys_addr_t)(x) + VIRT_PHYS_OFFSET))
|
#define __va(x) ((void *)(unsigned long)((phys_addr_t)(x) + VIRT_PHYS_OFFSET))
|
||||||
#define __pa(x) ((unsigned long)(x) - VIRT_PHYS_OFFSET)
|
#define __pa(x) ((unsigned long)(x) - VIRT_PHYS_OFFSET)
|
||||||
#else
|
#else
|
||||||
|
#ifdef CONFIG_PPC64
|
||||||
|
/*
|
||||||
|
* gcc miscompiles (unsigned long)(&static_var) - PAGE_OFFSET
|
||||||
|
* with -mcmodel=medium, so we use & and | instead of - and + on 64-bit.
|
||||||
|
*/
|
||||||
|
#define __va(x) ((void *)(unsigned long)((phys_addr_t)(x) | PAGE_OFFSET))
|
||||||
|
#define __pa(x) ((unsigned long)(x) & 0x0fffffffffffffffUL)
|
||||||
|
|
||||||
|
#else /* 32-bit, non book E */
|
||||||
#define __va(x) ((void *)(unsigned long)((phys_addr_t)(x) + PAGE_OFFSET - MEMORY_START))
|
#define __va(x) ((void *)(unsigned long)((phys_addr_t)(x) + PAGE_OFFSET - MEMORY_START))
|
||||||
#define __pa(x) ((unsigned long)(x) - PAGE_OFFSET + MEMORY_START)
|
#define __pa(x) ((unsigned long)(x) - PAGE_OFFSET + MEMORY_START)
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Unfortunately the PLT is in the BSS in the PPC32 ELF ABI,
|
* Unfortunately the PLT is in the BSS in the PPC32 ELF ABI,
|
||||||
|
@@ -35,7 +35,13 @@
|
|||||||
#include <asm/vdso_datapage.h>
|
#include <asm/vdso_datapage.h>
|
||||||
#include <asm/vio.h>
|
#include <asm/vio.h>
|
||||||
#include <asm/mmu.h>
|
#include <asm/mmu.h>
|
||||||
|
#include <asm/machdep.h>
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This isn't a module but we expose that to userspace
|
||||||
|
* via /proc so leave the definitions here
|
||||||
|
*/
|
||||||
#define MODULE_VERS "1.9"
|
#define MODULE_VERS "1.9"
|
||||||
#define MODULE_NAME "lparcfg"
|
#define MODULE_NAME "lparcfg"
|
||||||
|
|
||||||
@@ -418,7 +424,8 @@ static void parse_em_data(struct seq_file *m)
|
|||||||
{
|
{
|
||||||
unsigned long retbuf[PLPAR_HCALL_BUFSIZE];
|
unsigned long retbuf[PLPAR_HCALL_BUFSIZE];
|
||||||
|
|
||||||
if (plpar_hcall(H_GET_EM_PARMS, retbuf) == H_SUCCESS)
|
if (firmware_has_feature(FW_FEATURE_LPAR) &&
|
||||||
|
plpar_hcall(H_GET_EM_PARMS, retbuf) == H_SUCCESS)
|
||||||
seq_printf(m, "power_mode_data=%016lx\n", retbuf[0]);
|
seq_printf(m, "power_mode_data=%016lx\n", retbuf[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -677,7 +684,6 @@ static int lparcfg_open(struct inode *inode, struct file *file)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static const struct file_operations lparcfg_fops = {
|
static const struct file_operations lparcfg_fops = {
|
||||||
.owner = THIS_MODULE,
|
|
||||||
.read = seq_read,
|
.read = seq_read,
|
||||||
.write = lparcfg_write,
|
.write = lparcfg_write,
|
||||||
.open = lparcfg_open,
|
.open = lparcfg_open,
|
||||||
@@ -699,14 +705,4 @@ static int __init lparcfg_init(void)
|
|||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
machine_device_initcall(pseries, lparcfg_init);
|
||||||
static void __exit lparcfg_cleanup(void)
|
|
||||||
{
|
|
||||||
remove_proc_subtree("powerpc/lparcfg", NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
module_init(lparcfg_init);
|
|
||||||
module_exit(lparcfg_cleanup);
|
|
||||||
MODULE_DESCRIPTION("Interface for LPAR configuration data");
|
|
||||||
MODULE_AUTHOR("Dave Engebretsen");
|
|
||||||
MODULE_LICENSE("GPL");
|
|
||||||
|
@@ -32,6 +32,7 @@ struct mmu_gather {
|
|||||||
struct mm_struct *mm;
|
struct mm_struct *mm;
|
||||||
struct mmu_table_batch *batch;
|
struct mmu_table_batch *batch;
|
||||||
unsigned int fullmm;
|
unsigned int fullmm;
|
||||||
|
unsigned long start, end;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct mmu_table_batch {
|
struct mmu_table_batch {
|
||||||
@@ -48,10 +49,13 @@ extern void tlb_remove_table(struct mmu_gather *tlb, void *table);
|
|||||||
|
|
||||||
static inline void tlb_gather_mmu(struct mmu_gather *tlb,
|
static inline void tlb_gather_mmu(struct mmu_gather *tlb,
|
||||||
struct mm_struct *mm,
|
struct mm_struct *mm,
|
||||||
unsigned int full_mm_flush)
|
unsigned long start,
|
||||||
|
unsigned long end)
|
||||||
{
|
{
|
||||||
tlb->mm = mm;
|
tlb->mm = mm;
|
||||||
tlb->fullmm = full_mm_flush;
|
tlb->start = start;
|
||||||
|
tlb->end = end;
|
||||||
|
tlb->fullmm = !(start | (end+1));
|
||||||
tlb->batch = NULL;
|
tlb->batch = NULL;
|
||||||
if (tlb->fullmm)
|
if (tlb->fullmm)
|
||||||
__tlb_flush_mm(mm);
|
__tlb_flush_mm(mm);
|
||||||
|
@@ -36,10 +36,12 @@ static inline void init_tlb_gather(struct mmu_gather *tlb)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
tlb_gather_mmu(struct mmu_gather *tlb, struct mm_struct *mm, unsigned int full_mm_flush)
|
tlb_gather_mmu(struct mmu_gather *tlb, struct mm_struct *mm, unsigned long start, unsigned long end)
|
||||||
{
|
{
|
||||||
tlb->mm = mm;
|
tlb->mm = mm;
|
||||||
tlb->fullmm = full_mm_flush;
|
tlb->start = start;
|
||||||
|
tlb->end = end;
|
||||||
|
tlb->fullmm = !(start | (end+1));
|
||||||
|
|
||||||
init_tlb_gather(tlb);
|
init_tlb_gather(tlb);
|
||||||
}
|
}
|
||||||
|
@@ -45,10 +45,12 @@ static inline void init_tlb_gather(struct mmu_gather *tlb)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
tlb_gather_mmu(struct mmu_gather *tlb, struct mm_struct *mm, unsigned int full_mm_flush)
|
tlb_gather_mmu(struct mmu_gather *tlb, struct mm_struct *mm, unsigned long start, unsigned long end)
|
||||||
{
|
{
|
||||||
tlb->mm = mm;
|
tlb->mm = mm;
|
||||||
tlb->fullmm = full_mm_flush;
|
tlb->start = start;
|
||||||
|
tlb->end = end;
|
||||||
|
tlb->fullmm = !(start | (end+1));
|
||||||
|
|
||||||
init_tlb_gather(tlb);
|
init_tlb_gather(tlb);
|
||||||
}
|
}
|
||||||
|
@@ -35,9 +35,9 @@ static void sanitize_boot_params(struct boot_params *boot_params)
|
|||||||
*/
|
*/
|
||||||
if (boot_params->sentinel) {
|
if (boot_params->sentinel) {
|
||||||
/* fields in boot_params are left uninitialized, clear them */
|
/* fields in boot_params are left uninitialized, clear them */
|
||||||
memset(&boot_params->olpc_ofw_header, 0,
|
memset(&boot_params->ext_ramdisk_image, 0,
|
||||||
(char *)&boot_params->efi_info -
|
(char *)&boot_params->efi_info -
|
||||||
(char *)&boot_params->olpc_ofw_header);
|
(char *)&boot_params->ext_ramdisk_image);
|
||||||
memset(&boot_params->kbd_status, 0,
|
memset(&boot_params->kbd_status, 0,
|
||||||
(char *)&boot_params->hdr -
|
(char *)&boot_params->hdr -
|
||||||
(char *)&boot_params->kbd_status);
|
(char *)&boot_params->kbd_status);
|
||||||
|
@@ -59,7 +59,7 @@ static inline u16 find_equiv_id(struct equiv_cpu_entry *equiv_cpu_table,
|
|||||||
|
|
||||||
extern int __apply_microcode_amd(struct microcode_amd *mc_amd);
|
extern int __apply_microcode_amd(struct microcode_amd *mc_amd);
|
||||||
extern int apply_microcode_amd(int cpu);
|
extern int apply_microcode_amd(int cpu);
|
||||||
extern enum ucode_state load_microcode_amd(int cpu, const u8 *data, size_t size);
|
extern enum ucode_state load_microcode_amd(u8 family, const u8 *data, size_t size);
|
||||||
|
|
||||||
#ifdef CONFIG_MICROCODE_AMD_EARLY
|
#ifdef CONFIG_MICROCODE_AMD_EARLY
|
||||||
#ifdef CONFIG_X86_32
|
#ifdef CONFIG_X86_32
|
||||||
|
@@ -512,7 +512,7 @@ static void early_init_amd(struct cpuinfo_x86 *c)
|
|||||||
|
|
||||||
static const int amd_erratum_383[];
|
static const int amd_erratum_383[];
|
||||||
static const int amd_erratum_400[];
|
static const int amd_erratum_400[];
|
||||||
static bool cpu_has_amd_erratum(const int *erratum);
|
static bool cpu_has_amd_erratum(struct cpuinfo_x86 *cpu, const int *erratum);
|
||||||
|
|
||||||
static void init_amd(struct cpuinfo_x86 *c)
|
static void init_amd(struct cpuinfo_x86 *c)
|
||||||
{
|
{
|
||||||
@@ -729,11 +729,11 @@ static void init_amd(struct cpuinfo_x86 *c)
|
|||||||
value &= ~(1ULL << 24);
|
value &= ~(1ULL << 24);
|
||||||
wrmsrl_safe(MSR_AMD64_BU_CFG2, value);
|
wrmsrl_safe(MSR_AMD64_BU_CFG2, value);
|
||||||
|
|
||||||
if (cpu_has_amd_erratum(amd_erratum_383))
|
if (cpu_has_amd_erratum(c, amd_erratum_383))
|
||||||
set_cpu_bug(c, X86_BUG_AMD_TLB_MMATCH);
|
set_cpu_bug(c, X86_BUG_AMD_TLB_MMATCH);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cpu_has_amd_erratum(amd_erratum_400))
|
if (cpu_has_amd_erratum(c, amd_erratum_400))
|
||||||
set_cpu_bug(c, X86_BUG_AMD_APIC_C1E);
|
set_cpu_bug(c, X86_BUG_AMD_APIC_C1E);
|
||||||
|
|
||||||
rdmsr_safe(MSR_AMD64_PATCH_LEVEL, &c->microcode, &dummy);
|
rdmsr_safe(MSR_AMD64_PATCH_LEVEL, &c->microcode, &dummy);
|
||||||
@@ -878,23 +878,13 @@ static const int amd_erratum_400[] =
|
|||||||
static const int amd_erratum_383[] =
|
static const int amd_erratum_383[] =
|
||||||
AMD_OSVW_ERRATUM(3, AMD_MODEL_RANGE(0x10, 0, 0, 0xff, 0xf));
|
AMD_OSVW_ERRATUM(3, AMD_MODEL_RANGE(0x10, 0, 0, 0xff, 0xf));
|
||||||
|
|
||||||
static bool cpu_has_amd_erratum(const int *erratum)
|
|
||||||
|
static bool cpu_has_amd_erratum(struct cpuinfo_x86 *cpu, const int *erratum)
|
||||||
{
|
{
|
||||||
struct cpuinfo_x86 *cpu = __this_cpu_ptr(&cpu_info);
|
|
||||||
int osvw_id = *erratum++;
|
int osvw_id = *erratum++;
|
||||||
u32 range;
|
u32 range;
|
||||||
u32 ms;
|
u32 ms;
|
||||||
|
|
||||||
/*
|
|
||||||
* If called early enough that current_cpu_data hasn't been initialized
|
|
||||||
* yet, fall back to boot_cpu_data.
|
|
||||||
*/
|
|
||||||
if (cpu->x86 == 0)
|
|
||||||
cpu = &boot_cpu_data;
|
|
||||||
|
|
||||||
if (cpu->x86_vendor != X86_VENDOR_AMD)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (osvw_id >= 0 && osvw_id < 65536 &&
|
if (osvw_id >= 0 && osvw_id < 65536 &&
|
||||||
cpu_has(cpu, X86_FEATURE_OSVW)) {
|
cpu_has(cpu, X86_FEATURE_OSVW)) {
|
||||||
u64 osvw_len;
|
u64 osvw_len;
|
||||||
|
@@ -145,10 +145,9 @@ static int collect_cpu_info_amd(int cpu, struct cpu_signature *csig)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned int verify_patch_size(int cpu, u32 patch_size,
|
static unsigned int verify_patch_size(u8 family, u32 patch_size,
|
||||||
unsigned int size)
|
unsigned int size)
|
||||||
{
|
{
|
||||||
struct cpuinfo_x86 *c = &cpu_data(cpu);
|
|
||||||
u32 max_size;
|
u32 max_size;
|
||||||
|
|
||||||
#define F1XH_MPB_MAX_SIZE 2048
|
#define F1XH_MPB_MAX_SIZE 2048
|
||||||
@@ -156,7 +155,7 @@ static unsigned int verify_patch_size(int cpu, u32 patch_size,
|
|||||||
#define F15H_MPB_MAX_SIZE 4096
|
#define F15H_MPB_MAX_SIZE 4096
|
||||||
#define F16H_MPB_MAX_SIZE 3458
|
#define F16H_MPB_MAX_SIZE 3458
|
||||||
|
|
||||||
switch (c->x86) {
|
switch (family) {
|
||||||
case 0x14:
|
case 0x14:
|
||||||
max_size = F14H_MPB_MAX_SIZE;
|
max_size = F14H_MPB_MAX_SIZE;
|
||||||
break;
|
break;
|
||||||
@@ -277,9 +276,8 @@ static void cleanup(void)
|
|||||||
* driver cannot continue functioning normally. In such cases, we tear
|
* driver cannot continue functioning normally. In such cases, we tear
|
||||||
* down everything we've used up so far and exit.
|
* down everything we've used up so far and exit.
|
||||||
*/
|
*/
|
||||||
static int verify_and_add_patch(unsigned int cpu, u8 *fw, unsigned int leftover)
|
static int verify_and_add_patch(u8 family, u8 *fw, unsigned int leftover)
|
||||||
{
|
{
|
||||||
struct cpuinfo_x86 *c = &cpu_data(cpu);
|
|
||||||
struct microcode_header_amd *mc_hdr;
|
struct microcode_header_amd *mc_hdr;
|
||||||
struct ucode_patch *patch;
|
struct ucode_patch *patch;
|
||||||
unsigned int patch_size, crnt_size, ret;
|
unsigned int patch_size, crnt_size, ret;
|
||||||
@@ -299,7 +297,7 @@ static int verify_and_add_patch(unsigned int cpu, u8 *fw, unsigned int leftover)
|
|||||||
|
|
||||||
/* check if patch is for the current family */
|
/* check if patch is for the current family */
|
||||||
proc_fam = ((proc_fam >> 8) & 0xf) + ((proc_fam >> 20) & 0xff);
|
proc_fam = ((proc_fam >> 8) & 0xf) + ((proc_fam >> 20) & 0xff);
|
||||||
if (proc_fam != c->x86)
|
if (proc_fam != family)
|
||||||
return crnt_size;
|
return crnt_size;
|
||||||
|
|
||||||
if (mc_hdr->nb_dev_id || mc_hdr->sb_dev_id) {
|
if (mc_hdr->nb_dev_id || mc_hdr->sb_dev_id) {
|
||||||
@@ -308,7 +306,7 @@ static int verify_and_add_patch(unsigned int cpu, u8 *fw, unsigned int leftover)
|
|||||||
return crnt_size;
|
return crnt_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = verify_patch_size(cpu, patch_size, leftover);
|
ret = verify_patch_size(family, patch_size, leftover);
|
||||||
if (!ret) {
|
if (!ret) {
|
||||||
pr_err("Patch-ID 0x%08x: size mismatch.\n", mc_hdr->patch_id);
|
pr_err("Patch-ID 0x%08x: size mismatch.\n", mc_hdr->patch_id);
|
||||||
return crnt_size;
|
return crnt_size;
|
||||||
@@ -339,7 +337,8 @@ static int verify_and_add_patch(unsigned int cpu, u8 *fw, unsigned int leftover)
|
|||||||
return crnt_size;
|
return crnt_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
static enum ucode_state __load_microcode_amd(int cpu, const u8 *data, size_t size)
|
static enum ucode_state __load_microcode_amd(u8 family, const u8 *data,
|
||||||
|
size_t size)
|
||||||
{
|
{
|
||||||
enum ucode_state ret = UCODE_ERROR;
|
enum ucode_state ret = UCODE_ERROR;
|
||||||
unsigned int leftover;
|
unsigned int leftover;
|
||||||
@@ -362,7 +361,7 @@ static enum ucode_state __load_microcode_amd(int cpu, const u8 *data, size_t siz
|
|||||||
}
|
}
|
||||||
|
|
||||||
while (leftover) {
|
while (leftover) {
|
||||||
crnt_size = verify_and_add_patch(cpu, fw, leftover);
|
crnt_size = verify_and_add_patch(family, fw, leftover);
|
||||||
if (crnt_size < 0)
|
if (crnt_size < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
@@ -373,22 +372,22 @@ static enum ucode_state __load_microcode_amd(int cpu, const u8 *data, size_t siz
|
|||||||
return UCODE_OK;
|
return UCODE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum ucode_state load_microcode_amd(int cpu, const u8 *data, size_t size)
|
enum ucode_state load_microcode_amd(u8 family, const u8 *data, size_t size)
|
||||||
{
|
{
|
||||||
enum ucode_state ret;
|
enum ucode_state ret;
|
||||||
|
|
||||||
/* free old equiv table */
|
/* free old equiv table */
|
||||||
free_equiv_cpu_table();
|
free_equiv_cpu_table();
|
||||||
|
|
||||||
ret = __load_microcode_amd(cpu, data, size);
|
ret = __load_microcode_amd(family, data, size);
|
||||||
|
|
||||||
if (ret != UCODE_OK)
|
if (ret != UCODE_OK)
|
||||||
cleanup();
|
cleanup();
|
||||||
|
|
||||||
#if defined(CONFIG_MICROCODE_AMD_EARLY) && defined(CONFIG_X86_32)
|
#if defined(CONFIG_MICROCODE_AMD_EARLY) && defined(CONFIG_X86_32)
|
||||||
/* save BSP's matching patch for early load */
|
/* save BSP's matching patch for early load */
|
||||||
if (cpu_data(cpu).cpu_index == boot_cpu_data.cpu_index) {
|
if (cpu_data(smp_processor_id()).cpu_index == boot_cpu_data.cpu_index) {
|
||||||
struct ucode_patch *p = find_patch(cpu);
|
struct ucode_patch *p = find_patch(smp_processor_id());
|
||||||
if (p) {
|
if (p) {
|
||||||
memset(amd_bsp_mpb, 0, MPB_MAX_SIZE);
|
memset(amd_bsp_mpb, 0, MPB_MAX_SIZE);
|
||||||
memcpy(amd_bsp_mpb, p->data, min_t(u32, ksize(p->data),
|
memcpy(amd_bsp_mpb, p->data, min_t(u32, ksize(p->data),
|
||||||
@@ -441,7 +440,7 @@ static enum ucode_state request_microcode_amd(int cpu, struct device *device,
|
|||||||
goto fw_release;
|
goto fw_release;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = load_microcode_amd(cpu, fw->data, fw->size);
|
ret = load_microcode_amd(c->x86, fw->data, fw->size);
|
||||||
|
|
||||||
fw_release:
|
fw_release:
|
||||||
release_firmware(fw);
|
release_firmware(fw);
|
||||||
|
@@ -238,25 +238,17 @@ static void __init collect_cpu_sig_on_bsp(void *arg)
|
|||||||
uci->cpu_sig.sig = cpuid_eax(0x00000001);
|
uci->cpu_sig.sig = cpuid_eax(0x00000001);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
static void collect_cpu_info_amd_early(struct cpuinfo_x86 *c,
|
void load_ucode_amd_ap(void)
|
||||||
struct ucode_cpu_info *uci)
|
|
||||||
{
|
{
|
||||||
|
unsigned int cpu = smp_processor_id();
|
||||||
|
struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
|
||||||
u32 rev, eax;
|
u32 rev, eax;
|
||||||
|
|
||||||
rdmsr(MSR_AMD64_PATCH_LEVEL, rev, eax);
|
rdmsr(MSR_AMD64_PATCH_LEVEL, rev, eax);
|
||||||
eax = cpuid_eax(0x00000001);
|
eax = cpuid_eax(0x00000001);
|
||||||
|
|
||||||
uci->cpu_sig.sig = eax;
|
|
||||||
uci->cpu_sig.rev = rev;
|
uci->cpu_sig.rev = rev;
|
||||||
c->microcode = rev;
|
uci->cpu_sig.sig = eax;
|
||||||
c->x86 = ((eax >> 8) & 0xf) + ((eax >> 20) & 0xff);
|
|
||||||
}
|
|
||||||
|
|
||||||
void load_ucode_amd_ap(void)
|
|
||||||
{
|
|
||||||
unsigned int cpu = smp_processor_id();
|
|
||||||
|
|
||||||
collect_cpu_info_amd_early(&cpu_data(cpu), ucode_cpu_info + cpu);
|
|
||||||
|
|
||||||
if (cpu && !ucode_loaded) {
|
if (cpu && !ucode_loaded) {
|
||||||
void *ucode;
|
void *ucode;
|
||||||
@@ -265,8 +257,10 @@ void load_ucode_amd_ap(void)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
ucode = (void *)(initrd_start + ucode_offset);
|
ucode = (void *)(initrd_start + ucode_offset);
|
||||||
if (load_microcode_amd(0, ucode, ucode_size) != UCODE_OK)
|
eax = ((eax >> 8) & 0xf) + ((eax >> 20) & 0xff);
|
||||||
|
if (load_microcode_amd(eax, ucode, ucode_size) != UCODE_OK)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ucode_loaded = true;
|
ucode_loaded = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -278,6 +272,8 @@ int __init save_microcode_in_initrd_amd(void)
|
|||||||
{
|
{
|
||||||
enum ucode_state ret;
|
enum ucode_state ret;
|
||||||
void *ucode;
|
void *ucode;
|
||||||
|
u32 eax;
|
||||||
|
|
||||||
#ifdef CONFIG_X86_32
|
#ifdef CONFIG_X86_32
|
||||||
unsigned int bsp = boot_cpu_data.cpu_index;
|
unsigned int bsp = boot_cpu_data.cpu_index;
|
||||||
struct ucode_cpu_info *uci = ucode_cpu_info + bsp;
|
struct ucode_cpu_info *uci = ucode_cpu_info + bsp;
|
||||||
@@ -293,7 +289,10 @@ int __init save_microcode_in_initrd_amd(void)
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
ucode = (void *)(initrd_start + ucode_offset);
|
ucode = (void *)(initrd_start + ucode_offset);
|
||||||
ret = load_microcode_amd(0, ucode, ucode_size);
|
eax = cpuid_eax(0x00000001);
|
||||||
|
eax = ((eax >> 8) & 0xf) + ((eax >> 20) & 0xff);
|
||||||
|
|
||||||
|
ret = load_microcode_amd(eax, ucode, ucode_size);
|
||||||
if (ret != UCODE_OK)
|
if (ret != UCODE_OK)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
|
@@ -101,7 +101,7 @@ static void find_start_end(unsigned long flags, unsigned long *begin,
|
|||||||
*begin = new_begin;
|
*begin = new_begin;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
*begin = mmap_legacy_base();
|
*begin = current->mm->mmap_legacy_base;
|
||||||
*end = TASK_SIZE;
|
*end = TASK_SIZE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -78,8 +78,8 @@ __ref void *alloc_low_pages(unsigned int num)
|
|||||||
return __va(pfn << PAGE_SHIFT);
|
return __va(pfn << PAGE_SHIFT);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* need 4 4k for initial PMD_SIZE, 4k for 0-ISA_END_ADDRESS */
|
/* need 3 4k for initial PMD_SIZE, 3 4k for 0-ISA_END_ADDRESS */
|
||||||
#define INIT_PGT_BUF_SIZE (5 * PAGE_SIZE)
|
#define INIT_PGT_BUF_SIZE (6 * PAGE_SIZE)
|
||||||
RESERVE_BRK(early_pgt_alloc, INIT_PGT_BUF_SIZE);
|
RESERVE_BRK(early_pgt_alloc, INIT_PGT_BUF_SIZE);
|
||||||
void __init early_alloc_pgt_buf(void)
|
void __init early_alloc_pgt_buf(void)
|
||||||
{
|
{
|
||||||
|
@@ -98,7 +98,7 @@ static unsigned long mmap_base(void)
|
|||||||
* Bottom-up (legacy) layout on X86_32 did not support randomization, X86_64
|
* Bottom-up (legacy) layout on X86_32 did not support randomization, X86_64
|
||||||
* does, but not when emulating X86_32
|
* does, but not when emulating X86_32
|
||||||
*/
|
*/
|
||||||
unsigned long mmap_legacy_base(void)
|
static unsigned long mmap_legacy_base(void)
|
||||||
{
|
{
|
||||||
if (mmap_is_ia32())
|
if (mmap_is_ia32())
|
||||||
return TASK_UNMAPPED_BASE;
|
return TASK_UNMAPPED_BASE;
|
||||||
@@ -112,11 +112,13 @@ unsigned long mmap_legacy_base(void)
|
|||||||
*/
|
*/
|
||||||
void arch_pick_mmap_layout(struct mm_struct *mm)
|
void arch_pick_mmap_layout(struct mm_struct *mm)
|
||||||
{
|
{
|
||||||
|
mm->mmap_legacy_base = mmap_legacy_base();
|
||||||
|
mm->mmap_base = mmap_base();
|
||||||
|
|
||||||
if (mmap_is_legacy()) {
|
if (mmap_is_legacy()) {
|
||||||
mm->mmap_base = mmap_legacy_base();
|
mm->mmap_base = mm->mmap_legacy_base;
|
||||||
mm->get_unmapped_area = arch_get_unmapped_area;
|
mm->get_unmapped_area = arch_get_unmapped_area;
|
||||||
} else {
|
} else {
|
||||||
mm->mmap_base = mmap_base();
|
|
||||||
mm->get_unmapped_area = arch_get_unmapped_area_topdown;
|
mm->get_unmapped_area = arch_get_unmapped_area_topdown;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -313,6 +313,17 @@ static void xen_align_and_add_e820_region(u64 start, u64 size, int type)
|
|||||||
e820_add_region(start, end - start, type);
|
e820_add_region(start, end - start, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void xen_ignore_unusable(struct e820entry *list, size_t map_size)
|
||||||
|
{
|
||||||
|
struct e820entry *entry;
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
|
for (i = 0, entry = list; i < map_size; i++, entry++) {
|
||||||
|
if (entry->type == E820_UNUSABLE)
|
||||||
|
entry->type = E820_RAM;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* machine_specific_memory_setup - Hook for machine specific memory setup.
|
* machine_specific_memory_setup - Hook for machine specific memory setup.
|
||||||
**/
|
**/
|
||||||
@@ -353,6 +364,17 @@ char * __init xen_memory_setup(void)
|
|||||||
}
|
}
|
||||||
BUG_ON(rc);
|
BUG_ON(rc);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Xen won't allow a 1:1 mapping to be created to UNUSABLE
|
||||||
|
* regions, so if we're using the machine memory map leave the
|
||||||
|
* region as RAM as it is in the pseudo-physical map.
|
||||||
|
*
|
||||||
|
* UNUSABLE regions in domUs are not handled and will need
|
||||||
|
* a patch in the future.
|
||||||
|
*/
|
||||||
|
if (xen_initial_domain())
|
||||||
|
xen_ignore_unusable(map, memmap.nr_entries);
|
||||||
|
|
||||||
/* Make sure the Xen-supplied memory map is well-ordered. */
|
/* Make sure the Xen-supplied memory map is well-ordered. */
|
||||||
sanitize_e820_map(map, memmap.nr_entries, &memmap.nr_entries);
|
sanitize_e820_map(map, memmap.nr_entries, &memmap.nr_entries);
|
||||||
|
|
||||||
|
@@ -694,8 +694,15 @@ static void __init xen_hvm_smp_prepare_cpus(unsigned int max_cpus)
|
|||||||
static int xen_hvm_cpu_up(unsigned int cpu, struct task_struct *tidle)
|
static int xen_hvm_cpu_up(unsigned int cpu, struct task_struct *tidle)
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
rc = native_cpu_up(cpu, tidle);
|
/*
|
||||||
WARN_ON (xen_smp_intr_init(cpu));
|
* xen_smp_intr_init() needs to run before native_cpu_up()
|
||||||
|
* so that IPI vectors are set up on the booting CPU before
|
||||||
|
* it is marked online in native_cpu_up().
|
||||||
|
*/
|
||||||
|
rc = xen_smp_intr_init(cpu);
|
||||||
|
WARN_ON(rc);
|
||||||
|
if (!rc)
|
||||||
|
rc = native_cpu_up(cpu, tidle);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -908,9 +908,6 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device)
|
|||||||
device->cap._DDC = 1;
|
device->cap._DDC = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (acpi_video_init_brightness(device))
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (acpi_video_backlight_support()) {
|
if (acpi_video_backlight_support()) {
|
||||||
struct backlight_properties props;
|
struct backlight_properties props;
|
||||||
struct pci_dev *pdev;
|
struct pci_dev *pdev;
|
||||||
@@ -920,6 +917,9 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device)
|
|||||||
static int count = 0;
|
static int count = 0;
|
||||||
char *name;
|
char *name;
|
||||||
|
|
||||||
|
result = acpi_video_init_brightness(device);
|
||||||
|
if (result)
|
||||||
|
return;
|
||||||
name = kasprintf(GFP_KERNEL, "acpi_video%d", count);
|
name = kasprintf(GFP_KERNEL, "acpi_video%d", count);
|
||||||
if (!name)
|
if (!name)
|
||||||
return;
|
return;
|
||||||
@@ -979,11 +979,6 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device)
|
|||||||
if (result)
|
if (result)
|
||||||
printk(KERN_ERR PREFIX "Create sysfs link\n");
|
printk(KERN_ERR PREFIX "Create sysfs link\n");
|
||||||
|
|
||||||
} else {
|
|
||||||
/* Remove the brightness object. */
|
|
||||||
kfree(device->brightness->levels);
|
|
||||||
kfree(device->brightness);
|
|
||||||
device->brightness = NULL;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -289,24 +289,24 @@ static int sata_pmp_configure(struct ata_device *dev, int print_info)
|
|||||||
|
|
||||||
/* Disable sending Early R_OK.
|
/* Disable sending Early R_OK.
|
||||||
* With "cached read" HDD testing and multiple ports busy on a SATA
|
* With "cached read" HDD testing and multiple ports busy on a SATA
|
||||||
* host controller, 3726 PMP will very rarely drop a deferred
|
* host controller, 3x26 PMP will very rarely drop a deferred
|
||||||
* R_OK that was intended for the host. Symptom will be all
|
* R_OK that was intended for the host. Symptom will be all
|
||||||
* 5 drives under test will timeout, get reset, and recover.
|
* 5 drives under test will timeout, get reset, and recover.
|
||||||
*/
|
*/
|
||||||
if (vendor == 0x1095 && devid == 0x3726) {
|
if (vendor == 0x1095 && (devid == 0x3726 || devid == 0x3826)) {
|
||||||
u32 reg;
|
u32 reg;
|
||||||
|
|
||||||
err_mask = sata_pmp_read(&ap->link, PMP_GSCR_SII_POL, ®);
|
err_mask = sata_pmp_read(&ap->link, PMP_GSCR_SII_POL, ®);
|
||||||
if (err_mask) {
|
if (err_mask) {
|
||||||
rc = -EIO;
|
rc = -EIO;
|
||||||
reason = "failed to read Sil3726 Private Register";
|
reason = "failed to read Sil3x26 Private Register";
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
reg &= ~0x1;
|
reg &= ~0x1;
|
||||||
err_mask = sata_pmp_write(&ap->link, PMP_GSCR_SII_POL, reg);
|
err_mask = sata_pmp_write(&ap->link, PMP_GSCR_SII_POL, reg);
|
||||||
if (err_mask) {
|
if (err_mask) {
|
||||||
rc = -EIO;
|
rc = -EIO;
|
||||||
reason = "failed to write Sil3726 Private Register";
|
reason = "failed to write Sil3x26 Private Register";
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -383,8 +383,8 @@ static void sata_pmp_quirks(struct ata_port *ap)
|
|||||||
u16 devid = sata_pmp_gscr_devid(gscr);
|
u16 devid = sata_pmp_gscr_devid(gscr);
|
||||||
struct ata_link *link;
|
struct ata_link *link;
|
||||||
|
|
||||||
if (vendor == 0x1095 && devid == 0x3726) {
|
if (vendor == 0x1095 && (devid == 0x3726 || devid == 0x3826)) {
|
||||||
/* sil3726 quirks */
|
/* sil3x26 quirks */
|
||||||
ata_for_each_link(link, ap, EDGE) {
|
ata_for_each_link(link, ap, EDGE) {
|
||||||
/* link reports offline after LPM */
|
/* link reports offline after LPM */
|
||||||
link->flags |= ATA_LFLAG_NO_LPM;
|
link->flags |= ATA_LFLAG_NO_LPM;
|
||||||
|
@@ -293,6 +293,7 @@ static void fsl_sata_set_irq_coalescing(struct ata_host *host,
|
|||||||
{
|
{
|
||||||
struct sata_fsl_host_priv *host_priv = host->private_data;
|
struct sata_fsl_host_priv *host_priv = host->private_data;
|
||||||
void __iomem *hcr_base = host_priv->hcr_base;
|
void __iomem *hcr_base = host_priv->hcr_base;
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
if (count > ICC_MAX_INT_COUNT_THRESHOLD)
|
if (count > ICC_MAX_INT_COUNT_THRESHOLD)
|
||||||
count = ICC_MAX_INT_COUNT_THRESHOLD;
|
count = ICC_MAX_INT_COUNT_THRESHOLD;
|
||||||
@@ -305,12 +306,12 @@ static void fsl_sata_set_irq_coalescing(struct ata_host *host,
|
|||||||
(count > ICC_MIN_INT_COUNT_THRESHOLD))
|
(count > ICC_MIN_INT_COUNT_THRESHOLD))
|
||||||
ticks = ICC_SAFE_INT_TICKS;
|
ticks = ICC_SAFE_INT_TICKS;
|
||||||
|
|
||||||
spin_lock(&host->lock);
|
spin_lock_irqsave(&host->lock, flags);
|
||||||
iowrite32((count << 24 | ticks), hcr_base + ICC);
|
iowrite32((count << 24 | ticks), hcr_base + ICC);
|
||||||
|
|
||||||
intr_coalescing_count = count;
|
intr_coalescing_count = count;
|
||||||
intr_coalescing_ticks = ticks;
|
intr_coalescing_ticks = ticks;
|
||||||
spin_unlock(&host->lock);
|
spin_unlock_irqrestore(&host->lock, flags);
|
||||||
|
|
||||||
DPRINTK("interrupt coalescing, count = 0x%x, ticks = %x\n",
|
DPRINTK("interrupt coalescing, count = 0x%x, ticks = %x\n",
|
||||||
intr_coalescing_count, intr_coalescing_ticks);
|
intr_coalescing_count, intr_coalescing_ticks);
|
||||||
|
@@ -86,11 +86,11 @@ struct ecx_plat_data {
|
|||||||
|
|
||||||
#define SGPIO_SIGNALS 3
|
#define SGPIO_SIGNALS 3
|
||||||
#define ECX_ACTIVITY_BITS 0x300000
|
#define ECX_ACTIVITY_BITS 0x300000
|
||||||
#define ECX_ACTIVITY_SHIFT 2
|
#define ECX_ACTIVITY_SHIFT 0
|
||||||
#define ECX_LOCATE_BITS 0x80000
|
#define ECX_LOCATE_BITS 0x80000
|
||||||
#define ECX_LOCATE_SHIFT 1
|
#define ECX_LOCATE_SHIFT 1
|
||||||
#define ECX_FAULT_BITS 0x400000
|
#define ECX_FAULT_BITS 0x400000
|
||||||
#define ECX_FAULT_SHIFT 0
|
#define ECX_FAULT_SHIFT 2
|
||||||
static inline int sgpio_bit_shift(struct ecx_plat_data *pdata, u32 port,
|
static inline int sgpio_bit_shift(struct ecx_plat_data *pdata, u32 port,
|
||||||
u32 shift)
|
u32 shift)
|
||||||
{
|
{
|
||||||
|
@@ -141,6 +141,8 @@ static ssize_t show_mem_removable(struct device *dev,
|
|||||||
container_of(dev, struct memory_block, dev);
|
container_of(dev, struct memory_block, dev);
|
||||||
|
|
||||||
for (i = 0; i < sections_per_block; i++) {
|
for (i = 0; i < sections_per_block; i++) {
|
||||||
|
if (!present_section_nr(mem->start_section_nr + i))
|
||||||
|
continue;
|
||||||
pfn = section_nr_to_pfn(mem->start_section_nr + i);
|
pfn = section_nr_to_pfn(mem->start_section_nr + i);
|
||||||
ret &= is_mem_section_removable(pfn, PAGES_PER_SECTION);
|
ret &= is_mem_section_removable(pfn, PAGES_PER_SECTION);
|
||||||
}
|
}
|
||||||
|
@@ -332,7 +332,7 @@ regcache_rbtree_node_alloc(struct regmap *map, unsigned int reg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!rbnode->blklen) {
|
if (!rbnode->blklen) {
|
||||||
rbnode->blklen = sizeof(*rbnode);
|
rbnode->blklen = 1;
|
||||||
rbnode->base_reg = reg;
|
rbnode->base_reg = reg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -581,11 +581,15 @@ struct samsung_div_clock exynos4x12_div_clks[] __initdata = {
|
|||||||
DIV(none, "div_spi1_isp", "mout_spi1_isp", E4X12_DIV_ISP, 16, 4),
|
DIV(none, "div_spi1_isp", "mout_spi1_isp", E4X12_DIV_ISP, 16, 4),
|
||||||
DIV(none, "div_spi1_isp_pre", "div_spi1_isp", E4X12_DIV_ISP, 20, 8),
|
DIV(none, "div_spi1_isp_pre", "div_spi1_isp", E4X12_DIV_ISP, 20, 8),
|
||||||
DIV(none, "div_uart_isp", "mout_uart_isp", E4X12_DIV_ISP, 28, 4),
|
DIV(none, "div_uart_isp", "mout_uart_isp", E4X12_DIV_ISP, 28, 4),
|
||||||
DIV(div_isp0, "div_isp0", "aclk200", E4X12_DIV_ISP0, 0, 3),
|
DIV_F(div_isp0, "div_isp0", "aclk200", E4X12_DIV_ISP0, 0, 3,
|
||||||
DIV(div_isp1, "div_isp1", "aclk200", E4X12_DIV_ISP0, 4, 3),
|
CLK_GET_RATE_NOCACHE, 0),
|
||||||
|
DIV_F(div_isp1, "div_isp1", "aclk200", E4X12_DIV_ISP0, 4, 3,
|
||||||
|
CLK_GET_RATE_NOCACHE, 0),
|
||||||
DIV(none, "div_mpwm", "div_isp1", E4X12_DIV_ISP1, 0, 3),
|
DIV(none, "div_mpwm", "div_isp1", E4X12_DIV_ISP1, 0, 3),
|
||||||
DIV(div_mcuisp0, "div_mcuisp0", "aclk400_mcuisp", E4X12_DIV_ISP1, 4, 3),
|
DIV_F(div_mcuisp0, "div_mcuisp0", "aclk400_mcuisp", E4X12_DIV_ISP1,
|
||||||
DIV(div_mcuisp1, "div_mcuisp1", "div_mcuisp0", E4X12_DIV_ISP1, 8, 3),
|
4, 3, CLK_GET_RATE_NOCACHE, 0),
|
||||||
|
DIV_F(div_mcuisp1, "div_mcuisp1", "div_mcuisp0", E4X12_DIV_ISP1,
|
||||||
|
8, 3, CLK_GET_RATE_NOCACHE, 0),
|
||||||
DIV(sclk_fimg2d, "sclk_fimg2d", "mout_g2d", DIV_DMC1, 0, 4),
|
DIV(sclk_fimg2d, "sclk_fimg2d", "mout_g2d", DIV_DMC1, 0, 4),
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -863,57 +867,57 @@ struct samsung_gate_clock exynos4x12_gate_clks[] __initdata = {
|
|||||||
GATE_DA(i2s0, "samsung-i2s.0", "i2s0", "aclk100",
|
GATE_DA(i2s0, "samsung-i2s.0", "i2s0", "aclk100",
|
||||||
E4X12_GATE_IP_MAUDIO, 3, 0, 0, "iis"),
|
E4X12_GATE_IP_MAUDIO, 3, 0, 0, "iis"),
|
||||||
GATE(fimc_isp, "isp", "aclk200", E4X12_GATE_ISP0, 0,
|
GATE(fimc_isp, "isp", "aclk200", E4X12_GATE_ISP0, 0,
|
||||||
CLK_IGNORE_UNUSED, 0),
|
CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0),
|
||||||
GATE(fimc_drc, "drc", "aclk200", E4X12_GATE_ISP0, 1,
|
GATE(fimc_drc, "drc", "aclk200", E4X12_GATE_ISP0, 1,
|
||||||
CLK_IGNORE_UNUSED, 0),
|
CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0),
|
||||||
GATE(fimc_fd, "fd", "aclk200", E4X12_GATE_ISP0, 2,
|
GATE(fimc_fd, "fd", "aclk200", E4X12_GATE_ISP0, 2,
|
||||||
CLK_IGNORE_UNUSED, 0),
|
CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0),
|
||||||
GATE(fimc_lite0, "lite0", "aclk200", E4X12_GATE_ISP0, 3,
|
GATE(fimc_lite0, "lite0", "aclk200", E4X12_GATE_ISP0, 3,
|
||||||
CLK_IGNORE_UNUSED, 0),
|
CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0),
|
||||||
GATE(fimc_lite1, "lite1", "aclk200", E4X12_GATE_ISP0, 4,
|
GATE(fimc_lite1, "lite1", "aclk200", E4X12_GATE_ISP0, 4,
|
||||||
CLK_IGNORE_UNUSED, 0),
|
CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0),
|
||||||
GATE(mcuisp, "mcuisp", "aclk200", E4X12_GATE_ISP0, 5,
|
GATE(mcuisp, "mcuisp", "aclk200", E4X12_GATE_ISP0, 5,
|
||||||
CLK_IGNORE_UNUSED, 0),
|
CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0),
|
||||||
GATE(gicisp, "gicisp", "aclk200", E4X12_GATE_ISP0, 7,
|
GATE(gicisp, "gicisp", "aclk200", E4X12_GATE_ISP0, 7,
|
||||||
CLK_IGNORE_UNUSED, 0),
|
CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0),
|
||||||
GATE(smmu_isp, "smmu_isp", "aclk200", E4X12_GATE_ISP0, 8,
|
GATE(smmu_isp, "smmu_isp", "aclk200", E4X12_GATE_ISP0, 8,
|
||||||
CLK_IGNORE_UNUSED, 0),
|
CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0),
|
||||||
GATE(smmu_drc, "smmu_drc", "aclk200", E4X12_GATE_ISP0, 9,
|
GATE(smmu_drc, "smmu_drc", "aclk200", E4X12_GATE_ISP0, 9,
|
||||||
CLK_IGNORE_UNUSED, 0),
|
CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0),
|
||||||
GATE(smmu_fd, "smmu_fd", "aclk200", E4X12_GATE_ISP0, 10,
|
GATE(smmu_fd, "smmu_fd", "aclk200", E4X12_GATE_ISP0, 10,
|
||||||
CLK_IGNORE_UNUSED, 0),
|
CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0),
|
||||||
GATE(smmu_lite0, "smmu_lite0", "aclk200", E4X12_GATE_ISP0, 11,
|
GATE(smmu_lite0, "smmu_lite0", "aclk200", E4X12_GATE_ISP0, 11,
|
||||||
CLK_IGNORE_UNUSED, 0),
|
CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0),
|
||||||
GATE(smmu_lite1, "smmu_lite1", "aclk200", E4X12_GATE_ISP0, 12,
|
GATE(smmu_lite1, "smmu_lite1", "aclk200", E4X12_GATE_ISP0, 12,
|
||||||
CLK_IGNORE_UNUSED, 0),
|
CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0),
|
||||||
GATE(ppmuispmx, "ppmuispmx", "aclk200", E4X12_GATE_ISP0, 20,
|
GATE(ppmuispmx, "ppmuispmx", "aclk200", E4X12_GATE_ISP0, 20,
|
||||||
CLK_IGNORE_UNUSED, 0),
|
CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0),
|
||||||
GATE(ppmuispx, "ppmuispx", "aclk200", E4X12_GATE_ISP0, 21,
|
GATE(ppmuispx, "ppmuispx", "aclk200", E4X12_GATE_ISP0, 21,
|
||||||
CLK_IGNORE_UNUSED, 0),
|
CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0),
|
||||||
GATE(mcuctl_isp, "mcuctl_isp", "aclk200", E4X12_GATE_ISP0, 23,
|
GATE(mcuctl_isp, "mcuctl_isp", "aclk200", E4X12_GATE_ISP0, 23,
|
||||||
CLK_IGNORE_UNUSED, 0),
|
CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0),
|
||||||
GATE(mpwm_isp, "mpwm_isp", "aclk200", E4X12_GATE_ISP0, 24,
|
GATE(mpwm_isp, "mpwm_isp", "aclk200", E4X12_GATE_ISP0, 24,
|
||||||
CLK_IGNORE_UNUSED, 0),
|
CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0),
|
||||||
GATE(i2c0_isp, "i2c0_isp", "aclk200", E4X12_GATE_ISP0, 25,
|
GATE(i2c0_isp, "i2c0_isp", "aclk200", E4X12_GATE_ISP0, 25,
|
||||||
CLK_IGNORE_UNUSED, 0),
|
CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0),
|
||||||
GATE(i2c1_isp, "i2c1_isp", "aclk200", E4X12_GATE_ISP0, 26,
|
GATE(i2c1_isp, "i2c1_isp", "aclk200", E4X12_GATE_ISP0, 26,
|
||||||
CLK_IGNORE_UNUSED, 0),
|
CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0),
|
||||||
GATE(mtcadc_isp, "mtcadc_isp", "aclk200", E4X12_GATE_ISP0, 27,
|
GATE(mtcadc_isp, "mtcadc_isp", "aclk200", E4X12_GATE_ISP0, 27,
|
||||||
CLK_IGNORE_UNUSED, 0),
|
CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0),
|
||||||
GATE(pwm_isp, "pwm_isp", "aclk200", E4X12_GATE_ISP0, 28,
|
GATE(pwm_isp, "pwm_isp", "aclk200", E4X12_GATE_ISP0, 28,
|
||||||
CLK_IGNORE_UNUSED, 0),
|
CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0),
|
||||||
GATE(wdt_isp, "wdt_isp", "aclk200", E4X12_GATE_ISP0, 30,
|
GATE(wdt_isp, "wdt_isp", "aclk200", E4X12_GATE_ISP0, 30,
|
||||||
CLK_IGNORE_UNUSED, 0),
|
CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0),
|
||||||
GATE(uart_isp, "uart_isp", "aclk200", E4X12_GATE_ISP0, 31,
|
GATE(uart_isp, "uart_isp", "aclk200", E4X12_GATE_ISP0, 31,
|
||||||
CLK_IGNORE_UNUSED, 0),
|
CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0),
|
||||||
GATE(asyncaxim, "asyncaxim", "aclk200", E4X12_GATE_ISP1, 0,
|
GATE(asyncaxim, "asyncaxim", "aclk200", E4X12_GATE_ISP1, 0,
|
||||||
CLK_IGNORE_UNUSED, 0),
|
CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0),
|
||||||
GATE(smmu_ispcx, "smmu_ispcx", "aclk200", E4X12_GATE_ISP1, 4,
|
GATE(smmu_ispcx, "smmu_ispcx", "aclk200", E4X12_GATE_ISP1, 4,
|
||||||
CLK_IGNORE_UNUSED, 0),
|
CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0),
|
||||||
GATE(spi0_isp, "spi0_isp", "aclk200", E4X12_GATE_ISP1, 12,
|
GATE(spi0_isp, "spi0_isp", "aclk200", E4X12_GATE_ISP1, 12,
|
||||||
CLK_IGNORE_UNUSED, 0),
|
CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0),
|
||||||
GATE(spi1_isp, "spi1_isp", "aclk200", E4X12_GATE_ISP1, 13,
|
GATE(spi1_isp, "spi1_isp", "aclk200", E4X12_GATE_ISP1, 13,
|
||||||
CLK_IGNORE_UNUSED, 0),
|
CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0),
|
||||||
GATE(g2d, "g2d", "aclk200", GATE_IP_DMC, 23, 0, 0),
|
GATE(g2d, "g2d", "aclk200", GATE_IP_DMC, 23, 0, 0),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -71,6 +71,7 @@ static DEFINE_SPINLOCK(armpll_lock);
|
|||||||
static DEFINE_SPINLOCK(ddrpll_lock);
|
static DEFINE_SPINLOCK(ddrpll_lock);
|
||||||
static DEFINE_SPINLOCK(iopll_lock);
|
static DEFINE_SPINLOCK(iopll_lock);
|
||||||
static DEFINE_SPINLOCK(armclk_lock);
|
static DEFINE_SPINLOCK(armclk_lock);
|
||||||
|
static DEFINE_SPINLOCK(swdtclk_lock);
|
||||||
static DEFINE_SPINLOCK(ddrclk_lock);
|
static DEFINE_SPINLOCK(ddrclk_lock);
|
||||||
static DEFINE_SPINLOCK(dciclk_lock);
|
static DEFINE_SPINLOCK(dciclk_lock);
|
||||||
static DEFINE_SPINLOCK(gem0clk_lock);
|
static DEFINE_SPINLOCK(gem0clk_lock);
|
||||||
@@ -293,7 +294,7 @@ static void __init zynq_clk_setup(struct device_node *np)
|
|||||||
}
|
}
|
||||||
clks[swdt] = clk_register_mux(NULL, clk_output_name[swdt],
|
clks[swdt] = clk_register_mux(NULL, clk_output_name[swdt],
|
||||||
swdt_ext_clk_mux_parents, 2, CLK_SET_RATE_PARENT,
|
swdt_ext_clk_mux_parents, 2, CLK_SET_RATE_PARENT,
|
||||||
SLCR_SWDT_CLK_SEL, 0, 1, 0, &gem0clk_lock);
|
SLCR_SWDT_CLK_SEL, 0, 1, 0, &swdtclk_lock);
|
||||||
|
|
||||||
/* DDR clocks */
|
/* DDR clocks */
|
||||||
clk = clk_register_divider(NULL, "ddr2x_div", "ddrpll", 0,
|
clk = clk_register_divider(NULL, "ddr2x_div", "ddrpll", 0,
|
||||||
@@ -364,8 +365,9 @@ static void __init zynq_clk_setup(struct device_node *np)
|
|||||||
CLK_SET_RATE_PARENT, SLCR_GEM0_CLK_CTRL, 20, 6,
|
CLK_SET_RATE_PARENT, SLCR_GEM0_CLK_CTRL, 20, 6,
|
||||||
CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO,
|
CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO,
|
||||||
&gem0clk_lock);
|
&gem0clk_lock);
|
||||||
clk = clk_register_mux(NULL, "gem0_emio_mux", gem0_mux_parents, 2, 0,
|
clk = clk_register_mux(NULL, "gem0_emio_mux", gem0_mux_parents, 2,
|
||||||
SLCR_GEM0_CLK_CTRL, 6, 1, 0, &gem0clk_lock);
|
CLK_SET_RATE_PARENT, SLCR_GEM0_CLK_CTRL, 6, 1, 0,
|
||||||
|
&gem0clk_lock);
|
||||||
clks[gem0] = clk_register_gate(NULL, clk_output_name[gem0],
|
clks[gem0] = clk_register_gate(NULL, clk_output_name[gem0],
|
||||||
"gem0_emio_mux", CLK_SET_RATE_PARENT,
|
"gem0_emio_mux", CLK_SET_RATE_PARENT,
|
||||||
SLCR_GEM0_CLK_CTRL, 0, 0, &gem0clk_lock);
|
SLCR_GEM0_CLK_CTRL, 0, 0, &gem0clk_lock);
|
||||||
@@ -386,8 +388,9 @@ static void __init zynq_clk_setup(struct device_node *np)
|
|||||||
CLK_SET_RATE_PARENT, SLCR_GEM1_CLK_CTRL, 20, 6,
|
CLK_SET_RATE_PARENT, SLCR_GEM1_CLK_CTRL, 20, 6,
|
||||||
CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO,
|
CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO,
|
||||||
&gem1clk_lock);
|
&gem1clk_lock);
|
||||||
clk = clk_register_mux(NULL, "gem1_emio_mux", gem1_mux_parents, 2, 0,
|
clk = clk_register_mux(NULL, "gem1_emio_mux", gem1_mux_parents, 2,
|
||||||
SLCR_GEM1_CLK_CTRL, 6, 1, 0, &gem1clk_lock);
|
CLK_SET_RATE_PARENT, SLCR_GEM1_CLK_CTRL, 6, 1, 0,
|
||||||
|
&gem1clk_lock);
|
||||||
clks[gem1] = clk_register_gate(NULL, clk_output_name[gem1],
|
clks[gem1] = clk_register_gate(NULL, clk_output_name[gem1],
|
||||||
"gem1_emio_mux", CLK_SET_RATE_PARENT,
|
"gem1_emio_mux", CLK_SET_RATE_PARENT,
|
||||||
SLCR_GEM1_CLK_CTRL, 0, 0, &gem1clk_lock);
|
SLCR_GEM1_CLK_CTRL, 0, 0, &gem1clk_lock);
|
||||||
|
@@ -194,7 +194,7 @@ config SIRF_DMA
|
|||||||
Enable support for the CSR SiRFprimaII DMA engine.
|
Enable support for the CSR SiRFprimaII DMA engine.
|
||||||
|
|
||||||
config TI_EDMA
|
config TI_EDMA
|
||||||
tristate "TI EDMA support"
|
bool "TI EDMA support"
|
||||||
depends on ARCH_DAVINCI || ARCH_OMAP
|
depends on ARCH_DAVINCI || ARCH_OMAP
|
||||||
select DMA_ENGINE
|
select DMA_ENGINE
|
||||||
select DMA_VIRTUAL_CHANNELS
|
select DMA_VIRTUAL_CHANNELS
|
||||||
|
@@ -500,7 +500,8 @@ static bool psb_intel_sdvo_read_response(struct psb_intel_sdvo *psb_intel_sdvo,
|
|||||||
&status))
|
&status))
|
||||||
goto log_fail;
|
goto log_fail;
|
||||||
|
|
||||||
while (status == SDVO_CMD_STATUS_PENDING && retry--) {
|
while ((status == SDVO_CMD_STATUS_PENDING ||
|
||||||
|
status == SDVO_CMD_STATUS_TARGET_NOT_SPECIFIED) && retry--) {
|
||||||
udelay(15);
|
udelay(15);
|
||||||
if (!psb_intel_sdvo_read_byte(psb_intel_sdvo,
|
if (!psb_intel_sdvo_read_byte(psb_intel_sdvo,
|
||||||
SDVO_I2C_CMD_STATUS,
|
SDVO_I2C_CMD_STATUS,
|
||||||
|
@@ -85,9 +85,17 @@ static void i915_gem_unmap_dma_buf(struct dma_buf_attachment *attachment,
|
|||||||
struct sg_table *sg,
|
struct sg_table *sg,
|
||||||
enum dma_data_direction dir)
|
enum dma_data_direction dir)
|
||||||
{
|
{
|
||||||
|
struct drm_i915_gem_object *obj = attachment->dmabuf->priv;
|
||||||
|
|
||||||
|
mutex_lock(&obj->base.dev->struct_mutex);
|
||||||
|
|
||||||
dma_unmap_sg(attachment->dev, sg->sgl, sg->nents, dir);
|
dma_unmap_sg(attachment->dev, sg->sgl, sg->nents, dir);
|
||||||
sg_free_table(sg);
|
sg_free_table(sg);
|
||||||
kfree(sg);
|
kfree(sg);
|
||||||
|
|
||||||
|
i915_gem_object_unpin_pages(obj);
|
||||||
|
|
||||||
|
mutex_unlock(&obj->base.dev->struct_mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void i915_gem_dmabuf_release(struct dma_buf *dma_buf)
|
static void i915_gem_dmabuf_release(struct dma_buf *dma_buf)
|
||||||
|
@@ -752,6 +752,8 @@
|
|||||||
will not assert AGPBUSY# and will only
|
will not assert AGPBUSY# and will only
|
||||||
be delivered when out of C3. */
|
be delivered when out of C3. */
|
||||||
#define INSTPM_FORCE_ORDERING (1<<7) /* GEN6+ */
|
#define INSTPM_FORCE_ORDERING (1<<7) /* GEN6+ */
|
||||||
|
#define INSTPM_TLB_INVALIDATE (1<<9)
|
||||||
|
#define INSTPM_SYNC_FLUSH (1<<5)
|
||||||
#define ACTHD 0x020c8
|
#define ACTHD 0x020c8
|
||||||
#define FW_BLC 0x020d8
|
#define FW_BLC 0x020d8
|
||||||
#define FW_BLC2 0x020dc
|
#define FW_BLC2 0x020dc
|
||||||
@@ -4438,7 +4440,7 @@
|
|||||||
#define EDP_LINK_TRAIN_600MV_0DB_IVB (0x30 <<22)
|
#define EDP_LINK_TRAIN_600MV_0DB_IVB (0x30 <<22)
|
||||||
#define EDP_LINK_TRAIN_600MV_3_5DB_IVB (0x36 <<22)
|
#define EDP_LINK_TRAIN_600MV_3_5DB_IVB (0x36 <<22)
|
||||||
#define EDP_LINK_TRAIN_800MV_0DB_IVB (0x38 <<22)
|
#define EDP_LINK_TRAIN_800MV_0DB_IVB (0x38 <<22)
|
||||||
#define EDP_LINK_TRAIN_800MV_3_5DB_IVB (0x33 <<22)
|
#define EDP_LINK_TRAIN_800MV_3_5DB_IVB (0x3e <<22)
|
||||||
|
|
||||||
/* legacy values */
|
/* legacy values */
|
||||||
#define EDP_LINK_TRAIN_500MV_0DB_IVB (0x00 <<22)
|
#define EDP_LINK_TRAIN_500MV_0DB_IVB (0x00 <<22)
|
||||||
|
@@ -10042,6 +10042,8 @@ struct intel_display_error_state {
|
|||||||
|
|
||||||
u32 power_well_driver;
|
u32 power_well_driver;
|
||||||
|
|
||||||
|
int num_transcoders;
|
||||||
|
|
||||||
struct intel_cursor_error_state {
|
struct intel_cursor_error_state {
|
||||||
u32 control;
|
u32 control;
|
||||||
u32 position;
|
u32 position;
|
||||||
@@ -10050,16 +10052,7 @@ struct intel_display_error_state {
|
|||||||
} cursor[I915_MAX_PIPES];
|
} cursor[I915_MAX_PIPES];
|
||||||
|
|
||||||
struct intel_pipe_error_state {
|
struct intel_pipe_error_state {
|
||||||
enum transcoder cpu_transcoder;
|
|
||||||
u32 conf;
|
|
||||||
u32 source;
|
u32 source;
|
||||||
|
|
||||||
u32 htotal;
|
|
||||||
u32 hblank;
|
|
||||||
u32 hsync;
|
|
||||||
u32 vtotal;
|
|
||||||
u32 vblank;
|
|
||||||
u32 vsync;
|
|
||||||
} pipe[I915_MAX_PIPES];
|
} pipe[I915_MAX_PIPES];
|
||||||
|
|
||||||
struct intel_plane_error_state {
|
struct intel_plane_error_state {
|
||||||
@@ -10071,6 +10064,19 @@ struct intel_display_error_state {
|
|||||||
u32 surface;
|
u32 surface;
|
||||||
u32 tile_offset;
|
u32 tile_offset;
|
||||||
} plane[I915_MAX_PIPES];
|
} plane[I915_MAX_PIPES];
|
||||||
|
|
||||||
|
struct intel_transcoder_error_state {
|
||||||
|
enum transcoder cpu_transcoder;
|
||||||
|
|
||||||
|
u32 conf;
|
||||||
|
|
||||||
|
u32 htotal;
|
||||||
|
u32 hblank;
|
||||||
|
u32 hsync;
|
||||||
|
u32 vtotal;
|
||||||
|
u32 vblank;
|
||||||
|
u32 vsync;
|
||||||
|
} transcoder[4];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct intel_display_error_state *
|
struct intel_display_error_state *
|
||||||
@@ -10078,9 +10084,17 @@ intel_display_capture_error_state(struct drm_device *dev)
|
|||||||
{
|
{
|
||||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||||
struct intel_display_error_state *error;
|
struct intel_display_error_state *error;
|
||||||
enum transcoder cpu_transcoder;
|
int transcoders[] = {
|
||||||
|
TRANSCODER_A,
|
||||||
|
TRANSCODER_B,
|
||||||
|
TRANSCODER_C,
|
||||||
|
TRANSCODER_EDP,
|
||||||
|
};
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
if (INTEL_INFO(dev)->num_pipes == 0)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
error = kmalloc(sizeof(*error), GFP_ATOMIC);
|
error = kmalloc(sizeof(*error), GFP_ATOMIC);
|
||||||
if (error == NULL)
|
if (error == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -10089,9 +10103,6 @@ intel_display_capture_error_state(struct drm_device *dev)
|
|||||||
error->power_well_driver = I915_READ(HSW_PWR_WELL_DRIVER);
|
error->power_well_driver = I915_READ(HSW_PWR_WELL_DRIVER);
|
||||||
|
|
||||||
for_each_pipe(i) {
|
for_each_pipe(i) {
|
||||||
cpu_transcoder = intel_pipe_to_cpu_transcoder(dev_priv, i);
|
|
||||||
error->pipe[i].cpu_transcoder = cpu_transcoder;
|
|
||||||
|
|
||||||
if (INTEL_INFO(dev)->gen <= 6 || IS_VALLEYVIEW(dev)) {
|
if (INTEL_INFO(dev)->gen <= 6 || IS_VALLEYVIEW(dev)) {
|
||||||
error->cursor[i].control = I915_READ(CURCNTR(i));
|
error->cursor[i].control = I915_READ(CURCNTR(i));
|
||||||
error->cursor[i].position = I915_READ(CURPOS(i));
|
error->cursor[i].position = I915_READ(CURPOS(i));
|
||||||
@@ -10115,14 +10126,25 @@ intel_display_capture_error_state(struct drm_device *dev)
|
|||||||
error->plane[i].tile_offset = I915_READ(DSPTILEOFF(i));
|
error->plane[i].tile_offset = I915_READ(DSPTILEOFF(i));
|
||||||
}
|
}
|
||||||
|
|
||||||
error->pipe[i].conf = I915_READ(PIPECONF(cpu_transcoder));
|
|
||||||
error->pipe[i].source = I915_READ(PIPESRC(i));
|
error->pipe[i].source = I915_READ(PIPESRC(i));
|
||||||
error->pipe[i].htotal = I915_READ(HTOTAL(cpu_transcoder));
|
}
|
||||||
error->pipe[i].hblank = I915_READ(HBLANK(cpu_transcoder));
|
|
||||||
error->pipe[i].hsync = I915_READ(HSYNC(cpu_transcoder));
|
error->num_transcoders = INTEL_INFO(dev)->num_pipes;
|
||||||
error->pipe[i].vtotal = I915_READ(VTOTAL(cpu_transcoder));
|
if (HAS_DDI(dev_priv->dev))
|
||||||
error->pipe[i].vblank = I915_READ(VBLANK(cpu_transcoder));
|
error->num_transcoders++; /* Account for eDP. */
|
||||||
error->pipe[i].vsync = I915_READ(VSYNC(cpu_transcoder));
|
|
||||||
|
for (i = 0; i < error->num_transcoders; i++) {
|
||||||
|
enum transcoder cpu_transcoder = transcoders[i];
|
||||||
|
|
||||||
|
error->transcoder[i].cpu_transcoder = cpu_transcoder;
|
||||||
|
|
||||||
|
error->transcoder[i].conf = I915_READ(PIPECONF(cpu_transcoder));
|
||||||
|
error->transcoder[i].htotal = I915_READ(HTOTAL(cpu_transcoder));
|
||||||
|
error->transcoder[i].hblank = I915_READ(HBLANK(cpu_transcoder));
|
||||||
|
error->transcoder[i].hsync = I915_READ(HSYNC(cpu_transcoder));
|
||||||
|
error->transcoder[i].vtotal = I915_READ(VTOTAL(cpu_transcoder));
|
||||||
|
error->transcoder[i].vblank = I915_READ(VBLANK(cpu_transcoder));
|
||||||
|
error->transcoder[i].vsync = I915_READ(VSYNC(cpu_transcoder));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* In the code above we read the registers without checking if the power
|
/* In the code above we read the registers without checking if the power
|
||||||
@@ -10144,22 +10166,16 @@ intel_display_print_error_state(struct drm_i915_error_state_buf *m,
|
|||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
if (!error)
|
||||||
|
return;
|
||||||
|
|
||||||
err_printf(m, "Num Pipes: %d\n", INTEL_INFO(dev)->num_pipes);
|
err_printf(m, "Num Pipes: %d\n", INTEL_INFO(dev)->num_pipes);
|
||||||
if (HAS_POWER_WELL(dev))
|
if (HAS_POWER_WELL(dev))
|
||||||
err_printf(m, "PWR_WELL_CTL2: %08x\n",
|
err_printf(m, "PWR_WELL_CTL2: %08x\n",
|
||||||
error->power_well_driver);
|
error->power_well_driver);
|
||||||
for_each_pipe(i) {
|
for_each_pipe(i) {
|
||||||
err_printf(m, "Pipe [%d]:\n", i);
|
err_printf(m, "Pipe [%d]:\n", i);
|
||||||
err_printf(m, " CPU transcoder: %c\n",
|
|
||||||
transcoder_name(error->pipe[i].cpu_transcoder));
|
|
||||||
err_printf(m, " CONF: %08x\n", error->pipe[i].conf);
|
|
||||||
err_printf(m, " SRC: %08x\n", error->pipe[i].source);
|
err_printf(m, " SRC: %08x\n", error->pipe[i].source);
|
||||||
err_printf(m, " HTOTAL: %08x\n", error->pipe[i].htotal);
|
|
||||||
err_printf(m, " HBLANK: %08x\n", error->pipe[i].hblank);
|
|
||||||
err_printf(m, " HSYNC: %08x\n", error->pipe[i].hsync);
|
|
||||||
err_printf(m, " VTOTAL: %08x\n", error->pipe[i].vtotal);
|
|
||||||
err_printf(m, " VBLANK: %08x\n", error->pipe[i].vblank);
|
|
||||||
err_printf(m, " VSYNC: %08x\n", error->pipe[i].vsync);
|
|
||||||
|
|
||||||
err_printf(m, "Plane [%d]:\n", i);
|
err_printf(m, "Plane [%d]:\n", i);
|
||||||
err_printf(m, " CNTR: %08x\n", error->plane[i].control);
|
err_printf(m, " CNTR: %08x\n", error->plane[i].control);
|
||||||
@@ -10180,5 +10196,17 @@ intel_display_print_error_state(struct drm_i915_error_state_buf *m,
|
|||||||
err_printf(m, " POS: %08x\n", error->cursor[i].position);
|
err_printf(m, " POS: %08x\n", error->cursor[i].position);
|
||||||
err_printf(m, " BASE: %08x\n", error->cursor[i].base);
|
err_printf(m, " BASE: %08x\n", error->cursor[i].base);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < error->num_transcoders; i++) {
|
||||||
|
err_printf(m, " CPU transcoder: %c\n",
|
||||||
|
transcoder_name(error->transcoder[i].cpu_transcoder));
|
||||||
|
err_printf(m, " CONF: %08x\n", error->transcoder[i].conf);
|
||||||
|
err_printf(m, " HTOTAL: %08x\n", error->transcoder[i].htotal);
|
||||||
|
err_printf(m, " HBLANK: %08x\n", error->transcoder[i].hblank);
|
||||||
|
err_printf(m, " HSYNC: %08x\n", error->transcoder[i].hsync);
|
||||||
|
err_printf(m, " VTOTAL: %08x\n", error->transcoder[i].vtotal);
|
||||||
|
err_printf(m, " VBLANK: %08x\n", error->transcoder[i].vblank);
|
||||||
|
err_printf(m, " VSYNC: %08x\n", error->transcoder[i].vsync);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@@ -968,6 +968,18 @@ void intel_ring_setup_status_page(struct intel_ring_buffer *ring)
|
|||||||
|
|
||||||
I915_WRITE(mmio, (u32)ring->status_page.gfx_addr);
|
I915_WRITE(mmio, (u32)ring->status_page.gfx_addr);
|
||||||
POSTING_READ(mmio);
|
POSTING_READ(mmio);
|
||||||
|
|
||||||
|
/* Flush the TLB for this page */
|
||||||
|
if (INTEL_INFO(dev)->gen >= 6) {
|
||||||
|
u32 reg = RING_INSTPM(ring->mmio_base);
|
||||||
|
I915_WRITE(reg,
|
||||||
|
_MASKED_BIT_ENABLE(INSTPM_TLB_INVALIDATE |
|
||||||
|
INSTPM_SYNC_FLUSH));
|
||||||
|
if (wait_for((I915_READ(reg) & INSTPM_SYNC_FLUSH) == 0,
|
||||||
|
1000))
|
||||||
|
DRM_ERROR("%s: wait for SyncFlush to complete for TLB invalidation timed out\n",
|
||||||
|
ring->name);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
@@ -98,6 +98,8 @@ nouveau_mm_head(struct nouveau_mm *mm, u8 type, u32 size_max, u32 size_min,
|
|||||||
u32 splitoff;
|
u32 splitoff;
|
||||||
u32 s, e;
|
u32 s, e;
|
||||||
|
|
||||||
|
BUG_ON(!type);
|
||||||
|
|
||||||
list_for_each_entry(this, &mm->free, fl_entry) {
|
list_for_each_entry(this, &mm->free, fl_entry) {
|
||||||
e = this->offset + this->length;
|
e = this->offset + this->length;
|
||||||
s = this->offset;
|
s = this->offset;
|
||||||
@@ -162,6 +164,8 @@ nouveau_mm_tail(struct nouveau_mm *mm, u8 type, u32 size_max, u32 size_min,
|
|||||||
struct nouveau_mm_node *prev, *this, *next;
|
struct nouveau_mm_node *prev, *this, *next;
|
||||||
u32 mask = align - 1;
|
u32 mask = align - 1;
|
||||||
|
|
||||||
|
BUG_ON(!type);
|
||||||
|
|
||||||
list_for_each_entry_reverse(this, &mm->free, fl_entry) {
|
list_for_each_entry_reverse(this, &mm->free, fl_entry) {
|
||||||
u32 e = this->offset + this->length;
|
u32 e = this->offset + this->length;
|
||||||
u32 s = this->offset;
|
u32 s = this->offset;
|
||||||
|
@@ -20,8 +20,8 @@ nouveau_mc(void *obj)
|
|||||||
return (void *)nv_device(obj)->subdev[NVDEV_SUBDEV_MC];
|
return (void *)nv_device(obj)->subdev[NVDEV_SUBDEV_MC];
|
||||||
}
|
}
|
||||||
|
|
||||||
#define nouveau_mc_create(p,e,o,d) \
|
#define nouveau_mc_create(p,e,o,m,d) \
|
||||||
nouveau_mc_create_((p), (e), (o), sizeof(**d), (void **)d)
|
nouveau_mc_create_((p), (e), (o), (m), sizeof(**d), (void **)d)
|
||||||
#define nouveau_mc_destroy(p) ({ \
|
#define nouveau_mc_destroy(p) ({ \
|
||||||
struct nouveau_mc *pmc = (p); _nouveau_mc_dtor(nv_object(pmc)); \
|
struct nouveau_mc *pmc = (p); _nouveau_mc_dtor(nv_object(pmc)); \
|
||||||
})
|
})
|
||||||
@@ -33,7 +33,8 @@ nouveau_mc(void *obj)
|
|||||||
})
|
})
|
||||||
|
|
||||||
int nouveau_mc_create_(struct nouveau_object *, struct nouveau_object *,
|
int nouveau_mc_create_(struct nouveau_object *, struct nouveau_object *,
|
||||||
struct nouveau_oclass *, int, void **);
|
struct nouveau_oclass *, const struct nouveau_mc_intr *,
|
||||||
|
int, void **);
|
||||||
void _nouveau_mc_dtor(struct nouveau_object *);
|
void _nouveau_mc_dtor(struct nouveau_object *);
|
||||||
int _nouveau_mc_init(struct nouveau_object *);
|
int _nouveau_mc_init(struct nouveau_object *);
|
||||||
int _nouveau_mc_fini(struct nouveau_object *, bool);
|
int _nouveau_mc_fini(struct nouveau_object *, bool);
|
||||||
|
@@ -40,15 +40,15 @@ nv49_ram_create(struct nouveau_object *parent, struct nouveau_object *engine,
|
|||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
switch (pfb914 & 0x00000003) {
|
switch (pfb914 & 0x00000003) {
|
||||||
case 0x00000000: pfb->ram->type = NV_MEM_TYPE_DDR1; break;
|
case 0x00000000: ram->type = NV_MEM_TYPE_DDR1; break;
|
||||||
case 0x00000001: pfb->ram->type = NV_MEM_TYPE_DDR2; break;
|
case 0x00000001: ram->type = NV_MEM_TYPE_DDR2; break;
|
||||||
case 0x00000002: pfb->ram->type = NV_MEM_TYPE_GDDR3; break;
|
case 0x00000002: ram->type = NV_MEM_TYPE_GDDR3; break;
|
||||||
case 0x00000003: break;
|
case 0x00000003: break;
|
||||||
}
|
}
|
||||||
|
|
||||||
pfb->ram->size = nv_rd32(pfb, 0x10020c) & 0xff000000;
|
ram->size = nv_rd32(pfb, 0x10020c) & 0xff000000;
|
||||||
pfb->ram->parts = (nv_rd32(pfb, 0x100200) & 0x00000003) + 1;
|
ram->parts = (nv_rd32(pfb, 0x100200) & 0x00000003) + 1;
|
||||||
pfb->ram->tags = nv_rd32(pfb, 0x100320);
|
ram->tags = nv_rd32(pfb, 0x100320);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -38,8 +38,8 @@ nv4e_ram_create(struct nouveau_object *parent, struct nouveau_object *engine,
|
|||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
pfb->ram->size = nv_rd32(pfb, 0x10020c) & 0xff000000;
|
ram->size = nv_rd32(pfb, 0x10020c) & 0xff000000;
|
||||||
pfb->ram->type = NV_MEM_TYPE_STOLEN;
|
ram->type = NV_MEM_TYPE_STOLEN;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -30,8 +30,9 @@ struct nvc0_ltcg_priv {
|
|||||||
struct nouveau_ltcg base;
|
struct nouveau_ltcg base;
|
||||||
u32 part_nr;
|
u32 part_nr;
|
||||||
u32 subp_nr;
|
u32 subp_nr;
|
||||||
struct nouveau_mm tags;
|
|
||||||
u32 num_tags;
|
u32 num_tags;
|
||||||
|
u32 tag_base;
|
||||||
|
struct nouveau_mm tags;
|
||||||
struct nouveau_mm_node *tag_ram;
|
struct nouveau_mm_node *tag_ram;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -117,10 +118,6 @@ nvc0_ltcg_init_tag_ram(struct nouveau_fb *pfb, struct nvc0_ltcg_priv *priv)
|
|||||||
u32 tag_size, tag_margin, tag_align;
|
u32 tag_size, tag_margin, tag_align;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
nv_wr32(priv, 0x17e8d8, priv->part_nr);
|
|
||||||
if (nv_device(pfb)->card_type >= NV_E0)
|
|
||||||
nv_wr32(priv, 0x17e000, priv->part_nr);
|
|
||||||
|
|
||||||
/* tags for 1/4 of VRAM should be enough (8192/4 per GiB of VRAM) */
|
/* tags for 1/4 of VRAM should be enough (8192/4 per GiB of VRAM) */
|
||||||
priv->num_tags = (pfb->ram->size >> 17) / 4;
|
priv->num_tags = (pfb->ram->size >> 17) / 4;
|
||||||
if (priv->num_tags > (1 << 17))
|
if (priv->num_tags > (1 << 17))
|
||||||
@@ -142,7 +139,7 @@ nvc0_ltcg_init_tag_ram(struct nouveau_fb *pfb, struct nvc0_ltcg_priv *priv)
|
|||||||
tag_size += tag_align;
|
tag_size += tag_align;
|
||||||
tag_size = (tag_size + 0xfff) >> 12; /* round up */
|
tag_size = (tag_size + 0xfff) >> 12; /* round up */
|
||||||
|
|
||||||
ret = nouveau_mm_tail(&pfb->vram, 0, tag_size, tag_size, 1,
|
ret = nouveau_mm_tail(&pfb->vram, 1, tag_size, tag_size, 1,
|
||||||
&priv->tag_ram);
|
&priv->tag_ram);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
priv->num_tags = 0;
|
priv->num_tags = 0;
|
||||||
@@ -152,7 +149,7 @@ nvc0_ltcg_init_tag_ram(struct nouveau_fb *pfb, struct nvc0_ltcg_priv *priv)
|
|||||||
tag_base += tag_align - 1;
|
tag_base += tag_align - 1;
|
||||||
ret = do_div(tag_base, tag_align);
|
ret = do_div(tag_base, tag_align);
|
||||||
|
|
||||||
nv_wr32(priv, 0x17e8d4, tag_base);
|
priv->tag_base = tag_base;
|
||||||
}
|
}
|
||||||
ret = nouveau_mm_init(&priv->tags, 0, priv->num_tags, 1);
|
ret = nouveau_mm_init(&priv->tags, 0, priv->num_tags, 1);
|
||||||
|
|
||||||
@@ -182,8 +179,6 @@ nvc0_ltcg_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
|
|||||||
}
|
}
|
||||||
priv->subp_nr = nv_rd32(priv, 0x17e8dc) >> 28;
|
priv->subp_nr = nv_rd32(priv, 0x17e8dc) >> 28;
|
||||||
|
|
||||||
nv_mask(priv, 0x17e820, 0x00100000, 0x00000000); /* INTR_EN &= ~0x10 */
|
|
||||||
|
|
||||||
ret = nvc0_ltcg_init_tag_ram(pfb, priv);
|
ret = nvc0_ltcg_init_tag_ram(pfb, priv);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
@@ -209,13 +204,32 @@ nvc0_ltcg_dtor(struct nouveau_object *object)
|
|||||||
nouveau_ltcg_destroy(ltcg);
|
nouveau_ltcg_destroy(ltcg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
nvc0_ltcg_init(struct nouveau_object *object)
|
||||||
|
{
|
||||||
|
struct nouveau_ltcg *ltcg = (struct nouveau_ltcg *)object;
|
||||||
|
struct nvc0_ltcg_priv *priv = (struct nvc0_ltcg_priv *)ltcg;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = nouveau_ltcg_init(ltcg);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
nv_mask(priv, 0x17e820, 0x00100000, 0x00000000); /* INTR_EN &= ~0x10 */
|
||||||
|
nv_wr32(priv, 0x17e8d8, priv->part_nr);
|
||||||
|
if (nv_device(ltcg)->card_type >= NV_E0)
|
||||||
|
nv_wr32(priv, 0x17e000, priv->part_nr);
|
||||||
|
nv_wr32(priv, 0x17e8d4, priv->tag_base);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
struct nouveau_oclass
|
struct nouveau_oclass
|
||||||
nvc0_ltcg_oclass = {
|
nvc0_ltcg_oclass = {
|
||||||
.handle = NV_SUBDEV(LTCG, 0xc0),
|
.handle = NV_SUBDEV(LTCG, 0xc0),
|
||||||
.ofuncs = &(struct nouveau_ofuncs) {
|
.ofuncs = &(struct nouveau_ofuncs) {
|
||||||
.ctor = nvc0_ltcg_ctor,
|
.ctor = nvc0_ltcg_ctor,
|
||||||
.dtor = nvc0_ltcg_dtor,
|
.dtor = nvc0_ltcg_dtor,
|
||||||
.init = _nouveau_ltcg_init,
|
.init = nvc0_ltcg_init,
|
||||||
.fini = _nouveau_ltcg_fini,
|
.fini = _nouveau_ltcg_fini,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@@ -80,7 +80,9 @@ _nouveau_mc_dtor(struct nouveau_object *object)
|
|||||||
|
|
||||||
int
|
int
|
||||||
nouveau_mc_create_(struct nouveau_object *parent, struct nouveau_object *engine,
|
nouveau_mc_create_(struct nouveau_object *parent, struct nouveau_object *engine,
|
||||||
struct nouveau_oclass *oclass, int length, void **pobject)
|
struct nouveau_oclass *oclass,
|
||||||
|
const struct nouveau_mc_intr *intr_map,
|
||||||
|
int length, void **pobject)
|
||||||
{
|
{
|
||||||
struct nouveau_device *device = nv_device(parent);
|
struct nouveau_device *device = nv_device(parent);
|
||||||
struct nouveau_mc *pmc;
|
struct nouveau_mc *pmc;
|
||||||
@@ -92,6 +94,8 @@ nouveau_mc_create_(struct nouveau_object *parent, struct nouveau_object *engine,
|
|||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
pmc->intr_map = intr_map;
|
||||||
|
|
||||||
ret = request_irq(device->pdev->irq, nouveau_mc_intr,
|
ret = request_irq(device->pdev->irq, nouveau_mc_intr,
|
||||||
IRQF_SHARED, "nouveau", pmc);
|
IRQF_SHARED, "nouveau", pmc);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
|
@@ -50,12 +50,11 @@ nv04_mc_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
|
|||||||
struct nv04_mc_priv *priv;
|
struct nv04_mc_priv *priv;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = nouveau_mc_create(parent, engine, oclass, &priv);
|
ret = nouveau_mc_create(parent, engine, oclass, nv04_mc_intr, &priv);
|
||||||
*pobject = nv_object(priv);
|
*pobject = nv_object(priv);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
priv->base.intr_map = nv04_mc_intr;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -36,12 +36,11 @@ nv44_mc_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
|
|||||||
struct nv44_mc_priv *priv;
|
struct nv44_mc_priv *priv;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = nouveau_mc_create(parent, engine, oclass, &priv);
|
ret = nouveau_mc_create(parent, engine, oclass, nv04_mc_intr, &priv);
|
||||||
*pobject = nv_object(priv);
|
*pobject = nv_object(priv);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
priv->base.intr_map = nv04_mc_intr;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -53,12 +53,11 @@ nv50_mc_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
|
|||||||
struct nv50_mc_priv *priv;
|
struct nv50_mc_priv *priv;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = nouveau_mc_create(parent, engine, oclass, &priv);
|
ret = nouveau_mc_create(parent, engine, oclass, nv50_mc_intr, &priv);
|
||||||
*pobject = nv_object(priv);
|
*pobject = nv_object(priv);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
priv->base.intr_map = nv50_mc_intr;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -54,12 +54,11 @@ nv98_mc_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
|
|||||||
struct nv98_mc_priv *priv;
|
struct nv98_mc_priv *priv;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = nouveau_mc_create(parent, engine, oclass, &priv);
|
ret = nouveau_mc_create(parent, engine, oclass, nv98_mc_intr, &priv);
|
||||||
*pobject = nv_object(priv);
|
*pobject = nv_object(priv);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
priv->base.intr_map = nv98_mc_intr;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -57,12 +57,11 @@ nvc0_mc_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
|
|||||||
struct nvc0_mc_priv *priv;
|
struct nvc0_mc_priv *priv;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = nouveau_mc_create(parent, engine, oclass, &priv);
|
ret = nouveau_mc_create(parent, engine, oclass, nvc0_mc_intr, &priv);
|
||||||
*pobject = nv_object(priv);
|
*pobject = nv_object(priv);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
priv->base.intr_map = nvc0_mc_intr;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -606,6 +606,24 @@ nv_crtc_mode_set_regs(struct drm_crtc *crtc, struct drm_display_mode * mode)
|
|||||||
regp->ramdac_a34 = 0x1;
|
regp->ramdac_a34 = 0x1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
nv_crtc_swap_fbs(struct drm_crtc *crtc, struct drm_framebuffer *old_fb)
|
||||||
|
{
|
||||||
|
struct nv04_display *disp = nv04_display(crtc->dev);
|
||||||
|
struct nouveau_framebuffer *nvfb = nouveau_framebuffer(crtc->fb);
|
||||||
|
struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = nouveau_bo_pin(nvfb->nvbo, TTM_PL_FLAG_VRAM);
|
||||||
|
if (ret == 0) {
|
||||||
|
if (disp->image[nv_crtc->index])
|
||||||
|
nouveau_bo_unpin(disp->image[nv_crtc->index]);
|
||||||
|
nouveau_bo_ref(nvfb->nvbo, &disp->image[nv_crtc->index]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets up registers for the given mode/adjusted_mode pair.
|
* Sets up registers for the given mode/adjusted_mode pair.
|
||||||
*
|
*
|
||||||
@@ -622,10 +640,15 @@ nv_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode,
|
|||||||
struct drm_device *dev = crtc->dev;
|
struct drm_device *dev = crtc->dev;
|
||||||
struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
|
struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
|
||||||
struct nouveau_drm *drm = nouveau_drm(dev);
|
struct nouveau_drm *drm = nouveau_drm(dev);
|
||||||
|
int ret;
|
||||||
|
|
||||||
NV_DEBUG(drm, "CTRC mode on CRTC %d:\n", nv_crtc->index);
|
NV_DEBUG(drm, "CTRC mode on CRTC %d:\n", nv_crtc->index);
|
||||||
drm_mode_debug_printmodeline(adjusted_mode);
|
drm_mode_debug_printmodeline(adjusted_mode);
|
||||||
|
|
||||||
|
ret = nv_crtc_swap_fbs(crtc, old_fb);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
/* unlock must come after turning off FP_TG_CONTROL in output_prepare */
|
/* unlock must come after turning off FP_TG_CONTROL in output_prepare */
|
||||||
nv_lock_vga_crtc_shadow(dev, nv_crtc->index, -1);
|
nv_lock_vga_crtc_shadow(dev, nv_crtc->index, -1);
|
||||||
|
|
||||||
@@ -722,6 +745,7 @@ static void nv_crtc_commit(struct drm_crtc *crtc)
|
|||||||
|
|
||||||
static void nv_crtc_destroy(struct drm_crtc *crtc)
|
static void nv_crtc_destroy(struct drm_crtc *crtc)
|
||||||
{
|
{
|
||||||
|
struct nv04_display *disp = nv04_display(crtc->dev);
|
||||||
struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
|
struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
|
||||||
|
|
||||||
if (!nv_crtc)
|
if (!nv_crtc)
|
||||||
@@ -729,6 +753,10 @@ static void nv_crtc_destroy(struct drm_crtc *crtc)
|
|||||||
|
|
||||||
drm_crtc_cleanup(crtc);
|
drm_crtc_cleanup(crtc);
|
||||||
|
|
||||||
|
if (disp->image[nv_crtc->index])
|
||||||
|
nouveau_bo_unpin(disp->image[nv_crtc->index]);
|
||||||
|
nouveau_bo_ref(NULL, &disp->image[nv_crtc->index]);
|
||||||
|
|
||||||
nouveau_bo_unmap(nv_crtc->cursor.nvbo);
|
nouveau_bo_unmap(nv_crtc->cursor.nvbo);
|
||||||
nouveau_bo_unpin(nv_crtc->cursor.nvbo);
|
nouveau_bo_unpin(nv_crtc->cursor.nvbo);
|
||||||
nouveau_bo_ref(NULL, &nv_crtc->cursor.nvbo);
|
nouveau_bo_ref(NULL, &nv_crtc->cursor.nvbo);
|
||||||
@@ -753,6 +781,16 @@ nv_crtc_gamma_load(struct drm_crtc *crtc)
|
|||||||
nouveau_hw_load_state_palette(dev, nv_crtc->index, &nv04_display(dev)->mode_reg);
|
nouveau_hw_load_state_palette(dev, nv_crtc->index, &nv04_display(dev)->mode_reg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
nv_crtc_disable(struct drm_crtc *crtc)
|
||||||
|
{
|
||||||
|
struct nv04_display *disp = nv04_display(crtc->dev);
|
||||||
|
struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
|
||||||
|
if (disp->image[nv_crtc->index])
|
||||||
|
nouveau_bo_unpin(disp->image[nv_crtc->index]);
|
||||||
|
nouveau_bo_ref(NULL, &disp->image[nv_crtc->index]);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
nv_crtc_gamma_set(struct drm_crtc *crtc, u16 *r, u16 *g, u16 *b, uint32_t start,
|
nv_crtc_gamma_set(struct drm_crtc *crtc, u16 *r, u16 *g, u16 *b, uint32_t start,
|
||||||
uint32_t size)
|
uint32_t size)
|
||||||
@@ -791,7 +829,6 @@ nv04_crtc_do_mode_set_base(struct drm_crtc *crtc,
|
|||||||
struct drm_framebuffer *drm_fb;
|
struct drm_framebuffer *drm_fb;
|
||||||
struct nouveau_framebuffer *fb;
|
struct nouveau_framebuffer *fb;
|
||||||
int arb_burst, arb_lwm;
|
int arb_burst, arb_lwm;
|
||||||
int ret;
|
|
||||||
|
|
||||||
NV_DEBUG(drm, "index %d\n", nv_crtc->index);
|
NV_DEBUG(drm, "index %d\n", nv_crtc->index);
|
||||||
|
|
||||||
@@ -801,10 +838,8 @@ nv04_crtc_do_mode_set_base(struct drm_crtc *crtc,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* If atomic, we want to switch to the fb we were passed, so
|
/* If atomic, we want to switch to the fb we were passed, so
|
||||||
* now we update pointers to do that. (We don't pin; just
|
* now we update pointers to do that.
|
||||||
* assume we're already pinned and update the base address.)
|
|
||||||
*/
|
*/
|
||||||
if (atomic) {
|
if (atomic) {
|
||||||
drm_fb = passed_fb;
|
drm_fb = passed_fb;
|
||||||
@@ -812,17 +847,6 @@ nv04_crtc_do_mode_set_base(struct drm_crtc *crtc,
|
|||||||
} else {
|
} else {
|
||||||
drm_fb = crtc->fb;
|
drm_fb = crtc->fb;
|
||||||
fb = nouveau_framebuffer(crtc->fb);
|
fb = nouveau_framebuffer(crtc->fb);
|
||||||
/* If not atomic, we can go ahead and pin, and unpin the
|
|
||||||
* old fb we were passed.
|
|
||||||
*/
|
|
||||||
ret = nouveau_bo_pin(fb->nvbo, TTM_PL_FLAG_VRAM);
|
|
||||||
if (ret)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
if (passed_fb) {
|
|
||||||
struct nouveau_framebuffer *ofb = nouveau_framebuffer(passed_fb);
|
|
||||||
nouveau_bo_unpin(ofb->nvbo);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
nv_crtc->fb.offset = fb->nvbo->bo.offset;
|
nv_crtc->fb.offset = fb->nvbo->bo.offset;
|
||||||
@@ -877,6 +901,9 @@ static int
|
|||||||
nv04_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
|
nv04_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
|
||||||
struct drm_framebuffer *old_fb)
|
struct drm_framebuffer *old_fb)
|
||||||
{
|
{
|
||||||
|
int ret = nv_crtc_swap_fbs(crtc, old_fb);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
return nv04_crtc_do_mode_set_base(crtc, old_fb, x, y, false);
|
return nv04_crtc_do_mode_set_base(crtc, old_fb, x, y, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1027,6 +1054,7 @@ static const struct drm_crtc_helper_funcs nv04_crtc_helper_funcs = {
|
|||||||
.mode_set_base = nv04_crtc_mode_set_base,
|
.mode_set_base = nv04_crtc_mode_set_base,
|
||||||
.mode_set_base_atomic = nv04_crtc_mode_set_base_atomic,
|
.mode_set_base_atomic = nv04_crtc_mode_set_base_atomic,
|
||||||
.load_lut = nv_crtc_gamma_load,
|
.load_lut = nv_crtc_gamma_load,
|
||||||
|
.disable = nv_crtc_disable,
|
||||||
};
|
};
|
||||||
|
|
||||||
int
|
int
|
||||||
|
@@ -81,6 +81,7 @@ struct nv04_display {
|
|||||||
uint32_t saved_vga_font[4][16384];
|
uint32_t saved_vga_font[4][16384];
|
||||||
uint32_t dac_users[4];
|
uint32_t dac_users[4];
|
||||||
struct nouveau_object *core;
|
struct nouveau_object *core;
|
||||||
|
struct nouveau_bo *image[2];
|
||||||
};
|
};
|
||||||
|
|
||||||
static inline struct nv04_display *
|
static inline struct nv04_display *
|
||||||
|
@@ -577,6 +577,9 @@ nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb,
|
|||||||
ret = nv50_display_flip_next(crtc, fb, chan, 0);
|
ret = nv50_display_flip_next(crtc, fb, chan, 0);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto fail_unreserve;
|
goto fail_unreserve;
|
||||||
|
} else {
|
||||||
|
struct nv04_display *dispnv04 = nv04_display(dev);
|
||||||
|
nouveau_bo_ref(new_bo, &dispnv04->image[nouveau_crtc(crtc)->index]);
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = nouveau_page_flip_emit(chan, old_bo, new_bo, s, &fence);
|
ret = nouveau_page_flip_emit(chan, old_bo, new_bo, s, &fence);
|
||||||
|
@@ -131,7 +131,7 @@ nv40_calc_pll(struct drm_device *dev, u32 reg, struct nvbios_pll *pll,
|
|||||||
if (clk < pll->vco1.max_freq)
|
if (clk < pll->vco1.max_freq)
|
||||||
pll->vco2.max_freq = 0;
|
pll->vco2.max_freq = 0;
|
||||||
|
|
||||||
pclk->pll_calc(pclk, pll, clk, &coef);
|
ret = pclk->pll_calc(pclk, pll, clk, &coef);
|
||||||
if (ret == 0)
|
if (ret == 0)
|
||||||
return -ERANGE;
|
return -ERANGE;
|
||||||
|
|
||||||
|
@@ -2163,7 +2163,7 @@ void cik_mm_wdoorbell(struct radeon_device *rdev, u32 offset, u32 v);
|
|||||||
WREG32(reg, tmp_); \
|
WREG32(reg, tmp_); \
|
||||||
} while (0)
|
} while (0)
|
||||||
#define WREG32_AND(reg, and) WREG32_P(reg, 0, and)
|
#define WREG32_AND(reg, and) WREG32_P(reg, 0, and)
|
||||||
#define WREG32_OR(reg, or) WREG32_P(reg, or, ~or)
|
#define WREG32_OR(reg, or) WREG32_P(reg, or, ~(or))
|
||||||
#define WREG32_PLL_P(reg, val, mask) \
|
#define WREG32_PLL_P(reg, val, mask) \
|
||||||
do { \
|
do { \
|
||||||
uint32_t tmp_ = RREG32_PLL(reg); \
|
uint32_t tmp_ = RREG32_PLL(reg); \
|
||||||
|
@@ -356,6 +356,14 @@ static int radeon_uvd_cs_msg(struct radeon_cs_parser *p, struct radeon_bo *bo,
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (bo->tbo.sync_obj) {
|
||||||
|
r = radeon_fence_wait(bo->tbo.sync_obj, false);
|
||||||
|
if (r) {
|
||||||
|
DRM_ERROR("Failed waiting for UVD message (%d)!\n", r);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
r = radeon_bo_kmap(bo, &ptr);
|
r = radeon_bo_kmap(bo, &ptr);
|
||||||
if (r) {
|
if (r) {
|
||||||
DRM_ERROR("Failed mapping the UVD message (%d)!\n", r);
|
DRM_ERROR("Failed mapping the UVD message (%d)!\n", r);
|
||||||
|
@@ -744,10 +744,10 @@ static void rv770_init_golden_registers(struct radeon_device *rdev)
|
|||||||
(const u32)ARRAY_SIZE(r7xx_golden_dyn_gpr_registers));
|
(const u32)ARRAY_SIZE(r7xx_golden_dyn_gpr_registers));
|
||||||
radeon_program_register_sequence(rdev,
|
radeon_program_register_sequence(rdev,
|
||||||
rv730_golden_registers,
|
rv730_golden_registers,
|
||||||
(const u32)ARRAY_SIZE(rv770_golden_registers));
|
(const u32)ARRAY_SIZE(rv730_golden_registers));
|
||||||
radeon_program_register_sequence(rdev,
|
radeon_program_register_sequence(rdev,
|
||||||
rv730_mgcg_init,
|
rv730_mgcg_init,
|
||||||
(const u32)ARRAY_SIZE(rv770_mgcg_init));
|
(const u32)ARRAY_SIZE(rv730_mgcg_init));
|
||||||
break;
|
break;
|
||||||
case CHIP_RV710:
|
case CHIP_RV710:
|
||||||
radeon_program_register_sequence(rdev,
|
radeon_program_register_sequence(rdev,
|
||||||
@@ -758,18 +758,18 @@ static void rv770_init_golden_registers(struct radeon_device *rdev)
|
|||||||
(const u32)ARRAY_SIZE(r7xx_golden_dyn_gpr_registers));
|
(const u32)ARRAY_SIZE(r7xx_golden_dyn_gpr_registers));
|
||||||
radeon_program_register_sequence(rdev,
|
radeon_program_register_sequence(rdev,
|
||||||
rv710_golden_registers,
|
rv710_golden_registers,
|
||||||
(const u32)ARRAY_SIZE(rv770_golden_registers));
|
(const u32)ARRAY_SIZE(rv710_golden_registers));
|
||||||
radeon_program_register_sequence(rdev,
|
radeon_program_register_sequence(rdev,
|
||||||
rv710_mgcg_init,
|
rv710_mgcg_init,
|
||||||
(const u32)ARRAY_SIZE(rv770_mgcg_init));
|
(const u32)ARRAY_SIZE(rv710_mgcg_init));
|
||||||
break;
|
break;
|
||||||
case CHIP_RV740:
|
case CHIP_RV740:
|
||||||
radeon_program_register_sequence(rdev,
|
radeon_program_register_sequence(rdev,
|
||||||
rv740_golden_registers,
|
rv740_golden_registers,
|
||||||
(const u32)ARRAY_SIZE(rv770_golden_registers));
|
(const u32)ARRAY_SIZE(rv740_golden_registers));
|
||||||
radeon_program_register_sequence(rdev,
|
radeon_program_register_sequence(rdev,
|
||||||
rv740_mgcg_init,
|
rv740_mgcg_init,
|
||||||
(const u32)ARRAY_SIZE(rv770_mgcg_init));
|
(const u32)ARRAY_SIZE(rv740_mgcg_init));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
@@ -29,7 +29,9 @@
|
|||||||
#include <drm/drmP.h>
|
#include <drm/drmP.h>
|
||||||
#include <drm/ttm/ttm_bo_driver.h>
|
#include <drm/ttm/ttm_bo_driver.h>
|
||||||
|
|
||||||
#define VMW_PPN_SIZE sizeof(unsigned long)
|
#define VMW_PPN_SIZE (sizeof(unsigned long))
|
||||||
|
/* A future safe maximum remap size. */
|
||||||
|
#define VMW_PPN_PER_REMAP ((31 * 1024) / VMW_PPN_SIZE)
|
||||||
|
|
||||||
static int vmw_gmr2_bind(struct vmw_private *dev_priv,
|
static int vmw_gmr2_bind(struct vmw_private *dev_priv,
|
||||||
struct page *pages[],
|
struct page *pages[],
|
||||||
@@ -38,43 +40,61 @@ static int vmw_gmr2_bind(struct vmw_private *dev_priv,
|
|||||||
{
|
{
|
||||||
SVGAFifoCmdDefineGMR2 define_cmd;
|
SVGAFifoCmdDefineGMR2 define_cmd;
|
||||||
SVGAFifoCmdRemapGMR2 remap_cmd;
|
SVGAFifoCmdRemapGMR2 remap_cmd;
|
||||||
uint32_t define_size = sizeof(define_cmd) + 4;
|
|
||||||
uint32_t remap_size = VMW_PPN_SIZE * num_pages + sizeof(remap_cmd) + 4;
|
|
||||||
uint32_t *cmd;
|
uint32_t *cmd;
|
||||||
uint32_t *cmd_orig;
|
uint32_t *cmd_orig;
|
||||||
|
uint32_t define_size = sizeof(define_cmd) + sizeof(*cmd);
|
||||||
|
uint32_t remap_num = num_pages / VMW_PPN_PER_REMAP + ((num_pages % VMW_PPN_PER_REMAP) > 0);
|
||||||
|
uint32_t remap_size = VMW_PPN_SIZE * num_pages + (sizeof(remap_cmd) + sizeof(*cmd)) * remap_num;
|
||||||
|
uint32_t remap_pos = 0;
|
||||||
|
uint32_t cmd_size = define_size + remap_size;
|
||||||
uint32_t i;
|
uint32_t i;
|
||||||
|
|
||||||
cmd_orig = cmd = vmw_fifo_reserve(dev_priv, define_size + remap_size);
|
cmd_orig = cmd = vmw_fifo_reserve(dev_priv, cmd_size);
|
||||||
if (unlikely(cmd == NULL))
|
if (unlikely(cmd == NULL))
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
define_cmd.gmrId = gmr_id;
|
define_cmd.gmrId = gmr_id;
|
||||||
define_cmd.numPages = num_pages;
|
define_cmd.numPages = num_pages;
|
||||||
|
|
||||||
|
*cmd++ = SVGA_CMD_DEFINE_GMR2;
|
||||||
|
memcpy(cmd, &define_cmd, sizeof(define_cmd));
|
||||||
|
cmd += sizeof(define_cmd) / sizeof(*cmd);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Need to split the command if there are too many
|
||||||
|
* pages that goes into the gmr.
|
||||||
|
*/
|
||||||
|
|
||||||
remap_cmd.gmrId = gmr_id;
|
remap_cmd.gmrId = gmr_id;
|
||||||
remap_cmd.flags = (VMW_PPN_SIZE > sizeof(*cmd)) ?
|
remap_cmd.flags = (VMW_PPN_SIZE > sizeof(*cmd)) ?
|
||||||
SVGA_REMAP_GMR2_PPN64 : SVGA_REMAP_GMR2_PPN32;
|
SVGA_REMAP_GMR2_PPN64 : SVGA_REMAP_GMR2_PPN32;
|
||||||
remap_cmd.offsetPages = 0;
|
|
||||||
remap_cmd.numPages = num_pages;
|
|
||||||
|
|
||||||
*cmd++ = SVGA_CMD_DEFINE_GMR2;
|
while (num_pages > 0) {
|
||||||
memcpy(cmd, &define_cmd, sizeof(define_cmd));
|
unsigned long nr = min(num_pages, (unsigned long)VMW_PPN_PER_REMAP);
|
||||||
cmd += sizeof(define_cmd) / sizeof(uint32);
|
|
||||||
|
|
||||||
*cmd++ = SVGA_CMD_REMAP_GMR2;
|
remap_cmd.offsetPages = remap_pos;
|
||||||
memcpy(cmd, &remap_cmd, sizeof(remap_cmd));
|
remap_cmd.numPages = nr;
|
||||||
cmd += sizeof(remap_cmd) / sizeof(uint32);
|
|
||||||
|
|
||||||
for (i = 0; i < num_pages; ++i) {
|
*cmd++ = SVGA_CMD_REMAP_GMR2;
|
||||||
if (VMW_PPN_SIZE <= 4)
|
memcpy(cmd, &remap_cmd, sizeof(remap_cmd));
|
||||||
*cmd = page_to_pfn(*pages++);
|
cmd += sizeof(remap_cmd) / sizeof(*cmd);
|
||||||
else
|
|
||||||
*((uint64_t *)cmd) = page_to_pfn(*pages++);
|
|
||||||
|
|
||||||
cmd += VMW_PPN_SIZE / sizeof(*cmd);
|
for (i = 0; i < nr; ++i) {
|
||||||
|
if (VMW_PPN_SIZE <= 4)
|
||||||
|
*cmd = page_to_pfn(*pages++);
|
||||||
|
else
|
||||||
|
*((uint64_t *)cmd) = page_to_pfn(*pages++);
|
||||||
|
|
||||||
|
cmd += VMW_PPN_SIZE / sizeof(*cmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
num_pages -= nr;
|
||||||
|
remap_pos += nr;
|
||||||
}
|
}
|
||||||
|
|
||||||
vmw_fifo_commit(dev_priv, define_size + remap_size);
|
BUG_ON(cmd != cmd_orig + cmd_size / sizeof(*cmd));
|
||||||
|
|
||||||
|
vmw_fifo_commit(dev_priv, cmd_size);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@@ -232,7 +232,8 @@ static int adjd_s311_read_raw(struct iio_dev *indio_dev,
|
|||||||
|
|
||||||
switch (mask) {
|
switch (mask) {
|
||||||
case IIO_CHAN_INFO_RAW:
|
case IIO_CHAN_INFO_RAW:
|
||||||
ret = adjd_s311_read_data(indio_dev, chan->address, val);
|
ret = adjd_s311_read_data(indio_dev,
|
||||||
|
ADJD_S311_DATA_REG(chan->address), val);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
return IIO_VAL_INT;
|
return IIO_VAL_INT;
|
||||||
|
@@ -167,6 +167,7 @@ static const struct xpad_device {
|
|||||||
{ 0x1430, 0x8888, "TX6500+ Dance Pad (first generation)", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX },
|
{ 0x1430, 0x8888, "TX6500+ Dance Pad (first generation)", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX },
|
||||||
{ 0x146b, 0x0601, "BigBen Interactive XBOX 360 Controller", 0, XTYPE_XBOX360 },
|
{ 0x146b, 0x0601, "BigBen Interactive XBOX 360 Controller", 0, XTYPE_XBOX360 },
|
||||||
{ 0x1689, 0xfd00, "Razer Onza Tournament Edition", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360 },
|
{ 0x1689, 0xfd00, "Razer Onza Tournament Edition", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360 },
|
||||||
|
{ 0x1689, 0xfd01, "Razer Onza Classic Edition", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360 },
|
||||||
{ 0x1bad, 0x0002, "Harmonix Rock Band Guitar", 0, XTYPE_XBOX360 },
|
{ 0x1bad, 0x0002, "Harmonix Rock Band Guitar", 0, XTYPE_XBOX360 },
|
||||||
{ 0x1bad, 0x0003, "Harmonix Rock Band Drumkit", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360 },
|
{ 0x1bad, 0x0003, "Harmonix Rock Band Drumkit", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360 },
|
||||||
{ 0x1bad, 0xf016, "Mad Catz Xbox 360 Controller", 0, XTYPE_XBOX360 },
|
{ 0x1bad, 0xf016, "Mad Catz Xbox 360 Controller", 0, XTYPE_XBOX360 },
|
||||||
|
@@ -672,6 +672,7 @@ static int elantech_packet_check_v2(struct psmouse *psmouse)
|
|||||||
*/
|
*/
|
||||||
static int elantech_packet_check_v3(struct psmouse *psmouse)
|
static int elantech_packet_check_v3(struct psmouse *psmouse)
|
||||||
{
|
{
|
||||||
|
struct elantech_data *etd = psmouse->private;
|
||||||
const u8 debounce_packet[] = { 0xc4, 0xff, 0xff, 0x02, 0xff, 0xff };
|
const u8 debounce_packet[] = { 0xc4, 0xff, 0xff, 0x02, 0xff, 0xff };
|
||||||
unsigned char *packet = psmouse->packet;
|
unsigned char *packet = psmouse->packet;
|
||||||
|
|
||||||
@@ -682,19 +683,48 @@ static int elantech_packet_check_v3(struct psmouse *psmouse)
|
|||||||
if (!memcmp(packet, debounce_packet, sizeof(debounce_packet)))
|
if (!memcmp(packet, debounce_packet, sizeof(debounce_packet)))
|
||||||
return PACKET_DEBOUNCE;
|
return PACKET_DEBOUNCE;
|
||||||
|
|
||||||
if ((packet[0] & 0x0c) == 0x04 && (packet[3] & 0xcf) == 0x02)
|
/*
|
||||||
return PACKET_V3_HEAD;
|
* If the hardware flag 'crc_enabled' is set the packets have
|
||||||
|
* different signatures.
|
||||||
|
*/
|
||||||
|
if (etd->crc_enabled) {
|
||||||
|
if ((packet[3] & 0x09) == 0x08)
|
||||||
|
return PACKET_V3_HEAD;
|
||||||
|
|
||||||
if ((packet[0] & 0x0c) == 0x0c && (packet[3] & 0xce) == 0x0c)
|
if ((packet[3] & 0x09) == 0x09)
|
||||||
return PACKET_V3_TAIL;
|
return PACKET_V3_TAIL;
|
||||||
|
} else {
|
||||||
|
if ((packet[0] & 0x0c) == 0x04 && (packet[3] & 0xcf) == 0x02)
|
||||||
|
return PACKET_V3_HEAD;
|
||||||
|
|
||||||
|
if ((packet[0] & 0x0c) == 0x0c && (packet[3] & 0xce) == 0x0c)
|
||||||
|
return PACKET_V3_TAIL;
|
||||||
|
}
|
||||||
|
|
||||||
return PACKET_UNKNOWN;
|
return PACKET_UNKNOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int elantech_packet_check_v4(struct psmouse *psmouse)
|
static int elantech_packet_check_v4(struct psmouse *psmouse)
|
||||||
{
|
{
|
||||||
|
struct elantech_data *etd = psmouse->private;
|
||||||
unsigned char *packet = psmouse->packet;
|
unsigned char *packet = psmouse->packet;
|
||||||
unsigned char packet_type = packet[3] & 0x03;
|
unsigned char packet_type = packet[3] & 0x03;
|
||||||
|
bool sanity_check;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Sanity check based on the constant bits of a packet.
|
||||||
|
* The constant bits change depending on the value of
|
||||||
|
* the hardware flag 'crc_enabled' but are the same for
|
||||||
|
* every packet, regardless of the type.
|
||||||
|
*/
|
||||||
|
if (etd->crc_enabled)
|
||||||
|
sanity_check = ((packet[3] & 0x08) == 0x00);
|
||||||
|
else
|
||||||
|
sanity_check = ((packet[0] & 0x0c) == 0x04 &&
|
||||||
|
(packet[3] & 0x1c) == 0x10);
|
||||||
|
|
||||||
|
if (!sanity_check)
|
||||||
|
return PACKET_UNKNOWN;
|
||||||
|
|
||||||
switch (packet_type) {
|
switch (packet_type) {
|
||||||
case 0:
|
case 0:
|
||||||
@@ -1313,6 +1343,12 @@ static int elantech_set_properties(struct elantech_data *etd)
|
|||||||
etd->reports_pressure = true;
|
etd->reports_pressure = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The signatures of v3 and v4 packets change depending on the
|
||||||
|
* value of this hardware flag.
|
||||||
|
*/
|
||||||
|
etd->crc_enabled = ((etd->fw_version & 0x4000) == 0x4000);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -129,6 +129,7 @@ struct elantech_data {
|
|||||||
bool paritycheck;
|
bool paritycheck;
|
||||||
bool jumpy_cursor;
|
bool jumpy_cursor;
|
||||||
bool reports_pressure;
|
bool reports_pressure;
|
||||||
|
bool crc_enabled;
|
||||||
unsigned char hw_version;
|
unsigned char hw_version;
|
||||||
unsigned int fw_version;
|
unsigned int fw_version;
|
||||||
unsigned int single_finger_reports;
|
unsigned int single_finger_reports;
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user