* [PATCH 1/2] net/usb: pegasus: do not use stack for URB buffers
@ 2013-08-07 13:33 Jussi Kivilinna
2013-08-07 13:33 ` [PATCH 2/2] net/usb: pegasus: allocate URB transfer_buffers as separate buffers Jussi Kivilinna
0 siblings, 1 reply; 2+ messages in thread
From: Jussi Kivilinna @ 2013-08-07 13:33 UTC (permalink / raw)
To: netdev; +Cc: Greg Kroah-Hartman, linux-usb, Petko Manolov, David S. Miller
Currently pegasus passes stack memory (which must not be used for DMA
transfers) as URB buffers with get_registers(), set_registers() and
set_register(). Apply fix inside these functions instead of changing every
call site.
Stack usage was introduced by recent commit 323b34963d11 "drivers: net: usb:
pegasus: fix control urb submission".
Patch is only compile tested.
Cc: <stable@vger.kernel.org>
Signed-off-by: Jussi Kivilinna <jussi.kivilinna@iki.fi>
---
drivers/net/usb/pegasus.c | 26 +++++++++++++++++++++++---
1 file changed, 23 insertions(+), 3 deletions(-)
diff --git a/drivers/net/usb/pegasus.c b/drivers/net/usb/pegasus.c
index 03e8a15..3bce862 100644
--- a/drivers/net/usb/pegasus.c
+++ b/drivers/net/usb/pegasus.c
@@ -127,39 +127,59 @@ static void async_ctrl_callback(struct urb *urb)
static int get_registers(pegasus_t *pegasus, __u16 indx, __u16 size, void *data)
{
int ret;
+ void *buf;
+
+ buf = kmalloc(size, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
ret = usb_control_msg(pegasus->usb, usb_rcvctrlpipe(pegasus->usb, 0),
PEGASUS_REQ_GET_REGS, PEGASUS_REQT_READ, 0,
- indx, data, size, 1000);
+ indx, buf, size, 1000);
if (ret < 0)
netif_dbg(pegasus, drv, pegasus->net,
"%s returned %d\n", __func__, ret);
+ else
+ memcpy(data, buf, ret); /* ret == bytes read (max == size) */
+ kfree(buf);
return ret;
}
static int set_registers(pegasus_t *pegasus, __u16 indx, __u16 size, void *data)
{
int ret;
+ void *buf;
+
+ buf = kmemdup(data, size, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
ret = usb_control_msg(pegasus->usb, usb_sndctrlpipe(pegasus->usb, 0),
PEGASUS_REQ_SET_REGS, PEGASUS_REQT_WRITE, 0,
- indx, data, size, 100);
+ indx, buf, size, 100);
if (ret < 0)
netif_dbg(pegasus, drv, pegasus->net,
"%s returned %d\n", __func__, ret);
+ kfree(buf);
return ret;
}
static int set_register(pegasus_t *pegasus, __u16 indx, __u8 data)
{
int ret;
+ void *buf;
+
+ buf = kmemdup(&data, 1, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
ret = usb_control_msg(pegasus->usb, usb_sndctrlpipe(pegasus->usb, 0),
PEGASUS_REQ_SET_REG, PEGASUS_REQT_WRITE, data,
- indx, &data, 1, 1000);
+ indx, buf, 1, 1000);
if (ret < 0)
netif_dbg(pegasus, drv, pegasus->net,
"%s returned %d\n", __func__, ret);
+ kfree(buf);
return ret;
}
^ permalink raw reply related [flat|nested] 2+ messages in thread
* [PATCH 2/2] net/usb: pegasus: allocate URB transfer_buffers as separate buffers
2013-08-07 13:33 [PATCH 1/2] net/usb: pegasus: do not use stack for URB buffers Jussi Kivilinna
@ 2013-08-07 13:33 ` Jussi Kivilinna
0 siblings, 0 replies; 2+ messages in thread
From: Jussi Kivilinna @ 2013-08-07 13:33 UTC (permalink / raw)
To: netdev; +Cc: Greg Kroah-Hartman, linux-usb, Petko Manolov, David S. Miller
URB transfer_buffers must not be allocated as part of larger structure
because DMA coherence issues.
Patch changes pegasus to allocate intr_buff and tx_buff members of
'struct pegasus' as separate buffers.
Patch is only compile tested.
Cc: <stable@vger.kernel.org>
Signed-off-by: Jussi Kivilinna <jussi.kivilinna@iki.fi>
---
drivers/net/usb/pegasus.c | 11 ++++++++++-
drivers/net/usb/pegasus.h | 6 ++++--
2 files changed, 14 insertions(+), 3 deletions(-)
diff --git a/drivers/net/usb/pegasus.c b/drivers/net/usb/pegasus.c
index 3bce862..b734702 100644
--- a/drivers/net/usb/pegasus.c
+++ b/drivers/net/usb/pegasus.c
@@ -854,7 +854,7 @@ static int pegasus_open(struct net_device *net)
usb_fill_int_urb(pegasus->intr_urb, pegasus->usb,
usb_rcvintpipe(pegasus->usb, 3),
- pegasus->intr_buff, sizeof(pegasus->intr_buff),
+ pegasus->intr_buff, PEGASUS_INTR_BUFLEN,
intr_callback, pegasus, pegasus->intr_interval);
if ((res = usb_submit_urb(pegasus->intr_urb, GFP_KERNEL))) {
if (res == -ENODEV)
@@ -1162,6 +1162,11 @@ static int pegasus_probe(struct usb_interface *intf,
pegasus = netdev_priv(net);
pegasus->dev_index = dev_index;
+ pegasus->intr_buff = kzalloc(PEGASUS_INTR_BUFLEN, GFP_KERNEL);
+ pegasus->tx_buff = kzalloc(PEGASUS_MTU, GFP_KERNEL);
+ if (!pegasus->intr_buff || !pegasus->tx_buff)
+ goto out1;
+
res = alloc_urbs(pegasus);
if (res < 0) {
dev_err(&intf->dev, "can't allocate %s\n", "urbs");
@@ -1223,6 +1228,8 @@ out3:
out2:
free_all_urbs(pegasus);
out1:
+ kfree(pegasus->tx_buff);
+ kfree(pegasus->intr_buff);
free_netdev(net);
out:
pegasus_dec_workqueue();
@@ -1248,6 +1255,8 @@ static void pegasus_disconnect(struct usb_interface *intf)
dev_kfree_skb(pegasus->rx_skb);
pegasus->rx_skb = NULL;
}
+ kfree(pegasus->tx_buff);
+ kfree(pegasus->intr_buff);
free_netdev(pegasus->net);
pegasus_dec_workqueue();
}
diff --git a/drivers/net/usb/pegasus.h b/drivers/net/usb/pegasus.h
index d156462..6469aed 100644
--- a/drivers/net/usb/pegasus.h
+++ b/drivers/net/usb/pegasus.h
@@ -55,6 +55,8 @@
#define PEGASUS_REQ_SET_REGS 0xf1
#define PEGASUS_REQ_SET_REG PEGASUS_REQ_SET_REGS
+#define PEGASUS_INTR_BUFLEN 8
+
enum pegasus_registers {
EthCtrl0 = 0,
EthCtrl1 = 1,
@@ -96,8 +98,8 @@ typedef struct pegasus {
struct urb *rx_urb, *tx_urb, *intr_urb;
struct sk_buff *rx_skb;
int chip;
- unsigned char intr_buff[8];
- __u8 tx_buff[PEGASUS_MTU];
+ unsigned char *intr_buff;
+ __u8 *tx_buff;
__u8 eth_regs[4];
__u8 phy;
__u8 gpio_res;
^ permalink raw reply related [flat|nested] 2+ messages in thread
end of thread, other threads:[~2013-08-07 13:33 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-08-07 13:33 [PATCH 1/2] net/usb: pegasus: do not use stack for URB buffers Jussi Kivilinna
2013-08-07 13:33 ` [PATCH 2/2] net/usb: pegasus: allocate URB transfer_buffers as separate buffers Jussi Kivilinna
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).