diff --git a/0001-Input-gpio_keys-Allow-suppression-of-input-events-fo.patch b/0001-Input-gpio_keys-Allow-suppression-of-input-events-fo.patch new file mode 100644 index 000000000..1f03d710b --- /dev/null +++ b/0001-Input-gpio_keys-Allow-suppression-of-input-events-fo.patch @@ -0,0 +1,163 @@ +From 25bb14c1e78e641049fd1ee0c404a9ccd2755e44 Mon Sep 17 00:00:00 2001 +From: Hans de Goede +Date: Sat, 22 Jul 2017 13:00:05 +0200 +Subject: [PATCH 1/2] Input: gpio_keys - Allow suppression of input events for + wakeup button presses + +In some cases it is undesirable for a wakeup button to send input events +to userspace if pressed to wakeup the system (if pressed during suspend). + +A typical example of this is the power-button on laptops / tablets, +sending a KEY_POWER event to userspace when woken up with the power-button +will cause userspace to immediately suspend the system again which is +undesirable. + +For power-buttons attached to a PMIC, or handled by e.g. ACPI, not sending +an input event in this case is take care of by the PMIC / ACPI hardware / +code. But in the case of a GPIO button we need to explicitly suppress the +sending of the input event. + +This commit adds support for this by adding a no_wakeup_events bool to +struct gpio_keys_button, which platform code can set to suppress the +input events for presses of wakeup keys during suspend. + +Signed-off-by: Hans de Goede +--- +Changes in v2: +-This is a rewrite if my "Input: gpio_keys - Do not report wake button + presses as evdev events" patch. +-Instead of unconditionally ignoring presses of all wake-up buttons during + suspend, this rewrite makes this configurable per button +-This version uses a timer to delay clearing the suspended flag for software + debouncing, rather then jiffy compare magic +--- + drivers/input/keyboard/gpio_keys.c | 33 +++++++++++++++++++++++++++++++-- + include/linux/gpio_keys.h | 3 +++ + 2 files changed, 34 insertions(+), 2 deletions(-) + +diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c +index a047b9af8369..fa3a58620407 100644 +--- a/drivers/input/keyboard/gpio_keys.c ++++ b/drivers/input/keyboard/gpio_keys.c +@@ -38,6 +38,7 @@ struct gpio_button_data { + + unsigned short *code; + ++ struct timer_list unsuspend_timer; + struct timer_list release_timer; + unsigned int release_delay; /* in msecs, for IRQ-only buttons */ + +@@ -371,6 +372,9 @@ static void gpio_keys_gpio_report_event(struct gpio_button_data *bdata) + return; + } + ++ if (state && bdata->button->no_wakeup_events && bdata->suspended) ++ return; ++ + if (type == EV_ABS) { + if (state) + input_event(input, type, button->code, button->value); +@@ -400,6 +404,9 @@ static irqreturn_t gpio_keys_gpio_isr(int irq, void *dev_id) + if (bdata->button->wakeup) { + const struct gpio_keys_button *button = bdata->button; + ++ if (bdata->button->no_wakeup_events && bdata->suspended) ++ return IRQ_HANDLED; ++ + pm_stay_awake(bdata->input->dev.parent); + if (bdata->suspended && + (button->type == 0 || button->type == EV_KEY)) { +@@ -445,9 +452,13 @@ static irqreturn_t gpio_keys_irq_isr(int irq, void *dev_id) + spin_lock_irqsave(&bdata->lock, flags); + + if (!bdata->key_pressed) { +- if (bdata->button->wakeup) ++ if (bdata->button->wakeup) { + pm_wakeup_event(bdata->input->dev.parent, 0); + ++ if (bdata->button->no_wakeup_events && bdata->suspended) ++ goto out; ++ } ++ + input_event(input, EV_KEY, *bdata->code, 1); + input_sync(input); + +@@ -468,6 +479,13 @@ static irqreturn_t gpio_keys_irq_isr(int irq, void *dev_id) + return IRQ_HANDLED; + } + ++static void gpio_keys_unsuspend_timer(unsigned long _data) ++{ ++ struct gpio_button_data *bdata = (struct gpio_button_data *)_data; ++ ++ bdata->suspended = false; ++} ++ + static void gpio_keys_quiesce_key(void *data) + { + struct gpio_button_data *bdata = data; +@@ -476,6 +494,8 @@ static void gpio_keys_quiesce_key(void *data) + cancel_delayed_work_sync(&bdata->work); + else + del_timer_sync(&bdata->release_timer); ++ ++ del_timer_sync(&bdata->unsuspend_timer); + } + + static int gpio_keys_setup_key(struct platform_device *pdev, +@@ -496,6 +516,8 @@ static int gpio_keys_setup_key(struct platform_device *pdev, + bdata->input = input; + bdata->button = button; + spin_lock_init(&bdata->lock); ++ setup_timer(&bdata->unsuspend_timer, gpio_keys_unsuspend_timer, ++ (unsigned long)bdata); + + if (child) { + bdata->gpiod = devm_fwnode_get_gpiod_from_child(dev, NULL, +@@ -868,6 +890,7 @@ static int __maybe_unused gpio_keys_suspend(struct device *dev) + struct gpio_button_data *bdata = &ddata->data[i]; + if (bdata->button->wakeup) + enable_irq_wake(bdata->irq); ++ del_timer_sync(&bdata->unsuspend_timer); + bdata->suspended = true; + } + } else { +@@ -892,7 +915,13 @@ static int __maybe_unused gpio_keys_resume(struct device *dev) + struct gpio_button_data *bdata = &ddata->data[i]; + if (bdata->button->wakeup) + disable_irq_wake(bdata->irq); +- bdata->suspended = false; ++ if (bdata->button->no_wakeup_events) { ++ mod_timer(&bdata->unsuspend_timer, jiffies + ++ msecs_to_jiffies( ++ bdata->software_debounce)); ++ } else { ++ bdata->suspended = false; ++ } + } + } else { + mutex_lock(&input->mutex); +diff --git a/include/linux/gpio_keys.h b/include/linux/gpio_keys.h +index 0b71024c082c..d8a85e52b6bb 100644 +--- a/include/linux/gpio_keys.h ++++ b/include/linux/gpio_keys.h +@@ -15,6 +15,8 @@ struct device; + * @debounce_interval: debounce ticks interval in msecs + * @can_disable: %true indicates that userspace is allowed to + * disable button via sysfs ++ * @no_wakeup_events: For wake-up source buttons only, if %true then no input ++ * events will be generated if pressed while suspended + * @value: axis value for %EV_ABS + * @irq: Irq number in case of interrupt keys + */ +@@ -27,6 +29,7 @@ struct gpio_keys_button { + int wakeup; + int debounce_interval; + bool can_disable; ++ bool no_wakeup_events; + int value; + unsigned int irq; + }; +-- +2.13.4 + diff --git a/0001-cpupower-Correct-return-type-of-cpu_power_is_cpu_onl.patch b/0001-cpupower-Correct-return-type-of-cpu_power_is_cpu_onl.patch deleted file mode 100644 index 05b8cf999..000000000 --- a/0001-cpupower-Correct-return-type-of-cpu_power_is_cpu_onl.patch +++ /dev/null @@ -1,49 +0,0 @@ -From 9f692cbe4a01dd9e3c3e954ec6b59662b68f9ce4 Mon Sep 17 00:00:00 2001 -From: Laura Abbott -Date: Fri, 9 Sep 2016 10:19:02 -0700 -Subject: [PATCH] cpupower: Correct return type of cpu_power_is_cpu_online in - cpufreq -To: Thomas Renninger -Cc: linux-pm@vger.kernel.org -Cc: linux-kernel@vger.kernel.org - -When converting to a shared library in ac5a181d065d ("cpupower: Add -cpuidle parts into library"), cpu_freq_cpu_exists was converted to -cpupower_is_cpu_online. cpu_req_cpu_exists returned 0 on success and --ENOSYS on failure whereas cpupower_is_cpu_online returns 1 on success. -Check for the correct return value in cpufreq-set. - -See https://bugzilla.redhat.com/show_bug.cgi?id=1374212 - -Fixes: ac5a181d065d ("cpupower: Add cpuidle parts into library") -Reported-by: Julian Seward -Signed-off-by: Laura Abbott ---- - tools/power/cpupower/utils/cpufreq-set.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/tools/power/cpupower/utils/cpufreq-set.c b/tools/power/cpupower/utils/cpufreq-set.c -index b4bf769..8971d71 100644 ---- a/tools/power/cpupower/utils/cpufreq-set.c -+++ b/tools/power/cpupower/utils/cpufreq-set.c -@@ -296,7 +296,7 @@ int cmd_freq_set(int argc, char **argv) - struct cpufreq_affected_cpus *cpus; - - if (!bitmask_isbitset(cpus_chosen, cpu) || -- cpupower_is_cpu_online(cpu)) -+ cpupower_is_cpu_online(cpu) != 1) - continue; - - cpus = cpufreq_get_related_cpus(cpu); -@@ -316,7 +316,7 @@ int cmd_freq_set(int argc, char **argv) - cpu <= bitmask_last(cpus_chosen); cpu++) { - - if (!bitmask_isbitset(cpus_chosen, cpu) || -- cpupower_is_cpu_online(cpu)) -+ cpupower_is_cpu_online(cpu) != 1) - continue; - - if (cpupower_is_cpu_online(cpu) != 1) --- -2.10.0 - diff --git a/0001-fs-locks-Remove-fl_nspid-and-use-fs-specific-l_pid-f.patch b/0001-fs-locks-Remove-fl_nspid-and-use-fs-specific-l_pid-f.patch new file mode 100644 index 000000000..065132bc2 --- /dev/null +++ b/0001-fs-locks-Remove-fl_nspid-and-use-fs-specific-l_pid-f.patch @@ -0,0 +1,296 @@ +From 9d5b86ac13c573795525ecac6ed2db39ab23e2a8 Mon Sep 17 00:00:00 2001 +From: Benjamin Coddington +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 +Signed-off-by: Jeff Layton +--- + 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 + diff --git a/0001-mm-thp-Do-not-make-page-table-dirty-unconditionally-.patch b/0001-mm-thp-Do-not-make-page-table-dirty-unconditionally-.patch new file mode 100644 index 000000000..2a1d7b719 --- /dev/null +++ b/0001-mm-thp-Do-not-make-page-table-dirty-unconditionally-.patch @@ -0,0 +1,108 @@ +From a8f97366452ed491d13cf1e44241bc0b5740b1f0 Mon Sep 17 00:00:00 2001 +From: "Kirill A. Shutemov" +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 +Cc: Michal Hocko +Cc: Hugh Dickins +Signed-off-by: Linus Torvalds +--- + 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 + diff --git a/0001-platform-x86-Add-driver-for-ACPI-INT0002-Virtual-GPI.patch b/0001-platform-x86-Add-driver-for-ACPI-INT0002-Virtual-GPI.patch new file mode 100644 index 000000000..a0b6ff03e --- /dev/null +++ b/0001-platform-x86-Add-driver-for-ACPI-INT0002-Virtual-GPI.patch @@ -0,0 +1,339 @@ +From 3bbfe49a1d965b951527cde0da48f5d7677db264 Mon Sep 17 00:00:00 2001 +From: Hans de Goede +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 +Cc: Takashi Iwai +Signed-off-by: Hans de Goede +Reviewed-by: Andy Shevchenko +Acked-by: Rafael J. Wysocki +Reviewed-by: Linus Walleij +--- +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 ++ * ++ * Loosely based on android x86 kernel code which is: ++ * ++ * Copyright (c) 2014, Intel Corporation. ++ * ++ * Author: Dyut Kumar Sil ++ * ++ * 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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++ ++#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? */ ++ 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 "); ++MODULE_DESCRIPTION("Intel INT0002 Virtual GPIO driver"); ++MODULE_LICENSE("GPL"); +-- +2.13.0 + diff --git a/0001-power-supply-max17042_battery-Add-support-for-ACPI-e.patch b/0001-power-supply-max17042_battery-Add-support-for-ACPI-e.patch new file mode 100644 index 000000000..858cd5a34 --- /dev/null +++ b/0001-power-supply-max17042_battery-Add-support-for-ACPI-e.patch @@ -0,0 +1,78 @@ +From 075bb90dbb4d894938c5859e3850987238db9cd8 Mon Sep 17 00:00:00 2001 +From: Hans de Goede +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 +--- + 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 + #include + #include + #include +@@ -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 + diff --git a/0001-usb-usbtest-fix-NULL-pointer-dereference.patch b/0001-usb-usbtest-fix-NULL-pointer-dereference.patch new file mode 100644 index 000000000..acc03ec7d --- /dev/null +++ b/0001-usb-usbtest-fix-NULL-pointer-dereference.patch @@ -0,0 +1,41 @@ +From 7c80f9e4a588f1925b07134bb2e3689335f6c6d8 Mon Sep 17 00:00:00 2001 +From: Alan Stern +Date: Fri, 29 Sep 2017 10:54:24 -0400 +Subject: [PATCH] usb: usbtest: fix NULL pointer dereference + +If the usbtest driver encounters a device with an IN bulk endpoint but +no OUT bulk endpoint, it will try to dereference a NULL pointer +(out->desc.bEndpointAddress). The problem can be solved by adding a +missing test. + +Signed-off-by: Alan Stern +Reported-by: Andrey Konovalov +Tested-by: Andrey Konovalov +Signed-off-by: Felipe Balbi +--- + drivers/usb/misc/usbtest.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c +index 113e38bfe0ef..b3fc602b2e24 100644 +--- a/drivers/usb/misc/usbtest.c ++++ b/drivers/usb/misc/usbtest.c +@@ -202,12 +202,13 @@ get_endpoints(struct usbtest_dev *dev, struct usb_interface *intf) + return tmp; + } + +- if (in) { ++ if (in) + dev->in_pipe = usb_rcvbulkpipe(udev, + in->desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK); ++ if (out) + dev->out_pipe = usb_sndbulkpipe(udev, + out->desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK); +- } ++ + if (iso_in) { + dev->iso_in = &iso_in->desc; + dev->in_iso_pipe = usb_rcvisocpipe(udev, +-- +2.13.6 + diff --git a/0002-Input-soc_button_array-Suppress-power-button-presses.patch b/0002-Input-soc_button_array-Suppress-power-button-presses.patch new file mode 100644 index 000000000..d95aeb36c --- /dev/null +++ b/0002-Input-soc_button_array-Suppress-power-button-presses.patch @@ -0,0 +1,62 @@ +From d561f0543506bc12e7b3355efddb0bfd7ca83c74 Mon Sep 17 00:00:00 2001 +From: Hans de Goede +Date: Sat, 22 Jul 2017 13:17:36 +0200 +Subject: [PATCH 2/2] Input: soc_button_array - Suppress power button presses + during suspend + +If the power-button is pressed to wakeup the laptop/tablet from suspend +and we report a KEY_POWER event to userspace when woken up this will cause +userspace to immediately suspend the system again which is undesirable. + +This commit sets the new no_wakeup_events flag in the gpio_keys_button +struct for the power-button suppressing the undesirable KEY_POWER input +events on wake-up. + +Signed-off-by: Hans de Goede +--- +Changes in v2: +-New patch in v2 of this patch-set +--- + drivers/input/misc/soc_button_array.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/drivers/input/misc/soc_button_array.c b/drivers/input/misc/soc_button_array.c +index f600f3a7a3c6..27b99831cb97 100644 +--- a/drivers/input/misc/soc_button_array.c ++++ b/drivers/input/misc/soc_button_array.c +@@ -27,6 +27,7 @@ struct soc_button_info { + unsigned int event_code; + bool autorepeat; + bool wakeup; ++ bool no_wakeup_events; + }; + + /* +@@ -100,6 +101,7 @@ soc_button_device_create(struct platform_device *pdev, + gpio_keys[n_buttons].active_low = 1; + gpio_keys[n_buttons].desc = info->name; + gpio_keys[n_buttons].wakeup = info->wakeup; ++ gpio_keys[n_buttons].no_wakeup_events = info->no_wakeup_events; + /* These devices often use cheap buttons, use 50 ms debounce */ + gpio_keys[n_buttons].debounce_interval = 50; + n_buttons++; +@@ -185,6 +187,7 @@ static int soc_button_parse_btn_desc(struct device *dev, + info->name = "power"; + info->event_code = KEY_POWER; + info->wakeup = true; ++ info->no_wakeup_events = true; + } else if (upage == 0x07 && usage == 0xe3) { + info->name = "home"; + info->event_code = KEY_LEFTMETA; +@@ -369,7 +372,7 @@ static int soc_button_probe(struct platform_device *pdev) + * Platforms" + */ + static struct soc_button_info soc_button_PNP0C40[] = { +- { "power", 0, EV_KEY, KEY_POWER, false, true }, ++ { "power", 0, EV_KEY, KEY_POWER, false, true, true }, + { "home", 1, EV_KEY, KEY_LEFTMETA, false, true }, + { "volume_up", 2, EV_KEY, KEY_VOLUMEUP, true, false }, + { "volume_down", 3, EV_KEY, KEY_VOLUMEDOWN, true, false }, +-- +2.13.4 + diff --git a/0002-mfd-Add-Cherry-Trail-Whiskey-Cove-PMIC-driver.patch b/0002-mfd-Add-Cherry-Trail-Whiskey-Cove-PMIC-driver.patch new file mode 100644 index 000000000..49975811b --- /dev/null +++ b/0002-mfd-Add-Cherry-Trail-Whiskey-Cove-PMIC-driver.patch @@ -0,0 +1,355 @@ +From c0f9254fdd0703ade018b2ff3a8cca433f781a11 Mon Sep 17 00:00:00 2001 +From: Hans de Goede +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 +Cc: Felipe Balbi +Cc: Andy Shevchenko +Signed-off-by: Hans de Goede +Reviewed-by: Andy Shevchenko +--- +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 + +Changes in v3: +-Drop #include 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 ++ * ++ * 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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/* 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 + diff --git a/0002-power-supply-max17042_battery-Fix-ACPI-interrupt-iss.patch b/0002-power-supply-max17042_battery-Fix-ACPI-interrupt-iss.patch new file mode 100644 index 000000000..6daecaf4d --- /dev/null +++ b/0002-power-supply-max17042_battery-Fix-ACPI-interrupt-iss.patch @@ -0,0 +1,80 @@ +From 27b9d46d25c873b351757c44ce523bf0ede1d08e Mon Sep 17 00:00:00 2001 +From: Hans de Goede +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 +--- + 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 + diff --git a/0003-power-supply-core-Add-support-for-supplied-from-devi.patch b/0003-power-supply-core-Add-support-for-supplied-from-devi.patch new file mode 100644 index 000000000..ab646e2e5 --- /dev/null +++ b/0003-power-supply-core-Add-support-for-supplied-from-devi.patch @@ -0,0 +1,57 @@ +From 69dd0606a0d8680fe0a5e9b959f6662e582e1674 Mon Sep 17 00:00:00 2001 +From: Hans de Goede +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 +--- + 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 + diff --git a/0004-platform-x86-intel_cht_int33fe-Set-supplied-from-pro.patch b/0004-platform-x86-intel_cht_int33fe-Set-supplied-from-pro.patch new file mode 100644 index 000000000..342a48c54 --- /dev/null +++ b/0004-platform-x86-intel_cht_int33fe-Set-supplied-from-pro.patch @@ -0,0 +1,48 @@ +From 99c44df299d96db6a170ccce9b8108fc2e7f8bae Mon Sep 17 00:00:00 2001 +From: Hans de Goede +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 +--- + 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 + diff --git a/0005-ACPI-PMIC-xpower-Add-support-for-the-GPI1-regulator-.patch b/0005-ACPI-PMIC-xpower-Add-support-for-the-GPI1-regulator-.patch new file mode 100644 index 000000000..c6f299c29 --- /dev/null +++ b/0005-ACPI-PMIC-xpower-Add-support-for-the-GPI1-regulator-.patch @@ -0,0 +1,80 @@ +From cc2b0e2c164d02ab42efa736f91f53baf8d8bc36 Mon Sep 17 00:00:00 2001 +From: Hans de Goede +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 +Reviewed-by: Andy Shevchenko +--- +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 + diff --git a/0006-Input-axp20x-pek-Add-wakeup-support.patch b/0006-Input-axp20x-pek-Add-wakeup-support.patch new file mode 100644 index 000000000..1ec9659bd --- /dev/null +++ b/0006-Input-axp20x-pek-Add-wakeup-support.patch @@ -0,0 +1,67 @@ +From fbac4c05ec1d7c2d949f50baf1e934cbfbb6a494 Mon Sep 17 00:00:00 2001 +From: Hans de Goede +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 +--- + 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 + diff --git a/0007-platform-x86-silead_dmi-Add-touchscreen-info-for-GP-.patch b/0007-platform-x86-silead_dmi-Add-touchscreen-info-for-GP-.patch new file mode 100644 index 000000000..0b7633459 --- /dev/null +++ b/0007-platform-x86-silead_dmi-Add-touchscreen-info-for-GP-.patch @@ -0,0 +1,56 @@ +From d95c127c48ef784214671359a41ac505ac30098a Mon Sep 17 00:00:00 2001 +From: Hans de Goede +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 +--- + 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 + diff --git a/0008-platform-x86-silead_dmi-Add-touchscreen-info-for-PoV.patch b/0008-platform-x86-silead_dmi-Add-touchscreen-info-for-PoV.patch new file mode 100644 index 000000000..975deb8f0 --- /dev/null +++ b/0008-platform-x86-silead_dmi-Add-touchscreen-info-for-PoV.patch @@ -0,0 +1,59 @@ +From 55b347c61b2850d1e11e159ab02dc71f13b06481 Mon Sep 17 00:00:00 2001 +From: Hans de Goede +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 +--- + 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 + diff --git a/0009-platform-x86-silead_dmi-Add-touchscreen-info-for-Pip.patch b/0009-platform-x86-silead_dmi-Add-touchscreen-info-for-Pip.patch new file mode 100644 index 000000000..0770395d9 --- /dev/null +++ b/0009-platform-x86-silead_dmi-Add-touchscreen-info-for-Pip.patch @@ -0,0 +1,57 @@ +From b239a7a0c2a1435aa5cbab3f233e0c37e82943dd Mon Sep 17 00:00:00 2001 +From: Hans de Goede +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 +--- + 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 + diff --git a/0010-Input-silead-Add-support-for-capactive-home-button-f.patch b/0010-Input-silead-Add-support-for-capactive-home-button-f.patch new file mode 100644 index 000000000..ce9be3760 --- /dev/null +++ b/0010-Input-silead-Add-support-for-capactive-home-button-f.patch @@ -0,0 +1,114 @@ +From 33fc16fd8aa3684e19b1d1f0a712593e2e570ab1 Mon Sep 17 00:00:00 2001 +From: Hans de Goede +Date: Sun, 11 Jun 2017 21:24:50 +0200 +Subject: [PATCH 10/16] Input: silead: Add support for capactive home button + found on some x86 tablets + +On some x86 tablets with a silead touchscreen the windows logo on the +front is a capacitive home button. Touching this button results in a touch +with bits 12-15 of the Y coordinates set, while normally only the lower 12 +are used. + +Detect this and report a KEY_LEFTMETA press when this happens. Note for +now we only respond to the Y coordinate bits 12-15 containing 0x01, on some +tablets *without* a capacative button I've noticed these bits containing +0x04 when crossing the edges of the screen. + +Signed-off-by: Hans de Goede +--- + drivers/input/touchscreen/silead.c | 45 ++++++++++++++++++++++++++++---------- + 1 file changed, 34 insertions(+), 11 deletions(-) + +diff --git a/drivers/input/touchscreen/silead.c b/drivers/input/touchscreen/silead.c +index 0dbcf105f7db..c0ba40c09699 100644 +--- a/drivers/input/touchscreen/silead.c ++++ b/drivers/input/touchscreen/silead.c +@@ -56,7 +56,7 @@ + #define SILEAD_POINT_Y_MSB_OFF 0x01 + #define SILEAD_POINT_X_OFF 0x02 + #define SILEAD_POINT_X_MSB_OFF 0x03 +-#define SILEAD_TOUCH_ID_MASK 0xF0 ++#define SILEAD_EXTRA_DATA_MASK 0xF0 + + #define SILEAD_CMD_SLEEP_MIN 10000 + #define SILEAD_CMD_SLEEP_MAX 20000 +@@ -109,6 +109,8 @@ static int silead_ts_request_input_dev(struct silead_ts_data *data) + INPUT_MT_DIRECT | INPUT_MT_DROP_UNUSED | + INPUT_MT_TRACK); + ++ input_set_capability(data->input, EV_KEY, KEY_LEFTMETA); ++ + data->input->name = SILEAD_TS_NAME; + data->input->phys = "input/ts"; + data->input->id.bustype = BUS_I2C; +@@ -139,7 +141,8 @@ static void silead_ts_read_data(struct i2c_client *client) + struct input_dev *input = data->input; + struct device *dev = &client->dev; + u8 *bufp, buf[SILEAD_TS_DATA_LEN]; +- int touch_nr, error, i; ++ int touch_nr, softbutton, error, i; ++ bool softbutton_pressed = false; + + error = i2c_smbus_read_i2c_block_data(client, SILEAD_REG_DATA, + SILEAD_TS_DATA_LEN, buf); +@@ -148,21 +151,40 @@ static void silead_ts_read_data(struct i2c_client *client) + return; + } + +- touch_nr = buf[0]; +- if (touch_nr > data->max_fingers) { ++ if (buf[0] > data->max_fingers) { + dev_warn(dev, "More touches reported then supported %d > %d\n", +- touch_nr, data->max_fingers); +- touch_nr = data->max_fingers; ++ buf[0], data->max_fingers); ++ buf[0] = data->max_fingers; + } + ++ touch_nr = 0; + bufp = buf + SILEAD_POINT_DATA_LEN; +- for (i = 0; i < touch_nr; i++, bufp += SILEAD_POINT_DATA_LEN) { +- /* Bits 4-7 are the touch id */ +- data->id[i] = (bufp[SILEAD_POINT_X_MSB_OFF] & +- SILEAD_TOUCH_ID_MASK) >> 4; +- touchscreen_set_mt_pos(&data->pos[i], &data->prop, ++ for (i = 0; i < buf[0]; i++, bufp += SILEAD_POINT_DATA_LEN) { ++ softbutton = (bufp[SILEAD_POINT_Y_MSB_OFF] & ++ SILEAD_EXTRA_DATA_MASK) >> 4; ++ ++ if (softbutton) { ++ /* ++ * For now only respond to softbutton == 0x01, some ++ * tablets *without* a capacative button send 0x04 ++ * when crossing the edges of the screen. ++ */ ++ if (softbutton == 0x01) ++ softbutton_pressed = true; ++ ++ continue; ++ } ++ ++ /* ++ * Bits 4-7 are the touch id, note not all models have ++ * hardware touch ids so atm we don't use these. ++ */ ++ data->id[touch_nr] = (bufp[SILEAD_POINT_X_MSB_OFF] & ++ SILEAD_EXTRA_DATA_MASK) >> 4; ++ touchscreen_set_mt_pos(&data->pos[touch_nr], &data->prop, + get_unaligned_le16(&bufp[SILEAD_POINT_X_OFF]) & 0xfff, + get_unaligned_le16(&bufp[SILEAD_POINT_Y_OFF]) & 0xfff); ++ touch_nr++; + } + + input_mt_assign_slots(input, data->slots, data->pos, touch_nr, 0); +@@ -178,6 +200,7 @@ static void silead_ts_read_data(struct i2c_client *client) + } + + input_mt_sync_frame(input); ++ input_report_key(input, KEY_LEFTMETA, softbutton_pressed); + input_sync(input); + } + +-- +2.13.0 + diff --git a/0011-Input-goodix-Add-support-for-capacitive-home-button.patch b/0011-Input-goodix-Add-support-for-capacitive-home-button.patch new file mode 100644 index 000000000..162357c21 --- /dev/null +++ b/0011-Input-goodix-Add-support-for-capacitive-home-button.patch @@ -0,0 +1,53 @@ +From 2a99775c336303d2efc43eab4f24b34722a28faa Mon Sep 17 00:00:00 2001 +From: "Sergei A. Trusov" +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 +Acked-by: Bastien Nocera +--- + 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 + diff --git a/0012-Input-gpio_keys-Do-not-report-wake-button-presses-as.patch b/0012-Input-gpio_keys-Do-not-report-wake-button-presses-as.patch new file mode 100644 index 000000000..9b52e3908 --- /dev/null +++ b/0012-Input-gpio_keys-Do-not-report-wake-button-presses-as.patch @@ -0,0 +1,150 @@ +From 02b823a4d28ffb5fde5192799abd934d9de95630 Mon Sep 17 00:00:00 2001 +From: Hans de Goede +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 +--- +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 + #include + ++#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 + diff --git a/0013-iio-accel-bmc150-Add-support-for-BOSC0200-ACPI-devic.patch b/0013-iio-accel-bmc150-Add-support-for-BOSC0200-ACPI-devic.patch new file mode 100644 index 000000000..8eb41ee3f --- /dev/null +++ b/0013-iio-accel-bmc150-Add-support-for-BOSC0200-ACPI-devic.patch @@ -0,0 +1,32 @@ +From bf3e9581e10a19b2ce77a45fe001116d269b4c7f Mon Sep 17 00:00:00 2001 +From: Hans de Goede +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 +--- + 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 + diff --git a/0014-mmc-sdhci-acpi-Workaround-conflict-with-PCI-wifi-on-.patch b/0014-mmc-sdhci-acpi-Workaround-conflict-with-PCI-wifi-on-.patch new file mode 100644 index 000000000..b5c717c64 --- /dev/null +++ b/0014-mmc-sdhci-acpi-Workaround-conflict-with-PCI-wifi-on-.patch @@ -0,0 +1,143 @@ +From 51eb7454942c68c84b82782e47637de3ba37f113 Mon Sep 17 00:00:00 2001 +From: Adrian Hunter +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 +Acked-by: Hans de Goede +Tested-by: Hans de Goede +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 + #include + #include ++#include + #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 + diff --git a/0015-i2c-cht-wc-Add-Intel-Cherry-Trail-Whiskey-Cove-SMBUS.patch b/0015-i2c-cht-wc-Add-Intel-Cherry-Trail-Whiskey-Cove-SMBUS.patch new file mode 100644 index 000000000..5d7497ce1 --- /dev/null +++ b/0015-i2c-cht-wc-Add-Intel-Cherry-Trail-Whiskey-Cove-SMBUS.patch @@ -0,0 +1,410 @@ +From bd0d7169342e47919f68e75d659968f02b62f84b Mon Sep 17 00:00:00 2001 +From: Hans de Goede +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 +Signed-off-by: Hans de Goede +--- +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 ++ * ++ * 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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#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 "); ++MODULE_LICENSE("GPL"); +-- +2.13.0 + diff --git a/0016-Input-silead-Do-not-try-to-directly-access-the-GPIO-.patch b/0016-Input-silead-Do-not-try-to-directly-access-the-GPIO-.patch new file mode 100644 index 000000000..14b4c27bf --- /dev/null +++ b/0016-Input-silead-Do-not-try-to-directly-access-the-GPIO-.patch @@ -0,0 +1,54 @@ +From fd4fb1f6633b21042ff084868323e15e708fe1cd Mon Sep 17 00:00:00 2001 +From: Hans de Goede +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 +--- + 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 + diff --git a/1-2-kvm-vmx-Reinstate-support-for-CPUs-without-virtual-NMI.patch b/1-2-kvm-vmx-Reinstate-support-for-CPUs-without-virtual-NMI.patch new file mode 100644 index 000000000..ca079af42 --- /dev/null +++ b/1-2-kvm-vmx-Reinstate-support-for-CPUs-without-virtual-NMI.patch @@ -0,0 +1,296 @@ +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 +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 +--- + 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) diff --git a/1-3-net-set-tb--fast_sk_family.patch b/1-3-net-set-tb--fast_sk_family.patch new file mode 100644 index 000000000..dbe5250ab --- /dev/null +++ b/1-3-net-set-tb--fast_sk_family.patch @@ -0,0 +1,50 @@ +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 +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 , stable@vger.kernel.org +Date: Mon, 18 Sep 2017 12:28:55 -0400 +From: josef@toxicpanda.com +List-Id: + +From: Josef Bacik + +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 +Signed-off-by: Josef Bacik +--- + 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 diff --git a/2-3-net-use-inet6_rcv_saddr-to-compare-sockets.patch b/2-3-net-use-inet6_rcv_saddr-to-compare-sockets.patch new file mode 100644 index 000000000..3d64361df --- /dev/null +++ b/2-3-net-use-inet6_rcv_saddr-to-compare-sockets.patch @@ -0,0 +1,44 @@ +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 +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 , stable@vger.kernel.org +Date: Mon, 18 Sep 2017 12:28:56 -0400 +From: josef@toxicpanda.com +List-Id: + +From: Josef Bacik + +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 +Signed-off-by: Josef Bacik +--- + 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, diff --git a/3-3-inet-fix-improper-empty-comparison.patch b/3-3-inet-fix-improper-empty-comparison.patch new file mode 100644 index 000000000..421a235cb --- /dev/null +++ b/3-3-inet-fix-improper-empty-comparison.patch @@ -0,0 +1,53 @@ +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 +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 , stable@vger.kernel.org +Date: Mon, 18 Sep 2017 12:28:57 -0400 +From: josef@toxicpanda.com +List-Id: + +From: Josef Bacik + +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 +Signed-off-by: Josef Bacik +--- + 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; diff --git a/ACPI-Limit-access-to-custom_method.patch b/ACPI-Limit-access-to-custom_method.patch deleted file mode 100644 index 38236753e..000000000 --- a/ACPI-Limit-access-to-custom_method.patch +++ /dev/null @@ -1,31 +0,0 @@ -From 4b85149b764cd024e3dd2aff9eb22a9e1aadd1fa Mon Sep 17 00:00:00 2001 -From: Matthew Garrett -Date: Fri, 9 Mar 2012 08:39:37 -0500 -Subject: [PATCH 04/20] ACPI: Limit access to custom_method - -custom_method effectively allows arbitrary access to system memory, making -it possible for an attacker to circumvent restrictions on module loading. -Disable it if any such restrictions have been enabled. - -Signed-off-by: Matthew Garrett ---- - drivers/acpi/custom_method.c | 3 +++ - 1 file changed, 3 insertions(+) - -diff --git a/drivers/acpi/custom_method.c b/drivers/acpi/custom_method.c -index c68e72414a67..4277938af700 100644 ---- a/drivers/acpi/custom_method.c -+++ b/drivers/acpi/custom_method.c -@@ -29,6 +29,9 @@ static ssize_t cm_write(struct file *file, const char __user * user_buf, - struct acpi_table_header table; - acpi_status status; - -+ if (secure_modules()) -+ return -EPERM; -+ - if (!(*ppos)) { - /* parse the table header to get the table length */ - if (count <= sizeof(struct acpi_table_header)) --- -2.4.3 - diff --git a/Add-EFI-signature-data-types.patch b/Add-EFI-signature-data-types.patch index 23402354e..f7f7c36d3 100644 --- a/Add-EFI-signature-data-types.patch +++ b/Add-EFI-signature-data-types.patch @@ -1,37 +1,36 @@ -From 5216de8394ff599e41c8540c0572368c18c51459 Mon Sep 17 00:00:00 2001 +From 0451d4e795929a69a0fda6d960aa4b077c5bd179 Mon Sep 17 00:00:00 2001 From: Dave Howells -Date: Tue, 23 Oct 2012 09:30:54 -0400 -Subject: [PATCH 4/9] Add EFI signature data types +Date: Fri, 5 May 2017 08:21:58 +0100 +Subject: [PATCH 1/4] efi: Add EFI signature data types -Add the data types that are used for containing hashes, keys and certificates -for cryptographic verification. - -Bugzilla: N/A -Upstream-status: Fedora mustard for now +Add the data types that are used for containing hashes, keys and +certificates for cryptographic verification along with their corresponding +type GUIDs. Signed-off-by: David Howells --- - include/linux/efi.h | 20 ++++++++++++++++++++ - 1 file changed, 20 insertions(+) + include/linux/efi.h | 25 +++++++++++++++++++++++++ + 1 file changed, 25 insertions(+) diff --git a/include/linux/efi.h b/include/linux/efi.h -index 8cb38cfcba74..8c274b4ea8e6 100644 +index ec36f42..3259ad6 100644 --- a/include/linux/efi.h +++ b/include/linux/efi.h -@@ -647,6 +647,9 @@ void efi_native_runtime_setup(void); - #define LINUX_EFI_ARM_SCREEN_INFO_TABLE_GUID EFI_GUID(0xe03fc20a, 0x85dc, 0x406e, 0xb9, 0x0e, 0x4a, 0xb5, 0x02, 0x37, 0x1d, 0x95) - #define LINUX_EFI_LOADER_ENTRY_GUID EFI_GUID(0x4a67b082, 0x0a4c, 0x41cf, 0xb6, 0xc7, 0x44, 0x0b, 0x29, 0xbb, 0x8c, 0x4f) - -+#define EFI_CERT_SHA256_GUID EFI_GUID(0xc1c41626, 0x504c, 0x4092, 0xac, 0xa9, 0x41, 0xf9, 0x36, 0x93, 0x43, 0x28) -+#define EFI_CERT_X509_GUID EFI_GUID(0xa5c059a1, 0x94e4, 0x4aa7, 0x87, 0xb5, 0xab, 0x15, 0x5c, 0x2b, 0xf0, 0x72) +@@ -614,6 +614,10 @@ void efi_native_runtime_setup(void); + #define EFI_IMAGE_SECURITY_DATABASE_GUID EFI_GUID(0xd719b2cb, 0x3d3a, 0x4596, 0xa3, 0xbc, 0xda, 0xd0, 0x0e, 0x67, 0x65, 0x6f) + #define EFI_SHIM_LOCK_GUID EFI_GUID(0x605dab50, 0xe046, 0x4300, 0xab, 0xb6, 0x3d, 0xd8, 0x10, 0xdd, 0x8b, 0x23) + ++#define EFI_CERT_SHA256_GUID EFI_GUID(0xc1c41626, 0x504c, 0x4092, 0xac, 0xa9, 0x41, 0xf9, 0x36, 0x93, 0x43, 0x28) ++#define EFI_CERT_X509_GUID EFI_GUID(0xa5c059a1, 0x94e4, 0x4aa7, 0x87, 0xb5, 0xab, 0x15, 0x5c, 0x2b, 0xf0, 0x72) ++#define EFI_CERT_X509_SHA256_GUID EFI_GUID(0x3bd2a492, 0x96c0, 0x4079, 0xb4, 0x20, 0xfc, 0xf9, 0x8e, 0xf1, 0x03, 0xed) + - typedef struct { - efi_guid_t guid; - u64 table; -@@ -879,6 +885,20 @@ typedef struct { + /* + * This GUID is used to pass to the kernel proper the struct screen_info + * structure that was populated by the stub based on the GOP protocol instance +@@ -873,6 +877,27 @@ typedef struct { efi_memory_desc_t entry[0]; } efi_memory_attributes_table_t; - + +typedef struct { + efi_guid_t signature_owner; + u8 signature_data[]; @@ -45,10 +44,17 @@ index 8cb38cfcba74..8c274b4ea8e6 100644 + u8 signature_header[]; + /* efi_signature_data_t signatures[][] */ +} efi_signature_list_t; ++ ++typedef u8 efi_sha256_hash_t[32]; ++ ++typedef struct { ++ efi_sha256_hash_t to_be_signed_hash; ++ efi_time_t time_of_revocation; ++} efi_cert_x509_sha256_t; + /* * All runtime access to EFI goes through this structure: */ -- -2.5.5 +2.9.3 diff --git a/Add-an-EFI-signature-blob-parser-and-key-loader.patch b/Add-an-EFI-signature-blob-parser-and-key-loader.patch index 3697a4b74..e3941eeaa 100644 --- a/Add-an-EFI-signature-blob-parser-and-key-loader.patch +++ b/Add-an-EFI-signature-blob-parser-and-key-loader.patch @@ -1,29 +1,38 @@ -From e36a2d65e25fdf42b50aa5dc17583d7bfd09c4c4 Mon Sep 17 00:00:00 2001 +From e4c62c12635a371e43bd17e8d33a936668264491 Mon Sep 17 00:00:00 2001 From: Dave Howells -Date: Tue, 23 Oct 2012 09:36:28 -0400 -Subject: [PATCH 5/9] Add an EFI signature blob parser and key loader. +Date: Fri, 5 May 2017 08:21:58 +0100 +Subject: [PATCH 2/4] efi: Add an EFI signature blob parser -X.509 certificates are loaded into the specified keyring as asymmetric type -keys. +Add a function to parse an EFI signature blob looking for elements of +interest. A list is made up of a series of sublists, where all the +elements in a sublist are of the same type, but sublists can be of +different types. + +For each sublist encountered, the function pointed to by the +get_handler_for_guid argument is called with the type specifier GUID and +returns either a pointer to a function to handle elements of that type or +NULL if the type is not of interest. + +If the sublist is of interest, each element is passed to the handler +function in turn. -[labbott@fedoraproject.org: Drop KEY_ALLOC_TRUSTED] Signed-off-by: David Howells --- - crypto/asymmetric_keys/Kconfig | 8 +++ - crypto/asymmetric_keys/Makefile | 1 + - crypto/asymmetric_keys/efi_parser.c | 108 ++++++++++++++++++++++++++++++++++++ - include/linux/efi.h | 4 ++ - 4 files changed, 121 insertions(+) - create mode 100644 crypto/asymmetric_keys/efi_parser.c + certs/Kconfig | 8 ++++ + certs/Makefile | 1 + + certs/efi_parser.c | 112 ++++++++++++++++++++++++++++++++++++++++++++++++++++ + include/linux/efi.h | 9 +++++ + 4 files changed, 130 insertions(+) + create mode 100644 certs/efi_parser.c + +diff --git a/certs/Kconfig b/certs/Kconfig +index 6ce51ed..630ae09 100644 +--- a/certs/Kconfig ++++ b/certs/Kconfig +@@ -82,4 +82,12 @@ config SYSTEM_BLACKLIST_HASH_LIST + wrapper to incorporate the list into the kernel. Each should + be a string of hex digits. -diff --git a/crypto/asymmetric_keys/Kconfig b/crypto/asymmetric_keys/Kconfig -index e28e912000a7..94024e8aedaa 100644 ---- a/crypto/asymmetric_keys/Kconfig -+++ b/crypto/asymmetric_keys/Kconfig -@@ -60,4 +60,12 @@ config SIGNED_PE_FILE_VERIFICATION - This option provides support for verifying the signature(s) on a - signed PE binary. - +config EFI_SIGNATURE_LIST_PARSER + bool "EFI signature list parser" + depends on EFI @@ -32,28 +41,28 @@ index e28e912000a7..94024e8aedaa 100644 + This option provides support for parsing EFI signature lists for + X.509 certificates and turning them into keys. + - endif # ASYMMETRIC_KEY_TYPE -diff --git a/crypto/asymmetric_keys/Makefile b/crypto/asymmetric_keys/Makefile -index 6516855bec18..c099fe15ed6d 100644 ---- a/crypto/asymmetric_keys/Makefile -+++ b/crypto/asymmetric_keys/Makefile -@@ -10,6 +10,7 @@ asymmetric_keys-y := \ - signature.o - - obj-$(CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE) += public_key.o + endmenu +diff --git a/certs/Makefile b/certs/Makefile +index 4119bb3..738151a 100644 +--- a/certs/Makefile ++++ b/certs/Makefile +@@ -9,6 +9,7 @@ obj-$(CONFIG_SYSTEM_BLACKLIST_KEYRING) += blacklist_hashes.o + else + obj-$(CONFIG_SYSTEM_BLACKLIST_KEYRING) += blacklist_nohashes.o + endif +obj-$(CONFIG_EFI_SIGNATURE_LIST_PARSER) += efi_parser.o - - # - # X.509 Certificate handling -diff --git a/crypto/asymmetric_keys/efi_parser.c b/crypto/asymmetric_keys/efi_parser.c + + ifeq ($(CONFIG_SYSTEM_TRUSTED_KEYRING),y) + +diff --git a/certs/efi_parser.c b/certs/efi_parser.c new file mode 100644 -index 000000000000..636feb18b733 +index 0000000..4e396f9 --- /dev/null -+++ b/crypto/asymmetric_keys/efi_parser.c -@@ -0,0 +1,108 @@ ++++ b/certs/efi_parser.c +@@ -0,0 +1,112 @@ +/* EFI signature/key/certificate list parser + * -+ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. ++ * Copyright (C) 2012, 2016 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * This program is free software; you can redistribute it and/or @@ -67,27 +76,44 @@ index 000000000000..636feb18b733 +#include +#include +#include -+#include -+ -+static __initdata efi_guid_t efi_cert_x509_guid = EFI_CERT_X509_GUID; + +/** + * parse_efi_signature_list - Parse an EFI signature list for certificates ++ * @source: The source of the key + * @data: The data blob to parse + * @size: The size of the data blob -+ * @keyring: The keyring to add extracted keys to ++ * @get_handler_for_guid: Get the handler func for the sig type (or NULL) ++ * ++ * Parse an EFI signature list looking for elements of interest. A list is ++ * made up of a series of sublists, where all the elements in a sublist are of ++ * the same type, but sublists can be of different types. ++ * ++ * For each sublist encountered, the @get_handler_for_guid function is called ++ * with the type specifier GUID and returns either a pointer to a function to ++ * handle elements of that type or NULL if the type is not of interest. ++ * ++ * If the sublist is of interest, each element is passed to the handler ++ * function in turn. ++ * ++ * Error EBADMSG is returned if the list doesn't parse correctly and 0 is ++ * returned if the list was parsed correctly. No error can be returned from ++ * the @get_handler_for_guid function or the element handler function it ++ * returns. + */ -+int __init parse_efi_signature_list(const void *data, size_t size, struct key *keyring) ++int __init parse_efi_signature_list( ++ const char *source, ++ const void *data, size_t size, ++ efi_element_handler_t (*get_handler_for_guid)(const efi_guid_t *)) +{ ++ efi_element_handler_t handler; + unsigned offs = 0; -+ size_t lsize, esize, hsize, elsize; + + pr_devel("-->%s(,%zu)\n", __func__, size); + + while (size > 0) { -+ efi_signature_list_t list; + const efi_signature_data_t *elem; -+ key_ref_t key; ++ efi_signature_list_t list; ++ size_t lsize, esize, hsize, elsize; + + if (size < sizeof(list)) + return -EBADMSG; @@ -108,6 +134,7 @@ index 000000000000..636feb18b733 + __func__, offs); + return -EBADMSG; + } ++ + if (lsize < sizeof(list) || + lsize - sizeof(list) < hsize || + esize < sizeof(*elem) || @@ -117,7 +144,8 @@ index 000000000000..636feb18b733 + return -EBADMSG; + } + -+ if (efi_guidcmp(list.signature_type, efi_cert_x509_guid) != 0) { ++ handler = get_handler_for_guid(&list.signature_type); ++ if (!handler) { + data += lsize; + size -= lsize; + offs += lsize; @@ -132,24 +160,9 @@ index 000000000000..636feb18b733 + elem = data; + + pr_devel("ELEM[%04x]\n", offs); -+ -+ key = key_create_or_update( -+ make_key_ref(keyring, 1), -+ "asymmetric", -+ NULL, ++ handler(source, + &elem->signature_data, -+ esize - sizeof(*elem), -+ (KEY_POS_ALL & ~KEY_POS_SETATTR) | -+ KEY_USR_VIEW, -+ KEY_ALLOC_NOT_IN_QUOTA); -+ -+ if (IS_ERR(key)) -+ pr_err("Problem loading in-kernel X.509 certificate (%ld)\n", -+ PTR_ERR(key)); -+ else -+ pr_notice("Loaded cert '%s' linked to '%s'\n", -+ key_ref_to_ptr(key)->description, -+ keyring->description); ++ esize - sizeof(*elem)); + + data += esize; + size -= esize; @@ -160,20 +173,25 @@ index 000000000000..636feb18b733 + return 0; +} diff --git a/include/linux/efi.h b/include/linux/efi.h -index 8c274b4ea8e6..ff1877145aa4 100644 +index 3259ad6..08024c6 100644 --- a/include/linux/efi.h +++ b/include/linux/efi.h -@@ -1044,6 +1044,10 @@ extern int efi_memattr_apply_permissions(struct mm_struct *mm, +@@ -1055,6 +1055,15 @@ extern int efi_memattr_apply_permissions(struct mm_struct *mm, char * __init efi_md_typeattr_format(char *buf, size_t size, const efi_memory_desc_t *md); - -+struct key; -+extern int __init parse_efi_signature_list(const void *data, size_t size, -+ struct key *keyring); + ++ ++typedef void (*efi_element_handler_t)(const char *source, ++ const void *element_data, ++ size_t element_size); ++extern int __init parse_efi_signature_list( ++ const char *source, ++ const void *data, size_t size, ++ efi_element_handler_t (*get_handler_for_guid)(const efi_guid_t *)); + /** * efi_range_is_wc - check the WC bit on an address range * @start: starting kvirt address -- -2.5.5 +2.9.3 diff --git a/Add-option-to-automatically-enforce-module-signature.patch b/Add-option-to-automatically-enforce-module-signature.patch deleted file mode 100644 index aa1983377..000000000 --- a/Add-option-to-automatically-enforce-module-signature.patch +++ /dev/null @@ -1,217 +0,0 @@ -From 0000dc9edd5997cc49b8893a9d5407f89dfa1307 Mon Sep 17 00:00:00 2001 -From: Matthew Garrett -Date: Fri, 9 Aug 2013 18:36:30 -0400 -Subject: [PATCH] Add option to automatically enforce module signatures when in - Secure Boot mode - -UEFI Secure Boot provides a mechanism for ensuring that the firmware will -only load signed bootloaders and kernels. Certain use cases may also -require that all kernel modules also be signed. Add a configuration option -that enforces this automatically when enabled. - -Signed-off-by: Matthew Garrett ---- - Documentation/x86/zero-page.txt | 2 ++ - arch/x86/Kconfig | 11 ++++++ - arch/x86/boot/compressed/eboot.c | 66 +++++++++++++++++++++++++++++++++++ - arch/x86/include/uapi/asm/bootparam.h | 3 +- - arch/x86/kernel/setup.c | 6 ++++ - include/linux/module.h | 6 ++++ - kernel/module.c | 7 ++++ - 7 files changed, 100 insertions(+), 1 deletion(-) - -diff --git a/Documentation/x86/zero-page.txt b/Documentation/x86/zero-page.txt -index 95a4d34af3fd..b8527c6b7646 100644 ---- a/Documentation/x86/zero-page.txt -+++ b/Documentation/x86/zero-page.txt -@@ -31,6 +31,8 @@ Offset Proto Name Meaning - 1E9/001 ALL eddbuf_entries Number of entries in eddbuf (below) - 1EA/001 ALL edd_mbr_sig_buf_entries Number of entries in edd_mbr_sig_buffer - (below) -+1EB/001 ALL kbd_status Numlock is enabled -+1EC/001 ALL secure_boot Secure boot is enabled in the firmware - 1EF/001 ALL sentinel Used to detect broken bootloaders - 290/040 ALL edd_mbr_sig_buffer EDD MBR signatures - 2D0/A00 ALL e820_map E820 memory map table -diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig -index 0a7b885964ba..29b8ba9ae713 100644 ---- a/arch/x86/Kconfig -+++ b/arch/x86/Kconfig -@@ -1776,6 +1776,17 @@ config EFI_MIXED - - If unsure, say N. - -+config EFI_SECURE_BOOT_SIG_ENFORCE -+ def_bool n -+ depends on EFI -+ prompt "Force module signing when UEFI Secure Boot is enabled" -+ ---help--- -+ UEFI Secure Boot provides a mechanism for ensuring that the -+ firmware will only load signed bootloaders and kernels. Certain -+ use cases may also require that all kernel modules also be signed. -+ Say Y here to automatically enable module signature enforcement -+ when a system boots with UEFI Secure Boot enabled. -+ - config SECCOMP - def_bool y - prompt "Enable seccomp to safely compute untrusted bytecode" -diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c -index 52fef606bc54..6b8b9a775b46 100644 ---- a/arch/x86/boot/compressed/eboot.c -+++ b/arch/x86/boot/compressed/eboot.c -@@ -12,6 +12,7 @@ - #include - #include - #include -+#include - - #include "../string.h" - #include "eboot.h" -@@ -571,6 +572,67 @@ free_handle: - efi_call_early(free_pool, pci_handle); - } - -+static int get_secure_boot(void) -+{ -+ u8 sb, setup; -+ unsigned long datasize = sizeof(sb); -+ efi_guid_t var_guid = EFI_GLOBAL_VARIABLE_GUID; -+ efi_status_t status; -+ -+ status = efi_early->call((unsigned long)sys_table->runtime->get_variable, -+ L"SecureBoot", &var_guid, NULL, &datasize, &sb); -+ -+ if (status != EFI_SUCCESS) -+ return 0; -+ -+ if (sb == 0) -+ return 0; -+ -+ -+ status = efi_early->call((unsigned long)sys_table->runtime->get_variable, -+ L"SetupMode", &var_guid, NULL, &datasize, -+ &setup); -+ -+ if (status != EFI_SUCCESS) -+ return 0; -+ -+ if (setup == 1) -+ return 0; -+ -+ return 1; -+} -+ -+ -+/* -+ * See if we have Graphics Output Protocol -+ */ -+static efi_status_t setup_gop(struct screen_info *si, efi_guid_t *proto, -+ unsigned long size) -+{ -+ efi_status_t status; -+ void **gop_handle = NULL; -+ -+ status = efi_call_early(allocate_pool, EFI_LOADER_DATA, -+ size, (void **)&gop_handle); -+ if (status != EFI_SUCCESS) -+ return status; -+ -+ status = efi_call_early(locate_handle, -+ EFI_LOCATE_BY_PROTOCOL, -+ proto, NULL, &size, gop_handle); -+ if (status != EFI_SUCCESS) -+ goto free_handle; -+ -+ if (efi_early->is64) -+ status = setup_gop64(si, proto, size, gop_handle); -+ else -+ status = setup_gop32(si, proto, size, gop_handle); -+ -+free_handle: -+ efi_call_early(free_pool, gop_handle); -+ return status; -+} -+ - static efi_status_t - setup_uga32(void **uga_handle, unsigned long size, u32 *width, u32 *height) - { -@@ -1126,6 +1188,10 @@ struct boot_params *efi_main(struct efi_config *c, - else - setup_boot_services32(efi_early); - -+ sanitize_boot_params(boot_params); -+ -+ boot_params->secure_boot = get_secure_boot(); -+ - setup_graphics(boot_params); - - setup_efi_pci(boot_params); -diff --git a/arch/x86/include/uapi/asm/bootparam.h b/arch/x86/include/uapi/asm/bootparam.h -index c18ce67495fa..2b3e5427097b 100644 ---- a/arch/x86/include/uapi/asm/bootparam.h -+++ b/arch/x86/include/uapi/asm/bootparam.h -@@ -134,7 +134,8 @@ struct boot_params { - __u8 eddbuf_entries; /* 0x1e9 */ - __u8 edd_mbr_sig_buf_entries; /* 0x1ea */ - __u8 kbd_status; /* 0x1eb */ -- __u8 _pad5[3]; /* 0x1ec */ -+ __u8 secure_boot; /* 0x1ec */ -+ __u8 _pad5[2]; /* 0x1ed */ - /* - * The sentinel is set to a nonzero value (0xff) in header.S. - * -diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c -index c4e7b3991b60..bdb9881c7afd 100644 ---- a/arch/x86/kernel/setup.c -+++ b/arch/x86/kernel/setup.c -@@ -1152,6 +1152,12 @@ void __init setup_arch(char **cmdline_p) - - io_delay_init(); - -+#ifdef CONFIG_EFI_SECURE_BOOT_SIG_ENFORCE -+ if (boot_params.secure_boot) { -+ enforce_signed_modules(); -+ } -+#endif -+ - /* - * Parse the ACPI tables for possible boot-time SMP configuration. - */ -diff --git a/include/linux/module.h b/include/linux/module.h -index 082298a09df1..38d0597f7615 100644 ---- a/include/linux/module.h -+++ b/include/linux/module.h -@@ -273,6 +273,12 @@ const struct exception_table_entry *search_exception_tables(unsigned long add); - - struct notifier_block; - -+#ifdef CONFIG_MODULE_SIG -+extern void enforce_signed_modules(void); -+#else -+static inline void enforce_signed_modules(void) {}; -+#endif -+ - #ifdef CONFIG_MODULES - - extern int modules_disabled; /* for sysctl */ -diff --git a/kernel/module.c b/kernel/module.c -index 3c384968f553..ea484f3a35b2 100644 ---- a/kernel/module.c -+++ b/kernel/module.c -@@ -4200,6 +4200,13 @@ void module_layout(struct module *mod, - EXPORT_SYMBOL(module_layout); - #endif - -+#ifdef CONFIG_MODULE_SIG -+void enforce_signed_modules(void) -+{ -+ sig_enforce = true; -+} -+#endif -+ - bool secure_modules(void) - { - #ifdef CONFIG_MODULE_SIG --- -2.5.5 - diff --git a/Add-secure_modules-call.patch b/Add-secure_modules-call.patch deleted file mode 100644 index 1cbf3afd9..000000000 --- a/Add-secure_modules-call.patch +++ /dev/null @@ -1,63 +0,0 @@ -From 3213f1513a744fb21b6b9e4d4f2650a204855b3e Mon Sep 17 00:00:00 2001 -From: Matthew Garrett -Date: Fri, 9 Aug 2013 17:58:15 -0400 -Subject: [PATCH] Add secure_modules() call - -Provide a single call to allow kernel code to determine whether the system -has been configured to either disable module loading entirely or to load -only modules signed with a trusted key. - -Bugzilla: N/A -Upstream-status: Fedora mustard. Replaced by securelevels, but that was nak'd - -Signed-off-by: Matthew Garrett ---- - include/linux/module.h | 6 ++++++ - kernel/module.c | 10 ++++++++++ - 2 files changed, 16 insertions(+) - -diff --git a/include/linux/module.h b/include/linux/module.h -index 0c3207d..05bd6c9 100644 ---- a/include/linux/module.h -+++ b/include/linux/module.h -@@ -641,6 +641,8 @@ static inline bool is_livepatch_module(struct module *mod) - } - #endif /* CONFIG_LIVEPATCH */ - -+extern bool secure_modules(void); -+ - #else /* !CONFIG_MODULES... */ - - static inline struct module *__module_address(unsigned long addr) -@@ -750,6 +752,10 @@ static inline bool module_requested_async_probing(struct module *module) - return false; - } - -+static inline bool secure_modules(void) -+{ -+ return false; -+} - #endif /* CONFIG_MODULES */ - - #ifdef CONFIG_SYSFS -diff --git a/kernel/module.c b/kernel/module.c -index 529efae..0332fdd 100644 ---- a/kernel/module.c -+++ b/kernel/module.c -@@ -4279,3 +4279,13 @@ void module_layout(struct module *mod, - } - EXPORT_SYMBOL(module_layout); - #endif -+ -+bool secure_modules(void) -+{ -+#ifdef CONFIG_MODULE_SIG -+ return (sig_enforce || modules_disabled); -+#else -+ return modules_disabled; -+#endif -+} -+EXPORT_SYMBOL(secure_modules); --- -2.9.2 - diff --git a/Add-sysrq-option-to-disable-secure-boot-mode.patch b/Add-sysrq-option-to-disable-secure-boot-mode.patch deleted file mode 100644 index 3cecd1399..000000000 --- a/Add-sysrq-option-to-disable-secure-boot-mode.patch +++ /dev/null @@ -1,246 +0,0 @@ -From e27a9a98dcf3ff95568593026da065a72ad21b92 Mon Sep 17 00:00:00 2001 -From: Kyle McMartin -Date: Fri, 30 Aug 2013 09:28:51 -0400 -Subject: [PATCH 9/9] Add sysrq option to disable secure boot mode - -Bugzilla: N/A -Upstream-status: Fedora mustard ---- - arch/x86/kernel/setup.c | 36 ++++++++++++++++++++++++++++++++++++ - drivers/input/misc/uinput.c | 1 + - drivers/tty/sysrq.c | 19 +++++++++++++------ - include/linux/input.h | 5 +++++ - include/linux/sysrq.h | 8 +++++++- - kernel/debug/kdb/kdb_main.c | 2 +- - kernel/module.c | 2 +- - 7 files changed, 64 insertions(+), 9 deletions(-) - -diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c -index a666b6c29c77..7732c769937b 100644 ---- a/arch/x86/kernel/setup.c -+++ b/arch/x86/kernel/setup.c -@@ -70,6 +70,11 @@ - #include - #include - -+#include -+#include -+#include -+#include -+ - #include