linux-pci.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Mauro Carvalho Chehab <mchehab@redhat.com>
To: Bjorn Helgaas <bhelgaas@google.com>
Cc: Yinghai Lu <yinghai@kernel.org>, Jiang Liu <jiang.liu@huawei.com>,
	Tony Luck <tony.luck@intel.com>,
	"Rafael J. Wysocki" <rjw@sisk.pl>,
	Taku Izumi <izumi.taku@jp.fujitsu.com>,
	Toshi Kani <toshi.kani@hp.com>,
	Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
	linux-pci@vger.kernel.org, Russell King <linux@arm.linux.org.uk>,
	Linux Kernel Mailing List <linux-kernel@vger.kernel.org>
Subject: Re: [PATCH v3 00/22] PCI: Iterate pci host bridge instead of pci root bus
Date: Thu, 7 Feb 2013 08:24:35 -0200	[thread overview]
Message-ID: <20130207082435.21d897a3@redhat.com> (raw)
In-Reply-To: <CAErSpo4jtrp4ashHsfZP580_qdCXBEqmdd=SBfQrgQTV4uM4EA@mail.gmail.com>

Em Wed, 6 Feb 2013 10:45:16 -0700
Bjorn Helgaas <bhelgaas@google.com> escreveu:

> On Wed, Feb 6, 2013 at 1:53 AM, Mauro Carvalho Chehab
> <mchehab@redhat.com> wrote:
> > Em Tue, 5 Feb 2013 16:47:10 -0800
> > Yinghai Lu <yinghai@kernel.org> escreveu:
> >
> >> On Tue, Feb 5, 2013 at 4:19 PM, Bjorn Helgaas <bhelgaas@google.com> wrote:
> >> >
> >> > Maybe.  I'd rather not introduce for_each_pci_host_bridge() at all, if
> >> > we can avoid it.  Every place it's used is a place we have to audit to
> >> > make sure it's safe.  I think your audit above is correct and
> >> > complete, but it relies on way too much architecture knowledge.  It's
> >> > better if we can deduce correctness without knowing which arches
> >> > support hotplug and which CPUs support EDAC.
> >> >
> >> > As soon as for_each_pci_host_bridge() is in the tree, those uses can
> >> > be copied to even more places.  It's a macro, so it's usable by any
> >> > module, even out-of-tree ones that we'll never see and can't fix.  So
> >> > we won't really have a good way to deprecate and remove it.
> >>
> >> Now we only have two references in modules.
> >>
> >> drivers/edac/i7core_edac.c:     for_each_pci_host_bridge(host_bridge) {
> >> drivers/pci/hotplug/sgi_hotplug.c:      for_each_pci_host_bridge(host_bridge) {
> >>
> >> for the sgi_hotplug.c, it should be same problem that have for acpiphp
> >> and pciehp.
> >> need to make it support pci host bridge hotplug anyway.
> >>
> >> for edac, we need to check Mauro about their plan.
> >
> > The i7core_pci_lastbus() code at i7core_edac is there to make it work
> > with some Nehalem/Nehalem-EP machines that hide the memory controller's
> > PCI ID by using an artificially low last bus.
> 
> I don't really understand how this helps.  An example would probably
> make it clearer.
> 
> i7core_edac.c has some very creative use of PCI infrastructure.
> Normally a driver has a pci_device_id table that identifies the
> vendor/device IDs of the devices it cares about, and the driver's
> .probe() method is called for every matching device.
> 
> But i7core_edac only has two entries in its id_table.  When we find a
> device that matches one of those two entries, we call i7core_probe(),
> which then gropes around for all the *other* devices related to that
> original one.  This is a bit messy.
> 
> I'd like it a lot better if the device IDs in
> pci_dev_descr_i7core_nehalem[], pci_dev_descr_lynnfield[], etc., were
> just in the pci_device_id table directly.  Then i7core_probe() would
> be called directly for every device you care about, and you could sort
> them out there.  That should work without any need for
> pci_get_device(), i7core_pci_lastbus(), etc.


Bjorn,

On almost all Intel memory controllers since 2002, the memory controller
handling function were split into several different PCI devices and
PCI functions. So, for example, even if you look on old driver like 
i5000_edac.c, you'll see 5 different PCI IDs that are required to
control a single device:

#ifndef PCI_DEVICE_ID_INTEL_FBD_0
#define PCI_DEVICE_ID_INTEL_FBD_0	0x25F5
#endif
#ifndef PCI_DEVICE_ID_INTEL_FBD_1
#define PCI_DEVICE_ID_INTEL_FBD_1	0x25F6
#endif

/* Device 16,
 * Function 0: System Address
 * Function 1: Memory Branch Map, Control, Errors Register
 * Function 2: FSB Error Registers
 *
 * All 3 functions of Device 16 (0,1,2) share the SAME DID
 */
#define	PCI_DEVICE_ID_INTEL_I5000_DEV16	0x25F0

/* OFFSETS for Function 1 */

(a long list of registers there)

/*
 * Device 21,
 * Function 0: Memory Map Branch 0
 *
 * Device 22,
 * Function 0: Memory Map Branch 1
 */
#define PCI_DEVICE_ID_I5000_BRANCH_0	0x25F5
#define PCI_DEVICE_ID_I5000_BRANCH_1	0x25F6

(another long list or registers there)

I've no idea why the hardware engineers there decided on that way, 
but the number of different PCI devices required for the functionality 
to work has been increased on their newer chipsets. At the Sandy
Bridge driver (sb_edac.c), all those PCI devices need to be opened
at the same time, in order to allow controlling a single memory
controller (and one system have one memory controller per socket):

#define PCI_DEVICE_ID_INTEL_SBRIDGE_SAD0	0x3cf4	/* 12.6 */
#define PCI_DEVICE_ID_INTEL_SBRIDGE_SAD1	0x3cf6	/* 12.7 */
#define PCI_DEVICE_ID_INTEL_SBRIDGE_BR		0x3cf5	/* 13.6 */
#define PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_HA0	0x3ca0	/* 14.0 */
#define PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TA	0x3ca8	/* 15.0 */
#define PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_RAS	0x3c71	/* 15.1 */
#define PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD0	0x3caa	/* 15.2 */
#define PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD1	0x3cab	/* 15.3 */
#define PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD2	0x3cac	/* 15.4 */
#define PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD3	0x3cad	/* 15.5 */
#define PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_DDRIO	0x3cb8	/* 17.0 */

The first thing that any EDAC driver needs to do is to get the memory
configuration (number of DIMMs, channels filled, DIMM size, etc).
In the case of sb_edac, the logic is at get_dimm_config(). It needs
to read data on _several_ of the above PCI IDs:

static int get_dimm_config(struct mem_ctl_info *mci)
{
...
	pci_read_config_dword(pvt->pci_br, SAD_TARGET, &reg);		// reads from PCI_DEVICE_ID_INTEL_SBRIDGE_BR
...
	pci_read_config_dword(pvt->pci_br, SAD_CONTROL, &reg);		// reads from PCI_DEVICE_ID_INTEL_SBRIDGE_BR
...
	pci_read_config_dword(pvt->pci_ras, RASENABLES, &reg);		// reads from PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_RAS
...
	pci_read_config_dword(pvt->pci_ta, MCMTR, &pvt->info.mcmtr);	// reads from PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TA
...
	pci_read_config_dword(pvt->pci_ddrio, RANK_CFG_A, &reg);	// reads from PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_DDRIO
...
	for (i = 0; i < NUM_CHANNELS; i++) {
...
		for (j = 0; j < ARRAY_SIZE(mtr_regs); j++) {
...
			pci_read_config_dword(pvt->pci_tad[i],
					      mtr_regs[j], &mtr);	// PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD0 to PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD3

So, while the usual design of having one PCI ID entry for each device
works for the vast majority of drivers, as each different PCI ID/function
are typically independent and pci_driver.probe() can be called for every
entry inside the PCI ID table, that's not the case of EDAC.

On EDAC drivers, the probing routine can be called only after calling
pci_get_device() for the entire set of PCI devices that belongs to the
memory controller. 

To make things worse, the PCI IDs for the memory controllers are sometimes
after PCI lastbus.

So, the logic used on almost all drivers there is to use one PCI ID "detect"
device at the table, used to discover if the system has a supported memory
controller chipset. If it matches, the pci_driver.probe() will seek for the
actual PCI devices that are required for it to work, with may or may not be
the same as the "detect" device.

Also, the highest bus corresponds to the first memory controller. So,
bus=255 matches the memory controller for the CPU socket 0,
bus=254 matches the one for CPU socket 1 and so on. That forced the driver
to probe all devices at the same time, on all CPU sockets, in order to reverse
the order when initializing the memory controller EDAC structures.

There are some other odd details there... In the case of i7core_edac, it 
supports 3 different versions of memory controllers; each version has its 
own set of PCI ID's. So, its "real" PCI ID table set has 3 entries:

static const struct pci_id_table pci_dev_table[] = {
	PCI_ID_TABLE_ENTRY(pci_dev_descr_i7core_nehalem),
	PCI_ID_TABLE_ENTRY(pci_dev_descr_lynnfield),
	PCI_ID_TABLE_ENTRY(pci_dev_descr_i7core_westmere),
	{0,}			/* 0 terminated list. */
};

while its PCI ID "detect" table has only two, as the PCI device 8086:342e
(PCI_DEVICE_ID_INTEL_X58_HUB_MGMT) is found on both Nehalem and Westmere:

static DEFINE_PCI_DEVICE_TABLE(i7core_pci_tbl) = {
	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_X58_HUB_MGMT)},
	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_LYNNFIELD_QPI_LINK0)},
	{0,}			/* 0 terminated list. */

-- 

Cheers,
Mauro

  reply	other threads:[~2013-02-07 10:25 UTC|newest]

Thread overview: 90+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-01-21 21:20 [PATCH v10 00/11] PCI, ACPI: pci root bus hotplug support / pci match_driver Yinghai Lu
2013-01-21 21:20 ` [PATCH v10 01/11] PCI, acpiphp: Add is_hotplug_bridge detection Yinghai Lu
2013-01-21 21:20 ` [PATCH v10 02/11] PCI: Add root bus children dev's res to fail list Yinghai Lu
2013-01-21 21:20 ` [PATCH v10 03/11] PCI: Set dev_node early for pci_dev Yinghai Lu
2013-01-21 21:20 ` [PATCH v10 04/11] PCI: Fix a device reference count leakage issue in pci_dev_present() Yinghai Lu
2013-01-21 21:20 ` [PATCH v10 05/11] PCI: make PCI device create/destroy logic symmetric Yinghai Lu
2013-01-21 21:20 ` [PATCH v10 06/11] PCI, ACPI, acpiphp: Rename alloc_acpiphp_hp_work() to alloc_acpi_hp_work Yinghai Lu
2013-01-21 21:20 ` [PATCH v10 07/11] PCI, acpiphp: Move and enhance hotplug support of pci host bridge Yinghai Lu
2013-01-21 21:20 ` [PATCH v10 08/11] PCI, ACPI: debug print for installation of acpi root bridge's notifier Yinghai Lu
2013-01-21 21:20 ` [PATCH v10 09/11] PCI, acpiphp: Don't bailout even no slots found yet Yinghai Lu
2013-01-21 21:20 ` [PATCH v10 10/11] PCI: Skip attaching driver in device_add() Yinghai Lu
2013-01-21 21:20 ` [PATCH v10 11/11] PCI: Put pci dev to device tree as early as possible Yinghai Lu
2013-01-22 22:09 ` [PATCH v10 00/11] PCI, ACPI: pci root bus hotplug support / pci match_driver Rafael J. Wysocki
2013-01-22 22:19   ` Yinghai Lu
2013-01-26  0:04     ` Bjorn Helgaas
2013-01-26  1:24       ` Jiang Liu
2013-01-26 23:34       ` Yinghai Lu
2013-01-27  5:36         ` [PATCH v2 00/22] PCI: use pci host bridge to loop pci root bus Yinghai Lu
2013-01-27  5:36           ` [PATCH v2 01/22] PCI: Rename pci_release_bus_bridge_dev to pci_release_host_bridge_dev Yinghai Lu
2013-01-27 22:26             ` Rafael J. Wysocki
2013-01-27  5:36           ` [PATCH v2 02/22] PCI: Add dummy bus_type for pci_host_bridge Yinghai Lu
2013-01-27  5:36           ` [PATCH v2 03/22] PCI, libata: remove find_bridge in acpi_bus_type Yinghai Lu
2013-01-27  5:36           ` [PATCH v2 04/22] PCI, ACPI: Update comments for " Yinghai Lu
2013-01-27  5:36           ` [PATCH v2 05/22] PCI: Add for_each_pci_host_bridge() and pci_get_next_host_bridge Yinghai Lu
2013-01-27  5:36           ` [PATCH v2 06/22] PCI, hotplug: Kill pci_find_next_bus in sgi_hotplug Yinghai Lu
2013-01-27  5:36           ` [PATCH v2 07/22] PCI: Kill pci_find_next_bus in pci_sysfs Yinghai Lu
2013-01-27  5:36           ` [PATCH v2 08/22] PCI, edac: Kill pci_find_next_bus in edac Yinghai Lu
2013-01-27  5:36           ` [PATCH v2 09/22] PCI, x86: Kill pci_find_next_bus in pcibios_scan_root Yinghai Lu
2013-01-27  5:36           ` [PATCH v2 10/22] PCI, x86: Kill pci_root_buses in resources reservations Yinghai Lu
2013-01-27  5:36           ` [PATCH v2 11/22] PCI, drm: Kill pci_root_buses in alpha hose setting Yinghai Lu
2013-01-27  5:36           ` [PATCH v2 12/22] PCI: Kill pci_root_buses in setup-bus Yinghai Lu
2013-01-27  5:36           ` [PATCH v2 13/22] PCI, sparc: Kill pci_find_next_bus Yinghai Lu
2013-01-27  5:36           ` [PATCH v2 14/22] PCI, ia64: " Yinghai Lu
2013-01-27  5:36           ` [PATCH v2 15/22] PCI, alpha: Kill pci_root_buses Yinghai Lu
2013-01-27  5:36           ` [PATCH v2 16/22] PCI, arm: " Yinghai Lu
2013-01-27 17:38             ` Russell King - ARM Linux
2013-01-27 18:22               ` Yinghai Lu
     [not found]                 ` <1359314629-18651-1-git-send-email-yinghai@kernel.org>
2013-01-27 19:23                   ` [PATCH v3 01/22] PCI: Rename pci_release_bus_bridge_dev to pci_release_host_bridge_dev Yinghai Lu
2013-01-27 19:23                   ` [PATCH v3 03/22] PCI, libata: remove find_bridge in acpi_bus_type Yinghai Lu
2013-01-27 19:23                   ` [PATCH v3 04/22] PCI, ACPI: Update comments for " Yinghai Lu
2013-01-27 22:32                     ` Rafael J. Wysocki
2013-01-28  1:00                       ` Yinghai Lu
2013-01-28 12:37                         ` Rafael J. Wysocki
2013-01-27 19:23                   ` [PATCH v3 06/22] PCI, hotplug: Kill pci_find_next_bus in sgi_hotplug Yinghai Lu
2013-01-27 19:23                   ` [PATCH v3 07/22] PCI: Kill pci_find_next_bus in pci_sysfs Yinghai Lu
2013-01-27 19:23                   ` [PATCH v3 08/22] PCI, edac: Kill pci_find_next_bus in edac Yinghai Lu
2013-01-27 19:23                   ` [PATCH v3 09/22] PCI, x86: Kill pci_find_next_bus in pcibios_scan_root Yinghai Lu
2013-01-27 19:23                   ` [PATCH v3 10/22] PCI, x86: Kill pci_root_buses in resources reservations Yinghai Lu
2013-01-27 19:23                   ` [PATCH v3 11/22] PCI, drm: Kill pci_root_buses in alpha hose setting Yinghai Lu
2013-01-28  3:21                     ` Yijing Wang
2013-01-28  3:35                       ` Yinghai Lu
2013-01-27 19:23                   ` [PATCH v3 12/22] PCI: Kill pci_root_buses in setup-bus Yinghai Lu
2013-01-27 19:23                   ` [PATCH v3 13/22] PCI, sparc: Kill pci_find_next_bus Yinghai Lu
2013-01-27 19:23                   ` [PATCH v3 14/22] PCI, ia64: " Yinghai Lu
2013-01-27 19:23                   ` [PATCH v3 15/22] PCI, alpha: Kill pci_root_buses Yinghai Lu
2013-01-27 19:23                   ` [PATCH v3 16/22] PCI, arm: " Yinghai Lu
2013-01-27 19:23                   ` [PATCH v3 17/22] PCI, frv: Kill pci_root_buses in resources reservations Yinghai Lu
2013-01-27 19:23                   ` [PATCH v3 18/22] PCI, microblaze: " Yinghai Lu
2013-01-27 19:23                   ` [PATCH v3 19/22] PCI, mn10300: " Yinghai Lu
2013-01-27 19:23                   ` [PATCH v3 20/22] PCI, powerpc: " Yinghai Lu
2013-01-28  3:48                     ` Yijing Wang
2013-01-28  5:23                       ` Yinghai Lu
     [not found]                   ` <CAErSpo6r_LNEtYB3j5ELb8NdHu0a6_YOVj8S32CmByGFUpSsbg@mail.gmail.com>
2013-02-03  5:05                     ` [PATCH v3 00/22] PCI: Iterate pci host bridge instead of pci root bus Yinghai Lu
2013-02-05 23:55                       ` Yinghai Lu
2013-02-06  0:19                         ` Bjorn Helgaas
2013-02-06  0:47                           ` Yinghai Lu
2013-02-06  8:53                             ` Mauro Carvalho Chehab
2013-02-06 17:45                               ` Bjorn Helgaas
2013-02-07 10:24                                 ` Mauro Carvalho Chehab [this message]
2013-02-06 17:54                             ` Bjorn Helgaas
2013-02-06 18:59                               ` Yinghai Lu
2013-02-06 20:50                                 ` Bjorn Helgaas
2013-02-06 21:28                                   ` Yinghai Lu
2013-02-06 21:43                                     ` Rafael J. Wysocki
2013-02-06 21:53                                       ` Yinghai Lu
2013-02-06 22:05                                         ` Rafael J. Wysocki
2013-02-06 23:02                                           ` Bjorn Helgaas
2013-02-06 23:31                                             ` Yinghai Lu
2013-02-07  0:27                                             ` Jiang Liu
2013-01-28  1:54                 ` Yinghai Lu
2013-01-28  1:54                   ` [PATCH v3 02/22] PCI: Add dummy bus_type for pci_host_bridge Yinghai Lu
2013-01-28  1:54                   ` [PATCH v3 05/22] PCI: Add for_each_pci_host_bridge() and pci_get_next_host_bridge Yinghai Lu
2013-01-28  1:54                   ` [PATCH v3 21/22] PCI: Kill pci_find_next_bus Yinghai Lu
2013-01-28  1:54                   ` [PATCH v3 22/22] PCI: Kill pci_root_buses Yinghai Lu
2013-01-27  5:36           ` [PATCH v2 17/22] PCI, frv: Kill pci_root_buses in resources reservations Yinghai Lu
2013-01-27  5:36           ` [PATCH v2 18/22] PCI, microblaze: " Yinghai Lu
2013-01-27  5:36           ` [PATCH v2 19/22] PCI, mn10300: " Yinghai Lu
2013-01-27  5:36           ` [PATCH v2 20/22] PCI, powerpc: " Yinghai Lu
2013-01-27  5:36           ` [PATCH v2 21/22] PCI: Kill pci_find_next_bus Yinghai Lu
2013-01-27  5:36           ` [PATCH v2 22/22] PCI: Kill pci_root_buses Yinghai Lu

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20130207082435.21d897a3@redhat.com \
    --to=mchehab@redhat.com \
    --cc=bhelgaas@google.com \
    --cc=gregkh@linuxfoundation.org \
    --cc=izumi.taku@jp.fujitsu.com \
    --cc=jiang.liu@huawei.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-pci@vger.kernel.org \
    --cc=linux@arm.linux.org.uk \
    --cc=rjw@sisk.pl \
    --cc=tony.luck@intel.com \
    --cc=toshi.kani@hp.com \
    --cc=yinghai@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).