Newer
Older
/*
Copyright (C) 2004 - 2007 rt2x00 SourceForge Project
<http://rt2x00.serialmonkey.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the
Free Software Foundation, Inc.,
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/*
Module: rt2x00lib
Abstract: rt2x00 generic device routines.
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include "rt2x00.h"
#include "rt2x00lib.h"
/*
* Ring handler.
*/
struct data_ring *rt2x00lib_get_ring(struct rt2x00_dev *rt2x00dev,
const unsigned int queue)
{
int beacon = test_bit(DRIVER_REQUIRE_BEACON_RING, &rt2x00dev->flags);
/*
* Check if we are requesting a reqular TX ring,
* or if we are requesting a Beacon or Atim ring.
* For Atim rings, we should check if it is supported.
*/
if (queue < rt2x00dev->hw->queues && rt2x00dev->tx)
return &rt2x00dev->tx[queue];
if (!rt2x00dev->bcn || !beacon)
return NULL;
if (queue == IEEE80211_TX_QUEUE_BEACON)
return &rt2x00dev->bcn[0];
else if (queue == IEEE80211_TX_QUEUE_AFTER_BEACON)
return &rt2x00dev->bcn[1];
return NULL;
}
EXPORT_SYMBOL_GPL(rt2x00lib_get_ring);
/*
* Link tuning handlers
*/
static void rt2x00lib_start_link_tuner(struct rt2x00_dev *rt2x00dev)
{
rt2x00dev->link.count = 0;
rt2x00dev->link.vgc_level = 0;
memset(&rt2x00dev->link.qual, 0, sizeof(rt2x00dev->link.qual));
/*
* The RX and TX percentage should start at 50%
* this will assure we will get at least get some
* decent value when the link tuner starts.
* The value will be dropped and overwritten with
* the correct (measured )value anyway during the
* first run of the link tuner.
*/
rt2x00dev->link.qual.rx_percentage = 50;
rt2x00dev->link.qual.tx_percentage = 50;
/*
* Reset the link tuner.
*/
rt2x00dev->ops->lib->reset_tuner(rt2x00dev);
queue_delayed_work(rt2x00dev->hw->workqueue,
&rt2x00dev->link.work, LINK_TUNE_INTERVAL);
}
static void rt2x00lib_stop_link_tuner(struct rt2x00_dev *rt2x00dev)
{
Ivo van Doorn
committed
cancel_delayed_work_sync(&rt2x00dev->link.work);
}
void rt2x00lib_reset_link_tuner(struct rt2x00_dev *rt2x00dev)
{
if (!test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags))
return;
rt2x00lib_stop_link_tuner(rt2x00dev);
rt2x00lib_start_link_tuner(rt2x00dev);
}
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
/*
* Ring initialization
*/
static void rt2x00lib_init_rxrings(struct rt2x00_dev *rt2x00dev)
{
struct data_ring *ring = rt2x00dev->rx;
unsigned int i;
if (!rt2x00dev->ops->lib->init_rxentry)
return;
if (ring->data_addr)
memset(ring->data_addr, 0, rt2x00_get_ring_size(ring));
for (i = 0; i < ring->stats.limit; i++)
rt2x00dev->ops->lib->init_rxentry(rt2x00dev, &ring->entry[i]);
rt2x00_ring_index_clear(ring);
}
static void rt2x00lib_init_txrings(struct rt2x00_dev *rt2x00dev)
{
struct data_ring *ring;
unsigned int i;
if (!rt2x00dev->ops->lib->init_txentry)
return;
txringall_for_each(rt2x00dev, ring) {
if (ring->data_addr)
memset(ring->data_addr, 0, rt2x00_get_ring_size(ring));
for (i = 0; i < ring->stats.limit; i++)
rt2x00dev->ops->lib->init_txentry(rt2x00dev,
&ring->entry[i]);
rt2x00_ring_index_clear(ring);
}
}
/*
* Radio control handlers.
*/
int rt2x00lib_enable_radio(struct rt2x00_dev *rt2x00dev)
{
int status;
/*
* Don't enable the radio twice.
* And check if the hardware button has been disabled.
*/
if (test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags) ||
test_bit(DEVICE_DISABLED_RADIO_HW, &rt2x00dev->flags))
/*
* Initialize all data rings.
*/
rt2x00lib_init_rxrings(rt2x00dev);
rt2x00lib_init_txrings(rt2x00dev);
/*
* Enable radio.
*/
status = rt2x00dev->ops->lib->set_device_state(rt2x00dev,
STATE_RADIO_ON);
if (status)
return status;
__set_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags);
/*
* Enable RX.
*/
rt2x00lib_toggle_rx(rt2x00dev, STATE_RADIO_RX_ON);
/*
* Start the TX queues.
*/
ieee80211_start_queues(rt2x00dev->hw);
return 0;
}
void rt2x00lib_disable_radio(struct rt2x00_dev *rt2x00dev)
{
if (!__test_and_clear_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags))
return;
/*
* Stop all scheduled work.
*/
if (work_pending(&rt2x00dev->beacon_work))
cancel_work_sync(&rt2x00dev->beacon_work);
if (work_pending(&rt2x00dev->filter_work))
cancel_work_sync(&rt2x00dev->filter_work);
Loading
Loading full blame...