aboutsummaryrefslogtreecommitdiffstats
path: root/net/9p/trans_virtio.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/9p/trans_virtio.c')
-rw-r--r--net/9p/trans_virtio.c48
1 files changed, 39 insertions, 9 deletions
diff --git a/net/9p/trans_virtio.c b/net/9p/trans_virtio.c
index de2e950a0a7a..e1c26b101830 100644
--- a/net/9p/trans_virtio.c
+++ b/net/9p/trans_virtio.c
@@ -194,11 +194,14 @@ static int pack_sg_list(struct scatterlist *sg, int start,
194 if (s > count) 194 if (s > count)
195 s = count; 195 s = count;
196 BUG_ON(index > limit); 196 BUG_ON(index > limit);
197 /* Make sure we don't terminate early. */
198 sg_unmark_end(&sg[index]);
197 sg_set_buf(&sg[index++], data, s); 199 sg_set_buf(&sg[index++], data, s);
198 count -= s; 200 count -= s;
199 data += s; 201 data += s;
200 } 202 }
201 203 if (index-start)
204 sg_mark_end(&sg[index - 1]);
202 return index-start; 205 return index-start;
203} 206}
204 207
@@ -236,12 +239,17 @@ pack_sg_list_p(struct scatterlist *sg, int start, int limit,
236 s = rest_of_page(data); 239 s = rest_of_page(data);
237 if (s > count) 240 if (s > count)
238 s = count; 241 s = count;
242 /* Make sure we don't terminate early. */
243 sg_unmark_end(&sg[index]);
239 sg_set_page(&sg[index++], pdata[i++], s, data_off); 244 sg_set_page(&sg[index++], pdata[i++], s, data_off);
240 data_off = 0; 245 data_off = 0;
241 data += s; 246 data += s;
242 count -= s; 247 count -= s;
243 nr_pages--; 248 nr_pages--;
244 } 249 }
250
251 if (index-start)
252 sg_mark_end(&sg[index - 1]);
245 return index - start; 253 return index - start;
246} 254}
247 255
@@ -256,9 +264,10 @@ static int
256p9_virtio_request(struct p9_client *client, struct p9_req_t *req) 264p9_virtio_request(struct p9_client *client, struct p9_req_t *req)
257{ 265{
258 int err; 266 int err;
259 int in, out; 267 int in, out, out_sgs, in_sgs;
260 unsigned long flags; 268 unsigned long flags;
261 struct virtio_chan *chan = client->trans; 269 struct virtio_chan *chan = client->trans;
270 struct scatterlist *sgs[2];
262 271
263 p9_debug(P9_DEBUG_TRANS, "9p debug: virtio request\n"); 272 p9_debug(P9_DEBUG_TRANS, "9p debug: virtio request\n");
264 273
@@ -266,14 +275,19 @@ p9_virtio_request(struct p9_client *client, struct p9_req_t *req)
266req_retry: 275req_retry:
267 spin_lock_irqsave(&chan->lock, flags); 276 spin_lock_irqsave(&chan->lock, flags);
268 277
278 out_sgs = in_sgs = 0;
269 /* Handle out VirtIO ring buffers */ 279 /* Handle out VirtIO ring buffers */
270 out = pack_sg_list(chan->sg, 0, 280 out = pack_sg_list(chan->sg, 0,
271 VIRTQUEUE_NUM, req->tc->sdata, req->tc->size); 281 VIRTQUEUE_NUM, req->tc->sdata, req->tc->size);
282 if (out)
283 sgs[out_sgs++] = chan->sg;
272 284
273 in = pack_sg_list(chan->sg, out, 285 in = pack_sg_list(chan->sg, out,
274 VIRTQUEUE_NUM, req->rc->sdata, req->rc->capacity); 286 VIRTQUEUE_NUM, req->rc->sdata, req->rc->capacity);
287 if (in)
288 sgs[out_sgs + in_sgs++] = chan->sg + out;
275 289
276 err = virtqueue_add_buf(chan->vq, chan->sg, out, in, req->tc, 290 err = virtqueue_add_sgs(chan->vq, sgs, out_sgs, in_sgs, req->tc,
277 GFP_ATOMIC); 291 GFP_ATOMIC);
278 if (err < 0) { 292 if (err < 0) {
279 if (err == -ENOSPC) { 293 if (err == -ENOSPC) {
@@ -289,7 +303,7 @@ req_retry:
289 } else { 303 } else {
290 spin_unlock_irqrestore(&chan->lock, flags); 304 spin_unlock_irqrestore(&chan->lock, flags);
291 p9_debug(P9_DEBUG_TRANS, 305 p9_debug(P9_DEBUG_TRANS,
292 "virtio rpc add_buf returned failure\n"); 306 "virtio rpc add_sgs returned failure\n");
293 return -EIO; 307 return -EIO;
294 } 308 }
295 } 309 }
@@ -351,11 +365,12 @@ p9_virtio_zc_request(struct p9_client *client, struct p9_req_t *req,
351 char *uidata, char *uodata, int inlen, 365 char *uidata, char *uodata, int inlen,
352 int outlen, int in_hdr_len, int kern_buf) 366 int outlen, int in_hdr_len, int kern_buf)
353{ 367{
354 int in, out, err; 368 int in, out, err, out_sgs, in_sgs;
355 unsigned long flags; 369 unsigned long flags;
356 int in_nr_pages = 0, out_nr_pages = 0; 370 int in_nr_pages = 0, out_nr_pages = 0;
357 struct page **in_pages = NULL, **out_pages = NULL; 371 struct page **in_pages = NULL, **out_pages = NULL;
358 struct virtio_chan *chan = client->trans; 372 struct virtio_chan *chan = client->trans;
373 struct scatterlist *sgs[4];
359 374
360 p9_debug(P9_DEBUG_TRANS, "virtio request\n"); 375 p9_debug(P9_DEBUG_TRANS, "virtio request\n");
361 376
@@ -396,13 +411,22 @@ p9_virtio_zc_request(struct p9_client *client, struct p9_req_t *req,
396 req->status = REQ_STATUS_SENT; 411 req->status = REQ_STATUS_SENT;
397req_retry_pinned: 412req_retry_pinned:
398 spin_lock_irqsave(&chan->lock, flags); 413 spin_lock_irqsave(&chan->lock, flags);
414
415 out_sgs = in_sgs = 0;
416
399 /* out data */ 417 /* out data */
400 out = pack_sg_list(chan->sg, 0, 418 out = pack_sg_list(chan->sg, 0,
401 VIRTQUEUE_NUM, req->tc->sdata, req->tc->size); 419 VIRTQUEUE_NUM, req->tc->sdata, req->tc->size);
402 420
403 if (out_pages) 421 if (out)
422 sgs[out_sgs++] = chan->sg;
423
424 if (out_pages) {
425 sgs[out_sgs++] = chan->sg + out;
404 out += pack_sg_list_p(chan->sg, out, VIRTQUEUE_NUM, 426 out += pack_sg_list_p(chan->sg, out, VIRTQUEUE_NUM,
405 out_pages, out_nr_pages, uodata, outlen); 427 out_pages, out_nr_pages, uodata, outlen);
428 }
429
406 /* 430 /*
407 * Take care of in data 431 * Take care of in data
408 * For example TREAD have 11. 432 * For example TREAD have 11.
@@ -412,11 +436,17 @@ req_retry_pinned:
412 */ 436 */
413 in = pack_sg_list(chan->sg, out, 437 in = pack_sg_list(chan->sg, out,
414 VIRTQUEUE_NUM, req->rc->sdata, in_hdr_len); 438 VIRTQUEUE_NUM, req->rc->sdata, in_hdr_len);
415 if (in_pages) 439 if (in)
440 sgs[out_sgs + in_sgs++] = chan->sg + out;
441
442 if (in_pages) {
443 sgs[out_sgs + in_sgs++] = chan->sg + out + in;
416 in += pack_sg_list_p(chan->sg, out + in, VIRTQUEUE_NUM, 444 in += pack_sg_list_p(chan->sg, out + in, VIRTQUEUE_NUM,
417 in_pages, in_nr_pages, uidata, inlen); 445 in_pages, in_nr_pages, uidata, inlen);
446 }
418 447
419 err = virtqueue_add_buf(chan->vq, chan->sg, out, in, req->tc, 448 BUG_ON(out_sgs + in_sgs > ARRAY_SIZE(sgs));
449 err = virtqueue_add_sgs(chan->vq, sgs, out_sgs, in_sgs, req->tc,
420 GFP_ATOMIC); 450 GFP_ATOMIC);
421 if (err < 0) { 451 if (err < 0) {
422 if (err == -ENOSPC) { 452 if (err == -ENOSPC) {
@@ -432,7 +462,7 @@ req_retry_pinned:
432 } else { 462 } else {
433 spin_unlock_irqrestore(&chan->lock, flags); 463 spin_unlock_irqrestore(&chan->lock, flags);
434 p9_debug(P9_DEBUG_TRANS, 464 p9_debug(P9_DEBUG_TRANS,
435 "virtio rpc add_buf returned failure\n"); 465 "virtio rpc add_sgs returned failure\n");
436 err = -EIO; 466 err = -EIO;
437 goto err_out; 467 goto err_out;
438 } 468 }