Skip to content

Commit 7f063b2

Browse files
committed
Merge tag 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mst/vhost
Pull vhost,vdpa,virtio updates from Michael Tsirkin: - transport v3 support in virtio-mmio - suspend support in vduse - fixes, cleanups all over the place * tag 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mst/vhost: (54 commits) vduse: Add suspend vduse: do not take rwsem at reset work flush vduse: add F_QUEUE_READY feature vduse: add VDUSE_SET_FEATURES ioctl vduse: add VDUSE_GET_FEATURES ioctl vduse: store control device pointer tools/virtio: Fix control typo in trace agent comment tools/virtio: Fix userspace typo in vringh test comment vhost: reject zero-size IOTLB INVALIDATE vdpa: Remove redundant dev_err() virtio_ring: fix infinite loop in virtnet_poll_cleantx when device is broken vdpa/mlx5: roll back MR update after VQ setup failure MAINTAINERS: remove Gabriel from LiteX and fw-cfg drivers virtio_mem: fix typo in comment vdpa/solidrun: fix typos in snet_ctrl comments virtio: fix article before virtio in dma-buf comment vhost: fix inaccurate kdoc in iotlb helpers virtio: rtc: time out alarm requests vdpa/mlx5: fix wrong MLX5_ADDR_OF struct type in alloc_inout() vdpa: octeon_ep: add missing MODULE_DEVICE_TABLE() ...
2 parents a625b2a + b282418 commit 7f063b2

37 files changed

Lines changed: 760 additions & 222 deletions

MAINTAINERS

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15032,7 +15032,6 @@ F: lib/tests/list-test.c
1503215032
LITEX PLATFORM
1503315033
M: Karol Gugala <kgugala@antmicro.com>
1503415034
M: Mateusz Holenko <mholenko@antmicro.com>
15035-
M: Gabriel Somlo <gsomlo@gmail.com>
1503615035
M: Joel Stanley <joel@jms.id.au>
1503715036
S: Maintained
1503815037
F: Documentation/devicetree/bindings/*/litex,*.yaml
@@ -21987,7 +21986,6 @@ S: Maintained
2198721986
F: drivers/net/ipa/
2198821987

2198921988
QEMU MACHINE EMULATOR AND VIRTUALIZER SUPPORT
21990-
M: Gabriel Somlo <somlo@cmu.edu>
2199121989
M: "Michael S. Tsirkin" <mst@redhat.com>
2199221990
L: qemu-devel@nongnu.org
2199321991
S: Maintained

drivers/crypto/virtio/virtio_crypto_akcipher_algs.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,8 @@ static void virtio_crypto_dataq_akcipher_callback(struct virtio_crypto_request *
8888
}
8989

9090
/* actual length may be less than dst buffer */
91-
akcipher_req->dst_len = len - sizeof(vc_req->status);
91+
akcipher_req->dst_len = min_t(unsigned int, len - sizeof(vc_req->status),
92+
akcipher_req->dst_len);
9293
sg_copy_from_buffer(akcipher_req->dst, sg_nents(akcipher_req->dst),
9394
vc_akcipher_req->dst_buf, akcipher_req->dst_len);
9495
virtio_crypto_akcipher_finalize_req(vc_akcipher_req, akcipher_req, error);
@@ -194,7 +195,8 @@ static int virtio_crypto_alg_akcipher_close_session(struct virtio_crypto_akciphe
194195

195196
if (ctrl_status->status != VIRTIO_CRYPTO_OK) {
196197
pr_err("virtio_crypto: Close session failed status: %u, session_id: 0x%llx\n",
197-
ctrl_status->status, destroy_session->session_id);
198+
ctrl_status->status,
199+
le64_to_cpu(destroy_session->session_id));
198200
err = -EINVAL;
199201
goto out;
200202
}

drivers/crypto/virtio/virtio_crypto_skcipher_algs.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -232,7 +232,8 @@ static int virtio_crypto_alg_skcipher_close_session(
232232

233233
if (ctrl_status->status != VIRTIO_CRYPTO_OK) {
234234
pr_err("virtio_crypto: Close session failed status: %u, session_id: 0x%llx\n",
235-
ctrl_status->status, destroy_session->session_id);
235+
ctrl_status->status,
236+
le64_to_cpu(destroy_session->session_id));
236237

237238
err = -EINVAL;
238239
goto out;

drivers/nvdimm/nd_virtio.c

Lines changed: 219 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -9,26 +9,130 @@
99
#include "virtio_pmem.h"
1010
#include "nd.h"
1111

12+
struct virtio_pmem_flush_work {
13+
struct work_struct work;
14+
struct nd_region *nd_region;
15+
struct bio *bio;
16+
};
17+
18+
static void virtio_pmem_req_release(struct kref *kref)
19+
{
20+
struct virtio_pmem_request *req;
21+
22+
req = container_of(kref, struct virtio_pmem_request, kref);
23+
kfree(req);
24+
}
25+
26+
static void virtio_pmem_signal_done(struct virtio_pmem_request *req)
27+
{
28+
/* Pairs with smp_load_acquire() in virtio_pmem_req_done(). */
29+
smp_store_release(&req->done, true);
30+
wake_up(&req->host_acked);
31+
}
32+
33+
static bool virtio_pmem_req_done(struct virtio_pmem_request *req)
34+
{
35+
/* Pairs with smp_store_release() in virtio_pmem_signal_done(). */
36+
return smp_load_acquire(&req->done);
37+
}
38+
39+
static void virtio_pmem_complete_err(struct virtio_pmem_request *req)
40+
{
41+
req->resp.ret = cpu_to_le32(1);
42+
virtio_pmem_signal_done(req);
43+
}
44+
45+
static void virtio_pmem_wake_one_waiter(struct virtio_pmem *vpmem)
46+
{
47+
struct virtio_pmem_request *req_buf;
48+
49+
if (list_empty(&vpmem->req_list))
50+
return;
51+
52+
req_buf = list_first_entry(&vpmem->req_list,
53+
struct virtio_pmem_request, list);
54+
list_del_init(&req_buf->list);
55+
WRITE_ONCE(req_buf->wq_buf_avail, true);
56+
wake_up(&req_buf->wq_buf);
57+
}
58+
59+
static void virtio_pmem_wake_all_waiters(struct virtio_pmem *vpmem)
60+
{
61+
struct virtio_pmem_request *req, *tmp;
62+
63+
list_for_each_entry_safe(req, tmp, &vpmem->req_list, list) {
64+
list_del_init(&req->list);
65+
WRITE_ONCE(req->wq_buf_avail, true);
66+
wake_up(&req->wq_buf);
67+
}
68+
}
69+
70+
static void virtio_pmem_clear_inflight(struct virtio_pmem *vpmem,
71+
struct virtio_pmem_request *req)
72+
{
73+
if (vpmem->req_inflight == req)
74+
vpmem->req_inflight = NULL;
75+
}
76+
77+
static void virtio_pmem_wake_inflight(struct virtio_pmem *vpmem)
78+
{
79+
struct virtio_pmem_request *req = vpmem->req_inflight;
80+
81+
if (req)
82+
wake_up(&req->host_acked);
83+
}
84+
85+
void virtio_pmem_mark_broken(struct virtio_pmem *vpmem)
86+
{
87+
if (!READ_ONCE(vpmem->broken)) {
88+
WRITE_ONCE(vpmem->broken, true);
89+
dev_err_once(&vpmem->vdev->dev, "virtqueue is broken\n");
90+
}
91+
92+
virtio_pmem_wake_inflight(vpmem);
93+
virtio_pmem_wake_all_waiters(vpmem);
94+
}
95+
EXPORT_SYMBOL_GPL(virtio_pmem_mark_broken);
96+
97+
void virtio_pmem_drain(struct virtio_pmem *vpmem)
98+
{
99+
struct virtio_pmem_request *req;
100+
unsigned int len;
101+
102+
if (!vpmem->req_vq)
103+
return;
104+
105+
while ((req = virtqueue_get_buf(vpmem->req_vq, &len)) != NULL) {
106+
virtio_pmem_clear_inflight(vpmem, req);
107+
virtio_pmem_complete_err(req);
108+
kref_put(&req->kref, virtio_pmem_req_release);
109+
}
110+
111+
while ((req = virtqueue_detach_unused_buf(vpmem->req_vq)) != NULL) {
112+
virtio_pmem_clear_inflight(vpmem, req);
113+
virtio_pmem_complete_err(req);
114+
kref_put(&req->kref, virtio_pmem_req_release);
115+
}
116+
}
117+
EXPORT_SYMBOL_GPL(virtio_pmem_drain);
118+
12119
/* The interrupt handler */
13120
void virtio_pmem_host_ack(struct virtqueue *vq)
14121
{
15122
struct virtio_pmem *vpmem = vq->vdev->priv;
16-
struct virtio_pmem_request *req_data, *req_buf;
123+
struct virtio_pmem_request *req_data;
17124
unsigned long flags;
18125
unsigned int len;
19126

20127
spin_lock_irqsave(&vpmem->pmem_lock, flags);
21128
while ((req_data = virtqueue_get_buf(vq, &len)) != NULL) {
22-
req_data->done = true;
23-
wake_up(&req_data->host_acked);
24-
25-
if (!list_empty(&vpmem->req_list)) {
26-
req_buf = list_first_entry(&vpmem->req_list,
27-
struct virtio_pmem_request, list);
28-
req_buf->wq_buf_avail = true;
29-
wake_up(&req_buf->wq_buf);
30-
list_del(&req_buf->list);
31-
}
129+
virtio_pmem_clear_inflight(vpmem, req_data);
130+
virtio_pmem_wake_one_waiter(vpmem);
131+
if (READ_ONCE(vpmem->broken))
132+
virtio_pmem_complete_err(req_data);
133+
else
134+
virtio_pmem_signal_done(req_data);
135+
kref_put(&req_data->kref, virtio_pmem_req_release);
32136
}
33137
spin_unlock_irqrestore(&vpmem->pmem_lock, flags);
34138
}
@@ -55,11 +159,15 @@ static int virtio_pmem_flush(struct nd_region *nd_region)
55159
return -EIO;
56160
}
57161

58-
req_data = kmalloc_obj(*req_data);
162+
if (READ_ONCE(vpmem->broken))
163+
return -EIO;
164+
165+
req_data = kmalloc_obj(*req_data, GFP_NOIO);
59166
if (!req_data)
60167
return -ENOMEM;
61168

62-
req_data->done = false;
169+
kref_init(&req_data->kref);
170+
WRITE_ONCE(req_data->done, false);
63171
init_waitqueue_head(&req_data->host_acked);
64172
init_waitqueue_head(&req_data->wq_buf);
65173
INIT_LIST_HEAD(&req_data->list);
@@ -70,67 +178,132 @@ static int virtio_pmem_flush(struct nd_region *nd_region)
70178
sgs[1] = &ret;
71179

72180
spin_lock_irqsave(&vpmem->pmem_lock, flags);
73-
/*
74-
* If virtqueue_add_sgs returns -ENOSPC then req_vq virtual
75-
* queue does not have free descriptor. We add the request
76-
* to req_list and wait for host_ack to wake us up when free
77-
* slots are available.
78-
*/
79-
while ((err = virtqueue_add_sgs(vpmem->req_vq, sgs, 1, 1, req_data,
80-
GFP_ATOMIC)) == -ENOSPC) {
81-
82-
dev_info(&vdev->dev, "failed to send command to virtio pmem device, no free slots in the virtqueue\n");
83-
req_data->wq_buf_avail = false;
181+
/*
182+
* If virtqueue_add_sgs returns -ENOSPC then req_vq virtual
183+
* queue does not have free descriptor. We add the request
184+
* to req_list and wait for host_ack to wake us up when free
185+
* slots are available.
186+
*/
187+
for (;;) {
188+
if (READ_ONCE(vpmem->broken)) {
189+
err = -EIO;
190+
break;
191+
}
192+
193+
err = virtqueue_add_sgs(vpmem->req_vq, sgs, 1, 1, req_data,
194+
GFP_ATOMIC);
195+
if (!err) {
196+
/*
197+
* Take the virtqueue reference while @pmem_lock is
198+
* held so completion cannot run concurrently.
199+
*/
200+
kref_get(&req_data->kref);
201+
vpmem->req_inflight = req_data;
202+
break;
203+
}
204+
205+
if (err != -ENOSPC)
206+
break;
207+
208+
dev_info_ratelimited(&vdev->dev,
209+
"failed to send command to virtio pmem device, no free slots in the virtqueue\n");
210+
WRITE_ONCE(req_data->wq_buf_avail, false);
84211
list_add_tail(&req_data->list, &vpmem->req_list);
85212
spin_unlock_irqrestore(&vpmem->pmem_lock, flags);
86213

87214
/* A host response results in "host_ack" getting called */
88-
wait_event(req_data->wq_buf, req_data->wq_buf_avail);
215+
wait_event(req_data->wq_buf,
216+
READ_ONCE(req_data->wq_buf_avail) ||
217+
READ_ONCE(vpmem->broken));
89218
spin_lock_irqsave(&vpmem->pmem_lock, flags);
219+
220+
if (READ_ONCE(vpmem->broken))
221+
break;
222+
}
223+
224+
if (READ_ONCE(vpmem->broken))
225+
err = -EIO;
226+
if (err == -EIO || virtqueue_is_broken(vpmem->req_vq))
227+
virtio_pmem_mark_broken(vpmem);
228+
229+
err1 = true;
230+
if (!err && !READ_ONCE(vpmem->broken)) {
231+
err1 = virtqueue_kick(vpmem->req_vq);
232+
if (!err1)
233+
virtio_pmem_mark_broken(vpmem);
90234
}
91-
err1 = virtqueue_kick(vpmem->req_vq);
92235
spin_unlock_irqrestore(&vpmem->pmem_lock, flags);
93236
/*
94237
* virtqueue_add_sgs failed with error different than -ENOSPC, we can't
95238
* do anything about that.
96239
*/
97-
if (err || !err1) {
240+
if (READ_ONCE(vpmem->broken) || err || !err1) {
98241
dev_info(&vdev->dev, "failed to send command to virtio pmem device\n");
99242
err = -EIO;
100243
} else {
101244
/* A host response results in "host_ack" getting called */
102-
wait_event(req_data->host_acked, req_data->done);
103-
err = le32_to_cpu(req_data->resp.ret);
245+
wait_event(req_data->host_acked,
246+
virtio_pmem_req_done(req_data) ||
247+
READ_ONCE(vpmem->broken));
248+
if (virtio_pmem_req_done(req_data))
249+
err = le32_to_cpu(req_data->resp.ret);
250+
else
251+
err = -EIO;
104252
}
105253

106-
kfree(req_data);
254+
kref_put(&req_data->kref, virtio_pmem_req_release);
107255
return err;
108256
};
109257

258+
static void virtio_pmem_flush_work(struct work_struct *work)
259+
{
260+
struct virtio_pmem_flush_work *flush;
261+
int err;
262+
263+
flush = container_of(work, struct virtio_pmem_flush_work, work);
264+
err = virtio_pmem_flush(flush->nd_region);
265+
if (err > 0)
266+
err = -EIO;
267+
if (err)
268+
flush->bio->bi_status = errno_to_blk_status(err);
269+
bio_endio(flush->bio);
270+
kfree(flush);
271+
}
272+
110273
/* The asynchronous flush callback function */
111274
int async_pmem_flush(struct nd_region *nd_region, struct bio *bio)
112275
{
113-
/*
114-
* Create child bio for asynchronous flush and chain with
115-
* parent bio. Otherwise directly call nd_region flush.
116-
*/
117-
if (bio && bio->bi_iter.bi_sector != -1) {
118-
struct bio *child = bio_alloc(bio->bi_bdev, 0,
119-
REQ_OP_WRITE | REQ_PREFLUSH,
120-
GFP_ATOMIC);
276+
struct virtio_device *vdev = nd_region->provider_data;
277+
struct virtio_pmem *vpmem = vdev->priv;
278+
struct virtio_pmem_flush_work *flush;
279+
unsigned long flags;
280+
int err;
121281

122-
if (!child)
282+
if (bio && bio->bi_iter.bi_sector != -1) {
283+
flush = kmalloc_obj(*flush, GFP_NOIO);
284+
if (!flush)
123285
return -ENOMEM;
124-
bio_clone_blkg_association(child, bio);
125-
child->bi_iter.bi_sector = -1;
126-
bio_chain(child, bio);
127-
submit_bio(child);
128-
return 0;
286+
287+
INIT_WORK(&flush->work, virtio_pmem_flush_work);
288+
flush->nd_region = nd_region;
289+
flush->bio = bio;
290+
291+
spin_lock_irqsave(&vpmem->pmem_lock, flags);
292+
if (READ_ONCE(vpmem->broken)) {
293+
spin_unlock_irqrestore(&vpmem->pmem_lock, flags);
294+
kfree(flush);
295+
return -EIO;
296+
}
297+
queue_work(vpmem->flush_wq, &flush->work);
298+
spin_unlock_irqrestore(&vpmem->pmem_lock, flags);
299+
return NVDIMM_FLUSH_ASYNC;
129300
}
130-
if (virtio_pmem_flush(nd_region))
301+
302+
err = virtio_pmem_flush(nd_region);
303+
if (err > 0)
131304
return -EIO;
132305

133-
return 0;
306+
return err;
134307
};
135308
EXPORT_SYMBOL_GPL(async_pmem_flush);
136309
MODULE_DESCRIPTION("Virtio Persistent Memory Driver");

0 commit comments

Comments
 (0)