Commit 85736168 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull char/misc driver fixes from Greg KH:
 "Here are some small char and misc driver fixes for 5.15-rc3.

  Nothing huge in here, just fixes for a number of small issues that
  have been reported. These include:

   - habanalabs race conditions and other bugs fixed

   - binder driver fixes

   - fpga driver fixes

   - coresight build warning fix

   - nvmem driver fix

   - comedi memory leak fix

   - bcm-vk tty race fix

   - other tiny driver fixes

  All of these have been in linux-next for a while with no reported
  issues"

* tag 'char-misc-5.15-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc: (21 commits)
  comedi: Fix memory leak in compat_insnlist()
  nvmem: NVMEM_NINTENDO_OTP should depend on WII
  misc: bcm-vk: fix tty registration race
  fpga: dfl: Avoid reads to AFU CSRs during enumeration
  fpga: machxo2-spi: Fix missing error code in machxo2_write_complete()
  fpga: machxo2-spi: Return an error on failure
  habanalabs: expose a single cs seq in staged submissions
  habanalabs: fix wait offset handling
  habanalabs: rate limit multi CS completion errors
  habanalabs/gaudi: fix LBW RR configuration
  habanalabs: Fix spelling mistake "FEADBACK" -> "FEEDBACK"
  habanalabs: fail collective wait when not supported
  habanalabs/gaudi: use direct MSI in single mode
  habanalabs: fix kernel OOPs related to staged cs
  habanalabs: fix potential race in interrupt wait ioctl
  mcb: fix error handling in mcb_alloc_bus()
  misc: genwqe: Fixes DMA mask setting
  coresight: syscfg: Fix compiler warning
  nvmem: core: Add stubs for nvmem_cell_read_variable_le_u32/64 if !CONFIG_NVMEM
  binder: make sure fd closes complete
  ...
parents 9cbef308 bb509a6f
Loading
Loading
Loading
Loading
+46 −12
Original line number Diff line number Diff line
@@ -1852,6 +1852,7 @@ static void binder_deferred_fd_close(int fd)
}

static void binder_transaction_buffer_release(struct binder_proc *proc,
					      struct binder_thread *thread,
					      struct binder_buffer *buffer,
					      binder_size_t failed_at,
					      bool is_failure)
@@ -2011,8 +2012,16 @@ static void binder_transaction_buffer_release(struct binder_proc *proc,
						&proc->alloc, &fd, buffer,
						offset, sizeof(fd));
				WARN_ON(err);
				if (!err)
				if (!err) {
					binder_deferred_fd_close(fd);
					/*
					 * Need to make sure the thread goes
					 * back to userspace to complete the
					 * deferred close
					 */
					if (thread)
						thread->looper_need_return = true;
				}
			}
		} break;
		default:
@@ -3038,9 +3047,8 @@ static void binder_transaction(struct binder_proc *proc,
	if (reply) {
		binder_enqueue_thread_work(thread, tcomplete);
		binder_inner_proc_lock(target_proc);
		if (target_thread->is_dead || target_proc->is_frozen) {
			return_error = target_thread->is_dead ?
				BR_DEAD_REPLY : BR_FROZEN_REPLY;
		if (target_thread->is_dead) {
			return_error = BR_DEAD_REPLY;
			binder_inner_proc_unlock(target_proc);
			goto err_dead_proc_or_thread;
		}
@@ -3105,7 +3113,7 @@ static void binder_transaction(struct binder_proc *proc,
err_copy_data_failed:
	binder_free_txn_fixups(t);
	trace_binder_transaction_failed_buffer_release(t->buffer);
	binder_transaction_buffer_release(target_proc, t->buffer,
	binder_transaction_buffer_release(target_proc, NULL, t->buffer,
					  buffer_offset, true);
	if (target_node)
		binder_dec_node_tmpref(target_node);
@@ -3184,7 +3192,9 @@ static void binder_transaction(struct binder_proc *proc,
 * Cleanup buffer and free it.
 */
static void
binder_free_buf(struct binder_proc *proc, struct binder_buffer *buffer)
binder_free_buf(struct binder_proc *proc,
		struct binder_thread *thread,
		struct binder_buffer *buffer)
{
	binder_inner_proc_lock(proc);
	if (buffer->transaction) {
@@ -3212,7 +3222,7 @@ binder_free_buf(struct binder_proc *proc, struct binder_buffer *buffer)
		binder_node_inner_unlock(buf_node);
	}
	trace_binder_transaction_buffer_release(buffer);
	binder_transaction_buffer_release(proc, buffer, 0, false);
	binder_transaction_buffer_release(proc, thread, buffer, 0, false);
	binder_alloc_free_buf(&proc->alloc, buffer);
}

@@ -3414,7 +3424,7 @@ static int binder_thread_write(struct binder_proc *proc,
				     proc->pid, thread->pid, (u64)data_ptr,
				     buffer->debug_id,
				     buffer->transaction ? "active" : "finished");
			binder_free_buf(proc, buffer);
			binder_free_buf(proc, thread, buffer);
			break;
		}

@@ -4107,7 +4117,7 @@ static int binder_thread_read(struct binder_proc *proc,
			buffer->transaction = NULL;
			binder_cleanup_transaction(t, "fd fixups failed",
						   BR_FAILED_REPLY);
			binder_free_buf(proc, buffer);
			binder_free_buf(proc, thread, buffer);
			binder_debug(BINDER_DEBUG_FAILED_TRANSACTION,
				     "%d:%d %stransaction %d fd fixups failed %d/%d, line %d\n",
				     proc->pid, thread->pid,
@@ -4648,6 +4658,22 @@ static int binder_ioctl_get_node_debug_info(struct binder_proc *proc,
	return 0;
}

static bool binder_txns_pending_ilocked(struct binder_proc *proc)
{
	struct rb_node *n;
	struct binder_thread *thread;

	if (proc->outstanding_txns > 0)
		return true;

	for (n = rb_first(&proc->threads); n; n = rb_next(n)) {
		thread = rb_entry(n, struct binder_thread, rb_node);
		if (thread->transaction_stack)
			return true;
	}
	return false;
}

static int binder_ioctl_freeze(struct binder_freeze_info *info,
			       struct binder_proc *target_proc)
{
@@ -4679,8 +4705,13 @@ static int binder_ioctl_freeze(struct binder_freeze_info *info,
			(!target_proc->outstanding_txns),
			msecs_to_jiffies(info->timeout_ms));

	if (!ret && target_proc->outstanding_txns)
	/* Check pending transactions that wait for reply */
	if (ret >= 0) {
		binder_inner_proc_lock(target_proc);
		if (binder_txns_pending_ilocked(target_proc))
			ret = -EAGAIN;
		binder_inner_proc_unlock(target_proc);
	}

	if (ret < 0) {
		binder_inner_proc_lock(target_proc);
@@ -4696,6 +4727,7 @@ static int binder_ioctl_get_freezer_info(
{
	struct binder_proc *target_proc;
	bool found = false;
	__u32 txns_pending;

	info->sync_recv = 0;
	info->async_recv = 0;
@@ -4705,7 +4737,9 @@ static int binder_ioctl_get_freezer_info(
		if (target_proc->pid == info->pid) {
			found = true;
			binder_inner_proc_lock(target_proc);
			info->sync_recv |= target_proc->sync_recv;
			txns_pending = binder_txns_pending_ilocked(target_proc);
			info->sync_recv |= target_proc->sync_recv |
					(txns_pending << 1);
			info->async_recv |= target_proc->async_recv;
			binder_inner_proc_unlock(target_proc);
		}
+2 −0
Original line number Diff line number Diff line
@@ -378,6 +378,8 @@ struct binder_ref {
 *                        binder transactions
 *                        (protected by @inner_lock)
 * @sync_recv:            process received sync transactions since last frozen
 *                        bit 0: received sync transaction after being frozen
 *                        bit 1: new pending sync transaction during freezing
 *                        (protected by @inner_lock)
 * @async_recv:           process received async transactions since last frozen
 *                        (protected by @inner_lock)
+1 −0
Original line number Diff line number Diff line
@@ -3090,6 +3090,7 @@ static int compat_insnlist(struct file *file, unsigned long arg)
	mutex_lock(&dev->mutex);
	rc = do_insnlist_ioctl(dev, insns, insnlist32.n_insns, file);
	mutex_unlock(&dev->mutex);
	kfree(insns);
	return rc;
}

+8 −6
Original line number Diff line number Diff line
@@ -1019,16 +1019,18 @@ create_feature_instance(struct build_feature_devs_info *binfo,
{
	unsigned int irq_base, nr_irqs;
	struct dfl_feature_info *finfo;
	u8 revision = 0;
	int ret;
	u8 revision;
	u64 v;

	if (fid != FEATURE_ID_AFU) {
		v = readq(binfo->ioaddr + ofst);
		revision = FIELD_GET(DFH_REVISION, v);

		/* read feature size and id if inputs are invalid */
		size = size ? size : feature_size(v);
		fid = fid ? fid : feature_id(v);
	}

	if (binfo->len - ofst < size)
		return -EINVAL;
+5 −1
Original line number Diff line number Diff line
@@ -225,8 +225,10 @@ static int machxo2_write_init(struct fpga_manager *mgr,
		goto fail;

	get_status(spi, &status);
	if (test_bit(FAIL, &status))
	if (test_bit(FAIL, &status)) {
		ret = -EINVAL;
		goto fail;
	}
	dump_status_reg(&status);

	spi_message_init(&msg);
@@ -313,6 +315,7 @@ static int machxo2_write_complete(struct fpga_manager *mgr,
	dump_status_reg(&status);
	if (!test_bit(DONE, &status)) {
		machxo2_cleanup(mgr);
		ret = -EINVAL;
		goto fail;
	}

@@ -335,6 +338,7 @@ static int machxo2_write_complete(struct fpga_manager *mgr,
			break;
		if (++refreshloop == MACHXO2_MAX_REFRESH_LOOP) {
			machxo2_cleanup(mgr);
			ret = -EINVAL;
			goto fail;
		}
	} while (1);
Loading