From patchwork Tue May 22 05:05:01 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alex Williamson X-Patchwork-Id: 160559 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id F3368B6F77 for ; Tue, 22 May 2012 17:42:05 +1000 (EST) Received: from localhost ([::1]:44511 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1SWifG-000548-E3 for incoming@patchwork.ozlabs.org; Tue, 22 May 2012 02:33:50 -0400 Received: from eggs.gnu.org ([208.118.235.92]:50598) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1SWhHZ-0006OF-2O for qemu-devel@nongnu.org; Tue, 22 May 2012 01:05:18 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1SWhHW-0007MP-SP for qemu-devel@nongnu.org; Tue, 22 May 2012 01:05:16 -0400 Received: from mx1.redhat.com ([209.132.183.28]:19781) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1SWhHW-0007Lq-LK for qemu-devel@nongnu.org; Tue, 22 May 2012 01:05:14 -0400 Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id q4M553iw029466 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Tue, 22 May 2012 01:05:03 -0400 Received: from bling.home (ovpn-113-40.phx2.redhat.com [10.3.113.40]) by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id q4M551bl018870; Tue, 22 May 2012 01:05:02 -0400 From: Alex Williamson To: benh@kernel.crashing.org, aik@ozlabs.ru, david@gibson.dropbear.id.au, joerg.roedel@amd.com, dwmw2@infradead.org Date: Mon, 21 May 2012 23:05:01 -0600 Message-ID: <20120522050501.5871.89639.stgit@bling.home> In-Reply-To: <20120522043607.5871.11340.stgit@bling.home> References: <20120522043607.5871.11340.stgit@bling.home> User-Agent: StGIT/0.14.3 MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 209.132.183.28 X-Mailman-Approved-At: Tue, 22 May 2012 02:33:07 -0400 Cc: aafabbri@cisco.com, alex.williamson@redhat.com, kvm@vger.kernel.org, B07421@freescale.com, linux-pci@vger.kernel.org, konrad.wilk@oracle.com, agraf@suse.de, qemu-devel@nongnu.org, chrisw@sous-sol.org, B08248@freescale.com, iommu@lists.linux-foundation.org, ddutile@redhat.com, avi@redhat.com, gregkh@linuxfoundation.org, bhelgaas@google.com, linux-kernel@vger.kernel.org, benve@cisco.com Subject: [Qemu-devel] [PATCH v2 04/13] pci: Add PCI DMA source ID quirk X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org DMA transactions are tagged with the source ID of the device making the request. Occasionally hardware screws this up and uses the source ID of a different device (often the wrong function number of a multifunction device). A specific Ricoh multifunction device is a prime example of this problem and included in this patch. The purpose of this function is that given a pci_dev, return the pci_dev to use as the source ID for DMA. When hardware works correctly, this returns the input device. For the components of the Ricoh multifunction device, return the pci_dev for function 0. This will be used by IOMMU drivers for determining the boundaries of IOMMU groups as multiple devices using the same source ID must be contained within the same group. This can also be used by existing streaming DMA paths for the same purpose. Signed-off-by: Alex Williamson --- drivers/pci/quirks.c | 40 ++++++++++++++++++++++++++++++++++++++++ include/linux/pci.h | 5 +++++ 2 files changed, 45 insertions(+), 0 deletions(-) diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 4bf7102..a2dd77f 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -3109,3 +3109,43 @@ int pci_dev_specific_reset(struct pci_dev *dev, int probe) return -ENOTTY; } + +static struct pci_dev *pci_func_0_dma_source(struct pci_dev *dev) +{ + return pci_get_slot(dev->bus, PCI_DEVFN(PCI_SLOT(dev->devfn), 0)); +} + +static const struct pci_dev_dma_source { + u16 vendor; + u16 device; + struct pci_dev *(*dma_source)(struct pci_dev *dev); +} pci_dev_dma_source[] = { + /* + * https://bugzilla.redhat.com/show_bug.cgi?id=605888 + * + * Some Ricoh devices use the function 0 source ID for DMA on + * other functions of a multifunction device. The DMA devices + * is therefore function 0, which will have implications of the + * iommu grouping of these devices. + */ + { PCI_VENDOR_ID_RICOH, 0xe822, pci_func_0_dma_source }, + { PCI_VENDOR_ID_RICOH, 0xe230, pci_func_0_dma_source }, + { PCI_VENDOR_ID_RICOH, 0xe832, pci_func_0_dma_source }, + { PCI_VENDOR_ID_RICOH, 0xe832, pci_func_0_dma_source }, + { 0 } +}; + +struct pci_dev *pci_dma_source(struct pci_dev *dev) +{ + const struct pci_dev_dma_source *i; + + for (i = pci_dev_dma_source; i->dma_source; i++) { + if ((i->vendor == dev->vendor || + i->vendor == (u16)PCI_ANY_ID) && + (i->device == dev->device || + i->device == (u16)PCI_ANY_ID)) + return i->dma_source(dev); + } + + return dev; +} diff --git a/include/linux/pci.h b/include/linux/pci.h index e444f5b..02dbfed 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -1479,9 +1479,14 @@ enum pci_fixup_pass { #ifdef CONFIG_PCI_QUIRKS void pci_fixup_device(enum pci_fixup_pass pass, struct pci_dev *dev); +struct pci_dev *pci_dma_source(struct pci_dev *dev); #else static inline void pci_fixup_device(enum pci_fixup_pass pass, struct pci_dev *dev) {} +static inline struct pci_dev *pci_dma_source(struct pci_dev *dev) +{ + return dev; +} #endif void __iomem *pcim_iomap(struct pci_dev *pdev, int bar, unsigned long maxlen);