From patchwork Fri Apr 27 15:16:51 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jiang Liu X-Patchwork-Id: 155514 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id E7110B6FA5 for ; Sat, 28 Apr 2012 01:24:36 +1000 (EST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1760579Ab2D0PVd (ORCPT ); Fri, 27 Apr 2012 11:21:33 -0400 Received: from mail-pb0-f46.google.com ([209.85.160.46]:61293 "EHLO mail-pb0-f46.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1760581Ab2D0PVa (ORCPT ); Fri, 27 Apr 2012 11:21:30 -0400 Received: by mail-pb0-f46.google.com with SMTP id rp8so666347pbb.19 for ; Fri, 27 Apr 2012 08:21:30 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:cc:subject:date:message-id:x-mailer:in-reply-to:references; bh=LAuTX/OS5oc/uO2ehDsSurND5ex1Vi1UPIy3Fi5/lNM=; b=QApiwlRvMtqQyYmp/Rn6Gf67S0qcyvsydIQvPmxI+Fa0gzSaSM9znYxnXzWSieRGmV PvGYUdbPnn34qCCXMLGd5FBRWu/5MdO8hjFKu7+bnTA2WY6tPjuSbhXiRR4lHsd+Sdqk ay4zhWuxL4Sq7/1EZWWV/LCo7H+Ua9+jzHMiiruBz2Kayscb3CP+idnJSluEGMoCygq4 prgk4t0UrgAWrzeijM7sL+vqafeCNOAX3p7nmFqeWHvSaAmbNeDJHTok3lMcxKUkf+16 hRxRBAGcf6dnu+IBMxhybAMI58GAu4H7k2YBC800HfLRA0dH0YKAdyOfUakCcgXKxJ/n EeXw== Received: by 10.68.132.41 with SMTP id or9mr13854978pbb.30.1335540090190; Fri, 27 Apr 2012 08:21:30 -0700 (PDT) Received: from localhost.localdomain ([221.221.26.142]) by mx.google.com with ESMTPS id 2sm6743917pbw.57.2012.04.27.08.21.21 (version=TLSv1/SSLv3 cipher=OTHER); Fri, 27 Apr 2012 08:21:29 -0700 (PDT) From: Jiang Liu To: Yinghai Lu , Kenji Kaneshige , Bjorn Helgaas , Don Dutile , Greg KH Cc: Jiang Liu , Keping Chen , linux-kernel@vger.kernel.org, linux-pci@vger.kernel.org, Jiang Liu Subject: [PATCH v2 10/19] PCI: serialize hotplug operaitons triggered by the shpchp driver Date: Fri, 27 Apr 2012 23:16:51 +0800 Message-Id: <1335539820-11232-11-git-send-email-jiang.liu@huawei.com> X-Mailer: git-send-email 1.7.5.4 In-Reply-To: <1335539820-11232-1-git-send-email-jiang.liu@huawei.com> References: <1335539820-11232-1-git-send-email-jiang.liu@huawei.com> Sender: linux-pci-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pci@vger.kernel.org From: Jiang Liu Use PCI hotplug lock to serialize hotplug operations triggered by the shpchp driver. Signed-off-by: Jiang Liu --- drivers/pci/hotplug/shpchp.h | 2 ++ drivers/pci/hotplug/shpchp_core.c | 3 ++- drivers/pci/hotplug/shpchp_ctrl.c | 32 ++++++++++++++++++++++++++++++++ 3 files changed, 36 insertions(+), 1 deletions(-) diff --git a/drivers/pci/hotplug/shpchp.h b/drivers/pci/hotplug/shpchp.h index 6691dc4..07f3b2d 100644 --- a/drivers/pci/hotplug/shpchp.h +++ b/drivers/pci/hotplug/shpchp.h @@ -157,6 +157,7 @@ struct controller { #define BLINKINGOFF_STATE 2 #define POWERON_STATE 3 #define POWEROFF_STATE 4 +#define SHUTDOWN_STATE 5 /* Error messages */ #define INTERLOCK_OPEN 0x00000002 @@ -179,6 +180,7 @@ extern u8 shpchp_handle_presence_change(u8 hp_slot, struct controller *ctrl); extern u8 shpchp_handle_power_fault(u8 hp_slot, struct controller *ctrl); extern int shpchp_configure_device(struct slot *p_slot); extern int shpchp_unconfigure_device(struct slot *p_slot); +extern void shpchp_shutdown_slot(struct slot *slot); extern void cleanup_slots(struct controller *ctrl); extern void shpchp_queue_pushbutton_work(struct work_struct *work); extern int shpc_init( struct controller *ctrl, struct pci_dev *pdev); diff --git a/drivers/pci/hotplug/shpchp_core.c b/drivers/pci/hotplug/shpchp_core.c index 19762b3..71cc5f2 100644 --- a/drivers/pci/hotplug/shpchp_core.c +++ b/drivers/pci/hotplug/shpchp_core.c @@ -172,10 +172,11 @@ void cleanup_slots(struct controller *ctrl) list_for_each_safe(tmp, next, &ctrl->slot_list) { slot = list_entry(tmp, struct slot, slot_list); - list_del(&slot->slot_list); flush_workqueue(shpchp_wq); cancel_delayed_work_sync(&slot->work); + shpchp_shutdown_slot(slot); flush_workqueue(shpchp_ordered_wq); + list_del(&slot->slot_list); pci_hp_deregister(slot->hotplug_slot); } } diff --git a/drivers/pci/hotplug/shpchp_ctrl.c b/drivers/pci/hotplug/shpchp_ctrl.c index b00b09b..7b8e3a6 100644 --- a/drivers/pci/hotplug/shpchp_ctrl.c +++ b/drivers/pci/hotplug/shpchp_ctrl.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include "../pci.h" #include "shpchp.h" @@ -406,6 +407,18 @@ static void shpchp_pushbutton_thread(struct work_struct *work) struct pushbutton_work_info *info = container_of(work, struct pushbutton_work_info, work); struct slot *p_slot = info->p_slot; + bool shutdown; + + /* Break possible deadlock by using pci_hotplug_try_enter() */ + while (!pci_hotplug_try_enter()) { + mutex_lock(&p_slot->lock); + shutdown = p_slot->state == SHUTDOWN_STATE; + mutex_unlock(&p_slot->lock); + if (shutdown) + goto out; + else + mdelay(1); + } mutex_lock(&p_slot->lock); switch (p_slot->state) { @@ -427,6 +440,9 @@ static void shpchp_pushbutton_thread(struct work_struct *work) } mutex_unlock(&p_slot->lock); + pci_hotplug_exit(); + +out: kfree(info); } @@ -729,3 +745,19 @@ int shpchp_sysfs_disable_slot(struct slot *p_slot) return retval; } + +void shpchp_shutdown_slot(struct slot *slot) +{ + u8 getstatus; + + mutex_lock(&slot->lock); + slot->state = SHUTDOWN_STATE; + mutex_unlock(&slot->lock); + + slot->hpc_ops->set_attention_status(slot, 0); + slot->hpc_ops->get_power_status(slot, &getstatus); + if (getstatus) + slot->hpc_ops->green_led_on(slot); + else + slot->hpc_ops->green_led_off(slot); +}