Skip to content

Commit a14a145

Browse files
cris-masudeep-holla
authored andcommitted
firmware: arm_scmi: Simplify spinlocks in virtio transport
Remove unneeded nested irqsave/irqrestore spinlocks. Add also a few descriptive comments to explain better the system behaviour at shutdown time. Link: https://lore.kernel.org/r/[email protected] Cc: "Michael S. Tsirkin" <[email protected]> Cc: Sudeep Holla <[email protected]> Signed-off-by: Cristian Marussi <[email protected]> Signed-off-by: Sudeep Holla <[email protected]>
1 parent 1cd7320 commit a14a145

File tree

1 file changed

+21
-8
lines changed

1 file changed

+21
-8
lines changed

drivers/firmware/arm_scmi/virtio.c

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -110,18 +110,16 @@ static void scmi_finalize_message(struct scmi_vio_channel *vioch,
110110
if (vioch->is_rx) {
111111
scmi_vio_feed_vq_rx(vioch, msg);
112112
} else {
113-
unsigned long flags;
114-
115-
spin_lock_irqsave(&vioch->lock, flags);
113+
/* Here IRQs are assumed to be already disabled by the caller */
114+
spin_lock(&vioch->lock);
116115
list_add(&msg->list, &vioch->free_list);
117-
spin_unlock_irqrestore(&vioch->lock, flags);
116+
spin_unlock(&vioch->lock);
118117
}
119118
}
120119

121120
static void scmi_vio_complete_cb(struct virtqueue *vqueue)
122121
{
123122
unsigned long ready_flags;
124-
unsigned long flags;
125123
unsigned int length;
126124
struct scmi_vio_channel *vioch;
127125
struct scmi_vio_msg *msg;
@@ -140,7 +138,8 @@ static void scmi_vio_complete_cb(struct virtqueue *vqueue)
140138
goto unlock_ready_out;
141139
}
142140

143-
spin_lock_irqsave(&vioch->lock, flags);
141+
/* IRQs already disabled here no need to irqsave */
142+
spin_lock(&vioch->lock);
144143
if (cb_enabled) {
145144
virtqueue_disable_cb(vqueue);
146145
cb_enabled = false;
@@ -151,7 +150,7 @@ static void scmi_vio_complete_cb(struct virtqueue *vqueue)
151150
goto unlock_out;
152151
cb_enabled = true;
153152
}
154-
spin_unlock_irqrestore(&vioch->lock, flags);
153+
spin_unlock(&vioch->lock);
155154

156155
if (msg) {
157156
msg->rx_len = length;
@@ -161,11 +160,18 @@ static void scmi_vio_complete_cb(struct virtqueue *vqueue)
161160
scmi_finalize_message(vioch, msg);
162161
}
163162

163+
/*
164+
* Release ready_lock and re-enable IRQs between loop iterations
165+
* to allow virtio_chan_free() to possibly kick in and set the
166+
* flag vioch->ready to false even in between processing of
167+
* messages, so as to force outstanding messages to be ignored
168+
* when system is shutting down.
169+
*/
164170
spin_unlock_irqrestore(&vioch->ready_lock, ready_flags);
165171
}
166172

167173
unlock_out:
168-
spin_unlock_irqrestore(&vioch->lock, flags);
174+
spin_unlock(&vioch->lock);
169175
unlock_ready_out:
170176
spin_unlock_irqrestore(&vioch->ready_lock, ready_flags);
171177
}
@@ -435,6 +441,13 @@ static int scmi_vio_probe(struct virtio_device *vdev)
435441

436442
static void scmi_vio_remove(struct virtio_device *vdev)
437443
{
444+
/*
445+
* Once we get here, virtio_chan_free() will have already been called by
446+
* the SCMI core for any existing channel and, as a consequence, all the
447+
* virtio channels will have been already marked NOT ready, causing any
448+
* outstanding message on any vqueue to be ignored by complete_cb: now
449+
* we can just stop processing buffers and destroy the vqueues.
450+
*/
438451
vdev->config->reset(vdev);
439452
vdev->config->del_vqs(vdev);
440453
scmi_vdev = NULL;

0 commit comments

Comments
 (0)