]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
Bluetooth: btintel_pcie: Avoid redundant buffer allocation
authorKiran K <kiran.k@intel.com>
Thu, 17 Apr 2025 03:48:42 +0000 (09:18 +0530)
committerLuiz Augusto von Dentz <luiz.von.dentz@intel.com>
Fri, 25 Apr 2025 19:03:19 +0000 (15:03 -0400)
Reuse the skb buffer provided by the PCIe driver to pass it onto the
stack, instead of copying it to a new skb.

Fixes: c2b636b3f788 ("Bluetooth: btintel_pcie: Add support for PCIe transport")
Signed-off-by: Kiran K <kiran.k@intel.com>
Reviewed-by: Paul Menzel <pmenzel@molgen.mpg.de>
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
drivers/bluetooth/btintel_pcie.c

index c1e69fcc9c4faca180d4a18f513e37f7184e956a..efe6ad6d4dc0f8a6e60f0a2853c81f35062abef8 100644 (file)
@@ -957,8 +957,10 @@ static int btintel_pcie_recv_event(struct hci_dev *hdev, struct sk_buff *skb)
                /* This is a debug event that comes from IML and OP image when it
                 * starts execution. There is no need pass this event to stack.
                 */
-               if (skb->data[2] == 0x97)
+               if (skb->data[2] == 0x97) {
+                       hci_recv_diag(hdev, skb);
                        return 0;
+               }
        }
 
        return hci_recv_frame(hdev, skb);
@@ -974,7 +976,6 @@ static int btintel_pcie_recv_frame(struct btintel_pcie_data *data,
        u8 pkt_type;
        u16 plen;
        u32 pcie_pkt_type;
-       struct sk_buff *new_skb;
        void *pdata;
        struct hci_dev *hdev = data->hdev;
 
@@ -1051,24 +1052,20 @@ static int btintel_pcie_recv_frame(struct btintel_pcie_data *data,
 
        bt_dev_dbg(hdev, "pkt_type: 0x%2.2x len: %u", pkt_type, plen);
 
-       new_skb = bt_skb_alloc(plen, GFP_ATOMIC);
-       if (!new_skb) {
-               bt_dev_err(hdev, "Failed to allocate memory for skb of len: %u",
-                          skb->len);
-               ret = -ENOMEM;
-               goto exit_error;
-       }
-
-       hci_skb_pkt_type(new_skb) = pkt_type;
-       skb_put_data(new_skb, skb->data, plen);
+       hci_skb_pkt_type(skb) = pkt_type;
        hdev->stat.byte_rx += plen;
+       skb_trim(skb, plen);
 
        if (pcie_pkt_type == BTINTEL_PCIE_HCI_EVT_PKT)
-               ret = btintel_pcie_recv_event(hdev, new_skb);
+               ret = btintel_pcie_recv_event(hdev, skb);
        else
-               ret = hci_recv_frame(hdev, new_skb);
+               ret = hci_recv_frame(hdev, skb);
+       skb = NULL; /* skb is freed in the callee  */
 
 exit_error:
+       if (skb)
+               kfree_skb(skb);
+
        if (ret)
                hdev->stat.err_rx++;
 
@@ -1202,8 +1199,6 @@ static void btintel_pcie_rx_work(struct work_struct *work)
        struct btintel_pcie_data *data = container_of(work,
                                        struct btintel_pcie_data, rx_work);
        struct sk_buff *skb;
-       int err;
-       struct hci_dev *hdev = data->hdev;
 
        if (test_bit(BTINTEL_PCIE_HWEXP_INPROGRESS, &data->flags)) {
                /* Unlike usb products, controller will not send hardware
@@ -1224,11 +1219,7 @@ static void btintel_pcie_rx_work(struct work_struct *work)
 
        /* Process the sk_buf in queue and send to the HCI layer */
        while ((skb = skb_dequeue(&data->rx_skb_q))) {
-               err = btintel_pcie_recv_frame(data, skb);
-               if (err)
-                       bt_dev_err(hdev, "Failed to send received frame: %d",
-                                  err);
-               kfree_skb(skb);
+               btintel_pcie_recv_frame(data, skb);
        }
 }