Lines Matching +full:scatter +full:- +full:gather

1 // SPDX-License-Identifier: GPL-2.0-only
47 * struct virtio_chan - per-instance transport information
56 * @sg: scatter gather list which is used to pack a request (protected?)
59 * We keep all per-channel information in a structure.
60 * This structure is allocated within the devices dev->mem space.
94 return PAGE_SIZE - offset_in_page(data); in rest_of_page()
98 * p9_virtio_close - reclaim resources of a channel
108 struct virtio_chan *chan = client->trans; in p9_virtio_close()
112 chan->inuse = false; in p9_virtio_close()
117 * req_done - callback which signals activity from the server
121 * on the virtio channel - most likely a response to request we
131 struct virtio_chan *chan = vq->vdev->priv; in req_done()
139 spin_lock_irqsave(&chan->lock, flags); in req_done()
140 while ((req = virtqueue_get_buf(chan->vq, &len)) != NULL) { in req_done()
141 if (!chan->ring_bufs_avail) { in req_done()
142 chan->ring_bufs_avail = 1; in req_done()
147 req->rc.size = len; in req_done()
148 p9_client_cb(chan->client, req, REQ_STATUS_RCVD); in req_done()
151 spin_unlock_irqrestore(&chan->lock, flags); in req_done()
154 wake_up(chan->vc_wq); in req_done()
158 * pack_sg_list - pack a scatter gather list from a linear buffer
159 * @sg: scatter/gather list to pack into
162 * @data: data to pack into scatter/gather list
163 * @count: amount of data to pack into the scatter/gather list
166 * arbitrary data into an existing scatter gather list, segmenting the
185 count -= s; in pack_sg_list()
188 if (index-start) in pack_sg_list()
189 sg_mark_end(&sg[index - 1]); in pack_sg_list()
190 return index-start; in pack_sg_list()
207 * pack_sg_list_p - Just like pack_sg_list. Instead of taking a buffer,
209 * @sg: scatter/gather list to pack into
213 * @nr_pages: number of pages to pack into the scatter/gather list
215 * @count: amount of data to pack into the scatter/gather list
225 BUG_ON(nr_pages > (limit - start)); in pack_sg_list_p()
231 s = PAGE_SIZE - data_off; in pack_sg_list_p()
239 count -= s; in pack_sg_list_p()
240 nr_pages--; in pack_sg_list_p()
243 if (index-start) in pack_sg_list_p()
244 sg_mark_end(&sg[index - 1]); in pack_sg_list_p()
245 return index - start; in pack_sg_list_p()
249 * p9_virtio_request - issue a request
261 struct virtio_chan *chan = client->trans; in p9_virtio_request()
266 req->status = REQ_STATUS_SENT; in p9_virtio_request()
268 spin_lock_irqsave(&chan->lock, flags); in p9_virtio_request()
272 out = pack_sg_list(chan->sg, 0, in p9_virtio_request()
273 VIRTQUEUE_NUM, req->tc.sdata, req->tc.size); in p9_virtio_request()
275 sgs[out_sgs++] = chan->sg; in p9_virtio_request()
277 in = pack_sg_list(chan->sg, out, in p9_virtio_request()
278 VIRTQUEUE_NUM, req->rc.sdata, req->rc.capacity); in p9_virtio_request()
280 sgs[out_sgs + in_sgs++] = chan->sg + out; in p9_virtio_request()
282 err = virtqueue_add_sgs(chan->vq, sgs, out_sgs, in_sgs, req, in p9_virtio_request()
285 if (err == -ENOSPC) { in p9_virtio_request()
286 chan->ring_bufs_avail = 0; in p9_virtio_request()
287 spin_unlock_irqrestore(&chan->lock, flags); in p9_virtio_request()
288 err = wait_event_killable(*chan->vc_wq, in p9_virtio_request()
289 chan->ring_bufs_avail); in p9_virtio_request()
290 if (err == -ERESTARTSYS) in p9_virtio_request()
296 spin_unlock_irqrestore(&chan->lock, flags); in p9_virtio_request()
299 return -EIO; in p9_virtio_request()
302 virtqueue_kick(chan->vq); in p9_virtio_request()
303 spin_unlock_irqrestore(&chan->lock, flags); in p9_virtio_request()
328 if (atomic_read(&vp_pinned) >= chan->p9_max_pages) { in p9_get_mapped_pages()
330 (atomic_read(&vp_pinned) < chan->p9_max_pages)); in p9_get_mapped_pages()
331 if (err == -ERESTARTSYS) in p9_get_mapped_pages()
347 /* we'd already checked that it's non-empty */ in p9_get_mapped_pages()
351 p = data->kvec->iov_base + data->iov_offset; in p9_get_mapped_pages()
359 nr_pages = DIV_ROUND_UP((unsigned long)p + len, PAGE_SIZE) - in p9_get_mapped_pages()
365 return -ENOMEM; in p9_get_mapped_pages()
368 p -= (*offs = offset_in_page(p)); in p9_get_mapped_pages()
385 void *to = req->rc.sdata + in_hdr_len; in handle_rerror()
388 if (req->rc.size < in_hdr_len) in handle_rerror()
395 if (unlikely(req->rc.size > P9_ZC_HDR_SZ)) in handle_rerror()
396 req->rc.size = P9_ZC_HDR_SZ; in handle_rerror()
399 size = req->rc.size - in_hdr_len; in handle_rerror()
400 n = PAGE_SIZE - offs; in handle_rerror()
405 size -= n; in handle_rerror()
411 * p9_virtio_zc_request - issue a zero copy request
430 struct virtio_chan *chan = client->trans; in p9_virtio_zc_request()
449 memcpy(&req->tc.sdata[req->tc.size - 4], &v, 4); in p9_virtio_zc_request()
456 sz = cpu_to_le32(req->tc.size + outlen); in p9_virtio_zc_request()
457 memcpy(&req->tc.sdata[0], &sz, sizeof(sz)); in p9_virtio_zc_request()
468 memcpy(&req->tc.sdata[req->tc.size - 4], &v, 4); in p9_virtio_zc_request()
472 req->status = REQ_STATUS_SENT; in p9_virtio_zc_request()
474 spin_lock_irqsave(&chan->lock, flags); in p9_virtio_zc_request()
479 out = pack_sg_list(chan->sg, 0, in p9_virtio_zc_request()
480 VIRTQUEUE_NUM, req->tc.sdata, req->tc.size); in p9_virtio_zc_request()
483 sgs[out_sgs++] = chan->sg; in p9_virtio_zc_request()
486 sgs[out_sgs++] = chan->sg + out; in p9_virtio_zc_request()
487 out += pack_sg_list_p(chan->sg, out, VIRTQUEUE_NUM, in p9_virtio_zc_request()
498 in = pack_sg_list(chan->sg, out, in p9_virtio_zc_request()
499 VIRTQUEUE_NUM, req->rc.sdata, in_hdr_len); in p9_virtio_zc_request()
501 sgs[out_sgs + in_sgs++] = chan->sg + out; in p9_virtio_zc_request()
504 sgs[out_sgs + in_sgs++] = chan->sg + out + in; in p9_virtio_zc_request()
505 in += pack_sg_list_p(chan->sg, out + in, VIRTQUEUE_NUM, in p9_virtio_zc_request()
510 err = virtqueue_add_sgs(chan->vq, sgs, out_sgs, in_sgs, req, in p9_virtio_zc_request()
513 if (err == -ENOSPC) { in p9_virtio_zc_request()
514 chan->ring_bufs_avail = 0; in p9_virtio_zc_request()
515 spin_unlock_irqrestore(&chan->lock, flags); in p9_virtio_zc_request()
516 err = wait_event_killable(*chan->vc_wq, in p9_virtio_zc_request()
517 chan->ring_bufs_avail); in p9_virtio_zc_request()
518 if (err == -ERESTARTSYS) in p9_virtio_zc_request()
524 spin_unlock_irqrestore(&chan->lock, flags); in p9_virtio_zc_request()
527 err = -EIO; in p9_virtio_zc_request()
531 virtqueue_kick(chan->vq); in p9_virtio_zc_request()
532 spin_unlock_irqrestore(&chan->lock, flags); in p9_virtio_zc_request()
535 err = wait_event_killable(req->wq, req->status >= REQ_STATUS_RCVD); in p9_virtio_zc_request()
537 if (req->status == REQ_STATUS_RCVD && in p9_virtio_zc_request()
538 unlikely(req->rc.sdata[4] == P9_RERROR)) in p9_virtio_zc_request()
574 chan = vdev->priv; in p9_mount_tag_show()
575 tag_len = strlen(chan->tag); in p9_mount_tag_show()
577 memcpy(buf, chan->tag, tag_len + 1); in p9_mount_tag_show()
585 * p9_virtio_probe - probe for existence of 9P virtio channels
599 if (!vdev->config->get) { in p9_virtio_probe()
600 dev_err(&vdev->dev, "%s failure: config access disabled\n", in p9_virtio_probe()
602 return -EINVAL; in p9_virtio_probe()
608 err = -ENOMEM; in p9_virtio_probe()
612 chan->vdev = vdev; in p9_virtio_probe()
615 chan->vq = virtio_find_single_vq(vdev, req_done, "requests"); in p9_virtio_probe()
616 if (IS_ERR(chan->vq)) { in p9_virtio_probe()
617 err = PTR_ERR(chan->vq); in p9_virtio_probe()
620 chan->vq->vdev->priv = chan; in p9_virtio_probe()
621 spin_lock_init(&chan->lock); in p9_virtio_probe()
623 sg_init_table(chan->sg, VIRTQUEUE_NUM); in p9_virtio_probe()
625 chan->inuse = false; in p9_virtio_probe()
629 err = -EINVAL; in p9_virtio_probe()
634 err = -ENOMEM; in p9_virtio_probe()
640 chan->tag = tag; in p9_virtio_probe()
641 err = sysfs_create_file(&(vdev->dev.kobj), &dev_attr_mount_tag.attr); in p9_virtio_probe()
645 chan->vc_wq = kmalloc(sizeof(wait_queue_head_t), GFP_KERNEL); in p9_virtio_probe()
646 if (!chan->vc_wq) { in p9_virtio_probe()
647 err = -ENOMEM; in p9_virtio_probe()
650 init_waitqueue_head(chan->vc_wq); in p9_virtio_probe()
651 chan->ring_bufs_avail = 1; in p9_virtio_probe()
653 chan->p9_max_pages = nr_free_buffer_pages()/4; in p9_virtio_probe()
658 list_add_tail(&chan->chan_list, &virtio_chan_list); in p9_virtio_probe()
662 kobject_uevent(&(vdev->dev.kobj), KOBJ_CHANGE); in p9_virtio_probe()
667 sysfs_remove_file(&vdev->dev.kobj, &dev_attr_mount_tag.attr); in p9_virtio_probe()
671 vdev->config->del_vqs(vdev); in p9_virtio_probe()
680 * p9_virtio_create - allocate a new virtio channel
683 * @args: args passed from sys_mount() for per-transport options (unused)
697 int ret = -ENOENT; in p9_virtio_create()
701 return -EINVAL; in p9_virtio_create()
705 if (!strcmp(devname, chan->tag)) { in p9_virtio_create()
706 if (!chan->inuse) { in p9_virtio_create()
707 chan->inuse = true; in p9_virtio_create()
711 ret = -EBUSY; in p9_virtio_create()
721 client->trans = (void *)chan; in p9_virtio_create()
722 client->status = Connected; in p9_virtio_create()
723 chan->client = client; in p9_virtio_create()
729 * p9_virtio_remove - clean up resources associated with a virtio device
736 struct virtio_chan *chan = vdev->priv; in p9_virtio_remove()
742 list_del(&chan->chan_list); in p9_virtio_remove()
746 while (chan->inuse) { in p9_virtio_remove()
750 dev_emerg(&vdev->dev, in p9_virtio_remove()
760 vdev->config->del_vqs(vdev); in p9_virtio_remove()
762 sysfs_remove_file(&(vdev->dev.kobj), &dev_attr_mount_tag.attr); in p9_virtio_remove()
763 kobject_uevent(&(vdev->dev.kobj), KOBJ_CHANGE); in p9_virtio_remove()
764 kfree(chan->tag); in p9_virtio_remove()
765 kfree(chan->vc_wq); in p9_virtio_remove()
804 .maxsize = PAGE_SIZE * (VIRTQUEUE_NUM - 3),