From patchwork Tue Sep 13 16:31:59 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Keith Busch X-Patchwork-Id: 669470 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 3sYVZQ6gx5z9ryv for ; Wed, 14 Sep 2016 02:32:14 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1756837AbcIMQcE (ORCPT ); Tue, 13 Sep 2016 12:32:04 -0400 Received: from mga01.intel.com ([192.55.52.88]:8132 "EHLO mga01.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1759047AbcIMQcB (ORCPT ); Tue, 13 Sep 2016 12:32:01 -0400 Received: from fmsmga006.fm.intel.com ([10.253.24.20]) by fmsmga101.fm.intel.com with ESMTP; 13 Sep 2016 09:32:00 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.30,329,1470726000"; d="scan'208";a="7929918" Received: from dcgshare.lm.intel.com ([10.232.118.254]) by fmsmga006.fm.intel.com with ESMTP; 13 Sep 2016 09:32:00 -0700 Received: by dcgshare.lm.intel.com (Postfix, from userid 1017) id 49650E0C6D; Tue, 13 Sep 2016 10:32:00 -0600 (MDT) From: Keith Busch To: linux-pci@vger.kernel.org, Bjorn Helgaas Cc: Keith Busch Subject: [PATCHv4] pciehp: Let user control LED status Date: Tue, 13 Sep 2016 10:31:59 -0600 Message-Id: <1473784319-6137-1-git-send-email-keith.busch@intel.com> X-Mailer: git-send-email 1.7.1 Sender: linux-pci-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pci@vger.kernel.org This patch adds a new flag to the pci_dev structure instructing pciehp to not interpret PCIe slot LED indicators. The pciehp driver will instead allow all LED control from the user by setting the slot control indicators as the user requested through sysfs. This is preparing for domain devices that repurpose these control bits for non-standard use. Signed-off-by: Keith Busch --- v3 -> v4: Fixing symbol usage by generating patch from the tree that compiles correctly. drivers/pci/hotplug/pciehp.h | 5 +++++ drivers/pci/hotplug/pciehp_core.c | 3 +++ drivers/pci/hotplug/pciehp_hpc.c | 27 +++++++++++++++++++++++++++ include/linux/pci.h | 1 + 4 files changed, 36 insertions(+) diff --git a/drivers/pci/hotplug/pciehp.h b/drivers/pci/hotplug/pciehp.h index e764918..725078d 100644 --- a/drivers/pci/hotplug/pciehp.h +++ b/drivers/pci/hotplug/pciehp.h @@ -152,6 +152,11 @@ bool pciehp_check_link_active(struct controller *ctrl); void pciehp_release_ctrl(struct controller *ctrl); int pciehp_reset_slot(struct slot *slot, int probe); +int pciehp_set_raw_attention_status(struct hotplug_slot *hotplug_slot, + u8 status); +int pciehp_get_raw_attention_status(struct hotplug_slot *hotplug_slot, + u8 *status); + static inline const char *slot_name(struct slot *slot) { return hotplug_slot_name(slot->hotplug_slot); diff --git a/drivers/pci/hotplug/pciehp_core.c b/drivers/pci/hotplug/pciehp_core.c index fb0f863..68b7aeb 100644 --- a/drivers/pci/hotplug/pciehp_core.c +++ b/drivers/pci/hotplug/pciehp_core.c @@ -113,6 +113,9 @@ static int init_slot(struct controller *ctrl) if (ATTN_LED(ctrl)) { ops->get_attention_status = get_attention_status; ops->set_attention_status = set_attention_status; + } else if (ctrl->pcie->port->user_leds) { + ops->get_attention_status = pciehp_get_raw_attention_status; + ops->set_attention_status = pciehp_set_raw_attention_status; } /* register this slot with the hotplug pci core */ diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c index 08e84d6..5ab8604 100644 --- a/drivers/pci/hotplug/pciehp_hpc.c +++ b/drivers/pci/hotplug/pciehp_hpc.c @@ -355,6 +355,18 @@ static int pciehp_link_enable(struct controller *ctrl) return __pciehp_link_set(ctrl, true); } +int pciehp_get_raw_attention_status(struct hotplug_slot *hotplug_slot, + u8 *status) +{ + struct slot *slot = hotplug_slot->private; + struct pci_dev *pdev = ctrl_dev(slot->ctrl); + u16 slot_ctrl; + + pcie_capability_read_word(pdev, PCI_EXP_SLTCTL, &slot_ctrl); + *status = (slot_ctrl & (PCI_EXP_SLTCTL_AIC | PCI_EXP_SLTCTL_PIC)) >> 6; + return 0; +} + void pciehp_get_attention_status(struct slot *slot, u8 *status) { struct controller *ctrl = slot->ctrl; @@ -431,6 +443,17 @@ int pciehp_query_power_fault(struct slot *slot) return !!(slot_status & PCI_EXP_SLTSTA_PFD); } +int pciehp_set_raw_attention_status(struct hotplug_slot *hotplug_slot, + u8 status) +{ + struct slot *slot = hotplug_slot->private; + struct controller *ctrl = slot->ctrl; + + pcie_write_cmd_nowait(ctrl, status << 6, + PCI_EXP_SLTCTL_AIC | PCI_EXP_SLTCTL_PIC); + return 0; +} + void pciehp_set_attention_status(struct slot *slot, u8 value) { struct controller *ctrl = slot->ctrl; @@ -804,6 +827,10 @@ struct controller *pcie_init(struct pcie_device *dev) } ctrl->pcie = dev; pcie_capability_read_dword(pdev, PCI_EXP_SLTCAP, &slot_cap); + + if (pdev->user_leds) + slot_cap &= ~(PCI_EXP_SLTCAP_AIP | PCI_EXP_SLTCAP_PIP); + ctrl->slot_cap = slot_cap; mutex_init(&ctrl->ctrl_lock); init_waitqueue_head(&ctrl->queue); diff --git a/include/linux/pci.h b/include/linux/pci.h index 7256f33..f41bbca 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -308,6 +308,7 @@ struct pci_dev { powered on/off by the corresponding bridge */ unsigned int ignore_hotplug:1; /* Ignore hotplug events */ + unsigned int user_leds:1; /* User excluse LED SlotCtl */ unsigned int d3_delay; /* D3->D0 transition time in ms */ unsigned int d3cold_delay; /* D3cold->D0 transition time in ms */