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