From mboxrd@z Thu Jan 1 00:00:00 1970 From: Ivan Vecera Subject: Re: [PATCH] r8169: read MAC address from EEPROM on init Date: Fri, 19 Sep 2008 15:05:05 +0200 Message-ID: <48D3A381.1080500@redhat.com> References: <48D25BA2.6070008@redhat.com> Mime-Version: 1.0 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: QUOTED-PRINTABLE Cc: Netdev , Edward Hsu To: =?ISO-8859-1?Q?Ilpo_J=E4rvinen?= , Francois Romieu Return-path: Received: from mx2.redhat.com ([66.187.237.31]:46159 "EHLO mx2.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751373AbYISNIc (ORCPT ); Fri, 19 Sep 2008 09:08:32 -0400 In-Reply-To: Sender: netdev-owner@vger.kernel.org List-ID: Ilpo J=E4rvinen wrote: >> + * is always consecutive 4-byte data starting from the VPD address >> + * specified." >> + */ >> + if (rtl_eeprom_read(tp->pci_dev, vpd_cap, 0x000e, &low) < 0 || >> + rtl_eeprom_read(tp->pci_dev, vpd_cap, 0x0012, &high) < 0) { >> + dprintk("Reading MAC address from EEPROM failed\n"); >> + return; >> + } >> + >> + /* Mask hi-word */ >> + high &=3D 0xffff; >=20 > ..Hmm, and besides fixing sparse printouts, this looks like a real=20 > endianness bug. Yes it is, my mistake. The patch below will be better. --- drivers/net/r8169.c | 74 +++++++++++++++++++++++++++++++++++++++++++= +++++++- 1 files changed, 73 insertions(+), 1 deletions(-) diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c index befc927..cff8dd6 100644 --- a/drivers/net/r8169.c +++ b/drivers/net/r8169.c @@ -1910,6 +1910,75 @@ static void rtl_disable_msi(struct pci_dev *pdev= , struct rtl8169_private *tp) } } +static int rtl_eeprom_read(struct pci_dev *pdev, int cap, int addr, __= le32 *val) +{ + int ret, count =3D 100; + u16 status =3D 0; + u32 value; + + ret =3D pci_write_config_word(pdev, cap + PCI_VPD_ADDR, addr); + if (ret < 0) + return ret; + + do { + udelay(10); + ret =3D pci_read_config_word(pdev, cap + PCI_VPD_ADDR, &status); + if (ret < 0) + return ret; + } while (!(status & PCI_VPD_ADDR_F) && --count); + + if (!(status & PCI_VPD_ADDR_F)) + return -ETIMEDOUT; + + ret =3D pci_read_config_dword(pdev, cap + PCI_VPD_DATA, &value); + if (ret < 0) + return ret; + + *val =3D cpu_to_le32(value); + + return 0; +} + +static void rtl_init_mac_address(struct rtl8169_private *tp, + void __iomem *ioaddr) +{ + struct pci_dev *pdev =3D tp->pci_dev; + u8 cfg1; + int vpd_cap; + u8 mac[8]; + + cfg1 =3D RTL_R8(Config1); + if (!(cfg1 & VPD)) { + dprintk("VPD access not enabled, enabling\n"); + RTL_W8(Cfg9346, Cfg9346_Unlock); + RTL_W8(Config1, cfg1 | VPD); + RTL_W8(Cfg9346, Cfg9346_Lock); + } + + vpd_cap =3D pci_find_capability(pdev, PCI_CAP_ID_VPD); + if (!vpd_cap) + return; + + /* MAC address is stored in EEPROM at offset 0x0e + * Realtek says: "The VPD address does not have to be a DWORD-aligned + * address as defined in the PCI 2.2 Specifications, but the VPD data + * is always consecutive 4-byte data starting from the VPD address + * specified." + */ + if (rtl_eeprom_read(pdev, vpd_cap, 0x000e, (__le32*)&mac[0]) < 0 || + rtl_eeprom_read(pdev, vpd_cap, 0x0012, (__le32*)&mac[4]) < 0) { + dprintk("Reading MAC address from EEPROM failed\n"); + return; + } + + dprintk("MAC address found in EEPROM: " + "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x\n", + mac[0], mac[1], mac[2], mac[3], mac[4], mac[5], mac[6]); + + /* Write MAC address */ + rtl_rar_set(tp, mac); +} + static int __devinit rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent= ) { @@ -2079,7 +2148,10 @@ rtl8169_init_one(struct pci_dev *pdev, const str= uct pci_device_id *ent) dev->do_ioctl =3D rtl8169_ioctl; } - /* Get MAC address. FIXME: read EEPROM */ + /* Read MAC address from EEPROM */ + rtl_init_mac_address(tp, ioaddr); + + /* Get MAC address */ for (i =3D 0; i < MAC_ADDR_LEN; i++) dev->dev_addr[i] =3D RTL_R8(MAC0 + i); memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);