Messages in this thread | | | Subject | Re: [PATCH v5 2/5] firmware: encapsulate firmware loading status | From | Daniel Wagner <> | Date | Wed, 19 Oct 2016 10:05:49 +0200 |
| |
On 10/18/2016 11:54 PM, Luis R. Rodriguez wrote: > On Tue, Oct 18, 2016 at 03:30:45PM +0200, Daniel Wagner wrote: >> On 10/10/2016 10:37 PM, Luis R. Rodriguez wrote: >> >>>> fw_get_fileystem_firmware() >>>> fw_finish_direct_load() >>>> complete_all() >>>> >>>> >>>> 2nd request (waiter context) >>>> >>>> _request_firmware() >>>> _request_firmware_prepare() >>>> fw_lookup_allocate_buf() # finds previously allocated buf >>>> # returns 1 -> wait for loading >>>> sync_cached_firmware_buf() >>>> wait_for_completion_interruptible_timeout() >>> >>> No, that's wait_for_completion_interruptible() not >>> wait_for_completion_interruptible_timeout() >> >> I confused that one from _request_firmware_load(). > > Right and wait_for_completion_interruptible() has no timeout.
All wait_for_completion_*() function are small wrappers around a common implemention. I thought that would be a clever idea to reuse here, but from our discussion I see it isn't. My bad.
static int fw_umh_wait_timeout(struct fw_umh *fw_umh, long timeout) { int ret;
ret = wait_for_completion_interruptible_timeout(&fw_umh->completion, timeout); if (ret != 0 && test_bit(FW_UMH_ABORTED, &fw_umh->status)) return -ENOENT;
return ret; }
long __sched wait_for_completion_interruptible_timeout(struct completion *x, unsigned long timeout) { return wait_for_common(x, timeout, TASK_INTERRUPTIBLE); }
int __sched wait_for_completion_interruptible(struct completion *x) { long t = wait_for_common(x, MAX_SCHEDULE_TIMEOUT, TASK_INTERRUPTIBLE); if (t == -ERESTARTSYS) return t; return 0; }
I think it is far better to do something like:
static __fw_umh_wait_common(struct fw_umh *fw_umh, long timeout) { ... }
#define fw_umh_wait(fw_umh) __fw_umh_wait_common(fw_umh, MAX_SCHEDULE_TIMEOUT) #define fw_umh_wait_timeout(fw_umh, timeout) __fw_umh_wait_common(fw_umh, timeout)
(The function prefixes will be different, since umh isn't right as discussed.)
>>> Also note that we only call sync_cached_firmware_buf() >>> *iff* fw_lookup_and_allocate_buf() returned the 1 -- I mentioned >>> when this happens above. That happens only if we already had the entry on >>> the fw cache. As it stands -- concurrent calls against the same fw name >>> could cause a clash here, as such, the wait_for_completion_interruptible() >>> is indeed still needed. >>> >>> Further optimizations can be considered later but for indeed, agreed >>> that completion is needed even for the direct fw load case. The timeout >>> though, I don't see a reason for it. >> >> So I think I found the source of the confusion about fw_umh_wait_timeout(). >> When providing a timeout value of 0 you get the >> wait_for_completion_interruptible() version. > > I fail to see that, how so? Note that 0 does is not allowed anyway: > > static inline long firmware_loading_timeout(void) > { > return loading_timeout > 0 ? loading_timeout * HZ : MAX_JIFFY_OFFSET; > }
Correct. The fw_umh_wait_timeout(0) is hard coded in sync_cached_firmware_buf(). fw_umh_wait_timeout(fw_umh, firmware_loading_timeout()) is used _request_firmware_load().
I'll update the series and hopefully we get this all sorted out in the new version.
cheers, daniel
| |