carl9170 toolchain: update to gcc 9.1.0
[carl9170fw.git] / carlfw / src / wlantx.c
index 801086636c861749829d426553848ebc53e9a841..a8d09522d3619c2d7934d79d74be3dd01414a17c 100644 (file)
@@ -19,8 +19,7 @@
  * 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.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ * with this program; If not, see <http://www.gnu.org/licenses/>.
  */
 
 #include "carl9170.h"
 #include "linux/ieee80211.h"
 #include "wol.h"
 
-static void wlan_txunstuck(unsigned int queue)
+static void wlan_txunstuck(unsigned int qidx)
 {
-       set_wlan_txq_dma_addr(queue, ((uint32_t) fw.wlan.tx_queue[queue].head) | 1);
+       struct dma_queue *queue = &fw.wlan.tx_queue[qidx];
+       struct dma_desc *iter;
+
+       /*
+        * walk up to the last descriptor which hasn't been
+        * processed by the hardware before it bailed out
+        * due to a TX error.
+        * Note: if there was no more "pending" frame
+        * in the queue, it iter will be on the
+        *    queue->terminator (which is fine)
+        */
+       __for_each_desc_bits(iter, queue, AR9170_OWN_BITS_SW);
+
+       set_wlan_txq_dma_addr(qidx, ((uint32_t) iter) | 1);
+       wlan_trigger(BIT(qidx));
 }
 
 #ifdef CONFIG_CARL9170FW_DMA_QUEUE_BUMP
-static void wlan_txupdate(unsigned int queue)
+static void wlan_txupdate(unsigned int qidx)
 {
-       set_wlan_txq_dma_addr(queue, ((uint32_t) fw.wlan.tx_queue[queue].head));
+       struct dma_queue *queue = &fw.wlan.tx_queue[qidx];
+       struct dma_desc *iter;
+       /* comment in wlan_txunstuck applies here too. */
+       __for_each_desc_bits(iter, queue, AR9170_OWN_BITS_SW);
+
+       set_wlan_txq_dma_addr(qidx, ((uint32_t) iter));
+       wlan_trigger(BIT(qidx));
 }
 
 void wlan_dma_bump(unsigned int qidx)
@@ -241,7 +260,7 @@ static void __wlan_tx(struct dma_desc *desc)
 
        if (unlikely(super->s.fill_in_tsf)) {
                struct ieee80211_mgmt *mgmt = (void *) &super->f.data.i3e;
-               uint32_t *tsf = (uint32_t *) &mgmt->u.probe_resp.timestamp;
+               uint32_t tmptsf[2];
 
                /*
                 * Truth be told: this is a hack.
@@ -253,7 +272,8 @@ static void __wlan_tx(struct dma_desc *desc)
                 * (even, if it's got an accurate atomic clock source).
                 */
 
-               read_tsf(tsf);
+               read_tsf(tmptsf);
+               memcpy(&mgmt->u.probe_resp.timestamp, tmptsf, sizeof(tmptsf));
        }
 
        wlan_tx_ampdu(super);
@@ -367,7 +387,7 @@ static bool wlan_tx_status(struct dma_queue *queue,
                                wlan_txunstuck(qidx);
 
                                /* abort cycle - this is necessary due to HW design */
-                               return false;
+                               goto out;
                        } else {
                                /* (HT-) BlockACK failure */
 
@@ -383,7 +403,7 @@ static bool wlan_tx_status(struct dma_queue *queue,
                                BUG_ON(dma_unlink_head(queue) != desc);
 #endif /* CONFIG_CARL9170FW_DEBUG */
                                dma_put(&fw.wlan.tx_retry, desc);
-                               return true;
+                               goto out;
                        }
                } else {
                        /* out of frame attempts - discard frame */
@@ -415,7 +435,7 @@ static bool wlan_tx_status(struct dma_queue *queue,
                if (fw.wlan.fw_desc_callback)
                        fw.wlan.fw_desc_callback(super, success);
 
-               return true;
+               goto out;
        }
 
        if (unlikely(super->s.cab))
@@ -430,7 +450,12 @@ static bool wlan_tx_status(struct dma_queue *queue,
        /* recycle freed descriptors */
        dma_reclaim(&fw.pta.down_queue, desc);
        down_trigger();
-       return true;
+out:
+       /*
+        * if we encounter a frame which run out of (normal)
+        * tx retries we have to stop too.
+        */
+       return !txfail;
 }
 
 void handle_wlan_tx_completion(void)