/* see if any padding is done by the hw and remove it */
        hdr = (struct ieee80211_hdr *) skb->data;
        hdrlen = ieee80211_get_hdrlen_from_skb(skb);
-       padpos = 24;
        fc = hdr->frame_control;
-       if ((fc & cpu_to_le16(IEEE80211_FCTL_FROMDS|IEEE80211_FCTL_TODS)) ==
-           cpu_to_le16(IEEE80211_FCTL_FROMDS|IEEE80211_FCTL_TODS)) {
-         padpos += 6; /* ETH_ALEN */
-       }
-       if ((fc & cpu_to_le16(IEEE80211_STYPE_QOS_DATA|IEEE80211_FCTL_FTYPE)) ==
-           cpu_to_le16(IEEE80211_STYPE_QOS_DATA|IEEE80211_FTYPE_DATA)) {
-         padpos += 2;
-       }
+       padpos = ath9k_cmn_padpos(hdr->frame_control);
 
        /* The MAC header is padded to have 32-bit boundary if the
         * packet payload is non-zero. The general calculation for
 }
 EXPORT_SYMBOL(ath9k_cmn_rx_skb_postprocess);
 
+int ath9k_cmn_padpos(__le16 frame_control)
+{
+       int padpos = 24;
+       if (ieee80211_has_a4(frame_control)) {
+               padpos += ETH_ALEN;
+       }
+       if (ieee80211_is_data_qos(frame_control)) {
+               padpos += IEEE80211_QOS_CTL_LEN;
+       }
+
+       return padpos;
+}
+EXPORT_SYMBOL(ath9k_cmn_padpos);
+
 static int __init ath9k_cmn_init(void)
 {
        return 0;
 
        struct ath_softc *sc = aphy->sc;
        struct ath_common *common = ath9k_hw_common(sc->sc_ah);
        struct ath_tx_control txctl;
-       int hdrlen, padsize;
+       int padpos, padsize;
+       struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
 
        if (aphy->state != ATH_WIPHY_ACTIVE && aphy->state != ATH_WIPHY_SCAN) {
                ath_print(common, ATH_DBG_XMIT,
        }
 
        if (sc->ps_enabled) {
-               struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
                /*
                 * mac80211 does not set PM field for normal data frames, so we
                 * need to update that based on the current PS mode.
                 * power save mode. Need to wake up hardware for the TX to be
                 * completed and if needed, also for RX of buffered frames.
                 */
-               struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
                ath9k_ps_wakeup(sc);
                ath9k_hw_setrxabort(sc->sc_ah, 0);
                if (ieee80211_is_pspoll(hdr->frame_control)) {
         * BSSes.
         */
        if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) {
-               struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
                if (info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT)
                        sc->tx.seq_no += 0x10;
                hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG);
        }
 
        /* Add the padding after the header if this is not already done */
-       hdrlen = ieee80211_get_hdrlen_from_skb(skb);
-       if (hdrlen & 3) {
-               padsize = hdrlen % 4;
+       padpos = ath9k_cmn_padpos(hdr->frame_control);
+       padsize = padpos & 3;
+       if (padsize && skb->len>padpos) {
                if (skb_headroom(skb) < padsize)
                        return -1;
                skb_push(skb, padsize);
-               memmove(skb->data, skb->data + padsize, hdrlen);
+               memmove(skb->data, skb->data + padsize, padpos);
        }
 
        /* Check if a tx queue is available */
 
        struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
        int hdrlen;
        __le16 fc;
+       int padpos, padsize;
 
        tx_info->pad[0] = 0;
        switch (txctl->frame_type) {
        ATH_TXBUF_RESET(bf);
 
        bf->aphy = aphy;
-       bf->bf_frmlen = skb->len + FCS_LEN - (hdrlen & 3);
+       bf->bf_frmlen = skb->len + FCS_LEN;
+       /* Remove the padding size from bf_frmlen, if any */
+       padpos = ath9k_cmn_padpos(hdr->frame_control);
+       padsize = padpos & 3;
+       if (padsize && skb->len>padpos+padsize) {
+               bf->bf_frmlen -= padsize;
+       }
 
        if (conf_is_ht(&hw->conf) && !is_pae(skb))
                bf->bf_state.bf_type |= BUF_HT;