diff options
author | Francois Romieu <romieu@fr.zoreil.com> | 2011-06-18 02:10:29 +0400 |
---|---|---|
committer | Francois Romieu <romieu@fr.zoreil.com> | 2011-06-18 13:40:48 +0400 |
commit | fd112f2e15ba85d387de446a81aeb11e46ecc55d (patch) | |
tree | eadd165d2d8137220029bf674d456410bd577722 /drivers/net/r8169.c | |
parent | 960aee6c7d5951ac20c0227ad73bad56392f0afc (diff) | |
download | linux-fd112f2e15ba85d387de446a81aeb11e46ecc55d.tar.xz |
r8169: check firmware content sooner.
Firmware checking is only performed when the firmware is loaded
instead of each time the driver inits the phy.
Signed-off-by: Francois Romieu <romieu@fr.zoreil.com>
Diffstat (limited to 'drivers/net/r8169.c')
-rw-r--r-- | drivers/net/r8169.c | 63 |
1 files changed, 44 insertions, 19 deletions
diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c index 7074989d5f75..bc5bb378d008 100644 --- a/drivers/net/r8169.c +++ b/drivers/net/r8169.c @@ -1815,18 +1815,12 @@ out: return rc; } -static void rtl_phy_write_fw(struct rtl8169_private *tp, struct rtl_fw *rtl_fw) +static bool rtl_fw_data_ok(struct rtl8169_private *tp, struct net_device *dev, + struct rtl_fw_phy_action *pa) { - struct rtl_fw_phy_action *pa = &rtl_fw->phy_action; - struct net_device *dev = tp->dev; - u32 predata, count; + bool rc = false; size_t index; - if (!rtl_fw_format_ok(tp, rtl_fw)) { - netif_err(tp, probe, dev, "invalid firwmare\n"); - return; - } - for (index = 0; index < pa->size; index++) { u32 action = le32_to_cpu(pa->code[index]); u32 regno = (action & 0x0fff0000) >> 16; @@ -1844,25 +1838,25 @@ static void rtl_phy_write_fw(struct rtl8169_private *tp, struct rtl_fw *rtl_fw) case PHY_BJMPN: if (regno > index) { - netif_err(tp, probe, tp->dev, + netif_err(tp, ifup, tp->dev, "Out of range of firmware\n"); - return; + goto out; } break; case PHY_READCOUNT_EQ_SKIP: if (index + 2 >= pa->size) { - netif_err(tp, probe, tp->dev, + netif_err(tp, ifup, tp->dev, "Out of range of firmware\n"); - return; + goto out; } break; case PHY_COMP_EQ_SKIPN: case PHY_COMP_NEQ_SKIPN: case PHY_SKIPN: if (index + 1 + regno >= pa->size) { - netif_err(tp, probe, tp->dev, + netif_err(tp, ifup, tp->dev, "Out of range of firmware\n"); - return; + goto out; } break; @@ -1870,14 +1864,39 @@ static void rtl_phy_write_fw(struct rtl8169_private *tp, struct rtl_fw *rtl_fw) case PHY_WRITE_MAC_BYTE: case PHY_WRITE_ERI_WORD: default: - netif_err(tp, probe, tp->dev, + netif_err(tp, ifup, tp->dev, "Invalid action 0x%08x\n", action); - return; + goto out; } } + rc = true; +out: + return rc; +} - predata = 0; - count = 0; +static int rtl_check_firmware(struct rtl8169_private *tp, struct rtl_fw *rtl_fw) +{ + struct net_device *dev = tp->dev; + int rc = -EINVAL; + + if (!rtl_fw_format_ok(tp, rtl_fw)) { + netif_err(tp, ifup, dev, "invalid firwmare\n"); + goto out; + } + + if (rtl_fw_data_ok(tp, dev, &rtl_fw->phy_action)) + rc = 0; +out: + return rc; +} + +static void rtl_phy_write_fw(struct rtl8169_private *tp, struct rtl_fw *rtl_fw) +{ + struct rtl_fw_phy_action *pa = &rtl_fw->phy_action; + u32 predata, count; + size_t index; + + predata = count = 0; for (index = 0; index < pa->size; ) { u32 action = le32_to_cpu(pa->code[index]); @@ -3605,10 +3624,16 @@ static void rtl_request_uncached_firmware(struct rtl8169_private *tp) if (rc < 0) goto err_free; + rc = rtl_check_firmware(tp, rtl_fw); + if (rc < 0) + goto err_release_firmware; + tp->rtl_fw = rtl_fw; out: return; +err_release_firmware: + release_firmware(rtl_fw->fw); err_free: kfree(rtl_fw); err_warn: |