u32 pkt_offset;
        u32 pkt_desc_sz = chip->rx_pkt_desc_sz;
        u32 buf_desc_sz = chip->rx_buf_desc_sz;
+       u32 new_len;
        u8 *rx_desc;
        dma_addr_t dma;
 
                pkt_offset = pkt_desc_sz + pkt_stat.drv_info_sz +
                             pkt_stat.shift;
 
-               if (pkt_stat.is_c2h) {
-                       /* keep rx_desc, halmac needs it */
-                       skb_put(skb, pkt_stat.pkt_len + pkt_offset);
+               /* allocate a new skb for this frame,
+                * discard the frame if none available
+                */
+               new_len = pkt_stat.pkt_len + pkt_offset;
+               new = dev_alloc_skb(new_len);
+               if (WARN_ONCE(!new, "rx routine starvation\n"))
+                       goto next_rp;
+
+               /* put the DMA data including rx_desc from phy to new skb */
+               skb_put_data(new, skb->data, new_len);
 
-                       /* pass offset for further operation */
-                       *((u32 *)skb->cb) = pkt_offset;
-                       skb_queue_tail(&rtwdev->c2h_queue, skb);
+               if (pkt_stat.is_c2h) {
+                        /* pass rx_desc & offset for further operation */
+                       *((u32 *)new->cb) = pkt_offset;
+                       skb_queue_tail(&rtwdev->c2h_queue, new);
                        ieee80211_queue_work(rtwdev->hw, &rtwdev->c2h_work);
                } else {
-                       /* remove rx_desc, maybe use skb_pull? */
-                       skb_put(skb, pkt_stat.pkt_len);
-                       skb_reserve(skb, pkt_offset);
-
-                       /* alloc a smaller skb to mac80211 */
-                       new = dev_alloc_skb(pkt_stat.pkt_len);
-                       if (!new) {
-                               new = skb;
-                       } else {
-                               skb_put_data(new, skb->data, skb->len);
-                               dev_kfree_skb_any(skb);
-                       }
-                       /* TODO: merge into rx.c */
-                       rtw_rx_stats(rtwdev, pkt_stat.vif, skb);
+                       /* remove rx_desc */
+                       skb_pull(new, pkt_offset);
+
+                       rtw_rx_stats(rtwdev, pkt_stat.vif, new);
                        memcpy(new->cb, &rx_status, sizeof(rx_status));
                        ieee80211_rx_irqsafe(rtwdev->hw, new);
                }
 
-               /* skb delivered to mac80211, alloc a new one in rx ring */
-               new = dev_alloc_skb(RTK_PCI_RX_BUF_SIZE);
-               if (WARN(!new, "rx routine starvation\n"))
-                       return;
-
-               ring->buf[cur_rp] = new;
-               rtw_pci_reset_rx_desc(rtwdev, new, ring, cur_rp, buf_desc_sz);
+next_rp:
+               /* new skb delivered to mac80211, re-enable original skb DMA */
+               rtw_pci_reset_rx_desc(rtwdev, skb, ring, cur_rp, buf_desc_sz);
 
                /* host read next element in ring */
                if (++cur_rp >= ring->r.len)