Message ID | 1519394098-24220-5-git-send-email-amitkarwar@gmail.com (mailing list archive) |
---|---|
State | Superseded |
Delegated to: | Kalle Valo |
Headers | show |
Hi Prameela, Thank you for the patch! Yet something to improve: [auto build test ERROR on wireless-drivers-next/master] [also build test ERROR on v4.16-rc2 next-20180223] [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/Amitkumar-Karwar/rsi-add-bluetooth-and-coex-support/20180226-073244 base: https://git.kernel.org/pub/scm/linux/kernel/git/kvalo/wireless-drivers-next.git master config: sh-allmodconfig (attached as .config) compiler: sh4-linux-gnu-gcc (Debian 7.2.0-11) 7.2.0 reproduce: wget https://raw.githubusercontent.com/intel/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=sh Note: the linux-review/Amitkumar-Karwar/rsi-add-bluetooth-and-coex-support/20180226-073244 HEAD 9c5222af2b3dbf5143bc1fa4dc0af78fcfa3559d builds fine. It only hurts bisectibility. All errors (new ones prefixed by >>): drivers/net//wireless/rsi/rsi_91x_main.c: In function 'rsi_read_pkt': >> drivers/net//wireless/rsi/rsi_91x_main.c:165:5: error: implicit declaration of function 'rsi_coex_recv_pkt'; did you mean 'rsi_read_pkt'? [-Werror=implicit-function-declaration] rsi_coex_recv_pkt(common, frame_desc + offset); ^~~~~~~~~~~~~~~~~ rsi_read_pkt drivers/net//wireless/rsi/rsi_91x_main.c: In function 'rsi_91x_init': >> drivers/net//wireless/rsi/rsi_91x_main.c:287:7: error: implicit declaration of function 'rsi_coex_attach'; did you mean 'driver_attach'? [-Werror=implicit-function-declaration] if (rsi_coex_attach(common)) { ^~~~~~~~~~~~~~~ driver_attach drivers/net//wireless/rsi/rsi_91x_main.c: In function 'rsi_91x_deinit': >> drivers/net//wireless/rsi/rsi_91x_main.c:323:3: error: implicit declaration of function 'rsi_coex_detach'; did you mean 'rsi_91x_deinit'? [-Werror=implicit-function-declaration] rsi_coex_detach(common); ^~~~~~~~~~~~~~~ rsi_91x_deinit cc1: some warnings being treated as errors vim +165 drivers/net//wireless/rsi/rsi_91x_main.c 133 134 /** 135 * rsi_read_pkt() - This function reads frames from the card. 136 * @common: Pointer to the driver private structure. 137 * @rcv_pkt_len: Received pkt length. In case of USB it is 0. 138 * 139 * Return: 0 on success, -1 on failure. 140 */ 141 int rsi_read_pkt(struct rsi_common *common, u8 *rx_pkt, s32 rcv_pkt_len) 142 { 143 u8 *frame_desc = NULL, extended_desc = 0; 144 u32 index, length = 0, queueno = 0; 145 u16 actual_length = 0, offset; 146 struct sk_buff *skb = NULL; 147 148 index = 0; 149 do { 150 frame_desc = &rx_pkt[index]; 151 actual_length = *(u16 *)&frame_desc[0]; 152 offset = *(u16 *)&frame_desc[2]; 153 154 queueno = rsi_get_queueno(frame_desc, offset); 155 length = rsi_get_length(frame_desc, offset); 156 157 /* Extended descriptor is valid for WLAN queues only */ 158 if (queueno == RSI_WIFI_DATA_Q || queueno == RSI_WIFI_MGMT_Q) 159 extended_desc = rsi_get_extended_desc(frame_desc, 160 offset); 161 162 switch (queueno) { 163 case RSI_COEX_Q: 164 if (common->coex_mode > 1) > 165 rsi_coex_recv_pkt(common, frame_desc + offset); 166 else 167 rsi_mgmt_pkt_recv(common, 168 (frame_desc + offset)); 169 break; 170 171 case RSI_WIFI_DATA_Q: 172 skb = rsi_prepare_skb(common, 173 (frame_desc + offset), 174 length, 175 extended_desc); 176 if (skb == NULL) 177 goto fail; 178 179 rsi_indicate_pkt_to_os(common, skb); 180 break; 181 182 case RSI_WIFI_MGMT_Q: 183 rsi_mgmt_pkt_recv(common, (frame_desc + offset)); 184 break; 185 186 default: 187 rsi_dbg(ERR_ZONE, "%s: pkt from invalid queue: %d\n", 188 __func__, queueno); 189 goto fail; 190 } 191 192 index += actual_length; 193 rcv_pkt_len -= actual_length; 194 } while (rcv_pkt_len > 0); 195 196 return 0; 197 fail: 198 return -EINVAL; 199 } 200 EXPORT_SYMBOL_GPL(rsi_read_pkt); 201 202 /** 203 * rsi_tx_scheduler_thread() - This function is a kernel thread to send the 204 * packets to the device. 205 * @common: Pointer to the driver private structure. 206 * 207 * Return: None. 208 */ 209 static void rsi_tx_scheduler_thread(struct rsi_common *common) 210 { 211 struct rsi_hw *adapter = common->priv; 212 u32 timeout = EVENT_WAIT_FOREVER; 213 214 do { 215 if (adapter->determine_event_timeout) 216 timeout = adapter->determine_event_timeout(adapter); 217 rsi_wait_event(&common->tx_thread.event, timeout); 218 rsi_reset_event(&common->tx_thread.event); 219 220 if (common->init_done) 221 rsi_core_qos_processor(common); 222 } while (atomic_read(&common->tx_thread.thread_done) == 0); 223 complete_and_exit(&common->tx_thread.completion, 0); 224 } 225 226 enum rsi_host_intf rsi_get_host_intf(void *priv) 227 { 228 struct rsi_common *common = (struct rsi_common *)priv; 229 230 return common->priv->rsi_host_intf; 231 } 232 233 /** 234 * rsi_91x_init() - This function initializes os interface operations. 235 * @void: Void. 236 * 237 * Return: Pointer to the adapter structure on success, NULL on failure . 238 */ 239 struct rsi_hw *rsi_91x_init(void) 240 { 241 struct rsi_hw *adapter = NULL; 242 struct rsi_common *common = NULL; 243 u8 ii = 0; 244 245 adapter = kzalloc(sizeof(*adapter), GFP_KERNEL); 246 if (!adapter) 247 return NULL; 248 249 adapter->priv = kzalloc(sizeof(*common), GFP_KERNEL); 250 if (adapter->priv == NULL) { 251 rsi_dbg(ERR_ZONE, "%s: Failed in allocation of memory\n", 252 __func__); 253 kfree(adapter); 254 return NULL; 255 } else { 256 common = adapter->priv; 257 common->priv = adapter; 258 } 259 260 for (ii = 0; ii < NUM_SOFT_QUEUES; ii++) 261 skb_queue_head_init(&common->tx_queue[ii]); 262 263 rsi_init_event(&common->tx_thread.event); 264 mutex_init(&common->mutex); 265 mutex_init(&common->tx_lock); 266 mutex_init(&common->rx_lock); 267 mutex_init(&common->tx_bus_mutex); 268 269 if (rsi_create_kthread(common, 270 &common->tx_thread, 271 rsi_tx_scheduler_thread, 272 "Tx-Thread")) { 273 rsi_dbg(ERR_ZONE, "%s: Unable to init tx thrd\n", __func__); 274 goto err; 275 } 276 277 rsi_default_ps_params(adapter); 278 spin_lock_init(&adapter->ps_lock); 279 timer_setup(&common->roc_timer, rsi_roc_timeout, 0); 280 init_completion(&common->wlan_init_completion); 281 common->init_done = true; 282 283 common->coex_mode = RSI_DEV_COEX_MODE_WIFI_ALONE; 284 common->oper_mode = RSI_DEV_OPMODE_WIFI_ALONE; 285 adapter->device_model = RSI_DEV_9113; 286 if (common->coex_mode > 1) { > 287 if (rsi_coex_attach(common)) { 288 rsi_dbg(ERR_ZONE, "Failed to init coex module\n"); 289 goto err; 290 } 291 } 292 293 return adapter; 294 295 err: 296 kfree(common); 297 kfree(adapter); 298 return NULL; 299 } 300 EXPORT_SYMBOL_GPL(rsi_91x_init); 301 302 /** 303 * rsi_91x_deinit() - This function de-intializes os intf operations. 304 * @adapter: Pointer to the adapter structure. 305 * 306 * Return: None. 307 */ 308 void rsi_91x_deinit(struct rsi_hw *adapter) 309 { 310 struct rsi_common *common = adapter->priv; 311 u8 ii; 312 313 rsi_dbg(INFO_ZONE, "%s: Performing deinit os ops\n", __func__); 314 315 rsi_kill_thread(&common->tx_thread); 316 317 for (ii = 0; ii < NUM_SOFT_QUEUES; ii++) 318 skb_queue_purge(&common->tx_queue[ii]); 319 320 common->init_done = false; 321 322 if (common->coex_mode > 1) > 323 rsi_coex_detach(common); 324 325 kfree(common); 326 kfree(adapter->rsi_dev); 327 kfree(adapter); 328 } 329 EXPORT_SYMBOL_GPL(rsi_91x_deinit); 330 --- 0-DAY kernel test infrastructure Open Source Technology Center https://lists.01.org/pipermail/kbuild-all Intel Corporation
Hi Prameela, Thank you for the patch! Yet something to improve: [auto build test ERROR on wireless-drivers-next/master] [also build test ERROR on v4.16-rc3 next-20180223] [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/Amitkumar-Karwar/rsi-add-bluetooth-and-coex-support/20180226-073244 base: https://git.kernel.org/pub/scm/linux/kernel/git/kvalo/wireless-drivers-next.git master config: x86_64-randconfig-ne0-02261019 (attached as .config) compiler: gcc-6 (Debian 6.4.0-9) 6.4.0 20171026 reproduce: # save the attached .config to linux build tree make ARCH=x86_64 Note: the linux-review/Amitkumar-Karwar/rsi-add-bluetooth-and-coex-support/20180226-073244 HEAD 9c5222af2b3dbf5143bc1fa4dc0af78fcfa3559d builds fine. It only hurts bisectibility. All errors (new ones prefixed by >>): drivers/net/wireless/rsi/rsi_91x_main.c: In function 'rsi_read_pkt': >> drivers/net/wireless/rsi/rsi_91x_main.c:165:5: error: implicit declaration of function 'rsi_coex_recv_pkt' [-Werror=implicit-function-declaration] rsi_coex_recv_pkt(common, frame_desc + offset); ^~~~~~~~~~~~~~~~~ drivers/net/wireless/rsi/rsi_91x_main.c: In function 'rsi_91x_init': >> drivers/net/wireless/rsi/rsi_91x_main.c:287:7: error: implicit declaration of function 'rsi_coex_attach' [-Werror=implicit-function-declaration] if (rsi_coex_attach(common)) { ^~~~~~~~~~~~~~~ drivers/net/wireless/rsi/rsi_91x_main.c: In function 'rsi_91x_deinit': >> drivers/net/wireless/rsi/rsi_91x_main.c:323:3: error: implicit declaration of function 'rsi_coex_detach' [-Werror=implicit-function-declaration] rsi_coex_detach(common); ^~~~~~~~~~~~~~~ cc1: some warnings being treated as errors vim +/rsi_coex_recv_pkt +165 drivers/net/wireless/rsi/rsi_91x_main.c 133 134 /** 135 * rsi_read_pkt() - This function reads frames from the card. 136 * @common: Pointer to the driver private structure. 137 * @rcv_pkt_len: Received pkt length. In case of USB it is 0. 138 * 139 * Return: 0 on success, -1 on failure. 140 */ 141 int rsi_read_pkt(struct rsi_common *common, u8 *rx_pkt, s32 rcv_pkt_len) 142 { 143 u8 *frame_desc = NULL, extended_desc = 0; 144 u32 index, length = 0, queueno = 0; 145 u16 actual_length = 0, offset; 146 struct sk_buff *skb = NULL; 147 148 index = 0; 149 do { 150 frame_desc = &rx_pkt[index]; 151 actual_length = *(u16 *)&frame_desc[0]; 152 offset = *(u16 *)&frame_desc[2]; 153 154 queueno = rsi_get_queueno(frame_desc, offset); 155 length = rsi_get_length(frame_desc, offset); 156 157 /* Extended descriptor is valid for WLAN queues only */ 158 if (queueno == RSI_WIFI_DATA_Q || queueno == RSI_WIFI_MGMT_Q) 159 extended_desc = rsi_get_extended_desc(frame_desc, 160 offset); 161 162 switch (queueno) { 163 case RSI_COEX_Q: 164 if (common->coex_mode > 1) > 165 rsi_coex_recv_pkt(common, frame_desc + offset); 166 else 167 rsi_mgmt_pkt_recv(common, 168 (frame_desc + offset)); 169 break; 170 171 case RSI_WIFI_DATA_Q: 172 skb = rsi_prepare_skb(common, 173 (frame_desc + offset), 174 length, 175 extended_desc); 176 if (skb == NULL) 177 goto fail; 178 179 rsi_indicate_pkt_to_os(common, skb); 180 break; 181 182 case RSI_WIFI_MGMT_Q: 183 rsi_mgmt_pkt_recv(common, (frame_desc + offset)); 184 break; 185 186 default: 187 rsi_dbg(ERR_ZONE, "%s: pkt from invalid queue: %d\n", 188 __func__, queueno); 189 goto fail; 190 } 191 192 index += actual_length; 193 rcv_pkt_len -= actual_length; 194 } while (rcv_pkt_len > 0); 195 196 return 0; 197 fail: 198 return -EINVAL; 199 } 200 EXPORT_SYMBOL_GPL(rsi_read_pkt); 201 202 /** 203 * rsi_tx_scheduler_thread() - This function is a kernel thread to send the 204 * packets to the device. 205 * @common: Pointer to the driver private structure. 206 * 207 * Return: None. 208 */ 209 static void rsi_tx_scheduler_thread(struct rsi_common *common) 210 { 211 struct rsi_hw *adapter = common->priv; 212 u32 timeout = EVENT_WAIT_FOREVER; 213 214 do { 215 if (adapter->determine_event_timeout) 216 timeout = adapter->determine_event_timeout(adapter); 217 rsi_wait_event(&common->tx_thread.event, timeout); 218 rsi_reset_event(&common->tx_thread.event); 219 220 if (common->init_done) 221 rsi_core_qos_processor(common); 222 } while (atomic_read(&common->tx_thread.thread_done) == 0); 223 complete_and_exit(&common->tx_thread.completion, 0); 224 } 225 226 enum rsi_host_intf rsi_get_host_intf(void *priv) 227 { 228 struct rsi_common *common = (struct rsi_common *)priv; 229 230 return common->priv->rsi_host_intf; 231 } 232 233 /** 234 * rsi_91x_init() - This function initializes os interface operations. 235 * @void: Void. 236 * 237 * Return: Pointer to the adapter structure on success, NULL on failure . 238 */ 239 struct rsi_hw *rsi_91x_init(void) 240 { 241 struct rsi_hw *adapter = NULL; 242 struct rsi_common *common = NULL; 243 u8 ii = 0; 244 245 adapter = kzalloc(sizeof(*adapter), GFP_KERNEL); 246 if (!adapter) 247 return NULL; 248 249 adapter->priv = kzalloc(sizeof(*common), GFP_KERNEL); 250 if (adapter->priv == NULL) { 251 rsi_dbg(ERR_ZONE, "%s: Failed in allocation of memory\n", 252 __func__); 253 kfree(adapter); 254 return NULL; 255 } else { 256 common = adapter->priv; 257 common->priv = adapter; 258 } 259 260 for (ii = 0; ii < NUM_SOFT_QUEUES; ii++) 261 skb_queue_head_init(&common->tx_queue[ii]); 262 263 rsi_init_event(&common->tx_thread.event); 264 mutex_init(&common->mutex); 265 mutex_init(&common->tx_lock); 266 mutex_init(&common->rx_lock); 267 mutex_init(&common->tx_bus_mutex); 268 269 if (rsi_create_kthread(common, 270 &common->tx_thread, 271 rsi_tx_scheduler_thread, 272 "Tx-Thread")) { 273 rsi_dbg(ERR_ZONE, "%s: Unable to init tx thrd\n", __func__); 274 goto err; 275 } 276 277 rsi_default_ps_params(adapter); 278 spin_lock_init(&adapter->ps_lock); 279 timer_setup(&common->roc_timer, rsi_roc_timeout, 0); 280 init_completion(&common->wlan_init_completion); 281 common->init_done = true; 282 283 common->coex_mode = RSI_DEV_COEX_MODE_WIFI_ALONE; 284 common->oper_mode = RSI_DEV_OPMODE_WIFI_ALONE; 285 adapter->device_model = RSI_DEV_9113; 286 if (common->coex_mode > 1) { > 287 if (rsi_coex_attach(common)) { 288 rsi_dbg(ERR_ZONE, "Failed to init coex module\n"); 289 goto err; 290 } 291 } 292 293 return adapter; 294 295 err: 296 kfree(common); 297 kfree(adapter); 298 return NULL; 299 } 300 EXPORT_SYMBOL_GPL(rsi_91x_init); 301 302 /** 303 * rsi_91x_deinit() - This function de-intializes os intf operations. 304 * @adapter: Pointer to the adapter structure. 305 * 306 * Return: None. 307 */ 308 void rsi_91x_deinit(struct rsi_hw *adapter) 309 { 310 struct rsi_common *common = adapter->priv; 311 u8 ii; 312 313 rsi_dbg(INFO_ZONE, "%s: Performing deinit os ops\n", __func__); 314 315 rsi_kill_thread(&common->tx_thread); 316 317 for (ii = 0; ii < NUM_SOFT_QUEUES; ii++) 318 skb_queue_purge(&common->tx_queue[ii]); 319 320 common->init_done = false; 321 322 if (common->coex_mode > 1) > 323 rsi_coex_detach(common); 324 325 kfree(common); 326 kfree(adapter->rsi_dev); 327 kfree(adapter); 328 } 329 EXPORT_SYMBOL_GPL(rsi_91x_deinit); 330 --- 0-DAY kernel test infrastructure Open Source Technology Center https://lists.01.org/pipermail/kbuild-all Intel Corporation
diff --git a/drivers/net/wireless/rsi/Kconfig b/drivers/net/wireless/rsi/Kconfig index 7c5e4ca..e6135ee 100644 --- a/drivers/net/wireless/rsi/Kconfig +++ b/drivers/net/wireless/rsi/Kconfig @@ -42,4 +42,13 @@ config RSI_USB This option enables the USB bus support in rsi drivers. Select M (recommended), if you have a RSI 1x1 wireless module. +config RSI_COEX + bool "Redpine Signals WLAN BT Coexistence support" + depends on BT_HCIRSI && RSI_91X + default y + ---help--- + This option enables the WLAN BT coex support in rsi drivers. + Select M (recommended), if you have want to use this feature + and you have RS9113 module. + endif # WLAN_VENDOR_RSI diff --git a/drivers/net/wireless/rsi/Makefile b/drivers/net/wireless/rsi/Makefile index 47c4590..ff87121a 100644 --- a/drivers/net/wireless/rsi/Makefile +++ b/drivers/net/wireless/rsi/Makefile @@ -5,6 +5,7 @@ rsi_91x-y += rsi_91x_mac80211.o rsi_91x-y += rsi_91x_mgmt.o rsi_91x-y += rsi_91x_hal.o rsi_91x-y += rsi_91x_ps.o +rsi_91x-$(CONFIG_RSI_COEX) += rsi_91x_coex.o rsi_91x-$(CONFIG_RSI_DEBUGFS) += rsi_91x_debugfs.o rsi_usb-y += rsi_91x_usb.o rsi_91x_usb_ops.o diff --git a/drivers/net/wireless/rsi/rsi_91x_coex.c b/drivers/net/wireless/rsi/rsi_91x_coex.c new file mode 100644 index 0000000..c07e839 --- /dev/null +++ b/drivers/net/wireless/rsi/rsi_91x_coex.c @@ -0,0 +1,177 @@ +/** + * Copyright (c) 2018 Redpine Signals Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "rsi_main.h" +#include "rsi_coex.h" +#include "rsi_mgmt.h" +#include "rsi_hal.h" + +static enum rsi_coex_queues rsi_coex_determine_coex_q + (struct rsi_coex_ctrl_block *coex_cb) +{ + enum rsi_coex_queues q_num = RSI_COEX_Q_INVALID; + + if (skb_queue_len(&coex_cb->coex_tx_qs[RSI_COEX_Q_COMMON]) > 0) + q_num = RSI_COEX_Q_COMMON; + if (skb_queue_len(&coex_cb->coex_tx_qs[RSI_COEX_Q_BT]) > 0) + q_num = RSI_COEX_Q_BT; + if (skb_queue_len(&coex_cb->coex_tx_qs[RSI_COEX_Q_WLAN]) > 0) + q_num = RSI_COEX_Q_WLAN; + + return q_num; +} + +static void rsi_coex_sched_tx_pkts(struct rsi_coex_ctrl_block *coex_cb) +{ + enum rsi_coex_queues coex_q = RSI_COEX_Q_INVALID; + struct sk_buff *skb; + + do { + coex_q = rsi_coex_determine_coex_q(coex_cb); + rsi_dbg(INFO_ZONE, "queue = %d\n", coex_q); + + if (coex_q == RSI_COEX_Q_BT) + skb = skb_dequeue(&coex_cb->coex_tx_qs[RSI_COEX_Q_BT]); + } while (coex_q != RSI_COEX_Q_INVALID); +} + +static void rsi_coex_scheduler_thread(struct rsi_common *common) +{ + struct rsi_coex_ctrl_block *coex_cb = + (struct rsi_coex_ctrl_block *)common->coex_cb; + u32 timeout = EVENT_WAIT_FOREVER; + + do { + rsi_wait_event(&coex_cb->coex_tx_thread.event, timeout); + rsi_reset_event(&coex_cb->coex_tx_thread.event); + + rsi_coex_sched_tx_pkts(coex_cb); + } while (atomic_read(&coex_cb->coex_tx_thread.thread_done) == 0); + + complete_and_exit(&coex_cb->coex_tx_thread.completion, 0); +} + +int rsi_coex_recv_pkt(struct rsi_common *common, u8 *msg) +{ + u8 msg_type = msg[RSI_RX_DESC_MSG_TYPE_OFFSET]; + + switch (msg_type) { + case COMMON_CARD_READY_IND: + rsi_dbg(INFO_ZONE, "common card ready received\n"); + rsi_handle_card_ready(common, msg); + break; + case SLEEP_NOTIFY_IND: + rsi_dbg(INFO_ZONE, "sleep notify received\n"); + rsi_mgmt_pkt_recv(common, msg); + break; + } + + return 0; +} + +static inline int rsi_map_coex_q(u8 hal_queue) +{ + switch (hal_queue) { + case RSI_COEX_Q: + return RSI_COEX_Q_COMMON; + case RSI_WLAN_Q: + return RSI_COEX_Q_WLAN; + case RSI_BT_Q: + return RSI_COEX_Q_BT; + } + return RSI_COEX_Q_INVALID; +} + +int rsi_coex_send_pkt(void *priv, struct sk_buff *skb, u8 hal_queue) +{ + struct rsi_common *common = (struct rsi_common *)priv; + struct rsi_coex_ctrl_block *coex_cb = + (struct rsi_coex_ctrl_block *)common->coex_cb; + struct skb_info *tx_params = NULL; + enum rsi_coex_queues coex_q; + int status; + + coex_q = rsi_map_coex_q(hal_queue); + if (coex_q == RSI_COEX_Q_INVALID) { + rsi_dbg(ERR_ZONE, "Invalid coex queue\n"); + return -EINVAL; + } + if (coex_q != RSI_COEX_Q_COMMON && + coex_q != RSI_COEX_Q_WLAN) { + skb_queue_tail(&coex_cb->coex_tx_qs[coex_q], skb); + rsi_set_event(&coex_cb->coex_tx_thread.event); + return 0; + } + if (common->iface_down) { + tx_params = + (struct skb_info *)&IEEE80211_SKB_CB(skb)->driver_data; + + if (!(tx_params->flags & INTERNAL_MGMT_PKT)) { + rsi_indicate_tx_status(common->priv, skb, -EINVAL); + return 0; + } + } + + /* Send packet to hal */ + if (skb->priority == MGMT_SOFT_Q) + status = rsi_send_mgmt_pkt(common, skb); + else + status = rsi_send_data_pkt(common, skb); + + return status; +} + +int rsi_coex_attach(struct rsi_common *common) +{ + struct rsi_coex_ctrl_block *coex_cb; + int cnt; + + coex_cb = kzalloc(sizeof(*coex_cb), GFP_KERNEL); + if (!coex_cb) + return -ENOMEM; + + common->coex_cb = (void *)coex_cb; + coex_cb->priv = common; + + /* Initialize co-ex queues */ + for (cnt = 0; cnt < NUM_COEX_TX_QUEUES; cnt++) + skb_queue_head_init(&coex_cb->coex_tx_qs[cnt]); + rsi_init_event(&coex_cb->coex_tx_thread.event); + + /* Initialize co-ex thread */ + if (rsi_create_kthread(common, + &coex_cb->coex_tx_thread, + rsi_coex_scheduler_thread, + "Coex-Tx-Thread")) { + rsi_dbg(ERR_ZONE, "%s: Unable to init tx thrd\n", __func__); + return -EINVAL; + } + return 0; +} + +void rsi_coex_detach(struct rsi_common *common) +{ + struct rsi_coex_ctrl_block *coex_cb = + (struct rsi_coex_ctrl_block *)common->coex_cb; + int cnt; + + rsi_kill_thread(&coex_cb->coex_tx_thread); + + for (cnt = 0; cnt < NUM_COEX_TX_QUEUES; cnt++) + skb_queue_purge(&coex_cb->coex_tx_qs[cnt]); + + kfree(coex_cb); +} diff --git a/drivers/net/wireless/rsi/rsi_91x_hal.c b/drivers/net/wireless/rsi/rsi_91x_hal.c index 1176de6..151d228 100644 --- a/drivers/net/wireless/rsi/rsi_91x_hal.c +++ b/drivers/net/wireless/rsi/rsi_91x_hal.c @@ -31,8 +31,15 @@ int rsi_send_pkt_to_bus(struct rsi_common *common, struct sk_buff *skb) struct rsi_hw *adapter = common->priv; int status; + if (common->coex_mode > 1) + mutex_lock(&common->tx_bus_mutex); + status = adapter->host_intf_ops->write_pkt(common->priv, skb->data, skb->len); + + if (common->coex_mode > 1) + mutex_unlock(&common->tx_bus_mutex); + return status; } @@ -296,8 +303,7 @@ int rsi_send_data_pkt(struct rsi_common *common, struct sk_buff *skb) if (status) goto err; - status = adapter->host_intf_ops->write_pkt(common->priv, skb->data, - skb->len); + status = rsi_send_pkt_to_bus(common, skb); if (status) rsi_dbg(ERR_ZONE, "%s: Failed to write pkt\n", __func__); @@ -342,8 +348,7 @@ int rsi_send_mgmt_pkt(struct rsi_common *common, goto err; rsi_prepare_mgmt_desc(common, skb); - status = adapter->host_intf_ops->write_pkt(common->priv, - (u8 *)skb->data, skb->len); + status = rsi_send_pkt_to_bus(common, skb); if (status) rsi_dbg(ERR_ZONE, "%s: Failed to write the packet\n", __func__); @@ -926,10 +931,6 @@ int rsi_hal_device_init(struct rsi_hw *adapter) { struct rsi_common *common = adapter->priv; - common->coex_mode = RSI_DEV_COEX_MODE_WIFI_ALONE; - common->oper_mode = RSI_DEV_OPMODE_WIFI_ALONE; - adapter->device_model = RSI_DEV_9113; - switch (adapter->device_model) { case RSI_DEV_9113: if (rsi_load_firmware(adapter)) { diff --git a/drivers/net/wireless/rsi/rsi_91x_main.c b/drivers/net/wireless/rsi/rsi_91x_main.c index 0413af8..fe08ebc 100644 --- a/drivers/net/wireless/rsi/rsi_91x_main.c +++ b/drivers/net/wireless/rsi/rsi_91x_main.c @@ -20,6 +20,7 @@ #include <linux/firmware.h> #include "rsi_mgmt.h" #include "rsi_common.h" +#include "rsi_coex.h" #include "rsi_hal.h" u32 rsi_zone_enabled = /* INFO_ZONE | @@ -160,8 +161,13 @@ int rsi_read_pkt(struct rsi_common *common, u8 *rx_pkt, s32 rcv_pkt_len) switch (queueno) { case RSI_COEX_Q: - rsi_mgmt_pkt_recv(common, (frame_desc + offset)); + if (common->coex_mode > 1) + rsi_coex_recv_pkt(common, frame_desc + offset); + else + rsi_mgmt_pkt_recv(common, + (frame_desc + offset)); break; + case RSI_WIFI_DATA_Q: skb = rsi_prepare_skb(common, (frame_desc + offset), @@ -217,6 +223,13 @@ static void rsi_tx_scheduler_thread(struct rsi_common *common) complete_and_exit(&common->tx_thread.completion, 0); } +enum rsi_host_intf rsi_get_host_intf(void *priv) +{ + struct rsi_common *common = (struct rsi_common *)priv; + + return common->priv->rsi_host_intf; +} + /** * rsi_91x_init() - This function initializes os interface operations. * @void: Void. @@ -251,6 +264,7 @@ struct rsi_hw *rsi_91x_init(void) mutex_init(&common->mutex); mutex_init(&common->tx_lock); mutex_init(&common->rx_lock); + mutex_init(&common->tx_bus_mutex); if (rsi_create_kthread(common, &common->tx_thread, @@ -265,6 +279,17 @@ struct rsi_hw *rsi_91x_init(void) timer_setup(&common->roc_timer, rsi_roc_timeout, 0); init_completion(&common->wlan_init_completion); common->init_done = true; + + common->coex_mode = RSI_DEV_COEX_MODE_WIFI_ALONE; + common->oper_mode = RSI_DEV_OPMODE_WIFI_ALONE; + adapter->device_model = RSI_DEV_9113; + if (common->coex_mode > 1) { + if (rsi_coex_attach(common)) { + rsi_dbg(ERR_ZONE, "Failed to init coex module\n"); + goto err; + } + } + return adapter; err: @@ -294,6 +319,9 @@ void rsi_91x_deinit(struct rsi_hw *adapter) common->init_done = false; + if (common->coex_mode > 1) + rsi_coex_detach(common); + kfree(common); kfree(adapter->rsi_dev); kfree(adapter); diff --git a/drivers/net/wireless/rsi/rsi_91x_mgmt.c b/drivers/net/wireless/rsi/rsi_91x_mgmt.c index 46c9d54..c21fca7 100644 --- a/drivers/net/wireless/rsi/rsi_91x_mgmt.c +++ b/drivers/net/wireless/rsi/rsi_91x_mgmt.c @@ -1791,7 +1791,7 @@ static int rsi_handle_ta_confirm_type(struct rsi_common *common, return -EINVAL; } -static int rsi_handle_card_ready(struct rsi_common *common, u8 *msg) +int rsi_handle_card_ready(struct rsi_common *common, u8 *msg) { switch (common->fsm_state) { case FSM_CARD_NOT_READY: diff --git a/drivers/net/wireless/rsi/rsi_91x_sdio.c b/drivers/net/wireless/rsi/rsi_91x_sdio.c index b0cf411..ba38c6d 100644 --- a/drivers/net/wireless/rsi/rsi_91x_sdio.c +++ b/drivers/net/wireless/rsi/rsi_91x_sdio.c @@ -18,6 +18,7 @@ #include <linux/module.h> #include "rsi_sdio.h" #include "rsi_common.h" +#include "rsi_coex.h" #include "rsi_hal.h" /** diff --git a/drivers/net/wireless/rsi/rsi_91x_usb.c b/drivers/net/wireless/rsi/rsi_91x_usb.c index 9ab86fb..b33a05f 100644 --- a/drivers/net/wireless/rsi/rsi_91x_usb.c +++ b/drivers/net/wireless/rsi/rsi_91x_usb.c @@ -16,8 +16,10 @@ */ #include <linux/module.h> +#include <net/rsi_91x.h> #include "rsi_usb.h" #include "rsi_hal.h" +#include "rsi_coex.h" /** * rsi_usb_card_write() - This function writes to the USB Card. diff --git a/drivers/net/wireless/rsi/rsi_coex.h b/drivers/net/wireless/rsi/rsi_coex.h new file mode 100644 index 0000000..0fdc67f --- /dev/null +++ b/drivers/net/wireless/rsi/rsi_coex.h @@ -0,0 +1,37 @@ +/** + * Copyright (c) 2018 Redpine Signals Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef __RSI_COEX_H__ +#define __RSI_COEX_H__ + +#include "rsi_common.h" + +#ifdef CONFIG_RSI_COEX +#define COMMON_CARD_READY_IND 0 +#define NUM_COEX_TX_QUEUES 5 + +struct rsi_coex_ctrl_block { + struct rsi_common *priv; + struct sk_buff_head coex_tx_qs[NUM_COEX_TX_QUEUES]; + struct rsi_thread coex_tx_thread; +}; + +int rsi_coex_attach(struct rsi_common *common); +void rsi_coex_detach(struct rsi_common *common); +int rsi_coex_send_pkt(void *priv, struct sk_buff *skb, u8 proto_type); +int rsi_coex_recv_pkt(struct rsi_common *common, u8 *msg); +#endif +#endif diff --git a/drivers/net/wireless/rsi/rsi_main.h b/drivers/net/wireless/rsi/rsi_main.h index b0f4e2c..99a00a3 100644 --- a/drivers/net/wireless/rsi/rsi_main.h +++ b/drivers/net/wireless/rsi/rsi_main.h @@ -206,6 +206,7 @@ struct rsi_common { struct rsi_hw *priv; struct vif_priv vif_info[RSI_MAX_VIFS]; + void *coex_cb; bool mgmt_q_block; struct version_info lmac_ver; @@ -270,6 +271,8 @@ struct rsi_common { u8 obm_ant_sel_val; int tx_power; u8 ant_in_use; + /* Mutex used for writing packet to bus */ + struct mutex tx_bus_mutex; bool hibernate_resume; bool reinit_hw; u8 wow_flags; @@ -359,4 +362,7 @@ struct rsi_host_intf_ops { u8 *fw); int (*reinit_device)(struct rsi_hw *adapter); }; + +enum rsi_host_intf rsi_get_host_intf(void *priv); + #endif diff --git a/drivers/net/wireless/rsi/rsi_mgmt.h b/drivers/net/wireless/rsi/rsi_mgmt.h index 389094a..cf6567a 100644 --- a/drivers/net/wireless/rsi/rsi_mgmt.h +++ b/drivers/net/wireless/rsi/rsi_mgmt.h @@ -57,12 +57,14 @@ #define WOW_PATTERN_SIZE 256 /* Receive Frame Types */ +#define RSI_RX_DESC_MSG_TYPE_OFFSET 2 #define TA_CONFIRM_TYPE 0x01 #define RX_DOT11_MGMT 0x02 #define TX_STATUS_IND 0x04 #define BEACON_EVENT_IND 0x08 #define PROBEREQ_CONFIRM 2 #define CARD_READY_IND 0x00 +#define SLEEP_NOTIFY_IND 0x06 #define RSI_DELETE_PEER 0x0 #define RSI_ADD_PEER 0x1 @@ -638,6 +640,7 @@ static inline void rsi_set_len_qno(__le16 *addr, u16 len, u8 qno) *addr = cpu_to_le16(len | ((qno & 7) << 12)); } +int rsi_handle_card_ready(struct rsi_common *common, u8 *msg); int rsi_mgmt_pkt_recv(struct rsi_common *common, u8 *msg); int rsi_set_vap_capabilities(struct rsi_common *common, enum opmode mode, u8 *mac_addr, u8 vap_id, u8 vap_status); diff --git a/include/net/rsi_91x.h b/include/net/rsi_91x.h index 16a447b..737ab4e 100644 --- a/include/net/rsi_91x.h +++ b/include/net/rsi_91x.h @@ -17,6 +17,8 @@ #ifndef __RSI_HEADER_H__ #define __RSI_HEADER_H__ +#include <linux/skbuff.h> + /* HAL queue information */ #define RSI_COEX_Q 0x0 #define RSI_BT_Q 0x2 @@ -26,9 +28,27 @@ #define RSI_BT_MGMT_Q 0x6 #define RSI_BT_DATA_Q 0x7 +enum rsi_coex_queues { + RSI_COEX_Q_INVALID = -1, + RSI_COEX_Q_COMMON = 0, + RSI_COEX_Q_BT, + RSI_COEX_Q_WLAN +}; + enum rsi_host_intf { RSI_HOST_INTF_SDIO = 0, RSI_HOST_INTF_USB }; +struct rsi_proto_ops { + int (*coex_send_pkt)(void *priv, struct sk_buff *skb, u8 hal_queue); + enum rsi_host_intf (*get_host_intf)(void *priv); + void (*set_bt_context)(void *priv, void *context); +}; + +struct rsi_mod_ops { + int (*attach)(void *priv, struct rsi_proto_ops *ops); + void (*detach)(void *priv); + int (*recv_pkt)(void *priv, u8 *msg); +}; #endif