net: wireless: redpine: add the Proprietary Redpine 1.3 driver

Add the Redpine driver for RS9116 module
Signed-off-by: default avatarAngus Ainslie (Purism) <angus@akkea.ca>
parent 308814f1
......@@ -43,6 +43,7 @@ source "drivers/net/wireless/mediatek/Kconfig"
source "drivers/net/wireless/ralink/Kconfig"
source "drivers/net/wireless/realtek/Kconfig"
source "drivers/net/wireless/rsi/Kconfig"
source "drivers/net/wireless/redpine/Kconfig"
source "drivers/net/wireless/st/Kconfig"
source "drivers/net/wireless/ti/Kconfig"
source "drivers/net/wireless/zydas/Kconfig"
......
......@@ -15,6 +15,7 @@ obj-$(CONFIG_WLAN_VENDOR_MEDIATEK) += mediatek/
obj-$(CONFIG_WLAN_VENDOR_RALINK) += ralink/
obj-$(CONFIG_WLAN_VENDOR_REALTEK) += realtek/
obj-$(CONFIG_WLAN_VENDOR_RSI) += rsi/
obj-$(CONFIG_WLAN_VENDOR_REDPINE) += redpine/
obj-$(CONFIG_WLAN_VENDOR_ST) += st/
obj-$(CONFIG_WLAN_VENDOR_TI) += ti/
obj-$(CONFIG_WLAN_VENDOR_ZYDAS) += zydas/
......
config WLAN_VENDOR_REDPINE
bool "Redpine Signals Inc devices - PROPRIETARY DRIVER"
default y
---help---
If you have a wireless card belonging to this class, say Y.
Note that the answer to this question doesn't directly affect the
kernel: saying N will just cause the configurator to skip all
the questions about cards. If you say Y, you will be asked for
your specific card in the following questions.
if WLAN_VENDOR_REDPINE
config REDPINE_91X
tristate "Redpine Signals Inc 91x WLAN driver support"
depends on MAC80211
---help---
This option enabes support for REDPINE 1x1 devices.
Select M (recommended), if you have a REDPINE 1x1 wireless module.
config REDPINE_DEBUGFS
bool "Redpine Signals Inc debug support"
depends on REDPINE_91X
default y
---help---
Say Y, if you would like to enable debug support. This option
creates debugfs entries.
config REDPINE_SDIO
tristate "Redpine Signals SDIO bus support"
depends on MMC && REDPINE_91X
default m
---help---
This option enables the SDIO bus support in rsi drivers.
Select M (recommended), if you have a REDPINE 1x1 wireless module.
config REDPINE_USB
tristate "Redpine Signals USB bus support"
depends on USB && REDPINE_91X
default m
---help---
This option enables the USB bus support in rsi drivers.
Select M (recommended), if you have a REDPINE 1x1 wireless module.
config REDPINE_BT_ALONE
bool "Redpine Signals BT alone (classic/LE) mode support"
depends on REDPINE_91X
default n
---help---
This option enables the BT classic alone upport in rsi drivers.
Say Y, if you want to use this feature.
config REDPINE_COEX_MODE
bool "Redpine Signals Wi-Fi BT Coex support"
depends on REDPINE_91X
default n
---help---
This option enables the Wi-Fi BT coex support in rsi drivers.
Select Y, if you have to use this feature.
config REDPINE_WOW
bool "Redpine Signals WoWLAN support"
depends on REDPINE_91X
default n
---help---
This option enables the WoWLAN support.
Say Y if you want to use this feature.
config REDPINE_P2P
bool "Redpine Signals Wi-Fi Direct support"
depends on REDPINE_91X
default n
---help---
This option enables the Wi-Fi Direct support in rsi drivers.
Select Y, if you have to use this feature.
config HW_SCAN_OFFLOAD
bool "Redpine Signals Hardware scan offload feature"
depends on REDPINE_91X
default n
---help---
This option enables the hardware scan offload option in rsi drivers.
Select Y, if you have to use this feature.
config CARACALLA_BOARD
bool "Redpine device support on Caracalla board"
depends on REDPINE_91X
default n
---help---
This option is used to support Caracalla board with REDPINE driver.
Select Y, if you have to use this support.
config REDPINE_ZIGB
bool "Redpine device support on Zigbee"
depends on REDPINE_91X && REDPINE_COEX_MODE
default n
---help---
This option is used to support Zigbee with REDPINE driver.
Select Y, if you have to use this support.
config REDPINE_PURISM
bool "Redpine Signals PURISM FW support"
depends on REDPINE_91X && REDPINE_COEX_MODE
default n
---help---
This option enables the PURISM FW support.
Say Y if you want to use this feature.
endif # WLAN_VENDOR_REDPINE
#/*
# Copyright (c) 2017 Redpine Signals Inc. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# 3. Neither the name of the copyright holder nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION). HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
#*/
redpine_91x-y += rsi_91x_main.o
redpine_91x-y += rsi_91x_core.o
redpine_91x-y += rsi_91x_mac80211.o
redpine_91x-y += rsi_91x_mgmt.o
redpine_91x-y += rsi_91x_hal.o
redpine_91x-y += rsi_91x_ps.o
redpine_91x-$(CONFIG_REDPINE_DEBUGFS) += rsi_91x_debugfs.o
redpine_91x-$(CONFIG_REDPINE_BT_ALONE) += rsi_91x_hci.o
redpine_91x-$(CONFIG_REDPINE_COEX_MODE) += rsi_91x_coex.o
redpine_91x-$(CONFIG_REDPINE_COEX_MODE) += rsi_91x_hci.o
redpine_91x-$(CONFIG_REDPINE_ZIGB) += rsi_91x_zigb.o
redpine_91x-$(CONFIG_REDPINE_11K) += rsi_91x_rrm.o
redpine_usb-$(CONFIG_REDPINE_USB) += rsi_91x_usb.o rsi_91x_usb_ops.o
redpine_sdio-$(CONFIG_REDPINE_SDIO) += rsi_91x_sdio.o rsi_91x_sdio_ops.o
obj-$(CONFIG_REDPINE_91X) += redpine_91x.o
obj-$(CONFIG_REDPINE_SDIO) += redpine_sdio.o
obj-$(CONFIG_REDPINE_USB) += redpine_usb.o
/*
* Copyright (c) 2017 Redpine Signals Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION). HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include "rsi_main.h"
#include "rsi_coex.h"
#include "rsi_hal.h"
#include "rsi_mgmt.h"
static u8 rsi_coex_determine_coex_q(struct rsi_coex_ctrl_block *coex_cb)
{
u8 q_num = INVALID_QUEUE;
if (skb_queue_len(&coex_cb->coex_tx_qs[VIP_Q]) > 0)
q_num = VIP_Q;
if (skb_queue_len(&coex_cb->coex_tx_qs[COEX_Q]) > 0)
q_num = COEX_Q;
if (skb_queue_len(&coex_cb->coex_tx_qs[BT_Q]) > 0)
q_num = BT_Q;
if (skb_queue_len(&coex_cb->coex_tx_qs[ZIGB_Q]) > 0)
q_num = ZIGB_Q;
if (skb_queue_len(&coex_cb->coex_tx_qs[WLAN_Q]) > 0)
q_num = WLAN_Q;
return q_num;
}
static void rsi_coex_sched_tx_pkts(struct rsi_coex_ctrl_block *coex_cb)
{
u8 coex_q;
struct sk_buff *skb;
#ifdef CONFIG_REDPINE_ZIGB
struct rsi_common *common = coex_cb->priv;
#endif
while (1) {
coex_q = rsi_coex_determine_coex_q(coex_cb);
rsi_dbg(INFO_ZONE, "queue = %d\n", coex_q);
if (coex_q == INVALID_QUEUE) {
rsi_dbg(DATA_TX_ZONE, "No more pkt\n");
break;
}
if ((coex_q == BT_Q) || (coex_q == ZIGB_Q)) {
skb = skb_dequeue(&coex_cb->coex_tx_qs[BT_Q]);
#ifdef CONFIG_REDPINE_ZIGB
if (common->zb_fsm_state == ZB_DEVICE_READY) {
rsi_dbg(DATA_TX_ZONE, "Sending zigbee pkt\n");
rsi_send_zb_pkt(coex_cb->priv, skb);
} else {
#endif
rsi_dbg(DATA_TX_ZONE, "Sending BT pkt\n");
rsi_send_bt_pkt(coex_cb->priv, skb);
#ifdef CONFIG_REDPINE_ZIGB
}
#endif
}
}
}
/**
* rsi_coex_scheduler_thread() - This function is a kernel thread to schedule
* the coex packets to device
* @common: Pointer to the driver private structure.
*
* Return: None.
*/
static void rsi_coex_scheduler_thread(struct rsi_common *common)
{
int status = 0;
struct rsi_coex_ctrl_block *coex_cb =
(struct rsi_coex_ctrl_block *)common->coex_cb;
u32 timeout = EVENT_WAIT_FOREVER;
do {
status = rsi_wait_event(&coex_cb->coex_tx_thread.event, timeout);
if (status < 0)
break;
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)
{
u16 msg_type = msg[2];
if (msg_type == COMMON_CARD_READY_IND) {
common->hibernate_resume = false;
rsi_dbg(INFO_ZONE, "COMMON CARD READY RECEIVED\n");
rsi_handle_card_ready(common, msg);
} else if (msg_type == SLEEP_NOTIFY_IND) {
rsi_dbg(INFO_ZONE, "\n\n sleep notify RECEIVED\n");
rsi_mgmt_pkt_recv(common, msg);
}
return 0;
}
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;
int status = 0;
/* Add pkt to queue if not WLAN packet */
if (hal_queue != RSI_WLAN_Q) {
skb_queue_tail(&coex_cb->coex_tx_qs[hal_queue], skb);
rsi_set_event(&coex_cb->coex_tx_thread.event);
return status;
}
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 0;
}
int rsi_coex_init(struct rsi_common *common)
{
struct rsi_coex_ctrl_block *coex_cb = NULL;
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;
sema_init(&coex_cb->tx_bus_lock, 1);
/* 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__);
goto err;
}
return 0;
err:
return -EINVAL;
}
void rsi_coex_deinit(struct rsi_common *common)
{
int cnt;
struct rsi_coex_ctrl_block *coex_cb =
(struct rsi_coex_ctrl_block *)common->coex_cb;
/* Stop the coex tx thread */
rsi_kill_thread(&coex_cb->coex_tx_thread);
/* Empty the coex queue */
for (cnt = 0; cnt < NUM_COEX_TX_QUEUES; cnt++)
skb_queue_purge(&coex_cb->coex_tx_qs[cnt]);
/* Free the coex control block */
kfree(coex_cb);
}
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
/*
* Copyright (c) 2017 Redpine Signals Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION). HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <linux/etherdevice.h>
#include <linux/if.h>
#include <linux/version.h>
#include "rsi_debugfs.h"
#include "rsi_mgmt.h"
#include "rsi_common.h"
#include "rsi_ps.h"
/**
* str_psstate() - return the ps state in string format.
*
* @state - PS state.
*
* return: PS state in string format.
*/
char *str_psstate(enum ps_state state)
{
switch (state) {
case PS_NONE:
return "PS_NONE";
case PS_DISABLE_REQ_SENT:
return "PS_DISABLE_REQ_SENT";
case PS_ENABLE_REQ_SENT:
return "PS_ENABLE_REQ_SENT";
case PS_ENABLED:
return "PS_ENABLED";
default:
return "INVALID_STATE";
}
return "INVALID_STATE";
}
/**
* rsi_modify_ps_state() - Modify PS state to a new state.
*
* @adapter: pointer to rsi_hw structure.
* @nstate: new PS state.
*
* return: new state.
*/
static inline void rsi_modify_ps_state(struct rsi_hw *adapter,
enum ps_state nstate)
{
rsi_dbg(INFO_ZONE, "PS state changed %s => %s\n",
str_psstate(adapter->ps_state),
str_psstate(nstate));
adapter->ps_state = nstate;
}
/**
* rsi_default_ps_params() - Initalization of default powersave parameters.
*
* @adapter: pointer to rsi_hw structure.
*
* return: void.
*/
void rsi_default_ps_params(struct rsi_hw *adapter)
{
struct rsi_ps_info *ps_info = &adapter->ps_info;
ps_info->enabled = true;
ps_info->sleep_type = 1; /* LP */
ps_info->tx_threshold = 0;
ps_info->rx_threshold = 0;
ps_info->tx_hysterisis = 0;
ps_info->rx_hysterisis = 0;
ps_info->monitor_interval = 0;
ps_info->listen_interval = 2 * 100;
ps_info->num_bcns_per_lis_int = 0;
ps_info->dtim_interval_duration = 0;
ps_info->num_dtims_per_sleep = 0;
ps_info->deep_sleep_wakeup_period = 0;
}
EXPORT_SYMBOL_GPL(rsi_default_ps_params);
/**
* rsi_enable_ps() - enable power save
*
* @adapter: Pointer to rsi_hw structure.
*
* return: void.
*/
void rsi_enable_ps(struct rsi_hw *adapter)
{
if (rsi_send_ps_request(adapter, true)) {
rsi_dbg(ERR_ZONE,
"%s: Failed to send PS request to device\n",
__func__);
return;
}
rsi_modify_ps_state(adapter, PS_ENABLE_REQ_SENT);
}
/**
* rsi_disable_ps() - disable power save
*
* @adapter: Pointer to rsi_hw structure.
*
* return: void.
*/
void rsi_disable_ps(struct rsi_hw *adapter)
{
if (rsi_send_ps_request(adapter, false)) {
rsi_dbg(ERR_ZONE,
"%s: Failed to send PS request to device\n",
__func__);
return;
}
rsi_modify_ps_state(adapter, PS_DISABLE_REQ_SENT);
}
/**
* rsi_conf_uapsd() - configures UAPSD powersave.
*
* @adapter - Pointer to rsi_hw structure.
*
* return: void.
*/
void rsi_conf_uapsd(struct rsi_hw *adapter)
{
if (adapter->ps_state != PS_ENABLED)
return;
if (rsi_send_ps_request(adapter, false)) {
rsi_dbg(ERR_ZONE,
"%s: Failed to send PS request to device\n",
__func__);
return;
}
if (rsi_send_ps_request(adapter, true)) {
rsi_dbg(ERR_ZONE,
"%s: Failed to send PS request to device\n",
__func__);
}
}
/**
* rsi_handle_ps_confirm() - Processes powersave confirmation.
*
* @adapter - Pointer to rsi_hw structure.
* @msg - Recevied buffer.
*
* return: 0 on success.
*/
int rsi_handle_ps_confirm(struct rsi_hw *adapter, u8 *msg)
{
u16 cfm_type = 0;
cfm_type = *(u16 *)&msg[PS_CONFIRM_INDEX];
switch (cfm_type) {
case SLEEP_REQUEST:
if (adapter->ps_state == PS_ENABLE_REQ_SENT)
rsi_modify_ps_state(adapter, PS_ENABLED);
break;
case WAKEUP_REQUEST:
if (adapter->ps_state == PS_DISABLE_REQ_SENT)
rsi_modify_ps_state(adapter, PS_NONE);
break;
default:
rsi_dbg(ERR_ZONE,
"Invalid PS confirm type %x in state %s\n",
cfm_type, str_psstate(adapter->ps_state));
return -1;
}
return 0;
}
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment