From patchwork Mon Sep 13 15:52:23 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kyle Moffett X-Patchwork-Id: 71845 Return-Path: X-Original-To: wd@gemini.denx.de Delivered-To: wd@gemini.denx.de Received: from diddl.denx.de (diddl.denx.de [10.0.0.6]) by gemini.denx.de (Postfix) with ESMTP id 88EB715242D for ; Mon, 13 Sep 2010 17:54:19 +0200 (CEST) Received: from diddl.denx.de (localhost.localdomain [127.0.0.1]) by diddl.denx.de (Postfix) with ESMTP id 72D8731463C1 for ; Mon, 13 Sep 2010 17:54:19 +0200 (MEST) Received: from pop.mnet-online.de by diddl.denx.de with POP3 (fetchmail-6.3.17) for (single-drop); Mon, 13 Sep 2010 17:54:19 +0200 (MEST) Received: from murder ([192.168.6.180]) by backend2 (Cyrus v2.2.12) with LMTPA; Mon, 13 Sep 2010 17:53:23 +0200 X-Sieve: CMU Sieve 2.2 Received: from mail.m-online.net (localhost [127.0.0.1]) by frontend3.mail.m-online.net (Cyrus v2.2.12) with LMTPA; Mon, 13 Sep 2010 17:53:23 +0200 Received: from scanner-4.m-online.net (scanner-4.mail.m-online.net [192.168.1.18]) by mail.m-online.net (Postfix) with ESMTP id 8983A1C000B2; Mon, 13 Sep 2010 17:53:23 +0200 (CEST) Received: from mxin-1.m-online.net ([192.168.6.164]) by scanner-4.m-online.net (scanner-4.m-online.net [192.168.1.18]) (amavisd-new, port 10026) with ESMTP id 00336-04-3; Mon, 13 Sep 2010 17:53:21 +0200 (CEST) Received: from theia.denx.de (theia.denx.de [85.214.87.163]) by mxin-1.m-online.net (Postfix) with ESMTP id 352D646C0AB; Mon, 13 Sep 2010 17:53:21 +0200 (CEST) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 0CEE1280C6; Mon, 13 Sep 2010 17:52:50 +0200 (CEST) Received: from theia.denx.de ([127.0.0.1]) by localhost (theia.denx.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id i+G4LDam7Anv; Mon, 13 Sep 2010 17:52:49 +0200 (CEST) Received: from theia.denx.de (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 692AB280CE; Mon, 13 Sep 2010 17:52:38 +0200 (CEST) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 7B510280CE for ; Mon, 13 Sep 2010 17:52:35 +0200 (CEST) Received: from theia.denx.de ([127.0.0.1]) by localhost (theia.denx.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id AgI5VMDQ9ImB for ; Mon, 13 Sep 2010 17:52:34 +0200 (CEST) X-policyd-weight: NOT_IN_SBL_XBL_SPAMHAUS=-1.5 NOT_IN_SPAMCOP=-1.5 NOT_IN_BL_NJABL=-1.5 (only DNSBL check requested) Received: from firewall1 (wsip-70-167-241-26.dc.dc.cox.net [70.167.241.26]) by theia.denx.de (Postfix) with ESMTP id 084822807E for ; Mon, 13 Sep 2010 17:52:32 +0200 (CEST) Received: from eternium.exmeritus.com (firewall2.exmeritus.com [10.13.38.2]) by firewall1 (Postfix) with ESMTP id D305DAC07D; Mon, 13 Sep 2010 11:52:31 -0400 (EDT) From: Kyle Moffett To: u-boot@lists.denx.de Date: Mon, 13 Sep 2010 11:52:23 -0400 Message-Id: <1284393146-22142-2-git-send-email-Kyle.D.Moffett@boeing.com> X-Mailer: git-send-email 1.7.1 In-Reply-To: <1284393146-22142-1-git-send-email-Kyle.D.Moffett@boeing.com> References: <1284393146-22142-1-git-send-email-Kyle.D.Moffett@boeing.com> Cc: Kyle Moffett , Kyle Moffett , Ben Warren Subject: [U-Boot] [PATCH 2/5] e1000: Restructure and streamline PCI device probing X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.9 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: u-boot-bounces@lists.denx.de Errors-To: u-boot-bounces@lists.denx.de X-Virus-Scanned: by amavisd-new at m-online.net By allocating the e1000 device structures much earlier, we can easily generate better error messages and siginficantly clean things up. The only user-visable change (aside from reworded error messages) is that a detected e1000 device which fails to initialize due to software or hardware error will still be allocated a device number. As one example, consider a system with 2 e1000 PCI devices where the first controller has a corrupted EEPROM. Using the old code the second controller would be "e1000#0", while with this change it would be "e1000#1". This change should hopefully make such EEPROM errors much more straightforward to handle correctly in boot scripts and the like. It is also necessary for a followup patch which allows SPI programming of an e1000 controller's EEPROM even if the checksum is invalid. Signed-off-by: Kyle Moffett --- drivers/net/e1000.c | 105 +++++++++++++++++++++++++++------------------------ drivers/net/e1000.h | 3 + 2 files changed, 59 insertions(+), 49 deletions(-) diff --git a/drivers/net/e1000.c b/drivers/net/e1000.c index 28cedf7..f6c9be5 100644 --- a/drivers/net/e1000.c +++ b/drivers/net/e1000.c @@ -65,7 +65,7 @@ static struct e1000_rx_desc *rx_base; static int tx_tail; static int rx_tail, rx_last; -static struct pci_device_id supported[] = { +static struct pci_device_id e1000_supported[] = { {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82542}, {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82543GC_FIBER}, {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82543GC_COPPER}, @@ -4746,7 +4746,7 @@ e1000_set_media_type(struct e1000_hw *hw) **/ static int -e1000_sw_init(struct eth_device *nic, int cardnum) +e1000_sw_init(struct eth_device *nic) { struct e1000_hw *hw = (typeof(hw)) nic->priv; int result; @@ -5145,43 +5145,55 @@ You should omit the last argument struct pci_device * for a non-PCI NIC int e1000_initialize(bd_t * bis) { + unsigned int i; pci_dev_t devno; - int card_number = 0; - struct eth_device *nic = NULL; - struct e1000_hw *hw = NULL; - u32 iobase; - int idx = 0; - u32 PciCommandWord; DEBUGFUNC(); - while (1) { /* Find PCI device(s) */ - if ((devno = pci_find_devices(supported, idx++)) < 0) { - break; - } + /* Find and probe all the matching PCI devices */ + for (i = 0; (devno = pci_find_devices(e1000_supported, i)) >= 0; i++) { + u32 val; - pci_read_config_dword(devno, PCI_BASE_ADDRESS_0, &iobase); - iobase &= ~0xf; /* Mask the bits that say "this is an io addr" */ - DEBUGOUT("e1000#%d: iobase 0x%08x\n", card_number, iobase); - - pci_write_config_dword(devno, PCI_COMMAND, - PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER); - /* Check if I/O accesses and Bus Mastering are enabled. */ - pci_read_config_dword(devno, PCI_COMMAND, &PciCommandWord); - if (!(PciCommandWord & PCI_COMMAND_MEMORY)) { - printf("Error: Can not enable MEM access.\n"); - continue; - } else if (!(PciCommandWord & PCI_COMMAND_MASTER)) { - printf("Error: Can not enable Bus Mastering.\n"); + /* + * These will never get freed due to errors, this allows us to + * perform SPI EEPROM programming from U-boot, for example. + */ + struct eth_device *nic = malloc(sizeof(*nic)); + struct e1000_hw *hw = malloc(sizeof(*hw)); + if (!nic || !hw) { + printf("e1000#%u: Out of Memory!\n", i); + free(nic); + free(hw); continue; } - nic = (struct eth_device *) malloc(sizeof (*nic)); - hw = (struct e1000_hw *) malloc(sizeof (*hw)); + /* Assign the passed-in values */ + hw->cardnum = i; hw->pdev = devno; + hw->nic = nic; nic->priv = hw; - sprintf(nic->name, "e1000#%d", card_number); + /* Generate a card name */ + sprintf(nic->name, "e1000#%u", hw->cardnum); + + /* Print a debug message with the IO base address */ + pci_read_config_dword(devno, PCI_BASE_ADDRESS_0, &val); + DEBUGOUT("%s: iobase 0x%08x\n", nic->name, val & 0xfffffff0); + + /* Try to enable I/O accesses and bus-mastering */ + val = PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER; + pci_write_config_dword(devno, PCI_COMMAND, val); + + /* Make sure it worked */ + pci_read_config_dword(devno, PCI_COMMAND, &val); + if (!(val & PCI_COMMAND_MEMORY)) { + printf("%s: ERROR: Can't enable I/O memory\n", nic->name); + continue; + } + if (!(val & PCI_COMMAND_MASTER)) { + printf("%s: ERROR: Can't enable bus-mastering\n", nic->name); + continue; + } /* Are these variables needed? */ hw->fc = e1000_fc_default; @@ -5189,50 +5201,45 @@ e1000_initialize(bd_t * bis) hw->autoneg_failed = 0; hw->autoneg = 1; hw->get_link_status = TRUE; - hw->hw_addr = - pci_map_bar(devno, PCI_BASE_ADDRESS_0, PCI_REGION_MEM); + hw->hw_addr = pci_map_bar(devno, PCI_BASE_ADDRESS_0, PCI_REGION_MEM); hw->mac_type = e1000_undefined; /* MAC and Phy settings */ - if (e1000_sw_init(nic, card_number) < 0) { - free(hw); - free(nic); - return 0; + if (e1000_sw_init(nic) < 0) { + printf("%s: ERROR: Software init failed\n", nic->name); + continue; } if (e1000_check_phy_reset_block(hw)) - printf("phy reset block error \n"); + printf("%s: ERROR: PHY Reset is blocked!\n", nic->name); + + /* Basic init was OK, reset the hardware */ e1000_reset_hw(hw); + + /* Validate the EEPROM and get chipset information */ #if !(defined(CONFIG_AP1000) || defined(CONFIG_MVBC_1G)) if (e1000_init_eeprom_params(hw)) { - printf("The EEPROM Checksum Is Not Valid\n"); - free(hw); - free(nic); - return 0; + printf("%s: ERROR: EEPROM is invalid!\n", nic->name); + continue; } if (e1000_validate_eeprom_checksum(nic) < 0) { - printf("The EEPROM Checksum Is Not Valid\n"); - free(hw); - free(nic); - return 0; + printf("%s: ERROR: EEPROM checksum is bad!\n", nic->name); + continue; } #endif e1000_read_mac_addr(nic); - - /* get the bus type information */ e1000_get_bus_type(hw); printf("e1000: %02x:%02x:%02x:%02x:%02x:%02x\n", nic->enetaddr[0], nic->enetaddr[1], nic->enetaddr[2], nic->enetaddr[3], nic->enetaddr[4], nic->enetaddr[5]); + /* Set up the function pointers and register the device */ nic->init = e1000_init; nic->recv = e1000_poll; nic->send = e1000_transmit; nic->halt = e1000_disable; - eth_register(nic); - - card_number++; } - return card_number; + + return i; } diff --git a/drivers/net/e1000.h b/drivers/net/e1000.h index 8597e23..8573511 100644 --- a/drivers/net/e1000.h +++ b/drivers/net/e1000.h @@ -1043,6 +1043,9 @@ typedef enum { /* Structure containing variables used by the shared code (e1000_hw.c) */ struct e1000_hw { + struct eth_device *nic; + unsigned int cardnum; + pci_dev_t pdev; uint8_t *hw_addr; e1000_mac_type mac_type;