Linux v4.14.4 rebase
This commit is contained in:
parent
9edb1b5f46
commit
c75cb4d7fb
|
@ -0,0 +1,46 @@
|
|||
From 37af97ef14c201b1db8dd341aabd262da23e48aa Mon Sep 17 00:00:00 2001
|
||||
From: Fedora Kernel Team <kernel-team@fedoraproject.org>
|
||||
Date: Mon, 30 Oct 2017 11:38:27 -0500
|
||||
Subject: [PATCH] [PATCH] staging: rtl8822be: fix wrong dma unmap len
|
||||
|
||||
Patch fixes splat:
|
||||
|
||||
r8822be 0000:04:00.0: DMA-API: device driver frees DMA memory with different size
|
||||
[device address=0x0000000078477000] [map size=4096 bytes] [unmap size=424 bytes]
|
||||
<snip>
|
||||
Call Trace:
|
||||
debug_dma_unmap_page+0xa5/0xb0
|
||||
? unmap_single+0x2f/0x40
|
||||
_rtl8822be_send_bcn_or_cmd_packet+0x2c5/0x300 [r8822be]
|
||||
? _rtl8822be_send_bcn_or_cmd_packet+0x2c5/0x300 [r8822be]
|
||||
rtl8822b_halmac_cb_write_data_rsvd_page+0x51/0xc0 [r8822be]
|
||||
_halmac_write_data_rsvd_page+0x22/0x30 [r8822be]
|
||||
halmac_download_rsvd_page_88xx+0xee/0x1f0 [r8822be]
|
||||
halmac_dlfw_to_mem_88xx+0x80/0x120 [r8822be]
|
||||
halmac_download_firmware_88xx.part.47+0x477/0x600 [r8822be]
|
||||
halmac_download_firmware_88xx+0x32/0x40 [r8822be]
|
||||
rtl_halmac_dlfw+0x70/0x120 [r8822be]
|
||||
rtl_halmac_init_hal+0x5f/0x1b0 [r8822be]
|
||||
rtl8822be_hw_init+0x8a2/0x1040 [r8822be]
|
||||
|
||||
Signed-off-by: Stanislaw Gruszka <sgruszka at redhat.com>
|
||||
---
|
||||
drivers/staging/rtlwifi/rtl8822be/fw.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/drivers/staging/rtlwifi/rtl8822be/fw.c b/drivers/staging/rtlwifi/rtl8822be/fw.c
|
||||
index 8e24da1..a2cc548 100644
|
||||
--- a/drivers/staging/rtlwifi/rtl8822be/fw.c
|
||||
+++ b/drivers/staging/rtlwifi/rtl8822be/fw.c
|
||||
@@ -419,7 +419,7 @@ static bool _rtl8822be_send_bcn_or_cmd_packet(struct ieee80211_hw *hw,
|
||||
dma_addr = rtlpriv->cfg->ops->get_desc(
|
||||
hw, (u8 *)pbd_desc, true, HW_DESC_TXBUFF_ADDR);
|
||||
|
||||
- pci_unmap_single(rtlpci->pdev, dma_addr, skb->len,
|
||||
+ pci_unmap_single(rtlpci->pdev, dma_addr, pskb->len,
|
||||
PCI_DMA_TODEVICE);
|
||||
kfree_skb(pskb);
|
||||
|
||||
--
|
||||
2.13.6
|
||||
|
|
@ -1,296 +0,0 @@
|
|||
From 9d5b86ac13c573795525ecac6ed2db39ab23e2a8 Mon Sep 17 00:00:00 2001
|
||||
From: Benjamin Coddington <bcodding@redhat.com>
|
||||
Date: Sun, 16 Jul 2017 10:28:22 -0400
|
||||
Subject: [PATCH] fs/locks: Remove fl_nspid and use fs-specific l_pid for
|
||||
remote locks
|
||||
|
||||
Since commit c69899a17ca4 "NFSv4: Update of VFS byte range lock must be
|
||||
atomic with the stateid update", NFSv4 has been inserting locks in rpciod
|
||||
worker context. The result is that the file_lock's fl_nspid is the
|
||||
kworker's pid instead of the original userspace pid.
|
||||
|
||||
The fl_nspid is only used to represent the namespaced virtual pid number
|
||||
when displaying locks or returning from F_GETLK. There's no reason to set
|
||||
it for every inserted lock, since we can usually just look it up from
|
||||
fl_pid. So, instead of looking up and holding struct pid for every lock,
|
||||
let's just look up the virtual pid number from fl_pid when it is needed.
|
||||
That means we can remove fl_nspid entirely.
|
||||
|
||||
The translaton and presentation of fl_pid should handle the following four
|
||||
cases:
|
||||
|
||||
1 - F_GETLK on a remote file with a remote lock:
|
||||
In this case, the filesystem should determine the l_pid to return here.
|
||||
Filesystems should indicate that the fl_pid represents a non-local pid
|
||||
value that should not be translated by returning an fl_pid <= 0.
|
||||
|
||||
2 - F_GETLK on a local file with a remote lock:
|
||||
This should be the l_pid of the lock manager process, and translated.
|
||||
|
||||
3 - F_GETLK on a remote file with a local lock, and
|
||||
4 - F_GETLK on a local file with a local lock:
|
||||
These should be the translated l_pid of the local locking process.
|
||||
|
||||
Fuse was already doing the correct thing by translating the pid into the
|
||||
caller's namespace. With this change we must update fuse to translate
|
||||
to init's pid namespace, so that the locks API can then translate from
|
||||
init's pid namespace into the pid namespace of the caller.
|
||||
|
||||
With this change, the locks API will expect that if a filesystem returns
|
||||
a remote pid as opposed to a local pid for F_GETLK, that remote pid will
|
||||
be <= 0. This signifies that the pid is remote, and the locks API will
|
||||
forego translating that pid into the pid namespace of the local calling
|
||||
process.
|
||||
|
||||
Finally, we convert remote filesystems to present remote pids using
|
||||
negative numbers. Have lustre, 9p, ceph, cifs, and dlm negate the remote
|
||||
pid returned for F_GETLK lock requests.
|
||||
|
||||
Since local pids will never be larger than PID_MAX_LIMIT (which is
|
||||
currently defined as <= 4 million), but pid_t is an unsigned int, we
|
||||
should have plenty of room to represent remote pids with negative
|
||||
numbers if we assume that remote pid numbers are similarly limited.
|
||||
|
||||
If this is not the case, then we run the risk of having a remote pid
|
||||
returned for which there is also a corresponding local pid. This is a
|
||||
problem we have now, but this patch should reduce the chances of that
|
||||
occurring, while also returning those remote pid numbers, for whatever
|
||||
that may be worth.
|
||||
|
||||
Signed-off-by: Benjamin Coddington <bcodding@redhat.com>
|
||||
Signed-off-by: Jeff Layton <jlayton@redhat.com>
|
||||
---
|
||||
drivers/staging/lustre/lustre/ldlm/ldlm_flock.c | 2 +-
|
||||
fs/9p/vfs_file.c | 2 +-
|
||||
fs/ceph/locks.c | 2 +-
|
||||
fs/cifs/cifssmb.c | 2 +-
|
||||
fs/dlm/plock.c | 2 +-
|
||||
fs/fuse/file.c | 6 +--
|
||||
fs/locks.c | 62 +++++++++++++++----------
|
||||
include/linux/fs.h | 1 -
|
||||
8 files changed, 45 insertions(+), 34 deletions(-)
|
||||
|
||||
diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_flock.c b/drivers/staging/lustre/lustre/ldlm/ldlm_flock.c
|
||||
index b7f28b39c7b3..abcbf075acc0 100644
|
||||
--- a/drivers/staging/lustre/lustre/ldlm/ldlm_flock.c
|
||||
+++ b/drivers/staging/lustre/lustre/ldlm/ldlm_flock.c
|
||||
@@ -596,7 +596,7 @@ ldlm_flock_completion_ast(struct ldlm_lock *lock, __u64 flags, void *data)
|
||||
default:
|
||||
getlk->fl_type = F_UNLCK;
|
||||
}
|
||||
- getlk->fl_pid = (pid_t)lock->l_policy_data.l_flock.pid;
|
||||
+ getlk->fl_pid = -(pid_t)lock->l_policy_data.l_flock.pid;
|
||||
getlk->fl_start = (loff_t)lock->l_policy_data.l_flock.start;
|
||||
getlk->fl_end = (loff_t)lock->l_policy_data.l_flock.end;
|
||||
} else {
|
||||
diff --git a/fs/9p/vfs_file.c b/fs/9p/vfs_file.c
|
||||
index 3de3b4a89d89..43c242e17132 100644
|
||||
--- a/fs/9p/vfs_file.c
|
||||
+++ b/fs/9p/vfs_file.c
|
||||
@@ -288,7 +288,7 @@ static int v9fs_file_getlock(struct file *filp, struct file_lock *fl)
|
||||
fl->fl_end = OFFSET_MAX;
|
||||
else
|
||||
fl->fl_end = glock.start + glock.length - 1;
|
||||
- fl->fl_pid = glock.proc_id;
|
||||
+ fl->fl_pid = -glock.proc_id;
|
||||
}
|
||||
kfree(glock.client_id);
|
||||
return res;
|
||||
diff --git a/fs/ceph/locks.c b/fs/ceph/locks.c
|
||||
index 64ae74472046..8cd63e8123d8 100644
|
||||
--- a/fs/ceph/locks.c
|
||||
+++ b/fs/ceph/locks.c
|
||||
@@ -79,7 +79,7 @@ static int ceph_lock_message(u8 lock_type, u16 operation, struct file *file,
|
||||
err = ceph_mdsc_do_request(mdsc, inode, req);
|
||||
|
||||
if (operation == CEPH_MDS_OP_GETFILELOCK) {
|
||||
- fl->fl_pid = le64_to_cpu(req->r_reply_info.filelock_reply->pid);
|
||||
+ fl->fl_pid = -le64_to_cpu(req->r_reply_info.filelock_reply->pid);
|
||||
if (CEPH_LOCK_SHARED == req->r_reply_info.filelock_reply->type)
|
||||
fl->fl_type = F_RDLCK;
|
||||
else if (CEPH_LOCK_EXCL == req->r_reply_info.filelock_reply->type)
|
||||
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
|
||||
index 72a53bd19865..118a63e7e221 100644
|
||||
--- a/fs/cifs/cifssmb.c
|
||||
+++ b/fs/cifs/cifssmb.c
|
||||
@@ -2522,7 +2522,7 @@ CIFSSMBPosixLock(const unsigned int xid, struct cifs_tcon *tcon,
|
||||
pLockData->fl_start = le64_to_cpu(parm_data->start);
|
||||
pLockData->fl_end = pLockData->fl_start +
|
||||
le64_to_cpu(parm_data->length) - 1;
|
||||
- pLockData->fl_pid = le32_to_cpu(parm_data->pid);
|
||||
+ pLockData->fl_pid = -le32_to_cpu(parm_data->pid);
|
||||
}
|
||||
}
|
||||
|
||||
diff --git a/fs/dlm/plock.c b/fs/dlm/plock.c
|
||||
index d401425f602a..e631b1689228 100644
|
||||
--- a/fs/dlm/plock.c
|
||||
+++ b/fs/dlm/plock.c
|
||||
@@ -367,7 +367,7 @@ int dlm_posix_get(dlm_lockspace_t *lockspace, u64 number, struct file *file,
|
||||
locks_init_lock(fl);
|
||||
fl->fl_type = (op->info.ex) ? F_WRLCK : F_RDLCK;
|
||||
fl->fl_flags = FL_POSIX;
|
||||
- fl->fl_pid = op->info.pid;
|
||||
+ fl->fl_pid = -op->info.pid;
|
||||
fl->fl_start = op->info.start;
|
||||
fl->fl_end = op->info.end;
|
||||
rv = 0;
|
||||
diff --git a/fs/fuse/file.c b/fs/fuse/file.c
|
||||
index 3ee4fdc3da9e..7cd692f51d1d 100644
|
||||
--- a/fs/fuse/file.c
|
||||
+++ b/fs/fuse/file.c
|
||||
@@ -2101,11 +2101,11 @@ static int convert_fuse_file_lock(struct fuse_conn *fc,
|
||||
fl->fl_end = ffl->end;
|
||||
|
||||
/*
|
||||
- * Convert pid into the caller's pid namespace. If the pid
|
||||
- * does not map into the namespace fl_pid will get set to 0.
|
||||
+ * Convert pid into init's pid namespace. The locks API will
|
||||
+ * translate it into the caller's pid namespace.
|
||||
*/
|
||||
rcu_read_lock();
|
||||
- fl->fl_pid = pid_vnr(find_pid_ns(ffl->pid, fc->pid_ns));
|
||||
+ fl->fl_pid = pid_nr_ns(find_pid_ns(ffl->pid, fc->pid_ns), &init_pid_ns);
|
||||
rcu_read_unlock();
|
||||
break;
|
||||
|
||||
diff --git a/fs/locks.c b/fs/locks.c
|
||||
index d7daa6c8932f..6d0949880ebd 100644
|
||||
--- a/fs/locks.c
|
||||
+++ b/fs/locks.c
|
||||
@@ -137,6 +137,7 @@
|
||||
#define IS_FLOCK(fl) (fl->fl_flags & FL_FLOCK)
|
||||
#define IS_LEASE(fl) (fl->fl_flags & (FL_LEASE|FL_DELEG|FL_LAYOUT))
|
||||
#define IS_OFDLCK(fl) (fl->fl_flags & FL_OFDLCK)
|
||||
+#define IS_REMOTELCK(fl) (fl->fl_pid <= 0)
|
||||
|
||||
static inline bool is_remote_lock(struct file *filp)
|
||||
{
|
||||
@@ -733,7 +734,6 @@ static void locks_wake_up_blocks(struct file_lock *blocker)
|
||||
static void
|
||||
locks_insert_lock_ctx(struct file_lock *fl, struct list_head *before)
|
||||
{
|
||||
- fl->fl_nspid = get_pid(task_tgid(current));
|
||||
list_add_tail(&fl->fl_list, before);
|
||||
locks_insert_global_locks(fl);
|
||||
}
|
||||
@@ -743,10 +743,6 @@ locks_unlink_lock_ctx(struct file_lock *fl)
|
||||
{
|
||||
locks_delete_global_locks(fl);
|
||||
list_del_init(&fl->fl_list);
|
||||
- if (fl->fl_nspid) {
|
||||
- put_pid(fl->fl_nspid);
|
||||
- fl->fl_nspid = NULL;
|
||||
- }
|
||||
locks_wake_up_blocks(fl);
|
||||
}
|
||||
|
||||
@@ -823,8 +819,6 @@ posix_test_lock(struct file *filp, struct file_lock *fl)
|
||||
list_for_each_entry(cfl, &ctx->flc_posix, fl_list) {
|
||||
if (posix_locks_conflict(fl, cfl)) {
|
||||
locks_copy_conflock(fl, cfl);
|
||||
- if (cfl->fl_nspid)
|
||||
- fl->fl_pid = pid_vnr(cfl->fl_nspid);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
@@ -2048,9 +2042,33 @@ int vfs_test_lock(struct file *filp, struct file_lock *fl)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(vfs_test_lock);
|
||||
|
||||
+/**
|
||||
+ * locks_translate_pid - translate a file_lock's fl_pid number into a namespace
|
||||
+ * @fl: The file_lock who's fl_pid should be translated
|
||||
+ * @ns: The namespace into which the pid should be translated
|
||||
+ *
|
||||
+ * Used to tranlate a fl_pid into a namespace virtual pid number
|
||||
+ */
|
||||
+static pid_t locks_translate_pid(struct file_lock *fl, struct pid_namespace *ns)
|
||||
+{
|
||||
+ pid_t vnr;
|
||||
+ struct pid *pid;
|
||||
+
|
||||
+ if (IS_OFDLCK(fl))
|
||||
+ return -1;
|
||||
+ if (IS_REMOTELCK(fl))
|
||||
+ return fl->fl_pid;
|
||||
+
|
||||
+ rcu_read_lock();
|
||||
+ pid = find_pid_ns(fl->fl_pid, &init_pid_ns);
|
||||
+ vnr = pid_nr_ns(pid, ns);
|
||||
+ rcu_read_unlock();
|
||||
+ return vnr;
|
||||
+}
|
||||
+
|
||||
static int posix_lock_to_flock(struct flock *flock, struct file_lock *fl)
|
||||
{
|
||||
- flock->l_pid = IS_OFDLCK(fl) ? -1 : fl->fl_pid;
|
||||
+ flock->l_pid = locks_translate_pid(fl, task_active_pid_ns(current));
|
||||
#if BITS_PER_LONG == 32
|
||||
/*
|
||||
* Make sure we can represent the posix lock via
|
||||
@@ -2072,7 +2090,7 @@ static int posix_lock_to_flock(struct flock *flock, struct file_lock *fl)
|
||||
#if BITS_PER_LONG == 32
|
||||
static void posix_lock_to_flock64(struct flock64 *flock, struct file_lock *fl)
|
||||
{
|
||||
- flock->l_pid = IS_OFDLCK(fl) ? -1 : fl->fl_pid;
|
||||
+ flock->l_pid = locks_translate_pid(fl, task_active_pid_ns(current));
|
||||
flock->l_start = fl->fl_start;
|
||||
flock->l_len = fl->fl_end == OFFSET_MAX ? 0 :
|
||||
fl->fl_end - fl->fl_start + 1;
|
||||
@@ -2584,22 +2602,16 @@ static void lock_get_status(struct seq_file *f, struct file_lock *fl,
|
||||
{
|
||||
struct inode *inode = NULL;
|
||||
unsigned int fl_pid;
|
||||
+ struct pid_namespace *proc_pidns = file_inode(f->file)->i_sb->s_fs_info;
|
||||
|
||||
- if (fl->fl_nspid) {
|
||||
- struct pid_namespace *proc_pidns = file_inode(f->file)->i_sb->s_fs_info;
|
||||
-
|
||||
- /* Don't let fl_pid change based on who is reading the file */
|
||||
- fl_pid = pid_nr_ns(fl->fl_nspid, proc_pidns);
|
||||
-
|
||||
- /*
|
||||
- * If there isn't a fl_pid don't display who is waiting on
|
||||
- * the lock if we are called from locks_show, or if we are
|
||||
- * called from __show_fd_info - skip lock entirely
|
||||
- */
|
||||
- if (fl_pid == 0)
|
||||
- return;
|
||||
- } else
|
||||
- fl_pid = fl->fl_pid;
|
||||
+ fl_pid = locks_translate_pid(fl, proc_pidns);
|
||||
+ /*
|
||||
+ * If there isn't a fl_pid don't display who is waiting on
|
||||
+ * the lock if we are called from locks_show, or if we are
|
||||
+ * called from __show_fd_info - skip lock entirely
|
||||
+ */
|
||||
+ if (fl_pid == 0)
|
||||
+ return;
|
||||
|
||||
if (fl->fl_file != NULL)
|
||||
inode = locks_inode(fl->fl_file);
|
||||
@@ -2674,7 +2686,7 @@ static int locks_show(struct seq_file *f, void *v)
|
||||
|
||||
fl = hlist_entry(v, struct file_lock, fl_link);
|
||||
|
||||
- if (fl->fl_nspid && !pid_nr_ns(fl->fl_nspid, proc_pidns))
|
||||
+ if (locks_translate_pid(fl, proc_pidns) == 0)
|
||||
return 0;
|
||||
|
||||
lock_get_status(f, fl, iter->li_pos, "");
|
||||
diff --git a/include/linux/fs.h b/include/linux/fs.h
|
||||
index 7b5d6816542b..f0b108af9b02 100644
|
||||
--- a/include/linux/fs.h
|
||||
+++ b/include/linux/fs.h
|
||||
@@ -999,7 +999,6 @@ struct file_lock {
|
||||
unsigned char fl_type;
|
||||
unsigned int fl_pid;
|
||||
int fl_link_cpu; /* what cpu's list is this on? */
|
||||
- struct pid *fl_nspid;
|
||||
wait_queue_head_t fl_wait;
|
||||
struct file *fl_file;
|
||||
loff_t fl_start;
|
||||
--
|
||||
2.14.1
|
||||
|
|
@ -1,108 +0,0 @@
|
|||
From a8f97366452ed491d13cf1e44241bc0b5740b1f0 Mon Sep 17 00:00:00 2001
|
||||
From: "Kirill A. Shutemov" <kirill.shutemov@linux.intel.com>
|
||||
Date: Mon, 27 Nov 2017 06:21:25 +0300
|
||||
Subject: [PATCH] mm, thp: Do not make page table dirty unconditionally in
|
||||
touch_p[mu]d()
|
||||
|
||||
Currently, we unconditionally make page table dirty in touch_pmd().
|
||||
It may result in false-positive can_follow_write_pmd().
|
||||
|
||||
We may avoid the situation, if we would only make the page table entry
|
||||
dirty if caller asks for write access -- FOLL_WRITE.
|
||||
|
||||
The patch also changes touch_pud() in the same way.
|
||||
|
||||
Signed-off-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com>
|
||||
Cc: Michal Hocko <mhocko@suse.com>
|
||||
Cc: Hugh Dickins <hughd@google.com>
|
||||
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
|
||||
---
|
||||
mm/huge_memory.c | 36 +++++++++++++-----------------------
|
||||
1 file changed, 13 insertions(+), 23 deletions(-)
|
||||
|
||||
diff --git a/mm/huge_memory.c b/mm/huge_memory.c
|
||||
index 86fe697e8bfb..0e7ded98d114 100644
|
||||
--- a/mm/huge_memory.c
|
||||
+++ b/mm/huge_memory.c
|
||||
@@ -842,20 +842,15 @@ EXPORT_SYMBOL_GPL(vmf_insert_pfn_pud);
|
||||
#endif /* CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD */
|
||||
|
||||
static void touch_pmd(struct vm_area_struct *vma, unsigned long addr,
|
||||
- pmd_t *pmd)
|
||||
+ pmd_t *pmd, int flags)
|
||||
{
|
||||
pmd_t _pmd;
|
||||
|
||||
- /*
|
||||
- * We should set the dirty bit only for FOLL_WRITE but for now
|
||||
- * the dirty bit in the pmd is meaningless. And if the dirty
|
||||
- * bit will become meaningful and we'll only set it with
|
||||
- * FOLL_WRITE, an atomic set_bit will be required on the pmd to
|
||||
- * set the young bit, instead of the current set_pmd_at.
|
||||
- */
|
||||
- _pmd = pmd_mkyoung(pmd_mkdirty(*pmd));
|
||||
+ _pmd = pmd_mkyoung(*pmd);
|
||||
+ if (flags & FOLL_WRITE)
|
||||
+ _pmd = pmd_mkdirty(_pmd);
|
||||
if (pmdp_set_access_flags(vma, addr & HPAGE_PMD_MASK,
|
||||
- pmd, _pmd, 1))
|
||||
+ pmd, _pmd, flags & FOLL_WRITE))
|
||||
update_mmu_cache_pmd(vma, addr, pmd);
|
||||
}
|
||||
|
||||
@@ -884,7 +879,7 @@ struct page *follow_devmap_pmd(struct vm_area_struct *vma, unsigned long addr,
|
||||
return NULL;
|
||||
|
||||
if (flags & FOLL_TOUCH)
|
||||
- touch_pmd(vma, addr, pmd);
|
||||
+ touch_pmd(vma, addr, pmd, flags);
|
||||
|
||||
/*
|
||||
* device mapped pages can only be returned if the
|
||||
@@ -995,20 +990,15 @@ int copy_huge_pmd(struct mm_struct *dst_mm, struct mm_struct *src_mm,
|
||||
|
||||
#ifdef CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD
|
||||
static void touch_pud(struct vm_area_struct *vma, unsigned long addr,
|
||||
- pud_t *pud)
|
||||
+ pud_t *pud, int flags)
|
||||
{
|
||||
pud_t _pud;
|
||||
|
||||
- /*
|
||||
- * We should set the dirty bit only for FOLL_WRITE but for now
|
||||
- * the dirty bit in the pud is meaningless. And if the dirty
|
||||
- * bit will become meaningful and we'll only set it with
|
||||
- * FOLL_WRITE, an atomic set_bit will be required on the pud to
|
||||
- * set the young bit, instead of the current set_pud_at.
|
||||
- */
|
||||
- _pud = pud_mkyoung(pud_mkdirty(*pud));
|
||||
+ _pud = pud_mkyoung(*pud);
|
||||
+ if (flags & FOLL_WRITE)
|
||||
+ _pud = pud_mkdirty(_pud);
|
||||
if (pudp_set_access_flags(vma, addr & HPAGE_PUD_MASK,
|
||||
- pud, _pud, 1))
|
||||
+ pud, _pud, flags & FOLL_WRITE))
|
||||
update_mmu_cache_pud(vma, addr, pud);
|
||||
}
|
||||
|
||||
@@ -1031,7 +1021,7 @@ struct page *follow_devmap_pud(struct vm_area_struct *vma, unsigned long addr,
|
||||
return NULL;
|
||||
|
||||
if (flags & FOLL_TOUCH)
|
||||
- touch_pud(vma, addr, pud);
|
||||
+ touch_pud(vma, addr, pud, flags);
|
||||
|
||||
/*
|
||||
* device mapped pages can only be returned if the
|
||||
@@ -1424,7 +1414,7 @@ struct page *follow_trans_huge_pmd(struct vm_area_struct *vma,
|
||||
page = pmd_page(*pmd);
|
||||
VM_BUG_ON_PAGE(!PageHead(page) && !is_zone_device_page(page), page);
|
||||
if (flags & FOLL_TOUCH)
|
||||
- touch_pmd(vma, addr, pmd);
|
||||
+ touch_pmd(vma, addr, pmd, flags);
|
||||
if ((flags & FOLL_MLOCK) && (vma->vm_flags & VM_LOCKED)) {
|
||||
/*
|
||||
* We don't mlock() pte-mapped THPs. This way we can avoid
|
||||
--
|
||||
2.14.3
|
||||
|
|
@ -1,339 +0,0 @@
|
|||
From 3bbfe49a1d965b951527cde0da48f5d7677db264 Mon Sep 17 00:00:00 2001
|
||||
From: Hans de Goede <hdegoede@redhat.com>
|
||||
Date: Sun, 21 May 2017 13:15:11 +0200
|
||||
Subject: [PATCH 01/16] platform/x86: Add driver for ACPI INT0002 Virtual GPIO
|
||||
device
|
||||
|
||||
Some peripherals on Bay Trail and Cherry Trail platforms signal a
|
||||
Power Management Event (PME) to the Power Management Controller (PMC)
|
||||
to wakeup the system. When this happens software needs to explicitly
|
||||
clear the PME bus 0 status bit in the GPE0a_STS register to avoid an
|
||||
IRQ storm on IRQ 9.
|
||||
|
||||
This is modelled in ACPI through the INT0002 ACPI device, which is
|
||||
called a "Virtual GPIO controller" in ACPI because it defines the
|
||||
event handler to call when the PME triggers through _AEI and _L02
|
||||
methods as would be done for a real GPIO interrupt in ACPI.
|
||||
|
||||
This commit adds a driver which registers the Virtual GPIOs expected
|
||||
by the DSDT on these devices, letting gpiolib-acpi claim the
|
||||
virtual GPIO and install a GPIO-interrupt handler which call the _L02
|
||||
handler as it would for a real GPIO controller.
|
||||
|
||||
Cc: joeyli <jlee@suse.com>
|
||||
Cc: Takashi Iwai <tiwai@suse.de>
|
||||
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
|
||||
Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
|
||||
Acked-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
|
||||
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
|
||||
---
|
||||
Changes in v2:
|
||||
-Remove dev_err after malloc failure
|
||||
-Remove unused empty runtime pm callbacks
|
||||
-s/GPE0A_PME_/GPE0A_PME_B0_/
|
||||
-Fixed some checkpatch warnings (I forgot to run checkpatch on v1)
|
||||
|
||||
Changes in v3:
|
||||
-Rewrite as gpiochip driver letting gpiolib-acpi deal with claiming the pin
|
||||
0x0002 and calling the _L02 event handler when the virtual gpio-irq triggers
|
||||
-Rebase on 4.12-rc1
|
||||
|
||||
Changes in v4:
|
||||
-Drop device_init_wakeup() from _probe(), use pm_system_wakeup() instead
|
||||
of pm_wakeup_hard_event(chip->parent)
|
||||
-Improve commit message
|
||||
|
||||
Changes in v5:
|
||||
-Use BIT() macro for FOO_BIT defines
|
||||
-Drop unneeded ACPI_PTR macro usage
|
||||
|
||||
Changes in v6:
|
||||
-Move back to drivers/platform/x86
|
||||
-Expand certain acronyms (PME, PMC)
|
||||
-Use linux/gpio/driver.h include instead of linux/gpio.h
|
||||
-Document why the get / set / direction_output functions are dummys
|
||||
-No functional changes
|
||||
|
||||
Changes in v7:
|
||||
-Some minor cleanups from Andy:
|
||||
-Move asm/ includes below linux/ includes
|
||||
-s/APCI/ACPI/
|
||||
-Use bitmap_clear on chip->irq_valid_mask
|
||||
-Add Linus Walleij's Reviewed-by
|
||||
---
|
||||
drivers/platform/x86/Kconfig | 19 +++
|
||||
drivers/platform/x86/Makefile | 1 +
|
||||
drivers/platform/x86/intel_int0002_vgpio.c | 219 +++++++++++++++++++++++++++++
|
||||
3 files changed, 239 insertions(+)
|
||||
create mode 100644 drivers/platform/x86/intel_int0002_vgpio.c
|
||||
|
||||
diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig
|
||||
index 8489020ecf44..a3ccc3c795a5 100644
|
||||
--- a/drivers/platform/x86/Kconfig
|
||||
+++ b/drivers/platform/x86/Kconfig
|
||||
@@ -794,6 +794,25 @@ config INTEL_CHT_INT33FE
|
||||
This driver instantiates i2c-clients for these, so that standard
|
||||
i2c drivers for these chips can bind to the them.
|
||||
|
||||
+config INTEL_INT0002_VGPIO
|
||||
+ tristate "Intel ACPI INT0002 Virtual GPIO driver"
|
||||
+ depends on GPIOLIB && ACPI
|
||||
+ select GPIOLIB_IRQCHIP
|
||||
+ ---help---
|
||||
+ Some peripherals on Bay Trail and Cherry Trail platforms signal a
|
||||
+ Power Management Event (PME) to the Power Management Controller (PMC)
|
||||
+ to wakeup the system. When this happens software needs to explicitly
|
||||
+ clear the PME bus 0 status bit in the GPE0a_STS register to avoid an
|
||||
+ IRQ storm on IRQ 9.
|
||||
+
|
||||
+ This is modelled in ACPI through the INT0002 ACPI device, which is
|
||||
+ called a "Virtual GPIO controller" in ACPI because it defines the
|
||||
+ event handler to call when the PME triggers through _AEI and _L02
|
||||
+ methods as would be done for a real GPIO interrupt in ACPI.
|
||||
+
|
||||
+ To compile this driver as a module, choose M here: the module will
|
||||
+ be called intel_int0002_vgpio.
|
||||
+
|
||||
config INTEL_HID_EVENT
|
||||
tristate "INTEL HID Event"
|
||||
depends on ACPI
|
||||
diff --git a/drivers/platform/x86/Makefile b/drivers/platform/x86/Makefile
|
||||
index 182a3ed6605a..ab22ce77fb66 100644
|
||||
--- a/drivers/platform/x86/Makefile
|
||||
+++ b/drivers/platform/x86/Makefile
|
||||
@@ -46,6 +46,7 @@ obj-$(CONFIG_TOSHIBA_BT_RFKILL) += toshiba_bluetooth.o
|
||||
obj-$(CONFIG_TOSHIBA_HAPS) += toshiba_haps.o
|
||||
obj-$(CONFIG_TOSHIBA_WMI) += toshiba-wmi.o
|
||||
obj-$(CONFIG_INTEL_CHT_INT33FE) += intel_cht_int33fe.o
|
||||
+obj-$(CONFIG_INTEL_INT0002_VGPIO) += intel_int0002_vgpio.o
|
||||
obj-$(CONFIG_INTEL_HID_EVENT) += intel-hid.o
|
||||
obj-$(CONFIG_INTEL_VBTN) += intel-vbtn.o
|
||||
obj-$(CONFIG_INTEL_SCU_IPC) += intel_scu_ipc.o
|
||||
diff --git a/drivers/platform/x86/intel_int0002_vgpio.c b/drivers/platform/x86/intel_int0002_vgpio.c
|
||||
new file mode 100644
|
||||
index 000000000000..92dc230ef5b2
|
||||
--- /dev/null
|
||||
+++ b/drivers/platform/x86/intel_int0002_vgpio.c
|
||||
@@ -0,0 +1,219 @@
|
||||
+/*
|
||||
+ * Intel INT0002 "Virtual GPIO" driver
|
||||
+ *
|
||||
+ * Copyright (C) 2017 Hans de Goede <hdegoede@redhat.com>
|
||||
+ *
|
||||
+ * Loosely based on android x86 kernel code which is:
|
||||
+ *
|
||||
+ * Copyright (c) 2014, Intel Corporation.
|
||||
+ *
|
||||
+ * Author: Dyut Kumar Sil <dyut.k.sil@intel.com>
|
||||
+ *
|
||||
+ * This program is free software; you can redistribute it and/or modify
|
||||
+ * it under the terms of the GNU General Public License version 2 as
|
||||
+ * published by the Free Software Foundation.
|
||||
+ *
|
||||
+ * Some peripherals on Bay Trail and Cherry Trail platforms signal a Power
|
||||
+ * Management Event (PME) to the Power Management Controller (PMC) to wakeup
|
||||
+ * the system. When this happens software needs to clear the PME bus 0 status
|
||||
+ * bit in the GPE0a_STS register to avoid an IRQ storm on IRQ 9.
|
||||
+ *
|
||||
+ * This is modelled in ACPI through the INT0002 ACPI device, which is
|
||||
+ * called a "Virtual GPIO controller" in ACPI because it defines the event
|
||||
+ * handler to call when the PME triggers through _AEI and _L02 / _E02
|
||||
+ * methods as would be done for a real GPIO interrupt in ACPI. Note this
|
||||
+ * is a hack to define an AML event handler for the PME while using existing
|
||||
+ * ACPI mechanisms, this is not a real GPIO at all.
|
||||
+ *
|
||||
+ * This driver will bind to the INT0002 device, and register as a GPIO
|
||||
+ * controller, letting gpiolib-acpi.c call the _L02 handler as it would
|
||||
+ * for a real GPIO controller.
|
||||
+ */
|
||||
+
|
||||
+#include <linux/acpi.h>
|
||||
+#include <linux/bitmap.h>
|
||||
+#include <linux/gpio/driver.h>
|
||||
+#include <linux/interrupt.h>
|
||||
+#include <linux/io.h>
|
||||
+#include <linux/kernel.h>
|
||||
+#include <linux/module.h>
|
||||
+#include <linux/platform_device.h>
|
||||
+#include <linux/slab.h>
|
||||
+#include <linux/suspend.h>
|
||||
+
|
||||
+#include <asm/cpu_device_id.h>
|
||||
+#include <asm/intel-family.h>
|
||||
+
|
||||
+#define DRV_NAME "INT0002 Virtual GPIO"
|
||||
+
|
||||
+/* For some reason the virtual GPIO pin tied to the GPE is numbered pin 2 */
|
||||
+#define GPE0A_PME_B0_VIRT_GPIO_PIN 2
|
||||
+
|
||||
+#define GPE0A_PME_B0_STS_BIT BIT(13)
|
||||
+#define GPE0A_PME_B0_EN_BIT BIT(13)
|
||||
+#define GPE0A_STS_PORT 0x420
|
||||
+#define GPE0A_EN_PORT 0x428
|
||||
+
|
||||
+#define ICPU(model) { X86_VENDOR_INTEL, 6, model, X86_FEATURE_ANY, }
|
||||
+
|
||||
+static const struct x86_cpu_id int0002_cpu_ids[] = {
|
||||
+/*
|
||||
+ * Limit ourselves to Cherry Trail for now, until testing shows we
|
||||
+ * need to handle the INT0002 device on Baytrail too.
|
||||
+ * ICPU(INTEL_FAM6_ATOM_SILVERMONT1), * Valleyview, Bay Trail *
|
||||
+ */
|
||||
+ ICPU(INTEL_FAM6_ATOM_AIRMONT), /* Braswell, Cherry Trail */
|
||||
+ {}
|
||||
+};
|
||||
+
|
||||
+/*
|
||||
+ * As this is not a real GPIO at all, but just a hack to model an event in
|
||||
+ * ACPI the get / set functions are dummy functions.
|
||||
+ */
|
||||
+
|
||||
+static int int0002_gpio_get(struct gpio_chip *chip, unsigned int offset)
|
||||
+{
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static void int0002_gpio_set(struct gpio_chip *chip, unsigned int offset,
|
||||
+ int value)
|
||||
+{
|
||||
+}
|
||||
+
|
||||
+static int int0002_gpio_direction_output(struct gpio_chip *chip,
|
||||
+ unsigned int offset, int value)
|
||||
+{
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static void int0002_irq_ack(struct irq_data *data)
|
||||
+{
|
||||
+ outl(GPE0A_PME_B0_STS_BIT, GPE0A_STS_PORT);
|
||||
+}
|
||||
+
|
||||
+static void int0002_irq_unmask(struct irq_data *data)
|
||||
+{
|
||||
+ u32 gpe_en_reg;
|
||||
+
|
||||
+ gpe_en_reg = inl(GPE0A_EN_PORT);
|
||||
+ gpe_en_reg |= GPE0A_PME_B0_EN_BIT;
|
||||
+ outl(gpe_en_reg, GPE0A_EN_PORT);
|
||||
+}
|
||||
+
|
||||
+static void int0002_irq_mask(struct irq_data *data)
|
||||
+{
|
||||
+ u32 gpe_en_reg;
|
||||
+
|
||||
+ gpe_en_reg = inl(GPE0A_EN_PORT);
|
||||
+ gpe_en_reg &= ~GPE0A_PME_B0_EN_BIT;
|
||||
+ outl(gpe_en_reg, GPE0A_EN_PORT);
|
||||
+}
|
||||
+
|
||||
+static irqreturn_t int0002_irq(int irq, void *data)
|
||||
+{
|
||||
+ struct gpio_chip *chip = data;
|
||||
+ u32 gpe_sts_reg;
|
||||
+
|
||||
+ gpe_sts_reg = inl(GPE0A_STS_PORT);
|
||||
+ if (!(gpe_sts_reg & GPE0A_PME_B0_STS_BIT))
|
||||
+ return IRQ_NONE;
|
||||
+
|
||||
+ generic_handle_irq(irq_find_mapping(chip->irqdomain,
|
||||
+ GPE0A_PME_B0_VIRT_GPIO_PIN));
|
||||
+
|
||||
+ pm_system_wakeup();
|
||||
+
|
||||
+ return IRQ_HANDLED;
|
||||
+}
|
||||
+
|
||||
+static struct irq_chip int0002_irqchip = {
|
||||
+ .name = DRV_NAME,
|
||||
+ .irq_ack = int0002_irq_ack,
|
||||
+ .irq_mask = int0002_irq_mask,
|
||||
+ .irq_unmask = int0002_irq_unmask,
|
||||
+};
|
||||
+
|
||||
+static int int0002_probe(struct platform_device *pdev)
|
||||
+{
|
||||
+ struct device *dev = &pdev->dev;
|
||||
+ const struct x86_cpu_id *cpu_id;
|
||||
+ struct gpio_chip *chip;
|
||||
+ int irq, ret;
|
||||
+
|
||||
+ /* Menlow has a different INT0002 device? <sigh> */
|
||||
+ cpu_id = x86_match_cpu(int0002_cpu_ids);
|
||||
+ if (!cpu_id)
|
||||
+ return -ENODEV;
|
||||
+
|
||||
+ irq = platform_get_irq(pdev, 0);
|
||||
+ if (irq < 0) {
|
||||
+ dev_err(dev, "Error getting IRQ: %d\n", irq);
|
||||
+ return irq;
|
||||
+ }
|
||||
+
|
||||
+ chip = devm_kzalloc(dev, sizeof(*chip), GFP_KERNEL);
|
||||
+ if (!chip)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ chip->label = DRV_NAME;
|
||||
+ chip->parent = dev;
|
||||
+ chip->owner = THIS_MODULE;
|
||||
+ chip->get = int0002_gpio_get;
|
||||
+ chip->set = int0002_gpio_set;
|
||||
+ chip->direction_input = int0002_gpio_get;
|
||||
+ chip->direction_output = int0002_gpio_direction_output;
|
||||
+ chip->base = -1;
|
||||
+ chip->ngpio = GPE0A_PME_B0_VIRT_GPIO_PIN + 1;
|
||||
+ chip->irq_need_valid_mask = true;
|
||||
+
|
||||
+ ret = devm_gpiochip_add_data(&pdev->dev, chip, NULL);
|
||||
+ if (ret) {
|
||||
+ dev_err(dev, "Error adding gpio chip: %d\n", ret);
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ bitmap_clear(chip->irq_valid_mask, 0, GPE0A_PME_B0_VIRT_GPIO_PIN);
|
||||
+
|
||||
+ /*
|
||||
+ * We manually request the irq here instead of passing a flow-handler
|
||||
+ * to gpiochip_set_chained_irqchip, because the irq is shared.
|
||||
+ */
|
||||
+ ret = devm_request_irq(dev, irq, int0002_irq,
|
||||
+ IRQF_SHARED | IRQF_NO_THREAD, "INT0002", chip);
|
||||
+ if (ret) {
|
||||
+ dev_err(dev, "Error requesting IRQ %d: %d\n", irq, ret);
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ ret = gpiochip_irqchip_add(chip, &int0002_irqchip, 0, handle_edge_irq,
|
||||
+ IRQ_TYPE_NONE);
|
||||
+ if (ret) {
|
||||
+ dev_err(dev, "Error adding irqchip: %d\n", ret);
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ gpiochip_set_chained_irqchip(chip, &int0002_irqchip, irq, NULL);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static const struct acpi_device_id int0002_acpi_ids[] = {
|
||||
+ { "INT0002", 0 },
|
||||
+ { },
|
||||
+};
|
||||
+MODULE_DEVICE_TABLE(acpi, int0002_acpi_ids);
|
||||
+
|
||||
+static struct platform_driver int0002_driver = {
|
||||
+ .driver = {
|
||||
+ .name = DRV_NAME,
|
||||
+ .acpi_match_table = int0002_acpi_ids,
|
||||
+ },
|
||||
+ .probe = int0002_probe,
|
||||
+};
|
||||
+
|
||||
+module_platform_driver(int0002_driver);
|
||||
+
|
||||
+MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
|
||||
+MODULE_DESCRIPTION("Intel INT0002 Virtual GPIO driver");
|
||||
+MODULE_LICENSE("GPL");
|
||||
--
|
||||
2.13.0
|
||||
|
|
@ -1,78 +0,0 @@
|
|||
From 075bb90dbb4d894938c5859e3850987238db9cd8 Mon Sep 17 00:00:00 2001
|
||||
From: Hans de Goede <hdegoede@redhat.com>
|
||||
Date: Fri, 11 Aug 2017 22:30:55 +0200
|
||||
Subject: [PATCH 1/2] power: supply: max17042_battery: Add support for ACPI
|
||||
enumeration
|
||||
|
||||
Some x86 devices enumerate a max17047 fuel-gauge through a MAX17047
|
||||
ACPI firmware-node, add support for this.
|
||||
|
||||
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
|
||||
---
|
||||
drivers/power/supply/max17042_battery.c | 22 +++++++++++++++++++++-
|
||||
1 file changed, 21 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/drivers/power/supply/max17042_battery.c b/drivers/power/supply/max17042_battery.c
|
||||
index aecaaa2b0586..b2ddb7eb69c6 100644
|
||||
--- a/drivers/power/supply/max17042_battery.c
|
||||
+++ b/drivers/power/supply/max17042_battery.c
|
||||
@@ -22,6 +22,7 @@
|
||||
* This driver is based on max17040_battery.c
|
||||
*/
|
||||
|
||||
+#include <linux/acpi.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/slab.h>
|
||||
@@ -982,6 +983,8 @@ static int max17042_probe(struct i2c_client *client,
|
||||
struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
|
||||
const struct power_supply_desc *max17042_desc = &max17042_psy_desc;
|
||||
struct power_supply_config psy_cfg = {};
|
||||
+ const struct acpi_device_id *acpi_id;
|
||||
+ struct device *dev = &client->dev;
|
||||
struct max17042_chip *chip;
|
||||
int ret;
|
||||
int i;
|
||||
@@ -995,7 +998,15 @@ static int max17042_probe(struct i2c_client *client,
|
||||
return -ENOMEM;
|
||||
|
||||
chip->client = client;
|
||||
- chip->chip_type = id->driver_data;
|
||||
+ if (id) {
|
||||
+ chip->chip_type = id->driver_data;
|
||||
+ } else {
|
||||
+ acpi_id = acpi_match_device(dev->driver->acpi_match_table, dev);
|
||||
+ if (!acpi_id)
|
||||
+ return -ENODEV;
|
||||
+
|
||||
+ chip->chip_type = acpi_id->driver_data;
|
||||
+ }
|
||||
chip->regmap = devm_regmap_init_i2c(client, &max17042_regmap_config);
|
||||
if (IS_ERR(chip->regmap)) {
|
||||
dev_err(&client->dev, "Failed to initialize regmap\n");
|
||||
@@ -1104,6 +1115,14 @@ static int max17042_resume(struct device *dev)
|
||||
static SIMPLE_DEV_PM_OPS(max17042_pm_ops, max17042_suspend,
|
||||
max17042_resume);
|
||||
|
||||
+#ifdef CONFIG_ACPI
|
||||
+static const struct acpi_device_id max17042_acpi_match[] = {
|
||||
+ { "MAX17047", MAXIM_DEVICE_TYPE_MAX17047 },
|
||||
+ { }
|
||||
+};
|
||||
+MODULE_DEVICE_TABLE(acpi, max17042_acpi_match);
|
||||
+#endif
|
||||
+
|
||||
#ifdef CONFIG_OF
|
||||
static const struct of_device_id max17042_dt_match[] = {
|
||||
{ .compatible = "maxim,max17042" },
|
||||
@@ -1125,6 +1144,7 @@ MODULE_DEVICE_TABLE(i2c, max17042_id);
|
||||
static struct i2c_driver max17042_i2c_driver = {
|
||||
.driver = {
|
||||
.name = "max17042",
|
||||
+ .acpi_match_table = ACPI_PTR(max17042_acpi_match),
|
||||
.of_match_table = of_match_ptr(max17042_dt_match),
|
||||
.pm = &max17042_pm_ops,
|
||||
},
|
||||
--
|
||||
2.13.4
|
||||
|
|
@ -1,204 +0,0 @@
|
|||
From aca20afc84cf8578e044c67c4949672ac98f064a Mon Sep 17 00:00:00 2001
|
||||
From: Nicholas Piggin <npiggin@gmail.com>
|
||||
Date: Tue, 28 Nov 2017 11:26:54 +0100
|
||||
Subject: [PATCH 1/5] powerpc/64s/radix: Fix 128TB-512TB virtual address
|
||||
boundary case allocation
|
||||
|
||||
commit 85e3f1adcb9d49300b0a943bb93f9604be375bfb upstream.
|
||||
|
||||
Radix VA space allocations test addresses against mm->task_size which
|
||||
is 512TB, even in cases where the intention is to limit allocation to
|
||||
below 128TB.
|
||||
|
||||
This results in mmap with a hint address below 128TB but address +
|
||||
length above 128TB succeeding when it should fail (as hash does after
|
||||
the previous patch).
|
||||
|
||||
Set the high address limit to be considered up front, and base
|
||||
subsequent allocation checks on that consistently.
|
||||
|
||||
Fixes: f4ea6dcb08ea ("powerpc/mm: Enable mappings above 128TB")
|
||||
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
|
||||
Reviewed-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
|
||||
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
||||
---
|
||||
arch/powerpc/mm/hugetlbpage-radix.c | 26 ++++++++++++------
|
||||
arch/powerpc/mm/mmap.c | 55 ++++++++++++++++++++++---------------
|
||||
2 files changed, 50 insertions(+), 31 deletions(-)
|
||||
|
||||
diff --git a/arch/powerpc/mm/hugetlbpage-radix.c b/arch/powerpc/mm/hugetlbpage-radix.c
|
||||
index a12e86395025..0a3d71aae175 100644
|
||||
--- a/arch/powerpc/mm/hugetlbpage-radix.c
|
||||
+++ b/arch/powerpc/mm/hugetlbpage-radix.c
|
||||
@@ -48,17 +48,28 @@ radix__hugetlb_get_unmapped_area(struct file *file, unsigned long addr,
|
||||
struct mm_struct *mm = current->mm;
|
||||
struct vm_area_struct *vma;
|
||||
struct hstate *h = hstate_file(file);
|
||||
+ int fixed = (flags & MAP_FIXED);
|
||||
+ unsigned long high_limit;
|
||||
struct vm_unmapped_area_info info;
|
||||
|
||||
- if (unlikely(addr > mm->context.addr_limit && addr < TASK_SIZE))
|
||||
- mm->context.addr_limit = TASK_SIZE;
|
||||
+ high_limit = DEFAULT_MAP_WINDOW;
|
||||
+ if (addr >= high_limit || (fixed && (addr + len > high_limit)))
|
||||
+ high_limit = TASK_SIZE;
|
||||
|
||||
if (len & ~huge_page_mask(h))
|
||||
return -EINVAL;
|
||||
- if (len > mm->task_size)
|
||||
+ if (len > high_limit)
|
||||
return -ENOMEM;
|
||||
+ if (fixed) {
|
||||
+ if (addr > high_limit - len)
|
||||
+ return -ENOMEM;
|
||||
+ }
|
||||
|
||||
- if (flags & MAP_FIXED) {
|
||||
+ if (unlikely(addr > mm->context.addr_limit &&
|
||||
+ mm->context.addr_limit != TASK_SIZE))
|
||||
+ mm->context.addr_limit = TASK_SIZE;
|
||||
+
|
||||
+ if (fixed) {
|
||||
if (prepare_hugepage_range(file, addr, len))
|
||||
return -EINVAL;
|
||||
return addr;
|
||||
@@ -67,7 +78,7 @@ radix__hugetlb_get_unmapped_area(struct file *file, unsigned long addr,
|
||||
if (addr) {
|
||||
addr = ALIGN(addr, huge_page_size(h));
|
||||
vma = find_vma(mm, addr);
|
||||
- if (mm->task_size - len >= addr &&
|
||||
+ if (high_limit - len >= addr &&
|
||||
(!vma || addr + len <= vm_start_gap(vma)))
|
||||
return addr;
|
||||
}
|
||||
@@ -78,12 +89,9 @@ radix__hugetlb_get_unmapped_area(struct file *file, unsigned long addr,
|
||||
info.flags = VM_UNMAPPED_AREA_TOPDOWN;
|
||||
info.length = len;
|
||||
info.low_limit = PAGE_SIZE;
|
||||
- info.high_limit = current->mm->mmap_base;
|
||||
+ info.high_limit = mm->mmap_base + (high_limit - DEFAULT_MAP_WINDOW);
|
||||
info.align_mask = PAGE_MASK & ~huge_page_mask(h);
|
||||
info.align_offset = 0;
|
||||
|
||||
- if (addr > DEFAULT_MAP_WINDOW)
|
||||
- info.high_limit += mm->context.addr_limit - DEFAULT_MAP_WINDOW;
|
||||
-
|
||||
return vm_unmapped_area(&info);
|
||||
}
|
||||
diff --git a/arch/powerpc/mm/mmap.c b/arch/powerpc/mm/mmap.c
|
||||
index 5d78b193fec4..6d476a7b5611 100644
|
||||
--- a/arch/powerpc/mm/mmap.c
|
||||
+++ b/arch/powerpc/mm/mmap.c
|
||||
@@ -106,22 +106,32 @@ radix__arch_get_unmapped_area(struct file *filp, unsigned long addr,
|
||||
{
|
||||
struct mm_struct *mm = current->mm;
|
||||
struct vm_area_struct *vma;
|
||||
+ int fixed = (flags & MAP_FIXED);
|
||||
+ unsigned long high_limit;
|
||||
struct vm_unmapped_area_info info;
|
||||
|
||||
+ high_limit = DEFAULT_MAP_WINDOW;
|
||||
+ if (addr >= high_limit || (fixed && (addr + len > high_limit)))
|
||||
+ high_limit = TASK_SIZE;
|
||||
+
|
||||
+ if (len > high_limit)
|
||||
+ return -ENOMEM;
|
||||
+ if (fixed) {
|
||||
+ if (addr > high_limit - len)
|
||||
+ return -ENOMEM;
|
||||
+ }
|
||||
+
|
||||
if (unlikely(addr > mm->context.addr_limit &&
|
||||
mm->context.addr_limit != TASK_SIZE))
|
||||
mm->context.addr_limit = TASK_SIZE;
|
||||
|
||||
- if (len > mm->task_size - mmap_min_addr)
|
||||
- return -ENOMEM;
|
||||
-
|
||||
- if (flags & MAP_FIXED)
|
||||
+ if (fixed)
|
||||
return addr;
|
||||
|
||||
if (addr) {
|
||||
addr = PAGE_ALIGN(addr);
|
||||
vma = find_vma(mm, addr);
|
||||
- if (mm->task_size - len >= addr && addr >= mmap_min_addr &&
|
||||
+ if (high_limit - len >= addr && addr >= mmap_min_addr &&
|
||||
(!vma || addr + len <= vm_start_gap(vma)))
|
||||
return addr;
|
||||
}
|
||||
@@ -129,13 +139,9 @@ radix__arch_get_unmapped_area(struct file *filp, unsigned long addr,
|
||||
info.flags = 0;
|
||||
info.length = len;
|
||||
info.low_limit = mm->mmap_base;
|
||||
+ info.high_limit = high_limit;
|
||||
info.align_mask = 0;
|
||||
|
||||
- if (unlikely(addr > DEFAULT_MAP_WINDOW))
|
||||
- info.high_limit = mm->context.addr_limit;
|
||||
- else
|
||||
- info.high_limit = DEFAULT_MAP_WINDOW;
|
||||
-
|
||||
return vm_unmapped_area(&info);
|
||||
}
|
||||
|
||||
@@ -149,37 +155,42 @@ radix__arch_get_unmapped_area_topdown(struct file *filp,
|
||||
struct vm_area_struct *vma;
|
||||
struct mm_struct *mm = current->mm;
|
||||
unsigned long addr = addr0;
|
||||
+ int fixed = (flags & MAP_FIXED);
|
||||
+ unsigned long high_limit;
|
||||
struct vm_unmapped_area_info info;
|
||||
|
||||
+ high_limit = DEFAULT_MAP_WINDOW;
|
||||
+ if (addr >= high_limit || (fixed && (addr + len > high_limit)))
|
||||
+ high_limit = TASK_SIZE;
|
||||
+
|
||||
+ if (len > high_limit)
|
||||
+ return -ENOMEM;
|
||||
+ if (fixed) {
|
||||
+ if (addr > high_limit - len)
|
||||
+ return -ENOMEM;
|
||||
+ }
|
||||
+
|
||||
if (unlikely(addr > mm->context.addr_limit &&
|
||||
mm->context.addr_limit != TASK_SIZE))
|
||||
mm->context.addr_limit = TASK_SIZE;
|
||||
|
||||
- /* requested length too big for entire address space */
|
||||
- if (len > mm->task_size - mmap_min_addr)
|
||||
- return -ENOMEM;
|
||||
-
|
||||
- if (flags & MAP_FIXED)
|
||||
+ if (fixed)
|
||||
return addr;
|
||||
|
||||
- /* requesting a specific address */
|
||||
if (addr) {
|
||||
addr = PAGE_ALIGN(addr);
|
||||
vma = find_vma(mm, addr);
|
||||
- if (mm->task_size - len >= addr && addr >= mmap_min_addr &&
|
||||
- (!vma || addr + len <= vm_start_gap(vma)))
|
||||
+ if (high_limit - len >= addr && addr >= mmap_min_addr &&
|
||||
+ (!vma || addr + len <= vm_start_gap(vma)))
|
||||
return addr;
|
||||
}
|
||||
|
||||
info.flags = VM_UNMAPPED_AREA_TOPDOWN;
|
||||
info.length = len;
|
||||
info.low_limit = max(PAGE_SIZE, mmap_min_addr);
|
||||
- info.high_limit = mm->mmap_base;
|
||||
+ info.high_limit = mm->mmap_base + (high_limit - DEFAULT_MAP_WINDOW);
|
||||
info.align_mask = 0;
|
||||
|
||||
- if (addr > DEFAULT_MAP_WINDOW)
|
||||
- info.high_limit += mm->context.addr_limit - DEFAULT_MAP_WINDOW;
|
||||
-
|
||||
addr = vm_unmapped_area(&info);
|
||||
if (!(addr & ~PAGE_MASK))
|
||||
return addr;
|
||||
--
|
||||
2.14.3
|
||||
|
|
@ -1,355 +0,0 @@
|
|||
From c0f9254fdd0703ade018b2ff3a8cca433f781a11 Mon Sep 17 00:00:00 2001
|
||||
From: Hans de Goede <hdegoede@redhat.com>
|
||||
Date: Sun, 26 Feb 2017 21:07:29 +0100
|
||||
Subject: [PATCH 02/16] mfd: Add Cherry Trail Whiskey Cove PMIC driver
|
||||
|
||||
Add mfd driver for Intel CHT Whiskey Cove PMIC, based on various non
|
||||
upstreamed CHT Whiskey Cove PMIC patches.
|
||||
|
||||
This is a somewhat minimal version which adds irqchip support and cells
|
||||
for: ACPI PMIC opregion support, the i2c-controller driving the external
|
||||
charger irc and the pwrsrc/extcon block.
|
||||
|
||||
Further cells can be added in the future if/when drivers are upstreamed
|
||||
for them.
|
||||
|
||||
Cc: Bin Gao <bin.gao@intel.com>
|
||||
Cc: Felipe Balbi <felipe.balbi@linux.intel.com>
|
||||
Cc: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
|
||||
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
|
||||
Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
|
||||
---
|
||||
Changes in v2:
|
||||
-Since this uses plain mfd and not the intel_soc_pmic stuff give it
|
||||
its own Kconfig and allow this to be built as a module
|
||||
-Add missing #include <acpi/acpi_bus.h>
|
||||
|
||||
Changes in v3:
|
||||
-Drop #include <acpi/acpi_bus.h> again, not the right fix for the build errors
|
||||
-Error out when the upper byte of the register-address passed to the regmap
|
||||
functions is 0 rather then hardcoding an address in that case
|
||||
-Various minor style tweaks / cleanups
|
||||
-Move defines of regulator register addresses to intel_pmic_chtwc.c,
|
||||
it is the only place where they are used
|
||||
-Drop now empty include/linux/mfd/intel_chtwc.h
|
||||
-Rename intel_soc_pmic_chtwc.c to intel_cht_wc.c to match Kconfig option name
|
||||
-Add irqchip support
|
||||
-Add external charger cell
|
||||
-Add pwrsrc cell
|
||||
|
||||
Changes in v4:
|
||||
-Use PLATFORM_DEVID_NONE
|
||||
|
||||
Changes in v5:
|
||||
-Change Kconfig option from tristate to boolean and add a select for the
|
||||
i2c-bus driver, this is necessary because the chtwc PMIC provides an ACPI
|
||||
OPRegion handler, which must be available before other drivers using it
|
||||
are loaded, which can only be ensured if the mfd, opregion and i2c-bus
|
||||
drivers are built in. This fixes errors like these during boot:
|
||||
mmc0: SDHCI controller on ACPI [80860F14:00] using ADMA
|
||||
ACPI Error: No handler for Region [REGS] (ffff93543b0cc3a8) [UserDefinedRegion] (20170119/evregion-166)
|
||||
ACPI Error: Region UserDefinedRegion (ID=143) has no handler (20170119/exfldio-299)
|
||||
ACPI Error: Method parse/execution failed [\_SB.PCI0.I2C7.PMI5.GET] (Node ffff93543b0cde10), AE_NOT_EXIST (20170119/psparse-543)
|
||||
ACPI Error: Method parse/execution failed [\_SB.PCI0.SHC1._PS0] (Node ffff93543b0b5cd0), AE_NOT_EXIST (20170119/psparse-543)
|
||||
acpi 80860F14:02: Failed to change power state to D0
|
||||
-Some minor style and capitalization fixes from review by Lee Jones
|
||||
|
||||
Changes in v6:
|
||||
-Fix Kconfig depends and selects to fix warning reported by kbuild test robot
|
||||
|
||||
Changes in v7:
|
||||
-Add explanation why this is a bool and why it selects i2c-designwaree
|
||||
to the help text rather then as comments in the Kconfig
|
||||
|
||||
Changes in v8:
|
||||
-Remove MODULE macros, etc. now that this driver is a bool in Kconfig
|
||||
|
||||
Changes in v9:
|
||||
-Some whitespace tweaks
|
||||
-Return -EINVAL from probe on invalid irq
|
||||
-Use probe_new i2c_driver callback
|
||||
---
|
||||
drivers/mfd/Kconfig | 16 +++
|
||||
drivers/mfd/Makefile | 1 +
|
||||
drivers/mfd/intel_soc_pmic_chtwc.c | 230 +++++++++++++++++++++++++++++++++++++
|
||||
3 files changed, 247 insertions(+)
|
||||
create mode 100644 drivers/mfd/intel_soc_pmic_chtwc.c
|
||||
|
||||
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
|
||||
index 3eb5c93595f6..5203a86b8f6c 100644
|
||||
--- a/drivers/mfd/Kconfig
|
||||
+++ b/drivers/mfd/Kconfig
|
||||
@@ -470,6 +470,22 @@ config INTEL_SOC_PMIC_BXTWC
|
||||
thermal, charger and related power management functions
|
||||
on these systems.
|
||||
|
||||
+config INTEL_SOC_PMIC_CHTWC
|
||||
+ bool "Support for Intel Cherry Trail Whiskey Cove PMIC"
|
||||
+ depends on ACPI && HAS_IOMEM && I2C=y && COMMON_CLK
|
||||
+ depends on X86 || COMPILE_TEST
|
||||
+ select MFD_CORE
|
||||
+ select REGMAP_I2C
|
||||
+ select REGMAP_IRQ
|
||||
+ select I2C_DESIGNWARE_PLATFORM
|
||||
+ help
|
||||
+ Select this option to enable support for the Intel Cherry Trail
|
||||
+ Whiskey Cove PMIC found on some Intel Cherry Trail systems.
|
||||
+
|
||||
+ This option is a bool as it provides an ACPI OpRegion which must be
|
||||
+ available before any devices using it are probed. This option also
|
||||
+ causes the designware-i2c driver to be builtin for the same reason.
|
||||
+
|
||||
config MFD_INTEL_LPSS
|
||||
tristate
|
||||
select COMMON_CLK
|
||||
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
|
||||
index c16bf1ea0ea9..6f6aed8cfccc 100644
|
||||
--- a/drivers/mfd/Makefile
|
||||
+++ b/drivers/mfd/Makefile
|
||||
@@ -214,6 +214,7 @@ obj-$(CONFIG_MFD_SKY81452) += sky81452.o
|
||||
intel-soc-pmic-objs := intel_soc_pmic_core.o intel_soc_pmic_crc.o
|
||||
obj-$(CONFIG_INTEL_SOC_PMIC) += intel-soc-pmic.o
|
||||
obj-$(CONFIG_INTEL_SOC_PMIC_BXTWC) += intel_soc_pmic_bxtwc.o
|
||||
+obj-$(CONFIG_INTEL_SOC_PMIC_CHTWC) += intel_soc_pmic_chtwc.o
|
||||
obj-$(CONFIG_MFD_MT6397) += mt6397-core.o
|
||||
|
||||
obj-$(CONFIG_MFD_ALTERA_A10SR) += altera-a10sr.o
|
||||
diff --git a/drivers/mfd/intel_soc_pmic_chtwc.c b/drivers/mfd/intel_soc_pmic_chtwc.c
|
||||
new file mode 100644
|
||||
index 000000000000..b35da01d5bcf
|
||||
--- /dev/null
|
||||
+++ b/drivers/mfd/intel_soc_pmic_chtwc.c
|
||||
@@ -0,0 +1,230 @@
|
||||
+/*
|
||||
+ * MFD core driver for Intel Cherrytrail Whiskey Cove PMIC
|
||||
+ *
|
||||
+ * Copyright (C) 2017 Hans de Goede <hdegoede@redhat.com>
|
||||
+ *
|
||||
+ * Based on various non upstream patches to support the CHT Whiskey Cove PMIC:
|
||||
+ * Copyright (C) 2013-2015 Intel Corporation. All rights reserved.
|
||||
+ *
|
||||
+ * This program is free software; you can redistribute it and/or modify
|
||||
+ * it under the terms of the GNU General Public License version 2 as
|
||||
+ * published by the Free Software Foundation.
|
||||
+ */
|
||||
+
|
||||
+#include <linux/acpi.h>
|
||||
+#include <linux/delay.h>
|
||||
+#include <linux/err.h>
|
||||
+#include <linux/i2c.h>
|
||||
+#include <linux/interrupt.h>
|
||||
+#include <linux/kernel.h>
|
||||
+#include <linux/mfd/core.h>
|
||||
+#include <linux/mfd/intel_soc_pmic.h>
|
||||
+#include <linux/regmap.h>
|
||||
+
|
||||
+/* PMIC device registers */
|
||||
+#define REG_OFFSET_MASK GENMASK(7, 0)
|
||||
+#define REG_ADDR_MASK GENMASK(15, 8)
|
||||
+#define REG_ADDR_SHIFT 8
|
||||
+
|
||||
+#define CHT_WC_IRQLVL1 0x6e02
|
||||
+#define CHT_WC_IRQLVL1_MASK 0x6e0e
|
||||
+
|
||||
+/* Whiskey Cove PMIC share same ACPI ID between different platforms */
|
||||
+#define CHT_WC_HRV 3
|
||||
+
|
||||
+/* Level 1 IRQs (level 2 IRQs are handled in the child device drivers) */
|
||||
+enum {
|
||||
+ CHT_WC_PWRSRC_IRQ = 0,
|
||||
+ CHT_WC_THRM_IRQ,
|
||||
+ CHT_WC_BCU_IRQ,
|
||||
+ CHT_WC_ADC_IRQ,
|
||||
+ CHT_WC_EXT_CHGR_IRQ,
|
||||
+ CHT_WC_GPIO_IRQ,
|
||||
+ /* There is no irq 6 */
|
||||
+ CHT_WC_CRIT_IRQ = 7,
|
||||
+};
|
||||
+
|
||||
+static struct resource cht_wc_pwrsrc_resources[] = {
|
||||
+ DEFINE_RES_IRQ(CHT_WC_PWRSRC_IRQ),
|
||||
+};
|
||||
+
|
||||
+static struct resource cht_wc_ext_charger_resources[] = {
|
||||
+ DEFINE_RES_IRQ(CHT_WC_EXT_CHGR_IRQ),
|
||||
+};
|
||||
+
|
||||
+static struct mfd_cell cht_wc_dev[] = {
|
||||
+ {
|
||||
+ .name = "cht_wcove_pwrsrc",
|
||||
+ .num_resources = ARRAY_SIZE(cht_wc_pwrsrc_resources),
|
||||
+ .resources = cht_wc_pwrsrc_resources,
|
||||
+ }, {
|
||||
+ .name = "cht_wcove_ext_chgr",
|
||||
+ .num_resources = ARRAY_SIZE(cht_wc_ext_charger_resources),
|
||||
+ .resources = cht_wc_ext_charger_resources,
|
||||
+ },
|
||||
+ { .name = "cht_wcove_region", },
|
||||
+};
|
||||
+
|
||||
+/*
|
||||
+ * The CHT Whiskey Cove covers multiple I2C addresses, with a 1 Byte
|
||||
+ * register address space per I2C address, so we use 16 bit register
|
||||
+ * addresses where the high 8 bits contain the I2C client address.
|
||||
+ */
|
||||
+static int cht_wc_byte_reg_read(void *context, unsigned int reg,
|
||||
+ unsigned int *val)
|
||||
+{
|
||||
+ struct i2c_client *client = context;
|
||||
+ int ret, orig_addr = client->addr;
|
||||
+
|
||||
+ if (!(reg & REG_ADDR_MASK)) {
|
||||
+ dev_err(&client->dev, "Error I2C address not specified\n");
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ client->addr = (reg & REG_ADDR_MASK) >> REG_ADDR_SHIFT;
|
||||
+ ret = i2c_smbus_read_byte_data(client, reg & REG_OFFSET_MASK);
|
||||
+ client->addr = orig_addr;
|
||||
+
|
||||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
+
|
||||
+ *val = ret;
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int cht_wc_byte_reg_write(void *context, unsigned int reg,
|
||||
+ unsigned int val)
|
||||
+{
|
||||
+ struct i2c_client *client = context;
|
||||
+ int ret, orig_addr = client->addr;
|
||||
+
|
||||
+ if (!(reg & REG_ADDR_MASK)) {
|
||||
+ dev_err(&client->dev, "Error I2C address not specified\n");
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ client->addr = (reg & REG_ADDR_MASK) >> REG_ADDR_SHIFT;
|
||||
+ ret = i2c_smbus_write_byte_data(client, reg & REG_OFFSET_MASK, val);
|
||||
+ client->addr = orig_addr;
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static const struct regmap_config cht_wc_regmap_cfg = {
|
||||
+ .reg_bits = 16,
|
||||
+ .val_bits = 8,
|
||||
+ .reg_write = cht_wc_byte_reg_write,
|
||||
+ .reg_read = cht_wc_byte_reg_read,
|
||||
+};
|
||||
+
|
||||
+static const struct regmap_irq cht_wc_regmap_irqs[] = {
|
||||
+ REGMAP_IRQ_REG(CHT_WC_PWRSRC_IRQ, 0, BIT(CHT_WC_PWRSRC_IRQ)),
|
||||
+ REGMAP_IRQ_REG(CHT_WC_THRM_IRQ, 0, BIT(CHT_WC_THRM_IRQ)),
|
||||
+ REGMAP_IRQ_REG(CHT_WC_BCU_IRQ, 0, BIT(CHT_WC_BCU_IRQ)),
|
||||
+ REGMAP_IRQ_REG(CHT_WC_ADC_IRQ, 0, BIT(CHT_WC_ADC_IRQ)),
|
||||
+ REGMAP_IRQ_REG(CHT_WC_EXT_CHGR_IRQ, 0, BIT(CHT_WC_EXT_CHGR_IRQ)),
|
||||
+ REGMAP_IRQ_REG(CHT_WC_GPIO_IRQ, 0, BIT(CHT_WC_GPIO_IRQ)),
|
||||
+ REGMAP_IRQ_REG(CHT_WC_CRIT_IRQ, 0, BIT(CHT_WC_CRIT_IRQ)),
|
||||
+};
|
||||
+
|
||||
+static const struct regmap_irq_chip cht_wc_regmap_irq_chip = {
|
||||
+ .name = "cht_wc_irq_chip",
|
||||
+ .status_base = CHT_WC_IRQLVL1,
|
||||
+ .mask_base = CHT_WC_IRQLVL1_MASK,
|
||||
+ .irqs = cht_wc_regmap_irqs,
|
||||
+ .num_irqs = ARRAY_SIZE(cht_wc_regmap_irqs),
|
||||
+ .num_regs = 1,
|
||||
+};
|
||||
+
|
||||
+static int cht_wc_probe(struct i2c_client *client)
|
||||
+{
|
||||
+ struct device *dev = &client->dev;
|
||||
+ struct intel_soc_pmic *pmic;
|
||||
+ acpi_status status;
|
||||
+ unsigned long long hrv;
|
||||
+ int ret;
|
||||
+
|
||||
+ status = acpi_evaluate_integer(ACPI_HANDLE(dev), "_HRV", NULL, &hrv);
|
||||
+ if (ACPI_FAILURE(status)) {
|
||||
+ dev_err(dev, "Failed to get PMIC hardware revision\n");
|
||||
+ return -ENODEV;
|
||||
+ }
|
||||
+ if (hrv != CHT_WC_HRV) {
|
||||
+ dev_err(dev, "Invalid PMIC hardware revision: %llu\n", hrv);
|
||||
+ return -ENODEV;
|
||||
+ }
|
||||
+ if (client->irq < 0) {
|
||||
+ dev_err(dev, "Invalid IRQ\n");
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ pmic = devm_kzalloc(dev, sizeof(*pmic), GFP_KERNEL);
|
||||
+ if (!pmic)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ pmic->irq = client->irq;
|
||||
+ pmic->dev = dev;
|
||||
+ i2c_set_clientdata(client, pmic);
|
||||
+
|
||||
+ pmic->regmap = devm_regmap_init(dev, NULL, client, &cht_wc_regmap_cfg);
|
||||
+ if (IS_ERR(pmic->regmap))
|
||||
+ return PTR_ERR(pmic->regmap);
|
||||
+
|
||||
+ ret = devm_regmap_add_irq_chip(dev, pmic->regmap, pmic->irq,
|
||||
+ IRQF_ONESHOT | IRQF_SHARED, 0,
|
||||
+ &cht_wc_regmap_irq_chip,
|
||||
+ &pmic->irq_chip_data);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ return devm_mfd_add_devices(dev, PLATFORM_DEVID_NONE,
|
||||
+ cht_wc_dev, ARRAY_SIZE(cht_wc_dev), NULL, 0,
|
||||
+ regmap_irq_get_domain(pmic->irq_chip_data));
|
||||
+}
|
||||
+
|
||||
+static void cht_wc_shutdown(struct i2c_client *client)
|
||||
+{
|
||||
+ struct intel_soc_pmic *pmic = i2c_get_clientdata(client);
|
||||
+
|
||||
+ disable_irq(pmic->irq);
|
||||
+}
|
||||
+
|
||||
+static int __maybe_unused cht_wc_suspend(struct device *dev)
|
||||
+{
|
||||
+ struct intel_soc_pmic *pmic = dev_get_drvdata(dev);
|
||||
+
|
||||
+ disable_irq(pmic->irq);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int __maybe_unused cht_wc_resume(struct device *dev)
|
||||
+{
|
||||
+ struct intel_soc_pmic *pmic = dev_get_drvdata(dev);
|
||||
+
|
||||
+ enable_irq(pmic->irq);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+static SIMPLE_DEV_PM_OPS(cht_wc_pm_ops, cht_wc_suspend, cht_wc_resume);
|
||||
+
|
||||
+static const struct i2c_device_id cht_wc_i2c_id[] = {
|
||||
+ { }
|
||||
+};
|
||||
+
|
||||
+static const struct acpi_device_id cht_wc_acpi_ids[] = {
|
||||
+ { "INT34D3", },
|
||||
+ { }
|
||||
+};
|
||||
+
|
||||
+static struct i2c_driver cht_wc_driver = {
|
||||
+ .driver = {
|
||||
+ .name = "CHT Whiskey Cove PMIC",
|
||||
+ .pm = &cht_wc_pm_ops,
|
||||
+ .acpi_match_table = cht_wc_acpi_ids,
|
||||
+ },
|
||||
+ .probe_new = cht_wc_probe,
|
||||
+ .shutdown = cht_wc_shutdown,
|
||||
+ .id_table = cht_wc_i2c_id,
|
||||
+};
|
||||
+builtin_i2c_driver(cht_wc_driver);
|
||||
--
|
||||
2.13.0
|
||||
|
|
@ -1,80 +0,0 @@
|
|||
From 27b9d46d25c873b351757c44ce523bf0ede1d08e Mon Sep 17 00:00:00 2001
|
||||
From: Hans de Goede <hdegoede@redhat.com>
|
||||
Date: Mon, 14 Aug 2017 11:02:59 +0200
|
||||
Subject: [PATCH 2/2] power: supply: max17042_battery: Fix ACPI interrupt
|
||||
issues
|
||||
|
||||
On some x86/ACPI boards the DSDT defines an ACPI event handler for
|
||||
the max17047 IRQ, this causes several problems:
|
||||
|
||||
1) We need to share the IRQ to avoid an error getting it
|
||||
|
||||
2) Even of we are willing to share, we may fail to share because some
|
||||
DSDTs claim it exclusivly
|
||||
|
||||
3) If we are unable to share the IRQ, or the IRQ is only listed as an
|
||||
ACPI event source and not in the max1704 firmware node, then the
|
||||
charge threshold IRQ (which is used to give an IRQ every 1 percent
|
||||
charge change) becomes a problem, the ACPI event handler will not
|
||||
update this to the next 1 percent threshold, so the IRQ keeps firing
|
||||
and we get an IRQ storm pegging 1 CPU core.
|
||||
|
||||
This happens despite the max17042 driver not setting the charge
|
||||
threshold because Windows uses it and leaves it set on reboot.
|
||||
|
||||
So if we are unable to get the IRQ we need to reprogram the
|
||||
charge threshold to its disabled setting.
|
||||
|
||||
This commit fixes al of the above, while at it it also makes the error
|
||||
msg when being unable to get the IRQ consistent with other messages.
|
||||
|
||||
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
|
||||
---
|
||||
drivers/power/supply/max17042_battery.c | 20 +++++++++++++++-----
|
||||
1 file changed, 15 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/drivers/power/supply/max17042_battery.c b/drivers/power/supply/max17042_battery.c
|
||||
index b2ddb7eb69c6..18a44e4ed6ff 100644
|
||||
--- a/drivers/power/supply/max17042_battery.c
|
||||
+++ b/drivers/power/supply/max17042_battery.c
|
||||
@@ -1050,11 +1050,18 @@ static int max17042_probe(struct i2c_client *client,
|
||||
}
|
||||
|
||||
if (client->irq) {
|
||||
+ unsigned int flags = IRQF_TRIGGER_FALLING | IRQF_ONESHOT;
|
||||
+
|
||||
+ /*
|
||||
+ * On ACPI systems the IRQ may be handled by ACPI-event code,
|
||||
+ * so we need to share (if the ACPI code is willing to share).
|
||||
+ */
|
||||
+ if (acpi_id)
|
||||
+ flags |= IRQF_SHARED | IRQF_PROBE_SHARED;
|
||||
+
|
||||
ret = devm_request_threaded_irq(&client->dev, client->irq,
|
||||
NULL,
|
||||
- max17042_thread_handler,
|
||||
- IRQF_TRIGGER_FALLING |
|
||||
- IRQF_ONESHOT,
|
||||
+ max17042_thread_handler, flags,
|
||||
chip->battery->desc->name,
|
||||
chip);
|
||||
if (!ret) {
|
||||
@@ -1064,10 +1071,13 @@ static int max17042_probe(struct i2c_client *client,
|
||||
max17042_set_soc_threshold(chip, 1);
|
||||
} else {
|
||||
client->irq = 0;
|
||||
- dev_err(&client->dev, "%s(): cannot get IRQ\n",
|
||||
- __func__);
|
||||
+ if (ret != -EBUSY)
|
||||
+ dev_err(&client->dev, "Failed to get IRQ\n");
|
||||
}
|
||||
}
|
||||
+ /* Not able to update the charge threshold when exceeded? -> disable */
|
||||
+ if (!client->irq)
|
||||
+ regmap_write(chip->regmap, MAX17042_SALRT_Th, 0xff00);
|
||||
|
||||
regmap_read(chip->regmap, MAX17042_STATUS, &val);
|
||||
if (val & STATUS_POR_BIT) {
|
||||
--
|
||||
2.13.4
|
||||
|
|
@ -1,49 +0,0 @@
|
|||
From 75c7f5172c113af1ea3cf094436c9e03191673e0 Mon Sep 17 00:00:00 2001
|
||||
From: Michael Ellerman <mpe@ellerman.id.au>
|
||||
Date: Tue, 28 Nov 2017 11:26:55 +0100
|
||||
Subject: [PATCH 2/5] powerpc/64s/hash: Fix 512T hint detection to use >= 128T
|
||||
|
||||
commit 7ece370996b694ae263025e056ad785afc1be5ab upstream.
|
||||
|
||||
Currently userspace is able to request mmap() search between 128T-512T
|
||||
by specifying a hint address that is greater than 128T. But that means
|
||||
a hint of 128T exactly will return an address below 128T, which is
|
||||
confusing and wrong.
|
||||
|
||||
So fix the logic to check the hint is greater than *or equal* to 128T.
|
||||
|
||||
Fixes: f4ea6dcb08ea ("powerpc/mm: Enable mappings above 128TB")
|
||||
Suggested-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
|
||||
Suggested-by: Nicholas Piggin <npiggin@gmail.com>
|
||||
[mpe: Split out of Nick's bigger patch]
|
||||
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
||||
---
|
||||
arch/powerpc/mm/slice.c | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/arch/powerpc/mm/slice.c b/arch/powerpc/mm/slice.c
|
||||
index 45f6740dd407..48a5312103a1 100644
|
||||
--- a/arch/powerpc/mm/slice.c
|
||||
+++ b/arch/powerpc/mm/slice.c
|
||||
@@ -419,7 +419,7 @@ unsigned long slice_get_unmapped_area(unsigned long addr, unsigned long len,
|
||||
/*
|
||||
* Check if we need to expland slice area.
|
||||
*/
|
||||
- if (unlikely(addr > mm->context.addr_limit &&
|
||||
+ if (unlikely(addr >= mm->context.addr_limit &&
|
||||
mm->context.addr_limit != TASK_SIZE)) {
|
||||
mm->context.addr_limit = TASK_SIZE;
|
||||
on_each_cpu(slice_flush_segments, mm, 1);
|
||||
@@ -427,7 +427,7 @@ unsigned long slice_get_unmapped_area(unsigned long addr, unsigned long len,
|
||||
/*
|
||||
* This mmap request can allocate upt to 512TB
|
||||
*/
|
||||
- if (addr > DEFAULT_MAP_WINDOW)
|
||||
+ if (addr >= DEFAULT_MAP_WINDOW)
|
||||
high_limit = mm->context.addr_limit;
|
||||
else
|
||||
high_limit = DEFAULT_MAP_WINDOW;
|
||||
--
|
||||
2.14.3
|
||||
|
|
@ -1,57 +0,0 @@
|
|||
From 69dd0606a0d8680fe0a5e9b959f6662e582e1674 Mon Sep 17 00:00:00 2001
|
||||
From: Hans de Goede <hdegoede@redhat.com>
|
||||
Date: Tue, 2 May 2017 13:43:34 +0200
|
||||
Subject: [PATCH 03/16] power: supply: core: Add support for supplied-from
|
||||
device-property
|
||||
|
||||
On devicetree using platforms the devicetree can provide info on which
|
||||
power-supplies supply another power-supply through phandles.
|
||||
|
||||
This commit adds support for providing this info on non devicetree
|
||||
platforms through the platform code setting a supplied-from
|
||||
device-property on the power-supplies parent device.
|
||||
|
||||
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
|
||||
---
|
||||
drivers/power/supply/power_supply_core.c | 24 +++++++++++++++++++++++-
|
||||
1 file changed, 23 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/drivers/power/supply/power_supply_core.c b/drivers/power/supply/power_supply_core.c
|
||||
index 7ec7c7c202bd..0c09144193a6 100644
|
||||
--- a/drivers/power/supply/power_supply_core.c
|
||||
+++ b/drivers/power/supply/power_supply_core.c
|
||||
@@ -274,8 +274,30 @@ static int power_supply_check_supplies(struct power_supply *psy)
|
||||
return power_supply_populate_supplied_from(psy);
|
||||
}
|
||||
#else
|
||||
-static inline int power_supply_check_supplies(struct power_supply *psy)
|
||||
+static int power_supply_check_supplies(struct power_supply *psy)
|
||||
{
|
||||
+ int nval, ret;
|
||||
+
|
||||
+ if (!psy->dev.parent)
|
||||
+ return 0;
|
||||
+
|
||||
+ nval = device_property_read_string_array(psy->dev.parent,
|
||||
+ "supplied-from", NULL, 0);
|
||||
+ if (nval <= 0)
|
||||
+ return 0;
|
||||
+
|
||||
+ psy->supplied_from = devm_kmalloc_array(&psy->dev, nval,
|
||||
+ sizeof(char *), GFP_KERNEL);
|
||||
+ if (!psy->supplied_from)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ ret = device_property_read_string_array(psy->dev.parent,
|
||||
+ "supplied-from", (const char **)psy->supplied_from, nval);
|
||||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
+
|
||||
+ psy->num_supplies = nval;
|
||||
+
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
--
|
||||
2.13.0
|
||||
|
|
@ -1,129 +0,0 @@
|
|||
From e90387a8d2227f95bf5e5b5ffd816d48a87466e2 Mon Sep 17 00:00:00 2001
|
||||
From: Nicholas Piggin <npiggin@gmail.com>
|
||||
Date: Tue, 28 Nov 2017 11:26:56 +0100
|
||||
Subject: [PATCH 3/5] powerpc/64s/hash: Fix 128TB-512TB virtual address
|
||||
boundary case allocation
|
||||
|
||||
commit 6a72dc038b615229a1b285829d6c8378d15c2347 upstream.
|
||||
|
||||
When allocating VA space with a hint that crosses 128TB, the SLB
|
||||
addr_limit variable is not expanded if addr is not > 128TB, but the
|
||||
slice allocation looks at task_size, which is 512TB. This results in
|
||||
slice_check_fit() incorrectly succeeding because the slice_count
|
||||
truncates off bit 128 of the requested mask, so the comparison to the
|
||||
available mask succeeds.
|
||||
|
||||
Fix this by using mm->context.addr_limit instead of mm->task_size for
|
||||
testing allocation limits. This causes such allocations to fail.
|
||||
|
||||
Fixes: f4ea6dcb08ea ("powerpc/mm: Enable mappings above 128TB")
|
||||
Reported-by: Florian Weimer <fweimer@redhat.com>
|
||||
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
|
||||
Reviewed-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
|
||||
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
||||
---
|
||||
arch/powerpc/mm/slice.c | 50 ++++++++++++++++++++++++-------------------------
|
||||
1 file changed, 24 insertions(+), 26 deletions(-)
|
||||
|
||||
diff --git a/arch/powerpc/mm/slice.c b/arch/powerpc/mm/slice.c
|
||||
index 48a5312103a1..3889201b560c 100644
|
||||
--- a/arch/powerpc/mm/slice.c
|
||||
+++ b/arch/powerpc/mm/slice.c
|
||||
@@ -96,7 +96,7 @@ static int slice_area_is_free(struct mm_struct *mm, unsigned long addr,
|
||||
{
|
||||
struct vm_area_struct *vma;
|
||||
|
||||
- if ((mm->task_size - len) < addr)
|
||||
+ if ((mm->context.addr_limit - len) < addr)
|
||||
return 0;
|
||||
vma = find_vma(mm, addr);
|
||||
return (!vma || (addr + len) <= vm_start_gap(vma));
|
||||
@@ -133,7 +133,7 @@ static void slice_mask_for_free(struct mm_struct *mm, struct slice_mask *ret)
|
||||
if (!slice_low_has_vma(mm, i))
|
||||
ret->low_slices |= 1u << i;
|
||||
|
||||
- if (mm->task_size <= SLICE_LOW_TOP)
|
||||
+ if (mm->context.addr_limit <= SLICE_LOW_TOP)
|
||||
return;
|
||||
|
||||
for (i = 0; i < GET_HIGH_SLICE_INDEX(mm->context.addr_limit); i++)
|
||||
@@ -412,25 +412,31 @@ unsigned long slice_get_unmapped_area(unsigned long addr, unsigned long len,
|
||||
struct slice_mask compat_mask;
|
||||
int fixed = (flags & MAP_FIXED);
|
||||
int pshift = max_t(int, mmu_psize_defs[psize].shift, PAGE_SHIFT);
|
||||
+ unsigned long page_size = 1UL << pshift;
|
||||
struct mm_struct *mm = current->mm;
|
||||
unsigned long newaddr;
|
||||
unsigned long high_limit;
|
||||
|
||||
- /*
|
||||
- * Check if we need to expland slice area.
|
||||
- */
|
||||
- if (unlikely(addr >= mm->context.addr_limit &&
|
||||
- mm->context.addr_limit != TASK_SIZE)) {
|
||||
- mm->context.addr_limit = TASK_SIZE;
|
||||
+ high_limit = DEFAULT_MAP_WINDOW;
|
||||
+ if (addr >= high_limit)
|
||||
+ high_limit = TASK_SIZE;
|
||||
+
|
||||
+ if (len > high_limit)
|
||||
+ return -ENOMEM;
|
||||
+ if (len & (page_size - 1))
|
||||
+ return -EINVAL;
|
||||
+ if (fixed) {
|
||||
+ if (addr & (page_size - 1))
|
||||
+ return -EINVAL;
|
||||
+ if (addr > high_limit - len)
|
||||
+ return -ENOMEM;
|
||||
+ }
|
||||
+
|
||||
+ if (high_limit > mm->context.addr_limit) {
|
||||
+ mm->context.addr_limit = high_limit;
|
||||
on_each_cpu(slice_flush_segments, mm, 1);
|
||||
}
|
||||
- /*
|
||||
- * This mmap request can allocate upt to 512TB
|
||||
- */
|
||||
- if (addr >= DEFAULT_MAP_WINDOW)
|
||||
- high_limit = mm->context.addr_limit;
|
||||
- else
|
||||
- high_limit = DEFAULT_MAP_WINDOW;
|
||||
+
|
||||
/*
|
||||
* init different masks
|
||||
*/
|
||||
@@ -446,27 +452,19 @@ unsigned long slice_get_unmapped_area(unsigned long addr, unsigned long len,
|
||||
|
||||
/* Sanity checks */
|
||||
BUG_ON(mm->task_size == 0);
|
||||
+ BUG_ON(mm->context.addr_limit == 0);
|
||||
VM_BUG_ON(radix_enabled());
|
||||
|
||||
slice_dbg("slice_get_unmapped_area(mm=%p, psize=%d...\n", mm, psize);
|
||||
slice_dbg(" addr=%lx, len=%lx, flags=%lx, topdown=%d\n",
|
||||
addr, len, flags, topdown);
|
||||
|
||||
- if (len > mm->task_size)
|
||||
- return -ENOMEM;
|
||||
- if (len & ((1ul << pshift) - 1))
|
||||
- return -EINVAL;
|
||||
- if (fixed && (addr & ((1ul << pshift) - 1)))
|
||||
- return -EINVAL;
|
||||
- if (fixed && addr > (mm->task_size - len))
|
||||
- return -ENOMEM;
|
||||
-
|
||||
/* If hint, make sure it matches our alignment restrictions */
|
||||
if (!fixed && addr) {
|
||||
- addr = _ALIGN_UP(addr, 1ul << pshift);
|
||||
+ addr = _ALIGN_UP(addr, page_size);
|
||||
slice_dbg(" aligned addr=%lx\n", addr);
|
||||
/* Ignore hint if it's too large or overlaps a VMA */
|
||||
- if (addr > mm->task_size - len ||
|
||||
+ if (addr > high_limit - len ||
|
||||
!slice_area_is_free(mm, addr, len))
|
||||
addr = 0;
|
||||
}
|
||||
--
|
||||
2.14.3
|
||||
|
|
@ -1,48 +0,0 @@
|
|||
From 99c44df299d96db6a170ccce9b8108fc2e7f8bae Mon Sep 17 00:00:00 2001
|
||||
From: Hans de Goede <hdegoede@redhat.com>
|
||||
Date: Tue, 2 May 2017 13:40:44 +0200
|
||||
Subject: [PATCH 04/16] platform/x86: intel_cht_int33fe: Set supplied-from
|
||||
property on max17047 dev
|
||||
|
||||
Devices with the intel_cht_int33fe ACPI device use a max17047 fuel-gauge
|
||||
combined with a bq24272i charger, in order for the fuel-gauge driver to
|
||||
correctly display charging / discharging status it needs to know which
|
||||
charger is supplying the battery.
|
||||
|
||||
This commit sets the supplied-from device property to the name of the
|
||||
bq24272i charger for this.
|
||||
|
||||
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
|
||||
---
|
||||
drivers/platform/x86/intel_cht_int33fe.c | 8 ++++++++
|
||||
1 file changed, 8 insertions(+)
|
||||
|
||||
diff --git a/drivers/platform/x86/intel_cht_int33fe.c b/drivers/platform/x86/intel_cht_int33fe.c
|
||||
index 6a1b2ca5b6fe..da706e2c4232 100644
|
||||
--- a/drivers/platform/x86/intel_cht_int33fe.c
|
||||
+++ b/drivers/platform/x86/intel_cht_int33fe.c
|
||||
@@ -34,6 +34,13 @@ struct cht_int33fe_data {
|
||||
struct i2c_client *pi3usb30532;
|
||||
};
|
||||
|
||||
+static const char * const max17047_suppliers[] = { "bq24190-charger" };
|
||||
+
|
||||
+static const struct property_entry max17047_props[] = {
|
||||
+ PROPERTY_ENTRY_STRING_ARRAY("supplied-from", max17047_suppliers),
|
||||
+ { }
|
||||
+};
|
||||
+
|
||||
static int cht_int33fe_probe(struct i2c_client *client)
|
||||
{
|
||||
struct device *dev = &client->dev;
|
||||
@@ -70,6 +77,7 @@ static int cht_int33fe_probe(struct i2c_client *client)
|
||||
|
||||
memset(&board_info, 0, sizeof(board_info));
|
||||
strlcpy(board_info.type, "max17047", I2C_NAME_SIZE);
|
||||
+ board_info.properties = max17047_props;
|
||||
|
||||
data->max17047 = i2c_acpi_new_device(dev, 1, &board_info);
|
||||
if (!data->max17047)
|
||||
--
|
||||
2.13.0
|
||||
|
|
@ -1,48 +0,0 @@
|
|||
From fe50aa4374f20333d9b077bbe09397d38112b081 Mon Sep 17 00:00:00 2001
|
||||
From: Nicholas Piggin <npiggin@gmail.com>
|
||||
Date: Tue, 28 Nov 2017 11:26:57 +0100
|
||||
Subject: [PATCH 4/5] powerpc/64s/hash: Fix fork() with 512TB process address
|
||||
space
|
||||
|
||||
commit effc1b25088502fbd30305c79773de2d1f7470a6 upstream.
|
||||
|
||||
Hash unconditionally resets the addr_limit to default (128TB) when the
|
||||
mm context is initialised. If a process has > 128TB mappings when it
|
||||
forks, the child will not get the 512TB addr_limit, so accesses to
|
||||
valid > 128TB mappings will fail in the child.
|
||||
|
||||
Fix this by only resetting the addr_limit to default if it was 0. Non
|
||||
zero indicates it was duplicated from the parent (0 means exec()).
|
||||
|
||||
Fixes: f4ea6dcb08ea ("powerpc/mm: Enable mappings above 128TB")
|
||||
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
|
||||
Reviewed-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
|
||||
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
||||
---
|
||||
arch/powerpc/mm/mmu_context_book3s64.c | 8 ++++----
|
||||
1 file changed, 4 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/arch/powerpc/mm/mmu_context_book3s64.c b/arch/powerpc/mm/mmu_context_book3s64.c
|
||||
index a75f63833284..bb9cdf01fc4f 100644
|
||||
--- a/arch/powerpc/mm/mmu_context_book3s64.c
|
||||
+++ b/arch/powerpc/mm/mmu_context_book3s64.c
|
||||
@@ -95,11 +95,11 @@ static int hash__init_new_context(struct mm_struct *mm)
|
||||
return index;
|
||||
|
||||
/*
|
||||
- * We do switch_slb() early in fork, even before we setup the
|
||||
- * mm->context.addr_limit. Default to max task size so that we copy the
|
||||
- * default values to paca which will help us to handle slb miss early.
|
||||
+ * In the case of exec, use the default limit,
|
||||
+ * otherwise inherit it from the mm we are duplicating.
|
||||
*/
|
||||
- mm->context.addr_limit = DEFAULT_MAP_WINDOW_USER64;
|
||||
+ if (!mm->context.addr_limit)
|
||||
+ mm->context.addr_limit = DEFAULT_MAP_WINDOW_USER64;
|
||||
|
||||
/*
|
||||
* The old code would re-promote on fork, we don't do that when using
|
||||
--
|
||||
2.14.3
|
||||
|
|
@ -1,80 +0,0 @@
|
|||
From cc2b0e2c164d02ab42efa736f91f53baf8d8bc36 Mon Sep 17 00:00:00 2001
|
||||
From: Hans de Goede <hdegoede@redhat.com>
|
||||
Date: Thu, 20 Apr 2017 22:41:20 +0200
|
||||
Subject: [PATCH 05/16] ACPI / PMIC: xpower: Add support for the GPI1 regulator
|
||||
to the OpRegion handler
|
||||
|
||||
Some Bay Trail devices use a GPI1 regulator field (address 0x4c) in
|
||||
their 0x8d power OpRegion, add support for this.
|
||||
|
||||
This fixes AE_BAD_PARAMETER errors getting thrown on these devices and
|
||||
fixes these errors causing these devices to not suspend.
|
||||
|
||||
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
|
||||
Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
|
||||
---
|
||||
Changes in v2:
|
||||
-Simplify reg == 0x92 handling (suggested by Andy Shevchenko)
|
||||
-Add special handling for reg == 0x92 to intel_xpower_pmic_get_power() too
|
||||
Changes in v3:
|
||||
-Use defines for GPI1 reg and bits, rather then hardcoded hex values
|
||||
---
|
||||
drivers/acpi/pmic/intel_pmic_xpower.c | 21 ++++++++++++++++++++-
|
||||
1 file changed, 20 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/drivers/acpi/pmic/intel_pmic_xpower.c b/drivers/acpi/pmic/intel_pmic_xpower.c
|
||||
index 1a76c784cd4c..3b7d5be5b7ed 100644
|
||||
--- a/drivers/acpi/pmic/intel_pmic_xpower.c
|
||||
+++ b/drivers/acpi/pmic/intel_pmic_xpower.c
|
||||
@@ -21,6 +21,11 @@
|
||||
#include "intel_pmic.h"
|
||||
|
||||
#define XPOWER_GPADC_LOW 0x5b
|
||||
+#define XPOWER_GPI1_CTRL 0x92
|
||||
+
|
||||
+#define GPI1_LDO_MASK GENMASK(2, 0)
|
||||
+#define GPI1_LDO_ON (3 << 0)
|
||||
+#define GPI1_LDO_OFF (4 << 0)
|
||||
|
||||
static struct pmic_table power_table[] = {
|
||||
{
|
||||
@@ -118,6 +123,10 @@ static struct pmic_table power_table[] = {
|
||||
.reg = 0x10,
|
||||
.bit = 0x00
|
||||
}, /* BUC6 */
|
||||
+ {
|
||||
+ .address = 0x4c,
|
||||
+ .reg = 0x92,
|
||||
+ }, /* GPI1 */
|
||||
};
|
||||
|
||||
/* TMP0 - TMP5 are the same, all from GPADC */
|
||||
@@ -156,7 +165,12 @@ static int intel_xpower_pmic_get_power(struct regmap *regmap, int reg,
|
||||
if (regmap_read(regmap, reg, &data))
|
||||
return -EIO;
|
||||
|
||||
- *value = (data & BIT(bit)) ? 1 : 0;
|
||||
+ /* GPIO1 LDO regulator needs special handling */
|
||||
+ if (reg == XPOWER_GPI1_CTRL)
|
||||
+ *value = ((data & GPI1_LDO_MASK) == GPI1_LDO_ON);
|
||||
+ else
|
||||
+ *value = (data & BIT(bit)) ? 1 : 0;
|
||||
+
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -165,6 +179,11 @@ static int intel_xpower_pmic_update_power(struct regmap *regmap, int reg,
|
||||
{
|
||||
int data;
|
||||
|
||||
+ /* GPIO1 LDO regulator needs special handling */
|
||||
+ if (reg == XPOWER_GPI1_CTRL)
|
||||
+ return regmap_update_bits(regmap, reg, GPI1_LDO_MASK,
|
||||
+ on ? GPI1_LDO_ON : GPI1_LDO_OFF);
|
||||
+
|
||||
if (regmap_read(regmap, reg, &data))
|
||||
return -EIO;
|
||||
|
||||
--
|
||||
2.13.0
|
||||
|
|
@ -1,38 +0,0 @@
|
|||
From 2beb551e379191c2a24e7db8c4fcc64fef4b921a Mon Sep 17 00:00:00 2001
|
||||
From: Nicholas Piggin <npiggin@gmail.com>
|
||||
Date: Tue, 28 Nov 2017 11:26:58 +0100
|
||||
Subject: [PATCH 5/5] powerpc/64s/hash: Allow MAP_FIXED allocations to cross
|
||||
128TB boundary
|
||||
|
||||
commit 35602f82d0c765f991420e319c8d3a596c921eb8 upstream.
|
||||
|
||||
While mapping hints with a length that cross 128TB are disallowed,
|
||||
MAP_FIXED allocations that cross 128TB are allowed. These are failing
|
||||
on hash (on radix they succeed). Add an additional case for fixed
|
||||
mappings to expand the addr_limit when crossing 128TB.
|
||||
|
||||
Fixes: f4ea6dcb08ea ("powerpc/mm: Enable mappings above 128TB")
|
||||
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
|
||||
Reviewed-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
|
||||
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
||||
---
|
||||
arch/powerpc/mm/slice.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/arch/powerpc/mm/slice.c b/arch/powerpc/mm/slice.c
|
||||
index 3889201b560c..a4f93699194b 100644
|
||||
--- a/arch/powerpc/mm/slice.c
|
||||
+++ b/arch/powerpc/mm/slice.c
|
||||
@@ -418,7 +418,7 @@ unsigned long slice_get_unmapped_area(unsigned long addr, unsigned long len,
|
||||
unsigned long high_limit;
|
||||
|
||||
high_limit = DEFAULT_MAP_WINDOW;
|
||||
- if (addr >= high_limit)
|
||||
+ if (addr >= high_limit || (fixed && (addr + len > high_limit)))
|
||||
high_limit = TASK_SIZE;
|
||||
|
||||
if (len > high_limit)
|
||||
--
|
||||
2.14.3
|
||||
|
|
@ -1,67 +0,0 @@
|
|||
From fbac4c05ec1d7c2d949f50baf1e934cbfbb6a494 Mon Sep 17 00:00:00 2001
|
||||
From: Hans de Goede <hdegoede@redhat.com>
|
||||
Date: Mon, 17 Apr 2017 22:06:25 +0200
|
||||
Subject: [PATCH 06/16] Input: axp20x-pek - Add wakeup support
|
||||
|
||||
At least on devices with the AXP288 PMIC the device is expected to
|
||||
wakeup from suspend when the power-button gets pressed, add support
|
||||
for this.
|
||||
|
||||
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
|
||||
---
|
||||
drivers/input/misc/axp20x-pek.c | 28 ++++++++++++++++++++++++++++
|
||||
1 file changed, 28 insertions(+)
|
||||
|
||||
diff --git a/drivers/input/misc/axp20x-pek.c b/drivers/input/misc/axp20x-pek.c
|
||||
index 400869e61a06..5f16fceaae83 100644
|
||||
--- a/drivers/input/misc/axp20x-pek.c
|
||||
+++ b/drivers/input/misc/axp20x-pek.c
|
||||
@@ -253,6 +253,9 @@ static int axp20x_pek_probe_input_device(struct axp20x_pek *axp20x_pek,
|
||||
return error;
|
||||
}
|
||||
|
||||
+ if (axp20x_pek->axp20x->variant == AXP288_ID)
|
||||
+ enable_irq_wake(axp20x_pek->irq_dbr);
|
||||
+
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -331,10 +334,35 @@ static int axp20x_pek_probe(struct platform_device *pdev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static int __maybe_unused axp20x_pek_resume_noirq(struct device *dev)
|
||||
+{
|
||||
+ struct axp20x_pek *axp20x_pek = dev_get_drvdata(dev);
|
||||
+
|
||||
+ if (axp20x_pek->axp20x->variant != AXP288_ID)
|
||||
+ return 0;
|
||||
+
|
||||
+ /*
|
||||
+ * Clear interrupts from button presses during suspend, to avoid
|
||||
+ * a wakeup power-button press getting reported to userspace.
|
||||
+ */
|
||||
+ regmap_write(axp20x_pek->axp20x->regmap,
|
||||
+ AXP20X_IRQ1_STATE + AXP288_IRQ_POKN / 8,
|
||||
+ BIT(AXP288_IRQ_POKN % 8));
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+const struct dev_pm_ops axp20x_pek_pm_ops = {
|
||||
+#ifdef CONFIG_PM_SLEEP
|
||||
+ .resume_noirq = axp20x_pek_resume_noirq,
|
||||
+#endif
|
||||
+};
|
||||
+
|
||||
static struct platform_driver axp20x_pek_driver = {
|
||||
.probe = axp20x_pek_probe,
|
||||
.driver = {
|
||||
.name = "axp20x-pek",
|
||||
+ .pm = &axp20x_pek_pm_ops,
|
||||
},
|
||||
};
|
||||
module_platform_driver(axp20x_pek_driver);
|
||||
--
|
||||
2.13.0
|
||||
|
|
@ -1,56 +0,0 @@
|
|||
From d95c127c48ef784214671359a41ac505ac30098a Mon Sep 17 00:00:00 2001
|
||||
From: Hans de Goede <hdegoede@redhat.com>
|
||||
Date: Sun, 7 May 2017 12:32:11 +0200
|
||||
Subject: [PATCH 07/16] platform/x86: silead_dmi: Add touchscreen info for
|
||||
GP-electronic T701
|
||||
|
||||
Add touchscreen info for the GP-electronic T701 tablet.
|
||||
|
||||
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
|
||||
---
|
||||
drivers/platform/x86/silead_dmi.c | 22 ++++++++++++++++++++++
|
||||
1 file changed, 22 insertions(+)
|
||||
|
||||
diff --git a/drivers/platform/x86/silead_dmi.c b/drivers/platform/x86/silead_dmi.c
|
||||
index a3a57d93cf06..db3a877d2160 100644
|
||||
--- a/drivers/platform/x86/silead_dmi.c
|
||||
+++ b/drivers/platform/x86/silead_dmi.c
|
||||
@@ -80,6 +80,19 @@ static const struct silead_ts_dmi_data surftab_wintron70_st70416_6_data = {
|
||||
.properties = surftab_wintron70_st70416_6_props,
|
||||
};
|
||||
|
||||
+static const struct property_entry gp_electronic_t701_props[] = {
|
||||
+ PROPERTY_ENTRY_U32("touchscreen-size-x", 960),
|
||||
+ PROPERTY_ENTRY_U32("touchscreen-size-y", 640),
|
||||
+ PROPERTY_ENTRY_STRING("firmware-name",
|
||||
+ "gsl1680-gp-electronic-t701.fw"),
|
||||
+ { }
|
||||
+};
|
||||
+
|
||||
+static const struct silead_ts_dmi_data gp_electronic_t701_data = {
|
||||
+ .acpi_name = "MSSL1680:00",
|
||||
+ .properties = gp_electronic_t701_props,
|
||||
+};
|
||||
+
|
||||
static const struct dmi_system_id silead_ts_dmi_table[] = {
|
||||
{
|
||||
/* CUBE iwork8 Air */
|
||||
@@ -117,6 +130,15 @@ static const struct dmi_system_id silead_ts_dmi_table[] = {
|
||||
DMI_MATCH(DMI_BIOS_VERSION, "TREK.G.WI71C.JGBMRBA04"),
|
||||
},
|
||||
},
|
||||
+ {
|
||||
+ /* GP-electronic T701 */
|
||||
+ .driver_data = (void *)&gp_electronic_t701_data,
|
||||
+ .matches = {
|
||||
+ DMI_MATCH(DMI_SYS_VENDOR, "Insyde"),
|
||||
+ DMI_MATCH(DMI_PRODUCT_NAME, "T701"),
|
||||
+ DMI_MATCH(DMI_BIOS_VERSION, "BYT70A.YNCHENG.WIN.007"),
|
||||
+ },
|
||||
+ },
|
||||
{ },
|
||||
};
|
||||
|
||||
--
|
||||
2.13.0
|
||||
|
|
@ -1,59 +0,0 @@
|
|||
From 55b347c61b2850d1e11e159ab02dc71f13b06481 Mon Sep 17 00:00:00 2001
|
||||
From: Hans de Goede <hdegoede@redhat.com>
|
||||
Date: Sun, 11 Jun 2017 17:42:31 +0200
|
||||
Subject: [PATCH 08/16] platform/x86: silead_dmi: Add touchscreen info for PoV
|
||||
mobii wintab p800w
|
||||
|
||||
Add touchscreen info for the Point of View mobii wintab p800w tablet.
|
||||
|
||||
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
|
||||
---
|
||||
drivers/platform/x86/silead_dmi.c | 25 +++++++++++++++++++++++++
|
||||
1 file changed, 25 insertions(+)
|
||||
|
||||
diff --git a/drivers/platform/x86/silead_dmi.c b/drivers/platform/x86/silead_dmi.c
|
||||
index db3a877d2160..46c5e1ebfb53 100644
|
||||
--- a/drivers/platform/x86/silead_dmi.c
|
||||
+++ b/drivers/platform/x86/silead_dmi.c
|
||||
@@ -93,6 +93,20 @@ static const struct silead_ts_dmi_data gp_electronic_t701_data = {
|
||||
.properties = gp_electronic_t701_props,
|
||||
};
|
||||
|
||||
+static const struct property_entry pov_mobii_wintab_p800w_props[] = {
|
||||
+ PROPERTY_ENTRY_U32("touchscreen-size-x", 1800),
|
||||
+ PROPERTY_ENTRY_U32("touchscreen-size-y", 1150),
|
||||
+ PROPERTY_ENTRY_BOOL("touchscreen-swapped-x-y"),
|
||||
+ PROPERTY_ENTRY_STRING("firmware-name",
|
||||
+ "gsl3692-pov-mobii-wintab-p800w.fw"),
|
||||
+ { }
|
||||
+};
|
||||
+
|
||||
+static const struct silead_ts_dmi_data pov_mobii_wintab_p800w_data = {
|
||||
+ .acpi_name = "MSSL1680:00",
|
||||
+ .properties = pov_mobii_wintab_p800w_props,
|
||||
+};
|
||||
+
|
||||
static const struct dmi_system_id silead_ts_dmi_table[] = {
|
||||
{
|
||||
/* CUBE iwork8 Air */
|
||||
@@ -139,6 +153,17 @@ static const struct dmi_system_id silead_ts_dmi_table[] = {
|
||||
DMI_MATCH(DMI_BIOS_VERSION, "BYT70A.YNCHENG.WIN.007"),
|
||||
},
|
||||
},
|
||||
+ {
|
||||
+ /* Point of View mobii wintab p800w */
|
||||
+ .driver_data = (void *)&pov_mobii_wintab_p800w_data,
|
||||
+ .matches = {
|
||||
+ DMI_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"),
|
||||
+ DMI_MATCH(DMI_BOARD_NAME, "Aptio CRB"),
|
||||
+ DMI_MATCH(DMI_BIOS_VERSION, "3BAIR1013"),
|
||||
+ /* Above matches are too generic, add bios-date match */
|
||||
+ DMI_MATCH(DMI_BIOS_DATE, "08/22/2014"),
|
||||
+ },
|
||||
+ },
|
||||
{ },
|
||||
};
|
||||
|
||||
--
|
||||
2.13.0
|
||||
|
|
@ -1,57 +0,0 @@
|
|||
From b239a7a0c2a1435aa5cbab3f233e0c37e82943dd Mon Sep 17 00:00:00 2001
|
||||
From: Hans de Goede <hdegoede@redhat.com>
|
||||
Date: Tue, 13 Jun 2017 18:17:07 +0200
|
||||
Subject: [PATCH 09/16] platform/x86: silead_dmi: Add touchscreen info for Pipo
|
||||
W2S tablet
|
||||
|
||||
Add touchscreen info for Pipo W2S tablet.
|
||||
|
||||
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
|
||||
---
|
||||
drivers/platform/x86/silead_dmi.c | 23 +++++++++++++++++++++++
|
||||
1 file changed, 23 insertions(+)
|
||||
|
||||
diff --git a/drivers/platform/x86/silead_dmi.c b/drivers/platform/x86/silead_dmi.c
|
||||
index 46c5e1ebfb53..25cbea307a5e 100644
|
||||
--- a/drivers/platform/x86/silead_dmi.c
|
||||
+++ b/drivers/platform/x86/silead_dmi.c
|
||||
@@ -107,6 +107,21 @@ static const struct silead_ts_dmi_data pov_mobii_wintab_p800w_data = {
|
||||
.properties = pov_mobii_wintab_p800w_props,
|
||||
};
|
||||
|
||||
+static const struct property_entry pipo_w2s_props[] = {
|
||||
+ PROPERTY_ENTRY_U32("touchscreen-size-x", 1660),
|
||||
+ PROPERTY_ENTRY_U32("touchscreen-size-y", 880),
|
||||
+ PROPERTY_ENTRY_BOOL("touchscreen-inverted-x"),
|
||||
+ PROPERTY_ENTRY_BOOL("touchscreen-swapped-x-y"),
|
||||
+ PROPERTY_ENTRY_STRING("firmware-name",
|
||||
+ "gsl1680-pipo-w2s.fw"),
|
||||
+ { }
|
||||
+};
|
||||
+
|
||||
+static const struct silead_ts_dmi_data pipo_w2s_data = {
|
||||
+ .acpi_name = "MSSL1680:00",
|
||||
+ .properties = pipo_w2s_props,
|
||||
+};
|
||||
+
|
||||
static const struct dmi_system_id silead_ts_dmi_table[] = {
|
||||
{
|
||||
/* CUBE iwork8 Air */
|
||||
@@ -164,6 +179,14 @@ static const struct dmi_system_id silead_ts_dmi_table[] = {
|
||||
DMI_MATCH(DMI_BIOS_DATE, "08/22/2014"),
|
||||
},
|
||||
},
|
||||
+ {
|
||||
+ /* Pipo W2S */
|
||||
+ .driver_data = (void *)&pipo_w2s_data,
|
||||
+ .matches = {
|
||||
+ DMI_MATCH(DMI_SYS_VENDOR, "PIPO"),
|
||||
+ DMI_MATCH(DMI_PRODUCT_NAME, "W2S"),
|
||||
+ },
|
||||
+ },
|
||||
{ },
|
||||
};
|
||||
|
||||
--
|
||||
2.13.0
|
||||
|
|
@ -1,53 +0,0 @@
|
|||
From 2a99775c336303d2efc43eab4f24b34722a28faa Mon Sep 17 00:00:00 2001
|
||||
From: "Sergei A. Trusov" <sergei.a.trusov@ya.ru>
|
||||
Date: Tue, 20 Jun 2017 18:08:35 +0200
|
||||
Subject: [PATCH 11/16] Input: goodix: Add support for capacitive home button
|
||||
|
||||
On some x86 tablets with a Goodix touchscreen, the Windows logo on the
|
||||
front is a capacitive home button. Touching this button results in a touch
|
||||
with bit 4 of the first byte set, while only the lower 4 bits (0-3) are
|
||||
used to indicate the number of touches.
|
||||
|
||||
Report a KEY_LEFTMETA press when this happens.
|
||||
|
||||
Note that the hardware might support more than one button, in which
|
||||
case the "id" byte of coor_data would identify the button in question.
|
||||
This is not implemented as we don't have access to hardware with
|
||||
multiple buttons.
|
||||
|
||||
Signed-off-by: Sergei A. Trusov <sergei.a.trusov@ya.ru>
|
||||
Acked-by: Bastien Nocera <hadess@hadess.net>
|
||||
---
|
||||
drivers/input/touchscreen/goodix.c | 9 +++++++++
|
||||
1 file changed, 9 insertions(+)
|
||||
|
||||
diff --git a/drivers/input/touchscreen/goodix.c b/drivers/input/touchscreen/goodix.c
|
||||
index 240b16f3ee97..903137d9cf7d 100644
|
||||
--- a/drivers/input/touchscreen/goodix.c
|
||||
+++ b/drivers/input/touchscreen/goodix.c
|
||||
@@ -267,6 +267,12 @@ static void goodix_process_events(struct goodix_ts_data *ts)
|
||||
if (touch_num < 0)
|
||||
return;
|
||||
|
||||
+ /*
|
||||
+ * Bit 4 of the first byte reports the status of the capacitive
|
||||
+ * Windows/Home button.
|
||||
+ */
|
||||
+ input_report_key(ts->input_dev, KEY_LEFTMETA, !!(point_data[0] & BIT(4)));
|
||||
+
|
||||
for (i = 0; i < touch_num; i++)
|
||||
goodix_ts_report_touch(ts,
|
||||
&point_data[1 + GOODIX_CONTACT_SIZE * i]);
|
||||
@@ -612,6 +618,9 @@ static int goodix_request_input_dev(struct goodix_ts_data *ts)
|
||||
ts->input_dev->id.product = ts->id;
|
||||
ts->input_dev->id.version = ts->version;
|
||||
|
||||
+ /* Capacitive Windows/Home button on some devices */
|
||||
+ input_set_capability(ts->input_dev, EV_KEY, KEY_LEFTMETA);
|
||||
+
|
||||
error = input_register_device(ts->input_dev);
|
||||
if (error) {
|
||||
dev_err(&ts->client->dev,
|
||||
--
|
||||
2.13.0
|
||||
|
|
@ -1,150 +0,0 @@
|
|||
From 02b823a4d28ffb5fde5192799abd934d9de95630 Mon Sep 17 00:00:00 2001
|
||||
From: Hans de Goede <hdegoede@redhat.com>
|
||||
Date: Fri, 6 Jan 2017 20:08:11 +0100
|
||||
Subject: [PATCH 12/16] Input: gpio_keys - Do not report wake button presses as
|
||||
evdev events
|
||||
|
||||
If a button is a wake button, it may still be bouncing from the press
|
||||
to wakeup the device by the time the gpio interrupts get enabled again
|
||||
and / or the gpio_keys_report_state call from gpio_keys_resume may
|
||||
find the button still pressed and report this as a new press.
|
||||
|
||||
This is undesirable, esp. since the powerbutton on tablets is typically
|
||||
a wakeup source and uses the gpio_keys driver on some tablets, leading
|
||||
to userspace immediately re-suspending the tablet after the powerbutton
|
||||
is pressed, due to it seeing a powerbutton press.
|
||||
|
||||
This commit ignores wakeup button presses for the first 1 second after
|
||||
resume (and while resumed, as the workqueue may run before the resume
|
||||
function runs), avoiding this problem.
|
||||
|
||||
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
|
||||
---
|
||||
Note: maybe we should make WAKE_DEBOUNCE part of gpio_keys_button and
|
||||
only do this when drivers / platform-data set this to a non-zero value ?
|
||||
---
|
||||
drivers/input/keyboard/gpio_keys.c | 49 ++++++++++++++++++++++++++++++++++++--
|
||||
1 file changed, 47 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c
|
||||
index da3d362f21b1..e1488b534e7d 100644
|
||||
--- a/drivers/input/keyboard/gpio_keys.c
|
||||
+++ b/drivers/input/keyboard/gpio_keys.c
|
||||
@@ -31,6 +31,8 @@
|
||||
#include <linux/of_irq.h>
|
||||
#include <linux/spinlock.h>
|
||||
|
||||
+#define WAKE_DEBOUNCE msecs_to_jiffies(1000)
|
||||
+
|
||||
struct gpio_button_data {
|
||||
const struct gpio_keys_button *button;
|
||||
struct input_dev *input;
|
||||
@@ -44,10 +46,14 @@ struct gpio_button_data {
|
||||
struct delayed_work work;
|
||||
unsigned int software_debounce; /* in msecs, for GPIO-driven buttons */
|
||||
|
||||
+ unsigned long resume_time; /* in jiffies, for wakeup buttons */
|
||||
+
|
||||
unsigned int irq;
|
||||
spinlock_t lock;
|
||||
bool disabled;
|
||||
bool key_pressed;
|
||||
+ bool suspended;
|
||||
+ bool resume_time_valid;
|
||||
};
|
||||
|
||||
struct gpio_keys_drvdata {
|
||||
@@ -356,6 +362,27 @@ static struct attribute_group gpio_keys_attr_group = {
|
||||
.attrs = gpio_keys_attrs,
|
||||
};
|
||||
|
||||
+static bool gpio_keys_ignore_wakeup_button_press(struct gpio_button_data *bdata)
|
||||
+{
|
||||
+ unsigned long flags;
|
||||
+ bool ret = false;
|
||||
+
|
||||
+ if (!bdata->button->wakeup)
|
||||
+ return ret;
|
||||
+
|
||||
+ spin_lock_irqsave(&bdata->lock, flags);
|
||||
+
|
||||
+ if (bdata->suspended)
|
||||
+ ret = true; /* Our resume method did not run yet */
|
||||
+ else if (bdata->resume_time_valid &&
|
||||
+ time_before(jiffies, bdata->resume_time + WAKE_DEBOUNCE))
|
||||
+ ret = true; /* Assume this is a wakeup press and ignore */
|
||||
+
|
||||
+ spin_unlock_irqrestore(&bdata->lock, flags);
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
static void gpio_keys_gpio_report_event(struct gpio_button_data *bdata)
|
||||
{
|
||||
const struct gpio_keys_button *button = bdata->button;
|
||||
@@ -370,6 +397,9 @@ static void gpio_keys_gpio_report_event(struct gpio_button_data *bdata)
|
||||
return;
|
||||
}
|
||||
|
||||
+ if (state && gpio_keys_ignore_wakeup_button_press(bdata))
|
||||
+ return;
|
||||
+
|
||||
if (type == EV_ABS) {
|
||||
if (state)
|
||||
input_event(input, type, button->code, button->value);
|
||||
@@ -429,6 +459,9 @@ static irqreturn_t gpio_keys_irq_isr(int irq, void *dev_id)
|
||||
|
||||
BUG_ON(irq != bdata->irq);
|
||||
|
||||
+ if (gpio_keys_ignore_wakeup_button_press(bdata))
|
||||
+ return IRQ_HANDLED;
|
||||
+
|
||||
spin_lock_irqsave(&bdata->lock, flags);
|
||||
|
||||
if (!bdata->key_pressed) {
|
||||
@@ -848,13 +881,18 @@ static int __maybe_unused gpio_keys_suspend(struct device *dev)
|
||||
{
|
||||
struct gpio_keys_drvdata *ddata = dev_get_drvdata(dev);
|
||||
struct input_dev *input = ddata->input;
|
||||
+ unsigned long flags;
|
||||
int i;
|
||||
|
||||
if (device_may_wakeup(dev)) {
|
||||
for (i = 0; i < ddata->pdata->nbuttons; i++) {
|
||||
struct gpio_button_data *bdata = &ddata->data[i];
|
||||
- if (bdata->button->wakeup)
|
||||
+ if (bdata->button->wakeup) {
|
||||
+ spin_lock_irqsave(&bdata->lock, flags);
|
||||
+ bdata->suspended = true;
|
||||
+ spin_unlock_irqrestore(&bdata->lock, flags);
|
||||
enable_irq_wake(bdata->irq);
|
||||
+ }
|
||||
}
|
||||
} else {
|
||||
mutex_lock(&input->mutex);
|
||||
@@ -870,14 +908,21 @@ static int __maybe_unused gpio_keys_resume(struct device *dev)
|
||||
{
|
||||
struct gpio_keys_drvdata *ddata = dev_get_drvdata(dev);
|
||||
struct input_dev *input = ddata->input;
|
||||
+ unsigned long flags;
|
||||
int error = 0;
|
||||
int i;
|
||||
|
||||
if (device_may_wakeup(dev)) {
|
||||
for (i = 0; i < ddata->pdata->nbuttons; i++) {
|
||||
struct gpio_button_data *bdata = &ddata->data[i];
|
||||
- if (bdata->button->wakeup)
|
||||
+ if (bdata->button->wakeup) {
|
||||
disable_irq_wake(bdata->irq);
|
||||
+ spin_lock_irqsave(&bdata->lock, flags);
|
||||
+ bdata->resume_time = jiffies;
|
||||
+ bdata->resume_time_valid = true;
|
||||
+ bdata->suspended = false;
|
||||
+ spin_unlock_irqrestore(&bdata->lock, flags);
|
||||
+ }
|
||||
}
|
||||
} else {
|
||||
mutex_lock(&input->mutex);
|
||||
--
|
||||
2.13.0
|
||||
|
|
@ -1,32 +0,0 @@
|
|||
From bf3e9581e10a19b2ce77a45fe001116d269b4c7f Mon Sep 17 00:00:00 2001
|
||||
From: Hans de Goede <hdegoede@redhat.com>
|
||||
Date: Sun, 18 Jun 2017 12:47:38 +0200
|
||||
Subject: [PATCH 13/16] iio: accel: bmc150: Add support for BOSC0200 ACPI
|
||||
device id
|
||||
|
||||
Add support for the BOSC0200 ACPI device id used on some x86 tablets.
|
||||
note driver_data is not set to a specific model, driver_data is not
|
||||
used anyways (instead detection is done on the chip_id reg) and the
|
||||
2 tablets with a BOSC0200 ACPI device id I've have 2 different chips,
|
||||
one has a BMA250E, the other a BMA222E.
|
||||
|
||||
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
|
||||
---
|
||||
drivers/iio/accel/bmc150-accel-i2c.c | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
diff --git a/drivers/iio/accel/bmc150-accel-i2c.c b/drivers/iio/accel/bmc150-accel-i2c.c
|
||||
index 8ca8041267ef..f85014fbaa12 100644
|
||||
--- a/drivers/iio/accel/bmc150-accel-i2c.c
|
||||
+++ b/drivers/iio/accel/bmc150-accel-i2c.c
|
||||
@@ -64,6 +64,7 @@ static const struct acpi_device_id bmc150_accel_acpi_match[] = {
|
||||
{"BMA250E", bma250e},
|
||||
{"BMA222E", bma222e},
|
||||
{"BMA0280", bma280},
|
||||
+ {"BOSC0200"},
|
||||
{ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(acpi, bmc150_accel_acpi_match);
|
||||
--
|
||||
2.13.0
|
||||
|
|
@ -1,143 +0,0 @@
|
|||
From 51eb7454942c68c84b82782e47637de3ba37f113 Mon Sep 17 00:00:00 2001
|
||||
From: Adrian Hunter <adrian.hunter@intel.com>
|
||||
Date: Wed, 21 Jun 2017 15:08:39 +0300
|
||||
Subject: [PATCH 14/16] mmc: sdhci-acpi: Workaround conflict with PCI wifi on
|
||||
GPD Win handheld
|
||||
|
||||
GPDwin uses PCI wifi which conflicts with SDIO's use of
|
||||
acpi_device_fix_up_power() on child device nodes. Specifically
|
||||
acpi_device_fix_up_power() causes the wifi module to get turned off.
|
||||
Identifying GPDwin is problematic, but since SDIO is only used for wifi,
|
||||
the presence of the PCI wifi card in the expected slot with an ACPI
|
||||
companion node, is used to indicate that acpi_device_fix_up_power() should
|
||||
be avoided.
|
||||
|
||||
Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
|
||||
Acked-by: Hans de Goede <hdegoede@redhat.com>
|
||||
Tested-by: Hans de Goede <hdegoede@redhat.com>
|
||||
Cc: stable@vger.kernel.org
|
||||
---
|
||||
drivers/mmc/host/sdhci-acpi.c | 70 +++++++++++++++++++++++++++++++++++++++----
|
||||
1 file changed, 64 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/drivers/mmc/host/sdhci-acpi.c b/drivers/mmc/host/sdhci-acpi.c
|
||||
index c6a9a1bfaa22..b3fb155f50e4 100644
|
||||
--- a/drivers/mmc/host/sdhci-acpi.c
|
||||
+++ b/drivers/mmc/host/sdhci-acpi.c
|
||||
@@ -45,6 +45,7 @@
|
||||
#include <asm/cpu_device_id.h>
|
||||
#include <asm/intel-family.h>
|
||||
#include <asm/iosf_mbi.h>
|
||||
+#include <linux/pci.h>
|
||||
#endif
|
||||
|
||||
#include "sdhci.h"
|
||||
@@ -134,6 +135,16 @@ static bool sdhci_acpi_byt(void)
|
||||
return x86_match_cpu(byt);
|
||||
}
|
||||
|
||||
+static bool sdhci_acpi_cht(void)
|
||||
+{
|
||||
+ static const struct x86_cpu_id cht[] = {
|
||||
+ { X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_AIRMONT },
|
||||
+ {}
|
||||
+ };
|
||||
+
|
||||
+ return x86_match_cpu(cht);
|
||||
+}
|
||||
+
|
||||
#define BYT_IOSF_SCCEP 0x63
|
||||
#define BYT_IOSF_OCP_NETCTRL0 0x1078
|
||||
#define BYT_IOSF_OCP_TIMEOUT_BASE GENMASK(10, 8)
|
||||
@@ -178,6 +189,45 @@ static bool sdhci_acpi_byt_defer(struct device *dev)
|
||||
return false;
|
||||
}
|
||||
|
||||
+static bool sdhci_acpi_cht_pci_wifi(unsigned int vendor, unsigned int device,
|
||||
+ unsigned int slot, unsigned int parent_slot)
|
||||
+{
|
||||
+ struct pci_dev *dev, *parent, *from = NULL;
|
||||
+
|
||||
+ while (1) {
|
||||
+ dev = pci_get_device(vendor, device, from);
|
||||
+ pci_dev_put(from);
|
||||
+ if (!dev)
|
||||
+ break;
|
||||
+ parent = pci_upstream_bridge(dev);
|
||||
+ if (ACPI_COMPANION(&dev->dev) && PCI_SLOT(dev->devfn) == slot &&
|
||||
+ parent && PCI_SLOT(parent->devfn) == parent_slot &&
|
||||
+ !pci_upstream_bridge(parent)) {
|
||||
+ pci_dev_put(dev);
|
||||
+ return true;
|
||||
+ }
|
||||
+ from = dev;
|
||||
+ }
|
||||
+
|
||||
+ return false;
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * GPDwin uses PCI wifi which conflicts with SDIO's use of
|
||||
+ * acpi_device_fix_up_power() on child device nodes. Identifying GPDwin is
|
||||
+ * problematic, but since SDIO is only used for wifi, the presence of the PCI
|
||||
+ * wifi card in the expected slot with an ACPI companion node, is used to
|
||||
+ * indicate that acpi_device_fix_up_power() should be avoided.
|
||||
+ */
|
||||
+static inline bool sdhci_acpi_no_fixup_child_power(const char *hid,
|
||||
+ const char *uid)
|
||||
+{
|
||||
+ return sdhci_acpi_cht() &&
|
||||
+ !strcmp(hid, "80860F14") &&
|
||||
+ !strcmp(uid, "2") &&
|
||||
+ sdhci_acpi_cht_pci_wifi(0x14e4, 0x43ec, 0, 28);
|
||||
+}
|
||||
+
|
||||
#else
|
||||
|
||||
static inline void sdhci_acpi_byt_setting(struct device *dev)
|
||||
@@ -189,6 +239,12 @@ static inline bool sdhci_acpi_byt_defer(struct device *dev)
|
||||
return false;
|
||||
}
|
||||
|
||||
+static inline bool sdhci_acpi_no_fixup_child_power(const char *hid,
|
||||
+ const char *uid)
|
||||
+{
|
||||
+ return false;
|
||||
+}
|
||||
+
|
||||
#endif
|
||||
|
||||
static int bxt_get_cd(struct mmc_host *mmc)
|
||||
@@ -390,11 +446,16 @@ static int sdhci_acpi_probe(struct platform_device *pdev)
|
||||
if (acpi_bus_get_device(handle, &device))
|
||||
return -ENODEV;
|
||||
|
||||
+ hid = acpi_device_hid(device);
|
||||
+ uid = device->pnp.unique_id;
|
||||
+
|
||||
/* Power on the SDHCI controller and its children */
|
||||
acpi_device_fix_up_power(device);
|
||||
- list_for_each_entry(child, &device->children, node)
|
||||
- if (child->status.present && child->status.enabled)
|
||||
- acpi_device_fix_up_power(child);
|
||||
+ if (!sdhci_acpi_no_fixup_child_power(hid, uid)) {
|
||||
+ list_for_each_entry(child, &device->children, node)
|
||||
+ if (child->status.present && child->status.enabled)
|
||||
+ acpi_device_fix_up_power(child);
|
||||
+ }
|
||||
|
||||
if (acpi_bus_get_status(device) || !device->status.present)
|
||||
return -ENODEV;
|
||||
@@ -402,9 +463,6 @@ static int sdhci_acpi_probe(struct platform_device *pdev)
|
||||
if (sdhci_acpi_byt_defer(dev))
|
||||
return -EPROBE_DEFER;
|
||||
|
||||
- hid = acpi_device_hid(device);
|
||||
- uid = device->pnp.unique_id;
|
||||
-
|
||||
iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
if (!iomem)
|
||||
return -ENOMEM;
|
||||
--
|
||||
2.13.0
|
||||
|
|
@ -1,410 +0,0 @@
|
|||
From bd0d7169342e47919f68e75d659968f02b62f84b Mon Sep 17 00:00:00 2001
|
||||
From: Hans de Goede <hdegoede@redhat.com>
|
||||
Date: Fri, 3 Mar 2017 23:48:50 +0100
|
||||
Subject: [PATCH 15/16] i2c-cht-wc: Add Intel Cherry Trail Whiskey Cove SMBUS
|
||||
controller driver
|
||||
|
||||
The Intel Cherry Trail Whiskey Cove PMIC does not contain a builtin
|
||||
battery charger, instead boards with this PMIC use an external TI
|
||||
bq24292i charger IC, which is connected to a SMBUS controller built into
|
||||
the PMIC.
|
||||
|
||||
This commit adds an i2c-bus driver for the PMIC's builtin SMBUS
|
||||
controller. The probe function for this i2c-bus will also register an
|
||||
i2c-client for the TI bq24292i charger after the i2c-bus has been
|
||||
registered.
|
||||
|
||||
Note that several device-properties are set on the client-device to
|
||||
tell the bq24190 power-supply driver to integrate the Whiskey Cove PMIC
|
||||
and e.g. use the PMIC's BC1.2 detection (through extcon) to determine
|
||||
the maximum input current.
|
||||
|
||||
Cc: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
|
||||
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
|
||||
---
|
||||
Changes in v2:
|
||||
-Various style (mostly captialization and variable name) fixes
|
||||
-Use device-properties instead of platform_data for the i2c_board_info
|
||||
---
|
||||
drivers/i2c/busses/Kconfig | 8 +
|
||||
drivers/i2c/busses/Makefile | 1 +
|
||||
drivers/i2c/busses/i2c-cht-wc.c | 336 ++++++++++++++++++++++++++++++++++++++++
|
||||
3 files changed, 345 insertions(+)
|
||||
create mode 100644 drivers/i2c/busses/i2c-cht-wc.c
|
||||
|
||||
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
|
||||
index 144cbadc7c72..18c96178b177 100644
|
||||
--- a/drivers/i2c/busses/Kconfig
|
||||
+++ b/drivers/i2c/busses/Kconfig
|
||||
@@ -187,6 +187,14 @@ config I2C_PIIX4
|
||||
This driver can also be built as a module. If so, the module
|
||||
will be called i2c-piix4.
|
||||
|
||||
+config I2C_CHT_WC
|
||||
+ tristate "Intel Cherry Trail Whiskey Cove PMIC smbus controller"
|
||||
+ depends on INTEL_SOC_PMIC_CHTWC
|
||||
+ help
|
||||
+ If you say yes to this option, support will be included for the
|
||||
+ SMBus controller found in the Intel Cherry Trail Whiskey Cove PMIC
|
||||
+ found on some Intel Cherry Trail systems.
|
||||
+
|
||||
config I2C_NFORCE2
|
||||
tristate "Nvidia nForce2, nForce3 and nForce4"
|
||||
depends on PCI
|
||||
diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
|
||||
index 30b60855fbcd..f6443fa44f61 100644
|
||||
--- a/drivers/i2c/busses/Makefile
|
||||
+++ b/drivers/i2c/busses/Makefile
|
||||
@@ -12,6 +12,7 @@ obj-$(CONFIG_I2C_ALI15X3) += i2c-ali15x3.o
|
||||
obj-$(CONFIG_I2C_AMD756) += i2c-amd756.o
|
||||
obj-$(CONFIG_I2C_AMD756_S4882) += i2c-amd756-s4882.o
|
||||
obj-$(CONFIG_I2C_AMD8111) += i2c-amd8111.o
|
||||
+obj-$(CONFIG_I2C_CHT_WC) += i2c-cht-wc.o
|
||||
obj-$(CONFIG_I2C_I801) += i2c-i801.o
|
||||
obj-$(CONFIG_I2C_ISCH) += i2c-isch.o
|
||||
obj-$(CONFIG_I2C_ISMT) += i2c-ismt.o
|
||||
diff --git a/drivers/i2c/busses/i2c-cht-wc.c b/drivers/i2c/busses/i2c-cht-wc.c
|
||||
new file mode 100644
|
||||
index 000000000000..ccf0785bcb75
|
||||
--- /dev/null
|
||||
+++ b/drivers/i2c/busses/i2c-cht-wc.c
|
||||
@@ -0,0 +1,336 @@
|
||||
+/*
|
||||
+ * Intel CHT Whiskey Cove PMIC I2C Master driver
|
||||
+ * Copyright (C) 2017 Hans de Goede <hdegoede@redhat.com>
|
||||
+ *
|
||||
+ * Based on various non upstream patches to support the CHT Whiskey Cove PMIC:
|
||||
+ * Copyright (C) 2011 - 2014 Intel Corporation. All rights reserved.
|
||||
+ *
|
||||
+ * This program is free software; you can redistribute it and/or
|
||||
+ * modify it under the terms of the GNU General Public License version
|
||||
+ * 2 as published by the Free Software Foundation.
|
||||
+ *
|
||||
+ * This program is distributed in the hope that it will be useful,
|
||||
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
+ * GNU General Public License for more details.
|
||||
+ */
|
||||
+
|
||||
+#include <linux/completion.h>
|
||||
+#include <linux/delay.h>
|
||||
+#include <linux/i2c.h>
|
||||
+#include <linux/interrupt.h>
|
||||
+#include <linux/irq.h>
|
||||
+#include <linux/irqdomain.h>
|
||||
+#include <linux/mfd/intel_soc_pmic.h>
|
||||
+#include <linux/module.h>
|
||||
+#include <linux/platform_device.h>
|
||||
+#include <linux/slab.h>
|
||||
+
|
||||
+#define CHT_WC_I2C_CTRL 0x5e24
|
||||
+#define CHT_WC_I2C_CTRL_WR BIT(0)
|
||||
+#define CHT_WC_I2C_CTRL_RD BIT(1)
|
||||
+#define CHT_WC_I2C_CLIENT_ADDR 0x5e25
|
||||
+#define CHT_WC_I2C_REG_OFFSET 0x5e26
|
||||
+#define CHT_WC_I2C_WRDATA 0x5e27
|
||||
+#define CHT_WC_I2C_RDDATA 0x5e28
|
||||
+
|
||||
+#define CHT_WC_EXTCHGRIRQ 0x6e0a
|
||||
+#define CHT_WC_EXTCHGRIRQ_CLIENT_IRQ BIT(0)
|
||||
+#define CHT_WC_EXTCHGRIRQ_WRITE_IRQ BIT(1)
|
||||
+#define CHT_WC_EXTCHGRIRQ_READ_IRQ BIT(2)
|
||||
+#define CHT_WC_EXTCHGRIRQ_NACK_IRQ BIT(3)
|
||||
+#define CHT_WC_EXTCHGRIRQ_ADAP_IRQMASK ((u8)GENMASK(3, 1))
|
||||
+#define CHT_WC_EXTCHGRIRQ_MSK 0x6e17
|
||||
+
|
||||
+struct cht_wc_i2c_adap {
|
||||
+ struct i2c_adapter adapter;
|
||||
+ wait_queue_head_t wait;
|
||||
+ struct irq_chip irqchip;
|
||||
+ struct mutex irqchip_lock;
|
||||
+ struct regmap *regmap;
|
||||
+ struct irq_domain *irq_domain;
|
||||
+ struct i2c_client *client;
|
||||
+ int client_irq;
|
||||
+ u8 irq_mask;
|
||||
+ u8 old_irq_mask;
|
||||
+ bool nack;
|
||||
+ bool done;
|
||||
+};
|
||||
+
|
||||
+static irqreturn_t cht_wc_i2c_adap_thread_handler(int id, void *data)
|
||||
+{
|
||||
+ struct cht_wc_i2c_adap *adap = data;
|
||||
+ int ret, reg;
|
||||
+
|
||||
+ /* Read IRQs */
|
||||
+ ret = regmap_read(adap->regmap, CHT_WC_EXTCHGRIRQ, ®);
|
||||
+ if (ret) {
|
||||
+ dev_err(&adap->adapter.dev, "Error reading extchgrirq reg\n");
|
||||
+ return IRQ_NONE;
|
||||
+ }
|
||||
+
|
||||
+ reg &= ~adap->irq_mask;
|
||||
+
|
||||
+ /*
|
||||
+ * Immediately ack IRQs, so that if new IRQs arrives while we're
|
||||
+ * handling the previous ones our irq will re-trigger when we're done.
|
||||
+ */
|
||||
+ ret = regmap_write(adap->regmap, CHT_WC_EXTCHGRIRQ, reg);
|
||||
+ if (ret)
|
||||
+ dev_err(&adap->adapter.dev, "Error writing extchgrirq reg\n");
|
||||
+
|
||||
+ /*
|
||||
+ * Do NOT use handle_nested_irq here, the client irq handler will
|
||||
+ * likely want to do i2c transfers and the i2c controller uses this
|
||||
+ * interrupt handler as well, so running the client irq handler from
|
||||
+ * this thread will cause things to lock up.
|
||||
+ */
|
||||
+ if (reg & CHT_WC_EXTCHGRIRQ_CLIENT_IRQ) {
|
||||
+ /*
|
||||
+ * generic_handle_irq expects local IRQs to be disabled
|
||||
+ * as normally it is called from interrupt context.
|
||||
+ */
|
||||
+ local_irq_disable();
|
||||
+ generic_handle_irq(adap->client_irq);
|
||||
+ local_irq_enable();
|
||||
+ }
|
||||
+
|
||||
+ if (reg & CHT_WC_EXTCHGRIRQ_ADAP_IRQMASK) {
|
||||
+ adap->nack = !!(reg & CHT_WC_EXTCHGRIRQ_NACK_IRQ);
|
||||
+ adap->done = true;
|
||||
+ wake_up(&adap->wait);
|
||||
+ }
|
||||
+
|
||||
+ return IRQ_HANDLED;
|
||||
+}
|
||||
+
|
||||
+static u32 cht_wc_i2c_adap_master_func(struct i2c_adapter *adap)
|
||||
+{
|
||||
+ /* This i2c adapter only supports SMBUS byte transfers */
|
||||
+ return I2C_FUNC_SMBUS_BYTE_DATA;
|
||||
+}
|
||||
+
|
||||
+static int cht_wc_i2c_adap_smbus_xfer(struct i2c_adapter *_adap, u16 addr,
|
||||
+ unsigned short flags, char read_write,
|
||||
+ u8 command, int size,
|
||||
+ union i2c_smbus_data *data)
|
||||
+{
|
||||
+ struct cht_wc_i2c_adap *adap = i2c_get_adapdata(_adap);
|
||||
+ int ret, reg;
|
||||
+
|
||||
+ adap->nack = false;
|
||||
+ adap->done = false;
|
||||
+
|
||||
+ ret = regmap_write(adap->regmap, CHT_WC_I2C_CLIENT_ADDR, addr);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ if (read_write == I2C_SMBUS_WRITE) {
|
||||
+ ret = regmap_write(adap->regmap, CHT_WC_I2C_WRDATA, data->byte);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ ret = regmap_write(adap->regmap, CHT_WC_I2C_REG_OFFSET, command);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ ret = regmap_write(adap->regmap, CHT_WC_I2C_CTRL,
|
||||
+ (read_write == I2C_SMBUS_WRITE) ?
|
||||
+ CHT_WC_I2C_CTRL_WR : CHT_WC_I2C_CTRL_RD);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ /* 3 second timeout, during cable plug the PMIC responds quite slow */
|
||||
+ ret = wait_event_timeout(adap->wait, adap->done, 3 * HZ);
|
||||
+ if (ret == 0)
|
||||
+ return -ETIMEDOUT;
|
||||
+ if (adap->nack)
|
||||
+ return -EIO;
|
||||
+
|
||||
+ if (read_write == I2C_SMBUS_READ) {
|
||||
+ ret = regmap_read(adap->regmap, CHT_WC_I2C_RDDATA, ®);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ data->byte = reg;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static const struct i2c_algorithm cht_wc_i2c_adap_algo = {
|
||||
+ .functionality = cht_wc_i2c_adap_master_func,
|
||||
+ .smbus_xfer = cht_wc_i2c_adap_smbus_xfer,
|
||||
+};
|
||||
+
|
||||
+/**** irqchip for the client connected to the extchgr i2c adapter ****/
|
||||
+static void cht_wc_i2c_irq_lock(struct irq_data *data)
|
||||
+{
|
||||
+ struct cht_wc_i2c_adap *adap = irq_data_get_irq_chip_data(data);
|
||||
+
|
||||
+ mutex_lock(&adap->irqchip_lock);
|
||||
+}
|
||||
+
|
||||
+static void cht_wc_i2c_irq_sync_unlock(struct irq_data *data)
|
||||
+{
|
||||
+ struct cht_wc_i2c_adap *adap = irq_data_get_irq_chip_data(data);
|
||||
+ int ret;
|
||||
+
|
||||
+ if (adap->irq_mask != adap->old_irq_mask) {
|
||||
+ ret = regmap_write(adap->regmap, CHT_WC_EXTCHGRIRQ_MSK,
|
||||
+ adap->irq_mask);
|
||||
+ if (ret == 0)
|
||||
+ adap->old_irq_mask = adap->irq_mask;
|
||||
+ else
|
||||
+ dev_err(&adap->adapter.dev, "Error writing EXTCHGRIRQ_MSK\n");
|
||||
+ }
|
||||
+
|
||||
+ mutex_unlock(&adap->irqchip_lock);
|
||||
+}
|
||||
+
|
||||
+static void cht_wc_i2c_irq_enable(struct irq_data *data)
|
||||
+{
|
||||
+ struct cht_wc_i2c_adap *adap = irq_data_get_irq_chip_data(data);
|
||||
+
|
||||
+ adap->irq_mask &= ~CHT_WC_EXTCHGRIRQ_CLIENT_IRQ;
|
||||
+}
|
||||
+
|
||||
+static void cht_wc_i2c_irq_disable(struct irq_data *data)
|
||||
+{
|
||||
+ struct cht_wc_i2c_adap *adap = irq_data_get_irq_chip_data(data);
|
||||
+
|
||||
+ adap->irq_mask |= CHT_WC_EXTCHGRIRQ_CLIENT_IRQ;
|
||||
+}
|
||||
+
|
||||
+static const struct irq_chip cht_wc_i2c_irq_chip = {
|
||||
+ .irq_bus_lock = cht_wc_i2c_irq_lock,
|
||||
+ .irq_bus_sync_unlock = cht_wc_i2c_irq_sync_unlock,
|
||||
+ .irq_disable = cht_wc_i2c_irq_disable,
|
||||
+ .irq_enable = cht_wc_i2c_irq_enable,
|
||||
+ .name = "cht_wc_ext_chrg_irq_chip",
|
||||
+};
|
||||
+
|
||||
+static const struct property_entry bq24190_props[] = {
|
||||
+ PROPERTY_ENTRY_STRING("extcon-name", "cht_wcove_pwrsrc"),
|
||||
+ PROPERTY_ENTRY_BOOL("omit-battery-class"),
|
||||
+ PROPERTY_ENTRY_BOOL("disable-reset"),
|
||||
+ { }
|
||||
+};
|
||||
+
|
||||
+static int cht_wc_i2c_adap_i2c_probe(struct platform_device *pdev)
|
||||
+{
|
||||
+ struct intel_soc_pmic *pmic = dev_get_drvdata(pdev->dev.parent);
|
||||
+ struct cht_wc_i2c_adap *adap;
|
||||
+ struct i2c_board_info board_info = {
|
||||
+ .type = "bq24190",
|
||||
+ .addr = 0x6b,
|
||||
+ .properties = bq24190_props,
|
||||
+ };
|
||||
+ int ret, irq;
|
||||
+
|
||||
+ irq = platform_get_irq(pdev, 0);
|
||||
+ if (irq < 0) {
|
||||
+ dev_err(&pdev->dev, "Error missing irq resource\n");
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ adap = devm_kzalloc(&pdev->dev, sizeof(*adap), GFP_KERNEL);
|
||||
+ if (!adap)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ init_waitqueue_head(&adap->wait);
|
||||
+ mutex_init(&adap->irqchip_lock);
|
||||
+ adap->irqchip = cht_wc_i2c_irq_chip;
|
||||
+ adap->regmap = pmic->regmap;
|
||||
+ adap->adapter.owner = THIS_MODULE;
|
||||
+ adap->adapter.class = I2C_CLASS_HWMON;
|
||||
+ adap->adapter.algo = &cht_wc_i2c_adap_algo;
|
||||
+ strlcpy(adap->adapter.name, "PMIC I2C Adapter",
|
||||
+ sizeof(adap->adapter.name));
|
||||
+ adap->adapter.dev.parent = &pdev->dev;
|
||||
+
|
||||
+ /* Clear and activate i2c-adapter interrupts, disable client IRQ */
|
||||
+ adap->old_irq_mask = adap->irq_mask = ~CHT_WC_EXTCHGRIRQ_ADAP_IRQMASK;
|
||||
+ ret = regmap_write(adap->regmap, CHT_WC_EXTCHGRIRQ, ~adap->irq_mask);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ ret = regmap_write(adap->regmap, CHT_WC_EXTCHGRIRQ_MSK, adap->irq_mask);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ /* Alloc and register client IRQ */
|
||||
+ adap->irq_domain = irq_domain_add_linear(pdev->dev.of_node, 1,
|
||||
+ &irq_domain_simple_ops, NULL);
|
||||
+ if (!adap->irq_domain)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ adap->client_irq = irq_create_mapping(adap->irq_domain, 0);
|
||||
+ if (!adap->client_irq) {
|
||||
+ ret = -ENOMEM;
|
||||
+ goto remove_irq_domain;
|
||||
+ }
|
||||
+
|
||||
+ irq_set_chip_data(adap->client_irq, adap);
|
||||
+ irq_set_chip_and_handler(adap->client_irq, &adap->irqchip,
|
||||
+ handle_simple_irq);
|
||||
+
|
||||
+ ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
|
||||
+ cht_wc_i2c_adap_thread_handler,
|
||||
+ IRQF_ONESHOT, "PMIC I2C Adapter", adap);
|
||||
+ if (ret)
|
||||
+ goto remove_irq_domain;
|
||||
+
|
||||
+ i2c_set_adapdata(&adap->adapter, adap);
|
||||
+ ret = i2c_add_adapter(&adap->adapter);
|
||||
+ if (ret)
|
||||
+ goto remove_irq_domain;
|
||||
+
|
||||
+ board_info.irq = adap->client_irq;
|
||||
+ adap->client = i2c_new_device(&adap->adapter, &board_info);
|
||||
+ if (!adap->client) {
|
||||
+ ret = -ENOMEM;
|
||||
+ goto del_adapter;
|
||||
+ }
|
||||
+
|
||||
+ platform_set_drvdata(pdev, adap);
|
||||
+ return 0;
|
||||
+
|
||||
+del_adapter:
|
||||
+ i2c_del_adapter(&adap->adapter);
|
||||
+remove_irq_domain:
|
||||
+ irq_domain_remove(adap->irq_domain);
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static int cht_wc_i2c_adap_i2c_remove(struct platform_device *pdev)
|
||||
+{
|
||||
+ struct cht_wc_i2c_adap *adap = platform_get_drvdata(pdev);
|
||||
+
|
||||
+ i2c_unregister_device(adap->client);
|
||||
+ i2c_del_adapter(&adap->adapter);
|
||||
+ irq_domain_remove(adap->irq_domain);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static struct platform_device_id cht_wc_i2c_adap_id_table[] = {
|
||||
+ { .name = "cht_wcove_ext_chgr" },
|
||||
+ {},
|
||||
+};
|
||||
+MODULE_DEVICE_TABLE(platform, cht_wc_i2c_adap_id_table);
|
||||
+
|
||||
+struct platform_driver cht_wc_i2c_adap_driver = {
|
||||
+ .probe = cht_wc_i2c_adap_i2c_probe,
|
||||
+ .remove = cht_wc_i2c_adap_i2c_remove,
|
||||
+ .driver = {
|
||||
+ .name = "cht_wcove_ext_chgr",
|
||||
+ },
|
||||
+ .id_table = cht_wc_i2c_adap_id_table,
|
||||
+};
|
||||
+module_platform_driver(cht_wc_i2c_adap_driver);
|
||||
+
|
||||
+MODULE_DESCRIPTION("Intel CHT Whiskey Cove PMIC I2C Master driver");
|
||||
+MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
|
||||
+MODULE_LICENSE("GPL");
|
||||
--
|
||||
2.13.0
|
||||
|
|
@ -1,54 +0,0 @@
|
|||
From fd4fb1f6633b21042ff084868323e15e708fe1cd Mon Sep 17 00:00:00 2001
|
||||
From: Hans de Goede <hdegoede@redhat.com>
|
||||
Date: Sun, 1 Jan 2017 22:11:20 +0100
|
||||
Subject: [PATCH 16/16] Input: silead: Do not try to directly access the GPIO
|
||||
when using ACPI pm
|
||||
|
||||
On some x86 tablets we cannot directly access the GPIOs as they are
|
||||
claimed by the ACPI tables, so check it the i2c client is not being
|
||||
power-managed by ACPI before trying to get the power pin GPIO.
|
||||
|
||||
Note this is a workaround patch to fix this until Andy' gpiolib-ACPI
|
||||
patches which make gpiolib more strict land, once those are landed this
|
||||
patch is no longer needed.
|
||||
|
||||
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
|
||||
---
|
||||
drivers/input/touchscreen/silead.c | 22 ++++++++++++++++------
|
||||
1 file changed, 16 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/drivers/input/touchscreen/silead.c b/drivers/input/touchscreen/silead.c
|
||||
index c0ba40c09699..30fba3cbe277 100644
|
||||
--- a/drivers/input/touchscreen/silead.c
|
||||
+++ b/drivers/input/touchscreen/silead.c
|
||||
@@ -517,12 +518,21 @@ static int silead_ts_probe(struct i2c_client *client,
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
- /* Power GPIO pin */
|
||||
- data->gpio_power = devm_gpiod_get_optional(dev, "power", GPIOD_OUT_LOW);
|
||||
- if (IS_ERR(data->gpio_power)) {
|
||||
- if (PTR_ERR(data->gpio_power) != -EPROBE_DEFER)
|
||||
- dev_err(dev, "Shutdown GPIO request failed\n");
|
||||
- return PTR_ERR(data->gpio_power);
|
||||
+ /*
|
||||
+ * If device power is not managed by ACPI, get the power_gpio
|
||||
+ * and manage it ourselves.
|
||||
+ */
|
||||
+#ifdef CONFIG_ACPI
|
||||
+ if (!acpi_bus_power_manageable(ACPI_HANDLE(dev)))
|
||||
+#endif
|
||||
+ {
|
||||
+ data->gpio_power = devm_gpiod_get_optional(dev, "power",
|
||||
+ GPIOD_OUT_LOW);
|
||||
+ if (IS_ERR(data->gpio_power)) {
|
||||
+ if (PTR_ERR(data->gpio_power) != -EPROBE_DEFER)
|
||||
+ dev_err(dev, "Power GPIO request failed\n");
|
||||
+ return PTR_ERR(data->gpio_power);
|
||||
+ }
|
||||
}
|
||||
|
||||
error = silead_ts_setup(client);
|
||||
--
|
||||
2.13.0
|
||||
|
|
@ -1,296 +0,0 @@
|
|||
From patchwork Mon Nov 6 12:31:12 2017
|
||||
Content-Type: text/plain; charset="utf-8"
|
||||
MIME-Version: 1.0
|
||||
Content-Transfer-Encoding: 7bit
|
||||
Subject: [1/2] kvm: vmx: Reinstate support for CPUs without virtual NMI
|
||||
From: Paolo Bonzini <pbonzini@redhat.com>
|
||||
X-Patchwork-Id: 10043403
|
||||
Message-Id: <1509971473-74491-2-git-send-email-pbonzini@redhat.com>
|
||||
To: linux-kernel@vger.kernel.org, kvm@vger.kernel.org
|
||||
Cc: rkrcmar@redhat.com, stable@vger.kernel.org
|
||||
Date: Mon, 6 Nov 2017 13:31:12 +0100
|
||||
|
||||
This is more or less a revert of commit 2c82878b0cb3 ("KVM: VMX: require
|
||||
virtual NMI support", 2017-03-27); it turns out that Core 2 Duo machines
|
||||
only had virtual NMIs in some SKUs.
|
||||
|
||||
The revert is not trivial because in the meanwhile there have been several
|
||||
fixes to nested NMI injection. Therefore, the entire vNMI state is moved
|
||||
to struct loaded_vmcs.
|
||||
|
||||
Another change compared to before the patch is a simplification here:
|
||||
|
||||
if (unlikely(!cpu_has_virtual_nmis() && vmx->soft_vnmi_blocked &&
|
||||
!(is_guest_mode(vcpu) && nested_cpu_has_virtual_nmis(
|
||||
get_vmcs12(vcpu))))) {
|
||||
|
||||
The final condition here is always true (because nested_cpu_has_virtual_nmis
|
||||
is always false) and is removed.
|
||||
|
||||
Fixes: 2c82878b0cb38fd516fd612c67852a6bbf282003
|
||||
Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=1490803
|
||||
Cc: stable@vger.kernel.org
|
||||
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||
---
|
||||
arch/x86/kvm/vmx.c | 150 +++++++++++++++++++++++++++++++++++++----------------
|
||||
1 file changed, 106 insertions(+), 44 deletions(-)
|
||||
|
||||
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
|
||||
index e6c8ffa84968..d6b3b12ae1e2 100644
|
||||
--- a/arch/x86/kvm/vmx.c
|
||||
+++ b/arch/x86/kvm/vmx.c
|
||||
@@ -202,6 +202,10 @@ struct loaded_vmcs {
|
||||
bool nmi_known_unmasked;
|
||||
unsigned long vmcs_host_cr3; /* May not match real cr3 */
|
||||
unsigned long vmcs_host_cr4; /* May not match real cr4 */
|
||||
+ /* Support for vnmi-less CPUs */
|
||||
+ int soft_vnmi_blocked;
|
||||
+ ktime_t entry_time;
|
||||
+ s64 vnmi_blocked_time;
|
||||
struct list_head loaded_vmcss_on_cpu_link;
|
||||
};
|
||||
|
||||
@@ -1291,6 +1295,11 @@ static inline bool cpu_has_vmx_invpcid(void)
|
||||
SECONDARY_EXEC_ENABLE_INVPCID;
|
||||
}
|
||||
|
||||
+static inline bool cpu_has_virtual_nmis(void)
|
||||
+{
|
||||
+ return vmcs_config.pin_based_exec_ctrl & PIN_BASED_VIRTUAL_NMIS;
|
||||
+}
|
||||
+
|
||||
static inline bool cpu_has_vmx_wbinvd_exit(void)
|
||||
{
|
||||
return vmcs_config.cpu_based_2nd_exec_ctrl &
|
||||
@@ -1348,11 +1357,6 @@ static inline bool nested_cpu_has2(struct vmcs12 *vmcs12, u32 bit)
|
||||
(vmcs12->secondary_vm_exec_control & bit);
|
||||
}
|
||||
|
||||
-static inline bool nested_cpu_has_virtual_nmis(struct vmcs12 *vmcs12)
|
||||
-{
|
||||
- return vmcs12->pin_based_vm_exec_control & PIN_BASED_VIRTUAL_NMIS;
|
||||
-}
|
||||
-
|
||||
static inline bool nested_cpu_has_preemption_timer(struct vmcs12 *vmcs12)
|
||||
{
|
||||
return vmcs12->pin_based_vm_exec_control &
|
||||
@@ -3712,9 +3716,9 @@ static __init int setup_vmcs_config(struct vmcs_config *vmcs_conf)
|
||||
&_vmexit_control) < 0)
|
||||
return -EIO;
|
||||
|
||||
- min = PIN_BASED_EXT_INTR_MASK | PIN_BASED_NMI_EXITING |
|
||||
- PIN_BASED_VIRTUAL_NMIS;
|
||||
- opt = PIN_BASED_POSTED_INTR | PIN_BASED_VMX_PREEMPTION_TIMER;
|
||||
+ min = PIN_BASED_EXT_INTR_MASK | PIN_BASED_NMI_EXITING;
|
||||
+ opt = PIN_BASED_VIRTUAL_NMIS | PIN_BASED_POSTED_INTR |
|
||||
+ PIN_BASED_VMX_PREEMPTION_TIMER;
|
||||
if (adjust_vmx_controls(min, opt, MSR_IA32_VMX_PINBASED_CTLS,
|
||||
&_pin_based_exec_control) < 0)
|
||||
return -EIO;
|
||||
@@ -5669,7 +5673,8 @@ static void enable_irq_window(struct kvm_vcpu *vcpu)
|
||||
|
||||
static void enable_nmi_window(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
- if (vmcs_read32(GUEST_INTERRUPTIBILITY_INFO) & GUEST_INTR_STATE_STI) {
|
||||
+ if (!cpu_has_virtual_nmis() ||
|
||||
+ vmcs_read32(GUEST_INTERRUPTIBILITY_INFO) & GUEST_INTR_STATE_STI) {
|
||||
enable_irq_window(vcpu);
|
||||
return;
|
||||
}
|
||||
@@ -5709,6 +5714,19 @@ static void vmx_inject_nmi(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
struct vcpu_vmx *vmx = to_vmx(vcpu);
|
||||
|
||||
+ if (!cpu_has_virtual_nmis()) {
|
||||
+ /*
|
||||
+ * Tracking the NMI-blocked state in software is built upon
|
||||
+ * finding the next open IRQ window. This, in turn, depends on
|
||||
+ * well-behaving guests: They have to keep IRQs disabled at
|
||||
+ * least as long as the NMI handler runs. Otherwise we may
|
||||
+ * cause NMI nesting, maybe breaking the guest. But as this is
|
||||
+ * highly unlikely, we can live with the residual risk.
|
||||
+ */
|
||||
+ vmx->loaded_vmcs->soft_vnmi_blocked = 1;
|
||||
+ vmx->loaded_vmcs->vnmi_blocked_time = 0;
|
||||
+ }
|
||||
+
|
||||
++vcpu->stat.nmi_injections;
|
||||
vmx->loaded_vmcs->nmi_known_unmasked = false;
|
||||
|
||||
@@ -5727,6 +5745,8 @@ static bool vmx_get_nmi_mask(struct kvm_vcpu *vcpu)
|
||||
struct vcpu_vmx *vmx = to_vmx(vcpu);
|
||||
bool masked;
|
||||
|
||||
+ if (!cpu_has_virtual_nmis())
|
||||
+ return vmx->loaded_vmcs->soft_vnmi_blocked;
|
||||
if (vmx->loaded_vmcs->nmi_known_unmasked)
|
||||
return false;
|
||||
masked = vmcs_read32(GUEST_INTERRUPTIBILITY_INFO) & GUEST_INTR_STATE_NMI;
|
||||
@@ -5738,13 +5758,20 @@ static void vmx_set_nmi_mask(struct kvm_vcpu *vcpu, bool masked)
|
||||
{
|
||||
struct vcpu_vmx *vmx = to_vmx(vcpu);
|
||||
|
||||
- vmx->loaded_vmcs->nmi_known_unmasked = !masked;
|
||||
- if (masked)
|
||||
- vmcs_set_bits(GUEST_INTERRUPTIBILITY_INFO,
|
||||
- GUEST_INTR_STATE_NMI);
|
||||
- else
|
||||
- vmcs_clear_bits(GUEST_INTERRUPTIBILITY_INFO,
|
||||
- GUEST_INTR_STATE_NMI);
|
||||
+ if (!cpu_has_virtual_nmis()) {
|
||||
+ if (vmx->loaded_vmcs->soft_vnmi_blocked != masked) {
|
||||
+ vmx->loaded_vmcs->soft_vnmi_blocked = masked;
|
||||
+ vmx->loaded_vmcs->vnmi_blocked_time = 0;
|
||||
+ }
|
||||
+ } else {
|
||||
+ vmx->loaded_vmcs->nmi_known_unmasked = !masked;
|
||||
+ if (masked)
|
||||
+ vmcs_set_bits(GUEST_INTERRUPTIBILITY_INFO,
|
||||
+ GUEST_INTR_STATE_NMI);
|
||||
+ else
|
||||
+ vmcs_clear_bits(GUEST_INTERRUPTIBILITY_INFO,
|
||||
+ GUEST_INTR_STATE_NMI);
|
||||
+ }
|
||||
}
|
||||
|
||||
static int vmx_nmi_allowed(struct kvm_vcpu *vcpu)
|
||||
@@ -5752,6 +5779,10 @@ static int vmx_nmi_allowed(struct kvm_vcpu *vcpu)
|
||||
if (to_vmx(vcpu)->nested.nested_run_pending)
|
||||
return 0;
|
||||
|
||||
+ if (!cpu_has_virtual_nmis() &&
|
||||
+ to_vmx(vcpu)->loaded_vmcs->soft_vnmi_blocked)
|
||||
+ return 0;
|
||||
+
|
||||
return !(vmcs_read32(GUEST_INTERRUPTIBILITY_INFO) &
|
||||
(GUEST_INTR_STATE_MOV_SS | GUEST_INTR_STATE_STI
|
||||
| GUEST_INTR_STATE_NMI));
|
||||
@@ -6479,6 +6510,7 @@ static int handle_ept_violation(struct kvm_vcpu *vcpu)
|
||||
* AAK134, BY25.
|
||||
*/
|
||||
if (!(to_vmx(vcpu)->idt_vectoring_info & VECTORING_INFO_VALID_MASK) &&
|
||||
+ cpu_has_virtual_nmis() &&
|
||||
(exit_qualification & INTR_INFO_UNBLOCK_NMI))
|
||||
vmcs_set_bits(GUEST_INTERRUPTIBILITY_INFO, GUEST_INTR_STATE_NMI);
|
||||
|
||||
@@ -6965,7 +6997,7 @@ static struct loaded_vmcs *nested_get_current_vmcs02(struct vcpu_vmx *vmx)
|
||||
}
|
||||
|
||||
/* Create a new VMCS */
|
||||
- item = kmalloc(sizeof(struct vmcs02_list), GFP_KERNEL);
|
||||
+ item = kzalloc(sizeof(struct vmcs02_list), GFP_KERNEL);
|
||||
if (!item)
|
||||
return NULL;
|
||||
item->vmcs02.vmcs = alloc_vmcs();
|
||||
@@ -7982,6 +8014,7 @@ static int handle_pml_full(struct kvm_vcpu *vcpu)
|
||||
* "blocked by NMI" bit has to be set before next VM entry.
|
||||
*/
|
||||
if (!(to_vmx(vcpu)->idt_vectoring_info & VECTORING_INFO_VALID_MASK) &&
|
||||
+ cpu_has_virtual_nmis() &&
|
||||
(exit_qualification & INTR_INFO_UNBLOCK_NMI))
|
||||
vmcs_set_bits(GUEST_INTERRUPTIBILITY_INFO,
|
||||
GUEST_INTR_STATE_NMI);
|
||||
@@ -8826,6 +8859,25 @@ static int vmx_handle_exit(struct kvm_vcpu *vcpu)
|
||||
return 0;
|
||||
}
|
||||
|
||||
+ if (unlikely(!cpu_has_virtual_nmis() &&
|
||||
+ vmx->loaded_vmcs->soft_vnmi_blocked)) {
|
||||
+ if (vmx_interrupt_allowed(vcpu)) {
|
||||
+ vmx->loaded_vmcs->soft_vnmi_blocked = 0;
|
||||
+ } else if (vmx->loaded_vmcs->vnmi_blocked_time > 1000000000LL &&
|
||||
+ vcpu->arch.nmi_pending) {
|
||||
+ /*
|
||||
+ * This CPU don't support us in finding the end of an
|
||||
+ * NMI-blocked window if the guest runs with IRQs
|
||||
+ * disabled. So we pull the trigger after 1 s of
|
||||
+ * futile waiting, but inform the user about this.
|
||||
+ */
|
||||
+ printk(KERN_WARNING "%s: Breaking out of NMI-blocked "
|
||||
+ "state on VCPU %d after 1 s timeout\n",
|
||||
+ __func__, vcpu->vcpu_id);
|
||||
+ vmx->loaded_vmcs->soft_vnmi_blocked = 0;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
if (exit_reason < kvm_vmx_max_exit_handlers
|
||||
&& kvm_vmx_exit_handlers[exit_reason])
|
||||
return kvm_vmx_exit_handlers[exit_reason](vcpu);
|
||||
@@ -9108,33 +9160,38 @@ static void vmx_recover_nmi_blocking(struct vcpu_vmx *vmx)
|
||||
|
||||
idtv_info_valid = vmx->idt_vectoring_info & VECTORING_INFO_VALID_MASK;
|
||||
|
||||
- if (vmx->loaded_vmcs->nmi_known_unmasked)
|
||||
- return;
|
||||
- /*
|
||||
- * Can't use vmx->exit_intr_info since we're not sure what
|
||||
- * the exit reason is.
|
||||
- */
|
||||
- exit_intr_info = vmcs_read32(VM_EXIT_INTR_INFO);
|
||||
- unblock_nmi = (exit_intr_info & INTR_INFO_UNBLOCK_NMI) != 0;
|
||||
- vector = exit_intr_info & INTR_INFO_VECTOR_MASK;
|
||||
- /*
|
||||
- * SDM 3: 27.7.1.2 (September 2008)
|
||||
- * Re-set bit "block by NMI" before VM entry if vmexit caused by
|
||||
- * a guest IRET fault.
|
||||
- * SDM 3: 23.2.2 (September 2008)
|
||||
- * Bit 12 is undefined in any of the following cases:
|
||||
- * If the VM exit sets the valid bit in the IDT-vectoring
|
||||
- * information field.
|
||||
- * If the VM exit is due to a double fault.
|
||||
- */
|
||||
- if ((exit_intr_info & INTR_INFO_VALID_MASK) && unblock_nmi &&
|
||||
- vector != DF_VECTOR && !idtv_info_valid)
|
||||
- vmcs_set_bits(GUEST_INTERRUPTIBILITY_INFO,
|
||||
- GUEST_INTR_STATE_NMI);
|
||||
- else
|
||||
- vmx->loaded_vmcs->nmi_known_unmasked =
|
||||
- !(vmcs_read32(GUEST_INTERRUPTIBILITY_INFO)
|
||||
- & GUEST_INTR_STATE_NMI);
|
||||
+ if (cpu_has_virtual_nmis()) {
|
||||
+ if (vmx->loaded_vmcs->nmi_known_unmasked)
|
||||
+ return;
|
||||
+ /*
|
||||
+ * Can't use vmx->exit_intr_info since we're not sure what
|
||||
+ * the exit reason is.
|
||||
+ */
|
||||
+ exit_intr_info = vmcs_read32(VM_EXIT_INTR_INFO);
|
||||
+ unblock_nmi = (exit_intr_info & INTR_INFO_UNBLOCK_NMI) != 0;
|
||||
+ vector = exit_intr_info & INTR_INFO_VECTOR_MASK;
|
||||
+ /*
|
||||
+ * SDM 3: 27.7.1.2 (September 2008)
|
||||
+ * Re-set bit "block by NMI" before VM entry if vmexit caused by
|
||||
+ * a guest IRET fault.
|
||||
+ * SDM 3: 23.2.2 (September 2008)
|
||||
+ * Bit 12 is undefined in any of the following cases:
|
||||
+ * If the VM exit sets the valid bit in the IDT-vectoring
|
||||
+ * information field.
|
||||
+ * If the VM exit is due to a double fault.
|
||||
+ */
|
||||
+ if ((exit_intr_info & INTR_INFO_VALID_MASK) && unblock_nmi &&
|
||||
+ vector != DF_VECTOR && !idtv_info_valid)
|
||||
+ vmcs_set_bits(GUEST_INTERRUPTIBILITY_INFO,
|
||||
+ GUEST_INTR_STATE_NMI);
|
||||
+ else
|
||||
+ vmx->loaded_vmcs->nmi_known_unmasked =
|
||||
+ !(vmcs_read32(GUEST_INTERRUPTIBILITY_INFO)
|
||||
+ & GUEST_INTR_STATE_NMI);
|
||||
+ } else if (unlikely(vmx->loaded_vmcs->soft_vnmi_blocked))
|
||||
+ vmx->loaded_vmcs->vnmi_blocked_time +=
|
||||
+ ktime_to_ns(ktime_sub(ktime_get(),
|
||||
+ vmx->loaded_vmcs->entry_time));
|
||||
}
|
||||
|
||||
static void __vmx_complete_interrupts(struct kvm_vcpu *vcpu,
|
||||
@@ -9251,6 +9308,11 @@ static void __noclone vmx_vcpu_run(struct kvm_vcpu *vcpu)
|
||||
struct vcpu_vmx *vmx = to_vmx(vcpu);
|
||||
unsigned long debugctlmsr, cr3, cr4;
|
||||
|
||||
+ /* Record the guest's net vcpu time for enforced NMI injections. */
|
||||
+ if (unlikely(!cpu_has_virtual_nmis() &&
|
||||
+ vmx->loaded_vmcs->soft_vnmi_blocked))
|
||||
+ vmx->loaded_vmcs->entry_time = ktime_get();
|
||||
+
|
||||
/* Don't enter VMX if guest state is invalid, let the exit handler
|
||||
start emulation until we arrive back to a valid state */
|
||||
if (vmx->emulation_required)
|
|
@ -1,50 +0,0 @@
|
|||
From patchwork Mon Sep 18 16:28:55 2017
|
||||
Content-Type: text/plain; charset="utf-8"
|
||||
MIME-Version: 1.0
|
||||
Content-Transfer-Encoding: 7bit
|
||||
Subject: [1/3] net: set tb->fast_sk_family
|
||||
X-Patchwork-Submitter: Josef Bacik <josef@toxicpanda.com>
|
||||
X-Patchwork-Id: 815031
|
||||
X-Patchwork-Delegate: davem@davemloft.net
|
||||
Message-Id: <1505752137-15522-2-git-send-email-jbacik@fb.com>
|
||||
To: davem@davemloft.net, netdev@vger.kernel.org,
|
||||
linux-kernel@vger.kernel.org, crobinso@redhat.com,
|
||||
labbott@redhat.com, kernel-team@fb.com
|
||||
Cc: Josef Bacik <jbacik@fb.com>, stable@vger.kernel.org
|
||||
Date: Mon, 18 Sep 2017 12:28:55 -0400
|
||||
From: josef@toxicpanda.com
|
||||
List-Id: <netdev.vger.kernel.org>
|
||||
|
||||
From: Josef Bacik <jbacik@fb.com>
|
||||
|
||||
We need to set the tb->fast_sk_family properly so we can use the proper
|
||||
comparison function for all subsequent reuseport bind requests.
|
||||
|
||||
Cc: stable@vger.kernel.org
|
||||
Fixes: 637bc8bbe6c0 ("inet: reset tb->fastreuseport when adding a reuseport sk")
|
||||
Reported-and-tested-by: Cole Robinson <crobinso@redhat.com>
|
||||
Signed-off-by: Josef Bacik <jbacik@fb.com>
|
||||
---
|
||||
net/ipv4/inet_connection_sock.c | 2 ++
|
||||
1 file changed, 2 insertions(+)
|
||||
|
||||
diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c
|
||||
index b9c64b40a83a..f87f4805e244 100644
|
||||
--- a/net/ipv4/inet_connection_sock.c
|
||||
+++ b/net/ipv4/inet_connection_sock.c
|
||||
@@ -328,6 +328,7 @@ int inet_csk_get_port(struct sock *sk, unsigned short snum)
|
||||
tb->fastuid = uid;
|
||||
tb->fast_rcv_saddr = sk->sk_rcv_saddr;
|
||||
tb->fast_ipv6_only = ipv6_only_sock(sk);
|
||||
+ tb->fast_sk_family = sk->sk_family;
|
||||
#if IS_ENABLED(CONFIG_IPV6)
|
||||
tb->fast_v6_rcv_saddr = sk->sk_v6_rcv_saddr;
|
||||
#endif
|
||||
@@ -354,6 +355,7 @@ int inet_csk_get_port(struct sock *sk, unsigned short snum)
|
||||
tb->fastuid = uid;
|
||||
tb->fast_rcv_saddr = sk->sk_rcv_saddr;
|
||||
tb->fast_ipv6_only = ipv6_only_sock(sk);
|
||||
+ tb->fast_sk_family = sk->sk_family;
|
||||
#if IS_ENABLED(CONFIG_IPV6)
|
||||
tb->fast_v6_rcv_saddr = sk->sk_v6_rcv_saddr;
|
||||
#endif
|
|
@ -1,44 +0,0 @@
|
|||
From patchwork Mon Sep 18 16:28:56 2017
|
||||
Content-Type: text/plain; charset="utf-8"
|
||||
MIME-Version: 1.0
|
||||
Content-Transfer-Encoding: 7bit
|
||||
Subject: [2/3] net: use inet6_rcv_saddr to compare sockets
|
||||
X-Patchwork-Submitter: Josef Bacik <josef@toxicpanda.com>
|
||||
X-Patchwork-Id: 815028
|
||||
X-Patchwork-Delegate: davem@davemloft.net
|
||||
Message-Id: <1505752137-15522-3-git-send-email-jbacik@fb.com>
|
||||
To: davem@davemloft.net, netdev@vger.kernel.org,
|
||||
linux-kernel@vger.kernel.org, crobinso@redhat.com,
|
||||
labbott@redhat.com, kernel-team@fb.com
|
||||
Cc: Josef Bacik <jbacik@fb.com>, stable@vger.kernel.org
|
||||
Date: Mon, 18 Sep 2017 12:28:56 -0400
|
||||
From: josef@toxicpanda.com
|
||||
List-Id: <netdev.vger.kernel.org>
|
||||
|
||||
From: Josef Bacik <jbacik@fb.com>
|
||||
|
||||
In ipv6_rcv_saddr_equal() we need to use inet6_rcv_saddr(sk) for the
|
||||
ipv6 compare with the fast socket information to make sure we're doing
|
||||
the proper comparisons.
|
||||
|
||||
Cc: stable@vger.kernel.org
|
||||
Fixes: 637bc8bbe6c0 ("inet: reset tb->fastreuseport when adding a reuseport sk")
|
||||
Reported-and-tested-by: Cole Robinson <crobinso@redhat.com>
|
||||
Signed-off-by: Josef Bacik <jbacik@fb.com>
|
||||
---
|
||||
net/ipv4/inet_connection_sock.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c
|
||||
index f87f4805e244..a1bf30438bc5 100644
|
||||
--- a/net/ipv4/inet_connection_sock.c
|
||||
+++ b/net/ipv4/inet_connection_sock.c
|
||||
@@ -266,7 +266,7 @@ static inline int sk_reuseport_match(struct inet_bind_bucket *tb,
|
||||
#if IS_ENABLED(CONFIG_IPV6)
|
||||
if (tb->fast_sk_family == AF_INET6)
|
||||
return ipv6_rcv_saddr_equal(&tb->fast_v6_rcv_saddr,
|
||||
- &sk->sk_v6_rcv_saddr,
|
||||
+ inet6_rcv_saddr(sk),
|
||||
tb->fast_rcv_saddr,
|
||||
sk->sk_rcv_saddr,
|
||||
tb->fast_ipv6_only,
|
|
@ -1,53 +0,0 @@
|
|||
From patchwork Mon Sep 18 16:28:57 2017
|
||||
Content-Type: text/plain; charset="utf-8"
|
||||
MIME-Version: 1.0
|
||||
Content-Transfer-Encoding: 7bit
|
||||
Subject: [3/3] inet: fix improper empty comparison
|
||||
X-Patchwork-Submitter: Josef Bacik <josef@toxicpanda.com>
|
||||
X-Patchwork-Id: 815029
|
||||
X-Patchwork-Delegate: davem@davemloft.net
|
||||
Message-Id: <1505752137-15522-4-git-send-email-jbacik@fb.com>
|
||||
To: davem@davemloft.net, netdev@vger.kernel.org,
|
||||
linux-kernel@vger.kernel.org, crobinso@redhat.com,
|
||||
labbott@redhat.com, kernel-team@fb.com
|
||||
Cc: Josef Bacik <jbacik@fb.com>, stable@vger.kernel.org
|
||||
Date: Mon, 18 Sep 2017 12:28:57 -0400
|
||||
From: josef@toxicpanda.com
|
||||
List-Id: <netdev.vger.kernel.org>
|
||||
|
||||
From: Josef Bacik <jbacik@fb.com>
|
||||
|
||||
When doing my reuseport rework I screwed up and changed a
|
||||
|
||||
if (hlist_empty(&tb->owners))
|
||||
|
||||
to
|
||||
|
||||
if (!hlist_empty(&tb->owners))
|
||||
|
||||
This is obviously bad as all of the reuseport/reuse logic was reversed,
|
||||
which caused weird problems like allowing an ipv4 bind conflict if we
|
||||
opened an ipv4 only socket on a port followed by an ipv6 only socket on
|
||||
the same port.
|
||||
|
||||
Cc: stable@vger.kernel.org
|
||||
Fixes: b9470c27607b ("inet: kill smallest_size and smallest_port")
|
||||
Reported-by: Cole Robinson <crobinso@redhat.com>
|
||||
Signed-off-by: Josef Bacik <jbacik@fb.com>
|
||||
---
|
||||
net/ipv4/inet_connection_sock.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c
|
||||
index a1bf30438bc5..c039c937ba90 100644
|
||||
--- a/net/ipv4/inet_connection_sock.c
|
||||
+++ b/net/ipv4/inet_connection_sock.c
|
||||
@@ -321,7 +321,7 @@ int inet_csk_get_port(struct sock *sk, unsigned short snum)
|
||||
goto fail_unlock;
|
||||
}
|
||||
success:
|
||||
- if (!hlist_empty(&tb->owners)) {
|
||||
+ if (hlist_empty(&tb->owners)) {
|
||||
tb->fastreuse = reuse;
|
||||
if (sk->sk_reuseport) {
|
||||
tb->fastreuseport = FASTREUSEPORT_ANY;
|
File diff suppressed because it is too large
Load Diff
|
@ -1,166 +0,0 @@
|
|||
From patchwork Tue Sep 26 21:10:20 2017
|
||||
Content-Type: text/plain; charset="utf-8"
|
||||
MIME-Version: 1.0
|
||||
Content-Transfer-Encoding: 7bit
|
||||
Subject: [1/2] media: dvb-usb-v2: lmedm04: Improve logic checking of warm
|
||||
start.
|
||||
From: Malcolm Priestley <tvboxspy@gmail.com>
|
||||
X-Patchwork-Id: 44566
|
||||
Message-Id: <20170926211021.11036-1-tvboxspy@gmail.com>
|
||||
To: linux-media@vger.kernel.org
|
||||
Cc: Andrey Konovalov <andreyknvl@google.com>,
|
||||
Malcolm Priestley <tvboxspy@gmail.com>
|
||||
Date: Tue, 26 Sep 2017 22:10:20 +0100
|
||||
|
||||
Warm start has no check as whether a genuine device has
|
||||
connected and proceeds to next execution path.
|
||||
|
||||
Check device should read 0x47 at offset of 2 on USB descriptor read
|
||||
and it is the amount requested of 6 bytes.
|
||||
|
||||
Fix for
|
||||
kasan: CONFIG_KASAN_INLINE enabled
|
||||
kasan: GPF could be caused by NULL-ptr deref or user memory access as
|
||||
|
||||
Reported-by: Andrey Konovalov <andreyknvl@google.com>
|
||||
Signed-off-by: Malcolm Priestley <tvboxspy@gmail.com>
|
||||
---
|
||||
drivers/media/usb/dvb-usb-v2/lmedm04.c | 26 ++++++++++++++++++--------
|
||||
1 file changed, 18 insertions(+), 8 deletions(-)
|
||||
|
||||
diff --git a/drivers/media/usb/dvb-usb-v2/lmedm04.c b/drivers/media/usb/dvb-usb-v2/lmedm04.c
|
||||
index 5e320fa4a795..992f2011a6ba 100644
|
||||
--- a/drivers/media/usb/dvb-usb-v2/lmedm04.c
|
||||
+++ b/drivers/media/usb/dvb-usb-v2/lmedm04.c
|
||||
@@ -494,18 +494,23 @@ static int lme2510_pid_filter(struct dvb_usb_adapter *adap, int index, u16 pid,
|
||||
|
||||
static int lme2510_return_status(struct dvb_usb_device *d)
|
||||
{
|
||||
- int ret = 0;
|
||||
+ int ret;
|
||||
u8 *data;
|
||||
|
||||
- data = kzalloc(10, GFP_KERNEL);
|
||||
+ data = kzalloc(6, GFP_KERNEL);
|
||||
if (!data)
|
||||
return -ENOMEM;
|
||||
|
||||
- ret |= usb_control_msg(d->udev, usb_rcvctrlpipe(d->udev, 0),
|
||||
- 0x06, 0x80, 0x0302, 0x00, data, 0x0006, 200);
|
||||
- info("Firmware Status: %x (%x)", ret , data[2]);
|
||||
+ ret = usb_control_msg(d->udev, usb_rcvctrlpipe(d->udev, 0),
|
||||
+ 0x06, 0x80, 0x0302, 0x00,
|
||||
+ data, 0x6, 200);
|
||||
+ if (ret != 6)
|
||||
+ ret = -EINVAL;
|
||||
+ else
|
||||
+ ret = data[2];
|
||||
+
|
||||
+ info("Firmware Status: %6ph", data);
|
||||
|
||||
- ret = (ret < 0) ? -ENODEV : data[2];
|
||||
kfree(data);
|
||||
return ret;
|
||||
}
|
||||
@@ -1189,6 +1194,7 @@ static int lme2510_get_adapter_count(struct dvb_usb_device *d)
|
||||
static int lme2510_identify_state(struct dvb_usb_device *d, const char **name)
|
||||
{
|
||||
struct lme2510_state *st = d->priv;
|
||||
+ int status;
|
||||
|
||||
usb_reset_configuration(d->udev);
|
||||
|
||||
@@ -1197,12 +1203,16 @@ static int lme2510_identify_state(struct dvb_usb_device *d, const char **name)
|
||||
|
||||
st->dvb_usb_lme2510_firmware = dvb_usb_lme2510_firmware;
|
||||
|
||||
- if (lme2510_return_status(d) == 0x44) {
|
||||
+ status = lme2510_return_status(d);
|
||||
+ if (status == 0x44) {
|
||||
*name = lme_firmware_switch(d, 0);
|
||||
return COLD;
|
||||
}
|
||||
|
||||
- return 0;
|
||||
+ if (status != 0x47)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ return WARM;
|
||||
}
|
||||
|
||||
static int lme2510_get_stream_config(struct dvb_frontend *fe, u8 *ts_type,
|
||||
From patchwork Tue Sep 26 21:10:21 2017
|
||||
Content-Type: text/plain; charset="utf-8"
|
||||
MIME-Version: 1.0
|
||||
Content-Transfer-Encoding: 7bit
|
||||
Subject: [2/2] media: dvb-usb-v2: lmedm04: move ts2020 attach to
|
||||
dm04_lme2510_tuner
|
||||
From: Malcolm Priestley <tvboxspy@gmail.com>
|
||||
X-Patchwork-Id: 44567
|
||||
Message-Id: <20170926211021.11036-2-tvboxspy@gmail.com>
|
||||
To: linux-media@vger.kernel.org
|
||||
Cc: Andrey Konovalov <andreyknvl@google.com>,
|
||||
Malcolm Priestley <tvboxspy@gmail.com>
|
||||
Date: Tue, 26 Sep 2017 22:10:21 +0100
|
||||
|
||||
When the tuner was split from m88rs2000 the attach function is in wrong
|
||||
place.
|
||||
|
||||
Move to dm04_lme2510_tuner to trap errors on failure and removing
|
||||
a call to lme_coldreset.
|
||||
|
||||
Prevents driver starting up without any tuner connected.
|
||||
|
||||
Fixes to trap for ts2020 fail.
|
||||
LME2510(C): FE Found M88RS2000
|
||||
ts2020: probe of 0-0060 failed with error -11
|
||||
...
|
||||
LME2510(C): TUN Found RS2000 tuner
|
||||
kasan: CONFIG_KASAN_INLINE enabled
|
||||
kasan: GPF could be caused by NULL-ptr deref or user memory access
|
||||
general protection fault: 0000 [#1] PREEMPT SMP KASAN
|
||||
|
||||
Reported-by: Andrey Konovalov <andreyknvl@google.com>
|
||||
Signed-off-by: Malcolm Priestley <tvboxspy@gmail.com>
|
||||
Tested-by: Andrey Konovalov <andreyknvl@google.com>
|
||||
---
|
||||
drivers/media/usb/dvb-usb-v2/lmedm04.c | 13 ++++++-------
|
||||
1 file changed, 6 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/drivers/media/usb/dvb-usb-v2/lmedm04.c b/drivers/media/usb/dvb-usb-v2/lmedm04.c
|
||||
index 992f2011a6ba..be26c029546b 100644
|
||||
--- a/drivers/media/usb/dvb-usb-v2/lmedm04.c
|
||||
+++ b/drivers/media/usb/dvb-usb-v2/lmedm04.c
|
||||
@@ -1076,8 +1076,6 @@ static int dm04_lme2510_frontend_attach(struct dvb_usb_adapter *adap)
|
||||
|
||||
if (adap->fe[0]) {
|
||||
info("FE Found M88RS2000");
|
||||
- dvb_attach(ts2020_attach, adap->fe[0], &ts2020_config,
|
||||
- &d->i2c_adap);
|
||||
st->i2c_tuner_gate_w = 5;
|
||||
st->i2c_tuner_gate_r = 5;
|
||||
st->i2c_tuner_addr = 0x60;
|
||||
@@ -1143,17 +1141,18 @@ static int dm04_lme2510_tuner(struct dvb_usb_adapter *adap)
|
||||
ret = st->tuner_config;
|
||||
break;
|
||||
case TUNER_RS2000:
|
||||
- ret = st->tuner_config;
|
||||
+ if (dvb_attach(ts2020_attach, adap->fe[0],
|
||||
+ &ts2020_config, &d->i2c_adap))
|
||||
+ ret = st->tuner_config;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
- if (ret)
|
||||
+ if (ret) {
|
||||
info("TUN Found %s tuner", tun_msg[ret]);
|
||||
- else {
|
||||
- info("TUN No tuner found --- resetting device");
|
||||
- lme_coldreset(d);
|
||||
+ } else {
|
||||
+ info("TUN No tuner found");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
|
@ -1,73 +0,0 @@
|
|||
From 4d6fa57b4dab0d77f4d8e9d9c73d1e63f6fe8fee Mon Sep 17 00:00:00 2001
|
||||
From: "Jason A. Donenfeld" <Jason@zx2c4.com>
|
||||
Date: Fri, 21 Apr 2017 23:14:48 +0200
|
||||
Subject: macsec: avoid heap overflow in skb_to_sgvec
|
||||
|
||||
While this may appear as a humdrum one line change, it's actually quite
|
||||
important. An sk_buff stores data in three places:
|
||||
|
||||
1. A linear chunk of allocated memory in skb->data. This is the easiest
|
||||
one to work with, but it precludes using scatterdata since the memory
|
||||
must be linear.
|
||||
2. The array skb_shinfo(skb)->frags, which is of maximum length
|
||||
MAX_SKB_FRAGS. This is nice for scattergather, since these fragments
|
||||
can point to different pages.
|
||||
3. skb_shinfo(skb)->frag_list, which is a pointer to another sk_buff,
|
||||
which in turn can have data in either (1) or (2).
|
||||
|
||||
The first two are rather easy to deal with, since they're of a fixed
|
||||
maximum length, while the third one is not, since there can be
|
||||
potentially limitless chains of fragments. Fortunately dealing with
|
||||
frag_list is opt-in for drivers, so drivers don't actually have to deal
|
||||
with this mess. For whatever reason, macsec decided it wanted pain, and
|
||||
so it explicitly specified NETIF_F_FRAGLIST.
|
||||
|
||||
Because dealing with (1), (2), and (3) is insane, most users of sk_buff
|
||||
doing any sort of crypto or paging operation calls a convenient function
|
||||
called skb_to_sgvec (which happens to be recursive if (3) is in use!).
|
||||
This takes a sk_buff as input, and writes into its output pointer an
|
||||
array of scattergather list items. Sometimes people like to declare a
|
||||
fixed size scattergather list on the stack; othertimes people like to
|
||||
allocate a fixed size scattergather list on the heap. However, if you're
|
||||
doing it in a fixed-size fashion, you really shouldn't be using
|
||||
NETIF_F_FRAGLIST too (unless you're also ensuring the sk_buff and its
|
||||
frag_list children arent't shared and then you check the number of
|
||||
fragments in total required.)
|
||||
|
||||
Macsec specifically does this:
|
||||
|
||||
size += sizeof(struct scatterlist) * (MAX_SKB_FRAGS + 1);
|
||||
tmp = kmalloc(size, GFP_ATOMIC);
|
||||
*sg = (struct scatterlist *)(tmp + sg_offset);
|
||||
...
|
||||
sg_init_table(sg, MAX_SKB_FRAGS + 1);
|
||||
skb_to_sgvec(skb, sg, 0, skb->len);
|
||||
|
||||
Specifying MAX_SKB_FRAGS + 1 is the right answer usually, but not if you're
|
||||
using NETIF_F_FRAGLIST, in which case the call to skb_to_sgvec will
|
||||
overflow the heap, and disaster ensues.
|
||||
|
||||
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
|
||||
Cc: stable@vger.kernel.org
|
||||
Cc: security@kernel.org
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/macsec.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/drivers/net/macsec.c b/drivers/net/macsec.c
|
||||
index ff0a5ed..dbab05a 100644
|
||||
--- a/drivers/net/macsec.c
|
||||
+++ b/drivers/net/macsec.c
|
||||
@@ -2716,7 +2716,7 @@ static netdev_tx_t macsec_start_xmit(struct sk_buff *skb,
|
||||
}
|
||||
|
||||
#define MACSEC_FEATURES \
|
||||
- (NETIF_F_SG | NETIF_F_HIGHDMA | NETIF_F_FRAGLIST)
|
||||
+ (NETIF_F_SG | NETIF_F_HIGHDMA)
|
||||
static struct lock_class_key macsec_netdev_addr_lock_key;
|
||||
|
||||
static int macsec_dev_init(struct net_device *dev)
|
||||
--
|
||||
cgit v1.1
|
||||
|
|
@ -0,0 +1,180 @@
|
|||
From: "J. Bruce Fields" <bfields@redhat.com>
|
||||
Date: 2017-04-14 15:04:40
|
||||
Subject: [PATCH] nfsd: check for oversized NFSv2/v3 arguments
|
||||
|
||||
A client can append random data to the end of an NFSv2 or NFSv3 RPC call
|
||||
without our complaining; we'll just stop parsing at the end of the
|
||||
expected data and ignore the rest.
|
||||
|
||||
Encoded arguments and replies are stored together in an array of pages,
|
||||
and if a call is too large it could leave inadequate space for the
|
||||
reply. This is normally OK because NFS RPC's typically have either
|
||||
short arguments and long replies (like READ) or long arguments and short
|
||||
replies (like WRITE). But a client that sends an incorrectly long reply
|
||||
can violate those assumptions. This was observed to cause crashes.
|
||||
|
||||
So, insist that the argument not be any longer than we expect.
|
||||
|
||||
Also, several operations increment rq_next_page in the decode routine
|
||||
before checking the argument size, which can leave rq_next_page pointing
|
||||
well past the end of the page array, causing trouble later in
|
||||
svc_free_pages.
|
||||
|
||||
As followup we may also want to rewrite the encoding routines to check
|
||||
more carefully that they aren't running off the end of the page array.
|
||||
|
||||
Reported-by: Tuomas Haanpää <thaan@synopsys.com>
|
||||
Reported-by: Ari Kauppi <ari@synopsys.com>
|
||||
Cc: stable@vger.kernel.org
|
||||
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
|
||||
---
|
||||
fs/nfsd/nfs3xdr.c | 23 +++++++++++++++++------
|
||||
fs/nfsd/nfsxdr.c | 13 ++++++++++---
|
||||
include/linux/sunrpc/svc.h | 3 +--
|
||||
3 files changed, 28 insertions(+), 11 deletions(-)
|
||||
|
||||
diff --git a/fs/nfsd/nfs3xdr.c b/fs/nfsd/nfs3xdr.c
|
||||
index dba2ff8eaa68..be66bcadfaea 100644
|
||||
--- a/fs/nfsd/nfs3xdr.c
|
||||
+++ b/fs/nfsd/nfs3xdr.c
|
||||
@@ -334,8 +334,11 @@ nfs3svc_decode_readargs(struct svc_rqst *rqstp, __be32 *p,
|
||||
if (!p)
|
||||
return 0;
|
||||
p = xdr_decode_hyper(p, &args->offset);
|
||||
-
|
||||
args->count = ntohl(*p++);
|
||||
+
|
||||
+ if (!xdr_argsize_check(rqstp, p))
|
||||
+ return 0;
|
||||
+
|
||||
len = min(args->count, max_blocksize);
|
||||
|
||||
/* set up the kvec */
|
||||
@@ -349,7 +352,7 @@ nfs3svc_decode_readargs(struct svc_rqst *rqstp, __be32 *p,
|
||||
v++;
|
||||
}
|
||||
args->vlen = v;
|
||||
- return xdr_argsize_check(rqstp, p);
|
||||
+ return 1;
|
||||
}
|
||||
|
||||
int
|
||||
@@ -536,9 +539,11 @@ nfs3svc_decode_readlinkargs(struct svc_rqst *rqstp, __be32 *p,
|
||||
p = decode_fh(p, &args->fh);
|
||||
if (!p)
|
||||
return 0;
|
||||
+ if (!xdr_argsize_check(rqstp, p))
|
||||
+ return 0;
|
||||
args->buffer = page_address(*(rqstp->rq_next_page++));
|
||||
|
||||
- return xdr_argsize_check(rqstp, p);
|
||||
+ return 1;
|
||||
}
|
||||
|
||||
int
|
||||
@@ -564,10 +569,14 @@ nfs3svc_decode_readdirargs(struct svc_rqst *rqstp, __be32 *p,
|
||||
args->verf = p; p += 2;
|
||||
args->dircount = ~0;
|
||||
args->count = ntohl(*p++);
|
||||
+
|
||||
+ if (!xdr_argsize_check(rqstp, p))
|
||||
+ return 0;
|
||||
+
|
||||
args->count = min_t(u32, args->count, PAGE_SIZE);
|
||||
args->buffer = page_address(*(rqstp->rq_next_page++));
|
||||
|
||||
- return xdr_argsize_check(rqstp, p);
|
||||
+ return 1;
|
||||
}
|
||||
|
||||
int
|
||||
@@ -585,6 +594,9 @@ nfs3svc_decode_readdirplusargs(struct svc_rqst *rqstp, __be32 *p,
|
||||
args->dircount = ntohl(*p++);
|
||||
args->count = ntohl(*p++);
|
||||
|
||||
+ if (!xdr_argsize_check(rqstp, p))
|
||||
+ return 0;
|
||||
+
|
||||
len = args->count = min(args->count, max_blocksize);
|
||||
while (len > 0) {
|
||||
struct page *p = *(rqstp->rq_next_page++);
|
||||
@@ -592,8 +604,7 @@ nfs3svc_decode_readdirplusargs(struct svc_rqst *rqstp, __be32 *p,
|
||||
args->buffer = page_address(p);
|
||||
len -= PAGE_SIZE;
|
||||
}
|
||||
-
|
||||
- return xdr_argsize_check(rqstp, p);
|
||||
+ return 1;
|
||||
}
|
||||
|
||||
int
|
||||
diff --git a/fs/nfsd/nfsxdr.c b/fs/nfsd/nfsxdr.c
|
||||
index 41b468a6a90f..79268369f7b3 100644
|
||||
--- a/fs/nfsd/nfsxdr.c
|
||||
+++ b/fs/nfsd/nfsxdr.c
|
||||
@@ -257,6 +257,9 @@ nfssvc_decode_readargs(struct svc_rqst *rqstp, __be32 *p,
|
||||
len = args->count = ntohl(*p++);
|
||||
p++; /* totalcount - unused */
|
||||
|
||||
+ if (!xdr_argsize_check(rqstp, p))
|
||||
+ return 0;
|
||||
+
|
||||
len = min_t(unsigned int, len, NFSSVC_MAXBLKSIZE_V2);
|
||||
|
||||
/* set up somewhere to store response.
|
||||
@@ -272,7 +275,7 @@ nfssvc_decode_readargs(struct svc_rqst *rqstp, __be32 *p,
|
||||
v++;
|
||||
}
|
||||
args->vlen = v;
|
||||
- return xdr_argsize_check(rqstp, p);
|
||||
+ return 1;
|
||||
}
|
||||
|
||||
int
|
||||
@@ -360,9 +363,11 @@ nfssvc_decode_readlinkargs(struct svc_rqst *rqstp, __be32 *p, struct nfsd_readli
|
||||
p = decode_fh(p, &args->fh);
|
||||
if (!p)
|
||||
return 0;
|
||||
+ if (!xdr_argsize_check(rqstp, p))
|
||||
+ return 0;
|
||||
args->buffer = page_address(*(rqstp->rq_next_page++));
|
||||
|
||||
- return xdr_argsize_check(rqstp, p);
|
||||
+ return 1;
|
||||
}
|
||||
|
||||
int
|
||||
@@ -400,9 +405,11 @@ nfssvc_decode_readdirargs(struct svc_rqst *rqstp, __be32 *p,
|
||||
args->cookie = ntohl(*p++);
|
||||
args->count = ntohl(*p++);
|
||||
args->count = min_t(u32, args->count, PAGE_SIZE);
|
||||
+ if (!xdr_argsize_check(rqstp, p))
|
||||
+ return 0;
|
||||
args->buffer = page_address(*(rqstp->rq_next_page++));
|
||||
|
||||
- return xdr_argsize_check(rqstp, p);
|
||||
+ return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
diff --git a/include/linux/sunrpc/svc.h b/include/linux/sunrpc/svc.h
|
||||
index e770abeed32d..6ef19cf658b4 100644
|
||||
--- a/include/linux/sunrpc/svc.h
|
||||
+++ b/include/linux/sunrpc/svc.h
|
||||
@@ -336,8 +336,7 @@ xdr_argsize_check(struct svc_rqst *rqstp, __be32 *p)
|
||||
{
|
||||
char *cp = (char *)p;
|
||||
struct kvec *vec = &rqstp->rq_arg.head[0];
|
||||
- return cp >= (char*)vec->iov_base
|
||||
- && cp <= (char*)vec->iov_base + vec->iov_len;
|
||||
+ return cp == (char *)vec->iov_base + vec->iov_len;
|
||||
}
|
||||
|
||||
static inline int
|
||||
--
|
||||
2.9.3
|
||||
|
||||
--
|
||||
To unsubscribe from this list: send the line "unsubscribe linux-nfs" in
|
||||
the body of a message to majordomo@vger.kernel.org
|
||||
More majordomo info at http://vger.kernel.org/majordomo-info.html
|
|
@ -1,54 +0,0 @@
|
|||
From ef14a4bf0910d06c7e202552914028d4956809cb Mon Sep 17 00:00:00 2001
|
||||
From: Andrew Duggan <aduggan@synaptics.com>
|
||||
Date: Tue, 17 Oct 2017 18:37:36 -0700
|
||||
Subject: [PATCH] HID: rmi: Check that a device is a RMI device before calling
|
||||
RMI functions
|
||||
|
||||
The hid-rmi driver may handle non rmi devices on composite USB devices.
|
||||
Callbacks need to make sure that the current device is a RMI device before
|
||||
calling RMI specific functions. Most callbacks already have this check, but
|
||||
this patch adds checks to the remaining callbacks.
|
||||
|
||||
Reported-by: Hendrik Langer <hendrik.langer@gmx.de>
|
||||
Tested-by: Hendrik Langer <hendrik.langer@gmx.de>
|
||||
Reviewed-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
|
||||
Signed-off-by: Andrew Duggan <aduggan@synaptics.com>
|
||||
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
|
||||
---
|
||||
drivers/hid/hid-rmi.c | 13 ++++++++++---
|
||||
1 file changed, 10 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/drivers/hid/hid-rmi.c b/drivers/hid/hid-rmi.c
|
||||
index ef241d66562e..0f43c4292685 100644
|
||||
--- a/drivers/hid/hid-rmi.c
|
||||
+++ b/drivers/hid/hid-rmi.c
|
||||
@@ -368,6 +368,11 @@ static int rmi_check_sanity(struct hid_device *hdev, u8 *data, int size)
|
||||
static int rmi_raw_event(struct hid_device *hdev,
|
||||
struct hid_report *report, u8 *data, int size)
|
||||
{
|
||||
+ struct rmi_data *hdata = hid_get_drvdata(hdev);
|
||||
+
|
||||
+ if (!(hdata->device_flags & RMI_DEVICE))
|
||||
+ return 0;
|
||||
+
|
||||
size = rmi_check_sanity(hdev, data, size);
|
||||
if (size < 2)
|
||||
return 0;
|
||||
@@ -713,9 +718,11 @@ static void rmi_remove(struct hid_device *hdev)
|
||||
{
|
||||
struct rmi_data *hdata = hid_get_drvdata(hdev);
|
||||
|
||||
- clear_bit(RMI_STARTED, &hdata->flags);
|
||||
- cancel_work_sync(&hdata->reset_work);
|
||||
- rmi_unregister_transport_device(&hdata->xport);
|
||||
+ if (hdata->device_flags & RMI_DEVICE) {
|
||||
+ clear_bit(RMI_STARTED, &hdata->flags);
|
||||
+ cancel_work_sync(&hdata->reset_work);
|
||||
+ rmi_unregister_transport_device(&hdata->xport);
|
||||
+ }
|
||||
|
||||
hid_hw_stop(hdev);
|
||||
}
|
||||
--
|
||||
2.14.3
|
||||
|
|
@ -1,51 +0,0 @@
|
|||
From patchwork Thu Sep 28 20:07:19 2017
|
||||
Content-Type: text/plain; charset="utf-8"
|
||||
MIME-Version: 1.0
|
||||
Content-Transfer-Encoding: 8bit
|
||||
Subject: Input: synaptics - Disable kernel tracking on SMBus devices
|
||||
From: Andrew Duggan <aduggan@synaptics.com>
|
||||
X-Patchwork-Id: 9976729
|
||||
Message-Id: <1506629239-5940-1-git-send-email-aduggan@synaptics.com>
|
||||
To: linux-input@vger.kernel.org, linux-kernel@vger.kernel.org
|
||||
Cc: Andrew Duggan <aduggan@synaptics.com>,
|
||||
Dmitry Torokhov <dmitry.torokhov@gmail.com>,
|
||||
Benjamin Tissoires <benjamin.tissoires@redhat.com>,
|
||||
=?UTF-8?q?Kamil=20P=C3=A1ral?= <kparal@redhat.com>
|
||||
Date: Thu, 28 Sep 2017 13:07:19 -0700
|
||||
|
||||
In certain situations kernel tracking seems to be getting confused
|
||||
and incorrectly reporting the slot of a contact. On example is when
|
||||
the user does a three finger click or tap and then places two fingers
|
||||
on the touchpad in the same area. The kernel tracking code seems to
|
||||
continue to think that there are three contacts on the touchpad and
|
||||
incorrectly alternates the slot of one of the contacts. The result that
|
||||
is the input subsystem reports a stream of button press and release
|
||||
events as the reported slot changes.
|
||||
|
||||
Kernel tracking was originally enabled to prevent cursor jumps, but it
|
||||
is unclear how much of an issue kernel jumps actually are. This patch
|
||||
simply disabled kernel tracking for now.
|
||||
|
||||
Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=1482640
|
||||
|
||||
Signed-off-by: Andrew Duggan <aduggan@synaptics.com>
|
||||
Tested-by: Kamil Páral <kparal@redhat.com>
|
||||
Acked-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
|
||||
---
|
||||
drivers/input/mouse/synaptics.c | 3 +--
|
||||
1 file changed, 1 insertion(+), 2 deletions(-)
|
||||
|
||||
diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c
|
||||
index 5af0b7d..ee5466a 100644
|
||||
--- a/drivers/input/mouse/synaptics.c
|
||||
+++ b/drivers/input/mouse/synaptics.c
|
||||
@@ -1709,8 +1709,7 @@ static int synaptics_create_intertouch(struct psmouse *psmouse,
|
||||
.sensor_pdata = {
|
||||
.sensor_type = rmi_sensor_touchpad,
|
||||
.axis_align.flip_y = true,
|
||||
- /* to prevent cursors jumps: */
|
||||
- .kernel_tracking = true,
|
||||
+ .kernel_tracking = false,
|
||||
.topbuttonpad = topbuttonpad,
|
||||
},
|
||||
.f30_data = {
|
|
@ -1,102 +0,0 @@
|
|||
From 2a54526850121cd0d7cf649a321488b4dab5731d Mon Sep 17 00:00:00 2001
|
||||
From: Josh Boyer <jwboyer@fedoraproject.org>
|
||||
Date: Fri, 26 Oct 2012 12:36:24 -0400
|
||||
Subject: [PATCH 17/20] KEYS: Add a system blacklist keyring
|
||||
|
||||
This adds an additional keyring that is used to store certificates that
|
||||
are blacklisted. This keyring is searched first when loading signed modules
|
||||
and if the module's certificate is found, it will refuse to load. This is
|
||||
useful in cases where third party certificates are used for module signing.
|
||||
|
||||
Signed-off-by: Josh Boyer <jwboyer@fedoraproject.org>
|
||||
---
|
||||
certs/system_keyring.c | 22 ++++++++++++++++++++++
|
||||
include/keys/system_keyring.h | 4 ++++
|
||||
init/Kconfig | 9 +++++++++
|
||||
3 files changed, 35 insertions(+)
|
||||
|
||||
diff --git a/certs/system_keyring.c b/certs/system_keyring.c
|
||||
index 50979d6dcecd..787eeead2f57 100644
|
||||
--- a/certs/system_keyring.c
|
||||
+++ b/certs/system_keyring.c
|
||||
@@ -22,6 +22,9 @@ static struct key *builtin_trusted_keys;
|
||||
#ifdef CONFIG_SECONDARY_TRUSTED_KEYRING
|
||||
static struct key *secondary_trusted_keys;
|
||||
#endif
|
||||
+#ifdef CONFIG_SYSTEM_BLACKLIST_KEYRING
|
||||
+struct key *system_blacklist_keyring;
|
||||
+#endif
|
||||
|
||||
extern __initconst const u8 system_certificate_list[];
|
||||
extern __initconst const unsigned long system_certificate_list_size;
|
||||
@@ -99,6 +102,16 @@ static __init int system_trusted_keyring_init(void)
|
||||
if (key_link(secondary_trusted_keys, builtin_trusted_keys) < 0)
|
||||
panic("Can't link trusted keyrings\n");
|
||||
#endif
|
||||
+#ifdef CONFIG_SYSTEM_BLACKLIST_KEYRING
|
||||
+ system_blacklist_keyring = keyring_alloc(".system_blacklist_keyring",
|
||||
+ KUIDT_INIT(0), KGIDT_INIT(0), current_cred(),
|
||||
+ ((KEY_POS_ALL & ~KEY_POS_SETATTR) |
|
||||
+ KEY_USR_VIEW | KEY_USR_READ | KEY_USR_SEARCH),
|
||||
+ KEY_ALLOC_NOT_IN_QUOTA,
|
||||
+ NULL, NULL);
|
||||
+ if (IS_ERR(system_blacklist_keyring))
|
||||
+ panic("Can't allocate system blacklist keyring\n");
|
||||
+#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -214,6 +227,15 @@ int verify_pkcs7_signature(const void *data, size_t len,
|
||||
trusted_keys = builtin_trusted_keys;
|
||||
#endif
|
||||
}
|
||||
+#ifdef CONFIG_SYSTEM_BLACKLIST_KEYRING
|
||||
+ ret = pkcs7_validate_trust(pkcs7, system_blacklist_keyring);
|
||||
+ if (!ret) {
|
||||
+ /* module is signed with a cert in the blacklist. reject */
|
||||
+ pr_err("Module key is in the blacklist\n");
|
||||
+ ret = -EKEYREJECTED;
|
||||
+ goto error;
|
||||
+ }
|
||||
+#endif
|
||||
ret = pkcs7_validate_trust(pkcs7, trusted_keys);
|
||||
if (ret < 0) {
|
||||
if (ret == -ENOKEY)
|
||||
diff --git a/include/keys/system_keyring.h b/include/keys/system_keyring.h
|
||||
index fbd4647767e9..5bc291a3d261 100644
|
||||
--- a/include/keys/system_keyring.h
|
||||
+++ b/include/keys/system_keyring.h
|
||||
@@ -33,6 +33,10 @@ extern int restrict_link_by_builtin_and_secondary_trusted(
|
||||
#define restrict_link_by_builtin_and_secondary_trusted restrict_link_by_builtin_trusted
|
||||
#endif
|
||||
|
||||
+#ifdef CONFIG_SYSTEM_BLACKLIST_KEYRING
|
||||
+extern struct key *system_blacklist_keyring;
|
||||
+#endif
|
||||
+
|
||||
#ifdef CONFIG_IMA_BLACKLIST_KEYRING
|
||||
extern struct key *ima_blacklist_keyring;
|
||||
|
||||
diff --git a/init/Kconfig b/init/Kconfig
|
||||
index 34407f15e6d3..461ad575a608 100644
|
||||
--- a/init/Kconfig
|
||||
+++ b/init/Kconfig
|
||||
@@ -1859,6 +1859,15 @@ config SYSTEM_DATA_VERIFICATION
|
||||
module verification, kexec image verification and firmware blob
|
||||
verification.
|
||||
|
||||
+config SYSTEM_BLACKLIST_KEYRING
|
||||
+ bool "Provide system-wide ring of blacklisted keys"
|
||||
+ depends on KEYS
|
||||
+ help
|
||||
+ Provide a system keyring to which blacklisted keys can be added.
|
||||
+ Keys in the keyring are considered entirely untrusted. Keys in this
|
||||
+ keyring are used by the module signature checking to reject loading
|
||||
+ of modules signed with a blacklisted key.
|
||||
+
|
||||
config PROFILING
|
||||
bool "Profiling support"
|
||||
help
|
||||
--
|
||||
2.9.3
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
From patchwork Mon Oct 2 14:08:40 2017
|
||||
Content-Type: text/plain; charset="utf-8"
|
||||
MIME-Version: 1.0
|
||||
Content-Transfer-Encoding: 7bit
|
||||
Subject: PCI: aspm: deal with missing root ports in link state handling
|
||||
From: Ard Biesheuvel <ard.biesheuvel@linaro.org>
|
||||
X-Patchwork-Id: 9980861
|
||||
Message-Id: <20171002140840.7767-1-ard.biesheuvel@linaro.org>
|
||||
To: linux-pci@vger.kernel.org, bhelgaas@google.com
|
||||
Cc: graeme.gregory@linaro.org, leif.lindholm@linaro.org,
|
||||
daniel.thompson@Linaro.org, Ard Biesheuvel <ard.biesheuvel@linaro.org>
|
||||
Date: Mon, 2 Oct 2017 15:08:40 +0100
|
||||
|
||||
Even though it is unconventional, some PCIe host implementations omit
|
||||
the root ports entirely, and simply consist of a host bridge (which
|
||||
is not modeled as a device in the PCI hierarchy) and a link.
|
||||
|
||||
When the downstream device is an endpoint, our current code does not
|
||||
seem to mind this unusual configuration. However, when PCIe switches
|
||||
are involved, the ASPM code assumes that any downstream switch port
|
||||
has a parent, and blindly derefences the bus->parent->self field of
|
||||
the pci_dev struct to chain the downstream link state to the link
|
||||
state of the root port. Given that the root port is missing, the link
|
||||
is not modeled at all, and nor is the link state, and attempting to
|
||||
access it results in a NULL pointer dereference and a crash.
|
||||
|
||||
So let's avoid this by allowing the link state chain to terminate at
|
||||
the downstream port if no root port exists.
|
||||
|
||||
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
|
||||
---
|
||||
drivers/pci/pcie/aspm.c | 8 ++++++--
|
||||
1 file changed, 6 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/drivers/pci/pcie/aspm.c b/drivers/pci/pcie/aspm.c
|
||||
index 1dfa10cc566b..0bea8498b5a5 100644
|
||||
--- a/drivers/pci/pcie/aspm.c
|
||||
+++ b/drivers/pci/pcie/aspm.c
|
||||
@@ -802,10 +802,14 @@ static struct pcie_link_state *alloc_pcie_link_state(struct pci_dev *pdev)
|
||||
|
||||
/*
|
||||
* Root Ports and PCI/PCI-X to PCIe Bridges are roots of PCIe
|
||||
- * hierarchies.
|
||||
+ * hierarchies. Note that some PCIe host implementations omit
|
||||
+ * the root ports entirely, in which case a downstream port on
|
||||
+ * a switch may become the root of the link state chain for all
|
||||
+ * its subordinate endpoints.
|
||||
*/
|
||||
if (pci_pcie_type(pdev) == PCI_EXP_TYPE_ROOT_PORT ||
|
||||
- pci_pcie_type(pdev) == PCI_EXP_TYPE_PCIE_BRIDGE) {
|
||||
+ pci_pcie_type(pdev) == PCI_EXP_TYPE_PCIE_BRIDGE ||
|
||||
+ !pdev->bus->parent->self) {
|
||||
link->root = link;
|
||||
} else {
|
||||
struct pcie_link_state *parent;
|
|
@ -1,156 +0,0 @@
|
|||
From patchwork Thu Jun 15 15:28:58 2017
|
||||
Content-Type: text/plain; charset="utf-8"
|
||||
MIME-Version: 1.0
|
||||
Content-Transfer-Encoding: 7bit
|
||||
Subject: [RFC] audit: fix a race condition with the auditd tracking code
|
||||
From: Paul Moore <pmoore@redhat.com>
|
||||
X-Patchwork-Id: 9789009
|
||||
Message-Id: <149754053819.11365.5047864735077505545.stgit@sifl>
|
||||
To: linux-audit@redhat.com
|
||||
Cc: Dusty Mabe <dustymabe@redhat.com>
|
||||
Date: Thu, 15 Jun 2017 11:28:58 -0400
|
||||
|
||||
From: Paul Moore <paul@paul-moore.com>
|
||||
|
||||
Originally reported by Adam and Dusty, it appears we have a small
|
||||
race window in kauditd_thread(), as documented in the Fedora BZ:
|
||||
|
||||
* https://bugzilla.redhat.com/show_bug.cgi?id=1459326#c35
|
||||
|
||||
"This issue is partly due to the read-copy nature of RCU, and
|
||||
partly due to how we sync the auditd_connection state across
|
||||
kauditd_thread and the audit control channel. The kauditd_thread
|
||||
thread is always running so it can service the record queues and
|
||||
emit the multicast messages, if it happens to be just past the
|
||||
"main_queue" label, but before the "if (sk == NULL || ...)"
|
||||
if-statement which calls auditd_reset() when the new auditd
|
||||
connection is registered it could end up resetting the auditd
|
||||
connection, regardless of if it is valid or not. This is a rather
|
||||
small window and the variable nature of multi-core scheduling
|
||||
explains why this is proving rather difficult to reproduce."
|
||||
|
||||
The fix is to have functions only call auditd_reset() when they
|
||||
believe that the kernel/auditd connection is still valid, e.g.
|
||||
non-NULL, and to have these callers pass their local copy of the
|
||||
auditd_connection pointer to auditd_reset() where it can be compared
|
||||
with the current connection state before resetting. If the caller
|
||||
has a stale state tracking pointer then the reset is ignored.
|
||||
|
||||
We also make a small change to kauditd_thread() so that if the
|
||||
kernel/auditd connection is dead we skip the retry queue and send the
|
||||
records straight to the hold queue. This is necessary as we used to
|
||||
rely on auditd_reset() to occasionally purge the retry queue but we
|
||||
are going to be calling the reset function much less now and we want
|
||||
to make sure the retry queue doesn't grow unbounded.
|
||||
|
||||
Reported-by: Adam Williamson <awilliam@redhat.com>
|
||||
Reported-by: Dusty Mabe <dustymabe@redhat.com>
|
||||
Signed-off-by: Paul Moore <paul@paul-moore.com>
|
||||
Reviewed-by: Richard Guy Briggs <rgb@redhat.com>
|
||||
---
|
||||
kernel/audit.c | 36 +++++++++++++++++++++++-------------
|
||||
1 file changed, 23 insertions(+), 13 deletions(-)
|
||||
|
||||
|
||||
--
|
||||
Linux-audit mailing list
|
||||
Linux-audit@redhat.com
|
||||
https://www.redhat.com/mailman/listinfo/linux-audit
|
||||
|
||||
diff --git a/kernel/audit.c b/kernel/audit.c
|
||||
index b2e877100242..e1e2b3abfb93 100644
|
||||
--- a/kernel/audit.c
|
||||
+++ b/kernel/audit.c
|
||||
@@ -575,12 +575,16 @@ static void kauditd_retry_skb(struct sk_buff *skb)
|
||||
|
||||
/**
|
||||
* auditd_reset - Disconnect the auditd connection
|
||||
+ * @ac: auditd connection state
|
||||
*
|
||||
* Description:
|
||||
* Break the auditd/kauditd connection and move all the queued records into the
|
||||
- * hold queue in case auditd reconnects.
|
||||
+ * hold queue in case auditd reconnects. It is important to note that the @ac
|
||||
+ * pointer should never be dereferenced inside this function as it may be NULL
|
||||
+ * or invalid, you can only compare the memory address! If @ac is NULL then
|
||||
+ * the connection will always be reset.
|
||||
*/
|
||||
-static void auditd_reset(void)
|
||||
+static void auditd_reset(const struct auditd_connection *ac)
|
||||
{
|
||||
unsigned long flags;
|
||||
struct sk_buff *skb;
|
||||
@@ -590,6 +594,11 @@ static void auditd_reset(void)
|
||||
spin_lock_irqsave(&auditd_conn_lock, flags);
|
||||
ac_old = rcu_dereference_protected(auditd_conn,
|
||||
lockdep_is_held(&auditd_conn_lock));
|
||||
+ if (ac && ac != ac_old) {
|
||||
+ /* someone already registered a new auditd connection */
|
||||
+ spin_unlock_irqrestore(&auditd_conn_lock, flags);
|
||||
+ return;
|
||||
+ }
|
||||
rcu_assign_pointer(auditd_conn, NULL);
|
||||
spin_unlock_irqrestore(&auditd_conn_lock, flags);
|
||||
|
||||
@@ -649,8 +658,8 @@ static int auditd_send_unicast_skb(struct sk_buff *skb)
|
||||
return rc;
|
||||
|
||||
err:
|
||||
- if (rc == -ECONNREFUSED)
|
||||
- auditd_reset();
|
||||
+ if (ac && rc == -ECONNREFUSED)
|
||||
+ auditd_reset(ac);
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -795,9 +804,9 @@ static int kauditd_thread(void *dummy)
|
||||
rc = kauditd_send_queue(sk, portid,
|
||||
&audit_hold_queue, UNICAST_RETRIES,
|
||||
NULL, kauditd_rehold_skb);
|
||||
- if (rc < 0) {
|
||||
+ if (ac && rc < 0) {
|
||||
sk = NULL;
|
||||
- auditd_reset();
|
||||
+ auditd_reset(ac);
|
||||
goto main_queue;
|
||||
}
|
||||
|
||||
@@ -805,9 +814,9 @@ static int kauditd_thread(void *dummy)
|
||||
rc = kauditd_send_queue(sk, portid,
|
||||
&audit_retry_queue, UNICAST_RETRIES,
|
||||
NULL, kauditd_hold_skb);
|
||||
- if (rc < 0) {
|
||||
+ if (ac && rc < 0) {
|
||||
sk = NULL;
|
||||
- auditd_reset();
|
||||
+ auditd_reset(ac);
|
||||
goto main_queue;
|
||||
}
|
||||
|
||||
@@ -815,12 +824,13 @@ static int kauditd_thread(void *dummy)
|
||||
/* process the main queue - do the multicast send and attempt
|
||||
* unicast, dump failed record sends to the retry queue; if
|
||||
* sk == NULL due to previous failures we will just do the
|
||||
- * multicast send and move the record to the retry queue */
|
||||
+ * multicast send and move the record to the hold queue */
|
||||
rc = kauditd_send_queue(sk, portid, &audit_queue, 1,
|
||||
kauditd_send_multicast_skb,
|
||||
- kauditd_retry_skb);
|
||||
- if (sk == NULL || rc < 0)
|
||||
- auditd_reset();
|
||||
+ (sk ?
|
||||
+ kauditd_retry_skb : kauditd_hold_skb));
|
||||
+ if (ac && rc < 0)
|
||||
+ auditd_reset(ac);
|
||||
sk = NULL;
|
||||
|
||||
/* drop our netns reference, no auditd sends past this line */
|
||||
@@ -1230,7 +1240,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
|
||||
auditd_pid, 1);
|
||||
|
||||
/* unregister the auditd connection */
|
||||
- auditd_reset();
|
||||
+ auditd_reset(NULL);
|
||||
}
|
||||
}
|
||||
if (s.mask & AUDIT_STATUS_RATE_LIMIT) {
|
|
@ -0,0 +1,48 @@
|
|||
From patchwork Sat Nov 11 15:31:18 2017
|
||||
Content-Type: text/plain; charset="utf-8"
|
||||
MIME-Version: 1.0
|
||||
Content-Transfer-Encoding: 7bit
|
||||
Subject: USB: ulpi: fix bus-node lookup
|
||||
From: Johan Hovold <johan@kernel.org>
|
||||
X-Patchwork-Id: 10054387
|
||||
Message-Id: <20171111153118.16038-1-johan@kernel.org>
|
||||
To: Heikki Krogerus <heikki.krogerus@linux.intel.com>
|
||||
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
|
||||
linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org,
|
||||
linux-arm-msm@vger.kernel.org, Rob Clark <robdclark@gmail.com>,
|
||||
Peter Robinson <pbrobinson@gmail.com>, Johan Hovold <johan@kernel.org>,
|
||||
stable <stable@vger.kernel.org>
|
||||
Date: Sat, 11 Nov 2017 16:31:18 +0100
|
||||
|
||||
Fix bus-node lookup during registration, which ended up searching the whole
|
||||
device tree depth-first starting at the parent (or grand parent) rather
|
||||
than just matching on its children.
|
||||
|
||||
To make things worse, the parent (or grand-parent) node could end being
|
||||
prematurely freed as well.
|
||||
|
||||
Fixes: ef6a7bcfb01c ("usb: ulpi: Support device discovery via DT")
|
||||
Reported-by: Peter Robinson <pbrobinson@gmail.com>
|
||||
Reported-by: Stephen Boyd <sboyd@codeaurora.org>
|
||||
Cc: stable <stable@vger.kernel.org> # 4.10
|
||||
Signed-off-by: Johan Hovold <johan@kernel.org>
|
||||
---
|
||||
drivers/usb/common/ulpi.c | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/drivers/usb/common/ulpi.c b/drivers/usb/common/ulpi.c
|
||||
index 8b351444cc40..9a2ab6751a23 100644
|
||||
--- a/drivers/usb/common/ulpi.c
|
||||
+++ b/drivers/usb/common/ulpi.c
|
||||
@@ -180,9 +180,9 @@ static int ulpi_of_register(struct ulpi *ulpi)
|
||||
/* Find a ulpi bus underneath the parent or the grandparent */
|
||||
parent = ulpi->dev.parent;
|
||||
if (parent->of_node)
|
||||
- np = of_find_node_by_name(parent->of_node, "ulpi");
|
||||
+ np = of_get_child_by_name(parent->of_node, "ulpi");
|
||||
else if (parent->parent && parent->parent->of_node)
|
||||
- np = of_find_node_by_name(parent->parent->of_node, "ulpi");
|
||||
+ np = of_get_child_by_name(parent->parent->of_node, "ulpi");
|
||||
if (!np)
|
||||
return 0;
|
||||
|
|
@ -1,231 +0,0 @@
|
|||
From patchwork Fri Jun 23 09:36:37 2017
|
||||
Content-Type: text/plain; charset="utf-8"
|
||||
MIME-Version: 1.0
|
||||
Content-Transfer-Encoding: 8bit
|
||||
Subject: [V4] acpi: acpica: fix acpi parse and parseext cache leaks
|
||||
From: Seunghun Han <kkamagui@gmail.com>
|
||||
X-Patchwork-Id: 9806085
|
||||
Message-Id: <1498210597-112293-1-git-send-email-kkamagui@gmail.com>
|
||||
To: lv.zheng@intel.com
|
||||
Cc: robert.moore@intel.com, rafael.j.wysocki@intel.com,
|
||||
linux-acpi@vger.kernel.org, devel@acpica.org,
|
||||
linux-kernel@vger.kernel.org, Seunghun Han <kkamagui@gmail.com>
|
||||
Date: Fri, 23 Jun 2017 18:36:37 +0900
|
||||
|
||||
I'm Seunghun Han, and I work for National Security Research Institute of
|
||||
South Korea.
|
||||
|
||||
I have been doing a research on ACPI and found an ACPI cache leak in ACPI
|
||||
early abort cases.
|
||||
|
||||
Boot log of ACPI cache leak is as follows:
|
||||
[ 0.352414] ACPI: Added _OSI(Module Device)
|
||||
[ 0.353182] ACPI: Added _OSI(Processor Device)
|
||||
[ 0.353182] ACPI: Added _OSI(3.0 _SCP Extensions)
|
||||
[ 0.353182] ACPI: Added _OSI(Processor Aggregator Device)
|
||||
[ 0.356028] ACPI: Unable to start the ACPI Interpreter
|
||||
[ 0.356799] ACPI Error: Could not remove SCI handler (20170303/evmisc-281)
|
||||
[ 0.360215] kmem_cache_destroy Acpi-State: Slab cache still has objects
|
||||
[ 0.360648] CPU: 0 PID: 1 Comm: swapper/0 Tainted: G W
|
||||
4.12.0-rc4-next-20170608+ #10
|
||||
[ 0.361273] Hardware name: innotek GmbH VirtualBox/VirtualBox, BIOS
|
||||
VirtualBox 12/01/2006
|
||||
[ 0.361873] Call Trace:
|
||||
[ 0.362243] ? dump_stack+0x5c/0x81
|
||||
[ 0.362591] ? kmem_cache_destroy+0x1aa/0x1c0
|
||||
[ 0.362944] ? acpi_sleep_proc_init+0x27/0x27
|
||||
[ 0.363296] ? acpi_os_delete_cache+0xa/0x10
|
||||
[ 0.363646] ? acpi_ut_delete_caches+0x6d/0x7b
|
||||
[ 0.364000] ? acpi_terminate+0xa/0x14
|
||||
[ 0.364000] ? acpi_init+0x2af/0x34f
|
||||
[ 0.364000] ? __class_create+0x4c/0x80
|
||||
[ 0.364000] ? video_setup+0x7f/0x7f
|
||||
[ 0.364000] ? acpi_sleep_proc_init+0x27/0x27
|
||||
[ 0.364000] ? do_one_initcall+0x4e/0x1a0
|
||||
[ 0.364000] ? kernel_init_freeable+0x189/0x20a
|
||||
[ 0.364000] ? rest_init+0xc0/0xc0
|
||||
[ 0.364000] ? kernel_init+0xa/0x100
|
||||
[ 0.364000] ? ret_from_fork+0x25/0x30
|
||||
|
||||
I analyzed this memory leak in detail. I found that “Acpi-State” cache and
|
||||
“Acpi-Parse” cache were merged because the size of cache objects was same
|
||||
slab cache size.
|
||||
|
||||
I finally found “Acpi-Parse” cache and “Acpi-ParseExt” cache were leaked
|
||||
using SLAB_NEVER_MERGE flag in kmem_cache_create() function.
|
||||
|
||||
Real ACPI cache leak point is as follows:
|
||||
[ 0.360101] ACPI: Added _OSI(Module Device)
|
||||
[ 0.360101] ACPI: Added _OSI(Processor Device)
|
||||
[ 0.360101] ACPI: Added _OSI(3.0 _SCP Extensions)
|
||||
[ 0.361043] ACPI: Added _OSI(Processor Aggregator Device)
|
||||
[ 0.364016] ACPI: Unable to start the ACPI Interpreter
|
||||
[ 0.365061] ACPI Error: Could not remove SCI handler (20170303/evmisc-281)
|
||||
[ 0.368174] kmem_cache_destroy Acpi-Parse: Slab cache still has objects
|
||||
[ 0.369332] CPU: 1 PID: 1 Comm: swapper/0 Tainted: G W
|
||||
4.12.0-rc4-next-20170608+ #8
|
||||
[ 0.371256] Hardware name: innotek GmbH VirtualBox/VirtualBox, BIOS
|
||||
VirtualBox 12/01/2006
|
||||
[ 0.372000] Call Trace:
|
||||
[ 0.372000] ? dump_stack+0x5c/0x81
|
||||
[ 0.372000] ? kmem_cache_destroy+0x1aa/0x1c0
|
||||
[ 0.372000] ? acpi_sleep_proc_init+0x27/0x27
|
||||
[ 0.372000] ? acpi_os_delete_cache+0xa/0x10
|
||||
[ 0.372000] ? acpi_ut_delete_caches+0x56/0x7b
|
||||
[ 0.372000] ? acpi_terminate+0xa/0x14
|
||||
[ 0.372000] ? acpi_init+0x2af/0x34f
|
||||
[ 0.372000] ? __class_create+0x4c/0x80
|
||||
[ 0.372000] ? video_setup+0x7f/0x7f
|
||||
[ 0.372000] ? acpi_sleep_proc_init+0x27/0x27
|
||||
[ 0.372000] ? do_one_initcall+0x4e/0x1a0
|
||||
[ 0.372000] ? kernel_init_freeable+0x189/0x20a
|
||||
[ 0.372000] ? rest_init+0xc0/0xc0
|
||||
[ 0.372000] ? kernel_init+0xa/0x100
|
||||
[ 0.372000] ? ret_from_fork+0x25/0x30
|
||||
[ 0.388039] kmem_cache_destroy Acpi-ParseExt: Slab cache still has objects
|
||||
[ 0.389063] CPU: 1 PID: 1 Comm: swapper/0 Tainted: G W
|
||||
4.12.0-rc4-next-20170608+ #8
|
||||
[ 0.390557] Hardware name: innotek GmbH VirtualBox/VirtualBox, BIOS
|
||||
VirtualBox 12/01/2006
|
||||
[ 0.392000] Call Trace:
|
||||
[ 0.392000] ? dump_stack+0x5c/0x81
|
||||
[ 0.392000] ? kmem_cache_destroy+0x1aa/0x1c0
|
||||
[ 0.392000] ? acpi_sleep_proc_init+0x27/0x27
|
||||
[ 0.392000] ? acpi_os_delete_cache+0xa/0x10
|
||||
[ 0.392000] ? acpi_ut_delete_caches+0x6d/0x7b
|
||||
[ 0.392000] ? acpi_terminate+0xa/0x14
|
||||
[ 0.392000] ? acpi_init+0x2af/0x34f
|
||||
[ 0.392000] ? __class_create+0x4c/0x80
|
||||
[ 0.392000] ? video_setup+0x7f/0x7f
|
||||
[ 0.392000] ? acpi_sleep_proc_init+0x27/0x27
|
||||
[ 0.392000] ? do_one_initcall+0x4e/0x1a0
|
||||
[ 0.392000] ? kernel_init_freeable+0x189/0x20a
|
||||
[ 0.392000] ? rest_init+0xc0/0xc0
|
||||
[ 0.392000] ? kernel_init+0xa/0x100
|
||||
[ 0.392000] ? ret_from_fork+0x25/0x30
|
||||
|
||||
When early abort is occurred due to invalid ACPI information, Linux kernel
|
||||
terminates ACPI by calling acpi_terminate() function. The function calls
|
||||
acpi_ut_delete_caches() function to delete local caches (acpi_gbl_namespace_
|
||||
cache, state_cache, operand_cache, ps_node_cache, ps_node_ext_cache).
|
||||
|
||||
But the deletion codes in acpi_ut_delete_caches() function only delete
|
||||
slab caches using kmem_cache_destroy() function, therefore the cache
|
||||
objects should be flushed before acpi_ut_delete_caches() function.
|
||||
|
||||
“Acpi-Parse” cache and “Acpi-ParseExt” cache are used in an AML parse
|
||||
function, acpi_ps_parse_loop(). The function should have flush codes to
|
||||
handle an error state due to invalid AML codes.
|
||||
|
||||
This cache leak has a security threat because an old kernel (<= 4.9) shows
|
||||
memory locations of kernel functions in stack dump. Some malicious users
|
||||
could use this information to neutralize kernel ASLR.
|
||||
|
||||
To fix ACPI cache leak for enhancing security, I made a patch which has
|
||||
flush codes in acpi_ps_parse_loop() function.
|
||||
|
||||
I hope that this patch improves the security of Linux kernel.
|
||||
|
||||
Thank you.
|
||||
|
||||
Signed-off-by: Seunghun Han <kkamagui@gmail.com>
|
||||
---
|
||||
Changes since v3: change control transfer according to reviewer's comments.
|
||||
Changes since v2: merge flush code with existing code and change comments.
|
||||
Changes since v1: move flush code to acpi_ps_complete_final_op() function.
|
||||
|
||||
drivers/acpi/acpica/psobject.c | 53 +++++++++++++-----------------------------
|
||||
1 file changed, 16 insertions(+), 37 deletions(-)
|
||||
|
||||
diff --git a/drivers/acpi/acpica/psobject.c b/drivers/acpi/acpica/psobject.c
|
||||
index 5bcb618..4539391 100644
|
||||
--- a/drivers/acpi/acpica/psobject.c
|
||||
+++ b/drivers/acpi/acpica/psobject.c
|
||||
@@ -608,7 +608,8 @@ acpi_status
|
||||
acpi_ps_complete_final_op(struct acpi_walk_state *walk_state,
|
||||
union acpi_parse_object *op, acpi_status status)
|
||||
{
|
||||
- acpi_status status2;
|
||||
+ acpi_status return_status = AE_OK;
|
||||
+ u8 ascending = TRUE;
|
||||
|
||||
ACPI_FUNCTION_TRACE_PTR(ps_complete_final_op, walk_state);
|
||||
|
||||
@@ -622,7 +623,8 @@ acpi_ps_complete_final_op(struct acpi_walk_state *walk_state,
|
||||
op));
|
||||
do {
|
||||
if (op) {
|
||||
- if (walk_state->ascending_callback != NULL) {
|
||||
+ if (ascending &&
|
||||
+ walk_state->ascending_callback != NULL) {
|
||||
walk_state->op = op;
|
||||
walk_state->op_info =
|
||||
acpi_ps_get_opcode_info(op->common.
|
||||
@@ -644,49 +646,26 @@ acpi_ps_complete_final_op(struct acpi_walk_state *walk_state,
|
||||
}
|
||||
|
||||
if (status == AE_CTRL_TERMINATE) {
|
||||
- status = AE_OK;
|
||||
-
|
||||
- /* Clean up */
|
||||
- do {
|
||||
- if (op) {
|
||||
- status2 =
|
||||
- acpi_ps_complete_this_op
|
||||
- (walk_state, op);
|
||||
- if (ACPI_FAILURE
|
||||
- (status2)) {
|
||||
- return_ACPI_STATUS
|
||||
- (status2);
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- acpi_ps_pop_scope(&
|
||||
- (walk_state->
|
||||
- parser_state),
|
||||
- &op,
|
||||
- &walk_state->
|
||||
- arg_types,
|
||||
- &walk_state->
|
||||
- arg_count);
|
||||
-
|
||||
- } while (op);
|
||||
-
|
||||
- return_ACPI_STATUS(status);
|
||||
+ ascending = FALSE;
|
||||
+ return_status = AE_CTRL_TERMINATE;
|
||||
}
|
||||
|
||||
else if (ACPI_FAILURE(status)) {
|
||||
|
||||
/* First error is most important */
|
||||
|
||||
- (void)
|
||||
- acpi_ps_complete_this_op(walk_state,
|
||||
- op);
|
||||
- return_ACPI_STATUS(status);
|
||||
+ ascending = FALSE;
|
||||
+ return_status = status;
|
||||
}
|
||||
}
|
||||
|
||||
- status2 = acpi_ps_complete_this_op(walk_state, op);
|
||||
- if (ACPI_FAILURE(status2)) {
|
||||
- return_ACPI_STATUS(status2);
|
||||
+ status = acpi_ps_complete_this_op(walk_state, op);
|
||||
+ if (ACPI_FAILURE(status)) {
|
||||
+ ascending = FALSE;
|
||||
+ if (ACPI_SUCCESS(return_status) ||
|
||||
+ return_status == AE_CTRL_TERMINATE) {
|
||||
+ return_status = status;
|
||||
+ }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -696,5 +675,5 @@ acpi_ps_complete_final_op(struct acpi_walk_state *walk_state,
|
||||
|
||||
} while (op);
|
||||
|
||||
- return_ACPI_STATUS(status);
|
||||
+ return_ACPI_STATUS(return_status);
|
||||
}
|
|
@ -1,107 +0,0 @@
|
|||
From patchwork Thu Aug 24 05:11:35 2017
|
||||
Content-Type: text/plain; charset="utf-8"
|
||||
MIME-Version: 1.0
|
||||
Content-Transfer-Encoding: 7bit
|
||||
Subject: acpi: acpica: fix acpi operand cache leak in dsutils.c
|
||||
From: Seunghun Han <kkamagui@gmail.com>
|
||||
X-Patchwork-Id: 9919053
|
||||
Message-Id: <1503551495-33286-1-git-send-email-kkamagui@gmail.com>
|
||||
To: lv.zheng@intel.com
|
||||
Cc: robert.moore@intel.com, rafael.j.wysocki@intel.com,
|
||||
linux-acpi@vger.kernel.org, devel@acpica.org,
|
||||
linux-kernel@vger.kernel.org, security@kernel.org,
|
||||
Seunghun Han <kkamagui@gmail.com>
|
||||
Date: Thu, 24 Aug 2017 14:11:35 +0900
|
||||
|
||||
I found an ACPI cache leak in ACPI early termination and boot continuing case.
|
||||
|
||||
When early termination is occurred due to malicious ACPI table, Linux kernel
|
||||
terminates ACPI function and continues to boot process. While kernel terminates
|
||||
ACPI function, kmem_cache_destroy() reports Acpi-Operand cache leak.
|
||||
|
||||
Boot log of ACPI operand cache leak is as follows:
|
||||
>[ 0.585957] ACPI: Added _OSI(Module Device)
|
||||
>[ 0.587218] ACPI: Added _OSI(Processor Device)
|
||||
>[ 0.588530] ACPI: Added _OSI(3.0 _SCP Extensions)
|
||||
>[ 0.589790] ACPI: Added _OSI(Processor Aggregator Device)
|
||||
>[ 0.591534] ACPI Error: Illegal I/O port address/length above 64K: C806E00000004002/0x2 (20170303/hwvalid-155)
|
||||
>[ 0.594351] ACPI Exception: AE_LIMIT, Unable to initialize fixed events (20170303/evevent-88)
|
||||
>[ 0.597858] ACPI: Unable to start the ACPI Interpreter
|
||||
>[ 0.599162] ACPI Error: Could not remove SCI handler (20170303/evmisc-281)
|
||||
>[ 0.601836] kmem_cache_destroy Acpi-Operand: Slab cache still has objects
|
||||
>[ 0.603556] CPU: 0 PID: 1 Comm: swapper/0 Not tainted 4.12.0-rc5 #26
|
||||
>[ 0.605159] Hardware name: innotek GmbH VirtualBox/VirtualBox, BIOS VirtualBox 12/01/2006
|
||||
>[ 0.609177] Call Trace:
|
||||
>[ 0.610063] ? dump_stack+0x5c/0x81
|
||||
>[ 0.611118] ? kmem_cache_destroy+0x1aa/0x1c0
|
||||
>[ 0.612632] ? acpi_sleep_proc_init+0x27/0x27
|
||||
>[ 0.613906] ? acpi_os_delete_cache+0xa/0x10
|
||||
>[ 0.617986] ? acpi_ut_delete_caches+0x3f/0x7b
|
||||
>[ 0.619293] ? acpi_terminate+0xa/0x14
|
||||
>[ 0.620394] ? acpi_init+0x2af/0x34f
|
||||
>[ 0.621616] ? __class_create+0x4c/0x80
|
||||
>[ 0.623412] ? video_setup+0x7f/0x7f
|
||||
>[ 0.624585] ? acpi_sleep_proc_init+0x27/0x27
|
||||
>[ 0.625861] ? do_one_initcall+0x4e/0x1a0
|
||||
>[ 0.627513] ? kernel_init_freeable+0x19e/0x21f
|
||||
>[ 0.628972] ? rest_init+0x80/0x80
|
||||
>[ 0.630043] ? kernel_init+0xa/0x100
|
||||
>[ 0.631084] ? ret_from_fork+0x25/0x30
|
||||
>[ 0.633343] vgaarb: loaded
|
||||
>[ 0.635036] EDAC MC: Ver: 3.0.0
|
||||
>[ 0.638601] PCI: Probing PCI hardware
|
||||
>[ 0.639833] PCI host bridge to bus 0000:00
|
||||
>[ 0.641031] pci_bus 0000:00: root bus resource [io 0x0000-0xffff]
|
||||
> ... Continue to boot and log is omitted ...
|
||||
|
||||
I analyzed this memory leak in detail and found acpi_ds_obj_stack_pop_and_
|
||||
delete() function miscalculated the top of the stack. acpi_ds_obj_stack_push()
|
||||
function uses walk_state->operand_index for start position of the top, but
|
||||
acpi_ds_obj_stack_pop_and_delete() function considers index 0 for it.
|
||||
Therefore, this causes acpi operand memory leak.
|
||||
|
||||
This cache leak causes a security threat because an old kernel (<= 4.9) shows
|
||||
memory locations of kernel functions in stack dump. Some malicious users
|
||||
could use this information to neutralize kernel ASLR.
|
||||
|
||||
I made a patch to fix ACPI operand cache leak.
|
||||
|
||||
Signed-off-by: Seunghun Han <kkamagui@gmail.com>
|
||||
---
|
||||
drivers/acpi/acpica/dsutils.c | 9 ++++++++-
|
||||
1 file changed, 8 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/drivers/acpi/acpica/dsutils.c b/drivers/acpi/acpica/dsutils.c
|
||||
index 0dabd9b..2c8a060 100644
|
||||
--- a/drivers/acpi/acpica/dsutils.c
|
||||
+++ b/drivers/acpi/acpica/dsutils.c
|
||||
@@ -705,6 +705,8 @@ acpi_ds_create_operands(struct acpi_walk_state *walk_state,
|
||||
union acpi_parse_object *arguments[ACPI_OBJ_NUM_OPERANDS];
|
||||
u32 arg_count = 0;
|
||||
u32 index = walk_state->num_operands;
|
||||
+ u32 prev_num_operands = walk_state->num_operands;
|
||||
+ u32 new_num_operands;
|
||||
u32 i;
|
||||
|
||||
ACPI_FUNCTION_TRACE_PTR(ds_create_operands, first_arg);
|
||||
@@ -733,6 +735,7 @@ acpi_ds_create_operands(struct acpi_walk_state *walk_state,
|
||||
|
||||
/* Create the interpreter arguments, in reverse order */
|
||||
|
||||
+ new_num_operands = index;
|
||||
index--;
|
||||
for (i = 0; i < arg_count; i++) {
|
||||
arg = arguments[index];
|
||||
@@ -757,7 +760,11 @@ acpi_ds_create_operands(struct acpi_walk_state *walk_state,
|
||||
* pop everything off of the operand stack and delete those
|
||||
* objects
|
||||
*/
|
||||
- acpi_ds_obj_stack_pop_and_delete(arg_count, walk_state);
|
||||
+ walk_state->num_operands = i;
|
||||
+ acpi_ds_obj_stack_pop_and_delete(new_num_operands, walk_state);
|
||||
+
|
||||
+ /* Restore operand count */
|
||||
+ walk_state->num_operands = prev_num_operands;
|
||||
|
||||
ACPI_EXCEPTION((AE_INFO, status, "While creating Arg %u", index));
|
||||
return_ACPI_STATUS(status);
|
|
@ -1,96 +0,0 @@
|
|||
From patchwork Wed Jul 19 07:07:23 2017
|
||||
Content-Type: text/plain; charset="utf-8"
|
||||
MIME-Version: 1.0
|
||||
Content-Transfer-Encoding: 7bit
|
||||
Subject: acpi: acpica: fix acpi operand cache leak in nseval.c
|
||||
From: Seunghun Han <kkamagui@gmail.com>
|
||||
X-Patchwork-Id: 9850567
|
||||
Message-Id: <1500448043-137615-1-git-send-email-kkamagui@gmail.com>
|
||||
To: Lv Zheng <lv.zheng@intel.com>
|
||||
Cc: Robert Moore <robert.moore@intel.com>,
|
||||
"Rafael J. Wysocki" <rafael.j.wysocki@intel.com>,
|
||||
linux-acpi@vger.kernel.org, devel@acpica.org,
|
||||
linux-kernel@vger.kernel.org, security@kernel.org,
|
||||
Seunghun Han <kkamagui@gmail.com>
|
||||
Date: Wed, 19 Jul 2017 16:07:23 +0900
|
||||
|
||||
I found an ACPI cache leak in ACPI early termination and boot continuing case.
|
||||
|
||||
When early termination occurs due to malicious ACPI table, Linux kernel
|
||||
terminates ACPI function and continues to boot process. While kernel terminates
|
||||
ACPI function, kmem_cache_destroy() reports Acpi-Operand cache leak.
|
||||
|
||||
Boot log of ACPI operand cache leak is as follows:
|
||||
>[ 0.464168] ACPI: Added _OSI(Module Device)
|
||||
>[ 0.467022] ACPI: Added _OSI(Processor Device)
|
||||
>[ 0.469376] ACPI: Added _OSI(3.0 _SCP Extensions)
|
||||
>[ 0.471647] ACPI: Added _OSI(Processor Aggregator Device)
|
||||
>[ 0.477997] ACPI Error: Null stack entry at ffff880215c0aad8 (20170303/exresop-174)
|
||||
>[ 0.482706] ACPI Exception: AE_AML_INTERNAL, While resolving operands for [OpcodeName unavailable] (20170303/dswexec-461)
|
||||
>[ 0.487503] ACPI Error: Method parse/execution failed [\DBG] (Node ffff88021710ab40), AE_AML_INTERNAL (20170303/psparse-543)
|
||||
>[ 0.492136] ACPI Error: Method parse/execution failed [\_SB._INI] (Node ffff88021710a618), AE_AML_INTERNAL (20170303/psparse-543)
|
||||
>[ 0.497683] ACPI: Interpreter enabled
|
||||
>[ 0.499385] ACPI: (supports S0)
|
||||
>[ 0.501151] ACPI: Using IOAPIC for interrupt routing
|
||||
>[ 0.503342] ACPI Error: Null stack entry at ffff880215c0aad8 (20170303/exresop-174)
|
||||
>[ 0.506522] ACPI Exception: AE_AML_INTERNAL, While resolving operands for [OpcodeName unavailable] (20170303/dswexec-461)
|
||||
>[ 0.510463] ACPI Error: Method parse/execution failed [\DBG] (Node ffff88021710ab40), AE_AML_INTERNAL (20170303/psparse-543)
|
||||
>[ 0.514477] ACPI Error: Method parse/execution failed [\_PIC] (Node ffff88021710ab18), AE_AML_INTERNAL (20170303/psparse-543)
|
||||
>[ 0.518867] ACPI Exception: AE_AML_INTERNAL, Evaluating _PIC (20170303/bus-991)
|
||||
>[ 0.522384] kmem_cache_destroy Acpi-Operand: Slab cache still has objects
|
||||
>[ 0.524597] CPU: 1 PID: 1 Comm: swapper/0 Not tainted 4.12.0-rc5 #26
|
||||
>[ 0.526795] Hardware name: innotek GmbH VirtualBox/VirtualBox, BIOS VirtualBox 12/01/2006
|
||||
>[ 0.529668] Call Trace:
|
||||
>[ 0.530811] ? dump_stack+0x5c/0x81
|
||||
>[ 0.532240] ? kmem_cache_destroy+0x1aa/0x1c0
|
||||
>[ 0.533905] ? acpi_os_delete_cache+0xa/0x10
|
||||
>[ 0.535497] ? acpi_ut_delete_caches+0x3f/0x7b
|
||||
>[ 0.537237] ? acpi_terminate+0xa/0x14
|
||||
>[ 0.538701] ? acpi_init+0x2af/0x34f
|
||||
>[ 0.540008] ? acpi_sleep_proc_init+0x27/0x27
|
||||
>[ 0.541593] ? do_one_initcall+0x4e/0x1a0
|
||||
>[ 0.543008] ? kernel_init_freeable+0x19e/0x21f
|
||||
>[ 0.546202] ? rest_init+0x80/0x80
|
||||
>[ 0.547513] ? kernel_init+0xa/0x100
|
||||
>[ 0.548817] ? ret_from_fork+0x25/0x30
|
||||
>[ 0.550587] vgaarb: loaded
|
||||
>[ 0.551716] EDAC MC: Ver: 3.0.0
|
||||
>[ 0.553744] PCI: Probing PCI hardware
|
||||
>[ 0.555038] PCI host bridge to bus 0000:00
|
||||
> ... Continue to boot and log is omitted ...
|
||||
|
||||
I analyzed this memory leak in detail and found acpi_ns_evaluate() function
|
||||
only removes info->return_object in AE_CTRL_RETURN_VALUE case. But, when errors
|
||||
occur, the status value is not AE_CTRL_RETURN_VALUE, and info->return_object is
|
||||
also not null. Therefore, this causes acpi operand memory leak.
|
||||
|
||||
This cache leak causes a security threat because an old kernel (<= 4.9) shows
|
||||
memory locations of kernel functions in stack dump. Some malicious users
|
||||
could use this information to neutralize kernel ASLR.
|
||||
|
||||
I made a patch to fix ACPI operand cache leak.
|
||||
|
||||
Signed-off-by: Seunghun Han <kkamagui@gmail.com>
|
||||
---
|
||||
drivers/acpi/acpica/nseval.c | 8 ++++++++
|
||||
1 file changed, 8 insertions(+)
|
||||
|
||||
diff --git a/drivers/acpi/acpica/nseval.c b/drivers/acpi/acpica/nseval.c
|
||||
index d22167c..f13d3cf 100644
|
||||
--- a/drivers/acpi/acpica/nseval.c
|
||||
+++ b/drivers/acpi/acpica/nseval.c
|
||||
@@ -308,6 +308,14 @@ acpi_status acpi_ns_evaluate(struct acpi_evaluate_info *info)
|
||||
/* Map AE_CTRL_RETURN_VALUE to AE_OK, we are done with it */
|
||||
|
||||
status = AE_OK;
|
||||
+ } else if (ACPI_FAILURE(status)) {
|
||||
+
|
||||
+ /* If return_object exists, delete it */
|
||||
+
|
||||
+ if (info->return_object) {
|
||||
+ acpi_ut_remove_reference(info->return_object);
|
||||
+ info->return_object = NULL;
|
||||
+ }
|
||||
}
|
||||
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_NAMES,
|
File diff suppressed because it is too large
Load Diff
|
@ -1,40 +0,0 @@
|
|||
From patchwork Mon May 22 14:51:38 2017
|
||||
Content-Type: text/plain; charset="utf-8"
|
||||
MIME-Version: 1.0
|
||||
Content-Transfer-Encoding: 7bit
|
||||
Subject: arm: dts: boneblack-wireless: add WL1835 Bluetooth device node
|
||||
From: Ricardo Salveti <ricardo.salveti@linaro.org>
|
||||
X-Patchwork-Id: 9740719
|
||||
Message-Id: <1495464701-12046-1-git-send-email-ricardo.salveti@linaro.org>
|
||||
To: linux-omap@vger.kernel.org
|
||||
Cc: Mark Rutland <mark.rutland@arm.com>,
|
||||
Ricardo Salveti <ricardo.salveti@linaro.org>, devicetree@vger.kernel.org,
|
||||
Tony Lindgren <tony@atomide.com>, Russell King <linux@armlinux.org.uk>,
|
||||
linux-kernel@vger.kernel.org, Rob Herring <robh+dt@kernel.org>,
|
||||
=?UTF-8?q?Beno=C3=AEt=20Cousson?= <bcousson@baylibre.com>,
|
||||
robertcnelson@gmail.com, linux-arm-kernel@lists.infradead.org
|
||||
Date: Mon, 22 May 2017 11:51:38 -0300
|
||||
|
||||
This adds the serial slave device for the WL1835 Bluetooth interface.
|
||||
|
||||
Signed-off-by: Ricardo Salveti <ricardo.salveti@linaro.org>
|
||||
---
|
||||
arch/arm/boot/dts/am335x-boneblack-wireless.dts | 5 +++++
|
||||
1 file changed, 5 insertions(+)
|
||||
|
||||
diff --git a/arch/arm/boot/dts/am335x-boneblack-wireless.dts b/arch/arm/boot/dts/am335x-boneblack-wireless.dts
|
||||
index 105bd10..83f49f6 100644
|
||||
--- a/arch/arm/boot/dts/am335x-boneblack-wireless.dts
|
||||
+++ b/arch/arm/boot/dts/am335x-boneblack-wireless.dts
|
||||
@@ -97,6 +97,11 @@
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&uart3_pins &bt_pins>;
|
||||
status = "okay";
|
||||
+
|
||||
+ bluetooth {
|
||||
+ compatible = "ti,wl1835-st";
|
||||
+ enable-gpios = <&gpio0 28 GPIO_ACTIVE_HIGH>;
|
||||
+ };
|
||||
};
|
||||
|
||||
&gpio3 {
|
|
@ -0,0 +1,411 @@
|
|||
From patchwork Mon Oct 9 12:00:50 2017
|
||||
Content-Type: text/plain; charset="utf-8"
|
||||
MIME-Version: 1.0
|
||||
Content-Transfer-Encoding: 7bit
|
||||
Subject: [PATCHv4,1/2] drivers: phy: add calibrate method
|
||||
From: Andrzej Pietrasiewicz <andrzej.p@samsung.com>
|
||||
X-Patchwork-Id: 9992829
|
||||
Message-Id: <1507550451-21324-2-git-send-email-andrzej.p@samsung.com>
|
||||
To: linux-samsung-soc@vger.kernel.org, linux-usb@vger.kernel.org,
|
||||
linux-arm-kernel@lists.infradead.org, devicetree@vger.kernel.org
|
||||
Cc: Mark Rutland <mark.rutland@arm.com>, Felipe Balbi <balbi@kernel.org>,
|
||||
Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>,
|
||||
Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
|
||||
Russell King <linux@armlinux.org.uk>,
|
||||
Krzysztof Kozlowski <krzk@kernel.org>,
|
||||
Kishon Vijay Abraham I <kishon@ti.com>,
|
||||
Rob Herring <robh+dt@kernel.org>, Kukjin Kim <kgene@kernel.org>,
|
||||
Andrzej Pietrasiewicz <andrzej.p@samsung.com>,
|
||||
Marek Szyprowski <m.szyprowski@samsung.com>
|
||||
Date: Mon, 09 Oct 2017 14:00:50 +0200
|
||||
|
||||
Some quirky UDCs (like dwc3 on Exynos) need to have their phys calibrated e.g.
|
||||
for using super speed. This patch adds a new phy_calibrate() method.
|
||||
When the calibration should be used is dependent on actual chip.
|
||||
|
||||
In case of dwc3 on Exynos the calibration must happen after usb_add_hcd()
|
||||
(while in host mode), because certain phy parameters like Tx LOS levels
|
||||
and boost levels need to be calibrated further post initialization of xHCI
|
||||
controller, to get SuperSpeed operations working. But an hcd must be
|
||||
prepared first in order to pass it to usb_add_hcd(), so, in particular, dwc3
|
||||
registers must be available first, and in order for the latter to happen
|
||||
the phys must be initialized. This poses a chicken and egg problem if
|
||||
the calibration were to be performed in phy_init(). To break the circular
|
||||
dependency a separate method is added which can be called at a desired
|
||||
moment after phy intialization.
|
||||
|
||||
Signed-off-by: Andrzej Pietrasiewicz <andrzej.p@samsung.com>
|
||||
---
|
||||
drivers/phy/phy-core.c | 15 +++++++++++++++
|
||||
include/linux/phy/phy.h | 10 ++++++++++
|
||||
2 files changed, 25 insertions(+)
|
||||
|
||||
diff --git a/drivers/phy/phy-core.c b/drivers/phy/phy-core.c
|
||||
index a268f4d..b4964b0 100644
|
||||
--- a/drivers/phy/phy-core.c
|
||||
+++ b/drivers/phy/phy-core.c
|
||||
@@ -372,6 +372,21 @@ int phy_reset(struct phy *phy)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(phy_reset);
|
||||
|
||||
+int phy_calibrate(struct phy *phy)
|
||||
+{
|
||||
+ int ret;
|
||||
+
|
||||
+ if (!phy || !phy->ops->calibrate)
|
||||
+ return 0;
|
||||
+
|
||||
+ mutex_lock(&phy->mutex);
|
||||
+ ret = phy->ops->calibrate(phy);
|
||||
+ mutex_unlock(&phy->mutex);
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+EXPORT_SYMBOL_GPL(phy_calibrate);
|
||||
+
|
||||
/**
|
||||
* _of_phy_get() - lookup and obtain a reference to a phy by phandle
|
||||
* @np: device_node for which to get the phy
|
||||
diff --git a/include/linux/phy/phy.h b/include/linux/phy/phy.h
|
||||
index e694d40..87580c8 100644
|
||||
--- a/include/linux/phy/phy.h
|
||||
+++ b/include/linux/phy/phy.h
|
||||
@@ -39,6 +39,7 @@ enum phy_mode {
|
||||
* @power_off: powering off the phy
|
||||
* @set_mode: set the mode of the phy
|
||||
* @reset: resetting the phy
|
||||
+ * @calibrate: calibrate the phy
|
||||
* @owner: the module owner containing the ops
|
||||
*/
|
||||
struct phy_ops {
|
||||
@@ -48,6 +49,7 @@ struct phy_ops {
|
||||
int (*power_off)(struct phy *phy);
|
||||
int (*set_mode)(struct phy *phy, enum phy_mode mode);
|
||||
int (*reset)(struct phy *phy);
|
||||
+ int (*calibrate)(struct phy *phy);
|
||||
struct module *owner;
|
||||
};
|
||||
|
||||
@@ -141,6 +143,7 @@ static inline void *phy_get_drvdata(struct phy *phy)
|
||||
int phy_power_off(struct phy *phy);
|
||||
int phy_set_mode(struct phy *phy, enum phy_mode mode);
|
||||
int phy_reset(struct phy *phy);
|
||||
+int phy_calibrate(struct phy *phy);
|
||||
static inline int phy_get_bus_width(struct phy *phy)
|
||||
{
|
||||
return phy->attrs.bus_width;
|
||||
@@ -262,6 +265,13 @@ static inline int phy_reset(struct phy *phy)
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
+static inline int phy_calibrate(struct phy *phy)
|
||||
+{
|
||||
+ if (!phy)
|
||||
+ return 0;
|
||||
+ return -ENOSYS;
|
||||
+}
|
||||
+
|
||||
static inline int phy_get_bus_width(struct phy *phy)
|
||||
{
|
||||
return -ENOSYS;
|
||||
From patchwork Mon Oct 9 12:00:51 2017
|
||||
Content-Type: text/plain; charset="utf-8"
|
||||
MIME-Version: 1.0
|
||||
Content-Transfer-Encoding: 7bit
|
||||
Subject: [PATCHv4,
|
||||
2/2] phy: exynos5-usbdrd: Calibrate LOS levels for exynos5420/5800
|
||||
From: Andrzej Pietrasiewicz <andrzej.p@samsung.com>
|
||||
X-Patchwork-Id: 9992809
|
||||
Message-Id: <1507550451-21324-3-git-send-email-andrzej.p@samsung.com>
|
||||
To: linux-samsung-soc@vger.kernel.org, linux-usb@vger.kernel.org,
|
||||
linux-arm-kernel@lists.infradead.org, devicetree@vger.kernel.org
|
||||
Cc: Mark Rutland <mark.rutland@arm.com>, Felipe Balbi <balbi@kernel.org>,
|
||||
Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>,
|
||||
Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
|
||||
Russell King <linux@armlinux.org.uk>,
|
||||
Krzysztof Kozlowski <krzk@kernel.org>,
|
||||
Kishon Vijay Abraham I <kishon@ti.com>,
|
||||
Rob Herring <robh+dt@kernel.org>, Kukjin Kim <kgene@kernel.org>,
|
||||
Andrzej Pietrasiewicz <andrzej.p@samsung.com>,
|
||||
Marek Szyprowski <m.szyprowski@samsung.com>
|
||||
Date: Mon, 09 Oct 2017 14:00:51 +0200
|
||||
|
||||
From: Vivek Gautam <gautam.vivek@samsung.com>
|
||||
|
||||
Adding phy calibration sequence for USB 3.0 DRD PHY present on
|
||||
Exynos5420/5800 systems.
|
||||
This calibration facilitates setting certain PHY parameters viz.
|
||||
the Loss-of-Signal (LOS) Detector Threshold Level, as well as
|
||||
Tx-Vboost-Level for Super-Speed operations.
|
||||
Additionally we also set proper time to wait for RxDetect measurement,
|
||||
for desired PHY reference clock, so as to solve issue with enumeration
|
||||
of few USB 3.0 devices, like Samsung SUM-TSB16S 3.0 USB drive
|
||||
on the controller.
|
||||
|
||||
We are using CR_port for this purpose to send required data
|
||||
to override the LOS values.
|
||||
|
||||
On testing with USB 3.0 devices on USB 3.0 port present on
|
||||
SMDK5420, and peach-pit boards should see following message:
|
||||
usb 2-1: new SuperSpeed USB device number 2 using xhci-hcd
|
||||
|
||||
and without this patch, should see below shown message:
|
||||
usb 1-1: new high-speed USB device number 2 using xhci-hcd
|
||||
|
||||
[Also removed unnecessary extra lines in the register macro definitions]
|
||||
|
||||
Signed-off-by: Vivek Gautam <gautam.vivek@samsung.com>
|
||||
[adapted to use phy_calibrate as entry point]
|
||||
Signed-off-by: Andrzej Pietrasiewicz <andrzej.p@samsung.com>
|
||||
---
|
||||
drivers/phy/samsung/phy-exynos5-usbdrd.c | 183 +++++++++++++++++++++++++++++++
|
||||
drivers/usb/dwc3/core.c | 7 +-
|
||||
2 files changed, 188 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/drivers/phy/samsung/phy-exynos5-usbdrd.c b/drivers/phy/samsung/phy-exynos5-usbdrd.c
|
||||
index 22c68f5..9e83c15 100644
|
||||
--- a/drivers/phy/samsung/phy-exynos5-usbdrd.c
|
||||
+++ b/drivers/phy/samsung/phy-exynos5-usbdrd.c
|
||||
@@ -90,7 +90,17 @@
|
||||
#define PHYCLKRST_COMMONONN BIT(0)
|
||||
|
||||
#define EXYNOS5_DRD_PHYREG0 0x14
|
||||
+#define PHYREG0_SSC_REF_CLK_SEL BIT(21)
|
||||
+#define PHYREG0_SSC_RANGE BIT(20)
|
||||
+#define PHYREG0_CR_WRITE BIT(19)
|
||||
+#define PHYREG0_CR_READ BIT(18)
|
||||
+#define PHYREG0_CR_DATA_IN(_x) ((_x) << 2)
|
||||
+#define PHYREG0_CR_CAP_DATA BIT(1)
|
||||
+#define PHYREG0_CR_CAP_ADDR BIT(0)
|
||||
+
|
||||
#define EXYNOS5_DRD_PHYREG1 0x18
|
||||
+#define PHYREG1_CR_DATA_OUT(_x) ((_x) << 1)
|
||||
+#define PHYREG1_CR_ACK BIT(0)
|
||||
|
||||
#define EXYNOS5_DRD_PHYPARAM0 0x1c
|
||||
|
||||
@@ -119,6 +129,25 @@
|
||||
#define EXYNOS5_DRD_PHYRESUME 0x34
|
||||
#define EXYNOS5_DRD_LINKPORT 0x44
|
||||
|
||||
+/* USB 3.0 DRD PHY SS Function Control Reg; accessed by CR_PORT */
|
||||
+#define EXYNOS5_DRD_PHYSS_LOSLEVEL_OVRD_IN (0x15)
|
||||
+#define LOSLEVEL_OVRD_IN_LOS_BIAS_5420 (0x5 << 13)
|
||||
+#define LOSLEVEL_OVRD_IN_LOS_BIAS_DEFAULT (0x0 << 13)
|
||||
+#define LOSLEVEL_OVRD_IN_EN (0x1 << 10)
|
||||
+#define LOSLEVEL_OVRD_IN_LOS_LEVEL_DEFAULT (0x9 << 0)
|
||||
+
|
||||
+#define EXYNOS5_DRD_PHYSS_TX_VBOOSTLEVEL_OVRD_IN (0x12)
|
||||
+#define TX_VBOOSTLEVEL_OVRD_IN_VBOOST_5420 (0x5 << 13)
|
||||
+#define TX_VBOOSTLEVEL_OVRD_IN_VBOOST_DEFAULT (0x4 << 13)
|
||||
+
|
||||
+#define EXYNOS5_DRD_PHYSS_LANE0_TX_DEBUG (0x1010)
|
||||
+#define LANE0_TX_DEBUG_RXDET_MEAS_TIME_19M2_20M (0x4 << 4)
|
||||
+#define LANE0_TX_DEBUG_RXDET_MEAS_TIME_24M (0x8 << 4)
|
||||
+#define LANE0_TX_DEBUG_RXDET_MEAS_TIME_25M_26M (0x8 << 4)
|
||||
+#define LANE0_TX_DEBUG_RXDET_MEAS_TIME_48M_50M_52M (0x20 << 4)
|
||||
+#define LANE0_TX_DEBUG_RXDET_MEAS_TIME_62M5 (0x20 << 4)
|
||||
+#define LANE0_TX_DEBUG_RXDET_MEAS_TIME_96M_100M (0x40 << 4)
|
||||
+
|
||||
#define KHZ 1000
|
||||
#define MHZ (KHZ * KHZ)
|
||||
|
||||
@@ -527,6 +556,151 @@ static int exynos5_usbdrd_phy_power_off(struct phy *phy)
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static int crport_handshake(struct exynos5_usbdrd_phy *phy_drd,
|
||||
+ u32 val, u32 cmd)
|
||||
+{
|
||||
+ u32 usec = 100;
|
||||
+ unsigned int result;
|
||||
+
|
||||
+ writel(val | cmd, phy_drd->reg_phy + EXYNOS5_DRD_PHYREG0);
|
||||
+
|
||||
+ do {
|
||||
+ result = readl(phy_drd->reg_phy + EXYNOS5_DRD_PHYREG1);
|
||||
+ if (result & PHYREG1_CR_ACK)
|
||||
+ break;
|
||||
+
|
||||
+ udelay(1);
|
||||
+ } while (usec-- > 0);
|
||||
+
|
||||
+ if (!usec) {
|
||||
+ dev_err(phy_drd->dev,
|
||||
+ "CRPORT handshake timeout1 (0x%08x)\n", val);
|
||||
+ return -ETIME;
|
||||
+ }
|
||||
+
|
||||
+ usec = 100;
|
||||
+
|
||||
+ writel(val, phy_drd->reg_phy + EXYNOS5_DRD_PHYREG0);
|
||||
+
|
||||
+ do {
|
||||
+ result = readl(phy_drd->reg_phy + EXYNOS5_DRD_PHYREG1);
|
||||
+ if (!(result & PHYREG1_CR_ACK))
|
||||
+ break;
|
||||
+
|
||||
+ udelay(1);
|
||||
+ } while (usec-- > 0);
|
||||
+
|
||||
+ if (!usec) {
|
||||
+ dev_err(phy_drd->dev,
|
||||
+ "CRPORT handshake timeout2 (0x%08x)\n", val);
|
||||
+ return -ETIME;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int crport_ctrl_write(struct exynos5_usbdrd_phy *phy_drd,
|
||||
+ u32 addr, u32 data)
|
||||
+{
|
||||
+ int ret;
|
||||
+
|
||||
+ /* Write Address */
|
||||
+ writel(PHYREG0_CR_DATA_IN(addr),
|
||||
+ phy_drd->reg_phy + EXYNOS5_DRD_PHYREG0);
|
||||
+ ret = crport_handshake(phy_drd, PHYREG0_CR_DATA_IN(addr),
|
||||
+ PHYREG0_CR_CAP_ADDR);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ /* Write Data */
|
||||
+ writel(PHYREG0_CR_DATA_IN(data),
|
||||
+ phy_drd->reg_phy + EXYNOS5_DRD_PHYREG0);
|
||||
+ ret = crport_handshake(phy_drd, PHYREG0_CR_DATA_IN(data),
|
||||
+ PHYREG0_CR_CAP_DATA);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ ret = crport_handshake(phy_drd, PHYREG0_CR_DATA_IN(data),
|
||||
+ PHYREG0_CR_WRITE);
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * Calibrate few PHY parameters using CR_PORT register to meet
|
||||
+ * SuperSpeed requirements on Exynos5420 and Exynos5800 systems,
|
||||
+ * which have 28nm USB 3.0 DRD PHY.
|
||||
+ */
|
||||
+static int exynos5420_usbdrd_phy_calibrate(struct exynos5_usbdrd_phy *phy_drd)
|
||||
+{
|
||||
+ unsigned int temp;
|
||||
+ int ret = 0;
|
||||
+
|
||||
+ /*
|
||||
+ * Change los_bias to (0x5) for 28nm PHY from a
|
||||
+ * default value (0x0); los_level is set as default
|
||||
+ * (0x9) as also reflected in los_level[30:26] bits
|
||||
+ * of PHYPARAM0 register.
|
||||
+ */
|
||||
+ temp = LOSLEVEL_OVRD_IN_LOS_BIAS_5420 |
|
||||
+ LOSLEVEL_OVRD_IN_EN |
|
||||
+ LOSLEVEL_OVRD_IN_LOS_LEVEL_DEFAULT;
|
||||
+ ret = crport_ctrl_write(phy_drd,
|
||||
+ EXYNOS5_DRD_PHYSS_LOSLEVEL_OVRD_IN,
|
||||
+ temp);
|
||||
+ if (ret) {
|
||||
+ dev_err(phy_drd->dev,
|
||||
+ "Failed setting Loss-of-Signal level for SuperSpeed\n");
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ /*
|
||||
+ * Set tx_vboost_lvl to (0x5) for 28nm PHY Tuning,
|
||||
+ * to raise Tx signal level from its default value of (0x4)
|
||||
+ */
|
||||
+ temp = TX_VBOOSTLEVEL_OVRD_IN_VBOOST_5420;
|
||||
+ ret = crport_ctrl_write(phy_drd,
|
||||
+ EXYNOS5_DRD_PHYSS_TX_VBOOSTLEVEL_OVRD_IN,
|
||||
+ temp);
|
||||
+ if (ret) {
|
||||
+ dev_err(phy_drd->dev,
|
||||
+ "Failed setting Tx-Vboost-Level for SuperSpeed\n");
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ /*
|
||||
+ * Set proper time to wait for RxDetect measurement, for
|
||||
+ * desired reference clock of PHY, by tuning the CR_PORT
|
||||
+ * register LANE0.TX_DEBUG which is internal to PHY.
|
||||
+ * This fixes issue with few USB 3.0 devices, which are
|
||||
+ * not detected (not even generate interrupts on the bus
|
||||
+ * on insertion) without this change.
|
||||
+ * e.g. Samsung SUM-TSB16S 3.0 USB drive.
|
||||
+ */
|
||||
+ switch (phy_drd->extrefclk) {
|
||||
+ case EXYNOS5_FSEL_50MHZ:
|
||||
+ temp = LANE0_TX_DEBUG_RXDET_MEAS_TIME_48M_50M_52M;
|
||||
+ break;
|
||||
+ case EXYNOS5_FSEL_20MHZ:
|
||||
+ case EXYNOS5_FSEL_19MHZ2:
|
||||
+ temp = LANE0_TX_DEBUG_RXDET_MEAS_TIME_19M2_20M;
|
||||
+ break;
|
||||
+ case EXYNOS5_FSEL_24MHZ:
|
||||
+ default:
|
||||
+ temp = LANE0_TX_DEBUG_RXDET_MEAS_TIME_24M;
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ ret = crport_ctrl_write(phy_drd,
|
||||
+ EXYNOS5_DRD_PHYSS_LANE0_TX_DEBUG,
|
||||
+ temp);
|
||||
+ if (ret)
|
||||
+ dev_err(phy_drd->dev,
|
||||
+ "Failed setting RxDetect measurement time for SuperSpeed\n");
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
static struct phy *exynos5_usbdrd_phy_xlate(struct device *dev,
|
||||
struct of_phandle_args *args)
|
||||
{
|
||||
@@ -538,11 +712,20 @@ static struct phy *exynos5_usbdrd_phy_xlate(struct device *dev,
|
||||
return phy_drd->phys[args->args[0]].phy;
|
||||
}
|
||||
|
||||
+static int exynos5_usbdrd_phy_calibrate(struct phy *phy)
|
||||
+{
|
||||
+ struct phy_usb_instance *inst = phy_get_drvdata(phy);
|
||||
+ struct exynos5_usbdrd_phy *phy_drd = to_usbdrd_phy(inst);
|
||||
+
|
||||
+ return exynos5420_usbdrd_phy_calibrate(phy_drd);
|
||||
+}
|
||||
+
|
||||
static const struct phy_ops exynos5_usbdrd_phy_ops = {
|
||||
.init = exynos5_usbdrd_phy_init,
|
||||
.exit = exynos5_usbdrd_phy_exit,
|
||||
.power_on = exynos5_usbdrd_phy_power_on,
|
||||
.power_off = exynos5_usbdrd_phy_power_off,
|
||||
+ .calibrate = exynos5_usbdrd_phy_calibrate,
|
||||
.owner = THIS_MODULE,
|
||||
};
|
||||
|
||||
diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
|
||||
index 03474d3..224e0dd 100644
|
||||
--- a/drivers/usb/dwc3/core.c
|
||||
+++ b/drivers/usb/dwc3/core.c
|
||||
@@ -156,9 +156,10 @@ static void __dwc3_set_mode(struct work_struct *work)
|
||||
} else {
|
||||
if (dwc->usb2_phy)
|
||||
otg_set_vbus(dwc->usb2_phy->otg, true);
|
||||
- if (dwc->usb2_generic_phy)
|
||||
+ if (dwc->usb2_generic_phy) {
|
||||
phy_set_mode(dwc->usb2_generic_phy, PHY_MODE_USB_HOST);
|
||||
-
|
||||
+ phy_calibrate(dwc->usb2_generic_phy);
|
||||
+ }
|
||||
}
|
||||
break;
|
||||
case DWC3_GCTL_PRTCAP_DEVICE:
|
||||
@@ -955,6 +956,8 @@ static int dwc3_core_init_mode(struct dwc3 *dwc)
|
||||
dev_err(dev, "failed to initialize host\n");
|
||||
return ret;
|
||||
}
|
||||
+ if (dwc->usb2_generic_phy)
|
||||
+ phy_calibrate(dwc->usb2_generic_phy);
|
||||
break;
|
||||
case USB_DR_MODE_OTG:
|
||||
INIT_WORK(&dwc->drd_work, __dwc3_set_mode);
|
|
@ -1,121 +0,0 @@
|
|||
From 723288836628bc1c0855f3bb7b64b1803e4b9e4a Mon Sep 17 00:00:00 2001
|
||||
From: Robin Murphy <robin.murphy@arm.com>
|
||||
Date: Thu, 31 Aug 2017 11:32:54 +0100
|
||||
Subject: of: restrict DMA configuration
|
||||
|
||||
Moving DMA configuration to happen later at driver probe time had the
|
||||
unnoticed side-effect that we now perform DMA configuration for *every*
|
||||
device represented in DT, rather than only those explicitly created by
|
||||
the of_platform and PCI code.
|
||||
|
||||
As Christoph points out, this is not really the best thing to do. Whilst
|
||||
there may well be other DMA-capable buses that can benefit from having
|
||||
their children automatically configured after the bridge has probed,
|
||||
there are also plenty of others like USB, MDIO, etc. that definitely do
|
||||
not support DMA and should not be indiscriminately processed.
|
||||
|
||||
The good news is that in most cases the DT "dma-ranges" property serves
|
||||
as an appropriate indicator - per a strict interpretation of the spec,
|
||||
anything lacking a "dma-ranges" property should be considered not to
|
||||
have a mapping of DMA address space from its children to its parent,
|
||||
thus anything for which of_dma_get_range() does not succeed does not
|
||||
need DMA configuration. Certain bus types have a general expectation of
|
||||
DMA capability and carry a well-established precedent that an absent
|
||||
"dma-ranges" implies the same as the empty property, so we automatically
|
||||
opt those in to DMA configuration regardless, to avoid regressing most
|
||||
existing platforms.
|
||||
|
||||
Fixes: 09515ef5ddad ("of/acpi: Configure dma operations at probe time for platform/amba/pci bus devices")
|
||||
Reported-by: Christoph Hellwig <hch@lst.de>
|
||||
Signed-off-by: Robin Murphy <robin.murphy@arm.com>
|
||||
Acked-by: Rob Herring <robh@kernel.org>
|
||||
Signed-off-by: Christoph Hellwig <hch@lst.de>
|
||||
---
|
||||
drivers/of/device.c | 48 ++++++++++++++++++++++++++++++++----------------
|
||||
1 file changed, 32 insertions(+), 16 deletions(-)
|
||||
|
||||
diff --git a/drivers/of/device.c b/drivers/of/device.c
|
||||
index e0a28ea..04c4c95 100644
|
||||
--- a/drivers/of/device.c
|
||||
+++ b/drivers/of/device.c
|
||||
@@ -9,6 +9,9 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/mod_devicetable.h>
|
||||
#include <linux/slab.h>
|
||||
+#include <linux/pci.h>
|
||||
+#include <linux/platform_device.h>
|
||||
+#include <linux/amba/bus.h>
|
||||
|
||||
#include <asm/errno.h>
|
||||
#include "of_private.h"
|
||||
@@ -84,31 +87,28 @@ int of_device_add(struct platform_device *ofdev)
|
||||
*/
|
||||
int of_dma_configure(struct device *dev, struct device_node *np)
|
||||
{
|
||||
- u64 dma_addr, paddr, size;
|
||||
+ u64 dma_addr, paddr, size = 0;
|
||||
int ret;
|
||||
bool coherent;
|
||||
unsigned long offset;
|
||||
const struct iommu_ops *iommu;
|
||||
u64 mask;
|
||||
|
||||
- /*
|
||||
- * Set default coherent_dma_mask to 32 bit. Drivers are expected to
|
||||
- * setup the correct supported mask.
|
||||
- */
|
||||
- if (!dev->coherent_dma_mask)
|
||||
- dev->coherent_dma_mask = DMA_BIT_MASK(32);
|
||||
-
|
||||
- /*
|
||||
- * Set it to coherent_dma_mask by default if the architecture
|
||||
- * code has not set it.
|
||||
- */
|
||||
- if (!dev->dma_mask)
|
||||
- dev->dma_mask = &dev->coherent_dma_mask;
|
||||
-
|
||||
ret = of_dma_get_range(np, &dma_addr, &paddr, &size);
|
||||
if (ret < 0) {
|
||||
+ /*
|
||||
+ * For legacy reasons, we have to assume some devices need
|
||||
+ * DMA configuration regardless of whether "dma-ranges" is
|
||||
+ * correctly specified or not.
|
||||
+ */
|
||||
+ if (!dev_is_pci(dev) &&
|
||||
+#ifdef CONFIG_ARM_AMBA
|
||||
+ dev->bus != &amba_bustype &&
|
||||
+#endif
|
||||
+ dev->bus != &platform_bus_type)
|
||||
+ return ret == -ENODEV ? 0 : ret;
|
||||
+
|
||||
dma_addr = offset = 0;
|
||||
- size = max(dev->coherent_dma_mask, dev->coherent_dma_mask + 1);
|
||||
} else {
|
||||
offset = PFN_DOWN(paddr - dma_addr);
|
||||
|
||||
@@ -129,6 +129,22 @@ int of_dma_configure(struct device *dev, struct device_node *np)
|
||||
dev_dbg(dev, "dma_pfn_offset(%#08lx)\n", offset);
|
||||
}
|
||||
|
||||
+ /*
|
||||
+ * Set default coherent_dma_mask to 32 bit. Drivers are expected to
|
||||
+ * setup the correct supported mask.
|
||||
+ */
|
||||
+ if (!dev->coherent_dma_mask)
|
||||
+ dev->coherent_dma_mask = DMA_BIT_MASK(32);
|
||||
+ /*
|
||||
+ * Set it to coherent_dma_mask by default if the architecture
|
||||
+ * code has not set it.
|
||||
+ */
|
||||
+ if (!dev->dma_mask)
|
||||
+ dev->dma_mask = &dev->coherent_dma_mask;
|
||||
+
|
||||
+ if (!size)
|
||||
+ size = max(dev->coherent_dma_mask, dev->coherent_dma_mask + 1);
|
||||
+
|
||||
dev->dma_pfn_offset = offset;
|
||||
|
||||
/*
|
||||
--
|
||||
cgit v1.1
|
||||
|
|
@ -1,39 +0,0 @@
|
|||
From patchwork Sun Jul 9 16:36:14 2017
|
||||
Content-Type: text/plain; charset="utf-8"
|
||||
MIME-Version: 1.0
|
||||
Content-Transfer-Encoding: 7bit
|
||||
Subject: ARM: tegra: Register host1x node with iommu binding on tegra124
|
||||
From: Paul Kocialkowski <contact@paulk.fr>
|
||||
X-Patchwork-Id: 9831825
|
||||
Message-Id: <20170709163614.6746-1-contact@paulk.fr>
|
||||
To: linux-arm-kernel@lists.infradead.org, linux-tegra@vger.kernel.org,
|
||||
linux-kernel@vger.kernel.org
|
||||
Cc: Thierry Reding <thierry.reding@gmail.com>,
|
||||
Stephen Warren <swarren@wwwdotorg.org>,
|
||||
Mikko Perttunen <mperttunen@nvidia.com>,
|
||||
Paul Kocialkowski <contact@paulk.fr>,
|
||||
Jonathan Hunter <jonathanh@nvidia.com>
|
||||
Date: Sun, 9 Jul 2017 19:36:14 +0300
|
||||
|
||||
This registers the host1x node with the SMMU (as HC swgroup) to allow
|
||||
the host1x code to attach to it. It avoid failing the probe sequence,
|
||||
which resulted in the tegra drm driver not probing and thus nothing
|
||||
being displayed on-screen.
|
||||
|
||||
Signed-off-by: Paul Kocialkowski <contact@paulk.fr>
|
||||
---
|
||||
arch/arm/boot/dts/tegra124.dtsi | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
diff --git a/arch/arm/boot/dts/tegra124.dtsi b/arch/arm/boot/dts/tegra124.dtsi
|
||||
index 187a36c6d0fc..b3b89befffeb 100644
|
||||
--- a/arch/arm/boot/dts/tegra124.dtsi
|
||||
+++ b/arch/arm/boot/dts/tegra124.dtsi
|
||||
@@ -85,6 +85,7 @@
|
||||
clocks = <&tegra_car TEGRA124_CLK_HOST1X>;
|
||||
resets = <&tegra_car 28>;
|
||||
reset-names = "host1x";
|
||||
+ iommus = <&mc TEGRA_SWGROUP_HC>;
|
||||
|
||||
#address-cells = <2>;
|
||||
#size-cells = <2>;
|
|
@ -1,224 +0,0 @@
|
|||
From 0fe4d2181cc4cb3eba303c0e03f878d2558d0f3a Mon Sep 17 00:00:00 2001
|
||||
From: Stefan Wahren <stefan.wahren@i2se.com>
|
||||
Date: Fri, 31 Mar 2017 20:03:04 +0000
|
||||
Subject: [PATCH] ARM: dts: bcm283x: Add CPU thermal zone with 1
|
||||
trip point
|
||||
|
||||
As suggested by Eduardo Valentin this adds the thermal zone for
|
||||
the bcm2835 SoC with its single thermal sensor. We start with
|
||||
the criticial trip point and leave the cooling devices empty
|
||||
since we don't have any at the moment. Since the coefficients
|
||||
could vary depending on the SoC we need to define them separate.
|
||||
|
||||
Signed-off-by: Stefan Wahren <stefan.wahren@i2se.com>
|
||||
Signed-off-by: Eric Anholt <eric@anholt.net>
|
||||
Acked-by: Eduardo Valentin <edubezval@gmail.com>
|
||||
---
|
||||
arch/arm/boot/dts/bcm2835.dtsi | 4 ++++
|
||||
arch/arm/boot/dts/bcm2836.dtsi | 4 ++++
|
||||
arch/arm/boot/dts/bcm283x.dtsi | 21 +++++++++++++++++++++
|
||||
3 files changed, 29 insertions(+)
|
||||
|
||||
diff --git a/arch/arm/boot/dts/bcm2835.dtsi b/arch/arm/boot/dts/bcm2835.dtsi
|
||||
index 0890d97e674d..659b6e9513b1 100644
|
||||
--- a/arch/arm/boot/dts/bcm2835.dtsi
|
||||
+++ b/arch/arm/boot/dts/bcm2835.dtsi
|
||||
@@ -24,6 +24,10 @@
|
||||
};
|
||||
};
|
||||
|
||||
+&cpu_thermal {
|
||||
+ coefficients = <(-538) 407000>;
|
||||
+};
|
||||
+
|
||||
/* enable thermal sensor with the correct compatible property set */
|
||||
&thermal {
|
||||
compatible = "brcm,bcm2835-thermal";
|
||||
diff --git a/arch/arm/boot/dts/bcm2836.dtsi b/arch/arm/boot/dts/bcm2836.dtsi
|
||||
index 519a44f5d25a..da3deeb42592 100644
|
||||
--- a/arch/arm/boot/dts/bcm2836.dtsi
|
||||
+++ b/arch/arm/boot/dts/bcm2836.dtsi
|
||||
@@ -77,6 +77,10 @@
|
||||
interrupts = <8>;
|
||||
};
|
||||
|
||||
+&cpu_thermal {
|
||||
+ coefficients = <(-538) 407000>;
|
||||
+};
|
||||
+
|
||||
/* enable thermal sensor with the correct compatible property set */
|
||||
&thermal {
|
||||
compatible = "brcm,bcm2836-thermal";
|
||||
diff --git a/arch/arm/boot/dts/bcm283x.dtsi b/arch/arm/boot/dts/bcm283x.dtsi
|
||||
index 561f27d8d922..86a5db53da8f 100644
|
||||
--- a/arch/arm/boot/dts/bcm283x.dtsi
|
||||
+++ b/arch/arm/boot/dts/bcm283x.dtsi
|
||||
@@ -19,6 +19,26 @@
|
||||
bootargs = "earlyprintk console=ttyAMA0";
|
||||
};
|
||||
|
||||
+ thermal-zones {
|
||||
+ cpu_thermal: cpu-thermal {
|
||||
+ polling-delay-passive = <0>;
|
||||
+ polling-delay = <1000>;
|
||||
+
|
||||
+ thermal-sensors = <&thermal>;
|
||||
+
|
||||
+ trips {
|
||||
+ cpu-crit {
|
||||
+ temperature = <80000>;
|
||||
+ hysteresis = <0>;
|
||||
+ type = "critical";
|
||||
+ };
|
||||
+ };
|
||||
+
|
||||
+ cooling-maps {
|
||||
+ };
|
||||
+ };
|
||||
+ };
|
||||
+
|
||||
soc {
|
||||
compatible = "simple-bus";
|
||||
#address-cells = <1>;
|
||||
@@ -430,6 +450,7 @@
|
||||
compatible = "brcm,bcm2835-thermal";
|
||||
reg = <0x7e212000 0x8>;
|
||||
clocks = <&clocks BCM2835_CLOCK_TSENS>;
|
||||
+ #thermal-sensor-cells = <0>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
--
|
||||
2.13.3
|
||||
|
||||
From 4ae6f954b96c1fea86c6f21ae8fc413f5fc3444e Mon Sep 17 00:00:00 2001
|
||||
From: Stefan Wahren <stefan.wahren@i2se.com>
|
||||
Date: Fri, 31 Mar 2017 20:03:05 +0000
|
||||
Subject: [PATCH] ARM64: dts: bcm2837: Define CPU thermal coefficients
|
||||
|
||||
This defines the bcm2837 SoC specific thermal coefficients in
|
||||
order to initialize the thermal driver correctly.
|
||||
|
||||
Signed-off-by: Stefan Wahren <stefan.wahren@i2se.com>
|
||||
Signed-off-by: Eric Anholt <eric@anholt.net>
|
||||
Acked-by: Eduardo Valentin <edubezval@gmail.com>
|
||||
---
|
||||
arch/arm64/boot/dts/broadcom/bcm2837.dtsi | 4 ++++
|
||||
1 file changed, 4 insertions(+)
|
||||
|
||||
diff --git a/arch/arm64/boot/dts/broadcom/bcm2837.dtsi b/arch/arm64/boot/dts/broadcom/bcm2837.dtsi
|
||||
index 19f2fe620a21..2d5de6f0f78d 100644
|
||||
--- a/arch/arm64/boot/dts/broadcom/bcm2837.dtsi
|
||||
+++ b/arch/arm64/boot/dts/broadcom/bcm2837.dtsi
|
||||
@@ -75,6 +75,10 @@
|
||||
interrupts = <8>;
|
||||
};
|
||||
|
||||
+&cpu_thermal {
|
||||
+ coefficients = <(-538) 412000>;
|
||||
+};
|
||||
+
|
||||
/* enable thermal sensor with the correct compatible property set */
|
||||
&thermal {
|
||||
compatible = "brcm,bcm2837-thermal";
|
||||
--
|
||||
2.13.3
|
||||
|
||||
From 1fe3854a83b580727c9464b37b62ba77ead1d6f6 Mon Sep 17 00:00:00 2001
|
||||
From: Dan Carpenter <dan.carpenter@oracle.com>
|
||||
Date: Wed, 14 Jun 2017 12:13:27 +0300
|
||||
Subject: [PATCH] thermal: bcm2835: fix an error code in probe()
|
||||
|
||||
This causes a static checker because we're passing a valid pointer to
|
||||
PTR_ERR(). "err" is already the correct error code, so we can just
|
||||
delete this line.
|
||||
|
||||
Fixes: bcb7dd9ef206 ("thermal: bcm2835: add thermal driver for bcm2835 SoC")
|
||||
Acked-by: Stefan Wahren <stefan.wahren@i2se.com>
|
||||
Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
|
||||
Signed-off-by: Eduardo Valentin <edubezval@gmail.com>
|
||||
---
|
||||
drivers/thermal/broadcom/bcm2835_thermal.c | 1 -
|
||||
1 file changed, 1 deletion(-)
|
||||
|
||||
diff --git a/drivers/thermal/broadcom/bcm2835_thermal.c b/drivers/thermal/broadcom/bcm2835_thermal.c
|
||||
index 0ecf80890c84..e6863c841662 100644
|
||||
--- a/drivers/thermal/broadcom/bcm2835_thermal.c
|
||||
+++ b/drivers/thermal/broadcom/bcm2835_thermal.c
|
||||
@@ -245,7 +245,6 @@ static int bcm2835_thermal_probe(struct platform_device *pdev)
|
||||
*/
|
||||
err = tz->ops->get_trip_temp(tz, 0, &trip_temp);
|
||||
if (err < 0) {
|
||||
- err = PTR_ERR(tz);
|
||||
dev_err(&pdev->dev,
|
||||
"Not able to read trip_temp: %d\n",
|
||||
err);
|
||||
--
|
||||
2.13.3
|
||||
|
||||
From e3bdc8d7623d5875403ad40443e7b049ae200fcd Mon Sep 17 00:00:00 2001
|
||||
From: Arvind Yadav <arvind.yadav.cs@gmail.com>
|
||||
Date: Tue, 6 Jun 2017 15:12:37 +0530
|
||||
Subject: [PATCH] thermal: imx: Handle return value of clk_prepare_enable
|
||||
|
||||
clk_prepare_enable() can fail here and we must check its return value.
|
||||
|
||||
Signed-off-by: Arvind Yadav <arvind.yadav.cs@gmail.com>
|
||||
Signed-off-by: Eduardo Valentin <edubezval@gmail.com>
|
||||
---
|
||||
drivers/thermal/imx_thermal.c | 5 ++++-
|
||||
1 file changed, 4 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/drivers/thermal/imx_thermal.c b/drivers/thermal/imx_thermal.c
|
||||
index f7ec39f46ee4..4798b4b1fd77 100644
|
||||
--- a/drivers/thermal/imx_thermal.c
|
||||
+++ b/drivers/thermal/imx_thermal.c
|
||||
@@ -660,8 +660,11 @@ static int imx_thermal_resume(struct device *dev)
|
||||
{
|
||||
struct imx_thermal_data *data = dev_get_drvdata(dev);
|
||||
struct regmap *map = data->tempmon;
|
||||
+ int ret;
|
||||
|
||||
- clk_prepare_enable(data->thermal_clk);
|
||||
+ ret = clk_prepare_enable(data->thermal_clk);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
/* Enabled thermal sensor after resume */
|
||||
regmap_write(map, TEMPSENSE0 + REG_CLR, TEMPSENSE0_POWER_DOWN);
|
||||
regmap_write(map, TEMPSENSE0 + REG_SET, TEMPSENSE0_MEASURE_TEMP);
|
||||
--
|
||||
2.13.3
|
||||
|
||||
From 919054fdfc8adf58c5512fe9872eb53ea0f5525d Mon Sep 17 00:00:00 2001
|
||||
From: Arvind Yadav <arvind.yadav.cs@gmail.com>
|
||||
Date: Tue, 6 Jun 2017 15:04:46 +0530
|
||||
Subject: [PATCH] thermal: hisilicon: Handle return value of clk_prepare_enable
|
||||
|
||||
clk_prepare_enable() can fail here and we must check its return value.
|
||||
|
||||
Signed-off-by: Arvind Yadav <arvind.yadav.cs@gmail.com>
|
||||
Signed-off-by: Eduardo Valentin <edubezval@gmail.com>
|
||||
---
|
||||
drivers/thermal/hisi_thermal.c | 5 ++++-
|
||||
1 file changed, 4 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/drivers/thermal/hisi_thermal.c b/drivers/thermal/hisi_thermal.c
|
||||
index f6429666a1cf..9c3ce341eb97 100644
|
||||
--- a/drivers/thermal/hisi_thermal.c
|
||||
+++ b/drivers/thermal/hisi_thermal.c
|
||||
@@ -397,8 +397,11 @@ static int hisi_thermal_suspend(struct device *dev)
|
||||
static int hisi_thermal_resume(struct device *dev)
|
||||
{
|
||||
struct hisi_thermal_data *data = dev_get_drvdata(dev);
|
||||
+ int ret;
|
||||
|
||||
- clk_prepare_enable(data->clk);
|
||||
+ ret = clk_prepare_enable(data->clk);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
|
||||
data->irq_enabled = true;
|
||||
hisi_thermal_enable_bind_irq_sensor(data);
|
||||
--
|
||||
2.13.3
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
From 90e388ca5d8bbee022f9ed5fc24137b31579fa6e Mon Sep 17 00:00:00 2001
|
||||
From: Peter Robinson <pbrobinson@gmail.com>
|
||||
Date: Wed, 22 Nov 2017 15:52:36 +0000
|
||||
Subject: [PATCH] Revert "arm64: allwinner: a64: pine64: Use dcdc1 regulator
|
||||
for mmc0"
|
||||
|
||||
This reverts commit 3f241bfa60bdc9c4fde63fa6664a8ce00fd668c6.
|
||||
---
|
||||
arch/arm64/boot/dts/allwinner/sun50i-a64-pine64.dts | 9 ++++++++-
|
||||
1 file changed, 8 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64.dts
|
||||
index d06e34b5d192..caf8b6fbe5e3 100644
|
||||
--- a/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64.dts
|
||||
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64.dts
|
||||
@@ -61,6 +61,13 @@
|
||||
chosen {
|
||||
stdout-path = "serial0:115200n8";
|
||||
};
|
||||
+
|
||||
+ reg_vcc3v3: vcc3v3 {
|
||||
+ compatible = "regulator-fixed";
|
||||
+ regulator-name = "vcc3v3";
|
||||
+ regulator-min-microvolt = <3300000>;
|
||||
+ regulator-max-microvolt = <3300000>;
|
||||
+ };
|
||||
};
|
||||
|
||||
&ehci0 {
|
||||
@@ -84,7 +91,7 @@
|
||||
&mmc0 {
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&mmc0_pins>;
|
||||
- vmmc-supply = <®_dcdc1>;
|
||||
+ vmmc-supply = <®_vcc3v3>;
|
||||
cd-gpios = <&pio 5 6 GPIO_ACTIVE_HIGH>;
|
||||
cd-inverted;
|
||||
disable-wp;
|
||||
--
|
||||
2.14.3
|
||||
|
|
@ -1,455 +0,0 @@
|
|||
From c03847b4a603846903ee72a5e1baab03e0591423 Mon Sep 17 00:00:00 2001
|
||||
From: Ashok Kumar Sekar <asekar@redhat.com>
|
||||
Date: Fri, 23 Sep 2016 04:16:19 -0700
|
||||
Subject: [PATCH 1/8] PCI: Vulcan: AHCI PCI bar fix for Broadcom Vulcan early
|
||||
silicon
|
||||
|
||||
PCI BAR 5 is not setup correctly for the on-board AHCI
|
||||
controller on Broadcom's Vulcan processor. Added a quirk to fix BAR 5
|
||||
by using BAR 4's resources which are populated correctly but NOT used
|
||||
by the AHCI controller actually.
|
||||
|
||||
Signed-off-by: Ashok Kumar Sekar <asekar@redhat.com>
|
||||
Signed-off-by: Jayachandran C <jchandra@broadcom.com>
|
||||
Signed-off-by: Robert Richter <rrichter@cavium.com>
|
||||
---
|
||||
drivers/pci/quirks.c | 24 ++++++++++++++++++++++++
|
||||
1 file changed, 24 insertions(+)
|
||||
|
||||
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
|
||||
index dc624fb34e72..94b7bdf63b19 100644
|
||||
--- a/drivers/pci/quirks.c
|
||||
+++ b/drivers/pci/quirks.c
|
||||
@@ -3994,6 +3994,30 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_BROADCOM, 0x9084,
|
||||
quirk_bridge_cavm_thrx2_pcie_root);
|
||||
|
||||
/*
|
||||
+ * PCI BAR 5 is not setup correctly for the on-board AHCI controller
|
||||
+ * on Broadcom's Vulcan processor. Added a quirk to fix BAR 5 by
|
||||
+ * using BAR 4's resources which are populated correctly and NOT
|
||||
+ * actually used by the AHCI controller.
|
||||
+ */
|
||||
+static void quirk_fix_vulcan_ahci_bars(struct pci_dev *dev)
|
||||
+{
|
||||
+ struct resource *r = &dev->resource[4];
|
||||
+
|
||||
+ if (!(r->flags & IORESOURCE_MEM) || (r->start == 0))
|
||||
+ return;
|
||||
+
|
||||
+ /* Set BAR5 resource to BAR4 */
|
||||
+ dev->resource[5] = *r;
|
||||
+
|
||||
+ /* Update BAR5 in pci config space */
|
||||
+ pci_write_config_dword(dev, PCI_BASE_ADDRESS_5, r->start);
|
||||
+
|
||||
+ /* Clear BAR4's resource */
|
||||
+ memset(r, 0, sizeof(*r));
|
||||
+}
|
||||
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_BROADCOM, 0x9027, quirk_fix_vulcan_ahci_bars);
|
||||
+
|
||||
+/*
|
||||
* Intersil/Techwell TW686[4589]-based video capture cards have an empty (zero)
|
||||
* class code. Fix it.
|
||||
*/
|
||||
--
|
||||
2.11.0
|
||||
|
||||
From c84892e4b6b671fda7e499a0bb0787bd026de015 Mon Sep 17 00:00:00 2001
|
||||
From: Jayachandran C <jnair@caviumnetworks.com>
|
||||
Date: Fri, 10 Mar 2017 10:04:52 +0000
|
||||
Subject: [PATCH 2/8] ahci: thunderx2: Fix for errata that affects stop engine
|
||||
|
||||
Apply workaround for this errata:
|
||||
Synopsis: Resetting PxCMD.ST may hang the SATA device
|
||||
|
||||
Description: An internal ping-pong buffer state is not reset
|
||||
correctly for an PxCMD.ST=0 command for a SATA channel. This
|
||||
may cause the SATA interface to hang when a PxCMD.ST=0 command
|
||||
is received.
|
||||
|
||||
Workaround: A SATA_BIU_CORE_ENABLE.sw_init_bsi must be asserted
|
||||
by the driver whenever the PxCMD.ST needs to be de-asserted. This
|
||||
will reset both the ports. So, it may not always work in a 2
|
||||
channel SATA system.
|
||||
|
||||
Resolution: Fix in B0.
|
||||
|
||||
Add the code to ahci_stop_engine() to do this. It is not easy to
|
||||
stop the other "port" since it is associated with a different AHCI
|
||||
interface. Please note that with this fix, SATA reset does not
|
||||
hang any more, but it can cause failures on the other interface
|
||||
if that is in active use.
|
||||
|
||||
Unfortunately, we have nothing other the the CPU ID to check if the
|
||||
SATA block has this issue.
|
||||
|
||||
Signed-off-by: Jayachandran C <jnair@caviumnetworks.com>
|
||||
[added check to restict to pci devs on the soc only]
|
||||
Signed-off-by: Robert Richter <rrichter@cavium.com>
|
||||
---
|
||||
drivers/ata/libahci.c | 17 +++++++++++++++++
|
||||
1 file changed, 17 insertions(+)
|
||||
|
||||
diff --git a/drivers/ata/libahci.c b/drivers/ata/libahci.c
|
||||
index 3e286d86ab42..9116bba1b07d 100644
|
||||
--- a/drivers/ata/libahci.c
|
||||
+++ b/drivers/ata/libahci.c
|
||||
@@ -669,6 +669,23 @@ int ahci_stop_engine(struct ata_port *ap)
|
||||
tmp &= ~PORT_CMD_START;
|
||||
writel(tmp, port_mmio + PORT_CMD);
|
||||
|
||||
+#ifdef CONFIG_ARM64
|
||||
+ /* Rev Ax of Cavium CN99XX needs a hack for port stop */
|
||||
+ if (dev_is_pci(ap->host->dev) &&
|
||||
+ to_pci_dev(ap->host->dev)->vendor == 0x14e4 &&
|
||||
+ to_pci_dev(ap->host->dev)->device == 0x9027 &&
|
||||
+ MIDR_IS_CPU_MODEL_RANGE(read_cpuid_id(),
|
||||
+ MIDR_CPU_MODEL(ARM_CPU_IMP_BRCM, BRCM_CPU_PART_VULCAN),
|
||||
+ MIDR_CPU_VAR_REV(0, 0),
|
||||
+ MIDR_CPU_VAR_REV(0, MIDR_REVISION_MASK))) {
|
||||
+ tmp = readl(hpriv->mmio + 0x8000);
|
||||
+ writel(tmp | (1 << 26), hpriv->mmio + 0x8000);
|
||||
+ udelay(1);
|
||||
+ writel(tmp & ~(1 << 26), hpriv->mmio + 0x8000);
|
||||
+ dev_warn(ap->host->dev, "CN99XX stop engine fix applied!\n");
|
||||
+ }
|
||||
+#endif
|
||||
+
|
||||
/* wait for engine to stop. This could be as long as 500 msec */
|
||||
tmp = ata_wait_register(ap, port_mmio + PORT_CMD,
|
||||
PORT_CMD_LIST_ON, PORT_CMD_LIST_ON, 1, 500);
|
||||
--
|
||||
2.11.0
|
||||
|
||||
From 98a39621952f6a13c5198e79f1c080ea6fc1d092 Mon Sep 17 00:00:00 2001
|
||||
From: Jayachandran C <jnair@caviumnetworks.com>
|
||||
Date: Sun, 22 Feb 1998 18:42:42 -0800
|
||||
Subject: [PATCH 3/8] ahci: thunderx2: stop engine fix update
|
||||
|
||||
The current reset fix fails during continuous reboot test. The failure
|
||||
happens when both the on-board SATA slots are used and when one of the
|
||||
controllers are reset.
|
||||
|
||||
The latest ThunderX2 firmware (3.1) enables hardware error interrupts and
|
||||
when the reset fix fails, we get a hang with the print:
|
||||
[ 14.839308] sd 1:0:0:0: [sdb] 468862128 512-byte logical blocks: (240 GB/224 GiB)
|
||||
[ 14.846796] sd 1:0:0:0: [sdb] 4096-byte physical blocks
|
||||
[ 14.852036] sd 1:0:0:0: [sdb] Write Protect is off
|
||||
[ 14.856843] sd 1:0:0:0: [sdb] Write cache: enabled, read cache: enabled, doesn't support DPO or FUA
|
||||
[ 14.866022] ata2.00: Enabling discard_zeroes_data
|
||||
|
||||
*** NBU BAR Error 0x1e25c ***
|
||||
AddrLo 0x1d80180 AddrHi 0x0
|
||||
|
||||
To fix this issue, update the SATA reset fix to increase the delays between register writes.
|
||||
|
||||
Signed-off-by: Jayachandran C <jnair@caviumnetworks.com>
|
||||
Signed-off-by: Robert Richter <rrichter@cavium.com>
|
||||
---
|
||||
drivers/ata/libahci.c | 5 +++--
|
||||
1 file changed, 3 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/drivers/ata/libahci.c b/drivers/ata/libahci.c
|
||||
index 9116bba1b07d..1d3e614bad2b 100644
|
||||
--- a/drivers/ata/libahci.c
|
||||
+++ b/drivers/ata/libahci.c
|
||||
@@ -679,10 +679,11 @@ int ahci_stop_engine(struct ata_port *ap)
|
||||
MIDR_CPU_VAR_REV(0, 0),
|
||||
MIDR_CPU_VAR_REV(0, MIDR_REVISION_MASK))) {
|
||||
tmp = readl(hpriv->mmio + 0x8000);
|
||||
+ udelay(100);
|
||||
writel(tmp | (1 << 26), hpriv->mmio + 0x8000);
|
||||
- udelay(1);
|
||||
+ udelay(100);
|
||||
writel(tmp & ~(1 << 26), hpriv->mmio + 0x8000);
|
||||
- dev_warn(ap->host->dev, "CN99XX stop engine fix applied!\n");
|
||||
+ dev_warn(ap->host->dev, "CN99XX SATA reset workaround applied\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
--
|
||||
2.11.0
|
||||
|
||||
From 33c107d2a2b570cd5246262108ad07cc102e9fcd Mon Sep 17 00:00:00 2001
|
||||
From: Robert Richter <rrichter@cavium.com>
|
||||
Date: Thu, 16 Mar 2017 18:01:59 +0100
|
||||
Subject: [PATCH 4/8] iommu/arm-smmu, ACPI: Enable Cavium SMMU-v2
|
||||
|
||||
In next IORT spec release there will be a definition of a Cavium
|
||||
specific model. Until then, enable the Cavium SMMU using cpu id
|
||||
registers. All versions of Cavium's SMMUv2 implementation must be
|
||||
enabled.
|
||||
|
||||
Signed-off-by: Robert Richter <rrichter@cavium.com>
|
||||
---
|
||||
drivers/iommu/arm-smmu.c | 22 +++++++++++++++++++++-
|
||||
1 file changed, 21 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
|
||||
index d42cad5a3d52..37aee96ccc0e 100644
|
||||
--- a/drivers/iommu/arm-smmu.c
|
||||
+++ b/drivers/iommu/arm-smmu.c
|
||||
@@ -53,6 +53,8 @@
|
||||
|
||||
#include <linux/amba/bus.h>
|
||||
|
||||
+#include <asm/cputype.h>
|
||||
+
|
||||
#include "io-pgtable.h"
|
||||
#include "arm-smmu-regs.h"
|
||||
|
||||
@@ -1871,6 +1873,24 @@ static const struct of_device_id arm_smmu_of_match[] = {
|
||||
MODULE_DEVICE_TABLE(of, arm_smmu_of_match);
|
||||
|
||||
#ifdef CONFIG_ACPI
|
||||
+
|
||||
+static int acpi_smmu_enable_cavium(struct arm_smmu_device *smmu, int ret)
|
||||
+{
|
||||
+ u32 cpu_model;
|
||||
+
|
||||
+ if (!IS_ENABLED(CONFIG_ARM64))
|
||||
+ return ret;
|
||||
+
|
||||
+ cpu_model = read_cpuid_id() & MIDR_CPU_MODEL_MASK;
|
||||
+ if (cpu_model != MIDR_THUNDERX)
|
||||
+ return ret;
|
||||
+
|
||||
+ smmu->version = ARM_SMMU_V2;
|
||||
+ smmu->model = CAVIUM_SMMUV2;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
static int acpi_smmu_get_data(u32 model, struct arm_smmu_device *smmu)
|
||||
{
|
||||
int ret = 0;
|
||||
@@ -1901,7 +1921,7 @@ static int acpi_smmu_get_data(u32 model, struct arm_smmu_device *smmu)
|
||||
ret = -ENODEV;
|
||||
}
|
||||
|
||||
- return ret;
|
||||
+ return acpi_smmu_enable_cavium(smmu, ret);
|
||||
}
|
||||
|
||||
static int arm_smmu_device_acpi_probe(struct platform_device *pdev,
|
||||
--
|
||||
2.11.0
|
||||
|
||||
From 5523edb06c95d7ac9e81d94366e71d929c08ebd4 Mon Sep 17 00:00:00 2001
|
||||
From: Robert Richter <rrichter@cavium.com>
|
||||
Date: Wed, 12 Apr 2017 15:06:03 +0200
|
||||
Subject: [PATCH 5/8] iommu: Print a message with the default domain type
|
||||
created
|
||||
|
||||
There are several ways the bypass mode can be enabled. With commit
|
||||
|
||||
fccb4e3b8ab0 iommu: Allow default domain type to be set on the kernel command line
|
||||
|
||||
there is the option to switch into bypass mode. And, depending on
|
||||
devicetree options, bypass mode can be also enabled. This makes it
|
||||
hard to determine if direct mapping is enabled. Print message with the
|
||||
default domain type case.
|
||||
|
||||
Signed-off-by: Robert Richter <rrichter@cavium.com>
|
||||
---
|
||||
drivers/iommu/iommu.c | 4 +++-
|
||||
1 file changed, 3 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
|
||||
index 3f6ea160afed..7aaafaca6baf 100644
|
||||
--- a/drivers/iommu/iommu.c
|
||||
+++ b/drivers/iommu/iommu.c
|
||||
@@ -599,7 +599,9 @@ int iommu_group_add_device(struct iommu_group *group, struct device *dev)
|
||||
|
||||
trace_add_device_to_group(group->id, dev);
|
||||
|
||||
- pr_info("Adding device %s to group %d\n", dev_name(dev), group->id);
|
||||
+ pr_info("Adding device %s to group %d, default domain type %d\n",
|
||||
+ dev_name(dev), group->id,
|
||||
+ group->default_domain ? group->default_domain->type : -1);
|
||||
|
||||
return 0;
|
||||
|
||||
--
|
||||
2.11.0
|
||||
|
||||
From 71e0ad5ab606077c24a96d69f4bfed58d7ef16c7 Mon Sep 17 00:00:00 2001
|
||||
From: Robert Richter <rrichter@cavium.com>
|
||||
Date: Thu, 4 May 2017 17:48:48 +0200
|
||||
Subject: [PATCH 6/8] iommu, aarch64: Set bypass mode per default
|
||||
|
||||
We see a performance degradation if smmu is enabled in non-bypass mode.
|
||||
This is a problem in the kernel's implememntation. Until that is solved,
|
||||
enable smmu in bypass mode per default.
|
||||
|
||||
We have tested that SMMU passthrough mode doesn't effect VFIO on both
|
||||
CN88xx and CN99xx and haven't found any issues.
|
||||
|
||||
Signed-off-by: Robert Richter <rrichter@cavium.com>
|
||||
---
|
||||
drivers/iommu/iommu.c | 5 +++++
|
||||
1 file changed, 5 insertions(+)
|
||||
|
||||
diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
|
||||
index 7aaafaca6baf..24de0b934221 100644
|
||||
--- a/drivers/iommu/iommu.c
|
||||
+++ b/drivers/iommu/iommu.c
|
||||
@@ -36,7 +36,12 @@
|
||||
|
||||
static struct kset *iommu_group_kset;
|
||||
static DEFINE_IDA(iommu_group_ida);
|
||||
+
|
||||
+#ifdef CONFIG_ARM64
|
||||
+static unsigned int iommu_def_domain_type = IOMMU_DOMAIN_IDENTITY;
|
||||
+#else
|
||||
static unsigned int iommu_def_domain_type = IOMMU_DOMAIN_DMA;
|
||||
+#endif
|
||||
|
||||
struct iommu_callback_data {
|
||||
const struct iommu_ops *ops;
|
||||
--
|
||||
2.11.0
|
||||
|
||||
From 27f103963f926d6a7a8adaad1ee227fd3b51f591 Mon Sep 17 00:00:00 2001
|
||||
From: Robert Richter <rrichter@cavium.com>
|
||||
Date: Wed, 12 Apr 2017 10:31:15 +0200
|
||||
Subject: [PATCH 7/8] iommu/arm-smmu, ACPI: Enable Cavium SMMU-v3
|
||||
|
||||
In next IORT spec release there will be a definition of a Cavium
|
||||
specific model. Until then, enable the Cavium SMMU using cpu id
|
||||
registers. Early silicon versions (A1) of Cavium's CN99xx SMMUv3
|
||||
implementation must be enabled. For later silicon versions (B0) the
|
||||
iort change will be in place.
|
||||
|
||||
Signed-off-by: Robert Richter <rrichter@cavium.com>
|
||||
---
|
||||
drivers/acpi/arm64/iort.c | 16 ++++++++++++++--
|
||||
drivers/iommu/arm-smmu-v3.c | 19 +++++++++++++++++++
|
||||
2 files changed, 33 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c
|
||||
index a3215ee671c1..b603af92eec2 100644
|
||||
--- a/drivers/acpi/arm64/iort.c
|
||||
+++ b/drivers/acpi/arm64/iort.c
|
||||
@@ -26,6 +26,8 @@
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
+#include <asm/cputype.h>
|
||||
+
|
||||
#define IORT_TYPE_MASK(type) (1 << (type))
|
||||
#define IORT_MSI_TYPE (1 << ACPI_IORT_NODE_ITS_GROUP)
|
||||
#define IORT_IOMMU_TYPE ((1 << ACPI_IORT_NODE_SMMU) | \
|
||||
@@ -824,13 +826,22 @@ static int __init arm_smmu_v3_count_resources(struct acpi_iort_node *node)
|
||||
return num_res;
|
||||
}
|
||||
|
||||
+static bool is_cavium_cn99xx_smmu_v3(void)
|
||||
+{
|
||||
+ u32 cpu_model = read_cpuid_id() & MIDR_CPU_MODEL_MASK;
|
||||
+
|
||||
+ return cpu_model == MIDR_CPU_MODEL(ARM_CPU_IMP_BRCM,
|
||||
+ BRCM_CPU_PART_VULCAN);
|
||||
+}
|
||||
+
|
||||
static bool arm_smmu_v3_is_combined_irq(struct acpi_iort_smmu_v3 *smmu)
|
||||
{
|
||||
/*
|
||||
* Cavium ThunderX2 implementation doesn't not support unique
|
||||
* irq line. Use single irq line for all the SMMUv3 interrupts.
|
||||
*/
|
||||
- if (smmu->model != ACPI_IORT_SMMU_V3_CAVIUM_CN99XX)
|
||||
+ if (smmu->model != ACPI_IORT_SMMU_V3_CAVIUM_CN99XX
|
||||
+ && !is_cavium_cn99xx_smmu_v3())
|
||||
return false;
|
||||
|
||||
/*
|
||||
@@ -848,7 +859,8 @@ static unsigned long arm_smmu_v3_resource_size(struct acpi_iort_smmu_v3 *smmu)
|
||||
* Override the size, for Cavium ThunderX2 implementation
|
||||
* which doesn't support the page 1 SMMU register space.
|
||||
*/
|
||||
- if (smmu->model == ACPI_IORT_SMMU_V3_CAVIUM_CN99XX)
|
||||
+ if (smmu->model == ACPI_IORT_SMMU_V3_CAVIUM_CN99XX
|
||||
+ || is_cavium_cn99xx_smmu_v3())
|
||||
return SZ_64K;
|
||||
|
||||
return SZ_128K;
|
||||
diff --git a/drivers/iommu/arm-smmu-v3.c b/drivers/iommu/arm-smmu-v3.c
|
||||
index 568c400eeaed..d147cb5c7309 100644
|
||||
--- a/drivers/iommu/arm-smmu-v3.c
|
||||
+++ b/drivers/iommu/arm-smmu-v3.c
|
||||
@@ -39,6 +39,8 @@
|
||||
|
||||
#include <linux/amba/bus.h>
|
||||
|
||||
+#include <asm/cputype.h>
|
||||
+
|
||||
#include "io-pgtable.h"
|
||||
|
||||
/* MMIO registers */
|
||||
@@ -2659,6 +2661,21 @@ static int arm_smmu_device_hw_probe(struct arm_smmu_device *smmu)
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ACPI
|
||||
+
|
||||
+static void acpi_smmu_enable_cavium(struct arm_smmu_device *smmu)
|
||||
+{
|
||||
+ u32 cpu_model;
|
||||
+
|
||||
+ if (!IS_ENABLED(CONFIG_ARM64))
|
||||
+ return;
|
||||
+
|
||||
+ cpu_model = read_cpuid_id() & MIDR_CPU_MODEL_MASK;
|
||||
+ if (cpu_model != MIDR_CPU_MODEL(ARM_CPU_IMP_BRCM, BRCM_CPU_PART_VULCAN))
|
||||
+ return;
|
||||
+
|
||||
+ smmu->options |= ARM_SMMU_OPT_PAGE0_REGS_ONLY;
|
||||
+}
|
||||
+
|
||||
static void acpi_smmu_get_options(u32 model, struct arm_smmu_device *smmu)
|
||||
{
|
||||
switch (model) {
|
||||
@@ -2670,6 +2687,8 @@ static void acpi_smmu_get_options(u32 model, struct arm_smmu_device *smmu)
|
||||
break;
|
||||
}
|
||||
|
||||
+ acpi_smmu_enable_cavium(smmu);
|
||||
+
|
||||
dev_notice(smmu->dev, "option mask 0x%x\n", smmu->options);
|
||||
}
|
||||
|
||||
--
|
||||
2.11.0
|
||||
|
||||
From ff677cc625b52b93351dd73d7881251067f0e976 Mon Sep 17 00:00:00 2001
|
||||
From: Radha Mohan Chintakuntla <rchintakuntla@cavium.com>
|
||||
Date: Wed, 20 Aug 2014 15:10:58 -0700
|
||||
Subject: [PATCH 8/8] arm64: gicv3: its: Increase FORCE_MAX_ZONEORDER for
|
||||
Cavium ThunderX
|
||||
|
||||
In case of ARCH_THUNDER, there is a need to allocate the GICv3 ITS table
|
||||
which is bigger than the allowed max order. So we are forcing it only in
|
||||
case of 4KB page size.
|
||||
|
||||
Signed-off-by: Radha Mohan Chintakuntla <rchintakuntla@cavium.com>
|
||||
[rric: use ARM64_4K_PAGES since we have now ARM64_16K_PAGES, change order]
|
||||
Signed-off-by: Robert Richter <rrichter@cavium.com>
|
||||
---
|
||||
arch/arm64/Kconfig | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
|
||||
index 2c3e2d693d76..023867378f45 100644
|
||||
--- a/arch/arm64/Kconfig
|
||||
+++ b/arch/arm64/Kconfig
|
||||
@@ -784,6 +784,7 @@ config FORCE_MAX_ZONEORDER
|
||||
default "14" if (ARM64_64K_PAGES && TRANSPARENT_HUGEPAGE)
|
||||
default "13" if (ARCH_THUNDER && !ARM64_64K_PAGES)
|
||||
default "12" if (ARM64_16K_PAGES && TRANSPARENT_HUGEPAGE)
|
||||
+ default "13" if (ARM64_4K_PAGES && ARCH_THUNDER)
|
||||
default "11"
|
||||
help
|
||||
The kernel memory allocator divides physically contiguous memory
|
||||
--
|
||||
2.11.0
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,39 @@
|
|||
From fa6d7cb5d76cf0467c61420fc9238045aedfd379 Mon Sep 17 00:00:00 2001
|
||||
From: Sunil Goutham <sgoutham@cavium.com>
|
||||
Date: Thu, 23 Nov 2017 22:34:31 +0300
|
||||
Subject: net: thunderx: Fix TCP/UDP checksum offload for IPv6 pkts
|
||||
|
||||
Don't offload IP header checksum to NIC.
|
||||
|
||||
This fixes a previous patch which enabled checksum offloading
|
||||
for both IPv4 and IPv6 packets. So L3 checksum offload was
|
||||
getting enabled for IPv6 pkts. And HW is dropping these pkts
|
||||
as it assumes the pkt is IPv4 when IP csum offload is set
|
||||
in the SQ descriptor.
|
||||
|
||||
Fixes: 3a9024f52c2e ("net: thunderx: Enable TSO and checksum offloads for ipv6")
|
||||
Signed-off-by: Sunil Goutham <sgoutham@cavium.com>
|
||||
Signed-off-by: Aleksey Makarov <aleksey.makarov@auriga.com>
|
||||
Reviewed-by: Eric Dumazet <edumazet@google.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/ethernet/cavium/thunder/nicvf_queues.c | 1 -
|
||||
1 file changed, 1 deletion(-)
|
||||
|
||||
(limited to 'drivers/net/ethernet/cavium/thunder/nicvf_queues.c')
|
||||
|
||||
diff --git a/drivers/net/ethernet/cavium/thunder/nicvf_queues.c b/drivers/net/ethernet/cavium/thunder/nicvf_queues.c
|
||||
index d4496e9..8b2c31e 100644
|
||||
--- a/drivers/net/ethernet/cavium/thunder/nicvf_queues.c
|
||||
+++ b/drivers/net/ethernet/cavium/thunder/nicvf_queues.c
|
||||
@@ -1355,7 +1355,6 @@ nicvf_sq_add_hdr_subdesc(struct nicvf *nic, struct snd_queue *sq, int qentry,
|
||||
|
||||
/* Offload checksum calculation to HW */
|
||||
if (skb->ip_summed == CHECKSUM_PARTIAL) {
|
||||
- hdr->csum_l3 = 1; /* Enable IP csum calculation */
|
||||
hdr->l3_offset = skb_network_offset(skb);
|
||||
hdr->l4_offset = skb_transport_offset(skb);
|
||||
|
||||
--
|
||||
cgit v1.1
|
||||
|
|
@ -1,38 +0,0 @@
|
|||
From bdb9458a3382ba745a66be5526d3899103c76eda Mon Sep 17 00:00:00 2001
|
||||
From: Loc Ho <lho@apm.com>
|
||||
Date: Fri, 21 Jul 2017 11:24:37 -0700
|
||||
Subject: ACPI: APEI: Enable APEI multiple GHES source to share a single
|
||||
external IRQ
|
||||
|
||||
X-Gene platforms describe multiple GHES error sources with the same
|
||||
hardware error notification type (external interrupt) and interrupt
|
||||
number.
|
||||
|
||||
Change the GHES interrupt request to support sharing the same IRQ.
|
||||
|
||||
This change includs contributions from Tuan Phan <tphan@apm.com>.
|
||||
|
||||
Signed-off-by: Loc Ho <lho@apm.com>
|
||||
Acked-by: Borislav Petkov <bp@suse.de>
|
||||
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
|
||||
---
|
||||
drivers/acpi/apei/ghes.c | 3 ++-
|
||||
1 file changed, 2 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/drivers/acpi/apei/ghes.c b/drivers/acpi/apei/ghes.c
|
||||
index d661d45..eed09fc 100644
|
||||
--- a/drivers/acpi/apei/ghes.c
|
||||
+++ b/drivers/acpi/apei/ghes.c
|
||||
@@ -1157,7 +1157,8 @@ static int ghes_probe(struct platform_device *ghes_dev)
|
||||
generic->header.source_id);
|
||||
goto err_edac_unreg;
|
||||
}
|
||||
- rc = request_irq(ghes->irq, ghes_irq_func, 0, "GHES IRQ", ghes);
|
||||
+ rc = request_irq(ghes->irq, ghes_irq_func, IRQF_SHARED,
|
||||
+ "GHES IRQ", ghes);
|
||||
if (rc) {
|
||||
pr_err(GHES_PFX "Failed to register IRQ for generic hardware error source: %d\n",
|
||||
generic->header.source_id);
|
||||
--
|
||||
cgit v1.1
|
||||
|
|
@ -0,0 +1 @@
|
|||
CONFIG_ALLOW_LOCKDOWN_LIFT_BY_SYSRQ=y
|
|
@ -0,0 +1 @@
|
|||
CONFIG_ALTERA_MSGDMA=m
|
|
@ -0,0 +1 @@
|
|||
CONFIG_ATH10K_USB=m
|
|
@ -0,0 +1 @@
|
|||
# CONFIG_BATTERY_MAX1721X is not set
|
|
@ -1 +0,0 @@
|
|||
CONFIG_BLK_CPQ_CISS_DA=m
|
|
@ -1 +0,0 @@
|
|||
# CONFIG_BLK_DEV_UB is not set
|
|
@ -0,0 +1 @@
|
|||
CONFIG_BNXT_FLOWER_OFFLOAD=y
|
|
@ -0,0 +1 @@
|
|||
CONFIG_BPF_STREAM_PARSER=y
|
|
@ -1 +0,0 @@
|
|||
CONFIG_BT_SCO=y
|
|
@ -0,0 +1 @@
|
|||
# CONFIG_CCS811 is not set
|
|
@ -0,0 +1 @@
|
|||
CONFIG_CEC_PIN=y
|
|
@ -1 +0,0 @@
|
|||
# CONFIG_CHARGER_QCOM_SMBB is not set
|
|
@ -1 +0,0 @@
|
|||
CONFIG_CISS_SCSI_TAPE=y
|
|
@ -0,0 +1 @@
|
|||
# CONFIG_CLK_HSDK is not set
|
|
@ -0,0 +1 @@
|
|||
# CONFIG_CLOCK_THERMAL is not set
|
|
@ -0,0 +1 @@
|
|||
# CONFIG_CRYPTO_DEV_SP_CCP is not set
|
|
@ -0,0 +1 @@
|
|||
# CONFIG_DEVFREQ_THERMAL is not set
|
|
@ -0,0 +1 @@
|
|||
# CONFIG_DVB_DDBRIDGE_MSIENABLE is not set
|
|
@ -1 +1 @@
|
|||
# CONFIG_EARLY_PRINTK_USB_XDBC is not set
|
||||
CONFIG_EARLY_PRINTK_USB_XDBC=y
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
CONFIG_EXPERIMENTAL=y
|
|
@ -0,0 +1 @@
|
|||
CONFIG_GPIO_BD9571MWV=m
|
|
@ -1 +1 @@
|
|||
CONFIG_GPIO_IT87=m
|
||||
# CONFIG_GPIO_IT87 is not set
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
CONFIG_GPIO_TPS68470=y
|
|
@ -1 +1 @@
|
|||
# CONFIG_HID_CP2112 is not set
|
||||
CONFIG_HID_CP2112=m
|
||||
|
|
|
@ -1 +1 @@
|
|||
CONFIG_I2C_PARPORT_LIGHT=m
|
||||
# CONFIG_I2C_PARPORT_LIGHT is not set
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
# CONFIG_INFINIBAND_EXP_USER_ACCESS is not set
|
|
@ -1 +0,0 @@
|
|||
CONFIG_INOTIFY=y
|
|
@ -0,0 +1 @@
|
|||
# CONFIG_INPUT_PWM_VIBRA is not set
|
|
@ -0,0 +1 @@
|
|||
CONFIG_INPUT_RK805_PWRKEY=m
|
|
@ -1 +1 @@
|
|||
CONFIG_IP_DCCP=m
|
||||
# CONFIG_IP_DCCP is not set
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
CONFIG_IR_GPIO_TX=m
|
|
@ -0,0 +1 @@
|
|||
CONFIG_IR_PWM_TX=m
|
|
@ -0,0 +1 @@
|
|||
CONFIG_LEDS_AS3645A=m
|
|
@ -0,0 +1 @@
|
|||
# CONFIG_LOCK_DOWN_IN_EFI_SECURE_BOOT is not set
|
|
@ -0,0 +1 @@
|
|||
# CONFIG_LTC2471 is not set
|
|
@ -0,0 +1 @@
|
|||
CONFIG_MDIO_I2C=m
|
|
@ -0,0 +1 @@
|
|||
CONFIG_MFD_BD9571MWV=m
|
|
@ -0,0 +1 @@
|
|||
CONFIG_MFD_TPS68470=y
|
|
@ -0,0 +1 @@
|
|||
CONFIG_MLX5_ESWITCH=y
|
|
@ -0,0 +1 @@
|
|||
CONFIG_MLX5_MPFS=y
|
|
@ -1 +0,0 @@
|
|||
CONFIG_MMC_BLOCK_BOUNCE=y
|
|
@ -0,0 +1 @@
|
|||
CONFIG_NET_NSH=m
|
|
@ -0,0 +1 @@
|
|||
# CONFIG_NET_VENDOR_HUAWEI is not set
|
|
@ -0,0 +1 @@
|
|||
# CONFIG_NET_VENDOR_SNI is not set
|
|
@ -0,0 +1 @@
|
|||
CONFIG_NFT_FIB_NETDEV=m
|
|
@ -1 +1 @@
|
|||
CONFIG_PARPORT=m
|
||||
# CONFIG_PARPORT is not set
|
||||
|
|
|
@ -1 +1 @@
|
|||
CONFIG_PARPORT_PC=m
|
||||
# CONFIG_PARPORT_PC is not set
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue