USB CDC NCM: tx_fixup() race condition fix

- tx_fixup() can be called from either timer callback or from xmit()
  in usbnet, so spinlock is added to avoid concurrency-related problem.
- minor correction due to checkpatch warning for some line over 80
  chars after previous patch was applied.

Signed-off-by: Alexey Orishko <alexey.orishko@stericsson.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Alexey Orishko 2011-01-17 07:07:25 +00:00 committed by David S. Miller
parent 1956cc52e7
commit f742aa8acb
1 changed files with 12 additions and 7 deletions

View File

@ -54,7 +54,7 @@
#include <linux/usb/usbnet.h>
#include <linux/usb/cdc.h>
#define DRIVER_VERSION "30-Nov-2010"
#define DRIVER_VERSION "17-Jan-2011"
/* CDC NCM subclass 3.2.1 */
#define USB_CDC_NCM_NDP16_LENGTH_MIN 0x10
@ -868,15 +868,19 @@ static void cdc_ncm_tx_timeout(unsigned long arg)
if (ctx->tx_timer_pending != 0) {
ctx->tx_timer_pending--;
restart = 1;
} else
} else {
restart = 0;
}
spin_unlock(&ctx->mtx);
if (restart)
if (restart) {
spin_lock(&ctx->mtx);
cdc_ncm_tx_timeout_start(ctx);
else if (ctx->netdev != NULL)
spin_unlock(&ctx->mtx);
} else if (ctx->netdev != NULL) {
usbnet_start_xmit(NULL, ctx->netdev);
}
}
static struct sk_buff *
@ -900,7 +904,6 @@ cdc_ncm_tx_fixup(struct usbnet *dev, struct sk_buff *skb, gfp_t flags)
skb_out = cdc_ncm_fill_tx_frame(ctx, skb);
if (ctx->tx_curr_skb != NULL)
need_timer = 1;
spin_unlock(&ctx->mtx);
/* Start timer, if there is a remaining skb */
if (need_timer)
@ -908,6 +911,8 @@ cdc_ncm_tx_fixup(struct usbnet *dev, struct sk_buff *skb, gfp_t flags)
if (skb_out)
dev->net->stats.tx_packets += ctx->tx_curr_frame_num;
spin_unlock(&ctx->mtx);
return skb_out;
error:
@ -1020,8 +1025,8 @@ static int cdc_ncm_rx_fixup(struct usbnet *dev, struct sk_buff *skb_in)
if (((offset + temp) > actlen) ||
(temp > CDC_NCM_MAX_DATAGRAM_SIZE) || (temp < ETH_HLEN)) {
pr_debug("invalid frame detected (ignored)"
"offset[%u]=%u, length=%u, skb=%p\n",
x, offset, temp, skb_in);
"offset[%u]=%u, length=%u, skb=%p\n",
x, offset, temp, skb_in);
if (!x)
goto error;
break;