linux/drivers/staging/vt6656/int.c
<<
>>
Prefs
   1/*
   2 * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
   3 * All rights reserved.
   4 *
   5 * This program is free software; you can redistribute it and/or modify
   6 * it under the terms of the GNU General Public License as published by
   7 * the Free Software Foundation; either version 2 of the License, or
   8 * (at your option) any later version.
   9 *
  10 * This program is distributed in the hope that it will be useful,
  11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13 * GNU General Public License for more details.
  14 *
  15 *
  16 * File: int.c
  17 *
  18 * Purpose: Handle USB interrupt endpoint
  19 *
  20 * Author: Jerry Chen
  21 *
  22 * Date: Apr. 2, 2004
  23 *
  24 * Functions:
  25 *
  26 * Revision History:
  27 *      04-02-2004 Jerry Chen:  Initial release
  28 *
  29 */
  30
  31#include "int.h"
  32#include "mac.h"
  33#include "power.h"
  34#include "usbpipe.h"
  35
  36static const u8 fallback_rate0[5][5] = {
  37        {RATE_18M, RATE_18M, RATE_12M, RATE_12M, RATE_12M},
  38        {RATE_24M, RATE_24M, RATE_18M, RATE_12M, RATE_12M},
  39        {RATE_36M, RATE_36M, RATE_24M, RATE_18M, RATE_18M},
  40        {RATE_48M, RATE_48M, RATE_36M, RATE_24M, RATE_24M},
  41        {RATE_54M, RATE_54M, RATE_48M, RATE_36M, RATE_36M}
  42};
  43
  44static const u8 fallback_rate1[5][5] = {
  45        {RATE_18M, RATE_18M, RATE_12M, RATE_6M, RATE_6M},
  46        {RATE_24M, RATE_24M, RATE_18M, RATE_6M, RATE_6M},
  47        {RATE_36M, RATE_36M, RATE_24M, RATE_12M, RATE_12M},
  48        {RATE_48M, RATE_48M, RATE_24M, RATE_12M, RATE_12M},
  49        {RATE_54M, RATE_54M, RATE_36M, RATE_18M, RATE_18M}
  50};
  51
  52void vnt_int_start_interrupt(struct vnt_private *priv)
  53{
  54        unsigned long flags;
  55        int status;
  56
  57        dev_dbg(&priv->usb->dev, "---->Interrupt Polling Thread\n");
  58
  59        spin_lock_irqsave(&priv->lock, flags);
  60
  61        status = vnt_start_interrupt_urb(priv);
  62
  63        spin_unlock_irqrestore(&priv->lock, flags);
  64}
  65
  66static int vnt_int_report_rate(struct vnt_private *priv, u8 pkt_no, u8 tsr)
  67{
  68        struct vnt_usb_send_context *context;
  69        struct ieee80211_tx_info *info;
  70        struct ieee80211_rate *rate;
  71        u8 tx_retry = (tsr & 0xf0) >> 4;
  72        s8 idx;
  73
  74        if (pkt_no >= priv->num_tx_context)
  75                return -EINVAL;
  76
  77        context = priv->tx_context[pkt_no];
  78
  79        if (!context->skb)
  80                return -EINVAL;
  81
  82        info = IEEE80211_SKB_CB(context->skb);
  83        idx = info->control.rates[0].idx;
  84
  85        if (context->fb_option && !(tsr & (TSR_TMO | TSR_RETRYTMO))) {
  86                u8 tx_rate;
  87                u8 retry = tx_retry;
  88
  89                rate = ieee80211_get_tx_rate(priv->hw, info);
  90                tx_rate = rate->hw_value - RATE_18M;
  91
  92                if (retry > 4)
  93                        retry = 4;
  94
  95                if (context->fb_option == AUTO_FB_0)
  96                        tx_rate = fallback_rate0[tx_rate][retry];
  97                else if (context->fb_option == AUTO_FB_1)
  98                        tx_rate = fallback_rate1[tx_rate][retry];
  99
 100                if (info->band == IEEE80211_BAND_5GHZ)
 101                        idx = tx_rate - RATE_6M;
 102                else
 103                        idx = tx_rate;
 104        }
 105
 106        ieee80211_tx_info_clear_status(info);
 107
 108        info->status.rates[0].count = tx_retry;
 109
 110        if (!(tsr & (TSR_TMO | TSR_RETRYTMO))) {
 111                info->status.rates[0].idx = idx;
 112                info->flags |= IEEE80211_TX_STAT_ACK;
 113        }
 114
 115        ieee80211_tx_status_irqsafe(priv->hw, context->skb);
 116
 117        context->in_use = false;
 118
 119        return 0;
 120}
 121
 122void vnt_int_process_data(struct vnt_private *priv)
 123{
 124        struct vnt_interrupt_data *int_data;
 125        struct ieee80211_low_level_stats *low_stats = &priv->low_stats;
 126
 127        dev_dbg(&priv->usb->dev, "---->s_nsInterruptProcessData\n");
 128
 129        int_data = (struct vnt_interrupt_data *)priv->int_buf.data_buf;
 130
 131        if (int_data->tsr0 & TSR_VALID)
 132                vnt_int_report_rate(priv, int_data->pkt0, int_data->tsr0);
 133
 134        if (int_data->tsr1 & TSR_VALID)
 135                vnt_int_report_rate(priv, int_data->pkt1, int_data->tsr1);
 136
 137        if (int_data->tsr2 & TSR_VALID)
 138                vnt_int_report_rate(priv, int_data->pkt2, int_data->tsr2);
 139
 140        if (int_data->tsr3 & TSR_VALID)
 141                vnt_int_report_rate(priv, int_data->pkt3, int_data->tsr3);
 142
 143        if (int_data->isr0 != 0) {
 144                if (int_data->isr0 & ISR_BNTX &&
 145                                priv->op_mode == NL80211_IFTYPE_AP)
 146                        vnt_schedule_command(priv, WLAN_CMD_BECON_SEND);
 147
 148                if (int_data->isr0 & ISR_TBTT &&
 149                    priv->hw->conf.flags & IEEE80211_CONF_PS) {
 150                        if (!priv->wake_up_count)
 151                                priv->wake_up_count =
 152                                        priv->hw->conf.listen_interval;
 153
 154                        --priv->wake_up_count;
 155
 156                        /* Turn on wake up to listen next beacon */
 157                        if (priv->wake_up_count == 1)
 158                                vnt_schedule_command(priv,
 159                                                     WLAN_CMD_TBTT_WAKEUP);
 160                }
 161                priv->current_tsf = le64_to_cpu(int_data->tsf);
 162
 163                low_stats->dot11RTSSuccessCount += int_data->rts_success;
 164                low_stats->dot11RTSFailureCount += int_data->rts_fail;
 165                low_stats->dot11ACKFailureCount += int_data->ack_fail;
 166                low_stats->dot11FCSErrorCount += int_data->fcs_err;
 167        }
 168
 169        priv->int_buf.in_use = false;
 170}
 171