tty: max3100: Fix oops while 'cat/proc/tty/driver/ttyMAX'
Quoted 7 lines · On 09/15/2018, 04:14 AM, [email protected] wrote:
yes, creation and destroy of the workqueue is not locked, I think maybe there is some
remainder work to do in destroy-wq, so I cannot sure if there is any usage about lock destroy-wq.
Quoted 8 lines
What you worried of the races is about this ?
--> when max3100_shutdown, destroy_workqueue is doing, s->workqueue is not NULL, at this moment, get_mctrl is executed, destroying wq is queued again.
bu this cannot happen, becasue s->force_end_work = 1 before destroy_workqueue , so max3100_dowork do nothing.
Oh, so this relies on flush_workqueue or destroy_workqueue to be a barrier (so that the assignment to end_work is not reordered), correct?
Quoted 28 lines
static void
max3100_shutdown(struct uart_port *port){
...
s->force_end_work= 1;if (
s->poll_time> 0)
del_timer_sync(&s->timer);if (
s->workqueue) {
flush_workqueue(s->workqueue);
destroy_workqueue(s->workqueue);
s->workqueue= NULL;}
static void
max3100_dowork(struct max3100_port *s)
Quoted 7 lines
{
if (!s->force_end_work && !freezing(current) && !s->suspending)
queue_work(s->workqueue, &s->work);}
Also, on the first open:
s->force_end_work = 0;
s->parity = 0;
s->rts = 0;
sprintf(b, "max3100-%d", s->minor);
s->workqueue = create_freezable_workqueue(b);
if (!s->workqueue) {
dev_warn(&s->spi->dev, "cannot create workqueue\n");
return -EBUSY;
}Here, s->force_end_work is 0, s->workqueue is non-NULL, but s->work is garbage until:
INIT_WORK(&s->work, max3100_work);
INIT_WORK should be in max3100_probe as far as I can see (or at least before create_freezable_workqueue), right? But those variable assignments also rely on some implicit barrier which is not there.
thanks,
Signature · 2 lines
js suse labs