diff options
Diffstat (limited to 'drivers/net/wireless/p54/p54common.c')
| -rw-r--r-- | drivers/net/wireless/p54/p54common.c | 452 |
1 files changed, 396 insertions, 56 deletions
diff --git a/drivers/net/wireless/p54/p54common.c b/drivers/net/wireless/p54/p54common.c index cf04c721a012..1796b8c6c5b8 100644 --- a/drivers/net/wireless/p54/p54common.c +++ b/drivers/net/wireless/p54/p54common.c | |||
| @@ -9,7 +9,7 @@ | |||
| 9 | * - the islsm (softmac prism54) driver, which is: | 9 | * - the islsm (softmac prism54) driver, which is: |
| 10 | * Copyright 2004-2006 Jean-Baptiste Note <jbnote@gmail.com>, et al. | 10 | * Copyright 2004-2006 Jean-Baptiste Note <jbnote@gmail.com>, et al. |
| 11 | * - stlc45xx driver | 11 | * - stlc45xx driver |
| 12 | * C Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). | 12 | * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). |
| 13 | * | 13 | * |
| 14 | * This program is free software; you can redistribute it and/or modify | 14 | * This program is free software; you can redistribute it and/or modify |
| 15 | * it under the terms of the GNU General Public License version 2 as | 15 | * it under the terms of the GNU General Public License version 2 as |
| @@ -214,12 +214,17 @@ int p54_parse_firmware(struct ieee80211_hw *dev, const struct firmware *fw) | |||
| 214 | printk(KERN_INFO "p54: FW rev %s - Softmac protocol %x.%x\n", | 214 | printk(KERN_INFO "p54: FW rev %s - Softmac protocol %x.%x\n", |
| 215 | fw_version, priv->fw_var >> 8, priv->fw_var & 0xff); | 215 | fw_version, priv->fw_var >> 8, priv->fw_var & 0xff); |
| 216 | 216 | ||
| 217 | if (priv->fw_var < 0x500) | ||
| 218 | printk(KERN_INFO "p54: you are using an obsolete firmware. " | ||
| 219 | "visit http://wireless.kernel.org/en/users/Drivers/p54 " | ||
| 220 | "and grab one for \"kernel >= 2.6.28\"!\n"); | ||
| 221 | |||
| 217 | if (priv->fw_var >= 0x300) { | 222 | if (priv->fw_var >= 0x300) { |
| 218 | /* Firmware supports QoS, use it! */ | 223 | /* Firmware supports QoS, use it! */ |
| 219 | priv->tx_stats[4].limit = 3; | 224 | priv->tx_stats[4].limit = 3; /* AC_VO */ |
| 220 | priv->tx_stats[5].limit = 4; | 225 | priv->tx_stats[5].limit = 4; /* AC_VI */ |
| 221 | priv->tx_stats[6].limit = 3; | 226 | priv->tx_stats[6].limit = 3; /* AC_BE */ |
| 222 | priv->tx_stats[7].limit = 1; | 227 | priv->tx_stats[7].limit = 2; /* AC_BK */ |
| 223 | dev->queues = 4; | 228 | dev->queues = 4; |
| 224 | } | 229 | } |
| 225 | 230 | ||
| @@ -415,6 +420,30 @@ static int p54_parse_eeprom(struct ieee80211_hw *dev, void *eeprom, int len) | |||
| 415 | /* make it overrun */ | 420 | /* make it overrun */ |
| 416 | entry_len = len; | 421 | entry_len = len; |
| 417 | break; | 422 | break; |
| 423 | case PDR_MANUFACTURING_PART_NUMBER: | ||
| 424 | case PDR_PDA_VERSION: | ||
| 425 | case PDR_NIC_SERIAL_NUMBER: | ||
| 426 | case PDR_REGULATORY_DOMAIN_LIST: | ||
| 427 | case PDR_TEMPERATURE_TYPE: | ||
| 428 | case PDR_PRISM_PCI_IDENTIFIER: | ||
| 429 | case PDR_COUNTRY_INFORMATION: | ||
| 430 | case PDR_OEM_NAME: | ||
| 431 | case PDR_PRODUCT_NAME: | ||
| 432 | case PDR_UTF8_OEM_NAME: | ||
| 433 | case PDR_UTF8_PRODUCT_NAME: | ||
| 434 | case PDR_COUNTRY_LIST: | ||
| 435 | case PDR_DEFAULT_COUNTRY: | ||
| 436 | case PDR_ANTENNA_GAIN: | ||
| 437 | case PDR_PRISM_INDIGO_PA_CALIBRATION_DATA: | ||
| 438 | case PDR_RSSI_LINEAR_APPROXIMATION: | ||
| 439 | case PDR_RSSI_LINEAR_APPROXIMATION_DUAL_BAND: | ||
| 440 | case PDR_REGULATORY_POWER_LIMITS: | ||
| 441 | case PDR_RSSI_LINEAR_APPROXIMATION_EXTENDED: | ||
| 442 | case PDR_RADIATED_TRANSMISSION_CORRECTION: | ||
| 443 | case PDR_PRISM_TX_IQ_CALIBRATION: | ||
| 444 | case PDR_BASEBAND_REGISTERS: | ||
| 445 | case PDR_PER_CHANNEL_BASEBAND_REGISTERS: | ||
| 446 | break; | ||
| 418 | default: | 447 | default: |
| 419 | printk(KERN_INFO "p54: unknown eeprom code : 0x%x\n", | 448 | printk(KERN_INFO "p54: unknown eeprom code : 0x%x\n", |
| 420 | le16_to_cpu(entry->code)); | 449 | le16_to_cpu(entry->code)); |
| @@ -431,12 +460,12 @@ static int p54_parse_eeprom(struct ieee80211_hw *dev, void *eeprom, int len) | |||
| 431 | goto err; | 460 | goto err; |
| 432 | } | 461 | } |
| 433 | 462 | ||
| 434 | priv->rxhw = synth & 0x07; | 463 | priv->rxhw = synth & PDR_SYNTH_FRONTEND_MASK; |
| 435 | if (priv->rxhw == 4) | 464 | if (priv->rxhw == 4) |
| 436 | p54_init_xbow_synth(dev); | 465 | p54_init_xbow_synth(dev); |
| 437 | if (!(synth & 0x40)) | 466 | if (!(synth & PDR_SYNTH_24_GHZ_DISABLED)) |
| 438 | dev->wiphy->bands[IEEE80211_BAND_2GHZ] = &band_2GHz; | 467 | dev->wiphy->bands[IEEE80211_BAND_2GHZ] = &band_2GHz; |
| 439 | if (!(synth & 0x80)) | 468 | if (!(synth & PDR_SYNTH_5_GHZ_DISABLED)) |
| 440 | dev->wiphy->bands[IEEE80211_BAND_5GHZ] = &band_5GHz; | 469 | dev->wiphy->bands[IEEE80211_BAND_5GHZ] = &band_5GHz; |
| 441 | 470 | ||
| 442 | if (!is_valid_ether_addr(dev->wiphy->perm_addr)) { | 471 | if (!is_valid_ether_addr(dev->wiphy->perm_addr)) { |
| @@ -621,6 +650,12 @@ static void p54_rx_frame_sent(struct ieee80211_hw *dev, struct sk_buff *skb) | |||
| 621 | __skb_unlink(entry, &priv->tx_queue); | 650 | __skb_unlink(entry, &priv->tx_queue); |
| 622 | spin_unlock_irqrestore(&priv->tx_queue.lock, flags); | 651 | spin_unlock_irqrestore(&priv->tx_queue.lock, flags); |
| 623 | 652 | ||
| 653 | if (unlikely(entry == priv->cached_beacon)) { | ||
| 654 | kfree_skb(entry); | ||
| 655 | priv->cached_beacon = NULL; | ||
| 656 | goto out; | ||
| 657 | } | ||
| 658 | |||
| 624 | /* | 659 | /* |
| 625 | * Clear manually, ieee80211_tx_info_clear_status would | 660 | * Clear manually, ieee80211_tx_info_clear_status would |
| 626 | * clear the counts too and we need them. | 661 | * clear the counts too and we need them. |
| @@ -654,7 +689,7 @@ static void p54_rx_frame_sent(struct ieee80211_hw *dev, struct sk_buff *skb) | |||
| 654 | if (!(info->flags & IEEE80211_TX_CTL_NO_ACK) && | 689 | if (!(info->flags & IEEE80211_TX_CTL_NO_ACK) && |
| 655 | (!payload->status)) | 690 | (!payload->status)) |
| 656 | info->flags |= IEEE80211_TX_STAT_ACK; | 691 | info->flags |= IEEE80211_TX_STAT_ACK; |
| 657 | if (payload->status & 0x02) | 692 | if (payload->status & P54_TX_PSM_CANCELLED) |
| 658 | info->flags |= IEEE80211_TX_STAT_TX_FILTERED; | 693 | info->flags |= IEEE80211_TX_STAT_TX_FILTERED; |
| 659 | info->status.ack_signal = p54_rssi_to_dbm(dev, | 694 | info->status.ack_signal = p54_rssi_to_dbm(dev, |
| 660 | (int)payload->ack_rssi); | 695 | (int)payload->ack_rssi); |
| @@ -706,6 +741,35 @@ static void p54_rx_stats(struct ieee80211_hw *dev, struct sk_buff *skb) | |||
| 706 | mod_timer(&priv->stats_timer, jiffies + 5 * HZ); | 741 | mod_timer(&priv->stats_timer, jiffies + 5 * HZ); |
| 707 | } | 742 | } |
| 708 | 743 | ||
| 744 | static void p54_rx_trap(struct ieee80211_hw *dev, struct sk_buff *skb) | ||
| 745 | { | ||
| 746 | struct p54_hdr *hdr = (struct p54_hdr *) skb->data; | ||
| 747 | struct p54_trap *trap = (struct p54_trap *) hdr->data; | ||
| 748 | u16 event = le16_to_cpu(trap->event); | ||
| 749 | u16 freq = le16_to_cpu(trap->frequency); | ||
| 750 | |||
| 751 | switch (event) { | ||
| 752 | case P54_TRAP_BEACON_TX: | ||
| 753 | break; | ||
| 754 | case P54_TRAP_RADAR: | ||
| 755 | printk(KERN_INFO "%s: radar (freq:%d MHz)\n", | ||
| 756 | wiphy_name(dev->wiphy), freq); | ||
| 757 | break; | ||
| 758 | case P54_TRAP_NO_BEACON: | ||
| 759 | break; | ||
| 760 | case P54_TRAP_SCAN: | ||
| 761 | break; | ||
| 762 | case P54_TRAP_TBTT: | ||
| 763 | break; | ||
| 764 | case P54_TRAP_TIMER: | ||
| 765 | break; | ||
| 766 | default: | ||
| 767 | printk(KERN_INFO "%s: received event:%x freq:%d\n", | ||
| 768 | wiphy_name(dev->wiphy), event, freq); | ||
| 769 | break; | ||
| 770 | } | ||
| 771 | } | ||
| 772 | |||
| 709 | static int p54_rx_control(struct ieee80211_hw *dev, struct sk_buff *skb) | 773 | static int p54_rx_control(struct ieee80211_hw *dev, struct sk_buff *skb) |
| 710 | { | 774 | { |
| 711 | struct p54_hdr *hdr = (struct p54_hdr *) skb->data; | 775 | struct p54_hdr *hdr = (struct p54_hdr *) skb->data; |
| @@ -714,6 +778,9 @@ static int p54_rx_control(struct ieee80211_hw *dev, struct sk_buff *skb) | |||
| 714 | case P54_CONTROL_TYPE_TXDONE: | 778 | case P54_CONTROL_TYPE_TXDONE: |
| 715 | p54_rx_frame_sent(dev, skb); | 779 | p54_rx_frame_sent(dev, skb); |
| 716 | break; | 780 | break; |
| 781 | case P54_CONTROL_TYPE_TRAP: | ||
| 782 | p54_rx_trap(dev, skb); | ||
| 783 | break; | ||
| 717 | case P54_CONTROL_TYPE_BBP: | 784 | case P54_CONTROL_TYPE_BBP: |
| 718 | break; | 785 | break; |
| 719 | case P54_CONTROL_TYPE_STAT_READBACK: | 786 | case P54_CONTROL_TYPE_STAT_READBACK: |
| @@ -734,9 +801,9 @@ static int p54_rx_control(struct ieee80211_hw *dev, struct sk_buff *skb) | |||
| 734 | /* returns zero if skb can be reused */ | 801 | /* returns zero if skb can be reused */ |
| 735 | int p54_rx(struct ieee80211_hw *dev, struct sk_buff *skb) | 802 | int p54_rx(struct ieee80211_hw *dev, struct sk_buff *skb) |
| 736 | { | 803 | { |
| 737 | u8 type = le16_to_cpu(*((__le16 *)skb->data)) >> 8; | 804 | u16 type = le16_to_cpu(*((__le16 *)skb->data)); |
| 738 | 805 | ||
| 739 | if (type == 0x80) | 806 | if (type & P54_HDR_FLAG_CONTROL) |
| 740 | return p54_rx_control(dev, skb); | 807 | return p54_rx_control(dev, skb); |
| 741 | else | 808 | else |
| 742 | return p54_rx_data(dev, skb); | 809 | return p54_rx_data(dev, skb); |
| @@ -897,41 +964,162 @@ free: | |||
| 897 | } | 964 | } |
| 898 | EXPORT_SYMBOL_GPL(p54_read_eeprom); | 965 | EXPORT_SYMBOL_GPL(p54_read_eeprom); |
| 899 | 966 | ||
| 967 | static int p54_set_tim(struct ieee80211_hw *dev, struct ieee80211_sta *sta, | ||
| 968 | bool set) | ||
| 969 | { | ||
| 970 | struct p54_common *priv = dev->priv; | ||
| 971 | struct sk_buff *skb; | ||
| 972 | struct p54_tim *tim; | ||
| 973 | |||
| 974 | skb = p54_alloc_skb(dev, P54_HDR_FLAG_CONTROL_OPSET, | ||
| 975 | sizeof(struct p54_hdr) + sizeof(*tim), | ||
| 976 | P54_CONTROL_TYPE_TIM, GFP_KERNEL); | ||
| 977 | if (!skb) | ||
| 978 | return -ENOMEM; | ||
| 979 | |||
| 980 | tim = (struct p54_tim *) skb_put(skb, sizeof(*tim)); | ||
| 981 | tim->count = 1; | ||
| 982 | tim->entry[0] = cpu_to_le16(set ? (sta->aid | 0x8000) : sta->aid); | ||
| 983 | priv->tx(dev, skb, 1); | ||
| 984 | return 0; | ||
| 985 | } | ||
| 986 | |||
| 987 | static int p54_sta_unlock(struct ieee80211_hw *dev, u8 *addr) | ||
| 988 | { | ||
| 989 | struct p54_common *priv = dev->priv; | ||
| 990 | struct sk_buff *skb; | ||
| 991 | struct p54_sta_unlock *sta; | ||
| 992 | |||
| 993 | skb = p54_alloc_skb(dev, P54_HDR_FLAG_CONTROL_OPSET, | ||
| 994 | sizeof(struct p54_hdr) + sizeof(*sta), | ||
| 995 | P54_CONTROL_TYPE_PSM_STA_UNLOCK, GFP_ATOMIC); | ||
| 996 | if (!skb) | ||
| 997 | return -ENOMEM; | ||
| 998 | |||
| 999 | sta = (struct p54_sta_unlock *)skb_put(skb, sizeof(*sta)); | ||
| 1000 | memcpy(sta->addr, addr, ETH_ALEN); | ||
| 1001 | priv->tx(dev, skb, 1); | ||
| 1002 | return 0; | ||
| 1003 | } | ||
| 1004 | |||
| 1005 | static int p54_tx_cancel(struct ieee80211_hw *dev, struct sk_buff *entry) | ||
| 1006 | { | ||
| 1007 | struct p54_common *priv = dev->priv; | ||
| 1008 | struct sk_buff *skb; | ||
| 1009 | struct p54_hdr *hdr; | ||
| 1010 | struct p54_txcancel *cancel; | ||
| 1011 | |||
| 1012 | skb = p54_alloc_skb(dev, P54_HDR_FLAG_CONTROL_OPSET, | ||
| 1013 | sizeof(struct p54_hdr) + sizeof(*cancel), | ||
| 1014 | P54_CONTROL_TYPE_TXCANCEL, GFP_ATOMIC); | ||
| 1015 | if (!skb) | ||
| 1016 | return -ENOMEM; | ||
| 1017 | |||
| 1018 | hdr = (void *)entry->data; | ||
| 1019 | cancel = (struct p54_txcancel *)skb_put(skb, sizeof(*cancel)); | ||
| 1020 | cancel->req_id = hdr->req_id; | ||
| 1021 | priv->tx(dev, skb, 1); | ||
| 1022 | return 0; | ||
| 1023 | } | ||
| 1024 | |||
| 1025 | static int p54_tx_fill(struct ieee80211_hw *dev, struct sk_buff *skb, | ||
| 1026 | struct ieee80211_tx_info *info, u8 *queue, size_t *extra_len, | ||
| 1027 | u16 *flags, u16 *aid) | ||
| 1028 | { | ||
| 1029 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; | ||
| 1030 | struct p54_common *priv = dev->priv; | ||
| 1031 | int ret = 0; | ||
| 1032 | |||
| 1033 | if (unlikely(ieee80211_is_mgmt(hdr->frame_control))) { | ||
| 1034 | if (ieee80211_is_beacon(hdr->frame_control)) { | ||
| 1035 | *aid = 0; | ||
| 1036 | *queue = 0; | ||
| 1037 | *extra_len = IEEE80211_MAX_TIM_LEN; | ||
| 1038 | *flags = P54_HDR_FLAG_DATA_OUT_TIMESTAMP; | ||
| 1039 | return 0; | ||
| 1040 | } else if (ieee80211_is_probe_resp(hdr->frame_control)) { | ||
| 1041 | *aid = 0; | ||
| 1042 | *queue = 2; | ||
| 1043 | *flags = P54_HDR_FLAG_DATA_OUT_TIMESTAMP | | ||
| 1044 | P54_HDR_FLAG_DATA_OUT_NOCANCEL; | ||
| 1045 | return 0; | ||
| 1046 | } else { | ||
| 1047 | *queue = 2; | ||
| 1048 | ret = 0; | ||
| 1049 | } | ||
| 1050 | } else { | ||
| 1051 | *queue += 4; | ||
| 1052 | ret = 1; | ||
| 1053 | } | ||
| 1054 | |||
| 1055 | switch (priv->mode) { | ||
| 1056 | case NL80211_IFTYPE_STATION: | ||
| 1057 | *aid = 1; | ||
| 1058 | break; | ||
| 1059 | case NL80211_IFTYPE_AP: | ||
| 1060 | case NL80211_IFTYPE_ADHOC: | ||
| 1061 | if (info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM) { | ||
| 1062 | *aid = 0; | ||
| 1063 | *queue = 3; | ||
| 1064 | return 0; | ||
| 1065 | } | ||
| 1066 | if (info->control.sta) | ||
| 1067 | *aid = info->control.sta->aid; | ||
| 1068 | else | ||
| 1069 | *flags = P54_HDR_FLAG_DATA_OUT_NOCANCEL; | ||
| 1070 | } | ||
| 1071 | return ret; | ||
| 1072 | } | ||
| 1073 | |||
| 900 | static int p54_tx(struct ieee80211_hw *dev, struct sk_buff *skb) | 1074 | static int p54_tx(struct ieee80211_hw *dev, struct sk_buff *skb) |
| 901 | { | 1075 | { |
| 902 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 1076 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
| 903 | struct ieee80211_tx_queue_stats *current_queue; | 1077 | struct ieee80211_tx_queue_stats *current_queue = NULL; |
| 904 | struct p54_common *priv = dev->priv; | 1078 | struct p54_common *priv = dev->priv; |
| 905 | struct p54_hdr *hdr; | 1079 | struct p54_hdr *hdr; |
| 906 | struct p54_tx_data *txhdr; | 1080 | struct p54_tx_data *txhdr; |
| 907 | size_t padding, len; | 1081 | size_t padding, len, tim_len = 0; |
| 908 | int i, j, ridx; | 1082 | int i, j, ridx; |
| 909 | u8 rate; | 1083 | u16 hdr_flags = 0, aid = 0; |
| 1084 | u8 rate, queue; | ||
| 910 | u8 cts_rate = 0x20; | 1085 | u8 cts_rate = 0x20; |
| 911 | u8 rc_flags; | 1086 | u8 rc_flags; |
| 912 | u8 calculated_tries[4]; | 1087 | u8 calculated_tries[4]; |
| 913 | u8 nrates = 0, nremaining = 8; | 1088 | u8 nrates = 0, nremaining = 8; |
| 914 | 1089 | ||
| 915 | current_queue = &priv->tx_stats[skb_get_queue_mapping(skb) + 4]; | 1090 | queue = skb_get_queue_mapping(skb); |
| 916 | if (unlikely(current_queue->len > current_queue->limit)) | 1091 | |
| 917 | return NETDEV_TX_BUSY; | 1092 | if (p54_tx_fill(dev, skb, info, &queue, &tim_len, &hdr_flags, &aid)) { |
| 918 | current_queue->len++; | 1093 | current_queue = &priv->tx_stats[queue]; |
| 919 | current_queue->count++; | 1094 | if (unlikely(current_queue->len > current_queue->limit)) |
| 920 | if (current_queue->len == current_queue->limit) | 1095 | return NETDEV_TX_BUSY; |
| 921 | ieee80211_stop_queue(dev, skb_get_queue_mapping(skb)); | 1096 | current_queue->len++; |
| 1097 | current_queue->count++; | ||
| 1098 | if (current_queue->len == current_queue->limit) | ||
| 1099 | ieee80211_stop_queue(dev, skb_get_queue_mapping(skb)); | ||
| 1100 | } | ||
| 922 | 1101 | ||
| 923 | padding = (unsigned long)(skb->data - (sizeof(*hdr) + sizeof(*txhdr))) & 3; | 1102 | padding = (unsigned long)(skb->data - (sizeof(*hdr) + sizeof(*txhdr))) & 3; |
| 924 | len = skb->len; | 1103 | len = skb->len; |
| 925 | 1104 | ||
| 1105 | if (info->flags & IEEE80211_TX_CTL_CLEAR_PS_FILT) { | ||
| 1106 | if (info->control.sta) | ||
| 1107 | if (p54_sta_unlock(dev, info->control.sta->addr)) { | ||
| 1108 | if (current_queue) { | ||
| 1109 | current_queue->len--; | ||
| 1110 | current_queue->count--; | ||
| 1111 | } | ||
| 1112 | return NETDEV_TX_BUSY; | ||
| 1113 | } | ||
| 1114 | } | ||
| 1115 | |||
| 926 | txhdr = (struct p54_tx_data *) skb_push(skb, sizeof(*txhdr) + padding); | 1116 | txhdr = (struct p54_tx_data *) skb_push(skb, sizeof(*txhdr) + padding); |
| 927 | hdr = (struct p54_hdr *) skb_push(skb, sizeof(*hdr)); | 1117 | hdr = (struct p54_hdr *) skb_push(skb, sizeof(*hdr)); |
| 928 | 1118 | ||
| 929 | if (padding) | 1119 | if (padding) |
| 930 | hdr->flags = cpu_to_le16(P54_HDR_FLAG_DATA_ALIGN); | 1120 | hdr_flags |= P54_HDR_FLAG_DATA_ALIGN; |
| 931 | else | ||
| 932 | hdr->flags = cpu_to_le16(0); | ||
| 933 | hdr->len = cpu_to_le16(len); | 1121 | hdr->len = cpu_to_le16(len); |
| 934 | hdr->type = (info->flags & IEEE80211_TX_CTL_NO_ACK) ? 0 : cpu_to_le16(1); | 1122 | hdr->type = cpu_to_le16(aid); |
| 935 | hdr->rts_tries = info->control.rates[0].count; | 1123 | hdr->rts_tries = info->control.rates[0].count; |
| 936 | 1124 | ||
| 937 | /* | 1125 | /* |
| @@ -998,12 +1186,18 @@ static int p54_tx(struct ieee80211_hw *dev, struct sk_buff *skb) | |||
| 998 | ridx++; | 1186 | ridx++; |
| 999 | } | 1187 | } |
| 1000 | } | 1188 | } |
| 1189 | |||
| 1190 | if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) | ||
| 1191 | hdr_flags |= P54_HDR_FLAG_DATA_OUT_SEQNR; | ||
| 1192 | |||
| 1193 | /* TODO: enable bursting */ | ||
| 1194 | hdr->flags = cpu_to_le16(hdr_flags); | ||
| 1001 | hdr->tries = ridx; | 1195 | hdr->tries = ridx; |
| 1002 | txhdr->crypt_offset = 0; | 1196 | txhdr->crypt_offset = 0; |
| 1003 | txhdr->rts_rate_idx = 0; | 1197 | txhdr->rts_rate_idx = 0; |
| 1004 | txhdr->key_type = 0; | 1198 | txhdr->key_type = 0; |
| 1005 | txhdr->key_len = 0; | 1199 | txhdr->key_len = 0; |
| 1006 | txhdr->hw_queue = skb_get_queue_mapping(skb) + 4; | 1200 | txhdr->hw_queue = queue; |
| 1007 | txhdr->backlog = 32; | 1201 | txhdr->backlog = 32; |
| 1008 | memset(txhdr->durations, 0, sizeof(txhdr->durations)); | 1202 | memset(txhdr->durations, 0, sizeof(txhdr->durations)); |
| 1009 | txhdr->tx_antenna = (info->antenna_sel_tx == 0) ? | 1203 | txhdr->tx_antenna = (info->antenna_sel_tx == 0) ? |
| @@ -1014,8 +1208,12 @@ static int p54_tx(struct ieee80211_hw *dev, struct sk_buff *skb) | |||
| 1014 | txhdr->align[0] = padding; | 1208 | txhdr->align[0] = padding; |
| 1015 | 1209 | ||
| 1016 | /* modifies skb->cb and with it info, so must be last! */ | 1210 | /* modifies skb->cb and with it info, so must be last! */ |
| 1017 | if (unlikely(p54_assign_address(dev, skb, hdr, skb->len))) { | 1211 | if (unlikely(p54_assign_address(dev, skb, hdr, skb->len + tim_len))) { |
| 1018 | skb_pull(skb, sizeof(*hdr) + sizeof(*txhdr) + padding); | 1212 | skb_pull(skb, sizeof(*hdr) + sizeof(*txhdr) + padding); |
| 1213 | if (current_queue) { | ||
| 1214 | current_queue->len--; | ||
| 1215 | current_queue->count--; | ||
| 1216 | } | ||
| 1019 | return NETDEV_TX_BUSY; | 1217 | return NETDEV_TX_BUSY; |
| 1020 | } | 1218 | } |
| 1021 | priv->tx(dev, skb, 0); | 1219 | priv->tx(dev, skb, 0); |
| @@ -1043,8 +1241,10 @@ static int p54_setup_mac(struct ieee80211_hw *dev, u16 mode, const u8 *bssid) | |||
| 1043 | else | 1241 | else |
| 1044 | memcpy(setup->bssid, bssid, ETH_ALEN); | 1242 | memcpy(setup->bssid, bssid, ETH_ALEN); |
| 1045 | setup->rx_antenna = priv->rx_antenna; | 1243 | setup->rx_antenna = priv->rx_antenna; |
| 1244 | setup->rx_align = 0; | ||
| 1046 | if (priv->fw_var < 0x500) { | 1245 | if (priv->fw_var < 0x500) { |
| 1047 | setup->v1.basic_rate_mask = cpu_to_le32(0x15f); | 1246 | setup->v1.basic_rate_mask = cpu_to_le32(0x15f); |
| 1247 | memset(setup->v1.rts_rates, 0, 8); | ||
| 1048 | setup->v1.rx_addr = cpu_to_le32(priv->rx_end); | 1248 | setup->v1.rx_addr = cpu_to_le32(priv->rx_end); |
| 1049 | setup->v1.max_rx = cpu_to_le16(priv->rx_mtu); | 1249 | setup->v1.max_rx = cpu_to_le16(priv->rx_mtu); |
| 1050 | setup->v1.rxhw = cpu_to_le16(priv->rxhw); | 1250 | setup->v1.rxhw = cpu_to_le16(priv->rxhw); |
| @@ -1069,13 +1269,14 @@ static int p54_setup_mac(struct ieee80211_hw *dev, u16 mode, const u8 *bssid) | |||
| 1069 | return 0; | 1269 | return 0; |
| 1070 | } | 1270 | } |
| 1071 | 1271 | ||
| 1072 | static int p54_set_freq(struct ieee80211_hw *dev, __le16 freq) | 1272 | static int p54_set_freq(struct ieee80211_hw *dev, u16 frequency) |
| 1073 | { | 1273 | { |
| 1074 | struct p54_common *priv = dev->priv; | 1274 | struct p54_common *priv = dev->priv; |
| 1075 | struct sk_buff *skb; | 1275 | struct sk_buff *skb; |
| 1076 | struct p54_scan *chan; | 1276 | struct p54_scan *chan; |
| 1077 | unsigned int i; | 1277 | unsigned int i; |
| 1078 | void *entry; | 1278 | void *entry; |
| 1279 | __le16 freq = cpu_to_le16(frequency); | ||
| 1079 | 1280 | ||
| 1080 | skb = p54_alloc_skb(dev, P54_HDR_FLAG_CONTROL_OPSET, sizeof(*chan) + | 1281 | skb = p54_alloc_skb(dev, P54_HDR_FLAG_CONTROL_OPSET, sizeof(*chan) + |
| 1081 | sizeof(struct p54_hdr), P54_CONTROL_TYPE_SCAN, | 1282 | sizeof(struct p54_hdr), P54_CONTROL_TYPE_SCAN, |
| @@ -1127,11 +1328,11 @@ static int p54_set_freq(struct ieee80211_hw *dev, __le16 freq) | |||
| 1127 | } | 1328 | } |
| 1128 | 1329 | ||
| 1129 | entry += sizeof(__le16); | 1330 | entry += sizeof(__le16); |
| 1130 | chan->pa_points_per_curve = | 1331 | chan->pa_points_per_curve = 8; |
| 1131 | min(priv->curve_data->points_per_channel, (u8) 8); | 1332 | memset(chan->curve_data, 0, sizeof(*chan->curve_data)); |
| 1132 | 1333 | memcpy(chan->curve_data, entry, | |
| 1133 | memcpy(chan->curve_data, entry, sizeof(*chan->curve_data) * | 1334 | sizeof(struct p54_pa_curve_data_sample) * |
| 1134 | chan->pa_points_per_curve); | 1335 | min((u8)8, priv->curve_data->points_per_channel)); |
| 1135 | break; | 1336 | break; |
| 1136 | } | 1337 | } |
| 1137 | 1338 | ||
| @@ -1207,6 +1408,7 @@ static int p54_set_edcf(struct ieee80211_hw *dev) | |||
| 1207 | /* (see prism54/isl_oid.h for further details) */ | 1408 | /* (see prism54/isl_oid.h for further details) */ |
| 1208 | edcf->frameburst = cpu_to_le16(0); | 1409 | edcf->frameburst = cpu_to_le16(0); |
| 1209 | edcf->round_trip_delay = cpu_to_le16(0); | 1410 | edcf->round_trip_delay = cpu_to_le16(0); |
| 1411 | edcf->flags = 0; | ||
| 1210 | memset(edcf->mapping, 0, sizeof(edcf->mapping)); | 1412 | memset(edcf->mapping, 0, sizeof(edcf->mapping)); |
| 1211 | memcpy(edcf->queue, priv->qos_params, sizeof(edcf->queue)); | 1413 | memcpy(edcf->queue, priv->qos_params, sizeof(edcf->queue)); |
| 1212 | priv->tx(dev, skb, 1); | 1414 | priv->tx(dev, skb, 1); |
| @@ -1227,11 +1429,94 @@ static int p54_init_stats(struct ieee80211_hw *dev) | |||
| 1227 | return 0; | 1429 | return 0; |
| 1228 | } | 1430 | } |
| 1229 | 1431 | ||
| 1432 | static int p54_beacon_tim(struct sk_buff *skb) | ||
| 1433 | { | ||
| 1434 | /* | ||
| 1435 | * the good excuse for this mess is ... the firmware. | ||
| 1436 | * The dummy TIM MUST be at the end of the beacon frame, | ||
| 1437 | * because it'll be overwritten! | ||
| 1438 | */ | ||
| 1439 | |||
| 1440 | struct ieee80211_mgmt *mgmt = (void *)skb->data; | ||
| 1441 | u8 *pos, *end; | ||
| 1442 | |||
| 1443 | if (skb->len <= sizeof(mgmt)) { | ||
| 1444 | printk(KERN_ERR "p54: beacon is too short!\n"); | ||
| 1445 | return -EINVAL; | ||
| 1446 | } | ||
| 1447 | |||
| 1448 | pos = (u8 *)mgmt->u.beacon.variable; | ||
| 1449 | end = skb->data + skb->len; | ||
| 1450 | while (pos < end) { | ||
| 1451 | if (pos + 2 + pos[1] > end) { | ||
| 1452 | printk(KERN_ERR "p54: parsing beacon failed\n"); | ||
| 1453 | return -EINVAL; | ||
| 1454 | } | ||
| 1455 | |||
| 1456 | if (pos[0] == WLAN_EID_TIM) { | ||
| 1457 | u8 dtim_len = pos[1]; | ||
| 1458 | u8 dtim_period = pos[3]; | ||
| 1459 | u8 *next = pos + 2 + dtim_len; | ||
| 1460 | |||
| 1461 | if (dtim_len < 3) { | ||
| 1462 | printk(KERN_ERR "p54: invalid dtim len!\n"); | ||
| 1463 | return -EINVAL; | ||
| 1464 | } | ||
| 1465 | memmove(pos, next, end - next); | ||
| 1466 | |||
| 1467 | if (dtim_len > 3) | ||
| 1468 | skb_trim(skb, skb->len - (dtim_len - 3)); | ||
| 1469 | |||
| 1470 | pos = end - (dtim_len + 2); | ||
| 1471 | |||
| 1472 | /* add the dummy at the end */ | ||
| 1473 | pos[0] = WLAN_EID_TIM; | ||
| 1474 | pos[1] = 3; | ||
| 1475 | pos[2] = 0; | ||
| 1476 | pos[3] = dtim_period; | ||
| 1477 | pos[4] = 0; | ||
| 1478 | return 0; | ||
| 1479 | } | ||
| 1480 | pos += 2 + pos[1]; | ||
| 1481 | } | ||
| 1482 | return 0; | ||
| 1483 | } | ||
| 1484 | |||
| 1485 | static int p54_beacon_update(struct ieee80211_hw *dev, | ||
| 1486 | struct ieee80211_vif *vif) | ||
| 1487 | { | ||
| 1488 | struct p54_common *priv = dev->priv; | ||
| 1489 | struct sk_buff *beacon; | ||
| 1490 | int ret; | ||
| 1491 | |||
| 1492 | if (priv->cached_beacon) { | ||
| 1493 | p54_tx_cancel(dev, priv->cached_beacon); | ||
| 1494 | /* wait for the last beacon the be freed */ | ||
| 1495 | msleep(10); | ||
| 1496 | } | ||
| 1497 | |||
| 1498 | beacon = ieee80211_beacon_get(dev, vif); | ||
| 1499 | if (!beacon) | ||
| 1500 | return -ENOMEM; | ||
| 1501 | ret = p54_beacon_tim(beacon); | ||
| 1502 | if (ret) | ||
| 1503 | return ret; | ||
| 1504 | ret = p54_tx(dev, beacon); | ||
| 1505 | if (ret) | ||
| 1506 | return ret; | ||
| 1507 | priv->cached_beacon = beacon; | ||
| 1508 | priv->tsf_high32 = 0; | ||
| 1509 | priv->tsf_low32 = 0; | ||
| 1510 | |||
| 1511 | return 0; | ||
| 1512 | } | ||
| 1513 | |||
| 1230 | static int p54_start(struct ieee80211_hw *dev) | 1514 | static int p54_start(struct ieee80211_hw *dev) |
| 1231 | { | 1515 | { |
| 1232 | struct p54_common *priv = dev->priv; | 1516 | struct p54_common *priv = dev->priv; |
| 1233 | int err; | 1517 | int err; |
| 1234 | 1518 | ||
| 1519 | mutex_lock(&priv->conf_mutex); | ||
| 1235 | err = priv->open(dev); | 1520 | err = priv->open(dev); |
| 1236 | if (!err) | 1521 | if (!err) |
| 1237 | priv->mode = NL80211_IFTYPE_MONITOR; | 1522 | priv->mode = NL80211_IFTYPE_MONITOR; |
| @@ -1243,6 +1528,7 @@ static int p54_start(struct ieee80211_hw *dev) | |||
| 1243 | if (!err) | 1528 | if (!err) |
| 1244 | err = p54_init_stats(dev); | 1529 | err = p54_init_stats(dev); |
| 1245 | 1530 | ||
| 1531 | mutex_unlock(&priv->conf_mutex); | ||
| 1246 | return err; | 1532 | return err; |
| 1247 | } | 1533 | } |
| 1248 | 1534 | ||
| @@ -1251,15 +1537,22 @@ static void p54_stop(struct ieee80211_hw *dev) | |||
| 1251 | struct p54_common *priv = dev->priv; | 1537 | struct p54_common *priv = dev->priv; |
| 1252 | struct sk_buff *skb; | 1538 | struct sk_buff *skb; |
| 1253 | 1539 | ||
| 1540 | mutex_lock(&priv->conf_mutex); | ||
| 1254 | del_timer(&priv->stats_timer); | 1541 | del_timer(&priv->stats_timer); |
| 1255 | p54_free_skb(dev, priv->cached_stats); | 1542 | p54_free_skb(dev, priv->cached_stats); |
| 1256 | priv->cached_stats = NULL; | 1543 | priv->cached_stats = NULL; |
| 1544 | if (priv->cached_beacon) | ||
| 1545 | p54_tx_cancel(dev, priv->cached_beacon); | ||
| 1546 | |||
| 1257 | while ((skb = skb_dequeue(&priv->tx_queue))) | 1547 | while ((skb = skb_dequeue(&priv->tx_queue))) |
| 1258 | kfree_skb(skb); | 1548 | kfree_skb(skb); |
| 1259 | 1549 | ||
| 1550 | kfree(priv->cached_beacon); | ||
| 1551 | priv->cached_beacon = NULL; | ||
| 1260 | priv->stop(dev); | 1552 | priv->stop(dev); |
| 1261 | priv->tsf_high32 = priv->tsf_low32 = 0; | 1553 | priv->tsf_high32 = priv->tsf_low32 = 0; |
| 1262 | priv->mode = NL80211_IFTYPE_UNSPECIFIED; | 1554 | priv->mode = NL80211_IFTYPE_UNSPECIFIED; |
| 1555 | mutex_unlock(&priv->conf_mutex); | ||
| 1263 | } | 1556 | } |
| 1264 | 1557 | ||
| 1265 | static int p54_add_interface(struct ieee80211_hw *dev, | 1558 | static int p54_add_interface(struct ieee80211_hw *dev, |
| @@ -1267,14 +1560,20 @@ static int p54_add_interface(struct ieee80211_hw *dev, | |||
| 1267 | { | 1560 | { |
| 1268 | struct p54_common *priv = dev->priv; | 1561 | struct p54_common *priv = dev->priv; |
| 1269 | 1562 | ||
| 1270 | if (priv->mode != NL80211_IFTYPE_MONITOR) | 1563 | mutex_lock(&priv->conf_mutex); |
| 1564 | if (priv->mode != NL80211_IFTYPE_MONITOR) { | ||
| 1565 | mutex_unlock(&priv->conf_mutex); | ||
| 1271 | return -EOPNOTSUPP; | 1566 | return -EOPNOTSUPP; |
| 1567 | } | ||
| 1272 | 1568 | ||
| 1273 | switch (conf->type) { | 1569 | switch (conf->type) { |
| 1274 | case NL80211_IFTYPE_STATION: | 1570 | case NL80211_IFTYPE_STATION: |
| 1571 | case NL80211_IFTYPE_ADHOC: | ||
| 1572 | case NL80211_IFTYPE_AP: | ||
| 1275 | priv->mode = conf->type; | 1573 | priv->mode = conf->type; |
| 1276 | break; | 1574 | break; |
| 1277 | default: | 1575 | default: |
| 1576 | mutex_unlock(&priv->conf_mutex); | ||
| 1278 | return -EOPNOTSUPP; | 1577 | return -EOPNOTSUPP; |
| 1279 | } | 1578 | } |
| 1280 | 1579 | ||
| @@ -1286,6 +1585,12 @@ static int p54_add_interface(struct ieee80211_hw *dev, | |||
| 1286 | case NL80211_IFTYPE_STATION: | 1585 | case NL80211_IFTYPE_STATION: |
| 1287 | p54_setup_mac(dev, P54_FILTER_TYPE_STATION, NULL); | 1586 | p54_setup_mac(dev, P54_FILTER_TYPE_STATION, NULL); |
| 1288 | break; | 1587 | break; |
| 1588 | case NL80211_IFTYPE_AP: | ||
| 1589 | p54_setup_mac(dev, P54_FILTER_TYPE_AP, priv->mac_addr); | ||
| 1590 | break; | ||
| 1591 | case NL80211_IFTYPE_ADHOC: | ||
| 1592 | p54_setup_mac(dev, P54_FILTER_TYPE_IBSS, NULL); | ||
| 1593 | break; | ||
| 1289 | default: | 1594 | default: |
| 1290 | BUG(); /* impossible */ | 1595 | BUG(); /* impossible */ |
| 1291 | break; | 1596 | break; |
| @@ -1293,6 +1598,7 @@ static int p54_add_interface(struct ieee80211_hw *dev, | |||
| 1293 | 1598 | ||
| 1294 | p54_set_leds(dev, 1, 0, 0); | 1599 | p54_set_leds(dev, 1, 0, 0); |
| 1295 | 1600 | ||
| 1601 | mutex_unlock(&priv->conf_mutex); | ||
| 1296 | return 0; | 1602 | return 0; |
| 1297 | } | 1603 | } |
| 1298 | 1604 | ||
| @@ -1300,9 +1606,14 @@ static void p54_remove_interface(struct ieee80211_hw *dev, | |||
| 1300 | struct ieee80211_if_init_conf *conf) | 1606 | struct ieee80211_if_init_conf *conf) |
| 1301 | { | 1607 | { |
| 1302 | struct p54_common *priv = dev->priv; | 1608 | struct p54_common *priv = dev->priv; |
| 1609 | |||
| 1610 | mutex_lock(&priv->conf_mutex); | ||
| 1611 | if (priv->cached_beacon) | ||
| 1612 | p54_tx_cancel(dev, priv->cached_beacon); | ||
| 1613 | p54_setup_mac(dev, P54_FILTER_TYPE_NONE, NULL); | ||
| 1303 | priv->mode = NL80211_IFTYPE_MONITOR; | 1614 | priv->mode = NL80211_IFTYPE_MONITOR; |
| 1304 | memset(priv->mac_addr, 0, ETH_ALEN); | 1615 | memset(priv->mac_addr, 0, ETH_ALEN); |
| 1305 | p54_setup_mac(dev, P54_FILTER_TYPE_NONE, NULL); | 1616 | mutex_unlock(&priv->conf_mutex); |
| 1306 | } | 1617 | } |
| 1307 | 1618 | ||
| 1308 | static int p54_config(struct ieee80211_hw *dev, u32 changed) | 1619 | static int p54_config(struct ieee80211_hw *dev, u32 changed) |
| @@ -1314,7 +1625,7 @@ static int p54_config(struct ieee80211_hw *dev, u32 changed) | |||
| 1314 | mutex_lock(&priv->conf_mutex); | 1625 | mutex_lock(&priv->conf_mutex); |
| 1315 | priv->rx_antenna = 2; /* automatic */ | 1626 | priv->rx_antenna = 2; /* automatic */ |
| 1316 | priv->output_power = conf->power_level << 2; | 1627 | priv->output_power = conf->power_level << 2; |
| 1317 | ret = p54_set_freq(dev, cpu_to_le16(conf->channel->center_freq)); | 1628 | ret = p54_set_freq(dev, conf->channel->center_freq); |
| 1318 | if (!ret) | 1629 | if (!ret) |
| 1319 | ret = p54_set_edcf(dev); | 1630 | ret = p54_set_edcf(dev); |
| 1320 | mutex_unlock(&priv->conf_mutex); | 1631 | mutex_unlock(&priv->conf_mutex); |
| @@ -1326,13 +1637,41 @@ static int p54_config_interface(struct ieee80211_hw *dev, | |||
| 1326 | struct ieee80211_if_conf *conf) | 1637 | struct ieee80211_if_conf *conf) |
| 1327 | { | 1638 | { |
| 1328 | struct p54_common *priv = dev->priv; | 1639 | struct p54_common *priv = dev->priv; |
| 1640 | int ret = 0; | ||
| 1329 | 1641 | ||
| 1330 | mutex_lock(&priv->conf_mutex); | 1642 | mutex_lock(&priv->conf_mutex); |
| 1331 | p54_setup_mac(dev, P54_FILTER_TYPE_STATION, conf->bssid); | 1643 | switch (priv->mode) { |
| 1332 | p54_set_leds(dev, 1, !is_multicast_ether_addr(conf->bssid), 0); | 1644 | case NL80211_IFTYPE_STATION: |
| 1333 | memcpy(priv->bssid, conf->bssid, ETH_ALEN); | 1645 | ret = p54_setup_mac(dev, P54_FILTER_TYPE_STATION, conf->bssid); |
| 1646 | if (ret) | ||
| 1647 | goto out; | ||
| 1648 | ret = p54_set_leds(dev, 1, | ||
| 1649 | !is_multicast_ether_addr(conf->bssid), 0); | ||
| 1650 | if (ret) | ||
| 1651 | goto out; | ||
| 1652 | memcpy(priv->bssid, conf->bssid, ETH_ALEN); | ||
| 1653 | break; | ||
| 1654 | case NL80211_IFTYPE_AP: | ||
| 1655 | case NL80211_IFTYPE_ADHOC: | ||
| 1656 | memcpy(priv->bssid, conf->bssid, ETH_ALEN); | ||
| 1657 | ret = p54_set_freq(dev, dev->conf.channel->center_freq); | ||
| 1658 | if (ret) | ||
| 1659 | goto out; | ||
| 1660 | ret = p54_setup_mac(dev, priv->mac_mode, priv->bssid); | ||
| 1661 | if (ret) | ||
| 1662 | goto out; | ||
| 1663 | if (conf->changed & IEEE80211_IFCC_BEACON) { | ||
| 1664 | ret = p54_beacon_update(dev, vif); | ||
| 1665 | if (ret) | ||
| 1666 | goto out; | ||
| 1667 | ret = p54_set_edcf(dev); | ||
| 1668 | if (ret) | ||
| 1669 | goto out; | ||
| 1670 | } | ||
| 1671 | } | ||
| 1672 | out: | ||
| 1334 | mutex_unlock(&priv->conf_mutex); | 1673 | mutex_unlock(&priv->conf_mutex); |
| 1335 | return 0; | 1674 | return ret; |
| 1336 | } | 1675 | } |
| 1337 | 1676 | ||
| 1338 | static void p54_configure_filter(struct ieee80211_hw *dev, | 1677 | static void p54_configure_filter(struct ieee80211_hw *dev, |
| @@ -1367,14 +1706,18 @@ static int p54_conf_tx(struct ieee80211_hw *dev, u16 queue, | |||
| 1367 | const struct ieee80211_tx_queue_params *params) | 1706 | const struct ieee80211_tx_queue_params *params) |
| 1368 | { | 1707 | { |
| 1369 | struct p54_common *priv = dev->priv; | 1708 | struct p54_common *priv = dev->priv; |
| 1709 | int ret; | ||
| 1370 | 1710 | ||
| 1711 | mutex_lock(&priv->conf_mutex); | ||
| 1371 | if ((params) && !(queue > 4)) { | 1712 | if ((params) && !(queue > 4)) { |
| 1372 | P54_SET_QUEUE(priv->qos_params[queue], params->aifs, | 1713 | P54_SET_QUEUE(priv->qos_params[queue], params->aifs, |
| 1373 | params->cw_min, params->cw_max, params->txop); | 1714 | params->cw_min, params->cw_max, params->txop); |
| 1374 | } else | 1715 | } else |
| 1375 | return -EINVAL; | 1716 | ret = -EINVAL; |
| 1376 | 1717 | if (!ret) | |
| 1377 | return p54_set_edcf(dev); | 1718 | ret = p54_set_edcf(dev); |
| 1719 | mutex_unlock(&priv->conf_mutex); | ||
| 1720 | return ret; | ||
| 1378 | } | 1721 | } |
| 1379 | 1722 | ||
| 1380 | static int p54_init_xbow_synth(struct ieee80211_hw *dev) | 1723 | static int p54_init_xbow_synth(struct ieee80211_hw *dev) |
| @@ -1457,6 +1800,7 @@ static const struct ieee80211_ops p54_ops = { | |||
| 1457 | .stop = p54_stop, | 1800 | .stop = p54_stop, |
| 1458 | .add_interface = p54_add_interface, | 1801 | .add_interface = p54_add_interface, |
| 1459 | .remove_interface = p54_remove_interface, | 1802 | .remove_interface = p54_remove_interface, |
| 1803 | .set_tim = p54_set_tim, | ||
| 1460 | .config = p54_config, | 1804 | .config = p54_config, |
| 1461 | .config_interface = p54_config_interface, | 1805 | .config_interface = p54_config_interface, |
| 1462 | .bss_info_changed = p54_bss_info_changed, | 1806 | .bss_info_changed = p54_bss_info_changed, |
| @@ -1478,24 +1822,20 @@ struct ieee80211_hw *p54_init_common(size_t priv_data_len) | |||
| 1478 | priv = dev->priv; | 1822 | priv = dev->priv; |
| 1479 | priv->mode = NL80211_IFTYPE_UNSPECIFIED; | 1823 | priv->mode = NL80211_IFTYPE_UNSPECIFIED; |
| 1480 | skb_queue_head_init(&priv->tx_queue); | 1824 | skb_queue_head_init(&priv->tx_queue); |
| 1481 | dev->flags = IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | /* not sure */ | 1825 | dev->flags = IEEE80211_HW_RX_INCLUDES_FCS | |
| 1482 | IEEE80211_HW_RX_INCLUDES_FCS | | ||
| 1483 | IEEE80211_HW_SIGNAL_DBM | | 1826 | IEEE80211_HW_SIGNAL_DBM | |
| 1484 | IEEE80211_HW_NOISE_DBM; | 1827 | IEEE80211_HW_NOISE_DBM; |
| 1485 | 1828 | ||
| 1486 | /* | 1829 | dev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION | |
| 1487 | * XXX: when this driver gets support for any mode that | 1830 | NL80211_IFTYPE_ADHOC | |
| 1488 | * requires beacons (AP, MESH, IBSS) then it must | 1831 | NL80211_IFTYPE_AP); |
| 1489 | * implement IEEE80211_TX_CTL_ASSIGN_SEQ. | ||
| 1490 | */ | ||
| 1491 | dev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION); | ||
| 1492 | 1832 | ||
| 1493 | dev->channel_change_time = 1000; /* TODO: find actual value */ | 1833 | dev->channel_change_time = 1000; /* TODO: find actual value */ |
| 1494 | priv->tx_stats[0].limit = 1; | 1834 | priv->tx_stats[0].limit = 1; /* Beacon queue */ |
| 1495 | priv->tx_stats[1].limit = 1; | 1835 | priv->tx_stats[1].limit = 1; /* Probe queue for HW scan */ |
| 1496 | priv->tx_stats[2].limit = 1; | 1836 | priv->tx_stats[2].limit = 3; /* queue for MLMEs */ |
| 1497 | priv->tx_stats[3].limit = 1; | 1837 | priv->tx_stats[3].limit = 3; /* Broadcast / MC queue */ |
| 1498 | priv->tx_stats[4].limit = 5; | 1838 | priv->tx_stats[4].limit = 5; /* Data */ |
| 1499 | dev->queues = 1; | 1839 | dev->queues = 1; |
| 1500 | priv->noise = -94; | 1840 | priv->noise = -94; |
| 1501 | /* | 1841 | /* |
