linux/drivers/staging/vt6656/rxtx.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
   4 * All rights reserved.
   5 *
   6 * File: rxtx.c
   7 *
   8 * Purpose: handle WMAC/802.3/802.11 rx & tx functions
   9 *
  10 * Author: Lyndon Chen
  11 *
  12 * Date: May 20, 2003
  13 *
  14 * Functions:
  15 *      vnt_generate_tx_parameter - Generate tx dma required parameter.
  16 *      vnt_get_duration_le - get tx data required duration
  17 *      vnt_get_rtscts_duration_le- get rtx/cts required duration
  18 *      vnt_get_rtscts_rsvtime_le- get rts/cts reserved time
  19 *      vnt_get_rsvtime- get frame reserved time
  20 *      vnt_fill_cts_head- fulfill CTS ctl header
  21 *
  22 * Revision History:
  23 *
  24 */
  25
  26#include <linux/etherdevice.h>
  27#include "device.h"
  28#include "rxtx.h"
  29#include "card.h"
  30#include "mac.h"
  31#include "rf.h"
  32#include "usbpipe.h"
  33
  34static const u16 vnt_time_stampoff[2][MAX_RATE] = {
  35        /* Long Preamble */
  36        {384, 288, 226, 209, 54, 43, 37, 31, 28, 25, 24, 23},
  37
  38        /* Short Preamble */
  39        {384, 192, 130, 113, 54, 43, 37, 31, 28, 25, 24, 23},
  40};
  41
  42static const u16 vnt_fb_opt0[2][5] = {
  43        {RATE_12M, RATE_18M, RATE_24M, RATE_36M, RATE_48M}, /* fallback_rate0 */
  44        {RATE_12M, RATE_12M, RATE_18M, RATE_24M, RATE_36M}, /* fallback_rate1 */
  45};
  46
  47static const u16 vnt_fb_opt1[2][5] = {
  48        {RATE_12M, RATE_18M, RATE_24M, RATE_24M, RATE_36M}, /* fallback_rate0 */
  49        {RATE_6M,  RATE_6M,  RATE_12M, RATE_12M, RATE_18M}, /* fallback_rate1 */
  50};
  51
  52#define RTSDUR_BB       0
  53#define RTSDUR_BA       1
  54#define RTSDUR_AA       2
  55#define CTSDUR_BA       3
  56#define RTSDUR_BA_F0    4
  57#define RTSDUR_AA_F0    5
  58#define RTSDUR_BA_F1    6
  59#define RTSDUR_AA_F1    7
  60#define CTSDUR_BA_F0    8
  61#define CTSDUR_BA_F1    9
  62#define DATADUR_B       10
  63#define DATADUR_A       11
  64#define DATADUR_A_F0    12
  65#define DATADUR_A_F1    13
  66
  67static struct vnt_usb_send_context
  68        *vnt_get_free_context(struct vnt_private *priv)
  69{
  70        struct vnt_usb_send_context *context = NULL;
  71        int ii;
  72
  73        dev_dbg(&priv->usb->dev, "%s\n", __func__);
  74
  75        for (ii = 0; ii < priv->num_tx_context; ii++) {
  76                if (!priv->tx_context[ii])
  77                        return NULL;
  78
  79                context = priv->tx_context[ii];
  80                if (!context->in_use) {
  81                        context->in_use = true;
  82                        memset(context->data, 0,
  83                               MAX_TOTAL_SIZE_WITH_ALL_HEADERS);
  84
  85                        context->hdr = NULL;
  86
  87                        return context;
  88                }
  89        }
  90
  91        if (ii == priv->num_tx_context) {
  92                dev_dbg(&priv->usb->dev, "%s No Free Tx Context\n", __func__);
  93
  94                ieee80211_stop_queues(priv->hw);
  95        }
  96
  97        return NULL;
  98}
  99
 100static __le16 vnt_time_stamp_off(struct vnt_private *priv, u16 rate)
 101{
 102        return cpu_to_le16(vnt_time_stampoff[priv->preamble_type % 2]
 103                                                        [rate % MAX_RATE]);
 104}
 105
 106static u32 vnt_get_rsvtime(struct vnt_private *priv, u8 pkt_type,
 107                           u32 frame_length, u16 rate, int need_ack)
 108{
 109        u32 data_time, ack_time;
 110
 111        data_time = vnt_get_frame_time(priv->preamble_type, pkt_type,
 112                                       frame_length, rate);
 113
 114        if (pkt_type == PK_TYPE_11B)
 115                ack_time = vnt_get_frame_time(priv->preamble_type, pkt_type,
 116                                              14, (u16)priv->top_cck_basic_rate);
 117        else
 118                ack_time = vnt_get_frame_time(priv->preamble_type, pkt_type,
 119                                              14, (u16)priv->top_ofdm_basic_rate);
 120
 121        if (need_ack)
 122                return data_time + priv->sifs + ack_time;
 123
 124        return data_time;
 125}
 126
 127static __le16 vnt_rxtx_rsvtime_le16(struct vnt_private *priv, u8 pkt_type,
 128                                    u32 frame_length, u16 rate, int need_ack)
 129{
 130        return cpu_to_le16((u16)vnt_get_rsvtime(priv, pkt_type,
 131                frame_length, rate, need_ack));
 132}
 133
 134static __le16 vnt_get_rtscts_rsvtime_le(struct vnt_private *priv, u8 rsv_type,
 135                                        u8 pkt_type, u32 frame_length,
 136                                        u16 current_rate)
 137{
 138        u32 rrv_time, rts_time, cts_time, ack_time, data_time;
 139
 140        rrv_time = 0;
 141        rts_time = 0;
 142        cts_time = 0;
 143        ack_time = 0;
 144
 145        data_time = vnt_get_frame_time(priv->preamble_type, pkt_type,
 146                                       frame_length, current_rate);
 147
 148        if (rsv_type == 0) {
 149                rts_time = vnt_get_frame_time(priv->preamble_type, pkt_type,
 150                                              20, priv->top_cck_basic_rate);
 151                ack_time = vnt_get_frame_time(priv->preamble_type,
 152                                              pkt_type, 14,
 153                                              priv->top_cck_basic_rate);
 154                cts_time = ack_time;
 155
 156        } else if (rsv_type == 1) {
 157                rts_time = vnt_get_frame_time(priv->preamble_type, pkt_type,
 158                                              20, priv->top_cck_basic_rate);
 159                cts_time = vnt_get_frame_time(priv->preamble_type, pkt_type,
 160                                              14, priv->top_cck_basic_rate);
 161                ack_time = vnt_get_frame_time(priv->preamble_type, pkt_type,
 162                                              14, priv->top_ofdm_basic_rate);
 163        } else if (rsv_type == 2) {
 164                rts_time = vnt_get_frame_time(priv->preamble_type, pkt_type,
 165                                              20, priv->top_ofdm_basic_rate);
 166                ack_time = vnt_get_frame_time(priv->preamble_type,
 167                                              pkt_type, 14,
 168                                              priv->top_ofdm_basic_rate);
 169                cts_time = ack_time;
 170
 171        } else if (rsv_type == 3) {
 172                cts_time = vnt_get_frame_time(priv->preamble_type, pkt_type,
 173                                              14, priv->top_cck_basic_rate);
 174                ack_time = vnt_get_frame_time(priv->preamble_type, pkt_type,
 175                                              14, priv->top_ofdm_basic_rate);
 176
 177                rrv_time = cts_time + ack_time + data_time + 2 * priv->sifs;
 178
 179                return cpu_to_le16((u16)rrv_time);
 180        }
 181
 182        rrv_time = rts_time + cts_time + ack_time + data_time + 3 * priv->sifs;
 183
 184        return cpu_to_le16((u16)rrv_time);
 185}
 186
 187static __le16 vnt_get_duration_le(struct vnt_private *priv, u8 pkt_type,
 188                                  int need_ack)
 189{
 190        u32 ack_time = 0;
 191
 192        if (need_ack) {
 193                if (pkt_type == PK_TYPE_11B)
 194                        ack_time = vnt_get_frame_time(priv->preamble_type,
 195                                                      pkt_type, 14,
 196                                                      priv->top_cck_basic_rate);
 197                else
 198                        ack_time = vnt_get_frame_time(priv->preamble_type,
 199                                                      pkt_type, 14,
 200                                                      priv->top_ofdm_basic_rate);
 201
 202                return cpu_to_le16((u16)(priv->sifs + ack_time));
 203        }
 204
 205        return 0;
 206}
 207
 208static __le16 vnt_get_rtscts_duration_le(struct vnt_usb_send_context *context,
 209                                         u8 dur_type, u8 pkt_type, u16 rate)
 210{
 211        struct vnt_private *priv = context->priv;
 212        u32 cts_time = 0, dur_time = 0;
 213        u32 frame_length = context->frame_len;
 214        u8 need_ack = context->need_ack;
 215
 216        switch (dur_type) {
 217        case RTSDUR_BB:
 218        case RTSDUR_BA:
 219        case RTSDUR_BA_F0:
 220        case RTSDUR_BA_F1:
 221                cts_time = vnt_get_frame_time(priv->preamble_type, pkt_type,
 222                                              14, priv->top_cck_basic_rate);
 223                dur_time = cts_time + 2 * priv->sifs +
 224                        vnt_get_rsvtime(priv, pkt_type,
 225                                        frame_length, rate, need_ack);
 226                break;
 227
 228        case RTSDUR_AA:
 229        case RTSDUR_AA_F0:
 230        case RTSDUR_AA_F1:
 231                cts_time = vnt_get_frame_time(priv->preamble_type, pkt_type,
 232                                              14, priv->top_ofdm_basic_rate);
 233                dur_time = cts_time + 2 * priv->sifs +
 234                        vnt_get_rsvtime(priv, pkt_type,
 235                                        frame_length, rate, need_ack);
 236                break;
 237
 238        case CTSDUR_BA:
 239        case CTSDUR_BA_F0:
 240        case CTSDUR_BA_F1:
 241                dur_time = priv->sifs + vnt_get_rsvtime(priv,
 242                                pkt_type, frame_length, rate, need_ack);
 243                break;
 244
 245        default:
 246                break;
 247        }
 248
 249        return cpu_to_le16((u16)dur_time);
 250}
 251
 252static u16 vnt_mac_hdr_pos(struct vnt_usb_send_context *tx_context,
 253                           struct ieee80211_hdr *hdr)
 254{
 255        u8 *head = tx_context->data + offsetof(struct vnt_tx_buffer, fifo_head);
 256        u8 *hdr_pos = (u8 *)hdr;
 257
 258        tx_context->hdr = hdr;
 259        if (!tx_context->hdr)
 260                return 0;
 261
 262        return (u16)(hdr_pos - head);
 263}
 264
 265static u16 vnt_rxtx_datahead_g(struct vnt_usb_send_context *tx_context,
 266                               struct vnt_tx_datahead_g *buf)
 267{
 268        struct vnt_private *priv = tx_context->priv;
 269        struct ieee80211_hdr *hdr =
 270                                (struct ieee80211_hdr *)tx_context->skb->data;
 271        u32 frame_len = tx_context->frame_len;
 272        u16 rate = tx_context->tx_rate;
 273        u8 need_ack = tx_context->need_ack;
 274
 275        /* Get SignalField,ServiceField,Length */
 276        vnt_get_phy_field(priv, frame_len, rate, tx_context->pkt_type, &buf->a);
 277        vnt_get_phy_field(priv, frame_len, priv->top_cck_basic_rate,
 278                          PK_TYPE_11B, &buf->b);
 279
 280        /* Get Duration and TimeStamp */
 281        if (ieee80211_is_pspoll(hdr->frame_control)) {
 282                __le16 dur = cpu_to_le16(priv->current_aid | BIT(14) | BIT(15));
 283
 284                buf->duration_a = dur;
 285                buf->duration_b = dur;
 286        } else {
 287                buf->duration_a = vnt_get_duration_le(priv,
 288                                                tx_context->pkt_type, need_ack);
 289                buf->duration_b = vnt_get_duration_le(priv,
 290                                                        PK_TYPE_11B, need_ack);
 291        }
 292
 293        buf->time_stamp_off_a = vnt_time_stamp_off(priv, rate);
 294        buf->time_stamp_off_b = vnt_time_stamp_off(priv,
 295                                        priv->top_cck_basic_rate);
 296
 297        tx_context->tx_hdr_size = vnt_mac_hdr_pos(tx_context, &buf->hdr);
 298
 299        return le16_to_cpu(buf->duration_a);
 300}
 301
 302static u16 vnt_rxtx_datahead_g_fb(struct vnt_usb_send_context *tx_context,
 303                                  struct vnt_tx_datahead_g_fb *buf)
 304{
 305        struct vnt_private *priv = tx_context->priv;
 306        u32 frame_len = tx_context->frame_len;
 307        u16 rate = tx_context->tx_rate;
 308        u8 need_ack = tx_context->need_ack;
 309
 310        /* Get SignalField,ServiceField,Length */
 311        vnt_get_phy_field(priv, frame_len, rate, tx_context->pkt_type, &buf->a);
 312
 313        vnt_get_phy_field(priv, frame_len, priv->top_cck_basic_rate,
 314                          PK_TYPE_11B, &buf->b);
 315
 316        /* Get Duration and TimeStamp */
 317        buf->duration_a = vnt_get_duration_le(priv, tx_context->pkt_type,
 318                                              need_ack);
 319        buf->duration_b = vnt_get_duration_le(priv, PK_TYPE_11B, need_ack);
 320
 321        buf->duration_a_f0 = vnt_get_duration_le(priv, tx_context->pkt_type,
 322                                                 need_ack);
 323        buf->duration_a_f1 = vnt_get_duration_le(priv, tx_context->pkt_type,
 324                                                 need_ack);
 325
 326        buf->time_stamp_off_a = vnt_time_stamp_off(priv, rate);
 327        buf->time_stamp_off_b = vnt_time_stamp_off(priv,
 328                                                priv->top_cck_basic_rate);
 329
 330        tx_context->tx_hdr_size = vnt_mac_hdr_pos(tx_context, &buf->hdr);
 331
 332        return le16_to_cpu(buf->duration_a);
 333}
 334
 335static u16 vnt_rxtx_datahead_a_fb(struct vnt_usb_send_context *tx_context,
 336                                  struct vnt_tx_datahead_a_fb *buf)
 337{
 338        struct vnt_private *priv = tx_context->priv;
 339        u16 rate = tx_context->tx_rate;
 340        u8 pkt_type = tx_context->pkt_type;
 341        u8 need_ack = tx_context->need_ack;
 342        u32 frame_len = tx_context->frame_len;
 343
 344        /* Get SignalField,ServiceField,Length */
 345        vnt_get_phy_field(priv, frame_len, rate, pkt_type, &buf->a);
 346        /* Get Duration and TimeStampOff */
 347        buf->duration = vnt_get_duration_le(priv, pkt_type, need_ack);
 348
 349        buf->duration_f0 = vnt_get_duration_le(priv, pkt_type, need_ack);
 350        buf->duration_f1 = vnt_get_duration_le(priv, pkt_type, need_ack);
 351
 352        buf->time_stamp_off = vnt_time_stamp_off(priv, rate);
 353
 354        tx_context->tx_hdr_size = vnt_mac_hdr_pos(tx_context, &buf->hdr);
 355
 356        return le16_to_cpu(buf->duration);
 357}
 358
 359static u16 vnt_rxtx_datahead_ab(struct vnt_usb_send_context *tx_context,
 360                                struct vnt_tx_datahead_ab *buf)
 361{
 362        struct vnt_private *priv = tx_context->priv;
 363        struct ieee80211_hdr *hdr =
 364                                (struct ieee80211_hdr *)tx_context->skb->data;
 365        u32 frame_len = tx_context->frame_len;
 366        u16 rate = tx_context->tx_rate;
 367        u8 need_ack = tx_context->need_ack;
 368
 369        /* Get SignalField,ServiceField,Length */
 370        vnt_get_phy_field(priv, frame_len, rate,
 371                          tx_context->pkt_type, &buf->ab);
 372
 373        /* Get Duration and TimeStampOff */
 374        if (ieee80211_is_pspoll(hdr->frame_control)) {
 375                __le16 dur = cpu_to_le16(priv->current_aid | BIT(14) | BIT(15));
 376
 377                buf->duration = dur;
 378        } else {
 379                buf->duration = vnt_get_duration_le(priv, tx_context->pkt_type,
 380                                                    need_ack);
 381        }
 382
 383        buf->time_stamp_off = vnt_time_stamp_off(priv, rate);
 384
 385        tx_context->tx_hdr_size = vnt_mac_hdr_pos(tx_context, &buf->hdr);
 386
 387        return le16_to_cpu(buf->duration);
 388}
 389
 390static int vnt_fill_ieee80211_rts(struct vnt_usb_send_context *tx_context,
 391                                  struct ieee80211_rts *rts, __le16 duration)
 392{
 393        struct ieee80211_hdr *hdr =
 394                                (struct ieee80211_hdr *)tx_context->skb->data;
 395
 396        rts->duration = duration;
 397        rts->frame_control =
 398                cpu_to_le16(IEEE80211_FTYPE_CTL | IEEE80211_STYPE_RTS);
 399
 400        ether_addr_copy(rts->ra, hdr->addr1);
 401        ether_addr_copy(rts->ta, hdr->addr2);
 402
 403        return 0;
 404}
 405
 406static u16 vnt_rxtx_rts_g_head(struct vnt_usb_send_context *tx_context,
 407                               struct vnt_rts_g *buf)
 408{
 409        struct vnt_private *priv = tx_context->priv;
 410        u16 rts_frame_len = 20;
 411        u16 current_rate = tx_context->tx_rate;
 412
 413        vnt_get_phy_field(priv, rts_frame_len, priv->top_cck_basic_rate,
 414                          PK_TYPE_11B, &buf->b);
 415        vnt_get_phy_field(priv, rts_frame_len, priv->top_ofdm_basic_rate,
 416                          tx_context->pkt_type, &buf->a);
 417
 418        buf->duration_bb = vnt_get_rtscts_duration_le(tx_context, RTSDUR_BB,
 419                                                      PK_TYPE_11B,
 420                                                      priv->top_cck_basic_rate);
 421        buf->duration_aa = vnt_get_rtscts_duration_le(tx_context, RTSDUR_AA,
 422                                                      tx_context->pkt_type,
 423                                                      current_rate);
 424        buf->duration_ba = vnt_get_rtscts_duration_le(tx_context, RTSDUR_BA,
 425                                                      tx_context->pkt_type,
 426                                                      current_rate);
 427
 428        vnt_fill_ieee80211_rts(tx_context, &buf->data, buf->duration_aa);
 429
 430        return vnt_rxtx_datahead_g(tx_context, &buf->data_head);
 431}
 432
 433static u16 vnt_rxtx_rts_g_fb_head(struct vnt_usb_send_context *tx_context,
 434                                  struct vnt_rts_g_fb *buf)
 435{
 436        struct vnt_private *priv = tx_context->priv;
 437        u16 current_rate = tx_context->tx_rate;
 438        u16 rts_frame_len = 20;
 439
 440        vnt_get_phy_field(priv, rts_frame_len, priv->top_cck_basic_rate,
 441                          PK_TYPE_11B, &buf->b);
 442        vnt_get_phy_field(priv, rts_frame_len, priv->top_ofdm_basic_rate,
 443                          tx_context->pkt_type, &buf->a);
 444
 445        buf->duration_bb = vnt_get_rtscts_duration_le(tx_context, RTSDUR_BB,
 446                                                      PK_TYPE_11B,
 447                                                      priv->top_cck_basic_rate);
 448        buf->duration_aa = vnt_get_rtscts_duration_le(tx_context, RTSDUR_AA,
 449                                                      tx_context->pkt_type,
 450                                                      current_rate);
 451        buf->duration_ba = vnt_get_rtscts_duration_le(tx_context, RTSDUR_BA,
 452                                                      tx_context->pkt_type,
 453                                                      current_rate);
 454
 455        buf->rts_duration_ba_f0 =
 456                vnt_get_rtscts_duration_le(tx_context, RTSDUR_BA_F0,
 457                                           tx_context->pkt_type,
 458                                           priv->tx_rate_fb0);
 459        buf->rts_duration_aa_f0 =
 460                vnt_get_rtscts_duration_le(tx_context, RTSDUR_AA_F0,
 461                                           tx_context->pkt_type,
 462                                           priv->tx_rate_fb0);
 463        buf->rts_duration_ba_f1 =
 464                vnt_get_rtscts_duration_le(tx_context, RTSDUR_BA_F1,
 465                                           tx_context->pkt_type,
 466                                           priv->tx_rate_fb1);
 467        buf->rts_duration_aa_f1 =
 468                vnt_get_rtscts_duration_le(tx_context, RTSDUR_AA_F1,
 469                                           tx_context->pkt_type,
 470                                           priv->tx_rate_fb1);
 471
 472        vnt_fill_ieee80211_rts(tx_context, &buf->data, buf->duration_aa);
 473
 474        return vnt_rxtx_datahead_g_fb(tx_context, &buf->data_head);
 475}
 476
 477static u16 vnt_rxtx_rts_ab_head(struct vnt_usb_send_context *tx_context,
 478                                struct vnt_rts_ab *buf)
 479{
 480        struct vnt_private *priv = tx_context->priv;
 481        u16 current_rate = tx_context->tx_rate;
 482        u16 rts_frame_len = 20;
 483
 484        vnt_get_phy_field(priv, rts_frame_len, priv->top_ofdm_basic_rate,
 485                          tx_context->pkt_type, &buf->ab);
 486
 487        buf->duration = vnt_get_rtscts_duration_le(tx_context, RTSDUR_AA,
 488                                                   tx_context->pkt_type,
 489                                                   current_rate);
 490
 491        vnt_fill_ieee80211_rts(tx_context, &buf->data, buf->duration);
 492
 493        return vnt_rxtx_datahead_ab(tx_context, &buf->data_head);
 494}
 495
 496static u16 vnt_rxtx_rts_a_fb_head(struct vnt_usb_send_context *tx_context,
 497                                  struct vnt_rts_a_fb *buf)
 498{
 499        struct vnt_private *priv = tx_context->priv;
 500        u16 current_rate = tx_context->tx_rate;
 501        u16 rts_frame_len = 20;
 502
 503        vnt_get_phy_field(priv, rts_frame_len, priv->top_ofdm_basic_rate,
 504                          tx_context->pkt_type, &buf->a);
 505
 506        buf->duration = vnt_get_rtscts_duration_le(tx_context, RTSDUR_AA,
 507                                                   tx_context->pkt_type,
 508                                                   current_rate);
 509
 510        buf->rts_duration_f0 =
 511                vnt_get_rtscts_duration_le(tx_context, RTSDUR_AA_F0,
 512                                           tx_context->pkt_type,
 513                                           priv->tx_rate_fb0);
 514
 515        buf->rts_duration_f1 =
 516                vnt_get_rtscts_duration_le(tx_context, RTSDUR_AA_F1,
 517                                           tx_context->pkt_type,
 518                                           priv->tx_rate_fb1);
 519
 520        vnt_fill_ieee80211_rts(tx_context, &buf->data, buf->duration);
 521
 522        return vnt_rxtx_datahead_a_fb(tx_context, &buf->data_head);
 523}
 524
 525static u16 vnt_fill_cts_fb_head(struct vnt_usb_send_context *tx_context,
 526                                union vnt_tx_data_head *head)
 527{
 528        struct vnt_private *priv = tx_context->priv;
 529        struct vnt_cts_fb *buf = &head->cts_g_fb;
 530        u32 cts_frame_len = 14;
 531        u16 current_rate = tx_context->tx_rate;
 532
 533        /* Get SignalField,ServiceField,Length */
 534        vnt_get_phy_field(priv, cts_frame_len, priv->top_cck_basic_rate,
 535                          PK_TYPE_11B, &buf->b);
 536
 537        buf->duration_ba =
 538                vnt_get_rtscts_duration_le(tx_context, CTSDUR_BA,
 539                                           tx_context->pkt_type,
 540                                           current_rate);
 541        /* Get CTSDuration_ba_f0 */
 542        buf->cts_duration_ba_f0 =
 543                vnt_get_rtscts_duration_le(tx_context, CTSDUR_BA_F0,
 544                                           tx_context->pkt_type,
 545                                           priv->tx_rate_fb0);
 546        /* Get CTSDuration_ba_f1 */
 547        buf->cts_duration_ba_f1 =
 548                vnt_get_rtscts_duration_le(tx_context, CTSDUR_BA_F1,
 549                                           tx_context->pkt_type,
 550                                           priv->tx_rate_fb1);
 551        /* Get CTS Frame body */
 552        buf->data.duration = buf->duration_ba;
 553        buf->data.frame_control =
 554                cpu_to_le16(IEEE80211_FTYPE_CTL | IEEE80211_STYPE_CTS);
 555
 556        ether_addr_copy(buf->data.ra, priv->current_net_addr);
 557
 558        return vnt_rxtx_datahead_g_fb(tx_context, &buf->data_head);
 559}
 560
 561static u16 vnt_fill_cts_head(struct vnt_usb_send_context *tx_context,
 562                             union vnt_tx_data_head *head)
 563{
 564        struct vnt_private *priv = tx_context->priv;
 565        struct vnt_cts *buf = &head->cts_g;
 566        u32 cts_frame_len = 14;
 567        u16 current_rate = tx_context->tx_rate;
 568
 569        /* Get SignalField,ServiceField,Length */
 570        vnt_get_phy_field(priv, cts_frame_len, priv->top_cck_basic_rate,
 571                          PK_TYPE_11B, &buf->b);
 572        /* Get CTSDuration_ba */
 573        buf->duration_ba =
 574                vnt_get_rtscts_duration_le(tx_context, CTSDUR_BA,
 575                                           tx_context->pkt_type,
 576                                           current_rate);
 577        /*Get CTS Frame body*/
 578        buf->data.duration = buf->duration_ba;
 579        buf->data.frame_control =
 580                cpu_to_le16(IEEE80211_FTYPE_CTL | IEEE80211_STYPE_CTS);
 581
 582        ether_addr_copy(buf->data.ra, priv->current_net_addr);
 583
 584        return vnt_rxtx_datahead_g(tx_context, &buf->data_head);
 585}
 586
 587static u16 vnt_rxtx_rts(struct vnt_usb_send_context *tx_context,
 588                        union vnt_tx_head *tx_head, bool need_mic)
 589{
 590        struct vnt_private *priv = tx_context->priv;
 591        struct vnt_rrv_time_rts *buf = &tx_head->tx_rts.rts;
 592        union vnt_tx_data_head *head = &tx_head->tx_rts.tx.head;
 593        u32 frame_len = tx_context->frame_len;
 594        u16 current_rate = tx_context->tx_rate;
 595        u8 need_ack = tx_context->need_ack;
 596
 597        buf->rts_rrv_time_aa = vnt_get_rtscts_rsvtime_le(priv, 2,
 598                        tx_context->pkt_type, frame_len, current_rate);
 599        buf->rts_rrv_time_ba = vnt_get_rtscts_rsvtime_le(priv, 1,
 600                        tx_context->pkt_type, frame_len, current_rate);
 601        buf->rts_rrv_time_bb = vnt_get_rtscts_rsvtime_le(priv, 0,
 602                        tx_context->pkt_type, frame_len, current_rate);
 603
 604        buf->rrv_time_a = vnt_rxtx_rsvtime_le16(priv, tx_context->pkt_type,
 605                                                frame_len, current_rate,
 606                                                need_ack);
 607        buf->rrv_time_b = vnt_rxtx_rsvtime_le16(priv, PK_TYPE_11B, frame_len,
 608                                        priv->top_cck_basic_rate, need_ack);
 609
 610        if (need_mic)
 611                head = &tx_head->tx_rts.tx.mic.head;
 612
 613        if (tx_context->fb_option)
 614                return vnt_rxtx_rts_g_fb_head(tx_context, &head->rts_g_fb);
 615
 616        return vnt_rxtx_rts_g_head(tx_context, &head->rts_g);
 617}
 618
 619static u16 vnt_rxtx_cts(struct vnt_usb_send_context *tx_context,
 620                        union vnt_tx_head *tx_head, bool need_mic)
 621{
 622        struct vnt_private *priv = tx_context->priv;
 623        struct vnt_rrv_time_cts *buf = &tx_head->tx_cts.cts;
 624        union vnt_tx_data_head *head = &tx_head->tx_cts.tx.head;
 625        u32 frame_len = tx_context->frame_len;
 626        u16 current_rate = tx_context->tx_rate;
 627        u8 need_ack = tx_context->need_ack;
 628
 629        buf->rrv_time_a = vnt_rxtx_rsvtime_le16(priv, tx_context->pkt_type,
 630                                        frame_len, current_rate, need_ack);
 631        buf->rrv_time_b = vnt_rxtx_rsvtime_le16(priv, PK_TYPE_11B,
 632                                frame_len, priv->top_cck_basic_rate, need_ack);
 633
 634        buf->cts_rrv_time_ba = vnt_get_rtscts_rsvtime_le(priv, 3,
 635                        tx_context->pkt_type, frame_len, current_rate);
 636
 637        if (need_mic)
 638                head = &tx_head->tx_cts.tx.mic.head;
 639
 640        /* Fill CTS */
 641        if (tx_context->fb_option)
 642                return vnt_fill_cts_fb_head(tx_context, head);
 643
 644        return vnt_fill_cts_head(tx_context, head);
 645}
 646
 647static u16 vnt_rxtx_ab(struct vnt_usb_send_context *tx_context,
 648                       union vnt_tx_head *tx_head, bool need_rts, bool need_mic)
 649{
 650        struct vnt_private *priv = tx_context->priv;
 651        struct vnt_rrv_time_ab *buf = &tx_head->tx_ab.ab;
 652        union vnt_tx_data_head *head = &tx_head->tx_ab.tx.head;
 653        u32 frame_len = tx_context->frame_len;
 654        u16 current_rate = tx_context->tx_rate;
 655        u8 need_ack = tx_context->need_ack;
 656
 657        buf->rrv_time = vnt_rxtx_rsvtime_le16(priv, tx_context->pkt_type,
 658                        frame_len, current_rate, need_ack);
 659
 660        if (need_mic)
 661                head = &tx_head->tx_ab.tx.mic.head;
 662
 663        if (need_rts) {
 664                if (tx_context->pkt_type == PK_TYPE_11B)
 665                        buf->rts_rrv_time = vnt_get_rtscts_rsvtime_le(priv, 0,
 666                                tx_context->pkt_type, frame_len, current_rate);
 667                else /* PK_TYPE_11A */
 668                        buf->rts_rrv_time = vnt_get_rtscts_rsvtime_le(priv, 2,
 669                                tx_context->pkt_type, frame_len, current_rate);
 670
 671                if (tx_context->fb_option &&
 672                    tx_context->pkt_type == PK_TYPE_11A)
 673                        return vnt_rxtx_rts_a_fb_head(tx_context,
 674                                                      &head->rts_a_fb);
 675
 676                return vnt_rxtx_rts_ab_head(tx_context, &head->rts_ab);
 677        }
 678
 679        if (tx_context->pkt_type == PK_TYPE_11A)
 680                return vnt_rxtx_datahead_a_fb(tx_context,
 681                                              &head->data_head_a_fb);
 682
 683        return vnt_rxtx_datahead_ab(tx_context, &head->data_head_ab);
 684}
 685
 686static u16 vnt_generate_tx_parameter(struct vnt_usb_send_context *tx_context,
 687                                     struct vnt_tx_buffer *tx_buffer,
 688                                     struct vnt_mic_hdr **mic_hdr, u32 need_mic,
 689                                     bool need_rts)
 690{
 691        if (tx_context->pkt_type == PK_TYPE_11GB ||
 692            tx_context->pkt_type == PK_TYPE_11GA) {
 693                if (need_rts) {
 694                        if (need_mic)
 695                                *mic_hdr =
 696                                        &tx_buffer->tx_head.tx_rts.tx.mic.hdr;
 697
 698                        return vnt_rxtx_rts(tx_context, &tx_buffer->tx_head,
 699                                            need_mic);
 700                }
 701
 702                if (need_mic)
 703                        *mic_hdr = &tx_buffer->tx_head.tx_cts.tx.mic.hdr;
 704
 705                return vnt_rxtx_cts(tx_context, &tx_buffer->tx_head, need_mic);
 706        }
 707
 708        if (need_mic)
 709                *mic_hdr = &tx_buffer->tx_head.tx_ab.tx.mic.hdr;
 710
 711        return vnt_rxtx_ab(tx_context, &tx_buffer->tx_head, need_rts, need_mic);
 712}
 713
 714static void vnt_fill_txkey(struct vnt_usb_send_context *tx_context,
 715                           u8 *key_buffer, struct ieee80211_key_conf *tx_key,
 716                           struct sk_buff *skb, u16 payload_len,
 717                           struct vnt_mic_hdr *mic_hdr)
 718{
 719        struct ieee80211_hdr *hdr = tx_context->hdr;
 720        u64 pn64;
 721        u8 *iv = ((u8 *)hdr + ieee80211_get_hdrlen_from_skb(skb));
 722
 723        /* strip header and icv len from payload */
 724        payload_len -= ieee80211_get_hdrlen_from_skb(skb);
 725        payload_len -= tx_key->icv_len;
 726
 727        switch (tx_key->cipher) {
 728        case WLAN_CIPHER_SUITE_WEP40:
 729        case WLAN_CIPHER_SUITE_WEP104:
 730                memcpy(key_buffer, iv, 3);
 731                memcpy(key_buffer + 3, tx_key->key, tx_key->keylen);
 732
 733                if (tx_key->keylen == WLAN_KEY_LEN_WEP40) {
 734                        memcpy(key_buffer + 8, iv, 3);
 735                        memcpy(key_buffer + 11,
 736                               tx_key->key, WLAN_KEY_LEN_WEP40);
 737                }
 738
 739                break;
 740        case WLAN_CIPHER_SUITE_TKIP:
 741                ieee80211_get_tkip_p2k(tx_key, skb, key_buffer);
 742
 743                break;
 744        case WLAN_CIPHER_SUITE_CCMP:
 745
 746                if (!mic_hdr)
 747                        return;
 748
 749                mic_hdr->id = 0x59;
 750                mic_hdr->payload_len = cpu_to_be16(payload_len);
 751                ether_addr_copy(mic_hdr->mic_addr2, hdr->addr2);
 752
 753                pn64 = atomic64_read(&tx_key->tx_pn);
 754                mic_hdr->ccmp_pn[5] = pn64;
 755                mic_hdr->ccmp_pn[4] = pn64 >> 8;
 756                mic_hdr->ccmp_pn[3] = pn64 >> 16;
 757                mic_hdr->ccmp_pn[2] = pn64 >> 24;
 758                mic_hdr->ccmp_pn[1] = pn64 >> 32;
 759                mic_hdr->ccmp_pn[0] = pn64 >> 40;
 760
 761                if (ieee80211_has_a4(hdr->frame_control))
 762                        mic_hdr->hlen = cpu_to_be16(28);
 763                else
 764                        mic_hdr->hlen = cpu_to_be16(22);
 765
 766                ether_addr_copy(mic_hdr->addr1, hdr->addr1);
 767                ether_addr_copy(mic_hdr->addr2, hdr->addr2);
 768                ether_addr_copy(mic_hdr->addr3, hdr->addr3);
 769
 770                mic_hdr->frame_control = cpu_to_le16(
 771                        le16_to_cpu(hdr->frame_control) & 0xc78f);
 772                mic_hdr->seq_ctrl = cpu_to_le16(
 773                                le16_to_cpu(hdr->seq_ctrl) & 0xf);
 774
 775                if (ieee80211_has_a4(hdr->frame_control))
 776                        ether_addr_copy(mic_hdr->addr4, hdr->addr4);
 777
 778                memcpy(key_buffer, tx_key->key, WLAN_KEY_LEN_CCMP);
 779
 780                break;
 781        default:
 782                break;
 783        }
 784}
 785
 786int vnt_tx_packet(struct vnt_private *priv, struct sk_buff *skb)
 787{
 788        struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
 789        struct ieee80211_tx_rate *tx_rate = &info->control.rates[0];
 790        struct ieee80211_rate *rate;
 791        struct ieee80211_key_conf *tx_key;
 792        struct ieee80211_hdr *hdr;
 793        struct vnt_mic_hdr *mic_hdr = NULL;
 794        struct vnt_tx_buffer *tx_buffer;
 795        struct vnt_tx_fifo_head *tx_buffer_head;
 796        struct vnt_usb_send_context *tx_context;
 797        unsigned long flags;
 798        u16 tx_bytes, tx_header_size, tx_body_size, current_rate, duration_id;
 799        u8 pkt_type, fb_option = AUTO_FB_NONE;
 800        bool need_rts = false;
 801        bool need_mic = false;
 802
 803        hdr = (struct ieee80211_hdr *)(skb->data);
 804
 805        rate = ieee80211_get_tx_rate(priv->hw, info);
 806
 807        current_rate = rate->hw_value;
 808        if (priv->current_rate != current_rate &&
 809            !(priv->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL)) {
 810                priv->current_rate = current_rate;
 811                vnt_schedule_command(priv, WLAN_CMD_SETPOWER);
 812        }
 813
 814        if (current_rate > RATE_11M) {
 815                if (info->band == NL80211_BAND_5GHZ) {
 816                        pkt_type = PK_TYPE_11A;
 817                } else {
 818                        if (tx_rate->flags & IEEE80211_TX_RC_USE_CTS_PROTECT)
 819                                pkt_type = PK_TYPE_11GB;
 820                        else
 821                                pkt_type = PK_TYPE_11GA;
 822                }
 823        } else {
 824                pkt_type = PK_TYPE_11B;
 825        }
 826
 827        spin_lock_irqsave(&priv->lock, flags);
 828
 829        tx_context = vnt_get_free_context(priv);
 830        if (!tx_context) {
 831                dev_dbg(&priv->usb->dev, "%s No free context\n", __func__);
 832                spin_unlock_irqrestore(&priv->lock, flags);
 833                return -ENOMEM;
 834        }
 835
 836        tx_context->skb = skb;
 837        tx_context->pkt_type = pkt_type;
 838        tx_context->need_ack = false;
 839        tx_context->frame_len = skb->len + 4;
 840        tx_context->tx_rate = current_rate;
 841
 842        spin_unlock_irqrestore(&priv->lock, flags);
 843
 844        tx_buffer = (struct vnt_tx_buffer *)tx_context->data;
 845        tx_buffer_head = &tx_buffer->fifo_head;
 846        tx_body_size = skb->len;
 847
 848        /*Set fifo controls */
 849        if (pkt_type == PK_TYPE_11A)
 850                tx_buffer_head->fifo_ctl = 0;
 851        else if (pkt_type == PK_TYPE_11B)
 852                tx_buffer_head->fifo_ctl = cpu_to_le16(FIFOCTL_11B);
 853        else if (pkt_type == PK_TYPE_11GB)
 854                tx_buffer_head->fifo_ctl = cpu_to_le16(FIFOCTL_11GB);
 855        else if (pkt_type == PK_TYPE_11GA)
 856                tx_buffer_head->fifo_ctl = cpu_to_le16(FIFOCTL_11GA);
 857
 858        if (!ieee80211_is_data(hdr->frame_control)) {
 859                tx_buffer_head->fifo_ctl |= cpu_to_le16(FIFOCTL_GENINT |
 860                                                        FIFOCTL_ISDMA0);
 861                tx_buffer_head->fifo_ctl |= cpu_to_le16(FIFOCTL_TMOEN);
 862
 863                tx_buffer_head->time_stamp =
 864                        cpu_to_le16(DEFAULT_MGN_LIFETIME_RES_64us);
 865        } else {
 866                tx_buffer_head->time_stamp =
 867                        cpu_to_le16(DEFAULT_MSDU_LIFETIME_RES_64us);
 868        }
 869
 870        if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) {
 871                tx_buffer_head->fifo_ctl |= cpu_to_le16(FIFOCTL_NEEDACK);
 872                tx_context->need_ack = true;
 873        }
 874
 875        if (ieee80211_has_retry(hdr->frame_control))
 876                tx_buffer_head->fifo_ctl |= cpu_to_le16(FIFOCTL_LRETRY);
 877
 878        if (tx_rate->flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE)
 879                priv->preamble_type = PREAMBLE_SHORT;
 880        else
 881                priv->preamble_type = PREAMBLE_LONG;
 882
 883        if (tx_rate->flags & IEEE80211_TX_RC_USE_RTS_CTS) {
 884                need_rts = true;
 885                tx_buffer_head->fifo_ctl |= cpu_to_le16(FIFOCTL_RTS);
 886        }
 887
 888        if (ieee80211_has_a4(hdr->frame_control))
 889                tx_buffer_head->fifo_ctl |= cpu_to_le16(FIFOCTL_LHEAD);
 890
 891        tx_buffer_head->frag_ctl =
 892                        cpu_to_le16(ieee80211_get_hdrlen_from_skb(skb) << 10);
 893
 894        if (info->control.hw_key) {
 895                tx_key = info->control.hw_key;
 896                switch (info->control.hw_key->cipher) {
 897                case WLAN_CIPHER_SUITE_WEP40:
 898                case WLAN_CIPHER_SUITE_WEP104:
 899                        tx_buffer_head->frag_ctl |= cpu_to_le16(FRAGCTL_LEGACY);
 900                        break;
 901                case WLAN_CIPHER_SUITE_TKIP:
 902                        tx_buffer_head->frag_ctl |= cpu_to_le16(FRAGCTL_TKIP);
 903                        break;
 904                case WLAN_CIPHER_SUITE_CCMP:
 905                        tx_buffer_head->frag_ctl |= cpu_to_le16(FRAGCTL_AES);
 906                        need_mic = true;
 907                default:
 908                        break;
 909                }
 910                tx_context->frame_len += tx_key->icv_len;
 911        }
 912
 913        tx_buffer_head->current_rate = cpu_to_le16(current_rate);
 914
 915        /* legacy rates TODO use ieee80211_tx_rate */
 916        if (current_rate >= RATE_18M && ieee80211_is_data(hdr->frame_control)) {
 917                if (priv->auto_fb_ctrl == AUTO_FB_0) {
 918                        tx_buffer_head->fifo_ctl |=
 919                                                cpu_to_le16(FIFOCTL_AUTO_FB_0);
 920
 921                        priv->tx_rate_fb0 =
 922                                vnt_fb_opt0[FB_RATE0][current_rate - RATE_18M];
 923                        priv->tx_rate_fb1 =
 924                                vnt_fb_opt0[FB_RATE1][current_rate - RATE_18M];
 925
 926                        fb_option = AUTO_FB_0;
 927                } else if (priv->auto_fb_ctrl == AUTO_FB_1) {
 928                        tx_buffer_head->fifo_ctl |=
 929                                                cpu_to_le16(FIFOCTL_AUTO_FB_1);
 930
 931                        priv->tx_rate_fb0 =
 932                                vnt_fb_opt1[FB_RATE0][current_rate - RATE_18M];
 933                        priv->tx_rate_fb1 =
 934                                vnt_fb_opt1[FB_RATE1][current_rate - RATE_18M];
 935
 936                        fb_option = AUTO_FB_1;
 937                }
 938        }
 939
 940        tx_context->fb_option = fb_option;
 941
 942        duration_id = vnt_generate_tx_parameter(tx_context, tx_buffer, &mic_hdr,
 943                                                need_mic, need_rts);
 944
 945        tx_header_size = tx_context->tx_hdr_size;
 946        if (!tx_header_size) {
 947                tx_context->in_use = false;
 948                return -ENOMEM;
 949        }
 950
 951        tx_buffer_head->frag_ctl |= cpu_to_le16(FRAGCTL_NONFRAG);
 952
 953        tx_bytes = tx_header_size + tx_body_size;
 954
 955        memcpy(tx_context->hdr, skb->data, tx_body_size);
 956
 957        hdr->duration_id = cpu_to_le16(duration_id);
 958
 959        if (info->control.hw_key) {
 960                tx_key = info->control.hw_key;
 961                if (tx_key->keylen > 0)
 962                        vnt_fill_txkey(tx_context, tx_buffer_head->tx_key,
 963                                       tx_key, skb, tx_body_size, mic_hdr);
 964        }
 965
 966        priv->seq_counter = (le16_to_cpu(hdr->seq_ctrl) &
 967                                                IEEE80211_SCTL_SEQ) >> 4;
 968
 969        tx_buffer->tx_byte_count = cpu_to_le16(tx_bytes);
 970        tx_buffer->pkt_no = tx_context->pkt_no;
 971        tx_buffer->type = 0x00;
 972
 973        tx_bytes += 4;
 974
 975        tx_context->type = CONTEXT_DATA_PACKET;
 976        tx_context->buf_len = tx_bytes;
 977
 978        spin_lock_irqsave(&priv->lock, flags);
 979
 980        if (vnt_tx_context(priv, tx_context) != STATUS_PENDING) {
 981                spin_unlock_irqrestore(&priv->lock, flags);
 982                return -EIO;
 983        }
 984
 985        spin_unlock_irqrestore(&priv->lock, flags);
 986
 987        return 0;
 988}
 989
 990static int vnt_beacon_xmit(struct vnt_private *priv, struct sk_buff *skb)
 991{
 992        struct vnt_beacon_buffer *beacon_buffer;
 993        struct vnt_tx_short_buf_head *short_head;
 994        struct ieee80211_tx_info *info;
 995        struct vnt_usb_send_context *context;
 996        struct ieee80211_mgmt *mgmt_hdr;
 997        unsigned long flags;
 998        u32 frame_size = skb->len + 4;
 999        u16 current_rate, count;
1000
1001        spin_lock_irqsave(&priv->lock, flags);
1002
1003        context = vnt_get_free_context(priv);
1004        if (!context) {
1005                dev_dbg(&priv->usb->dev, "%s No free context!\n", __func__);
1006                spin_unlock_irqrestore(&priv->lock, flags);
1007                return -ENOMEM;
1008        }
1009
1010        context->skb = skb;
1011
1012        spin_unlock_irqrestore(&priv->lock, flags);
1013
1014        beacon_buffer = (struct vnt_beacon_buffer *)&context->data[0];
1015        short_head = &beacon_buffer->short_head;
1016
1017        if (priv->bb_type == BB_TYPE_11A) {
1018                current_rate = RATE_6M;
1019
1020                /* Get SignalField,ServiceField,Length */
1021                vnt_get_phy_field(priv, frame_size, current_rate,
1022                                  PK_TYPE_11A, &short_head->ab);
1023
1024                /* Get Duration and TimeStampOff */
1025                short_head->duration = vnt_get_duration_le(priv,
1026                                                           PK_TYPE_11A, false);
1027                short_head->time_stamp_off =
1028                                vnt_time_stamp_off(priv, current_rate);
1029        } else {
1030                current_rate = RATE_1M;
1031                short_head->fifo_ctl |= cpu_to_le16(FIFOCTL_11B);
1032
1033                /* Get SignalField,ServiceField,Length */
1034                vnt_get_phy_field(priv, frame_size, current_rate,
1035                                  PK_TYPE_11B, &short_head->ab);
1036
1037                /* Get Duration and TimeStampOff */
1038                short_head->duration = vnt_get_duration_le(priv,
1039                                                PK_TYPE_11B, false);
1040                short_head->time_stamp_off =
1041                        vnt_time_stamp_off(priv, current_rate);
1042        }
1043
1044        /* Generate Beacon Header */
1045        mgmt_hdr = &beacon_buffer->mgmt_hdr;
1046        memcpy(mgmt_hdr, skb->data, skb->len);
1047
1048        /* time stamp always 0 */
1049        mgmt_hdr->u.beacon.timestamp = 0;
1050
1051        info = IEEE80211_SKB_CB(skb);
1052        if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) {
1053                struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)mgmt_hdr;
1054
1055                hdr->duration_id = 0;
1056                hdr->seq_ctrl = cpu_to_le16(priv->seq_counter << 4);
1057        }
1058
1059        priv->seq_counter++;
1060        if (priv->seq_counter > 0x0fff)
1061                priv->seq_counter = 0;
1062
1063        count = sizeof(struct vnt_tx_short_buf_head) + skb->len;
1064
1065        beacon_buffer->tx_byte_count = cpu_to_le16(count);
1066        beacon_buffer->pkt_no = context->pkt_no;
1067        beacon_buffer->type = 0x01;
1068
1069        context->type = CONTEXT_BEACON_PACKET;
1070        context->buf_len = count + 4; /* USB header */
1071
1072        spin_lock_irqsave(&priv->lock, flags);
1073
1074        if (vnt_tx_context(priv, context) != STATUS_PENDING)
1075                ieee80211_free_txskb(priv->hw, context->skb);
1076
1077        spin_unlock_irqrestore(&priv->lock, flags);
1078
1079        return 0;
1080}
1081
1082int vnt_beacon_make(struct vnt_private *priv, struct ieee80211_vif *vif)
1083{
1084        struct sk_buff *beacon;
1085
1086        beacon = ieee80211_beacon_get(priv->hw, vif);
1087        if (!beacon)
1088                return -ENOMEM;
1089
1090        if (vnt_beacon_xmit(priv, beacon)) {
1091                ieee80211_free_txskb(priv->hw, beacon);
1092                return -ENODEV;
1093        }
1094
1095        return 0;
1096}
1097
1098int vnt_beacon_enable(struct vnt_private *priv, struct ieee80211_vif *vif,
1099                      struct ieee80211_bss_conf *conf)
1100{
1101        vnt_mac_reg_bits_off(priv, MAC_REG_TCR, TCR_AUTOBCNTX);
1102
1103        vnt_mac_reg_bits_off(priv, MAC_REG_TFTCTL, TFTCTL_TSFCNTREN);
1104
1105        vnt_mac_set_beacon_interval(priv, conf->beacon_int);
1106
1107        vnt_clear_current_tsf(priv);
1108
1109        vnt_mac_reg_bits_on(priv, MAC_REG_TFTCTL, TFTCTL_TSFCNTREN);
1110
1111        vnt_reset_next_tbtt(priv, conf->beacon_int);
1112
1113        return vnt_beacon_make(priv, vif);
1114}
1115