From patchwork Tue Sep 13 15:05:39 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Keith Busch X-Patchwork-Id: 669410 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 3sYSff13Ksz9sC4 for ; Wed, 14 Sep 2016 01:05:46 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1758923AbcIMPFn (ORCPT ); Tue, 13 Sep 2016 11:05:43 -0400 Received: from mga05.intel.com ([192.55.52.43]:43925 "EHLO mga05.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1758739AbcIMPFm (ORCPT ); Tue, 13 Sep 2016 11:05:42 -0400 Received: from fmsmga002.fm.intel.com ([10.253.24.26]) by fmsmga105.fm.intel.com with ESMTP; 13 Sep 2016 08:05:41 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.30,329,1470726000"; d="scan'208";a="1055368282" Received: from dcgshare.lm.intel.com ([10.232.118.254]) by fmsmga002.fm.intel.com with ESMTP; 13 Sep 2016 08:05:41 -0700 Received: by dcgshare.lm.intel.com (Postfix, from userid 1017) id 00E17E0C74; Tue, 13 Sep 2016 09:05:40 -0600 (MDT) From: Keith Busch To: linux-pci@vger.kernel.org, Bjorn Helgaas , Thomas Gleixner Cc: LKML , Keith Busch Subject: [PATCHv3 1/2] pciehp: Let user control LED status Date: Tue, 13 Sep 2016 09:05:39 -0600 Message-Id: <1473779140-4016-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 --- v2 -> v3: Moved the slot op's attention status callback to pciehp_hpc.c 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..7f71ac1 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 *value); + 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..fccb63d 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 *value) +{ + 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, value << 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 */