Received: by 2002:a05:6359:c8b:b0:c7:702f:21d4 with SMTP id go11csp1164991rwb; Tue, 4 Oct 2022 16:47:38 -0700 (PDT) X-Google-Smtp-Source: AMsMyM44d0b8VOUTuAg5qGD+bc3NX7xkxPAQdEmmLQdiy6zC5YTtBqI81xqxrZ7H1jJ1LKPQamT2 X-Received: by 2002:a17:90b:3808:b0:202:c5ba:d71b with SMTP id mq8-20020a17090b380800b00202c5bad71bmr2144962pjb.18.1664927258337; Tue, 04 Oct 2022 16:47:38 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1664927258; cv=none; d=google.com; s=arc-20160816; b=sek8BD/n8jhgZQopoVv3MVHiSJTSgmN3XoL/bW0Np3scEotlojEh3Cfs2ZlNYQM6w/ 3XnKSyRvqJXHgZay2CoTyOETNKHQNeMNF0a+SEA/b785ndYIpq64Dm0m29VWBWnaZwtH aHSgpSkB1HTUHWKOXL4tpaPEH99XIsDK+jjeJXPu4tsnZNm4qMvFkIhUYbYqN1mrgqh3 lvYf4yz8Yj/IPOpypqcjeaL8PzUEUwMBa+YBzfyxub6Gga8rPYHe0Zwno9dzEbeWQKQ4 eLdJykMngB7haodRpmGc3NgLsUNHFiH3qeTBS58bBD89adx/aEnHW2Brm3VnWjiKo/cr PNRA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:cc:to:subject:message-id:date:from:in-reply-to :references:mime-version:dkim-signature; bh=whALt7pNVL+koxRXWTvV8NjAjJN74CteWKaDreVtPBI=; b=UIQQOWh6Q5+z3Wac/du6Cw7pUxiuY2O+QE4fOWc1jvrazunZfRDh3eiNd9OdTuT6Du RPs8qTfy/boLooWT8xTG5mtyGcEwWcoMdqNshrtmA/9BROQkyGIkfRqLsiMCmsccfbSX Jbpc+/7PPV2otghlUnNRJ9PlTv1UO8adUIAH1MJBoSKiDAoiMix9zGw7gmFVTVb8EoTl wz2B3Te+zlXyQQi/in9LCePCVnUmr30MzOr2/W4YvWadJJyb0nReiFMgCtW+p2LbIOnl zsz7DVPVqRySapUWZNDgDafOIlScLAayQpWGyHNpJtpI7mb1YrjZIgI2sVTlpmb9ZAvE IxZg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gmail.com header.s=20210112 header.b=bWFdSiPi; spf=pass (google.com: domain of linux-bluetooth-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-bluetooth-owner@vger.kernel.org; dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Return-Path: Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id h131-20020a636c89000000b00457bc51e1a4si1165206pgc.506.2022.10.04.16.47.26; Tue, 04 Oct 2022 16:47:38 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-bluetooth-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@gmail.com header.s=20210112 header.b=bWFdSiPi; spf=pass (google.com: domain of linux-bluetooth-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-bluetooth-owner@vger.kernel.org; dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229468AbiJDXqs (ORCPT + 99 others); Tue, 4 Oct 2022 19:46:48 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:58370 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229462AbiJDXqr (ORCPT ); Tue, 4 Oct 2022 19:46:47 -0400 Received: from mail-lf1-x136.google.com (mail-lf1-x136.google.com [IPv6:2a00:1450:4864:20::136]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 6E32E12D3A for ; Tue, 4 Oct 2022 16:46:40 -0700 (PDT) Received: by mail-lf1-x136.google.com with SMTP id y5so3679713lfl.4 for ; Tue, 04 Oct 2022 16:46:39 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:from:to:cc:subject:date; bh=whALt7pNVL+koxRXWTvV8NjAjJN74CteWKaDreVtPBI=; b=bWFdSiPieg1VEi5s/sGOVWR/fRpnWI1mFobPEqc/xK6CG03C+BKc+9KT7zIM5pKNq7 giweksMEb2UEnlF501kvss0u7/VGQJiRphb5pia2fEHCcfxxEuZsyBX220kR59tZgDKz AGRgCtiEYv/PF1ztaZT8+mPWMIggV9ICTx2yB4QDzzR/xFek6XR5dRZv5UgDN7mu+jvM pXZVP+WfVFp7+0lsH4EWsyiGJRtY/9ldOUCKD6YXbVKc2gdzOFIu0TcFxIgD6VY7tnCv fdnpARonifkTdhd1GXo4sbYAJQCX90YfiwVzPEW4LMnMk8uHs+wXknxOGKz5ekaF0aGS Jgdw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:x-gm-message-state:from:to:cc:subject:date; bh=whALt7pNVL+koxRXWTvV8NjAjJN74CteWKaDreVtPBI=; b=jflrSKj7Phpka3wH8v03hWJNAsw5s22z/YEa0o4TFNxi/F4MxU9n27+h9DclckBs4u rZ9zoFZwB80b1fIBp05V2EJNn84vaW2PhdFDuXKn5n64zWSCq++EQM4NHGPNkGzkmF8m 5HirM6hKNtuKNKp0H9eoRDIGRnNsUxseP/7rZ/2uvjwjPscpPreMFjMMfleIPMVJYjNW R4kUdQkYiv4QLk2/iDRp1x7TvAOpQxKh1D6cyqg/nHEOogVvLMsLXTHHNqGS6lbIHEmk oCoyB5roo9eSmX3YdS1cRCZV3Xe1b2upG7loViIic13iuySV9EIg6h83I1KE0Zu4YjMz 3qRQ== X-Gm-Message-State: ACrzQf1VqfBbdKfpnl7p76R+SnXvk5kVTiAkEFTAuRujB322c3jNmi5V UFsR8qIVBaYapsBLLs4hN7xhdYG8rcqqFpFTUamNXgVm X-Received: by 2002:a05:6512:2150:b0:4a2:2f09:9629 with SMTP id s16-20020a056512215000b004a22f099629mr5488152lfr.198.1664927198079; Tue, 04 Oct 2022 16:46:38 -0700 (PDT) MIME-Version: 1.0 References: <20221004145351.13066-1-nicolas.cavallari@green-communications.fr> In-Reply-To: <20221004145351.13066-1-nicolas.cavallari@green-communications.fr> From: Luiz Augusto von Dentz Date: Tue, 4 Oct 2022 16:46:26 -0700 Message-ID: Subject: Re: [PATCH] Bluetooth: Work around SCO over USB HCI design defect To: Nicolas Cavallari Cc: Marcel Holtmann , Johan Hedberg , linux-bluetooth@vger.kernel.org Content-Type: text/plain; charset="UTF-8" X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,FREEMAIL_FROM, RCVD_IN_DNSWL_NONE,SPF_HELO_NONE,SPF_PASS autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-bluetooth@vger.kernel.org Hi Nicolas, On Tue, Oct 4, 2022 at 7:54 AM Nicolas Cavallari wrote: > > The USB interface between the host and the bluetooth adapter used for > SCO packets uses an USB isochronous endpoint with a fragmentation scheme > that does not tolerate errors. Except USB isochronous transfers do > not provide a reliable stream with guaranteed delivery. (There is no > retry on error, see USB spec v2.0 5.6 and 8.5.5.) > > To fragment a packet, the bluetooth HCI simply splits it in parts and > transfer them as-is. The receiver is expected to reconstruct the packet > by assuming the first fragment contains the header and parsing its size > field. There is no error detection either. > > If a fragment is lost, the end result is that the kernel is no longer > synchronized and will pass malformed data to the upper layers, since it > has no way to tell if the first fragment is an actual first fragment or > a continuation fragment. Resynchronization can only happen by luck and > requires an unbounded amount of time. > > The typical symptom for a HSP/HFP bluetooth headset is that the > microphone stops working and dmesg contains piles of rate-limited > "Bluetooth: hci0: SCO packet for unknown connection handle XXXX" > errors for an indeterminate amount of time, until the kernel accidentally > resynchronize. > > A workaround is to ask the upper layer to prevalidate the first fragment > header. This is not possible with user channels so this workaround is > disabled in this case. > > This problem is the most severe when using an ath3k adapter on an i.MX 6 > board, where packet loss occur regularly, possibly because it is an USB1 > device connected on an USB2 hub and this is a special case requiring > split transactions. Interesting, but does this actually make it work if with the packet losses? > Signed-off-by: Nicolas Cavallari > > --- > v2: fix typos in commit description and expand it > > drivers/bluetooth/btusb.c | 7 +++++-- > include/net/bluetooth/hci_core.h | 20 ++++++++++++++++++++ > 2 files changed, 25 insertions(+), 2 deletions(-) > > diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c > index 15caa6469538..f6256af98233 100644 > --- a/drivers/bluetooth/btusb.c > +++ b/drivers/bluetooth/btusb.c > @@ -980,9 +980,12 @@ static int btusb_recv_isoc(struct btusb_data *data, void *buffer, int count) > > if (skb->len == HCI_SCO_HDR_SIZE) { > /* Complete SCO header */ > - hci_skb_expect(skb) = hci_sco_hdr(skb)->dlen; > + struct hci_sco_hdr *hdr = hci_sco_hdr(skb); > > - if (skb_tailroom(skb) < hci_skb_expect(skb)) { > + hci_skb_expect(skb) = hdr->dlen; > + > + if (skb_tailroom(skb) < hci_skb_expect(skb) || > + !hci_conn_prevalidate_sco_hdr(data->hdev, hdr)) { > kfree_skb(skb); > skb = NULL; > > diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h > index e7862903187d..d589b54e89e6 100644 > --- a/include/net/bluetooth/hci_core.h > +++ b/include/net/bluetooth/hci_core.h > @@ -1286,6 +1286,26 @@ static inline struct hci_conn *hci_lookup_le_connect(struct hci_dev *hdev) > return NULL; > } > > +static inline bool hci_conn_prevalidate_sco_hdr(struct hci_dev *hdev, > + struct hci_sco_hdr *hdr) > +{ > + __u16 handle; > + > + if (hci_dev_test_flag(hdev, HCI_USER_CHANNEL)) > + // Can't validate, userspace controls everything. > + return true; > + > + handle = hci_handle(__le16_to_cpu(hdr->handle)); > + > + switch (hci_conn_lookup_type(hdev, handle)) { > + case SCO_LINK: > + case ESCO_LINK: > + return true; > + default: > + return false; > + } > +} Don't really like to have this in hci_core.h, it is sort of messy already beside this is probably too specific to USB so I'd go with something like btusb_validate_sco_handle and add a comment explaining why this is necessary. > int hci_disconnect(struct hci_conn *conn, __u8 reason); > bool hci_setup_sync(struct hci_conn *conn, __u16 handle); > void hci_sco_setup(struct hci_conn *conn, __u8 status); > -- > 2.37.2 > -- Luiz Augusto von Dentz