Commit a19c2619 authored by Sebastian Andrzej Siewior's avatar Sebastian Andrzej Siewior Committed by David S. Miller

net: usb: kaweth: Remove last user of kaweth_control()

kaweth_async_set_rx_mode() invokes kaweth_contol() and has two callers:

- kaweth_open() which is invoked from preemptible context
.
- kaweth_start_xmit() which holds a spinlock and has bottom halfs disabled.

If called from kaweth_start_xmit() kaweth_async_set_rx_mode() obviously
cannot block, which means it can't call kaweth_control(). This is detected
with an in_interrupt() check.

Replace the in_interrupt() check in kaweth_async_set_rx_mode() with an
argument which is set true by the caller if the context is safe to sleep,
otherwise false.

Now kaweth_control() is only called from preemptible context which means
there is no need for GFP_ATOMIC allocations anymore. Replace it with
usb_control_msg(). Cleanup the code a bit while at it.

Finally remove kaweth_control() since the last user is gone.
Signed-off-by: default avatarSebastian Andrzej Siewior <bigeasy@linutronix.de>
Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
Reviewed-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent af3563be
...@@ -103,10 +103,6 @@ static int kaweth_probe( ...@@ -103,10 +103,6 @@ static int kaweth_probe(
const struct usb_device_id *id /* from id_table */ const struct usb_device_id *id /* from id_table */
); );
static void kaweth_disconnect(struct usb_interface *intf); static void kaweth_disconnect(struct usb_interface *intf);
static int kaweth_internal_control_msg(struct usb_device *usb_dev,
unsigned int pipe,
struct usb_ctrlrequest *cmd, void *data,
int len, int timeout);
static int kaweth_suspend(struct usb_interface *intf, pm_message_t message); static int kaweth_suspend(struct usb_interface *intf, pm_message_t message);
static int kaweth_resume(struct usb_interface *intf); static int kaweth_resume(struct usb_interface *intf);
...@@ -235,48 +231,6 @@ struct kaweth_device ...@@ -235,48 +231,6 @@ struct kaweth_device
struct kaweth_ethernet_configuration configuration; struct kaweth_ethernet_configuration configuration;
}; };
/****************************************************************
* kaweth_control
****************************************************************/
static int kaweth_control(struct kaweth_device *kaweth,
unsigned int pipe,
__u8 request,
__u8 requesttype,
__u16 value,
__u16 index,
void *data,
__u16 size,
int timeout)
{
struct usb_ctrlrequest *dr;
int retval;
if(in_interrupt()) {
netdev_dbg(kaweth->net, "in_interrupt()\n");
return -EBUSY;
}
dr = kmalloc(sizeof(struct usb_ctrlrequest), GFP_ATOMIC);
if (!dr)
return -ENOMEM;
dr->bRequestType = requesttype;
dr->bRequest = request;
dr->wValue = cpu_to_le16(value);
dr->wIndex = cpu_to_le16(index);
dr->wLength = cpu_to_le16(size);
retval = kaweth_internal_control_msg(kaweth->dev,
pipe,
dr,
data,
size,
timeout);
kfree(dr);
return retval;
}
/**************************************************************** /****************************************************************
* kaweth_read_configuration * kaweth_read_configuration
****************************************************************/ ****************************************************************/
...@@ -531,7 +485,8 @@ static int kaweth_resubmit_rx_urb(struct kaweth_device *kaweth, ...@@ -531,7 +485,8 @@ static int kaweth_resubmit_rx_urb(struct kaweth_device *kaweth,
return result; return result;
} }
static void kaweth_async_set_rx_mode(struct kaweth_device *kaweth); static void kaweth_async_set_rx_mode(struct kaweth_device *kaweth,
bool may_sleep);
/**************************************************************** /****************************************************************
* kaweth_usb_receive * kaweth_usb_receive
...@@ -661,7 +616,7 @@ static int kaweth_open(struct net_device *net) ...@@ -661,7 +616,7 @@ static int kaweth_open(struct net_device *net)
netif_start_queue(net); netif_start_queue(net);
kaweth_async_set_rx_mode(kaweth); kaweth_async_set_rx_mode(kaweth, true);
return 0; return 0;
err_out: err_out:
...@@ -749,7 +704,7 @@ static netdev_tx_t kaweth_start_xmit(struct sk_buff *skb, ...@@ -749,7 +704,7 @@ static netdev_tx_t kaweth_start_xmit(struct sk_buff *skb,
spin_lock_irq(&kaweth->device_lock); spin_lock_irq(&kaweth->device_lock);
kaweth_async_set_rx_mode(kaweth); kaweth_async_set_rx_mode(kaweth, false);
netif_stop_queue(net); netif_stop_queue(net);
if (IS_BLOCKED(kaweth->status)) { if (IS_BLOCKED(kaweth->status)) {
goto skip; goto skip;
...@@ -826,36 +781,31 @@ static void kaweth_set_rx_mode(struct net_device *net) ...@@ -826,36 +781,31 @@ static void kaweth_set_rx_mode(struct net_device *net)
/**************************************************************** /****************************************************************
* kaweth_async_set_rx_mode * kaweth_async_set_rx_mode
****************************************************************/ ****************************************************************/
static void kaweth_async_set_rx_mode(struct kaweth_device *kaweth) static void kaweth_async_set_rx_mode(struct kaweth_device *kaweth,
bool may_sleep)
{ {
int result; int ret;
__u16 packet_filter_bitmap = kaweth->packet_filter_bitmap; __u16 packet_filter_bitmap = kaweth->packet_filter_bitmap;
kaweth->packet_filter_bitmap = 0; kaweth->packet_filter_bitmap = 0;
if (packet_filter_bitmap == 0) if (packet_filter_bitmap == 0)
return; return;
if (in_interrupt()) if (!may_sleep)
return; return;
result = kaweth_control(kaweth, ret = usb_control_msg(kaweth->dev, usb_sndctrlpipe(kaweth->dev, 0),
usb_sndctrlpipe(kaweth->dev, 0), KAWETH_COMMAND_SET_PACKET_FILTER,
KAWETH_COMMAND_SET_PACKET_FILTER, USB_TYPE_VENDOR | USB_DIR_OUT | USB_RECIP_DEVICE,
USB_TYPE_VENDOR | USB_DIR_OUT | USB_RECIP_DEVICE, packet_filter_bitmap, 0,
packet_filter_bitmap, &kaweth->scratch, 0,
0, KAWETH_CONTROL_TIMEOUT);
(void *)&kaweth->scratch, if (ret < 0)
0,
KAWETH_CONTROL_TIMEOUT);
if(result < 0) {
dev_err(&kaweth->intf->dev, "Failed to set Rx mode: %d\n", dev_err(&kaweth->intf->dev, "Failed to set Rx mode: %d\n",
result); ret);
} else
else {
netdev_dbg(kaweth->net, "Set Rx mode to %d\n", netdev_dbg(kaweth->net, "Set Rx mode to %d\n",
packet_filter_bitmap); packet_filter_bitmap);
}
} }
/**************************************************************** /****************************************************************
...@@ -1163,88 +1113,4 @@ static void kaweth_disconnect(struct usb_interface *intf) ...@@ -1163,88 +1113,4 @@ static void kaweth_disconnect(struct usb_interface *intf)
} }
// FIXME this completion stuff is a modified clone of
// an OLD version of some stuff in usb.c ...
struct usb_api_data {
wait_queue_head_t wqh;
int done;
};
/*-------------------------------------------------------------------*
* completion handler for compatibility wrappers (sync control/bulk) *
*-------------------------------------------------------------------*/
static void usb_api_blocking_completion(struct urb *urb)
{
struct usb_api_data *awd = (struct usb_api_data *)urb->context;
awd->done=1;
wake_up(&awd->wqh);
}
/*-------------------------------------------------------------------*
* COMPATIBILITY STUFF *
*-------------------------------------------------------------------*/
// Starts urb and waits for completion or timeout
static int usb_start_wait_urb(struct urb *urb, int timeout, int* actual_length)
{
struct usb_api_data awd;
int status;
init_waitqueue_head(&awd.wqh);
awd.done = 0;
urb->context = &awd;
status = usb_submit_urb(urb, GFP_ATOMIC);
if (status) {
// something went wrong
usb_free_urb(urb);
return status;
}
if (!wait_event_timeout(awd.wqh, awd.done, timeout)) {
// timeout
dev_warn(&urb->dev->dev, "usb_control/bulk_msg: timeout\n");
usb_kill_urb(urb); // remove urb safely
status = -ETIMEDOUT;
}
else {
status = urb->status;
}
if (actual_length) {
*actual_length = urb->actual_length;
}
usb_free_urb(urb);
return status;
}
/*-------------------------------------------------------------------*/
// returns status (negative) or length (positive)
static int kaweth_internal_control_msg(struct usb_device *usb_dev,
unsigned int pipe,
struct usb_ctrlrequest *cmd, void *data,
int len, int timeout)
{
struct urb *urb;
int retv;
int length = 0; /* shut up GCC */
urb = usb_alloc_urb(0, GFP_ATOMIC);
if (!urb)
return -ENOMEM;
usb_fill_control_urb(urb, usb_dev, pipe, (unsigned char*)cmd, data,
len, usb_api_blocking_completion, NULL);
retv = usb_start_wait_urb(urb, timeout, &length);
if (retv < 0) {
return retv;
}
else {
return length;
}
}
module_usb_driver(kaweth_driver); module_usb_driver(kaweth_driver);
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment