Skip to content

Commit 2108df3

Browse files
Prameela Rani GarnepudiKalle Valo
authored andcommitted
rsi: add coex support
With BT support, driver has to handle two streams of data (i.e. wlan and BT). Actual coex implementation is in firmware. Coex module just schedule the packets to firmware by taking them from the corresponding paths. Structures for module and protocol operations are introduced for this purpose. Protocol operations structure is global structure which can be shared among different modules. Move initialization of coex and operating mode values to rsi_91x_init(). Signed-off-by: Prameela Rani Garnepudi <prameela.j04cs@gmail.com> Signed-off-by: Siva Rebbagondla <siva.rebbagondla@redpinesignals.com> Signed-off-by: Amitkumar Karwar <amit.karwar@redpinesignals.com> Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
1 parent 4c10d56 commit 2108df3

File tree

12 files changed

+303
-10
lines changed

12 files changed

+303
-10
lines changed

drivers/net/wireless/rsi/Kconfig

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,4 +42,13 @@ config RSI_USB
4242
This option enables the USB bus support in rsi drivers.
4343
Select M (recommended), if you have a RSI 1x1 wireless module.
4444

45+
config RSI_COEX
46+
bool "Redpine Signals WLAN BT Coexistence support"
47+
depends on BT_HCIRSI && RSI_91X
48+
default y
49+
---help---
50+
This option enables the WLAN BT coex support in rsi drivers.
51+
Select M (recommended), if you have want to use this feature
52+
and you have RS9113 module.
53+
4554
endif # WLAN_VENDOR_RSI

drivers/net/wireless/rsi/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ rsi_91x-y += rsi_91x_mac80211.o
55
rsi_91x-y += rsi_91x_mgmt.o
66
rsi_91x-y += rsi_91x_hal.o
77
rsi_91x-y += rsi_91x_ps.o
8+
rsi_91x-$(CONFIG_RSI_COEX) += rsi_91x_coex.o
89
rsi_91x-$(CONFIG_RSI_DEBUGFS) += rsi_91x_debugfs.o
910

1011
rsi_usb-y += rsi_91x_usb.o rsi_91x_usb_ops.o
Lines changed: 177 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,177 @@
1+
/**
2+
* Copyright (c) 2018 Redpine Signals Inc.
3+
*
4+
* Permission to use, copy, modify, and/or distribute this software for any
5+
* purpose with or without fee is hereby granted, provided that the above
6+
* copyright notice and this permission notice appear in all copies.
7+
*
8+
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9+
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10+
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11+
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12+
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13+
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14+
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15+
*/
16+
17+
#include "rsi_main.h"
18+
#include "rsi_coex.h"
19+
#include "rsi_mgmt.h"
20+
#include "rsi_hal.h"
21+
22+
static enum rsi_coex_queues rsi_coex_determine_coex_q
23+
(struct rsi_coex_ctrl_block *coex_cb)
24+
{
25+
enum rsi_coex_queues q_num = RSI_COEX_Q_INVALID;
26+
27+
if (skb_queue_len(&coex_cb->coex_tx_qs[RSI_COEX_Q_COMMON]) > 0)
28+
q_num = RSI_COEX_Q_COMMON;
29+
if (skb_queue_len(&coex_cb->coex_tx_qs[RSI_COEX_Q_BT]) > 0)
30+
q_num = RSI_COEX_Q_BT;
31+
if (skb_queue_len(&coex_cb->coex_tx_qs[RSI_COEX_Q_WLAN]) > 0)
32+
q_num = RSI_COEX_Q_WLAN;
33+
34+
return q_num;
35+
}
36+
37+
static void rsi_coex_sched_tx_pkts(struct rsi_coex_ctrl_block *coex_cb)
38+
{
39+
enum rsi_coex_queues coex_q = RSI_COEX_Q_INVALID;
40+
struct sk_buff *skb;
41+
42+
do {
43+
coex_q = rsi_coex_determine_coex_q(coex_cb);
44+
rsi_dbg(INFO_ZONE, "queue = %d\n", coex_q);
45+
46+
if (coex_q == RSI_COEX_Q_BT)
47+
skb = skb_dequeue(&coex_cb->coex_tx_qs[RSI_COEX_Q_BT]);
48+
} while (coex_q != RSI_COEX_Q_INVALID);
49+
}
50+
51+
static void rsi_coex_scheduler_thread(struct rsi_common *common)
52+
{
53+
struct rsi_coex_ctrl_block *coex_cb =
54+
(struct rsi_coex_ctrl_block *)common->coex_cb;
55+
u32 timeout = EVENT_WAIT_FOREVER;
56+
57+
do {
58+
rsi_wait_event(&coex_cb->coex_tx_thread.event, timeout);
59+
rsi_reset_event(&coex_cb->coex_tx_thread.event);
60+
61+
rsi_coex_sched_tx_pkts(coex_cb);
62+
} while (atomic_read(&coex_cb->coex_tx_thread.thread_done) == 0);
63+
64+
complete_and_exit(&coex_cb->coex_tx_thread.completion, 0);
65+
}
66+
67+
int rsi_coex_recv_pkt(struct rsi_common *common, u8 *msg)
68+
{
69+
u8 msg_type = msg[RSI_RX_DESC_MSG_TYPE_OFFSET];
70+
71+
switch (msg_type) {
72+
case COMMON_CARD_READY_IND:
73+
rsi_dbg(INFO_ZONE, "common card ready received\n");
74+
rsi_handle_card_ready(common, msg);
75+
break;
76+
case SLEEP_NOTIFY_IND:
77+
rsi_dbg(INFO_ZONE, "sleep notify received\n");
78+
rsi_mgmt_pkt_recv(common, msg);
79+
break;
80+
}
81+
82+
return 0;
83+
}
84+
85+
static inline int rsi_map_coex_q(u8 hal_queue)
86+
{
87+
switch (hal_queue) {
88+
case RSI_COEX_Q:
89+
return RSI_COEX_Q_COMMON;
90+
case RSI_WLAN_Q:
91+
return RSI_COEX_Q_WLAN;
92+
case RSI_BT_Q:
93+
return RSI_COEX_Q_BT;
94+
}
95+
return RSI_COEX_Q_INVALID;
96+
}
97+
98+
int rsi_coex_send_pkt(void *priv, struct sk_buff *skb, u8 hal_queue)
99+
{
100+
struct rsi_common *common = (struct rsi_common *)priv;
101+
struct rsi_coex_ctrl_block *coex_cb =
102+
(struct rsi_coex_ctrl_block *)common->coex_cb;
103+
struct skb_info *tx_params = NULL;
104+
enum rsi_coex_queues coex_q;
105+
int status;
106+
107+
coex_q = rsi_map_coex_q(hal_queue);
108+
if (coex_q == RSI_COEX_Q_INVALID) {
109+
rsi_dbg(ERR_ZONE, "Invalid coex queue\n");
110+
return -EINVAL;
111+
}
112+
if (coex_q != RSI_COEX_Q_COMMON &&
113+
coex_q != RSI_COEX_Q_WLAN) {
114+
skb_queue_tail(&coex_cb->coex_tx_qs[coex_q], skb);
115+
rsi_set_event(&coex_cb->coex_tx_thread.event);
116+
return 0;
117+
}
118+
if (common->iface_down) {
119+
tx_params =
120+
(struct skb_info *)&IEEE80211_SKB_CB(skb)->driver_data;
121+
122+
if (!(tx_params->flags & INTERNAL_MGMT_PKT)) {
123+
rsi_indicate_tx_status(common->priv, skb, -EINVAL);
124+
return 0;
125+
}
126+
}
127+
128+
/* Send packet to hal */
129+
if (skb->priority == MGMT_SOFT_Q)
130+
status = rsi_send_mgmt_pkt(common, skb);
131+
else
132+
status = rsi_send_data_pkt(common, skb);
133+
134+
return status;
135+
}
136+
137+
int rsi_coex_attach(struct rsi_common *common)
138+
{
139+
struct rsi_coex_ctrl_block *coex_cb;
140+
int cnt;
141+
142+
coex_cb = kzalloc(sizeof(*coex_cb), GFP_KERNEL);
143+
if (!coex_cb)
144+
return -ENOMEM;
145+
146+
common->coex_cb = (void *)coex_cb;
147+
coex_cb->priv = common;
148+
149+
/* Initialize co-ex queues */
150+
for (cnt = 0; cnt < NUM_COEX_TX_QUEUES; cnt++)
151+
skb_queue_head_init(&coex_cb->coex_tx_qs[cnt]);
152+
rsi_init_event(&coex_cb->coex_tx_thread.event);
153+
154+
/* Initialize co-ex thread */
155+
if (rsi_create_kthread(common,
156+
&coex_cb->coex_tx_thread,
157+
rsi_coex_scheduler_thread,
158+
"Coex-Tx-Thread")) {
159+
rsi_dbg(ERR_ZONE, "%s: Unable to init tx thrd\n", __func__);
160+
return -EINVAL;
161+
}
162+
return 0;
163+
}
164+
165+
void rsi_coex_detach(struct rsi_common *common)
166+
{
167+
struct rsi_coex_ctrl_block *coex_cb =
168+
(struct rsi_coex_ctrl_block *)common->coex_cb;
169+
int cnt;
170+
171+
rsi_kill_thread(&coex_cb->coex_tx_thread);
172+
173+
for (cnt = 0; cnt < NUM_COEX_TX_QUEUES; cnt++)
174+
skb_queue_purge(&coex_cb->coex_tx_qs[cnt]);
175+
176+
kfree(coex_cb);
177+
}

drivers/net/wireless/rsi/rsi_91x_hal.c

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,15 @@ int rsi_send_pkt_to_bus(struct rsi_common *common, struct sk_buff *skb)
3131
struct rsi_hw *adapter = common->priv;
3232
int status;
3333

34+
if (common->coex_mode > 1)
35+
mutex_lock(&common->tx_bus_mutex);
36+
3437
status = adapter->host_intf_ops->write_pkt(common->priv,
3538
skb->data, skb->len);
39+
40+
if (common->coex_mode > 1)
41+
mutex_unlock(&common->tx_bus_mutex);
42+
3643
return status;
3744
}
3845

@@ -296,8 +303,7 @@ int rsi_send_data_pkt(struct rsi_common *common, struct sk_buff *skb)
296303
if (status)
297304
goto err;
298305

299-
status = adapter->host_intf_ops->write_pkt(common->priv, skb->data,
300-
skb->len);
306+
status = rsi_send_pkt_to_bus(common, skb);
301307
if (status)
302308
rsi_dbg(ERR_ZONE, "%s: Failed to write pkt\n", __func__);
303309

@@ -342,8 +348,7 @@ int rsi_send_mgmt_pkt(struct rsi_common *common,
342348
goto err;
343349

344350
rsi_prepare_mgmt_desc(common, skb);
345-
status = adapter->host_intf_ops->write_pkt(common->priv,
346-
(u8 *)skb->data, skb->len);
351+
status = rsi_send_pkt_to_bus(common, skb);
347352
if (status)
348353
rsi_dbg(ERR_ZONE, "%s: Failed to write the packet\n", __func__);
349354

@@ -926,10 +931,6 @@ int rsi_hal_device_init(struct rsi_hw *adapter)
926931
{
927932
struct rsi_common *common = adapter->priv;
928933

929-
common->coex_mode = RSI_DEV_COEX_MODE_WIFI_ALONE;
930-
common->oper_mode = RSI_DEV_OPMODE_WIFI_ALONE;
931-
adapter->device_model = RSI_DEV_9113;
932-
933934
switch (adapter->device_model) {
934935
case RSI_DEV_9113:
935936
if (rsi_load_firmware(adapter)) {

drivers/net/wireless/rsi/rsi_91x_main.c

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include <linux/firmware.h>
2121
#include "rsi_mgmt.h"
2222
#include "rsi_common.h"
23+
#include "rsi_coex.h"
2324
#include "rsi_hal.h"
2425

2526
u32 rsi_zone_enabled = /* INFO_ZONE |
@@ -160,8 +161,15 @@ int rsi_read_pkt(struct rsi_common *common, u8 *rx_pkt, s32 rcv_pkt_len)
160161

161162
switch (queueno) {
162163
case RSI_COEX_Q:
163-
rsi_mgmt_pkt_recv(common, (frame_desc + offset));
164+
#ifdef CONFIG_RSI_COEX
165+
if (common->coex_mode > 1)
166+
rsi_coex_recv_pkt(common, frame_desc + offset);
167+
else
168+
#endif
169+
rsi_mgmt_pkt_recv(common,
170+
(frame_desc + offset));
164171
break;
172+
165173
case RSI_WIFI_DATA_Q:
166174
skb = rsi_prepare_skb(common,
167175
(frame_desc + offset),
@@ -217,6 +225,15 @@ static void rsi_tx_scheduler_thread(struct rsi_common *common)
217225
complete_and_exit(&common->tx_thread.completion, 0);
218226
}
219227

228+
#ifdef CONFIG_RSI_COEX
229+
enum rsi_host_intf rsi_get_host_intf(void *priv)
230+
{
231+
struct rsi_common *common = (struct rsi_common *)priv;
232+
233+
return common->priv->rsi_host_intf;
234+
}
235+
#endif
236+
220237
/**
221238
* rsi_91x_init() - This function initializes os interface operations.
222239
* @void: Void.
@@ -251,6 +268,7 @@ struct rsi_hw *rsi_91x_init(void)
251268
mutex_init(&common->mutex);
252269
mutex_init(&common->tx_lock);
253270
mutex_init(&common->rx_lock);
271+
mutex_init(&common->tx_bus_mutex);
254272

255273
if (rsi_create_kthread(common,
256274
&common->tx_thread,
@@ -265,6 +283,19 @@ struct rsi_hw *rsi_91x_init(void)
265283
timer_setup(&common->roc_timer, rsi_roc_timeout, 0);
266284
init_completion(&common->wlan_init_completion);
267285
common->init_done = true;
286+
287+
common->coex_mode = RSI_DEV_COEX_MODE_WIFI_ALONE;
288+
common->oper_mode = RSI_DEV_OPMODE_WIFI_ALONE;
289+
adapter->device_model = RSI_DEV_9113;
290+
#ifdef CONFIG_RSI_COEX
291+
if (common->coex_mode > 1) {
292+
if (rsi_coex_attach(common)) {
293+
rsi_dbg(ERR_ZONE, "Failed to init coex module\n");
294+
goto err;
295+
}
296+
}
297+
#endif
298+
268299
return adapter;
269300

270301
err:
@@ -294,6 +325,11 @@ void rsi_91x_deinit(struct rsi_hw *adapter)
294325

295326
common->init_done = false;
296327

328+
#ifdef CONFIG_RSI_COEX
329+
if (common->coex_mode > 1)
330+
rsi_coex_detach(common);
331+
#endif
332+
297333
kfree(common);
298334
kfree(adapter->rsi_dev);
299335
kfree(adapter);

drivers/net/wireless/rsi/rsi_91x_mgmt.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1791,7 +1791,7 @@ static int rsi_handle_ta_confirm_type(struct rsi_common *common,
17911791
return -EINVAL;
17921792
}
17931793

1794-
static int rsi_handle_card_ready(struct rsi_common *common, u8 *msg)
1794+
int rsi_handle_card_ready(struct rsi_common *common, u8 *msg)
17951795
{
17961796
switch (common->fsm_state) {
17971797
case FSM_CARD_NOT_READY:

drivers/net/wireless/rsi/rsi_91x_sdio.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include <linux/module.h>
1919
#include "rsi_sdio.h"
2020
#include "rsi_common.h"
21+
#include "rsi_coex.h"
2122
#include "rsi_hal.h"
2223

2324
/**

drivers/net/wireless/rsi/rsi_91x_usb.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,10 @@
1616
*/
1717

1818
#include <linux/module.h>
19+
#include <net/rsi_91x.h>
1920
#include "rsi_usb.h"
2021
#include "rsi_hal.h"
22+
#include "rsi_coex.h"
2123

2224
/**
2325
* rsi_usb_card_write() - This function writes to the USB Card.
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
/**
2+
* Copyright (c) 2018 Redpine Signals Inc.
3+
*
4+
* Permission to use, copy, modify, and/or distribute this software for any
5+
* purpose with or without fee is hereby granted, provided that the above
6+
* copyright notice and this permission notice appear in all copies.
7+
*
8+
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9+
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10+
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11+
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12+
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13+
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14+
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15+
*/
16+
17+
#ifndef __RSI_COEX_H__
18+
#define __RSI_COEX_H__
19+
20+
#include "rsi_common.h"
21+
22+
#ifdef CONFIG_RSI_COEX
23+
#define COMMON_CARD_READY_IND 0
24+
#define NUM_COEX_TX_QUEUES 5
25+
26+
struct rsi_coex_ctrl_block {
27+
struct rsi_common *priv;
28+
struct sk_buff_head coex_tx_qs[NUM_COEX_TX_QUEUES];
29+
struct rsi_thread coex_tx_thread;
30+
};
31+
32+
int rsi_coex_attach(struct rsi_common *common);
33+
void rsi_coex_detach(struct rsi_common *common);
34+
int rsi_coex_send_pkt(void *priv, struct sk_buff *skb, u8 proto_type);
35+
int rsi_coex_recv_pkt(struct rsi_common *common, u8 *msg);
36+
#endif
37+
#endif

0 commit comments

Comments
 (0)