This patch fixes below sparse warning related to __virtio
type in virtio pmem driver. This is reported by Intel test
bot on linux-next tree.
nd_virtio.c:56:28: warning: incorrect type in assignment
                                (different base types)
nd_virtio.c:56:28:    expected unsigned int [unsigned] [usertype] type
nd_virtio.c:56:28:    got restricted __virtio32
nd_virtio.c:93:59: warning: incorrect type in argument 2
                                (different base types)
nd_virtio.c:93:59:    expected restricted __virtio32 [usertype] val
nd_virtio.c:93:59:    got unsigned int [unsigned] [usertype] ret
Reported-by: kbuild test robot <lkp@intel.com>
Signed-off-by: Pankaj Gupta <pagupta@redhat.com>
Acked-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
		
	
			
		
			
				
	
	
		
			126 lines
		
	
	
		
			3.6 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			126 lines
		
	
	
		
			3.6 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| // SPDX-License-Identifier: GPL-2.0
 | |
| /*
 | |
|  * virtio_pmem.c: Virtio pmem Driver
 | |
|  *
 | |
|  * Discovers persistent memory range information
 | |
|  * from host and provides a virtio based flushing
 | |
|  * interface.
 | |
|  */
 | |
| #include "virtio_pmem.h"
 | |
| #include "nd.h"
 | |
| 
 | |
|  /* The interrupt handler */
 | |
| void virtio_pmem_host_ack(struct virtqueue *vq)
 | |
| {
 | |
| 	struct virtio_pmem *vpmem = vq->vdev->priv;
 | |
| 	struct virtio_pmem_request *req_data, *req_buf;
 | |
| 	unsigned long flags;
 | |
| 	unsigned int len;
 | |
| 
 | |
| 	spin_lock_irqsave(&vpmem->pmem_lock, flags);
 | |
| 	while ((req_data = virtqueue_get_buf(vq, &len)) != NULL) {
 | |
| 		req_data->done = true;
 | |
| 		wake_up(&req_data->host_acked);
 | |
| 
 | |
| 		if (!list_empty(&vpmem->req_list)) {
 | |
| 			req_buf = list_first_entry(&vpmem->req_list,
 | |
| 					struct virtio_pmem_request, list);
 | |
| 			req_buf->wq_buf_avail = true;
 | |
| 			wake_up(&req_buf->wq_buf);
 | |
| 			list_del(&req_buf->list);
 | |
| 		}
 | |
| 	}
 | |
| 	spin_unlock_irqrestore(&vpmem->pmem_lock, flags);
 | |
| }
 | |
| EXPORT_SYMBOL_GPL(virtio_pmem_host_ack);
 | |
| 
 | |
|  /* The request submission function */
 | |
| static int virtio_pmem_flush(struct nd_region *nd_region)
 | |
| {
 | |
| 	struct virtio_device *vdev = nd_region->provider_data;
 | |
| 	struct virtio_pmem *vpmem  = vdev->priv;
 | |
| 	struct virtio_pmem_request *req_data;
 | |
| 	struct scatterlist *sgs[2], sg, ret;
 | |
| 	unsigned long flags;
 | |
| 	int err, err1;
 | |
| 
 | |
| 	might_sleep();
 | |
| 	req_data = kmalloc(sizeof(*req_data), GFP_KERNEL);
 | |
| 	if (!req_data)
 | |
| 		return -ENOMEM;
 | |
| 
 | |
| 	req_data->done = false;
 | |
| 	init_waitqueue_head(&req_data->host_acked);
 | |
| 	init_waitqueue_head(&req_data->wq_buf);
 | |
| 	INIT_LIST_HEAD(&req_data->list);
 | |
| 	req_data->req.type = cpu_to_le32(VIRTIO_PMEM_REQ_TYPE_FLUSH);
 | |
| 	sg_init_one(&sg, &req_data->req, sizeof(req_data->req));
 | |
| 	sgs[0] = &sg;
 | |
| 	sg_init_one(&ret, &req_data->resp.ret, sizeof(req_data->resp));
 | |
| 	sgs[1] = &ret;
 | |
| 
 | |
| 	spin_lock_irqsave(&vpmem->pmem_lock, flags);
 | |
| 	 /*
 | |
| 	  * If virtqueue_add_sgs returns -ENOSPC then req_vq virtual
 | |
| 	  * queue does not have free descriptor. We add the request
 | |
| 	  * to req_list and wait for host_ack to wake us up when free
 | |
| 	  * slots are available.
 | |
| 	  */
 | |
| 	while ((err = virtqueue_add_sgs(vpmem->req_vq, sgs, 1, 1, req_data,
 | |
| 					GFP_ATOMIC)) == -ENOSPC) {
 | |
| 
 | |
| 		dev_info(&vdev->dev, "failed to send command to virtio pmem device, no free slots in the virtqueue\n");
 | |
| 		req_data->wq_buf_avail = false;
 | |
| 		list_add_tail(&req_data->list, &vpmem->req_list);
 | |
| 		spin_unlock_irqrestore(&vpmem->pmem_lock, flags);
 | |
| 
 | |
| 		/* A host response results in "host_ack" getting called */
 | |
| 		wait_event(req_data->wq_buf, req_data->wq_buf_avail);
 | |
| 		spin_lock_irqsave(&vpmem->pmem_lock, flags);
 | |
| 	}
 | |
| 	err1 = virtqueue_kick(vpmem->req_vq);
 | |
| 	spin_unlock_irqrestore(&vpmem->pmem_lock, flags);
 | |
| 	/*
 | |
| 	 * virtqueue_add_sgs failed with error different than -ENOSPC, we can't
 | |
| 	 * do anything about that.
 | |
| 	 */
 | |
| 	if (err || !err1) {
 | |
| 		dev_info(&vdev->dev, "failed to send command to virtio pmem device\n");
 | |
| 		err = -EIO;
 | |
| 	} else {
 | |
| 		/* A host repsonse results in "host_ack" getting called */
 | |
| 		wait_event(req_data->host_acked, req_data->done);
 | |
| 		err = le32_to_cpu(req_data->resp.ret);
 | |
| 	}
 | |
| 
 | |
| 	kfree(req_data);
 | |
| 	return err;
 | |
| };
 | |
| 
 | |
| /* The asynchronous flush callback function */
 | |
| int async_pmem_flush(struct nd_region *nd_region, struct bio *bio)
 | |
| {
 | |
| 	/*
 | |
| 	 * Create child bio for asynchronous flush and chain with
 | |
| 	 * parent bio. Otherwise directly call nd_region flush.
 | |
| 	 */
 | |
| 	if (bio && bio->bi_iter.bi_sector != -1) {
 | |
| 		struct bio *child = bio_alloc(GFP_ATOMIC, 0);
 | |
| 
 | |
| 		if (!child)
 | |
| 			return -ENOMEM;
 | |
| 		bio_copy_dev(child, bio);
 | |
| 		child->bi_opf = REQ_PREFLUSH;
 | |
| 		child->bi_iter.bi_sector = -1;
 | |
| 		bio_chain(child, bio);
 | |
| 		submit_bio(child);
 | |
| 		return 0;
 | |
| 	}
 | |
| 	if (virtio_pmem_flush(nd_region))
 | |
| 		return -EIO;
 | |
| 
 | |
| 	return 0;
 | |
| };
 | |
| EXPORT_SYMBOL_GPL(async_pmem_flush);
 | |
| MODULE_LICENSE("GPL");
 |