On Wed, 27 Jan 2021 at 16:33, Kalle Valo <kvalo@xxxxxxxxxxxxxx> wrote: > ... > Forgot to mention that I can remove the Fixes tags during commit, so no > need to resend just because of those. Cool, thanks. > > I can definitely see how you can reasonably disagree, but I would not > > be comfortable having code that only works because the calling > > conventions of all relevant architectures happen to put the first > > unsigned long argument and the first pointer argument in the same > > register. > > If there's a bug this patch fixes please explain it clearly in the > commit log. But as I read it (though I admit very quickly) I understood > this is just cleanup. Sorry, I'll try again. So the tasklet_struct looks like this: struct tasklet_struct { .. bool use_callback; union { void (*func)(unsigned long); void (*callback)(struct tasklet_struct *); }; unsigned long data; }; ..and the use_callback flag is used like this: if (t->use_callback) t->callback(t); else t->func(t->data); Now commit d3ccc14dfe95 changed the _rtl_rx_work to be of the new callback, not func, type. But it didn't actually set the use_callback flag, and just typecast the _rtl_rx_work function pointer and assigned it to the func member. So _rtl_rx_work is still called as t->func(t->data) even though it was rewritten to be called as t->callback(t). Now 6b8c7574a5f8 set t->data = (unsigned long)t, so calling t->func(t->data) will probably work on most architectures because: a) "unsigned long" and "struct tasklet_struct *" has the same width on all Linux-capable architectures and b) calling t->func(t->data) will put the value from t->data into the same register as the function void _rtl_rx_work(struct tasklet_struct *t) expects to find the pointer t in the C calling conventions used by all relevant architectures. I guess it's debatable weather this is a bug or just ugly code. /Emil