Received: by 2002:ad5:474a:0:0:0:0:0 with SMTP id i10csp3002309imu; Fri, 18 Jan 2019 03:07:32 -0800 (PST) X-Google-Smtp-Source: ALg8bN6XXlxTRHQgLeOCFCs7iYa2G8HdmmdRZUI34sSUHKH5tlKY9Dq1ioWps4nLl7e2G9MT2olc X-Received: by 2002:a62:1709:: with SMTP id 9mr18698263pfx.249.1547809652940; Fri, 18 Jan 2019 03:07:32 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1547809652; cv=none; d=google.com; s=arc-20160816; b=sjM15svrHF+0v4SfU0FATMLUlYNLAfRXO/tiWoVFzFjWDXNuZL136dMlJh/HxK6vM6 44aHI/vSRFdvWYOp4XFI7vJkXMV/DbkrPhqU3MpQ6a5EoTsUZ3pMt8lUcpe3Ba0ouY0v qLIMRVD3Qur/5NszM7GZpP32S+5lQDlVkjrcDx1/qMpG6yfnae2PQkhVd9UKUwj16n4s aCJcMICSdNingcUxemaNMG3QEGqC13nzhkdRcda0DJFQ9a6pBmCWWR3vArB8X7CmzQQ8 MT7KX3I3F2JrslrfMOkYSHtDjbsKAH58W/lWG2hulVTNJ6WT/Zxfl7AeYQ45G0xt2v9X DfcA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:to:references:message-id :content-transfer-encoding:cc:date:in-reply-to:from:subject :mime-version; bh=msPNLU6DxX7kzVyKM6El93GiGovNWnM/pBXdQ+xMAxI=; b=M5wpEGVN4UPNiEhMzZplEiTjKxvU0Yy8xVKATrq3en8uePZBQeKyezXMT+M3X4UNEe jo32jlJmwaq8QjKYxycPndk28CbXwpFTa/Cs5x3zkJf2wM1PJ9wEU/6xQFEyOpgDT9qo Za+kurIQWySMJNqf0r1fPmOQrDBKZjhaQJ0WTkY5/wmZKjmspMqoMB0tfkn8A+DUJrRL aJlEL5eDq5Fz1FXbO24nGWB/4stM7f9Do0dYD3MzmYRI9XzrgVEa7wAbOVIt3S9RBYkc zTKltDQHQ84o/TrNiRyUdMxQJvps3Ogp5QO2QAPhOH1IgxOLb3pEAmFAi22sXjBUz2XO uLSA== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id z5si4592589plh.133.2019.01.18.03.07.14; Fri, 18 Jan 2019 03:07:32 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727371AbfARLEu convert rfc822-to-8bit (ORCPT + 99 others); Fri, 18 Jan 2019 06:04:50 -0500 Received: from coyote.holtmann.net ([212.227.132.17]:54631 "EHLO mail.holtmann.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727039AbfARLEu (ORCPT ); Fri, 18 Jan 2019 06:04:50 -0500 Received: from marcel-macpro.fritz.box (p4FF9FD60.dip0.t-ipconnect.de [79.249.253.96]) by mail.holtmann.org (Postfix) with ESMTPSA id BDA17CF2C6; Fri, 18 Jan 2019 12:12:33 +0100 (CET) Content-Type: text/plain; charset=utf-8 Mime-Version: 1.0 (Mac OS X Mail 12.2 \(3445.102.3\)) Subject: Re: [PATCH v3 5/5] Bluetooth: btusb: Use the hw_reset method to allow resetting the BT chip From: Marcel Holtmann In-Reply-To: <20181121235020.29461-5-rajatja@google.com> Date: Fri, 18 Jan 2019 12:04:47 +0100 Cc: Johan Hedberg , Greg Kroah-Hartman , "David S. Miller" , Dmitry Torokhov , Alex Hung , linux-bluetooth@vger.kernel.org, linux-kernel@vger.kernel.org, linux-usb@vger.kernel.org, netdev@vger.kernel.org, rajatxjain@gmail.com, dtor@google.com, raghuram.hegde@intel.com, chethan.tumkur.narayan@intel.com, sukumar.ghorai@intel.com Content-Transfer-Encoding: 8BIT Message-Id: References: <20181117010748.24347-1-rajatja@google.com> <20181121235020.29461-1-rajatja@google.com> <20181121235020.29461-5-rajatja@google.com> To: Rajat Jain X-Mailer: Apple Mail (2.3445.102.3) Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Hi Rajat, > If the platform provides it, use the reset gpio to reset the BT > chip (requested by the HCI core if needed). This has been found helpful > on some of Intel bluetooth controllers where the firmware gets stuck and > the only way out is a hard reset pin provided by the platform. > > Signed-off-by: Rajat Jain > --- > v3: Better error handling for gpiod_get_optional() > v2: Handle the EPROBE_DEFER case. > > drivers/bluetooth/btusb.c | 40 +++++++++++++++++++++++++++++++++++++++ > 1 file changed, 40 insertions(+) > > diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c > index e8e148480c91..e7631f770fae 100644 > --- a/drivers/bluetooth/btusb.c > +++ b/drivers/bluetooth/btusb.c > @@ -29,6 +29,7 @@ > #include > #include > #include > +#include > #include > > #include > @@ -475,6 +476,8 @@ struct btusb_data { > struct usb_endpoint_descriptor *diag_tx_ep; > struct usb_endpoint_descriptor *diag_rx_ep; > > + struct gpio_desc *reset_gpio; > + > __u8 cmdreq_type; > __u8 cmdreq; > > @@ -490,6 +493,26 @@ struct btusb_data { > int oob_wake_irq; /* irq for out-of-band wake-on-bt */ > }; > > + > +static void btusb_hw_reset(struct hci_dev *hdev) > +{ > + struct btusb_data *data = hci_get_drvdata(hdev); > + struct gpio_desc *reset_gpio = data->reset_gpio; > + > + /* > + * Toggle the hard reset line if the platform provides one. The reset > + * is going to yank the device off the USB and then replug. So doing > + * once is enough. The cleanup is handled correctly on the way out > + * (standard USB disconnect), and the new device is detected cleanly > + * and bound to the driver again like it should be. > + */ > + bt_dev_dbg(hdev, "%s: Initiating HW reset via gpio", __func__); No __func__ here. That bt_dev_dbg does all of that via dynamic debug already. > + clear_bit(HCI_QUIRK_HW_RESET_ON_TIMEOUT, &hdev->quirks); > + gpiod_set_value(reset_gpio, 1); > + mdelay(100); > + gpiod_set_value(reset_gpio, 0); > +} > + > static inline void btusb_free_frags(struct btusb_data *data) > { > unsigned long flags; > @@ -2917,6 +2940,7 @@ static int btusb_probe(struct usb_interface *intf, > const struct usb_device_id *id) > { > struct usb_endpoint_descriptor *ep_desc; > + struct gpio_desc *reset_gpio; > struct btusb_data *data; > struct hci_dev *hdev; > unsigned ifnum_base; > @@ -3030,6 +3054,16 @@ static int btusb_probe(struct usb_interface *intf, > > SET_HCIDEV_DEV(hdev, &intf->dev); > > + reset_gpio = gpiod_get_optional(&data->udev->dev, "reset", > + GPIOD_OUT_LOW); > + if (IS_ERR(reset_gpio)) { > + err = PTR_ERR(reset_gpio); > + goto out_free_dev; > + } else if (reset_gpio) { > + data->reset_gpio = reset_gpio; > + hdev->hw_reset = btusb_hw_reset; > + } > + How do we ensure that this is the right “reset” line. And it also needs to be bound to some hardware unless we can guarantee that this is always the same. > hdev->open = btusb_open; > hdev->close = btusb_close; > hdev->flush = btusb_flush; > @@ -3085,6 +3119,7 @@ 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); > + set_bit(HCI_QUIRK_HW_RESET_ON_TIMEOUT, &hdev->quirks); You are not messing with the quirks here please. Clearing quirks is crazy. Use the data->flags since this should be all btusb.c specific. > > if (id->driver_info & BTUSB_INTEL) { > hdev->setup = btusb_setup_intel; > @@ -3225,6 +3260,8 @@ static int btusb_probe(struct usb_interface *intf, > return 0; > > out_free_dev: > + if (data->reset_gpio) > + gpiod_put(data->reset_gpio); > hci_free_dev(hdev); > return err; > } > @@ -3268,6 +3305,9 @@ static void btusb_disconnect(struct usb_interface *intf) > if (data->oob_wake_irq) > device_init_wakeup(&data->udev->dev, false); > > + if (data->reset_gpio) > + gpiod_put(data->reset_gpio); > + > hci_free_dev(hdev); > } Regards Marcel