2017-12-13 12:42:49

by Amitkumar Karwar

[permalink] [raw]
Subject: [v5 0/8] rsi: add bluetooth and coex support

From: Amitkumar Karwar <[email protected]>

This patch series adds new bluetooth driver and coex enhancments
in existing wlan driver for RSI chipsets.
As per our architecture, both wlan and bluetooth drivers talk
over same SDIO interface to device. Separate endpoint will be
used in case of USB interface.

Changes in v5: 5/8 is modified
Changes in v4: 5/8 is modified
Changes in v3: 4/8, 5/8 and 6/8 patches are modified
Changes in v2: 2/8, 5/8 and 6/8 patches are modified

Prameela Rani Garnepudi (6):
rsi: add rx control block to handle rx packets in USB
rsi: add header file rsi_header
rsi: add coex support
Bluetooth: btrsi: add new rsi bluetooth driver
rsi: add module parameter operating mode
rsi: sdio changes to support BT

Siva Rebbagondla (2):
rsi: add bluetooth rx endpoint
rsi: handle BT traffic in driver

drivers/bluetooth/Kconfig | 11 ++
drivers/bluetooth/Makefile | 2 +
drivers/bluetooth/btrsi.c | 188 ++++++++++++++++++++++++++++
drivers/net/wireless/rsi/Kconfig | 2 +-
drivers/net/wireless/rsi/Makefile | 1 +
drivers/net/wireless/rsi/rsi_91x_coex.c | 184 +++++++++++++++++++++++++++
drivers/net/wireless/rsi/rsi_91x_core.c | 16 ++-
drivers/net/wireless/rsi/rsi_91x_hal.c | 56 +++++++--
drivers/net/wireless/rsi/rsi_91x_main.c | 110 +++++++++++++++-
drivers/net/wireless/rsi/rsi_91x_mgmt.c | 2 +-
drivers/net/wireless/rsi/rsi_91x_sdio.c | 13 +-
drivers/net/wireless/rsi/rsi_91x_sdio_ops.c | 5 +-
drivers/net/wireless/rsi/rsi_91x_usb.c | 124 +++++++++++++-----
drivers/net/wireless/rsi/rsi_91x_usb_ops.c | 35 ++++--
drivers/net/wireless/rsi/rsi_coex.h | 38 ++++++
drivers/net/wireless/rsi/rsi_common.h | 5 +-
drivers/net/wireless/rsi/rsi_hal.h | 21 ++++
drivers/net/wireless/rsi/rsi_main.h | 20 +--
drivers/net/wireless/rsi/rsi_mgmt.h | 3 +
drivers/net/wireless/rsi/rsi_usb.h | 16 ++-
include/linux/rsi_header.h | 56 +++++++++
21 files changed, 825 insertions(+), 83 deletions(-)
create mode 100644 drivers/bluetooth/btrsi.c
create mode 100644 drivers/net/wireless/rsi/rsi_91x_coex.c
create mode 100644 drivers/net/wireless/rsi/rsi_coex.h
create mode 100644 include/linux/rsi_header.h

--
2.7.4



2017-12-14 14:22:39

by Amitkumar Karwar

[permalink] [raw]
Subject: Re: [v5 5/8] Bluetooth: btrsi: add new rsi bluetooth driver

On Wed, Dec 13, 2017 at 7:16 PM, Marcel Holtmann <[email protected]> wrot=
e:
> Hi Amitkumar,
>
>> Redpine bluetooth driver is a thin driver which depends on
>> 'rsi_91x' driver for transmitting and receiving packets
>> to/from device. It creates hci interface when attach() is
>> called from 'rsi_91x' module.
>>
>> Signed-off-by: Prameela Rani Garnepudi <[email protected]>
>> Signed-off-by: Siva Rebbagondla <[email protected]>
>> Signed-off-by: Amitkumar Karwar <[email protected]>
>> ---
>> v5: Addressed review comments from Marcel.
>> Removed reduntant switch case code from rsi_hci_recv_pkt()
>> Changed bt_cb(skb)->pkt_type to hci_skb_pkt_type(skb)
>> Removed reduntant '\n' from BT_ERR and redundant BT_INFO messages
>> Changed u8 *pkt to const u8 *pkt in rsi_hci_recv_pkt()
>> v4: Removed rsi_hci.h file. Made the functions static(Marcel)
>> v3: Made BT_RSI module by default off(Marcel)
>> Removed redundant exported function rsi_get_hci_ops()(Marcel)
>> v2: Addressed review comments from Marcel
>> Removed unnecessary 'depends on BT && BT_RFOMM' line in Kconfig
>> Removed redundant BT_INFO messages
>> h_adapter initialization and declaration in a single line.
>> Removed unnecessary error checks for HCI_RUNNING and fsm_state
>> Allocated new skb with skb_realloc_headroom() API if headroom is not =
sufficient
>> Used get_unaligned_le16 helpers
>> Moved a structure and union from header file to btrsi.c file
>> ---
>> drivers/bluetooth/Kconfig | 11 +++
>> drivers/bluetooth/Makefile | 2 +
>> drivers/bluetooth/btrsi.c | 188 +++++++++++++++++++++++++++++++++++++++=
++++++
>> include/linux/rsi_header.h | 4 +-
>> 4 files changed, 204 insertions(+), 1 deletion(-)
>> create mode 100644 drivers/bluetooth/btrsi.c
>>
>> diff --git a/drivers/bluetooth/Kconfig b/drivers/bluetooth/Kconfig
>> index 60e1c7d..33d7514 100644
>> --- a/drivers/bluetooth/Kconfig
>> +++ b/drivers/bluetooth/Kconfig
>> @@ -378,4 +378,15 @@ config BT_QCOMSMD
>> Say Y here to compile support for HCI over Qualcomm SMD into the
>> kernel or say M to compile as a module.
>>
>> +config BT_RSI
>> + tristate "Redpine HCI support"
>> + default n
>> + help
>> + Redpine BT driver.
>> + This driver handles BT traffic from upper layers and pass
>> + to the RSI_91x coex module for further scheduling to device
>> +
>> + Say Y here to compile support for HCI over Redpine into the
>> + kernel or say M to compile as a module.
>> +
>> endmenu
>> diff --git a/drivers/bluetooth/Makefile b/drivers/bluetooth/Makefile
>> index 4e4e44d..712af83a 100644
>> --- a/drivers/bluetooth/Makefile
>> +++ b/drivers/bluetooth/Makefile
>> @@ -28,6 +28,8 @@ obj-$(CONFIG_BT_QCA) +=3D btqca.o
>>
>> obj-$(CONFIG_BT_HCIUART_NOKIA) +=3D hci_nokia.o
>>
>> +obj-$(CONFIG_BT_RSI) +=3D btrsi.o
>> +
>
> actually I never caught this before. Since this driver is doing the HCI p=
ortion, for consistency CONFIG_BT_HCIRSI would be better.
>
>> btmrvl-y :=3D btmrvl_main.o
>> btmrvl-$(CONFIG_DEBUG_FS) +=3D btmrvl_debugfs.o
>>
>> diff --git a/drivers/bluetooth/btrsi.c b/drivers/bluetooth/btrsi.c
>> new file mode 100644
>> index 0000000..c9e92cc
>> --- /dev/null
>> +++ b/drivers/bluetooth/btrsi.c
>> @@ -0,0 +1,188 @@
>> +/**
>> + * Copyright (c) 2017 Redpine Signals Inc.
>> + *
>> + * Permission to use, copy, modify, and/or distribute this software for=
any
>> + * purpose with or without fee is hereby granted, provided that the abo=
ve
>> + * copyright notice and this permission notice appear in all copies.
>> + *
>> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRAN=
TIES
>> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
>> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE =
FOR
>> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAG=
ES
>> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN A=
N
>> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT=
OF
>> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
>> + */
>> +#include <linux/version.h>
>> +#include <linux/module.h>
>> +#include <linux/kernel.h>
>> +#include <net/bluetooth/bluetooth.h>
>> +#include <net/bluetooth/hci_core.h>
>> +#include <linux/unaligned/le_byteshift.h>
>> +#include <linux/rsi_header.h>
>> +#include <net/genetlink.h>
>> +
>> +#define RSI_HEADROOM_FOR_BT_HAL 16
>> +#define RSI_FRAME_DESC_SIZE 16
>> +
>> +static struct rsi_hci_adapter {
>> + void *priv;
>> + struct rsi_proto_ops *proto_ops;
>> + struct hci_dev *hdev;
>> +};
>> +
>> +static int rsi_hci_open(struct hci_dev *hdev)
>> +{
>> + return 0;
>> +}
>> +
>> +static int rsi_hci_close(struct hci_dev *hdev)
>> +{
>> + return 0;
>> +}
>> +
>> +static int rsi_hci_flush(struct hci_dev *hdev)
>> +{
>> + return 0;
>> +}
>> +
>> +static int rsi_hci_send_pkt(struct hci_dev *hdev, struct sk_buff *skb)
>> +{
>> + struct rsi_hci_adapter *h_adapter =3D hci_get_drvdata(hdev);
>> + struct sk_buff *new_skb =3D NULL;
>> +
>> + switch (hci_skb_pkt_type(skb)) {
>> + case HCI_COMMAND_PKT:
>> + hdev->stat.cmd_tx++;
>> + break;
>> + case HCI_ACLDATA_PKT:
>> + hdev->stat.acl_tx++;
>> + break;
>> + case HCI_SCODATA_PKT:
>> + hdev->stat.sco_tx++;
>> + break;
>> + }
>> +
>> + if (skb_headroom(skb) < RSI_HEADROOM_FOR_BT_HAL) {
>> + /* Insufficient skb headroom - allocate a new skb */
>> + new_skb =3D skb_realloc_headroom(skb, RSI_HEADROOM_FOR_BT_=
HAL);
>> + if (unlikely(!new_skb))
>> + return -ENOMEM;
>> + bt_cb(new_skb)->pkt_type =3D hci_skb_pkt_type(skb);
>> + kfree_skb(skb);
>> + skb =3D new_skb;
>> + }
>> +
>> + return h_adapter->proto_ops->coex_send_pkt(h_adapter->priv, skb,
>> + RSI_BT_Q);
>> +}
>> +
>> +static int rsi_hci_recv_pkt(void *priv, const u8 *pkt)
>> +{
>> + struct rsi_hci_adapter *h_adapter =3D priv;
>> + struct hci_dev *hdev =3D h_adapter->hdev;
>> + struct sk_buff *skb;
>> + int pkt_len =3D get_unaligned_le16(pkt) & 0x0fff;
>> +
>> + skb =3D dev_alloc_skb(pkt_len);
>> + if (!skb)
>> + return -ENOMEM;
>> +
>> + memcpy(skb->data, pkt + RSI_FRAME_DESC_SIZE, pkt_len);
>> + skb_put(skb, pkt_len);
>> + h_adapter->hdev->stat.byte_rx +=3D skb->len;
>> +
>> + hci_skb_pkt_type(skb) =3D pkt[14];
>> +
>> + return hci_recv_frame(hdev, skb);
>> +}
>> +
>> +static int rsi_hci_attach(void *priv, struct rsi_proto_ops *ops)
>> +{
>> + struct rsi_hci_adapter *h_adapter =3D NULL;
>> + struct hci_dev *hdev;
>> + int err =3D 0;
>> +
>> + h_adapter =3D kzalloc(sizeof(*h_adapter), GFP_KERNEL);
>> + if (!h_adapter)
>> + return -ENOMEM;
>> +
>> + h_adapter->priv =3D priv;
>> + ops->set_bt_context(priv, h_adapter);
>> + h_adapter->proto_ops =3D ops;
>> +
>> + hdev =3D hci_alloc_dev();
>> + if (!hdev) {
>> + BT_ERR("Failed to alloc HCI device");
>> + goto err;
>> + }
>> +
>> + h_adapter->hdev =3D hdev;
>> +
>> + if (ops->get_host_intf(priv) =3D=3D RSI_HOST_INTF_SDIO)
>> + hdev->bus =3D HCI_SDIO;
>> + else
>> + hdev->bus =3D HCI_USB;
>> +
>> + hci_set_drvdata(hdev, h_adapter);
>> + hdev->dev_type =3D HCI_PRIMARY;
>> + hdev->open =3D rsi_hci_open;
>> + hdev->close =3D rsi_hci_close;
>> + hdev->flush =3D rsi_hci_flush;
>> + hdev->send =3D rsi_hci_send_pkt;
>
> this doesn=E2=80=99t have to be in this patch, but if you support hdev->s=
et_bdaddr, hdev->set_diag etc. that would be good to add in a follow up.
>
>> +
>> + err =3D hci_register_dev(hdev);
>> + if (err < 0) {
>> + BT_ERR("HCI registration failed with errcode %d", err);
>> + hci_free_dev(hdev);
>> + goto err;
>> + }
>> +
>> + return 0;
>> +err:
>> + h_adapter->hdev =3D NULL;
>> + kfree(h_adapter);
>> + return -EINVAL;
>> +}
>> +
>> +static void rsi_hci_detach(void *priv)
>> +{
>> + struct rsi_hci_adapter *h_adapter =3D priv;
>> + struct hci_dev *hdev;
>> +
>> + if (!h_adapter)
>> + return;
>> +
>> + hdev =3D h_adapter->hdev;
>> + if (hdev) {
>> + hci_unregister_dev(hdev);
>> + hci_free_dev(hdev);
>> + h_adapter->hdev =3D NULL;
>> + }
>> +
>> + kfree(h_adapter);
>> +}
>> +
>> +const struct rsi_mod_ops rsi_bt_ops =3D {
>> + .attach =3D rsi_hci_attach,
>> + .detach =3D rsi_hci_detach,
>> + .recv_pkt =3D rsi_hci_recv_pkt,
>> +};
>> +EXPORT_SYMBOL(rsi_bt_ops);
>> +
>> +static int rsi_91x_bt_module_init(void)
>> +{
>> + return 0;
>> +}
>> +
>> +static void rsi_91x_bt_module_exit(void)
>> +{
>> + return;
>> +}
>> +
>> +module_init(rsi_91x_bt_module_init);
>> +module_exit(rsi_91x_bt_module_exit);
>> +MODULE_AUTHOR("Redpine Signals Inc");
>> +MODULE_DESCRIPTION("RSI BT driver");
>> +MODULE_SUPPORTED_DEVICE("RSI-BT");
>> +MODULE_LICENSE("Dual BSD/GPL=E2=80=9D);
>
> Acked-by: Marcel Holtmann <[email protected]>
> Reviewed-by: Marcel Holtmann <[email protected]>
>

Thanks Marcel.
I will wait for Kalle's review and suggestions.
I will address your minor comments while preparing updated version
based on Kalle's feedback.

Regards,
Amitkumar

2017-12-13 13:46:02

by Marcel Holtmann

[permalink] [raw]
Subject: Re: [v5 5/8] Bluetooth: btrsi: add new rsi bluetooth driver

Hi Amitkumar,

> Redpine bluetooth driver is a thin driver which depends on
> 'rsi_91x' driver for transmitting and receiving packets
> to/from device. It creates hci interface when attach() is
> called from 'rsi_91x' module.
>
> Signed-off-by: Prameela Rani Garnepudi <[email protected]>
> Signed-off-by: Siva Rebbagondla <[email protected]>
> Signed-off-by: Amitkumar Karwar <[email protected]>
> ---
> v5: Addressed review comments from Marcel.
> Removed reduntant switch case code from rsi_hci_recv_pkt()
> Changed bt_cb(skb)->pkt_type to hci_skb_pkt_type(skb)
> Removed reduntant '\n' from BT_ERR and redundant BT_INFO messages
> Changed u8 *pkt to const u8 *pkt in rsi_hci_recv_pkt()
> v4: Removed rsi_hci.h file. Made the functions static(Marcel)
> v3: Made BT_RSI module by default off(Marcel)
> Removed redundant exported function rsi_get_hci_ops()(Marcel)
> v2: Addressed review comments from Marcel
> Removed unnecessary 'depends on BT && BT_RFOMM' line in Kconfig
> Removed redundant BT_INFO messages
> h_adapter initialization and declaration in a single line.
> Removed unnecessary error checks for HCI_RUNNING and fsm_state
> Allocated new skb with skb_realloc_headroom() API if headroom is not sufficient
> Used get_unaligned_le16 helpers
> Moved a structure and union from header file to btrsi.c file
> ---
> drivers/bluetooth/Kconfig | 11 +++
> drivers/bluetooth/Makefile | 2 +
> drivers/bluetooth/btrsi.c | 188 +++++++++++++++++++++++++++++++++++++++++++++
> include/linux/rsi_header.h | 4 +-
> 4 files changed, 204 insertions(+), 1 deletion(-)
> create mode 100644 drivers/bluetooth/btrsi.c
>
> diff --git a/drivers/bluetooth/Kconfig b/drivers/bluetooth/Kconfig
> index 60e1c7d..33d7514 100644
> --- a/drivers/bluetooth/Kconfig
> +++ b/drivers/bluetooth/Kconfig
> @@ -378,4 +378,15 @@ config BT_QCOMSMD
> Say Y here to compile support for HCI over Qualcomm SMD into the
> kernel or say M to compile as a module.
>
> +config BT_RSI
> + tristate "Redpine HCI support"
> + default n
> + help
> + Redpine BT driver.
> + This driver handles BT traffic from upper layers and pass
> + to the RSI_91x coex module for further scheduling to device
> +
> + Say Y here to compile support for HCI over Redpine into the
> + kernel or say M to compile as a module.
> +
> endmenu
> diff --git a/drivers/bluetooth/Makefile b/drivers/bluetooth/Makefile
> index 4e4e44d..712af83a 100644
> --- a/drivers/bluetooth/Makefile
> +++ b/drivers/bluetooth/Makefile
> @@ -28,6 +28,8 @@ obj-$(CONFIG_BT_QCA) += btqca.o
>
> obj-$(CONFIG_BT_HCIUART_NOKIA) += hci_nokia.o
>
> +obj-$(CONFIG_BT_RSI) += btrsi.o
> +

actually I never caught this before. Since this driver is doing the HCI portion, for consistency CONFIG_BT_HCIRSI would be better.

> btmrvl-y := btmrvl_main.o
> btmrvl-$(CONFIG_DEBUG_FS) += btmrvl_debugfs.o
>
> diff --git a/drivers/bluetooth/btrsi.c b/drivers/bluetooth/btrsi.c
> new file mode 100644
> index 0000000..c9e92cc
> --- /dev/null
> +++ b/drivers/bluetooth/btrsi.c
> @@ -0,0 +1,188 @@
> +/**
> + * Copyright (c) 2017 Redpine Signals Inc.
> + *
> + * Permission to use, copy, modify, and/or distribute this software for any
> + * purpose with or without fee is hereby granted, provided that the above
> + * copyright notice and this permission notice appear in all copies.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> + */
> +#include <linux/version.h>
> +#include <linux/module.h>
> +#include <linux/kernel.h>
> +#include <net/bluetooth/bluetooth.h>
> +#include <net/bluetooth/hci_core.h>
> +#include <linux/unaligned/le_byteshift.h>
> +#include <linux/rsi_header.h>
> +#include <net/genetlink.h>
> +
> +#define RSI_HEADROOM_FOR_BT_HAL 16
> +#define RSI_FRAME_DESC_SIZE 16
> +
> +static struct rsi_hci_adapter {
> + void *priv;
> + struct rsi_proto_ops *proto_ops;
> + struct hci_dev *hdev;
> +};
> +
> +static int rsi_hci_open(struct hci_dev *hdev)
> +{
> + return 0;
> +}
> +
> +static int rsi_hci_close(struct hci_dev *hdev)
> +{
> + return 0;
> +}
> +
> +static int rsi_hci_flush(struct hci_dev *hdev)
> +{
> + return 0;
> +}
> +
> +static int rsi_hci_send_pkt(struct hci_dev *hdev, struct sk_buff *skb)
> +{
> + struct rsi_hci_adapter *h_adapter = hci_get_drvdata(hdev);
> + struct sk_buff *new_skb = NULL;
> +
> + switch (hci_skb_pkt_type(skb)) {
> + case HCI_COMMAND_PKT:
> + hdev->stat.cmd_tx++;
> + break;
> + case HCI_ACLDATA_PKT:
> + hdev->stat.acl_tx++;
> + break;
> + case HCI_SCODATA_PKT:
> + hdev->stat.sco_tx++;
> + break;
> + }
> +
> + if (skb_headroom(skb) < RSI_HEADROOM_FOR_BT_HAL) {
> + /* Insufficient skb headroom - allocate a new skb */
> + new_skb = skb_realloc_headroom(skb, RSI_HEADROOM_FOR_BT_HAL);
> + if (unlikely(!new_skb))
> + return -ENOMEM;
> + bt_cb(new_skb)->pkt_type = hci_skb_pkt_type(skb);
> + kfree_skb(skb);
> + skb = new_skb;
> + }
> +
> + return h_adapter->proto_ops->coex_send_pkt(h_adapter->priv, skb,
> + RSI_BT_Q);
> +}
> +
> +static int rsi_hci_recv_pkt(void *priv, const u8 *pkt)
> +{
> + struct rsi_hci_adapter *h_adapter = priv;
> + struct hci_dev *hdev = h_adapter->hdev;
> + struct sk_buff *skb;
> + int pkt_len = get_unaligned_le16(pkt) & 0x0fff;
> +
> + skb = dev_alloc_skb(pkt_len);
> + if (!skb)
> + return -ENOMEM;
> +
> + memcpy(skb->data, pkt + RSI_FRAME_DESC_SIZE, pkt_len);
> + skb_put(skb, pkt_len);
> + h_adapter->hdev->stat.byte_rx += skb->len;
> +
> + hci_skb_pkt_type(skb) = pkt[14];
> +
> + return hci_recv_frame(hdev, skb);
> +}
> +
> +static int rsi_hci_attach(void *priv, struct rsi_proto_ops *ops)
> +{
> + struct rsi_hci_adapter *h_adapter = NULL;
> + struct hci_dev *hdev;
> + int err = 0;
> +
> + h_adapter = kzalloc(sizeof(*h_adapter), GFP_KERNEL);
> + if (!h_adapter)
> + return -ENOMEM;
> +
> + h_adapter->priv = priv;
> + ops->set_bt_context(priv, h_adapter);
> + h_adapter->proto_ops = ops;
> +
> + hdev = hci_alloc_dev();
> + if (!hdev) {
> + BT_ERR("Failed to alloc HCI device");
> + goto err;
> + }
> +
> + h_adapter->hdev = hdev;
> +
> + if (ops->get_host_intf(priv) == RSI_HOST_INTF_SDIO)
> + hdev->bus = HCI_SDIO;
> + else
> + hdev->bus = HCI_USB;
> +
> + hci_set_drvdata(hdev, h_adapter);
> + hdev->dev_type = HCI_PRIMARY;
> + hdev->open = rsi_hci_open;
> + hdev->close = rsi_hci_close;
> + hdev->flush = rsi_hci_flush;
> + hdev->send = rsi_hci_send_pkt;

this doesn’t have to be in this patch, but if you support hdev->set_bdaddr, hdev->set_diag etc. that would be good to add in a follow up.

> +
> + err = hci_register_dev(hdev);
> + if (err < 0) {
> + BT_ERR("HCI registration failed with errcode %d", err);
> + hci_free_dev(hdev);
> + goto err;
> + }
> +
> + return 0;
> +err:
> + h_adapter->hdev = NULL;
> + kfree(h_adapter);
> + return -EINVAL;
> +}
> +
> +static void rsi_hci_detach(void *priv)
> +{
> + struct rsi_hci_adapter *h_adapter = priv;
> + struct hci_dev *hdev;
> +
> + if (!h_adapter)
> + return;
> +
> + hdev = h_adapter->hdev;
> + if (hdev) {
> + hci_unregister_dev(hdev);
> + hci_free_dev(hdev);
> + h_adapter->hdev = NULL;
> + }
> +
> + kfree(h_adapter);
> +}
> +
> +const struct rsi_mod_ops rsi_bt_ops = {
> + .attach = rsi_hci_attach,
> + .detach = rsi_hci_detach,
> + .recv_pkt = rsi_hci_recv_pkt,
> +};
> +EXPORT_SYMBOL(rsi_bt_ops);
> +
> +static int rsi_91x_bt_module_init(void)
> +{
> + return 0;
> +}
> +
> +static void rsi_91x_bt_module_exit(void)
> +{
> + return;
> +}
> +
> +module_init(rsi_91x_bt_module_init);
> +module_exit(rsi_91x_bt_module_exit);
> +MODULE_AUTHOR("Redpine Signals Inc");
> +MODULE_DESCRIPTION("RSI BT driver");
> +MODULE_SUPPORTED_DEVICE("RSI-BT");
> +MODULE_LICENSE("Dual BSD/GPL”);

Acked-by: Marcel Holtmann <[email protected]>
Reviewed-by: Marcel Holtmann <[email protected]>

> diff --git a/include/linux/rsi_header.h b/include/linux/rsi_header.h
> index 737ab4e..040f07b 100644
> --- a/include/linux/rsi_header.h
> +++ b/include/linux/rsi_header.h
> @@ -49,6 +49,8 @@ struct rsi_proto_ops {
> struct rsi_mod_ops {
> int (*attach)(void *priv, struct rsi_proto_ops *ops);
> void (*detach)(void *priv);
> - int (*recv_pkt)(void *priv, u8 *msg);
> + int (*recv_pkt)(void *priv, const u8 *msg);

Think about if this is best done in this patch or one of the early patches before.

> };
> +
> +extern const struct rsi_mod_ops rsi_bt_ops;
> #endif

Regards

Marcel

2017-12-13 12:42:57

by Amitkumar Karwar

[permalink] [raw]
Subject: [v5 8/8] rsi: sdio changes to support BT

From: Prameela Rani Garnepudi <[email protected]>

Queue number is correctly updated for BT traffic. Also, kzalloc
instead of kmalloc is used for Rx packet allocation.

Signed-off-by: Prameela Rani Garnepudi <[email protected]>
Signed-off-by: Amitkumar Karwar <[email protected]>
---
drivers/net/wireless/rsi/rsi_91x_sdio.c | 2 ++
drivers/net/wireless/rsi/rsi_91x_sdio_ops.c | 2 +-
2 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/net/wireless/rsi/rsi_91x_sdio.c b/drivers/net/wireless/rsi/rsi_91x_sdio.c
index 5722736..beb18d0 100644
--- a/drivers/net/wireless/rsi/rsi_91x_sdio.c
+++ b/drivers/net/wireless/rsi/rsi_91x_sdio.c
@@ -763,6 +763,8 @@ static int rsi_sdio_host_intf_write_pkt(struct rsi_hw *adapter,
int status;

queueno = ((pkt[1] >> 4) & 0xf);
+ if (queueno == RSI_BT_MGMT_Q || queueno == RSI_BT_DATA_Q)
+ queueno = RSI_BT_Q;

num_blocks = len / block_size;

diff --git a/drivers/net/wireless/rsi/rsi_91x_sdio_ops.c b/drivers/net/wireless/rsi/rsi_91x_sdio_ops.c
index 26abe51..83652bd 100644
--- a/drivers/net/wireless/rsi/rsi_91x_sdio_ops.c
+++ b/drivers/net/wireless/rsi/rsi_91x_sdio_ops.c
@@ -103,7 +103,7 @@ static int rsi_process_pkt(struct rsi_common *common)

rcv_pkt_len = (num_blks * 256);

- common->rx_data_pkt = kmalloc(rcv_pkt_len, GFP_KERNEL);
+ common->rx_data_pkt = kzalloc(rcv_pkt_len, GFP_KERNEL);
if (!common->rx_data_pkt) {
rsi_dbg(ERR_ZONE, "%s: Failed in memory allocation\n",
__func__);
--
2.7.4


2017-12-13 12:42:56

by Amitkumar Karwar

[permalink] [raw]
Subject: [v5 7/8] rsi: add module parameter operating mode

From: Prameela Rani Garnepudi <[email protected]>

Operating mode determines the support for other protocols.
This is made as module parameter for better usage.

Signed-off-by: Prameela Rani Garnepudi <[email protected]>
Signed-off-by: Siva Rebbagondla <[email protected]>
Signed-off-by: Amitkumar Karwar <[email protected]>
---
drivers/net/wireless/rsi/rsi_91x_main.c | 57 ++++++++++++++++++++++++++++-----
drivers/net/wireless/rsi/rsi_91x_sdio.c | 10 +++++-
drivers/net/wireless/rsi/rsi_91x_usb.c | 10 +++++-
drivers/net/wireless/rsi/rsi_common.h | 2 +-
drivers/net/wireless/rsi/rsi_hal.h | 11 +++++++
5 files changed, 79 insertions(+), 11 deletions(-)

diff --git a/drivers/net/wireless/rsi/rsi_91x_main.c b/drivers/net/wireless/rsi/rsi_91x_main.c
index 375b725..4a0f5a18 100644
--- a/drivers/net/wireless/rsi/rsi_91x_main.c
+++ b/drivers/net/wireless/rsi/rsi_91x_main.c
@@ -68,8 +68,24 @@ EXPORT_SYMBOL_GPL(rsi_dbg);
static char *opmode_str(int oper_mode)
{
switch (oper_mode) {
- case RSI_DEV_OPMODE_WIFI_ALONE:
+ case DEV_OPMODE_WIFI_ALONE:
return "Wi-Fi alone";
+ case DEV_OPMODE_BT_ALONE:
+ return "BT EDR alone";
+ case DEV_OPMODE_BT_LE_ALONE:
+ return "BT LE alone";
+ case DEV_OPMODE_BT_DUAL:
+ return "BT Dual";
+ case DEV_OPMODE_STA_BT:
+ return "Wi-Fi STA + BT EDR";
+ case DEV_OPMODE_STA_BT_LE:
+ return "Wi-Fi STA + BT LE";
+ case DEV_OPMODE_STA_BT_DUAL:
+ return "Wi-Fi STA + BT DUAL";
+ case DEV_OPMODE_AP_BT:
+ return "Wi-Fi AP + BT EDR";
+ case DEV_OPMODE_AP_BT_DUAL:
+ return "Wi-Fi AP + BT DUAL";
}

return "Unknown";
@@ -267,7 +283,7 @@ void rsi_set_bt_context(void *priv, void *bt_context)
*
* Return: Pointer to the adapter structure on success, NULL on failure .
*/
-struct rsi_hw *rsi_91x_init(void)
+struct rsi_hw *rsi_91x_init(u16 oper_mode)
{
struct rsi_hw *adapter = NULL;
struct rsi_common *common = NULL;
@@ -309,11 +325,34 @@ struct rsi_hw *rsi_91x_init(void)
spin_lock_init(&adapter->ps_lock);
timer_setup(&common->roc_timer, rsi_roc_timeout, 0);
init_completion(&common->wlan_init_completion);
+ common->oper_mode = oper_mode;
common->init_done = true;
-
- common->coex_mode = RSI_DEV_COEX_MODE_WIFI_ALONE;
- common->oper_mode = RSI_DEV_OPMODE_WIFI_ALONE;
adapter->device_model = RSI_DEV_9113;
+
+ /* Determine coex mode */
+ switch (common->oper_mode) {
+ case DEV_OPMODE_STA_BT_DUAL:
+ case DEV_OPMODE_STA_BT:
+ case DEV_OPMODE_STA_BT_LE:
+ case DEV_OPMODE_BT_ALONE:
+ case DEV_OPMODE_BT_LE_ALONE:
+ case DEV_OPMODE_BT_DUAL:
+ common->coex_mode = 2;
+ break;
+ case DEV_OPMODE_AP_BT_DUAL:
+ case DEV_OPMODE_AP_BT:
+ common->coex_mode = 4;
+ break;
+ case DEV_OPMODE_WIFI_ALONE:
+ common->coex_mode = 1;
+ break;
+ default:
+ common->oper_mode = 1;
+ common->coex_mode = 1;
+ }
+ rsi_dbg(INFO_ZONE, "%s: oper_mode = %d, coex_mode = %d\n",
+ __func__, common->oper_mode, common->coex_mode);
+
if (common->coex_mode > 1) {
if (rsi_coex_attach(common)) {
rsi_dbg(ERR_ZONE, "Failed to init coex module\n");
@@ -348,10 +387,12 @@ void rsi_91x_deinit(struct rsi_hw *adapter)
for (ii = 0; ii < NUM_SOFT_QUEUES; ii++)
skb_queue_purge(&common->tx_queue[ii]);

- common->init_done = false;
-
- if (common->coex_mode > 1)
+ if (common->coex_mode > 1) {
rsi_coex_detach(common);
+ rsi_bt_ops.detach(common->bt_adapter);
+ }
+
+ common->init_done = false;

kfree(common);
kfree(adapter->rsi_dev);
diff --git a/drivers/net/wireless/rsi/rsi_91x_sdio.c b/drivers/net/wireless/rsi/rsi_91x_sdio.c
index ba38c6d..5722736 100644
--- a/drivers/net/wireless/rsi/rsi_91x_sdio.c
+++ b/drivers/net/wireless/rsi/rsi_91x_sdio.c
@@ -21,6 +21,14 @@
#include "rsi_coex.h"
#include "rsi_hal.h"

+/* Default operating mode is wlan STA + BT */
+static u16 dev_oper_mode = DEV_OPMODE_STA_BT_DUAL;
+module_param(dev_oper_mode, ushort, 0444);
+MODULE_PARM_DESC(dev_oper_mode,
+ "1[Wi-Fi], 4[BT], 8[BT LE], 5[Wi-Fi STA + BT classic]\n"
+ "9[Wi-Fi STA + BT LE], 13[Wi-Fi STA + BT classic + BT LE]\n"
+ "6[AP + BT classic], 14[AP + BT classic + BT LE]");
+
/**
* rsi_sdio_set_cmd52_arg() - This function prepares cmd 52 read/write arg.
* @rw: Read/write
@@ -926,7 +934,7 @@ static int rsi_probe(struct sdio_func *pfunction,

rsi_dbg(INIT_ZONE, "%s: Init function called\n", __func__);

- adapter = rsi_91x_init();
+ adapter = rsi_91x_init(dev_oper_mode);
if (!adapter) {
rsi_dbg(ERR_ZONE, "%s: Failed to init os intf ops\n",
__func__);
diff --git a/drivers/net/wireless/rsi/rsi_91x_usb.c b/drivers/net/wireless/rsi/rsi_91x_usb.c
index aec9d2c..a326162 100644
--- a/drivers/net/wireless/rsi/rsi_91x_usb.c
+++ b/drivers/net/wireless/rsi/rsi_91x_usb.c
@@ -21,6 +21,14 @@
#include "rsi_hal.h"
#include "rsi_coex.h"

+/* Default operating mode is wlan STA + BT */
+static u16 dev_oper_mode = DEV_OPMODE_STA_BT_DUAL;
+module_param(dev_oper_mode, ushort, 0444);
+MODULE_PARM_DESC(dev_oper_mode,
+ "1[Wi-Fi], 4[BT], 8[BT LE], 5[Wi-Fi STA + BT classic]\n"
+ "9[Wi-Fi STA + BT LE], 13[Wi-Fi STA + BT classic + BT LE]\n"
+ "6[AP + BT classic], 14[AP + BT classic + BT LE]");
+
/**
* rsi_usb_card_write() - This function writes to the USB Card.
* @adapter: Pointer to the adapter structure.
@@ -708,7 +716,7 @@ static int rsi_probe(struct usb_interface *pfunction,

rsi_dbg(INIT_ZONE, "%s: Init function called\n", __func__);

- adapter = rsi_91x_init();
+ adapter = rsi_91x_init(dev_oper_mode);
if (!adapter) {
rsi_dbg(ERR_ZONE, "%s: Failed to init os intf ops\n",
__func__);
diff --git a/drivers/net/wireless/rsi/rsi_common.h b/drivers/net/wireless/rsi/rsi_common.h
index 4616585..d9ff3b8 100644
--- a/drivers/net/wireless/rsi/rsi_common.h
+++ b/drivers/net/wireless/rsi/rsi_common.h
@@ -81,7 +81,7 @@ static inline int rsi_kill_thread(struct rsi_thread *handle)

void rsi_mac80211_detach(struct rsi_hw *hw);
u16 rsi_get_connected_channel(struct ieee80211_vif *vif);
-struct rsi_hw *rsi_91x_init(void);
+struct rsi_hw *rsi_91x_init(u16 oper_mode);
void rsi_91x_deinit(struct rsi_hw *adapter);
int rsi_read_pkt(struct rsi_common *common, u8 *rx_pkt, s32 rcv_pkt_len);
#ifdef CONFIG_PM
diff --git a/drivers/net/wireless/rsi/rsi_hal.h b/drivers/net/wireless/rsi/rsi_hal.h
index e712223..a7d3011 100644
--- a/drivers/net/wireless/rsi/rsi_hal.h
+++ b/drivers/net/wireless/rsi/rsi_hal.h
@@ -17,6 +17,17 @@
#ifndef __RSI_HAL_H__
#define __RSI_HAL_H__

+/* Device Operating modes */
+#define DEV_OPMODE_WIFI_ALONE 1
+#define DEV_OPMODE_BT_ALONE 4
+#define DEV_OPMODE_BT_LE_ALONE 8
+#define DEV_OPMODE_BT_DUAL 12
+#define DEV_OPMODE_STA_BT 5
+#define DEV_OPMODE_STA_BT_LE 9
+#define DEV_OPMODE_STA_BT_DUAL 13
+#define DEV_OPMODE_AP_BT 6
+#define DEV_OPMODE_AP_BT_DUAL 14
+
#define FLASH_WRITE_CHUNK_SIZE (4 * 1024)
#define FLASH_SECTOR_SIZE (4 * 1024)

--
2.7.4

2017-12-13 12:42:55

by Amitkumar Karwar

[permalink] [raw]
Subject: [v5 6/8] rsi: handle BT traffic in driver

From: Siva Rebbagondla <[email protected]>

BT frames are passed through coex and hal modules to BUS.
After firmware is loaded, based on the operating mode CARD
READY frame comes for each protocol. When BT card ready is
received, BT attach is called.
Protocol operations are exchanged between the modules
at initialization time.

Signed-off-by: Siva Rebbagondla <[email protected]>
Signed-off-by: Prameela Rani Garnepudi <[email protected]>
Signed-off-by: Amitkumar Karwar <[email protected]>
---
v5: Same as v3, v4
v3: bt_ops need not be present structure g_proto_ops. It is removed.
v2: WLAN module depends on BT module. Updated in Kconfig
---
drivers/net/wireless/rsi/Kconfig | 2 +-
drivers/net/wireless/rsi/rsi_91x_coex.c | 4 ++-
drivers/net/wireless/rsi/rsi_91x_core.c | 16 ++++++++----
drivers/net/wireless/rsi/rsi_91x_hal.c | 39 +++++++++++++++++++++++++++++
drivers/net/wireless/rsi/rsi_91x_main.c | 31 +++++++++++++++++++++++
drivers/net/wireless/rsi/rsi_91x_sdio_ops.c | 1 +
drivers/net/wireless/rsi/rsi_common.h | 1 +
drivers/net/wireless/rsi/rsi_hal.h | 10 ++++++++
drivers/net/wireless/rsi/rsi_main.h | 3 +++
9 files changed, 100 insertions(+), 7 deletions(-)

diff --git a/drivers/net/wireless/rsi/Kconfig b/drivers/net/wireless/rsi/Kconfig
index 7c5e4ca..ad72c80 100644
--- a/drivers/net/wireless/rsi/Kconfig
+++ b/drivers/net/wireless/rsi/Kconfig
@@ -13,7 +13,7 @@ if WLAN_VENDOR_RSI

config RSI_91X
tristate "Redpine Signals Inc 91x WLAN driver support"
- depends on MAC80211
+ depends on MAC80211 && BT_RSI
---help---
This option enabes support for RSI 1x1 devices.
Select M (recommended), if you have a RSI 1x1 wireless module.
diff --git a/drivers/net/wireless/rsi/rsi_91x_coex.c b/drivers/net/wireless/rsi/rsi_91x_coex.c
index 914a0c5..f502cf9 100644
--- a/drivers/net/wireless/rsi/rsi_91x_coex.c
+++ b/drivers/net/wireless/rsi/rsi_91x_coex.c
@@ -48,8 +48,10 @@ static void rsi_coex_sched_tx_pkts(struct rsi_coex_ctrl_block *coex_cb)
break;
}

- if (coex_q == RSI_COEX_Q_BT)
+ if (coex_q == RSI_COEX_Q_BT) {
skb = skb_dequeue(&coex_cb->coex_tx_qs[RSI_COEX_Q_BT]);
+ rsi_send_bt_pkt(coex_cb->priv, skb);
+ }
}
}

diff --git a/drivers/net/wireless/rsi/rsi_91x_core.c b/drivers/net/wireless/rsi/rsi_91x_core.c
index d0d2201..046ace8 100644
--- a/drivers/net/wireless/rsi/rsi_91x_core.c
+++ b/drivers/net/wireless/rsi/rsi_91x_core.c
@@ -17,6 +17,7 @@
#include "rsi_mgmt.h"
#include "rsi_common.h"
#include "rsi_hal.h"
+#include "rsi_coex.h"

/**
* rsi_determine_min_weight_queue() - This function determines the queue with
@@ -301,14 +302,19 @@ void rsi_core_qos_processor(struct rsi_common *common)
mutex_unlock(&common->tx_lock);
break;
}
-
- if (q_num == MGMT_SOFT_Q) {
- status = rsi_send_mgmt_pkt(common, skb);
- } else if (q_num == MGMT_BEACON_Q) {
+ if (q_num == MGMT_BEACON_Q) {
status = rsi_send_pkt_to_bus(common, skb);
dev_kfree_skb(skb);
} else {
- status = rsi_send_data_pkt(common, skb);
+ if (common->coex_mode > 1) {
+ status = rsi_coex_send_pkt(common, skb,
+ RSI_WLAN_Q);
+ } else {
+ if (q_num == MGMT_SOFT_Q)
+ status = rsi_send_mgmt_pkt(common, skb);
+ else
+ status = rsi_send_data_pkt(common, skb);
+ }
}

if (status) {
diff --git a/drivers/net/wireless/rsi/rsi_91x_hal.c b/drivers/net/wireless/rsi/rsi_91x_hal.c
index 8b30448..883dba1 100644
--- a/drivers/net/wireless/rsi/rsi_91x_hal.c
+++ b/drivers/net/wireless/rsi/rsi_91x_hal.c
@@ -15,6 +15,7 @@
*/

#include <linux/firmware.h>
+#include <net/bluetooth/bluetooth.h>
#include "rsi_mgmt.h"
#include "rsi_hal.h"
#include "rsi_sdio.h"
@@ -24,6 +25,7 @@
static struct ta_metadata metadata_flash_content[] = {
{"flash_content", 0x00010000},
{"rsi/rs9113_wlan_qspi.rps", 0x00010000},
+ {"rsi/rs9113_wlan_bt_dual_mode.rps", 0x00010000},
};

int rsi_send_pkt_to_bus(struct rsi_common *common, struct sk_buff *skb)
@@ -357,6 +359,43 @@ int rsi_send_mgmt_pkt(struct rsi_common *common,
return status;
}

+int rsi_send_bt_pkt(struct rsi_common *common, struct sk_buff *skb)
+{
+ int status = -EINVAL;
+ u8 header_size = 0;
+ struct rsi_bt_desc *bt_desc;
+ u8 queueno = ((skb->data[1] >> 4) & 0xf);
+
+ if (queueno == RSI_BT_MGMT_Q) {
+ status = rsi_send_pkt_to_bus(common, skb);
+ if (status)
+ rsi_dbg(ERR_ZONE, "%s: Failed to write bt mgmt pkt\n",
+ __func__);
+ goto out;
+ }
+ header_size = FRAME_DESC_SZ;
+ if (header_size > skb_headroom(skb)) {
+ rsi_dbg(ERR_ZONE, "%s: Not enough headroom\n", __func__);
+ status = -ENOSPC;
+ goto out;
+ }
+ skb_push(skb, header_size);
+ memset(skb->data, 0, header_size);
+ bt_desc = (struct rsi_bt_desc *)skb->data;
+
+ rsi_set_len_qno(&bt_desc->len_qno, (skb->len - FRAME_DESC_SZ),
+ RSI_BT_DATA_Q);
+ bt_desc->bt_pkt_type = cpu_to_le16(bt_cb(skb)->pkt_type);
+
+ status = rsi_send_pkt_to_bus(common, skb);
+ if (status)
+ rsi_dbg(ERR_ZONE, "%s: Failed to write bt pkt\n", __func__);
+
+out:
+ dev_kfree_skb(skb);
+ return status;
+}
+
int rsi_prepare_beacon(struct rsi_common *common, struct sk_buff *skb)
{
struct rsi_hw *adapter = (struct rsi_hw *)common->priv;
diff --git a/drivers/net/wireless/rsi/rsi_91x_main.c b/drivers/net/wireless/rsi/rsi_91x_main.c
index 7dce533..375b725 100644
--- a/drivers/net/wireless/rsi/rsi_91x_main.c
+++ b/drivers/net/wireless/rsi/rsi_91x_main.c
@@ -18,6 +18,7 @@

#include <linux/module.h>
#include <linux/firmware.h>
+#include <linux/rsi_header.h>
#include "rsi_mgmt.h"
#include "rsi_common.h"
#include "rsi_coex.h"
@@ -35,6 +36,12 @@ u32 rsi_zone_enabled = /* INFO_ZONE |
0;
EXPORT_SYMBOL_GPL(rsi_zone_enabled);

+static struct rsi_proto_ops g_proto_ops = {
+ .coex_send_pkt = rsi_coex_send_pkt,
+ .get_host_intf = rsi_get_host_intf,
+ .set_bt_context = rsi_set_bt_context,
+};
+
/**
* rsi_dbg() - This function outputs informational messages.
* @zone: Zone of interest for output message.
@@ -144,6 +151,7 @@ int rsi_read_pkt(struct rsi_common *common, u8 *rx_pkt, s32 rcv_pkt_len)
u32 index, length = 0, queueno = 0;
u16 actual_length = 0, offset;
struct sk_buff *skb = NULL;
+ u8 bt_pkt_type;

index = 0;
do {
@@ -183,6 +191,22 @@ int rsi_read_pkt(struct rsi_common *common, u8 *rx_pkt, s32 rcv_pkt_len)
rsi_mgmt_pkt_recv(common, (frame_desc + offset));
break;

+ case RSI_BT_MGMT_Q:
+ case RSI_BT_DATA_Q:
+#define BT_RX_PKT_TYPE_OFST 14
+#define BT_CARD_READY_IND 0x89
+ bt_pkt_type = frame_desc[offset + BT_RX_PKT_TYPE_OFST];
+ if (bt_pkt_type == BT_CARD_READY_IND) {
+ rsi_dbg(INFO_ZONE, "BT Card ready recvd\n");
+ if (rsi_bt_ops.attach(common, &g_proto_ops))
+ rsi_dbg(ERR_ZONE,
+ "Failed to attach BT module\n");
+ } else {
+ rsi_bt_ops.recv_pkt(common->bt_adapter,
+ frame_desc + offset);
+ }
+ break;
+
default:
rsi_dbg(ERR_ZONE, "%s: pkt from invalid queue: %d\n",
__func__, queueno);
@@ -230,6 +254,13 @@ enum rsi_host_intf rsi_get_host_intf(void *priv)
return common->priv->rsi_host_intf;
}

+void rsi_set_bt_context(void *priv, void *bt_context)
+{
+ struct rsi_common *common = (struct rsi_common *)priv;
+
+ common->bt_adapter = bt_context;
+}
+
/**
* rsi_91x_init() - This function initializes os interface operations.
* @void: Void.
diff --git a/drivers/net/wireless/rsi/rsi_91x_sdio_ops.c b/drivers/net/wireless/rsi/rsi_91x_sdio_ops.c
index 9fbc0ef..26abe51 100644
--- a/drivers/net/wireless/rsi/rsi_91x_sdio_ops.c
+++ b/drivers/net/wireless/rsi/rsi_91x_sdio_ops.c
@@ -16,6 +16,7 @@
*/

#include <linux/firmware.h>
+#include <linux/rsi_header.h>
#include "rsi_sdio.h"
#include "rsi_common.h"

diff --git a/drivers/net/wireless/rsi/rsi_common.h b/drivers/net/wireless/rsi/rsi_common.h
index 1d8af41..4616585 100644
--- a/drivers/net/wireless/rsi/rsi_common.h
+++ b/drivers/net/wireless/rsi/rsi_common.h
@@ -62,6 +62,7 @@ static inline int rsi_create_kthread(struct rsi_common *common,
u8 *name)
{
init_completion(&thread->completion);
+ atomic_set(&thread->thread_done, 0);
thread->task = kthread_run(func_ptr, common, "%s", name);
if (IS_ERR(thread->task))
return (int)PTR_ERR(thread->task);
diff --git a/drivers/net/wireless/rsi/rsi_hal.h b/drivers/net/wireless/rsi/rsi_hal.h
index a09d36b..e712223 100644
--- a/drivers/net/wireless/rsi/rsi_hal.h
+++ b/drivers/net/wireless/rsi/rsi_hal.h
@@ -145,8 +145,18 @@ struct rsi_data_desc {
u8 sta_id;
} __packed;

+struct rsi_bt_desc {
+ __le16 len_qno;
+ __le16 reserved1;
+ __le32 reserved2;
+ __le32 reserved3;
+ __le16 reserved4;
+ __le16 bt_pkt_type;
+} __packed;
+
int rsi_hal_device_init(struct rsi_hw *adapter);
int rsi_prepare_beacon(struct rsi_common *common, struct sk_buff *skb);
int rsi_send_pkt_to_bus(struct rsi_common *common, struct sk_buff *skb);
+int rsi_send_bt_pkt(struct rsi_common *common, struct sk_buff *skb);

#endif
diff --git a/drivers/net/wireless/rsi/rsi_main.h b/drivers/net/wireless/rsi/rsi_main.h
index e1c1dc8..69a604e 100644
--- a/drivers/net/wireless/rsi/rsi_main.h
+++ b/drivers/net/wireless/rsi/rsi_main.h
@@ -290,6 +290,8 @@ struct rsi_common {
bool p2p_enabled;
struct timer_list roc_timer;
struct ieee80211_vif *roc_vif;
+
+ void *bt_adapter;
};

struct eepromrw_info {
@@ -363,5 +365,6 @@ struct rsi_host_intf_ops {
};

enum rsi_host_intf rsi_get_host_intf(void *priv);
+void rsi_set_bt_context(void *priv, void *bt_context);

#endif
--
2.7.4


2017-12-13 12:42:54

by Amitkumar Karwar

[permalink] [raw]
Subject: [v5 5/8] Bluetooth: btrsi: add new rsi bluetooth driver

From: Prameela Rani Garnepudi <[email protected]>

Redpine bluetooth driver is a thin driver which depends on
'rsi_91x' driver for transmitting and receiving packets
to/from device. It creates hci interface when attach() is
called from 'rsi_91x' module.

Signed-off-by: Prameela Rani Garnepudi <[email protected]>
Signed-off-by: Siva Rebbagondla <[email protected]>
Signed-off-by: Amitkumar Karwar <[email protected]>
---
v5: Addressed review comments from Marcel.
Removed reduntant switch case code from rsi_hci_recv_pkt()
Changed bt_cb(skb)->pkt_type to hci_skb_pkt_type(skb)
Removed reduntant '\n' from BT_ERR and redundant BT_INFO messages
Changed u8 *pkt to const u8 *pkt in rsi_hci_recv_pkt()
v4: Removed rsi_hci.h file. Made the functions static(Marcel)
v3: Made BT_RSI module by default off(Marcel)
Removed redundant exported function rsi_get_hci_ops()(Marcel)
v2: Addressed review comments from Marcel
Removed unnecessary 'depends on BT && BT_RFOMM' line in Kconfig
Removed redundant BT_INFO messages
h_adapter initialization and declaration in a single line.
Removed unnecessary error checks for HCI_RUNNING and fsm_state
Allocated new skb with skb_realloc_headroom() API if headroom is not sufficient
Used get_unaligned_le16 helpers
Moved a structure and union from header file to btrsi.c file
---
drivers/bluetooth/Kconfig | 11 +++
drivers/bluetooth/Makefile | 2 +
drivers/bluetooth/btrsi.c | 188 +++++++++++++++++++++++++++++++++++++++++++++
include/linux/rsi_header.h | 4 +-
4 files changed, 204 insertions(+), 1 deletion(-)
create mode 100644 drivers/bluetooth/btrsi.c

diff --git a/drivers/bluetooth/Kconfig b/drivers/bluetooth/Kconfig
index 60e1c7d..33d7514 100644
--- a/drivers/bluetooth/Kconfig
+++ b/drivers/bluetooth/Kconfig
@@ -378,4 +378,15 @@ config BT_QCOMSMD
Say Y here to compile support for HCI over Qualcomm SMD into the
kernel or say M to compile as a module.

+config BT_RSI
+ tristate "Redpine HCI support"
+ default n
+ help
+ Redpine BT driver.
+ This driver handles BT traffic from upper layers and pass
+ to the RSI_91x coex module for further scheduling to device
+
+ Say Y here to compile support for HCI over Redpine into the
+ kernel or say M to compile as a module.
+
endmenu
diff --git a/drivers/bluetooth/Makefile b/drivers/bluetooth/Makefile
index 4e4e44d..712af83a 100644
--- a/drivers/bluetooth/Makefile
+++ b/drivers/bluetooth/Makefile
@@ -28,6 +28,8 @@ obj-$(CONFIG_BT_QCA) += btqca.o

obj-$(CONFIG_BT_HCIUART_NOKIA) += hci_nokia.o

+obj-$(CONFIG_BT_RSI) += btrsi.o
+
btmrvl-y := btmrvl_main.o
btmrvl-$(CONFIG_DEBUG_FS) += btmrvl_debugfs.o

diff --git a/drivers/bluetooth/btrsi.c b/drivers/bluetooth/btrsi.c
new file mode 100644
index 0000000..c9e92cc
--- /dev/null
+++ b/drivers/bluetooth/btrsi.c
@@ -0,0 +1,188 @@
+/**
+ * Copyright (c) 2017 Redpine Signals Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <net/bluetooth/bluetooth.h>
+#include <net/bluetooth/hci_core.h>
+#include <linux/unaligned/le_byteshift.h>
+#include <linux/rsi_header.h>
+#include <net/genetlink.h>
+
+#define RSI_HEADROOM_FOR_BT_HAL 16
+#define RSI_FRAME_DESC_SIZE 16
+
+static struct rsi_hci_adapter {
+ void *priv;
+ struct rsi_proto_ops *proto_ops;
+ struct hci_dev *hdev;
+};
+
+static int rsi_hci_open(struct hci_dev *hdev)
+{
+ return 0;
+}
+
+static int rsi_hci_close(struct hci_dev *hdev)
+{
+ return 0;
+}
+
+static int rsi_hci_flush(struct hci_dev *hdev)
+{
+ return 0;
+}
+
+static int rsi_hci_send_pkt(struct hci_dev *hdev, struct sk_buff *skb)
+{
+ struct rsi_hci_adapter *h_adapter = hci_get_drvdata(hdev);
+ struct sk_buff *new_skb = NULL;
+
+ switch (hci_skb_pkt_type(skb)) {
+ case HCI_COMMAND_PKT:
+ hdev->stat.cmd_tx++;
+ break;
+ case HCI_ACLDATA_PKT:
+ hdev->stat.acl_tx++;
+ break;
+ case HCI_SCODATA_PKT:
+ hdev->stat.sco_tx++;
+ break;
+ }
+
+ if (skb_headroom(skb) < RSI_HEADROOM_FOR_BT_HAL) {
+ /* Insufficient skb headroom - allocate a new skb */
+ new_skb = skb_realloc_headroom(skb, RSI_HEADROOM_FOR_BT_HAL);
+ if (unlikely(!new_skb))
+ return -ENOMEM;
+ bt_cb(new_skb)->pkt_type = hci_skb_pkt_type(skb);
+ kfree_skb(skb);
+ skb = new_skb;
+ }
+
+ return h_adapter->proto_ops->coex_send_pkt(h_adapter->priv, skb,
+ RSI_BT_Q);
+}
+
+static int rsi_hci_recv_pkt(void *priv, const u8 *pkt)
+{
+ struct rsi_hci_adapter *h_adapter = priv;
+ struct hci_dev *hdev = h_adapter->hdev;
+ struct sk_buff *skb;
+ int pkt_len = get_unaligned_le16(pkt) & 0x0fff;
+
+ skb = dev_alloc_skb(pkt_len);
+ if (!skb)
+ return -ENOMEM;
+
+ memcpy(skb->data, pkt + RSI_FRAME_DESC_SIZE, pkt_len);
+ skb_put(skb, pkt_len);
+ h_adapter->hdev->stat.byte_rx += skb->len;
+
+ hci_skb_pkt_type(skb) = pkt[14];
+
+ return hci_recv_frame(hdev, skb);
+}
+
+static int rsi_hci_attach(void *priv, struct rsi_proto_ops *ops)
+{
+ struct rsi_hci_adapter *h_adapter = NULL;
+ struct hci_dev *hdev;
+ int err = 0;
+
+ h_adapter = kzalloc(sizeof(*h_adapter), GFP_KERNEL);
+ if (!h_adapter)
+ return -ENOMEM;
+
+ h_adapter->priv = priv;
+ ops->set_bt_context(priv, h_adapter);
+ h_adapter->proto_ops = ops;
+
+ hdev = hci_alloc_dev();
+ if (!hdev) {
+ BT_ERR("Failed to alloc HCI device");
+ goto err;
+ }
+
+ h_adapter->hdev = hdev;
+
+ if (ops->get_host_intf(priv) == RSI_HOST_INTF_SDIO)
+ hdev->bus = HCI_SDIO;
+ else
+ hdev->bus = HCI_USB;
+
+ hci_set_drvdata(hdev, h_adapter);
+ hdev->dev_type = HCI_PRIMARY;
+ hdev->open = rsi_hci_open;
+ hdev->close = rsi_hci_close;
+ hdev->flush = rsi_hci_flush;
+ hdev->send = rsi_hci_send_pkt;
+
+ err = hci_register_dev(hdev);
+ if (err < 0) {
+ BT_ERR("HCI registration failed with errcode %d", err);
+ hci_free_dev(hdev);
+ goto err;
+ }
+
+ return 0;
+err:
+ h_adapter->hdev = NULL;
+ kfree(h_adapter);
+ return -EINVAL;
+}
+
+static void rsi_hci_detach(void *priv)
+{
+ struct rsi_hci_adapter *h_adapter = priv;
+ struct hci_dev *hdev;
+
+ if (!h_adapter)
+ return;
+
+ hdev = h_adapter->hdev;
+ if (hdev) {
+ hci_unregister_dev(hdev);
+ hci_free_dev(hdev);
+ h_adapter->hdev = NULL;
+ }
+
+ kfree(h_adapter);
+}
+
+const struct rsi_mod_ops rsi_bt_ops = {
+ .attach = rsi_hci_attach,
+ .detach = rsi_hci_detach,
+ .recv_pkt = rsi_hci_recv_pkt,
+};
+EXPORT_SYMBOL(rsi_bt_ops);
+
+static int rsi_91x_bt_module_init(void)
+{
+ return 0;
+}
+
+static void rsi_91x_bt_module_exit(void)
+{
+ return;
+}
+
+module_init(rsi_91x_bt_module_init);
+module_exit(rsi_91x_bt_module_exit);
+MODULE_AUTHOR("Redpine Signals Inc");
+MODULE_DESCRIPTION("RSI BT driver");
+MODULE_SUPPORTED_DEVICE("RSI-BT");
+MODULE_LICENSE("Dual BSD/GPL");
diff --git a/include/linux/rsi_header.h b/include/linux/rsi_header.h
index 737ab4e..040f07b 100644
--- a/include/linux/rsi_header.h
+++ b/include/linux/rsi_header.h
@@ -49,6 +49,8 @@ struct rsi_proto_ops {
struct rsi_mod_ops {
int (*attach)(void *priv, struct rsi_proto_ops *ops);
void (*detach)(void *priv);
- int (*recv_pkt)(void *priv, u8 *msg);
+ int (*recv_pkt)(void *priv, const u8 *msg);
};
+
+extern const struct rsi_mod_ops rsi_bt_ops;
#endif
--
2.7.4


2017-12-13 12:42:53

by Amitkumar Karwar

[permalink] [raw]
Subject: [v5 4/8] rsi: add coex support

From: Prameela Rani Garnepudi <[email protected]>

With BT support, driver has to handle two streams of data
(i.e. wlan and BT). Actual coex implementation is in firmware.
Coex module just schedule the packets to firmware by taking them
from the corresponding paths.

Structures for module and protocol operations are introduced for
this purpose. Protocol operations structure is global structure
which can be shared among different modules. Initialization of
coex and operating mode values is moved to rsi_91x_init().

Signed-off-by: Prameela Rani Garnepudi <[email protected]>
Signed-off-by: Siva Rebbagondla <[email protected]>
Signed-off-by: Amitkumar Karwar <[email protected]>
---
drivers/net/wireless/rsi/Makefile | 1 +
drivers/net/wireless/rsi/rsi_91x_coex.c | 182 ++++++++++++++++++++++++++++++++
drivers/net/wireless/rsi/rsi_91x_hal.c | 17 +--
drivers/net/wireless/rsi/rsi_91x_main.c | 30 +++++-
drivers/net/wireless/rsi/rsi_91x_mgmt.c | 2 +-
drivers/net/wireless/rsi/rsi_91x_sdio.c | 1 +
drivers/net/wireless/rsi/rsi_91x_usb.c | 2 +
drivers/net/wireless/rsi/rsi_coex.h | 38 +++++++
drivers/net/wireless/rsi/rsi_main.h | 5 +
drivers/net/wireless/rsi/rsi_mgmt.h | 3 +
include/linux/rsi_header.h | 20 ++++
11 files changed, 291 insertions(+), 10 deletions(-)
create mode 100644 drivers/net/wireless/rsi/rsi_91x_coex.c
create mode 100644 drivers/net/wireless/rsi/rsi_coex.h

diff --git a/drivers/net/wireless/rsi/Makefile b/drivers/net/wireless/rsi/Makefile
index 47c4590..fda827b 100644
--- a/drivers/net/wireless/rsi/Makefile
+++ b/drivers/net/wireless/rsi/Makefile
@@ -5,6 +5,7 @@ rsi_91x-y += rsi_91x_mac80211.o
rsi_91x-y += rsi_91x_mgmt.o
rsi_91x-y += rsi_91x_hal.o
rsi_91x-y += rsi_91x_ps.o
+rsi_91x-y += rsi_91x_coex.o
rsi_91x-$(CONFIG_RSI_DEBUGFS) += rsi_91x_debugfs.o

rsi_usb-y += rsi_91x_usb.o rsi_91x_usb_ops.o
diff --git a/drivers/net/wireless/rsi/rsi_91x_coex.c b/drivers/net/wireless/rsi/rsi_91x_coex.c
new file mode 100644
index 0000000..914a0c5
--- /dev/null
+++ b/drivers/net/wireless/rsi/rsi_91x_coex.c
@@ -0,0 +1,182 @@
+/**
+ * Copyright (c) 2017 Redpine Signals Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "rsi_main.h"
+#include "rsi_coex.h"
+#include "rsi_mgmt.h"
+#include "rsi_hal.h"
+
+static enum rsi_coex_queues rsi_coex_determine_coex_q
+ (struct rsi_coex_ctrl_block *coex_cb)
+{
+ enum rsi_coex_queues q_num = RSI_COEX_Q_INVALID;
+
+ if (skb_queue_len(&coex_cb->coex_tx_qs[RSI_COEX_Q_COMMON]) > 0)
+ q_num = RSI_COEX_Q_COMMON;
+ if (skb_queue_len(&coex_cb->coex_tx_qs[RSI_COEX_Q_BT]) > 0)
+ q_num = RSI_COEX_Q_BT;
+ if (skb_queue_len(&coex_cb->coex_tx_qs[RSI_COEX_Q_WLAN]) > 0)
+ q_num = RSI_COEX_Q_WLAN;
+
+ return q_num;
+}
+
+static void rsi_coex_sched_tx_pkts(struct rsi_coex_ctrl_block *coex_cb)
+{
+ enum rsi_coex_queues coex_q;
+ struct sk_buff *skb;
+
+ while (1) {
+ coex_q = rsi_coex_determine_coex_q(coex_cb);
+ rsi_dbg(INFO_ZONE, "queue = %d\n", coex_q);
+
+ if (coex_q == RSI_COEX_Q_INVALID) {
+ rsi_dbg(DATA_TX_ZONE, "No more pkt\n");
+ break;
+ }
+
+ if (coex_q == RSI_COEX_Q_BT)
+ skb = skb_dequeue(&coex_cb->coex_tx_qs[RSI_COEX_Q_BT]);
+ }
+}
+
+static void rsi_coex_scheduler_thread(struct rsi_common *common)
+{
+ struct rsi_coex_ctrl_block *coex_cb =
+ (struct rsi_coex_ctrl_block *)common->coex_cb;
+ u32 timeout = EVENT_WAIT_FOREVER;
+
+ do {
+ rsi_wait_event(&coex_cb->coex_tx_thread.event, timeout);
+ rsi_reset_event(&coex_cb->coex_tx_thread.event);
+
+ rsi_coex_sched_tx_pkts(coex_cb);
+ } while (atomic_read(&coex_cb->coex_tx_thread.thread_done) == 0);
+
+ complete_and_exit(&coex_cb->coex_tx_thread.completion, 0);
+}
+
+int rsi_coex_recv_pkt(struct rsi_common *common, u8 *msg)
+{
+ u8 msg_type = msg[RSI_RX_DESC_MSG_TYPE_OFFSET];
+
+ switch (msg_type) {
+ case COMMON_CARD_READY_IND:
+ rsi_dbg(INFO_ZONE, "common card ready received\n");
+ rsi_handle_card_ready(common, msg);
+ break;
+ case SLEEP_NOTIFY_IND:
+ rsi_dbg(INFO_ZONE, "sleep notify received\n");
+ rsi_mgmt_pkt_recv(common, msg);
+ break;
+ }
+
+ return 0;
+}
+
+static inline int rsi_map_coex_q(u8 hal_queue)
+{
+ switch (hal_queue) {
+ case RSI_COEX_Q:
+ return RSI_COEX_Q_COMMON;
+ case RSI_WLAN_Q:
+ return RSI_COEX_Q_WLAN;
+ case RSI_BT_Q:
+ return RSI_COEX_Q_BT;
+ }
+ return RSI_COEX_Q_INVALID;
+}
+
+int rsi_coex_send_pkt(void *priv, struct sk_buff *skb, u8 hal_queue)
+{
+ struct rsi_common *common = (struct rsi_common *)priv;
+ struct rsi_coex_ctrl_block *coex_cb =
+ (struct rsi_coex_ctrl_block *)common->coex_cb;
+ struct skb_info *tx_params = NULL;
+ enum rsi_coex_queues coex_q;
+ int status;
+
+ coex_q = rsi_map_coex_q(hal_queue);
+ if (coex_q == RSI_COEX_Q_INVALID) {
+ rsi_dbg(ERR_ZONE, "Invalid coex queue\n");
+ return -EINVAL;
+ }
+ if (coex_q != RSI_COEX_Q_COMMON &&
+ coex_q != RSI_COEX_Q_WLAN) {
+ skb_queue_tail(&coex_cb->coex_tx_qs[coex_q], skb);
+ rsi_set_event(&coex_cb->coex_tx_thread.event);
+ return 0;
+ }
+ if (common->iface_down) {
+ tx_params =
+ (struct skb_info *)&IEEE80211_SKB_CB(skb)->driver_data;
+
+ if (!(tx_params->flags & INTERNAL_MGMT_PKT)) {
+ rsi_indicate_tx_status(common->priv, skb, -EINVAL);
+ return 0;
+ }
+ }
+
+ /* Send packet to hal */
+ if (skb->priority == MGMT_SOFT_Q)
+ status = rsi_send_mgmt_pkt(common, skb);
+ else
+ status = rsi_send_data_pkt(common, skb);
+
+ return status;
+}
+
+int rsi_coex_attach(struct rsi_common *common)
+{
+ struct rsi_coex_ctrl_block *coex_cb;
+ int cnt;
+
+ coex_cb = kzalloc(sizeof(*coex_cb), GFP_KERNEL);
+ if (!coex_cb)
+ return -ENOMEM;
+
+ common->coex_cb = (void *)coex_cb;
+ coex_cb->priv = common;
+
+ /* Initialize co-ex queues */
+ for (cnt = 0; cnt < NUM_COEX_TX_QUEUES; cnt++)
+ skb_queue_head_init(&coex_cb->coex_tx_qs[cnt]);
+ rsi_init_event(&coex_cb->coex_tx_thread.event);
+
+ /* Initialize co-ex thread */
+ if (rsi_create_kthread(common,
+ &coex_cb->coex_tx_thread,
+ rsi_coex_scheduler_thread,
+ "Coex-Tx-Thread")) {
+ rsi_dbg(ERR_ZONE, "%s: Unable to init tx thrd\n", __func__);
+ return -EINVAL;
+ }
+ return 0;
+}
+
+void rsi_coex_detach(struct rsi_common *common)
+{
+ struct rsi_coex_ctrl_block *coex_cb =
+ (struct rsi_coex_ctrl_block *)common->coex_cb;
+ int cnt;
+
+ rsi_kill_thread(&coex_cb->coex_tx_thread);
+
+ for (cnt = 0; cnt < NUM_COEX_TX_QUEUES; cnt++)
+ skb_queue_purge(&coex_cb->coex_tx_qs[cnt]);
+
+ kfree(coex_cb);
+}
diff --git a/drivers/net/wireless/rsi/rsi_91x_hal.c b/drivers/net/wireless/rsi/rsi_91x_hal.c
index 1176de6..8b30448 100644
--- a/drivers/net/wireless/rsi/rsi_91x_hal.c
+++ b/drivers/net/wireless/rsi/rsi_91x_hal.c
@@ -31,8 +31,15 @@ int rsi_send_pkt_to_bus(struct rsi_common *common, struct sk_buff *skb)
struct rsi_hw *adapter = common->priv;
int status;

+ if (common->coex_mode > 1)
+ down(&common->tx_bus_lock);
+
status = adapter->host_intf_ops->write_pkt(common->priv,
skb->data, skb->len);
+
+ if (common->coex_mode > 1)
+ up(&common->tx_bus_lock);
+
return status;
}

@@ -296,8 +303,7 @@ int rsi_send_data_pkt(struct rsi_common *common, struct sk_buff *skb)
if (status)
goto err;

- status = adapter->host_intf_ops->write_pkt(common->priv, skb->data,
- skb->len);
+ status = rsi_send_pkt_to_bus(common, skb);
if (status)
rsi_dbg(ERR_ZONE, "%s: Failed to write pkt\n", __func__);

@@ -342,8 +348,7 @@ int rsi_send_mgmt_pkt(struct rsi_common *common,
goto err;

rsi_prepare_mgmt_desc(common, skb);
- status = adapter->host_intf_ops->write_pkt(common->priv,
- (u8 *)skb->data, skb->len);
+ status = rsi_send_pkt_to_bus(common, skb);
if (status)
rsi_dbg(ERR_ZONE, "%s: Failed to write the packet\n", __func__);

@@ -926,10 +931,6 @@ int rsi_hal_device_init(struct rsi_hw *adapter)
{
struct rsi_common *common = adapter->priv;

- common->coex_mode = RSI_DEV_COEX_MODE_WIFI_ALONE;
- common->oper_mode = RSI_DEV_OPMODE_WIFI_ALONE;
- adapter->device_model = RSI_DEV_9113;
-
switch (adapter->device_model) {
case RSI_DEV_9113:
if (rsi_load_firmware(adapter)) {
diff --git a/drivers/net/wireless/rsi/rsi_91x_main.c b/drivers/net/wireless/rsi/rsi_91x_main.c
index 0413af8..7dce533 100644
--- a/drivers/net/wireless/rsi/rsi_91x_main.c
+++ b/drivers/net/wireless/rsi/rsi_91x_main.c
@@ -20,6 +20,7 @@
#include <linux/firmware.h>
#include "rsi_mgmt.h"
#include "rsi_common.h"
+#include "rsi_coex.h"
#include "rsi_hal.h"

u32 rsi_zone_enabled = /* INFO_ZONE |
@@ -160,8 +161,13 @@ int rsi_read_pkt(struct rsi_common *common, u8 *rx_pkt, s32 rcv_pkt_len)

switch (queueno) {
case RSI_COEX_Q:
- rsi_mgmt_pkt_recv(common, (frame_desc + offset));
+ if (common->coex_mode > 1)
+ rsi_coex_recv_pkt(common, frame_desc + offset);
+ else
+ rsi_mgmt_pkt_recv(common,
+ (frame_desc + offset));
break;
+
case RSI_WIFI_DATA_Q:
skb = rsi_prepare_skb(common,
(frame_desc + offset),
@@ -217,6 +223,13 @@ static void rsi_tx_scheduler_thread(struct rsi_common *common)
complete_and_exit(&common->tx_thread.completion, 0);
}

+enum rsi_host_intf rsi_get_host_intf(void *priv)
+{
+ struct rsi_common *common = (struct rsi_common *)priv;
+
+ return common->priv->rsi_host_intf;
+}
+
/**
* rsi_91x_init() - This function initializes os interface operations.
* @void: Void.
@@ -251,6 +264,7 @@ struct rsi_hw *rsi_91x_init(void)
mutex_init(&common->mutex);
mutex_init(&common->tx_lock);
mutex_init(&common->rx_lock);
+ sema_init(&common->tx_bus_lock, 1);

if (rsi_create_kthread(common,
&common->tx_thread,
@@ -265,6 +279,17 @@ struct rsi_hw *rsi_91x_init(void)
timer_setup(&common->roc_timer, rsi_roc_timeout, 0);
init_completion(&common->wlan_init_completion);
common->init_done = true;
+
+ common->coex_mode = RSI_DEV_COEX_MODE_WIFI_ALONE;
+ common->oper_mode = RSI_DEV_OPMODE_WIFI_ALONE;
+ adapter->device_model = RSI_DEV_9113;
+ if (common->coex_mode > 1) {
+ if (rsi_coex_attach(common)) {
+ rsi_dbg(ERR_ZONE, "Failed to init coex module\n");
+ goto err;
+ }
+ }
+
return adapter;

err:
@@ -294,6 +319,9 @@ void rsi_91x_deinit(struct rsi_hw *adapter)

common->init_done = false;

+ if (common->coex_mode > 1)
+ rsi_coex_detach(common);
+
kfree(common);
kfree(adapter->rsi_dev);
kfree(adapter);
diff --git a/drivers/net/wireless/rsi/rsi_91x_mgmt.c b/drivers/net/wireless/rsi/rsi_91x_mgmt.c
index 46c9d54..c21fca7 100644
--- a/drivers/net/wireless/rsi/rsi_91x_mgmt.c
+++ b/drivers/net/wireless/rsi/rsi_91x_mgmt.c
@@ -1791,7 +1791,7 @@ static int rsi_handle_ta_confirm_type(struct rsi_common *common,
return -EINVAL;
}

-static int rsi_handle_card_ready(struct rsi_common *common, u8 *msg)
+int rsi_handle_card_ready(struct rsi_common *common, u8 *msg)
{
switch (common->fsm_state) {
case FSM_CARD_NOT_READY:
diff --git a/drivers/net/wireless/rsi/rsi_91x_sdio.c b/drivers/net/wireless/rsi/rsi_91x_sdio.c
index b0cf411..ba38c6d 100644
--- a/drivers/net/wireless/rsi/rsi_91x_sdio.c
+++ b/drivers/net/wireless/rsi/rsi_91x_sdio.c
@@ -18,6 +18,7 @@
#include <linux/module.h>
#include "rsi_sdio.h"
#include "rsi_common.h"
+#include "rsi_coex.h"
#include "rsi_hal.h"

/**
diff --git a/drivers/net/wireless/rsi/rsi_91x_usb.c b/drivers/net/wireless/rsi/rsi_91x_usb.c
index 343fcb2..aec9d2c 100644
--- a/drivers/net/wireless/rsi/rsi_91x_usb.c
+++ b/drivers/net/wireless/rsi/rsi_91x_usb.c
@@ -16,8 +16,10 @@
*/

#include <linux/module.h>
+#include <linux/rsi_header.h>
#include "rsi_usb.h"
#include "rsi_hal.h"
+#include "rsi_coex.h"

/**
* rsi_usb_card_write() - This function writes to the USB Card.
diff --git a/drivers/net/wireless/rsi/rsi_coex.h b/drivers/net/wireless/rsi/rsi_coex.h
new file mode 100644
index 0000000..22fe6ff
--- /dev/null
+++ b/drivers/net/wireless/rsi/rsi_coex.h
@@ -0,0 +1,38 @@
+/**
+ * Copyright (c) 2017 Redpine Signals Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef __RSI_COEX_H__
+#define __RSI_COEX_H__
+
+#include "rsi_common.h"
+
+#define RSI_COEX_TXQ_MAX_PKTS 64
+#define RSI_COEX_TXQ_WATER_MARK 50
+#define COMMON_CARD_READY_IND 0
+#define NUM_COEX_TX_QUEUES 5
+
+struct rsi_coex_ctrl_block {
+ struct rsi_common *priv;
+ struct sk_buff_head coex_tx_qs[NUM_COEX_TX_QUEUES];
+ struct rsi_thread coex_tx_thread;
+};
+
+int rsi_coex_attach(struct rsi_common *common);
+void rsi_coex_detach(struct rsi_common *common);
+int rsi_coex_send_pkt(void *priv, struct sk_buff *skb, u8 proto_type);
+int rsi_coex_recv_pkt(struct rsi_common *common, u8 *msg);
+
+#endif
diff --git a/drivers/net/wireless/rsi/rsi_main.h b/drivers/net/wireless/rsi/rsi_main.h
index ca02a4b..e1c1dc8 100644
--- a/drivers/net/wireless/rsi/rsi_main.h
+++ b/drivers/net/wireless/rsi/rsi_main.h
@@ -206,6 +206,7 @@ struct rsi_common {
struct rsi_hw *priv;
struct vif_priv vif_info[RSI_MAX_VIFS];

+ void *coex_cb;
bool mgmt_q_block;
struct version_info lmac_ver;

@@ -270,6 +271,7 @@ struct rsi_common {
u8 obm_ant_sel_val;
int tx_power;
u8 ant_in_use;
+ struct semaphore tx_bus_lock;
bool hibernate_resume;
bool reinit_hw;
u8 wow_flags;
@@ -359,4 +361,7 @@ struct rsi_host_intf_ops {
u8 *fw);
int (*reinit_device)(struct rsi_hw *adapter);
};
+
+enum rsi_host_intf rsi_get_host_intf(void *priv);
+
#endif
diff --git a/drivers/net/wireless/rsi/rsi_mgmt.h b/drivers/net/wireless/rsi/rsi_mgmt.h
index 389094a..cf6567a 100644
--- a/drivers/net/wireless/rsi/rsi_mgmt.h
+++ b/drivers/net/wireless/rsi/rsi_mgmt.h
@@ -57,12 +57,14 @@
#define WOW_PATTERN_SIZE 256

/* Receive Frame Types */
+#define RSI_RX_DESC_MSG_TYPE_OFFSET 2
#define TA_CONFIRM_TYPE 0x01
#define RX_DOT11_MGMT 0x02
#define TX_STATUS_IND 0x04
#define BEACON_EVENT_IND 0x08
#define PROBEREQ_CONFIRM 2
#define CARD_READY_IND 0x00
+#define SLEEP_NOTIFY_IND 0x06

#define RSI_DELETE_PEER 0x0
#define RSI_ADD_PEER 0x1
@@ -638,6 +640,7 @@ static inline void rsi_set_len_qno(__le16 *addr, u16 len, u8 qno)
*addr = cpu_to_le16(len | ((qno & 7) << 12));
}

+int rsi_handle_card_ready(struct rsi_common *common, u8 *msg);
int rsi_mgmt_pkt_recv(struct rsi_common *common, u8 *msg);
int rsi_set_vap_capabilities(struct rsi_common *common, enum opmode mode,
u8 *mac_addr, u8 vap_id, u8 vap_status);
diff --git a/include/linux/rsi_header.h b/include/linux/rsi_header.h
index 16a447b..737ab4e 100644
--- a/include/linux/rsi_header.h
+++ b/include/linux/rsi_header.h
@@ -17,6 +17,8 @@
#ifndef __RSI_HEADER_H__
#define __RSI_HEADER_H__

+#include <linux/skbuff.h>
+
/* HAL queue information */
#define RSI_COEX_Q 0x0
#define RSI_BT_Q 0x2
@@ -26,9 +28,27 @@
#define RSI_BT_MGMT_Q 0x6
#define RSI_BT_DATA_Q 0x7

+enum rsi_coex_queues {
+ RSI_COEX_Q_INVALID = -1,
+ RSI_COEX_Q_COMMON = 0,
+ RSI_COEX_Q_BT,
+ RSI_COEX_Q_WLAN
+};
+
enum rsi_host_intf {
RSI_HOST_INTF_SDIO = 0,
RSI_HOST_INTF_USB
};

+struct rsi_proto_ops {
+ int (*coex_send_pkt)(void *priv, struct sk_buff *skb, u8 hal_queue);
+ enum rsi_host_intf (*get_host_intf)(void *priv);
+ void (*set_bt_context)(void *priv, void *context);
+};
+
+struct rsi_mod_ops {
+ int (*attach)(void *priv, struct rsi_proto_ops *ops);
+ void (*detach)(void *priv);
+ int (*recv_pkt)(void *priv, u8 *msg);
+};
#endif
--
2.7.4

2017-12-13 12:42:52

by Amitkumar Karwar

[permalink] [raw]
Subject: [v5 3/8] rsi: add header file rsi_header

From: Prameela Rani Garnepudi <[email protected]>

The common parameters used by wlan and bt modules are added
to a new header file "rsi_header.h" defined in '/include/linux'

Signed-off-by: Prameela Rani Garnepudi <[email protected]>
Signed-off-by: Siva Rebbagondla <[email protected]>
Signed-off-by: Amitkumar Karwar <[email protected]>
---
drivers/net/wireless/rsi/rsi_main.h | 12 ++----------
include/linux/rsi_header.h | 34 ++++++++++++++++++++++++++++++++++
2 files changed, 36 insertions(+), 10 deletions(-)
create mode 100644 include/linux/rsi_header.h

diff --git a/drivers/net/wireless/rsi/rsi_main.h b/drivers/net/wireless/rsi/rsi_main.h
index ee469dc..ca02a4b 100644
--- a/drivers/net/wireless/rsi/rsi_main.h
+++ b/drivers/net/wireless/rsi/rsi_main.h
@@ -20,6 +20,7 @@
#include <linux/string.h>
#include <linux/skbuff.h>
#include <net/mac80211.h>
+#include <linux/rsi_header.h>

struct rsi_sta {
struct ieee80211_sta *sta;
@@ -85,10 +86,6 @@ extern __printf(2, 3) void rsi_dbg(u32 zone, const char *fmt, ...);
#define MGMT_HW_Q 10
#define BEACON_HW_Q 11

-/* Queue information */
-#define RSI_COEX_Q 0x0
-#define RSI_WIFI_MGMT_Q 0x4
-#define RSI_WIFI_DATA_Q 0x5
#define IEEE80211_MGMT_FRAME 0x00
#define IEEE80211_CTL_FRAME 0x04

@@ -293,11 +290,6 @@ struct rsi_common {
struct ieee80211_vif *roc_vif;
};

-enum host_intf {
- RSI_HOST_INTF_SDIO = 0,
- RSI_HOST_INTF_USB
-};
-
struct eepromrw_info {
u32 offset;
u32 length;
@@ -322,7 +314,7 @@ struct rsi_hw {
struct device *device;
u8 sc_nvifs;

- enum host_intf rsi_host_intf;
+ enum rsi_host_intf rsi_host_intf;
u16 block_size;
enum ps_state ps_state;
struct rsi_ps_info ps_info;
diff --git a/include/linux/rsi_header.h b/include/linux/rsi_header.h
new file mode 100644
index 0000000..16a447b
--- /dev/null
+++ b/include/linux/rsi_header.h
@@ -0,0 +1,34 @@
+/**
+ * Copyright (c) 2017 Redpine Signals Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef __RSI_HEADER_H__
+#define __RSI_HEADER_H__
+
+/* HAL queue information */
+#define RSI_COEX_Q 0x0
+#define RSI_BT_Q 0x2
+#define RSI_WLAN_Q 0x3
+#define RSI_WIFI_MGMT_Q 0x4
+#define RSI_WIFI_DATA_Q 0x5
+#define RSI_BT_MGMT_Q 0x6
+#define RSI_BT_DATA_Q 0x7
+
+enum rsi_host_intf {
+ RSI_HOST_INTF_SDIO = 0,
+ RSI_HOST_INTF_USB
+};
+
+#endif
--
2.7.4


2017-12-13 12:42:51

by Amitkumar Karwar

[permalink] [raw]
Subject: [v5 2/8] rsi: add bluetooth rx endpoint

From: Siva Rebbagondla <[email protected]>

USB endpoint 1 is used for WLAN which is presently in use.
USB endpoint 2 is introduced for BT Rx traffic. Enumeration
of Rx BT endpoint and submitting Rx BT URB are added.

>From /sys/kernel/debug/usb/devices,
Ad=81(I) is for WLAN EP IN and Ad=01(O) is for Wlan EP OUT.
Ad=82(I) is for BT EP IN and Ad=02(O) is for BT EP OUT.

T: Bus=01 Lev=01 Prnt=01 Port=09 Cnt=03 Dev#= 4 Spd=480 MxCh= 0
D: Ver= 2.00 Cls=00(>ifc ) Sub=00 Prot=00 MxPS=64 #Cfgs= 1
P: Vendor=1618 ProdID=9113 Rev= 0.02
S: Manufacturer=Redpine Signals, Inc.
S: Product=Wireless USB Network Module
S: SerialNumber=000000000001
C:* #Ifs= 1 Cfg#= 1 Atr=c0 MxPwr= 2mA
I:* If#= 0 Alt= 0 #EPs= 6 Cls=00(>ifc ) Sub=00 Prot=00 Driver=(none)
E: Ad=81(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms
E: Ad=01(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms
E: Ad=82(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms
E: Ad=02(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms
E: Ad=83(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms
E: Ad=03(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms

Signed-off-by: Siva Rebbagondla <[email protected]>
Signed-off-by: Prameela Rani Garnepudi <[email protected]>
Signed-off-by: Amitkumar Karwar <[email protected]>
---
v5: Same as v2, v3, v4
v2: Included '/sys/kernel/debug/usb/devices' info in patch description(Marcel)
---
drivers/net/wireless/rsi/rsi_91x_usb.c | 37 ++++++++++++++++++++--------------
drivers/net/wireless/rsi/rsi_usb.h | 6 +++---
2 files changed, 25 insertions(+), 18 deletions(-)

diff --git a/drivers/net/wireless/rsi/rsi_91x_usb.c b/drivers/net/wireless/rsi/rsi_91x_usb.c
index 6e99175..343fcb2 100644
--- a/drivers/net/wireless/rsi/rsi_91x_usb.c
+++ b/drivers/net/wireless/rsi/rsi_91x_usb.c
@@ -103,41 +103,42 @@ static int rsi_find_bulk_in_and_out_endpoints(struct usb_interface *interface,
struct usb_host_interface *iface_desc;
struct usb_endpoint_descriptor *endpoint;
__le16 buffer_size;
- int ii, bep_found = 0;
+ int ii, bin_found = 0, bout_found = 0;

iface_desc = &(interface->altsetting[0]);

for (ii = 0; ii < iface_desc->desc.bNumEndpoints; ++ii) {
endpoint = &(iface_desc->endpoint[ii].desc);

- if ((!(dev->bulkin_endpoint_addr)) &&
+ if (!dev->bulkin_endpoint_addr[bin_found] &&
(endpoint->bEndpointAddress & USB_DIR_IN) &&
- ((endpoint->bmAttributes &
- USB_ENDPOINT_XFERTYPE_MASK) ==
+ ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
USB_ENDPOINT_XFER_BULK)) {
buffer_size = endpoint->wMaxPacketSize;
- dev->bulkin_size = buffer_size;
- dev->bulkin_endpoint_addr =
+ dev->bulkin_size[bin_found] = buffer_size;
+ dev->bulkin_endpoint_addr[bin_found] =
endpoint->bEndpointAddress;
+ bin_found++;
}

- if (!dev->bulkout_endpoint_addr[bep_found] &&
+ if (!dev->bulkout_endpoint_addr[bout_found] &&
!(endpoint->bEndpointAddress & USB_DIR_IN) &&
((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
- USB_ENDPOINT_XFER_BULK)) {
- dev->bulkout_endpoint_addr[bep_found] =
+ USB_ENDPOINT_XFER_BULK)) {
+ buffer_size = endpoint->wMaxPacketSize;
+ dev->bulkout_endpoint_addr[bout_found] =
endpoint->bEndpointAddress;
buffer_size = endpoint->wMaxPacketSize;
- dev->bulkout_size[bep_found] = buffer_size;
- bep_found++;
+ dev->bulkout_size[bout_found] = buffer_size;
+ bout_found++;
}

- if (bep_found >= MAX_BULK_EP)
+ if (bin_found >= MAX_BULK_EP || bout_found >= MAX_BULK_EP)
break;
}

- if (!(dev->bulkin_endpoint_addr) &&
- (dev->bulkout_endpoint_addr[0]))
+ if (!(dev->bulkin_endpoint_addr[0]) &&
+ dev->bulkout_endpoint_addr[0])
return -EINVAL;

return 0;
@@ -273,7 +274,7 @@ static int rsi_rx_urb_submit(struct rsi_hw *adapter, u8 ep_num)
usb_fill_bulk_urb(urb,
dev->usbdev,
usb_rcvbulkpipe(dev->usbdev,
- dev->bulkin_endpoint_addr),
+ dev->bulkin_endpoint_addr[ep_num - 1]),
urb->transfer_buffer,
3000,
rsi_rx_done_handler,
@@ -745,6 +746,12 @@ static int rsi_probe(struct usb_interface *pfunction,
if (status)
goto err1;

+ if (adapter->priv->coex_mode > 1) {
+ status = rsi_rx_urb_submit(adapter, BT_EP);
+ if (status)
+ goto err1;
+ }
+
return 0;
err1:
rsi_deinit_usb_interface(adapter);
diff --git a/drivers/net/wireless/rsi/rsi_usb.h b/drivers/net/wireless/rsi/rsi_usb.h
index 7e781d5..0fda14c 100644
--- a/drivers/net/wireless/rsi/rsi_usb.h
+++ b/drivers/net/wireless/rsi/rsi_usb.h
@@ -31,7 +31,7 @@
#define USB_VENDOR_REGISTER_WRITE 0x16
#define RSI_USB_TX_HEAD_ROOM 128

-#define MAX_RX_URBS 1
+#define MAX_RX_URBS 2
#define MAX_BULK_EP 8
#define WLAN_EP 1
#define BT_EP 2
@@ -54,8 +54,8 @@ struct rsi_91x_usbdev {
struct usb_interface *pfunction;
struct rx_usb_ctrl_block rx_cb[MAX_RX_URBS];
u8 *tx_buffer;
- __le16 bulkin_size;
- u8 bulkin_endpoint_addr;
+ __le16 bulkin_size[MAX_BULK_EP];
+ u8 bulkin_endpoint_addr[MAX_BULK_EP];
__le16 bulkout_size[MAX_BULK_EP];
u8 bulkout_endpoint_addr[MAX_BULK_EP];
u32 tx_blk_size;
--
2.7.4

2017-12-13 12:42:50

by Amitkumar Karwar

[permalink] [raw]
Subject: [v5 1/8] rsi: add rx control block to handle rx packets in USB

From: Prameela Rani Garnepudi <[email protected]>

Rx bluetooth endpoint shall be added in further patches. Rx control
block is introduced here to handle Rx packets properly. Separate
function is written to initialize the RX control blocks.

Signed-off-by: Prameela Rani Garnepudi <[email protected]>
Signed-off-by: Siva Rebbagondla <[email protected]>
Signed-off-by: Amitkumar Karwar <[email protected]>
---
drivers/net/wireless/rsi/rsi_91x_main.c | 4 +-
drivers/net/wireless/rsi/rsi_91x_sdio_ops.c | 2 +-
drivers/net/wireless/rsi/rsi_91x_usb.c | 75 +++++++++++++++++++++++------
drivers/net/wireless/rsi/rsi_91x_usb_ops.c | 35 +++++++++-----
drivers/net/wireless/rsi/rsi_common.h | 2 +-
drivers/net/wireless/rsi/rsi_main.h | 2 +-
drivers/net/wireless/rsi/rsi_usb.h | 10 +++-
7 files changed, 96 insertions(+), 34 deletions(-)

diff --git a/drivers/net/wireless/rsi/rsi_91x_main.c b/drivers/net/wireless/rsi/rsi_91x_main.c
index 0cb8e68..0413af8 100644
--- a/drivers/net/wireless/rsi/rsi_91x_main.c
+++ b/drivers/net/wireless/rsi/rsi_91x_main.c
@@ -137,7 +137,7 @@ static struct sk_buff *rsi_prepare_skb(struct rsi_common *common,
*
* Return: 0 on success, -1 on failure.
*/
-int rsi_read_pkt(struct rsi_common *common, s32 rcv_pkt_len)
+int rsi_read_pkt(struct rsi_common *common, u8 *rx_pkt, s32 rcv_pkt_len)
{
u8 *frame_desc = NULL, extended_desc = 0;
u32 index, length = 0, queueno = 0;
@@ -146,7 +146,7 @@ int rsi_read_pkt(struct rsi_common *common, s32 rcv_pkt_len)

index = 0;
do {
- frame_desc = &common->rx_data_pkt[index];
+ frame_desc = &rx_pkt[index];
actual_length = *(u16 *)&frame_desc[0];
offset = *(u16 *)&frame_desc[2];

diff --git a/drivers/net/wireless/rsi/rsi_91x_sdio_ops.c b/drivers/net/wireless/rsi/rsi_91x_sdio_ops.c
index 8e2a95c..9fbc0ef 100644
--- a/drivers/net/wireless/rsi/rsi_91x_sdio_ops.c
+++ b/drivers/net/wireless/rsi/rsi_91x_sdio_ops.c
@@ -118,7 +118,7 @@ static int rsi_process_pkt(struct rsi_common *common)
goto fail;
}

- status = rsi_read_pkt(common, rcv_pkt_len);
+ status = rsi_read_pkt(common, common->rx_data_pkt, rcv_pkt_len);

fail:
kfree(common->rx_data_pkt);
diff --git a/drivers/net/wireless/rsi/rsi_91x_usb.c b/drivers/net/wireless/rsi/rsi_91x_usb.c
index 8f84438..6e99175 100644
--- a/drivers/net/wireless/rsi/rsi_91x_usb.c
+++ b/drivers/net/wireless/rsi/rsi_91x_usb.c
@@ -247,12 +247,13 @@ static int rsi_usb_reg_write(struct usb_device *usbdev,
*/
static void rsi_rx_done_handler(struct urb *urb)
{
- struct rsi_hw *adapter = urb->context;
- struct rsi_91x_usbdev *dev = (struct rsi_91x_usbdev *)adapter->rsi_dev;
+ struct rx_usb_ctrl_block *rx_cb = urb->context;
+ struct rsi_91x_usbdev *dev = (struct rsi_91x_usbdev *)rx_cb->data;

if (urb->status)
return;

+ rx_cb->pend = 1;
rsi_set_event(&dev->rx_thread.event);
}

@@ -262,10 +263,11 @@ static void rsi_rx_done_handler(struct urb *urb)
*
* Return: 0 on success, a negative error code on failure.
*/
-static int rsi_rx_urb_submit(struct rsi_hw *adapter)
+static int rsi_rx_urb_submit(struct rsi_hw *adapter, u8 ep_num)
{
struct rsi_91x_usbdev *dev = (struct rsi_91x_usbdev *)adapter->rsi_dev;
- struct urb *urb = dev->rx_usb_urb[0];
+ struct rx_usb_ctrl_block *rx_cb = &dev->rx_cb[ep_num - 1];
+ struct urb *urb = rx_cb->rx_urb;
int status;

usb_fill_bulk_urb(urb,
@@ -275,7 +277,7 @@ static int rsi_rx_urb_submit(struct rsi_hw *adapter)
urb->transfer_buffer,
3000,
rsi_rx_done_handler,
- adapter);
+ rx_cb);

status = usb_submit_urb(urb, GFP_KERNEL);
if (status)
@@ -484,14 +486,54 @@ static struct rsi_host_intf_ops usb_host_intf_ops = {
*/
static void rsi_deinit_usb_interface(struct rsi_hw *adapter)
{
+ u8 idx;
+
struct rsi_91x_usbdev *dev = (struct rsi_91x_usbdev *)adapter->rsi_dev;

rsi_kill_thread(&dev->rx_thread);
- usb_free_urb(dev->rx_usb_urb[0]);
+
+ for (idx = 0; idx < MAX_RX_URBS; idx++) {
+ usb_free_urb(dev->rx_cb[idx].rx_urb);
+ kfree(dev->rx_cb[idx].rx_buffer);
+ }
+
kfree(adapter->priv->rx_data_pkt);
kfree(dev->tx_buffer);
}

+static int rsi_usb_init_rx(struct rsi_hw *adapter)
+{
+ struct rsi_91x_usbdev *dev = (struct rsi_91x_usbdev *)adapter->rsi_dev;
+ struct rx_usb_ctrl_block *rx_cb;
+ u8 idx;
+
+ for (idx = 0; idx < MAX_RX_URBS; idx++) {
+ rx_cb = &dev->rx_cb[idx];
+
+ rx_cb->rx_buffer = kzalloc(RSI_USB_BUF_SIZE * 2,
+ GFP_KERNEL | GFP_DMA);
+ if (!rx_cb->rx_buffer)
+ goto err;
+
+ rx_cb->rx_urb = usb_alloc_urb(0, GFP_KERNEL);
+ if (!rx_cb->rx_urb) {
+ rsi_dbg(ERR_ZONE, "Failed alloc rx urb[%d]\n", idx);
+ goto err;
+ }
+ rx_cb->rx_urb->transfer_buffer = rx_cb->rx_buffer;
+ rx_cb->ep_num = idx + 1;
+ rx_cb->data = (void *)dev;
+ }
+ return 0;
+
+err:
+ for (idx = 0; idx < MAX_RX_URBS; idx++) {
+ kfree(dev->rx_cb[idx].rx_buffer);
+ kfree(dev->rx_cb[idx].rx_urb);
+ }
+ return -1;
+}
+
/**
* rsi_init_usb_interface() - This function initializes the usb interface.
* @adapter: Pointer to the adapter structure.
@@ -504,7 +546,7 @@ static int rsi_init_usb_interface(struct rsi_hw *adapter,
{
struct rsi_91x_usbdev *rsi_dev;
struct rsi_common *common = adapter->priv;
- int status;
+ int status, i;

rsi_dev = kzalloc(sizeof(*rsi_dev), GFP_KERNEL);
if (!rsi_dev)
@@ -531,12 +573,12 @@ static int rsi_init_usb_interface(struct rsi_hw *adapter,
status = -ENOMEM;
goto fail_tx;
}
- rsi_dev->rx_usb_urb[0] = usb_alloc_urb(0, GFP_KERNEL);
- if (!rsi_dev->rx_usb_urb[0]) {
- status = -ENOMEM;
- goto fail_rx;
+
+ if (rsi_usb_init_rx(adapter)) {
+ rsi_dbg(ERR_ZONE, "Failed to init RX handle\n");
+ return -ENOMEM;
}
- rsi_dev->rx_usb_urb[0]->transfer_buffer = adapter->priv->rx_data_pkt;
+
rsi_dev->tx_blk_size = 252;
adapter->block_size = rsi_dev->tx_blk_size;

@@ -564,9 +606,10 @@ static int rsi_init_usb_interface(struct rsi_hw *adapter,
return 0;

fail_thread:
- usb_free_urb(rsi_dev->rx_usb_urb[0]);
-fail_rx:
- kfree(rsi_dev->tx_buffer);
+ for (i = 0; i < MAX_RX_URBS; i++) {
+ kfree(rsi_dev->rx_cb[i].rx_buffer);
+ kfree(rsi_dev->rx_cb[i].rx_urb);
+ }
fail_tx:
kfree(common->rx_data_pkt);
return status;
@@ -698,7 +741,7 @@ static int rsi_probe(struct usb_interface *pfunction,
rsi_dbg(INIT_ZONE, "%s: Device Init Done\n", __func__);
}

- status = rsi_rx_urb_submit(adapter);
+ status = rsi_rx_urb_submit(adapter, WLAN_EP);
if (status)
goto err1;

diff --git a/drivers/net/wireless/rsi/rsi_91x_usb_ops.c b/drivers/net/wireless/rsi/rsi_91x_usb_ops.c
index 465692b..d0650ea 100644
--- a/drivers/net/wireless/rsi/rsi_91x_usb_ops.c
+++ b/drivers/net/wireless/rsi/rsi_91x_usb_ops.c
@@ -29,7 +29,8 @@ void rsi_usb_rx_thread(struct rsi_common *common)
{
struct rsi_hw *adapter = common->priv;
struct rsi_91x_usbdev *dev = (struct rsi_91x_usbdev *)adapter->rsi_dev;
- int status;
+ struct rx_usb_ctrl_block *rx_cb;
+ int status, idx;

do {
rsi_wait_event(&dev->rx_thread.event, EVENT_WAIT_FOREVER);
@@ -37,20 +38,30 @@ void rsi_usb_rx_thread(struct rsi_common *common)
if (atomic_read(&dev->rx_thread.thread_done))
goto out;

- mutex_lock(&common->rx_lock);
- status = rsi_read_pkt(common, 0);
- if (status) {
- rsi_dbg(ERR_ZONE, "%s: Failed To read data", __func__);
+ for (idx = 0; idx < MAX_RX_URBS; idx++) {
+ rx_cb = &dev->rx_cb[idx];
+ if (!rx_cb->pend)
+ continue;
+
+ mutex_lock(&common->rx_lock);
+ status = rsi_read_pkt(common, rx_cb->rx_buffer, 0);
+ if (status) {
+ rsi_dbg(ERR_ZONE, "%s: Failed To read data",
+ __func__);
+ mutex_unlock(&common->rx_lock);
+ break;
+ }
+ rx_cb->pend = 0;
mutex_unlock(&common->rx_lock);
- return;
+
+ if (adapter->rx_urb_submit(adapter, rx_cb->ep_num)) {
+ rsi_dbg(ERR_ZONE,
+ "%s: Failed in urb submission",
+ __func__);
+ return;
+ }
}
- mutex_unlock(&common->rx_lock);
rsi_reset_event(&dev->rx_thread.event);
- if (adapter->rx_urb_submit(adapter)) {
- rsi_dbg(ERR_ZONE,
- "%s: Failed in urb submission", __func__);
- return;
- }
} while (1);

out:
diff --git a/drivers/net/wireless/rsi/rsi_common.h b/drivers/net/wireless/rsi/rsi_common.h
index d07dbba..1d8af41 100644
--- a/drivers/net/wireless/rsi/rsi_common.h
+++ b/drivers/net/wireless/rsi/rsi_common.h
@@ -82,7 +82,7 @@ void rsi_mac80211_detach(struct rsi_hw *hw);
u16 rsi_get_connected_channel(struct ieee80211_vif *vif);
struct rsi_hw *rsi_91x_init(void);
void rsi_91x_deinit(struct rsi_hw *adapter);
-int rsi_read_pkt(struct rsi_common *common, s32 rcv_pkt_len);
+int rsi_read_pkt(struct rsi_common *common, u8 *rx_pkt, s32 rcv_pkt_len);
#ifdef CONFIG_PM
int rsi_config_wowlan(struct rsi_hw *adapter, struct cfg80211_wowlan *wowlan);
#endif
diff --git a/drivers/net/wireless/rsi/rsi_main.h b/drivers/net/wireless/rsi/rsi_main.h
index 8cab630..ee469dc 100644
--- a/drivers/net/wireless/rsi/rsi_main.h
+++ b/drivers/net/wireless/rsi/rsi_main.h
@@ -343,7 +343,7 @@ struct rsi_hw {
void *rsi_dev;
struct rsi_host_intf_ops *host_intf_ops;
int (*check_hw_queue_status)(struct rsi_hw *adapter, u8 q_num);
- int (*rx_urb_submit)(struct rsi_hw *adapter);
+ int (*rx_urb_submit)(struct rsi_hw *adapter, u8 ep_num);
int (*determine_event_timeout)(struct rsi_hw *adapter);
};

diff --git a/drivers/net/wireless/rsi/rsi_usb.h b/drivers/net/wireless/rsi/rsi_usb.h
index 891daea..7e781d5 100644
--- a/drivers/net/wireless/rsi/rsi_usb.h
+++ b/drivers/net/wireless/rsi/rsi_usb.h
@@ -39,12 +39,20 @@
#define RSI_USB_BUF_SIZE 4096
#define RSI_USB_CTRL_BUF_SIZE 0x04

+struct rx_usb_ctrl_block {
+ u8 *data;
+ struct urb *rx_urb;
+ u8 *rx_buffer;
+ u8 ep_num;
+ u8 pend;
+};
+
struct rsi_91x_usbdev {
struct rsi_thread rx_thread;
u8 endpoint;
struct usb_device *usbdev;
struct usb_interface *pfunction;
- struct urb *rx_usb_urb[MAX_RX_URBS];
+ struct rx_usb_ctrl_block rx_cb[MAX_RX_URBS];
u8 *tx_buffer;
__le16 bulkin_size;
u8 bulkin_endpoint_addr;
--
2.7.4


2018-01-19 06:53:11

by Amitkumar Karwar

[permalink] [raw]
Subject: Re: [v5 5/8] Bluetooth: btrsi: add new rsi bluetooth driver

Hi Kalle,

On Thu, Dec 14, 2017 at 7:52 PM, Amitkumar Karwar <[email protected]> wr=
ote:
> On Wed, Dec 13, 2017 at 7:16 PM, Marcel Holtmann <[email protected]> wr=
ote:
>> Hi Amitkumar,
>>
>>> Redpine bluetooth driver is a thin driver which depends on
>>> 'rsi_91x' driver for transmitting and receiving packets
>>> to/from device. It creates hci interface when attach() is
>>> called from 'rsi_91x' module.
>>>
>>> Signed-off-by: Prameela Rani Garnepudi <[email protected]>
>>> Signed-off-by: Siva Rebbagondla <[email protected]>
>>> Signed-off-by: Amitkumar Karwar <[email protected]>
>>> ---
>>> v5: Addressed review comments from Marcel.
>>> Removed reduntant switch case code from rsi_hci_recv_pkt()
>>> Changed bt_cb(skb)->pkt_type to hci_skb_pkt_type(skb)
>>> Removed reduntant '\n' from BT_ERR and redundant BT_INFO messages
>>> Changed u8 *pkt to const u8 *pkt in rsi_hci_recv_pkt()
>>> v4: Removed rsi_hci.h file. Made the functions static(Marcel)
>>> v3: Made BT_RSI module by default off(Marcel)
>>> Removed redundant exported function rsi_get_hci_ops()(Marcel)
>>> v2: Addressed review comments from Marcel
>>> Removed unnecessary 'depends on BT && BT_RFOMM' line in Kconfig
>>> Removed redundant BT_INFO messages
>>> h_adapter initialization and declaration in a single line.
>>> Removed unnecessary error checks for HCI_RUNNING and fsm_state
>>> Allocated new skb with skb_realloc_headroom() API if headroom is not=
sufficient
>>> Used get_unaligned_le16 helpers
>>> Moved a structure and union from header file to btrsi.c file
>>> ---
>>> drivers/bluetooth/Kconfig | 11 +++
>>> drivers/bluetooth/Makefile | 2 +
>>> drivers/bluetooth/btrsi.c | 188 ++++++++++++++++++++++++++++++++++++++=
+++++++
>>> include/linux/rsi_header.h | 4 +-
>>> 4 files changed, 204 insertions(+), 1 deletion(-)
>>> create mode 100644 drivers/bluetooth/btrsi.c
>>>
>>> diff --git a/drivers/bluetooth/Kconfig b/drivers/bluetooth/Kconfig
>>> index 60e1c7d..33d7514 100644
>>> --- a/drivers/bluetooth/Kconfig
>>> +++ b/drivers/bluetooth/Kconfig
>>> @@ -378,4 +378,15 @@ config BT_QCOMSMD
>>> Say Y here to compile support for HCI over Qualcomm SMD into th=
e
>>> kernel or say M to compile as a module.
>>>
>>> +config BT_RSI
>>> + tristate "Redpine HCI support"
>>> + default n
>>> + help
>>> + Redpine BT driver.
>>> + This driver handles BT traffic from upper layers and pass
>>> + to the RSI_91x coex module for further scheduling to device
>>> +
>>> + Say Y here to compile support for HCI over Redpine into the
>>> + kernel or say M to compile as a module.
>>> +
>>> endmenu
>>> diff --git a/drivers/bluetooth/Makefile b/drivers/bluetooth/Makefile
>>> index 4e4e44d..712af83a 100644
>>> --- a/drivers/bluetooth/Makefile
>>> +++ b/drivers/bluetooth/Makefile
>>> @@ -28,6 +28,8 @@ obj-$(CONFIG_BT_QCA) +=3D btqca.o
>>>
>>> obj-$(CONFIG_BT_HCIUART_NOKIA) +=3D hci_nokia.o
>>>
>>> +obj-$(CONFIG_BT_RSI) +=3D btrsi.o
>>> +
>>
>> actually I never caught this before. Since this driver is doing the HCI =
portion, for consistency CONFIG_BT_HCIRSI would be better.
>>
>>> btmrvl-y :=3D btmrvl_main.o
>>> btmrvl-$(CONFIG_DEBUG_FS) +=3D btmrvl_debugfs.o
>>>
>>> diff --git a/drivers/bluetooth/btrsi.c b/drivers/bluetooth/btrsi.c
>>> new file mode 100644
>>> index 0000000..c9e92cc
>>> --- /dev/null
>>> +++ b/drivers/bluetooth/btrsi.c
>>> @@ -0,0 +1,188 @@
>>> +/**
>>> + * Copyright (c) 2017 Redpine Signals Inc.
>>> + *
>>> + * Permission to use, copy, modify, and/or distribute this software fo=
r any
>>> + * purpose with or without fee is hereby granted, provided that the ab=
ove
>>> + * copyright notice and this permission notice appear in all copies.
>>> + *
>>> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRA=
NTIES
>>> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
>>> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE=
FOR
>>> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMA=
GES
>>> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN =
AN
>>> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OU=
T OF
>>> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
>>> + */
>>> +#include <linux/version.h>
>>> +#include <linux/module.h>
>>> +#include <linux/kernel.h>
>>> +#include <net/bluetooth/bluetooth.h>
>>> +#include <net/bluetooth/hci_core.h>
>>> +#include <linux/unaligned/le_byteshift.h>
>>> +#include <linux/rsi_header.h>
>>> +#include <net/genetlink.h>
>>> +
>>> +#define RSI_HEADROOM_FOR_BT_HAL 16
>>> +#define RSI_FRAME_DESC_SIZE 16
>>> +
>>> +static struct rsi_hci_adapter {
>>> + void *priv;
>>> + struct rsi_proto_ops *proto_ops;
>>> + struct hci_dev *hdev;
>>> +};
>>> +
>>> +static int rsi_hci_open(struct hci_dev *hdev)
>>> +{
>>> + return 0;
>>> +}
>>> +
>>> +static int rsi_hci_close(struct hci_dev *hdev)
>>> +{
>>> + return 0;
>>> +}
>>> +
>>> +static int rsi_hci_flush(struct hci_dev *hdev)
>>> +{
>>> + return 0;
>>> +}
>>> +
>>> +static int rsi_hci_send_pkt(struct hci_dev *hdev, struct sk_buff *skb)
>>> +{
>>> + struct rsi_hci_adapter *h_adapter =3D hci_get_drvdata(hdev);
>>> + struct sk_buff *new_skb =3D NULL;
>>> +
>>> + switch (hci_skb_pkt_type(skb)) {
>>> + case HCI_COMMAND_PKT:
>>> + hdev->stat.cmd_tx++;
>>> + break;
>>> + case HCI_ACLDATA_PKT:
>>> + hdev->stat.acl_tx++;
>>> + break;
>>> + case HCI_SCODATA_PKT:
>>> + hdev->stat.sco_tx++;
>>> + break;
>>> + }
>>> +
>>> + if (skb_headroom(skb) < RSI_HEADROOM_FOR_BT_HAL) {
>>> + /* Insufficient skb headroom - allocate a new skb */
>>> + new_skb =3D skb_realloc_headroom(skb, RSI_HEADROOM_FOR_BT=
_HAL);
>>> + if (unlikely(!new_skb))
>>> + return -ENOMEM;
>>> + bt_cb(new_skb)->pkt_type =3D hci_skb_pkt_type(skb);
>>> + kfree_skb(skb);
>>> + skb =3D new_skb;
>>> + }
>>> +
>>> + return h_adapter->proto_ops->coex_send_pkt(h_adapter->priv, skb,
>>> + RSI_BT_Q);
>>> +}
>>> +
>>> +static int rsi_hci_recv_pkt(void *priv, const u8 *pkt)
>>> +{
>>> + struct rsi_hci_adapter *h_adapter =3D priv;
>>> + struct hci_dev *hdev =3D h_adapter->hdev;
>>> + struct sk_buff *skb;
>>> + int pkt_len =3D get_unaligned_le16(pkt) & 0x0fff;
>>> +
>>> + skb =3D dev_alloc_skb(pkt_len);
>>> + if (!skb)
>>> + return -ENOMEM;
>>> +
>>> + memcpy(skb->data, pkt + RSI_FRAME_DESC_SIZE, pkt_len);
>>> + skb_put(skb, pkt_len);
>>> + h_adapter->hdev->stat.byte_rx +=3D skb->len;
>>> +
>>> + hci_skb_pkt_type(skb) =3D pkt[14];
>>> +
>>> + return hci_recv_frame(hdev, skb);
>>> +}
>>> +
>>> +static int rsi_hci_attach(void *priv, struct rsi_proto_ops *ops)
>>> +{
>>> + struct rsi_hci_adapter *h_adapter =3D NULL;
>>> + struct hci_dev *hdev;
>>> + int err =3D 0;
>>> +
>>> + h_adapter =3D kzalloc(sizeof(*h_adapter), GFP_KERNEL);
>>> + if (!h_adapter)
>>> + return -ENOMEM;
>>> +
>>> + h_adapter->priv =3D priv;
>>> + ops->set_bt_context(priv, h_adapter);
>>> + h_adapter->proto_ops =3D ops;
>>> +
>>> + hdev =3D hci_alloc_dev();
>>> + if (!hdev) {
>>> + BT_ERR("Failed to alloc HCI device");
>>> + goto err;
>>> + }
>>> +
>>> + h_adapter->hdev =3D hdev;
>>> +
>>> + if (ops->get_host_intf(priv) =3D=3D RSI_HOST_INTF_SDIO)
>>> + hdev->bus =3D HCI_SDIO;
>>> + else
>>> + hdev->bus =3D HCI_USB;
>>> +
>>> + hci_set_drvdata(hdev, h_adapter);
>>> + hdev->dev_type =3D HCI_PRIMARY;
>>> + hdev->open =3D rsi_hci_open;
>>> + hdev->close =3D rsi_hci_close;
>>> + hdev->flush =3D rsi_hci_flush;
>>> + hdev->send =3D rsi_hci_send_pkt;
>>
>> this doesn=E2=80=99t have to be in this patch, but if you support hdev->=
set_bdaddr, hdev->set_diag etc. that would be good to add in a follow up.
>>
>>> +
>>> + err =3D hci_register_dev(hdev);
>>> + if (err < 0) {
>>> + BT_ERR("HCI registration failed with errcode %d", err);
>>> + hci_free_dev(hdev);
>>> + goto err;
>>> + }
>>> +
>>> + return 0;
>>> +err:
>>> + h_adapter->hdev =3D NULL;
>>> + kfree(h_adapter);
>>> + return -EINVAL;
>>> +}
>>> +
>>> +static void rsi_hci_detach(void *priv)
>>> +{
>>> + struct rsi_hci_adapter *h_adapter =3D priv;
>>> + struct hci_dev *hdev;
>>> +
>>> + if (!h_adapter)
>>> + return;
>>> +
>>> + hdev =3D h_adapter->hdev;
>>> + if (hdev) {
>>> + hci_unregister_dev(hdev);
>>> + hci_free_dev(hdev);
>>> + h_adapter->hdev =3D NULL;
>>> + }
>>> +
>>> + kfree(h_adapter);
>>> +}
>>> +
>>> +const struct rsi_mod_ops rsi_bt_ops =3D {
>>> + .attach =3D rsi_hci_attach,
>>> + .detach =3D rsi_hci_detach,
>>> + .recv_pkt =3D rsi_hci_recv_pkt,
>>> +};
>>> +EXPORT_SYMBOL(rsi_bt_ops);
>>> +
>>> +static int rsi_91x_bt_module_init(void)
>>> +{
>>> + return 0;
>>> +}
>>> +
>>> +static void rsi_91x_bt_module_exit(void)
>>> +{
>>> + return;
>>> +}
>>> +
>>> +module_init(rsi_91x_bt_module_init);
>>> +module_exit(rsi_91x_bt_module_exit);
>>> +MODULE_AUTHOR("Redpine Signals Inc");
>>> +MODULE_DESCRIPTION("RSI BT driver");
>>> +MODULE_SUPPORTED_DEVICE("RSI-BT");
>>> +MODULE_LICENSE("Dual BSD/GPL=E2=80=9D);
>>
>> Acked-by: Marcel Holtmann <[email protected]>
>> Reviewed-by: Marcel Holtmann <[email protected]>
>>
>
> Thanks Marcel.
> I will wait for Kalle's review and suggestions.
> I will address your minor comments while preparing updated version
> based on Kalle's feedback.
>

This patch series has been pending for a while.
Please review and provide your feedback/comments.

Regards,
Amitkumar

2018-02-16 14:46:02

by Amitkumar Karwar

[permalink] [raw]
Subject: Re: [v5 4/8] rsi: add coex support

On Tue, Feb 13, 2018 at 9:07 PM, Kalle Valo <[email protected]> wrote:
> Amitkumar Karwar <[email protected]> writes:
>
>> On Thu, Feb 1, 2018 at 12:26 PM, Kalle Valo <[email protected]> wrote:
>>> Amitkumar Karwar <[email protected]> writes:
>>>
>>>> From: Prameela Rani Garnepudi <[email protected]>
>>>>
>>>> With BT support, driver has to handle two streams of data
>>>> (i.e. wlan and BT). Actual coex implementation is in firmware.
>>>> Coex module just schedule the packets to firmware by taking them
>>>> from the corresponding paths.
>>>>
>>>> Structures for module and protocol operations are introduced for
>>>> this purpose. Protocol operations structure is global structure
>>>> which can be shared among different modules. Initialization of
>>>> coex and operating mode values is moved to rsi_91x_init().
>>>>
>>>> Signed-off-by: Prameela Rani Garnepudi <[email protected]>
>>>> Signed-off-by: Siva Rebbagondla <[email protected]>
>>>> Signed-off-by: Amitkumar Karwar <[email protected]>
>>>
>>> [...]
>>>
>>>> @@ -270,6 +271,7 @@ struct rsi_common {
>>>> u8 obm_ant_sel_val;
>>>> int tx_power;
>>>> u8 ant_in_use;
>>>> + struct semaphore tx_bus_lock;
>>>
>>> Do you really need to use semaphore? I think nowadays the preference is
>>> to use something other than semaphores.
>>
>> We used semaphore here, as USB/SDIO bus write operations could be
>> blocking/waiting. I will check if spinlock suits here in follow up
>> patch. It will need some testing.
>
> I was more thinking about using a mutex.

Right. mutex would be better option. I will submit updated version
with this change

Regards,
Amitkumar Karwar

2018-02-13 15:37:51

by Kalle Valo

[permalink] [raw]
Subject: Re: [v5 4/8] rsi: add coex support

Amitkumar Karwar <[email protected]> writes:

> On Thu, Feb 1, 2018 at 12:26 PM, Kalle Valo <[email protected]> wrote:
>> Amitkumar Karwar <[email protected]> writes:
>>
>>> From: Prameela Rani Garnepudi <[email protected]>
>>>
>>> With BT support, driver has to handle two streams of data
>>> (i.e. wlan and BT). Actual coex implementation is in firmware.
>>> Coex module just schedule the packets to firmware by taking them
>>> from the corresponding paths.
>>>
>>> Structures for module and protocol operations are introduced for
>>> this purpose. Protocol operations structure is global structure
>>> which can be shared among different modules. Initialization of
>>> coex and operating mode values is moved to rsi_91x_init().
>>>
>>> Signed-off-by: Prameela Rani Garnepudi <[email protected]>
>>> Signed-off-by: Siva Rebbagondla <[email protected]>
>>> Signed-off-by: Amitkumar Karwar <[email protected]>
>>
>> [...]
>>
>>> @@ -270,6 +271,7 @@ struct rsi_common {
>>> u8 obm_ant_sel_val;
>>> int tx_power;
>>> u8 ant_in_use;
>>> + struct semaphore tx_bus_lock;
>>
>> Do you really need to use semaphore? I think nowadays the preference is
>> to use something other than semaphores.
>
> We used semaphore here, as USB/SDIO bus write operations could be
> blocking/waiting. I will check if spinlock suits here in follow up
> patch. It will need some testing.

I was more thinking about using a mutex.

--
Kalle Valo

2018-02-13 10:40:47

by Amitkumar Karwar

[permalink] [raw]
Subject: Re: [v5 4/8] rsi: add coex support

On Thu, Feb 1, 2018 at 12:38 PM, Kalle Valo <[email protected]> wrote:
> Amitkumar Karwar <[email protected]> writes:
>
>> From: Prameela Rani Garnepudi <[email protected]>
>>
>> With BT support, driver has to handle two streams of data
>> (i.e. wlan and BT). Actual coex implementation is in firmware.
>> Coex module just schedule the packets to firmware by taking them
>> from the corresponding paths.
>>
>> Structures for module and protocol operations are introduced for
>> this purpose. Protocol operations structure is global structure
>> which can be shared among different modules. Initialization of
>> coex and operating mode values is moved to rsi_91x_init().
>>
>> Signed-off-by: Prameela Rani Garnepudi <[email protected]>
>> Signed-off-by: Siva Rebbagondla <[email protected]>
>> Signed-off-by: Amitkumar Karwar <[email protected]>
>
> [...]
>
>> +static void rsi_coex_sched_tx_pkts(struct rsi_coex_ctrl_block *coex_cb)
>> +{
>> + enum rsi_coex_queues coex_q;
>> + struct sk_buff *skb;
>> +
>> + while (1) {
>> + coex_q = rsi_coex_determine_coex_q(coex_cb);
>> + rsi_dbg(INFO_ZONE, "queue = %d\n", coex_q);
>> +
>> + if (coex_q == RSI_COEX_Q_INVALID) {
>> + rsi_dbg(DATA_TX_ZONE, "No more pkt\n");
>> + break;
>> + }
>> +
>> + if (coex_q == RSI_COEX_Q_BT)
>> + skb = skb_dequeue(&coex_cb->coex_tx_qs[RSI_COEX_Q_BT]);
>> + }
>> +}
>
> Neverending loops are dangerous in kernel. Can you put a limit so that
> if there's a bug the loop will not run forever?

I will get rid of while(1) in v6 patch series.

Regards,
Amitkumar

2018-02-13 10:39:25

by Amitkumar Karwar

[permalink] [raw]
Subject: Re: [v5 4/8] rsi: add coex support

On Thu, Feb 1, 2018 at 12:26 PM, Kalle Valo <[email protected]> wrote:
> Amitkumar Karwar <[email protected]> writes:
>
>> From: Prameela Rani Garnepudi <[email protected]>
>>
>> With BT support, driver has to handle two streams of data
>> (i.e. wlan and BT). Actual coex implementation is in firmware.
>> Coex module just schedule the packets to firmware by taking them
>> from the corresponding paths.
>>
>> Structures for module and protocol operations are introduced for
>> this purpose. Protocol operations structure is global structure
>> which can be shared among different modules. Initialization of
>> coex and operating mode values is moved to rsi_91x_init().
>>
>> Signed-off-by: Prameela Rani Garnepudi <[email protected]>
>> Signed-off-by: Siva Rebbagondla <[email protected]>
>> Signed-off-by: Amitkumar Karwar <[email protected]>
>
> [...]
>
>> @@ -270,6 +271,7 @@ struct rsi_common {
>> u8 obm_ant_sel_val;
>> int tx_power;
>> u8 ant_in_use;
>> + struct semaphore tx_bus_lock;
>
> Do you really need to use semaphore? I think nowadays the preference is
> to use something other than semaphores.

We used semaphore here, as USB/SDIO bus write operations could be
blocking/waiting. I will check if spinlock suits here in follow up
patch. It will need some testing.

> Also calling it tx_bus_lock is IMHO misleading, tx_bus_sema would be
> nicer.

Sure. I will rename the variable

Regards,
Amitkumar

2018-02-13 10:22:30

by Amitkumar Karwar

[permalink] [raw]
Subject: Re: [v5 3/8] rsi: add header file rsi_header

On Thu, Feb 1, 2018 at 12:09 PM, Kalle Valo <[email protected]> wrote:
> Amitkumar Karwar <[email protected]> writes:
>
>> From: Prameela Rani Garnepudi <[email protected]>
>>
>> The common parameters used by wlan and bt modules are added
>> to a new header file "rsi_header.h" defined in '/include/linux'
>>
>> Signed-off-by: Prameela Rani Garnepudi <[email protected]>
>> Signed-off-by: Siva Rebbagondla <[email protected]>
>> Signed-off-by: Amitkumar Karwar <[email protected]>
>
> [...]
>
>> diff --git a/include/linux/rsi_header.h b/include/linux/rsi_header.h
>> new file mode 100644
>> index 0000000..16a447b
>> --- /dev/null
>> +++ b/include/linux/rsi_header.h
>> @@ -0,0 +1,34 @@
>> +/**
>> + * Copyright (c) 2017 Redpine Signals Inc.
>> + *
>> + * Permission to use, copy, modify, and/or distribute this software for any
>> + * purpose with or without fee is hereby granted, provided that the above
>> + * copyright notice and this permission notice appear in all copies.
>> + *
>> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
>> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
>> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
>> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
>> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
>> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
>> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
>> + */
>> +
>> +#ifndef __RSI_HEADER_H__
>> +#define __RSI_HEADER_H__
>> +
>> +/* HAL queue information */
>> +#define RSI_COEX_Q 0x0
>> +#define RSI_BT_Q 0x2
>> +#define RSI_WLAN_Q 0x3
>> +#define RSI_WIFI_MGMT_Q 0x4
>> +#define RSI_WIFI_DATA_Q 0x5
>> +#define RSI_BT_MGMT_Q 0x6
>> +#define RSI_BT_DATA_Q 0x7
>> +
>> +enum rsi_host_intf {
>> + RSI_HOST_INTF_SDIO = 0,
>> + RSI_HOST_INTF_USB
>> +};
>> +
>> +#endif
>
> The name of the header "rsi_header.h" looks odd. The ".h" prefix already
> tells that it's a header file, no need to repeat that in the filename.
> But also calling it "rsi.h" feels a bit weird, it's not really very
> specific. Would "rsi_91x.h" (from rsi_91x.ko) be any better?

Sure. Using rsi_91x.h makes sense.

>
> Also I'm not sure about the location (include/linux), is that really the
> correct place to have a header file shared by a wireless and bluetooth
> driver? Anyone know? Or would include/net be better?
>

include/net looks more appropriate. I will use it.

Regards,
Amitkumar

2018-02-13 10:20:44

by Amitkumar Karwar

[permalink] [raw]
Subject: Re: [v5 1/8] rsi: add rx control block to handle rx packets in USB

On Thu, Feb 1, 2018 at 12:00 PM, Kalle Valo <[email protected]> wrote:
> Amitkumar Karwar <[email protected]> writes:
>
>> From: Prameela Rani Garnepudi <[email protected]>
>>
>> Rx bluetooth endpoint shall be added in further patches. Rx control
>> block is introduced here to handle Rx packets properly. Separate
>> function is written to initialize the RX control blocks.
>>
>> Signed-off-by: Prameela Rani Garnepudi <[email protected]>
>> Signed-off-by: Siva Rebbagondla <[email protected]>
>> Signed-off-by: Amitkumar Karwar <[email protected]>
>
> [...]
>
>> +static int rsi_usb_init_rx(struct rsi_hw *adapter)
>> +{
>> + struct rsi_91x_usbdev *dev = (struct rsi_91x_usbdev *)adapter->rsi_dev;
>> + struct rx_usb_ctrl_block *rx_cb;
>> + u8 idx;
>> +
>> + for (idx = 0; idx < MAX_RX_URBS; idx++) {
>> + rx_cb = &dev->rx_cb[idx];
>> +
>> + rx_cb->rx_buffer = kzalloc(RSI_USB_BUF_SIZE * 2,
>> + GFP_KERNEL | GFP_DMA);
>
> Do you really need GFP_DMA? From the documentation:
>
> "GFP_DMA exists for historical reasons and should be avoided where
> possible."

Thanks for review. I will get rid of this flag,

Regards,
Amitkumar

2018-02-01 08:36:15

by Kalle Valo

[permalink] [raw]
Subject: Re: [v5 7/8] rsi: add module parameter operating mode

Marcel Holtmann <[email protected]> writes:

> Hi Kalle,
>
>>> Operating mode determines the support for other protocols.
>>> This is made as module parameter for better usage.
>>>
>>> Signed-off-by: Prameela Rani Garnepudi <[email protected]>
>>> Signed-off-by: Siva Rebbagondla <[email protected]>
>>> Signed-off-by: Amitkumar Karwar <[email protected]>
>>
>> [...]
>>
>>> +/* Default operating mode is wlan STA + BT */
>>> +static u16 dev_oper_mode = DEV_OPMODE_STA_BT_DUAL;
>>> +module_param(dev_oper_mode, ushort, 0444);
>>> +MODULE_PARM_DESC(dev_oper_mode,
>>> + "1[Wi-Fi], 4[BT], 8[BT LE], 5[Wi-Fi STA + BT classic]\n"
>>> + "9[Wi-Fi STA + BT LE], 13[Wi-Fi STA + BT classic + BT LE]\n"
>>> + "6[AP + BT classic], 14[AP + BT classic + BT LE]");
>>
>> I really wish that we have nl80211 interface for configuring btcoex. We
>> have been talking about that for years but nobody has implemented it :(
>
> the Bluetooth subsystem and Wireless subsystem can handle that
> perfectly between themselves. Involving userspace is utterly
> pointless. First step should be that the Wireless subsystem has an
> option to inform its actively used frequencies to the Bluetooth
> subsystem. It then could adjust AFP channel mapping.

Yeah, that would be much better.

--
Kalle Valo

2018-02-01 08:34:50

by Kalle Valo

[permalink] [raw]
Subject: Re: [v5 5/8] Bluetooth: btrsi: add new rsi bluetooth driver

Marcel Holtmann <[email protected]> writes:

>>> Acked-by: Marcel Holtmann <[email protected]>
>>> Reviewed-by: Marcel Holtmann <[email protected]>
>>
>> So how should we handle the logistics, should all these go via
>> wireless-drivers-next tree or what's the plan?
>
> I think they should go via wireless-drivers-next and once you send
> Dave a pull request, I pull back from net-next into bluetooth-next and
> we should be good. Any required fixup for Bluetooth we will do then
> via my tree.

Ok, that sounds good to me.

--
Kalle Valo

2018-02-01 08:20:39

by Marcel Holtmann

[permalink] [raw]
Subject: Re: [v5 7/8] rsi: add module parameter operating mode

Hi Kalle,

>> Operating mode determines the support for other protocols.
>> This is made as module parameter for better usage.
>>
>> Signed-off-by: Prameela Rani Garnepudi <[email protected]>
>> Signed-off-by: Siva Rebbagondla <[email protected]>
>> Signed-off-by: Amitkumar Karwar <[email protected]>
>
> [...]
>
>> +/* Default operating mode is wlan STA + BT */
>> +static u16 dev_oper_mode = DEV_OPMODE_STA_BT_DUAL;
>> +module_param(dev_oper_mode, ushort, 0444);
>> +MODULE_PARM_DESC(dev_oper_mode,
>> + "1[Wi-Fi], 4[BT], 8[BT LE], 5[Wi-Fi STA + BT classic]\n"
>> + "9[Wi-Fi STA + BT LE], 13[Wi-Fi STA + BT classic + BT LE]\n"
>> + "6[AP + BT classic], 14[AP + BT classic + BT LE]");
>
> I really wish that we have nl80211 interface for configuring btcoex. We
> have been talking about that for years but nobody has implemented it :(

the Bluetooth subsystem and Wireless subsystem can handle that perfectly between themselves. Involving userspace is utterly pointless. First step should be that the Wireless subsystem has an option to inform its actively used frequencies to the Bluetooth subsystem. It then could adjust AFP channel mapping.

Regards

Marcel

2018-02-01 08:16:14

by Marcel Holtmann

[permalink] [raw]
Subject: Re: [v5 5/8] Bluetooth: btrsi: add new rsi bluetooth driver

Hi Kalle,

>>> Redpine bluetooth driver is a thin driver which depends on
>>> 'rsi_91x' driver for transmitting and receiving packets
>>> to/from device. It creates hci interface when attach() is
>>> called from 'rsi_91x' module.
>>>
>>> Signed-off-by: Prameela Rani Garnepudi <[email protected]>
>>> Signed-off-by: Siva Rebbagondla <[email protected]>
>>> Signed-off-by: Amitkumar Karwar <[email protected]>
>
> [...]
>
>>> +module_init(rsi_91x_bt_module_init);
>>> +module_exit(rsi_91x_bt_module_exit);
>>> +MODULE_AUTHOR("Redpine Signals Inc");
>>> +MODULE_DESCRIPTION("RSI BT driver");
>>> +MODULE_SUPPORTED_DEVICE("RSI-BT");
>>> +MODULE_LICENSE("Dual BSD/GPL”);
>>
>> Acked-by: Marcel Holtmann <[email protected]>
>> Reviewed-by: Marcel Holtmann <[email protected]>
>
> So how should we handle the logistics, should all these go via
> wireless-drivers-next tree or what's the plan?

I think they should go via wireless-drivers-next and once you send Dave a pull request, I pull back from net-next into bluetooth-next and we should be good. Any required fixup for Bluetooth we will do then via my tree.

Regards

Marcel

2018-02-01 07:11:47

by Kalle Valo

[permalink] [raw]
Subject: Re: [v5 7/8] rsi: add module parameter operating mode

Amitkumar Karwar <[email protected]> writes:

> From: Prameela Rani Garnepudi <[email protected]>
>
> Operating mode determines the support for other protocols.
> This is made as module parameter for better usage.
>
> Signed-off-by: Prameela Rani Garnepudi <[email protected]>
> Signed-off-by: Siva Rebbagondla <[email protected]>
> Signed-off-by: Amitkumar Karwar <[email protected]>

[...]

> +/* Default operating mode is wlan STA + BT */
> +static u16 dev_oper_mode = DEV_OPMODE_STA_BT_DUAL;
> +module_param(dev_oper_mode, ushort, 0444);
> +MODULE_PARM_DESC(dev_oper_mode,
> + "1[Wi-Fi], 4[BT], 8[BT LE], 5[Wi-Fi STA + BT classic]\n"
> + "9[Wi-Fi STA + BT LE], 13[Wi-Fi STA + BT classic + BT LE]\n"
> + "6[AP + BT classic], 14[AP + BT classic + BT LE]");

I really wish that we have nl80211 interface for configuring btcoex. We
have been talking about that for years but nobody has implemented it :(

--
Kalle Valo

2018-02-01 07:10:31

by Kalle Valo

[permalink] [raw]
Subject: Re: [v5 6/8] rsi: handle BT traffic in driver

Amitkumar Karwar <[email protected]> writes:

> From: Siva Rebbagondla <[email protected]>
>
> BT frames are passed through coex and hal modules to BUS.
> After firmware is loaded, based on the operating mode CARD
> READY frame comes for each protocol. When BT card ready is
> received, BT attach is called.
> Protocol operations are exchanged between the modules
> at initialization time.
>
> Signed-off-by: Siva Rebbagondla <[email protected]>
> Signed-off-by: Prameela Rani Garnepudi <[email protected]>
> Signed-off-by: Amitkumar Karwar <[email protected]>
> ---
> v5: Same as v3, v4
> v3: bt_ops need not be present structure g_proto_ops. It is removed.
> v2: WLAN module depends on BT module. Updated in Kconfig
> ---
> drivers/net/wireless/rsi/Kconfig | 2 +-
> drivers/net/wireless/rsi/rsi_91x_coex.c | 4 ++-
> drivers/net/wireless/rsi/rsi_91x_core.c | 16 ++++++++----
> drivers/net/wireless/rsi/rsi_91x_hal.c | 39 +++++++++++++++++++++++++++++
> drivers/net/wireless/rsi/rsi_91x_main.c | 31 +++++++++++++++++++++++
> drivers/net/wireless/rsi/rsi_91x_sdio_ops.c | 1 +
> drivers/net/wireless/rsi/rsi_common.h | 1 +
> drivers/net/wireless/rsi/rsi_hal.h | 10 ++++++++
> drivers/net/wireless/rsi/rsi_main.h | 3 +++
> 9 files changed, 100 insertions(+), 7 deletions(-)
>
> diff --git a/drivers/net/wireless/rsi/Kconfig b/drivers/net/wireless/rsi/Kconfig
> index 7c5e4ca..ad72c80 100644
> --- a/drivers/net/wireless/rsi/Kconfig
> +++ b/drivers/net/wireless/rsi/Kconfig
> @@ -13,7 +13,7 @@ if WLAN_VENDOR_RSI
>
> config RSI_91X
> tristate "Redpine Signals Inc 91x WLAN driver support"
> - depends on MAC80211
> + depends on MAC80211 && BT_RSI

I think this is evil, now the wlan driver cannot be enabled unless the
bluetooth driver is enabled. And if I'm understanding correctly it won't
even show up in the menuconfig. A much nicer approach would be that
btcoex is just disabled in the wlan driver if BT_RSI is disabled.

--
Kalle Valo

2018-02-01 07:08:00

by Kalle Valo

[permalink] [raw]
Subject: Re: [v5 4/8] rsi: add coex support

Amitkumar Karwar <[email protected]> writes:

> From: Prameela Rani Garnepudi <[email protected]>
>
> With BT support, driver has to handle two streams of data
> (i.e. wlan and BT). Actual coex implementation is in firmware.
> Coex module just schedule the packets to firmware by taking them
> from the corresponding paths.
>
> Structures for module and protocol operations are introduced for
> this purpose. Protocol operations structure is global structure
> which can be shared among different modules. Initialization of
> coex and operating mode values is moved to rsi_91x_init().
>
> Signed-off-by: Prameela Rani Garnepudi <[email protected]>
> Signed-off-by: Siva Rebbagondla <[email protected]>
> Signed-off-by: Amitkumar Karwar <[email protected]>

[...]

> +static void rsi_coex_sched_tx_pkts(struct rsi_coex_ctrl_block *coex_cb)
> +{
> + enum rsi_coex_queues coex_q;
> + struct sk_buff *skb;
> +
> + while (1) {
> + coex_q = rsi_coex_determine_coex_q(coex_cb);
> + rsi_dbg(INFO_ZONE, "queue = %d\n", coex_q);
> +
> + if (coex_q == RSI_COEX_Q_INVALID) {
> + rsi_dbg(DATA_TX_ZONE, "No more pkt\n");
> + break;
> + }
> +
> + if (coex_q == RSI_COEX_Q_BT)
> + skb = skb_dequeue(&coex_cb->coex_tx_qs[RSI_COEX_Q_BT]);
> + }
> +}

Neverending loops are dangerous in kernel. Can you put a limit so that
if there's a bug the loop will not run forever?

--
Kalle Valo

2018-02-01 06:58:57

by Kalle Valo

[permalink] [raw]
Subject: Re: [v5 5/8] Bluetooth: btrsi: add new rsi bluetooth driver

Marcel Holtmann <[email protected]> writes:

>> Redpine bluetooth driver is a thin driver which depends on
>> 'rsi_91x' driver for transmitting and receiving packets
>> to/from device. It creates hci interface when attach() is
>> called from 'rsi_91x' module.
>>=20
>> Signed-off-by: Prameela Rani Garnepudi <[email protected]>
>> Signed-off-by: Siva Rebbagondla <[email protected]>
>> Signed-off-by: Amitkumar Karwar <[email protected]>

[...]

>> +module_init(rsi_91x_bt_module_init);
>> +module_exit(rsi_91x_bt_module_exit);
>> +MODULE_AUTHOR("Redpine Signals Inc");
>> +MODULE_DESCRIPTION("RSI BT driver");
>> +MODULE_SUPPORTED_DEVICE("RSI-BT");
>> +MODULE_LICENSE("Dual BSD/GPL=E2=80=9D);
>
> Acked-by: Marcel Holtmann <[email protected]>
> Reviewed-by: Marcel Holtmann <[email protected]>

So how should we handle the logistics, should all these go via
wireless-drivers-next tree or what's the plan?

--=20
Kalle Valo

2018-02-01 06:56:14

by Kalle Valo

[permalink] [raw]
Subject: Re: [v5 4/8] rsi: add coex support

Amitkumar Karwar <[email protected]> writes:

> From: Prameela Rani Garnepudi <[email protected]>
>
> With BT support, driver has to handle two streams of data
> (i.e. wlan and BT). Actual coex implementation is in firmware.
> Coex module just schedule the packets to firmware by taking them
> from the corresponding paths.
>
> Structures for module and protocol operations are introduced for
> this purpose. Protocol operations structure is global structure
> which can be shared among different modules. Initialization of
> coex and operating mode values is moved to rsi_91x_init().
>
> Signed-off-by: Prameela Rani Garnepudi <[email protected]>
> Signed-off-by: Siva Rebbagondla <[email protected]>
> Signed-off-by: Amitkumar Karwar <[email protected]>

[...]

> @@ -270,6 +271,7 @@ struct rsi_common {
> u8 obm_ant_sel_val;
> int tx_power;
> u8 ant_in_use;
> + struct semaphore tx_bus_lock;

Do you really need to use semaphore? I think nowadays the preference is
to use something other than semaphores.

Also calling it tx_bus_lock is IMHO misleading, tx_bus_sema would be
nicer.

--
Kalle Valo

2018-02-01 06:39:09

by Kalle Valo

[permalink] [raw]
Subject: Re: [v5 3/8] rsi: add header file rsi_header

Amitkumar Karwar <[email protected]> writes:

> From: Prameela Rani Garnepudi <[email protected]>
>
> The common parameters used by wlan and bt modules are added
> to a new header file "rsi_header.h" defined in '/include/linux'
>
> Signed-off-by: Prameela Rani Garnepudi <[email protected]>
> Signed-off-by: Siva Rebbagondla <[email protected]>
> Signed-off-by: Amitkumar Karwar <[email protected]>

[...]

> diff --git a/include/linux/rsi_header.h b/include/linux/rsi_header.h
> new file mode 100644
> index 0000000..16a447b
> --- /dev/null
> +++ b/include/linux/rsi_header.h
> @@ -0,0 +1,34 @@
> +/**
> + * Copyright (c) 2017 Redpine Signals Inc.
> + *
> + * Permission to use, copy, modify, and/or distribute this software for any
> + * purpose with or without fee is hereby granted, provided that the above
> + * copyright notice and this permission notice appear in all copies.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> + */
> +
> +#ifndef __RSI_HEADER_H__
> +#define __RSI_HEADER_H__
> +
> +/* HAL queue information */
> +#define RSI_COEX_Q 0x0
> +#define RSI_BT_Q 0x2
> +#define RSI_WLAN_Q 0x3
> +#define RSI_WIFI_MGMT_Q 0x4
> +#define RSI_WIFI_DATA_Q 0x5
> +#define RSI_BT_MGMT_Q 0x6
> +#define RSI_BT_DATA_Q 0x7
> +
> +enum rsi_host_intf {
> + RSI_HOST_INTF_SDIO = 0,
> + RSI_HOST_INTF_USB
> +};
> +
> +#endif

The name of the header "rsi_header.h" looks odd. The ".h" prefix already
tells that it's a header file, no need to repeat that in the filename.
But also calling it "rsi.h" feels a bit weird, it's not really very
specific. Would "rsi_91x.h" (from rsi_91x.ko) be any better?

Also I'm not sure about the location (include/linux), is that really the
correct place to have a header file shared by a wireless and bluetooth
driver? Anyone know? Or would include/net be better?

--
Kalle Valo

2018-02-01 06:30:09

by Kalle Valo

[permalink] [raw]
Subject: Re: [v5 1/8] rsi: add rx control block to handle rx packets in USB

Amitkumar Karwar <[email protected]> writes:

> From: Prameela Rani Garnepudi <[email protected]>
>
> Rx bluetooth endpoint shall be added in further patches. Rx control
> block is introduced here to handle Rx packets properly. Separate
> function is written to initialize the RX control blocks.
>
> Signed-off-by: Prameela Rani Garnepudi <[email protected]>
> Signed-off-by: Siva Rebbagondla <[email protected]>
> Signed-off-by: Amitkumar Karwar <[email protected]>

[...]

> +static int rsi_usb_init_rx(struct rsi_hw *adapter)
> +{
> + struct rsi_91x_usbdev *dev = (struct rsi_91x_usbdev *)adapter->rsi_dev;
> + struct rx_usb_ctrl_block *rx_cb;
> + u8 idx;
> +
> + for (idx = 0; idx < MAX_RX_URBS; idx++) {
> + rx_cb = &dev->rx_cb[idx];
> +
> + rx_cb->rx_buffer = kzalloc(RSI_USB_BUF_SIZE * 2,
> + GFP_KERNEL | GFP_DMA);

Do you really need GFP_DMA? From the documentation:

"GFP_DMA exists for historical reasons and should be avoided where
possible."

--
Kalle Valo