From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751913Ab3FWAWY (ORCPT ); Sat, 22 Jun 2013 20:22:24 -0400 Received: from mail-ie0-f173.google.com ([209.85.223.173]:41584 "EHLO mail-ie0-f173.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751487Ab3FWAWV (ORCPT ); Sat, 22 Jun 2013 20:22:21 -0400 MIME-Version: 1.0 In-Reply-To: <15269989.ojxutYs2L1@vostro.rjw.lan> References: <2737587.I0nULev1kj@vostro.rjw.lan> <15269989.ojxutYs2L1@vostro.rjw.lan> Date: Sat, 22 Jun 2013 17:22:20 -0700 X-Google-Sender-Auth: 4FxZHtuIVek3KyYhX_jQilwuJ4E Message-ID: Subject: Re: [PATCH 3/3] ACPI / dock / PCI: Synchronous handling of dock events for PCI devices From: Yinghai Lu To: "Rafael J. Wysocki" Cc: ACPI Devel Maling List , Bjorn Helgaas , "Alexander E . Patrakov" , Jiang Liu , Greg Kroah-Hartman , Yijing Wang , Jiang Liu , "linux-pci@vger.kernel.org" , Linux Kernel Mailing List Content-Type: text/plain; charset=ISO-8859-1 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On Sat, Jun 22, 2013 at 2:25 PM, Rafael J. Wysocki wrote: > From: Rafael J. Wysocki > > To resolve that deadlock use the observation that > unregister_hotplug_dock_device() won't need to acquire hp_lock > if PCI bridges the devices on the dock station depend on are > prevented from being removed prematurely while the first loop in > hotplug_dock_devices() is in progress. > > To make that possible, introduce a mechanism by which the callers of > register_hotplug_dock_device() can provide "init" and "release" > routines that will be executed, respectively, after the addition > and removal of the physical device object associated with the > given ACPI device handle. Make acpiphp use two new functions, > acpiphp_dock_init() and acpiphp_dock_release(), respectively, > calling get_bridge() and put_bridge() on the PCI bridge holding the > given device, respectively, for this purpose. > > In addition to that, remove the dock station's list of > "hotplug devices" and make the dock code always walk the whole list > of "dependent devices" instead in such a way that the loops in > hotplug_dock_devices() and dock_event() (replacing the loops over > "hotplug devices") will take references to the list entries that > register_hotplug_dock_device() has been called for. That prevents > the "release" routines associated with those entries from being > called while the given entry is being processed and for PCI > devices this means that their bridges won't be removed (by a > concurrent thread) while hotplug_event_func() handling them is > being executed. .. > -static void > -dock_del_hotplug_device(struct dock_station *ds, > - struct dock_dependent_device *dd) > +static void dock_release_hotplug(struct dock_dependent_device *dd) > { > - mutex_lock(&ds->hp_lock); > - list_del(&dd->hotplug_list); > - mutex_unlock(&ds->hp_lock); > + void (*release)(void *) = NULL; > + void *context = NULL; > + > + mutex_lock(&hotplug_lock); > + > + if (dd->hp_context && !--dd->hp_refcount) { > + dd->hp_ops = NULL; > + context = dd->hp_context; > + dd->hp_context = NULL; > + release = dd->hp_release; > + dd->hp_release = NULL; > + } > + > + if (release && context) > + release(context); > + > + mutex_unlock(&hotplug_lock); > +} > + > +static void dock_hotplug_event(struct dock_dependent_device *dd, u32 event, > + bool uevent) > +{ > + acpi_notify_handler cb = NULL; > + bool run = false; > + > + mutex_lock(&hotplug_lock); > + > + if (dd->hp_context) { > + run = true; > + dd->hp_refcount++; > + if (dd->hp_ops) > + cb = uevent ? dd->hp_ops->uevent : dd->hp_ops->handler; > + } > + > + mutex_unlock(&hotplug_lock); > + > + if (!run) > + return; > + > + if (cb) > + cb(dd->handle, event, dd->hp_context); > + > + dock_release_hotplug(dd); during DOCKING, dock_release_hotplug get called too? Yinghai