RE: [PATCH v1] Bluetooth: btintel: Support Digital(N) + RF(N-1) combination

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi Luiz, Marcel,

Thanks for the comments. I will make a new patch and suggested and send it for review.

Regards,
Kiran

> -----Original Message-----
> From: Luiz Augusto von Dentz <luiz.dentz@xxxxxxxxx>
> Sent: Thursday, June 10, 2021 4:02 AM
> To: Marcel Holtmann <marcel@xxxxxxxxxxxx>
> Cc: K, Kiran <kiran.k@xxxxxxxxx>; Bluez mailing list <linux-
> bluetooth@xxxxxxxxxxxxxxx>; An, Tedd <tedd.an@xxxxxxxxx>; Von Dentz,
> Luiz <luiz.von.dentz@xxxxxxxxx>; Tumkur Narayan, Chethan
> <chethan.tumkur.narayan@xxxxxxxxx>; Srivatsa, Ravishankar
> <ravishankar.srivatsa@xxxxxxxxx>
> Subject: Re: [PATCH v1] Bluetooth: btintel: Support Digital(N) + RF(N-1)
> combination
> 
> Hi Marcel, Kiran,
> 
> On Wed, Jun 9, 2021 at 12:15 PM Marcel Holtmann <marcel@xxxxxxxxxxxx>
> wrote:
> >
> > Hi Kiran,
> >
> > > New generation Intel controllers(N) need to support RF from (N-1)
> > > generation. Since PID comes from OTP present in RF module,
> > > *setup* function gets mapped to BTUSB_INTEL_NEW instead of
> > > BTUSB_INTEL_NEWGEN. This patch checks generation of CNVi in
> > > *setup* of BTUSB_INTEL_NEW and maps callbacks to
> BTUSB_INTEL_NEWGEN
> > > if new generation controller is found and attempts *setup* of
> > > BTUSB_INTEL_NEWGEN.
> > >
> > > Signed-off-by: Kiran K <kiran.k@xxxxxxxxx>
> > > Reviewed-by: Chethan T N <chethan.tumkur.narayan@xxxxxxxxx>
> > > Reviewed-by: Srivatsa Ravishankar <ravishankar.srivatsa@xxxxxxxxx>
> > > ---
> > > drivers/bluetooth/btintel.c | 119
> > > ++++++++++++++++++++++++++++++++++++
> > > drivers/bluetooth/btintel.h |  10 +++
> > > drivers/bluetooth/btusb.c   |  45 +++++++++++++-
> > > net/bluetooth/hci_core.c    |   5 +-
> > > 4 files changed, 177 insertions(+), 2 deletions(-)
> > >
> > > diff --git a/drivers/bluetooth/btintel.c
> > > b/drivers/bluetooth/btintel.c index e44b6993cf91..1d9ecc481f14
> > > 100644
> > > --- a/drivers/bluetooth/btintel.c
> > > +++ b/drivers/bluetooth/btintel.c
> > > @@ -483,6 +483,85 @@ int btintel_version_info_tlv(struct hci_dev
> > > *hdev, struct intel_version_tlv *ver }
> > > EXPORT_SYMBOL_GPL(btintel_version_info_tlv);
> > >
> > > +void btintel_parse_version_tlv(struct hci_dev *hdev, struct sk_buff *skb,
> > > +                            struct intel_version_tlv *version) {
> > > +     /* Consume Command Complete Status field */
> > > +     skb_pull(skb, sizeof(__u8));
> > > +
> > > +     /* 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;
> >
> > I think we already had this issue that you need to check that enough data is
> actually in the SKB.
> >
> > > +             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:
> > > +                     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:
> > > +                     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));
> > > +     }
> > > +}
> > > +EXPORT_SYMBOL_GPL(btintel_parse_version_tlv);
> > > +
> > > int btintel_read_version_tlv(struct hci_dev *hdev, struct
> > > intel_version_tlv *version) {
> > >       struct sk_buff *skb;
> > > @@ -595,6 +674,46 @@ int btintel_read_version_tlv(struct hci_dev
> > > *hdev, struct intel_version_tlv *ver }
> > > EXPORT_SYMBOL_GPL(btintel_read_version_tlv);
> > >
> > > +int btintel_generic_read_version(struct hci_dev *hdev,
> > > +                              struct intel_version_tlv *ver_tlv,
> > > +                              struct intel_version *ver, bool
> > > +*is_tlv) {
> > > +     struct sk_buff *skb;
> > > +     const u8 param[1] = { 0xFF };
> > > +
> > > +     skb = __hci_cmd_sync(hdev, 0xfc05, 1, param, HCI_CMD_TIMEOUT);
> > > +     if (IS_ERR(skb)) {
> > > +             bt_dev_err(hdev, "Reading Intel version information failed
> (%ld)",
> > > +                        PTR_ERR(skb));
> > > +             return PTR_ERR(skb);
> > > +     }
> > > +
> > > +     if (skb->data[0]) {
> > > +             bt_dev_err(hdev, "Intel Read Version command failed (%02x)",
> > > +                        skb->data[0]);
> > > +             kfree_skb(skb);
> > > +             return -EIO;
> > > +     }
> > > +
> > > +     if (skb->len < sizeof(struct intel_version))
> > > +             return -EILSEQ;
> > > +
> > > +     if (skb->len == sizeof(struct intel_version) &&
> > > +         skb->data[1] == 0x37)
> > > +             *is_tlv = false;
> > > +     else
> > > +             *is_tlv = true;
> > > +
> > > +     if (*is_tlv)
> > > +             btintel_parse_version_tlv(hdev, skb, ver_tlv);
> > > +     else
> > > +             memcpy(ver, skb->data, sizeof(*ver));
> > > +
> > > +     kfree_skb(skb);
> > > +     return 0;
> > > +}
> > > +EXPORT_SYMBOL_GPL(btintel_generic_read_version);
> > > +
> >
> > I have the feeling that we are falling back to a patch that I already rejected.
> >
> > > /* ------- REGMAP IBT SUPPORT ------- */
> > >
> > > #define IBT_REG_MODE_8BIT  0x00
> > > diff --git a/drivers/bluetooth/btintel.h
> > > b/drivers/bluetooth/btintel.h index d184064a5e7c..366cb746f9c4
> > > 100644
> > > --- a/drivers/bluetooth/btintel.h
> > > +++ b/drivers/bluetooth/btintel.h
> > > @@ -175,6 +175,10 @@ 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);
> > > +int btintel_generic_read_version(struct hci_dev *hdev,
> > > +                              struct intel_version_tlv *ver_tlv,
> > > +                              struct intel_version *ver,
> > > +                              bool *is_tlv);
> > > #else
> > >
> > > static inline int btintel_check_bdaddr(struct hci_dev *hdev) @@
> > > -307,4 +311,10 @@ static inline int btintel_set_debug_features(struct
> hci_dev *hdev,
> > >       return -EOPNOTSUPP;
> > > }
> > >
> > > +static int btintel_generic_read_version(struct hci_dev *hdev,
> > > +                                     struct intel_version_tlv *ver_tlv,
> > > +                                     struct intel_version *ver,
> > > +bool *is_tlv) {
> > > +     return -EOPNOTSUPP;
> > > +}
> > > #endif
> > > diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
> > > index a9855a2dd561..15d91aae52cc 100644
> > > --- a/drivers/bluetooth/btusb.c
> > > +++ b/drivers/bluetooth/btusb.c
> > > @@ -583,6 +583,9 @@ struct btusb_data {
> > >       unsigned cmd_timeout_cnt;
> > > };
> > >
> > > +static int btusb_setup_intel_newgen(struct hci_dev *hdev); static
> > > +int btusb_shutdown_intel_new(struct hci_dev *hdev);
> > > +
> > > static void btusb_intel_cmd_timeout(struct hci_dev *hdev) {
> > >       struct btusb_data *data = hci_get_drvdata(hdev); @@ -2842,6
> > > +2845,18 @@ static int btusb_intel_boot(struct hci_dev *hdev, u32
> boot_addr)
> > >       return err;
> > > }
> > >
> > > +static bool btintel_is_newgen_controller(struct hci_dev *hdev, u32
> > > +cnvi) {
> > > +     switch (cnvi & 0xFFF) {
> > > +     case 0x400: /* Slr */
> > > +     case 0x401: /* Slr-F */
> > > +     case 0x410: /* TyP */
> > > +     case 0x810: /* Mgr */
> > > +             return true;
> > > +     }
> > > +     return false;
> > > +}
> > > +
> > > static int btusb_setup_intel_new(struct hci_dev *hdev) {
> > >       struct btusb_data *data = hci_get_drvdata(hdev); @@ -2851,6
> > > +2866,8 @@ static int btusb_setup_intel_new(struct hci_dev *hdev)
> > >       char ddcname[64];
> > >       int err;
> > >       struct intel_debug_features features;
> > > +     struct intel_version_tlv ver_tlv;
> > > +     bool is_tlv;
> > >
> > >       BT_DBG("%s", hdev->name);
> > >
> > > @@ -2864,12 +2881,38 @@ static int btusb_setup_intel_new(struct
> hci_dev *hdev)
> > >        * is in bootloader mode or if it already has operational firmware
> > >        * loaded.
> > >        */
> > > -     err = btintel_read_version(hdev, &ver);
> > > +     err = btintel_generic_read_version(hdev, &ver_tlv, &ver,
> > > + &is_tlv);
> > >       if (err) {
> > >               bt_dev_err(hdev, "Intel Read version failed (%d)", err);
> > >               btintel_reset_to_bootloader(hdev);
> > >               return err;
> > >       }
> > > +     if (is_tlv) {
> > > +             /* We got TLV data. Check for new generation CNVi. If present,
> > > +              * then map the callbacks to BTUSB_INTEL_NEWGEN and attempt
> > > +              * setup function again
> > > +              */
> > > +             if (btintel_is_newgen_controller(hdev, ver_tlv.cnvi_top)) {
> > > +                     hdev->send = btusb_send_frame_intel;
> > > +                     hdev->setup = btusb_setup_intel_newgen;
> >
> > So this is a clear no, your are not changing hdev->setup within hdev->setup.
> >
> > > +                     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;
> > > +                     return -EAGAIN;
> > > +             }
> > > +
> > > +             /* we need to read legacy version here to minimize the changes
> > > +              * and keep the esixiting flow
> > > +              */
> > > +             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)
> > > diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
> > > index 1eb7ffd0dd29..8e407bad0e31 100644
> > > --- a/net/bluetooth/hci_core.c
> > > +++ b/net/bluetooth/hci_core.c
> > > @@ -1496,8 +1496,11 @@ static int hci_dev_do_open(struct hci_dev
> > > *hdev)
> > >
> > >               hci_sock_dev_event(hdev, HCI_DEV_SETUP);
> > >
> > > -             if (hdev->setup)
> > > +             if (hdev->setup) {
> > >                       ret = hdev->setup(hdev);
> > > +                     if (ret && ret == -EAGAIN)
> > > +                             ret = hdev->setup(hdev);
> > > +             }
> >
> > NO. Please stop hacking here. I think you need to take a whiteboard and
> draw how our controllers are initialized.
> 
> +1
> 
> It is already strange that we have mixed generation, besides we never really
> did a good job tracking the generation properly, but with this it seems we are
> attempting to mix generations so we no longer can detect them based on
> USB PID/VID but need to dig into the version information at runtime, so imo
> we should either detected based on USB PID/VID or if that is not possible
> then switch it to be runtime only and not try to do both as it should be clear
> by now that will just make the code really hard to follow.
> 
> --
> Luiz Augusto von Dentz




[Index of Archives]     [Bluez Devel]     [Linux Wireless Networking]     [Linux Wireless Personal Area Networking]     [Linux ATH6KL]     [Linux USB Devel]     [Linux Media Drivers]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Big List of Linux Books]

  Powered by Linux