aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/p54/p54common.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/p54/p54common.c')
-rw-r--r--drivers/net/wireless/p54/p54common.c452
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
744static 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
709static int p54_rx_control(struct ieee80211_hw *dev, struct sk_buff *skb) 773static 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 */
735int p54_rx(struct ieee80211_hw *dev, struct sk_buff *skb) 802int 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}
898EXPORT_SYMBOL_GPL(p54_read_eeprom); 965EXPORT_SYMBOL_GPL(p54_read_eeprom);
899 966
967static 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
987static 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
1005static 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
1025static 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
900static int p54_tx(struct ieee80211_hw *dev, struct sk_buff *skb) 1074static 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
1072static int p54_set_freq(struct ieee80211_hw *dev, __le16 freq) 1272static 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
1432static 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
1485static 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
1230static int p54_start(struct ieee80211_hw *dev) 1514static 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
1265static int p54_add_interface(struct ieee80211_hw *dev, 1558static 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
1308static int p54_config(struct ieee80211_hw *dev, u32 changed) 1619static 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 }
1672out:
1334 mutex_unlock(&priv->conf_mutex); 1673 mutex_unlock(&priv->conf_mutex);
1335 return 0; 1674 return ret;
1336} 1675}
1337 1676
1338static void p54_configure_filter(struct ieee80211_hw *dev, 1677static 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
1380static int p54_init_xbow_synth(struct ieee80211_hw *dev) 1723static 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 /*