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()
381 * p9_virtio_zc_request - issue a zero copy request
400 struct virtio_chan *chan = client->trans; in p9_virtio_zc_request()
419 memcpy(&req->tc.sdata[req->tc.size - 4], &v, 4); in p9_virtio_zc_request()
426 sz = cpu_to_le32(req->tc.size + outlen); in p9_virtio_zc_request()
427 memcpy(&req->tc.sdata[0], &sz, sizeof(sz)); in p9_virtio_zc_request()
438 memcpy(&req->tc.sdata[req->tc.size - 4], &v, 4); in p9_virtio_zc_request()
442 req->status = REQ_STATUS_SENT; in p9_virtio_zc_request()
444 spin_lock_irqsave(&chan->lock, flags); in p9_virtio_zc_request()
449 out = pack_sg_list(chan->sg, 0, in p9_virtio_zc_request()
450 VIRTQUEUE_NUM, req->tc.sdata, req->tc.size); in p9_virtio_zc_request()
453 sgs[out_sgs++] = chan->sg; in p9_virtio_zc_request()
456 sgs[out_sgs++] = chan->sg + out; in p9_virtio_zc_request()
457 out += pack_sg_list_p(chan->sg, out, VIRTQUEUE_NUM, in p9_virtio_zc_request()
468 in = pack_sg_list(chan->sg, out, in p9_virtio_zc_request()
469 VIRTQUEUE_NUM, req->rc.sdata, in_hdr_len); in p9_virtio_zc_request()
471 sgs[out_sgs + in_sgs++] = chan->sg + out; in p9_virtio_zc_request()
474 sgs[out_sgs + in_sgs++] = chan->sg + out + in; in p9_virtio_zc_request()
475 in += pack_sg_list_p(chan->sg, out + in, VIRTQUEUE_NUM, in p9_virtio_zc_request()
480 err = virtqueue_add_sgs(chan->vq, sgs, out_sgs, in_sgs, req, in p9_virtio_zc_request()
483 if (err == -ENOSPC) { in p9_virtio_zc_request()
484 chan->ring_bufs_avail = 0; in p9_virtio_zc_request()
485 spin_unlock_irqrestore(&chan->lock, flags); in p9_virtio_zc_request()
486 err = wait_event_killable(*chan->vc_wq, in p9_virtio_zc_request()
487 chan->ring_bufs_avail); in p9_virtio_zc_request()
488 if (err == -ERESTARTSYS) in p9_virtio_zc_request()
494 spin_unlock_irqrestore(&chan->lock, flags); in p9_virtio_zc_request()
497 err = -EIO; in p9_virtio_zc_request()
501 virtqueue_kick(chan->vq); in p9_virtio_zc_request()
502 spin_unlock_irqrestore(&chan->lock, flags); in p9_virtio_zc_request()
505 err = wait_event_killable(req->wq, req->status >= REQ_STATUS_RCVD); in p9_virtio_zc_request()
539 chan = vdev->priv; in p9_mount_tag_show()
540 tag_len = strlen(chan->tag); in p9_mount_tag_show()
542 memcpy(buf, chan->tag, tag_len + 1); in p9_mount_tag_show()
550 * p9_virtio_probe - probe for existence of 9P virtio channels
564 if (!vdev->config->get) { in p9_virtio_probe()
565 dev_err(&vdev->dev, "%s failure: config access disabled\n", in p9_virtio_probe()
567 return -EINVAL; in p9_virtio_probe()
573 err = -ENOMEM; in p9_virtio_probe()
577 chan->vdev = vdev; in p9_virtio_probe()
580 chan->vq = virtio_find_single_vq(vdev, req_done, "requests"); in p9_virtio_probe()
581 if (IS_ERR(chan->vq)) { in p9_virtio_probe()
582 err = PTR_ERR(chan->vq); in p9_virtio_probe()
585 chan->vq->vdev->priv = chan; in p9_virtio_probe()
586 spin_lock_init(&chan->lock); in p9_virtio_probe()
588 sg_init_table(chan->sg, VIRTQUEUE_NUM); in p9_virtio_probe()
590 chan->inuse = false; in p9_virtio_probe()
594 err = -EINVAL; in p9_virtio_probe()
599 err = -ENOMEM; in p9_virtio_probe()
605 chan->tag = tag; in p9_virtio_probe()
606 err = sysfs_create_file(&(vdev->dev.kobj), &dev_attr_mount_tag.attr); in p9_virtio_probe()
610 chan->vc_wq = kmalloc(sizeof(wait_queue_head_t), GFP_KERNEL); in p9_virtio_probe()
611 if (!chan->vc_wq) { in p9_virtio_probe()
612 err = -ENOMEM; in p9_virtio_probe()
615 init_waitqueue_head(chan->vc_wq); in p9_virtio_probe()
616 chan->ring_bufs_avail = 1; in p9_virtio_probe()
618 chan->p9_max_pages = nr_free_buffer_pages()/4; in p9_virtio_probe()
623 list_add_tail(&chan->chan_list, &virtio_chan_list); in p9_virtio_probe()
627 kobject_uevent(&(vdev->dev.kobj), KOBJ_CHANGE); in p9_virtio_probe()
632 sysfs_remove_file(&vdev->dev.kobj, &dev_attr_mount_tag.attr); in p9_virtio_probe()
636 vdev->config->del_vqs(vdev); in p9_virtio_probe()
645 * p9_virtio_create - allocate a new virtio channel
648 * @args: args passed from sys_mount() for per-transport options (unused)
662 int ret = -ENOENT; in p9_virtio_create()
666 return -EINVAL; in p9_virtio_create()
670 if (!strcmp(devname, chan->tag)) { in p9_virtio_create()
671 if (!chan->inuse) { in p9_virtio_create()
672 chan->inuse = true; in p9_virtio_create()
676 ret = -EBUSY; in p9_virtio_create()
686 client->trans = (void *)chan; in p9_virtio_create()
687 client->status = Connected; in p9_virtio_create()
688 chan->client = client; in p9_virtio_create()
694 * p9_virtio_remove - clean up resources associated with a virtio device
701 struct virtio_chan *chan = vdev->priv; in p9_virtio_remove()
707 list_del(&chan->chan_list); in p9_virtio_remove()
711 while (chan->inuse) { in p9_virtio_remove()
715 dev_emerg(&vdev->dev, in p9_virtio_remove()
724 vdev->config->reset(vdev); in p9_virtio_remove()
725 vdev->config->del_vqs(vdev); in p9_virtio_remove()
727 sysfs_remove_file(&(vdev->dev.kobj), &dev_attr_mount_tag.attr); in p9_virtio_remove()
728 kobject_uevent(&(vdev->dev.kobj), KOBJ_CHANGE); in p9_virtio_remove()
729 kfree(chan->tag); in p9_virtio_remove()
730 kfree(chan->vc_wq); in p9_virtio_remove()
769 .maxsize = PAGE_SIZE * (VIRTQUEUE_NUM - 3),