Skip to content

Commit

Permalink
Merge branch 'davem.r8169' of git://git.kernel.org/pub/scm/linux/kern…
Browse files Browse the repository at this point in the history
…el/git/romieu/netdev-2.6
  • Loading branch information
David S. Miller committed Apr 24, 2011
2 parents e39aece + 953a12c commit 9ac067a
Showing 1 changed file with 71 additions and 28 deletions.
99 changes: 71 additions & 28 deletions drivers/net/r8169.c
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,16 @@ static const struct {
};
#undef _R

static const struct rtl_firmware_info {
int mac_version;
const char *fw_name;
} rtl_firmware_infos[] = {
{ .mac_version = RTL_GIGA_MAC_VER_25, .fw_name = FIRMWARE_8168D_1 },
{ .mac_version = RTL_GIGA_MAC_VER_26, .fw_name = FIRMWARE_8168D_2 },
{ .mac_version = RTL_GIGA_MAC_VER_29, .fw_name = FIRMWARE_8105E_1 },
{ .mac_version = RTL_GIGA_MAC_VER_30, .fw_name = FIRMWARE_8105E_1 }
};

enum cfg_version {
RTL_CFG_0 = 0x00,
RTL_CFG_1,
Expand Down Expand Up @@ -565,6 +575,7 @@ struct rtl8169_private {
u32 saved_wolopts;

const struct firmware *fw;
#define RTL_FIRMWARE_UNKNOWN ERR_PTR(-EAGAIN);
};

MODULE_AUTHOR("Realtek and the Linux r8169 crew <netdev@vger.kernel.org>");
Expand Down Expand Up @@ -1789,25 +1800,26 @@ rtl_phy_write_fw(struct rtl8169_private *tp, const struct firmware *fw)

static void rtl_release_firmware(struct rtl8169_private *tp)
{
release_firmware(tp->fw);
tp->fw = NULL;
if (!IS_ERR_OR_NULL(tp->fw))
release_firmware(tp->fw);
tp->fw = RTL_FIRMWARE_UNKNOWN;
}

static int rtl_apply_firmware(struct rtl8169_private *tp, const char *fw_name)
static void rtl_apply_firmware(struct rtl8169_private *tp)
{
const struct firmware **fw = &tp->fw;
int rc = !*fw;

if (rc) {
rc = request_firmware(fw, fw_name, &tp->pci_dev->dev);
if (rc < 0)
goto out;
}
const struct firmware *fw = tp->fw;

/* TODO: release firmware once rtl_phy_write_fw signals failures. */
rtl_phy_write_fw(tp, *fw);
out:
return rc;
if (!IS_ERR_OR_NULL(fw))
rtl_phy_write_fw(tp, fw);
}

static void rtl_apply_firmware_cond(struct rtl8169_private *tp, u8 reg, u16 val)
{
if (rtl_readphy(tp, reg) != val)
netif_warn(tp, hw, tp->dev, "chipset not ready for firmware\n");
else
rtl_apply_firmware(tp);
}

static void rtl8169s_hw_phy_config(struct rtl8169_private *tp)
Expand Down Expand Up @@ -2246,10 +2258,8 @@ static void rtl8168d_1_hw_phy_config(struct rtl8169_private *tp)

rtl_writephy(tp, 0x1f, 0x0005);
rtl_writephy(tp, 0x05, 0x001b);
if ((rtl_readphy(tp, 0x06) != 0xbf00) ||
(rtl_apply_firmware(tp, FIRMWARE_8168D_1) < 0)) {
netif_warn(tp, probe, tp->dev, "unable to apply firmware patch\n");
}

rtl_apply_firmware_cond(tp, MII_EXPANSION, 0xbf00);

rtl_writephy(tp, 0x1f, 0x0000);
}
Expand Down Expand Up @@ -2351,10 +2361,8 @@ static void rtl8168d_2_hw_phy_config(struct rtl8169_private *tp)

rtl_writephy(tp, 0x1f, 0x0005);
rtl_writephy(tp, 0x05, 0x001b);
if ((rtl_readphy(tp, 0x06) != 0xb300) ||
(rtl_apply_firmware(tp, FIRMWARE_8168D_2) < 0)) {
netif_warn(tp, probe, tp->dev, "unable to apply firmware patch\n");
}

rtl_apply_firmware_cond(tp, MII_EXPANSION, 0xb300);

rtl_writephy(tp, 0x1f, 0x0000);
}
Expand Down Expand Up @@ -2474,8 +2482,7 @@ static void rtl8105e_hw_phy_config(struct rtl8169_private *tp)
rtl_writephy(tp, 0x18, 0x0310);
msleep(100);

if (rtl_apply_firmware(tp, FIRMWARE_8105E_1) < 0)
netif_warn(tp, probe, tp->dev, "unable to apply firmware patch\n");
rtl_apply_firmware(tp);

rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
}
Expand Down Expand Up @@ -3237,6 +3244,8 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
tp->timer.data = (unsigned long) dev;
tp->timer.function = rtl8169_phy_timer;

tp->fw = RTL_FIRMWARE_UNKNOWN;

rc = register_netdev(dev);
if (rc < 0)
goto err_out_msi_4;
Expand Down Expand Up @@ -3288,10 +3297,10 @@ static void __devexit rtl8169_remove_one(struct pci_dev *pdev)

cancel_delayed_work_sync(&tp->task);

rtl_release_firmware(tp);

unregister_netdev(dev);

rtl_release_firmware(tp);

if (pci_dev_run_wake(pdev))
pm_runtime_get_noresume(&pdev->dev);

Expand All @@ -3303,6 +3312,37 @@ static void __devexit rtl8169_remove_one(struct pci_dev *pdev)
pci_set_drvdata(pdev, NULL);
}

static void rtl_request_firmware(struct rtl8169_private *tp)
{
int i;

/* Return early if the firmware is already loaded / cached. */
if (!IS_ERR(tp->fw))
goto out;

for (i = 0; i < ARRAY_SIZE(rtl_firmware_infos); i++) {
const struct rtl_firmware_info *info = rtl_firmware_infos + i;

if (info->mac_version == tp->mac_version) {
const char *name = info->fw_name;
int rc;

rc = request_firmware(&tp->fw, name, &tp->pci_dev->dev);
if (rc < 0) {
netif_warn(tp, ifup, tp->dev, "unable to load "
"firmware patch %s (%d)\n", name, rc);
goto out_disable_request_firmware;
}
goto out;
}
}

out_disable_request_firmware:
tp->fw = NULL;
out:
return;
}

static int rtl8169_open(struct net_device *dev)
{
struct rtl8169_private *tp = netdev_priv(dev);
Expand Down Expand Up @@ -3334,11 +3374,13 @@ static int rtl8169_open(struct net_device *dev)

smp_mb();

rtl_request_firmware(tp);

retval = request_irq(dev->irq, rtl8169_interrupt,
(tp->features & RTL_FEATURE_MSI) ? 0 : IRQF_SHARED,
dev->name, dev);
if (retval < 0)
goto err_release_ring_2;
goto err_release_fw_2;

napi_enable(&tp->napi);

Expand All @@ -3359,7 +3401,8 @@ static int rtl8169_open(struct net_device *dev)
out:
return retval;

err_release_ring_2:
err_release_fw_2:
rtl_release_firmware(tp);
rtl8169_rx_clear(tp);
err_free_rx_1:
dma_free_coherent(&pdev->dev, R8169_RX_RING_BYTES, tp->RxDescArray,
Expand Down

0 comments on commit 9ac067a

Please sign in to comment.