Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 855e0c52 authored by Rusty Russell's avatar Rusty Russell
Browse files

virtio: use size-based config accessors.



This lets the transport do endian conversion if necessary, and insulates
the drivers from the difference.

Most drivers can use the simple helpers virtio_cread() and virtio_cwrite().

Signed-off-by: default avatarRusty Russell <rusty@rustcorp.com.au>
parent 0b90d062
Loading
Loading
Loading
Loading
+33 −44
Original line number Diff line number Diff line
@@ -456,18 +456,15 @@ static int virtblk_ioctl(struct block_device *bdev, fmode_t mode,
static int virtblk_getgeo(struct block_device *bd, struct hd_geometry *geo)
{
	struct virtio_blk *vblk = bd->bd_disk->private_data;
	struct virtio_blk_geometry vgeo;
	int err;

	/* see if the host passed in geometry config */
	err = virtio_config_val(vblk->vdev, VIRTIO_BLK_F_GEOMETRY,
				offsetof(struct virtio_blk_config, geometry),
				&vgeo);

	if (!err) {
		geo->heads = vgeo.heads;
		geo->sectors = vgeo.sectors;
		geo->cylinders = vgeo.cylinders;
	if (virtio_has_feature(vblk->vdev, VIRTIO_BLK_F_GEOMETRY)) {
		virtio_cread(vblk->vdev, struct virtio_blk_config,
			     geometry.cylinders, &geo->cylinders);
		virtio_cread(vblk->vdev, struct virtio_blk_config,
			     geometry.heads, &geo->heads);
		virtio_cread(vblk->vdev, struct virtio_blk_config,
			     geometry.sectors, &geo->sectors);
	} else {
		/* some standard values, similar to sd */
		geo->heads = 1 << 6;
@@ -529,8 +526,7 @@ static void virtblk_config_changed_work(struct work_struct *work)
		goto done;

	/* Host must always specify the capacity. */
	vdev->config->get(vdev, offsetof(struct virtio_blk_config, capacity),
			  &capacity, sizeof(capacity));
	virtio_cread(vdev, struct virtio_blk_config, capacity, &capacity);

	/* If capacity is too big, truncate with warning. */
	if ((sector_t)capacity != capacity) {
@@ -608,8 +604,8 @@ static int virtblk_get_cache_mode(struct virtio_device *vdev)
	u8 writeback;
	int err;

	err = virtio_config_val(vdev, VIRTIO_BLK_F_CONFIG_WCE,
				offsetof(struct virtio_blk_config, wce),
	err = virtio_cread_feature(vdev, VIRTIO_BLK_F_CONFIG_WCE,
				   struct virtio_blk_config, wce,
				   &writeback);
	if (err)
		writeback = virtio_has_feature(vdev, VIRTIO_BLK_F_WCE);
@@ -642,7 +638,6 @@ virtblk_cache_type_store(struct device *dev, struct device_attribute *attr,
	struct virtio_blk *vblk = disk->private_data;
	struct virtio_device *vdev = vblk->vdev;
	int i;
	u8 writeback;

	BUG_ON(!virtio_has_feature(vblk->vdev, VIRTIO_BLK_F_CONFIG_WCE));
	for (i = ARRAY_SIZE(virtblk_cache_types); --i >= 0; )
@@ -652,11 +647,7 @@ virtblk_cache_type_store(struct device *dev, struct device_attribute *attr,
	if (i < 0)
		return -EINVAL;

	writeback = i;
	vdev->config->set(vdev,
			  offsetof(struct virtio_blk_config, wce),
			  &writeback, sizeof(writeback));

	virtio_cwrite8(vdev, offsetof(struct virtio_blk_config, wce), i);
	virtblk_update_cache_mode(vdev);
	return count;
}
@@ -699,8 +690,8 @@ static int virtblk_probe(struct virtio_device *vdev)
	index = err;

	/* We need to know how many segments before we allocate. */
	err = virtio_config_val(vdev, VIRTIO_BLK_F_SEG_MAX,
				offsetof(struct virtio_blk_config, seg_max),
	err = virtio_cread_feature(vdev, VIRTIO_BLK_F_SEG_MAX,
				   struct virtio_blk_config, seg_max,
				   &sg_elems);

	/* We need at least one SG element, whatever they say. */
@@ -772,8 +763,7 @@ static int virtblk_probe(struct virtio_device *vdev)
		set_disk_ro(vblk->disk, 1);

	/* Host must always specify the capacity. */
	vdev->config->get(vdev, offsetof(struct virtio_blk_config, capacity),
			  &cap, sizeof(cap));
	virtio_cread(vdev, struct virtio_blk_config, capacity, &cap);

	/* If capacity is too big, truncate with warning. */
	if ((sector_t)cap != cap) {
@@ -794,17 +784,16 @@ static int virtblk_probe(struct virtio_device *vdev)

	/* Host can optionally specify maximum segment size and number of
	 * segments. */
	err = virtio_config_val(vdev, VIRTIO_BLK_F_SIZE_MAX,
				offsetof(struct virtio_blk_config, size_max),
				&v);
	err = virtio_cread_feature(vdev, VIRTIO_BLK_F_SIZE_MAX,
				   struct virtio_blk_config, size_max, &v);
	if (!err)
		blk_queue_max_segment_size(q, v);
	else
		blk_queue_max_segment_size(q, -1U);

	/* Host can optionally specify the block size of the device */
	err = virtio_config_val(vdev, VIRTIO_BLK_F_BLK_SIZE,
				offsetof(struct virtio_blk_config, blk_size),
	err = virtio_cread_feature(vdev, VIRTIO_BLK_F_BLK_SIZE,
				   struct virtio_blk_config, blk_size,
				   &blk_size);
	if (!err)
		blk_queue_logical_block_size(q, blk_size);
@@ -812,27 +801,27 @@ static int virtblk_probe(struct virtio_device *vdev)
		blk_size = queue_logical_block_size(q);

	/* Use topology information if available */
	err = virtio_config_val(vdev, VIRTIO_BLK_F_TOPOLOGY,
			offsetof(struct virtio_blk_config, physical_block_exp),
	err = virtio_cread_feature(vdev, VIRTIO_BLK_F_TOPOLOGY,
				   struct virtio_blk_config, physical_block_exp,
				   &physical_block_exp);
	if (!err && physical_block_exp)
		blk_queue_physical_block_size(q,
				blk_size * (1 << physical_block_exp));

	err = virtio_config_val(vdev, VIRTIO_BLK_F_TOPOLOGY,
			offsetof(struct virtio_blk_config, alignment_offset),
	err = virtio_cread_feature(vdev, VIRTIO_BLK_F_TOPOLOGY,
				   struct virtio_blk_config, alignment_offset,
				   &alignment_offset);
	if (!err && alignment_offset)
		blk_queue_alignment_offset(q, blk_size * alignment_offset);

	err = virtio_config_val(vdev, VIRTIO_BLK_F_TOPOLOGY,
			offsetof(struct virtio_blk_config, min_io_size),
	err = virtio_cread_feature(vdev, VIRTIO_BLK_F_TOPOLOGY,
				   struct virtio_blk_config, min_io_size,
				   &min_io_size);
	if (!err && min_io_size)
		blk_queue_io_min(q, blk_size * min_io_size);

	err = virtio_config_val(vdev, VIRTIO_BLK_F_TOPOLOGY,
			offsetof(struct virtio_blk_config, opt_io_size),
	err = virtio_cread_feature(vdev, VIRTIO_BLK_F_TOPOLOGY,
				   struct virtio_blk_config, opt_io_size,
				   &opt_io_size);
	if (!err && opt_io_size)
		blk_queue_io_opt(q, blk_size * opt_io_size);
+5 −10
Original line number Diff line number Diff line
@@ -1837,12 +1837,8 @@ static void config_intr(struct virtio_device *vdev)
		struct port *port;
		u16 rows, cols;

		vdev->config->get(vdev,
				  offsetof(struct virtio_console_config, cols),
				  &cols, sizeof(u16));
		vdev->config->get(vdev,
				  offsetof(struct virtio_console_config, rows),
				  &rows, sizeof(u16));
		virtio_cread(vdev, struct virtio_console_config, cols, &cols);
		virtio_cread(vdev, struct virtio_console_config, rows, &rows);

		port = find_port_by_id(portdev, 0);
		set_console_size(port, rows, cols);
@@ -2014,9 +2010,8 @@ static int virtcons_probe(struct virtio_device *vdev)

	/* Don't test MULTIPORT at all if we're rproc: not a valid feature! */
	if (!is_rproc_serial(vdev) &&
	    virtio_config_val(vdev, VIRTIO_CONSOLE_F_MULTIPORT,
				  offsetof(struct virtio_console_config,
					   max_nr_ports),
	    virtio_cread_feature(vdev, VIRTIO_CONSOLE_F_MULTIPORT,
				 struct virtio_console_config, max_nr_ports,
				 &portdev->config.max_nr_ports) == 0) {
		multiport = true;
	}
+12 −11
Original line number Diff line number Diff line
@@ -686,18 +686,19 @@ static int cfv_probe(struct virtio_device *vdev)
		goto err;

	/* Get the CAIF configuration from virtio config space, if available */
#define GET_VIRTIO_CONFIG_OPS(_v, _var, _f) \
	((_v)->config->get(_v, offsetof(struct virtio_caif_transf_config, _f), \
			   &_var, \
			   FIELD_SIZEOF(struct virtio_caif_transf_config, _f)))

	if (vdev->config->get) {
		GET_VIRTIO_CONFIG_OPS(vdev, cfv->tx_hr, headroom);
		GET_VIRTIO_CONFIG_OPS(vdev, cfv->rx_hr, headroom);
		GET_VIRTIO_CONFIG_OPS(vdev, cfv->tx_tr, tailroom);
		GET_VIRTIO_CONFIG_OPS(vdev, cfv->rx_tr, tailroom);
		GET_VIRTIO_CONFIG_OPS(vdev, cfv->mtu, mtu);
		GET_VIRTIO_CONFIG_OPS(vdev, cfv->mru, mtu);
		virtio_cread(vdev, struct virtio_caif_transf_config, headroom,
			     &cfv->tx_hr);
		virtio_cread(vdev, struct virtio_caif_transf_config, headroom,
			     &cfv->rx_hr);
		virtio_cread(vdev, struct virtio_caif_transf_config, tailroom,
			     &cfv->tx_tr);
		virtio_cread(vdev, struct virtio_caif_transf_config, tailroom,
			     &cfv->rx_tr);
		virtio_cread(vdev, struct virtio_caif_transf_config, mtu,
			     &cfv->mtu);
		virtio_cread(vdev, struct virtio_caif_transf_config, mtu,
			     &cfv->mru);
	} else {
		cfv->tx_hr = CFV_DEF_HEADROOM;
		cfv->rx_hr = CFV_DEF_HEADROOM;
+17 −11
Original line number Diff line number Diff line
@@ -852,8 +852,13 @@ static int virtnet_set_mac_address(struct net_device *dev, void *p)
			return -EINVAL;
		}
	} else if (virtio_has_feature(vdev, VIRTIO_NET_F_MAC)) {
		vdev->config->set(vdev, offsetof(struct virtio_net_config, mac),
				  addr->sa_data, dev->addr_len);
		unsigned int i;

		/* Naturally, this has an atomicity problem. */
		for (i = 0; i < dev->addr_len; i++)
			virtio_cwrite8(vdev,
				       offsetof(struct virtio_net_config, mac) +
				       i, addr->sa_data[i]);
	}

	eth_commit_mac_addr_change(dev, p);
@@ -1266,9 +1271,8 @@ static void virtnet_config_changed_work(struct work_struct *work)
	if (!vi->config_enable)
		goto done;

	if (virtio_config_val(vi->vdev, VIRTIO_NET_F_STATUS,
			      offsetof(struct virtio_net_config, status),
			      &v) < 0)
	if (virtio_cread_feature(vi->vdev, VIRTIO_NET_F_STATUS,
				 struct virtio_net_config, status, &v) < 0)
		goto done;

	if (v & VIRTIO_NET_S_ANNOUNCE) {
@@ -1490,9 +1494,9 @@ static int virtnet_probe(struct virtio_device *vdev)
	u16 max_queue_pairs;

	/* Find if host supports multiqueue virtio_net device */
	err = virtio_config_val(vdev, VIRTIO_NET_F_MQ,
				offsetof(struct virtio_net_config,
				max_virtqueue_pairs), &max_queue_pairs);
	err = virtio_cread_feature(vdev, VIRTIO_NET_F_MQ,
				   struct virtio_net_config,
				   max_virtqueue_pairs, &max_queue_pairs);

	/* We need at least 2 queue's */
	if (err || max_queue_pairs < VIRTIO_NET_CTRL_MQ_VQ_PAIRS_MIN ||
@@ -1544,9 +1548,11 @@ static int virtnet_probe(struct virtio_device *vdev)
	dev->vlan_features = dev->features;

	/* Configuration may specify what MAC to use.  Otherwise random. */
	if (virtio_config_val_len(vdev, VIRTIO_NET_F_MAC,
	if (virtio_has_feature(vdev, VIRTIO_NET_F_MAC))
		virtio_cread_bytes(vdev,
				   offsetof(struct virtio_net_config, mac),
				  dev->dev_addr, dev->addr_len) < 0)
				   dev->dev_addr, dev->addr_len);
	else
		eth_hw_addr_random(dev);

	/* Set up our device-specific information */
+4 −8
Original line number Diff line number Diff line
@@ -710,19 +710,15 @@ static struct scsi_host_template virtscsi_host_template_multi = {
#define virtscsi_config_get(vdev, fld) \
	({ \
		typeof(((struct virtio_scsi_config *)0)->fld) __val; \
		vdev->config->get(vdev, \
				  offsetof(struct virtio_scsi_config, fld), \
				  &__val, sizeof(__val)); \
		virtio_cread(vdev, struct virtio_scsi_config, fld, &__val); \
		__val; \
	})

#define virtscsi_config_set(vdev, fld, val) \
	(void)({ \
	do { \
		typeof(((struct virtio_scsi_config *)0)->fld) __val = (val); \
		vdev->config->set(vdev, \
				  offsetof(struct virtio_scsi_config, fld), \
				  &__val, sizeof(__val)); \
	})
		virtio_cwrite(vdev, struct virtio_scsi_config, fld, &__val); \
	} while(0)

static void __virtscsi_set_affinity(struct virtio_scsi *vscsi, bool affinity)
{
Loading