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 "rsi_mgmt.h" 22#include "rsi_common.h" 23 24u32 rsi_zone_enabled = /* INFO_ZONE | 25 INIT_ZONE | 26 MGMT_TX_ZONE | 27 MGMT_RX_ZONE | 28 DATA_TX_ZONE | 29 DATA_RX_ZONE | 30 FSM_ZONE | 31 ISR_ZONE | */ 32 ERR_ZONE | 33 0; 34EXPORT_SYMBOL_GPL(rsi_zone_enabled); 35 36/** 37 * rsi_dbg() - This function outputs informational messages. 38 * @zone: Zone of interest for output message. 39 * @fmt: printf-style format for output message. 40 * 41 * Return: none 42 */ 43void rsi_dbg(u32 zone, const char *fmt, ...) 44{ 45 struct va_format vaf; 46 va_list args; 47 48 va_start(args, fmt); 49 50 vaf.fmt = fmt; 51 vaf.va = &args; 52 53 if (zone & rsi_zone_enabled) 54 pr_info("%pV", &vaf); 55 va_end(args); 56} 57EXPORT_SYMBOL_GPL(rsi_dbg); 58 59/** 60 * rsi_prepare_skb() - This function prepares the skb. 61 * @common: Pointer to the driver private structure. 62 * @buffer: Pointer to the packet data. 63 * @pkt_len: Length of the packet. 64 * @extended_desc: Extended descriptor. 65 * 66 * Return: Successfully skb. 67 */ 68static struct sk_buff *rsi_prepare_skb(struct rsi_common *common, 69 u8 *buffer, 70 u32 pkt_len, 71 u8 extended_desc) 72{ 73 struct ieee80211_tx_info *info; 74 struct skb_info *rx_params; 75 struct sk_buff *skb = NULL; 76 u8 payload_offset; 77 78 if (WARN(!pkt_len, "%s: Dummy pkt received", __func__)) 79 return NULL; 80 81 if (pkt_len > (RSI_RCV_BUFFER_LEN * 4)) { 82 rsi_dbg(ERR_ZONE, "%s: Pkt size > max rx buf size %d\n", 83 __func__, pkt_len); 84 pkt_len = RSI_RCV_BUFFER_LEN * 4; 85 } 86 87 pkt_len -= extended_desc; 88 skb = dev_alloc_skb(pkt_len + FRAME_DESC_SZ); 89 if (skb == NULL) 90 return NULL; 91 92 payload_offset = (extended_desc + FRAME_DESC_SZ); 93 skb_put(skb, pkt_len); 94 memcpy((skb->data), (buffer + payload_offset), skb->len); 95 96 info = IEEE80211_SKB_CB(skb); 97 rx_params = (struct skb_info *)info->driver_data; 98 rx_params->rssi = rsi_get_rssi(buffer); 99 rx_params->channel = rsi_get_connected_channel(common->priv); 100 101 return skb; 102} 103 104/** 105 * rsi_read_pkt() - This function reads frames from the card. 106 * @common: Pointer to the driver private structure. 107 * @rcv_pkt_len: Received pkt length. In case of USB it is 0. 108 * 109 * Return: 0 on success, -1 on failure. 110 */ 111int rsi_read_pkt(struct rsi_common *common, s32 rcv_pkt_len) 112{ 113 u8 *frame_desc = NULL, extended_desc = 0; 114 u32 index, length = 0, queueno = 0; 115 u16 actual_length = 0, offset; 116 struct sk_buff *skb = NULL; 117 118 index = 0; 119 do { 120 frame_desc = &common->rx_data_pkt[index]; 121 actual_length = *(u16 *)&frame_desc[0]; 122 offset = *(u16 *)&frame_desc[2]; 123 124 queueno = rsi_get_queueno(frame_desc, offset); 125 length = rsi_get_length(frame_desc, offset); 126 extended_desc = rsi_get_extended_desc(frame_desc, offset); 127 128 switch (queueno) { 129 case RSI_WIFI_DATA_Q: 130 skb = rsi_prepare_skb(common, 131 (frame_desc + offset), 132 length, 133 extended_desc); 134 if (skb == NULL) 135 goto fail; 136 137 rsi_indicate_pkt_to_os(common, skb); 138 break; 139 140 case RSI_WIFI_MGMT_Q: 141 rsi_mgmt_pkt_recv(common, (frame_desc + offset)); 142 break; 143 144 default: 145 rsi_dbg(ERR_ZONE, "%s: pkt from invalid queue: %d\n", 146 __func__, queueno); 147 goto fail; 148 } 149 150 index += actual_length; 151 rcv_pkt_len -= actual_length; 152 } while (rcv_pkt_len > 0); 153 154 return 0; 155fail: 156 return -EINVAL; 157} 158EXPORT_SYMBOL_GPL(rsi_read_pkt); 159 160/** 161 * rsi_tx_scheduler_thread() - This function is a kernel thread to send the 162 * packets to the device. 163 * @common: Pointer to the driver private structure. 164 * 165 * Return: None. 166 */ 167static void rsi_tx_scheduler_thread(struct rsi_common *common) 168{ 169 struct rsi_hw *adapter = common->priv; 170 u32 timeout = EVENT_WAIT_FOREVER; 171 172 do { 173 if (adapter->determine_event_timeout) 174 timeout = adapter->determine_event_timeout(adapter); 175 rsi_wait_event(&common->tx_thread.event, timeout); 176 rsi_reset_event(&common->tx_thread.event); 177 178 if (common->init_done) 179 rsi_core_qos_processor(common); 180 } while (atomic_read(&common->tx_thread.thread_done) == 0); 181 complete_and_exit(&common->tx_thread.completion, 0); 182} 183 184/** 185 * rsi_91x_init() - This function initializes os interface operations. 186 * @void: Void. 187 * 188 * Return: Pointer to the adapter structure on success, NULL on failure . 189 */ 190struct rsi_hw *rsi_91x_init(void) 191{ 192 struct rsi_hw *adapter = NULL; 193 struct rsi_common *common = NULL; 194 u8 ii = 0; 195 196 adapter = kzalloc(sizeof(*adapter), GFP_KERNEL); 197 if (!adapter) 198 return NULL; 199 200 adapter->priv = kzalloc(sizeof(*common), GFP_KERNEL); 201 if (adapter->priv == NULL) { 202 rsi_dbg(ERR_ZONE, "%s: Failed in allocation of memory\n", 203 __func__); 204 kfree(adapter); 205 return NULL; 206 } else { 207 common = adapter->priv; 208 common->priv = adapter; 209 } 210 211 for (ii = 0; ii < NUM_SOFT_QUEUES; ii++) 212 skb_queue_head_init(&common->tx_queue[ii]); 213 214 rsi_init_event(&common->tx_thread.event); 215 mutex_init(&common->mutex); 216 mutex_init(&common->tx_rxlock); 217 218 if (rsi_create_kthread(common, 219 &common->tx_thread, 220 rsi_tx_scheduler_thread, 221 "Tx-Thread")) { 222 rsi_dbg(ERR_ZONE, "%s: Unable to init tx thrd\n", __func__); 223 goto err; 224 } 225 226 common->init_done = true; 227 return adapter; 228 229err: 230 kfree(common); 231 kfree(adapter); 232 return NULL; 233} 234EXPORT_SYMBOL_GPL(rsi_91x_init); 235 236/** 237 * rsi_91x_deinit() - This function de-intializes os intf operations. 238 * @adapter: Pointer to the adapter structure. 239 * 240 * Return: None. 241 */ 242void rsi_91x_deinit(struct rsi_hw *adapter) 243{ 244 struct rsi_common *common = adapter->priv; 245 u8 ii; 246 247 rsi_dbg(INFO_ZONE, "%s: Performing deinit os ops\n", __func__); 248 249 rsi_kill_thread(&common->tx_thread); 250 251 for (ii = 0; ii < NUM_SOFT_QUEUES; ii++) 252 skb_queue_purge(&common->tx_queue[ii]); 253 254 common->init_done = false; 255 256 kfree(common); 257 kfree(adapter->rsi_dev); 258 kfree(adapter); 259} 260EXPORT_SYMBOL_GPL(rsi_91x_deinit); 261 262/** 263 * rsi_91x_hal_module_init() - This function is invoked when the module is 264 * loaded into the kernel. 265 * It registers the client driver. 266 * @void: Void. 267 * 268 * Return: 0 on success, -1 on failure. 269 */ 270static int rsi_91x_hal_module_init(void) 271{ 272 rsi_dbg(INIT_ZONE, "%s: Module init called\n", __func__); 273 return 0; 274} 275 276/** 277 * rsi_91x_hal_module_exit() - This function is called at the time of 278 * removing/unloading the module. 279 * It unregisters the client driver. 280 * @void: Void. 281 * 282 * Return: None. 283 */ 284static void rsi_91x_hal_module_exit(void) 285{ 286 rsi_dbg(INIT_ZONE, "%s: Module exit called\n", __func__); 287} 288 289module_init(rsi_91x_hal_module_init); 290module_exit(rsi_91x_hal_module_exit); 291MODULE_AUTHOR("Redpine Signals Inc"); 292MODULE_DESCRIPTION("Station driver for RSI 91x devices"); 293MODULE_SUPPORTED_DEVICE("RSI-91x"); 294MODULE_VERSION("0.1"); 295MODULE_LICENSE("Dual BSD/GPL"); 296