From patchwork Mon Jun 25 07:47:38 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pingfan Liu X-Patchwork-Id: 934100 Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Received: from lists.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3]) (using TLSv1.2 with cipher ADH-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 41DhH92MPCz9ryk for ; Mon, 25 Jun 2018 17:52:53 +1000 (AEST) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="hU1yrn8g"; dkim-atps=neutral Received: from lists.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3]) by lists.ozlabs.org (Postfix) with ESMTP id 41DhH86ssLzF1Gj for ; Mon, 25 Jun 2018 17:52:52 +1000 (AEST) Authentication-Results: lists.ozlabs.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: lists.ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="hU1yrn8g"; dkim-atps=neutral X-Original-To: linuxppc-dev@lists.ozlabs.org Delivered-To: linuxppc-dev@lists.ozlabs.org Authentication-Results: lists.ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=gmail.com (client-ip=2607:f8b0:400e:c01::241; helo=mail-pl0-x241.google.com; envelope-from=kernelfans@gmail.com; receiver=) Authentication-Results: lists.ozlabs.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: lists.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="hU1yrn8g"; dkim-atps=neutral Received: from mail-pl0-x241.google.com (mail-pl0-x241.google.com [IPv6:2607:f8b0:400e:c01::241]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by lists.ozlabs.org (Postfix) with ESMTPS id 41Dh9V2P70zF18l for ; Mon, 25 Jun 2018 17:47:58 +1000 (AEST) Received: by mail-pl0-x241.google.com with SMTP id g20-v6so6444195plq.1 for ; Mon, 25 Jun 2018 00:47:58 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=BzaOHQJzsfa3ParVwOyiRh2VXWWpE9DRaIR73EkU7tA=; b=hU1yrn8grpIBz05rPXMk7nzEn7ujdzPsJOyPCwcLHavxAF7Fd++1yCbBXAYEKqBB7N ET0uiCIa0vKYls8Sk/lN/4X0FutFLESSxokl3UFzq3LXcGu7IW41ljPczBrF6fRPrNpf t1s+3CQyJ1/yV5KTOMLbg+DzpR55aRVDAdMXluWfjJfJprMxsTDG0SVNF/nq44eMC7D4 62HL5PZVWBOBe/z8qVQEpuPoE51ux3vQ7AtivwD5p2t2diZPq/GiIKpOiCSyOy/Fantf B96MNjyq6VRNamR9ShEud3UWJHuCcor8ySlZpXUBKfWA6ezW4IaxY0PZSLFxqYNqt6Mz qRJw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=BzaOHQJzsfa3ParVwOyiRh2VXWWpE9DRaIR73EkU7tA=; b=t/hzL+rVfe0fyptbDwGv5Ep5vZqn6Hw7nfGMIAcCeEziwsCqg/cC45CGNYsqomiL2W MTVXLZ5pZ9u8rMN18EEL9IzDGDURUv9TKaqFLH3CF3u8YZ03QNiXUh1djcPmv1WDe4AI m9sM081nlKeFj6ZUgVurGp04XFiKL2YzP5Vs9r2iXl9P5TUlwcx8VkZUgBd+JHZF6eWI 4dKm4ZhIB6CA0afAkIeseqGBmzSj4WzMDEOjhVNZpBrQok6r/tPeHJjsAwD9A1bswLn1 UrpKOHGzK8aBYc0t6hhj56/uE0Yjt+EUdBeSuhmwF+DaUnwjg2Qx6FbRO92lh/mvUOlQ PNvg== X-Gm-Message-State: APt69E33W+KkjRJN13DYuWHnj7m+RM6C1Wuqg0dgPuu8AhzZic0nk2qm QV6+rSm5d6D3kbe3HXMQqA== X-Google-Smtp-Source: ADUXVKK4eOsMRiplG82h3qgDpqcSm/f0OWr/mqNycQCmV9rfVZa4Q03GWOxD2Wwuwhk7Z2odBKRiCw== X-Received: by 2002:a17:902:585:: with SMTP id f5-v6mr11381540plf.142.1529912875732; Mon, 25 Jun 2018 00:47:55 -0700 (PDT) Received: from mylaptop.nay.redhat.com ([209.132.188.80]) by smtp.gmail.com with ESMTPSA id p12-v6sm27350460pfi.175.2018.06.25.00.47.52 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 25 Jun 2018 00:47:55 -0700 (PDT) From: Pingfan Liu To: linux-kernel@vger.kernel.org Subject: [PATCHv2 1/2] drivers/base: only reordering consumer device when probing Date: Mon, 25 Jun 2018 15:47:38 +0800 Message-Id: <1529912859-10475-2-git-send-email-kernelfans@gmail.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1529912859-10475-1-git-send-email-kernelfans@gmail.com> References: <1529912859-10475-1-git-send-email-kernelfans@gmail.com> X-BeenThere: linuxppc-dev@lists.ozlabs.org X-Mailman-Version: 2.1.26 Precedence: list List-Id: Linux on PowerPC Developers Mail List List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Grygorii Strashko , Greg Kroah-Hartman , linuxppc-dev@lists.ozlabs.org, Pingfan Liu , Christoph Hellwig , Bjorn Helgaas , linux-pci@vger.kernel.org, Dave Young Errors-To: linuxppc-dev-bounces+patchwork-incoming=ozlabs.org@lists.ozlabs.org Sender: "Linuxppc-dev" commit 52cdbdd49853 ("driver core: correct device's shutdown order") places an assumption of supplier<-consumer order on the process of probe. But it turns out to break down the parent <- child order in some scene. E.g in pci, a bridge is enabled by pci core, and behind it, the devices have been probed. Then comes the bridge's module, which enables extra feature(such as hotplug) on this bridge. This will break the parent<-children order and cause failure when "kexec -e" in some scenario. The detailed description of the scenario: An IBM Power9 machine on which, two drivers portdrv_pci and shpchp(a mod) match the PCI_CLASS_BRIDGE_PCI, but neither of them success to probe due to some issue. For this case, the bridge is moved after its children in devices_kset. Then, when "kexec -e", a ata-disk behind the bridge can not write back buffer in flight due to the former shutdown of the bridge which clears the BusMaster bit. To fix this issue, only reordering a device and all of its children if it is a consumer. Note, the bridge involved: 0004:00:00.0 PCI bridge: IBM Device 04c1 (prog-if 00 [Normal decode]) Control: I/O+ Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR+ FastB2B- DisINTx- Status: Cap+ 66MHz- UDF- FastB2B- ParErr- DEVSEL=fast >TAbort- SERR- TAbort- Reset- FastB2B- PriDiscTmr- SecDiscTmr- DiscTmrStat- DiscTmrSERREn- Capabilities: [40] Power Management version 3 Flags: PMEClk- DSI- D1- D2- AuxCurrent=0mA PME(D0+,D1-,D2-,D3hot+,D3cold+) Status: D0 NoSoftRst- PME-Enable- DSel=0 DScale=0 PME- Capabilities: [48] Express (v2) Root Port (Slot-), MSI 00 DevCap: MaxPayload 512 bytes, PhantFunc 0 ExtTag- RBE+ DevCtl: Report errors: Correctable- Non-Fatal- Fatal- Unsupported- RlxdOrd- ExtTag- PhantFunc- AuxPwr- NoSnoop- MaxPayload 256 bytes, MaxReadReq 128 bytes DevSta: CorrErr- UncorrErr- FatalErr- UnsuppReq- AuxPwr- TransPend- LnkCap: Port #0, Speed 8GT/s, Width x8, ASPM not supported, Exit Latency L0s <64ns, L1 <1us ClockPM- Surprise- LLActRep+ BwNot+ ASPMOptComp- LnkCtl: ASPM Disabled; RCB 128 bytes Disabled- CommClk- ExtSynch- ClockPM- AutWidDis- BWInt- AutBWInt- LnkSta: Speed 8GT/s, Width x4, TrErr- Train- SlotClk- DLActive+ BWMgmt- ABWMgmt+ RootCtl: ErrCorrectable- ErrNon-Fatal- ErrFatal- PMEIntEna- CRSVisible- RootCap: CRSVisible- RootSta: PME ReqID 0000, PMEStatus- PMEPending- DevCap2: Completion Timeout: Range ABCD, TimeoutDis+, LTR-, OBFF Not Supported ARIFwd+ DevCtl2: Completion Timeout: 16ms to 55ms, TimeoutDis+, LTR-, OBFF Disabled ARIFwd+ LnkCtl2: Target Link Speed: 8GT/s, EnterCompliance- SpeedDis- Transmit Margin: Normal Operating Range, EnterModifiedCompliance- ComplianceSOS- Compliance De-emphasis: -6dB LnkSta2: Current De-emphasis Level: -3.5dB, EqualizationComplete+, EqualizationPhase1+ EqualizationPhase2+, EqualizationPhase3+, LinkEqualizationRequest- Capabilities: [100 v1] Advanced Error Reporting UESta: DLP- SDES- TLP- FCP- CmpltTO- CmpltAbrt- UnxCmplt- RxOF- MalfTLP- ECRC- UnsupReq- ACSViol- UEMsk: DLP- SDES- TLP+ FCP- CmpltTO+ CmpltAbrt+ UnxCmplt- RxOF- MalfTLP- ECRC+ UnsupReq- ACSViol- UESvrt: DLP- SDES- TLP- FCP- CmpltTO- CmpltAbrt- UnxCmplt- RxOF- MalfTLP- ECRC- UnsupReq- ACSViol- CESta: RxErr- BadTLP- BadDLLP- Rollover- Timeout- NonFatalErr- CEMsk: RxErr- BadTLP- BadDLLP- Rollover- Timeout- NonFatalErr- AERCap: First Error Pointer: 00, GenCap+ CGenEn+ ChkCap+ ChkEn+ Capabilities: [148 v1] #19 Cc: Greg Kroah-Hartman Cc: Grygorii Strashko Cc: Christoph Hellwig Cc: Bjorn Helgaas Cc: Dave Young Cc: linux-pci@vger.kernel.org Cc: linuxppc-dev@lists.ozlabs.org Signed-off-by: Pingfan Liu --- note: this patch points out the code where the bug is introduced. and I hope it sketches out the scene. Will fold the series in one. --- drivers/base/base.h | 1 + drivers/base/core.c | 9 +++++++++ drivers/base/dd.c | 9 ++------- 3 files changed, 12 insertions(+), 7 deletions(-) diff --git a/drivers/base/base.h b/drivers/base/base.h index a75c302..37f86ca 100644 --- a/drivers/base/base.h +++ b/drivers/base/base.h @@ -135,6 +135,7 @@ extern void device_unblock_probing(void); /* /sys/devices directory */ extern struct kset *devices_kset; +extern int device_reorder_consumer(struct device *dev); extern void devices_kset_move_last(struct device *dev); #if defined(CONFIG_MODULES) && defined(CONFIG_SYSFS) diff --git a/drivers/base/core.c b/drivers/base/core.c index 36622b5..66f06ff 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -123,6 +123,15 @@ static int device_is_dependent(struct device *dev, void *target) return ret; } +/* a temporary place holder to mark out the root cause of the bug. + * The proposal algorithm will come in next patch + */ +int device_reorder_consumer(struct device *dev) +{ + devices_kset_move_last(dev); + return 0; +} + static int device_reorder_to_tail(struct device *dev, void *not_used) { struct device_link *link; diff --git a/drivers/base/dd.c b/drivers/base/dd.c index 1435d72..c74f23c 100644 --- a/drivers/base/dd.c +++ b/drivers/base/dd.c @@ -434,13 +434,8 @@ static int really_probe(struct device *dev, struct device_driver *drv) goto probe_failed; } - /* - * Ensure devices are listed in devices_kset in correct order - * It's important to move Dev to the end of devices_kset before - * calling .probe, because it could be recursive and parent Dev - * should always go first - */ - devices_kset_move_last(dev); + /* only reoder consumer and its children after suppliers.*/ + device_reorder_consumer(dev); if (dev->bus->probe) { ret = dev->bus->probe(dev); From patchwork Mon Jun 25 07:47:39 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pingfan Liu X-Patchwork-Id: 934101 Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Received: from lists.ozlabs.org (lists.ozlabs.org [203.11.71.2]) (using TLSv1.2 with cipher ADH-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 41DhLH01P8z9ryk for ; Mon, 25 Jun 2018 17:55:35 +1000 (AEST) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="uATzpB2Q"; dkim-atps=neutral Received: from lists.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3]) by lists.ozlabs.org (Postfix) with ESMTP id 41DhLG5btQzF1L4 for ; Mon, 25 Jun 2018 17:55:34 +1000 (AEST) Authentication-Results: lists.ozlabs.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: lists.ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="uATzpB2Q"; dkim-atps=neutral X-Original-To: linuxppc-dev@lists.ozlabs.org Delivered-To: linuxppc-dev@lists.ozlabs.org Authentication-Results: lists.ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=gmail.com (client-ip=2607:f8b0:400e:c05::242; helo=mail-pg0-x242.google.com; envelope-from=kernelfans@gmail.com; receiver=) Authentication-Results: lists.ozlabs.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: lists.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="uATzpB2Q"; dkim-atps=neutral Received: from mail-pg0-x242.google.com (mail-pg0-x242.google.com [IPv6:2607:f8b0:400e:c05::242]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by lists.ozlabs.org (Postfix) with ESMTPS id 41Dh9Y0XZczF18l for ; Mon, 25 Jun 2018 17:48:00 +1000 (AEST) Received: by mail-pg0-x242.google.com with SMTP id a14-v6so5702773pgw.10 for ; Mon, 25 Jun 2018 00:48:00 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=ogyKAoMRjvIakKgwsQm+pPeeTlRL2F3Jiux73o/n4F8=; b=uATzpB2QYBUEdOyDvmzphlapzwu3DrWZLBUeWIq8nXjvQMXxZ1Q8BF8rTD0e6q5T7F gYjxL58mUUjKj4dR7XTsDszkQpc9iDEvVk5emekO9WjwV1trBYjz5P72tj7vGtSH5ahj KvJDVV/TZsh4J8GQ+zhjhWdM80VxeVpCcMOOqykxSCPlAemHFNKxE0482npNg/gur1mV JYqnYl6cSjwKvWQvSPdBvkQRuUnl4XSJ/YrncgQl42xlcNYYXDMQB1lI7zR31GEQTsc0 mN2ZtLfE3jotwFNpx8cfVHJCD992K9iGaTxe5is5dCni6lghF1IfPixI6sgYddTbC/Rk uwtw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=ogyKAoMRjvIakKgwsQm+pPeeTlRL2F3Jiux73o/n4F8=; b=EKIksZNG5yoSri9yyrMYJVdBGojxmVfv2Wy5oc3CnpLL43bW7hXHfV3tosT6lhwI8/ LjUUvgeU52T54SEeB6MS3nMjZgw17uMHVRTi0/TBPv76b98cHPBpwwEgIlxMCHaCO3wf RSyWun6Kjt1t/SGWytCRTeoEpBZCyVfSVwjxF+VzhaqCyeJ2RWJlxqu1uT4sZM//MU86 wGLlE0XFEH6ej/6lQWszi7MDkR7uF2JLYq6UgmBaXtz/YdpdCaI9t8Hyl3mLQH/3cY1o 7u2q+QZb8TXOKjJRS++RAB4KWsJ4I3dTlvtvwzfP63nbPLV3yQlrOERylIqaq4S5v3mv AuFQ== X-Gm-Message-State: APt69E25KujhXvswcB5q1QUy2/otFv9kgyjy9697aUEnSufuJldRj9lq xSHk9GtZY0z7VwbcfcQXlA== X-Google-Smtp-Source: ADUXVKI9Kps8vpdhaoPNqwcdTtdUHxiqwk+Lm//Aeml3xoN+CLdY1OGhYZ7sI4oBwUvFtfq1Q8i2zA== X-Received: by 2002:a65:554b:: with SMTP id t11-v6mr9919837pgr.130.1529912879200; Mon, 25 Jun 2018 00:47:59 -0700 (PDT) Received: from mylaptop.nay.redhat.com ([209.132.188.80]) by smtp.gmail.com with ESMTPSA id p12-v6sm27350460pfi.175.2018.06.25.00.47.55 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 25 Jun 2018 00:47:58 -0700 (PDT) From: Pingfan Liu To: linux-kernel@vger.kernel.org Subject: [PATCHv2 2/2] drivers/base: reorder consumer and its children behind suppliers Date: Mon, 25 Jun 2018 15:47:39 +0800 Message-Id: <1529912859-10475-3-git-send-email-kernelfans@gmail.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1529912859-10475-1-git-send-email-kernelfans@gmail.com> References: <1529912859-10475-1-git-send-email-kernelfans@gmail.com> X-BeenThere: linuxppc-dev@lists.ozlabs.org X-Mailman-Version: 2.1.26 Precedence: list List-Id: Linux on PowerPC Developers Mail List List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Grygorii Strashko , Greg Kroah-Hartman , linuxppc-dev@lists.ozlabs.org, Pingfan Liu , Christoph Hellwig , Bjorn Helgaas , linux-pci@vger.kernel.org, Dave Young Errors-To: linuxppc-dev-bounces+patchwork-incoming=ozlabs.org@lists.ozlabs.org Sender: "Linuxppc-dev" commit 52cdbdd49853 ("driver core: correct device's shutdown order") introduces supplier<-consumer order in devices_kset. The commit tries to cleverly maintain both parent<-child and supplier<-consumer order by reordering a device when probing. This method makes things simple and clean, but unfortunately, breaks parent<-child order in some case, which is described in next patch in this series. Here this patch tries to resolve supplier<-consumer by only reordering a device when it has suppliers, and takes care of the following scenario: [consumer, children] [ ... potential ... ] supplier ^ ^ After moving the consumer and its children after the supplier, the potentail section may contain consumers whose supplier is inside children, and this poses the requirement to dry out all consumpers in the section recursively. Cc: Greg Kroah-Hartman Cc: Grygorii Strashko Cc: Christoph Hellwig Cc: Bjorn Helgaas Cc: Dave Young Cc: linux-pci@vger.kernel.org Cc: linuxppc-dev@lists.ozlabs.org Signed-off-by: Pingfan Liu --- note: there is lock issue in this patch, should be fixed in next version --- drivers/base/core.c | 132 ++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 129 insertions(+), 3 deletions(-) diff --git a/drivers/base/core.c b/drivers/base/core.c index 66f06ff..db30e86 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -123,12 +123,138 @@ static int device_is_dependent(struct device *dev, void *target) return ret; } -/* a temporary place holder to mark out the root cause of the bug. - * The proposal algorithm will come in next patch +struct pos_info { + struct device *pos; + struct device *tail; +}; + +/* caller takes the devices_kset->list_lock */ +static int descendants_reorder_after_pos(struct device *dev, + void *data) +{ + struct device *pos; + struct pos_info *p = data; + + pos = p->pos; + pr_debug("devices_kset: Moving %s after %s\n", + dev_name(dev), dev_name(pos)); + device_for_each_child(dev, p, descendants_reorder_after_pos); + /* children at the tail */ + list_move(&dev->kobj.entry, &pos->kobj.entry); + /* record the right boundary of the section */ + if (p->tail == NULL) + p->tail = dev; + return 0; +} + +/* iterate over an open section */ +#define list_opensect_for_each_reverse(cur, left, right) \ + for (cur = right->prev; cur == left; cur = cur->prev) + +static bool is_consumer(struct device *query, struct device *supplier) +{ + struct device_link *link; + /* todo, lock protection */ + list_for_each_entry(link, &supplier->links.consumers, s_node) + if (link->consumer == query) + return true; + return false; +} + +/* recursively move the potential consumers in open section (left, right) + * after the barrier + */ +static int __device_reorder_consumer(struct device *consumer, + struct list_head *left, struct list_head *right, + struct pos_info *p) +{ + struct list_head *iter; + struct device *c_dev, *s_dev, *tail_dev; + + descendants_reorder_after_pos(consumer, p); + tail_dev = p->tail; + /* (left, right) may contain consumers, hence checking if any moved + * child serving as supplier. The reversing order help us to meet + * the last supplier of a consumer. + */ + list_opensect_for_each_reverse(iter, left, right) { + struct list_head *l_iter, *moved_left, *moved_right; + + moved_left = (&consumer->kobj.entry)->prev; + moved_right = tail_dev->kobj.entry.next; + /* the moved section may contain potential suppliers */ + list_opensect_for_each_reverse(l_iter, moved_left, + moved_right) { + s_dev = list_entry(l_iter, struct device, kobj.entry); + c_dev = list_entry(iter, struct device, kobj.entry); + /* to fix: this poses extra effort for locking */ + if (is_consumer(c_dev, s_dev)) { + p->tail = NULL; + /* to fix: lock issue */ + p->pos = s_dev; + /* reorder after the last supplier */ + __device_reorder_consumer(c_dev, + l_iter, right, p); + } + } + } + return 0; +} + +static int find_last_supplier(struct device *dev, struct device *supplier) +{ + struct device_link *link; + + list_for_each_entry_reverse(link, &dev->links.suppliers, c_node) { + if (link->supplier == supplier) + return 1; + } + if (dev == supplier) + return -1; + return 0; +} + +/* When reodering, take care of the range of (old_pos(dev), new_pos(dev)), + * there may be requirement to recursively move item. */ int device_reorder_consumer(struct device *dev) { - devices_kset_move_last(dev); + struct list_head *iter, *left, *right; + struct device *cur_dev; + struct pos_info info; + int ret, idx; + + idx = device_links_read_lock(); + if (list_empty(&dev->links.suppliers)) { + device_links_read_unlock(idx); + return 0; + } + spin_lock(&devices_kset->list_lock); + list_for_each_prev(iter, &devices_kset->list) { + cur_dev = list_entry(iter, struct device, kobj.entry); + ret = find_last_supplier(dev, cur_dev); + switch (ret) { + case -1: + goto unlock; + case 1: + break; + case 0: + continue; + } + } + BUG_ON(!ret); + + /* record the affected open section */ + left = dev->kobj.entry.prev; + right = iter; + info.pos = list_entry(iter, struct device, kobj.entry); + info.tail = NULL; + /* dry out the consumers in (left,right) */ + __device_reorder_consumer(dev, left, right, &info); + +unlock: + spin_unlock(&devices_kset->list_lock); + device_links_read_unlock(idx); return 0; }