net: ethernet: ti: cpsw: fix race condition during open()
authorSekhar Nori <nsekhar@ti.com>
Mon, 3 Apr 2017 12:04:28 +0000 (17:34 +0530)
committerDavid S. Miller <davem@davemloft.net>
Tue, 4 Apr 2017 17:33:33 +0000 (10:33 -0700)
commit30c57f073449e09ae42f908bfff56c08c8751a6f
tree5a1316ef175e9b93befe4eee447c339aa60a8f74
parent249ee819e24c180909f43c1173c8ef6724d21faf
net: ethernet: ti: cpsw: fix race condition during open()

TI's cpsw driver handles both OF and non-OF case for phy
connect. Unfortunately of_phy_connect() returns NULL on
error while phy_connect() returns ERR_PTR().

To handle this, cpsw_slave_open() overrides the return value
from phy_connect() to make it NULL or error.

This leaves a small window, where cpsw_adjust_link() may be
invoked for a slave while slave->phy pointer is temporarily
set to -ENODEV (or some other error) before it is finally set
to NULL.

_cpsw_adjust_link() only handles the NULL case, and an oops
results when ERR_PTR() is seen by it.

Note that cpsw_adjust_link() checks PHY status for each
slave whenever it is invoked. It can so happen that even
though phy_connect() for a given slave returns error,
_cpsw_adjust_link() is still called for that slave because
the link status of another slave changed.

Fix this by using a temporary pointer to store return value
of {of_}phy_connect() and do a one-time write to slave->phy.

Reviewed-by: Grygorii Strashko <grygorii.strashko@ti.com>
Reported-by: Yan Liu <yan-liu@ti.com>
Signed-off-by: Sekhar Nori <nsekhar@ti.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/ti/cpsw.c