forked from Minki/linux
iommu/amd: Reduce delay waiting for command buffer space
Currently if there is no room to add a command to the command buffer, the driver performs a "completion wait" which only returns when all commands on the queue have been processed. There is no need to wait for the entire command queue to be executed before adding the next command. Update the driver to perform the same udelay() loop that the "completion wait" performs, but instead re-read the head pointer to determine if sufficient space is available. The very first time it is found that there is no space available, the udelay() will be skipped to immediately perform the opportunistic read of the head pointer. If it is still found that there is not sufficient space, then the udelay() will be performed. Signed-off-by: Leo Duran <leo.duran@amd.com> Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com> Signed-off-by: Joerg Roedel <jroedel@suse.de>
This commit is contained in:
parent
d334a5637d
commit
23e967e17c
@ -1045,7 +1045,7 @@ static int __iommu_queue_command_sync(struct amd_iommu *iommu,
|
||||
struct iommu_cmd *cmd,
|
||||
bool sync)
|
||||
{
|
||||
bool read_head = true;
|
||||
unsigned int count = 0;
|
||||
u32 left, next_tail;
|
||||
|
||||
next_tail = (iommu->cmd_buf_tail + sizeof(*cmd)) % CMD_BUFFER_SIZE;
|
||||
@ -1053,33 +1053,26 @@ again:
|
||||
left = (iommu->cmd_buf_head - next_tail) % CMD_BUFFER_SIZE;
|
||||
|
||||
if (left <= 0x20) {
|
||||
struct iommu_cmd sync_cmd;
|
||||
int ret;
|
||||
/* Skip udelay() the first time around */
|
||||
if (count++) {
|
||||
if (count == LOOP_TIMEOUT) {
|
||||
pr_err("AMD-Vi: Command buffer timeout\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if (read_head) {
|
||||
/* Update head and recheck remaining space */
|
||||
iommu->cmd_buf_head = readl(iommu->mmio_base +
|
||||
MMIO_CMD_HEAD_OFFSET);
|
||||
read_head = false;
|
||||
goto again;
|
||||
udelay(1);
|
||||
}
|
||||
|
||||
read_head = true;
|
||||
|
||||
iommu->cmd_sem = 0;
|
||||
|
||||
build_completion_wait(&sync_cmd, (u64)&iommu->cmd_sem);
|
||||
copy_cmd_to_buffer(iommu, &sync_cmd);
|
||||
|
||||
if ((ret = wait_on_sem(&iommu->cmd_sem)) != 0)
|
||||
return ret;
|
||||
/* Update head and recheck remaining space */
|
||||
iommu->cmd_buf_head = readl(iommu->mmio_base +
|
||||
MMIO_CMD_HEAD_OFFSET);
|
||||
|
||||
goto again;
|
||||
}
|
||||
|
||||
copy_cmd_to_buffer(iommu, cmd);
|
||||
|
||||
/* We need to sync now to make sure all commands are processed */
|
||||
/* Do we need to make sure all commands are processed? */
|
||||
iommu->need_sync = sync;
|
||||
|
||||
return 0;
|
||||
|
Loading…
Reference in New Issue
Block a user