Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6 into for-davem
Conflicts: drivers/net/wireless/iwlwifi/iwl-core.c drivers/net/wireless/rt2x00/rt2x00queue.c drivers/net/wireless/rt2x00/rt2x00queue.h
This commit is contained in:
@@ -60,7 +60,7 @@ struct sk_buff *rt2x00queue_alloc_rxskb(struct queue_entry *entry)
|
||||
* at least 8 bytes bytes available in headroom for IV/EIV
|
||||
* and 8 bytes for ICV data as tailroon.
|
||||
*/
|
||||
if (test_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags)) {
|
||||
if (test_bit(CAPABILITY_HW_CRYPTO, &rt2x00dev->cap_flags)) {
|
||||
head_size += 8;
|
||||
tail_size += 8;
|
||||
}
|
||||
@@ -86,7 +86,7 @@ struct sk_buff *rt2x00queue_alloc_rxskb(struct queue_entry *entry)
|
||||
memset(skbdesc, 0, sizeof(*skbdesc));
|
||||
skbdesc->entry = entry;
|
||||
|
||||
if (test_bit(DRIVER_REQUIRE_DMA, &rt2x00dev->flags)) {
|
||||
if (test_bit(REQUIRE_DMA, &rt2x00dev->cap_flags)) {
|
||||
skbdesc->skb_dma = dma_map_single(rt2x00dev->dev,
|
||||
skb->data,
|
||||
skb->len,
|
||||
@@ -213,7 +213,7 @@ static void rt2x00queue_create_tx_descriptor_seq(struct queue_entry *entry,
|
||||
|
||||
__set_bit(ENTRY_TXD_GENERATE_SEQ, &txdesc->flags);
|
||||
|
||||
if (!test_bit(DRIVER_REQUIRE_SW_SEQNO, &entry->queue->rt2x00dev->flags))
|
||||
if (!test_bit(REQUIRE_SW_SEQNO, &entry->queue->rt2x00dev->cap_flags))
|
||||
return;
|
||||
|
||||
/*
|
||||
@@ -302,6 +302,85 @@ static void rt2x00queue_create_tx_descriptor_plcp(struct queue_entry *entry,
|
||||
}
|
||||
}
|
||||
|
||||
static void rt2x00queue_create_tx_descriptor_ht(struct queue_entry *entry,
|
||||
struct txentry_desc *txdesc,
|
||||
const struct rt2x00_rate *hwrate)
|
||||
{
|
||||
struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(entry->skb);
|
||||
struct ieee80211_tx_rate *txrate = &tx_info->control.rates[0];
|
||||
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)entry->skb->data;
|
||||
|
||||
if (tx_info->control.sta)
|
||||
txdesc->u.ht.mpdu_density =
|
||||
tx_info->control.sta->ht_cap.ampdu_density;
|
||||
|
||||
txdesc->u.ht.ba_size = 7; /* FIXME: What value is needed? */
|
||||
|
||||
/*
|
||||
* Only one STBC stream is supported for now.
|
||||
*/
|
||||
if (tx_info->flags & IEEE80211_TX_CTL_STBC)
|
||||
txdesc->u.ht.stbc = 1;
|
||||
|
||||
/*
|
||||
* If IEEE80211_TX_RC_MCS is set txrate->idx just contains the
|
||||
* mcs rate to be used
|
||||
*/
|
||||
if (txrate->flags & IEEE80211_TX_RC_MCS) {
|
||||
txdesc->u.ht.mcs = txrate->idx;
|
||||
|
||||
/*
|
||||
* MIMO PS should be set to 1 for STA's using dynamic SM PS
|
||||
* when using more then one tx stream (>MCS7).
|
||||
*/
|
||||
if (tx_info->control.sta && txdesc->u.ht.mcs > 7 &&
|
||||
((tx_info->control.sta->ht_cap.cap &
|
||||
IEEE80211_HT_CAP_SM_PS) >>
|
||||
IEEE80211_HT_CAP_SM_PS_SHIFT) ==
|
||||
WLAN_HT_CAP_SM_PS_DYNAMIC)
|
||||
__set_bit(ENTRY_TXD_HT_MIMO_PS, &txdesc->flags);
|
||||
} else {
|
||||
txdesc->u.ht.mcs = rt2x00_get_rate_mcs(hwrate->mcs);
|
||||
if (txrate->flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE)
|
||||
txdesc->u.ht.mcs |= 0x08;
|
||||
}
|
||||
|
||||
/*
|
||||
* This frame is eligible for an AMPDU, however, don't aggregate
|
||||
* frames that are intended to probe a specific tx rate.
|
||||
*/
|
||||
if (tx_info->flags & IEEE80211_TX_CTL_AMPDU &&
|
||||
!(tx_info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE))
|
||||
__set_bit(ENTRY_TXD_HT_AMPDU, &txdesc->flags);
|
||||
|
||||
/*
|
||||
* Set 40Mhz mode if necessary (for legacy rates this will
|
||||
* duplicate the frame to both channels).
|
||||
*/
|
||||
if (txrate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH ||
|
||||
txrate->flags & IEEE80211_TX_RC_DUP_DATA)
|
||||
__set_bit(ENTRY_TXD_HT_BW_40, &txdesc->flags);
|
||||
if (txrate->flags & IEEE80211_TX_RC_SHORT_GI)
|
||||
__set_bit(ENTRY_TXD_HT_SHORT_GI, &txdesc->flags);
|
||||
|
||||
/*
|
||||
* Determine IFS values
|
||||
* - Use TXOP_BACKOFF for management frames except beacons
|
||||
* - Use TXOP_SIFS for fragment bursts
|
||||
* - Use TXOP_HTTXOP for everything else
|
||||
*
|
||||
* Note: rt2800 devices won't use CTS protection (if used)
|
||||
* for frames not transmitted with TXOP_HTTXOP
|
||||
*/
|
||||
if (ieee80211_is_mgmt(hdr->frame_control) &&
|
||||
!ieee80211_is_beacon(hdr->frame_control))
|
||||
txdesc->u.ht.txop = TXOP_BACKOFF;
|
||||
else if (!(tx_info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT))
|
||||
txdesc->u.ht.txop = TXOP_SIFS;
|
||||
else
|
||||
txdesc->u.ht.txop = TXOP_HTTXOP;
|
||||
}
|
||||
|
||||
static void rt2x00queue_create_tx_descriptor(struct queue_entry *entry,
|
||||
struct txentry_desc *txdesc)
|
||||
{
|
||||
@@ -396,8 +475,8 @@ static void rt2x00queue_create_tx_descriptor(struct queue_entry *entry,
|
||||
rt2x00crypto_create_tx_descriptor(entry, txdesc);
|
||||
rt2x00queue_create_tx_descriptor_seq(entry, txdesc);
|
||||
|
||||
if (test_bit(DRIVER_REQUIRE_HT_TX_DESC, &rt2x00dev->flags))
|
||||
rt2x00ht_create_tx_descriptor(entry, txdesc, hwrate);
|
||||
if (test_bit(REQUIRE_HT_TX_DESC, &rt2x00dev->cap_flags))
|
||||
rt2x00queue_create_tx_descriptor_ht(entry, txdesc, hwrate);
|
||||
else
|
||||
rt2x00queue_create_tx_descriptor_plcp(entry, txdesc, hwrate);
|
||||
}
|
||||
@@ -436,7 +515,7 @@ static int rt2x00queue_write_tx_data(struct queue_entry *entry,
|
||||
/*
|
||||
* Map the skb to DMA.
|
||||
*/
|
||||
if (test_bit(DRIVER_REQUIRE_DMA, &rt2x00dev->flags))
|
||||
if (test_bit(REQUIRE_DMA, &rt2x00dev->cap_flags))
|
||||
rt2x00queue_map_txskb(entry);
|
||||
|
||||
return 0;
|
||||
@@ -529,7 +608,7 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb,
|
||||
*/
|
||||
if (test_bit(ENTRY_TXD_ENCRYPT, &txdesc.flags) &&
|
||||
!test_bit(ENTRY_TXD_ENCRYPT_IV, &txdesc.flags)) {
|
||||
if (test_bit(DRIVER_REQUIRE_COPY_IV, &queue->rt2x00dev->flags))
|
||||
if (test_bit(REQUIRE_COPY_IV, &queue->rt2x00dev->cap_flags))
|
||||
rt2x00crypto_tx_copy_iv(skb, &txdesc);
|
||||
else
|
||||
rt2x00crypto_tx_remove_iv(skb, &txdesc);
|
||||
@@ -543,9 +622,9 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb,
|
||||
* PCI and USB devices, while header alignment only is valid
|
||||
* for PCI devices.
|
||||
*/
|
||||
if (test_bit(DRIVER_REQUIRE_L2PAD, &queue->rt2x00dev->flags))
|
||||
if (test_bit(REQUIRE_L2PAD, &queue->rt2x00dev->cap_flags))
|
||||
rt2x00queue_insert_l2pad(entry->skb, txdesc.header_length);
|
||||
else if (test_bit(DRIVER_REQUIRE_DMA, &queue->rt2x00dev->flags))
|
||||
else if (test_bit(REQUIRE_DMA, &queue->rt2x00dev->cap_flags))
|
||||
rt2x00queue_align_frame(entry->skb);
|
||||
|
||||
/*
|
||||
@@ -561,7 +640,7 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb,
|
||||
|
||||
set_bit(ENTRY_DATA_PENDING, &entry->flags);
|
||||
|
||||
rt2x00queue_index_inc(queue, Q_INDEX);
|
||||
rt2x00queue_index_inc(entry, Q_INDEX);
|
||||
rt2x00queue_write_tx_descriptor(entry, &txdesc);
|
||||
rt2x00queue_kick_tx_queue(queue, &txdesc);
|
||||
|
||||
@@ -650,10 +729,12 @@ int rt2x00queue_update_beacon(struct rt2x00_dev *rt2x00dev,
|
||||
return ret;
|
||||
}
|
||||
|
||||
void rt2x00queue_for_each_entry(struct data_queue *queue,
|
||||
bool rt2x00queue_for_each_entry(struct data_queue *queue,
|
||||
enum queue_index start,
|
||||
enum queue_index end,
|
||||
void (*fn)(struct queue_entry *entry))
|
||||
void *data,
|
||||
bool (*fn)(struct queue_entry *entry,
|
||||
void *data))
|
||||
{
|
||||
unsigned long irqflags;
|
||||
unsigned int index_start;
|
||||
@@ -664,7 +745,7 @@ void rt2x00queue_for_each_entry(struct data_queue *queue,
|
||||
ERROR(queue->rt2x00dev,
|
||||
"Entry requested from invalid index range (%d - %d)\n",
|
||||
start, end);
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -683,15 +764,23 @@ void rt2x00queue_for_each_entry(struct data_queue *queue,
|
||||
* send out all frames in the correct order.
|
||||
*/
|
||||
if (index_start < index_end) {
|
||||
for (i = index_start; i < index_end; i++)
|
||||
fn(&queue->entries[i]);
|
||||
for (i = index_start; i < index_end; i++) {
|
||||
if (fn(&queue->entries[i], data))
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
for (i = index_start; i < queue->limit; i++)
|
||||
fn(&queue->entries[i]);
|
||||
for (i = index_start; i < queue->limit; i++) {
|
||||
if (fn(&queue->entries[i], data))
|
||||
return true;
|
||||
}
|
||||
|
||||
for (i = 0; i < index_end; i++)
|
||||
fn(&queue->entries[i]);
|
||||
for (i = 0; i < index_end; i++) {
|
||||
if (fn(&queue->entries[i], data))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(rt2x00queue_for_each_entry);
|
||||
|
||||
@@ -717,8 +806,9 @@ struct queue_entry *rt2x00queue_get_entry(struct data_queue *queue,
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(rt2x00queue_get_entry);
|
||||
|
||||
void rt2x00queue_index_inc(struct data_queue *queue, enum queue_index index)
|
||||
void rt2x00queue_index_inc(struct queue_entry *entry, enum queue_index index)
|
||||
{
|
||||
struct data_queue *queue = entry->queue;
|
||||
unsigned long irqflags;
|
||||
|
||||
if (unlikely(index >= Q_INDEX_MAX)) {
|
||||
@@ -733,7 +823,7 @@ void rt2x00queue_index_inc(struct data_queue *queue, enum queue_index index)
|
||||
if (queue->index[index] >= queue->limit)
|
||||
queue->index[index] = 0;
|
||||
|
||||
queue->last_action[index] = jiffies;
|
||||
entry->last_action = jiffies;
|
||||
|
||||
if (index == Q_INDEX) {
|
||||
queue->length++;
|
||||
@@ -838,7 +928,6 @@ EXPORT_SYMBOL_GPL(rt2x00queue_stop_queue);
|
||||
|
||||
void rt2x00queue_flush_queue(struct data_queue *queue, bool drop)
|
||||
{
|
||||
unsigned int i;
|
||||
bool started;
|
||||
bool tx_queue =
|
||||
(queue->qid == QID_AC_VO) ||
|
||||
@@ -873,20 +962,12 @@ void rt2x00queue_flush_queue(struct data_queue *queue, bool drop)
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if driver supports flushing, we can only guarantee
|
||||
* full support for flushing if the driver is able
|
||||
* to cancel all pending frames (drop = true).
|
||||
* Check if driver supports flushing, if that is the case we can
|
||||
* defer the flushing to the driver. Otherwise we must use the
|
||||
* alternative which just waits for the queue to become empty.
|
||||
*/
|
||||
if (drop && queue->rt2x00dev->ops->lib->flush_queue)
|
||||
queue->rt2x00dev->ops->lib->flush_queue(queue);
|
||||
|
||||
/*
|
||||
* When we don't want to drop any frames, or when
|
||||
* the driver doesn't fully flush the queue correcly,
|
||||
* we must wait for the queue to become empty.
|
||||
*/
|
||||
for (i = 0; !rt2x00queue_empty(queue) && i < 100; i++)
|
||||
msleep(10);
|
||||
if (likely(queue->rt2x00dev->ops->lib->flush_queue))
|
||||
queue->rt2x00dev->ops->lib->flush_queue(queue, drop);
|
||||
|
||||
/*
|
||||
* The queue flush has failed...
|
||||
@@ -959,10 +1040,8 @@ static void rt2x00queue_reset(struct data_queue *queue)
|
||||
queue->count = 0;
|
||||
queue->length = 0;
|
||||
|
||||
for (i = 0; i < Q_INDEX_MAX; i++) {
|
||||
for (i = 0; i < Q_INDEX_MAX; i++)
|
||||
queue->index[i] = 0;
|
||||
queue->last_action[i] = jiffies;
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&queue->index_lock, irqflags);
|
||||
}
|
||||
@@ -1069,7 +1148,7 @@ int rt2x00queue_initialize(struct rt2x00_dev *rt2x00dev)
|
||||
if (status)
|
||||
goto exit;
|
||||
|
||||
if (test_bit(DRIVER_REQUIRE_ATIM_QUEUE, &rt2x00dev->flags)) {
|
||||
if (test_bit(REQUIRE_ATIM_QUEUE, &rt2x00dev->cap_flags)) {
|
||||
status = rt2x00queue_alloc_entries(rt2x00dev->atim,
|
||||
rt2x00dev->ops->atim);
|
||||
if (status)
|
||||
@@ -1121,7 +1200,7 @@ int rt2x00queue_allocate(struct rt2x00_dev *rt2x00dev)
|
||||
struct data_queue *queue;
|
||||
enum data_queue_qid qid;
|
||||
unsigned int req_atim =
|
||||
!!test_bit(DRIVER_REQUIRE_ATIM_QUEUE, &rt2x00dev->flags);
|
||||
!!test_bit(REQUIRE_ATIM_QUEUE, &rt2x00dev->cap_flags);
|
||||
|
||||
/*
|
||||
* We need the following queues:
|
||||
|
Reference in New Issue
Block a user