|
@@ -2247,17 +2247,30 @@ static int rio_cm_shutdown(struct notifier_block *nb, unsigned long code,
|
|
|
{
|
|
|
struct rio_channel *ch;
|
|
|
unsigned int i;
|
|
|
+ LIST_HEAD(list);
|
|
|
|
|
|
riocm_debug(EXIT, ".");
|
|
|
|
|
|
+ /*
|
|
|
+ * If there are any channels left in connected state send
|
|
|
+ * close notification to the connection partner.
|
|
|
+ * First build a list of channels that require a closing
|
|
|
+ * notification because function riocm_send_close() should
|
|
|
+ * be called outside of spinlock protected code.
|
|
|
+ */
|
|
|
spin_lock_bh(&idr_lock);
|
|
|
idr_for_each_entry(&ch_idr, ch, i) {
|
|
|
- riocm_debug(EXIT, "close ch %d", ch->id);
|
|
|
- if (ch->state == RIO_CM_CONNECTED)
|
|
|
- riocm_send_close(ch);
|
|
|
+ if (ch->state == RIO_CM_CONNECTED) {
|
|
|
+ riocm_debug(EXIT, "close ch %d", ch->id);
|
|
|
+ idr_remove(&ch_idr, ch->id);
|
|
|
+ list_add(&ch->ch_node, &list);
|
|
|
+ }
|
|
|
}
|
|
|
spin_unlock_bh(&idr_lock);
|
|
|
|
|
|
+ list_for_each_entry(ch, &list, ch_node)
|
|
|
+ riocm_send_close(ch);
|
|
|
+
|
|
|
return NOTIFY_DONE;
|
|
|
}
|
|
|
|