Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit bb17186a authored by Linus Torvalds's avatar Linus Torvalds
Browse files
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
Loading
Loading
Loading
Loading
+23 −6
Original line number Diff line number Diff line
@@ -1991,7 +1991,13 @@ static void binder_send_failed_reply(struct binder_transaction *t,
					&target_thread->reply_error.work);
				wake_up_interruptible(&target_thread->wait);
			} else {
				WARN(1, "Unexpected reply error: %u\n",
				/*
				 * 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);
@@ -2193,7 +2199,7 @@ static void binder_transaction_buffer_release(struct binder_proc *proc,
	int debug_id = buffer->debug_id;

	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,
		     buffer->data_size, buffer->offsets_size, failed_at);

@@ -3705,7 +3711,7 @@ static int binder_thread_write(struct binder_proc *proc,
				}
			}
			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,
				     death);
			if (death == NULL) {
@@ -4376,6 +4382,15 @@ static int binder_thread_release(struct binder_proc *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)
		binder_send_failed_reply(send_reply, BR_DEAD_REPLY);
	binder_release_work(proc, &thread->todo);
@@ -4391,6 +4406,8 @@ static __poll_t binder_poll(struct file *filp,
	bool wait_for_proc_work;

	thread = binder_get_thread(proc);
	if (!thread)
		return POLLERR;

	binder_inner_proc_lock(thread->proc);
	thread->looper |= BINDER_LOOPER_STATE_POLL;
@@ -5034,7 +5051,7 @@ static void print_binder_transaction_ilocked(struct seq_file *m,
	spin_lock(&t->lock);
	to_proc = t->to_proc;
	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,
		   t->from ? t->from->proc->pid : 0,
		   t->from ? t->from->pid : 0,
@@ -5058,7 +5075,7 @@ static void print_binder_transaction_ilocked(struct seq_file *m,
	}
	if (buffer->target_node)
		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);
}
+4 −32
Original line number Diff line number Diff line
/*
 * 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
 * Author: Ramakrishna Pallala <ramakrishna.pallala@intel.com>
 *
@@ -98,15 +97,13 @@ struct axp288_extcon_info {
	struct device *dev;
	struct regmap *regmap;
	struct regmap_irq_chip_data *regmap_irqc;
	struct delayed_work det_work;
	int irq[EXTCON_IRQ_END];
	struct extcon_dev *edev;
	unsigned int previous_cable;
	bool first_detect_done;
};

/* 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 a charger insertion",
	"Last wake caused by a battery insertion",
@@ -124,7 +121,7 @@ static char *axp288_pwr_up_down_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;
	int ret;

@@ -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);
}

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)
{
	int ret, stat, cfg, pwr_stat;
@@ -223,8 +201,6 @@ static int axp288_handle_chrg_det_event(struct axp288_extcon_info *info)
		info->previous_cable = cable;
	}

	axp288_chrg_detect_complete(info);

	return 0;

dev_det_ret:
@@ -246,11 +222,8 @@ static irqreturn_t axp288_extcon_isr(int irq, void *data)
	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,
						BC_GLOBAL_RUN, 0);
	/* Enable the charger detection logic */
@@ -272,7 +245,6 @@ static int axp288_extcon_probe(struct platform_device *pdev)
	info->regmap = axp20x->regmap;
	info->regmap_irqc = axp20x->regmap_irqc;
	info->previous_cable = EXTCON_NONE;
	INIT_DELAYED_WORK(&info->det_work, axp288_extcon_det_work);

	platform_set_drvdata(pdev, info);

@@ -318,7 +290,7 @@ static int axp288_extcon_probe(struct platform_device *pdev)
	}

	/* Start charger cable type detection */
	queue_delayed_work(system_wq, &info->det_work, 0);
	axp288_extcon_enable(info);

	return 0;
}
+2 −1
Original line number Diff line number Diff line
@@ -153,8 +153,9 @@ static int int3496_probe(struct platform_device *pdev)
		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);
	flush_delayed_work(&data->work);

	platform_set_drvdata(pdev, data);

+0 −6
Original line number Diff line number Diff line
@@ -548,12 +548,6 @@ int mei_cldev_disable(struct mei_cl_device *cldev)
		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);
	if (err < 0)
		dev_err(bus->dev, "Could not disconnect from the ME client\n");
+6 −0
Original line number Diff line number Diff line
@@ -945,6 +945,12 @@ int mei_cl_disconnect(struct mei_cl *cl)
		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);
	if (rets < 0 && rets != -EINPROGRESS) {
		pm_runtime_put_noidle(dev->dev);
Loading