1
2 /*
3 * This file is part of wl12xx
4 *
5 * Copyright (C) 2008-2009 Nokia Corporation
6 *
7 * Contact: Kalle Valo <kalle.valo@nokia.com>
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * version 2 as published by the Free Software Foundation.
12 *
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
21 * 02110-1301 USA
22 *
23 */
24
25 #include <linux/module.h>
26 #include <linux/interrupt.h>
27 #include <linux/firmware.h>
28 #include <linux/delay.h>
29 #include <linux/irq.h>
30 #include <linux/spi/spi.h>
31 #include <linux/crc32.h>
32 #include <linux/etherdevice.h>
33 #include <linux/spi/wl12xx.h>
34
35 #include "wl12xx.h"
36 #include "wl12xx_80211.h"
37 #include "reg.h"
38 #include "wl1251.h"
39 #include "spi.h"
40 #include "event.h"
41 #include "tx.h"
42 #include "rx.h"
43 #include "ps.h"
44 #include "init.h"
45 #include "debugfs.h"
46
47 static void wl12xx_disable_interrupts(
struct wl12xx *wl)
48 {
49 disable_irq(wl->irq);
50 }
51
52 static void wl12xx_power_off(
struct wl12xx *wl)
53 {
54 wl->set_power(false);
55 }
56
57 static void wl12xx_power_on(
struct wl12xx *wl)
58 {
59 wl->set_power(true);
60 }
61
62 static irqreturn_t wl12xx_irq(
int irq,
void *cookie)
63 {
64 struct wl12xx *wl;
65
66 wl12xx_debug(DEBUG_IRQ,
"IRQ");
67
68 wl = cookie;
69
70 schedule_work(&wl->irq_work);
71
72 return IRQ_HANDLED;
73 }
74
75 static int wl12xx_fetch_firmware(
struct wl12xx *wl)
76 {
77 const struct firmware *fw;
78 int ret;
79
80 ret = request_firmware(&fw, wl->chip.fw_filename, &wl->spi->dev);
81
82 if (ret <
0) {
83 wl12xx_error(
"could not get firmware: %d", ret);
84 return ret;
85 }
86
87 if (fw->size %
4) {
88 wl12xx_error(
"firmware size is not multiple of 32 bits: %zu",
89 fw->size);
90 ret = -EILSEQ;
91 goto out;
92 }
93
94 wl->fw_len = fw->size;
95 wl->fw = kmalloc(wl->fw_len, GFP_KERNEL);
96
97 if (!wl->fw) {
98 wl12xx_error(
"could not allocate memory for the firmware");
99 ret = -ENOMEM;
100 goto out;
101 }
102
103 memcpy(wl->fw, fw->data, wl->fw_len);
104
105 ret =
0;
106
107 out:
108 release_firmware(fw);
109
110 return ret;
111 }
112
113 static int wl12xx_fetch_nvs(
struct wl12xx *wl)
114 {
115 const struct firmware *fw;
116 int ret;
117
118 ret = request_firmware(&fw, wl->chip.nvs_filename, &wl->spi->dev);
119
120 if (ret <
0) {
121 wl12xx_error(
"could not get nvs file: %d", ret);
122 return ret;
123 }
124
125 if (fw->size %
4) {
126 wl12xx_error(
"nvs size is not multiple of 32 bits: %zu",
127 fw->size);
128 ret = -EILSEQ;
129 goto out;
130 }
131
132 wl->nvs_len = fw->size;
133 wl->nvs = kmalloc(wl->nvs_len, GFP_KERNEL);
134
135 if (!wl->nvs) {
136 wl12xx_error(
"could not allocate memory for the nvs file");
137 ret = -ENOMEM;
138 goto out;
139 }
140
141 memcpy(wl->nvs, fw->data, wl->nvs_len);
142
143 ret =
0;
144
145 out:
146 release_firmware(fw);
147
148 return ret;
149 }
150
151 static void wl12xx_fw_wakeup(
struct wl12xx *wl)
152 {
153 u32 elp_reg;
154
155 elp_reg = ELPCTRL_WAKE_UP;
156 wl12xx_write32(wl, HW_ACCESS_ELP_CTRL_REG_ADDR, elp_reg);
157 elp_reg = wl12xx_read32(wl, HW_ACCESS_ELP_CTRL_REG_ADDR);
158
159 if (!(elp_reg & ELPCTRL_WLAN_READY)) {
160 wl12xx_warning(
"WLAN not ready");
161 elp_reg = ELPCTRL_WAKE_UP_WLAN_READY;
162 wl12xx_write32(wl, HW_ACCESS_ELP_CTRL_REG_ADDR, elp_reg);
163 }
164 }
165
166 static int wl12xx_chip_wakeup(
struct wl12xx *wl)
167 {
168 int ret =
0;
169
170 wl12xx_power_on(wl);
171 msleep(wl->chip.power_on_sleep);
172 wl12xx_spi_reset(wl);
173 wl12xx_spi_init(wl);
174
175 /* We don't need a real memory partition here, because we only want
176 * to use the registers at this point. */
177 wl12xx_set_partition(wl,
178 0x00000000,
179 0x00000000,
180 REGISTERS_BASE,
181 REGISTERS_DOWN_SIZE);
182
183 /* ELP module wake up */
184 wl12xx_fw_wakeup(wl);
185
186 /* whal_FwCtrl_BootSm() */
187
188 /* 0. read chip id from CHIP_ID */
189 wl->chip.id = wl12xx_reg_read32(wl, CHIP_ID_B);
190
191 /* 1. check if chip id is valid */
192
193 switch (wl->chip.id) {
194 case CHIP_ID_1251_PG12:
195 wl12xx_debug(DEBUG_BOOT,
"chip id 0x%x (1251 PG12)",
196 wl->chip.id);
197
198 wl1251_setup(wl);
199
200 break;
201 case CHIP_ID_1271_PG10:
202 case CHIP_ID_1251_PG10:
203 case CHIP_ID_1251_PG11:
204 default:
205 wl12xx_error(
"unsupported chip id: 0x%x", wl->chip.id);
206 ret = -ENODEV;
207 goto out;
208 }
209
210 if (wl->fw == NULL) {
211 ret = wl12xx_fetch_firmware(wl);
212 if (ret <
0)
213 goto out;
214 }
215
216 /* No NVS from netlink, try to get it from the filesystem */
217 if (wl->nvs == NULL) {
218 ret = wl12xx_fetch_nvs(wl);
219 if (ret <
0)
220 goto out;
221 }
222
223 out:
224 return ret;
225 }
226
227 static void wl12xx_filter_work(
struct work_struct *work)
228 {
229 struct wl12xx *wl =
230 container_of(work,
struct wl12xx, filter_work);
231 int ret;
232
233 mutex_lock(&wl->mutex);
234
235 if (wl->state == WL12XX_STATE_OFF)
236 goto out;
237
238 ret = wl12xx_cmd_join(wl, wl->bss_type,
1,
100,
0);
239 if (ret <
0)
240 goto out;
241
242 out:
243 mutex_unlock(&wl->mutex);
244 }
245
246 int wl12xx_plt_start(
struct wl12xx *wl)
247 {
248 int ret;
249
250 wl12xx_notice(
"power up");
251
252 if (wl->state != WL12XX_STATE_OFF) {
253 wl12xx_error(
"cannot go into PLT state because not "
254 "in off state: %d", wl->state);
255 return -EBUSY;
256 }
257
258 wl->state = WL12XX_STATE_PLT;
259
260 ret = wl12xx_chip_wakeup(wl);
261 if (ret <
0)
262 return ret;
263
264 ret = wl->chip.op_boot(wl);
265 if (ret <
0)
266 return ret;
267
268 wl12xx_notice(
"firmware booted in PLT mode (%s)", wl->chip.fw_ver);
269
270 ret = wl->chip.op_plt_init(wl);
271 if (ret <
0)
272 return ret;
273
274 return 0;
275 }
276
277 int wl12xx_plt_stop(
struct wl12xx *wl)
278 {
279 wl12xx_notice(
"power down");
280
281 if (wl->state != WL12XX_STATE_PLT) {
282 wl12xx_error(
"cannot power down because not in PLT "
283 "state: %d", wl->state);
284 return -EBUSY;
285 }
286
287 wl12xx_disable_interrupts(wl);
288 wl12xx_power_off(wl);
289
290 wl->state = WL12XX_STATE_OFF;
291
292 return 0;
293 }
294
295
296 static int wl12xx_op_tx(
struct ieee80211_hw *hw,
struct sk_buff *skb)
297 {
298 struct wl12xx *wl = hw->priv;
299
300 skb_queue_tail(&wl->tx_queue, skb);
301
302 schedule_work(&wl->tx_work);
303
304 /*
305 * The workqueue is slow to process the tx_queue and we need stop
306 * the queue here, otherwise the queue will get too long.
307 */
308 if (skb_queue_len(&wl->tx_queue) >= WL12XX_TX_QUEUE_MAX_LENGTH) {
309 ieee80211_stop_queues(wl->hw);
310
311 /*
312 * FIXME: this is racy, the variable is not properly
313 * protected. Maybe fix this by removing the stupid
314 * variable altogether and checking the real queue state?
315 */
316 wl->tx_queue_stopped = true;
317 }
318
319 return NETDEV_TX_OK;
320 }
321
322 static int wl12xx_op_start(
struct ieee80211_hw *hw)
323 {
324 struct wl12xx *wl = hw->priv;
325 int ret =
0;
326
327 wl12xx_debug(DEBUG_MAC80211,
"mac80211 start");
328
329 mutex_lock(&wl->mutex);
330
331 if (wl->state != WL12XX_STATE_OFF) {
332 wl12xx_error(
"cannot start because not in off state: %d",
333 wl->state);
334 ret = -EBUSY;
335 goto out;
336 }
337
338 ret = wl12xx_chip_wakeup(wl);
339 if (ret <
0)
340 return ret;
341
342 ret = wl->chip.op_boot(wl);
343 if (ret <
0)
344 goto out;
345
346 ret = wl->chip.op_hw_init(wl);
347 if (ret <
0)
348 goto out;
349
350 ret = wl12xx_acx_station_id(wl);
351 if (ret <
0)
352 goto out;
353
354 wl->state = WL12XX_STATE_ON;
355
356 wl12xx_info(
"firmware booted (%s)", wl->chip.fw_ver);
357
358 out:
359 if (ret <
0)
360 wl12xx_power_off(wl);
361
362 mutex_unlock(&wl->mutex);
363
364 return ret;
365 }
366
367 static void wl12xx_op_stop(
struct ieee80211_hw *hw)
368 {
369 struct wl12xx *wl = hw->priv;
370
371 wl12xx_info(
"down");
372
373 wl12xx_debug(DEBUG_MAC80211,
"mac80211 stop");
374
375 mutex_lock(&wl->mutex);
376
377 WARN_ON(wl->state != WL12XX_STATE_ON);
378
379 if (wl->scanning) {
380 mutex_unlock(&wl->mutex);
381 ieee80211_scan_completed(wl->hw, true);
382 mutex_lock(&wl->mutex);
383 wl->scanning = false;
384 }
385
386 wl->state = WL12XX_STATE_OFF;
387
388 wl12xx_disable_interrupts(wl);
389
390 mutex_unlock(&wl->mutex);
391
392 cancel_work_sync(&wl->irq_work);
393 cancel_work_sync(&wl->tx_work);
394 cancel_work_sync(&wl->filter_work);
395
396 mutex_lock(&wl->mutex);
397
398 /* let's notify MAC80211 about the remaining pending TX frames */
399 wl12xx_tx_flush(wl);
400
401 wl12xx_power_off(wl);
402
403 memset(wl->bssid,
0, ETH_ALEN);
404 wl->listen_int =
1;
405 wl->bss_type = MAX_BSS_TYPE;
406
407 wl->data_in_count =
0;
408 wl->rx_counter =
0;
409 wl->rx_handled =
0;
410 wl->rx_current_buffer =
0;
411 wl->rx_last_id =
0;
412 wl->next_tx_complete =
0;
413 wl->elp = false;
414 wl->psm =
0;
415 wl->tx_queue_stopped = false;
416 wl->power_level = WL12XX_DEFAULT_POWER_LEVEL;
417
418 wl12xx_debugfs_reset(wl);
419
420 mutex_unlock(&wl->mutex);
421 }
422
423 static int wl12xx_op_add_interface(
struct ieee80211_hw *hw,
424 struct ieee80211_if_init_conf *conf)
425 {
426 struct wl12xx *wl = hw->priv;
427 DECLARE_MAC_BUF(mac);
428 int ret =
0;
429
430 wl12xx_debug(DEBUG_MAC80211,
"mac80211 add interface type %d mac %s",
431 conf->type, print_mac(mac, conf->mac_addr));
432
433 mutex_lock(&wl->mutex);
434
435 switch (conf->type) {
436 case NL80211_IFTYPE_STATION:
437 wl->bss_type = BSS_TYPE_STA_BSS;
438 break;
439 case NL80211_IFTYPE_ADHOC:
440 wl->bss_type = BSS_TYPE_IBSS;
441 break;
442 default:
443 ret = -EOPNOTSUPP;
444 goto out;
445 }
446
447 if (memcmp(wl->mac_addr, conf->mac_addr, ETH_ALEN)) {
448 memcpy(wl->mac_addr, conf->mac_addr, ETH_ALEN);
449 SET_IEEE80211_PERM_ADDR(wl->hw, wl->mac_addr);
450 ret = wl12xx_acx_station_id(wl);
451 if (ret <
0)
452 goto out;
453 }
454
455 out:
456 mutex_unlock(&wl->mutex);
457 return ret;
458 }
459
460 static void wl12xx_op_remove_interface(
struct ieee80211_hw *hw,
461 struct ieee80211_if_init_conf *conf)
462 {
463 wl12xx_debug(DEBUG_MAC80211,
"mac80211 remove interface");
464 }
465
466 static int wl12xx_build_null_data(
struct wl12xx *wl)
467 {
468 struct wl12xx_null_data_template
template;
469
470 if (!is_zero_ether_addr(wl->bssid)) {
471 memcpy(
template.header.da, wl->bssid, ETH_ALEN);
472 memcpy(
template.header.bssid, wl->bssid, ETH_ALEN);
473 }
else {
474 memset(
template.header.da, 0xff, ETH_ALEN);
475 memset(
template.header.bssid, 0xff, ETH_ALEN);
476 }
477
478 memcpy(
template.header.sa, wl->mac_addr, ETH_ALEN);
479 template.header.frame_ctl = cpu_to_le16(IEEE80211_FTYPE_DATA |
480 IEEE80211_STYPE_NULLFUNC);
481
482 return wl12xx_cmd_template_set(wl, CMD_NULL_DATA, &
template,
483 sizeof(
template));
484
485 }
486
487 static int wl12xx_build_ps_poll(
struct wl12xx *wl, u16 aid)
488 {
489 struct wl12xx_ps_poll_template
template;
490
491 memcpy(
template.bssid, wl->bssid, ETH_ALEN);
492 memcpy(
template.ta, wl->mac_addr, ETH_ALEN);
493 template.aid = aid;
494 template.fc = cpu_to_le16(IEEE80211_FTYPE_CTL | IEEE80211_STYPE_PSPOLL);
495
496 return wl12xx_cmd_template_set(wl, CMD_PS_POLL, &
template,
497 sizeof(
template));
498
499 }
500
501 static int wl12xx_op_config(
struct ieee80211_hw *hw, u32 changed)
502 {
503 struct wl12xx *wl = hw->priv;
504 struct ieee80211_conf *conf = &hw->conf;
505 int channel, ret =
0;
506
507 channel = ieee80211_frequency_to_channel(conf->channel->center_freq);
508
509 wl12xx_debug(DEBUG_MAC80211,
"mac80211 config ch %d psm %s power %d",
510 channel,
511 conf->flags & IEEE80211_CONF_PS ?
"on" :
"off",
512 conf->power_level);
513
514 mutex_lock(&wl->mutex);
515
516 if (channel != wl->channel) {
517 /* FIXME: use beacon interval provided by mac80211 */
518 ret = wl12xx_cmd_join(wl, wl->bss_type,
1,
100,
0);
519 if (ret <
0)
520 goto out;
521
522 wl->channel = channel;
523 }
524
525 ret = wl12xx_build_null_data(wl);
526 if (ret <
0)
527 goto out;
528
529 if (conf->flags & IEEE80211_CONF_PS && !wl->psm_requested) {
530 wl12xx_info(
"psm enabled");
531
532 wl->psm_requested = true;
533
534 /*
535 * We enter PSM only if we're already associated.
536 * If we're not, we'll enter it when joining an SSID,
537 * through the bss_info_changed() hook.
538 */
539 ret = wl12xx_ps_set_mode(wl, STATION_POWER_SAVE_MODE);
540 }
else if (!(conf->flags & IEEE80211_CONF_PS) &&
541 wl->psm_requested) {
542 wl12xx_info(
"psm disabled");
543
544 wl->psm_requested = false;
545
546 if (wl->psm)
547 ret = wl12xx_ps_set_mode(wl, STATION_ACTIVE_MODE);
548 }
549
550 if (conf->power_level != wl->power_level) {
551 ret = wl12xx_acx_tx_power(wl, conf->power_level);
552 if (ret <
0)
553 goto out;
554
555 wl->power_level = conf->power_level;
556 }
557
558 out:
559 mutex_unlock(&wl->mutex);
560 return ret;
561 }
562
563 #define WL12XX_SUPPORTED_FILTERS (FIF_PROMISC_IN_BSS | \
564 FIF_ALLMULTI | \
565 FIF_FCSFAIL | \
566 FIF_BCN_PRBRESP_PROMISC | \
567 FIF_CONTROL | \
568 FIF_OTHER_BSS)
569
570 static void wl12xx_op_configure_filter(
struct ieee80211_hw *hw,
571 unsigned int changed,
572 unsigned int *total,
573 int mc_count,
574 struct dev_addr_list *mc_list)
575 {
576 struct wl12xx *wl = hw->priv;
577
578 wl12xx_debug(DEBUG_MAC80211,
"mac80211 configure filter");
579
580 *total &= WL12XX_SUPPORTED_FILTERS;
581 changed &= WL12XX_SUPPORTED_FILTERS;
582
583 if (changed ==
0)
584 /* no filters which we support changed */
585 return;
586
587 /* FIXME: wl->rx_config and wl->rx_filter are not protected */
588
589 wl->rx_config = WL12XX_DEFAULT_RX_CONFIG;
590 wl->rx_filter = WL12XX_DEFAULT_RX_FILTER;
591
592 if (*total & FIF_PROMISC_IN_BSS) {
593 wl->rx_config |= CFG_BSSID_FILTER_EN;
594 wl->rx_config |= CFG_RX_ALL_GOOD;
595 }
596 if (*total & FIF_ALLMULTI)
597 /*
598 * CFG_MC_FILTER_EN in rx_config needs to be 0 to receive
599 * all multicast frames
600 */
601 wl->rx_config &= ~CFG_MC_FILTER_EN;
602 if (*total & FIF_FCSFAIL)
603 wl->rx_filter |= CFG_RX_FCS_ERROR;
604 if (*total & FIF_BCN_PRBRESP_PROMISC) {
605 wl->rx_config &= ~CFG_BSSID_FILTER_EN;
606 wl->rx_config &= ~CFG_SSID_FILTER_EN;
607 }
608 if (*total & FIF_CONTROL)
609 wl->rx_filter |= CFG_RX_CTL_EN;
610 if (*total & FIF_OTHER_BSS)
611 wl->rx_filter &= ~CFG_BSSID_FILTER_EN;
612
613 /*
614 * FIXME: workqueues need to be properly cancelled on stop(), for
615 * now let's just disable changing the filter settings. They will
616 * be updated any on config().
617 */
618 /* schedule_work(&wl->filter_work); */
619 }
620
621 /* HW encryption */
622 static int wl12xx_set_key_type(
struct wl12xx *wl,
struct acx_set_key *key,
623 enum set_key_cmd cmd,
624 struct ieee80211_key_conf *mac80211_key,
625 const u8 *addr)
626 {
627 switch (mac80211_key->alg) {
628 case ALG_WEP:
629 if (is_broadcast_ether_addr(addr))
630 key->key_type = KEY_WEP_DEFAULT;
631 else
632 key->key_type = KEY_WEP_ADDR;
633
634 mac80211_key->hw_key_idx = mac80211_key->keyidx;
635 break;
636 case ALG_TKIP:
637 if (is_broadcast_ether_addr(addr))
638 key->key_type = KEY_TKIP_MIC_GROUP;
639 else
640 key->key_type = KEY_TKIP_MIC_PAIRWISE;
641
642 mac80211_key->hw_key_idx = mac80211_key->keyidx;
643 break;
644 case ALG_CCMP:
645 if (is_broadcast_ether_addr(addr))
646 key->key_type = KEY_AES_GROUP;
647 else
648 key->key_type = KEY_AES_PAIRWISE;
649 mac80211_key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
650 break;
651 default:
652 wl12xx_error(
"Unknown key algo 0x%x", mac80211_key->alg);
653 return -EOPNOTSUPP;
654 }
655
656 return 0;
657 }
658
659 static int wl12xx_op_set_key(
struct ieee80211_hw *hw,
enum set_key_cmd cmd,
660 struct ieee80211_vif *vif,
661 struct ieee80211_sta *sta,
662 struct ieee80211_key_conf *key)
663 {
664 struct wl12xx *wl = hw->priv;
665 struct acx_set_key wl_key;
666 const u8 *addr;
667 int ret;
668
669 static const u8 bcast_addr[ETH_ALEN] =
670 { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
671
672 wl12xx_debug(DEBUG_MAC80211,
"mac80211 set key");
673
674 memset(&wl_key,
0,
sizeof(wl_key));
675
676 addr = sta ? sta->addr : bcast_addr;
677
678 wl12xx_debug(DEBUG_CRYPT,
"CMD: 0x%x", cmd);
679 wl12xx_dump(DEBUG_CRYPT,
"ADDR: ", addr, ETH_ALEN);
680 wl12xx_debug(DEBUG_CRYPT,
"Key: algo:0x%x, id:%d, len:%d flags 0x%x",
681 key->alg, key->keyidx, key->keylen, key->flags);
682 wl12xx_dump(DEBUG_CRYPT,
"KEY: ", key->key, key->keylen);
683
684 mutex_lock(&wl->mutex);
685
686 switch (cmd) {
687 case SET_KEY:
688 wl_key.key_action = KEY_ADD_OR_REPLACE;
689 break;
690 case DISABLE_KEY:
691 wl_key.key_action = KEY_REMOVE;
692 break;
693 default:
694 wl12xx_error(
"Unsupported key cmd 0x%x", cmd);
695 break;
696 }
697
698 ret = wl12xx_set_key_type(wl, &wl_key, cmd, key, addr);
699 if (ret <
0) {
700 wl12xx_error(
"Set KEY type failed");
701 goto out;
702 }
703
704 if (wl_key.key_type != KEY_WEP_DEFAULT)
705 memcpy(wl_key.addr, addr, ETH_ALEN);
706
707 if ((wl_key.key_type == KEY_TKIP_MIC_GROUP) ||
708 (wl_key.key_type == KEY_TKIP_MIC_PAIRWISE)) {
709 /*
710 * We get the key in the following form:
711 * TKIP (16 bytes) - TX MIC (8 bytes) - RX MIC (8 bytes)
712 * but the target is expecting:
713 * TKIP - RX MIC - TX MIC
714 */
715 memcpy(wl_key.key, key->key,
16);
716 memcpy(wl_key.key +
16, key->key +
24,
8);
717 memcpy(wl_key.key +
24, key->key +
16,
8);
718
719 }
else {
720 memcpy(wl_key.key, key->key, key->keylen);
721 }
722 wl_key.key_size = key->keylen;
723
724 wl_key.id = key->keyidx;
725 wl_key.ssid_profile =
0;
726
727 wl12xx_dump(DEBUG_CRYPT,
"TARGET KEY: ", &wl_key,
sizeof(wl_key));
728
729 if (wl12xx_cmd_send(wl, CMD_SET_KEYS, &wl_key,
sizeof(wl_key)) <
0) {
730 wl12xx_error(
"Set KEY failed");
731 ret = -EOPNOTSUPP;
732 goto out;
733 }
734
735 out:
736 mutex_unlock(&wl->mutex);
737 return ret;
738 }
739
740 static int wl12xx_build_basic_rates(
char *rates)
741 {
742 u8 index =
0;
743
744 rates[index++] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_1MB;
745 rates[index++] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_2MB;
746 rates[index++] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_5MB;
747 rates[index++] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_11MB;
748
749 return index;
750 }
751
752 static int wl12xx_build_extended_rates(
char *rates)
753 {
754 u8 index =
0;
755
756 rates[index++] = IEEE80211_OFDM_RATE_6MB;
757 rates[index++] = IEEE80211_OFDM_RATE_9MB;
758 rates[index++] = IEEE80211_OFDM_RATE_12MB;
759 rates[index++] = IEEE80211_OFDM_RATE_18MB;
760 rates[index++] = IEEE80211_OFDM_RATE_24MB;
761 rates[index++] = IEEE80211_OFDM_RATE_36MB;
762 rates[index++] = IEEE80211_OFDM_RATE_48MB;
763 rates[index++] = IEEE80211_OFDM_RATE_54MB;
764
765 return index;
766 }
767
768
769 static int wl12xx_build_probe_req(
struct wl12xx *wl, u8 *ssid, size_t ssid_len)
770 {
771 struct wl12xx_probe_req_template
template;
772 struct wl12xx_ie_rates *rates;
773 char *ptr;
774 u16 size;
775
776 ptr = (
char *)&
template;
777 size =
sizeof(
struct ieee80211_header);
778
779 memset(
template.header.da, 0xff, ETH_ALEN);
780 memset(
template.header.bssid, 0xff, ETH_ALEN);
781 memcpy(
template.header.sa, wl->mac_addr, ETH_ALEN);
782 template.header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_PROBE_REQ);
783
784 /* IEs */
785 /* SSID */
786 template.ssid.header.id = WLAN_EID_SSID;
787 template.ssid.header.len = ssid_len;
788 if (ssid_len && ssid)
789 memcpy(
template.ssid.ssid, ssid, ssid_len);
790 size +=
sizeof(
struct wl12xx_ie_header) + ssid_len;
791 ptr += size;
792
793 /* Basic Rates */
794 rates = (
struct wl12xx_ie_rates *)ptr;
795 rates->header.id = WLAN_EID_SUPP_RATES;
796 rates->header.len = wl12xx_build_basic_rates(rates->rates);
797 size +=
sizeof(
struct wl12xx_ie_header) + rates->header.len;
798 ptr +=
sizeof(
struct wl12xx_ie_header) + rates->header.len;
799
800 /* Extended rates */
801 rates = (
struct wl12xx_ie_rates *)ptr;
802 rates->header.id = WLAN_EID_EXT_SUPP_RATES;
803 rates->header.len = wl12xx_build_extended_rates(rates->rates);
804 size +=
sizeof(
struct wl12xx_ie_header) + rates->header.len;
805
806 wl12xx_dump(DEBUG_SCAN,
"PROBE REQ: ", &
template, size);
807
808 return wl12xx_cmd_template_set(wl, CMD_PROBE_REQ, &
template,
809 size);
810 }
811
812 static int wl12xx_hw_scan(
struct wl12xx *wl, u8 *ssid, size_t len,
813 u8 active_scan, u8 high_prio, u8 num_channels,
814 u8 probe_requests)
815 {
816 int i, ret;
817 u32 split_scan =
0;
818 u16 scan_options =
0;
819 struct cmd_scan *params;
820 struct wl12xx_command *cmd_answer;
821
822 if (wl->scanning)
823 return -EINVAL;
824
825 params = kzalloc(
sizeof(*params), GFP_KERNEL);
826 if (!params)
827 return -ENOMEM;
828
829 params->params.rx_config_options = cpu_to_le32(CFG_RX_ALL_GOOD);
830 params->params.rx_filter_options =
831 cpu_to_le32(CFG_RX_PRSP_EN | CFG_RX_MGMT_EN | CFG_RX_BCN_EN);
832
833 /* High priority scan */
834 if (!active_scan)
835 scan_options |= SCAN_PASSIVE;
836 if (high_prio)
837 scan_options |= SCAN_PRIORITY_HIGH;
838 params->params.scan_options = scan_options;
839
840 params->params.num_channels = num_channels;
841 params->params.num_probe_requests = probe_requests;
842 params->params.tx_rate = cpu_to_le16(
1 <<
1);
/* 2 Mbps */
843 params->params.tid_trigger =
0;
844
845 for (i =
0; i < num_channels; i++) {
846 params->channels[i].min_duration = cpu_to_le32(
30000);
847 params->channels[i].max_duration = cpu_to_le32(
60000);
848 memset(¶ms->channels[i].bssid_lsb, 0xff,
4);
849 memset(¶ms->channels[i].bssid_msb, 0xff,
2);
850 params->channels[i].early_termination =
0;
851 params->channels[i].tx_power_att =
0;
852 params->channels[i].channel = i +
1;
853 memset(params->channels[i].pad,
0,
3);
854 }
855
856 for (i = num_channels; i < SCAN_MAX_NUM_OF_CHANNELS; i++)
857 memset(¶ms->channels[i],
0,
858 sizeof(
struct basic_scan_channel_parameters));
859
860 if (len && ssid) {
861 params->params.ssid_len = len;
862 memcpy(params->params.ssid, ssid, len);
863 }
else {
864 params->params.ssid_len =
0;
865 memset(params->params.ssid,
0,
32);
866 }
867
868 ret = wl12xx_build_probe_req(wl, ssid, len);
869 if (ret <
0) {
870 wl12xx_error(
"PROBE request template failed");
871 goto out;
872 }
873
874 ret = wl12xx_cmd_send(wl, CMD_TRIGGER_SCAN_TO, &split_scan,
875 sizeof(u32));
876 if (ret <
0) {
877 wl12xx_error(
"Split SCAN failed");
878 goto out;
879 }
880
881 wl12xx_dump(DEBUG_SCAN,
"SCAN: ", params,
sizeof(*params));
882
883 wl->scanning = true;
884
885 ret = wl12xx_cmd_send(wl, CMD_SCAN, params,
sizeof(*params));
886 if (ret <
0)
887 wl12xx_error(
"SCAN failed");
888
889 wl12xx_spi_mem_read(wl, wl->cmd_box_addr, params,
sizeof(*params));
890
891 cmd_answer = (
struct wl12xx_command *) params;
892 if (cmd_answer->status != CMD_STATUS_SUCCESS) {
893 wl12xx_error(
"TEST command answer error: %d",
894 cmd_answer->status);
895 wl->scanning = false;
896 ret = -EIO;
897 goto out;
898 }
899
900 out:
901 kfree(params);
902 return ret;
903
904 }
905
906 static int wl12xx_op_hw_scan(
struct ieee80211_hw *hw,
907 struct cfg80211_scan_request *req)
908 {
909 struct wl12xx *wl = hw->priv;
910 int ret;
911 u8 *ssid = NULL;
912 size_t ssid_len =
0;
913
914 wl12xx_debug(DEBUG_MAC80211,
"mac80211 hw scan");
915
916 if (req->n_ssids) {
917 ssid = req->ssids[
0].ssid;
918 ssid_len = req->ssids[
0].ssid_len;
919 }
920
921 mutex_lock(&wl->mutex);
922 ret = wl12xx_hw_scan(hw->priv, ssid, ssid_len,
1,
0,
13,
3);
923 mutex_unlock(&wl->mutex);
924
925 return ret;
926 }
927
928 static int wl12xx_op_set_rts_threshold(
struct ieee80211_hw *hw, u32 value)
929 {
930 struct wl12xx *wl = hw->priv;
931 int ret;
932
933 ret = wl12xx_acx_rts_threshold(wl, (u16) value);
934
935 if (ret <
0)
936 wl12xx_warning(
"wl12xx_op_set_rts_threshold failed: %d", ret);
937
938 return ret;
939 }
940
941 static void wl12xx_op_bss_info_changed(
struct ieee80211_hw *hw,
942 struct ieee80211_vif *vif,
943 struct ieee80211_bss_conf *bss_conf,
944 u32 changed)
945 {
946 enum acx_ps_mode mode;
947 struct wl12xx *wl = hw->priv;
948 struct sk_buff *beacon;
949 int ret;
950
951 wl12xx_debug(DEBUG_MAC80211,
"mac80211 bss info changed");
952
953 mutex_lock(&wl->mutex);
954
955 if (changed & BSS_CHANGED_ASSOC) {
956 if (bss_conf->assoc) {
957 wl->aid = bss_conf->aid;
958
959 ret = wl12xx_build_ps_poll(wl, wl->aid);
960 if (ret <
0)
961 goto out;
962
963 ret = wl12xx_acx_aid(wl, wl->aid);
964 if (ret <
0)
965 goto out;
966
967 /* If we want to go in PSM but we're not there yet */
968 if (wl->psm_requested && !wl->psm) {
969 mode = STATION_POWER_SAVE_MODE;
970 ret = wl12xx_ps_set_mode(wl, mode);
971 if (ret <
0)
972 goto out;
973 }
974 }
975 }
976 if (changed & BSS_CHANGED_ERP_SLOT) {
977 if (bss_conf->use_short_slot)
978 ret = wl12xx_acx_slot(wl, SLOT_TIME_SHORT);
979 else
980 ret = wl12xx_acx_slot(wl, SLOT_TIME_LONG);
981 if (ret <
0) {
982 wl12xx_warning(
"Set slot time failed %d", ret);
983 goto out;
984 }
985 }
986
987 if (changed & BSS_CHANGED_ERP_PREAMBLE) {
988 if (bss_conf->use_short_preamble)
989 wl12xx_acx_set_preamble(wl, ACX_PREAMBLE_SHORT);
990 else
991 wl12xx_acx_set_preamble(wl, ACX_PREAMBLE_LONG);
992 }
993
994 if (changed & BSS_CHANGED_ERP_CTS_PROT) {
995 if (bss_conf->use_cts_prot)
996 ret = wl12xx_acx_cts_protect(wl, CTSPROTECT_ENABLE);
997 else
998 ret = wl12xx_acx_cts_protect(wl, CTSPROTECT_DISABLE);
999 if (ret <
0) {
1000 wl12xx_warning(
"Set ctsprotect failed %d", ret);
1001 goto out;
1002 }
1003 }
1004
1005 if (changed & BSS_CHANGED_BSSID) {
1006 memcpy(wl->bssid, bss_conf->bssid, ETH_ALEN);
1007
1008 ret = wl12xx_build_null_data(wl);
1009 if (ret <
0)
1010 goto out;
1011
1012 if (wl->bss_type != BSS_TYPE_IBSS) {
1013 ret = wl12xx_cmd_join(wl, wl->bss_type,
5,
100,
1);
1014 if (ret <
0)
1015 goto out;
1016 }
1017 }
1018
1019 if (changed & BSS_CHANGED_BEACON) {
1020 beacon = ieee80211_beacon_get(hw, vif);
1021 ret = wl12xx_cmd_template_set(wl, CMD_BEACON, beacon->data,
1022 beacon->len);
1023
1024 if (ret <
0) {
1025 dev_kfree_skb(beacon);
1026 goto out;
1027 }
1028
1029 ret = wl12xx_cmd_template_set(wl, CMD_PROBE_RESP, beacon->data,
1030 beacon->len);
1031
1032 dev_kfree_skb(beacon);
1033
1034 if (ret <
0)
1035 goto out;
1036
1037 ret = wl12xx_cmd_join(wl, wl->bss_type,
1,
100,
0);
1038
1039 if (ret <
0)
1040 goto out;
1041 }
1042
1043 out:
1044 mutex_unlock(&wl->mutex);
1045 }
1046
1047
1048 /* can't be const, mac80211 writes to this */
1049 static struct ieee80211_rate wl12xx_rates[] = {
1050 { .bitrate =
10,
1051 .hw_value = 0x1,
1052 .hw_value_short = 0x1, },
1053 { .bitrate =
20,
1054 .hw_value = 0x2,
1055 .hw_value_short = 0x2,
1056 .flags = IEEE80211_RATE_SHORT_PREAMBLE },
1057 { .bitrate =
55,
1058 .hw_value = 0x4,
1059 .hw_value_short = 0x4,
1060 .flags = IEEE80211_RATE_SHORT_PREAMBLE },
1061 { .bitrate =
110,
1062 .hw_value = 0x20,
1063 .hw_value_short = 0x20,
1064 .flags = IEEE80211_RATE_SHORT_PREAMBLE },
1065 { .bitrate =
60,
1066 .hw_value = 0x8,
1067 .hw_value_short = 0x8, },
1068 { .bitrate =
90,
1069 .hw_value = 0x10,
1070 .hw_value_short = 0x10, },
1071 { .bitrate =
120,
1072 .hw_value = 0x40,
1073 .hw_value_short = 0x40, },
1074 { .bitrate =
180,
1075 .hw_value = 0x80,
1076 .hw_value_short = 0x80, },
1077 { .bitrate =
240,
1078 .hw_value = 0x200,
1079 .hw_value_short = 0x200, },
1080 { .bitrate =
360,
1081 .hw_value = 0x400,
1082 .hw_value_short = 0x400, },
1083 { .bitrate =
480,
1084 .hw_value = 0x800,
1085 .hw_value_short = 0x800, },
1086 { .bitrate =
540,
1087 .hw_value = 0x1000,
1088 .hw_value_short = 0x1000, },
1089 };
1090
1091 /* can't be const, mac80211 writes to this */
1092 static struct ieee80211_channel wl12xx_channels[] = {
1093 { .hw_value =
1, .center_freq =
2412},
1094 { .hw_value =
2, .center_freq =
2417},
1095 { .hw_value =
3, .center_freq =
2422},
1096 { .hw_value =
4, .center_freq =
2427},
1097 { .hw_value =
5, .center_freq =
2432},
1098 { .hw_value =
6, .center_freq =
2437},
1099 { .hw_value =
7, .center_freq =
2442},
1100 { .hw_value =
8, .center_freq =
2447},
1101 { .hw_value =
9, .center_freq =
2452},
1102 { .hw_value =
10, .center_freq =
2457},
1103 { .hw_value =
11, .center_freq =
2462},
1104 { .hw_value =
12, .center_freq =
2467},
1105 { .hw_value =
13, .center_freq =
2472},
1106 };
1107
1108 /* can't be const, mac80211 writes to this */
1109 static struct ieee80211_supported_band wl12xx_band_2ghz = {
1110 .channels = wl12xx_channels,
1111 .n_channels = ARRAY_SIZE(wl12xx_channels),
1112 .bitrates = wl12xx_rates,
1113 .n_bitrates = ARRAY_SIZE(wl12xx_rates),
1114 };
1115
1116 static const struct ieee80211_ops wl12xx_ops = {
1117 .start = wl12xx_op_start,
1118 .stop = wl12xx_op_stop,
1119 .add_interface = wl12xx_op_add_interface,
1120 .remove_interface = wl12xx_op_remove_interface,
1121 .config = wl12xx_op_config,
1122 .configure_filter = wl12xx_op_configure_filter,
1123 .tx = wl12xx_op_tx,
1124 .set_key = wl12xx_op_set_key,
1125 .hw_scan = wl12xx_op_hw_scan,
1126 .bss_info_changed = wl12xx_op_bss_info_changed,
1127 .set_rts_threshold = wl12xx_op_set_rts_threshold,
1128 };
1129
1130 static int wl12xx_register_hw(
struct wl12xx *wl)
1131 {
1132 int ret;
1133
1134 if (wl->mac80211_registered)
1135 return 0;
1136
1137 SET_IEEE80211_PERM_ADDR(wl->hw, wl->mac_addr);
1138
1139 ret = ieee80211_register_hw(wl->hw);
1140 if (ret <
0) {
1141 wl12xx_error(
"unable to register mac80211 hw: %d", ret);
1142 return ret;
1143 }
1144
1145 wl->mac80211_registered = true;
1146
1147 wl12xx_notice(
"loaded");
1148
1149 return 0;
1150 }
1151
1152 static int wl12xx_init_ieee80211(
struct wl12xx *wl)
1153 {
1154 /* The tx descriptor buffer and the TKIP space */
1155 wl->hw->extra_tx_headroom =
sizeof(
struct tx_double_buffer_desc)
1156 + WL12XX_TKIP_IV_SPACE;
1157
1158 /* unit us */
1159 /* FIXME: find a proper value */
1160 wl->hw->channel_change_time =
10000;
1161
1162 wl->hw->flags = IEEE80211_HW_SIGNAL_DBM |
1163 IEEE80211_HW_NOISE_DBM;
1164
1165 wl->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION);
1166 wl->hw->wiphy->max_scan_ssids =
1;
1167 wl->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &wl12xx_band_2ghz;
1168
1169 SET_IEEE80211_DEV(wl->hw, &wl->spi->dev);
1170
1171 return 0;
1172 }
1173
1174 #define WL12XX_DEFAULT_CHANNEL
1
1175 static int __devinit wl12xx_probe(
struct spi_device *spi)
1176 {
1177 struct wl12xx_platform_data *pdata;
1178 struct ieee80211_hw *hw;
1179 struct wl12xx *wl;
1180 int ret, i;
1181 static const u8 nokia_oui[
3] = {0x00, 0x1f, 0xdf};
1182
1183 pdata = spi->dev.platform_data;
1184 if (!pdata) {
1185 wl12xx_error(
"no platform data");
1186 return -ENODEV;
1187 }
1188
1189 hw = ieee80211_alloc_hw(
sizeof(*wl), &wl12xx_ops);
1190 if (!hw) {
1191 wl12xx_error(
"could not alloc ieee80211_hw");
1192 return -ENOMEM;
1193 }
1194
1195 wl = hw->priv;
1196 memset(wl,
0,
sizeof(*wl));
1197
1198 wl->hw = hw;
1199 dev_set_drvdata(&spi->dev, wl);
1200 wl->spi = spi;
1201
1202 wl->data_in_count =
0;
1203
1204 skb_queue_head_init(&wl->tx_queue);
1205
1206 INIT_WORK(&wl->tx_work, wl12xx_tx_work);
1207 INIT_WORK(&wl->filter_work, wl12xx_filter_work);
1208 wl->channel = WL12XX_DEFAULT_CHANNEL;
1209 wl->scanning = false;
1210 wl->default_key =
0;
1211 wl->listen_int =
1;
1212 wl->rx_counter =
0;
1213 wl->rx_handled =
0;
1214 wl->rx_current_buffer =
0;
1215 wl->rx_last_id =
0;
1216 wl->rx_config = WL12XX_DEFAULT_RX_CONFIG;
1217 wl->rx_filter = WL12XX_DEFAULT_RX_FILTER;
1218 wl->elp = false;
1219 wl->psm =
0;
1220 wl->psm_requested = false;
1221 wl->tx_queue_stopped = false;
1222 wl->power_level = WL12XX_DEFAULT_POWER_LEVEL;
1223
1224 /* We use the default power on sleep time until we know which chip
1225 * we're using */
1226 wl->chip.power_on_sleep = WL12XX_DEFAULT_POWER_ON_SLEEP;
1227
1228 for (i =
0; i < FW_TX_CMPLT_BLOCK_SIZE; i++)
1229 wl->tx_frames[i] = NULL;
1230
1231 wl->next_tx_complete =
0;
1232
1233 /*
1234 * In case our MAC address is not correctly set,
1235 * we use a random but Nokia MAC.
1236 */
1237 memcpy(wl->mac_addr, nokia_oui,
3);
1238 get_random_bytes(wl->mac_addr +
3,
3);
1239
1240 wl->state = WL12XX_STATE_OFF;
1241 mutex_init(&wl->mutex);
1242
1243 wl->tx_mgmt_frm_rate = DEFAULT_HW_GEN_TX_RATE;
1244 wl->tx_mgmt_frm_mod = DEFAULT_HW_GEN_MODULATION_TYPE;
1245
1246 /* This is the only SPI value that we need to set here, the rest
1247 * comes from the board-peripherals file */
1248 spi->bits_per_word =
32;
1249
1250 ret = spi_setup(spi);
1251 if (ret <
0) {
1252 wl12xx_error(
"spi_setup failed");
1253 goto out_free;
1254 }
1255
1256 wl->set_power = pdata->set_power;
1257 if (!wl->set_power) {
1258 wl12xx_error(
"set power function missing in platform data");
1259 return -ENODEV;
1260 }
1261
1262 wl->irq = spi->irq;
1263 if (wl->irq <
0) {
1264 wl12xx_error(
"irq missing in platform data");
1265 return -ENODEV;
1266 }
1267
1268 ret = request_irq(wl->irq, wl12xx_irq,
0, DRIVER_NAME, wl);
1269 if (ret <
0) {
1270 wl12xx_error(
"request_irq() failed: %d", ret);
1271 goto out_free;
1272 }
1273
1274 set_irq_type(wl->irq, IRQ_TYPE_EDGE_RISING);
1275
1276 disable_irq(wl->irq);
1277
1278 ret = wl12xx_init_ieee80211(wl);
1279 if (ret)
1280 goto out_irq;
1281
1282 ret = wl12xx_register_hw(wl);
1283 if (ret)
1284 goto out_irq;
1285
1286 wl12xx_debugfs_init(wl);
1287
1288 wl12xx_notice(
"initialized");
1289
1290 return 0;
1291
1292 out_irq:
1293 free_irq(wl->irq, wl);
1294
1295 out_free:
1296 ieee80211_free_hw(hw);
1297
1298 return ret;
1299 }
1300
1301 static int __devexit wl12xx_remove(
struct spi_device *spi)
1302 {
1303 struct wl12xx *wl = dev_get_drvdata(&spi->dev);
1304
1305 ieee80211_unregister_hw(wl->hw);
1306
1307 wl12xx_debugfs_exit(wl);
1308
1309 free_irq(wl->irq, wl);
1310 kfree(wl->target_mem_map);
1311 kfree(wl->data_path);
1312 kfree(wl->fw);
1313 wl->fw = NULL;
1314 kfree(wl->nvs);
1315 wl->nvs = NULL;
1316 ieee80211_free_hw(wl->hw);
1317
1318 return 0;
1319 }
1320
1321
1322 static struct spi_driver wl12xx_spi_driver = {
1323 .driver = {
1324 .name =
"wl12xx",
1325 .bus = &spi_bus_type,
1326 .owner = THIS_MODULE,
1327 },
1328
1329 .probe = wl12xx_probe,
1330 .remove = __devexit_p(wl12xx_remove),
1331 };
1332
1333 static int __init wl12xx_init(
void)
1334 {
1335 int ret;
1336
1337 ret = spi_register_driver(&wl12xx_spi_driver);
1338 if (ret <
0) {
1339 wl12xx_error(
"failed to register spi driver: %d", ret);
1340 goto out;
1341 }
1342
1343 out:
1344 return ret;
1345 }
1346
1347 static void __exit wl12xx_exit(
void)
1348 {
1349 spi_unregister_driver(&wl12xx_spi_driver);
1350
1351 wl12xx_notice(
"unloaded");
1352 }
1353
1354 module_init(wl12xx_init);
1355 module_exit(wl12xx_exit);
1356
1357 MODULE_LICENSE(
"GPL");
1358 MODULE_AUTHOR(
"Kalle Valo <Kalle.Valo@nokia.com>, "
1359 "Luciano Coelho <luciano.coelho@nokia.com>");
1360
1361
1362
1363
1364
1365 /* LDV_COMMENT_BEGIN_MAIN */
1366 #ifdef LDV_MAIN0_sequence_infinite_withcheck_stateful
1367
1368 /*###########################################################################*/
1369
1370 /*############## Driver Environment Generator 0.2 output ####################*/
1371
1372 /*###########################################################################*/
1373
1374
1375
1376 /* LDV_COMMENT_FUNCTION_DECLARE_LDV Special function for LDV verifier. Test if all kernel resources are correctly released by driver before driver will be unloaded. */
1377 void ldv_check_final_state(
void);
1378
1379 /* LDV_COMMENT_FUNCTION_DECLARE_LDV Special function for LDV verifier. Test correct return result. */
1380 void ldv_check_return_value(
int res);
1381
1382 /* LDV_COMMENT_FUNCTION_DECLARE_LDV Special function for LDV verifier. Initializes the model. */
1383 void ldv_initialize(
void);
1384
1385 /* LDV_COMMENT_FUNCTION_DECLARE_LDV Special function for LDV verifier. Returns arbitrary interger value. */
1386 int nondet_int(
void);
1387
1388 /* LDV_COMMENT_VAR_DECLARE_LDV Special variable for LDV verifier. */
1389 int LDV_IN_INTERRUPT;
1390
1391 /* LDV_COMMENT_FUNCTION_MAIN Main function for LDV verifier. */
1392 void ldv_main0_sequence_infinite_withcheck_stateful(
void) {
1393
1394
1395
1396 /* LDV_COMMENT_BEGIN_VARIABLE_DECLARATION_PART */
1397 /*============================= VARIABLE DECLARATION PART =============================*/
1398 /** STRUCT: struct type: ieee80211_ops, struct name: wl12xx_ops **/
1399 /* content: static int wl12xx_op_start(struct ieee80211_hw *hw)*/
1400 /* LDV_COMMENT_END_PREP */
1401 /* LDV_COMMENT_VAR_DECLARE Variable declaration for function "wl12xx_op_start" */
1402 struct ieee80211_hw * var_group1;
1403 /* LDV_COMMENT_BEGIN_PREP */
1404 #define WL12XX_SUPPORTED_FILTERS (FIF_PROMISC_IN_BSS | \
1405 FIF_ALLMULTI | \
1406 FIF_FCSFAIL | \
1407 FIF_BCN_PRBRESP_PROMISC | \
1408 FIF_CONTROL | \
1409 FIF_OTHER_BSS)
1410 #define WL12XX_DEFAULT_CHANNEL
1
1411 /* LDV_COMMENT_END_PREP */
1412 /* content: static void wl12xx_op_stop(struct ieee80211_hw *hw)*/
1413 /* LDV_COMMENT_END_PREP */
1414 /* LDV_COMMENT_BEGIN_PREP */
1415 #define WL12XX_SUPPORTED_FILTERS (FIF_PROMISC_IN_BSS | \
1416 FIF_ALLMULTI | \
1417 FIF_FCSFAIL | \
1418 FIF_BCN_PRBRESP_PROMISC | \
1419 FIF_CONTROL | \
1420 FIF_OTHER_BSS)
1421 #define WL12XX_DEFAULT_CHANNEL
1
1422 /* LDV_COMMENT_END_PREP */
1423 /* content: static int wl12xx_op_add_interface(struct ieee80211_hw *hw, struct ieee80211_if_init_conf *conf)*/
1424 /* LDV_COMMENT_END_PREP */
1425 /* LDV_COMMENT_VAR_DECLARE Variable declaration for function "wl12xx_op_add_interface" */
1426 struct ieee80211_if_init_conf * var_group2;
1427 /* LDV_COMMENT_BEGIN_PREP */
1428 #define WL12XX_SUPPORTED_FILTERS (FIF_PROMISC_IN_BSS | \
1429 FIF_ALLMULTI | \
1430 FIF_FCSFAIL | \
1431 FIF_BCN_PRBRESP_PROMISC | \
1432 FIF_CONTROL | \
1433 FIF_OTHER_BSS)
1434 #define WL12XX_DEFAULT_CHANNEL
1
1435 /* LDV_COMMENT_END_PREP */
1436 /* content: static void wl12xx_op_remove_interface(struct ieee80211_hw *hw, struct ieee80211_if_init_conf *conf)*/
1437 /* LDV_COMMENT_END_PREP */
1438 /* LDV_COMMENT_BEGIN_PREP */
1439 #define WL12XX_SUPPORTED_FILTERS (FIF_PROMISC_IN_BSS | \
1440 FIF_ALLMULTI | \
1441 FIF_FCSFAIL | \
1442 FIF_BCN_PRBRESP_PROMISC | \
1443 FIF_CONTROL | \
1444 FIF_OTHER_BSS)
1445 #define WL12XX_DEFAULT_CHANNEL
1
1446 /* LDV_COMMENT_END_PREP */
1447 /* content: static int wl12xx_op_config(struct ieee80211_hw *hw, u32 changed)*/
1448 /* LDV_COMMENT_END_PREP */
1449 /* LDV_COMMENT_VAR_DECLARE Variable declaration for function "wl12xx_op_config" */
1450 u32 var_wl12xx_op_config_18_p1;
1451 /* LDV_COMMENT_BEGIN_PREP */
1452 #define WL12XX_SUPPORTED_FILTERS (FIF_PROMISC_IN_BSS | \
1453 FIF_ALLMULTI | \
1454 FIF_FCSFAIL | \
1455 FIF_BCN_PRBRESP_PROMISC | \
1456 FIF_CONTROL | \
1457 FIF_OTHER_BSS)
1458 #define WL12XX_DEFAULT_CHANNEL
1
1459 /* LDV_COMMENT_END_PREP */
1460 /* content: FIF_OTHER_BSS) static void wl12xx_op_configure_filter(struct ieee80211_hw *hw, unsigned int changed, unsigned int *total, int mc_count, struct dev_addr_list *mc_list)*/
1461 /* LDV_COMMENT_END_PREP */
1462 /* LDV_COMMENT_VAR_DECLARE Variable declaration for function "wl12xx_op_configure_filter" */
1463 unsigned int var_wl12xx_op_configure_filter_19_p1;
1464 /* LDV_COMMENT_VAR_DECLARE Variable declaration for function "wl12xx_op_configure_filter" */
1465 unsigned int * var_wl12xx_op_configure_filter_19_p2;
1466 /* LDV_COMMENT_VAR_DECLARE Variable declaration for function "wl12xx_op_configure_filter" */
1467 int var_wl12xx_op_configure_filter_19_p3;
1468 /* LDV_COMMENT_VAR_DECLARE Variable declaration for function "wl12xx_op_configure_filter" */
1469 struct dev_addr_list * var_wl12xx_op_configure_filter_19_p4;
1470 /* LDV_COMMENT_BEGIN_PREP */
1471 #define WL12XX_DEFAULT_CHANNEL
1
1472 /* LDV_COMMENT_END_PREP */
1473 /* content: static int wl12xx_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)*/
1474 /* LDV_COMMENT_END_PREP */
1475 /* LDV_COMMENT_VAR_DECLARE Variable declaration for function "wl12xx_op_tx" */
1476 struct sk_buff * var_group3;
1477 /* LDV_COMMENT_BEGIN_PREP */
1478 #define WL12XX_SUPPORTED_FILTERS (FIF_PROMISC_IN_BSS | \
1479 FIF_ALLMULTI | \
1480 FIF_FCSFAIL | \
1481 FIF_BCN_PRBRESP_PROMISC | \
1482 FIF_CONTROL | \
1483 FIF_OTHER_BSS)
1484 #define WL12XX_DEFAULT_CHANNEL
1
1485 /* LDV_COMMENT_END_PREP */
1486 /* content: static int wl12xx_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, struct ieee80211_vif *vif, struct ieee80211_sta *sta, struct ieee80211_key_conf *key)*/
1487 /* LDV_COMMENT_BEGIN_PREP */
1488 #define WL12XX_SUPPORTED_FILTERS (FIF_PROMISC_IN_BSS | \
1489 FIF_ALLMULTI | \
1490 FIF_FCSFAIL | \
1491 FIF_BCN_PRBRESP_PROMISC | \
1492 FIF_CONTROL | \
1493 FIF_OTHER_BSS)
1494 /* LDV_COMMENT_END_PREP */
1495 /* LDV_COMMENT_VAR_DECLARE Variable declaration for function "wl12xx_op_set_key" */
1496 enum set_key_cmd var_wl12xx_op_set_key_21_p1;
1497 /* LDV_COMMENT_VAR_DECLARE Variable declaration for function "wl12xx_op_set_key" */
1498 struct ieee80211_vif * var_wl12xx_op_set_key_21_p2;
1499 /* LDV_COMMENT_VAR_DECLARE Variable declaration for function "wl12xx_op_set_key" */
1500 struct ieee80211_sta * var_wl12xx_op_set_key_21_p3;
1501 /* LDV_COMMENT_VAR_DECLARE Variable declaration for function "wl12xx_op_set_key" */
1502 struct ieee80211_key_conf * var_wl12xx_op_set_key_21_p4;
1503 /* LDV_COMMENT_BEGIN_PREP */
1504 #define WL12XX_DEFAULT_CHANNEL
1
1505 /* LDV_COMMENT_END_PREP */
1506 /* content: static int wl12xx_op_hw_scan(struct ieee80211_hw *hw, struct cfg80211_scan_request *req)*/
1507 /* LDV_COMMENT_BEGIN_PREP */
1508 #define WL12XX_SUPPORTED_FILTERS (FIF_PROMISC_IN_BSS | \
1509 FIF_ALLMULTI | \
1510 FIF_FCSFAIL | \
1511 FIF_BCN_PRBRESP_PROMISC | \
1512 FIF_CONTROL | \
1513 FIF_OTHER_BSS)
1514 /* LDV_COMMENT_END_PREP */
1515 /* LDV_COMMENT_VAR_DECLARE Variable declaration for function "wl12xx_op_hw_scan" */
1516 struct cfg80211_scan_request * var_group4;
1517 /* LDV_COMMENT_BEGIN_PREP */
1518 #define WL12XX_DEFAULT_CHANNEL
1
1519 /* LDV_COMMENT_END_PREP */
1520 /* content: static void wl12xx_op_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_bss_conf *bss_conf, u32 changed)*/
1521 /* LDV_COMMENT_BEGIN_PREP */
1522 #define WL12XX_SUPPORTED_FILTERS (FIF_PROMISC_IN_BSS | \
1523 FIF_ALLMULTI | \
1524 FIF_FCSFAIL | \
1525 FIF_BCN_PRBRESP_PROMISC | \
1526 FIF_CONTROL | \
1527 FIF_OTHER_BSS)
1528 /* LDV_COMMENT_END_PREP */
1529 /* LDV_COMMENT_VAR_DECLARE Variable declaration for function "wl12xx_op_bss_info_changed" */
1530 struct ieee80211_vif * var_group5;
1531 /* LDV_COMMENT_VAR_DECLARE Variable declaration for function "wl12xx_op_bss_info_changed" */
1532 struct ieee80211_bss_conf * var_wl12xx_op_bss_info_changed_28_p2;
1533 /* LDV_COMMENT_VAR_DECLARE Variable declaration for function "wl12xx_op_bss_info_changed" */
1534 u32 var_wl12xx_op_bss_info_changed_28_p3;
1535 /* LDV_COMMENT_BEGIN_PREP */
1536 #define WL12XX_DEFAULT_CHANNEL
1
1537 /* LDV_COMMENT_END_PREP */
1538 /* content: static int wl12xx_op_set_rts_threshold(struct ieee80211_hw *hw, u32 value)*/
1539 /* LDV_COMMENT_BEGIN_PREP */
1540 #define WL12XX_SUPPORTED_FILTERS (FIF_PROMISC_IN_BSS | \
1541 FIF_ALLMULTI | \
1542 FIF_FCSFAIL | \
1543 FIF_BCN_PRBRESP_PROMISC | \
1544 FIF_CONTROL | \
1545 FIF_OTHER_BSS)
1546 /* LDV_COMMENT_END_PREP */
1547 /* LDV_COMMENT_VAR_DECLARE Variable declaration for function "wl12xx_op_set_rts_threshold" */
1548 u32 var_wl12xx_op_set_rts_threshold_27_p1;
1549 /* LDV_COMMENT_BEGIN_PREP */
1550 #define WL12XX_DEFAULT_CHANNEL
1
1551 /* LDV_COMMENT_END_PREP */
1552
1553 /** STRUCT: struct type: spi_driver, struct name: wl12xx_spi_driver **/
1554 /* content: static int __devinit wl12xx_probe(struct spi_device *spi)*/
1555 /* LDV_COMMENT_BEGIN_PREP */
1556 #define WL12XX_SUPPORTED_FILTERS (FIF_PROMISC_IN_BSS | \
1557 FIF_ALLMULTI | \
1558 FIF_FCSFAIL | \
1559 FIF_BCN_PRBRESP_PROMISC | \
1560 FIF_CONTROL | \
1561 FIF_OTHER_BSS)
1562 #define WL12XX_DEFAULT_CHANNEL
1
1563 /* LDV_COMMENT_END_PREP */
1564 /* LDV_COMMENT_VAR_DECLARE Variable declaration for function "wl12xx_probe" */
1565 struct spi_device * var_group6;
1566 /* LDV_COMMENT_VAR_DECLARE Variable declaration for test return result from function call "wl12xx_probe" */
1567 static int res_wl12xx_probe_31;
1568
1569 /** CALLBACK SECTION request_irq **/
1570 /* content: static irqreturn_t wl12xx_irq(int irq, void *cookie)*/
1571 /* LDV_COMMENT_END_PREP */
1572 /* LDV_COMMENT_VAR_DECLARE Variable declaration for function "wl12xx_irq" */
1573 int var_wl12xx_irq_3_p0;
1574 /* LDV_COMMENT_VAR_DECLARE Variable declaration for function "wl12xx_irq" */
1575 void * var_wl12xx_irq_3_p1;
1576 /* LDV_COMMENT_BEGIN_PREP */
1577 #define WL12XX_SUPPORTED_FILTERS (FIF_PROMISC_IN_BSS | \
1578 FIF_ALLMULTI | \
1579 FIF_FCSFAIL | \
1580 FIF_BCN_PRBRESP_PROMISC | \
1581 FIF_CONTROL | \
1582 FIF_OTHER_BSS)
1583 #define WL12XX_DEFAULT_CHANNEL
1
1584 /* LDV_COMMENT_END_PREP */
1585
1586
1587
1588
1589 /* LDV_COMMENT_END_VARIABLE_DECLARATION_PART */
1590 /* LDV_COMMENT_BEGIN_VARIABLE_INITIALIZING_PART */
1591 /*============================= VARIABLE INITIALIZING PART =============================*/
1592 LDV_IN_INTERRUPT=
1;
1593
1594
1595
1596
1597 /* LDV_COMMENT_END_VARIABLE_INITIALIZING_PART */
1598 /* LDV_COMMENT_BEGIN_FUNCTION_CALL_SECTION */
1599 /*============================= FUNCTION CALL SECTION =============================*/
1600 /* LDV_COMMENT_FUNCTION_CALL Initialize LDV model. */
1601 ldv_initialize();
1602
1603 /** INIT: init_type: ST_MODULE_INIT **/
1604 /* content: static int __init wl12xx_init(void)*/
1605 /* LDV_COMMENT_BEGIN_PREP */
1606 #define WL12XX_SUPPORTED_FILTERS (FIF_PROMISC_IN_BSS | \
1607 FIF_ALLMULTI | \
1608 FIF_FCSFAIL | \
1609 FIF_BCN_PRBRESP_PROMISC | \
1610 FIF_CONTROL | \
1611 FIF_OTHER_BSS)
1612 #define WL12XX_DEFAULT_CHANNEL
1
1613 /* LDV_COMMENT_END_PREP */
1614 /* LDV_COMMENT_FUNCTION_CALL Kernel calls driver init function after driver loading to kernel. This function declared as "MODULE_INIT(function name)". */
1615 if(wl12xx_init())
1616 goto ldv_final;
1617
1618
1619 int ldv_s_wl12xx_spi_driver_spi_driver =
0;
1620
1621
1622
1623
1624 while( nondet_int()
1625 || !(ldv_s_wl12xx_spi_driver_spi_driver ==
0)
1626 ) {
1627
1628 switch(nondet_int()) {
1629
1630 case 0: {
1631
1632 /** STRUCT: struct type: ieee80211_ops, struct name: wl12xx_ops **/
1633
1634
1635 /* content: static int wl12xx_op_start(struct ieee80211_hw *hw)*/
1636 /* LDV_COMMENT_END_PREP */
1637 /* LDV_COMMENT_FUNCTION_CALL Function from field "start" from driver structure with callbacks "wl12xx_ops" */
1638 wl12xx_op_start( var_group1);
1639 /* LDV_COMMENT_BEGIN_PREP */
1640 #define WL12XX_SUPPORTED_FILTERS (FIF_PROMISC_IN_BSS | \
1641 FIF_ALLMULTI | \
1642 FIF_FCSFAIL | \
1643 FIF_BCN_PRBRESP_PROMISC | \
1644 FIF_CONTROL | \
1645 FIF_OTHER_BSS)
1646 #define WL12XX_DEFAULT_CHANNEL
1
1647 /* LDV_COMMENT_END_PREP */
1648
1649
1650
1651
1652 }
1653
1654 break;
1655 case 1: {
1656
1657 /** STRUCT: struct type: ieee80211_ops, struct name: wl12xx_ops **/
1658
1659
1660 /* content: static void wl12xx_op_stop(struct ieee80211_hw *hw)*/
1661 /* LDV_COMMENT_END_PREP */
1662 /* LDV_COMMENT_FUNCTION_CALL Function from field "stop" from driver structure with callbacks "wl12xx_ops" */
1663 wl12xx_op_stop( var_group1);
1664 /* LDV_COMMENT_BEGIN_PREP */
1665 #define WL12XX_SUPPORTED_FILTERS (FIF_PROMISC_IN_BSS | \
1666 FIF_ALLMULTI | \
1667 FIF_FCSFAIL | \
1668 FIF_BCN_PRBRESP_PROMISC | \
1669 FIF_CONTROL | \
1670 FIF_OTHER_BSS)
1671 #define WL12XX_DEFAULT_CHANNEL
1
1672 /* LDV_COMMENT_END_PREP */
1673
1674
1675
1676
1677 }
1678
1679 break;
1680 case 2: {
1681
1682 /** STRUCT: struct type: ieee80211_ops, struct name: wl12xx_ops **/
1683
1684
1685 /* content: static int wl12xx_op_add_interface(struct ieee80211_hw *hw, struct ieee80211_if_init_conf *conf)*/
1686 /* LDV_COMMENT_END_PREP */
1687 /* LDV_COMMENT_FUNCTION_CALL Function from field "add_interface" from driver structure with callbacks "wl12xx_ops" */
1688 wl12xx_op_add_interface( var_group1, var_group2);
1689 /* LDV_COMMENT_BEGIN_PREP */
1690 #define WL12XX_SUPPORTED_FILTERS (FIF_PROMISC_IN_BSS | \
1691 FIF_ALLMULTI | \
1692 FIF_FCSFAIL | \
1693 FIF_BCN_PRBRESP_PROMISC | \
1694 FIF_CONTROL | \
1695 FIF_OTHER_BSS)
1696 #define WL12XX_DEFAULT_CHANNEL
1
1697 /* LDV_COMMENT_END_PREP */
1698
1699
1700
1701
1702 }
1703
1704 break;
1705 case 3: {
1706
1707 /** STRUCT: struct type: ieee80211_ops, struct name: wl12xx_ops **/
1708
1709
1710 /* content: static void wl12xx_op_remove_interface(struct ieee80211_hw *hw, struct ieee80211_if_init_conf *conf)*/
1711 /* LDV_COMMENT_END_PREP */
1712 /* LDV_COMMENT_FUNCTION_CALL Function from field "remove_interface" from driver structure with callbacks "wl12xx_ops" */
1713 wl12xx_op_remove_interface( var_group1, var_group2);
1714 /* LDV_COMMENT_BEGIN_PREP */
1715 #define WL12XX_SUPPORTED_FILTERS (FIF_PROMISC_IN_BSS | \
1716 FIF_ALLMULTI | \
1717 FIF_FCSFAIL | \
1718 FIF_BCN_PRBRESP_PROMISC | \
1719 FIF_CONTROL | \
1720 FIF_OTHER_BSS)
1721 #define WL12XX_DEFAULT_CHANNEL
1
1722 /* LDV_COMMENT_END_PREP */
1723
1724
1725
1726
1727 }
1728
1729 break;
1730 case 4: {
1731
1732 /** STRUCT: struct type: ieee80211_ops, struct name: wl12xx_ops **/
1733
1734
1735 /* content: static int wl12xx_op_config(struct ieee80211_hw *hw, u32 changed)*/
1736 /* LDV_COMMENT_END_PREP */
1737 /* LDV_COMMENT_FUNCTION_CALL Function from field "config" from driver structure with callbacks "wl12xx_ops" */
1738 wl12xx_op_config( var_group1, var_wl12xx_op_config_18_p1);
1739 /* LDV_COMMENT_BEGIN_PREP */
1740 #define WL12XX_SUPPORTED_FILTERS (FIF_PROMISC_IN_BSS | \
1741 FIF_ALLMULTI | \
1742 FIF_FCSFAIL | \
1743 FIF_BCN_PRBRESP_PROMISC | \
1744 FIF_CONTROL | \
1745 FIF_OTHER_BSS)
1746 #define WL12XX_DEFAULT_CHANNEL
1
1747 /* LDV_COMMENT_END_PREP */
1748
1749
1750
1751
1752 }
1753
1754 break;
1755 case 5: {
1756
1757 /** STRUCT: struct type: ieee80211_ops, struct name: wl12xx_ops **/
1758
1759
1760 /* content: FIF_OTHER_BSS) static void wl12xx_op_configure_filter(struct ieee80211_hw *hw, unsigned int changed, unsigned int *total, int mc_count, struct dev_addr_list *mc_list)*/
1761 /* LDV_COMMENT_END_PREP */
1762 /* LDV_COMMENT_FUNCTION_CALL Function from field "configure_filter" from driver structure with callbacks "wl12xx_ops" */
1763 wl12xx_op_configure_filter( var_group1, var_wl12xx_op_configure_filter_19_p1, var_wl12xx_op_configure_filter_19_p2, var_wl12xx_op_configure_filter_19_p3, var_wl12xx_op_configure_filter_19_p4);
1764 /* LDV_COMMENT_BEGIN_PREP */
1765 #define WL12XX_DEFAULT_CHANNEL
1
1766 /* LDV_COMMENT_END_PREP */
1767
1768
1769
1770
1771 }
1772
1773 break;
1774 case 6: {
1775
1776 /** STRUCT: struct type: ieee80211_ops, struct name: wl12xx_ops **/
1777
1778
1779 /* content: static int wl12xx_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)*/
1780 /* LDV_COMMENT_END_PREP */
1781 /* LDV_COMMENT_FUNCTION_CALL Function from field "tx" from driver structure with callbacks "wl12xx_ops" */
1782 wl12xx_op_tx( var_group1, var_group3);
1783 /* LDV_COMMENT_BEGIN_PREP */
1784 #define WL12XX_SUPPORTED_FILTERS (FIF_PROMISC_IN_BSS | \
1785 FIF_ALLMULTI | \
1786 FIF_FCSFAIL | \
1787 FIF_BCN_PRBRESP_PROMISC | \
1788 FIF_CONTROL | \
1789 FIF_OTHER_BSS)
1790 #define WL12XX_DEFAULT_CHANNEL
1
1791 /* LDV_COMMENT_END_PREP */
1792
1793
1794
1795
1796 }
1797
1798 break;
1799 case 7: {
1800
1801 /** STRUCT: struct type: ieee80211_ops, struct name: wl12xx_ops **/
1802
1803
1804 /* content: static int wl12xx_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, struct ieee80211_vif *vif, struct ieee80211_sta *sta, struct ieee80211_key_conf *key)*/
1805 /* LDV_COMMENT_BEGIN_PREP */
1806 #define WL12XX_SUPPORTED_FILTERS (FIF_PROMISC_IN_BSS | \
1807 FIF_ALLMULTI | \
1808 FIF_FCSFAIL | \
1809 FIF_BCN_PRBRESP_PROMISC | \
1810 FIF_CONTROL | \
1811 FIF_OTHER_BSS)
1812 /* LDV_COMMENT_END_PREP */
1813 /* LDV_COMMENT_FUNCTION_CALL Function from field "set_key" from driver structure with callbacks "wl12xx_ops" */
1814 wl12xx_op_set_key( var_group1, var_wl12xx_op_set_key_21_p1, var_wl12xx_op_set_key_21_p2, var_wl12xx_op_set_key_21_p3, var_wl12xx_op_set_key_21_p4);
1815 /* LDV_COMMENT_BEGIN_PREP */
1816 #define WL12XX_DEFAULT_CHANNEL
1
1817 /* LDV_COMMENT_END_PREP */
1818
1819
1820
1821
1822 }
1823
1824 break;
1825 case 8: {
1826
1827 /** STRUCT: struct type: ieee80211_ops, struct name: wl12xx_ops **/
1828
1829
1830 /* content: static int wl12xx_op_hw_scan(struct ieee80211_hw *hw, struct cfg80211_scan_request *req)*/
1831 /* LDV_COMMENT_BEGIN_PREP */
1832 #define WL12XX_SUPPORTED_FILTERS (FIF_PROMISC_IN_BSS | \
1833 FIF_ALLMULTI | \
1834 FIF_FCSFAIL | \
1835 FIF_BCN_PRBRESP_PROMISC | \
1836 FIF_CONTROL | \
1837 FIF_OTHER_BSS)
1838 /* LDV_COMMENT_END_PREP */
1839 /* LDV_COMMENT_FUNCTION_CALL Function from field "hw_scan" from driver structure with callbacks "wl12xx_ops" */
1840 wl12xx_op_hw_scan( var_group1, var_group4);
1841 /* LDV_COMMENT_BEGIN_PREP */
1842 #define WL12XX_DEFAULT_CHANNEL
1
1843 /* LDV_COMMENT_END_PREP */
1844
1845
1846
1847
1848 }
1849
1850 break;
1851 case 9: {
1852
1853 /** STRUCT: struct type: ieee80211_ops, struct name: wl12xx_ops **/
1854
1855
1856 /* content: static void wl12xx_op_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_bss_conf *bss_conf, u32 changed)*/
1857 /* LDV_COMMENT_BEGIN_PREP */
1858 #define WL12XX_SUPPORTED_FILTERS (FIF_PROMISC_IN_BSS | \
1859 FIF_ALLMULTI | \
1860 FIF_FCSFAIL | \
1861 FIF_BCN_PRBRESP_PROMISC | \
1862 FIF_CONTROL | \
1863 FIF_OTHER_BSS)
1864 /* LDV_COMMENT_END_PREP */
1865 /* LDV_COMMENT_FUNCTION_CALL Function from field "bss_info_changed" from driver structure with callbacks "wl12xx_ops" */
1866 wl12xx_op_bss_info_changed( var_group1, var_group5, var_wl12xx_op_bss_info_changed_28_p2, var_wl12xx_op_bss_info_changed_28_p3);
1867 /* LDV_COMMENT_BEGIN_PREP */
1868 #define WL12XX_DEFAULT_CHANNEL
1
1869 /* LDV_COMMENT_END_PREP */
1870
1871
1872
1873
1874 }
1875
1876 break;
1877 case 10: {
1878
1879 /** STRUCT: struct type: ieee80211_ops, struct name: wl12xx_ops **/
1880
1881
1882 /* content: static int wl12xx_op_set_rts_threshold(struct ieee80211_hw *hw, u32 value)*/
1883 /* LDV_COMMENT_BEGIN_PREP */
1884 #define WL12XX_SUPPORTED_FILTERS (FIF_PROMISC_IN_BSS | \
1885 FIF_ALLMULTI | \
1886 FIF_FCSFAIL | \
1887 FIF_BCN_PRBRESP_PROMISC | \
1888 FIF_CONTROL | \
1889 FIF_OTHER_BSS)
1890 /* LDV_COMMENT_END_PREP */
1891 /* LDV_COMMENT_FUNCTION_CALL Function from field "set_rts_threshold" from driver structure with callbacks "wl12xx_ops" */
1892 wl12xx_op_set_rts_threshold( var_group1, var_wl12xx_op_set_rts_threshold_27_p1);
1893 /* LDV_COMMENT_BEGIN_PREP */
1894 #define WL12XX_DEFAULT_CHANNEL
1
1895 /* LDV_COMMENT_END_PREP */
1896
1897
1898
1899
1900 }
1901
1902 break;
1903 case 11: {
1904
1905 /** STRUCT: struct type: spi_driver, struct name: wl12xx_spi_driver **/
1906 if(ldv_s_wl12xx_spi_driver_spi_driver==
0) {
1907
1908 /* content: static int __devinit wl12xx_probe(struct spi_device *spi)*/
1909 /* LDV_COMMENT_BEGIN_PREP */
1910 #define WL12XX_SUPPORTED_FILTERS (FIF_PROMISC_IN_BSS | \
1911 FIF_ALLMULTI | \
1912 FIF_FCSFAIL | \
1913 FIF_BCN_PRBRESP_PROMISC | \
1914 FIF_CONTROL | \
1915 FIF_OTHER_BSS)
1916 #define WL12XX_DEFAULT_CHANNEL
1
1917 /* LDV_COMMENT_END_PREP */
1918 /* LDV_COMMENT_FUNCTION_CALL Function from field "probe" from driver structure with callbacks "wl12xx_spi_driver". Standart function test for correct return result. */
1919 res_wl12xx_probe_31 = wl12xx_probe( var_group6);
1920 ldv_check_return_value(res_wl12xx_probe_31);
1921 if(res_wl12xx_probe_31)
1922 goto ldv_module_exit;
1923 ldv_s_wl12xx_spi_driver_spi_driver=
0;
1924
1925 }
1926
1927 }
1928
1929 break;
1930 case 12: {
1931
1932 /** CALLBACK SECTION request_irq **/
1933 LDV_IN_INTERRUPT=
2;
1934
1935 /* content: static irqreturn_t wl12xx_irq(int irq, void *cookie)*/
1936 /* LDV_COMMENT_END_PREP */
1937 /* LDV_COMMENT_FUNCTION_CALL */
1938 wl12xx_irq( var_wl12xx_irq_3_p0, var_wl12xx_irq_3_p1);
1939 /* LDV_COMMENT_BEGIN_PREP */
1940 #define WL12XX_SUPPORTED_FILTERS (FIF_PROMISC_IN_BSS | \
1941 FIF_ALLMULTI | \
1942 FIF_FCSFAIL | \
1943 FIF_BCN_PRBRESP_PROMISC | \
1944 FIF_CONTROL | \
1945 FIF_OTHER_BSS)
1946 #define WL12XX_DEFAULT_CHANNEL
1
1947 /* LDV_COMMENT_END_PREP */
1948 LDV_IN_INTERRUPT=
1;
1949
1950
1951
1952 }
1953
1954 break;
1955 default:
break;
1956
1957 }
1958
1959 }
1960
1961 ldv_module_exit:
1962
1963 /** INIT: init_type: ST_MODULE_EXIT **/
1964 /* content: static void __exit wl12xx_exit(void)*/
1965 /* LDV_COMMENT_BEGIN_PREP */
1966 #define WL12XX_SUPPORTED_FILTERS (FIF_PROMISC_IN_BSS | \
1967 FIF_ALLMULTI | \
1968 FIF_FCSFAIL | \
1969 FIF_BCN_PRBRESP_PROMISC | \
1970 FIF_CONTROL | \
1971 FIF_OTHER_BSS)
1972 #define WL12XX_DEFAULT_CHANNEL
1
1973 /* LDV_COMMENT_END_PREP */
1974 /* LDV_COMMENT_FUNCTION_CALL Kernel calls driver release function before driver will be uploaded from kernel. This function declared as "MODULE_EXIT(function name)". */
1975 wl12xx_exit();
1976
1977 /* LDV_COMMENT_FUNCTION_CALL Checks that all resources and locks are correctly released before the driver will be unloaded. */
1978 ldv_final: ldv_check_final_state();
1979
1980 /* LDV_COMMENT_END_FUNCTION_CALL_SECTION */
1981 return;
1982
1983 }
1984 #endif
1985
1986 /* LDV_COMMENT_END_MAIN */
1987 /* LDV_COMMENT_BEGIN_MODEL */
1988
1989 /*
1990 * CONFIG_DEBUG_LOCK_ALLOC must be turned off to apply the given model.
1991 * To be independ on the value of this flag there is the corresponding
1992 * aspect model.
1993 */
1994
1995 /* the function works only without aspectator */
1996 long __builtin_expect(
long val,
long res) {
1997 return val;
1998 }
1999
2000 #include "engine-blast.h"
2001
2002 #include <linux/kernel.h>
2003 #include <linux/mutex.h>
2004
2005 /* Need this because rerouter is buggy!.. */
2006 extern int ldv_mutex_TEMPLATE;
2007 /* Now the actual variable goes... */
2008 int ldv_mutex_TEMPLATE =
1;
2009
2010 /* LDV_COMMENT_MODEL_FUNCTION_DEFINITION(name='mutex_lock_interruptible') Check that the mutex was unlocked and nondeterministically lock it. Return the corresponding error code on fails*/
2011 int mutex_lock_interruptible_TEMPLATE(
struct mutex *lock)
2012 {
2013 int nondetermined;
2014
2015 /* LDV_COMMENT_ASSERT Mutex must be unlocked*/
2016 ldv_assert(ldv_mutex_TEMPLATE ==
1);
2017
2018 /* LDV_COMMENT_OTHER Construct the nondetermined result*/
2019 nondetermined = ldv_undef_int();
2020
2021 /* LDV_COMMENT_ASSERT Nondeterministically lock the mutex*/
2022 if (nondetermined)
2023 {
2024 /* LDV_COMMENT_CHANGE_STATE Lock the mutex*/
2025 ldv_mutex_TEMPLATE =
2;
2026 /* LDV_COMMENT_RETURN Finish with success*/
2027 return 0;
2028 }
2029 else
2030 {
2031 /* LDV_COMMENT_RETURN Finish with the fail. The mutex is keeped unlocked*/
2032 return -EINTR;
2033 }
2034 }
2035
2036 /* LDV_COMMENT_MODEL_FUNCTION_DEFINITION(name='atomic_dec_and_mutex_lock') Lock if atomic decrement result is zero */
2037 int atomic_dec_and_mutex_lock_TEMPLATE(atomic_t *cnt,
struct mutex *lock)
2038 {
2039 int atomic_value_after_dec;
2040
2041 /* LDV_COMMENT_ASSERT Mutex must be unlocked (since we may lock it in this function) */
2042 ldv_assert(ldv_mutex_TEMPLATE ==
1);
2043
2044 /* LDV_COMMENT_OTHER Assign the result of atomic decrement */
2045 atomic_value_after_dec = ldv_undef_int();
2046
2047 /* LDV_COMMENT_ASSERT Check if atomic decrement returns zero */
2048 if (atomic_value_after_dec ==
0)
2049 {
2050 /* LDV_COMMENT_CHANGE_STATE Lock the mutex, as atomic has decremented to zero*/
2051 ldv_mutex_TEMPLATE =
2;
2052 /* LDV_COMMENT_RETURN Return 1 with a locked mutex */
2053 return 1;
2054 }
2055
2056 /* LDV_COMMENT_RETURN Atomic decrement is still not zero, return 0 without locking the mutex */
2057 return 0;
2058 }
2059
2060 /* LDV_COMMENT_MODEL_FUNCTION_DEFINITION(name='mutex_lock_killable') Check that the mutex wasn unlocked and nondeterministically lock it. Return the corresponding error code on fails*/
2061 int __must_check mutex_lock_killable_TEMPLATE(
struct mutex *lock)
2062 {
2063 int nondetermined;
2064
2065 /* LDV_COMMENT_ASSERT Mutex must be unlocked*/
2066 ldv_assert(ldv_mutex_TEMPLATE ==
1);
2067
2068 /* LDV_COMMENT_OTHER Construct the nondetermined result*/
2069 nondetermined = ldv_undef_int();
2070
2071 /* LDV_COMMENT_ASSERT Nondeterministically lock the mutex*/
2072 if (nondetermined)
2073 {
2074 /* LDV_COMMENT_CHANGE_STATE Lock the mutex*/
2075 ldv_mutex_TEMPLATE =
2;
2076 /* LDV_COMMENT_RETURN Finish with success*/
2077 return 0;
2078 }
2079 else
2080 {
2081 /* LDV_COMMENT_RETURN Finish with the fail. The mutex is keeped unlocked*/
2082 return -EINTR;
2083 }
2084 }
2085
2086 /* LDV_COMMENT_MODEL_FUNCTION_DEFINITION(name='mutex_is_locked') Checks whether the mutex is locked*/
2087 int mutex_is_locked_TEMPLATE(
struct mutex *lock)
2088 {
2089 int nondetermined;
2090
2091 if(ldv_mutex_TEMPLATE ==
1) {
2092 /* LDV_COMMENT_OTHER Construct the nondetermined result*/
2093 nondetermined = ldv_undef_int();
2094 if(nondetermined) {
2095 /* LDV_COMMENT_RETURN the mutex is unlocked*/
2096 return 0;
2097 }
else {
2098 /* LDV_COMMENT_RETURN the mutex is locked*/
2099 return 1;
2100 }
2101 }
else {
2102 /* LDV_COMMENT_RETURN the mutex is locked*/
2103 return 1;
2104 }
2105 }
2106
2107 /* LDV_COMMENT_MODEL_FUNCTION_DEFINITION(name='mutex_lock(?!_interruptible|_killable)') Check that the mutex was not locked and lock it*/
2108 void mutex_lock_TEMPLATE(
struct mutex *lock)
2109 {
2110 /* LDV_COMMENT_ASSERT Mutex must be unlocked*/
2111 ldv_assert(ldv_mutex_TEMPLATE ==
1);
2112 /* LDV_COMMENT_CHANGE_STATE Lock the mutex*/
2113 ldv_mutex_TEMPLATE =
2;
2114 }
2115
2116 /* LDV_COMMENT_MODEL_FUNCTION_DEFINITION(name='mutex_trylock') Check that the mutex was not locked and nondeterministically lock it. Return 0 on fails*/
2117 int mutex_trylock_TEMPLATE(
struct mutex *lock)
2118 {
2119 int is_mutex_held_by_another_thread;
2120
2121 /* LDV_COMMENT_ASSERT Mutex must be unlocked*/
2122 ldv_assert(ldv_mutex_TEMPLATE ==
1);
2123
2124 /* LDV_COMMENT_OTHER Construct the nondetermined result*/
2125 is_mutex_held_by_another_thread = ldv_undef_int();
2126
2127 /* LDV_COMMENT_ASSERT Nondeterministically lock the mutex*/
2128 if (is_mutex_held_by_another_thread)
2129 {
2130 /* LDV_COMMENT_RETURN Finish with fail*/
2131 return 0;
2132 }
2133 else
2134 {
2135 /* LDV_COMMENT_CHANGE_STATE Lock the mutex*/
2136 ldv_mutex_TEMPLATE =
2;
2137 /* LDV_COMMENT_RETURN Finish with success*/
2138 return 1;
2139 }
2140 }
2141
2142 /* LDV_COMMENT_MODEL_FUNCTION_DEFINITION(name='mutex_unlock') Check that the mutex was locked and unlock it*/
2143 void mutex_unlock_TEMPLATE(
struct mutex *lock)
2144 {
2145 /* LDV_COMMENT_ASSERT Mutex must be locked*/
2146 ldv_assert(ldv_mutex_TEMPLATE ==
2);
2147 /* LDV_COMMENT_CHANGE_STATE Unlock the mutex*/
2148 ldv_mutex_TEMPLATE =
1;
2149 }
2150
2151 /* LDV_COMMENT_MODEL_FUNCTION_DEFINITION(name='check_final_state') Check that the mutex is unlocked at the end*/
2152 void ldv_check_final_state_TEMPLATE(
void)
2153 {
2154 /* LDV_COMMENT_ASSERT The mutex must be unlocked at the end*/
2155 ldv_assert(ldv_mutex_TEMPLATE ==
1);
2156 }
2157
2158 /* LDV_COMMENT_MODEL_FUNCTION_DEFINITION(name='ldv_initialize') Initialize mutex variables*/
2159 void ldv_initialize_TEMPLATE(
void)
2160 {
2161 /* LDV_COMMENT_ASSERT Initialize mutex with initial model value*/
2162 ldv_mutex_TEMPLATE =
1;
2163 }
2164
2165 /* LDV_COMMENT_END_MODEL */