diff options
Diffstat (limited to 'drivers/misc/mei/bus.c')
| -rw-r--r-- | drivers/misc/mei/bus.c | 67 | 
1 files changed, 64 insertions, 3 deletions
| diff --git a/drivers/misc/mei/bus.c b/drivers/misc/mei/bus.c index 44bac4ad687c..46aa3554e97b 100644 --- a/drivers/misc/mei/bus.c +++ b/drivers/misc/mei/bus.c @@ -643,6 +643,64 @@ static void mei_cl_bus_vtag_free(struct mei_cl_device *cldev)  	kfree(cl_vtag);  } +void *mei_cldev_dma_map(struct mei_cl_device *cldev, u8 buffer_id, size_t size) +{ +	struct mei_device *bus; +	struct mei_cl *cl; +	int ret; + +	if (!cldev || !buffer_id || !size) +		return ERR_PTR(-EINVAL); + +	if (!IS_ALIGNED(size, MEI_FW_PAGE_SIZE)) { +		dev_err(&cldev->dev, "Map size should be aligned to %lu\n", +			MEI_FW_PAGE_SIZE); +		return ERR_PTR(-EINVAL); +	} + +	cl = cldev->cl; +	bus = cldev->bus; + +	mutex_lock(&bus->device_lock); +	if (cl->state == MEI_FILE_UNINITIALIZED) { +		ret = mei_cl_link(cl); +		if (ret) +			goto out; +		/* update pointers */ +		cl->cldev = cldev; +	} + +	ret = mei_cl_dma_alloc_and_map(cl, NULL, buffer_id, size); +out: +	mutex_unlock(&bus->device_lock); +	if (ret) +		return ERR_PTR(ret); +	return cl->dma.vaddr; +} +EXPORT_SYMBOL_GPL(mei_cldev_dma_map); + +int mei_cldev_dma_unmap(struct mei_cl_device *cldev) +{ +	struct mei_device *bus; +	struct mei_cl *cl; +	int ret; + +	if (!cldev) +		return -EINVAL; + +	cl = cldev->cl; +	bus = cldev->bus; + +	mutex_lock(&bus->device_lock); +	ret = mei_cl_dma_unmap(cl, NULL); + +	mei_cl_flush_queues(cl, NULL); +	mei_cl_unlink(cl); +	mutex_unlock(&bus->device_lock); +	return ret; +} +EXPORT_SYMBOL_GPL(mei_cldev_dma_unmap); +  /**   * mei_cldev_enable - enable me client device   *     create connection with me client @@ -753,9 +811,11 @@ int mei_cldev_disable(struct mei_cl_device *cldev)  		dev_err(bus->dev, "Could not disconnect from the ME client\n");  out: -	/* Flush queues and remove any pending read */ -	mei_cl_flush_queues(cl, NULL); -	mei_cl_unlink(cl); +	/* Flush queues and remove any pending read unless we have mapped DMA */ +	if (!cl->dma_mapped) { +		mei_cl_flush_queues(cl, NULL); +		mei_cl_unlink(cl); +	}  	mutex_unlock(&bus->device_lock);  	return err; @@ -1052,6 +1112,7 @@ static void mei_cl_bus_dev_release(struct device *dev)  	if (!cldev)  		return; +	mei_cl_flush_queues(cldev->cl, NULL);  	mei_me_cl_put(cldev->me_cl);  	mei_dev_bus_put(cldev->bus);  	mei_cl_unlink(cldev->cl); |