0001
0002
0003
0004
0005
0006 #include <linux/netdevice.h>
0007 #include <linux/etherdevice.h>
0008 #include <linux/slab.h>
0009 #include <linux/usb.h>
0010 #include <linux/gpio.h>
0011 #include <linux/jiffies.h>
0012 #include <net/ieee80211_radiotap.h>
0013
0014 #include "chip.h"
0015 #include "mac.h"
0016 #include "usb.h"
0017
0018 static const struct ieee80211_rate plfxlc_rates[] = {
0019 { .bitrate = 10,
0020 .hw_value = PURELIFI_CCK_RATE_1M,
0021 .flags = 0 },
0022 { .bitrate = 20,
0023 .hw_value = PURELIFI_CCK_RATE_2M,
0024 .hw_value_short = PURELIFI_CCK_RATE_2M
0025 | PURELIFI_CCK_PREA_SHORT,
0026 .flags = IEEE80211_RATE_SHORT_PREAMBLE },
0027 { .bitrate = 55,
0028 .hw_value = PURELIFI_CCK_RATE_5_5M,
0029 .hw_value_short = PURELIFI_CCK_RATE_5_5M
0030 | PURELIFI_CCK_PREA_SHORT,
0031 .flags = IEEE80211_RATE_SHORT_PREAMBLE },
0032 { .bitrate = 110,
0033 .hw_value = PURELIFI_CCK_RATE_11M,
0034 .hw_value_short = PURELIFI_CCK_RATE_11M
0035 | PURELIFI_CCK_PREA_SHORT,
0036 .flags = IEEE80211_RATE_SHORT_PREAMBLE },
0037 { .bitrate = 60,
0038 .hw_value = PURELIFI_OFDM_RATE_6M,
0039 .flags = 0 },
0040 { .bitrate = 90,
0041 .hw_value = PURELIFI_OFDM_RATE_9M,
0042 .flags = 0 },
0043 { .bitrate = 120,
0044 .hw_value = PURELIFI_OFDM_RATE_12M,
0045 .flags = 0 },
0046 { .bitrate = 180,
0047 .hw_value = PURELIFI_OFDM_RATE_18M,
0048 .flags = 0 },
0049 { .bitrate = 240,
0050 .hw_value = PURELIFI_OFDM_RATE_24M,
0051 .flags = 0 },
0052 { .bitrate = 360,
0053 .hw_value = PURELIFI_OFDM_RATE_36M,
0054 .flags = 0 },
0055 { .bitrate = 480,
0056 .hw_value = PURELIFI_OFDM_RATE_48M,
0057 .flags = 0 },
0058 { .bitrate = 540,
0059 .hw_value = PURELIFI_OFDM_RATE_54M,
0060 .flags = 0 }
0061 };
0062
0063 static const struct ieee80211_channel plfxlc_channels[] = {
0064 { .center_freq = 2412, .hw_value = 1 },
0065 { .center_freq = 2417, .hw_value = 2 },
0066 { .center_freq = 2422, .hw_value = 3 },
0067 { .center_freq = 2427, .hw_value = 4 },
0068 { .center_freq = 2432, .hw_value = 5 },
0069 { .center_freq = 2437, .hw_value = 6 },
0070 { .center_freq = 2442, .hw_value = 7 },
0071 { .center_freq = 2447, .hw_value = 8 },
0072 { .center_freq = 2452, .hw_value = 9 },
0073 { .center_freq = 2457, .hw_value = 10 },
0074 { .center_freq = 2462, .hw_value = 11 },
0075 { .center_freq = 2467, .hw_value = 12 },
0076 { .center_freq = 2472, .hw_value = 13 },
0077 { .center_freq = 2484, .hw_value = 14 },
0078 };
0079
0080 int plfxlc_mac_preinit_hw(struct ieee80211_hw *hw, const u8 *hw_address)
0081 {
0082 SET_IEEE80211_PERM_ADDR(hw, hw_address);
0083 return 0;
0084 }
0085
0086 int plfxlc_mac_init_hw(struct ieee80211_hw *hw)
0087 {
0088 struct plfxlc_mac *mac = plfxlc_hw_mac(hw);
0089 struct plfxlc_chip *chip = &mac->chip;
0090 int r;
0091
0092 r = plfxlc_chip_init_hw(chip);
0093 if (r) {
0094 dev_warn(plfxlc_mac_dev(mac), "init hw failed (%d)\n", r);
0095 return r;
0096 }
0097
0098 dev_dbg(plfxlc_mac_dev(mac), "irq_disabled (%d)\n", irqs_disabled());
0099 regulatory_hint(hw->wiphy, "00");
0100 return r;
0101 }
0102
0103 void plfxlc_mac_release(struct plfxlc_mac *mac)
0104 {
0105 plfxlc_chip_release(&mac->chip);
0106 lockdep_assert_held(&mac->lock);
0107 }
0108
0109 int plfxlc_op_start(struct ieee80211_hw *hw)
0110 {
0111 plfxlc_hw_mac(hw)->chip.usb.initialized = 1;
0112 return 0;
0113 }
0114
0115 void plfxlc_op_stop(struct ieee80211_hw *hw)
0116 {
0117 struct plfxlc_mac *mac = plfxlc_hw_mac(hw);
0118
0119 clear_bit(PURELIFI_DEVICE_RUNNING, &mac->flags);
0120 }
0121
0122 int plfxlc_restore_settings(struct plfxlc_mac *mac)
0123 {
0124 int beacon_interval, beacon_period;
0125 struct sk_buff *beacon;
0126
0127 spin_lock_irq(&mac->lock);
0128 beacon_interval = mac->beacon.interval;
0129 beacon_period = mac->beacon.period;
0130 spin_unlock_irq(&mac->lock);
0131
0132 if (mac->type != NL80211_IFTYPE_ADHOC)
0133 return 0;
0134
0135 if (mac->vif) {
0136 beacon = ieee80211_beacon_get(mac->hw, mac->vif, 0);
0137 if (beacon) {
0138
0139 kfree_skb(beacon);
0140
0141
0142
0143 }
0144 }
0145
0146 plfxlc_set_beacon_interval(&mac->chip, beacon_interval,
0147 beacon_period, mac->type);
0148
0149 spin_lock_irq(&mac->lock);
0150 mac->beacon.last_update = jiffies;
0151 spin_unlock_irq(&mac->lock);
0152
0153 return 0;
0154 }
0155
0156 static void plfxlc_mac_tx_status(struct ieee80211_hw *hw,
0157 struct sk_buff *skb,
0158 int ackssi,
0159 struct tx_status *tx_status)
0160 {
0161 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
0162 int success = 1;
0163
0164 ieee80211_tx_info_clear_status(info);
0165 if (tx_status)
0166 success = !tx_status->failure;
0167
0168 if (success)
0169 info->flags |= IEEE80211_TX_STAT_ACK;
0170 else
0171 info->flags &= ~IEEE80211_TX_STAT_ACK;
0172
0173 info->status.ack_signal = 50;
0174 ieee80211_tx_status_irqsafe(hw, skb);
0175 }
0176
0177 void plfxlc_mac_tx_to_dev(struct sk_buff *skb, int error)
0178 {
0179 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
0180 struct ieee80211_hw *hw = info->rate_driver_data[0];
0181 struct plfxlc_mac *mac = plfxlc_hw_mac(hw);
0182 struct sk_buff_head *q = NULL;
0183
0184 ieee80211_tx_info_clear_status(info);
0185 skb_pull(skb, sizeof(struct plfxlc_ctrlset));
0186
0187 if (unlikely(error ||
0188 (info->flags & IEEE80211_TX_CTL_NO_ACK))) {
0189 ieee80211_tx_status_irqsafe(hw, skb);
0190 return;
0191 }
0192
0193 q = &mac->ack_wait_queue;
0194
0195 skb_queue_tail(q, skb);
0196 while (skb_queue_len(q)) {
0197 plfxlc_mac_tx_status(hw, skb_dequeue(q),
0198 mac->ack_pending ?
0199 mac->ack_signal : 0,
0200 NULL);
0201 mac->ack_pending = 0;
0202 }
0203 }
0204
0205 static int plfxlc_fill_ctrlset(struct plfxlc_mac *mac, struct sk_buff *skb)
0206 {
0207 unsigned int frag_len = skb->len;
0208 struct plfxlc_ctrlset *cs;
0209 u32 temp_payload_len = 0;
0210 unsigned int tmp;
0211 u32 temp_len = 0;
0212
0213 if (skb_headroom(skb) < sizeof(struct plfxlc_ctrlset)) {
0214 dev_dbg(plfxlc_mac_dev(mac), "Not enough hroom(1)\n");
0215 return 1;
0216 }
0217
0218 cs = (void *)skb_push(skb, sizeof(struct plfxlc_ctrlset));
0219 temp_payload_len = frag_len;
0220 temp_len = temp_payload_len +
0221 sizeof(struct plfxlc_ctrlset) -
0222 sizeof(cs->id) - sizeof(cs->len);
0223
0224
0225
0226
0227
0228
0229
0230
0231
0232
0233
0234
0235 tmp = skb->len & 3;
0236 if (tmp) {
0237 if (skb_tailroom(skb) < (3 - tmp)) {
0238 if (skb_headroom(skb) >= 4 - tmp) {
0239 u8 len;
0240 u8 *src_pt;
0241 u8 *dest_pt;
0242
0243 len = skb->len;
0244 src_pt = skb->data;
0245 dest_pt = skb_push(skb, 4 - tmp);
0246 memmove(dest_pt, src_pt, len);
0247 } else {
0248 return -ENOBUFS;
0249 }
0250 } else {
0251 skb_put(skb, 4 - tmp);
0252 }
0253 temp_len += 4 - tmp;
0254 }
0255
0256
0257 tmp = skb->len & 0x1ff;
0258 if (!tmp) {
0259 if (skb_tailroom(skb) < 4) {
0260 if (skb_headroom(skb) >= 4) {
0261 u8 len = skb->len;
0262 u8 *src_pt = skb->data;
0263 u8 *dest_pt = skb_push(skb, 4);
0264
0265 memmove(dest_pt, src_pt, len);
0266 } else {
0267
0268
0269
0270 return -ENOBUFS;
0271 }
0272 } else {
0273 skb_put(skb, 4);
0274 }
0275 temp_len += 4;
0276 }
0277
0278 cs->id = cpu_to_be32(USB_REQ_DATA_TX);
0279 cs->len = cpu_to_be32(temp_len);
0280 cs->payload_len_nw = cpu_to_be32(temp_payload_len);
0281
0282 return 0;
0283 }
0284
0285 static void plfxlc_op_tx(struct ieee80211_hw *hw,
0286 struct ieee80211_tx_control *control,
0287 struct sk_buff *skb)
0288 {
0289 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
0290 struct plfxlc_header *plhdr = (void *)skb->data;
0291 struct plfxlc_mac *mac = plfxlc_hw_mac(hw);
0292 struct plfxlc_usb *usb = &mac->chip.usb;
0293 unsigned long flags;
0294 int r;
0295
0296 r = plfxlc_fill_ctrlset(mac, skb);
0297 if (r)
0298 goto fail;
0299
0300 info->rate_driver_data[0] = hw;
0301
0302 if (plhdr->frametype == IEEE80211_FTYPE_DATA) {
0303 u8 *dst_mac = plhdr->dmac;
0304 u8 sidx;
0305 bool found = false;
0306 struct plfxlc_usb_tx *tx = &usb->tx;
0307
0308 for (sidx = 0; sidx < MAX_STA_NUM; sidx++) {
0309 if (!(tx->station[sidx].flag & STATION_CONNECTED_FLAG))
0310 continue;
0311 if (memcmp(tx->station[sidx].mac, dst_mac, ETH_ALEN))
0312 continue;
0313 found = true;
0314 break;
0315 }
0316
0317
0318 if (!found)
0319 sidx = STA_BROADCAST_INDEX;
0320
0321
0322 if (skb_queue_len(&tx->station[sidx].data_list) > 60)
0323 ieee80211_stop_queues(plfxlc_usb_to_hw(usb));
0324
0325
0326 if (skb_queue_len(&tx->station[sidx].data_list) > 256)
0327 goto fail;
0328 skb_queue_tail(&tx->station[sidx].data_list, skb);
0329 plfxlc_send_packet_from_data_queue(usb);
0330
0331 } else {
0332 spin_lock_irqsave(&usb->tx.lock, flags);
0333 r = plfxlc_usb_wreq_async(&mac->chip.usb, skb->data, skb->len,
0334 USB_REQ_DATA_TX, plfxlc_tx_urb_complete, skb);
0335 spin_unlock_irqrestore(&usb->tx.lock, flags);
0336 if (r)
0337 goto fail;
0338 }
0339 return;
0340
0341 fail:
0342 dev_kfree_skb(skb);
0343 }
0344
0345 static int plfxlc_filter_ack(struct ieee80211_hw *hw, struct ieee80211_hdr *rx_hdr,
0346 struct ieee80211_rx_status *stats)
0347 {
0348 struct plfxlc_mac *mac = plfxlc_hw_mac(hw);
0349 struct sk_buff_head *q;
0350 int i, position = 0;
0351 unsigned long flags;
0352 struct sk_buff *skb;
0353 bool found = false;
0354
0355 if (!ieee80211_is_ack(rx_hdr->frame_control))
0356 return 0;
0357
0358 dev_dbg(plfxlc_mac_dev(mac), "ACK Received\n");
0359
0360
0361 q = &mac->ack_wait_queue;
0362 spin_lock_irqsave(&q->lock, flags);
0363
0364 skb_queue_walk(q, skb) {
0365 struct ieee80211_hdr *tx_hdr;
0366
0367 position++;
0368
0369 if (mac->ack_pending && skb_queue_is_first(q, skb))
0370 continue;
0371 if (mac->ack_pending == 0)
0372 break;
0373
0374 tx_hdr = (struct ieee80211_hdr *)skb->data;
0375 if (likely(ether_addr_equal(tx_hdr->addr2, rx_hdr->addr1))) {
0376 found = 1;
0377 break;
0378 }
0379 }
0380
0381 if (found) {
0382 for (i = 1; i < position; i++)
0383 skb = __skb_dequeue(q);
0384 if (i == position) {
0385 plfxlc_mac_tx_status(hw, skb,
0386 mac->ack_pending ?
0387 mac->ack_signal : 0,
0388 NULL);
0389 mac->ack_pending = 0;
0390 }
0391
0392 mac->ack_pending = skb_queue_len(q) ? 1 : 0;
0393 mac->ack_signal = stats->signal;
0394 }
0395
0396 spin_unlock_irqrestore(&q->lock, flags);
0397 return 1;
0398 }
0399
0400 int plfxlc_mac_rx(struct ieee80211_hw *hw, const u8 *buffer,
0401 unsigned int length)
0402 {
0403 struct plfxlc_mac *mac = plfxlc_hw_mac(hw);
0404 struct ieee80211_rx_status stats;
0405 const struct rx_status *status;
0406 unsigned int payload_length;
0407 struct plfxlc_usb_tx *tx;
0408 struct sk_buff *skb;
0409 int need_padding;
0410 __le16 fc;
0411 int sidx;
0412
0413
0414 if (!mac->vif)
0415 return 0;
0416
0417 status = (struct rx_status *)buffer;
0418
0419 memset(&stats, 0, sizeof(stats));
0420
0421 stats.flag = 0;
0422 stats.freq = 2412;
0423 stats.band = NL80211_BAND_LC;
0424 mac->rssi = -15 * be16_to_cpu(status->rssi) / 10;
0425
0426 stats.signal = mac->rssi;
0427
0428 if (status->rate_idx > 7)
0429 stats.rate_idx = 0;
0430 else
0431 stats.rate_idx = status->rate_idx;
0432
0433 mac->crc_errors = be64_to_cpu(status->crc_error_count);
0434
0435
0436 if (plfxlc_filter_ack(hw, (struct ieee80211_hdr *)buffer, &stats) &&
0437 !mac->pass_ctrl)
0438 return 0;
0439
0440 buffer += sizeof(struct rx_status);
0441 payload_length = get_unaligned_be32(buffer);
0442
0443 if (payload_length > 1560) {
0444 dev_err(plfxlc_mac_dev(mac), " > MTU %u\n", payload_length);
0445 return 0;
0446 }
0447 buffer += sizeof(u32);
0448
0449 fc = get_unaligned((__le16 *)buffer);
0450 need_padding = ieee80211_is_data_qos(fc) ^ ieee80211_has_a4(fc);
0451
0452 tx = &mac->chip.usb.tx;
0453
0454 for (sidx = 0; sidx < MAX_STA_NUM - 1; sidx++) {
0455 if (memcmp(&buffer[10], tx->station[sidx].mac, ETH_ALEN))
0456 continue;
0457 if (tx->station[sidx].flag & STATION_CONNECTED_FLAG) {
0458 tx->station[sidx].flag |= STATION_HEARTBEAT_FLAG;
0459 break;
0460 }
0461 }
0462
0463 if (sidx == MAX_STA_NUM - 1) {
0464 for (sidx = 0; sidx < MAX_STA_NUM - 1; sidx++) {
0465 if (tx->station[sidx].flag & STATION_CONNECTED_FLAG)
0466 continue;
0467 memcpy(tx->station[sidx].mac, &buffer[10], ETH_ALEN);
0468 tx->station[sidx].flag |= STATION_CONNECTED_FLAG;
0469 tx->station[sidx].flag |= STATION_HEARTBEAT_FLAG;
0470 break;
0471 }
0472 }
0473
0474 switch (buffer[0]) {
0475 case IEEE80211_STYPE_PROBE_REQ:
0476 dev_dbg(plfxlc_mac_dev(mac), "Probe request\n");
0477 break;
0478 case IEEE80211_STYPE_ASSOC_REQ:
0479 dev_dbg(plfxlc_mac_dev(mac), "Association request\n");
0480 break;
0481 case IEEE80211_STYPE_AUTH:
0482 dev_dbg(plfxlc_mac_dev(mac), "Authentication req\n");
0483 break;
0484 case IEEE80211_FTYPE_DATA:
0485 dev_dbg(plfxlc_mac_dev(mac), "802.11 data frame\n");
0486 break;
0487 }
0488
0489 skb = dev_alloc_skb(payload_length + (need_padding ? 2 : 0));
0490 if (!skb)
0491 return -ENOMEM;
0492
0493 if (need_padding)
0494
0495 skb_reserve(skb, 2);
0496
0497 skb_put_data(skb, buffer, payload_length);
0498 memcpy(IEEE80211_SKB_RXCB(skb), &stats, sizeof(stats));
0499 ieee80211_rx_irqsafe(hw, skb);
0500 return 0;
0501 }
0502
0503 static int plfxlc_op_add_interface(struct ieee80211_hw *hw,
0504 struct ieee80211_vif *vif)
0505 {
0506 struct plfxlc_mac *mac = plfxlc_hw_mac(hw);
0507 static const char * const iftype80211[] = {
0508 [NL80211_IFTYPE_STATION] = "Station",
0509 [NL80211_IFTYPE_ADHOC] = "Adhoc"
0510 };
0511
0512 if (mac->type != NL80211_IFTYPE_UNSPECIFIED)
0513 return -EOPNOTSUPP;
0514
0515 if (vif->type == NL80211_IFTYPE_ADHOC ||
0516 vif->type == NL80211_IFTYPE_STATION) {
0517 dev_dbg(plfxlc_mac_dev(mac), "%s %s\n", __func__,
0518 iftype80211[vif->type]);
0519 mac->type = vif->type;
0520 mac->vif = vif;
0521 return 0;
0522 }
0523 dev_dbg(plfxlc_mac_dev(mac), "unsupported iftype\n");
0524 return -EOPNOTSUPP;
0525 }
0526
0527 static void plfxlc_op_remove_interface(struct ieee80211_hw *hw,
0528 struct ieee80211_vif *vif)
0529 {
0530 struct plfxlc_mac *mac = plfxlc_hw_mac(hw);
0531
0532 mac->type = NL80211_IFTYPE_UNSPECIFIED;
0533 mac->vif = NULL;
0534 }
0535
0536 static int plfxlc_op_config(struct ieee80211_hw *hw, u32 changed)
0537 {
0538 return 0;
0539 }
0540
0541 #define SUPPORTED_FIF_FLAGS \
0542 (FIF_ALLMULTI | FIF_FCSFAIL | FIF_CONTROL | \
0543 FIF_OTHER_BSS | FIF_BCN_PRBRESP_PROMISC)
0544 static void plfxlc_op_configure_filter(struct ieee80211_hw *hw,
0545 unsigned int changed_flags,
0546 unsigned int *new_flags,
0547 u64 multicast)
0548 {
0549 struct plfxlc_mc_hash hash = {
0550 .low = multicast,
0551 .high = multicast >> 32,
0552 };
0553 struct plfxlc_mac *mac = plfxlc_hw_mac(hw);
0554 unsigned long flags;
0555
0556
0557 *new_flags &= SUPPORTED_FIF_FLAGS;
0558
0559
0560
0561
0562
0563
0564
0565
0566 if (*new_flags & (FIF_ALLMULTI))
0567 plfxlc_mc_add_all(&hash);
0568
0569 spin_lock_irqsave(&mac->lock, flags);
0570 mac->pass_failed_fcs = !!(*new_flags & FIF_FCSFAIL);
0571 mac->pass_ctrl = !!(*new_flags & FIF_CONTROL);
0572 mac->multicast_hash = hash;
0573 spin_unlock_irqrestore(&mac->lock, flags);
0574
0575
0576
0577
0578
0579
0580
0581
0582
0583
0584
0585 }
0586
0587 static void plfxlc_op_bss_info_changed(struct ieee80211_hw *hw,
0588 struct ieee80211_vif *vif,
0589 struct ieee80211_bss_conf *bss_conf,
0590 u64 changes)
0591 {
0592 struct plfxlc_mac *mac = plfxlc_hw_mac(hw);
0593 int associated;
0594
0595 dev_dbg(plfxlc_mac_dev(mac), "changes: %llx\n", changes);
0596
0597 if (mac->type != NL80211_IFTYPE_ADHOC) {
0598 associated = is_valid_ether_addr(bss_conf->bssid);
0599 goto exit_all;
0600 }
0601
0602 associated = true;
0603 if (changes & BSS_CHANGED_BEACON) {
0604 struct sk_buff *beacon = ieee80211_beacon_get(hw, vif, 0);
0605
0606 if (beacon) {
0607
0608 kfree_skb(beacon);
0609
0610
0611
0612
0613 }
0614 }
0615
0616 if (changes & BSS_CHANGED_BEACON_ENABLED) {
0617 u16 interval = 0;
0618 u8 period = 0;
0619
0620 if (bss_conf->enable_beacon) {
0621 period = bss_conf->dtim_period;
0622 interval = bss_conf->beacon_int;
0623 }
0624
0625 spin_lock_irq(&mac->lock);
0626 mac->beacon.period = period;
0627 mac->beacon.interval = interval;
0628 mac->beacon.last_update = jiffies;
0629 spin_unlock_irq(&mac->lock);
0630
0631 plfxlc_set_beacon_interval(&mac->chip, interval,
0632 period, mac->type);
0633 }
0634 exit_all:
0635 spin_lock_irq(&mac->lock);
0636 mac->associated = associated;
0637 spin_unlock_irq(&mac->lock);
0638 }
0639
0640 static int plfxlc_get_stats(struct ieee80211_hw *hw,
0641 struct ieee80211_low_level_stats *stats)
0642 {
0643 stats->dot11ACKFailureCount = 0;
0644 stats->dot11RTSFailureCount = 0;
0645 stats->dot11FCSErrorCount = 0;
0646 stats->dot11RTSSuccessCount = 0;
0647 return 0;
0648 }
0649
0650 static const char et_strings[][ETH_GSTRING_LEN] = {
0651 "phy_rssi",
0652 "phy_rx_crc_err"
0653 };
0654
0655 static int plfxlc_get_et_sset_count(struct ieee80211_hw *hw,
0656 struct ieee80211_vif *vif, int sset)
0657 {
0658 if (sset == ETH_SS_STATS)
0659 return ARRAY_SIZE(et_strings);
0660
0661 return 0;
0662 }
0663
0664 static void plfxlc_get_et_strings(struct ieee80211_hw *hw,
0665 struct ieee80211_vif *vif,
0666 u32 sset, u8 *data)
0667 {
0668 if (sset == ETH_SS_STATS)
0669 memcpy(data, *et_strings, sizeof(et_strings));
0670 }
0671
0672 static void plfxlc_get_et_stats(struct ieee80211_hw *hw,
0673 struct ieee80211_vif *vif,
0674 struct ethtool_stats *stats, u64 *data)
0675 {
0676 struct plfxlc_mac *mac = plfxlc_hw_mac(hw);
0677
0678 data[0] = mac->rssi;
0679 data[1] = mac->crc_errors;
0680 }
0681
0682 static int plfxlc_set_rts_threshold(struct ieee80211_hw *hw, u32 value)
0683 {
0684 return 0;
0685 }
0686
0687 static const struct ieee80211_ops plfxlc_ops = {
0688 .tx = plfxlc_op_tx,
0689 .start = plfxlc_op_start,
0690 .stop = plfxlc_op_stop,
0691 .add_interface = plfxlc_op_add_interface,
0692 .remove_interface = plfxlc_op_remove_interface,
0693 .set_rts_threshold = plfxlc_set_rts_threshold,
0694 .config = plfxlc_op_config,
0695 .configure_filter = plfxlc_op_configure_filter,
0696 .bss_info_changed = plfxlc_op_bss_info_changed,
0697 .get_stats = plfxlc_get_stats,
0698 .get_et_sset_count = plfxlc_get_et_sset_count,
0699 .get_et_stats = plfxlc_get_et_stats,
0700 .get_et_strings = plfxlc_get_et_strings,
0701 };
0702
0703 struct ieee80211_hw *plfxlc_mac_alloc_hw(struct usb_interface *intf)
0704 {
0705 struct ieee80211_hw *hw;
0706 struct plfxlc_mac *mac;
0707
0708 hw = ieee80211_alloc_hw(sizeof(struct plfxlc_mac), &plfxlc_ops);
0709 if (!hw) {
0710 dev_dbg(&intf->dev, "out of memory\n");
0711 return NULL;
0712 }
0713 set_wiphy_dev(hw->wiphy, &intf->dev);
0714
0715 mac = plfxlc_hw_mac(hw);
0716 memset(mac, 0, sizeof(*mac));
0717 spin_lock_init(&mac->lock);
0718 mac->hw = hw;
0719
0720 mac->type = NL80211_IFTYPE_UNSPECIFIED;
0721
0722 memcpy(mac->channels, plfxlc_channels, sizeof(plfxlc_channels));
0723 memcpy(mac->rates, plfxlc_rates, sizeof(plfxlc_rates));
0724 mac->band.n_bitrates = ARRAY_SIZE(plfxlc_rates);
0725 mac->band.bitrates = mac->rates;
0726 mac->band.n_channels = ARRAY_SIZE(plfxlc_channels);
0727 mac->band.channels = mac->channels;
0728 hw->wiphy->bands[NL80211_BAND_LC] = &mac->band;
0729 hw->conf.chandef.width = NL80211_CHAN_WIDTH_20;
0730
0731 ieee80211_hw_set(hw, RX_INCLUDES_FCS);
0732 ieee80211_hw_set(hw, SIGNAL_DBM);
0733 ieee80211_hw_set(hw, HOST_BROADCAST_PS_BUFFERING);
0734 ieee80211_hw_set(hw, MFP_CAPABLE);
0735
0736 hw->wiphy->interface_modes =
0737 BIT(NL80211_IFTYPE_STATION) |
0738 BIT(NL80211_IFTYPE_ADHOC);
0739 hw->max_signal = 100;
0740 hw->queues = 1;
0741
0742 hw->extra_tx_headroom = sizeof(struct plfxlc_ctrlset) + 4;
0743
0744 hw->max_rates = IEEE80211_TX_MAX_RATES;
0745 hw->max_rate_tries = 18;
0746
0747 skb_queue_head_init(&mac->ack_wait_queue);
0748 mac->ack_pending = 0;
0749
0750 plfxlc_chip_init(&mac->chip, hw, intf);
0751
0752 SET_IEEE80211_DEV(hw, &intf->dev);
0753 return hw;
0754 }