summaryrefslogtreecommitdiffstats
path: root/drivers/rapidio
diff options
context:
space:
mode:
authorAlexandre Bounine <alexandre.bounine@idt.com>2016-09-19 17:44:47 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2016-09-19 18:36:17 -0400
commitb92ae139c308c5223521ed6ec022148b81312809 (patch)
treeca05935b1c708bc8c982633781d46aed1b0070df /drivers/rapidio
parent63b52c4936a2e679639c38ef51a50aa8ca1c5c07 (diff)
rapidio/rio_cm: avoid GFP_KERNEL in atomic context
As reported by Alexey Khoroshilov (https://lkml.org/lkml/2016/9/9/737): riocm_send_close() is called from rio_cm_shutdown() under spin_lock_bh(idr_lock), but riocm_send_close() uses a GFP_KERNEL allocation. Fix by taking riocm_send_close() outside of spinlock protected code. [akpm@linux-foundation.org: remove unneeded `if (!list_empty())'] Link: http://lkml.kernel.org/r/20160915175402.10122-1-alexandre.bounine@idt.com Signed-off-by: Alexandre Bounine <alexandre.bounine@idt.com> Reported-by: Alexey Khoroshilov <khoroshilov@ispras.ru> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/rapidio')
-rw-r--r--drivers/rapidio/rio_cm.c19
1 files changed, 16 insertions, 3 deletions
diff --git a/drivers/rapidio/rio_cm.c b/drivers/rapidio/rio_cm.c
index 3fa17ac8df54..cebc296463ad 100644
--- a/drivers/rapidio/rio_cm.c
+++ b/drivers/rapidio/rio_cm.c
@@ -2247,17 +2247,30 @@ static int rio_cm_shutdown(struct notifier_block *nb, unsigned long code,
2247{ 2247{
2248 struct rio_channel *ch; 2248 struct rio_channel *ch;
2249 unsigned int i; 2249 unsigned int i;
2250 LIST_HEAD(list);
2250 2251
2251 riocm_debug(EXIT, "."); 2252 riocm_debug(EXIT, ".");
2252 2253
2254 /*
2255 * If there are any channels left in connected state send
2256 * close notification to the connection partner.
2257 * First build a list of channels that require a closing
2258 * notification because function riocm_send_close() should
2259 * be called outside of spinlock protected code.
2260 */
2253 spin_lock_bh(&idr_lock); 2261 spin_lock_bh(&idr_lock);
2254 idr_for_each_entry(&ch_idr, ch, i) { 2262 idr_for_each_entry(&ch_idr, ch, i) {
2255 riocm_debug(EXIT, "close ch %d", ch->id); 2263 if (ch->state == RIO_CM_CONNECTED) {
2256 if (ch->state == RIO_CM_CONNECTED) 2264 riocm_debug(EXIT, "close ch %d", ch->id);
2257 riocm_send_close(ch); 2265 idr_remove(&ch_idr, ch->id);
2266 list_add(&ch->ch_node, &list);
2267 }
2258 } 2268 }
2259 spin_unlock_bh(&idr_lock); 2269 spin_unlock_bh(&idr_lock);
2260 2270
2271 list_for_each_entry(ch, &list, ch_node)
2272 riocm_send_close(ch);
2273
2261 return NOTIFY_DONE; 2274 return NOTIFY_DONE;
2262} 2275}
2263 2276