From patchwork Fri Sep 19 13:05:05 2008 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Ivan Vecera X-Patchwork-Id: 620 X-Patchwork-Delegate: jgarzik@pobox.com Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.176.167]) by ozlabs.org (Postfix) with ESMTP id 4943DDDFD2 for ; Fri, 19 Sep 2008 23:08:43 +1000 (EST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753293AbYISNId (ORCPT ); Fri, 19 Sep 2008 09:08:33 -0400 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S1751023AbYISNId (ORCPT ); Fri, 19 Sep 2008 09:08:33 -0400 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 Received: from int-mx2.corp.redhat.com (int-mx2.corp.redhat.com [172.16.27.26]) by mx2.redhat.com (8.13.8/8.13.8) with ESMTP id m8JD5Je4011879; Fri, 19 Sep 2008 09:05:39 -0400 Received: from ns3.rdu.redhat.com (ns3.rdu.redhat.com [10.11.255.199]) by int-mx2.corp.redhat.com (8.13.1/8.13.1) with ESMTP id m8JD57qZ019801; Fri, 19 Sep 2008 09:05:08 -0400 Received: from [10.32.4.22] (vpn-4-22.str.redhat.com [10.32.4.22]) by ns3.rdu.redhat.com (8.13.8/8.13.8) with ESMTP id m8JD53e9028246; Fri, 19 Sep 2008 09:05:04 -0400 Message-ID: <48D3A381.1080500@redhat.com> Date: Fri, 19 Sep 2008 15:05:05 +0200 From: Ivan Vecera User-Agent: Thunderbird 2.0.0.16 (X11/20080724) MIME-Version: 1.0 To: =?ISO-8859-1?Q?Ilpo_J=E4rvinen?= , Francois Romieu CC: Netdev , Edward Hsu Subject: Re: [PATCH] r8169: read MAC address from EEPROM on init References: <48D25BA2.6070008@redhat.com> In-Reply-To: X-Enigmail-Version: 0.95.0 X-Scanned-By: MIMEDefang 2.58 on 172.16.27.26 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Ilpo Järvinen 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 &= 0xffff; > > ..Hmm, and besides fixing sparse printouts, this looks like a real > endianness bug. Yes it is, my mistake. The patch below will be better. Reviewed-by: Ilpo Järvinen 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 = 100; + u16 status = 0; + u32 value; + + ret = pci_write_config_word(pdev, cap + PCI_VPD_ADDR, addr); + if (ret < 0) + return ret; + + do { + udelay(10); + ret = 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 = pci_read_config_dword(pdev, cap + PCI_VPD_DATA, &value); + if (ret < 0) + return ret; + + *val = cpu_to_le32(value); + + return 0; +} + +static void rtl_init_mac_address(struct rtl8169_private *tp, + void __iomem *ioaddr) +{ + struct pci_dev *pdev = tp->pci_dev; + u8 cfg1; + int vpd_cap; + u8 mac[8]; + + cfg1 = 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 = 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 struct pci_device_id *ent) dev->do_ioctl = rtl8169_ioctl; } - /* Get MAC address. FIXME: read EEPROM */ + /* Read MAC address from EEPROM */ + rtl_init_mac_address(tp, ioaddr); + + /* Get MAC address */ for (i = 0; i < MAC_ADDR_LEN; i++) dev->dev_addr[i] = RTL_R8(MAC0 + i); memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);