diff options
author | Erez Shitrit <erezsh@mellanox.com> | 2013-10-16 10:37:47 -0400 |
---|---|---|
committer | Roland Dreier <roland@purestorage.com> | 2013-11-08 17:42:48 -0500 |
commit | c2bb5628db44735bc0095a8ef8efc0278ba245df (patch) | |
tree | fa806db1ca48249da47b6f2c59f0b663d9279250 /drivers/infiniband/ulp | |
parent | 959f58544b7f20c92d5eb43d1232c96c15c01bfb (diff) |
IPoIB: Fix crash in dev_open error flow
If napi has never been enabled when calling ipoib_ib_dev_stop, a
kernel crash occurs, because the verbs layer completion handler
(ipoib_ib_completion) calls napi_schedule unconditionally.
If the napi structure passed in the napi_schedule call has not
been initialized, napi will crash.
The cleanest solution is to simply enable napi before calling
ipoib_ib_dev_stop in the dev_open error flow. (dev_stop then
immediately disables napi).
Signed-off-by: Jack Morgenstein <jackm@dev.mellanox.co.il>
Signed-off-by: Erez Shitrit <erezsh@mellanox.com>
Signed-off-by: Or Gerlitz <ogerlitz@mellanox.com>
Signed-off-by: Roland Dreier <roland@purestorage.com>
Diffstat (limited to 'drivers/infiniband/ulp')
-rw-r--r-- | drivers/infiniband/ulp/ipoib/ipoib_ib.c | 11 |
1 files changed, 7 insertions, 4 deletions
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_ib.c b/drivers/infiniband/ulp/ipoib/ipoib_ib.c index 196b1d13cbcb..c14f949edcb7 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_ib.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_ib.c | |||
@@ -685,15 +685,13 @@ int ipoib_ib_dev_open(struct net_device *dev) | |||
685 | ret = ipoib_ib_post_receives(dev); | 685 | ret = ipoib_ib_post_receives(dev); |
686 | if (ret) { | 686 | if (ret) { |
687 | ipoib_warn(priv, "ipoib_ib_post_receives returned %d\n", ret); | 687 | ipoib_warn(priv, "ipoib_ib_post_receives returned %d\n", ret); |
688 | ipoib_ib_dev_stop(dev, 1); | 688 | goto dev_stop; |
689 | return -1; | ||
690 | } | 689 | } |
691 | 690 | ||
692 | ret = ipoib_cm_dev_open(dev); | 691 | ret = ipoib_cm_dev_open(dev); |
693 | if (ret) { | 692 | if (ret) { |
694 | ipoib_warn(priv, "ipoib_cm_dev_open returned %d\n", ret); | 693 | ipoib_warn(priv, "ipoib_cm_dev_open returned %d\n", ret); |
695 | ipoib_ib_dev_stop(dev, 1); | 694 | goto dev_stop; |
696 | return -1; | ||
697 | } | 695 | } |
698 | 696 | ||
699 | clear_bit(IPOIB_STOP_REAPER, &priv->flags); | 697 | clear_bit(IPOIB_STOP_REAPER, &priv->flags); |
@@ -704,6 +702,11 @@ int ipoib_ib_dev_open(struct net_device *dev) | |||
704 | napi_enable(&priv->napi); | 702 | napi_enable(&priv->napi); |
705 | 703 | ||
706 | return 0; | 704 | return 0; |
705 | dev_stop: | ||
706 | if (!test_and_set_bit(IPOIB_FLAG_INITIALIZED, &priv->flags)) | ||
707 | napi_enable(&priv->napi); | ||
708 | ipoib_ib_dev_stop(dev, 1); | ||
709 | return -1; | ||
707 | } | 710 | } |
708 | 711 | ||
709 | static void ipoib_pkey_dev_check_presence(struct net_device *dev) | 712 | static void ipoib_pkey_dev_check_presence(struct net_device *dev) |