Commit bb17186a authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'char-misc-4.16-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc

Pull char/misc driver fixes from Greg KH:
 "Here are a handful of char/misc driver fixes for 4.16-rc3.

  There are some binder driver fixes to resolve reported issues in
  stress testing the recent binder changes, some extcon driver fixes,
  and a few mei driver fixes and new device ids.

  All of these, with the exception of the mei driver id additions, have
  been in linux-next for a while. I forgot to push out the mei driver id
  additions to kernel.org until today, but all build tests pass with
  them enabled"

* tag 'char-misc-4.16-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc:
  mei: me: add cannon point device ids for 4th device
  mei: me: add cannon point device ids
  mei: set device client to the disconnected state upon suspend.
  ANDROID: binder: synchronize_rcu() when using POLLFREE.
  binder: replace "%p" with "%pK"
  ANDROID: binder: remove WARN() for redundant txn error
  binder: check for binder_thread allocation failure in binder_poll()
  extcon: int3496: process id-pin first so that we start with the right status
  Revert "extcon: axp288: Redo charger type detection a couple of seconds after probe()"
  extcon: axp288: Constify the axp288_pwr_up_down_info array
parents 004e390d 2a4ac172
...@@ -1991,8 +1991,14 @@ static void binder_send_failed_reply(struct binder_transaction *t, ...@@ -1991,8 +1991,14 @@ static void binder_send_failed_reply(struct binder_transaction *t,
&target_thread->reply_error.work); &target_thread->reply_error.work);
wake_up_interruptible(&target_thread->wait); wake_up_interruptible(&target_thread->wait);
} else { } else {
WARN(1, "Unexpected reply error: %u\n", /*
target_thread->reply_error.cmd); * Cannot get here for normal operation, but
* we can if multiple synchronous transactions
* are sent without blocking for responses.
* Just ignore the 2nd error in this case.
*/
pr_warn("Unexpected reply error: %u\n",
target_thread->reply_error.cmd);
} }
binder_inner_proc_unlock(target_thread->proc); binder_inner_proc_unlock(target_thread->proc);
binder_thread_dec_tmpref(target_thread); binder_thread_dec_tmpref(target_thread);
...@@ -2193,7 +2199,7 @@ static void binder_transaction_buffer_release(struct binder_proc *proc, ...@@ -2193,7 +2199,7 @@ static void binder_transaction_buffer_release(struct binder_proc *proc,
int debug_id = buffer->debug_id; int debug_id = buffer->debug_id;
binder_debug(BINDER_DEBUG_TRANSACTION, binder_debug(BINDER_DEBUG_TRANSACTION,
"%d buffer release %d, size %zd-%zd, failed at %p\n", "%d buffer release %d, size %zd-%zd, failed at %pK\n",
proc->pid, buffer->debug_id, proc->pid, buffer->debug_id,
buffer->data_size, buffer->offsets_size, failed_at); buffer->data_size, buffer->offsets_size, failed_at);
...@@ -3705,7 +3711,7 @@ static int binder_thread_write(struct binder_proc *proc, ...@@ -3705,7 +3711,7 @@ static int binder_thread_write(struct binder_proc *proc,
} }
} }
binder_debug(BINDER_DEBUG_DEAD_BINDER, binder_debug(BINDER_DEBUG_DEAD_BINDER,
"%d:%d BC_DEAD_BINDER_DONE %016llx found %p\n", "%d:%d BC_DEAD_BINDER_DONE %016llx found %pK\n",
proc->pid, thread->pid, (u64)cookie, proc->pid, thread->pid, (u64)cookie,
death); death);
if (death == NULL) { if (death == NULL) {
...@@ -4376,6 +4382,15 @@ static int binder_thread_release(struct binder_proc *proc, ...@@ -4376,6 +4382,15 @@ static int binder_thread_release(struct binder_proc *proc,
binder_inner_proc_unlock(thread->proc); binder_inner_proc_unlock(thread->proc);
/*
* This is needed to avoid races between wake_up_poll() above and
* and ep_remove_waitqueue() called for other reasons (eg the epoll file
* descriptor being closed); ep_remove_waitqueue() holds an RCU read
* lock, so we can be sure it's done after calling synchronize_rcu().
*/
if (thread->looper & BINDER_LOOPER_STATE_POLL)
synchronize_rcu();
if (send_reply) if (send_reply)
binder_send_failed_reply(send_reply, BR_DEAD_REPLY); binder_send_failed_reply(send_reply, BR_DEAD_REPLY);
binder_release_work(proc, &thread->todo); binder_release_work(proc, &thread->todo);
...@@ -4391,6 +4406,8 @@ static __poll_t binder_poll(struct file *filp, ...@@ -4391,6 +4406,8 @@ static __poll_t binder_poll(struct file *filp,
bool wait_for_proc_work; bool wait_for_proc_work;
thread = binder_get_thread(proc); thread = binder_get_thread(proc);
if (!thread)
return POLLERR;
binder_inner_proc_lock(thread->proc); binder_inner_proc_lock(thread->proc);
thread->looper |= BINDER_LOOPER_STATE_POLL; thread->looper |= BINDER_LOOPER_STATE_POLL;
...@@ -5034,7 +5051,7 @@ static void print_binder_transaction_ilocked(struct seq_file *m, ...@@ -5034,7 +5051,7 @@ static void print_binder_transaction_ilocked(struct seq_file *m,
spin_lock(&t->lock); spin_lock(&t->lock);
to_proc = t->to_proc; to_proc = t->to_proc;
seq_printf(m, seq_printf(m,
"%s %d: %p from %d:%d to %d:%d code %x flags %x pri %ld r%d", "%s %d: %pK from %d:%d to %d:%d code %x flags %x pri %ld r%d",
prefix, t->debug_id, t, prefix, t->debug_id, t,
t->from ? t->from->proc->pid : 0, t->from ? t->from->proc->pid : 0,
t->from ? t->from->pid : 0, t->from ? t->from->pid : 0,
...@@ -5058,7 +5075,7 @@ static void print_binder_transaction_ilocked(struct seq_file *m, ...@@ -5058,7 +5075,7 @@ static void print_binder_transaction_ilocked(struct seq_file *m,
} }
if (buffer->target_node) if (buffer->target_node)
seq_printf(m, " node %d", buffer->target_node->debug_id); seq_printf(m, " node %d", buffer->target_node->debug_id);
seq_printf(m, " size %zd:%zd data %p\n", seq_printf(m, " size %zd:%zd data %pK\n",
buffer->data_size, buffer->offsets_size, buffer->data_size, buffer->offsets_size,
buffer->data); buffer->data);
} }
......
/* /*
* extcon-axp288.c - X-Power AXP288 PMIC extcon cable detection driver * extcon-axp288.c - X-Power AXP288 PMIC extcon cable detection driver
* *
* Copyright (C) 2016-2017 Hans de Goede <hdegoede@redhat.com>
* Copyright (C) 2015 Intel Corporation * Copyright (C) 2015 Intel Corporation
* Author: Ramakrishna Pallala <ramakrishna.pallala@intel.com> * Author: Ramakrishna Pallala <ramakrishna.pallala@intel.com>
* *
...@@ -98,15 +97,13 @@ struct axp288_extcon_info { ...@@ -98,15 +97,13 @@ struct axp288_extcon_info {
struct device *dev; struct device *dev;
struct regmap *regmap; struct regmap *regmap;
struct regmap_irq_chip_data *regmap_irqc; struct regmap_irq_chip_data *regmap_irqc;
struct delayed_work det_work;
int irq[EXTCON_IRQ_END]; int irq[EXTCON_IRQ_END];
struct extcon_dev *edev; struct extcon_dev *edev;
unsigned int previous_cable; unsigned int previous_cable;
bool first_detect_done;
}; };
/* Power up/down reason string array */ /* Power up/down reason string array */
static char *axp288_pwr_up_down_info[] = { static const char * const axp288_pwr_up_down_info[] = {
"Last wake caused by user pressing the power button", "Last wake caused by user pressing the power button",
"Last wake caused by a charger insertion", "Last wake caused by a charger insertion",
"Last wake caused by a battery insertion", "Last wake caused by a battery insertion",
...@@ -124,7 +121,7 @@ static char *axp288_pwr_up_down_info[] = { ...@@ -124,7 +121,7 @@ static char *axp288_pwr_up_down_info[] = {
*/ */
static void axp288_extcon_log_rsi(struct axp288_extcon_info *info) static void axp288_extcon_log_rsi(struct axp288_extcon_info *info)
{ {
char **rsi; const char * const *rsi;
unsigned int val, i, clear_mask = 0; unsigned int val, i, clear_mask = 0;
int ret; int ret;
...@@ -140,25 +137,6 @@ static void axp288_extcon_log_rsi(struct axp288_extcon_info *info) ...@@ -140,25 +137,6 @@ static void axp288_extcon_log_rsi(struct axp288_extcon_info *info)
regmap_write(info->regmap, AXP288_PS_BOOT_REASON_REG, clear_mask); regmap_write(info->regmap, AXP288_PS_BOOT_REASON_REG, clear_mask);
} }
static void axp288_chrg_detect_complete(struct axp288_extcon_info *info)
{
/*
* We depend on other drivers to do things like mux the data lines,
* enable/disable vbus based on the id-pin, etc. Sometimes the BIOS has
* not set these things up correctly resulting in the initial charger
* cable type detection giving a wrong result and we end up not charging
* or charging at only 0.5A.
*
* So we schedule a second cable type detection after 2 seconds to
* give the other drivers time to load and do their thing.
*/
if (!info->first_detect_done) {
queue_delayed_work(system_wq, &info->det_work,
msecs_to_jiffies(2000));
info->first_detect_done = true;
}
}
static int axp288_handle_chrg_det_event(struct axp288_extcon_info *info) static int axp288_handle_chrg_det_event(struct axp288_extcon_info *info)
{ {
int ret, stat, cfg, pwr_stat; int ret, stat, cfg, pwr_stat;
...@@ -223,8 +201,6 @@ static int axp288_handle_chrg_det_event(struct axp288_extcon_info *info) ...@@ -223,8 +201,6 @@ static int axp288_handle_chrg_det_event(struct axp288_extcon_info *info)
info->previous_cable = cable; info->previous_cable = cable;
} }
axp288_chrg_detect_complete(info);
return 0; return 0;
dev_det_ret: dev_det_ret:
...@@ -246,11 +222,8 @@ static irqreturn_t axp288_extcon_isr(int irq, void *data) ...@@ -246,11 +222,8 @@ static irqreturn_t axp288_extcon_isr(int irq, void *data)
return IRQ_HANDLED; return IRQ_HANDLED;
} }
static void axp288_extcon_det_work(struct work_struct *work) static void axp288_extcon_enable(struct axp288_extcon_info *info)
{ {
struct axp288_extcon_info *info =
container_of(work, struct axp288_extcon_info, det_work.work);
regmap_update_bits(info->regmap, AXP288_BC_GLOBAL_REG, regmap_update_bits(info->regmap, AXP288_BC_GLOBAL_REG,
BC_GLOBAL_RUN, 0); BC_GLOBAL_RUN, 0);
/* Enable the charger detection logic */ /* Enable the charger detection logic */
...@@ -272,7 +245,6 @@ static int axp288_extcon_probe(struct platform_device *pdev) ...@@ -272,7 +245,6 @@ static int axp288_extcon_probe(struct platform_device *pdev)
info->regmap = axp20x->regmap; info->regmap = axp20x->regmap;
info->regmap_irqc = axp20x->regmap_irqc; info->regmap_irqc = axp20x->regmap_irqc;
info->previous_cable = EXTCON_NONE; info->previous_cable = EXTCON_NONE;
INIT_DELAYED_WORK(&info->det_work, axp288_extcon_det_work);
platform_set_drvdata(pdev, info); platform_set_drvdata(pdev, info);
...@@ -318,7 +290,7 @@ static int axp288_extcon_probe(struct platform_device *pdev) ...@@ -318,7 +290,7 @@ static int axp288_extcon_probe(struct platform_device *pdev)
} }
/* Start charger cable type detection */ /* Start charger cable type detection */
queue_delayed_work(system_wq, &info->det_work, 0); axp288_extcon_enable(info);
return 0; return 0;
} }
......
...@@ -153,8 +153,9 @@ static int int3496_probe(struct platform_device *pdev) ...@@ -153,8 +153,9 @@ static int int3496_probe(struct platform_device *pdev)
return ret; return ret;
} }
/* queue initial processing of id-pin */ /* process id-pin so that we start with the right status */
queue_delayed_work(system_wq, &data->work, 0); queue_delayed_work(system_wq, &data->work, 0);
flush_delayed_work(&data->work);
platform_set_drvdata(pdev, data); platform_set_drvdata(pdev, data);
......
...@@ -548,12 +548,6 @@ int mei_cldev_disable(struct mei_cl_device *cldev) ...@@ -548,12 +548,6 @@ int mei_cldev_disable(struct mei_cl_device *cldev)
goto out; goto out;
} }
if (bus->dev_state == MEI_DEV_POWER_DOWN) {
dev_dbg(bus->dev, "Device is powering down, don't bother with disconnection\n");
err = 0;
goto out;
}
err = mei_cl_disconnect(cl); err = mei_cl_disconnect(cl);
if (err < 0) if (err < 0)
dev_err(bus->dev, "Could not disconnect from the ME client\n"); dev_err(bus->dev, "Could not disconnect from the ME client\n");
......
...@@ -945,6 +945,12 @@ int mei_cl_disconnect(struct mei_cl *cl) ...@@ -945,6 +945,12 @@ int mei_cl_disconnect(struct mei_cl *cl)
return 0; return 0;
} }
if (dev->dev_state == MEI_DEV_POWER_DOWN) {
cl_dbg(dev, cl, "Device is powering down, don't bother with disconnection\n");
mei_cl_set_disconnected(cl);
return 0;
}
rets = pm_runtime_get(dev->dev); rets = pm_runtime_get(dev->dev);
if (rets < 0 && rets != -EINPROGRESS) { if (rets < 0 && rets != -EINPROGRESS) {
pm_runtime_put_noidle(dev->dev); pm_runtime_put_noidle(dev->dev);
......
...@@ -132,6 +132,11 @@ ...@@ -132,6 +132,11 @@
#define MEI_DEV_ID_KBP 0xA2BA /* Kaby Point */ #define MEI_DEV_ID_KBP 0xA2BA /* Kaby Point */
#define MEI_DEV_ID_KBP_2 0xA2BB /* Kaby Point 2 */ #define MEI_DEV_ID_KBP_2 0xA2BB /* Kaby Point 2 */
#define MEI_DEV_ID_CNP_LP 0x9DE0 /* Cannon Point LP */
#define MEI_DEV_ID_CNP_LP_4 0x9DE4 /* Cannon Point LP 4 (iTouch) */
#define MEI_DEV_ID_CNP_H 0xA360 /* Cannon Point H */
#define MEI_DEV_ID_CNP_H_4 0xA364 /* Cannon Point H 4 (iTouch) */
/* /*
* MEI HW Section * MEI HW Section
*/ */
......
...@@ -98,6 +98,11 @@ static const struct pci_device_id mei_me_pci_tbl[] = { ...@@ -98,6 +98,11 @@ static const struct pci_device_id mei_me_pci_tbl[] = {
{MEI_PCI_DEVICE(MEI_DEV_ID_KBP, MEI_ME_PCH8_CFG)}, {MEI_PCI_DEVICE(MEI_DEV_ID_KBP, MEI_ME_PCH8_CFG)},
{MEI_PCI_DEVICE(MEI_DEV_ID_KBP_2, MEI_ME_PCH8_CFG)}, {MEI_PCI_DEVICE(MEI_DEV_ID_KBP_2, MEI_ME_PCH8_CFG)},
{MEI_PCI_DEVICE(MEI_DEV_ID_CNP_LP, MEI_ME_PCH8_CFG)},
{MEI_PCI_DEVICE(MEI_DEV_ID_CNP_LP_4, MEI_ME_PCH8_CFG)},
{MEI_PCI_DEVICE(MEI_DEV_ID_CNP_H, MEI_ME_PCH8_CFG)},
{MEI_PCI_DEVICE(MEI_DEV_ID_CNP_H_4, MEI_ME_PCH8_CFG)},
/* required last entry */ /* required last entry */
{0, } {0, }
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment