From patchwork Fri Aug 26 17:23:01 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Keith Busch X-Patchwork-Id: 663188 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 3sLSb43dc4z9sRB for ; Sat, 27 Aug 2016 03:24:32 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753600AbcHZRYI (ORCPT ); Fri, 26 Aug 2016 13:24:08 -0400 Received: from mga01.intel.com ([192.55.52.88]:25418 "EHLO mga01.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753103AbcHZRYH (ORCPT ); Fri, 26 Aug 2016 13:24:07 -0400 Received: from fmsmga002.fm.intel.com ([10.253.24.26]) by fmsmga101.fm.intel.com with ESMTP; 26 Aug 2016 10:24:06 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.28,581,1464678000"; d="scan'208";a="1047740440" Received: from dcgshare.lm.intel.com ([10.232.118.254]) by fmsmga002.fm.intel.com with ESMTP; 26 Aug 2016 10:24:06 -0700 Received: by dcgshare.lm.intel.com (Postfix, from userid 1017) id BF910E00EA; Fri, 26 Aug 2016 11:24:05 -0600 (MDT) From: Keith Busch To: linux-pci@vger.kernel.org, Bjorn Helgaas , Thomas Gleixner Cc: LKML , x86@kernel.org, Keith Busch Subject: [PATCHv2 1/2] pciehp: Let user control LED status Date: Fri, 26 Aug 2016 11:23:01 -0600 Message-Id: <1472232182-1448-2-git-send-email-keith.busch@intel.com> X-Mailer: git-send-email 1.7.1 In-Reply-To: <1472232182-1448-1-git-send-email-keith.busch@intel.com> References: <1472232182-1448-1-git-send-email-keith.busch@intel.com> 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 ignore PCIe slot LED indicators. The pciehp driver will instead provide exclusive attention control to the user by setting the slot control exactly as the user requested with out interpreting the input. This is preparing for domain devices that repurpose these for non-standard use. Signed-off-by: Keith Busch --- drivers/pci/hotplug/pciehp.h | 1 + drivers/pci/hotplug/pciehp_core.c | 26 ++++++++++++++++++++++++++ drivers/pci/hotplug/pciehp_hpc.c | 6 +++++- include/linux/pci.h | 1 + 4 files changed, 33 insertions(+), 1 deletion(-) diff --git a/drivers/pci/hotplug/pciehp.h b/drivers/pci/hotplug/pciehp.h index e764918..ed62645 100644 --- a/drivers/pci/hotplug/pciehp.h +++ b/drivers/pci/hotplug/pciehp.h @@ -151,6 +151,7 @@ int pciehp_check_link_status(struct controller *ctrl); bool pciehp_check_link_active(struct controller *ctrl); void pciehp_release_ctrl(struct controller *ctrl); int pciehp_reset_slot(struct slot *slot, int probe); +void pcie_write_cmd_nowait(struct controller *ctrl, u16 cmd, u16 mask); static inline const char *slot_name(struct slot *slot) { diff --git a/drivers/pci/hotplug/pciehp_core.c b/drivers/pci/hotplug/pciehp_core.c index ac531e6..ad19b33 100644 --- a/drivers/pci/hotplug/pciehp_core.c +++ b/drivers/pci/hotplug/pciehp_core.c @@ -70,6 +70,8 @@ static int get_attention_status(struct hotplug_slot *slot, u8 *value); static int get_latch_status(struct hotplug_slot *slot, u8 *value); static int get_adapter_status(struct hotplug_slot *slot, u8 *value); static int reset_slot(struct hotplug_slot *slot, int probe); +static int set_user_led_status(struct hotplug_slot *slot, u8 value); +static int get_user_led_status(struct hotplug_slot *slot, u8 *value); /** * release_slot - free up the memory used by a slot @@ -114,6 +116,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 = get_user_led_status; + ops->set_attention_status = set_user_led_status; } /* register this slot with the hotplug pci core */ @@ -142,6 +147,27 @@ static void cleanup_slot(struct controller *ctrl) pci_hp_deregister(ctrl->slot->hotplug_slot); } +static int get_user_led_status(struct hotplug_slot *hotplug_slot, u8 *value) +{ + u16 slot_ctrl; + struct slot *slot = hotplug_slot->private; + struct pci_dev *pdev = slot->ctrl->pcie->port; + + pcie_capability_read_word(pdev, PCI_EXP_SLTCTL, &slot_ctrl); + *value = (slot_ctrl & (PCI_EXP_SLTCTL_AIC | PCI_EXP_SLTCTL_PIC)) >> 6; + + return 0; +} + +static int set_user_led_status(struct hotplug_slot *hotplug_slot, u8 status) +{ + struct slot *slot = hotplug_slot->private; + + pcie_write_cmd_nowait(slot->ctrl, status << 6, + PCI_EXP_SLTCTL_AIC | PCI_EXP_SLTCTL_PIC); + return 0; +} + /* * set_attention_status - Turns the Amber LED for a slot on, off or blink */ diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c index 08e84d6..51cfc96 100644 --- a/drivers/pci/hotplug/pciehp_hpc.c +++ b/drivers/pci/hotplug/pciehp_hpc.c @@ -228,7 +228,7 @@ static void pcie_write_cmd(struct controller *ctrl, u16 cmd, u16 mask) } /* Same as above without waiting for the hardware to latch */ -static void pcie_write_cmd_nowait(struct controller *ctrl, u16 cmd, u16 mask) +void pcie_write_cmd_nowait(struct controller *ctrl, u16 cmd, u16 mask) { pcie_do_write_cmd(ctrl, cmd, mask, false); } @@ -804,6 +804,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 bbca681..a8ba7d7 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -309,6 +309,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 */