All of lore.kernel.org
 help / color / mirror / Atom feed
From: Yijing Wang <wangyijing@huawei.com>
To: Bjorn Helgaas <bhelgaas@google.com>
Cc: <linux-pci@vger.kernel.org>, <mjg59@coreos.com>,
	<rwhite@pobox.com>, <alex.williamson@redhat.com>
Subject: Re: [PATCH] PCI: Fix NULL pointer when find parent pcie_link_state
Date: Fri, 24 Apr 2015 14:12:47 +0800	[thread overview]
Message-ID: <5539DEDF.3050503@huawei.com> (raw)
In-Reply-To: <20150423142407.GL20701@google.com>

On 2015/4/23 22:24, Bjorn Helgaas wrote:
> [+cc Alex]
> 
> Hi Yijing,
> 
> Thanks for picking this up and working on it!
> 
> On Thu, Apr 23, 2015 at 03:41:56PM +0800, Yijing Wang wrote:
>> https://bugzilla.kernel.org/show_bug.cgi?id=94361 reported
>> NULL Pointer in pcie_aspm_init_link_state(), Some platform
>> like ATCA may has strange PCIe topology:
>> E.g.
>> ---root port---downstream port---upstream port
>>                               |--downstream port
>>                               |--downstream port
> 
> I agree that this is "strange" in the sense that it's not the typical PC
> topology.  However, I can't find anything in the spec that prohibits it.
> As far as I can tell, it is legal, so the PCI core shouldn't treat it as
> an exception.
> 
> PCI bridges (including PCIe switch ports) are symmetric: anything in the
> bridge windows will be transferred from the primary interface to the
> secondary, and anything outside the windows will be transferred from
> secondary to primary.  That applies to both address-routed transactions
> (using the I/O port, memory, and prefetchable memory windows) and
> ID-routed transactions (using the bus number windows).  And it applies
> to both Upstream and Downstream Ports, so from a routing perspective, I
> think Upstream and Downstream Ports are mostly interchangeable.
> 
> There are some wrinkles that might be issues:
> 
>   - PCIe spec r3.0, sec 7.3.3 says propagation of config requests from
>     Downstream to Upstream is unsupported.  I think that means we
>     wouldn't be able to discover anything on the other side of the
>     Upstream Port in the above topology.
> 
>   - Sec 7.5.1.7 says primary side Error Control/Status registers apply
>     to the link for Upstream Ports and to the internal logic for
>     Downstream Ports.  For this ATCA topology that means the primary
>     side registers of a Downstream Port really refer to the *secondary*
>     interface.
> 
>   - Sec 7.16 (ACS) might have issues similar to this ASPM one.
> 
> If this topology is legal, the NULL pointer is a hint that the code uses
> an incorrect assumption, and I'd rather fix the incorrect assumption
> than apply a point fix for the NULL pointer.
> 
> In this case, the code incorrectly assumes that a Downstream Port is
> always on the upstream end of a link.  I think it's safe to assume that
> a *Root Port* is always on the upstream end of a link.  Maybe we can
> start from there and deduce where the links are, without relying on
> whether a Port is an Upstream or Downstream Port.  The levels of the
> hierarchy should alternate between links and internal switch logic,

I agree with this assumption, there should be no adjacent links or internal buses.

Thanks!
Yijing.


> e.g.:
> 
>   RP -link- endpoint
>   RP -link- UP -int-bus- DP -link- endpoint
>   RP -link- UP -int-bus- DP -link- UP -int-bus- DP -link- endpoint
>   RP -link- DP -int-bus- DP -link- endpoint
>   RP -link- DP -int-bus- DP -link- UP -int-bus- DP -link- endpoint
> 
>> When we try to alloc pcie_link_state, we assumed downstream port
>> always has a upstream port, in this case, NULL pointer would
>> be triggered when try to find the parent pci_link_state,
>> because downstream port connects to root port directly.
> 
>> Signed-off-by: Yijing Wang <wangyijing@huawei.com>
>> ---
>>  drivers/pci/pcie/aspm.c |   13 +++++++++++--
>>  1 files changed, 11 insertions(+), 2 deletions(-)
>>
>> diff --git a/drivers/pci/pcie/aspm.c b/drivers/pci/pcie/aspm.c
>> index 7d4fcdc..f295824 100644
>> --- a/drivers/pci/pcie/aspm.c
>> +++ b/drivers/pci/pcie/aspm.c
>> @@ -526,8 +526,17 @@ static struct pcie_link_state *alloc_pcie_link_state(struct pci_dev *pdev)
>>  	INIT_LIST_HEAD(&link->link);
>>  	link->pdev = pdev;
>>  	if (pci_pcie_type(pdev) == PCI_EXP_TYPE_DOWNSTREAM) {
>> -		struct pcie_link_state *parent;
>> -		parent = pdev->bus->parent->self->link_state;
>> +		struct pci_bus *pbus = pdev->bus;
>> +		struct pcie_link_state *parent = NULL;
>> +
>> +		while (pbus) {
>> +			if (pbus->self) {
>> +				parent = pbus->self->link_state;
>> +				if (parent)
>> +					break;
>> +			}
>> +			pbus = pbus->parent;
>> +		}
>>  		if (!parent) {
>>  			kfree(link);
>>  			return NULL;
> 
> .
> 


-- 
Thanks!
Yijing


      reply	other threads:[~2015-04-24  6:13 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-04-23  7:41 [PATCH] PCI: Fix NULL pointer when find parent pcie_link_state Yijing Wang
2015-04-23 14:24 ` Bjorn Helgaas
2015-04-24  6:12   ` Yijing Wang [this message]

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=5539DEDF.3050503@huawei.com \
    --to=wangyijing@huawei.com \
    --cc=alex.williamson@redhat.com \
    --cc=bhelgaas@google.com \
    --cc=linux-pci@vger.kernel.org \
    --cc=mjg59@coreos.com \
    --cc=rwhite@pobox.com \
    /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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.