linux/drivers/staging/vt6656/usbpipe.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 * Purpose: Handle USB control endpoint
   7 *
   8 * Author: Warren Hsu
   9 *
  10 * Date: Mar. 29, 2005
  11 *
  12 * Functions:
  13 *      vnt_control_out - Write variable length bytes to MEM/BB/MAC/EEPROM
  14 *      vnt_control_in - Read variable length bytes from MEM/BB/MAC/EEPROM
  15 *      vnt_control_out_u8 - Write one byte to MEM/BB/MAC/EEPROM
  16 *      vnt_control_in_u8 - Read one byte from MEM/BB/MAC/EEPROM
  17 *
  18 * Revision History:
  19 *      04-05-2004 Jerry Chen: Initial release
  20 *      11-24-2004 Warren Hsu: Add ControlvWriteByte,ControlvReadByte,
  21 *                             ControlvMaskByte
  22 *
  23 */
  24
  25#include "rxtx.h"
  26#include "desc.h"
  27#include "device.h"
  28#include "usbpipe.h"
  29#include "mac.h"
  30#include "rf.h"
  31
  32#define USB_CTL_WAIT    500 /* ms */
  33
  34int vnt_control_out(struct vnt_private *priv, u8 request, u16 value,
  35                    u16 index, u16 length, const u8 *buffer)
  36{
  37        int ret = 0;
  38        u8 *usb_buffer;
  39
  40        if (test_bit(DEVICE_FLAGS_DISCONNECTED, &priv->flags)) {
  41                ret = -EINVAL;
  42                goto end;
  43        }
  44
  45        mutex_lock(&priv->usb_lock);
  46
  47        usb_buffer = kmemdup(buffer, length, GFP_KERNEL);
  48        if (!usb_buffer) {
  49                ret = -ENOMEM;
  50                goto end_unlock;
  51        }
  52
  53        ret = usb_control_msg(priv->usb,
  54                              usb_sndctrlpipe(priv->usb, 0),
  55                              request, 0x40, value,
  56                              index, usb_buffer, length, USB_CTL_WAIT);
  57
  58        kfree(usb_buffer);
  59
  60        if (ret == (int)length)
  61                ret = 0;
  62        else
  63                ret = -EIO;
  64
  65end_unlock:
  66        mutex_unlock(&priv->usb_lock);
  67end:
  68        return ret;
  69}
  70
  71int vnt_control_out_u8(struct vnt_private *priv, u8 reg, u8 reg_off, u8 data)
  72{
  73        return vnt_control_out(priv, MESSAGE_TYPE_WRITE,
  74                               reg_off, reg, sizeof(u8), &data);
  75}
  76
  77int vnt_control_out_blocks(struct vnt_private *priv,
  78                           u16 block, u8 reg, u16 length, const u8 *data)
  79{
  80        int ret = 0, i;
  81
  82        for (i = 0; i < length; i += block) {
  83                u16 len = min_t(int, length - i, block);
  84
  85                ret = vnt_control_out(priv, MESSAGE_TYPE_WRITE,
  86                                      i, reg, len, data + i);
  87                if (ret)
  88                        goto end;
  89        }
  90end:
  91        return ret;
  92}
  93
  94int vnt_control_in(struct vnt_private *priv, u8 request, u16 value,
  95                   u16 index, u16 length, u8 *buffer)
  96{
  97        int ret = 0;
  98        u8 *usb_buffer;
  99
 100        if (test_bit(DEVICE_FLAGS_DISCONNECTED, &priv->flags)) {
 101                ret = -EINVAL;
 102                goto end;
 103        }
 104
 105        mutex_lock(&priv->usb_lock);
 106
 107        usb_buffer = kmalloc(length, GFP_KERNEL);
 108        if (!usb_buffer) {
 109                ret = -ENOMEM;
 110                goto end_unlock;
 111        }
 112
 113        ret = usb_control_msg(priv->usb,
 114                              usb_rcvctrlpipe(priv->usb, 0),
 115                              request, 0xc0, value,
 116                              index, usb_buffer, length, USB_CTL_WAIT);
 117
 118        if (ret == length)
 119                memcpy(buffer, usb_buffer, length);
 120
 121        kfree(usb_buffer);
 122
 123        if (ret == (int)length)
 124                ret = 0;
 125        else
 126                ret = -EIO;
 127
 128end_unlock:
 129        mutex_unlock(&priv->usb_lock);
 130end:
 131        return ret;
 132}
 133
 134int vnt_control_in_u8(struct vnt_private *priv, u8 reg, u8 reg_off, u8 *data)
 135{
 136        return vnt_control_in(priv, MESSAGE_TYPE_READ,
 137                              reg_off, reg, sizeof(u8), data);
 138}
 139
 140static int vnt_int_report_rate(struct vnt_private *priv, u8 pkt_no, u8 tsr)
 141{
 142        struct vnt_usb_send_context *context;
 143        struct ieee80211_tx_info *info;
 144        u8 tx_retry = (tsr & 0xf0) >> 4;
 145        s8 idx;
 146
 147        if (pkt_no >= priv->num_tx_context)
 148                return -EINVAL;
 149
 150        context = priv->tx_context[pkt_no];
 151
 152        if (!context->skb)
 153                return -EINVAL;
 154
 155        info = IEEE80211_SKB_CB(context->skb);
 156        idx = info->control.rates[0].idx;
 157
 158        ieee80211_tx_info_clear_status(info);
 159
 160        info->status.rates[0].count = tx_retry;
 161
 162        if (!(tsr & TSR_TMO)) {
 163                info->status.rates[0].idx = idx;
 164
 165                if (!(info->flags & IEEE80211_TX_CTL_NO_ACK))
 166                        info->flags |= IEEE80211_TX_STAT_ACK;
 167        }
 168
 169        ieee80211_tx_status_irqsafe(priv->hw, context->skb);
 170
 171        context->in_use = false;
 172
 173        return 0;
 174}
 175
 176static void vnt_int_process_data(struct vnt_private *priv)
 177{
 178        struct vnt_interrupt_data *int_data;
 179        struct ieee80211_low_level_stats *low_stats = &priv->low_stats;
 180
 181        dev_dbg(&priv->usb->dev, "---->s_nsInterruptProcessData\n");
 182
 183        int_data = (struct vnt_interrupt_data *)priv->int_buf.data_buf;
 184
 185        if (int_data->tsr0 & TSR_VALID)
 186                vnt_int_report_rate(priv, int_data->pkt0, int_data->tsr0);
 187
 188        if (int_data->tsr1 & TSR_VALID)
 189                vnt_int_report_rate(priv, int_data->pkt1, int_data->tsr1);
 190
 191        if (int_data->tsr2 & TSR_VALID)
 192                vnt_int_report_rate(priv, int_data->pkt2, int_data->tsr2);
 193
 194        if (int_data->tsr3 & TSR_VALID)
 195                vnt_int_report_rate(priv, int_data->pkt3, int_data->tsr3);
 196
 197        if (!int_data->isr0)
 198                return;
 199
 200        if (int_data->isr0 & ISR_BNTX && priv->op_mode == NL80211_IFTYPE_AP)
 201                vnt_schedule_command(priv, WLAN_CMD_BECON_SEND);
 202
 203        priv->current_tsf = le64_to_cpu(int_data->tsf);
 204
 205        low_stats->dot11RTSSuccessCount += int_data->rts_success;
 206        low_stats->dot11RTSFailureCount += int_data->rts_fail;
 207        low_stats->dot11ACKFailureCount += int_data->ack_fail;
 208        low_stats->dot11FCSErrorCount += int_data->fcs_err;
 209}
 210
 211static void vnt_start_interrupt_urb_complete(struct urb *urb)
 212{
 213        struct vnt_private *priv = urb->context;
 214        int status = urb->status;
 215
 216        switch (status) {
 217        case 0:
 218        case -ETIMEDOUT:
 219                break;
 220        case -ECONNRESET:
 221        case -ENOENT:
 222        case -ESHUTDOWN:
 223                return;
 224        default:
 225                break;
 226        }
 227
 228        if (status)
 229                dev_dbg(&priv->usb->dev, "%s status = %d\n", __func__, status);
 230        else
 231                vnt_int_process_data(priv);
 232
 233        status = usb_submit_urb(priv->interrupt_urb, GFP_ATOMIC);
 234        if (status)
 235                dev_dbg(&priv->usb->dev, "Submit int URB failed %d\n", status);
 236}
 237
 238int vnt_start_interrupt_urb(struct vnt_private *priv)
 239{
 240        int ret = 0;
 241
 242        dev_dbg(&priv->usb->dev, "---->Interrupt Polling Thread\n");
 243
 244        usb_fill_int_urb(priv->interrupt_urb,
 245                         priv->usb,
 246                         usb_rcvintpipe(priv->usb, 1),
 247                         priv->int_buf.data_buf,
 248                         MAX_INTERRUPT_SIZE,
 249                         vnt_start_interrupt_urb_complete,
 250                         priv,
 251                         priv->int_interval);
 252
 253        ret = usb_submit_urb(priv->interrupt_urb, GFP_ATOMIC);
 254        if (ret)
 255                dev_dbg(&priv->usb->dev, "Submit int URB failed %d\n", ret);
 256
 257        return ret;
 258}
 259
 260static int vnt_rx_data(struct vnt_private *priv, struct vnt_rcb *ptr_rcb,
 261                       unsigned long bytes_received)
 262{
 263        struct ieee80211_hw *hw = priv->hw;
 264        struct ieee80211_supported_band *sband;
 265        struct sk_buff *skb;
 266        struct ieee80211_rx_status *rx_status;
 267        struct vnt_rx_header *head;
 268        struct vnt_rx_tail *tail;
 269        u32 frame_size;
 270        int ii;
 271        u16 rx_bitrate, pay_load_with_padding;
 272        u8 rate_idx = 0;
 273        long rx_dbm;
 274
 275        skb = ptr_rcb->skb;
 276        rx_status = IEEE80211_SKB_RXCB(skb);
 277
 278        /* [31:16]RcvByteCount ( not include 4-byte Status ) */
 279        head = (struct vnt_rx_header *)skb->data;
 280        frame_size = head->wbk_status >> 16;
 281        frame_size += 4;
 282
 283        if (bytes_received != frame_size) {
 284                dev_dbg(&priv->usb->dev, "------- WRONG Length 1\n");
 285                return false;
 286        }
 287
 288        if ((bytes_received > 2372) || (bytes_received <= 40)) {
 289                /* Frame Size error drop this packet.*/
 290                dev_dbg(&priv->usb->dev, "------ WRONG Length 2\n");
 291                return false;
 292        }
 293
 294        /* real Frame Size = USBframe_size -4WbkStatus - 4RxStatus */
 295        /* -8TSF - 4RSR - 4SQ3 - ?Padding */
 296
 297        /* if SQ3 the range is 24~27, if no SQ3 the range is 20~23 */
 298
 299        /*Fix hardware bug => PLCP_Length error */
 300        if (((bytes_received - head->pay_load_len) > 27) ||
 301            ((bytes_received - head->pay_load_len) < 24) ||
 302            (bytes_received < head->pay_load_len)) {
 303                dev_dbg(&priv->usb->dev, "Wrong PLCP Length %x\n",
 304                        head->pay_load_len);
 305                return false;
 306        }
 307
 308        sband = hw->wiphy->bands[hw->conf.chandef.chan->band];
 309        rx_bitrate = head->rx_rate * 5; /* rx_rate * 5 */
 310
 311        for (ii = 0; ii < sband->n_bitrates; ii++) {
 312                if (sband->bitrates[ii].bitrate == rx_bitrate) {
 313                        rate_idx = ii;
 314                                break;
 315                }
 316        }
 317
 318        if (ii == sband->n_bitrates) {
 319                dev_dbg(&priv->usb->dev, "Wrong Rx Bit Rate %d\n", rx_bitrate);
 320                return false;
 321        }
 322
 323        pay_load_with_padding = ((head->pay_load_len / 4) +
 324                ((head->pay_load_len % 4) ? 1 : 0)) * 4;
 325
 326        tail = (struct vnt_rx_tail *)(skb->data +
 327                                      sizeof(*head) + pay_load_with_padding);
 328        priv->tsf_time = le64_to_cpu(tail->tsf_time);
 329
 330        if (tail->rsr & (RSR_IVLDTYP | RSR_IVLDLEN))
 331                return false;
 332
 333        vnt_rf_rssi_to_dbm(priv, tail->rssi, &rx_dbm);
 334
 335        priv->bb_pre_ed_rssi = (u8)-rx_dbm + 1;
 336        priv->current_rssi = priv->bb_pre_ed_rssi;
 337
 338        skb_pull(skb, sizeof(*head));
 339        skb_trim(skb, head->pay_load_len);
 340
 341        rx_status->mactime = priv->tsf_time;
 342        rx_status->band = hw->conf.chandef.chan->band;
 343        rx_status->signal = rx_dbm;
 344        rx_status->flag = 0;
 345        rx_status->freq = hw->conf.chandef.chan->center_freq;
 346
 347        if (!(tail->rsr & RSR_CRCOK))
 348                rx_status->flag |= RX_FLAG_FAILED_FCS_CRC;
 349
 350        rx_status->rate_idx = rate_idx;
 351
 352        if (tail->new_rsr & NEWRSR_DECRYPTOK)
 353                rx_status->flag |= RX_FLAG_DECRYPTED;
 354
 355        ieee80211_rx_irqsafe(priv->hw, skb);
 356
 357        return true;
 358}
 359
 360static void vnt_submit_rx_urb_complete(struct urb *urb)
 361{
 362        struct vnt_rcb *rcb = urb->context;
 363        struct vnt_private *priv = rcb->priv;
 364
 365        switch (urb->status) {
 366        case 0:
 367                break;
 368        case -ECONNRESET:
 369        case -ENOENT:
 370        case -ESHUTDOWN:
 371                return;
 372        case -ETIMEDOUT:
 373        default:
 374                dev_dbg(&priv->usb->dev, "BULK In failed %d\n", urb->status);
 375                break;
 376        }
 377
 378        if (urb->actual_length) {
 379                if (vnt_rx_data(priv, rcb, urb->actual_length)) {
 380                        rcb->skb = dev_alloc_skb(priv->rx_buf_sz);
 381                        if (!rcb->skb)
 382                                return;
 383                } else {
 384                        skb_push(rcb->skb, skb_headroom(rcb->skb));
 385                        skb_trim(rcb->skb, 0);
 386                }
 387
 388                urb->transfer_buffer = skb_put(rcb->skb,
 389                                               skb_tailroom(rcb->skb));
 390        }
 391
 392        if (usb_submit_urb(urb, GFP_ATOMIC))
 393                dev_dbg(&priv->usb->dev, "Failed to re submit rx skb\n");
 394}
 395
 396int vnt_submit_rx_urb(struct vnt_private *priv, struct vnt_rcb *rcb)
 397{
 398        int ret = 0;
 399        struct urb *urb = rcb->urb;
 400
 401        if (!rcb->skb) {
 402                dev_dbg(&priv->usb->dev, "rcb->skb is null\n");
 403                ret = -EINVAL;
 404                goto end;
 405        }
 406
 407        usb_fill_bulk_urb(urb,
 408                          priv->usb,
 409                          usb_rcvbulkpipe(priv->usb, 2),
 410                          skb_put(rcb->skb, skb_tailroom(rcb->skb)),
 411                          MAX_TOTAL_SIZE_WITH_ALL_HEADERS,
 412                          vnt_submit_rx_urb_complete,
 413                          rcb);
 414
 415        ret = usb_submit_urb(urb, GFP_ATOMIC);
 416        if (ret)
 417                dev_dbg(&priv->usb->dev, "Submit Rx URB failed %d\n", ret);
 418end:
 419        return ret;
 420}
 421
 422static void vnt_tx_context_complete(struct urb *urb)
 423{
 424        struct vnt_usb_send_context *context = urb->context;
 425        struct vnt_private *priv = context->priv;
 426
 427        switch (urb->status) {
 428        case 0:
 429                dev_dbg(&priv->usb->dev,
 430                        "Write %d bytes\n", urb->actual_length);
 431                break;
 432        case -ECONNRESET:
 433        case -ENOENT:
 434        case -ESHUTDOWN:
 435                context->in_use = false;
 436                return;
 437        case -ETIMEDOUT:
 438        default:
 439                dev_dbg(&priv->usb->dev, "BULK Out failed %d\n", urb->status);
 440                break;
 441        }
 442
 443        if (context->type == CONTEXT_DATA_PACKET)
 444                ieee80211_wake_queues(priv->hw);
 445
 446        if (urb->status || context->type == CONTEXT_BEACON_PACKET) {
 447                if (context->skb)
 448                        ieee80211_free_txskb(priv->hw, context->skb);
 449
 450                context->in_use = false;
 451        }
 452}
 453
 454int vnt_tx_context(struct vnt_private *priv,
 455                   struct vnt_usb_send_context *context,
 456                   struct sk_buff *skb)
 457{
 458        struct vnt_tx_usb_header *usb;
 459        struct urb *urb;
 460        int status;
 461        u16 count = skb->len;
 462
 463        usb = skb_push(skb, sizeof(*usb));
 464        usb->tx_byte_count = cpu_to_le16(count);
 465        usb->pkt_no = context->pkt_no;
 466        usb->type = context->type;
 467
 468        if (test_bit(DEVICE_FLAGS_DISCONNECTED, &priv->flags)) {
 469                context->in_use = false;
 470                return -ENODEV;
 471        }
 472
 473        if (skb->len > MAX_TOTAL_SIZE_WITH_ALL_HEADERS) {
 474                context->in_use = false;
 475                return -E2BIG;
 476        }
 477
 478        urb = usb_alloc_urb(0, GFP_ATOMIC);
 479        if (!urb) {
 480                context->in_use = false;
 481                return -ENOMEM;
 482        }
 483
 484        usb_fill_bulk_urb(urb,
 485                          priv->usb,
 486                          usb_sndbulkpipe(priv->usb, 3),
 487                          skb->data,
 488                          skb->len,
 489                          vnt_tx_context_complete,
 490                          context);
 491
 492        usb_anchor_urb(urb, &priv->tx_submitted);
 493
 494        status = usb_submit_urb(urb, GFP_ATOMIC);
 495        if (status) {
 496                dev_dbg(&priv->usb->dev, "Submit Tx URB failed %d\n", status);
 497                usb_unanchor_urb(urb);
 498                context->in_use = false;
 499        }
 500
 501        usb_free_urb(urb);
 502
 503        return status;
 504}
 505