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