mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
synced 2025-01-04 04:02:26 +00:00
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>
This commit is contained in:
parent
e3e9bda38e
commit
8adc56b074
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user