1
0
Fork 0
mirror of synced 2025-03-06 20:59:54 +01:00
linux/drivers/net/wireless/mediatek/mt76/util.h
Felix Fietkau 5e616ad216 mt76: fix wcid allocation issues
mt76 core uses ffs() to find the next free bit. This works well for 32 bit
architectures where BITS_PER_LONG is 32. ffs only checks 32 bit values, so
allocation fails on 64 bit architectures.
Additionally, the wcid mask array was too small in cases where the array
was not a multiple of BITS_PER_LONG.
Fix this by making the wcid mask array u32 instead and use DIV_ROUND_UP
for the size, just in case we ever bump it to a value that's not a multiple
of 32.

Reported-by: Ryder Lee <ryder.lee@mediatek.com>
Signed-off-by: Felix Fietkau <nbd@nbd.name>
2020-05-28 17:57:24 +02:00

48 lines
1,001 B
C

/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (C) 2016 Felix Fietkau <nbd@nbd.name>
* Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
*/
#ifndef __MT76_UTIL_H
#define __MT76_UTIL_H
#include <linux/skbuff.h>
#include <linux/bitops.h>
#include <linux/bitfield.h>
#define MT76_INCR(_var, _size) \
(_var = (((_var) + 1) % (_size)))
int mt76_wcid_alloc(u32 *mask, int size);
static inline bool
mt76_wcid_mask_test(u32 *mask, int idx)
{
return mask[idx / 32] & BIT(idx % 32);
}
static inline void
mt76_wcid_mask_set(u32 *mask, int idx)
{
mask[idx / 32] |= BIT(idx % 32);
}
static inline void
mt76_wcid_mask_clear(u32 *mask, int idx)
{
mask[idx / 32] &= ~BIT(idx % 32);
}
static inline void
mt76_skb_set_moredata(struct sk_buff *skb, bool enable)
{
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
if (enable)
hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_MOREDATA);
else
hdr->frame_control &= ~cpu_to_le16(IEEE80211_FCTL_MOREDATA);
}
#endif