aboutsummaryrefslogtreecommitdiffstats
path: root/arch/xtensa/platforms/iss/network.c
diff options
context:
space:
mode:
authorMax Filippov <jcmvbkbc@gmail.com>2015-04-03 02:56:21 -0400
committerMax Filippov <jcmvbkbc@gmail.com>2015-04-13 02:01:00 -0400
commit24e94454c8cb6a13634f5a2f5a01da53a546a58d (patch)
tree97428ea550eb6c74ed239c3e2efd94369d9734e5 /arch/xtensa/platforms/iss/network.c
parent39a8804455fb23f09157341d3ba7db6d7ae6ee76 (diff)
xtensa: ISS: fix locking in TAP network adapter
- don't lock lp->lock in the iss_net_timer for the call of iss_net_poll, it will lock it itself; - invert order of lp->lock and opened_lock acquisition in the iss_net_open to make it consistent with iss_net_poll; - replace spin_lock with spin_lock_bh when acquiring locks used in iss_net_timer from non-atomic context; - replace spin_lock_irqsave with spin_lock_bh in the iss_net_start_xmit as the driver doesn't use lp->lock in the hard IRQ context; - replace __SPIN_LOCK_UNLOCKED(lp.lock) with spin_lock_init, otherwise lockdep is unhappy about using non-static key. Cc: <stable@vger.kernel.org> Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
Diffstat (limited to 'arch/xtensa/platforms/iss/network.c')
-rw-r--r--arch/xtensa/platforms/iss/network.c29
1 files changed, 15 insertions, 14 deletions
diff --git a/arch/xtensa/platforms/iss/network.c b/arch/xtensa/platforms/iss/network.c
index d05f8feeb8d7..17b1ef3232e4 100644
--- a/arch/xtensa/platforms/iss/network.c
+++ b/arch/xtensa/platforms/iss/network.c
@@ -349,8 +349,8 @@ static void iss_net_timer(unsigned long priv)
349{ 349{
350 struct iss_net_private *lp = (struct iss_net_private *)priv; 350 struct iss_net_private *lp = (struct iss_net_private *)priv;
351 351
352 spin_lock(&lp->lock);
353 iss_net_poll(); 352 iss_net_poll();
353 spin_lock(&lp->lock);
354 mod_timer(&lp->timer, jiffies + lp->timer_val); 354 mod_timer(&lp->timer, jiffies + lp->timer_val);
355 spin_unlock(&lp->lock); 355 spin_unlock(&lp->lock);
356} 356}
@@ -361,7 +361,7 @@ static int iss_net_open(struct net_device *dev)
361 struct iss_net_private *lp = netdev_priv(dev); 361 struct iss_net_private *lp = netdev_priv(dev);
362 int err; 362 int err;
363 363
364 spin_lock(&lp->lock); 364 spin_lock_bh(&lp->lock);
365 365
366 err = lp->tp.open(lp); 366 err = lp->tp.open(lp);
367 if (err < 0) 367 if (err < 0)
@@ -376,9 +376,11 @@ static int iss_net_open(struct net_device *dev)
376 while ((err = iss_net_rx(dev)) > 0) 376 while ((err = iss_net_rx(dev)) > 0)
377 ; 377 ;
378 378
379 spin_lock(&opened_lock); 379 spin_unlock_bh(&lp->lock);
380 spin_lock_bh(&opened_lock);
380 list_add(&lp->opened_list, &opened); 381 list_add(&lp->opened_list, &opened);
381 spin_unlock(&opened_lock); 382 spin_unlock_bh(&opened_lock);
383 spin_lock_bh(&lp->lock);
382 384
383 init_timer(&lp->timer); 385 init_timer(&lp->timer);
384 lp->timer_val = ISS_NET_TIMER_VALUE; 386 lp->timer_val = ISS_NET_TIMER_VALUE;
@@ -387,7 +389,7 @@ static int iss_net_open(struct net_device *dev)
387 mod_timer(&lp->timer, jiffies + lp->timer_val); 389 mod_timer(&lp->timer, jiffies + lp->timer_val);
388 390
389out: 391out:
390 spin_unlock(&lp->lock); 392 spin_unlock_bh(&lp->lock);
391 return err; 393 return err;
392} 394}
393 395
@@ -395,7 +397,7 @@ static int iss_net_close(struct net_device *dev)
395{ 397{
396 struct iss_net_private *lp = netdev_priv(dev); 398 struct iss_net_private *lp = netdev_priv(dev);
397 netif_stop_queue(dev); 399 netif_stop_queue(dev);
398 spin_lock(&lp->lock); 400 spin_lock_bh(&lp->lock);
399 401
400 spin_lock(&opened_lock); 402 spin_lock(&opened_lock);
401 list_del(&opened); 403 list_del(&opened);
@@ -405,18 +407,17 @@ static int iss_net_close(struct net_device *dev)
405 407
406 lp->tp.close(lp); 408 lp->tp.close(lp);
407 409
408 spin_unlock(&lp->lock); 410 spin_unlock_bh(&lp->lock);
409 return 0; 411 return 0;
410} 412}
411 413
412static int iss_net_start_xmit(struct sk_buff *skb, struct net_device *dev) 414static int iss_net_start_xmit(struct sk_buff *skb, struct net_device *dev)
413{ 415{
414 struct iss_net_private *lp = netdev_priv(dev); 416 struct iss_net_private *lp = netdev_priv(dev);
415 unsigned long flags;
416 int len; 417 int len;
417 418
418 netif_stop_queue(dev); 419 netif_stop_queue(dev);
419 spin_lock_irqsave(&lp->lock, flags); 420 spin_lock_bh(&lp->lock);
420 421
421 len = lp->tp.write(lp, &skb); 422 len = lp->tp.write(lp, &skb);
422 423
@@ -438,7 +439,7 @@ static int iss_net_start_xmit(struct sk_buff *skb, struct net_device *dev)
438 pr_err("%s: %s failed(%d)\n", dev->name, __func__, len); 439 pr_err("%s: %s failed(%d)\n", dev->name, __func__, len);
439 } 440 }
440 441
441 spin_unlock_irqrestore(&lp->lock, flags); 442 spin_unlock_bh(&lp->lock);
442 443
443 dev_kfree_skb(skb); 444 dev_kfree_skb(skb);
444 return NETDEV_TX_OK; 445 return NETDEV_TX_OK;
@@ -466,9 +467,9 @@ static int iss_net_set_mac(struct net_device *dev, void *addr)
466 467
467 if (!is_valid_ether_addr(hwaddr->sa_data)) 468 if (!is_valid_ether_addr(hwaddr->sa_data))
468 return -EADDRNOTAVAIL; 469 return -EADDRNOTAVAIL;
469 spin_lock(&lp->lock); 470 spin_lock_bh(&lp->lock);
470 memcpy(dev->dev_addr, hwaddr->sa_data, ETH_ALEN); 471 memcpy(dev->dev_addr, hwaddr->sa_data, ETH_ALEN);
471 spin_unlock(&lp->lock); 472 spin_unlock_bh(&lp->lock);
472 return 0; 473 return 0;
473} 474}
474 475
@@ -520,11 +521,11 @@ static int iss_net_configure(int index, char *init)
520 *lp = (struct iss_net_private) { 521 *lp = (struct iss_net_private) {
521 .device_list = LIST_HEAD_INIT(lp->device_list), 522 .device_list = LIST_HEAD_INIT(lp->device_list),
522 .opened_list = LIST_HEAD_INIT(lp->opened_list), 523 .opened_list = LIST_HEAD_INIT(lp->opened_list),
523 .lock = __SPIN_LOCK_UNLOCKED(lp.lock),
524 .dev = dev, 524 .dev = dev,
525 .index = index, 525 .index = index,
526 }; 526 };
527 527
528 spin_lock_init(&lp->lock);
528 /* 529 /*
529 * If this name ends up conflicting with an existing registered 530 * If this name ends up conflicting with an existing registered
530 * netdevice, that is OK, register_netdev{,ice}() will notice this 531 * netdevice, that is OK, register_netdev{,ice}() will notice this