Commit b01f5e8e authored by Angus Ainslie's avatar Angus Ainslie Committed by Martin Kepplinger
Browse files

wireless: redpine: drop the old vendor driver



Clean up in preperation for a new code drop
Signed-off-by: default avatarAngus Ainslie <angus@akkea.ca>
parent 3695e854
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);
redpine_dbg(INFO_ZONE, "queue = %d\n", coex_q);
if (coex_q == INVALID_QUEUE) {
redpine_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) {
redpine_dbg(DATA_TX_ZONE, "Sending zigbee pkt\n");
rsi_send_zb_pkt(coex_cb->priv, skb);
} else {
#endif
redpine_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;
redpine_dbg(INFO_ZONE, "COMMON CARD READY RECEIVED\n");
rsi_handle_card_ready(common, msg);
} else if (msg_type == SLEEP_NOTIFY_IND) {
redpine_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")) {
redpine_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);
}
/*
* 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_mgmt.h"
#include "rsi_common.h"
#include "rsi_hal.h"
#ifdef CONFIG_REDPINE_COEX_MODE
#include "rsi_coex.h"
#endif
/**
* rsi_determine_min_weight_queue() - This function determines the queue with
* the min weight.
* @common: Pointer to the driver private structure.
*
* Return: q_num: Corresponding queue number.
*/
static u8 rsi_determine_min_weight_queue(struct rsi_common *common)
{
struct wmm_qinfo *tx_qinfo = common->tx_qinfo;
u32 q_len = 0;
u8 ii = 0;
for (ii = 0; ii < NUM_EDCA_QUEUES; ii++) {
q_len = skb_queue_len(&common->tx_queue[ii]);
if ((tx_qinfo[ii].pkt_contended) && q_len) {
common->min_weight = tx_qinfo[ii].weight;
break;
}
}
return ii;
}
/**
* rsi_recalculate_weights() - This function recalculates the weights
* corresponding to each queue.
* @common: Pointer to the driver private structure.
*
* Return: recontend_queue bool variable
*/
static bool rsi_recalculate_weights(struct rsi_common *common)
{
struct wmm_qinfo *tx_qinfo = common->tx_qinfo;
bool recontend_queue = false;
u8 ii = 0;
u32 q_len = 0;
for (ii = 0; ii < NUM_EDCA_QUEUES; ii++) {
q_len = skb_queue_len(&common->tx_queue[ii]);
/* Check for the need of contention */
if (q_len) {
if (tx_qinfo[ii].pkt_contended) {
tx_qinfo[ii].weight =
((tx_qinfo[ii].weight > common->min_weight) ?
tx_qinfo[ii].weight - common->min_weight : 0);
} else {
tx_qinfo[ii].pkt_contended = 1;
tx_qinfo[ii].weight = tx_qinfo[ii].wme_params;
recontend_queue = true;
}
} else { /* No packets so no contention */
tx_qinfo[ii].weight = 0;
tx_qinfo[ii].pkt_contended = 0;
}
}
return recontend_queue;
}
/**
* rsi_get_num_pkts_dequeue() - This function determines the number of
* packets to be dequeued based on the number
* of bytes calculated using txop.
*
* @common: Pointer to the driver private structure.
* @q_num: the queue from which pkts have to be dequeued
*
* Return: pkt_num: Number of pkts to be dequeued.
*/
static u32 rsi_get_num_pkts_dequeue(struct rsi_common *common, u8 q_num)
{
struct rsi_hw *adapter = common->priv;
struct sk_buff *skb;
u32 pkt_cnt = 0;
s16 txop = common->tx_qinfo[q_num].txop * 32;
__le16 r_txop;
struct ieee80211_rate rate;
rate.bitrate = RSI_RATE_MCS0 * 5 * 10; /* Convert to Kbps */
if (q_num == VI_Q)
txop = ((txop << 5) / 80);
if (skb_queue_len(&common->tx_queue[q_num]))
skb = skb_peek(&common->tx_queue[q_num]);
else
return 0;
do {
r_txop = ieee80211_generic_frame_duration(adapter->hw,
adapter->vifs[adapter->sc_nvifs - 1],
common->band,
skb->len, &rate);
txop -= le16_to_cpu(r_txop);
pkt_cnt += 1;
/*checking if pkts are still there*/
if (skb_queue_len(&common->tx_queue[q_num]) - pkt_cnt)
skb = skb->next;
else
break;
} while (txop > 0);
return pkt_cnt;
}
/**
* rsi_core_determine_hal_queue() - This function determines the queue from
* which packet has to be dequeued.
* @common: Pointer to the driver private structure.
*
* Return: q_num: Corresponding queue number on success.
*/
static u8 rsi_core_determine_hal_queue(struct rsi_common *common)
{
bool recontend_queue = false;
u32 q_len = 0;
u8 q_num = INVALID_QUEUE;
u8 ii;
if (skb_queue_len(&common->tx_queue[MGMT_BEACON_Q])) {
q_num = MGMT_BEACON_Q;
return q_num;
}
if (skb_queue_len(&common->tx_queue[MGMT_SOFT_Q])) {
if (!common->mgmt_q_block)
q_num = MGMT_SOFT_Q;
return q_num;
}
if (common->hw_data_qs_blocked) {
redpine_dbg(INFO_ZONE, "%s: data queue blocked\n", __func__);
return q_num;
}
if (common->pkt_cnt != 0) {
--common->pkt_cnt;
return common->selected_qnum;
}
get_queue_num:
recontend_queue = false;
q_num = rsi_determine_min_weight_queue(common);
ii = q_num;
/* Selecting the queue with least back off */
for (; ii < NUM_EDCA_QUEUES; ii++) {
q_len = skb_queue_len(&common->tx_queue[ii]);
if (((common->tx_qinfo[ii].pkt_contended) &&
(common->tx_qinfo[ii].weight < common->min_weight)) &&
q_len) {
common->min_weight = common->tx_qinfo[ii].weight;
q_num = ii;
}
}
if (q_num < NUM_EDCA_QUEUES)
common->tx_qinfo[q_num].pkt_contended = 0;
/* Adjust the back off values for all queues again */
recontend_queue = rsi_recalculate_weights(common);
q_len = skb_queue_len(&common->tx_queue[q_num]);
if (!q_len) {
/* If any queues are freshly contended and the selected queue
* doesn't have any packets
* then get the queue number again with fresh values
*/
if (recontend_queue)
goto get_queue_num;
q_num = INVALID_QUEUE;
return q_num;
}
common->selected_qnum = q_num;
q_len = skb_queue_len(&common->tx_queue[q_num]);
if (q_num == VO_Q || q_num == VI_Q) {
common->pkt_cnt = rsi_get_num_pkts_dequeue(common, q_num);
common->pkt_cnt -= 1;
}
return q_num;
}
/**
* rsi_core_queue_pkt() - This functions enqueues the packet to the queue
* specified by the queue number.
* @common: Pointer to the driver private structure.
* @skb: Pointer to the socket buffer structure.
*
* Return: None.
*/