* [PATCH v4 10/16] y2038: powerpc: Extend sysvipc data structures
From: Arnd Bergmann @ 2018-04-25 15:06 UTC (permalink / raw)
To: y2038, linux-kernel
Cc: linux-api, linux-arch, libc-alpha, tglx, deepa.kernel, viro,
ebiederm, albert.aribaud, linux-s390, schwidefsky, x86,
catalin.marinas, will.deacon, linux-mips, jhogan, ralf,
linuxppc-dev, sparclinux, zackw, noloader, Arnd Bergmann
In-Reply-To: <20180425132242.1500539-1-arnd@arndb.de>
powerpc, uses a nonstandard variation of the generic sysvipc
data structures, intended to have the padding moved around
so it can deal with big-endian 32-bit user space that has
64-bit time_t.
powerpc has the same definition as parisc and sparc, but now also
supports little-endian mode, which is now wrong because the
padding is made for big-endian user space.
This takes just take the same approach here that we have for
the asm-generic headers and adds separate 32-bit fields for the
upper halves of the timestamps, to let libc deal with the mess
in user space.
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
---
arch/powerpc/include/asm/compat.h | 32 ++++++++++++++++----------------
arch/powerpc/include/uapi/asm/msgbuf.h | 18 +++++++++---------
arch/powerpc/include/uapi/asm/sembuf.h | 14 +++++++-------
arch/powerpc/include/uapi/asm/shmbuf.h | 19 ++++++++-----------
4 files changed, 40 insertions(+), 43 deletions(-)
diff --git a/arch/powerpc/include/asm/compat.h b/arch/powerpc/include/asm/compat.h
index b4773c81f7d5..85c8af2bb272 100644
--- a/arch/powerpc/include/asm/compat.h
+++ b/arch/powerpc/include/asm/compat.h
@@ -162,10 +162,10 @@ struct compat_ipc64_perm {
struct compat_semid64_ds {
struct compat_ipc64_perm sem_perm;
- unsigned int __unused1;
- compat_time_t sem_otime;
- unsigned int __unused2;
- compat_time_t sem_ctime;
+ unsigned int sem_otime_high;
+ unsigned int sem_otime;
+ unsigned int sem_ctime_high;
+ unsigned int sem_ctime;
compat_ulong_t sem_nsems;
compat_ulong_t __unused3;
compat_ulong_t __unused4;
@@ -173,12 +173,12 @@ struct compat_semid64_ds {
struct compat_msqid64_ds {
struct compat_ipc64_perm msg_perm;
- unsigned int __unused1;
- compat_time_t msg_stime;
- unsigned int __unused2;
- compat_time_t msg_rtime;
- unsigned int __unused3;
- compat_time_t msg_ctime;
+ unsigned int msg_stime_high;
+ unsigned int msg_stime;
+ unsigned int msg_rtime_high;
+ unsigned int msg_rtime;
+ unsigned int msg_ctime_high;
+ unsigned int msg_ctime;
compat_ulong_t msg_cbytes;
compat_ulong_t msg_qnum;
compat_ulong_t msg_qbytes;
@@ -190,12 +190,12 @@ struct compat_msqid64_ds {
struct compat_shmid64_ds {
struct compat_ipc64_perm shm_perm;
- unsigned int __unused1;
- compat_time_t shm_atime;
- unsigned int __unused2;
- compat_time_t shm_dtime;
- unsigned int __unused3;
- compat_time_t shm_ctime;
+ unsigned int shm_atime_high;
+ unsigned int shm_atime;
+ unsigned int shm_dtime_high;
+ unsigned int shm_dtime;
+ unsigned int shm_ctime_high;
+ unsigned int shm_ctime;
unsigned int __unused4;
compat_size_t shm_segsz;
compat_pid_t shm_cpid;
diff --git a/arch/powerpc/include/uapi/asm/msgbuf.h b/arch/powerpc/include/uapi/asm/msgbuf.h
index 65beb0942500..2b1b37797a47 100644
--- a/arch/powerpc/include/uapi/asm/msgbuf.h
+++ b/arch/powerpc/include/uapi/asm/msgbuf.h
@@ -10,18 +10,18 @@
struct msqid64_ds {
struct ipc64_perm msg_perm;
-#ifndef __powerpc64__
- unsigned int __unused1;
-#endif
+#ifdef __powerpc64__
__kernel_time_t msg_stime; /* last msgsnd time */
-#ifndef __powerpc64__
- unsigned int __unused2;
-#endif
__kernel_time_t msg_rtime; /* last msgrcv time */
-#ifndef __powerpc64__
- unsigned int __unused3;
-#endif
__kernel_time_t msg_ctime; /* last change time */
+#else
+ unsigned long msg_stime_high;
+ unsigned long msg_stime; /* last msgsnd time */
+ unsigned long msg_rtime_high;
+ unsigned long msg_rtime; /* last msgrcv time */
+ unsigned long msg_ctime_high;
+ unsigned long msg_ctime; /* last change time */
+#endif
unsigned long msg_cbytes; /* current number of bytes on queue */
unsigned long msg_qnum; /* number of messages in queue */
unsigned long msg_qbytes; /* max number of bytes on queue */
diff --git a/arch/powerpc/include/uapi/asm/sembuf.h b/arch/powerpc/include/uapi/asm/sembuf.h
index 8f393d60f02d..3f60946f77e3 100644
--- a/arch/powerpc/include/uapi/asm/sembuf.h
+++ b/arch/powerpc/include/uapi/asm/sembuf.h
@@ -15,20 +15,20 @@
* between kernel and user space.
*
* Pad space is left for:
- * - 64-bit time_t to solve y2038 problem
- * - 2 miscellaneous 32-bit values
+ * - 2 miscellaneous 32/64-bit values
*/
struct semid64_ds {
struct ipc64_perm sem_perm; /* permissions .. see ipc.h */
#ifndef __powerpc64__
- unsigned long __unused1;
-#endif
+ unsigned long sem_otime_high;
+ unsigned long sem_otime; /* last semop time */
+ unsigned long sem_ctime_high;
+ unsigned long sem_ctime; /* last change time */
+#else
__kernel_time_t sem_otime; /* last semop time */
-#ifndef __powerpc64__
- unsigned long __unused2;
-#endif
__kernel_time_t sem_ctime; /* last change time */
+#endif
unsigned long sem_nsems; /* no. of semaphores in array */
unsigned long __unused3;
unsigned long __unused4;
diff --git a/arch/powerpc/include/uapi/asm/shmbuf.h b/arch/powerpc/include/uapi/asm/shmbuf.h
index deb1c3e503d3..b591c4d7e4c5 100644
--- a/arch/powerpc/include/uapi/asm/shmbuf.h
+++ b/arch/powerpc/include/uapi/asm/shmbuf.h
@@ -16,25 +16,22 @@
* between kernel and user space.
*
* Pad space is left for:
- * - 64-bit time_t to solve y2038 problem
* - 2 miscellaneous 32-bit values
*/
struct shmid64_ds {
struct ipc64_perm shm_perm; /* operation perms */
-#ifndef __powerpc64__
- unsigned long __unused1;
-#endif
+#ifdef __powerpc64__
__kernel_time_t shm_atime; /* last attach time */
-#ifndef __powerpc64__
- unsigned long __unused2;
-#endif
__kernel_time_t shm_dtime; /* last detach time */
-#ifndef __powerpc64__
- unsigned long __unused3;
-#endif
__kernel_time_t shm_ctime; /* last change time */
-#ifndef __powerpc64__
+#else
+ unsigned long shm_atime_high;
+ unsigned long shm_atime; /* last attach time */
+ unsigned long shm_dtime_high;
+ unsigned long shm_dtime; /* last detach time */
+ unsigned long shm_ctime_high;
+ unsigned long shm_ctime; /* last change time */
unsigned long __unused4;
#endif
size_t shm_segsz; /* size of segment (bytes) */
--
2.9.0
^ permalink raw reply related
* [PATCH v4 16/16] y2038: ipc: Redirect ipc(SEMTIMEDOP, ...) to compat_ksys_semtimedop
From: Arnd Bergmann @ 2018-04-25 15:06 UTC (permalink / raw)
To: y2038, linux-kernel
Cc: linux-api, linux-arch, libc-alpha, tglx, deepa.kernel, viro,
ebiederm, albert.aribaud, linux-s390, schwidefsky, x86,
catalin.marinas, will.deacon, linux-mips, jhogan, ralf,
linuxppc-dev, sparclinux, zackw, noloader, Arnd Bergmann
In-Reply-To: <20180425132242.1500539-1-arnd@arndb.de>
32-bit architectures implementing 64BIT_TIME and COMPAT_32BIT_TIME
need to have the traditional semtimedop() behavior with 32-bit timestamps
for sys_ipc() by calling compat_ksys_semtimedop(), while those that
are not yet converted need to keep using ksys_semtimedop() like
64-bit architectures do.
Note that I chose to not implement a new SEMTIMEDOP64 function that
corresponds to the new sys_semtimedop() with 64-bit timeouts. The reason
here is that sys_ipc() should no longer be used for new system calls,
and libc should just call the semtimedop syscall directly.
One open question remain to whether we want to completely avoid the
sys_ipc() system call for architectures that do not yet have all the
individual calls as they get converted to 64-bit time_t. Doing that
would require adding several extra system calls on m68k, mips, powerpc,
s390, sh, sparc, and x86-32.
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
---
ipc/syscall.c | 13 ++++++++++---
1 file changed, 10 insertions(+), 3 deletions(-)
diff --git a/ipc/syscall.c b/ipc/syscall.c
index 77a883ef2eca..65d405f1ba0c 100644
--- a/ipc/syscall.c
+++ b/ipc/syscall.c
@@ -30,9 +30,14 @@ SYSCALL_DEFINE6(ipc, unsigned int, call, int, first, unsigned long, second,
return ksys_semtimedop(first, (struct sembuf __user *)ptr,
second, NULL);
case SEMTIMEDOP:
- return ksys_semtimedop(first, (struct sembuf __user *)ptr,
- second,
- (const struct timespec __user *)fifth);
+ if (IS_ENABLED(CONFIG_64BIT) || !IS_ENABLED(CONFIG_64BIT_TIME))
+ return ksys_semtimedop(first, ptr, second,
+ (const struct __kernel_timespec __user *)fifth);
+ else if (IS_ENABLED(CONFIG_COMPAT_32BIT_TIME))
+ return compat_ksys_semtimedop(first, ptr, second,
+ (const struct compat_timespec __user *)fifth);
+ else
+ return -ENOSYS;
case SEMGET:
return ksys_semget(first, second, third);
@@ -130,6 +135,8 @@ COMPAT_SYSCALL_DEFINE6(ipc, u32, call, int, first, int, second,
/* struct sembuf is the same on 32 and 64bit :)) */
return ksys_semtimedop(first, compat_ptr(ptr), second, NULL);
case SEMTIMEDOP:
+ if (!IS_ENABLED(CONFIG_COMPAT_32BIT_TIME))
+ return -ENOSYS;
return compat_ksys_semtimedop(first, compat_ptr(ptr), second,
compat_ptr(fifth));
case SEMGET:
--
2.9.0
^ permalink raw reply related
* [PATCH v4 15/16] y2038: ipc: Enable COMPAT_32BIT_TIME
From: Arnd Bergmann @ 2018-04-25 15:06 UTC (permalink / raw)
To: y2038, linux-kernel
Cc: linux-api, linux-arch, libc-alpha, tglx, deepa.kernel, viro,
ebiederm, albert.aribaud, linux-s390, schwidefsky, x86,
catalin.marinas, will.deacon, linux-mips, jhogan, ralf,
linuxppc-dev, sparclinux, zackw, noloader, Arnd Bergmann
In-Reply-To: <20180425132242.1500539-1-arnd@arndb.de>
Three ipc syscalls (mq_timedsend, mq_timedreceive and and semtimedop)
take a timespec argument. After we move 32-bit architectures over to
useing 64-bit time_t based syscalls, we need seperate entry points for
the old 32-bit based interfaces.
This changes the #ifdef guards for the existing 32-bit compat syscalls
to check for CONFIG_COMPAT_32BIT_TIME instead, which will then be
enabled on all existing 32-bit architectures.
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
---
ipc/mqueue.c | 80 +++++++++++++++++++++++++++++++-----------------------------
ipc/sem.c | 3 ++-
ipc/util.h | 2 +-
3 files changed, 44 insertions(+), 41 deletions(-)
diff --git a/ipc/mqueue.c b/ipc/mqueue.c
index 9610afcfa2e5..c0d58f390c3b 100644
--- a/ipc/mqueue.c
+++ b/ipc/mqueue.c
@@ -1420,6 +1420,47 @@ COMPAT_SYSCALL_DEFINE4(mq_open, const char __user *, u_name,
return do_mq_open(u_name, oflag, mode, p);
}
+COMPAT_SYSCALL_DEFINE2(mq_notify, mqd_t, mqdes,
+ const struct compat_sigevent __user *, u_notification)
+{
+ struct sigevent n, *p = NULL;
+ if (u_notification) {
+ if (get_compat_sigevent(&n, u_notification))
+ return -EFAULT;
+ if (n.sigev_notify == SIGEV_THREAD)
+ n.sigev_value.sival_ptr = compat_ptr(n.sigev_value.sival_int);
+ p = &n;
+ }
+ return do_mq_notify(mqdes, p);
+}
+
+COMPAT_SYSCALL_DEFINE3(mq_getsetattr, mqd_t, mqdes,
+ const struct compat_mq_attr __user *, u_mqstat,
+ struct compat_mq_attr __user *, u_omqstat)
+{
+ int ret;
+ struct mq_attr mqstat, omqstat;
+ struct mq_attr *new = NULL, *old = NULL;
+
+ if (u_mqstat) {
+ new = &mqstat;
+ if (get_compat_mq_attr(new, u_mqstat))
+ return -EFAULT;
+ }
+ if (u_omqstat)
+ old = &omqstat;
+
+ ret = do_mq_getsetattr(mqdes, new, old);
+ if (ret || !old)
+ return ret;
+
+ if (put_compat_mq_attr(old, u_omqstat))
+ return -EFAULT;
+ return 0;
+}
+#endif
+
+#ifdef CONFIG_COMPAT_32BIT_TIME
static int compat_prepare_timeout(const struct compat_timespec __user *p,
struct timespec64 *ts)
{
@@ -1459,45 +1500,6 @@ COMPAT_SYSCALL_DEFINE5(mq_timedreceive, mqd_t, mqdes,
}
return do_mq_timedreceive(mqdes, u_msg_ptr, msg_len, u_msg_prio, p);
}
-
-COMPAT_SYSCALL_DEFINE2(mq_notify, mqd_t, mqdes,
- const struct compat_sigevent __user *, u_notification)
-{
- struct sigevent n, *p = NULL;
- if (u_notification) {
- if (get_compat_sigevent(&n, u_notification))
- return -EFAULT;
- if (n.sigev_notify == SIGEV_THREAD)
- n.sigev_value.sival_ptr = compat_ptr(n.sigev_value.sival_int);
- p = &n;
- }
- return do_mq_notify(mqdes, p);
-}
-
-COMPAT_SYSCALL_DEFINE3(mq_getsetattr, mqd_t, mqdes,
- const struct compat_mq_attr __user *, u_mqstat,
- struct compat_mq_attr __user *, u_omqstat)
-{
- int ret;
- struct mq_attr mqstat, omqstat;
- struct mq_attr *new = NULL, *old = NULL;
-
- if (u_mqstat) {
- new = &mqstat;
- if (get_compat_mq_attr(new, u_mqstat))
- return -EFAULT;
- }
- if (u_omqstat)
- old = &omqstat;
-
- ret = do_mq_getsetattr(mqdes, new, old);
- if (ret || !old)
- return ret;
-
- if (put_compat_mq_attr(old, u_omqstat))
- return -EFAULT;
- return 0;
-}
#endif
static const struct inode_operations mqueue_dir_inode_operations = {
diff --git a/ipc/sem.c b/ipc/sem.c
index b951e25ba2db..cfd94d48a9aa 100644
--- a/ipc/sem.c
+++ b/ipc/sem.c
@@ -70,6 +70,7 @@
* The worst-case behavior is nevertheless O(N^2) for N wakeups.
*/
+#include <linux/compat.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
#include <linux/init.h>
@@ -2193,7 +2194,7 @@ SYSCALL_DEFINE4(semtimedop, int, semid, struct sembuf __user *, tsops,
return ksys_semtimedop(semid, tsops, nsops, timeout);
}
-#ifdef CONFIG_COMPAT
+#ifdef CONFIG_COMPAT_32BIT_TIME
long compat_ksys_semtimedop(int semid, struct sembuf __user *tsems,
unsigned int nsops,
const struct compat_timespec __user *timeout)
diff --git a/ipc/util.h b/ipc/util.h
index 975c6de2df9d..0aba3230d007 100644
--- a/ipc/util.h
+++ b/ipc/util.h
@@ -265,10 +265,10 @@ long ksys_shmdt(char __user *shmaddr);
long ksys_shmctl(int shmid, int cmd, struct shmid_ds __user *buf);
/* for CONFIG_ARCH_WANT_OLD_COMPAT_IPC */
-#ifdef CONFIG_COMPAT
long compat_ksys_semtimedop(int semid, struct sembuf __user *tsems,
unsigned int nsops,
const struct compat_timespec __user *timeout);
+#ifdef CONFIG_COMPAT
long compat_ksys_semctl(int semid, int semnum, int cmd, int arg);
long compat_ksys_msgctl(int msqid, int cmd, void __user *uptr);
long compat_ksys_msgrcv(int msqid, compat_uptr_t msgp, compat_ssize_t msgsz,
--
2.9.0
^ permalink raw reply related
* [PATCH v4 14/16] y2038: ipc: Use __kernel_timespec
From: Arnd Bergmann @ 2018-04-25 15:06 UTC (permalink / raw)
To: y2038, linux-kernel
Cc: linux-api, linux-arch, libc-alpha, tglx, deepa.kernel, viro,
ebiederm, albert.aribaud, linux-s390, schwidefsky, x86,
catalin.marinas, will.deacon, linux-mips, jhogan, ralf,
linuxppc-dev, sparclinux, zackw, noloader, Arnd Bergmann
In-Reply-To: <20180425132242.1500539-1-arnd@arndb.de>
This is a preparatation for changing over __kernel_timespec to 64-bit
times, which involves assigning new system call numbers for mq_timedsend(),
mq_timedreceive() and semtimedop() for compatibility with future y2038
proof user space.
The existing ABIs will remain available through compat code.
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
---
include/linux/syscalls.h | 6 +++---
ipc/mqueue.c | 6 +++---
ipc/sem.c | 4 ++--
ipc/util.h | 2 +-
4 files changed, 9 insertions(+), 9 deletions(-)
diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h
index c9a2a2601852..b92cb79d38c3 100644
--- a/include/linux/syscalls.h
+++ b/include/linux/syscalls.h
@@ -680,8 +680,8 @@ asmlinkage long sys_sysinfo(struct sysinfo __user *info);
/* ipc/mqueue.c */
asmlinkage long sys_mq_open(const char __user *name, int oflag, umode_t mode, struct mq_attr __user *attr);
asmlinkage long sys_mq_unlink(const char __user *name);
-asmlinkage long sys_mq_timedsend(mqd_t mqdes, const char __user *msg_ptr, size_t msg_len, unsigned int msg_prio, const struct timespec __user *abs_timeout);
-asmlinkage long sys_mq_timedreceive(mqd_t mqdes, char __user *msg_ptr, size_t msg_len, unsigned int __user *msg_prio, const struct timespec __user *abs_timeout);
+asmlinkage long sys_mq_timedsend(mqd_t mqdes, const char __user *msg_ptr, size_t msg_len, unsigned int msg_prio, const struct __kernel_timespec __user *abs_timeout);
+asmlinkage long sys_mq_timedreceive(mqd_t mqdes, char __user *msg_ptr, size_t msg_len, unsigned int __user *msg_prio, const struct __kernel_timespec __user *abs_timeout);
asmlinkage long sys_mq_notify(mqd_t mqdes, const struct sigevent __user *notification);
asmlinkage long sys_mq_getsetattr(mqd_t mqdes, const struct mq_attr __user *mqstat, struct mq_attr __user *omqstat);
@@ -698,7 +698,7 @@ asmlinkage long sys_semget(key_t key, int nsems, int semflg);
asmlinkage long sys_semctl(int semid, int semnum, int cmd, unsigned long arg);
asmlinkage long sys_semtimedop(int semid, struct sembuf __user *sops,
unsigned nsops,
- const struct timespec __user *timeout);
+ const struct __kernel_timespec __user *timeout);
asmlinkage long sys_semop(int semid, struct sembuf __user *sops,
unsigned nsops);
diff --git a/ipc/mqueue.c b/ipc/mqueue.c
index a808f29d4c5a..9610afcfa2e5 100644
--- a/ipc/mqueue.c
+++ b/ipc/mqueue.c
@@ -691,7 +691,7 @@ static void __do_notify(struct mqueue_inode_info *info)
wake_up(&info->wait_q);
}
-static int prepare_timeout(const struct timespec __user *u_abs_timeout,
+static int prepare_timeout(const struct __kernel_timespec __user *u_abs_timeout,
struct timespec64 *ts)
{
if (get_timespec64(ts, u_abs_timeout))
@@ -1128,7 +1128,7 @@ static int do_mq_timedreceive(mqd_t mqdes, char __user *u_msg_ptr,
SYSCALL_DEFINE5(mq_timedsend, mqd_t, mqdes, const char __user *, u_msg_ptr,
size_t, msg_len, unsigned int, msg_prio,
- const struct timespec __user *, u_abs_timeout)
+ const struct __kernel_timespec __user *, u_abs_timeout)
{
struct timespec64 ts, *p = NULL;
if (u_abs_timeout) {
@@ -1142,7 +1142,7 @@ SYSCALL_DEFINE5(mq_timedsend, mqd_t, mqdes, const char __user *, u_msg_ptr,
SYSCALL_DEFINE5(mq_timedreceive, mqd_t, mqdes, char __user *, u_msg_ptr,
size_t, msg_len, unsigned int __user *, u_msg_prio,
- const struct timespec __user *, u_abs_timeout)
+ const struct __kernel_timespec __user *, u_abs_timeout)
{
struct timespec64 ts, *p = NULL;
if (u_abs_timeout) {
diff --git a/ipc/sem.c b/ipc/sem.c
index 8935cd8cf166..b951e25ba2db 100644
--- a/ipc/sem.c
+++ b/ipc/sem.c
@@ -2176,7 +2176,7 @@ static long do_semtimedop(int semid, struct sembuf __user *tsops,
}
long ksys_semtimedop(int semid, struct sembuf __user *tsops,
- unsigned int nsops, const struct timespec __user *timeout)
+ unsigned int nsops, const struct __kernel_timespec __user *timeout)
{
if (timeout) {
struct timespec64 ts;
@@ -2188,7 +2188,7 @@ long ksys_semtimedop(int semid, struct sembuf __user *tsops,
}
SYSCALL_DEFINE4(semtimedop, int, semid, struct sembuf __user *, tsops,
- unsigned int, nsops, const struct timespec __user *, timeout)
+ unsigned int, nsops, const struct __kernel_timespec __user *, timeout)
{
return ksys_semtimedop(semid, tsops, nsops, timeout);
}
diff --git a/ipc/util.h b/ipc/util.h
index acc5159e96d0..975c6de2df9d 100644
--- a/ipc/util.h
+++ b/ipc/util.h
@@ -251,7 +251,7 @@ static inline int compat_ipc_parse_version(int *cmd)
/* for __ARCH_WANT_SYS_IPC */
long ksys_semtimedop(int semid, struct sembuf __user *tsops,
unsigned int nsops,
- const struct timespec __user *timeout);
+ const struct __kernel_timespec __user *timeout);
long ksys_semget(key_t key, int nsems, int semflg);
long ksys_semctl(int semid, int semnum, int cmd, unsigned long arg);
long ksys_msgget(key_t key, int msgflg);
--
2.9.0
^ permalink raw reply related
* [PATCH v4 05/16] y2038: s390: Remove unneeded ipc uapi header files
From: Arnd Bergmann @ 2018-04-25 15:05 UTC (permalink / raw)
To: y2038, linux-kernel
Cc: linux-api, linux-arch, libc-alpha, tglx, deepa.kernel, viro,
ebiederm, albert.aribaud, linux-s390, schwidefsky, x86,
catalin.marinas, will.deacon, linux-mips, jhogan, ralf,
linuxppc-dev, sparclinux, zackw, noloader, Arnd Bergmann
In-Reply-To: <20180425132242.1500539-1-arnd@arndb.de>
The s390 msgbuf/sembuf/shmbuf header files are all identical to the
version from asm-generic.
This patch removes the files and replaces them with 'generic-y'
statements, to avoid having to modify each copy when we extend sysvipc
to deal with 64-bit time_t in 32-bit user space.
Note that unlike alpha and ia64, the ipcbuf.h header file is slightly
different here, so I'm leaving the private copy.
To deal with 32-bit compat tasks, we also have to adapt the definitions
of compat_{shm,sem,msg}id_ds to match the changes to the respective
asm-generic files.
Acked-by: Heiko Carstens <heiko.carstens@de.ibm.com>
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
---
arch/s390/include/asm/compat.h | 32 ++++++++++++------------
arch/s390/include/uapi/asm/Kbuild | 3 +++
arch/s390/include/uapi/asm/msgbuf.h | 38 ----------------------------
arch/s390/include/uapi/asm/sembuf.h | 30 -----------------------
arch/s390/include/uapi/asm/shmbuf.h | 49 -------------------------------------
5 files changed, 19 insertions(+), 133 deletions(-)
delete mode 100644 arch/s390/include/uapi/asm/msgbuf.h
delete mode 100644 arch/s390/include/uapi/asm/sembuf.h
delete mode 100644 arch/s390/include/uapi/asm/shmbuf.h
diff --git a/arch/s390/include/asm/compat.h b/arch/s390/include/asm/compat.h
index 501aaff85304..97db2fba546a 100644
--- a/arch/s390/include/asm/compat.h
+++ b/arch/s390/include/asm/compat.h
@@ -232,10 +232,10 @@ struct compat_ipc64_perm {
struct compat_semid64_ds {
struct compat_ipc64_perm sem_perm;
- compat_time_t sem_otime;
- compat_ulong_t __pad1;
- compat_time_t sem_ctime;
- compat_ulong_t __pad2;
+ compat_ulong_t sem_otime;
+ compat_ulong_t sem_otime_high;
+ compat_ulong_t sem_ctime;
+ compat_ulong_t sem_ctime_high;
compat_ulong_t sem_nsems;
compat_ulong_t __unused1;
compat_ulong_t __unused2;
@@ -243,12 +243,12 @@ struct compat_semid64_ds {
struct compat_msqid64_ds {
struct compat_ipc64_perm msg_perm;
- compat_time_t msg_stime;
- compat_ulong_t __pad1;
- compat_time_t msg_rtime;
- compat_ulong_t __pad2;
- compat_time_t msg_ctime;
- compat_ulong_t __pad3;
+ compat_ulong_t msg_stime;
+ compat_ulong_t msg_stime_high;
+ compat_ulong_t msg_rtime;
+ compat_ulong_t msg_rtime_high;
+ compat_ulong_t msg_ctime;
+ compat_ulong_t msg_ctime_high;
compat_ulong_t msg_cbytes;
compat_ulong_t msg_qnum;
compat_ulong_t msg_qbytes;
@@ -261,12 +261,12 @@ struct compat_msqid64_ds {
struct compat_shmid64_ds {
struct compat_ipc64_perm shm_perm;
compat_size_t shm_segsz;
- compat_time_t shm_atime;
- compat_ulong_t __pad1;
- compat_time_t shm_dtime;
- compat_ulong_t __pad2;
- compat_time_t shm_ctime;
- compat_ulong_t __pad3;
+ compat_ulong_t shm_atime;
+ compat_ulong_t shm_atime_high;
+ compat_ulong_t shm_dtime;
+ compat_ulong_t shm_dtime_high;
+ compat_ulong_t shm_ctime;
+ compat_ulong_t shm_ctime_high;
compat_pid_t shm_cpid;
compat_pid_t shm_lpid;
compat_ulong_t shm_nattch;
diff --git a/arch/s390/include/uapi/asm/Kbuild b/arch/s390/include/uapi/asm/Kbuild
index faef3f7e8353..e364873e0d10 100644
--- a/arch/s390/include/uapi/asm/Kbuild
+++ b/arch/s390/include/uapi/asm/Kbuild
@@ -9,9 +9,12 @@ generic-y += errno.h
generic-y += fcntl.h
generic-y += ioctl.h
generic-y += mman.h
+generic-y += msgbuf.h
generic-y += param.h
generic-y += poll.h
generic-y += resource.h
+generic-y += sembuf.h
+generic-y += shmbuf.h
generic-y += sockios.h
generic-y += swab.h
generic-y += termbits.h
diff --git a/arch/s390/include/uapi/asm/msgbuf.h b/arch/s390/include/uapi/asm/msgbuf.h
deleted file mode 100644
index 604f847cd68c..000000000000
--- a/arch/s390/include/uapi/asm/msgbuf.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
-#ifndef _S390_MSGBUF_H
-#define _S390_MSGBUF_H
-
-/*
- * The msqid64_ds structure for S/390 architecture.
- * Note extra padding because this structure is passed back and forth
- * between kernel and user space.
- *
- * Pad space is left for:
- * - 64-bit time_t to solve y2038 problem
- * - 2 miscellaneous 32-bit values
- */
-
-struct msqid64_ds {
- struct ipc64_perm msg_perm;
- __kernel_time_t msg_stime; /* last msgsnd time */
-#ifndef __s390x__
- unsigned long __unused1;
-#endif /* ! __s390x__ */
- __kernel_time_t msg_rtime; /* last msgrcv time */
-#ifndef __s390x__
- unsigned long __unused2;
-#endif /* ! __s390x__ */
- __kernel_time_t msg_ctime; /* last change time */
-#ifndef __s390x__
- unsigned long __unused3;
-#endif /* ! __s390x__ */
- unsigned long msg_cbytes; /* current number of bytes on queue */
- unsigned long msg_qnum; /* number of messages in queue */
- unsigned long msg_qbytes; /* max number of bytes on queue */
- __kernel_pid_t msg_lspid; /* pid of last msgsnd */
- __kernel_pid_t msg_lrpid; /* last receive pid */
- unsigned long __unused4;
- unsigned long __unused5;
-};
-
-#endif /* _S390_MSGBUF_H */
diff --git a/arch/s390/include/uapi/asm/sembuf.h b/arch/s390/include/uapi/asm/sembuf.h
deleted file mode 100644
index 3e917697b668..000000000000
--- a/arch/s390/include/uapi/asm/sembuf.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
-#ifndef _S390_SEMBUF_H
-#define _S390_SEMBUF_H
-
-/*
- * The semid64_ds structure for S/390 architecture.
- * Note extra padding because this structure is passed back and forth
- * between kernel and user space.
- *
- * Pad space is left for:
- * - 64-bit time_t to solve y2038 problem (for !__s390x__)
- * - 2 miscellaneous 32-bit values
- */
-
-struct semid64_ds {
- struct ipc64_perm sem_perm; /* permissions .. see ipc.h */
- __kernel_time_t sem_otime; /* last semop time */
-#ifndef __s390x__
- unsigned long __unused1;
-#endif /* ! __s390x__ */
- __kernel_time_t sem_ctime; /* last change time */
-#ifndef __s390x__
- unsigned long __unused2;
-#endif /* ! __s390x__ */
- unsigned long sem_nsems; /* no. of semaphores in array */
- unsigned long __unused3;
- unsigned long __unused4;
-};
-
-#endif /* _S390_SEMBUF_H */
diff --git a/arch/s390/include/uapi/asm/shmbuf.h b/arch/s390/include/uapi/asm/shmbuf.h
deleted file mode 100644
index 9cdce8d7ce60..000000000000
--- a/arch/s390/include/uapi/asm/shmbuf.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
-#ifndef _S390_SHMBUF_H
-#define _S390_SHMBUF_H
-
-/*
- * The shmid64_ds structure for S/390 architecture.
- * Note extra padding because this structure is passed back and forth
- * between kernel and user space.
- *
- * Pad space is left for:
- * - 64-bit time_t to solve y2038 problem (for !__s390x__)
- * - 2 miscellaneous 32-bit values
- */
-
-struct shmid64_ds {
- struct ipc64_perm shm_perm; /* operation perms */
- size_t shm_segsz; /* size of segment (bytes) */
- __kernel_time_t shm_atime; /* last attach time */
-#ifndef __s390x__
- unsigned long __unused1;
-#endif /* ! __s390x__ */
- __kernel_time_t shm_dtime; /* last detach time */
-#ifndef __s390x__
- unsigned long __unused2;
-#endif /* ! __s390x__ */
- __kernel_time_t shm_ctime; /* last change time */
-#ifndef __s390x__
- unsigned long __unused3;
-#endif /* ! __s390x__ */
- __kernel_pid_t shm_cpid; /* pid of creator */
- __kernel_pid_t shm_lpid; /* pid of last operator */
- unsigned long shm_nattch; /* no. of current attaches */
- unsigned long __unused4;
- unsigned long __unused5;
-};
-
-struct shminfo64 {
- unsigned long shmmax;
- unsigned long shmmin;
- unsigned long shmmni;
- unsigned long shmseg;
- unsigned long shmall;
- unsigned long __unused1;
- unsigned long __unused2;
- unsigned long __unused3;
- unsigned long __unused4;
-};
-
-#endif /* _S390_SHMBUF_H */
--
2.9.0
^ permalink raw reply related
* [PATCH v4 07/16] y2038: mips: Extend sysvipc data structures
From: Arnd Bergmann @ 2018-04-25 15:05 UTC (permalink / raw)
To: y2038, linux-kernel
Cc: linux-api, linux-arch, libc-alpha, tglx, deepa.kernel, viro,
ebiederm, albert.aribaud, linux-s390, schwidefsky, x86,
catalin.marinas, will.deacon, linux-mips, jhogan, ralf,
linuxppc-dev, sparclinux, zackw, noloader, Arnd Bergmann
In-Reply-To: <20180425132242.1500539-1-arnd@arndb.de>
MIPS is the weirdest case for sysvipc, because each of the
three data structures is done differently:
* msqid64_ds has padding in the right place so we could in theory
extend this one to just have 64-bit values instead of time_t.
As this does not work for most of the other combinations,
we just handle it in the common manner though.
* semid64_ds has no padding for 64-bit time_t, but has two reserved
'long' fields, which are sufficient to extend the sem_otime
and sem_ctime fields to 64 bit. In order to do this, the libc
implementation will have to copy the data into another structure
that has the fields in a different order. MIPS is the only
architecture with this problem, so this is best done in MIPS
specific libc code.
* shmid64_ds is slightly worse than that, because it has three
time_t fields but only two unused 32-bit words. As a workaround,
we extend each field only by 16 bits, ending up with 48-bit
timestamps that user space again has to work around by itself.
The compat versions of the data structures are changed in the
same way.
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
---
arch/mips/include/asm/compat.h | 40 ++++++++++++++------------
arch/mips/include/uapi/asm/msgbuf.h | 57 ++++++++++++++++++++++++-------------
arch/mips/include/uapi/asm/sembuf.h | 15 ++++++++--
arch/mips/include/uapi/asm/shmbuf.h | 23 +++++++++++++--
4 files changed, 94 insertions(+), 41 deletions(-)
diff --git a/arch/mips/include/asm/compat.h b/arch/mips/include/asm/compat.h
index 3e548ee99a2f..78675f19440f 100644
--- a/arch/mips/include/asm/compat.h
+++ b/arch/mips/include/asm/compat.h
@@ -37,9 +37,11 @@ typedef struct {
typedef s32 compat_timer_t;
typedef s32 compat_key_t;
+typedef s16 compat_short_t;
typedef s32 compat_int_t;
typedef s32 compat_long_t;
typedef s64 compat_s64;
+typedef u16 compat_ushort_t;
typedef u32 compat_uint_t;
typedef u32 compat_ulong_t;
typedef u64 compat_u64;
@@ -157,35 +159,35 @@ struct compat_ipc64_perm {
struct compat_semid64_ds {
struct compat_ipc64_perm sem_perm;
- compat_time_t sem_otime;
- compat_time_t sem_ctime;
+ compat_ulong_t sem_otime;
+ compat_ulong_t sem_ctime;
compat_ulong_t sem_nsems;
- compat_ulong_t __unused1;
- compat_ulong_t __unused2;
+ compat_ulong_t sem_otime_high;
+ compat_ulong_t sem_ctime_high;
};
struct compat_msqid64_ds {
struct compat_ipc64_perm msg_perm;
#ifndef CONFIG_CPU_LITTLE_ENDIAN
- compat_ulong_t __unused1;
+ compat_ulong_t msg_stime_high;
#endif
- compat_time_t msg_stime;
+ compat_ulong_t msg_stime;
#ifdef CONFIG_CPU_LITTLE_ENDIAN
- compat_ulong_t __unused1;
+ compat_ulong_t msg_stime_high;
#endif
#ifndef CONFIG_CPU_LITTLE_ENDIAN
- compat_ulong_t __unused2;
+ compat_ulong_t msg_rtime_high;
#endif
- compat_time_t msg_rtime;
+ compat_ulong_t msg_rtime;
#ifdef CONFIG_CPU_LITTLE_ENDIAN
- compat_ulong_t __unused2;
+ compat_ulong_t msg_rtime_high;
#endif
#ifndef CONFIG_CPU_LITTLE_ENDIAN
- compat_ulong_t __unused3;
+ compat_ulong_t msg_ctime_high;
#endif
- compat_time_t msg_ctime;
+ compat_ulong_t msg_ctime;
#ifdef CONFIG_CPU_LITTLE_ENDIAN
- compat_ulong_t __unused3;
+ compat_ulong_t msg_ctime_high;
#endif
compat_ulong_t msg_cbytes;
compat_ulong_t msg_qnum;
@@ -199,14 +201,16 @@ struct compat_msqid64_ds {
struct compat_shmid64_ds {
struct compat_ipc64_perm shm_perm;
compat_size_t shm_segsz;
- compat_time_t shm_atime;
- compat_time_t shm_dtime;
- compat_time_t shm_ctime;
+ compat_ulong_t shm_atime;
+ compat_ulong_t shm_dtime;
+ compat_ulong_t shm_ctime;
compat_pid_t shm_cpid;
compat_pid_t shm_lpid;
compat_ulong_t shm_nattch;
- compat_ulong_t __unused1;
- compat_ulong_t __unused2;
+ compat_ushort_t shm_atime_high;
+ compat_ushort_t shm_dtime_high;
+ compat_ushort_t shm_ctime_high;
+ compat_ushort_t __unused2;
};
/* MIPS has unusual order of fields in stack_t */
diff --git a/arch/mips/include/uapi/asm/msgbuf.h b/arch/mips/include/uapi/asm/msgbuf.h
index eb4d0f9d7364..46aa15b13e4e 100644
--- a/arch/mips/include/uapi/asm/msgbuf.h
+++ b/arch/mips/include/uapi/asm/msgbuf.h
@@ -9,33 +9,15 @@
* between kernel and user space.
*
* Pad space is left for:
- * - extension of time_t to 64-bit on 32-bitsystem to solve the y2038 problem
* - 2 miscellaneous unsigned long values
*/
+#if defined(__mips64)
struct msqid64_ds {
struct ipc64_perm msg_perm;
-#if !defined(__mips64) && defined(__MIPSEB__)
- unsigned long __unused1;
-#endif
__kernel_time_t msg_stime; /* last msgsnd time */
-#if !defined(__mips64) && defined(__MIPSEL__)
- unsigned long __unused1;
-#endif
-#if !defined(__mips64) && defined(__MIPSEB__)
- unsigned long __unused2;
-#endif
__kernel_time_t msg_rtime; /* last msgrcv time */
-#if !defined(__mips64) && defined(__MIPSEL__)
- unsigned long __unused2;
-#endif
-#if !defined(__mips64) && defined(__MIPSEB__)
- unsigned long __unused3;
-#endif
__kernel_time_t msg_ctime; /* last change time */
-#if !defined(__mips64) && defined(__MIPSEL__)
- unsigned long __unused3;
-#endif
unsigned long msg_cbytes; /* current number of bytes on queue */
unsigned long msg_qnum; /* number of messages in queue */
unsigned long msg_qbytes; /* max number of bytes on queue */
@@ -44,5 +26,42 @@ struct msqid64_ds {
unsigned long __unused4;
unsigned long __unused5;
};
+#elif defined (__MIPSEB__)
+struct msqid64_ds {
+ struct ipc64_perm msg_perm;
+ unsigned long msg_stime_high;
+ unsigned long msg_stime; /* last msgsnd time */
+ unsigned long msg_rtime_high;
+ unsigned long msg_rtime; /* last msgrcv time */
+ unsigned long msg_ctime_high;
+ unsigned long msg_ctime; /* last change time */
+ unsigned long msg_cbytes; /* current number of bytes on queue */
+ unsigned long msg_qnum; /* number of messages in queue */
+ unsigned long msg_qbytes; /* max number of bytes on queue */
+ __kernel_pid_t msg_lspid; /* pid of last msgsnd */
+ __kernel_pid_t msg_lrpid; /* last receive pid */
+ unsigned long __unused4;
+ unsigned long __unused5;
+};
+#elif defined (__MIPSEL__)
+struct msqid64_ds {
+ struct ipc64_perm msg_perm;
+ unsigned long msg_stime; /* last msgsnd time */
+ unsigned long msg_stime_high;
+ unsigned long msg_rtime; /* last msgrcv time */
+ unsigned long msg_rtime_high;
+ unsigned long msg_ctime; /* last change time */
+ unsigned long msg_ctime_high;
+ unsigned long msg_cbytes; /* current number of bytes on queue */
+ unsigned long msg_qnum; /* number of messages in queue */
+ unsigned long msg_qbytes; /* max number of bytes on queue */
+ __kernel_pid_t msg_lspid; /* pid of last msgsnd */
+ __kernel_pid_t msg_lrpid; /* last receive pid */
+ unsigned long __unused4;
+ unsigned long __unused5;
+};
+#else
+#warning no endianess set
+#endif
#endif /* _ASM_MSGBUF_H */
diff --git a/arch/mips/include/uapi/asm/sembuf.h b/arch/mips/include/uapi/asm/sembuf.h
index 2c0f507ab7d1..60c89e6cb25b 100644
--- a/arch/mips/include/uapi/asm/sembuf.h
+++ b/arch/mips/include/uapi/asm/sembuf.h
@@ -7,10 +7,11 @@
* Note extra padding because this structure is passed back and forth
* between kernel and user space.
*
- * Pad space is left for:
- * - 2 miscellaneous 64-bit values
+ * Pad space is left for 2 miscellaneous 64-bit values on mips64,
+ * but used for the upper 32 bit of the time values on mips32.
*/
+#ifdef __mips64
struct semid64_ds {
struct ipc64_perm sem_perm; /* permissions .. see ipc.h */
__kernel_time_t sem_otime; /* last semop time */
@@ -19,5 +20,15 @@ struct semid64_ds {
unsigned long __unused1;
unsigned long __unused2;
};
+#else
+struct semid64_ds {
+ struct ipc64_perm sem_perm; /* permissions .. see ipc.h */
+ unsigned long sem_otime; /* last semop time */
+ unsigned long sem_ctime; /* last change time */
+ unsigned long sem_nsems; /* no. of semaphores in array */
+ unsigned long sem_otime_high;
+ unsigned long sem_ctime_high;
+};
+#endif
#endif /* _ASM_SEMBUF_H */
diff --git a/arch/mips/include/uapi/asm/shmbuf.h b/arch/mips/include/uapi/asm/shmbuf.h
index 379e6bca518b..9b9bba3401f2 100644
--- a/arch/mips/include/uapi/asm/shmbuf.h
+++ b/arch/mips/include/uapi/asm/shmbuf.h
@@ -7,10 +7,13 @@
* Note extra padding because this structure is passed back and forth
* between kernel and user space.
*
- * Pad space is left for:
- * - 2 miscellaneous 32-bit rsp. 64-bit values
+ * As MIPS was lacking proper padding after shm_?time, we use 48 bits
+ * of the padding at the end to store a few additional bits of the time.
+ * libc implementations need to take care to convert this into a proper
+ * data structure when moving to 64-bit time_t.
*/
+#ifdef __mips64
struct shmid64_ds {
struct ipc64_perm shm_perm; /* operation perms */
size_t shm_segsz; /* size of segment (bytes) */
@@ -23,6 +26,22 @@ struct shmid64_ds {
unsigned long __unused1;
unsigned long __unused2;
};
+#else
+struct shmid64_ds {
+ struct ipc64_perm shm_perm; /* operation perms */
+ size_t shm_segsz; /* size of segment (bytes) */
+ unsigned long shm_atime; /* last attach time */
+ unsigned long shm_dtime; /* last detach time */
+ unsigned long shm_ctime; /* last change time */
+ __kernel_pid_t shm_cpid; /* pid of creator */
+ __kernel_pid_t shm_lpid; /* pid of last operator */
+ unsigned long shm_nattch; /* no. of current attaches */
+ unsigned short shm_atime_high;
+ unsigned short shm_dtime_high;
+ unsigned short shm_ctime_high;
+ unsigned short __unused1;
+};
+#endif
struct shminfo64 {
unsigned long shmmax;
--
2.9.0
^ permalink raw reply related
* [PATCH v4 06/16] y2038: arm64: Extend sysvipc compat data structures
From: Arnd Bergmann @ 2018-04-25 15:05 UTC (permalink / raw)
To: y2038, linux-kernel
Cc: linux-api, linux-arch, libc-alpha, tglx, deepa.kernel, viro,
ebiederm, albert.aribaud, linux-s390, schwidefsky, x86,
catalin.marinas, will.deacon, linux-mips, jhogan, ralf,
linuxppc-dev, sparclinux, zackw, noloader, Arnd Bergmann
In-Reply-To: <20180425132242.1500539-1-arnd@arndb.de>
Both 32-bit amd 64-bit ARM use the asm-generic header files for their
sysvipc data structures, so no special care is needed to make those
work beyond y2038, with the one exception of compat mode: Since there
is no asm-generic definition of the compat mode IPC structures, ARM64
provides its own copy, and we make those match the changes in the native
asm-generic header files.
There is sufficient padding in these data structures to extend all
timestamps to 64 bit, but on big-endian ARM kernels, the padding
is in the wrong place, so the C library has to ensure it reassembles
a 64-bit time_t correctly.
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
---
arch/arm64/include/asm/compat.h | 32 ++++++++++++++++----------------
1 file changed, 16 insertions(+), 16 deletions(-)
diff --git a/arch/arm64/include/asm/compat.h b/arch/arm64/include/asm/compat.h
index 0030f79808b3..1a037b94eba1 100644
--- a/arch/arm64/include/asm/compat.h
+++ b/arch/arm64/include/asm/compat.h
@@ -181,10 +181,10 @@ struct compat_ipc64_perm {
struct compat_semid64_ds {
struct compat_ipc64_perm sem_perm;
- compat_time_t sem_otime;
- compat_ulong_t __unused1;
- compat_time_t sem_ctime;
- compat_ulong_t __unused2;
+ compat_ulong_t sem_otime;
+ compat_ulong_t sem_otime_high;
+ compat_ulong_t sem_ctime;
+ compat_ulong_t sem_ctime_high;
compat_ulong_t sem_nsems;
compat_ulong_t __unused3;
compat_ulong_t __unused4;
@@ -192,12 +192,12 @@ struct compat_semid64_ds {
struct compat_msqid64_ds {
struct compat_ipc64_perm msg_perm;
- compat_time_t msg_stime;
- compat_ulong_t __unused1;
- compat_time_t msg_rtime;
- compat_ulong_t __unused2;
- compat_time_t msg_ctime;
- compat_ulong_t __unused3;
+ compat_ulong_t msg_stime;
+ compat_ulong_t msg_stime_high;
+ compat_ulong_t msg_rtime;
+ compat_ulong_t msg_rtime_high;
+ compat_ulong_t msg_ctime;
+ compat_ulong_t msg_ctime_high;
compat_ulong_t msg_cbytes;
compat_ulong_t msg_qnum;
compat_ulong_t msg_qbytes;
@@ -210,12 +210,12 @@ struct compat_msqid64_ds {
struct compat_shmid64_ds {
struct compat_ipc64_perm shm_perm;
compat_size_t shm_segsz;
- compat_time_t shm_atime;
- compat_ulong_t __unused1;
- compat_time_t shm_dtime;
- compat_ulong_t __unused2;
- compat_time_t shm_ctime;
- compat_ulong_t __unused3;
+ compat_ulong_t shm_atime;
+ compat_ulong_t shm_atime_high;
+ compat_ulong_t shm_dtime;
+ compat_ulong_t shm_dtime_high;
+ compat_ulong_t shm_ctime;
+ compat_ulong_t shm_ctime_high;
compat_pid_t shm_cpid;
compat_pid_t shm_lpid;
compat_ulong_t shm_nattch;
--
2.9.0
^ permalink raw reply related
* [PATCH v2 0/1] misc: IBM Virtual Management Channel Driver (VMC)
From: Bryant G. Ly @ 2018-04-25 21:32 UTC (permalink / raw)
To: benh, mpe, gregkh, arnd
Cc: corbet, seroyer, mrochs, adreznec, fbarrat, davem, linus.walleij,
akpm, rdunlap, mikey, pombredanne, tlfalcon, msuchanek, linux-doc,
linuxppc-dev, tomburks, Bryant G. Ly
Steven Royer had previously attempted to upstream this
driver two years ago, but never got the chance to address
the concerns from Greg Kroah-Hartman.
The thread with the initial upstream is:
https://lkml.org/lkml/2016/2/16/918
I have addressed the following:
Version 1:
- Documentation
- Use of dev_dbg instead of pr_dbg
- Change to misc class
- Fixed memory barrier usages
- Addressed styling, checkpatch, renaming of functions
- General fixes to the driver to make it more inline with
existing upstream drivers.
Version 2:
- Changed Documentation from .rst to .txt and addressed
small changes in documentation per request from Randy.
- Clarified Documentation based upon Linus Walleij's
comments
- Fixed kbuild warning in regards to unititialized use of
rc
Bryant G. Ly (1):
misc: IBM Virtual Management Channel Driver (VMC)
Documentation/ioctl/ioctl-number.txt | 1 +
Documentation/misc-devices/ibmvmc.rst | 226 +++
MAINTAINERS | 6 +
arch/powerpc/include/asm/hvcall.h | 1 +
drivers/misc/Kconfig | 14 +
drivers/misc/Makefile | 1 +
drivers/misc/ibmvmc.c | 2418 +++++++++++++++++++++++++++++++++
drivers/misc/ibmvmc.h | 209 +++
8 files changed, 2876 insertions(+)
create mode 100644 Documentation/misc-devices/ibmvmc.rst
create mode 100644 drivers/misc/ibmvmc.c
create mode 100644 drivers/misc/ibmvmc.h
--
2.7.2
^ permalink raw reply
* [PATCH v2 1/1] misc: IBM Virtual Management Channel Driver (VMC)
From: Bryant G. Ly @ 2018-04-25 21:32 UTC (permalink / raw)
To: benh, mpe, gregkh, arnd
Cc: corbet, seroyer, mrochs, adreznec, fbarrat, davem, linus.walleij,
akpm, rdunlap, mikey, pombredanne, tlfalcon, msuchanek, linux-doc,
linuxppc-dev, tomburks, Bryant G. Ly
In-Reply-To: <1524691977-1456-1-git-send-email-bryantly@linux.vnet.ibm.com>
This driver is a logical device which provides an
interface between the hypervisor and a management
partition. This interface is like a message
passing interface. This management partition
is intended to provide an alternative to HMC-based
system management.
VMC enables the Management LPAR to provide basic
logical partition functions:
- Logical Partition Configuration
- Boot, start, and stop actions for individual
partitions
- Display of partition status
- Management of virtual Ethernet
- Management of virtual Storage
- Basic system management
This driver is to be used for the POWER Virtual
Management Channel Virtual Adapter on the PowerPC
platform. It provides a character device which
allows for both request/response and async message
support through the /dev/ibmvmc node.
Signed-off-by: Bryant G. Ly <bryantly@linux.vnet.ibm.com>
Reviewed-by: Steven Royer <seroyer@linux.vnet.ibm.com>
Reviewed-by: Adam Reznechek <adreznec@linux.vnet.ibm.com>
Reviewed-by: Randy Dunlap <rdunlap@infradead.org>
Tested-by: Taylor Jakobson <tjakobs@us.ibm.com>
Tested-by: Brad Warrum <bwarrum@us.ibm.com>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Michael Ellerman <mpe@ellerman.id.au>
---
Documentation/ioctl/ioctl-number.txt | 1 +
Documentation/misc-devices/ibmvmc.rst | 226 +++
MAINTAINERS | 6 +
arch/powerpc/include/asm/hvcall.h | 1 +
drivers/misc/Kconfig | 14 +
drivers/misc/Makefile | 1 +
drivers/misc/ibmvmc.c | 2418 +++++++++++++++++++++++++++++++++
drivers/misc/ibmvmc.h | 209 +++
8 files changed, 2876 insertions(+)
create mode 100644 Documentation/misc-devices/ibmvmc.rst
create mode 100644 drivers/misc/ibmvmc.c
create mode 100644 drivers/misc/ibmvmc.h
diff --git a/Documentation/ioctl/ioctl-number.txt b/Documentation/ioctl/ioctl-number.txt
index 84bb74d..9851cee 100644
--- a/Documentation/ioctl/ioctl-number.txt
+++ b/Documentation/ioctl/ioctl-number.txt
@@ -329,6 +329,7 @@ Code Seq#(hex) Include File Comments
0xCA 80-BF uapi/scsi/cxlflash_ioctl.h
0xCB 00-1F CBM serial IEC bus in development:
<mailto:michael.klein@puffin.lb.shuttle.de>
+0xCC 00-0F drivers/misc/ibmvmc.h pseries VMC driver
0xCD 01 linux/reiserfs_fs.h
0xCF 02 fs/cifs/ioctl.c
0xDB 00-0F drivers/char/mwave/mwavepub.h
diff --git a/Documentation/misc-devices/ibmvmc.rst b/Documentation/misc-devices/ibmvmc.rst
new file mode 100644
index 0000000..46ded79
--- /dev/null
+++ b/Documentation/misc-devices/ibmvmc.rst
@@ -0,0 +1,226 @@
+.. SPDX-License-Identifier: GPL-2.0+
+======================================================
+IBM Virtual Management Channel Kernel Driver (IBMVMC)
+======================================================
+
+:Authors:
+ Dave Engebretsen <engebret@us.ibm.com>,
+ Adam Reznechek <adreznec@linux.vnet.ibm.com>,
+ Steven Royer <seroyer@linux.vnet.ibm.com>,
+ Bryant G. Ly <bryantly@linux.vnet.ibm.com>,
+
+Introduction
+============
+
+Note: Knowledge of virtualization technology is required to understand
+this document.
+
+A good reference document would be:
+
+https://openpowerfoundation.org/wp-content/uploads/2016/05/LoPAPR_DRAFT_v11_24March2016_cmt1.pdf
+
+The Virtual Management Channel (VMC) is a logical device which provides an
+interface between the hypervisor and a management partition. This interface
+is like a message passing interface. This management partition is intended
+to provide an alternative to systems that use a Hardware Management
+Console (HMC) - based system management.
+
+The primary hardware management solution that is developed by IBM relies
+on an appliance server named the Hardware Management Console (HMC),
+packaged as an external tower or rack-mounted personal computer. In a
+Power Systems environment, a single HMC can manage multiple POWER
+processor-based systems.
+
+Management Application
+----------------------
+
+In the management partition, a management application exists which enables
+a system administrator to configure the system’s partitioning
+characteristics via a command line interface (CLI) or Representational
+State Transfer Application (REST API's).
+
+The management application runs on a Linux logical partition on a
+POWER8 or newer processor-based server that is virtualized by PowerVM.
+System configuration, maintenance, and control functions which
+traditionally require an HMC can be implemented in the management
+application using a combination of HMC to hypervisor interfaces and
+existing operating system methods. This tool provides a subset of the
+functions implemented by the HMC and enables basic partition configuration.
+The set of HMC to hypervisor messages supported by the management
+application component are passed to the hypervisor over a VMC interface,
+which is defined below.
+
+The VMC enables the management partition to provide basic partitioning
+functions:
+
+- Logical Partitioning Configuration
+- Start, and stop actions for individual partitions
+- Display of partition status
+- Management of virtual Ethernet
+- Management of virtual Storage
+- Basic system management
+
+Virtual Management Channel (VMC)
+--------------------------------
+
+A logical device, called the Virtual Management Channel (VMC), is defined
+for communicating between the management application and the hypervisor. It
+basically creates the pipes that enable virtualization management
+software. This device is presented to a designated management partition as
+a virtual device.
+
+This communication device uses Command/Response Queue (CRQ) and the
+Remote Direct Memory Access (RDMA) interfaces. A three-way handshake is
+defined that must take place to establish that both the hypervisor and
+management partition sides of the channel are running prior to
+sending/receiving any of the protocol messages.
+
+This driver also utilizes Transport Event CRQs. CRQ messages are sent
+when the hypervisor detects one of the peer partitions has abnormally
+terminated, or one side has called H_FREE_CRQ to close their CRQ.
+Two new classes of CRQ messages are introduced for the VMC device. VMC
+Administrative messages are used for each partition using the VMC to
+communicate capabilities to their partner. HMC Interface messages are used
+for the actual flow of HMC messages between the management partition and
+the hypervisor. As most HMC messages far exceed the size of a CRQ buffer,
+a virtual DMA (RMDA) of the HMC message data is done prior to each HMC
+Interface CRQ message. Only the management partition drives RDMA
+operations; hypervisors never directly cause the movement of message data.
+
+
+Terminology
+-----------
+RDMA
+ Remote Direct Memory Access is DMA transfer from the server to its
+ client or from the server to its partner partition. DMA refers
+ to both physical I/O to and from memory operations and to memory
+ to memory move operations.
+CRQ
+ Command/Response Queue a facility which is used to communicate
+ between partner partitions. Transport events which are signaled
+ from the hypervisor to partition are also reported in this queue.
+
+Example Management Partition VMC Driver Interface
+=================================================
+
+This section provides an example for the management application
+implementation where a device driver is used to interface to the VMC
+device. This driver consists of a new device, for example /dev/ibmvmc,
+which provides interfaces to open, close, read, write, and perform
+ioctl’s against the VMC device.
+
+VMC Interface Initialization
+----------------------------
+
+The device driver is responsible for initializing the VMC when the driver
+is loaded. It first creates and initializes the CRQ. Next, an exchange of
+VMC capabilities is performed to indicate the code version and number of
+resources available in both the management partition and the hypervisor.
+Finally, the hypervisor requests that the management partition create an
+initial pool of VMC buffers, one buffer for each possible HMC connection,
+which will be used for management application session initialization.
+Prior to completion of this initialization sequence, the device returns
+EBUSY to open() calls. EIO is returned for all open() failures.
+
+::
+
+ Management Partition Hypervisor
+ CRQ INIT
+ ---------------------------------------->
+ CRQ INIT COMPLETE
+ <----------------------------------------
+ CAPABILITIES
+ ---------------------------------------->
+ CAPABILITIES RESPONSE
+ <----------------------------------------
+ ADD BUFFER (HMC IDX=0,1,..) _
+ <---------------------------------------- |
+ ADD BUFFER RESPONSE | - Perform # HMCs Iterations
+ ----------------------------------------> -
+
+VMC Interface Open
+------------------
+
+After the basic VMC channel has been initialized, an HMC session level
+connection can be established. The application layer performs an open() to
+the VMC device and executes an ioctl() against it, indicating the HMC ID
+(32 bytes of data) for this session. If the VMC device is in an invalid
+state, EIO will be returned for the ioctl(). The device driver creates a
+new HMC session value (ranging from 1 to 255) and HMC index value (starting
+at index 0 and ranging to 254) for this HMC ID. The driver then does an
+RDMA of the HMC ID to the hypervisor, and then sends an Interface Open
+message to the hypervisor to establish the session over the VMC. After the
+hypervisor receives this information, it sends Add Buffer messages to the
+management partition to seed an initial pool of buffers for the new HMC
+connection. Finally, the hypervisor sends an Interface Open Response
+message, to indicate that it is ready for normal runtime messaging. The
+following illustrates this VMC flow:
+
+::
+
+ Management Partition Hypervisor
+ RDMA HMC ID
+ ---------------------------------------->
+ Interface Open
+ ---------------------------------------->
+ Add Buffer _
+ <---------------------------------------- |
+ Add Buffer Response | - Perform N Iterations
+ ----------------------------------------> -
+ Interface Open Response
+ <----------------------------------------
+
+VMC Interface Runtime
+---------------------
+
+During normal runtime, the management application and the hypervisor
+exchange HMC messages via the Signal VMC message and RDMA operations. When
+sending data to the hypervisor, the management application performs a
+write() to the VMC device, and the driver RDMA’s the data to the hypervisor
+and then sends a Signal Message. If a write() is attempted before VMC
+device buffers have been made available by the hypervisor, or no buffers
+are currently available, EBUSY is returned in response to the write(). A
+write() will return EIO for all other errors, such as an invalid device
+state. When the hypervisor sends a message to the management, the data is
+put into a VMC buffer and an Signal Message is sent to the VMC driver in
+the management partition. The driver RDMA’s the buffer into the partition
+and passes the data up to the appropriate management application via a
+read() to the VMC device. The read() request blocks if there is no buffer
+available to read. The management application may use select() to wait for
+the VMC device to become ready with data to read.
+
+::
+
+ Management Partition Hypervisor
+ MSG RDMA
+ ---------------------------------------->
+ SIGNAL MSG
+ ---------------------------------------->
+ SIGNAL MSG
+ <----------------------------------------
+ MSG RDMA
+ <----------------------------------------
+
+VMC Interface Close
+-------------------
+
+HMC session level connections are closed by the management partition when
+the application layer performs a close() against the device. This action
+results in an Interface Close message flowing to the hypervisor, which
+causes the session to be terminated. The device driver must free any
+storage allocated for buffers for this HMC connection.
+
+::
+
+ Management Partition Hypervisor
+ INTERFACE CLOSE
+ ---------------------------------------->
+ INTERFACE CLOSE RESPONSE
+ <----------------------------------------
+
+Additional Information
+======================
+
+For more information on the documentation for CRQ Messages, VMC Messages,
+HMC interface Buffers, and signal messages please refer to the Linux on
+Power Architecture Platform Reference. Section F.
diff --git a/MAINTAINERS b/MAINTAINERS
index c7182d2..79969f9 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -6721,6 +6721,12 @@ L: linux-scsi@vger.kernel.org
S: Supported
F: drivers/scsi/ibmvscsi/ibmvfc*
+IBM Power Virtual Management Channel Driver
+M: Bryant G. Ly <bryantly@linux.vnet.ibm.com>
+M: Steven Royer <seroyer@linux.vnet.ibm.com>
+S: Supported
+F: drivers/misc/ibmvmc.*
+
IBM Power Virtual SCSI Device Drivers
M: Tyrel Datwyler <tyreld@linux.vnet.ibm.com>
L: linux-scsi@vger.kernel.org
diff --git a/arch/powerpc/include/asm/hvcall.h b/arch/powerpc/include/asm/hvcall.h
index 2e2ddda..662c834 100644
--- a/arch/powerpc/include/asm/hvcall.h
+++ b/arch/powerpc/include/asm/hvcall.h
@@ -279,6 +279,7 @@
#define H_GET_MPP_X 0x314
#define H_SET_MODE 0x31C
#define H_CLEAR_HPT 0x358
+#define H_REQUEST_VMC 0x360
#define H_RESIZE_HPT_PREPARE 0x36C
#define H_RESIZE_HPT_COMMIT 0x370
#define H_REGISTER_PROC_TBL 0x37C
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index 5d71300..3726eac 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -113,6 +113,20 @@ config IBM_ASM
for information on the specific driver level and support statement
for your IBM server.
+config IBMVMC
+ tristate "IBM Virtual Management Channel support"
+ depends on PPC_PSERIES
+ help
+ This is the IBM POWER Virtual Management Channel
+
+ This driver is to be used for the POWER Virtual
+ Management Channel virtual adapter on the PowerVM
+ platform. It provides both request/response and
+ async message support through the /dev/ibmvmc node.
+
+ To compile this driver as a module, choose M here: the
+ module will be called ibmvmc.
+
config PHANTOM
tristate "Sensable PHANToM (PCI)"
depends on PCI
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index 20be70c..af22bbc 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -4,6 +4,7 @@
#
obj-$(CONFIG_IBM_ASM) += ibmasm/
+obj-$(CONFIG_IBMVMC) += ibmvmc.o
obj-$(CONFIG_AD525X_DPOT) += ad525x_dpot.o
obj-$(CONFIG_AD525X_DPOT_I2C) += ad525x_dpot-i2c.o
obj-$(CONFIG_AD525X_DPOT_SPI) += ad525x_dpot-spi.o
diff --git a/drivers/misc/ibmvmc.c b/drivers/misc/ibmvmc.c
new file mode 100644
index 0000000..fb83d13
--- /dev/null
+++ b/drivers/misc/ibmvmc.c
@@ -0,0 +1,2418 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * IBM Power Systems Virtual Management Channel Support.
+ *
+ * Copyright (c) 2004, 2018 IBM Corp.
+ * Dave Engebretsen engebret@us.ibm.com
+ * Steven Royer seroyer@linux.vnet.ibm.com
+ * Adam Reznechek adreznec@linux.vnet.ibm.com
+ * Bryant G. Ly <bryantly@linux.vnet.ibm.com>
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/kthread.h>
+#include <linux/major.h>
+#include <linux/string.h>
+#include <linux/fcntl.h>
+#include <linux/slab.h>
+#include <linux/poll.h>
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/percpu.h>
+#include <linux/delay.h>
+#include <linux/uaccess.h>
+#include <linux/io.h>
+#include <linux/miscdevice.h>
+#include <linux/sched/signal.h>
+
+#include <asm/byteorder.h>
+#include <asm/irq.h>
+#include <asm/vio.h>
+
+#include "ibmvmc.h"
+
+#define IBMVMC_DRIVER_VERSION "1.0"
+
+/*
+ * Static global variables
+ */
+static DECLARE_WAIT_QUEUE_HEAD(ibmvmc_read_wait);
+
+static const char ibmvmc_driver_name[] = "ibmvmc";
+
+static struct ibmvmc_struct ibmvmc;
+static struct ibmvmc_hmc hmcs[MAX_HMCS];
+static struct crq_server_adapter ibmvmc_adapter;
+
+static int ibmvmc_max_buf_pool_size = DEFAULT_BUF_POOL_SIZE;
+static int ibmvmc_max_hmcs = DEFAULT_HMCS;
+static int ibmvmc_max_mtu = DEFAULT_MTU;
+
+static inline long h_copy_rdma(s64 length, u64 sliobn, u64 slioba,
+ u64 dliobn, u64 dlioba)
+{
+ long rc = 0;
+
+ /* Ensure all writes to source memory are visible before hcall */
+ dma_wmb();
+ pr_debug("ibmvmc: h_copy_rdma(0x%llx, 0x%llx, 0x%llx, 0x%llx, 0x%llx\n",
+ length, sliobn, slioba, dliobn, dlioba);
+ rc = plpar_hcall_norets(H_COPY_RDMA, length, sliobn, slioba,
+ dliobn, dlioba);
+ pr_debug("ibmvmc: h_copy_rdma rc = 0x%lx\n", rc);
+
+ return rc;
+}
+
+static inline void h_free_crq(uint32_t unit_address)
+{
+ long rc = 0;
+
+ do {
+ if (H_IS_LONG_BUSY(rc))
+ msleep(get_longbusy_msecs(rc));
+
+ rc = plpar_hcall_norets(H_FREE_CRQ, unit_address);
+ } while ((rc == H_BUSY) || (H_IS_LONG_BUSY(rc)));
+}
+
+/**
+ * h_request_vmc: - request a hypervisor virtual management channel device
+ * @vmc_index: drc index of the vmc device created
+ *
+ * Requests the hypervisor create a new virtual management channel device,
+ * allowing this partition to send hypervisor virtualization control
+ * commands.
+ *
+ * Return:
+ * 0 - Success
+ * Non-zero - Failure
+ */
+static inline long h_request_vmc(u32 *vmc_index)
+{
+ long rc = 0;
+ unsigned long retbuf[PLPAR_HCALL_BUFSIZE];
+
+ do {
+ if (H_IS_LONG_BUSY(rc))
+ msleep(get_longbusy_msecs(rc));
+
+ /* Call to request the VMC device from phyp */
+ rc = plpar_hcall(H_REQUEST_VMC, retbuf);
+ pr_debug("ibmvmc: %s rc = 0x%lx\n", __func__, rc);
+ *vmc_index = retbuf[0];
+ } while ((rc == H_BUSY) || (H_IS_LONG_BUSY(rc)));
+
+ return rc;
+}
+
+/* routines for managing a command/response queue */
+/**
+ * ibmvmc_handle_event: - Interrupt handler for crq events
+ * @irq: number of irq to handle, not used
+ * @dev_instance: crq_server_adapter that received interrupt
+ *
+ * Disables interrupts and schedules ibmvmc_task
+ *
+ * Always returns IRQ_HANDLED
+ */
+static irqreturn_t ibmvmc_handle_event(int irq, void *dev_instance)
+{
+ struct crq_server_adapter *adapter =
+ (struct crq_server_adapter *)dev_instance;
+
+ vio_disable_interrupts(to_vio_dev(adapter->dev));
+ tasklet_schedule(&adapter->work_task);
+
+ return IRQ_HANDLED;
+}
+
+/**
+ * ibmvmc_release_crq_queue - Release CRQ Queue
+ *
+ * @adapter: crq_server_adapter struct
+ *
+ * Return:
+ * 0 - Success
+ * Non-Zero - Failure
+ */
+static void ibmvmc_release_crq_queue(struct crq_server_adapter *adapter)
+{
+ struct vio_dev *vdev = to_vio_dev(adapter->dev);
+ struct crq_queue *queue = &adapter->queue;
+
+ free_irq(vdev->irq, (void *)adapter);
+ tasklet_kill(&adapter->work_task);
+
+ if (adapter->reset_task)
+ kthread_stop(adapter->reset_task);
+
+ h_free_crq(vdev->unit_address);
+ dma_unmap_single(adapter->dev,
+ queue->msg_token,
+ queue->size * sizeof(*queue->msgs), DMA_BIDIRECTIONAL);
+ free_page((unsigned long)queue->msgs);
+}
+
+/**
+ * ibmvmc_reset_crq_queue - Reset CRQ Queue
+ *
+ * @adapter: crq_server_adapter struct
+ *
+ * This function calls h_free_crq and then calls H_REG_CRQ and does all the
+ * bookkeeping to get us back to where we can communicate.
+ *
+ * Return:
+ * 0 - Success
+ * Non-Zero - Failure
+ */
+static int ibmvmc_reset_crq_queue(struct crq_server_adapter *adapter)
+{
+ struct vio_dev *vdev = to_vio_dev(adapter->dev);
+ struct crq_queue *queue = &adapter->queue;
+ int rc = 0;
+
+ /* Close the CRQ */
+ h_free_crq(vdev->unit_address);
+
+ /* Clean out the queue */
+ memset(queue->msgs, 0x00, PAGE_SIZE);
+ queue->cur = 0;
+
+ /* And re-open it again */
+ rc = plpar_hcall_norets(H_REG_CRQ,
+ vdev->unit_address,
+ queue->msg_token, PAGE_SIZE);
+ if (rc == 2)
+ /* Adapter is good, but other end is not ready */
+ dev_warn(adapter->dev, "Partner adapter not ready\n");
+ else if (rc != 0)
+ dev_err(adapter->dev, "couldn't register crq--rc 0x%x\n", rc);
+
+ return rc;
+}
+
+/**
+ * crq_queue_next_crq: - Returns the next entry in message queue
+ * @queue: crq_queue to use
+ *
+ * Returns pointer to next entry in queue, or NULL if there are no new
+ * entried in the CRQ.
+ */
+static struct ibmvmc_crq_msg *crq_queue_next_crq(struct crq_queue *queue)
+{
+ struct ibmvmc_crq_msg *crq;
+ unsigned long flags;
+
+ spin_lock_irqsave(&queue->lock, flags);
+ crq = &queue->msgs[queue->cur];
+ if (crq->valid & 0x80) {
+ if (++queue->cur == queue->size)
+ queue->cur = 0;
+
+ /* Ensure the read of the valid bit occurs before reading any
+ * other bits of the CRQ entry
+ */
+ dma_rmb();
+ } else {
+ crq = NULL;
+ }
+
+ spin_unlock_irqrestore(&queue->lock, flags);
+
+ return crq;
+}
+
+/**
+ * ibmvmc_send_crq - Send CRQ
+ *
+ * @adapter: crq_server_adapter struct
+ * @word1: Word1 Data field
+ * @word2: Word2 Data field
+ *
+ * Return:
+ * 0 - Success
+ * Non-Zero - Failure
+ */
+static long ibmvmc_send_crq(struct crq_server_adapter *adapter,
+ u64 word1, u64 word2)
+{
+ struct vio_dev *vdev = to_vio_dev(adapter->dev);
+ long rc = 0;
+
+ dev_dbg(adapter->dev, "(0x%x, 0x%016llx, 0x%016llx)\n",
+ vdev->unit_address, word1, word2);
+
+ /*
+ * Ensure the command buffer is flushed to memory before handing it
+ * over to the other side to prevent it from fetching any stale data.
+ */
+ dma_wmb();
+ rc = plpar_hcall_norets(H_SEND_CRQ, vdev->unit_address, word1, word2);
+ dev_dbg(adapter->dev, "rc = 0x%lx\n", rc);
+
+ return rc;
+}
+
+/**
+ * alloc_dma_buffer - Create DMA Buffer
+ *
+ * @vdev: vio_dev struct
+ * @size: Size field
+ * @dma_handle: DMA address field
+ *
+ * Allocates memory for the command queue and maps remote memory into an
+ * ioba.
+ *
+ * Returns a pointer to the buffer
+ */
+static void *alloc_dma_buffer(struct vio_dev *vdev, size_t size,
+ dma_addr_t *dma_handle)
+{
+ /* allocate memory */
+ void *buffer = kzalloc(size, GFP_KERNEL);
+
+ if (!buffer) {
+ *dma_handle = 0;
+ return NULL;
+ }
+
+ /* DMA map */
+ *dma_handle = dma_map_single(&vdev->dev, buffer, size,
+ DMA_BIDIRECTIONAL);
+
+ if (dma_mapping_error(&vdev->dev, *dma_handle)) {
+ *dma_handle = 0;
+ kzfree(buffer);
+ return NULL;
+ }
+
+ return buffer;
+}
+
+/**
+ * free_dma_buffer - Free DMA Buffer
+ *
+ * @vdev: vio_dev struct
+ * @size: Size field
+ * @vaddr: Address field
+ * @dma_handle: DMA address field
+ *
+ * Releases memory for a command queue and unmaps mapped remote memory.
+ */
+static void free_dma_buffer(struct vio_dev *vdev, size_t size, void *vaddr,
+ dma_addr_t dma_handle)
+{
+ /* DMA unmap */
+ dma_unmap_single(&vdev->dev, dma_handle, size, DMA_BIDIRECTIONAL);
+
+ /* deallocate memory */
+ kzfree(vaddr);
+}
+
+/**
+ * ibmvmc_get_valid_hmc_buffer - Retrieve Valid HMC Buffer
+ *
+ * @hmc_index: HMC Index Field
+ *
+ * Return:
+ * Pointer to ibmvmc_buffer
+ */
+static struct ibmvmc_buffer *ibmvmc_get_valid_hmc_buffer(u8 hmc_index)
+{
+ struct ibmvmc_buffer *buffer;
+ struct ibmvmc_buffer *ret_buf = NULL;
+ unsigned long i;
+
+ if (hmc_index > ibmvmc.max_hmc_index)
+ return NULL;
+
+ buffer = hmcs[hmc_index].buffer;
+
+ for (i = 0; i < ibmvmc_max_buf_pool_size; i++) {
+ if (buffer[i].valid && buffer[i].free &&
+ buffer[i].owner == VMC_BUF_OWNER_ALPHA) {
+ buffer[i].free = 0;
+ ret_buf = &buffer[i];
+ break;
+ }
+ }
+
+ return ret_buf;
+}
+
+/**
+ * ibmvmc_get_free_hmc_buffer - Get Free HMC Buffer
+ *
+ * @adapter: crq_server_adapter struct
+ * @hmc_index: Hmc Index field
+ *
+ * Return:
+ * Pointer to ibmvmc_buffer
+ */
+static struct ibmvmc_buffer *ibmvmc_get_free_hmc_buffer(struct crq_server_adapter *adapter,
+ u8 hmc_index)
+{
+ struct ibmvmc_buffer *buffer;
+ struct ibmvmc_buffer *ret_buf = NULL;
+ unsigned long i;
+
+ if (hmc_index > ibmvmc.max_hmc_index) {
+ dev_info(adapter->dev, "get_free_hmc_buffer: invalid hmc_index=0x%x\n",
+ hmc_index);
+ return NULL;
+ }
+
+ buffer = hmcs[hmc_index].buffer;
+
+ for (i = 0; i < ibmvmc_max_buf_pool_size; i++) {
+ if (buffer[i].free &&
+ buffer[i].owner == VMC_BUF_OWNER_ALPHA) {
+ buffer[i].free = 0;
+ ret_buf = &buffer[i];
+ break;
+ }
+ }
+
+ return ret_buf;
+}
+
+/**
+ * ibmvmc_free_hmc_buffer - Free an HMC Buffer
+ *
+ * @hmc: ibmvmc_hmc struct
+ * @buffer: ibmvmc_buffer struct
+ *
+ */
+static void ibmvmc_free_hmc_buffer(struct ibmvmc_hmc *hmc,
+ struct ibmvmc_buffer *buffer)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&hmc->lock, flags);
+ buffer->free = 1;
+ spin_unlock_irqrestore(&hmc->lock, flags);
+}
+
+/**
+ * ibmvmc_count_hmc_buffers - Count HMC Buffers
+ *
+ * @hmc_index: HMC Index field
+ * @valid: Valid number of buffers field
+ * @free: Free number of buffers field
+ *
+ */
+static void ibmvmc_count_hmc_buffers(u8 hmc_index, unsigned int *valid,
+ unsigned int *free)
+{
+ struct ibmvmc_buffer *buffer;
+ unsigned long i;
+ unsigned long flags;
+
+ if (hmc_index > ibmvmc.max_hmc_index)
+ return;
+
+ if (!valid || !free)
+ return;
+
+ *valid = 0; *free = 0;
+
+ buffer = hmcs[hmc_index].buffer;
+ spin_lock_irqsave(&hmcs[hmc_index].lock, flags);
+
+ for (i = 0; i < ibmvmc_max_buf_pool_size; i++) {
+ if (buffer[i].valid) {
+ *valid = *valid + 1;
+ if (buffer[i].free)
+ *free = *free + 1;
+ }
+ }
+
+ spin_unlock_irqrestore(&hmcs[hmc_index].lock, flags);
+}
+
+/**
+ * ibmvmc_get_free_hmc - Get Free HMC
+ *
+ * Return:
+ * Pointer to an available HMC Connection
+ * Null otherwise
+ */
+static struct ibmvmc_hmc *ibmvmc_get_free_hmc(void)
+{
+ unsigned long i;
+ unsigned long flags;
+
+ /*
+ * Find an available HMC connection.
+ */
+ for (i = 0; i <= ibmvmc.max_hmc_index; i++) {
+ spin_lock_irqsave(&hmcs[i].lock, flags);
+ if (hmcs[i].state == ibmhmc_state_free) {
+ hmcs[i].index = i;
+ hmcs[i].state = ibmhmc_state_initial;
+ spin_unlock_irqrestore(&hmcs[i].lock, flags);
+ return &hmcs[i];
+ }
+ spin_unlock_irqrestore(&hmcs[i].lock, flags);
+ }
+
+ return NULL;
+}
+
+/**
+ * ibmvmc_return_hmc - Return an HMC Connection
+ *
+ * @hmc: ibmvmc_hmc struct
+ * @release_readers: Number of readers connected to session
+ *
+ * This function releases the HMC connections back into the pool.
+ *
+ * Return:
+ * 0 - Success
+ * Non-zero - Failure
+ */
+static int ibmvmc_return_hmc(struct ibmvmc_hmc *hmc, bool release_readers)
+{
+ struct ibmvmc_buffer *buffer;
+ struct crq_server_adapter *adapter;
+ struct vio_dev *vdev;
+ unsigned long i;
+ unsigned long flags;
+
+ if (!hmc || !hmc->adapter)
+ return -EIO;
+
+ if (release_readers) {
+ if (hmc->file_session) {
+ struct ibmvmc_file_session *session = hmc->file_session;
+
+ session->valid = 0;
+ wake_up_interruptible(&ibmvmc_read_wait);
+ }
+ }
+
+ adapter = hmc->adapter;
+ vdev = to_vio_dev(adapter->dev);
+
+ spin_lock_irqsave(&hmc->lock, flags);
+ hmc->index = 0;
+ hmc->state = ibmhmc_state_free;
+ hmc->queue_head = 0;
+ hmc->queue_tail = 0;
+ buffer = hmc->buffer;
+ for (i = 0; i < ibmvmc_max_buf_pool_size; i++) {
+ if (buffer[i].valid) {
+ free_dma_buffer(vdev,
+ ibmvmc.max_mtu,
+ buffer[i].real_addr_local,
+ buffer[i].dma_addr_local);
+ dev_dbg(adapter->dev, "Forgot buffer id 0x%lx\n", i);
+ }
+ memset(&buffer[i], 0, sizeof(struct ibmvmc_buffer));
+
+ hmc->queue_outbound_msgs[i] = VMC_INVALID_BUFFER_ID;
+ }
+
+ spin_unlock_irqrestore(&hmc->lock, flags);
+
+ return 0;
+}
+
+/**
+ * ibmvmc_send_open - Interface Open
+ * @buffer: Pointer to ibmvmc_buffer struct
+ * @hmc: Pointer to ibmvmc_hmc struct
+ *
+ * This command is sent by the management partition as the result of a
+ * management partition device request. It causes the hypervisor to
+ * prepare a set of data buffers for the management application connection
+ * indicated HMC idx. A unique HMC Idx would be used if multiple management
+ * applications running concurrently were desired. Before responding to this
+ * command, the hypervisor must provide the management partition with at
+ * least one of these new buffers via the Add Buffer. This indicates whether
+ * the messages are inbound or outbound from the hypervisor.
+ *
+ * Return:
+ * 0 - Success
+ * Non-zero - Failure
+ */
+static int ibmvmc_send_open(struct ibmvmc_buffer *buffer,
+ struct ibmvmc_hmc *hmc)
+{
+ struct ibmvmc_crq_msg crq_msg;
+ struct crq_server_adapter *adapter;
+ __be64 *crq_as_u64 = (__be64 *)&crq_msg;
+ int rc = 0;
+
+ if (!hmc || !hmc->adapter)
+ return -EIO;
+
+ adapter = hmc->adapter;
+
+ dev_dbg(adapter->dev, "send_open: 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx\n",
+ (unsigned long)buffer->size, (unsigned long)adapter->liobn,
+ (unsigned long)buffer->dma_addr_local,
+ (unsigned long)adapter->riobn,
+ (unsigned long)buffer->dma_addr_remote);
+
+ rc = h_copy_rdma(buffer->size,
+ adapter->liobn,
+ buffer->dma_addr_local,
+ adapter->riobn,
+ buffer->dma_addr_remote);
+ if (rc) {
+ dev_err(adapter->dev, "Error: In send_open, h_copy_rdma rc 0x%x\n",
+ rc);
+ return -EIO;
+ }
+
+ hmc->state = ibmhmc_state_opening;
+
+ crq_msg.valid = 0x80;
+ crq_msg.type = VMC_MSG_OPEN;
+ crq_msg.status = 0;
+ crq_msg.var1.rsvd = 0;
+ crq_msg.hmc_session = hmc->session;
+ crq_msg.hmc_index = hmc->index;
+ crq_msg.var2.buffer_id = cpu_to_be16(buffer->id);
+ crq_msg.rsvd = 0;
+ crq_msg.var3.rsvd = 0;
+
+ ibmvmc_send_crq(adapter, be64_to_cpu(crq_as_u64[0]),
+ be64_to_cpu(crq_as_u64[1]));
+
+ return rc;
+}
+
+/**
+ * ibmvmc_send_close - Interface Close
+ * @hmc: Pointer to ibmvmc_hmc struct
+ *
+ * This command is sent by the management partition to terminate a
+ * management application to hypervisor connection. When this command is
+ * sent, the management partition has quiesced all I/O operations to all
+ * buffers associated with this management application connection, and
+ * has freed any storage for these buffers.
+ *
+ * Return:
+ * 0 - Success
+ * Non-zero - Failure
+ */
+static int ibmvmc_send_close(struct ibmvmc_hmc *hmc)
+{
+ struct ibmvmc_crq_msg crq_msg;
+ struct crq_server_adapter *adapter;
+ __be64 *crq_as_u64 = (__be64 *)&crq_msg;
+ int rc = 0;
+
+ if (!hmc || !hmc->adapter)
+ return -EIO;
+
+ adapter = hmc->adapter;
+
+ dev_info(adapter->dev, "CRQ send: close\n");
+
+ crq_msg.valid = 0x80;
+ crq_msg.type = VMC_MSG_CLOSE;
+ crq_msg.status = 0;
+ crq_msg.var1.rsvd = 0;
+ crq_msg.hmc_session = hmc->session;
+ crq_msg.hmc_index = hmc->index;
+ crq_msg.var2.rsvd = 0;
+ crq_msg.rsvd = 0;
+ crq_msg.var3.rsvd = 0;
+
+ ibmvmc_send_crq(adapter, be64_to_cpu(crq_as_u64[0]),
+ be64_to_cpu(crq_as_u64[1]));
+
+ return rc;
+}
+
+/**
+ * ibmvmc_send_capabilities - Send VMC Capabilities
+ *
+ * @adapter: crq_server_adapter struct
+ *
+ * The capabilities message is an administrative message sent after the CRQ
+ * initialization sequence of messages and is used to exchange VMC capabilities
+ * between the management partition and the hypervisor. The management
+ * partition must send this message and the hypervisor must respond with VMC
+ * capabilities Response message before HMC interface message can begin. Any
+ * HMC interface messages received before the exchange of capabilities has
+ * complete are dropped.
+ *
+ * Return:
+ * 0 - Success
+ */
+static int ibmvmc_send_capabilities(struct crq_server_adapter *adapter)
+{
+ struct ibmvmc_admin_crq_msg crq_msg;
+ __be64 *crq_as_u64 = (__be64 *)&crq_msg;
+
+ dev_dbg(adapter->dev, "ibmvmc: CRQ send: capabilities\n");
+ crq_msg.valid = 0x80;
+ crq_msg.type = VMC_MSG_CAP;
+ crq_msg.status = 0;
+ crq_msg.rsvd[0] = 0;
+ crq_msg.rsvd[1] = 0;
+ crq_msg.max_hmc = ibmvmc_max_hmcs;
+ crq_msg.max_mtu = cpu_to_be32(ibmvmc_max_mtu);
+ crq_msg.pool_size = cpu_to_be16(ibmvmc_max_buf_pool_size);
+ crq_msg.crq_size = cpu_to_be16(adapter->queue.size);
+ crq_msg.version = cpu_to_be16(IBMVMC_PROTOCOL_VERSION);
+
+ ibmvmc_send_crq(adapter, be64_to_cpu(crq_as_u64[0]),
+ be64_to_cpu(crq_as_u64[1]));
+
+ ibmvmc.state = ibmvmc_state_capabilities;
+
+ return 0;
+}
+
+/**
+ * ibmvmc_send_add_buffer_resp - Add Buffer Response
+ *
+ * @adapter: crq_server_adapter struct
+ * @status: Status field
+ * @hmc_session: HMC Session field
+ * @hmc_index: HMC Index field
+ * @buffer_id: Buffer Id field
+ *
+ * This command is sent by the management partition to the hypervisor in
+ * response to the Add Buffer message. The Status field indicates the result of
+ * the command.
+ *
+ * Return:
+ * 0 - Success
+ */
+static int ibmvmc_send_add_buffer_resp(struct crq_server_adapter *adapter,
+ u8 status, u8 hmc_session,
+ u8 hmc_index, u16 buffer_id)
+{
+ struct ibmvmc_crq_msg crq_msg;
+ __be64 *crq_as_u64 = (__be64 *)&crq_msg;
+
+ dev_dbg(adapter->dev, "CRQ send: add_buffer_resp\n");
+ crq_msg.valid = 0x80;
+ crq_msg.type = VMC_MSG_ADD_BUF_RESP;
+ crq_msg.status = status;
+ crq_msg.var1.rsvd = 0;
+ crq_msg.hmc_session = hmc_session;
+ crq_msg.hmc_index = hmc_index;
+ crq_msg.var2.buffer_id = cpu_to_be16(buffer_id);
+ crq_msg.rsvd = 0;
+ crq_msg.var3.rsvd = 0;
+
+ ibmvmc_send_crq(adapter, be64_to_cpu(crq_as_u64[0]),
+ be64_to_cpu(crq_as_u64[1]));
+
+ return 0;
+}
+
+/**
+ * ibmvmc_send_rem_buffer_resp - Remove Buffer Response
+ *
+ * @adapter: crq_server_adapter struct
+ * @status: Status field
+ * @hmc_session: HMC Session field
+ * @hmc_index: HMC Index field
+ * @buffer_id: Buffer Id field
+ *
+ * This command is sent by the management partition to the hypervisor in
+ * response to the Remove Buffer message. The Buffer ID field indicates
+ * which buffer the management partition selected to remove. The Status
+ * field indicates the result of the command.
+ *
+ * Return:
+ * 0 - Success
+ */
+static int ibmvmc_send_rem_buffer_resp(struct crq_server_adapter *adapter,
+ u8 status, u8 hmc_session,
+ u8 hmc_index, u16 buffer_id)
+{
+ struct ibmvmc_crq_msg crq_msg;
+ __be64 *crq_as_u64 = (__be64 *)&crq_msg;
+
+ dev_dbg(adapter->dev, "CRQ send: rem_buffer_resp\n");
+ crq_msg.valid = 0x80;
+ crq_msg.type = VMC_MSG_REM_BUF_RESP;
+ crq_msg.status = status;
+ crq_msg.var1.rsvd = 0;
+ crq_msg.hmc_session = hmc_session;
+ crq_msg.hmc_index = hmc_index;
+ crq_msg.var2.buffer_id = cpu_to_be16(buffer_id);
+ crq_msg.rsvd = 0;
+ crq_msg.var3.rsvd = 0;
+
+ ibmvmc_send_crq(adapter, be64_to_cpu(crq_as_u64[0]),
+ be64_to_cpu(crq_as_u64[1]));
+
+ return 0;
+}
+
+/**
+ * ibmvmc_send_msg - Signal Message
+ *
+ * @adapter: crq_server_adapter struct
+ * @buffer: ibmvmc_buffer struct
+ * @hmc: ibmvmc_hmc struct
+ * @msg_length: message length field
+ *
+ * This command is sent between the management partition and the hypervisor
+ * in order to signal the arrival of an HMC protocol message. The command
+ * can be sent by both the management partition and the hypervisor. It is
+ * used for all traffic between the management application and the hypervisor,
+ * regardless of who initiated the communication.
+ *
+ * There is no response to this message.
+ *
+ * Return:
+ * 0 - Success
+ * Non-zero - Failure
+ */
+static int ibmvmc_send_msg(struct crq_server_adapter *adapter,
+ struct ibmvmc_buffer *buffer,
+ struct ibmvmc_hmc *hmc, int msg_len)
+{
+ struct ibmvmc_crq_msg crq_msg;
+ __be64 *crq_as_u64 = (__be64 *)&crq_msg;
+ int rc = 0;
+
+ dev_dbg(adapter->dev, "CRQ send: rdma to HV\n");
+ rc = h_copy_rdma(msg_len,
+ adapter->liobn,
+ buffer->dma_addr_local,
+ adapter->riobn,
+ buffer->dma_addr_remote);
+ if (rc) {
+ dev_err(adapter->dev, "Error in send_msg, h_copy_rdma rc 0x%x\n",
+ rc);
+ return rc;
+ }
+
+ crq_msg.valid = 0x80;
+ crq_msg.type = VMC_MSG_SIGNAL;
+ crq_msg.status = 0;
+ crq_msg.var1.rsvd = 0;
+ crq_msg.hmc_session = hmc->session;
+ crq_msg.hmc_index = hmc->index;
+ crq_msg.var2.buffer_id = cpu_to_be16(buffer->id);
+ crq_msg.var3.msg_len = cpu_to_be32(msg_len);
+ dev_dbg(adapter->dev, "CRQ send: msg to HV 0x%llx 0x%llx\n",
+ be64_to_cpu(crq_as_u64[0]), be64_to_cpu(crq_as_u64[1]));
+
+ buffer->owner = VMC_BUF_OWNER_HV;
+ ibmvmc_send_crq(adapter, be64_to_cpu(crq_as_u64[0]),
+ be64_to_cpu(crq_as_u64[1]));
+
+ return rc;
+}
+
+/**
+ * ibmvmc_open - Open Session
+ *
+ * @inode: inode struct
+ * @file: file struct
+ *
+ * Return:
+ * 0 - Success
+ */
+static int ibmvmc_open(struct inode *inode, struct file *file)
+{
+ struct ibmvmc_file_session *session;
+ int rc = 0;
+
+ pr_debug("%s: inode = 0x%lx, file = 0x%lx, state = 0x%x\n", __func__,
+ (unsigned long)inode, (unsigned long)file,
+ ibmvmc.state);
+
+ session = kzalloc(sizeof(*session), GFP_KERNEL);
+ session->file = file;
+ file->private_data = session;
+
+ return rc;
+}
+
+/**
+ * ibmvmc_close - Close Session
+ *
+ * @inode: inode struct
+ * @file: file struct
+ *
+ * Return:
+ * 0 - Success
+ * Non-zero - Failure
+ */
+static int ibmvmc_close(struct inode *inode, struct file *file)
+{
+ struct ibmvmc_file_session *session;
+ struct ibmvmc_hmc *hmc;
+ int rc = 0;
+ unsigned long flags;
+
+ pr_debug("%s: file = 0x%lx, state = 0x%x\n", __func__,
+ (unsigned long)file, ibmvmc.state);
+
+ session = file->private_data;
+ if (!session)
+ return -EIO;
+
+ hmc = session->hmc;
+ if (hmc) {
+ if (!hmc->adapter)
+ return -EIO;
+
+ if (ibmvmc.state == ibmvmc_state_failed) {
+ dev_warn(hmc->adapter->dev, "close: state_failed\n");
+ return -EIO;
+ }
+
+ spin_lock_irqsave(&hmc->lock, flags);
+ if (hmc->state >= ibmhmc_state_opening) {
+ rc = ibmvmc_send_close(hmc);
+ if (rc)
+ dev_warn(hmc->adapter->dev, "close: send_close failed.\n");
+ }
+ spin_unlock_irqrestore(&hmc->lock, flags);
+ }
+
+ kzfree(session);
+
+ return rc;
+}
+
+/**
+ * ibmvmc_read - Read
+ *
+ * @file: file struct
+ * @buf: Character buffer
+ * @nbytes: Size in bytes
+ * @ppos: Offset
+ *
+ * Return:
+ * 0 - Success
+ * Non-zero - Failure
+ */
+static ssize_t ibmvmc_read(struct file *file, char *buf, size_t nbytes,
+ loff_t *ppos)
+{
+ struct ibmvmc_file_session *session;
+ struct ibmvmc_hmc *hmc;
+ struct crq_server_adapter *adapter;
+ struct ibmvmc_buffer *buffer;
+ ssize_t n;
+ ssize_t retval = 0;
+ unsigned long flags;
+ DEFINE_WAIT(wait);
+
+ pr_debug("ibmvmc: read: file = 0x%lx, buf = 0x%lx, nbytes = 0x%lx\n",
+ (unsigned long)file, (unsigned long)buf,
+ (unsigned long)nbytes);
+
+ if (nbytes == 0)
+ return 0;
+
+ if (nbytes > ibmvmc.max_mtu) {
+ pr_warn("ibmvmc: read: nbytes invalid 0x%x\n",
+ (unsigned int)nbytes);
+ return -EINVAL;
+ }
+
+ session = file->private_data;
+ if (!session) {
+ pr_warn("ibmvmc: read: no session\n");
+ return -EIO;
+ }
+
+ hmc = session->hmc;
+ if (!hmc) {
+ pr_warn("ibmvmc: read: no hmc\n");
+ return -EIO;
+ }
+
+ adapter = hmc->adapter;
+ if (!adapter) {
+ pr_warn("ibmvmc: read: no adapter\n");
+ return -EIO;
+ }
+
+ do {
+ prepare_to_wait(&ibmvmc_read_wait, &wait, TASK_INTERRUPTIBLE);
+
+ spin_lock_irqsave(&hmc->lock, flags);
+ if (hmc->queue_tail != hmc->queue_head)
+ /* Data is available */
+ break;
+
+ spin_unlock_irqrestore(&hmc->lock, flags);
+
+ if (!session->valid) {
+ retval = -EBADFD;
+ goto out;
+ }
+ if (file->f_flags & O_NONBLOCK) {
+ retval = -EAGAIN;
+ goto out;
+ }
+
+ schedule();
+
+ if (signal_pending(current)) {
+ retval = -ERESTARTSYS;
+ goto out;
+ }
+ } while (1);
+
+ buffer = &(hmc->buffer[hmc->queue_outbound_msgs[hmc->queue_tail]]);
+ hmc->queue_tail++;
+ if (hmc->queue_tail == ibmvmc_max_buf_pool_size)
+ hmc->queue_tail = 0;
+ spin_unlock_irqrestore(&hmc->lock, flags);
+
+ nbytes = min_t(size_t, nbytes, buffer->msg_len);
+ n = copy_to_user((void *)buf, buffer->real_addr_local, nbytes);
+ dev_dbg(adapter->dev, "read: copy to user nbytes = 0x%lx.\n", nbytes);
+ ibmvmc_free_hmc_buffer(hmc, buffer);
+ retval = nbytes;
+
+ if (n) {
+ dev_warn(adapter->dev, "read: copy to user failed.\n");
+ retval = -EFAULT;
+ }
+
+ out:
+ finish_wait(&ibmvmc_read_wait, &wait);
+ dev_dbg(adapter->dev, "read: out %ld\n", retval);
+ return retval;
+}
+
+/**
+ * ibmvmc_poll - Poll
+ *
+ * @file: file struct
+ * @wait: Poll Table
+ *
+ * Return:
+ * poll.h return values
+ */
+static unsigned int ibmvmc_poll(struct file *file, poll_table *wait)
+{
+ struct ibmvmc_file_session *session;
+ struct ibmvmc_hmc *hmc;
+ unsigned int mask = 0;
+
+ session = file->private_data;
+ if (!session)
+ return 0;
+
+ hmc = session->hmc;
+ if (!hmc)
+ return 0;
+
+ poll_wait(file, &ibmvmc_read_wait, wait);
+
+ if (hmc->queue_head != hmc->queue_tail)
+ mask |= POLLIN | POLLRDNORM;
+
+ return mask;
+}
+
+/**
+ * ibmvmc_write - Write
+ *
+ * @file: file struct
+ * @buf: Character buffer
+ * @count: Count field
+ * @ppos: Offset
+ *
+ * Return:
+ * 0 - Success
+ * Non-zero - Failure
+ */
+static ssize_t ibmvmc_write(struct file *file, const char *buffer,
+ size_t count, loff_t *ppos)
+{
+ struct ibmvmc_buffer *vmc_buffer;
+ struct ibmvmc_file_session *session;
+ struct crq_server_adapter *adapter;
+ struct ibmvmc_hmc *hmc;
+ unsigned char *buf;
+ unsigned long flags;
+ size_t bytes;
+ const char *p = buffer;
+ size_t c = count;
+ int ret = 0;
+
+ session = file->private_data;
+ if (!session)
+ return -EIO;
+
+ hmc = session->hmc;
+ if (!hmc)
+ return -EIO;
+
+ spin_lock_irqsave(&hmc->lock, flags);
+ if (hmc->state == ibmhmc_state_free) {
+ /* HMC connection is not valid (possibly was reset under us). */
+ ret = -EIO;
+ goto out;
+ }
+
+ adapter = hmc->adapter;
+ if (!adapter) {
+ ret = -EIO;
+ goto out;
+ }
+
+ if (count > ibmvmc.max_mtu) {
+ dev_warn(adapter->dev, "invalid buffer size 0x%lx\n",
+ (unsigned long)count);
+ ret = -EIO;
+ goto out;
+ }
+
+ /* Waiting for the open resp message to the ioctl(1) - retry */
+ if (hmc->state == ibmhmc_state_opening) {
+ ret = -EBUSY;
+ goto out;
+ }
+
+ /* Make sure the ioctl() was called & the open msg sent, and that
+ * the HMC connection has not failed.
+ */
+ if (hmc->state != ibmhmc_state_ready) {
+ ret = -EIO;
+ goto out;
+ }
+
+ vmc_buffer = ibmvmc_get_valid_hmc_buffer(hmc->index);
+ if (!vmc_buffer) {
+ /* No buffer available for the msg send, or we have not yet
+ * completed the open/open_resp sequence. Retry until this is
+ * complete.
+ */
+ ret = -EBUSY;
+ goto out;
+ }
+ if (!vmc_buffer->real_addr_local) {
+ dev_err(adapter->dev, "no buffer storage assigned\n");
+ ret = -EIO;
+ goto out;
+ }
+ buf = vmc_buffer->real_addr_local;
+
+ while (c > 0) {
+ bytes = min_t(size_t, c, vmc_buffer->size);
+
+ bytes -= copy_from_user(buf, p, bytes);
+ if (!bytes) {
+ ret = -EFAULT;
+ goto out;
+ }
+ c -= bytes;
+ p += bytes;
+ }
+ if (p == buffer)
+ goto out;
+
+ file->f_path.dentry->d_inode->i_mtime = current_time(file_inode(file));
+ mark_inode_dirty(file->f_path.dentry->d_inode);
+
+ dev_dbg(adapter->dev, "write: file = 0x%lx, count = 0x%lx\n",
+ (unsigned long)file, (unsigned long)count);
+
+ ibmvmc_send_msg(adapter, vmc_buffer, hmc, count);
+ ret = p - buffer;
+ out:
+ spin_unlock_irqrestore(&hmc->lock, flags);
+ return (ssize_t)(ret);
+}
+
+/**
+ * ibmvmc_setup_hmc - Setup the HMC
+ *
+ * @session: ibmvmc_file_session struct
+ *
+ * Return:
+ * 0 - Success
+ * Non-zero - Failure
+ */
+static long ibmvmc_setup_hmc(struct ibmvmc_file_session *session)
+{
+ struct ibmvmc_hmc *hmc;
+ unsigned int valid, free, index;
+
+ if (ibmvmc.state == ibmvmc_state_failed) {
+ pr_warn("ibmvmc: Reserve HMC: state_failed\n");
+ return -EIO;
+ }
+
+ if (ibmvmc.state < ibmvmc_state_ready) {
+ pr_warn("ibmvmc: Reserve HMC: not state_ready\n");
+ return -EAGAIN;
+ }
+
+ /* Device is busy until capabilities have been exchanged and we
+ * have a generic buffer for each possible HMC connection.
+ */
+ for (index = 0; index <= ibmvmc.max_hmc_index; index++) {
+ valid = 0;
+ ibmvmc_count_hmc_buffers(index, &valid, &free);
+ if (valid == 0) {
+ pr_warn("ibmvmc: buffers not ready for index %d\n",
+ index);
+ return -ENOBUFS;
+ }
+ }
+
+ /* Get an hmc object, and transition to ibmhmc_state_initial */
+ hmc = ibmvmc_get_free_hmc();
+ if (!hmc) {
+ pr_warn("%s: free hmc not found\n", __func__);
+ return -EBUSY;
+ }
+
+ hmc->session = hmc->session + 1;
+ if (hmc->session == 0xff)
+ hmc->session = 1;
+
+ session->hmc = hmc;
+ hmc->adapter = &ibmvmc_adapter;
+ hmc->file_session = session;
+ session->valid = 1;
+
+ return 0;
+}
+
+/**
+ * ibmvmc_ioctl_sethmcid - IOCTL Set HMC ID
+ *
+ * @session: ibmvmc_file_session struct
+ * @new_hmc_id: HMC id field
+ *
+ * IOCTL command to setup the hmc id
+ *
+ * Return:
+ * 0 - Success
+ * Non-zero - Failure
+ */
+static long ibmvmc_ioctl_sethmcid(struct ibmvmc_file_session *session,
+ unsigned char __user *new_hmc_id)
+{
+ struct ibmvmc_hmc *hmc;
+ struct ibmvmc_buffer *buffer;
+ size_t bytes;
+ char print_buffer[HMC_ID_LEN + 1];
+ unsigned long flags;
+ long rc = 0;
+
+ /* Reserve HMC session */
+ hmc = session->hmc;
+ if (!hmc) {
+ rc = ibmvmc_setup_hmc(session);
+ if (rc)
+ return rc;
+
+ hmc = session->hmc;
+ if (!hmc) {
+ pr_err("ibmvmc: setup_hmc success but no hmc\n");
+ return -EIO;
+ }
+ }
+
+ if (hmc->state != ibmhmc_state_initial) {
+ pr_warn("ibmvmc: sethmcid: invalid state to send open 0x%x\n",
+ hmc->state);
+ return -EIO;
+ }
+
+ bytes = copy_from_user(hmc->hmc_id, new_hmc_id, HMC_ID_LEN);
+ if (bytes)
+ return -EFAULT;
+
+ /* Send Open Session command */
+ spin_lock_irqsave(&hmc->lock, flags);
+ buffer = ibmvmc_get_valid_hmc_buffer(hmc->index);
+ spin_unlock_irqrestore(&hmc->lock, flags);
+
+ if (!buffer || !buffer->real_addr_local) {
+ pr_warn("ibmvmc: sethmcid: no buffer available\n");
+ return -EIO;
+ }
+
+ /* Make sure buffer is NULL terminated before trying to print it */
+ memset(print_buffer, 0, HMC_ID_LEN + 1);
+ strncpy(print_buffer, hmc->hmc_id, HMC_ID_LEN);
+ pr_info("ibmvmc: sethmcid: Set HMC ID: \"%s\"\n", print_buffer);
+
+ memcpy(buffer->real_addr_local, hmc->hmc_id, HMC_ID_LEN);
+ /* RDMA over ID, send open msg, change state to ibmhmc_state_opening */
+ rc = ibmvmc_send_open(buffer, hmc);
+
+ return rc;
+}
+
+/**
+ * ibmvmc_ioctl_query - IOCTL Query
+ *
+ * @session: ibmvmc_file_session struct
+ * @ret_struct: ibmvmc_query_struct
+ *
+ * Return:
+ * 0 - Success
+ * Non-zero - Failure
+ */
+static long ibmvmc_ioctl_query(struct ibmvmc_file_session *session,
+ struct ibmvmc_query_struct __user *ret_struct)
+{
+ struct ibmvmc_query_struct query_struct;
+ size_t bytes;
+
+ memset(&query_struct, 0, sizeof(query_struct));
+ query_struct.have_vmc = (ibmvmc.state > ibmvmc_state_initial);
+ query_struct.state = ibmvmc.state;
+ query_struct.vmc_drc_index = ibmvmc.vmc_drc_index;
+
+ bytes = copy_to_user(ret_struct, &query_struct,
+ sizeof(query_struct));
+ if (bytes)
+ return -EFAULT;
+
+ return 0;
+}
+
+/**
+ * ibmvmc_ioctl_requestvmc - IOCTL Request VMC
+ *
+ * @session: ibmvmc_file_session struct
+ * @ret_vmc_index: VMC Index
+ *
+ * Return:
+ * 0 - Success
+ * Non-zero - Failure
+ */
+static long ibmvmc_ioctl_requestvmc(struct ibmvmc_file_session *session,
+ u32 __user *ret_vmc_index)
+{
+ /* TODO: (adreznec) Add locking to control multiple process access */
+ size_t bytes;
+ long rc;
+ u32 vmc_drc_index;
+
+ /* Call to request the VMC device from phyp*/
+ rc = h_request_vmc(&vmc_drc_index);
+ pr_debug("ibmvmc: requestvmc: H_REQUEST_VMC rc = 0x%lx\n", rc);
+
+ if (rc == H_SUCCESS) {
+ rc = 0;
+ } else if (rc == H_FUNCTION) {
+ pr_err("ibmvmc: requestvmc: h_request_vmc not supported\n");
+ return -EPERM;
+ } else if (rc == H_AUTHORITY) {
+ pr_err("ibmvmc: requestvmc: hypervisor denied vmc request\n");
+ return -EPERM;
+ } else if (rc == H_HARDWARE) {
+ pr_err("ibmvmc: requestvmc: hypervisor hardware fault\n");
+ return -EIO;
+ } else if (rc == H_RESOURCE) {
+ pr_err("ibmvmc: requestvmc: vmc resource unavailable\n");
+ return -ENODEV;
+ } else if (rc == H_NOT_AVAILABLE) {
+ pr_err("ibmvmc: requestvmc: system cannot be vmc managed\n");
+ return -EPERM;
+ } else if (rc == H_PARAMETER) {
+ pr_err("ibmvmc: requestvmc: invalid parameter\n");
+ return -EINVAL;
+ }
+
+ /* Success, set the vmc index in global struct */
+ ibmvmc.vmc_drc_index = vmc_drc_index;
+
+ bytes = copy_to_user(ret_vmc_index, &vmc_drc_index,
+ sizeof(*ret_vmc_index));
+ if (bytes) {
+ pr_warn("ibmvmc: requestvmc: copy to user failed.\n");
+ return -EFAULT;
+ }
+ return rc;
+}
+
+/**
+ * ibmvmc_ioctl - IOCTL
+ *
+ * @session: ibmvmc_file_session struct
+ * @cmd: cmd field
+ * @arg: Argument field
+ *
+ * Return:
+ * 0 - Success
+ * Non-zero - Failure
+ */
+static long ibmvmc_ioctl(struct file *file,
+ unsigned int cmd, unsigned long arg)
+{
+ struct ibmvmc_file_session *session = file->private_data;
+
+ pr_debug("ibmvmc: ioctl file=0x%lx, cmd=0x%x, arg=0x%lx, ses=0x%lx\n",
+ (unsigned long)file, cmd, arg,
+ (unsigned long)session);
+
+ if (!session) {
+ pr_warn("ibmvmc: ioctl: no session\n");
+ return -EIO;
+ }
+
+ switch (cmd) {
+ case VMC_IOCTL_SETHMCID:
+ return ibmvmc_ioctl_sethmcid(session,
+ (unsigned char __user *)arg);
+ case VMC_IOCTL_QUERY:
+ return ibmvmc_ioctl_query(session,
+ (struct ibmvmc_query_struct __user *)arg);
+ case VMC_IOCTL_REQUESTVMC:
+ return ibmvmc_ioctl_requestvmc(session,
+ (unsigned int __user *)arg);
+ default:
+ pr_warn("ibmvmc: unknown ioctl 0x%x\n", cmd);
+ return -EINVAL;
+ }
+}
+
+static const struct file_operations ibmvmc_fops = {
+ .owner = THIS_MODULE,
+ .read = ibmvmc_read,
+ .write = ibmvmc_write,
+ .poll = ibmvmc_poll,
+ .unlocked_ioctl = ibmvmc_ioctl,
+ .open = ibmvmc_open,
+ .release = ibmvmc_close,
+};
+
+/**
+ * ibmvmc_add_buffer - Add Buffer
+ *
+ * @adapter: crq_server_adapter struct
+ * @crq: ibmvmc_crq_msg struct
+ *
+ * This message transfers a buffer from hypervisor ownership to management
+ * partition ownership. The LIOBA is obtained from the virtual TCE table
+ * associated with the hypervisor side of the VMC device, and points to a
+ * buffer of size MTU (as established in the capabilities exchange).
+ *
+ * Typical flow for ading buffers:
+ * 1. A new management application connection is opened by the management
+ * partition.
+ * 2. The hypervisor assigns new buffers for the traffic associated with
+ * that connection.
+ * 3. The hypervisor sends VMC Add Buffer messages to the management
+ * partition, informing it of the new buffers.
+ * 4. The hypervisor sends an HMC protocol message (to the management
+ * application) notifying it of the new buffers. This informs the
+ * application that it has buffers available for sending HMC
+ * commands.
+ *
+ * Return:
+ * 0 - Success
+ * Non-zero - Failure
+ */
+static int ibmvmc_add_buffer(struct crq_server_adapter *adapter,
+ struct ibmvmc_crq_msg *crq)
+{
+ struct ibmvmc_buffer *buffer;
+ u8 hmc_index;
+ u8 hmc_session;
+ u16 buffer_id;
+ unsigned long flags;
+ int rc = 0;
+
+ if (!crq)
+ return -1;
+
+ hmc_session = crq->hmc_session;
+ hmc_index = crq->hmc_index;
+ buffer_id = be16_to_cpu(crq->var2.buffer_id);
+
+ if (hmc_index > ibmvmc.max_hmc_index) {
+ dev_err(adapter->dev, "add_buffer: invalid hmc_index = 0x%x\n",
+ hmc_index);
+ ibmvmc_send_add_buffer_resp(adapter, VMC_MSG_INVALID_HMC_INDEX,
+ hmc_session, hmc_index, buffer_id);
+ return -1;
+ }
+
+ if (buffer_id >= ibmvmc.max_buffer_pool_size) {
+ dev_err(adapter->dev, "add_buffer: invalid buffer_id = 0x%x\n",
+ buffer_id);
+ ibmvmc_send_add_buffer_resp(adapter, VMC_MSG_INVALID_BUFFER_ID,
+ hmc_session, hmc_index, buffer_id);
+ return -1;
+ }
+
+ spin_lock_irqsave(&hmcs[hmc_index].lock, flags);
+ buffer = &hmcs[hmc_index].buffer[buffer_id];
+
+ if (buffer->real_addr_local || buffer->dma_addr_local) {
+ dev_warn(adapter->dev, "add_buffer: already allocated id = 0x%lx\n",
+ (unsigned long)buffer_id);
+ spin_unlock_irqrestore(&hmcs[hmc_index].lock, flags);
+ ibmvmc_send_add_buffer_resp(adapter, VMC_MSG_INVALID_BUFFER_ID,
+ hmc_session, hmc_index, buffer_id);
+ return -1;
+ }
+
+ buffer->real_addr_local = alloc_dma_buffer(to_vio_dev(adapter->dev),
+ ibmvmc.max_mtu,
+ &buffer->dma_addr_local);
+
+ if (!buffer->real_addr_local) {
+ dev_err(adapter->dev, "add_buffer: alloc_dma_buffer failed.\n");
+ spin_unlock_irqrestore(&hmcs[hmc_index].lock, flags);
+ ibmvmc_send_add_buffer_resp(adapter, VMC_MSG_INTERFACE_FAILURE,
+ hmc_session, hmc_index, buffer_id);
+ return -1;
+ }
+
+ buffer->dma_addr_remote = be32_to_cpu(crq->var3.lioba);
+ buffer->size = ibmvmc.max_mtu;
+ buffer->owner = crq->var1.owner;
+ buffer->free = 1;
+ /* Must ensure valid==1 is observable only after all other fields are */
+ dma_wmb();
+ buffer->valid = 1;
+ buffer->id = buffer_id;
+
+ dev_dbg(adapter->dev, "add_buffer: successfully added a buffer:\n");
+ dev_dbg(adapter->dev, " index: %d, session: %d, buffer: 0x%x, owner: %d\n",
+ hmc_index, hmc_session, buffer_id, buffer->owner);
+ dev_dbg(adapter->dev, " local: 0x%x, remote: 0x%x\n",
+ (u32)buffer->dma_addr_local,
+ (u32)buffer->dma_addr_remote);
+ spin_unlock_irqrestore(&hmcs[hmc_index].lock, flags);
+
+ ibmvmc_send_add_buffer_resp(adapter, VMC_MSG_SUCCESS, hmc_session,
+ hmc_index, buffer_id);
+
+ return rc;
+}
+
+/**
+ * ibmvmc_rem_buffer - Remove Buffer
+ *
+ * @adapter: crq_server_adapter struct
+ * @crq: ibmvmc_crq_msg struct
+ *
+ * This message requests an HMC buffer to be transferred from management
+ * partition ownership to hypervisor ownership. The management partition may
+ * not be able to satisfy the request at a particular point in time if all its
+ * buffers are in use. The management partition requires a depth of at least
+ * one inbound buffer to allow management application commands to flow to the
+ * hypervisor. It is, therefore, an interface error for the hypervisor to
+ * attempt to remove the management partition's last buffer.
+ *
+ * The hypervisor is expected to manage buffer usage with the management
+ * application directly and inform the management partition when buffers may be
+ * removed. The typical flow for removing buffers:
+ *
+ * 1. The management application no longer needs a communication path to a
+ * particular hypervisor function. That function is closed.
+ * 2. The hypervisor and the management application quiesce all traffic to that
+ * function. The hypervisor requests a reduction in buffer pool size.
+ * 3. The management application acknowledges the reduction in buffer pool size.
+ * 4. The hypervisor sends a Remove Buffer message to the management partition,
+ * informing it of the reduction in buffers.
+ * 5. The management partition verifies it can remove the buffer. This is
+ * possible if buffers have been quiesced.
+ *
+ * Return:
+ * 0 - Success
+ * Non-zero - Failure
+ */
+/*
+ * The hypervisor requested that we pick an unused buffer, and return it.
+ * Before sending the buffer back, we free any storage associated with the
+ * buffer.
+ */
+static int ibmvmc_rem_buffer(struct crq_server_adapter *adapter,
+ struct ibmvmc_crq_msg *crq)
+{
+ struct ibmvmc_buffer *buffer;
+ u8 hmc_index;
+ u8 hmc_session;
+ u16 buffer_id = 0;
+ unsigned long flags;
+ int rc = 0;
+
+ if (!crq)
+ return -1;
+
+ hmc_session = crq->hmc_session;
+ hmc_index = crq->hmc_index;
+
+ if (hmc_index > ibmvmc.max_hmc_index) {
+ dev_warn(adapter->dev, "rem_buffer: invalid hmc_index = 0x%x\n",
+ hmc_index);
+ ibmvmc_send_rem_buffer_resp(adapter, VMC_MSG_INVALID_HMC_INDEX,
+ hmc_session, hmc_index, buffer_id);
+ return -1;
+ }
+
+ spin_lock_irqsave(&hmcs[hmc_index].lock, flags);
+ buffer = ibmvmc_get_free_hmc_buffer(adapter, hmc_index);
+ if (!buffer) {
+ dev_info(adapter->dev, "rem_buffer: no buffer to remove\n");
+ spin_unlock_irqrestore(&hmcs[hmc_index].lock, flags);
+ ibmvmc_send_rem_buffer_resp(adapter, VMC_MSG_NO_BUFFER,
+ hmc_session, hmc_index,
+ VMC_INVALID_BUFFER_ID);
+ return -1;
+ }
+
+ buffer_id = buffer->id;
+
+ if (buffer->valid)
+ free_dma_buffer(to_vio_dev(adapter->dev),
+ ibmvmc.max_mtu,
+ buffer->real_addr_local,
+ buffer->dma_addr_local);
+
+ memset(buffer, 0, sizeof(struct ibmvmc_buffer));
+ spin_unlock_irqrestore(&hmcs[hmc_index].lock, flags);
+
+ dev_dbg(adapter->dev, "rem_buffer: removed buffer 0x%x.\n", buffer_id);
+ ibmvmc_send_rem_buffer_resp(adapter, VMC_MSG_SUCCESS, hmc_session,
+ hmc_index, buffer_id);
+
+ return rc;
+}
+
+static int ibmvmc_recv_msg(struct crq_server_adapter *adapter,
+ struct ibmvmc_crq_msg *crq)
+{
+ struct ibmvmc_buffer *buffer;
+ struct ibmvmc_hmc *hmc;
+ unsigned long msg_len;
+ u8 hmc_index;
+ u8 hmc_session;
+ u16 buffer_id;
+ unsigned long flags;
+ int rc = 0;
+
+ if (!crq)
+ return -1;
+
+ /* Hypervisor writes CRQs directly into our memory in big endian */
+ dev_dbg(adapter->dev, "Recv_msg: msg from HV 0x%016llx 0x%016llx\n",
+ be64_to_cpu(*((unsigned long *)crq)),
+ be64_to_cpu(*(((unsigned long *)crq) + 1)));
+
+ hmc_session = crq->hmc_session;
+ hmc_index = crq->hmc_index;
+ buffer_id = be16_to_cpu(crq->var2.buffer_id);
+ msg_len = be32_to_cpu(crq->var3.msg_len);
+
+ if (hmc_index > ibmvmc.max_hmc_index) {
+ dev_err(adapter->dev, "Recv_msg: invalid hmc_index = 0x%x\n",
+ hmc_index);
+ ibmvmc_send_add_buffer_resp(adapter, VMC_MSG_INVALID_HMC_INDEX,
+ hmc_session, hmc_index, buffer_id);
+ return -1;
+ }
+
+ if (buffer_id >= ibmvmc.max_buffer_pool_size) {
+ dev_err(adapter->dev, "Recv_msg: invalid buffer_id = 0x%x\n",
+ buffer_id);
+ ibmvmc_send_add_buffer_resp(adapter, VMC_MSG_INVALID_BUFFER_ID,
+ hmc_session, hmc_index, buffer_id);
+ return -1;
+ }
+
+ hmc = &hmcs[hmc_index];
+ spin_lock_irqsave(&hmc->lock, flags);
+
+ if (hmc->state == ibmhmc_state_free) {
+ dev_err(adapter->dev, "Recv_msg: invalid hmc state = 0x%x\n",
+ hmc->state);
+ /* HMC connection is not valid (possibly was reset under us). */
+ spin_unlock_irqrestore(&hmc->lock, flags);
+ return -1;
+ }
+
+ buffer = &hmc->buffer[buffer_id];
+
+ if (buffer->valid == 0 || buffer->owner == VMC_BUF_OWNER_ALPHA) {
+ dev_err(adapter->dev, "Recv_msg: not valid, or not HV. 0x%x 0x%x\n",
+ buffer->valid, buffer->owner);
+ spin_unlock_irqrestore(&hmc->lock, flags);
+ return -1;
+ }
+
+ /* RDMA the data into the partition. */
+ rc = h_copy_rdma(msg_len,
+ adapter->riobn,
+ buffer->dma_addr_remote,
+ adapter->liobn,
+ buffer->dma_addr_local);
+
+ dev_dbg(adapter->dev, "Recv_msg: msg_len = 0x%x, buffer_id = 0x%x, queue_head = 0x%x, hmc_idx = 0x%x\n",
+ (unsigned int)msg_len, (unsigned int)buffer_id,
+ (unsigned int)hmc->queue_head, (unsigned int)hmc_index);
+ buffer->msg_len = msg_len;
+ buffer->free = 0;
+ buffer->owner = VMC_BUF_OWNER_ALPHA;
+
+ if (rc) {
+ dev_err(adapter->dev, "Failure in recv_msg: h_copy_rdma = 0x%x\n",
+ rc);
+ spin_unlock_irqrestore(&hmc->lock, flags);
+ return -1;
+ }
+
+ /* Must be locked because read operates on the same data */
+ hmc->queue_outbound_msgs[hmc->queue_head] = buffer_id;
+ hmc->queue_head++;
+ if (hmc->queue_head == ibmvmc_max_buf_pool_size)
+ hmc->queue_head = 0;
+
+ if (hmc->queue_head == hmc->queue_tail)
+ dev_err(adapter->dev, "outbound buffer queue wrapped.\n");
+
+ spin_unlock_irqrestore(&hmc->lock, flags);
+
+ wake_up_interruptible(&ibmvmc_read_wait);
+
+ return 0;
+}
+
+/**
+ * ibmvmc_process_capabilities - Process Capabilities
+ *
+ * @adapter: crq_server_adapter struct
+ * @crqp: ibmvmc_crq_msg struct
+ *
+ */
+static void ibmvmc_process_capabilities(struct crq_server_adapter *adapter,
+ struct ibmvmc_crq_msg *crqp)
+{
+ struct ibmvmc_admin_crq_msg *crq = (struct ibmvmc_admin_crq_msg *)crqp;
+
+ if ((be16_to_cpu(crq->version) >> 8) !=
+ (IBMVMC_PROTOCOL_VERSION >> 8)) {
+ dev_err(adapter->dev, "init failed, incompatible versions 0x%x 0x%x\n",
+ be16_to_cpu(crq->version),
+ IBMVMC_PROTOCOL_VERSION);
+ ibmvmc.state = ibmvmc_state_failed;
+ return;
+ }
+
+ ibmvmc.max_mtu = min_t(u32, ibmvmc_max_mtu, be32_to_cpu(crq->max_mtu));
+ ibmvmc.max_buffer_pool_size = min_t(u16, ibmvmc_max_buf_pool_size,
+ be16_to_cpu(crq->pool_size));
+ ibmvmc.max_hmc_index = min_t(u8, ibmvmc_max_hmcs, crq->max_hmc) - 1;
+ ibmvmc.state = ibmvmc_state_ready;
+
+ dev_info(adapter->dev, "Capabilities: mtu=0x%x, pool_size=0x%x, max_hmc=0x%x\n",
+ ibmvmc.max_mtu, ibmvmc.max_buffer_pool_size,
+ ibmvmc.max_hmc_index);
+}
+
+/**
+ * ibmvmc_validate_hmc_session - Validate HMC Session
+ *
+ * @adapter: crq_server_adapter struct
+ * @crq: ibmvmc_crq_msg struct
+ *
+ * Return:
+ * 0 - Success
+ * Non-zero - Failure
+ */
+static int ibmvmc_validate_hmc_session(struct crq_server_adapter *adapter,
+ struct ibmvmc_crq_msg *crq)
+{
+ unsigned char hmc_index;
+
+ hmc_index = crq->hmc_index;
+
+ if (crq->hmc_session == 0)
+ return 0;
+
+ if (hmc_index > ibmvmc.max_hmc_index)
+ return -1;
+
+ if (hmcs[hmc_index].session != crq->hmc_session) {
+ dev_warn(adapter->dev, "Drop, bad session: expected 0x%x, recv 0x%x\n",
+ hmcs[hmc_index].session, crq->hmc_session);
+ return -1;
+ }
+
+ return 0;
+}
+
+/**
+ * ibmvmc_reset - Reset
+ *
+ * @adapter: crq_server_adapter struct
+ * @xport_event: export_event field
+ *
+ * Closes all HMC sessions and conditionally schedules a CRQ reset.
+ * @xport_event: If true, the partner closed their CRQ; we don't need to reset.
+ * If false, we need to schedule a CRQ reset.
+ */
+static void ibmvmc_reset(struct crq_server_adapter *adapter, bool xport_event)
+{
+ int i;
+
+ if (ibmvmc.state != ibmvmc_state_sched_reset) {
+ dev_info(adapter->dev, "*** Reset to initial state.\n");
+ for (i = 0; i < ibmvmc_max_hmcs; i++)
+ ibmvmc_return_hmc(&hmcs[i], xport_event);
+
+ if (xport_event) {
+ /* CRQ was closed by the partner. We don't need to do
+ * anything except set ourself to the correct state to
+ * handle init msgs.
+ */
+ ibmvmc.state = ibmvmc_state_crqinit;
+ } else {
+ /* The partner did not close their CRQ - instead, we're
+ * closing the CRQ on our end. Need to schedule this
+ * for process context, because CRQ reset may require a
+ * sleep.
+ *
+ * Setting ibmvmc.state here immediately prevents
+ * ibmvmc_open from completing until the reset
+ * completes in process context.
+ */
+ ibmvmc.state = ibmvmc_state_sched_reset;
+ dev_dbg(adapter->dev, "Device reset scheduled");
+ wake_up_interruptible(&adapter->reset_wait_queue);
+ }
+ }
+}
+
+/**
+ * ibmvmc_reset_task - Reset Task
+ *
+ * @data: Data field
+ *
+ * Performs a CRQ reset of the VMC device in process context.
+ * NOTE: This function should not be called directly, use ibmvmc_reset.
+ */
+static int ibmvmc_reset_task(void *data)
+{
+ struct crq_server_adapter *adapter = data;
+ int rc;
+
+ set_user_nice(current, -20);
+
+ while (!kthread_should_stop()) {
+ wait_event_interruptible(adapter->reset_wait_queue,
+ (ibmvmc.state == ibmvmc_state_sched_reset) ||
+ kthread_should_stop());
+
+ if (kthread_should_stop())
+ break;
+
+ dev_dbg(adapter->dev, "CRQ resetting in process context");
+ tasklet_disable(&adapter->work_task);
+
+ rc = ibmvmc_reset_crq_queue(adapter);
+
+ if (rc != H_SUCCESS && rc != H_RESOURCE) {
+ dev_err(adapter->dev, "Error initializing CRQ. rc = 0x%x\n",
+ rc);
+ ibmvmc.state = ibmvmc_state_failed;
+ } else {
+ ibmvmc.state = ibmvmc_state_crqinit;
+
+ if (ibmvmc_send_crq(adapter, 0xC001000000000000LL, 0)
+ != 0 && rc != H_RESOURCE)
+ dev_warn(adapter->dev, "Failed to send initialize CRQ message\n");
+ }
+
+ vio_enable_interrupts(to_vio_dev(adapter->dev));
+ tasklet_enable(&adapter->work_task);
+ }
+
+ return 0;
+}
+
+/**
+ * ibmvmc_process_open_resp - Process Open Response
+ *
+ * @crq: ibmvmc_crq_msg struct
+ * @adapter: crq_server_adapter struct
+ *
+ * This command is sent by the hypervisor in response to the Interface
+ * Open message. When this message is received, the indicated buffer is
+ * again available for management partition use.
+ */
+static void ibmvmc_process_open_resp(struct ibmvmc_crq_msg *crq,
+ struct crq_server_adapter *adapter)
+{
+ unsigned char hmc_index;
+ unsigned short buffer_id;
+
+ hmc_index = crq->hmc_index;
+ if (hmc_index > ibmvmc.max_hmc_index) {
+ /* Why would PHYP give an index > max negotiated? */
+ ibmvmc_reset(adapter, false);
+ return;
+ }
+
+ if (crq->status) {
+ dev_warn(adapter->dev, "open_resp: failed - status 0x%x\n",
+ crq->status);
+ ibmvmc_return_hmc(&hmcs[hmc_index], false);
+ return;
+ }
+
+ if (hmcs[hmc_index].state == ibmhmc_state_opening) {
+ buffer_id = be16_to_cpu(crq->var2.buffer_id);
+ if (buffer_id >= ibmvmc.max_buffer_pool_size) {
+ dev_err(adapter->dev, "open_resp: invalid buffer_id = 0x%x\n",
+ buffer_id);
+ hmcs[hmc_index].state = ibmhmc_state_failed;
+ } else {
+ ibmvmc_free_hmc_buffer(&hmcs[hmc_index],
+ &hmcs[hmc_index].buffer[buffer_id]);
+ hmcs[hmc_index].state = ibmhmc_state_ready;
+ dev_dbg(adapter->dev, "open_resp: set hmc state = ready\n");
+ }
+ } else {
+ dev_warn(adapter->dev, "open_resp: invalid hmc state (0x%x)\n",
+ hmcs[hmc_index].state);
+ }
+}
+
+/**
+ * ibmvmc_process_close_resp - Process Close Response
+ *
+ * @crq: ibmvmc_crq_msg struct
+ * @adapter: crq_server_adapter struct
+ *
+ * This command is sent by the hypervisor in response to the managemant
+ * application Interface Close message.
+ *
+ * If the close fails, simply reset the entire driver as the state of the VMC
+ * must be in tough shape.
+ */
+static void ibmvmc_process_close_resp(struct ibmvmc_crq_msg *crq,
+ struct crq_server_adapter *adapter)
+{
+ unsigned char hmc_index;
+
+ hmc_index = crq->hmc_index;
+ if (hmc_index > ibmvmc.max_hmc_index) {
+ ibmvmc_reset(adapter, false);
+ return;
+ }
+
+ if (crq->status) {
+ dev_warn(adapter->dev, "close_resp: failed - status 0x%x\n",
+ crq->status);
+ ibmvmc_reset(adapter, false);
+ return;
+ }
+
+ ibmvmc_return_hmc(&hmcs[hmc_index], false);
+}
+
+/**
+ * ibmvmc_crq_process - Process CRQ
+ *
+ * @adapter: crq_server_adapter struct
+ * @crq: ibmvmc_crq_msg struct
+ *
+ * Process the CRQ message based upon the type of message received.
+ *
+ */
+static void ibmvmc_crq_process(struct crq_server_adapter *adapter,
+ struct ibmvmc_crq_msg *crq)
+{
+ switch (crq->type) {
+ case VMC_MSG_CAP_RESP:
+ dev_dbg(adapter->dev, "CRQ recv: capabilities resp (0x%x)\n",
+ crq->type);
+ if (ibmvmc.state == ibmvmc_state_capabilities)
+ ibmvmc_process_capabilities(adapter, crq);
+ else
+ dev_warn(adapter->dev, "caps msg invalid in state 0x%x\n",
+ ibmvmc.state);
+ break;
+ case VMC_MSG_OPEN_RESP:
+ dev_dbg(adapter->dev, "CRQ recv: open resp (0x%x)\n",
+ crq->type);
+ if (ibmvmc_validate_hmc_session(adapter, crq) == 0)
+ ibmvmc_process_open_resp(crq, adapter);
+ break;
+ case VMC_MSG_ADD_BUF:
+ dev_dbg(adapter->dev, "CRQ recv: add buf (0x%x)\n",
+ crq->type);
+ if (ibmvmc_validate_hmc_session(adapter, crq) == 0)
+ ibmvmc_add_buffer(adapter, crq);
+ break;
+ case VMC_MSG_REM_BUF:
+ dev_dbg(adapter->dev, "CRQ recv: rem buf (0x%x)\n",
+ crq->type);
+ if (ibmvmc_validate_hmc_session(adapter, crq) == 0)
+ ibmvmc_rem_buffer(adapter, crq);
+ break;
+ case VMC_MSG_SIGNAL:
+ dev_dbg(adapter->dev, "CRQ recv: signal msg (0x%x)\n",
+ crq->type);
+ if (ibmvmc_validate_hmc_session(adapter, crq) == 0)
+ ibmvmc_recv_msg(adapter, crq);
+ break;
+ case VMC_MSG_CLOSE_RESP:
+ dev_dbg(adapter->dev, "CRQ recv: close resp (0x%x)\n",
+ crq->type);
+ if (ibmvmc_validate_hmc_session(adapter, crq) == 0)
+ ibmvmc_process_close_resp(crq, adapter);
+ break;
+ case VMC_MSG_CAP:
+ case VMC_MSG_OPEN:
+ case VMC_MSG_CLOSE:
+ case VMC_MSG_ADD_BUF_RESP:
+ case VMC_MSG_REM_BUF_RESP:
+ dev_warn(adapter->dev, "CRQ recv: unexpected msg (0x%x)\n",
+ crq->type);
+ break;
+ default:
+ dev_warn(adapter->dev, "CRQ recv: unknown msg (0x%x)\n",
+ crq->type);
+ break;
+ }
+}
+
+/**
+ * ibmvmc_handle_crq_init - Handle CRQ Init
+ *
+ * @crq: ibmvmc_crq_msg struct
+ * @adapter: crq_server_adapter struct
+ *
+ * Handle the type of crq initialization based on whether
+ * it is a message or a response.
+ *
+ */
+static void ibmvmc_handle_crq_init(struct ibmvmc_crq_msg *crq,
+ struct crq_server_adapter *adapter)
+{
+ switch (crq->type) {
+ case 0x01: /* Initialization message */
+ dev_dbg(adapter->dev, "CRQ recv: CRQ init msg - state 0x%x\n",
+ ibmvmc.state);
+ if (ibmvmc.state == ibmvmc_state_crqinit) {
+ /* Send back a response */
+ if (ibmvmc_send_crq(adapter, 0xC002000000000000,
+ 0) == 0)
+ ibmvmc_send_capabilities(adapter);
+ else
+ dev_err(adapter->dev, " Unable to send init rsp\n");
+ } else {
+ dev_err(adapter->dev, "Invalid state 0x%x mtu = 0x%x\n",
+ ibmvmc.state, ibmvmc.max_mtu);
+ }
+
+ break;
+ case 0x02: /* Initialization response */
+ dev_dbg(adapter->dev, "CRQ recv: initialization resp msg - state 0x%x\n",
+ ibmvmc.state);
+ if (ibmvmc.state == ibmvmc_state_crqinit)
+ ibmvmc_send_capabilities(adapter);
+ break;
+ default:
+ dev_warn(adapter->dev, "Unknown crq message type 0x%lx\n",
+ (unsigned long)crq->type);
+ }
+}
+
+/**
+ * ibmvmc_handle_crq - Handle CRQ
+ *
+ * @crq: ibmvmc_crq_msg struct
+ * @adapter: crq_server_adapter struct
+ *
+ * Read the command elements from the command queue and execute the
+ * requests based upon the type of crq message.
+ *
+ */
+static void ibmvmc_handle_crq(struct ibmvmc_crq_msg *crq,
+ struct crq_server_adapter *adapter)
+{
+ switch (crq->valid) {
+ case 0xC0: /* initialization */
+ ibmvmc_handle_crq_init(crq, adapter);
+ break;
+ case 0xFF: /* Hypervisor telling us the connection is closed */
+ dev_warn(adapter->dev, "CRQ recv: virtual adapter failed - resetting.\n");
+ ibmvmc_reset(adapter, true);
+ break;
+ case 0x80: /* real payload */
+ ibmvmc_crq_process(adapter, crq);
+ break;
+ default:
+ dev_warn(adapter->dev, "CRQ recv: unknown msg 0x%02x.\n",
+ crq->valid);
+ break;
+ }
+}
+
+static void ibmvmc_task(unsigned long data)
+{
+ struct crq_server_adapter *adapter =
+ (struct crq_server_adapter *)data;
+ struct vio_dev *vdev = to_vio_dev(adapter->dev);
+ struct ibmvmc_crq_msg *crq;
+ int done = 0;
+
+ while (!done) {
+ /* Pull all the valid messages off the CRQ */
+ while ((crq = crq_queue_next_crq(&adapter->queue)) != NULL) {
+ ibmvmc_handle_crq(crq, adapter);
+ crq->valid = 0x00;
+ /* CRQ reset was requested, stop processing CRQs.
+ * Interrupts will be re-enabled by the reset task.
+ */
+ if (ibmvmc.state == ibmvmc_state_sched_reset)
+ return;
+ }
+
+ vio_enable_interrupts(vdev);
+ crq = crq_queue_next_crq(&adapter->queue);
+ if (crq) {
+ vio_disable_interrupts(vdev);
+ ibmvmc_handle_crq(crq, adapter);
+ crq->valid = 0x00;
+ /* CRQ reset was requested, stop processing CRQs.
+ * Interrupts will be re-enabled by the reset task.
+ */
+ if (ibmvmc.state == ibmvmc_state_sched_reset)
+ return;
+ } else {
+ done = 1;
+ }
+ }
+}
+
+/**
+ * ibmvmc_init_crq_queue - Init CRQ Queue
+ *
+ * @adapter: crq_server_adapter struct
+ *
+ * Return:
+ * 0 - Success
+ * Non-zero - Failure
+ */
+static int ibmvmc_init_crq_queue(struct crq_server_adapter *adapter)
+{
+ struct vio_dev *vdev = to_vio_dev(adapter->dev);
+ struct crq_queue *queue = &adapter->queue;
+ int rc = 0;
+ int retrc = 0;
+
+ queue->msgs = (struct ibmvmc_crq_msg *)get_zeroed_page(GFP_KERNEL);
+
+ if (!queue->msgs)
+ goto malloc_failed;
+
+ queue->size = PAGE_SIZE / sizeof(*queue->msgs);
+
+ queue->msg_token = dma_map_single(adapter->dev, queue->msgs,
+ queue->size * sizeof(*queue->msgs),
+ DMA_BIDIRECTIONAL);
+
+ if (dma_mapping_error(adapter->dev, queue->msg_token))
+ goto map_failed;
+
+ retrc = plpar_hcall_norets(H_REG_CRQ,
+ vdev->unit_address,
+ queue->msg_token, PAGE_SIZE);
+ retrc = rc;
+
+ if (rc == H_RESOURCE)
+ rc = ibmvmc_reset_crq_queue(adapter);
+
+ if (rc == 2) {
+ dev_warn(adapter->dev, "Partner adapter not ready\n");
+ retrc = 0;
+ } else if (rc != 0) {
+ dev_err(adapter->dev, "Error %d opening adapter\n", rc);
+ goto reg_crq_failed;
+ }
+
+ queue->cur = 0;
+ spin_lock_init(&queue->lock);
+
+ tasklet_init(&adapter->work_task, ibmvmc_task, (unsigned long)adapter);
+
+ if (request_irq(vdev->irq,
+ ibmvmc_handle_event,
+ 0, "ibmvmc", (void *)adapter) != 0) {
+ dev_err(adapter->dev, "couldn't register irq 0x%x\n",
+ vdev->irq);
+ goto req_irq_failed;
+ }
+
+ rc = vio_enable_interrupts(vdev);
+ if (rc != 0) {
+ dev_err(adapter->dev, "Error %d enabling interrupts!!!\n", rc);
+ goto req_irq_failed;
+ }
+
+ return retrc;
+
+req_irq_failed:
+ /* Cannot have any work since we either never got our IRQ registered,
+ * or never got interrupts enabled
+ */
+ tasklet_kill(&adapter->work_task);
+ h_free_crq(vdev->unit_address);
+reg_crq_failed:
+ dma_unmap_single(adapter->dev,
+ queue->msg_token,
+ queue->size * sizeof(*queue->msgs), DMA_BIDIRECTIONAL);
+map_failed:
+ free_page((unsigned long)queue->msgs);
+malloc_failed:
+ return -ENOMEM;
+}
+
+/* Fill in the liobn and riobn fields on the adapter */
+static int read_dma_window(struct vio_dev *vdev,
+ struct crq_server_adapter *adapter)
+{
+ const __be32 *dma_window;
+ const __be32 *prop;
+
+ /* TODO Using of_parse_dma_window would be better, but it doesn't give
+ * a way to read multiple windows without already knowing the size of
+ * a window or the number of windows
+ */
+ dma_window =
+ (const __be32 *)vio_get_attribute(vdev, "ibm,my-dma-window",
+ NULL);
+ if (!dma_window) {
+ dev_warn(adapter->dev, "Couldn't find ibm,my-dma-window property\n");
+ return -1;
+ }
+
+ adapter->liobn = be32_to_cpu(*dma_window);
+ dma_window++;
+
+ prop = (const __be32 *)vio_get_attribute(vdev, "ibm,#dma-address-cells",
+ NULL);
+ if (!prop) {
+ dev_warn(adapter->dev, "Couldn't find ibm,#dma-address-cells property\n");
+ dma_window++;
+ } else {
+ dma_window += be32_to_cpu(*prop);
+ }
+
+ prop = (const __be32 *)vio_get_attribute(vdev, "ibm,#dma-size-cells",
+ NULL);
+ if (!prop) {
+ dev_warn(adapter->dev, "Couldn't find ibm,#dma-size-cells property\n");
+ dma_window++;
+ } else {
+ dma_window += be32_to_cpu(*prop);
+ }
+
+ /* dma_window should point to the second window now */
+ adapter->riobn = be32_to_cpu(*dma_window);
+
+ return 0;
+}
+
+static int ibmvmc_probe(struct vio_dev *vdev, const struct vio_device_id *id)
+{
+ struct crq_server_adapter *adapter = &ibmvmc_adapter;
+ int rc;
+
+ dev_set_drvdata(&vdev->dev, NULL);
+ memset(adapter, 0, sizeof(*adapter));
+ adapter->dev = &vdev->dev;
+
+ dev_info(adapter->dev, "Probe for UA 0x%x\n", vdev->unit_address);
+
+ rc = read_dma_window(vdev, adapter);
+ if (rc != 0) {
+ ibmvmc.state = ibmvmc_state_failed;
+ return -1;
+ }
+
+ dev_dbg(adapter->dev, "Probe: liobn 0x%x, riobn 0x%x\n",
+ adapter->liobn, adapter->riobn);
+
+ init_waitqueue_head(&adapter->reset_wait_queue);
+ adapter->reset_task = kthread_run(ibmvmc_reset_task, adapter, "ibmvmc");
+ if (IS_ERR(adapter->reset_task)) {
+ dev_err(adapter->dev, "Failed to start reset thread\n");
+ ibmvmc.state = ibmvmc_state_failed;
+ rc = PTR_ERR(adapter->reset_task);
+ adapter->reset_task = NULL;
+ return rc;
+ }
+
+ rc = ibmvmc_init_crq_queue(adapter);
+ if (rc != 0 && rc != H_RESOURCE) {
+ dev_err(adapter->dev, "Error initializing CRQ. rc = 0x%x\n",
+ rc);
+ ibmvmc.state = ibmvmc_state_failed;
+ goto crq_failed;
+ }
+
+ ibmvmc.state = ibmvmc_state_crqinit;
+
+ /* Try to send an initialization message. Note that this is allowed
+ * to fail if the other end is not acive. In that case we just wait
+ * for the other side to initialize.
+ */
+ if (ibmvmc_send_crq(adapter, 0xC001000000000000LL, 0) != 0 &&
+ rc != H_RESOURCE)
+ dev_warn(adapter->dev, "Failed to send initialize CRQ message\n");
+
+ dev_set_drvdata(&vdev->dev, adapter);
+
+ return 0;
+
+crq_failed:
+ kthread_stop(adapter->reset_task);
+ adapter->reset_task = NULL;
+ return -EPERM;
+}
+
+static int ibmvmc_remove(struct vio_dev *vdev)
+{
+ struct crq_server_adapter *adapter = dev_get_drvdata(&vdev->dev);
+
+ dev_info(adapter->dev, "Entering remove for UA 0x%x\n",
+ vdev->unit_address);
+ ibmvmc_release_crq_queue(adapter);
+
+ return 0;
+}
+
+static struct vio_device_id ibmvmc_device_table[] = {
+ { "ibm,vmc", "IBM,vmc" },
+ { "", "" }
+};
+MODULE_DEVICE_TABLE(vio, ibmvmc_device_table);
+
+static struct vio_driver ibmvmc_driver = {
+ .name = ibmvmc_driver_name,
+ .id_table = ibmvmc_device_table,
+ .probe = ibmvmc_probe,
+ .remove = ibmvmc_remove,
+};
+
+static void __init ibmvmc_scrub_module_parms(void)
+{
+ if (ibmvmc_max_mtu > MAX_MTU) {
+ pr_warn("ibmvmc: Max MTU reduced to %d\n", MAX_MTU);
+ ibmvmc_max_mtu = MAX_MTU;
+ } else if (ibmvmc_max_mtu < MIN_MTU) {
+ pr_warn("ibmvmc: Max MTU increased to %d\n", MIN_MTU);
+ ibmvmc_max_mtu = MIN_MTU;
+ }
+
+ if (ibmvmc_max_buf_pool_size > MAX_BUF_POOL_SIZE) {
+ pr_warn("ibmvmc: Max buffer pool size reduced to %d\n",
+ MAX_BUF_POOL_SIZE);
+ ibmvmc_max_buf_pool_size = MAX_BUF_POOL_SIZE;
+ } else if (ibmvmc_max_buf_pool_size < MIN_BUF_POOL_SIZE) {
+ pr_warn("ibmvmc: Max buffer pool size increased to %d\n",
+ MIN_BUF_POOL_SIZE);
+ ibmvmc_max_buf_pool_size = MIN_BUF_POOL_SIZE;
+ }
+
+ if (ibmvmc_max_hmcs > MAX_HMCS) {
+ pr_warn("ibmvmc: Max HMCs reduced to %d\n", MAX_HMCS);
+ ibmvmc_max_hmcs = MAX_HMCS;
+ } else if (ibmvmc_max_hmcs < MIN_HMCS) {
+ pr_warn("ibmvmc: Max HMCs increased to %d\n", MIN_HMCS);
+ ibmvmc_max_hmcs = MIN_HMCS;
+ }
+}
+
+static struct miscdevice ibmvmc_miscdev = {
+ .name = ibmvmc_driver_name,
+ .minor = MISC_DYNAMIC_MINOR,
+ .fops = &ibmvmc_fops,
+};
+
+static int __init ibmvmc_module_init(void)
+{
+ int rc, i, j;
+
+ ibmvmc.state = ibmvmc_state_initial;
+ pr_info("ibmvmc: version %s\n", IBMVMC_DRIVER_VERSION);
+
+ rc = misc_register(&ibmvmc_miscdev);
+ if (rc) {
+ pr_err("ibmvmc: misc registration failed\n");
+ goto misc_register_failed;
+ }
+ pr_info("ibmvmc: node %d:%d\n", MISC_MAJOR,
+ ibmvmc_miscdev.minor);
+
+ /* Initialize data structures */
+ memset(hmcs, 0, sizeof(struct ibmvmc_hmc) * MAX_HMCS);
+ for (i = 0; i < MAX_HMCS; i++) {
+ spin_lock_init(&hmcs[i].lock);
+ hmcs[i].state = ibmhmc_state_free;
+ for (j = 0; j < MAX_BUF_POOL_SIZE; j++)
+ hmcs[i].queue_outbound_msgs[j] = VMC_INVALID_BUFFER_ID;
+ }
+
+ /* Sanity check module parms */
+ ibmvmc_scrub_module_parms();
+
+ /*
+ * Initialize some reasonable values. Might be negotiated smaller
+ * values during the capabilities exchange.
+ */
+ ibmvmc.max_mtu = ibmvmc_max_mtu;
+ ibmvmc.max_buffer_pool_size = ibmvmc_max_buf_pool_size;
+ ibmvmc.max_hmc_index = ibmvmc_max_hmcs - 1;
+
+ rc = vio_register_driver(&ibmvmc_driver);
+
+ if (rc) {
+ pr_err("ibmvmc: rc %d from vio_register_driver\n", rc);
+ goto vio_reg_failed;
+ }
+
+ return 0;
+
+vio_reg_failed:
+ misc_deregister(&ibmvmc_miscdev);
+misc_register_failed:
+ return rc;
+}
+
+static void __exit ibmvmc_module_exit(void)
+{
+ pr_info("ibmvmc: module exit\n");
+ vio_unregister_driver(&ibmvmc_driver);
+ misc_deregister(&ibmvmc_miscdev);
+}
+
+module_init(ibmvmc_module_init);
+module_exit(ibmvmc_module_exit);
+
+module_param_named(buf_pool_size, ibmvmc_max_buf_pool_size,
+ int, 0644);
+MODULE_PARM_DESC(buf_pool_size, "Buffer pool size");
+module_param_named(max_hmcs, ibmvmc_max_hmcs, int, 0644);
+MODULE_PARM_DESC(max_hmcs, "Max HMCs");
+module_param_named(max_mtu, ibmvmc_max_mtu, int, 0644);
+MODULE_PARM_DESC(max_mtu, "Max MTU");
+
+MODULE_AUTHOR("Steven Royer <seroyer@linux.vnet.ibm.com>");
+MODULE_DESCRIPTION("IBM VMC");
+MODULE_VERSION(IBMVMC_DRIVER_VERSION);
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/misc/ibmvmc.h b/drivers/misc/ibmvmc.h
new file mode 100644
index 0000000..e140ada
--- /dev/null
+++ b/drivers/misc/ibmvmc.h
@@ -0,0 +1,209 @@
+/* SPDX-License-Identifier: GPL-2.0+
+ *
+ * linux/drivers/misc/ibmvmc.h
+ *
+ * IBM Power Systems Virtual Management Channel Support.
+ *
+ * Copyright (c) 2004, 2018 IBM Corp.
+ * Dave Engebretsen engebret@us.ibm.com
+ * Steven Royer seroyer@linux.vnet.ibm.com
+ * Adam Reznechek adreznec@linux.vnet.ibm.com
+ * Bryant G. Ly <bryantly@linux.vnet.ibm.com>
+ */
+#ifndef IBMVMC_H
+#define IBMVMC_H
+
+#include <linux/types.h>
+#include <linux/cdev.h>
+
+#include <asm/vio.h>
+
+#define IBMVMC_PROTOCOL_VERSION 0x0101
+
+#define MIN_BUF_POOL_SIZE 16
+#define MIN_HMCS 1
+#define MIN_MTU 4096
+#define MAX_BUF_POOL_SIZE 64
+#define MAX_HMCS 2
+#define MAX_MTU (4 * 4096)
+#define DEFAULT_BUF_POOL_SIZE 32
+#define DEFAULT_HMCS 1
+#define DEFAULT_MTU 4096
+#define HMC_ID_LEN 32
+
+#define VMC_INVALID_BUFFER_ID 0xFFFF
+
+/* ioctl numbers */
+#define VMC_BASE 0xCC
+#define VMC_IOCTL_SETHMCID _IOW(VMC_BASE, 0x00, unsigned char *)
+#define VMC_IOCTL_QUERY _IOR(VMC_BASE, 0x01, struct ibmvmc_query_struct)
+#define VMC_IOCTL_REQUESTVMC _IOR(VMC_BASE, 0x02, u32)
+
+#define VMC_MSG_CAP 0x01
+#define VMC_MSG_CAP_RESP 0x81
+#define VMC_MSG_OPEN 0x02
+#define VMC_MSG_OPEN_RESP 0x82
+#define VMC_MSG_CLOSE 0x03
+#define VMC_MSG_CLOSE_RESP 0x83
+#define VMC_MSG_ADD_BUF 0x04
+#define VMC_MSG_ADD_BUF_RESP 0x84
+#define VMC_MSG_REM_BUF 0x05
+#define VMC_MSG_REM_BUF_RESP 0x85
+#define VMC_MSG_SIGNAL 0x06
+
+#define VMC_MSG_SUCCESS 0
+#define VMC_MSG_INVALID_HMC_INDEX 1
+#define VMC_MSG_INVALID_BUFFER_ID 2
+#define VMC_MSG_CLOSED_HMC 3
+#define VMC_MSG_INTERFACE_FAILURE 4
+#define VMC_MSG_NO_BUFFER 5
+
+#define VMC_BUF_OWNER_ALPHA 0
+#define VMC_BUF_OWNER_HV 1
+
+enum ibmvmc_states {
+ ibmvmc_state_sched_reset = -1,
+ ibmvmc_state_initial = 0,
+ ibmvmc_state_crqinit = 1,
+ ibmvmc_state_capabilities = 2,
+ ibmvmc_state_ready = 3,
+ ibmvmc_state_failed = 4,
+};
+
+enum ibmhmc_states {
+ /* HMC connection not established */
+ ibmhmc_state_free = 0,
+
+ /* HMC connection established (open called) */
+ ibmhmc_state_initial = 1,
+
+ /* open msg sent to HV, due to ioctl(1) call */
+ ibmhmc_state_opening = 2,
+
+ /* HMC connection ready, open resp msg from HV */
+ ibmhmc_state_ready = 3,
+
+ /* HMC connection failure */
+ ibmhmc_state_failed = 4,
+};
+
+struct ibmvmc_buffer {
+ u8 valid; /* 1 when DMA storage allocated to buffer */
+ u8 free; /* 1 when buffer available for the Alpha Partition */
+ u8 owner;
+ u16 id;
+ u32 size;
+ u32 msg_len;
+ dma_addr_t dma_addr_local;
+ dma_addr_t dma_addr_remote;
+ void *real_addr_local;
+};
+
+struct ibmvmc_admin_crq_msg {
+ u8 valid; /* RPA Defined */
+ u8 type; /* ibmvmc msg type */
+ u8 status; /* Response msg status. Zero is success and on failure,
+ * either 1 - General Failure, or 2 - Invalid Version is
+ * returned.
+ */
+ u8 rsvd[2];
+ u8 max_hmc; /* Max # of independent HMC connections supported */
+ __be16 pool_size; /* Maximum number of buffers supported per HMC
+ * connection
+ */
+ __be32 max_mtu; /* Maximum message size supported (bytes) */
+ __be16 crq_size; /* # of entries available in the CRQ for the
+ * source partition. The target partition must
+ * limit the number of outstanding messages to
+ * one half or less.
+ */
+ __be16 version; /* Indicates the code level of the management partition
+ * or the hypervisor with the high-order byte
+ * indicating a major version and the low-order byte
+ * indicating a minor version.
+ */
+};
+
+struct ibmvmc_crq_msg {
+ u8 valid; /* RPA Defined */
+ u8 type; /* ibmvmc msg type */
+ u8 status; /* Response msg status */
+ union {
+ u8 rsvd; /* Reserved */
+ u8 owner;
+ } var1;
+ u8 hmc_session; /* Session Identifier for the current VMC connection */
+ u8 hmc_index; /* A unique HMC Idx would be used if multiple management
+ * applications running concurrently were desired
+ */
+ union {
+ __be16 rsvd;
+ __be16 buffer_id;
+ } var2;
+ __be32 rsvd;
+ union {
+ __be32 rsvd;
+ __be32 lioba;
+ __be32 msg_len;
+ } var3;
+};
+
+/* an RPA command/response transport queue */
+struct crq_queue {
+ struct ibmvmc_crq_msg *msgs;
+ int size, cur;
+ dma_addr_t msg_token;
+ spinlock_t lock;
+};
+
+/* VMC server adapter settings */
+struct crq_server_adapter {
+ struct device *dev;
+ struct crq_queue queue;
+ u32 liobn;
+ u32 riobn;
+ struct tasklet_struct work_task;
+ wait_queue_head_t reset_wait_queue;
+ struct task_struct *reset_task;
+};
+
+/* Driver wide settings */
+struct ibmvmc_struct {
+ u32 state;
+ u32 max_mtu;
+ u32 max_buffer_pool_size;
+ u32 max_hmc_index;
+ struct crq_server_adapter *adapter;
+ struct cdev cdev;
+ u32 vmc_drc_index;
+};
+
+struct ibmvmc_file_session;
+
+/* Connection specific settings */
+struct ibmvmc_hmc {
+ u8 session;
+ u8 index;
+ u32 state;
+ struct crq_server_adapter *adapter;
+ spinlock_t lock;
+ unsigned char hmc_id[HMC_ID_LEN];
+ struct ibmvmc_buffer buffer[MAX_BUF_POOL_SIZE];
+ unsigned short queue_outbound_msgs[MAX_BUF_POOL_SIZE];
+ int queue_head, queue_tail;
+ struct ibmvmc_file_session *file_session;
+};
+
+struct ibmvmc_file_session {
+ struct file *file;
+ struct ibmvmc_hmc *hmc;
+ bool valid;
+};
+
+struct ibmvmc_query_struct {
+ int have_vmc;
+ int state;
+ int vmc_drc_index;
+};
+
+#endif /* __IBMVMC_H */
--
2.7.2
^ permalink raw reply related
* Re: [PATCH 5/6 v2] bus: fsl-mc: supoprt dma configure for devices on fsl-mc bus
From: kbuild test robot @ 2018-04-26 0:00 UTC (permalink / raw)
To: Nipun Gupta
Cc: kbuild-all, robin.murphy, will.deacon, mark.rutland,
catalin.marinas, hch, gregkh, joro, robh+dt, m.szyprowski,
shawnguo, frowand.list, bhelgaas, iommu, linux-kernel, devicetree,
linux-arm-kernel, linuxppc-dev, linux-pci, bharat.bhushan,
stuyoder, laurentiu.tudor, leoyang.li, Nipun Gupta
In-Reply-To: <1523960514-25457-6-git-send-email-nipun.gupta@nxp.com>
[-- Attachment #1: Type: text/plain, Size: 2834 bytes --]
Hi Nipun,
Thank you for the patch! Yet something to improve:
[auto build test ERROR on linus/master]
[also build test ERROR on v4.17-rc2 next-20180424]
[cannot apply to iommu/next glikely/devicetree/next]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]
url: https://github.com/0day-ci/linux/commits/Nipun-Gupta/Support-for-fsl-mc-bus-and-its-devices-in-SMMU/20180418-034931
config: powerpc64-allmodconfig (attached as .config)
compiler: powerpc64-linux-gnu-gcc (Debian 7.2.0-11) 7.2.0
reproduce:
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
chmod +x ~/bin/make.cross
# save the attached .config to linux build tree
make.cross ARCH=powerpc64
All errors (new ones prefixed by >>):
drivers/bus/fsl-mc/fsl-mc-bus.c: In function 'fsl_mc_dma_configure':
>> drivers/bus/fsl-mc/fsl-mc-bus.c:137:9: error: too many arguments to function 'of_dma_configure'
return of_dma_configure(dev, dma_dev->of_node, 0);
^~~~~~~~~~~~~~~~
In file included from drivers/bus/fsl-mc/fsl-mc-bus.c:13:0:
include/linux/of_device.h:58:5: note: declared here
int of_dma_configure(struct device *dev, struct device_node *np);
^~~~~~~~~~~~~~~~
drivers/bus/fsl-mc/fsl-mc-bus.c: At top level:
>> drivers/bus/fsl-mc/fsl-mc-bus.c:161:3: error: 'struct bus_type' has no member named 'dma_configure'
.dma_configure = fsl_mc_dma_configure,
^~~~~~~~~~~~~
vim +/of_dma_configure +137 drivers/bus/fsl-mc/fsl-mc-bus.c
129
130 static int fsl_mc_dma_configure(struct device *dev)
131 {
132 struct device *dma_dev = dev;
133
134 while (dev_is_fsl_mc(dma_dev))
135 dma_dev = dma_dev->parent;
136
> 137 return of_dma_configure(dev, dma_dev->of_node, 0);
138 }
139
140 static ssize_t modalias_show(struct device *dev, struct device_attribute *attr,
141 char *buf)
142 {
143 struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev);
144
145 return sprintf(buf, "fsl-mc:v%08Xd%s\n", mc_dev->obj_desc.vendor,
146 mc_dev->obj_desc.type);
147 }
148 static DEVICE_ATTR_RO(modalias);
149
150 static struct attribute *fsl_mc_dev_attrs[] = {
151 &dev_attr_modalias.attr,
152 NULL,
153 };
154
155 ATTRIBUTE_GROUPS(fsl_mc_dev);
156
157 struct bus_type fsl_mc_bus_type = {
158 .name = "fsl-mc",
159 .match = fsl_mc_bus_match,
160 .uevent = fsl_mc_bus_uevent,
> 161 .dma_configure = fsl_mc_dma_configure,
162 .dev_groups = fsl_mc_dev_groups,
163 };
164 EXPORT_SYMBOL_GPL(fsl_mc_bus_type);
165
---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation
[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 56229 bytes --]
^ permalink raw reply
* Re: [PATCH V3] cpufreq: powernv: Fix the hardlockup by synchronus smp_call in timer interrupt
From: Viresh Kumar @ 2018-04-26 5:14 UTC (permalink / raw)
To: Shilpasri G Bhat
Cc: rjw, npiggin, benh, mpe, linux-pm, linuxppc-dev, linux-kernel,
ppaidipe, svaidy, stable
In-Reply-To: <1524653971-4919-1-git-send-email-shilpa.bhat@linux.vnet.ibm.com>
On 25-04-18, 16:29, Shilpasri G Bhat wrote:
> gpstate_timer_handler() uses synchronous smp_call to set the pstate
> on the requested core. This causes the below hard lockup:
>
> [c000003fe566b320] [c0000000001d5340] smp_call_function_single+0x110/0x180 (unreliable)
> [c000003fe566b390] [c0000000001d55e0] smp_call_function_any+0x180/0x250
> [c000003fe566b3f0] [c000000000acd3e8] gpstate_timer_handler+0x1e8/0x580
> [c000003fe566b4a0] [c0000000001b46b0] call_timer_fn+0x50/0x1c0
> [c000003fe566b520] [c0000000001b4958] expire_timers+0x138/0x1f0
> [c000003fe566b590] [c0000000001b4bf8] run_timer_softirq+0x1e8/0x270
> [c000003fe566b630] [c000000000d0d6c8] __do_softirq+0x158/0x3e4
> [c000003fe566b710] [c000000000114be8] irq_exit+0xe8/0x120
> [c000003fe566b730] [c000000000024d0c] timer_interrupt+0x9c/0xe0
> [c000003fe566b760] [c000000000009014] decrementer_common+0x114/0x120
> -- interrupt: 901 at doorbell_global_ipi+0x34/0x50
> LR = arch_send_call_function_ipi_mask+0x120/0x130
> [c000003fe566ba50] [c00000000004876c]
> arch_send_call_function_ipi_mask+0x4c/0x130
> [c000003fe566ba90] [c0000000001d59f0] smp_call_function_many+0x340/0x450
> [c000003fe566bb00] [c000000000075f18] pmdp_invalidate+0x98/0xe0
> [c000003fe566bb30] [c0000000003a1120] change_huge_pmd+0xe0/0x270
> [c000003fe566bba0] [c000000000349278] change_protection_range+0xb88/0xe40
> [c000003fe566bcf0] [c0000000003496c0] mprotect_fixup+0x140/0x340
> [c000003fe566bdb0] [c000000000349a74] SyS_mprotect+0x1b4/0x350
> [c000003fe566be30] [c00000000000b184] system_call+0x58/0x6c
>
> One way to avoid this is removing the smp-call. We can ensure that the timer
> always runs on one of the policy-cpus. If the timer gets migrated to a
> cpu outside the policy then re-queue it back on the policy->cpus. This way
> we can get rid of the smp-call which was being used to set the pstate
> on the policy->cpus.
>
> Fixes: 7bc54b652f13 (timers, cpufreq/powernv: Initialize the gpstate timer as pinned)
> Cc: <stable@vger.kernel.org> [4.8+]
> Reported-by: Nicholas Piggin <npiggin@gmail.com>
> Reported-by: Pridhiviraj Paidipeddi <ppaidipe@linux.vnet.ibm.com>
> Signed-off-by: Shilpasri G Bhat <shilpa.bhat@linux.vnet.ibm.com>
> ---
> Changes from V2:
> - Remove the check for active policy while requeing the migrated timer
> Changes from V1:
> - Remove smp_call in the pstate handler.
Acked-by: Viresh Kumar <viresh.kumar@linaro.org>
--
viresh
^ permalink raw reply
* Re: [PATCH V3] cpufreq: powernv: Fix the hardlockup by synchronus smp_call in timer interrupt
From: Vaidyanathan Srinivasan @ 2018-04-26 5:32 UTC (permalink / raw)
To: Shilpasri G Bhat
Cc: rjw, viresh.kumar, npiggin, benh, mpe, linux-pm, linuxppc-dev,
linux-kernel, ppaidipe, stable
In-Reply-To: <1524653971-4919-1-git-send-email-shilpa.bhat@linux.vnet.ibm.com>
* Shilpa Bhat <shilpa.bhat@linux.vnet.ibm.com> [2018-04-25 16:29:31]:
> gpstate_timer_handler() uses synchronous smp_call to set the pstate
> on the requested core. This causes the below hard lockup:
>
> [c000003fe566b320] [c0000000001d5340] smp_call_function_single+0x110/0x180 (unreliable)
> [c000003fe566b390] [c0000000001d55e0] smp_call_function_any+0x180/0x250
> [c000003fe566b3f0] [c000000000acd3e8] gpstate_timer_handler+0x1e8/0x580
> [c000003fe566b4a0] [c0000000001b46b0] call_timer_fn+0x50/0x1c0
> [c000003fe566b520] [c0000000001b4958] expire_timers+0x138/0x1f0
> [c000003fe566b590] [c0000000001b4bf8] run_timer_softirq+0x1e8/0x270
> [c000003fe566b630] [c000000000d0d6c8] __do_softirq+0x158/0x3e4
> [c000003fe566b710] [c000000000114be8] irq_exit+0xe8/0x120
> [c000003fe566b730] [c000000000024d0c] timer_interrupt+0x9c/0xe0
> [c000003fe566b760] [c000000000009014] decrementer_common+0x114/0x120
> -- interrupt: 901 at doorbell_global_ipi+0x34/0x50
> LR = arch_send_call_function_ipi_mask+0x120/0x130
> [c000003fe566ba50] [c00000000004876c]
> arch_send_call_function_ipi_mask+0x4c/0x130
> [c000003fe566ba90] [c0000000001d59f0] smp_call_function_many+0x340/0x450
> [c000003fe566bb00] [c000000000075f18] pmdp_invalidate+0x98/0xe0
> [c000003fe566bb30] [c0000000003a1120] change_huge_pmd+0xe0/0x270
> [c000003fe566bba0] [c000000000349278] change_protection_range+0xb88/0xe40
> [c000003fe566bcf0] [c0000000003496c0] mprotect_fixup+0x140/0x340
> [c000003fe566bdb0] [c000000000349a74] SyS_mprotect+0x1b4/0x350
> [c000003fe566be30] [c00000000000b184] system_call+0x58/0x6c
>
> One way to avoid this is removing the smp-call. We can ensure that the timer
> always runs on one of the policy-cpus. If the timer gets migrated to a
> cpu outside the policy then re-queue it back on the policy->cpus. This way
> we can get rid of the smp-call which was being used to set the pstate
> on the policy->cpus.
>
> Fixes: 7bc54b652f13 (timers, cpufreq/powernv: Initialize the gpstate timer as pinned)
> Cc: <stable@vger.kernel.org> [4.8+]
> Reported-by: Nicholas Piggin <npiggin@gmail.com>
> Reported-by: Pridhiviraj Paidipeddi <ppaidipe@linux.vnet.ibm.com>
> Signed-off-by: Shilpasri G Bhat <shilpa.bhat@linux.vnet.ibm.com>
> ---
> Changes from V2:
> - Remove the check for active policy while requeing the migrated timer
> Changes from V1:
> - Remove smp_call in the pstate handler.
>
> drivers/cpufreq/powernv-cpufreq.c | 14 +++++++++++---
> 1 file changed, 11 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/cpufreq/powernv-cpufreq.c b/drivers/cpufreq/powernv-cpufreq.c
> index 71f8682..e368e1f 100644
> --- a/drivers/cpufreq/powernv-cpufreq.c
> +++ b/drivers/cpufreq/powernv-cpufreq.c
> @@ -679,6 +679,16 @@ void gpstate_timer_handler(struct timer_list *t)
>
> if (!spin_trylock(&gpstates->gpstate_lock))
> return;
> + /*
> + * If the timer has migrated to the different cpu then bring
> + * it back to one of the policy->cpus
> + */
> + if (!cpumask_test_cpu(raw_smp_processor_id(), policy->cpus)) {
> + gpstates->timer.expires = jiffies + msecs_to_jiffies(1);
> + add_timer_on(&gpstates->timer, cpumask_first(policy->cpus));
> + spin_unlock(&gpstates->gpstate_lock);
> + return;
> + }
>
> /*
> * If PMCR was last updated was using fast_swtich then
> @@ -718,10 +728,8 @@ void gpstate_timer_handler(struct timer_list *t)
> if (gpstate_idx != gpstates->last_lpstate_idx)
> queue_gpstate_timer(gpstates);
>
> + set_pstate(&freq_data);
> spin_unlock(&gpstates->gpstate_lock);
> -
> - /* Timer may get migrated to a different cpu on cpu hot unplug */
> - smp_call_function_any(policy->cpus, set_pstate, &freq_data, 1);
> }
Fix looks good.
Acked-by: Vaidyanathan Srinivasan <svaidy@linux.vnet.ibm.com>
^ permalink raw reply
* Re: OOM killer invoked while still one forth of mem is available
From: Christophe LEROY @ 2018-04-26 6:10 UTC (permalink / raw)
To: David Rientjes; +Cc: linux-mm, linuxppc-dev@lists.ozlabs.org
In-Reply-To: <alpine.DEB.2.21.1804251253240.151692@chino.kir.corp.google.com>
Le 25/04/2018 à 21:57, David Rientjes a écrit :
> On Tue, 24 Apr 2018, christophe leroy wrote:
>
>> Hi
>>
>> Allthough there is still about one forth of memory available (7976kB
>> among 32MB), oom-killer is invoked and makes a victim.
>>
>> What could be the reason and how could it be solved ?
>>
>> [ 54.400754] S99watchdogd-ap invoked oom-killer:
>> gfp_mask=0x27000c0(GFP_KERNEL_ACCOUNT|__GFP_NOTRACK), nodemask=0,
>> order=1, oom_score_adj=0
>> [ 54.400815] CPU: 0 PID: 777 Comm: S99watchdogd-ap Not tainted
>> 4.9.85-local-knld-998 #5
>> [ 54.400830] Call Trace:
>> [ 54.400910] [c1ca5d10] [c0327d28] dump_header.isra.4+0x54/0x17c
>> (unreliable)
>> [ 54.400998] [c1ca5d50] [c0079d88] oom_kill_process+0xc4/0x414
>> [ 54.401067] [c1ca5d90] [c007a5c8] out_of_memory+0x35c/0x37c
>> [ 54.401220] [c1ca5dc0] [c007d68c] __alloc_pages_nodemask+0x8ec/0x9a8
>> [ 54.401318] [c1ca5e70] [c00169d4] copy_process.isra.9.part.10+0xdc/0x10d0
>> [ 54.401398] [c1ca5f00] [c0017b30] _do_fork+0xcc/0x2a8
>> [ 54.401473] [c1ca5f40] [c000a660] ret_from_syscall+0x0/0x38
>
> Looks like this is because the allocation is order-1, likely the
> allocation of a struct task_struct for a new process on fork.
I'm not sure I understand what you mean. The allocation is order 1, yes,
does it explains why OOM killer is invoked ?
>
> I'm interested in your platform, though, with 512KB and 8MB hugepages.
> Could you send the .config and also describe the system a bit more? How
> many cpus are there and does this always happen?
It is a home made board designed 15 years ago. There is only one CPU and
there is 32 Mbytes of DRAM on the board. The processor is a MPC866
(powerpc 8xx family). Its MMU supports 4 page sizes (4k, 16k, 512k and 8M).
Yes the problem always happens, it happens when the watchdogd get
started, at the end of the startup, and there is always approx 8Mbytes
available at that time.
We are running a 4.9.x kernel, with commit 4b91428699477 from 4.10
backported on it.
See .config below
Christophe
#
# Automatically generated file; DO NOT EDIT.
# Linux/powerpc 4.9.85 Kernel Configuration
#
# CONFIG_PPC64 is not set
#
# Processor support
#
# CONFIG_PPC_BOOK3S_32 is not set
# CONFIG_PPC_85xx is not set
CONFIG_PPC_8xx=y
# CONFIG_40x is not set
# CONFIG_44x is not set
# CONFIG_E200 is not set
CONFIG_8xx=y
CONFIG_PPC_8xx_PERF_EVENT=y
CONFIG_PPC_MMU_NOHASH=y
# CONFIG_PPC_MM_SLICES is not set
CONFIG_NOT_COHERENT_CACHE=y
# CONFIG_PPC_DOORBELL is not set
CONFIG_VDSO32=y
CONFIG_CPU_BIG_ENDIAN=y
CONFIG_PPC32=y
CONFIG_32BIT=y
# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set
# CONFIG_ARCH_DMA_ADDR_T_64BIT is not set
CONFIG_MMU=y
# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set
# CONFIG_NEED_PER_CPU_EMBED_FIRST_CHUNK is not set
CONFIG_NR_IRQS=512
CONFIG_STACKTRACE_SUPPORT=y
CONFIG_TRACE_IRQFLAGS_SUPPORT=y
CONFIG_LOCKDEP_SUPPORT=y
CONFIG_RWSEM_XCHGADD_ALGORITHM=y
CONFIG_ARCH_HAS_ILOG2_U32=y
CONFIG_GENERIC_HWEIGHT=y
CONFIG_ARCH_HAS_DMA_SET_COHERENT_MASK=y
CONFIG_PPC=y
# CONFIG_GENERIC_CSUM is not set
CONFIG_EARLY_PRINTK=y
CONFIG_PANIC_TIMEOUT=180
CONFIG_GENERIC_NVRAM=y
CONFIG_SCHED_OMIT_FRAME_POINTER=y
# CONFIG_ARCH_MAY_HAVE_PC_FDC is not set
# CONFIG_PPC_UDBG_16550 is not set
# CONFIG_GENERIC_TBSYNC is not set
CONFIG_AUDIT_ARCH=y
CONFIG_GENERIC_BUG=y
# CONFIG_EPAPR_BOOT is not set
CONFIG_DEFAULT_UIMAGE=y
CONFIG_ARCH_HIBERNATION_POSSIBLE=y
# CONFIG_PPC_DCR_NATIVE is not set
# CONFIG_PPC_DCR_MMIO is not set
CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
CONFIG_ARCH_SUPPORTS_UPROBES=y
CONFIG_PPC_EMULATE_SSTEP=y
CONFIG_PGTABLE_LEVELS=2
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
CONFIG_IRQ_WORK=y
#
# General setup
#
CONFIG_BROKEN_ON_SMP=y
CONFIG_INIT_ENV_ARG_LIMIT=32
CONFIG_CROSS_COMPILE="ppc-linux-"
# CONFIG_COMPILE_TEST is not set
CONFIG_LOCALVERSION="-s3k-dev"
CONFIG_LOCALVERSION_AUTO=y
CONFIG_HAVE_KERNEL_GZIP=y
CONFIG_KERNEL_GZIP=y
CONFIG_DEFAULT_HOSTNAME="(none)"
CONFIG_SYSVIPC=y
CONFIG_SYSVIPC_SYSCTL=y
# CONFIG_POSIX_MQUEUE is not set
CONFIG_CROSS_MEMORY_ATTACH=y
# CONFIG_FHANDLE is not set
# CONFIG_USELIB is not set
# CONFIG_AUDIT is not set
CONFIG_HAVE_ARCH_AUDITSYSCALL=y
#
# IRQ subsystem
#
CONFIG_GENERIC_IRQ_SHOW=y
CONFIG_GENERIC_IRQ_SHOW_LEVEL=y
CONFIG_IRQ_DOMAIN=y
CONFIG_IRQ_DOMAIN_DEBUG=y
CONFIG_IRQ_FORCED_THREADING=y
CONFIG_SPARSE_IRQ=y
CONFIG_GENERIC_TIME_VSYSCALL_OLD=y
CONFIG_GENERIC_CLOCKEVENTS=y
CONFIG_GENERIC_CMOS_UPDATE=y
#
# Timers subsystem
#
CONFIG_TICK_ONESHOT=y
CONFIG_HZ_PERIODIC=y
# CONFIG_NO_HZ_IDLE is not set
# CONFIG_NO_HZ is not set
CONFIG_HIGH_RES_TIMERS=y
#
# CPU/Task time and stats accounting
#
CONFIG_VIRT_CPU_ACCOUNTING=y
# CONFIG_TICK_CPU_ACCOUNTING is not set
CONFIG_VIRT_CPU_ACCOUNTING_NATIVE=y
# CONFIG_BSD_PROCESS_ACCT is not set
# CONFIG_TASKSTATS is not set
#
# RCU Subsystem
#
CONFIG_PREEMPT_RCU=y
# CONFIG_RCU_EXPERT is not set
CONFIG_SRCU=y
# CONFIG_TASKS_RCU is not set
CONFIG_RCU_STALL_COMMON=y
# CONFIG_TREE_RCU_TRACE is not set
# CONFIG_RCU_EXPEDITE_BOOT is not set
# CONFIG_BUILD_BIN2C is not set
# CONFIG_IKCONFIG is not set
CONFIG_LOG_BUF_SHIFT=17
CONFIG_NMI_LOG_BUF_SHIFT=13
# CONFIG_CGROUPS is not set
# CONFIG_CHECKPOINT_RESTORE is not set
# CONFIG_NAMESPACES is not set
# CONFIG_SCHED_AUTOGROUP is not set
# CONFIG_SYSFS_DEPRECATED is not set
# CONFIG_RELAY is not set
CONFIG_BLK_DEV_INITRD=y
CONFIG_INITRAMFS_SOURCE="initramfs.txt"
CONFIG_INITRAMFS_ROOT_UID=0
CONFIG_INITRAMFS_ROOT_GID=0
# CONFIG_RD_GZIP is not set
# CONFIG_RD_BZIP2 is not set
# CONFIG_RD_LZMA is not set
# CONFIG_RD_XZ is not set
# CONFIG_RD_LZO is not set
# CONFIG_RD_LZ4 is not set
# CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE is not set
CONFIG_CC_OPTIMIZE_FOR_SIZE=y
CONFIG_SYSCTL=y
CONFIG_ANON_INODES=y
CONFIG_SYSCTL_EXCEPTION_TRACE=y
CONFIG_BPF=y
CONFIG_EXPERT=y
CONFIG_MULTIUSER=y
# CONFIG_SGETMASK_SYSCALL is not set
# CONFIG_SYSFS_SYSCALL is not set
# CONFIG_SYSCTL_SYSCALL is not set
CONFIG_KALLSYMS=y
# CONFIG_KALLSYMS_ALL is not set
# CONFIG_KALLSYMS_ABSOLUTE_PERCPU is not set
CONFIG_KALLSYMS_BASE_RELATIVE=y
CONFIG_PRINTK=y
CONFIG_PRINTK_NMI=y
CONFIG_BUG=y
CONFIG_ELF_CORE=y
CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
CONFIG_SIGNALFD=y
CONFIG_TIMERFD=y
CONFIG_EVENTFD=y
# CONFIG_BPF_SYSCALL is not set
CONFIG_SHMEM=y
CONFIG_AIO=y
# CONFIG_ADVISE_SYSCALLS is not set
# CONFIG_USERFAULTFD is not set
CONFIG_MEMBARRIER=y
CONFIG_EMBEDDED=y
CONFIG_HAVE_PERF_EVENTS=y
#
# Kernel Performance Events And Counters
#
CONFIG_PERF_EVENTS=y
# CONFIG_VM_EVENT_COUNTERS is not set
# CONFIG_SLUB_DEBUG is not set
CONFIG_COMPAT_BRK=y
# CONFIG_SLAB is not set
CONFIG_SLUB=y
# CONFIG_SLOB is not set
# CONFIG_SLAB_FREELIST_RANDOM is not set
# CONFIG_SYSTEM_DATA_VERIFICATION is not set
CONFIG_PROFILING=y
# CONFIG_OPROFILE is not set
CONFIG_HAVE_OPROFILE=y
CONFIG_JUMP_LABEL=y
# CONFIG_STATIC_KEYS_SELFTEST is not set
# CONFIG_UPROBES is not set
# CONFIG_HAVE_64BIT_ALIGNED_ACCESS is not set
CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
CONFIG_ARCH_USE_BUILTIN_BSWAP=y
CONFIG_HAVE_IOREMAP_PROT=y
CONFIG_HAVE_KPROBES=y
CONFIG_HAVE_KRETPROBES=y
CONFIG_HAVE_NMI=y
CONFIG_HAVE_ARCH_TRACEHOOK=y
CONFIG_GENERIC_SMP_IDLE_THREAD=y
CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y
CONFIG_HAVE_DMA_API_DEBUG=y
CONFIG_HAVE_HW_BREAKPOINT=y
CONFIG_HAVE_PERF_REGS=y
CONFIG_HAVE_PERF_USER_STACK_DUMP=y
CONFIG_HAVE_ARCH_JUMP_LABEL=y
CONFIG_ARCH_HAVE_NMI_SAFE_CMPXCHG=y
CONFIG_ARCH_WANT_IPC_PARSE_VERSION=y
CONFIG_HAVE_ARCH_SECCOMP_FILTER=y
# CONFIG_CC_STACKPROTECTOR is not set
CONFIG_HAVE_VIRT_CPU_ACCOUNTING=y
CONFIG_HAVE_MOD_ARCH_SPECIFIC=y
CONFIG_MODULES_USE_ELF_RELA=y
CONFIG_HAVE_IRQ_EXIT_ON_IRQ_STACK=y
CONFIG_ARCH_HAS_ELF_RANDOMIZE=y
# CONFIG_HAVE_ARCH_HASH is not set
# CONFIG_ISA_BUS_API is not set
CONFIG_CLONE_BACKWARDS=y
CONFIG_OLD_SIGSUSPEND=y
CONFIG_OLD_SIGACTION=y
# CONFIG_CPU_NO_EFFICIENT_FFS is not set
# CONFIG_HAVE_ARCH_VMAP_STACK is not set
#
# GCOV-based kernel profiling
#
# CONFIG_GCOV_KERNEL is not set
CONFIG_ARCH_HAS_GCOV_PROFILE_ALL=y
# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
CONFIG_RT_MUTEXES=y
CONFIG_BASE_SMALL=0
# CONFIG_MODULES is not set
CONFIG_MODULES_TREE_LOOKUP=y
# CONFIG_BLOCK is not set
CONFIG_UNINLINE_SPIN_UNLOCK=y
CONFIG_ARCH_SUPPORTS_ATOMIC_RMW=y
# CONFIG_FREEZER is not set
# CONFIG_PPC_XICS is not set
# CONFIG_PPC_ICP_NATIVE is not set
# CONFIG_PPC_ICP_HV is not set
# CONFIG_PPC_ICS_RTAS is not set
# CONFIG_GE_FPGA is not set
#
# Platform support
#
# CONFIG_PPC_CELL is not set
# CONFIG_PPC_CELL_NATIVE is not set
CONFIG_CPM1=y
# CONFIG_MPC8XXFADS is not set
# CONFIG_MPC86XADS is not set
CONFIG_SAF3000_8XX=y
# CONFIG_MPC885ADS is not set
# CONFIG_PPC_EP88XC is not set
# CONFIG_PPC_ADDER875 is not set
# CONFIG_TQM8XX is not set
#
# MPC8xx CPM Options
#
#
# Generic MPC8xx Options
#
CONFIG_8xx_COPYBACK=y
CONFIG_8xx_GPIO=y
# CONFIG_8xx_CPU6 is not set
CONFIG_NO_UCODE_PATCH=y
# CONFIG_USB_SOF_UCODE_PATCH is not set
# CONFIG_I2C_SPI_UCODE_PATCH is not set
# CONFIG_I2C_SPI_SMC1_UCODE_PATCH is not set
# CONFIG_SMC_UCODE_PATCH is not set
# CONFIG_PQ2ADS is not set
# CONFIG_KVM_GUEST is not set
# CONFIG_EPAPR_PARAVIRT is not set
# CONFIG_IPIC is not set
# CONFIG_MPIC is not set
# CONFIG_PPC_EPAPR_HV_PIC is not set
# CONFIG_MPIC_WEIRD is not set
# CONFIG_PPC_I8259 is not set
# CONFIG_PPC_RTAS is not set
# CONFIG_MMIO_NVRAM is not set
# CONFIG_MPIC_U3_HT_IRQS is not set
# CONFIG_PPC_MPC106 is not set
# CONFIG_PPC_970_NAP is not set
# CONFIG_PPC_P7_NAP is not set
#
# CPU Frequency scaling
#
# CONFIG_CPU_FREQ is not set
#
# CPUIdle driver
#
#
# CPU Idle
#
# CONFIG_CPU_IDLE is not set
# CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED is not set
# CONFIG_FSL_ULI1575 is not set
CONFIG_CPM=y
CONFIG_GEN_RTC=y
CONFIG_SIMPLE_GPIO=y
#
# Kernel options
#
# CONFIG_HIGHMEM is not set
CONFIG_HZ_100=y
# CONFIG_HZ_250 is not set
# CONFIG_HZ_300 is not set
# CONFIG_HZ_1000 is not set
CONFIG_HZ=100
CONFIG_SCHED_HRTICK=y
# CONFIG_PREEMPT_NONE is not set
# CONFIG_PREEMPT_VOLUNTARY is not set
CONFIG_PREEMPT=y
CONFIG_PREEMPT_COUNT=y
CONFIG_BINFMT_ELF=y
CONFIG_ELFCORE=y
# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
CONFIG_BINFMT_SCRIPT=y
# CONFIG_HAVE_AOUT is not set
# CONFIG_BINFMT_MISC is not set
CONFIG_COREDUMP=y
CONFIG_HUGETLB_PAGE_SIZE_VARIABLE=y
# CONFIG_MATH_EMULATION is not set
# CONFIG_IOMMU_HELPER is not set
# CONFIG_SWIOTLB is not set
CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
CONFIG_ARCH_HAS_WALK_MEMORY=y
CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
CONFIG_ARCH_FLATMEM_ENABLE=y
CONFIG_SYS_SUPPORTS_HUGETLBFS=y
CONFIG_FLATMEM=y
CONFIG_FLAT_NODE_MEM_MAP=y
CONFIG_HAVE_MEMBLOCK=y
CONFIG_HAVE_MEMBLOCK_NODE_MAP=y
CONFIG_HAVE_GENERIC_RCU_GUP=y
CONFIG_NO_BOOTMEM=y
# CONFIG_HAVE_BOOTMEM_INFO_NODE is not set
CONFIG_SPLIT_PTLOCK_CPUS=4
CONFIG_COMPACTION=y
CONFIG_MIGRATION=y
# CONFIG_PHYS_ADDR_T_64BIT is not set
CONFIG_VIRT_TO_BUS=y
# CONFIG_KSM is not set
CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
CONFIG_NEED_PER_CPU_KM=y
# CONFIG_CLEANCACHE is not set
# CONFIG_CMA is not set
# CONFIG_ZPOOL is not set
# CONFIG_ZBUD is not set
# CONFIG_ZSMALLOC is not set
CONFIG_ARCH_SUPPORTS_DEFERRED_STRUCT_PAGE_INIT=y
# CONFIG_IDLE_PAGE_TRACKING is not set
CONFIG_PPC_4K_PAGES=y
# CONFIG_PPC_16K_PAGES is not set
CONFIG_FORCE_MAX_ZONEORDER=12
# CONFIG_PPC_COPRO_BASE is not set
# CONFIG_CMDLINE_BOOL is not set
CONFIG_EXTRA_TARGETS="saf3000/mcr3000.dtb"
# CONFIG_PM is not set
# CONFIG_SECCOMP is not set
# CONFIG_ISA_DMA_API is not set
#
# Bus options
#
CONFIG_ZONE_DMA=y
CONFIG_NEED_DMA_MAP_STATE=y
CONFIG_NEED_SG_DMA_LENGTH=y
CONFIG_FSL_SOC=y
# CONFIG_FSL_LBC is not set
# CONFIG_PCI is not set
# CONFIG_PCI_DOMAINS is not set
# CONFIG_PCI_SYSCALL is not set
# CONFIG_PCI_QSPAN is not set
# CONFIG_PCCARD is not set
# CONFIG_HAS_RAPIDIO is not set
# CONFIG_NONSTATIC_KERNEL is not set
#
# Advanced setup
#
CONFIG_ADVANCED_OPTIONS=y
# CONFIG_LOWMEM_SIZE_BOOL is not set
CONFIG_LOWMEM_SIZE=0x30000000
# CONFIG_PAGE_OFFSET_BOOL is not set
CONFIG_PAGE_OFFSET=0xc0000000
# CONFIG_KERNEL_START_BOOL is not set
CONFIG_KERNEL_START=0xc0000000
CONFIG_PHYSICAL_START=0x00000000
# CONFIG_TASK_SIZE_BOOL is not set
CONFIG_TASK_SIZE=0x80000000
# CONFIG_CONSISTENT_SIZE_BOOL is not set
CONFIG_CONSISTENT_SIZE=0x00200000
CONFIG_PIN_TLB=y
CONFIG_PIN_TLB_IMMR=y
# CONFIG_ARCH_RANDOM is not set
CONFIG_NET=y
CONFIG_NET_INGRESS=y
#
# Networking options
#
CONFIG_PACKET=y
# CONFIG_PACKET_DIAG is not set
CONFIG_UNIX=y
# CONFIG_UNIX_DIAG is not set
# CONFIG_XFRM_USER is not set
# CONFIG_NET_KEY is not set
CONFIG_INET=y
CONFIG_IP_MULTICAST=y
# CONFIG_IP_ADVANCED_ROUTER is not set
# CONFIG_IP_PNP is not set
# CONFIG_NET_IPIP is not set
# CONFIG_NET_IPGRE_DEMUX is not set
# CONFIG_NET_IP_TUNNEL is not set
# CONFIG_IP_MROUTE is not set
CONFIG_SYN_COOKIES=y
# CONFIG_NET_UDP_TUNNEL is not set
# CONFIG_NET_FOU is not set
# CONFIG_INET_AH is not set
# CONFIG_INET_ESP is not set
# CONFIG_INET_IPCOMP is not set
# CONFIG_INET_XFRM_TUNNEL is not set
# CONFIG_INET_TUNNEL is not set
# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
# CONFIG_INET_XFRM_MODE_TUNNEL is not set
# CONFIG_INET_XFRM_MODE_BEET is not set
CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
# CONFIG_INET_UDP_DIAG is not set
# CONFIG_INET_DIAG_DESTROY is not set
# CONFIG_TCP_CONG_ADVANCED is not set
CONFIG_TCP_CONG_CUBIC=y
CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_TCP_MD5SIG is not set
# CONFIG_IPV6 is not set
# CONFIG_NETWORK_SECMARK is not set
# CONFIG_NET_PTP_CLASSIFY is not set
# CONFIG_NETWORK_PHY_TIMESTAMPING is not set
CONFIG_NETFILTER=y
# CONFIG_NETFILTER_DEBUG is not set
CONFIG_NETFILTER_ADVANCED=y
#
# Core Netfilter Configuration
#
CONFIG_NETFILTER_INGRESS=y
CONFIG_NETFILTER_NETLINK=y
# CONFIG_NETFILTER_NETLINK_ACCT is not set
# CONFIG_NETFILTER_NETLINK_QUEUE is not set
# CONFIG_NETFILTER_NETLINK_LOG is not set
CONFIG_NF_CONNTRACK=y
CONFIG_NF_LOG_COMMON=y
CONFIG_NF_CONNTRACK_MARK=y
CONFIG_NF_CONNTRACK_PROCFS=y
# CONFIG_NF_CONNTRACK_EVENTS is not set
# CONFIG_NF_CONNTRACK_TIMEOUT is not set
# CONFIG_NF_CONNTRACK_TIMESTAMP is not set
# CONFIG_NF_CT_PROTO_DCCP is not set
# CONFIG_NF_CT_PROTO_SCTP is not set
# CONFIG_NF_CT_PROTO_UDPLITE is not set
# CONFIG_NF_CONNTRACK_AMANDA is not set
CONFIG_NF_CONNTRACK_FTP=y
# CONFIG_NF_CONNTRACK_H323 is not set
# CONFIG_NF_CONNTRACK_IRC is not set
# CONFIG_NF_CONNTRACK_NETBIOS_NS is not set
# CONFIG_NF_CONNTRACK_SNMP is not set
# CONFIG_NF_CONNTRACK_PPTP is not set
# CONFIG_NF_CONNTRACK_SANE is not set
# CONFIG_NF_CONNTRACK_SIP is not set
CONFIG_NF_CONNTRACK_TFTP=y
CONFIG_NF_CT_NETLINK=y
# CONFIG_NF_CT_NETLINK_TIMEOUT is not set
CONFIG_NF_TABLES=y
# CONFIG_NF_TABLES_NETDEV is not set
# CONFIG_NFT_EXTHDR is not set
CONFIG_NFT_META=y
# CONFIG_NFT_NUMGEN is not set
CONFIG_NFT_CT=y
CONFIG_NFT_SET_RBTREE=y
# CONFIG_NFT_SET_HASH is not set
CONFIG_NFT_COUNTER=y
CONFIG_NFT_LOG=y
CONFIG_NFT_LIMIT=y
# CONFIG_NFT_NAT is not set
# CONFIG_NFT_QUOTA is not set
CONFIG_NFT_REJECT=y
CONFIG_NFT_HASH=y
# CONFIG_NETFILTER_XTABLES is not set
# CONFIG_IP_SET is not set
# CONFIG_IP_VS is not set
#
# IP: Netfilter Configuration
#
CONFIG_NF_DEFRAG_IPV4=y
CONFIG_NF_CONNTRACK_IPV4=y
CONFIG_NF_TABLES_IPV4=y
# CONFIG_NFT_CHAIN_ROUTE_IPV4 is not set
CONFIG_NFT_REJECT_IPV4=y
# CONFIG_NFT_DUP_IPV4 is not set
# CONFIG_NF_TABLES_ARP is not set
# CONFIG_NF_DUP_IPV4 is not set
# CONFIG_NF_LOG_ARP is not set
CONFIG_NF_LOG_IPV4=y
CONFIG_NF_REJECT_IPV4=y
# CONFIG_NF_NAT_IPV4 is not set
# CONFIG_IP_NF_IPTABLES is not set
# CONFIG_IP_NF_ARPTABLES is not set
# CONFIG_IP_DCCP is not set
# CONFIG_IP_SCTP is not set
# CONFIG_RDS is not set
# CONFIG_TIPC is not set
# CONFIG_ATM is not set
# CONFIG_L2TP is not set
CONFIG_STP=y
CONFIG_GARP=y
# CONFIG_BRIDGE is not set
CONFIG_HAVE_NET_DSA=y
# CONFIG_NET_DSA is not set
CONFIG_VLAN_8021Q=y
CONFIG_VLAN_8021Q_GVRP=y
# CONFIG_VLAN_8021Q_MVRP is not set
# CONFIG_DECNET is not set
CONFIG_LLC=y
# CONFIG_LLC2 is not set
# CONFIG_IPX is not set
# CONFIG_ATALK is not set
# CONFIG_X25 is not set
# CONFIG_LAPB is not set
# CONFIG_PHONET is not set
# CONFIG_IEEE802154 is not set
# CONFIG_NET_SCHED is not set
# CONFIG_DCB is not set
# CONFIG_BATMAN_ADV is not set
# CONFIG_OPENVSWITCH is not set
# CONFIG_VSOCKETS is not set
# CONFIG_NETLINK_DIAG is not set
# CONFIG_MPLS is not set
# CONFIG_HSR is not set
# CONFIG_NET_SWITCHDEV is not set
# CONFIG_NET_L3_MASTER_DEV is not set
# CONFIG_NET_NCSI is not set
# CONFIG_SOCK_CGROUP_DATA is not set
CONFIG_NET_RX_BUSY_POLL=y
CONFIG_BQL=y
#
# Network testing
#
# CONFIG_NET_PKTGEN is not set
# CONFIG_HAMRADIO is not set
# CONFIG_CAN is not set
# CONFIG_IRDA is not set
# CONFIG_BT is not set
# CONFIG_AF_RXRPC is not set
# CONFIG_AF_KCM is not set
# CONFIG_STREAM_PARSER is not set
# CONFIG_WIRELESS is not set
# CONFIG_WIMAX is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
# CONFIG_CAIF is not set
# CONFIG_CEPH_LIB is not set
# CONFIG_NFC is not set
# CONFIG_LWTUNNEL is not set
# CONFIG_DST_CACHE is not set
# CONFIG_NET_DEVLINK is not set
CONFIG_MAY_USE_DEVLINK=y
CONFIG_HAVE_CBPF_JIT=y
#
# Device Drivers
#
#
# Generic Driver Options
#
# CONFIG_UEVENT_HELPER is not set
CONFIG_DEVTMPFS=y
CONFIG_DEVTMPFS_MOUNT=y
CONFIG_STANDALONE=y
CONFIG_PREVENT_FIRMWARE_BUILD=y
CONFIG_FW_LOADER=y
# CONFIG_FIRMWARE_IN_KERNEL is not set
CONFIG_EXTRA_FIRMWARE=""
# CONFIG_FW_LOADER_USER_HELPER_FALLBACK is not set
# CONFIG_ALLOW_DEV_COREDUMP is not set
CONFIG_DEBUG_DRIVER=y
# CONFIG_DEBUG_DEVRES is not set
# CONFIG_DEBUG_TEST_DRIVER_REMOVE is not set
# CONFIG_SYS_HYPERVISOR is not set
# CONFIG_GENERIC_CPU_DEVICES is not set
CONFIG_GENERIC_CPU_AUTOPROBE=y
CONFIG_REGMAP=y
CONFIG_REGMAP_SPI=y
# CONFIG_DMA_SHARED_BUFFER is not set
#
# Bus devices
#
# CONFIG_CONNECTOR is not set
CONFIG_MTD=y
# CONFIG_MTD_REDBOOT_PARTS is not set
CONFIG_MTD_CMDLINE_PARTS=y
CONFIG_MTD_OF_PARTS=y
# CONFIG_MTD_AR7_PARTS is not set
#
# User Modules And Translation Layers
#
# CONFIG_MTD_OOPS is not set
# CONFIG_MTD_PARTITIONED_MASTER is not set
#
# RAM/ROM/Flash chip drivers
#
CONFIG_MTD_CFI=y
# CONFIG_MTD_JEDECPROBE is not set
CONFIG_MTD_GEN_PROBE=y
# CONFIG_MTD_CFI_ADV_OPTIONS is not set
CONFIG_MTD_MAP_BANK_WIDTH_1=y
CONFIG_MTD_MAP_BANK_WIDTH_2=y
CONFIG_MTD_MAP_BANK_WIDTH_4=y
# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
CONFIG_MTD_CFI_I1=y
CONFIG_MTD_CFI_I2=y
# CONFIG_MTD_CFI_I4 is not set
# CONFIG_MTD_CFI_I8 is not set
# CONFIG_MTD_CFI_INTELEXT is not set
CONFIG_MTD_CFI_AMDSTD=y
# CONFIG_MTD_CFI_STAA is not set
CONFIG_MTD_CFI_UTIL=y
# CONFIG_MTD_RAM is not set
# CONFIG_MTD_ROM is not set
# CONFIG_MTD_ABSENT is not set
#
# Mapping drivers for chip access
#
CONFIG_MTD_COMPLEX_MAPPINGS=y
# CONFIG_MTD_PHYSMAP is not set
CONFIG_MTD_PHYSMAP_OF=y
# CONFIG_MTD_CFI_FLAGADM is not set
# CONFIG_MTD_GPIO_ADDR is not set
# CONFIG_MTD_PLATRAM is not set
# CONFIG_MTD_LATCH_ADDR is not set
#
# Self-contained MTD device drivers
#
# CONFIG_MTD_DATAFLASH is not set
# CONFIG_MTD_SST25L is not set
# CONFIG_MTD_SLRAM is not set
# CONFIG_MTD_PHRAM is not set
# CONFIG_MTD_MTDRAM is not set
#
# Disk-On-Chip Device Drivers
#
# CONFIG_MTD_DOCG3 is not set
CONFIG_MTD_NAND_ECC=y
# CONFIG_MTD_NAND_ECC_SMC is not set
CONFIG_MTD_NAND=y
# CONFIG_MTD_NAND_ECC_BCH is not set
# CONFIG_MTD_SM_COMMON is not set
CONFIG_MTD_NAND_GPIO=y
# CONFIG_MTD_NAND_OMAP_BCH_BUILD is not set
CONFIG_MTD_NAND_IDS=y
# CONFIG_MTD_NAND_DISKONCHIP is not set
# CONFIG_MTD_NAND_DOCG4 is not set
# CONFIG_MTD_NAND_NANDSIM is not set
# CONFIG_MTD_NAND_PLATFORM is not set
# CONFIG_MTD_NAND_FSL_ELBC is not set
# CONFIG_MTD_NAND_FSL_IFC is not set
# CONFIG_MTD_NAND_HISI504 is not set
# CONFIG_MTD_NAND_MTK is not set
# CONFIG_MTD_ONENAND is not set
#
# LPDDR & LPDDR2 PCM memory drivers
#
# CONFIG_MTD_LPDDR is not set
# CONFIG_MTD_SPI_NOR is not set
CONFIG_MTD_UBI=y
CONFIG_MTD_UBI_WL_THRESHOLD=4096
CONFIG_MTD_UBI_BEB_LIMIT=20
# CONFIG_MTD_UBI_FASTMAP is not set
# CONFIG_MTD_UBI_GLUEBI is not set
CONFIG_DTC=y
CONFIG_OF=y
# CONFIG_OF_UNITTEST is not set
CONFIG_OF_FLATTREE=y
CONFIG_OF_EARLY_FLATTREE=y
CONFIG_OF_ADDRESS=y
CONFIG_OF_IRQ=y
CONFIG_OF_NET=y
CONFIG_OF_MDIO=y
CONFIG_OF_RESERVED_MEM=y
# CONFIG_OF_OVERLAY is not set
CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y
# CONFIG_PARPORT is not set
#
# Misc devices
#
# CONFIG_AD525X_DPOT is not set
# CONFIG_DUMMY_IRQ is not set
# CONFIG_ENCLOSURE_SERVICES is not set
# CONFIG_TI_DAC7512 is not set
# CONFIG_LATTICE_ECP3_CONFIG is not set
# CONFIG_SRAM is not set
# CONFIG_C2PORT is not set
#
# EEPROM support
#
# CONFIG_EEPROM_AT25 is not set
# CONFIG_EEPROM_93CX6 is not set
# CONFIG_EEPROM_93XX46 is not set
#
# Texas Instruments shared transport line discipline
#
# CONFIG_TI_ST is not set
#
# Altera FPGA firmware download module
#
#
# Intel MIC Bus Driver
#
#
# SCIF Bus Driver
#
#
# VOP Bus Driver
#
#
# Intel MIC Host Driver
#
#
# Intel MIC Card Driver
#
#
# SCIF Driver
#
#
# Intel MIC Coprocessor State Management (COSM) Drivers
#
#
# VOP Driver
#
# CONFIG_ECHO is not set
# CONFIG_CXL_BASE is not set
# CONFIG_CXL_AFU_DRIVER_OPS is not set
CONFIG_HAVE_IDE=y
#
# SCSI device support
#
CONFIG_SCSI_MOD=y
# CONFIG_SCSI_DMA is not set
# CONFIG_SCSI_NETLINK is not set
# CONFIG_MACINTOSH_DRIVERS is not set
CONFIG_NETDEVICES=y
CONFIG_MII=y
CONFIG_NET_CORE=y
# CONFIG_BONDING is not set
# CONFIG_DUMMY is not set
# CONFIG_EQUALIZER is not set
# CONFIG_NET_TEAM is not set
# CONFIG_MACVLAN is not set
# CONFIG_VXLAN is not set
# CONFIG_MACSEC is not set
# CONFIG_NETCONSOLE is not set
# CONFIG_NETPOLL is not set
# CONFIG_NET_POLL_CONTROLLER is not set
# CONFIG_TUN is not set
# CONFIG_TUN_VNET_CROSS_LE is not set
# CONFIG_VETH is not set
# CONFIG_NLMON is not set
#
# CAIF transport drivers
#
#
# Distributed Switch Architecture drivers
#
CONFIG_ETHERNET=y
# CONFIG_ALTERA_TSE is not set
CONFIG_NET_VENDOR_AMAZON=y
# CONFIG_NET_VENDOR_ARC is not set
# CONFIG_NET_VENDOR_AURORA is not set
CONFIG_NET_CADENCE=y
# CONFIG_MACB is not set
# CONFIG_NET_VENDOR_BROADCOM is not set
# CONFIG_DNET is not set
CONFIG_NET_VENDOR_EZCHIP=y
# CONFIG_EZCHIP_NPS_MANAGEMENT_ENET is not set
CONFIG_NET_VENDOR_FREESCALE=y
# CONFIG_FS_ENET is not set
# CONFIG_FSL_FMAN is not set
# CONFIG_FSL_PQ_MDIO is not set
# CONFIG_FSL_XGMAC_MDIO is not set
# CONFIG_GIANFAR is not set
# CONFIG_NET_VENDOR_INTEL is not set
# CONFIG_NET_VENDOR_MARVELL is not set
# CONFIG_NET_VENDOR_MICREL is not set
# CONFIG_NET_VENDOR_MICROCHIP is not set
# CONFIG_NET_VENDOR_NATSEMI is not set
CONFIG_NET_VENDOR_NETRONOME=y
# CONFIG_ETHOC is not set
# CONFIG_NET_VENDOR_QUALCOMM is not set
CONFIG_NET_VENDOR_RENESAS=y
CONFIG_NET_VENDOR_ROCKER=y
# CONFIG_NET_VENDOR_SAMSUNG is not set
# CONFIG_NET_VENDOR_SEEQ is not set
# CONFIG_NET_VENDOR_STMICRO is not set
CONFIG_NET_VENDOR_SYNOPSYS=y
# CONFIG_SYNOPSYS_DWC_ETH_QOS is not set
# CONFIG_NET_VENDOR_VIA is not set
# CONFIG_NET_VENDOR_WIZNET is not set
# CONFIG_NET_VENDOR_XILINX is not set
CONFIG_PHYLIB=y
CONFIG_SWPHY=y
#
# MDIO bus device drivers
#
# CONFIG_MDIO_BCM_UNIMAC is not set
# CONFIG_MDIO_BITBANG is not set
# CONFIG_MDIO_BUS_MUX_GPIO is not set
# CONFIG_MDIO_BUS_MUX_MMIOREG is not set
# CONFIG_MDIO_HISI_FEMAC is not set
#
# MII PHY device drivers
#
# CONFIG_AMD_PHY is not set
# CONFIG_AQUANTIA_PHY is not set
# CONFIG_AT803X_PHY is not set
# CONFIG_BCM7XXX_PHY is not set
# CONFIG_BCM87XX_PHY is not set
# CONFIG_BROADCOM_PHY is not set
# CONFIG_CICADA_PHY is not set
# CONFIG_DAVICOM_PHY is not set
# CONFIG_DP83848_PHY is not set
# CONFIG_DP83867_PHY is not set
CONFIG_FIXED_PHY=y
# CONFIG_ICPLUS_PHY is not set
# CONFIG_INTEL_XWAY_PHY is not set
# CONFIG_LSI_ET1011C_PHY is not set
CONFIG_LXT_PHY=y
# CONFIG_MARVELL_PHY is not set
# CONFIG_MICREL_PHY is not set
# CONFIG_MICROCHIP_PHY is not set
# CONFIG_MICROSEMI_PHY is not set
# CONFIG_NATIONAL_PHY is not set
# CONFIG_QSEMI_PHY is not set
# CONFIG_REALTEK_PHY is not set
# CONFIG_SMSC_PHY is not set
# CONFIG_STE10XP is not set
# CONFIG_TERANETICS_PHY is not set
# CONFIG_VITESSE_PHY is not set
# CONFIG_XILINX_GMII2RGMII is not set
# CONFIG_MICREL_KS8995MA is not set
# CONFIG_PPP is not set
# CONFIG_SLIP is not set
#
# Host-side USB support is needed for USB Network Adapter support
#
# CONFIG_WLAN is not set
#
# Enable WiMAX (Networking options) to see the WiMAX drivers
#
# CONFIG_WAN is not set
# CONFIG_ISDN is not set
#
# Input device support
#
# CONFIG_INPUT is not set
#
# Hardware I/O ports
#
# CONFIG_SERIO is not set
CONFIG_ARCH_MIGHT_HAVE_PC_SERIO=y
# CONFIG_GAMEPORT is not set
#
# Character devices
#
CONFIG_TTY=y
# CONFIG_VT is not set
CONFIG_UNIX98_PTYS=y
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=5
# CONFIG_SERIAL_NONSTANDARD is not set
# CONFIG_N_GSM is not set
# CONFIG_TRACE_SINK is not set
# CONFIG_PPC_EPAPR_HV_BYTECHAN is not set
CONFIG_DEVMEM=y
CONFIG_DEVKMEM=y
#
# Serial drivers
#
# CONFIG_SERIAL_8250 is not set
#
# Non-8250 serial port support
#
# CONFIG_SERIAL_MAX3100 is not set
# CONFIG_SERIAL_MAX310X is not set
# CONFIG_SERIAL_UARTLITE is not set
CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
CONFIG_SERIAL_CPM=y
CONFIG_SERIAL_CPM_CONSOLE=y
# CONFIG_SERIAL_SCCNXP is not set
# CONFIG_SERIAL_SC16IS7XX is not set
# CONFIG_SERIAL_ALTERA_JTAGUART is not set
# CONFIG_SERIAL_ALTERA_UART is not set
# CONFIG_SERIAL_IFX6X60 is not set
# CONFIG_SERIAL_XILINX_PS_UART is not set
# CONFIG_SERIAL_ARC is not set
# CONFIG_SERIAL_FSL_LPUART is not set
# CONFIG_SERIAL_CONEXANT_DIGICOLOR is not set
# CONFIG_TTY_PRINTK is not set
# CONFIG_HVC_UDBG is not set
# CONFIG_IPMI_HANDLER is not set
CONFIG_HW_RANDOM=y
# CONFIG_HW_RANDOM_TIMERIOMEM is not set
# CONFIG_NVRAM is not set
# CONFIG_R3964 is not set
# CONFIG_TCG_TPM is not set
# CONFIG_XILLYBUS is not set
#
# I2C support
#
# CONFIG_I2C is not set
CONFIG_SPI=y
# CONFIG_SPI_DEBUG is not set
CONFIG_SPI_MASTER=y
#
# SPI Master Controller Drivers
#
# CONFIG_SPI_ALTERA is not set
# CONFIG_SPI_AXI_SPI_ENGINE is not set
# CONFIG_SPI_BITBANG is not set
# CONFIG_SPI_CADENCE is not set
# CONFIG_SPI_DESIGNWARE is not set
# CONFIG_SPI_GPIO is not set
CONFIG_SPI_FSL_LIB=y
CONFIG_SPI_FSL_CPM=y
CONFIG_SPI_FSL_SPI=y
# CONFIG_SPI_FSL_ESPI is not set
# CONFIG_SPI_OC_TINY is not set
# CONFIG_SPI_PXA2XX_PCI is not set
# CONFIG_SPI_ROCKCHIP is not set
# CONFIG_SPI_XILINX is not set
# CONFIG_SPI_ZYNQMP_GQSPI is not set
#
# SPI Protocol Masters
#
# CONFIG_SPI_SPIDEV is not set
# CONFIG_SPI_TLE62X0 is not set
# CONFIG_SPMI is not set
# CONFIG_HSI is not set
#
# PPS support
#
# CONFIG_PPS is not set
#
# PPS generators support
#
#
# PTP clock support
#
# CONFIG_PTP_1588_CLOCK is not set
#
# Enable PHYLIB and NETWORK_PHY_TIMESTAMPING to see the additional clocks.
#
CONFIG_GPIOLIB=y
CONFIG_OF_GPIO=y
CONFIG_DEBUG_GPIO=y
CONFIG_GPIO_SYSFS=y
#
# Memory mapped GPIO drivers
#
# CONFIG_GPIO_74XX_MMIO is not set
# CONFIG_GPIO_ALTERA is not set
# CONFIG_GPIO_DWAPB is not set
# CONFIG_GPIO_GENERIC_PLATFORM is not set
# CONFIG_GPIO_GRGPIO is not set
# CONFIG_GPIO_MOCKUP is not set
# CONFIG_GPIO_XILINX is not set
# CONFIG_GPIO_ZX is not set
#
# MFD GPIO expanders
#
#
# SPI GPIO expanders
#
# CONFIG_GPIO_74X164 is not set
# CONFIG_GPIO_MAX7301 is not set
# CONFIG_GPIO_MC33880 is not set
# CONFIG_GPIO_PISOSR is not set
#
# SPI or I2C GPIO expanders
#
# CONFIG_GPIO_MCP23S08 is not set
# CONFIG_W1 is not set
# CONFIG_POWER_AVS is not set
# CONFIG_POWER_RESET is not set
# CONFIG_POWER_SUPPLY is not set
CONFIG_HWMON=y
# CONFIG_HWMON_VID is not set
# CONFIG_HWMON_DEBUG_CHIP is not set
#
# Native drivers
#
# CONFIG_SENSORS_AD7314 is not set
# CONFIG_SENSORS_ADT7310 is not set
# CONFIG_SENSORS_GPIO_FAN is not set
# CONFIG_SENSORS_MAX1111 is not set
# CONFIG_SENSORS_MAX197 is not set
# CONFIG_SENSORS_MAX31722 is not set
# CONFIG_SENSORS_ADCXX is not set
CONFIG_SENSORS_LM70=y
# CONFIG_SENSORS_NTC_THERMISTOR is not set
# CONFIG_SENSORS_SHT15 is not set
# CONFIG_SENSORS_SCH56XX_COMMON is not set
# CONFIG_SENSORS_ADS7871 is not set
CONFIG_THERMAL=y
CONFIG_THERMAL_HWMON=y
CONFIG_THERMAL_OF=y
# CONFIG_THERMAL_WRITABLE_TRIPS is not set
CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE=y
# CONFIG_THERMAL_DEFAULT_GOV_FAIR_SHARE is not set
# CONFIG_THERMAL_DEFAULT_GOV_USER_SPACE is not set
# CONFIG_THERMAL_DEFAULT_GOV_POWER_ALLOCATOR is not set
# CONFIG_THERMAL_GOV_FAIR_SHARE is not set
CONFIG_THERMAL_GOV_STEP_WISE=y
# CONFIG_THERMAL_GOV_BANG_BANG is not set
# CONFIG_THERMAL_GOV_USER_SPACE is not set
# CONFIG_THERMAL_GOV_POWER_ALLOCATOR is not set
# CONFIG_THERMAL_EMULATION is not set
# CONFIG_QORIQ_THERMAL is not set
#
# ACPI INT340X thermal drivers
#
CONFIG_WATCHDOG=y
CONFIG_WATCHDOG_CORE=y
# CONFIG_WATCHDOG_NOWAYOUT is not set
# CONFIG_WATCHDOG_SYSFS is not set
#
# Watchdog Device Drivers
#
# CONFIG_SOFT_WATCHDOG is not set
# CONFIG_GPIO_WATCHDOG is not set
# CONFIG_XILINX_WATCHDOG is not set
# CONFIG_CADENCE_WATCHDOG is not set
# CONFIG_DW_WATCHDOG is not set
# CONFIG_MAX63XX_WATCHDOG is not set
CONFIG_8xxx_WDT=y
# CONFIG_MEN_A21_WDT is not set
#
# Watchdog Pretimeout Governors
#
# CONFIG_WATCHDOG_PRETIMEOUT_GOV is not set
CONFIG_SSB_POSSIBLE=y
#
# Sonics Silicon Backplane
#
# CONFIG_SSB is not set
CONFIG_BCMA_POSSIBLE=y
#
# Broadcom specific AMBA
#
# CONFIG_BCMA is not set
#
# Multifunction device drivers
#
# CONFIG_MFD_CORE is not set
# CONFIG_MFD_ATMEL_FLEXCOM is not set
# CONFIG_MFD_ATMEL_HLCDC is not set
# CONFIG_MFD_DA9052_SPI is not set
# CONFIG_MFD_EXYNOS_LPASS is not set
# CONFIG_MFD_MC13XXX_SPI is not set
# CONFIG_MFD_HI6421_PMIC is not set
# CONFIG_HTC_PASIC3 is not set
# CONFIG_MFD_KEMPLD is not set
# CONFIG_MFD_MT6397 is not set
# CONFIG_EZX_PCAP is not set
# CONFIG_MFD_SM501 is not set
# CONFIG_ABX500_CORE is not set
# CONFIG_MFD_STMPE is not set
# CONFIG_MFD_SYSCON is not set
# CONFIG_MFD_TI_AM335X_TSCADC is not set
# CONFIG_MFD_TPS65912_SPI is not set
# CONFIG_MFD_TMIO is not set
# CONFIG_MFD_ARIZONA_SPI is not set
# CONFIG_MFD_WM831X_SPI is not set
# CONFIG_REGULATOR is not set
# CONFIG_MEDIA_SUPPORT is not set
#
# Graphics support
#
# CONFIG_DRM is not set
#
# ACP (Audio CoProcessor) Configuration
#
#
# Frame buffer Devices
#
# CONFIG_FB is not set
# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
# CONFIG_VGASTATE is not set
# CONFIG_SOUND is not set
CONFIG_USB_OHCI_LITTLE_ENDIAN=y
# CONFIG_USB_SUPPORT is not set
# CONFIG_UWB is not set
# CONFIG_MMC is not set
# CONFIG_MEMSTICK is not set
CONFIG_NEW_LEDS=y
CONFIG_LEDS_CLASS=y
# CONFIG_LEDS_CLASS_FLASH is not set
#
# LED drivers
#
# CONFIG_LEDS_BCM6328 is not set
# CONFIG_LEDS_BCM6358 is not set
CONFIG_LEDS_GPIO=y
# CONFIG_LEDS_DAC124S085 is not set
# CONFIG_LEDS_LT3593 is not set
#
# LED driver for blink(1) USB RGB LED is under Special HID drivers
(HID_THINGM)
#
#
# LED Triggers
#
CONFIG_LEDS_TRIGGERS=y
CONFIG_LEDS_TRIGGER_TIMER=y
# CONFIG_LEDS_TRIGGER_ONESHOT is not set
# CONFIG_LEDS_TRIGGER_MTD is not set
CONFIG_LEDS_TRIGGER_HEARTBEAT=y
# CONFIG_LEDS_TRIGGER_BACKLIGHT is not set
# CONFIG_LEDS_TRIGGER_CPU is not set
CONFIG_LEDS_TRIGGER_GPIO=y
CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
#
# iptables trigger is under Netfilter config (LED target)
#
# CONFIG_LEDS_TRIGGER_TRANSIENT is not set
# CONFIG_LEDS_TRIGGER_CAMERA is not set
# CONFIG_LEDS_TRIGGER_PANIC is not set
# CONFIG_ACCESSIBILITY is not set
CONFIG_EDAC_ATOMIC_SCRUB=y
CONFIG_EDAC_SUPPORT=y
# CONFIG_EDAC is not set
CONFIG_RTC_LIB=y
CONFIG_RTC_CLASS=y
CONFIG_RTC_HCTOSYS=y
CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
CONFIG_RTC_SYSTOHC=y
CONFIG_RTC_SYSTOHC_DEVICE="rtc0"
# CONFIG_RTC_DEBUG is not set
#
# RTC interfaces
#
CONFIG_RTC_INTF_SYSFS=y
CONFIG_RTC_INTF_PROC=y
CONFIG_RTC_INTF_DEV=y
# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
# CONFIG_RTC_DRV_TEST is not set
#
# I2C RTC drivers
#
#
# SPI RTC drivers
#
# CONFIG_RTC_DRV_M41T93 is not set
# CONFIG_RTC_DRV_M41T94 is not set
# CONFIG_RTC_DRV_DS1302 is not set
# CONFIG_RTC_DRV_DS1305 is not set
# CONFIG_RTC_DRV_DS1343 is not set
# CONFIG_RTC_DRV_DS1347 is not set
# CONFIG_RTC_DRV_DS1390 is not set
# CONFIG_RTC_DRV_MAX6916 is not set
# CONFIG_RTC_DRV_R9701 is not set
# CONFIG_RTC_DRV_RX4581 is not set
# CONFIG_RTC_DRV_RX6110 is not set
# CONFIG_RTC_DRV_RS5C348 is not set
# CONFIG_RTC_DRV_MAX6902 is not set
# CONFIG_RTC_DRV_PCF2123 is not set
# CONFIG_RTC_DRV_MCP795 is not set
CONFIG_RTC_I2C_AND_SPI=y
#
# SPI and I2C RTC drivers
#
# CONFIG_RTC_DRV_DS3232 is not set
# CONFIG_RTC_DRV_PCF2127 is not set
# CONFIG_RTC_DRV_RV3029C2 is not set
#
# Platform RTC drivers
#
# CONFIG_RTC_DRV_CMOS is not set
# CONFIG_RTC_DRV_DS1286 is not set
# CONFIG_RTC_DRV_DS1511 is not set
# CONFIG_RTC_DRV_DS1553 is not set
# CONFIG_RTC_DRV_DS1685_FAMILY is not set
# CONFIG_RTC_DRV_DS1742 is not set
# CONFIG_RTC_DRV_DS2404 is not set
# CONFIG_RTC_DRV_STK17TA8 is not set
# CONFIG_RTC_DRV_M48T86 is not set
# CONFIG_RTC_DRV_M48T35 is not set
# CONFIG_RTC_DRV_M48T59 is not set
# CONFIG_RTC_DRV_MSM6242 is not set
# CONFIG_RTC_DRV_BQ4802 is not set
# CONFIG_RTC_DRV_RP5C01 is not set
# CONFIG_RTC_DRV_V3020 is not set
# CONFIG_RTC_DRV_ZYNQMP is not set
#
# on-CPU RTC drivers
#
CONFIG_RTC_DRV_GENERIC=y
# CONFIG_RTC_DRV_SNVS is not set
#
# HID Sensor RTC drivers
#
# CONFIG_DMADEVICES is not set
#
# DMABUF options
#
# CONFIG_SYNC_FILE is not set
# CONFIG_AUXDISPLAY is not set
# CONFIG_UIO is not set
# CONFIG_VIRT_DRIVERS is not set
#
# Virtio drivers
#
# CONFIG_VIRTIO_MMIO is not set
#
# Microsoft Hyper-V guest support
#
# CONFIG_STAGING is not set
CONFIG_SAF3000_PLATFORM_DEVICES=y
CONFIG_SAF3000=y
CONFIG_SAF3000_COMMON=y
# CONFIG_SAF3000_83XX is not set
CONFIG_MCR3000=y
# CONFIG_CMPC885 is not set
# CONFIG_DSP is not set
CONFIG_FPGA_LOADER=y
CONFIG_OPX_GPIO=y
CONFIG_U16_GPIO=y
CONFIG_SAF3000_DRV=y
CONFIG_SAF3000_NET=y
CONFIG_SAF3000_DRV_MENU=y
CONFIG_MCR3000_DRV=y
CONFIG_MCR3000_CPLD=y
CONFIG_MCR3000_HWMON=y
CONFIG_MCR3000_NET=y
CONFIG_FPGA_INFO=y
#
# Hardware Spinlock drivers
#
#
# Clock Source drivers
#
# CONFIG_ATMEL_PIT is not set
# CONFIG_SH_TIMER_CMT is not set
# CONFIG_SH_TIMER_MTU2 is not set
# CONFIG_SH_TIMER_TMU is not set
# CONFIG_EM_TIMER_STI is not set
# CONFIG_MAILBOX is not set
# CONFIG_IOMMU_SUPPORT is not set
#
# Remoteproc drivers
#
# CONFIG_STE_MODEM_RPROC is not set
#
# Rpmsg drivers
#
#
# SOC (System On Chip) specific Drivers
#
#
# Broadcom SoC drivers
#
# CONFIG_QUICC_ENGINE is not set
# CONFIG_SUNXI_SRAM is not set
# CONFIG_SOC_TI is not set
# CONFIG_PM_DEVFREQ is not set
# CONFIG_EXTCON is not set
# CONFIG_MEMORY is not set
# CONFIG_IIO is not set
# CONFIG_PWM is not set
CONFIG_IRQCHIP=y
CONFIG_ARM_GIC_MAX_NR=1
# CONFIG_IPACK_BUS is not set
# CONFIG_RESET_CONTROLLER is not set
# CONFIG_FMC is not set
#
# PHY Subsystem
#
# CONFIG_GENERIC_PHY is not set
# CONFIG_PHY_PXA_28NM_HSIC is not set
# CONFIG_PHY_PXA_28NM_USB2 is not set
# CONFIG_BCM_KONA_USB2_PHY is not set
# CONFIG_POWERCAP is not set
# CONFIG_MCB is not set
#
# Performance monitor support
#
# CONFIG_RAS is not set
#
# Android
#
# CONFIG_ANDROID is not set
# CONFIG_NVMEM is not set
# CONFIG_STM is not set
# CONFIG_INTEL_TH is not set
#
# FPGA Configuration Support
#
CONFIG_FPGA=y
#
# File systems
#
# CONFIG_FS_POSIX_ACL is not set
# CONFIG_EXPORTFS_BLOCK_OPS is not set
CONFIG_FILE_LOCKING=y
CONFIG_MANDATORY_FILE_LOCKING=y
CONFIG_FSNOTIFY=y
# CONFIG_DNOTIFY is not set
CONFIG_INOTIFY_USER=y
# CONFIG_FANOTIFY is not set
# CONFIG_QUOTA is not set
# CONFIG_QUOTACTL is not set
# CONFIG_AUTOFS4_FS is not set
# CONFIG_FUSE_FS is not set
# CONFIG_OVERLAY_FS is not set
#
# Caches
#
CONFIG_FSCACHE=y
# CONFIG_FSCACHE_STATS is not set
# CONFIG_FSCACHE_HISTOGRAM is not set
# CONFIG_FSCACHE_DEBUG is not set
# CONFIG_FSCACHE_OBJECT_LIST is not set
#
# Pseudo filesystems
#
CONFIG_PROC_FS=y
# CONFIG_PROC_KCORE is not set
CONFIG_PROC_SYSCTL=y
CONFIG_PROC_PAGE_MONITOR=y
# CONFIG_PROC_CHILDREN is not set
CONFIG_KERNFS=y
CONFIG_SYSFS=y
CONFIG_TMPFS=y
# CONFIG_TMPFS_POSIX_ACL is not set
# CONFIG_TMPFS_XATTR is not set
CONFIG_HUGETLBFS=y
CONFIG_HUGETLB_PAGE=y
# CONFIG_CONFIGFS_FS is not set
CONFIG_MISC_FILESYSTEMS=y
# CONFIG_ORANGEFS_FS is not set
# CONFIG_JFFS2_FS is not set
CONFIG_UBIFS_FS=y
CONFIG_UBIFS_FS_ADVANCED_COMPR=y
CONFIG_UBIFS_FS_LZO=y
CONFIG_UBIFS_FS_ZLIB=y
# CONFIG_UBIFS_ATIME_SUPPORT is not set
# CONFIG_LOGFS is not set
# CONFIG_ROMFS_FS is not set
# CONFIG_PSTORE is not set
CONFIG_NETWORK_FILESYSTEMS=y
CONFIG_NFS_FS=y
CONFIG_NFS_V2=y
CONFIG_NFS_V3=y
# CONFIG_NFS_V3_ACL is not set
# CONFIG_NFS_V4 is not set
# CONFIG_NFS_SWAP is not set
# CONFIG_NFS_FSCACHE is not set
# CONFIG_NFSD is not set
CONFIG_GRACE_PERIOD=y
CONFIG_LOCKD=y
CONFIG_LOCKD_V4=y
CONFIG_NFS_COMMON=y
CONFIG_SUNRPC=y
# CONFIG_SUNRPC_DEBUG is not set
# CONFIG_CEPH_FS is not set
# CONFIG_CIFS is not set
# CONFIG_NCP_FS is not set
# CONFIG_CODA_FS is not set
# CONFIG_AFS_FS is not set
# CONFIG_NLS is not set
# CONFIG_BINARY_PRINTF is not set
#
# Library routines
#
CONFIG_BITREVERSE=y
# CONFIG_HAVE_ARCH_BITREVERSE is not set
CONFIG_GENERIC_STRNCPY_FROM_USER=y
CONFIG_GENERIC_STRNLEN_USER=y
CONFIG_GENERIC_NET_UTILS=y
CONFIG_GENERIC_IO=y
# CONFIG_CRC_CCITT is not set
CONFIG_CRC16=y
# CONFIG_CRC_T10DIF is not set
# CONFIG_CRC_ITU_T is not set
CONFIG_CRC32=y
# CONFIG_CRC32_SELFTEST is not set
# CONFIG_CRC32_SLICEBY8 is not set
# CONFIG_CRC32_SLICEBY4 is not set
CONFIG_CRC32_SARWATE=y
# CONFIG_CRC32_BIT is not set
# CONFIG_CRC7 is not set
# CONFIG_LIBCRC32C is not set
# CONFIG_CRC8 is not set
# CONFIG_AUDIT_ARCH_COMPAT_GENERIC is not set
# CONFIG_RANDOM32_SELFTEST is not set
CONFIG_ZLIB_INFLATE=y
CONFIG_ZLIB_DEFLATE=y
CONFIG_LZO_COMPRESS=y
CONFIG_LZO_DECOMPRESS=y
CONFIG_XZ_DEC=y
# CONFIG_XZ_DEC_X86 is not set
CONFIG_XZ_DEC_POWERPC=y
# CONFIG_XZ_DEC_IA64 is not set
# CONFIG_XZ_DEC_ARM is not set
# CONFIG_XZ_DEC_ARMTHUMB is not set
# CONFIG_XZ_DEC_SPARC is not set
CONFIG_XZ_DEC_BCJ=y
# CONFIG_XZ_DEC_TEST is not set
CONFIG_GENERIC_ALLOCATOR=y
CONFIG_HAS_IOMEM=y
CONFIG_HAS_IOPORT_MAP=y
CONFIG_HAS_DMA=y
CONFIG_DQL=y
CONFIG_NLATTR=y
CONFIG_GENERIC_ATOMIC64=y
# CONFIG_CORDIC is not set
# CONFIG_DDR is not set
# CONFIG_IRQ_POLL is not set
CONFIG_LIBFDT=y
# CONFIG_SG_SPLIT is not set
# CONFIG_SG_POOL is not set
CONFIG_ARCH_HAS_SG_CHAIN=y
#
# Kernel hacking
#
#
# printk and dmesg options
#
CONFIG_PRINTK_TIME=y
CONFIG_MESSAGE_LOGLEVEL_DEFAULT=4
# CONFIG_DYNAMIC_DEBUG is not set
#
# Compile-time checks and compiler options
#
CONFIG_DEBUG_INFO=y
CONFIG_DEBUG_INFO_REDUCED=y
# CONFIG_DEBUG_INFO_SPLIT is not set
# CONFIG_DEBUG_INFO_DWARF4 is not set
# CONFIG_GDB_SCRIPTS is not set
CONFIG_ENABLE_WARN_DEPRECATED=y
CONFIG_ENABLE_MUST_CHECK=y
CONFIG_FRAME_WARN=1024
# CONFIG_STRIP_ASM_SYMS is not set
# CONFIG_READABLE_ASM is not set
# CONFIG_UNUSED_SYMBOLS is not set
# CONFIG_PAGE_OWNER is not set
CONFIG_DEBUG_FS=y
# CONFIG_HEADERS_CHECK is not set
# CONFIG_DEBUG_SECTION_MISMATCH is not set
CONFIG_SECTION_MISMATCH_WARN_ONLY=y
# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set
CONFIG_MAGIC_SYSRQ=y
CONFIG_MAGIC_SYSRQ_DEFAULT_ENABLE=0x1
CONFIG_DEBUG_KERNEL=y
#
# Memory Debugging
#
# CONFIG_PAGE_EXTENSION is not set
# CONFIG_DEBUG_PAGEALLOC is not set
# CONFIG_PAGE_POISONING is not set
# CONFIG_DEBUG_OBJECTS is not set
# CONFIG_SLUB_STATS is not set
CONFIG_HAVE_DEBUG_KMEMLEAK=y
# CONFIG_DEBUG_KMEMLEAK is not set
# CONFIG_DEBUG_STACK_USAGE is not set
# CONFIG_DEBUG_VM is not set
# CONFIG_DEBUG_MEMORY_INIT is not set
CONFIG_HAVE_DEBUG_STACKOVERFLOW=y
# CONFIG_DEBUG_STACKOVERFLOW is not set
# CONFIG_DEBUG_SHIRQ is not set
#
# Debug Lockups and Hangs
#
# CONFIG_LOCKUP_DETECTOR is not set
CONFIG_DETECT_HUNG_TASK=y
CONFIG_DEFAULT_HUNG_TASK_TIMEOUT=120
# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set
CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0
# CONFIG_WQ_WATCHDOG is not set
# CONFIG_PANIC_ON_OOPS is not set
CONFIG_PANIC_ON_OOPS_VALUE=0
# CONFIG_SCHED_DEBUG is not set
# CONFIG_SCHED_INFO is not set
# CONFIG_SCHEDSTATS is not set
# CONFIG_SCHED_STACK_END_CHECK is not set
# CONFIG_DEBUG_TIMEKEEPING is not set
# CONFIG_TIMER_STATS is not set
# CONFIG_DEBUG_PREEMPT is not set
#
# Lock Debugging (spinlocks, mutexes, etc...)
#
# CONFIG_DEBUG_RT_MUTEXES is not set
# CONFIG_DEBUG_SPINLOCK is not set
# CONFIG_DEBUG_MUTEXES is not set
# CONFIG_DEBUG_WW_MUTEX_SLOWPATH is not set
# CONFIG_DEBUG_LOCK_ALLOC is not set
# CONFIG_PROVE_LOCKING is not set
# CONFIG_LOCK_STAT is not set
# CONFIG_DEBUG_ATOMIC_SLEEP is not set
# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
# CONFIG_LOCK_TORTURE_TEST is not set
CONFIG_STACKTRACE=y
# CONFIG_DEBUG_KOBJECT is not set
CONFIG_DEBUG_BUGVERBOSE=y
# CONFIG_DEBUG_LIST is not set
# CONFIG_DEBUG_PI_LIST is not set
# CONFIG_DEBUG_SG is not set
# CONFIG_DEBUG_NOTIFIERS is not set
# CONFIG_DEBUG_CREDENTIALS is not set
#
# RCU Debugging
#
# CONFIG_PROVE_RCU is not set
# CONFIG_SPARSE_RCU_POINTER is not set
# CONFIG_TORTURE_TEST is not set
# CONFIG_RCU_PERF_TEST is not set
# CONFIG_RCU_TORTURE_TEST is not set
CONFIG_RCU_CPU_STALL_TIMEOUT=21
# CONFIG_RCU_TRACE is not set
# CONFIG_RCU_EQS_DEBUG is not set
# CONFIG_DEBUG_WQ_FORCE_RR_CPU is not set
# CONFIG_NOTIFIER_ERROR_INJECTION is not set
# CONFIG_FAULT_INJECTION is not set
# CONFIG_LATENCYTOP is not set
CONFIG_HAVE_FUNCTION_TRACER=y
CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
CONFIG_HAVE_DYNAMIC_FTRACE=y
CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
CONFIG_HAVE_SYSCALL_TRACEPOINTS=y
CONFIG_TRACING_SUPPORT=y
# CONFIG_FTRACE is not set
#
# Runtime Testing
#
# CONFIG_TEST_LIST_SORT is not set
# CONFIG_BACKTRACE_SELF_TEST is not set
# CONFIG_RBTREE_TEST is not set
# CONFIG_ATOMIC64_SELFTEST is not set
# CONFIG_TEST_HEXDUMP is not set
# CONFIG_TEST_STRING_HELPERS is not set
# CONFIG_TEST_KSTRTOX is not set
# CONFIG_TEST_PRINTF is not set
# CONFIG_TEST_BITMAP is not set
# CONFIG_TEST_UUID is not set
# CONFIG_TEST_RHASHTABLE is not set
# CONFIG_TEST_HASH is not set
# CONFIG_DMA_API_DEBUG is not set
# CONFIG_TEST_FIRMWARE is not set
# CONFIG_TEST_UDELAY is not set
# CONFIG_MEMTEST is not set
# CONFIG_SAMPLES is not set
CONFIG_HAVE_ARCH_KGDB=y
# CONFIG_KGDB is not set
CONFIG_ARCH_HAS_UBSAN_SANITIZE_ALL=y
# CONFIG_ARCH_WANTS_UBSAN_NO_NULL is not set
# CONFIG_UBSAN is not set
CONFIG_ARCH_HAS_DEVMEM_IS_ALLOWED=y
CONFIG_STRICT_DEVMEM=y
# CONFIG_IO_STRICT_DEVMEM is not set
# CONFIG_PPC_DISABLE_WERROR is not set
CONFIG_PPC_WERROR=y
CONFIG_PRINT_STACK_DEPTH=64
# CONFIG_PPC_EMULATED_STATS is not set
# CONFIG_CODE_PATCHING_SELFTEST is not set
CONFIG_JUMP_LABEL_FEATURE_CHECKS=y
# CONFIG_JUMP_LABEL_FEATURE_CHECK_DEBUG is not set
# CONFIG_FTR_FIXUP_SELFTEST is not set
# CONFIG_MSI_BITMAP_SELFTEST is not set
# CONFIG_XMON is not set
CONFIG_BDI_SWITCH=y
# CONFIG_PPC_EARLY_DEBUG is not set
#
# Security options
#
# CONFIG_KEYS is not set
# CONFIG_SECURITY_DMESG_RESTRICT is not set
# CONFIG_SECURITY is not set
# CONFIG_SECURITYFS is not set
CONFIG_HAVE_HARDENED_USERCOPY_ALLOCATOR=y
CONFIG_HAVE_ARCH_HARDENED_USERCOPY=y
# CONFIG_HARDENED_USERCOPY is not set
CONFIG_DEFAULT_SECURITY_DAC=y
CONFIG_DEFAULT_SECURITY=""
CONFIG_CRYPTO=y
#
# Crypto core or helper
#
CONFIG_CRYPTO_ALGAPI=y
CONFIG_CRYPTO_ALGAPI2=y
CONFIG_CRYPTO_AEAD=y
CONFIG_CRYPTO_AEAD2=y
CONFIG_CRYPTO_BLKCIPHER=y
CONFIG_CRYPTO_BLKCIPHER2=y
CONFIG_CRYPTO_HASH=y
CONFIG_CRYPTO_HASH2=y
CONFIG_CRYPTO_RNG=y
CONFIG_CRYPTO_RNG2=y
CONFIG_CRYPTO_RNG_DEFAULT=y
CONFIG_CRYPTO_AKCIPHER2=y
CONFIG_CRYPTO_KPP2=y
# CONFIG_CRYPTO_RSA is not set
# CONFIG_CRYPTO_DH is not set
# CONFIG_CRYPTO_ECDH is not set
CONFIG_CRYPTO_MANAGER=y
CONFIG_CRYPTO_MANAGER2=y
CONFIG_CRYPTO_USER=y
# CONFIG_CRYPTO_MANAGER_DISABLE_TESTS is not set
# CONFIG_CRYPTO_GF128MUL is not set
CONFIG_CRYPTO_NULL=y
CONFIG_CRYPTO_NULL2=y
CONFIG_CRYPTO_WORKQUEUE=y
# CONFIG_CRYPTO_CRYPTD is not set
# CONFIG_CRYPTO_MCRYPTD is not set
CONFIG_CRYPTO_AUTHENC=y
#
# Authenticated Encryption with Associated Data
#
# CONFIG_CRYPTO_CCM is not set
# CONFIG_CRYPTO_GCM is not set
# CONFIG_CRYPTO_CHACHA20POLY1305 is not set
# CONFIG_CRYPTO_SEQIV is not set
CONFIG_CRYPTO_ECHAINIV=y
#
# Block modes
#
CONFIG_CRYPTO_CBC=y
# CONFIG_CRYPTO_CTR is not set
# CONFIG_CRYPTO_CTS is not set
# CONFIG_CRYPTO_ECB is not set
# CONFIG_CRYPTO_LRW is not set
# CONFIG_CRYPTO_PCBC is not set
# CONFIG_CRYPTO_XTS is not set
# CONFIG_CRYPTO_KEYWRAP is not set
#
# Hash modes
#
# CONFIG_CRYPTO_CMAC is not set
CONFIG_CRYPTO_HMAC=y
# CONFIG_CRYPTO_XCBC is not set
# CONFIG_CRYPTO_VMAC is not set
#
# Digest
#
# CONFIG_CRYPTO_CRC32C is not set
# CONFIG_CRYPTO_CRC32 is not set
# CONFIG_CRYPTO_CRCT10DIF is not set
# CONFIG_CRYPTO_GHASH is not set
# CONFIG_CRYPTO_POLY1305 is not set
# CONFIG_CRYPTO_MD4 is not set
# CONFIG_CRYPTO_MD5 is not set
CONFIG_CRYPTO_MD5_PPC=y
# CONFIG_CRYPTO_MICHAEL_MIC is not set
# CONFIG_CRYPTO_RMD128 is not set
# CONFIG_CRYPTO_RMD160 is not set
# CONFIG_CRYPTO_RMD256 is not set
# CONFIG_CRYPTO_RMD320 is not set
# CONFIG_CRYPTO_SHA1 is not set
CONFIG_CRYPTO_SHA1_PPC=y
CONFIG_CRYPTO_SHA256=y
# CONFIG_CRYPTO_SHA512 is not set
# CONFIG_CRYPTO_SHA3 is not set
# CONFIG_CRYPTO_TGR192 is not set
# CONFIG_CRYPTO_WP512 is not set
#
# Ciphers
#
CONFIG_CRYPTO_AES=y
# CONFIG_CRYPTO_ANUBIS is not set
# CONFIG_CRYPTO_ARC4 is not set
# CONFIG_CRYPTO_BLOWFISH is not set
# CONFIG_CRYPTO_CAMELLIA is not set
# CONFIG_CRYPTO_CAST5 is not set
# CONFIG_CRYPTO_CAST6 is not set
CONFIG_CRYPTO_DES=y
# CONFIG_CRYPTO_FCRYPT is not set
# CONFIG_CRYPTO_KHAZAD is not set
# CONFIG_CRYPTO_SALSA20 is not set
# CONFIG_CRYPTO_CHACHA20 is not set
# CONFIG_CRYPTO_SEED is not set
# CONFIG_CRYPTO_SERPENT is not set
# CONFIG_CRYPTO_TEA is not set
# CONFIG_CRYPTO_TWOFISH is not set
#
# Compression
#
CONFIG_CRYPTO_DEFLATE=y
CONFIG_CRYPTO_LZO=y
# CONFIG_CRYPTO_842 is not set
# CONFIG_CRYPTO_LZ4 is not set
# CONFIG_CRYPTO_LZ4HC is not set
#
# Random Number Generation
#
# CONFIG_CRYPTO_ANSI_CPRNG is not set
CONFIG_CRYPTO_DRBG_MENU=y
CONFIG_CRYPTO_DRBG_HMAC=y
# CONFIG_CRYPTO_DRBG_HASH is not set
CONFIG_CRYPTO_DRBG=y
CONFIG_CRYPTO_JITTERENTROPY=y
CONFIG_CRYPTO_USER_API=y
CONFIG_CRYPTO_USER_API_HASH=y
CONFIG_CRYPTO_USER_API_SKCIPHER=y
CONFIG_CRYPTO_USER_API_RNG=y
CONFIG_CRYPTO_USER_API_AEAD=y
# CONFIG_CRYPTO_HW is not set
#
# Certificates for signature checking
#
# CONFIG_PPC_CLOCK is not set
CONFIG_PPC_LIB_RHEAP=y
# CONFIG_VIRTUALIZATION is not set
>
>> [ 54.401501] Mem-Info:
>> [ 54.401616] active_anon:2727 inactive_anon:91 isolated_anon:0
>> [ 54.401616] active_file:51 inactive_file:26 isolated_file:0
>> [ 54.401616] unevictable:604 dirty:0 writeback:0 unstable:0
>> [ 54.401616] slab_reclaimable:115 slab_unreclaimable:722
>> [ 54.401616] mapped:787 shmem:284 pagetables:167 bounce:0
>> [ 54.401616] free:1994 free_pcp:0 free_cma:0
>> [ 54.401715] Node 0 active_anon:10908kB inactive_anon:364kB
>> active_file:204kB inactive_file:104kB unevictable:2416kB
>> isolated(anon):0kB isolated(file):0kB mapped:3148kB dirty:0kB
>> writeback:0kB shmem:1136kB writeback_tmp:0kB unstable:0kB
>> pages_scanned:59 all_unreclaimable? no
>> [ 54.401851] DMA free:7976kB min:660kB low:824kB high:988kB
>> active_anon:10908kB inactive_anon:364kB active_file:204kB
>> inactive_file:104kB unevictable:2416kB writepending:0kB present:32768kB
>> managed:27912kB mlocked:2416kB slab_reclaimable:460kB
>> slab_unreclaimable:2888kB kernel_stack:880kB pagetables:668kB bounce:0kB
>> free_pcp:0kB local_pcp:0kB free_cma:0kB
>> lowmem_reserve[]: 0 0 0
>> [ 54.437414] DMA: 460*4kB (UH) 201*8kB (UH) 121*16kB (UH) 43*32kB (UH)
>> 10*64kB (U) 4*128kB (UH) 0*256kB 0*512kB 0*1024kB 0*2048kB 0*4096kB
>> 0*8192kB = 7912kB
>> [ 54.437730] Node 0 hugepages_total=0 hugepages_free=0
>> hugepages_surp=0 hugepages_size=512kB
>> [ 54.437768] Node 0 hugepages_total=0 hugepages_free=0
>> hugepages_surp=0 hugepages_size=8192kB
>> [ 54.437784] 892 total pagecache pages
>> [ 54.437802] 8192 pages RAM
>> [ 54.437818] 0 pages HighMem/MovableOnly
>> [ 54.437834] 1214 pages reserved
>> [ 54.437854] [ pid ] uid tgid total_vm rss nr_ptes nr_pmds
>> swapents oom_score_adj name
>> [ 54.437928] [ 216] 0 216 1240 253 6 0
>> 0 0 rcS
>> [ 54.437986] [ 356] 0 356 4687 333 7 0
>> 0 0 rsyslogd
>> [ 54.438042] [ 360] 0 360 1240 245 5 0
>> 0 0 klogd
>> [ 54.438099] [ 370] 0 370 701 607 5 0
>> 0 -1000 watchdog
>> [ 54.438156] [ 384] 0 384 1114 440 5 0
>> 0 0 ntpd
>> [ 54.438213] [ 401] 0 401 1279 419 6 0
>> 0 0 inetd
>> [ 54.438270] [ 413] 0 413 1240 330 6 0
>> 0 0 crond
>> [ 54.438328] [ 587] 0 587 3334 586 7 0
>> 0 0 CORSurv
>> [ 54.438384] [ 614] 0 614 484 232 5 0
>> 0 0 ASMcsci
>> [ 54.438441] [ 662] 0 662 18777 625 13 0
>> 0 0 VOIPcsc
>> [ 54.438499] [ 708] 0 708 18402 1166 22 0
>> 0 0 RCUSwitch
>> [ 54.447253] [ 739] 0 739 12958 1275 17 0
>> 0 0 CRI_main
>> [ 54.447320] [ 756] 0 756 1240 380 6 0
>> 0 0 exe
>> [ 54.447379] [ 757] 0 757 1240 369 6 0
>> 0 0 S99watchdogd-ap
>> [ 54.447436] [ 777] 0 777 1240 210 5 0
>> 0 0 S99watchdogd-ap
>> [ 54.447493] [ 782] 0 782 793 425 5 0
>> 0 0 socat
>> [ 54.447550] [ 784] 0 784 754 420 5 0
>> 0 0 socat
>> [ 54.447607] [ 791] 0 791 793 426 5 0
>> 0 0 socat
>> [ 54.447663] [ 792] 0 792 754 420 5 0
>> 0 0 socat
>> [ 54.447720] [ 799] 0 799 793 426 5 0
>> 0 0 socat
>> [ 54.447777] [ 800] 0 800 754 420 5 0
>> 0 0 socat
>> [ 54.447833] [ 807] 0 807 793 425 5 0
>> 0 0 socat
>> [ 54.447890] [ 808] 0 808 754 421 5 0
>> 0 0 socat
>> [ 54.447927] Out of memory: Kill process 739 (CRI_main) score 180 or
>> sacrifice child
>> [ 54.528280] Killed process 739 (CRI_main) total-vm:51832kB,
>> anon-rss:3140kB, file-rss:1592kB, shmem-rss:236kB
^ permalink raw reply
* [PATCH] powerpc: Add NVDIMM to powernv_defconfig
From: Michael Neuling @ 2018-04-26 6:22 UTC (permalink / raw)
To: mpe; +Cc: linuxppc-dev, oohall, mikey
This enables greater testing NVDIMMs as it becomes more
prevalent. This is also the minimal required to enable persistent
memory in mambo.
This adds 100KB to the kernel text and 170KB to the vmlinux
Signed-off-by: Michael Neuling <mikey@neuling.org>
---
arch/powerpc/configs/powernv_defconfig | 2 ++
1 file changed, 2 insertions(+)
diff --git a/arch/powerpc/configs/powernv_defconfig b/arch/powerpc/configs/powernv_defconfig
index 9e92aa6a52..0f94b7dc11 100644
--- a/arch/powerpc/configs/powernv_defconfig
+++ b/arch/powerpc/configs/powernv_defconfig
@@ -238,6 +238,8 @@ CONFIG_RTC_CLASS=y
CONFIG_RTC_DRV_GENERIC=y
CONFIG_VIRTIO_PCI=m
CONFIG_VIRTIO_BALLOON=m
+CONFIG_LIBNVDIMM=y
+# CONFIG_ND_BLK is not set
CONFIG_EXT2_FS=y
CONFIG_EXT2_FS_XATTR=y
CONFIG_EXT2_FS_POSIX_ACL=y
--
2.14.1
^ permalink raw reply related
* [PATCH] powerpc: paste - Mask XERSO bit in CR
From: Haren Myneni @ 2018-04-26 6:48 UTC (permalink / raw)
To: mpe; +Cc: linuxppc-dev
NX can set 3rd bit in CR register for XER[SO] (Summation overflow)
which is not used for paste return value. So. mask this bit to get
proper return status.
Signed-off-by: Haren Myneni <haren@us.ibm.com>
diff --git a/arch/powerpc/platforms/powernv/copy-paste.h b/arch/powerpc/platforms/powernv/copy-paste.h
index c9a5036..82392e3 100644
--- a/arch/powerpc/platforms/powernv/copy-paste.h
+++ b/arch/powerpc/platforms/powernv/copy-paste.h
@@ -9,7 +9,8 @@
#include <asm/ppc-opcode.h>
#define CR0_SHIFT 28
-#define CR0_MASK 0xF
+#define CR0_MASK 0xE /* 3rd bit undefined or set for XER[SO] */
+
/*
* Copy/paste instructions:
*
^ permalink raw reply related
* Re: [PATCH v2 3/7] powerpc: use task_pid_nr() for TID allocation
From: Andrew Donnellan @ 2018-04-26 9:25 UTC (permalink / raw)
To: Sukadev Bhattiprolu
Cc: Alastair D'Silva, linuxppc-dev, linux-kernel, linux-doc,
mikey, vaibhav, aneesh.kumar, malat, felix, pombredanne, sukadev,
npiggin, gregkh, arnd, fbarrat, corbet, Alastair D'Silva,
Christophe Lombard
In-Reply-To: <20180424211231.GA25392@us.ibm.com>
On 25/04/18 07:12, Sukadev Bhattiprolu wrote:
> Yes. Like with PIDR, was trying to assign TIDR initially to all threads.
> But since only a subset of threads need/use TIDR, we can assign the
> value later (when set_thread_tidr() is called). So we should be able to
> use task_pid_nr() then.
OK. Alastair has also confirmed with me that truncating the pid to a u16
should be safe, so therefore:
Reviewed-by: Andrew Donnellan <andrew.donnellan@au1.ibm.com>
--
Andrew Donnellan OzLabs, ADL Canberra
andrew.donnellan@au1.ibm.com IBM Australia Limited
^ permalink raw reply
* Re: [PATCH] powerpc: Fix smp_send_stop NMI IPI handling
From: Michael Ellerman @ 2018-04-26 9:47 UTC (permalink / raw)
To: Nicholas Piggin; +Cc: linuxppc-dev, Abdul Haleem
In-Reply-To: <20180425135104.3e9e3812@roar.ozlabs.ibm.com>
Nicholas Piggin <npiggin@gmail.com> writes:
> On Wed, 25 Apr 2018 13:15:34 +1000
> Michael Ellerman <mpe@ellerman.id.au> wrote:
>> Nicholas Piggin <npiggin@gmail.com> writes:
>>
>> > The NMI IPI handler for a receiving CPU increments nmi_ipi_busy_count
>> > over the handler function call, which causes later smp_send_nmi_ipi()
>> > callers to spin until the call is finished.
>> >
>> > The smp_send_stop function never returns, so the busy count is never
>> > decremeted, which can cause the system to hang in some cases. For
>> > example panic() will call smp_send_stop early on, then later in the
>> > reboot path, pnv_restart will call smp_send_stop again, which hangs.
>> >
>> > Fix this by adding a special case to the smp_send_stop handler to
>> > decrement the busy count, because it will never return.
>> >
>> > Fixes: 6bed3237624e3 ("powerpc: use NMI IPI for smp_send_stop")
>> > Reported-by: Abdul Haleem <abdhalee@linux.vnet.ibm.com>
>> > Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
>> > ---
>> > arch/powerpc/kernel/smp.c | 11 ++++++++++-
>> > 1 file changed, 10 insertions(+), 1 deletion(-)
>> >
>> > diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c
>> > index e16ec7b3b427..250fccf04c6e 100644
>> > --- a/arch/powerpc/kernel/smp.c
>> > +++ b/arch/powerpc/kernel/smp.c
>> > @@ -567,10 +567,19 @@ void crash_send_ipi(void (*crash_ipi_callback)(struct pt_regs *))
>> >
>> > #ifdef CONFIG_NMI_IPI
>> > static void stop_this_cpu(struct pt_regs *regs)
>> > +{
>> > + /*
>> > + * This is a special case because it never returns, so the NMI IPI
>> > + * handling would never mark it as done, which makes any later
>> > + * smp_send_nmi_ipi() call spin forever. Mark it done now.
>> > + */
>> > + nmi_ipi_lock();
>> > + nmi_ipi_busy_count--;
>> > + nmi_ipi_unlock();
>> > #else
>> > static void stop_this_cpu(void *dummy)
>> > -#endif
>> > {
>> > +#endif
>>
>> I don't love this ifdef/endif business.
>>
>> Can we do it this way instead?
>
> Yeah that's better. Does stop_this_cpu give you an unused function warning
> if you compile with NMI though? I think we need an #if/#else
No because it's called from nmi_stop_this_cpu():
>> +#ifdef CONFIG_NMI_IPI
>> +static void nmi_stop_this_cpu(struct pt_regs *regs)
>> +{
>> + /*
>> + * This is a special case because it never returns, so the NMI IPI
>> + * handling would never mark it as done, which makes any later
>> + * smp_send_nmi_ipi() call spin forever. Mark it done now.
>> + */
>> + nmi_ipi_lock();
>> + nmi_ipi_busy_count--;
>> + nmi_ipi_unlock();
>> +
>> + stop_this_cpu(NULL);
>> +}
>> +#endif
cheers
^ permalink raw reply
* [PATCH v3] powerpc: Fix smp_send_stop NMI IPI handling
From: Michael Ellerman @ 2018-04-26 10:19 UTC (permalink / raw)
To: linuxppc-dev; +Cc: npiggin
From: Nicholas Piggin <npiggin@gmail.com>
The NMI IPI handler for a receiving CPU increments nmi_ipi_busy_count
over the handler function call, which causes later smp_send_nmi_ipi()
callers to spin until the call is finished.
The stop_this_cpu() function never returns, so the busy count is never
decremeted, which can cause the system to hang in some cases. For
example panic() will call smp_send_stop() early on which calls
stop_this_cpu() on other CPUs, then later in the reboot path,
pnv_restart() will call smp_send_stop() again, which hangs.
Fix this by adding a special case to the stop_this_cpu() handler to
decrement the busy count, because it will never return.
Now that the NMI/non-NMI versions of stop_this_cpu() are different,
split them out into separate functions rather than doing #ifdef tricks
to share the body between the two functions.
Fixes: 6bed3237624e3 ("powerpc: use NMI IPI for smp_send_stop")
Reported-by: Abdul Haleem <abdhalee@linux.vnet.ibm.com>
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
[mpe: Split out the functions, tweak change log a bit]
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
---
arch/powerpc/kernel/smp.c | 22 +++++++++++++++++-----
1 file changed, 17 insertions(+), 5 deletions(-)
v3: Split into separate functions, rather than doing #ifdef tricks.
diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c
index e16ec7b3b427..3582f30b60b7 100644
--- a/arch/powerpc/kernel/smp.c
+++ b/arch/powerpc/kernel/smp.c
@@ -565,11 +565,7 @@ void crash_send_ipi(void (*crash_ipi_callback)(struct pt_regs *))
}
#endif
-#ifdef CONFIG_NMI_IPI
-static void stop_this_cpu(struct pt_regs *regs)
-#else
static void stop_this_cpu(void *dummy)
-#endif
{
/* Remove this CPU */
set_cpu_online(smp_processor_id(), false);
@@ -580,10 +576,26 @@ static void stop_this_cpu(void *dummy)
spin_cpu_relax();
}
+#ifdef CONFIG_NMI_IPI
+static void nmi_stop_this_cpu(struct pt_regs *regs)
+{
+ /*
+ * This is a special case because it never returns, so the NMI IPI
+ * handling would never mark it as done, which makes any later
+ * smp_send_nmi_ipi() call spin forever. Mark it done now.
+ */
+ nmi_ipi_lock();
+ nmi_ipi_busy_count--;
+ nmi_ipi_unlock();
+
+ stop_this_cpu(NULL);
+}
+#endif
+
void smp_send_stop(void)
{
#ifdef CONFIG_NMI_IPI
- smp_send_nmi_ipi(NMI_IPI_ALL_OTHERS, stop_this_cpu, 1000000);
+ smp_send_nmi_ipi(NMI_IPI_ALL_OTHERS, nmi_stop_this_cpu, 1000000);
#else
smp_call_function(stop_this_cpu, NULL, 0);
#endif
--
2.14.1
^ permalink raw reply related
* Re: [2/3] powerpc/powernv: Fix OPAL RTC driver OPAL_BUSY loops
From: Michael Ellerman @ 2018-04-26 10:22 UTC (permalink / raw)
To: Nicholas Piggin, linuxppc-dev; +Cc: linux-rtc, Nicholas Piggin
In-Reply-To: <20180410114933.24581-3-npiggin@gmail.com>
On Tue, 2018-04-10 at 11:49:32 UTC, Nicholas Piggin wrote:
> The OPAL RTC driver does not sleep in case it gets OPAL_BUSY or
> OPAL_BUSY_EVENT from firmware, which causes large scheduling
> latencies, up to 50 seconds have been observed here when RTC stops
> responding (BMC reboot can do it).
>
> Fix this by converting it to the standard form OPAL_BUSY loop that
> sleeps.
>
> Fixes 628daa8d5abfd ("powerpc/powernv: Add RTC and NVRAM support plus RTAS fallbacks"
> Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
> Cc: linux-rtc@vger.kernel.org
> Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
> Acked-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
Applied to powerpc fixes, thanks.
https://git.kernel.org/powerpc/c/682e6b4da5cbe8e9a53f979a58c2a9
cheers
^ permalink raw reply
* Re: [v3] powerpc: Fix smp_send_stop NMI IPI handling
From: Michael Ellerman @ 2018-04-26 10:22 UTC (permalink / raw)
To: Michael Ellerman, linuxppc-dev; +Cc: npiggin
In-Reply-To: <20180426101902.22886-1-mpe@ellerman.id.au>
On Thu, 2018-04-26 at 10:19:02 UTC, Michael Ellerman wrote:
> From: Nicholas Piggin <npiggin@gmail.com>
>
> The NMI IPI handler for a receiving CPU increments nmi_ipi_busy_count
> over the handler function call, which causes later smp_send_nmi_ipi()
> callers to spin until the call is finished.
>
> The stop_this_cpu() function never returns, so the busy count is never
> decremeted, which can cause the system to hang in some cases. For
> example panic() will call smp_send_stop() early on which calls
> stop_this_cpu() on other CPUs, then later in the reboot path,
> pnv_restart() will call smp_send_stop() again, which hangs.
>
> Fix this by adding a special case to the stop_this_cpu() handler to
> decrement the busy count, because it will never return.
>
> Now that the NMI/non-NMI versions of stop_this_cpu() are different,
> split them out into separate functions rather than doing #ifdef tricks
> to share the body between the two functions.
>
> Fixes: 6bed3237624e3 ("powerpc: use NMI IPI for smp_send_stop")
> Reported-by: Abdul Haleem <abdhalee@linux.vnet.ibm.com>
> Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
> [mpe: Split out the functions, tweak change log a bit]
> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Applied to powerpc fixes.
https://git.kernel.org/powerpc/c/ac61c1156623455c46701654abd8c9
cheers
^ permalink raw reply
* Re: [PATCH v2] powerpc: Fix smp_send_stop NMI IPI handling
From: Michael Ellerman @ 2018-04-26 10:30 UTC (permalink / raw)
To: Nicholas Piggin, linuxppc-dev; +Cc: Nicholas Piggin, Abdul Haleem
In-Reply-To: <20180425113512.20595-1-npiggin@gmail.com>
Nicholas Piggin <npiggin@gmail.com> writes:
> The NMI IPI handler for a receiving CPU increments nmi_ipi_busy_count
> over the handler function call, which causes later smp_send_nmi_ipi()
> callers to spin until the call is finished.
>
> The smp_send_stop function never returns, so the busy count is never
> decremeted, which can cause the system to hang in some cases. For
> example panic() will call smp_send_stop early on, then later in the
> reboot path, pnv_restart will call smp_send_stop again, which hangs.
>
> Fix this by adding a special case to the smp_send_stop handler to
> decrement the busy count, because it will never return.
>
> Fixes: 6bed3237624e3 ("powerpc: use NMI IPI for smp_send_stop")
> Reported-by: Abdul Haleem <abdhalee@linux.vnet.ibm.com>
> Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
> ---
> Changes since v1:
> - Reduce #ifdef spaghetti suggested by mpe
Sorry I missed this.
But then saw it in the patchwork listing, which is why I sent my version
as v3. Which I also merged. Sorry for the confusion.
I'm pretty sure my version is equivalent to this, except for the way the
#ifdefs are arranged.
The end result of this is nicer than my version, so I'd take a cleanup
patch to get us to this final state.
cheers
^ permalink raw reply
* Re: [PATCH v2 9/9] powerpc/hugetlb: Enable hugetlb migration for ppc64
From: Christophe LEROY @ 2018-04-26 10:35 UTC (permalink / raw)
To: Aneesh Kumar K.V, mpe; +Cc: akpm, linux-mm, linuxppc-dev, linux-kernel
In-Reply-To: <1494926612-23928-10-git-send-email-aneesh.kumar@linux.vnet.ibm.com>
Le 16/05/2017 à 11:23, Aneesh Kumar K.V a écrit :
> Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
> ---
> arch/powerpc/platforms/Kconfig.cputype | 5 +++++
> 1 file changed, 5 insertions(+)
>
> diff --git a/arch/powerpc/platforms/Kconfig.cputype b/arch/powerpc/platforms/Kconfig.cputype
> index 80175000042d..8acc4f27d101 100644
> --- a/arch/powerpc/platforms/Kconfig.cputype
> +++ b/arch/powerpc/platforms/Kconfig.cputype
> @@ -351,6 +351,11 @@ config PPC_RADIX_MMU
> is only implemented by IBM Power9 CPUs, if you don't have one of them
> you can probably disable this.
>
> +config ARCH_ENABLE_HUGEPAGE_MIGRATION
> + def_bool y
> + depends on PPC_BOOK3S_64 && HUGETLB_PAGE && MIGRATION
> +
> +
Is there a reason why you redefine ARCH_ENABLE_HUGEPAGE_MIGRATION
instead of doing a 'select' as it is already defined in mm/Kconfig ?
Christophe
> config PPC_MMU_NOHASH
> def_bool y
> depends on !PPC_STD_MMU
>
^ permalink raw reply
* [PATCH v5 0/4] powerpc/fadump: Improvements and fixes for firmware-assisted dump.
From: Mahesh J Salgaonkar @ 2018-04-26 11:41 UTC (permalink / raw)
To: linuxppc-dev
Cc: Srikar Dronamraju, kernelfans, Aneesh Kumar K.V, Hari Bathini,
Nathan Fontenot, Anshuman Khandual, Ananth Narayan
One of the primary issues with Firmware Assisted Dump (fadump) on Power
is that it needs a large amount of memory to be reserved. This reserved
memory is used for saving the contents of old crashed kernel's memory before
fadump capture kernel uses old kernel's memory area to boot. However, This
reserved memory area stays unused until system crash and isn't available
for production kernel to use.
Instead of setting aside a significant chunk of memory that nobody can use,
take advantage Linux kernel's Contiguous Memory Allocator (CMA) feature,
to reserve a significant chunk of memory that the kernel is prevented from
using , but applications are free to use it.
Patch 2 implements the usage of CMA region to allow production kernel to
use that memory for applications usage, making fadump reservationless.
We now initialize siginificant chunk of faump reserved memory for CMA.
Patch 1, 3 and 4 fixes various fadump issues and bugs.
Changes in V5:
- Drop the patch that does metadata movement.
- Move the kexec fix patch to top (patch 1)
- Fold CMA documenation patch into patch 2
- Fix the compilation issues when CONFIG_CMA is not set. Reported by Hari.
- Use the approach of using boot memory size for CMA as suggested by Hari
except the movement of sections. Thanks to Hari.
Changes in V4:
- patch 1: Make fadump compatible irrespective of kernel versions.
- patch 4: moved out of the series and been posted seperatly at
http://patchwork.ozlabs.org/patch/896716/
- Documentation update about CMA reservation.
Changes in V3:
- patch 1 & 2: move metadata region and documentation update.
- patch 7: Un-register the faudmp on kexec path
---
Mahesh Salgaonkar (4):
powerpc/fadump: un-register fadump on kexec path.
powerpc/fadump: Reservationless firmware assisted dump
powerpc/fadump: throw proper error message on fadump registration failure.
powerpc/fadump: Do not allow hot-remove memory from fadump reserved area.
Documentation/powerpc/firmware-assisted-dump.txt | 10 ++
arch/powerpc/include/asm/fadump.h | 6 +
arch/powerpc/kernel/fadump.c | 130 ++++++++++++++++++++--
arch/powerpc/platforms/pseries/hotplug-memory.c | 7 +
4 files changed, 137 insertions(+), 16 deletions(-)
--
Signature
^ permalink raw reply
* [PATCH v5 1/4] powerpc/fadump: un-register fadump on kexec path.
From: Mahesh J Salgaonkar @ 2018-04-26 11:42 UTC (permalink / raw)
To: linuxppc-dev
Cc: Srikar Dronamraju, kernelfans, Aneesh Kumar K.V, Hari Bathini,
Nathan Fontenot, Anshuman Khandual, Ananth Narayan
In-Reply-To: <152474278043.5697.2553982145593952228.stgit@jupiter.in.ibm.com>
From: Mahesh Salgaonkar <mahesh@linux.vnet.ibm.com>
otherwise the fadump registration in new kexec-ed kernel complains that
fadump is already registered. This makes new kernel to continue using
fadump registered by previous kernel which may lead to invalid vmcore
generation. Hence this patch fixes this issue by un-registering fadump
in fadump_cleanup() which is called during kexec path so that new kernel
can register fadump with new valid values.
Signed-off-by: Mahesh Salgaonkar <mahesh@linux.vnet.ibm.com>
---
arch/powerpc/kernel/fadump.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/arch/powerpc/kernel/fadump.c b/arch/powerpc/kernel/fadump.c
index 8ceabef40d3d..07e8396d472b 100644
--- a/arch/powerpc/kernel/fadump.c
+++ b/arch/powerpc/kernel/fadump.c
@@ -1180,6 +1180,9 @@ void fadump_cleanup(void)
init_fadump_mem_struct(&fdm,
be64_to_cpu(fdm_active->cpu_state_data.destination_address));
fadump_invalidate_dump(&fdm);
+ } else if (fw_dump.dump_registered) {
+ /* Un-register Firmware-assisted dump if it was registered. */
+ fadump_unregister_dump(&fdm);
}
}
^ permalink raw reply related
* [PATCH v5 2/4] powerpc/fadump: Reservationless firmware assisted dump
From: Mahesh J Salgaonkar @ 2018-04-26 11:42 UTC (permalink / raw)
To: linuxppc-dev
Cc: Srikar Dronamraju, kernelfans, Aneesh Kumar K.V, Hari Bathini,
Nathan Fontenot, Anshuman Khandual, Ananth Narayan
In-Reply-To: <152474278043.5697.2553982145593952228.stgit@jupiter.in.ibm.com>
From: Mahesh Salgaonkar <mahesh@linux.vnet.ibm.com>
One of the primary issues with Firmware Assisted Dump (fadump) on Power
is that it needs a large amount of memory to be reserved. On large
systems with TeraBytes of memory, this reservation can be quite
significant.
In some cases, fadump fails if the memory reserved is insufficient, or
if the reserved memory was DLPAR hot-removed.
In the normal case, post reboot, the preserved memory is filtered to
extract only relevant areas of interest using the makedumpfile tool.
While the tool provides flexibility to determine what needs to be part
of the dump and what memory to filter out, all supported distributions
default this to "Capture only kernel data and nothing else".
We take advantage of this default and the Linux kernel's Contiguous
Memory Allocator (CMA) to fundamentally change the memory reservation
model for fadump.
Instead of setting aside a significant chunk of memory nobody can use,
this patch uses CMA instead, to reserve a significant chunk of memory
that the kernel is prevented from using (due to MIGRATE_CMA), but
applications are free to use it. With this fadump will still be able
to capture all of the kernel memory and most of the user space memory
except the user pages that were present in CMA region.
Essentially, on a P9 LPAR with 2 cores, 8GB RAM and current upstream:
[root@zzxx-yy10 ~]# free -m
total used free shared buff/cache available
Mem: 7557 193 6822 12 541 6725
Swap: 4095 0 4095
With this patch:
[root@zzxx-yy10 ~]# free -m
total used free shared buff/cache available
Mem: 8133 194 7464 12 475 7338
Swap: 4095 0 4095
Changes made here are completely transparent to how fadump has
traditionally worked.
Thanks to Aneesh Kumar and Anshuman Khandual for helping us understand
CMA and its usage.
TODO:
- Handle case where CMA reservation spans nodes.
Signed-off-by: Ananth N Mavinakayanahalli <ananth@linux.vnet.ibm.com>
Signed-off-by: Mahesh Salgaonkar <mahesh@linux.vnet.ibm.com>
Signed-off-by: Hari Bathini <hbathini@linux.vnet.ibm.com>
---
Documentation/powerpc/firmware-assisted-dump.txt | 10 ++-
arch/powerpc/include/asm/fadump.h | 4 +
arch/powerpc/kernel/fadump.c | 84 +++++++++++++++++++---
3 files changed, 87 insertions(+), 11 deletions(-)
diff --git a/Documentation/powerpc/firmware-assisted-dump.txt b/Documentation/powerpc/firmware-assisted-dump.txt
index bdd344aa18d9..f2823a1e3f9d 100644
--- a/Documentation/powerpc/firmware-assisted-dump.txt
+++ b/Documentation/powerpc/firmware-assisted-dump.txt
@@ -113,7 +113,15 @@ header, is usually reserved at an offset greater than boot memory
size (see Fig. 1). This area is *not* released: this region will
be kept permanently reserved, so that it can act as a receptacle
for a copy of the boot memory content in addition to CPU state
-and HPTE region, in the case a crash does occur.
+and HPTE region, in the case a crash does occur. Since this reserved
+memory area is used only after the system crash, there is no point in
+blocking this significant chunk of memory from production kernel.
+Hence, the implementation uses the Linux kernel's Contiguous Memory
+Allocator (CMA) for memory reservation if CMA is configured for kernel.
+With CMA reservation this memory will be available for applications to
+use it, while kernel is prevented from using it. With this fadump will
+still be able to capture all of the kernel memory and most of the user
+space memory except the user pages that were present in CMA region.
o Memory Reservation during first kernel
diff --git a/arch/powerpc/include/asm/fadump.h b/arch/powerpc/include/asm/fadump.h
index 5a23010af600..0bf0d3b37c6e 100644
--- a/arch/powerpc/include/asm/fadump.h
+++ b/arch/powerpc/include/asm/fadump.h
@@ -48,6 +48,10 @@
#define memblock_num_regions(memblock_type) (memblock.memblock_type.cnt)
+/* Alignement per CMA requirement. */
+#define FADUMP_CMA_ALIGNMENT (PAGE_SIZE << \
+ max_t(unsigned long, MAX_ORDER - 1, pageblock_order))
+
/* Firmware provided dump sections */
#define FADUMP_CPU_STATE_DATA 0x0001
#define FADUMP_HPTE_REGION 0x0002
diff --git a/arch/powerpc/kernel/fadump.c b/arch/powerpc/kernel/fadump.c
index 07e8396d472b..d44d89c8967f 100644
--- a/arch/powerpc/kernel/fadump.c
+++ b/arch/powerpc/kernel/fadump.c
@@ -34,6 +34,7 @@
#include <linux/crash_dump.h>
#include <linux/kobject.h>
#include <linux/sysfs.h>
+#include <linux/cma.h>
#include <asm/debugfs.h>
#include <asm/page.h>
@@ -45,11 +46,68 @@
static struct fw_dump fw_dump;
static struct fadump_mem_struct fdm;
static const struct fadump_mem_struct *fdm_active;
+#ifdef CONFIG_CMA
+static struct cma *fadump_cma;
+#endif
static DEFINE_MUTEX(fadump_mutex);
struct fad_crash_memory_ranges crash_memory_ranges[INIT_CRASHMEM_RANGES];
int crash_mem_ranges;
+#ifdef CONFIG_CMA
+/*
+ * fadump_cma_init() - Initializ CMA area from a fadump reserved memory
+ *
+ * This function initializes CMA area from fadump reserved memory.
+ * The total size of fadump reserved memory covers for boot memory size
+ * + cpu data size + hpte size and metadata.
+ * Initialize only the area equivalent to boot memory size for CMA use.
+ * The reamining portion of fadump reserved memory will be not given
+ * to CMA and pages for thoes will stay reserved. boot memory size is
+ * aligned per CMA requirement to satisy cma_init_reserved_mem() call.
+ * But for some reason even if it fails we still have the memory reservation
+ * with us and we can still continue doing fadump.
+ */
+int __init fadump_cma_init(void)
+{
+ unsigned long long base, size;
+ int rc;
+
+ if (!fw_dump.fadump_enabled)
+ return 0;
+
+ base = fw_dump.reserve_dump_area_start;
+ size = fw_dump.boot_memory_size;
+
+ if (!size)
+ return 0;
+
+ rc = cma_init_reserved_mem(base, size, 0, "fadump_cma", &fadump_cma);
+ if (rc) {
+ pr_err("Failed to init cma area for firmware-assisted dump,%d\n", rc);
+ /*
+ * Though the CMA init has failed we still have memory
+ * reservation with us. The reserved memory will be
+ * blocked from production system usage. Hence return 1,
+ * so that we can continue with fadump.
+ */
+ return 1;
+ }
+
+ /*
+ * So we now have successfully initialized cma area for fadump.
+ */
+ pr_info("Initialized 0x%lx bytes cma area at %ldMB from 0x%lx "
+ "bytes of memory reserved for firmware-assisted dump\n",
+ cma_get_size(fadump_cma),
+ (unsigned long)cma_get_base(fadump_cma) >> 20,
+ fw_dump.reserve_dump_area_size);
+ return 1;
+}
+#else
+static int __init fadump_cma_init(void) { return 1; }
+#endif /* CONFIG_CMA */
+
/* Scan the Firmware Assisted dump configuration details. */
int __init early_init_dt_scan_fw_dump(unsigned long node,
const char *uname, int depth, void *data)
@@ -375,8 +433,13 @@ int __init fadump_reserve_mem(void)
*/
if (fdm_active)
fw_dump.boot_memory_size = be64_to_cpu(fdm_active->rmr_region.source_len);
- else
+ else {
fw_dump.boot_memory_size = fadump_calculate_reserve_size();
+#ifdef CONFIG_CMA
+ fw_dump.boot_memory_size = ALIGN(fw_dump.boot_memory_size,
+ FADUMP_CMA_ALIGNMENT);
+#endif
+ }
/*
* Calculate the memory boundary.
@@ -423,8 +486,9 @@ int __init fadump_reserve_mem(void)
fw_dump.fadumphdr_addr =
be64_to_cpu(fdm_active->rmr_region.destination_address) +
be64_to_cpu(fdm_active->rmr_region.source_len);
- pr_debug("fadumphdr_addr = %p\n",
- (void *) fw_dump.fadumphdr_addr);
+ pr_debug("fadumphdr_addr = %pa\n", &fw_dump.fadumphdr_addr);
+ fw_dump.reserve_dump_area_start = base;
+ fw_dump.reserve_dump_area_size = size;
} else {
size = get_fadump_area_size();
@@ -452,10 +516,11 @@ int __init fadump_reserve_mem(void)
(unsigned long)(size >> 20),
(unsigned long)(base >> 20),
(unsigned long)(memblock_phys_mem_size() >> 20));
- }
- fw_dump.reserve_dump_area_start = base;
- fw_dump.reserve_dump_area_size = size;
+ fw_dump.reserve_dump_area_start = base;
+ fw_dump.reserve_dump_area_size = size;
+ return fadump_cma_init();
+ }
return 1;
}
@@ -1146,7 +1211,7 @@ static int fadump_unregister_dump(struct fadump_mem_struct *fdm)
return 0;
}
-static int fadump_invalidate_dump(struct fadump_mem_struct *fdm)
+static int fadump_invalidate_dump(const struct fadump_mem_struct *fdm)
{
int rc = 0;
unsigned int wait_time;
@@ -1177,9 +1242,8 @@ void fadump_cleanup(void)
{
/* Invalidate the registration only if dump is active. */
if (fw_dump.dump_active) {
- init_fadump_mem_struct(&fdm,
- be64_to_cpu(fdm_active->cpu_state_data.destination_address));
- fadump_invalidate_dump(&fdm);
+ /* pass the same memory dump structure provided by platform */
+ fadump_invalidate_dump(fdm_active);
} else if (fw_dump.dump_registered) {
/* Un-register Firmware-assisted dump if it was registered. */
fadump_unregister_dump(&fdm);
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox