aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless
diff options
context:
space:
mode:
authorStanislaw Gruszka <sgruszka@redhat.com>2012-03-14 06:16:18 -0400
committerJohn W. Linville <linville@tuxdriver.com>2012-03-15 13:40:31 -0400
commited61e2b02027935520d1be884fac0b2ffce8379a (patch)
treebae0638ed6f68013b93b895ec5fcdb9ba8fe2667 /drivers/net/wireless
parent627fdaf763f80a4db41289c4af7dc279dcba7363 (diff)
rt2x00: rt2800usb: rework txdone code
Patch change txdone code to make it similar like txdone in rt2800pci, process only one entry from queue matching tx status. Before we processed all pending entries from queue until PACKEDID match, that caused that we do not report tx statuses correctly. Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com> Acked-by: Gertjan van Wingerde <gwingerde@gmail.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless')
-rw-r--r--drivers/net/wireless/rt2x00/rt2800usb.c72
1 files changed, 31 insertions, 41 deletions
diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c
index 8e1855a478be..4eaa6280f367 100644
--- a/drivers/net/wireless/rt2x00/rt2800usb.c
+++ b/drivers/net/wireless/rt2x00/rt2800usb.c
@@ -438,35 +438,25 @@ static int rt2800usb_get_tx_data_len(struct queue_entry *entry)
438/* 438/*
439 * TX control handlers 439 * TX control handlers
440 */ 440 */
441static bool rt2800usb_txdone_entry_check(struct queue_entry *entry, u32 reg) 441static enum txdone_entry_desc_flags
442rt2800usb_txdone_entry_check(struct queue_entry *entry, u32 reg)
442{ 443{
443 __le32 *txwi; 444 __le32 *txwi;
444 u32 word; 445 u32 word;
445 int wcid, ack, pid; 446 int wcid, ack, pid;
446 int tx_wcid, tx_ack, tx_pid; 447 int tx_wcid, tx_ack, tx_pid;
447 448
448 if (test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags) ||
449 !test_bit(ENTRY_DATA_STATUS_PENDING, &entry->flags)) {
450 WARNING(entry->queue->rt2x00dev,
451 "Data pending for entry %u in queue %u\n",
452 entry->entry_idx, entry->queue->qid);
453 cond_resched();
454 return false;
455 }
456
457 wcid = rt2x00_get_field32(reg, TX_STA_FIFO_WCID);
458 ack = rt2x00_get_field32(reg, TX_STA_FIFO_TX_ACK_REQUIRED);
459 pid = rt2x00_get_field32(reg, TX_STA_FIFO_PID_TYPE);
460
461 /* 449 /*
462 * This frames has returned with an IO error, 450 * This frames has returned with an IO error,
463 * so the status report is not intended for this 451 * so the status report is not intended for this
464 * frame. 452 * frame.
465 */ 453 */
466 if (test_bit(ENTRY_DATA_IO_FAILED, &entry->flags)) { 454 if (test_bit(ENTRY_DATA_IO_FAILED, &entry->flags))
467 rt2x00lib_txdone_noinfo(entry, TXDONE_FAILURE); 455 return TXDONE_FAILURE;
468 return false; 456
469 } 457 wcid = rt2x00_get_field32(reg, TX_STA_FIFO_WCID);
458 ack = rt2x00_get_field32(reg, TX_STA_FIFO_TX_ACK_REQUIRED);
459 pid = rt2x00_get_field32(reg, TX_STA_FIFO_PID_TYPE);
470 460
471 /* 461 /*
472 * Validate if this TX status report is intended for 462 * Validate if this TX status report is intended for
@@ -482,12 +472,11 @@ static bool rt2800usb_txdone_entry_check(struct queue_entry *entry, u32 reg)
482 if ((wcid != tx_wcid) || (ack != tx_ack) || (pid != tx_pid)) { 472 if ((wcid != tx_wcid) || (ack != tx_ack) || (pid != tx_pid)) {
483 WARNING(entry->queue->rt2x00dev, 473 WARNING(entry->queue->rt2x00dev,
484 "TX status report missed for queue %d entry %d\n", 474 "TX status report missed for queue %d entry %d\n",
485 entry->queue->qid, entry->entry_idx); 475 entry->queue->qid, entry->entry_idx);
486 rt2x00lib_txdone_noinfo(entry, TXDONE_UNKNOWN); 476 return TXDONE_UNKNOWN;
487 return false;
488 } 477 }
489 478
490 return true; 479 return TXDONE_SUCCESS;
491} 480}
492 481
493static void rt2800usb_txdone(struct rt2x00_dev *rt2x00dev) 482static void rt2800usb_txdone(struct rt2x00_dev *rt2x00dev)
@@ -496,35 +485,36 @@ static void rt2800usb_txdone(struct rt2x00_dev *rt2x00dev)
496 struct queue_entry *entry; 485 struct queue_entry *entry;
497 u32 reg; 486 u32 reg;
498 u8 qid; 487 u8 qid;
488 enum txdone_entry_desc_flags done_status;
499 489
500 while (kfifo_get(&rt2x00dev->txstatus_fifo, &reg)) { 490 while (kfifo_get(&rt2x00dev->txstatus_fifo, &reg)) {
501 491 /*
502 /* TX_STA_FIFO_PID_QUEUE is a 2-bit field, thus 492 * TX_STA_FIFO_PID_QUEUE is a 2-bit field, thus qid is
503 * qid is guaranteed to be one of the TX QIDs 493 * guaranteed to be one of the TX QIDs .
504 */ 494 */
505 qid = rt2x00_get_field32(reg, TX_STA_FIFO_PID_QUEUE); 495 qid = rt2x00_get_field32(reg, TX_STA_FIFO_PID_QUEUE);
506 queue = rt2x00queue_get_tx_queue(rt2x00dev, qid); 496 queue = rt2x00queue_get_tx_queue(rt2x00dev, qid);
507 if (unlikely(!queue)) { 497
508 WARNING(rt2x00dev, "Got TX status for an unavailable " 498 if (unlikely(rt2x00queue_empty(queue))) {
499 WARNING(rt2x00dev, "Got TX status for an empty "
509 "queue %u, dropping\n", qid); 500 "queue %u, dropping\n", qid);
510 continue; 501 break;
511 } 502 }
512 503
513 /* 504 entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE);
514 * Inside each queue, we process each entry in a chronological 505
515 * order. We first check that the queue is not empty. 506 if (unlikely(test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags) ||
516 */ 507 !test_bit(ENTRY_DATA_STATUS_PENDING, &entry->flags))) {
517 entry = NULL; 508 WARNING(rt2x00dev, "Data pending for entry %u "
518 while (!rt2x00queue_empty(queue)) { 509 "in queue %u\n", entry->entry_idx, qid);
519 entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE); 510 break;
520 if (rt2800usb_txdone_entry_check(entry, reg))
521 break;
522 entry = NULL;
523 } 511 }
524 512
525 if (entry) 513 done_status = rt2800usb_txdone_entry_check(entry, reg);
526 rt2800_txdone_entry(entry, reg, 514 if (likely(done_status == TXDONE_SUCCESS))
527 rt2800usb_get_txwi(entry)); 515 rt2800_txdone_entry(entry, reg, rt2800usb_get_txwi(entry));
516 else
517 rt2x00lib_txdone_noinfo(entry, done_status);
528 } 518 }
529} 519}
530 520