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

Commit 412e6d3f authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull char/misc driver fixes from Greg KH:
 "Here are two bugfixes that resolve some reported issues. One in the
  firmware loader, that should fix the much-reported problem of crashes
  with it. The other is a hyperv fix for a reported regression.

  Both have been in linux-next for a week or so with no reported issues"

* tag 'char-misc-4.10-rc7' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc:
  Drivers: hv: vmbus: finally fix hv_need_to_signal_on_read()
  firmware: fix NULL pointer dereference in __fw_load_abort()
parents 252bf9f4 433e19cf
Loading
Loading
Loading
Loading
+1 −4
Original line number Diff line number Diff line
@@ -558,9 +558,6 @@ static void fw_load_abort(struct firmware_priv *fw_priv)
	struct firmware_buf *buf = fw_priv->buf;

	__fw_load_abort(buf);

	/* avoid user action after loading abort */
	fw_priv->buf = NULL;
}

static LIST_HEAD(pending_fw_head);
@@ -713,7 +710,7 @@ static ssize_t firmware_loading_store(struct device *dev,

	mutex_lock(&fw_lock);
	fw_buf = fw_priv->buf;
	if (!fw_buf)
	if (fw_state_is_aborted(&fw_buf->fw_st))
		goto out;

	switch (loading) {
+1 −0
Original line number Diff line number Diff line
@@ -383,6 +383,7 @@ int hv_ringbuffer_read(struct vmbus_channel *channel,
		return ret;
	}

	init_cached_read_index(channel);
	next_read_location = hv_get_next_read_location(inring_info);
	next_read_location = hv_copyfrom_ringbuffer(inring_info, &desc,
						    sizeof(desc),
+6 −0
Original line number Diff line number Diff line
@@ -1295,6 +1295,9 @@ void netvsc_channel_cb(void *context)
	ndev = hv_get_drvdata(device);
	buffer = get_per_channel_state(channel);

	/* commit_rd_index() -> hv_signal_on_read() needs this. */
	init_cached_read_index(channel);

	do {
		desc = get_next_pkt_raw(channel);
		if (desc != NULL) {
@@ -1347,6 +1350,9 @@ void netvsc_channel_cb(void *context)

			bufferlen = bytes_recvd;
		}

		init_cached_read_index(channel);

	} while (1);

	if (bufferlen > NETVSC_PACKET_SIZE)
+30 −2
Original line number Diff line number Diff line
@@ -128,6 +128,7 @@ struct hv_ring_buffer_info {
	u32 ring_data_startoffset;
	u32 priv_write_index;
	u32 priv_read_index;
	u32 cached_read_index;
};

/*
@@ -180,6 +181,19 @@ static inline u32 hv_get_bytes_to_write(struct hv_ring_buffer_info *rbi)
	return write;
}

static inline u32 hv_get_cached_bytes_to_write(
	const struct hv_ring_buffer_info *rbi)
{
	u32 read_loc, write_loc, dsize, write;

	dsize = rbi->ring_datasize;
	read_loc = rbi->cached_read_index;
	write_loc = rbi->ring_buffer->write_index;

	write = write_loc >= read_loc ? dsize - (write_loc - read_loc) :
		read_loc - write_loc;
	return write;
}
/*
 * VMBUS version is 32 bit entity broken up into
 * two 16 bit quantities: major_number. minor_number.
@@ -1488,7 +1502,7 @@ hv_get_ring_buffer(struct hv_ring_buffer_info *ring_info)

static inline  void hv_signal_on_read(struct vmbus_channel *channel)
{
	u32 cur_write_sz;
	u32 cur_write_sz, cached_write_sz;
	u32 pending_sz;
	struct hv_ring_buffer_info *rbi = &channel->inbound;

@@ -1512,12 +1526,24 @@ static inline void hv_signal_on_read(struct vmbus_channel *channel)

	cur_write_sz = hv_get_bytes_to_write(rbi);

	if (cur_write_sz >= pending_sz)
	if (cur_write_sz < pending_sz)
		return;

	cached_write_sz = hv_get_cached_bytes_to_write(rbi);
	if (cached_write_sz < pending_sz)
		vmbus_setevent(channel);

	return;
}

static inline void
init_cached_read_index(struct vmbus_channel *channel)
{
	struct hv_ring_buffer_info *rbi = &channel->inbound;

	rbi->cached_read_index = rbi->ring_buffer->read_index;
}

/*
 * An API to support in-place processing of incoming VMBUS packets.
 */
@@ -1569,6 +1595,8 @@ static inline void put_pkt_raw(struct vmbus_channel *channel,
 * This call commits the read index and potentially signals the host.
 * Here is the pattern for using the "in-place" consumption APIs:
 *
 * init_cached_read_index();
 *
 * while (get_next_pkt_raw() {
 *	process the packet "in-place";
 *	put_pkt_raw();