cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

rsi_91x_main.c (11638B)


      1/*
      2 * Copyright (c) 2014 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#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
     18
     19#include <linux/module.h>
     20#include <linux/firmware.h>
     21#include <net/rsi_91x.h>
     22#include "rsi_mgmt.h"
     23#include "rsi_common.h"
     24#include "rsi_coex.h"
     25#include "rsi_hal.h"
     26#include "rsi_usb.h"
     27
     28u32 rsi_zone_enabled = /* INFO_ZONE |
     29			INIT_ZONE |
     30			MGMT_TX_ZONE |
     31			MGMT_RX_ZONE |
     32			DATA_TX_ZONE |
     33			DATA_RX_ZONE |
     34			FSM_ZONE |
     35			ISR_ZONE | */
     36			ERR_ZONE |
     37			0;
     38EXPORT_SYMBOL_GPL(rsi_zone_enabled);
     39
     40#ifdef CONFIG_RSI_COEX
     41static struct rsi_proto_ops g_proto_ops = {
     42	.coex_send_pkt = rsi_coex_send_pkt,
     43	.get_host_intf = rsi_get_host_intf,
     44	.set_bt_context = rsi_set_bt_context,
     45};
     46#endif
     47
     48/**
     49 * rsi_dbg() - This function outputs informational messages.
     50 * @zone: Zone of interest for output message.
     51 * @fmt: printf-style format for output message.
     52 *
     53 * Return: none
     54 */
     55void rsi_dbg(u32 zone, const char *fmt, ...)
     56{
     57	struct va_format vaf;
     58	va_list args;
     59
     60	va_start(args, fmt);
     61
     62	vaf.fmt = fmt;
     63	vaf.va = &args;
     64
     65	if (zone & rsi_zone_enabled)
     66		pr_info("%pV", &vaf);
     67	va_end(args);
     68}
     69EXPORT_SYMBOL_GPL(rsi_dbg);
     70
     71static char *opmode_str(int oper_mode)
     72{
     73	switch (oper_mode) {
     74	case DEV_OPMODE_WIFI_ALONE:
     75		return "Wi-Fi alone";
     76	case DEV_OPMODE_BT_ALONE:
     77		return "BT EDR alone";
     78	case DEV_OPMODE_BT_LE_ALONE:
     79		return "BT LE alone";
     80	case DEV_OPMODE_BT_DUAL:
     81		return "BT Dual";
     82	case DEV_OPMODE_STA_BT:
     83		return "Wi-Fi STA + BT EDR";
     84	case DEV_OPMODE_STA_BT_LE:
     85		return "Wi-Fi STA + BT LE";
     86	case DEV_OPMODE_STA_BT_DUAL:
     87		return "Wi-Fi STA + BT DUAL";
     88	case DEV_OPMODE_AP_BT:
     89		return "Wi-Fi AP + BT EDR";
     90	case DEV_OPMODE_AP_BT_DUAL:
     91		return "Wi-Fi AP + BT DUAL";
     92	}
     93
     94	return "Unknown";
     95}
     96
     97void rsi_print_version(struct rsi_common *common)
     98{
     99	rsi_dbg(ERR_ZONE, "================================================\n");
    100	rsi_dbg(ERR_ZONE, "================ RSI Version Info ==============\n");
    101	rsi_dbg(ERR_ZONE, "================================================\n");
    102	rsi_dbg(ERR_ZONE, "FW Version\t: %d.%d.%d\n",
    103		common->lmac_ver.major, common->lmac_ver.minor,
    104		common->lmac_ver.release_num);
    105	rsi_dbg(ERR_ZONE, "Operating mode\t: %d [%s]",
    106		common->oper_mode, opmode_str(common->oper_mode));
    107	rsi_dbg(ERR_ZONE, "Firmware file\t: %s", common->priv->fw_file_name);
    108	rsi_dbg(ERR_ZONE, "================================================\n");
    109}
    110
    111/**
    112 * rsi_prepare_skb() - This function prepares the skb.
    113 * @common: Pointer to the driver private structure.
    114 * @buffer: Pointer to the packet data.
    115 * @pkt_len: Length of the packet.
    116 * @extended_desc: Extended descriptor.
    117 *
    118 * Return: Successfully skb.
    119 */
    120static struct sk_buff *rsi_prepare_skb(struct rsi_common *common,
    121				       u8 *buffer,
    122				       u32 pkt_len,
    123				       u8 extended_desc)
    124{
    125	struct sk_buff *skb = NULL;
    126	u8 payload_offset;
    127
    128	if (WARN(!pkt_len, "%s: Dummy pkt received", __func__))
    129		return NULL;
    130
    131	if (pkt_len > (RSI_RCV_BUFFER_LEN * 4)) {
    132		rsi_dbg(ERR_ZONE, "%s: Pkt size > max rx buf size %d\n",
    133			__func__, pkt_len);
    134		pkt_len = RSI_RCV_BUFFER_LEN * 4;
    135	}
    136
    137	pkt_len -= extended_desc;
    138	skb = dev_alloc_skb(pkt_len + FRAME_DESC_SZ);
    139	if (skb == NULL)
    140		return NULL;
    141
    142	payload_offset = (extended_desc + FRAME_DESC_SZ);
    143	skb_put(skb, pkt_len);
    144	memcpy((skb->data), (buffer + payload_offset), skb->len);
    145
    146	return skb;
    147}
    148
    149/**
    150 * rsi_read_pkt() - This function reads frames from the card.
    151 * @common: Pointer to the driver private structure.
    152 * @rx_pkt: Received pkt.
    153 * @rcv_pkt_len: Received pkt length. In case of USB it is 0.
    154 *
    155 * Return: 0 on success, -1 on failure.
    156 */
    157int rsi_read_pkt(struct rsi_common *common, u8 *rx_pkt, s32 rcv_pkt_len)
    158{
    159	u8 *frame_desc = NULL, extended_desc = 0;
    160	u32 index, length = 0, queueno = 0;
    161	u16 actual_length = 0, offset;
    162	struct sk_buff *skb = NULL;
    163#ifdef CONFIG_RSI_COEX
    164	u8 bt_pkt_type;
    165#endif
    166
    167	index = 0;
    168	do {
    169		frame_desc = &rx_pkt[index];
    170		actual_length = *(u16 *)&frame_desc[0];
    171		offset = *(u16 *)&frame_desc[2];
    172		if (!rcv_pkt_len && offset >
    173			RSI_MAX_RX_USB_PKT_SIZE - FRAME_DESC_SZ)
    174			goto fail;
    175
    176		queueno = rsi_get_queueno(frame_desc, offset);
    177		length = rsi_get_length(frame_desc, offset);
    178
    179		/* Extended descriptor is valid for WLAN queues only */
    180		if (queueno == RSI_WIFI_DATA_Q || queueno == RSI_WIFI_MGMT_Q)
    181			extended_desc = rsi_get_extended_desc(frame_desc,
    182							      offset);
    183
    184		switch (queueno) {
    185		case RSI_COEX_Q:
    186#ifdef CONFIG_RSI_COEX
    187			if (common->coex_mode > 1)
    188				rsi_coex_recv_pkt(common, frame_desc + offset);
    189			else
    190#endif
    191				rsi_mgmt_pkt_recv(common,
    192						  (frame_desc + offset));
    193			break;
    194
    195		case RSI_WIFI_DATA_Q:
    196			skb = rsi_prepare_skb(common,
    197					      (frame_desc + offset),
    198					      length,
    199					      extended_desc);
    200			if (skb == NULL)
    201				goto fail;
    202
    203			rsi_indicate_pkt_to_os(common, skb);
    204			break;
    205
    206		case RSI_WIFI_MGMT_Q:
    207			rsi_mgmt_pkt_recv(common, (frame_desc + offset));
    208			break;
    209
    210#ifdef CONFIG_RSI_COEX
    211		case RSI_BT_MGMT_Q:
    212		case RSI_BT_DATA_Q:
    213#define BT_RX_PKT_TYPE_OFST	14
    214#define BT_CARD_READY_IND	0x89
    215			bt_pkt_type = frame_desc[offset + BT_RX_PKT_TYPE_OFST];
    216			if (bt_pkt_type == BT_CARD_READY_IND) {
    217				rsi_dbg(INFO_ZONE, "BT Card ready recvd\n");
    218				if (common->fsm_state == FSM_MAC_INIT_DONE)
    219					rsi_attach_bt(common);
    220				else
    221					common->bt_defer_attach = true;
    222			} else {
    223				if (common->bt_adapter)
    224					rsi_bt_ops.recv_pkt(common->bt_adapter,
    225							frame_desc + offset);
    226			}
    227			break;
    228#endif
    229
    230		default:
    231			rsi_dbg(ERR_ZONE, "%s: pkt from invalid queue: %d\n",
    232				__func__,   queueno);
    233			goto fail;
    234		}
    235
    236		index  += actual_length;
    237		rcv_pkt_len -= actual_length;
    238	} while (rcv_pkt_len > 0);
    239
    240	return 0;
    241fail:
    242	return -EINVAL;
    243}
    244EXPORT_SYMBOL_GPL(rsi_read_pkt);
    245
    246/**
    247 * rsi_tx_scheduler_thread() - This function is a kernel thread to send the
    248 *			       packets to the device.
    249 * @common: Pointer to the driver private structure.
    250 *
    251 * Return: None.
    252 */
    253static void rsi_tx_scheduler_thread(struct rsi_common *common)
    254{
    255	struct rsi_hw *adapter = common->priv;
    256	u32 timeout = EVENT_WAIT_FOREVER;
    257
    258	do {
    259		if (adapter->determine_event_timeout)
    260			timeout = adapter->determine_event_timeout(adapter);
    261		rsi_wait_event(&common->tx_thread.event, timeout);
    262		rsi_reset_event(&common->tx_thread.event);
    263
    264		if (common->init_done)
    265			rsi_core_qos_processor(common);
    266	} while (atomic_read(&common->tx_thread.thread_done) == 0);
    267	kthread_complete_and_exit(&common->tx_thread.completion, 0);
    268}
    269
    270#ifdef CONFIG_RSI_COEX
    271enum rsi_host_intf rsi_get_host_intf(void *priv)
    272{
    273	struct rsi_common *common = (struct rsi_common *)priv;
    274
    275	return common->priv->rsi_host_intf;
    276}
    277
    278void rsi_set_bt_context(void *priv, void *bt_context)
    279{
    280	struct rsi_common *common = (struct rsi_common *)priv;
    281
    282	common->bt_adapter = bt_context;
    283}
    284#endif
    285
    286void rsi_attach_bt(struct rsi_common *common)
    287{
    288#ifdef CONFIG_RSI_COEX
    289	if (rsi_bt_ops.attach(common, &g_proto_ops))
    290		rsi_dbg(ERR_ZONE,
    291			"Failed to attach BT module\n");
    292#endif
    293}
    294
    295/**
    296 * rsi_91x_init() - This function initializes os interface operations.
    297 * @oper_mode: One of DEV_OPMODE_*.
    298 *
    299 * Return: Pointer to the adapter structure on success, NULL on failure .
    300 */
    301struct rsi_hw *rsi_91x_init(u16 oper_mode)
    302{
    303	struct rsi_hw *adapter = NULL;
    304	struct rsi_common *common = NULL;
    305	u8 ii = 0;
    306
    307	adapter = kzalloc(sizeof(*adapter), GFP_KERNEL);
    308	if (!adapter)
    309		return NULL;
    310
    311	adapter->priv = kzalloc(sizeof(*common), GFP_KERNEL);
    312	if (adapter->priv == NULL) {
    313		rsi_dbg(ERR_ZONE, "%s: Failed in allocation of memory\n",
    314			__func__);
    315		kfree(adapter);
    316		return NULL;
    317	} else {
    318		common = adapter->priv;
    319		common->priv = adapter;
    320	}
    321
    322	for (ii = 0; ii < NUM_SOFT_QUEUES; ii++)
    323		skb_queue_head_init(&common->tx_queue[ii]);
    324
    325	rsi_init_event(&common->tx_thread.event);
    326	mutex_init(&common->mutex);
    327	mutex_init(&common->tx_lock);
    328	mutex_init(&common->rx_lock);
    329	mutex_init(&common->tx_bus_mutex);
    330
    331	if (rsi_create_kthread(common,
    332			       &common->tx_thread,
    333			       rsi_tx_scheduler_thread,
    334			       "Tx-Thread")) {
    335		rsi_dbg(ERR_ZONE, "%s: Unable to init tx thrd\n", __func__);
    336		goto err;
    337	}
    338
    339	rsi_default_ps_params(adapter);
    340	init_bgscan_params(common);
    341	spin_lock_init(&adapter->ps_lock);
    342	timer_setup(&common->roc_timer, rsi_roc_timeout, 0);
    343	init_completion(&common->wlan_init_completion);
    344	adapter->device_model = RSI_DEV_9113;
    345	common->oper_mode = oper_mode;
    346
    347	/* Determine coex mode */
    348	switch (common->oper_mode) {
    349	case DEV_OPMODE_STA_BT_DUAL:
    350	case DEV_OPMODE_STA_BT:
    351	case DEV_OPMODE_STA_BT_LE:
    352	case DEV_OPMODE_BT_ALONE:
    353	case DEV_OPMODE_BT_LE_ALONE:
    354	case DEV_OPMODE_BT_DUAL:
    355		common->coex_mode = 2;
    356		break;
    357	case DEV_OPMODE_AP_BT_DUAL:
    358	case DEV_OPMODE_AP_BT:
    359		common->coex_mode = 4;
    360		break;
    361	case DEV_OPMODE_WIFI_ALONE:
    362		common->coex_mode = 1;
    363		break;
    364	default:
    365		common->oper_mode = 1;
    366		common->coex_mode = 1;
    367	}
    368	rsi_dbg(INFO_ZONE, "%s: oper_mode = %d, coex_mode = %d\n",
    369		__func__, common->oper_mode, common->coex_mode);
    370
    371	adapter->device_model = RSI_DEV_9113;
    372#ifdef CONFIG_RSI_COEX
    373	if (common->coex_mode > 1) {
    374		if (rsi_coex_attach(common)) {
    375			rsi_dbg(ERR_ZONE, "Failed to init coex module\n");
    376			rsi_kill_thread(&common->tx_thread);
    377			goto err;
    378		}
    379	}
    380#endif
    381
    382	common->init_done = true;
    383	return adapter;
    384
    385err:
    386	kfree(common);
    387	kfree(adapter);
    388	return NULL;
    389}
    390EXPORT_SYMBOL_GPL(rsi_91x_init);
    391
    392/**
    393 * rsi_91x_deinit() - This function de-intializes os intf operations.
    394 * @adapter: Pointer to the adapter structure.
    395 *
    396 * Return: None.
    397 */
    398void rsi_91x_deinit(struct rsi_hw *adapter)
    399{
    400	struct rsi_common *common = adapter->priv;
    401	u8 ii;
    402
    403	rsi_dbg(INFO_ZONE, "%s: Performing deinit os ops\n", __func__);
    404
    405	rsi_kill_thread(&common->tx_thread);
    406
    407	for (ii = 0; ii < NUM_SOFT_QUEUES; ii++)
    408		skb_queue_purge(&common->tx_queue[ii]);
    409
    410#ifdef CONFIG_RSI_COEX
    411	if (common->coex_mode > 1) {
    412		if (common->bt_adapter) {
    413			rsi_bt_ops.detach(common->bt_adapter);
    414			common->bt_adapter = NULL;
    415		}
    416		rsi_coex_detach(common);
    417	}
    418#endif
    419
    420	common->init_done = false;
    421
    422	kfree(common);
    423	kfree(adapter->rsi_dev);
    424	kfree(adapter);
    425}
    426EXPORT_SYMBOL_GPL(rsi_91x_deinit);
    427
    428/**
    429 * rsi_91x_hal_module_init() - This function is invoked when the module is
    430 *			       loaded into the kernel.
    431 *			       It registers the client driver.
    432 * @void: Void.
    433 *
    434 * Return: 0 on success, -1 on failure.
    435 */
    436static int rsi_91x_hal_module_init(void)
    437{
    438	rsi_dbg(INIT_ZONE, "%s: Module init called\n", __func__);
    439	return 0;
    440}
    441
    442/**
    443 * rsi_91x_hal_module_exit() - This function is called at the time of
    444 *			       removing/unloading the module.
    445 *			       It unregisters the client driver.
    446 * @void: Void.
    447 *
    448 * Return: None.
    449 */
    450static void rsi_91x_hal_module_exit(void)
    451{
    452	rsi_dbg(INIT_ZONE, "%s: Module exit called\n", __func__);
    453}
    454
    455module_init(rsi_91x_hal_module_init);
    456module_exit(rsi_91x_hal_module_exit);
    457MODULE_AUTHOR("Redpine Signals Inc");
    458MODULE_DESCRIPTION("Station driver for RSI 91x devices");
    459MODULE_VERSION("0.1");
    460MODULE_LICENSE("Dual BSD/GPL");