This patch series adds changes made to implement access
category based data classification and manages buffers allocation
between different access categories on the Tx path.
Aditya Shankar (7):
staging: wilc1000: Add support for AC classification.
staging: wilc1000: Add function to calculate ac queue limit
staging: wilc1000: WMM classification of data
staging: wilc1000: Add function to balance packet count
staging: wilc1000: Get packet count from firmware
staging: wilc1000: Change ac based on acm status
staging: wilc1000: Update ACM bit status
drivers/staging/wilc1000/wilc_wlan.c | 136 +++++++++++++++++++++++++++++++++++
drivers/staging/wilc1000/wilc_wlan.h | 25 +++++++
2 files changed, 161 insertions(+)
--
2.7.4
Add a new function to track the cound of packets and
determine the ratio of current number of packets to
maximum count of packets.
Signed-off-by: Aditya Shankar <[email protected]>
---
drivers/staging/wilc1000/wilc_wlan.c | 17 +++++++++++++++++
1 file changed, 17 insertions(+)
diff --git a/drivers/staging/wilc1000/wilc_wlan.c b/drivers/staging/wilc1000/wilc_wlan.c
index d1ed3ba8..655f229 100644
--- a/drivers/staging/wilc1000/wilc_wlan.c
+++ b/drivers/staging/wilc1000/wilc_wlan.c
@@ -426,6 +426,23 @@ static inline u8 ac_classify(struct wilc *wilc, struct txq_entry_t *tqe)
return ac;
}
+static inline int ac_balance(u8 *count, u8 *ratio)
+{
+ u8 i, max_count = 0;
+
+ if (!count || !ratio)
+ return -1;
+
+ for (i = 0; i < NQUEUES; i++)
+ if (count[i] > max_count)
+ max_count = count[i];
+
+ for (i = 0; i < NQUEUES; i++)
+ ratio[i] = max_count - count[i];
+
+ return 0;
+}
+
int wilc_wlan_txq_add_net_pkt(struct net_device *dev, void *priv, u8 *buffer,
u32 buffer_size, wilc_tx_complete_func_t func)
{
--
2.7.4
Hi Aditya,
[auto build test ERROR on staging/staging-testing]
[also build test ERROR on v4.12-rc7 next-20170626]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]
url: https://github.com/0day-ci/linux/commits/Aditya-Shankar/staging-wilc1000-Add-support-for-AC-classification/20170627-015835
config: sparc64-allyesconfig (attached as .config)
compiler: sparc64-linux-gnu-gcc (Debian 6.1.1-9) 6.1.1 20160705
reproduce:
wget https://raw.githubusercontent.com/01org/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
chmod +x ~/bin/make.cross
# save the attached .config to linux build tree
make.cross ARCH=sparc64
All errors (new ones prefixed by >>):
drivers/staging/wilc1000/wilc_wlan.c: In function 'ac_change':
>> drivers/staging/wilc1000/wilc_wlan.c:457:11: error: 'struct wilc' has no member named 'txq'
if (wilc->txq[*ac].acm == 0)
^~
vim +457 drivers/staging/wilc1000/wilc_wlan.c
451 pkt_count[AC_VO_Q] = (reg & 0xfe000000) >> VO_AC_COUNT_POS;
452 }
453
454 static inline u8 ac_change(struct wilc *wilc, u8 *ac)
455 {
456 do {
> 457 if (wilc->txq[*ac].acm == 0)
458 return 0;
459 (*ac)++;
460 } while (*ac < NQUEUES);
---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation
This patch adds new variables and defines for adding access
category classification
Signed-off-by: Aditya Shankar <[email protected]>
---
drivers/staging/wilc1000/wilc_wlan.h | 25 +++++++++++++++++++++++++
1 file changed, 25 insertions(+)
diff --git a/drivers/staging/wilc1000/wilc_wlan.h b/drivers/staging/wilc1000/wilc_wlan.h
index 7a5eba9..c97f94a 100644
--- a/drivers/staging/wilc1000/wilc_wlan.h
+++ b/drivers/staging/wilc1000/wilc_wlan.h
@@ -133,6 +133,17 @@
#define MODALIAS "WILC_SPI"
#define GPIO_NUM 0x44
+
+#define NQUEUES 4
+#define VO_AC_COUNT_POS 25
+#define VO_AC_ACM_STAT_POS 24
+#define VI_AC_COUNT_POS 17
+#define VI_AC_ACM_STAT_POS 16
+#define BE_AC_COUNT_POS 9
+#define BE_AC_ACM_STAT_POS 8
+#define BK_AC_COUNT_POS 2
+#define BK_AC_ACM_STAT_POS 1
+#define AC_BUFFER_SIZE 1000
/*******************************************/
/* E0 and later Interrupt flags. */
/*******************************************/
@@ -206,11 +217,25 @@ typedef void (*wilc_debug_func)(u32, char *, ...);
* Tx/Rx Queue Structure
*
********************************************/
+struct txq_handle {
+ struct txq_entry_t *txq_head;
+ struct txq_entry_t *txq_tail;
+ u16 count;
+ u8 acm;
+};
+
+enum ip_pkt_priority {
+ AC_VO_Q = 0,
+ AC_VI_Q = 1,
+ AC_BE_Q = 2,
+ AC_BK_Q = 3
+};
struct txq_entry_t {
struct txq_entry_t *next;
struct txq_entry_t *prev;
int type;
+ u8 q_num;
int tcp_pending_ack_idx;
u8 *buffer;
int buffer_size;
--
2.7.4
This patch adds a function which calculates the queue limit
for a given access category queue.
Signed-off-by: Aditya Shankar <[email protected]>
---
drivers/staging/wilc1000/wilc_wlan.c | 42 ++++++++++++++++++++++++++++++++++++
1 file changed, 42 insertions(+)
diff --git a/drivers/staging/wilc1000/wilc_wlan.c b/drivers/staging/wilc1000/wilc_wlan.c
index 9addef1..8c997ba 100644
--- a/drivers/staging/wilc1000/wilc_wlan.c
+++ b/drivers/staging/wilc1000/wilc_wlan.c
@@ -333,6 +333,48 @@ static int wilc_wlan_txq_add_cfg_pkt(struct wilc_vif *vif, u8 *buffer,
return 1;
}
+static inline void ac_q_limit(u8 ac, u16 *q_limit)
+{
+ static bool initialized;
+ static u8 buffer[AC_BUFFER_SIZE];
+ static u16 cnt[NQUEUES];
+ u8 factors[NQUEUES] = {1, 1, 1, 1};
+ static u16 sum;
+ u16 i;
+ static u16 end_index;
+
+ if (!initialized) {
+ for (i = 0; i < AC_BUFFER_SIZE; i++)
+ buffer[i] = i % NQUEUES;
+
+ for (i = 0; i < NQUEUES; i++) {
+ cnt[i] = AC_BUFFER_SIZE * factors[i] / NQUEUES;
+ sum += cnt[i];
+ }
+ end_index = AC_BUFFER_SIZE - 1;
+ initialized = 1;
+ }
+ if (end_index > AC_BUFFER_SIZE - 1)
+ end_index = AC_BUFFER_SIZE - 1;
+
+ cnt[buffer[end_index]] -= factors[buffer[end_index]];
+ cnt[ac] += factors[ac];
+ sum += (factors[ac] - factors[buffer[end_index]]);
+
+ buffer[end_index] = ac;
+ if (end_index > 0)
+ end_index--;
+ else
+ end_index = AC_BUFFER_SIZE - 1;
+
+ for (i = 0; i < NQUEUES; i++)
+ if (!sum)
+ q_limit[i] = 1;
+ else
+ q_limit[i] = (cnt[i] * FLOW_CONTROL_UPPER_THRESHOLD /
+ sum) + 1;
+}
+
int wilc_wlan_txq_add_net_pkt(struct net_device *dev, void *priv, u8 *buffer,
u32 buffer_size, wilc_tx_complete_func_t func)
{
--
2.7.4
Add a new function to update ACM bit status for a queue
for all access categories.
Signed-off-by: Aditya Shankar <[email protected]>
---
drivers/staging/wilc1000/wilc_wlan.c | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/drivers/staging/wilc1000/wilc_wlan.c b/drivers/staging/wilc1000/wilc_wlan.c
index e323fd4..929166a 100644
--- a/drivers/staging/wilc1000/wilc_wlan.c
+++ b/drivers/staging/wilc1000/wilc_wlan.c
@@ -461,6 +461,14 @@ static inline u8 ac_change(struct wilc *wilc, u8 *ac)
return 1;
}
+static inline void ac_acm_bit(struct wilc *wilc, u32 reg)
+{
+ wilc->txq[AC_BK_Q].acm = (reg & 0x00000002) >> BK_AC_ACM_STAT_POS;
+ wilc->txq[AC_BE_Q].acm = (reg & 0x00000100) >> BE_AC_ACM_STAT_POS;
+ wilc->txq[AC_VI_Q].acm = (reg & 0x00010000) >> VI_AC_ACM_STAT_POS;
+ wilc->txq[AC_VO_Q].acm = (reg & 0x01000000) >> VO_AC_ACM_STAT_POS;
+}
+
int wilc_wlan_txq_add_net_pkt(struct net_device *dev, void *priv, u8 *buffer,
u32 buffer_size, wilc_tx_complete_func_t func)
{
--
2.7.4
Add a new function to check and alter the ac if needed
based on the acm status for a particular queue.
Signed-off-by: Aditya Shankar <[email protected]>
---
drivers/staging/wilc1000/wilc_wlan.c | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/drivers/staging/wilc1000/wilc_wlan.c b/drivers/staging/wilc1000/wilc_wlan.c
index b3e1136..e323fd4 100644
--- a/drivers/staging/wilc1000/wilc_wlan.c
+++ b/drivers/staging/wilc1000/wilc_wlan.c
@@ -451,6 +451,16 @@ static inline void ac_pkt_count(u32 reg, u8 *pkt_count)
pkt_count[AC_VO_Q] = (reg & 0xfe000000) >> VO_AC_COUNT_POS;
}
+static inline u8 ac_change(struct wilc *wilc, u8 *ac)
+{
+ do {
+ if (wilc->txq[*ac].acm == 0)
+ return 0;
+ (*ac)++;
+ } while (*ac < NQUEUES);
+ return 1;
+}
+
int wilc_wlan_txq_add_net_pkt(struct net_device *dev, void *priv, u8 *buffer,
u32 buffer_size, wilc_tx_complete_func_t func)
{
--
2.7.4
This patch adds a new function to classify data to available
WMM access categories based on the DSCP value in the header.
Signed-off-by: Aditya Shankar <[email protected]>
---
drivers/staging/wilc1000/wilc_wlan.c | 51 ++++++++++++++++++++++++++++++++++++
1 file changed, 51 insertions(+)
diff --git a/drivers/staging/wilc1000/wilc_wlan.c b/drivers/staging/wilc1000/wilc_wlan.c
index 8c997ba..d1ed3ba8 100644
--- a/drivers/staging/wilc1000/wilc_wlan.c
+++ b/drivers/staging/wilc1000/wilc_wlan.c
@@ -375,6 +375,57 @@ static inline void ac_q_limit(u8 ac, u16 *q_limit)
sum) + 1;
}
+static inline u8 ac_classify(struct wilc *wilc, struct txq_entry_t *tqe)
+{
+ u8 *eth_hdr_ptr;
+ u8 *buffer = tqe->buffer;
+ u8 ac;
+ u16 h_proto;
+
+ spin_lock_irqsave(&wilc->txq_spinlock, wilc->txq_spinlock_flags);
+
+ eth_hdr_ptr = &buffer[0];
+ h_proto = ntohs(*((unsigned short *)ð_hdr_ptr[12]));
+ if (h_proto == ETH_P_IP) {
+ u8 *ip_hdr_ptr;
+ u32 IHL, DSCP;
+
+ ip_hdr_ptr = &buffer[ETHERNET_HDR_LEN];
+ IHL = (ip_hdr_ptr[0] & 0xf) << 2;
+ DSCP = (ip_hdr_ptr[1] & 0xfc);
+
+ switch (DSCP) {
+ case 0x20:
+ case 0x40:
+ case 0x08:
+ ac = AC_BK_Q;
+ break;
+ case 0x80:
+ case 0xA0:
+ case 0x28:
+ ac = AC_VI_Q;
+ break;
+ case 0xC0:
+ case 0xd0:
+ case 0xE0:
+ case 0x88:
+ case 0xB8:
+ ac = AC_VO_Q;
+ break;
+ default:
+ ac = AC_BE_Q;
+ break;
+ }
+ } else {
+ ac = AC_BE_Q;
+ }
+
+ tqe->q_num = ac;
+ spin_unlock_irqrestore(&wilc->txq_spinlock, wilc->txq_spinlock_flags);
+
+ return ac;
+}
+
int wilc_wlan_txq_add_net_pkt(struct net_device *dev, void *priv, u8 *buffer,
u32 buffer_size, wilc_tx_complete_func_t func)
{
--
2.7.4
Add a new function to get packet count from the firmware.
31:25 24 23:17 16 15:9 8 7:2 1 0
VO CNT VO ACM VI CNT VI ACM BE CNT BE ACM BK CNT BK ACM VMM ready
Signed-off-by: Aditya Shankar <[email protected]>
---
drivers/staging/wilc1000/wilc_wlan.c | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/drivers/staging/wilc1000/wilc_wlan.c b/drivers/staging/wilc1000/wilc_wlan.c
index 655f229..b3e1136 100644
--- a/drivers/staging/wilc1000/wilc_wlan.c
+++ b/drivers/staging/wilc1000/wilc_wlan.c
@@ -443,6 +443,14 @@ static inline int ac_balance(u8 *count, u8 *ratio)
return 0;
}
+static inline void ac_pkt_count(u32 reg, u8 *pkt_count)
+{
+ pkt_count[AC_BK_Q] = (reg & 0x000000fa) >> BK_AC_COUNT_POS;
+ pkt_count[AC_BE_Q] = (reg & 0x0000fe00) >> BE_AC_COUNT_POS;
+ pkt_count[AC_VI_Q] = (reg & 0x00fe0000) >> VI_AC_COUNT_POS;
+ pkt_count[AC_VO_Q] = (reg & 0xfe000000) >> VO_AC_COUNT_POS;
+}
+
int wilc_wlan_txq_add_net_pkt(struct net_device *dev, void *priv, u8 *buffer,
u32 buffer_size, wilc_tx_complete_func_t func)
{
--
2.7.4