From patchwork Tue Jul 27 23:51:17 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tedd Ho-Jeong An X-Patchwork-Id: 12404669 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.7 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id B2418C4338F for ; Tue, 27 Jul 2021 23:51:44 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 9931860F9C for ; Tue, 27 Jul 2021 23:51:44 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232956AbhG0Xvn (ORCPT ); Tue, 27 Jul 2021 19:51:43 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37188 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232766AbhG0Xvn (ORCPT ); Tue, 27 Jul 2021 19:51:43 -0400 Received: from mail-pj1-x1032.google.com (mail-pj1-x1032.google.com [IPv6:2607:f8b0:4864:20::1032]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id A4F5AC061757 for ; Tue, 27 Jul 2021 16:51:41 -0700 (PDT) Received: by mail-pj1-x1032.google.com with SMTP id b6so2383335pji.4 for ; Tue, 27 Jul 2021 16:51:41 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=RoMZyv4TQqJ9vQuH666cg9xWrRSijabmEdIpEtBdFco=; b=POhH4LVo/oBvuJU8aDTo18xUeW70bVNR5e6y21+jHjPczCy2M8UtMACgCAwSY/RA/B P2UOuZEJcVcXKVJV1LNLvJvNFv1yw0mrmuRxeTXnrk2L/ZADL4U4N/8BDcG8YySdy2V/ /vvo9mvn5IVm2zuq7UhqWGvv+ulrB89CGo57mUnCtK5x8nzijCaCyyloaUqkgEewZIqi /xw6P5ek4giJab5N0rW5m2cjOCokINbwHEvS6Dykcwd/jQVHyFsSbq0Jx65YPq2U3LSu pSLpmRC7o2fQmoASkgR3ZDTyvTdaws2TaAJON9uueQ4uWIT7wT1DBRz7UIOpENh3os1K TB0g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=RoMZyv4TQqJ9vQuH666cg9xWrRSijabmEdIpEtBdFco=; b=OzJMunToZobqY68e8nvYhRRRg4qBdRXTYDuvKZhl2saKExvoWwNacTdUstAYhtIoHI +I9ooZl0CexYpwk+eHO/vSQU3FOCkiHWZ18qazLfYAIhGTe3LmBYcYObTIdUOeW8h3ZW G+TYKA5G09CsPCwgdsCe9jDXKPM6lA+ApNu8PRGVip4Qy7v80OUlPsMSPAdGYwKSdFTk e9YkoiOKxu9OFIGDVu/Y3VAWJwv+2+FTsvyf3KR8J0W2NxUylZfXDUCy0HPePdM3t5k8 0v2GyX3gt+IkyWGYCe2hiChwwId5WaWTjtud/rIrzLXraiRzjZonJcDCbMD2PnctaB+4 wvEA== X-Gm-Message-State: AOAM532S6ZP/rEK7eGI39KVFB9KuoklqZGh+5gho51yofmaSvsvUHqjO YxhEgplboiCRf95QMc79dZf6J5laiOo= X-Google-Smtp-Source: ABdhPJwtM0WmuUX++26D1AB5h9UOeri4GxvDQtMrLl+0XCY8ovjDSJYY/E6nk2B5wG6GJsmsMIWPqQ== X-Received: by 2002:a17:90a:fa1:: with SMTP id 30mr6609866pjz.42.1627429900886; Tue, 27 Jul 2021 16:51:40 -0700 (PDT) Received: from localhost.localdomain ([2601:1c0:6a01:d830::7cb2]) by smtp.gmail.com with ESMTPSA id y9sm1545332pfq.199.2021.07.27.16.51.40 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 27 Jul 2021 16:51:40 -0700 (PDT) From: Tedd Ho-Jeong An To: linux-bluetooth@vger.kernel.org Cc: Tedd Ho-Jeong An Subject: [RFC PATCH v4 01/11] Bluetooth: Add support hdev to allocate private data Date: Tue, 27 Jul 2021 16:51:17 -0700 Message-Id: <20210727235127.173149-2-hj.tedd.an@gmail.com> X-Mailer: git-send-email 2.26.3 In-Reply-To: <20210727235127.173149-1-hj.tedd.an@gmail.com> References: <20210727235127.173149-1-hj.tedd.an@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-bluetooth@vger.kernel.org From: Tedd Ho-Jeong An This patch adds support hdev to allocate extra size for private data. The size of private data is specified in the hdev_alloc_size(priv_size) and the allocated buffer can be accessed with hci_get_priv(hdev). Signed-off-by: Tedd Ho-Jeong An --- drivers/bluetooth/bfusb.c | 2 +- drivers/bluetooth/bluecard_cs.c | 2 +- drivers/bluetooth/bpa10x.c | 2 +- drivers/bluetooth/bt3c_cs.c | 2 +- drivers/bluetooth/btmrvl_main.c | 2 +- drivers/bluetooth/btmtksdio.c | 2 +- drivers/bluetooth/btmtkuart.c | 2 +- drivers/bluetooth/btqcomsmd.c | 2 +- drivers/bluetooth/btrsi.c | 2 +- drivers/bluetooth/btsdio.c | 2 +- drivers/bluetooth/btusb.c | 2 +- drivers/bluetooth/dtl1_cs.c | 2 +- drivers/bluetooth/hci_ldisc.c | 2 +- drivers/bluetooth/hci_serdev.c | 2 +- drivers/bluetooth/hci_vhci.c | 2 +- drivers/bluetooth/virtio_bt.c | 2 +- include/net/bluetooth/hci_core.h | 7 ++++++- net/bluetooth/hci_core.c | 11 +++++++++-- 18 files changed, 31 insertions(+), 19 deletions(-) diff --git a/drivers/bluetooth/bfusb.c b/drivers/bluetooth/bfusb.c index 5a321b4076aa..430e230999fa 100644 --- a/drivers/bluetooth/bfusb.c +++ b/drivers/bluetooth/bfusb.c @@ -651,7 +651,7 @@ static int bfusb_probe(struct usb_interface *intf, const struct usb_device_id *i release_firmware(firmware); /* Initialize and register HCI device */ - hdev = hci_alloc_dev(); + hdev = hci_alloc_dev(0); if (!hdev) { BT_ERR("Can't allocate HCI device"); goto done; diff --git a/drivers/bluetooth/bluecard_cs.c b/drivers/bluetooth/bluecard_cs.c index 36eabf61717f..d62b878aff7e 100644 --- a/drivers/bluetooth/bluecard_cs.c +++ b/drivers/bluetooth/bluecard_cs.c @@ -694,7 +694,7 @@ static int bluecard_open(struct bluecard_info *info) info->rx_skb = NULL; /* Initialize HCI device */ - hdev = hci_alloc_dev(); + hdev = hci_alloc_dev(0); if (!hdev) { BT_ERR("Can't allocate HCI device"); return -ENOMEM; diff --git a/drivers/bluetooth/bpa10x.c b/drivers/bluetooth/bpa10x.c index 1fa58c059cbf..bd670352a336 100644 --- a/drivers/bluetooth/bpa10x.c +++ b/drivers/bluetooth/bpa10x.c @@ -380,7 +380,7 @@ static int bpa10x_probe(struct usb_interface *intf, init_usb_anchor(&data->tx_anchor); init_usb_anchor(&data->rx_anchor); - hdev = hci_alloc_dev(); + hdev = hci_alloc_dev(0); if (!hdev) return -ENOMEM; diff --git a/drivers/bluetooth/bt3c_cs.c b/drivers/bluetooth/bt3c_cs.c index 54713833951a..cd135a736688 100644 --- a/drivers/bluetooth/bt3c_cs.c +++ b/drivers/bluetooth/bt3c_cs.c @@ -550,7 +550,7 @@ static int bt3c_open(struct bt3c_info *info) info->rx_skb = NULL; /* Initialize HCI device */ - hdev = hci_alloc_dev(); + hdev = hci_alloc_dev(0); if (!hdev) { BT_ERR("Can't allocate HCI device"); return -ENOMEM; diff --git a/drivers/bluetooth/btmrvl_main.c b/drivers/bluetooth/btmrvl_main.c index 8b9d78ce6bb2..0157fa4ce528 100644 --- a/drivers/bluetooth/btmrvl_main.c +++ b/drivers/bluetooth/btmrvl_main.c @@ -680,7 +680,7 @@ int btmrvl_register_hdev(struct btmrvl_private *priv) struct btmrvl_sdio_card *card = priv->btmrvl_dev.card; int ret; - hdev = hci_alloc_dev(); + hdev = hci_alloc_dev(0); if (!hdev) { BT_ERR("Can not allocate HCI device"); goto err_hdev; diff --git a/drivers/bluetooth/btmtksdio.c b/drivers/bluetooth/btmtksdio.c index 9872ef18f9fe..b48aec25c09d 100644 --- a/drivers/bluetooth/btmtksdio.c +++ b/drivers/bluetooth/btmtksdio.c @@ -959,7 +959,7 @@ static int btmtksdio_probe(struct sdio_func *func, skb_queue_head_init(&bdev->txq); /* Initialize and register HCI device */ - hdev = hci_alloc_dev(); + hdev = hci_alloc_dev(0); if (!hdev) { dev_err(&func->dev, "Can't allocate HCI device\n"); return -ENOMEM; diff --git a/drivers/bluetooth/btmtkuart.c b/drivers/bluetooth/btmtkuart.c index e9d91d7c0db4..96ee364507c5 100644 --- a/drivers/bluetooth/btmtkuart.c +++ b/drivers/bluetooth/btmtkuart.c @@ -987,7 +987,7 @@ static int btmtkuart_probe(struct serdev_device *serdev) skb_queue_head_init(&bdev->txq); /* Initialize and register HCI device */ - hdev = hci_alloc_dev(); + hdev = hci_alloc_dev(0); if (!hdev) { dev_err(&serdev->dev, "Can't allocate HCI device\n"); return -ENOMEM; diff --git a/drivers/bluetooth/btqcomsmd.c b/drivers/bluetooth/btqcomsmd.c index 2acb719e596f..47aaffceb8c1 100644 --- a/drivers/bluetooth/btqcomsmd.c +++ b/drivers/bluetooth/btqcomsmd.c @@ -147,7 +147,7 @@ static int btqcomsmd_probe(struct platform_device *pdev) goto destroy_acl_channel; } - hdev = hci_alloc_dev(); + hdev = hci_alloc_dev(0); if (!hdev) { ret = -ENOMEM; goto destroy_cmd_channel; diff --git a/drivers/bluetooth/btrsi.c b/drivers/bluetooth/btrsi.c index 8646b6dd11e9..2f8d186e4807 100644 --- a/drivers/bluetooth/btrsi.c +++ b/drivers/bluetooth/btrsi.c @@ -121,7 +121,7 @@ static int rsi_hci_attach(void *priv, struct rsi_proto_ops *ops) ops->set_bt_context(priv, h_adapter); h_adapter->proto_ops = ops; - hdev = hci_alloc_dev(); + hdev = hci_alloc_dev(0); if (!hdev) { BT_ERR("Failed to alloc HCI device"); goto err; diff --git a/drivers/bluetooth/btsdio.c b/drivers/bluetooth/btsdio.c index 199e8f7d426d..69d2a26ed5db 100644 --- a/drivers/bluetooth/btsdio.c +++ b/drivers/bluetooth/btsdio.c @@ -310,7 +310,7 @@ static int btsdio_probe(struct sdio_func *func, skb_queue_head_init(&data->txq); - hdev = hci_alloc_dev(); + hdev = hci_alloc_dev(0); if (!hdev) return -ENOMEM; diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index 1876a960b3dc..baf0934657d8 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -4575,7 +4575,7 @@ static int btusb_probe(struct usb_interface *intf, data->recv_bulk = btusb_recv_bulk; } - hdev = hci_alloc_dev(); + hdev = hci_alloc_dev(0); if (!hdev) return -ENOMEM; diff --git a/drivers/bluetooth/dtl1_cs.c b/drivers/bluetooth/dtl1_cs.c index 2adfe4fade76..f06c8151f0ea 100644 --- a/drivers/bluetooth/dtl1_cs.c +++ b/drivers/bluetooth/dtl1_cs.c @@ -449,7 +449,7 @@ static int dtl1_open(struct dtl1_info *info) set_bit(XMIT_WAITING, &(info->tx_state)); /* Initialize HCI device */ - hdev = hci_alloc_dev(); + hdev = hci_alloc_dev(0); if (!hdev) { BT_ERR("Can't allocate HCI device"); return -ENOMEM; diff --git a/drivers/bluetooth/hci_ldisc.c b/drivers/bluetooth/hci_ldisc.c index 5ed2cfa7da1d..89eb9d7685ae 100644 --- a/drivers/bluetooth/hci_ldisc.c +++ b/drivers/bluetooth/hci_ldisc.c @@ -627,7 +627,7 @@ static int hci_uart_register_dev(struct hci_uart *hu) BT_DBG(""); /* Initialize and register HCI device */ - hdev = hci_alloc_dev(); + hdev = hci_alloc_dev(0); if (!hdev) { BT_ERR("Can't allocate HCI device"); return -ENOMEM; diff --git a/drivers/bluetooth/hci_serdev.c b/drivers/bluetooth/hci_serdev.c index 3b00d82d36cf..327fa2ecc5e7 100644 --- a/drivers/bluetooth/hci_serdev.c +++ b/drivers/bluetooth/hci_serdev.c @@ -313,7 +313,7 @@ int hci_uart_register_device(struct hci_uart *hu, set_bit(HCI_UART_PROTO_READY, &hu->flags); /* Initialize and register HCI device */ - hdev = hci_alloc_dev(); + hdev = hci_alloc_dev(0); if (!hdev) { BT_ERR("Can't allocate HCI device"); err = -ENOMEM; diff --git a/drivers/bluetooth/hci_vhci.c b/drivers/bluetooth/hci_vhci.c index 8ab26dec5f6e..5486aa3945da 100644 --- a/drivers/bluetooth/hci_vhci.c +++ b/drivers/bluetooth/hci_vhci.c @@ -96,7 +96,7 @@ static int __vhci_create_device(struct vhci_data *data, __u8 opcode) if (!skb) return -ENOMEM; - hdev = hci_alloc_dev(); + hdev = hci_alloc_dev(0); if (!hdev) { kfree_skb(skb); return -ENOMEM; diff --git a/drivers/bluetooth/virtio_bt.c b/drivers/bluetooth/virtio_bt.c index 57908ce4fae8..28576ec4860e 100644 --- a/drivers/bluetooth/virtio_bt.c +++ b/drivers/bluetooth/virtio_bt.c @@ -283,7 +283,7 @@ static int virtbt_probe(struct virtio_device *vdev) if (err) return err; - hdev = hci_alloc_dev(); + hdev = hci_alloc_dev(0); if (!hdev) { err = -ENOMEM; goto failed; diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index a53e94459ecd..5c689c5dc089 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -1223,10 +1223,15 @@ static inline void hci_set_drvdata(struct hci_dev *hdev, void *data) dev_set_drvdata(&hdev->dev, data); } +static inline void *hci_get_priv(struct hci_dev *hdev) +{ + return (char *)hdev + sizeof(*hdev); +} + struct hci_dev *hci_dev_get(int index); struct hci_dev *hci_get_route(bdaddr_t *dst, bdaddr_t *src, u8 src_type); -struct hci_dev *hci_alloc_dev(void); +struct hci_dev *hci_alloc_dev(int sizeof_priv); void hci_free_dev(struct hci_dev *hdev); int hci_register_dev(struct hci_dev *hdev); void hci_unregister_dev(struct hci_dev *hdev); diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 2560ed2f144d..66b72c7efa3d 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -3751,11 +3751,18 @@ static int hci_suspend_notifier(struct notifier_block *nb, unsigned long action, } /* Alloc HCI device */ -struct hci_dev *hci_alloc_dev(void) +struct hci_dev *hci_alloc_dev(int sizeof_priv) { struct hci_dev *hdev; + unsigned int alloc_size; - hdev = kzalloc(sizeof(*hdev), GFP_KERNEL); + alloc_size = sizeof(*hdev); + if (sizeof_priv) { + /* Fixme: May need ALIGN-ment? */ + alloc_size += sizeof_priv; + } + + hdev = kzalloc(alloc_size, GFP_KERNEL); if (!hdev) return NULL; From patchwork Tue Jul 27 23:51:18 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tedd Ho-Jeong An X-Patchwork-Id: 12404671 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.7 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 0F57FC432BE for ; Tue, 27 Jul 2021 23:51:45 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id E6A8760FC0 for ; Tue, 27 Jul 2021 23:51:44 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232963AbhG0Xvo (ORCPT ); Tue, 27 Jul 2021 19:51:44 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37194 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232883AbhG0Xvn (ORCPT ); Tue, 27 Jul 2021 19:51:43 -0400 Received: from mail-pl1-x635.google.com (mail-pl1-x635.google.com [IPv6:2607:f8b0:4864:20::635]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 51747C061760 for ; Tue, 27 Jul 2021 16:51:42 -0700 (PDT) Received: by mail-pl1-x635.google.com with SMTP id n10so481353plf.4 for ; Tue, 27 Jul 2021 16:51:42 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=ujv8xZH/VDjMO2Ul6piiScZ73Az6pJDrbgCUWoOkWrU=; b=mrb8bflPohHwodSl0tJjpW5Vt6H7ySlQqPfy8GpoIJW5iRxc+bjJDVCkkHkcyQJLlD YuPHL2APipq5jmD5Qu9RTzCL1kEXznna3eDWjoCpnsFDu0RATcV9/DJYT6brsyv3r3RS dT/K1Dw8RgR2mo/2xLvUdsgO1F0Ow5wDBAdx0BSP09tnw0l9B3qV3seXtw+OengeZMm3 X0e7/d+gWgOqB13iAg0A9ezgBIYZIMawLrmQLVO8i9Y+xKOq5uJoHhfTp2edHpxa687J 0y+vlVf4XkAW6/6NlI02OOdW4XyR9VJFo82MPk1TVU66yYNBqKNjMVt1htKDjpAxJ+w2 ghOQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=ujv8xZH/VDjMO2Ul6piiScZ73Az6pJDrbgCUWoOkWrU=; b=O4cVDc+TFgpQNemrjA6mkVx091Pd+lPg8ibzy/vAqeyyJZxcpI7qA05o823qSvuf3s kiuQQRcDU+0GH2iKOzdF6hTdGPG6PdcoXch8QLU8X1Ils704irw8bh9gITXpeaHTEH96 iXQd3WLUi427QtxXMFrCUCCeGwA9ZM7gD4HP71/TmXTuASUOr3VBo33IkwOISkoNewIa YBtXF5j2F+Y7H0NMuiwBInzZzETvhkYp9Ij7Bt2qhSfxwPNmw8uVfm6Db9YVnwbYb9EZ qCW3YlH/eV7lw8mlzm6NmFcyiDR5pm0Fu0IQe+6FbvSTFa8aX0/ScrLQwIFvueFW0MV5 WFsg== X-Gm-Message-State: AOAM532xMycLLNE9+CD36Pp1QflW6NzzWwNjBviE6qD7a54/p/cxVYUv dhMc320PMHBkdBafJEglxvqwdb3qEYs= X-Google-Smtp-Source: ABdhPJyiCOHiqIWuD/ctL80aodPjv7Ak14P+l84wywpNaD4pd/0NCaQK+vE+mgN2cGIJfaE28Yz68w== X-Received: by 2002:a17:902:8e88:b029:11e:b703:83f1 with SMTP id bg8-20020a1709028e88b029011eb70383f1mr20435389plb.79.1627429901598; Tue, 27 Jul 2021 16:51:41 -0700 (PDT) Received: from localhost.localdomain ([2601:1c0:6a01:d830::7cb2]) by smtp.gmail.com with ESMTPSA id y9sm1545332pfq.199.2021.07.27.16.51.40 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 27 Jul 2021 16:51:41 -0700 (PDT) From: Tedd Ho-Jeong An To: linux-bluetooth@vger.kernel.org Cc: Tedd Ho-Jeong An Subject: [RFC PATCH v4 02/11] Bluetooth: btintel: Add combined setup and shutdown functions Date: Tue, 27 Jul 2021 16:51:18 -0700 Message-Id: <20210727235127.173149-3-hj.tedd.an@gmail.com> X-Mailer: git-send-email 2.26.3 In-Reply-To: <20210727235127.173149-1-hj.tedd.an@gmail.com> References: <20210727235127.173149-1-hj.tedd.an@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-bluetooth@vger.kernel.org From: Tedd Ho-Jeong An There are multiple setup and shutdown functions for Intel device and the setup function to use is depends on the USB PID/VID, which makes difficult to maintain the code and increases the code size. This patch adds combined setup and shutdown functions to provide a single entry point for all Intel devices and choose the setup functions based on the information read with HCI_Intel_Read_Version command. Starting from TyP device, for HCI_Intel_Read_Version command, the command parameter and response are changed even though OCF remains same. Luckly the legacy devices still can handle the command without error even if it has a extra parameter, so it uses the new command format to support both legacy and new (tlv based) format. Signed-off-by: Tedd Ho-Jeong An --- drivers/bluetooth/btintel.c | 196 ++++++++++++++++++++++++++++++++++++ drivers/bluetooth/btintel.h | 12 +++ 2 files changed, 208 insertions(+) diff --git a/drivers/bluetooth/btintel.c b/drivers/bluetooth/btintel.c index e44b6993cf91..a23304435814 100644 --- a/drivers/bluetooth/btintel.c +++ b/drivers/bluetooth/btintel.c @@ -236,6 +236,8 @@ int btintel_version_info(struct hci_dev *hdev, struct intel_version *ver) * compatibility options when newer hardware variants come along. */ switch (ver->hw_variant) { + case 0x07: /* WP - Legacy ROM */ + case 0x08: /* StP - Legacy ROM */ case 0x0b: /* SfP */ case 0x0c: /* WsP */ case 0x11: /* JfP */ @@ -250,9 +252,15 @@ int btintel_version_info(struct hci_dev *hdev, struct intel_version *ver) } switch (ver->fw_variant) { + case 0x01: + variant = "Legacy ROM 2.5"; + break; case 0x06: variant = "Bootloader"; break; + case 0x22: + variant = "Legacy ROM 2.x"; + break; case 0x23: variant = "Firmware"; break; @@ -483,6 +491,98 @@ int btintel_version_info_tlv(struct hci_dev *hdev, struct intel_version_tlv *ver } EXPORT_SYMBOL_GPL(btintel_version_info_tlv); +static int btintel_parse_version_tlv(struct hci_dev *hdev, + struct intel_version_tlv *version, + struct sk_buff *skb) +{ + /* Consume Command Complete Status field */ + skb_pull(skb, 1); + + /* Event parameters contatin multiple TLVs. Read each of them + * and only keep the required data. Also, it use existing legacy + * version field like hw_platform, hw_variant, and fw_variant + * to keep the existing setup flow + */ + while (skb->len) { + struct intel_tlv *tlv; + + tlv = (struct intel_tlv *)skb->data; + switch (tlv->type) { + case INTEL_TLV_CNVI_TOP: + version->cnvi_top = get_unaligned_le32(tlv->val); + break; + case INTEL_TLV_CNVR_TOP: + version->cnvr_top = get_unaligned_le32(tlv->val); + break; + case INTEL_TLV_CNVI_BT: + version->cnvi_bt = get_unaligned_le32(tlv->val); + break; + case INTEL_TLV_CNVR_BT: + version->cnvr_bt = get_unaligned_le32(tlv->val); + break; + case INTEL_TLV_DEV_REV_ID: + version->dev_rev_id = get_unaligned_le16(tlv->val); + break; + case INTEL_TLV_IMAGE_TYPE: + version->img_type = tlv->val[0]; + break; + case INTEL_TLV_TIME_STAMP: + /* If image type is Operational firmware (0x03), then + * running FW Calendar Week and Year information can + * be extracted from Timestamp information + */ + version->min_fw_build_cw = tlv->val[0]; + version->min_fw_build_yy = tlv->val[1]; + version->timestamp = get_unaligned_le16(tlv->val); + break; + case INTEL_TLV_BUILD_TYPE: + version->build_type = tlv->val[0]; + break; + case INTEL_TLV_BUILD_NUM: + /* If image type is Operational firmware (0x03), then + * running FW build number can be extracted from the + * Build information + */ + version->min_fw_build_nn = tlv->val[0]; + version->build_num = get_unaligned_le32(tlv->val); + break; + case INTEL_TLV_SECURE_BOOT: + version->secure_boot = tlv->val[0]; + break; + case INTEL_TLV_OTP_LOCK: + version->otp_lock = tlv->val[0]; + break; + case INTEL_TLV_API_LOCK: + version->api_lock = tlv->val[0]; + break; + case INTEL_TLV_DEBUG_LOCK: + version->debug_lock = tlv->val[0]; + break; + case INTEL_TLV_MIN_FW: + version->min_fw_build_nn = tlv->val[0]; + version->min_fw_build_cw = tlv->val[1]; + version->min_fw_build_yy = tlv->val[2]; + break; + case INTEL_TLV_LIMITED_CCE: + version->limited_cce = tlv->val[0]; + break; + case INTEL_TLV_SBE_TYPE: + version->sbe_type = tlv->val[0]; + break; + case INTEL_TLV_OTP_BDADDR: + memcpy(&version->otp_bd_addr, tlv->val, tlv->len); + break; + default: + /* Ignore rest of information */ + break; + } + /* consume the current tlv and move to next*/ + skb_pull(skb, tlv->len + sizeof(*tlv)); + } + + return 0; +} + int btintel_read_version_tlv(struct hci_dev *hdev, struct intel_version_tlv *version) { struct sk_buff *skb; @@ -1272,6 +1372,102 @@ int btintel_set_debug_features(struct hci_dev *hdev, } EXPORT_SYMBOL_GPL(btintel_set_debug_features); +int btintel_setup_combined(struct hci_dev *hdev) +{ + const u8 param[1] = { 0xFF }; + struct intel_version ver; + struct intel_version_tlv ver_tlv; + struct sk_buff *skb; + int err; + + BT_DBG("%s", hdev->name); + + /* Starting from TyP device, the command parameter and response are + * changed even though the OCF for HCI_Intel_Read_Version command + * remains same. The legacy devices can handle even if the + * command has a parameter and returns a correct version information. + * So, it uses new format to support both legacy and new format. + */ + skb = __hci_cmd_sync(hdev, 0xfc05, 1, param, HCI_CMD_TIMEOUT); + if (IS_ERR(skb)) { + bt_dev_err(hdev, "Reading Intel version command failed (%ld)", + PTR_ERR(skb)); + return PTR_ERR(skb); + } + + /* Check the status */ + if (skb->data[0]) { + bt_dev_err(hdev, "Intel Read Version command failed (%02x)", + skb->data[0]); + kfree_skb(skb); + return -EIO; + } + + /* For Legacy device, check the HW platform value and size */ + if (skb->data[1] == 0x37 && skb->len == sizeof(ver)) { + bt_dev_dbg(hdev, "Read the legacy Intel version information"); + + memcpy(&ver, skb->data, sizeof(ver)); + + /* Display version information */ + btintel_version_info(hdev, &ver); + + /* Identify the device type based on the read version */ + switch (ver.hw_variant) { + case 0x07: /* WP */ + case 0x08: /* StP */ + /* Legacy ROM product */ + /* TODO: call setup routine for legacy rom product */ + break; + case 0x0b: /* SfP */ + case 0x0c: /* WsP */ + case 0x11: /* JfP */ + case 0x12: /* ThP */ + case 0x13: /* HrP */ + case 0x14: /* CcP */ + /* TODO: call setup routine for bootloader product */ + break; + default: + bt_dev_err(hdev, "Unsupported Intel hw variant (%u)", + ver.hw_variant); + return -EINVAL; + } + + return err; + } + + /* For TLV type device, parse the tlv data */ + btintel_parse_version_tlv(hdev, &ver_tlv, skb); + + /* Display version information of TLV type */ + btintel_version_info_tlv(hdev, &ver_tlv); + + /* TODO: Need to filter the device for new generation */ + /* TODO: call setup routine for tlv based bootloader product */ + + return err; +} +EXPORT_SYMBOL_GPL(btintel_setup_combined); + +int btintel_shutdown_combined(struct hci_dev *hdev) +{ + struct sk_buff *skb; + + /* Send HCI Reset to the controller to stop any BT activity which + * were triggered. This will help to save power and maintain the + * sync b/w Host and controller + */ + skb = __hci_cmd_sync(hdev, HCI_OP_RESET, 0, NULL, HCI_INIT_TIMEOUT); + if (IS_ERR(skb)) { + bt_dev_err(hdev, "HCI reset during shutdown failed"); + return PTR_ERR(skb); + } + kfree_skb(skb); + + return 0; +} +EXPORT_SYMBOL_GPL(btintel_shutdown_combined); + MODULE_AUTHOR("Marcel Holtmann "); MODULE_DESCRIPTION("Bluetooth support for Intel devices ver " VERSION); MODULE_VERSION(VERSION); diff --git a/drivers/bluetooth/btintel.h b/drivers/bluetooth/btintel.h index d184064a5e7c..68ffa84fa87a 100644 --- a/drivers/bluetooth/btintel.h +++ b/drivers/bluetooth/btintel.h @@ -165,6 +165,8 @@ int btintel_read_boot_params(struct hci_dev *hdev, struct intel_boot_params *params); int btintel_download_firmware(struct hci_dev *dev, struct intel_version *ver, const struct firmware *fw, u32 *boot_param); +int btintel_setup_combined(struct hci_dev *hdev); +int btintel_shutdown_combined(struct hci_dev *hdev); int btintel_download_firmware_newgen(struct hci_dev *hdev, struct intel_version_tlv *ver, const struct firmware *fw, @@ -283,6 +285,16 @@ static inline int btintel_download_firmware(struct hci_dev *dev, return -EOPNOTSUPP; } +static inline int btintel_setup_combined(struct hci_dev *hdev) +{ + return -EOPNOTSUPP; +} + +static inline int btintel_shutdown_combined(struct hci_dev *hdev) +{ + return -EOPNOTSUPP; +} + static inline int btintel_download_firmware_newgen(struct hci_dev *hdev, const struct firmware *fw, u32 *boot_param, From patchwork Tue Jul 27 23:51:19 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tedd Ho-Jeong An X-Patchwork-Id: 12404673 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.7 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 8A333C4320A for ; Tue, 27 Jul 2021 23:51:46 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 68BB960F93 for ; Tue, 27 Jul 2021 23:51:46 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233132AbhG0Xvp (ORCPT ); Tue, 27 Jul 2021 19:51:45 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37196 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232983AbhG0Xvo (ORCPT ); Tue, 27 Jul 2021 19:51:44 -0400 Received: from mail-pj1-x1036.google.com (mail-pj1-x1036.google.com [IPv6:2607:f8b0:4864:20::1036]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 1A544C061757 for ; Tue, 27 Jul 2021 16:51:43 -0700 (PDT) Received: by mail-pj1-x1036.google.com with SMTP id b6so2383414pji.4 for ; Tue, 27 Jul 2021 16:51:43 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=uybIKVPM4hp9SywafLYCli1GHjZzX15ud3br2iWGeUU=; b=H87g7gerkRMb824X13goNJ95X97gh92MvaYYiVt7GvKiTarlh6U6DeeeCY4Hf7ozvi 4KedmNoLI8Z0HrCNR5XNGZxZXjUTQAH0HOy368w8zEgXwsHH5WRW8xDlzMAhl2zSYN6N l9HhmJvLnNsPH2NJculFVaNQFSj5jhqfC0wv+n/7iLODmXI6wiI2G32efZpWXXMqgDQf oHxNnzhFr4uVhluwKiCZ7w48ZhXboWllD+wXk04s3ERqXbEgGAfjVVEMIut0gZH67cLz ylt7sfqsau98Jxbw+60xwWaxyMW3tHGKPWftRI/Xa1rcqUsa2QAVv22bU1z+vwIfDokZ qa7A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=uybIKVPM4hp9SywafLYCli1GHjZzX15ud3br2iWGeUU=; b=Wq0mYstBTni/pO3JlwGORvR6AYk5pqSFLcoCEOjni3RtRjlC3eJDfThoPdteJyCjFw CfSYjewZd7zBk8sVdCoryRQCCRQoT1dJWm8D88as/f1aZH0schRHRfY2qX9egqS6swK/ NHCAkr+y6jSPLVdvaejN4zdn+LQbuz6225m9rp0mZdVwxbY+Tu1tZtN8kQsGx/FHooJ1 OGHjXJ+yYpThsSDDKfR/bIUjtgvTQD9mOb2vygDZ1TLCDsHPwO/YBBUGUiYzR+8eAQEp b9owS6Tk3s/WxtPErJ95M5+o6JOLAPAJhV7AMiOG1Wr2N1Qi7WWpXQ/X5oXJiv0nFHPF XebQ== X-Gm-Message-State: AOAM532T3BEo2xPmU/FwHX5ZXSyp7+ppIQIHZgQuPGev0+sfvgL3vRtt 2AQhIuv4uXeZTIQ5V1ME2aPxpnJV7jw= X-Google-Smtp-Source: ABdhPJz/IApKKAXYV1p0M/DJZRkdTvbBcH9wptfn69axHrO/LjuTqYUJA5YreaM9BcZ2g/cWUBHg+A== X-Received: by 2002:a05:6a00:882:b029:354:a616:7fbb with SMTP id q2-20020a056a000882b0290354a6167fbbmr25209422pfj.2.1627429902258; Tue, 27 Jul 2021 16:51:42 -0700 (PDT) Received: from localhost.localdomain ([2601:1c0:6a01:d830::7cb2]) by smtp.gmail.com with ESMTPSA id y9sm1545332pfq.199.2021.07.27.16.51.41 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 27 Jul 2021 16:51:41 -0700 (PDT) From: Tedd Ho-Jeong An To: linux-bluetooth@vger.kernel.org Cc: Tedd Ho-Jeong An Subject: [RFC PATCH v4 03/11] Bluetooth: btintel: Refactoring setup routine for legacy ROM sku Date: Tue, 27 Jul 2021 16:51:19 -0700 Message-Id: <20210727235127.173149-4-hj.tedd.an@gmail.com> X-Mailer: git-send-email 2.26.3 In-Reply-To: <20210727235127.173149-1-hj.tedd.an@gmail.com> References: <20210727235127.173149-1-hj.tedd.an@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-bluetooth@vger.kernel.org From: Tedd Ho-Jeong An This patch refactors the setup routines for legacy ROM product into combined setup, and move the related functions from btusb to btintel. Signed-off-by: Tedd Ho-Jeong An --- drivers/bluetooth/btintel.c | 287 +++++++++++++++++++++++++++- drivers/bluetooth/btusb.c | 362 +----------------------------------- 2 files changed, 294 insertions(+), 355 deletions(-) diff --git a/drivers/bluetooth/btintel.c b/drivers/bluetooth/btintel.c index a23304435814..cfc097694b53 100644 --- a/drivers/bluetooth/btintel.c +++ b/drivers/bluetooth/btintel.c @@ -1372,6 +1372,291 @@ int btintel_set_debug_features(struct hci_dev *hdev, } EXPORT_SYMBOL_GPL(btintel_set_debug_features); +static const struct firmware *btintel_legacy_rom_get_fw(struct hci_dev *hdev, + struct intel_version *ver) +{ + const struct firmware *fw; + char fwname[64]; + int ret; + + snprintf(fwname, sizeof(fwname), + "intel/ibt-hw-%x.%x.%x-fw-%x.%x.%x.%x.%x.bseq", + ver->hw_platform, ver->hw_variant, ver->hw_revision, + ver->fw_variant, ver->fw_revision, ver->fw_build_num, + ver->fw_build_ww, ver->fw_build_yy); + + ret = request_firmware(&fw, fwname, &hdev->dev); + if (ret < 0) { + if (ret == -EINVAL) { + bt_dev_err(hdev, "Intel firmware file request failed (%d)", + ret); + return NULL; + } + + bt_dev_err(hdev, "failed to open Intel firmware file: %s (%d)", + fwname, ret); + + /* If the correct firmware patch file is not found, use the + * default firmware patch file instead + */ + snprintf(fwname, sizeof(fwname), "intel/ibt-hw-%x.%x.bseq", + ver->hw_platform, ver->hw_variant); + if (request_firmware(&fw, fwname, &hdev->dev) < 0) { + bt_dev_err(hdev, "failed to open default fw file: %s", + fwname); + return NULL; + } + } + + bt_dev_info(hdev, "Intel Bluetooth firmware file: %s", fwname); + + return fw; +} + +static int btintel_legacy_rom_patching(struct hci_dev *hdev, + const struct firmware *fw, + const u8 **fw_ptr, int *disable_patch) +{ + struct sk_buff *skb; + struct hci_command_hdr *cmd; + const u8 *cmd_param; + struct hci_event_hdr *evt = NULL; + const u8 *evt_param = NULL; + int remain = fw->size - (*fw_ptr - fw->data); + + /* The first byte indicates the types of the patch command or event. + * 0x01 means HCI command and 0x02 is HCI event. If the first bytes + * in the current firmware buffer doesn't start with 0x01 or + * the size of remain buffer is smaller than HCI command header, + * the firmware file is corrupted and it should stop the patching + * process. + */ + if (remain > HCI_COMMAND_HDR_SIZE && *fw_ptr[0] != 0x01) { + bt_dev_err(hdev, "Intel fw corrupted: invalid cmd read"); + return -EINVAL; + } + (*fw_ptr)++; + remain--; + + cmd = (struct hci_command_hdr *)(*fw_ptr); + *fw_ptr += sizeof(*cmd); + remain -= sizeof(*cmd); + + /* Ensure that the remain firmware data is long enough than the length + * of command parameter. If not, the firmware file is corrupted. + */ + if (remain < cmd->plen) { + bt_dev_err(hdev, "Intel fw corrupted: invalid cmd len"); + return -EFAULT; + } + + /* If there is a command that loads a patch in the firmware + * file, then enable the patch upon success, otherwise just + * disable the manufacturer mode, for example patch activation + * is not required when the default firmware patch file is used + * because there are no patch data to load. + */ + if (*disable_patch && le16_to_cpu(cmd->opcode) == 0xfc8e) + *disable_patch = 0; + + cmd_param = *fw_ptr; + *fw_ptr += cmd->plen; + remain -= cmd->plen; + + /* This reads the expected events when the above command is sent to the + * device. Some vendor commands expects more than one events, for + * example command status event followed by vendor specific event. + * For this case, it only keeps the last expected event. so the command + * can be sent with __hci_cmd_sync_ev() which returns the sk_buff of + * last expected event. + */ + while (remain > HCI_EVENT_HDR_SIZE && *fw_ptr[0] == 0x02) { + (*fw_ptr)++; + remain--; + + evt = (struct hci_event_hdr *)(*fw_ptr); + *fw_ptr += sizeof(*evt); + remain -= sizeof(*evt); + + if (remain < evt->plen) { + bt_dev_err(hdev, "Intel fw corrupted: invalid evt len"); + return -EFAULT; + } + + evt_param = *fw_ptr; + *fw_ptr += evt->plen; + remain -= evt->plen; + } + + /* Every HCI commands in the firmware file has its correspond event. + * If event is not found or remain is smaller than zero, the firmware + * file is corrupted. + */ + if (!evt || !evt_param || remain < 0) { + bt_dev_err(hdev, "Intel fw corrupted: invalid evt read"); + return -EFAULT; + } + + skb = __hci_cmd_sync_ev(hdev, le16_to_cpu(cmd->opcode), cmd->plen, + cmd_param, evt->evt, HCI_INIT_TIMEOUT); + if (IS_ERR(skb)) { + bt_dev_err(hdev, "sending Intel patch command (0x%4.4x) failed (%ld)", + cmd->opcode, PTR_ERR(skb)); + return PTR_ERR(skb); + } + + /* It ensures that the returned event matches the event data read from + * the firmware file. At fist, it checks the length and then + * the contents of the event. + */ + if (skb->len != evt->plen) { + bt_dev_err(hdev, "mismatch event length (opcode 0x%4.4x)", + le16_to_cpu(cmd->opcode)); + kfree_skb(skb); + return -EFAULT; + } + + if (memcmp(skb->data, evt_param, evt->plen)) { + bt_dev_err(hdev, "mismatch event parameter (opcode 0x%4.4x)", + le16_to_cpu(cmd->opcode)); + kfree_skb(skb); + return -EFAULT; + } + kfree_skb(skb); + + return 0; +} + +static int btintel_legacy_rom_setup(struct hci_dev *hdev, + struct intel_version *ver) +{ + const struct firmware *fw; + const u8 *fw_ptr; + int disable_patch, err; + struct intel_version new_ver; + + BT_DBG("%s", hdev->name); + + /* fw_patch_num indicates the version of patch the device currently + * have. If there is no patch data in the device, it is always 0x00. + * So, if it is other than 0x00, no need to patch the device again. + */ + if (ver->fw_patch_num) { + bt_dev_info(hdev, + "Intel device is already patched. patch num: %02x", + ver->fw_patch_num); + goto complete; + } + + /* Opens the firmware patch file based on the firmware version read + * from the controller. If it fails to open the matching firmware + * patch file, it tries to open the default firmware patch file. + * If no patch file is found, allow the device to operate without + * a patch. + */ + fw = btintel_legacy_rom_get_fw(hdev, ver); + if (!fw) + goto complete; + fw_ptr = fw->data; + + /* Enable the manufacturer mode of the controller. + * Only while this mode is enabled, the driver can download the + * firmware patch data and configuration parameters. + */ + err = btintel_enter_mfg(hdev); + if (err) { + release_firmware(fw); + return err; + } + + disable_patch = 1; + + /* The firmware data file consists of list of Intel specific HCI + * commands and its expected events. The first byte indicates the + * type of the message, either HCI command or HCI event. + * + * It reads the command and its expected event from the firmware file, + * and send to the controller. Once __hci_cmd_sync_ev() returns, + * the returned event is compared with the event read from the firmware + * file and it will continue until all the messages are downloaded to + * the controller. + * + * Once the firmware patching is completed successfully, + * the manufacturer mode is disabled with reset and activating the + * downloaded patch. + * + * If the firmware patching fails, the manufacturer mode is + * disabled with reset and deactivating the patch. + * + * If the default patch file is used, no reset is done when disabling + * the manufacturer. + */ + while (fw->size > fw_ptr - fw->data) { + int ret; + + ret = btintel_legacy_rom_patching(hdev, fw, &fw_ptr, + &disable_patch); + if (ret < 0) + goto exit_mfg_deactivate; + } + + release_firmware(fw); + + if (disable_patch) + goto exit_mfg_disable; + + /* Patching completed successfully and disable the manufacturer mode + * with reset and activate the downloaded firmware patches. + */ + err = btintel_exit_mfg(hdev, true, true); + if (err) + return err; + + /* Need build number for downloaded fw patches in + * every power-on boot + */ + err = btintel_read_version(hdev, &new_ver); + if (err) + return err; + + bt_dev_info(hdev, "Intel BT fw patch 0x%02x completed & activated", + new_ver.fw_patch_num); + + goto complete; + +exit_mfg_disable: + /* Disable the manufacturer mode without reset */ + err = btintel_exit_mfg(hdev, false, false); + if (err) + return err; + + bt_dev_info(hdev, "Intel firmware patch completed"); + + goto complete; + +exit_mfg_deactivate: + release_firmware(fw); + + /* Patching failed. Disable the manufacturer mode with reset and + * deactivate the downloaded firmware patches. + */ + err = btintel_exit_mfg(hdev, true, false); + if (err) + return err; + + bt_dev_info(hdev, "Intel firmware patch completed and deactivated"); + +complete: + /* Set the event mask for Intel specific vendor events. This enables + * a few extra events that are useful during general operation. + */ + btintel_set_event_mask_mfg(hdev, false); + + btintel_check_bdaddr(hdev); + + return 0; +} + int btintel_setup_combined(struct hci_dev *hdev) { const u8 param[1] = { 0xFF }; @@ -1417,7 +1702,7 @@ int btintel_setup_combined(struct hci_dev *hdev) case 0x07: /* WP */ case 0x08: /* StP */ /* Legacy ROM product */ - /* TODO: call setup routine for legacy rom product */ + err = btintel_legacy_rom_setup(hdev, &ver); break; case 0x0b: /* SfP */ case 0x0c: /* WsP */ diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index baf0934657d8..3382d75b1969 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -61,6 +61,7 @@ static struct usb_driver btusb_driver; #define BTUSB_VALID_LE_STATES 0x800000 #define BTUSB_QCA_WCN6855 0x1000000 #define BTUSB_INTEL_NEWGEN 0x2000000 +#define BTUSB_INTEL_COMBINED 0x4000000 static const struct usb_device_id btusb_table[] = { /* Generic Bluetooth USB device */ @@ -375,11 +376,11 @@ static const struct usb_device_id blacklist_table[] = { BTUSB_WIDEBAND_SPEECH | BTUSB_VALID_LE_STATES }, { USB_DEVICE(0x8087, 0x07da), .driver_info = BTUSB_CSR }, - { USB_DEVICE(0x8087, 0x07dc), .driver_info = BTUSB_INTEL }, - { USB_DEVICE(0x8087, 0x0a2a), .driver_info = BTUSB_INTEL }, + { USB_DEVICE(0x8087, 0x07dc), .driver_info = BTUSB_INTEL_COMBINED }, + { USB_DEVICE(0x8087, 0x0a2a), .driver_info = BTUSB_INTEL_COMBINED }, { USB_DEVICE(0x8087, 0x0a2b), .driver_info = BTUSB_INTEL_NEW | BTUSB_WIDEBAND_SPEECH }, - { USB_DEVICE(0x8087, 0x0aa7), .driver_info = BTUSB_INTEL | + { USB_DEVICE(0x8087, 0x0aa7), .driver_info = BTUSB_INTEL_COMBINED | BTUSB_WIDEBAND_SPEECH }, { USB_DEVICE(0x8087, 0x0aaa), .driver_info = BTUSB_INTEL_NEW | BTUSB_WIDEBAND_SPEECH | @@ -1962,319 +1963,6 @@ static int btusb_setup_csr(struct hci_dev *hdev) return 0; } -static const struct firmware *btusb_setup_intel_get_fw(struct hci_dev *hdev, - struct intel_version *ver) -{ - const struct firmware *fw; - char fwname[64]; - int ret; - - snprintf(fwname, sizeof(fwname), - "intel/ibt-hw-%x.%x.%x-fw-%x.%x.%x.%x.%x.bseq", - ver->hw_platform, ver->hw_variant, ver->hw_revision, - ver->fw_variant, ver->fw_revision, ver->fw_build_num, - ver->fw_build_ww, ver->fw_build_yy); - - ret = request_firmware(&fw, fwname, &hdev->dev); - if (ret < 0) { - if (ret == -EINVAL) { - bt_dev_err(hdev, "Intel firmware file request failed (%d)", - ret); - return NULL; - } - - bt_dev_err(hdev, "failed to open Intel firmware file: %s (%d)", - fwname, ret); - - /* If the correct firmware patch file is not found, use the - * default firmware patch file instead - */ - snprintf(fwname, sizeof(fwname), "intel/ibt-hw-%x.%x.bseq", - ver->hw_platform, ver->hw_variant); - if (request_firmware(&fw, fwname, &hdev->dev) < 0) { - bt_dev_err(hdev, "failed to open default fw file: %s", - fwname); - return NULL; - } - } - - bt_dev_info(hdev, "Intel Bluetooth firmware file: %s", fwname); - - return fw; -} - -static int btusb_setup_intel_patching(struct hci_dev *hdev, - const struct firmware *fw, - const u8 **fw_ptr, int *disable_patch) -{ - struct sk_buff *skb; - struct hci_command_hdr *cmd; - const u8 *cmd_param; - struct hci_event_hdr *evt = NULL; - const u8 *evt_param = NULL; - int remain = fw->size - (*fw_ptr - fw->data); - - /* The first byte indicates the types of the patch command or event. - * 0x01 means HCI command and 0x02 is HCI event. If the first bytes - * in the current firmware buffer doesn't start with 0x01 or - * the size of remain buffer is smaller than HCI command header, - * the firmware file is corrupted and it should stop the patching - * process. - */ - if (remain > HCI_COMMAND_HDR_SIZE && *fw_ptr[0] != 0x01) { - bt_dev_err(hdev, "Intel fw corrupted: invalid cmd read"); - return -EINVAL; - } - (*fw_ptr)++; - remain--; - - cmd = (struct hci_command_hdr *)(*fw_ptr); - *fw_ptr += sizeof(*cmd); - remain -= sizeof(*cmd); - - /* Ensure that the remain firmware data is long enough than the length - * of command parameter. If not, the firmware file is corrupted. - */ - if (remain < cmd->plen) { - bt_dev_err(hdev, "Intel fw corrupted: invalid cmd len"); - return -EFAULT; - } - - /* If there is a command that loads a patch in the firmware - * file, then enable the patch upon success, otherwise just - * disable the manufacturer mode, for example patch activation - * is not required when the default firmware patch file is used - * because there are no patch data to load. - */ - if (*disable_patch && le16_to_cpu(cmd->opcode) == 0xfc8e) - *disable_patch = 0; - - cmd_param = *fw_ptr; - *fw_ptr += cmd->plen; - remain -= cmd->plen; - - /* This reads the expected events when the above command is sent to the - * device. Some vendor commands expects more than one events, for - * example command status event followed by vendor specific event. - * For this case, it only keeps the last expected event. so the command - * can be sent with __hci_cmd_sync_ev() which returns the sk_buff of - * last expected event. - */ - while (remain > HCI_EVENT_HDR_SIZE && *fw_ptr[0] == 0x02) { - (*fw_ptr)++; - remain--; - - evt = (struct hci_event_hdr *)(*fw_ptr); - *fw_ptr += sizeof(*evt); - remain -= sizeof(*evt); - - if (remain < evt->plen) { - bt_dev_err(hdev, "Intel fw corrupted: invalid evt len"); - return -EFAULT; - } - - evt_param = *fw_ptr; - *fw_ptr += evt->plen; - remain -= evt->plen; - } - - /* Every HCI commands in the firmware file has its correspond event. - * If event is not found or remain is smaller than zero, the firmware - * file is corrupted. - */ - if (!evt || !evt_param || remain < 0) { - bt_dev_err(hdev, "Intel fw corrupted: invalid evt read"); - return -EFAULT; - } - - skb = __hci_cmd_sync_ev(hdev, le16_to_cpu(cmd->opcode), cmd->plen, - cmd_param, evt->evt, HCI_INIT_TIMEOUT); - if (IS_ERR(skb)) { - bt_dev_err(hdev, "sending Intel patch command (0x%4.4x) failed (%ld)", - cmd->opcode, PTR_ERR(skb)); - return PTR_ERR(skb); - } - - /* It ensures that the returned event matches the event data read from - * the firmware file. At fist, it checks the length and then - * the contents of the event. - */ - if (skb->len != evt->plen) { - bt_dev_err(hdev, "mismatch event length (opcode 0x%4.4x)", - le16_to_cpu(cmd->opcode)); - kfree_skb(skb); - return -EFAULT; - } - - if (memcmp(skb->data, evt_param, evt->plen)) { - bt_dev_err(hdev, "mismatch event parameter (opcode 0x%4.4x)", - le16_to_cpu(cmd->opcode)); - kfree_skb(skb); - return -EFAULT; - } - kfree_skb(skb); - - return 0; -} - -static int btusb_setup_intel(struct hci_dev *hdev) -{ - struct sk_buff *skb; - const struct firmware *fw; - const u8 *fw_ptr; - int disable_patch, err; - struct intel_version ver; - - BT_DBG("%s", hdev->name); - - /* The controller has a bug with the first HCI command sent to it - * returning number of completed commands as zero. This would stall the - * command processing in the Bluetooth core. - * - * As a workaround, send HCI Reset command first which will reset the - * number of completed commands and allow normal command processing - * from now on. - */ - skb = __hci_cmd_sync(hdev, HCI_OP_RESET, 0, NULL, HCI_INIT_TIMEOUT); - if (IS_ERR(skb)) { - bt_dev_err(hdev, "sending initial HCI reset command failed (%ld)", - PTR_ERR(skb)); - return PTR_ERR(skb); - } - kfree_skb(skb); - - /* Read Intel specific controller version first to allow selection of - * which firmware file to load. - * - * The returned information are hardware variant and revision plus - * firmware variant, revision and build number. - */ - err = btintel_read_version(hdev, &ver); - if (err) - return err; - - bt_dev_info(hdev, "read Intel version: %02x%02x%02x%02x%02x%02x%02x%02x%02x", - ver.hw_platform, ver.hw_variant, ver.hw_revision, - ver.fw_variant, ver.fw_revision, ver.fw_build_num, - ver.fw_build_ww, ver.fw_build_yy, ver.fw_patch_num); - - /* fw_patch_num indicates the version of patch the device currently - * have. If there is no patch data in the device, it is always 0x00. - * So, if it is other than 0x00, no need to patch the device again. - */ - if (ver.fw_patch_num) { - bt_dev_info(hdev, "Intel device is already patched. " - "patch num: %02x", ver.fw_patch_num); - goto complete; - } - - /* Opens the firmware patch file based on the firmware version read - * from the controller. If it fails to open the matching firmware - * patch file, it tries to open the default firmware patch file. - * If no patch file is found, allow the device to operate without - * a patch. - */ - fw = btusb_setup_intel_get_fw(hdev, &ver); - if (!fw) - goto complete; - fw_ptr = fw->data; - - /* Enable the manufacturer mode of the controller. - * Only while this mode is enabled, the driver can download the - * firmware patch data and configuration parameters. - */ - err = btintel_enter_mfg(hdev); - if (err) { - release_firmware(fw); - return err; - } - - disable_patch = 1; - - /* The firmware data file consists of list of Intel specific HCI - * commands and its expected events. The first byte indicates the - * type of the message, either HCI command or HCI event. - * - * It reads the command and its expected event from the firmware file, - * and send to the controller. Once __hci_cmd_sync_ev() returns, - * the returned event is compared with the event read from the firmware - * file and it will continue until all the messages are downloaded to - * the controller. - * - * Once the firmware patching is completed successfully, - * the manufacturer mode is disabled with reset and activating the - * downloaded patch. - * - * If the firmware patching fails, the manufacturer mode is - * disabled with reset and deactivating the patch. - * - * If the default patch file is used, no reset is done when disabling - * the manufacturer. - */ - while (fw->size > fw_ptr - fw->data) { - int ret; - - ret = btusb_setup_intel_patching(hdev, fw, &fw_ptr, - &disable_patch); - if (ret < 0) - goto exit_mfg_deactivate; - } - - release_firmware(fw); - - if (disable_patch) - goto exit_mfg_disable; - - /* Patching completed successfully and disable the manufacturer mode - * with reset and activate the downloaded firmware patches. - */ - err = btintel_exit_mfg(hdev, true, true); - if (err) - return err; - - /* Need build number for downloaded fw patches in - * every power-on boot - */ - err = btintel_read_version(hdev, &ver); - if (err) - return err; - bt_dev_info(hdev, "Intel BT fw patch 0x%02x completed & activated", - ver.fw_patch_num); - - goto complete; - -exit_mfg_disable: - /* Disable the manufacturer mode without reset */ - err = btintel_exit_mfg(hdev, false, false); - if (err) - return err; - - bt_dev_info(hdev, "Intel firmware patch completed"); - - goto complete; - -exit_mfg_deactivate: - release_firmware(fw); - - /* Patching failed. Disable the manufacturer mode with reset and - * deactivate the downloaded firmware patches. - */ - err = btintel_exit_mfg(hdev, true, false); - if (err) - return err; - - bt_dev_info(hdev, "Intel firmware patch completed and deactivated"); - -complete: - /* Set the event mask for Intel specific vendor events. This enables - * a few extra events that are useful during general operation. - */ - btintel_set_event_mask_mfg(hdev, false); - - btintel_check_bdaddr(hdev); - return 0; -} - static int inject_cmd_complete(struct hci_dev *hdev, __u16 opcode) { struct sk_buff *skb; @@ -3042,41 +2730,6 @@ static int btusb_setup_intel_newgen(struct hci_dev *hdev) return 0; } -static int btusb_shutdown_intel(struct hci_dev *hdev) -{ - struct sk_buff *skb; - long ret; - - /* In the shutdown sequence where Bluetooth is turned off followed - * by WiFi being turned off, turning WiFi back on causes issue with - * the RF calibration. - * - * To ensure that any RF activity has been stopped, issue HCI Reset - * command to clear all ongoing activity including advertising, - * scanning etc. - */ - skb = __hci_cmd_sync(hdev, HCI_OP_RESET, 0, NULL, HCI_INIT_TIMEOUT); - if (IS_ERR(skb)) { - ret = PTR_ERR(skb); - bt_dev_err(hdev, "HCI reset during shutdown failed"); - return ret; - } - kfree_skb(skb); - - /* Some platforms have an issue with BT LED when the interface is - * down or BT radio is turned off, which takes 5 seconds to BT LED - * goes off. This command turns off the BT LED immediately. - */ - skb = __hci_cmd_sync(hdev, 0xfc3f, 0, NULL, HCI_INIT_TIMEOUT); - if (IS_ERR(skb)) { - ret = PTR_ERR(skb); - bt_dev_err(hdev, "turning off Intel device LED failed"); - return ret; - } - kfree_skb(skb); - - return 0; -} static int btusb_shutdown_intel_new(struct hci_dev *hdev) { @@ -4649,10 +4302,11 @@ static int btusb_probe(struct usb_interface *intf, data->diag = usb_ifnum_to_if(data->udev, ifnum_base + 2); } - if (id->driver_info & BTUSB_INTEL) { + /* Combined Intel Device setup to support multiple setup routine */ + if (id->driver_info & BTUSB_INTEL_COMBINED) { hdev->manufacturer = 2; - hdev->setup = btusb_setup_intel; - hdev->shutdown = btusb_shutdown_intel; + hdev->setup = btintel_setup_combined; + hdev->shutdown = btintel_shutdown_combined; hdev->set_diag = btintel_set_diag_mfg; hdev->set_bdaddr = btintel_set_bdaddr; hdev->cmd_timeout = btusb_intel_cmd_timeout; From patchwork Tue Jul 27 23:51:20 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tedd Ho-Jeong An X-Patchwork-Id: 12404675 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.7 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id E48DDC4338F for ; Tue, 27 Jul 2021 23:51:47 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id CAE2D60F6C for ; Tue, 27 Jul 2021 23:51:47 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233455AbhG0Xvq (ORCPT ); Tue, 27 Jul 2021 19:51:46 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37202 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233081AbhG0Xvo (ORCPT ); Tue, 27 Jul 2021 19:51:44 -0400 Received: from mail-pl1-x62f.google.com (mail-pl1-x62f.google.com [IPv6:2607:f8b0:4864:20::62f]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id CF3D9C061760 for ; Tue, 27 Jul 2021 16:51:43 -0700 (PDT) Received: by mail-pl1-x62f.google.com with SMTP id d1so500149pll.1 for ; Tue, 27 Jul 2021 16:51:43 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=poDdS+mjq55XVF8DCA6fkrxGqvX6sArB63dSvSdWPXk=; b=qS7nuSIQ9pV4QfpE2GkNAkKDj3w5ICnN7pSRBInufVMR3p98ycrGisY+qDTGm9ftfq 4PFMBPpSx0xQBf7qaQWms+lnCRx9w+2wy2rlpdF0HxDG3G+JtwfpDRb51f+AfHP3Deln 5trvVJt9g17Ktx8wM1g9vsgnqmOpm/9THL6sbd81gZQGuFxK1mKHQRaZxQq/NjpD4yRz zW8AeeeT1j2zTelYpBMsw5cVJpnjcpTqHsquI4toVvnd35Ws9gGFY7PjklLAvXvxItI3 AaJgYtMP0plryjs3ga92Aj/kjHyorqyO93pmjrZX8raBVfM1KAU8JAo48E8TCJKwjnFG L+WQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=poDdS+mjq55XVF8DCA6fkrxGqvX6sArB63dSvSdWPXk=; b=BNHUZ8E+ivxYMeo35ZTgvqna8Ziw6hnbTjltoQc6e9H5by52yveuPHtInZ/9mzbCqO qmxNekCDki5RTB/1Un43AGaFC6vaKx+GViVooI8jqneMo7cAwCgOcWwAduS5BJ3LwV9n JNFcgAVmXzP9hHxC8SMEEu9+B8mILY5LOuPgkOgUqNIznf6pbYEsa9fzNGvsVdXIdxZx mTe7dKhM6ihq1fXFJWqNWefmBAD1Msx4rIJAusu1OPyKEluH+5rPLfOJ5XGyzTbwRrFF w2lMonnkHibkztTWlOAyayo72SUDO3O+AgK+kY+Qf4j6tRw05BZH9RCWC0/qSw3CPvrz Essg== X-Gm-Message-State: AOAM531M2fM3I9562BKW6/quwo8CixLFyHgdJeuVPTIHa9q06tKha3tv /uvTjzzePIyCrZCiIzs/s/lQE/iaozQ= X-Google-Smtp-Source: ABdhPJyYNorwq6AY/PD2p9p2mgnfqF7cF7xTgT4POVEDkQiUauejEfecLsh73yk8p9i8K+mOiwS/jw== X-Received: by 2002:a17:902:c64b:b029:12a:d8db:d0fe with SMTP id s11-20020a170902c64bb029012ad8dbd0femr20432956pls.11.1627429903108; Tue, 27 Jul 2021 16:51:43 -0700 (PDT) Received: from localhost.localdomain ([2601:1c0:6a01:d830::7cb2]) by smtp.gmail.com with ESMTPSA id y9sm1545332pfq.199.2021.07.27.16.51.42 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 27 Jul 2021 16:51:42 -0700 (PDT) From: Tedd Ho-Jeong An To: linux-bluetooth@vger.kernel.org Cc: Tedd Ho-Jeong An Subject: [RFC PATCH v4 04/11] Bluetooth: btintel: Add btintel data struct Date: Tue, 27 Jul 2021 16:51:20 -0700 Message-Id: <20210727235127.173149-5-hj.tedd.an@gmail.com> X-Mailer: git-send-email 2.26.3 In-Reply-To: <20210727235127.173149-1-hj.tedd.an@gmail.com> References: <20210727235127.173149-1-hj.tedd.an@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-bluetooth@vger.kernel.org From: Tedd Ho-Jeong An This patch adds a data structure for btintel for btintel object, and the definition of bootloder states. Signed-off-by: Tedd Ho-Jeong An --- drivers/bluetooth/btintel.c | 8 ++++++++ drivers/bluetooth/btintel.h | 15 +++++++++++++++ drivers/bluetooth/btusb.c | 6 ++++-- 3 files changed, 27 insertions(+), 2 deletions(-) diff --git a/drivers/bluetooth/btintel.c b/drivers/bluetooth/btintel.c index cfc097694b53..bf0ad05b80fe 100644 --- a/drivers/bluetooth/btintel.c +++ b/drivers/bluetooth/btintel.c @@ -1753,6 +1753,14 @@ int btintel_shutdown_combined(struct hci_dev *hdev) } EXPORT_SYMBOL_GPL(btintel_shutdown_combined); +void btintel_set_flags(struct hci_dev *hdev, unsigned int flag) +{ + struct btintel_data *intel = hci_get_priv(hdev); + + set_bit(flag, &intel->flags); +} +EXPORT_SYMBOL_GPL(btintel_set_flags); + MODULE_AUTHOR("Marcel Holtmann "); MODULE_DESCRIPTION("Bluetooth support for Intel devices ver " VERSION); MODULE_VERSION(VERSION); diff --git a/drivers/bluetooth/btintel.h b/drivers/bluetooth/btintel.h index 68ffa84fa87a..df7aa30142b4 100644 --- a/drivers/bluetooth/btintel.h +++ b/drivers/bluetooth/btintel.h @@ -138,6 +138,16 @@ struct intel_debug_features { #define INTEL_CNVX_TOP_STEP(cnvx_top) (((cnvx_top) & 0x0f000000) >> 24) #define INTEL_CNVX_TOP_PACK_SWAB(t, s) __swab16(((__u16)(((t) << 4) | (s)))) +#define INTEL_BOOTLOADER 0 +#define INTEL_DOWNLOADING 1 +#define INTEL_FIRMWARE_LOADED 2 +#define INTEL_FIRMWARE_FAILED 3 +#define INTEL_BOOTING 4 + +struct btintel_data { + unsigned long flags; +}; + #if IS_ENABLED(CONFIG_BT_INTEL) int btintel_check_bdaddr(struct hci_dev *hdev); @@ -167,6 +177,7 @@ int btintel_download_firmware(struct hci_dev *dev, struct intel_version *ver, const struct firmware *fw, u32 *boot_param); int btintel_setup_combined(struct hci_dev *hdev); int btintel_shutdown_combined(struct hci_dev *hdev); +void btintel_set_flags(struct hci_dev *hdev, unsigned int flag); int btintel_download_firmware_newgen(struct hci_dev *hdev, struct intel_version_tlv *ver, const struct firmware *fw, @@ -295,6 +306,10 @@ static inline int btintel_shutdown_combined(struct hci_dev *hdev) return -EOPNOTSUPP; } +static inline void btintel_set_flags(struct hci_dev *hdev, unsigned int flag) +{ +} + static inline int btintel_download_firmware_newgen(struct hci_dev *hdev, const struct firmware *fw, u32 *boot_param, diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index 3382d75b1969..4cd49a758bb0 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -4133,7 +4133,7 @@ static int btusb_probe(struct usb_interface *intf, struct btusb_data *data; struct hci_dev *hdev; unsigned ifnum_base; - int i, err; + int i, err, priv_size; BT_DBG("intf %p id %p", intf, id); @@ -4219,6 +4219,8 @@ static int btusb_probe(struct usb_interface *intf, init_usb_anchor(&data->ctrl_anchor); spin_lock_init(&data->rxlock); + priv_size = 0; + if (id->driver_info & BTUSB_INTEL_NEW) { data->recv_event = btusb_recv_event_intel; data->recv_bulk = btusb_recv_bulk_intel; @@ -4228,7 +4230,7 @@ static int btusb_probe(struct usb_interface *intf, data->recv_bulk = btusb_recv_bulk; } - hdev = hci_alloc_dev(0); + hdev = hci_alloc_dev(priv_size); if (!hdev) return -ENOMEM; From patchwork Tue Jul 27 23:51:21 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tedd Ho-Jeong An X-Patchwork-Id: 12404677 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.7 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 53724C4320E for ; Tue, 27 Jul 2021 23:51:48 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 392A260FD8 for ; Tue, 27 Jul 2021 23:51:48 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233449AbhG0Xvs (ORCPT ); Tue, 27 Jul 2021 19:51:48 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37208 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233412AbhG0Xvp (ORCPT ); Tue, 27 Jul 2021 19:51:45 -0400 Received: from mail-pj1-x102f.google.com (mail-pj1-x102f.google.com [IPv6:2607:f8b0:4864:20::102f]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id AA720C061757 for ; Tue, 27 Jul 2021 16:51:44 -0700 (PDT) Received: by mail-pj1-x102f.google.com with SMTP id mz5-20020a17090b3785b0290176ecf64922so7223234pjb.3 for ; Tue, 27 Jul 2021 16:51:44 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=ylIJAmp+yr1bvyYwwG8PQSq7oO8H0eUvt5uuIq7+q+4=; b=Oi5Ojwywb/uI7I2MdJPBNyXegskfjr58cAFmnL7qzzgLXUj6WfAyM5jyS53YduERYs 5RciH5I8gw0wJW3hkagK44q0mV9TwArBNYEtiCPGhcdutnuG3jJMMIZZ/lqYDTkdeOiB qFydUwhRwphtXTLQ759ajUGZPl+J6u4OIk0e8+Czb5+ggefyavnKvPGEzKRox6NNNAv2 Gp476CEEek5Y3hlYBBDkFQVEnYLJLeh9SYIfSfH86L6sddt4VHS8wau+4BMEMwU0M+RC jrCaHgSqPz0jsP7bR8zqsRzaN6trvkSRDUqAvIk59N9gRFi1uWjlh3IV/yKAvukar0yY AIDQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=ylIJAmp+yr1bvyYwwG8PQSq7oO8H0eUvt5uuIq7+q+4=; b=el6IIfa27lAnTKD1AmZZiC2oqLA/BAQL8o4HZ05oFXLx5T4FwxGroM3foToLjltOIW H7G4E9h2K93Q+F9Gs2lPmDDzB9xBL3CJHZerHCWqD6BB8SKQ1LobG0Hn8lbog7E7zsU0 HLaM9PwreZPtRntnUsVp7ib/22rF7Dh2P9bQV3yLq2OULiC6KAoVGZ5CRzDxnPqObhRB G2DoJXwZwdCicHTGgx0Z0Yoo5mDCCwNxU4uME8ioTZZEEfi4PtlZdoij6yOgoV8RN/8c panOd3dtcwYw7PHiMEMc0v5Qr6WQjOTPmYMZpjLZt6Lx8Y7cFkveT3R+x5HesWmBqpzT B7/g== X-Gm-Message-State: AOAM530c/8ITnZQtKh0ACkxWKbRxHOYHJflhDoiCZF0FPi1xJJkx8n4B PkNIl9n/c9DatXNqaPRGLm822cqljsw= X-Google-Smtp-Source: ABdhPJwp3XIOG5Out2IzQUk0rJmFWo0d7PhN3F8EuFc8dNzt4NliRDhj7dCheDjuAVwLtIaiDFjKxw== X-Received: by 2002:a17:902:e843:b029:129:acb4:2464 with SMTP id t3-20020a170902e843b0290129acb42464mr20736770plg.77.1627429904036; Tue, 27 Jul 2021 16:51:44 -0700 (PDT) Received: from localhost.localdomain ([2601:1c0:6a01:d830::7cb2]) by smtp.gmail.com with ESMTPSA id y9sm1545332pfq.199.2021.07.27.16.51.43 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 27 Jul 2021 16:51:43 -0700 (PDT) From: Tedd Ho-Jeong An To: linux-bluetooth@vger.kernel.org Cc: Tedd Ho-Jeong An Subject: [RFC PATCH v4 05/11] Bluetooth: btintel: Fix the first HCI command not work with ROM device. Date: Tue, 27 Jul 2021 16:51:21 -0700 Message-Id: <20210727235127.173149-6-hj.tedd.an@gmail.com> X-Mailer: git-send-email 2.26.3 In-Reply-To: <20210727235127.173149-1-hj.tedd.an@gmail.com> References: <20210727235127.173149-1-hj.tedd.an@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-bluetooth@vger.kernel.org From: Tedd Ho-Jeong An The some legacy ROM controllers have a bug with the first HCI command sent to it returning number of completed commands as zero, which would stall the command processing in the Bluetooth core. As a workaround, send HCI Rest command first which will reset the controller to fix the issue. Signed-off-by: Tedd Ho-Jeong An --- drivers/bluetooth/btintel.c | 21 +++++++++++++++++++++ drivers/bluetooth/btintel.h | 1 + drivers/bluetooth/btusb.c | 16 ++++++++++++++-- 3 files changed, 36 insertions(+), 2 deletions(-) diff --git a/drivers/bluetooth/btintel.c b/drivers/bluetooth/btintel.c index bf0ad05b80fe..65ecf2ae9a10 100644 --- a/drivers/bluetooth/btintel.c +++ b/drivers/bluetooth/btintel.c @@ -1659,6 +1659,7 @@ static int btintel_legacy_rom_setup(struct hci_dev *hdev, int btintel_setup_combined(struct hci_dev *hdev) { + struct btintel_data *intel = hci_get_priv(hdev); const u8 param[1] = { 0xFF }; struct intel_version ver; struct intel_version_tlv ver_tlv; @@ -1667,6 +1668,26 @@ int btintel_setup_combined(struct hci_dev *hdev) BT_DBG("%s", hdev->name); + /* The some controllers have a bug with the first HCI command sent to it + * returning number of completed commands as zero. This would stall the + * command processing in the Bluetooth core. + * + * As a workaround, send HCI Reset command first which will reset the + * number of completed commands and allow normal command processing + * from now on. + */ + if (test_bit(INTEL_BROKEN_READ_VERSION, &intel->flags)) { + skb = __hci_cmd_sync(hdev, HCI_OP_RESET, 0, NULL, + HCI_INIT_TIMEOUT); + if (IS_ERR(skb)) { + bt_dev_err(hdev, + "sending initial HCI reset failed (%ld)", + PTR_ERR(skb)); + return PTR_ERR(skb); + } + kfree_skb(skb); + } + /* Starting from TyP device, the command parameter and response are * changed even though the OCF for HCI_Intel_Read_Version command * remains same. The legacy devices can handle even if the diff --git a/drivers/bluetooth/btintel.h b/drivers/bluetooth/btintel.h index df7aa30142b4..29b678364a79 100644 --- a/drivers/bluetooth/btintel.h +++ b/drivers/bluetooth/btintel.h @@ -143,6 +143,7 @@ struct intel_debug_features { #define INTEL_FIRMWARE_LOADED 2 #define INTEL_FIRMWARE_FAILED 3 #define INTEL_BOOTING 4 +#define INTEL_BROKEN_READ_VERSION 5 struct btintel_data { unsigned long flags; diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index 4cd49a758bb0..28ad13d6c032 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -62,6 +62,7 @@ static struct usb_driver btusb_driver; #define BTUSB_QCA_WCN6855 0x1000000 #define BTUSB_INTEL_NEWGEN 0x2000000 #define BTUSB_INTEL_COMBINED 0x4000000 +#define BTUSB_INTEL_BROKEN_READ_VERSION 0x8000000 static const struct usb_device_id btusb_table[] = { /* Generic Bluetooth USB device */ @@ -376,11 +377,14 @@ static const struct usb_device_id blacklist_table[] = { BTUSB_WIDEBAND_SPEECH | BTUSB_VALID_LE_STATES }, { USB_DEVICE(0x8087, 0x07da), .driver_info = BTUSB_CSR }, - { USB_DEVICE(0x8087, 0x07dc), .driver_info = BTUSB_INTEL_COMBINED }, - { USB_DEVICE(0x8087, 0x0a2a), .driver_info = BTUSB_INTEL_COMBINED }, + { USB_DEVICE(0x8087, 0x07dc), .driver_info = BTUSB_INTEL_COMBINED | + BTUSB_INTEL_BROKEN_READ_VERSION }, + { USB_DEVICE(0x8087, 0x0a2a), .driver_info = BTUSB_INTEL_COMBINED | + BTUSB_INTEL_BROKEN_READ_VERSION }, { USB_DEVICE(0x8087, 0x0a2b), .driver_info = BTUSB_INTEL_NEW | BTUSB_WIDEBAND_SPEECH }, { USB_DEVICE(0x8087, 0x0aa7), .driver_info = BTUSB_INTEL_COMBINED | + BTUSB_INTEL_BROKEN_READ_VERSION | BTUSB_WIDEBAND_SPEECH }, { USB_DEVICE(0x8087, 0x0aaa), .driver_info = BTUSB_INTEL_NEW | BTUSB_WIDEBAND_SPEECH | @@ -4221,6 +4225,11 @@ static int btusb_probe(struct usb_interface *intf, priv_size = 0; + if (id->driver_info & BTUSB_INTEL_COMBINED) { + /* Allocate extra space for Intel device */ + priv_size += sizeof(struct btintel_data); + } + if (id->driver_info & BTUSB_INTEL_NEW) { data->recv_event = btusb_recv_event_intel; data->recv_bulk = btusb_recv_bulk_intel; @@ -4315,6 +4324,9 @@ static int btusb_probe(struct usb_interface *intf, set_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks); set_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY, &hdev->quirks); set_bit(HCI_QUIRK_NON_PERSISTENT_DIAG, &hdev->quirks); + + if (id->driver_info & BTUSB_INTEL_BROKEN_READ_VERSION) + btintel_set_flags(hdev, INTEL_BROKEN_READ_VERSION); } if (id->driver_info & BTUSB_INTEL_NEW) { From patchwork Tue Jul 27 23:51:22 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tedd Ho-Jeong An X-Patchwork-Id: 12404679 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.7 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 7F70CC432BE for ; Tue, 27 Jul 2021 23:51:49 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 68CF960FC0 for ; Tue, 27 Jul 2021 23:51:49 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233605AbhG0Xvt (ORCPT ); Tue, 27 Jul 2021 19:51:49 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37212 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233496AbhG0Xvq (ORCPT ); Tue, 27 Jul 2021 19:51:46 -0400 Received: from mail-pl1-x635.google.com (mail-pl1-x635.google.com [IPv6:2607:f8b0:4864:20::635]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 60B53C061760 for ; Tue, 27 Jul 2021 16:51:45 -0700 (PDT) Received: by mail-pl1-x635.google.com with SMTP id t21so428444plr.13 for ; Tue, 27 Jul 2021 16:51:45 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=i6W6r/P4hJaZ5RSIDZqCKaCzrxnbkZ7j5E64mDodXO8=; b=qs3f2EnptgHUKryYPiZHd7Lhv48tEw5KLnuxWxHogw5IH5RPYcYEURIMwH2ebbLqu8 wQVyhw4Nkc9LPreKRZSp4T7g62WxxnoyNOhdYaB0F9plR8kjVD4Xebs3f72YvJkt6t0C /UQNAwa1FwIMhvQfHDK/yk0dOylTDx+M98+X6f+xaUfYGgSxlKe9ClGituflOoOMlyfZ KOlLbFeGwcUAP4VRY/fW5OU4twom0OspRFpcWMFiij2SKafb3LXEqkeDEUFGMtiSU6pi 0TwnFjNuoHEBjizZdiLe+8mWSLAWwbAc/slapPE4+mBz8rmL6sN8egQUEXOAvEIv2O44 H7Hg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=i6W6r/P4hJaZ5RSIDZqCKaCzrxnbkZ7j5E64mDodXO8=; b=l/PqvHEKypgkNhOoPqWqzjc7+Y5JyZPzvb3wggp2D5IxN/NqKAWlSXSdZ4a7K7SpVQ JZAYqQ+Rlvq90xlpBuOFAeYDWNJYFpv1Y5UQM0OTD+wfvubJD5tevBRRBy8lpSSM1fFg M1ckKklcN3h1r4bniZft9x2+F22r71Y4y1s39VaY5vkSojHF8JI1L27MXRBIaSXYxOW0 Fq97VF/KAbvB8pu2ndQDAYpof9rRdsmoaexBotksGiX3ENDZ5FlIVRzKcucobhkUlwqY Vwx6Zd58OmIj22xLS/Cv+p9ZiUPbFalMMvNMIm8Jt5w7nNnzULKTsA4bgZBzntemrxgM f0pw== X-Gm-Message-State: AOAM530zJX6hnI9U24LUMzD0U0sCzTjRwRYZWuiPBVT3Wa9P2PoNhGQm KuNab92WYJ3g6CdUjXd/IKT4IuGvBy0= X-Google-Smtp-Source: ABdhPJx6XaNiMqyT9lF+StYGtjEBuBMBIkEJn0IqOIlr87hyOgXPTz3O6Skn2RHueUWMgFIv6NyNxw== X-Received: by 2002:a17:90a:9314:: with SMTP id p20mr1930962pjo.87.1627429904812; Tue, 27 Jul 2021 16:51:44 -0700 (PDT) Received: from localhost.localdomain ([2601:1c0:6a01:d830::7cb2]) by smtp.gmail.com with ESMTPSA id y9sm1545332pfq.199.2021.07.27.16.51.44 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 27 Jul 2021 16:51:44 -0700 (PDT) From: Tedd Ho-Jeong An To: linux-bluetooth@vger.kernel.org Cc: Tedd Ho-Jeong An Subject: [RFC PATCH v4 06/11] Bluetooth: btintel: Fix the LED is not turning off immediately Date: Tue, 27 Jul 2021 16:51:22 -0700 Message-Id: <20210727235127.173149-7-hj.tedd.an@gmail.com> X-Mailer: git-send-email 2.26.3 In-Reply-To: <20210727235127.173149-1-hj.tedd.an@gmail.com> References: <20210727235127.173149-1-hj.tedd.an@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-bluetooth@vger.kernel.org From: Tedd Ho-Jeong An Some platforms have an issue with BT LED when the interface is down or BT radio is turned off, which takes 5 seconds to BT LED goes off. This command turns off the BT LED immediately. This patch sends the Intel vendor command to turn off the LED. Signed-off-by: Tedd Ho-Jeong An --- drivers/bluetooth/btintel.c | 17 +++++++++++++++++ drivers/bluetooth/btintel.h | 1 + drivers/bluetooth/btusb.c | 11 +++++++++-- 3 files changed, 27 insertions(+), 2 deletions(-) diff --git a/drivers/bluetooth/btintel.c b/drivers/bluetooth/btintel.c index 65ecf2ae9a10..4e72d806387c 100644 --- a/drivers/bluetooth/btintel.c +++ b/drivers/bluetooth/btintel.c @@ -1757,7 +1757,9 @@ EXPORT_SYMBOL_GPL(btintel_setup_combined); int btintel_shutdown_combined(struct hci_dev *hdev) { + struct btintel_data *intel = hci_get_priv(hdev); struct sk_buff *skb; + int ret; /* Send HCI Reset to the controller to stop any BT activity which * were triggered. This will help to save power and maintain the @@ -1770,6 +1772,21 @@ int btintel_shutdown_combined(struct hci_dev *hdev) } kfree_skb(skb); + + /* Some platforms have an issue with BT LED when the interface is + * down or BT radio is turned off, which takes 5 seconds to BT LED + * goes off. This command turns off the BT LED immediately. + */ + if (test_bit(INTEL_BROKEN_LED, &intel->flags)) { + skb = __hci_cmd_sync(hdev, 0xfc3f, 0, NULL, HCI_INIT_TIMEOUT); + if (IS_ERR(skb)) { + ret = PTR_ERR(skb); + bt_dev_err(hdev, "turning off Intel device LED failed"); + return ret; + } + kfree_skb(skb); + } + return 0; } EXPORT_SYMBOL_GPL(btintel_shutdown_combined); diff --git a/drivers/bluetooth/btintel.h b/drivers/bluetooth/btintel.h index 29b678364a79..4a35762c3220 100644 --- a/drivers/bluetooth/btintel.h +++ b/drivers/bluetooth/btintel.h @@ -144,6 +144,7 @@ struct intel_debug_features { #define INTEL_FIRMWARE_FAILED 3 #define INTEL_BOOTING 4 #define INTEL_BROKEN_READ_VERSION 5 +#define INTEL_BROKEN_LED 6 struct btintel_data { unsigned long flags; diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index 28ad13d6c032..542fe0196ac7 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -63,6 +63,7 @@ static struct usb_driver btusb_driver; #define BTUSB_INTEL_NEWGEN 0x2000000 #define BTUSB_INTEL_COMBINED 0x4000000 #define BTUSB_INTEL_BROKEN_READ_VERSION 0x8000000 +#define BTUSB_INTEL_BROKEN_LED 0x10000000 static const struct usb_device_id btusb_table[] = { /* Generic Bluetooth USB device */ @@ -378,13 +379,16 @@ static const struct usb_device_id blacklist_table[] = { BTUSB_VALID_LE_STATES }, { USB_DEVICE(0x8087, 0x07da), .driver_info = BTUSB_CSR }, { USB_DEVICE(0x8087, 0x07dc), .driver_info = BTUSB_INTEL_COMBINED | - BTUSB_INTEL_BROKEN_READ_VERSION }, + BTUSB_INTEL_BROKEN_READ_VERSION | + BTUSB_INTEL_BROKEN_LED }, { USB_DEVICE(0x8087, 0x0a2a), .driver_info = BTUSB_INTEL_COMBINED | - BTUSB_INTEL_BROKEN_READ_VERSION }, + BTUSB_INTEL_BROKEN_READ_VERSION | + BTUSB_INTEL_BROKEN_LED }, { USB_DEVICE(0x8087, 0x0a2b), .driver_info = BTUSB_INTEL_NEW | BTUSB_WIDEBAND_SPEECH }, { USB_DEVICE(0x8087, 0x0aa7), .driver_info = BTUSB_INTEL_COMBINED | BTUSB_INTEL_BROKEN_READ_VERSION | + BTUSB_INTEL_BROKEN_LED | BTUSB_WIDEBAND_SPEECH }, { USB_DEVICE(0x8087, 0x0aaa), .driver_info = BTUSB_INTEL_NEW | BTUSB_WIDEBAND_SPEECH | @@ -4327,6 +4331,9 @@ static int btusb_probe(struct usb_interface *intf, if (id->driver_info & BTUSB_INTEL_BROKEN_READ_VERSION) btintel_set_flags(hdev, INTEL_BROKEN_READ_VERSION); + + if (id->driver_info & BTUSB_INTEL_BROKEN_LED) + btintel_set_flags(hdev, INTEL_BROKEN_LED); } if (id->driver_info & BTUSB_INTEL_NEW) { From patchwork Tue Jul 27 23:51:23 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tedd Ho-Jeong An X-Patchwork-Id: 12404685 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.7 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id A3FCFC4320E for ; Tue, 27 Jul 2021 23:51:53 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 8786760FA0 for ; Tue, 27 Jul 2021 23:51:53 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233865AbhG0Xvw (ORCPT ); Tue, 27 Jul 2021 19:51:52 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37214 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233693AbhG0Xvt (ORCPT ); Tue, 27 Jul 2021 19:51:49 -0400 Received: from mail-pl1-x635.google.com (mail-pl1-x635.google.com [IPv6:2607:f8b0:4864:20::635]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 2A0B0C061757 for ; Tue, 27 Jul 2021 16:51:46 -0700 (PDT) Received: by mail-pl1-x635.google.com with SMTP id a20so538339plm.0 for ; Tue, 27 Jul 2021 16:51:46 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=naa9yAoIxU7KV0k4nabBW+sJrEj5izmp7EoZzkTLf8I=; b=QPfKi4LP+XLYOHRgz2b5fNKPIoNndUo6FScqCzRpEyRAbeXHzSw1aM7mbWuI5sFu87 4W0d2ubAl5W4HGydC+SYoUcAGSaKEOg0rd+x/1SVf0iih9Jokb1cV7qapn+K9qjkb9Y+ FQA3l99JghJe9pqzPNhbGqgM2He6LFpCGoNQDnZnDUenY2EWsDbsneXEmXqflbtG5H8e t7BjrHfumVtLW0vGOcQKRpma0kTJDQ2NAsqC9MRNGwqeFiamLMFlBZht2o1Zn7b55Sie xCd3ZzG+WV/OJc1hlCQJ4uUW/TKPw2gwx5yOPwMHZIdXdgj9+zakcwip0wXUWrXD6FQl pQIg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=naa9yAoIxU7KV0k4nabBW+sJrEj5izmp7EoZzkTLf8I=; b=SvjY1nVkkT5Ro1hm8IigCVL+oimns64cld3eoc6gBZ0fFxQQV9+/vfgBbXjlZOB8iW t2vQm8EjxgnP1QORxjhGOq3byL5FSIrl7ELowPZ5of0TgZ1p0w8h0P77cqOQhO+8LgQp f3YaNsQmn04ZSa8laN1MlleJFimije8ivl1kJGr8DTZo2yIrVIgZKaoVzoMCGi/g4VUO cUT0+kHf+2Y8X+y3OLWRuRDoXEPpI4RoLM2jrkpl9lD2ONXP+7KwcToP04Stmz/W35LC 27tKsymU5Ji9uJUYiAC/howUbzIwOg3rovZVRhDNNCX+yqS4aBoz5xfZ8EAT1WfLUyNF sNZA== X-Gm-Message-State: AOAM530+OHqCgJoBlgSXlmCh7tH2IMvILQbXA9qE8pH/NBRl815zoZjU 7erhpsYZMzMFkvYBgo40VElyaDSDjww= X-Google-Smtp-Source: ABdhPJz3AVkxz+ZU0xG+rpNlxAymh4zoFcavPaLb5NpBitfIOfT9lI2L/yDD41dQF3hiAWotGscUIg== X-Received: by 2002:a62:7d16:0:b029:32d:cfc4:279c with SMTP id y22-20020a627d160000b029032dcfc4279cmr25384650pfc.8.1627429905502; Tue, 27 Jul 2021 16:51:45 -0700 (PDT) Received: from localhost.localdomain ([2601:1c0:6a01:d830::7cb2]) by smtp.gmail.com with ESMTPSA id y9sm1545332pfq.199.2021.07.27.16.51.44 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 27 Jul 2021 16:51:45 -0700 (PDT) From: Tedd Ho-Jeong An To: linux-bluetooth@vger.kernel.org Cc: Tedd Ho-Jeong An Subject: [RFC PATCH v4 07/11] Bluetooth: btintel: Add combined set_diag functions Date: Tue, 27 Jul 2021 16:51:23 -0700 Message-Id: <20210727235127.173149-8-hj.tedd.an@gmail.com> X-Mailer: git-send-email 2.26.3 In-Reply-To: <20210727235127.173149-1-hj.tedd.an@gmail.com> References: <20210727235127.173149-1-hj.tedd.an@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-bluetooth@vger.kernel.org From: Tedd Ho-Jeong An This patch adds a combined set_diag functions. It also changes the btintel_set_diag_mfg() to static since it is no longer used by others. Signed-off-by: Tedd Ho-Jeong An --- drivers/bluetooth/btintel.c | 23 +++++++++++++++++++++-- drivers/bluetooth/btintel.h | 5 +++-- drivers/bluetooth/btusb.c | 2 +- 3 files changed, 25 insertions(+), 5 deletions(-) diff --git a/drivers/bluetooth/btintel.c b/drivers/bluetooth/btintel.c index 4e72d806387c..24b79f449527 100644 --- a/drivers/bluetooth/btintel.c +++ b/drivers/bluetooth/btintel.c @@ -164,7 +164,7 @@ int btintel_set_diag(struct hci_dev *hdev, bool enable) } EXPORT_SYMBOL_GPL(btintel_set_diag); -int btintel_set_diag_mfg(struct hci_dev *hdev, bool enable) +static int btintel_set_diag_mfg(struct hci_dev *hdev, bool enable) { int err, ret; @@ -180,7 +180,25 @@ int btintel_set_diag_mfg(struct hci_dev *hdev, bool enable) return ret; } -EXPORT_SYMBOL_GPL(btintel_set_diag_mfg); + +int btintel_set_diag_combined(struct hci_dev *hdev, bool enable) +{ + struct btintel_data *intel = hci_get_priv(hdev); + int ret; + + /* Legacy ROM device needs to be in the manufacturer mode to apply + * diagnostic setting + * + * This flag is set after reading the Intel version. + */ + if (test_bit(INTEL_ROM_LEGACY, &intel->flags)) + ret = btintel_set_diag_mfg(hdev, enable); + else + ret = btintel_set_diag(hdev, enable); + + return ret; +} +EXPORT_SYMBOL_GPL(btintel_set_diag_combined); void btintel_hw_error(struct hci_dev *hdev, u8 code) { @@ -1723,6 +1741,7 @@ int btintel_setup_combined(struct hci_dev *hdev) case 0x07: /* WP */ case 0x08: /* StP */ /* Legacy ROM product */ + set_bit(INTEL_ROM_LEGACY, &intel->flags); err = btintel_legacy_rom_setup(hdev, &ver); break; case 0x0b: /* SfP */ diff --git a/drivers/bluetooth/btintel.h b/drivers/bluetooth/btintel.h index 4a35762c3220..abc438b9c62e 100644 --- a/drivers/bluetooth/btintel.h +++ b/drivers/bluetooth/btintel.h @@ -145,6 +145,7 @@ struct intel_debug_features { #define INTEL_BOOTING 4 #define INTEL_BROKEN_READ_VERSION 5 #define INTEL_BROKEN_LED 6 +#define INTEL_ROM_LEGACY 7 struct btintel_data { unsigned long flags; @@ -157,7 +158,7 @@ int btintel_enter_mfg(struct hci_dev *hdev); int btintel_exit_mfg(struct hci_dev *hdev, bool reset, bool patched); int btintel_set_bdaddr(struct hci_dev *hdev, const bdaddr_t *bdaddr); int btintel_set_diag(struct hci_dev *hdev, bool enable); -int btintel_set_diag_mfg(struct hci_dev *hdev, bool enable); +int btintel_set_diag_combined(struct hci_dev *hdev, bool enable); void btintel_hw_error(struct hci_dev *hdev, u8 code); int btintel_version_info(struct hci_dev *hdev, struct intel_version *ver); @@ -217,7 +218,7 @@ static inline int btintel_set_diag(struct hci_dev *hdev, bool enable) return -EOPNOTSUPP; } -static inline int btintel_set_diag_mfg(struct hci_dev *hdev, bool enable) +static inline int btintel_set_diag_combined(struct hci_dev *hdev, bool enable) { return -EOPNOTSUPP; } diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index 542fe0196ac7..e83df93faed6 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -4322,7 +4322,7 @@ static int btusb_probe(struct usb_interface *intf, hdev->manufacturer = 2; hdev->setup = btintel_setup_combined; hdev->shutdown = btintel_shutdown_combined; - hdev->set_diag = btintel_set_diag_mfg; + hdev->set_diag = btintel_set_diag_combined; hdev->set_bdaddr = btintel_set_bdaddr; hdev->cmd_timeout = btusb_intel_cmd_timeout; set_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks); From patchwork Tue Jul 27 23:51:24 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tedd Ho-Jeong An X-Patchwork-Id: 12404681 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.7 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 1685EC4338F for ; Tue, 27 Jul 2021 23:51:51 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id F022260F93 for ; Tue, 27 Jul 2021 23:51:50 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233654AbhG0Xvt (ORCPT ); Tue, 27 Jul 2021 19:51:49 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37224 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233553AbhG0Xvs (ORCPT ); Tue, 27 Jul 2021 19:51:48 -0400 Received: from mail-pj1-x102e.google.com (mail-pj1-x102e.google.com [IPv6:2607:f8b0:4864:20::102e]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 6D13FC061764 for ; Tue, 27 Jul 2021 16:51:47 -0700 (PDT) Received: by mail-pj1-x102e.google.com with SMTP id j1so2396339pjv.3 for ; Tue, 27 Jul 2021 16:51:47 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=kiU4qkKTxqLRQZua0UpbtywphpRbroeK8KZoUoUZELg=; b=nUcT6FOWrwnSO10l8Ib61NR9iWAnuGO9O2SLn1wE6Y4/0Lbaz5HM2uXy95xvwHqdwM 2PWv0R1ZYYZEgLGtPjyA09vTNn51Z+1bEKV4Dy/U28ptVPGXsb6zxySf4KxycZp0oPwP uS5pT7YlbBbnjoo+RBVjxdyM7/w8ew8X74JtWogBY3unOTINoXgZCOCxDOoSKM5Ny1OD 45foP3W8vgunjjfJhh3AngAJBFe1xsgAKJ7dCqNFJouqbD7Qfz+MnKSKL90lQdRVIiLm Ak5obTG97N5uNST/TPIWhpQTASqMDaEeZQLeL+IBsv2D/+QmZCOEk2En+yU/vNws+Efd dA6A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=kiU4qkKTxqLRQZua0UpbtywphpRbroeK8KZoUoUZELg=; b=b0dMkshYZ1pGjlvtLyfwW2yaGkbDdD2zS5BUyP/Xgx3mrrpcc2Hepdhz+U6gA3CfV5 /PZPHjxa25sstgQB+FdMTSdvjV8ae17+bSqLBai+3fJLkHRW5Vp0BqH0Z6s2s21sy7ys zREIbC5PVEm4+WxLy13eOy4XslFhx8AjfcCi6jl9N+29YsQtaD+kfdhC3uPkYD5qN5CN xyQ6hlj5Ev0QNZRIL3N0MxLny/jnT1qTX8+mwJWmPfZR8nisvWYUtCz8hF9y1ryOGrZg YQKtvTfziuEVjD3HX0WJV5OFzBzMAsk5WW9paI7DrB41q2sisRACaVFZ+mbTrt1zyGRS YhYw== X-Gm-Message-State: AOAM5333HjuKi5KBFffCuJAVCyWr/ozvlpvo4AlHDQoQyNd2s9YoBDGk lmSR35L7VOul5uDCYDn+SVWMVfaovK0= X-Google-Smtp-Source: ABdhPJw+5w9NgiUA3XJIdnXTGicP3oVMj4kThn4bB1R7kXGcnuk2OsMHZZiphnO7DVYqJs1ysMZf0w== X-Received: by 2002:a17:902:e851:b029:12b:c50a:1ebc with SMTP id t17-20020a170902e851b029012bc50a1ebcmr18608639plg.84.1627429906376; Tue, 27 Jul 2021 16:51:46 -0700 (PDT) Received: from localhost.localdomain ([2601:1c0:6a01:d830::7cb2]) by smtp.gmail.com with ESMTPSA id y9sm1545332pfq.199.2021.07.27.16.51.45 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 27 Jul 2021 16:51:46 -0700 (PDT) From: Tedd Ho-Jeong An To: linux-bluetooth@vger.kernel.org Cc: Tedd Ho-Jeong An Subject: [RFC PATCH v4 08/11] Bluetooth: btintel: Refactoring setup routine for legacy bootloader Date: Tue, 27 Jul 2021 16:51:24 -0700 Message-Id: <20210727235127.173149-9-hj.tedd.an@gmail.com> X-Mailer: git-send-email 2.26.3 In-Reply-To: <20210727235127.173149-1-hj.tedd.an@gmail.com> References: <20210727235127.173149-1-hj.tedd.an@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-bluetooth@vger.kernel.org From: Tedd Ho-Jeong An This patch refactors the setup routines for legacy bootloader devices into combined setup, and move the related functions from btusb to btintel. Signed-off-by: Tedd Ho-Jeong An --- drivers/bluetooth/btintel.c | 419 +++++++++++++++++++++++++++++++++++- drivers/bluetooth/btintel.h | 12 ++ drivers/bluetooth/btusb.c | 377 +++++--------------------------- 3 files changed, 479 insertions(+), 329 deletions(-) diff --git a/drivers/bluetooth/btintel.c b/drivers/bluetooth/btintel.c index 24b79f449527..944203cae8e0 100644 --- a/drivers/bluetooth/btintel.c +++ b/drivers/bluetooth/btintel.c @@ -1675,6 +1675,392 @@ static int btintel_legacy_rom_setup(struct hci_dev *hdev, return 0; } +static int btintel_download_wait(struct hci_dev *hdev, ktime_t calltime, int msec) +{ + struct btintel_data *intel = hci_get_priv(hdev); + ktime_t delta, rettime; + unsigned long long duration; + int err; + + set_bit(INTEL_FIRMWARE_LOADED, &intel->flags); + + bt_dev_info(hdev, "Waiting for firmware download to complete"); + + err = wait_on_bit_timeout(&intel->flags, INTEL_DOWNLOADING, + TASK_INTERRUPTIBLE, + msecs_to_jiffies(msec)); + if (err == -EINTR) { + bt_dev_err(hdev, "Firmware loading interrupted"); + return err; + } + + if (err) { + bt_dev_err(hdev, "Firmware loading timeout"); + return -ETIMEDOUT; + } + + if (test_bit(INTEL_FIRMWARE_FAILED, &intel->flags)) { + bt_dev_err(hdev, "Firmware loading failed"); + return -ENOEXEC; + } + + rettime = ktime_get(); + delta = ktime_sub(rettime, calltime); + duration = (unsigned long long)ktime_to_ns(delta) >> 10; + + bt_dev_info(hdev, "Firmware loaded in %llu usecs", duration); + + return 0; +} + +static int btintel_boot_wait(struct hci_dev *hdev, ktime_t calltime, int msec) +{ + struct btintel_data *intel = hci_get_priv(hdev); + ktime_t delta, rettime; + unsigned long long duration; + int err; + + bt_dev_info(hdev, "Waiting for device to boot"); + + err = wait_on_bit_timeout(&intel->flags, INTEL_BOOTING, + TASK_INTERRUPTIBLE, msecs_to_jiffies(msec)); + if (err == -EINTR) { + bt_dev_err(hdev, "Device boot interrupted"); + return -EINTR; + } + + if (err) { + bt_dev_err(hdev, "Device boot timeout"); + return -ETIMEDOUT; + } + + rettime = ktime_get(); + delta = ktime_sub(rettime, calltime); + duration = (unsigned long long) ktime_to_ns(delta) >> 10; + + bt_dev_info(hdev, "Device booted in %llu usecs", duration); + + return 0; +} + +static int btintel_boot(struct hci_dev *hdev, u32 boot_addr) +{ + struct btintel_data *intel = hci_get_priv(hdev); + ktime_t calltime; + int err; + + calltime = ktime_get(); + + set_bit(INTEL_BOOTING, &intel->flags); + + err = btintel_send_intel_reset(hdev, boot_addr); + if (err) { + bt_dev_err(hdev, "Intel Soft Reset failed (%d)", err); + btintel_reset_to_bootloader(hdev); + return err; + } + + /* The bootloader will not indicate when the device is ready. This + * is done by the operational firmware sending bootup notification. + * + * Booting into operational firmware should not take longer than + * 1 second. However if that happens, then just fail the setup + * since something went wrong. + */ + err = btintel_boot_wait(hdev, calltime, 1000); + if (err == -ETIMEDOUT) + btintel_reset_to_bootloader(hdev); + + return err; +} + +static int btintel_get_fw_name(struct intel_version *ver, + struct intel_boot_params *params, + char *fw_name, size_t len, + const char *suffix) +{ + switch (ver->hw_variant) { + case 0x0b: /* SfP */ + case 0x0c: /* WsP */ + snprintf(fw_name, len, "intel/ibt-%u-%u.%s", + le16_to_cpu(ver->hw_variant), + le16_to_cpu(params->dev_revid), + suffix); + break; + case 0x11: /* JfP */ + case 0x12: /* ThP */ + case 0x13: /* HrP */ + case 0x14: /* CcP */ + snprintf(fw_name, len, "intel/ibt-%u-%u-%u.%s", + le16_to_cpu(ver->hw_variant), + le16_to_cpu(ver->hw_revision), + le16_to_cpu(ver->fw_revision), + suffix); + break; + default: + return -EINVAL; + } + + return 0; +} + +static int btintel_download_fw(struct hci_dev *hdev, + struct intel_version *ver, + struct intel_boot_params *params, + u32 *boot_param) +{ + const struct firmware *fw; + char fwname[64]; + int err; + struct btintel_data *intel = hci_get_priv(hdev); + ktime_t calltime; + + if (!ver || !params) + return -EINVAL; + + /* The firmware variant determines if the device is in bootloader + * mode or is running operational firmware. The value 0x06 identifies + * the bootloader and the value 0x23 identifies the operational + * firmware. + * + * When the operational firmware is already present, then only + * the check for valid Bluetooth device address is needed. This + * determines if the device will be added as configured or + * unconfigured controller. + * + * It is not possible to use the Secure Boot Parameters in this + * case since that command is only available in bootloader mode. + */ + if (ver->fw_variant == 0x23) { + clear_bit(INTEL_BOOTLOADER, &intel->flags); + btintel_check_bdaddr(hdev); + + /* SfP and WsP don't seem to update the firmware version on file + * so version checking is currently possible. + */ + switch (ver->hw_variant) { + case 0x0b: /* SfP */ + case 0x0c: /* WsP */ + return 0; + } + + /* Proceed to download to check if the version matches */ + goto download; + } + + /* Read the secure boot parameters to identify the operating + * details of the bootloader. + */ + err = btintel_read_boot_params(hdev, params); + if (err) + return err; + + /* It is required that every single firmware fragment is acknowledged + * with a command complete event. If the boot parameters indicate + * that this bootloader does not send them, then abort the setup. + */ + if (params->limited_cce != 0x00) { + bt_dev_err(hdev, "Unsupported Intel firmware loading method (%u)", + params->limited_cce); + return -EINVAL; + } + + /* If the OTP has no valid Bluetooth device address, then there will + * also be no valid address for the operational firmware. + */ + if (!bacmp(¶ms->otp_bdaddr, BDADDR_ANY)) { + bt_dev_info(hdev, "No device address configured"); + set_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks); + } + +download: + /* With this Intel bootloader only the hardware variant and device + * revision information are used to select the right firmware for SfP + * and WsP. + * + * The firmware filename is ibt--.sfi. + * + * Currently the supported hardware variants are: + * 11 (0x0b) for iBT3.0 (LnP/SfP) + * 12 (0x0c) for iBT3.5 (WsP) + * + * For ThP/JfP and for future SKU's, the FW name varies based on HW + * variant, HW revision and FW revision, as these are dependent on CNVi + * and RF Combination. + * + * 17 (0x11) for iBT3.5 (JfP) + * 18 (0x12) for iBT3.5 (ThP) + * + * The firmware file name for these will be + * ibt---.sfi. + * + */ + err = btintel_get_fw_name(ver, params, fwname, sizeof(fwname), "sfi"); + if (err < 0) { + if (!test_bit(INTEL_BOOTLOADER, &intel->flags)) { + /* Firmware has already been loaded */ + set_bit(INTEL_FIRMWARE_LOADED, &intel->flags); + return 0; + } + + bt_dev_err(hdev, "Unsupported Intel firmware naming"); + return -EINVAL; + } + + err = firmware_request_nowarn(&fw, fwname, &hdev->dev); + if (err < 0) { + if (!test_bit(INTEL_BOOTLOADER, &intel->flags)) { + /* Firmware has already been loaded */ + set_bit(INTEL_FIRMWARE_LOADED, &intel->flags); + return 0; + } + + bt_dev_err(hdev, "Failed to load Intel firmware file %s (%d)", + fwname, err); + return err; + } + + bt_dev_info(hdev, "Found device firmware: %s", fwname); + + if (fw->size < 644) { + bt_dev_err(hdev, "Invalid size of firmware file (%zu)", + fw->size); + err = -EBADF; + goto done; + } + + calltime = ktime_get(); + + set_bit(INTEL_DOWNLOADING, &intel->flags); + + /* Start firmware downloading and get boot parameter */ + err = btintel_download_firmware(hdev, ver, fw, boot_param); + if (err < 0) { + if (err == -EALREADY) { + /* Firmware has already been loaded */ + set_bit(INTEL_FIRMWARE_LOADED, &intel->flags); + err = 0; + goto done; + } + + /* When FW download fails, send Intel Reset to retry + * FW download. + */ + btintel_reset_to_bootloader(hdev); + goto done; + } + + /* Before switching the device into operational mode and with that + * booting the loaded firmware, wait for the bootloader notification + * that all fragments have been successfully received. + * + * When the event processing receives the notification, then the + * INTEL_DOWNLOADING flag will be cleared. + * + * The firmware loading should not take longer than 5 seconds + * and thus just timeout if that happens and fail the setup + * of this device. + */ + err = btintel_download_wait(hdev, calltime, 5000); + if (err == -ETIMEDOUT) + btintel_reset_to_bootloader(hdev); + +done: + release_firmware(fw); + return err; +} + +static int btintel_bootloader_setup(struct hci_dev *hdev, + struct intel_version *ver) +{ + struct btintel_data *intel = hci_get_priv(hdev); + struct intel_version new_ver; + struct intel_boot_params params; + u32 boot_param; + char ddcname[64]; + int err; + struct intel_debug_features features; + + BT_DBG("%s", hdev->name); + + /* Set the default boot parameter to 0x0 and it is updated to + * SKU specific boot parameter after reading Intel_Write_Boot_Params + * command while downloading the firmware. + */ + boot_param = 0x00000000; + + set_bit(INTEL_BOOTLOADER, &intel->flags); + + err = btintel_download_fw(hdev, ver, ¶ms, &boot_param); + if (err) + return err; + + /* controller is already having an operational firmware */ + if (ver->fw_variant == 0x23) + goto finish; + + err = btintel_boot(hdev, boot_param); + if (err) + return err; + + clear_bit(INTEL_BOOTLOADER, &intel->flags); + + err = btintel_get_fw_name(ver, ¶ms, ddcname, + sizeof(ddcname), "ddc"); + + if (err < 0) { + bt_dev_err(hdev, "Unsupported Intel firmware naming"); + } else { + /* Once the device is running in operational mode, it needs to + * apply the device configuration (DDC) parameters. + * + * The device can work without DDC parameters, so even if it + * fails to load the file, no need to fail the setup. + */ + btintel_load_ddc_config(hdev, ddcname); + } + + /* Read the Intel supported features and if new exception formats + * supported, need to load the additional DDC config to enable. + */ + err = btintel_read_debug_features(hdev, &features); + if (!err) { + /* Set DDC mask for available debug features */ + btintel_set_debug_features(hdev, &features); + } + + /* Read the Intel version information after loading the FW */ + err = btintel_read_version(hdev, &new_ver); + if (err) + return err; + + btintel_version_info(hdev, &new_ver); + +finish: + /* All Intel controllers that support the Microsoft vendor + * extension are using 0xFC1E for VsMsftOpCode. + */ + switch (ver->hw_variant) { + case 0x11: /* JfP */ + case 0x12: /* ThP */ + case 0x13: /* HrP */ + case 0x14: /* CcP */ + hci_set_msft_opcode(hdev, 0xFC1E); + break; + } + + /* Set the event mask for Intel specific vendor events. This enables + * a few extra events that are useful during general operation. It + * does not enable any debugging related events. + * + * The device will function correctly without these events enabled + * and thus no need to fail the setup. + */ + btintel_set_event_mask(hdev, false); + + return 0; +} + int btintel_setup_combined(struct hci_dev *hdev) { struct btintel_data *intel = hci_get_priv(hdev); @@ -1750,7 +2136,7 @@ int btintel_setup_combined(struct hci_dev *hdev) case 0x12: /* ThP */ case 0x13: /* HrP */ case 0x14: /* CcP */ - /* TODO: call setup routine for bootloader product */ + err = btintel_bootloader_setup(hdev, &ver); break; default: bt_dev_err(hdev, "Unsupported Intel hw variant (%u)", @@ -1818,6 +2204,37 @@ void btintel_set_flags(struct hci_dev *hdev, unsigned int flag) } EXPORT_SYMBOL_GPL(btintel_set_flags); +void btintel_bootup(struct hci_dev *hdev, const void *ptr, unsigned int len) +{ + struct btintel_data *intel = hci_get_priv(hdev); + const struct intel_bootup *evt = ptr; + + if (len != sizeof(*evt)) + return; + + if (test_and_clear_bit(INTEL_BOOTING, &intel->flags)) + wake_up_bit(&intel->flags, INTEL_BOOTING); +} +EXPORT_SYMBOL_GPL(btintel_bootup); + +void btintel_secure_send_result(struct hci_dev *hdev, + const void *ptr, unsigned int len) +{ + struct btintel_data *intel = hci_get_priv(hdev); + const struct intel_secure_send_result *evt = ptr; + + if (len != sizeof(*evt)) + return; + + if (evt->result) + set_bit(INTEL_FIRMWARE_FAILED, &intel->flags); + + if (test_and_clear_bit(INTEL_DOWNLOADING, &intel->flags) && + test_bit(INTEL_FIRMWARE_LOADED, &intel->flags)) + wake_up_bit(&intel->flags, INTEL_DOWNLOADING); +} +EXPORT_SYMBOL_GPL(btintel_secure_send_result); + MODULE_AUTHOR("Marcel Holtmann "); MODULE_DESCRIPTION("Bluetooth support for Intel devices ver " VERSION); MODULE_VERSION(VERSION); diff --git a/drivers/bluetooth/btintel.h b/drivers/bluetooth/btintel.h index abc438b9c62e..f02ccd7e76fb 100644 --- a/drivers/bluetooth/btintel.h +++ b/drivers/bluetooth/btintel.h @@ -191,6 +191,9 @@ int btintel_read_debug_features(struct hci_dev *hdev, struct intel_debug_features *features); int btintel_set_debug_features(struct hci_dev *hdev, const struct intel_debug_features *features); +void btintel_bootup(struct hci_dev *hdev, const void *ptr, unsigned int len); +void btintel_secure_send_result(struct hci_dev *hdev, + const void *ptr, unsigned int len); #else static inline int btintel_check_bdaddr(struct hci_dev *hdev) @@ -337,4 +340,13 @@ static inline int btintel_set_debug_features(struct hci_dev *hdev, return -EOPNOTSUPP; } +static inline void btintel_bootup(struct hci_dev *hdev, + const void *ptr, unsigned int len) +{ +} + +static inline void btintel_secure_send_result(struct hci_dev *hdev, + const void *ptr, unsigned int len) +{ +} #endif diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index e83df93faed6..189820b92c5e 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -365,12 +365,12 @@ static const struct usb_device_id blacklist_table[] = { { USB_DEVICE(0x1286, 0x204e), .driver_info = BTUSB_MARVELL }, /* Intel Bluetooth devices */ - { USB_DEVICE(0x8087, 0x0025), .driver_info = BTUSB_INTEL_NEW | + { USB_DEVICE(0x8087, 0x0025), .driver_info = BTUSB_INTEL_COMBINED | BTUSB_WIDEBAND_SPEECH | BTUSB_VALID_LE_STATES }, - { USB_DEVICE(0x8087, 0x0026), .driver_info = BTUSB_INTEL_NEW | + { USB_DEVICE(0x8087, 0x0026), .driver_info = BTUSB_INTEL_COMBINED | BTUSB_WIDEBAND_SPEECH }, - { USB_DEVICE(0x8087, 0x0029), .driver_info = BTUSB_INTEL_NEW | + { USB_DEVICE(0x8087, 0x0029), .driver_info = BTUSB_INTEL_COMBINED | BTUSB_WIDEBAND_SPEECH }, { USB_DEVICE(0x8087, 0x0032), .driver_info = BTUSB_INTEL_NEWGEN | BTUSB_WIDEBAND_SPEECH}, @@ -384,13 +384,13 @@ static const struct usb_device_id blacklist_table[] = { { USB_DEVICE(0x8087, 0x0a2a), .driver_info = BTUSB_INTEL_COMBINED | BTUSB_INTEL_BROKEN_READ_VERSION | BTUSB_INTEL_BROKEN_LED }, - { USB_DEVICE(0x8087, 0x0a2b), .driver_info = BTUSB_INTEL_NEW | + { USB_DEVICE(0x8087, 0x0a2b), .driver_info = BTUSB_INTEL_COMBINED | BTUSB_WIDEBAND_SPEECH }, { USB_DEVICE(0x8087, 0x0aa7), .driver_info = BTUSB_INTEL_COMBINED | BTUSB_INTEL_BROKEN_READ_VERSION | BTUSB_INTEL_BROKEN_LED | BTUSB_WIDEBAND_SPEECH }, - { USB_DEVICE(0x8087, 0x0aaa), .driver_info = BTUSB_INTEL_NEW | + { USB_DEVICE(0x8087, 0x0aaa), .driver_info = BTUSB_INTEL_COMBINED | BTUSB_WIDEBAND_SPEECH | BTUSB_VALID_LE_STATES }, @@ -1999,11 +1999,14 @@ static int inject_cmd_complete(struct hci_dev *hdev, __u16 opcode) static int btusb_recv_bulk_intel(struct btusb_data *data, void *buffer, int count) { + struct btintel_data *intel = hci_get_priv(data->hdev); + /* When the device is in bootloader mode, then it can send * events via the bulk endpoint. These events are treated the * same way as the ones received from the interrupt endpoint. */ - if (test_bit(BTUSB_BOOTLOADER, &data->flags)) + if (test_bit(BTUSB_BOOTLOADER, &data->flags) || + test_bit(INTEL_BOOTLOADER, &intel->flags)) return btusb_recv_intr(data, buffer, count); return btusb_recv_bulk(data, buffer, count); @@ -2040,6 +2043,7 @@ static void btusb_intel_secure_send_result(struct btusb_data *data, static int btusb_recv_event_intel(struct hci_dev *hdev, struct sk_buff *skb) { struct btusb_data *data = hci_get_drvdata(hdev); + struct btintel_data *intel = hci_get_priv(hdev); if (test_bit(BTUSB_BOOTLOADER, &data->flags)) { struct hci_event_hdr *hdr = (void *)skb->data; @@ -2069,19 +2073,49 @@ static int btusb_recv_event_intel(struct hci_dev *hdev, struct sk_buff *skb) } } + if (test_bit(INTEL_BOOTLOADER, &intel->flags)) { + struct hci_event_hdr *hdr = (void *)skb->data; + + if (skb->len > HCI_EVENT_HDR_SIZE && hdr->evt == 0xff && + hdr->plen > 0) { + const void *ptr = skb->data + HCI_EVENT_HDR_SIZE + 1; + unsigned int len = skb->len - HCI_EVENT_HDR_SIZE - 1; + + switch (skb->data[2]) { + case 0x02: + /* When switching to the operational firmware + * the device sends a vendor specific event + * indicating that the bootup completed. + */ + btintel_bootup(hdev, ptr, len); + break; + case 0x06: + /* When the firmware loading completes the + * device sends out a vendor specific event + * indicating the result of the firmware + * loading. + */ + btintel_secure_send_result(hdev, ptr, len); + break; + } + } + } + return hci_recv_frame(hdev, skb); } static int btusb_send_frame_intel(struct hci_dev *hdev, struct sk_buff *skb) { struct btusb_data *data = hci_get_drvdata(hdev); + struct btintel_data *intel = hci_get_priv(hdev); struct urb *urb; BT_DBG("%s", hdev->name); switch (hci_skb_pkt_type(skb)) { case HCI_COMMAND_PKT: - if (test_bit(BTUSB_BOOTLOADER, &data->flags)) { + if (test_bit(BTUSB_BOOTLOADER, &data->flags) || + test_bit(INTEL_BOOTLOADER, &intel->flags)) { struct hci_command_hdr *cmd = (void *)skb->data; __u16 opcode = le16_to_cpu(cmd->opcode); @@ -2133,36 +2167,6 @@ static int btusb_send_frame_intel(struct hci_dev *hdev, struct sk_buff *skb) return -EILSEQ; } -static int btusb_setup_intel_new_get_fw_name(struct intel_version *ver, - struct intel_boot_params *params, - char *fw_name, size_t len, - const char *suffix) -{ - switch (ver->hw_variant) { - case 0x0b: /* SfP */ - case 0x0c: /* WsP */ - snprintf(fw_name, len, "intel/ibt-%u-%u.%s", - le16_to_cpu(ver->hw_variant), - le16_to_cpu(params->dev_revid), - suffix); - break; - case 0x11: /* JfP */ - case 0x12: /* ThP */ - case 0x13: /* HrP */ - case 0x14: /* CcP */ - snprintf(fw_name, len, "intel/ibt-%u-%u-%u.%s", - le16_to_cpu(ver->hw_variant), - le16_to_cpu(ver->hw_revision), - le16_to_cpu(ver->fw_revision), - suffix); - break; - default: - return -EINVAL; - } - - return 0; -} - static void btusb_setup_intel_newgen_get_fw_name(const struct intel_version_tlv *ver_tlv, char *fw_name, size_t len, const char *suffix) @@ -2322,173 +2326,6 @@ static int btusb_intel_download_firmware_newgen(struct hci_dev *hdev, return err; } -static int btusb_intel_download_firmware(struct hci_dev *hdev, - struct intel_version *ver, - struct intel_boot_params *params, - u32 *boot_param) -{ - const struct firmware *fw; - char fwname[64]; - int err; - struct btusb_data *data = hci_get_drvdata(hdev); - ktime_t calltime; - - if (!ver || !params) - return -EINVAL; - - /* The firmware variant determines if the device is in bootloader - * mode or is running operational firmware. The value 0x06 identifies - * the bootloader and the value 0x23 identifies the operational - * firmware. - * - * When the operational firmware is already present, then only - * the check for valid Bluetooth device address is needed. This - * determines if the device will be added as configured or - * unconfigured controller. - * - * It is not possible to use the Secure Boot Parameters in this - * case since that command is only available in bootloader mode. - */ - if (ver->fw_variant == 0x23) { - clear_bit(BTUSB_BOOTLOADER, &data->flags); - btintel_check_bdaddr(hdev); - - /* SfP and WsP don't seem to update the firmware version on file - * so version checking is currently possible. - */ - switch (ver->hw_variant) { - case 0x0b: /* SfP */ - case 0x0c: /* WsP */ - return 0; - } - - /* Proceed to download to check if the version matches */ - goto download; - } - - /* Read the secure boot parameters to identify the operating - * details of the bootloader. - */ - err = btintel_read_boot_params(hdev, params); - if (err) - return err; - - /* It is required that every single firmware fragment is acknowledged - * with a command complete event. If the boot parameters indicate - * that this bootloader does not send them, then abort the setup. - */ - if (params->limited_cce != 0x00) { - bt_dev_err(hdev, "Unsupported Intel firmware loading method (%u)", - params->limited_cce); - return -EINVAL; - } - - /* If the OTP has no valid Bluetooth device address, then there will - * also be no valid address for the operational firmware. - */ - if (!bacmp(¶ms->otp_bdaddr, BDADDR_ANY)) { - bt_dev_info(hdev, "No device address configured"); - set_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks); - } - -download: - /* With this Intel bootloader only the hardware variant and device - * revision information are used to select the right firmware for SfP - * and WsP. - * - * The firmware filename is ibt--.sfi. - * - * Currently the supported hardware variants are: - * 11 (0x0b) for iBT3.0 (LnP/SfP) - * 12 (0x0c) for iBT3.5 (WsP) - * - * For ThP/JfP and for future SKU's, the FW name varies based on HW - * variant, HW revision and FW revision, as these are dependent on CNVi - * and RF Combination. - * - * 17 (0x11) for iBT3.5 (JfP) - * 18 (0x12) for iBT3.5 (ThP) - * - * The firmware file name for these will be - * ibt---.sfi. - * - */ - err = btusb_setup_intel_new_get_fw_name(ver, params, fwname, - sizeof(fwname), "sfi"); - if (err < 0) { - if (!test_bit(BTUSB_BOOTLOADER, &data->flags)) { - /* Firmware has already been loaded */ - set_bit(BTUSB_FIRMWARE_LOADED, &data->flags); - return 0; - } - - bt_dev_err(hdev, "Unsupported Intel firmware naming"); - return -EINVAL; - } - - err = firmware_request_nowarn(&fw, fwname, &hdev->dev); - if (err < 0) { - if (!test_bit(BTUSB_BOOTLOADER, &data->flags)) { - /* Firmware has already been loaded */ - set_bit(BTUSB_FIRMWARE_LOADED, &data->flags); - return 0; - } - - bt_dev_err(hdev, "Failed to load Intel firmware file %s (%d)", - fwname, err); - return err; - } - - bt_dev_info(hdev, "Found device firmware: %s", fwname); - - if (fw->size < 644) { - bt_dev_err(hdev, "Invalid size of firmware file (%zu)", - fw->size); - err = -EBADF; - goto done; - } - - calltime = ktime_get(); - - set_bit(BTUSB_DOWNLOADING, &data->flags); - - /* Start firmware downloading and get boot parameter */ - err = btintel_download_firmware(hdev, ver, fw, boot_param); - if (err < 0) { - if (err == -EALREADY) { - /* Firmware has already been loaded */ - set_bit(BTUSB_FIRMWARE_LOADED, &data->flags); - err = 0; - goto done; - } - - /* When FW download fails, send Intel Reset to retry - * FW download. - */ - btintel_reset_to_bootloader(hdev); - goto done; - } - - /* Before switching the device into operational mode and with that - * booting the loaded firmware, wait for the bootloader notification - * that all fragments have been successfully received. - * - * When the event processing receives the notification, then the - * BTUSB_DOWNLOADING flag will be cleared. - * - * The firmware loading should not take longer than 5 seconds - * and thus just timeout if that happens and fail the setup - * of this device. - */ - err = btusb_download_wait(hdev, calltime, 5000); - if (err == -ETIMEDOUT) - btintel_reset_to_bootloader(hdev); - -done: - release_firmware(fw); - return err; -} - static int btusb_boot_wait(struct hci_dev *hdev, ktime_t calltime, int msec) { struct btusb_data *data = hci_get_drvdata(hdev); @@ -2551,109 +2388,6 @@ static int btusb_intel_boot(struct hci_dev *hdev, u32 boot_addr) return err; } -static int btusb_setup_intel_new(struct hci_dev *hdev) -{ - struct btusb_data *data = hci_get_drvdata(hdev); - struct intel_version ver; - struct intel_boot_params params; - u32 boot_param; - char ddcname[64]; - int err; - struct intel_debug_features features; - - BT_DBG("%s", hdev->name); - - /* Set the default boot parameter to 0x0 and it is updated to - * SKU specific boot parameter after reading Intel_Write_Boot_Params - * command while downloading the firmware. - */ - boot_param = 0x00000000; - - /* Read the Intel version information to determine if the device - * is in bootloader mode or if it already has operational firmware - * loaded. - */ - err = btintel_read_version(hdev, &ver); - if (err) { - bt_dev_err(hdev, "Intel Read version failed (%d)", err); - btintel_reset_to_bootloader(hdev); - return err; - } - - err = btintel_version_info(hdev, &ver); - if (err) - return err; - - err = btusb_intel_download_firmware(hdev, &ver, ¶ms, &boot_param); - if (err) - return err; - - /* controller is already having an operational firmware */ - if (ver.fw_variant == 0x23) - goto finish; - - err = btusb_intel_boot(hdev, boot_param); - if (err) - return err; - - clear_bit(BTUSB_BOOTLOADER, &data->flags); - - err = btusb_setup_intel_new_get_fw_name(&ver, ¶ms, ddcname, - sizeof(ddcname), "ddc"); - - if (err < 0) { - bt_dev_err(hdev, "Unsupported Intel firmware naming"); - } else { - /* Once the device is running in operational mode, it needs to - * apply the device configuration (DDC) parameters. - * - * The device can work without DDC parameters, so even if it - * fails to load the file, no need to fail the setup. - */ - btintel_load_ddc_config(hdev, ddcname); - } - - /* Read the Intel supported features and if new exception formats - * supported, need to load the additional DDC config to enable. - */ - err = btintel_read_debug_features(hdev, &features); - if (!err) { - /* Set DDC mask for available debug features */ - btintel_set_debug_features(hdev, &features); - } - - /* Read the Intel version information after loading the FW */ - err = btintel_read_version(hdev, &ver); - if (err) - return err; - - btintel_version_info(hdev, &ver); - -finish: - /* All Intel controllers that support the Microsoft vendor - * extension are using 0xFC1E for VsMsftOpCode. - */ - switch (ver.hw_variant) { - case 0x11: /* JfP */ - case 0x12: /* ThP */ - case 0x13: /* HrP */ - case 0x14: /* CcP */ - hci_set_msft_opcode(hdev, 0xFC1E); - break; - } - - /* Set the event mask for Intel specific vendor events. This enables - * a few extra events that are useful during general operation. It - * does not enable any debugging related events. - * - * The device will function correctly without these events enabled - * and thus no need to fail the setup. - */ - btintel_set_event_mask(hdev, false); - - return 0; -} - static int btusb_setup_intel_newgen(struct hci_dev *hdev) { struct btusb_data *data = hci_get_drvdata(hdev); @@ -4229,18 +3963,17 @@ static int btusb_probe(struct usb_interface *intf, priv_size = 0; - if (id->driver_info & BTUSB_INTEL_COMBINED) { + data->recv_event = hci_recv_frame; + data->recv_bulk = btusb_recv_bulk; + + if (id->driver_info & BTUSB_INTEL_COMBINED || + id->driver_info & BTUSB_INTEL_NEW) { /* Allocate extra space for Intel device */ priv_size += sizeof(struct btintel_data); - } - if (id->driver_info & BTUSB_INTEL_NEW) { + /* Override the rx handlers */ data->recv_event = btusb_recv_event_intel; data->recv_bulk = btusb_recv_bulk_intel; - set_bit(BTUSB_BOOTLOADER, &data->flags); - } else { - data->recv_event = hci_recv_frame; - data->recv_bulk = btusb_recv_bulk; } hdev = hci_alloc_dev(priv_size); @@ -4320,8 +4053,10 @@ static int btusb_probe(struct usb_interface *intf, /* Combined Intel Device setup to support multiple setup routine */ if (id->driver_info & BTUSB_INTEL_COMBINED) { hdev->manufacturer = 2; + hdev->send = btusb_send_frame_intel; hdev->setup = btintel_setup_combined; hdev->shutdown = btintel_shutdown_combined; + hdev->hw_error = btintel_hw_error; hdev->set_diag = btintel_set_diag_combined; hdev->set_bdaddr = btintel_set_bdaddr; hdev->cmd_timeout = btusb_intel_cmd_timeout; @@ -4336,20 +4071,6 @@ static int btusb_probe(struct usb_interface *intf, btintel_set_flags(hdev, INTEL_BROKEN_LED); } - if (id->driver_info & BTUSB_INTEL_NEW) { - hdev->manufacturer = 2; - hdev->send = btusb_send_frame_intel; - hdev->setup = btusb_setup_intel_new; - hdev->shutdown = btusb_shutdown_intel_new; - hdev->hw_error = btintel_hw_error; - hdev->set_diag = btintel_set_diag; - hdev->set_bdaddr = btintel_set_bdaddr; - hdev->cmd_timeout = btusb_intel_cmd_timeout; - set_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks); - set_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY, &hdev->quirks); - set_bit(HCI_QUIRK_NON_PERSISTENT_DIAG, &hdev->quirks); - } - if (id->driver_info & BTUSB_INTEL_NEWGEN) { hdev->manufacturer = 2; hdev->send = btusb_send_frame_intel; From patchwork Tue Jul 27 23:51:25 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tedd Ho-Jeong An X-Patchwork-Id: 12404683 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.7 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 8E39BC432BE for ; Tue, 27 Jul 2021 23:51:52 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 75E4B60F9C for ; Tue, 27 Jul 2021 23:51:52 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233776AbhG0Xvv (ORCPT ); Tue, 27 Jul 2021 19:51:51 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37226 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233496AbhG0Xvt (ORCPT ); Tue, 27 Jul 2021 19:51:49 -0400 Received: from mail-pj1-x1030.google.com (mail-pj1-x1030.google.com [IPv6:2607:f8b0:4864:20::1030]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id D53A1C061760 for ; Tue, 27 Jul 2021 16:51:47 -0700 (PDT) Received: by mail-pj1-x1030.google.com with SMTP id g23-20020a17090a5797b02901765d605e14so1575198pji.5 for ; Tue, 27 Jul 2021 16:51:47 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=qk//TNZO+9a1W2Ks+ArTNoS+C5geuHfId+ew8Oorp4E=; b=R9ApCnHbe3Cm9w9Zj7s2FFVmg7pEoFq1dHCRzkJ11+CxQJ+BVbaQAWnxquCa+snIag Gq5dw8TzSVb1XWcOVOMQEp3S37OJmfyv3Z8sRaAFo7uHWLFxYqgpjvbrP1iP7OPdeXUC NYaOsEXL/M0190fXhAjzbbs5lSfSmeYcAypeT+TB8cc5gNuXTUSnwwiEHJhWhDv+QMye rxWaXU7OxUdfmY/E4H/Qes2VIQfupHqoc/96hSmqcpKPdnZCFgfOLQgLQiAZld/LpCUK a8hpWHOap+rxxltrPpLJW4zAGY/lkACMc+JVhZX45CDke8ge+qVJQIVgDXNxsVE45gow GmUQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=qk//TNZO+9a1W2Ks+ArTNoS+C5geuHfId+ew8Oorp4E=; b=hP3rIxHUgoMr/RPbt2T0ikaKUCPW1M5MQ4caVFlQpkebWio8KZSJKVt1rqeSmuNYWy vBLkv41AX5x042nZ+rScVTeKQfJynDHF++Xj2bmMTE+WFkmlxhTypZ2hX1cBSyHe8mHy GfX6fueKPyXllIEzF6Z4ggpNQyCvIWUg/VmOLzH0UoIjpYwiDeynOLMFWdk6AP6ZZe91 p6XZ0KL2yO7D9CJS6ErvI/xpBrjRhqivzvBltCHZl+G/qPwfW+Dk4k/r/hY/40dw3tB3 4o23usPA5uAMbMwNwhPsf5c2Ur+/DE2DMuJ5eUNQB//UCAUeGGbeF3H/eqRA0u2L5Wo/ tEBA== X-Gm-Message-State: AOAM530aIlu+2jcwyF4dyTlN+5uOVmntHzYAzRTAqz04YOwZSqaVgzlo oYdifcPZ4hCqvCTjUwOSB2BtxrPGt1U= X-Google-Smtp-Source: ABdhPJxFNrVptIw1vQuQUWzCvSmjefVPfEI03cXmYdxPQ/lXqvPDnwB1h2BbJHcouGjSBlHpYCmWbw== X-Received: by 2002:a17:90a:ab0f:: with SMTP id m15mr19495719pjq.154.1627429907114; Tue, 27 Jul 2021 16:51:47 -0700 (PDT) Received: from localhost.localdomain ([2601:1c0:6a01:d830::7cb2]) by smtp.gmail.com with ESMTPSA id y9sm1545332pfq.199.2021.07.27.16.51.46 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 27 Jul 2021 16:51:46 -0700 (PDT) From: Tedd Ho-Jeong An To: linux-bluetooth@vger.kernel.org Cc: Tedd Ho-Jeong An Subject: [RFC PATCH v4 09/11] Bluetooth: btintel: Refactoring setup routine for TLV based booloader Date: Tue, 27 Jul 2021 16:51:25 -0700 Message-Id: <20210727235127.173149-10-hj.tedd.an@gmail.com> X-Mailer: git-send-email 2.26.3 In-Reply-To: <20210727235127.173149-1-hj.tedd.an@gmail.com> References: <20210727235127.173149-1-hj.tedd.an@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-bluetooth@vger.kernel.org From: Tedd Ho-Jeong An This patch refactors the setup routines for the TLV based bootloader devices into combined setup, and move the related functions from btubs to btintel. Signed-off-by: Tedd Ho-Jeong An --- drivers/bluetooth/btintel.c | 289 +++++++++++++++++-------- drivers/bluetooth/btintel.h | 13 -- drivers/bluetooth/btusb.c | 413 +----------------------------------- 3 files changed, 204 insertions(+), 511 deletions(-) diff --git a/drivers/bluetooth/btintel.c b/drivers/bluetooth/btintel.c index 944203cae8e0..dc5e2b255605 100644 --- a/drivers/bluetooth/btintel.c +++ b/drivers/bluetooth/btintel.c @@ -623,90 +623,7 @@ int btintel_read_version_tlv(struct hci_dev *hdev, struct intel_version_tlv *ver return -EIO; } - /* Consume Command Complete Status field */ - skb_pull(skb, 1); - - /* Event parameters contatin multiple TLVs. Read each of them - * and only keep the required data. Also, it use existing legacy - * version field like hw_platform, hw_variant, and fw_variant - * to keep the existing setup flow - */ - while (skb->len) { - struct intel_tlv *tlv; - - tlv = (struct intel_tlv *)skb->data; - switch (tlv->type) { - case INTEL_TLV_CNVI_TOP: - version->cnvi_top = get_unaligned_le32(tlv->val); - break; - case INTEL_TLV_CNVR_TOP: - version->cnvr_top = get_unaligned_le32(tlv->val); - break; - case INTEL_TLV_CNVI_BT: - version->cnvi_bt = get_unaligned_le32(tlv->val); - break; - case INTEL_TLV_CNVR_BT: - version->cnvr_bt = get_unaligned_le32(tlv->val); - break; - case INTEL_TLV_DEV_REV_ID: - version->dev_rev_id = get_unaligned_le16(tlv->val); - break; - case INTEL_TLV_IMAGE_TYPE: - version->img_type = tlv->val[0]; - break; - case INTEL_TLV_TIME_STAMP: - /* If image type is Operational firmware (0x03), then - * running FW Calendar Week and Year information can - * be extracted from Timestamp information - */ - version->min_fw_build_cw = tlv->val[0]; - version->min_fw_build_yy = tlv->val[1]; - version->timestamp = get_unaligned_le16(tlv->val); - break; - case INTEL_TLV_BUILD_TYPE: - version->build_type = tlv->val[0]; - break; - case INTEL_TLV_BUILD_NUM: - /* If image type is Operational firmware (0x03), then - * running FW build number can be extracted from the - * Build information - */ - version->min_fw_build_nn = tlv->val[0]; - version->build_num = get_unaligned_le32(tlv->val); - break; - case INTEL_TLV_SECURE_BOOT: - version->secure_boot = tlv->val[0]; - break; - case INTEL_TLV_OTP_LOCK: - version->otp_lock = tlv->val[0]; - break; - case INTEL_TLV_API_LOCK: - version->api_lock = tlv->val[0]; - break; - case INTEL_TLV_DEBUG_LOCK: - version->debug_lock = tlv->val[0]; - break; - case INTEL_TLV_MIN_FW: - version->min_fw_build_nn = tlv->val[0]; - version->min_fw_build_cw = tlv->val[1]; - version->min_fw_build_yy = tlv->val[2]; - break; - case INTEL_TLV_LIMITED_CCE: - version->limited_cce = tlv->val[0]; - break; - case INTEL_TLV_SBE_TYPE: - version->sbe_type = tlv->val[0]; - break; - case INTEL_TLV_OTP_BDADDR: - memcpy(&version->otp_bd_addr, tlv->val, tlv->len); - break; - default: - /* Ignore rest of information */ - break; - } - /* consume the current tlv and move to next*/ - skb_pull(skb, tlv->len + sizeof(*tlv)); - } + btintel_parse_version_tlv(hdev, version, skb); kfree_skb(skb); return 0; @@ -1184,10 +1101,10 @@ int btintel_download_firmware(struct hci_dev *hdev, } EXPORT_SYMBOL_GPL(btintel_download_firmware); -int btintel_download_firmware_newgen(struct hci_dev *hdev, - struct intel_version_tlv *ver, - const struct firmware *fw, u32 *boot_param, - u8 hw_variant, u8 sbe_type) +static int btintel_download_fw_tlv(struct hci_dev *hdev, + struct intel_version_tlv *ver, + const struct firmware *fw, u32 *boot_param, + u8 hw_variant, u8 sbe_type) { int err; u32 css_header_ver; @@ -1284,7 +1201,6 @@ int btintel_download_firmware_newgen(struct hci_dev *hdev, } return 0; } -EXPORT_SYMBOL_GPL(btintel_download_firmware_newgen); void btintel_reset_to_bootloader(struct hci_dev *hdev) { @@ -2061,6 +1977,199 @@ static int btintel_bootloader_setup(struct hci_dev *hdev, return 0; } +static void btintel_get_fw_name_tlv(const struct intel_version_tlv *ver, + char *fw_name, size_t len, + const char *suffix) +{ + /* The firmware file name for new generation controllers will be + * ibt-- + */ + snprintf(fw_name, len, "intel/ibt-%04x-%04x.%s", + INTEL_CNVX_TOP_PACK_SWAB(INTEL_CNVX_TOP_TYPE(ver->cnvi_top), + INTEL_CNVX_TOP_STEP(ver->cnvi_top)), + INTEL_CNVX_TOP_PACK_SWAB(INTEL_CNVX_TOP_TYPE(ver->cnvr_top), + INTEL_CNVX_TOP_STEP(ver->cnvr_top)), + suffix); +} + +static int btintel_prepare_fw_download_tlv(struct hci_dev *hdev, + struct intel_version_tlv *ver, + u32 *boot_param) +{ + struct btintel_data *intel = hci_get_priv(hdev); + const struct firmware *fw; + char fwname[64]; + int err; + ktime_t calltime; + + if (!ver || !boot_param) + return -EINVAL; + + /* The firmware variant determines if the device is in bootloader + * mode or is running operational firmware. The value 0x03 identifies + * the bootloader and the value 0x23 identifies the operational + * firmware. + * + * When the operational firmware is already present, then only + * the check for valid Bluetooth device address is needed. This + * determines if the device will be added as configured or + * unconfigured controller. + * + * It is not possible to use the Secure Boot Parameters in this + * case since that command is only available in bootloader mode. + */ + if (ver->img_type == 0x03) { + clear_bit(INTEL_BOOTLOADER, &intel->flags); + btintel_check_bdaddr(hdev); + } + + /* If the OTP has no valid Bluetooth device address, then there will + * also be no valid address for the operational firmware. + */ + if (!bacmp(&ver->otp_bd_addr, BDADDR_ANY)) { + bt_dev_info(hdev, "No device address configured"); + set_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks); + } + + btintel_get_fw_name_tlv(ver, fwname, sizeof(fwname), "sfi"); + err = firmware_request_nowarn(&fw, fwname, &hdev->dev); + if (err < 0) { + if (!test_bit(INTEL_BOOTLOADER, &intel->flags)) { + /* Firmware has already been loaded */ + set_bit(INTEL_FIRMWARE_LOADED, &intel->flags); + return 0; + } + + bt_dev_err(hdev, "Failed to load Intel firmware file %s (%d)", + fwname, err); + + return err; + } + + bt_dev_info(hdev, "Found device firmware: %s", fwname); + + if (fw->size < 644) { + bt_dev_err(hdev, "Invalid size of firmware file (%zu)", + fw->size); + err = -EBADF; + goto done; + } + + calltime = ktime_get(); + + set_bit(INTEL_DOWNLOADING, &intel->flags); + + /* Start firmware downloading and get boot parameter */ + err = btintel_download_fw_tlv(hdev, ver, fw, boot_param, + INTEL_HW_VARIANT(ver->cnvi_bt), + ver->sbe_type); + if (err < 0) { + if (err == -EALREADY) { + /* Firmware has already been loaded */ + set_bit(INTEL_FIRMWARE_LOADED, &intel->flags); + err = 0; + goto done; + } + + /* When FW download fails, send Intel Reset to retry + * FW download. + */ + btintel_reset_to_bootloader(hdev); + goto done; + } + + /* Before switching the device into operational mode and with that + * booting the loaded firmware, wait for the bootloader notification + * that all fragments have been successfully received. + * + * When the event processing receives the notification, then the + * BTUSB_DOWNLOADING flag will be cleared. + * + * The firmware loading should not take longer than 5 seconds + * and thus just timeout if that happens and fail the setup + * of this device. + */ + err = btintel_download_wait(hdev, calltime, 5000); + if (err == -ETIMEDOUT) + btintel_reset_to_bootloader(hdev); + +done: + release_firmware(fw); + return err; +} + +static int btintel_bootloader_setup_tlv(struct hci_dev *hdev, + struct intel_version_tlv *ver) +{ + struct btintel_data *intel = hci_get_priv(hdev); + u32 boot_param; + char ddcname[64]; + int err; + struct intel_debug_features features; + struct intel_version_tlv new_ver; + + bt_dev_dbg(hdev, ""); + + /* Set the default boot parameter to 0x0 and it is updated to + * SKU specific boot parameter after reading Intel_Write_Boot_Params + * command while downloading the firmware. + */ + boot_param = 0x00000000; + + set_bit(INTEL_BOOTLOADER, &intel->flags); + + err = btintel_prepare_fw_download_tlv(hdev, ver, &boot_param); + if (err) + return err; + + /* check if controller is already having an operational firmware */ + if (ver->img_type == 0x03) + goto finish; + + err = btintel_boot(hdev, boot_param); + if (err) + return err; + + clear_bit(INTEL_BOOTLOADER, &intel->flags); + + btintel_get_fw_name_tlv(ver, ddcname, sizeof(ddcname), "ddc"); + /* Once the device is running in operational mode, it needs to + * apply the device configuration (DDC) parameters. + * + * The device can work without DDC parameters, so even if it + * fails to load the file, no need to fail the setup. + */ + btintel_load_ddc_config(hdev, ddcname); + + /* Read the Intel supported features and if new exception formats + * supported, need to load the additional DDC config to enable. + */ + err = btintel_read_debug_features(hdev, &features); + if (!err) { + /* Set DDC mask for available debug features */ + btintel_set_debug_features(hdev, &features); + } + + /* Read the Intel version information after loading the FW */ + err = btintel_read_version_tlv(hdev, &new_ver); + if (err) + return err; + + btintel_version_info_tlv(hdev, &new_ver); + +finish: + /* Set the event mask for Intel specific vendor events. This enables + * a few extra events that are useful during general operation. It + * does not enable any debugging related events. + * + * The device will function correctly without these events enabled + * and thus no need to fail the setup. + */ + btintel_set_event_mask(hdev, false); + + return 0; +} + int btintel_setup_combined(struct hci_dev *hdev) { struct btintel_data *intel = hci_get_priv(hdev); @@ -2154,7 +2263,7 @@ int btintel_setup_combined(struct hci_dev *hdev) btintel_version_info_tlv(hdev, &ver_tlv); /* TODO: Need to filter the device for new generation */ - /* TODO: call setup routine for tlv based bootloader product */ + err = btintel_bootloader_setup_tlv(hdev, &ver_tlv); return err; } diff --git a/drivers/bluetooth/btintel.h b/drivers/bluetooth/btintel.h index f02ccd7e76fb..696656fd7e99 100644 --- a/drivers/bluetooth/btintel.h +++ b/drivers/bluetooth/btintel.h @@ -181,11 +181,6 @@ int btintel_download_firmware(struct hci_dev *dev, struct intel_version *ver, int btintel_setup_combined(struct hci_dev *hdev); int btintel_shutdown_combined(struct hci_dev *hdev); void btintel_set_flags(struct hci_dev *hdev, unsigned int flag); -int btintel_download_firmware_newgen(struct hci_dev *hdev, - struct intel_version_tlv *ver, - const struct firmware *fw, - u32 *boot_param, u8 hw_variant, - u8 sbe_type); void btintel_reset_to_bootloader(struct hci_dev *hdev); int btintel_read_debug_features(struct hci_dev *hdev, struct intel_debug_features *features); @@ -316,14 +311,6 @@ static inline void btintel_set_flags(struct hci_dev *hdev, unsigned int flag) { } -static inline int btintel_download_firmware_newgen(struct hci_dev *hdev, - const struct firmware *fw, - u32 *boot_param, - u8 hw_variant, u8 sbe_type) -{ - return -EOPNOTSUPP; -} - static inline void btintel_reset_to_bootloader(struct hci_dev *hdev) { } diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index 189820b92c5e..b752fdde9504 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -372,9 +372,9 @@ static const struct usb_device_id blacklist_table[] = { BTUSB_WIDEBAND_SPEECH }, { USB_DEVICE(0x8087, 0x0029), .driver_info = BTUSB_INTEL_COMBINED | BTUSB_WIDEBAND_SPEECH }, - { USB_DEVICE(0x8087, 0x0032), .driver_info = BTUSB_INTEL_NEWGEN | + { USB_DEVICE(0x8087, 0x0032), .driver_info = BTUSB_INTEL_COMBINED | BTUSB_WIDEBAND_SPEECH}, - { USB_DEVICE(0x8087, 0x0033), .driver_info = BTUSB_INTEL_NEWGEN | + { USB_DEVICE(0x8087, 0x0033), .driver_info = BTUSB_INTEL_COMBINED | BTUSB_WIDEBAND_SPEECH | BTUSB_VALID_LE_STATES }, { USB_DEVICE(0x8087, 0x07da), .driver_info = BTUSB_CSR }, @@ -2005,74 +2005,16 @@ static int btusb_recv_bulk_intel(struct btusb_data *data, void *buffer, * events via the bulk endpoint. These events are treated the * same way as the ones received from the interrupt endpoint. */ - if (test_bit(BTUSB_BOOTLOADER, &data->flags) || - test_bit(INTEL_BOOTLOADER, &intel->flags)) + if (test_bit(INTEL_BOOTLOADER, &intel->flags)) return btusb_recv_intr(data, buffer, count); return btusb_recv_bulk(data, buffer, count); } -static void btusb_intel_bootup(struct btusb_data *data, const void *ptr, - unsigned int len) -{ - const struct intel_bootup *evt = ptr; - - if (len != sizeof(*evt)) - return; - - if (test_and_clear_bit(BTUSB_BOOTING, &data->flags)) - wake_up_bit(&data->flags, BTUSB_BOOTING); -} - -static void btusb_intel_secure_send_result(struct btusb_data *data, - const void *ptr, unsigned int len) -{ - const struct intel_secure_send_result *evt = ptr; - - if (len != sizeof(*evt)) - return; - - if (evt->result) - set_bit(BTUSB_FIRMWARE_FAILED, &data->flags); - - if (test_and_clear_bit(BTUSB_DOWNLOADING, &data->flags) && - test_bit(BTUSB_FIRMWARE_LOADED, &data->flags)) - wake_up_bit(&data->flags, BTUSB_DOWNLOADING); -} - static int btusb_recv_event_intel(struct hci_dev *hdev, struct sk_buff *skb) { - struct btusb_data *data = hci_get_drvdata(hdev); struct btintel_data *intel = hci_get_priv(hdev); - if (test_bit(BTUSB_BOOTLOADER, &data->flags)) { - struct hci_event_hdr *hdr = (void *)skb->data; - - if (skb->len > HCI_EVENT_HDR_SIZE && hdr->evt == 0xff && - hdr->plen > 0) { - const void *ptr = skb->data + HCI_EVENT_HDR_SIZE + 1; - unsigned int len = skb->len - HCI_EVENT_HDR_SIZE - 1; - - switch (skb->data[2]) { - case 0x02: - /* When switching to the operational firmware - * the device sends a vendor specific event - * indicating that the bootup completed. - */ - btusb_intel_bootup(data, ptr, len); - break; - case 0x06: - /* When the firmware loading completes the - * device sends out a vendor specific event - * indicating the result of the firmware - * loading. - */ - btusb_intel_secure_send_result(data, ptr, len); - break; - } - } - } - if (test_bit(INTEL_BOOTLOADER, &intel->flags)) { struct hci_event_hdr *hdr = (void *)skb->data; @@ -2106,7 +2048,6 @@ static int btusb_recv_event_intel(struct hci_dev *hdev, struct sk_buff *skb) static int btusb_send_frame_intel(struct hci_dev *hdev, struct sk_buff *skb) { - struct btusb_data *data = hci_get_drvdata(hdev); struct btintel_data *intel = hci_get_priv(hdev); struct urb *urb; @@ -2114,8 +2055,7 @@ static int btusb_send_frame_intel(struct hci_dev *hdev, struct sk_buff *skb) switch (hci_skb_pkt_type(skb)) { case HCI_COMMAND_PKT: - if (test_bit(BTUSB_BOOTLOADER, &data->flags) || - test_bit(INTEL_BOOTLOADER, &intel->flags)) { + if (test_bit(INTEL_BOOTLOADER, &intel->flags)) { struct hci_command_hdr *cmd = (void *)skb->data; __u16 opcode = le16_to_cpu(cmd->opcode); @@ -2167,330 +2107,6 @@ static int btusb_send_frame_intel(struct hci_dev *hdev, struct sk_buff *skb) return -EILSEQ; } -static void btusb_setup_intel_newgen_get_fw_name(const struct intel_version_tlv *ver_tlv, - char *fw_name, size_t len, - const char *suffix) -{ - /* The firmware file name for new generation controllers will be - * ibt-- - */ - snprintf(fw_name, len, "intel/ibt-%04x-%04x.%s", - INTEL_CNVX_TOP_PACK_SWAB(INTEL_CNVX_TOP_TYPE(ver_tlv->cnvi_top), - INTEL_CNVX_TOP_STEP(ver_tlv->cnvi_top)), - INTEL_CNVX_TOP_PACK_SWAB(INTEL_CNVX_TOP_TYPE(ver_tlv->cnvr_top), - INTEL_CNVX_TOP_STEP(ver_tlv->cnvr_top)), - suffix); -} - -static int btusb_download_wait(struct hci_dev *hdev, ktime_t calltime, int msec) -{ - struct btusb_data *data = hci_get_drvdata(hdev); - ktime_t delta, rettime; - unsigned long long duration; - int err; - - set_bit(BTUSB_FIRMWARE_LOADED, &data->flags); - - bt_dev_info(hdev, "Waiting for firmware download to complete"); - - err = wait_on_bit_timeout(&data->flags, BTUSB_DOWNLOADING, - TASK_INTERRUPTIBLE, - msecs_to_jiffies(msec)); - if (err == -EINTR) { - bt_dev_err(hdev, "Firmware loading interrupted"); - return err; - } - - if (err) { - bt_dev_err(hdev, "Firmware loading timeout"); - return -ETIMEDOUT; - } - - if (test_bit(BTUSB_FIRMWARE_FAILED, &data->flags)) { - bt_dev_err(hdev, "Firmware loading failed"); - return -ENOEXEC; - } - - rettime = ktime_get(); - delta = ktime_sub(rettime, calltime); - duration = (unsigned long long)ktime_to_ns(delta) >> 10; - - bt_dev_info(hdev, "Firmware loaded in %llu usecs", duration); - - return 0; -} - -static int btusb_intel_download_firmware_newgen(struct hci_dev *hdev, - struct intel_version_tlv *ver, - u32 *boot_param) -{ - const struct firmware *fw; - char fwname[64]; - int err; - struct btusb_data *data = hci_get_drvdata(hdev); - ktime_t calltime; - - if (!ver || !boot_param) - return -EINVAL; - - /* The firmware variant determines if the device is in bootloader - * mode or is running operational firmware. The value 0x03 identifies - * the bootloader and the value 0x23 identifies the operational - * firmware. - * - * When the operational firmware is already present, then only - * the check for valid Bluetooth device address is needed. This - * determines if the device will be added as configured or - * unconfigured controller. - * - * It is not possible to use the Secure Boot Parameters in this - * case since that command is only available in bootloader mode. - */ - if (ver->img_type == 0x03) { - clear_bit(BTUSB_BOOTLOADER, &data->flags); - btintel_check_bdaddr(hdev); - } - - /* If the OTP has no valid Bluetooth device address, then there will - * also be no valid address for the operational firmware. - */ - if (!bacmp(&ver->otp_bd_addr, BDADDR_ANY)) { - bt_dev_info(hdev, "No device address configured"); - set_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks); - } - - btusb_setup_intel_newgen_get_fw_name(ver, fwname, sizeof(fwname), "sfi"); - err = firmware_request_nowarn(&fw, fwname, &hdev->dev); - if (err < 0) { - if (!test_bit(BTUSB_BOOTLOADER, &data->flags)) { - /* Firmware has already been loaded */ - set_bit(BTUSB_FIRMWARE_LOADED, &data->flags); - return 0; - } - - bt_dev_err(hdev, "Failed to load Intel firmware file %s (%d)", - fwname, err); - - return err; - } - - bt_dev_info(hdev, "Found device firmware: %s", fwname); - - if (fw->size < 644) { - bt_dev_err(hdev, "Invalid size of firmware file (%zu)", - fw->size); - err = -EBADF; - goto done; - } - - calltime = ktime_get(); - - set_bit(BTUSB_DOWNLOADING, &data->flags); - - /* Start firmware downloading and get boot parameter */ - err = btintel_download_firmware_newgen(hdev, ver, fw, boot_param, - INTEL_HW_VARIANT(ver->cnvi_bt), - ver->sbe_type); - if (err < 0) { - if (err == -EALREADY) { - /* Firmware has already been loaded */ - set_bit(BTUSB_FIRMWARE_LOADED, &data->flags); - err = 0; - goto done; - } - - /* When FW download fails, send Intel Reset to retry - * FW download. - */ - btintel_reset_to_bootloader(hdev); - goto done; - } - - /* Before switching the device into operational mode and with that - * booting the loaded firmware, wait for the bootloader notification - * that all fragments have been successfully received. - * - * When the event processing receives the notification, then the - * BTUSB_DOWNLOADING flag will be cleared. - * - * The firmware loading should not take longer than 5 seconds - * and thus just timeout if that happens and fail the setup - * of this device. - */ - err = btusb_download_wait(hdev, calltime, 5000); - if (err == -ETIMEDOUT) - btintel_reset_to_bootloader(hdev); - -done: - release_firmware(fw); - return err; -} - -static int btusb_boot_wait(struct hci_dev *hdev, ktime_t calltime, int msec) -{ - struct btusb_data *data = hci_get_drvdata(hdev); - ktime_t delta, rettime; - unsigned long long duration; - int err; - - bt_dev_info(hdev, "Waiting for device to boot"); - - err = wait_on_bit_timeout(&data->flags, BTUSB_BOOTING, - TASK_INTERRUPTIBLE, - msecs_to_jiffies(msec)); - if (err == -EINTR) { - bt_dev_err(hdev, "Device boot interrupted"); - return -EINTR; - } - - if (err) { - bt_dev_err(hdev, "Device boot timeout"); - return -ETIMEDOUT; - } - - rettime = ktime_get(); - delta = ktime_sub(rettime, calltime); - duration = (unsigned long long) ktime_to_ns(delta) >> 10; - - bt_dev_info(hdev, "Device booted in %llu usecs", duration); - - return 0; -} - -static int btusb_intel_boot(struct hci_dev *hdev, u32 boot_addr) -{ - struct btusb_data *data = hci_get_drvdata(hdev); - ktime_t calltime; - int err; - - calltime = ktime_get(); - - set_bit(BTUSB_BOOTING, &data->flags); - - err = btintel_send_intel_reset(hdev, boot_addr); - if (err) { - bt_dev_err(hdev, "Intel Soft Reset failed (%d)", err); - btintel_reset_to_bootloader(hdev); - return err; - } - - /* The bootloader will not indicate when the device is ready. This - * is done by the operational firmware sending bootup notification. - * - * Booting into operational firmware should not take longer than - * 1 second. However if that happens, then just fail the setup - * since something went wrong. - */ - err = btusb_boot_wait(hdev, calltime, 1000); - if (err == -ETIMEDOUT) - btintel_reset_to_bootloader(hdev); - - return err; -} - -static int btusb_setup_intel_newgen(struct hci_dev *hdev) -{ - struct btusb_data *data = hci_get_drvdata(hdev); - u32 boot_param; - char ddcname[64]; - int err; - struct intel_debug_features features; - struct intel_version_tlv version; - - bt_dev_dbg(hdev, ""); - - /* Set the default boot parameter to 0x0 and it is updated to - * SKU specific boot parameter after reading Intel_Write_Boot_Params - * command while downloading the firmware. - */ - boot_param = 0x00000000; - - /* Read the Intel version information to determine if the device - * is in bootloader mode or if it already has operational firmware - * loaded. - */ - err = btintel_read_version_tlv(hdev, &version); - if (err) { - bt_dev_err(hdev, "Intel Read version failed (%d)", err); - btintel_reset_to_bootloader(hdev); - return err; - } - - err = btintel_version_info_tlv(hdev, &version); - if (err) - return err; - - err = btusb_intel_download_firmware_newgen(hdev, &version, &boot_param); - if (err) - return err; - - /* check if controller is already having an operational firmware */ - if (version.img_type == 0x03) - goto finish; - - err = btusb_intel_boot(hdev, boot_param); - if (err) - return err; - - clear_bit(BTUSB_BOOTLOADER, &data->flags); - - btusb_setup_intel_newgen_get_fw_name(&version, ddcname, sizeof(ddcname), - "ddc"); - /* Once the device is running in operational mode, it needs to - * apply the device configuration (DDC) parameters. - * - * The device can work without DDC parameters, so even if it - * fails to load the file, no need to fail the setup. - */ - btintel_load_ddc_config(hdev, ddcname); - - /* Read the Intel supported features and if new exception formats - * supported, need to load the additional DDC config to enable. - */ - err = btintel_read_debug_features(hdev, &features); - if (!err) { - /* Set DDC mask for available debug features */ - btintel_set_debug_features(hdev, &features); - } - - /* Read the Intel version information after loading the FW */ - err = btintel_read_version_tlv(hdev, &version); - if (err) - return err; - - btintel_version_info_tlv(hdev, &version); - -finish: - /* Set the event mask for Intel specific vendor events. This enables - * a few extra events that are useful during general operation. It - * does not enable any debugging related events. - * - * The device will function correctly without these events enabled - * and thus no need to fail the setup. - */ - btintel_set_event_mask(hdev, false); - - return 0; -} - -static int btusb_shutdown_intel_new(struct hci_dev *hdev) -{ - struct sk_buff *skb; - - /* Send HCI Reset to the controller to stop any BT activity which - * were triggered. This will help to save power and maintain the - * sync b/w Host and controller - */ - skb = __hci_cmd_sync(hdev, HCI_OP_RESET, 0, NULL, HCI_INIT_TIMEOUT); - if (IS_ERR(skb)) { - bt_dev_err(hdev, "HCI reset during shutdown failed"); - return PTR_ERR(skb); - } - kfree_skb(skb); - - return 0; -} - #define FIRMWARE_MT7663 "mediatek/mt7663pr2h.bin" #define FIRMWARE_MT7668 "mediatek/mt7668pr2h.bin" @@ -3966,8 +3582,7 @@ static int btusb_probe(struct usb_interface *intf, data->recv_event = hci_recv_frame; data->recv_bulk = btusb_recv_bulk; - if (id->driver_info & BTUSB_INTEL_COMBINED || - id->driver_info & BTUSB_INTEL_NEW) { + if (id->driver_info & BTUSB_INTEL_COMBINED) { /* Allocate extra space for Intel device */ priv_size += sizeof(struct btintel_data); @@ -4071,24 +3686,6 @@ static int btusb_probe(struct usb_interface *intf, btintel_set_flags(hdev, INTEL_BROKEN_LED); } - if (id->driver_info & BTUSB_INTEL_NEWGEN) { - hdev->manufacturer = 2; - hdev->send = btusb_send_frame_intel; - hdev->setup = btusb_setup_intel_newgen; - hdev->shutdown = btusb_shutdown_intel_new; - hdev->hw_error = btintel_hw_error; - hdev->set_diag = btintel_set_diag; - hdev->set_bdaddr = btintel_set_bdaddr; - hdev->cmd_timeout = btusb_intel_cmd_timeout; - set_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks); - set_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY, &hdev->quirks); - set_bit(HCI_QUIRK_NON_PERSISTENT_DIAG, &hdev->quirks); - - data->recv_event = btusb_recv_event_intel; - data->recv_bulk = btusb_recv_bulk_intel; - set_bit(BTUSB_BOOTLOADER, &data->flags); - } - if (id->driver_info & BTUSB_MARVELL) hdev->set_bdaddr = btusb_set_bdaddr_marvell; From patchwork Tue Jul 27 23:51:26 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tedd Ho-Jeong An X-Patchwork-Id: 12404687 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.7 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id C4905C4320A for ; Tue, 27 Jul 2021 23:51:54 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id AF8B460FA0 for ; Tue, 27 Jul 2021 23:51:54 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233883AbhG0Xvx (ORCPT ); Tue, 27 Jul 2021 19:51:53 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37224 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233709AbhG0Xvu (ORCPT ); Tue, 27 Jul 2021 19:51:50 -0400 Received: from mail-pj1-x102f.google.com (mail-pj1-x102f.google.com [IPv6:2607:f8b0:4864:20::102f]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 78376C061765 for ; Tue, 27 Jul 2021 16:51:48 -0700 (PDT) Received: by mail-pj1-x102f.google.com with SMTP id pf12-20020a17090b1d8cb0290175c085e7a5so7275274pjb.0 for ; Tue, 27 Jul 2021 16:51:48 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=jIj4LSRHJj+nUrzMRomDFsfCDLySvb1T1lr9q3VJMXU=; b=ufq+Fc2MJSxLSZqurAk1DgmuBK2Pl/NDtAV737S4JACfaLOpxSLeLayH9EEf05GVUd autsgH0BTKjlbNylwRByrJuEj0I/krnf5scVFAeKjcTqfQFjjhofO1VCfmSD4BCd+Xcr kKa4OumXEU3wky3C+Qe21cT40lVqUPWMSyyheLHtGu7oZTaQmahLVv+rhu9ZjpFmTnPR XIH3bobWRtGufbvUWuJKB35d34OqSh1EwPoNf81/4gEVuPaAed7Pw5JTaOzmAzSa3D1/ TvUHUcsxWi5yRLV+zCiLIChfj19U1Vv66JaMHBnfnX1PikAXzrmlr5NosOXjlJNBOUOW Jo3A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=jIj4LSRHJj+nUrzMRomDFsfCDLySvb1T1lr9q3VJMXU=; b=WOKduloKIcY/E2xTSQsb9yjPKd6JeGQMqIGnpHWCKDm+mpZ63ALGbuWssHml/8kqhs d+p5xP0DoxEAGq4if2q5Bu2YXgZjS50d1LQQBnBM0HoCYLO2gBKIV055IMHDKNZGKLUY oorcR7OGKGABwccOViKpj0T/GZneDicQzHRS9l1GEqWsG+xxJSN2KxqDQGo6VuM8bcHL AoRucadGiEhO941w/YVjJ/R1tc6yn/qYgpXZGbmUu2n1MR6VMRjPlqznrMDvSpRG2UxR NUdENqmwjg90VEiVJIh025JIDLl+DnzgkkVAs2+3A10vIKtEJyX9KkqroyhXaFaubfxR cSMg== X-Gm-Message-State: AOAM533L7IECSw/4S/Of0cYfTaqzNMzNWOFsIX0IxrsKJUFunLwWWVHF 42+39Nzimav9sVehn81TxI5AZe+yLao= X-Google-Smtp-Source: ABdhPJwWhlE10TqEvRz26Do1lIgplbFmGuOjmR5Wp8x+tAjbOQVCke3BYVkBR3KBZqxv1mOLxYJj/g== X-Received: by 2002:a05:6a00:2494:b029:340:298b:acf7 with SMTP id c20-20020a056a002494b0290340298bacf7mr25454029pfv.18.1627429907817; Tue, 27 Jul 2021 16:51:47 -0700 (PDT) Received: from localhost.localdomain ([2601:1c0:6a01:d830::7cb2]) by smtp.gmail.com with ESMTPSA id y9sm1545332pfq.199.2021.07.27.16.51.47 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 27 Jul 2021 16:51:47 -0700 (PDT) From: Tedd Ho-Jeong An To: linux-bluetooth@vger.kernel.org Cc: Tedd Ho-Jeong An Subject: [RFC PATCH v4 10/11] Bluetooth: btintel: Clean the exported function to static Date: Tue, 27 Jul 2021 16:51:26 -0700 Message-Id: <20210727235127.173149-11-hj.tedd.an@gmail.com> X-Mailer: git-send-email 2.26.3 In-Reply-To: <20210727235127.173149-1-hj.tedd.an@gmail.com> References: <20210727235127.173149-1-hj.tedd.an@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-bluetooth@vger.kernel.org From: Tedd Ho-Jeong An This patch changes the exported functions to static if they are no longer used by others. Signed-off-by: Tedd Ho-Jeong An --- drivers/bluetooth/btintel.c | 65 +++++++++++++++++-------------------- drivers/bluetooth/btintel.h | 50 ---------------------------- 2 files changed, 30 insertions(+), 85 deletions(-) diff --git a/drivers/bluetooth/btintel.c b/drivers/bluetooth/btintel.c index dc5e2b255605..57b64d744f0a 100644 --- a/drivers/bluetooth/btintel.c +++ b/drivers/bluetooth/btintel.c @@ -131,6 +131,26 @@ int btintel_set_bdaddr(struct hci_dev *hdev, const bdaddr_t *bdaddr) } EXPORT_SYMBOL_GPL(btintel_set_bdaddr); +static int btintel_set_event_mask(struct hci_dev *hdev, bool debug) +{ + u8 mask[8] = { 0x87, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + struct sk_buff *skb; + int err; + + if (debug) + mask[1] |= 0x62; + + skb = __hci_cmd_sync(hdev, 0xfc52, 8, mask, HCI_INIT_TIMEOUT); + if (IS_ERR(skb)) { + err = PTR_ERR(skb); + bt_dev_err(hdev, "Setting Intel event mask failed (%d)", err); + return err; + } + kfree_skb(skb); + + return 0; +} + int btintel_set_diag(struct hci_dev *hdev, bool enable) { struct sk_buff *skb; @@ -296,8 +316,8 @@ int btintel_version_info(struct hci_dev *hdev, struct intel_version *ver) } EXPORT_SYMBOL_GPL(btintel_version_info); -int btintel_secure_send(struct hci_dev *hdev, u8 fragment_type, u32 plen, - const void *param) +static int btintel_secure_send(struct hci_dev *hdev, u8 fragment_type, u32 plen, + const void *param) { while (plen > 0) { struct sk_buff *skb; @@ -319,7 +339,6 @@ int btintel_secure_send(struct hci_dev *hdev, u8 fragment_type, u32 plen, return 0; } -EXPORT_SYMBOL_GPL(btintel_secure_send); int btintel_load_ddc_config(struct hci_dev *hdev, const char *ddc_name) { @@ -366,27 +385,6 @@ int btintel_load_ddc_config(struct hci_dev *hdev, const char *ddc_name) } EXPORT_SYMBOL_GPL(btintel_load_ddc_config); -int btintel_set_event_mask(struct hci_dev *hdev, bool debug) -{ - u8 mask[8] = { 0x87, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; - struct sk_buff *skb; - int err; - - if (debug) - mask[1] |= 0x62; - - skb = __hci_cmd_sync(hdev, 0xfc52, 8, mask, HCI_INIT_TIMEOUT); - if (IS_ERR(skb)) { - err = PTR_ERR(skb); - bt_dev_err(hdev, "Setting Intel event mask failed (%d)", err); - return err; - } - kfree_skb(skb); - - return 0; -} -EXPORT_SYMBOL_GPL(btintel_set_event_mask); - int btintel_set_event_mask_mfg(struct hci_dev *hdev, bool debug) { int err, ret; @@ -430,7 +428,8 @@ int btintel_read_version(struct hci_dev *hdev, struct intel_version *ver) } EXPORT_SYMBOL_GPL(btintel_read_version); -int btintel_version_info_tlv(struct hci_dev *hdev, struct intel_version_tlv *version) +static int btintel_version_info_tlv(struct hci_dev *hdev, + struct intel_version_tlv *version) { const char *variant; @@ -507,7 +506,6 @@ int btintel_version_info_tlv(struct hci_dev *hdev, struct intel_version_tlv *ver return 0; } -EXPORT_SYMBOL_GPL(btintel_version_info_tlv); static int btintel_parse_version_tlv(struct hci_dev *hdev, struct intel_version_tlv *version, @@ -601,7 +599,8 @@ static int btintel_parse_version_tlv(struct hci_dev *hdev, return 0; } -int btintel_read_version_tlv(struct hci_dev *hdev, struct intel_version_tlv *version) +static int btintel_read_version_tlv(struct hci_dev *hdev, + struct intel_version_tlv *version) { struct sk_buff *skb; const u8 param[1] = { 0xFF }; @@ -628,7 +627,6 @@ int btintel_read_version_tlv(struct hci_dev *hdev, struct intel_version_tlv *ver kfree_skb(skb); return 0; } -EXPORT_SYMBOL_GPL(btintel_read_version_tlv); /* ------- REGMAP IBT SUPPORT ------- */ @@ -1202,7 +1200,7 @@ static int btintel_download_fw_tlv(struct hci_dev *hdev, return 0; } -void btintel_reset_to_bootloader(struct hci_dev *hdev) +static void btintel_reset_to_bootloader(struct hci_dev *hdev) { struct intel_reset params; struct sk_buff *skb; @@ -1245,10 +1243,9 @@ void btintel_reset_to_bootloader(struct hci_dev *hdev) */ msleep(150); } -EXPORT_SYMBOL_GPL(btintel_reset_to_bootloader); -int btintel_read_debug_features(struct hci_dev *hdev, - struct intel_debug_features *features) +static int btintel_read_debug_features(struct hci_dev *hdev, + struct intel_debug_features *features) { struct sk_buff *skb; u8 page_no = 1; @@ -1277,9 +1274,8 @@ int btintel_read_debug_features(struct hci_dev *hdev, kfree_skb(skb); return 0; } -EXPORT_SYMBOL_GPL(btintel_read_debug_features); -int btintel_set_debug_features(struct hci_dev *hdev, +static int btintel_set_debug_features(struct hci_dev *hdev, const struct intel_debug_features *features) { u8 mask[11] = { 0x0a, 0x92, 0x02, 0x07, 0x00, 0x00, 0x00, 0x00, @@ -1304,7 +1300,6 @@ int btintel_set_debug_features(struct hci_dev *hdev, kfree_skb(skb); return 0; } -EXPORT_SYMBOL_GPL(btintel_set_debug_features); static const struct firmware *btintel_legacy_rom_get_fw(struct hci_dev *hdev, struct intel_version *ver) diff --git a/drivers/bluetooth/btintel.h b/drivers/bluetooth/btintel.h index 696656fd7e99..71af25cd1672 100644 --- a/drivers/bluetooth/btintel.h +++ b/drivers/bluetooth/btintel.h @@ -162,15 +162,9 @@ int btintel_set_diag_combined(struct hci_dev *hdev, bool enable); void btintel_hw_error(struct hci_dev *hdev, u8 code); int btintel_version_info(struct hci_dev *hdev, struct intel_version *ver); -int btintel_version_info_tlv(struct hci_dev *hdev, struct intel_version_tlv *version); -int btintel_secure_send(struct hci_dev *hdev, u8 fragment_type, u32 plen, - const void *param); int btintel_load_ddc_config(struct hci_dev *hdev, const char *ddc_name); -int btintel_set_event_mask(struct hci_dev *hdev, bool debug); int btintel_set_event_mask_mfg(struct hci_dev *hdev, bool debug); int btintel_read_version(struct hci_dev *hdev, struct intel_version *ver); -int btintel_read_version_tlv(struct hci_dev *hdev, struct intel_version_tlv *ver); - struct regmap *btintel_regmap_init(struct hci_dev *hdev, u16 opcode_read, u16 opcode_write); int btintel_send_intel_reset(struct hci_dev *hdev, u32 boot_param); @@ -181,11 +175,6 @@ int btintel_download_firmware(struct hci_dev *dev, struct intel_version *ver, int btintel_setup_combined(struct hci_dev *hdev); int btintel_shutdown_combined(struct hci_dev *hdev); void btintel_set_flags(struct hci_dev *hdev, unsigned int flag); -void btintel_reset_to_bootloader(struct hci_dev *hdev); -int btintel_read_debug_features(struct hci_dev *hdev, - struct intel_debug_features *features); -int btintel_set_debug_features(struct hci_dev *hdev, - const struct intel_debug_features *features); void btintel_bootup(struct hci_dev *hdev, const void *ptr, unsigned int len); void btintel_secure_send_result(struct hci_dev *hdev, const void *ptr, unsigned int len); @@ -231,29 +220,12 @@ static inline int btintel_version_info(struct hci_dev *hdev, return -EOPNOTSUPP; } -static inline int btintel_version_info_tlv(struct hci_dev *hdev, - struct intel_version_tlv *version) -{ - return -EOPNOTSUPP; -} - -static inline int btintel_secure_send(struct hci_dev *hdev, u8 fragment_type, - u32 plen, const void *param) -{ - return -EOPNOTSUPP; -} - static inline int btintel_load_ddc_config(struct hci_dev *hdev, const char *ddc_name) { return -EOPNOTSUPP; } -static inline int btintel_set_event_mask(struct hci_dev *hdev, bool debug) -{ - return -EOPNOTSUPP; -} - static inline int btintel_set_event_mask_mfg(struct hci_dev *hdev, bool debug) { return -EOPNOTSUPP; @@ -265,12 +237,6 @@ static inline int btintel_read_version(struct hci_dev *hdev, return -EOPNOTSUPP; } -static inline int btintel_read_version_tlv(struct hci_dev *hdev, - struct intel_version_tlv *ver) -{ - return -EOPNOTSUPP; -} - static inline struct regmap *btintel_regmap_init(struct hci_dev *hdev, u16 opcode_read, u16 opcode_write) @@ -311,22 +277,6 @@ static inline void btintel_set_flags(struct hci_dev *hdev, unsigned int flag) { } -static inline void btintel_reset_to_bootloader(struct hci_dev *hdev) -{ -} - -static inline int btintel_read_debug_features(struct hci_dev *hdev, - struct intel_debug_features *features) -{ - return -EOPNOTSUPP; -} - -static inline int btintel_set_debug_features(struct hci_dev *hdev, - const struct intel_debug_features *features) -{ - return -EOPNOTSUPP; -} - static inline void btintel_bootup(struct hci_dev *hdev, const void *ptr, unsigned int len) { From patchwork Tue Jul 27 23:51:27 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tedd Ho-Jeong An X-Patchwork-Id: 12404689 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.7 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 4F5D3C43216 for ; Tue, 27 Jul 2021 23:51:55 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 33D9760FD8 for ; Tue, 27 Jul 2021 23:51:55 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233731AbhG0Xvz (ORCPT ); Tue, 27 Jul 2021 19:51:55 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37232 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233553AbhG0Xvu (ORCPT ); Tue, 27 Jul 2021 19:51:50 -0400 Received: from mail-pl1-x636.google.com (mail-pl1-x636.google.com [IPv6:2607:f8b0:4864:20::636]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 26A05C061764 for ; Tue, 27 Jul 2021 16:51:49 -0700 (PDT) Received: by mail-pl1-x636.google.com with SMTP id k1so435861plt.12 for ; Tue, 27 Jul 2021 16:51:49 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=PffmxY3Txm8DGIrTncbEm9nKetf0x7Nku6FrCvIyZ88=; b=e2UeuhRxk67ni5dzkA3YzZuhVQY6AMEAWi+leVZDPQM7TnzZ/QDEOOKFGXP8VcaqyW PZWANhL2hpw+a3kd2WELyC1Hjz4lPaVYpnUu+TK7z7TLs3Lg5aCOj1XtNxc/AuD5qkmr pmj3sCwi9un7tDh4pHNI01d1BIHMetb9gMdEpmtefHkJcu6C3fporqyCoPvxnYPkPIjT 5IhGNT6PU//B7Pc3S2iQrN56MkSGGtnq1zzU28ZsMll9e2RBEDBuiD3y/F3F+OYEBAxD SCfIX2iXJoGIcn+BD4xeRG5/sYChCm0KpufPFnrrxqIF26/k2WNa3lS8ZIAzqHrWq/I6 BR7A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=PffmxY3Txm8DGIrTncbEm9nKetf0x7Nku6FrCvIyZ88=; b=GNxFP0vhn5VE4XzJfbD+yFqfbOsxVqx8vrO7fHU7vfBF5nj9wobC9bG/bdY4jKYArX g7nJdK/fHtZZn0f+nBETfBVr368Idgm3XAwGt91Zm8jtnTEzFAbX2QofJmBy38+HrbUy TEDtkFIK0Ushy9QFTxE8PUvi1+p4H8UfdbA3q9QF3YeWDrx/5VJQuiWYWqiI/yqlbqKo ZZPZsMQY94AfctZrb1k1IHou75dY0NESlCZ+8NyO4XMRVaVn1Ka04igWvR2Y+zUQ2jNb K9zRSHHUhNgMc39f0FacW2j1ps9GxOo9kIA8EfWvlUqujLN7sTJf8oO1GS02zBbAbpaM wpRg== X-Gm-Message-State: AOAM5327kqDGEcoay4w6H57LAha1Hi5jUwlmZKQmnCHPQhxCxk3QUR7t RnJ0czQ1LKIz/0H4Z8HPlFAbK426tFw= X-Google-Smtp-Source: ABdhPJzD0A8zKMzfgUaD1kSwU6VF/QIoqXpjVuQWAG9LM52rTQ3IYirfLO6AjAQb+bhsu+5YS37NzA== X-Received: by 2002:a17:902:c20c:b029:12a:edee:a7fa with SMTP id 12-20020a170902c20cb029012aedeea7famr21064839pll.2.1627429908487; Tue, 27 Jul 2021 16:51:48 -0700 (PDT) Received: from localhost.localdomain ([2601:1c0:6a01:d830::7cb2]) by smtp.gmail.com with ESMTPSA id y9sm1545332pfq.199.2021.07.27.16.51.47 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 27 Jul 2021 16:51:48 -0700 (PDT) From: Tedd Ho-Jeong An To: linux-bluetooth@vger.kernel.org Cc: Tedd Ho-Jeong An Subject: [RFC PATCH v4 11/11] Bluetooth: btintel: Fix the legacy bootloader returns tlv based version Date: Tue, 27 Jul 2021 16:51:27 -0700 Message-Id: <20210727235127.173149-12-hj.tedd.an@gmail.com> X-Mailer: git-send-email 2.26.3 In-Reply-To: <20210727235127.173149-1-hj.tedd.an@gmail.com> References: <20210727235127.173149-1-hj.tedd.an@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-bluetooth@vger.kernel.org From: Tedd Ho-Jeong An From the ThP, it supports both old and TLV based HCI_Intel_Read_Version command after downloading the operational firmware. Starting from th JfP, it supports both old and TLV based HCI_Intel_Read_Version command in the operational firmware and it causes the setup() uses the TLV based setup instead of legacy setup. So, as a workaround, this patch checks the fw variant from the TLV based version and it uses the legacy HCI_Intel_Read_Version command to get the legacy version information and run the legacy bootloader setup with it. Signed-off-by: Tedd Ho-Jeong An --- drivers/bluetooth/btintel.c | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/drivers/bluetooth/btintel.c b/drivers/bluetooth/btintel.c index 57b64d744f0a..7bc9bb65a5be 100644 --- a/drivers/bluetooth/btintel.c +++ b/drivers/bluetooth/btintel.c @@ -2254,10 +2254,33 @@ int btintel_setup_combined(struct hci_dev *hdev) /* For TLV type device, parse the tlv data */ btintel_parse_version_tlv(hdev, &ver_tlv, skb); + /* Some legacy bootloader devices from JfP supports both old and TLV + * based HCI_Intel_Read_Version command. But we don't want to use the + * TLV based setup routines for those old bootloader device. + * Also, it is not easy to convert TLV based version to the legacy + * version format. + * + * So, as a workaround for those devices, use the legacy + * HCI_Intel_Read_Version to get the version information and run the + * legacy bootloader setup. + */ + switch(INTEL_HW_VARIANT(ver_tlv.cnvi_bt)) { + case 0x11: /* JfP */ + case 0x12: /* ThP */ + case 0x13: /* HrP */ + case 0x14: /* CcP */ + err = btintel_read_version(hdev, &ver); + if (err) + return err; + return btintel_bootloader_setup(hdev, &ver); + default: + /* Nothing to do here */ + break; + } + /* Display version information of TLV type */ btintel_version_info_tlv(hdev, &ver_tlv); - /* TODO: Need to filter the device for new generation */ err = btintel_bootloader_setup_tlv(hdev, &ver_tlv); return err;