+ int count = preempt_count();
+ ktime_t calltime, delta, rettime;
+ char msgbuf[64];
+ struct boot_trace_call call;
+ struct boot_trace_ret ret;
+
+ if (initcall_debug) {
+ call.caller = task_pid_nr(current);
+ printk("calling %pF @ %i\n", fn, call.caller);
+ calltime = ktime_get();
+ trace_boot_call(&call, fn);
+ enable_boot_trace();
+ }
+
+ ret.result = fn();
+
+ if (initcall_debug) {
+ disable_boot_trace();
+ rettime = ktime_get();
+ delta = ktime_sub(rettime, calltime);
+ ret.duration = (unsigned long long) ktime_to_ns(delta) >> 10;
+ trace_boot_ret(&ret, fn);
+ printk("initcall %pF returned %d after %Ld usecs\n", fn,
+ ret.result, ret.duration);
+ }
+
+ msgbuf[0] = 0;
+
+ if (ret.result && ret.result != -ENODEV && initcall_debug)
+ sprintf(msgbuf, "error code %d ", ret.result);
+
+ if (preempt_count() != count) {
+ strlcat(msgbuf, "preemption imbalance ", sizeof(msgbuf));
+ preempt_count() = count;
+ }
+ if (irqs_disabled()) {
+ strlcat(msgbuf, "disabled interrupts ", sizeof(msgbuf));
+ local_irq_enable();
+ }
+ if (msgbuf[0]) {
+ printk("initcall %pF returned with %s\n", fn, msgbuf);
+ }
+
+ return ret.result;