diff options
Diffstat (limited to 'drivers/net/wireless/wl12xx/main.c')
-rw-r--r-- | drivers/net/wireless/wl12xx/main.c | 151 |
1 files changed, 119 insertions, 32 deletions
diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index 61dea73f5fd..947491a1d9c 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c | |||
@@ -482,6 +482,10 @@ static int wl1271_plt_init(struct wl1271 *wl) | |||
482 | if (ret < 0) | 482 | if (ret < 0) |
483 | goto out_free_memmap; | 483 | goto out_free_memmap; |
484 | 484 | ||
485 | ret = wl1271_acx_sta_mem_cfg(wl); | ||
486 | if (ret < 0) | ||
487 | goto out_free_memmap; | ||
488 | |||
485 | /* Default fragmentation threshold */ | 489 | /* Default fragmentation threshold */ |
486 | ret = wl1271_acx_frag_threshold(wl, wl->conf.tx.frag_threshold); | 490 | ret = wl1271_acx_frag_threshold(wl, wl->conf.tx.frag_threshold); |
487 | if (ret < 0) | 491 | if (ret < 0) |
@@ -533,6 +537,57 @@ static int wl1271_plt_init(struct wl1271 *wl) | |||
533 | return ret; | 537 | return ret; |
534 | } | 538 | } |
535 | 539 | ||
540 | static void wl1271_irq_ps_regulate_link(struct wl1271 *wl, u8 hlid, u8 tx_blks) | ||
541 | { | ||
542 | bool fw_ps; | ||
543 | |||
544 | /* only regulate station links */ | ||
545 | if (hlid < WL1271_AP_STA_HLID_START) | ||
546 | return; | ||
547 | |||
548 | fw_ps = test_bit(hlid, (unsigned long *)&wl->ap_fw_ps_map); | ||
549 | |||
550 | /* | ||
551 | * Wake up from high level PS if the STA is asleep with too little | ||
552 | * blocks in FW or if the STA is awake. | ||
553 | */ | ||
554 | if (!fw_ps || tx_blks < WL1271_PS_STA_MAX_BLOCKS) | ||
555 | wl1271_ps_link_end(wl, hlid); | ||
556 | |||
557 | /* Start high-level PS if the STA is asleep with enough blocks in FW */ | ||
558 | else if (fw_ps && tx_blks >= WL1271_PS_STA_MAX_BLOCKS) | ||
559 | wl1271_ps_link_start(wl, hlid, true); | ||
560 | } | ||
561 | |||
562 | static void wl1271_irq_update_links_status(struct wl1271 *wl, | ||
563 | struct wl1271_fw_ap_status *status) | ||
564 | { | ||
565 | u32 cur_fw_ps_map; | ||
566 | u8 hlid; | ||
567 | |||
568 | cur_fw_ps_map = le32_to_cpu(status->link_ps_bitmap); | ||
569 | if (wl->ap_fw_ps_map != cur_fw_ps_map) { | ||
570 | wl1271_debug(DEBUG_PSM, | ||
571 | "link ps prev 0x%x cur 0x%x changed 0x%x", | ||
572 | wl->ap_fw_ps_map, cur_fw_ps_map, | ||
573 | wl->ap_fw_ps_map ^ cur_fw_ps_map); | ||
574 | |||
575 | wl->ap_fw_ps_map = cur_fw_ps_map; | ||
576 | } | ||
577 | |||
578 | for (hlid = WL1271_AP_STA_HLID_START; hlid < AP_MAX_LINKS; hlid++) { | ||
579 | u8 cnt = status->tx_lnk_free_blks[hlid] - | ||
580 | wl->links[hlid].prev_freed_blks; | ||
581 | |||
582 | wl->links[hlid].prev_freed_blks = | ||
583 | status->tx_lnk_free_blks[hlid]; | ||
584 | wl->links[hlid].allocated_blks -= cnt; | ||
585 | |||
586 | wl1271_irq_ps_regulate_link(wl, hlid, | ||
587 | wl->links[hlid].allocated_blks); | ||
588 | } | ||
589 | } | ||
590 | |||
536 | static void wl1271_fw_status(struct wl1271 *wl, | 591 | static void wl1271_fw_status(struct wl1271 *wl, |
537 | struct wl1271_fw_full_status *full_status) | 592 | struct wl1271_fw_full_status *full_status) |
538 | { | 593 | { |
@@ -570,6 +625,10 @@ static void wl1271_fw_status(struct wl1271 *wl, | |||
570 | if (total) | 625 | if (total) |
571 | clear_bit(WL1271_FLAG_FW_TX_BUSY, &wl->flags); | 626 | clear_bit(WL1271_FLAG_FW_TX_BUSY, &wl->flags); |
572 | 627 | ||
628 | /* for AP update num of allocated TX blocks per link and ps status */ | ||
629 | if (wl->bss_type == BSS_TYPE_AP_BSS) | ||
630 | wl1271_irq_update_links_status(wl, &full_status->ap); | ||
631 | |||
573 | /* update the host-chipset time offset */ | 632 | /* update the host-chipset time offset */ |
574 | getnstimeofday(&ts); | 633 | getnstimeofday(&ts); |
575 | wl->time_offset = (timespec_to_ns(&ts) >> 10) - | 634 | wl->time_offset = (timespec_to_ns(&ts) >> 10) - |
@@ -975,19 +1034,37 @@ int wl1271_plt_stop(struct wl1271 *wl) | |||
975 | return ret; | 1034 | return ret; |
976 | } | 1035 | } |
977 | 1036 | ||
978 | static int wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) | 1037 | static void wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) |
979 | { | 1038 | { |
980 | struct wl1271 *wl = hw->priv; | 1039 | struct wl1271 *wl = hw->priv; |
981 | unsigned long flags; | 1040 | unsigned long flags; |
982 | int q; | 1041 | int q; |
1042 | u8 hlid = 0; | ||
983 | 1043 | ||
984 | spin_lock_irqsave(&wl->wl_lock, flags); | 1044 | spin_lock_irqsave(&wl->wl_lock, flags); |
985 | wl->tx_queue_count++; | 1045 | wl->tx_queue_count++; |
1046 | |||
1047 | /* | ||
1048 | * The workqueue is slow to process the tx_queue and we need stop | ||
1049 | * the queue here, otherwise the queue will get too long. | ||
1050 | */ | ||
1051 | if (wl->tx_queue_count >= WL1271_TX_QUEUE_HIGH_WATERMARK) { | ||
1052 | wl1271_debug(DEBUG_TX, "op_tx: stopping queues"); | ||
1053 | ieee80211_stop_queues(wl->hw); | ||
1054 | set_bit(WL1271_FLAG_TX_QUEUE_STOPPED, &wl->flags); | ||
1055 | } | ||
1056 | |||
986 | spin_unlock_irqrestore(&wl->wl_lock, flags); | 1057 | spin_unlock_irqrestore(&wl->wl_lock, flags); |
987 | 1058 | ||
988 | /* queue the packet */ | 1059 | /* queue the packet */ |
989 | q = wl1271_tx_get_queue(skb_get_queue_mapping(skb)); | 1060 | q = wl1271_tx_get_queue(skb_get_queue_mapping(skb)); |
990 | skb_queue_tail(&wl->tx_queue[q], skb); | 1061 | if (wl->bss_type == BSS_TYPE_AP_BSS) { |
1062 | hlid = wl1271_tx_get_hlid(skb); | ||
1063 | wl1271_debug(DEBUG_TX, "queue skb hlid %d q %d", hlid, q); | ||
1064 | skb_queue_tail(&wl->links[hlid].tx_queue[q], skb); | ||
1065 | } else { | ||
1066 | skb_queue_tail(&wl->tx_queue[q], skb); | ||
1067 | } | ||
991 | 1068 | ||
992 | /* | 1069 | /* |
993 | * The chip specific setup must run before the first TX packet - | 1070 | * The chip specific setup must run before the first TX packet - |
@@ -996,21 +1073,6 @@ static int wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
996 | 1073 | ||
997 | if (!test_bit(WL1271_FLAG_FW_TX_BUSY, &wl->flags)) | 1074 | if (!test_bit(WL1271_FLAG_FW_TX_BUSY, &wl->flags)) |
998 | ieee80211_queue_work(wl->hw, &wl->tx_work); | 1075 | ieee80211_queue_work(wl->hw, &wl->tx_work); |
999 | |||
1000 | /* | ||
1001 | * The workqueue is slow to process the tx_queue and we need stop | ||
1002 | * the queue here, otherwise the queue will get too long. | ||
1003 | */ | ||
1004 | if (wl->tx_queue_count >= WL1271_TX_QUEUE_HIGH_WATERMARK) { | ||
1005 | wl1271_debug(DEBUG_TX, "op_tx: stopping queues"); | ||
1006 | |||
1007 | spin_lock_irqsave(&wl->wl_lock, flags); | ||
1008 | ieee80211_stop_queues(wl->hw); | ||
1009 | set_bit(WL1271_FLAG_TX_QUEUE_STOPPED, &wl->flags); | ||
1010 | spin_unlock_irqrestore(&wl->wl_lock, flags); | ||
1011 | } | ||
1012 | |||
1013 | return NETDEV_TX_OK; | ||
1014 | } | 1076 | } |
1015 | 1077 | ||
1016 | static struct notifier_block wl1271_dev_notifier = { | 1078 | static struct notifier_block wl1271_dev_notifier = { |
@@ -1221,6 +1283,8 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl) | |||
1221 | wl->filters = 0; | 1283 | wl->filters = 0; |
1222 | wl1271_free_ap_keys(wl); | 1284 | wl1271_free_ap_keys(wl); |
1223 | memset(wl->ap_hlid_map, 0, sizeof(wl->ap_hlid_map)); | 1285 | memset(wl->ap_hlid_map, 0, sizeof(wl->ap_hlid_map)); |
1286 | wl->ap_fw_ps_map = 0; | ||
1287 | wl->ap_ps_map = 0; | ||
1224 | 1288 | ||
1225 | for (i = 0; i < NUM_TX_QUEUES; i++) | 1289 | for (i = 0; i < NUM_TX_QUEUES; i++) |
1226 | wl->tx_blocks_freed[i] = 0; | 1290 | wl->tx_blocks_freed[i] = 0; |
@@ -2218,6 +2282,8 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl, | |||
2218 | u32 sta_rate_set = 0; | 2282 | u32 sta_rate_set = 0; |
2219 | int ret; | 2283 | int ret; |
2220 | struct ieee80211_sta *sta; | 2284 | struct ieee80211_sta *sta; |
2285 | bool sta_exists = false; | ||
2286 | struct ieee80211_sta_ht_cap sta_ht_cap; | ||
2221 | 2287 | ||
2222 | if (is_ibss) { | 2288 | if (is_ibss) { |
2223 | ret = wl1271_bss_beacon_info_changed(wl, vif, bss_conf, | 2289 | ret = wl1271_bss_beacon_info_changed(wl, vif, bss_conf, |
@@ -2289,16 +2355,20 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl, | |||
2289 | if (sta->ht_cap.ht_supported) | 2355 | if (sta->ht_cap.ht_supported) |
2290 | sta_rate_set |= | 2356 | sta_rate_set |= |
2291 | (sta->ht_cap.mcs.rx_mask[0] << HW_HT_RATES_OFFSET); | 2357 | (sta->ht_cap.mcs.rx_mask[0] << HW_HT_RATES_OFFSET); |
2358 | sta_ht_cap = sta->ht_cap; | ||
2359 | sta_exists = true; | ||
2360 | } | ||
2361 | rcu_read_unlock(); | ||
2292 | 2362 | ||
2363 | if (sta_exists) { | ||
2293 | /* handle new association with HT and HT information change */ | 2364 | /* handle new association with HT and HT information change */ |
2294 | if ((changed & BSS_CHANGED_HT) && | 2365 | if ((changed & BSS_CHANGED_HT) && |
2295 | (bss_conf->channel_type != NL80211_CHAN_NO_HT)) { | 2366 | (bss_conf->channel_type != NL80211_CHAN_NO_HT)) { |
2296 | ret = wl1271_acx_set_ht_capabilities(wl, &sta->ht_cap, | 2367 | ret = wl1271_acx_set_ht_capabilities(wl, &sta_ht_cap, |
2297 | true); | 2368 | true); |
2298 | if (ret < 0) { | 2369 | if (ret < 0) { |
2299 | wl1271_warning("Set ht cap true failed %d", | 2370 | wl1271_warning("Set ht cap true failed %d", |
2300 | ret); | 2371 | ret); |
2301 | rcu_read_unlock(); | ||
2302 | goto out; | 2372 | goto out; |
2303 | } | 2373 | } |
2304 | ret = wl1271_acx_set_ht_information(wl, | 2374 | ret = wl1271_acx_set_ht_information(wl, |
@@ -2306,23 +2376,20 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl, | |||
2306 | if (ret < 0) { | 2376 | if (ret < 0) { |
2307 | wl1271_warning("Set ht information failed %d", | 2377 | wl1271_warning("Set ht information failed %d", |
2308 | ret); | 2378 | ret); |
2309 | rcu_read_unlock(); | ||
2310 | goto out; | 2379 | goto out; |
2311 | } | 2380 | } |
2312 | } | 2381 | } |
2313 | /* handle new association without HT and disassociation */ | 2382 | /* handle new association without HT and disassociation */ |
2314 | else if (changed & BSS_CHANGED_ASSOC) { | 2383 | else if (changed & BSS_CHANGED_ASSOC) { |
2315 | ret = wl1271_acx_set_ht_capabilities(wl, &sta->ht_cap, | 2384 | ret = wl1271_acx_set_ht_capabilities(wl, &sta_ht_cap, |
2316 | false); | 2385 | false); |
2317 | if (ret < 0) { | 2386 | if (ret < 0) { |
2318 | wl1271_warning("Set ht cap false failed %d", | 2387 | wl1271_warning("Set ht cap false failed %d", |
2319 | ret); | 2388 | ret); |
2320 | rcu_read_unlock(); | ||
2321 | goto out; | 2389 | goto out; |
2322 | } | 2390 | } |
2323 | } | 2391 | } |
2324 | } | 2392 | } |
2325 | rcu_read_unlock(); | ||
2326 | 2393 | ||
2327 | if ((changed & BSS_CHANGED_ASSOC)) { | 2394 | if ((changed & BSS_CHANGED_ASSOC)) { |
2328 | if (bss_conf->assoc) { | 2395 | if (bss_conf->assoc) { |
@@ -2612,7 +2679,7 @@ static int wl1271_op_get_survey(struct ieee80211_hw *hw, int idx, | |||
2612 | return 0; | 2679 | return 0; |
2613 | } | 2680 | } |
2614 | 2681 | ||
2615 | static int wl1271_allocate_hlid(struct wl1271 *wl, | 2682 | static int wl1271_allocate_sta(struct wl1271 *wl, |
2616 | struct ieee80211_sta *sta, | 2683 | struct ieee80211_sta *sta, |
2617 | u8 *hlid) | 2684 | u8 *hlid) |
2618 | { | 2685 | { |
@@ -2626,18 +2693,25 @@ static int wl1271_allocate_hlid(struct wl1271 *wl, | |||
2626 | } | 2693 | } |
2627 | 2694 | ||
2628 | wl_sta = (struct wl1271_station *)sta->drv_priv; | 2695 | wl_sta = (struct wl1271_station *)sta->drv_priv; |
2629 | |||
2630 | __set_bit(id, wl->ap_hlid_map); | 2696 | __set_bit(id, wl->ap_hlid_map); |
2631 | wl_sta->hlid = WL1271_AP_STA_HLID_START + id; | 2697 | wl_sta->hlid = WL1271_AP_STA_HLID_START + id; |
2632 | *hlid = wl_sta->hlid; | 2698 | *hlid = wl_sta->hlid; |
2699 | memcpy(wl->links[wl_sta->hlid].addr, sta->addr, ETH_ALEN); | ||
2633 | return 0; | 2700 | return 0; |
2634 | } | 2701 | } |
2635 | 2702 | ||
2636 | static void wl1271_free_hlid(struct wl1271 *wl, u8 hlid) | 2703 | static void wl1271_free_sta(struct wl1271 *wl, u8 hlid) |
2637 | { | 2704 | { |
2638 | int id = hlid - WL1271_AP_STA_HLID_START; | 2705 | int id = hlid - WL1271_AP_STA_HLID_START; |
2639 | 2706 | ||
2707 | if (WARN_ON(!test_bit(id, wl->ap_hlid_map))) | ||
2708 | return; | ||
2709 | |||
2640 | __clear_bit(id, wl->ap_hlid_map); | 2710 | __clear_bit(id, wl->ap_hlid_map); |
2711 | memset(wl->links[hlid].addr, 0, ETH_ALEN); | ||
2712 | wl1271_tx_reset_link_queues(wl, hlid); | ||
2713 | __clear_bit(hlid, &wl->ap_ps_map); | ||
2714 | __clear_bit(hlid, (unsigned long *)&wl->ap_fw_ps_map); | ||
2641 | } | 2715 | } |
2642 | 2716 | ||
2643 | static int wl1271_op_sta_add(struct ieee80211_hw *hw, | 2717 | static int wl1271_op_sta_add(struct ieee80211_hw *hw, |
@@ -2658,13 +2732,13 @@ static int wl1271_op_sta_add(struct ieee80211_hw *hw, | |||
2658 | 2732 | ||
2659 | wl1271_debug(DEBUG_MAC80211, "mac80211 add sta %d", (int)sta->aid); | 2733 | wl1271_debug(DEBUG_MAC80211, "mac80211 add sta %d", (int)sta->aid); |
2660 | 2734 | ||
2661 | ret = wl1271_allocate_hlid(wl, sta, &hlid); | 2735 | ret = wl1271_allocate_sta(wl, sta, &hlid); |
2662 | if (ret < 0) | 2736 | if (ret < 0) |
2663 | goto out; | 2737 | goto out; |
2664 | 2738 | ||
2665 | ret = wl1271_ps_elp_wakeup(wl, false); | 2739 | ret = wl1271_ps_elp_wakeup(wl, false); |
2666 | if (ret < 0) | 2740 | if (ret < 0) |
2667 | goto out; | 2741 | goto out_free_sta; |
2668 | 2742 | ||
2669 | ret = wl1271_cmd_add_sta(wl, sta, hlid); | 2743 | ret = wl1271_cmd_add_sta(wl, sta, hlid); |
2670 | if (ret < 0) | 2744 | if (ret < 0) |
@@ -2673,6 +2747,10 @@ static int wl1271_op_sta_add(struct ieee80211_hw *hw, | |||
2673 | out_sleep: | 2747 | out_sleep: |
2674 | wl1271_ps_elp_sleep(wl); | 2748 | wl1271_ps_elp_sleep(wl); |
2675 | 2749 | ||
2750 | out_free_sta: | ||
2751 | if (ret < 0) | ||
2752 | wl1271_free_sta(wl, hlid); | ||
2753 | |||
2676 | out: | 2754 | out: |
2677 | mutex_unlock(&wl->mutex); | 2755 | mutex_unlock(&wl->mutex); |
2678 | return ret; | 2756 | return ret; |
@@ -2709,7 +2787,7 @@ static int wl1271_op_sta_remove(struct ieee80211_hw *hw, | |||
2709 | if (ret < 0) | 2787 | if (ret < 0) |
2710 | goto out_sleep; | 2788 | goto out_sleep; |
2711 | 2789 | ||
2712 | wl1271_free_hlid(wl, wl_sta->hlid); | 2790 | wl1271_free_sta(wl, wl_sta->hlid); |
2713 | 2791 | ||
2714 | out_sleep: | 2792 | out_sleep: |
2715 | wl1271_ps_elp_sleep(wl); | 2793 | wl1271_ps_elp_sleep(wl); |
@@ -3212,7 +3290,9 @@ int wl1271_init_ieee80211(struct wl1271 *wl) | |||
3212 | IEEE80211_HW_SUPPORTS_UAPSD | | 3290 | IEEE80211_HW_SUPPORTS_UAPSD | |
3213 | IEEE80211_HW_HAS_RATE_CONTROL | | 3291 | IEEE80211_HW_HAS_RATE_CONTROL | |
3214 | IEEE80211_HW_CONNECTION_MONITOR | | 3292 | IEEE80211_HW_CONNECTION_MONITOR | |
3215 | IEEE80211_HW_SUPPORTS_CQM_RSSI; | 3293 | IEEE80211_HW_SUPPORTS_CQM_RSSI | |
3294 | IEEE80211_HW_REPORTS_TX_ACK_STATUS | | ||
3295 | IEEE80211_HW_AP_LINK_PS; | ||
3216 | 3296 | ||
3217 | wl->hw->wiphy->cipher_suites = cipher_suites; | 3297 | wl->hw->wiphy->cipher_suites = cipher_suites; |
3218 | wl->hw->wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites); | 3298 | wl->hw->wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites); |
@@ -3264,7 +3344,7 @@ struct ieee80211_hw *wl1271_alloc_hw(void) | |||
3264 | struct ieee80211_hw *hw; | 3344 | struct ieee80211_hw *hw; |
3265 | struct platform_device *plat_dev = NULL; | 3345 | struct platform_device *plat_dev = NULL; |
3266 | struct wl1271 *wl; | 3346 | struct wl1271 *wl; |
3267 | int i, ret; | 3347 | int i, j, ret; |
3268 | unsigned int order; | 3348 | unsigned int order; |
3269 | 3349 | ||
3270 | hw = ieee80211_alloc_hw(sizeof(*wl), &wl1271_ops); | 3350 | hw = ieee80211_alloc_hw(sizeof(*wl), &wl1271_ops); |
@@ -3292,6 +3372,10 @@ struct ieee80211_hw *wl1271_alloc_hw(void) | |||
3292 | for (i = 0; i < NUM_TX_QUEUES; i++) | 3372 | for (i = 0; i < NUM_TX_QUEUES; i++) |
3293 | skb_queue_head_init(&wl->tx_queue[i]); | 3373 | skb_queue_head_init(&wl->tx_queue[i]); |
3294 | 3374 | ||
3375 | for (i = 0; i < NUM_TX_QUEUES; i++) | ||
3376 | for (j = 0; j < AP_MAX_LINKS; j++) | ||
3377 | skb_queue_head_init(&wl->links[j].tx_queue[i]); | ||
3378 | |||
3295 | INIT_DELAYED_WORK(&wl->elp_work, wl1271_elp_work); | 3379 | INIT_DELAYED_WORK(&wl->elp_work, wl1271_elp_work); |
3296 | INIT_DELAYED_WORK(&wl->pspoll_work, wl1271_pspoll_work); | 3380 | INIT_DELAYED_WORK(&wl->pspoll_work, wl1271_pspoll_work); |
3297 | INIT_WORK(&wl->irq_work, wl1271_irq_work); | 3381 | INIT_WORK(&wl->irq_work, wl1271_irq_work); |
@@ -3317,6 +3401,9 @@ struct ieee80211_hw *wl1271_alloc_hw(void) | |||
3317 | wl->bss_type = MAX_BSS_TYPE; | 3401 | wl->bss_type = MAX_BSS_TYPE; |
3318 | wl->set_bss_type = MAX_BSS_TYPE; | 3402 | wl->set_bss_type = MAX_BSS_TYPE; |
3319 | wl->fw_bss_type = MAX_BSS_TYPE; | 3403 | wl->fw_bss_type = MAX_BSS_TYPE; |
3404 | wl->last_tx_hlid = 0; | ||
3405 | wl->ap_ps_map = 0; | ||
3406 | wl->ap_fw_ps_map = 0; | ||
3320 | 3407 | ||
3321 | memset(wl->tx_frames_map, 0, sizeof(wl->tx_frames_map)); | 3408 | memset(wl->tx_frames_map, 0, sizeof(wl->tx_frames_map)); |
3322 | for (i = 0; i < ACX_TX_DESCRIPTORS; i++) | 3409 | for (i = 0; i < ACX_TX_DESCRIPTORS; i++) |
@@ -3412,5 +3499,5 @@ module_param_named(debug_level, wl12xx_debug_level, uint, S_IRUSR | S_IWUSR); | |||
3412 | MODULE_PARM_DESC(debug_level, "wl12xx debugging level"); | 3499 | MODULE_PARM_DESC(debug_level, "wl12xx debugging level"); |
3413 | 3500 | ||
3414 | MODULE_LICENSE("GPL"); | 3501 | MODULE_LICENSE("GPL"); |
3415 | MODULE_AUTHOR("Luciano Coelho <luciano.coelho@nokia.com>"); | 3502 | MODULE_AUTHOR("Luciano Coelho <coelho@ti.com>"); |
3416 | MODULE_AUTHOR("Juuso Oikarinen <juuso.oikarinen@nokia.com>"); | 3503 | MODULE_AUTHOR("Juuso Oikarinen <juuso.oikarinen@nokia.com>"); |