Skip to content

Commit cbeb936

Browse files
Sebastian Andrzej Siewiorkelvin-cao
authored andcommitted
pci/switchtec: Replace completion wait queue usage for poll
The poll callback is using the completion wait queue and sticks it into poll_wait() to wake up pollers after a command has completed. This works to some extent, but cannot provide EPOLLEXCLUSIVE support because the waker side uses complete_all() which unconditionally wakes up all waiters. complete_all() is required because completions internally use exclusive wait and complete() only wakes up one waiter by default. This mixes conceptually different mechanisms and relies on internal implementation details of completions, which in turn puts contraints on changing the internal implementation of completions. Replace it with a regular wait queue and store the state in struct switchtec_user. Signed-off-by: Sebastian Andrzej Siewior <[email protected]> Signed-off-by: Thomas Gleixner <[email protected]> Signed-off-by: Peter Zijlstra (Intel) <[email protected]> Reviewed-by: Logan Gunthorpe <[email protected]> Acked-by: Bjorn Helgaas <[email protected]> Acked-by: Peter Zijlstra (Intel) <[email protected]> Link: https://lkml.kernel.org/r/[email protected]
1 parent f4ac050 commit cbeb936

File tree

1 file changed

+13
-9
lines changed

1 file changed

+13
-9
lines changed

switchtec.c

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -64,10 +64,11 @@ struct switchtec_user {
6464

6565
enum mrpc_state state;
6666

67-
struct completion comp;
67+
wait_queue_head_t cmd_comp;
6868
struct kref kref;
6969
struct list_head list;
7070

71+
bool cmd_done;
7172
u32 cmd;
7273
u32 status;
7374
u32 return_code;
@@ -96,7 +97,7 @@ static struct switchtec_user *stuser_create(struct switchtec_dev *stdev)
9697
stuser->stdev = stdev;
9798
kref_init(&stuser->kref);
9899
INIT_LIST_HEAD(&stuser->list);
99-
init_completion(&stuser->comp);
100+
init_waitqueue_head(&stuser->cmd_comp);
100101
stuser->event_cnt = atomic_read(&stdev->event_cnt);
101102

102103
dev_dbg(&stdev->dev, "%s: %p\n", __func__, stuser);
@@ -191,7 +192,7 @@ static int mrpc_queue_cmd(struct switchtec_user *stuser)
191192
kref_get(&stuser->kref);
192193
stuser->read_len = sizeof(stuser->data);
193194
stuser_set_state(stuser, MRPC_QUEUED);
194-
reinit_completion(&stuser->comp);
195+
stuser->cmd_done = false;
195196
list_add_tail(&stuser->list, &stdev->mrpc_queue);
196197

197198
mrpc_cmd_submit(stdev);
@@ -205,7 +206,8 @@ static void mrpc_cleanup_cmd(struct switchtec_dev *stdev)
205206
struct switchtec_user *stuser = list_entry(stdev->mrpc_queue.next,
206207
struct switchtec_user, list);
207208

208-
complete_all(&stuser->comp);
209+
stuser->cmd_done = true;
210+
wake_up_interruptible(&stuser->cmd_comp);
209211
list_del_init(&stuser->list);
210212
stuser_put(stuser);
211213
stdev->mrpc_busy = 0;
@@ -577,10 +579,11 @@ static ssize_t switchtec_dev_read(struct file *filp, char __user *data,
577579
mutex_unlock(&stdev->mrpc_mutex);
578580

579581
if (filp->f_flags & O_NONBLOCK) {
580-
if (!try_wait_for_completion(&stuser->comp))
582+
if (!stuser->cmd_done)
581583
return -EAGAIN;
582584
} else {
583-
rc = wait_for_completion_interruptible(&stuser->comp);
585+
rc = wait_event_interruptible(stuser->cmd_comp,
586+
stuser->cmd_done);
584587
if (rc < 0)
585588
return rc;
586589
}
@@ -634,15 +637,15 @@ static __poll_t switchtec_dev_poll(struct file *filp, poll_table *wait)
634637
struct switchtec_dev *stdev = stuser->stdev;
635638
__poll_t ret = 0;
636639

637-
poll_wait(filp, &stuser->comp.wait, wait);
640+
poll_wait(filp, &stuser->cmd_comp, wait);
638641
poll_wait(filp, &stdev->event_wq, wait);
639642

640643
if (lock_mutex_and_test_alive(stdev))
641644
return EPOLLIN | EPOLLRDHUP | EPOLLOUT | EPOLLERR | EPOLLHUP;
642645

643646
mutex_unlock(&stdev->mrpc_mutex);
644647

645-
if (try_wait_for_completion(&stuser->comp))
648+
if (stuser->cmd_done)
646649
ret |= EPOLLIN | EPOLLRDNORM;
647650

648651
if (stuser->event_cnt != atomic_read(&stdev->event_cnt))
@@ -1328,7 +1331,8 @@ static void stdev_kill(struct switchtec_dev *stdev)
13281331

13291332
/* Wake up and kill any users waiting on an MRPC request */
13301333
list_for_each_entry_safe(stuser, tmpuser, &stdev->mrpc_queue, list) {
1331-
complete_all(&stuser->comp);
1334+
stuser->cmd_done = true;
1335+
wake_up_interruptible(&stuser->cmd_comp);
13321336
list_del_init(&stuser->list);
13331337
stuser_put(stuser);
13341338
}

0 commit comments

Comments
 (0)