ac_classify() expects a struct sk_buff* as its second argument, which is
a member of struct tx_complete_data. priv happens to be a pointer to
struct tx_complete_data, so passing it directly to ac_classify() leads
to wrong behaviour and occasional panics.
Signed-off-by: Vsevolod Kozlov <[email protected]>
---
drivers/net/wireless/microchip/wilc1000/wlan.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/net/wireless/microchip/wilc1000/wlan.c b/drivers/net/wireless/microchip/wilc1000/wlan.c
index c12f27be9f79..04ed52c736ff 100644
--- a/drivers/net/wireless/microchip/wilc1000/wlan.c
+++ b/drivers/net/wireless/microchip/wilc1000/wlan.c
@@ -415,6 +415,7 @@ int wilc_wlan_txq_add_net_pkt(struct net_device *dev, void *priv, u8 *buffer,
struct txq_entry_t *tqe;
struct wilc_vif *vif = netdev_priv(dev);
struct wilc *wilc;
+ struct tx_complete_data *tx_data = priv;
u8 q_num;
wilc = vif->wilc;
@@ -437,7 +438,7 @@ int wilc_wlan_txq_add_net_pkt(struct net_device *dev, void *priv, u8 *buffer,
tqe->priv = priv;
tqe->vif = vif;
- q_num = ac_classify(wilc, priv);
+ q_num = ac_classify(wilc, tx_data->skb);
tqe->q_num = q_num;
if (ac_change(wilc, &q_num)) {
tx_complete_fn(priv, 0);
--
2.20.1
Vsevolod Kozlov <[email protected]> writes:
> ac_classify() expects a struct sk_buff* as its second argument, which is
> a member of struct tx_complete_data. priv happens to be a pointer to
> struct tx_complete_data, so passing it directly to ac_classify() leads
> to wrong behaviour and occasional panics.
A perfect example why void pointers should be avoided.
> Signed-off-by: Vsevolod Kozlov <[email protected]>
> ---
> drivers/net/wireless/microchip/wilc1000/wlan.c | 3 ++-
> 1 file changed, 2 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/net/wireless/microchip/wilc1000/wlan.c b/drivers/net/wireless/microchip/wilc1000/wlan.c
> index c12f27be9f79..04ed52c736ff 100644
> --- a/drivers/net/wireless/microchip/wilc1000/wlan.c
> +++ b/drivers/net/wireless/microchip/wilc1000/wlan.c
> @@ -415,6 +415,7 @@ int wilc_wlan_txq_add_net_pkt(struct net_device *dev, void *priv, u8 *buffer,
> struct txq_entry_t *tqe;
> struct wilc_vif *vif = netdev_priv(dev);
> struct wilc *wilc;
> + struct tx_complete_data *tx_data = priv;
> u8 q_num;
>
> wilc = vif->wilc;
> @@ -437,7 +438,7 @@ int wilc_wlan_txq_add_net_pkt(struct net_device *dev, void *priv, u8 *buffer,
> tqe->priv = priv;
> tqe->vif = vif;
>
> - q_num = ac_classify(wilc, priv);
> + q_num = ac_classify(wilc, tx_data->skb);
I think a safer fix would be to change wilc_wlan_txq_add_net_pkt() to
take that struct tx_complete_data *tx_data directly, and not use void
pointer at all. At the same time you could remove the ugly cast from the
caller:
netdev.c:740: queue_count = wilc_wlan_txq_add_net_pkt(ndev, (void *)tx_data,
--
https://patchwork.kernel.org/project/linux-wireless/list/
https://wireless.wiki.kernel.org/en/developers/documentation/submittingpatches