iwlwifi: pcie: move page tracking into get_page_hdr()
authorJohannes Berg <johannes.berg@intel.com>
Tue, 12 Nov 2019 14:18:16 +0000 (15:18 +0100)
committerLuca Coelho <luciano.coelho@intel.com>
Fri, 20 Dec 2019 11:35:42 +0000 (13:35 +0200)
Move the tracking that records the page in the SKB for later
free (refcount decrement) into the get_page_hdr() function
for better code reuse.

While at it, also add an assertion that this doesn't overwrite
any existing page pointer in the skb.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
drivers/net/wireless/intel/iwlwifi/pcie/internal.h
drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c
drivers/net/wireless/intel/iwlwifi/pcie/tx.c

index a091690f6c799fad751b7759c775740d46692888..3688911ce3dfcc0efeac359d340e584bd6133b40 100644 (file)
@@ -1082,7 +1082,8 @@ void iwl_pcie_apply_destination(struct iwl_trans *trans);
 void iwl_pcie_free_tso_page(struct iwl_trans_pcie *trans_pcie,
                            struct sk_buff *skb);
 #ifdef CONFIG_INET
-struct iwl_tso_hdr_page *get_page_hdr(struct iwl_trans *trans, size_t len);
+struct iwl_tso_hdr_page *get_page_hdr(struct iwl_trans *trans, size_t len,
+                                     struct sk_buff *skb);
 #endif
 
 /* common functions that are used by gen3 transport */
index 8ca0250de99ec06882b27ff8e176998db97c72c9..494a8864368df70796ed3033b76f6534854ba93b 100644 (file)
@@ -246,7 +246,6 @@ static int iwl_pcie_gen2_build_amsdu(struct iwl_trans *trans,
                                     u8 hdr_len, struct iwl_device_cmd *dev_cmd)
 {
 #ifdef CONFIG_INET
-       struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
        struct iwl_tx_cmd_gen2 *tx_cmd = (void *)dev_cmd->payload;
        struct ieee80211_hdr *hdr = (void *)skb->data;
        unsigned int snap_ip_tcp_hdrlen, ip_hdrlen, total_len, hdr_room;
@@ -254,7 +253,6 @@ static int iwl_pcie_gen2_build_amsdu(struct iwl_trans *trans,
        u16 length, amsdu_pad;
        u8 *start_hdr;
        struct iwl_tso_hdr_page *hdr_page;
-       struct page **page_ptr;
        struct tso_t tso;
 
        trace_iwlwifi_dev_tx(trans->dev, skb, tfd, sizeof(*tfd),
@@ -270,14 +268,11 @@ static int iwl_pcie_gen2_build_amsdu(struct iwl_trans *trans,
                (3 + snap_ip_tcp_hdrlen + sizeof(struct ethhdr));
 
        /* Our device supports 9 segments at most, it will fit in 1 page */
-       hdr_page = get_page_hdr(trans, hdr_room);
+       hdr_page = get_page_hdr(trans, hdr_room, skb);
        if (!hdr_page)
                return -ENOMEM;
 
-       get_page(hdr_page->page);
        start_hdr = hdr_page->pos;
-       page_ptr = (void *)((u8 *)skb->cb + trans_pcie->page_offs);
-       *page_ptr = hdr_page->page;
 
        /*
         * Pull the ieee80211 header to be able to use TSO core,
index f21f16ab2a97003d2f3b0ace53e8dd2b3f0fdb50..2d1758031a0ad037cfa9158e89aed6edee6537eb 100644 (file)
@@ -2052,17 +2052,24 @@ static int iwl_fill_data_tbs(struct iwl_trans *trans, struct sk_buff *skb,
 }
 
 #ifdef CONFIG_INET
-struct iwl_tso_hdr_page *get_page_hdr(struct iwl_trans *trans, size_t len)
+struct iwl_tso_hdr_page *get_page_hdr(struct iwl_trans *trans, size_t len,
+                                     struct sk_buff *skb)
 {
        struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
        struct iwl_tso_hdr_page *p = this_cpu_ptr(trans_pcie->tso_hdr_page);
+       struct page **page_ptr;
+
+       page_ptr = (void *)((u8 *)skb->cb + trans_pcie->page_offs);
+
+       if (WARN_ON(*page_ptr))
+               return NULL;
 
        if (!p->page)
                goto alloc;
 
        /* enough room on this page */
        if (p->pos + len < (u8 *)page_address(p->page) + PAGE_SIZE)
-               return p;
+               goto out;
 
        /* We don't have enough room on this page, get a new one. */
        __free_page(p->page);
@@ -2072,6 +2079,9 @@ alloc:
        if (!p->page)
                return NULL;
        p->pos = page_address(p->page);
+out:
+       *page_ptr = p->page;
+       get_page(p->page);
        return p;
 }
 
@@ -2107,7 +2117,6 @@ static int iwl_fill_data_tbs_amsdu(struct iwl_trans *trans, struct sk_buff *skb,
        u16 length, iv_len, amsdu_pad;
        u8 *start_hdr;
        struct iwl_tso_hdr_page *hdr_page;
-       struct page **page_ptr;
        struct tso_t tso;
 
        /* if the packet is protected, then it must be CCMP or GCMP */
@@ -2130,14 +2139,11 @@ static int iwl_fill_data_tbs_amsdu(struct iwl_trans *trans, struct sk_buff *skb,
                (3 + snap_ip_tcp_hdrlen + sizeof(struct ethhdr)) + iv_len;
 
        /* Our device supports 9 segments at most, it will fit in 1 page */
-       hdr_page = get_page_hdr(trans, hdr_room);
+       hdr_page = get_page_hdr(trans, hdr_room, skb);
        if (!hdr_page)
                return -ENOMEM;
 
-       get_page(hdr_page->page);
        start_hdr = hdr_page->pos;
-       page_ptr = (void *)((u8 *)skb->cb + trans_pcie->page_offs);
-       *page_ptr = hdr_page->page;
        memcpy(hdr_page->pos, skb->data + hdr_len, iv_len);
        hdr_page->pos += iv_len;