diff options
author | Halil Pasic <pasic@linux.ibm.com> | 2024-03-07 15:28:09 +0300 |
---|---|---|
committer | Heiko Carstens <hca@linux.ibm.com> | 2024-03-13 11:23:46 +0300 |
commit | 8adc56b074322a0cd03a61418295969f19e5fb0e (patch) | |
tree | 5d8401e5673250f843cdcb94e7914eb9d11c0b29 /drivers/s390 | |
parent | e3e9bda38e6d9f2af50b521741071d6406b40152 (diff) | |
download | linux-8adc56b074322a0cd03a61418295969f19e5fb0e.tar.xz |
s390/virtio_ccw: avoid converting dma addresses / handles
Instead of converting virtual to physical addresses with the virt_to_dma*()
functions, use dma addresses as provided by DMA API and only add offsets to
these addresses. This makes sure that address conversion is only done by
the DMA API.
Signed-off-by: Halil Pasic <pasic@linux.ibm.com>
Reviewed-by: Eric Farman <farman@linux.ibm.com>
Signed-off-by: Heiko Carstens <hca@linux.ibm.com>
Diffstat (limited to 'drivers/s390')
-rw-r--r-- | drivers/s390/virtio/virtio_ccw.c | 71 |
1 files changed, 53 insertions, 18 deletions
diff --git a/drivers/s390/virtio/virtio_ccw.c b/drivers/s390/virtio/virtio_ccw.c index ee9c82721a7e..d7569f395559 100644 --- a/drivers/s390/virtio/virtio_ccw.c +++ b/drivers/s390/virtio/virtio_ccw.c @@ -72,6 +72,7 @@ struct virtio_ccw_device { unsigned int config_ready; void *airq_info; struct vcdev_dma_area *dma_area; + dma32_t dma_area_addr; }; static inline unsigned long *indicators(struct virtio_ccw_device *vcdev) @@ -84,6 +85,36 @@ static inline unsigned long *indicators2(struct virtio_ccw_device *vcdev) return &vcdev->dma_area->indicators2; } +/* Spec stipulates a 64 bit address */ +static inline dma64_t indicators_dma(struct virtio_ccw_device *vcdev) +{ + u64 dma_area_addr = dma32_to_u32(vcdev->dma_area_addr); + + return dma64_add(u64_to_dma64(dma_area_addr), + offsetof(struct vcdev_dma_area, indicators)); +} + +/* Spec stipulates a 64 bit address */ +static inline dma64_t indicators2_dma(struct virtio_ccw_device *vcdev) +{ + u64 dma_area_addr = dma32_to_u32(vcdev->dma_area_addr); + + return dma64_add(u64_to_dma64(dma_area_addr), + offsetof(struct vcdev_dma_area, indicators2)); +} + +static inline dma32_t config_block_dma(struct virtio_ccw_device *vcdev) +{ + return dma32_add(vcdev->dma_area_addr, + offsetof(struct vcdev_dma_area, config_block)); +} + +static inline dma32_t status_dma(struct virtio_ccw_device *vcdev) +{ + return dma32_add(vcdev->dma_area_addr, + offsetof(struct vcdev_dma_area, status)); +} + struct vq_info_block_legacy { dma64_t queue; __u32 align; @@ -157,6 +188,11 @@ static inline u8 *get_summary_indicator(struct airq_info *info) return summary_indicators + info->summary_indicator_idx; } +static inline dma64_t get_summary_indicator_dma(struct airq_info *info) +{ + return virt_to_dma64(get_summary_indicator(info)); +} + #define CCW_CMD_SET_VQ 0x13 #define CCW_CMD_VDEV_RESET 0x33 #define CCW_CMD_SET_IND 0x43 @@ -349,9 +385,9 @@ static void virtio_ccw_drop_indicator(struct virtio_ccw_device *vcdev, struct ccw1 *ccw) { int ret; - unsigned long *indicatorp = NULL; struct virtio_thinint_area *thinint_area = NULL; struct airq_info *airq_info = vcdev->airq_info; + dma64_t *indicatorp = NULL; if (vcdev->is_thinint) { thinint_area = ccw_device_dma_zalloc(vcdev->cdev, @@ -360,20 +396,20 @@ static void virtio_ccw_drop_indicator(struct virtio_ccw_device *vcdev, if (!thinint_area) return; thinint_area->summary_indicator = - virt_to_dma64(get_summary_indicator(airq_info)); + get_summary_indicator_dma(airq_info); thinint_area->isc = VIRTIO_AIRQ_ISC; ccw->cmd_code = CCW_CMD_SET_IND_ADAPTER; ccw->count = sizeof(*thinint_area); } else { /* payload is the address of the indicators */ indicatorp = ccw_device_dma_zalloc(vcdev->cdev, - sizeof(indicators(vcdev)), + sizeof(*indicatorp), &ccw->cda); if (!indicatorp) return; *indicatorp = 0; ccw->cmd_code = CCW_CMD_SET_IND; - ccw->count = sizeof(indicators(vcdev)); + ccw->count = sizeof(*indicatorp); } /* Deregister indicators from host. */ *indicators(vcdev) = 0; @@ -387,7 +423,7 @@ static void virtio_ccw_drop_indicator(struct virtio_ccw_device *vcdev, "Failed to deregister indicators (%d)\n", ret); else if (vcdev->is_thinint) virtio_ccw_drop_indicators(vcdev); - ccw_device_dma_free(vcdev->cdev, indicatorp, sizeof(indicators(vcdev))); + ccw_device_dma_free(vcdev->cdev, indicatorp, sizeof(*indicatorp)); ccw_device_dma_free(vcdev->cdev, thinint_area, sizeof(*thinint_area)); } @@ -427,7 +463,7 @@ static int virtio_ccw_read_vq_conf(struct virtio_ccw_device *vcdev, ccw->cmd_code = CCW_CMD_READ_VQ_CONF; ccw->flags = 0; ccw->count = sizeof(struct vq_config_block); - ccw->cda = virt_to_dma32(&vcdev->dma_area->config_block); + ccw->cda = config_block_dma(vcdev); ret = ccw_io_helper(vcdev, ccw, VIRTIO_CCW_DOING_READ_VQ_CONF); if (ret) return ret; @@ -627,8 +663,7 @@ static int virtio_ccw_register_adapter_ind(struct virtio_ccw_device *vcdev, } thinint_area->indicator = virt_to_dma64(indicator_addr); info = vcdev->airq_info; - thinint_area->summary_indicator = - virt_to_dma64(get_summary_indicator(info)); + thinint_area->summary_indicator = get_summary_indicator_dma(info); thinint_area->isc = VIRTIO_AIRQ_ISC; ccw->cmd_code = CCW_CMD_SET_IND_ADAPTER; ccw->flags = CCW_FLAG_SLI; @@ -689,11 +724,11 @@ static int virtio_ccw_find_vqs(struct virtio_device *vdev, unsigned nvqs, * the address of the indicators. */ indicatorp = ccw_device_dma_zalloc(vcdev->cdev, - sizeof(indicators(vcdev)), + sizeof(*indicatorp), &ccw->cda); if (!indicatorp) goto out; - *indicatorp = virt_to_dma64(indicators(vcdev)); + *indicatorp = indicators_dma(vcdev); if (vcdev->is_thinint) { ret = virtio_ccw_register_adapter_ind(vcdev, vqs, nvqs, ccw); if (ret) @@ -705,30 +740,30 @@ static int virtio_ccw_find_vqs(struct virtio_device *vdev, unsigned nvqs, *indicators(vcdev) = 0; ccw->cmd_code = CCW_CMD_SET_IND; ccw->flags = 0; - ccw->count = sizeof(indicators(vcdev)); + ccw->count = sizeof(*indicatorp); ret = ccw_io_helper(vcdev, ccw, VIRTIO_CCW_DOING_SET_IND); if (ret) goto out; } /* Register indicators2 with host for config changes */ - *indicatorp = virt_to_dma64(indicators2(vcdev)); + *indicatorp = indicators2_dma(vcdev); *indicators2(vcdev) = 0; ccw->cmd_code = CCW_CMD_SET_CONF_IND; ccw->flags = 0; - ccw->count = sizeof(indicators2(vcdev)); + ccw->count = sizeof(*indicatorp); ret = ccw_io_helper(vcdev, ccw, VIRTIO_CCW_DOING_SET_CONF_IND); if (ret) goto out; if (indicatorp) ccw_device_dma_free(vcdev->cdev, indicatorp, - sizeof(indicators(vcdev))); + sizeof(*indicatorp)); ccw_device_dma_free(vcdev->cdev, ccw, sizeof(*ccw)); return 0; out: if (indicatorp) ccw_device_dma_free(vcdev->cdev, indicatorp, - sizeof(indicators(vcdev))); + sizeof(*indicatorp)); ccw_device_dma_free(vcdev->cdev, ccw, sizeof(*ccw)); virtio_ccw_del_vqs(vdev); return ret; @@ -962,7 +997,7 @@ static u8 virtio_ccw_get_status(struct virtio_device *vdev) ccw->cmd_code = CCW_CMD_READ_STATUS; ccw->flags = 0; ccw->count = sizeof(vcdev->dma_area->status); - ccw->cda = virt_to_dma32(&vcdev->dma_area->status); + ccw->cda = status_dma(vcdev); ccw_io_helper(vcdev, ccw, VIRTIO_CCW_DOING_READ_STATUS); /* * If the channel program failed (should only happen if the device @@ -995,7 +1030,7 @@ static void virtio_ccw_set_status(struct virtio_device *vdev, u8 status) * instruction that guarantees the memory writes have * completed before ssch. */ - ccw->cda = virt_to_dma32(&vcdev->dma_area->status); + ccw->cda = status_dma(vcdev); ret = ccw_io_helper(vcdev, ccw, VIRTIO_CCW_DOING_WRITE_STATUS); /* Write failed? We assume status is unchanged. */ if (ret) @@ -1332,7 +1367,7 @@ static int virtio_ccw_online(struct ccw_device *cdev) vcdev->cdev = cdev; vcdev->dma_area = ccw_device_dma_zalloc(vcdev->cdev, sizeof(*vcdev->dma_area), - NULL); + &vcdev->dma_area_addr); if (!vcdev->dma_area) { ret = -ENOMEM; goto out_free; |