aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless
diff options
context:
space:
mode:
authorIvo van Doorn <ivdoorn@gmail.com>2008-05-10 07:42:06 -0400
committerJohn W. Linville <linville@tuxdriver.com>2008-05-21 21:47:30 -0400
commitfb55f4d1fa252ba1e479284b79da1049d658c371 (patch)
tree0922dcd4e12037026293dd41914d774f06955641 /drivers/net/wireless
parent5a6e59991b82580c3ca00115603b85762ec76104 (diff)
rt2x00: Fix TX status reporting
The tx_status enumeration was broken since the introduction of rt61pci. That driver uses different values to report the status of the tx action. This would lead to frames that were reported as success but actually failed to be send out, or frames that were neither successfull or failure which were reported as failure. Fix this by change the TX status reporting and more explicitely check for failure or success. Note that a third possibility is added "unknown". Not all hardware (USB) can report the actual TX status, for rt61pci some frames will receive this status because the TXdone handler is never called for those frames. This unknown will now be handled as neither success or failure, so we no longer increment the failure counter while this conclusion could not be determined from the real status of the frame. Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless')
-rw-r--r--drivers/net/wireless/rt2x00/rt2400pci.c13
-rw-r--r--drivers/net/wireless/rt2x00/rt2500pci.c13
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00dev.c24
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00queue.h20
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00reg.h11
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00usb.c11
-rw-r--r--drivers/net/wireless/rt2x00/rt61pci.c15
7 files changed, 76 insertions, 31 deletions
diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c
index afa565c63621..69b1dbd1adf0 100644
--- a/drivers/net/wireless/rt2x00/rt2400pci.c
+++ b/drivers/net/wireless/rt2x00/rt2400pci.c
@@ -1137,7 +1137,18 @@ static void rt2400pci_txdone(struct rt2x00_dev *rt2x00dev,
1137 /* 1137 /*
1138 * Obtain the status about this packet. 1138 * Obtain the status about this packet.
1139 */ 1139 */
1140 txdesc.status = rt2x00_get_field32(word, TXD_W0_RESULT); 1140 txdesc.flags = 0;
1141 switch (rt2x00_get_field32(word, TXD_W0_RESULT)) {
1142 case 0: /* Success */
1143 case 1: /* Success with retry */
1144 __set_bit(TXDONE_SUCCESS, &txdesc.flags);
1145 break;
1146 case 2: /* Failure, excessive retries */
1147 __set_bit(TXDONE_EXCESSIVE_RETRY, &txdesc.flags);
1148 /* Don't break, this is a failed frame! */
1149 default: /* Failure */
1150 __set_bit(TXDONE_FAILURE, &txdesc.flags);
1151 }
1141 txdesc.retry = rt2x00_get_field32(word, TXD_W0_RETRY_COUNT); 1152 txdesc.retry = rt2x00_get_field32(word, TXD_W0_RETRY_COUNT);
1142 1153
1143 rt2x00pci_txdone(rt2x00dev, entry, &txdesc); 1154 rt2x00pci_txdone(rt2x00dev, entry, &txdesc);
diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c
index c06f1b5e5887..aa195dab1554 100644
--- a/drivers/net/wireless/rt2x00/rt2500pci.c
+++ b/drivers/net/wireless/rt2x00/rt2500pci.c
@@ -1292,7 +1292,18 @@ static void rt2500pci_txdone(struct rt2x00_dev *rt2x00dev,
1292 /* 1292 /*
1293 * Obtain the status about this packet. 1293 * Obtain the status about this packet.
1294 */ 1294 */
1295 txdesc.status = rt2x00_get_field32(word, TXD_W0_RESULT); 1295 txdesc.flags = 0;
1296 switch (rt2x00_get_field32(word, TXD_W0_RESULT)) {
1297 case 0: /* Success */
1298 case 1: /* Success with retry */
1299 __set_bit(TXDONE_SUCCESS, &txdesc.flags);
1300 break;
1301 case 2: /* Failure, excessive retries */
1302 __set_bit(TXDONE_EXCESSIVE_RETRY, &txdesc.flags);
1303 /* Don't break, this is a failed frame! */
1304 default: /* Failure */
1305 __set_bit(TXDONE_FAILURE, &txdesc.flags);
1306 }
1296 txdesc.retry = rt2x00_get_field32(word, TXD_W0_RETRY_COUNT); 1307 txdesc.retry = rt2x00_get_field32(word, TXD_W0_RETRY_COUNT);
1297 1308
1298 rt2x00pci_txdone(rt2x00dev, entry, &txdesc); 1309 rt2x00pci_txdone(rt2x00dev, entry, &txdesc);
diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c
index ea130f2eb008..69da22cf085c 100644
--- a/drivers/net/wireless/rt2x00/rt2x00dev.c
+++ b/drivers/net/wireless/rt2x00/rt2x00dev.c
@@ -496,38 +496,36 @@ void rt2x00lib_txdone(struct queue_entry *entry,
496 struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; 496 struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
497 struct skb_frame_desc *skbdesc; 497 struct skb_frame_desc *skbdesc;
498 struct ieee80211_tx_status tx_status; 498 struct ieee80211_tx_status tx_status;
499 int success = !!(txdesc->status == TX_SUCCESS ||
500 txdesc->status == TX_SUCCESS_RETRY);
501 int fail = !!(txdesc->status == TX_FAIL_RETRY ||
502 txdesc->status == TX_FAIL_INVALID ||
503 txdesc->status == TX_FAIL_OTHER);
504 499
505 /* 500 /*
506 * Update TX statistics. 501 * Update TX statistics.
507 */ 502 */
508 rt2x00dev->link.qual.tx_success += success; 503 rt2x00dev->link.qual.tx_success +=
509 rt2x00dev->link.qual.tx_failed += txdesc->retry + fail; 504 test_bit(TXDONE_SUCCESS, &txdesc->flags);
505 rt2x00dev->link.qual.tx_failed +=
506 txdesc->retry + !!test_bit(TXDONE_FAILURE, &txdesc->flags);
510 507
511 /* 508 /*
512 * Initialize TX status 509 * Initialize TX status
513 */ 510 */
514 tx_status.flags = 0; 511 tx_status.flags = 0;
515 tx_status.ack_signal = 0; 512 tx_status.ack_signal = 0;
516 tx_status.excessive_retries = (txdesc->status == TX_FAIL_RETRY); 513 tx_status.excessive_retries =
514 test_bit(TXDONE_EXCESSIVE_RETRY, &txdesc->flags);
517 tx_status.retry_count = txdesc->retry; 515 tx_status.retry_count = txdesc->retry;
518 memcpy(&tx_status.control, txdesc->control, sizeof(*txdesc->control)); 516 memcpy(&tx_status.control, txdesc->control, sizeof(*txdesc->control));
519 517
520 if (!(tx_status.control.flags & IEEE80211_TXCTL_NO_ACK)) { 518 if (!(tx_status.control.flags & IEEE80211_TXCTL_NO_ACK)) {
521 if (success) 519 if (test_bit(TXDONE_SUCCESS, &txdesc->flags))
522 tx_status.flags |= IEEE80211_TX_STATUS_ACK; 520 tx_status.flags |= IEEE80211_TX_STATUS_ACK;
523 else 521 else if (test_bit(TXDONE_FAILURE, &txdesc->flags))
524 rt2x00dev->low_level_stats.dot11ACKFailureCount++; 522 rt2x00dev->low_level_stats.dot11ACKFailureCount++;
525 } 523 }
526 524
527 if (tx_status.control.flags & IEEE80211_TXCTL_USE_RTS_CTS) { 525 if (tx_status.control.flags & IEEE80211_TXCTL_USE_RTS_CTS) {
528 if (success) 526 if (test_bit(TXDONE_SUCCESS, &txdesc->flags))
529 rt2x00dev->low_level_stats.dot11RTSSuccessCount++; 527 rt2x00dev->low_level_stats.dot11RTSSuccessCount++;
530 else 528 else if (test_bit(TXDONE_FAILURE, &txdesc->flags))
531 rt2x00dev->low_level_stats.dot11RTSFailureCount++; 529 rt2x00dev->low_level_stats.dot11RTSFailureCount++;
532 } 530 }
533 531
@@ -546,7 +544,7 @@ void rt2x00lib_txdone(struct queue_entry *entry,
546 ieee80211_tx_status_irqsafe(rt2x00dev->hw, 544 ieee80211_tx_status_irqsafe(rt2x00dev->hw,
547 entry->skb, &tx_status); 545 entry->skb, &tx_status);
548 else 546 else
549 dev_kfree_skb(entry->skb); 547 dev_kfree_skb_irq(entry->skb);
550 entry->skb = NULL; 548 entry->skb = NULL;
551} 549}
552EXPORT_SYMBOL_GPL(rt2x00lib_txdone); 550EXPORT_SYMBOL_GPL(rt2x00lib_txdone);
diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.h b/drivers/net/wireless/rt2x00/rt2x00queue.h
index c3493ed7f4c3..f361f784965e 100644
--- a/drivers/net/wireless/rt2x00/rt2x00queue.h
+++ b/drivers/net/wireless/rt2x00/rt2x00queue.h
@@ -168,18 +168,34 @@ struct rxdone_entry_desc {
168}; 168};
169 169
170/** 170/**
171 * enum txdone_entry_desc_flags: Flags for &struct txdone_entry_desc
172 *
173 * @TXDONE_UNKNOWN: Hardware could not determine success of transmission.
174 * @TXDONE_SUCCESS: Frame was successfully send
175 * @TXDONE_FAILURE: Frame was not successfully send
176 * @TXDONE_EXCESSIVE_RETRY: In addition to &TXDONE_FAILURE, the
177 * frame transmission failed due to excessive retries.
178 */
179enum txdone_entry_desc_flags {
180 TXDONE_UNKNOWN = 1 << 0,
181 TXDONE_SUCCESS = 1 << 1,
182 TXDONE_FAILURE = 1 << 2,
183 TXDONE_EXCESSIVE_RETRY = 1 << 3,
184};
185
186/**
171 * struct txdone_entry_desc: TX done entry descriptor 187 * struct txdone_entry_desc: TX done entry descriptor
172 * 188 *
173 * Summary of information that has been read from the TX frame descriptor 189 * Summary of information that has been read from the TX frame descriptor
174 * after the device is done with transmission. 190 * after the device is done with transmission.
175 * 191 *
176 * @control: Control structure which was used to transmit the frame. 192 * @control: Control structure which was used to transmit the frame.
177 * @status: TX status (See &enum tx_status). 193 * @flags: TX done flags (See &enum txdone_entry_desc_flags).
178 * @retry: Retry count. 194 * @retry: Retry count.
179 */ 195 */
180struct txdone_entry_desc { 196struct txdone_entry_desc {
181 struct ieee80211_tx_control *control; 197 struct ieee80211_tx_control *control;
182 int status; 198 unsigned long flags;
183 int retry; 199 int retry;
184}; 200};
185 201
diff --git a/drivers/net/wireless/rt2x00/rt2x00reg.h b/drivers/net/wireless/rt2x00/rt2x00reg.h
index 0325bed2fbf5..3f255df58b78 100644
--- a/drivers/net/wireless/rt2x00/rt2x00reg.h
+++ b/drivers/net/wireless/rt2x00/rt2x00reg.h
@@ -27,17 +27,6 @@
27#define RT2X00REG_H 27#define RT2X00REG_H
28 28
29/* 29/*
30 * TX result flags.
31 */
32enum tx_status {
33 TX_SUCCESS = 0,
34 TX_SUCCESS_RETRY = 1,
35 TX_FAIL_RETRY = 2,
36 TX_FAIL_INVALID = 3,
37 TX_FAIL_OTHER = 4,
38};
39
40/*
41 * Antenna values 30 * Antenna values
42 */ 31 */
43enum antenna { 32enum antenna {
diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c
index 98aafc2d584a..caee65e82198 100644
--- a/drivers/net/wireless/rt2x00/rt2x00usb.c
+++ b/drivers/net/wireless/rt2x00/rt2x00usb.c
@@ -147,8 +147,17 @@ static void rt2x00usb_interrupt_txdone(struct urb *urb)
147 147
148 /* 148 /*
149 * Obtain the status about this packet. 149 * Obtain the status about this packet.
150 * Note that when the status is 0 it does not mean the
151 * frame was send out correctly. It only means the frame
152 * was succesfully pushed to the hardware, we have no
153 * way to determine the transmission status right now.
154 * (Only indirectly by looking at the failed TX counters
155 * in the register).
150 */ 156 */
151 txdesc.status = !urb->status ? TX_SUCCESS : TX_FAIL_RETRY; 157 if (!urb->status)
158 __set_bit(TXDONE_UNKNOWN, &txdesc.flags);
159 else
160 __set_bit(TXDONE_FAILURE, &txdesc.flags);
152 txdesc.retry = 0; 161 txdesc.retry = 0;
153 txdesc.control = &priv_tx->control; 162 txdesc.control = &priv_tx->control;
154 163
diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c
index edddbf35bbab..15191d6581b1 100644
--- a/drivers/net/wireless/rt2x00/rt61pci.c
+++ b/drivers/net/wireless/rt2x00/rt61pci.c
@@ -1764,7 +1764,8 @@ static void rt61pci_txdone(struct rt2x00_dev *rt2x00dev)
1764 "TX status report missed for entry %d\n", 1764 "TX status report missed for entry %d\n",
1765 entry_done->entry_idx); 1765 entry_done->entry_idx);
1766 1766
1767 txdesc.status = TX_FAIL_OTHER; 1767 txdesc.flags = 0;
1768 __set_bit(TXDONE_UNKNOWN, &txdesc.flags);
1768 txdesc.retry = 0; 1769 txdesc.retry = 0;
1769 1770
1770 rt2x00pci_txdone(rt2x00dev, entry_done, &txdesc); 1771 rt2x00pci_txdone(rt2x00dev, entry_done, &txdesc);
@@ -1774,7 +1775,17 @@ static void rt61pci_txdone(struct rt2x00_dev *rt2x00dev)
1774 /* 1775 /*
1775 * Obtain the status about this packet. 1776 * Obtain the status about this packet.
1776 */ 1777 */
1777 txdesc.status = rt2x00_get_field32(reg, STA_CSR4_TX_RESULT); 1778 txdesc.flags = 0;
1779 switch (rt2x00_get_field32(reg, STA_CSR4_TX_RESULT)) {
1780 case 0: /* Success, maybe with retry */
1781 __set_bit(TXDONE_SUCCESS, &txdesc.flags);
1782 break;
1783 case 6: /* Failure, excessive retries */
1784 __set_bit(TXDONE_EXCESSIVE_RETRY, &txdesc.flags);
1785 /* Don't break, this is a failed frame! */
1786 default: /* Failure */
1787 __set_bit(TXDONE_FAILURE, &txdesc.flags);
1788 }
1778 txdesc.retry = rt2x00_get_field32(reg, STA_CSR4_RETRY_COUNT); 1789 txdesc.retry = rt2x00_get_field32(reg, STA_CSR4_RETRY_COUNT);
1779 1790
1780 rt2x00pci_txdone(rt2x00dev, entry, &txdesc); 1791 rt2x00pci_txdone(rt2x00dev, entry, &txdesc);