int error = 0, i;
u32 size;
+
+ common->rx_bufsize = roundup(IEEE80211_MAX_MPDU_LEN +
+ ah->caps.rx_status_len,
+ min(common->cachelsz, (u16)64));
+
ath9k_hw_set_rx_bufsize(ah, common->rx_bufsize -
ah->caps.rx_status_len);
sc->sc_flags &= ~SC_OP_RXFLUSH;
spin_lock_init(&sc->rx.rxbuflock);
- common->rx_bufsize = IEEE80211_MAX_MPDU_LEN / 2 +
- sc->sc_ah->caps.rx_status_len;
-
if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) {
return ath_rx_edma_init(sc, nbufs);
} else {
+ common->rx_bufsize = roundup(IEEE80211_MAX_MPDU_LEN,
+ min(common->cachelsz, (u16)64));
+
ath_dbg(common, ATH_DBG_CONFIG, "cachelsz %u rxbufsize %u\n",
common->cachelsz, common->rx_bufsize);
if (rx_stats->rs_datalen > (common->rx_bufsize - rx_status_len))
return false;
- /* Only use error bits from the last fragment */
+ /*
+ * rs_more indicates chained descriptors which can be used
+ * to link buffers together for a sort of scatter-gather
+ * operation.
+ * reject the frame, we don't support scatter-gather yet and
+ * the frame is probably corrupt anyway
+ */
if (rx_stats->rs_more)
- return true;
+ return false;
/*
* The rx_stats->rs_status will not be set until the end of the
if (!ath9k_rx_accept(common, hdr, rx_status, rx_stats, decrypt_error))
return -EINVAL;
- /* Only use status info from the last fragment */
- if (rx_stats->rs_more)
- return 0;
-
ath9k_process_rssi(common, hw, hdr, rx_stats);
if (ath9k_process_rate(common, hw, rx_stats, rx_status))
int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
{
struct ath_buf *bf;
- struct sk_buff *skb = NULL, *requeue_skb, *hdr_skb;
+ struct sk_buff *skb = NULL, *requeue_skb;
struct ieee80211_rx_status *rxs;
struct ath_hw *ah = sc->sc_ah;
struct ath_common *common = ath9k_hw_common(ah);
if (!skb)
continue;
- /*
- * Take frame header from the first fragment and RX status from
- * the last one.
- */
- if (sc->rx.frag)
- hdr_skb = sc->rx.frag;
- else
- hdr_skb = skb;
-
- hdr = (struct ieee80211_hdr *) (hdr_skb->data + rx_status_len);
- rxs = IEEE80211_SKB_RXCB(hdr_skb);
+ hdr = (struct ieee80211_hdr *) (skb->data + rx_status_len);
+ rxs = IEEE80211_SKB_RXCB(skb);
hw = ath_get_virt_hw(sc, hdr);
* chain it back at the queue without processing it.
*/
if (flush)
- goto requeue_drop_frag;
+ goto requeue;
retval = ath9k_rx_skb_preprocess(common, hw, hdr, &rs,
rxs, &decrypt_error);
if (retval)
- goto requeue_drop_frag;
+ goto requeue;
rxs->mactime = (tsf & ~0xffffffffULL) | rs.rs_tstamp;
if (rs.rs_tstamp > tsf_lower &&
* skb and put it at the tail of the sc->rx.rxbuf list for
* processing. */
if (!requeue_skb)
- goto requeue_drop_frag;
+ goto requeue;
/* Unmap the frame */
dma_unmap_single(sc->dev, bf->bf_buf_addr,
if (ah->caps.rx_status_len)
skb_pull(skb, ah->caps.rx_status_len);
- if (!rs.rs_more)
- ath9k_rx_skb_postprocess(common, hdr_skb, &rs,
- rxs, decrypt_error);
+ ath9k_rx_skb_postprocess(common, skb, &rs,
+ rxs, decrypt_error);
/* We will now give hardware our shiny new allocated skb */
bf->bf_mpdu = requeue_skb;
break;
}
- if (rs.rs_more) {
- /*
- * rs_more indicates chained descriptors which can be
- * used to link buffers together for a sort of
- * scatter-gather operation.
- */
- if (sc->rx.frag) {
- /* too many fragments - cannot handle frame */
- dev_kfree_skb_any(sc->rx.frag);
- dev_kfree_skb_any(skb);
- skb = NULL;
- }
- sc->rx.frag = skb;
- goto requeue;
- }
-
- if (sc->rx.frag) {
- int space = skb->len - skb_tailroom(hdr_skb);
-
- sc->rx.frag = NULL;
-
- if (pskb_expand_head(hdr_skb, 0, space, GFP_ATOMIC) < 0) {
- dev_kfree_skb(skb);
- goto requeue_drop_frag;
- }
-
- skb_copy_from_linear_data(skb, skb_put(hdr_skb, skb->len),
- skb->len);
- dev_kfree_skb_any(skb);
- skb = hdr_skb;
- }
-
/*
* change the default rx antenna if rx diversity chooses the
* other antenna 3 times in a row.
ath_rx_send_to_mac80211(hw, sc, skb);
-requeue_drop_frag:
- if (sc->rx.frag) {
- dev_kfree_skb_any(sc->rx.frag);
- sc->rx.frag = NULL;
- }
requeue:
if (edma) {
list_add_tail(&bf->list, &sc->rx.rxbuf);