From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: MIME-Version: 1.0 In-Reply-To: <20180608162009.22762-1-attitokes@gmail.com> References: <280FCB2C-6DF1-4790-A89F-AF5BE3513AE5@holtmann.org> <20180608162009.22762-1-attitokes@gmail.com> From: =?UTF-8?B?QXR0aWxhIFTFkWvDqXM=?= Date: Fri, 8 Jun 2018 19:33:43 +0300 Message-ID: Subject: Re: [PATCH] Bluetooth: hci_bcm: Configure SCO routing automatically To: Tokes Attila Cc: "David S. Miller" , Rob Herring , Mark Rutland , Marcel Holtmann , Johan Hedberg , Artiom Vaskov , netdev@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, Bluez mailing list Content-Type: multipart/alternative; boundary="0000000000009c093f056e23f644" List-ID: --0000000000009c093f056e23f644 Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable Hi Marcel, Fixed the problems from the first patch. Related to the possibility of missing device tree parameters, the pcm-* parameters are only relevant for the sco-routing =3D 0 (PCM) case, in which case you probably want to explicitly set that parameters. For sco-routing = =3D 1-3 (transport, codec, i2s) the pcm- parameters seems to be ignored, so I think it's safe to just send zeros. Thanks, Attila T=C5=91k=C3=A9s On Fri, Jun 8, 2018 at 7:20 PM, wrote: > From: Attila T=C5=91k=C3=A9s > > Added support to automatically configure the SCO packet routing at the > device setup. The SCO packets are used with the HSP / HFP profiles, but i= n > some devices (ex. CYW43438) they are routed to a PCM output by default. > This change allows sending the vendor specific HCI command to configure t= he > SCO routing. The parameters of the command are loaded from the device tre= e. > > Signed-off-by: Attila T=C5=91k=C3=A9s > --- > .../bindings/net/broadcom-bluetooth.txt | 7 ++ > drivers/bluetooth/hci_bcm.c | 72 +++++++++++++++++++ > 2 files changed, 79 insertions(+) > > diff --git a/Documentation/devicetree/bindings/net/broadcom-bluetooth.txt > b/Documentation/devicetree/bindings/net/broadcom-bluetooth.txt > index 4194ff7e..aea3a094 100644 > --- a/Documentation/devicetree/bindings/net/broadcom-bluetooth.txt > +++ b/Documentation/devicetree/bindings/net/broadcom-bluetooth.txt > @@ -21,6 +21,12 @@ Optional properties: > - clocks: clock specifier if external clock provided to the controller > - clock-names: should be "extclk" > > + SCO routing parameters: > + - sco-routing: 0-3 (PCM, Transport, Codec, I2S) > + - pcm-interface-rate: 0-4 (128 Kbps - 2048 Kbps) > + - pcm-frame-type: 0 (short), 1 (long) > + - pcm-sync-mode: 0 (slave), 1 (master) > + - pcm-clock-mode: 0 (slave), 1 (master) > > Example: > > @@ -31,5 +37,6 @@ Example: > bluetooth { > compatible =3D "brcm,bcm43438-bt"; > max-speed =3D <921600>; > + sco-routing =3D <1>; /* 1 =3D transport (UART) */ > }; > }; > diff --git a/drivers/bluetooth/hci_bcm.c b/drivers/bluetooth/hci_bcm.c > index ddbd8c6a..0e729534 100644 > --- a/drivers/bluetooth/hci_bcm.c > +++ b/drivers/bluetooth/hci_bcm.c > @@ -83,6 +83,16 @@ > * @hu: pointer to HCI UART controller struct, > * used to disable flow control during runtime suspend and system > sleep > * @is_suspended: whether flow control is currently disabled > + * > + * SCO routing parameters: > + * used as the parameters for the bcm_set_pcm_int_params command > + * @sco_routing: > + * >=3D 255 (skip SCO routing configuration) > + * 0-3 (PCM, Transport, Codec, I2S) > + * @pcm_interface_rate: 0-4 (128 Kbps - 2048 Kbps) > + * @pcm_frame_type: 0 (short), 1 (long) > + * @pcm_sync_mode: 0 (slave), 1 (master) > + * @pcm_clock_mode: 0 (slave), 1 (master) > */ > struct bcm_device { > /* Must be the first member, hci_serdev.c expects this. */ > @@ -114,6 +124,13 @@ struct bcm_device { > struct hci_uart *hu; > bool is_suspended; > #endif > + > + /* SCO routing parameters */ > + u8 sco_routing; > + u8 pcm_interface_rate; > + u8 pcm_frame_type; > + u8 pcm_sync_mode; > + u8 pcm_clock_mode; > }; > > /* generic bcm uart resources */ > @@ -189,6 +206,40 @@ static int bcm_set_baudrate(struct hci_uart *hu, > unsigned int speed) > return 0; > } > > +static int bcm_configure_sco_routing(struct hci_uart *hu, struct > bcm_device *bcm_dev) > +{ > + struct hci_dev *hdev =3D hu->hdev; > + struct sk_buff *skb; > + struct bcm_set_pcm_int_params params; > + > + if (bcm_dev->sco_routing >=3D 0xff) { > + /* SCO routing configuration should be skipped */ > + return 0; > + } > + > + bt_dev_dbg(hdev, "BCM: Configuring SCO routing (%d %d %d %d %d)", > + bcm_dev->sco_routing, bcm_dev->pcm_interface_rate= , > bcm_dev->pcm_frame_type, > + bcm_dev->pcm_sync_mode, bcm_dev->pcm_clock_mode); > + > + params.routing =3D bcm_dev->sco_routing; > + params.rate =3D bcm_dev->pcm_interface_rate; > + params.frame_sync =3D bcm_dev->pcm_frame_type; > + params.sync_mode =3D bcm_dev->pcm_sync_mode; > + params.clock_mode =3D bcm_dev->pcm_clock_mode; > + > + /* Send the SCO routing configuration command */ > + skb =3D __hci_cmd_sync(hdev, 0xfc1c, sizeof(params), ¶ms, > HCI_CMD_TIMEOUT); > + if (IS_ERR(skb)) { > + int err =3D PTR_ERR(skb); > + bt_dev_err(hdev, "BCM: failed to configure SCO routing > (%d)", err); > + return err; > + } > + > + kfree_skb(skb); > + > + return 0; > +} > + > /* bcm_device_exists should be protected by bcm_device_lock */ > static bool bcm_device_exists(struct bcm_device *device) > { > @@ -534,6 +585,9 @@ static int bcm_setup(struct hci_uart *hu) > host_set_baudrate(hu, speed); > } > > + /* Configure SCO routing if needed */ > + bcm_configure_sco_routing(hu, bcm->dev); > + > finalize: > release_firmware(fw); > > @@ -1004,9 +1058,21 @@ static int bcm_acpi_probe(struct bcm_device *dev) > } > #endif /* CONFIG_ACPI */ > > +static void read_u8_device_property(struct device *device, const char > *property, u8 *destination) { > + u32 temp; > + if (device_property_read_u32(device, property, &temp) =3D=3D 0) { > + *destination =3D temp & 0xff; > + } > +} > + > static int bcm_of_probe(struct bcm_device *bdev) > { > device_property_read_u32(bdev->dev, "max-speed", > &bdev->oper_speed); > + read_u8_device_property(bdev->dev, "sco-routing", > &bdev->sco_routing); > + read_u8_device_property(bdev->dev, "pcm-interface-rate", > &bdev->pcm_interface_rate); > + read_u8_device_property(bdev->dev, "pcm-frame-type", > &bdev->pcm_frame_type); > + read_u8_device_property(bdev->dev, "pcm-sync-mode", > &bdev->pcm_sync_mode); > + read_u8_device_property(bdev->dev, "pcm-clock-mode", > &bdev->pcm_clock_mode); > return 0; > } > > @@ -1022,6 +1088,9 @@ static int bcm_probe(struct platform_device *pdev) > dev->dev =3D &pdev->dev; > dev->irq =3D platform_get_irq(pdev, 0); > > + /* SCO routing configuration is disabled by default */ > + dev->sco_routing =3D 0xff; > + > if (has_acpi_companion(&pdev->dev)) { > ret =3D bcm_acpi_probe(dev); > if (ret) > @@ -1281,6 +1350,9 @@ static int bcm_serdev_probe(struct serdev_device > *serdev) > bcmdev->serdev_hu.serdev =3D serdev; > serdev_device_set_drvdata(serdev, bcmdev); > > + /* SCO routing configuration is disabled by default */ > + bcmdev->sco_routing =3D 0xff; > + > if (has_acpi_companion(&serdev->dev)) > err =3D bcm_acpi_probe(bcmdev); > else > -- > 2.17.0 > > --0000000000009c093f056e23f644 Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable
Hi Marcel,

Fixed the problems from the fir= st patch.

Related to the pos= sibility of missing device tree parameters, the pcm-* parameters are only r= elevant for the=C2=A0sco-routing =3D 0 (PCM) case, in which case you pro= bably want to explicitly set that parameters. For sco-routing =3D 1-= 3 (transport, codec, i2s) the pcm- parameters seems to be ignored, so I thi= nk it's safe to just send zeros.=C2=A0

Tha= nks,
Attila T=C5=91k=C3=A9s

On Fri, Jun 8, 2018 at 7:20 PM, <a= ttitokes@gmail.com> wrote:
= From: Attila T=C5=91k=C3=A9s <att= itokes@gmail.com>

Added support to automatically configure the SCO packet routing at the devi= ce setup. The SCO packets are used with the HSP / HFP profiles, but in some= devices (ex. CYW43438) they are routed to a PCM output by default. This ch= ange allows sending the vendor specific HCI command to configure the SCO ro= uting. The parameters of the command are loaded from the device tree.

Signed-off-by: Attila T=C5=91k=C3=A9s <attitokes@gmail.com>
---
=C2=A0.../bindings/net/broadcom-bluetooth.txt=C2=A0 =C2=A0 =C2= =A0 =C2=A0|=C2=A0 7 ++
=C2=A0drivers/bluetooth/hci_bcm.c=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0| 72 +++++++++++++++++++
=C2=A02 files changed, 79 insertions(+)

diff --git a/Documentation/devicetree/bindings/net/broadcom-bluet= ooth.txt b/Documentation/devicetree/bindings/net/broadcom-bluetoo= th.txt
index 4194ff7e..aea3a094 100644
--- a/Documentation/devicetree/bindings/net/broadcom-bluetooth.tx= t
+++ b/Documentation/devicetree/bindings/net/broadcom-bluetooth.tx= t
@@ -21,6 +21,12 @@ Optional properties:
=C2=A0 - clocks: clock specifier if external clock provided to the controll= er
=C2=A0 - clock-names: should be "extclk"

+ SCO routing parameters:
+ - sco-routing: 0-3 (PCM, Transport, Codec, I2S)
+ - pcm-interface-rate: 0-4 (128 Kbps - 2048 Kbps)
+ - pcm-frame-type: 0 (short), 1 (long)
+ - pcm-sync-mode: 0 (slave), 1 (master)
+ - pcm-clock-mode: 0 (slave), 1 (master)

=C2=A0Example:

@@ -31,5 +37,6 @@ Example:
=C2=A0 =C2=A0 =C2=A0 =C2=A0 bluetooth {
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 compatible =3D &quo= t;brcm,bcm43438-bt";
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 max-speed =3D <9= 21600>;
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0sco-routing =3D <= ;1>; /* 1 =3D transport (UART) */
=C2=A0 =C2=A0 =C2=A0 =C2=A0 };
=C2=A0};
diff --git a/drivers/bluetooth/hci_bcm.c b/drivers/bluetooth/hci_bcm.c
index ddbd8c6a..0e729534 100644
--- a/drivers/bluetooth/hci_bcm.c
+++ b/drivers/bluetooth/hci_bcm.c
@@ -83,6 +83,16 @@
=C2=A0 * @hu: pointer to HCI UART controller struct,
=C2=A0 *=C2=A0 =C2=A0 =C2=A0used to disable flow control during runtime sus= pend and system sleep
=C2=A0 * @is_suspended: whether flow control is currently disabled
+ *
+ *=C2=A0 SCO routing parameters:
+ *=C2=A0 =C2=A0used as the parameters for the bcm_set_pcm_int_params comma= nd
+ *=C2=A0 =C2=A0 =C2=A0@sco_routing:
+ *=C2=A0 =C2=A0 =C2=A0 >=3D 255 (skip SCO routing configuration)
+ *=C2=A0 =C2=A0 =C2=A0 0-3 (PCM, Transport, Codec, I2S)
+ *=C2=A0 =C2=A0 =C2=A0@pcm_interface_rate: 0-4 (128 Kbps - 2048 Kbps)
+ *=C2=A0 =C2=A0 =C2=A0@pcm_frame_type: 0 (short), 1 (long)
+ *=C2=A0 =C2=A0 =C2=A0@pcm_sync_mode: 0 (slave), 1 (master)
+ *=C2=A0 =C2=A0 =C2=A0@pcm_clock_mode: 0 (slave), 1 (master)
=C2=A0 */
=C2=A0struct bcm_device {
=C2=A0 =C2=A0 =C2=A0 =C2=A0 /* Must be the first member, hci_serdev.c expec= ts this. */
@@ -114,6 +124,13 @@ struct bcm_device {
=C2=A0 =C2=A0 =C2=A0 =C2=A0 struct hci_uart=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0*hu;
=C2=A0 =C2=A0 =C2=A0 =C2=A0 bool=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 is_suspended;
=C2=A0#endif
+
+=C2=A0 =C2=A0 =C2=A0 =C2=A0/* SCO routing parameters */
+=C2=A0 =C2=A0 =C2=A0 =C2=A0u8=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 sco_routing;
+=C2=A0 =C2=A0 =C2=A0 =C2=A0u8=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 pcm_interface_rate;
+=C2=A0 =C2=A0 =C2=A0 =C2=A0u8=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 pcm_frame_type;
+=C2=A0 =C2=A0 =C2=A0 =C2=A0u8=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 pcm_sync_mode;
+=C2=A0 =C2=A0 =C2=A0 =C2=A0u8=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 pcm_clock_mode;
=C2=A0};
=C2=A0
=C2=A0/* generic bcm uart resources */
@@ -189,6 +206,40 @@ static int bcm_set_baudrate(struct hci_uart *hu= , unsigned int speed)
=C2=A0 =C2=A0 =C2=A0 =C2=A0 return 0;
=C2=A0}

+static int bcm_configure_sco_routing(struct hci_uart *hu, struct bcm_= device *bcm_dev)
+{
+=C2=A0 =C2=A0 =C2=A0 =C2=A0struct hci_dev *hdev =3D hu->hdev;
+=C2=A0 =C2=A0 =C2=A0 =C2=A0struct sk_buff *skb;
+=C2=A0 =C2=A0 =C2=A0 =C2=A0struct bcm_set_pcm_int_params params;
+
+=C2=A0 =C2=A0 =C2=A0 =C2=A0if (bcm_dev->sco_routing >=3D 0xff= ) {
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0/* SCO routing conf= iguration should be skipped */
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0re= turn 0;
+=C2=A0 =C2=A0 =C2=A0 =C2=A0}
+
+=C2=A0 =C2=A0 =C2=A0 =C2=A0bt_dev_dbg(hdev, "= BCM: Configuring SCO routing (%d %d %d %d %d)",
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0bcm_dev->sco_routing, bcm_dev->pcm_interface_rate, bcm_dev-= >pcm_frame_type,
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0bcm_dev->pcm_sync_mode, bcm_dev->pcm_clock_mode);
+
+=C2=A0 =C2=A0 =C2=A0 =C2=A0params.routing =3D bcm_dev->sco_routing;
+=C2=A0 =C2=A0 =C2=A0 =C2=A0params.rate =3D bcm_dev->pcm_interface_rate;=
+=C2=A0 =C2=A0 =C2=A0 =C2=A0params.frame_sync =3D bcm_dev->pcm_frame_typ= e;
+=C2=A0 =C2=A0 =C2=A0 =C2=A0params.sync_mode =3D bcm_dev->pcm_sync_mode;=
+=C2=A0 =C2=A0 =C2=A0 =C2=A0params.clock_mode =3D bcm_dev->pcm_clock_mod= e;
+
+=C2=A0 =C2=A0 =C2=A0 =C2=A0/* Send the SCO routing configuration co= mmand */
+=C2=A0 =C2=A0 =C2=A0 =C2=A0skb =3D __hci_cmd_sync(hdev, 0= xfc1c, sizeof(params), &params, HCI_CMD_TIMEOUT);
+=C2=A0 =C2=A0 =C2=A0 =C2=A0if (IS_ERR(skb)) {
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0int err =3D PTR_ERR= (skb);
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0bt_dev_err(hdev, &q= uot;BCM: failed to configure SCO routing (%d)", err);
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0return err;
+=C2=A0 =C2=A0 =C2=A0 =C2=A0}
+
+=C2=A0 =C2=A0 =C2=A0 =C2=A0kfree_skb(skb);
+
+=C2=A0 =C2=A0 =C2=A0 =C2=A0return 0;
+}
+
=C2=A0/* bcm_device_exists should be protected by bcm_device_lock */
=C2=A0static bool bcm_device_exists(struct bcm_device *device)
=C2=A0{
@@ -534,6 +585,9 @@ static int bcm_setup(struct hci_uart *hu)
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 host_set_baudrate(hu, speed);
=C2=A0 =C2=A0 =C2=A0 =C2=A0 }

+=C2=A0 =C2=A0 =C2=A0 =C2=A0/* Configure SCO routing if needed */
+=C2=A0 =C2=A0 =C2=A0 =C2=A0bcm_configure_sco_routing(hu, = bcm->dev);
+
=C2=A0finalize:
=C2=A0 =C2=A0 =C2=A0 =C2=A0 release_firmware(fw);

@@ -1004,9 +1058,21 @@ static int bcm_acpi_probe(struct bcm_device *dev) =C2=A0}
=C2=A0#endif /* CONFIG_ACPI */

+static void read_u8_device_property(struct device *device, const char *pro= perty, u8 *destination) {
+=C2=A0 =C2=A0 =C2=A0 =C2=A0u32 temp;
+=C2=A0 =C2=A0 =C2=A0 =C2=A0if (device_property_read_u32(device, prope= rty, &temp) =3D=3D 0) {
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0*destination =3D te= mp & 0xff;
+=C2=A0 =C2=A0 =C2=A0 =C2=A0}
+}
+
=C2=A0static int bcm_of_probe(struct bcm_device *bdev)
=C2=A0{
=C2=A0 =C2=A0 =C2=A0 =C2=A0 device_property_read_u32(bdev->dev, &qu= ot;max-speed", &bdev->oper_speed);
+=C2=A0 =C2=A0 =C2=A0 =C2=A0read_u8_device_property(bdev->de= v, "sco-routing", &bdev->sco_routing);
+=C2=A0 =C2=A0 =C2=A0 =C2=A0read_u8_device_property(bdev->dev, &quo= t;pcm-interface-rate", &bdev->pcm_interface_rate);
+=C2=A0 =C2=A0 =C2=A0 =C2=A0read_u8_device_property(bdev->dev, &quo= t;pcm-frame-type", &bdev->pcm_frame_type);
+=C2=A0 =C2=A0 =C2=A0 =C2=A0read_u8_device_property(bdev->dev, &quo= t;pcm-sync-mode", &bdev->pcm_sync_mode);
+=C2=A0 =C2=A0 =C2=A0 =C2=A0read_u8_device_property(bdev->dev, &quo= t;pcm-clock-mode", &bdev->pcm_clock_mode);
=C2=A0 =C2=A0 =C2=A0 =C2=A0 return 0;
=C2=A0}

@@ -1022,6 +1088,9 @@ static int bcm_probe(struct platform_device *pdev) =C2=A0 =C2=A0 =C2=A0 =C2=A0 dev->dev =3D &pdev->= dev;
=C2=A0 =C2=A0 =C2=A0 =C2=A0 dev->irq =3D platform_get_irq(pdev, 0);

+=C2=A0 =C2=A0 =C2=A0 =C2=A0/* SCO routing configuration is disabled by def= ault */
+=C2=A0 =C2=A0 =C2=A0 =C2=A0dev->sco_routing =3D 0xff;
+
=C2=A0 =C2=A0 =C2=A0 =C2=A0 if (has_acpi_companion(&pdev->dev))= {
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 ret =3D bcm_acpi_pr= obe(dev);
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 if (ret)
@@ -1281,6 +1350,9 @@ static int bcm_serdev_probe(struct serdev_devi= ce *serdev)
=C2=A0 =C2=A0 =C2=A0 =C2=A0 bcmdev-= >serdev_hu.serdev =3D serdev;
=C2=A0 =C2=A0 =C2=A0 =C2=A0 serdev_device_set_drvdata(serdev, bcmdev);=

+=C2=A0 =C2=A0 =C2=A0 =C2=A0/* SCO routing configuration is disabled by def= ault */
+=C2=A0 =C2=A0 =C2=A0 =C2=A0bcmdev->sco_routing =3D 0xff;
+
=C2=A0 =C2=A0 =C2=A0 =C2=A0 if (has_acpi_companion(&serdev->dev= ))
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 err =3D bcm_acpi_pr= obe(bcmdev);
=C2=A0 =C2=A0 =C2=A0 =C2=A0 else
--
2.17.0


--0000000000009c093f056e23f644--