Don't use udelay to allow other kernel tasks to execute if the kernel
has been built without preemption. Also determine the timeout based on
jiffies instead of loop iterations.
This is especially important on devices containing a watchdog with a
short timeout. Without this change, the watchdog is not serviced during
PHY patching which can take multiple seconds.
Tested-by: Birger Koblitz <mail@birger-koblitz.de>
Signed-off-by: Jan Hoffmann <jan@3e8.eu>
int rtl838x_smi_wait_op(int timeout)
{
int rtl838x_smi_wait_op(int timeout)
{
- do {
- timeout--;
- udelay(10);
- } while ((sw_r32(RTL838X_SMI_ACCESS_PHY_CTRL_1) & 0x1) && (timeout >= 0));
- if (timeout <= 0)
- return -1;
- return 0;
+ unsigned long end = jiffies + usecs_to_jiffies(timeout);
+
+ while (1) {
+ if (!(sw_r32(RTL838X_SMI_ACCESS_PHY_CTRL_1) & 0x1))
+ return 0;
+
+ if (time_after(jiffies, end))
+ break;
+
+ usleep_range(10, 20);
+ }
+
+ pr_err("rtl838x_smi_wait_op: timeout\n");
+ return -1;
- if (rtl838x_smi_wait_op(10000))
+ if (rtl838x_smi_wait_op(100000))
goto timeout;
sw_w32_mask(0xffff0000, port << 16, RTL838X_SMI_ACCESS_PHY_CTRL_2);
goto timeout;
sw_w32_mask(0xffff0000, port << 16, RTL838X_SMI_ACCESS_PHY_CTRL_2);
sw_w32(v | park_page, RTL838X_SMI_ACCESS_PHY_CTRL_1);
sw_w32_mask(0, 1, RTL838X_SMI_ACCESS_PHY_CTRL_1);
sw_w32(v | park_page, RTL838X_SMI_ACCESS_PHY_CTRL_1);
sw_w32_mask(0, 1, RTL838X_SMI_ACCESS_PHY_CTRL_1);
- if (rtl838x_smi_wait_op(10000))
+ if (rtl838x_smi_wait_op(100000))
goto timeout;
*val = sw_r32(RTL838X_SMI_ACCESS_PHY_CTRL_2) & 0xffff;
goto timeout;
*val = sw_r32(RTL838X_SMI_ACCESS_PHY_CTRL_2) & 0xffff;
return -ENOTSUPP;
mutex_lock(&smi_lock);
return -ENOTSUPP;
mutex_lock(&smi_lock);
- if (rtl838x_smi_wait_op(10000))
+ if (rtl838x_smi_wait_op(100000))
goto timeout;
sw_w32(BIT(port), RTL838X_SMI_ACCESS_PHY_CTRL_0);
goto timeout;
sw_w32(BIT(port), RTL838X_SMI_ACCESS_PHY_CTRL_0);
sw_w32(v | park_page, RTL838X_SMI_ACCESS_PHY_CTRL_1);
sw_w32_mask(0, 1, RTL838X_SMI_ACCESS_PHY_CTRL_1);
sw_w32(v | park_page, RTL838X_SMI_ACCESS_PHY_CTRL_1);
sw_w32_mask(0, 1, RTL838X_SMI_ACCESS_PHY_CTRL_1);
- if (rtl838x_smi_wait_op(10000))
+ if (rtl838x_smi_wait_op(100000))
goto timeout;
mutex_unlock(&smi_lock);
goto timeout;
mutex_unlock(&smi_lock);
- if (rtl838x_smi_wait_op(10000))
+ if (rtl838x_smi_wait_op(100000))
goto timeout;
sw_w32(1 << port, RTL838X_SMI_ACCESS_PHY_CTRL_0);
goto timeout;
sw_w32(1 << port, RTL838X_SMI_ACCESS_PHY_CTRL_0);
v = 1 << 1 | 0 << 2 | 1;
sw_w32(v, RTL838X_SMI_ACCESS_PHY_CTRL_1);
v = 1 << 1 | 0 << 2 | 1;
sw_w32(v, RTL838X_SMI_ACCESS_PHY_CTRL_1);
- if (rtl838x_smi_wait_op(10000))
+ if (rtl838x_smi_wait_op(100000))
goto timeout;
*val = sw_r32(RTL838X_SMI_ACCESS_PHY_CTRL_2) & 0xffff;
goto timeout;
*val = sw_r32(RTL838X_SMI_ACCESS_PHY_CTRL_2) & 0xffff;
val &= 0xffff;
mutex_lock(&smi_lock);
val &= 0xffff;
mutex_lock(&smi_lock);
- if (rtl838x_smi_wait_op(10000))
+ if (rtl838x_smi_wait_op(100000))
goto timeout;
sw_w32(1 << port, RTL838X_SMI_ACCESS_PHY_CTRL_0);
goto timeout;
sw_w32(1 << port, RTL838X_SMI_ACCESS_PHY_CTRL_0);
v = 1 << 1 | 1 << 2 | 1;
sw_w32(v, RTL838X_SMI_ACCESS_PHY_CTRL_1);
v = 1 << 1 | 1 << 2 | 1;
sw_w32(v, RTL838X_SMI_ACCESS_PHY_CTRL_1);
- if (rtl838x_smi_wait_op(10000))
+ if (rtl838x_smi_wait_op(100000))
goto timeout;
mutex_unlock(&smi_lock);
goto timeout;
mutex_unlock(&smi_lock);