From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753197AbYKDNc3 (ORCPT ); Tue, 4 Nov 2008 08:32:29 -0500 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S1751888AbYKDNcV (ORCPT ); Tue, 4 Nov 2008 08:32:21 -0500 Received: from cavan.codon.org.uk ([93.93.128.6]:50274 "EHLO vavatch.codon.org.uk" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751879AbYKDNcU (ORCPT ); Tue, 4 Nov 2008 08:32:20 -0500 Date: Tue, 4 Nov 2008 13:32:14 +0000 From: Matthew Garrett To: Alan Jenkins Cc: linux-kernel@vger.kernel.org Subject: Re: Add option to passively listen for PCIE hotplug events Message-ID: <20081104133214.GA20427@srcf.ucam.org> References: <20081104124706.GB19401@srcf.ucam.org> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20081104124706.GB19401@srcf.ucam.org> User-Agent: Mutt/1.5.12-2006-07-14 X-SA-Exim-Connect-IP: X-SA-Exim-Mail-From: mjg59@codon.org.uk X-SA-Exim-Scanned: No (on vavatch.codon.org.uk); SAEximRunCond expanded to false Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Can you try this one? diff --git a/drivers/pci/hotplug/pciehp.h b/drivers/pci/hotplug/pciehp.h index b2801a7..c9f18f9 100644 --- a/drivers/pci/hotplug/pciehp.h +++ b/drivers/pci/hotplug/pciehp.h @@ -224,6 +224,10 @@ static inline int pciehp_get_hp_hw_control_from_firmware(struct pci_dev *dev) { u32 flags = (OSC_PCI_EXPRESS_NATIVE_HP_CONTROL | OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL); + if (pciehp_force) { + dev_info(&dev->dev, "Bypassing BIOS check for pciehp\n"); + return 0; + } return acpi_get_hp_hw_control_from_firmware(dev, flags); } diff --git a/drivers/pci/hotplug/pciehp_core.c b/drivers/pci/hotplug/pciehp_core.c index 4b23bc3..429e505 100644 --- a/drivers/pci/hotplug/pciehp_core.c +++ b/drivers/pci/hotplug/pciehp_core.c @@ -41,6 +41,7 @@ int pciehp_debug; int pciehp_poll_mode; int pciehp_poll_time; int pciehp_force; +int pciehp_passive=1; struct workqueue_struct *pciehp_wq; #define DRIVER_VERSION "0.4" @@ -50,15 +51,18 @@ struct workqueue_struct *pciehp_wq; MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); +MODULE_ALIAS("acpi*:PNP0A08:*"); module_param(pciehp_debug, bool, 0644); module_param(pciehp_poll_mode, bool, 0644); module_param(pciehp_poll_time, int, 0644); module_param(pciehp_force, bool, 0644); +module_param(pciehp_passive, bool, 0644); MODULE_PARM_DESC(pciehp_debug, "Debugging mode enabled or not"); MODULE_PARM_DESC(pciehp_poll_mode, "Using polling mechanism for hot-plug events or not"); MODULE_PARM_DESC(pciehp_poll_time, "Polling mechanism frequency, in seconds"); MODULE_PARM_DESC(pciehp_force, "Force pciehp, even if _OSC and OSHP are missing"); +MODULE_PARM_DESC(pciehp_passive, "Listen for pciehp events, even if _OSC and OSHP are missing"); #define PCIE_MODULE_NAME "pciehp" @@ -85,6 +89,13 @@ static struct hotplug_slot_ops pciehp_hotplug_slot_ops = { .get_cur_bus_speed = get_cur_bus_speed, }; +static struct hotplug_slot_ops pciehp_passive_hotplug_slot_ops = { + .owner = THIS_MODULE, + .get_adapter_status = get_adapter_status, + .get_max_bus_speed = get_max_bus_speed, + .get_cur_bus_speed = get_cur_bus_speed, +}; + /* * Check the status of the Electro Mechanical Interlock (EMI) */ @@ -212,7 +223,11 @@ static int init_slots(struct controller *ctrl) hotplug_slot->info = info; hotplug_slot->private = slot; hotplug_slot->release = &release_slot; - hotplug_slot->ops = &pciehp_hotplug_slot_ops; + if (pciehp_passive && + pciehp_get_hp_hw_control_from_firmware(ctrl->pci_dev)) + hotplug_slot->ops = &pciehp_passive_hotplug_slot_ops; + else + hotplug_slot->ops = &pciehp_hotplug_slot_ops; slot->hotplug_slot = hotplug_slot; snprintf(name, SLOT_NAME_SIZE, "%u", slot->number); @@ -407,11 +422,7 @@ static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_ u8 value; struct pci_dev *pdev = dev->port; - if (pciehp_force) - dev_info(&dev->device, - "Bypassing BIOS check for pciehp use on %s\n", - pci_name(pdev)); - else if (pciehp_get_hp_hw_control_from_firmware(pdev)) + if (!pciehp_passive && pciehp_get_hp_hw_control_from_firmware(pdev)) goto err_out_none; ctrl = pcie_init(dev); @@ -435,11 +446,9 @@ static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_ t_slot = pciehp_find_slot(ctrl, ctrl->slot_device_offset); t_slot->hpc_ops->get_adapter_status(t_slot, &value); /* Check if slot is occupied */ - if (value && pciehp_force) { - rc = pciehp_enable_slot(t_slot); - if (rc) /* -ENODEV: shouldn't happen, but deal with it */ - value = 0; - } + if (value && (pciehp_force || pciehp_passive)) + pciehp_enable_slot(t_slot); + if ((POWER_CTRL(ctrl)) && !value) { rc = t_slot->hpc_ops->power_off_slot(t_slot); /* Power off slot if not occupied*/ if (rc) @@ -473,8 +482,11 @@ static int pciehp_suspend (struct pcie_device *dev, pm_message_t state) static int pciehp_resume (struct pcie_device *dev) { + struct pci_dev *pdev = dev->port; dev_info(&dev->device, "%s ENTRY\n", __func__); - if (pciehp_force) { + + if (pciehp_force || (pciehp_passive && + pciehp_get_hp_hw_control_from_firmware(pdev))) { struct controller *ctrl = get_service_data(dev); struct slot *t_slot; u8 status; diff --git a/drivers/pci/hotplug/pciehp_ctrl.c b/drivers/pci/hotplug/pciehp_ctrl.c index fead63c..87b704d 100644 --- a/drivers/pci/hotplug/pciehp_ctrl.c +++ b/drivers/pci/hotplug/pciehp_ctrl.c @@ -185,7 +185,8 @@ static void set_slot_off(struct controller *ctrl, struct slot * pslot) * before taking any action that relies on power having been * removed from the slot/adapter. */ - msleep(1000); + if (PWR_LED(ctrl) || ATTN_LED(ctrl)) + msleep(1000); if (PWR_LED(ctrl)) pslot->hpc_ops->green_led_off(pslot); -- Matthew Garrett | mjg59@srcf.ucam.org