From patchwork Mon Aug 5 08:54:56 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yijing Wang X-Patchwork-Id: 2838594 X-Patchwork-Delegate: bhelgaas@google.com Return-Path: X-Original-To: patchwork-linux-pci@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 437B39F485 for ; Mon, 5 Aug 2013 08:55:38 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id C8BB1201EE for ; Mon, 5 Aug 2013 08:55:36 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 8CD60201F2 for ; Mon, 5 Aug 2013 08:55:34 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755357Ab3HEIz3 (ORCPT ); Mon, 5 Aug 2013 04:55:29 -0400 Received: from szxga01-in.huawei.com ([119.145.14.64]:18419 "EHLO szxga01-in.huawei.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754963Ab3HEIzY (ORCPT ); Mon, 5 Aug 2013 04:55:24 -0400 Received: from 172.24.2.119 (EHLO szxeml213-edg.china.huawei.com) ([172.24.2.119]) by szxrg01-dlp.huawei.com (MOS 4.3.4-GA FastPath queued) with ESMTP id BGG00813; Mon, 05 Aug 2013 16:55:22 +0800 (CST) Received: from SZXEML419-HUB.china.huawei.com (10.82.67.158) by szxeml213-edg.china.huawei.com (172.24.2.30) with Microsoft SMTP Server (TLS) id 14.1.323.7; Mon, 5 Aug 2013 16:55:21 +0800 Received: from localhost (10.135.76.69) by szxeml419-hub.china.huawei.com (10.82.67.158) with Microsoft SMTP Server id 14.1.323.7; Mon, 5 Aug 2013 16:55:14 +0800 From: Yijing Wang To: Bjorn Helgaas CC: , Rafael , Oliver Neukum , Gu Zheng , Paul Bolle , Hanjun Guo , , Yijing Wang Subject: [PATCH -v5 4/6] PCI: add pci_serial_number_changed() for device change identification Date: Mon, 5 Aug 2013 16:54:56 +0800 Message-ID: <1375692898-27476-5-git-send-email-wangyijing@huawei.com> X-Mailer: git-send-email 1.7.11.msysgit.1 In-Reply-To: <1375692898-27476-1-git-send-email-wangyijing@huawei.com> References: <1375692898-27476-1-git-send-email-wangyijing@huawei.com> MIME-Version: 1.0 X-Originating-IP: [10.135.76.69] X-CFilter-Loop: Reflected Sender: linux-pci-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pci@vger.kernel.org X-Spam-Status: No, score=-6.9 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Sometimes OS do not know the physical device swap, for instance, some device hotplug during system suspend. Interrupt can not deliver to OS in some platform. So we can use pci serial number capability to detect this issue if device supports serial number. Signed-off-by: Yijing Wang Cc: Paul Bolle Cc: "Rafael J. Wysocki" Cc: Oliver Neukum Cc: Gu Zheng Cc: linux-pci@vger.kernel.org --- drivers/pci/access.c | 9 --------- drivers/pci/pci.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ drivers/pci/pci.h | 8 ++++++++ include/linux/pci.h | 2 ++ 4 files changed, 58 insertions(+), 9 deletions(-) diff --git a/drivers/pci/access.c b/drivers/pci/access.c index 0069981..7f8df11 100644 --- a/drivers/pci/access.c +++ b/drivers/pci/access.c @@ -194,15 +194,6 @@ PCI_USER_WRITE_CONFIG(dword, u32) /* VPD access through PCI 2.2+ VPD capability */ - -struct pci_vpd_pci22 { - struct pci_vpd base; - struct mutex lock; - u16 flag; - bool busy; - u8 cap; -}; - /* * Wait for last operation to complete. * This code has to spin since there is no other notification from the PCI diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index cfc0f7f..a6ac0c8 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -2077,6 +2077,54 @@ void pci_dsn_init(struct pci_dev *dev) } /** + * pci_serial_number_changed - check the device SN is changed + * @pdev: the PCI device + * + * check the device serial number is changed. + * if device does not support device serial number, + * return false. + */ +bool pci_serial_number_changed(struct pci_dev *pdev) +{ + struct pci_vpd *vpd; + u64 old_dsn, new_dsn; + int ret; + + /* first check PCIe DSN */ + old_dsn = pdev->sn; + new_dsn = pci_device_serial_number(pdev); + + if (old_dsn != new_dsn) + return true; + else if (old_dsn) + return false; + + /* PCIe DSN does not support, check VPD SN */ + vpd = pci_vpd_serial_number_init(pdev, NULL); + if (!pdev->vpd && !vpd) { + /* VPD SN does not support */ + return false; + } else if (pdev->vpd && pdev->vpd->sn && vpd) { + ret = strcmp(pdev->vpd->sn, vpd->sn); + kfree(vpd->sn); + kfree(container_of(vpd, struct pci_vpd_pci22, base)); + if (!ret) + return false; + else + return true; + } else if ((pdev->vpd && pdev->vpd->sn) || (vpd && vpd->sn)) { + if (vpd) { + kfree(vpd->sn); + kfree(container_of(vpd, struct pci_vpd_pci22, base)); + } + return true; + } + + return false; +} +EXPORT_SYMBOL(pci_serial_number_changed); + +/** * pci_configure_ari - enable or disable ARI forwarding * @dev: the PCI device * diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h index eb77124..5d1f261 100644 --- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h @@ -98,6 +98,14 @@ struct pci_vpd { struct bin_attribute *attr; /* descriptor for sysfs VPD entry */ }; +struct pci_vpd_pci22 { + struct pci_vpd base; + struct mutex lock; + u16 flag; + bool busy; + u8 cap; +}; + int pci_vpd_pci22_init(struct pci_dev *dev); static inline void pci_vpd_release(struct pci_dev *dev) { diff --git a/include/linux/pci.h b/include/linux/pci.h index 5c38b55..9580fa5 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -996,6 +996,8 @@ ssize_t pci_read_vpd(struct pci_dev *dev, loff_t pos, size_t count, void *buf); ssize_t pci_write_vpd(struct pci_dev *dev, loff_t pos, size_t count, const void *buf); int pci_vpd_truncate(struct pci_dev *dev, size_t size); +bool pci_serial_number_changed(struct pci_dev *pdev); + /* Helper functions for low-level code (drivers/pci/setup-[bus,res].c) */ resource_size_t pcibios_retrieve_fw_addr(struct pci_dev *dev, int idx); void pci_bus_assign_resources(const struct pci_bus *bus);