Commit 38b6c01a authored by Kalle Valo's avatar Kalle Valo
Browse files
ath.git patches for v5.20. Major changes:

ath9k

* fix use-after-free in ath9k_hif_usb_rx_cb()
parents 8bc65d38 d1954e3e
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -1165,7 +1165,7 @@ void ath11k_hal_srng_shadow_update_hp_tp(struct ath11k_base *ab,
	lockdep_assert_held(&srng->lock);

	/* check whether the ring is emptry. Update the shadow
	 * HP only when then ring isn't' empty.
	 * HP only when then ring isn't empty.
	 */
	if (srng->ring_dir == HAL_SRNG_DIR_SRC &&
	    *srng->u.src_ring.tp_addr != srng->u.src_ring.hp)
+12 −4
Original line number Diff line number Diff line
@@ -71,6 +71,7 @@ struct ath6kl_usb {
	u8 *diag_cmd_buffer;
	u8 *diag_resp_buffer;
	struct ath6kl *ar;
	struct workqueue_struct *wq;
};

/* usb urb object */
@@ -478,7 +479,7 @@ static void ath6kl_usb_flush_all(struct ath6kl_usb *ar_usb)
	 * Flushing any pending I/O may schedule work this call will block
	 * until all scheduled work runs to completion.
	 */
	flush_scheduled_work();
	flush_workqueue(ar_usb->wq);
}

static void ath6kl_usb_start_recv_pipes(struct ath6kl_usb *ar_usb)
@@ -544,7 +545,7 @@ static void ath6kl_usb_recv_complete(struct urb *urb)

	/* note: queue implements a lock */
	skb_queue_tail(&pipe->io_comp_queue, skb);
	schedule_work(&pipe->io_complete_work);
	queue_work(pipe->ar_usb->wq, &pipe->io_complete_work);

cleanup_recv_urb:
	ath6kl_usb_cleanup_recv_urb(urb_context);
@@ -579,7 +580,7 @@ static void ath6kl_usb_usb_transmit_complete(struct urb *urb)

	/* note: queue implements a lock */
	skb_queue_tail(&pipe->io_comp_queue, skb);
	schedule_work(&pipe->io_complete_work);
	queue_work(pipe->ar_usb->wq, &pipe->io_complete_work);
}

static void ath6kl_usb_io_comp_work(struct work_struct *work)
@@ -619,6 +620,7 @@ static void ath6kl_usb_destroy(struct ath6kl_usb *ar_usb)

	kfree(ar_usb->diag_cmd_buffer);
	kfree(ar_usb->diag_resp_buffer);
	destroy_workqueue(ar_usb->wq);

	kfree(ar_usb);
}
@@ -631,9 +633,15 @@ static struct ath6kl_usb *ath6kl_usb_create(struct usb_interface *interface)
	int status = 0;
	int i;

	/* ath6kl_usb_destroy() needs ar_usb != NULL && ar_usb->wq != NULL. */
	ar_usb = kzalloc(sizeof(struct ath6kl_usb), GFP_KERNEL);
	if (ar_usb == NULL)
		goto fail_ath6kl_usb_create;
		return NULL;
	ar_usb->wq = alloc_workqueue("ath6kl_wq", 0, 0);
	if (!ar_usb->wq) {
		kfree(ar_usb);
		return NULL;
	}

	usb_set_intfdata(interface, ar_usb);
	spin_lock_init(&(ar_usb->cs_lock));
+1 −1
Original line number Diff line number Diff line
@@ -498,7 +498,7 @@ static void ar9002_hw_spectral_scan_config(struct ath_hw *ah,
	else
		REG_CLR_BIT(ah, AR_PHY_SPECTRAL_SCAN, repeat_bit);

	/* on AR92xx, the highest bit of count will make the the chip send
	/* on AR92xx, the highest bit of count will make the chip send
	 * spectral samples endlessly. Check if this really was intended,
	 * and fix otherwise.
	 */
+13 −13
Original line number Diff line number Diff line
@@ -244,11 +244,11 @@ static inline void ath9k_skb_queue_complete(struct hif_device_usb *hif_dev,
		ath9k_htc_txcompletion_cb(hif_dev->htc_handle,
					  skb, txok);
		if (txok) {
			TX_STAT_INC(skb_success);
			TX_STAT_ADD(skb_success_bytes, ln);
			TX_STAT_INC(hif_dev, skb_success);
			TX_STAT_ADD(hif_dev, skb_success_bytes, ln);
		}
		else
			TX_STAT_INC(skb_failed);
			TX_STAT_INC(hif_dev, skb_failed);
	}
}

@@ -302,7 +302,7 @@ static void hif_usb_tx_cb(struct urb *urb)
	hif_dev->tx.tx_buf_cnt++;
	if (!(hif_dev->tx.flags & HIF_USB_TX_STOP))
		__hif_usb_tx(hif_dev); /* Check for pending SKBs */
	TX_STAT_INC(buf_completed);
	TX_STAT_INC(hif_dev, buf_completed);
	spin_unlock(&hif_dev->tx.tx_lock);
}

@@ -353,7 +353,7 @@ static int __hif_usb_tx(struct hif_device_usb *hif_dev)
			tx_buf->len += tx_buf->offset;

		__skb_queue_tail(&tx_buf->skb_queue, nskb);
		TX_STAT_INC(skb_queued);
		TX_STAT_INC(hif_dev, skb_queued);
	}

	usb_fill_bulk_urb(tx_buf->urb, hif_dev->udev,
@@ -369,7 +369,7 @@ static int __hif_usb_tx(struct hif_device_usb *hif_dev)
		list_move_tail(&tx_buf->list, &hif_dev->tx.tx_buf);
		hif_dev->tx.tx_buf_cnt++;
	} else {
		TX_STAT_INC(buf_queued);
		TX_STAT_INC(hif_dev, buf_queued);
	}

	return ret;
@@ -514,7 +514,7 @@ static void hif_usb_sta_drain(void *hif_handle, u8 idx)
			ath9k_htc_txcompletion_cb(hif_dev->htc_handle,
						  skb, false);
			hif_dev->tx.tx_skb_cnt--;
			TX_STAT_INC(skb_failed);
			TX_STAT_INC(hif_dev, skb_failed);
		}
	}

@@ -585,14 +585,14 @@ static void ath9k_hif_usb_rx_stream(struct hif_device_usb *hif_dev,
		pkt_tag = get_unaligned_le16(ptr + index + 2);

		if (pkt_tag != ATH_USB_RX_STREAM_MODE_TAG) {
			RX_STAT_INC(skb_dropped);
			RX_STAT_INC(hif_dev, skb_dropped);
			return;
		}

		if (pkt_len > 2 * MAX_RX_BUF_SIZE) {
			dev_err(&hif_dev->udev->dev,
				"ath9k_htc: invalid pkt_len (%x)\n", pkt_len);
			RX_STAT_INC(skb_dropped);
			RX_STAT_INC(hif_dev, skb_dropped);
			return;
		}

@@ -618,7 +618,7 @@ static void ath9k_hif_usb_rx_stream(struct hif_device_usb *hif_dev,
				goto err;
			}
			skb_reserve(nskb, 32);
			RX_STAT_INC(skb_allocated);
			RX_STAT_INC(hif_dev, skb_allocated);

			memcpy(nskb->data, &(skb->data[chk_idx+4]),
			       hif_dev->rx_transfer_len);
@@ -639,7 +639,7 @@ static void ath9k_hif_usb_rx_stream(struct hif_device_usb *hif_dev,
				goto err;
			}
			skb_reserve(nskb, 32);
			RX_STAT_INC(skb_allocated);
			RX_STAT_INC(hif_dev, skb_allocated);

			memcpy(nskb->data, &(skb->data[chk_idx+4]), pkt_len);
			skb_put(nskb, pkt_len);
@@ -649,10 +649,10 @@ static void ath9k_hif_usb_rx_stream(struct hif_device_usb *hif_dev,

err:
	for (i = 0; i < pool_index; i++) {
		RX_STAT_ADD(skb_completed_bytes, skb_pool[i]->len);
		RX_STAT_ADD(hif_dev, skb_completed_bytes, skb_pool[i]->len);
		ath9k_htc_rx_msg(hif_dev->htc_handle, skb_pool[i],
				 skb_pool[i]->len, USB_WLAN_RX_PIPE);
		RX_STAT_INC(skb_completed);
		RX_STAT_INC(hif_dev, skb_completed);
	}
}

+18 −14
Original line number Diff line number Diff line
@@ -327,14 +327,18 @@ static inline struct ath9k_htc_tx_ctl *HTC_SKB_CB(struct sk_buff *skb)
}

#ifdef CONFIG_ATH9K_HTC_DEBUGFS

#define TX_STAT_INC(c) (hif_dev->htc_handle->drv_priv->debug.tx_stats.c++)
#define TX_STAT_ADD(c, a) (hif_dev->htc_handle->drv_priv->debug.tx_stats.c += a)
#define RX_STAT_INC(c) (hif_dev->htc_handle->drv_priv->debug.skbrx_stats.c++)
#define RX_STAT_ADD(c, a) (hif_dev->htc_handle->drv_priv->debug.skbrx_stats.c += a)
#define CAB_STAT_INC   priv->debug.tx_stats.cab_queued++

#define TX_QSTAT_INC(q) (priv->debug.tx_stats.queue_stats[q]++)
#define __STAT_SAFE(hif_dev, expr)	((hif_dev)->htc_handle->drv_priv ? (expr) : 0)
#define CAB_STAT_INC(priv)		((priv)->debug.tx_stats.cab_queued++)
#define TX_QSTAT_INC(priv, q)		((priv)->debug.tx_stats.queue_stats[q]++)

#define TX_STAT_INC(hif_dev, c) \
		__STAT_SAFE((hif_dev), (hif_dev)->htc_handle->drv_priv->debug.tx_stats.c++)
#define TX_STAT_ADD(hif_dev, c, a) \
		__STAT_SAFE((hif_dev), (hif_dev)->htc_handle->drv_priv->debug.tx_stats.c += a)
#define RX_STAT_INC(hif_dev, c) \
		__STAT_SAFE((hif_dev), (hif_dev)->htc_handle->drv_priv->debug.skbrx_stats.c++)
#define RX_STAT_ADD(hif_dev, c, a) \
		__STAT_SAFE((hif_dev), (hif_dev)->htc_handle->drv_priv->debug.skbrx_stats.c += a)

void ath9k_htc_err_stat_rx(struct ath9k_htc_priv *priv,
			   struct ath_rx_status *rs);
@@ -374,13 +378,13 @@ void ath9k_htc_get_et_stats(struct ieee80211_hw *hw,
			    struct ethtool_stats *stats, u64 *data);
#else

#define TX_STAT_INC(c) do { } while (0)
#define TX_STAT_ADD(c, a) do { } while (0)
#define RX_STAT_INC(c) do { } while (0)
#define RX_STAT_ADD(c, a) do { } while (0)
#define CAB_STAT_INC   do { } while (0)
#define TX_STAT_INC(hif_dev, c)
#define TX_STAT_ADD(hif_dev, c, a)
#define RX_STAT_INC(hif_dev, c)
#define RX_STAT_ADD(hif_dev, c, a)

#define TX_QSTAT_INC(c) do { } while (0)
#define CAB_STAT_INC(priv)
#define TX_QSTAT_INC(priv, c)

static inline void ath9k_htc_err_stat_rx(struct ath9k_htc_priv *priv,
					 struct ath_rx_status *rs)
Loading