Merge branch 'net-Fix-on-stack-USB-buffers'
Ben Hutchings says: ==================== net: Fix on-stack USB buffers Allocating USB buffers on the stack is not portable, and no longer works on x86_64 (with VMAP_STACK enabled as per default). This series fixes all the instances I could find where USB networking drivers do that. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
6a413e269b
|
@ -776,7 +776,7 @@ static int catc_probe(struct usb_interface *intf, const struct usb_device_id *id
|
||||||
struct net_device *netdev;
|
struct net_device *netdev;
|
||||||
struct catc *catc;
|
struct catc *catc;
|
||||||
u8 broadcast[ETH_ALEN];
|
u8 broadcast[ETH_ALEN];
|
||||||
int i, pktsz;
|
int pktsz, ret;
|
||||||
|
|
||||||
if (usb_set_interface(usbdev,
|
if (usb_set_interface(usbdev,
|
||||||
intf->altsetting->desc.bInterfaceNumber, 1)) {
|
intf->altsetting->desc.bInterfaceNumber, 1)) {
|
||||||
|
@ -811,12 +811,8 @@ static int catc_probe(struct usb_interface *intf, const struct usb_device_id *id
|
||||||
if ((!catc->ctrl_urb) || (!catc->tx_urb) ||
|
if ((!catc->ctrl_urb) || (!catc->tx_urb) ||
|
||||||
(!catc->rx_urb) || (!catc->irq_urb)) {
|
(!catc->rx_urb) || (!catc->irq_urb)) {
|
||||||
dev_err(&intf->dev, "No free urbs available.\n");
|
dev_err(&intf->dev, "No free urbs available.\n");
|
||||||
usb_free_urb(catc->ctrl_urb);
|
ret = -ENOMEM;
|
||||||
usb_free_urb(catc->tx_urb);
|
goto fail_free;
|
||||||
usb_free_urb(catc->rx_urb);
|
|
||||||
usb_free_urb(catc->irq_urb);
|
|
||||||
free_netdev(netdev);
|
|
||||||
return -ENOMEM;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The F5U011 has the same vendor/product as the netmate but a device version of 0x130 */
|
/* The F5U011 has the same vendor/product as the netmate but a device version of 0x130 */
|
||||||
|
@ -844,15 +840,24 @@ static int catc_probe(struct usb_interface *intf, const struct usb_device_id *id
|
||||||
catc->irq_buf, 2, catc_irq_done, catc, 1);
|
catc->irq_buf, 2, catc_irq_done, catc, 1);
|
||||||
|
|
||||||
if (!catc->is_f5u011) {
|
if (!catc->is_f5u011) {
|
||||||
|
u32 *buf;
|
||||||
|
int i;
|
||||||
|
|
||||||
dev_dbg(dev, "Checking memory size\n");
|
dev_dbg(dev, "Checking memory size\n");
|
||||||
|
|
||||||
i = 0x12345678;
|
buf = kmalloc(4, GFP_KERNEL);
|
||||||
catc_write_mem(catc, 0x7a80, &i, 4);
|
if (!buf) {
|
||||||
i = 0x87654321;
|
ret = -ENOMEM;
|
||||||
catc_write_mem(catc, 0xfa80, &i, 4);
|
goto fail_free;
|
||||||
catc_read_mem(catc, 0x7a80, &i, 4);
|
}
|
||||||
|
|
||||||
|
*buf = 0x12345678;
|
||||||
|
catc_write_mem(catc, 0x7a80, buf, 4);
|
||||||
|
*buf = 0x87654321;
|
||||||
|
catc_write_mem(catc, 0xfa80, buf, 4);
|
||||||
|
catc_read_mem(catc, 0x7a80, buf, 4);
|
||||||
|
|
||||||
switch (i) {
|
switch (*buf) {
|
||||||
case 0x12345678:
|
case 0x12345678:
|
||||||
catc_set_reg(catc, TxBufCount, 8);
|
catc_set_reg(catc, TxBufCount, 8);
|
||||||
catc_set_reg(catc, RxBufCount, 32);
|
catc_set_reg(catc, RxBufCount, 32);
|
||||||
|
@ -867,6 +872,8 @@ static int catc_probe(struct usb_interface *intf, const struct usb_device_id *id
|
||||||
dev_dbg(dev, "32k Memory\n");
|
dev_dbg(dev, "32k Memory\n");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
kfree(buf);
|
||||||
|
|
||||||
dev_dbg(dev, "Getting MAC from SEEROM.\n");
|
dev_dbg(dev, "Getting MAC from SEEROM.\n");
|
||||||
|
|
||||||
|
@ -913,16 +920,21 @@ static int catc_probe(struct usb_interface *intf, const struct usb_device_id *id
|
||||||
usb_set_intfdata(intf, catc);
|
usb_set_intfdata(intf, catc);
|
||||||
|
|
||||||
SET_NETDEV_DEV(netdev, &intf->dev);
|
SET_NETDEV_DEV(netdev, &intf->dev);
|
||||||
if (register_netdev(netdev) != 0) {
|
ret = register_netdev(netdev);
|
||||||
usb_set_intfdata(intf, NULL);
|
if (ret)
|
||||||
usb_free_urb(catc->ctrl_urb);
|
goto fail_clear_intfdata;
|
||||||
usb_free_urb(catc->tx_urb);
|
|
||||||
usb_free_urb(catc->rx_urb);
|
|
||||||
usb_free_urb(catc->irq_urb);
|
|
||||||
free_netdev(netdev);
|
|
||||||
return -EIO;
|
|
||||||
}
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
fail_clear_intfdata:
|
||||||
|
usb_set_intfdata(intf, NULL);
|
||||||
|
fail_free:
|
||||||
|
usb_free_urb(catc->ctrl_urb);
|
||||||
|
usb_free_urb(catc->tx_urb);
|
||||||
|
usb_free_urb(catc->rx_urb);
|
||||||
|
usb_free_urb(catc->irq_urb);
|
||||||
|
free_netdev(netdev);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void catc_disconnect(struct usb_interface *intf)
|
static void catc_disconnect(struct usb_interface *intf)
|
||||||
|
|
|
@ -126,40 +126,61 @@ static void async_ctrl_callback(struct urb *urb)
|
||||||
|
|
||||||
static int get_registers(pegasus_t *pegasus, __u16 indx, __u16 size, void *data)
|
static int get_registers(pegasus_t *pegasus, __u16 indx, __u16 size, void *data)
|
||||||
{
|
{
|
||||||
|
u8 *buf;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
buf = kmalloc(size, GFP_NOIO);
|
||||||
|
if (!buf)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
ret = usb_control_msg(pegasus->usb, usb_rcvctrlpipe(pegasus->usb, 0),
|
ret = usb_control_msg(pegasus->usb, usb_rcvctrlpipe(pegasus->usb, 0),
|
||||||
PEGASUS_REQ_GET_REGS, PEGASUS_REQT_READ, 0,
|
PEGASUS_REQ_GET_REGS, PEGASUS_REQT_READ, 0,
|
||||||
indx, data, size, 1000);
|
indx, buf, size, 1000);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
netif_dbg(pegasus, drv, pegasus->net,
|
netif_dbg(pegasus, drv, pegasus->net,
|
||||||
"%s returned %d\n", __func__, ret);
|
"%s returned %d\n", __func__, ret);
|
||||||
|
else if (ret <= size)
|
||||||
|
memcpy(data, buf, ret);
|
||||||
|
kfree(buf);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int set_registers(pegasus_t *pegasus, __u16 indx, __u16 size, void *data)
|
static int set_registers(pegasus_t *pegasus, __u16 indx, __u16 size,
|
||||||
|
const void *data)
|
||||||
{
|
{
|
||||||
|
u8 *buf;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
buf = kmemdup(data, size, GFP_NOIO);
|
||||||
|
if (!buf)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
ret = usb_control_msg(pegasus->usb, usb_sndctrlpipe(pegasus->usb, 0),
|
ret = usb_control_msg(pegasus->usb, usb_sndctrlpipe(pegasus->usb, 0),
|
||||||
PEGASUS_REQ_SET_REGS, PEGASUS_REQT_WRITE, 0,
|
PEGASUS_REQ_SET_REGS, PEGASUS_REQT_WRITE, 0,
|
||||||
indx, data, size, 100);
|
indx, buf, size, 100);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
netif_dbg(pegasus, drv, pegasus->net,
|
netif_dbg(pegasus, drv, pegasus->net,
|
||||||
"%s returned %d\n", __func__, ret);
|
"%s returned %d\n", __func__, ret);
|
||||||
|
kfree(buf);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int set_register(pegasus_t *pegasus, __u16 indx, __u8 data)
|
static int set_register(pegasus_t *pegasus, __u16 indx, __u8 data)
|
||||||
{
|
{
|
||||||
|
u8 *buf;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
buf = kmemdup(&data, 1, GFP_NOIO);
|
||||||
|
if (!buf)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
ret = usb_control_msg(pegasus->usb, usb_sndctrlpipe(pegasus->usb, 0),
|
ret = usb_control_msg(pegasus->usb, usb_sndctrlpipe(pegasus->usb, 0),
|
||||||
PEGASUS_REQ_SET_REG, PEGASUS_REQT_WRITE, data,
|
PEGASUS_REQ_SET_REG, PEGASUS_REQT_WRITE, data,
|
||||||
indx, &data, 1, 1000);
|
indx, buf, 1, 1000);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
netif_dbg(pegasus, drv, pegasus->net,
|
netif_dbg(pegasus, drv, pegasus->net,
|
||||||
"%s returned %d\n", __func__, ret);
|
"%s returned %d\n", __func__, ret);
|
||||||
|
kfree(buf);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -155,16 +155,36 @@ static const char driver_name [] = "rtl8150";
|
||||||
*/
|
*/
|
||||||
static int get_registers(rtl8150_t * dev, u16 indx, u16 size, void *data)
|
static int get_registers(rtl8150_t * dev, u16 indx, u16 size, void *data)
|
||||||
{
|
{
|
||||||
return usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0),
|
void *buf;
|
||||||
RTL8150_REQ_GET_REGS, RTL8150_REQT_READ,
|
int ret;
|
||||||
indx, 0, data, size, 500);
|
|
||||||
|
buf = kmalloc(size, GFP_NOIO);
|
||||||
|
if (!buf)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
ret = usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0),
|
||||||
|
RTL8150_REQ_GET_REGS, RTL8150_REQT_READ,
|
||||||
|
indx, 0, buf, size, 500);
|
||||||
|
if (ret > 0 && ret <= size)
|
||||||
|
memcpy(data, buf, ret);
|
||||||
|
kfree(buf);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int set_registers(rtl8150_t * dev, u16 indx, u16 size, void *data)
|
static int set_registers(rtl8150_t * dev, u16 indx, u16 size, const void *data)
|
||||||
{
|
{
|
||||||
return usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0),
|
void *buf;
|
||||||
RTL8150_REQ_SET_REGS, RTL8150_REQT_WRITE,
|
int ret;
|
||||||
indx, 0, data, size, 500);
|
|
||||||
|
buf = kmemdup(data, size, GFP_NOIO);
|
||||||
|
if (!buf)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
ret = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0),
|
||||||
|
RTL8150_REQ_SET_REGS, RTL8150_REQT_WRITE,
|
||||||
|
indx, 0, buf, size, 500);
|
||||||
|
kfree(buf);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void async_set_reg_cb(struct urb *urb)
|
static void async_set_reg_cb(struct urb *urb)
|
||||||
|
|
Loading…
Reference in New Issue