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

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
...@@ -456,18 +456,15 @@ static int virtblk_ioctl(struct block_device *bdev, fmode_t mode, ...@@ -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) static int virtblk_getgeo(struct block_device *bd, struct hd_geometry *geo)
{ {
struct virtio_blk *vblk = bd->bd_disk->private_data; struct virtio_blk *vblk = bd->bd_disk->private_data;
struct virtio_blk_geometry vgeo;
int err;
/* see if the host passed in geometry config */ /* see if the host passed in geometry config */
err = virtio_config_val(vblk->vdev, VIRTIO_BLK_F_GEOMETRY, if (virtio_has_feature(vblk->vdev, VIRTIO_BLK_F_GEOMETRY)) {
offsetof(struct virtio_blk_config, geometry), virtio_cread(vblk->vdev, struct virtio_blk_config,
&vgeo); geometry.cylinders, &geo->cylinders);
virtio_cread(vblk->vdev, struct virtio_blk_config,
if (!err) { geometry.heads, &geo->heads);
geo->heads = vgeo.heads; virtio_cread(vblk->vdev, struct virtio_blk_config,
geo->sectors = vgeo.sectors; geometry.sectors, &geo->sectors);
geo->cylinders = vgeo.cylinders;
} else { } else {
/* some standard values, similar to sd */ /* some standard values, similar to sd */
geo->heads = 1 << 6; geo->heads = 1 << 6;
...@@ -529,8 +526,7 @@ static void virtblk_config_changed_work(struct work_struct *work) ...@@ -529,8 +526,7 @@ static void virtblk_config_changed_work(struct work_struct *work)
goto done; goto done;
/* Host must always specify the capacity. */ /* Host must always specify the capacity. */
vdev->config->get(vdev, offsetof(struct virtio_blk_config, capacity), virtio_cread(vdev, struct virtio_blk_config, capacity, &capacity);
&capacity, sizeof(capacity));
/* If capacity is too big, truncate with warning. */ /* If capacity is too big, truncate with warning. */
if ((sector_t)capacity != capacity) { if ((sector_t)capacity != capacity) {
...@@ -608,8 +604,8 @@ static int virtblk_get_cache_mode(struct virtio_device *vdev) ...@@ -608,8 +604,8 @@ static int virtblk_get_cache_mode(struct virtio_device *vdev)
u8 writeback; u8 writeback;
int err; int err;
err = virtio_config_val(vdev, VIRTIO_BLK_F_CONFIG_WCE, err = virtio_cread_feature(vdev, VIRTIO_BLK_F_CONFIG_WCE,
offsetof(struct virtio_blk_config, wce), struct virtio_blk_config, wce,
&writeback); &writeback);
if (err) if (err)
writeback = virtio_has_feature(vdev, VIRTIO_BLK_F_WCE); writeback = virtio_has_feature(vdev, VIRTIO_BLK_F_WCE);
...@@ -642,7 +638,6 @@ virtblk_cache_type_store(struct device *dev, struct device_attribute *attr, ...@@ -642,7 +638,6 @@ virtblk_cache_type_store(struct device *dev, struct device_attribute *attr,
struct virtio_blk *vblk = disk->private_data; struct virtio_blk *vblk = disk->private_data;
struct virtio_device *vdev = vblk->vdev; struct virtio_device *vdev = vblk->vdev;
int i; int i;
u8 writeback;
BUG_ON(!virtio_has_feature(vblk->vdev, VIRTIO_BLK_F_CONFIG_WCE)); BUG_ON(!virtio_has_feature(vblk->vdev, VIRTIO_BLK_F_CONFIG_WCE));
for (i = ARRAY_SIZE(virtblk_cache_types); --i >= 0; ) for (i = ARRAY_SIZE(virtblk_cache_types); --i >= 0; )
...@@ -652,11 +647,7 @@ virtblk_cache_type_store(struct device *dev, struct device_attribute *attr, ...@@ -652,11 +647,7 @@ virtblk_cache_type_store(struct device *dev, struct device_attribute *attr,
if (i < 0) if (i < 0)
return -EINVAL; return -EINVAL;
writeback = i; virtio_cwrite8(vdev, offsetof(struct virtio_blk_config, wce), i);
vdev->config->set(vdev,
offsetof(struct virtio_blk_config, wce),
&writeback, sizeof(writeback));
virtblk_update_cache_mode(vdev); virtblk_update_cache_mode(vdev);
return count; return count;
} }
...@@ -699,8 +690,8 @@ static int virtblk_probe(struct virtio_device *vdev) ...@@ -699,8 +690,8 @@ static int virtblk_probe(struct virtio_device *vdev)
index = err; index = err;
/* We need to know how many segments before we allocate. */ /* We need to know how many segments before we allocate. */
err = virtio_config_val(vdev, VIRTIO_BLK_F_SEG_MAX, err = virtio_cread_feature(vdev, VIRTIO_BLK_F_SEG_MAX,
offsetof(struct virtio_blk_config, seg_max), struct virtio_blk_config, seg_max,
&sg_elems); &sg_elems);
/* We need at least one SG element, whatever they say. */ /* We need at least one SG element, whatever they say. */
...@@ -772,8 +763,7 @@ static int virtblk_probe(struct virtio_device *vdev) ...@@ -772,8 +763,7 @@ static int virtblk_probe(struct virtio_device *vdev)
set_disk_ro(vblk->disk, 1); set_disk_ro(vblk->disk, 1);
/* Host must always specify the capacity. */ /* Host must always specify the capacity. */
vdev->config->get(vdev, offsetof(struct virtio_blk_config, capacity), virtio_cread(vdev, struct virtio_blk_config, capacity, &cap);
&cap, sizeof(cap));
/* If capacity is too big, truncate with warning. */ /* If capacity is too big, truncate with warning. */
if ((sector_t)cap != cap) { if ((sector_t)cap != cap) {
...@@ -794,17 +784,16 @@ static int virtblk_probe(struct virtio_device *vdev) ...@@ -794,17 +784,16 @@ static int virtblk_probe(struct virtio_device *vdev)
/* Host can optionally specify maximum segment size and number of /* Host can optionally specify maximum segment size and number of
* segments. */ * segments. */
err = virtio_config_val(vdev, VIRTIO_BLK_F_SIZE_MAX, err = virtio_cread_feature(vdev, VIRTIO_BLK_F_SIZE_MAX,
offsetof(struct virtio_blk_config, size_max), struct virtio_blk_config, size_max, &v);
&v);
if (!err) if (!err)
blk_queue_max_segment_size(q, v); blk_queue_max_segment_size(q, v);
else else
blk_queue_max_segment_size(q, -1U); blk_queue_max_segment_size(q, -1U);
/* Host can optionally specify the block size of the device */ /* Host can optionally specify the block size of the device */
err = virtio_config_val(vdev, VIRTIO_BLK_F_BLK_SIZE, err = virtio_cread_feature(vdev, VIRTIO_BLK_F_BLK_SIZE,
offsetof(struct virtio_blk_config, blk_size), struct virtio_blk_config, blk_size,
&blk_size); &blk_size);
if (!err) if (!err)
blk_queue_logical_block_size(q, blk_size); blk_queue_logical_block_size(q, blk_size);
...@@ -812,27 +801,27 @@ static int virtblk_probe(struct virtio_device *vdev) ...@@ -812,27 +801,27 @@ static int virtblk_probe(struct virtio_device *vdev)
blk_size = queue_logical_block_size(q); blk_size = queue_logical_block_size(q);
/* Use topology information if available */ /* Use topology information if available */
err = virtio_config_val(vdev, VIRTIO_BLK_F_TOPOLOGY, err = virtio_cread_feature(vdev, VIRTIO_BLK_F_TOPOLOGY,
offsetof(struct virtio_blk_config, physical_block_exp), struct virtio_blk_config, physical_block_exp,
&physical_block_exp); &physical_block_exp);
if (!err && physical_block_exp) if (!err && physical_block_exp)
blk_queue_physical_block_size(q, blk_queue_physical_block_size(q,
blk_size * (1 << physical_block_exp)); blk_size * (1 << physical_block_exp));
err = virtio_config_val(vdev, VIRTIO_BLK_F_TOPOLOGY, err = virtio_cread_feature(vdev, VIRTIO_BLK_F_TOPOLOGY,
offsetof(struct virtio_blk_config, alignment_offset), struct virtio_blk_config, alignment_offset,
&alignment_offset); &alignment_offset);
if (!err && alignment_offset) if (!err && alignment_offset)
blk_queue_alignment_offset(q, blk_size * alignment_offset); blk_queue_alignment_offset(q, blk_size * alignment_offset);
err = virtio_config_val(vdev, VIRTIO_BLK_F_TOPOLOGY, err = virtio_cread_feature(vdev, VIRTIO_BLK_F_TOPOLOGY,
offsetof(struct virtio_blk_config, min_io_size), struct virtio_blk_config, min_io_size,
&min_io_size); &min_io_size);
if (!err && min_io_size) if (!err && min_io_size)
blk_queue_io_min(q, blk_size * min_io_size); blk_queue_io_min(q, blk_size * min_io_size);
err = virtio_config_val(vdev, VIRTIO_BLK_F_TOPOLOGY, err = virtio_cread_feature(vdev, VIRTIO_BLK_F_TOPOLOGY,
offsetof(struct virtio_blk_config, opt_io_size), struct virtio_blk_config, opt_io_size,
&opt_io_size); &opt_io_size);
if (!err && opt_io_size) if (!err && opt_io_size)
blk_queue_io_opt(q, blk_size * opt_io_size); blk_queue_io_opt(q, blk_size * opt_io_size);
......
...@@ -1837,12 +1837,8 @@ static void config_intr(struct virtio_device *vdev) ...@@ -1837,12 +1837,8 @@ static void config_intr(struct virtio_device *vdev)
struct port *port; struct port *port;
u16 rows, cols; u16 rows, cols;
vdev->config->get(vdev, virtio_cread(vdev, struct virtio_console_config, cols, &cols);
offsetof(struct virtio_console_config, cols), virtio_cread(vdev, struct virtio_console_config, rows, &rows);
&cols, sizeof(u16));
vdev->config->get(vdev,
offsetof(struct virtio_console_config, rows),
&rows, sizeof(u16));
port = find_port_by_id(portdev, 0); port = find_port_by_id(portdev, 0);
set_console_size(port, rows, cols); set_console_size(port, rows, cols);
...@@ -2014,9 +2010,8 @@ static int virtcons_probe(struct virtio_device *vdev) ...@@ -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! */ /* Don't test MULTIPORT at all if we're rproc: not a valid feature! */
if (!is_rproc_serial(vdev) && if (!is_rproc_serial(vdev) &&
virtio_config_val(vdev, VIRTIO_CONSOLE_F_MULTIPORT, virtio_cread_feature(vdev, VIRTIO_CONSOLE_F_MULTIPORT,
offsetof(struct virtio_console_config, struct virtio_console_config, max_nr_ports,
max_nr_ports),
&portdev->config.max_nr_ports) == 0) { &portdev->config.max_nr_ports) == 0) {
multiport = true; multiport = true;
} }
......
...@@ -686,18 +686,19 @@ static int cfv_probe(struct virtio_device *vdev) ...@@ -686,18 +686,19 @@ static int cfv_probe(struct virtio_device *vdev)
goto err; goto err;
/* Get the CAIF configuration from virtio config space, if available */ /* 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) { if (vdev->config->get) {
GET_VIRTIO_CONFIG_OPS(vdev, cfv->tx_hr, headroom); virtio_cread(vdev, struct virtio_caif_transf_config, headroom,
GET_VIRTIO_CONFIG_OPS(vdev, cfv->rx_hr, headroom); &cfv->tx_hr);
GET_VIRTIO_CONFIG_OPS(vdev, cfv->tx_tr, tailroom); virtio_cread(vdev, struct virtio_caif_transf_config, headroom,
GET_VIRTIO_CONFIG_OPS(vdev, cfv->rx_tr, tailroom); &cfv->rx_hr);
GET_VIRTIO_CONFIG_OPS(vdev, cfv->mtu, mtu); virtio_cread(vdev, struct virtio_caif_transf_config, tailroom,
GET_VIRTIO_CONFIG_OPS(vdev, cfv->mru, mtu); &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 { } else {
cfv->tx_hr = CFV_DEF_HEADROOM; cfv->tx_hr = CFV_DEF_HEADROOM;
cfv->rx_hr = CFV_DEF_HEADROOM; cfv->rx_hr = CFV_DEF_HEADROOM;
......
...@@ -852,8 +852,13 @@ static int virtnet_set_mac_address(struct net_device *dev, void *p) ...@@ -852,8 +852,13 @@ static int virtnet_set_mac_address(struct net_device *dev, void *p)
return -EINVAL; return -EINVAL;
} }
} else if (virtio_has_feature(vdev, VIRTIO_NET_F_MAC)) { } else if (virtio_has_feature(vdev, VIRTIO_NET_F_MAC)) {
vdev->config->set(vdev, offsetof(struct virtio_net_config, mac), unsigned int i;
addr->sa_data, dev->addr_len);
/* 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); eth_commit_mac_addr_change(dev, p);
...@@ -1266,9 +1271,8 @@ static void virtnet_config_changed_work(struct work_struct *work) ...@@ -1266,9 +1271,8 @@ static void virtnet_config_changed_work(struct work_struct *work)
if (!vi->config_enable) if (!vi->config_enable)
goto done; goto done;
if (virtio_config_val(vi->vdev, VIRTIO_NET_F_STATUS, if (virtio_cread_feature(vi->vdev, VIRTIO_NET_F_STATUS,
offsetof(struct virtio_net_config, status), struct virtio_net_config, status, &v) < 0)
&v) < 0)
goto done; goto done;
if (v & VIRTIO_NET_S_ANNOUNCE) { if (v & VIRTIO_NET_S_ANNOUNCE) {
...@@ -1490,9 +1494,9 @@ static int virtnet_probe(struct virtio_device *vdev) ...@@ -1490,9 +1494,9 @@ static int virtnet_probe(struct virtio_device *vdev)
u16 max_queue_pairs; u16 max_queue_pairs;
/* Find if host supports multiqueue virtio_net device */ /* Find if host supports multiqueue virtio_net device */
err = virtio_config_val(vdev, VIRTIO_NET_F_MQ, err = virtio_cread_feature(vdev, VIRTIO_NET_F_MQ,
offsetof(struct virtio_net_config, struct virtio_net_config,
max_virtqueue_pairs), &max_queue_pairs); max_virtqueue_pairs, &max_queue_pairs);
/* We need at least 2 queue's */ /* We need at least 2 queue's */
if (err || max_queue_pairs < VIRTIO_NET_CTRL_MQ_VQ_PAIRS_MIN || if (err || max_queue_pairs < VIRTIO_NET_CTRL_MQ_VQ_PAIRS_MIN ||
...@@ -1544,9 +1548,11 @@ static int virtnet_probe(struct virtio_device *vdev) ...@@ -1544,9 +1548,11 @@ static int virtnet_probe(struct virtio_device *vdev)
dev->vlan_features = dev->features; dev->vlan_features = dev->features;
/* Configuration may specify what MAC to use. Otherwise random. */ /* 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), 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); eth_hw_addr_random(dev);
/* Set up our device-specific information */ /* Set up our device-specific information */
......
...@@ -710,19 +710,15 @@ static struct scsi_host_template virtscsi_host_template_multi = { ...@@ -710,19 +710,15 @@ static struct scsi_host_template virtscsi_host_template_multi = {
#define virtscsi_config_get(vdev, fld) \ #define virtscsi_config_get(vdev, fld) \
({ \ ({ \
typeof(((struct virtio_scsi_config *)0)->fld) __val; \ typeof(((struct virtio_scsi_config *)0)->fld) __val; \
vdev->config->get(vdev, \ virtio_cread(vdev, struct virtio_scsi_config, fld, &__val); \
offsetof(struct virtio_scsi_config, fld), \
&__val, sizeof(__val)); \
__val; \ __val; \
}) })
#define virtscsi_config_set(vdev, fld, val) \ #define virtscsi_config_set(vdev, fld, val) \
(void)({ \ do { \
typeof(((struct virtio_scsi_config *)0)->fld) __val = (val); \ typeof(((struct virtio_scsi_config *)0)->fld) __val = (val); \
vdev->config->set(vdev, \ virtio_cwrite(vdev, struct virtio_scsi_config, fld, &__val); \
offsetof(struct virtio_scsi_config, fld), \ } while(0)
&__val, sizeof(__val)); \
})
static void __virtscsi_set_affinity(struct virtio_scsi *vscsi, bool affinity) static void __virtscsi_set_affinity(struct virtio_scsi *vscsi, bool affinity)
{ {
......
...@@ -275,9 +275,8 @@ static inline s64 towards_target(struct virtio_balloon *vb) ...@@ -275,9 +275,8 @@ static inline s64 towards_target(struct virtio_balloon *vb)
__le32 v; __le32 v;
s64 target; s64 target;
vb->vdev->config->get(vb->vdev, virtio_cread(vb->vdev, struct virtio_balloon_config, num_pages, &v);
offsetof(struct virtio_balloon_config, num_pages),
&v, sizeof(v));
target = le32_to_cpu(v); target = le32_to_cpu(v);
return target - vb->num_pages; return target - vb->num_pages;
} }
...@@ -286,9 +285,8 @@ static void update_balloon_size(struct virtio_balloon *vb) ...@@ -286,9 +285,8 @@ static void update_balloon_size(struct virtio_balloon *vb)
{ {
__le32 actual = cpu_to_le32(vb->num_pages); __le32 actual = cpu_to_le32(vb->num_pages);
vb->vdev->config->set(vb->vdev, virtio_cwrite(vb->vdev, struct virtio_balloon_config, num_pages,
offsetof(struct virtio_balloon_config, actual), &actual);
&actual, sizeof(actual));
} }
static int balloon(void *_vballoon) static int balloon(void *_vballoon)
......
...@@ -544,9 +544,7 @@ static int p9_virtio_probe(struct virtio_device *vdev) ...@@ -544,9 +544,7 @@ static int p9_virtio_probe(struct virtio_device *vdev)
chan->inuse = false; chan->inuse = false;
if (virtio_has_feature(vdev, VIRTIO_9P_MOUNT_TAG)) { if (virtio_has_feature(vdev, VIRTIO_9P_MOUNT_TAG)) {
vdev->config->get(vdev, virtio_cread(vdev, struct virtio_9p_config, tag_len, &tag_len);
offsetof(struct virtio_9p_config, tag_len),
&tag_len, sizeof(tag_len));
} else { } else {
err = -EINVAL; err = -EINVAL;
goto out_free_vq; goto out_free_vq;
...@@ -556,7 +554,8 @@ static int p9_virtio_probe(struct virtio_device *vdev) ...@@ -556,7 +554,8 @@ static int p9_virtio_probe(struct virtio_device *vdev)
err = -ENOMEM; err = -ENOMEM;
goto out_free_vq; goto out_free_vq;
} }
vdev->config->get(vdev, offsetof(struct virtio_9p_config, tag),
virtio_cread_bytes(vdev, offsetof(struct virtio_9p_config, tag),
tag, tag_len); tag, tag_len);
chan->tag = tag; chan->tag = tag;
chan->tag_len = tag_len; chan->tag_len = tag_len;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment