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

Commit e0615925 authored by qctecmdr Service's avatar qctecmdr Service Committed by Gerrit - the friendly Code Review server
Browse files

Merge "wil6210: fix locking in wmi_call"

parents 40da75f6 a8cd4104
Loading
Loading
Loading
Loading
+10 −5
Original line number Diff line number Diff line
@@ -663,10 +663,10 @@ static ssize_t wil_read_file_ioblob(struct file *file, char __user *user_buf,
	enum { max_count = 4096 };
	struct wil_blob_wrapper *wil_blob = file->private_data;
	struct wil6210_priv *wil = wil_blob->wil;
	loff_t pos = *ppos;
	loff_t aligned_pos, pos = *ppos;
	size_t available = wil_blob->blob.size;
	void *buf;
	size_t ret;
	size_t unaligned_bytes, aligned_count, ret;
	int rc;

	if (test_bit(wil_status_suspending, wil_blob->wil->status) ||
@@ -684,7 +684,12 @@ static ssize_t wil_read_file_ioblob(struct file *file, char __user *user_buf,
	if (count > max_count)
		count = max_count;

	buf = kmalloc(count, GFP_KERNEL);
	/* set pos to 4 bytes aligned */
	unaligned_bytes = pos % 4;
	aligned_pos = pos - unaligned_bytes;
	aligned_count = count + unaligned_bytes;

	buf = kmalloc(aligned_count, GFP_KERNEL);
	if (!buf)
		return -ENOMEM;

@@ -695,9 +700,9 @@ static ssize_t wil_read_file_ioblob(struct file *file, char __user *user_buf,
	}

	wil_memcpy_fromio_32(buf, (const void __iomem *)
			     wil_blob->blob.data + pos, count);
			     wil_blob->blob.data + aligned_pos, aligned_count);

	ret = copy_to_user(user_buf, buf, count);
	ret = copy_to_user(user_buf, buf + unaligned_bytes, count);

	wil_pm_runtime_put(wil);

+18 −36
Original line number Diff line number Diff line
@@ -160,7 +160,7 @@ static int wil_ring_alloc_skb_edma(struct wil6210_priv *wil,
				   struct wil_ring *ring, u32 i)
{
	struct device *dev = wil_to_dev(wil);
	unsigned int sz = ALIGN(wil->rx_buf_len, 4);
	unsigned int sz = wil->rx_buf_len;
	dma_addr_t pa;
	u16 buff_id;
	struct list_head *active = &wil->rx_buff_mgmt.active;
@@ -235,9 +235,10 @@ static int wil_rx_refill_edma(struct wil6210_priv *wil)
	struct wil_ring *ring = &wil->ring_rx;
	u32 next_head;
	int rc = 0;
	u32 swtail = *ring->edma_rx_swtail.va;
	ring->swtail = *ring->edma_rx_swtail.va;

	for (; next_head = wil_ring_next_head(ring), (next_head != swtail);
	for (; next_head = wil_ring_next_head(ring),
	     (next_head != ring->swtail);
	     ring->swhead = next_head) {
		rc = wil_ring_alloc_skb_edma(wil, ring, ring->swhead);
		if (unlikely(rc)) {
@@ -265,43 +266,26 @@ static void wil_move_all_rx_buff_to_free_list(struct wil6210_priv *wil,
					      struct wil_ring *ring)
{
	struct device *dev = wil_to_dev(wil);
	u32 next_tail;
	u32 swhead = (ring->swhead + 1) % ring->size;
	struct list_head *active = &wil->rx_buff_mgmt.active;
	dma_addr_t pa;
	u16 dmalen;

	for (; next_tail = wil_ring_next_tail(ring), (next_tail != swhead);
	     ring->swtail = next_tail) {
		struct wil_rx_enhanced_desc dd, *d = ⅆ
		struct wil_rx_enhanced_desc *_d =
			(struct wil_rx_enhanced_desc *)
			&ring->va[ring->swtail].rx.enhanced;
		struct sk_buff *skb;
		u16 buff_id;

		*d = *_d;
	while (!list_empty(active)) {
		struct wil_rx_buff *rx_buff =
			list_first_entry(active, struct wil_rx_buff, list);
		struct sk_buff *skb = rx_buff->skb;

		/* Extract the SKB from the rx_buff management array */
		buff_id = __le16_to_cpu(d->mac.buff_id);
		if (buff_id >= wil->rx_buff_mgmt.size) {
			wil_err(wil, "invalid buff_id %d\n", buff_id);
			continue;
		}
		skb = wil->rx_buff_mgmt.buff_arr[buff_id].skb;
		wil->rx_buff_mgmt.buff_arr[buff_id].skb = NULL;
		if (unlikely(!skb)) {
			wil_err(wil, "No Rx skb at buff_id %d\n", buff_id);
			wil_err(wil, "No Rx skb at buff_id %d\n", rx_buff->id);
		} else {
			pa = wil_rx_desc_get_addr_edma(&d->dma);
			dmalen = le16_to_cpu(d->dma.length);
			dma_unmap_single(dev, pa, dmalen, DMA_FROM_DEVICE);

			rx_buff->skb = NULL;
			memcpy(&pa, skb->cb, sizeof(pa));
			dma_unmap_single(dev, pa, wil->rx_buf_len,
					 DMA_FROM_DEVICE);
			kfree_skb(skb);
		}

		/* Move the buffer from the active to the free list */
		list_move(&wil->rx_buff_mgmt.buff_arr[buff_id].list,
			  &wil->rx_buff_mgmt.free);
		list_move(&rx_buff->list, &wil->rx_buff_mgmt.free);
	}
}

@@ -603,6 +587,7 @@ static bool wil_is_rx_idle_edma(struct wil6210_priv *wil)

static void wil_rx_buf_len_init_edma(struct wil6210_priv *wil)
{
	/* RX buffer size must be aligned to 4 bytes */
	wil->rx_buf_len = rx_large_buf ?
		WIL_MAX_ETH_MTU : WIL_EDMA_RX_BUF_LEN_DEFAULT;
}
@@ -616,7 +601,6 @@ static int wil_rx_init_edma(struct wil6210_priv *wil, uint desc_ring_order)
		sizeof(struct wil_rx_status_compressed) :
		sizeof(struct wil_rx_status_extended);
	int i;
	u16 max_rx_pl_per_desc;

	/* In SW reorder one must use extended status messages */
	if (wil->use_compressed_rx_status && !wil->use_rx_hw_reordering) {
@@ -642,8 +626,6 @@ static int wil_rx_init_edma(struct wil6210_priv *wil, uint desc_ring_order)

	wil_rx_buf_len_init_edma(wil);

	max_rx_pl_per_desc = ALIGN(wil->rx_buf_len, 4);

	/* Use debugfs dbg_num_rx_srings if set, reserve one sring for TX */
	if (wil->num_rx_status_rings > WIL6210_MAX_STATUS_RINGS - 1)
		wil->num_rx_status_rings = WIL6210_MAX_STATUS_RINGS - 1;
@@ -651,7 +633,7 @@ static int wil_rx_init_edma(struct wil6210_priv *wil, uint desc_ring_order)
	wil_dbg_misc(wil, "rx_init: allocate %d status rings\n",
		     wil->num_rx_status_rings);

	rc = wil_wmi_cfg_def_rx_offload(wil, max_rx_pl_per_desc);
	rc = wil_wmi_cfg_def_rx_offload(wil, wil->rx_buf_len);
	if (rc)
		return rc;

@@ -888,7 +870,7 @@ static struct sk_buff *wil_sring_reap_rx_edma(struct wil6210_priv *wil,
	struct sk_buff *skb;
	dma_addr_t pa;
	struct wil_ring_rx_data *rxdata = &sring->rx_data;
	unsigned int sz = ALIGN(wil->rx_buf_len, 4);
	unsigned int sz = wil->rx_buf_len;
	struct wil_net_stats *stats = NULL;
	u16 dmalen;
	int cid;
+5 −4
Original line number Diff line number Diff line
@@ -2029,16 +2029,17 @@ int wmi_call(struct wil6210_priv *wil, u16 cmdid, u8 mid, void *buf, u16 len,
{
	int rc;
	unsigned long remain;
	ulong flags;

	mutex_lock(&wil->wmi_mutex);

	spin_lock(&wil->wmi_ev_lock);
	spin_lock_irqsave(&wil->wmi_ev_lock, flags);
	wil->reply_id = reply_id;
	wil->reply_mid = mid;
	wil->reply_buf = reply;
	wil->reply_size = reply_size;
	reinit_completion(&wil->wmi_call);
	spin_unlock(&wil->wmi_ev_lock);
	spin_unlock_irqrestore(&wil->wmi_ev_lock, flags);

	rc = __wmi_send(wil, cmdid, mid, buf, len, false);
	if (rc)
@@ -2058,12 +2059,12 @@ int wmi_call(struct wil6210_priv *wil, u16 cmdid, u8 mid, void *buf, u16 len,
	}

out:
	spin_lock(&wil->wmi_ev_lock);
	spin_lock_irqsave(&wil->wmi_ev_lock, flags);
	wil->reply_id = 0;
	wil->reply_mid = U8_MAX;
	wil->reply_buf = NULL;
	wil->reply_size = 0;
	spin_unlock(&wil->wmi_ev_lock);
	spin_unlock_irqrestore(&wil->wmi_ev_lock, flags);

	mutex_unlock(&wil->wmi_mutex);