2009-10-21 16:41:40

by David Vrabel

[permalink] [raw]
Subject: [PATCH] bluetooth: don't DMA to stack in btsdio driver

sdio_read() may use DMA so read the Type-A header into a kmalloc'd
buffer instead of an on-stack buffer (which results in a DMA API
warning).

Signed-off-by: David Vrabel <[email protected]>
---
drivers/bluetooth/btsdio.c | 34 +++++++++++++++++++++-------------
1 files changed, 21 insertions(+), 13 deletions(-)

diff --git a/drivers/bluetooth/btsdio.c b/drivers/bluetooth/btsdio.c
index 7e29827..70468a2 100644
--- a/drivers/bluetooth/btsdio.c
+++ b/drivers/bluetooth/btsdio.c
@@ -54,6 +54,7 @@ MODULE_DEVICE_TABLE(sdio, btsdio_table);
struct btsdio_data {
struct hci_dev *hdev;
struct sdio_func *func;
+ u8 *hdr_buf;

struct work_struct work;

@@ -122,7 +123,7 @@ static void btsdio_work(struct work_struct *work)

static int btsdio_rx_packet(struct btsdio_data *data)
{
- u8 hdr[4] __attribute__ ((aligned(4)));
+ u8 *hdr = data->hdr_buf;
struct sk_buff *skb;
int err, len;

@@ -299,9 +300,9 @@ static int btsdio_probe(struct sdio_func *func,
const struct sdio_device_id *id)
{
struct btsdio_data *data;
- struct hci_dev *hdev;
+ struct hci_dev *hdev = NULL;
struct sdio_func_tuple *tuple = func->tuples;
- int err;
+ int err = -ENOMEM;

BT_DBG("func %p id %p class 0x%04x", func, id, func->class);

@@ -312,7 +313,11 @@ static int btsdio_probe(struct sdio_func *func,

data = kzalloc(sizeof(*data), GFP_KERNEL);
if (!data)
- return -ENOMEM;
+ goto error;
+
+ data->hdr_buf = kmalloc(4, GFP_KERNEL);
+ if (!data->hdr_buf)
+ goto error;

data->func = func;

@@ -321,10 +326,8 @@ static int btsdio_probe(struct sdio_func *func,
skb_queue_head_init(&data->txq);

hdev = hci_alloc_dev();
- if (!hdev) {
- kfree(data);
- return -ENOMEM;
- }
+ if (!hdev)
+ goto error;

hdev->type = HCI_SDIO;
hdev->driver_data = data;
@@ -342,15 +345,20 @@ static int btsdio_probe(struct sdio_func *func,
hdev->owner = THIS_MODULE;

err = hci_register_dev(hdev);
- if (err < 0) {
- hci_free_dev(hdev);
- kfree(data);
- return err;
- }
+ if (err < 0)
+ goto error;

sdio_set_drvdata(func, data);

return 0;
+error:
+ if (data) {
+ if (hdev)
+ hci_free_dev(hdev);
+ kfree(data->hdr_buf);
+ kfree(data);
+ }
+ return err;
}

static void btsdio_remove(struct sdio_func *func)
--
1.6.3.3


2009-10-27 14:28:31

by David Vrabel

[permalink] [raw]
Subject: [PATCH] bluetooth: don't DMA to stack in btsdio driver

sdio_read() may use DMA so read the Type-A header into a kmalloc'd
buffer instead of an on-stack buffer (which results in a DMA API
warning).

Signed-off-by: David Vrabel <[email protected]>
---
Apply this instead, it frees the header buffer.

David

drivers/bluetooth/btsdio.c | 35 ++++++++++++++++++++++-------------
1 files changed, 22 insertions(+), 13 deletions(-)

diff --git a/drivers/bluetooth/btsdio.c b/drivers/bluetooth/btsdio.c
index 7e29827..59d0d3b 100644
--- a/drivers/bluetooth/btsdio.c
+++ b/drivers/bluetooth/btsdio.c
@@ -54,6 +54,7 @@ MODULE_DEVICE_TABLE(sdio, btsdio_table);
struct btsdio_data {
struct hci_dev *hdev;
struct sdio_func *func;
+ u8 *hdr_buf;

struct work_struct work;

@@ -122,7 +123,7 @@ static void btsdio_work(struct work_struct *work)

static int btsdio_rx_packet(struct btsdio_data *data)
{
- u8 hdr[4] __attribute__ ((aligned(4)));
+ u8 *hdr = data->hdr_buf;
struct sk_buff *skb;
int err, len;

@@ -292,6 +293,7 @@ static void btsdio_destruct(struct hci_dev *hdev)

BT_DBG("%s", hdev->name);

+ kfree(data->hdr_buf);
kfree(data);
}

@@ -299,9 +301,9 @@ static int btsdio_probe(struct sdio_func *func,
const struct sdio_device_id *id)
{
struct btsdio_data *data;
- struct hci_dev *hdev;
+ struct hci_dev *hdev = NULL;
struct sdio_func_tuple *tuple = func->tuples;
- int err;
+ int err = -ENOMEM;

BT_DBG("func %p id %p class 0x%04x", func, id, func->class);

@@ -312,7 +314,11 @@ static int btsdio_probe(struct sdio_func *func,

data = kzalloc(sizeof(*data), GFP_KERNEL);
if (!data)
- return -ENOMEM;
+ goto error;
+
+ data->hdr_buf = kmalloc(4, GFP_KERNEL);
+ if (!data->hdr_buf)
+ goto error;

data->func = func;

@@ -321,10 +327,8 @@ static int btsdio_probe(struct sdio_func *func,
skb_queue_head_init(&data->txq);

hdev = hci_alloc_dev();
- if (!hdev) {
- kfree(data);
- return -ENOMEM;
- }
+ if (!hdev)
+ goto error;

hdev->type = HCI_SDIO;
hdev->driver_data = data;
@@ -342,15 +346,20 @@ static int btsdio_probe(struct sdio_func *func,
hdev->owner = THIS_MODULE;

err = hci_register_dev(hdev);
- if (err < 0) {
- hci_free_dev(hdev);
- kfree(data);
- return err;
- }
+ if (err < 0)
+ goto error;

sdio_set_drvdata(func, data);

return 0;
+error:
+ if (data) {
+ if (hdev)
+ hci_free_dev(hdev);
+ kfree(data->hdr_buf);
+ kfree(data);
+ }
+ return err;
}

static void btsdio_remove(struct sdio_func *func)
--
1.6.3.3

2009-11-04 12:22:40

by David Vrabel

[permalink] [raw]
Subject: Re: [PATCH] bluetooth: don't DMA to stack in btsdio driver

Tomas Winkler wrote:
>
>> @@ -299,9 +301,9 @@ static int btsdio_probe(struct sdio_func *func,
>> const struct sdio_device_id *id)
>> {
>> struct btsdio_data *data;
>> - struct hci_dev *hdev;
>> + struct hci_dev *hdev = NULL;
>
> This kind of assignments prevent useful warning from compiler, maybe
> it's better to stage
> the error bailout.

I think that having to have an error_foo label for each error makes
writing error handling harder not easier. I'm not inclined to change
this, particular as I can't think of any "useful warnings" are prevented.

>> struct sdio_func_tuple *tuple = func->tuples;
>> - int err;
>> + int err = -ENOMEM;
> You are assuming no other code between 2 allocations, it's seems to
> me error prone.

Yeah, it's probably best to set err at the source of the error. This
code is so short it doesn't make any real practical difference. I'll
keep it in mind for the future though.

David
--
David Vrabel, Senior Software Engineer, Drivers
CSR, Churchill House, Cambridge Business Park, Tel: +44 (0)1223 692562
Cowley Road, Cambridge, CB4 0WZ http://www.csr.com/


Member of the CSR plc group of companies. CSR plc registered in England and Wales, registered number 4187346, registered office Churchill House, Cambridge Business Park, Cowley Road, Cambridge, CB4 0WZ, United Kingdom

2009-11-04 10:56:46

by Tomas Winkler

[permalink] [raw]
Subject: Re: [PATCH] bluetooth: don't DMA to stack in btsdio driver

On Tue, Oct 27, 2009 at 4:28 PM, David Vrabel <[email protected]> wrote:
> sdio_read() may use DMA so read the Type-A header into a kmalloc'd
> buffer instead of an on-stack buffer (which results in a DMA API
> warning).
>
> Signed-off-by: David Vrabel <[email protected]>
> ---
> Apply this instead, it frees the header buffer.
>
> David
>
> =C2=A0drivers/bluetooth/btsdio.c | =C2=A0 35 ++++++++++++++++++++++------=
-------
> =C2=A01 files changed, 22 insertions(+), 13 deletions(-)
>
> diff --git a/drivers/bluetooth/btsdio.c b/drivers/bluetooth/btsdio.c
> index 7e29827..59d0d3b 100644
> --- a/drivers/bluetooth/btsdio.c
> +++ b/drivers/bluetooth/btsdio.c
> @@ -54,6 +54,7 @@ MODULE_DEVICE_TABLE(sdio, btsdio_table);
> =C2=A0struct btsdio_data {
> =C2=A0 =C2=A0 =C2=A0 =C2=A0struct hci_dev =C2=A0 *hdev;
> =C2=A0 =C2=A0 =C2=A0 =C2=A0struct sdio_func *func;
> + =C2=A0 =C2=A0 =C2=A0 u8 *hdr_buf;
>
> =C2=A0 =C2=A0 =C2=A0 =C2=A0struct work_struct work;
>
> @@ -122,7 +123,7 @@ static void btsdio_work(struct work_struct *work)
>
> =C2=A0static int btsdio_rx_packet(struct btsdio_data *data)
> =C2=A0{
> - =C2=A0 =C2=A0 =C2=A0 u8 hdr[4] __attribute__ ((aligned(4)));
> + =C2=A0 =C2=A0 =C2=A0 u8 *hdr =3D data->hdr_buf;
> =C2=A0 =C2=A0 =C2=A0 =C2=A0struct sk_buff *skb;
> =C2=A0 =C2=A0 =C2=A0 =C2=A0int err, len;
>
> @@ -292,6 +293,7 @@ static void btsdio_destruct(struct hci_dev *hdev)
>
> =C2=A0 =C2=A0 =C2=A0 =C2=A0BT_DBG("%s", hdev->name);
>
> + =C2=A0 =C2=A0 =C2=A0 kfree(data->hdr_buf);
> =C2=A0 =C2=A0 =C2=A0 =C2=A0kfree(data);
> =C2=A0}
>
> @@ -299,9 +301,9 @@ static int btsdio_probe(struct sdio_func *func,
> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0const struct sdio_device_id *id)
> =C2=A0{
> =C2=A0 =C2=A0 =C2=A0 =C2=A0struct btsdio_data *data;
> - =C2=A0 =C2=A0 =C2=A0 struct hci_dev *hdev;
> + =C2=A0 =C2=A0 =C2=A0 struct hci_dev *hdev =3D NULL;

This kind of assignments prevent useful warning from compiler, maybe
it's better to stage
the error bailout.

> =C2=A0 =C2=A0 =C2=A0 =C2=A0struct sdio_func_tuple *tuple =3D func->tuples=
;
> - =C2=A0 =C2=A0 =C2=A0 int err;
> + =C2=A0 =C2=A0 =C2=A0 int err =3D -ENOMEM;
You are assuming no other code between 2 allocations, it's seems to
me error prone.
>

Thanks
Tomas